aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/xwin/glx/gen_gl_wrappers.py
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/hw/xwin/glx/gen_gl_wrappers.py')
-rwxr-xr-xxorg-server/hw/xwin/glx/gen_gl_wrappers.py472
1 files changed, 202 insertions, 270 deletions
diff --git a/xorg-server/hw/xwin/glx/gen_gl_wrappers.py b/xorg-server/hw/xwin/glx/gen_gl_wrappers.py
index 683b9d903..e5fa57142 100755
--- a/xorg-server/hw/xwin/glx/gen_gl_wrappers.py
+++ b/xorg-server/hw/xwin/glx/gen_gl_wrappers.py
@@ -1,8 +1,5 @@
#!/usr/bin/python3
#
-# python script to generate cdecl to stdcall wrappers for GL functions
-# adapted from genheaders.py
-#
# Copyright (c) 2013 The Khronos Group Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a
@@ -27,23 +24,30 @@
import sys, time, pdb, string, cProfile
from reg import *
+# debug - start header generation in debugger
+# dump - dump registry after loading
+# profile - enable Python profiling
+# protect - whether to use #ifndef protections
+# registry <filename> - use specified XML registry instead of gl.xml
+# timeit - time length of registry loading & header generation
+# validate - validate return & parameter group tags against <group>
+debug = False
+dump = False
+profile = False
+protect = True
+timeit = False
+validate= False
# Default input / log files
errFilename = None
diagFilename = 'diag.txt'
regFilename = 'gl.xml'
outFilename = 'gen_gl_wrappers.c'
-
-protect=True
+dispatchheader=None
prefix="gl"
preresolve=False
-wrapper=False
-shim=False
-thunk=False
-thunkdefs=False
staticwrappers=False
-nodebug=False
+nodebugcallcounting=False
-#exclude base WGL API
WinGDI={key: 1 for key in [
"wglCopyContext"
,"wglCreateContext"
@@ -79,45 +83,110 @@ if __name__ == '__main__':
while (i < len(sys.argv)):
arg = sys.argv[i]
i = i + 1
- if (arg == '-noprotect'):
+ if (arg == '-debug'):
+ print('Enabling debug (-debug)', file=sys.stderr)
+ debug = True
+ elif (arg == '-dump'):
+ print('Enabling dump (-dump)', file=sys.stderr)
+ dump = True
+ elif (arg == '-noprotect'):
print('Disabling inclusion protection in output headers', file=sys.stderr)
protect = False
+ elif (arg == '-profile'):
+ print('Enabling profiling (-profile)', file=sys.stderr)
+ profile = True
elif (arg == '-registry'):
regFilename = sys.argv[i]
i = i+1
- print('Using registry', regFilename, file=sys.stderr)
+ print('Using registry ', regFilename, file=sys.stderr)
+ elif (arg == '-time'):
+ print('Enabling timing (-time)', file=sys.stderr)
+ timeit = True
+ elif (arg == '-validate'):
+ print('Enabling group validation (-validate)', file=sys.stderr)
+ validate = True
elif (arg == '-outfile'):
outFilename = sys.argv[i]
i = i+1
elif (arg == '-preresolve'):
preresolve=True
- elif (arg == '-wrapper'):
- wrapper=True
- elif (arg == '-shim'):
- shim=True
- elif (arg == '-thunk'):
- thunk=True
- elif (arg == '-thunkdefs'):
- thunkdefs=True
elif (arg == '-staticwrappers'):
staticwrappers=True
+ elif (arg == '-dispatchheader'):
+ dispatchheader = sys.argv[i]
+ i = i+1
elif (arg == '-prefix'):
prefix = sys.argv[i]
i = i+1
- elif (arg == '-nodebug'):
- nodebug = True
+ elif (arg == '-nodbgcount'):
+ nodebugcallcounting = True
elif (arg[0:1] == '-'):
print('Unrecognized argument:', arg, file=sys.stderr)
exit(1)
-
-print('Generating', outFilename, file=sys.stderr)
+print('Generating ', outFilename, file=sys.stderr)
+
+# Simple timer functions
+startTime = None
+def startTimer():
+ global startTime
+ startTime = time.clock()
+def endTimer(msg):
+ global startTime
+ endTime = time.clock()
+ if (timeit):
+ print(msg, endTime - startTime)
+ startTime = None
# Load & parse registry
reg = Registry()
+
+startTimer()
tree = etree.parse(regFilename)
-reg.loadElementTree(tree)
+endTimer('Time to make ElementTree =')
-allVersions = '.*'
+startTimer()
+reg.loadElementTree(tree)
+endTimer('Time to parse ElementTree =')
+
+if (validate):
+ reg.validateGroups()
+
+if (dump):
+ print('***************************************')
+ print('Performing Registry dump to regdump.txt')
+ print('***************************************')
+ reg.dumpReg(filehandle = open('regdump.txt','w'))
+
+# Turn a list of strings into a regexp string matching exactly those strings
+def makeREstring(list):
+ return '^(' + '|'.join(list) + ')$'
+
+# These are "mandatory" OpenGL ES 1 extensions, to
+# be included in the core GLES/gl.h header.
+es1CoreList = [
+ 'GL_OES_read_format',
+ 'GL_OES_compressed_paletted_texture',
+ 'GL_OES_point_size_array',
+ 'GL_OES_point_sprite'
+]
+
+# Descriptive names for various regexp patterns used to select
+# versions and extensions
+
+allVersions = allExtensions = '.*'
+noVersions = noExtensions = None
+gl12andLaterPat = '1\.[2-9]|[234]\.[0-9]'
+gles2onlyPat = '2\.[0-9]'
+gles2and3Pat = '[23]\.[0-9]'
+es1CorePat = makeREstring(es1CoreList)
+# Extensions in old glcorearb.h but not yet tagged accordingly in gl.xml
+glCoreARBPat = None
+glx13andLaterPat = '1\.[3-9]'
+
+# Defaults for generating re-inclusion protection wrappers (or not)
+protectFile = protect
+protectFeature = protect
+protectProto = protect
genOpts = CGeneratorOptions(
apiname = prefix,
@@ -125,9 +194,16 @@ genOpts = CGeneratorOptions(
versions = allVersions,
emitversions = allVersions,
defaultExtensions = prefix, # Default extensions for GL
- protectFile = protect,
- protectFeature = protect,
- protectProto = protect,
+# addExtensions = None,
+# removeExtensions = None,
+# prefixText = prefixStrings + glExtPlatformStrings + glextVersionStrings,
+# genFuncPointers = True,
+# protectFile = protectFile,
+# protectFeature = protectFeature,
+# protectProto = protectProto,
+# apicall = 'GLAPI ',
+# apientry = 'APIENTRY ',
+# apientryp = 'APIENTRYP '),
)
# create error/warning & diagnostic files
@@ -137,6 +213,28 @@ else:
errWarn = sys.stderr
diag = open(diagFilename, 'w')
+#
+# look for all the SET_ macros in dispatch.h, this is the set of functions
+# we need to generate
+#
+
+dispatch = {}
+
+if dispatchheader :
+ fh = open(dispatchheader)
+ dispatchh = fh.readlines()
+
+ dispatch_regex = re.compile(r'(?:#define|static\s+INLINE\s+void)\s+SET_([^\()]+)\(')
+
+ for line in dispatchh :
+ line = line.strip()
+ m1 = dispatch_regex.search(line)
+
+ if m1 :
+ dispatch[prefix+m1.group(1)] = 1
+
+ del dispatch['glby_offset']
+
class PreResolveOutputGenerator(OutputGenerator):
def __init__(self,
errFile = sys.stderr,
@@ -145,7 +243,7 @@ class PreResolveOutputGenerator(OutputGenerator):
OutputGenerator.__init__(self, errFile, warnFile, diagFile)
self.wrappers={}
def beginFile(self, genOpts):
- self.outFile.write('/* Automatically generated from %s - DO NOT EDIT */\n\n'%regFilename)
+ pass
def endFile(self):
self.outFile.write('\nvoid ' + prefix + 'ResolveExtensionProcs(void)\n{\n')
for funcname in self.wrappers.keys():
@@ -153,6 +251,7 @@ class PreResolveOutputGenerator(OutputGenerator):
self.outFile.write('}\n\n')
def beginFeature(self, interface, emit):
OutputGenerator.beginFeature(self, interface, emit)
+ self.OldVersion = self.featureName.startswith('GL_VERSION_1_0') or self.featureName.startswith('GL_VERSION_1_1')
def endFeature(self):
OutputGenerator.endFeature(self)
def genType(self, typeinfo, name):
@@ -161,21 +260,21 @@ class PreResolveOutputGenerator(OutputGenerator):
OutputGenerator.genEnum(self, enuminfo, name)
def genCmd(self, cmd, name):
OutputGenerator.genCmd(self, cmd, name)
-
if name in WinGDI:
return
self.outFile.write('RESOLVE_DECL(PFN' + name.upper() + 'PROC);\n')
self.wrappers[name]=1
-class WrapperOutputGenerator(OutputGenerator):
+class MyOutputGenerator(OutputGenerator):
def __init__(self,
errFile = sys.stderr,
warnFile = sys.stderr,
diagFile = sys.stdout):
OutputGenerator.__init__(self, errFile, warnFile, diagFile)
+ self.wrappers={}
def beginFile(self, genOpts):
- self.outFile.write('/* Automatically generated from %s - DO NOT EDIT */\n\n'%regFilename)
+ pass
def endFile(self):
pass
def beginFeature(self, interface, emit):
@@ -189,18 +288,26 @@ class WrapperOutputGenerator(OutputGenerator):
OutputGenerator.genEnum(self, enuminfo, name)
def genCmd(self, cmd, name):
OutputGenerator.genCmd(self, cmd, name)
+ # Avoid generating wrappers which aren't referenced by the dispatch table
+ if dispatchheader and not name in dispatch :
+ self.outFile.write('/* No wrapper for ' + name + ', not in dispatch table */\n')
+ return
if name in WinGDI:
return
+ self.wrappers[name]=1
+
proto=noneStr(cmd.elem.find('proto'))
rettype=noneStr(proto.text)
if rettype.lower()!="void ":
plist = ([t for t in proto.itertext()])
rettype = ''.join(plist[:-1])
- rettype=rettype.strip()
+ #ptype=proto.find("ptype")
+ #if ptype!=None:
+ # rettype = (noneStr(ptype.text))+" "
if staticwrappers: self.outFile.write("static ")
- self.outFile.write("%s %sWrapper("%(rettype, name))
+ self.outFile.write("%s__stdcall %sWrapper("%(rettype, name))
params = cmd.elem.findall('param')
plist=[]
for param in params:
@@ -215,230 +322,55 @@ class WrapperOutputGenerator(OutputGenerator):
Comma=", "
else:
self.outFile.write("void")
-
- self.outFile.write(")\n{\n")
-
- # for GL 1.0 and 1.1 functions, generate stdcall wrappers which call the function directly
if self.OldVersion:
- if not nodebug:
- self.outFile.write(' if (glxWinDebugSettings.enable%scallTrace) ErrorF("%s\\n");\n'%(prefix.upper(), name))
- self.outFile.write(" glWinDirectProcCalls++;\n")
- self.outFile.write("\n")
-
- if rettype.lower()=="void":
- self.outFile.write(" %s( "%(name))
+ if nodebugcallcounting:
+ self.outFile.write(")\n{\n")
else:
- self.outFile.write(" return %s( "%(name))
-
- Comma=""
- for ptype, pname in plist:
- self.outFile.write("%s%s_"%(Comma, pname))
- Comma=", "
-
- # for GL 1.2+ functions, generate stdcall wrappers which use wglGetProcAddress()
- else:
- if rettype.lower()=="void":
- self.outFile.write(' RESOLVE(PFN%sPROC, "%s");\n'%(name.upper(), name))
-
- if not nodebug:
- self.outFile.write("\n")
- self.outFile.write(' if (glxWinDebugSettings.enable%scallTrace) ErrorF("%s\\n");\n'%(prefix.upper(), name))
- self.outFile.write("\n")
-
- self.outFile.write(" RESOLVED_PROC(PFN%sPROC)( """%(name.upper()))
- else:
- self.outFile.write(' RESOLVE_RET(PFN%sPROC, "%s", FALSE);\n'%(name.upper(), name))
-
- if not nodebug:
- self.outFile.write("\n")
- self.outFile.write(' if (glxWinDebugSettings.enable%scallTrace) ErrorF("%s\\n");\n'%(prefix.upper(), name))
- self.outFile.write("\n")
-
- self.outFile.write(" return RESOLVED_PROC(PFN%sPROC)("%(name.upper()))
-
- Comma=""
- for ptype, pname in plist:
- self.outFile.write("%s%s_"%(Comma, pname))
- Comma=", "
- self.outFile.write(" );\n}\n\n")
-
-class ThunkOutputGenerator(OutputGenerator):
- def __init__(self,
- errFile = sys.stderr,
- warnFile = sys.stderr,
- diagFile = sys.stdout):
- OutputGenerator.__init__(self, errFile, warnFile, diagFile)
- def beginFile(self, genOpts):
- self.outFile.write('/* Automatically generated from %s - DO NOT EDIT */\n\n'%regFilename)
- def endFile(self):
- pass
- def beginFeature(self, interface, emit):
- OutputGenerator.beginFeature(self, interface, emit)
- self.OldVersion = self.featureName.startswith('GL_VERSION_1_0') or self.featureName.startswith('GL_VERSION_1_1')
- def endFeature(self):
- OutputGenerator.endFeature(self)
- def genType(self, typeinfo, name):
- OutputGenerator.genType(self, typeinfo, name)
- def genEnum(self, enuminfo, name):
- OutputGenerator.genEnum(self, enuminfo, name)
- def genCmd(self, cmd, name):
- OutputGenerator.genCmd(self, cmd, name)
-
- proto=noneStr(cmd.elem.find('proto'))
- rettype=noneStr(proto.text)
- if rettype.lower()!="void ":
- plist = ([t for t in proto.itertext()])
- rettype = ''.join(plist[:-1])
- rettype=rettype.strip()
- self.outFile.write("%s %sWrapper("%(rettype, name))
- params = cmd.elem.findall('param')
- plist=[]
- for param in params:
- paramlist = ([t for t in param.itertext()])
- paramtype = ''.join(paramlist[:-1])
- paramname = paramlist[-1]
- plist.append((paramtype, paramname))
- Comma=""
- if len(plist):
- for ptype, pname in plist:
- self.outFile.write("%s%s%s_"%(Comma, ptype, pname))
- Comma=", "
- else:
- self.outFile.write("void")
-
- self.outFile.write(")\n{\n")
-
- # for GL 1.0 and 1.1 functions, generate stdcall thunk wrappers which call the function directly
- if self.OldVersion:
- if rettype.lower()=="void":
+ self.outFile.write( """)
+{
+#ifdef _DEBUG
+ if (glxWinDebugSettings.enable%scallTrace) ErrorF("%s\\n");
+ glWinDirectProcCalls++;
+#endif
+"""%(prefix.upper(), name))
+ if rettype.lower()=="void ":
self.outFile.write(" %s( "%(name))
else:
self.outFile.write(" return %s( "%(name))
-
Comma=""
for ptype, pname in plist:
self.outFile.write("%s%s_"%(Comma, pname))
Comma=", "
-
- # for GL 1.2+ functions, generate wrappers which use wglGetProcAddress()
else:
- if rettype.lower()=="void":
- self.outFile.write(' RESOLVE(PFN%sPROC, "%s");\n'%(name.upper(), name))
- self.outFile.write(" RESOLVED_PROC(PFN%sPROC)( """%(name.upper()))
+ if rettype.lower()=="void ":
+ self.outFile.write(""")
+{
+ RESOLVE(PFN%sPROC, "%s");"""%(name.upper(), name))
+ if not nodebugcallcounting: self.outFile.write("""
+#ifdef _DEBUG
+ if (glxWinDebugSettings.enable%scallTrace) ErrorF("%s\\n");
+#endif"""%(prefix.upper(), name))
+ self.outFile.write("""
+ RESOLVED_PROC(PFN%sPROC)( """%(name.upper()))
else:
- self.outFile.write(' RESOLVE_RET(PFN%sPROC, "%s", FALSE);\n'%(name.upper(), name))
- self.outFile.write(" return RESOLVED_PROC(PFN%sPROC)("%(name.upper()))
-
+ self.outFile.write(""")
+{
+ RESOLVE_RET(PFN%sPROC, "%s", FALSE);"""%(name.upper(), name))
+ if not nodebugcallcounting: self.outFile.write("""
+#ifdef _DEBUG
+ if (glxWinDebugSettings.enable%scallTrace) ErrorF("%s\\n");
+#endif"""%(prefix.upper(), name))
+ self.outFile.write("""
+ return RESOLVED_PROC(PFN%sPROC)( """%(name.upper()))
Comma=""
for ptype, pname in plist:
self.outFile.write("%s%s_"%(Comma, pname))
Comma=", "
self.outFile.write(" );\n}\n\n")
-class ThunkDefsOutputGenerator(OutputGenerator):
- def __init__(self,
- errFile = sys.stderr,
- warnFile = sys.stderr,
- diagFile = sys.stdout):
- OutputGenerator.__init__(self, errFile, warnFile, diagFile)
- def beginFile(self, genOpts):
- self.outFile.write("EXPORTS\n"); # this must be the first line for libtool to realize this is a .def file
- self.outFile.write('; Automatically generated from %s - DO NOT EDIT\n\n'%regFilename)
- def endFile(self):
- pass
- def beginFeature(self, interface, emit):
- OutputGenerator.beginFeature(self, interface, emit)
- def endFeature(self):
- OutputGenerator.endFeature(self)
- def genType(self, typeinfo, name):
- OutputGenerator.genType(self, typeinfo, name)
- def genEnum(self, enuminfo, name):
- OutputGenerator.genEnum(self, enuminfo, name)
- def genCmd(self, cmd, name):
- OutputGenerator.genCmd(self, cmd, name)
-
- # export the wrapper function with the name of the function it wraps
- self.outFile.write("%s = %sWrapper\n"%(name, name))
-
-class ShimOutputGenerator(OutputGenerator):
- def __init__(self,
- errFile = sys.stderr,
- warnFile = sys.stderr,
- diagFile = sys.stdout):
- OutputGenerator.__init__(self, errFile, warnFile, diagFile)
- def beginFile(self, genOpts):
- self.outFile.write('/* Automatically generated from %s - DO NOT EDIT */\n\n'%regFilename)
- def endFile(self):
- pass
- def beginFeature(self, interface, emit):
- OutputGenerator.beginFeature(self, interface, emit)
- self.OldVersion = self.featureName.startswith('GL_VERSION_1_0') or self.featureName.startswith('GL_VERSION_1_1') or self.featureName.startswith('GL_VERSION_1_2') or self.featureName.startswith('GL_ARB_imaging') or self.featureName.startswith('GL_ARB_multitexture') or self.featureName.startswith('GL_ARB_texture_compression')
- def endFeature(self):
- OutputGenerator.endFeature(self)
- def genType(self, typeinfo, name):
- OutputGenerator.genType(self, typeinfo, name)
- def genEnum(self, enuminfo, name):
- OutputGenerator.genEnum(self, enuminfo, name)
- def genCmd(self, cmd, name):
- OutputGenerator.genCmd(self, cmd, name)
-
- if not self.OldVersion:
- return
-
- # for GL functions which are in the ABI, generate a shim which calls the function via GetProcAddress
- proto=noneStr(cmd.elem.find('proto'))
- rettype=noneStr(proto.text)
- if rettype.lower()!="void ":
- plist = ([t for t in proto.itertext()])
- rettype = ''.join(plist[:-1])
- rettype=rettype.strip()
- self.outFile.write("%s %s("%(rettype, name))
- params = cmd.elem.findall('param')
- plist=[]
- for param in params:
- paramlist = ([t for t in param.itertext()])
- paramtype = ''.join(paramlist[:-1])
- paramname = paramlist[-1]
- plist.append((paramtype, paramname))
- Comma=""
- if len(plist):
- for ptype, pname in plist:
- self.outFile.write("%s%s%s_"%(Comma, ptype, pname))
- Comma=", "
- else:
- self.outFile.write("void")
-
- self.outFile.write(")\n{\n")
-
- self.outFile.write(' typedef %s (* PFN%sPROC)(' % (rettype, name.upper()))
-
- if len(plist):
- Comma=""
- for ptype, pname in plist:
- self.outFile.write("%s %s %s_"%(Comma, ptype, pname))
- Comma=", "
- else:
- self.outFile.write("void")
-
- self.outFile.write(');\n')
-
- if rettype.lower()=="void":
- self.outFile.write(' RESOLVE(PFN%sPROC, "%s");\n'%(name.upper(), name))
- self.outFile.write(' RESOLVED_PROC(')
- else:
- self.outFile.write(' RESOLVE_RET(PFN%sPROC, "%s", 0);\n'%(name.upper(), name))
- self.outFile.write(' return RESOLVED_PROC(')
-
- Comma=""
- for ptype, pname in plist:
- self.outFile.write("%s%s_"%(Comma, pname))
- Comma=", "
-
- self.outFile.write(" );\n}\n\n")
-
def genHeaders():
+ startTimer()
outFile = open(outFilename,"w")
-
if preresolve:
gen = PreResolveOutputGenerator(errFile=errWarn,
warnFile=errWarn,
@@ -446,40 +378,40 @@ def genHeaders():
gen.outFile=outFile
reg.setGenerator(gen)
reg.apiGen(genOpts)
+ gen = MyOutputGenerator(errFile=errWarn,
+ warnFile=errWarn,
+ diagFile=diag)
+ gen.outFile=outFile
+ reg.setGenerator(gen)
+ reg.apiGen(genOpts)
- if wrapper:
- gen = WrapperOutputGenerator(errFile=errWarn,
- warnFile=errWarn,
- diagFile=diag)
- gen.outFile=outFile
- reg.setGenerator(gen)
- reg.apiGen(genOpts)
+ # generate function to setup the dispatch table, which sets each
+ # dispatch table entry to point to it's wrapper function
+ # (assuming we were able to make one)
- if shim:
- gen = ShimOutputGenerator(errFile=errWarn,
- warnFile=errWarn,
- diagFile=diag)
- gen.outFile=outFile
- reg.setGenerator(gen)
- reg.apiGen(genOpts)
+ if dispatchheader :
+ outFile.write( 'void glWinSetupDispatchTable(void)\n')
+ outFile.write( '{\n')
+ outFile.write( ' struct _glapi_table *disp = _glapi_get_dispatch();\n')
- if thunk:
- gen = ThunkOutputGenerator(errFile=errWarn,
- warnFile=errWarn,
- diagFile=diag)
- gen.outFile=outFile
- reg.setGenerator(gen)
- reg.apiGen(genOpts)
+ for d in sorted(dispatch.keys()) :
+ if d in gen.wrappers :
+ outFile.write(' SET_'+ d[len(prefix):] + '(disp, (void *)' + d + 'Wrapper);\n')
+ else :
+ outFile.write('#pragma message("No wrapper for ' + d + ' !")\n')
+
+ outFile.write('}\n')
- if thunkdefs:
- gen = ThunkDefsOutputGenerator(errFile=errWarn,
- warnFile=errWarn,
- diagFile=diag)
- gen.outFile=outFile
- reg.setGenerator(gen)
- reg.apiGen(genOpts)
outFile.close()
-genHeaders()
+if (debug):
+ pdb.run('genHeaders()')
+elif (profile):
+ import cProfile, pstats
+ cProfile.run('genHeaders()', 'profile.txt')
+ p = pstats.Stats('profile.txt')
+ p.strip_dirs().sort_stats('time').print_stats(50)
+else:
+ genHeaders()