Merge branch 'alternative-fix-5685' into 'main'
authorChun-wei Fan <fanc999@yahoo.com.tw>
Fri, 24 Mar 2023 15:30:01 +0000 (15:30 +0000)
committerChun-wei Fan <fanc999@yahoo.com.tw>
Fri, 24 Mar 2023 15:38:58 +0000 (11:38 -0400)
GDK/Win32: Use wgl* functions directly as needed (fix #5685)

Closes #5685

See merge request GNOME/gtk!5702

(cherry picked from commit d209f5567768aaa445d70a30424df2041ed3ac75)

627ee674 GDK-Win32: Add wrapper functions for calling core wgl* functions
b5ebe270 gtkgstsink.c: Drop workarounds needed for Windows

gdk/win32/gdkglcontext-win32-wgl-private.c [new file with mode: 0644]
gdk/win32/gdkglcontext-win32-wgl.c
gdk/win32/gdkglcontext-win32.h
gdk/win32/meson.build
modules/media/gtkgstsink.c

diff --git a/gdk/win32/gdkglcontext-win32-wgl-private.c b/gdk/win32/gdkglcontext-win32-wgl-private.c
new file mode 100644 (file)
index 0000000..7da5016
--- /dev/null
@@ -0,0 +1,56 @@
+/* GDK - The GIMP Drawing Kit
+ *
+ * gdkglcontext-win32-wgl-private.c: Win32 specific OpenGL wrappers
+ *
+ * Copyright © 2023 Chun-wei Fan
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * These wrapper functions are used when we don't want to use the wgl*() core functions
+ * that we acquire via libepoxy (such as when we are disposing the Gdk(W)GLContext from,
+ * different threads, so for these calls, we are actually linking to the system's/ICD
+ * opengl32.dll directly, so that we are guaranteed that the "right" versions of these
+ * WGL calls are carried out.  This must be a separate source file because we can't include
+ * the system's GL/gl.h with epoxy/(w)gl.h together in a single source file.  We should not
+ * need to use these when we are creating/initializing a WGL context in GDK, since we should
+ * be in the same thread at this point.
+ */
+
+#define DONT_INCLUDE_LIBEPOXY
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <GL/gl.h>
+
+#include "gdkglcontext-win32.h"
+
+void
+gdk_win32_private_wglDeleteContext (HGLRC hglrc)
+{
+  wglDeleteContext (hglrc);
+}
+
+HGLRC
+gdk_win32_private_wglGetCurrentContext (void)
+{
+  return wglGetCurrentContext ();
+}
+
+BOOL
+gdk_win32_private_wglMakeCurrent (HDC   hdc,
+                                  HGLRC hglrc)
+{
+  return wglMakeCurrent (hdc, hglrc);
+}
index 4c32a74f887e3d0bcbf56f883450ae3aab57a738..572c2f37b7fbf6b165977cc853fb9e830d2408c4 100644 (file)
@@ -60,12 +60,12 @@ gdk_win32_gl_context_wgl_dispose (GObject *gobject)
 
   if (context_wgl->wgl_context != NULL)
     {
-      if (wglGetCurrentContext () == context_wgl->wgl_context)
-        wglMakeCurrent (NULL, NULL);
+      if (gdk_win32_private_wglGetCurrentContext () == context_wgl->wgl_context)
+        gdk_win32_private_wglMakeCurrent (NULL, NULL);
 
       GDK_NOTE (OPENGL, g_print ("Destroying WGL context\n"));
 
-      wglDeleteContext (context_wgl->wgl_context);
+      gdk_win32_private_wglDeleteContext (context_wgl->wgl_context);
       context_wgl->wgl_context = NULL;
     }
 
@@ -628,7 +628,7 @@ gdk_win32_gl_context_wgl_realize (GdkGLContext *context,
 static gboolean
 gdk_win32_gl_context_wgl_clear_current (GdkGLContext *context)
 {
-  return wglMakeCurrent (NULL, NULL);
+  return gdk_win32_private_wglMakeCurrent (NULL, NULL);
 }
 
 static gboolean
@@ -636,7 +636,7 @@ gdk_win32_gl_context_wgl_is_current (GdkGLContext *context)
 {
   GdkWin32GLContextWGL *self = GDK_WIN32_GL_CONTEXT_WGL (context);
 
-  return self->wgl_context == wglGetCurrentContext ();
+  return self->wgl_context == gdk_win32_private_wglGetCurrentContext ();
 }
 
 static gboolean
@@ -654,7 +654,7 @@ gdk_win32_gl_context_wgl_make_current (GdkGLContext *context,
   else
     hdc = GDK_WIN32_SURFACE (surface)->hdc;
 
-  if (!wglMakeCurrent (hdc, context_wgl->wgl_context))
+  if (!gdk_win32_private_wglMakeCurrent (hdc, context_wgl->wgl_context))
     return FALSE;
 
   if (!surfaceless && display_win32->hasWglEXTSwapControl)
index 77995671cec8e3573452b79cc9aeae1399e4840b..787c8b1a0962be8927ad206e290896919a78b0fe 100644 (file)
@@ -21,6 +21,7 @@
 #ifndef __GDK_WIN32_GL_CONTEXT__
 #define __GDK_WIN32_GL_CONTEXT__
 
+#ifndef DONT_INCLUDE_LIBEPOXY
 #include <epoxy/gl.h>
 #include <epoxy/wgl.h>
 
 #include "gdkglcontextprivate.h"
 #include "gdkdisplayprivate.h"
 #include "gdksurface.h"
+#else
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# include <GL/gl.h>
+
+# include <glib.h>
+#endif
 
 G_BEGIN_DECLS
 
+#ifndef DONT_INCLUDE_LIBEPOXY
+
 #define GDK_WIN32_GL_CONTEXT_CLASS(klass)         (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WIN32_GL_CONTEXT, GdkWin32GLContextClass))
 #define GDK_WIN32_GL_CONTEXT_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WIN32_GL_CONTEXT, GdkWin32GLContextClass))
 #define GDK_WIN32_IS_GL_CONTEXT_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WIN32_GL_CONTEXT))
@@ -78,6 +88,13 @@ GType     gdk_win32_gl_context_egl_get_type         (void) G_GNUC_CONST;
 void
 _gdk_win32_surface_invalidate_egl_framebuffer (GdkSurface *surface);
 
+#endif /* !DONT_INCLUDE_LIBEPOXY */
+
+HGLRC     gdk_win32_private_wglGetCurrentContext (void);
+BOOL      gdk_win32_private_wglMakeCurrent       (HDC hdc,
+                                                  HGLRC hglrc);
+void      gdk_win32_private_wglDeleteContext     (HGLRC hglrc);
+
 G_END_DECLS
 
 #endif /* __GDK_WIN32_GL_CONTEXT__ */
index bcf7d7c78ff80db51b4ad7a3fae3cbac8875d899..3dc16aabb6c6e38fbd4d491ea5967696f4fc2d51 100644 (file)
@@ -23,6 +23,7 @@ gdk_win32_sources = gdk_win32_public_sources + files([
   'gdkdevice-wintab.c',
   'gdkdrop-win32.c',
   'gdkglobals-win32.c',
+  'gdkglcontext-win32-wgl-private.c',
   'gdkhdataoutputstream-win32.c',
   'gdkinput-dmanipulation.c',
   'gdkinput-winpointer.c',
@@ -59,6 +60,7 @@ endif
 gdk_win32_deps = [
   pangowin32_dep, # FIXME
   cc.find_library('hid'),
+  cc.find_library('opengl32'),
 ]
 
 libgdk_win32 = static_library('gdk-win32',
index 0e3e29b9f73de2c3866b26311adfc5ec0edce463..552c23c23d75d0d6b84b23c62f39e1bd3c0e261a 100644 (file)
@@ -40,7 +40,6 @@
 
 #if GST_GL_HAVE_WINDOW_WIN32 && (GST_GL_HAVE_PLATFORM_WGL || GST_GL_HAVE_PLATFORM_EGL) && defined (GDK_WINDOWING_WIN32)
 #include <gdk/win32/gdkwin32.h>
-#include <epoxy/wgl.h>
 #endif
 
 #if GST_GL_HAVE_PLATFORM_EGL && (GST_GL_HAVE_WINDOW_WIN32 || GST_GL_HAVE_WINDOW_X11)
@@ -359,69 +358,6 @@ gtk_gst_sink_show_frame (GstVideoSink *vsink,
   return GST_FLOW_OK;
 }
 
-#if GST_GL_HAVE_WINDOW_WIN32 && (GST_GL_HAVE_PLATFORM_WGL || GST_GL_HAVE_PLATFORM_EGL) && defined (GDK_WINDOWING_WIN32)
-#define HANDLE_EXTERNAL_WGL_MAKE_CURRENT(ctx) handle_wgl_makecurrent(ctx)
-#define DEACTIVATE_WGL_CONTEXT(ctx) deactivate_gdk_wgl_context(ctx)
-#define REACTIVATE_WGL_CONTEXT(ctx) reactivate_gdk_wgl_context(ctx)
-
-static void
-handle_wgl_makecurrent (GdkGLContext *ctx)
-{
-  if (!gdk_gl_context_get_use_es (ctx))
-    epoxy_handle_external_wglMakeCurrent();
-}
-
-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);
-}
-
-/*
- * 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 just ask GDK about our WGL context, since it already
- * knows what kind of WGL context we have there...
- */
-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
-    *gl_api = gdk_gl_context_is_legacy (ctx) ? GST_GL_API_OPENGL : GST_GL_API_OPENGL3;
-
-  return is_gles;
-}
-#else
-#define HANDLE_EXTERNAL_WGL_MAKE_CURRENT(ctx)
-#define DEACTIVATE_WGL_CONTEXT(ctx)
-#define REACTIVATE_WGL_CONTEXT(ctx)
-#endif
-
 static gboolean
 gtk_gst_sink_initialize_gl (GtkGstSink *self)
 {
@@ -434,7 +370,6 @@ gtk_gst_sink_initialize_gl (GtkGstSink *self)
 
   display = gdk_gl_context_get_display (self->gdk_context);
 
-  HANDLE_EXTERNAL_WGL_MAKE_CURRENT (self->gdk_context);
   gdk_gl_context_make_current (self->gdk_context);
 
 #ifdef HAVE_GST_X11_SUPPORT
@@ -528,8 +463,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 = check_win32_gst_gl_api (self->gdk_context, &platform, &gl_api);
-      const gchar *gl_type = is_gles ? "EGL" : "WGL";
+      gboolean is_gles = gdk_gl_context_get_use_es (self->gdk_context);
+      const char *gl_type = is_gles ? "EGL" : "WGL";
+
+      platform = is_gles ? GST_GL_PLATFORM_EGL : GST_GL_PLATFORM_WGL;
+      gl_api = gst_gl_context_get_current_gl_api (platform, NULL, NULL);
 
       GST_DEBUG_OBJECT (self, "got %s on Win32!", gl_type);
 
@@ -596,12 +534,12 @@ gtk_gst_sink_initialize_gl (GtkGstSink *self)
       g_clear_error (&error);
       g_clear_object (&self->gst_gdk_context);
       g_clear_object (&self->gst_display);
-      HANDLE_EXTERNAL_WGL_MAKE_CURRENT (self->gdk_context);
+
       return FALSE;
     }
   else
     {
-      DEACTIVATE_WGL_CONTEXT (self->gdk_context);
+      gdk_gl_context_clear_current ();
       gst_gl_context_activate (self->gst_gdk_context, FALSE);
     }
 
@@ -615,8 +553,6 @@ gtk_gst_sink_initialize_gl (GtkGstSink *self)
       g_clear_object (&self->gst_display);
     }
 
-  HANDLE_EXTERNAL_WGL_MAKE_CURRENT (self->gdk_context);
-  REACTIVATE_WGL_CONTEXT (self->gdk_context);
   return succeeded;
 }