• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 os
11import sys
12import registry_xml
13
14out_file_name_gles = "../src/libGLESv2/egl_stubs_getprocaddress_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{{
36
37namespace
38{{
39struct ProcEntry
40{{
41    const char *name;
42    __eglMustCastToProperFunctionPointerType func;
43}};
44
45bool CompareProc(const ProcEntry &a, const char *b)
46{{
47    return strcmp(a.name, b) < 0;
48}}
49
50// clang-format off
51const ProcEntry g_procTable[] = {{
52{proc_data}
53}};
54// clang-format on
55}}  // anonymous namespace
56
57__eglMustCastToProperFunctionPointerType GetProcAddress(Thread *thread, const char *procname)
58{{
59    if (procname == nullptr)
60    {{
61        return nullptr;
62    }}
63
64    const ProcEntry *entry =
65        std::lower_bound(std::begin(g_procTable), std::end(g_procTable), procname, CompareProc);
66
67    thread->setSuccess();
68
69    if (entry == std::end(g_procTable) || strcmp(entry->name, procname) != 0)
70    {{
71        return nullptr;
72    }}
73
74    return entry->func;
75}}
76
77}}  // namespace {namespace}
78
79"""
80
81# FOR OPENCL
82template_map_cpp = """// GENERATED FILE - DO NOT EDIT.
83// Generated by {script_name} using data from {data_source_name}.
84//
85// Copyright 2021 The ANGLE Project Authors. All rights reserved.
86// Use of this source code is governed by a BSD-style license that can be
87// found in the LICENSE file.
88//
89// proc_table:
90//   Mapping from a string entry point name to function address.
91//
92
93{includes}
94#define P(FUNC) reinterpret_cast<{cast}>(FUNC)
95
96namespace {namespace}
97{{
98
99const ProcTable &GetProcTable()
100{{
101    static angle::base::NoDestructor<ProcTable> sProcTable(
102        {{{proc_data}}});
103    return *sProcTable;
104}}
105
106}}  // namespace {namespace}
107"""
108
109# FOR OPENCL
110template_map = """/* GENERATED FILE - DO NOT EDIT.
111 * Generated by {script_name} using data from {data_source_name}.
112 *
113 * Copyright 2021 The ANGLE Project Authors. All rights reserved.
114 * Use of this source code is governed by a BSD-style license that can be
115 * found in the LICENSE file.
116 *
117 * symbol version map: Maps versions to entry point names for a shared library.
118 */
119{symbol_maps}
120"""
121
122includes_gles = """#include "libANGLE/Thread.h"
123#include "libGLESv2/entry_points_egl_autogen.h"
124#include "libGLESv2/entry_points_egl_ext_autogen.h"
125#include "libGLESv2/entry_points_gles_1_0_autogen.h"
126#include "libGLESv2/entry_points_gles_2_0_autogen.h"
127#include "libGLESv2/entry_points_gles_3_0_autogen.h"
128#include "libGLESv2/entry_points_gles_3_1_autogen.h"
129#include "libGLESv2/entry_points_gles_3_2_autogen.h"
130#include "libGLESv2/entry_points_gles_ext_autogen.h"
131#include "platform/PlatformMethods.h"
132
133#include <iterator>
134"""
135
136includes_cl = """#include "libGLESv2/proc_table_cl.h"
137
138#include "libGLESv2/entry_points_cl_autogen.h"
139
140#include "anglebase/no_destructor.h"
141
142// Using fully qualified entry point identifiers to make sure that missing entry points would not
143// pick up the global declarations of OpenCL
144"""
145
146sys.path.append('../src/libANGLE/renderer')
147import angle_format
148
149
150def _get_annotations(versions):
151    return ["%d_%d" % version for version in versions]
152
153
154def main():
155
156    # auto_script parameters.
157    if len(sys.argv) > 1:
158        inputs = [source for source in registry_xml.xml_inputs]
159        outputs = [out_file_name_gles, out_file_name_cl, out_file_name_cl_map]
160        if sys.argv[1] == 'inputs':
161            print(','.join(inputs))
162        elif sys.argv[1] == 'outputs':
163            print(','.join(outputs))
164        else:
165            print('Invalid script parameters')
166            return 1
167        return 0
168
169    glesxml = registry_xml.RegistryXML('gl.xml', 'gl_angle_ext.xml')
170
171    for annotation in _get_annotations(registry_xml.GLES_VERSIONS):
172        name_prefix = "GL_ES_VERSION_"
173        if annotation[0] == '1':
174            name_prefix = "GL_VERSION_ES_CM_"
175        feature_name = "{}{}".format(name_prefix, annotation)
176        glesxml.AddCommands(feature_name, annotation)
177
178    glesxml.AddExtensionCommands(registry_xml.supported_extensions, ['gles2', 'gles1'])
179
180    # Also don't add GLES extension commands to libGL proc table
181    extension_commands = []
182    for extension_name, ext_cmd_names in sorted(glesxml.ext_data.items()):
183        extension_commands.extend(glesxml.ext_data[extension_name])
184    for name in extension_commands:
185        name_no_suffix = name
186        for suffix in strip_suffixes:
187            if name_no_suffix.endswith(suffix):
188                name_no_suffix = name_no_suffix[0:-len(suffix)]
189
190    gles_data = glesxml.all_cmd_names.get_all_commands()
191    eglxml = registry_xml.RegistryXML('egl.xml', 'egl_angle_ext.xml')
192
193    for annotation in _get_annotations(registry_xml.EGL_VERSIONS):
194        name_prefix = "EGL_VERSION_"
195        feature_name = "{}{}".format(name_prefix, annotation)
196        eglxml.AddCommands(feature_name, annotation)
197
198    eglxml.AddExtensionCommands(registry_xml.supported_egl_extensions, ['gles2', 'gles1'])
199
200    gles_data.extend(eglxml.all_cmd_names.get_all_commands())
201
202    gles_data.append("ANGLEGetDisplayPlatform")
203    gles_data.append("ANGLEResetDisplayPlatform")
204    gles_data = set(gles_data)
205
206    all_functions = {}
207    for function in gles_data:
208        if function.startswith("gl"):
209            all_functions[function] = "GL_" + function[2:]
210        elif function.startswith("egl"):
211            all_functions[function] = "EGL_" + function[3:]
212        else:
213            all_functions[function] = function
214
215    proc_data = []
216    for func, angle_func in sorted(all_functions.items()):
217        proc_data.append('    {"%s", P(%s)},' % (func, angle_func))
218
219    with open(out_file_name_gles, 'w') as out_file:
220        output_cpp = template_cpp.format(
221            script_name=os.path.basename(sys.argv[0]),
222            data_source_name="gl.xml, gl_angle_ext.xml, egl.xml, egl_angle_ext.xml",
223            includes=includes_gles,
224            cast="__eglMustCastToProperFunctionPointerType",
225            namespace="egl",
226            proc_data="\n".join(proc_data),
227            num_procs="std::size(g_procTable)")
228        out_file.write(output_cpp)
229        out_file.close()
230
231    # libCL proc table
232    clxml = registry_xml.RegistryXML('cl.xml')
233    symbol_maps = []
234    symbol_map_dependency = ""
235
236    for major_version, minor_version in registry_xml.CL_VERSIONS:
237        name_prefix = "CL_VERSION_"
238        annotation = "%d_%d" % (major_version, minor_version)
239        feature_name = "%s%s" % (name_prefix, annotation)
240        clxml.AddCommands(feature_name, annotation)
241        symbol_version = "OPENCL_%d.%d" % (major_version, minor_version)
242        symbol_maps += ["\n%s {\n    global:" % symbol_version]
243        symbol_maps += ['        %s;' % cmd for cmd in clxml.commands[annotation]]
244        if not symbol_map_dependency:
245            symbol_maps += ["    local:\n        *;\n};"]
246        else:
247            symbol_maps += ["} %s;" % symbol_map_dependency]
248        symbol_map_dependency = symbol_version
249
250    clxml.AddExtensionCommands(registry_xml.supported_cl_extensions, ['cl'])
251    cl_commands = clxml.all_cmd_names.get_all_commands()
252    proc_data = ['{"%s", P(::cl::%s)}' % (cmd, cmd) for cmd in cl_commands]
253
254    with open(out_file_name_cl, 'w') as out_file:
255        output_cpp = template_map_cpp.format(
256            script_name=os.path.basename(sys.argv[0]),
257            data_source_name="cl.xml",
258            includes=includes_cl,
259            cast="void *",
260            namespace="cl",
261            proc_data=",\n         ".join(proc_data))
262        out_file.write(output_cpp)
263        out_file.close()
264
265    with open(out_file_name_cl_map, 'w') as out_file:
266        output_map = template_map.format(
267            script_name=os.path.basename(sys.argv[0]),
268            data_source_name="cl.xml",
269            symbol_maps="\n".join(symbol_maps))
270        out_file.write(output_map)
271        out_file.close()
272
273    return 0
274
275
276if __name__ == '__main__':
277    sys.exit(main())
278