summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian <[email protected]>2007-08-23 08:53:43 +0100
committerBrian <[email protected]>2007-08-23 08:53:43 +0100
commit4b654d41da08b3b5475144c027e97a3ae7ab5696 (patch)
tree2b19565434268fad9c767e6f39553fffafca7fcf
parentdbef6158c6c19a28dc96a96357c9ed9bd9422b88 (diff)
For _mesa_share_state(), update the context's references to the new share group's objects (Shane Blackett)
-rw-r--r--src/mesa/drivers/windows/gdi/wgl.c4
-rw-r--r--src/mesa/drivers/windows/gdi/wmesa.c5
-rw-r--r--src/mesa/main/bufferobj.c170
-rw-r--r--src/mesa/main/bufferobj.h3
-rw-r--r--src/mesa/main/context.c36
-rw-r--r--src/mesa/main/texstate.c24
-rw-r--r--src/mesa/main/texstate.h3
-rw-r--r--src/mesa/shader/program.c43
-rw-r--r--src/mesa/shader/program.h3
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
@@ -999,6 +999,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
* first checking if the extension's supported.
@@ -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
@@ -57,6 +57,9 @@ 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);
extern const GLubyte *