sRGB: also handle sRGB for loading DDS textures
authordivverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Thu, 20 Oct 2011 17:40:34 +0000 (17:40 +0000)
committerdivverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Thu, 20 Oct 2011 17:40:34 +0000 (17:40 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@11449 d7cf8633-e32d-0410-b094-e92efae38249

gl_draw.c
gl_rmain.c
gl_textures.c
r_textures.h

index 3ffbf43..44a83a9 100644 (file)
--- a/gl_draw.c
+++ b/gl_draw.c
@@ -392,7 +392,7 @@ reload:
        pic->lastusedframe = draw_frame;
 
        // load a high quality image from disk if possible
-       if (!loaded && r_texture_dds_load.integer != 0 && (pic->tex = R_LoadTextureDDSFile(drawtexturepool, va("dds/%s.dds", pic->name), pic->texflags, &ddshasalpha, ddsavgcolor, 0)))
+       if (!loaded && r_texture_dds_load.integer != 0 && (pic->tex = R_LoadTextureDDSFile(drawtexturepool, va("dds/%s.dds", pic->name), vid.sRGB2D, pic->texflags, &ddshasalpha, ddsavgcolor, 0)))
        {
                // note this loads even if autoload is true, otherwise we can't get the width/height
                loaded = true;
@@ -517,7 +517,7 @@ rtexture_t *Draw_GetPicTexture(cachepic_t *pic)
                {
                        qboolean ddshasalpha;
                        float ddsavgcolor[4];
-                       pic->tex = R_LoadTextureDDSFile(drawtexturepool, va("dds/%s.dds", pic->name), pic->texflags, &ddshasalpha, ddsavgcolor, 0);
+                       pic->tex = R_LoadTextureDDSFile(drawtexturepool, va("dds/%s.dds", pic->name), vid.sRGB2D, pic->texflags, &ddshasalpha, ddsavgcolor, 0);
                }
                if (pic->tex == NULL)
                {
index f5489cf..b61ea3f 100644 (file)
@@ -3302,7 +3302,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
        Image_StripImageExtension(name, basename, sizeof(basename));
 
        // check for DDS texture file first
-       if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
+       if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
        {
                basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
                if (basepixels == NULL)
@@ -3336,7 +3336,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
                skinframe->hasalpha = ddshasalpha;
                VectorCopy(ddsavgcolor, skinframe->avgcolor);
                if (r_loadfog && skinframe->hasalpha)
-                       skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
+                       skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
                //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
        }
        else
@@ -3383,13 +3383,13 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
        {
                mymiplevel = savemiplevel;
                if (r_loadnormalmap)
-                       skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
-               skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
+                       skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), false, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
+               skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
                if (r_loadgloss)
-                       skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
-               skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
-               skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
-               skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
+                       skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
+               skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
+               skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
+               skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
        }
 
        // _norm is the name used by tenebrae and has been adopted as standard
index 00a9c33..0c0b810 100644 (file)
@@ -2020,7 +2020,7 @@ int R_SaveTextureDDSFile(rtexture_t *rt, const char *filename, qboolean skipunco
 #endif
 }
 
-rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filename, int flags, qboolean *hasalphaflag, float *avgcolor, int miplevel) // DDS textures are opaque, so miplevel isn't a pointer but just seen as a hint
+rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filename, qboolean srgb, int flags, qboolean *hasalphaflag, float *avgcolor, int miplevel) // DDS textures are opaque, so miplevel isn't a pointer but just seen as a hint
 {
        int i, size, dds_format_flags, dds_miplevels, dds_width, dds_height;
        //int dds_flags;
@@ -2031,10 +2031,10 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen
        gltexturepool_t *pool = (gltexturepool_t *)rtexturepool;
        textypeinfo_t *texinfo;
        int mip, mipwidth, mipheight, mipsize, mipsize_total;
-       unsigned int c;
+       unsigned int c, r, g, b;
        GLint oldbindtexnum = 0;
-       const unsigned char *mippixels;
-       const unsigned char *mippixels_start;
+       unsigned char *mippixels;
+       unsigned char *mippixels_start;
        unsigned char *ddspixels;
        unsigned char *dds;
        fs_offset_t ddsfilesize;
@@ -2365,6 +2365,65 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen
                }
        }
 
+       // if we want sRGB, convert now
+       if(srgb)
+       {
+               if (vid.support.ext_texture_srgb)
+               {
+                       switch(textype)
+                       {
+                       case TEXTYPE_DXT1:    textype = TEXTYPE_SRGB_DXT1   ;break;
+                       case TEXTYPE_DXT1A:   textype = TEXTYPE_SRGB_DXT1A  ;break;
+                       case TEXTYPE_DXT3:    textype = TEXTYPE_SRGB_DXT3   ;break;
+                       case TEXTYPE_DXT5:    textype = TEXTYPE_SRGB_DXT5   ;break;
+                       case TEXTYPE_RGBA:    textype = TEXTYPE_SRGB_RGBA   ;break;
+                       default:
+                               break;
+                       }
+               }
+               else
+               {
+                       switch(textype)
+                       {
+                       case TEXTYPE_DXT1:
+                       case TEXTYPE_DXT1A:
+                       case TEXTYPE_DXT3:
+                       case TEXTYPE_DXT5:
+                               {
+                                       for (i = bytesperblock == 16 ? 8 : 0;i < mipsize;i += bytesperblock)
+                                       {
+                                               c = mippixels_start[i] + 256*mippixels_start[i+1];
+                                               r = ((c >> 11) & 0x1F);
+                                               g = ((c >>  5) & 0x3F);
+                                               b = ((c      ) & 0x1F);
+                                               r = floor(Image_LinearFloatFromsRGB(r * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
+                                               g = floor(Image_LinearFloatFromsRGB(g * (255.0f / 63.0f)) * 63.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
+                                               b = floor(Image_LinearFloatFromsRGB(b * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
+                                               c = (r << 11) | (g << 5) | b;
+                                               mippixels_start[i] = c & 255;
+                                               mippixels_start[i+1] = c >> 8;
+                                               c = mippixels_start[i+2] + 256*mippixels_start[i+3];
+                                               r = ((c >> 11) & 0x1F);
+                                               g = ((c >>  5) & 0x3F);
+                                               b = ((c      ) & 0x1F);
+                                               r = floor(Image_LinearFloatFromsRGB(r * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
+                                               g = floor(Image_LinearFloatFromsRGB(g * (255.0f / 63.0f)) * 63.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
+                                               b = floor(Image_LinearFloatFromsRGB(b * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
+                                               c = (r << 11) | (g << 5) | b;
+                                               mippixels_start[i+2] = c & 255;
+                                               mippixels_start[i+3] = c >> 8;
+                                       }
+                               }
+                               break;
+                       case TEXTYPE_RGBA:
+                               Image_MakeLinearColorsFromsRGB(mippixels, mippixels, mipsize_total / bytesperblock);
+                               break;
+                       default:
+                               break;
+                       }
+               }
+       }
+
        // when not requesting mipmaps, do not load them
        if(!(flags & TEXF_MIPMAP))
                dds_miplevels = 0;
index 82e3189..bc654a3 100644 (file)
@@ -155,7 +155,7 @@ rtexture_t *R_LoadTexture2D(rtexturepool_t *rtexturepool, const char *identifier
 rtexture_t *R_LoadTexture3D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int depth, const unsigned char *data, textype_t textype, int flags, int miplevel, const unsigned int *palette);
 rtexture_t *R_LoadTextureCubeMap(rtexturepool_t *rtexturepool, const char *identifier, int width, const unsigned char *data, textype_t textype, int flags, int miplevel, const unsigned int *palette);
 rtexture_t *R_LoadTextureShadowMap2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int precision, qboolean filter);
-rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filename, int flags, qboolean *hasalphaflag, float *avgcolor, int miplevel);
+rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filename, qboolean srgb, int flags, qboolean *hasalphaflag, float *avgcolor, int miplevel);
 
 // saves a texture to a DDS file
 int R_SaveTextureDDSFile(rtexture_t *rt, const char *filename, qboolean skipuncompressed, qboolean hasalpha);