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 <kbrenneman@nvidia.com> 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/eglextchromium.h> 105 #include "glvnd/libeglabi.h" 106 107 """.lstrip("\n")) 108 109 text += "enum {\n" 110 for (func, eglFunc) in functions: 111 text += generateGuardBegin(func, eglFunc) 112 text += " __EGL_DISPATCH_" + func.name + ",\n" 113 text += generateGuardEnd(func, eglFunc) 114 text += " __EGL_DISPATCH_COUNT\n" 115 text += "};\n" 116 117 for (func, eglFunc) in functions: 118 if eglFunc["inheader"]: 119 text += generateGuardBegin(func, eglFunc) 120 text += "{f.rt} EGLAPIENTRY {ex[prefix]}{f.name}({f.decArgs});\n".format(f=func, ex=eglFunc) 121 text += generateGuardEnd(func, eglFunc) 122 123 text += textwrap.dedent(r""" 124 #ifdef __cplusplus 125 } 126 #endif 127 #endif // G_EGLDISPATCH_STUBS_H 128 """) 129 return text 130 131def generateSource(functions): 132 # First, sort the function list by name. 133 text = "" 134 text += '#include "egldispatchstubs.h"\n' 135 text += '#include "g_egldispatchstubs.h"\n' 136 text += '#include <stddef.h>\n' 137 text += "\n" 138 139 for (func, eglFunc) in functions: 140 if eglFunc["method"] not in ("custom", "none"): 141 text += generateGuardBegin(func, eglFunc) 142 text += generateDispatchFunc(func, eglFunc) 143 text += generateGuardEnd(func, eglFunc) 144 145 text += "\n" 146 text += "const char * const __EGL_DISPATCH_FUNC_NAMES[__EGL_DISPATCH_COUNT + 1] = {\n" 147 for (func, eglFunc) in functions: 148 text += generateGuardBegin(func, eglFunc) 149 text += ' "' + func.name + '",\n' 150 text += generateGuardEnd(func, eglFunc) 151 text += " NULL\n" 152 text += "};\n" 153 154 text += "const __eglMustCastToProperFunctionPointerType __EGL_DISPATCH_FUNCS[__EGL_DISPATCH_COUNT + 1] = {\n" 155 for (func, eglFunc) in functions: 156 text += generateGuardBegin(func, eglFunc) 157 if eglFunc["method"] != "none": 158 text += " (__eglMustCastToProperFunctionPointerType) " + eglFunc.get("prefix", "") + func.name + ",\n" 159 else: 160 text += " NULL, // " + func.name + "\n" 161 text += generateGuardEnd(func, eglFunc) 162 text += " NULL\n" 163 text += "};\n" 164 165 return text 166 167def generateGuardBegin(func, eglFunc): 168 ext = eglFunc.get("extension") 169 if ext is not None: 170 return "#if " + ext + "\n" 171 else: 172 return "" 173 174def generateGuardEnd(func, eglFunc): 175 if eglFunc.get("extension") is not None: 176 return "#endif\n" 177 else: 178 return "" 179 180def generateDispatchFunc(func, eglFunc): 181 text = "" 182 183 if eglFunc.get("static"): 184 text += "static " 185 elif eglFunc.get("public"): 186 text += "PUBLIC " 187 text += textwrap.dedent( 188 r""" 189 {f.rt} EGLAPIENTRY {ef[prefix]}{f.name}({f.decArgs}) 190 {{ 191 typedef {f.rt} EGLAPIENTRY (* _pfn_{f.name})({f.decArgs}); 192 """).lstrip("\n").format(f=func, ef=eglFunc) 193 194 if func.hasReturn(): 195 text += " {f.rt} _ret = {ef[retval]};\n".format(f=func, ef=eglFunc) 196 197 text += " _pfn_{f.name} _ptr_{f.name} = (_pfn_{f.name}) ".format(f=func) 198 if eglFunc["method"] == "current": 199 text += "__eglDispatchFetchByCurrent(__EGL_DISPATCH_{f.name});\n".format(f=func) 200 201 elif eglFunc["method"] in ("display", "device"): 202 if eglFunc["method"] == "display": 203 lookupFunc = "__eglDispatchFetchByDisplay" 204 lookupType = "EGLDisplay" 205 else: 206 assert eglFunc["method"] == "device" 207 lookupFunc = "__eglDispatchFetchByDevice" 208 lookupType = "EGLDeviceEXT" 209 210 lookupArg = None 211 for arg in func.args: 212 if arg.type == lookupType: 213 lookupArg = arg.name 214 break 215 if lookupArg is None: 216 raise ValueError("Can't find %s argument for function %s" % (lookupType, func.name,)) 217 218 text += "{lookupFunc}({lookupArg}, __EGL_DISPATCH_{f.name});\n".format( 219 f=func, lookupFunc=lookupFunc, lookupArg=lookupArg) 220 else: 221 raise ValueError("Unknown dispatch method: %r" % (eglFunc["method"],)) 222 223 text += " if(_ptr_{f.name} != NULL) {{\n".format(f=func) 224 text += " " 225 if func.hasReturn(): 226 text += "_ret = " 227 text += "_ptr_{f.name}({f.callArgs});\n".format(f=func) 228 text += " }\n" 229 230 if func.hasReturn(): 231 text += " return _ret;\n" 232 text += "}\n" 233 return text 234 235def getDefaultReturnValue(typename): 236 if typename.endswith("*"): 237 return "NULL" 238 elif typename == "EGLDisplay": 239 return "EGL_NO_DISPLAY" 240 elif typename == "EGLContext": 241 return "EGL_NO_CONTEXT" 242 elif typename == "EGLSurface": 243 return "EGL_NO_SURFACE" 244 elif typename == "EGLBoolean": 245 return "EGL_FALSE"; 246 247 return "0" 248 249if __name__ == "__main__": 250 main() 251 252