[gtk/win32-gl-reorg-3: 11/11] GDK-Win32: Add fallback mode to GLES




commit a445f86d3b365dd2958b8e182aa833b3956ae52f
Author: Chun-wei Fan <fanchunwei src gnome org>
Date:   Fri Aug 20 12:31:54 2021 +0800

    GDK-Win32: Add fallback mode to GLES
    
    ...if GLES (libANGLE) support was enabled in the build.  This way, we can
    check whether the GL driver is capable enough to support the OpenGL
    features that we use in GTK.  If the driver is not capable enough, and
    GLES support is enabled, we can try to create the GdkGLContext again as a
    GLES context.

 gdk/win32/gdkdisplay-win32.c   |   4 +-
 gdk/win32/gdkdisplay-win32.h   |   1 -
 gdk/win32/gdkglcontext-win32.c | 164 ++++++++++++++++++++++++++---------------
 3 files changed, 109 insertions(+), 60 deletions(-)
---
diff --git a/gdk/win32/gdkdisplay-win32.c b/gdk/win32/gdkdisplay-win32.c
index cad26edf4f..ff52b2bef9 100644
--- a/gdk/win32/gdkdisplay-win32.c
+++ b/gdk/win32/gdkdisplay-win32.c
@@ -1034,6 +1034,8 @@ _gdk_win32_enable_hidpi (GdkWin32Display *display)
     }
 }
 
+#if 0
+/* Keep code around in case we need to check for running on ARM64 in the future */
 static void
 _gdk_win32_check_on_arm64 (GdkWin32Display *display)
 {
@@ -1067,6 +1069,7 @@ _gdk_win32_check_on_arm64 (GdkWin32Display *display)
       g_once_init_leave (&checked, 1);
     }
 }
+#endif
 
 static void
 gdk_win32_display_init (GdkWin32Display *display)
@@ -1076,7 +1079,6 @@ gdk_win32_display_init (GdkWin32Display *display)
   display->monitors = g_ptr_array_new_with_free_func (g_object_unref);
 
   _gdk_win32_enable_hidpi (display);
-  _gdk_win32_check_on_arm64 (display);
 
   /* if we have DPI awareness, set up fixed scale if set */
   if (display->dpi_aware_type != PROCESS_DPI_UNAWARE &&
diff --git a/gdk/win32/gdkdisplay-win32.h b/gdk/win32/gdkdisplay-win32.h
index 602e666bb2..4d6ac732a6 100644
--- a/gdk/win32/gdkdisplay-win32.h
+++ b/gdk/win32/gdkdisplay-win32.h
@@ -124,7 +124,6 @@ struct _GdkWin32Display
   GdkWin32User32DPIFuncs user32_dpi_funcs;
 
   /* Running CPU items */
-  guint running_on_arm64 : 1;
   GdkWin32KernelCPUFuncs cpu_funcs;
 };
 
diff --git a/gdk/win32/gdkglcontext-win32.c b/gdk/win32/gdkglcontext-win32.c
index 86ce9ad75b..2f62262a9b 100644
--- a/gdk/win32/gdkglcontext-win32.c
+++ b/gdk/win32/gdkglcontext-win32.c
@@ -210,7 +210,7 @@ get_dummy_window_hwnd (GdkWGLDummy *dummy)
 
 static gint
 gdk_init_dummy_context (GdkWGLDummy    *dummy,
-                         const gboolean  need_alpha_bits);
+                        const gboolean  need_alpha_bits);
 
 #define PIXEL_ATTRIBUTES 19
 
@@ -455,6 +455,28 @@ gdk_win32_gl_context_end_frame_wgl (GdkGLContext   *context,
     SwapBuffers (context_win32->gl_hdc);
 }
 
+/*
+ * We need to check whether the OpenGL driver is capable of delvering
+ * what we need to use in GdkGLContext.  This function in the future
+ * will also check for blacklisted drivers, if needed.  If things fail
+ * here, we can try falling back to OpenGL/ES (libANGLE) if that is enabled.
+ */
+static gboolean
+gdk_win32_gl_context_wgl_check_capabilities (GdkWin32Display *display_win32,
+                                             GdkWGLDummy      dummy)
+{
+  if (!wglMakeCurrent (dummy.hdc, dummy.hglrc))
+    return FALSE;
+
+  display_win32->gl_version = epoxy_gl_version ();
+
+  /* We must have OpenGL/WGL 2.0 or later, or have the GL_ARB_shader_objects extension */
+  if (display_win32->gl_version < 20 && !epoxy_has_gl_extension ("GL_ARB_shader_objects"))
+    return FALSE;
+
+  return TRUE;
+}
+
 static void
 gdk_win32_display_init_wgl (GdkWin32Display *display_win32,
                             const gboolean   need_alpha_bits)
@@ -465,56 +487,61 @@ gdk_win32_display_init_wgl (GdkWin32Display *display_win32,
    */
   GdkWGLDummy dummy;
   gint best_idx = 0;
+  gboolean proceed = TRUE;
 
   memset (&dummy, 0, sizeof (GdkWGLDummy));
 
   best_idx = gdk_init_dummy_context (&dummy, need_alpha_bits);
 
-  if (best_idx == 0 || !wglMakeCurrent (dummy.hdc, dummy.hglrc))
-    {
-      display_win32->gl_type = GDK_WIN32_GL_NONE;
-      return;
-    }
+  if (best_idx != 0)
+    proceed = gdk_win32_gl_context_wgl_check_capabilities (display_win32, dummy);
 
-  display_win32->gl_version = epoxy_gl_version ();
+  if (best_idx != 0 && proceed)
+    {
+      display_win32->hasWglARBCreateContext =
+        epoxy_has_wgl_extension (dummy.hdc, "WGL_ARB_create_context");
+      display_win32->hasWglEXTSwapControl =
+        epoxy_has_wgl_extension (dummy.hdc, "WGL_EXT_swap_control");
+      display_win32->hasWglOMLSyncControl =
+        epoxy_has_wgl_extension (dummy.hdc, "WGL_OML_sync_control");
+      display_win32->hasWglARBPixelFormat =
+        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);
 
-  display_win32->hasWglARBCreateContext =
-    epoxy_has_wgl_extension (dummy.hdc, "WGL_ARB_create_context");
-  display_win32->hasWglEXTSwapControl =
-    epoxy_has_wgl_extension (dummy.hdc, "WGL_EXT_swap_control");
-  display_win32->hasWglOMLSyncControl =
-    epoxy_has_wgl_extension (dummy.hdc, "WGL_OML_sync_control");
-  display_win32->hasWglARBPixelFormat =
-    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"
+                         "\t* WGL_EXT_swap_control: %s\n"
+                         "\t* WGL_OML_sync_control: %s\n"
+                         "\t* WGL_ARB_multisample: %s\n",
+                         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",
+                         display_win32->hasWglOMLSyncControl ? "yes" : "no",
+                         display_win32->hasWglARBmultisample ? "yes" : "no"));
+
+      display_win32->gl_type = GDK_WIN32_GL_WGL;
+    }
+  else
+    display_win32->gl_type = GDK_WIN32_GL_NONE;
 
-  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"
-                     "\t* WGL_EXT_swap_control: %s\n"
-                     "\t* WGL_OML_sync_control: %s\n"
-                     "\t* WGL_ARB_multisample: %s\n",
-                     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",
-                     display_win32->hasWglOMLSyncControl ? "yes" : "no",
-                     display_win32->hasWglARBmultisample ? "yes" : "no"));
-
-  wglMakeCurrent (NULL, NULL);
-  destroy_dummy_gl_context (dummy);
-
-  display_win32->gl_type = GDK_WIN32_GL_WGL;
+  /* clean up things if we indeed created our dummy WGL context */
+  if (best_idx != 0)
+    {
+      wglMakeCurrent (NULL, NULL);
+      destroy_dummy_gl_context (dummy);
+    }
 }
 
 /* Setup the legacy WGL context after creating it */
@@ -733,6 +760,9 @@ gdk_win32_gl_context_realize_wgl (GdkGLContext  *context,
       share != NULL && gdk_gl_context_is_legacy (share))
     legacy_bit = TRUE;
 
+  /* say early enough that we are not using GLES, so that we acquire the correct versions */
+  gdk_gl_context_set_use_es (context, FALSE);
+
   gdk_gl_context_get_required_version (context, &major, &minor);
   debug_bit = gdk_gl_context_get_debug_enabled (context);
   compat_bit = gdk_gl_context_get_forward_compatible (context);
@@ -786,9 +816,6 @@ gdk_win32_gl_context_realize_wgl (GdkGLContext  *context,
 
   GDK_WIN32_GL_CONTEXT_WGL (context)->wgl_context = hglrc;
 
-  /* set whether we are using GLES */
-  gdk_gl_context_set_use_es (context, FALSE);
-
   /* OpenGL does not work with WS_EX_LAYERED enabled, so we need to
    * disable WS_EX_LAYERED when we acquire a valid HGLRC
    */
@@ -824,10 +851,10 @@ 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 (!wglMakeCurrent (context_win32->gl_hdc,
+                       GDK_WIN32_GL_CONTEXT_WGL (context)->wgl_context))
     {
-      GDK_NOTE (OPENGL,
-                g_print ("Making WGL context current failed\n"));
+      GDK_NOTE (OPENGL, g_print ("Making WGL context current failed\n"));
       return FALSE;
     }
 
@@ -1011,7 +1038,12 @@ gdk_win32_gl_context_end_frame_egl (GdkGLContext *context,
 static void
 gdk_win32_display_init_egl (GdkWin32Display *display_win32)
 {
-  EGLDisplay egl_disp = gdk_win32_get_egl_display (display_win32);
+  EGLDisplay egl_disp;
+
+  if (display_win32->gl_type == GDK_WIN32_GL_NONE)
+    GDK_NOTE (OPENGL, g_message ("Falling back to GLES..."));
+
+  egl_disp = gdk_win32_get_egl_display (display_win32);
 
   if (egl_disp == EGL_NO_DISPLAY ||
      !eglInitialize (egl_disp, NULL, NULL))
@@ -1195,6 +1227,9 @@ gdk_win32_gl_context_realize_egl (GdkGLContext  *context,
   gint major = 0;
   gint minor = 0;
 
+  /* we are using GLES, so set early so that we get the correct GLES versions to request */
+  gdk_gl_context_set_use_es (context, TRUE);
+
   gdk_gl_context_get_required_version (context, &major, &minor);
   debug_bit = gdk_gl_context_get_debug_enabled (context);
   compat_bit = gdk_gl_context_get_forward_compatible (context);
@@ -1230,9 +1265,6 @@ gdk_win32_gl_context_realize_egl (GdkGLContext  *context,
                      ctx));
 
   GDK_WIN32_GL_CONTEXT_EGL (context)->egl_context = ctx;
-  
-  /* set whether we are using GLES */
-  gdk_gl_context_set_use_es (context, TRUE);
 
   /* OpenGL does not work with WS_EX_LAYERED enabled, so we need to
    * disable WS_EX_LAYERED when we acquire a valid HGLRC
@@ -1328,7 +1360,15 @@ gdk_win32_gl_context_egl_init (GdkWin32GLContextEGL *egl_context)
 #else /* GDK_WIN32_ENABLE_EGL */
 /* define EGL stuff as no-op macros or functions if it is not enabled */
 
-#define gdk_win32_display_init_egl(disp) disp->gl_type = GDK_WIN32_GL_NONE
+static void
+gdk_win32_display_init_egl (GdkWin32Display *display_win32)
+{
+  GDK_NOTE (OPENGL, g_message ("Cannot %s GLES contexts: no GLES support",
+                               display_win32->gl_type == GDK_WIN32_GL_PENDING ?
+                               "create" : "fallback to"));
+  display_win32->gl_type = GDK_WIN32_GL_NONE;
+}
+
 #define gdk_win32_display_make_egl_context_current(disp,ctx) FALSE
 
 void
@@ -1396,6 +1436,7 @@ gdk_win32_window_invalidate_for_new_frame (GdkWindow      *window,
 
 static void
 gdk_win32_display_init_gl (GdkDisplay     *display,
+                           GdkGLContext   *share,
                            const gboolean  need_alpha_bits)
 {
   GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
@@ -1406,13 +1447,18 @@ gdk_win32_display_init_gl (GdkDisplay     *display,
       display_win32->gl_type == GDK_WIN32_GL_EGL)
     return;
 
+  /*
+   * We must disable WGL if we are using GDK_GL=gles or if the
+   * existing shared GLContext is a GLES context
+   */
   disable_wgl = ((_gdk_gl_flags & GDK_GL_GLES) != 0) ||
-                 display_win32->running_on_arm64;
+                (share != NULL && gdk_gl_context_get_use_es (share));
 
   if (!disable_wgl)
     gdk_win32_display_init_wgl (display_win32, need_alpha_bits);
 
-  else
+  if (display_win32->gl_type == GDK_WIN32_GL_PENDING ||
+      display_win32->gl_type == GDK_WIN32_GL_NONE)
     gdk_win32_display_init_egl (display_win32);
 }
 
@@ -1434,7 +1480,9 @@ gdk_win32_window_create_gl_context (GdkWindow *window,
 
   /* display_win32->hdc_egl_temp should *not* be destroyed here!  It is destroyed at dispose()! */
   display_win32->hdc_egl_temp = hdc;
-  gdk_win32_display_init_gl (display, need_alpha_bits);
+  gdk_win32_display_init_gl (display,
+                             share,
+                             need_alpha_bits);
 
   if (display_win32->gl_type == GDK_WIN32_GL_NONE)
     {
@@ -1515,7 +1563,7 @@ gdk_win32_display_get_wgl_version (GdkDisplay *display,
   display_win32 = GDK_WIN32_DISPLAY (display);
 
   if (display_win32->gl_type == GDK_WIN32_GL_PENDING)
-    gdk_win32_display_init_gl (display, FALSE);
+    gdk_win32_display_init_gl (display, NULL, FALSE);
 
   if (display_win32->gl_type == GDK_WIN32_GL_NONE)
     return FALSE;


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