summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChun-wei Fan <fanchunwei@src.gnome.org>2017-10-30 15:00:28 +0800
committerChun-wei Fan <fanchunwei@src.gnome.org>2017-11-04 10:39:03 +0800
commit322814989280441c25fc654dba4b7ac427fdfb57 (patch)
treec45169cccc6f4b7d9054e61ff8eeeaec4149bfd2
parent6a12a3cd10c9985d2dbbf176e6899b54880e14dd (diff)
downloadgtk+-322814989280441c25fc654dba4b7ac427fdfb57.tar.gz
gdk/win32: Fix Win32 GL Context switching
Since on Windows we need to use a good amount of temporary GL contexts, we need to switch back to the original GL contexts we were using when we are done with the temporary GL contexts, otherwise multi-GL windows will cause confusions causing display artifacts and crashes. Also, use the GdkWin32GLContext::gl_hdc consistently throughout the code and remove the GdkWin32Display::gl_hdc as Lukas K pointed out that GdkWin32Display::gl_hdc becomes out-of-date and so the HDC that the GL context is bound to becomes incorrect in sceanarios using multiple windows with GtkGLArea/GdkGLArea items (which would cause the artifacts in programs that use multiple windows with GtkGLArea/GdkGLArea items, and it turns out that GdkWin32Display::gl_hdc is actually not necessary to help keep track of the HDCs we use for our GL contexts. This will also fix on Windows with GDK_GL=always, or when GSK's gl renderer is used. Partly based on patch from Lukas K <lu@0x83.eu> https://bugzilla.gnome.org/show_bug.cgi?id=789213
-rw-r--r--gdk/win32/gdkdisplay-win32.h1
-rw-r--r--gdk/win32/gdkglcontext-win32.c43
2 files changed, 29 insertions, 15 deletions
diff --git a/gdk/win32/gdkdisplay-win32.h b/gdk/win32/gdkdisplay-win32.h
index c468a0e8e3..9d7a18dd52 100644
--- a/gdk/win32/gdkdisplay-win32.h
+++ b/gdk/win32/gdkdisplay-win32.h
@@ -72,7 +72,6 @@ struct _GdkWin32Display
/* WGL/OpenGL Items */
guint have_wgl : 1;
guint gl_version;
- HDC gl_hdc;
HWND gl_hwnd;
GPtrArray *monitors;
diff --git a/gdk/win32/gdkglcontext-win32.c b/gdk/win32/gdkglcontext-win32.c
index 8a5a1c249c..0bb5f34f7e 100644
--- a/gdk/win32/gdkglcontext-win32.c
+++ b/gdk/win32/gdkglcontext-win32.c
@@ -198,8 +198,6 @@ _destroy_dummy_gl_context (GdkWGLDummy dummy)
{
if (dummy.hglrc != NULL)
{
- if (wglGetCurrentContext () == dummy.hglrc)
- wglMakeCurrent (NULL, NULL);
wglDeleteContext (dummy.hglrc);
dummy.hglrc = NULL;
}
@@ -282,6 +280,10 @@ _get_wgl_pfd (HDC hdc,
gint i = 0;
int pixelAttribs[PIXEL_ATTRIBUTES];
+ /* Save up the HDC and HGLRC that we are currently using, to restore back to it when we are done here */
+ HDC hdc_current = wglGetCurrentDC ();
+ HGLRC hglrc_current = wglGetCurrentContext ();
+
if (display->hasWglARBmultisample)
{
/* 2 pairs of values needed for multisampling/AA support */
@@ -329,7 +331,10 @@ _get_wgl_pfd (HDC hdc,
best_pf = _gdk_init_dummy_context (&dummy);
if (best_pf == 0 || !wglMakeCurrent (dummy.hdc, dummy.hglrc))
- return 0;
+ {
+ wglMakeCurrent (hdc_current, hglrc_current);
+ return 0;
+ }
wglChoosePixelFormatARB (hdc,
pixelAttribs,
@@ -338,7 +343,8 @@ _get_wgl_pfd (HDC hdc,
&best_pf,
&num_formats);
- wglMakeCurrent (NULL, NULL);
+ /* Go back to the HDC that we were using, since we are done with the dummy HDC and GL Context */
+ wglMakeCurrent (hdc_current, hglrc_current);
_destroy_dummy_gl_context (dummy);
}
else
@@ -390,7 +396,7 @@ _gdk_init_dummy_context (GdkWGLDummy *dummy)
return best_idx;
}
-gboolean
+static gboolean
_gdk_win32_display_init_gl (GdkDisplay *display)
{
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
@@ -520,11 +526,18 @@ _create_gl_context (HDC hdc,
HGLRC hglrc_base = wglCreateContext (hdc);
gboolean success = TRUE;
+ /* Save up the HDC and HGLRC that we are currently using, to restore back to it when we are done here */
+ HDC hdc_current = wglGetCurrentDC ();
+ HGLRC hglrc_current = wglGetCurrentContext ();
+
/* if we have no wglCreateContextAttribsARB(), return the legacy context when all is set */
if (*is_legacy && !hasWglARBCreateContext)
{
if (_ensure_legacy_gl_context (hdc, hglrc_base, share))
- return hglrc_base;
+ {
+ wglMakeCurrent (hdc_current, hglrc_current);
+ return hglrc_base;
+ }
success = FALSE;
goto gl_fail;
@@ -574,17 +587,21 @@ _create_gl_context (HDC hdc,
}
gl_fail:
- if (!success || hglrc != NULL)
+
+ if (!success)
{
wglMakeCurrent (NULL, NULL);
wglDeleteContext (hglrc_base);
+ return NULL;
}
- if (!success)
- return NULL;
+ wglMakeCurrent (hdc_current, hglrc_current);
if (hglrc != NULL)
- return hglrc;
+ {
+ wglDeleteContext (hglrc_base);
+ return hglrc;
+ }
return hglrc_base;
}
@@ -641,6 +658,7 @@ gdk_win32_gl_context_realize (GdkGLContext *context,
g_set_error_literal (error, GDK_GL_ERROR,
GDK_GL_ERROR_UNSUPPORTED_FORMAT,
_("No available configurations for the given pixel format"));
+
return FALSE;
}
@@ -758,7 +776,6 @@ _gdk_win32_window_create_gl_context (GdkWindow *window,
hwnd = GDK_WINDOW_HWND (window);
hdc = GetDC (hwnd);
- display_win32->gl_hdc = hdc;
display_win32->gl_hwnd = hwnd;
context = g_object_new (GDK_TYPE_WIN32_GL_CONTEXT,
@@ -790,15 +807,13 @@ _gdk_win32_display_make_gl_context_current (GdkDisplay *display,
context_win32 = GDK_WIN32_GL_CONTEXT (context);
- if (!wglMakeCurrent (display_win32->gl_hdc, context_win32->hglrc))
+ if (!wglMakeCurrent (context_win32->gl_hdc, context_win32->hglrc))
{
GDK_NOTE (OPENGL,
g_print ("Making WGL context current failed\n"));
return FALSE;
}
- context_win32->gl_hdc = display_win32->gl_hdc;
-
if (context_win32->is_attached && display_win32->hasWglEXTSwapControl)
{
window = gdk_gl_context_get_window (context);