xf86drm: Add a human readable representation for format modifiers
authorMarius Vlad <marius.vlad@collabora.com>
Mon, 1 Feb 2021 11:23:20 +0000 (13:23 +0200)
committerDaniel Stone <daniels@collabora.com>
Tue, 22 Jun 2021 11:16:04 +0000 (11:16 +0000)
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>
.gitlab-ci.yml
.gitlab-ci/debian-install.sh
core-symbols.txt
gen_table_fourcc.py [new file with mode: 0644]
meson.build
tests/modetest/modetest.c
xf86drm.c
xf86drm.h

index 7cd6d0f..26eaf83 100644 (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"
 
index 886e808..ab90136 100644 (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
index 410054b..a79e626 100644 (file)
@@ -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 (file)
index 0000000..4e8bc40
--- /dev/null
@@ -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('''\
+};
+''')
index fd59c4b..2bbb485 100644 (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],
index fc75383..2c83bd0 100644 (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)
index edfeb34..2416366 100644 (file)
--- 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;
+}
index 9fc06ab..930d2f4 100644 (file)
--- 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