1#!/usr/bin/python3 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# registry_xml.py: 8# Parses information from Khronos registry files.. 9 10# List of supported extensions. Add to this list to enable new extensions 11# available in gl.xml. 12 13import os 14import sys 15import xml.etree.ElementTree as etree 16 17from enum import Enum 18 19xml_inputs = [ 20 'cl.xml', 21 'gl.xml', 22 'gl_angle_ext.xml', 23 'egl.xml', 24 'egl_angle_ext.xml', 25 'wgl.xml', 26 'registry_xml.py', 27] 28 29angle_extensions = [ 30 # ANGLE extensions 31 "GL_CHROMIUM_bind_uniform_location", 32 "GL_CHROMIUM_framebuffer_mixed_samples", 33 "GL_CHROMIUM_path_rendering", 34 "GL_CHROMIUM_copy_texture", 35 "GL_CHROMIUM_copy_compressed_texture", 36 "GL_CHROMIUM_lose_context", 37 "GL_ANGLE_copy_texture_3d", 38 "GL_ANGLE_get_image", 39 "GL_ANGLE_get_serialized_context_string", 40 "GL_ANGLE_get_tex_level_parameter", 41 "GL_ANGLE_program_binary", 42 "GL_ANGLE_request_extension", 43 "GL_ANGLE_robust_client_memory", 44 "GL_ANGLE_texture_external_update", 45] 46 47gles1_extensions = [ 48 # ES1 (Possibly the min set of extensions needed by Android) 49 "GL_OES_draw_texture", 50 "GL_OES_framebuffer_object", 51 "GL_OES_matrix_palette", 52 "GL_OES_point_size_array", 53 "GL_OES_query_matrix", 54 "GL_OES_texture_cube_map", 55] 56 57gles_extensions = [ 58 # ES2+ 59 "GL_ANGLE_base_vertex_base_instance", 60 "GL_ANGLE_framebuffer_blit", 61 "GL_ANGLE_framebuffer_multisample", 62 "GL_ANGLE_instanced_arrays", 63 "GL_ANGLE_memory_object_flags", 64 "GL_ANGLE_memory_object_fuchsia", 65 "GL_ANGLE_multi_draw", 66 "GL_ANGLE_provoking_vertex", 67 "GL_ANGLE_semaphore_fuchsia", 68 "GL_ANGLE_texture_multisample", 69 "GL_ANGLE_translated_shader_source", 70 "GL_KHR_blend_equation_advanced", 71 "GL_EXT_blend_func_extended", 72 "GL_EXT_buffer_storage", 73 "GL_EXT_copy_image", 74 "GL_EXT_clip_control", 75 "GL_EXT_debug_label", 76 "GL_EXT_debug_marker", 77 "GL_EXT_discard_framebuffer", 78 "GL_EXT_disjoint_timer_query", 79 "GL_EXT_draw_buffers", 80 "GL_EXT_draw_buffers_indexed", 81 "GL_EXT_draw_elements_base_vertex", 82 "GL_EXT_EGL_image_array", 83 "GL_EXT_external_buffer", 84 "GL_EXT_geometry_shader", 85 "GL_EXT_instanced_arrays", 86 "GL_EXT_map_buffer_range", 87 "GL_EXT_memory_object", 88 "GL_EXT_memory_object_fd", 89 "GL_EXT_multisampled_render_to_texture", 90 "GL_EXT_multisampled_render_to_texture2", 91 "GL_EXT_occlusion_query_boolean", 92 "GL_EXT_primitive_bounding_box", 93 "GL_EXT_read_format_bgra", 94 "GL_EXT_robustness", 95 "GL_EXT_semaphore", 96 "GL_EXT_semaphore_fd", 97 "GL_EXT_separate_shader_objects", 98 "GL_EXT_shader_framebuffer_fetch_non_coherent", 99 "GL_EXT_shader_io_blocks", 100 "GL_EXT_sRGB", 101 "GL_EXT_sRGB_write_control", 102 "GL_EXT_tessellation_shader", 103 "GL_EXT_texture_border_clamp", 104 "GL_EXT_texture_buffer", 105 "GL_EXT_texture_compression_bptc", 106 "GL_EXT_texture_compression_dxt1", 107 "GL_EXT_texture_compression_rgtc", 108 "GL_EXT_texture_compression_s3tc", 109 "GL_EXT_texture_compression_s3tc_srgb", 110 "GL_EXT_texture_cube_map_array", 111 "GL_EXT_texture_filter_anisotropic", 112 "GL_EXT_texture_format_BGRA8888", 113 "GL_EXT_texture_storage", 114 "GL_EXT_texture_sRGB_R8", 115 "GL_EXT_texture_sRGB_RG8", 116 "GL_EXT_YUV_target", 117 "GL_KHR_debug", 118 "GL_KHR_parallel_shader_compile", 119 "GL_NV_fence", 120 "GL_NV_framebuffer_blit", 121 "GL_OES_compressed_ETC1_RGB8_texture", 122 "GL_EXT_compressed_ETC1_RGB8_sub_texture", 123 "GL_OES_copy_image", 124 "GL_OES_depth32", 125 "GL_OES_draw_buffers_indexed", 126 "GL_OES_draw_elements_base_vertex", 127 "GL_OES_EGL_image", 128 "GL_OES_geometry_shader", 129 "GL_OES_get_program_binary", 130 "GL_OES_mapbuffer", 131 "GL_OES_sample_shading", 132 "GL_OES_shader_io_blocks", 133 "GL_OES_texture_3D", 134 "GL_OES_texture_border_clamp", 135 "GL_OES_texture_buffer", 136 "GL_OES_texture_cube_map_array", 137 "GL_OES_texture_half_float", 138 "GL_OES_texture_stencil8", 139 "GL_OES_texture_storage_multisample_2d_array", 140 "GL_OES_vertex_array_object", 141 "GL_OVR_multiview", 142 "GL_OVR_multiview2", 143] 144 145supported_extensions = sorted(angle_extensions + gles1_extensions + gles_extensions) 146 147supported_egl_extensions = [ 148 "EGL_ANDROID_blob_cache", 149 "EGL_ANDROID_create_native_client_buffer", 150 "EGL_ANDROID_framebuffer_target", 151 "EGL_ANDROID_get_frame_timestamps", 152 "EGL_ANDROID_get_native_client_buffer", 153 "EGL_ANDROID_native_fence_sync", 154 "EGL_ANDROID_presentation_time", 155 "EGL_ANGLE_d3d_share_handle_client_buffer", 156 "EGL_ANGLE_device_creation", 157 "EGL_ANGLE_device_d3d", 158 "EGL_ANGLE_display_semaphore_share_group", 159 "EGL_ANGLE_display_texture_share_group", 160 "EGL_ANGLE_feature_control", 161 "EGL_ANGLE_ggp_stream_descriptor", 162 "EGL_ANGLE_power_preference", 163 "EGL_ANGLE_program_cache_control", 164 "EGL_ANGLE_query_surface_pointer", 165 "EGL_ANGLE_stream_producer_d3d_texture", 166 "EGL_ANGLE_surface_d3d_texture_2d_share_handle", 167 "EGL_ANGLE_swap_with_frame_token", 168 "EGL_ANGLE_sync_control_rate", 169 "EGL_ANGLE_window_fixed_size", 170 "EGL_CHROMIUM_sync_control", 171 "EGL_EXT_create_context_robustness", 172 "EGL_EXT_device_query", 173 "EGL_EXT_gl_colorspace_display_p3", 174 "EGL_EXT_gl_colorspace_display_p3_linear", 175 "EGL_EXT_gl_colorspace_display_p3_passthrough", 176 "EGL_EXT_gl_colorspace_scrgb", 177 "EGL_EXT_gl_colorspace_scrgb_linear", 178 "EGL_EXT_image_gl_colorspace", 179 "EGL_EXT_pixel_format_float", 180 "EGL_EXT_platform_base", 181 "EGL_EXT_platform_device", 182 "EGL_EXT_protected_content", 183 "EGL_IMG_context_priority", 184 "EGL_KHR_debug", 185 "EGL_KHR_fence_sync", 186 "EGL_KHR_gl_colorspace", 187 "EGL_KHR_image", 188 "EGL_KHR_mutable_render_buffer", 189 "EGL_KHR_no_config_context", 190 "EGL_KHR_reusable_sync", 191 "EGL_KHR_stream", 192 "EGL_KHR_stream_consumer_gltexture", 193 "EGL_KHR_surfaceless_context", 194 "EGL_KHR_swap_buffers_with_damage", 195 "EGL_KHR_wait_sync", 196 "EGL_NV_post_sub_buffer", 197 "EGL_NV_stream_consumer_gltexture_yuv", 198] 199 200supported_cl_extensions = [ 201 # Since OpenCL 1.1 202 "cl_khr_byte_addressable_store", 203 "cl_khr_global_int32_base_atomics", 204 "cl_khr_global_int32_extended_atomics", 205 "cl_khr_local_int32_base_atomics", 206 "cl_khr_local_int32_extended_atomics", 207 208 # OpenCL 2.0 - 2.2 209 "cl_khr_3d_image_writes", 210 "cl_khr_depth_images", 211 "cl_khr_image2d_from_buffer", 212 213 # Optional 214 "cl_khr_extended_versioning", 215 "cl_khr_fp64", 216 "cl_khr_icd", 217 "cl_khr_int64_base_atomics", 218 "cl_khr_int64_extended_atomics", 219] 220 221# Strip these suffixes from Context entry point names. NV is excluded (for now). 222strip_suffixes = ["ANGLE", "EXT", "KHR", "OES", "CHROMIUM"] 223 224# The EGL_ANGLE_explicit_context extension is generated differently from other extensions. 225# Toggle generation here. 226support_EGL_ANGLE_explicit_context = True 227 228# For ungrouped GLenum types 229default_enum_group_name = "DefaultGroup" 230 231# Group names that appear in command/param, but not present in groups/group 232unsupported_enum_group_names = { 233 'GetMultisamplePNameNV', 234 'BufferPNameARB', 235 'BufferPointerNameARB', 236 'VertexAttribPointerPropertyARB', 237 'VertexAttribPropertyARB', 238 'FenceParameterNameNV', 239 'FenceConditionNV', 240 'BufferPointerNameARB', 241 'MatrixIndexPointerTypeARB', 242 'PointParameterNameARB', 243 'ClampColorTargetARB', 244 'ClampColorModeARB', 245} 246 247# Versions (major, minor). Note that GLES intentionally places 1.0 last. 248DESKTOP_GL_VERSIONS = [(1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (2, 0), (2, 1), (3, 0), 249 (3, 1), (3, 2), (3, 3), (4, 0), (4, 1), (4, 2), (4, 3), (4, 4), (4, 5), 250 (4, 6)] 251GLES_VERSIONS = [(2, 0), (3, 0), (3, 1), (3, 2), (1, 0)] 252EGL_VERSIONS = [(1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5)] 253WGL_VERSIONS = [(1, 0)] 254CL_VERSIONS = [(1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2), (3, 0)] 255 256 257# API types 258class apis: 259 GL = 'GL' 260 GLES = 'GLES' 261 WGL = 'WGL' 262 EGL = 'EGL' 263 CL = 'CL' 264 265 266def script_relative(path): 267 return os.path.join(os.path.dirname(sys.argv[0]), path) 268 269 270def path_to(folder, file): 271 return os.path.join(script_relative(".."), "src", folder, file) 272 273 274def strip_api_prefix(cmd_name): 275 return cmd_name.lstrip("cwegl") 276 277 278def get_cmd_name(command_node): 279 proto = command_node.find('proto') 280 cmd_name = proto.find('name').text 281 return cmd_name 282 283 284class CommandNames: 285 286 def __init__(self): 287 self.command_names = {} 288 289 def get_commands(self, version): 290 return self.command_names[version] 291 292 def get_all_commands(self): 293 cmd_names = [] 294 # Combine all the version lists into a single list 295 for version, version_cmd_names in sorted(self.command_names.items()): 296 cmd_names += version_cmd_names 297 298 return cmd_names 299 300 def add_commands(self, version, commands): 301 # Add key if it doesn't exist 302 if version not in self.command_names: 303 self.command_names[version] = [] 304 # Add the commands that aren't duplicates 305 self.command_names[version] += commands 306 307 308class RegistryXML: 309 310 def __init__(self, xml_file, ext_file=None): 311 tree = etree.parse(script_relative(xml_file)) 312 self.root = tree.getroot() 313 if (ext_file): 314 self._AppendANGLEExts(ext_file) 315 self.all_commands = self.root.findall('commands/command') 316 self.all_cmd_names = CommandNames() 317 self.commands = {} 318 319 def _AppendANGLEExts(self, ext_file): 320 angle_ext_tree = etree.parse(script_relative(ext_file)) 321 angle_ext_root = angle_ext_tree.getroot() 322 323 insertion_point = self.root.findall("./commands")[0] 324 for command in angle_ext_root.iter('commands'): 325 insertion_point.extend(command) 326 327 insertion_point = self.root.findall("./extensions")[0] 328 for extension in angle_ext_root.iter('extensions'): 329 insertion_point.extend(extension) 330 331 insertion_point = self.root 332 for enums in angle_ext_root.iter('enums'): 333 insertion_point.append(enums) 334 335 def AddCommands(self, feature_name, annotation): 336 xpath = ".//feature[@name='%s']//command" % feature_name 337 commands = [cmd.attrib['name'] for cmd in self.root.findall(xpath)] 338 339 # Remove commands that have already been processed 340 current_cmds = self.all_cmd_names.get_all_commands() 341 commands = [cmd for cmd in commands if cmd not in current_cmds] 342 343 self.all_cmd_names.add_commands(annotation, commands) 344 self.commands[annotation] = commands 345 346 def _ClassifySupport(self, supported): 347 if 'gles2' in supported: 348 return 'gl2ext' 349 elif 'gles1' in supported: 350 return 'glext' 351 elif 'egl' in supported: 352 return 'eglext' 353 elif 'wgl' in supported: 354 return 'wglext' 355 elif 'cl' in supported: 356 return 'clext' 357 else: 358 assert False 359 return 'unknown' 360 361 def AddExtensionCommands(self, supported_extensions, apis): 362 # Use a first step to run through the extensions so we can generate them 363 # in sorted order. 364 self.ext_data = {} 365 self.ext_dupes = {} 366 ext_annotations = {} 367 368 for extension in self.root.findall("extensions/extension"): 369 extension_name = extension.attrib['name'] 370 if not extension_name in supported_extensions: 371 continue 372 373 ext_annotations[extension_name] = self._ClassifySupport(extension.attrib['supported']) 374 375 ext_cmd_names = [] 376 377 # There's an extra step here to filter out 'api=gl' extensions. This 378 # is necessary for handling KHR extensions, which have separate entry 379 # point signatures (without the suffix) for desktop GL. Note that this 380 # extra step is necessary because of Etree's limited Xpath support. 381 for require in extension.findall('require'): 382 if 'api' in require.attrib and require.attrib['api'] not in apis: 383 continue 384 385 # A special case for EXT_texture_storage 386 filter_out_comment = "Supported only if GL_EXT_direct_state_access is supported" 387 if 'comment' in require.attrib and require.attrib['comment'] == filter_out_comment: 388 continue 389 390 extension_commands = require.findall('command') 391 ext_cmd_names += [command.attrib['name'] for command in extension_commands] 392 393 self.ext_data[extension_name] = sorted(ext_cmd_names) 394 395 for extension_name, ext_cmd_names in sorted(self.ext_data.items()): 396 397 # Detect and filter duplicate extensions. 398 dupes = [] 399 for ext_cmd in ext_cmd_names: 400 if ext_cmd in self.all_cmd_names.get_all_commands(): 401 dupes.append(ext_cmd) 402 403 for dupe in dupes: 404 ext_cmd_names.remove(dupe) 405 406 self.ext_data[extension_name] = sorted(ext_cmd_names) 407 self.ext_dupes[extension_name] = dupes 408 self.all_cmd_names.add_commands(ext_annotations[extension_name], ext_cmd_names) 409 410 411class EntryPoints: 412 413 def __init__(self, api, xml, commands): 414 self.api = api 415 self._cmd_info = [] 416 417 for command_node in xml.all_commands: 418 cmd_name = get_cmd_name(command_node) 419 420 if api == apis.WGL: 421 cmd_name = cmd_name if cmd_name[:3] == 'wgl' else 'wgl' + cmd_name 422 423 if cmd_name not in commands: 424 continue 425 426 param_text = ["".join(param.itertext()) for param in command_node.findall('param')] 427 428 # Treat (void) as () 429 if len(param_text) == 1 and param_text[0].strip() == 'void': 430 param_text = [] 431 432 proto = command_node.find('proto') 433 proto_text = "".join(proto.itertext()) 434 435 self._cmd_info.append((cmd_name, command_node, param_text, proto_text)) 436 437 def get_infos(self): 438 return self._cmd_info 439