Browse Source

egl: Better attempt at retrying surface creation w/o EGL_EXT_present_opaque.

Fixes #13094.
Ryan C. Gordon 3 days ago
parent
commit
808a3f573f
1 changed files with 15 additions and 12 deletions
  1. 15 12
      src/video/SDL_egl.c

+ 15 - 12
src/video/SDL_egl.c

@@ -1250,12 +1250,9 @@ EGLSurface SDL_EGL_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, Nat
     // max 16 key+value pairs, plus terminator.
     EGLint attribs[33];
     int attr = 0;
-    bool use_opaque_ext;
-    
+
     EGLSurface surface;
 
-    use_opaque_ext = true;
-try:
     if (!SDL_EGL_ChooseConfig(_this)) {
         return EGL_NO_SURFACE;
     }
@@ -1284,8 +1281,11 @@ try:
         }
     }
 
+    int opaque_ext_idx = -1;
+
 #ifdef EGL_EXT_present_opaque
-    if (SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_EXT_present_opaque") && use_opaque_ext) {
+    if (SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_EXT_present_opaque")) {
+        opaque_ext_idx = attr;
         bool allow_transparent = false;
         if (window && (window->flags & SDL_WINDOW_TRANSPARENT)) {
             allow_transparent = true;
@@ -1321,15 +1321,18 @@ try:
 
     attribs[attr++] = EGL_NONE;
 
-    surface = _this->egl_data->eglCreateWindowSurface(
-        _this->egl_data->egl_display,
-        _this->egl_data->egl_config,
-        nw, &attribs[0]);
+    surface = _this->egl_data->eglCreateWindowSurface(_this->egl_data->egl_display, _this->egl_data->egl_config, nw, &attribs[0]);
     if (surface == EGL_NO_SURFACE) {
-        if (_this->egl_data->eglGetError() == EGL_BAD_ATTRIBUTE && use_opaque_ext) {
-            use_opaque_ext = false;
-            goto try;    
+        // we had a report of Nvidia drivers that report EGL_BAD_ATTRIBUTE if you try to
+        //  use EGL_PRESENT_OPAQUE_EXT, even when EGL_EXT_present_opaque is reported as available.
+        //  If we used it, try a second time without this attribute.
+        if ((_this->egl_data->eglGetError() == EGL_BAD_ATTRIBUTE) && (opaque_ext_idx >= 0)) {
+            SDL_memmove(&attribs[opaque_ext_idx], &attribs[opaque_ext_idx + 2], sizeof (attribs[0]) * ((attr - opaque_ext_idx) - 2));
+            surface = _this->egl_data->eglCreateWindowSurface(_this->egl_data->egl_display, _this->egl_data->egl_config, nw, &attribs[0]);
         }
+    }
+
+    if (surface == EGL_NO_SURFACE) {
         SDL_EGL_SetError("unable to create an EGL window surface", "eglCreateWindowSurface");
     }