]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_textures.c
renamed r_shadow_shadows to r_shadow_dlightshadows and added r_shadow_worldshadows...
[xonotic/darkplaces.git] / gl_textures.c
index cab9f636b450bd135bb4be3df5b18eda327d8ffb..f3e8a1b24725f79354ef47fbb8096cea351b55e4 100644 (file)
@@ -8,6 +8,7 @@ cvar_t  r_max_scrapsize = {CVAR_SAVE, "r_max_scrapsize", "256"};
 cvar_t r_picmip = {CVAR_SAVE, "r_picmip", "0"};
 cvar_t r_lerpimages = {CVAR_SAVE, "r_lerpimages", "1"};
 cvar_t r_precachetextures = {CVAR_SAVE, "r_precachetextures", "1"};
+cvar_t  gl_texture_anisotropy = {CVAR_SAVE, "gl_texture_anisotropy", "0"};
 
 int            gl_filter_min = GL_LINEAR_MIPMAP_LINEAR;
 int            gl_filter_mag = GL_LINEAR;
@@ -38,11 +39,12 @@ typedef struct
 }
 textypeinfo_t;
 
-static textypeinfo_t textype_palette       = {TEXTYPE_PALETTE, 1, 4, GL_RGBA, 3};
-static textypeinfo_t textype_rgb           = {TEXTYPE_RGB    , 3, 3, GL_RGB , 3};
-static textypeinfo_t textype_rgba          = {TEXTYPE_RGBA   , 4, 4, GL_RGBA, 3};
-static textypeinfo_t textype_palette_alpha = {TEXTYPE_PALETTE, 1, 4, GL_RGBA, 4};
-static textypeinfo_t textype_rgba_alpha    = {TEXTYPE_RGBA   , 4, 4, GL_RGBA, 4};
+static textypeinfo_t textype_palette       = {TEXTYPE_PALETTE, 1, 4, GL_RGBA   , 3};
+static textypeinfo_t textype_rgb           = {TEXTYPE_RGB    , 3, 3, GL_RGB    , 3};
+static textypeinfo_t textype_rgba          = {TEXTYPE_RGBA   , 4, 4, GL_RGBA   , 3};
+static textypeinfo_t textype_palette_alpha = {TEXTYPE_PALETTE, 1, 4, GL_RGBA   , 4};
+static textypeinfo_t textype_rgba_alpha    = {TEXTYPE_RGBA   , 4, 4, GL_RGBA   , 4};
+static textypeinfo_t textype_dsdt          = {TEXTYPE_DSDT   , 2, 2, GL_DSDT_NV, GL_DSDT8_NV};
 
 // a tiling texture (most common type)
 #define GLIMAGETYPE_TILE 0
@@ -55,6 +57,7 @@ static textypeinfo_t textype_rgba_alpha    = {TEXTYPE_RGBA   , 4, 4, GL_RGBA, 4}
 #define GLTEXTURETYPE_CUBEMAP 3
 
 static int gltexturetypeenums[4] = {GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP_ARB};
+static int gltexturetypebindingenums[4] = {GL_TEXTURE_BINDING_1D, GL_TEXTURE_BINDING_2D, GL_TEXTURE_BINDING_3D, GL_TEXTURE_BINDING_CUBE_MAP_ARB};
 static int gltexturetypedimensions[4] = {1, 2, 3, 2};
 static int cubemapside[6] =
 {
@@ -165,6 +168,8 @@ static textypeinfo_t *R_GetTexTypeInfo(int textype, int flags)
                        return &textype_rgb;
                case TEXTYPE_RGBA:
                        return &textype_rgba;
+               case TEXTYPE_DSDT:
+                       return &textype_dsdt;
                default:
                        Host_Error("R_GetTexTypeInfo: unknown texture format\n");
                        return NULL;
@@ -320,11 +325,10 @@ static glmode_t modes[] =
        {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
 };
 
-extern int gl_backend_rebindtextures;
-
 static void GL_TextureMode_f (void)
 {
        int i;
+       GLint oldbindtexnum;
        gltextureimage_t *image;
        gltexturepool_t *pool;
 
@@ -361,18 +365,19 @@ static void GL_TextureMode_f (void)
                for (image = pool->imagechain;image;image = image->imagechain)
                {
                        // only update already uploaded images
-                       if (!(image->flags & GLTEXF_UPLOAD))
+                       if (!(image->flags & GLTEXF_UPLOAD) && !(image->flags & (TEXF_FORCENEAREST | TEXF_FORCELINEAR)))
                        {
-                               qglBindTexture(GL_TEXTURE_2D, image->texnum);
+                               qglGetIntegerv(gltexturetypebindingenums[image->texturetype], &oldbindtexnum);
+                               qglBindTexture(gltexturetypeenums[image->texturetype], image->texnum);
                                if (image->flags & TEXF_MIPMAP)
-                                       qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
+                                       qglTexParameteri(gltexturetypeenums[image->texturetype], GL_TEXTURE_MIN_FILTER, gl_filter_min);
                                else
-                                       qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_mag);
-                               qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_mag);
+                                       qglTexParameteri(gltexturetypeenums[image->texturetype], GL_TEXTURE_MIN_FILTER, gl_filter_mag);
+                               qglTexParameteri(gltexturetypeenums[image->texturetype], GL_TEXTURE_MAG_FILTER, gl_filter_mag);
+                               qglBindTexture(gltexturetypeenums[image->texturetype], oldbindtexnum);
                        }
                }
        }
-       gl_backend_rebindtextures = true;
 }
 
 static int R_CalcTexelDataSize (gltexture_t *glt)
@@ -478,7 +483,9 @@ static void r_textures_start(void)
        texturedatamempool = Mem_AllocPool("Texture Storage (not yet uploaded)");
        textureprocessingmempool = Mem_AllocPool("Texture Processing Buffers");
 
-       JPEG_OpenLibrary ();
+       // Disable JPEG screenshots if the DLL isn't loaded
+       if (! JPEG_OpenLibrary ())
+               Cvar_SetValueQuick (&scr_screenshot_jpeg, 0);
 }
 
 static void r_textures_shutdown(void)
@@ -516,6 +523,7 @@ void R_Textures_Init (void)
        Cvar_RegisterVariable (&r_picmip);
        Cvar_RegisterVariable (&r_lerpimages);
        Cvar_RegisterVariable (&r_precachetextures);
+       Cvar_RegisterVariable (&gl_texture_anisotropy);
 
        R_RegisterModule("R_Textures", r_textures_start, r_textures_shutdown, r_textures_newmap);
 }
@@ -562,6 +570,8 @@ static void GL_SetupTextureParameters(int flags, int texturetype)
 
        CHECKGLERROR
 
+       if (gl_support_anisotropy)
+               qglTexParameterf(textureenum, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_anisotropy.value);
        qglTexParameteri(textureenum, GL_TEXTURE_WRAP_S, wrapmode);
        qglTexParameteri(textureenum, GL_TEXTURE_WRAP_T, wrapmode);
        if (gltexturetypedimensions[texturetype] >= 3)
@@ -602,17 +612,19 @@ static void GL_SetupTextureParameters(int flags, int texturetype)
 
 static void R_Upload(gltexture_t *glt, qbyte *data)
 {
-       int i, mip, width, height, depth, internalformat;
+       int i, mip, width, height, depth;
+       GLint oldbindtexnum;
        qbyte *prevbuffer;
        prevbuffer = data;
 
        CHECKGLERROR
 
        glt->texnum = glt->image->texnum;
+       // we need to restore the texture binding after finishing the upload
+       qglGetIntegerv(gltexturetypebindingenums[glt->image->texturetype], &oldbindtexnum);
        qglBindTexture(gltexturetypeenums[glt->image->texturetype], glt->image->texnum);
        CHECKGLERROR
        glt->flags &= ~GLTEXF_UPLOAD;
-       gl_backend_rebindtextures = true;
 
        if (glt->flags & TEXF_FRAGMENT)
        {
@@ -676,124 +688,85 @@ static void R_Upload(gltexture_t *glt, qbyte *data)
                        Host_Error("R_Upload: fragment texture of type other than 1D, 2D, or 3D\n");
                        break;
                }
-               glt->texnum = glt->image->texnum;
-               return;
-       }
-
-       glt->image->flags &= ~GLTEXF_UPLOAD;
-
-       // these are rounded up versions of the size to do better resampling
-       for (width  = 1;width  < glt->width ;width  <<= 1);
-       for (height = 1;height < glt->height;height <<= 1);
-       for (depth  = 1;depth  < glt->depth ;depth  <<= 1);
-
-       R_MakeResizeBufferBigger(width * height * depth * glt->image->sides * glt->image->bytesperpixel);
-
-       if (prevbuffer == NULL)
-       {
-               width = glt->image->width;
-               height = glt->image->height;
-               depth = glt->image->depth;
-               memset(resizebuffer, 255, width * height * depth * glt->image->bytesperpixel);
-               prevbuffer = resizebuffer;
        }
        else
        {
-               if (glt->textype->textype == TEXTYPE_PALETTE)
-               {
-                       // promote paletted to RGBA, so we only have to worry about RGB and
-                       // RGBA in the rest of this code
-                       Image_Copy8bitRGBA(prevbuffer, colorconvertbuffer, glt->width * glt->height * glt->depth * glt->image->sides, glt->palette);
-                       prevbuffer = colorconvertbuffer;
-               }
-       }
+               glt->image->flags &= ~GLTEXF_UPLOAD;
 
-       // 3 and 4 are converted by the driver to it's preferred format for the current display mode
-       internalformat = 3;
-       if (glt->flags & TEXF_ALPHA)
-               internalformat = 4;
+               // these are rounded up versions of the size to do better resampling
+               for (width  = 1;width  < glt->width ;width  <<= 1);
+               for (height = 1;height < glt->height;height <<= 1);
+               for (depth  = 1;depth  < glt->depth ;depth  <<= 1);
 
-       // cubemaps contain multiple images and thus get processed a bit differently
-       if (glt->image->texturetype != GLTEXTURETYPE_CUBEMAP)
-       {
-               if (glt->width != width || glt->height != height || glt->depth != depth)
-               {
-                       Image_Resample(prevbuffer, glt->width, glt->height, glt->depth, resizebuffer, width, height, depth, glt->image->bytesperpixel, r_lerpimages.integer);
-                       prevbuffer = resizebuffer;
-               }
-               // picmip/max_size
-               while (width > glt->image->width || height > glt->image->height || depth > glt->image->depth)
+               R_MakeResizeBufferBigger(width * height * depth * glt->image->sides * glt->image->bytesperpixel);
+
+               if (prevbuffer == NULL)
                {
-                       Image_MipReduce(prevbuffer, resizebuffer, &width, &height, &depth, glt->image->width, glt->image->height, glt->image->depth, glt->image->bytesperpixel);
+                       width = glt->image->width;
+                       height = glt->image->height;
+                       depth = glt->image->depth;
+                       memset(resizebuffer, 255, width * height * depth * glt->image->bytesperpixel);
                        prevbuffer = resizebuffer;
                }
-       }
-       mip = 0;
-       switch(glt->image->texturetype)
-       {
-       case GLTEXTURETYPE_1D:
-               qglTexImage1D(GL_TEXTURE_1D, mip++, internalformat, width, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
-               CHECKGLERROR
-               if (glt->flags & TEXF_MIPMAP)
+               else
                {
-                       while (width > 1 || height > 1 || depth > 1)
+                       if (glt->textype->textype == TEXTYPE_PALETTE)
                        {
-                               Image_MipReduce(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1, glt->image->bytesperpixel);
-                               prevbuffer = resizebuffer;
-                               qglTexImage1D(GL_TEXTURE_1D, mip++, internalformat, width, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
-                               CHECKGLERROR
+                               // promote paletted to RGBA, so we only have to worry about RGB and
+                               // RGBA in the rest of this code
+                               Image_Copy8bitRGBA(prevbuffer, colorconvertbuffer, glt->width * glt->height * glt->depth * glt->image->sides, glt->palette);
+                               prevbuffer = colorconvertbuffer;
                        }
                }
-               break;
-       case GLTEXTURETYPE_2D:
-               qglTexImage2D(GL_TEXTURE_2D, mip++, internalformat, width, height, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
-               CHECKGLERROR
-               if (glt->flags & TEXF_MIPMAP)
+
+               // cubemaps contain multiple images and thus get processed a bit differently
+               if (glt->image->texturetype != GLTEXTURETYPE_CUBEMAP)
                {
-                       while (width > 1 || height > 1 || depth > 1)
+                       if (glt->width != width || glt->height != height || glt->depth != depth)
                        {
-                               Image_MipReduce(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1, glt->image->bytesperpixel);
+                               Image_Resample(prevbuffer, glt->width, glt->height, glt->depth, resizebuffer, width, height, depth, glt->image->bytesperpixel, r_lerpimages.integer);
                                prevbuffer = resizebuffer;
-                               qglTexImage2D(GL_TEXTURE_2D, mip++, internalformat, width, height, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
-                               CHECKGLERROR
                        }
-               }
-               break;
-       case GLTEXTURETYPE_3D:
-               qglTexImage3D(GL_TEXTURE_3D, mip++, internalformat, width, height, depth, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
-               CHECKGLERROR
-               if (glt->flags & TEXF_MIPMAP)
-               {
-                       while (width > 1 || height > 1 || depth > 1)
+                       // picmip/max_size
+                       while (width > glt->image->width || height > glt->image->height || depth > glt->image->depth)
                        {
-                               Image_MipReduce(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1, glt->image->bytesperpixel);
+                               Image_MipReduce(prevbuffer, resizebuffer, &width, &height, &depth, glt->image->width, glt->image->height, glt->image->depth, glt->image->bytesperpixel);
                                prevbuffer = resizebuffer;
-                               qglTexImage3D(GL_TEXTURE_3D, mip++, internalformat, width, height, depth, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
-                               CHECKGLERROR
                        }
                }
-               break;
-       case GLTEXTURETYPE_CUBEMAP:
-               // convert and upload each side in turn,
-               // from a continuous block of input texels
-               texturebuffer = prevbuffer;
-               for (i = 0;i < 6;i++)
+               mip = 0;
+               switch(glt->image->texturetype)
                {
-                       prevbuffer = texturebuffer;
-                       texturebuffer += width * height * depth * glt->textype->inputbytesperpixel;
-                       if (glt->width != width || glt->height != height || glt->depth != depth)
+               case GLTEXTURETYPE_1D:
+                       qglTexImage1D(GL_TEXTURE_1D, mip++, glt->image->glinternalformat, width, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
+                       CHECKGLERROR
+                       if (glt->flags & TEXF_MIPMAP)
                        {
-                               Image_Resample(prevbuffer, glt->width, glt->height, glt->depth, resizebuffer, width, height, depth, glt->image->bytesperpixel, r_lerpimages.integer);
-                               prevbuffer = resizebuffer;
+                               while (width > 1 || height > 1 || depth > 1)
+                               {
+                                       Image_MipReduce(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1, glt->image->bytesperpixel);
+                                       prevbuffer = resizebuffer;
+                                       qglTexImage1D(GL_TEXTURE_1D, mip++, glt->image->glinternalformat, width, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
+                                       CHECKGLERROR
+                               }
                        }
-                       // picmip/max_size
-                       while (width > glt->image->width || height > glt->image->height || depth > glt->image->depth)
+                       break;
+               case GLTEXTURETYPE_2D:
+                       qglTexImage2D(GL_TEXTURE_2D, mip++, glt->image->glinternalformat, width, height, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
+                       CHECKGLERROR
+                       if (glt->flags & TEXF_MIPMAP)
                        {
-                               Image_MipReduce(prevbuffer, resizebuffer, &width, &height, &depth, glt->image->width, glt->image->height, glt->image->depth, glt->image->bytesperpixel);
-                               prevbuffer = resizebuffer;
+                               while (width > 1 || height > 1 || depth > 1)
+                               {
+                                       Image_MipReduce(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1, glt->image->bytesperpixel);
+                                       prevbuffer = resizebuffer;
+                                       qglTexImage2D(GL_TEXTURE_2D, mip++, glt->image->glinternalformat, width, height, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
+                                       CHECKGLERROR
+                               }
                        }
-                       mip = 0;
-                       qglTexImage2D(cubemapside[i], mip++, internalformat, width, height, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
+                       break;
+               case GLTEXTURETYPE_3D:
+                       qglTexImage3D(GL_TEXTURE_3D, mip++, glt->image->glinternalformat, width, height, depth, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
                        CHECKGLERROR
                        if (glt->flags & TEXF_MIPMAP)
                        {
@@ -801,14 +774,49 @@ static void R_Upload(gltexture_t *glt, qbyte *data)
                                {
                                        Image_MipReduce(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1, glt->image->bytesperpixel);
                                        prevbuffer = resizebuffer;
-                                       qglTexImage2D(cubemapside[i], mip++, internalformat, width, height, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
+                                       qglTexImage3D(GL_TEXTURE_3D, mip++, glt->image->glinternalformat, width, height, depth, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
                                        CHECKGLERROR
                                }
                        }
+                       break;
+               case GLTEXTURETYPE_CUBEMAP:
+                       // convert and upload each side in turn,
+                       // from a continuous block of input texels
+                       texturebuffer = prevbuffer;
+                       for (i = 0;i < 6;i++)
+                       {
+                               prevbuffer = texturebuffer;
+                               texturebuffer += width * height * depth * glt->textype->inputbytesperpixel;
+                               if (glt->width != width || glt->height != height || glt->depth != depth)
+                               {
+                                       Image_Resample(prevbuffer, glt->width, glt->height, glt->depth, resizebuffer, width, height, depth, glt->image->bytesperpixel, r_lerpimages.integer);
+                                       prevbuffer = resizebuffer;
+                               }
+                               // picmip/max_size
+                               while (width > glt->image->width || height > glt->image->height || depth > glt->image->depth)
+                               {
+                                       Image_MipReduce(prevbuffer, resizebuffer, &width, &height, &depth, glt->image->width, glt->image->height, glt->image->depth, glt->image->bytesperpixel);
+                                       prevbuffer = resizebuffer;
+                               }
+                               mip = 0;
+                               qglTexImage2D(cubemapside[i], mip++, glt->image->glinternalformat, width, height, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
+                               CHECKGLERROR
+                               if (glt->flags & TEXF_MIPMAP)
+                               {
+                                       while (width > 1 || height > 1 || depth > 1)
+                                       {
+                                               Image_MipReduce(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1, glt->image->bytesperpixel);
+                                               prevbuffer = resizebuffer;
+                                               qglTexImage2D(cubemapside[i], mip++, glt->image->glinternalformat, width, height, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
+                                               CHECKGLERROR
+                                       }
+                               }
+                       }
+                       break;
                }
-               break;
+               GL_SetupTextureParameters(glt->image->flags, glt->image->texturetype);
        }
-       GL_SetupTextureParameters(glt->image->flags, glt->image->texturetype);
+       qglBindTexture(gltexturetypeenums[glt->image->texturetype], oldbindtexnum);
 }
 
 static void R_FindImageForTexture(gltexture_t *glt)
@@ -1027,6 +1035,8 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *iden
                        }
                }
                break;
+       case TEXTYPE_DSDT:
+               break;
        default:
                Host_Error("R_LoadTexture: unknown texture type\n");
        }