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