[KMS/DRM] Fix for bug #5470: ratio correction for fullscreen windows with no matching resolution. Correct bracket position in else statements so they follow the coding style.

This commit is contained in:
Manuel Alfayate Corchete 2021-01-17 21:17:01 +01:00
parent c265e73f3b
commit 99facb1df3
1 changed files with 81 additions and 52 deletions

View File

@ -386,8 +386,7 @@ KMSDRM_WaitPageflip(_THIS, SDL_WindowData *windata) {
/* poll() returning < 0 and setting errno = EINTR means there was a signal before
any requested event, so we immediately poll again. */
continue;
}
else {
} 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");
return SDL_FALSE; /* Return number 1. */
@ -425,19 +424,33 @@ KMSDRM_WaitPageflip(_THIS, SDL_WindowData *windata) {
return SDL_TRUE;
}
/* Given w and h, returns a DRM video mode from the modes available on the connector.
Returns NULL if no mode matching the specified size is found. */
/* Given w, h and refresh rate, returns the closest DRM video mode
available on the DRM connector of the display.
We use the SDL mode list (which we filled in KMSDRM_GetDisplayModes)
because it's ordered, while the list on the connector is mostly random.*/
drmModeModeInfo*
KMSDRM_GetConnectorMode(drmModeConnector *connector, uint32_t width, uint32_t height) {
int i = 0;
for (i = 0; i < connector->count_modes; i++) {
if (connector->modes[i].hdisplay == width &&
connector->modes[i].vdisplay == height)
{
return &connector->modes[i];
}
KMSDRM_GetClosestDisplayMode(SDL_VideoDisplay * display,
uint32_t width, uint32_t height, uint32_t refresh_rate){
SDL_DisplayData *dispdata = (SDL_DisplayData *) display->driverdata;
drmModeConnector *connector = dispdata->connector;
SDL_DisplayMode target, closest;
drmModeModeInfo *drm_mode;
target.w = width;
target.h = height;
target.format = 0; /* Will use the default mode format. */
target.refresh_rate = refresh_rate;
target.driverdata = 0; /* Initialize to 0 */
if (!SDL_GetClosestDisplayMode(0, &target, &closest)) {
return NULL;
} else {
SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)closest.driverdata;
drm_mode = &connector->modes[modedata->mode_index];
return drm_mode;
}
return NULL;
}
/*****************************************************************************/
@ -1016,9 +1029,9 @@ KMSDRM_DestroyWindow(_THIS, SDL_Window *window)
/* Free display plane, and destroy GBM device. */
KMSDRM_GBMDeinit(_this, dispdata);
}
else {
} else {
/* If we were in Vulkan mode, get out of it. */
if (viddata->vulkan_mode) {
viddata->vulkan_mode = SDL_FALSE;
@ -1044,14 +1057,14 @@ KMSDRM_DestroyWindow(_THIS, SDL_Window *window)
/*********************************************************************/
/* Free the window driverdata. Bye bye, surface and buffer pointers! */
/*********************************************************************/
SDL_free(window->driverdata);
window->driverdata = NULL;
SDL_free(windata);
}
/**********************************************************************/
/* We simply IGNORE if it's a fullscreen window, window->flags don't */
/* reflect it: if it's fullscreen, KMSDRM_SetWindwoFullscreen() which */
/* will be called by SDL later, and we can manage it there. */
/* reflect it: if it's fullscreen, KMSDRM_SetWindwoFullscreen() will */
/* be called by SDL later, and we can manage it there. */
/**********************************************************************/
int
KMSDRM_CreateWindow(_THIS, SDL_Window * window)
@ -1066,6 +1079,11 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window)
int ret = 0;
drmModeModeInfo *mode;
/* Only 1 window is allowed: we can't flip on several windows in KMSDRM. */
if (viddata->num_windows > 0) {
return -1;
}
/* Allocate window internal data */
windata = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData));
if (!windata) {
@ -1127,25 +1145,31 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window)
KMSDRM_InitCursor();
}
/* Try to find a matching video mode for the window, fallback to the
original mode if not available, and configure the mode we chose
into the CRTC.
You may be tempted to not do a videomode change, remaining always on
/* Try to find the videomode that is the closest to the original size
of the window, and configure the mode we chose into the CRTC.
(You may be tempted to not do a videomode change, remaining always on
the original resolution, and use the SendWindowEvent() parameters to
make SDL2 pre-scale the image for us to an AR-corrected size inside
the original mode, but DON'T: vectorized games (GL games) are rendered
with the size specified in SendWindowEvent(),instead of being rendered
at the original size and then scaled.
It makes sense because GL is used to render the scene in GL games,
so the scene is rendered at the window size. */
mode = KMSDRM_GetConnectorMode(dispdata->connector, window->w, window->h );
so the scene is rendered at the window size).
The FULLSCREEN flags are cut out from window->flags at this point,
so we can't know if a window is fullscreen or not, hence all windows
are considered "windowed" at this point of their life.
If a window is fullscreen, SDL internals will call
KMSDRM_SetWindowFullscreen() to reconfigure it if necessary. */
mode = KMSDRM_GetClosestDisplayMode(display,
window->windowed.w, window->windowed.h, 0 );
if (mode) {
windata->surface_w = window->w;
windata->surface_h = window->h;
windata->surface_w = mode->hdisplay;
windata->surface_h = mode->vdisplay;
dispdata->mode = *mode;
}
else {
} else {
windata->surface_w = dispdata->original_mode.hdisplay;
windata->surface_h = dispdata->original_mode.vdisplay;
dispdata->mode = dispdata->original_mode;
@ -1163,25 +1187,21 @@ 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);
windata->surface_w, windata->surface_h);
} /* NON-Vulkan block ends. */
/* Add window to the internal list of tracked windows. Note, while it may
seem odd to support multiple fullscreen windows, some apps create an
extra window as a dummy surface when working with multiple contexts */
if (viddata->num_windows >= viddata->max_windows) {
unsigned int new_max_windows = viddata->max_windows + 1;
viddata->windows = (SDL_Window **)SDL_realloc(viddata->windows,
new_max_windows * sizeof(SDL_Window *));
viddata->max_windows = new_max_windows;
/* Add window to the internal list of tracked windows, which will
have 1 member only. */
viddata->windows = (SDL_Window **)SDL_calloc(1, sizeof(SDL_Window *));
viddata->num_windows++;
viddata->max_windows = 1;
if (!viddata->windows) {
ret = SDL_OutOfMemory();
goto cleanup;
}
if (!viddata->windows) {
ret = SDL_OutOfMemory();
goto cleanup;
}
viddata->windows[viddata->num_windows++] = window;
viddata->windows[0] = window;
/* If we have just created a Vulkan window, establish that we are in Vulkan mode now. */
viddata->vulkan_mode = is_vulkan;
@ -1215,8 +1235,11 @@ cleanup:
/*****************************************************************************/
void
KMSDRM_ReconfigureWindow( _THIS, SDL_Window * window) {
SDL_DisplayData *dispdata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
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)
@ -1227,21 +1250,27 @@ KMSDRM_ReconfigureWindow( _THIS, SDL_Window * window) {
windata->surface_w = dispdata->original_mode.hdisplay;
windata->surface_h = dispdata->original_mode.vdisplay;
dispdata->mode = dispdata->original_mode;
}
else
{
} 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. */
drmModeModeInfo *mode = KMSDRM_GetConnectorMode(dispdata->connector,
window->windowed.w, window->windowed.h );
mode = KMSDRM_GetClosestDisplayMode(display,
window->windowed.w, window->windowed.h, refresh_rate );
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 = window->windowed.w;
windata->surface_h = window->windowed.h;
windata->surface_w = mode->hdisplay;
windata->surface_h = mode->vdisplay;
dispdata->mode = *mode;
}
else {
} 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. */