wayland: Refactor for video core changes

Accommodate the new video core changes.

The new video core changes allow for some window geometry calculation refactoring that simplify the system:

- Removal of helper functions
- Eliminate some discrepancies between the libdecor and xdg-toplevel paths
- No need to short-circuit the video core window size event deduplication check
- Exclusive fullscreen windows will always end up on the correct output, even when fullscreen is initiated from the compositor
- Better handling of cases where the desktop is scaled, but does not expose the viewport protocol
- Return the display bounds for the emulated mode if an exclusive fullscreen window has focus
- Fixed cases where changing display properties during runtime wouldn't update the display mode lists
- General cleanup
This commit is contained in:
Frank Praznik
2023-02-01 11:18:03 -05:00
committed by Sam Lantinga
parent 47cdb532f1
commit 7def1438c3
3 changed files with 235 additions and 307 deletions
+80 -68
View File
@@ -361,7 +361,7 @@ static const struct zxdg_output_v1_listener xdg_output_listener = {
xdg_output_handle_description,
};
static void AddEmulatedModes(SDL_VideoDisplay *dpy, SDL_bool rot_90)
static void AddEmulatedModes(SDL_DisplayData *dispdata, SDL_bool rot_90)
{
struct EmulatedMode
{
@@ -413,8 +413,9 @@ static void AddEmulatedModes(SDL_VideoDisplay *dpy, SDL_bool rot_90)
int i;
SDL_DisplayMode mode;
const int native_width = dpy->desktop_mode.pixel_w;
const int native_height = dpy->desktop_mode.pixel_h;
SDL_VideoDisplay *dpy = dispdata->display ? SDL_GetVideoDisplay(dispdata->display) : &dispdata->placeholder;
const int native_width = dispdata->pixel_width;
const int native_height = dispdata->pixel_height;
for (i = 0; i < SDL_arraysize(mode_list); ++i) {
SDL_zero(mode);
@@ -423,18 +424,19 @@ static void AddEmulatedModes(SDL_VideoDisplay *dpy, SDL_bool rot_90)
mode.refresh_rate = dpy->desktop_mode.refresh_rate;
mode.driverdata = dpy->desktop_mode.driverdata;
if (rot_90) {
mode.pixel_w = mode_list[i].h;
mode.pixel_h = mode_list[i].w;
} else {
mode.pixel_w = mode_list[i].w;
mode.pixel_h = mode_list[i].h;
}
/* Only add modes that are smaller than the native mode. */
if ((mode.pixel_w < native_width && mode.pixel_h < native_height) ||
(mode.pixel_w < native_width && mode.pixel_h == native_height) ||
(mode.pixel_w == native_width && mode.pixel_h < native_height)) {
if ((mode_list[i].w < native_width && mode_list[i].h < native_height) ||
(mode_list[i].w < native_width && mode_list[i].h == native_height) ||
(mode_list[i].w == native_width && mode_list[i].h < native_height)) {
if (rot_90) {
mode.pixel_w = mode_list[i].h;
mode.pixel_h = mode_list[i].w;
} else {
mode.pixel_w = mode_list[i].w;
mode.pixel_h = mode_list[i].h;
}
SDL_AddFullscreenDisplayMode(dpy, &mode);
}
}
@@ -452,22 +454,6 @@ static void display_handle_geometry(void *data,
{
SDL_DisplayData *driverdata = (SDL_DisplayData *)data;
SDL_VideoDisplay *display;
int i;
if (driverdata->wl_output_done_count) {
/* Clear the wl_output ref so Reset doesn't free it */
display = SDL_GetVideoDisplay(driverdata->display);
for (i = 0; i < display->num_fullscreen_modes; ++i) {
display->fullscreen_modes[i].driverdata = NULL;
}
/* Okay, now it's safe to reset */
SDL_ResetFullscreenDisplayModes(display);
/* The display has officially started over. */
driverdata->wl_output_done_count = 0;
}
/* Apply the change from wl-output only if xdg-output is not supported */
if (!driverdata->has_logical_position) {
@@ -558,14 +544,29 @@ static void display_handle_done(void *data,
driverdata->wl_output_done_count = SDL_min(driverdata->wl_output_done_count + 1, event_await_count + 1);
if (driverdata->wl_output_done_count != event_await_count) {
if (driverdata->wl_output_done_count < event_await_count) {
return;
}
/* If the display was already created, reset and rebuild the mode list. */
if (driverdata->display != 0) {
int i;
dpy = SDL_GetVideoDisplay(driverdata->display);
/* Clear the wl_output ref so Reset doesn't free it */
for (i = 0; i < dpy->num_fullscreen_modes; ++i) {
dpy->fullscreen_modes[i].driverdata = NULL;
}
/* Okay, now it's safe to reset */
SDL_ResetFullscreenDisplayModes(dpy);
}
/* The native display resolution */
SDL_zero(native_mode);
native_mode.format = SDL_PIXELFORMAT_RGB888;
/* Transform the pixel values, if necessary. */
if (driverdata->transform & WL_OUTPUT_TRANSFORM_90) {
native_mode.pixel_w = driverdata->pixel_height;
native_mode.pixel_h = driverdata->pixel_width;
@@ -577,27 +578,29 @@ static void display_handle_done(void *data,
native_mode.refresh_rate = ((100 * driverdata->refresh) / 1000) / 100.0f; /* mHz to Hz */
native_mode.driverdata = driverdata->output;
if (driverdata->has_logical_size) { /* If xdg-output is present... */
if (video->viewporter) {
/* ...and viewports are supported, calculate the true scale of the output. */
driverdata->scale_factor = (float)native_mode.pixel_w / (float)driverdata->screen_width;
} else {
/* ...otherwise, the 'native' pixel values are a multiple of the logical screen size. */
driverdata->pixel_width = driverdata->screen_width * (int)driverdata->scale_factor;
driverdata->pixel_height = driverdata->screen_height * (int)driverdata->scale_factor;
}
} else {
/* Calculate the screen coordinates from the pixel values, if xdg-output isn't present.
* Use the native mode pixel values since they are pre-transformed.
*/
driverdata->screen_width = native_mode.pixel_w / (int)driverdata->scale_factor;
driverdata->screen_height = native_mode.pixel_h / (int)driverdata->scale_factor;
}
/* The scaled desktop mode */
SDL_zero(desktop_mode);
desktop_mode.format = SDL_PIXELFORMAT_RGB888;
if (driverdata->has_logical_size) { /* If xdg-output is present, calculate the true scale of the desktop */
if (video->viewporter) {
driverdata->scale_factor = (float)native_mode.pixel_w / (float)driverdata->screen_width;
}
} else { /* Scale the desktop coordinates, if xdg-output isn't present */
driverdata->screen_width /= driverdata->scale_factor;
driverdata->screen_height /= driverdata->scale_factor;
}
/* xdg-output dimensions are already transformed, so no need to rotate. */
if (driverdata->has_logical_size || !(driverdata->transform & WL_OUTPUT_TRANSFORM_90)) {
desktop_mode.pixel_w = driverdata->pixel_width;
desktop_mode.pixel_h = driverdata->pixel_height;
} else {
desktop_mode.pixel_w = driverdata->pixel_height;
desktop_mode.pixel_h = driverdata->pixel_width;
}
desktop_mode.screen_w = driverdata->screen_width;
desktop_mode.screen_h = driverdata->screen_height;
desktop_mode.display_scale = driverdata->scale_factor;
desktop_mode.refresh_rate = ((100 * driverdata->refresh) / 1000) / 100.0f; /* mHz to Hz */
desktop_mode.driverdata = driverdata->output;
@@ -609,25 +612,23 @@ static void display_handle_done(void *data,
}
/* Set the desktop display mode. */
SDL_memcpy(&dpy->desktop_mode, &desktop_mode, sizeof(&dpy->desktop_mode));
SDL_SetDesktopDisplayMode(dpy, &desktop_mode);
/* If the desktop is scaled... */
if (driverdata->scale_factor > 1.0f) {
/* ...expose the native resolution if viewports are available... */
if (video->viewporter != NULL) {
SDL_AddFullscreenDisplayMode(dpy, &native_mode);
} else {
/* ...if not, expose some smaller, integer scaled resolutions. */
int i;
const int base_pixel_w = desktop_mode.pixel_w / (int)desktop_mode.display_scale;
const int base_pixel_h = desktop_mode.pixel_h / (int)desktop_mode.display_scale;
for (i = 1; i < (int)desktop_mode.display_scale; ++i) {
desktop_mode.pixel_w = base_pixel_w * i;
desktop_mode.pixel_h = base_pixel_h * i;
desktop_mode.display_scale = (float)i;
/* ...expose the unscaled, native resolution if the scale is 1.0 or viewports are available... */
if (driverdata->scale_factor == 1.0f || video->viewporter != NULL) {
SDL_AddFullscreenDisplayMode(dpy, &native_mode);
} else {
/* ...if not, expose the integer scaled variants of the desktop resolution down to 1. */
int i;
SDL_AddFullscreenDisplayMode(dpy, &desktop_mode);
}
desktop_mode.pixel_w = 0;
desktop_mode.pixel_h = 0;
desktop_mode.screen_w = driverdata->screen_width;
desktop_mode.screen_h = driverdata->screen_height;
for (i = (int)driverdata->scale_factor; i > 0; --i) {
desktop_mode.display_scale = (float)i;
SDL_AddFullscreenDisplayMode(dpy, &desktop_mode);
}
}
@@ -635,7 +636,7 @@ static void display_handle_done(void *data,
if (video->viewporter && mode_emulation_enabled) {
const SDL_bool rot_90 = ((driverdata->transform & WL_OUTPUT_TRANSFORM_90) != 0) ||
(driverdata->screen_width < driverdata->screen_height);
AddEmulatedModes(dpy, rot_90);
AddEmulatedModes(driverdata, rot_90);
}
/* Calculate the display DPI */
@@ -974,8 +975,19 @@ static int Wayland_GetDisplayBounds(_THIS, SDL_VideoDisplay *display, SDL_Rect *
SDL_DisplayData *driverdata = display->driverdata;
rect->x = driverdata->x;
rect->y = driverdata->y;
rect->w = display->current_mode->screen_w;
rect->h = display->current_mode->screen_h;
/* When an emulated, exclusive fullscreen window has focus, treat the mode dimensions as the display bounds. */
if (display->fullscreen_window &&
display->fullscreen_window->fullscreen_exclusive &&
display->fullscreen_window == SDL_GetFocusWindow() &&
display->fullscreen_window->fullscreen_mode.screen_w != 0 &&
display->fullscreen_window->fullscreen_mode.screen_h != 0) {
rect->w = display->fullscreen_window->fullscreen_mode.screen_w;
rect->h = display->fullscreen_window->fullscreen_mode.screen_h;
} else {
rect->w = display->current_mode->screen_w;
rect->h = display->current_mode->screen_h;
}
return 0;
}
File diff suppressed because it is too large Load Diff
+4 -5
View File
@@ -106,14 +106,13 @@ struct SDL_WindowData
float windowed_scale_factor;
float pointer_scale_x;
float pointer_scale_y;
int requested_window_width, requested_window_height;
int drawable_width, drawable_height;
int fs_output_width, fs_output_height;
int window_width, window_height;
int wl_window_width, wl_window_height;
int system_min_required_width;
int system_min_required_height;
SDL_bool needs_resize_event;
SDL_bool floating_resize_pending;
SDL_bool was_floating;
SDL_DisplayID fullscreen_display;
SDL_bool floating;
SDL_bool is_fullscreen;
SDL_bool in_fullscreen_transition;
};