From 65425f5b2edd9069854883a636eb3e0b2d390ca0 Mon Sep 17 00:00:00 2001 From: veclavtalica Date: Wed, 25 Sep 2024 18:01:50 +0300 Subject: [PATCH] twn_textures.c: stream-based texture load --- src/twn_textures.c | 49 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/src/twn_textures.c b/src/twn_textures.c index eba5ac4..f9325c0 100644 --- a/src/twn_textures.c +++ b/src/twn_textures.c @@ -14,27 +14,55 @@ #include +typedef struct { + SDL_RWops *rwops; + size_t size; + size_t position; +} TextureLoadingContext; + + +static int load_read_callback(void *user, char *data, int size) { + TextureLoadingContext *context = user; + int read = (int)SDL_RWread(context->rwops, data, 1, size); + context->position += read; + if (read == 0) + CRY_SDL( "Error in streamed texture load."); + return read; +} + +static void load_skip_callback(void *user, int n) { + TextureLoadingContext *context = user; + context->position += n; + Sint64 result = SDL_RWseek(context->rwops, n, RW_SEEK_CUR); + SDL_assert_always(result != -1); +} + +static int load_eof_callback(void *user) { + TextureLoadingContext *context = user; + return context->position == context->size; +} static SDL_Surface *image_to_surface(const char *path) { SDL_RWops *handle = PHYSFSRWOPS_openRead(path); if (handle == NULL) goto ERR_CANNOT_OPEN_FILE; - /* TODO: try using callbacks so that no loading of whole files is needed */ - size_t file_size; - void *file_mem = SDL_LoadFile_RW(handle, &file_size, 0); - SDL_FreeRW(handle); + TextureLoadingContext context = { + .rwops = handle, + .size = SDL_RWsize(handle), + }; - if (!file_mem) - goto ERR_CANNOT_ALLOCATE_MEM; + stbi_io_callbacks callbacks = { + .read = load_read_callback, + .skip = load_skip_callback, + .eof = load_eof_callback, + }; int width, height, channels; - void *image_mem = stbi_load_from_memory(file_mem, (int)file_size, &width, &height, &channels, 0); + void *image_mem = stbi_load_from_callbacks(&callbacks, &context, &width, &height, &channels, 0); if (!image_mem) goto ERR_CANNOT_READ_IMAGE; - SDL_free(file_mem); - Uint32 rmask, gmask, bmask, amask; #if SDL_BYTEORDER == SDL_BIG_ENDIAN @@ -65,9 +93,6 @@ ERR_CANNOT_CREATE_SURFACE: stbi_image_free(image_mem); ERR_CANNOT_READ_IMAGE: - SDL_free(file_mem); - -ERR_CANNOT_ALLOCATE_MEM: ERR_CANNOT_OPEN_FILE: CRY(path, "Failed to load image. Aborting..."); die_abruptly();