gldisplay: add gst_gl_display_create_context
authorJulien Isorce <j.isorce@samsung.com>
Mon, 15 Jun 2015 15:09:54 +0000 (16:09 +0100)
committerJulien Isorce <j.isorce@samsung.com>
Fri, 19 Jun 2015 12:10:30 +0000 (13:10 +0100)
It also emits a create-context signal so that an application
can provide an external GstGLContext backend.

https://bugzilla.gnome.org/show_bug.cgi?id=750310

ext/gl/gstglimagesink.c
gst-libs/gst/gl/gstgldisplay.c
gst-libs/gst/gl/gstgldisplay.h

index d266097..b8fd96c 100644 (file)
@@ -696,22 +696,37 @@ _ensure_gl_setup (GstGLImageSink * gl_sink)
   if (!gl_sink->context) {
     GST_OBJECT_LOCK (gl_sink->display);
     do {
-      GstGLContext *other_context;
-      GstGLWindow *window;
+      GstGLContext *other_context = NULL;
+      GstGLWindow *window = NULL;
 
-      if (gl_sink->context)
+      if (gl_sink->context) {
         gst_object_unref (gl_sink->context);
+        gl_sink->context = NULL;
+      }
 
       GST_DEBUG_OBJECT (gl_sink,
           "No current context, creating one for %" GST_PTR_FORMAT,
           gl_sink->display);
 
-      gl_sink->context = gst_gl_context_new (gl_sink->display);
-      if (!gl_sink->context) {
+      if (gl_sink->other_context) {
+        other_context = gst_object_ref (gl_sink->other_context);
+      } else {
+        other_context =
+            gst_gl_display_get_gl_context_for_thread (gl_sink->display, NULL);
+      }
+
+      if (!gst_gl_display_create_context (gl_sink->display,
+              other_context, &gl_sink->context, &error)) {
+        if (other_context)
+          gst_object_unref (other_context);
         GST_OBJECT_UNLOCK (gl_sink->display);
-        goto context_creation_error;
+        goto context_error;
       }
 
+      GST_DEBUG_OBJECT (gl_sink,
+          "created context %" GST_PTR_FORMAT " from other context %"
+          GST_PTR_FORMAT, gl_sink->context, gl_sink->other_context);
+
       window = gst_gl_context_get_window (gl_sink->context);
 
       GST_DEBUG_OBJECT (gl_sink, "got window %" GST_PTR_FORMAT, window);
@@ -729,25 +744,6 @@ _ensure_gl_setup (GstGLImageSink * gl_sink)
         gst_gl_window_set_window_handle (window, gl_sink->window_id);
       }
 
-      if (gl_sink->other_context) {
-        other_context = gst_object_ref (gl_sink->other_context);
-      } else {
-        other_context =
-            gst_gl_display_get_gl_context_for_thread (gl_sink->display, NULL);
-      }
-
-      GST_DEBUG_OBJECT (gl_sink,
-          "creating context %" GST_PTR_FORMAT " from other context %"
-          GST_PTR_FORMAT, gl_sink->context, other_context);
-
-      if (!gst_gl_context_create (gl_sink->context, other_context, &error)) {
-        if (other_context)
-          gst_object_unref (other_context);
-        gst_object_unref (window);
-        GST_OBJECT_UNLOCK (gl_sink->display);
-        goto context_error;
-      }
-
       gst_gl_window_handle_events (window, gl_sink->handle_events);
 
       /* setup callbacks */
@@ -782,19 +778,21 @@ _ensure_gl_setup (GstGLImageSink * gl_sink)
 
   return TRUE;
 
-context_creation_error:
-  {
-    GST_ELEMENT_ERROR (gl_sink, RESOURCE, NOT_FOUND,
-        ("Failed to create GL context"), (NULL));
-    return FALSE;
-  }
-
 context_error:
   {
     GST_ELEMENT_ERROR (gl_sink, RESOURCE, NOT_FOUND, ("%s", error->message),
         (NULL));
-    gst_object_unref (gl_sink->context);
-    gl_sink->context = NULL;
+
+    if (gl_sink->context) {
+      gst_object_unref (gl_sink->context);
+      gl_sink->context = NULL;
+    }
+
+    if (error) {
+      g_error_free (error);
+      error = NULL;
+    }
+
     return FALSE;
   }
 }
index b1264a9..51c1df5 100644 (file)
@@ -84,6 +84,15 @@ G_DEFINE_TYPE_WITH_CODE (GstGLDisplay, gst_gl_display, GST_TYPE_OBJECT,
 #define GST_GL_DISPLAY_GET_PRIVATE(o) \
   (G_TYPE_INSTANCE_GET_PRIVATE((o), GST_TYPE_GL_DISPLAY, GstGLDisplayPrivate))
 
+enum
+{
+  SIGNAL_0,
+  CREATE_CONTEXT,
+  LAST_SIGNAL
+};
+
+static guint gst_gl_display_signals[LAST_SIGNAL] = { 0 };
+
 static void gst_gl_display_finalize (GObject * object);
 static guintptr gst_gl_display_default_get_handle (GstGLDisplay * display);
 
@@ -99,6 +108,22 @@ gst_gl_display_class_init (GstGLDisplayClass * klass)
 {
   g_type_class_add_private (klass, sizeof (GstGLDisplayPrivate));
 
+  /**
+   * GstGLDisplay::create-context:
+   * @object: the #GstGLDisplay
+   * @context: other context to share resources with.
+   *
+   * Overrides the @GstGLContext creation mechanism.
+   * It can be called in any thread and it is emitted with
+   * display's object lock held.
+   *
+   * Returns: the new context.
+   */
+  gst_gl_display_signals[CREATE_CONTEXT] =
+      g_signal_new ("create-context", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic,
+      GST_GL_TYPE_CONTEXT, 1, GST_GL_TYPE_CONTEXT);
+
   klass->get_handle = gst_gl_display_default_get_handle;
 
   G_OBJECT_CLASS (klass)->finalize = gst_gl_display_finalize;
@@ -341,6 +366,58 @@ gst_context_get_gl_display (GstContext * context, GstGLDisplay ** display)
   return ret;
 }
 
+/**
+ * gst_gl_display_create_context:
+ * @display: a #GstGLDisplay
+ * @other_context: other #GstGLContext to share resources with.
+ * @p_context: resulting #GstGLContext
+ * @error: resulting #GError
+ *
+ * It requires the display's object lock to be held.
+ *
+ * Returns: whether a new context could be created.
+ *
+ * Since: 1.6
+ */
+gboolean
+gst_gl_display_create_context (GstGLDisplay * display,
+    GstGLContext * other_context, GstGLContext ** p_context, GError ** error)
+{
+  GstGLContext *context = NULL;
+  gboolean ret = FALSE;
+
+  g_return_val_if_fail (display != NULL, FALSE);
+  g_return_val_if_fail (p_context != NULL, FALSE);
+  g_return_val_if_fail (error != NULL, FALSE);
+  g_return_val_if_fail (*error == NULL, FALSE);
+
+  g_signal_emit (display, gst_gl_display_signals[CREATE_CONTEXT], 0,
+      other_context, &context);
+
+  if (context) {
+    *p_context = context;
+    return TRUE;
+  }
+
+  context = gst_gl_context_new (display);
+  if (!context) {
+    g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED,
+        "Failed to create GL context");
+    return FALSE;
+  }
+
+  GST_DEBUG_OBJECT (display,
+      "creating context %" GST_PTR_FORMAT " from other context %"
+      GST_PTR_FORMAT, context, other_context);
+
+  ret = gst_gl_context_create (context, other_context, error);
+
+  if (ret)
+    *p_context = context;
+
+  return ret;
+}
+
 static GstGLContext *
 _get_gl_context_for_thread_unlocked (GstGLDisplay * display, GThread * thread)
 {
index a9c1433..9341884 100644 (file)
@@ -92,6 +92,8 @@ GstGLAPI         gst_gl_display_get_gl_api_unlocked    (GstGLDisplay * display);
 void     gst_context_set_gl_display (GstContext * context, GstGLDisplay * display);
 gboolean gst_context_get_gl_display (GstContext * context, GstGLDisplay ** display);
 
+gboolean  gst_gl_display_create_context (GstGLDisplay * display,
+    GstGLContext * other_context, GstGLContext ** p_context, GError **error);
 GstGLContext * gst_gl_display_get_gl_context_for_thread (GstGLDisplay * display,
     GThread * thread);
 gboolean gst_gl_display_add_context (GstGLDisplay * display,