mirror of
https://github.com/Relintai/sdl2_frt.git
synced 2024-12-20 22:16:49 +01:00
[KMS/DRM] Small fix to KMSDRM_Waitpageflip(). More comments on how it works.
This commit is contained in:
parent
bdb3e6b84f
commit
03665004d0
@ -99,7 +99,7 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) {
|
|||||||
|
|
||||||
/* Wait for confirmation that the next front buffer has been flipped, at which
|
/* Wait for confirmation that the next front buffer has been flipped, at which
|
||||||
point the previous front buffer can be released */
|
point the previous front buffer can be released */
|
||||||
if (!KMSDRM_WaitPageFlip(_this, windata)) {
|
if (!KMSDRM_WaitPageflip(_this, windata)) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Wait for previous pageflip failed");
|
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Wait for previous pageflip failed");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -182,16 +182,16 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Wait immediately for vsync (as if we only had two buffers).
|
/* Wait immediately for vsync (as if we only had two buffers).
|
||||||
Even if we are already doing a WaitPageFlip at the begining of this
|
Even if we are already doing a WaitPageflip at the begining of this
|
||||||
function, this is NOT redundant because here we wait immediately
|
function, this is NOT redundant because here we wait immediately
|
||||||
after submitting the image to the screen, reducing lag, and if
|
after submitting the image to the screen, reducing lag, and if
|
||||||
we have waited here, there won't be a pending pageflip so the
|
we have waited here, there won't be a pending pageflip so the
|
||||||
WaitPageFlip at the beggining of this function will be a no-op.
|
WaitPageflip at the beggining of this function will be a no-op.
|
||||||
Just leave it here and don't worry.
|
Just leave it here and don't worry.
|
||||||
Run your SDL2 program with "SDL_KMSDRM_DOUBLE_BUFFER=1 <program_name>"
|
Run your SDL2 program with "SDL_KMSDRM_DOUBLE_BUFFER=1 <program_name>"
|
||||||
to enable this. */
|
to enable this. */
|
||||||
if (windata->double_buffer) {
|
if (windata->double_buffer) {
|
||||||
if (!KMSDRM_WaitPageFlip(_this, windata)) {
|
if (!KMSDRM_WaitPageflip(_this, windata)) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Immediate wait for previous pageflip failed");
|
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Immediate wait for previous pageflip failed");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -341,11 +341,12 @@ KMSDRM_FlipHandler(int fd, unsigned int frame, unsigned int sec, unsigned int us
|
|||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool
|
SDL_bool
|
||||||
KMSDRM_WaitPageFlip(_THIS, SDL_WindowData *windata) {
|
KMSDRM_WaitPageflip(_THIS, SDL_WindowData *windata) {
|
||||||
|
|
||||||
SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
|
SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
|
||||||
drmEventContext ev = {0};
|
drmEventContext ev = {0};
|
||||||
struct pollfd pfd = {0};
|
struct pollfd pfd = {0};
|
||||||
|
int ret;
|
||||||
|
|
||||||
ev.version = DRM_EVENT_CONTEXT_VERSION;
|
ev.version = DRM_EVENT_CONTEXT_VERSION;
|
||||||
ev.page_flip_handler = KMSDRM_FlipHandler;
|
ev.page_flip_handler = KMSDRM_FlipHandler;
|
||||||
@ -355,11 +356,11 @@ KMSDRM_WaitPageFlip(_THIS, SDL_WindowData *windata) {
|
|||||||
|
|
||||||
/* Stay on the while loop until we get the desired event.
|
/* Stay on the while loop until we get the desired event.
|
||||||
We need the while the loop because we could be in a situation where:
|
We need the while the loop because we could be in a situation where:
|
||||||
-We get events on the FD in time, thus not on exiting on return number 1.
|
-We get and event on the FD in time, thus not on exiting on return number 1.
|
||||||
-These events are not errors, thus not exiting on return number 2.
|
-The event is not an error, thus not exiting on return number 2.
|
||||||
-These events are of POLLIN type, thus not exiting on return number 3,
|
-The event is of POLLIN type, but even then, if the event is not a pageflip,
|
||||||
but if the event is not the pageflip we are waiting for, we arrive at the end
|
drmHandleEvent() won't unset wait_for_pageflip, so we have to iterate
|
||||||
of the loop and do loop re-entry, hoping the next event will be the pageflip.
|
and go polling again.
|
||||||
|
|
||||||
If it wasn't for the while loop, we could erroneously exit the function
|
If it wasn't for the while loop, we could erroneously exit the function
|
||||||
without the pageflip event to arrive!
|
without the pageflip event to arrive!
|
||||||
@ -368,20 +369,30 @@ KMSDRM_WaitPageFlip(_THIS, SDL_WindowData *windata) {
|
|||||||
means "there's data to read on the FD"), but they are not the pageflip event
|
means "there's data to read on the FD"), but they are not the pageflip event
|
||||||
we are waiting for, so the drmEventHandle() doesn't run the flip handler, and
|
we are waiting for, so the drmEventHandle() doesn't run the flip handler, and
|
||||||
since waiting_for_flip is set on the pageflip handle, it's not set and we stay
|
since waiting_for_flip is set on the pageflip handle, it's not set and we stay
|
||||||
on the loop.
|
on the loop, until we get the event for the pageflip, which is fine.
|
||||||
*/
|
*/
|
||||||
while (windata->waiting_for_flip) {
|
while (windata->waiting_for_flip) {
|
||||||
|
|
||||||
pfd.revents = 0;
|
pfd.revents = 0;
|
||||||
|
|
||||||
/* poll() waits for events arriving on the FD, and returns < 0 if timeout
|
/* poll() waits for events arriving on the FD, and returns < 0 if timeout passes
|
||||||
passes with no events.
|
with no events or a signal occurred before any requested event (-EINTR).
|
||||||
We wait forever (timeout = -1), but even if we DO get an event,
|
We wait forever (timeout = -1), but even if we DO get an event, we have yet
|
||||||
we have yet to see if it's of the required type. */
|
to see if it's of the required type, then if it's a pageflip, etc */
|
||||||
if (poll(&pfd, 1, -1) < 0) {
|
ret = poll(&pfd, 1, -1);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
if (errno == EINTR) {
|
||||||
|
/* poll() returning < 0 and setting errno = EINTR means there was a signal before
|
||||||
|
any requested event, so we immediately poll again. */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* There was another error. Don't pull again or we could get into a busy loop. */
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "DRM poll error");
|
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "DRM poll error");
|
||||||
return SDL_FALSE; /* Return number 1. */
|
return SDL_FALSE; /* Return number 1. */
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (pfd.revents & (POLLHUP | POLLERR)) {
|
if (pfd.revents & (POLLHUP | POLLERR)) {
|
||||||
/* An event arrived on the FD in time, but it's an error. */
|
/* An event arrived on the FD in time, but it's an error. */
|
||||||
@ -396,10 +407,19 @@ KMSDRM_WaitPageFlip(_THIS, SDL_WindowData *windata) {
|
|||||||
windata->waiting_for_flip and we will get out of the "while" loop.
|
windata->waiting_for_flip and we will get out of the "while" loop.
|
||||||
If it's not, we keep iterating on the loop. */
|
If it's not, we keep iterating on the loop. */
|
||||||
KMSDRM_drmHandleEvent(viddata->drm_fd, &ev);
|
KMSDRM_drmHandleEvent(viddata->drm_fd, &ev);
|
||||||
} else {
|
|
||||||
SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Dropping frame while waiting_for_flip");
|
|
||||||
return SDL_FALSE; /* Return number 3. */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we got to this point in the loop, we may iterate or exit the loop:
|
||||||
|
-A legit (non-error) event arrived, and it was a POLLING event, and it was consumed
|
||||||
|
by drmHandleEvent().
|
||||||
|
-If it was a PAGEFLIP event, waiting_for_flip will be unset by drmHandleEvent()
|
||||||
|
and we will exit the loop.
|
||||||
|
-If it wasn't a PAGEFLIP, drmHandleEvent() won't unset waiting_for_flip, so we
|
||||||
|
iterare back to polling.
|
||||||
|
-A legit (non-error) event arrived, but it's not a POLLIN event, so it hasn't to be
|
||||||
|
consumed by drmHandleEvent(), so waiting_for_flip isn't set and we iterate back
|
||||||
|
to polling. */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
@ -679,7 +699,7 @@ KMSDRM_DestroySurfaces(_THIS, SDL_Window *window)
|
|||||||
/**********************************************/
|
/**********************************************/
|
||||||
/* Wait for last issued pageflip to complete. */
|
/* Wait for last issued pageflip to complete. */
|
||||||
/**********************************************/
|
/**********************************************/
|
||||||
KMSDRM_WaitPageFlip(_this, windata);
|
KMSDRM_WaitPageflip(_this, windata);
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* Restore the original CRTC configuration: configue the crtc with the */
|
/* 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);
|
int KMSDRM_CreateSurfaces(_THIS, SDL_Window * window);
|
||||||
KMSDRM_FBInfo *KMSDRM_FBFromBO(_THIS, struct gbm_bo *bo);
|
KMSDRM_FBInfo *KMSDRM_FBFromBO(_THIS, struct gbm_bo *bo);
|
||||||
KMSDRM_FBInfo *KMSDRM_FBFromBO2(_THIS, struct gbm_bo *bo, int w, int h);
|
KMSDRM_FBInfo *KMSDRM_FBFromBO2(_THIS, struct gbm_bo *bo, int w, int h);
|
||||||
SDL_bool KMSDRM_WaitPageFlip(_THIS, SDL_WindowData *windata);
|
SDL_bool KMSDRM_WaitPageflip(_THIS, SDL_WindowData *windata);
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
/* SDL_VideoDevice functions declaration */
|
/* SDL_VideoDevice functions declaration */
|
||||||
|
Loading…
Reference in New Issue
Block a user