diff --git a/Plugins/Renderer/gl_draw.cpp b/Plugins/Renderer/gl_draw.cpp index 822632d9..e6e5bdca 100644 --- a/Plugins/Renderer/gl_draw.cpp +++ b/Plugins/Renderer/gl_draw.cpp @@ -78,21 +78,47 @@ void GL_Texturemode_internal(const char *value) { if (pgltextures[j].texnum) { - if (pgltextures[j].mipmap) + int iTextureTarget = GL_GetTextureTargetFromTextureEntry(&pgltextures[j]); + + if (iTextureTarget == GL_TEXTURE_2D_ARRAY) { - GL_Bind(pgltextures[j].texnum); + glBindTexture(GL_TEXTURE_2D_ARRAY, pgltextures[j].texnum); + + if (pgltextures[j].mipmap) + { + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, (*gl_filter_min)); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, (*gl_filter_max)); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_ANISOTROPY, GL_GetAnsioValue()); + } + else + { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (*gl_filter_min)); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (*gl_filter_max)); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY, GL_GetAnsioValue()); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, (*gl_filter_max)); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, (*gl_filter_max)); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_ANISOTROPY, GL_GetAnsioValue()); + } + + glBindTexture(GL_TEXTURE_2D_ARRAY, 0); } - else + else if (iTextureTarget == GL_TEXTURE_2D) { GL_Bind(pgltextures[j].texnum); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (*gl_filter_max)); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (*gl_filter_max)); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY, GL_GetAnsioValue()); + if (pgltextures[j].mipmap) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (*gl_filter_min)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (*gl_filter_max)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY, GL_GetAnsioValue()); + } + else + { + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (*gl_filter_max)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (*gl_filter_max)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY, GL_GetAnsioValue()); + } + + GL_Bind(0); } } } @@ -106,9 +132,12 @@ void GL_Texturemode_internal(const char *value) if (r_wsurf.vSkyboxTextureId[j]) { GL_Bind(r_wsurf.vSkyboxTextureId[j]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, *gl_filter_min); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, *gl_filter_max); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY, GL_GetAnsioValue()); + + GL_Bind(0); } } @@ -128,124 +157,163 @@ void GL_Texturemode_f(void) void GL_GenerateHashedTextureIndentifier(const char* identifier, GL_TEXTURETYPE textureType, char* hashedIdentifier, size_t len) { - if (textureType == GLT_SYSTEM) - { - snprintf(hashedIdentifier, len, "@SYS_%08X", MurmurHash2(identifier, strlen(identifier), textureType)); - } - else if (textureType == GLT_DECAL) - { - snprintf(hashedIdentifier, len, "@DCL_%08X", MurmurHash2(identifier, strlen(identifier), textureType)); - } - else if (textureType == GLT_HUDSPRITE) - { - snprintf(hashedIdentifier, len, "@SPH_%08X", MurmurHash2(identifier, strlen(identifier), textureType)); - } - else if (textureType == GLT_STUDIO) - { - snprintf(hashedIdentifier, len, "@MDL_%08X", MurmurHash2(identifier, strlen(identifier), textureType)); - } - else if (textureType == GLT_WORLD) - { - snprintf(hashedIdentifier, len, "@BSP_%08X", MurmurHash2(identifier, strlen(identifier), textureType)); - } - else if (textureType == GLT_SPRITE) - { - snprintf(hashedIdentifier, len, "@SPR_%08X", MurmurHash2(identifier, strlen(identifier), textureType)); - } - else if (textureType == GLT_DETAIL) - { - snprintf(hashedIdentifier, len, "@DET_%08X", MurmurHash2(identifier, strlen(identifier), textureType)); - } - else - { - strncpy(hashedIdentifier, identifier, len); +#define FORMAT_TEXTURE_IDENTIFIER(Ty, Name) if (textureType == Ty)\ + {\ + snprintf(hashedIdentifier, len, "@" Name "_%08X", MurmurHash2(identifier, strlen(identifier), textureType));\ + return;\ } + + FORMAT_TEXTURE_IDENTIFIER(GLT_SYSTEM, "SYS"); + FORMAT_TEXTURE_IDENTIFIER(GLT_DECAL, "DCL"); + FORMAT_TEXTURE_IDENTIFIER(GLT_HUDSPRITE, "HSP"); + FORMAT_TEXTURE_IDENTIFIER(GLT_STUDIO, "MDL"); + FORMAT_TEXTURE_IDENTIFIER(GLT_WORLD, "BSP"); + FORMAT_TEXTURE_IDENTIFIER(GLT_SPRITE, "SPR"); + FORMAT_TEXTURE_IDENTIFIER(GLT_DETAIL, "DET"); + +#undef FORMAT_TEXTURE_IDENTIFIER + + //Default case + strncpy(hashedIdentifier, identifier, len); } void GL_GenerateHashedTextureIndentifier2(const char* identifier, GL_TEXTURETYPE textureType, int width, int height, char * hashedIdentifier, size_t len) { - if (textureType == GLT_SYSTEM) - { - snprintf(hashedIdentifier, len, "@SYS_%08X_%04X_%04X", MurmurHash2(identifier, strlen(identifier), textureType), width, height); - } - else if (textureType == GLT_DECAL) - { - snprintf(hashedIdentifier, len, "@DCL_%08X_%04X_%04X", MurmurHash2(identifier, strlen(identifier), textureType), width, height); - } - else if (textureType == GLT_HUDSPRITE) - { - snprintf(hashedIdentifier, len, "@SPH_%08X_%04X_%04X", MurmurHash2(identifier, strlen(identifier), textureType), width, height); - } - else if (textureType == GLT_STUDIO) - { - snprintf(hashedIdentifier, len, "@MDL_%08X_%04X_%04X", MurmurHash2(identifier, strlen(identifier), textureType), width, height); - } - else if (textureType == GLT_WORLD) - { - snprintf(hashedIdentifier, len, "@BSP_%08X_%04X_%04X", MurmurHash2(identifier, strlen(identifier), textureType), width, height); - } - else if (textureType == GLT_SPRITE) - { - snprintf(hashedIdentifier, len, "@SPR_%08X_%04X_%04X", MurmurHash2(identifier, strlen(identifier), textureType), width, height); +#define FORMAT_TEXTURE_IDENTIFIER(Ty, Name) if (textureType == Ty)\ + {\ + snprintf(hashedIdentifier, len, "@" Name "_%08X_%04X_%04X", MurmurHash2(identifier, strlen(identifier), textureType), width, height);\ + return;\ } - else if (textureType == GLT_DETAIL) - { - snprintf(hashedIdentifier, len, "@DET_%08X_%04X_%04X", MurmurHash2(identifier, strlen(identifier), textureType), width, height); + + FORMAT_TEXTURE_IDENTIFIER(GLT_SYSTEM, "SYS"); + FORMAT_TEXTURE_IDENTIFIER(GLT_DECAL, "DCL"); + FORMAT_TEXTURE_IDENTIFIER(GLT_HUDSPRITE, "HSP"); + FORMAT_TEXTURE_IDENTIFIER(GLT_STUDIO, "MDL"); + FORMAT_TEXTURE_IDENTIFIER(GLT_WORLD, "BSP"); + FORMAT_TEXTURE_IDENTIFIER(GLT_SPRITE, "SPR"); + FORMAT_TEXTURE_IDENTIFIER(GLT_DETAIL, "DET"); + +#undef FORMAT_TEXTURE_IDENTIFIER + + //Default case + strncpy(hashedIdentifier, identifier, len); +} + +void GL_GenerateHashedTextureIndentifier3(const char* identifier, GL_TEXTURETYPE textureType, int width, int height, int numframes, char* hashedIdentifier, size_t len) +{ +#define FORMAT_TEXTURE_IDENTIFIER(Ty, Name) if (textureType == Ty)\ + {\ + snprintf(hashedIdentifier, len, "@" Name "_%08X_%04X_%04X_%04X", MurmurHash2(identifier, strlen(identifier), textureType), width, height, numframes);\ + return;\ } - else + + FORMAT_TEXTURE_IDENTIFIER(GLT_SYSTEM, "SYS"); + FORMAT_TEXTURE_IDENTIFIER(GLT_DECAL, "DCL"); + FORMAT_TEXTURE_IDENTIFIER(GLT_HUDSPRITE, "HSP"); + FORMAT_TEXTURE_IDENTIFIER(GLT_STUDIO, "MDL"); + FORMAT_TEXTURE_IDENTIFIER(GLT_WORLD, "BSP"); + FORMAT_TEXTURE_IDENTIFIER(GLT_SPRITE, "SPR"); + FORMAT_TEXTURE_IDENTIFIER(GLT_DETAIL, "DET"); + +#undef FORMAT_TEXTURE_IDENTIFIER + + //Default case + strncpy(hashedIdentifier, identifier, len); +} + +/* + Purpose : Parse texture's identifier. Get textureType, width, height and numframes (if exists) +*/ + +bool GL_ParseTextureIdentifier(const char* identifier, GL_TEXTURETYPE* textureType, int* width, int* height, int* numframes) +{ + int hash = 0, w = 0, h = 0, n = 0; + + auto Ty = GL_GetTextureTypeFromTextureIdentifier(identifier); + + if (Ty != GLT_UNKNOWN) { - strncpy(hashedIdentifier, identifier, len); + auto len = strlen(identifier); + + if (len == sizeof("@SYS_12345678_1234_1234_1234") - 1) + { + if (sscanf(identifier + sizeof("@SYS_") - 1, "%08X_%04X_%04X_%04X", &hash, &w, &h, &n) == 4) + { + if (width) + *width = w; + if (height) + *height = h; + if (numframes) + *numframes = n; + + return true; + } + } + else if (len == sizeof("@SYS_12345678_1234_1234") - 1) + { + if (sscanf(identifier + sizeof("@SYS_") - 1, "%08X_%04X_%04X", &hash, &w, &h) == 3) + { + if (width) + *width = w; + if (height) + *height = h; + + return true; + } + } } + + return false; } -GL_TEXTURETYPE GL_GetTextureTypeFromGLTexture(gltexture_t* glt) +GL_TEXTURETYPE GL_GetTextureTypeFromTextureIdentifier(const char *identifier) { - if (glt->identifier[0] == '@') + if (identifier[0] == '@') { - if (glt->identifier[1] == 'S' && - glt->identifier[2] == 'Y' && - glt->identifier[3] == 'S' && - glt->identifier[4] == '_') + if (identifier[1] == 'S' && + identifier[2] == 'Y' && + identifier[3] == 'S' && + identifier[4] == '_') { return GLT_SYSTEM; } - if (glt->identifier[1] == 'D' && - glt->identifier[2] == 'C' && - glt->identifier[3] == 'L' && - glt->identifier[4] == '_') + if (identifier[1] == 'D' && + identifier[2] == 'C' && + identifier[3] == 'L' && + identifier[4] == '_') { return GLT_DECAL; } - if (glt->identifier[1] == 'S' && - glt->identifier[2] == 'P' && - glt->identifier[3] == 'H' && - glt->identifier[4] == '_') + if (identifier[1] == 'S' && + identifier[2] == 'P' && + identifier[3] == 'H' && + identifier[4] == '_') { return GLT_HUDSPRITE; } - if (glt->identifier[1] == 'M' && - glt->identifier[2] == 'D' && - glt->identifier[3] == 'L' && - glt->identifier[4] == '_') + if (identifier[1] == 'M' && + identifier[2] == 'D' && + identifier[3] == 'L' && + identifier[4] == '_') { return GLT_STUDIO; } - if (glt->identifier[1] == 'B' && - glt->identifier[2] == 'S' && - glt->identifier[3] == 'P' && - glt->identifier[4] == '_') + if (identifier[1] == 'B' && + identifier[2] == 'S' && + identifier[3] == 'P' && + identifier[4] == '_') { return GLT_WORLD; } - if (glt->identifier[1] == 'S' && - glt->identifier[2] == 'P' && - glt->identifier[3] == 'R' && - glt->identifier[4] == '_') + if (identifier[1] == 'S' && + identifier[2] == 'P' && + identifier[3] == 'R' && + identifier[4] == '_') { return GLT_SPRITE; } @@ -254,6 +322,24 @@ GL_TEXTURETYPE GL_GetTextureTypeFromGLTexture(gltexture_t* glt) return GLT_UNKNOWN; } +int GL_GetTextureTargetFromTextureIdentifier(const char *identifier) +{ + int iTextureTarget = GL_TEXTURE_2D; + + //Make sure it's animated texture + if (GL_GetTextureTypeFromTextureIdentifier(identifier) != GLT_UNKNOWN && strlen(identifier) == sizeof("@SYS_12345678_1234_1234_1234") - 1) + { + iTextureTarget = GL_TEXTURE_2D_ARRAY; + } + + return iTextureTarget; +} + +int GL_GetTextureTargetFromTextureEntry(const gltexture_t* glt) +{ + return GL_GetTextureTargetFromTextureIdentifier(glt->identifier); +} + //GL Start GLuint GL_GenTexture(void) diff --git a/Plugins/Renderer/gl_local.h b/Plugins/Renderer/gl_local.h index d9d868bc..ed6ad152 100644 --- a/Plugins/Renderer/gl_local.h +++ b/Plugins/Renderer/gl_local.h @@ -507,7 +507,10 @@ void GL_Texturemode_cb(cvar_t *); void GL_GenerateHashedTextureIndentifier(const char* identifier, GL_TEXTURETYPE textureType, char* hashedIdentifier, size_t len); void GL_GenerateHashedTextureIndentifier2(const char* identifier, GL_TEXTURETYPE textureType, int width, int height, char* hashedIdentifier, size_t len); -GL_TEXTURETYPE GL_GetTextureTypeFromGLTexture(gltexture_t* glt); +void GL_GenerateHashedTextureIndentifier3(const char* identifier, GL_TEXTURETYPE textureType, int width, int height, int numframes, char* hashedIdentifier, size_t len); +GL_TEXTURETYPE GL_GetTextureTypeFromTextureIdentifier(const char* identifier); +int GL_GetTextureTargetFromTextureEntry(const gltexture_t* glt); +int GL_GetTextureTargetFromTextureIdentifier(const char* identifier); int EngineGetMaxGLTextures(); int EngineGetNumKnownModel(); diff --git a/Plugins/Renderer/gl_rmain.cpp b/Plugins/Renderer/gl_rmain.cpp index 3edc0adb..46a38dcf 100644 --- a/Plugins/Renderer/gl_rmain.cpp +++ b/Plugins/Renderer/gl_rmain.cpp @@ -2377,7 +2377,7 @@ void R_UnloadNoreferenceTextures(const std::set& textures) //"lambda" goes LoadTransPic //BSP detail texture goes GLT_SPRITE under GoldSrc while GLT_DETAIL under SvEngine, need to block vanilla detail texture - auto textureType = GL_GetTextureTypeFromGLTexture(glt); + auto textureType = GL_GetTextureTypeFromTextureIdentifier(glt->identifier); if (textureType == GLT_STUDIO || textureType == GLT_HUDSPRITE || textureType == GLT_SPRITE) { diff --git a/Plugins/Renderer/gl_studio.cpp b/Plugins/Renderer/gl_studio.cpp index cf725c2c..9a70b1ca 100644 --- a/Plugins/Renderer/gl_studio.cpp +++ b/Plugins/Renderer/gl_studio.cpp @@ -2987,6 +2987,12 @@ bool R_StudioFreeTextureInVBOMaterial(studio_vbo_material_t* VBOMaterial, int gl return false; } +/* + +Purpose : Free VBOMaterial (if there is) for this gltexturenum. + +*/ + bool R_StudioFreeVBOMaterialByTextureId(int gltexturenum) { const auto& itor = g_StudioVBOMaterialCache.find(gltexturenum); @@ -3008,9 +3014,18 @@ bool R_StudioFreeVBOMaterialByTextureId(int gltexturenum) return false; } +/* + +Purpose : + +1. Free all VBOMaterials owned by this glt. +2. Free any VBOMaterial linked to this glt. + +*/ + void R_StudioFreeTextureCallback(gltexture_t *glt) { - if (GL_GetTextureTypeFromGLTexture(glt) != GLT_STUDIO) + if (GL_GetTextureTypeFromTextureIdentifier(glt->identifier) != GLT_STUDIO) return; if (R_StudioFreeVBOMaterialByTextureId(glt->texnum))