1*61046927SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*61046927SAndroid Build Coastguard Worker 3*61046927SAndroid Build Coastguard Worker# (C) Copyright 2015, NVIDIA CORPORATION. 4*61046927SAndroid Build Coastguard Worker# All Rights Reserved. 5*61046927SAndroid Build Coastguard Worker# 6*61046927SAndroid Build Coastguard Worker# Permission is hereby granted, free of charge, to any person obtaining a 7*61046927SAndroid Build Coastguard Worker# copy of this software and associated documentation files (the "Software"), 8*61046927SAndroid Build Coastguard Worker# to deal in the Software without restriction, including without limitation 9*61046927SAndroid Build Coastguard Worker# on the rights to use, copy, modify, merge, publish, distribute, sub 10*61046927SAndroid Build Coastguard Worker# license, and/or sell copies of the Software, and to permit persons to whom 11*61046927SAndroid Build Coastguard Worker# the Software is furnished to do so, subject to the following conditions: 12*61046927SAndroid Build Coastguard Worker# 13*61046927SAndroid Build Coastguard Worker# The above copyright notice and this permission notice (including the next 14*61046927SAndroid Build Coastguard Worker# paragraph) shall be included in all copies or substantial portions of the 15*61046927SAndroid Build Coastguard Worker# Software. 16*61046927SAndroid Build Coastguard Worker# 17*61046927SAndroid Build Coastguard Worker# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18*61046927SAndroid Build Coastguard Worker# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19*61046927SAndroid Build Coastguard Worker# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 20*61046927SAndroid Build Coastguard Worker# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21*61046927SAndroid Build Coastguard Worker# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22*61046927SAndroid Build Coastguard Worker# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23*61046927SAndroid Build Coastguard Worker# IN THE SOFTWARE. 24*61046927SAndroid Build Coastguard Worker# 25*61046927SAndroid Build Coastguard Worker# Authors: 26*61046927SAndroid Build Coastguard Worker# Kyle Brenneman <[email protected]> 27*61046927SAndroid Build Coastguard Worker 28*61046927SAndroid Build Coastguard Workerimport collections 29*61046927SAndroid Build Coastguard Workerimport re 30*61046927SAndroid Build Coastguard Workerimport sys 31*61046927SAndroid Build Coastguard Workerimport xml.etree.ElementTree as etree 32*61046927SAndroid Build Coastguard Worker 33*61046927SAndroid Build Coastguard Workerimport os 34*61046927SAndroid Build Coastguard WorkerGLAPI = os.path.join(os.path.dirname(__file__), "..", "glapi", "gen") 35*61046927SAndroid Build Coastguard Workersys.path.insert(0, GLAPI) 36*61046927SAndroid Build Coastguard Workerimport static_data 37*61046927SAndroid Build Coastguard Worker 38*61046927SAndroid Build Coastguard WorkerMAPI_TABLE_NUM_DYNAMIC = 4096 39*61046927SAndroid Build Coastguard Worker 40*61046927SAndroid Build Coastguard Worker_LIBRARY_FEATURE_NAMES = { 41*61046927SAndroid Build Coastguard Worker # libGL and libGLdiapatch both include every function. 42*61046927SAndroid Build Coastguard Worker "gl" : None, 43*61046927SAndroid Build Coastguard Worker "gldispatch" : None, 44*61046927SAndroid Build Coastguard Worker "opengl" : frozenset(( "GL_VERSION_1_0", "GL_VERSION_1_1", 45*61046927SAndroid Build Coastguard Worker "GL_VERSION_1_2", "GL_VERSION_1_3", "GL_VERSION_1_4", "GL_VERSION_1_5", 46*61046927SAndroid Build Coastguard Worker "GL_VERSION_2_0", "GL_VERSION_2_1", "GL_VERSION_3_0", "GL_VERSION_3_1", 47*61046927SAndroid Build Coastguard Worker "GL_VERSION_3_2", "GL_VERSION_3_3", "GL_VERSION_4_0", "GL_VERSION_4_1", 48*61046927SAndroid Build Coastguard Worker "GL_VERSION_4_2", "GL_VERSION_4_3", "GL_VERSION_4_4", "GL_VERSION_4_5", 49*61046927SAndroid Build Coastguard Worker )), 50*61046927SAndroid Build Coastguard Worker "glesv1" : frozenset(("GL_VERSION_ES_CM_1_0", "GL_OES_point_size_array")), 51*61046927SAndroid Build Coastguard Worker "glesv2" : frozenset(("GL_ES_VERSION_2_0", "GL_ES_VERSION_3_0", 52*61046927SAndroid Build Coastguard Worker "GL_ES_VERSION_3_1", "GL_ES_VERSION_3_2", 53*61046927SAndroid Build Coastguard Worker )), 54*61046927SAndroid Build Coastguard Worker} 55*61046927SAndroid Build Coastguard Worker 56*61046927SAndroid Build Coastguard Workerdef getFunctions(xmlFiles): 57*61046927SAndroid Build Coastguard Worker """ 58*61046927SAndroid Build Coastguard Worker Reads an XML file and returns all of the functions defined in it. 59*61046927SAndroid Build Coastguard Worker 60*61046927SAndroid Build Coastguard Worker xmlFile should be the path to Khronos's gl.xml file. The return value is a 61*61046927SAndroid Build Coastguard Worker sequence of FunctionDesc objects, ordered by slot number. 62*61046927SAndroid Build Coastguard Worker """ 63*61046927SAndroid Build Coastguard Worker roots = [ etree.parse(xmlFile).getroot() for xmlFile in xmlFiles ] 64*61046927SAndroid Build Coastguard Worker return getFunctionsFromRoots(roots) 65*61046927SAndroid Build Coastguard Worker 66*61046927SAndroid Build Coastguard Workerdef getFunctionsFromRoots(roots): 67*61046927SAndroid Build Coastguard Worker functions = {} 68*61046927SAndroid Build Coastguard Worker for root in roots: 69*61046927SAndroid Build Coastguard Worker for func in _getFunctionList(root): 70*61046927SAndroid Build Coastguard Worker functions[func.name] = func 71*61046927SAndroid Build Coastguard Worker functions = functions.values() 72*61046927SAndroid Build Coastguard Worker 73*61046927SAndroid Build Coastguard Worker # Sort the function list by name. 74*61046927SAndroid Build Coastguard Worker functions = sorted(functions, key=lambda f: f.name) 75*61046927SAndroid Build Coastguard Worker 76*61046927SAndroid Build Coastguard Worker # Lookup for fixed offset/slot functions and use it if available. 77*61046927SAndroid Build Coastguard Worker # Assign a slot number to each function. This isn't strictly necessary, 78*61046927SAndroid Build Coastguard Worker # since you can just look at the index in the list, but it makes it easier 79*61046927SAndroid Build Coastguard Worker # to include the slot when formatting output. 80*61046927SAndroid Build Coastguard Worker 81*61046927SAndroid Build Coastguard Worker next_slot = 0 82*61046927SAndroid Build Coastguard Worker for i in range(len(functions)): 83*61046927SAndroid Build Coastguard Worker name = functions[i].name[2:] 84*61046927SAndroid Build Coastguard Worker 85*61046927SAndroid Build Coastguard Worker if name in static_data.offsets: 86*61046927SAndroid Build Coastguard Worker functions[i] = functions[i]._replace(slot=static_data.offsets[name]) 87*61046927SAndroid Build Coastguard Worker elif not name.endswith("ARB") and name + "ARB" in static_data.offsets: 88*61046927SAndroid Build Coastguard Worker functions[i] = functions[i]._replace(slot=static_data.offsets[name + "ARB"]) 89*61046927SAndroid Build Coastguard Worker elif not name.endswith("EXT") and name + "EXT" in static_data.offsets: 90*61046927SAndroid Build Coastguard Worker functions[i] = functions[i]._replace(slot=static_data.offsets[name + "EXT"]) 91*61046927SAndroid Build Coastguard Worker else: 92*61046927SAndroid Build Coastguard Worker functions[i] = functions[i]._replace(slot=next_slot) 93*61046927SAndroid Build Coastguard Worker next_slot += 1 94*61046927SAndroid Build Coastguard Worker 95*61046927SAndroid Build Coastguard Worker return functions 96*61046927SAndroid Build Coastguard Worker 97*61046927SAndroid Build Coastguard Workerdef getExportNamesFromRoots(target, roots): 98*61046927SAndroid Build Coastguard Worker """ 99*61046927SAndroid Build Coastguard Worker Goes through the <feature> tags from gl.xml and returns a set of OpenGL 100*61046927SAndroid Build Coastguard Worker functions that a library should export. 101*61046927SAndroid Build Coastguard Worker 102*61046927SAndroid Build Coastguard Worker target should be one of "gl", "gldispatch", "opengl", "glesv1", or 103*61046927SAndroid Build Coastguard Worker "glesv2". 104*61046927SAndroid Build Coastguard Worker """ 105*61046927SAndroid Build Coastguard Worker featureNames = _LIBRARY_FEATURE_NAMES[target] 106*61046927SAndroid Build Coastguard Worker if featureNames is None: 107*61046927SAndroid Build Coastguard Worker return set(func.name for func in getFunctionsFromRoots(roots)) 108*61046927SAndroid Build Coastguard Worker 109*61046927SAndroid Build Coastguard Worker names = set() 110*61046927SAndroid Build Coastguard Worker for root in roots: 111*61046927SAndroid Build Coastguard Worker features = [] 112*61046927SAndroid Build Coastguard Worker for featElem in root.findall("feature"): 113*61046927SAndroid Build Coastguard Worker if featElem.get("name") in featureNames: 114*61046927SAndroid Build Coastguard Worker features.append(featElem) 115*61046927SAndroid Build Coastguard Worker for featElem in root.findall("extensions/extension"): 116*61046927SAndroid Build Coastguard Worker if featElem.get("name") in featureNames: 117*61046927SAndroid Build Coastguard Worker features.append(featElem) 118*61046927SAndroid Build Coastguard Worker for featElem in features: 119*61046927SAndroid Build Coastguard Worker for commandElem in featElem.findall("require/command"): 120*61046927SAndroid Build Coastguard Worker names.add(commandElem.get("name")) 121*61046927SAndroid Build Coastguard Worker return names 122*61046927SAndroid Build Coastguard Worker 123*61046927SAndroid Build Coastguard Workerclass FunctionArg(collections.namedtuple("FunctionArg", "type name")): 124*61046927SAndroid Build Coastguard Worker @property 125*61046927SAndroid Build Coastguard Worker def dec(self): 126*61046927SAndroid Build Coastguard Worker """ 127*61046927SAndroid Build Coastguard Worker Returns a "TYPE NAME" string, suitable for a function prototype. 128*61046927SAndroid Build Coastguard Worker """ 129*61046927SAndroid Build Coastguard Worker rv = str(self.type) 130*61046927SAndroid Build Coastguard Worker if not rv.endswith("*"): 131*61046927SAndroid Build Coastguard Worker rv += " " 132*61046927SAndroid Build Coastguard Worker rv += self.name 133*61046927SAndroid Build Coastguard Worker return rv 134*61046927SAndroid Build Coastguard Worker 135*61046927SAndroid Build Coastguard Workerclass FunctionDesc(collections.namedtuple("FunctionDesc", "name rt args slot")): 136*61046927SAndroid Build Coastguard Worker def hasReturn(self): 137*61046927SAndroid Build Coastguard Worker """ 138*61046927SAndroid Build Coastguard Worker Returns true if the function returns a value. 139*61046927SAndroid Build Coastguard Worker """ 140*61046927SAndroid Build Coastguard Worker return (self.rt != "void") 141*61046927SAndroid Build Coastguard Worker 142*61046927SAndroid Build Coastguard Worker @property 143*61046927SAndroid Build Coastguard Worker def decArgs(self): 144*61046927SAndroid Build Coastguard Worker """ 145*61046927SAndroid Build Coastguard Worker Returns a string with the types and names of the arguments, as you 146*61046927SAndroid Build Coastguard Worker would use in a function declaration. 147*61046927SAndroid Build Coastguard Worker """ 148*61046927SAndroid Build Coastguard Worker if not self.args: 149*61046927SAndroid Build Coastguard Worker return "void" 150*61046927SAndroid Build Coastguard Worker else: 151*61046927SAndroid Build Coastguard Worker return ", ".join(arg.dec for arg in self.args) 152*61046927SAndroid Build Coastguard Worker 153*61046927SAndroid Build Coastguard Worker @property 154*61046927SAndroid Build Coastguard Worker def callArgs(self): 155*61046927SAndroid Build Coastguard Worker """ 156*61046927SAndroid Build Coastguard Worker Returns a string with the names of the arguments, as you would use in a 157*61046927SAndroid Build Coastguard Worker function call. 158*61046927SAndroid Build Coastguard Worker """ 159*61046927SAndroid Build Coastguard Worker return ", ".join(arg.name for arg in self.args) 160*61046927SAndroid Build Coastguard Worker 161*61046927SAndroid Build Coastguard Worker @property 162*61046927SAndroid Build Coastguard Worker def basename(self): 163*61046927SAndroid Build Coastguard Worker assert self.name.startswith("gl") 164*61046927SAndroid Build Coastguard Worker return self.name[2:] 165*61046927SAndroid Build Coastguard Worker 166*61046927SAndroid Build Coastguard Workerdef _getFunctionList(root): 167*61046927SAndroid Build Coastguard Worker for elem in root.findall("commands/command"): 168*61046927SAndroid Build Coastguard Worker yield _parseCommandElem(elem) 169*61046927SAndroid Build Coastguard Worker 170*61046927SAndroid Build Coastguard Workerdef _parseCommandElem(elem): 171*61046927SAndroid Build Coastguard Worker protoElem = elem.find("proto") 172*61046927SAndroid Build Coastguard Worker (rt, name) = _parseProtoElem(protoElem) 173*61046927SAndroid Build Coastguard Worker 174*61046927SAndroid Build Coastguard Worker args = [] 175*61046927SAndroid Build Coastguard Worker for ch in elem.findall("param"): 176*61046927SAndroid Build Coastguard Worker # <param> tags have the same format as a <proto> tag. 177*61046927SAndroid Build Coastguard Worker args.append(FunctionArg(*_parseProtoElem(ch))) 178*61046927SAndroid Build Coastguard Worker func = FunctionDesc(name, rt, tuple(args), slot=None) 179*61046927SAndroid Build Coastguard Worker 180*61046927SAndroid Build Coastguard Worker return func 181*61046927SAndroid Build Coastguard Worker 182*61046927SAndroid Build Coastguard Workerdef _parseProtoElem(elem): 183*61046927SAndroid Build Coastguard Worker # If I just remove the tags and string the text together, I'll get valid C code. 184*61046927SAndroid Build Coastguard Worker text = _flattenText(elem) 185*61046927SAndroid Build Coastguard Worker text = text.strip() 186*61046927SAndroid Build Coastguard Worker m = re.match(r"^(.+)\b(\w+)(?:\s*\[\s*(\d*)\s*\])?$", text, re.S) 187*61046927SAndroid Build Coastguard Worker if m: 188*61046927SAndroid Build Coastguard Worker typename = _fixupTypeName(m.group(1)) 189*61046927SAndroid Build Coastguard Worker name = m.group(2) 190*61046927SAndroid Build Coastguard Worker if m.group(3): 191*61046927SAndroid Build Coastguard Worker # HACK: glPathGlyphIndexRangeNV defines an argument like this: 192*61046927SAndroid Build Coastguard Worker # GLuint baseAndCount[2] 193*61046927SAndroid Build Coastguard Worker # Convert it to a pointer and hope for the best. 194*61046927SAndroid Build Coastguard Worker typename += "*" 195*61046927SAndroid Build Coastguard Worker return (typename, name) 196*61046927SAndroid Build Coastguard Worker else: 197*61046927SAndroid Build Coastguard Worker raise ValueError("Can't parse element %r -> %r" % (elem, text)) 198*61046927SAndroid Build Coastguard Worker 199*61046927SAndroid Build Coastguard Workerdef _flattenText(elem): 200*61046927SAndroid Build Coastguard Worker """ 201*61046927SAndroid Build Coastguard Worker Returns the text in an element and all child elements, with the tags 202*61046927SAndroid Build Coastguard Worker removed. 203*61046927SAndroid Build Coastguard Worker """ 204*61046927SAndroid Build Coastguard Worker text = "" 205*61046927SAndroid Build Coastguard Worker if elem.text is not None: 206*61046927SAndroid Build Coastguard Worker text = elem.text 207*61046927SAndroid Build Coastguard Worker for ch in elem: 208*61046927SAndroid Build Coastguard Worker text += _flattenText(ch) 209*61046927SAndroid Build Coastguard Worker if ch.tail is not None: 210*61046927SAndroid Build Coastguard Worker text += ch.tail 211*61046927SAndroid Build Coastguard Worker return text 212*61046927SAndroid Build Coastguard Worker 213*61046927SAndroid Build Coastguard Workerdef _fixupTypeName(typeName): 214*61046927SAndroid Build Coastguard Worker """ 215*61046927SAndroid Build Coastguard Worker Converts a typename into a more consistent format. 216*61046927SAndroid Build Coastguard Worker """ 217*61046927SAndroid Build Coastguard Worker 218*61046927SAndroid Build Coastguard Worker rv = typeName.strip() 219*61046927SAndroid Build Coastguard Worker 220*61046927SAndroid Build Coastguard Worker # Replace "GLvoid" with just plain "void". 221*61046927SAndroid Build Coastguard Worker rv = re.sub(r"\bGLvoid\b", "void", rv) 222*61046927SAndroid Build Coastguard Worker 223*61046927SAndroid Build Coastguard Worker # Remove the vendor suffixes from types that have a suffix-less version. 224*61046927SAndroid Build Coastguard Worker rv = re.sub(r"\b(GLhalf|GLintptr|GLsizeiptr|GLint64|GLuint64)(?:ARB|EXT|NV|ATI)\b", r"\1", rv) 225*61046927SAndroid Build Coastguard Worker 226*61046927SAndroid Build Coastguard Worker rv = re.sub(r"\bGLDEBUGPROCKHR\b", "GLDEBUGPROC", rv) 227*61046927SAndroid Build Coastguard Worker 228*61046927SAndroid Build Coastguard Worker # Clear out any leading and trailing whitespace. 229*61046927SAndroid Build Coastguard Worker rv = rv.strip() 230*61046927SAndroid Build Coastguard Worker 231*61046927SAndroid Build Coastguard Worker # Remove any whitespace before a '*' 232*61046927SAndroid Build Coastguard Worker rv = re.sub(r"\s+\*", r"*", rv) 233*61046927SAndroid Build Coastguard Worker 234*61046927SAndroid Build Coastguard Worker # Change "foo*" to "foo *" 235*61046927SAndroid Build Coastguard Worker rv = re.sub(r"([^\*])\*", r"\1 *", rv) 236*61046927SAndroid Build Coastguard Worker 237*61046927SAndroid Build Coastguard Worker # Condense all whitespace into a single space. 238*61046927SAndroid Build Coastguard Worker rv = re.sub(r"\s+", " ", rv) 239*61046927SAndroid Build Coastguard Worker 240*61046927SAndroid Build Coastguard Worker return rv 241*61046927SAndroid Build Coastguard Worker 242