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