• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/python2
2#
3# Copyright 2018 The ANGLE Project Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6#
7# generate_loader.py:
8#   Generates dynamic loaders for various binding interfaces.
9#   NOTE: don't run this script directly. Run scripts/run_code_generation.py.
10
11import sys, os, pprint, json
12from datetime import date
13import registry_xml
14
15
16def write_header(data_source_name,
17                 all_cmds,
18                 api,
19                 preamble,
20                 path,
21                 lib,
22                 ns="",
23                 prefix=None,
24                 export=""):
25    file_name = "%s_loader_autogen.h" % api
26    header_path = registry_xml.path_to(path, file_name)
27
28    def pre(cmd):
29        if prefix == None:
30            return cmd
31        return prefix + cmd[len(api):]
32
33    with open(header_path, "w") as out:
34        var_protos = [
35            "%sextern PFN%sPROC %s%s;" % (export, cmd.upper(), ns, pre(cmd)) for cmd in all_cmds
36        ]
37        loader_header = template_loader_h.format(
38            script_name=os.path.basename(sys.argv[0]),
39            data_source_name=data_source_name,
40            year=date.today().year,
41            function_pointers="\n".join(var_protos),
42            api_upper=api.upper(),
43            api_lower=api,
44            preamble=preamble,
45            export=export,
46            lib=lib.upper(),
47            load_fn_name="Load%s%s" % (prefix if prefix else "", api.upper()))
48
49        out.write(loader_header)
50        out.close()
51
52
53def write_source(data_source_name, all_cmds, api, path, ns="", prefix=None, export=""):
54    file_name = "%s_loader_autogen.cpp" % api
55    source_path = registry_xml.path_to(path, file_name)
56
57    def pre(cmd):
58        if prefix == None:
59            return cmd
60        return prefix + cmd[len(api):]
61
62    with open(source_path, "w") as out:
63        var_defs = ["%sPFN%sPROC %s%s;" % (export, cmd.upper(), ns, pre(cmd)) for cmd in all_cmds]
64
65        setter = "    %s%s = reinterpret_cast<PFN%sPROC>(loadProc(\"%s\"));"
66        setters = [setter % (ns, pre(cmd), cmd.upper(), pre(cmd)) for cmd in all_cmds]
67
68        loader_source = template_loader_cpp.format(
69            script_name=os.path.basename(sys.argv[0]),
70            data_source_name=data_source_name,
71            year=date.today().year,
72            function_pointers="\n".join(var_defs),
73            set_pointers="\n".join(setters),
74            api_upper=api.upper(),
75            api_lower=api,
76            load_fn_name="Load%s%s" % (prefix if prefix else "", api.upper()))
77
78        out.write(loader_source)
79        out.close()
80
81
82def gen_libegl_loader():
83
84    data_source_name = "egl.xml and egl_angle_ext.xml"
85    xml = registry_xml.RegistryXML("egl.xml", "egl_angle_ext.xml")
86
87    for major_version, minor_version in [[1, 0], [1, 1], [1, 2], [1, 3], [1, 4], [1, 5]]:
88        annotation = "{}_{}".format(major_version, minor_version)
89        name_prefix = "EGL_VERSION_"
90
91        feature_name = "{}{}".format(name_prefix, annotation)
92
93        xml.AddCommands(feature_name, annotation)
94
95    xml.AddExtensionCommands(registry_xml.supported_egl_extensions, ['egl'])
96
97    all_cmds = xml.all_cmd_names.get_all_commands()
98
99    path = os.path.join("..", "src", "libEGL")
100    write_header(data_source_name, all_cmds, "egl", libegl_preamble, path, "LIBEGL", "", "EGL_",
101                 "ANGLE_NO_EXPORT ")
102    write_source(data_source_name, all_cmds, "egl", path, "", "EGL_")
103
104
105def gen_gl_loader():
106
107    data_source_name = "gl.xml and gl_angle_ext.xml"
108    xml = registry_xml.RegistryXML("gl.xml", "gl_angle_ext.xml")
109
110    # First run through the main GLES entry points.  Since ES2+ is the primary use
111    # case, we go through those first and then add ES1-only APIs at the end.
112    for major_version, minor_version in [[2, 0], [3, 0], [3, 1], [1, 0]]:
113        annotation = "{}_{}".format(major_version, minor_version)
114        name_prefix = "GL_ES_VERSION_"
115
116        is_gles1 = major_version == 1
117        if is_gles1:
118            name_prefix = "GL_VERSION_ES_CM_"
119
120        feature_name = "{}{}".format(name_prefix, annotation)
121
122        xml.AddCommands(feature_name, annotation)
123
124    xml.AddExtensionCommands(registry_xml.supported_extensions, ['gles2', 'gles1'])
125
126    all_cmds = xml.all_cmd_names.get_all_commands()
127
128    if registry_xml.support_EGL_ANGLE_explicit_context:
129        all_cmds += [cmd + "ContextANGLE" for cmd in xml.all_cmd_names.get_all_commands()]
130
131    path = os.path.join("..", "util")
132    ex = "ANGLE_UTIL_EXPORT "
133    write_header(data_source_name, all_cmds, "gles", util_gles_preamble, path, "UTIL", export=ex)
134    write_source(data_source_name, all_cmds, "gles", path, export=ex)
135
136
137def gen_egl_loader():
138
139    data_source_name = "egl.xml and egl_angle_ext.xml"
140    xml = registry_xml.RegistryXML("egl.xml", "egl_angle_ext.xml")
141
142    for major_version, minor_version in [[1, 0], [1, 1], [1, 2], [1, 3], [1, 4], [1, 5]]:
143        annotation = "{}_{}".format(major_version, minor_version)
144        name_prefix = "EGL_VERSION_"
145
146        feature_name = "{}{}".format(name_prefix, annotation)
147
148        xml.AddCommands(feature_name, annotation)
149
150    xml.AddExtensionCommands(registry_xml.supported_egl_extensions, ['egl'])
151
152    all_cmds = xml.all_cmd_names.get_all_commands()
153
154    path = os.path.join("..", "util")
155    ex = "ANGLE_UTIL_EXPORT "
156    write_header(data_source_name, all_cmds, "egl", util_egl_preamble, path, "UTIL", export=ex)
157    write_source(data_source_name, all_cmds, "egl", path, export=ex)
158
159
160def gen_wgl_loader():
161
162    supported_wgl_extensions = [
163        "WGL_ARB_create_context",
164        "WGL_ARB_extensions_string",
165        "WGL_EXT_swap_control",
166    ]
167
168    source = "wgl.xml"
169    xml = registry_xml.RegistryXML(source)
170
171    for major_version, minor_version in [[1, 0]]:
172        annotation = "{}_{}".format(major_version, minor_version)
173        name_prefix = "WGL_VERSION_"
174
175        feature_name = "{}{}".format(name_prefix, annotation)
176
177        xml.AddCommands(feature_name, annotation)
178
179    xml.AddExtensionCommands(supported_wgl_extensions, ['wgl'])
180
181    all_cmds = xml.all_cmd_names.get_all_commands()
182
183    path = os.path.join("..", "util", "windows")
184    write_header(source, all_cmds, "wgl", util_wgl_preamble, path, "UTIL_WINDOWS", "_")
185    write_source(source, all_cmds, "wgl", path, "_")
186
187
188def main():
189
190    # Handle inputs/outputs for run_code_generation.py's auto_script
191    if len(sys.argv) > 1:
192        inputs = [
193            'gl.xml',
194            'gl_angle_ext.xml',
195            'egl.xml',
196            'egl_angle_ext.xml',
197            'registry_xml.py',
198            'wgl.xml',
199        ]
200        outputs = [
201            '../src/libEGL/egl_loader_autogen.cpp',
202            '../src/libEGL/egl_loader_autogen.h',
203            '../util/egl_loader_autogen.cpp',
204            '../util/egl_loader_autogen.h',
205            '../util/gles_loader_autogen.cpp',
206            '../util/gles_loader_autogen.h',
207            '../util/windows/wgl_loader_autogen.cpp',
208            '../util/windows/wgl_loader_autogen.h',
209        ]
210
211        if sys.argv[1] == 'inputs':
212            print ','.join(inputs)
213        elif sys.argv[1] == 'outputs':
214            print ','.join(outputs)
215        else:
216            print('Invalid script parameters')
217            return 1
218        return 0
219
220    gen_libegl_loader()
221    gen_gl_loader()
222    gen_egl_loader()
223    gen_wgl_loader()
224    return 0
225
226
227libegl_preamble = """#include <EGL/egl.h>
228#include <EGL/eglext.h>
229#include <export.h>
230"""
231
232util_gles_preamble = """#if defined(GL_GLES_PROTOTYPES) && GL_GLES_PROTOTYPES
233#error "Don't define GL prototypes if you want to use a loader!"
234#endif  // defined(GL_GLES_PROTOTYPES)
235
236#include "angle_gl.h"
237#include "util/util_export.h"
238"""
239
240util_egl_preamble = """#include "util/util_export.h"
241
242#include <EGL/egl.h>
243#include <EGL/eglext.h>
244"""
245
246util_wgl_preamble = """
247#include <WGL/wgl.h>
248#include <GLES2/gl2.h>
249
250// We add an underscore before each function name to ensure common names like "ChoosePixelFormat"
251// and "SwapBuffers" don't conflict with our function pointers. We can't use a namespace because
252// some functions conflict with preprocessor definitions.
253"""
254
255template_loader_h = """// GENERATED FILE - DO NOT EDIT.
256// Generated by {script_name} using data from {data_source_name}.
257//
258// Copyright {year} The ANGLE Project Authors. All rights reserved.
259// Use of this source code is governed by a BSD-style license that can be
260// found in the LICENSE file.
261//
262// {api_lower}_loader_autogen.h:
263//   Simple {api_upper} function loader.
264
265#ifndef {lib}_{api_upper}_LOADER_AUTOGEN_H_
266#define {lib}_{api_upper}_LOADER_AUTOGEN_H_
267
268{preamble}
269{function_pointers}
270
271namespace angle
272{{
273using GenericProc = void (*)();
274using LoadProc = GenericProc (KHRONOS_APIENTRY *)(const char *);
275{export}void {load_fn_name}(LoadProc loadProc);
276}}  // namespace angle
277
278#endif  // {lib}_{api_upper}_LOADER_AUTOGEN_H_
279"""
280
281template_loader_cpp = """// GENERATED FILE - DO NOT EDIT.
282// Generated by {script_name} using data from {data_source_name}.
283//
284// Copyright {year} The ANGLE Project Authors. All rights reserved.
285// Use of this source code is governed by a BSD-style license that can be
286// found in the LICENSE file.
287//
288// {api_lower}_loader_autogen.cpp:
289//   Simple {api_upper} function loader.
290
291#include "{api_lower}_loader_autogen.h"
292
293{function_pointers}
294
295namespace angle
296{{
297void {load_fn_name}(LoadProc loadProc)
298{{
299{set_pointers}
300}}
301}}  // namespace angle
302"""
303
304if __name__ == '__main__':
305    sys.exit(main())
306