From a1bc0d0f51c2aa248a349283c3b86ae2c72af4aa Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Wed, 18 Jul 2007 20:17:14 +0200 Subject: fix mesa's handling of fbo's / window fb (again) Make sure the relevant fields in window fbs get updated at appropriate time (those are NOT the same as fbos!!!), and fix up related code accordingly. This is a bit ugly, but there's a reason the issues section in EXT_fbo is a couple hundred pages long... Hopefully correct now. --- src/mesa/main/attrib.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/mesa/main/attrib.c') diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c index 1aa0a02fc7..b422198f92 100644 --- a/src/mesa/main/attrib.c +++ b/src/mesa/main/attrib.c @@ -98,9 +98,13 @@ _mesa_PushAttrib(GLbitfield mask) } if (mask & GL_COLOR_BUFFER_BIT) { + GLuint i; struct gl_colorbuffer_attrib *attr; attr = MALLOC_STRUCT( gl_colorbuffer_attrib ); MEMCPY( attr, &ctx->Color, sizeof(struct gl_colorbuffer_attrib) ); + /* push the Draw FBO's DrawBuffer[] state, not ctx->Color.DrawBuffer[] */ + for (i = 0; i < ctx->Const.MaxDrawBuffers; i ++) + attr->DrawBuffer[i] = ctx->DrawBuffer->ColorDrawBuffer[i]; newnode = new_attrib_node( GL_COLOR_BUFFER_BIT ); newnode->data = attr; newnode->next = head; -- cgit v1.2.3 From 9e01b915f1243a3f551cb795b7124bd1e52ca15f Mon Sep 17 00:00:00 2001 From: Brian Date: Mon, 13 Aug 2007 11:29:46 +0100 Subject: 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. --- src/mesa/main/attrib.c | 1 + src/mesa/main/context.c | 14 +-- src/mesa/main/fbobject.c | 22 ++-- src/mesa/main/framebuffer.c | 13 +-- src/mesa/main/mtypes.h | 1 + src/mesa/main/texobj.c | 252 +++++++++++++++++++++++--------------------- src/mesa/main/texobj.h | 4 + src/mesa/main/texstate.c | 89 ++++++---------- 8 files changed, 184 insertions(+), 212 deletions(-) (limited to 'src/mesa/main/attrib.c') 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); } @@ -213,6 +226,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. * @@ -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); @@ -766,62 +840,6 @@ _mesa_BindTexture( GLenum target, GLuint texName ) _mesa_debug(ctx, "glBindTexture %s %d\n", _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) */ @@ -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 @@ -57,6 +57,10 @@ extern void _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; iTexture.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 */ -- cgit v1.2.3 From 145d762044f795bf9d68f28079cc5e5d3056920e Mon Sep 17 00:00:00 2001 From: Brian Date: Thu, 16 Aug 2007 10:05:00 +0100 Subject: Bring over the texobj refcounting changes from mesa_7_0_branch --- src/mesa/main/attrib.c | 236 +++++++++++++++++++++++++++++++---------------- src/mesa/main/attrib.h | 20 ++-- src/mesa/main/context.c | 5 +- src/mesa/main/texobj.c | 20 +--- src/mesa/main/texstate.c | 46 +++++---- 5 files changed, 202 insertions(+), 125 deletions(-) (limited to 'src/mesa/main/attrib.c') diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c index 36e438a53c..52e3f22adc 100644 --- a/src/mesa/main/attrib.c +++ b/src/mesa/main/attrib.c @@ -51,6 +51,36 @@ #include "math/m_xform.h" +/** + * Special struct for saving/restoring texture state (GL_TEXTURE_BIT) + */ +struct texture_state +{ + struct gl_texture_attrib Texture; /**< The usual context state */ + + /** to save per texture object state (wrap modes, filters, etc): */ + struct gl_texture_object Saved1D[MAX_TEXTURE_UNITS]; + struct gl_texture_object Saved2D[MAX_TEXTURE_UNITS]; + struct gl_texture_object Saved3D[MAX_TEXTURE_UNITS]; + struct gl_texture_object SavedCube[MAX_TEXTURE_UNITS]; + struct gl_texture_object SavedRect[MAX_TEXTURE_UNITS]; + struct gl_texture_object Saved1DArray[MAX_TEXTURE_UNITS]; + struct gl_texture_object Saved2DArray[MAX_TEXTURE_UNITS]; + + /** + * To save references to texture objects (so they don't get accidentally + * deleted while saved in the attribute stack). + */ + struct gl_texture_object *SavedRef1D[MAX_TEXTURE_UNITS]; + struct gl_texture_object *SavedRef2D[MAX_TEXTURE_UNITS]; + struct gl_texture_object *SavedRef3D[MAX_TEXTURE_UNITS]; + struct gl_texture_object *SavedRefCube[MAX_TEXTURE_UNITS]; + struct gl_texture_object *SavedRefRect[MAX_TEXTURE_UNITS]; + struct gl_texture_object *SavedRef1DArray[MAX_TEXTURE_UNITS]; + struct gl_texture_object *SavedRef2DArray[MAX_TEXTURE_UNITS]; +}; + + /** * Allocate a new attribute state node. These nodes have a * "kind" value and a pointer to a struct of state data. @@ -339,47 +369,54 @@ _mesa_PushAttrib(GLbitfield mask) } if (mask & GL_TEXTURE_BIT) { - struct gl_texture_attrib *attr; + struct texture_state *texstate = CALLOC_STRUCT(texture_state); GLuint u; + if (!texstate) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib(GL_TEXTURE_BIT)"); + goto end; + } + _mesa_lock_context_textures(ctx); - /* Bump the texture object reference counts so that they don't - * inadvertantly get deleted. + + /* copy/save the bulk of texture state here */ + _mesa_memcpy(&texstate->Texture, &ctx->Texture, sizeof(ctx->Texture)); + + /* Save references to the currently bound texture objects so they don't + * accidentally get deleted while referenced in the attribute stack. */ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { - ctx->Texture.Unit[u].Current1D->RefCount++; - ctx->Texture.Unit[u].Current2D->RefCount++; - ctx->Texture.Unit[u].Current3D->RefCount++; - ctx->Texture.Unit[u].CurrentCubeMap->RefCount++; - ctx->Texture.Unit[u].CurrentRect->RefCount++; - ctx->Texture.Unit[u].Current1DArray->RefCount++; - ctx->Texture.Unit[u].Current2DArray->RefCount++; + _mesa_reference_texobj(&texstate->SavedRef1D[u], ctx->Texture.Unit[u].Current1D); + _mesa_reference_texobj(&texstate->SavedRef2D[u], ctx->Texture.Unit[u].Current2D); + _mesa_reference_texobj(&texstate->SavedRef3D[u], ctx->Texture.Unit[u].Current3D); + _mesa_reference_texobj(&texstate->SavedRefCube[u], ctx->Texture.Unit[u].CurrentCubeMap); + _mesa_reference_texobj(&texstate->SavedRefRect[u], ctx->Texture.Unit[u].CurrentRect); + _mesa_reference_texobj(&texstate->SavedRef1DArray[u], ctx->Texture.Unit[u].Current1DArray); + _mesa_reference_texobj(&texstate->SavedRef2DArray[u], ctx->Texture.Unit[u].Current2DArray); } - attr = MALLOC_STRUCT( gl_texture_attrib ); - MEMCPY( attr, &ctx->Texture, sizeof(struct gl_texture_attrib) ); - /* copy state of the currently bound texture objects */ + /* copy state/contents of the currently bound texture objects */ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { - _mesa_copy_texture_object(&attr->Unit[u].Saved1D, - attr->Unit[u].Current1D); - _mesa_copy_texture_object(&attr->Unit[u].Saved2D, - attr->Unit[u].Current2D); - _mesa_copy_texture_object(&attr->Unit[u].Saved3D, - attr->Unit[u].Current3D); - _mesa_copy_texture_object(&attr->Unit[u].SavedCubeMap, - attr->Unit[u].CurrentCubeMap); - _mesa_copy_texture_object(&attr->Unit[u].SavedRect, - attr->Unit[u].CurrentRect); - _mesa_copy_texture_object(&attr->Unit[u].Saved1DArray, - attr->Unit[u].Current1DArray); - _mesa_copy_texture_object(&attr->Unit[u].Saved2DArray, - attr->Unit[u].Current2DArray); + _mesa_copy_texture_object(&texstate->Saved1D[u], + ctx->Texture.Unit[u].Current1D); + _mesa_copy_texture_object(&texstate->Saved2D[u], + ctx->Texture.Unit[u].Current2D); + _mesa_copy_texture_object(&texstate->Saved3D[u], + ctx->Texture.Unit[u].Current3D); + _mesa_copy_texture_object(&texstate->SavedCube[u], + ctx->Texture.Unit[u].CurrentCubeMap); + _mesa_copy_texture_object(&texstate->SavedRect[u], + ctx->Texture.Unit[u].CurrentRect); + _mesa_copy_texture_object(&texstate->Saved1DArray[u], + ctx->Texture.Unit[u].Current1DArray); + _mesa_copy_texture_object(&texstate->Saved2DArray[u], + ctx->Texture.Unit[u].Current2DArray); } _mesa_unlock_context_textures(ctx); newnode = new_attrib_node( GL_TEXTURE_BIT ); - newnode->data = attr; + newnode->data = texstate; newnode->next = head; head = newnode; } @@ -415,6 +452,7 @@ _mesa_PushAttrib(GLbitfield mask) head = newnode; } +end: ctx->AttribStack[ctx->AttribStackDepth] = head; ctx->AttribStackDepth++; } @@ -624,14 +662,19 @@ pop_enable_group(GLcontext *ctx, const struct gl_enable_attrib *enable) } +/** + * Pop/restore texture attribute/group state. + */ static void -pop_texture_group(GLcontext *ctx, const struct gl_texture_attrib *texAttrib) +pop_texture_group(GLcontext *ctx, struct texture_state *texstate) { GLuint u; + _mesa_lock_context_textures(ctx); + for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { - const struct gl_texture_unit *unit = &texAttrib->Unit[u]; - GLuint i; + const struct gl_texture_unit *unit = &texstate->Texture.Unit[u]; + GLuint tgt; _mesa_ActiveTextureARB(GL_TEXTURE0_ARB + u); _mesa_set_enable(ctx, GL_TEXTURE_1D, @@ -724,53 +767,56 @@ pop_texture_group(GLcontext *ctx, const struct gl_texture_attrib *texAttrib) 1 << unit->Combine.ScaleShiftA); } - /* Restore texture object state */ - for (i = 0; i < NUM_TEXTURE_TARGETS; i++) { - GLenum target = 0; + /* Restore texture object state for each target */ + for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) { const struct gl_texture_object *obj = NULL; GLfloat bordColor[4]; + GLenum target; - switch (i) { - case 0: - target = GL_TEXTURE_1D; - obj = &unit->Saved1D; + switch (tgt) { + case TEXTURE_1D_INDEX: + obj = &texstate->Saved1D[u]; + ASSERT(obj->Target == GL_TEXTURE_1D); break; - case 1: - target = GL_TEXTURE_2D; - obj = &unit->Saved2D; + case TEXTURE_2D_INDEX: + obj = &texstate->Saved2D[u]; + ASSERT(obj->Target == GL_TEXTURE_2D); break; - case 2: - target = GL_TEXTURE_3D; - obj = &unit->Saved3D; + case TEXTURE_3D_INDEX: + obj = &texstate->Saved3D[u]; + ASSERT(obj->Target == GL_TEXTURE_3D); break; - case 3: + case TEXTURE_CUBE_INDEX: if (!ctx->Extensions.ARB_texture_cube_map) continue; - target = GL_TEXTURE_CUBE_MAP_ARB; - obj = &unit->SavedCubeMap; + obj = &texstate->SavedCube[u]; + ASSERT(obj->Target == GL_TEXTURE_CUBE_MAP_ARB); break; - case 4: + case TEXTURE_RECT_INDEX: if (!ctx->Extensions.NV_texture_rectangle) continue; - target = GL_TEXTURE_RECTANGLE_NV; - obj = &unit->SavedRect; + obj = &texstate->SavedRect[u]; + ASSERT(obj->Target == GL_TEXTURE_RECTANGLE_NV); break; - case 5: + case TEXTURE_1D_ARRAY_INDEX: if (!ctx->Extensions.MESA_texture_array) continue; - target = GL_TEXTURE_1D_ARRAY_EXT; - obj = &unit->Saved1DArray; + obj = &texstate->Saved1DArray[u]; + ASSERT(obj->Target == GL_TEXTURE_1D_ARRAY_EXT); break; - case 6: + case TEXTURE_2D_ARRAY_INDEX: if (!ctx->Extensions.MESA_texture_array) continue; - target = GL_TEXTURE_2D_ARRAY_EXT; - obj = &unit->Saved2DArray; + obj = &texstate->Saved2DArray[u]; + ASSERT(obj->Target == GL_TEXTURE_2D_ARRAY_EXT); break; default: - ; /* silence warnings */ + _mesa_problem(ctx, "bad texture index in pop_texture_group"); + continue; } + target = obj->Target; + _mesa_BindTexture(target, obj->Name); bordColor[0] = CHAN_TO_FLOAT(obj->BorderColor[0]); @@ -778,8 +824,8 @@ pop_texture_group(GLcontext *ctx, const struct gl_texture_attrib *texAttrib) bordColor[2] = CHAN_TO_FLOAT(obj->BorderColor[2]); bordColor[3] = CHAN_TO_FLOAT(obj->BorderColor[3]); - _mesa_TexParameterf(target, GL_TEXTURE_PRIORITY, obj->Priority); _mesa_TexParameterfv(target, GL_TEXTURE_BORDER_COLOR, bordColor); + _mesa_TexParameterf(target, GL_TEXTURE_PRIORITY, obj->Priority); _mesa_TexParameteri(target, GL_TEXTURE_WRAP_S, obj->WrapS); _mesa_TexParameteri(target, GL_TEXTURE_WRAP_T, obj->WrapT); _mesa_TexParameteri(target, GL_TEXTURE_WRAP_R, obj->WrapR); @@ -805,25 +851,21 @@ pop_texture_group(GLcontext *ctx, const struct gl_texture_attrib *texAttrib) _mesa_TexParameterf(target, GL_SHADOW_AMBIENT_SGIX, obj->ShadowAmbient); } - } - } - _mesa_ActiveTextureARB(GL_TEXTURE0_ARB - + texAttrib->CurrentUnit); - /* "un-bump" the texture object reference counts. We did that so they - * wouldn't inadvertantly get deleted while they were still referenced - * inside the attribute state stack. - */ - for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { - ctx->Texture.Unit[u].Current1D->RefCount--; - ctx->Texture.Unit[u].Current2D->RefCount--; - ctx->Texture.Unit[u].Current3D->RefCount--; - ctx->Texture.Unit[u].CurrentCubeMap->RefCount--; - ctx->Texture.Unit[u].CurrentRect->RefCount--; - ctx->Texture.Unit[u].Current1DArray->RefCount--; - ctx->Texture.Unit[u].Current2DArray->RefCount--; + /* remove saved references to the texture objects */ + _mesa_reference_texobj(&texstate->SavedRef1D[u], NULL); + _mesa_reference_texobj(&texstate->SavedRef2D[u], NULL); + _mesa_reference_texobj(&texstate->SavedRef3D[u], NULL); + _mesa_reference_texobj(&texstate->SavedRefCube[u], NULL); + _mesa_reference_texobj(&texstate->SavedRefRect[u], NULL); + _mesa_reference_texobj(&texstate->SavedRef1DArray[u], NULL); + _mesa_reference_texobj(&texstate->SavedRef2DArray[u], NULL); } + + _mesa_ActiveTextureARB(GL_TEXTURE0_ARB + texstate->Texture.CurrentUnit); + + _mesa_unlock_context_textures(ctx); } @@ -1202,9 +1244,9 @@ _mesa_PopAttrib(void) case GL_TEXTURE_BIT: /* Take care of texture object reference counters */ { - const struct gl_texture_attrib *texture; - texture = (const struct gl_texture_attrib *) attr->data; - pop_texture_group(ctx, texture); + struct texture_state *texstate + = (struct texture_state *) attr->data; + pop_texture_group(ctx, texstate); ctx->NewState |= _NEW_TEXTURE; } break; @@ -1426,6 +1468,46 @@ _mesa_PopClientAttrib(void) } +/** + * Free any attribute state data that might be attached to the context. + */ +void +_mesa_free_attrib_data(GLcontext *ctx) +{ + while (ctx->AttribStackDepth > 0) { + struct gl_attrib_node *attr, *next; + + ctx->AttribStackDepth--; + attr = ctx->AttribStack[ctx->AttribStackDepth]; + + while (attr) { + if (attr->kind == GL_TEXTURE_BIT) { + struct texture_state *texstate = (struct texture_state*)attr->data; + GLuint u; + /* clear references to the saved texture objects */ + for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { + _mesa_reference_texobj(&texstate->SavedRef1D[u], NULL); + _mesa_reference_texobj(&texstate->SavedRef2D[u], NULL); + _mesa_reference_texobj(&texstate->SavedRef3D[u], NULL); + _mesa_reference_texobj(&texstate->SavedRefCube[u], NULL); + _mesa_reference_texobj(&texstate->SavedRefRect[u], NULL); + _mesa_reference_texobj(&texstate->SavedRef1DArray[u], NULL); + _mesa_reference_texobj(&texstate->SavedRef2DArray[u], NULL); + } + } + else { + /* any other chunks of state that requires special handling? */ + } + + next = attr->next; + _mesa_free(attr->data); + _mesa_free(attr); + attr = next; + } + } +} + + void _mesa_init_attrib( GLcontext *ctx ) { /* Renderer and client attribute stacks */ diff --git a/src/mesa/main/attrib.h b/src/mesa/main/attrib.h index 09d75196b2..2cf8fe6934 100644 --- a/src/mesa/main/attrib.h +++ b/src/mesa/main/attrib.h @@ -1,18 +1,8 @@ -/** - * \file attrib.h - * Attribute stacks. - * - * \if subset - * (No-op) - * - * \endif - */ - /* * Mesa 3-D graphics library - * Version: 5.1 + * Version: 7.1 * - * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +22,6 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - - #ifndef ATTRIB_H #define ATTRIB_H @@ -58,10 +46,14 @@ _mesa_PopClientAttrib( void ); extern void _mesa_init_attrib( GLcontext *ctx ); +extern void +_mesa_free_attrib_data( GLcontext *ctx ); + #else /** No-op */ #define _mesa_init_attrib( c ) ((void)0) +#define _mesa_free_attrib_data( c ) ((void)0) #endif diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index 37a14d3004..f3141fe63e 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -6,9 +6,9 @@ /* * Mesa 3-D graphics library - * Version: 6.5 + * Version: 7.1 * - * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -1209,6 +1209,7 @@ _mesa_free_context_data( GLcontext *ctx ) _mesa_unreference_framebuffer(&ctx->DrawBuffer); _mesa_unreference_framebuffer(&ctx->ReadBuffer); + _mesa_free_attrib_data(ctx); _mesa_free_lighting_data( ctx ); _mesa_free_eval_data( ctx ); _mesa_free_texture_data( ctx ); diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c index ea3328a047..3e017c1eda 100644 --- a/src/mesa/main/texobj.c +++ b/src/mesa/main/texobj.c @@ -5,9 +5,9 @@ /* * Mesa 3-D graphics library - * Version: 6.5 + * Version: 7.1 * - * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -152,10 +152,6 @@ _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 @@ -195,6 +191,7 @@ void _mesa_copy_texture_object( struct gl_texture_object *dest, const struct gl_texture_object *src ) { + dest->Target = src->Target; dest->Name = src->Name; dest->Priority = src->Priority; dest->BorderColor[0] = src->BorderColor[0]; @@ -278,10 +275,7 @@ _mesa_reference_texobj(struct gl_texture_object **ptr, _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); @@ -309,10 +303,6 @@ _mesa_reference_texobj(struct gl_texture_object **ptr, } else { tex->RefCount++; - /* - printf("TEX INCR %p (%u) to %d\n", - (void*) tex, tex->Name, tex->RefCount); - */ *ptr = tex; } _glthread_UNLOCK_MUTEX(tex->Mutex); @@ -805,7 +795,7 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures) _mesa_HashRemove(ctx->Shared->TexObjects, delObj->Name); _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); - /* Unrefernce the texobj. If refcount hits zero, the texture + /* Unreference the texobj. If refcount hits zero, the texture * will be deleted. */ _mesa_reference_texobj(&delObj, NULL); diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c index 08d083d201..91ee6513dc 100644 --- a/src/mesa/main/texstate.c +++ b/src/mesa/main/texstate.c @@ -119,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); - _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_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); } @@ -3201,7 +3201,19 @@ _mesa_init_texture(GLcontext *ctx) void _mesa_free_texture_data(GLcontext *ctx) { - GLuint i; + GLuint u; + + /* 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 ); @@ -3212,8 +3224,8 @@ _mesa_free_texture_data(GLcontext *ctx) (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy1DArray ); (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy2DArray ); - for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++) - _mesa_free_colortable_data( &ctx->Texture.Unit[i].ColorTable ); + for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++) + _mesa_free_colortable_data( &ctx->Texture.Unit[u].ColorTable ); _mesa_TexEnvProgramCacheDestroy( ctx ); } -- cgit v1.2.3 From 0135ff512d25b221d1a4cf9a5d344420d4ad3341 Mon Sep 17 00:00:00 2001 From: Brian Date: Thu, 16 Aug 2007 10:28:23 +0100 Subject: replace separate 1D/2D/etc fields with an array indexed by texture target --- src/mesa/main/attrib.c | 128 ++++++++++++++++++------------------------------- 1 file changed, 46 insertions(+), 82 deletions(-) (limited to 'src/mesa/main/attrib.c') diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c index 52e3f22adc..3199c9b426 100644 --- a/src/mesa/main/attrib.c +++ b/src/mesa/main/attrib.c @@ -59,25 +59,13 @@ struct texture_state struct gl_texture_attrib Texture; /**< The usual context state */ /** to save per texture object state (wrap modes, filters, etc): */ - struct gl_texture_object Saved1D[MAX_TEXTURE_UNITS]; - struct gl_texture_object Saved2D[MAX_TEXTURE_UNITS]; - struct gl_texture_object Saved3D[MAX_TEXTURE_UNITS]; - struct gl_texture_object SavedCube[MAX_TEXTURE_UNITS]; - struct gl_texture_object SavedRect[MAX_TEXTURE_UNITS]; - struct gl_texture_object Saved1DArray[MAX_TEXTURE_UNITS]; - struct gl_texture_object Saved2DArray[MAX_TEXTURE_UNITS]; + struct gl_texture_object SavedObj[MAX_TEXTURE_UNITS][NUM_TEXTURE_TARGETS]; /** * To save references to texture objects (so they don't get accidentally * deleted while saved in the attribute stack). */ - struct gl_texture_object *SavedRef1D[MAX_TEXTURE_UNITS]; - struct gl_texture_object *SavedRef2D[MAX_TEXTURE_UNITS]; - struct gl_texture_object *SavedRef3D[MAX_TEXTURE_UNITS]; - struct gl_texture_object *SavedRefCube[MAX_TEXTURE_UNITS]; - struct gl_texture_object *SavedRefRect[MAX_TEXTURE_UNITS]; - struct gl_texture_object *SavedRef1DArray[MAX_TEXTURE_UNITS]; - struct gl_texture_object *SavedRef2DArray[MAX_TEXTURE_UNITS]; + struct gl_texture_object *SavedTexRef[MAX_TEXTURE_UNITS][NUM_TEXTURE_TARGETS]; }; @@ -386,30 +374,37 @@ _mesa_PushAttrib(GLbitfield mask) * accidentally get deleted while referenced in the attribute stack. */ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { - _mesa_reference_texobj(&texstate->SavedRef1D[u], ctx->Texture.Unit[u].Current1D); - _mesa_reference_texobj(&texstate->SavedRef2D[u], ctx->Texture.Unit[u].Current2D); - _mesa_reference_texobj(&texstate->SavedRef3D[u], ctx->Texture.Unit[u].Current3D); - _mesa_reference_texobj(&texstate->SavedRefCube[u], ctx->Texture.Unit[u].CurrentCubeMap); - _mesa_reference_texobj(&texstate->SavedRefRect[u], ctx->Texture.Unit[u].CurrentRect); - _mesa_reference_texobj(&texstate->SavedRef1DArray[u], ctx->Texture.Unit[u].Current1DArray); - _mesa_reference_texobj(&texstate->SavedRef2DArray[u], ctx->Texture.Unit[u].Current2DArray); + _mesa_reference_texobj(&texstate->SavedTexRef[u][TEXTURE_1D_INDEX], + ctx->Texture.Unit[u].Current1D); + _mesa_reference_texobj(&texstate->SavedTexRef[u][TEXTURE_2D_INDEX], + ctx->Texture.Unit[u].Current2D); + _mesa_reference_texobj(&texstate->SavedTexRef[u][TEXTURE_3D_INDEX], + ctx->Texture.Unit[u].Current3D); + _mesa_reference_texobj(&texstate->SavedTexRef[u][TEXTURE_CUBE_INDEX], + ctx->Texture.Unit[u].CurrentCubeMap); + _mesa_reference_texobj(&texstate->SavedTexRef[u][TEXTURE_RECT_INDEX], + ctx->Texture.Unit[u].CurrentRect); + _mesa_reference_texobj(&texstate->SavedTexRef[u][TEXTURE_1D_ARRAY_INDEX], + ctx->Texture.Unit[u].Current1DArray); + _mesa_reference_texobj(&texstate->SavedTexRef[u][TEXTURE_2D_ARRAY_INDEX], + ctx->Texture.Unit[u].Current2DArray); } /* copy state/contents of the currently bound texture objects */ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { - _mesa_copy_texture_object(&texstate->Saved1D[u], + _mesa_copy_texture_object(&texstate->SavedObj[u][TEXTURE_1D_INDEX], ctx->Texture.Unit[u].Current1D); - _mesa_copy_texture_object(&texstate->Saved2D[u], + _mesa_copy_texture_object(&texstate->SavedObj[u][TEXTURE_2D_INDEX], ctx->Texture.Unit[u].Current2D); - _mesa_copy_texture_object(&texstate->Saved3D[u], + _mesa_copy_texture_object(&texstate->SavedObj[u][TEXTURE_3D_INDEX], ctx->Texture.Unit[u].Current3D); - _mesa_copy_texture_object(&texstate->SavedCube[u], + _mesa_copy_texture_object(&texstate->SavedObj[u][TEXTURE_CUBE_INDEX], ctx->Texture.Unit[u].CurrentCubeMap); - _mesa_copy_texture_object(&texstate->SavedRect[u], + _mesa_copy_texture_object(&texstate->SavedObj[u][TEXTURE_RECT_INDEX], ctx->Texture.Unit[u].CurrentRect); - _mesa_copy_texture_object(&texstate->Saved1DArray[u], + _mesa_copy_texture_object(&texstate->SavedObj[u][TEXTURE_1D_ARRAY_INDEX], ctx->Texture.Unit[u].Current1DArray); - _mesa_copy_texture_object(&texstate->Saved2DArray[u], + _mesa_copy_texture_object(&texstate->SavedObj[u][TEXTURE_2D_ARRAY_INDEX], ctx->Texture.Unit[u].Current2DArray); } @@ -773,45 +768,22 @@ pop_texture_group(GLcontext *ctx, struct texture_state *texstate) GLfloat bordColor[4]; GLenum target; - switch (tgt) { - case TEXTURE_1D_INDEX: - obj = &texstate->Saved1D[u]; - ASSERT(obj->Target == GL_TEXTURE_1D); - break; - case TEXTURE_2D_INDEX: - obj = &texstate->Saved2D[u]; - ASSERT(obj->Target == GL_TEXTURE_2D); - break; - case TEXTURE_3D_INDEX: - obj = &texstate->Saved3D[u]; - ASSERT(obj->Target == GL_TEXTURE_3D); - break; - case TEXTURE_CUBE_INDEX: - if (!ctx->Extensions.ARB_texture_cube_map) - continue; - obj = &texstate->SavedCube[u]; - ASSERT(obj->Target == GL_TEXTURE_CUBE_MAP_ARB); - break; - case TEXTURE_RECT_INDEX: - if (!ctx->Extensions.NV_texture_rectangle) - continue; - obj = &texstate->SavedRect[u]; - ASSERT(obj->Target == GL_TEXTURE_RECTANGLE_NV); - break; - case TEXTURE_1D_ARRAY_INDEX: - if (!ctx->Extensions.MESA_texture_array) - continue; - obj = &texstate->Saved1DArray[u]; - ASSERT(obj->Target == GL_TEXTURE_1D_ARRAY_EXT); - break; - case TEXTURE_2D_ARRAY_INDEX: - if (!ctx->Extensions.MESA_texture_array) - continue; - obj = &texstate->Saved2DArray[u]; - ASSERT(obj->Target == GL_TEXTURE_2D_ARRAY_EXT); - break; - default: - _mesa_problem(ctx, "bad texture index in pop_texture_group"); + obj = &texstate->SavedObj[u][tgt]; + + /* don't restore state for unsupported targets to prevent + * raising GL errors. + */ + if (obj->Target == GL_TEXTURE_CUBE_MAP_ARB && + !ctx->Extensions.ARB_texture_cube_map) { + continue; + } + else if (obj->Target == GL_TEXTURE_RECTANGLE_NV && + !ctx->Extensions.NV_texture_rectangle) { + continue; + } + else if ((obj->Target == GL_TEXTURE_1D_ARRAY_EXT || + obj->Target == GL_TEXTURE_2D_ARRAY_EXT) && + !ctx->Extensions.MESA_texture_array) { continue; } @@ -854,13 +826,9 @@ pop_texture_group(GLcontext *ctx, struct texture_state *texstate) } /* remove saved references to the texture objects */ - _mesa_reference_texobj(&texstate->SavedRef1D[u], NULL); - _mesa_reference_texobj(&texstate->SavedRef2D[u], NULL); - _mesa_reference_texobj(&texstate->SavedRef3D[u], NULL); - _mesa_reference_texobj(&texstate->SavedRefCube[u], NULL); - _mesa_reference_texobj(&texstate->SavedRefRect[u], NULL); - _mesa_reference_texobj(&texstate->SavedRef1DArray[u], NULL); - _mesa_reference_texobj(&texstate->SavedRef2DArray[u], NULL); + for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) { + _mesa_reference_texobj(&texstate->SavedTexRef[u][tgt], NULL); + } } _mesa_ActiveTextureARB(GL_TEXTURE0_ARB + texstate->Texture.CurrentUnit); @@ -1483,16 +1451,12 @@ _mesa_free_attrib_data(GLcontext *ctx) while (attr) { if (attr->kind == GL_TEXTURE_BIT) { struct texture_state *texstate = (struct texture_state*)attr->data; - GLuint u; + GLuint u, tgt; /* clear references to the saved texture objects */ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { - _mesa_reference_texobj(&texstate->SavedRef1D[u], NULL); - _mesa_reference_texobj(&texstate->SavedRef2D[u], NULL); - _mesa_reference_texobj(&texstate->SavedRef3D[u], NULL); - _mesa_reference_texobj(&texstate->SavedRefCube[u], NULL); - _mesa_reference_texobj(&texstate->SavedRefRect[u], NULL); - _mesa_reference_texobj(&texstate->SavedRef1DArray[u], NULL); - _mesa_reference_texobj(&texstate->SavedRef2DArray[u], NULL); + for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) { + _mesa_reference_texobj(&texstate->SavedTexRef[u][tgt], NULL); + } } } else { -- cgit v1.2.3