]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_textures.c
reorganize textypeinfo_t
[xonotic/darkplaces.git] / gl_textures.c
index ea76ea63fa7c564245fd052a41ebbf9dad5a7604..5a486ed23e9266cc510cfb2fa4eee1ef625245c2 100644 (file)
@@ -3,6 +3,7 @@
 #include "image.h"
 #include "jpeg.h"
 #include "image_png.h"
+#include "intoverflow.h"
 
 cvar_t gl_max_size = {CVAR_SAVE, "gl_max_size", "2048", "maximum allowed texture size, can be used to reduce video memory usage, limited by hardware capabilities (typically 2048, 4096, or 8192)"};
 cvar_t gl_max_lightmapsize = {CVAR_SAVE, "gl_max_lightmapsize", "1024", "maximum allowed texture size for lightmap textures, use larger values to improve rendering speed, as long as there is enough video memory available (setting it too high for the hardware will cause very bad performance)"};
@@ -39,29 +40,32 @@ typedef struct textypeinfo_s
        int inputbytesperpixel;
        int internalbytesperpixel;
        float glinternalbytesperpixel;
-       int glformat;
        int glinternalformat;
+       int glformat;
        int gltype;
 }
 textypeinfo_t;
 
-static textypeinfo_t textype_palette                = {TEXTYPE_PALETTE, 1, 4, 4.0f, GL_BGRA   , 3, GL_UNSIGNED_BYTE};
-static textypeinfo_t textype_palette_alpha          = {TEXTYPE_PALETTE, 1, 4, 4.0f, GL_BGRA   , 4, GL_UNSIGNED_BYTE};
-static textypeinfo_t textype_rgba                   = {TEXTYPE_RGBA   , 4, 4, 4.0f, GL_RGBA   , 3, GL_UNSIGNED_BYTE};
-static textypeinfo_t textype_rgba_alpha             = {TEXTYPE_RGBA   , 4, 4, 4.0f, GL_RGBA   , 4, GL_UNSIGNED_BYTE};
-static textypeinfo_t textype_rgba_compress          = {TEXTYPE_RGBA   , 4, 4, 0.5f, GL_RGBA   , GL_COMPRESSED_RGB_ARB, GL_UNSIGNED_BYTE};
-static textypeinfo_t textype_rgba_alpha_compress    = {TEXTYPE_RGBA   , 4, 4, 1.0f, GL_RGBA   , GL_COMPRESSED_RGBA_ARB, GL_UNSIGNED_BYTE};
-static textypeinfo_t textype_bgra                   = {TEXTYPE_BGRA   , 4, 4, 4.0f, GL_BGRA   , 3, GL_UNSIGNED_BYTE};
-static textypeinfo_t textype_bgra_alpha             = {TEXTYPE_BGRA   , 4, 4, 4.0f, GL_BGRA   , 4, GL_UNSIGNED_BYTE};
-static textypeinfo_t textype_bgra_compress          = {TEXTYPE_BGRA   , 4, 4, 0.5f, GL_BGRA   , GL_COMPRESSED_RGB_ARB, GL_UNSIGNED_BYTE};
-static textypeinfo_t textype_bgra_alpha_compress    = {TEXTYPE_BGRA   , 4, 4, 1.0f, GL_BGRA   , GL_COMPRESSED_RGBA_ARB, GL_UNSIGNED_BYTE};
-static textypeinfo_t textype_shadowmap16            = {TEXTYPE_SHADOWMAP,2,2, 2.0f, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT16_ARB, GL_UNSIGNED_SHORT};
-static textypeinfo_t textype_shadowmap24            = {TEXTYPE_SHADOWMAP,4,4, 4.0f, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT24_ARB, GL_UNSIGNED_INT};
-static textypeinfo_t textype_alpha                  = {TEXTYPE_ALPHA  , 1, 4, 4.0f, GL_ALPHA  , 4, GL_UNSIGNED_BYTE};
-static textypeinfo_t textype_dxt1                   = {TEXTYPE_DXT1   , 4, 0, 0.5f, 0         , GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 0};
-static textypeinfo_t textype_dxt1a                  = {TEXTYPE_DXT1A  , 4, 0, 0.5f, 0         , GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 0};
-static textypeinfo_t textype_dxt3                   = {TEXTYPE_DXT3   , 4, 0, 1.0f, 0         , GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 0};
-static textypeinfo_t textype_dxt5                   = {TEXTYPE_DXT5   , 4, 0, 1.0f, 0         , GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 0};
+
+static textypeinfo_t textype_palette                = {TEXTYPE_PALETTE    , 1, 4, 4.0f, 3                               , GL_BGRA           , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_palette_alpha          = {TEXTYPE_PALETTE    , 1, 4, 4.0f, 4                               , GL_BGRA           , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_rgba                   = {TEXTYPE_RGBA       , 4, 4, 4.0f, 3                               , GL_RGBA           , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_rgba_alpha             = {TEXTYPE_RGBA       , 4, 4, 4.0f, 4                               , GL_RGBA           , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_rgba_compress          = {TEXTYPE_RGBA       , 4, 4, 0.5f, GL_COMPRESSED_RGB_S3TC_DXT1_EXT , GL_RGBA           , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_rgba_alpha_compress    = {TEXTYPE_RGBA       , 4, 4, 1.0f, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA           , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_bgra                   = {TEXTYPE_BGRA       , 4, 4, 4.0f, 3                               , GL_BGRA           , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_bgra_alpha             = {TEXTYPE_BGRA       , 4, 4, 4.0f, 4                               , GL_BGRA           , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_bgra_compress          = {TEXTYPE_BGRA       , 4, 4, 0.5f, GL_COMPRESSED_RGB_S3TC_DXT1_EXT , GL_BGRA           , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_bgra_alpha_compress    = {TEXTYPE_BGRA       , 4, 4, 1.0f, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_BGRA           , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_shadowmap16            = {TEXTYPE_SHADOWMAP  , 2, 2, 2.0f, GL_DEPTH_COMPONENT16_ARB        , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
+static textypeinfo_t textype_shadowmap24            = {TEXTYPE_SHADOWMAP  , 4, 4, 4.0f, GL_DEPTH_COMPONENT24_ARB        , GL_DEPTH_COMPONENT, GL_UNSIGNED_INT  };
+static textypeinfo_t textype_alpha                  = {TEXTYPE_ALPHA      , 1, 4, 4.0f, GL_ALPHA                        , GL_ALPHA          , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_dxt1                   = {TEXTYPE_DXT1       , 4, 0, 0.5f, GL_COMPRESSED_RGB_S3TC_DXT1_EXT , 0                 , 0                };
+static textypeinfo_t textype_dxt1a                  = {TEXTYPE_DXT1A      , 4, 0, 0.5f, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 0                 , 0                };
+static textypeinfo_t textype_dxt3                   = {TEXTYPE_DXT3       , 4, 0, 1.0f, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 0                 , 0                };
+static textypeinfo_t textype_dxt5                   = {TEXTYPE_DXT5       , 4, 0, 1.0f, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 0                 , 0                };
+static textypeinfo_t textype_colorbuffer            = {TEXTYPE_COLORBUFFER, 4, 4, 4.0f, 4                               , GL_BGRA           , GL_UNSIGNED_BYTE };
+
 
 typedef enum gltexturetype_e
 {
@@ -187,6 +191,8 @@ static textypeinfo_t *R_GetTexTypeInfo(textype_t textype, int flags)
                return &textype_alpha;
        case TEXTYPE_SHADOWMAP:
                return (flags & TEXF_LOWPRECISION) ? &textype_shadowmap16 : &textype_shadowmap24;
+       case TEXTYPE_COLORBUFFER:
+               return &textype_colorbuffer;
        default:
                Host_Error("R_GetTexTypeInfo: unknown texture format");
                return NULL;
@@ -888,7 +894,7 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *iden
        int i, size;
        gltexture_t *glt;
        gltexturepool_t *pool = (gltexturepool_t *)rtexturepool;
-       textypeinfo_t *texinfo;
+       textypeinfo_t *texinfo, *texinfo2;
 
        if (cls.state == ca_dedicated)
                return NULL;
@@ -967,10 +973,19 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *iden
        case TEXTYPE_ALPHA:
                flags |= TEXF_ALPHA;
                break;
+       case TEXTYPE_COLORBUFFER:
+               flags |= TEXF_ALPHA;
+               break;
        default:
                Host_Error("R_LoadTexture: unknown texture type");
        }
 
+       texinfo2 = R_GetTexTypeInfo(textype, flags);
+       if(size == width * height * depth * sides * texinfo->inputbytesperpixel)
+               texinfo = texinfo2;
+       else
+               Con_Printf ("R_LoadTexture: input size changed after alpha fallback\n");
+
        glt = (gltexture_t *)Mem_Alloc(texturemempool, sizeof(gltexture_t));
        if (identifier)
                strlcpy (glt->identifier, identifier, sizeof(glt->identifier));
@@ -1203,7 +1218,7 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen
        if (!dds)
                return NULL; // not found
 
-       if (memcmp(dds, "DDS ", 4) || ddssize < (unsigned int)BuffLittleLong(dds+4) || BuffLittleLong(dds+76) != 32)
+       if (ddsfilesize <= 128 || memcmp(dds, "DDS ", 4) || ddssize < (unsigned int)BuffLittleLong(dds+4) || BuffLittleLong(dds+76) != 32)
        {
                Mem_Free(dds);
                Con_Printf("^1%s: not a DDS image\n", filename);
@@ -1224,19 +1239,19 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen
                textype = TEXTYPE_BGRA;
                bytesperblock = 0;
                bytesperpixel = 4;
-               size = dds_width*dds_height*bytesperpixel;
-               if(128 + size > ddsfilesize)
+               size = INTOVERFLOW_MUL(INTOVERFLOW_MUL(dds_width, dds_height), bytesperpixel);
+               if(INTOVERFLOW_ADD(128, size) > INTOVERFLOW_NORMALIZE(ddsfilesize))
                {
                        Mem_Free(dds);
-                       Con_Printf("^1%s: invalid BGRA DDS image\n");
+                       Con_Printf("^1%s: invalid BGRA DDS image\n", filename);
                        return NULL;
                }
                // check alpha
                for (i = 3;i < size;i += 4)
                        if (ddspixels[i] < 255)
                                break;
-               if (i < size)
-                       flags |= TEXF_ALPHA;
+               if (i >= size)
+                       flags &= ~TEXF_ALPHA;
        }
        else if (!memcmp(dds+84, "DXT1", 4))
        {
@@ -1246,49 +1261,47 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen
                textype = TEXTYPE_DXT1;
                bytesperblock = 8;
                bytesperpixel = 0;
-               size = ((dds_width+3)/4)*((dds_height+3)/4)*bytesperblock;
-               if(128 + size > ddsfilesize)
+               //size = ((dds_width+3)/4)*((dds_height+3)/4)*bytesperblock;
+               size = INTOVERFLOW_MUL(INTOVERFLOW_MUL(INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_width, 3), 4), INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_height, 3), 4)), bytesperblock);
+               if(INTOVERFLOW_ADD(128, size) > INTOVERFLOW_NORMALIZE(ddsfilesize))
                {
                        Mem_Free(dds);
-                       Con_Printf("^1%s: invalid DXT1 DDS image\n");
+                       Con_Printf("^1%s: invalid DXT1 DDS image\n", filename);
                        return NULL;
                }
                for (i = 0;i < size;i += bytesperblock)
                        if (ddspixels[i+0] + ddspixels[i+1] * 256 <= ddspixels[i+2] + ddspixels[i+3] * 256)
                                break;
                if (i < size)
-               {
                        textype = TEXTYPE_DXT1A;
-                       flags |= TEXF_ALPHA;
-               }
+               else
+                       flags &= ~TEXF_ALPHA;
        }
        else if (!memcmp(dds+84, "DXT3", 4))
        {
                textype = TEXTYPE_DXT3;
                bytesperblock = 16;
                bytesperpixel = 0;
-               size = ((dds_width+3)/4)*((dds_height+3)/4)*bytesperblock;
-               if(128 + size > ddsfilesize)
+               size = INTOVERFLOW_MUL(INTOVERFLOW_MUL(INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_width, 3), 4), INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_height, 3), 4)), bytesperblock);
+               if(INTOVERFLOW_ADD(128, size) > INTOVERFLOW_NORMALIZE(ddsfilesize))
                {
                        Mem_Free(dds);
-                       Con_Printf("^1%s: invalid DXT3 DDS image\n");
+                       Con_Printf("^1%s: invalid DXT3 DDS image\n", filename);
                        return NULL;
                }
-               flags |= TEXF_ALPHA;
        }
        else if (!memcmp(dds+84, "DXT5", 4))
        {
                textype = TEXTYPE_DXT5;
                bytesperblock = 16;
                bytesperpixel = 0;
-               size = ((dds_width+3)/4)*((dds_height+3)/4)*bytesperblock;
-               if(128 + size > ddsfilesize)
+               size = INTOVERFLOW_MUL(INTOVERFLOW_MUL(INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_width, 3), 4), INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_height, 3), 4)), bytesperblock);
+               if(INTOVERFLOW_ADD(128, size) > INTOVERFLOW_NORMALIZE(ddsfilesize))
                {
                        Mem_Free(dds);
-                       Con_Printf("^1%s: invalid DXT5 DDS image\n");
+                       Con_Printf("^1%s: invalid DXT5 DDS image\n", filename);
                        return NULL;
                }
-               flags |= TEXF_ALPHA;
        }
        else
        {