1#!/usr/bin/python2 2# 3# Copyright 2018 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_loader.py: 8# Generates dynamic loaders for various binding interfaces. 9# NOTE: don't run this script directly. Run scripts/run_code_generation.py. 10 11import sys, os, pprint, json 12from datetime import date 13import registry_xml 14 15 16def write_header(data_source_name, 17 all_cmds, 18 api, 19 preamble, 20 path, 21 lib, 22 ns="", 23 prefix=None, 24 export=""): 25 file_name = "%s_loader_autogen.h" % api 26 header_path = registry_xml.path_to(path, file_name) 27 28 def pre(cmd): 29 if prefix == None: 30 return cmd 31 return prefix + cmd[len(api):] 32 33 with open(header_path, "w") as out: 34 var_protos = [ 35 "%sextern PFN%sPROC %s%s;" % (export, cmd.upper(), ns, pre(cmd)) for cmd in all_cmds 36 ] 37 loader_header = template_loader_h.format( 38 script_name=os.path.basename(sys.argv[0]), 39 data_source_name=data_source_name, 40 year=date.today().year, 41 function_pointers="\n".join(var_protos), 42 api_upper=api.upper(), 43 api_lower=api, 44 preamble=preamble, 45 export=export, 46 lib=lib.upper(), 47 load_fn_name="Load%s%s" % (prefix if prefix else "", api.upper())) 48 49 out.write(loader_header) 50 out.close() 51 52 53def write_source(data_source_name, all_cmds, api, path, ns="", prefix=None, export=""): 54 file_name = "%s_loader_autogen.cpp" % api 55 source_path = registry_xml.path_to(path, file_name) 56 57 def pre(cmd): 58 if prefix == None: 59 return cmd 60 return prefix + cmd[len(api):] 61 62 with open(source_path, "w") as out: 63 var_defs = ["%sPFN%sPROC %s%s;" % (export, cmd.upper(), ns, pre(cmd)) for cmd in all_cmds] 64 65 setter = " %s%s = reinterpret_cast<PFN%sPROC>(loadProc(\"%s\"));" 66 setters = [setter % (ns, pre(cmd), cmd.upper(), pre(cmd)) for cmd in all_cmds] 67 68 loader_source = template_loader_cpp.format( 69 script_name=os.path.basename(sys.argv[0]), 70 data_source_name=data_source_name, 71 year=date.today().year, 72 function_pointers="\n".join(var_defs), 73 set_pointers="\n".join(setters), 74 api_upper=api.upper(), 75 api_lower=api, 76 load_fn_name="Load%s%s" % (prefix if prefix else "", api.upper())) 77 78 out.write(loader_source) 79 out.close() 80 81 82def gen_libegl_loader(): 83 84 data_source_name = "egl.xml and egl_angle_ext.xml" 85 xml = registry_xml.RegistryXML("egl.xml", "egl_angle_ext.xml") 86 87 for major_version, minor_version in [[1, 0], [1, 1], [1, 2], [1, 3], [1, 4], [1, 5]]: 88 annotation = "{}_{}".format(major_version, minor_version) 89 name_prefix = "EGL_VERSION_" 90 91 feature_name = "{}{}".format(name_prefix, annotation) 92 93 xml.AddCommands(feature_name, annotation) 94 95 xml.AddExtensionCommands(registry_xml.supported_egl_extensions, ['egl']) 96 97 all_cmds = xml.all_cmd_names.get_all_commands() 98 99 path = os.path.join("..", "src", "libEGL") 100 write_header(data_source_name, all_cmds, "egl", libegl_preamble, path, "LIBEGL", "", "EGL_", 101 "ANGLE_NO_EXPORT ") 102 write_source(data_source_name, all_cmds, "egl", path, "", "EGL_") 103 104 105def gen_gl_loader(): 106 107 data_source_name = "gl.xml and gl_angle_ext.xml" 108 xml = registry_xml.RegistryXML("gl.xml", "gl_angle_ext.xml") 109 110 # First run through the main GLES entry points. Since ES2+ is the primary use 111 # case, we go through those first and then add ES1-only APIs at the end. 112 for major_version, minor_version in [[2, 0], [3, 0], [3, 1], [1, 0]]: 113 annotation = "{}_{}".format(major_version, minor_version) 114 name_prefix = "GL_ES_VERSION_" 115 116 is_gles1 = major_version == 1 117 if is_gles1: 118 name_prefix = "GL_VERSION_ES_CM_" 119 120 feature_name = "{}{}".format(name_prefix, annotation) 121 122 xml.AddCommands(feature_name, annotation) 123 124 xml.AddExtensionCommands(registry_xml.supported_extensions, ['gles2', 'gles1']) 125 126 all_cmds = xml.all_cmd_names.get_all_commands() 127 128 if registry_xml.support_EGL_ANGLE_explicit_context: 129 all_cmds += [cmd + "ContextANGLE" for cmd in xml.all_cmd_names.get_all_commands()] 130 131 path = os.path.join("..", "util") 132 ex = "ANGLE_UTIL_EXPORT " 133 write_header(data_source_name, all_cmds, "gles", util_gles_preamble, path, "UTIL", export=ex) 134 write_source(data_source_name, all_cmds, "gles", path, export=ex) 135 136 137def gen_egl_loader(): 138 139 data_source_name = "egl.xml and egl_angle_ext.xml" 140 xml = registry_xml.RegistryXML("egl.xml", "egl_angle_ext.xml") 141 142 for major_version, minor_version in [[1, 0], [1, 1], [1, 2], [1, 3], [1, 4], [1, 5]]: 143 annotation = "{}_{}".format(major_version, minor_version) 144 name_prefix = "EGL_VERSION_" 145 146 feature_name = "{}{}".format(name_prefix, annotation) 147 148 xml.AddCommands(feature_name, annotation) 149 150 xml.AddExtensionCommands(registry_xml.supported_egl_extensions, ['egl']) 151 152 all_cmds = xml.all_cmd_names.get_all_commands() 153 154 path = os.path.join("..", "util") 155 ex = "ANGLE_UTIL_EXPORT " 156 write_header(data_source_name, all_cmds, "egl", util_egl_preamble, path, "UTIL", export=ex) 157 write_source(data_source_name, all_cmds, "egl", path, export=ex) 158 159 160def gen_wgl_loader(): 161 162 supported_wgl_extensions = [ 163 "WGL_ARB_create_context", 164 "WGL_ARB_extensions_string", 165 "WGL_EXT_swap_control", 166 ] 167 168 source = "wgl.xml" 169 xml = registry_xml.RegistryXML(source) 170 171 for major_version, minor_version in [[1, 0]]: 172 annotation = "{}_{}".format(major_version, minor_version) 173 name_prefix = "WGL_VERSION_" 174 175 feature_name = "{}{}".format(name_prefix, annotation) 176 177 xml.AddCommands(feature_name, annotation) 178 179 xml.AddExtensionCommands(supported_wgl_extensions, ['wgl']) 180 181 all_cmds = xml.all_cmd_names.get_all_commands() 182 183 path = os.path.join("..", "util", "windows") 184 write_header(source, all_cmds, "wgl", util_wgl_preamble, path, "UTIL_WINDOWS", "_") 185 write_source(source, all_cmds, "wgl", path, "_") 186 187 188def main(): 189 190 # Handle inputs/outputs for run_code_generation.py's auto_script 191 if len(sys.argv) > 1: 192 inputs = [ 193 'gl.xml', 194 'gl_angle_ext.xml', 195 'egl.xml', 196 'egl_angle_ext.xml', 197 'registry_xml.py', 198 'wgl.xml', 199 ] 200 outputs = [ 201 '../src/libEGL/egl_loader_autogen.cpp', 202 '../src/libEGL/egl_loader_autogen.h', 203 '../util/egl_loader_autogen.cpp', 204 '../util/egl_loader_autogen.h', 205 '../util/gles_loader_autogen.cpp', 206 '../util/gles_loader_autogen.h', 207 '../util/windows/wgl_loader_autogen.cpp', 208 '../util/windows/wgl_loader_autogen.h', 209 ] 210 211 if sys.argv[1] == 'inputs': 212 print ','.join(inputs) 213 elif sys.argv[1] == 'outputs': 214 print ','.join(outputs) 215 else: 216 print('Invalid script parameters') 217 return 1 218 return 0 219 220 gen_libegl_loader() 221 gen_gl_loader() 222 gen_egl_loader() 223 gen_wgl_loader() 224 return 0 225 226 227libegl_preamble = """#include <EGL/egl.h> 228#include <EGL/eglext.h> 229#include <export.h> 230""" 231 232util_gles_preamble = """#if defined(GL_GLES_PROTOTYPES) && GL_GLES_PROTOTYPES 233#error "Don't define GL prototypes if you want to use a loader!" 234#endif // defined(GL_GLES_PROTOTYPES) 235 236#include "angle_gl.h" 237#include "util/util_export.h" 238""" 239 240util_egl_preamble = """#include "util/util_export.h" 241 242#include <EGL/egl.h> 243#include <EGL/eglext.h> 244""" 245 246util_wgl_preamble = """ 247#include <WGL/wgl.h> 248#include <GLES2/gl2.h> 249 250// We add an underscore before each function name to ensure common names like "ChoosePixelFormat" 251// and "SwapBuffers" don't conflict with our function pointers. We can't use a namespace because 252// some functions conflict with preprocessor definitions. 253""" 254 255template_loader_h = """// GENERATED FILE - DO NOT EDIT. 256// Generated by {script_name} using data from {data_source_name}. 257// 258// Copyright {year} The ANGLE Project Authors. All rights reserved. 259// Use of this source code is governed by a BSD-style license that can be 260// found in the LICENSE file. 261// 262// {api_lower}_loader_autogen.h: 263// Simple {api_upper} function loader. 264 265#ifndef {lib}_{api_upper}_LOADER_AUTOGEN_H_ 266#define {lib}_{api_upper}_LOADER_AUTOGEN_H_ 267 268{preamble} 269{function_pointers} 270 271namespace angle 272{{ 273using GenericProc = void (*)(); 274using LoadProc = GenericProc (KHRONOS_APIENTRY *)(const char *); 275{export}void {load_fn_name}(LoadProc loadProc); 276}} // namespace angle 277 278#endif // {lib}_{api_upper}_LOADER_AUTOGEN_H_ 279""" 280 281template_loader_cpp = """// GENERATED FILE - DO NOT EDIT. 282// Generated by {script_name} using data from {data_source_name}. 283// 284// Copyright {year} The ANGLE Project Authors. All rights reserved. 285// Use of this source code is governed by a BSD-style license that can be 286// found in the LICENSE file. 287// 288// {api_lower}_loader_autogen.cpp: 289// Simple {api_upper} function loader. 290 291#include "{api_lower}_loader_autogen.h" 292 293{function_pointers} 294 295namespace angle 296{{ 297void {load_fn_name}(LoadProc loadProc) 298{{ 299{set_pointers} 300}} 301}} // namespace angle 302""" 303 304if __name__ == '__main__': 305 sys.exit(main()) 306