Path: blob/21.2-virgl/src/egl/generate/gen_egl_dispatch.py
4560 views
#!/usr/bin/env python12# (C) Copyright 2016, NVIDIA CORPORATION.3# All Rights Reserved.4#5# Permission is hereby granted, free of charge, to any person obtaining a6# copy of this software and associated documentation files (the "Software"),7# to deal in the Software without restriction, including without limitation8# on the rights to use, copy, modify, merge, publish, distribute, sub9# license, and/or sell copies of the Software, and to permit persons to whom10# the Software is furnished to do so, subject to the following conditions:11#12# The above copyright notice and this permission notice (including the next13# paragraph) shall be included in all copies or substantial portions of the14# Software.15#16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,18# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL19# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING21# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS22# IN THE SOFTWARE.23#24# Authors:25# Kyle Brenneman <[email protected]>2627"""28Generates dispatch functions for EGL.2930The list of functions and arguments is read from the Khronos's XML files, with31additional information defined in the module eglFunctionList.32"""3334import argparse35import collections36import eglFunctionList37import sys38import textwrap3940import os41NEWAPI = os.path.join(os.path.dirname(__file__), "..", "..", "mapi", "new")42sys.path.insert(0, NEWAPI)43import genCommon4445def main():46parser = argparse.ArgumentParser()47parser.add_argument("target", choices=("header", "source"),48help="Whether to build the source or header file.")49parser.add_argument("xml_files", nargs="+", help="The XML files with the EGL function lists.")5051args = parser.parse_args()5253xmlFunctions = genCommon.getFunctions(args.xml_files)54xmlByName = dict((f.name, f) for f in xmlFunctions)55functions = []56for (name, eglFunc) in eglFunctionList.EGL_FUNCTIONS:57func = xmlByName[name]58eglFunc = fixupEglFunc(func, eglFunc)59functions.append((func, eglFunc))6061# Sort the function list by name.62functions = sorted(functions, key=lambda f: f[0].name)6364if args.target == "header":65text = generateHeader(functions)66elif args.target == "source":67text = generateSource(functions)68sys.stdout.write(text)6970def fixupEglFunc(func, eglFunc):71result = dict(eglFunc)72if result.get("prefix") is None:73result["prefix"] = ""7475if result.get("extension") is not None:76text = "defined(" + result["extension"] + ")"77result["extension"] = text7879if result["method"] in ("none", "custom"):80return result8182if result["method"] not in ("display", "device", "current"):83raise ValueError("Invalid dispatch method %r for function %r" % (result["method"], func.name))8485if func.hasReturn():86if result.get("retval") is None:87result["retval"] = getDefaultReturnValue(func.rt)8889return result9091def generateHeader(functions):92text = textwrap.dedent(r"""93#ifndef G_EGLDISPATCH_STUBS_H94#define G_EGLDISPATCH_STUBS_H9596#ifdef __cplusplus97extern "C" {98#endif99100#include <EGL/egl.h>101#include <EGL/eglext.h>102#include <EGL/eglmesaext.h>103#include <EGL/eglextchromium.h>104#include "glvnd/libeglabi.h"105106""".lstrip("\n"))107108text += "enum {\n"109for (func, eglFunc) in functions:110text += generateGuardBegin(func, eglFunc)111text += " __EGL_DISPATCH_" + func.name + ",\n"112text += generateGuardEnd(func, eglFunc)113text += " __EGL_DISPATCH_COUNT\n"114text += "};\n"115116for (func, eglFunc) in functions:117if eglFunc["inheader"]:118text += generateGuardBegin(func, eglFunc)119text += "{f.rt} EGLAPIENTRY {ex[prefix]}{f.name}({f.decArgs});\n".format(f=func, ex=eglFunc)120text += generateGuardEnd(func, eglFunc)121122text += textwrap.dedent(r"""123#ifdef __cplusplus124}125#endif126#endif // G_EGLDISPATCH_STUBS_H127""")128return text129130def generateSource(functions):131# First, sort the function list by name.132text = ""133text += '#include "egldispatchstubs.h"\n'134text += '#include "g_egldispatchstubs.h"\n'135text += '#include <stddef.h>\n'136text += "\n"137138for (func, eglFunc) in functions:139if eglFunc["method"] not in ("custom", "none"):140text += generateGuardBegin(func, eglFunc)141text += generateDispatchFunc(func, eglFunc)142text += generateGuardEnd(func, eglFunc)143144text += "\n"145text += "const char * const __EGL_DISPATCH_FUNC_NAMES[__EGL_DISPATCH_COUNT + 1] = {\n"146for (func, eglFunc) in functions:147text += generateGuardBegin(func, eglFunc)148text += ' "' + func.name + '",\n'149text += generateGuardEnd(func, eglFunc)150text += " NULL\n"151text += "};\n"152153text += "const __eglMustCastToProperFunctionPointerType __EGL_DISPATCH_FUNCS[__EGL_DISPATCH_COUNT + 1] = {\n"154for (func, eglFunc) in functions:155text += generateGuardBegin(func, eglFunc)156if eglFunc["method"] != "none":157text += " (__eglMustCastToProperFunctionPointerType) " + eglFunc.get("prefix", "") + func.name + ",\n"158else:159text += " NULL, // " + func.name + "\n"160text += generateGuardEnd(func, eglFunc)161text += " NULL\n"162text += "};\n"163164return text165166def generateGuardBegin(func, eglFunc):167ext = eglFunc.get("extension")168if ext is not None:169return "#if " + ext + "\n"170else:171return ""172173def generateGuardEnd(func, eglFunc):174if eglFunc.get("extension") is not None:175return "#endif\n"176else:177return ""178179def generateDispatchFunc(func, eglFunc):180text = ""181182if eglFunc.get("static"):183text += "static "184elif eglFunc.get("public"):185text += "PUBLIC "186text += textwrap.dedent(187r"""188{f.rt} EGLAPIENTRY {ef[prefix]}{f.name}({f.decArgs})189{{190typedef {f.rt} EGLAPIENTRY (* _pfn_{f.name})({f.decArgs});191""").lstrip("\n").format(f=func, ef=eglFunc)192193if func.hasReturn():194text += " {f.rt} _ret = {ef[retval]};\n".format(f=func, ef=eglFunc)195196text += " _pfn_{f.name} _ptr_{f.name} = (_pfn_{f.name}) ".format(f=func)197if eglFunc["method"] == "current":198text += "__eglDispatchFetchByCurrent(__EGL_DISPATCH_{f.name});\n".format(f=func)199200elif eglFunc["method"] in ("display", "device"):201if eglFunc["method"] == "display":202lookupFunc = "__eglDispatchFetchByDisplay"203lookupType = "EGLDisplay"204else:205assert eglFunc["method"] == "device"206lookupFunc = "__eglDispatchFetchByDevice"207lookupType = "EGLDeviceEXT"208209lookupArg = None210for arg in func.args:211if arg.type == lookupType:212lookupArg = arg.name213break214if lookupArg is None:215raise ValueError("Can't find %s argument for function %s" % (lookupType, func.name,))216217text += "{lookupFunc}({lookupArg}, __EGL_DISPATCH_{f.name});\n".format(218f=func, lookupFunc=lookupFunc, lookupArg=lookupArg)219else:220raise ValueError("Unknown dispatch method: %r" % (eglFunc["method"],))221222text += " if(_ptr_{f.name} != NULL) {{\n".format(f=func)223text += " "224if func.hasReturn():225text += "_ret = "226text += "_ptr_{f.name}({f.callArgs});\n".format(f=func)227text += " }\n"228229if func.hasReturn():230text += " return _ret;\n"231text += "}\n"232return text233234def getDefaultReturnValue(typename):235if typename.endswith("*"):236return "NULL"237elif typename == "EGLDisplay":238return "EGL_NO_DISPLAY"239elif typename == "EGLContext":240return "EGL_NO_CONTEXT"241elif typename == "EGLSurface":242return "EGL_NO_SURFACE"243elif typename == "EGLBoolean":244return "EGL_FALSE";245246return "0"247248if __name__ == "__main__":249main()250251252253