[gtk/wip.win32.fixes: 21/21] gtkgstsink.c: Acquire GstGL API manually if needed




commit 79098e5fce56beda79776d339d19fa550b54fe28
Author: Chun-wei Fan <fanchunwei src gnome org>
Date:   Fri May 21 12:44:37 2021 +0800

    gtkgstsink.c: Acquire GstGL API manually if needed
    
    We need to juggle things between our GstGLContext and GdkGLContext,
    which involved going through libepoxy.  libepoxy provided
    epoxy_handle_external_wglMakeCurrent(), which is required after we call
    wglMakeCurrent() from within GstGL, so that it has the correct GL
    function pointers to perform gdk_gl_context_make_current() for
    WGL (desktop OpenGL) contexts, but neither libepoxy nor GstGL provide
    functionality to go the other way round.
    
    In order to remedy that, we call glGetString() and glGetIntegerv()
    (which is routed through libepoxy and so we have the correct function
    pointers for them) directly when our GdkGLContext is a WGL context, so
    that we can correctly determine the GstGLAPI that we want to use for our
    GstGLContext.  For EGL contexts, we continue to use
    gst_gl_context_get_current_gl_api().

 modules/media/gtkgstsink.c | 61 ++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 56 insertions(+), 5 deletions(-)
---
diff --git a/modules/media/gtkgstsink.c b/modules/media/gtkgstsink.c
index 746f02b327..c37254c699 100644
--- a/modules/media/gtkgstsink.c
+++ b/modules/media/gtkgstsink.c
@@ -382,6 +382,60 @@ reactivate_gdk_wgl_context (GdkGLContext *ctx)
   if (!gdk_gl_context_get_use_es (ctx))
     gdk_gl_context_make_current (ctx);
 }
+
+/*
+ * Unfortunately, libepoxy does not offer a way to allow us to safely call
+ * gst_gl_context_get_current_gl_api() on a WGL context that underlies a
+ * GdkGLContext after we notify libepoxy an external wglMakeCurrent() has
+ * been called (which is required for the first gdk_gl_context_make_current()
+ * call in gtk_gst_sink_initialize_gl(), for instance), so we can't do
+ * gst_gl_context_get_current_gl_api() directly on WGL contexts that underlies
+ * GdkGLContext's.  So, we do things manually on WGL, which mimics what is
+ * done in gst_gl_context_get_current_gl_api()...
+ */
+static gboolean
+check_win32_gst_gl_api (GdkGLContext  *ctx,
+                        GstGLPlatform *platform,
+                        GstGLAPI      *gl_api)
+{
+  gboolean is_gles = gdk_gl_context_get_use_es (ctx);
+
+  g_return_val_if_fail (*gl_api == GST_GL_API_NONE, FALSE);
+
+  *platform = is_gles ? GST_GL_PLATFORM_EGL : GST_GL_PLATFORM_WGL;
+
+  if (is_gles)
+    *gl_api = gst_gl_context_get_current_gl_api (*platform, NULL, NULL);
+  else
+    {
+      int major, minor;
+      const char *glver = glGetString (GL_VERSION);
+
+      if (glver == NULL || strlen (glver) < 3)
+               return is_gles;
+
+      sscanf (glver, "%d.%d", &major, &minor);
+
+      if (major <= 0 || minor < 0)
+               return is_gles;
+
+      if (major >= 3 || (major == 3 && minor >= 1))
+        {
+          GLuint context_flags = 0;
+
+          glGetIntegerv (GL_CONTEXT_PROFILE_MASK, &context_flags);
+
+          if (context_flags & GL_CONTEXT_CORE_PROFILE_BIT)
+            *gl_api |= GST_GL_API_OPENGL3;
+          if (context_flags & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
+            *gl_api |= GST_GL_API_OPENGL;
+        }
+      else
+        *gl_api = GST_GL_API_OPENGL;
+    }
+
+  return is_gles;
+}
 #else
 #define HANDLE_EXTERNAL_WGL_MAKE_CURRENT(ctx)
 #define DEACTIVATE_WGL_CONTEXT(ctx)
@@ -470,14 +524,11 @@ gtk_gst_sink_initialize_gl (GtkGstSink *self)
 #if GST_GL_HAVE_WINDOW_WIN32 && (GST_GL_HAVE_PLATFORM_WGL || GST_GL_HAVE_PLATFORM_EGL) && defined 
(GDK_WINDOWING_WIN32)
   if (GDK_IS_WIN32_DISPLAY (display))
     {
-      gboolean is_gles = gdk_gl_context_get_use_es (self->gdk_context);
+      gboolean is_gles = check_win32_gst_gl_api (self->gdk_context, &platform, &gl_api);
       const gchar *gl_type = is_gles ? "EGL" : "WGL";
 
-      platform = is_gles ? GST_GL_PLATFORM_EGL : GST_GL_PLATFORM_WGL;
-
       GST_DEBUG_OBJECT (self, "got %s on Win32!", gl_type);
 
-      gl_api = gst_gl_context_get_current_gl_api (platform, NULL, NULL);
       gl_handle = gst_gl_context_get_current_gl_context (platform);
 
       if (gl_handle)
@@ -491,7 +542,7 @@ gtk_gst_sink_initialize_gl (GtkGstSink *self)
            * otherwise gst_gl_display_new() will assume an EGL display, which won't work for us
            */
 
-          if (gl_api == GST_GL_API_OPENGL3 || gl_api == GST_GL_API_OPENGL)
+          if (gl_api & (GST_GL_API_OPENGL3 | GST_GL_API_OPENGL))
             {
 #ifdef HAVE_GST_GL_DISPLAY_NEW_WITH_TYPE
               self->gst_display = gst_gl_display_new_with_type (GST_GL_DISPLAY_TYPE_WIN32);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]