Commit b6a818b6a286c5ec7a1b695c56e38a5a6bbde4ca

Manuel Alfayate Corchete 2020-07-19T18:45:29

Fix SDL_Window recreation: drmModeSetCrtc() has to be called everytime the EGL and GBM surfaces are recreated.

diff --git a/src/video/kmsdrm/SDL_kmsdrmopengles.c b/src/video/kmsdrm/SDL_kmsdrmopengles.c
index 355d57b..dcc8d47 100644
--- a/src/video/kmsdrm/SDL_kmsdrmopengles.c
+++ b/src/video/kmsdrm/SDL_kmsdrmopengles.c
@@ -61,7 +61,6 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) {
     SDL_DisplayData *dispdata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
     SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
     KMSDRM_FBInfo *fb_info;
-    SDL_bool crtc_setup_pending = SDL_FALSE;
 
     /* ALWAYS wait for each pageflip to complete before issuing another, vsync or not,
        or drmModePageFlip() will start returning EBUSY if there are pending pageflips.
@@ -79,8 +78,6 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) {
     /* Recreate the GBM / EGL surfaces if the display mode has changed */
     if (windata->egl_surface_dirty) {
         KMSDRM_CreateSurfaces(_this, window);
-        /* Do this later, when a fb_id is obtained. */
-        crtc_setup_pending = SDL_TRUE;
     }
 
     if (windata->double_buffer) {
@@ -121,12 +118,12 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) {
         }
 
         /* When needed, this is done once we have the needed fb_id, not before. */
-        if (crtc_setup_pending) {
+        if (windata->crtc_setup_pending) {
 	    if (KMSDRM_drmModeSetCrtc(viddata->drm_fd, dispdata->crtc_id, fb_info->fb_id, 0,
 					0, &dispdata->conn->connector_id, 1, &dispdata->mode)) {
 		SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not configure CRTC on video mode setting.");
 	    }
-            crtc_setup_pending = SDL_FALSE;
+            windata->crtc_setup_pending = SDL_FALSE;
         }
 
         if (!KMSDRM_drmModePageFlip(viddata->drm_fd, dispdata->crtc_id, fb_info->fb_id,
@@ -210,12 +207,12 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) {
         }
 
         /* When needed, this is done once we have the needed fb_id, not before. */
-        if (crtc_setup_pending) {
+        if (windata->crtc_setup_pending) {
 	    if (KMSDRM_drmModeSetCrtc(viddata->drm_fd, dispdata->crtc_id, fb_info->fb_id, 0,
 					0, &dispdata->conn->connector_id, 1, &dispdata->mode)) {
 		SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not configure CRTC on video mode setting.");
 	    }
-            crtc_setup_pending = SDL_FALSE;
+            windata->crtc_setup_pending = SDL_FALSE;
         }
 
 
diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c
index 387d95e..02092aa 100644
--- a/src/video/kmsdrm/SDL_kmsdrmvideo.c
+++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c
@@ -433,9 +433,13 @@ KMSDRM_CreateSurfaces(_THIS, SDL_Window * window)
 
     SDL_EGL_MakeCurrent(_this, windata->egl_surface, egl_context);
 
-    windata->egl_surface_dirty = 0;
+    windata->egl_surface_dirty = SDL_FALSE;
 #endif
 
+    /* We can't call KMSDRM_SetCRTC() until we have a fb_id, in KMSDRM_GLES_SwapWindow().
+       So we take note here to do it there. */
+    windata->crtc_setup_pending = SDL_TRUE;
+
     return 0;
 }
 
@@ -757,7 +761,7 @@ KMSDRM_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
 #if SDL_VIDEO_OPENGL_EGL
         /* Can't recreate EGL surfaces right now, need to wait until SwapWindow
            so the correct thread-local surface and context state are available */
-        windata->egl_surface_dirty = 1;
+        windata->egl_surface_dirty = SDL_TRUE;
 #else
         if (KMSDRM_CreateSurfaces(_this, window)) {
             return -1;
@@ -793,9 +797,13 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window)
         goto error;
     }
 
-    /* In case low-latency is wanted, double-buffered video will be used. We take note here */
-    windata->double_buffer = SDL_FALSE;
+    /* Init windata fields. */
+    windata->waiting_for_flip   = SDL_FALSE;
+    windata->double_buffer      = SDL_FALSE;
+    windata->crtc_setup_pending = SDL_FALSE;
+    windata->egl_surface_dirty  = SDL_FALSE;
 
+    /* In case low-latency is wanted, double-buffered video will be used. We take note here */
     if (SDL_GetHintBoolean(SDL_HINT_VIDEO_DOUBLE_BUFFER, SDL_FALSE)) {
         windata->double_buffer = SDL_TRUE;
     }
diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.h b/src/video/kmsdrm/SDL_kmsdrmvideo.h
index 63dcf6f..df6133e 100644
--- a/src/video/kmsdrm/SDL_kmsdrmvideo.h
+++ b/src/video/kmsdrm/SDL_kmsdrmvideo.h
@@ -71,8 +71,9 @@ typedef struct SDL_WindowData
     struct gbm_bo *crtc_bo;
     SDL_bool waiting_for_flip;
     SDL_bool double_buffer;
+    SDL_bool crtc_setup_pending;
 #if SDL_VIDEO_OPENGL_EGL
-    int egl_surface_dirty;
+    SDL_bool egl_surface_dirty;
     EGLSurface egl_surface;
 #endif
 } SDL_WindowData;