From: "Ville Syrjälä" <ville.syrjala@linux.intel.com>
To: Jeevan B <jeevan.b@intel.com>
Cc: igt-dev@lists.freedesktop.org, uma.shankar@intel.com,
jani.nikula@intel.com
Subject: Re: [PATCH i-g-t v2 1/2] lib: Add modifier helper for querying driver-supported modifiers
Date: Wed, 1 Apr 2026 19:00:46 +0300 [thread overview]
Message-ID: <ac1BLkuepyVmF4bl@intel.com> (raw)
In-Reply-To: <20260401152538.632846-2-jeevan.b@intel.com>
On Wed, Apr 01, 2026 at 08:55:36PM +0530, Jeevan B wrote:
> Introduce a new helper library that collects DRM format modifiers
> reported by KMS planes via the IN_FORMATS property.
We already have this parsed.
> Two functions are
> added:
>
> - igt_get_all_supported_modifiers()
> - igt_get_basic_tiling_modifiers()
>
> These helpers return unique modifier lists for a given format and will
> be used by modifier-related tests.
>
> v2: Update license headers, removes unnecessary inline usage,
> standardizes loops to use int, drops unused casts, introduces
> a small struct to manage modifier lists more cleanly, improves
> allocation handling, simplifies the basic modifier selection
> logic, and update coding‑style improvements.
>
> Signed-off-by: Jeevan B <jeevan.b@intel.com>
> ---
> lib/igt_modifier.c | 242 +++++++++++++++++++++++++++++++++++++++++++++
> lib/igt_modifier.h | 18 ++++
> lib/meson.build | 1 +
> 3 files changed, 261 insertions(+)
> create mode 100644 lib/igt_modifier.c
> create mode 100644 lib/igt_modifier.h
>
> diff --git a/lib/igt_modifier.c b/lib/igt_modifier.c
> new file mode 100644
> index 000000000..ffcf09bc9
> --- /dev/null
> +++ b/lib/igt_modifier.c
> @@ -0,0 +1,242 @@
> +/* SPDX-License-Identifier: MIT */
> +
> +/*
> + * Copyright © 2026 Intel Corporation
> + */
> +
> +
> +#include <stdlib.h>
> +#include <string.h>
> +#include <stdbool.h>
> +
> +#include <drm_fourcc.h>
> +#include <xf86drm.h>
> +#include <xf86drmMode.h>
> +
> +#include "igt_modifier.h"
> +#include "igt_core.h"
> +#include "drmtest.h"
> +
> +/*
> + * Modifier array with dynamic allocation.
> + */
> +struct modifiers {
> + uint64_t *array;
> + int nelems;
> + int alloc;
> +};
> +
> +static void modifiers_init(struct modifiers *m)
> +{
> + m->array = NULL;
> + m->nelems = 0;
> + m->alloc = 0;
> +}
> +
> +static bool modifiers_contains(const struct modifiers *m, uint64_t val)
> +{
> + for (int i = 0; i < m->nelems; i++)
> + if (m->array[i] == val)
> + return true;
> + return false;
> +}
> +
> +static void modifiers_append_unique(struct modifiers *m, uint64_t val)
> +{
> + if (modifiers_contains(m, val))
> + return;
> +
> + if (m->nelems == m->alloc) {
> + int new_alloc = m->alloc ? m->alloc * 2 : 8;
> + m->array = realloc(m->array, new_alloc * sizeof(uint64_t));
> + igt_assert(m->array);
> +
> + m->alloc = new_alloc;
> + }
> +
> + m->array[m->nelems++] = val;
> +}
> +
> +static void modifiers_finalize(struct modifiers *m, uint64_t **out, int *count)
> +{
> + *out = m->array;
> + *count = m->nelems;
> +}
> +
> +
> +static const uint32_t *
> +blob_formats_ptr(const struct drm_format_modifier_blob *blob)
> +{
> + return (const uint32_t *)((const char *)blob + blob->formats_offset);
> +}
> +
> +static const struct drm_format_modifier *
> +blob_modifiers_ptr(const struct drm_format_modifier_blob *blob)
> +{
> + return (const struct drm_format_modifier *)
> + ((const char *)blob + blob->modifiers_offset);
> +}
> +
> +static void collect_modifiers_from_blob(struct modifiers *m,
> + const struct drm_format_modifier_blob *blob,
> + uint32_t format)
> +{
> + const uint32_t *formats = blob_formats_ptr(blob);
> + const struct drm_format_modifier *mods = blob_modifiers_ptr(blob);
> +
> + int fmt_idx = -1;
> +
> + for (int i = 0; i < (int)blob->count_formats; i++) {
> + if (formats[i] == format) {
> + fmt_idx = i;
> + break;
> + }
> + }
> +
> + if (fmt_idx < 0)
> + return;
> +
> + for (int i = 0; i < (int)blob->count_modifiers; i++) {
> + const struct drm_format_modifier *entry = &mods[i];
> + int rel = fmt_idx - entry->offset;
> +
> + if (rel < 0 || rel >= 64)
> + continue;
> +
> + if (entry->formats & (1ULL << rel))
> + modifiers_append_unique(m, entry->modifier);
> + }
> +}
> +
> +static int query_plane_modifiers(int drm_fd, uint32_t format,
> + uint64_t **out)
> +{
> + struct modifiers mods;
> + drmModePlaneResPtr pres;
> +
> + modifiers_init(&mods);
> +
> + drmSetClientCap(drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
> +
> + pres = drmModeGetPlaneResources(drm_fd);
> + if (!pres)
> + goto fallback;
> +
> + for (int i = 0; i < (int)pres->count_planes; i++) {
> + drmModePlanePtr p;
> + drmModeObjectPropertiesPtr props;
> + drmModePropertyBlobPtr blob;
> + bool supported;
> + int f, j;
> +
> + p = drmModeGetPlane(drm_fd, pres->planes[i]);
> + if (!p)
> + continue;
> +
> + supported = false;
> +
> + for (f = 0; f < (int)p->count_formats; f++) {
> + if (p->formats[f] == format) {
> + supported = true;
> + break;
> + }
> + }
> +
> + if (!supported) {
> + drmModeFreePlane(p);
> + continue;
> + }
> +
> + props = drmModeObjectGetProperties(drm_fd, p->plane_id,
> + DRM_MODE_OBJECT_PLANE);
> +
> + blob = NULL;
> +
> + if (props) {
> + for ( j = 0; j < props->count_props; j++) {
> + drmModePropertyPtr prop =
> + drmModeGetProperty(drm_fd, props->props[j]);
> + if (!prop)
> + continue;
> +
> + if (!strcmp(prop->name, "IN_FORMATS") &&
> + drm_property_type_is(prop, DRM_MODE_PROP_BLOB) &&
> + props->prop_values[j] != 0) {
> + blob = drmModeGetPropertyBlob(
> + drm_fd, props->prop_values[j]);
> + }
> +
> + drmModeFreeProperty(prop);
> +
> + if (blob)
> + break;
> + }
> + drmModeFreeObjectProperties(props);
> + }
> +
> + if (blob) {
> + const struct drm_format_modifier_blob *b =
> + (const struct drm_format_modifier_blob *)blob->data;
> +
> + collect_modifiers_from_blob(&mods, b, format);
> + drmModeFreePropertyBlob(blob);
> + } else {
> + modifiers_append_unique(&mods, DRM_FORMAT_MOD_LINEAR);
> + }
> +
> + drmModeFreePlane(p);
> + }
> +
> + drmModeFreePlaneResources(pres);
> +
> +fallback:
> + int count;
> +
> + if (mods.nelems == 0)
> + modifiers_append_unique(&mods, DRM_FORMAT_MOD_LINEAR);
> +
> + modifiers_finalize(&mods, out, &count);
> + return count;
> +}
> +
> +int igt_get_all_supported_modifiers(int drm_fd, uint32_t format,
> + uint64_t **modifiers_out)
> +{
> + igt_assert(modifiers_out);
> + return query_plane_modifiers(drm_fd, format, modifiers_out);
> +}
> +
> +static const uint64_t basic_mods[] = {
> + DRM_FORMAT_MOD_LINEAR,
> + I915_FORMAT_MOD_X_TILED,
> + I915_FORMAT_MOD_Y_TILED,
> + I915_FORMAT_MOD_4_TILED,
> +};
> +
> +int igt_get_basic_tiling_modifiers(int drm_fd, uint32_t format,
> + uint64_t **modifiers_out)
> +{
> + uint64_t *all = NULL;
> + int all_count = query_plane_modifiers(drm_fd, format, &all);
> + int count;
> +
> + struct modifiers out;
> + modifiers_init(&out);
> +
> + for (int i = 0; i < all_count; i++) {
> + for (int j = 0; j < (int)(sizeof(basic_mods)/sizeof(basic_mods[0])); j++) {
> + if (all[i] == basic_mods[j]) {
> + modifiers_append_unique(&out, all[i]);
> + break;
> + }
> + }
> + }
> +
> + free(all);
> +
> + if (out.nelems == 0)
> + modifiers_append_unique(&out, DRM_FORMAT_MOD_LINEAR);
> +
> + modifiers_finalize(&out, modifiers_out, &count);
> + return count;
> +}
> diff --git a/lib/igt_modifier.h b/lib/igt_modifier.h
> new file mode 100644
> index 000000000..069ea334a
> --- /dev/null
> +++ b/lib/igt_modifier.h
> @@ -0,0 +1,18 @@
> +/* SPDX-License-Identifier: MIT */
> +
> +/*
> + * Copyright © 2026 Intel Corporation
> + */
> +
> +#ifndef __IGT_MODIFIER_H__
> +#define __IGT_MODIFIER_H__
> +
> +#include <stdint.h>
> +
> +int igt_get_all_supported_modifiers(int drm_fd, uint32_t format,
> + uint64_t **modifiers_out);
> +
> +int igt_get_basic_tiling_modifiers(int drm_fd, uint32_t format,
> + uint64_t **modifiers_out);
> +
> +#endif /* __IGT_MODIFIER_H__ */
> diff --git a/lib/meson.build b/lib/meson.build
> index 5c4829345..ca2867eed 100644
> --- a/lib/meson.build
> +++ b/lib/meson.build
> @@ -99,6 +99,7 @@ lib_sources = [
> 'igt_draw.c',
> 'igt_list.c',
> 'igt_map.c',
> + 'igt_modifier.c',
> 'igt_panel.c',
> 'igt_pm.c',
> 'igt_dummyload.c',
> --
> 2.43.0
--
Ville Syrjälä
Intel
next prev parent reply other threads:[~2026-04-01 16:01 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-01 15:25 [PATCH i-g-t v2 0/2] RFC: Add modifier helper and temporary test Jeevan B
2026-04-01 15:25 ` [PATCH i-g-t v2 1/2] lib: Add modifier helper for querying driver-supported modifiers Jeevan B
2026-04-01 16:00 ` Ville Syrjälä [this message]
2026-04-01 15:25 ` [PATCH i-g-t v2 2/2] DONT_MERGE: Add kms_modifier_list test to verify new modifier helper Jeevan B
-- strict thread matches above, loose matches on Subject: below --
2026-04-01 15:31 [PATCH i-g-t v2 0/2] RFC: Add modifier helper and temporary test Jeevan B
2026-04-01 15:31 ` [PATCH i-g-t v2 1/2] lib: Add modifier helper for querying driver-supported modifiers Jeevan B
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ac1BLkuepyVmF4bl@intel.com \
--to=ville.syrjala@linux.intel.com \
--cc=igt-dev@lists.freedesktop.org \
--cc=jani.nikula@intel.com \
--cc=jeevan.b@intel.com \
--cc=uma.shankar@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox