From: havoc Date: Mon, 30 Apr 2018 06:38:44 +0000 (+0000) Subject: Fix bugs with unloading of cachepic skinframes in QC menus - the reloading was broken... X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=7689a4aa19ea33f53a5a0345c904e7081c6ac6ea;p=xonotic%2Fdarkplaces.git Fix bugs with unloading of cachepic skinframes in QC menus - the reloading was broken in some weird way that made it white (it wasn't reusing the skinframe). Simplify Draw_CachePic behaviors with regards to NewPic and textureflags (mismatch now causes texture reload rather than having multiple with the same name in memory). Improved reloading of unloaded pics by reusing the existing skinframe, so it can not produce duplicates. Make Draw_NewPic clear the pic->autoload flag, this is a behavior change in VM_CL_ReadPicture. git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@12407 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/gl_draw.c b/gl_draw.c index 47a90f9c..b33200fe 100644 --- a/gl_draw.c +++ b/gl_draw.c @@ -105,23 +105,19 @@ cachepic_t *Draw_CachePic_Flags(const char *path, unsigned int cachepicflags) if (!strcmp(path, pic->name)) { // if it was created (or replaced) by Draw_NewPic, just return it - if (pic->flags & CACHEPICFLAG_NEWPIC) + if (!(pic->flags & CACHEPICFLAG_NEWPIC)) { - if (pic->skinframe) - R_SkinFrame_MarkUsed(pic->skinframe); - pic->lastusedframe = draw_frame; - return pic; - } - if (!((pic->texflags ^ texflags) & ~(TEXF_COMPRESS | TEXF_MIPMAP))) // ignore TEXF_COMPRESS when comparing, because fallback pics remove the flag, and ignore TEXF_MIPMAP because QC specifies that - { - if (!pic->skinframe || !pic->skinframe->base) + // reload the pic if texflags changed in important ways + // ignore TEXF_COMPRESS when comparing, because fallback pics remove the flag, and ignore TEXF_MIPMAP because QC specifies that + if (!pic->skinframe || !pic->skinframe->base || ((pic->texflags ^ texflags) & ~(TEXF_COMPRESS | TEXF_MIPMAP))) goto reload; if (!(cachepicflags & CACHEPICFLAG_NOTPERSISTENT)) pic->autoload = false; // caller is making this pic persistent - R_SkinFrame_MarkUsed(pic->skinframe); - pic->lastusedframe = draw_frame; - return pic; } + if (pic->skinframe) + R_SkinFrame_MarkUsed(pic->skinframe); + pic->lastusedframe = draw_frame; + return pic; } } @@ -147,8 +143,16 @@ reload: pic->autoload = (cachepicflags & CACHEPICFLAG_NOTPERSISTENT) != 0; pic->lastusedframe = draw_frame; - // load high quality image (this falls back to low quality too) - pic->skinframe = R_SkinFrame_LoadExternal(pic->name, texflags | TEXF_FORCE_RELOAD, (cachepicflags & CACHEPICFLAG_QUIET) == 0, (cachepicflags & CACHEPICFLAG_FAILONMISSING) == 0); + if (pic->skinframe) + { + // reload image after it was unloaded or texflags changed significantly + R_SkinFrame_LoadExternal_SkinFrame(pic->skinframe, pic->name, texflags | TEXF_FORCE_RELOAD, (cachepicflags & CACHEPICFLAG_QUIET) == 0, (cachepicflags & CACHEPICFLAG_FAILONMISSING) == 0); + } + else + { + // load high quality image (this falls back to low quality too) + pic->skinframe = R_SkinFrame_LoadExternal(pic->name, texflags | TEXF_FORCE_RELOAD, (cachepicflags & CACHEPICFLAG_QUIET) == 0, (cachepicflags & CACHEPICFLAG_FAILONMISSING) == 0); + } // get the dimensions of the image we loaded (if it was successful) if (pic->skinframe && pic->skinframe->base) @@ -262,6 +266,7 @@ cachepic_t *Draw_NewPic(const char *picname, int width, int height, unsigned cha R_SkinFrame_PurgeSkinFrame(pic->skinframe); + pic->autoload = false; pic->flags = CACHEPICFLAG_NEWPIC; // disable texflags checks in Draw_CachePic pic->flags |= (texflags & TEXF_CLAMP) ? 0 : CACHEPICFLAG_NOCLAMP; pic->flags |= (texflags & TEXF_FORCENEAREST) ? CACHEPICFLAG_NEAREST : 0; @@ -759,6 +764,8 @@ void DrawQ_Pic(float x, float y, cachepic_t *pic, float width, float height, flo int e0, e1, e2, e3; if (!pic) pic = Draw_CachePic("white"); + // make sure pic is loaded - we don't use the texture here, Mod_Mesh_GetTexture looks up the skinframe by name + Draw_GetPicTexture(pic); if (width == 0) width = pic->width; if (height == 0) @@ -785,6 +792,8 @@ void DrawQ_RotPic(float x, float y, cachepic_t *pic, float width, float height, int e0, e1, e2, e3; if (!pic) pic = Draw_CachePic("white"); + // make sure pic is loaded - we don't use the texture here, Mod_Mesh_GetTexture looks up the skinframe by name + Draw_GetPicTexture(pic); if (width == 0) width = pic->width; if (height == 0) @@ -1379,6 +1388,8 @@ void DrawQ_SuperPic(float x, float y, cachepic_t *pic, float width, float height int e0, e1, e2, e3; if (!pic) pic = Draw_CachePic("white"); + // make sure pic is loaded - we don't use the texture here, Mod_Mesh_GetTexture looks up the skinframe by name + Draw_GetPicTexture(pic); if (width == 0) width = pic->width; if (height == 0) diff --git a/gl_rmain.c b/gl_rmain.c index 6fc78526..5efd8434 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -2278,8 +2278,25 @@ skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewid skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \ } -extern cvar_t gl_picmip; skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain, qboolean fallbacknotexture) +{ + skinframe_t *skinframe; + + if (cls.state == ca_dedicated) + return NULL; + + // return an existing skinframe if already loaded + // if loading of the first image fails, don't make a new skinframe as it + // would cause all future lookups of this to be missing + skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, -1, false); + if (skinframe && skinframe->base) + return skinframe; + + return R_SkinFrame_LoadExternal_SkinFrame(skinframe, name, textureflags, complain, fallbacknotexture); +} + +extern cvar_t gl_picmip; +skinframe_t *R_SkinFrame_LoadExternal_SkinFrame(skinframe_t *skinframe, const char *name, int textureflags, qboolean complain, qboolean fallbacknotexture) { int j; unsigned char *pixels; @@ -2287,7 +2304,6 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole unsigned char *basepixels = NULL; int basepixels_width = 0; int basepixels_height = 0; - skinframe_t *skinframe; rtexture_t *ddsbase = NULL; qboolean ddshasalpha = false; float ddsavgcolor[4]; @@ -2300,13 +2316,6 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole if (cls.state == ca_dedicated) return NULL; - // return an existing skinframe if already loaded - // if loading of the first image fails, don't make a new skinframe as it - // would cause all future lookups of this to be missing - skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, -1, false); - if (skinframe && skinframe->base) - return skinframe; - Image_StripImageExtension(name, basename, sizeof(basename)); // check for DDS texture file first @@ -2512,7 +2521,7 @@ skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, co return NULL; // if already loaded just return it, otherwise make a new skinframe - skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true); + skinframe = R_SkinFrame_Find(name, textureflags, width, height, (!(textureflags & TEXF_FORCE_RELOAD) && skindata) ? CRC_Block(skindata, width*height*4) : -1, true); if (skinframe->base) return skinframe; textureflags &= ~TEXF_FORCE_RELOAD; @@ -2582,7 +2591,7 @@ skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, i return NULL; // if already loaded just return it, otherwise make a new skinframe - skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true); + skinframe = R_SkinFrame_Find(name, textureflags, width, height, (!(textureflags & TEXF_FORCE_RELOAD) && skindata) ? CRC_Block(skindata, width*height) : -1, true); if (skinframe->base) return skinframe; //textureflags &= ~TEXF_FORCE_RELOAD; diff --git a/render.h b/render.h index ce95a4b2..dcacb639 100644 --- a/render.h +++ b/render.h @@ -280,6 +280,7 @@ void R_SkinFrame_Purge(void); skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ); skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add); skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain, qboolean fallbacknotexture); +skinframe_t *R_SkinFrame_LoadExternal_SkinFrame(skinframe_t *skinframe, const char *name, int textureflags, qboolean complain, qboolean fallbacknotexture); skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB); skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height); skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette);