#!/usr/bin/python3 # Copyright 2017 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. # # gen_proc_table.py: # Code generation for entry point loading tables. # NOTE: don't run this script directly. Run scripts/run_code_generation.py. import os import sys import registry_xml out_file_name_gles = "../src/libGLESv2/proc_table_egl_autogen.cpp" out_file_name_wgl = "../src/libGLESv2/proc_table_wgl_autogen.cpp" out_file_name_glx = "../src/libGLESv2/proc_table_glx_autogen.cpp" out_file_name_cl = "../src/libGLESv2/proc_table_cl_autogen.cpp" out_file_name_cl_map = "../src/libOpenCL/libOpenCL_autogen.map" strip_suffixes = ["ANGLE", "EXT", "KHR", "OES", "CHROMIUM", "OVR"] template_cpp = """// GENERATED FILE - DO NOT EDIT. // Generated by {script_name} using data from {data_source_name}. // // Copyright 2019 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. // // getProcAddress loader table: // Mapping from a string entry point name to function address. // {includes} #define P(FUNC) reinterpret_cast<{cast}>(FUNC) {desktop_only_macro_definition} namespace {namespace} {{ // clang-format off const ProcEntry g_procTable[] = {{ {proc_data} }}; // clang-format on const size_t g_numProcs = {num_procs}; }} // namespace {namespace} """ desktop_only_macro_definition = """ #if defined(ANGLE_ENABLE_GL_DESKTOP_FRONTEND) # define DESKTOP_ONLY(func, angleFunc) {func, P(angleFunc)}, #else # define DESKTOP_ONLY(func, angleFunc) #endif """ # FOR OPENCL template_map_cpp = """// GENERATED FILE - DO NOT EDIT. // Generated by {script_name} using data from {data_source_name}. // // Copyright 2021 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. // // proc_table: // Mapping from a string entry point name to function address. // {includes} #define P(FUNC) reinterpret_cast<{cast}>(FUNC) namespace {namespace} {{ const ProcTable &GetProcTable() {{ static angle::base::NoDestructor sProcTable( {{{proc_data}}}); return *sProcTable; }} }} // namespace {namespace} """ # FOR OPENCL template_map = """/* GENERATED FILE - DO NOT EDIT. * Generated by {script_name} using data from {data_source_name}. * * Copyright 2021 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. * * symbol version map: Maps versions to entry point names for a shared library. */ {symbol_maps} """ includes_gles = """#include "libGLESv2/proc_table_egl.h" #include "libGLESv2/entry_points_egl_autogen.h" #include "libGLESv2/entry_points_egl_ext_autogen.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_3_2_autogen.h" #include "libGLESv2/entry_points_gles_ext_autogen.h" #include "platform/PlatformMethods.h" #if defined(ANGLE_ENABLE_GL_DESKTOP_FRONTEND) # include "libGLESv2/entry_points_gl_1_autogen.h" # include "libGLESv2/entry_points_gl_2_autogen.h" # include "libGLESv2/entry_points_gl_3_autogen.h" # include "libGLESv2/entry_points_gl_4_autogen.h" #endif #include """ includes_wgl = """#include "libGLESv2/proc_table_wgl.h" #include "libGLESv2/entry_points_egl_ext_autogen.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_3_2_autogen.h" #include "libGLESv2/entry_points_gles_ext_autogen.h" #include "platform/PlatformMethods.h" #include "libGLESv2/entry_points_gl_1_autogen.h" #include "libGLESv2/entry_points_gl_2_autogen.h" #include "libGLESv2/entry_points_gl_3_autogen.h" #include "libGLESv2/entry_points_gl_4_autogen.h" #include "libGLESv2/entry_points_wgl.h" #include """ includes_glx = """#include "libGLESv2/proc_table_glx.h" #include "libGLESv2/entry_points_egl_ext_autogen.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_3_2_autogen.h" #include "libGLESv2/entry_points_gles_ext_autogen.h" #include "platform/PlatformMethods.h" #include "libGLESv2/entry_points_gl_1_autogen.h" #include "libGLESv2/entry_points_gl_2_autogen.h" #include "libGLESv2/entry_points_gl_3_autogen.h" #include "libGLESv2/entry_points_gl_4_autogen.h" #include "libGLESv2/entry_points_glx.h" #include """ includes_cl = """#include "libGLESv2/proc_table_cl.h" #include "libGLESv2/entry_points_cl_autogen.h" #include "anglebase/no_destructor.h" // Using fully qualified entry point identifiers to make sure that missing entry points would not // pick up the global declarations of OpenCL """ sys.path.append('../src/libANGLE/renderer') import angle_format def _get_annotations(versions): return ["%d_%d" % version for version in versions] def main(): # auto_script parameters. if len(sys.argv) > 1: inputs = [source for source in registry_xml.xml_inputs] outputs = [ out_file_name_gles, out_file_name_wgl, out_file_name_glx, out_file_name_cl, out_file_name_cl_map ] if sys.argv[1] == 'inputs': print(','.join(inputs)) elif sys.argv[1] == 'outputs': print(','.join(outputs)) else: print('Invalid script parameters') return 1 return 0 glesxml = registry_xml.RegistryXML('gl.xml', 'gl_angle_ext.xml') for annotation in _get_annotations(registry_xml.GLES_VERSIONS): name_prefix = "GL_ES_VERSION_" if annotation[0] == '1': name_prefix = "GL_VERSION_ES_CM_" feature_name = "{}{}".format(name_prefix, annotation) glesxml.AddCommands(feature_name, annotation) glesxml.AddExtensionCommands(registry_xml.supported_extensions, ['gles2', 'gles1']) # Also don't add GLES extension commands to libGL proc table extension_commands = [] for extension_name, ext_cmd_names in sorted(glesxml.ext_data.items()): extension_commands.extend(glesxml.ext_data[extension_name]) for name in extension_commands: name_no_suffix = name for suffix in strip_suffixes: if name_no_suffix.endswith(suffix): name_no_suffix = name_no_suffix[0:-len(suffix)] gles_data = glesxml.all_cmd_names.get_all_commands() eglxml = registry_xml.RegistryXML('egl.xml', 'egl_angle_ext.xml') for annotation in _get_annotations(registry_xml.EGL_VERSIONS): name_prefix = "EGL_VERSION_" feature_name = "{}{}".format(name_prefix, annotation) eglxml.AddCommands(feature_name, annotation) eglxml.AddExtensionCommands(registry_xml.supported_egl_extensions, ['gles2', 'gles1']) gles_data.extend(eglxml.all_cmd_names.get_all_commands()) gles_data.append("ANGLEGetDisplayPlatform") gles_data.append("ANGLEResetDisplayPlatform") gles_data = set(gles_data) glxml = registry_xml.RegistryXML('gl.xml') for annotation in _get_annotations(registry_xml.DESKTOP_GL_VERSIONS): name_prefix = "GL_VERSION_" feature_name = "{}{}".format(name_prefix, annotation) glxml.AddCommands(feature_name, annotation) gl_data = set([cmd for cmd in glxml.all_cmd_names.get_all_commands()]) all_gl_data = list(set(gles_data).union(gl_data)) all_functions = {} for function in all_gl_data: if function.startswith("gl"): all_functions[function] = "GL_" + function[2:] elif function.startswith("egl"): all_functions[function] = "EGL_" + function[3:] else: all_functions[function] = function proc_data = [] gl_only_data = gl_data.difference(gles_data) for func, angle_func in sorted(all_functions.items()): if func in gl_only_data: proc_data.append(' DESKTOP_ONLY("%s", %s)' % (func, angle_func)) else: proc_data.append(' {"%s", P(%s)},' % (func, angle_func)) with open(out_file_name_gles, 'w') as out_file: output_cpp = template_cpp.format( script_name=os.path.basename(sys.argv[0]), data_source_name="gl.xml, gl_angle_ext.xml, egl.xml, egl_angle_ext.xml", includes=includes_gles, cast="__eglMustCastToProperFunctionPointerType", namespace="egl", proc_data="\n".join(proc_data), num_procs="std::size(g_procTable)", desktop_only_macro_definition=desktop_only_macro_definition) out_file.write(output_cpp) out_file.close() def WriteWindowingProcTable(api_name, out_file_name, includes, cast): xml_file_name = '{}.xml'.format(api_name) xml = registry_xml.RegistryXML(xml_file_name) annotations = _get_annotations( getattr(registry_xml, '{}_VERSIONS'.format(api_name.upper()))) for annotation in annotations: name_prefix = "{}_VERSION_".format(api_name.upper()) feature_name = "{}{}".format(name_prefix, annotation) xml.AddCommands(feature_name, annotation) commands = [ # Some WGL EP's need to have "wgl" appended to their names cmd if api_name != 'wgl' or cmd.startswith(api_name) else api_name + cmd for cmd in xml.all_cmd_names.get_all_commands() ] # Start with all of the GLES + Desktop entry points, filtering out the EGL ones proc_data = [ ' {"%s", P(%s)},' % (func, angle_func) for func, angle_func in sorted(all_functions.items()) if not func.startswith('egl') ] proc_data.extend([' {"%s", P(%s)},' % (cmd, cmd) for cmd in sorted(commands)]) with open(out_file_name, 'w') as out_file: output_cpp = template_cpp.format( script_name=os.path.basename(sys.argv[0]), data_source_name="gl.xml, gl_angle_ext.xml, {}".format(xml_file_name), includes=includes, cast=cast, namespace=api_name, proc_data="\n".join(proc_data), num_procs="std::size(g_procTable)", desktop_only_macro_definition='') out_file.write(output_cpp) out_file.close() WriteWindowingProcTable('wgl', out_file_name_wgl, includes_wgl, "PROC") WriteWindowingProcTable('glx', out_file_name_glx, includes_glx, "__GLXextFuncPtr") # libCL proc table clxml = registry_xml.RegistryXML('cl.xml') symbol_maps = [] symbol_map_dependency = "" for major_version, minor_version in registry_xml.CL_VERSIONS: name_prefix = "CL_VERSION_" annotation = "%d_%d" % (major_version, minor_version) feature_name = "%s%s" % (name_prefix, annotation) clxml.AddCommands(feature_name, annotation) symbol_version = "OPENCL_%d.%d" % (major_version, minor_version) symbol_maps += ["\n%s {\n global:" % symbol_version] symbol_maps += [' %s;' % cmd for cmd in clxml.commands[annotation]] if not symbol_map_dependency: symbol_maps += [" local:\n *;\n};"] else: symbol_maps += ["} %s;" % symbol_map_dependency] symbol_map_dependency = symbol_version clxml.AddExtensionCommands(registry_xml.supported_cl_extensions, ['cl']) cl_commands = clxml.all_cmd_names.get_all_commands() proc_data = ['{"%s", P(::cl::%s)}' % (cmd, cmd) for cmd in cl_commands] with open(out_file_name_cl, 'w') as out_file: output_cpp = template_map_cpp.format( script_name=os.path.basename(sys.argv[0]), data_source_name="cl.xml", includes=includes_cl, cast="void *", namespace="cl", proc_data=",\n ".join(proc_data)) out_file.write(output_cpp) out_file.close() with open(out_file_name_cl_map, 'w') as out_file: output_map = template_map.format( script_name=os.path.basename(sys.argv[0]), data_source_name="cl.xml", symbol_maps="\n".join(symbol_maps)) out_file.write(output_map) out_file.close() return 0 if __name__ == '__main__': sys.exit(main())