mesa: don't include m_xform.h where not needed
[mesa.git] / src / mesa / main / texstate.c
index dbd769d7407c0a5d307b65ed8f2bf6492cca1445..6586a486464d6876abe7083c0d856a7e4585430f 100644 (file)
 #include "texstate.h"
 #include "texenvprogram.h"
 #include "mtypes.h"
-#include "math/m_xform.h"
 
 
-#define ENUM_TO_FLOAT(X) ((GLfloat)(GLint)(X))
-#define ENUM_TO_DOUBLE(X) ((GLdouble)(GLint)(X))
-
 
 /**
  * Default texture combine environment state.  This is used to initialize
  */
 static const struct gl_tex_env_combine_state default_combine_state = {
    GL_MODULATE, GL_MODULATE,
-   { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT },
-   { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT },
-   { GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_ALPHA },
-   { GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA },
+   { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT, GL_CONSTANT },
+   { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT, GL_CONSTANT },
+   { GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_ALPHA, GL_SRC_ALPHA },
+   { GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA },
    0, 0,
    2, 2
 };
 
 
-/**
- * Copy a texture binding.  Helper used by _mesa_copy_texture_state().
- */
-static void
-copy_texture_binding(const GLcontext *ctx,
-                     struct gl_texture_object **dst,
-                     struct gl_texture_object *src)
-{
-   /* only copy if names differ (per OpenGL SI) */
-   if ((*dst)->Name != src->Name) {
-      /* unbind/delete dest binding which we're changing */
-      (*dst)->RefCount--;
-      if ((*dst)->RefCount == 0) {
-         /* time to delete this texture object */
-         ASSERT((*dst)->Name != 0);
-         ASSERT(ctx->Driver.DeleteTexture);
-         /* XXX cast-away const, unfortunately */
-         (*ctx->Driver.DeleteTexture)((GLcontext *) ctx, *dst);
-      }
-      /* make new binding, incrementing ref count */
-      *dst = src;
-      src->RefCount++;
-   }
-}
-
 
 /**
  * Used by glXCopyContext to copy texture state from one context to another.
@@ -109,7 +80,7 @@ _mesa_copy_texture_state( const GLcontext *src, GLcontext *dst )
    dst->Texture.SharedPalette = src->Texture.SharedPalette;
 
    /* per-unit state */
-   for (i = 0; i < src->Const.MaxTextureUnits; i++) {
+   for (i = 0; i < src->Const.MaxTextureImageUnits; i++) {
       dst->Texture.Unit[i].Enabled = src->Texture.Unit[i].Enabled;
       dst->Texture.Unit[i].EnvMode = src->Texture.Unit[i].EnvMode;
       COPY_4V(dst->Texture.Unit[i].EnvColor, src->Texture.Unit[i].EnvColor);
@@ -146,20 +117,20 @@ _mesa_copy_texture_state( const GLcontext *src, GLcontext *dst )
       /* copy texture object bindings, not contents of texture objects */
       _mesa_lock_context_textures(dst);
 
-      copy_texture_binding(src, &dst->Texture.Unit[i].Current1D,
-                           src->Texture.Unit[i].Current1D);
-      copy_texture_binding(src, &dst->Texture.Unit[i].Current2D,
-                           src->Texture.Unit[i].Current2D);
-      copy_texture_binding(src, &dst->Texture.Unit[i].Current3D,
-                           src->Texture.Unit[i].Current3D);
-      copy_texture_binding(src, &dst->Texture.Unit[i].CurrentCubeMap,
-                           src->Texture.Unit[i].CurrentCubeMap);
-      copy_texture_binding(src, &dst->Texture.Unit[i].CurrentRect,
-                           src->Texture.Unit[i].CurrentRect);
-      copy_texture_binding(src, &dst->Texture.Unit[i].Current1DArray,
-                           src->Texture.Unit[i].Current1DArray);
-      copy_texture_binding(src, &dst->Texture.Unit[i].Current2DArray,
-                           src->Texture.Unit[i].Current2DArray);
+      _mesa_reference_texobj(&dst->Texture.Unit[i].Current1D,
+                             src->Texture.Unit[i].Current1D);
+      _mesa_reference_texobj(&dst->Texture.Unit[i].Current2D,
+                             src->Texture.Unit[i].Current2D);
+      _mesa_reference_texobj(&dst->Texture.Unit[i].Current3D,
+                             src->Texture.Unit[i].Current3D);
+      _mesa_reference_texobj(&dst->Texture.Unit[i].CurrentCubeMap,
+                             src->Texture.Unit[i].CurrentCubeMap);
+      _mesa_reference_texobj(&dst->Texture.Unit[i].CurrentRect,
+                             src->Texture.Unit[i].CurrentRect);
+      _mesa_reference_texobj(&dst->Texture.Unit[i].Current1DArray,
+                             src->Texture.Unit[i].Current1DArray);
+      _mesa_reference_texobj(&dst->Texture.Unit[i].Current2DArray,
+                             src->Texture.Unit[i].Current2DArray);
 
       _mesa_unlock_context_textures(dst);
    }
@@ -335,8 +306,7 @@ _mesa_ActiveTextureARB(GLenum texture)
       _mesa_debug(ctx, "glActiveTexture %s\n",
                   _mesa_lookup_enum_by_nr(texture));
 
-   /* XXX error-check against max(coordunits, imageunits) */
-   if (texUnit >= ctx->Const.MaxTextureUnits) {
+   if (texUnit >= ctx->Const.MaxTextureImageUnits) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glActiveTexture(texture)");
       return;
    }
@@ -397,7 +367,7 @@ update_texture_matrices( GLcontext *ctx )
 
    ctx->Texture._TexMatEnabled = 0;
 
-   for (i=0; i < ctx->Const.MaxTextureUnits; i++) {
+   for (i=0; i < ctx->Const.MaxTextureCoordUnits; i++) {
       if (_math_matrix_is_dirty(ctx->TextureMatrixStack[i].Top)) {
         _math_matrix_analyse( ctx->TextureMatrixStack[i].Top );
 
@@ -433,16 +403,6 @@ update_texture_compare_function(GLcontext *ctx,
        */
       tObj->_Function = GL_NONE;
    }
-   else if (tObj->CompareFlag) {
-      /* GL_SGIX_shadow */
-      if (tObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) {
-         tObj->_Function = GL_LEQUAL;
-      }
-      else {
-         ASSERT(tObj->CompareOperator == GL_TEXTURE_GEQUAL_R_SGIX);
-         tObj->_Function = GL_GEQUAL;
-      }
-   }
    else if (tObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) {
       /* GL_ARB_shadow */
       tObj->_Function = tObj->CompareFunc;
@@ -475,6 +435,96 @@ texture_override(GLcontext *ctx,
 }
 
 
+/**
+ * Examine texture unit's combine/env state to update derived state.
+ */
+static void
+update_tex_combine(GLcontext *ctx, struct gl_texture_unit *texUnit)
+{
+   /* Set the texUnit->_CurrentCombine field to point to the user's combiner
+    * state, or the combiner state which is derived from traditional texenv
+    * mode.
+    */
+   if (texUnit->EnvMode == GL_COMBINE ||
+       texUnit->EnvMode == GL_COMBINE4_NV) {
+      texUnit->_CurrentCombine = & texUnit->Combine;
+   }
+   else {
+      const struct gl_texture_object *texObj = texUnit->_Current;
+      GLenum format = texObj->Image[0][texObj->BaseLevel]->_BaseFormat;
+      if (format == GL_COLOR_INDEX) {
+         format = GL_RGBA;  /* a bit of a hack */
+      }
+      else if (format == GL_DEPTH_COMPONENT ||
+               format == GL_DEPTH_STENCIL_EXT) {
+         format = texObj->DepthMode;
+      }
+      calculate_derived_texenv(&texUnit->_EnvMode, texUnit->EnvMode, format);
+      texUnit->_CurrentCombine = & texUnit->_EnvMode;
+   }
+
+   /* Determine number of source RGB terms in the combiner function */
+   switch (texUnit->_CurrentCombine->ModeRGB) {
+   case GL_REPLACE:
+      texUnit->_CurrentCombine->_NumArgsRGB = 1;
+      break;
+   case GL_ADD:
+   case GL_ADD_SIGNED:
+      if (texUnit->EnvMode == GL_COMBINE4_NV)
+         texUnit->_CurrentCombine->_NumArgsRGB = 4;
+      else
+         texUnit->_CurrentCombine->_NumArgsRGB = 2;
+      break;
+   case GL_MODULATE:
+   case GL_SUBTRACT:
+   case GL_DOT3_RGB:
+   case GL_DOT3_RGBA:
+   case GL_DOT3_RGB_EXT:
+   case GL_DOT3_RGBA_EXT:
+      texUnit->_CurrentCombine->_NumArgsRGB = 2;
+      break;
+   case GL_INTERPOLATE:
+   case GL_MODULATE_ADD_ATI:
+   case GL_MODULATE_SIGNED_ADD_ATI:
+   case GL_MODULATE_SUBTRACT_ATI:
+      texUnit->_CurrentCombine->_NumArgsRGB = 3;
+      break;
+   default:
+      texUnit->_CurrentCombine->_NumArgsRGB = 0;
+      _mesa_problem(ctx, "invalid RGB combine mode in update_texture_state");
+      return;
+   }
+
+   /* Determine number of source Alpha terms in the combiner function */
+   switch (texUnit->_CurrentCombine->ModeA) {
+   case GL_REPLACE:
+      texUnit->_CurrentCombine->_NumArgsA = 1;
+      break;
+   case GL_ADD:
+   case GL_ADD_SIGNED:
+      if (texUnit->EnvMode == GL_COMBINE4_NV)
+         texUnit->_CurrentCombine->_NumArgsA = 4;
+      else
+         texUnit->_CurrentCombine->_NumArgsA = 2;
+      break;
+   case GL_MODULATE:
+   case GL_SUBTRACT:
+      texUnit->_CurrentCombine->_NumArgsA = 2;
+      break;
+   case GL_INTERPOLATE:
+   case GL_MODULATE_ADD_ATI:
+   case GL_MODULATE_SIGNED_ADD_ATI:
+   case GL_MODULATE_SUBTRACT_ATI:
+      texUnit->_CurrentCombine->_NumArgsA = 3;
+      break;
+   default:
+      texUnit->_CurrentCombine->_NumArgsA = 0;
+      _mesa_problem(ctx, "invalid Alpha combine mode in update_texture_state");
+      break;
+   }
+}
+
+
 /**
  * \note This routine refers to derived texture matrix values to
  * compute the ENABLE_TEXMAT flags, but is only called on
@@ -507,9 +557,8 @@ update_texture_state( GLcontext *ctx )
       }
    }
 
-   ctx->NewState |= _NEW_TEXTURE; /* TODO: only set this if there are 
-                                  * actual changes. 
-                                  */
+   /* TODO: only set this if there are actual changes */
+   ctx->NewState |= _NEW_TEXTURE;
 
    ctx->Texture._EnabledUnits = 0;
    ctx->Texture._GenFlags = 0;
@@ -519,7 +568,7 @@ update_texture_state( GLcontext *ctx )
    /*
     * Update texture unit state.
     */
-   for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
+   for (unit = 0; unit < ctx->Const.MaxTextureImageUnits; unit++) {
       struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
       GLbitfield enableBits;
 
@@ -527,25 +576,35 @@ update_texture_state( GLcontext *ctx )
       texUnit->_ReallyEnabled = 0;
       texUnit->_GenFlags = 0;
 
-      /* Get the bitmask of texture enables.
+      /* Get the bitmask of texture target enables.
        * enableBits will be a mask of the TEXTURE_*_BIT flags indicating
        * which texture targets are enabled (fixed function) or referenced
        * by a fragment shader/program.  When multiple flags are set, we'll
        * settle on the one with highest priority (see texture_override below).
        */
-      if (fprog || vprog) {
-         enableBits = 0x0;
-         if (fprog)
-            enableBits |= fprog->Base.TexturesUsed[unit];
-         if (vprog)
-            enableBits |= vprog->Base.TexturesUsed[unit];
+      enableBits = 0x0;
+      if (vprog) {
+         enableBits |= vprog->Base.TexturesUsed[unit];
+      }
+      if (fprog) {
+         enableBits |= fprog->Base.TexturesUsed[unit];
       }
       else {
-         if (!texUnit->Enabled)
-            continue;
-         enableBits = texUnit->Enabled;
+         /* fixed-function fragment program */
+         enableBits |= texUnit->Enabled;
       }
 
+      if (enableBits == 0x0)
+         continue;
+
+      ASSERT(texUnit->Current1D);
+      ASSERT(texUnit->Current2D);
+      ASSERT(texUnit->Current3D);
+      ASSERT(texUnit->CurrentCubeMap);
+      ASSERT(texUnit->CurrentRect);
+      ASSERT(texUnit->Current1DArray);
+      ASSERT(texUnit->Current2DArray);
+
       /* Look for the highest-priority texture target that's enabled and
        * complete.  That's the one we'll use for texturing.  If we're using
        * a fragment program we're guaranteed that bitcount(enabledBits) <= 1.
@@ -569,73 +628,30 @@ update_texture_state( GLcontext *ctx )
          continue;
       }
 
-      if (texUnit->_ReallyEnabled)
-         ctx->Texture._EnabledUnits |= (1 << unit);
+      /* if we get here, we know this texture unit is enabled */
 
-      if (texUnit->EnvMode == GL_COMBINE) {
-        texUnit->_CurrentCombine = & texUnit->Combine;
-      }
-      else {
-         const struct gl_texture_object *texObj = texUnit->_Current;
-         GLenum format = texObj->Image[0][texObj->BaseLevel]->_BaseFormat;
-         if (format == GL_COLOR_INDEX) {
-            format = GL_RGBA;  /* a bit of a hack */
-         }
-         else if (format == GL_DEPTH_COMPONENT
-                  || format == GL_DEPTH_STENCIL_EXT) {
-            format = texObj->DepthMode;
-         }
-        calculate_derived_texenv(&texUnit->_EnvMode, texUnit->EnvMode, format);
-        texUnit->_CurrentCombine = & texUnit->_EnvMode;
-      }
+      ctx->Texture._EnabledUnits |= (1 << unit);
 
-      switch (texUnit->_CurrentCombine->ModeRGB) {
-      case GL_REPLACE:
-        texUnit->_CurrentCombine->_NumArgsRGB = 1;
-        break;
-      case GL_MODULATE:
-      case GL_ADD:
-      case GL_ADD_SIGNED:
-      case GL_SUBTRACT:
-      case GL_DOT3_RGB:
-      case GL_DOT3_RGBA:
-      case GL_DOT3_RGB_EXT:
-      case GL_DOT3_RGBA_EXT:
-        texUnit->_CurrentCombine->_NumArgsRGB = 2;
-        break;
-      case GL_INTERPOLATE:
-      case GL_MODULATE_ADD_ATI:
-      case GL_MODULATE_SIGNED_ADD_ATI:
-      case GL_MODULATE_SUBTRACT_ATI:
-        texUnit->_CurrentCombine->_NumArgsRGB = 3;
-        break;
-      default:
-        texUnit->_CurrentCombine->_NumArgsRGB = 0;
-         _mesa_problem(ctx, "invalid RGB combine mode in update_texture_state");
-         return;
-      }
+      update_tex_combine(ctx, texUnit);
+   }
 
-      switch (texUnit->_CurrentCombine->ModeA) {
-      case GL_REPLACE:
-        texUnit->_CurrentCombine->_NumArgsA = 1;
-        break;
-      case GL_MODULATE:
-      case GL_ADD:
-      case GL_ADD_SIGNED:
-      case GL_SUBTRACT:
-        texUnit->_CurrentCombine->_NumArgsA = 2;
-        break;
-      case GL_INTERPOLATE:
-      case GL_MODULATE_ADD_ATI:
-      case GL_MODULATE_SIGNED_ADD_ATI:
-      case GL_MODULATE_SUBTRACT_ATI:
-        texUnit->_CurrentCombine->_NumArgsA = 3;
-        break;
-      default:
-        texUnit->_CurrentCombine->_NumArgsA = 0;
-         _mesa_problem(ctx, "invalid Alpha combine mode in update_texture_state");
-        break;
-      }
+
+   /* Determine which texture coordinate sets are actually needed */
+   if (fprog) {
+      const GLuint coordMask = (1 << MAX_TEXTURE_COORD_UNITS) - 1;
+      ctx->Texture._EnabledCoordUnits
+         = (fprog->Base.InputsRead >> FRAG_ATTRIB_TEX0) & coordMask;
+   }
+   else {
+      ctx->Texture._EnabledCoordUnits = ctx->Texture._EnabledUnits;
+   }
+
+   /* Setup texgen for those texture coordinate sets that are in use */
+   for (unit = 0; unit < ctx->Const.MaxTextureCoordUnits; unit++) {
+      struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+
+      if (!(ctx->Texture._EnabledCoordUnits & (1 << unit)))
+        continue;
 
       if (texUnit->TexGenEnabled) {
         if (texUnit->TexGenEnabled & S_BIT) {
@@ -658,16 +674,6 @@ update_texture_state( GLcontext *ctx )
       if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY)
         ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(unit);
    }
-
-   /* Determine which texture coordinate sets are actually needed */
-   if (fprog) {
-      const GLuint coordMask = (1 << MAX_TEXTURE_COORD_UNITS) - 1;
-      ctx->Texture._EnabledCoordUnits
-         = (fprog->Base.InputsRead >> FRAG_ATTRIB_TEX0) & coordMask;
-   }
-   else {
-      ctx->Texture._EnabledCoordUnits = ctx->Texture._EnabledUnits;
-   }
 }
 
 
@@ -702,52 +708,32 @@ _mesa_update_texture( GLcontext *ctx, GLuint new_state )
 static GLboolean
 alloc_proxy_textures( GLcontext *ctx )
 {
-   ctx->Texture.Proxy1D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_1D);
-   if (!ctx->Texture.Proxy1D)
-      goto cleanup;
-
-   ctx->Texture.Proxy2D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_2D);
-   if (!ctx->Texture.Proxy2D)
-      goto cleanup;
-
-   ctx->Texture.Proxy3D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_3D);
-   if (!ctx->Texture.Proxy3D)
-      goto cleanup;
-
-   ctx->Texture.ProxyCubeMap = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_CUBE_MAP_ARB);
-   if (!ctx->Texture.ProxyCubeMap)
-      goto cleanup;
-
-   ctx->Texture.ProxyRect = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_RECTANGLE_NV);
-   if (!ctx->Texture.ProxyRect)
-      goto cleanup;
-
-   ctx->Texture.Proxy1DArray = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_1D_ARRAY_EXT);
-   if (!ctx->Texture.Proxy1DArray)
-      goto cleanup;
-
-   ctx->Texture.Proxy2DArray = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_2D_ARRAY_EXT);
-   if (!ctx->Texture.Proxy2DArray)
-      goto cleanup;
+   static const GLenum targets[] = {
+      GL_TEXTURE_1D,
+      GL_TEXTURE_2D,
+      GL_TEXTURE_3D,
+      GL_TEXTURE_CUBE_MAP_ARB,
+      GL_TEXTURE_RECTANGLE_NV,
+      GL_TEXTURE_1D_ARRAY_EXT,
+      GL_TEXTURE_2D_ARRAY_EXT
+   };
+   GLint tgt;
+
+   ASSERT(Elements(targets) == NUM_TEXTURE_TARGETS);
+
+   for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
+      if (!(ctx->Texture.ProxyTex[tgt]
+            = ctx->Driver.NewTextureObject(ctx, 0, targets[tgt]))) {
+         /* out of memory, free what we did allocate */
+         while (--tgt >= 0) {
+            ctx->Driver.DeleteTexture(ctx, ctx->Texture.ProxyTex[tgt]);
+         }
+         return GL_FALSE;
+      }
+   }
 
+   assert(ctx->Texture.ProxyTex[0]->RefCount == 1); /* sanity check */
    return GL_TRUE;
-
- cleanup:
-   if (ctx->Texture.Proxy1D)
-      (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy1D);
-   if (ctx->Texture.Proxy2D)
-      (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy2D);
-   if (ctx->Texture.Proxy3D)
-      (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy3D);
-   if (ctx->Texture.ProxyCubeMap)
-      (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.ProxyCubeMap);
-   if (ctx->Texture.ProxyRect)
-      (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.ProxyRect);
-   if (ctx->Texture.Proxy1DArray)
-      (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy1DArray);
-   if (ctx->Texture.Proxy2DArray)
-      (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy2DArray);
-   return GL_FALSE;
 }
 
 
@@ -789,13 +775,14 @@ init_texture_unit( GLcontext *ctx, GLuint unit )
    ASSIGN_4V( texUnit->EyePlaneR, 0.0, 0.0, 0.0, 0.0 );
    ASSIGN_4V( texUnit->EyePlaneQ, 0.0, 0.0, 0.0, 0.0 );
 
-   texUnit->Current1D = ctx->Shared->Default1D;
-   texUnit->Current2D = ctx->Shared->Default2D;
-   texUnit->Current3D = ctx->Shared->Default3D;
-   texUnit->CurrentCubeMap = ctx->Shared->DefaultCubeMap;
-   texUnit->CurrentRect = ctx->Shared->DefaultRect;
-   texUnit->Current1DArray = ctx->Shared->Default1DArray;
-   texUnit->Current2DArray = ctx->Shared->Default2DArray;
+   /* initialize current texture object ptrs to the shared default objects */
+   _mesa_reference_texobj(&texUnit->Current1D, ctx->Shared->Default1D);
+   _mesa_reference_texobj(&texUnit->Current2D, ctx->Shared->Default2D);
+   _mesa_reference_texobj(&texUnit->Current3D, ctx->Shared->Default3D);
+   _mesa_reference_texobj(&texUnit->CurrentCubeMap, ctx->Shared->DefaultCubeMap);
+   _mesa_reference_texobj(&texUnit->CurrentRect, ctx->Shared->DefaultRect);
+   _mesa_reference_texobj(&texUnit->Current1DArray, ctx->Shared->Default1DArray);
+   _mesa_reference_texobj(&texUnit->Current2DArray, ctx->Shared->Default2DArray);
 }
 
 
@@ -810,25 +797,22 @@ _mesa_init_texture(GLcontext *ctx)
    assert(MAX_TEXTURE_LEVELS >= MAX_3D_TEXTURE_LEVELS);
    assert(MAX_TEXTURE_LEVELS >= MAX_CUBE_TEXTURE_LEVELS);
 
-   /* Effectively bind the default textures to all texture units */
-   ctx->Shared->Default1D->RefCount += MAX_TEXTURE_UNITS;
-   ctx->Shared->Default2D->RefCount += MAX_TEXTURE_UNITS;
-   ctx->Shared->Default3D->RefCount += MAX_TEXTURE_UNITS;
-   ctx->Shared->DefaultCubeMap->RefCount += MAX_TEXTURE_UNITS;
-   ctx->Shared->DefaultRect->RefCount += MAX_TEXTURE_UNITS;
-   ctx->Shared->Default1DArray->RefCount += MAX_TEXTURE_UNITS;
-   ctx->Shared->Default2DArray->RefCount += MAX_TEXTURE_UNITS;
-
    /* Texture group */
    ctx->Texture.CurrentUnit = 0;      /* multitexture */
    ctx->Texture._EnabledUnits = 0;
-   for (i=0; i<MAX_TEXTURE_UNITS; i++)
-      init_texture_unit( ctx, i );
    ctx->Texture.SharedPalette = GL_FALSE;
 #if FEATURE_colortable
    _mesa_init_colortable(&ctx->Texture.Palette);
 #endif
 
+   for (i = 0; i < MAX_TEXTURE_UNITS; i++)
+      init_texture_unit( ctx, i );
+
+   /* After we're done initializing the context's texture state the default
+    * texture objects' refcounts should be at least MAX_TEXTURE_UNITS + 1.
+    */
+   assert(ctx->Shared->Default1D->RefCount >= MAX_TEXTURE_UNITS + 1);
+
    /* Allocate proxy textures */
    if (!alloc_proxy_textures( ctx ))
       return GL_FALSE;
@@ -843,14 +827,23 @@ _mesa_init_texture(GLcontext *ctx)
 void
 _mesa_free_texture_data(GLcontext *ctx)
 {
+   GLuint u, tgt;
+
+   /* unreference current textures */
+   for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++) {
+      struct gl_texture_unit *unit = ctx->Texture.Unit + u;
+      _mesa_reference_texobj(&unit->Current1D, NULL);
+      _mesa_reference_texobj(&unit->Current2D, NULL);
+      _mesa_reference_texobj(&unit->Current3D, NULL);
+      _mesa_reference_texobj(&unit->CurrentCubeMap, NULL);
+      _mesa_reference_texobj(&unit->CurrentRect, NULL);
+      _mesa_reference_texobj(&unit->Current1DArray, NULL);
+      _mesa_reference_texobj(&unit->Current2DArray, NULL);
+   }
+
    /* Free proxy texture objects */
-   (ctx->Driver.DeleteTexture)(ctx,  ctx->Texture.Proxy1D );
-   (ctx->Driver.DeleteTexture)(ctx,  ctx->Texture.Proxy2D );
-   (ctx->Driver.DeleteTexture)(ctx,  ctx->Texture.Proxy3D );
-   (ctx->Driver.DeleteTexture)(ctx,  ctx->Texture.ProxyCubeMap );
-   (ctx->Driver.DeleteTexture)(ctx,  ctx->Texture.ProxyRect );
-   (ctx->Driver.DeleteTexture)(ctx,  ctx->Texture.Proxy1DArray );
-   (ctx->Driver.DeleteTexture)(ctx,  ctx->Texture.Proxy2DArray );
+   for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++)
+      ctx->Driver.DeleteTexture(ctx, ctx->Texture.ProxyTex[tgt]);
 
 #if FEATURE_colortable
    {
@@ -860,3 +853,27 @@ _mesa_free_texture_data(GLcontext *ctx)
    }
 #endif
 }
+
+
+/**
+ * Update the default texture objects in the given context to reference those
+ * specified in the shared state and release those referencing the old 
+ * shared state.
+ */
+void
+_mesa_update_default_objects_texture(GLcontext *ctx)
+{
+   GLuint i;
+
+   for (i = 0; i < MAX_TEXTURE_UNITS; i++) {
+      struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
+
+      _mesa_reference_texobj(&texUnit->Current1D, ctx->Shared->Default1D);
+      _mesa_reference_texobj(&texUnit->Current2D, ctx->Shared->Default2D);
+      _mesa_reference_texobj(&texUnit->Current3D, ctx->Shared->Default3D);
+      _mesa_reference_texobj(&texUnit->CurrentCubeMap, ctx->Shared->DefaultCubeMap);
+      _mesa_reference_texobj(&texUnit->CurrentRect, ctx->Shared->DefaultRect);
+      _mesa_reference_texobj(&texUnit->Current1DArray, ctx->Shared->Default1DArray);
+      _mesa_reference_texobj(&texUnit->Current2DArray, ctx->Shared->Default2DArray);
+   }
+}