implemented support for GL_EXT_texture_sRGB to preserve precision if
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sun, 10 Apr 2011 12:50:11 +0000 (12:50 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sun, 10 Apr 2011 12:50:11 +0000 (12:50 +0000)
supported (otherwise it just converts to linear and uses regular texture
formats)
renamed r_texture_convertsRGB_ cvars to r_texture_sRGB_ and broke out
the individual skin textures as separate cvars
added vid.forcetextype which allows particular renderpaths to force
desired texture component layouts (GL_RGBA for GLES, otherwise GL_BGRA)

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@11045 d7cf8633-e32d-0410-b094-e92efae38249

18 files changed:
cl_particles.c
gl_draw.c
gl_rmain.c
gl_textures.c
glquake.h
image.c
image.h
model_brush.c
model_sprite.c
r_lightning.c
r_shadow.c
r_sky.c
r_textures.h
render.h
vid.h
vid_sdl.c
vid_shared.c
vid_wgl.c

index 6efe27a..392b46b 100644 (file)
@@ -2140,7 +2140,7 @@ static void R_InitParticleTexture (void)
                Image_WriteTGABGRA ("particles/particlefont.tga", PARTICLEFONTSIZE, PARTICLEFONTSIZE, particletexturedata);
 #endif
 
-               decalskinframe = R_SkinFrame_LoadInternalBGRA("particlefont", TEXF_ALPHA | TEXF_FORCELINEAR | TEXF_RGBMULTIPLYBYALPHA, particletexturedata, PARTICLEFONTSIZE, PARTICLEFONTSIZE);
+               decalskinframe = R_SkinFrame_LoadInternalBGRA("particlefont", TEXF_ALPHA | TEXF_FORCELINEAR | TEXF_RGBMULTIPLYBYALPHA, particletexturedata, PARTICLEFONTSIZE, PARTICLEFONTSIZE, false);
                particlefonttexture = decalskinframe->base;
 
                Mem_Free(particletexturedata);
@@ -2159,7 +2159,7 @@ static void R_InitParticleTexture (void)
        }
 
 #ifndef DUMPPARTICLEFONT
-       particletexture[tex_beam].texture = loadtextureimage(particletexturepool, "particles/nexbeam.tga", false, TEXF_ALPHA | TEXF_FORCELINEAR | TEXF_RGBMULTIPLYBYALPHA, true, r_texture_convertsRGB_particles.integer != 0);
+       particletexture[tex_beam].texture = loadtextureimage(particletexturepool, "particles/nexbeam.tga", false, TEXF_ALPHA | TEXF_FORCELINEAR | TEXF_RGBMULTIPLYBYALPHA, true, r_texture_sRGB_skin_diffuse.integer != 0);
        if (!particletexture[tex_beam].texture)
 #endif
        {
index 50fcb81..5e76d3d 100644 (file)
--- a/gl_draw.c
+++ b/gl_draw.c
@@ -371,9 +371,9 @@ reload:
        pic->autoload = (cachepicflags & CACHEPICFLAG_NOTPERSISTENT);
 
        // load a high quality image from disk if possible
-       pixels = loadimagepixelsbgra(path, false, true, r_texture_convertsRGB_2d.integer != 0, NULL);
+       pixels = loadimagepixelsbgra(path, false, true, false, NULL);
        if (pixels == NULL && !strncmp(path, "gfx/", 4))
-               pixels = loadimagepixelsbgra(path+4, false, true, r_texture_convertsRGB_2d.integer != 0, NULL);
+               pixels = loadimagepixelsbgra(path+4, false, true, false, NULL);
        if (pixels)
        {
                pic->hasalpha = false;
@@ -392,7 +392,7 @@ reload:
                pic->width = image_width;
                pic->height = image_height;
                if (!pic->autoload)
-                       pic->tex = R_LoadTexture2D(drawtexturepool, path, image_width, image_height, pixels, TEXTYPE_BGRA, pic->texflags & (pic->hasalpha ? ~0 : ~TEXF_ALPHA), -1, NULL);
+                       pic->tex = R_LoadTexture2D(drawtexturepool, path, image_width, image_height, pixels, r_texture_sRGB_2d.integer ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, pic->texflags & (pic->hasalpha ? ~0 : ~TEXF_ALPHA), -1, NULL);
        }
        else
        {
@@ -472,9 +472,9 @@ rtexture_t *Draw_GetPicTexture(cachepic_t *pic)
 {
        if (pic->autoload && !pic->tex)
        {
-               pic->tex = loadtextureimage(drawtexturepool, pic->name, false, pic->texflags, true, r_texture_convertsRGB_2d.integer != 0);
+               pic->tex = loadtextureimage(drawtexturepool, pic->name, false, pic->texflags, true, r_texture_sRGB_2d.integer != 0);
                if (pic->tex == NULL && !strncmp(pic->name, "gfx/", 4))
-                       pic->tex = loadtextureimage(drawtexturepool, pic->name+4, false, pic->texflags, true, r_texture_convertsRGB_2d.integer != 0);
+                       pic->tex = loadtextureimage(drawtexturepool, pic->name+4, false, pic->texflags, true, r_texture_sRGB_2d.integer != 0);
                if (pic->tex == NULL)
                        pic->tex = draw_generatepic(pic->name, true);
        }
index 0d331be..870bfb6 100644 (file)
@@ -131,11 +131,13 @@ cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the re
 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
 
-cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
-cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
-cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
-cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
-cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
+cvar_t r_texture_sRGB_2d = {0, "r_texture_sRGB_2d", "0", "load textures as sRGB"};
+cvar_t r_texture_sRGB_skin_diffuse = {0, "r_texture_sRGB_skin_diffuse", "0", "load textures as sRGB"};
+cvar_t r_texture_sRGB_skin_gloss = {0, "r_texture_sRGB_skin_gloss", "0", "load textures as sRGB"};
+cvar_t r_texture_sRGB_skin_glow = {0, "r_texture_sRGB_skin_glow", "0", "load textures as sRGB"};
+cvar_t r_texture_sRGB_skin_reflect = {0, "r_texture_sRGB_skin_reflect", "0", "load textures as sRGB"};
+cvar_t r_texture_sRGB_cubemap = {0, "r_texture_sRGB_cubemap", "0", "load textures as sRGB"};
+cvar_t r_texture_sRGB_skybox = {0, "r_texture_sRGB_skybox", "0", "load textures as sRGB"};
 
 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
@@ -3168,7 +3170,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
        // check for DDS texture file first
        if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
        {
-               basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
+               basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
                if (basepixels == NULL)
                        return NULL;
        }
@@ -3206,7 +3208,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
        {
                basepixels_width = image_width;
                basepixels_height = image_height;
-               skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
+               skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, r_texture_sRGB_skin_diffuse.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
                if (textureflags & TEXF_ALPHA)
                {
                        for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
@@ -3285,18 +3287,18 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
        // _luma is supported only for tenebrae compatibility
        // _glow is the preferred name
        mymiplevel = savemiplevel;
-       if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel))))
+       if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
        {
-               skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
+               skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_glow.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
                if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
                        R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
                Mem_Free(pixels);pixels = NULL;
        }
 
        mymiplevel = savemiplevel;
-       if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
+       if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
        {
-               skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
+               skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_gloss.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
                if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
                        R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
                Mem_Free(pixels);
@@ -3304,9 +3306,9 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
        }
 
        mymiplevel = savemiplevel;
-       if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
+       if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
        {
-               skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
+               skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_diffuse.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
                if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
                        R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
                Mem_Free(pixels);
@@ -3314,9 +3316,9 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
        }
 
        mymiplevel = savemiplevel;
-       if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
+       if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
        {
-               skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
+               skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_diffuse.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
                if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
                        R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
                Mem_Free(pixels);
@@ -3324,9 +3326,9 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
        }
 
        mymiplevel = savemiplevel;
-       if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
+       if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
        {
-               skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
+               skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_reflect.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
                if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
                        R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
                Mem_Free(pixels);
@@ -3340,7 +3342,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
 }
 
 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
-skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
+skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
 {
        int i;
        unsigned char *temp1, *temp2;
@@ -3381,7 +3383,7 @@ skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, co
                skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
                Mem_Free(temp1);
        }
-       skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
+       skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
        if (textureflags & TEXF_ALPHA)
        {
                for (i = 3;i < width * height * 4;i += 4)
@@ -3668,7 +3670,7 @@ rtexture_t *R_LoadCubemap(const char *basename)
                        // generate an image name based on the base and and suffix
                        dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
                        // load it
-                       if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
+                       if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
                        {
                                // an image loaded, make sure width and height are equal
                                if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
@@ -3697,7 +3699,7 @@ rtexture_t *R_LoadCubemap(const char *basename)
                if (developer_loading.integer)
                        Con_Printf("loading cubemap \"%s\"\n", basename);
 
-               cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
+               cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, r_texture_sRGB_cubemap.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
                Mem_Free(cubemappixels);
        }
        else
@@ -4071,11 +4073,13 @@ void GL_Main_Init(void)
        Cvar_RegisterVariable(&r_transparentdepthmasking);
        Cvar_RegisterVariable(&r_texture_dds_load);
        Cvar_RegisterVariable(&r_texture_dds_save);
-       Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
-       Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
-       Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
-       Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
-       Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
+       Cvar_RegisterVariable(&r_texture_sRGB_2d);
+       Cvar_RegisterVariable(&r_texture_sRGB_skin_diffuse);
+       Cvar_RegisterVariable(&r_texture_sRGB_skin_gloss);
+       Cvar_RegisterVariable(&r_texture_sRGB_skin_glow);
+       Cvar_RegisterVariable(&r_texture_sRGB_skin_reflect);
+       Cvar_RegisterVariable(&r_texture_sRGB_cubemap);
+       Cvar_RegisterVariable(&r_texture_sRGB_skybox);
        Cvar_RegisterVariable(&r_textureunits);
        Cvar_RegisterVariable(&gl_combine);
        Cvar_RegisterVariable(&r_viewfbo);
index bb33548..f86ddc4 100644 (file)
@@ -74,28 +74,43 @@ typedef struct textypeinfo_s
 }
 textypeinfo_t;
 
-
-static textypeinfo_t textype_palette                = {TEXTYPE_PALETTE    , 1, 4, 4.0f, GL_RGB                          , GL_BGRA           , GL_UNSIGNED_BYTE };
-static textypeinfo_t textype_palette_alpha          = {TEXTYPE_PALETTE    , 1, 4, 4.0f, GL_RGBA                         , GL_BGRA           , GL_UNSIGNED_BYTE };
-static textypeinfo_t textype_rgba                   = {TEXTYPE_RGBA       , 4, 4, 4.0f, GL_RGB                          , GL_RGBA           , GL_UNSIGNED_BYTE };
-static textypeinfo_t textype_rgba_alpha             = {TEXTYPE_RGBA       , 4, 4, 4.0f, GL_RGBA                         , 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, GL_RGB                          , GL_BGRA           , GL_UNSIGNED_BYTE };
-static textypeinfo_t textype_bgra_alpha             = {TEXTYPE_BGRA       , 4, 4, 4.0f, GL_RGBA                         , 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, GL_RGBA                         , GL_BGRA           , GL_UNSIGNED_BYTE };
-static textypeinfo_t textype_colorbuffer16f         = {TEXTYPE_COLORBUFFER16F,8,8,8.0f, GL_RGBA16F_ARB                  , GL_RGBA           , GL_FLOAT         };
-static textypeinfo_t textype_colorbuffer32f         = {TEXTYPE_COLORBUFFER32F,16,16,16.0f,GL_RGBA32F_ARB                , GL_RGBA           , GL_FLOAT         };
-
+// framebuffer texture formats
+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_colorbuffer                 = {TEXTYPE_COLORBUFFER   ,  4,  4,  4.0f, GL_RGBA                               , GL_BGRA           , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_colorbuffer16f              = {TEXTYPE_COLORBUFFER16F,  8,  8,  8.0f, GL_RGBA16F_ARB                        , GL_RGBA           , GL_FLOAT         };
+static textypeinfo_t textype_colorbuffer32f              = {TEXTYPE_COLORBUFFER32F, 16, 16, 16.0f, GL_RGBA32F_ARB                        , GL_RGBA           , GL_FLOAT         };
+
+// image formats:
+static textypeinfo_t textype_alpha                       = {TEXTYPE_ALPHA         ,  1,  4,  4.0f, GL_ALPHA                              , GL_ALPHA          , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_palette                     = {TEXTYPE_PALETTE       ,  1,  4,  4.0f, GL_RGB                                , GL_BGRA           , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_palette_alpha               = {TEXTYPE_PALETTE       ,  1,  4,  4.0f, GL_RGBA                               , GL_BGRA           , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_rgba                        = {TEXTYPE_RGBA          ,  4,  4,  4.0f, GL_RGB                                , GL_RGBA           , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_rgba_alpha                  = {TEXTYPE_RGBA          ,  4,  4,  4.0f, GL_RGBA                               , 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, GL_RGB                                , GL_BGRA           , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_bgra_alpha                  = {TEXTYPE_BGRA          ,  4,  4,  4.0f, GL_RGBA                               , 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_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_sRGB_palette                = {TEXTYPE_PALETTE       ,  1,  4,  4.0f, GL_SRGB_EXT                           , GL_BGRA           , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_sRGB_palette_alpha          = {TEXTYPE_PALETTE       ,  1,  4,  4.0f, GL_SRGB_ALPHA_EXT                     , GL_BGRA           , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_sRGB_rgba                   = {TEXTYPE_RGBA          ,  4,  4,  4.0f, GL_SRGB_EXT                           , GL_RGBA           , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_sRGB_rgba_alpha             = {TEXTYPE_RGBA          ,  4,  4,  4.0f, GL_SRGB_ALPHA_EXT                     , GL_RGBA           , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_sRGB_rgba_compress          = {TEXTYPE_RGBA          ,  4,  4,  0.5f, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT      , GL_RGBA           , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_sRGB_rgba_alpha_compress    = {TEXTYPE_RGBA          ,  4,  4,  1.0f, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_RGBA           , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_sRGB_bgra                   = {TEXTYPE_BGRA          ,  4,  4,  4.0f, GL_SRGB_EXT                           , GL_BGRA           , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_sRGB_bgra_alpha             = {TEXTYPE_BGRA          ,  4,  4,  4.0f, GL_SRGB_ALPHA_EXT                     , GL_BGRA           , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_sRGB_bgra_compress          = {TEXTYPE_BGRA          ,  4,  4,  0.5f, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT      , GL_BGRA           , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_sRGB_bgra_alpha_compress    = {TEXTYPE_BGRA          ,  4,  4,  1.0f, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_BGRA           , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_sRGB_dxt1                   = {TEXTYPE_DXT1          ,  4,  0,  0.5f, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT      , 0                 , 0                };
+static textypeinfo_t textype_sRGB_dxt1a                  = {TEXTYPE_DXT1A         ,  4,  0,  0.5f, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 0                 , 0                };
+static textypeinfo_t textype_sRGB_dxt3                   = {TEXTYPE_DXT3          ,  4,  0,  1.0f, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0                 , 0                };
+static textypeinfo_t textype_sRGB_dxt5                   = {TEXTYPE_DXT5          ,  4,  0,  1.0f, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0                 , 0                };
 
 typedef enum gltexturetype_e
 {
@@ -214,34 +229,25 @@ static textypeinfo_t *R_GetTexTypeInfo(textype_t textype, int flags)
 {
        switch(textype)
        {
-       case TEXTYPE_DXT1:
-               return &textype_dxt1;
-       case TEXTYPE_DXT1A:
-               return &textype_dxt1a;
-       case TEXTYPE_DXT3:
-               return &textype_dxt3;
-       case TEXTYPE_DXT5:
-               return &textype_dxt5;
-       case TEXTYPE_PALETTE:
-               return (flags & TEXF_ALPHA) ? &textype_palette_alpha : &textype_palette;
-       case TEXTYPE_RGBA:
-               if ((flags & TEXF_COMPRESS) && gl_texturecompression.integer >= 1 && vid.support.ext_texture_compression_s3tc)
-                       return (flags & TEXF_ALPHA) ? &textype_rgba_alpha_compress : &textype_rgba_compress;
-               return (flags & TEXF_ALPHA) ? &textype_rgba_alpha : &textype_rgba;
-       case TEXTYPE_BGRA:
-               if ((flags & TEXF_COMPRESS) && gl_texturecompression.integer >= 1 && vid.support.ext_texture_compression_s3tc)
-                       return (flags & TEXF_ALPHA) ? &textype_bgra_alpha_compress : &textype_bgra_compress;
-               return (flags & TEXF_ALPHA) ? &textype_bgra_alpha : &textype_bgra;
-       case TEXTYPE_ALPHA:
-               return &textype_alpha;
-       case TEXTYPE_SHADOWMAP:
-               return (flags & TEXF_LOWPRECISION) ? &textype_shadowmap16 : &textype_shadowmap24;
-       case TEXTYPE_COLORBUFFER:
-               return &textype_colorbuffer;
-       case TEXTYPE_COLORBUFFER16F:
-               return &textype_colorbuffer16f;
-       case TEXTYPE_COLORBUFFER32F:
-               return &textype_colorbuffer32f;
+       case TEXTYPE_DXT1: return &textype_dxt1;
+       case TEXTYPE_DXT1A: return &textype_dxt1a;
+       case TEXTYPE_DXT3: return &textype_dxt3;
+       case TEXTYPE_DXT5: return &textype_dxt5;
+       case TEXTYPE_PALETTE: return (flags & TEXF_ALPHA) ? &textype_palette_alpha : &textype_palette;
+       case TEXTYPE_RGBA: return ((flags & TEXF_COMPRESS) && gl_texturecompression.integer >= 1 && vid.support.ext_texture_compression_s3tc) ? ((flags & TEXF_ALPHA) ? &textype_rgba_alpha_compress : &textype_rgba_compress) : ((flags & TEXF_ALPHA) ? &textype_rgba_alpha : &textype_rgba);
+       case TEXTYPE_BGRA: return ((flags & TEXF_COMPRESS) && gl_texturecompression.integer >= 1 && vid.support.ext_texture_compression_s3tc) ? ((flags & TEXF_ALPHA) ? &textype_bgra_alpha_compress : &textype_bgra_compress) : ((flags & TEXF_ALPHA) ? &textype_bgra_alpha : &textype_bgra);
+       case TEXTYPE_ALPHA: return &textype_alpha;
+       case TEXTYPE_SHADOWMAP: return (flags & TEXF_LOWPRECISION) ? &textype_shadowmap16 : &textype_shadowmap24;
+       case TEXTYPE_COLORBUFFER: return &textype_colorbuffer;
+       case TEXTYPE_COLORBUFFER16F: return &textype_colorbuffer16f;
+       case TEXTYPE_COLORBUFFER32F: return &textype_colorbuffer32f;
+       case TEXTYPE_SRGB_DXT1: return &textype_sRGB_dxt1;
+       case TEXTYPE_SRGB_DXT1A: return &textype_sRGB_dxt1a;
+       case TEXTYPE_SRGB_DXT3: return &textype_sRGB_dxt3;
+       case TEXTYPE_SRGB_DXT5: return &textype_sRGB_dxt5;
+       case TEXTYPE_SRGB_PALETTE: return (flags & TEXF_ALPHA) ? &textype_sRGB_palette_alpha : &textype_sRGB_palette;
+       case TEXTYPE_SRGB_RGBA: return ((flags & TEXF_COMPRESS) && gl_texturecompression.integer >= 1 && vid.support.ext_texture_compression_s3tc) ? ((flags & TEXF_ALPHA) ? &textype_sRGB_rgba_alpha_compress : &textype_sRGB_rgba_compress) : ((flags & TEXF_ALPHA) ? &textype_sRGB_rgba_alpha : &textype_sRGB_rgba);
+       case TEXTYPE_SRGB_BGRA: return ((flags & TEXF_COMPRESS) && gl_texturecompression.integer >= 1 && vid.support.ext_texture_compression_s3tc) ? ((flags & TEXF_ALPHA) ? &textype_sRGB_bgra_alpha_compress : &textype_sRGB_bgra_compress) : ((flags & TEXF_ALPHA) ? &textype_sRGB_bgra_alpha : &textype_sRGB_bgra);
        default:
                Host_Error("R_GetTexTypeInfo: unknown texture format");
                break;
@@ -1484,10 +1490,59 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *iden
        gltexturepool_t *pool = (gltexturepool_t *)rtexturepool;
        textypeinfo_t *texinfo, *texinfo2;
        unsigned char *temppixels = NULL;
+       qboolean swaprb;
 
        if (cls.state == ca_dedicated)
                return NULL;
 
+       // see if we need to swap red and blue (BGRA <-> RGBA conversion)
+       swaprb = false;
+       switch(textype)
+       {
+       case TEXTYPE_RGBA: if (vid.forcetextype == TEXTYPE_BGRA) {swaprb = true;textype = TEXTYPE_BGRA;} break;
+       case TEXTYPE_BGRA: if (vid.forcetextype == TEXTYPE_RGBA) {swaprb = true;textype = TEXTYPE_RGBA;} break;
+       case TEXTYPE_SRGB_RGBA: if (vid.forcetextype == TEXTYPE_BGRA) {swaprb = true;textype = TEXTYPE_SRGB_BGRA;} break;
+       case TEXTYPE_SRGB_BGRA: if (vid.forcetextype == TEXTYPE_RGBA) {swaprb = true;textype = TEXTYPE_SRGB_RGBA;} break;
+       default: break;
+       }
+       if (swaprb)
+       {
+               // swap bytes
+               static int rgbaswapindices[4] = {2, 1, 0, 3};
+               size = width * height * depth * sides * 4;
+               temppixels = (unsigned char *)Mem_Alloc(tempmempool, size);
+               Image_CopyMux(temppixels, data, width, height*depth*sides, false, false, false, 4, 4, rgbaswapindices);
+               data = temppixels;
+       }
+
+       // if sRGB texture formats are not supported, convert input to linear and upload as normal types
+       if (!vid.support.ext_texture_srgb)
+       {
+               qboolean convertsRGB = false;
+               switch(textype)
+               {
+               case TEXTYPE_SRGB_DXT1:    textype = TEXTYPE_DXT1   ;convertsRGB = true;break;
+               case TEXTYPE_SRGB_DXT1A:   textype = TEXTYPE_DXT1A  ;convertsRGB = true;break;
+               case TEXTYPE_SRGB_DXT3:    textype = TEXTYPE_DXT3   ;convertsRGB = true;break;
+               case TEXTYPE_SRGB_DXT5:    textype = TEXTYPE_DXT5   ;convertsRGB = true;break;
+               case TEXTYPE_SRGB_PALETTE: textype = TEXTYPE_PALETTE;convertsRGB = true;break;
+               case TEXTYPE_SRGB_RGBA:    textype = TEXTYPE_RGBA   ;convertsRGB = true;break;
+               case TEXTYPE_SRGB_BGRA:    textype = TEXTYPE_BGRA   ;convertsRGB = true;break;
+               default:
+                       break;
+               }
+               if (convertsRGB && data)
+               {
+                       size = width * height * depth * sides * 4;
+                       if (!temppixels)
+                       {
+                               temppixels = (unsigned char *)Mem_Alloc(tempmempool, size);
+                               memcpy(temppixels, data, size);
+                       }
+                       Image_MakeLinearColorsFromsRGB(temppixels, temppixels, width*height*depth*sides);
+               }
+       }
+
        if (texturetype == GLTEXTURETYPE_CUBEMAP && !vid.support.arb_texture_cube_map)
        {
                Con_Printf ("R_LoadTexture: cubemap texture not supported by driver\n");
@@ -1507,21 +1562,11 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *iden
                return NULL;
        }
 
-       if (textype == TEXTYPE_RGBA)
-       {
-               // swap bytes
-               static int rgbaswapindices[4] = {2, 1, 0, 3};
-               textype = TEXTYPE_BGRA;
-               texinfo = R_GetTexTypeInfo(textype, flags);
-               temppixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * depth * sides * 4);
-               Image_CopyMux(temppixels, data, width, height*depth*sides, false, false, false, 4, 4, rgbaswapindices);
-               data = temppixels;
-       }
-
        // clear the alpha flag if the texture has no transparent pixels
        switch(textype)
        {
        case TEXTYPE_PALETTE:
+       case TEXTYPE_SRGB_PALETTE:
                if (flags & TEXF_ALPHA)
                {
                        flags &= ~TEXF_ALPHA;
@@ -1540,6 +1585,8 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *iden
                break;
        case TEXTYPE_RGBA:
        case TEXTYPE_BGRA:
+       case TEXTYPE_SRGB_RGBA:
+       case TEXTYPE_SRGB_BGRA:
                if (flags & TEXF_ALPHA)
                {
                        flags &= ~TEXF_ALPHA;
@@ -1559,10 +1606,14 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *iden
        case TEXTYPE_SHADOWMAP:
                break;
        case TEXTYPE_DXT1:
+       case TEXTYPE_SRGB_DXT1:
                break;
        case TEXTYPE_DXT1A:
+       case TEXTYPE_SRGB_DXT1A:
        case TEXTYPE_DXT3:
+       case TEXTYPE_SRGB_DXT3:
        case TEXTYPE_DXT5:
+       case TEXTYPE_SRGB_DXT5:
                flags |= TEXF_ALPHA;
                break;
        case TEXTYPE_ALPHA:
index c5b1b52..120c453 100644 (file)
--- a/glquake.h
+++ b/glquake.h
@@ -614,6 +614,26 @@ extern void (GLAPIENTRY *qglDrawBuffersARB)(GLsizei n, const GLenum *bufs);
 #define GL_LUMINANCE_ALPHA16F_ARB                            0x881F
 #endif
 
+// GL_EXT_texture_sRGB
+#ifndef GL_SRGB_EXT
+#define GL_SRGB_EXT                                          0x8C40
+#define GL_SRGB8_EXT                                         0x8C41
+#define GL_SRGB_ALPHA_EXT                                    0x8C42
+#define GL_SRGB8_ALPHA8_EXT                                  0x8C43
+#define GL_SLUMINANCE_ALPHA_EXT                              0x8C44
+#define GL_SLUMINANCE8_ALPHA8_EXT                            0x8C45
+#define GL_SLUMINANCE_EXT                                    0x8C46
+#define GL_SLUMINANCE8_EXT                                   0x8C47
+#define GL_COMPRESSED_SRGB_EXT                               0x8C48
+#define GL_COMPRESSED_SRGB_ALPHA_EXT                         0x8C49
+#define GL_COMPRESSED_SLUMINANCE_EXT                         0x8C4A
+#define GL_COMPRESSED_SLUMINANCE_ALPHA_EXT                   0x8C4B
+#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT                     0x8C4C
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT               0x8C4D
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT               0x8C4E
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT               0x8C4F
+#endif
+
 extern void (GLAPIENTRY *qglScissor)(GLint x, GLint y, GLsizei width, GLsizei height);
 
 extern void (GLAPIENTRY *qglClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
diff --git a/image.c b/image.c
index bec68ec..e35dd33 100644 (file)
--- a/image.c
+++ b/image.c
@@ -1004,14 +1004,14 @@ unsigned char *loadimagepixelsbgra (const char *filename, qboolean complain, qbo
 }
 
 extern cvar_t gl_picmip;
-rtexture_t *loadtextureimage (rtexturepool_t *pool, const char *filename, qboolean complain, int flags, qboolean allowFixtrans, qboolean convertsRGB)
+rtexture_t *loadtextureimage (rtexturepool_t *pool, const char *filename, qboolean complain, int flags, qboolean allowFixtrans, qboolean sRGB)
 {
        unsigned char *data;
        rtexture_t *rt;
        int miplevel = R_PicmipForFlags(flags);
-       if (!(data = loadimagepixelsbgra (filename, complain, allowFixtrans, convertsRGB, &miplevel)))
+       if (!(data = loadimagepixelsbgra (filename, complain, allowFixtrans, false, &miplevel)))
                return 0;
-       rt = R_LoadTexture2D(pool, filename, image_width, image_height, data, TEXTYPE_BGRA, flags, miplevel, NULL);
+       rt = R_LoadTexture2D(pool, filename, image_width, image_height, data, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, flags, miplevel, NULL);
        Mem_Free(data);
        return rt;
 }
diff --git a/image.h b/image.h
index c553a97..10d190d 100644 (file)
--- a/image.h
+++ b/image.h
@@ -29,7 +29,7 @@ unsigned char *loadimagepixelsbgra (const char *filename, qboolean complain, qbo
 qboolean LoadPCX_QWSkin(const unsigned char *f, int filesize, unsigned char *pixels, int outwidth, int outheight);
 
 // loads a texture, as a texture
-rtexture_t *loadtextureimage (rtexturepool_t *pool, const char *filename, qboolean complain, int flags, qboolean allowFixtrans, qboolean convertsRGB);
+rtexture_t *loadtextureimage (rtexturepool_t *pool, const char *filename, qboolean complain, int flags, qboolean allowFixtrans, qboolean sRGB);
 
 // writes an upside down BGR image into a TGA
 qboolean Image_WriteTGABGR_preflipped (const char *filename, int width, int height, const unsigned char *data);
@@ -49,5 +49,7 @@ void Image_HeightmapToNormalmap_BGRA(const unsigned char *inpixels, unsigned cha
 void Image_FixTransparentPixels_f(void);
 extern cvar_t r_fixtrans_auto;
 
+void Image_MakeLinearColorsFromsRGB(unsigned char *pout, const unsigned char *pin, int numpixels);
+
 #endif
 
index a04e96c..e59393a 100644 (file)
@@ -1578,8 +1578,8 @@ void R_Q1BSP_LoadSplitSky (unsigned char *src, int width, int height, int bytesp
                }
        }
 
-       loadmodel->brush.solidskyskinframe = R_SkinFrame_LoadInternalBGRA("sky_solidtexture", 0         , (unsigned char *) solidpixels, w, h);
-       loadmodel->brush.alphaskyskinframe = R_SkinFrame_LoadInternalBGRA("sky_alphatexture", TEXF_ALPHA, (unsigned char *) alphapixels, w, h);
+       loadmodel->brush.solidskyskinframe = R_SkinFrame_LoadInternalBGRA("sky_solidtexture", 0         , (unsigned char *) solidpixels, w, h, bytesperpixel == 4 && r_texture_sRGB_skybox.integer);
+       loadmodel->brush.alphaskyskinframe = R_SkinFrame_LoadInternalBGRA("sky_alphatexture", TEXF_ALPHA, (unsigned char *) alphapixels, w, h, bytesperpixel == 4 && r_texture_sRGB_skybox.integer);
        Mem_Free(solidpixels);
        Mem_Free(alphapixels);
 }
@@ -1595,9 +1595,9 @@ static void Mod_Q1BSP_LoadTextures(lump_t *l)
        unsigned char *data, *mtdata;
        const char *s;
        char mapname[MAX_QPATH], name[MAX_QPATH];
-       unsigned char zero[4];
-
-       memset(zero, 0, sizeof(zero));
+       unsigned char zeroopaque[4], zerotrans[4];
+       Vector4Set(zeroopaque, 0, 0, 0, 255);
+       Vector4Set(zerotrans, 0, 0, 0, 128);
 
        loadmodel->data_textures = NULL;
 
@@ -1770,9 +1770,9 @@ static void Mod_Q1BSP_LoadTextures(lump_t *l)
                        // LordHavoc: HL sky textures are entirely different than quake
                        if (!loadmodel->brush.ishlbsp && !strncmp(tx->name, "sky", 3) && mtwidth == mtheight * 2)
                        {
-                               data = loadimagepixelsbgra(gamemode == GAME_TENEBRAE ? tx->name : va("textures/%s/%s", mapname, tx->name), false, false, r_texture_convertsRGB_skin.integer != 0, NULL);
+                               data = loadimagepixelsbgra(gamemode == GAME_TENEBRAE ? tx->name : va("textures/%s/%s", mapname, tx->name), false, false, r_texture_sRGB_skin_diffuse.integer != 0, NULL);
                                if (!data)
-                                       data = loadimagepixelsbgra(gamemode == GAME_TENEBRAE ? tx->name : va("textures/%s", tx->name), false, false, r_texture_convertsRGB_skin.integer != 0, NULL);
+                                       data = loadimagepixelsbgra(gamemode == GAME_TENEBRAE ? tx->name : va("textures/%s", tx->name), false, false, r_texture_sRGB_skin_diffuse.integer != 0, NULL);
                                if (data && image_width == image_height * 2)
                                {
                                        R_Q1BSP_LoadSplitSky(data, image_width, image_height, 4);
@@ -1802,7 +1802,7 @@ static void Mod_Q1BSP_LoadTextures(lump_t *l)
                                                {
                                                        tx->width = image_width;
                                                        tx->height = image_height;
-                                                       skinframe = R_SkinFrame_LoadInternalBGRA(tx->name, TEXF_ALPHA | TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP, pixels, image_width, image_height);
+                                                       skinframe = R_SkinFrame_LoadInternalBGRA(tx->name, TEXF_ALPHA | TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP, pixels, image_width, image_height, true);
                                                }
                                                if (freepixels)
                                                        Mem_Free(freepixels);
@@ -1822,8 +1822,7 @@ static void Mod_Q1BSP_LoadTextures(lump_t *l)
                                if (!strncmp(tx->name, "*glassmirror", 12)) // Tenebrae
                                {
                                        // replace the texture with transparent black
-                                       Vector4Set(zero, 128, 128, 128, 128);
-                                       tx->skinframes[0] = R_SkinFrame_LoadInternalBGRA(tx->name, TEXF_MIPMAP | TEXF_ALPHA, zero, 1, 1);
+                                       tx->skinframes[0] = R_SkinFrame_LoadInternalBGRA(tx->name, TEXF_MIPMAP | TEXF_ALPHA, zerotrans, 1, 1, false);
                                        tx->basematerialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_REFLECTION;
                                }
                                else if (!strncmp(tx->name,"*lava",5)
@@ -1838,7 +1837,7 @@ static void Mod_Q1BSP_LoadTextures(lump_t *l)
                        else if (!strncmp(tx->name, "mirror", 6)) // Tenebrae
                        {
                                // replace the texture with black
-                               tx->skinframes[0] = R_SkinFrame_LoadInternalBGRA(tx->name, 0, zero, 1, 1);
+                               tx->skinframes[0] = R_SkinFrame_LoadInternalBGRA(tx->name, 0, zeroopaque, 1, 1, false);
                                tx->basematerialflags |= MATERIALFLAG_REFLECTION;
                        }
                        else if (!strncmp(tx->name, "sky", 3))
index 7c80ef4..3588c61 100644 (file)
@@ -212,7 +212,7 @@ static void Mod_Sprite_SharedSetup(const unsigned char *datapointer, int version
                                                }
                                                else //if (version == SPRITEHL_VERSION || version == SPRITE_VERSION)
                                                        Image_Copy8bitBGRA(datapointer, pixels, width*height, palette ? palette : palette_bgra_transparent);
-                                               skinframe = R_SkinFrame_LoadInternalBGRA(name, texflags, pixels, width, height);
+                                               skinframe = R_SkinFrame_LoadInternalBGRA(name, texflags, pixels, width, height, false);
                                                Mem_Free(pixels);
                                        }
                                }
index af966a9..67d32ae 100644 (file)
@@ -144,7 +144,7 @@ void r_lightningbeams_setuptexture(void)
                }
        }
 
-       r_lightningbeamtexture = R_SkinFrame_LoadInternalBGRA("lightningbeam", TEXF_FORCELINEAR, data, BEAMWIDTH, BEAMHEIGHT);
+       r_lightningbeamtexture = R_SkinFrame_LoadInternalBGRA("lightningbeam", TEXF_FORCELINEAR, data, BEAMWIDTH, BEAMHEIGHT, false);
        Mem_Free(noise1);
        Mem_Free(noise2);
        Mem_Free(data);
index ed371f1..d479f12 100644 (file)
@@ -1762,7 +1762,7 @@ static void R_Shadow_MakeTextures_MakeCorona(void)
                        pixels[y][x][3] = 255;
                }
        }
-       r_shadow_lightcorona = R_SkinFrame_LoadInternalBGRA("lightcorona", TEXF_FORCELINEAR, &pixels[0][0][0], 32, 32);
+       r_shadow_lightcorona = R_SkinFrame_LoadInternalBGRA("lightcorona", TEXF_FORCELINEAR, &pixels[0][0][0], 32, 32, false);
 }
 
 static unsigned int R_Shadow_MakeTextures_SamplePoint(float x, float y, float z)
diff --git a/r_sky.c b/r_sky.c
index 4aa4d7f..eabb996 100644 (file)
--- a/r_sky.c
+++ b/r_sky.c
@@ -109,20 +109,20 @@ int R_LoadSkyBox(void)
                success = 0;
                for (i=0; i<6; i++)
                {
-                       if (dpsnprintf(name, sizeof(name), "%s_%s", skyname, suffix[j][i].suffix) < 0 || !(image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_skybox.integer != 0, NULL)))
+                       if (dpsnprintf(name, sizeof(name), "%s_%s", skyname, suffix[j][i].suffix) < 0 || !(image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
                        {
-                               if (dpsnprintf(name, sizeof(name), "%s%s", skyname, suffix[j][i].suffix) < 0 || !(image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_skybox.integer != 0, NULL)))
+                               if (dpsnprintf(name, sizeof(name), "%s%s", skyname, suffix[j][i].suffix) < 0 || !(image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
                                {
-                                       if (dpsnprintf(name, sizeof(name), "env/%s%s", skyname, suffix[j][i].suffix) < 0 || !(image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_skybox.integer != 0, NULL)))
+                                       if (dpsnprintf(name, sizeof(name), "env/%s%s", skyname, suffix[j][i].suffix) < 0 || !(image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
                                        {
-                                               if (dpsnprintf(name, sizeof(name), "gfx/env/%s%s", skyname, suffix[j][i].suffix) < 0 || !(image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_skybox.integer != 0, NULL)))
+                                               if (dpsnprintf(name, sizeof(name), "gfx/env/%s%s", skyname, suffix[j][i].suffix) < 0 || !(image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
                                                        continue;
                                        }
                                }
                        }
                        temp = (unsigned char *)Mem_Alloc(tempmempool, image_width*image_height*4);
                        Image_CopyMux (temp, image_buffer, image_width, image_height, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, indices);
-                       skyboxskinframe[i] = R_SkinFrame_LoadInternalBGRA(va("skyboxside%d", i), TEXF_CLAMP | (gl_texturecompression_sky.integer ? TEXF_COMPRESS : 0), temp, image_width, image_height);
+                       skyboxskinframe[i] = R_SkinFrame_LoadInternalBGRA(va("skyboxside%d", i), TEXF_CLAMP | (gl_texturecompression_sky.integer ? TEXF_COMPRESS : 0), temp, image_width, image_height, r_texture_sRGB_skybox.integer != 0);
                        Mem_Free(image_buffer);
                        Mem_Free(temp);
                        success++;
index b66201c..4265c5e 100644 (file)
@@ -43,8 +43,6 @@ typedef enum textype_e
        TEXTYPE_RGBA,
        // 32bit BGRA (preferred format due to faster uploads on most hardware)
        TEXTYPE_BGRA,
-       // 16bit D16 (16bit depth) or 32bit S8D24 (24bit depth, 8bit stencil unused)
-       TEXTYPE_SHADOWMAP,
        // 8bit ALPHA (used for freetype fonts)
        TEXTYPE_ALPHA,
        // 4x4 block compressed 15bit color (4 bits per pixel)
@@ -55,12 +53,30 @@ typedef enum textype_e
        TEXTYPE_DXT3,
        // 4x4 block compressed 15bit color plus 8bit alpha (8 bits per pixel)
        TEXTYPE_DXT5,
+
+       // 8bit paletted in sRGB colorspace
+       TEXTYPE_SRGB_PALETTE,
+       // 32bit RGBA in sRGB colorspace
+       TEXTYPE_SRGB_RGBA,
+       // 32bit BGRA (preferred format due to faster uploads on most hardware) in sRGB colorspace
+       TEXTYPE_SRGB_BGRA,
+       // 4x4 block compressed 15bit color (4 bits per pixel) in sRGB colorspace
+       TEXTYPE_SRGB_DXT1,
+       // 4x4 block compressed 15bit color plus 1bit alpha (4 bits per pixel) in sRGB colorspace
+       TEXTYPE_SRGB_DXT1A,
+       // 4x4 block compressed 15bit color plus 8bit alpha (8 bits per pixel) in sRGB colorspace
+       TEXTYPE_SRGB_DXT3,
+       // 4x4 block compressed 15bit color plus 8bit alpha (8 bits per pixel) in sRGB colorspace
+       TEXTYPE_SRGB_DXT5,
+
        // this represents the same format as the framebuffer, for fast copies
        TEXTYPE_COLORBUFFER,
        // this represents an RGBA half_float texture (4 16bit floats)
        TEXTYPE_COLORBUFFER16F,
        // this represents an RGBA float texture (4 32bit floats)
-       TEXTYPE_COLORBUFFER32F
+       TEXTYPE_COLORBUFFER32F,
+       // 16bit D16 (16bit depth) or 32bit S8D24 (24bit depth, 8bit stencil unused)
+       TEXTYPE_SHADOWMAP
 }
 textype_t;
 
index c1911e0..9cfd6f2 100644 (file)
--- a/render.h
+++ b/render.h
@@ -143,7 +143,7 @@ void R_SkinFrame_Purge(void);
 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name );
 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add);
 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain);
-skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height);
+skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB);
 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height);
 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette);
 skinframe_t *R_SkinFrame_LoadMissing(void);
@@ -199,11 +199,13 @@ extern cvar_t r_smoothnormals_areaweighting;
 
 extern cvar_t r_test;
 
-extern cvar_t r_texture_convertsRGB_2d;
-extern cvar_t r_texture_convertsRGB_skin;
-extern cvar_t r_texture_convertsRGB_cubemap;
-extern cvar_t r_texture_convertsRGB_skybox;
-extern cvar_t r_texture_convertsRGB_particles;
+extern cvar_t r_texture_sRGB_2d;
+extern cvar_t r_texture_sRGB_skin_diffuse;
+extern cvar_t r_texture_sRGB_skin_gloss;
+extern cvar_t r_texture_sRGB_skin_glow;
+extern cvar_t r_texture_sRGB_skin_reflect;
+extern cvar_t r_texture_sRGB_cubemap;
+extern cvar_t r_texture_sRGB_skybox;
 
 #include "gl_backend.h"
 
diff --git a/vid.h b/vid.h
index ebde4ff..ff691aa 100644 (file)
--- a/vid.h
+++ b/vid.h
@@ -67,6 +67,7 @@ typedef struct viddef_support_s
        qboolean ext_texture_compression_s3tc;
        qboolean ext_texture_edge_clamp;
        qboolean ext_texture_filter_anisotropic;
+       qboolean ext_texture_srgb;
 }
 viddef_support_t;
 
@@ -122,6 +123,8 @@ typedef struct viddef_s
        //  blit to the window)
        unsigned int *softpixels;
        unsigned int *softdepthpixels;
+
+       int forcetextype; // always use GL_BGRA for D3D, always use GL_RGBA for GLES, etc
 } viddef_t;
 
 // global video state
index ea18c92..5302620 100644 (file)
--- a/vid_sdl.c
+++ b/vid_sdl.c
@@ -1685,6 +1685,9 @@ void GLES_Init(void)
        
        // LordHavoc: report supported extensions
        Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
+
+       // GLES devices in general do not like GL_BGRA, so use GL_RGBA
+       vid.forcetextype = TEXTYPE_RGBA;
        
        vid.support.gl20shaders = true;
        vid.support.amd_texture_texture4 = false;
@@ -1709,6 +1712,7 @@ void GLES_Init(void)
        vid.support.ext_texture_compression_s3tc = false;
        vid.support.ext_texture_edge_clamp = true;
        vid.support.ext_texture_filter_anisotropic = false; // probably don't want to use it...
+       vid.support.ext_texture_srgb = false;
 
        qglGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint*)&vid.maxtexturesize_2d);
        if (vid.support.ext_texture_filter_anisotropic)
@@ -2516,8 +2520,11 @@ void VID_Finish (void)
                case RENDERPATH_SOFT:
                        DPSOFTRAST_Finish();
 #if SETVIDEOMODE
+               if (!r_test.integer)
+               {
                        SDL_BlitSurface(vid_softsurface, NULL, screen, NULL);
                        SDL_Flip(screen);
+               }
 #else
                        {
                                SDL_Surface *screen = SDL_GetWindowSurface(window);
index b2e2636..81f6fee 100644 (file)
@@ -92,7 +92,7 @@ cvar_t v_color_white_g = {CVAR_SAVE, "v_color_white_g", "1", "desired color of w
 cvar_t v_color_white_b = {CVAR_SAVE, "v_color_white_b", "1", "desired color of white"};
 cvar_t v_hwgamma = {CVAR_SAVE, "v_hwgamma", "1", "enables use of hardware gamma correction ramps if available (note: does not work very well on Windows2000 and above), values are 0 = off, 1 = attempt to use hardware gamma, 2 = use hardware gamma whether it works or not"};
 cvar_t v_glslgamma = {CVAR_SAVE, "v_glslgamma", "0", "enables use of GLSL to apply gamma correction ramps if available (note: overrides v_hwgamma)"};
-cvar_t v_psycho = {0, "v_psycho", "0", "easter egg (does not work on Windows2000 or above)"};
+cvar_t v_psycho = {0, "v_psycho", "0", "easter egg"};
 
 // brand of graphics chip
 const char *gl_vendor;
@@ -857,6 +857,9 @@ void VID_CheckExtensions(void)
        else
                Con_DPrintf("Using GLSL 1.00\n");
 
+       // GL drivers generally prefer GL_BGRA
+       vid.forcetextype = GL_BGRA;
+
        vid.support.amd_texture_texture4 = GL_CheckExtension("GL_AMD_texture_texture4", NULL, "-notexture4", false);
        vid.support.arb_depth_texture = GL_CheckExtension("GL_ARB_depth_texture", NULL, "-nodepthtexture", false);
        vid.support.arb_draw_buffers = GL_CheckExtension("GL_ARB_draw_buffers", drawbuffersfuncs, "-nodrawbuffers", false);
@@ -879,6 +882,7 @@ void VID_CheckExtensions(void)
        vid.support.ext_texture_compression_s3tc = GL_CheckExtension("GL_EXT_texture_compression_s3tc", NULL, "-nos3tc", false);
        vid.support.ext_texture_edge_clamp = GL_CheckExtension("GL_EXT_texture_edge_clamp", NULL, "-noedgeclamp", false) || GL_CheckExtension("GL_SGIS_texture_edge_clamp", NULL, "-noedgeclamp", false);
        vid.support.ext_texture_filter_anisotropic = GL_CheckExtension("GL_EXT_texture_filter_anisotropic", NULL, "-noanisotropy", false);
+       vid.support.ext_texture_srgb = GL_CheckExtension("GL_EXT_texture_sRGB", NULL, "-nosrgb", false);
 // COMMANDLINEOPTION: GL: -noshaders disables use of OpenGL 2.0 shaders (which allow pixel shader effects, can improve per pixel lighting performance and capabilities)
 // COMMANDLINEOPTION: GL: -noanisotropy disables GL_EXT_texture_filter_anisotropic (allows higher quality texturing)
 // COMMANDLINEOPTION: GL: -noblendminmax disables GL_EXT_blend_minmax
@@ -902,6 +906,7 @@ void VID_CheckExtensions(void)
 // COMMANDLINEOPTION: GL: -notexturegather disables GL_ARB_texture_gather (which provides fetch4 sampling)
 // COMMANDLINEOPTION: GL: -notexturenonpoweroftwo disables GL_ARB_texture_non_power_of_two (which saves video memory if it is supported, but crashes on some buggy drivers)
 // COMMANDLINEOPTION: GL: -novbo disables GL_ARB_vertex_buffer_object (which accelerates rendering)
+// COMMANDLINEOPTION: GL: -nosrgb disables GL_EXT_texture_sRGB (which is used for higher quality non-linear texture gamma)
 
        if (vid.support.arb_draw_buffers)
                qglGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, (GLint*)&vid.maxdrawbuffers);
@@ -1290,6 +1295,7 @@ int VID_Mode(int fullscreen, int width, int height, int bpp, float refreshrate,
                vid.stereobuffer   = vid.mode.stereobuffer;
                vid.samples        = vid.mode.samples;
                vid.stencil        = vid.mode.bitsperpixel > 16;
+
                Con_Printf("Video Mode: %s %dx%dx%dx%.2fhz%s%s\n", mode.fullscreen ? "fullscreen" : "window", mode.width, mode.height, mode.bitsperpixel, mode.refreshrate, mode.stereobuffer ? " stereo" : "", mode.samples > 1 ? va(" (%ix AA)", mode.samples) : "");
 
                Cvar_SetValueQuick(&vid_fullscreen, vid.mode.fullscreen);
@@ -1492,6 +1498,9 @@ void VID_Soft_SharedSetup(void)
        memset(&vid.support, 0, sizeof(vid.support));
        Cvar_SetQuick(&gl_info_extensions, "");
 
+       // DPSOFTRAST requires BGRA
+       vid.forcetextype = TEXTYPE_BGRA;
+
        vid.forcevbo = false;
        vid.support.arb_depth_texture = true;
        vid.support.arb_draw_buffers = true;
@@ -1508,6 +1517,7 @@ void VID_Soft_SharedSetup(void)
        //vid.support.ext_texture_compression_s3tc = true;
        vid.support.ext_texture_filter_anisotropic = true;
        vid.support.ati_separate_stencil = true;
+       vid.support.ext_texture_srgb = false;
 
        vid.maxtexturesize_2d = 16384;
        vid.maxtexturesize_3d = 512;
index acfece3..37b4a11 100644 (file)
--- a/vid_wgl.c
+++ b/vid_wgl.c
@@ -1569,6 +1569,9 @@ qboolean VID_InitModeDX(viddef_mode_t *mode, int version)
        memset(&vid.support, 0, sizeof(vid.support));
        Cvar_SetQuick(&gl_info_extensions, "");
 
+       // D3D9 requires BGRA
+       vid.forcetextype = TEXTYPE_BGRA;
+
        vid.forcevbo = false;
        vid.support.arb_depth_texture = true;
        vid.support.arb_draw_buffers = vid_d3d9caps.NumSimultaneousRTs > 1;
@@ -1585,6 +1588,7 @@ qboolean VID_InitModeDX(viddef_mode_t *mode, int version)
        vid.support.ext_texture_compression_s3tc = true;
        vid.support.ext_texture_filter_anisotropic = true;
        vid.support.ati_separate_stencil = (vid_d3d9caps.StencilCaps & D3DSTENCILCAPS_TWOSIDED) != 0;
+       vid.support.ext_texture_srgb = false; // FIXME use D3DSAMP_SRGBTEXTURE if CheckDeviceFormat agrees
 
        vid.maxtexturesize_2d = min(vid_d3d9caps.MaxTextureWidth, vid_d3d9caps.MaxTextureHeight);
        vid.maxtexturesize_3d = vid_d3d9caps.MaxVolumeExtent;