orca/scripts/gles_gen.py

235 lines
5.3 KiB
Python

from reg_modified import *
import xml.etree.ElementTree as et
from argparse import ArgumentParser
def gen_gles_header(spec, filename):
# Generates the GLES header, wrapping gl functions
# prototypes in ORCA_IMPORT() macro
gles2through31Pat = '2\.[0-9]|3\.[01]'
allVersions = '.*'
genOpts = CGeneratorOptions(
filename=filename,
apiname='gles2',
profile='common',
versions=gles2through31Pat,
emitversions=allVersions,
protectProto=False,
procMacro='ORCA_IMPORT')
reg = Registry()
tree = et.parse(spec)
reg.loadElementTree(tree)
logFile = open('./gles_gen.log', 'w')
gen = COutputGenerator(diagFile=logFile)
reg.setGenerator(gen)
reg.apiGen(genOpts)
logFile.close()
def get_bindgen_tag_for_type(typeName):
typeToTags = {
"void": "v",
"GLenum": "i",
"GLbitfield": "i",
"GLboolean": "i",
"GLbyte": "i",
"GLubyte": "i",
"GLchar": "i",
"GLshort": "i",
"GLushort": "i",
"GLhalf": "i",
"GLhalfARB": "i",
"GLuint": "i",
"GLint": "i",
"GLclampx": "i",
"GLsizei": "i",
"GLfixed": "i",
"GLuint64": "I",
"GLint64": "I",
"GLintptr": "I",
"GLsizeiptr": "I",
"GLfloat": "f",
"GLclampf": "f",
"GLdouble": "F",
"GLclampd": "F",
"GLsync": "p"
}
if typeName[len(typeName)-1] == '*':
return "p"
else:
tag = typeToTags.get(typeName)
return tag
def gen_gles_bindgen_json(spec, filename):
# Gather gles 3.1 required functions
tree = et.parse(spec)
api = []
for feature in tree.iterfind('feature[@api="gles2"]'):
if float(feature.get('number')) > 3.1:
break
for require in feature.iter('require'):
if require.get('profile') == 'compatibility':
continue
for command in require.iter('command'):
api.append(command.get('name'))
for remove in feature.iter('remove'):
for command in remove.iter('command'):
api.remove(command.get('name'))
# put all GL commands in a dict
commands = dict()
commandsSpec = tree.find('./commands')
for command in commandsSpec.iter('command'):
name = command.find('proto/name')
commands[name.text] = command
# TODO: Generate json descriptions for commands in api
manualBind = [
"glShaderSource"]
json = '[\n'
for name in api:
if name in manualBind:
continue
command = commands.get(name)
if command == None:
print("Couldn't find definition for required command '" + name + "'")
exit(-1)
proto = command.find("proto")
ptype = proto.find("ptype")
retType = ''
if proto.text != None:
retType += proto.text
if ptype != None:
if ptype.text != None:
retType += ptype.text
if ptype.tail != None:
retType += ptype.tail
retType = retType.strip()
retTag = get_bindgen_tag_for_type(retType)
if retTag == None:
print("Couldn't find tag for GL type '" + retType + "'")
exit(-1)
entry = '{\n\t"name": "' + name + '",\n'
entry += '\t"cname": "' + name + '",\n'
entry += '\t"ret": { "name": "' + retType + '", "tag": "' + retTag + '"},\n'
entry += '\t"args": [ '
# iterate through params
for param in command.iter('param'):
argNode = param.find('name')
argName = argNode.text
typeNode = param.find('ptype')
typeName = ''
if param.text != None:
typeName += param.text
if typeNode != None:
if typeNode.text != None:
typeName += typeNode.text
if typeNode.tail != None:
typeName += typeNode.tail
typeName = typeName.strip()
if typeName.endswith('**'):
print("Warning: function " + name + ": parameter " + argName + " has 2 (or more) levels of indirection")
typeTag = get_bindgen_tag_for_type(typeName)
if typeTag == None:
print("Couldn't find tag for GL type '" + typeName + "' in function '"+ name +"'")
exit(-1)
entry += '\n'
entry += '\t\t{"name": "'+ argName +'",\n'
entry += '\t\t "type": {"name": "'+ typeName +'", "tag": "'+ typeTag +'"}'
if param.get('len') != None:
lenString = param.get('len')
tokens = lenString.split('*')
if lenString.startswith("COMPSIZE"):
print("Warning: function " + name + ": parameter " + argName + " lenght uses COMPSIZE")
else:
entry += ',\n'
entry += '\t\t "len": {'
if len(tokens) == 2:
if tokens[1].isnumeric() == False:
print("Warning: function " + name + ": couldn't parse parameter '" + argName + "' lenght attribute")
entry += '"count": "' + tokens[0] + '", "components": "'+ tokens[1] + '"'
elif len(tokens) == 1:
if tokens[0].isnumeric():
entry += '"components":'+ tokens[0]
else:
entry += '"count": "'+ tokens[0] + '"'
else:
print("Warning: function " + name + ": couldn't parse parameter '" + argName + "' lenght attribute")
entry += '}'
elif typeTag == "p":
print("Warning: function " + name + ": parameter " + argName + " has no len attribute")
entry += '},'
entry = entry[:-1]
entry += '\n\t]\n}'
json += entry
json += ',\n'
json = json[:-2]
json += '\n]'
# write json to jsonFile
f = open(filename, 'w')
f.write(json)
f.close()
#----------------------------------------
# driver
#----------------------------------------
parser = ArgumentParser()
parser.add_argument("-s", "--spec")
parser.add_argument("--header")
parser.add_argument("-j", "--json")
args = parser.parse_args()
glesHeader = args.header
jsonFile = args.json
gen_gles_header(args.spec, glesHeader)
gen_gles_bindgen_json(args.spec, jsonFile)