diff options
author | Matthew Waters <matthew@centricular.com> | 2015-07-16 00:37:58 +1000 |
---|---|---|
committer | Matthew Waters <matthew@centricular.com> | 2015-07-18 15:34:55 +1000 |
commit | be9ad5eeb255c68b7ed07c6cb6d64b744c2076c7 (patch) | |
tree | d1b5716f247262a79751408c09480d3b6cff5d99 /gst-libs | |
parent | b679cc2238942a77ecf64038aa0a89a83063e287 (diff) | |
download | gstreamer-plugins-bad-be9ad5eeb255c68b7ed07c6cb6d64b744c2076c7.tar.gz |
glcontext: track sharedness with a cookie
The previous approach of traversing the other_context weak ref tree was
1. Less performant
2. Incorrect for context destruction removing a link in the tree
Example of 2:
c1 = context_create (NULL)
c2 = context_create (c1)
c3 = context_create (c2)
context_can_share (c1, c3) == TRUE
context_destroy (c2)
unref (c2)
context_can_share (c1, c3) returns FALSE when it should be TRUE!
This does not remove the restriction that context sharedness can only
be tracked between GstGLContext's.
Diffstat (limited to 'gst-libs')
-rw-r--r-- | gst-libs/gst/gl/gstglcontext.c | 87 |
1 files changed, 39 insertions, 48 deletions
diff --git a/gst-libs/gst/gl/gstglcontext.c b/gst-libs/gst/gl/gstglcontext.c index 12c220619..2a418e1ea 100644 --- a/gst-libs/gst/gl/gstglcontext.c +++ b/gst-libs/gst/gl/gstglcontext.c @@ -133,6 +133,35 @@ load_self_module (gpointer user_data) #error "Add module loading support for GLES3" #endif +/* Context sharedness es tracked by a unique id stored in each context object + * in order track complex creation/deletion scenarios. As a result, sharedness + * can only be successfully validated between two GstGLContext's where one is + * not a wrapped context. + * + * As there is no API at the winsys level to tell whether two OpenGL contexts + * can share GL resources, this is the next best thing. + */ +static volatile guint sharegroup_idx; + +static guint +_new_sharegroup_id (void) +{ + guint current, ret; + + do { + current = g_atomic_int_get (&sharegroup_idx); + ret = current + 1; + + /* 0 is special */ + if (ret == 0) + ret++; + } while (!g_atomic_int_compare_and_exchange (&sharegroup_idx, current, ret)); + + GST_TRACE ("generated new share group id %u", ret); + + return ret; +} + #define GST_CAT_DEFAULT gst_gl_context_debug GST_DEBUG_CATEGORY (GST_CAT_DEFAULT); @@ -163,6 +192,7 @@ struct _GstGLContextPrivate gboolean alive; GWeakRef other_context_ref; + guint sharegroup_id; GError **error; gint gl_major; @@ -359,6 +389,7 @@ gst_gl_context_new_wrapped (GstGLDisplay * display, guintptr handle, context = (GstGLContext *) context_wrap; context->display = gst_object_ref (display); + context->priv->sharegroup_id = _new_sharegroup_id (); context_wrap->handle = handle; context_wrap->platform = context_type; context_wrap->available_apis = available_apis; @@ -822,53 +853,13 @@ gst_gl_context_get_window (GstGLContext * context) return gst_object_ref (context->window); } -static gboolean -_share_group_descendant (GstGLContext * context, GstGLContext * other_context, - GstGLContext ** root) -{ - GstGLContext *next = gst_object_ref (context); - GstGLContext *prev = NULL; - - /* given a context tree where --> means "has other gl context": - * - * a-->b-->c-->d - * / / - * e / - * / - * f-->g - * - * return TRUE if @other_context is a descendant of @context - * - * e.g. [a, b], [f, d], [e, c] are all descendants - * but [b, a], [d, f], [e, f] are not descendants. Provide the root node (d) - * so that we can check if two chains end up at the end with the same - * GstGLContext - */ - - while (next != NULL) { - if (next == other_context) { - gst_object_unref (next); - if (root) - *root = NULL; - return TRUE; - } - - prev = next; - next = g_weak_ref_get (&next->priv->other_context_ref); - gst_object_unref (prev); - } - - if (root != NULL) - *root = prev; - - return FALSE; -} - /** * gst_gl_context_can_share: * @context: a #GstGLContext * @other_context: another #GstGLContext * + * Note: This will always fail for two wrapped #GstGLContext's + * * Returns: whether @context and @other_context are able to share OpenGL * resources. * @@ -877,16 +868,12 @@ _share_group_descendant (GstGLContext * context, GstGLContext * other_context, gboolean gst_gl_context_can_share (GstGLContext * context, GstGLContext * other_context) { - GstGLContext *root1, *root2; - g_return_val_if_fail (GST_GL_IS_CONTEXT (context), FALSE); g_return_val_if_fail (GST_GL_IS_CONTEXT (other_context), FALSE); /* check if the contexts are descendants or the root nodes are the same */ - return context == other_context - || _share_group_descendant (context, other_context, &root1) - || _share_group_descendant (other_context, context, &root2) - || ((root1 != NULL || root2 != NULL) && root1 == root2); + return context->priv->sharegroup_id != 0 + && context->priv->sharegroup_id == other_context->priv->sharegroup_id; } /** @@ -926,6 +913,10 @@ gst_gl_context_create (GstGLContext * context, if (!context->priv->created) { g_weak_ref_set (&context->priv->other_context_ref, other_context); context->priv->error = error; + if (other_context == NULL) + context->priv->sharegroup_id = _new_sharegroup_id (); + else + context->priv->sharegroup_id = other_context->priv->sharegroup_id; context->priv->gl_thread = g_thread_new ("gstglcontext", (GThreadFunc) gst_gl_context_create_thread, context); |