Commit 86e95a607b5d375e4a80ad9eac7597924d8e1882

Brandon Schaefer 2017-08-02T17:45:15

kmsdrm: Fix tearing in neverputt/ball https://gfycat.com/FatalFarawayHeron

diff --git a/src/video/kmsdrm/SDL_kmsdrmopengles.c b/src/video/kmsdrm/SDL_kmsdrmopengles.c
index fb0c248..8da1963 100644
--- a/src/video/kmsdrm/SDL_kmsdrmopengles.c
+++ b/src/video/kmsdrm/SDL_kmsdrmopengles.c
@@ -73,10 +73,12 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) {
     }
 
     /* Release previously displayed buffer (which is now the backbuffer) and lock a new one */
-    if (wdata->locked_bo != NULL) {
-        KMSDRM_gbm_surface_release_buffer(wdata->gs, wdata->locked_bo);
-        /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Released GBM surface %p", (void *)wdata->locked_bo); */
-        wdata->locked_bo = NULL;
+    if (wdata->next_bo != NULL) {
+        KMSDRM_gbm_surface_release_buffer(wdata->gs, wdata->current_bo);
+        /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Released GBM surface %p", (void *)wdata->next_bo); */
+
+        wdata->current_bo = wdata->next_bo;
+        wdata->next_bo = NULL;
     }
 
     if (!(_this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, wdata->egl_surface))) {
@@ -84,15 +86,22 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) {
         return 0;
     }
 
-    wdata->locked_bo = KMSDRM_gbm_surface_lock_front_buffer(wdata->gs);
-    if (wdata->locked_bo == NULL) {
+    if (wdata->current_bo == NULL) {
+        wdata->current_bo = KMSDRM_gbm_surface_lock_front_buffer(wdata->gs);
+        if (wdata->current_bo == NULL) {
+            return 0;
+        }
+    }
+
+    wdata->next_bo = KMSDRM_gbm_surface_lock_front_buffer(wdata->gs);
+    if (wdata->next_bo == NULL) {
         SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not lock GBM surface front buffer");
         return 0;
     /* } else {
-        SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Locked GBM surface %p", (void *)wdata->locked_bo); */
+        SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Locked GBM surface %p", (void *)wdata->next_bo); */
     }
 
-    fb_info = KMSDRM_FBFromBO(_this, wdata->locked_bo);
+    fb_info = KMSDRM_FBFromBO(_this, wdata->next_bo);
     if (_this->egl_data->egl_swapinterval == 0) {
         /* Swap buffers instantly, possible tearing */
         /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "drmModeSetCrtc(%d, %u, %u, 0, 0, &%u, 1, &%ux%u@%u)",
diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c
index bb16837..637fe8c 100644
--- a/src/video/kmsdrm/SDL_kmsdrmvideo.c
+++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c
@@ -542,9 +542,13 @@ KMSDRM_DestroyWindow(_THIS, SDL_Window * window)
     if(data) {
         /* Wait for any pending page flips and unlock buffer */
         KMSDRM_WaitPageFlip(_this, data, -1);
-        if (data->locked_bo != NULL) {
-            KMSDRM_gbm_surface_release_buffer(data->gs, data->locked_bo);
-            data->locked_bo = NULL;
+        if (data->next_bo != NULL) {
+            KMSDRM_gbm_surface_release_buffer(data->gs, data->next_bo);
+            data->next_bo = NULL;
+        }
+        if (data->current_bo != NULL) {
+            KMSDRM_gbm_surface_release_buffer(data->gs, data->current_bo);
+            data->current_bo = NULL;
         }
 #if SDL_VIDEO_OPENGL_EGL
         SDL_EGL_MakeCurrent(_this, EGL_NO_SURFACE, EGL_NO_CONTEXT);
diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.h b/src/video/kmsdrm/SDL_kmsdrmvideo.h
index bc44e1a..39eb8ab 100644
--- a/src/video/kmsdrm/SDL_kmsdrmvideo.h
+++ b/src/video/kmsdrm/SDL_kmsdrmvideo.h
@@ -58,7 +58,8 @@ typedef struct SDL_DisplayData
 typedef struct SDL_WindowData
 {
     struct gbm_surface *gs;
-    struct gbm_bo *locked_bo;
+    struct gbm_bo *current_bo;
+    struct gbm_bo *next_bo;
     SDL_bool waiting_for_flip;
 #if SDL_VIDEO_OPENGL_EGL
     EGLSurface egl_surface;