mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-20 23:36:38 +00:00
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.
This commit is contained in:
parent
b679cc2238
commit
be9ad5eeb2
2 changed files with 80 additions and 48 deletions
|
@ -133,6 +133,35 @@ load_self_module (gpointer user_data)
|
||||||
#error "Add module loading support for GLES3"
|
#error "Add module loading support for GLES3"
|
||||||
#endif
|
#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
|
#define GST_CAT_DEFAULT gst_gl_context_debug
|
||||||
GST_DEBUG_CATEGORY (GST_CAT_DEFAULT);
|
GST_DEBUG_CATEGORY (GST_CAT_DEFAULT);
|
||||||
|
|
||||||
|
@ -163,6 +192,7 @@ struct _GstGLContextPrivate
|
||||||
gboolean alive;
|
gboolean alive;
|
||||||
|
|
||||||
GWeakRef other_context_ref;
|
GWeakRef other_context_ref;
|
||||||
|
guint sharegroup_id;
|
||||||
GError **error;
|
GError **error;
|
||||||
|
|
||||||
gint gl_major;
|
gint gl_major;
|
||||||
|
@ -359,6 +389,7 @@ gst_gl_context_new_wrapped (GstGLDisplay * display, guintptr handle,
|
||||||
context = (GstGLContext *) context_wrap;
|
context = (GstGLContext *) context_wrap;
|
||||||
|
|
||||||
context->display = gst_object_ref (display);
|
context->display = gst_object_ref (display);
|
||||||
|
context->priv->sharegroup_id = _new_sharegroup_id ();
|
||||||
context_wrap->handle = handle;
|
context_wrap->handle = handle;
|
||||||
context_wrap->platform = context_type;
|
context_wrap->platform = context_type;
|
||||||
context_wrap->available_apis = available_apis;
|
context_wrap->available_apis = available_apis;
|
||||||
|
@ -822,53 +853,13 @@ gst_gl_context_get_window (GstGLContext * context)
|
||||||
return gst_object_ref (context->window);
|
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:
|
* gst_gl_context_can_share:
|
||||||
* @context: a #GstGLContext
|
* @context: a #GstGLContext
|
||||||
* @other_context: another #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
|
* Returns: whether @context and @other_context are able to share OpenGL
|
||||||
* resources.
|
* resources.
|
||||||
*
|
*
|
||||||
|
@ -877,16 +868,12 @@ _share_group_descendant (GstGLContext * context, GstGLContext * other_context,
|
||||||
gboolean
|
gboolean
|
||||||
gst_gl_context_can_share (GstGLContext * context, GstGLContext * other_context)
|
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 (context), FALSE);
|
||||||
g_return_val_if_fail (GST_GL_IS_CONTEXT (other_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 */
|
/* check if the contexts are descendants or the root nodes are the same */
|
||||||
return context == other_context
|
return context->priv->sharegroup_id != 0
|
||||||
|| _share_group_descendant (context, other_context, &root1)
|
&& context->priv->sharegroup_id == other_context->priv->sharegroup_id;
|
||||||
|| _share_group_descendant (other_context, context, &root2)
|
|
||||||
|| ((root1 != NULL || root2 != NULL) && root1 == root2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -926,6 +913,10 @@ gst_gl_context_create (GstGLContext * context,
|
||||||
if (!context->priv->created) {
|
if (!context->priv->created) {
|
||||||
g_weak_ref_set (&context->priv->other_context_ref, other_context);
|
g_weak_ref_set (&context->priv->other_context_ref, other_context);
|
||||||
context->priv->error = error;
|
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",
|
context->priv->gl_thread = g_thread_new ("gstglcontext",
|
||||||
(GThreadFunc) gst_gl_context_create_thread, context);
|
(GThreadFunc) gst_gl_context_create_thread, context);
|
||||||
|
|
|
@ -442,6 +442,46 @@ GST_START_TEST (test_current_context)
|
||||||
|
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
||||||
|
GST_START_TEST (test_context_can_share)
|
||||||
|
{
|
||||||
|
GstGLContext *c1, *c2, *c3;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
c1 = gst_gl_context_new (display);
|
||||||
|
gst_gl_context_create (c1, NULL, &error);
|
||||||
|
fail_if (error != NULL, "Error creating context %s\n",
|
||||||
|
error ? error->message : "Unknown Error");
|
||||||
|
|
||||||
|
c2 = gst_gl_context_new (display);
|
||||||
|
gst_gl_context_create (c2, c1, &error);
|
||||||
|
fail_if (error != NULL, "Error creating context %s\n",
|
||||||
|
error ? error->message : "Unknown Error");
|
||||||
|
|
||||||
|
fail_unless (gst_gl_context_can_share (c1, c2));
|
||||||
|
fail_unless (gst_gl_context_can_share (c2, c1));
|
||||||
|
|
||||||
|
c3 = gst_gl_context_new (display);
|
||||||
|
gst_gl_context_create (c3, c2, &error);
|
||||||
|
fail_if (error != NULL, "Error creating context %s\n",
|
||||||
|
error ? error->message : "Unknown Error");
|
||||||
|
|
||||||
|
fail_unless (gst_gl_context_can_share (c1, c3));
|
||||||
|
fail_unless (gst_gl_context_can_share (c3, c1));
|
||||||
|
fail_unless (gst_gl_context_can_share (c2, c3));
|
||||||
|
fail_unless (gst_gl_context_can_share (c3, c2));
|
||||||
|
|
||||||
|
/* destroy the middle context */
|
||||||
|
gst_object_unref (c2);
|
||||||
|
c2 = NULL;
|
||||||
|
|
||||||
|
fail_unless (gst_gl_context_can_share (c1, c3));
|
||||||
|
fail_unless (gst_gl_context_can_share (c3, c1));
|
||||||
|
|
||||||
|
gst_object_unref (c1);
|
||||||
|
gst_object_unref (c3);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
static Suite *
|
static Suite *
|
||||||
gst_gl_context_suite (void)
|
gst_gl_context_suite (void)
|
||||||
|
@ -454,6 +494,7 @@ gst_gl_context_suite (void)
|
||||||
tcase_add_test (tc_chain, test_share);
|
tcase_add_test (tc_chain, test_share);
|
||||||
tcase_add_test (tc_chain, test_wrapped_context);
|
tcase_add_test (tc_chain, test_wrapped_context);
|
||||||
tcase_add_test (tc_chain, test_current_context);
|
tcase_add_test (tc_chain, test_current_context);
|
||||||
|
tcase_add_test (tc_chain, test_context_can_share);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue