Commit 3c6004feb79b2b24c6ace7809b2f205d79c64c7e

Ryan C. Gordon 2020-09-10T15:07:23

kmsdrm: Choose how to swap buffers based on EGL extension availability.

diff --git a/src/video/kmsdrm/SDL_kmsdrmopengles.c b/src/video/kmsdrm/SDL_kmsdrmopengles.c
index af55f50..5eaa11b 100644
--- a/src/video/kmsdrm/SDL_kmsdrmopengles.c
+++ b/src/video/kmsdrm/SDL_kmsdrmopengles.c
@@ -27,6 +27,7 @@
 #include "SDL_kmsdrmvideo.h"
 #include "SDL_kmsdrmopengles.h"
 #include "SDL_kmsdrmdyn.h"
+#include "SDL_hints.h"
 
 #ifndef EGL_PLATFORM_GBM_MESA
 #define EGL_PLATFORM_GBM_MESA 0x31D7
@@ -99,30 +100,18 @@ static EGLSyncKHR create_fence(int fd, _THIS)
 	return fence;
 }
 
-int
-KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window)
+static int
+KMSDRM_GLES_SwapWindowFenced(_THIS, SDL_Window * window)
 {
     SDL_WindowData *windata = ((SDL_WindowData *) window->driverdata);
     SDL_DisplayData *dispdata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
     KMSDRM_FBInfo *fb;
     KMSDRM_PlaneInfo info = {0};
 
-    /* Get the EGL context, now that SDL_CreateRenderer() has already been called,
-       and call eglMakeCurrent() on it and the EGL surface. */
-#if SDL_VIDEO_OPENGL_EGL
-    if (windata->egl_context_pending) {
-        EGLContext egl_context;
-        egl_context = (EGLContext)SDL_GL_GetCurrentContext();
-        SDL_EGL_MakeCurrent(_this, windata->egl_surface, egl_context);
-        windata->egl_context_pending = SDL_FALSE;
-    }   
-#endif
-
     /*************************************************************************/
     /* Block for telling KMS to wait for GPU rendering of the current frame  */
     /* before applying the KMS changes requested in the atomic ioctl.        */
     /*************************************************************************/
-
     /* Create the fence that will be inserted in the cmdstream exactly at the end
        of the gl commands that form a frame. KMS will have to wait on it before doing a pageflip. */
     dispdata->gpu_fence = create_fence(EGL_NO_NATIVE_FENCE_FD_ANDROID, _this);
@@ -222,25 +211,14 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window)
     return 0;
 }
 
-int
-KMSDRM_GLES_SwapWindowDB(_THIS, SDL_Window * window)
+static int
+KMSDRM_GLES_SwapWindowDoubleBuffered(_THIS, SDL_Window * window)
 {
     SDL_WindowData *windata = ((SDL_WindowData *) window->driverdata);
     SDL_DisplayData *dispdata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
     KMSDRM_FBInfo *fb;
     KMSDRM_PlaneInfo info = {0};
 
-    /* Get the EGL context, now that SDL_CreateRenderer() has already been called,
-       and call eglMakeCurrent() on it and the EGL surface. */
-#if SDL_VIDEO_OPENGL_EGL
-    if (windata->egl_context_pending) {
-        EGLContext egl_context;
-        egl_context = (EGLContext)SDL_GL_GetCurrentContext();
-        SDL_EGL_MakeCurrent(_this, windata->egl_surface, egl_context);
-        windata->egl_context_pending = SDL_FALSE;
-    }   
-#endif
-
     /****************************************************************************************************/
     /* In double-buffer mode, atomic commit will always be synchronous/blocking (ie: won't return until */
     /* the requested changes are really done).                                                          */
@@ -306,6 +284,34 @@ KMSDRM_GLES_SwapWindowDB(_THIS, SDL_Window * window)
     return 0;
 }
 
+int
+KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window)
+{
+    SDL_WindowData *windata = ((SDL_WindowData *) window->driverdata);
+
+     /* Get the EGL context, now that SDL_CreateRenderer() has already been called,
+       and call eglMakeCurrent() on it and the EGL surface. */
+#if SDL_VIDEO_OPENGL_EGL
+    if (windata->egl_context_pending) {
+        EGLContext egl_context = (EGLContext)SDL_GL_GetCurrentContext();
+        SDL_EGL_MakeCurrent(_this, windata->egl_surface, egl_context);
+        windata->egl_context_pending = SDL_FALSE;
+    }
+#endif
+
+    if (windata->swap_window == NULL) {
+        /* We want the fenced version by default, but it needs extensions. */
+        if ( (SDL_GetHintBoolean(SDL_HINT_VIDEO_DOUBLE_BUFFER, SDL_FALSE)) ||
+             (!SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_ANDROID_native_fence_sync")) ) {
+            windata->swap_window = KMSDRM_GLES_SwapWindowDoubleBuffered;
+        } else {
+            windata->swap_window = KMSDRM_GLES_SwapWindowFenced;
+        }
+    }
+
+    return windata->swap_window(_this, window);
+}
+
 
 /***************************************/
 /* End of Atomic functions block       */
diff --git a/src/video/kmsdrm/SDL_kmsdrmopengles.h b/src/video/kmsdrm/SDL_kmsdrmopengles.h
index 0d944ee..2718f96 100644
--- a/src/video/kmsdrm/SDL_kmsdrmopengles.h
+++ b/src/video/kmsdrm/SDL_kmsdrmopengles.h
@@ -41,7 +41,6 @@ extern int KMSDRM_GLES_SetSwapInterval(_THIS, int interval);
 extern int KMSDRM_GLES_LoadLibrary(_THIS, const char *path);
 extern SDL_GLContext KMSDRM_GLES_CreateContext(_THIS, SDL_Window * window);
 extern int KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window);
-extern int KMSDRM_GLES_SwapWindowDB(_THIS, SDL_Window * window);
 extern int KMSDRM_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
 
 #endif /* SDL_VIDEO_DRIVER_KMSDRM && SDL_VIDEO_OPENGL_EGL */
diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c
index 9c05927..0fe093b 100644
--- a/src/video/kmsdrm/SDL_kmsdrmvideo.c
+++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c
@@ -27,7 +27,6 @@
 /* SDL internals */
 #include "../SDL_sysvideo.h"
 #include "SDL_syswm.h"
-#include "SDL_hints.h"
 #include "../../events/SDL_events_c.h"
 #include "../../events/SDL_mouse_c.h"
 #include "../../events/SDL_keyboard_c.h"
@@ -50,7 +49,6 @@
 #define KMSDRM_DRI_PATH "/dev/dri/"
 
 #define AMDGPU_COMPAT 1
-#define RPI4_COMPAT 0
 
 static int
 check_modesetting(int devindex)
@@ -792,16 +790,7 @@ KMSDRM_CreateDevice(int devindex)
     device->GL_MakeCurrent = KMSDRM_GLES_MakeCurrent;
     device->GL_SetSwapInterval = KMSDRM_GLES_SetSwapInterval;
     device->GL_GetSwapInterval = KMSDRM_GLES_GetSwapInterval;
-
-#if RPI4_COMPAT
-    device->GL_SwapWindow = KMSDRM_GLES_SwapWindowDB;
-#else
-    if (SDL_GetHintBoolean(SDL_HINT_VIDEO_DOUBLE_BUFFER, SDL_FALSE))
-        device->GL_SwapWindow = KMSDRM_GLES_SwapWindowDB;
-    else
-        device->GL_SwapWindow = KMSDRM_GLES_SwapWindow;
-#endif
-    
+    device->GL_SwapWindow = KMSDRM_GLES_SwapWindow;
     device->GL_DeleteContext = KMSDRM_GLES_DeleteContext;
 #endif
     device->PumpEvents = KMSDRM_PumpEvents;
diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.h b/src/video/kmsdrm/SDL_kmsdrmvideo.h
index 535ee6e..8a36778 100644
--- a/src/video/kmsdrm/SDL_kmsdrmvideo.h
+++ b/src/video/kmsdrm/SDL_kmsdrmvideo.h
@@ -171,6 +171,8 @@ typedef struct SDL_WindowData
        the EGL context is available, but we need the EGL surface sooner. */
     SDL_bool egl_context_pending;
 
+    /* This dictates what approach we'll use for SwapBuffers. */
+    int (*swap_window)(_THIS, SDL_Window * window);
 } SDL_WindowData;
 
 typedef struct SDL_DisplayModeData