[gtk/workaround-win32-intel-blit] gdkglcontext-win32.c: Workaround Intel glBlitFramebuffer() issues




commit 6cd4eef1c8a3a03971f0a6713b7c2c858fe5d673
Author: Chun-wei Fan <fanchunwei src gnome org>
Date:   Wed Dec 23 18:32:11 2020 +0800

    gdkglcontext-win32.c: Workaround Intel glBlitFramebuffer() issues
    
    Intel OpenGL drivers have an issue where the results of a series of
    glBlitFramebuffer() can delay updating the display, when we use GDK_GL=always,
    which is manifested when attempting to enter text in text boxes.
    
    This attempts to work around this issue by requiring a glFlush() call and a
    retry to the same glBlitFramebuffer() calls to avoid delays in keystrokes when
    using GDK_GL=always and when not using libANGLE OpenGL/ES, when an Intel OpenGL
    driver is being used.
    
    Fixes issue 3487
    emulation

 gdk/win32/gdkdisplay-win32.h   |  3 +++
 gdk/win32/gdkglcontext-win32.c | 37 +++++++++++++++++++++++++++----------
 2 files changed, 30 insertions(+), 10 deletions(-)
---
diff --git a/gdk/win32/gdkdisplay-win32.h b/gdk/win32/gdkdisplay-win32.h
index 3089f4dea0..f33b76bf34 100644
--- a/gdk/win32/gdkdisplay-win32.h
+++ b/gdk/win32/gdkdisplay-win32.h
@@ -102,6 +102,9 @@ struct _GdkWin32Display
   guint hasWglARBPixelFormat : 1;
   guint hasWglARBmultisample : 1;
 
+  /* compensate around Intel OpenGL driver issues on blitting, see issue #3487 */
+  guint needIntelGLWorkaround : 1; 
+
 #ifdef GDK_WIN32_ENABLE_EGL
   guint hasEglKHRCreateContext : 1;
   guint hasEglSurfacelessContext : 1;
diff --git a/gdk/win32/gdkglcontext-win32.c b/gdk/win32/gdkglcontext-win32.c
index 0782c9a59a..7e7549af92 100644
--- a/gdk/win32/gdkglcontext-win32.c
+++ b/gdk/win32/gdkglcontext-win32.c
@@ -123,21 +123,34 @@ gdk_win32_gl_context_init (GdkWin32GLContext *self)
 }
 
 static void
-gdk_gl_blit_region (GdkWindow *window, cairo_region_t *region)
+gdk_gl_blit_region (GdkWindow      *window,
+                    cairo_region_t *region,
+                    gboolean        use_intel_workaround)
 {
-  int n_rects, i;
+  int n_rects, i, j;
   int scale = gdk_window_get_scale_factor (window);
   int wh = gdk_window_get_height (window);
   cairo_rectangle_int_t rect;
+  int retries = 0;
+
+  if (use_intel_workaround)
+    retries = 1;
 
   n_rects = cairo_region_num_rectangles (region);
-  for (i = 0; i < n_rects; i++)
+
+  for (i = 0; i <= retries; i ++)
     {
-      cairo_region_get_rectangle (region, i, &rect);
-      glScissor (rect.x * scale, (wh - rect.y - rect.height) * scale, rect.width * scale, rect.height * 
scale);
-      glBlitFramebuffer (rect.x * scale, (wh - rect.y - rect.height) * scale, (rect.x + rect.width) * scale, 
(wh - rect.y) * scale,
-                         rect.x * scale, (wh - rect.y - rect.height) * scale, (rect.x + rect.width) * scale, 
(wh - rect.y) * scale,
-                         GL_COLOR_BUFFER_BIT, GL_NEAREST);
+      for (j = 0; j < n_rects; j++)
+        {
+          cairo_region_get_rectangle (region, j, &rect);
+          glScissor (rect.x * scale, (wh - rect.y - rect.height) * scale, rect.width * scale, rect.height * 
scale);
+          glBlitFramebuffer (rect.x * scale, (wh - rect.y - rect.height) * scale, (rect.x + rect.width) * 
scale, (wh - rect.y) * scale,
+                             rect.x * scale, (wh - rect.y - rect.height) * scale, (rect.x + rect.width) * 
scale, (wh - rect.y) * scale,
+                             GL_COLOR_BUFFER_BIT, GL_NEAREST);
+        }
+
+      if (retries > 0)
+        glFlush ();
     }
 }
 
@@ -206,7 +219,7 @@ _gdk_win32_gl_context_end_frame (GdkGLContext *context,
         {
           glDrawBuffer(GL_FRONT);
           glReadBuffer(GL_BACK);
-          gdk_gl_blit_region (window, painted);
+          gdk_gl_blit_region (window, painted, display->needIntelGLWorkaround);
           glDrawBuffer(GL_BACK);
           glFlush();
 
@@ -224,7 +237,7 @@ _gdk_win32_gl_context_end_frame (GdkGLContext *context,
       gboolean force_egl_redraw_all = _get_is_egl_force_redraw (window);
 
       if (context_win32->do_blit_swap && !force_egl_redraw_all)
-        gdk_gl_blit_region (window, painted);
+        gdk_gl_blit_region (window, painted, FALSE);
       else if (force_egl_redraw_all)
         {
           GdkRectangle rect = {0, 0, gdk_window_get_width (window), gdk_window_get_height (window)};
@@ -616,10 +629,13 @@ _gdk_win32_display_init_gl (GdkDisplay *display,
         epoxy_has_wgl_extension (dummy.hdc, "WGL_ARB_pixel_format");
       display_win32->hasWglARBmultisample =
         epoxy_has_wgl_extension (dummy.hdc, "WGL_ARB_multisample");
+      display_win32->needIntelGLWorkaround =
+        (g_ascii_strcasecmp (glGetString (GL_VENDOR), "intel") == 0);
 
       GDK_NOTE (OPENGL,
                 g_print ("WGL API version %d.%d found\n"
                          " - Vendor: %s\n"
+                         " - Intel OpenGL workaround: %s\n"
                          " - Checked extensions:\n"
                          "\t* WGL_ARB_pixel_format: %s\n"
                          "\t* WGL_ARB_create_context: %s\n"
@@ -629,6 +645,7 @@ _gdk_win32_display_init_gl (GdkDisplay *display,
                          display_win32->gl_version / 10,
                          display_win32->gl_version % 10,
                          glGetString (GL_VENDOR),
+                         display_win32->needIntelGLWorkaround ? "yes" : "no",
                          display_win32->hasWglARBPixelFormat ? "yes" : "no",
                          display_win32->hasWglARBCreateContext ? "yes" : "no",
                          display_win32->hasWglEXTSwapControl ? "yes" : "no",


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