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