1#!/usr/bin/env python3 2 3# (C) Copyright 2016, NVIDIA CORPORATION. 4# All Rights Reserved. 5# 6# Permission is hereby granted, free of charge, to any person obtaining a 7# copy of this software and associated documentation files (the "Software"), 8# to deal in the Software without restriction, including without limitation 9# on the rights to use, copy, modify, merge, publish, distribute, sub 10# license, and/or sell copies of the Software, and to permit persons to whom 11# the Software is furnished to do so, subject to the following conditions: 12# 13# The above copyright notice and this permission notice (including the next 14# paragraph) shall be included in all copies or substantial portions of the 15# Software. 16# 17# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 20# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23# IN THE SOFTWARE. 24# 25# Authors: 26# Kyle Brenneman <[email protected]> 27 28""" 29Generates dispatch functions for EGL. 30 31The list of functions and arguments is read from the Khronos's XML files, with 32additional information defined in the module eglFunctionList. 33""" 34 35import argparse 36import collections 37import eglFunctionList 38import sys 39import textwrap 40 41import os 42NEWAPI = os.path.join(os.path.dirname(__file__), "..", "..", "mapi", "new") 43sys.path.insert(0, NEWAPI) 44import genCommon 45 46def main(): 47 parser = argparse.ArgumentParser() 48 parser.add_argument("target", choices=("header", "source"), 49 help="Whether to build the source or header file.") 50 parser.add_argument("xml_files", nargs="+", help="The XML files with the EGL function lists.") 51 52 args = parser.parse_args() 53 54 xmlFunctions = genCommon.getFunctions(args.xml_files) 55 xmlByName = dict((f.name, f) for f in xmlFunctions) 56 functions = [] 57 for (name, eglFunc) in eglFunctionList.EGL_FUNCTIONS: 58 func = xmlByName[name] 59 eglFunc = fixupEglFunc(func, eglFunc) 60 functions.append((func, eglFunc)) 61 62 # Sort the function list by name. 63 functions = sorted(functions, key=lambda f: f[0].name) 64 65 if args.target == "header": 66 text = generateHeader(functions) 67 elif args.target == "source": 68 text = generateSource(functions) 69 sys.stdout.write(text) 70 71def fixupEglFunc(func, eglFunc): 72 result = dict(eglFunc) 73 if result.get("prefix") is None: 74 result["prefix"] = "" 75 76 if result.get("extension") is not None: 77 text = "defined(" + result["extension"] + ")" 78 result["extension"] = text 79 80 if result["method"] in ("none", "custom"): 81 return result 82 83 if result["method"] not in ("display", "device", "current"): 84 raise ValueError("Invalid dispatch method %r for function %r" % (result["method"], func.name)) 85 86 if func.hasReturn(): 87 if result.get("retval") is None: 88 result["retval"] = getDefaultReturnValue(func.rt) 89 90 return result 91 92def generateHeader(functions): 93 text = textwrap.dedent(r""" 94 #ifndef G_EGLDISPATCH_STUBS_H 95 #define G_EGLDISPATCH_STUBS_H 96 97 #ifdef __cplusplus 98 extern "C" { 99 #endif 100 101 #include <EGL/egl.h> 102 #include <EGL/eglext.h> 103 #include <EGL/eglmesaext.h> 104 #include <EGL/eglext_angle.h> 105 #include <GL/mesa_glinterop.h> 106 #include "glvnd/libeglabi.h" 107 108 """.lstrip("\n")) 109 110 text += "enum {\n" 111 for (func, eglFunc) in functions: 112 text += generateGuardBegin(func, eglFunc) 113 text += " __EGL_DISPATCH_" + func.name + ",\n" 114 text += generateGuardEnd(func, eglFunc) 115 text += " __EGL_DISPATCH_COUNT\n" 116 text += "};\n" 117 118 for (func, eglFunc) in functions: 119 if eglFunc["inheader"]: 120 text += generateGuardBegin(func, eglFunc) 121 text += "{f.rt} EGLAPIENTRY {ex[prefix]}{f.name}({f.decArgs});\n".format(f=func, ex=eglFunc) 122 text += generateGuardEnd(func, eglFunc) 123 124 text += textwrap.dedent(r""" 125 #ifdef __cplusplus 126 } 127 #endif 128 #endif // G_EGLDISPATCH_STUBS_H 129 """) 130 return text 131 132def generateSource(functions): 133 # First, sort the function list by name. 134 text = "" 135 text += '#include "egldispatchstubs.h"\n' 136 text += '#include "g_egldispatchstubs.h"\n' 137 text += '#include <stddef.h>\n' 138 text += "\n" 139 140 for (func, eglFunc) in functions: 141 if eglFunc["method"] not in ("custom", "none"): 142 text += generateGuardBegin(func, eglFunc) 143 text += generateDispatchFunc(func, eglFunc) 144 text += generateGuardEnd(func, eglFunc) 145 146 text += "\n" 147 text += "const char * const __EGL_DISPATCH_FUNC_NAMES[__EGL_DISPATCH_COUNT + 1] = {\n" 148 for (func, eglFunc) in functions: 149 text += generateGuardBegin(func, eglFunc) 150 text += ' "' + func.name + '",\n' 151 text += generateGuardEnd(func, eglFunc) 152 text += " NULL\n" 153 text += "};\n" 154 155 text += "const __eglMustCastToProperFunctionPointerType __EGL_DISPATCH_FUNCS[__EGL_DISPATCH_COUNT + 1] = {\n" 156 for (func, eglFunc) in functions: 157 text += generateGuardBegin(func, eglFunc) 158 if eglFunc["method"] != "none": 159 text += " (__eglMustCastToProperFunctionPointerType) " + eglFunc.get("prefix", "") + func.name + ",\n" 160 else: 161 text += " NULL, // " + func.name + "\n" 162 text += generateGuardEnd(func, eglFunc) 163 text += " NULL\n" 164 text += "};\n" 165 166 return text 167 168def generateGuardBegin(func, eglFunc): 169 ext = eglFunc.get("extension") 170 if ext is not None: 171 return "#if " + ext + "\n" 172 else: 173 return "" 174 175def generateGuardEnd(func, eglFunc): 176 if eglFunc.get("extension") is not None: 177 return "#endif\n" 178 else: 179 return "" 180 181def generateDispatchFunc(func, eglFunc): 182 text = "" 183 184 if eglFunc.get("static"): 185 text += "static " 186 elif eglFunc.get("public"): 187 text += "PUBLIC " 188 text += textwrap.dedent( 189 r""" 190 {f.rt} EGLAPIENTRY {ef[prefix]}{f.name}({f.decArgs}) 191 {{ 192 typedef {f.rt} EGLAPIENTRY (* _pfn_{f.name})({f.decArgs}); 193 """).lstrip("\n").format(f=func, ef=eglFunc) 194 195 if func.hasReturn(): 196 text += " {f.rt} _ret = {ef[retval]};\n".format(f=func, ef=eglFunc) 197 198 text += " _pfn_{f.name} _ptr_{f.name} = (_pfn_{f.name}) ".format(f=func) 199 if eglFunc["method"] == "current": 200 text += "__eglDispatchFetchByCurrent(__EGL_DISPATCH_{f.name});\n".format(f=func) 201 202 elif eglFunc["method"] in ("display", "device"): 203 if eglFunc["method"] == "display": 204 lookupFunc = "__eglDispatchFetchByDisplay" 205 lookupType = "EGLDisplay" 206 else: 207 assert eglFunc["method"] == "device" 208 lookupFunc = "__eglDispatchFetchByDevice" 209 lookupType = "EGLDeviceEXT" 210 211 lookupArg = None 212 for arg in func.args: 213 if arg.type == lookupType: 214 lookupArg = arg.name 215 break 216 if lookupArg is None: 217 raise ValueError("Can't find %s argument for function %s" % (lookupType, func.name,)) 218 219 text += "{lookupFunc}({lookupArg}, __EGL_DISPATCH_{f.name});\n".format( 220 f=func, lookupFunc=lookupFunc, lookupArg=lookupArg) 221 else: 222 raise ValueError("Unknown dispatch method: %r" % (eglFunc["method"],)) 223 224 text += " if(_ptr_{f.name} != NULL) {{\n".format(f=func) 225 text += " " 226 if func.hasReturn(): 227 text += "_ret = " 228 text += "_ptr_{f.name}({f.callArgs});\n".format(f=func) 229 text += " }\n" 230 231 if func.hasReturn(): 232 text += " return _ret;\n" 233 text += "}\n" 234 return text 235 236def getDefaultReturnValue(typename): 237 if typename.endswith("*"): 238 return "NULL" 239 elif typename == "EGLDisplay": 240 return "EGL_NO_DISPLAY" 241 elif typename == "EGLContext": 242 return "EGL_NO_CONTEXT" 243 elif typename == "EGLSurface": 244 return "EGL_NO_SURFACE" 245 elif typename == "EGLBoolean": 246 return "EGL_FALSE"; 247 248 return "0" 249 250if __name__ == "__main__": 251 main() 252 253