From 67e911977fbe1f444045f59028c149a04ba29566 Mon Sep 17 00:00:00 2001 From: Marius Vlad Date: Mon, 1 Feb 2021 13:23:20 +0200 Subject: [PATCH] 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 ). 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 --- .gitlab-ci.yml | 2 +- .gitlab-ci/debian-install.sh | 2 +- core-symbols.txt | 2 ++ gen_table_fourcc.py | 84 ++++++++++++++++++++++++++++++++++++++++++++ meson.build | 9 +++-- tests/modetest/modetest.c | 75 ++++++++++++++++----------------------- xf86drm.c | 80 +++++++++++++++++++++++++++++++++++++++++ xf86drm.h | 11 ++++++ 8 files changed, 216 insertions(+), 49 deletions(-) create mode 100644 gen_table_fourcc.py diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7cd6d0f..26eaf83 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -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" diff --git a/.gitlab-ci/debian-install.sh b/.gitlab-ci/debian-install.sh index 886e808..ab90136 100644 --- a/.gitlab-ci/debian-install.sh +++ b/.gitlab-ci/debian-install.sh @@ -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 diff --git a/core-symbols.txt b/core-symbols.txt index 410054b..a79e626 100644 --- a/core-symbols.txt +++ b/core-symbols.txt @@ -196,3 +196,5 @@ drmUnmap drmUnmapBufs drmUpdateDrawableInfo drmWaitVBlank +drmGetFormatModifierName +drmGetFormatModifierVendor diff --git a/gen_table_fourcc.py b/gen_table_fourcc.py new file mode 100644 index 0000000..4e8bc40 --- /dev/null +++ b/gen_table_fourcc.py @@ -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('''\ +}; +''') diff --git a/meson.build b/meson.build index fd59c4b..2bbb485 100644 --- a/meson.build +++ b/meson.build @@ -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], diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index fc75383..2c83bd0 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -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) diff --git a/xf86drm.c b/xf86drm.c index edfeb34..2416366 100644 --- a/xf86drm.c +++ b/xf86drm.c @@ -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; +} diff --git a/xf86drm.h b/xf86drm.h index 9fc06ab..930d2f4 100644 --- a/xf86drm.h +++ b/xf86drm.h @@ -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 -- 2.7.4