Merge branch 'alternative-fix-5685' into 'main'

GDK/Win32: Use wgl* functions directly as needed (fix #5685)

Closes #5685

See merge request GNOME/gtk!5702
This commit is contained in:
Chun-wei Fan 2023-03-24 15:30:01 +00:00
commit d209f55677
5 changed files with 88 additions and 77 deletions

View File

@ -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);
}

View 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)

View 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>
@ -31,9 +32,18 @@
#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__ */

View 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',

View 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;
}