wayland/output: Make each wl_output correspond to one monitor

This is more in line with the protocol, and allows us to remove some
awkward code that tries to "combine" different metadata from different
monitors into one, which sometimes meant picking an arbitrary "main"
monitor, or "and" metadata together to find a common ground.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1712>
This commit is contained in:
Jonas Ådahl 2021-02-05 17:22:30 +01:00 committed by Marge Bot
parent 4615da2122
commit bf7c34507d
2 changed files with 76 additions and 114 deletions

View File

@ -53,7 +53,6 @@ struct _MetaWaylandOutput
GObject parent; GObject parent;
struct wl_global *global; struct wl_global *global;
MetaLogicalMonitor *logical_monitor;
uint32_t mode_flags; uint32_t mode_flags;
float refresh_rate; float refresh_rate;
int scale; int scale;
@ -63,7 +62,7 @@ struct _MetaWaylandOutput
GList *resources; GList *resources;
GList *xdg_output_resources; GList *xdg_output_resources;
uint64_t winsys_id; MetaMonitor *monitor;
}; };
G_DEFINE_TYPE (MetaWaylandOutput, meta_wayland_output, G_TYPE_OBJECT) G_DEFINE_TYPE (MetaWaylandOutput, meta_wayland_output, G_TYPE_OBJECT)
@ -71,7 +70,7 @@ G_DEFINE_TYPE (MetaWaylandOutput, meta_wayland_output, G_TYPE_OBJECT)
static void static void
send_xdg_output_events (struct wl_resource *resource, send_xdg_output_events (struct wl_resource *resource,
MetaWaylandOutput *wayland_output, MetaWaylandOutput *wayland_output,
MetaLogicalMonitor *logical_monitor, MetaMonitor *monitor,
gboolean need_all_events, gboolean need_all_events,
gboolean *pending_done_event); gboolean *pending_done_event);
@ -84,7 +83,7 @@ meta_wayland_output_get_resources (MetaWaylandOutput *wayland_output)
MetaLogicalMonitor * MetaLogicalMonitor *
meta_wayland_output_get_logical_monitor (MetaWaylandOutput *wayland_output) meta_wayland_output_get_logical_monitor (MetaWaylandOutput *wayland_output)
{ {
return wayland_output->logical_monitor; return meta_monitor_get_logical_monitor (wayland_output->monitor);
} }
static void static void
@ -99,15 +98,6 @@ output_resource_destroy (struct wl_resource *res)
wayland_output->resources = g_list_remove (wayland_output->resources, res); wayland_output->resources = g_list_remove (wayland_output->resources, res);
} }
static MetaMonitor *
pick_main_monitor (MetaLogicalMonitor *logical_monitor)
{
GList *monitors;
monitors = meta_logical_monitor_get_monitors (logical_monitor);
return g_list_first (monitors)->data;
}
static enum wl_output_subpixel static enum wl_output_subpixel
cogl_subpixel_order_to_wl_output_subpixel (CoglSubpixelOrder subpixel_order) cogl_subpixel_order_to_wl_output_subpixel (CoglSubpixelOrder subpixel_order)
{ {
@ -131,37 +121,13 @@ cogl_subpixel_order_to_wl_output_subpixel (CoglSubpixelOrder subpixel_order)
return WL_OUTPUT_SUBPIXEL_UNKNOWN; return WL_OUTPUT_SUBPIXEL_UNKNOWN;
} }
static enum wl_output_subpixel
calculate_suitable_subpixel_order (MetaLogicalMonitor *logical_monitor)
{
GList *monitors;
GList *l;
MetaMonitor *first_monitor;
CoglSubpixelOrder subpixel_order;
monitors = meta_logical_monitor_get_monitors (logical_monitor);
first_monitor = monitors->data;
subpixel_order = meta_monitor_get_subpixel_order (first_monitor);
for (l = monitors->next; l; l = l->next)
{
MetaMonitor *monitor = l->data;
if (meta_monitor_get_subpixel_order (monitor) != subpixel_order)
{
subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
break;
}
}
return cogl_subpixel_order_to_wl_output_subpixel (subpixel_order);
}
static int static int
calculate_wayland_output_scale (MetaLogicalMonitor *logical_monitor) calculate_wayland_output_scale (MetaMonitor *monitor)
{ {
MetaLogicalMonitor *logical_monitor;
float scale; float scale;
logical_monitor = meta_monitor_get_logical_monitor (monitor);
scale = meta_logical_monitor_get_scale (logical_monitor); scale = meta_logical_monitor_get_scale (logical_monitor);
return ceilf (scale); return ceilf (scale);
} }
@ -200,13 +166,15 @@ is_different_rotation (MetaLogicalMonitor *a,
} }
static void static void
get_native_output_mode_resolution (MetaLogicalMonitor *logical_monitor, get_native_output_mode_resolution (MetaMonitor *monitor,
MetaMonitorMode *mode, MetaMonitorMode *mode,
int *mode_width, int *mode_width,
int *mode_height) int *mode_height)
{ {
MetaLogicalMonitor *logical_monitor;
MetaMonitorTransform transform; MetaMonitorTransform transform;
logical_monitor = meta_monitor_get_logical_monitor (monitor);
transform = meta_logical_monitor_get_transform (logical_monitor); transform = meta_logical_monitor_get_transform (logical_monitor);
if (meta_monitor_transform_is_rotated (transform)) if (meta_monitor_transform_is_rotated (transform))
meta_monitor_mode_get_resolution (mode, mode_height, mode_width); meta_monitor_mode_get_resolution (mode, mode_height, mode_width);
@ -217,15 +185,15 @@ get_native_output_mode_resolution (MetaLogicalMonitor *logical_monitor,
static void static void
send_output_events (struct wl_resource *resource, send_output_events (struct wl_resource *resource,
MetaWaylandOutput *wayland_output, MetaWaylandOutput *wayland_output,
MetaLogicalMonitor *logical_monitor, MetaMonitor *monitor,
gboolean need_all_events, gboolean need_all_events,
gboolean *pending_done_event) gboolean *pending_done_event)
{ {
int version = wl_resource_get_version (resource); int version = wl_resource_get_version (resource);
MetaMonitor *monitor;
MetaMonitorMode *current_mode; MetaMonitorMode *current_mode;
MetaMonitorMode *preferred_mode; MetaMonitorMode *preferred_mode;
guint mode_flags = WL_OUTPUT_MODE_CURRENT; guint mode_flags = WL_OUTPUT_MODE_CURRENT;
MetaLogicalMonitor *logical_monitor;
MetaLogicalMonitor *old_logical_monitor; MetaLogicalMonitor *old_logical_monitor;
guint old_mode_flags; guint old_mode_flags;
gint old_scale; gint old_scale;
@ -233,13 +201,13 @@ send_output_events (struct wl_resource *resource,
float refresh_rate; float refresh_rate;
int new_width, new_height; int new_width, new_height;
old_logical_monitor = wayland_output->logical_monitor; 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_mode_flags = wayland_output->mode_flags;
old_scale = wayland_output->scale; old_scale = wayland_output->scale;
old_refresh_rate = wayland_output->refresh_rate; old_refresh_rate = wayland_output->refresh_rate;
monitor = pick_main_monitor (logical_monitor);
current_mode = meta_monitor_get_current_mode (monitor); current_mode = meta_monitor_get_current_mode (monitor);
refresh_rate = meta_monitor_mode_get_refresh_rate (current_mode); refresh_rate = meta_monitor_mode_get_refresh_rate (current_mode);
@ -254,20 +222,16 @@ send_output_events (struct wl_resource *resource,
const char *vendor; const char *vendor;
const char *product; const char *product;
uint32_t transform; uint32_t transform;
CoglSubpixelOrder cogl_subpixel_order;
enum wl_output_subpixel subpixel_order; enum wl_output_subpixel subpixel_order;
/*
* While the wl_output carries information specific to a single monitor,
* it is actually referring to a region of the compositor's screen region
* (logical monitor), which may consist of multiple monitors (clones).
* Arbitrarily use whatever monitor is the first in the logical monitor
* and use that for these details.
*/
get_rotated_physical_dimensions (monitor, &width_mm, &height_mm); get_rotated_physical_dimensions (monitor, &width_mm, &height_mm);
vendor = meta_monitor_get_vendor (monitor); vendor = meta_monitor_get_vendor (monitor);
product = meta_monitor_get_product (monitor); product = meta_monitor_get_product (monitor);
subpixel_order = calculate_suitable_subpixel_order (logical_monitor); cogl_subpixel_order = meta_monitor_get_subpixel_order (monitor);
subpixel_order =
cogl_subpixel_order_to_wl_output_subpixel (cogl_subpixel_order);
/* /*
* TODO: When we support wl_surface.set_buffer_transform, pass along * TODO: When we support wl_surface.set_buffer_transform, pass along
@ -293,7 +257,7 @@ send_output_events (struct wl_resource *resource,
if (current_mode == preferred_mode) if (current_mode == preferred_mode)
mode_flags |= WL_OUTPUT_MODE_PREFERRED; mode_flags |= WL_OUTPUT_MODE_PREFERRED;
get_native_output_mode_resolution (logical_monitor, get_native_output_mode_resolution (monitor,
current_mode, current_mode,
&new_width, &new_width,
&new_height); &new_height);
@ -315,7 +279,7 @@ send_output_events (struct wl_resource *resource,
{ {
int scale; int scale;
scale = calculate_wayland_output_scale (logical_monitor); scale = calculate_wayland_output_scale (monitor);
if (need_all_events || if (need_all_events ||
old_scale != scale) old_scale != scale)
{ {
@ -341,10 +305,10 @@ bind_output (struct wl_client *client,
guint32 id) guint32 id)
{ {
MetaWaylandOutput *wayland_output = data; MetaWaylandOutput *wayland_output = data;
MetaLogicalMonitor *logical_monitor = wayland_output->logical_monitor; MetaMonitor *monitor;
struct wl_resource *resource; struct wl_resource *resource;
#ifdef WITH_VERBOSE_MODE #ifdef WITH_VERBOSE_MODE
MetaMonitor *monitor; MetaLogicalMonitor *logical_monitor;
#endif #endif
resource = wl_resource_create (client, &wl_output_interface, version, id); resource = wl_resource_create (client, &wl_output_interface, version, id);
@ -353,12 +317,12 @@ bind_output (struct wl_client *client,
wl_resource_set_user_data (resource, wayland_output); wl_resource_set_user_data (resource, wayland_output);
wl_resource_set_destructor (resource, output_resource_destroy); wl_resource_set_destructor (resource, output_resource_destroy);
if (!logical_monitor) monitor = wayland_output->monitor;
if (!monitor)
return; return;
#ifdef WITH_VERBOSE_MODE #ifdef WITH_VERBOSE_MODE
monitor = pick_main_monitor (logical_monitor); logical_monitor = meta_monitor_get_logical_monitor (monitor);
meta_verbose ("Binding monitor %p/%s (%u, %u, %u, %u) x %f", meta_verbose ("Binding monitor %p/%s (%u, %u, %u, %u) x %f",
logical_monitor, logical_monitor,
meta_monitor_get_product (monitor), meta_monitor_get_product (monitor),
@ -368,33 +332,30 @@ bind_output (struct wl_client *client,
wayland_output->refresh_rate); wayland_output->refresh_rate);
#endif #endif
send_output_events (resource, wayland_output, logical_monitor, TRUE, NULL); send_output_events (resource, wayland_output, monitor, TRUE, NULL);
g_signal_emit (wayland_output, signals[OUTPUT_BOUND], 0, resource); g_signal_emit (wayland_output, signals[OUTPUT_BOUND], 0, resource);
} }
static void static void
meta_wayland_output_set_logical_monitor (MetaWaylandOutput *wayland_output, meta_wayland_output_set_monitor (MetaWaylandOutput *wayland_output,
MetaLogicalMonitor *logical_monitor) MetaMonitor *monitor)
{ {
MetaMonitor *monitor;
MetaMonitorMode *current_mode; MetaMonitorMode *current_mode;
MetaMonitorMode *preferred_mode; MetaMonitorMode *preferred_mode;
wayland_output->logical_monitor = logical_monitor; wayland_output->monitor = monitor;
wayland_output->mode_flags = WL_OUTPUT_MODE_CURRENT; wayland_output->mode_flags = WL_OUTPUT_MODE_CURRENT;
monitor = pick_main_monitor (logical_monitor);
current_mode = meta_monitor_get_current_mode (monitor); current_mode = meta_monitor_get_current_mode (monitor);
preferred_mode = meta_monitor_get_preferred_mode (monitor); preferred_mode = meta_monitor_get_preferred_mode (monitor);
if (current_mode == preferred_mode) if (current_mode == preferred_mode)
wayland_output->mode_flags |= WL_OUTPUT_MODE_PREFERRED; wayland_output->mode_flags |= WL_OUTPUT_MODE_PREFERRED;
wayland_output->scale = calculate_wayland_output_scale (logical_monitor); wayland_output->scale = calculate_wayland_output_scale (monitor);
wayland_output->refresh_rate = meta_monitor_mode_get_refresh_rate (current_mode); wayland_output->refresh_rate = meta_monitor_mode_get_refresh_rate (current_mode);
wayland_output->winsys_id = logical_monitor->winsys_id; get_native_output_mode_resolution (monitor,
get_native_output_mode_resolution (logical_monitor,
current_mode, current_mode,
&wayland_output->mode_width, &wayland_output->mode_width,
&wayland_output->mode_height); &wayland_output->mode_height);
@ -402,7 +363,7 @@ meta_wayland_output_set_logical_monitor (MetaWaylandOutput *wayland_output,
static void static void
wayland_output_update_for_output (MetaWaylandOutput *wayland_output, wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
MetaLogicalMonitor *logical_monitor) MetaMonitor *monitor)
{ {
GList *iter; GList *iter;
gboolean pending_done_event; gboolean pending_done_event;
@ -411,13 +372,17 @@ wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
for (iter = wayland_output->resources; iter; iter = iter->next) for (iter = wayland_output->resources; iter; iter = iter->next)
{ {
struct wl_resource *resource = iter->data; struct wl_resource *resource = iter->data;
send_output_events (resource, wayland_output, logical_monitor, FALSE, &pending_done_event);
send_output_events (resource, wayland_output, monitor,
FALSE, &pending_done_event);
} }
for (iter = wayland_output->xdg_output_resources; iter; iter = iter->next) for (iter = wayland_output->xdg_output_resources; iter; iter = iter->next)
{ {
struct wl_resource *xdg_output = iter->data; struct wl_resource *xdg_output = iter->data;
send_xdg_output_events (xdg_output, wayland_output, logical_monitor, FALSE, &pending_done_event);
send_xdg_output_events (xdg_output, wayland_output, monitor,
FALSE, &pending_done_event);
} }
/* Send the "done" events if needed */ /* Send the "done" events if needed */
@ -437,14 +402,13 @@ wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
zxdg_output_v1_send_done (xdg_output); zxdg_output_v1_send_done (xdg_output);
} }
} }
/* It's very important that we change the output pointer here, as
the old structure is about to be freed by MetaMonitorManager */ meta_wayland_output_set_monitor (wayland_output, monitor);
meta_wayland_output_set_logical_monitor (wayland_output, logical_monitor);
} }
static MetaWaylandOutput * static MetaWaylandOutput *
meta_wayland_output_new (MetaWaylandCompositor *compositor, meta_wayland_output_new (MetaWaylandCompositor *compositor,
MetaLogicalMonitor *logical_monitor) MetaMonitor *monitor)
{ {
MetaWaylandOutput *wayland_output; MetaWaylandOutput *wayland_output;
@ -454,7 +418,7 @@ meta_wayland_output_new (MetaWaylandCompositor *compositor,
META_WL_OUTPUT_VERSION, META_WL_OUTPUT_VERSION,
wayland_output, bind_output); wayland_output, bind_output);
meta_wayland_compositor_flush_clients (compositor); meta_wayland_compositor_flush_clients (compositor);
meta_wayland_output_set_logical_monitor (wayland_output, logical_monitor); meta_wayland_output_set_monitor (wayland_output, monitor);
return wayland_output; return wayland_output;
} }
@ -492,7 +456,7 @@ make_output_inert (gpointer key,
g_signal_emit (wayland_output, signals[OUTPUT_DESTROYED], 0); g_signal_emit (wayland_output, signals[OUTPUT_DESTROYED], 0);
wayland_output->logical_monitor = NULL; wayland_output->monitor = NULL;
make_output_resources_inert (wayland_output); make_output_resources_inert (wayland_output);
} }
@ -508,42 +472,42 @@ meta_wayland_compositor_update_outputs (MetaWaylandCompositor *compositor,
MetaMonitorManager *monitor_manager) MetaMonitorManager *monitor_manager)
{ {
GHashTable *new_table; GHashTable *new_table;
GList *logical_monitors, *l; GList *monitors, *l;
logical_monitors = monitors = meta_monitor_manager_get_monitors (monitor_manager);
meta_monitor_manager_get_logical_monitors (monitor_manager); new_table = g_hash_table_new_full (meta_monitor_spec_hash,
new_table = g_hash_table_new_full (g_int64_hash, g_int64_equal, NULL, (GEqualFunc) meta_monitor_spec_equals,
(GDestroyNotify) meta_monitor_spec_free,
g_object_unref); g_object_unref);
for (l = logical_monitors; l; l = l->next) for (l = monitors; l; l = l->next)
{ {
MetaLogicalMonitor *logical_monitor = l->data; MetaMonitor *monitor = l->data;
MetaMonitorSpec *monitor_spec = meta_monitor_get_spec (monitor);
MetaWaylandOutput *wayland_output = NULL; MetaWaylandOutput *wayland_output = NULL;
if (logical_monitor->winsys_id == 0) if (!meta_monitor_is_active (monitor))
continue; continue;
wayland_output = g_hash_table_lookup (compositor->outputs, if (compositor->outputs)
&logical_monitor->winsys_id); wayland_output = g_hash_table_lookup (compositor->outputs, monitor_spec);
if (wayland_output) if (wayland_output)
{ g_hash_table_steal (compositor->outputs, monitor_spec);
g_hash_table_steal (compositor->outputs,
&logical_monitor->winsys_id);
}
else else
{ wayland_output = meta_wayland_output_new (compositor, monitor);
wayland_output = meta_wayland_output_new (compositor, logical_monitor);
}
wayland_output_update_for_output (wayland_output, logical_monitor); wayland_output_update_for_output (wayland_output, monitor);
g_hash_table_insert (new_table, g_hash_table_insert (new_table,
&wayland_output->winsys_id, meta_monitor_spec_clone (monitor_spec),
wayland_output); wayland_output);
} }
if (compositor->outputs)
{
g_hash_table_foreach (compositor->outputs, make_output_inert, NULL); g_hash_table_foreach (compositor->outputs, make_output_inert, NULL);
g_timeout_add_seconds (10, delayed_destroy_outputs, compositor->outputs); g_timeout_add_seconds (10, delayed_destroy_outputs, compositor->outputs);
}
return new_table; return new_table;
} }
@ -626,19 +590,21 @@ static const struct zxdg_output_v1_interface
static void static void
send_xdg_output_events (struct wl_resource *resource, send_xdg_output_events (struct wl_resource *resource,
MetaWaylandOutput *wayland_output, MetaWaylandOutput *wayland_output,
MetaLogicalMonitor *logical_monitor, MetaMonitor *monitor,
gboolean need_all_events, gboolean need_all_events,
gboolean *pending_done_event) gboolean *pending_done_event)
{ {
MetaRectangle new_layout; MetaRectangle new_layout;
MetaRectangle old_layout; MetaRectangle old_layout;
MetaLogicalMonitor *logical_monitor;
MetaLogicalMonitor *old_logical_monitor; MetaLogicalMonitor *old_logical_monitor;
MetaMonitor *monitor;
gboolean need_done; gboolean need_done;
int version; int version;
need_done = FALSE; need_done = FALSE;
old_logical_monitor = wayland_output->logical_monitor; logical_monitor = meta_monitor_get_logical_monitor (monitor);
old_logical_monitor =
meta_monitor_get_logical_monitor (wayland_output->monitor);
old_layout = meta_logical_monitor_get_layout (old_logical_monitor); old_layout = meta_logical_monitor_get_layout (old_logical_monitor);
new_layout = meta_logical_monitor_get_layout (logical_monitor); new_layout = meta_logical_monitor_get_layout (logical_monitor);
@ -663,7 +629,6 @@ send_xdg_output_events (struct wl_resource *resource,
} }
version = wl_resource_get_version (resource); version = wl_resource_get_version (resource);
monitor = pick_main_monitor (logical_monitor);
if (need_all_events && version >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION) if (need_all_events && version >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION)
{ {
@ -712,12 +677,12 @@ meta_xdg_output_manager_get_xdg_output (struct wl_client *client,
wayland_output->xdg_output_resources = wayland_output->xdg_output_resources =
g_list_prepend (wayland_output->xdg_output_resources, xdg_output_resource); g_list_prepend (wayland_output->xdg_output_resources, xdg_output_resource);
if (!wayland_output->logical_monitor) if (!wayland_output->monitor)
return; return;
send_xdg_output_events (xdg_output_resource, send_xdg_output_events (xdg_output_resource,
wayland_output, wayland_output,
wayland_output->logical_monitor, wayland_output->monitor,
TRUE, NULL); TRUE, NULL);
xdg_output_version = wl_resource_get_version (xdg_output_resource); xdg_output_version = wl_resource_get_version (xdg_output_resource);
@ -768,8 +733,6 @@ meta_wayland_outputs_init (MetaWaylandCompositor *compositor)
g_signal_connect (monitors, "monitors-changed-internal", g_signal_connect (monitors, "monitors-changed-internal",
G_CALLBACK (on_monitors_changed), compositor); G_CALLBACK (on_monitors_changed), compositor);
compositor->outputs = g_hash_table_new_full (g_int64_hash, g_int64_equal, NULL,
g_object_unref);
compositor->outputs = meta_wayland_compositor_update_outputs (compositor, monitors); compositor->outputs = meta_wayland_compositor_update_outputs (compositor, monitors);
wl_global_create (compositor->wayland_display, wl_global_create (compositor->wayland_display,

View File

@ -240,7 +240,6 @@ get_output_for_stage_view (MetaWaylandCompositor *compositor,
MetaCrtc *crtc; MetaCrtc *crtc;
MetaOutput *output; MetaOutput *output;
MetaMonitor *monitor; MetaMonitor *monitor;
MetaLogicalMonitor *logical_monitor;
crtc = meta_renderer_view_get_crtc (META_RENDERER_VIEW (stage_view)); crtc = meta_renderer_view_get_crtc (META_RENDERER_VIEW (stage_view));
@ -251,8 +250,8 @@ get_output_for_stage_view (MetaWaylandCompositor *compositor,
output = meta_crtc_get_outputs (crtc)->data; output = meta_crtc_get_outputs (crtc)->data;
monitor = meta_output_get_monitor (output); monitor = meta_output_get_monitor (output);
logical_monitor = meta_monitor_get_logical_monitor (monitor); return g_hash_table_lookup (compositor->outputs,
return g_hash_table_lookup (compositor->outputs, &logical_monitor->winsys_id); meta_monitor_get_spec (monitor));
} }
static void static void