mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-20 00:31:13 +00:00
glcontext: implement checking whether a context has been shared
Some operations are unnecessary when running with only a single GL context. e.g. glFlush when setting a fence object as the flush happens on wait. API: gst_gl_context_is_shared
This commit is contained in:
parent
a0a0e51249
commit
472970324c
3 changed files with 93 additions and 24 deletions
|
@ -138,35 +138,52 @@ 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
|
/* Context sharedness is tracked by a refcounted pointer stored in each context
|
||||||
* in order track complex creation/deletion scenarios. As a result, sharedness
|
* object to track complex creation/deletion scenarios. As a result,
|
||||||
* can only be successfully validated between two GstGLContext's where one is
|
* sharedness can only be successfully validated between two GstGLContext's
|
||||||
* not a wrapped context.
|
* where one is not a wrapped context.
|
||||||
*
|
*
|
||||||
* As there is no API at the winsys level to tell whether two OpenGL contexts
|
* 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.
|
* can share GL resources, this is the next best thing.
|
||||||
|
*
|
||||||
|
* XXX: we may need a way to associate two wrapped GstGLContext's as being
|
||||||
|
* shared however I have not come across a use case that requries this yet.
|
||||||
*/
|
*/
|
||||||
static volatile guint sharegroup_idx;
|
struct ContextShareGroup
|
||||||
|
|
||||||
static guint
|
|
||||||
_new_sharegroup_id (void)
|
|
||||||
{
|
{
|
||||||
guint current, ret;
|
volatile int refcount;
|
||||||
|
};
|
||||||
|
|
||||||
do {
|
static struct ContextShareGroup *
|
||||||
current = g_atomic_int_get (&sharegroup_idx);
|
_context_share_group_new (void)
|
||||||
ret = current + 1;
|
{
|
||||||
|
struct ContextShareGroup *ret = g_new0 (struct ContextShareGroup, 1);
|
||||||
|
|
||||||
/* 0 is special */
|
ret->refcount = 1;
|
||||||
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct ContextShareGroup *
|
||||||
|
_context_share_group_ref (struct ContextShareGroup *share)
|
||||||
|
{
|
||||||
|
g_atomic_int_inc (&share->refcount);
|
||||||
|
return share;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_context_share_group_unref (struct ContextShareGroup *share)
|
||||||
|
{
|
||||||
|
if (g_atomic_int_dec_and_test (&share->refcount))
|
||||||
|
g_free (share);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_context_share_group_is_shared (struct ContextShareGroup *share)
|
||||||
|
{
|
||||||
|
return g_atomic_int_get (&share->refcount) > 1;
|
||||||
|
}
|
||||||
|
|
||||||
#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);
|
||||||
|
|
||||||
|
@ -194,7 +211,7 @@ struct _GstGLContextPrivate
|
||||||
gboolean alive;
|
gboolean alive;
|
||||||
|
|
||||||
GWeakRef other_context_ref;
|
GWeakRef other_context_ref;
|
||||||
guint sharegroup_id;
|
struct ContextShareGroup *sharegroup;
|
||||||
GError **error;
|
GError **error;
|
||||||
|
|
||||||
gint gl_major;
|
gint gl_major;
|
||||||
|
@ -389,7 +406,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->priv->sharegroup = _context_share_group_new ();
|
||||||
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;
|
||||||
|
@ -638,6 +655,9 @@ gst_gl_context_finalize (GObject * object)
|
||||||
gst_object_unref (context->window);
|
gst_object_unref (context->window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (context->priv->sharegroup)
|
||||||
|
_context_share_group_unref (context->priv->sharegroup);
|
||||||
|
|
||||||
gst_object_unref (context->display);
|
gst_object_unref (context->display);
|
||||||
|
|
||||||
if (context->gl_vtable) {
|
if (context->gl_vtable) {
|
||||||
|
@ -887,8 +907,8 @@ gst_gl_context_can_share (GstGLContext * context, GstGLContext * other_context)
|
||||||
g_return_val_if_fail (GST_IS_GL_CONTEXT (other_context), FALSE);
|
g_return_val_if_fail (GST_IS_GL_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->priv->sharegroup_id != 0
|
return context->priv->sharegroup != NULL
|
||||||
&& context->priv->sharegroup_id == other_context->priv->sharegroup_id;
|
&& context->priv->sharegroup == other_context->priv->sharegroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -929,9 +949,10 @@ gst_gl_context_create (GstGLContext * context,
|
||||||
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)
|
if (other_context == NULL)
|
||||||
context->priv->sharegroup_id = _new_sharegroup_id ();
|
context->priv->sharegroup = _context_share_group_new ();
|
||||||
else
|
else
|
||||||
context->priv->sharegroup_id = other_context->priv->sharegroup_id;
|
context->priv->sharegroup =
|
||||||
|
_context_share_group_ref (other_context->priv->sharegroup);
|
||||||
|
|
||||||
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);
|
||||||
|
@ -1590,6 +1611,23 @@ gst_gl_context_get_current (void)
|
||||||
return g_private_get (¤t_context_key);
|
return g_private_get (¤t_context_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_gl_context_is_shared:
|
||||||
|
* @context: a #GstGLContext
|
||||||
|
*
|
||||||
|
* Returns: Whether the #GstGLContext has been shared with another #GstGLContext
|
||||||
|
*
|
||||||
|
* Since: 1.8
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_gl_context_is_shared (GstGLContext * context)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE);
|
||||||
|
g_return_val_if_fail (context->priv->alive, FALSE);
|
||||||
|
|
||||||
|
return _context_share_group_is_shared (context->priv->sharegroup);
|
||||||
|
}
|
||||||
|
|
||||||
static GstGLAPI
|
static GstGLAPI
|
||||||
gst_gl_wrapped_context_get_gl_api (GstGLContext * context)
|
gst_gl_wrapped_context_get_gl_api (GstGLContext * context)
|
||||||
{
|
{
|
||||||
|
|
|
@ -148,6 +148,8 @@ gboolean gst_gl_context_check_feature (GstGLContext *context, const gchar *
|
||||||
guintptr gst_gl_context_get_current_gl_context (GstGLPlatform platform);
|
guintptr gst_gl_context_get_current_gl_context (GstGLPlatform platform);
|
||||||
GstGLAPI gst_gl_context_get_current_gl_api (GstGLPlatform platform, guint *major, guint *minor);
|
GstGLAPI gst_gl_context_get_current_gl_api (GstGLPlatform platform, guint *major, guint *minor);
|
||||||
|
|
||||||
|
gboolean gst_gl_context_is_shared (GstGLContext * context);
|
||||||
|
|
||||||
gboolean gst_gl_context_fill_info (GstGLContext * context, GError ** error);
|
gboolean gst_gl_context_fill_info (GstGLContext * context, GError ** error);
|
||||||
|
|
||||||
/* FIXME: remove */
|
/* FIXME: remove */
|
||||||
|
|
|
@ -489,6 +489,34 @@ GST_START_TEST (test_context_can_share)
|
||||||
|
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
||||||
|
GST_START_TEST (test_is_shared)
|
||||||
|
{
|
||||||
|
GstGLContext *c1, *c2;
|
||||||
|
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_is_shared (c1));
|
||||||
|
fail_unless (gst_gl_context_is_shared (c2));
|
||||||
|
|
||||||
|
gst_object_unref (c2);
|
||||||
|
c2 = NULL;
|
||||||
|
|
||||||
|
fail_unless (!gst_gl_context_is_shared (c1));
|
||||||
|
|
||||||
|
gst_object_unref (c1);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
static Suite *
|
static Suite *
|
||||||
gst_gl_context_suite (void)
|
gst_gl_context_suite (void)
|
||||||
{
|
{
|
||||||
|
@ -501,6 +529,7 @@ gst_gl_context_suite (void)
|
||||||
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);
|
tcase_add_test (tc_chain, test_context_can_share);
|
||||||
|
tcase_add_test (tc_chain, test_is_shared);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue