From 875d32800f3297404162351e0034eb9615a6cbb4 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Sat, 9 Mar 2024 14:39:35 -0600 Subject: [PATCH 1/4] Disallow patches >2048 in size Our technical hardware support baseline is GLES2, which has a minimum supported texture size of 2048x2048. This means we cannot allow anything larger without introducing compatibility issues between GL players and software players. Even if Software is able to handle larger images, GL hardware may not, even on the same device. This additionally prevents an issue with Twodee where the patch atlas can't handle images larger than 2048x2048 due to the page size. --- src/w_wad.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/w_wad.cpp b/src/w_wad.cpp index 780acadee..576ce5f96 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -1931,6 +1931,17 @@ static void *MakePatch(void *lumpdata, size_t size, INT32 tag, void *cache) Patch_Create(static_cast(ptr), len, dest); + { + patch_t* patch = (patch_t*) ptr; + + if (patch->width > 2048 || patch->height > 2048) + { + // This is INTENTIONAL. Even if software can handle it, very old GL hardware will not. + // For the sake of a compatibility baseline, we will not allow anything larger than this. + I_Error("Patch size cannot be greater than 2048x2048!"); + } + } + return dest; } From 2ee595419c89a494203f61aa2cadc7c60c8927b4 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 9 Mar 2024 15:35:06 -0800 Subject: [PATCH 2/4] Let texture loading skip some textures - Set numtextures correctly if textures are skipped (no textures are skipped in this commit) --- src/r_textures.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/r_textures.c b/src/r_textures.c index 971b63ab9..ea1033c84 100644 --- a/src/r_textures.c +++ b/src/r_textures.c @@ -1491,13 +1491,6 @@ void R_LoadTextures(void) for (w = 0; w < numwadfiles; w++) { newtextures += R_CountTextures((UINT16)w); - -#ifdef DEVELOP - if (w == mainwads) - { - maintextures = newtextures; - } -#endif } // If no textures found by this point, bomb out @@ -1509,9 +1502,16 @@ void R_LoadTextures(void) for (i = 0, w = 0; w < numwadfiles; w++) { i = R_DefineTextures(i, w); + +#ifdef DEVELOP + if (w == mainwads) + { + maintextures = i; + } +#endif } - R_FinishLoadingTextures(newtextures); + R_FinishLoadingTextures(i); #ifdef DEVELOP R_CheckTextureDuplicates(0, maintextures); @@ -1523,7 +1523,7 @@ void R_LoadTexturesPwad(UINT16 wadnum) INT32 newtextures = R_CountTextures(wadnum); R_AllocateTextures(newtextures); - R_DefineTextures(numtextures, wadnum); + newtextures = R_DefineTextures(numtextures, wadnum); R_FinishLoadingTextures(newtextures); } From 6d7dd8adacdbf65ad27ee3ea897228550f39b24c Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 9 Mar 2024 15:36:22 -0800 Subject: [PATCH 3/4] Disallow textures >2048 in size, print a console warning --- src/r_textures.c | 52 ++++++++++++++++++++++++++++------------- src/r_textures.h | 3 +++ src/r_textures_dups.cpp | 34 +++++++++++++++++++++++---- 3 files changed, 68 insertions(+), 21 deletions(-) diff --git a/src/r_textures.c b/src/r_textures.c index ea1033c84..e3df88b82 100644 --- a/src/r_textures.c +++ b/src/r_textures.c @@ -1259,6 +1259,7 @@ Rloadtextures (INT32 i, INT32 w) #ifndef NO_PNG_LUMPS size_t lumplength; #endif + INT32 width, height; if (wadfiles[w]->type == RET_PK3) { @@ -1271,6 +1272,35 @@ Rloadtextures (INT32 i, INT32 w) lumplength = W_LumpLengthPwad(wadnum, lumpnum); #endif +#ifndef NO_PNG_LUMPS + if (Picture_IsLumpPNG((UINT8 *)&patchlump, lumplength)) + { + UINT8 *png = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + Picture_PNGDimensions(png, &width, &height, NULL, NULL, lumplength); + width = (INT16)width; + height = (INT16)height; + Z_Free(png); + } + else +#endif + { + width = SHORT(patchlump.width); + height = SHORT(patchlump.height); + } + + if (width > 2048 || height > 2048) + { + // This is INTENTIONAL. Even if software can handle it, very old GL hardware will not. + // For the sake of a compatibility baseline, we will not allow anything larger than this. + char header[1024]; + sprintf(header, + "Texture patch size cannot be greater than %dx%d!\n" + "List of affected textures:\n", + sizeLimit, sizeLimit); + R_InsertTextureWarning(header, va("\x82" "WARNING: %s", wadfiles[wadnum]->lumpinfo[lumpnum].fullname)); + continue; + } + //CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),patchlump->width, patchlump->height); texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL); @@ -1278,22 +1308,8 @@ Rloadtextures (INT32 i, INT32 w) M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name)); texture->hash = quickncasehash(texture->name, 8); -#ifndef NO_PNG_LUMPS - if (Picture_IsLumpPNG((UINT8 *)&patchlump, lumplength)) - { - UINT8 *png = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); - INT32 width, height; - Picture_PNGDimensions(png, &width, &height, NULL, NULL, lumplength); - texture->width = (INT16)width; - texture->height = (INT16)height; - Z_Free(png); - } - else -#endif - { - texture->width = SHORT(patchlump.width); - texture->height = SHORT(patchlump.height); - } + texture->width = width; + texture->height = height; texture->type = TEXTURETYPE_SINGLEPATCH; texture->patchcount = 1; @@ -1516,6 +1532,8 @@ void R_LoadTextures(void) #ifdef DEVELOP R_CheckTextureDuplicates(0, maintextures); #endif + + R_PrintTextureWarnings(); } void R_LoadTexturesPwad(UINT16 wadnum) @@ -1525,6 +1543,8 @@ void R_LoadTexturesPwad(UINT16 wadnum) R_AllocateTextures(newtextures); newtextures = R_DefineTextures(numtextures, wadnum); R_FinishLoadingTextures(newtextures); + + R_PrintTextureWarnings(); } static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) diff --git a/src/r_textures.h b/src/r_textures.h index 5a2dffd79..98a78ba0d 100644 --- a/src/r_textures.h +++ b/src/r_textures.h @@ -114,6 +114,9 @@ lumpnum_t R_GetFlatNumForName(const char *name); void R_CheckTextureDuplicates(INT32 start, INT32 end); void R_PrintTextureDuplicates(void); +void R_InsertTextureWarning(const char *header, const char *warning); +void R_PrintTextureWarnings(void); + extern INT32 numtextures; extern INT32 g_texturenum_dbgline; diff --git a/src/r_textures_dups.cpp b/src/r_textures_dups.cpp index ba167df80..1de9cb1c1 100644 --- a/src/r_textures_dups.cpp +++ b/src/r_textures_dups.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,7 @@ namespace { std::unordered_map> g_dups; +std::map> g_warnings; std::thread g_dups_thread; std::string key8char(const char cstr[8]) @@ -146,15 +148,37 @@ void R_PrintTextureDuplicates(void) g_dups_thread.join(); } - if (g_dups.empty()) - { - return; - } - for (auto [key, v] : g_dups) { std::for_each(v.cbegin(), v.cend(), print_dup); } g_dups = {}; + + R_PrintTextureWarnings(); +} + +void R_InsertTextureWarning(const char *header, const char *warning) +{ + g_warnings[header].push_back(warning); +} + +void R_PrintTextureWarnings(void) +{ + if (g_dups_thread.joinable()) + { + return; + } + + for (auto [header, v] : g_warnings) + { + CONS_Alert(CONS_WARNING, "\n%s", header.c_str()); + + for (const std::string& warning : v) + { + CONS_Printf("%s\n", warning.c_str()); + } + } + + g_warnings = {}; } From 7d23dd49afce28edff7f7dac0a765b91970e16d0 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 9 Mar 2024 16:14:53 -0800 Subject: [PATCH 4/4] Let base game textures be 4096x4096 max, print developer warning in DEVELOP - In the future we should make sure no textures exceed 2048x2048, but this fine for release - The warning will not show up in release builds --- src/r_textures.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/r_textures.c b/src/r_textures.c index e3df88b82..d0aef77d9 100644 --- a/src/r_textures.c +++ b/src/r_textures.c @@ -1288,7 +1288,26 @@ Rloadtextures (INT32 i, INT32 w) height = SHORT(patchlump.height); } - if (width > 2048 || height > 2048) + INT32 sizeLimit = 2048; + if (w <= mainwads) + { + // TODO: we ran out of time to do this properly. + // 4096 limit on textures may be incompatible with some older graphics cards (circa 2005-2008?). + // This only a consideration for Legacy GL at the moment -- these will still work in Software. + // In the future, we may rely more on hardware rendering and this would become a problem. + sizeLimit = 4096; +#ifdef DEVELOP + if ((width > 2048 && width < sizeLimit) || (height > 2048 && height < sizeLimit)) + { + R_InsertTextureWarning( + " \x87(2.x developer warning, will not appear on release)\n" + "\x87These textures should ideally not be larger than 2048x2048:\n", + va("\x86%s", wadfiles[wadnum]->lumpinfo[lumpnum].fullname) + ); + } +#endif + } + if (width > sizeLimit || height > sizeLimit) { // This is INTENTIONAL. Even if software can handle it, very old GL hardware will not. // For the sake of a compatibility baseline, we will not allow anything larger than this.