twn_textures.c: stream-based texture load

This commit is contained in:
veclav talica 2024-09-25 18:01:50 +03:00
parent 1430a13832
commit 65425f5b2e

View File

@ -14,27 +14,55 @@
#include <stdbool.h> #include <stdbool.h>
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) { static SDL_Surface *image_to_surface(const char *path) {
SDL_RWops *handle = PHYSFSRWOPS_openRead(path); SDL_RWops *handle = PHYSFSRWOPS_openRead(path);
if (handle == NULL) if (handle == NULL)
goto ERR_CANNOT_OPEN_FILE; goto ERR_CANNOT_OPEN_FILE;
/* TODO: try using callbacks so that no loading of whole files is needed */ TextureLoadingContext context = {
size_t file_size; .rwops = handle,
void *file_mem = SDL_LoadFile_RW(handle, &file_size, 0); .size = SDL_RWsize(handle),
SDL_FreeRW(handle); };
if (!file_mem) stbi_io_callbacks callbacks = {
goto ERR_CANNOT_ALLOCATE_MEM; .read = load_read_callback,
.skip = load_skip_callback,
.eof = load_eof_callback,
};
int width, height, channels; 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) if (!image_mem)
goto ERR_CANNOT_READ_IMAGE; goto ERR_CANNOT_READ_IMAGE;
SDL_free(file_mem);
Uint32 rmask, gmask, bmask, amask; Uint32 rmask, gmask, bmask, amask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN #if SDL_BYTEORDER == SDL_BIG_ENDIAN
@ -65,9 +93,6 @@ ERR_CANNOT_CREATE_SURFACE:
stbi_image_free(image_mem); stbi_image_free(image_mem);
ERR_CANNOT_READ_IMAGE: ERR_CANNOT_READ_IMAGE:
SDL_free(file_mem);
ERR_CANNOT_ALLOCATE_MEM:
ERR_CANNOT_OPEN_FILE: ERR_CANNOT_OPEN_FILE:
CRY(path, "Failed to load image. Aborting..."); CRY(path, "Failed to load image. Aborting...");
die_abruptly(); die_abruptly();