mirror of https://gitlab.freedesktop.org/mesa/mesa
nouveau/headers: Add Rust bindings for texture headers
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27397>
This commit is contained in:
parent
56aefac615
commit
640d14969e
|
@ -77,6 +77,16 @@ if with_nouveau_vk
|
|||
'--out-rs', '@OUTPUT0@'],
|
||||
depend_files: nvk_cl_header_depend_files,
|
||||
)
|
||||
|
||||
if cl.endswith('97')
|
||||
cl_rs_generated += custom_target(
|
||||
'nvh_' + cl + 'tex.rs',
|
||||
input : ['struct_parser.py', 'nvidia/classes/'+cl+'tex.h'],
|
||||
output : ['nvh_'+cl+'_tex.rs'],
|
||||
command : [prog_python, '@INPUT0@', '--in-h', '@INPUT1@',
|
||||
'--out-rs', '@OUTPUT0@']
|
||||
)
|
||||
endif
|
||||
endforeach
|
||||
|
||||
_nvidia_headers_lib_rs = custom_target(
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
#! /usr/bin/env python3
|
||||
#
|
||||
# Copyright © 2024 Collabora Ltd. and Red Hat Inc.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
import argparse
|
||||
import os.path
|
||||
import re
|
||||
import sys
|
||||
|
||||
from collections import namedtuple
|
||||
from mako.template import Template
|
||||
|
||||
TEMPLATE_RS = Template("""\
|
||||
// Copyright © 2024 Collabora Ltd. and Red Hat Inc.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// This file is generated by struct_parser.py. DO NOT EDIT!
|
||||
|
||||
use std::ops::Range;
|
||||
|
||||
% for s in structs:
|
||||
% for f in s.fields:
|
||||
pub const ${s.name}_${f.name}: Range<usize> = ${f.lo}..${f.hi + 1};
|
||||
% for e in f.enums:
|
||||
pub const ${s.name}_${f.name}_${e.name}: u32 = ${e.value};
|
||||
% endfor
|
||||
% endfor
|
||||
% endfor
|
||||
""")
|
||||
|
||||
STRUCTS = [
|
||||
'TEXHEADV2',
|
||||
'TEXHEADV3',
|
||||
'TEXHEAD_BL',
|
||||
'TEXHEAD_1D',
|
||||
'TEXHEAD_PITCH',
|
||||
# This one goes last because it's a substring of the others
|
||||
'TEXHEAD',
|
||||
'TEXSAMP',
|
||||
]
|
||||
|
||||
Enum = namedtuple('Enum', ['name', 'value'])
|
||||
|
||||
class Field(object):
|
||||
def __init__(self, name, lo, hi):
|
||||
self.name = name
|
||||
self.lo = lo
|
||||
self.hi = hi
|
||||
self.enums = []
|
||||
|
||||
def add_enum(self, name, value):
|
||||
self.enums.append(Enum(name, value))
|
||||
|
||||
class Struct(object):
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.fields = []
|
||||
|
||||
def add_field(self, name, lo, hi):
|
||||
self.fields.append(Field(name, lo, hi))
|
||||
|
||||
DRF_RE = re.compile(r'(?P<hi>[0-9]+):(?P<lo>[0-9]+)')
|
||||
FIELD_NAME_RE = re.compile(r'_?(?P<dw>[0-9]+)?_?(?P<name>.*)')
|
||||
MW_RE = re.compile(r'MW\((?P<hi>[0-9]+):(?P<lo>[0-9]+)\)')
|
||||
|
||||
def parse_header(nvcl, file):
|
||||
structs = {}
|
||||
for line in file:
|
||||
line = line.strip().split()
|
||||
if not line:
|
||||
continue
|
||||
|
||||
if line[0] != '#define':
|
||||
continue
|
||||
|
||||
if not line[1].startswith(nvcl):
|
||||
continue
|
||||
|
||||
name = line[1][(len(nvcl)+1):]
|
||||
|
||||
struct = None
|
||||
for s in STRUCTS:
|
||||
if name.startswith(s):
|
||||
if s not in structs:
|
||||
structs[s] = Struct(s)
|
||||
struct = structs[s]
|
||||
name = name[len(s):]
|
||||
break
|
||||
|
||||
if struct is None:
|
||||
continue
|
||||
|
||||
name_m = FIELD_NAME_RE.match(name)
|
||||
name = name_m.group('name')
|
||||
|
||||
drf = DRF_RE.match(line[2])
|
||||
mw = MW_RE.match(line[2])
|
||||
if drf:
|
||||
dw = int(name_m.group('dw'))
|
||||
lo = int(drf.group('lo')) + dw * 32
|
||||
hi = int(drf.group('hi')) + dw * 32
|
||||
struct.add_field(name, lo, hi)
|
||||
elif mw:
|
||||
lo = int(mw.group('lo'))
|
||||
hi = int(mw.group('hi'))
|
||||
struct.add_field(name, lo, hi)
|
||||
else:
|
||||
for f in struct.fields:
|
||||
if name.startswith(f.name + '_'):
|
||||
name = name[(len(f.name)+1):]
|
||||
f.add_enum(name, line[2])
|
||||
|
||||
return list(structs.values())
|
||||
|
||||
NVCL_RE = re.compile(r'cl(?P<clsver>[0-9a-f]{4}).*')
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--out-rs', required=True, help='Output Rust file.')
|
||||
parser.add_argument('--in-h',
|
||||
help='Input class header file.',
|
||||
required=True)
|
||||
args = parser.parse_args()
|
||||
|
||||
clheader = os.path.basename(args.in_h)
|
||||
nvcl = NVCL_RE.match(clheader).group('clsver')
|
||||
nvcl = nvcl.upper()
|
||||
nvcl = "NV" + nvcl
|
||||
|
||||
with open(args.in_h, 'r', encoding='utf-8') as f:
|
||||
structs = parse_header(nvcl, f)
|
||||
|
||||
try:
|
||||
with open(args.out_rs, 'w', encoding='utf-8') as f:
|
||||
f.write(TEMPLATE_RS.render(structs=structs))
|
||||
|
||||
except Exception:
|
||||
# In the event there's an error, this imports some helpers from mako
|
||||
# to print a useful stack trace and prints it, then exits with
|
||||
# status 1, if python is run with debug; otherwise it just raises
|
||||
# the exception
|
||||
import sys
|
||||
from mako import exceptions
|
||||
print(exceptions.text_error_template().render(), file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Reference in New Issue