[gtk+] gdk/win32: Fix Win32 GL Context switching



commit 322814989280441c25fc654dba4b7ac427fdfb57
Author: Chun-wei Fan <fanchunwei src gnome org>
Date:   Mon Oct 30 15:00:28 2017 +0800

    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

 gdk/win32/gdkdisplay-win32.h   |    1 -
 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 c468a0e..9d7a18d 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 8a5a1c2..0bb5f34 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);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]