#!/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_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_multi_draw",
    "GL_ANGLE_provoking_vertex",
    "GL_ANGLE_texture_multisample",
    "GL_ANGLE_translated_shader_source",
    "GL_EXT_blend_func_extended",
    "GL_EXT_debug_marker",
    "GL_EXT_discard_framebuffer",
    "GL_EXT_disjoint_timer_query",
    "GL_EXT_draw_buffers",
    "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_occlusion_query_boolean",
    "GL_EXT_robustness",
    "GL_EXT_semaphore",
    "GL_EXT_semaphore_fd",
    "GL_EXT_texture_filter_anisotropic",
    "GL_EXT_texture_storage",
    "GL_KHR_debug",
    "GL_KHR_parallel_shader_compile",
    "GL_NV_fence",
    "GL_OES_EGL_image",
    "GL_OES_get_program_binary",
    "GL_OES_mapbuffer",
    "GL_OES_texture_3D",
    "GL_OES_texture_border_clamp",
    "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_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_feature_control",
    "EGL_ANGLE_ggp_stream_descriptor",
    "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_get_sync_values",
    "EGL_EXT_create_context_robustness",
    "EGL_EXT_device_query",
    "EGL_EXT_platform_base",
    "EGL_EXT_platform_device",
    "EGL_KHR_debug",
    "EGL_KHR_fence_sync",
    "EGL_KHR_image",
    "EGL_KHR_no_config_context",
    "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)

    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)
