wayland: drop buffer_scale use for viewporter

The core wayland protocol way of handling scaling is to use the
buffer_scale mechanism. But this sucks in several ways for reasons I
won't list here and fractional scaling rightly avoids this altogether
and uses a buffer_scale of 1 (i.e. not setting it) along with
viewporter. When originally implemented, this was only specifically used
when the fractional scale protocol was available, but we actually can
use it as a full replacement instead. This means that mpv now hard
requires viewporter, but this protocol is supported by everyone and is
one of the few that is actually stable.

How it works is the same regardless of fractional scaling or not. When
the compositor has a scale value not equal to 1, it will always scale
the client by that factor (unless you set buffer_scale). What we do here
is pass a viewporter size that exactly undos the compositor-side scale
(sans a possible rounding error). So what we are left with is just the
exactly physical pixels we want to display. Fixes #13316.
This commit is contained in:
Dudemanguy 2024-01-20 12:41:11 -06:00
parent 99d387bbc8
commit e32554cd57
6 changed files with 23 additions and 28 deletions

View File

@ -47,14 +47,14 @@ static void resize(struct ra_ctx *ctx)
const int32_t width = mp_rect_w(wl->geometry);
const int32_t height = mp_rect_h(wl->geometry);
vo_wayland_handle_scale(wl);
vo_wayland_set_opaque_region(wl, ctx->opts.want_alpha);
if (p->egl_window)
wl_egl_window_resize(p->egl_window, width, height, 0, 0);
wl->vo->dwidth = width;
wl->vo->dheight = height;
vo_wayland_handle_fractional_scale(wl);
}
static bool wayland_egl_check_visible(struct ra_ctx *ctx)

View File

@ -781,12 +781,6 @@ static int preinit(struct vo *vo)
goto err;
}
if (!vo->wl->viewport) {
MP_FATAL(vo->wl, "Compositor doesn't support the %s protocol!\n",
wp_viewporter_interface.name);
goto err;
}
if (vo->wl->single_pixel_manager) {
#if HAVE_WAYLAND_PROTOCOLS_1_27
p->solid_buffer = wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer(

View File

@ -209,7 +209,7 @@ static int resize(struct vo *vo)
talloc_free(buf);
}
vo_wayland_handle_fractional_scale(wl);
vo_wayland_handle_scale(wl);
return mp_sws_reinit(p->sws);
}

View File

@ -118,7 +118,7 @@ static bool resize(struct ra_ctx *ctx)
const int32_t height = mp_rect_h(wl->geometry);
vo_wayland_set_opaque_region(wl, ctx->opts.want_alpha);
vo_wayland_handle_fractional_scale(wl);
vo_wayland_handle_scale(wl);
return ra_vk_ctx_resize(ctx, width, height);
}

View File

@ -1012,13 +1012,13 @@ static void handle_toplevel_config(void *data, struct xdg_toplevel *toplevel,
}
wl->window_size.x0 = 0;
wl->window_size.y0 = 0;
wl->window_size.x1 = round(width * wl->scaling);
wl->window_size.y1 = round(height * wl->scaling);
wl->window_size.x1 = lround(width * wl->scaling);
wl->window_size.y1 = lround(height * wl->scaling);
}
wl->geometry.x0 = 0;
wl->geometry.y0 = 0;
wl->geometry.x1 = round(width * wl->scaling);
wl->geometry.y1 = round(height * wl->scaling);
wl->geometry.x1 = lround(width * wl->scaling);
wl->geometry.y1 = lround(height * wl->scaling);
if (mp_rect_equals(&old_geometry, &wl->geometry))
return;
@ -1500,13 +1500,11 @@ static bool create_input(struct vo_wayland_state *wl)
static int create_viewports(struct vo_wayland_state *wl)
{
if (wl->viewporter) {
wl->viewport = wp_viewporter_get_viewport(wl->viewporter, wl->surface);
wl->osd_viewport = wp_viewporter_get_viewport(wl->viewporter, wl->osd_surface);
wl->video_viewport = wp_viewporter_get_viewport(wl->viewporter, wl->video_surface);
}
wl->viewport = wp_viewporter_get_viewport(wl->viewporter, wl->surface);
wl->osd_viewport = wp_viewporter_get_viewport(wl->viewporter, wl->osd_surface);
wl->video_viewport = wp_viewporter_get_viewport(wl->viewporter, wl->video_surface);
if (wl->viewporter && (!wl->viewport || !wl->osd_viewport || !wl->video_viewport)) {
if (!wl->viewport || !wl->osd_viewport || !wl->video_viewport) {
MP_ERR(wl, "failed to create viewport interfaces!\n");
return 1;
}
@ -1847,9 +1845,7 @@ static void set_surface_scaling(struct vo_wayland_state *wl)
// dmabuf_wayland is always wl->scaling = 1
double old_scale = wl->scaling;
wl->scaling = !wl->using_dmabuf_wayland ? wl->current_output->scale : 1;
rescale_geometry(wl, old_scale);
wl_surface_set_buffer_scale(wl->surface, wl->scaling);
}
static void set_window_bounds(struct vo_wayland_state *wl)
@ -2182,12 +2178,11 @@ int vo_wayland_control(struct vo *vo, int *events, int request, void *arg)
return VO_NOTIMPL;
}
void vo_wayland_handle_fractional_scale(struct vo_wayland_state *wl)
void vo_wayland_handle_scale(struct vo_wayland_state *wl)
{
if (wl->fractional_scale_manager && wl->viewport)
wp_viewport_set_destination(wl->viewport,
round(mp_rect_w(wl->geometry) / wl->scaling),
round(mp_rect_h(wl->geometry) / wl->scaling));
wp_viewport_set_destination(wl->viewport,
lround(mp_rect_w(wl->geometry) / wl->scaling),
lround(mp_rect_h(wl->geometry) / wl->scaling));
}
bool vo_wayland_init(struct vo *vo)
@ -2244,6 +2239,12 @@ bool vo_wayland_init(struct vo *vo)
goto err;
}
if (!wl->viewporter) {
MP_FATAL(wl, "Compositor doesn't support the required %s protocol!\n",
wp_viewporter_interface.name);
goto err;
}
/* Can't be initialized during registry due to multi-protocol dependence */
if (create_viewports(wl))
goto err;

View File

@ -178,7 +178,7 @@ bool vo_wayland_reconfig(struct vo *vo);
int vo_wayland_allocate_memfd(struct vo *vo, size_t size);
int vo_wayland_control(struct vo *vo, int *events, int request, void *arg);
void vo_wayland_handle_fractional_scale(struct vo_wayland_state *wl);
void vo_wayland_handle_scale(struct vo_wayland_state *wl);
void vo_wayland_set_opaque_region(struct vo_wayland_state *wl, bool alpha);
void vo_wayland_sync_swap(struct vo_wayland_state *wl);
void vo_wayland_uninit(struct vo *vo);