[PATCH weston v5 38/42] compositor-drm: Discover atomic properties

Daniel Stone daniels at collabora.com
Wed Nov 16 14:25:30 UTC 2016


Set the atomic client cap, where it exists, and use this to discover the
plane/CRTC/connector properties we require for atomic modesetting.

Signed-off-by: Daniel Stone <daniels at collabora.com>
Co-authored-by: Pekka Paalanen <pekka.paalanen at collabora.co.uk>

Differential Revision: https://phabricator.freedesktop.org/D1503
---
 libweston/compositor-drm.c | 148 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 148 insertions(+)

diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
index 9ccd291..c800ffc 100644
--- a/libweston/compositor-drm.c
+++ b/libweston/compositor-drm.c
@@ -73,6 +73,14 @@
 #define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2
 #endif
 
+#ifndef DRM_CAP_ATOMIC
+#define DRM_CAP_ATOMIC 0xa
+#endif
+
+#ifndef DRM_CLIENT_CAP_ATOMIC
+#define DRM_CLIENT_CAP_ATOMIC 3
+#endif
+
 #ifndef DRM_CAP_CURSOR_WIDTH
 #define DRM_CAP_CURSOR_WIDTH 0x8
 #endif
@@ -98,6 +106,16 @@ struct property_item {
  */
 enum wdrm_plane_property {
 	WDRM_PLANE_TYPE = 0,
+	WDRM_PLANE_SRC_X,
+	WDRM_PLANE_SRC_Y,
+	WDRM_PLANE_SRC_W,
+	WDRM_PLANE_SRC_H,
+	WDRM_PLANE_CRTC_X,
+	WDRM_PLANE_CRTC_Y,
+	WDRM_PLANE_CRTC_W,
+	WDRM_PLANE_CRTC_H,
+	WDRM_PLANE_FB_ID,
+	WDRM_PLANE_CRTC_ID,
 	WDRM_PLANE__COUNT
 };
 
@@ -121,6 +139,37 @@ struct plane_properties {
 };
 
 /**
+ * List of properties attached to DRM CRTCs
+ */
+enum wdrm_crtc_property {
+	WDRM_CRTC_MODE_ID = 0,
+	WDRM_CRTC_ACTIVE,
+	WDRM_CRTC__COUNT
+};
+
+/**
+ * List of properties attached to DRM connectors
+ */
+enum wdrm_connector_property {
+	WDRM_CONNECTOR_CRTC_ID = 0,
+	WDRM_CONNECTOR__COUNT
+};
+
+/**
+ * Holding structure for CRTC properties.
+ */
+struct crtc_properties {
+	struct property_item item[WDRM_CRTC__COUNT];
+};
+
+/**
+ * Holding structure for CRTC properties.
+ */
+struct connector_properties {
+	struct property_item item[WDRM_CONNECTOR__COUNT];
+};
+
+/**
  * Mode for drm_output_state_duplicate.
  */
 enum drm_output_state_duplicate_mode {
@@ -171,6 +220,7 @@ struct drm_backend {
 	int cursors_are_broken;
 
 	bool universal_planes;
+	bool atomic_modeset;
 
 	int use_pixman;
 
@@ -297,6 +347,9 @@ struct drm_output {
 	drmModePropertyPtr dpms_prop;
 	uint32_t gbm_format;
 
+	struct crtc_properties props_crtc;
+	struct connector_properties props_conn;
+
 	int vblank_pending;
 	int page_flip_pending;
 	int destroy_pending;
@@ -587,6 +640,16 @@ plane_properties_init(struct drm_plane *plane)
 {
 	static const char * const plane_property_names[] = {
 		[WDRM_PLANE_TYPE] = "type",
+		[WDRM_PLANE_SRC_X] = "SRC_X",
+		[WDRM_PLANE_SRC_Y] = "SRC_Y",
+		[WDRM_PLANE_SRC_W] = "SRC_W",
+		[WDRM_PLANE_SRC_H] = "SRC_H",
+		[WDRM_PLANE_CRTC_X] = "CRTC_X",
+		[WDRM_PLANE_CRTC_Y] = "CRTC_Y",
+		[WDRM_PLANE_CRTC_W] = "CRTC_W",
+		[WDRM_PLANE_CRTC_H] = "CRTC_H",
+		[WDRM_PLANE_FB_ID] = "FB_ID",
+		[WDRM_PLANE_CRTC_ID] = "CRTC_ID",
 	};
 	static const char * const plane_type_names[] = {
 		[WDRM_PLANE_TYPE_PRIMARY] = "Primary",
@@ -679,6 +742,84 @@ drm_plane_get_type(struct drm_plane *plane)
 	return WDRM_PLANE_TYPE_OVERLAY;
 }
 
+/**
+ * Initialise DRM properties for CRTC and connector
+ *
+ * Set up the holding structures to track DRM object properties set on the CRTC
+ * and connector associated with an output.
+ * Free the memory allocated here with output_properties_release.
+ *
+ * @param b DRM backend
+ * @param output Output to configure
+ */
+static bool output_properties_init(struct drm_backend *b,
+				   struct drm_output *output)
+{
+	static const char * const crtc_property_names[] = {
+		[WDRM_CRTC_MODE_ID] = "MODE_ID",
+		[WDRM_CRTC_ACTIVE] = "ACTIVE",
+	};
+	static const char * const connector_property_names[] = {
+		[WDRM_CONNECTOR_CRTC_ID] = "CRTC_ID",
+	};
+	uint32_t valid_mask, required_mask;
+
+	static_assert(ARRAY_LENGTH(crtc_property_names) == WDRM_CRTC__COUNT,
+		      "crtc_property_names mismatch with the enum");
+	static_assert(WDRM_CRTC__COUNT <= 32,
+		      "need more bits for crtc item_valid_mask");
+
+	static_assert(ARRAY_LENGTH(connector_property_names) == WDRM_CONNECTOR__COUNT,
+		      "connector_property_names mismatch with the enum");
+	static_assert(WDRM_CONNECTOR__COUNT <= 32,
+		      "need more bits for connector item_valid_mask");
+
+	valid_mask = drm_properties_get_from_obj(b,
+						 output->props_crtc.item,
+						 crtc_property_names,
+						 WDRM_CRTC__COUNT,
+						 output->crtc_id,
+						 DRM_MODE_OBJECT_CRTC);
+
+	required_mask = 0;
+	if ((valid_mask & required_mask) != required_mask) {
+		weston_log("DRM error: failed to look up all CRTC properties "
+			   "(wanted 0x%x got 0x%x) on ID %d\n",
+			   required_mask, valid_mask, output->crtc_id);
+		return false;
+	}
+
+	valid_mask = drm_properties_get_from_obj(b,
+						 output->props_conn.item,
+						 connector_property_names,
+						 WDRM_CONNECTOR__COUNT,
+						 output->connector_id,
+						 DRM_MODE_OBJECT_CONNECTOR);
+	required_mask = 0;
+	if ((valid_mask & required_mask) != required_mask) {
+		weston_log("DRM error: failed to look up all connector properties "
+			   "(wanted 0x%x got 0x%x) on ID %d\n",
+			   required_mask, valid_mask, output->connector_id);
+		return false;
+	}
+
+	return true;
+}
+
+/**
+ * Free DRM CRTC and connector properties
+ *
+ * The counterpart to output_properties_init.
+ *
+ * @param output Output to release properties for
+ */
+static void output_properties_release(struct drm_output *output)
+{
+	property_item_array_release(output->props_crtc.item, WDRM_CRTC__COUNT);
+	property_item_array_release(output->props_conn.item,
+				    WDRM_CONNECTOR__COUNT);
+}
+
 static void
 drm_output_set_cursor(struct drm_output_state *output_state);
 
@@ -2550,6 +2691,11 @@ init_drm(struct drm_backend *b, struct udev_device *device)
 	weston_log("DRM: %s universal planes\n",
 		   b->universal_planes ? "supports" : "does not support");
 
+	ret = drmSetClientCap(fd, DRM_CLIENT_CAP_ATOMIC, 1);
+	b->atomic_modeset = (ret == 0);
+	weston_log("DRM: %s atomic modesetting\n",
+		   b->atomic_modeset ? "supports" : "does not support");
+
 	return 0;
 }
 
@@ -3806,6 +3952,7 @@ drm_output_destroy(struct weston_output *base)
 
 	assert(!output->state_last);
 	drm_output_state_free(output->state_cur);
+	output_properties_release(output);
 	assert(!output->state_pending);
 
 	free(output);
@@ -3881,6 +4028,7 @@ create_output_for_connector(struct drm_backend *b,
 	output->base.destroy = drm_output_destroy;
 	output->base.disable = drm_output_disable;
 	output->base.name = make_connector_name(connector);
+	output_properties_init(b, output);
 
 	output->destroy_pending = 0;
 	output->disable_pending = 0;
-- 
2.9.3



More information about the wayland-devel mailing list