From a2ee4ea0eeb70c0d82d9940fb4be042fc963418e Mon Sep 17 00:00:00 2001 From: Allanis Date: Sun, 23 Jun 2013 00:10:58 +0100 Subject: [PATCH] [Change] Optimised image loading, loading graphics once only. --- .gitignore | 1 + locperday.sh | 2 +- src/opengl.c | 99 +++++++++++++++++++++++++++++++++++++++++++++------- src/opengl.h | 22 ++++++++---- src/pack.c | 5 +++ 5 files changed, 109 insertions(+), 20 deletions(-) diff --git a/.gitignore b/.gitignore index ef0ead1..1e4b2a2 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,7 @@ screenshots/*.png *VERSION utils/resedit/*.xml +docs/doxygen/docs/* # Windows Crap win32/Lephisto/* diff --git a/locperday.sh b/locperday.sh index 21c4d8c..96d93bc 100755 --- a/locperday.sh +++ b/locperday.sh @@ -1 +1 @@ -git log --shortstat --author "Allanis" --since "1 day ago" --until "0 day ago" | grep "files changed" | awk '{files+=$1; inserted+=$4; deleted+=$6} END {print "| files changed", files, " | lines inserted:" inserted " | lines deleted:", deleted }' +git log --shortstat --author "Allanis" --since "23 hours ago" --until "1 minute ago" | grep "files changed" | awk '{files+=$1; inserted+=$4; deleted+=$6} END {print "| files changed", files, " | lines inserted:" inserted " | lines deleted:", deleted }' diff --git a/src/opengl.c b/src/opengl.c index 9bc15f7..5993404 100644 --- a/src/opengl.c +++ b/src/opengl.c @@ -14,17 +14,27 @@ #include "pack.h" #include "opengl.h" -/* offsets to Adjust the pilot's place onscreen */ -/*to be in the middle, even with the GUI. */ -extern double gui_xoff; -extern double gui_yoff; - /* The screen info, gives data of current opengl settings. */ glInfo gl_screen; /* Our precious camera. */ Vec2* gl_camera; +/* offsets to Adjust the pilot's place onscreen */ +/*to be in the middle, even with the GUI. */ +extern double gui_xoff; +extern double gui_yoff; + +/* + * Graphic list. + */ +typedef struct glTexList_ { + struct glTexList_* next; /**< Next in linked list */ + glTexture* tex; /**< Assosciated texture. */ + int used; /**< Count how many times texture is being used. */ +} glTexList; +static glTexList* texture_list = NULL; + /* Misc. */ static int SDL_VFlipSurface(SDL_Surface* surface); static int SDL_IsTrans(SDL_Surface* s, int x, int y); @@ -32,6 +42,7 @@ static uint8_t* SDL_MapTrans(SDL_Surface* s); static int pot(int n); /* glTexture. */ static GLuint gl_loadSurface(SDL_Surface* surface, int* rw, int* rh); +static glTexture* gl_loadNewImage(const char* path); static void gl_blitTexture(const glTexture* texture, const double x, const double y, const double tx, const double ty, const glColour* c); @@ -42,9 +53,9 @@ int write_png(const char* file_name, png_bytep* rows, int w, int h, /* Global. */ static GLboolean gl_hasExt(char* name); -/* ================ */ -/* MISC! */ -/* ================ */ +/* + * MISC! + */ /* Get the closest power of two. */ static int pot(int n) { @@ -246,13 +257,47 @@ glTexture* gl_loadImage(SDL_Surface* surface) { return texture; } -/* Load the image directly as an opengl texture. */ +/* Load the image if not already done. */ glTexture* gl_newImage(const char* path) { + glTexList* cur, *last; + + /* Check to see if it already exists. */ + if(texture_list != NULL) { + for(cur = texture_list; cur != NULL; cur = cur->next) { + if(strcmp(path, cur->tex->name)==0) { + cur->used += 1; + return cur->tex; + } + last = cur; + } + } + + /* Allocate memory. */ + if(texture_list == NULL) { /* Special condition - creating new list. */ + texture_list = cur = malloc(sizeof(glTexList)); + } else { + cur = malloc(sizeof(glTexList)); + last->next = cur; + } + + /* Set node properties */ + cur->next = NULL; + cur->tex = gl_loadNewImage(path); + cur->used = 1; + + return cur->tex; +} + +/* Load the image as an opengl texture directly. */ +static glTexture* gl_loadNewImage(const char* path) { SDL_Surface* tmp, *surface; glTexture* t; uint8_t* trans = NULL; uint32_t filesize; - char* buf = pack_readfile(DATA, (char*)path, &filesize); + char* buf; + + /* Load from packfile. */ + buf = pack_readfile(DATA, (char*)path, &filesize); if(buf == NULL) { ERR("Loading surface from packfile."); return NULL; @@ -285,8 +330,10 @@ glTexture* gl_newImage(const char* path) { trans = SDL_MapTrans(surface); SDL_UnlockSurface(surface); + /* Set the texture. */ t = gl_loadImage(surface); t->trans = trans; + t->name = strdup(path); return t; } @@ -295,6 +342,11 @@ glTexture* gl_newSprite(const char* path, const int sx, const int sy) { glTexture* texture; if((texture = gl_newImage(path)) == NULL) return NULL; + + /* + * Will possibly overwrite an existing textures properties + * so we have to load some texture, always the same sprite. + */ texture->sx = (double)sx; texture->sy = (double)sy; texture->sw = texture->w/texture->sx; @@ -304,9 +356,30 @@ glTexture* gl_newSprite(const char* path, const int sx, const int sy) { /* Free the texture. */ void gl_freeTexture(glTexture* texture) { - glDeleteTextures(1, &texture->texture); - if(texture->trans) free(texture->trans); - free(texture); + glTexList* cur, *last; + + /* See if we can find it in stack. */ + last = NULL; + for(cur = texture_list; cur != NULL; cur = cur->next) { + if(cur->tex == texture) { /* Found it! */ + cur->used--; + if(cur->used <= 0) { + /* Not used anymore - Free the texture. */ + glDeleteTextures(1, &texture->texture); + if(texture->trans) free(texture->trans); + free(texture); + + /* Free the list node. */ + if(last == NULL) /* Incase it's the last texture. */ + texture_list = NULL; + else + last->next = cur->next; + free(cur); + } + return; /* We already found it so we can exit. */ + } + last = cur; + } } /* Return true if pixel at pos (x,y) is transparent. */ diff --git a/src/opengl.h b/src/opengl.h index 66b7181..cb3ca41 100644 --- a/src/opengl.h +++ b/src/opengl.h @@ -45,12 +45,22 @@ extern glInfo gl_screen; /* Local structure set with gl_init etc. */ /* Spritesheet info. */ typedef struct glTexture_ { - double w, h; /* Real size of the image (excluding POT buffer. */ - double rw, rh; /* Size of POT surface. */ - double sx, sy; /* Number of sprites on x and y axes. */ - double sw, sh; /* Size of each sprite. */ - GLuint texture; /* The opengl texture itself. */ - uint8_t* trans; /* Maps the transparency. */ + char* name; /**< Name of graphic. */ + + /* Dimensions */ + double w, h; /**< Real size of the image (excluding POT buffer). */ + double rw, rh; /**< Size of POT surface. */ + + /* Sprites */ + double sx, sy; /**< Number of sprites on x and y axes. */ + double sw, sh; /**< Size of each sprite. */ + + /* Data */ + GLuint texture; /**< The opengl texture itself. */ + uint8_t* trans; /**< Maps the transparency. */ + + /* Properies */ + uint8_t flags; /**< Flags used for texture properties. */ } glTexture; /* gl_texute loading/freeing. */ diff --git a/src/pack.c b/src/pack.c index 93a7072..46d5fbd 100644 --- a/src/pack.c +++ b/src/pack.c @@ -396,6 +396,11 @@ void* pack_readfile(const char* packfile, const char* filename, uint32_t* filesi /* Read the entire file. */ size = file->end - file->start; buf = malloc(size+1); + if(buf == NULL) { + ERR("Unable to allocate %d bytes of memory!", size+1); + free(file); + return NULL; + } if((bytes = pack_read(file, buf, size)) != size) { ERR("Reading '%s' from packfile '%s'. Expected %d bytes got %d bytes", filename, packfile, size, bytes);