1#!/usr/bin/python3
2# Copyright 2017 The ANGLE Project Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5#
6# gen_proc_table.py:
7#  Code generation for entry point loading tables.
8#  NOTE: don't run this script directly. Run scripts/run_code_generation.py.
9
10import sys
11import registry_xml
12
13out_file_name_gles = "../src/libGLESv2/proc_table_egl_autogen.cpp"
14out_file_name_gl = "../src/libGL/proc_table_wgl_autogen.cpp"
15out_file_name_cl = "../src/libGLESv2/proc_table_cl_autogen.cpp"
16out_file_name_cl_map = "../src/libOpenCL/libOpenCL_autogen.map"
17
18strip_suffixes = ["ANGLE", "EXT", "KHR", "OES", "CHROMIUM", "OVR"]
19
20template_cpp = """// GENERATED FILE - DO NOT EDIT.
21// Generated by {script_name} using data from {data_source_name}.
22//
23// Copyright 2019 The ANGLE Project Authors. All rights reserved.
24// Use of this source code is governed by a BSD-style license that can be
25// found in the LICENSE file.
26//
27// getProcAddress loader table:
28//   Mapping from a string entry point name to function address.
29//
30
31{includes}
32#define P(FUNC) reinterpret_cast<{cast}>(FUNC)
33
34namespace {namespace}
35{{
36const ProcEntry g_procTable[] = {{
37{proc_data}
38}};
39
40const size_t g_numProcs = {num_procs};
41}}  // namespace {namespace}
42"""
43
44template_map_cpp = """// GENERATED FILE - DO NOT EDIT.
45// Generated by {script_name} using data from {data_source_name}.
46//
47// Copyright 2021 The ANGLE Project Authors. All rights reserved.
48// Use of this source code is governed by a BSD-style license that can be
49// found in the LICENSE file.
50//
51// proc_table:
52//   Mapping from a string entry point name to function address.
53//
54
55{includes}
56#define P(FUNC) reinterpret_cast<{cast}>(FUNC)
57
58namespace {namespace}
59{{
60
61const ProcTable &GetProcTable()
62{{
63    static angle::base::NoDestructor<ProcTable> sProcTable(
64        {{{proc_data}}});
65    return *sProcTable;
66}}
67
68}}  // namespace {namespace}
69"""
70
71template_map = """/* GENERATED FILE - DO NOT EDIT.
72 * Generated by {script_name} using data from {data_source_name}.
73 *
74 * Copyright 2021 The ANGLE Project Authors. All rights reserved.
75 * Use of this source code is governed by a BSD-style license that can be
76 * found in the LICENSE file.
77 *
78 * symbol version map: Maps versions to entry point names for a shared library.
79 */
80{symbol_maps}
81"""
82
83includes_gles = """#include "libGLESv2/proc_table_egl.h"
84
85#include "libGLESv2/entry_points_egl_autogen.h"
86#include "libGLESv2/entry_points_egl_ext_autogen.h"
87#include "libGLESv2/entry_points_gles_1_0_autogen.h"
88#include "libGLESv2/entry_points_gles_2_0_autogen.h"
89#include "libGLESv2/entry_points_gles_3_0_autogen.h"
90#include "libGLESv2/entry_points_gles_3_1_autogen.h"
91#include "libGLESv2/entry_points_gles_3_2_autogen.h"
92#include "libGLESv2/entry_points_gles_ext_autogen.h"
93#include "platform/PlatformMethods.h"
94"""
95
96includes_gl = """#include "libGL/proc_table_wgl.h"
97
98#include "libGL/entry_points_wgl.h"
99#include "libGL/entry_points_gl_1_autogen.h"
100#include "libGL/entry_points_gl_2_autogen.h"
101#include "libGL/entry_points_gl_3_autogen.h"
102#include "libGL/entry_points_gl_4_autogen.h"
103#include "platform/PlatformMethods.h"
104"""
105
106includes_cl = """#include "libGLESv2/proc_table_cl.h"
107
108#include "libGLESv2/entry_points_cl_autogen.h"
109
110#include "anglebase/no_destructor.h"
111
112// Using fully qualified entry point identifiers to make sure that missing entry points would not
113// pick up the global declarations of OpenCL
114"""
115
116sys.path.append('../src/libANGLE/renderer')
117import angle_format
118
119
120def _get_annotations(versions):
121    return ["%d_%d" % version for version in versions]
122
123
124def main():
125
126    # auto_script parameters.
127    if len(sys.argv) > 1:
128        inputs = [source for source in registry_xml.xml_inputs]
129        outputs = [out_file_name_gles, out_file_name_gl, out_file_name_cl, out_file_name_cl_map]
130        if sys.argv[1] == 'inputs':
131            print(','.join(inputs))
132        elif sys.argv[1] == 'outputs':
133            print(','.join(outputs))
134        else:
135            print('Invalid script parameters')
136            return 1
137        return 0
138
139    glesxml = registry_xml.RegistryXML('gl.xml', 'gl_angle_ext.xml')
140
141    for annotation in _get_annotations(registry_xml.GLES_VERSIONS):
142        name_prefix = "GL_ES_VERSION_"
143        if annotation[0] == '1':
144            name_prefix = "GL_VERSION_ES_CM_"
145        feature_name = "{}{}".format(name_prefix, annotation)
146        glesxml.AddCommands(feature_name, annotation)
147
148    glesxml.AddExtensionCommands(registry_xml.supported_extensions, ['gles2', 'gles1'])
149
150    # Also don't add GLES extension commands to libGL proc table
151    extension_commands = []
152    for extension_name, ext_cmd_names in sorted(glesxml.ext_data.items()):
153        extension_commands.extend(glesxml.ext_data[extension_name])
154    for name in extension_commands:
155        name_no_suffix = name
156        for suffix in strip_suffixes:
157            if name_no_suffix.endswith(suffix):
158                name_no_suffix = name_no_suffix[0:-len(suffix)]
159
160    gles_data = glesxml.all_cmd_names.get_all_commands()
161
162    eglxml = registry_xml.RegistryXML('egl.xml', 'egl_angle_ext.xml')
163
164    for annotation in _get_annotations(registry_xml.EGL_VERSIONS):
165        name_prefix = "EGL_VERSION_"
166        feature_name = "{}{}".format(name_prefix, annotation)
167        eglxml.AddCommands(feature_name, annotation)
168
169    eglxml.AddExtensionCommands(registry_xml.supported_egl_extensions, ['gles2', 'gles1'])
170
171    gles_data.extend(eglxml.all_cmd_names.get_all_commands())
172
173    gles_data.append("ANGLEGetDisplayPlatform")
174    gles_data.append("ANGLEResetDisplayPlatform")
175
176    all_functions = {}
177
178    for function in gles_data:
179        if function.startswith("gl"):
180            all_functions[function] = "GL_" + function[2:]
181        elif function.startswith("egl"):
182            all_functions[function] = "EGL_" + function[3:]
183        else:
184            all_functions[function] = function
185
186    proc_data = [('    {"%s", P(%s)}' % (func, angle_func))
187                 for func, angle_func in sorted(all_functions.items())]
188
189    with open(out_file_name_gles, 'w') as out_file:
190        output_cpp = template_cpp.format(
191            script_name=sys.argv[0],
192            data_source_name="gl.xml, gl_angle_ext.xml, egl.xml, egl_angle_ext.xml",
193            includes=includes_gles,
194            cast="__eglMustCastToProperFunctionPointerType",
195            namespace="egl",
196            proc_data=",\n".join(proc_data),
197            num_procs=len(proc_data))
198        out_file.write(output_cpp)
199        out_file.close()
200
201    # libGL proc table
202    glxml = registry_xml.RegistryXML('gl.xml')
203
204    for annotation in _get_annotations(registry_xml.DESKTOP_GL_VERSIONS):
205        name_prefix = "GL_VERSION_"
206        feature_name = "{}{}".format(name_prefix, annotation)
207        glxml.AddCommands(feature_name, annotation)
208
209    gl_data = [cmd for cmd in glxml.all_cmd_names.get_all_commands()]
210
211    wglxml = registry_xml.RegistryXML('wgl.xml')
212
213    for annotation in _get_annotations(registry_xml.WGL_VERSIONS):
214        name_prefix = "WGL_VERSION_"
215        feature_name = "{}{}".format(name_prefix, annotation)
216        wglxml.AddCommands(feature_name, annotation)
217
218    gl_commands = wglxml.all_cmd_names.get_all_commands()
219    gl_data.extend([cmd if cmd[:3] == 'wgl' else 'wgl' + cmd for cmd in gl_commands])
220
221    all_functions = {}
222
223    for function in gl_data:
224        if function.startswith("gl"):
225            all_functions[function] = "GL_" + function[2:]
226        else:
227            all_functions[function] = function
228
229    proc_data = [('    {"%s", P(%s)}' % (func, angle_func))
230                 for func, angle_func in sorted(all_functions.items())]
231
232    with open(out_file_name_gl, 'w') as out_file:
233        output_cpp = template_cpp.format(
234            script_name=sys.argv[0],
235            data_source_name="gl.xml, wgl.xml",
236            includes=includes_gl,
237            cast="PROC",
238            namespace="wgl",
239            proc_data=",\n".join(proc_data),
240            num_procs=len(proc_data))
241        out_file.write(output_cpp)
242        out_file.close()
243
244    # libCL proc table
245    clxml = registry_xml.RegistryXML('cl.xml')
246    symbol_maps = []
247    symbol_map_dependency = ""
248
249    for major_version, minor_version in registry_xml.CL_VERSIONS:
250        name_prefix = "CL_VERSION_"
251        annotation = "%d_%d" % (major_version, minor_version)
252        feature_name = "%s%s" % (name_prefix, annotation)
253        clxml.AddCommands(feature_name, annotation)
254        symbol_version = "OPENCL_%d.%d" % (major_version, minor_version)
255        symbol_maps += ["\n%s {\n    global:" % symbol_version]
256        symbol_maps += ['        %s;' % cmd for cmd in clxml.commands[annotation]]
257        if not symbol_map_dependency:
258            symbol_maps += ["    local:\n        *;\n};"]
259        else:
260            symbol_maps += ["} %s;" % symbol_map_dependency]
261        symbol_map_dependency = symbol_version
262
263    clxml.AddExtensionCommands(registry_xml.supported_cl_extensions, ['cl'])
264    cl_commands = clxml.all_cmd_names.get_all_commands()
265    proc_data = ['{"%s", P(::cl::%s)}' % (cmd, cmd) for cmd in cl_commands]
266
267    with open(out_file_name_cl, 'w') as out_file:
268        output_cpp = template_map_cpp.format(
269            script_name=sys.argv[0],
270            data_source_name="cl.xml",
271            includes=includes_cl,
272            cast="void *",
273            namespace="cl",
274            proc_data=",\n         ".join(proc_data))
275        out_file.write(output_cpp)
276        out_file.close()
277
278    with open(out_file_name_cl_map, 'w') as out_file:
279        output_map = template_map.format(
280            script_name=sys.argv[0], data_source_name="cl.xml", symbol_maps="\n".join(symbol_maps))
281        out_file.write(output_map)
282        out_file.close()
283
284    return 0
285
286
287if __name__ == '__main__':
288    sys.exit(main())
289