Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve texture loading #478

Merged
merged 1 commit into from Aug 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 3 additions & 5 deletions include/textures.h
Expand Up @@ -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
2 changes: 1 addition & 1 deletion src/bdmsupport.c
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion src/ethsupport.c
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion src/hddsupport.c
Expand Up @@ -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.
Expand Down
12 changes: 2 additions & 10 deletions 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"
Expand Down Expand Up @@ -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;
Expand Down
167 changes: 96 additions & 71 deletions src/textures.c
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand All @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -407,23 +453,17 @@ 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;
png_rw_ptr readFunction = NULL;
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;
Expand Down Expand Up @@ -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);
Expand All @@ -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:
Expand Down Expand Up @@ -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);
}
Expand All @@ -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;
}
Expand All @@ -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;
}

Expand Down