[PATCH v15 01/34] compositor-drm: Track unused connectors and CRTCs

Daniel Stone daniels at collabora.com
Mon Feb 5 18:44:10 UTC 2018


Rather than a more piecemeal approach at backend creation, explicitly
track connectors and CRTCs we do not intend to use, so we can ensure
they are disabled where appropriate.

When we have an updated list of connector and CRTC IDs, we add any which
are not owned by an enabled drm_output to the list. We remove them from
the list when drm_output_repaint() is called for that output, and re-add
them when the output is disabled or destroyed.

Signed-off-by: Daniel Stone <daniels at collabora.com>
---
 libweston/compositor-drm.c | 89 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 88 insertions(+), 1 deletion(-)

diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
index fe59bf52f..f2d99b97f 100644
--- a/libweston/compositor-drm.c
+++ b/libweston/compositor-drm.c
@@ -188,6 +188,10 @@ struct drm_backend {
 
 	void *repaint_data;
 
+	/* Connector and CRTC IDs not used by any enabled output. */
+	struct wl_array unused_connectors;
+	struct wl_array unused_crtcs;
+
 	int cursors_are_broken;
 
 	bool universal_planes;
@@ -386,6 +390,26 @@ static struct gl_renderer_interface *gl_renderer;
 
 static const char default_seat[] = "seat0";
 
+static void
+wl_array_remove_uint32(struct wl_array *array, uint32_t elm)
+{
+	uint32_t *pos, *end;
+
+	end = (uint32_t *) ((char *) array->data + array->size);
+
+	wl_array_for_each(pos, array) {
+		if (*pos != elm)
+			continue;
+
+		array->size -= sizeof(*pos);
+		if (pos + 1 == end)
+			break;
+
+		memmove(pos, pos + 1, (char *) end -  (char *) (pos + 1));
+		break;
+	}
+}
+
 static inline struct drm_output *
 to_drm_output(struct weston_output *base)
 {
@@ -1694,7 +1718,6 @@ drm_output_repaint(struct weston_output *output_base,
 						   pending_state,
 						   DRM_OUTPUT_STATE_CLEAR_PLANES);
 
-
 	/* If disable_planes is set then assign_planes() wasn't
 	 * called for this render, so we could still have a stale
 	 * cursor plane set up.
@@ -1710,6 +1733,10 @@ drm_output_repaint(struct weston_output *output_base,
 	if (!scanout_state || !scanout_state->fb)
 		goto err;
 
+	wl_array_remove_uint32(&backend->unused_connectors,
+			       output->connector_id);
+	wl_array_remove_uint32(&backend->unused_crtcs, output->crtc_id);
+
 	/* The legacy SetCrtc API doesn't allow us to do scaling, and the
 	 * legacy PageFlip API doesn't allow us to do clipping either. */
 	assert(scanout_state->src_x == 0);
@@ -3989,6 +4016,7 @@ drm_output_deinit(struct weston_output *base)
 {
 	struct drm_output *output = to_drm_output(base);
 	struct drm_backend *b = to_drm_backend(base->compositor);
+	uint32_t *unused;
 
 	if (b->use_pixman)
 		drm_output_fini_pixman(output);
@@ -4010,6 +4038,11 @@ drm_output_deinit(struct weston_output *base)
 			drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
 		}
 	}
+
+	unused = wl_array_add(&b->unused_connectors, sizeof(*unused));
+	*unused = output->connector_id;
+	unused = wl_array_add(&b->unused_crtcs, sizeof(*unused));
+	*unused = output->crtc_id;
 }
 
 static void
@@ -4105,6 +4138,51 @@ drm_output_disable(struct weston_output *base)
 	return 0;
 }
 
+/**
+ * Update the list of unused connectors and CRTCs
+ *
+ * This keeps the unused_connectors and unused_crtcs arrays up to date.
+ *
+ * @param b Weston backend structure
+ * @param resources DRM resources for this device
+ */
+static void
+drm_backend_update_unused_outputs(struct drm_backend *b, drmModeRes *resources)
+{
+	int i;
+
+	wl_array_release(&b->unused_connectors);
+	wl_array_init(&b->unused_connectors);
+
+	for (i = 0; i < resources->count_connectors; i++) {
+		struct drm_output *output;
+		uint32_t *connector_id;
+
+		output = drm_output_find_by_connector(b, resources->connectors[i]);
+		if (output && output->base.enabled)
+			continue;
+
+		connector_id = wl_array_add(&b->unused_connectors,
+					    sizeof(*connector_id));
+		*connector_id = resources->connectors[i];
+	}
+
+	wl_array_release(&b->unused_crtcs);
+	wl_array_init(&b->unused_crtcs);
+
+	for (i = 0; i < resources->count_crtcs; i++) {
+		struct drm_output *output;
+		uint32_t *crtc_id;
+
+		output = drm_output_find_by_crtc(b, resources->crtcs[i]);
+		if (output && output->base.enabled)
+			continue;
+
+		crtc_id = wl_array_add(&b->unused_crtcs, sizeof(*crtc_id));
+		*crtc_id = resources->crtcs[i];
+	}
+}
+
 /**
  * Create a Weston output structure
  *
@@ -4265,6 +4343,8 @@ create_outputs(struct drm_backend *b, struct udev_device *drm_device)
 		}
 	}
 
+	drm_backend_update_unused_outputs(b, resources);
+
 	if (wl_list_empty(&b->compositor->output_list) &&
 	    wl_list_empty(&b->compositor->pending_output_list))
 		weston_log("No currently active connector found.\n");
@@ -4356,6 +4436,8 @@ update_outputs(struct drm_backend *b, struct udev_device *drm_device)
 		drm_output_destroy(&output->base);
 	}
 
+	drm_backend_update_unused_outputs(b, resources);
+
 	free(connected);
 	drmModeFreeResources(resources);
 }
@@ -4422,6 +4504,9 @@ drm_destroy(struct weston_compositor *ec)
 
 	weston_launcher_destroy(ec->launcher);
 
+	wl_array_release(&b->unused_crtcs);
+	wl_array_release(&b->unused_connectors);
+
 	close(b->drm.fd);
 	free(b);
 }
@@ -4854,6 +4939,8 @@ drm_backend_create(struct weston_compositor *compositor,
 		return NULL;
 
 	b->drm.fd = -1;
+	wl_array_init(&b->unused_crtcs);
+	wl_array_init(&b->unused_connectors);
 
 	/*
 	 * KMS support for hardware planes cannot properly synchronize
-- 
2.14.3



More information about the wayland-devel mailing list