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

This commit is contained in:
Manuel Alfayate Corchete 2020-07-19 18:45:29 +02:00
parent 71e9df99c7
commit b6a818b6a2
3 changed files with 18 additions and 12 deletions

View file

@ -61,7 +61,6 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) {
SDL_DisplayData *dispdata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata; SDL_DisplayData *dispdata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata); SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
KMSDRM_FBInfo *fb_info; KMSDRM_FBInfo *fb_info;
SDL_bool crtc_setup_pending = SDL_FALSE;
/* ALWAYS wait for each pageflip to complete before issuing another, vsync or not, /* ALWAYS wait for each pageflip to complete before issuing another, vsync or not,
or drmModePageFlip() will start returning EBUSY if there are pending pageflips. 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 */ /* Recreate the GBM / EGL surfaces if the display mode has changed */
if (windata->egl_surface_dirty) { if (windata->egl_surface_dirty) {
KMSDRM_CreateSurfaces(_this, window); KMSDRM_CreateSurfaces(_this, window);
/* Do this later, when a fb_id is obtained. */
crtc_setup_pending = SDL_TRUE;
} }
if (windata->double_buffer) { 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. */ /* 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, if (KMSDRM_drmModeSetCrtc(viddata->drm_fd, dispdata->crtc_id, fb_info->fb_id, 0,
0, &dispdata->conn->connector_id, 1, &dispdata->mode)) { 0, &dispdata->conn->connector_id, 1, &dispdata->mode)) {
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not configure CRTC on video mode setting."); 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, 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. */ /* 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, if (KMSDRM_drmModeSetCrtc(viddata->drm_fd, dispdata->crtc_id, fb_info->fb_id, 0,
0, &dispdata->conn->connector_id, 1, &dispdata->mode)) { 0, &dispdata->conn->connector_id, 1, &dispdata->mode)) {
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not configure CRTC on video mode setting."); 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;
} }

View file

@ -433,9 +433,13 @@ KMSDRM_CreateSurfaces(_THIS, SDL_Window * window)
SDL_EGL_MakeCurrent(_this, windata->egl_surface, egl_context); SDL_EGL_MakeCurrent(_this, windata->egl_surface, egl_context);
windata->egl_surface_dirty = 0; windata->egl_surface_dirty = SDL_FALSE;
#endif #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; return 0;
} }
@ -757,7 +761,7 @@ KMSDRM_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
#if SDL_VIDEO_OPENGL_EGL #if SDL_VIDEO_OPENGL_EGL
/* Can't recreate EGL surfaces right now, need to wait until SwapWindow /* Can't recreate EGL surfaces right now, need to wait until SwapWindow
so the correct thread-local surface and context state are available */ so the correct thread-local surface and context state are available */
windata->egl_surface_dirty = 1; windata->egl_surface_dirty = SDL_TRUE;
#else #else
if (KMSDRM_CreateSurfaces(_this, window)) { if (KMSDRM_CreateSurfaces(_this, window)) {
return -1; return -1;
@ -793,9 +797,13 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window)
goto error; goto error;
} }
/* In case low-latency is wanted, double-buffered video will be used. We take note here */ /* Init windata fields. */
windata->double_buffer = SDL_FALSE; 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)) { if (SDL_GetHintBoolean(SDL_HINT_VIDEO_DOUBLE_BUFFER, SDL_FALSE)) {
windata->double_buffer = SDL_TRUE; windata->double_buffer = SDL_TRUE;
} }

View file

@ -71,8 +71,9 @@ typedef struct SDL_WindowData
struct gbm_bo *crtc_bo; struct gbm_bo *crtc_bo;
SDL_bool waiting_for_flip; SDL_bool waiting_for_flip;
SDL_bool double_buffer; SDL_bool double_buffer;
SDL_bool crtc_setup_pending;
#if SDL_VIDEO_OPENGL_EGL #if SDL_VIDEO_OPENGL_EGL
int egl_surface_dirty; SDL_bool egl_surface_dirty;
EGLSurface egl_surface; EGLSurface egl_surface;
#endif #endif
} SDL_WindowData; } SDL_WindowData;