util: add a script to auto-generate a drirc infrascture per driver

Instead of having each driver define :
  - options through DRI_CONF_OPT_* macros
  - call driQueryOption*() to parse those options
  - define all the variables to old those options' values

We add one script to do it all for you. All you have to do now is list
all the options you want in a python file.

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/41697>
This commit is contained in:
Lionel Landwerlin 2026-05-18 13:13:43 +02:00 committed by Marge Bot
parent 0dc8f95316
commit a9aeae71f5
2 changed files with 214 additions and 0 deletions

212
src/util/drirc_gen.py Normal file
View file

@ -0,0 +1,212 @@
#!/usr/bin/env python3
# Copyright (C) 2026 Valve Corporation
# SPDX-License-Identifier: MIT
import argparse
import os
import re
import sys
from enum import Enum
from mako.template import Template
class DrircOptionType(Enum):
BOOL = 0,
INT = 1,
UINT64 = 2,
FLOAT = 3,
STRING = 4,
STRING_NODEF = 5,
ENUM = 6,
type_to_ctype: dict[DrircOptionType, str] = {
DrircOptionType.BOOL: "bool",
DrircOptionType.INT: "int",
DrircOptionType.UINT64: "uint64_t",
DrircOptionType.FLOAT: "float",
DrircOptionType.STRING: "char *",
DrircOptionType.STRING_NODEF: "char *",
DrircOptionType.ENUM: "int",
}
type_to_macro: dict[DrircOptionType, str] = {
DrircOptionType.BOOL: "DRI_CONF_OPT_B",
DrircOptionType.INT: "DRI_CONF_OPT_I",
DrircOptionType.UINT64: "DRI_CONF_OPT_U64",
DrircOptionType.FLOAT: "DRI_CONF_OPT_F",
DrircOptionType.STRING: "DRI_CONF_OPT_S",
DrircOptionType.STRING_NODEF: "DRI_CONF_OPT_S_NODEF",
DrircOptionType.ENUM: "DRI_CONF_OPT_E",
}
type_to_queryfn: dict[DrircOptionType, str] = {
DrircOptionType.BOOL: "driQueryOptionb",
DrircOptionType.INT: "driQueryOptioni",
DrircOptionType.UINT64: "driQueryOptionu64",
DrircOptionType.FLOAT: "driQueryOptionf",
DrircOptionType.STRING: "driQueryOptionstr",
DrircOptionType.STRING_NODEF: "driQueryOptionstr",
DrircOptionType.ENUM: "driQueryOptioni",
}
class DrircOption(object):
def __init__(self, dtype, name, description, c_name):
self.dtype = dtype
self.name = name
self.description = description
self.c_name = c_name if c_name is not None else name.lower()
self.c_args = []
class DrircBool(DrircOption):
def __init__(self, name, value, description="", c_name=None):
super().__init__(DrircOptionType.BOOL, name, description, c_name)
self.value = value
self.c_args = ["true" if value else "false", f"\"{self.description}\""]
class DrircInt(DrircOption):
def __init__(self, name, value, min_value, max_value, description="", c_name=None):
super().__init__(DrircOptionType.INT, name, description, c_name)
self.value = value
self.min_value = min_value
self.max_value = max_value
self.c_args = [f"{value}", f"{min_value}", f"{max_value}", f"\"{self.description}\""]
class DrircUint64(DrircOption):
def __init__(self, name, value, min_value, max_value, description="", c_name=None):
super().__init__(DrircOptionType.UINT64, name, description, c_name)
self.value = value
self.min_value = min_value
self.max_value = max_value
self.c_args = [f"{value}", f"{min_value}", f"{max_value}", f"\"{self.description}\""]
class DrircFloat(DrircOption):
def __init__(self, name, value, min_value, max_value, description="", c_name=None):
super().__init__(DrircOptionType.FLOAT, name, description, c_name)
self.value = value
self.min_value = min_value
self.max_value = max_value
self.c_args = [f"{value}", f"{min_value}", f"{max_value}", f"\"{self.description}\""]
class DrircString(DrircOption):
def __init__(self, name, value=None, description="", c_name=None):
super().__init__(DrircOptionType.STRING if value is not None else DrircOptionType.STRING_NODEF,
"char *", name, description, c_name)
self.value = value
self.c_args = [f"{value}", f"\"{self.description}\""]
class DrircEnumValue(object):
def __init__(self, value, description=""):
self.value = value
self.description = description
class DrircEnum(DrircOption):
def __init__(self, name, value, min_value, max_value, values, description="", c_name=None):
super().__init__(DrircOptionType.ENUM, name, description, c_name)
self.values = values
self.value = value
self.min_value = min_value
self.max_value = max_value
self.c_args = [f"{value}", f"{min_value}", f"{min_value}", f"\"{self.description}\""]
vals = []
for v in values:
vals.append(f"DRI_CONF_ENUM({v.value}, \"{v.description}\")")
self.c_args.append(''.join(vals))
class DrircSection(object):
"""Class that represents a DRIRC section
"""
def __init__(self, name, options=[], c_name=None):
"""Parameters:
- options: list of DrircOption
"""
self.name = name
self.options = options
self.c_name = c_name if c_name is not None else name.lower()
TEMPLATE_H = """\
/* This file is autogenerated. Do not edit. */
#ifndef ${driver_prefix.upper()}_DRIRC_H
#define ${driver_prefix.upper()}_DRIRC_H
#include "util/driconf.h"
struct ${driver_prefix}_drirc {
struct driOptionCache options;
struct driOptionCache available_options;
% for section in sections:
struct {
% for option in section.options:
${type_to_ctype(option.dtype)} ${option.c_name};
% endfor
} ${section.c_name};
% endfor
};
void ${driver_prefix}_parse_dri_options(struct ${driver_prefix}_drirc *drirc,
const driConfigFileParseParams *params);
#endif /* ${driver_prefix.upper()}_DRIRC_H */
"""
TEMPLATE_C = """\
/* This file is autogenerated. Do not edit. */
#include "${include_file}"
static const driOptionDescription dri_options[] = {
% for section in sections:
DRI_CONF_SECTION("${section.name}")
% for option in section.options:
${type_to_macro(option.dtype)}(${option.name}
% for arg in option.c_args:
, ${arg}
% endfor
)
% endfor
DRI_CONF_SECTION_END
% endfor
};
void
${driver_prefix}_parse_dri_options(struct ${driver_prefix}_drirc *drirc,
const driConfigFileParseParams *params)
{
driParseOptionInfo(&drirc->available_options, dri_options, ARRAY_SIZE(dri_options));
driParseConfigFiles(&drirc->options, &drirc->available_options, params);
% for section in sections:
% for option in section.options:
drirc->${section.c_name}.${option.c_name} = ${type_to_queryfn(option.dtype)}(&drirc->options, "${option.name}");
% endfor
% endfor
}
"""
def drirc_generate(cpath, hpath, driver_prefix, sections):
environment = {
'driver_prefix': driver_prefix,
'sections': sections,
'type_to_ctype': lambda dtype: type_to_ctype[dtype],
'type_to_macro': lambda dtype: type_to_macro[dtype],
'type_to_queryfn': lambda dtype: type_to_queryfn[dtype],
'include_file': os.path.basename(hpath),
}
with open(cpath, 'w', encoding='utf-8') as f:
try:
result = f.write(Template(TEMPLATE_C).render(**environment))
except Exception:
from mako import exceptions
print(exceptions.text_error_template().render(), file=sys.stderr)
sys.exit(1)
with open(hpath, 'w', encoding='utf-8') as f:
try:
result = f.write(Template(TEMPLATE_H).render(**environment))
except Exception:
from mako import exceptions
print(exceptions.text_error_template().render(), file=sys.stderr)
sys.exit(1)

View file

@ -217,6 +217,8 @@ if with_amd_vk
files_drirc += files('00-radv-defaults.conf')
endif
drirc_gen = files('drirc_gen.py')
if with_tests
prog_xmllint = find_program('xmllint', required : false, native : true)
if prog_xmllint.found()