xf86drm: add iterator API for DRM/KMS IN_FORMATS blobs
Add support for parsing IN_FORMATS property blobs. Providing libdrm with this functionality helps to standardise how user-space reads kernel blobs and decreases duplication on the client side. drmModeFormatModifierBlobIterNext() allows the caller to view formats and associated modifiers given a valid property blob. An example is available inside the libdrm unit test, modetest.c. Signed-off-by: Luigi Santivetti <luigi.santivetti@imgtec.com> Reviewed-by: Simon Ser <contact@emersion.fr>main
parent
f256bb9afd
commit
e641e2a632
|
@ -110,6 +110,7 @@ drmModeCrtcSetGamma
|
||||||
drmModeDestroyPropertyBlob
|
drmModeDestroyPropertyBlob
|
||||||
drmModeDetachMode
|
drmModeDetachMode
|
||||||
drmModeDirtyFB
|
drmModeDirtyFB
|
||||||
|
drmModeFormatModifierBlobIterNext
|
||||||
drmModeFreeConnector
|
drmModeFreeConnector
|
||||||
drmModeFreeCrtc
|
drmModeFreeCrtc
|
||||||
drmModeFreeEncoder
|
drmModeFreeEncoder
|
||||||
|
|
|
@ -300,11 +300,9 @@ static const char *modifier_to_string(uint64_t modifier)
|
||||||
|
|
||||||
static void dump_in_formats(struct device *dev, uint32_t blob_id)
|
static void dump_in_formats(struct device *dev, uint32_t blob_id)
|
||||||
{
|
{
|
||||||
uint32_t i, j;
|
drmModeFormatModifierIterator iter = {0};
|
||||||
drmModePropertyBlobPtr blob;
|
drmModePropertyBlobPtr blob;
|
||||||
struct drm_format_modifier_blob *header;
|
uint32_t fmt = 0;
|
||||||
uint32_t *formats;
|
|
||||||
struct drm_format_modifier *modifiers;
|
|
||||||
|
|
||||||
printf("\t\tin_formats blob decoded:\n");
|
printf("\t\tin_formats blob decoded:\n");
|
||||||
blob = drmModeGetPropertyBlob(dev->fd, blob_id);
|
blob = drmModeGetPropertyBlob(dev->fd, blob_id);
|
||||||
|
@ -313,22 +311,18 @@ static void dump_in_formats(struct device *dev, uint32_t blob_id)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
header = blob->data;
|
while (drmModeFormatModifierBlobIterNext(blob, &iter)) {
|
||||||
formats = (uint32_t *) ((char *) header + header->formats_offset);
|
if (!fmt || fmt != iter.fmt) {
|
||||||
modifiers = (struct drm_format_modifier *)
|
printf("%s\t\t\t", !fmt ? "" : "\n");
|
||||||
((char *) header + header->modifiers_offset);
|
fmt = iter.fmt;
|
||||||
|
dump_fourcc(fmt);
|
||||||
for (i = 0; i < header->count_formats; i++) {
|
|
||||||
printf("\t\t\t");
|
|
||||||
dump_fourcc(formats[i]);
|
|
||||||
printf(": ");
|
printf(": ");
|
||||||
for (j = 0; j < header->count_modifiers; j++) {
|
|
||||||
uint64_t mask = 1ULL << i;
|
|
||||||
if (modifiers[j].formats & mask)
|
|
||||||
printf(" %s", modifier_to_string(modifiers[j].modifier));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf(" %s", modifier_to_string(iter.mod));
|
||||||
|
}
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
|
||||||
|
|
||||||
drmModeFreePropertyBlob(blob);
|
drmModeFreePropertyBlob(blob);
|
||||||
}
|
}
|
||||||
|
|
108
xf86drmMode.c
108
xf86drmMode.c
|
@ -33,6 +33,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -50,6 +51,7 @@
|
||||||
#include "xf86drmMode.h"
|
#include "xf86drmMode.h"
|
||||||
#include "xf86drm.h"
|
#include "xf86drm.h"
|
||||||
#include <drm.h>
|
#include <drm.h>
|
||||||
|
#include <drm_fourcc.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -727,6 +729,112 @@ err_allocs:
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline const uint32_t *
|
||||||
|
get_formats_ptr(const struct drm_format_modifier_blob *blob)
|
||||||
|
{
|
||||||
|
return (const uint32_t *)(((uint8_t *)blob) + blob->formats_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const struct drm_format_modifier *
|
||||||
|
get_modifiers_ptr(const struct drm_format_modifier_blob *blob)
|
||||||
|
{
|
||||||
|
return (const struct drm_format_modifier *)(((uint8_t *)blob) +
|
||||||
|
blob->modifiers_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool _drmModeFormatModifierGetNext(const drmModePropertyBlobRes *blob,
|
||||||
|
drmModeFormatModifierIterator *iter)
|
||||||
|
{
|
||||||
|
const struct drm_format_modifier *blob_modifiers, *mod;
|
||||||
|
const struct drm_format_modifier_blob *fmt_mod_blob;
|
||||||
|
const uint32_t *blob_formats;
|
||||||
|
|
||||||
|
assert(blob && iter);
|
||||||
|
|
||||||
|
fmt_mod_blob = blob->data;
|
||||||
|
blob_modifiers = get_modifiers_ptr(fmt_mod_blob);
|
||||||
|
blob_formats = get_formats_ptr(fmt_mod_blob);
|
||||||
|
|
||||||
|
/* fmt_idx and mod_idx designate the number of processed formats
|
||||||
|
* and modifiers.
|
||||||
|
*/
|
||||||
|
if (iter->fmt_idx >= fmt_mod_blob->count_formats ||
|
||||||
|
iter->mod_idx >= fmt_mod_blob->count_modifiers)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
iter->fmt = blob_formats[iter->fmt_idx];
|
||||||
|
iter->mod = DRM_FORMAT_MOD_INVALID;
|
||||||
|
|
||||||
|
/* From the latest valid found, get the next valid modifier */
|
||||||
|
while (iter->mod_idx < fmt_mod_blob->count_modifiers) {
|
||||||
|
mod = &blob_modifiers[iter->mod_idx++];
|
||||||
|
|
||||||
|
/* Check if the format that fmt_idx designates, belongs to
|
||||||
|
* this modifier 64-bit window selected via mod->offset.
|
||||||
|
*/
|
||||||
|
if (iter->fmt_idx < mod->offset ||
|
||||||
|
iter->fmt_idx >= mod->offset + 64)
|
||||||
|
continue;
|
||||||
|
if (!(mod->formats & (1 << (iter->fmt_idx - mod->offset))))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
iter->mod = mod->modifier;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iter->mod_idx == fmt_mod_blob->count_modifiers) {
|
||||||
|
iter->mod_idx = 0;
|
||||||
|
iter->fmt_idx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Since mod_idx reset, in order for the caller to iterate over
|
||||||
|
* the last modifier of the last format, always return true here
|
||||||
|
* and early return from the next call.
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterate over formats first and then over modifiers. On each call, iter->fmt
|
||||||
|
* is retained until all associated modifiers are returned. Then, either update
|
||||||
|
* iter->fmt with the next format, or exit if there aren't any left.
|
||||||
|
*
|
||||||
|
* NOTE: clients should not make any assumption on mod_idx and fmt_idx values
|
||||||
|
*
|
||||||
|
* @blob: valid kernel blob holding formats and modifiers
|
||||||
|
* @iter: input and output iterator data. Iter data must be initialised to zero
|
||||||
|
* @return: false, on error or there aren't any further formats or modifiers left.
|
||||||
|
* true, on success and there are more formats or modifiers.
|
||||||
|
*/
|
||||||
|
drm_public bool drmModeFormatModifierBlobIterNext(const drmModePropertyBlobRes *blob,
|
||||||
|
drmModeFormatModifierIterator *iter)
|
||||||
|
{
|
||||||
|
drmModeFormatModifierIterator tmp;
|
||||||
|
bool has_fmt;
|
||||||
|
|
||||||
|
if (!blob || !iter)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
tmp.fmt_idx = iter->fmt_idx;
|
||||||
|
tmp.mod_idx = iter->mod_idx;
|
||||||
|
|
||||||
|
/* With the current state of things, DRM/KMS drivers are allowed to
|
||||||
|
* construct blobs having formats and no modifiers. Userspace can't
|
||||||
|
* legitimately abort in such cases.
|
||||||
|
*
|
||||||
|
* While waiting for the kernel to perhaps disallow formats with no
|
||||||
|
* modifiers in IN_FORMATS blobs, skip the format altogether.
|
||||||
|
*/
|
||||||
|
do {
|
||||||
|
has_fmt = _drmModeFormatModifierGetNext(blob, &tmp);
|
||||||
|
if (has_fmt && tmp.mod != DRM_FORMAT_MOD_INVALID)
|
||||||
|
*iter = tmp;
|
||||||
|
|
||||||
|
} while (has_fmt && tmp.mod == DRM_FORMAT_MOD_INVALID);
|
||||||
|
|
||||||
|
return has_fmt;
|
||||||
|
}
|
||||||
|
|
||||||
drm_public void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr)
|
drm_public void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr)
|
||||||
{
|
{
|
||||||
if (!ptr)
|
if (!ptr)
|
||||||
|
|
|
@ -42,6 +42,7 @@ extern "C" {
|
||||||
|
|
||||||
#include <drm.h>
|
#include <drm.h>
|
||||||
#include <drm_mode.h>
|
#include <drm_mode.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
@ -231,6 +232,12 @@ typedef struct _drmModeObjectProperties {
|
||||||
uint64_t *prop_values;
|
uint64_t *prop_values;
|
||||||
} drmModeObjectProperties, *drmModeObjectPropertiesPtr;
|
} drmModeObjectProperties, *drmModeObjectPropertiesPtr;
|
||||||
|
|
||||||
|
typedef struct _drmModeFormatModifierIterator {
|
||||||
|
uint32_t fmt_idx, mod_idx;
|
||||||
|
uint32_t fmt;
|
||||||
|
uint64_t mod;
|
||||||
|
} drmModeFormatModifierIterator;
|
||||||
|
|
||||||
typedef struct _drmModePlane {
|
typedef struct _drmModePlane {
|
||||||
uint32_t count_formats;
|
uint32_t count_formats;
|
||||||
uint32_t *formats;
|
uint32_t *formats;
|
||||||
|
@ -388,6 +395,8 @@ extern drmModePropertyPtr drmModeGetProperty(int fd, uint32_t propertyId);
|
||||||
extern void drmModeFreeProperty(drmModePropertyPtr ptr);
|
extern void drmModeFreeProperty(drmModePropertyPtr ptr);
|
||||||
|
|
||||||
extern drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id);
|
extern drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id);
|
||||||
|
extern bool drmModeFormatModifierBlobIterNext(const drmModePropertyBlobRes *blob,
|
||||||
|
drmModeFormatModifierIterator *iter);
|
||||||
extern void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr);
|
extern void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr);
|
||||||
extern int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property_id,
|
extern int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property_id,
|
||||||
uint64_t value);
|
uint64_t value);
|
||||||
|
|
Loading…
Reference in New Issue