1#!/usr/bin/python3 2# Copyright 2017 The ANGLE Project Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5# 6# gen_proc_table.py: 7# Code generation for entry point loading tables. 8# NOTE: don't run this script directly. Run scripts/run_code_generation.py. 9 10import os 11import sys 12import registry_xml 13 14out_file_name_gles = "../src/libGLESv2/egl_stubs_getprocaddress_autogen.cpp" 15out_file_name_cl = "../src/libGLESv2/proc_table_cl_autogen.cpp" 16out_file_name_cl_map = "../src/libOpenCL/libOpenCL_autogen.map" 17 18strip_suffixes = ["ANGLE", "EXT", "KHR", "OES", "CHROMIUM", "OVR"] 19 20template_cpp = """// GENERATED FILE - DO NOT EDIT. 21// Generated by {script_name} using data from {data_source_name}. 22// 23// Copyright 2019 The ANGLE Project Authors. All rights reserved. 24// Use of this source code is governed by a BSD-style license that can be 25// found in the LICENSE file. 26// 27// getProcAddress loader table: 28// Mapping from a string entry point name to function address. 29// 30 31{includes} 32#define P(FUNC) reinterpret_cast<{cast}>(FUNC) 33 34namespace {namespace} 35{{ 36 37namespace 38{{ 39struct ProcEntry 40{{ 41 const char *name; 42 __eglMustCastToProperFunctionPointerType func; 43}}; 44 45bool CompareProc(const ProcEntry &a, const char *b) 46{{ 47 return strcmp(a.name, b) < 0; 48}} 49 50// clang-format off 51const ProcEntry g_procTable[] = {{ 52{proc_data} 53}}; 54// clang-format on 55}} // anonymous namespace 56 57__eglMustCastToProperFunctionPointerType GetProcAddress(Thread *thread, const char *procname) 58{{ 59 if (procname == nullptr) 60 {{ 61 return nullptr; 62 }} 63 64 const ProcEntry *entry = 65 std::lower_bound(std::begin(g_procTable), std::end(g_procTable), procname, CompareProc); 66 67 thread->setSuccess(); 68 69 if (entry == std::end(g_procTable) || strcmp(entry->name, procname) != 0) 70 {{ 71 return nullptr; 72 }} 73 74 return entry->func; 75}} 76 77}} // namespace {namespace} 78 79""" 80 81# FOR OPENCL 82template_map_cpp = """// GENERATED FILE - DO NOT EDIT. 83// Generated by {script_name} using data from {data_source_name}. 84// 85// Copyright 2021 The ANGLE Project Authors. All rights reserved. 86// Use of this source code is governed by a BSD-style license that can be 87// found in the LICENSE file. 88// 89// proc_table: 90// Mapping from a string entry point name to function address. 91// 92 93{includes} 94#define P(FUNC) reinterpret_cast<{cast}>(FUNC) 95 96namespace {namespace} 97{{ 98 99const ProcTable &GetProcTable() 100{{ 101 static angle::base::NoDestructor<ProcTable> sProcTable( 102 {{{proc_data}}}); 103 return *sProcTable; 104}} 105 106}} // namespace {namespace} 107""" 108 109# FOR OPENCL 110template_map = """/* GENERATED FILE - DO NOT EDIT. 111 * Generated by {script_name} using data from {data_source_name}. 112 * 113 * Copyright 2021 The ANGLE Project Authors. All rights reserved. 114 * Use of this source code is governed by a BSD-style license that can be 115 * found in the LICENSE file. 116 * 117 * symbol version map: Maps versions to entry point names for a shared library. 118 */ 119{symbol_maps} 120""" 121 122includes_gles = """#include "libANGLE/Thread.h" 123#include "libGLESv2/entry_points_egl_autogen.h" 124#include "libGLESv2/entry_points_egl_ext_autogen.h" 125#include "libGLESv2/entry_points_gles_1_0_autogen.h" 126#include "libGLESv2/entry_points_gles_2_0_autogen.h" 127#include "libGLESv2/entry_points_gles_3_0_autogen.h" 128#include "libGLESv2/entry_points_gles_3_1_autogen.h" 129#include "libGLESv2/entry_points_gles_3_2_autogen.h" 130#include "libGLESv2/entry_points_gles_ext_autogen.h" 131#include "platform/PlatformMethods.h" 132 133#include <iterator> 134""" 135 136includes_cl = """#include "libGLESv2/proc_table_cl.h" 137 138#include "libGLESv2/entry_points_cl_autogen.h" 139 140#include "anglebase/no_destructor.h" 141 142// Using fully qualified entry point identifiers to make sure that missing entry points would not 143// pick up the global declarations of OpenCL 144""" 145 146sys.path.append('../src/libANGLE/renderer') 147import angle_format 148 149 150def _get_annotations(versions): 151 return ["%d_%d" % version for version in versions] 152 153 154def main(): 155 156 # auto_script parameters. 157 if len(sys.argv) > 1: 158 inputs = [source for source in registry_xml.xml_inputs] 159 outputs = [out_file_name_gles, out_file_name_cl, out_file_name_cl_map] 160 if sys.argv[1] == 'inputs': 161 print(','.join(inputs)) 162 elif sys.argv[1] == 'outputs': 163 print(','.join(outputs)) 164 else: 165 print('Invalid script parameters') 166 return 1 167 return 0 168 169 glesxml = registry_xml.RegistryXML('gl.xml', 'gl_angle_ext.xml') 170 171 for annotation in _get_annotations(registry_xml.GLES_VERSIONS): 172 name_prefix = "GL_ES_VERSION_" 173 if annotation[0] == '1': 174 name_prefix = "GL_VERSION_ES_CM_" 175 feature_name = "{}{}".format(name_prefix, annotation) 176 glesxml.AddCommands(feature_name, annotation) 177 178 glesxml.AddExtensionCommands(registry_xml.supported_extensions, ['gles2', 'gles1']) 179 180 # Also don't add GLES extension commands to libGL proc table 181 extension_commands = [] 182 for extension_name, ext_cmd_names in sorted(glesxml.ext_data.items()): 183 extension_commands.extend(glesxml.ext_data[extension_name]) 184 for name in extension_commands: 185 name_no_suffix = name 186 for suffix in strip_suffixes: 187 if name_no_suffix.endswith(suffix): 188 name_no_suffix = name_no_suffix[0:-len(suffix)] 189 190 gles_data = glesxml.all_cmd_names.get_all_commands() 191 eglxml = registry_xml.RegistryXML('egl.xml', 'egl_angle_ext.xml') 192 193 for annotation in _get_annotations(registry_xml.EGL_VERSIONS): 194 name_prefix = "EGL_VERSION_" 195 feature_name = "{}{}".format(name_prefix, annotation) 196 eglxml.AddCommands(feature_name, annotation) 197 198 eglxml.AddExtensionCommands(registry_xml.supported_egl_extensions, ['gles2', 'gles1']) 199 200 gles_data.extend(eglxml.all_cmd_names.get_all_commands()) 201 202 gles_data.append("ANGLEGetDisplayPlatform") 203 gles_data.append("ANGLEResetDisplayPlatform") 204 gles_data = set(gles_data) 205 206 all_functions = {} 207 for function in gles_data: 208 if function.startswith("gl"): 209 all_functions[function] = "GL_" + function[2:] 210 elif function.startswith("egl"): 211 all_functions[function] = "EGL_" + function[3:] 212 else: 213 all_functions[function] = function 214 215 proc_data = [] 216 for func, angle_func in sorted(all_functions.items()): 217 proc_data.append(' {"%s", P(%s)},' % (func, angle_func)) 218 219 with open(out_file_name_gles, 'w') as out_file: 220 output_cpp = template_cpp.format( 221 script_name=os.path.basename(sys.argv[0]), 222 data_source_name="gl.xml, gl_angle_ext.xml, egl.xml, egl_angle_ext.xml", 223 includes=includes_gles, 224 cast="__eglMustCastToProperFunctionPointerType", 225 namespace="egl", 226 proc_data="\n".join(proc_data), 227 num_procs="std::size(g_procTable)") 228 out_file.write(output_cpp) 229 out_file.close() 230 231 # libCL proc table 232 clxml = registry_xml.RegistryXML('cl.xml') 233 symbol_maps = [] 234 symbol_map_dependency = "" 235 236 for major_version, minor_version in registry_xml.CL_VERSIONS: 237 name_prefix = "CL_VERSION_" 238 annotation = "%d_%d" % (major_version, minor_version) 239 feature_name = "%s%s" % (name_prefix, annotation) 240 clxml.AddCommands(feature_name, annotation) 241 symbol_version = "OPENCL_%d.%d" % (major_version, minor_version) 242 symbol_maps += ["\n%s {\n global:" % symbol_version] 243 symbol_maps += [' %s;' % cmd for cmd in clxml.commands[annotation]] 244 if not symbol_map_dependency: 245 symbol_maps += [" local:\n *;\n};"] 246 else: 247 symbol_maps += ["} %s;" % symbol_map_dependency] 248 symbol_map_dependency = symbol_version 249 250 clxml.AddExtensionCommands(registry_xml.supported_cl_extensions, ['cl']) 251 cl_commands = clxml.all_cmd_names.get_all_commands() 252 proc_data = ['{"%s", P(::cl::%s)}' % (cmd, cmd) for cmd in cl_commands] 253 254 with open(out_file_name_cl, 'w') as out_file: 255 output_cpp = template_map_cpp.format( 256 script_name=os.path.basename(sys.argv[0]), 257 data_source_name="cl.xml", 258 includes=includes_cl, 259 cast="void *", 260 namespace="cl", 261 proc_data=",\n ".join(proc_data)) 262 out_file.write(output_cpp) 263 out_file.close() 264 265 with open(out_file_name_cl_map, 'w') as out_file: 266 output_map = template_map.format( 267 script_name=os.path.basename(sys.argv[0]), 268 data_source_name="cl.xml", 269 symbol_maps="\n".join(symbol_maps)) 270 out_file.write(output_map) 271 out_file.close() 272 273 return 0 274 275 276if __name__ == '__main__': 277 sys.exit(main()) 278