From e15ffd2bc8a76ede6ce15973b52ba78bc6bd17ca Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 20 Oct 2019 20:21:22 -0700 Subject: [PATCH] Optimize texture/patch/png/flat flat caching SIGSEGV in the case where you have a TEXTURES entry, but no texture or flat, has been fixed. Missing flats for now yield a HOM instead of REDFLR as well. OpenGL also doesn't work yet. And I'm too tired for now to bother with it. --- src/p_setup.c | 173 ++++++++++++++++++++++++++++---------------------- src/p_setup.h | 39 ++++++++++-- src/p_spec.c | 22 +++---- src/r_data.c | 42 ------------ src/r_plane.c | 85 +++++++++++++------------ 5 files changed, 186 insertions(+), 175 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index c83c8cd5c..ffd8de33f 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -546,52 +546,110 @@ size_t P_PrecacheLevelFlats(void) //SoM: 4/18/2000: New flat code to make use of levelflats. for (i = 0; i < numlevelflats; i++) { - lump = levelflats[i].lumpnum; - if (devparm) - flatmemory += W_LumpLength(lump); - R_GetFlat(lump); + if (levelflats[i].type == LEVELFLAT_FLAT) + { + lump = levelflats[i].u.flat.lumpnum; + if (devparm) + flatmemory += W_LumpLength(lump); + R_GetFlat(lump); + } } return flatmemory; } +/* +levelflat refers to an array of level flats, +or NULL if we want to allocate it now. +*/ +static INT32 +Ploadflat (levelflat_t *levelflat, const char *flatname) +{ + UINT8 buffer[8]; + + lumpnum_t flatnum; + int texturenum; + + size_t i; + + if (levelflat) + { + // Scan through the already found flats, return if it matches. + for (i = 0; i < numlevelflats; i++) + { + if (strnicmp(levelflat[i].name, flatname, 8) == 0) + return i; + } + } + +#ifndef ZDEBUG + CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name); +#endif + + if (numlevelflats >= MAXLEVELFLATS) + I_Error("Too many flats in level\n"); + + if (levelflat) + levelflat += numlevelflats; + else + { + // allocate new flat memory + levelflats = Z_Realloc(levelflats, (numlevelflats + 1) * sizeof(*levelflats), PU_LEVEL, NULL); + levelflat = levelflats + numlevelflats; + } + + // Store the name. + strlcpy(levelflat->name, flatname, sizeof (levelflat->name)); + strupr(levelflat->name); + + /* If we can't find a flat, try looking for a texture! */ + if (( flatnum = R_GetFlatNumForName(flatname) ) == LUMPERROR) + { + if (( texturenum = R_CheckTextureNumForName(flatname) ) == -1) + { + /* we can handle REDWALL later */ + levelflat->type = LEVELFLAT_NONE; + } + else + { + levelflat->type = LEVELFLAT_TEXTURE; + levelflat->u.texture. num = texturenum; + levelflat->u.texture.lastnum = texturenum; + /* start out unanimated */ + levelflat->u.texture.basenum = -1; + } + } + else + { + /* This could be a flat, patch, or PNG. */ + if (R_CheckIfPatch(flatnum)) + levelflat->type = LEVELFLAT_PATCH; + else + { +#ifndef NO_PNG_LUMPS + /* + Only need eight bytes for PNG headers. + FIXME: Put this elsewhere. + */ + W_ReadLumpHeader(flatnum, buffer, 8, 0); + if (R_IsLumpPNG(buffer, W_LumpLength(flatnum))) + levelflat->type = LEVELFLAT_PNG; + else +#endif/*NO_PNG_LUMPS*/ + levelflat->type = LEVELFLAT_FLAT;/* phew */ + } + + levelflat->u.flat. lumpnum = flatnum; + levelflat->u.flat.baselumpnum = LUMPERROR; + } + + return ( numlevelflats++ ); +} + // Auxiliary function. Find a flat in the active wad files, // allocate an id for it, and set the levelflat (to speedup search) INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat) { - size_t i; - - // Scan through the already found flats, break if it matches. - for (i = 0; i < numlevelflats; i++, levelflat++) - if (strnicmp(levelflat->name, flatname, 8) == 0) - break; - - // If there is no match, make room for a new flat. - if (i == numlevelflats) - { - // Store the name. - strlcpy(levelflat->name, flatname, sizeof (levelflat->name)); - strupr(levelflat->name); - - // store the flat lump number - levelflat->lumpnum = R_GetFlatNumForName(flatname); - levelflat->texturenum = R_CheckTextureNumForName(flatname); - levelflat->lasttexturenum = levelflat->texturenum; - - levelflat->baselumpnum = LUMPERROR; - levelflat->basetexturenum = -1; - -#ifndef ZDEBUG - CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name); -#endif - - numlevelflats++; - - if (numlevelflats >= MAXLEVELFLATS) - I_Error("Too many flats in level\n"); - } - - // level flat id - return (INT32)i; + return Ploadflat(levelflat, flatname); } // help function for Lua and $$$.sav reading @@ -600,44 +658,7 @@ INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat) // INT32 P_AddLevelFlatRuntime(const char *flatname) { - size_t i; - levelflat_t *levelflat = levelflats; - - // - // first scan through the already found flats - // - for (i = 0; i < numlevelflats; i++, levelflat++) - if (strnicmp(levelflat->name,flatname,8)==0) - break; - - // that flat was already found in the level, return the id - if (i == numlevelflats) - { - // allocate new flat memory - levelflats = Z_Realloc(levelflats, (numlevelflats + 1) * sizeof(*levelflats), PU_LEVEL, NULL); - levelflat = levelflats+i; - - // store the name - strlcpy(levelflat->name, flatname, sizeof (levelflat->name)); - strupr(levelflat->name); - - // store the flat lump number - levelflat->lumpnum = R_GetFlatNumForName(flatname); - levelflat->texturenum = R_CheckTextureNumForName(flatname); - levelflat->lasttexturenum = levelflat->texturenum; - - levelflat->baselumpnum = LUMPERROR; - levelflat->basetexturenum = -1; - -#ifndef ZDEBUG - CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name); -#endif - - numlevelflats++; - } - - // level flat id - return (INT32)i; + return Ploadflat(0, flatname); } // help function for $$$.sav checking diff --git a/src/p_setup.h b/src/p_setup.h index 7e3a149eb..d8787073b 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -30,20 +30,51 @@ extern boolean levelloading; extern UINT8 levelfadecol; extern lumpnum_t lastloadedmaplumpnum; // for comparative savegame + +/* for levelflat type */ +enum +{ + LEVELFLAT_NONE,/* HOM time my friend */ + LEVELFLAT_FLAT, + LEVELFLAT_PATCH, +#ifndef NO_PNG_LUMPS + LEVELFLAT_PNG, +#endif + LEVELFLAT_TEXTURE, +}; + // // MAP used flats lookup table // typedef struct { char name[9]; // resource name from wad - lumpnum_t lumpnum; // lump number of the flat - INT32 texturenum, lasttexturenum; // texture number of the flat + + UINT8 type; + union + { + struct + { + lumpnum_t lumpnum; // lump number of the flat + // for flat animation + lumpnum_t baselumpnum; + } + flat; + struct + { + INT32 num; + INT32 lastnum; // texture number of the flat + // for flat animation + INT32 basenum; + } + texture; + } + u; + UINT16 width, height; fixed_t topoffset, leftoffset; // for flat animation - lumpnum_t baselumpnum; - INT32 basetexturenum; INT32 animseq; // start pos. in the anim sequence INT32 numpics; INT32 speed; diff --git a/src/p_spec.c b/src/p_spec.c index ebee50a45..3c987ac68 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -464,11 +464,11 @@ static inline void P_FindAnimatedFlat(INT32 animnum) for (i = 0; i < numlevelflats; i++, foundflats++) { // is that levelflat from the flat anim sequence ? - if ((anims[animnum].istexture) && (foundflats->texturenum != 0 && foundflats->texturenum != -1) - && ((UINT16)foundflats->texturenum >= startflatnum && (UINT16)foundflats->texturenum <= endflatnum)) + if ((anims[animnum].istexture) && (foundflats->u.texture.num != 0 && foundflats->u.texture.num != -1) + && ((UINT16)foundflats->u.texture.num >= startflatnum && (UINT16)foundflats->u.texture.num <= endflatnum)) { - foundflats->basetexturenum = startflatnum; - foundflats->animseq = foundflats->texturenum - startflatnum; + foundflats->u.texture.basenum = startflatnum; + foundflats->animseq = foundflats->u.texture.num - startflatnum; foundflats->numpics = endflatnum - startflatnum + 1; foundflats->speed = anims[animnum].speed; @@ -476,10 +476,10 @@ static inline void P_FindAnimatedFlat(INT32 animnum) atoi(sizeu1(i)), foundflats->name, foundflats->animseq, foundflats->numpics,foundflats->speed); } - else if (foundflats->lumpnum >= startflatnum && foundflats->lumpnum <= endflatnum) + else if (foundflats->u.flat.lumpnum >= startflatnum && foundflats->u.flat.lumpnum <= endflatnum) { - foundflats->baselumpnum = startflatnum; - foundflats->animseq = foundflats->lumpnum - startflatnum; + foundflats->u.flat.baselumpnum = startflatnum; + foundflats->animseq = foundflats->u.flat.lumpnum - startflatnum; foundflats->numpics = endflatnum - startflatnum + 1; foundflats->speed = anims[animnum].speed; @@ -5578,11 +5578,11 @@ void P_UpdateSpecials(void) if (foundflats->speed) // it is an animated flat { // update the levelflat texture number - if (foundflats->basetexturenum != -1) - foundflats->texturenum = foundflats->basetexturenum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics); + if (foundflats->u.texture.basenum != -1) + foundflats->u.texture.num = foundflats->u.texture.basenum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics); // update the levelflat lump number - else if (foundflats->baselumpnum != LUMPERROR) - foundflats->lumpnum = foundflats->baselumpnum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics); + else if (foundflats->u.flat.baselumpnum != LUMPERROR) + foundflats->u.flat.lumpnum = foundflats->u.flat.baselumpnum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics); } } } diff --git a/src/r_data.c b/src/r_data.c index f1d19a219..610568d8f 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1446,48 +1446,6 @@ lumpnum_t R_GetFlatNumForName(const char *name) lump = LUMPERROR; } - // Detect textures - if (lump == LUMPERROR) - { - // Scan wad files backwards so patched textures take preference. - for (i = numwadfiles - 1; i >= 0; i--) - { - switch (wadfiles[i]->type) - { - case RET_WAD: - if ((start = W_CheckNumForNamePwad("TX_START", (UINT16)i, 0)) == INT16_MAX) - continue; - if ((end = W_CheckNumForNamePwad("TX_END", (UINT16)i, start)) == INT16_MAX) - continue; - break; - case RET_PK3: - if ((start = W_CheckNumForFolderStartPK3("Textures/", i, 0)) == INT16_MAX) - continue; - if ((end = W_CheckNumForFolderEndPK3("Textures/", i, start)) == INT16_MAX) - continue; - break; - default: - continue; - } - - // Now find lump with specified name in that range. - lump = W_CheckNumForNamePwad(name, (UINT16)i, start); - if (lump < end) - { - lump += (i<<16); // found it, in our constraints - break; - } - lump = LUMPERROR; - } - } - - if (lump == LUMPERROR) - { - if (strcmp(name, SKYFLATNAME)) - CONS_Debug(DBG_SETUP, "R_GetFlatNumForName: Could not find flat %.8s\n", name); - lump = W_CheckNumForName("REDFLR"); - } - return lump; } diff --git a/src/r_plane.c b/src/r_plane.c index 34debeea7..8aab50a68 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -753,9 +753,9 @@ static UINT8 *R_GenerateFlat(UINT16 width, UINT16 height) static UINT8 *R_GetTextureFlat(levelflat_t *levelflat, boolean leveltexture, boolean ispng) { UINT8 *flat; - textureflat_t *texflat = &texflats[levelflat->texturenum]; + textureflat_t *texflat = &texflats[levelflat->u.texture.num]; patch_t *patch = NULL; - boolean texturechanged = (leveltexture ? (levelflat->texturenum != levelflat->lasttexturenum) : false); + boolean texturechanged = (leveltexture ? (levelflat->u.texture.num != levelflat->u.texture.lastnum) : false); // Check if the texture changed. if (leveltexture && (!texturechanged)) @@ -777,12 +777,12 @@ static UINT8 *R_GetTextureFlat(levelflat_t *levelflat, boolean leveltexture, boo // Level texture if (leveltexture) { - texture_t *texture = textures[levelflat->texturenum]; + texture_t *texture = textures[levelflat->u.texture.num]; texflat->width = ds_flatwidth = texture->width; texflat->height = ds_flatheight = texture->height; texflat->flat = R_GenerateFlat(ds_flatwidth, ds_flatheight); - R_TextureToFlat(levelflat->texturenum, texflat->flat); + R_TextureToFlat(levelflat->u.texture.num, texflat->flat); flat = texflat->flat; levelflat->flatpatch = flat; @@ -796,7 +796,7 @@ static UINT8 *R_GetTextureFlat(levelflat_t *levelflat, boolean leveltexture, boo #ifndef NO_PNG_LUMPS if (ispng) { - levelflat->flatpatch = R_PNGToFlat(&levelflat->width, &levelflat->height, ds_source, W_LumpLength(levelflat->lumpnum)); + levelflat->flatpatch = R_PNGToFlat(&levelflat->width, &levelflat->height, ds_source, W_LumpLength(levelflat->u.flat.lumpnum)); levelflat->topoffset = levelflat->leftoffset = 0; ds_flatwidth = levelflat->width; ds_flatheight = levelflat->height; @@ -826,7 +826,7 @@ static UINT8 *R_GetTextureFlat(levelflat_t *levelflat, boolean leveltexture, boo xoffs += levelflat->leftoffset; yoffs += levelflat->topoffset; - levelflat->lasttexturenum = levelflat->texturenum; + levelflat->u.texture.lastnum = levelflat->u.texture.num; return flat; } @@ -836,10 +836,9 @@ void R_DrawSinglePlane(visplane_t *pl) INT32 light = 0; INT32 x; INT32 stop, angle; - size_t size; ffloor_t *rover; levelflat_t *levelflat; - boolean rawflat = false; + int type; if (!(pl->minx <= pl->maxx)) return; @@ -985,43 +984,45 @@ void R_DrawSinglePlane(visplane_t *pl) currentplane = pl; levelflat = &levelflats[pl->picnum]; - size = W_LumpLength(levelflat->lumpnum); - ds_source = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_STATIC); // Stay here until Z_ChangeTag - // Check if the flat is actually a wall texture. - if (levelflat->texturenum != 0 && levelflat->texturenum != -1) - flat = R_GetTextureFlat(levelflat, true, false); + /* :james: */ + type = levelflat->type; + switch (type) + { + case LEVELFLAT_NONE: + return; + case LEVELFLAT_FLAT: + ds_source = W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_CACHE); + R_CheckFlatLength(W_LumpLength(levelflat->u.flat.lumpnum)); + // Raw flats always have dimensions that are powers-of-two numbers. + ds_powersoftwo = true; + break; + default: + switch (type) + { + case LEVELFLAT_TEXTURE: + /* Textures get cached differently and don't need ds_source */ + ds_source = R_GetTextureFlat(levelflat, true, false); + break; + default: + ds_source = W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_STATIC); + flat = R_GetTextureFlat(levelflat, false, #ifndef NO_PNG_LUMPS - // Maybe it's a PNG?! - else if (R_IsLumpPNG(ds_source, size)) - flat = R_GetTextureFlat(levelflat, false, true); + ( type == LEVELFLAT_PNG ) +#else + false #endif - // Maybe it's just a patch, then? - else if (R_CheckIfPatch(levelflat->lumpnum)) - flat = R_GetTextureFlat(levelflat, false, false); - // It's a raw flat. - else - { - rawflat = true; - R_CheckFlatLength(size); - flat = ds_source; - } - - Z_ChangeTag(ds_source, PU_CACHE); - ds_source = flat; - - if (ds_source == NULL) - return; - - // Raw flats always have dimensions that are powers-of-two numbers. - if (rawflat) - ds_powersoftwo = true; - // Otherwise, check if this texture or patch has such dimensions. - else if (R_CheckPowersOfTwo()) - { - R_CheckFlatLength(ds_flatwidth * ds_flatheight); - if (spanfunc == basespanfunc) - spanfunc = mmxspanfunc; + ); + Z_ChangeTag(ds_source, PU_CACHE); + ds_source = flat; + } + // Check if this texture or patch has power-of-two dimensions. + if (R_CheckPowersOfTwo()) + { + R_CheckFlatLength(ds_flatwidth * ds_flatheight); + if (spanfunc == basespanfunc) + spanfunc = mmxspanfunc; + } } if (light >= LIGHTLEVELS)