diff --git a/src/video/kmsdrm/SDL_kmsdrmopengles.c b/src/video/kmsdrm/SDL_kmsdrmopengles.c index 2b54b496a..f5f93be47 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 debc18666..76c037eff 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 */ /*********************/