xf86drm: Add a human readable representation for format modifiers

Introduces two new methods to retrieve a human readable representation of a
format modifier:

drmGetFormatModifierName() - returns a format modifier as a string,
from a token modifier
drmGetFormatModifierVendor() - returns the vendor as a string, from a
token modifier

and the fourcc_mod_get_vendor macro that returns the vendor.

New format modifiers added in drm_fourcc.h uapi kernel header should be
sync'ed up with libdrm and should include a human readable
representation for that format modifier, in order to display it
correctly as a string.

That happens with the help of a python script that reads up drm_fourcc
header file and outputs a static table comprised of token modifiers
alongside a vendor table (Suggested-by Simon Ser <contact@emersion.fr>).

The reason for doing it in libdrm is to have a unified place instead of each
user of libdrm having a way to keep track of the format modifiers.

With this patch, modetest has also been modified to make use of it.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
main
Marius Vlad 2021-02-01 13:23:20 +02:00 committed by Daniel Stone
parent f287d1990b
commit 67e911977f
8 changed files with 216 additions and 49 deletions

View File

@ -14,7 +14,7 @@
# repository's registry will be used there as well.
variables:
UPSTREAM_REPO: mesa/drm
DEBIAN_TAG: "2020-11-15"
DEBIAN_TAG: "2021-02-11"
DEBIAN_VERSION: buster-slim
DEBIAN_IMAGE: "$CI_REGISTRY_IMAGE/debian/$DEBIAN_VERSION:$DEBIAN_TAG"

View File

@ -63,4 +63,4 @@ done
# Test that the oldest Meson version we claim to support is still supported
pip3 install meson==0.43
pip3 install meson==0.46

View File

@ -196,3 +196,5 @@ drmUnmap
drmUnmapBufs
drmUpdateDrawableInfo
drmWaitVBlank
drmGetFormatModifierName
drmGetFormatModifierVendor

84
gen_table_fourcc.py Normal file
View File

@ -0,0 +1,84 @@
#!/usr/bin/env python3
# Copyright 2021 Collabora, Ltd.
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice (including the
# next paragraph) shall be included in all copies or substantial
# portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# Helper script that reads drm_fourcc.h and writes a static table with the
# simpler format token modifiers
import sys
import re
filename = sys.argv[1]
towrite = sys.argv[2]
fm_re = {
'intel': r'^#define I915_FORMAT_MOD_(\w+)',
'others': r'^#define DRM_FORMAT_MOD_((?:ARM|SAMSUNG|QCOM|VIVANTE|NVIDIA|BROADCOM|ALLWINNER)\w+)\s',
'vendors': r'^#define DRM_FORMAT_MOD_VENDOR_(\w+)'
}
def print_fm_intel(f, f_mod):
f.write(' {{ DRM_MODIFIER_INTEL({}, {}) }},\n'.format(f_mod, f_mod))
# generic write func
def print_fm(f, vendor, mod, f_name):
f.write(' {{ DRM_MODIFIER({}, {}, {}) }},\n'.format(vendor, mod, f_name))
with open(filename, "r") as f:
data = f.read()
for k, v in fm_re.items():
fm_re[k] = re.findall(v, data, flags=re.M)
with open(towrite, "w") as f:
f.write('''\
/* AUTOMATICALLY GENERATED by gen_table_fourcc.py. You should modify
that script instead of adding here entries manually! */
static const struct drmFormatModifierInfo drm_format_modifier_table[] = {
''')
f.write(' { DRM_MODIFIER_INVALID(NONE, INVALID_MODIFIER) },\n')
f.write(' { DRM_MODIFIER_LINEAR(NONE, LINEAR) },\n')
for entry in fm_re['intel']:
print_fm_intel(f, entry)
for entry in fm_re['others']:
(vendor, mod) = entry.split('_', 1)
if vendor == 'ARM' and (mod == 'TYPE_AFBC' or mod == 'TYPE_MISC'):
continue
print_fm(f, vendor, mod, mod)
f.write('''\
};
''')
f.write('''\
static const struct drmFormatModifierVendorInfo drm_format_modifier_vendor_table[] = {
''')
for entry in fm_re['vendors']:
f.write(" {{ DRM_FORMAT_MOD_VENDOR_{}, \"{}\" }},\n".format(entry, entry))
f.write('''\
};
''')

View File

@ -23,7 +23,7 @@ project(
['c'],
version : '2.4.106',
license : 'MIT',
meson_version : '>= 0.43',
meson_version : '>= 0.46',
default_options : ['buildtype=debugoptimized', 'c_std=gnu99'],
)
@ -51,6 +51,11 @@ prog_nm = find_program('nm')
intel_atomics = false
lib_atomics = false
python3 = import('python').find_installation()
format_mod_static_table = custom_target('format_mod_static_table',
output : 'generated_static_table_fourcc.h', input: 'include/drm/drm_fourcc.h',
command : [python3, files('gen_table_fourcc.py'), '@INPUT@', '@OUTPUT@'])
dep_atomic_ops = dependency('atomic_ops', required : false)
if cc.links('''
int atomic_add(int *i) { return __sync_add_and_fetch (i, 1); }
@ -300,7 +305,7 @@ libdrm = library(
'xf86drm.c', 'xf86drmHash.c', 'xf86drmRandom.c', 'xf86drmSL.c',
'xf86drmMode.c'
),
config_file,
config_file, format_mod_static_table
],
c_args : libdrm_c_args,
dependencies : [dep_valgrind, dep_rt, dep_m],

View File

@ -265,52 +265,37 @@ static void dump_blob(struct device *dev, uint32_t blob_id)
static const char *modifier_to_string(uint64_t modifier)
{
switch (modifier) {
case DRM_FORMAT_MOD_INVALID:
return "INVALID";
case DRM_FORMAT_MOD_LINEAR:
return "LINEAR";
case I915_FORMAT_MOD_X_TILED:
return "X_TILED";
case I915_FORMAT_MOD_Y_TILED:
return "Y_TILED";
case I915_FORMAT_MOD_Yf_TILED:
return "Yf_TILED";
case I915_FORMAT_MOD_Y_TILED_CCS:
return "Y_TILED_CCS";
case I915_FORMAT_MOD_Yf_TILED_CCS:
return "Yf_TILED_CCS";
case DRM_FORMAT_MOD_SAMSUNG_64_32_TILE:
return "SAMSUNG_64_32_TILE";
case DRM_FORMAT_MOD_VIVANTE_TILED:
return "VIVANTE_TILED";
case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED:
return "VIVANTE_SUPER_TILED";
case DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED:
return "VIVANTE_SPLIT_TILED";
case DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED:
return "VIVANTE_SPLIT_SUPER_TILED";
case DRM_FORMAT_MOD_NVIDIA_TEGRA_TILED:
return "NVIDIA_TEGRA_TILED";
case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0):
return "NVIDIA_16BX2_BLOCK(0)";
case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1):
return "NVIDIA_16BX2_BLOCK(1)";
case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2):
return "NVIDIA_16BX2_BLOCK(2)";
case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3):
return "NVIDIA_16BX2_BLOCK(3)";
case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4):
return "NVIDIA_16BX2_BLOCK(4)";
case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5):
return "NVIDIA_16BX2_BLOCK(5)";
case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
return "MOD_BROADCOM_VC4_T_TILED";
case DRM_FORMAT_MOD_QCOM_COMPRESSED:
return "QCOM_COMPRESSED";
default:
return "(UNKNOWN MODIFIER)";
static char mod_string[4096];
char *modifier_name = drmGetFormatModifierName(modifier);
char *vendor_name = drmGetFormatModifierVendor(modifier);
memset(mod_string, 0x00, sizeof(mod_string));
if (!modifier_name) {
if (vendor_name)
snprintf(mod_string, sizeof(mod_string), "%s_%s",
vendor_name, "UNKNOWN_MODIFIER");
else
snprintf(mod_string, sizeof(mod_string), "%s_%s",
"UNKNOWN_VENDOR", "UNKNOWN_MODIFIER");
/* safe, as free is no-op for NULL */
free(vendor_name);
return mod_string;
}
if (modifier == DRM_FORMAT_MOD_LINEAR) {
snprintf(mod_string, sizeof(mod_string), "%s", modifier_name);
free(modifier_name);
free(vendor_name);
return mod_string;
}
snprintf(mod_string, sizeof(mod_string), "%s_%s",
vendor_name, modifier_name);
free(modifier_name);
free(vendor_name);
return mod_string;
}
static void dump_in_formats(struct device *dev, uint32_t blob_id)

View File

@ -76,6 +76,7 @@
#include "xf86drm.h"
#include "libdrm_macros.h"
#include "drm_fourcc.h"
#include "util_math.h"
@ -124,6 +125,33 @@ static drmServerInfoPtr drm_server_info;
static bool drmNodeIsDRM(int maj, int min);
static char *drmGetMinorNameForFD(int fd, int type);
#define DRM_MODIFIER(v, f, f_name) \
.modifier = DRM_FORMAT_MOD_##v ## _ ##f, \
.modifier_name = #f_name
#define DRM_MODIFIER_INVALID(v, f_name) \
.modifier = DRM_FORMAT_MOD_INVALID, .modifier_name = #f_name
#define DRM_MODIFIER_LINEAR(v, f_name) \
.modifier = DRM_FORMAT_MOD_LINEAR, .modifier_name = #f_name
/* Intel is abit special as the format doesn't follow other vendors naming
* scheme */
#define DRM_MODIFIER_INTEL(f, f_name) \
.modifier = I915_FORMAT_MOD_##f, .modifier_name = #f_name
struct drmFormatModifierInfo {
uint64_t modifier;
const char *modifier_name;
};
struct drmFormatModifierVendorInfo {
uint8_t vendor;
const char *vendor_name;
};
#include "generated_static_table_fourcc.h"
static unsigned log2_int(unsigned x)
{
unsigned l;
@ -4585,3 +4613,55 @@ drm_public int drmSyncobjTransfer(int fd,
return ret;
}
static char *
drmGetFormatModifierFromSimpleTokens(uint64_t modifier)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(drm_format_modifier_table); i++) {
if (drm_format_modifier_table[i].modifier == modifier)
return strdup(drm_format_modifier_table[i].modifier_name);
}
return NULL;
}
/** Retrieves a human-readable representation of a vendor (as a string) from
* the format token modifier
*
* \param modifier the format modifier token
* \return a char pointer to the human-readable form of the vendor. Caller is
* responsible for freeing it.
*/
drm_public char *
drmGetFormatModifierVendor(uint64_t modifier)
{
unsigned int i;
uint8_t vendor = fourcc_mod_get_vendor(modifier);
for (i = 0; i < ARRAY_SIZE(drm_format_modifier_vendor_table); i++) {
if (drm_format_modifier_vendor_table[i].vendor == vendor)
return strdup(drm_format_modifier_vendor_table[i].vendor_name);
}
return NULL;
}
/** Retrieves a human-readable representation string from a format token
* modifier
*
* If the format modifier was not in the table, this function would return
* NULL.
*
* \param modifier the token format
* \return a malloc'ed string representation of the modifier. Caller is
* responsible for freeing the string returned.
*
*/
drm_public char *
drmGetFormatModifierName(uint64_t modifier)
{
char *modifier_found = drmGetFormatModifierFromSimpleTokens(modifier);
return modifier_found;
}

View File

@ -944,6 +944,17 @@ extern int drmSyncobjTransfer(int fd,
uint32_t src_handle, uint64_t src_point,
uint32_t flags);
extern char *
drmGetFormatModifierVendor(uint64_t modifier);
extern char *
drmGetFormatModifierName(uint64_t modifier);
#ifndef fourcc_mod_get_vendor
#define fourcc_mod_get_vendor(modifier) \
(((modifier) >> 56) & 0xff)
#endif
#if defined(__cplusplus)
}
#endif