early-access version 1780

This commit is contained in:
pineappleEA
2021-06-11 20:56:03 +02:00
parent e46a402c25
commit 388881fdbb
93 changed files with 2410 additions and 851 deletions
+47 -48
View File
@@ -97,6 +97,11 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) {
even if you do async flips. */
uint32_t flip_flags = DRM_MODE_PAGE_FLIP_EVENT;
/* Recreate the GBM / EGL surfaces if the display mode has changed */
if (windata->egl_surface_dirty) {
KMSDRM_CreateSurfaces(_this, window);
}
/* Wait for confirmation that the next front buffer has been flipped, at which
point the previous front buffer can be released */
if (!KMSDRM_WaitPageflip(_this, windata)) {
@@ -136,64 +141,58 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) {
return 0;
}
/* Do we have a modeset pending? If so, configure the new mode on the CRTC.
Has to be done before next pageflip issues, so the buffer with the
new size is big enough for preventing CRTC from reading out of bounds. */
if (dispdata->modeset_pending) {
if (!windata->bo) {
/* On the first swap, immediately present the new front buffer. Before
drmModePageFlip can be used the CRTC has to be configured to use
the current connector and mode with drmModeSetCrtc */
ret = KMSDRM_drmModeSetCrtc(viddata->drm_fd,
dispdata->crtc->crtc_id, fb_info->fb_id, 0, 0,
&dispdata->connector->connector_id, 1, &dispdata->mode);
dispdata->modeset_pending = SDL_FALSE;
if (ret) {
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not set videomode on CRTC.");
return 0;
}
/* It's OK to return now if we have done a drmModeSetCrtc(),
it has done the pageflip and blocked until it was done. */
return 1;
}
/* Issue pageflip on the next front buffer.
Remember: drmModePageFlip() never blocks, it just issues the flip,
which will be done during the next vblank, or immediately if
we pass the DRM_MODE_PAGE_FLIP_ASYNC flag.
Since calling drmModePageFlip() will return EBUSY if we call it
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
to do so, so even if we don't block on EGL, the flip will have completed
when we get here again. */
if (_this->egl_data->egl_swapinterval == 0 && viddata->async_pageflip_support) {
flip_flags |= DRM_MODE_PAGE_FLIP_ASYNC;
}
ret = KMSDRM_drmModePageFlip(viddata->drm_fd, dispdata->crtc->crtc_id,
fb_info->fb_id, flip_flags, &windata->waiting_for_flip);
if (ret == 0) {
windata->waiting_for_flip = SDL_TRUE;
} else {
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not queue pageflip: %d", ret);
}
/* On subsequent swaps, queue the new front buffer to be flipped during
the next vertical blank
/* Wait immediately for vsync (as if we only had two buffers).
Even if we are already doing a WaitPageflip at the begining of this
function, this is NOT redundant because here we wait immediately
after submitting the image to the screen, reducing lag, and if
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.
Just leave it here and don't worry.
Run your SDL2 program with "SDL_KMSDRM_DOUBLE_BUFFER=1 <program_name>"
to enable this. */
if (windata->double_buffer) {
if (!KMSDRM_WaitPageflip(_this, windata)) {
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Immediate wait for previous pageflip failed");
return 0;
Remember: drmModePageFlip() never blocks, it just issues the flip,
which will be done during the next vblank, or immediately if
we pass the DRM_MODE_PAGE_FLIP_ASYNC flag.
Since calling drmModePageFlip() will return EBUSY if we call it
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
to do so, so even if we don't block on EGL, the flip will have completed
when we get here again. */
if (_this->egl_data->egl_swapinterval == 0 && viddata->async_pageflip_support) {
flip_flags |= DRM_MODE_PAGE_FLIP_ASYNC;
}
ret = KMSDRM_drmModePageFlip(viddata->drm_fd, dispdata->crtc->crtc_id,
fb_info->fb_id, flip_flags, &windata->waiting_for_flip);
if (ret == 0) {
windata->waiting_for_flip = SDL_TRUE;
} else {
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not queue pageflip: %d", ret);
}
/* Wait immediately for vsync (as if we only had two buffers).
Even if we are already doing a WaitPageflip at the begining of this
function, this is NOT redundant because here we wait immediately
after submitting the image to the screen, reducing lag, and if
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.
Just leave it here and don't worry.
Run your SDL2 program with "SDL_KMSDRM_DOUBLE_BUFFER=1 <program_name>"
to enable this. */
if (windata->double_buffer) {
if (!KMSDRM_WaitPageflip(_this, windata)) {
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Immediate wait for previous pageflip failed");
return 0;
}
}
}
+21 -44
View File
@@ -551,7 +551,6 @@ void KMSDRM_AddDisplay (_THIS, drmModeConnector *connector, drmModeRes *resource
/* Initialize some of the members of the new display's driverdata
to sane values. */
dispdata->modeset_pending = SDL_FALSE;
dispdata->cursor_bo = NULL;
/* Since we create and show the default cursor on KMSDRM_InitMouse(),
@@ -907,6 +906,7 @@ KMSDRM_CreateSurfaces(_THIS, SDL_Window * window)
{
SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
SDL_WindowData *windata = (SDL_WindowData *)window->driverdata;
SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayForWindow(window)->driverdata;
uint32_t surface_fmt = GBM_FORMAT_ARGB8888;
uint32_t surface_flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
@@ -929,7 +929,8 @@ KMSDRM_CreateSurfaces(_THIS, SDL_Window * window)
}
windata->gs = KMSDRM_gbm_surface_create(viddata->gbm_dev,
windata->surface_w, windata->surface_h, surface_fmt, surface_flags);
dispdata->mode.hdisplay, dispdata->mode.vdisplay,
surface_fmt, surface_flags);
if (!windata->gs) {
return SDL_SetError("Could not create GBM surface");
@@ -951,6 +952,8 @@ KMSDRM_CreateSurfaces(_THIS, SDL_Window * window)
egl_context = (EGLContext)SDL_GL_GetCurrentContext();
ret = SDL_EGL_MakeCurrent(_this, windata->egl_surface, egl_context);
windata->egl_surface_dirty = SDL_FALSE;
cleanup:
if (ret) {
@@ -1069,14 +1072,14 @@ KMSDRM_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
/* Take note of the new mode to be set, and leave the CRTC modeset pending
so it's done in SwapWindow. */
dispdata->mode = conn->modes[modedata->mode_index];
dispdata->modeset_pending = SDL_TRUE;
for (i = 0; i < viddata->num_windows; i++) {
SDL_Window *window = viddata->windows[i];
SDL_WindowData *windata = (SDL_WindowData *)window->driverdata;
if (KMSDRM_CreateSurfaces(_this, window)) {
return -1;
}
/* Can't recreate EGL surfaces right now, need to wait until SwapWindow
so the correct thread-local surface and context state are available */
windata->egl_surface_dirty = SDL_TRUE;
/* Tell app about the window resize */
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, mode->w, mode->h);
@@ -1246,18 +1249,11 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window)
window->windowed.w, window->windowed.h, 0 );
if (mode) {
windata->surface_w = mode->hdisplay;
windata->surface_h = mode->vdisplay;
dispdata->mode = *mode;
} else {
windata->surface_w = dispdata->original_mode.hdisplay;
windata->surface_h = dispdata->original_mode.vdisplay;
dispdata->mode = dispdata->original_mode;
}
/* Take note to do the modesettng on the CRTC in SwapWindow. */
dispdata->modeset_pending = SDL_TRUE;
/* Create the window surfaces with the size we have just chosen.
Needs the window diverdata in place. */
if ((ret = KMSDRM_CreateSurfaces(_this, window))) {
@@ -1267,7 +1263,7 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window)
/* Tell app about the size we have determined for the window,
so SDL pre-scales to that size for us. */
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED,
windata->surface_w, windata->surface_h);
dispdata->mode.hdisplay, dispdata->mode.vdisplay);
} /* NON-Vulkan block ends. */
@@ -1310,67 +1306,48 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window)
/* To be used by SetWindowSize() and SetWindowFullscreen(). */
/*****************************************************************************/
void
KMSDRM_ReconfigureWindow( _THIS, SDL_Window * window) {
SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
KMSDRM_ReconfigureWindow( _THIS, SDL_Window * window)
{
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
SDL_DisplayData *dispdata = display->driverdata;
uint32_t refresh_rate = 0;
if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) ==
SDL_WINDOW_FULLSCREEN_DESKTOP)
if ((window->flags & SDL_WINDOW_FULLSCREEN) ==
SDL_WINDOW_FULLSCREEN)
{
/* Nothing to do, honor the most recent mode requested by the user */
}
else if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) ==
SDL_WINDOW_FULLSCREEN_DESKTOP)
{
/* Update the current mode to the desktop mode. */
windata->surface_w = dispdata->original_mode.hdisplay;
windata->surface_h = dispdata->original_mode.vdisplay;
dispdata->mode = dispdata->original_mode;
} else {
drmModeModeInfo *mode;
/* Refresh rate is only important for fullscreen windows. */
if ((window->flags & SDL_WINDOW_FULLSCREEN) ==
SDL_WINDOW_FULLSCREEN)
{
refresh_rate = (uint32_t)window->fullscreen_mode.refresh_rate;
}
/* Try to find a valid video mode matching the size of the window. */
mode = KMSDRM_GetClosestDisplayMode(display,
window->windowed.w, window->windowed.h, refresh_rate );
window->windowed.w, window->windowed.h, 0);
if (mode) {
/* If matching mode found, recreate the GBM surface with the size
of that mode and configure it on the CRTC. */
windata->surface_w = mode->hdisplay;
windata->surface_h = mode->vdisplay;
dispdata->mode = *mode;
} else {
/* If not matching mode found, recreate the GBM surfaces with the
size of the mode that was originally configured on the CRTC,
and setup that mode on the CRTC. */
windata->surface_w = dispdata->original_mode.hdisplay;
windata->surface_h = dispdata->original_mode.vdisplay;
dispdata->mode = dispdata->original_mode;
}
/* Tell app about the size we have determined for the window,
so SDL pre-scales to that size for us. */
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED,
windata->surface_w, windata->surface_h);
}
/* Recreate the GBM (and EGL) surfaces, and mark the CRTC mode/fb setting
as pending so it's done on SwapWindow. */
KMSDRM_CreateSurfaces(_this, window);
dispdata->modeset_pending = SDL_TRUE;
/* Tell app about the size we have determined for the window,
so SDL pre-scales to that size for us. */
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED,
windata->surface_w, windata->surface_h);
dispdata->mode.hdisplay, dispdata->mode.vdisplay);
}
int
+1 -9
View File
@@ -80,8 +80,6 @@ typedef struct SDL_DisplayData
uint64_t cursor_w, cursor_h;
SDL_bool default_cursor_init;
SDL_bool modeset_pending;
} SDL_DisplayData;
typedef struct SDL_WindowData
@@ -99,13 +97,7 @@ typedef struct SDL_WindowData
SDL_bool double_buffer;
EGLSurface egl_surface;
/* The size we chose for the GBM surface. REMEMBER that the CRTC must always have
a mode with the same size configured before trying to flip to a buffer of that
surface or drmModePageFlip() will return -28. */
uint32_t surface_w;
uint32_t surface_h;
SDL_bool egl_surface_dirty;
} SDL_WindowData;
typedef struct KMSDRM_FBInfo