gl/display: provide a gst_gl_display_new_with_type()
authorMatthew Waters <matthew@centricular.com>
Tue, 18 May 2021 09:56:13 +0000 (19:56 +1000)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Wed, 19 May 2021 10:15:56 +0000 (10:15 +0000)
Allows more fine-grained control over the exact display type that is
created.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/1154>

gst-libs/gst/gl/eagl/gstglcontext_eagl.m
gst-libs/gst/gl/gstgldisplay.c
gst-libs/gst/gl/gstgldisplay.h

index b869030..ec18a0e 100644 (file)
@@ -103,7 +103,13 @@ gst_gl_context_eagl_new (GstGLDisplay * display)
 {
   GstGLContextEagl *context;
 
-  /* there isn't actually a display type for eagl yet? */
+  if ((gst_gl_display_get_handle_type (display) & GST_GL_DISPLAY_TYPE_EAGL)
+      == GST_GL_DISPLAY_TYPE_NONE) {
+    GST_INFO ("Wrong display type %u for this window type %u", display->type,
+        GST_GL_DISPLAY_TYPE_EAGL);
+    return NULL;
+  }
+
   context = g_object_new (GST_TYPE_GL_CONTEXT_EAGL, NULL);
   gst_object_ref_sink (context);
 
index dbd2d0a..effaaa3 100644 (file)
@@ -265,18 +265,9 @@ gst_gl_display_finalize (GObject * object)
   G_OBJECT_CLASS (gst_gl_display_parent_class)->finalize (object);
 }
 
-/**
- * gst_gl_display_new:
- *
- * Returns: (transfer full): a new #GstGLDisplay
- *
- * Since: 1.4
- */
-GstGLDisplay *
-gst_gl_display_new (void)
+static void
+init_debug (void)
 {
-  GstGLDisplay *display = NULL;
-  const gchar *user_choice, *platform_choice;
   static gsize _init = 0;
 
   if (g_once_init_enter (&_init)) {
@@ -284,29 +275,106 @@ gst_gl_display_new (void)
         "gldisplay element");
     g_once_init_leave (&_init, 1);
   }
+}
+
+static GstGLDisplayType
+gst_gl_display_type_from_environment (void)
+{
+  const char *env = g_getenv ("GST_GL_WINDOW");
+  const char *platform = g_getenv ("GST_GL_PLATFORM");
+
+  init_debug ();
 
-  user_choice = g_getenv ("GST_GL_WINDOW");
-  platform_choice = g_getenv ("GST_GL_PLATFORM");
   GST_INFO ("creating a display, user choice:%s (platform: %s)",
-      GST_STR_NULL (user_choice), GST_STR_NULL (platform_choice));
+      GST_STR_NULL (env), GST_STR_NULL (platform));
+
+  if (!env && !platform)
+    return GST_GL_DISPLAY_TYPE_ANY;
+
+  if (env) {
+    if (g_strstr_len (env, 3, "x11")) {
+      return GST_GL_DISPLAY_TYPE_X11;
+    } else if (g_strstr_len (env, 7, "wayland")) {
+      return GST_GL_DISPLAY_TYPE_WAYLAND;
+    } else if (g_strstr_len (env, 5, "cocoa")) {
+      return GST_GL_DISPLAY_TYPE_COCOA;
+    } else if (g_strstr_len (env, 5, "win32")) {
+      return GST_GL_DISPLAY_TYPE_WIN32;
+    } else if (g_strstr_len (env, 8, "dispmanx")) {
+      return GST_GL_DISPLAY_TYPE_DISPMANX;
+    } else if (g_strstr_len (env, 3, "egl")) {
+      return GST_GL_DISPLAY_TYPE_EGL;
+    } else if (g_strstr_len (env, 6, "viv-fb")) {
+      return GST_GL_DISPLAY_TYPE_VIV_FB;
+    } else if (g_strstr_len (env, 3, "gbm")) {
+      return GST_GL_DISPLAY_TYPE_GBM;
+    } else if (g_strstr_len (env, 10, "egl-device")) {
+      return GST_GL_DISPLAY_TYPE_EGL_DEVICE;
+    } else if (g_strstr_len (env, 4, "eagl")) {
+      return GST_GL_DISPLAY_TYPE_EAGL;
+    } else if (g_strstr_len (env, 7, "android")) {
+      return GST_GL_DISPLAY_TYPE_EGL;
+    } else if (g_strstr_len (env, 4, "winrt")) {
+      return GST_GL_DISPLAY_TYPE_EGL;
+    }
+  }
+
+  if (platform && g_strstr_len (platform, 3, "egl")) {
+    return GST_GL_DISPLAY_TYPE_EGL;
+  }
+
+  return GST_GL_DISPLAY_TYPE_NONE;
+}
+
+static GstGLDisplay *
+create_dummy_display (void)
+{
+  GstGLDisplay *display = g_object_new (GST_TYPE_GL_DISPLAY, NULL);
+  return gst_object_ref_sink (display);
+}
+
+/**
+ * gst_gl_display_new_with_type:
+ * @type: #GstGLDisplayType
+ *
+ * Will always return a #GstGLDisplay of a single type.  This differs from
+ * gst_gl_display_new() and the seemingly equivalent call
+ * gst_gl_display_new_with_type (GST_GL_DISPLAY_TYPE_ANY) in that the latter
+ * may return NULL.
+ *
+ * Returns: (transfer full) (nullable): a new #GstGLDisplay or %NULL if @type is
+ *          not supported
+ *
+ * Since: 1.20
+ */
+GstGLDisplay *
+gst_gl_display_new_with_type (GstGLDisplayType type)
+{
+  GstGLDisplay *display = NULL;
+  GstGLDisplayType custom_new_types = 0;
+
+  init_debug ();
 
 #if GST_GL_HAVE_WINDOW_COCOA
-  if (!display && (!user_choice || g_strstr_len (user_choice, 5, "cocoa"))) {
+  if (!display && (type & GST_GL_DISPLAY_TYPE_COCOA)) {
     display = GST_GL_DISPLAY (gst_gl_display_cocoa_new ());
     if (!display)
       return NULL;
   }
 #endif
+  custom_new_types |= GST_GL_DISPLAY_TYPE_COCOA;
 #if GST_GL_HAVE_WINDOW_WAYLAND
-  if (!display && (!user_choice || g_strstr_len (user_choice, 7, "wayland")))
+  if (!display && (type & GST_GL_DISPLAY_TYPE_WAYLAND))
     display = GST_GL_DISPLAY (gst_gl_display_wayland_new (NULL));
 #endif
+  custom_new_types |= GST_GL_DISPLAY_TYPE_WAYLAND;
 #if GST_GL_HAVE_WINDOW_X11
-  if (!display && (!user_choice || g_strstr_len (user_choice, 3, "x11")))
+  if (!display && (type & GST_GL_DISPLAY_TYPE_X11))
     display = GST_GL_DISPLAY (gst_gl_display_x11_new (NULL));
 #endif
+  custom_new_types |= GST_GL_DISPLAY_TYPE_X11;
 #if GST_GL_HAVE_WINDOW_VIV_FB
-  if (!display && (!user_choice || g_strstr_len (user_choice, 6, "viv-fb"))) {
+  if (!display && (GST_GL_DISPLAY_TYPE_VIV_FB)) {
     const gchar *disp_idx_str = NULL;
     gint disp_idx = 0;
     disp_idx_str = g_getenv ("GST_GL_VIV_FB");
@@ -318,27 +386,77 @@ gst_gl_display_new (void)
     display = GST_GL_DISPLAY (gst_gl_display_viv_fb_new (disp_idx));
   }
 #endif
+  custom_new_types |= GST_GL_DISPLAY_TYPE_VIV_FB;
 #if GST_GL_HAVE_WINDOW_GBM
-  if (!display && (!user_choice || g_strstr_len (user_choice, 3, "gbm"))) {
+  if (!display && (type & GST_GL_DISPLAY_TYPE_GBM)) {
     display = GST_GL_DISPLAY (gst_gl_display_gbm_new ());
   }
 #endif
+  custom_new_types |= GST_GL_DISPLAY_TYPE_GBM;
 #if GST_GL_HAVE_PLATFORM_EGL
-  if (!display && (user_choice && g_strstr_len (user_choice, 10, "egl-device"))) {
+  if (!display && (type == GST_GL_DISPLAY_TYPE_EGL_DEVICE)) {
     display = GST_GL_DISPLAY (gst_gl_display_egl_device_new (0));
   }
 
-  if (!display && (!platform_choice
-          || g_strstr_len (platform_choice, 3, "egl"))) {
+  if (!display && (type & GST_GL_DISPLAY_TYPE_EGL)) {
     display = GST_GL_DISPLAY (gst_gl_display_egl_new ());
   }
 #endif
+  custom_new_types |= GST_GL_DISPLAY_TYPE_EGL_DEVICE;
+  custom_new_types |= GST_GL_DISPLAY_TYPE_EGL;
+  custom_new_types |= GST_GL_DISPLAY_TYPE_DISPMANX;
+  custom_new_types |= GST_GL_DISPLAY_TYPE_WINRT;
+  custom_new_types |= GST_GL_DISPLAY_TYPE_ANDROID;
+#if GST_GL_HAVE_WINDOW_WIN32 || GST_GL_HAVE_WINDOW_EAGL
   if (!display) {
-    GST_INFO ("Could not create platform/winsys display. user specified %s "
-        "(platform: %s), creating dummy",
-        GST_STR_NULL (user_choice), GST_STR_NULL (platform_choice));
+    GstGLDisplayType create_type = 0;
+    if (type & GST_GL_DISPLAY_TYPE_WIN32)
+      create_type = GST_GL_DISPLAY_TYPE_WIN32;
+    else if (type & GST_GL_DISPLAY_TYPE_EAGL)
+      create_type = GST_GL_DISPLAY_TYPE_EAGL;
+    if (create_type) {
+      GST_INFO_OBJECT (display, "Creating display with type %u(0x%x)",
+          create_type, create_type);
+      display = create_dummy_display ();
+      display->type = create_type;
+    }
+  }
+#endif
+  custom_new_types |= GST_GL_DISPLAY_TYPE_WIN32;
+  custom_new_types |= GST_GL_DISPLAY_TYPE_EAGL;
+
+  if (!display && type != GST_GL_DISPLAY_TYPE_ANY
+      && type != GST_GL_DISPLAY_TYPE_NONE) {
+    /* remove all the display types that we know about */
+    type &= ~custom_new_types;
+    if (type && (type & (type - 1)) == 0) {
+      /* only create a dummy display if we only have a single type */
+      GST_INFO_OBJECT (display, "Creating dummy display with type %u(0x%x)",
+          type, type);
+      display = create_dummy_display ();
+      display->type = type;
+    }
+  }
 
+  return display;
+}
+
+/**
+ * gst_gl_display_new:
+ *
+ * Returns: (transfer full): a new #GstGLDisplay
+ *
+ * Since: 1.4
+ */
+GstGLDisplay *
+gst_gl_display_new (void)
+{
+  GstGLDisplayType env_choice = gst_gl_display_type_from_environment ();
+  GstGLDisplay *display = gst_gl_display_new_with_type (env_choice);
+
+  if (!display) {
     display = g_object_new (GST_TYPE_GL_DISPLAY, NULL);
+    GST_INFO_OBJECT (display, "Creating dummy display");
     gst_object_ref_sink (display);
   }
 
index c83b07a..9f52d10 100644 (file)
@@ -50,9 +50,36 @@ GType gst_gl_display_get_type (void);
  * @GST_GL_DISPLAY_TYPE_EGL: EGL display
  * @GST_GL_DISPLAY_TYPE_VIV_FB: Vivante Framebuffer display
  * @GST_GL_DISPLAY_TYPE_GBM: Mesa3D GBM display
- * @GST_GL_DISPLAY_TYPE_EGL_DEVICE: EGLDevice display (Since: 1.18)
  * @GST_GL_DISPLAY_TYPE_ANY: any display type
  */
+/**
+ * GST_GL_DISPLAY_TYPE_EGL_DEVICE:
+ *
+ * EGLDevice display.
+ *
+ * Since: 1.18
+ */
+/**
+ * GST_GL_DISPLAY_TYPE_EAGL:
+ *
+ * EAGL display.
+ *
+ * Since: 1.20
+ */
+/**
+ * GST_GL_DISPLAY_TYPE_WINRT:
+ *
+ * WinRT display.
+ *
+ * Since: 1.20
+ */
+/**
+ * GST_GL_DISPLAY_TYPE_ANDROID:
+ *
+ * Android display.
+ *
+ * Since: 1.20
+ */
 typedef enum
 {
   GST_GL_DISPLAY_TYPE_NONE = 0,
@@ -65,6 +92,9 @@ typedef enum
   GST_GL_DISPLAY_TYPE_VIV_FB = (1 << 6),
   GST_GL_DISPLAY_TYPE_GBM = (1 << 7),
   GST_GL_DISPLAY_TYPE_EGL_DEVICE = (1 << 8),
+  GST_GL_DISPLAY_TYPE_EAGL = (1 << 9),
+  GST_GL_DISPLAY_TYPE_WINRT = (1 << 10),
+  GST_GL_DISPLAY_TYPE_ANDROID = (1 << 11),
 
   GST_GL_DISPLAY_TYPE_ANY = G_MAXUINT32
 } GstGLDisplayType;
@@ -104,6 +134,8 @@ struct _GstGLDisplayClass
 
 GST_GL_API
 GstGLDisplay *gst_gl_display_new (void);
+GST_GL_API
+GstGLDisplay *gst_gl_display_new_with_type (GstGLDisplayType type);
 
 #define gst_gl_display_lock(display)        GST_OBJECT_LOCK (display)
 #define gst_gl_display_unlock(display)      GST_OBJECT_UNLOCK (display)