#!/usr/bin/python2
#
# 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 sys
import os
import xml.etree.ElementTree as etree

xml_inputs = [
    'gl.xml',
    'gl_angle_ext.xml',
    'egl.xml',
    'egl_angle_ext.xml',
    'wgl.xml',
    'registry_xml.py',
]

angle_extensions = [
    # ANGLE extensions
    "GL_CHROMIUM_bind_uniform_location",
    "GL_CHROMIUM_framebuffer_mixed_samples",
    "GL_CHROMIUM_path_rendering",
    "GL_CHROMIUM_copy_texture",
    "GL_CHROMIUM_copy_compressed_texture",
    "GL_CHROMIUM_lose_context",
    "GL_ANGLE_copy_texture_3d",
    "GL_ANGLE_get_image",
    "GL_ANGLE_get_tex_level_parameter",
    "GL_ANGLE_program_binary",
    "GL_ANGLE_request_extension",
    "GL_ANGLE_robust_client_memory",
    "GL_ANGLE_texture_external_update",
]

gles1_extensions = [
    # ES1 (Possibly the min set of extensions needed by Android)
    "GL_OES_draw_texture",
    "GL_OES_framebuffer_object",
    "GL_OES_matrix_palette",
    "GL_OES_point_size_array",
    "GL_OES_query_matrix",
    "GL_OES_texture_cube_map",
]

gles_extensions = [
    # ES2+
    "GL_ANGLE_base_vertex_base_instance",
    "GL_ANGLE_framebuffer_blit",
    "GL_ANGLE_framebuffer_multisample",
    "GL_ANGLE_instanced_arrays",
    "GL_ANGLE_memory_object_flags",
    "GL_ANGLE_memory_object_fuchsia",
    "GL_ANGLE_multi_draw",
    "GL_ANGLE_provoking_vertex",
    "GL_ANGLE_semaphore_fuchsia",
    "GL_ANGLE_texture_multisample",
    "GL_ANGLE_translated_shader_source",
    "GL_EXT_blend_func_extended",
    "GL_EXT_buffer_storage",
    "GL_EXT_copy_image",
    "GL_EXT_debug_marker",
    "GL_EXT_discard_framebuffer",
    "GL_EXT_disjoint_timer_query",
    "GL_EXT_draw_buffers",
    "GL_EXT_draw_buffers_indexed",
    "GL_EXT_draw_elements_base_vertex",
    "GL_EXT_EGL_image_array",
    "GL_EXT_external_buffer",
    "GL_EXT_geometry_shader",
    "GL_EXT_instanced_arrays",
    "GL_EXT_map_buffer_range",
    "GL_EXT_memory_object",
    "GL_EXT_memory_object_fd",
    "GL_EXT_multisampled_render_to_texture",
    "GL_EXT_multisampled_render_to_texture2",
    "GL_EXT_occlusion_query_boolean",
    "GL_EXT_read_format_bgra",
    "GL_EXT_robustness",
    "GL_EXT_semaphore",
    "GL_EXT_semaphore_fd",
    "GL_EXT_sRGB",
    "GL_EXT_texture_buffer",
    "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_format_BGRA8888",
    "GL_EXT_texture_storage",
    "GL_EXT_texture_sRGB_R8",
    "GL_KHR_debug",
    "GL_KHR_parallel_shader_compile",
    "GL_NV_fence",
    "GL_OES_compressed_ETC1_RGB8_texture",
    "GL_EXT_compressed_ETC1_RGB8_sub_texture",
    "GL_OES_copy_image",
    "GL_OES_depth32",
    "GL_OES_draw_buffers_indexed",
    "GL_OES_draw_elements_base_vertex",
    "GL_OES_EGL_image",
    "GL_OES_get_program_binary",
    "GL_OES_mapbuffer",
    "GL_OES_sample_shading",
    "GL_OES_texture_3D",
    "GL_OES_texture_border_clamp",
    "GL_OES_texture_buffer",
    "GL_OES_texture_cube_map_array",
    "GL_OES_texture_half_float",
    "GL_OES_texture_stencil8",
    "GL_OES_texture_storage_multisample_2d_array",
    "GL_OES_vertex_array_object",
    "GL_OVR_multiview",
    "GL_OVR_multiview2",
]

supported_extensions = sorted(angle_extensions + gles1_extensions + gles_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_d3d_share_handle_client_buffer",
    "EGL_ANGLE_device_creation",
    "EGL_ANGLE_device_d3d",
    "EGL_ANGLE_display_semaphore_share_group",
    "EGL_ANGLE_display_texture_share_group",
    "EGL_ANGLE_feature_control",
    "EGL_ANGLE_ggp_stream_descriptor",
    "EGL_ANGLE_power_preference",
    "EGL_ANGLE_program_cache_control",
    "EGL_ANGLE_query_surface_pointer",
    "EGL_ANGLE_stream_producer_d3d_texture",
    "EGL_ANGLE_surface_d3d_texture_2d_share_handle",
    "EGL_ANGLE_swap_with_frame_token",
    "EGL_ANGLE_window_fixed_size",
    "EGL_CHROMIUM_sync_control",
    "EGL_ANGLE_sync_control_rate",
    "EGL_EXT_create_context_robustness",
    "EGL_EXT_device_query",
    "EGL_EXT_image_gl_colorspace",
    "EGL_EXT_pixel_format_float",
    "EGL_EXT_platform_base",
    "EGL_EXT_platform_device",
    "EGL_IMG_context_priority",
    "EGL_KHR_debug",
    "EGL_KHR_fence_sync",
    "EGL_KHR_gl_colorspace",
    "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_KHR_image",
    "EGL_KHR_no_config_context",
    "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_post_sub_buffer",
    "EGL_NV_stream_consumer_gltexture_yuv",
]

# Strip these suffixes from Context entry point names. NV is excluded (for now).
strip_suffixes = ["ANGLE", "EXT", "KHR", "OES", "CHROMIUM"]

# The EGL_ANGLE_explicit_context extension is generated differently from other extensions.
# Toggle generation here.
support_EGL_ANGLE_explicit_context = True

# For ungrouped GLenum types
default_enum_group_name = "DefaultGroup"

# 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',
}


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)


class GLCommandNames:

    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.iteritems()):
            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(xml_file))
        self.root = tree.getroot()
        if (ext_file):
            self._AppendANGLEExts(ext_file)
        self.all_commands = self.root.findall('commands/command')
        self.all_cmd_names = GLCommandNames()
        self.commands = {}

    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("./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)]

        # 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, supported):
        if 'gles2' in supported:
            return 'gl2ext'
        elif 'gles1' in supported:
            return 'glext'
        elif 'egl' in supported:
            return 'eglext'
        elif 'wgl' in supported:
            return 'wglext'
        else:
            assert False
            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 = {}

        for extension in self.root.findall("extensions/extension"):
            extension_name = extension.attrib['name']
            if not extension_name in supported_extensions:
                continue

            ext_annotations[extension_name] = self._ClassifySupport(extension.attrib['supported'])

            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

                # A special case for EXT_texture_storage
                filter_out_comment = "Supported only if GL_EXT_direct_state_access is supported"
                if 'comment' in require.attrib and require.attrib['comment'] == filter_out_comment:
                    continue

                extension_commands = require.findall('command')
                ext_cmd_names += [command.attrib['name'] for command in extension_commands]

            self.ext_data[extension_name] = sorted(ext_cmd_names)

        for extension_name, ext_cmd_names in sorted(self.ext_data.iteritems()):

            # 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)
