Commit 98f7614b authored by Ville Syrjälä's avatar Ville Syrjälä

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ä's avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson's avatarChris Wilson <chris@chris-wilson.co.uk>
parent 2db6d500
......@@ -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;
}
......@@ -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__ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment