From 0f598c8c2cb8f9c48af08668b92c2a10a6889642 Mon Sep 17 00:00:00 2001 From: Maximus32 Date: Fri, 6 Aug 2021 15:20:39 +0200 Subject: [PATCH] Improve texture loading --- include/textures.h | 8 +-- src/bdmsupport.c | 2 +- src/ethsupport.c | 2 +- src/hddsupport.c | 2 +- src/texcache.c | 12 +--- src/textures.c | 167 ++++++++++++++++++++++++++------------------- src/themes.c | 18 ++--- 7 files changed, 111 insertions(+), 100 deletions(-) diff --git a/include/textures.h b/include/textures.h index 297498236..44f8d70f9 100644 --- a/include/textures.h +++ b/include/textures.h @@ -92,10 +92,8 @@ enum INTERNAL_TEXTURE { #define ERR_BAD_DEPTH -7 int texLookupInternalTexId(const char *name); -int texPngLoad(GSTEXTURE *texture, const char *path, int texId, short psm); -int texJpgLoad(GSTEXTURE *texture, const char *path, int texId, short psm); -int texBmpLoad(GSTEXTURE *texture, const char *path, int texId, short psm); -void texPrepare(GSTEXTURE *texture, short psm); -int texDiscoverLoad(GSTEXTURE *texture, const char *path, int texId, short psm); +int texLoadInternal(GSTEXTURE *texture, int texId); +int texDiscoverLoad(GSTEXTURE *texture, const char *path, int texId); +void texFree(GSTEXTURE *texture); #endif diff --git a/src/bdmsupport.c b/src/bdmsupport.c index c30b46f60..61db0f7dc 100644 --- a/src/bdmsupport.c +++ b/src/bdmsupport.c @@ -402,7 +402,7 @@ static int bdmGetImage(char *folder, int isRelative, char *value, char *suffix, snprintf(path, sizeof(path), "%s%s/%s_%s", bdmPrefix, folder, value, suffix); else snprintf(path, sizeof(path), "%s%s_%s", folder, value, suffix); - return texDiscoverLoad(resultTex, path, -1, psm); + return texDiscoverLoad(resultTex, path, -1); } // This may be called, even if bdmInit() was not. diff --git a/src/ethsupport.c b/src/ethsupport.c index 4411ace80..c031a234e 100644 --- a/src/ethsupport.c +++ b/src/ethsupport.c @@ -716,7 +716,7 @@ static int ethGetImage(char *folder, int isRelative, char *value, char *suffix, snprintf(path, sizeof(path), "%s%s\\%s_%s", ethPrefix, folder, value, suffix); else snprintf(path, sizeof(path), "%s%s_%s", folder, value, suffix); - return texDiscoverLoad(resultTex, path, -1, psm); + return texDiscoverLoad(resultTex, path, -1); } // This may be called, even if ethInit() was not. diff --git a/src/hddsupport.c b/src/hddsupport.c index 0ff87f7c4..fd0cfcaab 100644 --- a/src/hddsupport.c +++ b/src/hddsupport.c @@ -501,7 +501,7 @@ static int hddGetImage(char *folder, int isRelative, char *value, char *suffix, snprintf(path, sizeof(path), "%s%s/%s_%s", gHDDPrefix, folder, value, suffix); else snprintf(path, sizeof(path), "%s%s_%s", folder, value, suffix); - return texDiscoverLoad(resultTex, path, -1, psm); + return texDiscoverLoad(resultTex, path, -1); } // This may be called, even if hddInit() was not. diff --git a/src/texcache.c b/src/texcache.c index c12727495..ba0335bd4 100644 --- a/src/texcache.c +++ b/src/texcache.c @@ -1,5 +1,6 @@ #include "include/opl.h" #include "include/texcache.h" +#include "include/textures.h" #include "include/ioman.h" #include "include/gui.h" #include "include/util.h" @@ -34,16 +35,7 @@ static void cacheLoadImage(void *data) // seems okay. we can proceed GSTEXTURE *texture = &req->entry->texture; - if (texture->Mem != NULL) { - free(texture->Mem); - texture->Mem = NULL; - texture->ClutPSM = 0; - if (texture->Clut != NULL) - free(texture->Clut); - texture->Clut = NULL; - texture->Vram = 0; - texture->VramClut = 0; - } + texFree(texture); if (handler->itemGetImage(req->cache->prefix, req->cache->isPrefixRelative, req->value, req->cache->suffix, texture, GS_PSM_CT24) < 0) req->entry->lastUsed = 0; diff --git a/src/textures.c b/src/textures.c index 516a7c9a1..e94f2517a 100644 --- a/src/textures.c +++ b/src/textures.c @@ -87,6 +87,11 @@ extern void *Vmode_pal_png; extern void *logo_png; extern void *case_png; +static int texPngLoad(GSTEXTURE *texture, const char *path); +static int texPngLoadInternal(GSTEXTURE *texture, int texId); +static int texJpgLoad(GSTEXTURE *texture, const char *path); +static int texBmpLoad(GSTEXTURE *texture, const char *path); + // Not related to screen size, just to limit at some point static int maxSize = 720 * 512 * 4; @@ -179,9 +184,10 @@ static texture_t internalDefault[TEXTURES_COUNT] = { int texLookupInternalTexId(const char *name) { - int i, result; + int i; + int result = -1; - for (result = -1, i = 0; i < TEXTURES_COUNT; i++) { + for (i = 0; i < TEXTURES_COUNT; i++) { if (!strcmp(name, internalDefault[i].name)) { result = internalDefault[i].id; break; @@ -191,12 +197,6 @@ int texLookupInternalTexId(const char *name) return result; } -static void texUpdate(GSTEXTURE *texture, int width, int height) -{ - texture->Width = width; - texture->Height = height; -} - static int texSizeValidate(int width, int height, short psm) { if (width > 1024 || height > 1024) @@ -208,32 +208,78 @@ static int texSizeValidate(int width, int height, short psm) return 0; } -void texPrepare(GSTEXTURE *texture, short psm) +static void texPrepare(GSTEXTURE *texture) { - texture->PSM = psm; - texture->ClutPSM = 0; - texture->Filter = GS_FILTER_LINEAR; - texture->Mem = NULL; - texture->Vram = 0; - texture->VramClut = 0; - texture->Clut = NULL; - // gsKit_setup_tbw(texture); already done in gsKit_texture_upload + texture->Width = 0; // Must be set by loader + texture->Height = 0; // Must be set by loader + texture->PSM = GS_PSM_CT24; // Must be set by loader + texture->ClutPSM = 0; // Default, can be set by loader + texture->TBW = 0; // gsKit internal value + texture->Mem = NULL; // Must be allocated by loader + texture->Clut = NULL; // Default, can be set by loader + texture->Vram = 0; // VRAM allocation handled by texture manager + texture->VramClut = 0; // VRAM allocation handled by texture manager + texture->Filter = GS_FILTER_LINEAR; // Default + + // Do not load the texture to VRAM directly, only load it to EE RAM + texture->Delayed = 1; } -int texDiscoverLoad(GSTEXTURE *texture, const char *path, int texId, short psm) +void texFree(GSTEXTURE *texture) { - if (texPngLoad(texture, path, texId, psm) >= 0) - return 0; + if (texture->Mem) { + free(texture->Mem); + texture->Mem = NULL; + } + if (texture->Clut) { + free(texture->Clut); + texture->Clut = NULL; + } +} - if ((psm == GS_PSM_CT24) && texJpgLoad(texture, path, texId, psm) >= 0) - return 0; +typedef int (*fpTexLoad)(GSTEXTURE *texture, const char *path); +struct STexLoader +{ + char *sFileExtension; + fpTexLoad load; +}; +static struct STexLoader texLoader[] = { + {"png", texPngLoad}, + {"jpg", texJpgLoad}, + {"bmp", texBmpLoad}, + {NULL, NULL}}; - if (texBmpLoad(texture, path, texId, psm) >= 0) - return 0; +int texDiscoverLoad(GSTEXTURE *texture, const char *path, int texId) +{ + char filePath[256]; + int loaderId = 0; + + LOG("texDiscoverLoad(%s)\n", path); + + while (texLoader[loaderId].load != NULL) { + if (texId != -1) + snprintf(filePath, sizeof(filePath), "%s%s.%s", path, internalDefault[texId].name, texLoader[loaderId].sFileExtension); + else + snprintf(filePath, sizeof(filePath), "%s.%s", path, texLoader[loaderId].sFileExtension); + + int fd = open(filePath, O_RDONLY); + if (fd > 0) { + // File found, load it + close(fd); + return (texLoader[loaderId].load(texture, filePath) >= 0) ? 0 : ERR_BAD_FILE; + } + + loaderId++; + } return ERR_BAD_FILE; } +int texLoadInternal(GSTEXTURE *texture, int texId) +{ + return texPngLoadInternal(texture, texId); +} + /// PNG SUPPORT /////////////////////////////////////////////////////////////////////////////////////// typedef struct @@ -407,9 +453,9 @@ static void texPngReadData(GSTEXTURE *texture, png_structp pngPtr, png_infop inf png_read_end(pngPtr, NULL); } -int texPngLoad(GSTEXTURE *texture, const char *path, int texId, short psm) +static int texPngLoadAll(GSTEXTURE *texture, const char *filePath, int texId) { - texPrepare(texture, psm); + texPrepare(texture); png_structp pngPtr = NULL; png_infop infoPtr = NULL; png_voidp readData = NULL; @@ -417,13 +463,7 @@ int texPngLoad(GSTEXTURE *texture, const char *path, int texId, short psm) FILE *file = NULL; void **PngFileBufferPtr; - if (path) { - char filePath[256]; - if (texId != -1) - snprintf(filePath, sizeof(filePath), "%s%s.png", path, internalDefault[texId].name); - else - snprintf(filePath, sizeof(filePath), "%s.png", path); - + if (filePath) { file = fopen(filePath, "rb"); if (file == NULL) return ERR_BAD_FILE; @@ -461,7 +501,8 @@ int texPngLoad(GSTEXTURE *texture, const char *path, int texId, short psm) png_uint_32 pngWidth, pngHeight; int bitDepth, colorType, interlaceType; png_get_IHDR(pngPtr, infoPtr, &pngWidth, &pngHeight, &bitDepth, &colorType, &interlaceType, NULL, NULL); - texUpdate(texture, pngWidth, pngHeight); + texture->Width = pngWidth; + texture->Height = pngHeight; if (bitDepth == 16) png_set_strip_16(pngPtr); @@ -478,14 +519,11 @@ int texPngLoad(GSTEXTURE *texture, const char *path, int texId, short psm) void (*texPngReadPixels)(GSTEXTURE * texture, png_bytep * rowPointers, size_t size); switch (png_get_color_type(pngPtr, infoPtr)) { case PNG_COLOR_TYPE_RGB_ALPHA: - // if PNG have alpha, then it fits for every case (even if we only wanted RGB) texture->PSM = GS_PSM_CT32; texPngReadPixels = &texPngReadPixels32; break; case PNG_COLOR_TYPE_RGB: - if (psm != GS_PSM_CT24) - return texPngEnd(pngPtr, infoPtr, file, ERR_MISSING_ALPHA); - + texture->PSM = GS_PSM_CT24; texPngReadPixels = &texPngReadPixels24; break; case PNG_COLOR_TYPE_PALETTE: @@ -518,10 +556,7 @@ int texPngLoad(GSTEXTURE *texture, const char *path, int texId, short psm) } if (texSizeValidate(texture->Width, texture->Height, texture->PSM) < 0) { - if (texture->Clut) { - free(texture->Clut); - texture->Clut = NULL; - } + texFree(texture); return texPngEnd(pngPtr, infoPtr, file, ERR_BAD_DIMENSION); } @@ -531,26 +566,31 @@ int texPngLoad(GSTEXTURE *texture, const char *path, int texId, short psm) return texPngEnd(pngPtr, infoPtr, file, 0); } +static int texPngLoad(GSTEXTURE *texture, const char *filePath) +{ + return texPngLoadAll(texture, filePath, -1); +} + +static int texPngLoadInternal(GSTEXTURE *texture, int texId) +{ + return texPngLoadAll(texture, NULL, texId); +} + /// JPG SUPPORT /////////////////////////////////////////////////////////////////////////////////////// -int texJpgLoad(GSTEXTURE *texture, const char *path, int texId, short psm) +static int texJpgLoad(GSTEXTURE *texture, const char *filePath) { - texPrepare(texture, GS_PSM_CT24); + texPrepare(texture); int result = ERR_BAD_FILE; jpgData *jpg = NULL; - char filePath[256]; - - if (texId != -1) - snprintf(filePath, sizeof(filePath), "%s%s.jpg", path, internalDefault[texId].name); - else - snprintf(filePath, sizeof(filePath), "%s.jpg", path); - jpg = jpgFromFilename(filePath, JPG_NORMAL); if (jpg) { + texture->Width = jpg->width; + texture->Height = jpg->height; + texture->PSM = GS_PSM_CT24; texture->Mem = jpg->buffer; - texUpdate(texture, jpg->width, jpg->height); free(jpg); result = 0; } @@ -561,32 +601,17 @@ int texJpgLoad(GSTEXTURE *texture, const char *path, int texId, short psm) /// BMP SUPPORT /////////////////////////////////////////////////////////////////////////////////////// extern GSGLOBAL *gsGlobal; -int texBmpLoad(GSTEXTURE *texture, const char *path, int texId, short psm) +static int texBmpLoad(GSTEXTURE *texture, const char *filePath) { - texPrepare(texture, GS_PSM_CT24); - char filePath[256]; + texPrepare(texture); - if (texId != -1) - snprintf(filePath, sizeof(filePath), "%s%s.bmp", path, internalDefault[texId].name); - else - snprintf(filePath, sizeof(filePath), "%s.bmp", path); - - texture->Delayed = 1; - if (gsKit_texture_bmp(gsGlobal, texture, filePath) < 0) + if (gsKit_texture_bmp(gsGlobal, texture, (char *)filePath) < 0) return ERR_BAD_FILE; texture->Filter = GS_FILTER_LINEAR; if (texSizeValidate(texture->Width, texture->Height, texture->PSM) < 0) { - if (texture->Mem) { - free(texture->Mem); - texture->Mem = NULL; - } - if (texture->Clut) { - free(texture->Clut); - texture->Clut = NULL; - } - + texFree(texture); return ERR_BAD_DIMENSION; } diff --git a/src/themes.c b/src/themes.c index e683cb1de..9aac1f303 100644 --- a/src/themes.c +++ b/src/themes.c @@ -316,9 +316,7 @@ static void freeImageTexture(image_texture_t *texture) static image_texture_t *initImageTexture(const char *themePath, config_set_t *themeConfig, const char *name, const char *imgName, int isOverlay) { - int psm = isOverlay ? GS_PSM_CT32 : GS_PSM_CT24; image_texture_t *texture = (image_texture_t *)malloc(sizeof(image_texture_t)); - texPrepare(&texture->source, psm); texture->name = NULL; int texId = -1; @@ -327,12 +325,12 @@ static image_texture_t *initImageTexture(const char *themePath, config_set_t *th if (themePath) { char path[256]; snprintf(path, sizeof(path), "%s%s", themePath, imgName); - if (texDiscoverLoad(&texture->source, path, texId, psm) >= 0) + if (texDiscoverLoad(&texture->source, path, texId) >= 0) ; result = 1; } else { texId = texLookupInternalTexId(imgName); - if (texDiscoverLoad(&texture->source, NULL, texId, psm) >= 0) + if (texLoadInternal(&texture->source, texId) >= 0) ; result = 1; } @@ -381,12 +379,11 @@ static image_texture_t *initImageTexture(const char *themePath, config_set_t *th static image_texture_t *initImageInternalTexture(config_set_t *themeConfig, const char *name) { image_texture_t *texture = (image_texture_t *)malloc(sizeof(image_texture_t)); - texPrepare(&texture->source, GS_PSM_CT24); texture->name = NULL; int result; if ((result = texLookupInternalTexId(name)) >= 0) { - result = texDiscoverLoad(&texture->source, NULL, result, GS_PSM_CT24); + result = texLoadInternal(&texture->source, result); int length = strlen(name) + 1; texture->name = (char *)malloc(length * sizeof(char)); memcpy(texture->name, name, length); @@ -1046,8 +1043,7 @@ static void thmFree(theme_t *theme) texture = &theme->textures[id]; if (texture->Mem != NULL) { rmUnloadTexture(texture); - free(texture->Mem); - texture->Mem = NULL; + texFree(texture); } } @@ -1087,10 +1083,10 @@ static int thmLoadResource(GSTEXTURE *texture, int texId, const char *themePath, int success = -1; if (themePath != NULL) - success = texDiscoverLoad(texture, themePath, texId, psm); // only set success here + success = texDiscoverLoad(texture, themePath, texId); // only set success here if ((success < 0) && useDefault) - texPngLoad(texture, NULL, texId, psm); // we don't mind the result of "default" + texLoadInternal(texture, texId); // we don't mind the result of "default" return success; } @@ -1217,7 +1213,7 @@ static void thmLoad(const char *themePath) newT->textures[i].Mem = NULL; // LOGO, loaded here to avoid flickering during startup with device in AUTO + theme set - texPngLoad(&newT->textures[LOGO_PICTURE], NULL, LOGO_PICTURE, GS_PSM_CT24); + texLoadInternal(&newT->textures[LOGO_PICTURE], LOGO_PICTURE); // First start with busy icon const char *themePath_temp = themePath;