SDL: Fixed KMSDRM window creation failing if OpenGL libraries are not available, but GLES 2.0 libraries are

From ff99e56d3af276f8fa199d57a64cc863d9c9f798 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Fri, 18 Nov 2022 12:54:55 -0800
Subject: [PATCH] Fixed KMSDRM window creation failing if OpenGL libraries are
 not available, but GLES 2.0 libraries are

---
 src/video/SDL_egl.c                | 33 ++++++++++++++++--------
 src/video/kmsdrm/SDL_kmsdrmvideo.c | 40 +++++++++++++++++-------------
 2 files changed, 45 insertions(+), 28 deletions(-)

diff --git a/src/video/SDL_egl.c b/src/video/SDL_egl.c
index 2438faf00a71..41ae6ec01649 100644
--- a/src/video/SDL_egl.c
+++ b/src/video/SDL_egl.c
@@ -292,8 +292,8 @@ SDL_EGL_UnloadLibrary(_THIS)
     }
 }
 
-int
-SDL_EGL_LoadLibraryOnly(_THIS, const char *egl_path)
+static int
+SDL_EGL_LoadLibraryInternal(_THIS, const char *egl_path)
 {
     void *egl_dll_handle = NULL, *opengl_dll_handle = NULL;
     const char *path = NULL;
@@ -304,15 +304,6 @@ SDL_EGL_LoadLibraryOnly(_THIS, const char *egl_path)
     SDL_bool vc4 = (0 == access("/sys/module/vc4/", F_OK));
 #endif
 
-    if (_this->egl_data) {
-        return SDL_SetError("EGL context already created");
-    }
-
-    _this->egl_data = (struct SDL_EGL_VideoData *) SDL_calloc(1, sizeof(SDL_EGL_VideoData));
-    if (!_this->egl_data) {
-        return SDL_OutOfMemory();
-    }
-
 #if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT
     d3dcompiler = SDL_GetHint(SDL_HINT_VIDEO_WIN_D3DCOMPILER);
     if (d3dcompiler) {
@@ -473,6 +464,26 @@ SDL_EGL_LoadLibraryOnly(_THIS, const char *egl_path)
     return 0;
 }
 
+int
+SDL_EGL_LoadLibraryOnly(_THIS, const char *egl_path)
+{
+    if (_this->egl_data) {
+        return SDL_SetError("EGL context already created");
+    }
+
+    _this->egl_data = (struct SDL_EGL_VideoData *) SDL_calloc(1, sizeof(SDL_EGL_VideoData));
+    if (!_this->egl_data) {
+        return SDL_OutOfMemory();
+    }
+
+    if (SDL_EGL_LoadLibraryInternal(_this, egl_path) < 0) {
+        SDL_free(_this->egl_data);
+        _this->egl_data = NULL;
+        return -1;
+    }
+    return 0;
+}
+
 static void
 SDL_EGL_GetVersion(_THIS) {
     if (_this->egl_data->eglQueryString) {
diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c
index eeeefef2b2c1..6c05bbd9bfd3 100644
--- a/src/video/kmsdrm/SDL_kmsdrmvideo.c
+++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c
@@ -1456,28 +1456,34 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window)
             }
         }
 
-	/* Manually load the GL library. KMSDRM_EGL_LoadLibrary() has already
-	   been called by SDL_CreateWindow() but we don't do anything there,
-	   out KMSDRM_EGL_LoadLibrary() is a dummy precisely to be able to load it here.
-	   If we let SDL_CreateWindow() load the lib, it would be loaded
-	   before we call KMSDRM_GBMInit(), causing all GLES programs to fail. */
-	if (!_this->egl_data) {
-	    egl_display = (NativeDisplayType)((SDL_VideoData *)_this->driverdata)->gbm_dev;
-	    if (SDL_EGL_LoadLibrary(_this, NULL, egl_display, EGL_PLATFORM_GBM_MESA)) {
-                return (SDL_SetError("Can't load EGL/GL library on window creation."));
-	    }
+        /* Manually load the GL library. KMSDRM_EGL_LoadLibrary() has already
+           been called by SDL_CreateWindow() but we don't do anything there,
+           our KMSDRM_EGL_LoadLibrary() is a dummy precisely to be able to load it here.
+           If we let SDL_CreateWindow() load the lib, it would be loaded
+           before we call KMSDRM_GBMInit(), causing all GLES programs to fail. */
+        if (!_this->egl_data) {
+            egl_display = (NativeDisplayType)((SDL_VideoData *)_this->driverdata)->gbm_dev;
+            if (SDL_EGL_LoadLibrary(_this, NULL, egl_display, EGL_PLATFORM_GBM_MESA) < 0) {
+                /* Try again with OpenGL ES 2.0 */
+                _this->gl_config.profile_mask = SDL_GL_CONTEXT_PROFILE_ES;
+                _this->gl_config.major_version = 2;
+                _this->gl_config.minor_version = 0;
+                if (SDL_EGL_LoadLibrary(_this, NULL, egl_display, EGL_PLATFORM_GBM_MESA) < 0) {
+                    return (SDL_SetError("Can't load EGL/GL library on window creation."));
+                }
+            }
 
-	    _this->gl_config.driver_loaded = 1;
+            _this->gl_config.driver_loaded = 1;
 
-	}
+        }
 
-	/* Create the cursor BO for the display of this window,
-	   now that we know this is not a VK window. */
-	KMSDRM_CreateCursorBO(display);
+        /* Create the cursor BO for the display of this window,
+           now that we know this is not a VK window. */
+        KMSDRM_CreateCursorBO(display);
 
-	/* Create and set the default cursor for the display
+        /* Create and set the default cursor for the display
            of this window, now that we know this is not a VK window. */
-	KMSDRM_InitMouse(_this, display);
+        KMSDRM_InitMouse(_this, display);
 
         /* The FULLSCREEN flags are cut out from window->flags at this point,
            so we can't know if a window is fullscreen or not, hence all windows