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