mirror of https://github.com/encounter/SDL.git
[KMS/DRM] Enable async pageflips.
This commit is contained in:
parent
9384e59561
commit
aac74db685
|
@ -72,12 +72,6 @@ SDL_EGL_CreateContext_impl(KMSDRM)
|
|||
|
||||
int KMSDRM_GLES_SetSwapInterval(_THIS, int interval) {
|
||||
|
||||
/* Issuing a new pageflip before the previous has completed
|
||||
causes drmModePageFlip() to return EBUSY errors.
|
||||
So just set egl_swapinterval to 1 to prevent that. */
|
||||
|
||||
#if 0
|
||||
|
||||
if (!_this->egl_data) {
|
||||
return SDL_SetError("EGL not initialized");
|
||||
}
|
||||
|
@ -87,9 +81,6 @@ int KMSDRM_GLES_SetSwapInterval(_THIS, int interval) {
|
|||
} else {
|
||||
return SDL_SetError("Only swap intervals of 0 or 1 are supported");
|
||||
}
|
||||
#endif
|
||||
|
||||
_this->egl_data->egl_swapinterval = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -100,15 +91,15 @@ 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;
|
||||
int ret, timeout;
|
||||
int ret = 0;
|
||||
|
||||
/* Always wait for the previous issued flip before issing a new one,
|
||||
even if you do async flips. */
|
||||
uint32_t flip_flags = DRM_MODE_PAGE_FLIP_EVENT;
|
||||
|
||||
/* Wait for confirmation that the next front buffer has been flipped, at which
|
||||
point the previous front buffer can be released */
|
||||
timeout = 0;
|
||||
if (_this->egl_data->egl_swapinterval == 1) {
|
||||
timeout = -1;
|
||||
}
|
||||
if (!KMSDRM_WaitPageFlip(_this, windata, timeout)) {
|
||||
if (!KMSDRM_WaitPageFlip(_this, windata)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -162,16 +153,27 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) {
|
|||
}
|
||||
|
||||
/* Issue pageflip on the next front buffer.
|
||||
The pageflip will be done during the next vblank. */
|
||||
Remember: drmModePageFlip() never blocks, it just issues the flip,
|
||||
which will be done during the next vblank.
|
||||
Since it will return EBUSY if we call it again without having
|
||||
completed the last issued flip, we must pass the
|
||||
DRM_MODE_PAGE_FLIP_ASYNC if we don't block on EGL (egl_swapinterval = 0).
|
||||
That makes it flip immediately, without waiting for the next vblank,
|
||||
so even if we don't block on EGL, it will have flipped when we
|
||||
get back here. */
|
||||
|
||||
if (_this->egl_data->egl_swapinterval == 0) {
|
||||
flip_flags |= DRM_MODE_PAGE_FLIP_ASYNC;
|
||||
}
|
||||
|
||||
ret = KMSDRM_drmModePageFlip(viddata->drm_fd, dispdata->crtc->crtc_id,
|
||||
fb_info->fb_id, DRM_MODE_PAGE_FLIP_EVENT, &windata->waiting_for_flip);
|
||||
fb_info->fb_id, flip_flags, &windata->waiting_for_flip);
|
||||
|
||||
if (ret == 0) {
|
||||
if (_this->egl_data->egl_swapinterval == 1) {
|
||||
windata->waiting_for_flip = SDL_TRUE;
|
||||
}
|
||||
windata->waiting_for_flip = SDL_TRUE;
|
||||
} else {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not queue pageflip: %d", ret);
|
||||
printf("Could not queue pageflip: %s\n", strerror(errno));
|
||||
}
|
||||
|
||||
/* If we are in double-buffer mode, wait immediately for vsync
|
||||
|
@ -179,7 +181,7 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) {
|
|||
Run your SDL2 program with "SDL_KMSDRM_DOUBLE_BUFFER=1 <program_name>"
|
||||
to enable this. */
|
||||
if (_this->egl_data->egl_swapinterval == 1 && windata->double_buffer) {
|
||||
KMSDRM_WaitPageFlip(_this, windata, -1);
|
||||
KMSDRM_WaitPageFlip(_this, windata);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -339,11 +339,13 @@ KMSDRM_FlipHandler(int fd, unsigned int frame, unsigned int sec, unsigned int us
|
|||
}
|
||||
|
||||
SDL_bool
|
||||
KMSDRM_WaitPageFlip(_THIS, SDL_WindowData *windata, int timeout) {
|
||||
KMSDRM_WaitPageFlip(_THIS, SDL_WindowData *windata) {
|
||||
SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
|
||||
drmEventContext ev = {0};
|
||||
struct pollfd pfd = {0};
|
||||
|
||||
/* If the pageflip hasn't completed after 10 seconds, it nevel will. */
|
||||
uint32_t timeout = 10000;
|
||||
|
||||
ev.version = DRM_EVENT_CONTEXT_VERSION;
|
||||
ev.page_flip_handler = KMSDRM_FlipHandler;
|
||||
|
||||
|
@ -353,21 +355,25 @@ KMSDRM_WaitPageFlip(_THIS, SDL_WindowData *windata, int timeout) {
|
|||
while (windata->waiting_for_flip) {
|
||||
pfd.revents = 0;
|
||||
|
||||
/* poll() waits for events arriving on the FD, and returns < 0 if timeout
|
||||
passes with no events. */
|
||||
if (poll(&pfd, 1, timeout) < 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "DRM poll error");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (pfd.revents & (POLLHUP | POLLERR)) {
|
||||
/* An event arrived on the FD in time, but it's an error. */
|
||||
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "DRM poll hup or error");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (pfd.revents & POLLIN) {
|
||||
/* Page flip? If so, drmHandleEvent will unset windata->waiting_for_flip */
|
||||
/* There is data to read on the FD!
|
||||
Is the event a pageflip? If so, drmHandleEvent will
|
||||
unset windata->waiting_for_flip */
|
||||
KMSDRM_drmHandleEvent(viddata->drm_fd, &ev);
|
||||
} else {
|
||||
/* Timed out and page flip didn't happen */
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Dropping frame while waiting_for_flip");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
@ -650,7 +656,7 @@ KMSDRM_DestroySurfaces(_THIS, SDL_Window *window)
|
|||
/**********************************************/
|
||||
/* Wait for last issued pageflip to complete. */
|
||||
/**********************************************/
|
||||
KMSDRM_WaitPageFlip(_this, windata, -1);
|
||||
KMSDRM_WaitPageFlip(_this, windata);
|
||||
|
||||
/***********************************************************************/
|
||||
/* Restore the original CRTC configuration: configue the crtc with the */
|
||||
|
|
|
@ -114,7 +114,7 @@ typedef struct KMSDRM_FBInfo
|
|||
int KMSDRM_CreateSurfaces(_THIS, SDL_Window * window);
|
||||
KMSDRM_FBInfo *KMSDRM_FBFromBO(_THIS, struct gbm_bo *bo);
|
||||
KMSDRM_FBInfo *KMSDRM_FBFromBO2(_THIS, struct gbm_bo *bo, int w, int h);
|
||||
SDL_bool KMSDRM_WaitPageFlip(_THIS, SDL_WindowData *windata, int timeout);
|
||||
SDL_bool KMSDRM_WaitPageFlip(_THIS, SDL_WindowData *windata);
|
||||
|
||||
/****************************************************************************/
|
||||
/* SDL_VideoDevice functions declaration */
|
||||
|
|
Loading…
Reference in New Issue