blob: c431ef2fe833498bc32380701770b9642d896db9 [file] [log] [blame]
Jeff Gilbert1b605ee2017-10-30 18:41:46 -07001#!/usr/bin/python2
Jamie Madill2e16d962017-04-19 14:06:36 -04002#
3# Copyright 2017 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_entry_points.py:
8# Generates the OpenGL bindings and entry point layers for ANGLE.
9
Corentin Wallez2e568cf2017-09-18 17:05:22 -040010import sys, os, pprint, json
Jamie Madill2e16d962017-04-19 14:06:36 -040011import xml.etree.ElementTree as etree
12from datetime import date
13
Jamie Madill2e16d962017-04-19 14:06:36 -040014template_entry_point_header = """// GENERATED FILE - DO NOT EDIT.
15// Generated by {script_name} using data from {data_source_name}.
16//
17// Copyright {year} The ANGLE Project Authors. All rights reserved.
18// Use of this source code is governed by a BSD-style license that can be
19// found in the LICENSE file.
20//
Jamie Madillc8c9a242018-01-02 13:39:00 -050021// entry_points_gles_{annotation_lower}_autogen.h:
22// Defines the GLES {comment} entry points.
Jamie Madill2e16d962017-04-19 14:06:36 -040023
Jamie Madillc8c9a242018-01-02 13:39:00 -050024#ifndef LIBGLESV2_ENTRY_POINTS_GLES_{annotation_upper}_AUTOGEN_H_
25#define LIBGLESV2_ENTRY_POINTS_GLES_{annotation_upper}_AUTOGEN_H_
Jamie Madill2e16d962017-04-19 14:06:36 -040026
Jamie Madillc8c9a242018-01-02 13:39:00 -050027{includes}
28
Jamie Madill2e16d962017-04-19 14:06:36 -040029namespace gl
30{{
31{entry_points}
32}} // namespace gl
33
Jamie Madillc8c9a242018-01-02 13:39:00 -050034#endif // LIBGLESV2_ENTRY_POINTS_GLES_{annotation_upper}_AUTOGEN_H_
Jamie Madill2e16d962017-04-19 14:06:36 -040035"""
36
Jamie Madillee769dd2017-05-04 11:38:30 -040037template_entry_point_source = """// GENERATED FILE - DO NOT EDIT.
38// Generated by {script_name} using data from {data_source_name}.
39//
40// Copyright {year} The ANGLE Project Authors. All rights reserved.
41// Use of this source code is governed by a BSD-style license that can be
42// found in the LICENSE file.
43//
Jamie Madillc8c9a242018-01-02 13:39:00 -050044// entry_points_gles_{annotation_lower}_autogen.cpp:
45// Defines the GLES {comment} entry points.
Jamie Madillee769dd2017-05-04 11:38:30 -040046
Jamie Madillc8c9a242018-01-02 13:39:00 -050047{includes}
Jamie Madillee769dd2017-05-04 11:38:30 -040048
49namespace gl
50{{
51{entry_points}}} // namespace gl
52"""
53
54template_entry_points_enum_header = """// GENERATED FILE - DO NOT EDIT.
55// Generated by {script_name} using data from {data_source_name}.
56//
57// Copyright {year} The ANGLE Project Authors. All rights reserved.
58// Use of this source code is governed by a BSD-style license that can be
59// found in the LICENSE file.
60//
61// entry_points_enum_autogen.h:
62// Defines the GLES entry points enumeration.
63
64#ifndef LIBGLESV2_ENTRYPOINTSENUM_AUTOGEN_H_
65#define LIBGLESV2_ENTRYPOINTSENUM_AUTOGEN_H_
66
67namespace gl
68{{
69enum class EntryPoint
70{{
71{entry_points_list}
72}};
73}} // namespace gl
74#endif // LIBGLESV2_ENTRY_POINTS_ENUM_AUTOGEN_H_
75"""
76
Jamie Madill2e16d962017-04-19 14:06:36 -040077template_entry_point_decl = """ANGLE_EXPORT {return_type}GL_APIENTRY {name}({params});"""
78
Jamie Madillee769dd2017-05-04 11:38:30 -040079template_entry_point_def = """{return_type}GL_APIENTRY {name}({params})
80{{
81 EVENT("({format_params})"{comma_if_needed}{pass_params});
82
Geoff Langcae72d62017-06-01 11:53:45 -040083 Context *context = {context_getter}();
Jamie Madillee769dd2017-05-04 11:38:30 -040084 if (context)
Corentin Wallez2e568cf2017-09-18 17:05:22 -040085 {{{packed_gl_enum_conversions}
86 context->gatherParams<EntryPoint::{name}>({internal_params});
Jamie Madillee769dd2017-05-04 11:38:30 -040087
Jamie Madill53d38412017-04-20 11:33:00 -040088 if (context->skipValidation() || Validate{name}({validate_params}))
Jamie Madillee769dd2017-05-04 11:38:30 -040089 {{
Jamie Madillc8c9a242018-01-02 13:39:00 -050090 {return_if_needed}context->{name_lower_no_suffix}({internal_params});
Jamie Madillee769dd2017-05-04 11:38:30 -040091 }}
Jamie Madillee769dd2017-05-04 11:38:30 -040092 }}
93{default_return_if_needed}}}
94"""
95
Jamie Madill16daadb2017-08-26 23:34:31 -040096def script_relative(path):
97 return os.path.join(os.path.dirname(sys.argv[0]), path)
98
99tree = etree.parse(script_relative('gl.xml'))
100root = tree.getroot()
Jamie Madill2e16d962017-04-19 14:06:36 -0400101commands = root.find(".//commands[@namespace='GL']")
Jamie Madill2e16d962017-04-19 14:06:36 -0400102
Corentin Wallez2e568cf2017-09-18 17:05:22 -0400103with open(script_relative('entry_point_packed_gl_enums.json')) as f:
104 cmd_packed_gl_enums = json.loads(f.read())
105
Jamie Madill2e16d962017-04-19 14:06:36 -0400106def format_entry_point_decl(cmd_name, proto, params):
107 return template_entry_point_decl.format(
108 name = cmd_name[2:],
109 return_type = proto[:-len(cmd_name)],
110 params = ", ".join(params))
111
Jamie Madillee769dd2017-05-04 11:38:30 -0400112def type_name_sep_index(param):
113 space = param.rfind(" ")
114 pointer = param.rfind("*")
115 return max(space, pointer)
116
117def just_the_type(param):
118 return param[:type_name_sep_index(param)]
119
120def just_the_name(param):
121 return param[type_name_sep_index(param)+1:]
122
Corentin Wallez2e568cf2017-09-18 17:05:22 -0400123def just_the_name_packed(param, reserved_set):
124 name = just_the_name(param)
125 if name in reserved_set:
126 return name + 'Packed'
127 else:
128 return name
129
Jamie Madillee769dd2017-05-04 11:38:30 -0400130format_dict = {
131 "GLbitfield": "0x%X",
132 "GLboolean": "%u",
133 "GLenum": "0x%X",
134 "GLfloat": "%f",
135 "GLint": "%d",
136 "GLintptr": "%d",
137 "GLsizei": "%d",
138 "GLsizeiptr": "%d",
Jamie Madill16daadb2017-08-26 23:34:31 -0400139 "GLsync": "0x%0.8p",
Jamie Madillff161f82017-08-26 23:49:10 -0400140 "GLuint": "%u",
Jamie Madill16daadb2017-08-26 23:34:31 -0400141 "GLuint64": "%llu"
Jamie Madillee769dd2017-05-04 11:38:30 -0400142}
143
144def param_format_string(param):
145 if "*" in param:
146 return param + " = 0x%0.8p"
147 else:
Jamie Madill16daadb2017-08-26 23:34:31 -0400148 type_only = just_the_type(param)
149 if type_only not in format_dict:
150 raise Exception(type_only + " is not a known type in 'format_dict'")
151
152 return param + " = " + format_dict[type_only]
Jamie Madillee769dd2017-05-04 11:38:30 -0400153
Jamie Madill2e29b132017-08-28 17:22:11 -0400154def default_return_value(cmd_name, return_type):
Jamie Madillee769dd2017-05-04 11:38:30 -0400155 if return_type == "void":
156 return ""
Jamie Madill2e29b132017-08-28 17:22:11 -0400157 return "GetDefaultReturnValue<EntryPoint::" + cmd_name[2:] + ", " + return_type + ">()"
Jamie Madillee769dd2017-05-04 11:38:30 -0400158
Geoff Langcae72d62017-06-01 11:53:45 -0400159def get_context_getter_function(cmd_name):
160 if cmd_name == "glGetError":
161 return "GetGlobalContext"
162 else:
163 return "GetValidGlobalContext"
164
Jamie Madillee769dd2017-05-04 11:38:30 -0400165def format_entry_point_def(cmd_name, proto, params):
Corentin Wallez2e568cf2017-09-18 17:05:22 -0400166 packed_gl_enums = cmd_packed_gl_enums.get(cmd_name, {})
167 internal_params = [just_the_name_packed(param, packed_gl_enums) for param in params]
168 packed_gl_enum_conversions = []
169 for param in params:
170 name = just_the_name(param)
171 if name in packed_gl_enums:
172 internal_name = name + "Packed"
173 internal_type = packed_gl_enums[name]
174 packed_gl_enum_conversions += ["\n " + internal_type + " " + internal_name +" = FromGLenum<" +
175 internal_type + ">(" + name + ");"]
176
Jamie Madillee769dd2017-05-04 11:38:30 -0400177 pass_params = [just_the_name(param) for param in params]
178 format_params = [param_format_string(param) for param in params]
179 return_type = proto[:-len(cmd_name)]
Jamie Madill2e29b132017-08-28 17:22:11 -0400180 default_return = default_return_value(cmd_name, return_type.strip())
Jamie Madillc8c9a242018-01-02 13:39:00 -0500181 name_lower_no_suffix = cmd_name[2:3].lower() + cmd_name[3:]
182
Jamie Madillee769dd2017-05-04 11:38:30 -0400183 return template_entry_point_def.format(
184 name = cmd_name[2:],
Jamie Madillc8c9a242018-01-02 13:39:00 -0500185 name_lower_no_suffix = name_lower_no_suffix,
Jamie Madillee769dd2017-05-04 11:38:30 -0400186 return_type = return_type,
187 params = ", ".join(params),
Corentin Wallez2e568cf2017-09-18 17:05:22 -0400188 internal_params = ", ".join(internal_params),
189 packed_gl_enum_conversions = "".join(packed_gl_enum_conversions),
Jamie Madillee769dd2017-05-04 11:38:30 -0400190 pass_params = ", ".join(pass_params),
191 comma_if_needed = ", " if len(params) > 0 else "",
Corentin Wallez2e568cf2017-09-18 17:05:22 -0400192 validate_params = ", ".join(["context"] + internal_params),
Jamie Madillee769dd2017-05-04 11:38:30 -0400193 format_params = ", ".join(format_params),
Jamie Madillee769dd2017-05-04 11:38:30 -0400194 return_if_needed = "" if default_return == "" else "return ",
Geoff Langcae72d62017-06-01 11:53:45 -0400195 default_return_if_needed = "" if default_return == "" else "\n return " + default_return + ";\n",
196 context_getter = get_context_getter_function(cmd_name))
Jamie Madillee769dd2017-05-04 11:38:30 -0400197
Jiajia Qincb59a902017-11-22 13:03:42 +0800198def path_to(folder, file):
199 return os.path.join(script_relative(".."), "src", folder, file)
Jamie Madill2e16d962017-04-19 14:06:36 -0400200
Jamie Madillc8c9a242018-01-02 13:39:00 -0500201def get_entry_points(all_commands, gles_commands):
Jamie Madillffa2cd02017-12-28 14:57:53 -0500202
Jamie Madillc8c9a242018-01-02 13:39:00 -0500203 decls = []
204 defs = []
Jamie Madillffa2cd02017-12-28 14:57:53 -0500205
206 for command in all_commands:
207 proto = command.find('proto')
208 cmd_name = proto.find('name').text
209
210 if cmd_name not in gles_commands:
211 continue
212
213 param_text = ["".join(param.itertext()) for param in command.findall('param')]
214 proto_text = "".join(proto.itertext())
Jamie Madill2e16d962017-04-19 14:06:36 -0400215
Jamie Madillc8c9a242018-01-02 13:39:00 -0500216 decls.append(format_entry_point_decl(cmd_name, proto_text, param_text))
217 defs.append(format_entry_point_def(cmd_name, proto_text, param_text))
Jamie Madillee769dd2017-05-04 11:38:30 -0400218
Jamie Madillc8c9a242018-01-02 13:39:00 -0500219 return decls, defs
Jamie Madill16daadb2017-08-26 23:34:31 -0400220
Jamie Madillc8c9a242018-01-02 13:39:00 -0500221def write_file(annotation, comment, template, entry_points, suffix, includes):
Jiajia Qincb59a902017-11-22 13:03:42 +0800222
Jamie Madillc8c9a242018-01-02 13:39:00 -0500223 content = template.format(
224 script_name = os.path.basename(sys.argv[0]),
225 data_source_name = "gl.xml",
226 year = date.today().year,
227 annotation_lower = annotation.lower(),
228 annotation_upper = annotation.upper(),
229 comment = comment,
230 includes = includes,
231 entry_points = entry_points)
Jiajia Qincb59a902017-11-22 13:03:42 +0800232
Jamie Madillc8c9a242018-01-02 13:39:00 -0500233 path = path_to("libGLESv2", "entry_points_gles_{}_autogen.{}".format(
234 annotation.lower(), suffix))
235
236 with open(path, "w") as out:
237 out.write(content)
238 out.close()
239
240all_commands = root.findall('commands/command')
241all_cmd_names = []
242
243template_header_includes = """#include <GLES{}/gl{}{}.h>
244#include <export.h>"""
245
246template_sources_includes = """#include "libANGLE/Context.h"
247#include "libANGLE/validationES{}{}.h"
248#include "libGLESv2/global_state.h"
249"""
250
251# First run through the main GLES entry points.
252for major_version, minor_version in [[2, 0], [3, 0], [3, 1]]:
253 annotation = "{}_{}".format(major_version, minor_version)
254 comment = annotation.replace("_", ".")
255 gles_xpath = ".//feature[@name='GL_ES_VERSION_{}']//command".format(annotation)
256 gles_commands = [cmd.attrib['name'] for cmd in root.findall(gles_xpath)]
257 all_cmd_names += gles_commands
258
259 decls, defs = get_entry_points(all_commands, gles_commands)
260
261 minor_if_not_zero = minor_version if minor_version != 0 else ""
262
263 header_includes = template_header_includes.format(
264 major_version, major_version, minor_if_not_zero)
265
266 # We include the platform.h header since it undefines the conflicting MemoryBarrier macro.
267 if major_version == 3 and minor_version == 1:
268 header_includes += "\n#include \"common/platform.h\"\n"
269
270 source_includes = template_sources_includes.format(major_version, minor_if_not_zero)
271
272 write_file(annotation, comment, template_entry_point_header,
273 "\n".join(decls), "h", header_includes)
274 write_file(annotation, comment, template_entry_point_source,
275 "\n".join(defs), "cpp", source_includes)
Jamie Madill57ae8c12017-08-30 12:14:29 -0400276
Jamie Madill16daadb2017-08-26 23:34:31 -0400277# TODO(jmadill): Remove manually added entry points once we auto-gen them.
Jamie Madillc8c9a242018-01-02 13:39:00 -0500278all_cmd_names += ["glDrawElementsInstancedANGLE"]
279
280sorted_cmd_names = ["Invalid"] + [cmd[2:] for cmd in sorted(all_cmd_names)]
281
Jamie Madillee769dd2017-05-04 11:38:30 -0400282entry_points_enum = template_entry_points_enum_header.format(
283 script_name = os.path.basename(sys.argv[0]),
284 data_source_name = "gl.xml",
285 year = date.today().year,
Jamie Madillc8c9a242018-01-02 13:39:00 -0500286 entry_points_list = ",\n".join([" " + cmd for cmd in sorted_cmd_names]))
Jamie Madillee769dd2017-05-04 11:38:30 -0400287
Jamie Madillee769dd2017-05-04 11:38:30 -0400288entry_points_enum_header_path = path_to("libANGLE", "entry_points_enum_autogen.h")
Jamie Madillee769dd2017-05-04 11:38:30 -0400289with open(entry_points_enum_header_path, "w") as out:
290 out.write(entry_points_enum)
Geoff Langcae72d62017-06-01 11:53:45 -0400291 out.close()