summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBrian <brian.paul@tungstengraphics.com>2007-08-13 11:29:46 +0100
committerBrian <brian.paul@tungstengraphics.com>2007-08-13 11:29:46 +0100
commit9e01b915f1243a3f551cb795b7124bd1e52ca15f (patch)
tree8813956c0705bb9b8b85948480320b3ea5cfede8 /src
parent6f4725088842fbc0069aeb51f41907b87e0a8f08 (diff)
Implement mutex/locking around texture object reference counting.
Use new _mesa_reference_texobj() function for referencing/unreferencing textures. Add new assertions/tests to try to detect invalid usage of deleted textures.
Diffstat (limited to 'src')
-rw-r--r--src/mesa/main/attrib.c1
-rw-r--r--src/mesa/main/context.c14
-rw-r--r--src/mesa/main/fbobject.c22
-rw-r--r--src/mesa/main/framebuffer.c13
-rw-r--r--src/mesa/main/mtypes.h1
-rw-r--r--src/mesa/main/texobj.c252
-rw-r--r--src/mesa/main/texobj.h4
-rw-r--r--src/mesa/main/texstate.c89
8 files changed, 184 insertions, 212 deletions
diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c
index b422198f92..36e438a53c 100644
--- a/src/mesa/main/attrib.c
+++ b/src/mesa/main/attrib.c
@@ -355,6 +355,7 @@ _mesa_PushAttrib(GLbitfield mask)
ctx->Texture.Unit[u].Current1DArray->RefCount++;
ctx->Texture.Unit[u].Current2DArray->RefCount++;
}
+
attr = MALLOC_STRUCT( gl_texture_attrib );
MEMCPY( attr, &ctx->Texture, sizeof(struct gl_texture_attrib) );
/* copy state of the currently bound texture objects */
diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
index 6fa32b320a..f360eac1e7 100644
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -475,19 +475,12 @@ alloc_shared_state( GLcontext *ctx )
if (!ss->Default2DArray)
goto cleanup;
- /* Effectively bind the default textures to all texture units */
- ss->Default1D->RefCount += MAX_TEXTURE_IMAGE_UNITS;
- ss->Default2D->RefCount += MAX_TEXTURE_IMAGE_UNITS;
- ss->Default3D->RefCount += MAX_TEXTURE_IMAGE_UNITS;
- ss->DefaultCubeMap->RefCount += MAX_TEXTURE_IMAGE_UNITS;
- ss->DefaultRect->RefCount += MAX_TEXTURE_IMAGE_UNITS;
- ss->Default1DArray->RefCount += MAX_TEXTURE_IMAGE_UNITS;
- ss->Default2DArray->RefCount += MAX_TEXTURE_IMAGE_UNITS;
+ /* sanity check */
+ assert(ss->Default1D->RefCount == 1);
_glthread_INIT_MUTEX(ss->TexMutex);
ss->TextureStateStamp = 0;
-
#if FEATURE_EXT_framebuffer_object
ss->FrameBuffers = _mesa_NewHashTable();
if (!ss->FrameBuffers)
@@ -497,10 +490,9 @@ alloc_shared_state( GLcontext *ctx )
goto cleanup;
#endif
-
return GL_TRUE;
- cleanup:
+cleanup:
/* Ran out of memory at some point. Free everything and return NULL */
if (ss->DisplayList)
_mesa_DeleteHashTable(ss->DisplayList);
diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c
index 6f7effcce7..fcb620b39d 100644
--- a/src/mesa/main/fbobject.c
+++ b/src/mesa/main/fbobject.c
@@ -151,22 +151,18 @@ _mesa_remove_attachment(GLcontext *ctx, struct gl_renderbuffer_attachment *att)
{
if (att->Type == GL_TEXTURE) {
ASSERT(att->Texture);
- att->Texture->RefCount--;
- if (att->Texture->RefCount == 0) {
- ctx->Driver.DeleteTexture(ctx, att->Texture);
+ if (ctx->Driver.FinishRenderTexture) {
+ /* tell driver we're done rendering to this texobj */
+ ctx->Driver.FinishRenderTexture(ctx, att);
}
- else {
- /* tell driver that we're done rendering to this texture. */
- if (ctx->Driver.FinishRenderTexture) {
- ctx->Driver.FinishRenderTexture(ctx, att);
- }
- }
- att->Texture = NULL;
+ _mesa_reference_texobj(&att->Texture, NULL); /* unbind */
+ ASSERT(!att->Texture);
}
if (att->Type == GL_TEXTURE || att->Type == GL_RENDERBUFFER_EXT) {
ASSERT(att->Renderbuffer);
ASSERT(!att->Texture);
- _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
+ _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); /* unbind */
+ ASSERT(!att->Renderbuffer);
}
att->Type = GL_NONE;
att->Complete = GL_TRUE;
@@ -192,8 +188,8 @@ _mesa_set_texture_attachment(GLcontext *ctx,
/* new attachment */
_mesa_remove_attachment(ctx, att);
att->Type = GL_TEXTURE;
- att->Texture = texObj;
- texObj->RefCount++;
+ assert(!att->Texture);
+ _mesa_reference_texobj(&att->Texture, texObj);
}
/* always update these fields */
diff --git a/src/mesa/main/framebuffer.c b/src/mesa/main/framebuffer.c
index c9b30d3252..0a6de12fb8 100644
--- a/src/mesa/main/framebuffer.c
+++ b/src/mesa/main/framebuffer.c
@@ -38,6 +38,7 @@
#include "fbobject.h"
#include "framebuffer.h"
#include "renderbuffer.h"
+#include "texobj.h"
@@ -192,17 +193,11 @@ _mesa_free_framebuffer_data(struct gl_framebuffer *fb)
_mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
}
if (att->Texture) {
- /* render to texture */
- att->Texture->RefCount--;
- if (att->Texture->RefCount == 0) {
- GET_CURRENT_CONTEXT(ctx);
- if (ctx) {
- ctx->Driver.DeleteTexture(ctx, att->Texture);
- }
- }
+ _mesa_reference_texobj(&att->Texture, NULL);
}
+ ASSERT(!att->Renderbuffer);
+ ASSERT(!att->Texture);
att->Type = GL_NONE;
- att->Texture = NULL;
}
/* unbind _Depth/_StencilBuffer to decr ref counts */
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 3e4c49249a..989d199a10 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -1400,6 +1400,7 @@ struct gl_texture_image
*/
struct gl_texture_object
{
+ _glthread_Mutex Mutex; /**< for thread safety */
GLint RefCount; /**< reference count */
GLuint Name; /**< the user-visible texture object ID */
GLenum Target; /**< GL_TEXTURE_1D, GL_TEXTURE_2D, etc. */
diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c
index df64002f99..ac70e5a22e 100644
--- a/src/mesa/main/texobj.c
+++ b/src/mesa/main/texobj.c
@@ -106,6 +106,7 @@ _mesa_initialize_texture_object( struct gl_texture_object *obj,
_mesa_bzero(obj, sizeof(*obj));
/* init the non-zero fields */
+ _glthread_INIT_MUTEX(obj->Mutex);
obj->RefCount = 1;
obj->Name = name;
obj->Target = target;
@@ -151,8 +152,17 @@ _mesa_delete_texture_object( GLcontext *ctx, struct gl_texture_object *texObj )
{
GLuint i, face;
+ /*
+ printf("TEX DELETE %p (%u)\n", (void*) texObj, texObj->Name);
+ */
+
(void) ctx;
+ /* Set Target to an invalid value. With some assertions elsewhere
+ * we can try to detect possible use of deleted textures.
+ */
+ texObj->Target = 0x99;
+
_mesa_free_colortable_data(&texObj->Palette);
/* free the texture images */
@@ -164,6 +174,9 @@ _mesa_delete_texture_object( GLcontext *ctx, struct gl_texture_object *texObj )
}
}
+ /* destroy the mutex -- it may have allocated memory (eg on bsd) */
+ _glthread_DESTROY_MUTEX(texObj->Mutex);
+
/* free this object */
_mesa_free(texObj);
}
@@ -214,6 +227,98 @@ _mesa_copy_texture_object( struct gl_texture_object *dest,
/**
+ * Check if the given texture object is valid by examining its Target field.
+ * For debugging only.
+ */
+static GLboolean
+valid_texture_object(const struct gl_texture_object *tex)
+{
+ switch (tex->Target) {
+ case 0:
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ case GL_TEXTURE_RECTANGLE_NV:
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ return GL_TRUE;
+ case 0x99:
+ _mesa_problem(NULL, "invalid reference to a deleted texture object");
+ return GL_FALSE;
+ default:
+ _mesa_problem(NULL, "invalid texture object Target value");
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Reference (or unreference) a texture object.
+ * If '*ptr', decrement *ptr's refcount (and delete if it becomes zero).
+ * If 'tex' is non-null, increment its refcount.
+ */
+void
+_mesa_reference_texobj(struct gl_texture_object **ptr,
+ struct gl_texture_object *tex)
+{
+ assert(ptr);
+ if (*ptr == tex) {
+ /* no change */
+ return;
+ }
+
+ if (*ptr) {
+ /* Unreference the old texture */
+ GLboolean deleteFlag = GL_FALSE;
+ struct gl_texture_object *oldTex = *ptr;
+
+ assert(valid_texture_object(oldTex));
+
+ _glthread_LOCK_MUTEX(oldTex->Mutex);
+ ASSERT(oldTex->RefCount > 0);
+ oldTex->RefCount--;
+ /*
+ printf("TEX DECR %p (%u) to %d\n",
+ (void*) oldTex, oldTex->Name, oldTex->RefCount);
+ */
+ deleteFlag = (oldTex->RefCount == 0);
+ _glthread_UNLOCK_MUTEX(oldTex->Mutex);
+
+ if (deleteFlag) {
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.DeleteTexture(ctx, oldTex);
+ }
+
+ *ptr = NULL;
+ }
+ assert(!*ptr);
+
+ if (tex) {
+ /* reference new texture */
+ assert(valid_texture_object(tex));
+ _glthread_LOCK_MUTEX(tex->Mutex);
+ if (tex->RefCount == 0) {
+ /* this texture's being deleted (look just above) */
+ /* Not sure this can every really happen. Warn if it does. */
+ _mesa_problem(NULL, "referencing deleted texture object");
+ *ptr = NULL;
+ }
+ else {
+ tex->RefCount++;
+ /*
+ printf("TEX INCR %p (%u) to %d\n",
+ (void*) tex, tex->Name, tex->RefCount);
+ */
+ *ptr = tex;
+ }
+ _glthread_UNLOCK_MUTEX(tex->Mutex);
+ }
+}
+
+
+
+/**
* Report why a texture object is incomplete.
*
* \param t texture object.
@@ -609,8 +714,7 @@ unbind_texobj_from_fbo(GLcontext *ctx, struct gl_texture_object *texObj)
/**
* Check if the given texture object is bound to any texture image units and
- * unbind it if so.
- * XXX all RefCount accesses should be protected by a mutex.
+ * unbind it if so (revert to default textures).
*/
static void
unbind_texobj_from_texunits(GLcontext *ctx, struct gl_texture_object *texObj)
@@ -619,42 +723,26 @@ unbind_texobj_from_texunits(GLcontext *ctx, struct gl_texture_object *texObj)
for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++) {
struct gl_texture_unit *unit = &ctx->Texture.Unit[u];
- struct gl_texture_object **curr = NULL;
-
if (texObj == unit->Current1D) {
- curr = &unit->Current1D;
- unit->Current1D = ctx->Shared->Default1D;
+ _mesa_reference_texobj(&unit->Current1D, ctx->Shared->Default1D);
}
else if (texObj == unit->Current2D) {
- curr = &unit->Current2D;
- unit->Current2D = ctx->Shared->Default2D;
+ _mesa_reference_texobj(&unit->Current2D, ctx->Shared->Default2D);
}
else if (texObj == unit->Current3D) {
- curr = &unit->Current3D;
- unit->Current3D = ctx->Shared->Default3D;
+ _mesa_reference_texobj(&unit->Current3D, ctx->Shared->Default3D);
}
else if (texObj == unit->CurrentCubeMap) {
- curr = &unit->CurrentCubeMap;
- unit->CurrentCubeMap = ctx->Shared->DefaultCubeMap;
+ _mesa_reference_texobj(&unit->CurrentCubeMap, ctx->Shared->DefaultCubeMap);
}
else if (texObj == unit->CurrentRect) {
- curr = &unit->CurrentRect;
- unit->CurrentRect = ctx->Shared->DefaultRect;
+ _mesa_reference_texobj(&unit->CurrentRect, ctx->Shared->DefaultRect);
}
else if (texObj == unit->Current1DArray) {
- curr = &unit->Current1DArray;
- unit->CurrentRect = ctx->Shared->Default1DArray;
+ _mesa_reference_texobj(&unit->Current1DArray, ctx->Shared->Default1DArray);
}
else if (texObj == unit->Current2DArray) {
- curr = &unit->Current1DArray;
- unit->CurrentRect = ctx->Shared->Default2DArray;
- }
-
- if (curr) {
- (*curr)->RefCount++;
- texObj->RefCount--;
- if (texObj == unit->_Current)
- unit->_Current = *curr;
+ _mesa_reference_texobj(&unit->Current2DArray, ctx->Shared->Default2DArray);
}
}
}
@@ -690,8 +778,6 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures)
= _mesa_lookup_texture(ctx, textures[i]);
if (delObj) {
- GLboolean deleted;
-
_mesa_lock_texture(ctx, delObj);
/* Check if texture is bound to any framebuffer objects.
@@ -701,10 +787,12 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures)
unbind_texobj_from_fbo(ctx, delObj);
/* Check if this texture is currently bound to any texture units.
- * If so, unbind it and decrement the reference count.
+ * If so, unbind it.
*/
unbind_texobj_from_texunits(ctx, delObj);
+ _mesa_unlock_texture(ctx, delObj);
+
ctx->NewState |= _NEW_TEXTURE;
/* The texture _name_ is now free for re-use.
@@ -714,23 +802,10 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures)
_mesa_HashRemove(ctx->Shared->TexObjects, delObj->Name);
_glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
- /* The actual texture object will not be freed until it's no
- * longer bound in any context.
- * XXX all RefCount accesses should be protected by a mutex.
+ /* Unrefernce the texobj. If refcount hits zero, the texture
+ * will be deleted.
*/
- delObj->RefCount--;
- deleted = (delObj->RefCount == 0);
- _mesa_unlock_texture(ctx, delObj);
-
- /* We know that refcount went to zero above, so this is
- * the only pointer left to delObj, so we don't have to
- * worry about locking any more:
- */
- if (deleted) {
- ASSERT(delObj->Name != 0); /* Never delete default tex objs */
- ASSERT(ctx->Driver.DeleteTexture);
- (*ctx->Driver.DeleteTexture)(ctx, delObj);
- }
+ _mesa_reference_texobj(&delObj, NULL);
}
}
}
@@ -758,7 +833,6 @@ _mesa_BindTexture( GLenum target, GLuint texName )
GET_CURRENT_CONTEXT(ctx);
const GLuint unit = ctx->Texture.CurrentUnit;
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
- struct gl_texture_object *oldTexObj;
struct gl_texture_object *newTexObj = NULL;
ASSERT_OUTSIDE_BEGIN_END(ctx);
@@ -767,62 +841,6 @@ _mesa_BindTexture( GLenum target, GLuint texName )
_mesa_lookup_enum_by_nr(target), (GLint) texName);
/*
- * Get pointer to currently bound texture object (oldTexObj)
- */
- switch (target) {
- case GL_TEXTURE_1D:
- oldTexObj = texUnit->Current1D;
- break;
- case GL_TEXTURE_2D:
- oldTexObj = texUnit->Current2D;
- break;
- case GL_TEXTURE_3D:
- oldTexObj = texUnit->Current3D;
- break;
- case GL_TEXTURE_CUBE_MAP_ARB:
- if (!ctx->Extensions.ARB_texture_cube_map) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glBindTexture(target)" );
- return;
- }
- oldTexObj = texUnit->CurrentCubeMap;
- break;
- case GL_TEXTURE_RECTANGLE_NV:
- if (!ctx->Extensions.NV_texture_rectangle) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glBindTexture(target)" );
- return;
- }
- oldTexObj = texUnit->CurrentRect;
- break;
- case GL_TEXTURE_1D_ARRAY_EXT:
- if (!ctx->Extensions.MESA_texture_array) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glBindTexture(target)" );
- return;
- }
- oldTexObj = texUnit->Current1DArray;
- break;
- case GL_TEXTURE_2D_ARRAY_EXT:
- if (!ctx->Extensions.MESA_texture_array) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glBindTexture(target)" );
- return;
- }
- oldTexObj = texUnit->Current2DArray;
- break;
- default:
- _mesa_error( ctx, GL_INVALID_ENUM, "glBindTexture(target)" );
- return;
- }
-
- if (oldTexObj->Name == texName) {
- /* XXX this might be wrong. If the texobj is in use by another
- * context and a texobj parameter was changed, this might be our
- * only chance to update this context's hardware state.
- * Note that some applications re-bind the same texture a lot so we
- * want to handle that case quickly.
- */
- return; /* rebinding the same texture- no change */
- }
-
- /*
* Get pointer to new texture object (newTexObj)
*/
if (texName == 0) {
@@ -896,28 +914,30 @@ _mesa_BindTexture( GLenum target, GLuint texName )
newTexObj->Target = target;
}
- /* XXX all RefCount accesses should be protected by a mutex. */
- newTexObj->RefCount++;
+ assert(valid_texture_object(newTexObj));
- /* do the actual binding, but first flush outstanding vertices:
- */
+ /* flush before changing binding */
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ /* Do the actual binding. The refcount on the previously bound
+ * texture object will be decremented. It'll be deleted if the
+ * count hits zero.
+ */
switch (target) {
case GL_TEXTURE_1D:
- texUnit->Current1D = newTexObj;
+ _mesa_reference_texobj(&texUnit->Current1D, newTexObj);
break;
case GL_TEXTURE_2D:
- texUnit->Current2D = newTexObj;
+ _mesa_reference_texobj(&texUnit->Current2D, newTexObj);
break;
case GL_TEXTURE_3D:
- texUnit->Current3D = newTexObj;
+ _mesa_reference_texobj(&texUnit->Current3D, newTexObj);
break;
case GL_TEXTURE_CUBE_MAP_ARB:
- texUnit->CurrentCubeMap = newTexObj;
+ _mesa_reference_texobj(&texUnit->CurrentCubeMap, newTexObj);
break;
case GL_TEXTURE_RECTANGLE_NV:
- texUnit->CurrentRect = newTexObj;
+ _mesa_reference_texobj(&texUnit->CurrentRect, newTexObj);
break;
case GL_TEXTURE_1D_ARRAY_EXT:
texUnit->Current1DArray = newTexObj;
@@ -933,18 +953,6 @@ _mesa_BindTexture( GLenum target, GLuint texName )
/* Pass BindTexture call to device driver */
if (ctx->Driver.BindTexture)
(*ctx->Driver.BindTexture)( ctx, target, newTexObj );
-
- /* Decrement the reference count on the old texture and check if it's
- * time to delete it.
- */
- /* XXX all RefCount accesses should be protected by a mutex. */
- oldTexObj->RefCount--;
- ASSERT(oldTexObj->RefCount >= 0);
- if (oldTexObj->RefCount == 0) {
- ASSERT(oldTexObj->Name != 0);
- ASSERT(ctx->Driver.DeleteTexture);
- (*ctx->Driver.DeleteTexture)( ctx, oldTexObj );
- }
}
diff --git a/src/mesa/main/texobj.h b/src/mesa/main/texobj.h
index 2a2bde3601..d5374c5d6c 100644
--- a/src/mesa/main/texobj.h
+++ b/src/mesa/main/texobj.h
@@ -58,6 +58,10 @@ _mesa_copy_texture_object( struct gl_texture_object *dest,
const struct gl_texture_object *src );
extern void
+_mesa_reference_texobj(struct gl_texture_object **ptr,
+ struct gl_texture_object *tex);
+
+extern void
_mesa_test_texobj_completeness( const GLcontext *ctx,
struct gl_texture_object *obj );
diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c
index c9f8a0656e..08d083d201 100644
--- a/src/mesa/main/texstate.c
+++ b/src/mesa/main/texstate.c
@@ -63,31 +63,6 @@ static const struct gl_tex_env_combine_state default_combine_state = {
};
-/**
- * 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.
@@ -144,20 +119,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);
}
@@ -3113,6 +3088,8 @@ alloc_proxy_textures( GLcontext *ctx )
if (!ctx->Texture.Proxy2DArray)
goto cleanup;
+ assert(ctx->Texture.Proxy1D->RefCount == 1);
+
return GL_TRUE;
cleanup:
@@ -3172,13 +3149,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);
}
@@ -3193,23 +3171,20 @@ _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;
_mesa_init_colortable(&ctx->Texture.Palette);
+ 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);
+
_mesa_TexEnvProgramCacheInit( ctx );
/* Allocate proxy textures */