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