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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.