[PATCH weston v3 36/36] compositor-wayland: migrate to head-based output API

Pekka Paalanen ppaalanen at gmail.com
Tue Oct 31 11:48:46 UTC 2017


From: Pekka Paalanen <pekka.paalanen at collabora.co.uk>

Follow the standard pattern used in the headless and x11 backend
migration, but also cater for the two other backend modes: --sprawl or
fullscreen-shell, and --fullscreen.

Stops relying on the implicit weston_output::head.

Unlike other backends, this uses the attach_head hook to do the
required head setup that is not possible to do without an output, but
must be done before weston_output_enable(). This also requires the
detach_head hook for the one case where the user attaches a --fullscreen
head and then detaches it without enabling the output.

It is a little awkward to fully initialize heads as late as attach, but
aside from the --sprawl/fullscreen-shell case, there is not really a way
to know the head properties without creating the parent wl_surface and
configuring it.

Heads/outputs created for parent outputs now have distinct names instead
of all being called "wlparent".

Signed-off-by: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
---
 libweston/compositor-wayland.c | 239 ++++++++++++++++++++++++++++++-----------
 1 file changed, 178 insertions(+), 61 deletions(-)

diff --git a/libweston/compositor-wayland.c b/libweston/compositor-wayland.c
index b2e96d0e..6fb9ef91 100644
--- a/libweston/compositor-wayland.c
+++ b/libweston/compositor-wayland.c
@@ -136,7 +136,7 @@ struct wayland_output {
 
 struct wayland_parent_output {
 	struct wayland_backend *backend;	/**< convenience */
-	struct wayland_output *output;
+	struct wayland_head *head;
 	struct wl_list link;
 
 	struct wl_output *global;
@@ -160,6 +160,11 @@ struct wayland_parent_output {
 	struct weston_mode *current_mode;
 };
 
+struct wayland_head {
+	struct weston_head base;
+	struct wayland_parent_output *parent_output;
+};
+
 struct wayland_shm_buffer {
 	struct wayland_output *output;
 	struct wl_list link;
@@ -209,6 +214,12 @@ struct wayland_input {
 
 struct gl_renderer_interface *gl_renderer;
 
+static inline struct wayland_head *
+to_wayland_head(struct weston_head *base)
+{
+	return container_of(base, struct wayland_head, base);
+}
+
 static inline struct wayland_output *
 to_wayland_output(struct weston_output *base)
 {
@@ -1274,9 +1285,59 @@ err_output:
 	return -1;
 }
 
-static struct wayland_output *
-wayland_output_create_common(struct weston_compositor *compositor,
-			     const char *name)
+static int
+wayland_output_setup_for_parent_output(struct wayland_output *output,
+				       struct wayland_parent_output *poutput);
+
+static int
+wayland_output_setup_fullscreen(struct wayland_output *output,
+				struct wayland_head *head);
+
+static int
+wayland_output_attach_head(struct weston_output *output_base,
+			   struct weston_head *head_base)
+{
+	struct wayland_backend *b = to_wayland_backend(output_base->compositor);
+	struct wayland_output *output = to_wayland_output(output_base);
+	struct wayland_head *head = to_wayland_head(head_base);
+
+	if (!wl_list_empty(&output->base.head_list))
+		return -1;
+
+	if (head->parent_output) {
+		if (wayland_output_setup_for_parent_output(output,
+							   head->parent_output) < 0)
+			return -1;
+	} else if (b->fullscreen) {
+		if (wayland_output_setup_fullscreen(output, head) < 0)
+			return -1;
+	} else {
+		/* A floating window, nothing to do. */
+	}
+
+	return 0;
+}
+
+static void
+wayland_output_detach_head(struct weston_output *output_base,
+			   struct weston_head *head)
+{
+	struct wayland_output *output = to_wayland_output(output_base);
+
+	/* Rely on the disable hook if the output was enabled. We do not
+	 * support cloned heads, so detaching is guaranteed to disable the
+	 * output.
+	 */
+	if (output->base.enabled)
+		return;
+
+	/* undo setup fullscreen */
+	if (output->parent.surface)
+		wayland_backend_destroy_output_surface(output);
+}
+
+static struct weston_output *
+wayland_output_create(struct weston_compositor *compositor, const char *name)
 {
 	struct wayland_output *output;
 	char *title;
@@ -1301,29 +1362,87 @@ wayland_output_create_common(struct weston_compositor *compositor,
 	output->base.destroy = wayland_output_destroy;
 	output->base.disable = wayland_output_disable;
 	output->base.enable = wayland_output_enable;
+	output->base.attach_head = wayland_output_attach_head;
+	output->base.detach_head = wayland_output_detach_head;
+
+	weston_compositor_add_pending_output(&output->base, compositor);
+
+	return &output->base;
+}
+
+static struct wayland_head *
+wayland_head_create(struct weston_compositor *compositor, const char *name)
+{
+	struct wayland_head *head;
+
+	assert(name);
+
+	head = zalloc(sizeof *head);
+	if (!head)
+		return NULL;
+
+	weston_head_init(&head->base, name);
+	weston_head_set_connection_status(&head->base, true);
+	weston_compositor_add_head(compositor, &head->base);
 
-	return output;
+	return head;
 }
 
 static int
-wayland_output_create(struct weston_compositor *compositor, const char *name)
+wayland_head_create_windowed(struct weston_compositor *compositor,
+			     const char *name)
 {
-	struct wayland_output *output;
+	 if (!wayland_head_create(compositor, name))
+		return -1;
 
-	output = wayland_output_create_common(compositor, name);
-	if (!output)
+	return 0;
+}
+
+static int
+wayland_head_create_for_parent_output(struct weston_compositor *compositor,
+				      struct wayland_parent_output *poutput)
+{
+	struct wayland_head *head;
+	char name[100];
+	int ret;
+
+	ret = snprintf(name, sizeof(name), "wlparent-%d", poutput->id);
+	if (ret < 1 || (unsigned)ret >= sizeof(name))
 		return -1;
 
-	weston_compositor_add_pending_output(&output->base, compositor);
+	head = wayland_head_create(compositor, name);
+	if (!head)
+		return -1;
+
+	assert(!poutput->head);
+	head->parent_output = poutput;
+	poutput->head = head;
+
+	weston_head_set_monitor_strings(&head->base,
+					poutput->physical.make,
+					poutput->physical.model, NULL);
+	weston_head_set_physical_size(&head->base,
+				      poutput->physical.width,
+				      poutput->physical.height);
 
 	return 0;
 }
 
+static void
+wayland_head_destroy(struct wayland_head *head)
+{
+	if (head->parent_output)
+		head->parent_output->head = NULL;
+
+	weston_head_release(&head->base);
+	free(head);
+}
+
 static int
 wayland_output_set_size(struct weston_output *base, int width, int height)
 {
 	struct wayland_output *output = to_wayland_output(base);
-	struct weston_head *head = &output->base.head;
+	struct weston_head *head;
 	int output_width, output_height;
 
 	/* We can only be called once. */
@@ -1344,6 +1463,13 @@ wayland_output_set_size(struct weston_output *base, int width, int height)
 		return -1;
 	}
 
+	wl_list_for_each(head, &output->base.head_list, output_link) {
+		weston_head_set_monitor_strings(head, "wayland", "none", NULL);
+
+		/* XXX: Calculate proper size. */
+		weston_head_set_physical_size(head, width, height);
+	}
+
 	output_width = width * output->base.scale;
 	output_height = height * output->base.scale;
 
@@ -1357,25 +1483,15 @@ wayland_output_set_size(struct weston_output *base, int width, int height)
 
 	output->base.current_mode = &output->mode;
 
-	weston_head_set_monitor_strings(head, "wayland", "none", NULL);
-
-	/* XXX: Calculate proper size. */
-	weston_head_set_physical_size(head, width, height);
-
 	return 0;
 }
 
 static int
-wayland_output_create_for_parent_output(struct wayland_backend *b,
-					struct wayland_parent_output *poutput)
+wayland_output_setup_for_parent_output(struct wayland_output *output,
+				       struct wayland_parent_output *poutput)
 {
-	struct wayland_output *output;
 	struct weston_mode *mode;
 
-	output = wayland_output_create_common(b->compositor, "wlparent");
-	if (!output)
-		return -1;
-
 	if (poutput->current_mode) {
 		mode = poutput->current_mode;
 	} else if (poutput->preferred_mode) {
@@ -1385,7 +1501,7 @@ wayland_output_create_for_parent_output(struct wayland_backend *b,
 				    struct weston_mode, link);
 	} else {
 		weston_log("No valid modes found. Skipping output.\n");
-		goto out;
+		return -1;
 	}
 
 	output->base.scale = 1;
@@ -1393,13 +1509,6 @@ wayland_output_create_for_parent_output(struct wayland_backend *b,
 
 	output->parent.output = poutput->global;
 
-	weston_head_set_monitor_strings(&output->base.head,
-					poutput->physical.make,
-					poutput->physical.model, NULL);
-	weston_head_set_physical_size(&output->base.head,
-				      poutput->physical.width,
-				      poutput->physical.height);
-
 	wl_list_insert_list(&output->base.mode_list, &poutput->mode_list);
 	wl_list_init(&poutput->mode_list);
 
@@ -1409,33 +1518,21 @@ wayland_output_create_for_parent_output(struct wayland_backend *b,
 
 	/* output->mode is unused in this path. */
 
-	weston_compositor_add_pending_output(&output->base, b->compositor);
-
 	return 0;
-
-out:
-	weston_output_release(&output->base);
-	free(output->title);
-	free(output);
-
-	return -1;
 }
 
 static int
-wayland_output_create_fullscreen(struct wayland_backend *b)
+wayland_output_setup_fullscreen(struct wayland_output *output,
+				struct wayland_head *head)
 {
-	struct wayland_output *output;
+	struct wayland_backend *b = to_wayland_backend(output->base.compositor);
 	int width = 0, height = 0;
 
-	output = wayland_output_create_common(b->compositor, "wayland-fullscreen");
-	if (!output)
-		return -1;
-
 	output->base.scale = 1;
 	output->base.transform = WL_OUTPUT_TRANSFORM_NORMAL;
 
 	if (wayland_backend_create_output_surface(output) < 0)
-		goto err_surface;
+		return -1;
 
 	/* What should size be set if conditional is false? */
 	if (b->parent.xdg_shell || b->parent.shell) {
@@ -1455,16 +1552,15 @@ wayland_output_create_fullscreen(struct wayland_backend *b)
 	if (wayland_output_set_size(&output->base, width, height) < 0)
 		goto err_set_size;
 
-	weston_compositor_add_pending_output(&output->base, b->compositor);
+	/* The head is not attached yet, so set_size did not set these. */
+	weston_head_set_monitor_strings(&head->base, "wayland", "none", NULL);
+	/* XXX: Calculate proper size. */
+	weston_head_set_physical_size(&head->base, width, height);
 
 	return 0;
 
 err_set_size:
 	wayland_backend_destroy_output_surface(output);
-err_surface:
-	weston_output_release(&output->base);
-	free(output->title);
-	free(output);
 
 	return -1;
 }
@@ -2248,16 +2344,32 @@ find_mode(struct wl_list *list, int32_t width, int32_t height, uint32_t refresh)
 	return mode;
 }
 
+static struct weston_output *
+wayland_parent_output_get_enabled_output(struct wayland_parent_output *poutput)
+{
+	struct wayland_head *head = poutput->head;
+
+	if (!head)
+		return NULL;
+
+	if (!weston_head_is_enabled(&head->base))
+		return NULL;
+
+	return weston_head_get_output(&head->base);
+}
+
 static void
 wayland_parent_output_mode(void *data, struct wl_output *wl_output_proxy,
 			   uint32_t flags, int32_t width, int32_t height,
 			   int32_t refresh)
 {
 	struct wayland_parent_output *output = data;
+	struct weston_output *enabled_output;
 	struct weston_mode *mode;
 
-	if (output->output) {
-		mode = find_mode(&output->output->base.mode_list,
+	enabled_output = wayland_parent_output_get_enabled_output(output);
+	if (enabled_output) {
+		mode = find_mode(&enabled_output->mode_list,
 				 width, height, refresh);
 		if (!mode)
 			return;
@@ -2291,7 +2403,7 @@ output_sync_callback(void *data, struct wl_callback *callback, uint32_t unused)
 
 	assert(output->backend->sprawl_across_outputs);
 
-	wayland_output_create_for_parent_output(output->backend, output);
+	wayland_head_create_for_parent_output(output->backend->compositor, output);
 }
 
 static const struct wl_callback_listener output_sync_listener = {
@@ -2339,8 +2451,8 @@ wayland_parent_output_destroy(struct wayland_parent_output *output)
 	if (output->sync_cb)
 		wl_callback_destroy(output->sync_cb);
 
-	if (output->output)
-		wayland_output_destroy(&output->output->base);
+	if (output->head)
+		wayland_head_destroy(output->head);
 
 	wl_output_destroy(output->global);
 	free(output->physical.make);
@@ -2450,11 +2562,15 @@ static void
 wayland_destroy(struct weston_compositor *ec)
 {
 	struct wayland_backend *b = to_wayland_backend(ec);
+	struct weston_head *base, *next;
 
 	wl_event_source_remove(b->parent.wl_source);
 
 	weston_compositor_shutdown(ec);
 
+	wl_list_for_each_safe(base, next, &ec->head_list, compositor_link)
+		wayland_head_destroy(to_wayland_head(base));
+
 	if (b->parent.shm)
 		wl_shm_destroy(b->parent.shm);
 
@@ -2610,6 +2726,7 @@ wayland_backend_create(struct weston_compositor *compositor,
 
 	b->base.destroy = wayland_destroy;
 	b->base.restore = wayland_restore;
+	b->base.create_output = wayland_output_create;
 
 	loop = wl_display_get_event_loop(compositor->wl_display);
 
@@ -2654,7 +2771,7 @@ wayland_backend_destroy(struct wayland_backend *b)
 
 static const struct weston_windowed_output_api windowed_api = {
 	wayland_output_set_size,
-	wayland_output_create,
+	wayland_head_create_windowed,
 };
 
 static void
@@ -2691,14 +2808,14 @@ weston_backend_init(struct weston_compositor *compositor,
 		wl_display_roundtrip(b->parent.wl_display);
 
 		wl_list_for_each(poutput, &b->parent.output_list, link)
-			wayland_output_create_for_parent_output(b, poutput);
+			wayland_head_create_for_parent_output(compositor, poutput);
 
 		return 0;
 	}
 
 	if (new_config.fullscreen) {
-		if (wayland_output_create_fullscreen(b) < 0) {
-			weston_log("Unable to create a fullscreen output.\n");
+		if (!wayland_head_create(compositor, "wayland-fullscreen")) {
+			weston_log("Unable to create a fullscreen head.\n");
 			goto err_outputs;
 		}
 
-- 
2.13.6



More information about the wayland-devel mailing list