From c223c6b663cd5db39ba19c2be74b88cc3b8f53f3 Mon Sep 17 00:00:00 2001 From: Brian Date: Wed, 4 Jul 2007 13:15:20 -0600 Subject: Be more consistant with paths in #includes. Eventually, eliminate a bunch of -I flags. --- src/mesa/main/context.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/mesa/main/context.c') diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index 255023c0fa..21adcf3210 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -97,12 +97,9 @@ #include "fog.h" #include "framebuffer.h" #include "get.h" -#include "glthread.h" -#include "glapioffsets.h" #include "histogram.h" #include "hint.h" #include "hash.h" -#include "atifragshader.h" #include "light.h" #include "lines.h" #include "macros.h" @@ -110,9 +107,6 @@ #include "pixel.h" #include "points.h" #include "polygon.h" -#if FEATURE_NV_vertex_program || FEATURE_NV_fragment_program -#include "program.h" -#endif #include "queryobj.h" #include "rastpos.h" #include "simple_list.h" @@ -126,13 +120,19 @@ #include "varray.h" #include "version.h" #include "vtxfmt.h" +#include "glapi/glthread.h" +#include "glapi/glapioffsets.h" +#if FEATURE_NV_vertex_program || FEATURE_NV_fragment_program +#include "shader/program.h" +#endif +#include "shader/shader_api.h" +#include "shader/atifragshader.h" #if _HAVE_FULL_GL #include "math/m_translate.h" #include "math/m_matrix.h" #include "math/m_xform.h" #include "math/mathmod.h" #endif -#include "shader_api.h" #ifdef USE_SPARC_ASM #include "sparc/sparc.h" -- cgit v1.2.3 From cbfe29cdee5d338a25f13abbbb191b80428d05c8 Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Mon, 16 Jul 2007 18:21:36 +0200 Subject: fix bogus fb/drawable information the framebuffer objects attached to drawables can have invalidate state associated with them, since for the window framebuffer this is per-context state and not per-fbo state. Since drivers rely on that information (otherwise would need to check if currently the window-framebuffer is bound in a lot of places) fix it up in _mesa_make_current (ugly). (Brought over from i915tex_privbuffers, where it fixes xdemos/wincopy when switching to front buffer rendering.) --- src/mesa/main/context.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/mesa/main/context.c') diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index 21adcf3210..2ad1badac7 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -1495,9 +1495,20 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer, */ if (!newCtx->DrawBuffer || newCtx->DrawBuffer->Name == 0) { _mesa_reference_framebuffer(&newCtx->DrawBuffer, drawBuffer); + /* fix up the fb fields - these will end up wrong otherwise + if the DRIdrawable changes, and someone may rely on them. + */ + /* What a mess!?! */ + int i; + GLenum buffers[MAX_DRAW_BUFFERS]; + for(i = 0; i < newCtx->Const.MaxDrawBuffers; i++) { + buffers[i] = newCtx->Color.DrawBuffer[i]; + } + _mesa_drawbuffers(newCtx, newCtx->Const.MaxDrawBuffers, buffers, NULL); } if (!newCtx->ReadBuffer || newCtx->ReadBuffer->Name == 0) { _mesa_reference_framebuffer(&newCtx->ReadBuffer, readBuffer); + _mesa_ReadBuffer(newCtx->Pixel.ReadBuffer); } newCtx->NewState |= _NEW_BUFFERS; -- cgit v1.2.3 From 6075df53b5435ddada989d776d989132def363a6 Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Wed, 18 Jul 2007 18:07:12 +0200 Subject: more fixes for mesa's fbo handling (fixes tests/fbotest1/2) --- src/mesa/main/buffers.c | 5 ++--- src/mesa/main/context.c | 5 +++++ src/mesa/main/fbobject.c | 7 +++++++ 3 files changed, 14 insertions(+), 3 deletions(-) (limited to 'src/mesa/main/context.c') diff --git a/src/mesa/main/buffers.c b/src/mesa/main/buffers.c index c280f89e1d..68a0575d93 100644 --- a/src/mesa/main/buffers.c +++ b/src/mesa/main/buffers.c @@ -557,9 +557,8 @@ _mesa_ReadBuffer(GLenum buffer) } } - if (fb->Name == 0) { - ctx->Pixel.ReadBuffer = buffer; - } + ctx->Pixel.ReadBuffer = buffer; + fb->ColorReadBuffer = buffer; fb->_ColorReadBufferIndex = srcBuffer; diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index 2ad1badac7..4e6732dc7a 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -1499,6 +1499,11 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer, if the DRIdrawable changes, and someone may rely on them. */ /* What a mess!?! */ + /* XXX this is still not quite correct. Imagine a user-created fbo + bound on a context. Now rebind with a completely new drawable. + Upon rebinding to the window-framebuffer, we have no idea what + the read and write buffers should be (front, back, ...) - that + information was only available in the previously used drawable... */ int i; GLenum buffers[MAX_DRAW_BUFFERS]; for(i = 0; i < newCtx->Const.MaxDrawBuffers; i++) { diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c index 5345310ca1..f300e481ce 100644 --- a/src/mesa/main/fbobject.c +++ b/src/mesa/main/fbobject.c @@ -1003,13 +1003,20 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) if (bindReadBuf) { _mesa_reference_framebuffer(&ctx->ReadBuffer, newFbread); + /* set context value */ + ctx->Pixel.ReadBuffer = newFbread->ColorReadBuffer; } if (bindDrawBuf) { + GLuint i; /* check if old FB had any texture attachments */ check_end_texture_render(ctx, ctx->DrawBuffer); /* check if time to delete this framebuffer */ _mesa_reference_framebuffer(&ctx->DrawBuffer, newFb); + /* set context value */ + for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) { + ctx->Color.DrawBuffer[i] = newFb->ColorDrawBuffer[i]; + } if (newFb->Name != 0) { /* check if newly bound framebuffer has any texture attachments */ check_begin_texture_render(ctx, newFb); -- cgit v1.2.3 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 +++ src/mesa/main/buffers.c | 72 ++++++++++++++++++++++++++++++--------------- src/mesa/main/buffers.h | 3 ++ src/mesa/main/context.c | 12 ++------ src/mesa/main/fbobject.c | 24 ++++++++++----- src/mesa/main/framebuffer.c | 3 +- 6 files changed, 77 insertions(+), 41 deletions(-) (limited to 'src/mesa/main/context.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; diff --git a/src/mesa/main/buffers.c b/src/mesa/main/buffers.c index 68a0575d93..7764a5d3b2 100644 --- a/src/mesa/main/buffers.c +++ b/src/mesa/main/buffers.c @@ -370,6 +370,14 @@ _mesa_DrawBuffer(GLenum buffer) /* if we get here, there's no error so set new state */ _mesa_drawbuffers(ctx, 1, &buffer, &destMask); + + /* + * Call device driver function. + */ + if (ctx->Driver.DrawBuffers) + ctx->Driver.DrawBuffers(ctx, 1, &buffer); + else if (ctx->Driver.DrawBuffer) + ctx->Driver.DrawBuffer(ctx, buffer); } @@ -435,6 +443,14 @@ _mesa_DrawBuffersARB(GLsizei n, const GLenum *buffers) /* OK, if we get here, there were no errors so set the new state */ _mesa_drawbuffers(ctx, n, buffers, destMask); + + /* + * Call device driver function. + */ + if (ctx->Driver.DrawBuffers) + ctx->Driver.DrawBuffers(ctx, n, buffers); + else if (ctx->Driver.DrawBuffer) + ctx->Driver.DrawBuffer(ctx, buffers[0]); } @@ -463,14 +479,15 @@ set_color_output(GLcontext *ctx, GLuint output, GLenum buffer, /* not really needed, will be set later */ fb->_NumColorDrawBuffers[output] = 0; + if (fb->Name == 0) /* Set traditional state var */ - ctx->Color.DrawBuffer[output] = buffer; + ctx->Color.DrawBuffer[output] = buffer; } /** * Helper routine used by _mesa_DrawBuffer, _mesa_DrawBuffersARB and - * _mesa_PopAttrib to set drawbuffer state. + * other places (window fbo fixup) to set fbo (and the old ctx) fields. * All error checking will have been done prior to calling this function * so nothing should go wrong at this point. * \param ctx current context @@ -479,6 +496,7 @@ set_color_output(GLcontext *ctx, GLuint output, GLenum buffer, * \param destMask array[n] of BUFFER_* bitmasks which correspond to the * colorbuffer names. (i.e. GL_FRONT_AND_BACK => * BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT). + * \param callDriver call driver or not (bad idea sometimes this is called) */ void _mesa_drawbuffers(GLcontext *ctx, GLuint n, const GLenum *buffers, @@ -509,30 +527,15 @@ _mesa_drawbuffers(GLcontext *ctx, GLuint n, const GLenum *buffers, } ctx->NewState |= _NEW_COLOR; - - /* - * Call device driver function. - */ - if (ctx->Driver.DrawBuffers) - ctx->Driver.DrawBuffers(ctx, n, buffers); - else if (ctx->Driver.DrawBuffer) - ctx->Driver.DrawBuffer(ctx, buffers[0]); } - -/** - * Called by glReadBuffer to set the source renderbuffer for reading pixels. - * \param mode color buffer such as GL_FRONT, GL_BACK, etc. - */ -void GLAPIENTRY -_mesa_ReadBuffer(GLenum buffer) +GLboolean +_mesa_readbuffer_update_fields(GLcontext *ctx, GLenum buffer) { struct gl_framebuffer *fb; GLbitfield supportedMask; GLint srcBuffer; - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); fb = ctx->ReadBuffer; @@ -548,20 +551,43 @@ _mesa_ReadBuffer(GLenum buffer) srcBuffer = read_buffer_enum_to_index(buffer); if (srcBuffer == -1) { _mesa_error(ctx, GL_INVALID_ENUM, "glReadBuffer(buffer=0x%x)", buffer); - return; + return GL_FALSE; } supportedMask = supported_buffer_bitmask(ctx, fb); if (((1 << srcBuffer) & supportedMask) == 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "glReadBuffer(buffer=0x%x)", buffer); - return; + return GL_FALSE; } } - ctx->Pixel.ReadBuffer = buffer; - + if (fb->Name == 0) { + ctx->Pixel.ReadBuffer = buffer; + } fb->ColorReadBuffer = buffer; fb->_ColorReadBufferIndex = srcBuffer; + return GL_TRUE; +} + + + +/** + * Called by glReadBuffer to set the source renderbuffer for reading pixels. + * \param mode color buffer such as GL_FRONT, GL_BACK, etc. + * \param callDriver call driver or not (bad idea sometimes this is called) + */ +void GLAPIENTRY +_mesa_ReadBuffer(GLenum buffer) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); + + if (!_mesa_readbuffer_update_fields(ctx, buffer)) + return; + ctx->NewState |= _NEW_PIXEL; /* diff --git a/src/mesa/main/buffers.h b/src/mesa/main/buffers.h index fcc2152342..208e7af2b9 100644 --- a/src/mesa/main/buffers.h +++ b/src/mesa/main/buffers.h @@ -56,6 +56,9 @@ extern void _mesa_drawbuffers(GLcontext *ctx, GLuint n, const GLenum *buffers, const GLbitfield *destMask); +extern GLboolean +_mesa_readbuffer_update_fields(GLcontext *ctx, GLenum buffer); + extern void GLAPIENTRY _mesa_ReadBuffer( GLenum mode ); diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index 4e6732dc7a..00e4c8328e 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -1496,14 +1496,8 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer, if (!newCtx->DrawBuffer || newCtx->DrawBuffer->Name == 0) { _mesa_reference_framebuffer(&newCtx->DrawBuffer, drawBuffer); /* fix up the fb fields - these will end up wrong otherwise - if the DRIdrawable changes, and someone may rely on them. - */ - /* What a mess!?! */ - /* XXX this is still not quite correct. Imagine a user-created fbo - bound on a context. Now rebind with a completely new drawable. - Upon rebinding to the window-framebuffer, we have no idea what - the read and write buffers should be (front, back, ...) - that - information was only available in the previously used drawable... */ + if the DRIdrawable changes, and everything relies on them. + This is a bit messy (same as needed in _mesa_BindFramebufferEXT) */ int i; GLenum buffers[MAX_DRAW_BUFFERS]; for(i = 0; i < newCtx->Const.MaxDrawBuffers; i++) { @@ -1513,7 +1507,7 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer, } if (!newCtx->ReadBuffer || newCtx->ReadBuffer->Name == 0) { _mesa_reference_framebuffer(&newCtx->ReadBuffer, readBuffer); - _mesa_ReadBuffer(newCtx->Pixel.ReadBuffer); + _mesa_readbuffer_update_fields(newCtx, newCtx->Pixel.ReadBuffer); } newCtx->NewState |= _NEW_BUFFERS; diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c index f300e481ce..6f7effcce7 100644 --- a/src/mesa/main/fbobject.c +++ b/src/mesa/main/fbobject.c @@ -29,6 +29,7 @@ */ +#include "buffers.h" #include "context.h" #include "fbobject.h" #include "framebuffer.h" @@ -1001,23 +1002,32 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) * XXX check if re-binding same buffer and skip some of this code. */ + /* for window-framebuffers, re-initialize the fbo values, as they + could be wrong (makecurrent with a new drawable while still a fbo + was bound will lead to default init fbo values). + note that therefore the context ReadBuffer/DrawBuffer values are not + valid while fbo's are bound!!! */ if (bindReadBuf) { _mesa_reference_framebuffer(&ctx->ReadBuffer, newFbread); - /* set context value */ - ctx->Pixel.ReadBuffer = newFbread->ColorReadBuffer; + if (!newFbread->Name) { + _mesa_readbuffer_update_fields(ctx, ctx->Pixel.ReadBuffer); + } } if (bindDrawBuf) { - GLuint i; /* check if old FB had any texture attachments */ check_end_texture_render(ctx, ctx->DrawBuffer); /* check if time to delete this framebuffer */ _mesa_reference_framebuffer(&ctx->DrawBuffer, newFb); - /* set context value */ - for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) { - ctx->Color.DrawBuffer[i] = newFb->ColorDrawBuffer[i]; + if (!newFb->Name) { + GLuint i; + GLenum buffers[MAX_DRAW_BUFFERS]; + for(i = 0; i < ctx->Const.MaxDrawBuffers; i++) { + buffers[i] = ctx->Color.DrawBuffer[i]; + } + _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers, buffers, NULL); } - if (newFb->Name != 0) { + else { /* check if newly bound framebuffer has any texture attachments */ check_begin_texture_render(ctx, newFb); } diff --git a/src/mesa/main/framebuffer.c b/src/mesa/main/framebuffer.c index 2ff067164b..c9b30d3252 100644 --- a/src/mesa/main/framebuffer.c +++ b/src/mesa/main/framebuffer.c @@ -695,8 +695,7 @@ _mesa_update_framebuffer(GLcontext *ctx) struct gl_framebuffer *fbread = ctx->ReadBuffer; update_framebuffer(ctx, fb); - if (fbread != fb && fbread != NULL /* can happen at make_current - - core/driver circular dependencies, should be fixed up */) + if (fbread != fb) update_framebuffer(ctx, fbread); } -- cgit v1.2.3 From 6f4725088842fbc0069aeb51f41907b87e0a8f08 Mon Sep 17 00:00:00 2001 From: Brian Date: Mon, 13 Aug 2007 11:09:48 +0100 Subject: added some missing Default1D/2DArray texture code --- src/mesa/main/context.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/mesa/main/context.c') diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index 00e4c8328e..6fa32b320a 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -552,6 +552,10 @@ alloc_shared_state( GLcontext *ctx ) (*ctx->Driver.DeleteTexture)(ctx, ss->DefaultCubeMap); if (ss->DefaultRect) (*ctx->Driver.DeleteTexture)(ctx, ss->DefaultRect); + if (ss->Default1DArray) + (*ctx->Driver.DeleteTexture)(ctx, ss->Default1DArray); + if (ss->Default2DArray) + (*ctx->Driver.DeleteTexture)(ctx, ss->Default2DArray); if (ss) _mesa_free(ss); return GL_FALSE; @@ -676,6 +680,9 @@ free_shared_state( GLcontext *ctx, struct gl_shared_state *ss ) ctx->Driver.DeleteTexture(ctx, ss->Default3D); ctx->Driver.DeleteTexture(ctx, ss->DefaultCubeMap); ctx->Driver.DeleteTexture(ctx, ss->DefaultRect); + ctx->Driver.DeleteTexture(ctx, ss->Default1DArray); + ctx->Driver.DeleteTexture(ctx, ss->Default2DArray); + /* all other textures */ _mesa_HashDeleteAll(ss->TexObjects, delete_texture_cb, ctx); _mesa_DeleteHashTable(ss->TexObjects); -- 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/context.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 393a6255381f019586bd9acc49fbf2fd431e534e Mon Sep 17 00:00:00 2001 From: Brian Date: Mon, 13 Aug 2007 17:37:30 +0100 Subject: free any render/framebuffers left in hash tables when freeing shared state --- src/mesa/main/context.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'src/mesa/main/context.c') diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index f360eac1e7..5fbc69693e 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -640,6 +640,27 @@ delete_shader_cb(GLuint id, void *data, void *userData) } } +/** + * Callback for deleting a framebuffer object. Called by _mesa_HashDeleteAll() + */ +static void +delete_framebuffer_cb(GLuint id, void *data, void *userData) +{ + struct gl_framebuffer *fb = (struct gl_framebuffer *) data; + fb->Delete(fb); +} + +/** + * Callback for deleting a renderbuffer object. Called by _mesa_HashDeleteAll() + */ +static void +delete_renderbuffer_cb(GLuint id, void *data, void *userData) +{ + struct gl_renderbuffer *rb = (struct gl_renderbuffer *) data; + rb->Delete(rb); +} + + /** * Deallocate a shared state object and all children structures. @@ -710,7 +731,9 @@ free_shared_state( GLcontext *ctx, struct gl_shared_state *ss ) #endif #if FEATURE_EXT_framebuffer_object + _mesa_HashDeleteAll(ss->FrameBuffers, delete_framebuffer_cb, ctx); _mesa_DeleteHashTable(ss->FrameBuffers); + _mesa_HashDeleteAll(ss->RenderBuffers, delete_renderbuffer_cb, ctx); _mesa_DeleteHashTable(ss->RenderBuffers); #endif -- cgit v1.2.3 From dc73217294efcba83c46183ed2f208250217486f Mon Sep 17 00:00:00 2001 From: Brian Date: Tue, 14 Aug 2007 11:56:59 +0100 Subject: Fix a few more problems with freeing FBOs/textures during context destruction. Free FBOs before textures since the later may be referenced by the former. Need to bind the context we're destroying if there isn't a current context so that ctx->DeleteTexture() etc can be used. --- src/mesa/main/context.c | 66 +++++++++++++++++++++++++++++-------------------- src/mesa/main/texobj.c | 5 +++- 2 files changed, 43 insertions(+), 28 deletions(-) (limited to 'src/mesa/main/context.c') diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index 5fbc69693e..37a14d3004 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -647,6 +647,11 @@ static void delete_framebuffer_cb(GLuint id, void *data, void *userData) { struct gl_framebuffer *fb = (struct gl_framebuffer *) data; + /* The fact that the framebuffer is in the hashtable means its refcount + * is one, but we're removing from the hashtable now. So clear refcount. + */ + /*assert(fb->RefCount == 1);*/ + fb->RefCount = 0; fb->Delete(fb); } @@ -657,6 +662,7 @@ static void delete_renderbuffer_cb(GLuint id, void *data, void *userData) { struct gl_renderbuffer *rb = (struct gl_renderbuffer *) data; + rb->RefCount = 0; /* see comment for FBOs above */ rb->Delete(rb); } @@ -683,23 +689,6 @@ free_shared_state( GLcontext *ctx, struct gl_shared_state *ss ) _mesa_HashDeleteAll(ss->DisplayList, delete_displaylist_cb, ctx); _mesa_DeleteHashTable(ss->DisplayList); - /* - * Free texture objects - */ - ASSERT(ctx->Driver.DeleteTexture); - /* the default textures */ - ctx->Driver.DeleteTexture(ctx, ss->Default1D); - ctx->Driver.DeleteTexture(ctx, ss->Default2D); - ctx->Driver.DeleteTexture(ctx, ss->Default3D); - ctx->Driver.DeleteTexture(ctx, ss->DefaultCubeMap); - ctx->Driver.DeleteTexture(ctx, ss->DefaultRect); - ctx->Driver.DeleteTexture(ctx, ss->Default1DArray); - ctx->Driver.DeleteTexture(ctx, ss->Default2DArray); - - /* all other textures */ - _mesa_HashDeleteAll(ss->TexObjects, delete_texture_cb, ctx); - _mesa_DeleteHashTable(ss->TexObjects); - #if defined(FEATURE_NV_vertex_program) || defined(FEATURE_NV_fragment_program) _mesa_HashDeleteAll(ss->Programs, delete_program_cb, ctx); _mesa_DeleteHashTable(ss->Programs); @@ -737,6 +726,23 @@ free_shared_state( GLcontext *ctx, struct gl_shared_state *ss ) _mesa_DeleteHashTable(ss->RenderBuffers); #endif + /* + * Free texture objects (after FBOs since some textures might have + * been bound to FBOs). + */ + ASSERT(ctx->Driver.DeleteTexture); + /* the default textures */ + ctx->Driver.DeleteTexture(ctx, ss->Default1D); + ctx->Driver.DeleteTexture(ctx, ss->Default2D); + ctx->Driver.DeleteTexture(ctx, ss->Default3D); + ctx->Driver.DeleteTexture(ctx, ss->DefaultCubeMap); + ctx->Driver.DeleteTexture(ctx, ss->DefaultRect); + ctx->Driver.DeleteTexture(ctx, ss->Default1DArray); + ctx->Driver.DeleteTexture(ctx, ss->Default2DArray); + /* all other textures */ + _mesa_HashDeleteAll(ss->TexObjects, delete_texture_cb, ctx); + _mesa_DeleteHashTable(ss->TexObjects); + _glthread_DESTROY_MUTEX(ss->Mutex); _mesa_free(ss); @@ -1190,18 +1196,19 @@ _mesa_create_context(const GLvisual *visual, void _mesa_free_context_data( GLcontext *ctx ) { - /* if we're destroying the current context, unbind it first */ - if (ctx == _mesa_get_current_context()) { - _mesa_make_current(NULL, NULL, NULL); - } - else { - /* unreference WinSysDraw/Read buffers */ - _mesa_unreference_framebuffer(&ctx->WinSysDrawBuffer); - _mesa_unreference_framebuffer(&ctx->WinSysReadBuffer); - _mesa_unreference_framebuffer(&ctx->DrawBuffer); - _mesa_unreference_framebuffer(&ctx->ReadBuffer); + if (!_mesa_get_current_context()){ + /* No current context, but we may need one in order to delete + * texture objs, etc. So temporarily bind the context now. + */ + _mesa_make_current(ctx, NULL, NULL); } + /* unreference WinSysDraw/Read buffers */ + _mesa_unreference_framebuffer(&ctx->WinSysDrawBuffer); + _mesa_unreference_framebuffer(&ctx->WinSysReadBuffer); + _mesa_unreference_framebuffer(&ctx->DrawBuffer); + _mesa_unreference_framebuffer(&ctx->ReadBuffer); + _mesa_free_lighting_data( ctx ); _mesa_free_eval_data( ctx ); _mesa_free_texture_data( ctx ); @@ -1233,6 +1240,11 @@ _mesa_free_context_data( GLcontext *ctx ) if (ctx->Extensions.String) _mesa_free((void *) ctx->Extensions.String); + + /* unbind the context if it's currently bound */ + if (ctx == _mesa_get_current_context()) { + _mesa_make_current(NULL, NULL, NULL); + } } diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c index ac70e5a22e..ea3328a047 100644 --- a/src/mesa/main/texobj.c +++ b/src/mesa/main/texobj.c @@ -287,7 +287,10 @@ _mesa_reference_texobj(struct gl_texture_object **ptr, if (deleteFlag) { GET_CURRENT_CONTEXT(ctx); - ctx->Driver.DeleteTexture(ctx, oldTex); + if (ctx) + ctx->Driver.DeleteTexture(ctx, oldTex); + else + _mesa_problem(NULL, "Unable to delete texture, no context"); } *ptr = NULL; -- 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/context.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 32d86eb28aedd01a03ceab746214a8db2a4cbbab Mon Sep 17 00:00:00 2001 From: Brian Date: Thu, 16 Aug 2007 18:52:48 +0100 Subject: Rework the GL_READ_BUFFER, GL_DRAW_BUFFER state repairs that Roland previously did. Basically, in update_framebuffer() (which should be called after an FBO is bound with MakeCurrent or BindFramebuffer) we check if the FBO is a window-system FBO. If it is, update the FBO's GL_READ/DRAW_BUFFER state according to the context state. Old code still in place but disabled with #if 0 / #endif. --- src/mesa/main/buffers.c | 86 ++++++++++++++++++++++++++++++++++++++++++--- src/mesa/main/buffers.h | 9 +++-- src/mesa/main/context.c | 7 ++++ src/mesa/main/fbobject.c | 21 ++++++++--- src/mesa/main/framebuffer.c | 26 ++++++++++---- 5 files changed, 131 insertions(+), 18 deletions(-) (limited to 'src/mesa/main/context.c') diff --git a/src/mesa/main/buffers.c b/src/mesa/main/buffers.c index 82dd059e4b..94b4be54d5 100644 --- a/src/mesa/main/buffers.c +++ b/src/mesa/main/buffers.c @@ -336,6 +336,20 @@ read_buffer_enum_to_index(GLenum buffer) * \sa _mesa_DrawBuffersARB * * \param buffer buffer token such as GL_LEFT or GL_FRONT_AND_BACK, etc. + * + * Note that the behaviour of this function depends on whether the + * current ctx->DrawBuffer is a window-system framebuffer (Name=0) or + * a user-created framebuffer object (Name!=0). + * In the former case, we update the per-context ctx->Color.DrawBuffer + * state var _and_ the FB's ColorDrawBuffer state. + * In the later case, we update the FB's ColorDrawBuffer state only. + * + * Furthermore, upon a MakeCurrent() or BindFramebuffer() call, if the + * new FB is a window system FB, we need to re-update the FB's + * ColorDrawBuffer state to match the context. This is handled in + * _mesa_update_framebuffer(). + * + * See the GL_EXT_framebuffer_object spec for more info. */ void GLAPIENTRY _mesa_DrawBuffer(GLenum buffer) @@ -489,10 +503,12 @@ set_color_output(GLcontext *ctx, GLuint output, GLenum buffer, /** - * Helper routine used by _mesa_DrawBuffer, _mesa_DrawBuffersARB and - * other places (window fbo fixup) to set fbo (and the old ctx) fields. + * Helper function to set the GL_DRAW_BUFFER state in the context and + * current FBO. + * * All error checking will have been done prior to calling this function * so nothing should go wrong at this point. + * * \param ctx current context * \param n number of color outputs to set * \param buffers array[n] of colorbuffer names, like GL_LEFT. @@ -532,6 +548,7 @@ _mesa_drawbuffers(GLcontext *ctx, GLuint n, const GLenum *buffers, } +#if 0 GLboolean _mesa_readbuffer_update_fields(GLcontext *ctx, GLenum buffer) { @@ -563,13 +580,45 @@ _mesa_readbuffer_update_fields(GLcontext *ctx, GLenum buffer) } if (fb->Name == 0) { + /* Only update the per-context GL_READ_BUFFER state if we're bound to + * a window-system framebuffer. + */ ctx->Pixel.ReadBuffer = buffer; } + + /* Set the FBO's GL_READ_BUFFER state */ fb->ColorReadBuffer = buffer; fb->_ColorReadBufferIndex = srcBuffer; return GL_TRUE; } +#endif + + +/** + * Like \sa _mesa_drawbuffers(), this is a helper function for setting + * GL_READ_BUFFER state in the context and current FBO. + * \param ctx the rendering context + * \param buffer GL_FRONT, GL_BACK, GL_COLOR_ATTACHMENT0, etc. + * \param bufferIndex the numerical index corresponding to 'buffer' + */ +void +_mesa_readbuffer(GLcontext *ctx, GLenum buffer, GLint bufferIndex) +{ + struct gl_framebuffer *fb = ctx->ReadBuffer; + + if (fb->Name == 0) { + /* Only update the per-context READ_BUFFER state if we're bound to + * a window-system framebuffer. + */ + ctx->Pixel.ReadBuffer = buffer; + } + + fb->ColorReadBuffer = buffer; + fb->_ColorReadBufferIndex = bufferIndex; + + ctx->NewState |= _NEW_PIXEL; +} @@ -580,16 +629,43 @@ _mesa_readbuffer_update_fields(GLcontext *ctx, GLenum buffer) void GLAPIENTRY _mesa_ReadBuffer(GLenum buffer) { + struct gl_framebuffer *fb; + GLbitfield supportedMask; + GLint srcBuffer; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); - if (!_mesa_readbuffer_update_fields(ctx, buffer)) - return; + fb = ctx->ReadBuffer; - ctx->NewState |= _NEW_PIXEL; + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); + + if (fb->Name > 0 && buffer == GL_NONE) { + /* This is legal for user-created framebuffer objects */ + srcBuffer = -1; + } + else { + /* general case / window-system framebuffer */ + srcBuffer = read_buffer_enum_to_index(buffer); + if (srcBuffer == -1) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glReadBuffer(buffer=0x%x)", buffer); + return; + } + supportedMask = supported_buffer_bitmask(ctx, fb); + if (((1 << srcBuffer) & supportedMask) == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glReadBuffer(buffer=0x%x)", buffer); + return; + } + } + + /* OK, all error checking has been completed now */ + + _mesa_readbuffer(ctx, buffer, srcBuffer); /* * Call device driver function. diff --git a/src/mesa/main/buffers.h b/src/mesa/main/buffers.h index 208e7af2b9..e7228a6da6 100644 --- a/src/mesa/main/buffers.h +++ b/src/mesa/main/buffers.h @@ -5,9 +5,9 @@ /* * Mesa 3-D graphics library - * Version: 6.5 + * Version: 7.1 * - * Copyright (C) 1999-2005 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"), @@ -56,8 +56,13 @@ extern void _mesa_drawbuffers(GLcontext *ctx, GLuint n, const GLenum *buffers, const GLbitfield *destMask); +extern void +_mesa_readbuffer(GLcontext *ctx, GLenum buffer, GLint bufferIndex); + +#if 0 extern GLboolean _mesa_readbuffer_update_fields(GLcontext *ctx, GLenum buffer); +#endif extern void GLAPIENTRY _mesa_ReadBuffer( GLenum mode ); diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index f3141fe63e..9ee7b4bec7 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -1530,6 +1530,7 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer, */ if (!newCtx->DrawBuffer || newCtx->DrawBuffer->Name == 0) { _mesa_reference_framebuffer(&newCtx->DrawBuffer, drawBuffer); +#if 000 /* fix up the fb fields - these will end up wrong otherwise if the DRIdrawable changes, and everything relies on them. This is a bit messy (same as needed in _mesa_BindFramebufferEXT) */ @@ -1539,12 +1540,18 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer, buffers[i] = newCtx->Color.DrawBuffer[i]; } _mesa_drawbuffers(newCtx, newCtx->Const.MaxDrawBuffers, buffers, NULL); +#endif } if (!newCtx->ReadBuffer || newCtx->ReadBuffer->Name == 0) { _mesa_reference_framebuffer(&newCtx->ReadBuffer, readBuffer); +#if 00 _mesa_readbuffer_update_fields(newCtx, newCtx->Pixel.ReadBuffer); +#endif } + /* XXX only set this flag if we're really changing the draw/read + * framebuffer bindings. + */ newCtx->NewState |= _NEW_BUFFERS; #if 1 diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c index fcb620b39d..5cd18d0287 100644 --- a/src/mesa/main/fbobject.c +++ b/src/mesa/main/fbobject.c @@ -962,9 +962,11 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) } FLUSH_VERTICES(ctx, _NEW_BUFFERS); + if (ctx->Driver.Flush) { ctx->Driver.Flush(ctx); } + if (framebuffer) { /* Binding a user-created framebuffer object */ newFb = _mesa_lookup_framebuffer(ctx, framebuffer); @@ -998,34 +1000,43 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) * XXX check if re-binding same buffer and skip some of this code. */ +#if 000 /* for window-framebuffers, re-initialize the fbo values, as they could be wrong (makecurrent with a new drawable while still a fbo was bound will lead to default init fbo values). note that therefore the context ReadBuffer/DrawBuffer values are not valid while fbo's are bound!!! */ +#endif if (bindReadBuf) { _mesa_reference_framebuffer(&ctx->ReadBuffer, newFbread); +#if 000 if (!newFbread->Name) { _mesa_readbuffer_update_fields(ctx, ctx->Pixel.ReadBuffer); } +#endif } if (bindDrawBuf) { /* check if old FB had any texture attachments */ check_end_texture_render(ctx, ctx->DrawBuffer); + /* check if time to delete this framebuffer */ _mesa_reference_framebuffer(&ctx->DrawBuffer, newFb); - if (!newFb->Name) { + + if (newFb->Name != 0) { + /* check if newly bound framebuffer has any texture attachments */ + check_begin_texture_render(ctx, newFb); + } + else { + /* XXX try to remove this: */ +#if 000 GLuint i; GLenum buffers[MAX_DRAW_BUFFERS]; for(i = 0; i < ctx->Const.MaxDrawBuffers; i++) { buffers[i] = ctx->Color.DrawBuffer[i]; } _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers, buffers, NULL); - } - else { - /* check if newly bound framebuffer has any texture attachments */ - check_begin_texture_render(ctx, newFb); +#endif } } diff --git a/src/mesa/main/framebuffer.c b/src/mesa/main/framebuffer.c index 72d85f6f89..3e36197d88 100644 --- a/src/mesa/main/framebuffer.c +++ b/src/mesa/main/framebuffer.c @@ -32,6 +32,7 @@ #include "glheader.h" #include "imports.h" +#include "buffers.h" #include "context.h" #include "depthstencil.h" #include "mtypes.h" @@ -583,7 +584,7 @@ _mesa_update_stencil_buffer(GLcontext *ctx, /** - * Update the list of color drawing renderbuffer pointers. + * Update the (derived) list of color drawing renderbuffer pointers. * Later, when we're rendering we'll loop from 0 to _NumColorDrawBuffers * writing colors. */ @@ -627,7 +628,7 @@ update_color_draw_buffers(GLcontext *ctx, struct gl_framebuffer *fb) /** - * Update the color read renderbuffer pointer. + * Update the (derived) color read renderbuffer pointer. * Unlike the DrawBuffer, we can only read from one (or zero) color buffers. */ static void @@ -668,10 +669,23 @@ update_color_read_buffer(GLcontext *ctx, struct gl_framebuffer *fb) static void update_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb) { - /* Completeness only matters for user-created framebuffers */ - if (fb->Name != 0) { - /* XXX: EXT_framebuffer_blit: - framebuffer must still be complete wrt read/draw? */ + if (fb->Name == 0) { + /* This is a window-system framebuffer */ + /* Need to update the FB's GL_DRAW_BUFFER state to match the + * context state (GL_READ_BUFFER too). + */ + if (fb->ColorDrawBuffer[0] != ctx->Color.DrawBuffer[0]) { + _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers, + ctx->Color.DrawBuffer, NULL); + } + if (fb->ColorReadBuffer != ctx->Pixel.ReadBuffer) { + + } + } + else { + /* This is a user-created framebuffer. + * Completeness only matters for user-created framebuffers. + */ _mesa_test_framebuffer_completeness(ctx, fb); _mesa_update_framebuffer_visual(fb); } -- cgit v1.2.3 From 95e84a09ce3f35f59465be28026e83c1bc40ae8a Mon Sep 17 00:00:00 2001 From: Brian Date: Sat, 18 Aug 2007 16:10:25 +0100 Subject: remove dead code left over after fixing GL_READ/DRAW_BUFFER state issues --- src/mesa/main/buffers.c | 47 ----------------------------------------------- src/mesa/main/buffers.h | 5 ----- src/mesa/main/context.c | 14 -------------- src/mesa/main/fbobject.c | 23 ----------------------- 4 files changed, 89 deletions(-) (limited to 'src/mesa/main/context.c') diff --git a/src/mesa/main/buffers.c b/src/mesa/main/buffers.c index 94b4be54d5..cbbe3e8698 100644 --- a/src/mesa/main/buffers.c +++ b/src/mesa/main/buffers.c @@ -548,53 +548,6 @@ _mesa_drawbuffers(GLcontext *ctx, GLuint n, const GLenum *buffers, } -#if 0 -GLboolean -_mesa_readbuffer_update_fields(GLcontext *ctx, GLenum buffer) -{ - struct gl_framebuffer *fb; - GLbitfield supportedMask; - GLint srcBuffer; - - fb = ctx->ReadBuffer; - - if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); - - if (fb->Name > 0 && buffer == GL_NONE) { - /* This is legal for user-created framebuffer objects */ - srcBuffer = -1; - } - else { - /* general case / window-system framebuffer */ - srcBuffer = read_buffer_enum_to_index(buffer); - if (srcBuffer == -1) { - _mesa_error(ctx, GL_INVALID_ENUM, "glReadBuffer(buffer=0x%x)", buffer); - return GL_FALSE; - } - supportedMask = supported_buffer_bitmask(ctx, fb); - if (((1 << srcBuffer) & supportedMask) == 0) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glReadBuffer(buffer=0x%x)", buffer); - return GL_FALSE; - } - } - - if (fb->Name == 0) { - /* Only update the per-context GL_READ_BUFFER state if we're bound to - * a window-system framebuffer. - */ - ctx->Pixel.ReadBuffer = buffer; - } - - /* Set the FBO's GL_READ_BUFFER state */ - fb->ColorReadBuffer = buffer; - fb->_ColorReadBufferIndex = srcBuffer; - - return GL_TRUE; -} -#endif - - /** * Like \sa _mesa_drawbuffers(), this is a helper function for setting * GL_READ_BUFFER state in the context and current FBO. diff --git a/src/mesa/main/buffers.h b/src/mesa/main/buffers.h index e7228a6da6..9c0070e00f 100644 --- a/src/mesa/main/buffers.h +++ b/src/mesa/main/buffers.h @@ -59,11 +59,6 @@ _mesa_drawbuffers(GLcontext *ctx, GLuint n, const GLenum *buffers, extern void _mesa_readbuffer(GLcontext *ctx, GLenum buffer, GLint bufferIndex); -#if 0 -extern GLboolean -_mesa_readbuffer_update_fields(GLcontext *ctx, GLenum buffer); -#endif - extern void GLAPIENTRY _mesa_ReadBuffer( GLenum mode ); diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index 9ee7b4bec7..bb48109317 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -1530,23 +1530,9 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer, */ if (!newCtx->DrawBuffer || newCtx->DrawBuffer->Name == 0) { _mesa_reference_framebuffer(&newCtx->DrawBuffer, drawBuffer); -#if 000 - /* fix up the fb fields - these will end up wrong otherwise - if the DRIdrawable changes, and everything relies on them. - This is a bit messy (same as needed in _mesa_BindFramebufferEXT) */ - int i; - GLenum buffers[MAX_DRAW_BUFFERS]; - for(i = 0; i < newCtx->Const.MaxDrawBuffers; i++) { - buffers[i] = newCtx->Color.DrawBuffer[i]; - } - _mesa_drawbuffers(newCtx, newCtx->Const.MaxDrawBuffers, buffers, NULL); -#endif } if (!newCtx->ReadBuffer || newCtx->ReadBuffer->Name == 0) { _mesa_reference_framebuffer(&newCtx->ReadBuffer, readBuffer); -#if 00 - _mesa_readbuffer_update_fields(newCtx, newCtx->Pixel.ReadBuffer); -#endif } /* XXX only set this flag if we're really changing the draw/read diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c index 5cd18d0287..db04c785de 100644 --- a/src/mesa/main/fbobject.c +++ b/src/mesa/main/fbobject.c @@ -1000,20 +1000,8 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) * XXX check if re-binding same buffer and skip some of this code. */ -#if 000 - /* for window-framebuffers, re-initialize the fbo values, as they - could be wrong (makecurrent with a new drawable while still a fbo - was bound will lead to default init fbo values). - note that therefore the context ReadBuffer/DrawBuffer values are not - valid while fbo's are bound!!! */ -#endif if (bindReadBuf) { _mesa_reference_framebuffer(&ctx->ReadBuffer, newFbread); -#if 000 - if (!newFbread->Name) { - _mesa_readbuffer_update_fields(ctx, ctx->Pixel.ReadBuffer); - } -#endif } if (bindDrawBuf) { @@ -1027,17 +1015,6 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) /* check if newly bound framebuffer has any texture attachments */ check_begin_texture_render(ctx, newFb); } - else { - /* XXX try to remove this: */ -#if 000 - GLuint i; - GLenum buffers[MAX_DRAW_BUFFERS]; - for(i = 0; i < ctx->Const.MaxDrawBuffers; i++) { - buffers[i] = ctx->Color.DrawBuffer[i]; - } - _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers, buffers, NULL); -#endif - } } if (ctx->Driver.BindFramebuffer) { -- cgit v1.2.3 From 4b654d41da08b3b5475144c027e97a3ae7ab5696 Mon Sep 17 00:00:00 2001 From: Brian Date: Thu, 23 Aug 2007 08:53:43 +0100 Subject: For _mesa_share_state(), update the context's references to the new share group's objects (Shane Blackett) --- src/mesa/drivers/windows/gdi/wgl.c | 4 +- src/mesa/drivers/windows/gdi/wmesa.c | 5 ++ src/mesa/main/bufferobj.c | 170 ++++++++++++++++++++--------------- src/mesa/main/bufferobj.h | 3 + src/mesa/main/context.c | 36 +++++++- src/mesa/main/texstate.c | 24 +++++ src/mesa/main/texstate.h | 3 + src/mesa/shader/program.c | 43 +++++++++ src/mesa/shader/program.h | 3 + 9 files changed, 214 insertions(+), 77 deletions(-) (limited to 'src/mesa/main/context.c') diff --git a/src/mesa/drivers/windows/gdi/wgl.c b/src/mesa/drivers/windows/gdi/wgl.c index dad3dc1160..17eed1dc32 100644 --- a/src/mesa/drivers/windows/gdi/wgl.c +++ b/src/mesa/drivers/windows/gdi/wgl.c @@ -601,8 +601,8 @@ WINGDIAPI HGLRC GLAPIENTRY wglCreateLayerContext(HDC hdc, WINGDIAPI BOOL GLAPIENTRY wglShareLists(HGLRC hglrc1, HGLRC hglrc2) { - (void) hglrc1; (void) hglrc2; - return(TRUE); + WMesaShareLists(hglrc1, hglrc2); + return(TRUE); } diff --git a/src/mesa/drivers/windows/gdi/wmesa.c b/src/mesa/drivers/windows/gdi/wmesa.c index 5b67439f0f..ea3f1780d3 100644 --- a/src/mesa/drivers/windows/gdi/wmesa.c +++ b/src/mesa/drivers/windows/gdi/wmesa.c @@ -1401,6 +1401,11 @@ void WMesaSwapBuffers( HDC hdc ) } } +void WMesaShareLists(WMesaContext ctx_to_share, WMesaContext ctx) +{ + _mesa_share_state(&ctx->gl_ctx, &ctx_to_share->gl_ctx); +} + /* This is hopefully a temporary hack to define some needed dispatch * table entries. Hopefully, I'll find a better solution. The * dispatch table generation scripts ought to be making these dummy diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c index 009055a6ab..9ad2dccc12 100644 --- a/src/mesa/main/bufferobj.c +++ b/src/mesa/main/bufferobj.c @@ -409,6 +409,101 @@ _mesa_init_buffer_objects( GLcontext *ctx ) ctx->Array.ElementArrayBufferObj = ctx->Array.NullBufferObj; } +/** + * Bind the specified target to buffer for the specified context. + */ +static void +bind_buffer_object(GLcontext *ctx, GLenum target, GLuint buffer) +{ + struct gl_buffer_object *oldBufObj; + struct gl_buffer_object *newBufObj = NULL; + struct gl_buffer_object **bindTarget = NULL; + + switch (target) { + case GL_ARRAY_BUFFER_ARB: + bindTarget = &ctx->Array.ArrayBufferObj; + break; + case GL_ELEMENT_ARRAY_BUFFER_ARB: + bindTarget = &ctx->Array.ElementArrayBufferObj; + break; + case GL_PIXEL_PACK_BUFFER_EXT: + bindTarget = &ctx->Pack.BufferObj; + break; + case GL_PIXEL_UNPACK_BUFFER_EXT: + bindTarget = &ctx->Unpack.BufferObj; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferARB(target)"); + return; + } + + /* Get pointer to old buffer object (to be unbound) */ + oldBufObj = get_buffer(ctx, target); + if (oldBufObj && oldBufObj->Name == buffer) + return; /* rebinding the same buffer object- no change */ + + /* + * Get pointer to new buffer object (newBufObj) + */ + if (buffer == 0) { + /* The spec says there's not a buffer object named 0, but we use + * one internally because it simplifies things. + */ + newBufObj = ctx->Array.NullBufferObj; + } + else { + /* non-default buffer object */ + newBufObj = _mesa_lookup_bufferobj(ctx, buffer); + if (!newBufObj) { + /* if this is a new buffer object id, allocate a buffer object now */ + ASSERT(ctx->Driver.NewBufferObject); + newBufObj = ctx->Driver.NewBufferObject(ctx, buffer, target); + if (!newBufObj) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindBufferARB"); + return; + } + _mesa_save_buffer_object(ctx, newBufObj); + } + } + + /* Make new binding */ + *bindTarget = newBufObj; + newBufObj->RefCount++; + + /* Pass BindBuffer call to device driver */ + if (ctx->Driver.BindBuffer && newBufObj) + ctx->Driver.BindBuffer( ctx, target, newBufObj ); + + /* decr ref count on old buffer obj, delete if needed */ + if (oldBufObj) { + oldBufObj->RefCount--; + assert(oldBufObj->RefCount >= 0); + if (oldBufObj->RefCount == 0) { + assert(oldBufObj->Name != 0); + ASSERT(ctx->Driver.DeleteBuffer); + ctx->Driver.DeleteBuffer( ctx, oldBufObj ); + } + } +} + + +/** + * Update the default buffer 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_buffer_objects(GLcontext *ctx) +{ + /* Bind the NullBufferObj to remove references to those + * in the shared context hash table. + */ + bind_buffer_object( ctx, GL_ARRAY_BUFFER_ARB, 0); + bind_buffer_object( ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, 0); + bind_buffer_object( ctx, GL_PIXEL_PACK_BUFFER_ARB, 0); + bind_buffer_object( ctx, GL_PIXEL_UNPACK_BUFFER_ARB, 0); +} + /** * When we're about to read pixel data out of a PBO (via glDrawPixels, @@ -493,76 +588,9 @@ void GLAPIENTRY _mesa_BindBufferARB(GLenum target, GLuint buffer) { GET_CURRENT_CONTEXT(ctx); - struct gl_buffer_object *oldBufObj; - struct gl_buffer_object *newBufObj = NULL; - struct gl_buffer_object **bindTarget = NULL; ASSERT_OUTSIDE_BEGIN_END(ctx); - switch (target) { - case GL_ARRAY_BUFFER_ARB: - bindTarget = &ctx->Array.ArrayBufferObj; - break; - case GL_ELEMENT_ARRAY_BUFFER_ARB: - bindTarget = &ctx->Array.ElementArrayBufferObj; - break; - case GL_PIXEL_PACK_BUFFER_EXT: - bindTarget = &ctx->Pack.BufferObj; - break; - case GL_PIXEL_UNPACK_BUFFER_EXT: - bindTarget = &ctx->Unpack.BufferObj; - break; - default: - _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferARB(target)"); - return; - } - - /* Get pointer to old buffer object (to be unbound) */ - oldBufObj = get_buffer(ctx, target); - if (oldBufObj && oldBufObj->Name == buffer) - return; /* rebinding the same buffer object- no change */ - - /* - * Get pointer to new buffer object (newBufObj) - */ - if (buffer == 0) { - /* The spec says there's not a buffer object named 0, but we use - * one internally because it simplifies things. - */ - newBufObj = ctx->Array.NullBufferObj; - } - else { - /* non-default buffer object */ - newBufObj = _mesa_lookup_bufferobj(ctx, buffer); - if (!newBufObj) { - /* if this is a new buffer object id, allocate a buffer object now */ - ASSERT(ctx->Driver.NewBufferObject); - newBufObj = ctx->Driver.NewBufferObject(ctx, buffer, target); - if (!newBufObj) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindBufferARB"); - return; - } - _mesa_save_buffer_object(ctx, newBufObj); - } - } - - /* Make new binding */ - *bindTarget = newBufObj; - newBufObj->RefCount++; - - /* Pass BindBuffer call to device driver */ - if (ctx->Driver.BindBuffer && newBufObj) - ctx->Driver.BindBuffer( ctx, target, newBufObj ); - - /* decr ref count on old buffer obj, delete if needed */ - if (oldBufObj) { - oldBufObj->RefCount--; - assert(oldBufObj->RefCount >= 0); - if (oldBufObj->RefCount == 0) { - assert(oldBufObj->Name != 0); - ASSERT(ctx->Driver.DeleteBuffer); - ctx->Driver.DeleteBuffer( ctx, oldBufObj ); - } - } + bind_buffer_object(ctx, target, buffer); } @@ -658,9 +686,9 @@ _mesa_DeleteBuffersARB(GLsizei n, const GLuint *ids) _mesa_BindBufferARB( GL_PIXEL_UNPACK_BUFFER_EXT, 0 ); } - /* The ID is immediately freed for re-use */ - _mesa_remove_buffer_object(ctx, bufObj); - _mesa_unbind_buffer_object(ctx, bufObj); + /* The ID is immediately freed for re-use */ + _mesa_remove_buffer_object(ctx, bufObj); + _mesa_unbind_buffer_object(ctx, bufObj); } } diff --git a/src/mesa/main/bufferobj.h b/src/mesa/main/bufferobj.h index f54f9e9ff0..1d2715da84 100644 --- a/src/mesa/main/bufferobj.h +++ b/src/mesa/main/bufferobj.h @@ -38,6 +38,9 @@ extern void _mesa_init_buffer_objects( GLcontext *ctx ); +extern void +_mesa_update_default_objects_buffer_objects(GLcontext *ctx); + extern struct gl_buffer_object * _mesa_new_buffer_object( GLcontext *ctx, GLuint name, GLenum target ); diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index bb48109317..d988ef2d21 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -998,6 +998,28 @@ init_attrib_groups(GLcontext *ctx) } +/** + * Update default objects in a GL context with respect to shared state. + * + * \param ctx GL context. + * + * Removes references to old default objects, (texture objects, program + * objects, etc.) and changes to reference those from the current shared + * state. + */ +static GLboolean +update_default_objects(GLcontext *ctx) +{ + assert(ctx); + + _mesa_update_default_objects_program(ctx); + _mesa_update_default_objects_texture(ctx); + _mesa_update_default_objects_buffer_objects(ctx); + + return GL_TRUE; +} + + /** * This is the default function we plug into all dispatch table slots * This helps prevents a segfault when someone calls a GL function without @@ -1605,12 +1627,18 @@ GLboolean _mesa_share_state(GLcontext *ctx, GLcontext *ctxToShare) { if (ctx && ctxToShare && ctx->Shared && ctxToShare->Shared) { - ctx->Shared->RefCount--; - if (ctx->Shared->RefCount == 0) { - free_shared_state(ctx, ctx->Shared); - } + struct gl_shared_state *oldSharedState = ctx->Shared; + ctx->Shared = ctxToShare->Shared; ctx->Shared->RefCount++; + + update_default_objects(ctx); + + oldSharedState->RefCount--; + if (oldSharedState->RefCount == 0) { + free_shared_state(ctx, oldSharedState); + } + return GL_TRUE; } else { diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c index 020e3eef4c..288b334eaf 100644 --- a/src/mesa/main/texstate.c +++ b/src/mesa/main/texstate.c @@ -3202,3 +3202,27 @@ _mesa_free_texture_data(GLcontext *ctx) _mesa_TexEnvProgramCacheDestroy( ctx ); } + + +/** + * 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); + } +} diff --git a/src/mesa/main/texstate.h b/src/mesa/main/texstate.h index 60145691b8..b978654116 100644 --- a/src/mesa/main/texstate.h +++ b/src/mesa/main/texstate.h @@ -148,6 +148,9 @@ _mesa_init_texture( GLcontext *ctx ); extern void _mesa_free_texture_data( GLcontext *ctx ); +extern void +_mesa_update_default_objects_texture(GLcontext *ctx); + /*@}*/ #endif diff --git a/src/mesa/shader/program.c b/src/mesa/shader/program.c index 1f227390af..2097c39591 100644 --- a/src/mesa/shader/program.c +++ b/src/mesa/shader/program.c @@ -118,6 +118,49 @@ _mesa_free_program_data(GLcontext *ctx) } +/** + * Update the default program 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_program(GLcontext *ctx) +{ +#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program + if (ctx->VertexProgram.Current) { + ctx->VertexProgram.Current->Base.RefCount--; + if (ctx->VertexProgram.Current->Base.RefCount <= 0) + ctx->Driver.DeleteProgram(ctx, &(ctx->VertexProgram.Current->Base)); + } + ctx->VertexProgram.Current = (struct gl_vertex_program *) ctx->Shared->DefaultVertexProgram; + assert(ctx->VertexProgram.Current); + ctx->VertexProgram.Current->Base.RefCount++; +#endif + +#if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program + if (ctx->FragmentProgram.Current) { + ctx->FragmentProgram.Current->Base.RefCount--; + if (ctx->FragmentProgram.Current->Base.RefCount <= 0) + ctx->Driver.DeleteProgram(ctx, &(ctx->FragmentProgram.Current->Base)); + } + ctx->FragmentProgram.Current = (struct gl_fragment_program *) ctx->Shared->DefaultFragmentProgram; + assert(ctx->FragmentProgram.Current); + ctx->FragmentProgram.Current->Base.RefCount++; +#endif + + /* XXX probably move this stuff */ +#if FEATURE_ATI_fragment_shader + if (ctx->ATIFragmentShader.Current) { + ctx->ATIFragmentShader.Current->RefCount--; + if (ctx->ATIFragmentShader.Current->RefCount <= 0) { + _mesa_free(ctx->ATIFragmentShader.Current); + } + } + ctx->ATIFragmentShader.Current = (struct ati_fragment_shader *) ctx->Shared->DefaultFragmentShader; + assert(ctx->ATIFragmentShader.Current); + ctx->ATIFragmentShader.Current->RefCount++; +#endif +} /** diff --git a/src/mesa/shader/program.h b/src/mesa/shader/program.h index 52704856ab..ea2c8c3050 100644 --- a/src/mesa/shader/program.h +++ b/src/mesa/shader/program.h @@ -56,6 +56,9 @@ _mesa_init_program(GLcontext *ctx); extern void _mesa_free_program_data(GLcontext *ctx); +extern void +_mesa_update_default_objects_program(GLcontext *ctx); + extern void _mesa_set_program_error(GLcontext *ctx, GLint pos, const char *string); -- cgit v1.2.3 From a614877592e8526d997242ce336fb455dd3f5bdb Mon Sep 17 00:00:00 2001 From: Brian Date: Tue, 11 Sep 2007 10:56:35 -0600 Subject: In _mesa_make_current(), don't unbind FBOs from the old context. This fixes the X server crash reported by KeithP on Aug 29. The old context's FBOs will be unreferenced during context destruction so there's no memleak with this change. --- src/mesa/main/context.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'src/mesa/main/context.c') diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index d988ef2d21..08db12b1b6 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -1499,8 +1499,6 @@ void _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer, GLframebuffer *readBuffer ) { - GET_CURRENT_CONTEXT(oldCtx); - if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(newCtx, "_mesa_make_current()\n"); @@ -1525,13 +1523,6 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer, _glapi_set_context((void *) newCtx); ASSERT(_mesa_get_current_context() == newCtx); - if (oldCtx) { - _mesa_unreference_framebuffer(&oldCtx->WinSysDrawBuffer); - _mesa_unreference_framebuffer(&oldCtx->WinSysReadBuffer); - _mesa_unreference_framebuffer(&oldCtx->DrawBuffer); - _mesa_unreference_framebuffer(&oldCtx->ReadBuffer); - } - if (!newCtx) { _glapi_set_dispatch(NULL); /* none current */ } -- cgit v1.2.3