kmsdrm: wait for possible pending atomic commits before destroying surfaces, and before restoring video on quit. Move messages to the SDL_Log* functions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
diff --git a/src/video/kmsdrm/SDL_kmsdrmopengles.c b/src/video/kmsdrm/SDL_kmsdrmopengles.c
index 2b54b49..f5f93be 100644
--- a/src/video/kmsdrm/SDL_kmsdrmopengles.c
+++ b/src/video/kmsdrm/SDL_kmsdrmopengles.c
@@ -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. */
diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c
index debc186..76c037e 100644
--- a/src/video/kmsdrm/SDL_kmsdrmvideo.c
+++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c
@@ -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 */
/*********************/