From f0eca69a14137b8a9383fe2706c31f2365ff8b36 Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Tue, 18 May 2021 19:56:13 +1000 Subject: [PATCH] gl/display: provide a gst_gl_display_new_with_type() Allows more fine-grained control over the exact display type that is created. Part-of: --- gst-libs/gst/gl/eagl/gstglcontext_eagl.m | 8 +- gst-libs/gst/gl/gstgldisplay.c | 168 +++++++++++++++++++---- gst-libs/gst/gl/gstgldisplay.h | 34 ++++- 3 files changed, 183 insertions(+), 27 deletions(-) diff --git a/gst-libs/gst/gl/eagl/gstglcontext_eagl.m b/gst-libs/gst/gl/eagl/gstglcontext_eagl.m index b869030ac5..ec18a0e748 100644 --- a/gst-libs/gst/gl/eagl/gstglcontext_eagl.m +++ b/gst-libs/gst/gl/eagl/gstglcontext_eagl.m @@ -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); diff --git a/gst-libs/gst/gl/gstgldisplay.c b/gst-libs/gst/gl/gstgldisplay.c index dbd2d0ad52..effaaa3a0f 100644 --- a/gst-libs/gst/gl/gstgldisplay.c +++ b/gst-libs/gst/gl/gstgldisplay.c @@ -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); } diff --git a/gst-libs/gst/gl/gstgldisplay.h b/gst-libs/gst/gl/gstgldisplay.h index c83b07ae3a..9f52d109f8 100644 --- a/gst-libs/gst/gl/gstgldisplay.h +++ b/gst-libs/gst/gl/gstgldisplay.h @@ -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)