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;
}
}
if (!ctx->Exec) {
- _mesa_release_shared_state(ctx, ctx->Shared);
+ _mesa_reference_shared_state(ctx, &ctx->Shared, NULL);
return GL_FALSE;
}
#endif
#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;
}
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);
_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;
}
/**
- * 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;
-
- _glthread_LOCK_MUTEX(shared->Mutex);
- RefCount = --shared->RefCount;
- _glthread_UNLOCK_MUTEX(shared->Mutex);
+ if (*ptr == state)
+ return;
+
+ if (*ptr) {
+ /* unref old state */
+ struct gl_shared_state *old = *ptr;
+ GLboolean delete;
+
+ _glthread_LOCK_MUTEX(old->Mutex);
+ assert(old->RefCount >= 1);
+ old->RefCount--;
+ delete = (old->RefCount == 0);
+ _glthread_UNLOCK_MUTEX(old->Mutex);
+
+ if (delete) {
+ free_shared_state(ctx, old);
+ }
- assert(RefCount >= 0);
+ *ptr = NULL;
+ }
- if (RefCount == 0) {
- /* free shared state */
- free_shared_state( ctx, shared );
+ if (state) {
+ /* reference new state */
+ _glthread_LOCK_MUTEX(state->Mutex);
+ state->RefCount++;
+ *ptr = state;
+ _glthread_UNLOCK_MUTEX(state->Mutex);
}
}
struct gl_context;
-struct gl_shared_state *
-_mesa_alloc_shared_state(struct gl_context *ctx);
+void
+_mesa_reference_shared_state(struct gl_context *ctx,
+ struct gl_shared_state **ptr,
+ struct gl_shared_state *state);
-void
-_mesa_release_shared_state(struct gl_context *ctx,
- struct gl_shared_state *shared);
+struct gl_shared_state *
+_mesa_alloc_shared_state(struct gl_context *ctx);
#endif