summaryrefslogtreecommitdiffstats
path: root/src/VBox/GuestHost/OpenGL/glapi_parser/apiutil.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/GuestHost/OpenGL/glapi_parser/apiutil.py')
-rwxr-xr-xsrc/VBox/GuestHost/OpenGL/glapi_parser/apiutil.py773
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)
+