[igt-dev] [PATCH i-g-t 2/3] lib: Parse plane IN_FORMATS blobifiers into a nicer form

Ville Syrjala ville.syrjala at linux.intel.com
Mon Mar 12 20:42:23 UTC 2018


From: Ville Syrjälä <ville.syrjala at linux.intel.com>

Maintain straight up arrays of format+modifier tuples for each plane,
and also collect up a similar device wide array. These will make it
easy to confirm whether each plane (or the whole device) supports a
specific format+modifier pair.

Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
---
 lib/igt_kms.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 lib/igt_kms.h |  12 +++++
 2 files changed, 182 insertions(+), 1 deletion(-)

diff --git a/lib/igt_kms.c b/lib/igt_kms.c
index 6bac4d1fae50..3385846f59e5 100644
--- a/lib/igt_kms.c
+++ b/lib/igt_kms.c
@@ -171,7 +171,8 @@ const char *igt_plane_prop_names[IGT_NUM_PLANE_PROPS] = {
 	"CRTC_ID",
 	"IN_FENCE_FD",
 	"type",
-	"rotation"
+	"rotation",
+	"IN_FORMATS",
 };
 
 const char *igt_crtc_prop_names[IGT_NUM_CRTC_PROPS] = {
@@ -1801,6 +1802,9 @@ void igt_display_reset(igt_display_t *display)
 	}
 }
 
+static void igt_fill_plane_format_mod(igt_display_t *display, igt_plane_t *plane);
+static void igt_fill_display_format_mod(igt_display_t *display);
+
 /**
  * igt_display_init:
  * @display: a pointer to an #igt_display_t structure
@@ -1912,6 +1916,8 @@ void igt_display_init(igt_display_t *display, int drm_fd)
 			plane->values[IGT_PLANE_IN_FENCE_FD] = ~0ULL;
 
 			igt_fill_plane_props(display, plane, IGT_NUM_PLANE_PROPS, igt_plane_prop_names);
+
+			igt_fill_plane_format_mod(display, plane);
 		}
 
 		/*
@@ -1929,6 +1935,8 @@ void igt_display_init(igt_display_t *display, int drm_fd)
 		pipe->n_planes = n_planes;
 	}
 
+	igt_fill_display_format_mod(display);
+
 	/*
 	 * The number of connectors is set, so we just initialize the outputs
 	 * array in _init(). This may change when we need dynamic connectors
@@ -3822,3 +3830,164 @@ uint32_t kmstest_get_vbl_flag(uint32_t pipe_id)
 		return pipe_flag;
 	}
 }
+
+static inline const uint32_t *
+formats_ptr(const struct drm_format_modifier_blob *blob)
+{
+	return (const uint32_t *)((const char *)blob + blob->formats_offset);
+}
+
+static inline const struct drm_format_modifier *
+modifiers_ptr(const struct drm_format_modifier_blob *blob)
+{
+	return (const struct drm_format_modifier *)((const char *)blob + blob->modifiers_offset);
+}
+
+static int igt_count_plane_format_mod(const struct drm_format_modifier_blob *blob_data)
+{
+	const struct drm_format_modifier *modifiers;
+	int count = 0;
+
+	modifiers = modifiers_ptr(blob_data);
+
+	for (int i = 0; i < blob_data->count_modifiers; i++)
+		count += igt_hweight64(modifiers[i].formats);
+
+	return count;
+}
+
+static void igt_fill_plane_format_mod(igt_display_t *display, igt_plane_t *plane)
+{
+	const struct drm_format_modifier_blob *blob_data;
+	drmModePropertyBlobPtr blob;
+	uint64_t blob_id;
+	int idx = 0;
+	int count;
+
+	blob_id = igt_plane_get_prop(plane, IGT_PLANE_IN_FORMATS);
+
+	blob = drmModeGetPropertyBlob(display->drm_fd, blob_id);
+	if (!blob)
+		return;
+
+	blob_data = (const struct drm_format_modifier_blob *) blob->data;
+
+	count = igt_count_plane_format_mod(blob_data);
+	if (!count)
+		return;
+
+	plane->format_mod_count = count;
+	plane->formats = calloc(count, sizeof(plane->formats[0]));
+	igt_assert(plane->formats);
+	plane->modifiers = calloc(count, sizeof(plane->modifiers[0]));
+	igt_assert(plane->modifiers);
+
+	for (int i = 0; i < blob_data->count_modifiers; i++) {
+		for (int j = 0; j < 64; j++) {
+			const struct drm_format_modifier *modifiers =
+				modifiers_ptr(blob_data);
+			const uint32_t *formats = formats_ptr(blob_data);
+
+			if (!(modifiers[i].formats & (1ULL << j)))
+				continue;
+
+			plane->formats[idx] = formats[modifiers[i].offset + j];
+			plane->modifiers[idx] = modifiers[i].modifier;
+			idx++;
+			igt_assert_lte(idx, plane->format_mod_count);
+		}
+	}
+
+	igt_assert_eq(idx, plane->format_mod_count);
+}
+
+bool igt_plane_has_format_mod(igt_plane_t *plane, uint32_t format,
+			      uint64_t modifier)
+{
+	int i;
+
+	for (i = 0; i < plane->format_mod_count; i++) {
+		if (plane->formats[i] == format &&
+		    plane->modifiers[i] == modifier)
+			return true;
+
+	}
+
+	return false;
+}
+
+static int igt_count_display_format_mod(igt_display_t *display)
+{
+	enum pipe pipe;
+	int count = 0;
+
+	for_each_pipe(display, pipe) {
+		igt_plane_t *plane;
+
+		for_each_plane_on_pipe(display, pipe, plane) {
+			count += plane->format_mod_count;
+		}
+	}
+
+	return count;
+}
+
+static void
+igt_add_display_format_mod(igt_display_t *display, uint32_t format,
+			   uint64_t modifier)
+{
+	int i;
+
+	for (i = 0; i < display->format_mod_count; i++) {
+		if (display->formats[i] == format &&
+		    display->modifiers[i] == modifier)
+			return;
+
+	}
+
+	display->formats[i] = format;
+	display->modifiers[i] = modifier;
+	display->format_mod_count++;
+}
+
+static void igt_fill_display_format_mod(igt_display_t *display)
+{
+	int count = igt_count_display_format_mod(display);
+	enum pipe pipe;
+
+	if (!count)
+		return;
+
+	display->formats = calloc(count, sizeof(display->formats[0]));
+	igt_assert(display->formats);
+	display->modifiers = calloc(count, sizeof(display->modifiers[0]));
+	igt_assert(display->modifiers);
+
+	for_each_pipe(display, pipe) {
+		igt_plane_t *plane;
+
+		for_each_plane_on_pipe(display, pipe, plane) {
+			for (int i = 0; i < plane->format_mod_count; i++) {
+				igt_add_display_format_mod(display,
+							   plane->formats[i],
+							   plane->modifiers[i]);
+				igt_assert_lte(display->format_mod_count, count);
+			}
+		}
+	}
+}
+
+bool igt_display_has_format_mod(igt_display_t *display, uint32_t format,
+				uint64_t modifier)
+{
+	int i;
+
+	for (i = 0; i < display->format_mod_count; i++) {
+		if (display->formats[i] == format &&
+		    display->modifiers[i] == modifier)
+			return true;
+
+	}
+
+	return false;
+}
diff --git a/lib/igt_kms.h b/lib/igt_kms.h
index 1c46186e8a9d..3a9df94c07e2 100644
--- a/lib/igt_kms.h
+++ b/lib/igt_kms.h
@@ -262,6 +262,7 @@ enum igt_atomic_plane_properties {
        IGT_PLANE_IN_FENCE_FD,
        IGT_PLANE_TYPE,
        IGT_PLANE_ROTATION,
+       IGT_PLANE_IN_FORMATS,
        IGT_NUM_PLANE_PROPS
 };
 
@@ -309,6 +310,10 @@ typedef struct {
 	uint64_t changed;
 	uint32_t props[IGT_NUM_PLANE_PROPS];
 	uint64_t values[IGT_NUM_PLANE_PROPS];
+
+	uint64_t *modifiers;
+	uint32_t *formats;
+	int format_mod_count;
 } igt_plane_t;
 
 struct igt_pipe {
@@ -357,6 +362,10 @@ struct igt_display {
 	bool has_cursor_plane;
 	bool is_atomic;
 	bool first_commit;
+
+	uint64_t *modifiers;
+	uint32_t *formats;
+	int format_mod_count;
 };
 
 void igt_display_init(igt_display_t *display, int drm_fd);
@@ -671,4 +680,7 @@ bool igt_hotplug_detected(struct udev_monitor *mon,
 void igt_flush_hotplugs(struct udev_monitor *mon);
 void igt_cleanup_hotplug(struct udev_monitor *mon);
 
+bool igt_display_has_format_mod(igt_display_t *display, uint32_t format, uint64_t modifier);
+bool igt_plane_has_format_mod(igt_plane_t *plane, uint32_t format, uint64_t modifier);
+
 #endif /* __IGT_KMS_H__ */
-- 
2.16.1



More information about the igt-dev mailing list