Implement EGL_ANGLE_explicit_context
Implementation of EGL_ANGLE_explicit_context. Includes new libGLESv2 entry
points and exports, libANGLE entry points, extension declarations for
eglGetProcAddress, and unit tests. Autogeneration scripts have been
modified to produce entry points, exports, eglGetProcAddress function
table, extension function pointers, and function declarations.
Bug:angleproject:1395
Change-Id: I1b79c6069bbed05beb4700a32139a64ddc465c4c
Reviewed-on: https://chromium-review.googlesource.com/1039865
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Geoff Lang <geofflang@chromium.org>
diff --git a/scripts/generate_entry_points.py b/scripts/generate_entry_points.py
index 6dc9a13..3a4948c 100755
--- a/scripts/generate_entry_points.py
+++ b/scripts/generate_entry_points.py
@@ -69,6 +69,10 @@
"GL_OES_vertex_array_object",
])
+# The EGL_ANGLE_explicit_context extension is generated differently from other extensions.
+# Toggle generation here.
+support_EGL_ANGLE_explicit_context = True
+
# This is a list of exceptions for entry points which don't want to have
# the EVENT macro. This is required for some debug marker entry points.
no_event_marker_exceptions_list = sorted([
@@ -170,14 +174,15 @@
"""
template_entry_point_decl = """ANGLE_EXPORT {return_type}GL_APIENTRY {name}({params});"""
+template_entry_point_decl = """ANGLE_EXPORT {return_type}GL_APIENTRY {name}{explicit_context_suffix}({explicit_context_param}{explicit_context_comma}{params});"""
-template_entry_point_def = """{return_type}GL_APIENTRY {name}({params})
+template_entry_point_def = """{return_type}GL_APIENTRY {name}{explicit_context_suffix}({explicit_context_param}{explicit_context_comma}{params})
{{
{event_comment}EVENT("({format_params})"{comma_if_needed}{pass_params});
- Context *context = {context_getter}();
+ Context *context = {context_getter};
if (context)
- {{{packed_gl_enum_conversions}
+ {{{assert_explicit_context}{packed_gl_enum_conversions}
context->gatherParams<EntryPoint::{name}>({internal_params});
if (context->skipValidation() || Validate{name}({validate_params}))
@@ -208,13 +213,32 @@
context_gles_decl = """ {return_type} {name_lower_no_suffix}({internal_params}); \\"""
-libgles_entry_point_def = """{return_type}GL_APIENTRY gl{name}({params})
+libgles_entry_point_def = """{return_type}GL_APIENTRY gl{name}{explicit_context_suffix}({explicit_context_param}{explicit_context_comma}{params})
{{
- return gl::{name}({internal_params});
+ return gl::{name}{explicit_context_suffix}({explicit_context_internal_param}{explicit_context_comma}{internal_params});
}}
"""
-libgles_entry_point_export = """ {name}{spaces}@{ordinal}"""
+libgles_entry_point_export = """ {name}{explicit_context_suffix}{spaces}@{ordinal}"""
+
+template_glext_explicit_context_inc = """// GENERATED FILE - DO NOT EDIT.
+// Generated by {script_name} using data from {data_source_name}.
+//
+// Copyright {year} The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// gl{version}ext_explicit_context_autogen.inc:
+// Function declarations for the EGL_ANGLE_explicit_context extension
+
+{function_pointers}
+#ifdef GL_GLEXT_PROTOTYPES
+{function_prototypes}
+#endif
+"""
+
+template_glext_function_pointer = """typedef {return_type}(GL_APIENTRYP PFN{name_upper}{explicit_context_suffix_upper})({explicit_context_param}{explicit_context_comma}{params});"""
+template_glext_function_prototype = """{apicall} {return_type}GL_APIENTRY {name}{explicit_context_suffix}({explicit_context_param}{explicit_context_comma}{params});"""
def script_relative(path):
return os.path.join(os.path.dirname(sys.argv[0]), path)
@@ -226,11 +250,16 @@
with open(script_relative('entry_point_packed_gl_enums.json')) as f:
cmd_packed_gl_enums = json.loads(f.read())
-def format_entry_point_decl(cmd_name, proto, params):
+def format_entry_point_decl(cmd_name, proto, params, is_explicit_context):
+ comma_if_needed = ", " if len(params) > 0 else ""
return template_entry_point_decl.format(
name = cmd_name[2:],
return_type = proto[:-len(cmd_name)],
- params = ", ".join(params))
+ params = ", ".join(params),
+ comma_if_needed = comma_if_needed,
+ explicit_context_suffix = "ContextANGLE" if is_explicit_context else "",
+ explicit_context_param = "GLeglContext ctx" if is_explicit_context else "",
+ explicit_context_comma = ", " if is_explicit_context and len(params) > 0 else "")
def type_name_sep_index(param):
space = param.rfind(" ")
@@ -298,17 +327,19 @@
return ""
return "GetDefaultReturnValue<EntryPoint::" + cmd_name[2:] + ", " + return_type + ">()"
-def get_context_getter_function(cmd_name):
+def get_context_getter_function(cmd_name, is_explicit_context):
if cmd_name == "glGetError":
- return "GetGlobalContext"
+ return "GetGlobalContext()"
+ elif is_explicit_context:
+ return "static_cast<gl::Context *>(ctx)"
else:
- return "GetValidGlobalContext"
+ return "GetValidGlobalContext()"
template_event_comment = """// Don't run an EVENT() macro on the EXT_debug_marker entry points.
// It can interfere with the debug events being set by the caller.
// """
-def format_entry_point_def(cmd_name, proto, params):
+def format_entry_point_def(cmd_name, proto, params, is_explicit_context):
packed_gl_enums = cmd_packed_gl_enums.get(cmd_name, {})
internal_params = [just_the_name_packed(param, packed_gl_enums) for param in params]
packed_gl_enum_conversions = []
@@ -344,8 +375,13 @@
format_params = ", ".join(format_params),
return_if_needed = "" if default_return == "" else "return ",
default_return_if_needed = "" if default_return == "" else "\n return " + default_return + ";\n",
- context_getter = get_context_getter_function(cmd_name),
- event_comment = event_comment)
+ context_getter = get_context_getter_function(cmd_name, is_explicit_context),
+ event_comment = event_comment,
+ explicit_context_suffix = "ContextANGLE" if is_explicit_context else "",
+ explicit_context_param = "GLeglContext ctx" if is_explicit_context else "",
+ explicit_context_comma = ", " if is_explicit_context and len(params) > 0 else "",
+ assert_explicit_context = "\nASSERT(context == GetValidGlobalContext());"
+ if is_explicit_context else "")
def format_context_gles_decl(cmd_name, proto, params):
packed_gl_enums = cmd_packed_gl_enums.get(cmd_name, {})
@@ -364,7 +400,7 @@
name_lower_no_suffix = name_lower_no_suffix,
internal_params = internal_params)
-def format_libgles_entry_point_def(cmd_name, proto, params):
+def format_libgles_entry_point_def(cmd_name, proto, params, is_explicit_context):
internal_params = [just_the_name(param) for param in params]
return_type = proto[:-len(cmd_name)]
@@ -372,20 +408,23 @@
name = cmd_name[2:],
return_type = return_type,
params = ", ".join(params),
- internal_params = ", ".join(internal_params)
- )
+ internal_params = ", ".join(internal_params),
+ explicit_context_suffix = "ContextANGLE" if is_explicit_context else "",
+ explicit_context_param = "GLeglContext ctx" if is_explicit_context else "",
+ explicit_context_comma = ", " if is_explicit_context and len(params) > 0 else "",
+ explicit_context_internal_param = "ctx" if is_explicit_context else "")
-def format_libgles_entry_point_export(cmd_name, ordinal):
+def format_libgles_entry_point_export(cmd_name, ordinal, is_explicit_context):
return libgles_entry_point_export.format(
name = cmd_name,
ordinal = ordinal,
- spaces = " "*(50 - len(cmd_name))
- )
+ spaces = " "*(50 - len(cmd_name)),
+ explicit_context_suffix = "ContextANGLE" if is_explicit_context else "")
def path_to(folder, file):
return os.path.join(script_relative(".."), "src", folder, file)
-def get_entry_points(all_commands, gles_commands, ordinal):
+def get_entry_points(all_commands, gles_commands, ordinal, is_explicit_context):
decls = []
defs = []
export_defs = []
@@ -400,12 +439,13 @@
param_text = ["".join(param.itertext()) for param in command.findall('param')]
proto_text = "".join(proto.itertext())
+ decls.append(format_entry_point_decl(cmd_name, proto_text, param_text,
+ is_explicit_context))
+ defs.append(format_entry_point_def(cmd_name, proto_text, param_text, is_explicit_context))
- decls.append(format_entry_point_decl(cmd_name, proto_text, param_text))
- defs.append(format_entry_point_def(cmd_name, proto_text, param_text))
-
- export_defs.append(format_libgles_entry_point_def(cmd_name, proto_text, param_text))
- exports.append(format_libgles_entry_point_export(cmd_name, ordinal))
+ export_defs.append(format_libgles_entry_point_def(cmd_name, proto_text, param_text,
+ is_explicit_context))
+ exports.append(format_libgles_entry_point_export(cmd_name, ordinal, is_explicit_context))
ordinal = ordinal + 1
return decls, defs, export_defs, exports
@@ -428,6 +468,45 @@
return decls
+def get_glext_decls(all_commands, gles_commands, version, is_explicit_context):
+ glext_ptrs = []
+ glext_protos = []
+ is_gles1 = False
+
+ if(version == ""):
+ is_gles1 = True
+
+ for command in all_commands:
+ proto = command.find('proto')
+ cmd_name = proto.find('name').text
+
+ if cmd_name not in gles_commands:
+ continue
+
+ param_text = ["".join(param.itertext()) for param in command.findall('param')]
+ proto_text = "".join(proto.itertext())
+
+ return_type = proto_text[:-len(cmd_name)]
+ params = ", ".join(param_text)
+
+ format_params = {
+ "apicall": "GL_API" if is_gles1 else "GL_APICALL",
+ "name": cmd_name,
+ "name_upper": cmd_name.upper(),
+ "return_type": return_type,
+ "params": params,
+ "explicit_context_comma": ", " if is_explicit_context and len(params) > 0 else "",
+ "explicit_context_suffix": "ContextANGLE" if is_explicit_context else "",
+ "explicit_context_suffix_upper": "CONTEXTANGLE" if is_explicit_context else "",
+ "explicit_context_param": "GLeglContext ctx" if is_explicit_context else ""}
+
+ glext_ptrs.append(template_glext_function_pointer.format(
+ **format_params))
+ glext_protos.append(template_glext_function_prototype.format(
+ **format_params))
+
+ return glext_ptrs, glext_protos
+
def write_file(annotation, comment, template, entry_points, suffix, includes, file):
content = template.format(
@@ -499,6 +578,24 @@
out.write(content)
out.close()
+def write_glext_explicit_context_inc(version, ptrs, protos):
+ folder_version = version if version != "31" else "3"
+
+ content = template_glext_explicit_context_inc.format(
+ script_name = os.path.basename(sys.argv[0]),
+ data_source_name = "gl.xml and gl_angle_ext.xml",
+ year = date.today().year,
+ version = version,
+ function_pointers = ptrs,
+ function_prototypes = protos)
+
+ path = path_to("..\include\GLES{}".format(folder_version),
+ "gl{}ext_explicit_context_autogen.inc".format(version))
+
+ with open(path, "w") as out:
+ out.write(content)
+ out.close()
+
def append_angle_extensions(base_root):
angle_ext_tree = etree.parse(script_relative('gl_angle_ext.xml'))
angle_ext_root = angle_ext_tree.getroot()
@@ -512,10 +609,32 @@
insertion_point.extend(extension)
return base_root
+class GLCommandNames:
+ def __init__(self):
+ self.command_names = {}
+
+ def get_commands(self, version):
+ return self.command_names[version]
+
+ def get_all_commands(self):
+ cmd_names = []
+ # Combine all the version lists into a single list
+ for version, version_cmd_names in sorted(self.command_names.iteritems()):
+ cmd_names += version_cmd_names
+
+ return cmd_names
+
+ def add_commands(self, version, commands):
+ # Add key if it doesn't exist
+ if version not in self.command_names:
+ self.command_names[version] = []
+ # Add the commands that aren't duplicates
+ self.command_names[version] += commands
+
root = append_angle_extensions(root)
all_commands = root.findall('commands/command')
-all_cmd_names = []
+all_cmd_names = GLCommandNames()
template_header_includes = """#include <GLES{major}/gl{major}{minor}.h>
#include <export.h>"""
@@ -552,12 +671,12 @@
gles_commands = [cmd.attrib['name'] for cmd in root.findall(gles_xpath)]
# Remove commands that have already been processed
- gles_commands = [cmd for cmd in gles_commands if cmd not in all_cmd_names]
+ gles_commands = [cmd for cmd in gles_commands if cmd not in all_cmd_names.get_all_commands()]
- all_cmd_names += gles_commands
+ all_cmd_names.add_commands(annotation, gles_commands)
decls, defs, libgles_defs, libgles_exports = get_entry_points(
- all_commands, gles_commands, ordinal_start)
+ all_commands, gles_commands, ordinal_start, False)
# Increment the ordinal before inserting the version comment
ordinal_start += len(libgles_exports)
@@ -580,7 +699,7 @@
header_includes += "\n#include \"common/platform.h\"\n"
source_includes = template_sources_includes.format(
- annotation.lower(), major_version,minor_if_not_zero)
+ annotation.lower(), major_version, minor_if_not_zero)
write_file(annotation, comment, template_entry_point_header,
"\n".join(decls), "h", header_includes, "gl.xml")
@@ -631,16 +750,19 @@
# Detect and filter duplicate extensions.
dupes = []
for ext_cmd in ext_cmd_names:
- if ext_cmd in all_cmd_names:
+ if ext_cmd in all_cmd_names.get_all_commands():
dupes.append(ext_cmd)
for dupe in dupes:
ext_cmd_names.remove(dupe)
- all_cmd_names += ext_cmd_names
+ if extension_name in gles1_extensions:
+ all_cmd_names.add_commands("glext", ext_cmd_names)
+ else:
+ all_cmd_names.add_commands("gl2ext", ext_cmd_names)
decls, defs, libgles_defs, libgles_exports = get_entry_points(
- all_commands, ext_cmd_names, ordinal_start)
+ all_commands, ext_cmd_names, ordinal_start, False)
# Avoid writing out entry points defined by a prior extension.
for dupe in dupes:
@@ -667,6 +789,51 @@
if extension_name not in gles1_no_context_decl_extensions:
gles1decls['exts'][extension_name] = get_gles1_decls(all_commands, ext_cmd_names)
+# Special handling for EGL_ANGLE_explicit_context extension
+if support_EGL_ANGLE_explicit_context:
+ comment = "\n// EGL_ANGLE_explicit_context"
+ extension_defs.append(comment)
+ extension_decls.append(comment)
+ libgles_ep_defs.append(comment)
+ libgles_ep_exports.append("\n ; EGL_ANGLE_explicit_context")
+
+ # Get the explicit context entry points
+ decls, defs, libgles_defs, libgles_exports = get_entry_points(all_commands,
+ all_cmd_names.get_all_commands(), ordinal_start, True)
+
+ # Append the explicit context entry points
+ extension_decls += decls
+ extension_defs += defs
+ libgles_ep_defs += libgles_defs
+ libgles_ep_exports += libgles_exports
+
+ # Generate .inc files for extension function pointers and declarations
+ for major, minor in [[2, 0], [3, 0], [3, 1], [1, 0]]:
+ annotation = "{}_{}".format(major, minor)
+
+ major_if_not_one = major if major != 1 else ""
+ minor_if_not_zero = minor if minor != 0 else ""
+ version = "{}{}".format(major_if_not_one, minor_if_not_zero)
+
+ glext_ptrs, glext_protos = get_glext_decls(all_commands,
+ all_cmd_names.get_commands(annotation), version, True)
+
+ glext_ext_ptrs = []
+ glext_ext_protos = []
+
+ # Append extensions for 1.0 and 2.0
+ if(annotation == "1_0"):
+ glext_ext_ptrs, glext_ext_protos = get_glext_decls(all_commands,
+ all_cmd_names.get_commands("glext"), version, True)
+ elif(annotation == "2_0"):
+ glext_ext_ptrs, glext_ext_protos = get_glext_decls(all_commands,
+ all_cmd_names.get_commands("gl2ext"), version, True)
+
+ glext_ptrs += glext_ext_ptrs
+ glext_protos += glext_ext_protos
+
+ write_glext_explicit_context_inc(version, "\n".join(glext_ptrs), "\n".join(glext_protos))
+
header_includes = template_header_includes.format(
major="", minor="")
header_includes += """
@@ -693,7 +860,7 @@
write_context_api_decls("1_0", context_gles_header, gles1decls)
-sorted_cmd_names = ["Invalid"] + [cmd[2:] for cmd in sorted(all_cmd_names)]
+sorted_cmd_names = ["Invalid"] + [cmd[2:] for cmd in sorted(all_cmd_names.get_all_commands())]
entry_points_enum = template_entry_points_enum_header.format(
script_name = os.path.basename(sys.argv[0]),