Blame src/generate/gen_egl_dispatch.py

Packit Service c8dffe
#!/usr/bin/python3
Packit Service 9e77c8
Packit Service 9e77c8
"""
Packit Service 9e77c8
Generates dispatch functions for EGL.
Packit Service 9e77c8
Packit Service 9e77c8
The list of functions and arguments is read from the Khronos's XML files, with
Packit Service 9e77c8
additional information defined in the module eglFunctionList.
Packit Service 9e77c8
"""
Packit Service 9e77c8
Packit Service 9e77c8
import sys
Packit Service 9e77c8
import collections
Packit Service 9e77c8
import imp
Packit Service 9e77c8
Packit Service 9e77c8
import genCommon
Packit Service 9e77c8
Packit Service 9e77c8
def main():
Packit Service 9e77c8
    if (len(sys.argv) < 4):
Packit Service 9e77c8
        print("Usage: %r source|header <function_list> <xml_file> [xml_file...]" % (sys.argv[0],))
Packit Service 9e77c8
        sys.exit(2)
Packit Service 9e77c8
Packit Service 9e77c8
    target = sys.argv[1]
Packit Service 9e77c8
    funcListFile = sys.argv[2]
Packit Service 9e77c8
    xmlFiles = sys.argv[3:]
Packit Service 9e77c8
Packit Service 9e77c8
    # The function list is a Python module, but it's specified on the command
Packit Service 9e77c8
    # line.
Packit Service 9e77c8
    eglFunctionList = imp.load_source("eglFunctionList", funcListFile)
Packit Service 9e77c8
Packit Service 9e77c8
    xmlFunctions = genCommon.getFunctions(xmlFiles)
Packit Service 9e77c8
    xmlByName = dict((f.name, f) for f in xmlFunctions)
Packit Service 9e77c8
    functions = []
Packit Service 9e77c8
    for (name, eglFunc) in eglFunctionList.EGL_FUNCTIONS:
Packit Service 9e77c8
        func = xmlByName[name]
Packit Service 9e77c8
        eglFunc = fixupEglFunc(func, eglFunc)
Packit Service 9e77c8
        functions.append((func, eglFunc))
Packit Service 9e77c8
Packit Service 9e77c8
    # Sort the function list by name.
Packit Service 9e77c8
    functions = sorted(functions, key=lambda f: f[0].name)
Packit Service 9e77c8
Packit Service 9e77c8
    if (target == "header"):
Packit Service 9e77c8
        text = generateHeader(functions)
Packit Service 9e77c8
    elif (target == "source"):
Packit Service 9e77c8
        text = generateSource(functions)
Packit Service 9e77c8
    else:
Packit Service 9e77c8
        raise ValueError("Invalid target: %r" % (target,))
Packit Service 9e77c8
    sys.stdout.write(text)
Packit Service 9e77c8
Packit Service 9e77c8
def fixupEglFunc(func, eglFunc):
Packit Service 9e77c8
    result = dict(eglFunc)
Packit Service 9e77c8
    if (result.get("prefix") == None):
Packit Service 9e77c8
        result["prefix"] = ""
Packit Service 9e77c8
Packit Service 9e77c8
    if (result.get("extension") != None):
Packit Service 9e77c8
        text = "defined(" + result["extension"] + ")"
Packit Service 9e77c8
        result["extension"] = text
Packit Service 9e77c8
Packit Service 9e77c8
    if (result["method"] in ("none", "custom")):
Packit Service 9e77c8
        return result
Packit Service 9e77c8
Packit Service 9e77c8
    if (result["method"] not in ("display", "device", "current")):
Packit Service 9e77c8
        raise ValueError("Invalid dispatch method %r for function %r" % (result["method"], func.name))
Packit Service 9e77c8
Packit Service 9e77c8
    if (func.hasReturn()):
Packit Service 9e77c8
        if (result.get("retval") == None):
Packit Service 9e77c8
            result["retval"] = getDefaultReturnValue(func.rt)
Packit Service 9e77c8
Packit Service 9e77c8
    return result
Packit Service 9e77c8
Packit Service 9e77c8
def generateHeader(functions):
Packit Service 9e77c8
    text = r"""
Packit Service 9e77c8
#ifndef G_EGLDISPATCH_STUBS_H
Packit Service 9e77c8
#define G_EGLDISPATCH_STUBS_H
Packit Service 9e77c8
Packit Service 9e77c8
#ifdef __cplusplus
Packit Service 9e77c8
extern "C" {
Packit Service 9e77c8
#endif
Packit Service 9e77c8
Packit Service 9e77c8
#include <EGL/egl.h>
Packit Service 9e77c8
#include <EGL/eglext.h>
Packit Service 9e77c8
#include "glvnd/libeglabi.h"
Packit Service 9e77c8
Packit Service 9e77c8
""".lstrip("\n")
Packit Service 9e77c8
Packit Service 9e77c8
    text += "enum {\n"
Packit Service 9e77c8
    for (func, eglFunc) in functions:
Packit Service 9e77c8
        text += generateGuardBegin(func, eglFunc)
Packit Service 9e77c8
        text += "    __EGL_DISPATCH_" + func.name + ",\n"
Packit Service 9e77c8
        text += generateGuardEnd(func, eglFunc)
Packit Service 9e77c8
    text += "    __EGL_DISPATCH_COUNT\n"
Packit Service 9e77c8
    text += "};\n"
Packit Service 9e77c8
Packit Service 9e77c8
    for (func, eglFunc) in functions:
Packit Service 9e77c8
        if (eglFunc["inheader"]):
Packit Service 9e77c8
            text += generateGuardBegin(func, eglFunc)
Packit Service 9e77c8
            text += "{f.rt} EGLAPIENTRY {ex[prefix]}{f.name}({f.decArgs});\n".format(f=func, ex=eglFunc)
Packit Service 9e77c8
            text += generateGuardEnd(func, eglFunc)
Packit Service 9e77c8
Packit Service 9e77c8
    text += r"""
Packit Service 9e77c8
#ifdef __cplusplus
Packit Service 9e77c8
}
Packit Service 9e77c8
#endif
Packit Service 9e77c8
#endif // G_EGLDISPATCH_STUBS_H
Packit Service 9e77c8
"""
Packit Service 9e77c8
    return text
Packit Service 9e77c8
Packit Service 9e77c8
def generateSource(functions):
Packit Service 9e77c8
    # First, sort the function list by name.
Packit Service 9e77c8
    text = ""
Packit Service 9e77c8
    text += '#include "egldispatchstubs.h"\n'
Packit Service 9e77c8
    text += '#include "g_egldispatchstubs.h"\n'
Packit Service 9e77c8
    text += "\n"
Packit Service 9e77c8
Packit Service 9e77c8
    for (func, eglFunc) in functions:
Packit Service 9e77c8
        if (eglFunc["method"] not in ("custom", "none")):
Packit Service 9e77c8
            text += generateGuardBegin(func, eglFunc)
Packit Service 9e77c8
            text += generateDispatchFunc(func, eglFunc)
Packit Service 9e77c8
            text += generateGuardEnd(func, eglFunc)
Packit Service 9e77c8
Packit Service 9e77c8
    text += "\n"
Packit Service 9e77c8
    text += "const char * const __EGL_DISPATCH_FUNC_NAMES[__EGL_DISPATCH_COUNT + 1] = {\n"
Packit Service 9e77c8
    for (func, eglFunc) in functions:
Packit Service 9e77c8
        text += generateGuardBegin(func, eglFunc)
Packit Service 9e77c8
        text += '    "' + func.name + '",\n'
Packit Service 9e77c8
        text += generateGuardEnd(func, eglFunc)
Packit Service 9e77c8
    text += "    NULL\n"
Packit Service 9e77c8
    text += "};\n"
Packit Service 9e77c8
Packit Service 9e77c8
    text += "const __eglMustCastToProperFunctionPointerType __EGL_DISPATCH_FUNCS[__EGL_DISPATCH_COUNT + 1] = {\n"
Packit Service 9e77c8
    for (func, eglFunc) in functions:
Packit Service 9e77c8
        text += generateGuardBegin(func, eglFunc)
Packit Service 9e77c8
        if (eglFunc["method"] != "none"):
Packit Service 9e77c8
            text += "    (__eglMustCastToProperFunctionPointerType) " + eglFunc.get("prefix", "") + func.name + ",\n"
Packit Service 9e77c8
        else:
Packit Service 9e77c8
            text += "    NULL, // " + func.name + "\n"
Packit Service 9e77c8
        text += generateGuardEnd(func, eglFunc)
Packit Service 9e77c8
    text += "    NULL\n"
Packit Service 9e77c8
    text += "};\n"
Packit Service 9e77c8
Packit Service 9e77c8
    return text
Packit Service 9e77c8
Packit Service 9e77c8
def generateGuardBegin(func, eglFunc):
Packit Service 9e77c8
    ext = eglFunc.get("extension")
Packit Service 9e77c8
    if (ext != None):
Packit Service 9e77c8
        return "#if " + ext + "\n"
Packit Service 9e77c8
    else:
Packit Service 9e77c8
        return ""
Packit Service 9e77c8
Packit Service 9e77c8
def generateGuardEnd(func, eglFunc):
Packit Service 9e77c8
    if (eglFunc.get("extension") != None):
Packit Service 9e77c8
        return "#endif\n"
Packit Service 9e77c8
    else:
Packit Service 9e77c8
        return ""
Packit Service 9e77c8
Packit Service 9e77c8
def generateDispatchFunc(func, eglFunc):
Packit Service 9e77c8
    text = ""
Packit Service 9e77c8
Packit Service 9e77c8
    if (eglFunc.get("static")):
Packit Service 9e77c8
        text += "static "
Packit Service 9e77c8
    else:
Packit Service 9e77c8
        text += "PUBLIC "
Packit Service 9e77c8
    text += r"""{f.rt} EGLAPIENTRY {ef[prefix]}{f.name}({f.decArgs})
Packit Service 9e77c8
{{
Packit Service 9e77c8
    typedef {f.rt} EGLAPIENTRY (* _pfn_{f.name})({f.decArgs});
Packit Service 9e77c8
""".format(f=func, ef=eglFunc)
Packit Service 9e77c8
Packit Service 9e77c8
    if (func.hasReturn()):
Packit Service 9e77c8
        text += "    {f.rt} _ret = {ef[retval]};\n".format(f=func, ef=eglFunc)
Packit Service 9e77c8
Packit Service 9e77c8
    text += "    _pfn_{f.name} _ptr_{f.name} = (_pfn_{f.name}) ".format(f=func)
Packit Service 9e77c8
    if (eglFunc["method"] == "current"):
Packit Service 9e77c8
        text += "__eglDispatchFetchByCurrent(__EGL_DISPATCH_{f.name});\n".format(f=func)
Packit Service 9e77c8
Packit Service 9e77c8
    elif (eglFunc["method"] in ("display", "device")):
Packit Service 9e77c8
        if (eglFunc["method"] == "display"):
Packit Service 9e77c8
            lookupFunc = "__eglDispatchFetchByDisplay"
Packit Service 9e77c8
            lookupType = "EGLDisplay"
Packit Service 9e77c8
        else:
Packit Service 9e77c8
            assert(eglFunc["method"] == "device")
Packit Service 9e77c8
            lookupFunc = "__eglDispatchFetchByDevice"
Packit Service 9e77c8
            lookupType = "EGLDeviceEXT"
Packit Service 9e77c8
Packit Service 9e77c8
        lookupArg = None
Packit Service 9e77c8
        for arg in func.args:
Packit Service 9e77c8
            if (arg.type == lookupType):
Packit Service 9e77c8
                lookupArg = arg.name
Packit Service 9e77c8
                break
Packit Service 9e77c8
        if (lookupArg == None):
Packit Service 9e77c8
            raise ValueError("Can't find %s argument for function %s" % (lookupType, func.name,))
Packit Service 9e77c8
Packit Service 9e77c8
        text += "{lookupFunc}({lookupArg}, __EGL_DISPATCH_{f.name});\n".format(
Packit Service 9e77c8
                f=func, lookupFunc=lookupFunc, lookupArg=lookupArg)
Packit Service 9e77c8
    else:
Packit Service 9e77c8
        raise ValueError("Unknown dispatch method: %r" % (eglFunc["method"],))
Packit Service 9e77c8
Packit Service 9e77c8
    text += "    if(_ptr_{f.name} != NULL) {{\n".format(f=func)
Packit Service 9e77c8
    text += "        "
Packit Service 9e77c8
    if (func.hasReturn()):
Packit Service 9e77c8
        text += "_ret = "
Packit Service 9e77c8
    text += "_ptr_{f.name}({f.callArgs});\n".format(f=func)
Packit Service 9e77c8
    text += "    }\n"
Packit Service 9e77c8
Packit Service 9e77c8
    if (func.hasReturn()):
Packit Service 9e77c8
        text += "    return _ret;\n"
Packit Service 9e77c8
    text += "}\n"
Packit Service 9e77c8
    return text
Packit Service 9e77c8
Packit Service 9e77c8
def getDefaultReturnValue(typename):
Packit Service 9e77c8
    if (typename.endswith("*")):
Packit Service 9e77c8
        return "NULL"
Packit Service 9e77c8
    elif (typename == "EGLDisplay"):
Packit Service 9e77c8
        return "EGL_NO_DISPLAY"
Packit Service 9e77c8
    elif (typename == "EGLContext"):
Packit Service 9e77c8
        return "EGL_NO_CONTEXT"
Packit Service 9e77c8
    elif (typename == "EGLSurface"):
Packit Service 9e77c8
        return "EGL_NO_SURFACE"
Packit Service 9e77c8
    elif (typename == "EGLBoolean"):
Packit Service 9e77c8
        return "EGL_FALSE";
Packit Service 9e77c8
Packit Service 9e77c8
    return "0"
Packit Service 9e77c8
Packit Service 9e77c8
if (__name__ == "__main__"):
Packit Service 9e77c8
    main()
Packit Service 9e77c8