[PATCH weston v6 38/73] compositor-drm: start migration to head-based output API

Pekka Paalanen ppaalanen at gmail.com
Fri Feb 16 14:57:23 UTC 2018


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

Hook up the libweston facing head-based output API by introducing struct
drm_head, but leave it as a fake so that members can be migrated in
pieces in follow-up patches.

The DRM backend continues to create an output for each connected
connector only, and during output creation it also creates a drm_head
for it. This allows it to pretend it supports the head-based output API
as long as there is only one head per output ever attached.

create_output callback is fake, it will only look up the existing
drm_output by the head name.

Clones are not yet supported, hence max is defined to 1.

This unfortunately introduces some temporary code that will be revomed
later, but seems to be necessary to avoid a single big patch.

v6:
- add missing drm_head_destroy() call

Signed-off-by: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
---
 libweston/compositor-drm.c | 135 +++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 129 insertions(+), 6 deletions(-)

diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
index 5ce0255b..58aae1ac 100644
--- a/libweston/compositor-drm.c
+++ b/libweston/compositor-drm.c
@@ -83,6 +83,8 @@
 #define GBM_BO_USE_CURSOR GBM_BO_USE_CURSOR_64X64
 #endif
 
+#define MAX_CLONED_CONNECTORS 1
+
 /**
  * Represents the values of an enum-type KMS property
  */
@@ -401,6 +403,13 @@ struct drm_plane {
 	uint32_t formats[];
 };
 
+struct drm_head {
+	struct weston_head base;
+	struct drm_backend *backend;
+
+	struct drm_output *output; /* XXX: temporary */
+};
+
 struct drm_output {
 	struct weston_output base;
 	drmModeConnector *connector;
@@ -476,6 +485,12 @@ wl_array_remove_uint32(struct wl_array *array, uint32_t elm)
 	}
 }
 
+static inline struct drm_head *
+to_drm_head(struct weston_head *base)
+{
+	return container_of(base, struct drm_head, base);
+}
+
 static inline struct drm_output *
 to_drm_output(struct weston_output *base)
 {
@@ -4412,6 +4427,16 @@ setup_output_seat_constraint(struct drm_backend *b,
 }
 
 static int
+drm_output_attach_head(struct weston_output *output_base,
+		       struct weston_head *head_base)
+{
+	if (wl_list_length(&output_base->head_list) >= MAX_CLONED_CONNECTORS)
+		return -1;
+
+	return 0;
+}
+
+static int
 parse_gbm_format(const char *s, uint32_t default_value, uint32_t *gbm_format)
 {
 	int ret = 0;
@@ -4829,10 +4854,14 @@ drm_output_deinit(struct weston_output *base)
 }
 
 static void
+drm_head_destroy(struct drm_head *head);
+
+static void
 drm_output_destroy(struct weston_output *base)
 {
 	struct drm_output *output = to_drm_output(base);
 	struct drm_backend *b = to_drm_backend(base->compositor);
+	struct weston_head *head = weston_output_get_first_head(base);
 
 	if (output->page_flip_pending || output->vblank_pending ||
 	    output->atomic_complete_pending) {
@@ -4863,6 +4892,10 @@ drm_output_destroy(struct weston_output *base)
 	drm_output_state_free(output->state_cur);
 
 	free(output);
+
+	/* XXX: temporary */
+	if (head)
+		drm_head_destroy(to_drm_head(head));
 }
 
 static int
@@ -4886,6 +4919,19 @@ drm_output_disable(struct weston_output *base)
 	return 0;
 }
 
+static struct weston_output *
+drm_output_create(struct weston_compositor *compositor, const char *name)
+{
+	struct drm_head *head;
+
+	/* XXX: Temporary until we can have heads without an output */
+	wl_list_for_each(head, &compositor->head_list, base.compositor_link)
+		if (strcmp(name, head->base.name) == 0)
+			return &head->output->base;
+
+	return NULL;
+}
+
 /**
  * Update the list of unused connectors and CRTCs
  *
@@ -4932,6 +4978,71 @@ drm_backend_update_unused_outputs(struct drm_backend *b, drmModeRes *resources)
 }
 
 /**
+ * Create a Weston head for a connector
+ *
+ * Given a DRM connector, create a matching drm_head structure and add it
+ * to Weston's head list.
+ *
+ * @param b Weston backend structure
+ * @param connector_id DRM connector ID for the head
+ * @param drm_device udev device pointer
+ * @returns The new head, or NULL on failure.
+ */
+static struct drm_head *
+drm_head_create(struct drm_backend *backend, uint32_t connector_id,
+		struct udev_device *drm_device)
+{
+	struct drm_head *head;
+	drmModeConnector *connector;
+	char *name;
+
+	head = zalloc(sizeof *head);
+	if (!head)
+		return NULL;
+
+	connector = drmModeGetConnector(backend->drm.fd, connector_id);
+	if (!connector)
+		goto err_alloc;
+
+	name = make_connector_name(connector);
+	if (!name)
+		goto err_alloc;
+
+	weston_head_init(&head->base, name);
+	free(name);
+
+	head->backend = backend;
+
+	/* Unknown connection status is assumed disconnected. */
+	weston_head_set_connection_status(&head->base,
+				connector->connection == DRM_MODE_CONNECTED);
+
+	weston_compositor_add_head(backend->compositor, &head->base);
+	drmModeFreeConnector(connector);
+
+	weston_log("DRM: found head '%s', connector %d %s.\n",
+		   head->base.name, connector_id,
+		   head->base.connected ? "connected" : "disconnected");
+
+	return head;
+
+err_alloc:
+	if (connector)
+		drmModeFreeConnector(connector);
+
+	free(head);
+
+	return NULL;
+}
+
+static void
+drm_head_destroy(struct drm_head *head)
+{
+	weston_head_release(&head->base);
+	free(head);
+}
+
+/**
  * Create a Weston output structure
  *
  * Given a DRM connector, create a matching drm_output structure and add it
@@ -4951,7 +5062,7 @@ create_output_for_connector(struct drm_backend *b,
 			    struct udev_device *drm_device)
 {
 	struct drm_output *output;
-	struct weston_head *head;
+	struct drm_head *head;
 	drmModeObjectPropertiesPtr props;
 	struct drm_mode *drm_mode;
 	char *name;
@@ -4974,9 +5085,16 @@ create_output_for_connector(struct drm_backend *b,
 	weston_output_init(&output->base, b->compositor, name);
 	free(name);
 
+	/* XXX: temporary */
+	head = drm_head_create(b, connector->connector_id, drm_device);
+	if (!head)
+		abort();
+	head->output = output;
+
 	output->base.enable = drm_output_enable;
 	output->base.destroy = drm_output_destroy;
 	output->base.disable = drm_output_disable;
+	output->base.attach_head = drm_output_attach_head;
 
 	output->destroy_pending = 0;
 	output->disable_pending = 0;
@@ -4992,23 +5110,22 @@ create_output_for_connector(struct drm_backend *b,
 	}
 	drm_property_info_populate(b, connector_props, output->props_conn,
 				   WDRM_CONNECTOR__COUNT, props);
-	head = &output->base.head;
 	find_and_parse_output_edid(b, output, props,
 				   &make, &model, &serial_number);
-	weston_head_set_monitor_strings(head, make, model, serial_number);
-	weston_head_set_subpixel(head,
+	weston_head_set_monitor_strings(&head->base, make, model, serial_number);
+	weston_head_set_subpixel(&head->base,
 		drm_subpixel_to_wayland(output->connector->subpixel));
 
 	drmModeFreeObjectProperties(props);
 
 	if (output->connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
 	    output->connector->connector_type == DRM_MODE_CONNECTOR_eDP)
-		weston_head_set_internal(head);
+		weston_head_set_internal(&head->base);
 
 	if (drm_output_init_gamma_size(output) < 0)
 		goto err_output;
 
-	weston_head_set_physical_size(head, output->connector->mmWidth,
+	weston_head_set_physical_size(&head->base, output->connector->mmWidth,
 				      output->connector->mmHeight);
 
 	output->state_cur = drm_output_state_alloc(output, NULL);
@@ -5026,6 +5143,7 @@ create_output_for_connector(struct drm_backend *b,
 	return 0;
 
 err_output:
+	drm_head_destroy(head);
 	drm_output_destroy(&output->base);
 	return -1;
 	/* no fallthrough! */
@@ -5207,6 +5325,7 @@ static void
 drm_destroy(struct weston_compositor *ec)
 {
 	struct drm_backend *b = to_drm_backend(ec);
+	struct weston_head *base, *next;
 
 	udev_input_destroy(&b->input);
 
@@ -5219,6 +5338,9 @@ drm_destroy(struct weston_compositor *ec)
 
 	weston_compositor_shutdown(ec);
 
+	wl_list_for_each_safe(base, next, &ec->head_list, compositor_link)
+		drm_head_destroy(to_drm_head(base));
+
 	if (b->gbm)
 		gbm_device_destroy(b->gbm);
 
@@ -5736,6 +5858,7 @@ drm_backend_create(struct weston_compositor *compositor,
 	b->base.repaint_begin = drm_repaint_begin;
 	b->base.repaint_flush = drm_repaint_flush;
 	b->base.repaint_cancel = drm_repaint_cancel;
+	b->base.create_output = drm_output_create;
 
 	weston_setup_vt_switch_bindings(compositor);
 
-- 
2.13.6



More information about the wayland-devel mailing list