]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_textures.c
changed R_Mesh_TexCombine to use GL_COMBINE_ARB mode only when necessary
[xonotic/darkplaces.git] / gl_textures.c
index 0a3f2cb16a04199fbd1bd0fb967ab930e9dbf053..d437365066727fe33c8c782be852096afe256507 100644 (file)
@@ -60,12 +60,11 @@ static textypeinfo_t textype_bgra                   = {TEXTYPE_BGRA   , 4, 4, 4.
 static textypeinfo_t textype_bgra_alpha             = {TEXTYPE_BGRA   , 4, 4, 4.0f, GL_BGRA   , 4, GL_UNSIGNED_BYTE};
 static textypeinfo_t textype_bgra_compress          = {TEXTYPE_BGRA   , 4, 4, 0.5f, GL_BGRA   , GL_COMPRESSED_RGB_ARB, GL_UNSIGNED_BYTE};
 static textypeinfo_t textype_bgra_alpha_compress    = {TEXTYPE_BGRA   , 4, 4, 1.0f, GL_BGRA   , GL_COMPRESSED_RGBA_ARB, GL_UNSIGNED_BYTE};
-static textypeinfo_t textype_shadowmap              = {TEXTYPE_SHADOWMAP,4,4, 4.0f, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT24_ARB, GL_UNSIGNED_INT};
-static textypeinfo_t textype_projection             = {TEXTYPE_PROJECTION,4,4,4.0f, GL_LUMINANCE_ALPHA, GL_LUMINANCE16_ALPHA16, GL_UNSIGNED_SHORT};
+static textypeinfo_t textype_shadowmap16            = {TEXTYPE_SHADOWMAP,2,2, 2.0f, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT16_ARB, GL_UNSIGNED_SHORT};
+static textypeinfo_t textype_shadowmap24            = {TEXTYPE_SHADOWMAP,4,4, 4.0f, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT24_ARB, GL_UNSIGNED_INT};
 
 typedef enum gltexturetype_e
 {
-       GLTEXTURETYPE_1D,
        GLTEXTURETYPE_2D,
        GLTEXTURETYPE_3D,
        GLTEXTURETYPE_CUBEMAP,
@@ -74,9 +73,9 @@ typedef enum gltexturetype_e
 }
 gltexturetype_t;
 
-static int gltexturetypeenums[GLTEXTURETYPE_TOTAL] = {GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_RECTANGLE_ARB};
-static int gltexturetypebindingenums[GLTEXTURETYPE_TOTAL] = {GL_TEXTURE_BINDING_1D, GL_TEXTURE_BINDING_2D, GL_TEXTURE_BINDING_3D, GL_TEXTURE_BINDING_CUBE_MAP_ARB, GL_TEXTURE_BINDING_RECTANGLE_ARB};
-static int gltexturetypedimensions[GLTEXTURETYPE_TOTAL] = {1, 2, 3, 2, 2};
+static int gltexturetypeenums[GLTEXTURETYPE_TOTAL] = {GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_RECTANGLE_ARB};
+static int gltexturetypebindingenums[GLTEXTURETYPE_TOTAL] = {GL_TEXTURE_BINDING_2D, GL_TEXTURE_BINDING_3D, GL_TEXTURE_BINDING_CUBE_MAP_ARB, GL_TEXTURE_BINDING_RECTANGLE_ARB};
+static int gltexturetypedimensions[GLTEXTURETYPE_TOTAL] = {2, 3, 2, 2};
 static int cubemapside[6] =
 {
        GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
@@ -123,7 +122,7 @@ typedef struct gltexture_s
        // palette if the texture is TEXTYPE_PALETTE
        const unsigned int *palette;
        // actual stored texture size after gl_picmip and gl_max_size are applied
-       // (power of 2 if gl_support_arb_texture_non_power_of_two is not supported)
+       // (power of 2 if vid.support.arb_texture_non_power_of_two is not supported)
        int tilewidth, tileheight, tiledepth;
        // 1 or 6 depending on texturetype
        int sides;
@@ -157,7 +156,7 @@ static int texturebuffersize = 0;
 
 static textypeinfo_t *R_GetTexTypeInfo(textype_t textype, int flags)
 {
-       if ((flags & TEXF_COMPRESS) && gl_texturecompression.integer >= 1 && gl_support_texture_compression)
+       if ((flags & TEXF_COMPRESS) && gl_texturecompression.integer >= 1 && vid.support.arb_texture_compression)
        {
                if (flags & TEXF_ALPHA)
                {
@@ -218,9 +217,7 @@ static textypeinfo_t *R_GetTexTypeInfo(textype_t textype, int flags)
                        case TEXTYPE_BGRA:
                                return &textype_bgra;
                        case TEXTYPE_SHADOWMAP:
-                               return &textype_shadowmap;
-                       case TEXTYPE_PROJECTION:
-                               return &textype_projection;
+                               return (flags & TEXF_LOWPRECISION) ? &textype_shadowmap16 : &textype_shadowmap24;
                        default:
                                Host_Error("R_GetTexTypeInfo: unknown texture format");
                                return NULL;
@@ -267,41 +264,6 @@ static void R_UpdateDynamicTexture(gltexture_t *glt) {
        }
 }
 
-static void R_UploadTexture(gltexture_t *t);
-
-static void R_PrecacheTexture(gltexture_t *glt)
-{
-       int precache;
-       precache = false;
-       if (glt->flags & TEXF_ALWAYSPRECACHE)
-               precache = true;
-       else if (r_precachetextures.integer >= 2)
-               precache = true;
-       else if (r_precachetextures.integer >= 1)
-               if (glt->flags & TEXF_PRECACHE)
-                       precache = true;
-
-       if (precache)
-               R_UploadTexture(glt);
-}
-
-int R_RealGetTexture(rtexture_t *rt)
-{
-       if (rt)
-       {
-               gltexture_t *glt;
-               glt = (gltexture_t *)rt;
-               if (glt->flags & GLTEXF_DYNAMIC)
-                       R_UpdateDynamicTexture(glt);
-               if (glt->flags & GLTEXF_UPLOAD)
-                       R_UploadTexture(glt);
-
-               return glt->texnum;
-       }
-       else
-               return 0;
-}
-
 void R_PurgeTexture(rtexture_t *rt)
 {
        if(rt && !(((gltexture_t*) rt)->flags & TEXF_PERSISTENT)) {
@@ -451,21 +413,20 @@ static void GL_Texture_CalcImageSize(int texturetype, int flags, int inwidth, in
 {
        int picmip = 0, maxsize = 0, width2 = 1, height2 = 1, depth2 = 1;
 
-       if (gl_max_size.integer > gl_max_texture_size)
-               Cvar_SetValue("gl_max_size", gl_max_texture_size);
+       if (gl_max_size.integer > (int)vid.maxtexturesize_2d)
+               Cvar_SetValue("gl_max_size", vid.maxtexturesize_2d);
 
        switch (texturetype)
        {
        default:
-       case GLTEXTURETYPE_1D:
        case GLTEXTURETYPE_2D:
-               maxsize = gl_max_texture_size;
+               maxsize = vid.maxtexturesize_2d;
                break;
        case GLTEXTURETYPE_3D:
-               maxsize = gl_max_3d_texture_size;
+               maxsize = vid.maxtexturesize_3d;
                break;
        case GLTEXTURETYPE_CUBEMAP:
-               maxsize = gl_max_cube_map_texture_size;
+               maxsize = vid.maxtexturesize_cubemap;
                break;
        }
 
@@ -477,7 +438,7 @@ static void GL_Texture_CalcImageSize(int texturetype, int flags, int inwidth, in
 
        if (outwidth)
        {
-               if (gl_support_arb_texture_non_power_of_two)
+               if (vid.support.arb_texture_non_power_of_two)
                        width2 = min(inwidth >> picmip, maxsize);
                else
                {
@@ -488,7 +449,7 @@ static void GL_Texture_CalcImageSize(int texturetype, int flags, int inwidth, in
        }
        if (outheight)
        {
-               if (gl_support_arb_texture_non_power_of_two)
+               if (vid.support.arb_texture_non_power_of_two)
                        height2 = min(inheight >> picmip, maxsize);
                else
                {
@@ -499,7 +460,7 @@ static void GL_Texture_CalcImageSize(int texturetype, int flags, int inwidth, in
        }
        if (outdepth)
        {
-               if (gl_support_arb_texture_non_power_of_two)
+               if (vid.support.arb_texture_non_power_of_two)
                        depth2 = min(indepth >> picmip, maxsize);
                else
                {
@@ -677,7 +638,7 @@ void R_Textures_Frame (void)
                gltexturepool_t *pool;
                GLint oldbindtexnum;
 
-               old_aniso = bound(1, gl_texture_anisotropy.integer, gl_max_anisotropy);
+               old_aniso = bound(1, gl_texture_anisotropy.integer, (int)vid.max_anisotropy);
 
                Cvar_SetValueQuick(&gl_texture_anisotropy, old_aniso);
 
@@ -720,13 +681,13 @@ void R_MakeResizeBufferBigger(int size)
 static void GL_SetupTextureParameters(int flags, textype_t textype, int texturetype)
 {
        int textureenum = gltexturetypeenums[texturetype];
-       int wrapmode = ((flags & TEXF_CLAMP) && gl_support_clamptoedge) ? GL_CLAMP_TO_EDGE : GL_REPEAT;
+       int wrapmode = (flags & TEXF_CLAMP) ? GL_CLAMP_TO_EDGE : GL_REPEAT;
 
        CHECKGLERROR
 
-       if (gl_support_anisotropy && (flags & TEXF_MIPMAP))
+       if (vid.support.ext_texture_filter_anisotropic && (flags & TEXF_MIPMAP))
        {
-               int aniso = bound(1, gl_texture_anisotropy.integer, gl_max_anisotropy);
+               int aniso = bound(1, gl_texture_anisotropy.integer, (int)vid.max_anisotropy);
                if (gl_texture_anisotropy.integer != aniso)
                        Cvar_SetValueQuick(&gl_texture_anisotropy, aniso);
                qglTexParameteri(textureenum, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);CHECKGLERROR
@@ -785,15 +746,18 @@ static void GL_SetupTextureParameters(int flags, textype_t textype, int texturet
 
        if (textype == TEXTYPE_SHADOWMAP)
        {
-               if (flags & TEXF_COMPARE)
-               {
-                       qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);CHECKGLERROR
-               }
-               else
+               if (vid.support.arb_shadow)
                {
-                       qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);CHECKGLERROR
+                       if (flags & TEXF_COMPARE)
+                       {
+                               qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);CHECKGLERROR
+                       }
+                       else
+                       {
+                               qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);CHECKGLERROR
+                       }
+                       qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);CHECKGLERROR
                }
-               qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);CHECKGLERROR
                qglTexParameteri(textureenum, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);CHECKGLERROR
        }
 
@@ -814,7 +778,7 @@ static void R_Upload(gltexture_t *glt, const unsigned char *data, int fragx, int
        qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR
 
        // these are rounded up versions of the size to do better resampling
-       if (gl_support_arb_texture_non_power_of_two || glt->texturetype == GLTEXTURETYPE_RECTANGLE)
+       if (vid.support.arb_texture_non_power_of_two || glt->texturetype == GLTEXTURETYPE_RECTANGLE)
        {
                width = glt->inputwidth;
                height = glt->inputheight;
@@ -847,9 +811,6 @@ static void R_Upload(gltexture_t *glt, const unsigned char *data, int fragx, int
                // update a portion of the image
                switch(glt->texturetype)
                {
-               case GLTEXTURETYPE_1D:
-                       qglTexSubImage1D(GL_TEXTURE_1D, 0, fragx, fragwidth, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
-                       break;
                case GLTEXTURETYPE_2D:
                        qglTexSubImage2D(GL_TEXTURE_2D, 0, fragx, fragy, fragwidth, fragheight, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
                        break;
@@ -857,7 +818,7 @@ static void R_Upload(gltexture_t *glt, const unsigned char *data, int fragx, int
                        qglTexSubImage3D(GL_TEXTURE_3D, 0, fragx, fragy, fragz, fragwidth, fragheight, fragdepth, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
                        break;
                default:
-                       Host_Error("R_Upload: partial update of type other than 1D, 2D, or 3D");
+                       Host_Error("R_Upload: partial update of type other than 2D");
                        break;
                }
        }
@@ -885,7 +846,7 @@ static void R_Upload(gltexture_t *glt, const unsigned char *data, int fragx, int
                        }
                }
                mip = 0;
-               if (gl_support_texture_compression)
+               if (vid.support.arb_texture_compression)
                {
                        if (gl_texturecompression.integer >= 2)
                                qglHint(GL_TEXTURE_COMPRESSION_HINT_ARB, GL_NICEST);
@@ -895,18 +856,6 @@ static void R_Upload(gltexture_t *glt, const unsigned char *data, int fragx, int
                }
                switch(glt->texturetype)
                {
-               case GLTEXTURETYPE_1D:
-                       qglTexImage1D(GL_TEXTURE_1D, mip++, glt->glinternalformat, width, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
-                       if (glt->flags & TEXF_MIPMAP)
-                       {
-                               while (width > 1 || height > 1 || depth > 1)
-                               {
-                                       Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
-                                       prevbuffer = resizebuffer;
-                                       qglTexImage1D(GL_TEXTURE_1D, mip++, glt->glinternalformat, width, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
-                               }
-                       }
-                       break;
                case GLTEXTURETYPE_2D:
                        qglTexImage2D(GL_TEXTURE_2D, mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
                        if (glt->flags & TEXF_MIPMAP)
@@ -972,22 +921,33 @@ static void R_Upload(gltexture_t *glt, const unsigned char *data, int fragx, int
        qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
 }
 
-static void R_UploadTexture (gltexture_t *glt)
+int R_RealGetTexture(rtexture_t *rt)
 {
-       if (!(glt->flags & GLTEXF_UPLOAD))
-               return;
-
-       CHECKGLERROR
-       qglGenTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR
-       R_Upload(glt, glt->inputtexels, 0, 0, 0, glt->inputwidth, glt->inputheight, glt->inputdepth);
-       if (glt->inputtexels)
+       if (rt)
        {
-               Mem_Free(glt->inputtexels);
-               glt->inputtexels = NULL;
-               glt->flags |= GLTEXF_DESTROYED;
+               gltexture_t *glt;
+               glt = (gltexture_t *)rt;
+               if (glt->flags & GLTEXF_DYNAMIC)
+                       R_UpdateDynamicTexture(glt);
+               if (glt->flags & GLTEXF_UPLOAD)
+               {
+                       CHECKGLERROR
+                       qglGenTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR
+                       R_Upload(glt, glt->inputtexels, 0, 0, 0, glt->inputwidth, glt->inputheight, glt->inputdepth);
+                       if (glt->inputtexels)
+                       {
+                               Mem_Free(glt->inputtexels);
+                               glt->inputtexels = NULL;
+                               glt->flags |= GLTEXF_DESTROYED;
+                       }
+                       else if (glt->flags & GLTEXF_DESTROYED)
+                               Con_Printf("R_GetTexture: Texture %s already uploaded and destroyed.  Can not upload original image again.  Uploaded blank texture.\n", glt->identifier);
+               }
+
+               return glt->texnum;
        }
-       else if (glt->flags & GLTEXF_DESTROYED)
-               Con_Printf("R_UploadTexture: Texture %s already uploaded and destroyed.  Can not upload original image again.  Uploaded blank texture.\n", glt->identifier);
+       else
+               return 0;
 }
 
 static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int depth, int sides, int flags, textype_t textype, int texturetype, const unsigned char *data, const unsigned int *palette)
@@ -996,21 +956,22 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *iden
        gltexture_t *glt;
        gltexturepool_t *pool = (gltexturepool_t *)rtexturepool;
        textypeinfo_t *texinfo;
+       int precache;
 
        if (cls.state == ca_dedicated)
                return NULL;
 
-       if (texturetype == GLTEXTURETYPE_RECTANGLE && !gl_texturerectangle)
+       if (texturetype == GLTEXTURETYPE_RECTANGLE && !vid.support.arb_texture_rectangle)
        {
                Con_Printf ("R_LoadTexture: rectangle texture not supported by driver\n");
                return NULL;
        }
-       if (texturetype == GLTEXTURETYPE_CUBEMAP && !gl_texturecubemap)
+       if (texturetype == GLTEXTURETYPE_CUBEMAP && !vid.support.arb_texture_cube_map)
        {
                Con_Printf ("R_LoadTexture: cubemap texture not supported by driver\n");
                return NULL;
        }
-       if (texturetype == GLTEXTURETYPE_3D && !gl_texture3d)
+       if (texturetype == GLTEXTURETYPE_3D && !vid.support.ext_texture_3d)
        {
                Con_Printf ("R_LoadTexture: 3d texture not supported by driver\n");
                return NULL;
@@ -1063,7 +1024,6 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *iden
                }
                break;
        case TEXTYPE_SHADOWMAP:
-       case TEXTYPE_PROJECTION:
                break;
        default:
                Host_Error("R_LoadTexture: unknown texture type");
@@ -1094,16 +1054,45 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *iden
        glt->updatecallback = NULL;
        glt->updatacallback_data = NULL;
 
-       if (data)
+       GL_Texture_CalcImageSize(glt->texturetype, glt->flags, glt->inputwidth, glt->inputheight, glt->inputdepth, &glt->tilewidth, &glt->tileheight, &glt->tiledepth);
+
+       precache = false;
+       if (glt->flags & TEXF_ALWAYSPRECACHE)
+               precache = true;
+       else if (r_precachetextures.integer >= 2)
+               precache = true;
+       else if (r_precachetextures.integer >= 1)
+               if (glt->flags & TEXF_PRECACHE)
+                       precache = true;
+
+       if (precache)
        {
-               glt->inputtexels = (unsigned char *)Mem_Alloc(texturemempool, size);
-               memcpy(glt->inputtexels, data, size);
+               // immediate upload (most common case)
+               // data may be NULL (blank texture for dynamic rendering)
+               CHECKGLERROR
+               qglGenTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR
+               R_Upload(glt, data, 0, 0, 0, glt->inputwidth, glt->inputheight, glt->inputdepth);
+       }
+       else if (data)
+       {
+               // deferred texture upload (menu graphics)
+               // optimize first if possible
+               if ((textype == TEXTYPE_BGRA || textype == TEXTYPE_RGBA) && glt->inputwidth * glt->inputheight * glt->inputdepth > glt->tilewidth * glt->tileheight * glt->tiledepth)
+               {
+                       glt->inputtexels = (unsigned char *)Mem_Alloc(texturemempool, glt->tilewidth*glt->tileheight*glt->tiledepth*glt->sides*glt->bytesperpixel);
+                       Image_Resample32(data, glt->inputwidth, glt->inputheight, glt->inputdepth, glt->inputtexels, glt->tilewidth, glt->tileheight, glt->tiledepth, r_lerpimages.integer);
+                       // change texture size accordingly
+                       glt->inputwidth = glt->tilewidth;
+                       glt->inputheight = glt->tileheight;
+                       glt->inputdepth = glt->tiledepth;
+                       GL_Texture_CalcImageSize(glt->texturetype, glt->flags, glt->inputwidth, glt->inputheight, glt->inputdepth, &glt->tilewidth, &glt->tileheight, &glt->tiledepth);
+               }
+               else
+               {
+                       glt->inputtexels = (unsigned char *)Mem_Alloc(texturemempool, size);
+                       memcpy(glt->inputtexels, data, size);
+               }
        }
-       else
-               glt->inputtexels = NULL;
-
-       GL_Texture_CalcImageSize(glt->texturetype, glt->flags, glt->inputwidth, glt->inputheight, glt->inputdepth, &glt->tilewidth, &glt->tileheight, &glt->tiledepth);
-       R_PrecacheTexture(glt);
 
        // texture converting and uploading can take a while, so make sure we're sending keepalives
        CL_KeepaliveMessage(false);
@@ -1111,11 +1100,6 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *iden
        return (rtexture_t *)glt;
 }
 
-rtexture_t *R_LoadTexture1D(rtexturepool_t *rtexturepool, const char *identifier, int width, const unsigned char *data, textype_t textype, int flags, const unsigned int *palette)
-{
-       return R_SetupTexture(rtexturepool, identifier, width, 1, 1, 1, flags, textype, GLTEXTURETYPE_1D, data, palette);
-}
-
 rtexture_t *R_LoadTexture2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, const unsigned char *data, textype_t textype, int flags, const unsigned int *palette)
 {
        return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, flags, textype, GLTEXTURETYPE_2D, data, palette);
@@ -1131,58 +1115,31 @@ rtexture_t *R_LoadTextureCubeMap(rtexturepool_t *rtexturepool, const char *ident
        return R_SetupTexture(rtexturepool, identifier, width, width, 1, 6, flags, textype, GLTEXTURETYPE_CUBEMAP, data, palette);
 }
 
-rtexture_t *R_LoadTextureShadowMapRectangle(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, qboolean filter)
+static int R_ShadowMapTextureFlags(int precision, qboolean filter)
 {
-       return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, TEXF_ALWAYSPRECACHE | TEXF_CLAMP | (filter ? TEXF_FORCELINEAR | TEXF_COMPARE : TEXF_FORCENEAREST), TEXTYPE_SHADOWMAP, GLTEXTURETYPE_RECTANGLE, NULL, NULL);
+       int flags = TEXF_ALWAYSPRECACHE | TEXF_CLAMP;
+       if (filter)
+               flags |= TEXF_FORCELINEAR | TEXF_COMPARE;
+       else
+               flags |= TEXF_FORCENEAREST;
+       if (precision <= 16)
+               flags |= TEXF_LOWPRECISION;
+       return flags;
 }
 
-rtexture_t *R_LoadTextureShadowMap2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, qboolean filter)
+rtexture_t *R_LoadTextureShadowMapRectangle(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int precision, qboolean filter)
 {
-       return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, TEXF_ALWAYSPRECACHE | TEXF_CLAMP | (filter ? TEXF_FORCELINEAR | TEXF_COMPARE : TEXF_FORCENEAREST), TEXTYPE_SHADOWMAP, GLTEXTURETYPE_2D, NULL, NULL);
+       return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, R_ShadowMapTextureFlags(precision, filter), TEXTYPE_SHADOWMAP, GLTEXTURETYPE_RECTANGLE, NULL, NULL);
 }
 
-rtexture_t *R_LoadTextureShadowMapCube(rtexturepool_t *rtexturepool, const char *identifier, int width, qboolean filter)
+rtexture_t *R_LoadTextureShadowMap2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int precision, qboolean filter)
 {
-    return R_SetupTexture(rtexturepool, identifier, width, width, 1, 6, TEXF_ALWAYSPRECACHE | TEXF_CLAMP | (filter ? TEXF_FORCELINEAR | TEXF_COMPARE : TEXF_FORCENEAREST), TEXTYPE_SHADOWMAP, GLTEXTURETYPE_CUBEMAP, NULL, NULL);
+       return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, R_ShadowMapTextureFlags(precision, filter), TEXTYPE_SHADOWMAP, GLTEXTURETYPE_2D, NULL, NULL);
 }
 
-rtexture_t *R_LoadTextureCubeProjection(rtexturepool_t *rtexturepool, const char *identifier, int size, int border)
+rtexture_t *R_LoadTextureShadowMapCube(rtexturepool_t *rtexturepool, const char *identifier, int width, int precision, qboolean filter)
 {
-    // maps to a 2x3 texture rectangle with normalized coordinates (must be scaled by size after lookup)
-    // +-
-    // XX
-    // YY
-    // ZZ
-    rtexture_t *projection;
-       unsigned short *data, *texel;
-       unsigned int sizebits = 0, stepbits = 0, res, i, j, k;
-       while ((1 << sizebits) < size) sizebits++;
-       while ((1 << stepbits) <= border) stepbits++;
-    stepbits = min(stepbits, sizebits);
-       res = size>>stepbits;
-       stepbits += 16 - sizebits - 1;
-       data = (unsigned short *)Mem_Alloc(texturemempool, 2*sizeof(unsigned short)*res*res*6);
-       texel = data;
-       for (i = 0;i < 6;i++) 
-       {
-               unsigned int x = (i%2)<<16, y = (i/2)<<16;
-               for (j = 0;j < res;j++)
-               {
-                       for (k = 0;k < res;k++)
-                       {
-                               *texel++ = (x + ((2*k + 1)<<stepbits))/2;
-                               *texel++ = (y + ((2*j + 1)<<stepbits))/3;
-                       }
-               }
-       }
-       projection = R_SetupTexture(rtexturepool, identifier, res, res, 1, 6, TEXF_ALWAYSPRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, TEXTYPE_PROJECTION, GLTEXTURETYPE_CUBEMAP, (unsigned char *)data, NULL);
-       Mem_Free(data);
-    return projection;
-}
-
-int R_TextureHasAlpha(rtexture_t *rt)
-{
-       return rt ? (((gltexture_t *)rt)->flags & TEXF_ALPHA) != 0 : false;
+    return R_SetupTexture(rtexturepool, identifier, width, width, 1, 6, R_ShadowMapTextureFlags(precision, filter), TEXTYPE_SHADOWMAP, GLTEXTURETYPE_CUBEMAP, NULL, NULL);
 }
 
 int R_TextureWidth(rtexture_t *rt)
@@ -1197,17 +1154,13 @@ int R_TextureHeight(rtexture_t *rt)
 
 void R_UpdateTexture(rtexture_t *rt, const unsigned char *data, int x, int y, int width, int height)
 {
-       gltexture_t *glt;
-       if (rt == NULL)
-               Host_Error("R_UpdateTexture: no texture supplied");
+       gltexture_t *glt = (gltexture_t *)rt;
        if (data == NULL)
                Host_Error("R_UpdateTexture: no data supplied");
-       glt = (gltexture_t *)rt;
-
-       // we need it to be uploaded before we can update a part of it
-       if (glt->flags & GLTEXF_UPLOAD)
-               R_UploadTexture(glt);
-
+       if (glt == NULL)
+               Host_Error("R_UpdateTexture: no texture supplied");
+       if (!glt->texnum)
+               Host_Error("R_UpdateTexture: texture has not been uploaded yet");
        // update part of the texture
        R_Upload(glt, data, x, y, 0, width, height, 1);
 }