From abdaf6a355523023f41ad62690b05d891e85a6f9 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Fri, 8 Feb 2019 23:20:19 +0100 Subject: [PATCH 1/6] R_FindImageLoader: make algorithm to find alternative image names reusable --- src/engine/renderer/tr_image.cpp | 99 +++++++++++++++++++------------- 1 file changed, 59 insertions(+), 40 deletions(-) diff --git a/src/engine/renderer/tr_image.cpp b/src/engine/renderer/tr_image.cpp index 563e4ec9e0..fb6072a0a8 100644 --- a/src/engine/renderer/tr_image.cpp +++ b/src/engine/renderer/tr_image.cpp @@ -1611,6 +1611,58 @@ static const imageExtToLoaderMap_t imageLoaders[] = static int numImageLoaders = ARRAY_LEN( imageLoaders ); +/* +================= +R_FindImageLoader + +Finds and returns an image loader for a given basename, +tells the extra prefix that may be required to load the image. +================= +*/ +int R_FindImageLoader( char *baseName, const char **prefix ) { + const FS::PakInfo* bestPak = nullptr; + int i; + + // Darkplaces or Doom3 packages can ship alternative texture path in the form of + // dds/.dds + std::string altName = Str::Format( "dds/%s.dds", baseName ); + bestPak = FS::PakPath::LocateFile( altName ); + + // If this alternative path exists, it's expected to be loaded as the best one + // except when it goes against Daemon's rule to load the hardcoded one if exists + // because this dds alternative is only supported for compatibility with + // third-party content + if ( bestPak != nullptr ) { + for ( i = 0; i < numImageLoaders; i++ ) { + if ( !Q_stricmp( "dds", imageLoaders[i].ext ) ) { + *prefix = "dds/"; + return i; + } + } + } + + int bestLoader = -1; + *prefix = ""; + // try and find a suitable match using all the image formats supported + // prioritize with the pak priority + for ( i = 0; i < numImageLoaders; i++ ) + { + std::string altName = Str::Format( "%s.%s", baseName, imageLoaders[i].ext ); + const FS::PakInfo* pak = FS::PakPath::LocateFile( altName ); + + // We found a file and its pak is better than the best pak we have + // this relies on how the filesystem works internally and should be moved + // to a more explicit interface once there is one. (FIXME) + if ( pak != nullptr && ( bestPak == nullptr || pak < bestPak ) ) + { + bestPak = pak; + bestLoader = i; + } + } + + return bestLoader; +} + /* ================= R_LoadImage @@ -1682,13 +1734,7 @@ static void R_LoadImage( const char **buffer, byte **pic, int *width, int *heigh // a loader was found if ( i < numImageLoaders ) { - if ( *pic == nullptr ) - { - // loader failed, most likely because the file isn't there; - // try again without the extension - COM_StripExtension3( token, filename, MAX_QPATH ); - } - else + if ( *pic != nullptr ) { // something loaded return; @@ -1696,43 +1742,16 @@ static void R_LoadImage( const char **buffer, byte **pic, int *width, int *heigh } } - int bestLoader = -1; - const FS::PakInfo* bestPak = nullptr; - - // Darkplaces or Doom3 packages can ship alternative texture path in the form of - // dds/.dds - std::string altName = Str::Format("dds/%s.dds", filename); - bestPak = FS::PakPath::LocateFile(altName); - - // If this alternative path exists, it's expected to be loaded as the best one - // except when it goes against Daemon's rule to load the hardcoded one if exists - // because this dds alternative is only supported for compatibility with - // third-party content - if ( bestPak != nullptr ) { - LoadDDS( altName.c_str(), pic, width, height, numLayers, numMips, bits, alphaByte ); - return; - } - - // try and find a suitable match using all the image formats supported - // prioritize with the pak priority - for ( i = 0; i < numImageLoaders; i++ ) - { - std::string altName = Str::Format("%s.%s", filename, imageLoaders[i].ext); - const FS::PakInfo* pak = FS::PakPath::LocateFile(altName); + // loader failed, most likely because the file isn't there; + // try again without the extension + COM_StripExtension3( token, filename, MAX_QPATH ); - // We found a file and its pak is better than the best pak we have - // this relies on how the filesystem works internally and should be moved - // to a more explicit interface once there is one. (FIXME) - if ( pak != nullptr && (bestPak == nullptr || pak < bestPak ) ) - { - bestPak = pak; - bestLoader = i; - } - } + const char *prefix; + int bestLoader = R_FindImageLoader( filename, &prefix ); if ( bestLoader >= 0 ) { - char *altName = va( "%s.%s", filename, imageLoaders[ bestLoader ].ext ); + char *altName = va( "%s%s.%s", prefix, filename, imageLoaders[ bestLoader ].ext ); imageLoaders[ bestLoader ].ImageLoader( altName, pic, width, height, numLayers, numMips, bits, alphaByte ); } } From bf6f8b0010e415d587de3aa783f272cf70c7f454 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Tue, 5 Mar 2019 04:25:36 +0100 Subject: [PATCH 2/6] R_FindImageLoader: make an alternative without prefix --- src/engine/renderer/tr_image.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/engine/renderer/tr_image.cpp b/src/engine/renderer/tr_image.cpp index fb6072a0a8..6b5f3f5e7e 100644 --- a/src/engine/renderer/tr_image.cpp +++ b/src/engine/renderer/tr_image.cpp @@ -1663,6 +1663,11 @@ int R_FindImageLoader( char *baseName, const char **prefix ) { return bestLoader; } +int R_FindImageLoader( char *baseName ) { + const char *prefix; // not used but required by R_FindImageLoader + return R_FindImageLoader( baseName, &prefix ); +} + /* ================= R_LoadImage From 1432b20bdfb7db4aca1252b5429377a529e9cb8f Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Sat, 9 Feb 2019 18:24:43 +0100 Subject: [PATCH 3/6] R_FindImageLoader: walk the image loader list only once I see no need to priorize dds/%s.dds over other formats in anyway, it's a compatibility layer after all --- src/engine/renderer/tr_image.cpp | 34 +++++++++++++------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/src/engine/renderer/tr_image.cpp b/src/engine/renderer/tr_image.cpp index 6b5f3f5e7e..e7a518cfe9 100644 --- a/src/engine/renderer/tr_image.cpp +++ b/src/engine/renderer/tr_image.cpp @@ -1623,24 +1623,6 @@ int R_FindImageLoader( char *baseName, const char **prefix ) { const FS::PakInfo* bestPak = nullptr; int i; - // Darkplaces or Doom3 packages can ship alternative texture path in the form of - // dds/.dds - std::string altName = Str::Format( "dds/%s.dds", baseName ); - bestPak = FS::PakPath::LocateFile( altName ); - - // If this alternative path exists, it's expected to be loaded as the best one - // except when it goes against Daemon's rule to load the hardcoded one if exists - // because this dds alternative is only supported for compatibility with - // third-party content - if ( bestPak != nullptr ) { - for ( i = 0; i < numImageLoaders; i++ ) { - if ( !Q_stricmp( "dds", imageLoaders[i].ext ) ) { - *prefix = "dds/"; - return i; - } - } - } - int bestLoader = -1; *prefix = ""; // try and find a suitable match using all the image formats supported @@ -1658,6 +1640,19 @@ int R_FindImageLoader( char *baseName, const char **prefix ) { bestPak = pak; bestLoader = i; } + + // DarkPlaces or Doom3 packages can ship alternative texture path in the form of + // dds/.dds + if ( bestPak == nullptr && !Q_stricmp( "dds", imageLoaders[i].ext ) ) + { + std::string prefixedName = Str::Format( "dds/%s.dds", baseName ); + bestPak = FS::PakPath::LocateFile( prefixedName ); + if ( bestPak != nullptr ) { + *prefix = "dds/"; + bestPak = pak; + bestLoader = i; + } + } } return bestLoader; @@ -1747,8 +1742,7 @@ static void R_LoadImage( const char **buffer, byte **pic, int *width, int *heigh } } - // loader failed, most likely because the file isn't there; - // try again without the extension + // the file isn't there, try again without the extension COM_StripExtension3( token, filename, MAX_QPATH ); const char *prefix; From f8dac065e7314a7f85edc57b42c953e50ce922de Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Tue, 5 Mar 2019 04:08:53 +0100 Subject: [PATCH 4/6] =?UTF-8?q?R=5FFindCubeImage:=20avoid=20the=20boring?= =?UTF-8?q?=20=E2=80=9CFailed=20to=20open=E2=80=9D=20on=20skybox=20format?= =?UTF-8?q?=20try?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/engine/renderer/tr_image.cpp | 49 ++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/src/engine/renderer/tr_image.cpp b/src/engine/renderer/tr_image.cpp index e7a518cfe9..cd09e930bc 100644 --- a/src/engine/renderer/tr_image.cpp +++ b/src/engine/renderer/tr_image.cpp @@ -1956,6 +1956,22 @@ static void R_FreeCubePics( byte **pic, int count ) } } +struct cubeMapLoader_t +{ + const char *ext; + void ( *ImageLoader )( const char *, unsigned char **, int *, int *, int *, int *, int *, byte ); +}; + +// Note that the ordering indicates the order of preference used +// when there are multiple images of different formats available +static const cubeMapLoader_t cubeMapLoaders[] = +{ + { "crn", LoadCRN }, + { "ktx", LoadKTX }, +}; + +static int numCubeMapLoaders = ARRAY_LEN( cubeMapLoaders ); + image_t *R_FindCubeImage( const char *imageName, int bits, filterType_t filterType, wrapType_t wrapType ) { int i; @@ -1996,22 +2012,25 @@ image_t *R_FindCubeImage( const char *imageName, int bits, filterType_t f } } - // try to load .CRN cubemap - LoadCRN( buffer, pic, &width, &height, &numLayers, &numMips, &bits, 0 ); - if( numLayers == 6 && pic[0] ) { - numPicsToFree = 1; - goto createCubeImage; - } else { - R_FreeCubePics( pic, numLayers ); - } + const char *cubeMapName; + char cubeMapBaseName[ MAX_QPATH ]; - // try to load .KTX cubemap - LoadKTX( buffer, pic, &width, &height, &numLayers, &numMips, &bits, 0 ); - if( numLayers == 6 && pic[0] ) { - numPicsToFree = 1; - goto createCubeImage; - } else { - R_FreeCubePics( pic, numLayers ); + COM_StripExtension3( buffer, cubeMapBaseName, MAX_QPATH ); + + for ( i = 0; i < numCubeMapLoaders; i++ ) + { + cubeMapName = va( "%s.%s", cubeMapBaseName, cubeMapLoaders[ i ].ext ); + if( R_FindImageLoader( (char*) cubeMapName ) >= 0 ) + { + Log::Debug( "found %s cube map '%s'", cubeMapLoaders[ i ].ext, cubeMapBaseName ); + cubeMapLoaders[ i ].ImageLoader( cubeMapName, pic, &width, &height, &numLayers, &numMips, &bits, 0 ); + if( numLayers == 6 && pic[0] ) { + numPicsToFree = 1; + goto createCubeImage; + } else { + R_FreeCubePics( pic, numLayers ); + } + } } for ( i = 0; i < 6; i++ ) From 943627452c448607b346a782d3dd24fd98c6e16b Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Wed, 6 Mar 2019 05:12:35 +0100 Subject: [PATCH 5/6] R_FindImageLoader/R_FindCubeImage: better c++ --- src/engine/renderer/tr_image.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/engine/renderer/tr_image.cpp b/src/engine/renderer/tr_image.cpp index cd09e930bc..3a434c8737 100644 --- a/src/engine/renderer/tr_image.cpp +++ b/src/engine/renderer/tr_image.cpp @@ -1619,7 +1619,7 @@ Finds and returns an image loader for a given basename, tells the extra prefix that may be required to load the image. ================= */ -int R_FindImageLoader( char *baseName, const char **prefix ) { +static int R_FindImageLoader( const char *baseName, const char **prefix ) { const FS::PakInfo* bestPak = nullptr; int i; @@ -1658,8 +1658,10 @@ int R_FindImageLoader( char *baseName, const char **prefix ) { return bestLoader; } -int R_FindImageLoader( char *baseName ) { - const char *prefix; // not used but required by R_FindImageLoader +static int R_FindImageLoader( const char *baseName ) { + // not used but required by R_FindImageLoader + const char *prefix; + return R_FindImageLoader( baseName, &prefix ); } @@ -2012,18 +2014,16 @@ image_t *R_FindCubeImage( const char *imageName, int bits, filterType_t f } } - const char *cubeMapName; char cubeMapBaseName[ MAX_QPATH ]; - - COM_StripExtension3( buffer, cubeMapBaseName, MAX_QPATH ); + COM_StripExtension3( buffer, cubeMapBaseName, sizeof( cubeMapBaseName ) ); for ( i = 0; i < numCubeMapLoaders; i++ ) { - cubeMapName = va( "%s.%s", cubeMapBaseName, cubeMapLoaders[ i ].ext ); - if( R_FindImageLoader( (char*) cubeMapName ) >= 0 ) + std::string cubeMapName = Str::Format( "%s.%s", cubeMapBaseName, cubeMapLoaders[ i ].ext ); + if( R_FindImageLoader( cubeMapName.c_str() ) >= 0 ) { Log::Debug( "found %s cube map '%s'", cubeMapLoaders[ i ].ext, cubeMapBaseName ); - cubeMapLoaders[ i ].ImageLoader( cubeMapName, pic, &width, &height, &numLayers, &numMips, &bits, 0 ); + cubeMapLoaders[ i ].ImageLoader( cubeMapName.c_str(), pic, &width, &height, &numLayers, &numMips, &bits, 0 ); if( numLayers == 6 && pic[0] ) { numPicsToFree = 1; goto createCubeImage; From f71cba58b13f907c4b5feed10dfa969a1073c0ce Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Wed, 6 Mar 2019 05:52:37 +0100 Subject: [PATCH 6/6] R_FindImageLoader: export symbol --- src/engine/renderer/tr_image.cpp | 2 +- src/engine/renderer/tr_local.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/engine/renderer/tr_image.cpp b/src/engine/renderer/tr_image.cpp index 3a434c8737..35c2c80a24 100644 --- a/src/engine/renderer/tr_image.cpp +++ b/src/engine/renderer/tr_image.cpp @@ -1658,7 +1658,7 @@ static int R_FindImageLoader( const char *baseName, const char **prefix ) { return bestLoader; } -static int R_FindImageLoader( const char *baseName ) { +int R_FindImageLoader( const char *baseName ) { // not used but required by R_FindImageLoader const char *prefix; diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index 165dd65f70..1d894ae511 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -3150,6 +3150,7 @@ static inline void halfToFloat( const f16vec4_t in, vec4_t out ) void R_InitImages(); void R_ShutdownImages(); + int R_FindImageLoader( const char *baseName ); image_t *R_FindImageFile( const char *name, int bits, filterType_t filterType, wrapType_t wrapType ); image_t *R_FindCubeImage( const char *name, int bits, filterType_t filterType, wrapType_t wrapType );