diff options
author | Chun-wei Fan <fanchunwei@src.gnome.org> | 2017-10-30 15:00:28 +0800 |
---|---|---|
committer | Chun-wei Fan <fanchunwei@src.gnome.org> | 2017-11-04 10:39:03 +0800 |
commit | 322814989280441c25fc654dba4b7ac427fdfb57 (patch) | |
tree | c45169cccc6f4b7d9054e61ff8eeeaec4149bfd2 | |
parent | 6a12a3cd10c9985d2dbbf176e6899b54880e14dd (diff) | |
download | gtk+-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.h | 1 | ||||
-rw-r--r-- | gdk/win32/gdkglcontext-win32.c | 43 |
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); |