mesa: use new _mesa_reference_shared_state() function
This cleans up the reference counting of shared context state.
The next patch will use this to fix an actual bug.
NOTE: This is a candidate for the 8.0 branch.
Reviewed-by: José Fonseca <jfonseca@vmware.com>
diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
index f39cab5..43e7438 100644
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -939,13 +939,10 @@
return GL_FALSE;
}
- _glthread_LOCK_MUTEX(shared->Mutex);
- ctx->Shared = shared;
- shared->RefCount++;
- _glthread_UNLOCK_MUTEX(shared->Mutex);
+ _mesa_reference_shared_state(ctx, &ctx->Shared, shared);
if (!init_attrib_groups( ctx )) {
- _mesa_release_shared_state(ctx, ctx->Shared);
+ _mesa_reference_shared_state(ctx, &ctx->Shared, NULL);
return GL_FALSE;
}
@@ -973,7 +970,7 @@
}
if (!ctx->Exec) {
- _mesa_release_shared_state(ctx, ctx->Shared);
+ _mesa_reference_shared_state(ctx, &ctx->Shared, NULL);
return GL_FALSE;
}
#endif
@@ -1002,7 +999,7 @@
#if FEATURE_dlist
ctx->Save = _mesa_create_save_table();
if (!ctx->Save) {
- _mesa_release_shared_state(ctx, ctx->Shared);
+ _mesa_reference_shared_state(ctx, &ctx->Shared, NULL);
free(ctx->Exec);
return GL_FALSE;
}
@@ -1140,7 +1137,7 @@
free(ctx->Save);
/* Shared context state (display lists, textures, etc) */
- _mesa_release_shared_state( ctx, ctx->Shared );
+ _mesa_reference_shared_state(ctx, &ctx->Shared, NULL);
/* needs to be after freeing shared state */
_mesa_free_display_list_data(ctx);
@@ -1540,17 +1537,18 @@
_mesa_share_state(struct gl_context *ctx, struct gl_context *ctxToShare)
{
if (ctx && ctxToShare && ctx->Shared && ctxToShare->Shared) {
- struct gl_shared_state *oldSharedState = ctx->Shared;
+ struct gl_shared_state *oldShared = NULL;
- ctx->Shared = ctxToShare->Shared;
-
- _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
- ctx->Shared->RefCount++;
- _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+ /* save ref to old state to prevent it from being deleted immediately */
+ _mesa_reference_shared_state(ctx, &oldShared, ctx->Shared);
+
+ /* update ctx's Shared pointer */
+ _mesa_reference_shared_state(ctx, &ctx->Shared, ctxToShare->Shared);
update_default_objects(ctx);
- _mesa_release_shared_state(ctx, oldSharedState);
+ /* release the old shared state */
+ _mesa_reference_shared_state(ctx, &oldShared, NULL);
return GL_TRUE;
}
diff --git a/src/mesa/main/shared.c b/src/mesa/main/shared.c
index c3e93b5..c07ce82 100644
--- a/src/mesa/main/shared.c
+++ b/src/mesa/main/shared.c
@@ -388,28 +388,40 @@
/**
- * Decrement shared state object reference count and potentially free it
- * and all children structures.
- *
- * \param ctx GL context.
- * \param shared shared state pointer.
- *
- * \sa free_shared_state().
+ * gl_shared_state objects are ref counted.
+ * If ptr's refcount goes to zero, free the shared state.
*/
void
-_mesa_release_shared_state(struct gl_context *ctx,
- struct gl_shared_state *shared)
+_mesa_reference_shared_state(struct gl_context *ctx,
+ struct gl_shared_state **ptr,
+ struct gl_shared_state *state)
{
- GLint RefCount;
+ if (*ptr == state)
+ return;
- _glthread_LOCK_MUTEX(shared->Mutex);
- RefCount = --shared->RefCount;
- _glthread_UNLOCK_MUTEX(shared->Mutex);
+ if (*ptr) {
+ /* unref old state */
+ struct gl_shared_state *old = *ptr;
+ GLboolean delete;
- assert(RefCount >= 0);
+ _glthread_LOCK_MUTEX(old->Mutex);
+ assert(old->RefCount >= 1);
+ old->RefCount--;
+ delete = (old->RefCount == 0);
+ _glthread_UNLOCK_MUTEX(old->Mutex);
- if (RefCount == 0) {
- /* free shared state */
- free_shared_state( ctx, shared );
+ if (delete) {
+ free_shared_state(ctx, old);
+ }
+
+ *ptr = NULL;
+ }
+
+ if (state) {
+ /* reference new state */
+ _glthread_LOCK_MUTEX(state->Mutex);
+ state->RefCount++;
+ *ptr = state;
+ _glthread_UNLOCK_MUTEX(state->Mutex);
}
}
diff --git a/src/mesa/main/shared.h b/src/mesa/main/shared.h
index 55516a8..3fe4578 100644
--- a/src/mesa/main/shared.h
+++ b/src/mesa/main/shared.h
@@ -27,13 +27,14 @@
struct gl_context;
+void
+_mesa_reference_shared_state(struct gl_context *ctx,
+ struct gl_shared_state **ptr,
+ struct gl_shared_state *state);
+
+
struct gl_shared_state *
_mesa_alloc_shared_state(struct gl_context *ctx);
-void
-_mesa_release_shared_state(struct gl_context *ctx,
- struct gl_shared_state *shared);
-
-
#endif