diff options
Diffstat (limited to 'src/VBox/GuestHost/OpenGL/glapi_parser/apiutil.py')
-rwxr-xr-x | src/VBox/GuestHost/OpenGL/glapi_parser/apiutil.py | 773 |
1 files changed, 773 insertions, 0 deletions
diff --git a/src/VBox/GuestHost/OpenGL/glapi_parser/apiutil.py b/src/VBox/GuestHost/OpenGL/glapi_parser/apiutil.py new file mode 100755 index 00000000..12d11222 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/glapi_parser/apiutil.py @@ -0,0 +1,773 @@ +#!/usr/common/bin/python + +# apiutil.py +# +# This file defines a bunch of utility functions for OpenGL API code +# generation. + +from __future__ import print_function +import sys, string, re + + +#====================================================================== + +def CopyrightC( ): + print("""/* Copyright (c) 2001, Stanford University + All rights reserved. + + See the file LICENSE.txt for information on redistributing this software. */ + """) + +def CopyrightDef( ): + print("""; Copyright (c) 2001, Stanford University + ; All rights reserved. + ; + ; See the file LICENSE.txt for information on redistributing this software. + """) + + + +#====================================================================== + +class APIFunction: + """Class to represent a GL API function (name, return type, + parameters, etc).""" + def __init__(self): + self.name = '' + self.returnType = '' + self.category = '' + self.offset = -1 + self.alias = '' + self.vectoralias = '' + self.params = [] + self.paramlist = [] + self.paramvec = [] + self.paramaction = [] + self.paramprop = [] + self.paramset = [] + self.props = [] + self.chromium = [] + self.chrelopcode = -1 + + + +def ProcessSpecFile(filename, userFunc): + """Open the named API spec file and call userFunc(record) for each record + processed.""" + specFile = open(filename, "r") + if not specFile: + print("Error: couldn't open %s file!" % filename) + sys.exit() + + record = APIFunction() + + for line in specFile.readlines(): + + # split line into tokens + tokens = line.split() + + if len(tokens) > 0 and line[0] != '#': + + if tokens[0] == 'name': + if record.name != '': + # process the function now + userFunc(record) + # reset the record + record = APIFunction() + + record.name = tokens[1] + + elif tokens[0] == 'return': + record.returnType = ' '.join(tokens[1:]) + + elif tokens[0] == 'param': + name = tokens[1] + type = ' '.join(tokens[2:]) + vecSize = 0 + record.params.append((name, type, vecSize)) + + elif tokens[0] == 'paramprop': + name = tokens[1] + str = tokens[2:] + enums = [] + for i in range(len(str)): + enums.append(str[i]) + record.paramprop.append((name, enums)) + + elif tokens[0] == 'paramlist': + name = tokens[1] + str = tokens[2:] + list = [] + for i in range(len(str)): + list.append(str[i]) + record.paramlist.append((name,list)) + + elif tokens[0] == 'paramvec': + name = tokens[1] + str = tokens[2:] + vec = [] + for i in range(len(str)): + vec.append(str[i]) + record.paramvec.append((name,vec)) + + elif tokens[0] == 'paramset': + line = tokens[1:] + result = [] + for i in range(len(line)): + tset = line[i] + if tset == '[': + nlist = [] + elif tset == ']': + result.append(nlist) + nlist = [] + else: + nlist.append(tset) + if result != []: + record.paramset.append(result) + + elif tokens[0] == 'paramaction': + name = tokens[1] + str = tokens[2:] + list = [] + for i in range(len(str)): + list.append(str[i]) + record.paramaction.append((name,list)) + + elif tokens[0] == 'category': + record.category = tokens[1] + + elif tokens[0] == 'offset': + if tokens[1] == '?': + record.offset = -2 + else: + record.offset = int(tokens[1]) + + elif tokens[0] == 'alias': + record.alias = tokens[1] + + elif tokens[0] == 'vectoralias': + record.vectoralias = tokens[1] + + elif tokens[0] == 'props': + record.props = tokens[1:] + + elif tokens[0] == 'chromium': + record.chromium = tokens[1:] + + elif tokens[0] == 'vector': + vecName = tokens[1] + vecSize = int(tokens[2]) + for i in range(len(record.params)): + (name, type, oldSize) = record.params[i] + if name == vecName: + record.params[i] = (name, type, vecSize) + break + + elif tokens[0] == 'chrelopcode': + record.chrelopcode = int(tokens[1]) + + else: + print('Invalid token %s after function %s' % (tokens[0], record.name)) + #endif + #endif + #endfor + specFile.close() +#enddef + + + + + +# Dictionary [name] of APIFunction: +__FunctionDict = {} + +# Dictionary [name] of name +__VectorVersion = {} + +# Reverse mapping of function name aliases +__ReverseAliases = {} + + +def AddFunction(record): + assert record.name not in __FunctionDict + #if not "omit" in record.chromium: + __FunctionDict[record.name] = record + + + +def GetFunctionDict(specFile = ""): + if not specFile: + specFile = sys.argv[1]+"/APIspec.txt" + if len(__FunctionDict) == 0: + ProcessSpecFile(specFile, AddFunction) + # Look for vector aliased functions + for func in __FunctionDict.keys(): + va = __FunctionDict[func].vectoralias + if va != '': + __VectorVersion[va] = func + #endif + + # and look for regular aliases (for glloader) + a = __FunctionDict[func].alias + if a: + if a in __ReverseAliases: + __ReverseAliases[a].append(func) + else: + __ReverseAliases[a] = [func] + #endif + return __FunctionDict + + +def GetAllFunctions(specFile = ""): + """Return sorted list of all functions known to Chromium.""" + d = GetFunctionDict(specFile) + funcs = [] + for func in d.keys(): + rec = d[func] + if not "omit" in rec.chromium: + funcs.append(func) + funcs.sort() + return funcs + +def GetAllFunctionsAndOmittedAliases(specFile = ""): + """Return sorted list of all functions known to Chromium.""" + d = GetFunctionDict(specFile) + funcs = [] + for func in d.keys(): + rec = d[func] + if (not "omit" in rec.chromium or + rec.alias != ''): + funcs.append(func) + funcs.sort() + return funcs + +def GetDispatchedFunctions(specFile = ""): + """Return sorted list of all functions handled by SPU dispatch table.""" + d = GetFunctionDict(specFile) + funcs = [] + for func in d.keys(): + rec = d[func] + if (not "omit" in rec.chromium and + not "stub" in rec.chromium and + rec.alias == ''): + funcs.append(func) + funcs.sort() + return funcs + +#====================================================================== + +def ReturnType(funcName): + """Return the C return type of named function. + Examples: "void" or "const GLubyte *". """ + d = GetFunctionDict() + return d[funcName].returnType + + +def Parameters(funcName): + """Return list of tuples (name, type, vecSize) of function parameters. + Example: if funcName=="ClipPlane" return + [ ("plane", "GLenum", 0), ("equation", "const GLdouble *", 4) ] """ + d = GetFunctionDict() + return d[funcName].params + +def ParamAction(funcName): + """Return list of names of actions for testing. + For PackerTest only.""" + d = GetFunctionDict() + return d[funcName].paramaction + +def ParamList(funcName): + """Return list of tuples (name, list of values) of function parameters. + For PackerTest only.""" + d = GetFunctionDict() + return d[funcName].paramlist + +def ParamVec(funcName): + """Return list of tuples (name, vector of values) of function parameters. + For PackerTest only.""" + d = GetFunctionDict() + return d[funcName].paramvec + +def ParamSet(funcName): + """Return list of tuples (name, list of values) of function parameters. + For PackerTest only.""" + d = GetFunctionDict() + return d[funcName].paramset + + +def Properties(funcName): + """Return list of properties of the named GL function.""" + d = GetFunctionDict() + return d[funcName].props + +def AllWithProperty(property): + """Return list of functions that have the named property.""" + funcs = [] + for funcName in GetDispatchedFunctions(): + if property in Properties(funcName): + funcs.append(funcName) + return funcs + +def Category(funcName): + """Return the category of the named GL function.""" + d = GetFunctionDict() + return d[funcName].category + +def ChromiumProps(funcName): + """Return list of Chromium-specific properties of the named GL function.""" + d = GetFunctionDict() + return d[funcName].chromium + +def ChromiumRelOpCode(funcName): + """Return list of Chromium-specific properties of the named GL function.""" + d = GetFunctionDict() + return d[funcName].chrelopcode + + +def ParamProps(funcName): + """Return list of Parameter-specific properties of the named GL function.""" + d = GetFunctionDict() + return d[funcName].paramprop + +def Alias(funcName): + """Return the function that the named function is an alias of. + Ex: Alias('DrawArraysEXT') = 'DrawArrays'. + """ + d = GetFunctionDict() + return d[funcName].alias + + +def ReverseAliases(funcName): + """Return a list of aliases.""" + d = GetFunctionDict() + if funcName in __ReverseAliases: + return sorted(__ReverseAliases[funcName]) + else: + return [] + + +def ReverseAliasesMaxCount(): + """Returns the maximum number of aliases possible for a function.""" + d = GetFunctionDict() + return max([len(a) for a in __ReverseAliases.values()]) + + +def NonVectorFunction(funcName): + """Return the non-vector version of the given function, or ''. + For example: NonVectorFunction("Color3fv") = "Color3f".""" + d = GetFunctionDict() + return d[funcName].vectoralias + + +def VectorFunction(funcName): + """Return the vector version of the given non-vector-valued function, + or ''. + For example: VectorVersion("Color3f") = "Color3fv".""" + d = GetFunctionDict() + if funcName in __VectorVersion.keys(): + return __VectorVersion[funcName] + else: + return '' + + +def GetCategoryWrapper(func_name): + """Return a C preprocessor token to test in order to wrap code. + This handles extensions. + Example: GetTestWrapper("glActiveTextureARB") = "CR_multitexture" + Example: GetTestWrapper("glBegin") = "" + """ + cat = Category(func_name) + if (cat == "1.0" or + cat == "1.1" or + cat == "1.2" or + cat == "Chromium" or + cat == "GL_chromium" or + cat == "VBox"): + return '' + elif (cat == '1.3' or + cat == '1.4' or + cat == '1.5' or + cat == '2.0' or + cat == '2.1'): + # i.e. OpenGL 1.3 or 1.4 or 1.5 + return "OPENGL_VERSION_" + cat.replace(".", "_") + else: + assert cat != '' + return cat.replace("GL_", "") + + +def CanCompile(funcName): + """Return 1 if the function can be compiled into display lists, else 0.""" + props = Properties(funcName) + if ("nolist" in props or + "get" in props or + "setclient" in props): + return 0 + else: + return 1 + +def HasChromiumProperty(funcName, propertyList): + """Return 1 if the function or any alias has any property in the + propertyList""" + for funcAlias in [funcName, NonVectorFunction(funcName), VectorFunction(funcName)]: + if funcAlias: + props = ChromiumProps(funcAlias) + for p in propertyList: + if p in props: + return 1 + return 0 + +def CanPack(funcName): + """Return 1 if the function can be packed, else 0.""" + return HasChromiumProperty(funcName, ['pack', 'extpack', 'expandpack']) + +def HasPackOpcode(funcName): + """Return 1 if the function has a true pack opcode""" + return HasChromiumProperty(funcName, ['pack', 'extpack']) + +def SetsState(funcName): + """Return 1 if the function sets server-side state, else 0.""" + props = Properties(funcName) + + # Exceptions. The first set of these functions *do* have + # server-side state-changing effects, but will be missed + # by the general query, because they either render (e.g. + # Bitmap) or do not compile into display lists (e.g. all the others). + # + # The second set do *not* have server-side state-changing + # effects, despite the fact that they do not render + # and can be compiled. They are control functions + # that are not trackable via state. + if funcName in ['Bitmap', 'DeleteTextures', 'FeedbackBuffer', + 'RenderMode', 'BindBufferARB', 'DeleteFencesNV']: + return 1 + elif funcName in ['ExecuteProgramNV']: + return 0 + + # All compilable functions that do not render and that do + # not set or use client-side state (e.g. DrawArrays, et al.), set + # server-side state. + if CanCompile(funcName) and "render" not in props and "useclient" not in props and "setclient" not in props: + return 1 + + # All others don't set server-side state. + return 0 + +def SetsClientState(funcName): + """Return 1 if the function sets client-side state, else 0.""" + props = Properties(funcName) + if "setclient" in props: + return 1 + return 0 + +def SetsTrackedState(funcName): + """Return 1 if the function sets state that is tracked by + the state tracker, else 0.""" + # These functions set state, but aren't tracked by the state + # tracker for various reasons: + # - because the state tracker doesn't manage display lists + # (e.g. CallList and CallLists) + # - because the client doesn't have information about what + # the server supports, so the function has to go to the + # server (e.g. CompressedTexImage calls) + # - because they require a round-trip to the server (e.g. + # the CopyTexImage calls, SetFenceNV, TrackMatrixNV) + if funcName in [ + 'CopyTexImage1D', 'CopyTexImage2D', + 'CopyTexSubImage1D', 'CopyTexSubImage2D', 'CopyTexSubImage3D', + 'CallList', 'CallLists', + 'CompressedTexImage1DARB', 'CompressedTexSubImage1DARB', + 'CompressedTexImage2DARB', 'CompressedTexSubImage2DARB', + 'CompressedTexImage3DARB', 'CompressedTexSubImage3DARB', + 'SetFenceNV' + ]: + return 0 + + # Anything else that affects client-side state is trackable. + if SetsClientState(funcName): + return 1 + + # Anything else that doesn't set state at all is certainly + # not trackable. + if not SetsState(funcName): + return 0 + + # Per-vertex state isn't tracked the way other state is + # tracked, so it is specifically excluded. + if "pervertex" in Properties(funcName): + return 0 + + # Everything else is fine + return 1 + +def UsesClientState(funcName): + """Return 1 if the function uses client-side state, else 0.""" + props = Properties(funcName) + if "pixelstore" in props or "useclient" in props: + return 1 + return 0 + +def IsQuery(funcName): + """Return 1 if the function returns information to the user, else 0.""" + props = Properties(funcName) + if "get" in props: + return 1 + return 0 + +def FuncGetsState(funcName): + """Return 1 if the function gets GL state, else 0.""" + d = GetFunctionDict() + props = Properties(funcName) + if "get" in props: + return 1 + else: + return 0 + +def IsPointer(dataType): + """Determine if the datatype is a pointer. Return 1 or 0.""" + if dataType.find("*") == -1: + return 0 + else: + return 1 + + +def PointerType(pointerType): + """Return the type of a pointer. + Ex: PointerType('const GLubyte *') = 'GLubyte' + """ + t = pointerType.split(' ') + if t[0] == "const": + t[0] = t[1] + return t[0] + + + + +def OpcodeName(funcName): + """Return the C token for the opcode for the given function.""" + return "CR_" + funcName.upper() + "_OPCODE" + + +def ExtendedOpcodeName(funcName): + """Return the C token for the extended opcode for the given function.""" + return "CR_" + funcName.upper() + "_EXTEND_OPCODE" + + + + +#====================================================================== + +def MakeCallString(params): + """Given a list of (name, type, vectorSize) parameters, make a C-style + formal parameter string. + Ex return: 'index, x, y, z'. + """ + result = '' + i = 1 + n = len(params) + for (name, type, vecSize) in params: + result += name + if i < n: + result = result + ', ' + i += 1 + #endfor + return result +#enddef + + +def MakeDeclarationString(params): + """Given a list of (name, type, vectorSize) parameters, make a C-style + parameter declaration string. + Ex return: 'GLuint index, GLfloat x, GLfloat y, GLfloat z'. + """ + n = len(params) + if n == 0: + return 'void' + else: + result = '' + i = 1 + for (name, type, vecSize) in params: + result = result + type + ' ' + name + if i < n: + result = result + ', ' + i += 1 + #endfor + return result + #endif +#enddef + +def MakeDeclarationStringWithContext(ctx_macro_prefix, params): + """Same as MakeDeclarationString, but adds a context macro + """ + + n = len(params) + if n == 0: + return ctx_macro_prefix + '_ARGSINGLEDECL' + else: + result = MakeDeclarationString(params) + return ctx_macro_prefix + '_ARGDECL ' + result + #endif +#enddef + + +def MakePrototypeString(params): + """Given a list of (name, type, vectorSize) parameters, make a C-style + parameter prototype string (types only). + Ex return: 'GLuint, GLfloat, GLfloat, GLfloat'. + """ + n = len(params) + if n == 0: + return 'void' + else: + result = '' + i = 1 + for (name, type, vecSize) in params: + result = result + type + # see if we need a comma separator + if i < n: + result = result + ', ' + i += 1 + #endfor + return result + #endif +#enddef + + +#====================================================================== + +__lengths = { + 'GLbyte': 1, + 'GLubyte': 1, + 'GLshort': 2, + 'GLushort': 2, + 'GLint': 4, + 'GLuint': 4, + 'GLfloat': 4, + 'GLclampf': 4, + 'GLdouble': 8, + 'GLclampd': 8, + 'GLenum': 4, + 'GLboolean': 1, + 'GLsizei': 4, + 'GLbitfield': 4, + 'void': 0, # XXX why? + 'int': 4, + 'GLintptrARB': 4, # XXX or 8 bytes? + 'GLsizeiptrARB': 4, # XXX or 8 bytes? + 'VBoxGLhandleARB': 4, + 'GLcharARB': 1, + 'uintptr_t': 4 +} + +def sizeof(type): + """Return size of C datatype, in bytes.""" + if not type in __lengths.keys(): + print >>sys.stderr, "%s not in lengths!" % type + return __lengths[type] + + +#====================================================================== +align_types = 1 + +def FixAlignment( pos, alignment ): + # if we want double-alignment take word-alignment instead, + # yes, this is super-lame, but we know what we are doing + if alignment > 4: + alignment = 4 + if align_types and alignment and ( pos % alignment ): + pos += alignment - ( pos % alignment ) + return pos + +def WordAlign( pos ): + return FixAlignment( pos, 4 ) + +def PointerSize(): + return 8 # Leave room for a 64 bit pointer + +def PacketLength( params ): + len = 0 + for (name, type, vecSize) in params: + if IsPointer(type): + size = PointerSize() + else: + assert type.find("const") == -1 + size = sizeof(type) + len = FixAlignment( len, size ) + size + len = WordAlign( len ) + return len + +#====================================================================== + +__specials = {} + +def LoadSpecials( filename ): + table = {} + try: + f = open( filename, "r" ) + except: +# try: + f = open( sys.argv[2]+"/"+filename, "r") +# except: +# __specials[filename] = {} +# print "%s not present" % filename +# return {} + + for line in f.readlines(): + line = line.strip() + if line == "" or line[0] == '#': + continue + table[line] = 1 + + __specials[filename] = table + return table + + +def FindSpecial( table_file, glName ): + table = {} + filename = table_file + "_special" + try: + table = __specials[filename] + except KeyError: + table = LoadSpecials( filename ) + + try: + if (table[glName] == 1): + return 1 + else: + return 0 #should never happen + except KeyError: + return 0 + + +def AllSpecials( table_file ): + table = {} + filename = table_file + "_special" + try: + table = __specials[filename] + except KeyError: + table = LoadSpecials( filename ) + + return sorted(table.keys()) + + +def NumSpecials( table_file ): + filename = table_file + "_special" + table = {} + try: + table = __specials[filename] + except KeyError: + table = LoadSpecials(filename) + return len(table.keys()) + +def PrintRecord(record): + argList = MakeDeclarationString(record.params) + if record.category == "Chromium": + prefix = "cr" + else: + prefix = "gl" + print('%s %s%s(%s);' % (record.returnType, prefix, record.name, argList )) + if len(record.props) > 0: + print(' /* %s */' % string.join(record.props, ' ')) + +#ProcessSpecFile("APIspec.txt", PrintRecord) + |