Asset refactor, phase one.
This commit is contained in:
@@ -8,8 +8,6 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
|||||||
PUBLIC
|
PUBLIC
|
||||||
asset.c
|
asset.c
|
||||||
assetfile.c
|
assetfile.c
|
||||||
assetcache.c
|
|
||||||
assetbatch.c
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Subdirs
|
# Subdirs
|
||||||
|
|||||||
+120
-15
@@ -21,7 +21,6 @@ errorret_t assetInit(void) {
|
|||||||
errorChain(assetInitPlatform());
|
errorChain(assetInitPlatform());
|
||||||
assertNotNull(ASSET.zip, "Asset zip null without error.");
|
assertNotNull(ASSET.zip, "Asset zip null without error.");
|
||||||
|
|
||||||
assetCacheInit(&ASSET.cache);
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,26 +32,132 @@ bool_t assetFileExists(const char_t *filename) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
errorret_t assetLoad(
|
assetentry_t * assetGetEntry(
|
||||||
const char_t *filename,
|
const char_t *name,
|
||||||
assetfileloader_t loader,
|
const assetloadertype_t type,
|
||||||
void *params,
|
assetloaderinput_t *input
|
||||||
void *output
|
|
||||||
) {
|
) {
|
||||||
assertStrLenMax(filename, ASSET_FILE_NAME_MAX, "Filename too long.");
|
// Is there an existing asset?
|
||||||
assertNotNull(output, "Output pointer cannot be NULL.");
|
assetentry_t *entry = ASSET.entries;
|
||||||
assertNotNull(loader, "Asset file loader cannot be NULL.");
|
do {
|
||||||
|
if(entry->type == ASSET_LOADER_TYPE_NULL) {
|
||||||
|
entry++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(stringEquals(entry->name, name)) {
|
||||||
|
assertTrue(entry->type == type, "Asset entry type mismatch.");
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
entry++;
|
||||||
|
} while(entry < ASSET.entries + ASSET_ENTRY_COUNT_MAX);
|
||||||
|
|
||||||
|
// We did not find one existing, Find first available slot.
|
||||||
|
entry = ASSET.entries;
|
||||||
|
do {
|
||||||
|
if(entry->type != ASSET_LOADER_TYPE_NULL) {
|
||||||
|
entry++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
assetfile_t file;
|
if(entry->state == ASSET_ENTRY_STATE_NOT_STARTED) {
|
||||||
errorChain(assetFileInit(&file, filename, params, output));
|
assetEntryInit(entry, name, type, input);
|
||||||
errorChain(loader(&file));
|
return entry;
|
||||||
errorChain(assetFileDispose(&file));
|
}
|
||||||
|
entry++;
|
||||||
|
} while(entry < ASSET.entries + ASSET_ENTRY_COUNT_MAX);
|
||||||
|
|
||||||
|
assertUnreachable("No available asset entry slots.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t assetRequireLoaded(assetentry_t *entry) {
|
||||||
|
assertNotNull(entry, "Entry cannot be NULL.");
|
||||||
|
assertTrue(entry->type != ASSET_LOADER_TYPE_NULL, "Invalid loader type.");
|
||||||
|
|
||||||
|
// Already loaded?
|
||||||
|
if(entry->state == ASSET_ENTRY_STATE_LOADED) {
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not loaded, just spin the wheel
|
||||||
|
while(entry->state != ASSET_ENTRY_STATE_LOADED) {
|
||||||
|
errorChain(assetUpdate());
|
||||||
|
}
|
||||||
|
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t assetUpdate(void) {
|
||||||
|
// Is there any pending entries?
|
||||||
|
assetentry_t *entry = ASSET.entries;
|
||||||
|
assetloading_t *loading;
|
||||||
|
do {
|
||||||
|
// Is this asset "ready to start loading" ?
|
||||||
|
if(entry->type == ASSET_LOADER_TYPE_NULL) {
|
||||||
|
entry++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(entry->state != ASSET_ENTRY_STATE_NOT_STARTED) {
|
||||||
|
entry++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Yes, this is ready to load, but we need to see if we have a loading slot
|
||||||
|
loading = ASSET.loading;
|
||||||
|
bool_t found = false;
|
||||||
|
do {
|
||||||
|
if(loading->type != ASSET_LOADER_TYPE_NULL) {
|
||||||
|
loading++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
} while(loading < ASSET.loading + ASSET_LOADING_COUNT_MAX);
|
||||||
|
|
||||||
|
if(!found) {
|
||||||
|
// No loading slot, try again next frame.
|
||||||
|
entry++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start loading this asset.
|
||||||
|
assetEntryStartLoading(entry, loading);
|
||||||
|
entry++;
|
||||||
|
} while(entry < ASSET.entries + ASSET_ENTRY_COUNT_MAX);
|
||||||
|
|
||||||
|
// At this point we have to see the state of all the loading assets.
|
||||||
|
loading = ASSET.loading;
|
||||||
|
do {
|
||||||
|
if(loading->entry == NULL) {
|
||||||
|
loading++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(loading->entry->state) {
|
||||||
|
case ASSET_ENTRY_STATE_PENDING_SYNC:
|
||||||
|
// Begin sync loading
|
||||||
|
loading->entry->state = ASSET_ENTRY_STATE_LOADING_SYNC;
|
||||||
|
errorret_t ret = ASSET_LOADING_CALLBACKS[loading->type].loadSync(loading);
|
||||||
|
if(ret.code != ERROR_OK) {
|
||||||
|
loading->entry->state = ASSET_ENTRY_STATE_ERROR;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
loading->entry->state = ASSET_ENTRY_STATE_LOADED;
|
||||||
|
loading++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
loading++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} while(loading < ASSET.loading + ASSET_LOADING_COUNT_MAX);
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
errorret_t assetDispose(void) {
|
errorret_t assetDispose(void) {
|
||||||
assetCacheDispose(&ASSET.cache);
|
|
||||||
|
|
||||||
if(ASSET.zip != NULL) {
|
if(ASSET.zip != NULL) {
|
||||||
if(zip_close(ASSET.zip) != 0) {
|
if(zip_close(ASSET.zip) != 0) {
|
||||||
errorThrow("Failed to close asset zip archive.");
|
errorThrow("Failed to close asset zip archive.");
|
||||||
|
|||||||
+36
-13
@@ -9,7 +9,9 @@
|
|||||||
#include "error/error.h"
|
#include "error/error.h"
|
||||||
#include "asset/assetplatform.h"
|
#include "asset/assetplatform.h"
|
||||||
#include "assetfile.h"
|
#include "assetfile.h"
|
||||||
#include "assetcache.h"
|
|
||||||
|
#include "asset/loader/assetentry.h"
|
||||||
|
#include "asset/loader/assetloading.h"
|
||||||
|
|
||||||
#ifndef assetInitPlatform
|
#ifndef assetInitPlatform
|
||||||
#error "Platform must define assetInitPlatform function."
|
#error "Platform must define assetInitPlatform function."
|
||||||
@@ -21,16 +23,24 @@
|
|||||||
#define ASSET_FILE_NAME "dusk.dsk"
|
#define ASSET_FILE_NAME "dusk.dsk"
|
||||||
#define ASSET_HEADER_SIZE 3
|
#define ASSET_HEADER_SIZE 3
|
||||||
|
|
||||||
|
#define ASSET_LOADING_COUNT_MAX 4
|
||||||
|
#define ASSET_ENTRY_COUNT_MAX 128
|
||||||
|
|
||||||
typedef struct asset_s {
|
typedef struct asset_s {
|
||||||
zip_t *zip;
|
zip_t *zip;
|
||||||
assetplatform_t platform;
|
assetplatform_t platform;
|
||||||
assetcache_t cache;
|
|
||||||
|
// Assets that are mid loading.
|
||||||
|
assetloading_t loading[ASSET_LOADING_COUNT_MAX];
|
||||||
|
assetentry_t entries[ASSET_ENTRY_COUNT_MAX];
|
||||||
} asset_t;
|
} asset_t;
|
||||||
|
|
||||||
extern asset_t ASSET;
|
extern asset_t ASSET;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the asset system.
|
* Initializes the asset system.
|
||||||
|
*
|
||||||
|
* @return An error code if the asset system could not be initialized properly.
|
||||||
*/
|
*/
|
||||||
errorret_t assetInit(void);
|
errorret_t assetInit(void);
|
||||||
|
|
||||||
@@ -43,21 +53,34 @@ errorret_t assetInit(void);
|
|||||||
bool_t assetFileExists(const char_t *filename);
|
bool_t assetFileExists(const char_t *filename);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads an asset by its filename,
|
* Gets, or creates, a new asset entry. You will need to lock the asset soon
|
||||||
|
* after creating or else it will be freed up on the next update cycle.
|
||||||
*
|
*
|
||||||
* @param filename The filename of the asset to retrieve.
|
* @param name Filename of the asset.
|
||||||
* @param loader Loader to use for loading the asset file.
|
* @param type Type of the asset.
|
||||||
* @param params Parameters to pass to the loader.
|
|
||||||
* @param output The output pointer to store the loaded asset data.
|
|
||||||
* @return An error code if the asset could not be loaded.
|
|
||||||
*/
|
*/
|
||||||
errorret_t assetLoad(
|
assetentry_t * assetGetEntry(
|
||||||
const char_t *filename,
|
const char_t *name,
|
||||||
assetfileloader_t loader,
|
const assetloadertype_t type,
|
||||||
void *params,
|
assetloaderinput_t *input
|
||||||
void *output
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requires an asset entry to be loaded. This will block until the asset entry
|
||||||
|
* is fully loaded.
|
||||||
|
*
|
||||||
|
* @param entry The asset entry to require.
|
||||||
|
* @return An error code if the asset entry could not be loaded properly.
|
||||||
|
*/
|
||||||
|
errorret_t assetRequireLoaded(assetentry_t *entry);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the asset system.
|
||||||
|
*
|
||||||
|
* @return An error code if the asset system could not be updated properly.
|
||||||
|
*/
|
||||||
|
errorret_t assetUpdate(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disposes/cleans up the asset system.
|
* Disposes/cleans up the asset system.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,81 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "assetbatch.h"
|
|
||||||
#include "asset.h"
|
|
||||||
#include "util/memory.h"
|
|
||||||
#include "util/string.h"
|
|
||||||
#include "assert/assert.h"
|
|
||||||
|
|
||||||
void assetBatchInit(
|
|
||||||
assetbatch_t *batch,
|
|
||||||
assetbatchcomplete_t onComplete,
|
|
||||||
assetbatcherror_t onError,
|
|
||||||
void *context
|
|
||||||
) {
|
|
||||||
memoryZero(batch, sizeof(assetbatch_t));
|
|
||||||
batch->onComplete = onComplete;
|
|
||||||
batch->onError = onError;
|
|
||||||
batch->context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
void assetBatchAdd(
|
|
||||||
assetbatch_t *batch,
|
|
||||||
const char_t *path,
|
|
||||||
assetfileloader_t loader,
|
|
||||||
const void *params,
|
|
||||||
size_t paramsSize,
|
|
||||||
size_t dataSize,
|
|
||||||
assetcachedisposer_t disposer,
|
|
||||||
void **outPtr
|
|
||||||
) {
|
|
||||||
assertTrue(batch->count < ASSET_BATCH_MAX, "Asset batch is full.");
|
|
||||||
assertTrue(paramsSize <= ASSET_BATCH_PARAMS_SIZE, "Asset batch params too large.");
|
|
||||||
assertNotNull(outPtr, "Batch output pointer cannot be NULL.");
|
|
||||||
|
|
||||||
assetbatchitem_t *item = &batch->items[batch->count++];
|
|
||||||
stringCopy(item->path, path, ASSET_FILE_NAME_MAX);
|
|
||||||
item->loader = loader;
|
|
||||||
if (params != NULL && paramsSize > 0) {
|
|
||||||
memoryCopy(item->params, params, paramsSize);
|
|
||||||
}
|
|
||||||
item->dataSize = dataSize;
|
|
||||||
item->disposer = disposer;
|
|
||||||
item->outPtr = outPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
errorret_t assetBatchLoad(assetbatch_t *batch) {
|
|
||||||
for (uint8_t i = 0; i < batch->count; i++) {
|
|
||||||
assetbatchitem_t *item = &batch->items[i];
|
|
||||||
|
|
||||||
void *cached = assetCacheLookup(&ASSET.cache, item->path);
|
|
||||||
if (cached != NULL) {
|
|
||||||
assetCacheRetain(&ASSET.cache, item->path);
|
|
||||||
*item->outPtr = cached;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *data = memoryAllocate(item->dataSize);
|
|
||||||
errorret_t err = assetLoad(item->path, item->loader, item->params, data);
|
|
||||||
if (err.code != ERROR_OK) {
|
|
||||||
memoryFree(data);
|
|
||||||
if (batch->onError != NULL) {
|
|
||||||
batch->onError(batch, batch->context, err);
|
|
||||||
}
|
|
||||||
return errorChainImpl(err, __FILE__, __func__, __LINE__);
|
|
||||||
}
|
|
||||||
|
|
||||||
assetCacheInsert(&ASSET.cache, item->path, data, item->disposer);
|
|
||||||
*item->outPtr = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (batch->onComplete != NULL) {
|
|
||||||
batch->onComplete(batch, batch->context);
|
|
||||||
}
|
|
||||||
|
|
||||||
errorOk();
|
|
||||||
}
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "assetcache.h"
|
|
||||||
#include "error/error.h"
|
|
||||||
|
|
||||||
#ifndef ASSET_BATCH_MAX
|
|
||||||
#define ASSET_BATCH_MAX 16
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ASSET_BATCH_PARAMS_SIZE 16
|
|
||||||
|
|
||||||
typedef struct assetbatch_s assetbatch_t;
|
|
||||||
|
|
||||||
typedef void (*assetbatchcomplete_t)(assetbatch_t *batch, void *context);
|
|
||||||
typedef void (*assetbatcherror_t)(
|
|
||||||
assetbatch_t *batch,
|
|
||||||
void *context,
|
|
||||||
errorret_t error
|
|
||||||
);
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char_t path[ASSET_FILE_NAME_MAX];
|
|
||||||
assetfileloader_t loader;
|
|
||||||
uint8_t params[ASSET_BATCH_PARAMS_SIZE];
|
|
||||||
size_t dataSize;
|
|
||||||
assetcachedisposer_t disposer;
|
|
||||||
void **outPtr;
|
|
||||||
} assetbatchitem_t;
|
|
||||||
|
|
||||||
struct assetbatch_s {
|
|
||||||
assetbatchitem_t items[ASSET_BATCH_MAX];
|
|
||||||
uint8_t count;
|
|
||||||
assetbatchcomplete_t onComplete;
|
|
||||||
assetbatcherror_t onError;
|
|
||||||
void *context;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes a batch, optionally with completion and error callbacks.
|
|
||||||
*
|
|
||||||
* @param batch The batch to initialize.
|
|
||||||
* @param onComplete Called when all items have loaded successfully. May be NULL.
|
|
||||||
* @param onError Called if any item fails to load. May be NULL.
|
|
||||||
* @param context Passed through to both callbacks.
|
|
||||||
*/
|
|
||||||
void assetBatchInit(
|
|
||||||
assetbatch_t *batch,
|
|
||||||
assetbatchcomplete_t onComplete,
|
|
||||||
assetbatcherror_t onError,
|
|
||||||
void *context
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds an item to the batch. Params are copied into inline storage.
|
|
||||||
*
|
|
||||||
* @param batch The batch to add to.
|
|
||||||
* @param path Asset path, used as the cache key.
|
|
||||||
* @param loader The loader function for this asset type.
|
|
||||||
* @param params Loader-specific parameters. Copied — safe to pass stack address.
|
|
||||||
* @param paramsSize Size of params in bytes. Must be <= ASSET_BATCH_PARAMS_SIZE.
|
|
||||||
* @param dataSize Size in bytes to allocate for the output struct.
|
|
||||||
* @param disposer Called on the data before freeing when released. May be NULL.
|
|
||||||
* @param outPtr Caller's pointer variable. Set to the cache-owned data on load.
|
|
||||||
*/
|
|
||||||
void assetBatchAdd(
|
|
||||||
assetbatch_t *batch,
|
|
||||||
const char_t *path,
|
|
||||||
assetfileloader_t loader,
|
|
||||||
const void *params,
|
|
||||||
size_t paramsSize,
|
|
||||||
size_t dataSize,
|
|
||||||
assetcachedisposer_t disposer,
|
|
||||||
void **outPtr
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads all items in the batch, checking the cache for each. Fires onComplete
|
|
||||||
* on success or onError on the first failure. Also returns the error for
|
|
||||||
* synchronous callers.
|
|
||||||
*
|
|
||||||
* @param batch The batch to execute.
|
|
||||||
* @return Error if any item failed to load.
|
|
||||||
*/
|
|
||||||
errorret_t assetBatchLoad(assetbatch_t *batch);
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "assetcache.h"
|
|
||||||
#include "util/memory.h"
|
|
||||||
#include "util/string.h"
|
|
||||||
#include "assert/assert.h"
|
|
||||||
|
|
||||||
void assetCacheInit(assetcache_t *cache) {
|
|
||||||
memoryZero(cache, sizeof(assetcache_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
void *assetCacheLookup(assetcache_t *cache, const char_t *path) {
|
|
||||||
for(uint8_t i = 0; i < cache->count; i++) {
|
|
||||||
if(stringCompare(cache->entries[i].path, path) == 0) {
|
|
||||||
return cache->entries[i].data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void assetCacheInsert(
|
|
||||||
assetcache_t *cache,
|
|
||||||
const char_t *path,
|
|
||||||
void *data,
|
|
||||||
assetcachedisposer_t disposer
|
|
||||||
) {
|
|
||||||
assertTrue(cache->count < ASSET_CACHE_MAX, "Asset cache is full.");
|
|
||||||
|
|
||||||
assetcacheentry_t *entry = &cache->entries[cache->count++];
|
|
||||||
stringCopy(entry->path, path, ASSET_FILE_NAME_MAX);
|
|
||||||
entry->data = data;
|
|
||||||
entry->refcount = 1;
|
|
||||||
entry->disposer = disposer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void assetCacheRetain(assetcache_t *cache, const char_t *path) {
|
|
||||||
for (uint8_t i = 0; i < cache->count; i++) {
|
|
||||||
if (stringCompare(cache->entries[i].path, path) == 0) {
|
|
||||||
cache->entries[i].refcount++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assertTrue(false, "Asset not found in cache for retain.");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void assetCacheEntryDispose(assetcacheentry_t *entry) {
|
|
||||||
if (entry->disposer != NULL) {
|
|
||||||
entry->disposer(entry->data);
|
|
||||||
}
|
|
||||||
memoryFree(entry->data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void assetCacheRelease(assetcache_t *cache, const char_t *path) {
|
|
||||||
for (uint8_t i = 0; i < cache->count; i++) {
|
|
||||||
if (stringCompare(cache->entries[i].path, path) == 0) {
|
|
||||||
assetcacheentry_t *entry = &cache->entries[i];
|
|
||||||
entry->refcount--;
|
|
||||||
if (entry->refcount == 0) {
|
|
||||||
assetCacheEntryDispose(entry);
|
|
||||||
for (uint8_t j = i; j < cache->count - 1; j++) {
|
|
||||||
cache->entries[j] = cache->entries[j + 1];
|
|
||||||
}
|
|
||||||
cache->count--;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assertTrue(false, "Asset not found in cache for release.");
|
|
||||||
}
|
|
||||||
|
|
||||||
void assetCacheDispose(assetcache_t *cache) {
|
|
||||||
for (uint8_t i = 0; i < cache->count; i++) {
|
|
||||||
assetCacheEntryDispose(&cache->entries[i]);
|
|
||||||
}
|
|
||||||
memoryZero(cache, sizeof(assetcache_t));
|
|
||||||
}
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "assetfile.h"
|
|
||||||
|
|
||||||
#ifndef ASSET_CACHE_MAX
|
|
||||||
#define ASSET_CACHE_MAX 64
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef void (*assetcachedisposer_t)(void *data);
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char_t path[ASSET_FILE_NAME_MAX];
|
|
||||||
void *data;
|
|
||||||
uint32_t refcount;
|
|
||||||
assetcachedisposer_t disposer;
|
|
||||||
} assetcacheentry_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
assetcacheentry_t entries[ASSET_CACHE_MAX];
|
|
||||||
uint8_t count;
|
|
||||||
} assetcache_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the asset cache.
|
|
||||||
*
|
|
||||||
* @param cache The cache to initialize.
|
|
||||||
*/
|
|
||||||
void assetCacheInit(assetcache_t *cache);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Looks up a cached asset by path.
|
|
||||||
*
|
|
||||||
* @param cache The cache to search.
|
|
||||||
* @param path The asset path to look up.
|
|
||||||
* @return Pointer to the cached data, or NULL if not found.
|
|
||||||
*/
|
|
||||||
void *assetCacheLookup(assetcache_t *cache, const char_t *path);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inserts a newly loaded asset into the cache with refcount 1.
|
|
||||||
*
|
|
||||||
* @param cache The cache to insert into.
|
|
||||||
* @param path The asset path key.
|
|
||||||
* @param data Heap-allocated asset data. The cache takes ownership.
|
|
||||||
* @param disposer Called with data before freeing when refcount reaches 0.
|
|
||||||
*/
|
|
||||||
void assetCacheInsert(
|
|
||||||
assetcache_t *cache,
|
|
||||||
const char_t *path,
|
|
||||||
void *data,
|
|
||||||
assetcachedisposer_t disposer
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Increments the refcount for a cached asset.
|
|
||||||
*
|
|
||||||
* @param cache The cache containing the asset.
|
|
||||||
* @param path The asset path.
|
|
||||||
*/
|
|
||||||
void assetCacheRetain(assetcache_t *cache, const char_t *path);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decrements the refcount. Disposes and frees the asset when it reaches 0.
|
|
||||||
*
|
|
||||||
* @param cache The cache containing the asset.
|
|
||||||
* @param path The asset path.
|
|
||||||
*/
|
|
||||||
void assetCacheRelease(assetcache_t *cache, const char_t *path);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disposes all remaining cache entries and resets the cache.
|
|
||||||
*
|
|
||||||
* @param cache The cache to dispose.
|
|
||||||
*/
|
|
||||||
void assetCacheDispose(assetcache_t *cache);
|
|
||||||
@@ -15,6 +15,7 @@ typedef struct assetfile_s assetfile_t;
|
|||||||
|
|
||||||
typedef errorret_t (*assetfileloader_t)(assetfile_t *file);
|
typedef errorret_t (*assetfileloader_t)(assetfile_t *file);
|
||||||
|
|
||||||
|
// Describes a file not yet loaded.
|
||||||
typedef struct assetfile_s {
|
typedef struct assetfile_s {
|
||||||
char_t filename[ASSET_FILE_NAME_MAX];
|
char_t filename[ASSET_FILE_NAME_MAX];
|
||||||
void *params;
|
void *params;
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "dusk.h"
|
||||||
|
|
||||||
|
typedef enum assetloadertype_e {
|
||||||
|
ASSET_LOADER_TYPE_NULL,
|
||||||
|
|
||||||
|
ASSET_LOADER_TYPE_MESH,
|
||||||
|
ASSET_LOADER_TYPE_TEXTURE,
|
||||||
|
ASSET_LOADER_TYPE_SHADER,
|
||||||
|
|
||||||
|
ASSET_LOADER_TYPE_COUNT
|
||||||
|
} assetloadertype_t;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
void *nothing;
|
||||||
|
} assetloaderloading_t;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
void *nothing;
|
||||||
|
} assetloaderoutput_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ASSET_LOADER_LOADING_STATE_NOT_STARTED,
|
||||||
|
ASSET_LOADER_LOADING_STATE_PENDING_ASYNC,
|
||||||
|
ASSET_LOADER_LOADING_STATE_LOADING_ASYNC,
|
||||||
|
ASSET_LOADER_LOADING_STATE_PENDING_SYNC,
|
||||||
|
ASSET_LOADER_LOADING_STATE_LOADING_SYNC,
|
||||||
|
ASSET_LOADER_LOADING_STATE_LOADED,
|
||||||
|
ASSET_LOADER_LOADING_STATE_ERROR
|
||||||
|
} assetloaderloadingstate_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
assetloadertype_t type;
|
||||||
|
assetloaderloadingstate_t state;
|
||||||
|
assetloaderloading_t loading;
|
||||||
|
} assetloadingentry_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
assetloadertype_t type;
|
||||||
|
assetloaderoutput_t output;
|
||||||
|
} assetentry_t;
|
||||||
@@ -4,6 +4,12 @@
|
|||||||
# https://opensource.org/licenses/MIT
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
# Sources
|
# Sources
|
||||||
|
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||||
|
PUBLIC
|
||||||
|
assetentry.c
|
||||||
|
assetloading.c
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Subdirs
|
# Subdirs
|
||||||
add_subdirectory(display)
|
add_subdirectory(display)
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "assetentry.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "util/memory.h"
|
||||||
|
#include "util/string.h"
|
||||||
|
|
||||||
|
assetentrycallbacks_t ASSET_ENTRY_CALLBACKS[ASSET_LOADER_TYPE_COUNT] = {
|
||||||
|
[ASSET_LOADER_TYPE_NULL] = { 0 },
|
||||||
|
|
||||||
|
[ASSET_LOADER_TYPE_TEXTURE] = {
|
||||||
|
.dispose = &assetTextureDisposeNEW
|
||||||
|
},
|
||||||
|
|
||||||
|
[ASSET_LOADER_TYPE_TILESET] = {
|
||||||
|
.dispose = &assetTilesetDisposeNEW
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
void assetEntryInit(
|
||||||
|
assetentry_t *entry,
|
||||||
|
const char_t *name,
|
||||||
|
const assetloadertype_t type,
|
||||||
|
assetloaderinput_t *input
|
||||||
|
) {
|
||||||
|
assertNotNull(entry, "Entry cannot be NULL");
|
||||||
|
assertStrLenMin(name, 1, "Name cannot be empty");
|
||||||
|
assertStrLenMax(name, ASSET_FILE_NAME_MAX - 1, "Name too long");
|
||||||
|
assertTrue(type != ASSET_LOADER_TYPE_NULL, "Invalid loader type.");
|
||||||
|
assertTrue(type < ASSET_LOADER_TYPE_COUNT, "Invalid loader type.");
|
||||||
|
|
||||||
|
memoryZero(entry, sizeof(assetentry_t));
|
||||||
|
stringCopy(entry->name, name, ASSET_FILE_NAME_MAX);
|
||||||
|
entry->type = type;
|
||||||
|
entry->input = input;
|
||||||
|
entry->state = ASSET_ENTRY_STATE_NOT_STARTED;
|
||||||
|
refInit(&entry->refs, entry, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void assetEntryLock(assetentry_t *entry) {
|
||||||
|
assertNotNull(entry, "Entry cannot be NULL");
|
||||||
|
assertTrue(entry->type != ASSET_LOADER_TYPE_NULL, "Invalid loader type.");
|
||||||
|
refLock(&entry->refs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void assetEntryUnlock(assetentry_t *entry) {
|
||||||
|
assertNotNull(entry, "Entry cannot be NULL");
|
||||||
|
assertTrue(entry->type != ASSET_LOADER_TYPE_NULL, "Invalid loader type.");
|
||||||
|
refUnlock(&entry->refs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void assetEntryStartLoading(
|
||||||
|
assetentry_t *entry,
|
||||||
|
assetloading_t *loading
|
||||||
|
) {
|
||||||
|
assertNotNull(entry, "Entry cannot be NULL");
|
||||||
|
assertNotNull(loading, "Loading cannot be NULL");
|
||||||
|
assertTrue(entry->type != ASSET_LOADER_TYPE_NULL, "Invalid loader type.");
|
||||||
|
assertTrue(
|
||||||
|
entry->state == ASSET_ENTRY_STATE_NOT_STARTED,
|
||||||
|
"Can only start loading from NOT_STARTED state."
|
||||||
|
);
|
||||||
|
|
||||||
|
entry->state = ASSET_ENTRY_STATE_PENDING_SYNC;
|
||||||
|
memoryZero(loading, sizeof(assetloading_t));
|
||||||
|
loading->type = entry->type;
|
||||||
|
loading->entry = entry;
|
||||||
|
// At this point the asset manager will manage this thing's loading
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t assetEntryDispose(assetentry_t *entry) {
|
||||||
|
assertNotNull(entry, "Entry cannot be NULL");
|
||||||
|
|
||||||
|
assertTrue(entry->type != ASSET_LOADER_TYPE_NULL, "Invalid loader type.");
|
||||||
|
assertTrue(entry->type < ASSET_LOADER_TYPE_COUNT, "Invalid loader type.");
|
||||||
|
|
||||||
|
errorChain(ASSET_ENTRY_CALLBACKS[entry->type].dispose(entry));
|
||||||
|
memoryZero(entry, sizeof(assetentry_t));
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "asset/loader/assetloading.h"
|
||||||
|
#include "util/ref.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ASSET_ENTRY_STATE_NOT_STARTED,
|
||||||
|
// ASSET_ENTRY_STATE_PENDING_ASYNC,
|
||||||
|
// ASSET_ENTRY_STATE_LOADING_ASYNC,
|
||||||
|
ASSET_ENTRY_STATE_PENDING_SYNC,
|
||||||
|
ASSET_ENTRY_STATE_LOADING_SYNC,
|
||||||
|
ASSET_ENTRY_STATE_LOADED,
|
||||||
|
ASSET_ENTRY_STATE_ERROR
|
||||||
|
} assetentrystate_t;
|
||||||
|
|
||||||
|
typedef struct assetentry_s {
|
||||||
|
// Filename and cache key
|
||||||
|
char_t name[ASSET_FILE_NAME_MAX];
|
||||||
|
// What type of asset is this?
|
||||||
|
assetloadertype_t type;
|
||||||
|
// Data
|
||||||
|
assetloaderoutput_t data;
|
||||||
|
// What state is this asset entry in currently?
|
||||||
|
assetentrystate_t state;
|
||||||
|
// What is referencing this asset entry.
|
||||||
|
ref_t refs;
|
||||||
|
// Data that will be passed to the loader about how it should load.
|
||||||
|
assetloaderinput_t *input;
|
||||||
|
} assetentry_t;
|
||||||
|
|
||||||
|
typedef errorret_t (*assetentrydisposecallback_t)(assetentry_t *entry);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
assetentrydisposecallback_t dispose;
|
||||||
|
} assetentrycallbacks_t;
|
||||||
|
|
||||||
|
extern assetentrycallbacks_t ASSET_ENTRY_CALLBACKS[ASSET_LOADER_TYPE_COUNT];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes an asset entry with the given name and type. This does not load
|
||||||
|
* the asset.
|
||||||
|
*
|
||||||
|
* @param entry The asset entry to initialize.
|
||||||
|
* @param name The name of the asset, used as a key for loading and caching.
|
||||||
|
* @param type The type of asset this entry represents.
|
||||||
|
* @param input Data that will be passed to the loader about how it should load.
|
||||||
|
*/
|
||||||
|
void assetEntryInit(
|
||||||
|
assetentry_t *entry,
|
||||||
|
const char_t *name,
|
||||||
|
const assetloadertype_t type,
|
||||||
|
assetloaderinput_t *input
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locks an asset entry, preventing it from being freed until it is unlocked.
|
||||||
|
*
|
||||||
|
* @param entry The asset entry to lock.
|
||||||
|
*/
|
||||||
|
void assetEntryLock(assetentry_t *entry);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unlocks an asset entry, allowing it to be freed if there are no more locks.
|
||||||
|
*
|
||||||
|
* @param entry The asset entry to unlock.
|
||||||
|
*/
|
||||||
|
void assetEntryUnlock(assetentry_t *entry);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts loading the given asset entry using an assetloading slot. This will
|
||||||
|
* be called by the asset manager when it deems it's a good time to begin the
|
||||||
|
* loading of this asset entry.
|
||||||
|
*
|
||||||
|
* Currently we return the error but in future this will not be returned.
|
||||||
|
*
|
||||||
|
* @param entry The asset entry to start loading.
|
||||||
|
* @param loading The assetloading slot to use for loading this asset entry.
|
||||||
|
* @return Any error that occurs during loading.
|
||||||
|
*/
|
||||||
|
void assetEntryStartLoading(assetentry_t *entry, assetloading_t *loading);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disposes an asset entry, freeing any resources it holds.
|
||||||
|
*
|
||||||
|
* @param entry The asset entry to dispose.
|
||||||
|
* @return Any error that occurs during disposal.
|
||||||
|
*/
|
||||||
|
errorret_t assetEntryDispose(assetentry_t *entry);
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "asset/loader/display/assetmeshloader.h"
|
||||||
|
#include "asset/loader/display/assettextureloader.h"
|
||||||
|
#include "asset/loader/display/assettilesetloader.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ASSET_LOADER_TYPE_NULL,
|
||||||
|
|
||||||
|
// ASSET_LOADER_TYPE_MESH,
|
||||||
|
ASSET_LOADER_TYPE_TEXTURE,
|
||||||
|
ASSET_LOADER_TYPE_TILESET,
|
||||||
|
|
||||||
|
ASSET_LOADER_TYPE_COUNT
|
||||||
|
} assetloadertype_t;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
assettextureloaderinput_t texture;
|
||||||
|
assettilesetloaderinput_t tileset;
|
||||||
|
} assetloaderinput_t;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
assettextureloaderloading_t texture;
|
||||||
|
assettilesetloaderloading_t tileset;
|
||||||
|
} assetloaderloading_t;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
assettextureoutput_t texture;
|
||||||
|
assettilesetoutput_t tileset;
|
||||||
|
} assetloaderoutput_t;
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "assetloading.h"
|
||||||
|
#include "asset/loader/display/assetmeshloader.h"
|
||||||
|
|
||||||
|
assetloadingcallbacks_t ASSET_LOADING_CALLBACKS[ASSET_LOADER_TYPE_COUNT] = {
|
||||||
|
[ASSET_LOADER_TYPE_NULL] = { 0 },
|
||||||
|
|
||||||
|
// [ASSET_LOADER_TYPE_MESH] = {
|
||||||
|
// .loadSync = assetMeshLoaderNEW,
|
||||||
|
// },
|
||||||
|
|
||||||
|
[ASSET_LOADER_TYPE_TEXTURE] = {
|
||||||
|
.loadSync = assetTextureLoaderNEW
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
[ASSET_LOADER_TYPE_TILESET] = {
|
||||||
|
.loadSync = assetTilesetLoaderNEW
|
||||||
|
},
|
||||||
|
|
||||||
|
// [ASSET_LOADER_TYPE_SHADER] = {
|
||||||
|
|
||||||
|
// }
|
||||||
|
};
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "assetloader.h"
|
||||||
|
#include "asset/assetfile.h"
|
||||||
|
|
||||||
|
typedef struct assetentry_s assetentry_t;
|
||||||
|
|
||||||
|
typedef struct assetloading_s {
|
||||||
|
// What type of asset is being loaded.
|
||||||
|
assetloadertype_t type;
|
||||||
|
// Referral back to the asset entry that will be kept alive after load done.
|
||||||
|
assetentry_t *entry;
|
||||||
|
// Information used during the load operation only.
|
||||||
|
assetloaderloading_t loading;
|
||||||
|
} assetloading_t;
|
||||||
|
|
||||||
|
typedef errorret_t (assetloadingcallback_t)(assetloading_t *loading);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
assetloadingcallback_t *loadSync;
|
||||||
|
} assetloadingcallbacks_t;
|
||||||
|
|
||||||
|
extern assetloadingcallbacks_t ASSET_LOADING_CALLBACKS[ASSET_LOADER_TYPE_COUNT];
|
||||||
@@ -151,32 +151,32 @@ errorret_t assetMeshLoader(assetfile_t *file) {
|
|||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
errorret_t assetMeshLoadToOutput(
|
// errorret_t assetMeshLoadToOutput(
|
||||||
const char_t *path,
|
// const char_t *path,
|
||||||
assetmeshoutput_t *output
|
// assetmeshoutput_t *output
|
||||||
) {
|
// ) {
|
||||||
assertNotNull(path, "Path cannot be null");
|
// assertNotNull(path, "Path cannot be null");
|
||||||
assertNotNull(output, "Output cannot be null");
|
// assertNotNull(output, "Output cannot be null");
|
||||||
assertNotNull(output->outMesh, "Output mesh cannot be null");
|
// assertNotNull(output->outMesh, "Output mesh cannot be null");
|
||||||
assertNotNull(output->outVertices, "Output vertices cannot be null");
|
// assertNotNull(output->outVertices, "Output vertices cannot be null");
|
||||||
|
|
||||||
return assetLoad(path, &assetMeshLoader, NULL, output);
|
// return assetLoad(path, &assetMeshLoader, NULL, output);
|
||||||
}
|
// }
|
||||||
|
|
||||||
errorret_t assetMeshLoad(
|
// errorret_t assetMeshLoad(
|
||||||
const char_t *path,
|
// const char_t *path,
|
||||||
mesh_t *outMesh,
|
// mesh_t *outMesh,
|
||||||
meshvertex_t **outVertices,
|
// meshvertex_t **outVertices,
|
||||||
const assetmeshinputaxis_t inputAxis
|
// const assetmeshinputaxis_t inputAxis
|
||||||
) {
|
// ) {
|
||||||
assertNotNull(path, "Path cannot be null");
|
// assertNotNull(path, "Path cannot be null");
|
||||||
assertNotNull(outMesh, "Output mesh cannot be null");
|
// assertNotNull(outMesh, "Output mesh cannot be null");
|
||||||
assertNotNull(outVertices, "Output vertices cannot be null");
|
// assertNotNull(outVertices, "Output vertices cannot be null");
|
||||||
|
|
||||||
assetmeshoutput_t output = {
|
// assetmeshoutput_t output = {
|
||||||
outMesh,
|
// outMesh,
|
||||||
outVertices,
|
// outVertices,
|
||||||
inputAxis
|
// inputAxis
|
||||||
};
|
// };
|
||||||
return assetMeshLoadToOutput(path, &output);
|
// return assetMeshLoadToOutput(path, &output);
|
||||||
}
|
// }
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "asset/asset.h"
|
#include "asset/assetfile.h"
|
||||||
#include "display/mesh/mesh.h"
|
#include "display/mesh/mesh.h"
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
|
|
||||||
@@ -42,20 +42,4 @@ assertStructSize(assetmeshstltriangle_t, 50);
|
|||||||
* @param file Asset file to load the mesh from.
|
* @param file Asset file to load the mesh from.
|
||||||
* @return Any error that occurs during loading.
|
* @return Any error that occurs during loading.
|
||||||
*/
|
*/
|
||||||
errorret_t assetMeshLoader(assetfile_t *file);
|
errorret_t assetMeshLoader(assetfile_t *file);
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for mesh assets.
|
|
||||||
*
|
|
||||||
* @param file Asset file to load the mesh from.
|
|
||||||
* @param outMesh Output mesh to load the data into.
|
|
||||||
* @param outVertices Output pointer to the vertex data, used for cleanup.
|
|
||||||
* @param inputAxis The axis orientation of the input mesh data.
|
|
||||||
* @return Any error that occurs during loading.
|
|
||||||
*/
|
|
||||||
errorret_t assetMeshLoad(
|
|
||||||
const char_t *path,
|
|
||||||
mesh_t *outMesh,
|
|
||||||
meshvertex_t **outVertices,
|
|
||||||
const assetmeshinputaxis_t inputAxis
|
|
||||||
);
|
|
||||||
@@ -6,13 +6,41 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "assettextureloader.h"
|
#include "assettextureloader.h"
|
||||||
#include "asset/assetbatch.h"
|
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
#include "stb_image.h"
|
#include "stb_image.h"
|
||||||
#include "log/log.h"
|
#include "log/log.h"
|
||||||
#include "util/endian.h"
|
#include "util/endian.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "asset/loader/assetloading.h"
|
||||||
|
#include "asset/loader/assetentry.h"
|
||||||
|
|
||||||
|
errorret_t assetTextureLoaderNEW(assetloading_t *loading) {
|
||||||
|
assertNotNull(loading, "Loading cannot be NULL");
|
||||||
|
|
||||||
|
assettextureloaderparams_t params;
|
||||||
|
params.format = loading->entry->input->texture;
|
||||||
|
|
||||||
|
assetfile_t *file = &loading->loading.texture.file;
|
||||||
|
errorChain(assetFileInit(
|
||||||
|
file,
|
||||||
|
loading->entry->name,
|
||||||
|
¶ms,
|
||||||
|
&loading->entry->data.texture
|
||||||
|
));
|
||||||
|
errorChain(assetTextureLoader(file));
|
||||||
|
assetFileDispose(file);
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t assetTextureDisposeNEW(assetentry_t *entry) {
|
||||||
|
assertNotNull(entry, "Asset entry cannot be NULL");
|
||||||
|
return textureDispose(&entry->data.texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
stbi_io_callbacks ASSET_TEXTURE_STB_CALLBACKS = {
|
stbi_io_callbacks ASSET_TEXTURE_STB_CALLBACKS = {
|
||||||
.read = assetTextureReader,
|
.read = assetTextureReader,
|
||||||
.skip = assetTextureSkipper,
|
.skip = assetTextureSkipper,
|
||||||
@@ -102,37 +130,4 @@ errorret_t assetTextureLoader(assetfile_t *file) {
|
|||||||
|
|
||||||
stbi_image_free(data);
|
stbi_image_free(data);
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
|
||||||
|
|
||||||
errorret_t assetTextureLoad(
|
|
||||||
const char_t *path,
|
|
||||||
texture_t *out,
|
|
||||||
const textureformat_t format
|
|
||||||
) {
|
|
||||||
assettextureloaderparams_t params = {
|
|
||||||
.format = format
|
|
||||||
};
|
|
||||||
return assetLoad(path, assetTextureLoader, ¶ms, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void assetTextureCacheDispose(void *data) {
|
|
||||||
errorCatch(textureDispose((texture_t*)data));
|
|
||||||
}
|
|
||||||
|
|
||||||
void assetBatchTexture(
|
|
||||||
assetbatch_t *batch,
|
|
||||||
const char_t *path,
|
|
||||||
textureformat_t format,
|
|
||||||
texture_t **out
|
|
||||||
) {
|
|
||||||
assettextureloaderparams_t params = { .format = format };
|
|
||||||
assetBatchAdd(
|
|
||||||
batch,
|
|
||||||
path,
|
|
||||||
assetTextureLoader,
|
|
||||||
¶ms, sizeof(params),
|
|
||||||
sizeof(texture_t),
|
|
||||||
assetTextureCacheDispose,
|
|
||||||
(void**)out
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
@@ -6,14 +6,28 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "asset/asset.h"
|
#include "asset/assetfile.h"
|
||||||
#include "asset/assetbatch.h"
|
|
||||||
#include "display/texture/texture.h"
|
#include "display/texture/texture.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
textureformat_t format;
|
textureformat_t format;
|
||||||
} assettextureloaderparams_t;
|
} assettextureloaderparams_t;
|
||||||
|
|
||||||
|
// NEW STUFF
|
||||||
|
typedef struct assetloading_s assetloading_t;
|
||||||
|
typedef struct assetentry_s assetentry_t;
|
||||||
|
|
||||||
|
typedef textureformat_t assettextureloaderinput_t;
|
||||||
|
typedef struct {
|
||||||
|
assetfile_t file;
|
||||||
|
} assettextureloaderloading_t;
|
||||||
|
typedef texture_t assettextureoutput_t;
|
||||||
|
|
||||||
|
errorret_t assetTextureLoaderNEW(assetloading_t *loading);
|
||||||
|
errorret_t assetTextureDisposeNEW(assetentry_t *entry);
|
||||||
|
|
||||||
|
// END NEW STUFF
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* STB image read callback for asset files.
|
* STB image read callback for asset files.
|
||||||
*
|
*
|
||||||
@@ -34,34 +48,4 @@ int assetTextureEOF(void *user);
|
|||||||
* @param file Asset file to load the texture from.
|
* @param file Asset file to load the texture from.
|
||||||
* @return Any error that occurs during loading.
|
* @return Any error that occurs during loading.
|
||||||
*/
|
*/
|
||||||
errorret_t assetTextureLoader(assetfile_t *file);
|
errorret_t assetTextureLoader(assetfile_t *file);
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads a texture from the specified path.
|
|
||||||
*
|
|
||||||
* @param path Path to the texture asset.
|
|
||||||
* @param out Output texture to load into.
|
|
||||||
* @param format Format of the texture to load.
|
|
||||||
* @return Any error that occurs during loading.
|
|
||||||
*/
|
|
||||||
errorret_t assetTextureLoad(
|
|
||||||
const char_t *path,
|
|
||||||
texture_t *out,
|
|
||||||
const textureformat_t format
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a texture load request to a batch. The cache-owned texture_t* is
|
|
||||||
* written to *out when the batch completes.
|
|
||||||
*
|
|
||||||
* @param batch The batch to add to.
|
|
||||||
* @param path Path to the texture asset.
|
|
||||||
* @param format Format of the texture to load.
|
|
||||||
* @param out Receives a pointer to the loaded texture on completion.
|
|
||||||
*/
|
|
||||||
void assetBatchTexture(
|
|
||||||
assetbatch_t *batch,
|
|
||||||
const char_t *path,
|
|
||||||
textureformat_t format,
|
|
||||||
texture_t **out
|
|
||||||
);
|
|
||||||
@@ -6,11 +6,35 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "assettilesetloader.h"
|
#include "assettilesetloader.h"
|
||||||
#include "asset/assetbatch.h"
|
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
#include "util/endian.h"
|
#include "util/endian.h"
|
||||||
|
|
||||||
|
#include "asset/loader/assetloading.h"
|
||||||
|
#include "asset/loader/assetentry.h"
|
||||||
|
|
||||||
|
errorret_t assetTilesetLoaderNEW(assetloading_t *loading) {
|
||||||
|
assertNotNull(loading, "Loading cannot be NULL");
|
||||||
|
assertTrue(loading->type == ASSET_LOADER_TYPE_TILESET, "Invalid type.");
|
||||||
|
|
||||||
|
assetfile_t *file = &loading->loading.tileset.file;
|
||||||
|
tileset_t *out = &loading->entry->data.tileset;
|
||||||
|
assertNotNull(file, "File cannot be NULL");
|
||||||
|
assertNotNull(out, "Output cannot be NULL");
|
||||||
|
|
||||||
|
errorChain(assetFileInit(file, loading->entry->name, NULL, out));
|
||||||
|
errorChain(assetTilesetLoader(file));
|
||||||
|
errorChain(assetFileDispose(file));
|
||||||
|
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t assetTilesetDisposeNEW(assetentry_t *entry) {
|
||||||
|
assertNotNull(entry, "Entry cannot be NULL");
|
||||||
|
assertTrue(entry->type == ASSET_LOADER_TYPE_TILESET, "Invalid type.");
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
errorret_t assetTilesetLoader(assetfile_t *file) {
|
errorret_t assetTilesetLoader(assetfile_t *file) {
|
||||||
assertNotNull(file, "Asset file pointer for tileset loader is null.");
|
assertNotNull(file, "Asset file pointer for tileset loader is null.");
|
||||||
|
|
||||||
@@ -73,25 +97,9 @@ errorret_t assetTilesetLoader(assetfile_t *file) {
|
|||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
errorret_t assetTilesetLoad(
|
// errorret_t assetTilesetLoad(
|
||||||
const char_t *path,
|
// const char_t *path,
|
||||||
tileset_t *out
|
// tileset_t *out
|
||||||
) {
|
// ) {
|
||||||
return assetLoad(path, assetTilesetLoader, NULL, out);
|
// return assetLoad(path, assetTilesetLoader, NULL, out);
|
||||||
}
|
// }
|
||||||
|
|
||||||
void assetBatchTileset(
|
|
||||||
assetbatch_t *batch,
|
|
||||||
const char_t *path,
|
|
||||||
tileset_t **out
|
|
||||||
) {
|
|
||||||
assetBatchAdd(
|
|
||||||
batch,
|
|
||||||
path,
|
|
||||||
assetTilesetLoader,
|
|
||||||
NULL, 0,
|
|
||||||
sizeof(tileset_t),
|
|
||||||
NULL,
|
|
||||||
(void**)out
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -6,40 +6,30 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "asset/asset.h"
|
#include "asset/assetfile.h"
|
||||||
#include "asset/assetbatch.h"
|
|
||||||
#include "display/texture/tileset.h"
|
#include "display/texture/tileset.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void *nothing;
|
||||||
|
} assettilesetloaderinput_t;
|
||||||
|
|
||||||
|
// NEW STUFF
|
||||||
|
typedef struct assetloading_s assetloading_t;
|
||||||
|
typedef struct assetentry_s assetentry_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
assetfile_t file;
|
||||||
|
} assettilesetloaderloading_t;
|
||||||
|
|
||||||
|
typedef tileset_t assettilesetoutput_t;
|
||||||
|
|
||||||
|
errorret_t assetTilesetLoaderNEW(assetloading_t *loading);
|
||||||
|
errorret_t assetTilesetDisposeNEW(assetentry_t *entry);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for tileset assets.
|
* Handler for tileset assets.
|
||||||
*
|
*
|
||||||
* @param file Asset file to load the tileset from.
|
* @param file Asset file to load the tileset from.
|
||||||
* @return Any error that occurs during loading.
|
* @return Any error that occurs during loading.
|
||||||
*/
|
*/
|
||||||
errorret_t assetTilesetLoader(assetfile_t *file);
|
errorret_t assetTilesetLoader(assetfile_t *file);
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads a tileset from the specified path.
|
|
||||||
*
|
|
||||||
* @param path Path to the tileset asset.
|
|
||||||
* @param out Output tileset to load into.
|
|
||||||
* @return Any error that occurs during loading.
|
|
||||||
*/
|
|
||||||
errorret_t assetTilesetLoad(
|
|
||||||
const char_t *path,
|
|
||||||
tileset_t *out
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a tileset load request to a batch. The cache-owned tileset_t* is
|
|
||||||
* written to *out when the batch completes.
|
|
||||||
*
|
|
||||||
* @param batch The batch to add to.
|
|
||||||
* @param path Path to the tileset asset.
|
|
||||||
* @param out Receives a pointer to the loaded tileset on completion.
|
|
||||||
*/
|
|
||||||
void assetBatchTileset(
|
|
||||||
assetbatch_t *batch,
|
|
||||||
const char_t *path,
|
|
||||||
tileset_t **out
|
|
||||||
);
|
|
||||||
@@ -45,9 +45,9 @@ errorret_t assetJsonLoader(assetfile_t *file) {
|
|||||||
return assetJsonLoadFileToDoc(file, outDoc);
|
return assetJsonLoadFileToDoc(file, outDoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
errorret_t assetJsonLoad(
|
// errorret_t assetJsonLoad(
|
||||||
const char_t *path,
|
// const char_t *path,
|
||||||
yyjson_doc **outDoc
|
// yyjson_doc **outDoc
|
||||||
) {
|
// ) {
|
||||||
return assetLoad(path, assetJsonLoader, NULL, outDoc);
|
// return assetLoad(path, assetJsonLoader, NULL, outDoc);
|
||||||
}
|
// }
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "asset/asset.h"
|
#include "asset/assetfile.h"
|
||||||
#include "yyjson.h"
|
#include "yyjson.h"
|
||||||
|
|
||||||
#define ASSET_JSON_FILE_SIZE_MAX 1024*256
|
#define ASSET_JSON_FILE_SIZE_MAX 1024*256
|
||||||
@@ -30,16 +30,4 @@ errorret_t assetJsonLoadFileToDoc(assetfile_t *file, yyjson_doc **outDoc);
|
|||||||
* @param file Asset file to load the locale from.
|
* @param file Asset file to load the locale from.
|
||||||
* @return Any error that occurs during loading.
|
* @return Any error that occurs during loading.
|
||||||
*/
|
*/
|
||||||
errorret_t assetJsonLoader(assetfile_t *file);
|
errorret_t assetJsonLoader(assetfile_t *file);
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads a locale from the specified path.
|
|
||||||
*
|
|
||||||
* @param path Path to the locale asset.
|
|
||||||
* @param outDoc Pointer to store the loaded JSON document.
|
|
||||||
* @return Any error that occurs during loading.
|
|
||||||
*/
|
|
||||||
errorret_t assetJsonLoad(
|
|
||||||
const char_t *path,
|
|
||||||
yyjson_doc **outDoc
|
|
||||||
);
|
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "asset/asset.h"
|
#include "asset/assetfile.h"
|
||||||
|
|
||||||
#define ASSET_LOCALE_FILE_PLURAL_FORM_COUNT 6
|
#define ASSET_LOCALE_FILE_PLURAL_FORM_COUNT 6
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
#include "display/spritebatch/spritebatch.h"
|
#include "display/spritebatch/spritebatch.h"
|
||||||
#include "asset/asset.h"
|
#include "asset/asset.h"
|
||||||
#include "asset/assetbatch.h"
|
|
||||||
#include "asset/loader/display/assettextureloader.h"
|
#include "asset/loader/display/assettextureloader.h"
|
||||||
#include "asset/loader/display/assettilesetloader.h"
|
#include "asset/loader/display/assettilesetloader.h"
|
||||||
#include "display/shader/shaderunlit.h"
|
#include "display/shader/shaderunlit.h"
|
||||||
@@ -18,17 +17,35 @@
|
|||||||
font_t FONT_DEFAULT;
|
font_t FONT_DEFAULT;
|
||||||
|
|
||||||
errorret_t textInit(void) {
|
errorret_t textInit(void) {
|
||||||
assetbatch_t batch;
|
assetloaderinput_t input = {
|
||||||
assetBatchInit(&batch, NULL, NULL, NULL);
|
.texture = TEXTURE_FORMAT_RGBA
|
||||||
assetBatchTexture(&batch, "ui/minogram.png", TEXTURE_FORMAT_RGBA, &FONT_DEFAULT.texture);
|
};
|
||||||
assetBatchTileset(&batch, "ui/minogram.dtf", &FONT_DEFAULT.tileset);
|
assetentry_t *entryTexture = assetGetEntry(
|
||||||
errorChain(assetBatchLoad(&batch));
|
"ui/minogram.png", ASSET_LOADER_TYPE_TEXTURE, &input
|
||||||
|
);
|
||||||
|
assetentry_t *entryTileset = assetGetEntry(
|
||||||
|
"ui/minogram.dtf", ASSET_LOADER_TYPE_TILESET, NULL
|
||||||
|
);
|
||||||
|
errorChain(assetRequireLoaded(entryTexture));
|
||||||
|
errorChain(assetRequireLoaded(entryTileset));
|
||||||
|
FONT_DEFAULT.texture = &entryTexture->data.texture;
|
||||||
|
FONT_DEFAULT.tileset = &entryTileset->data.tileset;
|
||||||
|
|
||||||
|
// assetentry_t *entryTileset = assetGetEntry(
|
||||||
|
// "ui/minogram.dtf", ASSET_LOADER_TYPE_TILESET
|
||||||
|
// );
|
||||||
|
|
||||||
|
// assetbatch_t batch;
|
||||||
|
// assetBatchInit(&batch, NULL, NULL, NULL);
|
||||||
|
// assetBatchTexture(&batch, "ui/minogram.png", TEXTURE_FORMAT_RGBA, &FONT_DEFAULT.texture);
|
||||||
|
// assetBatchTileset(&batch, "ui/minogram.dtf", &FONT_DEFAULT.tileset);
|
||||||
|
// errorChain(assetBatchLoad(&batch));
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
errorret_t textDispose(void) {
|
errorret_t textDispose(void) {
|
||||||
assetCacheRelease(&ASSET.cache, "ui/minogram.png");
|
// assetCacheRelease(&ASSET.cache, "ui/minogram.png");
|
||||||
assetCacheRelease(&ASSET.cache, "ui/minogram.dtf");
|
// assetCacheRelease(&ASSET.cache, "ui/minogram.dtf");
|
||||||
FONT_DEFAULT.texture = NULL;
|
FONT_DEFAULT.texture = NULL;
|
||||||
FONT_DEFAULT.tileset = NULL;
|
FONT_DEFAULT.tileset = NULL;
|
||||||
errorOk();
|
errorOk();
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ errorret_t engineUpdate(void) {
|
|||||||
errorChain(displayUpdate());
|
errorChain(displayUpdate());
|
||||||
errorChain(cutsceneUpdate());
|
errorChain(cutsceneUpdate());
|
||||||
errorChain(sceneUpdate());
|
errorChain(sceneUpdate());
|
||||||
|
errorChain(assetUpdate());
|
||||||
|
|
||||||
if(inputPressed(INPUT_ACTION_RAGEQUIT)) ENGINE.running = false;
|
if(inputPressed(INPUT_ACTION_RAGEQUIT)) ENGINE.running = false;
|
||||||
errorOk();
|
errorOk();
|
||||||
|
|||||||
@@ -13,4 +13,5 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
|||||||
string.c
|
string.c
|
||||||
math.c
|
math.c
|
||||||
sort.c
|
sort.c
|
||||||
|
ref.c
|
||||||
)
|
)
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ref.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
|
||||||
|
void refInit(
|
||||||
|
ref_t *ref,
|
||||||
|
void *data,
|
||||||
|
refcallback_t onLock,
|
||||||
|
refcallback_t onUnlock,
|
||||||
|
refcallback_t onAllUnlocked
|
||||||
|
) {
|
||||||
|
assertNotNull(ref, "Ref cannot be NULL.");
|
||||||
|
memoryZero(ref, sizeof(ref_t));
|
||||||
|
ref->count = 1;
|
||||||
|
ref->data = data;
|
||||||
|
ref->onLock = onLock;
|
||||||
|
ref->onUnlock = onUnlock;
|
||||||
|
ref->onAllUnlocked = onAllUnlocked;
|
||||||
|
}
|
||||||
|
|
||||||
|
void refLock(ref_t *ref) {
|
||||||
|
assertNotNull(ref, "Ref cannot be NULL.");
|
||||||
|
assertTrue(ref->count > 0, "Cannot lock a ref with zero count.");
|
||||||
|
ref->count++;
|
||||||
|
if(ref->onLock != NULL) ref->onLock(ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t refUnlock(ref_t *ref) {
|
||||||
|
assertNotNull(ref, "Ref cannot be NULL.");
|
||||||
|
assertTrue(ref->count > 0, "Cannot unlock a ref with zero count.");
|
||||||
|
|
||||||
|
ref->count--;
|
||||||
|
|
||||||
|
if(ref->count > 0) {
|
||||||
|
if(ref->onUnlock != NULL) ref->onUnlock(ref);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *data = ref->data;
|
||||||
|
refcallback_t onAllUnlocked = ref->onAllUnlocked;
|
||||||
|
memoryZero(ref, sizeof(ref_t));
|
||||||
|
ref->data = data;
|
||||||
|
if(onAllUnlocked != NULL) onAllUnlocked(ref);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "dusk.h"
|
||||||
|
|
||||||
|
typedef struct ref_s ref_t;
|
||||||
|
typedef void (*refcallback_t)(ref_t *ref);
|
||||||
|
|
||||||
|
typedef struct ref_s {
|
||||||
|
uint32_t count;
|
||||||
|
void *data;
|
||||||
|
refcallback_t onLock;
|
||||||
|
refcallback_t onUnlock;
|
||||||
|
refcallback_t onAllUnlocked;
|
||||||
|
} ref_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a ref with a count of 1.
|
||||||
|
*
|
||||||
|
* @param ref The ref to initialize.
|
||||||
|
* @param data Opaque context pointer accessible to all callbacks.
|
||||||
|
* @param onLock Called each time the ref is locked. May be NULL.
|
||||||
|
* @param onUnlock Called each time the ref is unlocked (count still > 0). May be NULL.
|
||||||
|
* @param onAllUnlocked Called when the count reaches zero. Responsible for
|
||||||
|
* any cleanup. May be NULL.
|
||||||
|
*/
|
||||||
|
void refInit(
|
||||||
|
ref_t *ref,
|
||||||
|
void *data,
|
||||||
|
refcallback_t onLock,
|
||||||
|
refcallback_t onUnlock,
|
||||||
|
refcallback_t onAllUnlocked
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increments the lock count.
|
||||||
|
*
|
||||||
|
* @param ref The ref to lock.
|
||||||
|
*/
|
||||||
|
void refLock(ref_t *ref);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrements the lock count. When it reaches zero onAllUnlocked is called
|
||||||
|
* (if set) and the ref struct is zeroed.
|
||||||
|
*
|
||||||
|
* @param ref The ref to unlock.
|
||||||
|
* @return true if the count reached zero.
|
||||||
|
*/
|
||||||
|
bool_t refUnlock(ref_t *ref);
|
||||||
Reference in New Issue
Block a user