Hi,

Attached is a change to core mesa. This fixes a potential refcount locking 
problem with shared OpenGL objects.
This change survives a piglit r600 run on my local machine.
Please review.

Thanks

Mathias
From e0298379c240f3a3885d1db92e0bcf5fc44af953 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mathias=20Fr=C3=B6hlich?= <mathias.froehl...@gmx.net>
Date: Mon, 17 Oct 2011 23:18:43 +0200
Subject: [PATCH] mesa: Fix multithreaded buffer object refcounting.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Buffer objects may be shared across contexts.
Lock the buffer objects mutex while modifying reference
counts for push/pop of client array attributes.
Also ensure that each taken reference on push is released
on pop.

Signed-off-by: Mathias Fröhlich <mathias.froehl...@web.de>
---
 src/mesa/main/attrib.c |  108 +++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 88 insertions(+), 20 deletions(-)

diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c
index e67957d..0308bcc 100644
--- a/src/mesa/main/attrib.c
+++ b/src/mesa/main/attrib.c
@@ -1277,28 +1277,92 @@ _mesa_PopAttrib(void)
    }
 }
 
+/**
+ * Helper for incrementing vertex buffer object reference
+ * counts when pushing the GL_CLIENT_VERTEX_ARRAY_BIT attribute group.
+ */
+static void
+inc_buffer_object_ref_count(struct gl_buffer_object *bufferObj)
+{
+   _glthread_LOCK_MUTEX(bufferObj->Mutex);
+   bufferObj->RefCount += 1;
+   _glthread_UNLOCK_MUTEX(bufferObj->Mutex);
+}
 
 /**
- * Helper for incrementing/decrementing vertex buffer object reference
- * counts when pushing/popping the GL_CLIENT_VERTEX_ARRAY_BIT attribute group.
+ * Helper for incrementing vertex buffer object reference
+ * counts when pushing the GL_CLIENT_VERTEX_ARRAY_BIT attribute group.
  */
 static void
-adjust_buffer_object_ref_counts(struct gl_array_object *arrayObj, GLint step)
+inc_array_object_ref_counts(struct gl_array_object *arrayObj)
 {
    GLuint i;
 
-   arrayObj->Vertex.BufferObj->RefCount += step;
-   arrayObj->Weight.BufferObj->RefCount += step;
-   arrayObj->Normal.BufferObj->RefCount += step;
-   arrayObj->Color.BufferObj->RefCount += step;
-   arrayObj->SecondaryColor.BufferObj->RefCount += step;
-   arrayObj->FogCoord.BufferObj->RefCount += step;
-   arrayObj->Index.BufferObj->RefCount += step;
-   arrayObj->EdgeFlag.BufferObj->RefCount += step;
+   inc_buffer_object_ref_count(arrayObj->Vertex.BufferObj);
+   inc_buffer_object_ref_count(arrayObj->Weight.BufferObj);
+   inc_buffer_object_ref_count(arrayObj->Normal.BufferObj);
+   inc_buffer_object_ref_count(arrayObj->Color.BufferObj);
+   inc_buffer_object_ref_count(arrayObj->SecondaryColor.BufferObj);
+   inc_buffer_object_ref_count(arrayObj->FogCoord.BufferObj);
+   inc_buffer_object_ref_count(arrayObj->Index.BufferObj);
+   inc_buffer_object_ref_count(arrayObj->EdgeFlag.BufferObj);
    for (i = 0; i < Elements(arrayObj->TexCoord); i++)
-      arrayObj->TexCoord[i].BufferObj->RefCount += step;
+      inc_buffer_object_ref_count(arrayObj->TexCoord[i].BufferObj);
+#if FEATURE_point_size_array
+   inc_buffer_object_ref_count(arrayObj->PointSize.BufferObj);
+#endif
    for (i = 0; i < Elements(arrayObj->VertexAttrib); i++)
-      arrayObj->VertexAttrib[i].BufferObj->RefCount += step;
+      inc_buffer_object_ref_count(arrayObj->VertexAttrib[i].BufferObj);
+}
+
+/**
+ * Helper for decrementing vertex buffer object reference
+ * counts when popping the GL_CLIENT_VERTEX_ARRAY_BIT attribute group.
+ */
+static void
+pop_buffer_object(struct gl_context *ctx, struct gl_buffer_object **ptr,
+                  struct gl_buffer_object *bufObj)
+{
+   _mesa_reference_buffer_object_(ctx, ptr, NULL);
+   *ptr = bufObj;
+}
+
+/**
+ * Helper for decrementing vertex buffer object reference
+ * counts when popping the GL_CLIENT_VERTEX_ARRAY_BIT attribute group.
+ */
+static void
+pop_array_object(struct gl_context *ctx, struct gl_array_object *curArrayObj,
+                 struct gl_array_object *arrayObj)
+{
+   GLuint i;
+
+   pop_buffer_object(ctx, &curArrayObj->Vertex.BufferObj,
+                     arrayObj->Vertex.BufferObj);
+   pop_buffer_object(ctx, &curArrayObj->Weight.BufferObj,
+                     arrayObj->Weight.BufferObj);
+   pop_buffer_object(ctx, &curArrayObj->Normal.BufferObj,
+                     arrayObj->Normal.BufferObj);
+   pop_buffer_object(ctx, &curArrayObj->Color.BufferObj,
+                     arrayObj->Color.BufferObj);
+   pop_buffer_object(ctx, &curArrayObj->SecondaryColor.BufferObj,
+                     arrayObj->SecondaryColor.BufferObj);
+   pop_buffer_object(ctx, &curArrayObj->FogCoord.BufferObj,
+                     arrayObj->FogCoord.BufferObj);
+   pop_buffer_object(ctx, &curArrayObj->Index.BufferObj,
+                     arrayObj->Index.BufferObj);
+   pop_buffer_object(ctx, &curArrayObj->EdgeFlag.BufferObj,
+                     arrayObj->EdgeFlag.BufferObj);
+   for (i = 0; i < Elements(arrayObj->TexCoord); i++)
+      pop_buffer_object(ctx, &curArrayObj->TexCoord[i].BufferObj,
+                        arrayObj->TexCoord[i].BufferObj);
+#if FEATURE_point_size_array
+   pop_buffer_object(ctx, &curArrayObj->PointSize.BufferObj,
+                     arrayObj->PointSize.BufferObj);
+#endif
+   for (i = 0; i < Elements(arrayObj->VertexAttrib); i++)
+      pop_buffer_object(ctx, &curArrayObj->VertexAttrib[i].BufferObj,
+                        arrayObj->VertexAttrib[i].BufferObj);
 }
 
 
@@ -1365,10 +1429,13 @@ _mesa_PushClientAttrib(GLbitfield mask)
       attr = MALLOC_STRUCT( gl_array_attrib );
       obj = MALLOC_STRUCT( gl_array_object );
 
+      /* bump reference counts on buffer objects */
+      inc_array_object_ref_counts(ctx->Array.ArrayObj);
+
 #if FEATURE_ARB_vertex_buffer_object
       /* increment ref counts since we're copying pointers to these objects */
-      ctx->Array.ArrayBufferObj->RefCount++;
-      ctx->Array.ElementArrayBufferObj->RefCount++;
+      inc_buffer_object_ref_count(ctx->Array.ArrayBufferObj);
+      inc_buffer_object_ref_count(ctx->Array.ElementArrayBufferObj);
 #endif
 
       memcpy( attr, &ctx->Array, sizeof(struct gl_array_attrib) );
@@ -1377,9 +1444,6 @@ _mesa_PushClientAttrib(GLbitfield mask)
       attr->ArrayObj = obj;
 
       save_attrib_data(&head, GL_CLIENT_VERTEX_ARRAY_BIT, attr);
-
-      /* bump reference counts on buffer objects */
-      adjust_buffer_object_ref_counts(ctx->Array.ArrayObj, 1);
    }
 
    ctx->ClientAttribStack[ctx->ClientAttribStackDepth] = head;
@@ -1429,8 +1493,6 @@ _mesa_PopClientAttrib(void)
 	    struct gl_array_attrib * data =
 	      (struct gl_array_attrib *) node->data;
 
-            adjust_buffer_object_ref_counts(ctx->Array.ArrayObj, -1);
-	 
             ctx->Array.ActiveTexture = data->ActiveTexture;
 	    if (data->LockCount != 0)
 	       _mesa_LockArraysEXT(data->LockFirst, data->LockCount);
@@ -1438,12 +1500,18 @@ _mesa_PopClientAttrib(void)
 	       _mesa_UnlockArraysEXT();
 
 	    _mesa_BindVertexArrayAPPLE( data->ArrayObj->Name );
+            
+            pop_array_object(ctx, ctx->Array.ArrayObj, data->ArrayObj);
 	    
 #if FEATURE_ARB_vertex_buffer_object
             _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB,
                                 data->ArrayBufferObj->Name);
+            _mesa_reference_buffer_object_(ctx, &data->ArrayBufferObj,
+                                           NULL);
             _mesa_BindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
                                 data->ElementArrayBufferObj->Name);
+            _mesa_reference_buffer_object_(ctx, &data->ElementArrayBufferObj,
+                                           NULL);
 #endif
 
 	    memcpy( ctx->Array.ArrayObj, data->ArrayObj,
-- 
1.7.4.4

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to