Autogenerate libGLESv2.cpp and .def

Add generation of libGLESv2.cpp and libGLESv2.def to generate_entry_points.py

Bug: angleproject:2476
Change-Id: I86c7fb31f73ccbbbc32b28acca179b11527dff9e
Reviewed-on: https://chromium-review.googlesource.com/1040647
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/scripts/generate_entry_points.py b/scripts/generate_entry_points.py
index 2843877..6dc9a13 100755
--- a/scripts/generate_entry_points.py
+++ b/scripts/generate_entry_points.py
@@ -143,6 +143,32 @@
 #endif  // LIBGLESV2_ENTRY_POINTS_ENUM_AUTOGEN_H_
 """
 
+template_libgles_entry_point_source = """// 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.
+//
+// libGLESv2.cpp: Implements the exported OpenGL ES functions.
+
+{includes}
+extern "C" {{
+{entry_points}
+}} // extern "C"
+"""
+
+template_libgles_entry_point_export = """; 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.
+LIBRARY libGLESv2
+EXPORTS
+{exports}
+"""
+
 template_entry_point_decl = """ANGLE_EXPORT {return_type}GL_APIENTRY {name}({params});"""
 
 template_entry_point_def = """{return_type}GL_APIENTRY {name}({params})
@@ -182,6 +208,14 @@
 
 context_gles_decl = """    {return_type} {name_lower_no_suffix}({internal_params}); \\"""
 
+libgles_entry_point_def = """{return_type}GL_APIENTRY gl{name}({params})
+{{
+    return gl::{name}({internal_params});
+}}
+"""
+
+libgles_entry_point_export = """    {name}{spaces}@{ordinal}"""
+
 def script_relative(path):
     return os.path.join(os.path.dirname(sys.argv[0]), path)
 
@@ -330,12 +364,33 @@
         name_lower_no_suffix = name_lower_no_suffix,
         internal_params = internal_params)
 
+def format_libgles_entry_point_def(cmd_name, proto, params):
+    internal_params = [just_the_name(param) for param in params]
+    return_type = proto[:-len(cmd_name)]
+
+    return libgles_entry_point_def.format(
+        name = cmd_name[2:],
+        return_type = return_type,
+        params = ", ".join(params),
+        internal_params = ", ".join(internal_params)
+    )
+
+def format_libgles_entry_point_export(cmd_name, ordinal):
+    return libgles_entry_point_export.format(
+        name = cmd_name,
+        ordinal = ordinal,
+        spaces = " "*(50 - len(cmd_name))
+    )
+
 def path_to(folder, file):
     return os.path.join(script_relative(".."), "src", folder, file)
 
-def get_entry_points(all_commands, gles_commands):
+def get_entry_points(all_commands, gles_commands, ordinal):
     decls = []
     defs = []
+    export_defs = []
+    exports = []
+
     for command in all_commands:
         proto = command.find('proto')
         cmd_name = proto.find('name').text
@@ -345,10 +400,15 @@
 
         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))
         defs.append(format_entry_point_def(cmd_name, proto_text, param_text))
 
-    return decls, defs
+        export_defs.append(format_libgles_entry_point_def(cmd_name, proto_text, param_text))
+        exports.append(format_libgles_entry_point_export(cmd_name, ordinal))
+        ordinal = ordinal + 1
+
+    return decls, defs, export_defs, exports
 
 def get_gles1_decls(all_commands, gles_commands):
     decls = []
@@ -368,7 +428,6 @@
 
     return decls
 
-
 def write_file(annotation, comment, template, entry_points, suffix, includes, file):
 
     content = template.format(
@@ -388,6 +447,33 @@
         out.write(content)
         out.close()
 
+def write_export_files(entry_points, includes, exports):
+
+    content = template_libgles_entry_point_source.format(
+        script_name = os.path.basename(sys.argv[0]),
+        data_source_name = "gl.xml and gl_angle_ext.xml",
+        year = date.today().year,
+        includes = includes,
+        entry_points = entry_points)
+
+    path = path_to("libGLESv2", "libGLESv2_autogen.cpp")
+
+    with open(path, "w") as out:
+        out.write(content)
+        out.close()
+
+    content = template_libgles_entry_point_export.format(
+        script_name = os.path.basename(sys.argv[0]),
+        data_source_name = "gl.xml and gl_angle_ext.xml",
+        exports = exports,
+        year = date.today().year)
+
+    path = path_to("libGLESv2", "libGLESv2_autogen.def")
+
+    with open(path, "w") as out:
+        out.write(content)
+        out.close()
+
 def write_context_api_decls(annotation, template, decls):
 
     interface_lines = []
@@ -446,6 +532,11 @@
 gles1decls['core'] = []
 gles1decls['exts'] = {}
 
+libgles_ep_defs = []
+libgles_ep_exports = []
+
+ordinal_start = 1
+
 # First run through the main GLES entry points.  Since ES2+ is the primary use
 # case, we go through those first and then add ES1-only APIs at the end.
 for major_version, minor_version in [[2, 0], [3, 0], [3, 1], [1, 0]]:
@@ -465,7 +556,18 @@
 
     all_cmd_names += gles_commands
 
-    decls, defs = get_entry_points(all_commands, gles_commands)
+    decls, defs, libgles_defs, libgles_exports = get_entry_points(
+        all_commands, gles_commands, ordinal_start)
+
+    # Increment the ordinal before inserting the version comment
+    ordinal_start += len(libgles_exports)
+
+    # Write the version as a comment before the first EP.
+    libgles_defs.insert(0, "\n// OpenGL ES {}.{}".format(major_version, minor_version))
+    libgles_exports.insert(0, "\n    ; OpenGL ES {}.{}".format(major_version, minor_version))
+
+    libgles_ep_defs += libgles_defs
+    libgles_ep_exports += libgles_exports
 
     major_if_not_one = major_version if major_version != 1 else ""
     minor_if_not_zero = minor_version if minor_version != 0 else ""
@@ -537,21 +639,30 @@
 
     all_cmd_names += ext_cmd_names
 
-    decls, defs = get_entry_points(all_commands, ext_cmd_names)
+    decls, defs, libgles_defs, libgles_exports = get_entry_points(
+        all_commands, ext_cmd_names, ordinal_start)
 
     # Avoid writing out entry points defined by a prior extension.
     for dupe in dupes:
         msg = "// {} is already defined.\n".format(dupe[2:])
         defs.append(msg)
 
+    # Increment starting ordinal before adding extension comment
+    ordinal_start += len(libgles_exports)
+
     # Write the extension name as a comment before the first EP.
     comment = "\n// {}".format(extension_name)
     defs.insert(0, comment)
     decls.insert(0, comment)
+    libgles_defs.insert(0, comment)
+    libgles_exports.insert(0, "\n    ; {}".format(extension_name))
 
     extension_defs += defs
     extension_decls += decls
 
+    libgles_ep_defs += libgles_defs
+    libgles_ep_exports += libgles_exports
+
     if extension_name in gles1_extensions:
         if extension_name not in gles1_no_context_decl_extensions:
             gles1decls['exts'][extension_name] = get_gles1_decls(all_commands, ext_cmd_names)
@@ -594,3 +705,17 @@
 with open(entry_points_enum_header_path, "w") as out:
     out.write(entry_points_enum)
     out.close()
+
+source_includes = """
+#include "angle_gl.h"
+
+#include "libGLESv2/entry_points_gles_1_0_autogen.h"
+#include "libGLESv2/entry_points_gles_2_0_autogen.h"
+#include "libGLESv2/entry_points_gles_3_0_autogen.h"
+#include "libGLESv2/entry_points_gles_3_1_autogen.h"
+#include "libGLESv2/entry_points_gles_ext_autogen.h"
+
+#include "common/event_tracer.h"
+"""
+
+write_export_files("\n".join([item for item in libgles_ep_defs]), source_includes, "\n".join([item for item in libgles_ep_exports]))
\ No newline at end of file