| #!/usr/bin/python3 | |
| # | |
| # Copyright 2018 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. | |
| # | |
| # registry_xml.py: | |
| # Parses information from Khronos registry files.. | |
| # List of supported extensions. Add to this list to enable new extensions | |
| # available in gl.xml. | |
| import difflib | |
| import os | |
| import re | |
| import sys | |
| import xml.etree.ElementTree as etree | |
| from enum import Enum | |
| khronos_xml_inputs = [ | |
| '../third_party/EGL-Registry/src/api/egl.xml', | |
| '../third_party/OpenCL-Docs/src/xml/cl.xml', | |
| '../third_party/OpenGL-Registry/src/xml/gl.xml', | |
| '../third_party/OpenGL-Registry/src/xml/glx.xml', | |
| '../third_party/OpenGL-Registry/src/xml/wgl.xml', | |
| ] | |
| angle_xml_inputs = [ | |
| 'gl_angle_ext.xml', | |
| 'egl_angle_ext.xml', | |
| 'registry_xml.py', | |
| ] | |
| xml_inputs = sorted(khronos_xml_inputs + angle_xml_inputs) | |
| # Notes on categories of extensions: | |
| # 'Requestable' extensions are extensions that can be enabled with ANGLE_request_extension | |
| # 'ES-Only' extensions are always implicitly enabled. | |
| # 'ANGLE' extensions are extensions that are not yet officially upstreamed to Khronos. | |
| # We document those extensions in gl_angle_ext.xml instead of the canonical gl.xml. | |
| angle_requestable_extensions = [ | |
| "GL_ANGLE_base_vertex_base_instance", | |
| "GL_ANGLE_base_vertex_base_instance_shader_builtin", | |
| "GL_ANGLE_blob_cache", | |
| "GL_ANGLE_clip_cull_distance", | |
| "GL_ANGLE_compressed_texture_etc", | |
| "GL_ANGLE_copy_texture_3d", | |
| "GL_ANGLE_framebuffer_multisample", | |
| "GL_ANGLE_get_image", | |
| "GL_ANGLE_get_tex_level_parameter", | |
| "GL_ANGLE_logic_op", | |
| "GL_ANGLE_memory_object_flags", | |
| "GL_ANGLE_memory_object_fuchsia", | |
| "GL_ANGLE_memory_size", | |
| "GL_ANGLE_multi_draw", | |
| "GL_ANGLE_multiview_multisample", | |
| "GL_ANGLE_polygon_mode", | |
| "GL_ANGLE_provoking_vertex", | |
| "GL_ANGLE_read_only_depth_stencil_feedback_loops", | |
| "GL_ANGLE_renderability_validation", | |
| "GL_ANGLE_robust_fragment_shader_output", | |
| "GL_ANGLE_semaphore_fuchsia", | |
| "GL_ANGLE_shader_pixel_local_storage", | |
| "GL_ANGLE_shader_pixel_local_storage_coherent", | |
| "GL_ANGLE_stencil_texturing", | |
| "GL_ANGLE_texture_compression_dxt3", | |
| "GL_ANGLE_texture_compression_dxt5", | |
| "GL_ANGLE_texture_multisample", | |
| "GL_ANGLE_texture_rectangle", | |
| "GL_ANGLE_trim_memory", | |
| "GL_ANGLE_vulkan_image", | |
| "GL_ANGLE_yuv_internal_format", | |
| "GL_CHROMIUM_color_buffer_float_rgb", | |
| "GL_CHROMIUM_color_buffer_float_rgba", | |
| "GL_CHROMIUM_lose_context", | |
| ] | |
| gles_requestable_extensions = [ | |
| "GL_ANGLE_framebuffer_blit", | |
| "GL_ANGLE_instanced_arrays", | |
| "GL_ANGLE_pack_reverse_row_order", | |
| "GL_ANGLE_texture_usage", | |
| "GL_APPLE_clip_distance", | |
| "GL_ARM_rgba8", | |
| "GL_ARM_shader_framebuffer_fetch", | |
| "GL_ARM_shader_framebuffer_fetch_depth_stencil", | |
| "GL_ARM_texture_unnormalized_coordinates", | |
| "GL_EXT_base_instance", | |
| "GL_EXT_blend_func_extended", | |
| "GL_EXT_blend_minmax", | |
| "GL_EXT_buffer_storage", | |
| "GL_EXT_clear_texture", | |
| "GL_EXT_clip_control", | |
| "GL_EXT_clip_cull_distance", | |
| "GL_EXT_color_buffer_float", | |
| "GL_EXT_color_buffer_half_float", | |
| "GL_EXT_compressed_ETC1_RGB8_sub_texture", | |
| "GL_EXT_conservative_depth", | |
| "GL_EXT_copy_image", | |
| "GL_EXT_depth_clamp", | |
| "GL_EXT_disjoint_timer_query", | |
| "GL_EXT_draw_buffers", | |
| "GL_EXT_draw_buffers_indexed", | |
| "GL_EXT_draw_elements_base_vertex", | |
| "GL_EXT_draw_instanced", | |
| "GL_EXT_EGL_image_array", | |
| "GL_EXT_EGL_image_external_wrap_modes", | |
| "GL_EXT_EGL_image_storage", | |
| "GL_EXT_EGL_image_storage_compression", | |
| "GL_EXT_external_buffer", | |
| "GL_EXT_float_blend", | |
| "GL_EXT_frag_depth", | |
| "GL_EXT_fragment_shading_rate", | |
| "GL_EXT_fragment_shading_rate_attachment", | |
| "GL_EXT_fragment_shading_rate_primitive", | |
| "GL_EXT_geometry_shader", | |
| "GL_EXT_gpu_shader5", | |
| "GL_EXT_instanced_arrays", | |
| "GL_EXT_map_buffer_range", | |
| "GL_EXT_memory_object", | |
| "GL_EXT_memory_object_fd", | |
| "GL_EXT_multi_draw_arrays", | |
| "GL_EXT_multi_draw_indirect", | |
| "GL_EXT_multisampled_render_to_texture", | |
| "GL_EXT_multisampled_render_to_texture2", | |
| "GL_EXT_occlusion_query_boolean", | |
| "GL_EXT_polygon_offset_clamp", | |
| "GL_EXT_primitive_bounding_box", | |
| "GL_EXT_protected_textures", | |
| "GL_EXT_pvrtc_sRGB", | |
| "GL_EXT_read_format_bgra", | |
| "GL_EXT_render_snorm", | |
| "GL_EXT_semaphore", | |
| "GL_EXT_semaphore_fd", | |
| "GL_EXT_separate_depth_stencil", | |
| "GL_EXT_separate_shader_objects", | |
| "GL_EXT_shader_framebuffer_fetch", | |
| "GL_EXT_shader_framebuffer_fetch_non_coherent", | |
| "GL_EXT_shader_io_blocks", | |
| "GL_EXT_shader_non_constant_global_initializers", | |
| "GL_EXT_shader_texture_lod", | |
| "GL_EXT_shader_texture_samples", | |
| "GL_EXT_shadow_samplers", | |
| "GL_EXT_sRGB", | |
| "GL_EXT_sRGB_write_control", | |
| "GL_EXT_tessellation_shader", | |
| "GL_EXT_texture_border_clamp", | |
| "GL_EXT_texture_buffer", | |
| "GL_EXT_texture_compression_astc_decode_mode", | |
| "GL_EXT_texture_compression_astc_decode_mode_rgb9e5", | |
| "GL_EXT_texture_compression_bptc", | |
| "GL_EXT_texture_compression_dxt1", | |
| "GL_EXT_texture_compression_rgtc", | |
| "GL_EXT_texture_compression_s3tc", | |
| "GL_EXT_texture_compression_s3tc_srgb", | |
| "GL_EXT_texture_cube_map_array", | |
| "GL_EXT_texture_filter_anisotropic", | |
| "GL_EXT_texture_filter_minmax", | |
| "GL_EXT_texture_format_BGRA8888", | |
| "GL_EXT_texture_format_sRGB_override", | |
| "GL_EXT_texture_mirror_clamp_to_edge", | |
| "GL_EXT_texture_norm16", | |
| "GL_EXT_texture_query_lod", | |
| "GL_EXT_texture_rg", | |
| "GL_EXT_texture_shadow_lod", | |
| "GL_EXT_texture_sRGB_decode", | |
| "GL_EXT_texture_sRGB_R8", | |
| "GL_EXT_texture_sRGB_RG8", | |
| "GL_EXT_texture_storage", | |
| "GL_EXT_texture_storage_compression", | |
| "GL_EXT_texture_type_2_10_10_10_REV", | |
| "GL_EXT_unpack_subimage", | |
| "GL_EXT_YUV_target", | |
| "GL_IMG_texture_compression_pvrtc", | |
| "GL_IMG_texture_compression_pvrtc2", | |
| "GL_KHR_blend_equation_advanced", | |
| "GL_KHR_blend_equation_advanced_coherent", | |
| "GL_KHR_parallel_shader_compile", | |
| "GL_KHR_texture_compression_astc_hdr", | |
| "GL_KHR_texture_compression_astc_ldr", | |
| "GL_KHR_texture_compression_astc_sliced_3d", | |
| "GL_MESA_framebuffer_flip_y", | |
| "GL_NV_EGL_stream_consumer_external", | |
| "GL_NV_framebuffer_blit", | |
| "GL_NV_pack_subimage", | |
| "GL_NV_pixel_buffer_object", | |
| "GL_NV_polygon_mode", | |
| "GL_NV_read_depth", | |
| "GL_NV_read_depth_stencil", | |
| "GL_NV_read_stencil", | |
| "GL_NV_shader_noperspective_interpolation", | |
| "GL_OES_compressed_ETC1_RGB8_texture", | |
| "GL_OES_compressed_paletted_texture", | |
| "GL_OES_copy_image", | |
| "GL_OES_depth_texture_cube_map", | |
| "GL_OES_draw_buffers_indexed", | |
| "GL_OES_draw_elements_base_vertex", | |
| "GL_OES_EGL_image", | |
| "GL_OES_EGL_image_external", | |
| "GL_OES_EGL_image_external_essl3", | |
| "GL_OES_element_index_uint", | |
| "GL_OES_fbo_render_mipmap", | |
| "GL_OES_geometry_shader", | |
| "GL_OES_get_program_binary", | |
| "GL_OES_gpu_shader5", | |
| "GL_OES_mapbuffer", | |
| "GL_OES_primitive_bounding_box", | |
| "GL_OES_required_internalformat", | |
| "GL_OES_rgb8_rgba8", | |
| "GL_OES_sample_shading", | |
| "GL_OES_sample_variables", | |
| "GL_OES_shader_image_atomic", | |
| "GL_OES_shader_io_blocks", | |
| "GL_OES_shader_multisample_interpolation", | |
| "GL_OES_standard_derivatives", | |
| "GL_OES_tessellation_shader", | |
| "GL_OES_texture_3D", | |
| "GL_OES_texture_border_clamp", | |
| "GL_OES_texture_buffer", | |
| "GL_OES_texture_compression_astc", | |
| "GL_OES_texture_cube_map_array", | |
| "GL_OES_texture_float", | |
| "GL_OES_texture_float_linear", | |
| "GL_OES_texture_half_float", | |
| "GL_OES_texture_half_float_linear", | |
| "GL_OES_texture_npot", | |
| "GL_OES_texture_stencil8", | |
| "GL_OES_texture_storage_multisample_2d_array", | |
| "GL_OES_vertex_array_object", | |
| "GL_OES_vertex_half_float", | |
| "GL_OES_vertex_type_10_10_10_2", | |
| "GL_OVR_multiview", | |
| "GL_OVR_multiview2", | |
| "GL_OVR_multiview_multisampled_render_to_texture", | |
| "GL_QCOM_framebuffer_foveated", | |
| "GL_QCOM_render_shared_exponent", | |
| "GL_QCOM_shading_rate", | |
| "GL_QCOM_texture_foveated", | |
| "GL_QCOM_texture_lod_bias", | |
| "GL_QCOM_tiled_rendering", | |
| ] | |
| angle_es_only_extensions = [ | |
| "GL_ANGLE_client_arrays", | |
| "GL_ANGLE_explicit_context", | |
| "GL_ANGLE_get_serialized_context_string", | |
| "GL_ANGLE_program_binary", | |
| "GL_ANGLE_program_binary_readiness_query", | |
| "GL_ANGLE_program_cache_control", | |
| "GL_ANGLE_relaxed_vertex_attribute_type", | |
| "GL_ANGLE_request_extension", | |
| "GL_ANGLE_rgbx_internal_format", | |
| "GL_ANGLE_robust_client_memory", | |
| "GL_ANGLE_robust_resource_initialization", | |
| "GL_ANGLE_shader_binary", | |
| "GL_ANGLE_webgl_compatibility", | |
| "GL_CHROMIUM_bind_generates_resource", | |
| "GL_CHROMIUM_bind_uniform_location", | |
| "GL_CHROMIUM_copy_compressed_texture", | |
| "GL_CHROMIUM_copy_texture", | |
| ] | |
| gles_es_only_extensions = [ | |
| "GL_AMD_performance_monitor", | |
| "GL_ANDROID_extension_pack_es31a", | |
| "GL_ANGLE_depth_texture", | |
| "GL_ANGLE_translated_shader_source", | |
| "GL_EXT_debug_label", | |
| "GL_EXT_debug_marker", | |
| "GL_EXT_discard_framebuffer", | |
| "GL_EXT_multisample_compatibility", | |
| "GL_EXT_robustness", | |
| "GL_KHR_debug", | |
| "GL_KHR_no_error", | |
| "GL_KHR_robust_buffer_access_behavior", | |
| "GL_KHR_robustness", | |
| "GL_NV_fence", | |
| "GL_NV_robustness_video_memory_purge", | |
| "GL_OES_depth24", | |
| "GL_OES_depth32", | |
| "GL_OES_depth_texture", | |
| "GL_OES_EGL_sync", | |
| "GL_OES_packed_depth_stencil", | |
| "GL_OES_surfaceless_context", | |
| ] | |
| # ES1 (Possibly the min set of extensions needed by Android) | |
| gles1_extensions = [ | |
| "GL_EXT_texture_lod_bias", | |
| "GL_OES_blend_subtract", | |
| "GL_OES_draw_texture", | |
| "GL_OES_framebuffer_object", | |
| "GL_OES_matrix_palette", | |
| "GL_OES_point_size_array", | |
| "GL_OES_point_sprite", | |
| "GL_OES_query_matrix", | |
| "GL_OES_stencil8", | |
| "GL_OES_texture_cube_map", | |
| "GL_OES_texture_mirrored_repeat", | |
| ] | |
| # Unsupported entry points that require explicit exclusion | |
| # because XML registry does not contain enough information. | |
| gles_skipped_commands = [ | |
| # GL_EXT_EGL_image_storage | |
| "glEGLImageTargetTextureStorageEXT", | |
| # GL_EXT_external_buffer | |
| "glNamedBufferStorageExternalEXT", | |
| # GL_EXT_memory_object | |
| "glTextureStorageMem2DEXT", | |
| "glTextureStorageMem2DMultisampleEXT", | |
| "glTextureStorageMem3DEXT", | |
| "glTextureStorageMem3DMultisampleEXT", | |
| "glNamedBufferStorageMemEXT", | |
| # GL_EXT_texture_storage | |
| "glTexStorage1DEXT", | |
| "glTextureStorage1DEXT", | |
| "glTextureStorage2DEXT", | |
| "glTextureStorage3DEXT", | |
| # GL_OVR_multiview | |
| "glNamedFramebufferTextureMultiviewOVR", | |
| ] | |
| def check_sorted(name, l): | |
| unidiff = difflib.unified_diff(l, sorted(l, key=str.casefold), 'unsorted', 'sorted') | |
| diff_lines = list(unidiff) | |
| assert not diff_lines, '\n\nPlease sort "%s":\n%s' % (name, '\n'.join(diff_lines)) | |
| angle_extensions = angle_requestable_extensions + angle_es_only_extensions | |
| gles_extensions = gles_requestable_extensions + gles_es_only_extensions | |
| supported_extensions = sorted(angle_extensions + gles1_extensions + gles_extensions) | |
| assert len(supported_extensions) == len(set(supported_extensions)), 'Duplicates in extension list' | |
| check_sorted('angle_requestable_extensions', angle_requestable_extensions) | |
| check_sorted('angle_es_only_extensions', angle_es_only_extensions) | |
| check_sorted('gles_requestable_extensions', gles_requestable_extensions) | |
| check_sorted('gles_es_only_extensions', gles_es_only_extensions) | |
| check_sorted('gles_extensions', gles1_extensions) | |
| supported_egl_extensions = [ | |
| "EGL_ANDROID_blob_cache", | |
| "EGL_ANDROID_create_native_client_buffer", | |
| "EGL_ANDROID_framebuffer_target", | |
| "EGL_ANDROID_get_frame_timestamps", | |
| "EGL_ANDROID_get_native_client_buffer", | |
| "EGL_ANDROID_native_fence_sync", | |
| "EGL_ANDROID_presentation_time", | |
| "EGL_ANGLE_create_surface_swap_interval", | |
| "EGL_ANGLE_d3d_share_handle_client_buffer", | |
| "EGL_ANGLE_device_creation", | |
| "EGL_ANGLE_device_d3d", | |
| "EGL_ANGLE_device_d3d11", | |
| "EGL_ANGLE_device_vulkan", | |
| "EGL_ANGLE_display_semaphore_share_group", | |
| "EGL_ANGLE_display_texture_share_group", | |
| "EGL_ANGLE_external_context_and_surface", | |
| "EGL_ANGLE_feature_control", | |
| "EGL_ANGLE_memory_usage_report", | |
| "EGL_ANGLE_metal_create_context_ownership_identity", | |
| "EGL_ANGLE_metal_shared_event_sync", | |
| "EGL_ANGLE_no_error", | |
| "EGL_ANGLE_power_preference", | |
| "EGL_ANGLE_prepare_swap_buffers", | |
| "EGL_ANGLE_program_cache_control", | |
| "EGL_ANGLE_query_renderer_strings", | |
| "EGL_ANGLE_query_surface_pointer", | |
| "EGL_ANGLE_stream_producer_d3d_texture", | |
| "EGL_ANGLE_surface_d3d_texture_2d_share_handle", | |
| "EGL_ANGLE_sync_control_rate", | |
| "EGL_ANGLE_vulkan_image", | |
| "EGL_ANGLE_wait_until_work_scheduled", | |
| "EGL_ANGLE_window_fixed_size", | |
| "EGL_CHROMIUM_sync_control", | |
| "EGL_EXT_create_context_robustness", | |
| "EGL_EXT_device_query", | |
| "EGL_EXT_gl_colorspace_bt2020_hlg", | |
| "EGL_EXT_gl_colorspace_bt2020_linear", | |
| "EGL_EXT_gl_colorspace_bt2020_pq", | |
| "EGL_EXT_gl_colorspace_display_p3", | |
| "EGL_EXT_gl_colorspace_display_p3_linear", | |
| "EGL_EXT_gl_colorspace_display_p3_passthrough", | |
| "EGL_EXT_gl_colorspace_scrgb", | |
| "EGL_EXT_gl_colorspace_scrgb_linear", | |
| "EGL_EXT_image_dma_buf_import", | |
| "EGL_EXT_image_dma_buf_import_modifiers", | |
| "EGL_EXT_image_gl_colorspace", | |
| "EGL_EXT_pixel_format_float", | |
| "EGL_EXT_platform_base", | |
| "EGL_EXT_platform_device", | |
| "EGL_EXT_protected_content", | |
| "EGL_EXT_surface_compression", | |
| "EGL_IMG_context_priority", | |
| "EGL_KHR_debug", | |
| "EGL_KHR_fence_sync", | |
| "EGL_KHR_gl_colorspace", | |
| "EGL_KHR_image", | |
| "EGL_KHR_lock_surface3", | |
| "EGL_KHR_mutable_render_buffer", | |
| "EGL_KHR_no_config_context", | |
| "EGL_KHR_partial_update", | |
| "EGL_KHR_reusable_sync", | |
| "EGL_KHR_stream", | |
| "EGL_KHR_stream_consumer_gltexture", | |
| "EGL_KHR_surfaceless_context", | |
| "EGL_KHR_swap_buffers_with_damage", | |
| "EGL_KHR_wait_sync", | |
| "EGL_NV_context_priority_realtime", | |
| "EGL_NV_post_sub_buffer", | |
| "EGL_NV_stream_consumer_gltexture_yuv", | |
| ] | |
| check_sorted('supported_egl_extensions', supported_egl_extensions) | |
| supported_cl_extensions = [ | |
| # OpenCL 1.0 | |
| "cl_arm_import_memory", | |
| # Since OpenCL 1.1 | |
| "cl_khr_byte_addressable_store", | |
| "cl_khr_global_int32_base_atomics", | |
| "cl_khr_global_int32_extended_atomics", | |
| "cl_khr_local_int32_base_atomics", | |
| "cl_khr_local_int32_extended_atomics", | |
| # OpenCL 2.0 - 2.2 | |
| "cl_khr_3d_image_writes", | |
| "cl_khr_depth_images", | |
| "cl_khr_image2d_from_buffer", | |
| # OpenCL 3.0 | |
| "cl_khr_external_memory", | |
| # Optional | |
| "cl_khr_extended_versioning", | |
| "cl_khr_fp64", | |
| "cl_khr_icd", | |
| "cl_khr_int64_base_atomics", | |
| "cl_khr_int64_extended_atomics", | |
| "cl_khr_priority_hints", | |
| "cl_khr_subgroups", | |
| ] | |
| # Strip these suffixes from Context entry point names. | |
| strip_suffixes = [ | |
| "AMD", "ANDROID", "ANGLE", "CHROMIUM", "EXT", "KHR", "MESA", "NV", "OES", "OVR", "QCOM" | |
| ] | |
| check_sorted('strip_suffixes', strip_suffixes) | |
| # Group names that appear in command/param, but not present in groups/group | |
| unsupported_enum_group_names = { | |
| 'GetMultisamplePNameNV', | |
| 'BufferPNameARB', | |
| 'BufferPointerNameARB', | |
| 'VertexAttribPointerPropertyARB', | |
| 'VertexAttribPropertyARB', | |
| 'FenceParameterNameNV', | |
| 'FenceConditionNV', | |
| 'BufferPointerNameARB', | |
| 'MatrixIndexPointerTypeARB', | |
| 'PointParameterNameARB', | |
| 'ClampColorTargetARB', | |
| 'ClampColorModeARB', | |
| } | |
| # Versions (major, minor). Note that GLES intentionally places 1.0 last. | |
| GLES_VERSIONS = [(2, 0), (3, 0), (3, 1), (3, 2), (1, 0)] | |
| EGL_VERSIONS = [(1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5)] | |
| CL_VERSIONS = [(1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2), (3, 0)] | |
| # API types | |
| class apis: | |
| GL = 'GL' | |
| GLES = 'GLES' | |
| WGL = 'WGL' | |
| GLX = 'GLX' | |
| EGL = 'EGL' | |
| CL = 'CL' | |
| # For GLenum types | |
| api_enums = {apis.GLES: 'GLESEnum'} | |
| default_enum_group_name = 'AllEnums' | |
| def script_relative(path): | |
| return os.path.join(os.path.dirname(sys.argv[0]), path) | |
| def path_to(folder, file): | |
| return os.path.join(script_relative(".."), "src", folder, file) | |
| def strip_api_prefix(cmd_name): | |
| return cmd_name.lstrip("cwegl") | |
| def find_xml_input(xml_file): | |
| for found_xml in xml_inputs: | |
| if found_xml == xml_file or found_xml.endswith('/' + xml_file): | |
| return found_xml | |
| raise Exception('Could not find XML input: ' + xml_file) | |
| def get_cmd_name(command_node): | |
| proto = command_node.find('proto') | |
| cmd_name = proto.find('name').text | |
| return cmd_name | |
| class CommandNames: | |
| def __init__(self): | |
| self.command_names = {} | |
| def get_commands(self, version): | |
| return self.command_names[version] | |
| def get_all_commands(self): | |
| cmd_names = [] | |
| # Combine all the version lists into a single list | |
| for version, version_cmd_names in sorted(self.command_names.items()): | |
| cmd_names += version_cmd_names | |
| return cmd_names | |
| def add_commands(self, version, commands): | |
| # Add key if it doesn't exist | |
| if version not in self.command_names: | |
| self.command_names[version] = [] | |
| # Add the commands that aren't duplicates | |
| self.command_names[version] += commands | |
| class RegistryXML: | |
| def __init__(self, xml_file, ext_file=None): | |
| tree = etree.parse(script_relative(find_xml_input(xml_file))) | |
| self.root = tree.getroot() | |
| if (ext_file): | |
| self._AppendANGLEExts(find_xml_input(ext_file)) | |
| self.all_commands = self.root.findall('commands/command') | |
| self.all_cmd_names = CommandNames() | |
| self.commands = {} | |
| self.sources_by_command = {} | |
| self.sources_by_command_no_suffix = {} | |
| def _AppendANGLEExts(self, ext_file): | |
| angle_ext_tree = etree.parse(script_relative(ext_file)) | |
| angle_ext_root = angle_ext_tree.getroot() | |
| insertion_point = self.root.findall("./types")[0] | |
| for t in angle_ext_root.iter('types'): | |
| insertion_point.extend(t) | |
| insertion_point = self.root.findall("./commands")[0] | |
| for command in angle_ext_root.iter('commands'): | |
| insertion_point.extend(command) | |
| insertion_point = self.root.findall("./extensions")[0] | |
| for extension in angle_ext_root.iter('extensions'): | |
| insertion_point.extend(extension) | |
| insertion_point = self.root | |
| for enums in angle_ext_root.iter('enums'): | |
| insertion_point.append(enums) | |
| def AddCommands(self, feature_name, annotation): | |
| xpath = ".//feature[@name='%s']//command" % feature_name | |
| commands = [cmd.attrib['name'] for cmd in self.root.findall(xpath)] | |
| # Reverse cache for all places a command may be defined in. | |
| for cmd in commands: | |
| self.sources_by_command.setdefault(cmd, []).append(annotation) | |
| self.sources_by_command_no_suffix.setdefault(cmd, []).append(annotation) | |
| # Remove commands that have already been processed | |
| current_cmds = self.all_cmd_names.get_all_commands() | |
| commands = [cmd for cmd in commands if cmd not in current_cmds] | |
| self.all_cmd_names.add_commands(annotation, commands) | |
| self.commands[annotation] = commands | |
| def _ClassifySupport(self, extension): | |
| supported = extension.attrib['supported'] | |
| # Desktop GL extensions exposed in ANGLE GLES for Chrome. | |
| if extension.attrib['name'] in ['GL_NV_robustness_video_memory_purge']: | |
| supported += "|gles2" | |
| if 'gles2' in supported: | |
| return 'gl2ext' | |
| elif 'gles1' in supported: | |
| return 'glext' | |
| elif 'egl' in supported: | |
| return 'eglext' | |
| elif 'wgl' in supported: | |
| return 'wglext' | |
| elif 'glx' in supported: | |
| return 'glxext' | |
| elif 'cl' in supported: | |
| return 'clext' | |
| else: | |
| assert False, 'Cannot classify support for %s: %s' % (extension.attrib['name'], | |
| supported) | |
| return 'unknown' | |
| def AddExtensionCommands(self, supported_extensions, apis): | |
| # Use a first step to run through the extensions so we can generate them | |
| # in sorted order. | |
| self.ext_data = {} | |
| self.ext_dupes = {} | |
| ext_annotations = {} | |
| ext_prefixes = set() | |
| for extension in self.root.findall("extensions/extension"): | |
| extension_name = extension.attrib['name'] | |
| if not extension_name in supported_extensions: | |
| continue | |
| # Extract the extension prefix | |
| if (extension_name.startswith("GL_")): | |
| ext_prefixes.add(re.match(r"^GL_([A-Z]+)_", extension_name).group(1)) | |
| ext_annotations[extension_name] = self._ClassifySupport(extension) | |
| ext_cmd_names = [] | |
| # There's an extra step here to filter out 'api=gl' extensions. This | |
| # is necessary for handling KHR extensions, which have separate entry | |
| # point signatures (without the suffix) for desktop GL. Note that this | |
| # extra step is necessary because of Etree's limited Xpath support. | |
| for require in extension.findall('require'): | |
| if 'api' in require.attrib and require.attrib['api'] not in apis: | |
| continue | |
| ext_cmd_names += [ | |
| command.attrib['name'] | |
| for command in require.findall('command') | |
| if command.attrib['name'] not in gles_skipped_commands | |
| ] | |
| self.ext_data[extension_name] = sorted(ext_cmd_names) | |
| for extension_name, ext_cmd_names in sorted(self.ext_data.items()): | |
| # Reverse cache for all places a command may be defined in. | |
| for cmd in ext_cmd_names: | |
| self.sources_by_command.setdefault(cmd, []).append(extension_name) | |
| for prefix in ext_prefixes: | |
| if cmd.endswith(prefix): | |
| self.sources_by_command_no_suffix.setdefault(cmd[:-len(prefix)], | |
| []).append(extension_name) | |
| break | |
| # Detect and filter duplicate extensions. | |
| dupes = [] | |
| for ext_cmd in ext_cmd_names: | |
| if ext_cmd in self.all_cmd_names.get_all_commands(): | |
| dupes.append(ext_cmd) | |
| for dupe in dupes: | |
| ext_cmd_names.remove(dupe) | |
| self.ext_data[extension_name] = sorted(ext_cmd_names) | |
| self.ext_dupes[extension_name] = dupes | |
| self.all_cmd_names.add_commands(ext_annotations[extension_name], ext_cmd_names) | |
| def GetEnums(self, override_prefix=None): | |
| cmd_names = [] | |
| for cmd in self.all_cmd_names.get_all_commands(): | |
| stripped = strip_api_prefix(cmd) | |
| prefix = override_prefix or cmd[:(len(cmd) - len(stripped))] | |
| cmd_names.append( | |
| ('%s%s' % (prefix.upper(), stripped), '%s%s' % (prefix.lower(), stripped))) | |
| return cmd_names | |
| class EntryPoints: | |
| def __init__(self, api, xml, commands): | |
| self.api = api | |
| self._cmd_info = [] | |
| for command_node in xml.all_commands: | |
| cmd_name = get_cmd_name(command_node) | |
| if api == apis.WGL: | |
| cmd_name = cmd_name if cmd_name.startswith('wgl') else 'wgl' + cmd_name | |
| if cmd_name not in commands: | |
| continue | |
| param_text = ["".join(param.itertext()) for param in command_node.findall('param')] | |
| # Treat (void) as () | |
| if len(param_text) == 1 and param_text[0].strip() == 'void': | |
| param_text = [] | |
| proto = command_node.find('proto') | |
| proto_text = "".join(proto.itertext()) | |
| self._cmd_info.append((cmd_name, command_node, param_text, proto_text)) | |
| def get_infos(self): | |
| return self._cmd_info | |
| def GetEGL(): | |
| egl = RegistryXML('egl.xml', 'egl_angle_ext.xml') | |
| for major_version, minor_version in EGL_VERSIONS: | |
| version = "%d_%d" % (major_version, minor_version) | |
| name_prefix = "EGL_VERSION_" | |
| feature_name = "%s%s" % (name_prefix, version) | |
| egl.AddCommands(feature_name, version) | |
| egl.AddExtensionCommands(supported_egl_extensions, ['egl']) | |
| return egl | |
| def GetGLES(): | |
| gles = RegistryXML('gl.xml', 'gl_angle_ext.xml') | |
| for major_version, minor_version in GLES_VERSIONS: | |
| version = "{}_{}".format(major_version, minor_version) | |
| name_prefix = "GL_ES_VERSION_" | |
| if major_version == 1: | |
| name_prefix = "GL_VERSION_ES_CM_" | |
| feature_name = "{}{}".format(name_prefix, version) | |
| gles.AddCommands(feature_name, version) | |
| gles.AddExtensionCommands(supported_extensions, ['gles2', 'gles1']) | |
| return gles |