[gtk/wip.win32.fixes: 1/2] media/gstreamer: Attempt to use GL for video for Windows




commit 59f28f0601ea3d6044988bab8ff1dec21af32444
Author: Chun-wei Fan <fanchunwei src gnome org>
Date:   Sat Feb 13 18:40:56 2021 +0800

    media/gstreamer: Attempt to use GL for video for Windows
    
    Add a stab to support sharing the WGL context in GDK with the WGL
    context in GStreamer, so that we can also use OpenGL in the gstreamer
    media backend to playback videos.

 gdk/win32/gdkglcontext-win32.c  | 13 +++++--
 modules/media/gtkgstpaintable.c | 13 -------
 modules/media/gtkgstsink.c      | 77 ++++++++++++++++++++++++++++++++++++-----
 3 files changed, 80 insertions(+), 23 deletions(-)
---
diff --git a/gdk/win32/gdkglcontext-win32.c b/gdk/win32/gdkglcontext-win32.c
index 610711d3b8..c4427fcec3 100644
--- a/gdk/win32/gdkglcontext-win32.c
+++ b/gdk/win32/gdkglcontext-win32.c
@@ -656,10 +656,19 @@ _create_gl_context (HDC           hdc,
                                                hglrc_base,
                                                share,
                                                flags,
-                                               major,
-                                               minor,
+                                               4,
+                                               1,
                                                is_legacy);
 
+      if (hglrc == NULL)
+        hglrc = _create_gl_context_with_attribs (hdc,
+                                                 hglrc_base,
+                                                 share,
+                                                 flags,
+                                                 major,
+                                                 minor,
+                                                 is_legacy);
+
       /* return the legacy context we have if it could be setup properly, in case the 3.0+ context creation 
failed */
       if (hglrc == NULL)
         {
diff --git a/modules/media/gtkgstpaintable.c b/modules/media/gtkgstpaintable.c
index ab837382b8..ba5aefca4b 100644
--- a/modules/media/gtkgstpaintable.c
+++ b/modules/media/gtkgstpaintable.c
@@ -118,18 +118,6 @@ gtk_gst_paintable_video_renderer_create_video_sink (GstPlayerVideoRenderer *rend
   GtkGstPaintable *self = GTK_GST_PAINTABLE (renderer);
   GstElement *sink, *glsinkbin;
 
-#if GST_GL_HAVE_WINDOW_WIN32 && GST_GL_HAVE_PLATFORM_WGL && defined (GDK_WINDOWING_WIN32)
-  /*
-   * Unfortunately, we can't connect the GstGLContext with our GDKGLContext,
-   * since gdk_gl_context_make_current(), which calls wglMakeCurrent(), does not
-   * allow us to share WGL contexts across threads, which will cause a crash.
-   * See MR !3034, so no WGL in the gstreamer media backend :(
-   */
-  sink = g_object_new (GTK_TYPE_GST_SINK,
-                       "paintable", self,
-                       NULL);
-  return sink;
-#else
   sink = g_object_new (GTK_TYPE_GST_SINK,
                        "paintable", self,
                        "gl-context", self->context,
@@ -143,7 +131,6 @@ gtk_gst_paintable_video_renderer_create_video_sink (GstPlayerVideoRenderer *rend
   g_object_set (glsinkbin, "sink", sink, NULL);
 
   return glsinkbin;
-#endif
 }
 
 static void
diff --git a/modules/media/gtkgstsink.c b/modules/media/gtkgstsink.c
index 8a0a124e3b..e47b9d7360 100644
--- a/modules/media/gtkgstsink.c
+++ b/modules/media/gtkgstsink.c
@@ -35,6 +35,11 @@
 #include <gst/gl/wayland/gstgldisplay_wayland.h>
 #endif
 
+#if GST_GL_HAVE_WINDOW_WIN32 && GST_GL_HAVE_PLATFORM_WGL && defined (GDK_WINDOWING_WIN32)
+#include <gdk/win32/gdkwin32.h>
+#include <epoxy/wgl.h>
+#endif
+
 #include <gst/gl/gstglfuncs.h>
 
 enum {
@@ -341,27 +346,57 @@ gtk_gst_sink_show_frame (GstVideoSink *vsink,
   return GST_FLOW_OK;
 }
 
+#if GST_GL_HAVE_WINDOW_WIN32 && GST_GL_HAVE_PLATFORM_WGL && defined (GDK_WINDOWING_WIN32)
+#define HANDLE_EXTERNAL_WGL_MAKE_CURRENT epoxy_handle_external_wglMakeCurrent ()
+#define DEACTIVATE_WGL_CONTEXT(ctx) deactivate_gdk_wgl_context(ctx)
+#define REACTIVATE_WGL_CONTEXT(ctx) reactivate_gdk_wgl_context(ctx)
+
+static void
+deactivate_gdk_wgl_context (GdkGLContext *ctx)
+{
+  if (!gdk_gl_context_get_use_es (ctx))
+    {
+      HDC hdc = GetDC (GDK_SURFACE_HWND (gdk_gl_context_get_surface (ctx)));
+      wglMakeCurrent (hdc, NULL);
+    }
+}
+
+static void
+reactivate_gdk_wgl_context (GdkGLContext *ctx)
+{
+  if (!gdk_gl_context_get_use_es (ctx))
+    gdk_gl_context_make_current (ctx);
+}
+#else
+#define HANDLE_EXTERNAL_WGL_MAKE_CURRENT
+#define DEACTIVATE_WGL_CONTEXT(ctx)
+#define REACTIVATE_WGL_CONTEXT(ctx)
+#endif
+
 static void
 gtk_gst_sink_initialize_gl (GtkGstSink *self)
 {
   GdkDisplay *display;
   GError *error = NULL;
+  GstGLPlatform platform = GST_GL_PLATFORM_NONE;
+  GstGLAPI gl_api = GST_GL_API_NONE;
+  guintptr gl_handle = 0;
 
   display = gdk_gl_context_get_display (self->gdk_context);
 
+  HANDLE_EXTERNAL_WGL_MAKE_CURRENT;
   gdk_gl_context_make_current (self->gdk_context);
 
 #if GST_GL_HAVE_WINDOW_X11 && GST_GL_HAVE_PLATFORM_GLX && defined (GDK_WINDOWING_X11)
   if (GDK_IS_X11_DISPLAY (display))
     {
-      GstGLPlatform platform = GST_GL_PLATFORM_GLX;
-      GstGLAPI gl_api;
-      guintptr gl_handle;
+      platform = GST_GL_PLATFORM_GLX;
 
       GST_DEBUG_OBJECT (self, "got GLX on X11!");
 
       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)
         {
           self->gst_display = GST_GL_DISPLAY (gst_gl_display_x11_new_with_display 
(gdk_x11_display_get_xdisplay (display)));
@@ -378,13 +413,10 @@ gtk_gst_sink_initialize_gl (GtkGstSink *self)
 #if GST_GL_HAVE_WINDOW_WAYLAND && GST_GL_HAVE_PLATFORM_EGL && defined (GDK_WINDOWING_WAYLAND)
   if (GDK_IS_WAYLAND_DISPLAY (display))
     {
-      GstGLPlatform platform = GST_GL_PLATFORM_GLX;
-      GstGLAPI gl_api;
-      guintptr gl_handle;
+      platform = GST_GL_PLATFORM_EGL;
 
       GST_DEBUG_OBJECT (self, "got EGL on Wayland!");
 
-      platform = GST_GL_PLATFORM_EGL;
       gl_api = gst_gl_context_get_current_gl_api (platform, NULL, NULL);
       gl_handle = gst_gl_context_get_current_gl_context (platform);
 
@@ -403,6 +435,30 @@ gtk_gst_sink_initialize_gl (GtkGstSink *self)
         }
     }
   else
+#endif
+#if GST_GL_HAVE_WINDOW_WIN32 && GST_GL_HAVE_PLATFORM_WGL && defined (GDK_WINDOWING_WIN32)
+  if (GDK_IS_WIN32_DISPLAY (display) &&
+      !gdk_gl_context_get_use_es (self->gdk_context))
+    {
+      platform = GST_GL_PLATFORM_WGL;
+
+      GST_DEBUG_OBJECT (self, "got WGL on Win32!");
+
+      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)
+        {
+          self->gst_display = gst_gl_display_new ();
+          self->gst_app_context = gst_gl_context_new_wrapped (self->gst_display, gl_handle, platform, 
gl_api);
+        }
+      else
+        {
+          GST_ERROR_OBJECT (self, "Failed to get handle from GdkGLContext, not using WGL");
+             return;
+        }
+    }
+  else
 #endif
     {
       GST_INFO_OBJECT (self, "Unsupported GDK display %s for GL", G_OBJECT_TYPE_NAME (display));
@@ -412,16 +468,19 @@ gtk_gst_sink_initialize_gl (GtkGstSink *self)
   g_assert (self->gst_app_context != NULL);
 
   gst_gl_context_activate (self->gst_app_context, TRUE);
+
   if (!gst_gl_context_fill_info (self->gst_app_context, &error))
     {
       GST_ERROR_OBJECT (self, "failed to retrieve GDK context info: %s", error->message);
       g_clear_error (&error);
       g_clear_object (&self->gst_app_context);
       g_clear_object (&self->gst_display);
+      HANDLE_EXTERNAL_WGL_MAKE_CURRENT;
       return;
     }
   else
     {
+      DEACTIVATE_WGL_CONTEXT (self->gdk_context);
       gst_gl_context_activate (self->gst_app_context, FALSE);
     }
 
@@ -431,8 +490,10 @@ gtk_gst_sink_initialize_gl (GtkGstSink *self)
       g_error_free (error);
       g_clear_object (&self->gst_app_context);
       g_clear_object (&self->gst_display);
-      return;
     }
+
+  HANDLE_EXTERNAL_WGL_MAKE_CURRENT;
+  REACTIVATE_WGL_CONTEXT (self->gdk_context);
 }
 
 static void


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