From 4b654d41da08b3b5475144c027e97a3ae7ab5696 Mon Sep 17 00:00:00 2001 From: Brian Date: Thu, 23 Aug 2007 08:53:43 +0100 Subject: [PATCH] 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(-) diff --git a/src/mesa/drivers/windows/gdi/wgl.c b/src/mesa/drivers/windows/gdi/wgl.c index dad3dc11604..17eed1dc329 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 5b67439f0f2..ea3f1780d3c 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 009055a6ab6..9ad2dccc124 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 f54f9e9ff00..1d2715da846 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 bb481093170..d988ef2d215 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 020e3eef4c0..288b334eaf6 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 60145691b8c..b978654116e 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 1f227390afd..2097c395918 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 52704856ab0..ea2c8c30508 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); -- 2.30.2