summaryrefslogtreecommitdiff
path: root/lib/igt_kms.c
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2018-01-18 19:33:57 +0200
committerVille Syrjälä <ville.syrjala@linux.intel.com>2018-03-16 18:38:00 +0200
commit98f7614bd725afaae48f7b70d18329149075661b (patch)
tree74ff5a79d79070332c0414310775d66cb0156e7a /lib/igt_kms.c
parent2db6d5007fee63f6dceb0c9ee9d8cb4f77308841 (diff)
lib: Parse plane IN_FORMATS blobifiers into a nicer form
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. v2: s/igt_hweight64/igt_hweight/ Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'lib/igt_kms.c')
-rw-r--r--lib/igt_kms.c171
1 files changed, 170 insertions, 1 deletions
diff --git a/lib/igt_kms.c b/lib/igt_kms.c
index 6bac4d1f..cf6389f2 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_hweight(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;
+}