/*
 * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above
 *    copyright notice, this list of conditions and the following
 *    disclaimer.
 * 2. Redistributions in binary form must reproduce the above
 *    copyright notice, this list of conditions and the following
 *    disclaimer in the documentation and/or other materials
 *    provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include "config.h"

#include "core/platform/graphics/filters/custom/CustomFilterValidatedProgram.h"

#include "core/platform/NotImplemented.h"
#include "core/platform/graphics/ANGLEWebKitBridge.h"
#include "core/platform/graphics/filters/custom/CustomFilterConstants.h"
#include "core/platform/graphics/filters/custom/CustomFilterGlobalContext.h"
#include "core/platform/graphics/filters/custom/CustomFilterProgramInfo.h"
#include "wtf/HashMap.h"
#include "wtf/text/StringBuilder.h"
#include "wtf/text/StringHash.h"
#include "wtf/Vector.h"

namespace WebCore {

#define SHADER(Src) (#Src)

typedef HashMap<String, ShDataType> SymbolNameToTypeMap;

static SymbolNameToTypeMap* builtInAttributeNameToTypeMap()
{
    static SymbolNameToTypeMap* nameToTypeMap = 0;
    if (!nameToTypeMap) {
        nameToTypeMap = new SymbolNameToTypeMap;
        nameToTypeMap->set("a_meshCoord", SH_FLOAT_VEC2);
        nameToTypeMap->set("a_position", SH_FLOAT_VEC4);
        nameToTypeMap->set("a_texCoord", SH_FLOAT_VEC2);
        nameToTypeMap->set("a_triangleCoord", SH_FLOAT_VEC3);
    }
    return nameToTypeMap;
}

static SymbolNameToTypeMap* builtInUniformNameToTypeMap()
{
    static SymbolNameToTypeMap* nameToTypeMap = 0;
    if (!nameToTypeMap) {
        nameToTypeMap = new SymbolNameToTypeMap;
        nameToTypeMap->set("u_meshBox", SH_FLOAT_VEC4);
        nameToTypeMap->set("u_meshSize", SH_FLOAT_VEC2);
        nameToTypeMap->set("u_projectionMatrix", SH_FLOAT_MAT4);
        nameToTypeMap->set("u_textureSize", SH_FLOAT_VEC2);
        nameToTypeMap->set("u_tileSize", SH_FLOAT_VEC2);
    }
    return nameToTypeMap;
}

static bool validateSymbols(const Vector<ANGLEShaderSymbol>& symbols, CustomFilterMeshType meshType)
{
    for (size_t i = 0; i < symbols.size(); ++i) {
        const ANGLEShaderSymbol& symbol = symbols[i];
        switch (symbol.symbolType) {
        case SHADER_SYMBOL_TYPE_ATTRIBUTE: {
            SymbolNameToTypeMap* attributeNameToTypeMap = builtInAttributeNameToTypeMap();
            SymbolNameToTypeMap::iterator builtInAttribute = attributeNameToTypeMap->find(symbol.name);
            if (builtInAttribute == attributeNameToTypeMap->end()) {
                // The author defined a custom attribute.
                // FIXME: Report the validation error.
                // https://bugs.webkit.org/show_bug.cgi?id=74416
                return false;
            }
            if (meshType == MeshTypeAttached && symbol.name == "a_triangleCoord") {
                // a_triangleCoord is only available for detached meshes.
                // FIXME: Report the validation error.
                // https://bugs.webkit.org/show_bug.cgi?id=74416
                return false;
            }
            if (symbol.dataType != builtInAttribute->value) {
                // The author defined one of the built-in attributes with the wrong type.
                // FIXME: Report the validation error.
                // https://bugs.webkit.org/show_bug.cgi?id=74416
                return false;
            }
            break;
        }
        case SHADER_SYMBOL_TYPE_UNIFORM: {
            if (symbol.isSampler()) {
                // FIXME: For now, we restrict shaders with any sampler defined.
                // When we implement texture parameters, we will allow shaders whose samplers are bound to valid textures.
                // We must not allow OpenGL to give unbound samplers a default value of 0 because that references the element texture,
                // which should be inaccessible to the author's shader code.
                // https://bugs.webkit.org/show_bug.cgi?id=96230
                return false;
            }

            SymbolNameToTypeMap* uniformNameToTypeMap = builtInUniformNameToTypeMap();
            SymbolNameToTypeMap::iterator builtInUniform = uniformNameToTypeMap->find(symbol.name);
            if (builtInUniform != uniformNameToTypeMap->end() && (symbol.isArray || symbol.dataType != builtInUniform->value)) {
                // The author defined one of the built-in uniforms with the wrong type.
                // FIXME: Report the validation error.
                // https://bugs.webkit.org/show_bug.cgi?id=74416
                return false;
            }
            break;
        }
        default:
            ASSERT_NOT_REACHED();
            break;
        }
    }

    return true;
}

String CustomFilterValidatedProgram::defaultVertexShaderString()
{
    DEFINE_STATIC_LOCAL(String, vertexShaderString, (SHADER(
        attribute mediump vec4 a_position;
        uniform mediump mat4 u_projectionMatrix;

        void main()
        {
            gl_Position = u_projectionMatrix * a_position;
        }
    )));
    return vertexShaderString;
}

String CustomFilterValidatedProgram::defaultFragmentShaderString()
{
    DEFINE_STATIC_LOCAL(String, fragmentShaderString, (SHADER(
        void main()
        {
        }
    )));
    return fragmentShaderString;
}

CustomFilterValidatedProgram::CustomFilterValidatedProgram(CustomFilterGlobalContext* globalContext, const CustomFilterProgramInfo& programInfo)
    : m_globalContext(globalContext)
    , m_programInfo(programInfo)
    , m_isInitialized(false)
{
    platformInit();

    String originalVertexShader = programInfo.vertexShaderString();
    if (originalVertexShader.isNull())
        originalVertexShader = defaultVertexShaderString();

    String originalFragmentShader = programInfo.fragmentShaderString();
    if (originalFragmentShader.isNull())
        originalFragmentShader = defaultFragmentShaderString();

    // Shaders referenced from the CSS mix function use a different validator than regular WebGL shaders. See core/platform/graphics/filters/custom/CustomFilterGlobalContext.h for more details.
    bool blendsElementTexture = (programInfo.programType() == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE);
    ANGLEWebKitBridge* validator = blendsElementTexture ? m_globalContext->mixShaderValidator() : m_globalContext->webglShaderValidator();
    String vertexShaderLog, fragmentShaderLog;
    Vector<ANGLEShaderSymbol> symbols;
    bool vertexShaderValid = validator->compileShaderSource(originalVertexShader.utf8().data(), SHADER_TYPE_VERTEX, m_validatedVertexShader, vertexShaderLog, symbols);
    bool fragmentShaderValid = validator->compileShaderSource(originalFragmentShader.utf8().data(), SHADER_TYPE_FRAGMENT, m_validatedFragmentShader, fragmentShaderLog, symbols);
    if (!vertexShaderValid || !fragmentShaderValid) {
        // FIXME: Report the validation errors.
        // https://bugs.webkit.org/show_bug.cgi?id=74416
        return;
    }

    if (!validateSymbols(symbols, m_programInfo.meshType())) {
        // FIXME: Report validation errors.
        // https://bugs.webkit.org/show_bug.cgi?id=74416
        return;
    }

    // We need to add texture access, blending, and compositing code to shaders that are referenced from the CSS mix function.
    if (blendsElementTexture) {
        rewriteMixVertexShader(symbols);
        rewriteMixFragmentShader();
    }

    m_isInitialized = true;
}

PassRefPtr<CustomFilterCompiledProgram> CustomFilterValidatedProgram::compiledProgram()
{
    ASSERT(m_isInitialized && m_globalContext && !m_validatedVertexShader.isNull() && !m_validatedFragmentShader.isNull());
    if (!m_compiledProgram) {
        m_compiledProgram = CustomFilterCompiledProgram::create(m_globalContext->context(), m_validatedVertexShader, m_validatedFragmentShader, m_programInfo.programType());
        ASSERT(m_compiledProgram->isInitialized());
        ASSERT(m_compiledProgram->samplerLocation() != -1 || !needsInputTexture());
    }
    return m_compiledProgram;
}

bool CustomFilterValidatedProgram::needsInputTexture() const
{
    return m_programInfo.programType() == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE
        && m_programInfo.mixSettings().compositeOperator != CompositeClear
        && m_programInfo.mixSettings().compositeOperator != CompositeCopy;
}

void CustomFilterValidatedProgram::rewriteMixVertexShader(const Vector<ANGLEShaderSymbol>& symbols)
{
    ASSERT(m_programInfo.programType() == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE);

    // If the author defined a_texCoord, we can use it to shuttle the texture coordinate to the fragment shader.
    // Note that vertex attributes are read-only in GLSL, so the author could not have changed a_texCoord's value.
    // Also, note that we would have already rejected the shader if the author defined a_texCoord with the wrong type.
    bool texCoordAttributeDefined = false;
    for (size_t i = 0; i < symbols.size(); ++i) {
        if (symbols[i].name == "a_texCoord")
            texCoordAttributeDefined = true;
    }

    if (!texCoordAttributeDefined)
        m_validatedVertexShader.append("attribute mediump vec2 a_texCoord;");

    // During validation, ANGLE renamed the author's "main" function to "css_main".
    // We write our own "main" function and call "css_main" from it.
    // This makes rewriting easy and ensures that our code runs after all author code.
    m_validatedVertexShader.append(SHADER(
        varying mediump vec2 css_v_texCoord;

        void main()
        {
            css_main();
            css_v_texCoord = a_texCoord;
        }
    ));
}

void CustomFilterValidatedProgram::rewriteMixFragmentShader()
{
    ASSERT(m_programInfo.programType() == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE);

    StringBuilder builder;
    // ANGLE considered these symbols as built-ins during validation under the SH_CSS_SHADERS_SPEC flag.
    // Now, we have to define these symbols in order to make this shader valid GLSL.
    // We define these symbols before the author's shader code, which makes them accessible to author code.
    builder.append(SHADER(
        mediump vec4 css_MixColor = vec4(0.0);
        mediump mat4 css_ColorMatrix = mat4(1.0);
    ));
    builder.append(m_validatedFragmentShader);
    builder.append(blendFunctionString(m_programInfo.mixSettings().blendMode));
    builder.append(compositeFunctionString(m_programInfo.mixSettings().compositeOperator));
    // We define symbols like "css_u_texture" after the author's shader code, which makes them inaccessible to author code.
    // In particular, "css_u_texture" represents the DOM element texture, so it's important to keep it inaccessible to
    // author code for security reasons.
    builder.append(SHADER(
        uniform sampler2D css_u_texture;
        varying mediump vec2 css_v_texCoord;

        void main()
        {
            css_main();
            mediump vec4 originalColor = texture2D(css_u_texture, css_v_texCoord);
            mediump vec4 multipliedColor = clamp(css_ColorMatrix * originalColor, 0.0, 1.0);
            mediump vec4 clampedMixColor = clamp(css_MixColor, 0.0, 1.0);
            mediump vec3 blendedColor = css_BlendColor(multipliedColor.rgb, clampedMixColor.rgb);
            mediump vec3 weightedColor = (1.0 - multipliedColor.a) * clampedMixColor.rgb + multipliedColor.a * blendedColor;
            gl_FragColor = css_Composite(multipliedColor.rgb, multipliedColor.a, weightedColor.rgb, clampedMixColor.a);
        }
    ));
    m_validatedFragmentShader = builder.toString();
}

String CustomFilterValidatedProgram::blendFunctionString(BlendMode blendMode)
{
    // Implemented using the same symbol names as the Compositing and Blending spec:
    // https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnormal
    // Cs: is the source color in css_BlendColor() and the source color component in css_BlendComponent()
    // Cb: is the backdrop color in css_BlendColor() and the backdrop color component in css_BlendComponent()
    const char* blendColorExpression = "vec3(css_BlendComponent(Cb.r, Cs.r), css_BlendComponent(Cb.g, Cs.g), css_BlendComponent(Cb.b, Cs.b))";
    const char* blendComponentExpression = "Co = 0.0;";
    bool needsLuminosityHelperFunctions = false;
    bool needsSaturationHelperFunctions = false;
    String blendFunctionString;
    switch (blendMode) {
    case BlendModeNormal:
        blendColorExpression = "Cs";
        break;
    case BlendModeMultiply:
        blendColorExpression = "Cs * Cb";
        break;
    case BlendModeScreen:
        blendColorExpression = "Cb + Cs - (Cb * Cs)";
        break;
    case BlendModeDarken:
        blendColorExpression = "min(Cb, Cs)";
        break;
    case BlendModeLighten:
        blendColorExpression = "max(Cb, Cs)";
        break;
    case BlendModeDifference:
        blendColorExpression = "abs(Cb - Cs)";
        break;
    case BlendModeExclusion:
        blendColorExpression = "Cb + Cs - 2.0 * Cb * Cs";
        break;
    case BlendModeOverlay:
        /*
            Co = HardLight(Cs, Cb)
               = if(Cb <= 0.5)
                     Multiply(Cs, 2 x Cb)
                 else
                     Screen(Cs, 2 x Cb - 1)
               = if(Cb <= 0.5)
                     Cs x (2 x Cb)
                 else
                     Cs + (2 x Cb - 1) - (Cs x (2 x Cb - 1))
        */
        blendComponentExpression = SHADER(
            if (Cb <= 0.5)
                Co = Cs * (2.0 * Cb);
            else
                Co = Cs + (2.0 * Cb - 1.0) - (Cs * (2.0 * Cb - 1.0));
        );
        break;
    case BlendModeColorDodge:
        /*
            Co = if(Cs < 1)
                     min(1, Cb / (1 - Cs))
                 else
                     1
        */
        blendComponentExpression = SHADER(
            if (Cs < 1.0)
                Co = min(1.0, Cb / (1.0 - Cs));
            else
                Co = 1.0;
        );
        break;
    case BlendModeColorBurn:
        /*
            Co = if(Cs > 0)
                     1 - min(1, (1 - Cb) / Cs)
                 else
                     0
        */
        blendComponentExpression = SHADER(
            if (Cs > 0.0)
                Co = 1.0 - min(1.0, (1.0 - Cb) / Cs);
            else
                Co = 0.0;
        );
        break;
    case BlendModeHardLight:
        /*
            Co = if(Cs <= 0.5)
                     Multiply(Cb, 2 x Cs)
                 else
                     Screen(Cb, 2 x Cs -1)
               = if(Cs <= 0.5)
                     Cb x (2 x Cs)
                 else
                     Cb + (2 x Cs - 1) - (Cb x (2 x Cs - 1))
        */
        blendComponentExpression = SHADER(
            if (Cs <= 0.5)
                Co = Cb * (2.0 * Cs);
            else
                Co = Cb + (2.0 * Cs - 1.0) - (Cb * (2.0 * Cs - 1.0));
        );
        break;
    case BlendModeSoftLight:
        /*
            Co = if(Cs <= 0.5)
                     Cb - (1 - 2 x Cs) x Cb x (1 - Cb)
                 else
                     Cb + (2 x Cs - 1) x (D(Cb) - Cb)

            with

            D(Cb) = if(Cb <= 0.25)
                        (16 * Cb - 12) x Cb + 4) x Cb
                    else
                        sqrt(Cb)
        */
        blendComponentExpression = SHADER(
            mediump float D;
            if (Cb <= 0.25)
                D = ((16.0 * Cb - 12.0) * Cb + 4.0) * Cb;
            else
                D = sqrt(Cb);

            if (Cs <= 0.5)
                Co = Cb - (1.0 - 2.0 * Cs) * Cb * (1.0 - Cb);
            else
                Co = Cb + (2.0 * Cs - 1.0) * (D - Cb);
        );
        break;
    case BlendModeColor:
        needsLuminosityHelperFunctions = true;
        blendColorExpression = "css_SetLum(Cs, css_Lum(Cb))";
        break;
    case BlendModeLuminosity:
        needsLuminosityHelperFunctions = true;
        blendColorExpression = "css_SetLum(Cb, css_Lum(Cs))";
        break;
    case BlendModeHue:
        needsLuminosityHelperFunctions = true;
        needsSaturationHelperFunctions = true;
        blendColorExpression = "css_SetLum(css_SetSat(Cs, css_Sat(Cb)), css_Lum(Cb))";
        break;
    case BlendModeSaturation:
        needsLuminosityHelperFunctions = true;
        needsSaturationHelperFunctions = true;
        blendColorExpression = "css_SetLum(css_SetSat(Cb, css_Sat(Cs)), css_Lum(Cb))";
        break;
    default:
        ASSERT_NOT_REACHED();
    }

    if (needsLuminosityHelperFunctions) {
        blendFunctionString.append(SHADER(
            mediump float css_Lum(mediump vec3 C)
            {
                return 0.3 * C.r + 0.59 * C.g + 0.11 * C.b;
            }
            mediump vec3 css_ClipColor(mediump vec3 C)
            {
                mediump float L = css_Lum(C);
                mediump float n = min(min(C.r, C.g), C.b);
                mediump float x = max(max(C.r, C.g), C.b);
                if (n < 0.0)
                    C = L + (((C - L) * L) / (L - n));
                if (x > 1.0)
                    C = L + (((C - L) * (1.0 - L) / (x - L)));
                return C;
            }
            mediump vec3 css_SetLum(mediump vec3 C, mediump float l)
            {
                C += l - css_Lum(C);
                return css_ClipColor(C);
            }
        ));
    }

    if (needsSaturationHelperFunctions) {
        blendFunctionString.append(SHADER(
            mediump float css_Sat(mediump vec3 C)
            {
                mediump float cMin = min(min(C.r, C.g), C.b);
                mediump float cMax = max(max(C.r, C.g), C.b);
                return cMax - cMin;
            }
            void css_SetSatHelper(inout mediump float cMin, inout mediump float cMid, inout mediump float cMax, mediump float s)
            {
                if (cMax > cMin) {
                    cMid = (((cMid - cMin) * s) / (cMax - cMin));
                    cMax = s;
                } else
                    cMid = cMax = 0.0;
                cMin = 0.0;
            }
            mediump vec3 css_SetSat(mediump vec3 C, mediump float s)
            {
                if (C.r <= C.g) {
                    if (C.g <= C.b)
                        css_SetSatHelper(C.r, C.g, C.b, s);
                    else {
                        if (C.r <= C.b)
                            css_SetSatHelper(C.r, C.b, C.g, s);
                        else
                            css_SetSatHelper(C.b, C.r, C.g, s);
                    }
                } else {
                    if (C.r <= C.b)
                        css_SetSatHelper(C.g, C.r, C.b, s);
                    else {
                        if (C.g <= C.b)
                            css_SetSatHelper(C.g, C.b, C.r, s);
                        else
                            css_SetSatHelper(C.b, C.g, C.r, s);
                    }
                }
                return C;
            }
        ));
    }

    blendFunctionString.append(String::format(SHADER(
        mediump float css_BlendComponent(mediump float Cb, mediump float Cs)
        {
            mediump float Co;
            %s
            return Co;
        }
        mediump vec3 css_BlendColor(mediump vec3 Cb, mediump vec3 Cs)
        {
            return %s;
        }
    ), blendComponentExpression, blendColorExpression));

    return blendFunctionString;
}

String CustomFilterValidatedProgram::compositeFunctionString(CompositeOperator compositeOperator)
{
    // Use the same symbol names as the Compositing and Blending spec:
    // https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnormal
    // Cs: is the source color
    // Cb: is the backdrop color
    // as: is the source alpha
    // ab: is the backdrop alpha
    // Fa: is defined by the Porter Duff operator in use
    // Fb: is defined by the Porter Duff operator in use
    const char* Fa = 0;
    const char* Fb = 0;
    switch (compositeOperator) {
    case CompositeSourceAtop:
        Fa = "ab";
        Fb = "1.0 - as";
        break;
    case CompositeClear:
        Fa = "0.0";
        Fb = "0.0";
        break;
    case CompositeCopy:
        Fa = "1.0";
        Fb = "0.0";
        break;
    case CompositeSourceOver:
        Fa = "1.0";
        Fb = "1.0 - as";
        break;
    case CompositeSourceIn:
        Fa = "ab";
        Fb = "0.0";
        break;
    case CompositeSourceOut:
        Fa = "1.0 - ab";
        Fb = "0.0";
        break;
    case CompositeDestinationOver:
        Fa = "1.0 - ab";
        Fb = "1.0";
        break;
    case CompositeDestinationIn:
        Fa = "0.0";
        Fb = "as";
        break;
    case CompositeDestinationOut:
        Fa = "0.0";
        Fb = "1.0 - as";
        break;
    case CompositeDestinationAtop:
        Fa = "1.0 - ab";
        Fb = "as";
        break;
    case CompositeXOR:
        Fa = "1.0 - ab";
        Fb = "1.0 - as";
        break;
    case CompositePlusLighter:
        notImplemented();
        return String();
    default:
        // The CSS parser should not have accepted any other composite operators.
        ASSERT_NOT_REACHED();
        return String();
    }

    ASSERT(Fa && Fb);
    // Use the general formula for compositing, lifted from the spec:
    // https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#generalformula
    return String::format(SHADER(
        mediump vec4 css_Composite(mediump vec3 Cb, mediump float ab, mediump vec3 Cs, mediump float as)
        {
            mediump float Fa = %s;
            mediump float Fb = %s;
            return vec4(as * Fa * Cs + ab * Fb * Cb, as * Fa + ab * Fb);
        }
    ), Fa, Fb);
}

CustomFilterValidatedProgram::~CustomFilterValidatedProgram()
{
    platformDestroy();

    if (m_globalContext)
        m_globalContext->removeValidatedProgram(this);
}

CustomFilterProgramInfo CustomFilterValidatedProgram::validatedProgramInfo() const
{
    ASSERT(m_isInitialized);
    return CustomFilterProgramInfo(m_validatedVertexShader, m_validatedFragmentShader, m_programInfo.programType(), m_programInfo.mixSettings(), m_programInfo.meshType());
}

void CustomFilterValidatedProgram::platformInit()
{
}

void CustomFilterValidatedProgram::platformDestroy()
{
}

} // namespace WebCore

