#!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_3_2_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())
