#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.
+/* Context sharedness is tracked by a refcounted pointer stored in each context
+ * object to 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.
+ *
+ * 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
+{
+ volatile int refcount;
+};
-static guint
-_new_sharegroup_id (void)
+static struct ContextShareGroup *
+_context_share_group_new (void)
{
- guint current, ret;
+ struct ContextShareGroup *ret = g_new0 (struct ContextShareGroup, 1);
- do {
- current = g_atomic_int_get (&sharegroup_idx);
- ret = current + 1;
+ ret->refcount = 1;
- /* 0 is special */
- if (ret == 0)
- ret++;
- } while (!g_atomic_int_compare_and_exchange (&sharegroup_idx, current, ret));
+ return ret;
+}
- GST_TRACE ("generated new share group id %u", ret);
+static struct ContextShareGroup *
+_context_share_group_ref (struct ContextShareGroup *share)
+{
+ g_atomic_int_inc (&share->refcount);
+ return share;
+}
- return ret;
+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
gboolean alive;
GWeakRef other_context_ref;
- guint sharegroup_id;
+ struct ContextShareGroup *sharegroup;
GError **error;
gint gl_major;
context = (GstGLContext *) context_wrap;
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->platform = context_type;
context_wrap->available_apis = available_apis;
gst_object_unref (context->window);
}
+ if (context->priv->sharegroup)
+ _context_share_group_unref (context->priv->sharegroup);
+
gst_object_unref (context->display);
if (context->gl_vtable) {
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 */
- return context->priv->sharegroup_id != 0
- && context->priv->sharegroup_id == other_context->priv->sharegroup_id;
+ return context->priv->sharegroup != NULL
+ && context->priv->sharegroup == other_context->priv->sharegroup;
}
/**
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 ();
+ context->priv->sharegroup = _context_share_group_new ();
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",
(GThreadFunc) gst_gl_context_create_thread, context);
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
gst_gl_wrapped_context_get_gl_api (GstGLContext * context)
{
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 *
gst_gl_context_suite (void)
{
tcase_add_test (tc_chain, test_wrapped_context);
tcase_add_test (tc_chain, test_current_context);
tcase_add_test (tc_chain, test_context_can_share);
+ tcase_add_test (tc_chain, test_is_shared);
return s;
}