This is an automated email from the git hooks/post-receive script.

smcv pushed a commit to annotated tag 1.5a
in repository iortcw.

commit a383f6a3298469e22ed3e5794dd5a02200ea18e2
Author: MAN-AT-ARMS <m4n4t4...@gmail.com>
Date:   Thu Feb 11 20:12:50 2016 -0500

    MP: Rend2: Direct State Access / Cubemap loading / Merge cvars into r_pbr
    
    Merged cvars: r_glossIsRoughness, r_specularIsMetallic, r_framebufferGamma, 
r_tonemapGamma, r_materialGamma, r_lightGamma
---
 MP/Makefile                             |   1 +
 MP/code/rend2/glsl/calclevels4x_fp.glsl |   4 +-
 MP/code/rend2/glsl/lightall_fp.glsl     |  48 ++--
 MP/code/rend2/glsl/tonemap_fp.glsl      |   8 +-
 MP/code/rend2/qgl.h                     |  44 ++++
 MP/code/rend2/tr_animation.c            |   6 +-
 MP/code/rend2/tr_backend.c              | 212 +++++-------------
 MP/code/rend2/tr_bsp.c                  |  43 +++-
 MP/code/rend2/tr_dsa.c                  | 287 ++++++++++++++++++++++++
 MP/code/rend2/tr_dsa.h                  |  80 +++++++
 MP/code/rend2/tr_extensions.c           | 109 +++++++++
 MP/code/rend2/tr_fbo.c                  | 290 +++++-------------------
 MP/code/rend2/tr_fbo.h                  |   1 +
 MP/code/rend2/tr_glsl.c                 | 102 ++-------
 MP/code/rend2/tr_image.c                | 376 +++++++++++++++-----------------
 MP/code/rend2/tr_init.c                 |  37 +---
 MP/code/rend2/tr_local.h                |  27 +--
 MP/code/rend2/tr_main.c                 |   2 +-
 MP/code/rend2/tr_postprocess.c          | 105 ++++-----
 MP/code/rend2/tr_scene.c                |   2 +-
 MP/code/rend2/tr_shade.c                |  16 +-
 MP/code/rend2/tr_shader.c               |  60 +++--
 MP/code/rend2/tr_shadows.c              |   4 +-
 MP/code/rend2/tr_sky.c                  |   4 +-
 MP/code/rend2/tr_surface.c              |   4 +-
 MP/code/renderer/qgl.h                  |  56 ++++-
 MP/code/renderer/tr_image.c             |   6 +-
 MP/code/renderer/tr_local.h             |   1 -
 MP/rend2-readme.txt                     |  20 +-
 29 files changed, 1057 insertions(+), 898 deletions(-)

diff --git a/MP/Makefile b/MP/Makefile
index 403256d..423ae78 100644
--- a/MP/Makefile
+++ b/MP/Makefile
@@ -1735,6 +1735,7 @@ Q3R2OBJ = \
   $(B)/rend2/tr_bsp.o \
   $(B)/rend2/tr_cmds.o \
   $(B)/rend2/tr_curve.o \
+  $(B)/rend2/tr_dsa.o \
   $(B)/rend2/tr_extramath.o \
   $(B)/rend2/tr_extensions.o \
   $(B)/rend2/tr_fbo.o \
diff --git a/MP/code/rend2/glsl/calclevels4x_fp.glsl 
b/MP/code/rend2/glsl/calclevels4x_fp.glsl
index 1de59e9..0d298b6 100644
--- a/MP/code/rend2/glsl/calclevels4x_fp.glsl
+++ b/MP/code/rend2/glsl/calclevels4x_fp.glsl
@@ -14,8 +14,8 @@ vec3 GetValues(vec2 offset, vec3 current)
 
 #ifdef FIRST_PASS
 
-  #if defined(r_framebufferGamma)
-       minAvgMax = pow(minAvgMax, vec3(r_framebufferGamma));
+  #if defined(USE_PBR)
+       minAvgMax = pow(minAvgMax, vec3(2.2));
   #endif
 
        float lumi = max(dot(LUMINANCE_VECTOR, minAvgMax), 0.000001);
diff --git a/MP/code/rend2/glsl/lightall_fp.glsl 
b/MP/code/rend2/glsl/lightall_fp.glsl
index b8f3985..eb8ba90 100644
--- a/MP/code/rend2/glsl/lightall_fp.glsl
+++ b/MP/code/rend2/glsl/lightall_fp.glsl
@@ -276,9 +276,9 @@ void main()
        attenuation  = 1.0;
   #endif
 
-  #if defined(r_lightGamma)
-       lightColor   = pow(lightColor,   vec3(r_lightGamma));
-       ambientColor = pow(ambientColor, vec3(r_lightGamma));
+  #if defined(USE_PBR)
+       lightColor   = pow(lightColor,   vec3(2.2));
+       ambientColor = pow(ambientColor, vec3(2.2));
   #endif
 
   #if defined(USE_NORMALMAP)
@@ -319,7 +319,7 @@ void main()
 
        // Recover any unused light as ambient, in case attenuation is over 4x 
or
        // light is below the surface
-       ambientColor = clamp(ambientColor - lightColor * surfNL, 0.0, 1.0);
+       ambientColor = max(ambientColor - lightColor * surfNL, vec3(0.0));
   #endif
   
        vec3 reflectance;
@@ -335,21 +335,18 @@ void main()
 
        specular *= u_SpecularScale;
 
-  #if defined(r_materialGamma)
-       diffuse.rgb   = pow(diffuse.rgb,  vec3(r_materialGamma));
-    #if !defined(SPECULAR_IS_METALLIC)
-       specular.rgb  = pow(specular.rgb, vec3(r_materialGamma));
-    #endif
+  #if defined(USE_PBR)
+       diffuse.rgb = pow(diffuse.rgb, vec3(2.2));
   #endif
 
        float gloss = specular.a;
-  #if defined(GLOSS_IS_ROUGHNESS)
-       float roughness = gloss;
+  #if defined(USE_PBR)
+       float roughness = 1.0 - specular.r;
   #else
        float roughness = exp2(-3.0 * gloss);
   #endif
 
-  #if defined(SPECULAR_IS_METALLIC)
+  #if defined(USE_PBR)
        // diffuse is actually base color, and green of specular is metallicness
        float metallic = specular.g;
 
@@ -374,7 +371,7 @@ void main()
        // from 
http://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
        vec3 parallax = u_CubeMapInfo.xyz + u_CubeMapInfo.w * viewDir;
 
-    #if defined(GLOSS_IS_ROUGHNESS)
+    #if defined(USE_PBR)
        vec3 cubeLightColor = textureCubeLod(u_CubeMap, R + parallax, 7.0 * 
roughness).rgb * u_EnableTextures.w;
     #else
        vec3 cubeLightColor = textureCubeLod(u_CubeMap, R + parallax, 7.0 - 
gloss * 7.0).rgb * u_EnableTextures.w;
@@ -385,8 +382,8 @@ void main()
        //vec3 cubeLightDiffuse = max(textureCubeLod(u_CubeMap, N, 6.0).rgb, 
0.5 / 255.0);
        //cubeLightColor /= dot(cubeLightDiffuse, vec3(0.2125, 0.7154, 0.0721));
 
-    #if defined(r_framebufferGamma)
-       cubeLightColor = pow(cubeLightColor, vec3(r_framebufferGamma));
+    #if defined(USE_PBR)
+       cubeLightColor = pow(cubeLightColor, vec3(2.2));
     #endif
 
        // multiply cubemap values by lighting
@@ -421,8 +418,8 @@ void main()
 
        lightColor = u_PrimaryLightColor;
 
-    #if defined(r_lightGamma)
-       lightColor = pow(lightColor, vec3(r_lightGamma));
+    #if defined(USE_PBR)
+       lightColor = pow(lightColor, vec3(2.2));
     #endif
 
     #if defined(USE_SHADOWMAP)
@@ -434,6 +431,11 @@ void main()
 
        gl_FragColor.rgb += lightColor * reflectance * NL2;
   #endif
+
+  #if defined(USE_PBR)
+       gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(1.0 / 2.2));
+  #endif
+
 #else
        lightColor = var_Color.rgb;
 
@@ -441,21 +443,9 @@ void main()
        lightColor *= lightmapColor.rgb;
   #endif
 
-  #if defined(r_lightGamma)
-       lightColor = pow(lightColor, vec3(r_lightGamma));
-  #endif
-
-  #if defined(r_materialGamma)
-       diffuse.rgb   = pow(diffuse.rgb,  vec3(r_materialGamma));
-  #endif
-
        gl_FragColor.rgb = diffuse.rgb * lightColor;
 
 #endif
 
-#if defined(r_framebufferGamma)
-       gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(1.0 / 
r_framebufferGamma));
-#endif
-
        gl_FragColor.a = diffuse.a * var_Color.a;
 }
diff --git a/MP/code/rend2/glsl/tonemap_fp.glsl 
b/MP/code/rend2/glsl/tonemap_fp.glsl
index 1368c5b..5d8841d 100644
--- a/MP/code/rend2/glsl/tonemap_fp.glsl
+++ b/MP/code/rend2/glsl/tonemap_fp.glsl
@@ -28,8 +28,8 @@ void main()
 {
        vec4 color = texture2D(u_TextureMap, var_TexCoords) * u_Color;
 
-#if defined(r_framebufferGamma)
-       color.rgb = pow(color.rgb, vec3(r_framebufferGamma));
+#if defined(USE_PBR)
+       color.rgb = pow(color.rgb, vec3(2.2));
 #endif
 
        vec3 minAvgMax = texture2D(u_LevelsMap, var_TexCoords).rgb;
@@ -46,8 +46,8 @@ void main()
 
        color.rgb = clamp(color.rgb * var_InvWhite, 0.0, 1.0);
 
-#if defined(r_tonemapGamma)
-       color.rgb = pow(color.rgb, vec3(1.0 / r_tonemapGamma));
+#if defined(USE_PBR)
+       color.rgb = pow(color.rgb, vec3(1.0 / 2.2));
 #endif
 
        gl_FragColor = color;
diff --git a/MP/code/rend2/qgl.h b/MP/code/rend2/qgl.h
index 5e20b48..4ab6b45 100644
--- a/MP/code/rend2/qgl.h
+++ b/MP/code/rend2/qgl.h
@@ -814,6 +814,50 @@ extern GLboolean (APIENTRY * qglIsVertexArrayARB)(GLuint 
array);
 #define GL_VERTEX_ARRAY_BINDING_ARB                0x85B5
 #endif
 
+// GL_EXT_direct_state_access
+extern GLvoid(APIENTRY * qglBindMultiTexture)(GLenum texunit, GLenum target, 
GLuint texture);
+extern GLvoid(APIENTRY * qglTextureParameterf)(GLuint texture, GLenum target, 
GLenum pname, GLfloat param);
+extern GLvoid(APIENTRY * qglTextureParameteri)(GLuint texture, GLenum target, 
GLenum pname, GLint param);
+extern GLvoid(APIENTRY * qglTextureImage2D)(GLuint texture, GLenum target, 
GLint level, GLint internalformat,
+       GLsizei width, GLsizei height, GLint border, GLenum format, GLenum 
type, const GLvoid *pixels);
+extern GLvoid(APIENTRY * qglTextureSubImage2D)(GLuint texture, GLenum target, 
GLint level, GLint xoffset, GLint yoffset,
+       GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid 
*pixels);
+extern GLvoid(APIENTRY * qglCopyTextureImage2D)(GLuint texture, GLenum target, 
GLint level, GLenum internalformat,
+       GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+extern GLvoid(APIENTRY * qglCompressedTextureImage2D)(GLuint texture, GLenum 
target, GLint level, GLenum internalformat,
+       GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const 
GLvoid *data);
+extern GLvoid(APIENTRY * qglCompressedTextureSubImage2D)(GLuint texture, 
GLenum target, GLint level,
+       GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum 
format,
+       GLsizei imageSize, const GLvoid *data);
+extern GLvoid(APIENTRY * qglGenerateTextureMipmap)(GLuint texture, GLenum 
target);
+
+extern GLvoid(APIENTRY * qglProgramUniform1i)(GLuint program, GLint location, 
GLint v0);
+extern GLvoid(APIENTRY * qglProgramUniform1f)(GLuint program, GLint location, 
GLfloat v0);
+extern GLvoid(APIENTRY * qglProgramUniform2f)(GLuint program, GLint location,
+       GLfloat v0, GLfloat v1);
+extern GLvoid(APIENTRY * qglProgramUniform3f)(GLuint program, GLint location,
+       GLfloat v0, GLfloat v1, GLfloat v2);
+extern GLvoid(APIENTRY * qglProgramUniform4f)(GLuint program, GLint location,
+       GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+extern GLvoid(APIENTRY * qglProgramUniform1fv)(GLuint program, GLint location,
+       GLsizei count, const GLfloat *value);
+extern GLvoid(APIENTRY * qglProgramUniformMatrix4fv)(GLuint program, GLint 
location,
+       GLsizei count, GLboolean transpose,
+       const GLfloat *value);
+
+extern GLvoid(APIENTRY * qglNamedRenderbufferStorage)(GLuint renderbuffer,
+       GLenum internalformat, GLsizei width, GLsizei height);
+
+extern GLvoid(APIENTRY * qglNamedRenderbufferStorageMultisample)(GLuint 
renderbuffer,
+       GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+
+extern GLenum(APIENTRY * qglCheckNamedFramebufferStatus)(GLuint framebuffer, 
GLenum target);
+extern GLvoid(APIENTRY * qglNamedFramebufferTexture2D)(GLuint framebuffer,
+       GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+extern GLvoid(APIENTRY * qglNamedFramebufferRenderbuffer)(GLuint framebuffer,
+       GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+
+
 #if defined(WIN32)
 // WGL_ARB_create_context
 #ifndef WGL_ARB_create_context
diff --git a/MP/code/rend2/tr_animation.c b/MP/code/rend2/tr_animation.c
index 20d9b93..5932f89 100644
--- a/MP/code/rend2/tr_animation.c
+++ b/MP/code/rend2/tr_animation.c
@@ -1198,7 +1198,7 @@ void RB_SurfaceAnim( mdsSurface_t *surface ) {
                        for ( i = 0; i < surface->numBoneReferences; i++, 
boneRefs++ ) {
                                bonePtr = &bones[*boneRefs];
 
-                               GL_Bind( tr.whiteImage );
+                               GL_BindToTMU( tr.whiteImage, TB_COLORMAP );
                                qglLineWidth( 1 );
                                qglBegin( GL_LINES );
                                for ( j = 0; j < 3; j++ ) {
@@ -1232,7 +1232,7 @@ void RB_SurfaceAnim( mdsSurface_t *surface ) {
                        tempVert = ( float * )( tess.xyz + baseVertex );
                        tempNormal = ( uint32_t * )( tess.normal + baseVertex );
 
-                       GL_Bind( tr.whiteImage );
+                       GL_BindToTMU( tr.whiteImage, TB_COLORMAP );
                        qglLineWidth( 1 );
                        qglBegin( GL_LINES );
                        qglColor3f( .0,.0,.8 );
@@ -1352,7 +1352,7 @@ int R_GetBoneTag( orientation_t *outTag, mdsHeader_t 
*mds, int startTagIndex, co
        if (r_bonesDebug->integer == 4) {
                int j;
                // DEBUG: show the tag position/axis
-               GL_Bind( tr.whiteImage );
+               GL_BindToTMU( tr.whiteImage, TB_COLORMAP );
                qglLineWidth( 2 );
                qglBegin( GL_LINES );
                for (j=0; j<3; j++) {
diff --git a/MP/code/rend2/tr_backend.c b/MP/code/rend2/tr_backend.c
index 34550ae..f33e5a5 100644
--- a/MP/code/rend2/tr_backend.c
+++ b/MP/code/rend2/tr_backend.c
@@ -27,6 +27,8 @@ If you have questions concerning this license or the 
applicable additional terms
 */
 
 #include "tr_local.h"
+#include "tr_fbo.h"
+#include "tr_dsa.h"
 
 backEndData_t  *backEndData;
 backEndState_t backEnd;
@@ -43,80 +45,27 @@ static float s_flipMatrix[16] = {
 
 
 /*
-** GL_Bind
-*/
-void GL_Bind( image_t *image ) {
-       int texnum;
-
-       if ( !image ) {
-               ri.Printf( PRINT_WARNING, "GL_Bind: NULL image\n" );
-               texnum = tr.defaultImage->texnum;
-       } else {
-               texnum = image->texnum;
-       }
-
-       if ( r_nobind->integer && tr.dlightImage ) {        // performance 
evaluation option
-               texnum = tr.dlightImage->texnum;
-       }
-
-       if ( glState.currenttextures[glState.currenttmu] != texnum ) {
-               if ( image ) {
-                       image->frameUsed = tr.frameCount;
-               }
-               glState.currenttextures[glState.currenttmu] = texnum;
-               if (image && image->flags & IMGFLAG_CUBEMAP)
-                       qglBindTexture( GL_TEXTURE_CUBE_MAP, texnum );
-               else
-                       qglBindTexture( GL_TEXTURE_2D, texnum );
-       }
-}
-
-
-/*
-** GL_SelectTexture
-*/
-void GL_SelectTexture( int unit ) {
-       if ( glState.currenttmu == unit ) {
-               return;
-       }
-
-       if (!(unit >= 0 && unit <= 31))
-               ri.Error( ERR_DROP, "GL_SelectTexture: unit = %i", unit );
-
-       if (!qglActiveTextureARB)
-               ri.Error( ERR_DROP, "GL_SelectTexture: multitexture disabled" );
-
-       qglActiveTextureARB( GL_TEXTURE0_ARB + unit );
-
-       glState.currenttmu = unit;
-}
-
-
-/*
 ** GL_BindToTMU
 */
 void GL_BindToTMU( image_t *image, int tmu )
 {
-       int             texnum;
-       int     oldtmu = glState.currenttmu;
+       GLuint texture = (tmu == TB_COLORMAP) ? tr.defaultImage->texnum : 0;
+       GLenum target = GL_TEXTURE_2D;
 
-       if (!image)
-               texnum = 0;
-       else
-               texnum = image->texnum;
-
-       if ( glState.currenttextures[tmu] != texnum ) {
-               GL_SelectTexture( tmu );
-               if (image)
-                       image->frameUsed = tr.frameCount;
-               glState.currenttextures[tmu] = texnum;
+       if (image)
+       {
+               if (image->flags & IMGFLAG_CUBEMAP)
+                       target = GL_TEXTURE_CUBE_MAP;
 
-               if (image && (image->flags & IMGFLAG_CUBEMAP))
-                       qglBindTexture( GL_TEXTURE_CUBE_MAP, texnum );
-               else
-                       qglBindTexture( GL_TEXTURE_2D, texnum );
-               GL_SelectTexture( oldtmu );
+               image->frameUsed = tr.frameCount;
+               texture = image->texnum;
+       }
+       else
+       {
+               ri.Printf(PRINT_WARNING, "GL_BindToTMU: NULL image\n");
        }
+
+       GL_BindMultiTexture(GL_TEXTURE0_ARB + tmu, target, texture);
 }
 
 /*
@@ -148,37 +97,6 @@ void GL_Cull( int cullType ) {
 }
 
 /*
-** GL_TexEnv
-*/
-void GL_TexEnv( int env ) {
-       if ( env == glState.texEnv[glState.currenttmu] ) {
-               return;
-       }
-
-       glState.texEnv[glState.currenttmu] = env;
-
-
-       switch ( env )
-       {
-       case GL_MODULATE:
-               qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
-               break;
-       case GL_REPLACE:
-               qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
-               break;
-       case GL_DECAL:
-               qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
-               break;
-       case GL_ADD:
-               qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD );
-               break;
-       default:
-               ri.Error( ERR_DROP, "GL_TexEnv: invalid env '%d' passed", env );
-               break;
-       }
-}
-
-/*
 ** GL_State
 **
 ** This routine is responsible for setting the most commonly changed state
@@ -452,31 +370,19 @@ void RB_BeginDrawingView( void ) {
 
        if (glRefConfig.framebufferObject)
        {
+               FBO_t *fbo = backEnd.viewParms.targetFbo;
+
                // FIXME: HUGE HACK: render to the screen fbo if we've already 
postprocessed the frame and aren't drawing more world
                // drawing more world check is in case of double renders, such 
as skyportals
-               if (backEnd.viewParms.targetFbo == NULL)
-               {
-                       if (!tr.renderFbo || (backEnd.framePostProcessed && 
(backEnd.refdef.rdflags & RDF_NOWORLDMODEL)))
-                       {
-                               FBO_Bind(NULL);
-                       }
-                       else
-                       {
-                               FBO_Bind(tr.renderFbo);
-                       }
-               }
-               else
-               {
-                       FBO_Bind(backEnd.viewParms.targetFbo);
+               if (fbo == NULL && !(backEnd.framePostProcessed && 
(backEnd.refdef.rdflags & RDF_NOWORLDMODEL)))
+                       fbo = tr.renderFbo;
 
-                       // FIXME: hack for cubemap testing
-                       if (tr.renderCubeFbo && backEnd.viewParms.targetFbo == 
tr.renderCubeFbo)
-                       {
-                               cubemap_t *cubemap = 
&tr.cubemaps[backEnd.viewParms.targetFboCubemapIndex];
-                               
//qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, 
GL_TEXTURE_CUBE_MAP_POSITIVE_X + backEnd.viewParms.targetFboLayer, 
backEnd.viewParms.targetFbo->colorImage[0]->texnum, 0);
-                               qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, 
GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + 
backEnd.viewParms.targetFboLayer, cubemap->image->texnum, 0);
-                       }
+               if (tr.renderCubeFbo && fbo == tr.renderCubeFbo)
+               {
+                       cubemap_t *cubemap = 
&tr.cubemaps[backEnd.viewParms.targetFboCubemapIndex];
+                       FBO_AttachImage(fbo, cubemap->image, 
GL_COLOR_ATTACHMENT0_EXT, backEnd.viewParms.targetFboLayer);
                }
+               FBO_Bind(fbo);
        }
 
        //
@@ -928,6 +834,7 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, 
int rows, const byte *
        }
 
        RE_UploadCinematic (w, h, cols, rows, data, client, dirty);
+       GL_BindToTMU(tr.scratchImage[client], TB_COLORMAP);
 
        if ( r_speeds->integer ) {
                end = ri.Milliseconds();
@@ -937,14 +844,7 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, 
int rows, const byte *
        // FIXME: HUGE hack
        if (glRefConfig.framebufferObject)
        {
-               if (!tr.renderFbo || backEnd.framePostProcessed)
-               {
-                       FBO_Bind(NULL);
-               }
-               else
-               {
-                       FBO_Bind(tr.renderFbo);
-               }
+               FBO_Bind(backEnd.framePostProcessed ? NULL : tr.renderFbo);
        }
 
        RB_SetGL2D();
@@ -969,23 +869,30 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, 
int rows, const byte *
 
 
 void RE_UploadCinematic( int w, int h, int cols, int rows, const byte *data, 
int client, qboolean dirty ) {
+       GLuint texture;
+
+       if (!tr.scratchImage[client])
+       {
+               ri.Printf(PRINT_WARNING, "RE_UploadCinematic: scratch images 
not initialized\n");
+               return;
+       }
 
-       GL_Bind( tr.scratchImage[client] );
+       texture = tr.scratchImage[client]->texnum;
 
        // if the scratchImage isn't in the format we want, specify it as a new 
texture
        if ( cols != tr.scratchImage[client]->width || rows != 
tr.scratchImage[client]->height ) {
                tr.scratchImage[client]->width = 
tr.scratchImage[client]->uploadWidth = cols;
                tr.scratchImage[client]->height = 
tr.scratchImage[client]->uploadHeight = rows;
-               qglTexImage2D( GL_TEXTURE_2D, 0, 3, cols, rows, 0, GL_RGBA, 
GL_UNSIGNED_BYTE, data );
-               qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 
GL_LINEAR );
-               qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 
GL_LINEAR );
-               qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 
GL_CLAMP_TO_EDGE );
-               qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 
GL_CLAMP_TO_EDGE );
+               qglTextureImage2D(texture, GL_TEXTURE_2D, 0, GL_RGB8, cols, 
rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+               qglTextureParameterf(texture, GL_TEXTURE_2D, 
GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+               qglTextureParameterf(texture, GL_TEXTURE_2D, 
GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+               qglTextureParameterf(texture, GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 
GL_CLAMP_TO_EDGE);
+               qglTextureParameterf(texture, GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 
GL_CLAMP_TO_EDGE);
        } else {
                if ( dirty ) {
                        // otherwise, just subimage upload it so that drivers 
can tell we are going to be changing
                        // it and don't try and do a texture compression
-                       qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, 
GL_RGBA, GL_UNSIGNED_BYTE, data );
+                       qglTextureSubImage2D(texture, GL_TEXTURE_2D, 0, 0, 0, 
cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data);
                }
        }
 }
@@ -1024,16 +931,7 @@ const void *RB_StretchPic( const void *data ) {
 
        // FIXME: HUGE hack
        if (glRefConfig.framebufferObject)
-       {
-               if (!tr.renderFbo || backEnd.framePostProcessed)
-               {
-                       FBO_Bind(NULL);
-               }
-               else
-               {
-                       FBO_Bind(tr.renderFbo);
-               }
-       }
+               FBO_Bind(backEnd.framePostProcessed ? NULL : tr.renderFbo);
 
        RB_SetGL2D();
 
@@ -1337,11 +1235,10 @@ const void  *RB_DrawSurfs( const void *data ) {
                        // If we're using multisampling, resolve the depth first
                        FBO_FastBlit(tr.renderFbo, NULL, tr.msaaResolveFbo, 
NULL, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
                }
-               else if (tr.renderFbo == NULL)
+               else if (tr.renderFbo == NULL && tr.renderDepthImage)
                {
                        // If we're rendering directly to the screen, copy the 
depth to a texture
-                       GL_BindToTMU(tr.renderDepthImage, 0);
-                       qglCopyTexImage2D(GL_TEXTURE_2D, 0, 
GL_DEPTH_COMPONENT24, 0, 0, glConfig.vidWidth, glConfig.vidHeight, 0);
+                       qglCopyTextureImage2D(tr.renderDepthImage->texnum, 
GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 0, 0, glConfig.vidWidth, 
glConfig.vidHeight, 0);
                }
 
                if (r_ssao->integer)
@@ -1581,10 +1478,8 @@ const void  *RB_DrawSurfs( const void *data ) {
                cubemap_t *cubemap = 
&tr.cubemaps[backEnd.viewParms.targetFboCubemapIndex];
 
                FBO_Bind(NULL);
-               GL_SelectTexture(TB_CUBEMAP);
-               GL_BindToTMU(cubemap->image, TB_CUBEMAP);
-               qglGenerateMipmapEXT(GL_TEXTURE_CUBE_MAP);
-               GL_SelectTexture(0);
+               if (cubemap && cubemap->image)
+                       qglGenerateTextureMipmap(cubemap->image->texnum, 
GL_TEXTURE_CUBE_MAP);
        }
 
        return (const void *)( cmd + 1 );
@@ -1663,7 +1558,7 @@ void RB_ShowImages( void ) {
                {
                        vec4_t quadVerts[4];
 
-                       GL_Bind(image);
+                       GL_BindToTMU(image, TB_COLORMAP);
 
                        VectorSet4(quadVerts[0], x, y, 0, 1);
                        VectorSet4(quadVerts[1], x + w, y, 0, 1);
@@ -1838,21 +1733,18 @@ const void *RB_CapShadowMap(const void *data)
 
        if (cmd->map != -1)
        {
-               GL_SelectTexture(0);
                if (cmd->cubeSide != -1)
                {
                        if (tr.shadowCubemaps[cmd->map])
                        {
-                               GL_Bind(tr.shadowCubemaps[cmd->map]);
-                               
qglCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cmd->cubeSide, 0, GL_RGBA8, 
backEnd.refdef.x, glConfig.vidHeight - ( backEnd.refdef.y + PSHADOW_MAP_SIZE ), 
PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, 0);
+                               
qglCopyTextureImage2D(tr.shadowCubemaps[cmd->map]->texnum, 
GL_TEXTURE_CUBE_MAP_POSITIVE_X + cmd->cubeSide, 0, GL_RGBA8, backEnd.refdef.x, 
glConfig.vidHeight - ( backEnd.refdef.y + PSHADOW_MAP_SIZE ), PSHADOW_MAP_SIZE, 
PSHADOW_MAP_SIZE, 0);
                        }
                }
                else
                {
                        if (tr.pshadowMaps[cmd->map])
                        {
-                               GL_Bind(tr.pshadowMaps[cmd->map]);
-                               qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 
backEnd.refdef.x, glConfig.vidHeight - ( backEnd.refdef.y + PSHADOW_MAP_SIZE ), 
PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, 0);
+                               
qglCopyTextureImage2D(tr.pshadowMaps[cmd->map]->texnum, GL_TEXTURE_2D, 0, 
GL_RGBA8, backEnd.refdef.x, glConfig.vidHeight - (backEnd.refdef.y + 
PSHADOW_MAP_SIZE), PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, 0);
                        }
                }
        }
@@ -1925,7 +1817,7 @@ const void *RB_PostProcess(const void *data)
 
        if (srcFbo)
        {
-               if (r_hdr->integer && (r_toneMap->integer || 
r_forceToneMap->integer) && qglActiveTextureARB)
+               if (r_hdr->integer && (r_toneMap->integer || 
r_forceToneMap->integer))
                {
                        autoExposure = r_autoExposure->integer || 
r_forceAutoExposure->integer;
                        RB_ToneMap(srcFbo, srcBox, NULL, dstBox, autoExposure);
@@ -2041,11 +1933,11 @@ const void *RB_ExportCubemaps(const void *data)
                {
                        char filename[MAX_QPATH];
                        cubemap_t *cubemap = &tr.cubemaps[i];
-                       unsigned char *p = cubemapPixels;
+                       byte *p = cubemapPixels;
 
                        for (j = 0; j < 6; j++)
                        {
-                               qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, 
GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, 
cubemap->image->texnum, 0);
+                               FBO_AttachImage(tr.renderCubeFbo, 
cubemap->image, GL_COLOR_ATTACHMENT0_EXT, j);
                                qglReadPixels(0, 0, r_cubemapSize->integer, 
r_cubemapSize->integer, GL_RGBA, GL_UNSIGNED_BYTE, p);
                                p += sideSize;
                        }
diff --git a/MP/code/rend2/tr_bsp.c b/MP/code/rend2/tr_bsp.c
index be2170e..0fa488a 100644
--- a/MP/code/rend2/tr_bsp.c
+++ b/MP/code/rend2/tr_bsp.c
@@ -146,7 +146,7 @@ static void R_ColorShiftLightingFloats(float in[4], float 
out[4], float scale )
        float   r, g, b;
 
 #if defined(USE_OVERBRIGHT)
-       scale *= pow(2.0f, r_mapOverBrightBits->integer - tr.overbrightBits);
+       scale *= 1 << (r_mapOverBrightBits->integer - tr.overbrightBits);
 #endif
 
        r = in[0] * scale;
@@ -3112,7 +3112,7 @@ void R_LoadLightGrid( lump_t *l ) {
                if (hdrLightGrid)
                {
 #if defined(USE_OVERBRIGHT)
-                       float lightScale = pow(2, r_mapOverBrightBits->integer 
- tr.overbrightBits);
+                       float lightScale = 1 << (r_mapOverBrightBits->integer - 
tr.overbrightBits);
 #else
                        float lightScale = 1.0f;
 #endif
@@ -3419,25 +3419,43 @@ void R_AssignCubemapsToWorldSurfaces(void)
 }
 
 
-void R_RenderAllCubemaps(void)
+void R_LoadCubemaps(void)
 {
-       int i, j;
+       int i;
+       imgFlags_t flags = IMGFLAG_CLAMPTOEDGE | IMGFLAG_MIPMAP | 
IMGFLAG_NOLIGHTSCALE | IMGFLAG_CUBEMAP;
 
        for (i = 0; i < tr.numCubemaps; i++)
        {
-               tr.cubemaps[i].image = R_CreateImage(va("*cubeMap%d", i), NULL, 
r_cubemapSize->integer, r_cubemapSize->integer, IMGTYPE_COLORALPHA, 
IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE | IMGFLAG_MIPMAP | 
IMGFLAG_CUBEMAP, GL_RGBA8);
+               char filename[MAX_QPATH];
+               cubemap_t *cubemap = &tr.cubemaps[i];
+
+               Com_sprintf(filename, MAX_QPATH, "cubemaps/%s/%03d.dds", 
tr.world->baseName, i);
+
+               cubemap->image = R_FindImageFile(filename, IMGTYPE_COLORALPHA, 
flags);
        }
+}
+
+
+void R_RenderMissingCubemaps(void)
+{
+       int i, j;
+       imgFlags_t flags = IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE | 
IMGFLAG_MIPMAP | IMGFLAG_NOLIGHTSCALE | IMGFLAG_CUBEMAP;
        
        ri.Printf(PRINT_ALL, "Total cubemaps: %d\n", tr.numCubemaps );
 
        for (i = 0; i < tr.numCubemaps; i++)
        {
-               for (j = 0; j < 6; j++)
+               if (!tr.cubemaps[i].image)
                {
-                       RE_ClearScene();
-                       R_RenderCubemapSide(i, j, qfalse);
-                       R_IssuePendingRenderCommands();
-                       R_InitNextFrame();
+                       tr.cubemaps[i].image = R_CreateImage(va("*cubeMap%d", 
i), NULL, r_cubemapSize->integer, r_cubemapSize->integer, IMGTYPE_COLORALPHA, 
flags, GL_RGBA8);
+
+                       for (j = 0; j < 6; j++)
+                       {
+                               RE_ClearScene();
+                               R_RenderCubemapSide(i, j, qfalse);
+                               R_IssuePendingRenderCommands();
+                               R_InitNextFrame();
+                       }
                }
        }
 }
@@ -3812,10 +3830,11 @@ void RE_LoadWorldMap( const char *name ) {
        // make sure the VAO glState entry is safe
        R_BindNullVao();
 
-       // Render all cubemaps
+       // Render or load all cubemaps
        if (r_cubeMapping->integer && tr.numCubemaps)
        {
-               R_RenderAllCubemaps();
+               R_LoadCubemaps();
+               R_RenderMissingCubemaps();
        }
 
        ri.FS_FreeFile( buffer.v );
diff --git a/MP/code/rend2/tr_dsa.c b/MP/code/rend2/tr_dsa.c
new file mode 100644
index 0000000..a766263
--- /dev/null
+++ b/MP/code/rend2/tr_dsa.c
@@ -0,0 +1,287 @@
+/*
+===========================================================================
+Copyright (C) 2016 James Canete
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+===========================================================================
+*/
+
+#include "tr_local.h"
+
+#include "tr_dsa.h"
+
+static struct
+{
+       GLuint textures[NUM_TEXTURE_BUNDLES];
+       GLenum texunit;
+
+       GLuint program;
+
+       GLuint drawFramebuffer;
+       GLuint readFramebuffer;
+       GLuint renderbuffer;
+}
+glDsaState;
+
+void GL_BindNullTextures()
+{
+       int i;
+
+       if (glRefConfig.directStateAccess)
+       {
+               for (i = 0; i < NUM_TEXTURE_BUNDLES; i++)
+               {
+                       qglBindMultiTexture(GL_TEXTURE0_ARB + i, GL_TEXTURE_2D, 
0);
+                       glDsaState.textures[i] = 0;
+               }
+       }
+       else
+       {
+               for (i = 0; i < NUM_TEXTURE_BUNDLES; i++)
+               {
+                       qglActiveTextureARB(GL_TEXTURE0_ARB + i);
+                       qglBindTexture(GL_TEXTURE_2D, 0);
+                       glDsaState.textures[i] = 0;
+               }
+
+               qglActiveTextureARB(GL_TEXTURE0_ARB);
+               glDsaState.texunit = GL_TEXTURE0_ARB;
+       }
+}
+
+int GL_BindMultiTexture(GLenum texunit, GLenum target, GLuint texture)
+{
+       GLuint tmu = texunit - GL_TEXTURE0_ARB;
+
+       if (glDsaState.textures[tmu] == texture)
+               return 0;
+
+       if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= 
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
+               target = GL_TEXTURE_CUBE_MAP;
+
+       qglBindMultiTexture(texunit, target, texture);
+       glDsaState.textures[tmu] = texture;
+       return 1;
+}
+
+GLvoid APIENTRY GLDSA_BindMultiTexture(GLenum texunit, GLenum target, GLuint 
texture)
+{
+       if (glDsaState.texunit != texunit)
+       {
+               qglActiveTextureARB(texunit);
+               glDsaState.texunit = texunit;
+       }
+
+       qglBindTexture(target, texture);
+}
+
+GLvoid APIENTRY GLDSA_TextureParameterf(GLuint texture, GLenum target, GLenum 
pname, GLfloat param)
+{
+       GL_BindMultiTexture(glDsaState.texunit, target, texture);
+       qglTexParameterf(target, pname, param);
+}
+
+GLvoid APIENTRY GLDSA_TextureParameteri(GLuint texture, GLenum target, GLenum 
pname, GLint param)
+{
+       GL_BindMultiTexture(glDsaState.texunit, target, texture);
+       qglTexParameteri(target, pname, param);
+}
+
+GLvoid APIENTRY GLDSA_TextureImage2D(GLuint texture, GLenum target, GLint 
level, GLint internalformat,
+       GLsizei width, GLsizei height, GLint border, GLenum format, GLenum 
type, const GLvoid *pixels)
+{
+       GL_BindMultiTexture(glDsaState.texunit, target, texture);
+       qglTexImage2D(target, level, internalformat, width, height, border, 
format, type, pixels);
+}
+
+GLvoid APIENTRY GLDSA_TextureSubImage2D(GLuint texture, GLenum target, GLint 
level, GLint xoffset, GLint yoffset,
+       GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid 
*pixels)
+{
+       GL_BindMultiTexture(glDsaState.texunit, target, texture);
+       qglTexSubImage2D(target, level, xoffset, yoffset, width, height, 
format, type, pixels);
+}
+
+GLvoid APIENTRY GLDSA_CopyTextureImage2D(GLuint texture, GLenum target, GLint 
level, GLenum internalformat,
+       GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
+{
+       GL_BindMultiTexture(glDsaState.texunit, target, texture);
+       qglCopyTexImage2D(target, level, internalformat, x, y, width, height, 
border);
+}
+
+GLvoid APIENTRY  GLDSA_CompressedTextureImage2D(GLuint texture, GLenum target, 
GLint level, GLenum internalformat,
+       GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const 
GLvoid *data)
+{
+       GL_BindMultiTexture(glDsaState.texunit, target, texture);
+       qglCompressedTexImage2DARB(target, level, internalformat, width, 
height, border, imageSize, data);
+}
+
+GLvoid APIENTRY GLDSA_CompressedTextureSubImage2D(GLuint texture, GLenum 
target, GLint level,
+       GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum 
format,
+       GLsizei imageSize, const GLvoid *data)
+{
+       GL_BindMultiTexture(glDsaState.texunit, target, texture);
+       qglCompressedTexSubImage2DARB(target, level, xoffset, yoffset, width, 
height, format, imageSize, data);
+}
+
+GLvoid APIENTRY GLDSA_GenerateTextureMipmap(GLuint texture, GLenum target)
+{
+       GL_BindMultiTexture(glDsaState.texunit, target, texture);
+       qglGenerateMipmapEXT(target);
+}
+
+void GL_BindNullProgram()
+{
+       qglUseProgramObjectARB(0);
+       glDsaState.program = 0;
+}
+
+int GL_UseProgramObject(GLuint program)
+{
+       if (glDsaState.program == program)
+               return 0;
+
+       qglUseProgramObjectARB(program);
+       glDsaState.program = program;
+       return 1;
+}
+
+GLvoid APIENTRY GLDSA_ProgramUniform1i(GLuint program, GLint location, GLint 
v0)
+{
+       GL_UseProgramObject(program);
+       qglUniform1iARB(location, v0);
+}
+
+GLvoid APIENTRY GLDSA_ProgramUniform1f(GLuint program, GLint location, GLfloat 
v0)
+{
+       GL_UseProgramObject(program);
+       qglUniform1fARB(location, v0);
+}
+
+GLvoid APIENTRY GLDSA_ProgramUniform2f(GLuint program, GLint location,
+       GLfloat v0, GLfloat v1)
+{
+       GL_UseProgramObject(program);
+       qglUniform2fARB(location, v0, v1);
+}
+
+GLvoid APIENTRY GLDSA_ProgramUniform3f(GLuint program, GLint location,
+       GLfloat v0, GLfloat v1, GLfloat v2)
+{
+       GL_UseProgramObject(program);
+       qglUniform3fARB(location, v0, v1, v2);
+}
+
+GLvoid APIENTRY GLDSA_ProgramUniform4f(GLuint program, GLint location,
+       GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
+{
+       GL_UseProgramObject(program);
+       qglUniform4fARB(location, v0, v1, v2, v3);
+}
+
+GLvoid APIENTRY GLDSA_ProgramUniform1fv(GLuint program, GLint location,
+       GLsizei count, const GLfloat *value)
+{
+       GL_UseProgramObject(program);
+       qglUniform1fvARB(location, count, value);
+}
+
+GLvoid APIENTRY GLDSA_ProgramUniformMatrix4fv(GLuint program, GLint location,
+       GLsizei count, GLboolean transpose,
+       const GLfloat *value)
+{
+       GL_UseProgramObject(program);
+       qglUniformMatrix4fvARB(location, count, transpose, value);
+}
+
+void GL_BindNullFramebuffers()
+{
+       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+       glDsaState.drawFramebuffer = glDsaState.readFramebuffer = 0;
+       qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+       glDsaState.readFramebuffer = 0;
+}
+
+void GL_BindFramebuffer(GLenum target, GLuint framebuffer)
+{
+       switch (target)
+       {
+               case GL_FRAMEBUFFER_EXT:
+                       if (framebuffer != glDsaState.drawFramebuffer || 
framebuffer != glDsaState.readFramebuffer)
+                       {
+                               qglBindFramebufferEXT(target, framebuffer);
+                               glDsaState.drawFramebuffer = 
glDsaState.readFramebuffer = framebuffer;
+                       }
+                       break;
+
+               case GL_DRAW_FRAMEBUFFER_EXT:
+                       if (framebuffer != glDsaState.drawFramebuffer)
+                       {
+                               qglBindFramebufferEXT(target, framebuffer);
+                               glDsaState.drawFramebuffer = framebuffer;
+                       }
+                       break;
+
+               case GL_READ_FRAMEBUFFER_EXT:
+                       if (framebuffer != glDsaState.readFramebuffer)
+                       {
+                               qglBindFramebufferEXT(target, framebuffer);
+                               glDsaState.readFramebuffer = framebuffer;
+                       }
+                       break;
+       }
+}
+
+void GL_BindRenderbuffer(GLuint renderbuffer)
+{
+       if (renderbuffer != glDsaState.renderbuffer)
+       {
+               qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderbuffer);
+               glDsaState.renderbuffer = renderbuffer;
+       }
+}
+
+GLvoid APIENTRY GLDSA_NamedRenderbufferStorage(GLuint renderbuffer,
+       GLenum internalformat, GLsizei width, GLsizei height)
+{
+       GL_BindRenderbuffer(renderbuffer);
+       qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, internalformat, width, 
height);
+}
+
+GLvoid APIENTRY GLDSA_NamedRenderbufferStorageMultisample(GLuint renderbuffer,
+       GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
+{
+       GL_BindRenderbuffer(renderbuffer);
+       qglRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, 
internalformat, width, height);
+}
+
+GLenum APIENTRY GLDSA_CheckNamedFramebufferStatus(GLuint framebuffer, GLenum 
target)
+{
+       GL_BindFramebuffer(target, framebuffer);
+       return qglCheckFramebufferStatusEXT(target);
+}
+
+GLvoid APIENTRY GLDSA_NamedFramebufferTexture2D(GLuint framebuffer,
+       GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+{
+       GL_BindFramebuffer(GL_FRAMEBUFFER_EXT, framebuffer);
+       qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, textarget, 
texture, level);
+}
+
+GLvoid APIENTRY GLDSA_NamedFramebufferRenderbuffer(GLuint framebuffer,
+       GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+{
+       GL_BindFramebuffer(GL_FRAMEBUFFER_EXT, framebuffer);
+       qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attachment, 
renderbuffertarget, renderbuffer);
+}
diff --git a/MP/code/rend2/tr_dsa.h b/MP/code/rend2/tr_dsa.h
new file mode 100644
index 0000000..9d610ef
--- /dev/null
+++ b/MP/code/rend2/tr_dsa.h
@@ -0,0 +1,80 @@
+/*
+===========================================================================
+Copyright (C) 2016 James Canete
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+===========================================================================
+*/
+
+#ifndef __TR_DSA_H__
+#define __TR_DSA_H__
+
+#include "qgl.h"
+
+void GL_BindNullTextures(void);
+int GL_BindMultiTexture(GLenum texunit, GLenum target, GLuint texture);
+
+GLvoid APIENTRY GLDSA_BindMultiTexture(GLenum texunit, GLenum target, GLuint 
texture);
+GLvoid APIENTRY GLDSA_TextureParameterf(GLuint texture, GLenum target, GLenum 
pname, GLfloat param);
+GLvoid APIENTRY GLDSA_TextureParameteri(GLuint texture, GLenum target, GLenum 
pname, GLint param);
+GLvoid APIENTRY GLDSA_TextureImage2D(GLuint texture, GLenum target, GLint 
level, GLint internalformat,
+       GLsizei width, GLsizei height, GLint border, GLenum format, GLenum 
type, const GLvoid *pixels);
+GLvoid APIENTRY GLDSA_TextureSubImage2D(GLuint texture, GLenum target, GLint 
level, GLint xoffset, GLint yoffset,
+       GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid 
*pixels);
+GLvoid APIENTRY GLDSA_CopyTextureImage2D(GLuint texture, GLenum target, GLint 
level, GLenum internalformat,
+       GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GLvoid APIENTRY GLDSA_CompressedTextureImage2D(GLuint texture, GLenum target, 
GLint level, GLenum internalformat,
+       GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const 
GLvoid *data);
+GLvoid APIENTRY GLDSA_CompressedTextureSubImage2D(GLuint texture, GLenum 
target, GLint level,
+       GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum 
format,
+       GLsizei imageSize, const GLvoid *data);
+
+GLvoid APIENTRY GLDSA_GenerateTextureMipmap(GLuint texture, GLenum target);
+
+void GL_BindNullProgram(void);
+int GL_UseProgramObject(GLuint program);
+
+GLvoid APIENTRY GLDSA_ProgramUniform1i(GLuint program, GLint location, GLint 
v0);
+GLvoid APIENTRY GLDSA_ProgramUniform1f(GLuint program, GLint location, GLfloat 
v0);
+GLvoid APIENTRY GLDSA_ProgramUniform2f(GLuint program, GLint location,
+       GLfloat v0, GLfloat v1);
+GLvoid APIENTRY GLDSA_ProgramUniform3f(GLuint program, GLint location,
+       GLfloat v0, GLfloat v1, GLfloat v2);
+GLvoid APIENTRY GLDSA_ProgramUniform4f(GLuint program, GLint location,
+       GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GLvoid APIENTRY GLDSA_ProgramUniform1fv(GLuint program, GLint location,
+       GLsizei count, const GLfloat *value);
+GLvoid APIENTRY GLDSA_ProgramUniformMatrix4fv(GLuint program, GLint location,
+       GLsizei count, GLboolean transpose,
+       const GLfloat *value);
+
+void GL_BindNullFramebuffers(void);
+void GL_BindFramebuffer(GLenum target, GLuint framebuffer);
+void GL_BindRenderbuffer(GLuint renderbuffer);
+
+GLvoid APIENTRY GLDSA_NamedRenderbufferStorage(GLuint renderbuffer,
+       GLenum internalformat, GLsizei width, GLsizei height);
+
+GLvoid APIENTRY GLDSA_NamedRenderbufferStorageMultisample(GLuint renderbuffer,
+       GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+
+GLenum APIENTRY GLDSA_CheckNamedFramebufferStatus(GLuint framebuffer, GLenum 
target);
+GLvoid APIENTRY GLDSA_NamedFramebufferTexture2D(GLuint framebuffer,
+       GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLvoid APIENTRY GLDSA_NamedFramebufferRenderbuffer(GLuint framebuffer,
+       GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+
+
+#endif
diff --git a/MP/code/rend2/tr_extensions.c b/MP/code/rend2/tr_extensions.c
index 8c2d9d0..7a4bacc 100644
--- a/MP/code/rend2/tr_extensions.c
+++ b/MP/code/rend2/tr_extensions.c
@@ -28,6 +28,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  
02110-1301  USA
 #endif
 
 #include "tr_local.h"
+#include "tr_dsa.h"
 
 // GL_EXT_draw_range_elements
 void            (APIENTRY * qglDrawRangeElementsEXT) (GLenum mode, GLuint 
start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
@@ -184,6 +185,50 @@ void (APIENTRY * qglDeleteVertexArraysARB)(GLsizei n, 
const GLuint *arrays);
 void (APIENTRY * qglGenVertexArraysARB)(GLsizei n, GLuint *arrays);
 GLboolean (APIENTRY * qglIsVertexArrayARB)(GLuint array);
 
+// GL_EXT_direct_state_access
+GLvoid (APIENTRY * qglBindMultiTexture)(GLenum texunit, GLenum target, GLuint 
texture);
+GLvoid (APIENTRY * qglTextureParameterf)(GLuint texture, GLenum target, GLenum 
pname, GLfloat param);
+GLvoid (APIENTRY * qglTextureParameteri)(GLuint texture, GLenum target, GLenum 
pname, GLint param);
+GLvoid (APIENTRY * qglTextureImage2D)(GLuint texture, GLenum target, GLint 
level, GLint internalformat,
+       GLsizei width, GLsizei height, GLint border, GLenum format, GLenum 
type, const GLvoid *pixels);
+GLvoid (APIENTRY * qglTextureSubImage2D)(GLuint texture, GLenum target, GLint 
level, GLint xoffset, GLint yoffset,
+       GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid 
*pixels);
+GLvoid (APIENTRY * qglCopyTextureImage2D)(GLuint texture, GLenum target, GLint 
level, GLenum internalformat,
+       GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GLvoid (APIENTRY * qglCompressedTextureImage2D)(GLuint texture, GLenum target, 
GLint level, GLenum internalformat,
+       GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const 
GLvoid *data);
+GLvoid (APIENTRY * qglCompressedTextureSubImage2D)(GLuint texture, GLenum 
target, GLint level,
+       GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum 
format,
+       GLsizei imageSize, const GLvoid *data);
+GLvoid (APIENTRY * qglGenerateTextureMipmap)(GLuint texture, GLenum target);
+
+GLvoid(APIENTRY * qglProgramUniform1i)(GLuint program, GLint location, GLint 
v0);
+GLvoid(APIENTRY * qglProgramUniform1f)(GLuint program, GLint location, GLfloat 
v0);
+GLvoid(APIENTRY * qglProgramUniform2f)(GLuint program, GLint location,
+       GLfloat v0, GLfloat v1);
+GLvoid(APIENTRY * qglProgramUniform3f)(GLuint program, GLint location,
+       GLfloat v0, GLfloat v1, GLfloat v2);
+GLvoid(APIENTRY * qglProgramUniform4f)(GLuint program, GLint location,
+       GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GLvoid(APIENTRY * qglProgramUniform1fv)(GLuint program, GLint location,
+       GLsizei count, const GLfloat *value);
+GLvoid(APIENTRY * qglProgramUniformMatrix4fv)(GLuint program, GLint location,
+       GLsizei count, GLboolean transpose,
+       const GLfloat *value);
+
+GLvoid(APIENTRY * qglNamedRenderbufferStorage)(GLuint renderbuffer,
+       GLenum internalformat, GLsizei width, GLsizei height);
+
+GLvoid(APIENTRY * qglNamedRenderbufferStorageMultisample)(GLuint renderbuffer,
+       GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+
+GLenum(APIENTRY * qglCheckNamedFramebufferStatus)(GLuint framebuffer, GLenum 
target);
+GLvoid(APIENTRY * qglNamedFramebufferTexture2D)(GLuint framebuffer,
+       GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLvoid(APIENTRY * qglNamedFramebufferRenderbuffer)(GLuint framebuffer,
+       GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+
+
 static qboolean GLimp_HaveExtension(const char *ext)
 {
        const char *ptr = Q_stristr( (char *)qglGetString(GL_EXTENSIONS), ext );
@@ -750,4 +795,68 @@ void GLimp_InitExtraExtensions()
                ri.Printf(PRINT_ALL, result[2], extension);
        }
 
+       // GL_EXT_direct_state_access
+       extension = "GL_EXT_direct_state_access";
+
+       qglBindMultiTexture = GLDSA_BindMultiTexture;
+       qglTextureParameterf = GLDSA_TextureParameterf;
+       qglTextureParameteri = GLDSA_TextureParameteri;
+       qglTextureImage2D = GLDSA_TextureImage2D;
+       qglTextureSubImage2D = GLDSA_TextureSubImage2D;
+       qglCopyTextureImage2D = GLDSA_CopyTextureImage2D;
+       qglCompressedTextureImage2D = GLDSA_CompressedTextureImage2D;
+       qglCompressedTextureSubImage2D = GLDSA_CompressedTextureSubImage2D;
+       qglGenerateTextureMipmap = GLDSA_GenerateTextureMipmap;
+
+       qglProgramUniform1i = GLDSA_ProgramUniform1i;
+       qglProgramUniform1f = GLDSA_ProgramUniform1f;
+       qglProgramUniform2f = GLDSA_ProgramUniform2f;
+       qglProgramUniform3f = GLDSA_ProgramUniform3f;
+       qglProgramUniform4f = GLDSA_ProgramUniform4f;
+       qglProgramUniform1fv = GLDSA_ProgramUniform1fv;
+       qglProgramUniformMatrix4fv = GLDSA_ProgramUniformMatrix4fv;
+
+       qglNamedRenderbufferStorage = GLDSA_NamedRenderbufferStorage;
+       qglNamedRenderbufferStorageMultisample = 
GLDSA_NamedRenderbufferStorageMultisample;
+       qglCheckNamedFramebufferStatus = GLDSA_CheckNamedFramebufferStatus;
+       qglNamedFramebufferTexture2D = GLDSA_NamedFramebufferTexture2D;
+       qglNamedFramebufferRenderbuffer = GLDSA_NamedFramebufferRenderbuffer;
+
+       glRefConfig.directStateAccess = qfalse;
+       if (GLimp_HaveExtension(extension))
+       {
+               if (r_ext_direct_state_access->integer)
+               {
+                       glRefConfig.directStateAccess = qtrue;
+                       qglBindMultiTexture = (void 
*)SDL_GL_GetProcAddress("glBindMultiTextureEXT");
+                       qglTextureParameterf = (void 
*)SDL_GL_GetProcAddress("glTextureParameterfEXT");
+                       qglTextureParameteri = (void 
*)SDL_GL_GetProcAddress("glTextureParameteriEXT");
+                       qglTextureImage2D = (void 
*)SDL_GL_GetProcAddress("glTextureImage2DEXT");
+                       qglTextureSubImage2D = (void 
*)SDL_GL_GetProcAddress("glTextureSubImage2DEXT");
+                       qglCopyTextureImage2D = (void 
*)SDL_GL_GetProcAddress("glCopyTextureImage2DEXT");
+                       qglCompressedTextureImage2D = (void 
*)SDL_GL_GetProcAddress("glCompressedTextureImage2DEXT");
+                       qglCompressedTextureSubImage2D = (void 
*)SDL_GL_GetProcAddress("glCompressedTextureSubImage2DEXT");
+                       qglGenerateTextureMipmap = (void 
*)SDL_GL_GetProcAddress("glGenerateTextureMipmapEXT");
+
+                       qglProgramUniform1i = (void 
*)SDL_GL_GetProcAddress("glProgramUniform1iEXT");
+                       qglProgramUniform1f = (void 
*)SDL_GL_GetProcAddress("glProgramUniform1fEXT");
+                       qglProgramUniform2f = (void 
*)SDL_GL_GetProcAddress("glProgramUniform2fEXT");
+                       qglProgramUniform3f = (void 
*)SDL_GL_GetProcAddress("glProgramUniform3fEXT");
+                       qglProgramUniform4f = (void 
*)SDL_GL_GetProcAddress("glProgramUniform4fEXT");
+                       qglProgramUniform1fv = (void 
*)SDL_GL_GetProcAddress("glProgramUniform1fvEXT");
+                       qglProgramUniformMatrix4fv = (void 
*)SDL_GL_GetProcAddress("glProgramUniformMatrix4fvEXT");
+
+                       qglNamedRenderbufferStorage = (void 
*)SDL_GL_GetProcAddress("glNamedRenderbufferStorageEXT");
+                       qglNamedRenderbufferStorageMultisample = (void 
*)SDL_GL_GetProcAddress("glNamedRenderbufferStorageMultisampleEXT");
+                       qglCheckNamedFramebufferStatus = (void 
*)SDL_GL_GetProcAddress("glCheckNamedFramebufferStatusEXT");
+                       qglNamedFramebufferTexture2D = (void 
*)SDL_GL_GetProcAddress("glNamedFramebufferTexture2DEXT");
+                       qglNamedFramebufferRenderbuffer = (void 
*)SDL_GL_GetProcAddress("glNamedFramebufferRenderbufferEXT");
+               }
+
+               ri.Printf(PRINT_ALL, result[glRefConfig.directStateAccess ? 1 : 
0], extension);
+       }
+       else
+       {
+               ri.Printf(PRINT_ALL, result[2], extension);
+       }
 }
diff --git a/MP/code/rend2/tr_fbo.c b/MP/code/rend2/tr_fbo.c
index c8ea0ae..59b1703 100644
--- a/MP/code/rend2/tr_fbo.c
+++ b/MP/code/rend2/tr_fbo.c
@@ -23,6 +23,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  
02110-1301  USA
 // tr_fbo.c
 #include "tr_local.h"
 
+#include "tr_dsa.h"
+
 /*
 =============
 R_CheckFBO
@@ -30,19 +32,10 @@ R_CheckFBO
 */
 qboolean R_CheckFBO(const FBO_t * fbo)
 {
-       int             code;
-       int             id;
-
-       qglGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &id);
-       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->frameBuffer);
-
-       code = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+       GLenum code = qglCheckNamedFramebufferStatus(fbo->frameBuffer, 
GL_FRAMEBUFFER_EXT);
 
        if(code == GL_FRAMEBUFFER_COMPLETE_EXT)
-       {
-               qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id);
                return qtrue;
-       }
 
        // an error occured
        switch (code)
@@ -83,13 +76,9 @@ qboolean R_CheckFBO(const FBO_t * fbo)
 
                default:
                        ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) unknown 
error 0x%X\n", fbo->name, code);
-                       //ri.Error(ERR_FATAL, "R_CheckFBO: (%s) unknown error 
0x%X", fbo->name, code);
-                       //assert(0);
                        break;
        }
 
-       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id);
-
        return qfalse;
 }
 
@@ -133,6 +122,11 @@ FBO_t          *FBO_Create(const char *name, int width, 
int height)
        return fbo;
 }
 
+/*
+=================
+FBO_CreateBuffer
+=================
+*/
 void FBO_CreateBuffer(FBO_t *fbo, int format, int index, int multisample)
 {
        uint32_t *pRenderBuffer;
@@ -189,115 +183,45 @@ void FBO_CreateBuffer(FBO_t *fbo, int format, int index, 
int multisample)
        if (absent)
                qglGenRenderbuffersEXT(1, pRenderBuffer);
 
-       qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, *pRenderBuffer);
        if (multisample && glRefConfig.framebufferMultisample)
-       {
-               qglRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, 
multisample, format, fbo->width, fbo->height);
-       }
+               qglNamedRenderbufferStorageMultisample(*pRenderBuffer, 
multisample, format, fbo->width, fbo->height);
        else
-       {
-               qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, format, 
fbo->width, fbo->height);
-       }
+               qglNamedRenderbufferStorage(*pRenderBuffer, format, fbo->width, 
fbo->height);
 
        if(absent)
        {
                if (attachment == 0)
                {
-                       qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, 
GL_DEPTH_ATTACHMENT_EXT,   GL_RENDERBUFFER_EXT, *pRenderBuffer);
-                       qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, 
GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, *pRenderBuffer);
+                       qglNamedFramebufferRenderbuffer(fbo->frameBuffer, 
GL_DEPTH_ATTACHMENT_EXT,   GL_RENDERBUFFER_EXT, *pRenderBuffer);
+                       qglNamedFramebufferRenderbuffer(fbo->frameBuffer, 
GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, *pRenderBuffer);
                }
                else
-                       qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, 
attachment, GL_RENDERBUFFER_EXT, *pRenderBuffer);
-       }
-}
-
-
-/*
-=================
-R_AttachFBOTexture1D
-=================
-*/
-void R_AttachFBOTexture1D(int texId, int index)
-{
-       if(index < 0 || index >= glRefConfig.maxColorAttachments)
-       {
-               ri.Printf(PRINT_WARNING, "R_AttachFBOTexture1D: invalid 
attachment index %i\n", index);
-               return;
+               {
+                       qglNamedFramebufferRenderbuffer(fbo->frameBuffer, 
attachment, GL_RENDERBUFFER_EXT, *pRenderBuffer);
+               }
        }
-
-       qglFramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT 
+ index, GL_TEXTURE_1D, texId, 0);
 }
 
-/*
-=================
-R_AttachFBOTexture2D
-=================
-*/
-void R_AttachFBOTexture2D(int target, int texId, int index)
-{
-       if(target != GL_TEXTURE_2D && (target < 
GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB || target > 
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB))
-       {
-               ri.Printf(PRINT_WARNING, "R_AttachFBOTexture2D: invalid target 
%i\n", target);
-               return;
-       }
-
-       if(index < 0 || index >= glRefConfig.maxColorAttachments)
-       {
-               ri.Printf(PRINT_WARNING, "R_AttachFBOTexture2D: invalid 
attachment index %i\n", index);
-               return;
-       }
-
-       qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT 
+ index, target, texId, 0);
-}
 
 /*
 =================
-R_AttachFBOTexture3D
+FBO_AttachImage
 =================
 */
-void R_AttachFBOTexture3D(int texId, int index, int zOffset)
+void FBO_AttachImage(FBO_t *fbo, image_t *image, GLenum attachment, GLuint 
cubemapside)
 {
-       if(index < 0 || index >= glRefConfig.maxColorAttachments)
-       {
-               ri.Printf(PRINT_WARNING, "R_AttachFBOTexture3D: invalid 
attachment index %i\n", index);
-               return;
-       }
+       GLenum target = GL_TEXTURE_2D;
+       int index;
 
-       qglFramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT 
+ index, GL_TEXTURE_3D_EXT, texId, 0, zOffset);
-}
+       if (image->flags & IMGFLAG_CUBEMAP)
+               target = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + cubemapside;
 
-/*
-=================
-R_AttachFBOTextureDepth
-=================
-*/
-void R_AttachFBOTextureDepth(int texId)
-{
-       qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, 
GL_TEXTURE_2D, texId, 0);
+       qglNamedFramebufferTexture2D(fbo->frameBuffer, attachment, target, 
image->texnum, 0);
+       index = attachment - GL_COLOR_ATTACHMENT0_EXT;
+       if (index >= 0 && index <= 15)
+               fbo->colorImage[index] = image;
 }
 
-/*
-=================
-R_AttachFBOTexturePackedDepthStencil
-=================
-*/
-void R_AttachFBOTexturePackedDepthStencil(int texId)
-{
-       qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, 
GL_TEXTURE_2D, texId, 0);
-       qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, 
GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, texId, 0);
-}
-
-void FBO_AttachTextureImage(image_t *img, int index)
-{
-       if (!glState.currentFBO)
-       {
-               ri.Printf(PRINT_WARNING, "FBO: attempted to attach a texture 
image with no FBO bound!\n");
-               return;
-       }
-
-       R_AttachFBOTexture2D(GL_TEXTURE_2D, img->texnum, index);
-       glState.currentFBO->colorImage[index] = img;
-}
 
 /*
 ============
@@ -312,38 +236,10 @@ void FBO_Bind(FBO_t * fbo)
        if (r_logFile->integer)
        {
                // don't just call LogComment, or we will get a call to va() 
every frame!
-               if (fbo)
-                       GLimp_LogComment(va("--- FBO_Bind( %s ) ---\n", 
fbo->name));
-               else
-                       GLimp_LogComment("--- FBO_Bind ( NULL ) ---\n");
-       }
-
-       if (!fbo)
-       {
-               qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
-               //qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
-               glState.currentFBO = NULL;
-               
-               return;
+               GLimp_LogComment(va("--- FBO_Bind( %s ) ---\n", fbo ? fbo->name 
: "NULL"));
        }
-               
-       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->frameBuffer);
-
-       /*
-          if(fbo->colorBuffers[0])
-          {
-          qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->colorBuffers[0]);
-          }
-        */
-
-       /*
-          if(fbo->depthBuffer)
-          {
-          qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->depthBuffer);
-          qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, 
GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->depthBuffer);
-          }
-        */
 
+       GL_BindFramebuffer(GL_FRAMEBUFFER_EXT, fbo ? fbo->frameBuffer : 0);
        glState.currentFBO = fbo;
 }
 
@@ -355,7 +251,6 @@ FBO_Init
 void FBO_Init(void)
 {
        int             i;
-       // int             width, height, hdrFormat, multisample;
        int             hdrFormat, multisample;
 
        ri.Printf(PRINT_ALL, "------- FBO_Init -------\n");
@@ -369,73 +264,40 @@ void FBO_Init(void)
 
        R_IssuePendingRenderCommands();
 
-/*     if(glRefConfig.textureNonPowerOfTwo)
-       {
-               width = glConfig.vidWidth;
-               height = glConfig.vidHeight;
-       }
-       else
-       {
-               width = NextPowerOfTwo(glConfig.vidWidth);
-               height = NextPowerOfTwo(glConfig.vidHeight);
-       } */
-
        hdrFormat = GL_RGBA8;
        if (r_hdr->integer && glRefConfig.framebufferObject && 
glRefConfig.textureFloat)
-       {
                hdrFormat = GL_RGBA16F_ARB;
-       }
 
        qglGetIntegerv(GL_MAX_SAMPLES_EXT, &multisample);
 
        if (r_ext_framebuffer_multisample->integer < multisample)
-       {
                multisample = r_ext_framebuffer_multisample->integer;
-       }
 
        if (multisample < 2 || !glRefConfig.framebufferBlit)
                multisample = 0;
 
        if (multisample != r_ext_framebuffer_multisample->integer)
-       {
                ri.Cvar_SetValue("r_ext_framebuffer_multisample", 
(float)multisample);
-       }
        
        // only create a render FBO if we need to resolve MSAA or do HDR
        // otherwise just render straight to the screen (tr.renderFbo = NULL)
        if (multisample && glRefConfig.framebufferMultisample)
        {
                tr.renderFbo = FBO_Create("_render", 
tr.renderDepthImage->width, tr.renderDepthImage->height);
-               FBO_Bind(tr.renderFbo);
-
                FBO_CreateBuffer(tr.renderFbo, hdrFormat, 0, multisample);
                FBO_CreateBuffer(tr.renderFbo, GL_DEPTH_COMPONENT24_ARB, 0, 
multisample);
-
                R_CheckFBO(tr.renderFbo);
 
-
                tr.msaaResolveFbo = FBO_Create("_msaaResolve", 
tr.renderDepthImage->width, tr.renderDepthImage->height);
-               FBO_Bind(tr.msaaResolveFbo);
-
-               //FBO_CreateBuffer(tr.msaaResolveFbo, hdrFormat, 0, 0);
-               FBO_AttachTextureImage(tr.renderImage, 0);
-
-               //FBO_CreateBuffer(tr.msaaResolveFbo, GL_DEPTH_COMPONENT24_ARB, 
0, 0);
-               R_AttachFBOTextureDepth(tr.renderDepthImage->texnum);
-
+               FBO_AttachImage(tr.msaaResolveFbo, tr.renderImage, 
GL_COLOR_ATTACHMENT0_EXT, 0);
+               FBO_AttachImage(tr.msaaResolveFbo, tr.renderDepthImage, 
GL_DEPTH_ATTACHMENT_EXT, 0);
                R_CheckFBO(tr.msaaResolveFbo);
        }
        else if (r_hdr->integer)
        {
                tr.renderFbo = FBO_Create("_render", 
tr.renderDepthImage->width, tr.renderDepthImage->height);
-               FBO_Bind(tr.renderFbo);
-
-               //FBO_CreateBuffer(tr.renderFbo, hdrFormat, 0, 0);
-               FBO_AttachTextureImage(tr.renderImage, 0);
-
-               //FBO_CreateBuffer(tr.renderFbo, GL_DEPTH_COMPONENT24_ARB, 0, 
0);
-               R_AttachFBOTextureDepth(tr.renderDepthImage->texnum);
-
+               FBO_AttachImage(tr.renderFbo, tr.renderImage, 
GL_COLOR_ATTACHMENT0_EXT, 0);
+               FBO_AttachImage(tr.renderFbo, tr.renderDepthImage, 
GL_DEPTH_ATTACHMENT_EXT, 0);
                R_CheckFBO(tr.renderFbo);
        }
 
@@ -443,20 +305,15 @@ void FBO_Init(void)
        // this fixes the corrupt screen bug with r_hdr 1 on older hardware
        if (tr.renderFbo)
        {
-               FBO_Bind(tr.renderFbo);
+               GL_BindFramebuffer(GL_FRAMEBUFFER_EXT, 
tr.renderFbo->frameBuffer);
                qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
-               FBO_Bind(NULL);
        }
 
        if (r_drawSunRays->integer)
        {
                tr.sunRaysFbo = FBO_Create("_sunRays", 
tr.renderDepthImage->width, tr.renderDepthImage->height);
-               FBO_Bind(tr.sunRaysFbo);
-
-               FBO_AttachTextureImage(tr.sunRaysImage, 0);
-
-               R_AttachFBOTextureDepth(tr.renderDepthImage->texnum);
-
+               FBO_AttachImage(tr.sunRaysFbo, tr.sunRaysImage, 
GL_COLOR_ATTACHMENT0_EXT, 0);
+               FBO_AttachImage(tr.sunRaysFbo, tr.renderDepthImage, 
GL_DEPTH_ATTACHMENT_EXT, 0);
                R_CheckFBO(tr.sunRaysFbo);
        }
 
@@ -466,14 +323,8 @@ void FBO_Init(void)
                for( i = 0; i < MAX_DRAWN_PSHADOWS; i++)
                {
                        tr.pshadowFbos[i] = FBO_Create(va("_shadowmap%d", i), 
tr.pshadowMaps[i]->width, tr.pshadowMaps[i]->height);
-                       FBO_Bind(tr.pshadowFbos[i]);
-
-                       //FBO_CreateBuffer(tr.pshadowFbos[i], GL_RGBA8, 0, 0);
-                       FBO_AttachTextureImage(tr.pshadowMaps[i], 0);
-
+                       FBO_AttachImage(tr.pshadowFbos[i], tr.pshadowMaps[i], 
GL_COLOR_ATTACHMENT0_EXT, 0);
                        FBO_CreateBuffer(tr.pshadowFbos[i], 
GL_DEPTH_COMPONENT24_ARB, 0, 0);
-                       //R_AttachFBOTextureDepth(tr.textureDepthImage->texnum);
-
                        R_CheckFBO(tr.pshadowFbos[i]);
                }
        }
@@ -483,104 +334,64 @@ void FBO_Init(void)
                for ( i = 0; i < 4; i++)
                {
                        tr.sunShadowFbo[i] = FBO_Create("_sunshadowmap", 
tr.sunShadowDepthImage[i]->width, tr.sunShadowDepthImage[i]->height);
-                       FBO_Bind(tr.sunShadowFbo[i]);
-
-                       //FBO_CreateBuffer(tr.sunShadowFbo[i], GL_RGBA8, 0, 0);
-                       //FBO_AttachTextureImage(tr.sunShadowImage, 0);
-                       qglDrawBuffer(GL_NONE);
-                       qglReadBuffer(GL_NONE);
-
-                       //FBO_CreateBuffer(tr.sunShadowFbo, 
GL_DEPTH_COMPONENT24_ARB, 0, 0);
-                       
R_AttachFBOTextureDepth(tr.sunShadowDepthImage[i]->texnum);
-
+                       FBO_AttachImage(tr.sunShadowFbo[i], 
tr.sunShadowDepthImage[i], GL_DEPTH_ATTACHMENT_EXT, 0);
                        R_CheckFBO(tr.sunShadowFbo[i]);
-
                }
 
                tr.screenShadowFbo = FBO_Create("_screenshadow", 
tr.screenShadowImage->width, tr.screenShadowImage->height);
-               FBO_Bind(tr.screenShadowFbo);
-
-               FBO_AttachTextureImage(tr.screenShadowImage, 0);
-
+               FBO_AttachImage(tr.screenShadowFbo, tr.screenShadowImage, 
GL_COLOR_ATTACHMENT0_EXT, 0);
                R_CheckFBO(tr.screenShadowFbo);
        }
 
        for (i = 0; i < 2; i++)
        {
                tr.textureScratchFbo[i] = FBO_Create(va("_texturescratch%d", 
i), tr.textureScratchImage[i]->width, tr.textureScratchImage[i]->height);
-               FBO_Bind(tr.textureScratchFbo[i]);
-
-               //FBO_CreateBuffer(tr.textureScratchFbo[i], GL_RGBA8, 0, 0);
-               FBO_AttachTextureImage(tr.textureScratchImage[i], 0);
-
+               FBO_AttachImage(tr.textureScratchFbo[i], 
tr.textureScratchImage[i], GL_COLOR_ATTACHMENT0_EXT, 0);
                R_CheckFBO(tr.textureScratchFbo[i]);
        }
 
        {
                tr.calcLevelsFbo = FBO_Create("_calclevels", 
tr.calcLevelsImage->width, tr.calcLevelsImage->height);
-               FBO_Bind(tr.calcLevelsFbo);
-
-               //FBO_CreateBuffer(tr.calcLevelsFbo, hdrFormat, 0, 0);
-               FBO_AttachTextureImage(tr.calcLevelsImage, 0);
-
+               FBO_AttachImage(tr.calcLevelsFbo, tr.calcLevelsImage, 
GL_COLOR_ATTACHMENT0_EXT, 0);
                R_CheckFBO(tr.calcLevelsFbo);
        }
 
        {
                tr.targetLevelsFbo = FBO_Create("_targetlevels", 
tr.targetLevelsImage->width, tr.targetLevelsImage->height);
-               FBO_Bind(tr.targetLevelsFbo);
-
-               //FBO_CreateBuffer(tr.targetLevelsFbo, hdrFormat, 0, 0);
-               FBO_AttachTextureImage(tr.targetLevelsImage, 0);
-
+               FBO_AttachImage(tr.targetLevelsFbo, tr.targetLevelsImage, 
GL_COLOR_ATTACHMENT0_EXT, 0);
                R_CheckFBO(tr.targetLevelsFbo);
        }
 
        for (i = 0; i < 2; i++)
        {
                tr.quarterFbo[i] = FBO_Create(va("_quarter%d", i), 
tr.quarterImage[i]->width, tr.quarterImage[i]->height);
-               FBO_Bind(tr.quarterFbo[i]);
-
-               //FBO_CreateBuffer(tr.quarterFbo[i], hdrFormat, 0, 0);
-               FBO_AttachTextureImage(tr.quarterImage[i], 0);
-
+               FBO_AttachImage(tr.quarterFbo[i], tr.quarterImage[i], 
GL_COLOR_ATTACHMENT0_EXT, 0);
                R_CheckFBO(tr.quarterFbo[i]);
        }
 
        if (r_ssao->integer)
        {
                tr.hdrDepthFbo = FBO_Create("_hdrDepth", 
tr.hdrDepthImage->width, tr.hdrDepthImage->height);
-               FBO_Bind(tr.hdrDepthFbo);
-
-               FBO_AttachTextureImage(tr.hdrDepthImage, 0);
-
+               FBO_AttachImage(tr.hdrDepthFbo, tr.hdrDepthImage, 
GL_COLOR_ATTACHMENT0_EXT, 0);
                R_CheckFBO(tr.hdrDepthFbo);
 
                tr.screenSsaoFbo = FBO_Create("_screenssao", 
tr.screenSsaoImage->width, tr.screenSsaoImage->height);
-               FBO_Bind(tr.screenSsaoFbo);
-               
-               FBO_AttachTextureImage(tr.screenSsaoImage, 0);
-
+               FBO_AttachImage(tr.screenSsaoFbo, tr.screenSsaoImage, 
GL_COLOR_ATTACHMENT0_EXT, 0);
                R_CheckFBO(tr.screenSsaoFbo);
        }
 
        if (tr.renderCubeImage)
        {
                tr.renderCubeFbo = FBO_Create("_renderCubeFbo", 
tr.renderCubeImage->width, tr.renderCubeImage->height);
-               FBO_Bind(tr.renderCubeFbo);
-               
-               //FBO_AttachTextureImage(tr.renderCubeImage, 0);
-               R_AttachFBOTexture2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 
tr.renderCubeImage->texnum, 0);
-               glState.currentFBO->colorImage[0] = tr.renderCubeImage;
-
+               FBO_AttachImage(tr.renderCubeFbo, tr.renderCubeImage, 
GL_COLOR_ATTACHMENT0_EXT, 0);
                FBO_CreateBuffer(tr.renderCubeFbo, GL_DEPTH_COMPONENT24_ARB, 0, 
0);
-
                R_CheckFBO(tr.renderCubeFbo);
        }
 
        GL_CheckErrors();
 
-       FBO_Bind(NULL);
+       GL_BindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
+       glState.currentFBO = NULL;
 }
 
 /*
@@ -663,7 +474,10 @@ void FBO_BlitFromTexture(struct image_s *src, ivec4_t 
inSrcBox, vec2_t inSrcTexS
        int width, height;
 
        if (!src)
+       {
+               ri.Printf(PRINT_WARNING, "Tried to blit from a NULL 
texture!\n");
                return;
+       }
 
        if (inSrcBox)
        {
@@ -849,12 +663,12 @@ void FBO_FastBlit(FBO_t *src, ivec4_t srcBox, FBO_t *dst, 
ivec4_t dstBox, int bu
                VectorSet4(dstBoxFinal, dstBox[0], dstBox[1], dstBox[0] + 
dstBox[2], dstBox[1] + dstBox[3]);
        }
 
-       qglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, srcFb);
-       qglBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, dstFb);
+       GL_BindFramebuffer(GL_READ_FRAMEBUFFER_EXT, srcFb);
+       GL_BindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, dstFb);
        qglBlitFramebufferEXT(srcBoxFinal[0], srcBoxFinal[1], srcBoxFinal[2], 
srcBoxFinal[3],
                              dstBoxFinal[0], dstBoxFinal[1], dstBoxFinal[2], 
dstBoxFinal[3],
                                                  buffers, filter);
 
-       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+       GL_BindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
        glState.currentFBO = NULL;
 }
diff --git a/MP/code/rend2/tr_fbo.h b/MP/code/rend2/tr_fbo.h
index b5ab18c..3f23a35 100644
--- a/MP/code/rend2/tr_fbo.h
+++ b/MP/code/rend2/tr_fbo.h
@@ -52,6 +52,7 @@ typedef struct FBO_s
        int             height;
 } FBO_t;
 
+void FBO_AttachImage(FBO_t *fbo, image_t *image, GLenum attachment, GLuint 
cubemapside);
 void FBO_Bind(FBO_t *fbo);
 void FBO_Init(void);
 void FBO_Shutdown(void);
diff --git a/MP/code/rend2/tr_glsl.c b/MP/code/rend2/tr_glsl.c
index ce83a62..9cfa025 100644
--- a/MP/code/rend2/tr_glsl.c
+++ b/MP/code/rend2/tr_glsl.c
@@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  
02110-1301  USA
 // tr_glsl.c
 #include "tr_local.h"
 
-void GLSL_BindNullProgram(void);
+#include "tr_dsa.h"
 
 extern const char *fallbackShader_bokeh_vp;
 extern const char *fallbackShader_bokeh_fp;
@@ -328,17 +328,8 @@ static void GLSL_GetShaderHeader( GLenum shaderType, const 
GLcharARB *extra, cha
        Q_strcat(dest, size,
                         va("#ifndef r_FBufScale\n#define r_FBufScale vec2(%f, 
%f)\n#endif\n", fbufWidthScale, fbufHeightScale));
 
-       if (r_materialGamma->value != 1.0f)
-               Q_strcat(dest, size, va("#ifndef r_materialGamma\n#define 
r_materialGamma %f\n#endif\n", r_materialGamma->value));
-
-       if (r_lightGamma->value != 1.0f)
-               Q_strcat(dest, size, va("#ifndef r_lightGamma\n#define 
r_lightGamma %f\n#endif\n", r_lightGamma->value));
-
-       if (r_framebufferGamma->value != 1.0f)
-               Q_strcat(dest, size, va("#ifndef r_framebufferGamma\n#define 
r_framebufferGamma %f\n#endif\n", r_framebufferGamma->value));
-
-       if (r_tonemapGamma->value != 1.0f)
-               Q_strcat(dest, size, va("#ifndef r_tonemapGamma\n#define 
r_tonemapGamma %f\n#endif\n", r_tonemapGamma->value));
+       if (r_pbr->integer)
+               Q_strcat(dest, size, "#define USE_PBR\n");
 
        if (extra)
        {
@@ -488,11 +479,6 @@ static void GLSL_ShowProgramUniforms(GLhandleARB program)
        GLenum                  type;
        char            uniformName[1000];
 
-       // install the executables in the program object as part of current 
state.
-       qglUseProgramObjectARB(program);
-
-       // check for GL Errors
-
        // query the number of active uniforms
        qglGetObjectParameterivARB(program, GL_OBJECT_ACTIVE_UNIFORMS_ARB, 
&count);
 
@@ -503,8 +489,6 @@ static void GLSL_ShowProgramUniforms(GLhandleARB program)
 
                ri.Printf(PRINT_DEVELOPER, "active uniform: '%s'\n", 
uniformName);
        }
-
-       qglUseProgramObjectARB(0);
 }
 
 static int GLSL_InitGPUShader2(shaderProgram_t * program, const char *name, 
int attribs, const char *vpCode, const char *fpCode)
@@ -709,7 +693,7 @@ void GLSL_SetUniformInt(shaderProgram_t *program, int 
uniformNum, GLint value)
 
        *compare = value;
 
-       qglUniform1iARB(uniforms[uniformNum], value);
+       qglProgramUniform1i(program->program, uniforms[uniformNum], value);
 }
 
 void GLSL_SetUniformFloat(shaderProgram_t *program, int uniformNum, GLfloat 
value)
@@ -733,7 +717,7 @@ void GLSL_SetUniformFloat(shaderProgram_t *program, int 
uniformNum, GLfloat valu
 
        *compare = value;
        
-       qglUniform1fARB(uniforms[uniformNum], value);
+       qglProgramUniform1f(program->program, uniforms[uniformNum], value);
 }
 
 void GLSL_SetUniformVec2(shaderProgram_t *program, int uniformNum, const 
vec2_t v)
@@ -758,7 +742,7 @@ void GLSL_SetUniformVec2(shaderProgram_t *program, int 
uniformNum, const vec2_t
        compare[0] = v[0];
        compare[1] = v[1];
 
-       qglUniform2fARB(uniforms[uniformNum], v[0], v[1]);
+       qglProgramUniform2f(program->program, uniforms[uniformNum], v[0], v[1]);
 }
 
 void GLSL_SetUniformVec3(shaderProgram_t *program, int uniformNum, const 
vec3_t v)
@@ -782,7 +766,7 @@ void GLSL_SetUniformVec3(shaderProgram_t *program, int 
uniformNum, const vec3_t
 
        VectorCopy(v, compare);
 
-       qglUniform3fARB(uniforms[uniformNum], v[0], v[1], v[2]);
+       qglProgramUniform3f(program->program, uniforms[uniformNum], v[0], v[1], 
v[2]);
 }
 
 void GLSL_SetUniformVec4(shaderProgram_t *program, int uniformNum, const 
vec4_t v)
@@ -806,7 +790,7 @@ void GLSL_SetUniformVec4(shaderProgram_t *program, int 
uniformNum, const vec4_t
 
        VectorCopy4(v, compare);
 
-       qglUniform4fARB(uniforms[uniformNum], v[0], v[1], v[2], v[3]);
+       qglProgramUniform4f(program->program, uniforms[uniformNum], v[0], v[1], 
v[2], v[3]);
 }
 
 void GLSL_SetUniformFloat5(shaderProgram_t *program, int uniformNum, const 
vec5_t v)
@@ -830,7 +814,7 @@ void GLSL_SetUniformFloat5(shaderProgram_t *program, int 
uniformNum, const vec5_
 
        VectorCopy5(v, compare);
 
-       qglUniform1fvARB(uniforms[uniformNum], 5, v);
+       qglProgramUniform1fv(program->program, uniforms[uniformNum], 5, v);
 }
 
 void GLSL_SetUniformMat4(shaderProgram_t *program, int uniformNum, const 
mat4_t matrix)
@@ -854,7 +838,7 @@ void GLSL_SetUniformMat4(shaderProgram_t *program, int 
uniformNum, const mat4_t
 
        Mat4Copy(matrix, compare);
 
-       qglUniformMatrix4fvARB(uniforms[uniformNum], 1, GL_FALSE, matrix);
+       qglProgramUniformMatrix4fv(program->program, uniforms[uniformNum], 1, 
GL_FALSE, matrix);
 }
 
 void GLSL_DeleteGPUShader(shaderProgram_t *program)
@@ -937,10 +921,8 @@ void GLSL_InitGPUShaders(void)
 
                GLSL_InitUniforms(&tr.genericShader[i]);
 
-               qglUseProgramObjectARB(tr.genericShader[i].program);
                GLSL_SetUniformInt(&tr.genericShader[i], UNIFORM_DIFFUSEMAP, 
TB_DIFFUSEMAP);
                GLSL_SetUniformInt(&tr.genericShader[i], UNIFORM_LIGHTMAP,   
TB_LIGHTMAP);
-               qglUseProgramObjectARB(0);
 
                GLSL_FinishGPUShader(&tr.genericShader[i]);
 
@@ -957,9 +939,7 @@ void GLSL_InitGPUShaders(void)
        
        GLSL_InitUniforms(&tr.textureColorShader);
 
-       qglUseProgramObjectARB(tr.textureColorShader.program);
        GLSL_SetUniformInt(&tr.textureColorShader, UNIFORM_TEXTUREMAP, 
TB_DIFFUSEMAP);
-       qglUseProgramObjectARB(0);
 
        GLSL_FinishGPUShader(&tr.textureColorShader);
 
@@ -1011,9 +991,7 @@ void GLSL_InitGPUShaders(void)
 
                GLSL_InitUniforms(&tr.dlightShader[i]);
                
-               qglUseProgramObjectARB(tr.dlightShader[i].program);
                GLSL_SetUniformInt(&tr.dlightShader[i], UNIFORM_DIFFUSEMAP, 
TB_DIFFUSEMAP);
-               qglUseProgramObjectARB(0);
 
                GLSL_FinishGPUShader(&tr.dlightShader[i]);
 
@@ -1040,12 +1018,6 @@ void GLSL_InitGPUShaders(void)
 
                extradefines[0] = '\0';
 
-               if (r_specularIsMetallic->value)
-                       Q_strcat(extradefines, 1024, "#define 
SPECULAR_IS_METALLIC\n");
-
-               if (r_glossIsRoughness->value)
-                       Q_strcat(extradefines, 1024, "#define 
GLOSS_IS_ROUGHNESS\n");
-
                if (r_dlightMode->integer >= 2)
                        Q_strcat(extradefines, 1024, "#define USE_SHADOWMAP\n");
 
@@ -1141,7 +1113,6 @@ void GLSL_InitGPUShaders(void)
 
                GLSL_InitUniforms(&tr.lightallShader[i]);
 
-               qglUseProgramObjectARB(tr.lightallShader[i].program);
                GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_DIFFUSEMAP,  
TB_DIFFUSEMAP);
                GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_LIGHTMAP,    
TB_LIGHTMAP);
                GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_NORMALMAP,   
TB_NORMALMAP);
@@ -1149,7 +1120,6 @@ void GLSL_InitGPUShaders(void)
                GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_SPECULARMAP, 
TB_SPECULARMAP);
                GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_SHADOWMAP,   
TB_SHADOWMAP);
                GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_CUBEMAP,     
TB_CUBEMAP);
-               qglUseProgramObjectARB(0);
 
                GLSL_FinishGPUShader(&tr.lightallShader[i]);
 
@@ -1182,9 +1152,7 @@ void GLSL_InitGPUShaders(void)
        
        GLSL_InitUniforms(&tr.pshadowShader);
 
-       qglUseProgramObjectARB(tr.pshadowShader.program);
        GLSL_SetUniformInt(&tr.pshadowShader, UNIFORM_SHADOWMAP, TB_DIFFUSEMAP);
-       qglUseProgramObjectARB(0);
 
        GLSL_FinishGPUShader(&tr.pshadowShader);
 
@@ -1201,9 +1169,7 @@ void GLSL_InitGPUShaders(void)
        
        GLSL_InitUniforms(&tr.down4xShader);
 
-       qglUseProgramObjectARB(tr.down4xShader.program);
        GLSL_SetUniformInt(&tr.down4xShader, UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP);
-       qglUseProgramObjectARB(0);
 
        GLSL_FinishGPUShader(&tr.down4xShader);
 
@@ -1220,9 +1186,7 @@ void GLSL_InitGPUShaders(void)
 
        GLSL_InitUniforms(&tr.bokehShader);
 
-       qglUseProgramObjectARB(tr.bokehShader.program);
        GLSL_SetUniformInt(&tr.bokehShader, UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP);
-       qglUseProgramObjectARB(0);
 
        GLSL_FinishGPUShader(&tr.bokehShader);
 
@@ -1239,10 +1203,8 @@ void GLSL_InitGPUShaders(void)
 
        GLSL_InitUniforms(&tr.tonemapShader);
 
-       qglUseProgramObjectARB(tr.tonemapShader.program);
        GLSL_SetUniformInt(&tr.tonemapShader, UNIFORM_TEXTUREMAP, TB_COLORMAP);
        GLSL_SetUniformInt(&tr.tonemapShader, UNIFORM_LEVELSMAP,  TB_LEVELSMAP);
-       qglUseProgramObjectARB(0);
 
        GLSL_FinishGPUShader(&tr.tonemapShader);
 
@@ -1264,9 +1226,7 @@ void GLSL_InitGPUShaders(void)
 
                GLSL_InitUniforms(&tr.calclevels4xShader[i]);
 
-               qglUseProgramObjectARB(tr.calclevels4xShader[i].program);
                GLSL_SetUniformInt(&tr.calclevels4xShader[i], 
UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP);
-               qglUseProgramObjectARB(0);
 
                GLSL_FinishGPUShader(&tr.calclevels4xShader[i]);
 
@@ -1297,13 +1257,11 @@ void GLSL_InitGPUShaders(void)
        
        GLSL_InitUniforms(&tr.shadowmaskShader);
 
-       qglUseProgramObjectARB(tr.shadowmaskShader.program);
        GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SCREENDEPTHMAP, 
TB_COLORMAP);
        GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP,  
TB_SHADOWMAP);
        GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP2, 
TB_SHADOWMAP2);
        GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP3, 
TB_SHADOWMAP3);
        GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP4, 
TB_SHADOWMAP4);
-       qglUseProgramObjectARB(0);
 
        GLSL_FinishGPUShader(&tr.shadowmaskShader);
 
@@ -1320,9 +1278,7 @@ void GLSL_InitGPUShaders(void)
 
        GLSL_InitUniforms(&tr.ssaoShader);
 
-       qglUseProgramObjectARB(tr.ssaoShader.program);
        GLSL_SetUniformInt(&tr.ssaoShader, UNIFORM_SCREENDEPTHMAP, TB_COLORMAP);
-       qglUseProgramObjectARB(0);
 
        GLSL_FinishGPUShader(&tr.ssaoShader);
 
@@ -1347,10 +1303,8 @@ void GLSL_InitGPUShaders(void)
                
                GLSL_InitUniforms(&tr.depthBlurShader[i]);
 
-               qglUseProgramObjectARB(tr.depthBlurShader[i].program);
                GLSL_SetUniformInt(&tr.depthBlurShader[i], 
UNIFORM_SCREENIMAGEMAP, TB_COLORMAP);
                GLSL_SetUniformInt(&tr.depthBlurShader[i], 
UNIFORM_SCREENDEPTHMAP, TB_LIGHTMAP);
-               qglUseProgramObjectARB(0);
 
                GLSL_FinishGPUShader(&tr.depthBlurShader[i]);
 
@@ -1368,9 +1322,7 @@ void GLSL_InitGPUShaders(void)
 
        GLSL_InitUniforms(&tr.testcubeShader);
 
-       qglUseProgramObjectARB(tr.testcubeShader.program);
        GLSL_SetUniformInt(&tr.testcubeShader, UNIFORM_TEXTUREMAP, TB_COLORMAP);
-       qglUseProgramObjectARB(0);
 
        GLSL_FinishGPUShader(&tr.testcubeShader);
 
@@ -1394,7 +1346,7 @@ void GLSL_ShutdownGPUShaders(void)
        for (i = 0; i < ATTR_INDEX_COUNT; i++)
                qglDisableVertexAttribArrayARB(i);
 
-       GLSL_BindNullProgram();
+       GL_BindNullProgram();
 
        for ( i = 0; i < GENERICDEF_COUNT; i++)
                GLSL_DeleteGPUShader(&tr.genericShader[i]);
@@ -1424,49 +1376,25 @@ void GLSL_ShutdownGPUShaders(void)
 
        for ( i = 0; i < 2; i++)
                GLSL_DeleteGPUShader(&tr.depthBlurShader[i]);
-
-       glState.currentProgram = 0;
-       qglUseProgramObjectARB(0);
 }
 
 
 void GLSL_BindProgram(shaderProgram_t * program)
 {
-       if(!program)
-       {
-               GLSL_BindNullProgram();
-               return;
-       }
+       GLuint programObject = program ? program->program : 0;
+       char *name = program ? program->name : "NULL";
 
        if(r_logFile->integer)
        {
                // don't just call LogComment, or we will get a call to va() 
every frame!
-               GLimp_LogComment(va("--- GL_BindProgram( %s ) ---\n", 
program->name));
+               GLimp_LogComment(va("--- GLSL_BindProgram( %s ) ---\n", name));
        }
 
-       if(glState.currentProgram != program)
-       {
-               qglUseProgramObjectARB(program->program);
-               glState.currentProgram = program;
+       if (GL_UseProgramObject(programObject))
                backEnd.pc.c_glslShaderBinds++;
-       }
 }
 
 
-void GLSL_BindNullProgram(void)
-{
-       if(r_logFile->integer)
-       {
-               GLimp_LogComment("--- GL_BindNullProgram ---\n");
-       }
-
-       if(glState.currentProgram)
-       {
-               qglUseProgramObjectARB(0);
-               glState.currentProgram = NULL;
-       }
-}
-
 
 shaderProgram_t *GLSL_GetGenericShaderProgram(int stage, glfog_t *glFog)
 {
diff --git a/MP/code/rend2/tr_image.c b/MP/code/rend2/tr_image.c
index 0b01a25..65cde8e 100644
--- a/MP/code/rend2/tr_image.c
+++ b/MP/code/rend2/tr_image.c
@@ -35,6 +35,7 @@ If you have questions concerning this license or the 
applicable additional terms
 
 #include "tr_local.h"
 
+#include "tr_dsa.h"
 
 static byte s_intensitytable[256];
 static unsigned char s_gammatable[256];
@@ -132,9 +133,8 @@ void GL_TextureMode( const char *string ) {
        for ( i = 0 ; i < tr.numImages ; i++ ) {
                glt = tr.images[ i ];
                if ( glt->flags & IMGFLAG_MIPMAP ) {
-                       GL_Bind( glt );
-                       qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 
gl_filter_min );
-                       qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 
gl_filter_max );
+                       qglTextureParameterf(glt->texnum, GL_TEXTURE_2D, 
GL_TEXTURE_MIN_FILTER, gl_filter_min);
+                       qglTextureParameterf(glt->texnum, GL_TEXTURE_2D, 
GL_TEXTURE_MAG_FILTER, gl_filter_max);
                }
        }
 }
@@ -1979,7 +1979,7 @@ static void CompressMonoBlock(byte outdata[8], const byte 
indata[16])
        }
 }
 
-static void RawImage_UploadToRgtc2Texture(byte *data, int width, int height, 
int mip)
+static void RawImage_UploadToRgtc2Texture(GLuint texture, byte *data, int 
width, int height, int mip)
 {
        int wBlocks, hBlocks, y, x, size;
        byte *compressedData, *p;
@@ -2019,86 +2019,61 @@ static void RawImage_UploadToRgtc2Texture(byte *data, 
int width, int height, int
                }
        }
 
-       qglCompressedTexImage2DARB(GL_TEXTURE_2D, mip, GL_COMPRESSED_RG_RGTC2, 
width, height, 0, size, compressedData);
+       qglCompressedTextureImage2D(texture, GL_TEXTURE_2D, mip, 
GL_COMPRESSED_RG_RGTC2, width, height, 0, size, compressedData);
 
        ri.Hunk_FreeTempMemory(compressedData);
 }
 
-static void RawImage_UploadTexture( byte *data, int x, int y, int width, int 
height, GLenum picFormat, int numMips, GLenum internalFormat, imgType_t type, 
imgFlags_t flags, qboolean subtexture )
+static int CalculateMipSize(int width, int height, GLenum picFormat)
 {
-       int dataFormat, dataType;
-       qboolean rgtc = (internalFormat == GL_COMPRESSED_RG_RGTC2);
+       int numBlocks = ((width + 3) / 4) * ((height + 3) / 4);
+       int numPixels = width * height;
 
-       if (data && picFormat != GL_RGBA8 && picFormat != GL_SRGB8_ALPHA8_EXT)
+       switch (picFormat)
        {
-               int bytesPer4x4Block = 0;
-               int miplevel = 0;
-
-               switch (picFormat)
-               {
-                       case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
-                       case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
-                       case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-                       case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
-                       case GL_COMPRESSED_RED_RGTC1:
-                       case GL_COMPRESSED_SIGNED_RED_RGTC1:
-                               bytesPer4x4Block = 8;
-                               break;
-                       case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
-                       case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
-                       case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
-                       case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
-                       case GL_COMPRESSED_RG_RGTC2:
-                       case GL_COMPRESSED_SIGNED_RG_RGTC2:
-                       case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB:
-                       case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB:
-                       case GL_COMPRESSED_RGBA_BPTC_UNORM_ARB:
-                       case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB:
-                               bytesPer4x4Block = 16;
-                               break;
-                       default:
-                               ri.Printf(PRINT_ALL, "Unsupported texture 
format %08x\n", picFormat);
-                               return;
-                               break;
-               }
-
-               if (flags & IMGFLAG_PICMIP)
-               {
-                       for (miplevel = r_picmip->integer; miplevel > 0 && 
numMips > 1; miplevel--, numMips--)
-                       {
-                               int size = ((width + 3) / 4) * ((height + 3) / 
4) * bytesPer4x4Block;
-
-                               x >>= 1;
-                               y >>= 1;
-                               width = MAX(1, width >> 1);
-                               height = MAX(1, height >> 1);
-                               data += size;
-                       }
-               }
+               case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+               case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+               case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+               case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+               case GL_COMPRESSED_RED_RGTC1:
+               case GL_COMPRESSED_SIGNED_RED_RGTC1:
+                       return numBlocks * 8;
 
-               if (!(flags & IMGFLAG_MIPMAP))
-                       numMips = 1;
+               case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+               case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+               case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+               case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+               case GL_COMPRESSED_RG_RGTC2:
+               case GL_COMPRESSED_SIGNED_RG_RGTC2:
+               case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB:
+               case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB:
+               case GL_COMPRESSED_RGBA_BPTC_UNORM_ARB:
+               case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB:
+                       return numBlocks * 16;
 
-               for (miplevel = 0; miplevel < numMips; miplevel++)
-               {
-                       int size = ((width + 3) / 4) * ((height + 3) / 4) * 
bytesPer4x4Block;
+               case GL_RGBA8:
+               case GL_SRGB8_ALPHA8_EXT:
+                       return numPixels * 4;
 
-                       if (subtexture)
-                               qglCompressedTexSubImage2DARB(GL_TEXTURE_2D, 
miplevel, x, y, width, height, internalFormat, size, data);
-                       else
-                               qglCompressedTexImage2DARB(GL_TEXTURE_2D, 
miplevel, internalFormat, width, height, 0, size, data);
+               default:
+                       ri.Printf(PRINT_ALL, "Unsupported texture format 
%08x\n", picFormat);
+                       return 0;
+       }
 
-                       x >>= 1;
-                       y >>= 1;
-                       width  = MAX(1, width >> 1);
-                       height = MAX(1, height >> 1);
-                       data += size;
-               }
+       return 0;
+}
 
-               return;
-       }
+static void RawImage_UploadTexture(GLuint texture, byte *data, int x, int y, 
int width, int height, GLenum target, GLenum picFormat, int numMips, GLenum 
internalFormat, imgType_t type, imgFlags_t flags, qboolean subtexture )
+{
+       int dataFormat, dataType;
+       qboolean rgtc = (internalFormat == GL_COMPRESSED_RG_RGTC2);
+       qboolean compressed = (!(picFormat == GL_RGBA8) || (picFormat == 
GL_SRGB8_ALPHA8_EXT));
+       qboolean mipmap = !!(flags & IMGFLAG_MIPMAP);
+       qboolean picmip = !!(flags & IMGFLAG_PICMIP);
+       int size, miplevel;
+       qboolean lastMip = qfalse;
 
-       switch(internalFormat)
+       switch (internalFormat)
        {
                case GL_DEPTH_COMPONENT:
                case GL_DEPTH_COMPONENT16_ARB:
@@ -2117,52 +2092,83 @@ static void RawImage_UploadTexture( byte *data, int x, 
int y, int width, int hei
                        break;
        }
 
-       if ( subtexture )
-               qglTexSubImage2D( GL_TEXTURE_2D, 0, x, y, width, height, 
dataFormat, dataType, data );
-       else
+       if (!data)
        {
-               if (rgtc)
-                       RawImage_UploadToRgtc2Texture(data, width, height, 0);
-               else
-                       qglTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, 
height, 0, dataFormat, dataType, data);
+               miplevel = 0;
+               do
+               {
+                       lastMip = (width == 1 && height == 1) || !mipmap;
+                       qglTextureImage2D(texture, target, miplevel, 
internalFormat, width, height, 0, dataFormat, dataType, NULL);
+
+                       width = MAX(1, width >> 1);
+                       height = MAX(1, height >> 1);
+                       miplevel++;
+               }
+               while (!lastMip);
+
+               return;
        }
 
-       if (flags & IMGFLAG_MIPMAP)
+       if (compressed && picmip)
        {
-               int miplevel = 0;
-
-               while (width > 1 || height > 1)
+               for (miplevel = r_picmip->integer; miplevel > 0 && numMips > 1; 
miplevel--, numMips--)
                {
-                       if (data)
-                       {
-                               if (type == IMGTYPE_NORMAL || type == 
IMGTYPE_NORMALHEIGHT)
-                                       R_MipMapNormalHeight( data, data, 
width, height, glRefConfig.swizzleNormalmap );
-                               else
-                                       R_MipMapsRGB( data, width, height );
-                       }
-                       
+                       size = CalculateMipSize(width, height, picFormat);
+                       x >>= 1;
+                       y >>= 1;
                        width = MAX(1, width >> 1);
                        height = MAX(1, height >> 1);
-                       miplevel++;
+                       data += size;
+               }
+       }
 
-                       if ( data && r_colorMipLevels->integer )
-                               R_BlendOverTexture( (byte *)data, width * 
height, mipBlendColors[miplevel] );
+       miplevel = 0;
+       do
+       {
+               lastMip = (width == 1 && height == 1) || !mipmap;
+               size = CalculateMipSize(width, height, picFormat);
 
-                       if ( subtexture )
-                       {
-                               x >>= 1;
-                               y >>= 1;
-                               qglTexSubImage2D( GL_TEXTURE_2D, miplevel, x, 
y, width, height, dataFormat, dataType, data );
-                       }
+               if (compressed)
+               {
+                       if (subtexture)
+                               qglCompressedTextureSubImage2D(texture, target, 
miplevel, x, y, width, height, picFormat, size, data);
                        else
+                               qglCompressedTextureImage2D(texture, target, 
miplevel, picFormat, width, height, 0, size, data);
+               }
+               else
+               {
+                       if (miplevel != 0 && r_colorMipLevels->integer)
+                               R_BlendOverTexture((byte *)data, width * 
height, mipBlendColors[miplevel]);
+
+                       if (rgtc)
+                               RawImage_UploadToRgtc2Texture(texture, data, 
width, height, miplevel);
+                       else if (subtexture)
+                               qglTextureSubImage2D(texture, target, miplevel, 
x, y, width, height, dataFormat, dataType, data);
+                       else
+                               qglTextureImage2D(texture, target, miplevel, 
internalFormat, width, height, 0, dataFormat, dataType, data);
+
+                       if (!lastMip && numMips < 2)
                        {
-                               if (rgtc)
-                                       RawImage_UploadToRgtc2Texture(data, 
width, height, miplevel);
+                               if (type == IMGTYPE_NORMAL || type == 
IMGTYPE_NORMALHEIGHT)
+                                       R_MipMapNormalHeight(data, data, width, 
height, glRefConfig.swizzleNormalmap);
                                else
-                                       qglTexImage2D(GL_TEXTURE_2D, miplevel, 
internalFormat, width, height, 0, dataFormat, dataType, data);
+                                       R_MipMapsRGB(data, width, height);
                        }
                }
+
+               x >>= 1;
+               y >>= 1;
+               width = MAX(1, width >> 1);
+               height = MAX(1, height >> 1);
+               miplevel++;
+
+               if (numMips > 1)
+               {
+                       data += size;
+                       numMips--;
+               }
        }
+       while (!lastMip);
 }
 
 /*
@@ -2196,19 +2202,35 @@ static void Upload32(byte *data, int x, int y, int 
width, int height, GLenum pic
        GLenum internalFormat = image->internalFormat;
        qboolean subtexture = (x != 0) || (y != 0) || (width != image->width) 
|| (height != image->height);
        qboolean notScaled = qtrue;
-       qboolean mipmap = !!(flags & IMGFLAG_MIPMAP);
+       qboolean compressed = (picFormat != GL_RGBA8 && picFormat != 
GL_SRGB8_ALPHA8_EXT);
+       qboolean mipmap = !!(flags & IMGFLAG_MIPMAP) && (!compressed || numMips 
> 1);
+       qboolean cubemap = !!(flags & IMGFLAG_CUBEMAP);
+       GLenum uploadTarget = cubemap ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : 
GL_TEXTURE_2D;
+       GLenum textureTarget = cubemap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
+       int depth = cubemap ? 6 : 1;
 
        if (!data)
        {
                RawImage_ScaleToPower2(NULL, &width, &height, type, flags, 
NULL);
-               RawImage_UploadTexture(NULL, 0, 0, width, height, GL_RGBA8, 0, 
internalFormat, type, flags, qfalse);
+               for (i = 0; i < depth; i++)
+                       RawImage_UploadTexture(image->texnum, NULL, 0, 0, 
width, height, uploadTarget + i, GL_RGBA8, 0, internalFormat, type, flags, 
qfalse);
                goto done;
        }
        else if (!subtexture)
        {
-               if (picFormat != GL_RGBA8 && picFormat != GL_SRGB8_ALPHA8_EXT)
+               if (compressed || cubemap)
                {
-                       RawImage_UploadTexture(data, 0, 0, width, height, 
picFormat, numMips, internalFormat, type, flags, qfalse);
+                       for (i = 0; i < depth; i++)
+                       {
+                               int w2 = width, h2 = height;
+                               RawImage_UploadTexture(image->texnum, data, 0, 
0, width, height, uploadTarget + i, picFormat, numMips, internalFormat, type, 
flags, qfalse);
+                               for (c = numMips; c; c--)
+                               {
+                                       data += CalculateMipSize(w2, h2, 
picFormat);
+                                       w2 = MAX(1, w2 >> 1);
+                                       h2 = MAX(1, h2 >> 1);
+                               }
+                       }
                        goto done;
                }
                notScaled = RawImage_ScaleToPower2(&data, &width, &height, 
type, flags, &resampledBuffer);
@@ -2248,12 +2270,12 @@ static void Upload32(byte *data, int x, int y, int 
width, int height, GLenum pic
        if (subtexture)
        {
                // FIXME: Incorrect if original texture was not a power of 2 
texture or picmipped
-               RawImage_UploadTexture(data, x, y, width, height, GL_RGBA8, 0, 
internalFormat, type, flags, qtrue);
+               RawImage_UploadTexture(image->texnum, data, x, y, width, 
height, uploadTarget, GL_RGBA8, 0, internalFormat, type, flags, qtrue);
                GL_CheckErrors();
                return;
        }
 
-       RawImage_UploadTexture(data, 0, 0, width, height, GL_RGBA8, 0, 
internalFormat, type, flags, qfalse);
+       RawImage_UploadTexture(image->texnum, data, 0, 0, width, height, 
uploadTarget, GL_RGBA8, 0, internalFormat, type, flags, qfalse);
 
 done:
 
@@ -2262,20 +2284,20 @@ done:
 
        if (mipmap)
        {
-               if ( textureFilterAnisotropic )
-                       qglTexParameteri( GL_TEXTURE_2D, 
GL_TEXTURE_MAX_ANISOTROPY_EXT,
-                                       (GLint)Com_Clamp( 1, maxAnisotropy, 
r_ext_max_anisotropy->integer ) );
+               if (textureFilterAnisotropic && !cubemap)
+                       qglTextureParameteri(image->texnum, textureTarget, 
GL_TEXTURE_MAX_ANISOTROPY_EXT,
+                       (GLint)Com_Clamp(1, maxAnisotropy, 
r_ext_max_anisotropy->integer));
 
-               qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 
gl_filter_min);
-               qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 
gl_filter_max);
+               qglTextureParameterf(image->texnum, textureTarget, 
GL_TEXTURE_MIN_FILTER, gl_filter_min);
+               qglTextureParameterf(image->texnum, textureTarget, 
GL_TEXTURE_MAG_FILTER, gl_filter_max);
        }
        else
        {
-               if ( textureFilterAnisotropic )
-                       qglTexParameteri( GL_TEXTURE_2D, 
GL_TEXTURE_MAX_ANISOTROPY_EXT, 1 );
+               if (textureFilterAnisotropic && !cubemap)
+                       qglTextureParameteri(image->texnum, textureTarget, 
GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
 
-               qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 
GL_LINEAR );
-               qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 
GL_LINEAR );
+               qglTextureParameterf(image->texnum, textureTarget, 
GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+               qglTextureParameterf(image->texnum, textureTarget, 
GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        }
 
        // Fix for sampling depth buffer on old nVidia cards
@@ -2286,9 +2308,9 @@ done:
                case GL_DEPTH_COMPONENT16_ARB:
                case GL_DEPTH_COMPONENT24_ARB:
                case GL_DEPTH_COMPONENT32_ARB:
-                       qglTexParameterf(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, 
GL_LUMINANCE );
-                       qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 
GL_NEAREST );
-                       qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 
GL_NEAREST );
+                       qglTextureParameterf(image->texnum, textureTarget, 
GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);
+                       qglTextureParameterf(image->texnum, textureTarget, 
GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+                       qglTextureParameterf(image->texnum, textureTarget, 
GL_TEXTURE_MAG_FILTER, GL_NEAREST);
                        break;
                default:
                        break;
@@ -2341,68 +2363,24 @@ image_t *R_CreateImage2( const char *name, byte *pic, 
int width, int height, GLe
                glWrapClampMode = GL_REPEAT;
 
        if (!internalFormat)
-       {
-               if (image->flags & IMGFLAG_CUBEMAP)
-                       internalFormat = GL_RGBA8;
-               else
-                       internalFormat = RawImage_GetFormat(pic, width * 
height, picFormat, isLightmap, image->type, image->flags);
-       }
+               internalFormat = RawImage_GetFormat(pic, width * height, 
picFormat, isLightmap, image->type, image->flags);
 
        image->internalFormat = internalFormat;
 
-       // lightmaps are always allocated on TMU 1
-       if ( qglActiveTextureARB && isLightmap ) {
-               image->TMU = 1;
-       } else {
-               image->TMU = 0;
-       }
-
-       if ( qglActiveTextureARB ) {
-               GL_SelectTexture( image->TMU );
-       }
-
-       GL_Bind(image);
+       Upload32(pic, 0, 0, image->width, image->height, picFormat, numMips, 
image);
 
        if (image->flags & IMGFLAG_CUBEMAP)
        {
-               qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, 
GL_CLAMP_TO_EDGE);
-               qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, 
GL_CLAMP_TO_EDGE);
-               qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, 
GL_CLAMP_TO_EDGE);
-
-               qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, 
GL_LINEAR);
-
-               if (image->flags & IMGFLAG_MIPMAP)
-               {
-                       qglTexParameteri(GL_TEXTURE_CUBE_MAP, 
GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
-               }
-               else
-               {
-                       qglTexParameteri(GL_TEXTURE_CUBE_MAP, 
GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-               }
-
-               qglTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA8, 
width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
-               qglTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA8, 
width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
-               qglTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA8, 
width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
-               qglTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA8, 
width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
-               qglTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA8, 
width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
-               qglTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA8, 
width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
-
-               if (image->flags & IMGFLAG_MIPMAP)
-                       qglGenerateMipmapEXT(GL_TEXTURE_CUBE_MAP);
-
-               image->uploadWidth = width;
-               image->uploadHeight = height;
+               qglTextureParameterf(image->texnum, GL_TEXTURE_CUBE_MAP, 
GL_TEXTURE_WRAP_S, glWrapClampMode);
+               qglTextureParameterf(image->texnum, GL_TEXTURE_CUBE_MAP, 
GL_TEXTURE_WRAP_T, glWrapClampMode);
+               qglTextureParameteri(image->texnum, GL_TEXTURE_CUBE_MAP, 
GL_TEXTURE_WRAP_R, glWrapClampMode);
        }
        else
        {
-               Upload32( pic, 0, 0, image->width, image->height, picFormat, 
numMips, image );
-
-               qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 
glWrapClampMode );
-               qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 
glWrapClampMode );
+               qglTextureParameterf(image->texnum, GL_TEXTURE_2D, 
GL_TEXTURE_WRAP_S, glWrapClampMode);
+               qglTextureParameterf(image->texnum, GL_TEXTURE_2D, 
GL_TEXTURE_WRAP_T, glWrapClampMode);
        }
 
-       GL_SelectTexture( 0 );
-
        hash = generateHashValue( name );
        image->next = hashTable[hash];
        hashTable[hash] = image;
@@ -2427,15 +2405,7 @@ image_t *R_CreateImage(const char *name, byte *pic, int 
width, int height, imgTy
 
 void R_UpdateSubImage( image_t *image, byte *pic, int x, int y, int width, int 
height )
 {
-       if (qglActiveTextureARB) {
-               GL_SelectTexture(image->TMU);
-       }
-
-       GL_Bind(image);
-
        Upload32(pic, x, y, width, height, GL_RGBA8, 0, image);
-
-       GL_SelectTexture(0);
 }
 
 //===================================================================
@@ -2579,6 +2549,7 @@ image_t   *R_FindImageFile( const char *name, imgType_t 
type, imgFlags_t flags )
        GLenum  picFormat;
        int picNumMips;
        long hash;
+       imgFlags_t checkFlagsTrue, checkFlagsFalse;
 
        if ( !name ) {
                return NULL;
@@ -2609,7 +2580,10 @@ image_t  *R_FindImageFile( const char *name, imgType_t 
type, imgFlags_t flags )
                return NULL;
        }
 
-       if (r_normalMapping->integer && (picFormat == GL_RGBA8) && !(type == 
IMGTYPE_NORMAL) && (flags & IMGFLAG_PICMIP) && (flags & IMGFLAG_MIPMAP) && 
(flags & IMGFLAG_GENNORMALMAP))
+       checkFlagsTrue = IMGFLAG_PICMIP | IMGFLAG_MIPMAP | IMGFLAG_GENNORMALMAP;
+       checkFlagsFalse = IMGFLAG_CUBEMAP;
+       if (r_normalMapping->integer && (picFormat == GL_RGBA8) && (type == 
IMGTYPE_COLORALPHA) &&
+               ((flags & checkFlagsTrue) == checkFlagsTrue) && !(flags & 
checkFlagsFalse))
        {
                char normalName[MAX_QPATH];
                image_t *normalImage;
@@ -2712,6 +2686,20 @@ image_t  *R_FindImageFile( const char *name, imgType_t 
type, imgFlags_t flags )
                }
        }
 
+       // force mipmaps off if image is compressed but doesn't have enough mips
+       if ((flags & IMGFLAG_MIPMAP) && picFormat != GL_RGBA8 && picFormat != 
GL_SRGB8_ALPHA8_EXT)
+       {
+               int wh = MAX(width, height);
+               int neededMips = 0;
+               while (wh)
+               {
+                       neededMips++;
+                       wh >>= 1;
+               }
+               if (neededMips > picNumMips)
+                       flags &= ~IMGFLAG_MIPMAP;
+       }
+
        image = R_CreateImage2( ( char * ) name, pic, width, height, picFormat, 
picNumMips, type, flags, 0 );
        ri.Free( pic );
        return image;
@@ -3002,11 +2990,10 @@ void R_CreateBuiltinImages( void ) {
                        for ( x = 0; x < 4; x++)
                        {
                                tr.sunShadowDepthImage[x] = 
R_CreateImage(va("*sunshadowdepth%i", x), NULL, r_shadowMapSize->integer, 
r_shadowMapSize->integer, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | 
IMGFLAG_CLAMPTOEDGE, GL_DEPTH_COMPONENT24_ARB);
-                               GL_Bind(tr.sunShadowDepthImage[x]);
-                               qglTexParameterf(GL_TEXTURE_2D, 
GL_TEXTURE_MIN_FILTER, GL_LINEAR );
-                               qglTexParameterf(GL_TEXTURE_2D, 
GL_TEXTURE_MAG_FILTER, GL_LINEAR );
-                               qglTexParameterf(GL_TEXTURE_2D, 
GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
-                               qglTexParameterf(GL_TEXTURE_2D, 
GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+                               
qglTextureParameterf(tr.sunShadowDepthImage[x]->texnum, GL_TEXTURE_2D, 
GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+                               
qglTextureParameterf(tr.sunShadowDepthImage[x]->texnum, GL_TEXTURE_2D, 
GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+                               
qglTextureParameterf(tr.sunShadowDepthImage[x]->texnum, GL_TEXTURE_2D, 
GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
+                               
qglTextureParameterf(tr.sunShadowDepthImage[x]->texnum, GL_TEXTURE_2D, 
GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
                        }
 
                        tr.screenShadowImage = R_CreateImage("*screenShadow", 
NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | 
IMGFLAG_CLAMPTOEDGE, GL_RGBA8);
@@ -3044,6 +3031,11 @@ void R_SetColorMappings( void ) {
                tr.overbrightBits = 0;
        }
 
+       // don't allow more overbright bits than map overbright bits
+       if ( tr.overbrightBits > r_mapOverBrightBits->integer ) {
+               tr.overbrightBits = r_mapOverBrightBits->integer;
+       }
+
        tr.identityLight = 1.0f / ( 1 << tr.overbrightBits );
        tr.identityLightByte = 255 * tr.identityLight;
 
@@ -3115,17 +3107,11 @@ void R_DeleteTextures( void ) {
        for ( i = 0; i < tr.numImages ; i++ ) {
                qglDeleteTextures( 1, &tr.images[i]->texnum );
        }
-       memset( tr.images, 0, sizeof( tr.images ) );
+       Com_Memset( tr.images, 0, sizeof( tr.images ) );
 
-       memset( glState.currenttextures, 0, sizeof( glState.currenttextures ) );
-       if ( qglActiveTextureARB ) {
-               GL_SelectTexture( 1 );
-               qglBindTexture( GL_TEXTURE_2D, 0 );
-               GL_SelectTexture( 0 );
-               qglBindTexture( GL_TEXTURE_2D, 0 );
-       } else {
-               qglBindTexture( GL_TEXTURE_2D, 0 );
-       }
+       tr.numImages = 0;
+
+       GL_BindNullTextures();
 }
 
 /*
diff --git a/MP/code/rend2/tr_init.c b/MP/code/rend2/tr_init.c
index 85ebd1b..1787326 100644
--- a/MP/code/rend2/tr_init.c
+++ b/MP/code/rend2/tr_init.c
@@ -30,6 +30,8 @@ If you have questions concerning this license or the 
applicable additional terms
 
 #include "tr_local.h"
 
+#include "tr_dsa.h"
+
 glconfig_t  glConfig;
 glRefConfig_t glRefConfig;
 qboolean    textureFilterAnisotropic = qfalse;
@@ -125,6 +127,7 @@ cvar_t  *r_ext_framebuffer_multisample;
 cvar_t  *r_arb_seamless_cube_map;
 cvar_t  *r_arb_vertex_type_2_10_10_10_rev;
 cvar_t  *r_arb_vertex_array_object;
+cvar_t  *r_ext_direct_state_access;
 
 cvar_t  *r_mergeMultidraws;
 cvar_t  *r_mergeLeafSurfaces;
@@ -148,11 +151,6 @@ cvar_t  *r_forceAutoExposure;
 cvar_t  *r_forceAutoExposureMin;
 cvar_t  *r_forceAutoExposureMax;
 
-cvar_t  *r_materialGamma;
-cvar_t  *r_lightGamma;
-cvar_t  *r_framebufferGamma;
-cvar_t  *r_tonemapGamma;
-
 cvar_t  *r_depthPrepass;
 cvar_t  *r_ssao;
 
@@ -162,8 +160,7 @@ cvar_t  *r_deluxeMapping;
 cvar_t  *r_parallaxMapping;
 cvar_t  *r_cubeMapping;
 cvar_t  *r_cubemapSize;
-cvar_t  *r_specularIsMetallic;
-cvar_t  *r_glossIsRoughness;
+cvar_t  *r_pbr;
 cvar_t  *r_baseNormalX;
 cvar_t  *r_baseNormalY;
 cvar_t  *r_baseParallax;
@@ -1025,19 +1022,11 @@ void GL_SetDefaultState( void ) {
 
        qglColor4f( 1,1,1,1 );
 
-       // initialize downstream texture unit if we're running
-       // in a multitexture environment
-       if ( qglActiveTextureARB ) {
-               GL_SelectTexture( 1 );
-               GL_TextureMode( r_textureMode->string );
-               GL_TexEnv( GL_MODULATE );
-               qglDisable( GL_TEXTURE_2D );
-               GL_SelectTexture( 0 );
-       }
+       GL_BindNullTextures();
+       GL_BindNullFramebuffers();
 
        qglEnable( GL_TEXTURE_2D );
        GL_TextureMode( r_textureMode->string );
-       GL_TexEnv( GL_MODULATE );
 
        //qglShadeModel( GL_SMOOTH );
        qglDepthFunc( GL_LEQUAL );
@@ -1050,8 +1039,7 @@ void GL_SetDefaultState( void ) {
        glState.faceCulling = CT_TWO_SIDED;
        glState.faceCullFront = qtrue;
 
-       glState.currentProgram = 0;
-       qglUseProgramObjectARB(0);
+       GL_BindNullProgram();
 
        if (glRefConfig.vertexArrayObject)
                qglBindVertexArrayARB(0);
@@ -1290,6 +1278,7 @@ void R_Register( void ) {
        r_arb_seamless_cube_map = ri.Cvar_Get( "r_arb_seamless_cube_map", "0", 
CVAR_ARCHIVE | CVAR_LATCH);
        r_arb_vertex_type_2_10_10_10_rev = ri.Cvar_Get( 
"r_arb_vertex_type_2_10_10_10_rev", "1", CVAR_ARCHIVE | CVAR_LATCH);
        r_arb_vertex_array_object = ri.Cvar_Get( "r_arb_vertex_array_object", 
"1", CVAR_ARCHIVE | CVAR_LATCH);
+       r_ext_direct_state_access = ri.Cvar_Get("r_ext_direct_state_access", 
"1", CVAR_ARCHIVE | CVAR_LATCH);
 
        r_ext_texture_filter_anisotropic = ri.Cvar_Get( 
"r_ext_texture_filter_anisotropic", "0", CVAR_ARCHIVE | CVAR_LATCH );
        r_ext_max_anisotropy = ri.Cvar_Get( "r_ext_max_anisotropy", "2", 
CVAR_ARCHIVE | CVAR_LATCH );
@@ -1328,7 +1317,7 @@ void R_Register( void ) {
        r_floatLightmap = ri.Cvar_Get( "r_floatLightmap", "0", CVAR_ARCHIVE | 
CVAR_LATCH );
        r_postProcess = ri.Cvar_Get( "r_postProcess", "1", CVAR_ARCHIVE );
 
-       r_toneMap = ri.Cvar_Get( "r_toneMap", "1", CVAR_ARCHIVE | CVAR_LATCH );
+       r_toneMap = ri.Cvar_Get( "r_toneMap", "1", CVAR_ARCHIVE );
        r_forceToneMap = ri.Cvar_Get( "r_forceToneMap", "0", CVAR_CHEAT );
        r_forceToneMapMin = ri.Cvar_Get( "r_forceToneMapMin", "-8.0", 
CVAR_CHEAT );
        r_forceToneMapAvg = ri.Cvar_Get( "r_forceToneMapAvg", "-2.0", 
CVAR_CHEAT );
@@ -1341,11 +1330,6 @@ void R_Register( void ) {
 
        r_cameraExposure = ri.Cvar_Get( "r_cameraExposure", "0", CVAR_CHEAT );
 
-       r_materialGamma = ri.Cvar_Get( "r_materialGamma", "1.0", CVAR_ARCHIVE | 
CVAR_LATCH );
-       r_lightGamma = ri.Cvar_Get( "r_lightGamma", "1.0", CVAR_ARCHIVE | 
CVAR_LATCH );
-       r_framebufferGamma = ri.Cvar_Get( "r_framebufferGamma", "1.0", 
CVAR_ARCHIVE | CVAR_LATCH );
-       r_tonemapGamma = ri.Cvar_Get( "r_tonemapGamma", "1.0", CVAR_ARCHIVE | 
CVAR_LATCH );
-
        r_depthPrepass = ri.Cvar_Get( "r_depthPrepass", "1", CVAR_ARCHIVE );
        r_ssao = ri.Cvar_Get( "r_ssao", "0", CVAR_LATCH | CVAR_ARCHIVE );
 
@@ -1355,8 +1339,7 @@ void R_Register( void ) {
        r_parallaxMapping = ri.Cvar_Get( "r_parallaxMapping", "0", CVAR_ARCHIVE 
| CVAR_LATCH );
        r_cubeMapping = ri.Cvar_Get( "r_cubeMapping", "0", CVAR_ARCHIVE | 
CVAR_LATCH );
        r_cubemapSize = ri.Cvar_Get( "r_cubemapSize", "128", CVAR_ARCHIVE | 
CVAR_LATCH );
-       r_specularIsMetallic = ri.Cvar_Get( "r_specularIsMetallic", "0", 
CVAR_ARCHIVE | CVAR_LATCH );
-       r_glossIsRoughness = ri.Cvar_Get("r_glossIsRoughness", "0", 
CVAR_ARCHIVE | CVAR_LATCH);
+       r_pbr = ri.Cvar_Get("r_pbr", "0", CVAR_ARCHIVE | CVAR_LATCH);
        r_baseNormalX = ri.Cvar_Get( "r_baseNormalX", "1.0", CVAR_ARCHIVE | 
CVAR_LATCH );
        r_baseNormalY = ri.Cvar_Get( "r_baseNormalY", "1.0", CVAR_ARCHIVE | 
CVAR_LATCH );
        r_baseParallax = ri.Cvar_Get( "r_baseParallax", "0.05", CVAR_ARCHIVE | 
CVAR_LATCH );
diff --git a/MP/code/rend2/tr_local.h b/MP/code/rend2/tr_local.h
index f5e7e0a..b5bae66 100644
--- a/MP/code/rend2/tr_local.h
+++ b/MP/code/rend2/tr_local.h
@@ -27,7 +27,6 @@ If you have questions concerning this license or the 
applicable additional terms
 */
 
 
-
 #ifndef TR_LOCAL_H
 #define TR_LOCAL_H
 
@@ -35,10 +34,6 @@ If you have questions concerning this license or the 
applicable additional terms
 #include "../qcommon/qfiles.h"
 #include "../qcommon/qcommon.h"
 #include "../renderer/tr_public.h"
-#include "tr_extratypes.h"
-#include "tr_extramath.h"
-#include "tr_fbo.h"
-#include "tr_postprocess.h"
 #include "qgl.h"
 #include "../renderer/iqm.h"
 
@@ -130,6 +125,11 @@ typedef struct image_s {
        struct image_s* next;
 } image_t;
 
+#include "tr_extratypes.h"
+#include "tr_extramath.h"
+#include "tr_fbo.h"
+#include "tr_postprocess.h"
+
 // Ensure this is >= the ATTR_INDEX_COUNT enum below
 #define VAO_MAX_ATTRIBS 16
 
@@ -1483,8 +1483,6 @@ typedef struct {
 
 // the renderer front end should never modify glstate_t
 typedef struct {
-       int                     currenttextures[NUM_TEXTURE_BUNDLES];
-       int currenttmu;
        qboolean finishCalled;
        int texEnv[2];
        int faceCulling;
@@ -1494,7 +1492,6 @@ typedef struct {
        float           vertexAttribsInterpolation;
        qboolean        vertexAnimation;
        uint32_t        vertexAttribsEnabled;  // global if no VAOs, tess only 
otherwise
-       shaderProgram_t *currentProgram;
        FBO_t          *currentFBO;
        vao_t          *currentVao;
        mat4_t        modelview;
@@ -1552,6 +1549,7 @@ typedef struct {
 
        qboolean floatLightmap;
        qboolean vertexArrayObject;
+       qboolean directStateAccess;
 } glRefConfig_t;
 
 typedef struct {
@@ -1898,6 +1896,7 @@ extern  cvar_t  *r_ext_framebuffer_multisample;
 extern  cvar_t  *r_arb_seamless_cube_map;
 extern  cvar_t  *r_arb_vertex_type_2_10_10_10_rev;
 extern  cvar_t  *r_arb_vertex_array_object;
+extern  cvar_t  *r_ext_direct_state_access;
 
 //----(SA)     added
 extern cvar_t   *r_ext_NV_fog_dist;
@@ -1975,11 +1974,6 @@ extern  cvar_t  *r_forceAutoExposureMax;
 
 extern  cvar_t  *r_cameraExposure;
 
-extern  cvar_t  *r_materialGamma;
-extern  cvar_t  *r_lightGamma;
-extern  cvar_t  *r_framebufferGamma;
-extern  cvar_t  *r_tonemapGamma;
-
 extern  cvar_t  *r_depthPrepass;
 extern  cvar_t  *r_ssao;
 
@@ -1989,8 +1983,7 @@ extern  cvar_t  *r_deluxeMapping;
 extern  cvar_t  *r_parallaxMapping;
 extern  cvar_t  *r_cubeMapping;
 extern  cvar_t  *r_cubemapSize;
-extern  cvar_t  *r_specularIsMetallic;
-extern  cvar_t  *r_glossIsRoughness;
+extern  cvar_t  *r_pbr;
 extern  cvar_t  *r_baseNormalX;
 extern  cvar_t  *r_baseNormalY;
 extern  cvar_t  *r_baseParallax;
@@ -2095,17 +2088,14 @@ void R_RotateForEntity( const trRefEntity_t * ent, 
const viewParms_t * viewParms
 /*
 ** GL wrapper/helper functions
 */
-void    GL_Bind( image_t *image );
 void   GL_BindToTMU( image_t *image, int tmu );
 void    GL_SetDefaultState( void );
-void    GL_SelectTexture( int unit );
 void    GL_TextureMode( const char *string );
 void   GL_CheckErrs( char *file, int line );
 #define GL_CheckErrors(...) GL_CheckErrs(__FILE__, __LINE__)
 void    GL_State( unsigned long stateVector );
 void    GL_SetProjectionMatrix(mat4_t matrix);
 void    GL_SetModelviewMatrix(mat4_t matrix);
-void    GL_TexEnv( int env );
 void    GL_Cull( int cullType );
 
 #define GLS_SRCBLEND_ZERO                       0x00000001
@@ -2453,7 +2443,6 @@ void GLSL_InitGPUShaders(void);
 void GLSL_ShutdownGPUShaders(void);
 void GLSL_VertexAttribPointers(uint32_t attribBits);
 void GLSL_BindProgram(shaderProgram_t * program);
-void GLSL_BindNullProgram(void);
 
 void GLSL_SetUniformInt(shaderProgram_t *program, int uniformNum, GLint value);
 void GLSL_SetUniformFloat(shaderProgram_t *program, int uniformNum, GLfloat 
value);
diff --git a/MP/code/rend2/tr_main.c b/MP/code/rend2/tr_main.c
index c5756f8..0ee2e5e 100644
--- a/MP/code/rend2/tr_main.c
+++ b/MP/code/rend2/tr_main.c
@@ -2299,7 +2299,7 @@ void R_DebugGraphics( void ) {
 
        R_IssuePendingRenderCommands();
 
-       GL_Bind( tr.whiteImage );
+       GL_BindToTMU(tr.whiteImage, TB_COLORMAP);
        GL_Cull( CT_FRONT_SIDED );
        ri.CM_DrawDebugSurface( R_DebugPolygon );
 }
diff --git a/MP/code/rend2/tr_postprocess.c b/MP/code/rend2/tr_postprocess.c
index 35982fc..1952ae9 100644
--- a/MP/code/rend2/tr_postprocess.c
+++ b/MP/code/rend2/tr_postprocess.c
@@ -183,7 +183,7 @@ void RB_BokehBlur(FBO_t *src, ivec4_t srcBox, FBO_t *dst, 
ivec4_t dstBox, float
                                        FBO_Blit(tr.textureScratchFbo[0], NULL, 
blurTexScale, tr.textureScratchFbo[1], NULL, &tr.bokehShader, color, 0);
                        }
 
-                       FBO_Blit(tr.textureScratchFbo[1], NULL, NULL, dst, 
dstBox, &tr.textureColorShader, NULL, 0);
+                       FBO_Blit(tr.textureScratchFbo[1], NULL, NULL, dst, 
dstBox, NULL, NULL, 0);
                }
 #else // higher quality blur, but slower
                else if (blur > 1.0f)
@@ -217,7 +217,7 @@ void RB_BokehBlur(FBO_t *src, ivec4_t srcBox, FBO_t *dst, 
ivec4_t dstBox, float
                                FBO_Blit(tr.quarterFbo[0], NULL, blurTexScale, 
tr.quarterFbo[1], NULL, &tr.bokehShader, color, GLS_SRCBLEND_SRC_ALPHA | 
GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA);
                        }
 
-                       FBO_Blit(tr.quarterFbo[1], NULL, NULL, dst, dstBox, 
&tr.textureColorShader, NULL, 0);
+                       FBO_Blit(tr.quarterFbo[1], NULL, NULL, dst, dstBox, 
NULL, NULL, 0);
                }
 #endif
        }
@@ -232,49 +232,44 @@ static void RB_RadialBlur(FBO_t *srcFbo, FBO_t *dstFbo, 
int passes, float stretc
        const float mul = powf(stretch, inc);
        float scale;
 
-       {
-               vec2_t texScale;
+       alpha *= inc;
+       VectorSet4(color, alpha, alpha, alpha, 1.0f);
 
-               texScale[0] = 
-               texScale[1] = 1.0f;
+       if (srcFbo)
+               VectorSet4(srcBox, 0, 0, srcFbo->width, srcFbo->height);
+       else
+               VectorSet4(srcBox, 0, 0, glConfig.vidWidth, glConfig.vidHeight);
 
-               alpha *= inc;
-               VectorSet4(color, alpha, alpha, alpha, 1.0f);
+       VectorSet4(dstBox, x, y, w, h);
+       FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, 0);
 
-               VectorSet4(srcBox, 0, 0, srcFbo->width, srcFbo->height);
-               VectorSet4(dstBox, x, y, w, h);
-               FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, 
&tr.textureColorShader, color, 0);
+       --passes;
+       scale = mul;
+       while (passes > 0)
+       {
+               float iscale = 1.f / scale;
+               float s0 = xcenter * (1.f - iscale);
+               float t0 = (1.0f - ycenter) * (1.f - iscale);
 
-               --passes;
-               scale = mul;
-               while (passes > 0)
+               if (srcFbo)
                {
-                       float iscale = 1.f / scale;
-                       float s0 = xcenter * (1.f - iscale);
-                       float t0 = (1.0f - ycenter) * (1.f - iscale);
-                       float s1 = iscale + s0;
-                       float t1 = iscale + t0;
-
-                       if (srcFbo)
-                       {
-                               srcBox[0] = s0 * srcFbo->width;
-                               srcBox[1] = t0 * srcFbo->height;
-                               srcBox[2] = (s1 - s0) * srcFbo->width;
-                               srcBox[3] = (t1 - t0) * srcFbo->height;
-                       }
-                       else
-                       {
-                               srcBox[0] = s0 * glConfig.vidWidth;
-                               srcBox[1] = t0 * glConfig.vidHeight;
-                               srcBox[2] = (s1 - s0) * glConfig.vidWidth;
-                               srcBox[3] = (t1 - t0) * glConfig.vidHeight;
-                       }
+                       srcBox[0] = s0 * srcFbo->width;
+                       srcBox[1] = t0 * srcFbo->height;
+                       srcBox[2] = iscale * srcFbo->width;
+                       srcBox[3] = iscale * srcFbo->height;
+               }
+               else
+               {
+                       srcBox[0] = s0 * glConfig.vidWidth;
+                       srcBox[1] = t0 * glConfig.vidHeight;
+                       srcBox[2] = iscale * glConfig.vidWidth;
+                       srcBox[3] = iscale * glConfig.vidHeight;
+               }
                        
-                       FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, 
&tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
+               FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, 
GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
 
-                       scale *= mul;
-                       --passes;
-               }
+               scale *= mul;
+               --passes;
        }
 }
 
@@ -329,7 +324,7 @@ void RB_SunRays(FBO_t *srcFbo, ivec4_t srcBox, FBO_t 
*dstFbo, ivec4_t dstBox)
        // From RB_DrawSun()
        {
                float dist;
-               mat4_t trans, model, mvp;
+               mat4_t trans, model;
 
                Mat4Translation( backEnd.viewParms.or.origin, trans );
                Mat4Multiply( backEnd.viewParms.world.modelMatrix, trans, model 
);
@@ -353,12 +348,8 @@ void RB_SunRays(FBO_t *srcFbo, ivec4_t srcBox, FBO_t 
*dstFbo, ivec4_t dstBox)
        // initialize quarter buffers
        {
                float mul = 1.f;
-               vec2_t texScale;
                ivec4_t rayBox, quarterBox;
 
-               texScale[0] = 
-               texScale[1] = 1.0f;
-
                VectorSet4(color, mul, mul, mul, 1);
 
                if (srcFbo)
@@ -408,14 +399,10 @@ void RB_SunRays(FBO_t *srcFbo, ivec4_t srcBox, FBO_t 
*dstFbo, ivec4_t dstBox)
        // add result back on top of the main buffer
        {
                float mul = 1.f;
-               vec2_t texScale;
-
-               texScale[0] = 
-               texScale[1] = 1.0f;
 
                VectorSet4(color, mul, mul, mul, 1);
 
-               FBO_Blit(tr.quarterFbo[0], NULL, texScale, dstFbo, dstBox, 
&tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
+               FBO_Blit(tr.quarterFbo[0], NULL, NULL, dstFbo, dstBox, NULL, 
color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
        }
 }
 
@@ -443,31 +430,27 @@ static void RB_BlurAxis(FBO_t *srcFbo, FBO_t *dstFbo, 
float strength, qboolean h
        {
                ivec4_t srcBox, dstBox;
                vec4_t color;
-               vec2_t texScale;
-
-               texScale[0] = 
-               texScale[1] = 1.0f;
 
                VectorSet4(color, weights[0], weights[0], weights[0], 1.0f);
                VectorSet4(srcBox, 0, 0, srcFbo->width, srcFbo->height);
                VectorSet4(dstBox, 0, 0, dstFbo->width, dstFbo->height);
-               FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, 
&tr.textureColorShader, color, 0 );
+               FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, 0);
 
                VectorSet4(color, weights[1], weights[1], weights[1], 1.0f);
                dx = offsets[1] * xmul;
                dy = offsets[1] * ymul;
                VectorSet4(srcBox, dx, dy, srcFbo->width, srcFbo->height);
-               FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, 
&tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
+               FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, 
GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
                VectorSet4(srcBox, -dx, -dy, srcFbo->width, srcFbo->height);
-               FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, 
&tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
+               FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, 
GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
 
                VectorSet4(color, weights[2], weights[2], weights[2], 1.0f);
                dx = offsets[2] * xmul;
                dy = offsets[2] * ymul;
                VectorSet4(srcBox, dx, dy, srcFbo->width, srcFbo->height);
-               FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, 
&tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
+               FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, 
GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
                VectorSet4(srcBox, -dx, -dy, srcFbo->width, srcFbo->height);
-               FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, 
&tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
+               FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, 
GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
        }
 }
 
@@ -492,10 +475,6 @@ void RB_GaussianBlur(float blur)
        {
                ivec4_t srcBox, dstBox;
                vec4_t color;
-               vec2_t texScale;
-
-               texScale[0] = 
-               texScale[1] = 1.0f;
 
                VectorSet4(color, 1, 1, 1, 1);
 
@@ -507,7 +486,7 @@ void RB_GaussianBlur(float blur)
                VectorSet4(srcBox, 0, 0, tr.whiteImage->width, 
tr.whiteImage->height);
                VectorSet4(dstBox, 0, 0, tr.textureScratchFbo[0]->width, 
tr.textureScratchFbo[0]->height);
                qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
-               FBO_BlitFromTexture(tr.whiteImage, srcBox, texScale, 
tr.textureScratchFbo[0], dstBox, &tr.textureColorShader, color, 
GLS_DEPTHTEST_DISABLE);
+               FBO_BlitFromTexture(tr.whiteImage, srcBox, NULL, 
tr.textureScratchFbo[0], dstBox, NULL, color, GLS_DEPTHTEST_DISABLE);
                qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
 
                // blur the tiny buffer horizontally and vertically
@@ -518,6 +497,6 @@ void RB_GaussianBlur(float blur)
                VectorSet4(srcBox, 0, 0, tr.textureScratchFbo[0]->width, 
tr.textureScratchFbo[0]->height);
                VectorSet4(dstBox, 0, 0, glConfig.vidWidth,              
glConfig.vidHeight);
                color[3] = factor;
-               FBO_Blit(tr.textureScratchFbo[0], srcBox, texScale, NULL, 
dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_SRC_ALPHA | 
GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA);
+               FBO_Blit(tr.textureScratchFbo[0], srcBox, NULL, NULL, dstBox, 
NULL, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA);
        }
 }
diff --git a/MP/code/rend2/tr_scene.c b/MP/code/rend2/tr_scene.c
index eb0a372..07cb46c 100644
--- a/MP/code/rend2/tr_scene.c
+++ b/MP/code/rend2/tr_scene.c
@@ -452,7 +452,7 @@ void RE_BeginScene(const refdef_t *fd)
        else
        {
 #if defined(USE_OVERBRIGHT)
-               float scale = pow(2, r_mapOverBrightBits->integer - 
tr.overbrightBits - 8);
+               float scale = (1 << (r_mapOverBrightBits->integer - 
tr.overbrightBits)) / 255.0f;
 #else
                float scale = (1 << r_mapOverBrightBits->integer) / 255.0f;
 #endif
diff --git a/MP/code/rend2/tr_shade.c b/MP/code/rend2/tr_shade.c
index 897501b..9d7c0e1 100644
--- a/MP/code/rend2/tr_shade.c
+++ b/MP/code/rend2/tr_shade.c
@@ -107,11 +107,9 @@ static void R_BindAnimatedImageToTMU( textureBundle_t 
*bundle, int tmu ) {
        int             index;
 
        if ( bundle->isVideoMap ) {
-               int oldtmu = glState.currenttmu;
-               GL_SelectTexture(tmu);
                ri.CIN_RunCinematic(bundle->videoMapHandle);
                ri.CIN_UploadCinematic(bundle->videoMapHandle);
-               GL_SelectTexture(oldtmu);
+               GL_BindToTMU(tr.scratchImage[bundle->videoMapHandle], tmu);
                return;
        }
 
@@ -150,7 +148,7 @@ Draws triangle outlines for debugging
 ================
 */
 static void DrawTris (shaderCommands_t *input) {
-       GL_Bind( tr.whiteImage );
+       GL_BindToTMU( tr.whiteImage, TB_COLORMAP );
 
        GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE );
        qglDepthRange( 0, 0 );
@@ -449,7 +447,7 @@ static void ProjectDlightTexture( void ) {
                vector[3] = scale;
                GLSL_SetUniformVec4(sp, UNIFORM_DLIGHTINFO, vector);
          
-               GL_Bind( tr.dlightImage );
+               GL_BindToTMU( tr.dlightImage, TB_COLORMAP );
 
                // include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't 
add light
                // where they aren't rendered
@@ -960,11 +958,7 @@ static void ForwardDlight( void ) {
                }
 
                if (r_dlightMode->integer >= 2)
-               {
-                       GL_SelectTexture(TB_SHADOWMAP);
-                       GL_Bind(tr.shadowCubemaps[l]);
-                       GL_SelectTexture(0);
-               }
+                       GL_BindToTMU(tr.shadowCubemaps[l], TB_SHADOWMAP);
 
                ComputeTexMods( pStage, TB_DIFFUSEMAP, texMatrix, texOffTurb );
                GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, texMatrix);
@@ -1562,7 +1556,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t 
*input )
                if ( backEnd.depthFill )
                {
                        if (!(pStage->stateBits & GLS_ATEST_BITS))
-                               GL_BindToTMU( tr.whiteImage, 0 );
+                               GL_BindToTMU( tr.whiteImage, TB_COLORMAP );
                        else if ( pStage->bundle[TB_COLORMAP].image[0] != 0 )
                                R_BindAnimatedImageToTMU( 
&pStage->bundle[TB_COLORMAP], TB_COLORMAP );
                }
diff --git a/MP/code/rend2/tr_shader.c b/MP/code/rend2/tr_shader.c
index 060371e..d367e4d 100644
--- a/MP/code/rend2/tr_shader.c
+++ b/MP/code/rend2/tr_shader.c
@@ -912,9 +912,18 @@ static qboolean ParseStage( shaderStage_t *stage, char 
**text ) {
                                ri.Printf( PRINT_WARNING, "WARNING: missing 
parameter for specular reflectance in shader '%s'\n", shader.name );
                                continue;
                        }
-                       stage->specularScale[0] = 
-                       stage->specularScale[1] = 
-                       stage->specularScale[2] = atof( token );
+
+                       if (r_pbr->integer)
+                       {
+                               // interpret specularReflectance < 0.5 as 
nonmetal
+                               stage->specularScale[1] = (atof(token) < 0.5f) 
? 0.0f : 1.0f;
+                       }
+                       else
+                       {
+                               stage->specularScale[0] =
+                               stage->specularScale[1] =
+                               stage->specularScale[2] = atof( token );
+                       }
                }
                //
                // specularExponent <value>
@@ -932,8 +941,8 @@ static qboolean ParseStage( shaderStage_t *stage, char 
**text ) {
 
                        exponent = atof( token );
 
-                       if (r_glossIsRoughness->integer)
-                               stage->specularScale[3] = powf(2.0f / (exponent 
+ 2.0), 0.25);
+                       if (r_pbr->integer)
+                               stage->specularScale[0] = 1.0f - powf(2.0f / 
(exponent + 2.0), 0.25);
                        else
                        {
                                // Change shininess to gloss
@@ -958,8 +967,8 @@ static qboolean ParseStage( shaderStage_t *stage, char 
**text ) {
 
                        gloss = atof(token);
 
-                       if (r_glossIsRoughness->integer)
-                               stage->specularScale[3] = exp2f(-3.0f * gloss);
+                       if (r_pbr->integer)
+                               stage->specularScale[0] = 1.0f - exp2f(-3.0f * 
gloss);
                        else
                                stage->specularScale[3] = gloss;
                }
@@ -979,8 +988,8 @@ static qboolean ParseStage( shaderStage_t *stage, char 
**text ) {
 
                        roughness = atof(token);
 
-                       if (r_glossIsRoughness->integer)
-                               stage->specularScale[3] = roughness;
+                       if (r_pbr->integer)
+                               stage->specularScale[0] = 1.0 - roughness;
                        else
                        {
                                if (roughness >= 0.125)
@@ -1040,6 +1049,7 @@ static qboolean ParseStage( shaderStage_t *stage, char 
**text ) {
                }
                //
                // specularScale <rgb> <gloss>
+               // or specularScale <metallic> <smoothness> with r_pbr 1
                // or specularScale <r> <g> <b>
                // or specularScale <r> <g> <b> <gloss>
                //
@@ -1066,10 +1076,19 @@ static qboolean ParseStage( shaderStage_t *stage, char 
**text ) {
                        token = COM_ParseExt(text, qfalse);
                        if ( token[0] == 0 )
                        {
-                               // two values, rgb then gloss
-                               stage->specularScale[3] = 
stage->specularScale[1];
-                               stage->specularScale[1] =
-                               stage->specularScale[2] = 
stage->specularScale[0];
+                               if (r_pbr->integer)
+                               {
+                                       // two values, metallic then smoothness
+                                       float smoothness = 
stage->specularScale[1];
+                                       stage->specularScale[1] = 
(stage->specularScale[0] < 0.5f) ? 0.0f : 1.0f;
+                                       stage->specularScale[0] = smoothness;
+                               }
+                               {
+                                       // two values, rgb then gloss
+                                       stage->specularScale[3] = 
stage->specularScale[1];
+                                       stage->specularScale[1] =
+                                       stage->specularScale[2] = 
stage->specularScale[0];
+                               }
                                continue;
                        }
 
@@ -2933,10 +2952,17 @@ static void InitShader( const char *name, int 
lightmapIndex ) {
 
                // default normal/specular
                VectorSet4(stages[i].normalScale, 0.0f, 0.0f, 0.0f, 0.0f);
-               stages[i].specularScale[0] =
-               stages[i].specularScale[1] =
-               stages[i].specularScale[2] = r_baseSpecular->value;
-               stages[i].specularScale[3] = r_baseGloss->value;
+               if (r_pbr->integer)
+               {
+                       stages[i].specularScale[0] = r_baseGloss->value;
+               }
+               else
+               {
+                       stages[i].specularScale[0] =
+                       stages[i].specularScale[1] =
+                       stages[i].specularScale[2] = r_baseSpecular->value;
+                       stages[i].specularScale[3] = r_baseGloss->value;
+               }
        }
 }
 
diff --git a/MP/code/rend2/tr_shadows.c b/MP/code/rend2/tr_shadows.c
index 6036ece..85e754e 100644
--- a/MP/code/rend2/tr_shadows.c
+++ b/MP/code/rend2/tr_shadows.c
@@ -213,7 +213,7 @@ void RB_ShadowTessEnd( void ) {
 
        // draw the silhouette edges
 
-       GL_Bind( tr.whiteImage );
+       GL_BindToTMU( tr.whiteImage, TB_COLORMAP );
        GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
        qglColor3f( 0.2f, 0.2f, 0.2f );
 
@@ -262,7 +262,7 @@ void RB_ShadowFinish( void ) {
        qglDisable( GL_CLIP_PLANE0 );
        GL_Cull( CT_TWO_SIDED );
 
-       GL_Bind( tr.whiteImage );
+       GL_BindToTMU( tr.whiteImage, TB_COLORMAP );
 
        qglLoadIdentity();
 
diff --git a/MP/code/rend2/tr_sky.c b/MP/code/rend2/tr_sky.c
index 37bc21d..34d2fff 100644
--- a/MP/code/rend2/tr_sky.c
+++ b/MP/code/rend2/tr_sky.c
@@ -388,7 +388,7 @@ static void DrawSkySide( struct image_s *image, const int 
mins[2], const int max
        //tess.numIndexes = 0;
        tess.firstIndex = tess.numIndexes;
        
-       GL_Bind( image );
+       GL_BindToTMU( image, TB_COLORMAP );
        GL_Cull( CT_TWO_SIDED );
 
        for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t <= 
maxs[1]+HALF_SKY_SUBDIVISIONS; t++ )
@@ -505,7 +505,7 @@ static void DrawSkySideInner( struct image_s *image, const 
int mins[2], const in
        //tess.numIndexes = 0;
        tess.firstIndex = tess.numIndexes;
        
-       GL_Bind( image );
+       GL_BindToTMU( image, TB_COLORMAP );
        GL_Cull( CT_TWO_SIDED );
 
        for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t <= 
maxs[1]+HALF_SKY_SUBDIVISIONS; t++ )
diff --git a/MP/code/rend2/tr_surface.c b/MP/code/rend2/tr_surface.c
index df76ec9..4f2fd88 100644
--- a/MP/code/rend2/tr_surface.c
+++ b/MP/code/rend2/tr_surface.c
@@ -603,7 +603,7 @@ static void RB_SurfaceBeam( void ) {
                VectorAdd( start_points[i], direction, end_points[i] );
        }
 
-       GL_Bind( tr.whiteImage );
+       GL_BindToTMU( tr.whiteImage, TB_COLORMAP );
 
        GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
 
@@ -1772,7 +1772,7 @@ Draws x/y/z lines from the origin for orientation 
debugging
 */
 static void RB_SurfaceAxis( void ) {
 #if 0
-       GL_Bind( tr.whiteImage );
+       GL_BindToTMU( tr.whiteImage, TB_COLORMAP );
        GL_State( GLS_DEFAULT );
        qglLineWidth( 3 );
        qglBegin( GL_LINES );
diff --git a/MP/code/renderer/qgl.h b/MP/code/renderer/qgl.h
index f1164fb..2ae3d4e 100644
--- a/MP/code/renderer/qgl.h
+++ b/MP/code/renderer/qgl.h
@@ -815,12 +815,12 @@ extern void (APIENTRY * 
qglRenderbufferStorageMultisampleEXT)(GLenum target, GLs
 #define GL_FRAMEBUFFER_SRGB_EXT                         0x8DB9
 #endif
 
-#ifndef GL_EXT_texture_compression_latc
-#define GL_EXT_texture_compression_latc
-#define GL_COMPRESSED_LUMINANCE_LATC1_EXT                 0x8C70
-#define GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT          0x8C71
-#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT           0x8C72
-#define GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT    0x8C73
+#ifndef GL_ARB_texture_compression_rgtc
+#define GL_ARB_texture_compression_rgtc
+#define GL_COMPRESSED_RED_RGTC1                       0x8DBB
+#define GL_COMPRESSED_SIGNED_RED_RGTC1                0x8DBC
+#define GL_COMPRESSED_RG_RGTC2                        0x8DBD
+#define GL_COMPRESSED_SIGNED_RG_RGTC2                 0x8DBE
 #endif
 
 #ifndef GL_ARB_texture_compression_bptc
@@ -874,6 +874,50 @@ extern GLboolean (APIENTRY * qglIsVertexArrayARB)(GLuint 
array);
 #define GL_VERTEX_ARRAY_BINDING_ARB                0x85B5
 #endif
 
+// GL_EXT_direct_state_access
+extern GLvoid(APIENTRY * qglBindMultiTexture)(GLenum texunit, GLenum target, 
GLuint texture);
+extern GLvoid(APIENTRY * qglTextureParameterf)(GLuint texture, GLenum target, 
GLenum pname, GLfloat param);
+extern GLvoid(APIENTRY * qglTextureParameteri)(GLuint texture, GLenum target, 
GLenum pname, GLint param);
+extern GLvoid(APIENTRY * qglTextureImage2D)(GLuint texture, GLenum target, 
GLint level, GLint internalformat,
+       GLsizei width, GLsizei height, GLint border, GLenum format, GLenum 
type, const GLvoid *pixels);
+extern GLvoid(APIENTRY * qglTextureSubImage2D)(GLuint texture, GLenum target, 
GLint level, GLint xoffset, GLint yoffset,
+       GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid 
*pixels);
+extern GLvoid(APIENTRY * qglCopyTextureImage2D)(GLuint texture, GLenum target, 
GLint level, GLenum internalformat,
+       GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+extern GLvoid(APIENTRY * qglCompressedTextureImage2D)(GLuint texture, GLenum 
target, GLint level, GLenum internalformat,
+       GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const 
GLvoid *data);
+extern GLvoid(APIENTRY * qglCompressedTextureSubImage2D)(GLuint texture, 
GLenum target, GLint level,
+       GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum 
format,
+       GLsizei imageSize, const GLvoid *data);
+extern GLvoid(APIENTRY * qglGenerateTextureMipmap)(GLuint texture, GLenum 
target);
+
+extern GLvoid(APIENTRY * qglProgramUniform1i)(GLuint program, GLint location, 
GLint v0);
+extern GLvoid(APIENTRY * qglProgramUniform1f)(GLuint program, GLint location, 
GLfloat v0);
+extern GLvoid(APIENTRY * qglProgramUniform2f)(GLuint program, GLint location,
+       GLfloat v0, GLfloat v1);
+extern GLvoid(APIENTRY * qglProgramUniform3f)(GLuint program, GLint location,
+       GLfloat v0, GLfloat v1, GLfloat v2);
+extern GLvoid(APIENTRY * qglProgramUniform4f)(GLuint program, GLint location,
+       GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+extern GLvoid(APIENTRY * qglProgramUniform1fv)(GLuint program, GLint location,
+       GLsizei count, const GLfloat *value);
+extern GLvoid(APIENTRY * qglProgramUniformMatrix4fv)(GLuint program, GLint 
location,
+       GLsizei count, GLboolean transpose,
+       const GLfloat *value);
+
+extern GLvoid(APIENTRY * qglNamedRenderbufferStorage)(GLuint renderbuffer,
+       GLenum internalformat, GLsizei width, GLsizei height);
+
+extern GLvoid(APIENTRY * qglNamedRenderbufferStorageMultisample)(GLuint 
renderbuffer,
+       GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+
+extern GLenum(APIENTRY * qglCheckNamedFramebufferStatus)(GLuint framebuffer, 
GLenum target);
+extern GLvoid(APIENTRY * qglNamedFramebufferTexture2D)(GLuint framebuffer,
+       GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+extern GLvoid(APIENTRY * qglNamedFramebufferRenderbuffer)(GLuint framebuffer,
+       GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+
+
 #if defined(WIN32)
 // WGL_ARB_create_context
 #ifndef WGL_ARB_create_context
diff --git a/MP/code/renderer/tr_image.c b/MP/code/renderer/tr_image.c
index 5c2e738..6b3ce45 100644
--- a/MP/code/renderer/tr_image.c
+++ b/MP/code/renderer/tr_image.c
@@ -1659,9 +1659,11 @@ void R_DeleteTextures( void ) {
        for ( i = 0; i < tr.numImages ; i++ ) {
                qglDeleteTextures( 1, &tr.images[i]->texnum );
        }
-       memset( tr.images, 0, sizeof( tr.images ) );
+       Com_Memset( tr.images, 0, sizeof( tr.images ) );
 
-       memset( glState.currenttextures, 0, sizeof( glState.currenttextures ) );
+       tr.numImages = 0;
+
+       Com_Memset( glState.currenttextures, 0, sizeof( glState.currenttextures 
) );
        if ( qglActiveTextureARB ) {
                GL_SelectTexture( 1 );
                qglBindTexture( GL_TEXTURE_2D, 0 );
diff --git a/MP/code/renderer/tr_local.h b/MP/code/renderer/tr_local.h
index 0bcb1e0..c036572 100644
--- a/MP/code/renderer/tr_local.h
+++ b/MP/code/renderer/tr_local.h
@@ -27,7 +27,6 @@ If you have questions concerning this license or the 
applicable additional terms
 */
 
 
-
 #ifndef TR_LOCAL_H
 #define TR_LOCAL_H
 
diff --git a/MP/rend2-readme.txt b/MP/rend2-readme.txt
index 9504c42..0c096d8 100644
--- a/MP/rend2-readme.txt
+++ b/MP/rend2-readme.txt
@@ -219,6 +219,12 @@ Cvars for advanced material usage:
                                      0.05 - Standard depth. (default)
                                      0.1  - Looks broken.
 
+  r_pbr                          - Enable physically based rendering.
+                                   Experimental, will not look correct without
+                                   assets meant for it.
+                                     0 - No. (default)
+                                     1 - Yes.
+
 Cvars for image interpolation and generation:
   r_imageUpsample                - Use interpolation to artifically increase
                                    the resolution of all textures.  Looks good
@@ -337,21 +343,7 @@ Cvars that you probably don't care about or shouldn't mess 
with:
   r_shadowCascadeZBias           - Z-bias for shadow cascade frustums.
                                      -256 - Default.
 
-  r_materialGamma                - Gamma level for material textures.
-                                   (diffuse, specular)
-                                     1.0 - RTCW, fastest. (default)
-
-  r_lightGamma                   - Gamma level for light.
-                                   (lightmap, lightgrid, vertex lights)
-                                     1.0 - RTCW, fastest. (default)
 
-  r_framebufferGamma             - Gamma level for framebuffers.
-                                     1.0 - RTCW, fastest. (default)
-
-  r_tonemapGamma                 - Gamma applied after tonemapping.
-                                     1.0 - RTCW, fastest. (default)
-
-  
 Cvars that have broken bits:
   r_dlightMode                   - Change how dynamic lights look.
                                      0 - RTCW style dlights, fake

-- 
Alioth's /usr/local/bin/git-commit-notice on 
/srv/git.debian.org/git/pkg-games/iortcw.git

_______________________________________________
Pkg-games-commits mailing list
Pkg-games-commits@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-games-commits

Reply via email to