wayland/output: Track protocol state for computing changed properties

This makes sure that xdg-output.logical_size and
xdg-output.logical_position are only sent when they actually changed.

There should be no behavior change in wl_output_transform_from_transform
but it now uses the same technique of tracking the protocol state and
comparing it to the current state to compute which properties have
changed.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3622>
This commit is contained in:
Sebastian Wick 2024-02-27 16:21:09 +01:00 committed by Marge Bot
parent f94e32037c
commit 5690bd3eaa

View File

@ -51,16 +51,17 @@ struct _MetaWaylandOutput
GObject parent;
struct wl_global *global;
uint32_t mode_flags;
float refresh_rate;
int scale;
MetaMonitorTransform transform;
int mode_width;
int mode_height;
GList *resources;
GList *xdg_output_resources;
/* Protocol state */
MtkRectangle layout;
CoglSubpixelOrder subpixel_order;
MetaMonitorTransform transform;
MetaMonitorMode *mode;
MetaMonitorMode *preferred_mode;
float scale;
MetaMonitor *monitor;
};
@ -131,17 +132,6 @@ cogl_subpixel_order_to_wl_output_subpixel (CoglSubpixelOrder subpixel_order)
return WL_OUTPUT_SUBPIXEL_UNKNOWN;
}
static int
calculate_wayland_output_scale (MetaMonitor *monitor)
{
MetaLogicalMonitor *logical_monitor;
float scale;
logical_monitor = meta_monitor_get_logical_monitor (monitor);
scale = meta_logical_monitor_get_scale (logical_monitor);
return ceilf (scale);
}
static enum wl_output_transform
wl_output_transform_from_transform (MetaMonitorTransform transform)
{
@ -174,101 +164,114 @@ send_output_events (struct wl_resource *resource,
gboolean need_all_events,
gboolean *pending_done_event)
{
MetaLogicalMonitor *logical_monitor =
meta_monitor_get_logical_monitor (monitor);
int version = wl_resource_get_version (resource);
MetaMonitorMode *current_mode;
MetaMonitorMode *preferred_mode;
guint mode_flags = WL_OUTPUT_MODE_CURRENT;
MetaLogicalMonitor *logical_monitor;
MetaLogicalMonitor *old_logical_monitor;
guint old_mode_flags;
gint old_scale;
float old_refresh_rate;
float refresh_rate;
MetaMonitorTransform old_transform;
MtkRectangle layout;
MtkRectangle old_layout;
MetaMonitorTransform transform;
int new_width, new_height;
logical_monitor = meta_monitor_get_logical_monitor (monitor);
old_logical_monitor =
meta_monitor_get_logical_monitor (wayland_output->monitor);
old_mode_flags = wayland_output->mode_flags;
old_scale = wayland_output->scale;
old_transform = wayland_output->transform;
old_refresh_rate = wayland_output->refresh_rate;
current_mode = meta_monitor_get_current_mode (monitor);
refresh_rate = meta_monitor_mode_get_refresh_rate (current_mode);
transform = meta_logical_monitor_get_transform (logical_monitor);
MetaMonitorTransform old_transform;
MetaMonitorMode *mode;
MetaMonitorMode *old_mode;
MetaMonitorMode *preferred_mode;
MetaMonitorMode *old_preferred_mode;
guint mode_flags;
guint old_mode_flags;
int32_t refresh_rate_khz;
int32_t old_refresh_rate_khz;
int scale_int;
int old_scale_int;
int mode_width, mode_height;
int old_mode_width, old_mode_height;
gboolean need_done = FALSE;
layout = meta_logical_monitor_get_layout (logical_monitor);
old_layout = wayland_output->layout;
transform = meta_logical_monitor_get_transform (logical_monitor);
old_transform = wayland_output->transform;
mode = meta_monitor_get_current_mode (monitor);
old_mode = wayland_output->mode;
preferred_mode = meta_monitor_get_preferred_mode (monitor);
old_preferred_mode = wayland_output->preferred_mode;
mode_flags = WL_OUTPUT_MODE_CURRENT;
if (mode == preferred_mode)
mode_flags |= WL_OUTPUT_MODE_PREFERRED;
old_mode_flags = WL_OUTPUT_MODE_CURRENT;
if (old_mode == old_preferred_mode)
old_mode_flags |= WL_OUTPUT_MODE_PREFERRED;
refresh_rate_khz = meta_monitor_mode_get_refresh_rate (mode) * 1000;
old_refresh_rate_khz = meta_monitor_mode_get_refresh_rate (old_mode) * 1000;
scale_int = ceilf (meta_logical_monitor_get_scale (logical_monitor));
old_scale_int = ceilf (wayland_output->scale);
meta_monitor_mode_get_resolution (mode, &mode_width, &mode_height);
meta_monitor_mode_get_resolution (old_mode,
&old_mode_width, &old_mode_height);
if (need_all_events ||
old_logical_monitor->rect.x != logical_monitor->rect.x ||
old_logical_monitor->rect.y != logical_monitor->rect.y ||
old_layout.x != layout.x || old_layout.y != layout.y ||
old_transform != transform)
{
int width_mm, height_mm;
const char *vendor;
const char *product;
int physical_width_mm;
int physical_height_mm;
CoglSubpixelOrder subpixel_order;
enum wl_output_subpixel wl_subpixel_order;
uint32_t wl_transform;
CoglSubpixelOrder cogl_subpixel_order;
enum wl_output_subpixel subpixel_order;
meta_monitor_get_physical_dimensions (monitor, &width_mm, &height_mm);
vendor = meta_monitor_get_vendor (monitor);
product = meta_monitor_get_product (monitor);
cogl_subpixel_order = meta_monitor_get_subpixel_order (monitor);
subpixel_order =
cogl_subpixel_order_to_wl_output_subpixel (cogl_subpixel_order);
meta_monitor_get_physical_dimensions (monitor,
&physical_width_mm,
&physical_height_mm);
subpixel_order = meta_monitor_get_subpixel_order (monitor);
wl_subpixel_order =
cogl_subpixel_order_to_wl_output_subpixel (subpixel_order);
wl_transform = wl_output_transform_from_transform (transform);
wl_output_send_geometry (resource,
logical_monitor->rect.x,
logical_monitor->rect.y,
width_mm,
height_mm,
subpixel_order,
layout.x,
layout.y,
physical_width_mm,
physical_height_mm,
wl_subpixel_order,
vendor ? vendor : "unknown",
product ? product : "unknown",
wl_transform);
need_done = TRUE;
}
preferred_mode = meta_monitor_get_preferred_mode (monitor);
if (current_mode == preferred_mode)
mode_flags |= WL_OUTPUT_MODE_PREFERRED;
meta_monitor_mode_get_resolution (current_mode,
&new_width,
&new_height);
if (need_all_events ||
wayland_output->mode_width != new_width ||
wayland_output->mode_height != new_height ||
old_refresh_rate != refresh_rate ||
old_mode_width != mode_width ||
old_mode_height != mode_height ||
old_refresh_rate_khz != refresh_rate_khz ||
old_mode_flags != mode_flags)
{
wl_output_send_mode (resource,
mode_flags,
new_width,
new_height,
(int32_t) (refresh_rate * 1000));
mode_width,
mode_height,
refresh_rate_khz);
need_done = TRUE;
}
if (version >= WL_OUTPUT_SCALE_SINCE_VERSION)
if (version >= WL_OUTPUT_SCALE_SINCE_VERSION &&
(need_all_events || old_scale_int != scale_int))
{
int scale;
scale = calculate_wayland_output_scale (monitor);
if (need_all_events ||
old_scale != scale)
{
wl_output_send_scale (resource, scale);
wl_output_send_scale (resource, scale_int);
need_done = TRUE;
}
}
if (need_all_events && version >= WL_OUTPUT_NAME_SINCE_VERSION)
{
@ -309,6 +312,7 @@ bind_output (struct wl_client *client,
struct wl_resource *resource;
#ifdef WITH_VERBOSE_MODE
MetaLogicalMonitor *logical_monitor;
int mode_width, mode_height;
#endif
resource = wl_resource_create (client, &wl_output_interface, version, id);
@ -331,13 +335,14 @@ bind_output (struct wl_client *client,
#ifdef WITH_VERBOSE_MODE
logical_monitor = meta_monitor_get_logical_monitor (monitor);
meta_monitor_mode_get_resolution (wayland_output->mode, &mode_width, &mode_height);
meta_verbose ("Binding monitor %p/%s (%u, %u, %u, %u) x %f",
logical_monitor,
meta_monitor_get_product (monitor),
logical_monitor->rect.x, logical_monitor->rect.y,
wayland_output->mode_width,
wayland_output->mode_height,
wayland_output->refresh_rate);
wayland_output->layout.x, wayland_output->layout.y,
mode_width, mode_height,
meta_monitor_mode_get_refresh_rate (wayland_output->mode));
#endif
send_output_events (resource, wayland_output, monitor, TRUE, NULL);
@ -349,28 +354,18 @@ static void
meta_wayland_output_set_monitor (MetaWaylandOutput *wayland_output,
MetaMonitor *monitor)
{
MetaMonitorMode *current_mode;
MetaMonitorMode *preferred_mode;
MetaLogicalMonitor *logical_monitor;
wayland_output->monitor = monitor;
wayland_output->mode_flags = WL_OUTPUT_MODE_CURRENT;
current_mode = meta_monitor_get_current_mode (monitor);
preferred_mode = meta_monitor_get_preferred_mode (monitor);
if (current_mode == preferred_mode)
wayland_output->mode_flags |= WL_OUTPUT_MODE_PREFERRED;
wayland_output->scale = calculate_wayland_output_scale (monitor);
wayland_output->refresh_rate = meta_monitor_mode_get_refresh_rate (current_mode);
logical_monitor = meta_monitor_get_logical_monitor (monitor);
wayland_output->layout = meta_logical_monitor_get_layout (logical_monitor);
wayland_output->subpixel_order = meta_monitor_get_subpixel_order (monitor);
wayland_output->transform =
meta_logical_monitor_get_transform (logical_monitor);
meta_monitor_mode_get_resolution (current_mode,
&wayland_output->mode_width,
&wayland_output->mode_height);
wayland_output->mode = meta_monitor_get_current_mode (monitor);
wayland_output->preferred_mode = meta_monitor_get_preferred_mode (monitor);
wayland_output->scale = meta_logical_monitor_get_scale (logical_monitor);
}
static void
@ -608,17 +603,29 @@ send_xdg_output_events (struct wl_resource *resource,
gboolean need_all_events,
gboolean *pending_done_event)
{
MetaLogicalMonitor *logical_monitor =
meta_monitor_get_logical_monitor (monitor);
int version = wl_resource_get_version (resource);
MtkRectangle layout;
MetaLogicalMonitor *logical_monitor;
int version;
MtkRectangle old_layout;
gboolean need_done = FALSE;
logical_monitor = meta_monitor_get_logical_monitor (monitor);
layout = meta_logical_monitor_get_layout (logical_monitor);
old_layout = wayland_output->layout;
if (need_all_events ||
old_layout.x != layout.x || old_layout.y != layout.y)
{
zxdg_output_v1_send_logical_position (resource, layout.x, layout.y);
zxdg_output_v1_send_logical_size (resource, layout.width, layout.height);
need_done = TRUE;
}
version = wl_resource_get_version (resource);
if (need_all_events ||
old_layout.width != layout.width || old_layout.height != layout.height)
{
zxdg_output_v1_send_logical_size (resource, layout.width, layout.height);
need_done = TRUE;
}
if (need_all_events && version >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION)
{
@ -626,6 +633,7 @@ send_xdg_output_events (struct wl_resource *resource,
name = meta_monitor_get_connector (monitor);
zxdg_output_v1_send_name (resource, name);
need_done = TRUE;
}
if (need_all_events && version >= ZXDG_OUTPUT_V1_DESCRIPTION_SINCE_VERSION)
@ -634,9 +642,10 @@ send_xdg_output_events (struct wl_resource *resource,
description = meta_monitor_get_display_name (monitor);
zxdg_output_v1_send_description (resource, description);
need_done = TRUE;
}
if (pending_done_event)
if (pending_done_event && need_done)
*pending_done_event = TRUE;
}