#!python
# Copyright 2017 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.
#
# gen_proc_table.py:
#  Code generation for entry point loading tables.
#  NOTE: don't run this script directly. Run scripts/run_code_generation.py.

import sys
from datetime import date
import registry_xml

out_file_name_gles = "../src/libGLESv2/proc_table_egl_autogen.cpp"
out_file_name_gl = "../src/libGL/proc_table_wgl_autogen.cpp"

# The EGL_ANGLE_explicit_context extension is generated differently from other extensions.
# Toggle generation here.
# Only for GLES
support_egl_ANGLE_explicit_context = True

strip_suffixes = ["ANGLE", "EXT", "KHR", "OES", "CHROMIUM", "OVR"]

template_cpp = """// GENERATED FILE - DO NOT EDIT.
// Generated by {script_name} using data from {data_source_name}.
//
// Copyright {copyright_year} 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.
//
// getProcAddress loader table:
//   Mapping from a string entry point name to function address.
//

{includes}
#define P(FUNC) reinterpret_cast<{cast}>(FUNC)

namespace {namespace}
{{
ProcEntry g_procTable[] = {{
{proc_data}
}};

size_t g_numProcs = {num_procs};
}}  // namespace {namespace}
"""

includes_gles = """#include "libGLESv2/proc_table_egl.h"

#include "libGLESv2/entry_points_egl.h"
#include "libGLESv2/entry_points_egl_ext.h"
#include "libGLESv2/entry_points_gles_1_0_autogen.h"
#include "libGLESv2/entry_points_gles_2_0_autogen.h"
#include "libGLESv2/entry_points_gles_3_0_autogen.h"
#include "libGLESv2/entry_points_gles_3_1_autogen.h"
#include "libGLESv2/entry_points_gles_ext_autogen.h"
#include "platform/Platform.h"
"""

includes_gl = """#include "libGL/proc_table_wgl.h"

#include "libGL/entry_points_wgl.h"
#include "libGL/entry_points_gl_1_0_autogen.h"
#include "libGL/entry_points_gl_1_1_autogen.h"
#include "libGL/entry_points_gl_1_2_autogen.h"
#include "libGL/entry_points_gl_1_3_autogen.h"
#include "libGL/entry_points_gl_1_4_autogen.h"
#include "libGL/entry_points_gl_1_5_autogen.h"
#include "libGL/entry_points_gl_2_0_autogen.h"
#include "libGL/entry_points_gl_2_1_autogen.h"
#include "libGL/entry_points_gl_3_0_autogen.h"
#include "libGL/entry_points_gl_3_1_autogen.h"
#include "libGL/entry_points_gl_3_2_autogen.h"
#include "libGL/entry_points_gl_3_3_autogen.h"
#include "libGL/entry_points_gl_4_0_autogen.h"
#include "libGL/entry_points_gl_4_1_autogen.h"
#include "libGL/entry_points_gl_4_2_autogen.h"
#include "libGL/entry_points_gl_4_3_autogen.h"
#include "libGL/entry_points_gl_4_4_autogen.h"
#include "libGL/entry_points_gl_4_5_autogen.h"
#include "libGL/entry_points_gl_4_6_autogen.h"
#include "platform/Platform.h"
"""

sys.path.append('../src/libANGLE/renderer')
import angle_format


def main():

    # auto_script parameters.
    if len(sys.argv) > 1:
        inputs = [source for source in registry_xml.xml_inputs]
        outputs = [out_file_name_gles, out_file_name_gl]
        if sys.argv[1] == 'inputs':
            print ','.join(inputs)
        elif sys.argv[1] == 'outputs':
            print ','.join(outputs)
        else:
            print('Invalid script parameters')
            return 1
        return 0

    glesxml = registry_xml.RegistryXML('gl.xml', 'gl_angle_ext.xml')

    for annotation in ["2_0", "3_0", "3_1", "1_0"]:

        name_prefix = "GL_ES_VERSION_"
        if annotation[0] == '1':
            name_prefix = "GL_VERSION_ES_CM_"
        feature_name = "{}{}".format(name_prefix, annotation)
        glesxml.AddCommands(feature_name, annotation)

    glesxml.AddExtensionCommands(registry_xml.supported_extensions, ['gles2', 'gles1'])

    # Also don't add GLES extension commands to libGL proc table
    extension_commands = []
    for extension_name, ext_cmd_names in sorted(glesxml.ext_data.iteritems()):
        extension_commands.extend(glesxml.ext_data[extension_name])
    for name in extension_commands:
        name_no_suffix = name
        for suffix in strip_suffixes:
            if name_no_suffix.endswith(suffix):
                name_no_suffix = name_no_suffix[0:-len(suffix)]

    gles_data = glesxml.all_cmd_names.get_all_commands()

    eglxml = registry_xml.RegistryXML('egl.xml', 'egl_angle_ext.xml')

    for annotation in ["1_0", "1_1", "1_2", "1_3", "1_4", "1_5"]:

        name_prefix = "EGL_VERSION_"
        feature_name = "{}{}".format(name_prefix, annotation)
        eglxml.AddCommands(feature_name, annotation)

    eglxml.AddExtensionCommands(registry_xml.supported_egl_extensions, ['gles2', 'gles1'])

    gles_data.extend(eglxml.all_cmd_names.get_all_commands())

    gles_data.append("ANGLEGetDisplayPlatform")
    gles_data.append("ANGLEResetDisplayPlatform")

    all_functions = {}

    for function in gles_data:
        if function.startswith("gl"):
            all_functions[function] = "gl::" + function[2:]
            # Special handling for EGL_ANGLE_explicit_context extension
            if support_egl_ANGLE_explicit_context:
                all_functions[function + "ContextANGLE"] = "gl::" + function[2:] + "ContextANGLE"
        elif function.startswith("egl"):
            all_functions[function] = "EGL_" + function[3:]
        else:
            all_functions[function] = function

    proc_data = [('    {"%s", P(%s)}' % (func, angle_func))
                 for func, angle_func in sorted(all_functions.iteritems())]

    with open(out_file_name_gles, 'w') as out_file:
        output_cpp = template_cpp.format(
            script_name=sys.argv[0],
            data_source_name="gl.xml, gl_angle_ext.xml, egl.xml, egl_angle_ext.xml",
            copyright_year=date.today().year,
            includes=includes_gles,
            cast="__eglMustCastToProperFunctionPointerType",
            namespace="egl",
            proc_data=",\n".join(proc_data),
            num_procs=len(proc_data))
        out_file.write(output_cpp)
        out_file.close()

    # libGL proc table
    glxml = registry_xml.RegistryXML('gl.xml')

    for annotation in [
            "1_0", "1_1", "1_2", "1_3", "1_4", "1_5", "2_0", "2_1", "3_0", "3_1", "3_2", "3_3",
            "4_0", "4_1", "4_2", "4_3", "4_4", "4_5", "4_6"
    ]:

        name_prefix = "GL_VERSION_"
        feature_name = "{}{}".format(name_prefix, annotation)
        glxml.AddCommands(feature_name, annotation)

    gl_data = [cmd for cmd in glxml.all_cmd_names.get_all_commands()]

    wglxml = registry_xml.RegistryXML('wgl.xml')

    for annotation in ["1_0"]:

        name_prefix = "WGL_VERSION_"
        feature_name = "{}{}".format(name_prefix, annotation)
        wglxml.AddCommands(feature_name, annotation)

    gl_commands = wglxml.all_cmd_names.get_all_commands()
    gl_data.extend([cmd if cmd[:3] == 'wgl' else 'wgl' + cmd for cmd in gl_commands])

    all_functions = {}

    for function in gl_data:
        if function.startswith("gl"):
            all_functions[function] = "gl::" + function[2:]
        else:
            all_functions[function] = function

    proc_data = [('    {"%s", P(%s)}' % (func, angle_func))
                 for func, angle_func in sorted(all_functions.iteritems())]

    with open(out_file_name_gl, 'w') as out_file:
        output_cpp = template_cpp.format(
            script_name=sys.argv[0],
            data_source_name="gl.xml, wgl.xml",
            copyright_year=date.today().year,
            includes=includes_gl,
            cast="PROC",
            namespace="wgl",
            proc_data=",\n".join(proc_data),
            num_procs=len(proc_data))
        out_file.write(output_cpp)
        out_file.close()
    return 0


if __name__ == '__main__':
    sys.exit(main())
