Add async texture loading

This commit is contained in:
2026-06-01 14:53:18 -05:00
parent eedb7769e6
commit c4c93097cd
5 changed files with 86 additions and 10 deletions
+17 -3
View File
@@ -180,11 +180,11 @@ errorret_t assetUpdate(void) {
// If an error occured these things need to be true, basically just
// ensuring the sync loader is setting the error correctly.
if(errorIsNotOk(ret)) {
errorCatch(errorPrint(ret));
assertTrue(
loading->entry->state == ASSET_ENTRY_STATE_ERROR,
"Loader did not set entry state to error on failed load."
);
errorCatch(errorPrint(ret));
}
threadMutexUnlock(&loading->mutex);
@@ -236,8 +236,22 @@ void assetUpdateAsync(thread_t *thread) {
switch(loading->entry->state) {
case ASSET_ENTRY_STATE_PENDING_ASYNC:
loading->entry->state = ASSET_ENTRY_STATE_LOADING_ASYNC;
printf("Simulated async load\n");
sleep(1);
assertNotNull(
ASSET_LOADER_CALLBACKS[loading->type].loadAsync,
"Loader does not support async loading."
);
errorret_t ret = (
ASSET_LOADER_CALLBACKS[loading->type].loadAsync(loading)
);
if(errorIsNotOk(ret)) {
errorCatch(errorPrint(ret));
assertTrue(
loading->entry->state == ASSET_ENTRY_STATE_ERROR,
"Loader did not set entry state to error on failed load."
);
}
threadMutexUnlock(&loading->mutex);
loading++;
break;
+5
View File
@@ -12,26 +12,31 @@ assetloadercallbacks_t ASSET_LOADER_CALLBACKS[ASSET_LOADER_TYPE_COUNT] = {
[ASSET_LOADER_TYPE_MESH] = {
.loadSync = assetMeshLoaderSync,
.loadAsync = NULL,
.dispose = assetMeshDispose
},
[ASSET_LOADER_TYPE_TEXTURE] = {
.loadSync = assetTextureLoaderSync,
.loadAsync = assetTextureLoaderAsync,
.dispose = assetTextureDispose
},
[ASSET_LOADER_TYPE_TILESET] = {
.loadSync = assetTilesetLoaderSync,
.loadAsync = NULL,
.dispose = assetTilesetDispose
},
[ASSET_LOADER_TYPE_LOCALE] = {
.loadSync = assetLocaleLoaderSync,
.loadAsync = NULL,
.dispose = assetLocaleDispose
},
[ASSET_LOADER_TYPE_JSON] = {
.loadSync = assetJsonLoaderSync,
.loadAsync = NULL,
.dispose = assetJsonDispose
},
};
+2
View File
@@ -52,10 +52,12 @@ typedef struct assetloading_s assetloading_t;
typedef struct assetentry_s assetentry_t;
typedef errorret_t (assetloadersynccallback_t)(assetloading_t *loading);
typedef errorret_t (assetloaderasynccallback_t)(assetloading_t *loading);
typedef errorret_t (assetloaderdisposecallback_t)(assetentry_t *entry);
typedef struct {
assetloadersynccallback_t *loadSync;
assetloaderasynccallback_t *loadAsync;
assetloaderdisposecallback_t *dispose;
} assetloadercallbacks_t;
@@ -52,10 +52,19 @@ int assetTextureEOF(void *user) {
return file->position >= file->size;
}
errorret_t assetTextureLoaderSync(assetloading_t *loading) {
errorret_t assetTextureLoaderAsync(assetloading_t *loading) {
assertNotNull(loading, "Loading cannot be NULL");
// Only care about loading pixels.
if(loading->loading.texture.state != ASSET_TEXTURE_LOADING_STATE_LOAD_PIXELS){
errorOk();
}
// Init the file
assertNull(
loading->loading.texture.data, "Pixels already defined?"
);
assetfile_t *file = &loading->loading.texture.file;
assetLoaderErrorChain(loading, assetFileInit(
file,
@@ -77,13 +86,12 @@ errorret_t assetTextureLoaderSync(assetloading_t *loading) {
}
// Load image pixels.
int width, height, channels;
loading->loading.texture.data = stbi_load_from_callbacks(
&ASSET_TEXTURE_STB_CALLBACKS,
file,
&width,
&height,
&channels,
&loading->loading.texture.width,
&loading->loading.texture.height,
&loading->loading.texture.channels,
channelsDesired
);
@@ -101,14 +109,43 @@ errorret_t assetTextureLoaderSync(assetloading_t *loading) {
if(!isHostLittleEndian()) {
stbi__vertical_flip(
loading->loading.texture.data,
width, height, channelsDesired
loading->loading.texture.width,
loading->loading.texture.height,
loading->loading.texture.channels
);
}
loading->loading.texture.state = ASSET_TEXTURE_LOADING_STATE_CREATE_TEXTURE;
loading->entry->state = ASSET_ENTRY_STATE_PENDING_SYNC;
errorOk();
}
errorret_t assetTextureLoaderSync(assetloading_t *loading) {
assertNotNull(loading, "Loading cannot be NULL");
switch(loading->loading.texture.state) {
case ASSET_TEXTURE_LOADING_STATE_INITIAL:
loading->loading.texture.state = ASSET_TEXTURE_LOADING_STATE_LOAD_PIXELS;
loading->entry->state = ASSET_ENTRY_STATE_PENDING_ASYNC;
errorOk();
break;
case ASSET_TEXTURE_LOADING_STATE_CREATE_TEXTURE:
break;
default:
errorOk();
}
// Create the texture.
assertNotNull(
loading->loading.texture.data, "Pixels should have been loaded by now."
);
assetLoaderErrorChain(loading, textureInit(
(texture_t*)&loading->entry->data.texture,
(int32_t)width, (int32_t)height,
loading->loading.texture.width,
loading->loading.texture.height,
loading->entry->input->texture,
(texturedata_t){
.rgbaColors = (color_t*)loading->loading.texture.data
@@ -13,8 +13,18 @@ typedef struct assetloading_s assetloading_t;
typedef struct assetentry_s assetentry_t;
typedef textureformat_t assettextureloaderinput_t;
typedef enum {
ASSET_TEXTURE_LOADING_STATE_INITIAL,
ASSET_TEXTURE_LOADING_STATE_LOAD_PIXELS,
ASSET_TEXTURE_LOADING_STATE_CREATE_TEXTURE,
ASSET_TEXTURE_LOADING_STATE_DONE
} assettextureloadingstate_t;
typedef struct {
assetfile_t file;
assettextureloadingstate_t state;
int channels, width, height;
uint8_t *data;
} assettextureloaderloading_t;
@@ -46,6 +56,14 @@ void assetTextureSkipper(void *user, int n);
*/
int assetTextureEOF(void *user);
/**
* Synchronous loader for texture assets.
*
* @param loading Loading information for the asset being loaded.
* @return Error code indicating success or failure of the load operation.
*/
errorret_t assetTextureLoaderAsync(assetloading_t *loading);
/**
* Synchronous loader for texture assets.
*