kmsdrm: wait for possible pending atomic commits before destroying surfaces, and before restoring video on quit. Move messages to the SDL_Log* functions.

This commit is contained in:
Manuel Alfayate Corchete 2020-08-07 11:53:04 +02:00
parent 96c99693a2
commit 3b9f1073c6
2 changed files with 34 additions and 26 deletions

View File

@ -121,13 +121,11 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window)
be chosen by EGL as back buffer to draw on), and get a handle to it to request the pageflip on it. */
windata->next_bo = KMSDRM_gbm_surface_lock_front_buffer(windata->gs);
if (!windata->next_bo) {
printf("Failed to lock frontbuffer\n");
return -1;
return SDL_SetError("Failed to lock frontbuffer");
}
fb = KMSDRM_FBFromBO(_this, windata->next_bo);
if (!fb) {
printf("Failed to get a new framebuffer BO\n");
return -1;
return SDL_SetError("Failed to get a new framebuffer BO");
}
/* Don't issue another atomic ioctl until previous one has completed: it will cause errors. */
@ -139,13 +137,13 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window)
} while (status != EGL_CONDITION_SATISFIED_KHR);
_this->egl_data->eglDestroySyncKHR(_this->egl_data->egl_display, dispdata->kms_fence);
dispdata->kms_fence = NULL;
}
/* Issue atomic commit, where we request the pageflip. */
ret = drm_atomic_commit(_this, fb->fb_id, flags);
if (ret) {
printf("failed to do atomic commit\n");
return -1;
return SDL_SetError("failed to issue atomic commit");
}
/* Release the last front buffer so EGL can chose it as back buffer and render on it again. */
@ -206,20 +204,17 @@ KMSDRM_GLES_SwapWindowDB(_THIS, SDL_Window * window)
be chosen by EGL as back buffer to draw on), and get a handle to it to request the pageflip on it. */
windata->next_bo = KMSDRM_gbm_surface_lock_front_buffer(windata->gs);
if (!windata->next_bo) {
printf("Failed to lock frontbuffer\n");
return -1;
return SDL_SetError("Failed to lock frontbuffer");
}
fb = KMSDRM_FBFromBO(_this, windata->next_bo);
if (!fb) {
printf("Failed to get a new framebuffer BO\n");
return -1;
return SDL_SetError("Failed to get a new framebuffer BO");
}
/* Issue atomic commit, where we request the pageflip. */
ret = drm_atomic_commit(_this, fb->fb_id, flags);
if (ret) {
printf("failed to do atomic commit\n");
return -1;
return SDL_SetError("failed to do atomic commit");
}
/* Release last front buffer so EGL can chose it as back buffer and render on it again. */

View File

@ -462,12 +462,30 @@ out:
return ret;
}
void
wait_pending_atomic(_THIS)
{
SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
/* Will return immediately if we have already destroyed the fence, because we NULL-ify it just after.
Also, will return immediately in double-buffer mode, because kms_fence will alsawys be NULL. */
if (dispdata->kms_fence) {
EGLint status;
do {
status = _this->egl_data->eglClientWaitSyncKHR(_this->egl_data->egl_display,
dispdata->kms_fence, 0, EGL_FOREVER_KHR);
} while (status != EGL_CONDITION_SATISFIED_KHR);
_this->egl_data->eglDestroySyncKHR(_this->egl_data->egl_display, dispdata->kms_fence);
dispdata->kms_fence = NULL;
}
}
/***************************************/
/* End of Atomic helper functions block*/
/***************************************/
static int
KMSDRM_Available(void)
{
@ -657,6 +675,9 @@ KMSDRM_DestroySurfaces(_THIS, SDL_Window * window)
{
SDL_WindowData *windata = (SDL_WindowData *)window->driverdata;
/* Wait for pending atomic commit (like pageflips requested in SwapWindow) to complete. */
wait_pending_atomic(_this);
if (windata->bo) {
KMSDRM_gbm_surface_release_buffer(windata->gs, windata->bo);
windata->bo = NULL;
@ -1073,21 +1094,13 @@ KMSDRM_VideoQuit(_THIS)
/* Atomic block for video mode and crt->buffer restoration */
/***********************************************************/
/* It could happen that we will get here after an async atomic commit (as it's in triple buffer
SwapWindow()) and we don't want to issue another atomic commit before previous one is completed. */
if (dispdata->kms_fence) {
EGLint status;
do {
status = _this->egl_data->eglClientWaitSyncKHR(_this->egl_data->egl_display,
dispdata->kms_fence, 0, EGL_FOREVER_KHR);
} while (status != EGL_CONDITION_SATISFIED_KHR);
_this->egl_data->eglDestroySyncKHR(_this->egl_data->egl_display, dispdata->kms_fence);
}
/* We could get here after an async atomic commit (as it's in triple buffer SwapWindow())
and we don't want to issue another atomic commit before previous one is completed. */
wait_pending_atomic(_this);
/* Issue sync/blocking atomic commit that restores original video mode and points crtc to original buffer. */
ret = drm_atomic_commit(_this, dispdata->crtc->buffer_id, flags);
/*********************/
/* Atomic block ends */
/*********************/