GDK-Win32: Add wrapper functions for calling core wgl* functions

This is a backport from the GTK-4.x update, so that we can aim to
support gtkglsink in gst-plugins-good even on Windows, beyond using
just Cairo in gstsink for rendering.

From the commit message in GTK-4.x, in commit 627ee674:

We might be dealing with GL contexts from different threads, which have more
gotchas when we are using libepoxy, so in case the function pointers for
these are invalidated by wglMakeCurrent() calls outside of GTK/GDK, such as
in GstGL, we want to use these functions that are directly linked to
opengl32.dll provided by the system/ICD, by linking to opengl32.lib.

This will ensure that we will indeed call the "correct" wgl* functions that
we need.
This commit is contained in:
Chun-wei Fan 2024-05-22 11:50:59 +08:00
parent 60a3955ce2
commit a0306f758f
5 changed files with 90 additions and 15 deletions

View File

@ -216,6 +216,7 @@ if win32_enabled
cc.find_library('comctl32'),
cc.find_library('dwmapi'),
cc.find_library('imm32'),
cc.find_library('opengl32'),
cc.find_library('setupapi'),
cc.find_library('winmm')]

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 underlying WGL context in,
* GdkGLContext 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

@ -397,12 +397,12 @@ gdk_win32_gl_context_dispose_wgl (GObject *gobject)
{
GdkWindow *window = gdk_gl_context_get_window (context);
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;
gdk_win32_gl_context_cleanup (context);
@ -843,7 +843,7 @@ gdk_win32_display_make_wgl_context_current (GdkDisplay *display,
if (context == NULL)
{
wglMakeCurrent(NULL, NULL);
gdk_win32_private_wglMakeCurrent (NULL, NULL);
return TRUE;
}
@ -851,8 +851,8 @@ gdk_win32_display_make_wgl_context_current (GdkDisplay *display,
context_win32 = GDK_WIN32_GL_CONTEXT (context);
window = gdk_gl_context_get_window (context);
if (!wglMakeCurrent (context_win32->gl_hdc,
GDK_WIN32_GL_CONTEXT_WGL (context)->wgl_context))
if (!gdk_win32_private_wglMakeCurrent (context_win32->gl_hdc,
GDK_WIN32_GL_CONTEXT_WGL (context)->wgl_context))
{
GDK_NOTE (OPENGL, g_print ("Making WGL context current failed\n"));
return FALSE;

View File

@ -21,20 +21,29 @@
#ifndef __GDK_WIN32_GL_CONTEXT__
#define __GDK_WIN32_GL_CONTEXT__
#include <epoxy/gl.h>
#include <epoxy/wgl.h>
#ifdef DONT_INCLUDE_LIBEPOXY
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# include <GL/gl.h>
#ifdef GDK_WIN32_ENABLE_EGL
# include <epoxy/egl.h>
# include <glib.h>
#else
# include <epoxy/gl.h>
# include <epoxy/wgl.h>
# ifdef GDK_WIN32_ENABLE_EGL
# include <epoxy/egl.h>
# endif
# include "gdkglcontextprivate.h"
# include "gdkdisplayprivate.h"
# include "gdkvisual.h"
# include "gdkwindow.h"
#endif
#include "gdkglcontextprivate.h"
#include "gdkdisplayprivate.h"
#include "gdkvisual.h"
#include "gdkwindow.h"
G_BEGIN_DECLS
#ifndef DONT_INCLUDE_LIBEPOXY
void
gdk_win32_window_invalidate_egl_framebuffer (GdkWindow *window);
@ -52,6 +61,14 @@ gboolean
gdk_win32_display_make_gl_context_current (GdkDisplay *display,
GdkGLContext *context);
#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

@ -11,6 +11,7 @@ gdk_win32_sources = files(
'gdkevents-win32.c',
'gdkgeometry-win32.c',
'gdkglcontext-win32.c',
'gdkglcontext-win32-private.c',
'gdkglobals-win32.c',
'gdkkeys-win32.c',
'gdkkeys-win32-impl.c',