For _mesa_share_state(), update the context's references to the new share group's...
authorBrian <brian.paul@tungstengraphics.com>
Thu, 23 Aug 2007 07:53:43 +0000 (08:53 +0100)
committerBrian <brian.paul@tungstengraphics.com>
Thu, 23 Aug 2007 07:53:43 +0000 (08:53 +0100)
src/mesa/drivers/windows/gdi/wgl.c
src/mesa/drivers/windows/gdi/wmesa.c
src/mesa/main/bufferobj.c
src/mesa/main/bufferobj.h
src/mesa/main/context.c
src/mesa/main/texstate.c
src/mesa/main/texstate.h
src/mesa/shader/program.c
src/mesa/shader/program.h

index dad3dc116043c5bbc752e3bb1bdfd41233069a29..17eed1dc3298732c040c70306d797485f419a904 100644 (file)
@@ -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);
 }
 
 
index 5b67439f0f2577f106e63491b698ff7b804132e0..ea3f1780d3cbaaec7fa79b237ef79a7dad78f4d5 100644 (file)
@@ -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
index 009055a6ab6cba19851b32c212b46e40fe5e9479..9ad2dccc1243683d76f2e58a7322f2e54429a911 100644 (file)
@@ -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);
       }
    }
 
index f54f9e9ff00c1b228819eb8d8131fdcdac376af5..1d2715da846aaa8e62065fff344709460d65d1a4 100644 (file)
@@ -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 );
 
index bb481093170a6b75c85640333d94b9f2e48edfa1..d988ef2d215c9743a27f7a2dc44f9afc68fb26ba 100644 (file)
@@ -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 {
index 020e3eef4c0e3c0fc1e8765fa6a91709753c9934..288b334eaf6f7bb6c1d01473206e53c3fb4c8512 100644 (file)
@@ -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);
+   }
+}
index 60145691b8c3c0bccafee707fb77ed38b0495741..b978654116e1437673394035326aacd48dab412c 100644 (file)
@@ -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
index 1f227390afd3551dcb67eb3a56c34d895c59b7a7..2097c395918d2c7a2c9a2e241987563193805793 100644 (file)
@@ -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
+}
 
 
 /**
index 52704856ab08e647e7f46eeeb5b390f03f449669..ea2c8c30508d417fa72c64cb5dde108c14945880 100644 (file)
@@ -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);