[PATCH weston v6 49/73] compositor-drm: move connector fields into drm_head

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


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

Move the connector related fields from drm_output to the drm_head. A
drm_head represents a connector for now.

The code in drm_head_create() to update connector data, monitor
information, etc. is moved into a new function. This will be useful when
DRM-backend starts creating heads for all connectors regardless of their
connection status and will need to update them on hotplug events.

v6:
- adapt to the new places of updating unused_connectors
- free connector in create_output_for_connector() error path

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

diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
index d386a0d2..63295d2a 100644
--- a/libweston/compositor-drm.c
+++ b/libweston/compositor-drm.c
@@ -409,20 +409,22 @@ struct drm_head {
 
 	struct drm_output *output; /* XXX: temporary */
 
+	drmModeConnector *connector;
+	uint32_t connector_id;
+	struct drm_edid edid;
+
+	/* Holds the properties for the connector */
+	struct drm_property_info props_conn[WDRM_CONNECTOR__COUNT];
+
 	struct backlight *backlight;
 };
 
 struct drm_output {
 	struct weston_output base;
-	drmModeConnector *connector;
 
 	uint32_t crtc_id; /* object ID to pass to DRM functions */
 	int pipe; /* index of CRTC in resource array / bitmasks */
-	uint32_t connector_id;
-	struct drm_edid edid;
 
-	/* Holds the properties for the connector */
-	struct drm_property_info props_conn[WDRM_CONNECTOR__COUNT];
 	/* Holds the properties for the CRTC */
 	struct drm_property_info props_crtc[WDRM_CRTC__COUNT];
 
@@ -813,7 +815,7 @@ drm_head_find_by_connector(struct drm_backend *backend, uint32_t connector_id)
 	wl_list_for_each(base,
 			 &backend->compositor->head_list, compositor_link) {
 		head = to_drm_head(base);
-		if (head->output && head->output->connector_id == connector_id)
+		if (head->connector_id == connector_id)
 			return head;
 	}
 
@@ -1836,10 +1838,11 @@ static int
 drm_output_apply_state_legacy(struct drm_output_state *state)
 {
 	struct drm_output *output = state->output;
+	struct drm_head *head = to_drm_head(weston_output_get_first_head(&output->base));
 	struct drm_backend *backend = to_drm_backend(output->base.compositor);
 	struct drm_plane *scanout_plane = output->scanout_plane;
 	struct drm_property_info *dpms_prop =
-		&output->props_conn[WDRM_CONNECTOR_DPMS];
+		&head->props_conn[WDRM_CONNECTOR_DPMS];
 	struct drm_plane_state *scanout_state;
 	struct drm_plane_state *ps;
 	struct drm_plane *p;
@@ -1880,7 +1883,7 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
 		}
 
 		ret = drmModeSetCrtc(backend->drm.fd, output->crtc_id, 0, 0, 0,
-				     &output->connector_id, 0, NULL);
+				     &head->connector_id, 0, NULL);
 		if (ret)
 			weston_log("drmModeSetCrtc failed disabling: %m\n");
 
@@ -1915,7 +1918,7 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
 		ret = drmModeSetCrtc(backend->drm.fd, output->crtc_id,
 				     scanout_state->fb->fb_id,
 				     0, 0,
-				     &output->connector_id, 1,
+				     &head->connector_id, 1,
 				     &mode->mode_info);
 		if (ret) {
 			weston_log("set mode failed: %m\n");
@@ -1988,7 +1991,7 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
 
 	if (dpms_prop->prop_id && state->dpms != output->state_cur->dpms) {
 		ret = drmModeConnectorSetProperty(backend->drm.fd,
-						  output->connector_id,
+						  head->connector_id,
 						  dpms_prop->prop_id,
 						  state->dpms);
 		if (ret) {
@@ -2024,16 +2027,16 @@ crtc_add_prop(drmModeAtomicReq *req, struct drm_output *output,
 }
 
 static int
-connector_add_prop(drmModeAtomicReq *req, struct drm_output *output,
+connector_add_prop(drmModeAtomicReq *req, struct drm_head *head,
 		   enum wdrm_connector_property prop, uint64_t val)
 {
-	struct drm_property_info *info = &output->props_conn[prop];
+	struct drm_property_info *info = &head->props_conn[prop];
 	int ret;
 
 	if (info->prop_id == 0)
 		return -1;
 
-	ret = drmModeAtomicAddProperty(req, output->connector_id,
+	ret = drmModeAtomicAddProperty(req, head->connector_id,
 				       info->prop_id, val);
 	return (ret <= 0) ? -1 : 0;
 }
@@ -2077,6 +2080,7 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
 			      uint32_t *flags)
 {
 	struct drm_output *output = state->output;
+	struct drm_head *head = to_drm_head(weston_output_get_first_head(&output->base));
 	struct drm_backend *backend = to_drm_backend(output->base.compositor);
 	struct drm_plane_state *plane_state;
 	struct drm_mode *current_mode = to_drm_mode(output->base.current_mode);
@@ -2093,13 +2097,12 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
 		ret |= crtc_add_prop(req, output, WDRM_CRTC_MODE_ID,
 				     current_mode->blob_id);
 		ret |= crtc_add_prop(req, output, WDRM_CRTC_ACTIVE, 1);
-		ret |= connector_add_prop(req, output, WDRM_CONNECTOR_CRTC_ID,
+		ret |= connector_add_prop(req, head, WDRM_CONNECTOR_CRTC_ID,
 					  output->crtc_id);
 	} else {
 		ret |= crtc_add_prop(req, output, WDRM_CRTC_MODE_ID, 0);
 		ret |= crtc_add_prop(req, output, WDRM_CRTC_ACTIVE, 0);
-		ret |= connector_add_prop(req, output, WDRM_CONNECTOR_CRTC_ID,
-					  0);
+		ret |= connector_add_prop(req, head, WDRM_CONNECTOR_CRTC_ID, 0);
 	}
 
 	if (ret != 0) {
@@ -4314,8 +4317,7 @@ edid_parse(struct drm_edid *edid, const uint8_t *data, size_t length)
 
 /** Parse monitor make, model and serial from EDID
  *
- * \param b The backend instance.
- * \param output The output whose \c drm_edid to fill in.
+ * \param head The head whose \c drm_edid to fill in.
  * \param props The DRM connector properties to get the EDID from.
  * \param make[out] The monitor make (PNP ID).
  * \param model[out] The monitor model (name).
@@ -4324,10 +4326,10 @@ edid_parse(struct drm_edid *edid, const uint8_t *data, size_t length)
  * Each of \c *make, \c *model and \c *serial_number are set only if the
  * information is found in the EDID. The pointers they are set to must not
  * be free()'d explicitly, instead they get implicitly freed when the
- * \c drm_output is destroyed.
+ * \c drm_head is destroyed.
  */
 static void
-find_and_parse_output_edid(struct drm_backend *b, struct drm_output *output,
+find_and_parse_output_edid(struct drm_head *head,
 			   drmModeObjectPropertiesPtr props,
 			   const char **make,
 			   const char **model,
@@ -4338,29 +4340,29 @@ find_and_parse_output_edid(struct drm_backend *b, struct drm_output *output,
 	int rc;
 
 	blob_id =
-		drm_property_get_value(&output->props_conn[WDRM_CONNECTOR_EDID],
+		drm_property_get_value(&head->props_conn[WDRM_CONNECTOR_EDID],
 				       props, 0);
 	if (!blob_id)
 		return;
 
-	edid_blob = drmModeGetPropertyBlob(b->drm.fd, blob_id);
+	edid_blob = drmModeGetPropertyBlob(head->backend->drm.fd, blob_id);
 	if (!edid_blob)
 		return;
 
-	rc = edid_parse(&output->edid,
+	rc = edid_parse(&head->edid,
 			edid_blob->data,
 			edid_blob->length);
 	if (!rc) {
 		weston_log("EDID data '%s', '%s', '%s'\n",
-			   output->edid.pnp_id,
-			   output->edid.monitor_name,
-			   output->edid.serial_number);
-		if (output->edid.pnp_id[0] != '\0')
-			*make = output->edid.pnp_id;
-		if (output->edid.monitor_name[0] != '\0')
-			*model = output->edid.monitor_name;
-		if (output->edid.serial_number[0] != '\0')
-			*serial_number = output->edid.serial_number;
+			   head->edid.pnp_id,
+			   head->edid.monitor_name,
+			   head->edid.serial_number);
+		if (head->edid.pnp_id[0] != '\0')
+			*make = head->edid.pnp_id;
+		if (head->edid.monitor_name[0] != '\0')
+			*model = head->edid.monitor_name;
+		if (head->edid.serial_number[0] != '\0')
+			*serial_number = head->edid.serial_number;
 	}
 	drmModeFreePropertyBlob(edid_blob);
 }
@@ -4587,11 +4589,12 @@ drm_output_set_mode(struct weston_output *base,
 {
 	struct drm_output *output = to_drm_output(base);
 	struct drm_backend *b = to_drm_backend(base->compositor);
+	struct drm_head *head = to_drm_head(weston_output_get_first_head(base));
 
 	struct drm_mode *current;
 	drmModeModeInfo crtc_mode;
 
-	if (connector_get_current_mode(output->connector, b->drm.fd, &crtc_mode) < 0)
+	if (connector_get_current_mode(head->connector, b->drm.fd, &crtc_mode) < 0)
 		return -1;
 
 	current = drm_output_choose_initial_mode(b, output, mode, modeline, &crtc_mode);
@@ -4806,11 +4809,11 @@ drm_output_enable(struct weston_output *base)
 				      &output->scanout_plane->base,
 				      &b->compositor->primary_plane);
 
-	wl_array_remove_uint32(&b->unused_connectors, output->connector_id);
+	wl_array_remove_uint32(&b->unused_connectors, head->connector_id);
 	wl_array_remove_uint32(&b->unused_crtcs, output->crtc_id);
 
 	weston_log("Output %s, (connector %d, crtc %d)\n",
-		   output->base.name, output->connector_id, output->crtc_id);
+		   output->base.name, head->connector_id, output->crtc_id);
 	wl_list_for_each(m, &output->base.mode_list, link)
 		weston_log_continue(STAMP_SPACE "mode %dx%d@%.1f%s%s%s\n",
 				    m->width, m->height, m->refresh / 1000.0,
@@ -4818,7 +4821,7 @@ drm_output_enable(struct weston_output *base)
 				    ", preferred" : "",
 				    m->flags & WL_OUTPUT_MODE_CURRENT ?
 				    ", current" : "",
-				    output->connector->count_modes == 0 ?
+				    head->connector->count_modes == 0 ?
 				    ", built-in" : "");
 
 	return 0;
@@ -4831,6 +4834,7 @@ static void
 drm_output_deinit(struct weston_output *base)
 {
 	struct drm_output *output = to_drm_output(base);
+	struct drm_head *head = to_drm_head(weston_output_get_first_head(base));
 	struct drm_backend *b = to_drm_backend(base->compositor);
 	uint32_t *unused;
 
@@ -4856,7 +4860,7 @@ drm_output_deinit(struct weston_output *base)
 	}
 
 	unused = wl_array_add(&b->unused_connectors, sizeof(*unused));
-	*unused = output->connector_id;
+	*unused = head->connector_id;
 	unused = wl_array_add(&b->unused_crtcs, sizeof(*unused));
 	*unused = output->crtc_id;
 
@@ -4893,9 +4897,6 @@ drm_output_destroy(struct weston_output *base)
 
 	drm_output_fini_crtc(output);
 
-	drm_property_info_free(output->props_conn, WDRM_CONNECTOR__COUNT);
-	drmModeFreeConnector(output->connector);
-
 	assert(!output->state_last);
 	drm_output_state_free(output->state_cur);
 
@@ -4985,6 +4986,62 @@ drm_backend_update_unused_outputs(struct drm_backend *b, drmModeRes *resources)
 	}
 }
 
+/** Replace connector data and monitor information
+ *
+ * @param head The head to update.
+ * @param connector The connector data to be owned by the head, must match
+ * the head's connector ID.
+ * @return 0 on success, -1 on failure.
+ *
+ * Takes ownership of @c connector on success, not on failure.
+ *
+ * May schedule a heads changed call.
+ */
+static int
+drm_head_assign_connector_info(struct drm_head *head,
+			       drmModeConnector *connector)
+{
+	drmModeObjectProperties *props;
+	const char *make = "unknown";
+	const char *model = "unknown";
+	const char *serial_number = "unknown";
+
+	assert(connector);
+	assert(head->connector_id == connector->connector_id);
+
+	props = drmModeObjectGetProperties(head->backend->drm.fd,
+					   head->connector_id,
+					   DRM_MODE_OBJECT_CONNECTOR);
+	if (!props) {
+		weston_log("Error: failed to get connector '%s' properties\n",
+			   head->base.name);
+		return -1;
+	}
+
+	if (head->connector)
+		drmModeFreeConnector(head->connector);
+	head->connector = connector;
+
+	drm_property_info_populate(head->backend, connector_props,
+				   head->props_conn,
+				   WDRM_CONNECTOR__COUNT, props);
+	find_and_parse_output_edid(head, props, &make, &model, &serial_number);
+	weston_head_set_monitor_strings(&head->base, make, model, serial_number);
+	weston_head_set_subpixel(&head->base,
+		drm_subpixel_to_wayland(head->connector->subpixel));
+
+	weston_head_set_physical_size(&head->base, head->connector->mmWidth,
+				      head->connector->mmHeight);
+
+	drmModeFreeObjectProperties(props);
+
+	/* Unknown connection status is assumed disconnected. */
+	weston_head_set_connection_status(&head->base,
+			head->connector->connection == DRM_MODE_CONNECTED);
+
+	return 0;
+}
+
 /**
  * Create a Weston head for a connector
  *
@@ -5019,23 +5076,29 @@ drm_head_create(struct drm_backend *backend, uint32_t connector_id,
 	weston_head_init(&head->base, name);
 	free(name);
 
+	head->connector_id = connector_id;
 	head->backend = backend;
 
 	head->backlight = backlight_init(drm_device, connector->connector_type);
 
-	/* Unknown connection status is assumed disconnected. */
-	weston_head_set_connection_status(&head->base,
-				connector->connection == DRM_MODE_CONNECTED);
+	if (drm_head_assign_connector_info(head, connector) < 0)
+		goto err_init;
+
+	if (head->connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
+	    head->connector->connector_type == DRM_MODE_CONNECTOR_eDP)
+		weston_head_set_internal(&head->base);
 
 	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.name, head->connector_id,
 		   head->base.connected ? "connected" : "disconnected");
 
 	return head;
 
+err_init:
+	weston_head_release(&head->base);
+
 err_alloc:
 	if (connector)
 		drmModeFreeConnector(connector);
@@ -5050,6 +5113,9 @@ drm_head_destroy(struct drm_head *head)
 {
 	weston_head_release(&head->base);
 
+	drm_property_info_free(head->props_conn, WDRM_CONNECTOR__COUNT);
+	drmModeFreeConnector(head->connector);
+
 	if (head->backlight)
 		backlight_destroy(head->backlight);
 
@@ -5077,31 +5143,21 @@ create_output_for_connector(struct drm_backend *b,
 {
 	struct drm_output *output;
 	struct drm_head *head;
-	drmModeObjectPropertiesPtr props;
 	struct drm_mode *drm_mode;
-	char *name;
-	const char *make = "unknown";
-	const char *model = "unknown";
-	const char *serial_number = "unknown";
 	int i;
 
 	output = zalloc(sizeof *output);
 	if (output == NULL)
 		goto err_init;
 
-	output->connector = connector;
-	output->connector_id = connector->connector_id;
-
-	name = make_connector_name(connector);
-	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;
 
+	weston_output_init(&output->base, b->compositor, head->base.name);
+
 	output->base.enable = drm_output_enable;
 	output->base.destroy = drm_output_destroy;
 	output->base.disable = drm_output_disable;
@@ -5113,36 +5169,13 @@ create_output_for_connector(struct drm_backend *b,
 	if (drm_output_init_crtc(output, resources, connector) < 0)
 		goto err_output;
 
-	props = drmModeObjectGetProperties(b->drm.fd, connector->connector_id,
-					   DRM_MODE_OBJECT_CONNECTOR);
-	if (!props) {
-		weston_log("failed to get connector properties\n");
-		goto err_output;
-	}
-	drm_property_info_populate(b, connector_props, output->props_conn,
-				   WDRM_CONNECTOR__COUNT, props);
-	find_and_parse_output_edid(b, output, props,
-				   &make, &model, &serial_number);
-	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->base);
-
 	if (drm_output_init_gamma_size(output) < 0)
 		goto err_output;
 
-	weston_head_set_physical_size(&head->base, output->connector->mmWidth,
-				      output->connector->mmHeight);
-
 	output->state_cur = drm_output_state_alloc(output, NULL);
 
-	for (i = 0; i < output->connector->count_modes; i++) {
-		drm_mode = drm_output_add_mode(output, &output->connector->modes[i]);
+	for (i = 0; i < head->connector->count_modes; i++) {
+		drm_mode = drm_output_add_mode(output, &head->connector->modes[i]);
 		if (!drm_mode) {
 			weston_log("failed to add mode\n");
 			goto err_output;
@@ -5151,13 +5184,14 @@ create_output_for_connector(struct drm_backend *b,
 
 	weston_compositor_add_pending_output(&output->base, b->compositor);
 
+	/* drm_head_create() made its own connector */
+	drmModeFreeConnector(connector);
+
 	return 0;
 
 err_output:
 	drm_head_destroy(head);
 	drm_output_destroy(&output->base);
-	return -1;
-	/* no fallthrough! */
 
 err_init:
 	drmModeFreeConnector(connector);
@@ -5268,7 +5302,7 @@ update_outputs(struct drm_backend *b, struct udev_device *drm_device)
 			continue;
 
 		for (i = 0; i < resources->count_connectors; i++) {
-			if (connected[i] == head->output->connector_id) {
+			if (connected[i] == head->connector_id) {
 				disconnected = false;
 				break;
 			}
@@ -5277,7 +5311,7 @@ update_outputs(struct drm_backend *b, struct udev_device *drm_device)
 		if (!disconnected)
 			continue;
 
-		weston_log("connector %d disconnected\n", head->output->connector_id);
+		weston_log("connector %d disconnected\n", head->connector_id);
 		drm_output_destroy(&head->output->base);
 	}
 
-- 
2.13.6



More information about the wayland-devel mailing list