/*
 * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
 * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
 * Copyright (C) 2013 Google Inc. 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/FECustomFilter.h"

#include "core/platform/graphics/Extensions3D.h"
#include "core/platform/graphics/GraphicsContext3D.h"
#include "core/platform/graphics/filters/custom/CustomFilterRenderer.h"
#include "core/platform/graphics/filters/custom/CustomFilterValidatedProgram.h"
#include "core/platform/text/TextStream.h"
#include "core/rendering/RenderTreeAsText.h"

#include "wtf/Uint8ClampedArray.h"

namespace WebCore {

FECustomFilter::FECustomFilter(Filter* filter, PassRefPtr<GraphicsContext3D> context, PassRefPtr<CustomFilterValidatedProgram> validatedProgram, const CustomFilterParameterList& parameters,
    unsigned meshRows, unsigned meshColumns, CustomFilterMeshType meshType)
    : FilterEffect(filter)
    , m_context(context)
    , m_validatedProgram(validatedProgram)
    , m_inputTexture(0)
    , m_frameBuffer(0)
    , m_depthBuffer(0)
    , m_destTexture(0)
    , m_triedMultisampleBuffer(false)
    , m_multisampleFrameBuffer(0)
    , m_multisampleRenderBuffer(0)
    , m_multisampleDepthBuffer(0)
{
    // We will not pass a CustomFilterCompiledProgram here, as we only want to compile it when we actually need it in the first paint.
    m_customFilterRenderer = CustomFilterRenderer::create(m_context, m_validatedProgram->programInfo().programType(), parameters, meshRows, meshColumns, meshType);
}

PassRefPtr<FECustomFilter> FECustomFilter::create(Filter* filter, PassRefPtr<GraphicsContext3D> context, PassRefPtr<CustomFilterValidatedProgram> validatedProgram, const CustomFilterParameterList& parameters,
    unsigned meshRows, unsigned meshColumns, CustomFilterMeshType meshType)
{
    return adoptRef(new FECustomFilter(filter, context, validatedProgram, parameters, meshRows, meshColumns, meshType));
}

FECustomFilter::~FECustomFilter()
{
    deleteRenderBuffers();
}

void FECustomFilter::deleteRenderBuffers()
{
    ASSERT(m_context);
    m_context->makeContextCurrent();
    if (m_inputTexture) {
        m_context->deleteTexture(m_inputTexture);
        m_inputTexture = 0;
    }
    if (m_frameBuffer) {
        // Make sure to unbind any framebuffer from the context first, otherwise
        // some platforms might refuse to bind the same buffer id again.
        m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0);
        m_context->deleteFramebuffer(m_frameBuffer);
        m_frameBuffer = 0;
    }
    if (m_depthBuffer) {
        m_context->deleteRenderbuffer(m_depthBuffer);
        m_depthBuffer = 0;
    }
    if (m_destTexture) {
        m_context->deleteTexture(m_destTexture);
        m_destTexture = 0;
    }
    deleteMultisampleRenderBuffers();
}

void FECustomFilter::deleteMultisampleRenderBuffers()
{
    if (m_multisampleFrameBuffer) {
        // Make sure to unbind any framebuffer from the context first, otherwise
        // some platforms might refuse to bind the same buffer id again.
        m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0);
        m_context->deleteFramebuffer(m_multisampleFrameBuffer);
        m_multisampleFrameBuffer = 0;
    }
    if (m_multisampleRenderBuffer) {
        m_context->deleteRenderbuffer(m_multisampleRenderBuffer);
        m_multisampleRenderBuffer = 0;
    }
    if (m_multisampleDepthBuffer) {
        m_context->deleteRenderbuffer(m_multisampleDepthBuffer);
        m_multisampleDepthBuffer = 0;
    }
}

void FECustomFilter::applySoftware()
{
    if (!applyShader())
        clearShaderResult();
}

void FECustomFilter::clearShaderResult()
{
    clearResult();
    Uint8ClampedArray* dstPixelArray = createUnmultipliedImageResult();
    if (!dstPixelArray)
        return;

    FilterEffect* in = inputEffect(0);
    setIsAlphaImage(in->isAlphaImage());
    IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
    in->copyUnmultipliedImage(dstPixelArray, effectDrawingRect);
}

void FECustomFilter::drawFilterMesh(Platform3DObject inputTexture)
{
    bool multisample = canUseMultisampleBuffers();
    m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, multisample ? m_multisampleFrameBuffer : m_frameBuffer);
    m_context->viewport(0, 0, m_contextSize.width(), m_contextSize.height());

    m_context->clearColor(0, 0, 0, 0);
    m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_BUFFER_BIT);

    m_customFilterRenderer->draw(inputTexture, m_contextSize);

    if (multisample)
        resolveMultisampleBuffer();
}

bool FECustomFilter::prepareForDrawing()
{
    m_context->makeContextCurrent();

    // Lazily inject the compiled program into the CustomFilterRenderer.
    if (!m_customFilterRenderer->compiledProgram())
        m_customFilterRenderer->setCompiledProgram(m_validatedProgram->compiledProgram());

    if (!m_customFilterRenderer->prepareForDrawing())
        return false;

    // Only allocate a texture if the program needs one and the caller doesn't allocate one by itself.
    if ((m_customFilterRenderer->programNeedsInputTexture() && !ensureInputTexture()) || !ensureFrameBuffer())
        return false;

    return true;
}

bool FECustomFilter::applyShader()
{
    Uint8ClampedArray* dstPixelArray = m_customFilterRenderer->premultipliedAlpha() ? createPremultipliedImageResult() : createUnmultipliedImageResult();
    if (!dstPixelArray)
        return false;

    if (!prepareForDrawing())
        return false;

    FilterEffect* in = inputEffect(0);
    IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
    IntSize newContextSize(effectDrawingRect.size());
    if (!resizeContextIfNeeded(newContextSize))
        return false;

    bool needsInputTexture = m_customFilterRenderer->programNeedsInputTexture();
    if (needsInputTexture) {
        RefPtr<Uint8ClampedArray> srcPixelArray = in->asUnmultipliedImage(effectDrawingRect);
        uploadInputTexture(srcPixelArray.get());
    }
    drawFilterMesh(needsInputTexture ? m_inputTexture : 0);

    ASSERT(static_cast<size_t>(newContextSize.width() * newContextSize.height() * 4) == dstPixelArray->length());
    m_context->readPixels(0, 0, newContextSize.width(), newContextSize.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, dstPixelArray->data());

    return true;
}

bool FECustomFilter::ensureInputTexture()
{
    if (!m_inputTexture)
        m_inputTexture = m_context->createTexture();
    return m_inputTexture;
}

void FECustomFilter::uploadInputTexture(Uint8ClampedArray* srcPixelArray)
{
    m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_inputTexture);
    m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, m_contextSize.width(), m_contextSize.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, srcPixelArray->data());
}

bool FECustomFilter::ensureFrameBuffer()
{
    if (!m_frameBuffer)
        m_frameBuffer = m_context->createFramebuffer();
    if (!m_depthBuffer)
        m_depthBuffer = m_context->createRenderbuffer();
    if (!m_destTexture)
        m_destTexture = m_context->createTexture();
    return m_frameBuffer && m_depthBuffer && m_destTexture;
}

bool FECustomFilter::createMultisampleBuffer()
{
    ASSERT(!m_triedMultisampleBuffer);
    m_triedMultisampleBuffer = true;

    Extensions3D* extensions = m_context->extensions();
    if (!extensions
        || !extensions->supports("GL_ANGLE_framebuffer_multisample")
        || !extensions->supports("GL_ANGLE_framebuffer_blit")
        || !extensions->supports("GL_OES_rgb8_rgba8"))
        return false;

    extensions->ensureEnabled("GL_ANGLE_framebuffer_blit");
    extensions->ensureEnabled("GL_ANGLE_framebuffer_multisample");
    extensions->ensureEnabled("GL_OES_rgb8_rgba8");

    if (!m_multisampleFrameBuffer)
        m_multisampleFrameBuffer = m_context->createFramebuffer();
    if (!m_multisampleRenderBuffer)
        m_multisampleRenderBuffer = m_context->createRenderbuffer();
    if (!m_multisampleDepthBuffer)
        m_multisampleDepthBuffer = m_context->createRenderbuffer();

    return true;
}

void FECustomFilter::resolveMultisampleBuffer()
{
    ASSERT(m_triedMultisampleBuffer && m_multisampleFrameBuffer && m_multisampleRenderBuffer && m_multisampleDepthBuffer);
    m_context->bindFramebuffer(Extensions3D::READ_FRAMEBUFFER, m_multisampleFrameBuffer);
    m_context->bindFramebuffer(Extensions3D::DRAW_FRAMEBUFFER, m_frameBuffer);

    ASSERT(m_context->extensions());
    m_context->extensions()->blitFramebuffer(0, 0, m_contextSize.width(), m_contextSize.height(), 0, 0, m_contextSize.width(), m_contextSize.height(), GraphicsContext3D::COLOR_BUFFER_BIT, GraphicsContext3D::NEAREST);

    m_context->bindFramebuffer(Extensions3D::READ_FRAMEBUFFER, 0);
    m_context->bindFramebuffer(Extensions3D::DRAW_FRAMEBUFFER, 0);

    m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_frameBuffer);
}

bool FECustomFilter::canUseMultisampleBuffers() const
{
    return m_triedMultisampleBuffer && m_multisampleFrameBuffer && m_multisampleRenderBuffer && m_multisampleDepthBuffer;
}

bool FECustomFilter::resizeMultisampleBuffers(const IntSize& newContextSize)
{
    if (!m_triedMultisampleBuffer && !createMultisampleBuffer())
        return false;

    if (!canUseMultisampleBuffers())
        return false;

    static const int kMaxSampleCount = 4;
    int maxSupportedSampleCount = 0;
    m_context->getIntegerv(Extensions3D::MAX_SAMPLES, &maxSupportedSampleCount);
    int sampleCount = std::min(kMaxSampleCount, maxSupportedSampleCount);
    if (!sampleCount) {
        deleteMultisampleRenderBuffers();
        return false;
    }

    Extensions3D* extensions = m_context->extensions();
    ASSERT(extensions);

    m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFrameBuffer);

    m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_multisampleRenderBuffer);
    extensions->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, Extensions3D::RGBA8_OES, newContextSize.width(), newContextSize.height());
    m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::RENDERBUFFER, m_multisampleRenderBuffer);

    m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_multisampleDepthBuffer);
    extensions->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, GraphicsContext3D::DEPTH_COMPONENT16, newContextSize.width(), newContextSize.height());
    m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_multisampleDepthBuffer);

    m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0);

    if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
        deleteMultisampleRenderBuffers();
        return false;
    }

    return true;
}

bool FECustomFilter::resizeContextIfNeeded(const IntSize& newContextSize)
{
    if (newContextSize.isEmpty())
        return false;
    if (m_contextSize == newContextSize)
        return true;

    int maxTextureSize = 0;
    m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &maxTextureSize);
    if (newContextSize.height() > maxTextureSize || newContextSize.width() > maxTextureSize)
        return false;

    return resizeContext(newContextSize);
}

bool FECustomFilter::resizeContext(const IntSize& newContextSize)
{
    bool multisample = resizeMultisampleBuffers(newContextSize);

    m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_frameBuffer);
    m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_destTexture);
    // We are going to clear the output buffer anyway, so we can safely initialize the destination texture with garbage data.
    // FIXME: GraphicsContext3D::texImage2DDirect is not implemented on Chromium.
    m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, newContextSize.width(), newContextSize.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, 0);
    m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_destTexture, 0);

    // We don't need the depth buffer for the texture framebuffer, if we already
    // have a multisample buffer.
    if (!multisample) {
        m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_depthBuffer);
        m_context->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT16, newContextSize.width(), newContextSize.height());
        m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthBuffer);
    }

    if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE)
        return false;

    if (multisample) {
        // Clear the framebuffer first, otherwise the first blit will fail.
        m_context->clearColor(0, 0, 0, 0);
        m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
    }

    m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0);

    m_contextSize = newContextSize;
    return true;
}

TextStream& FECustomFilter::externalRepresentation(TextStream& ts, int indent) const
{
    writeIndent(ts, indent);
    ts << "[feCustomFilter";
    FilterEffect::externalRepresentation(ts);
    ts << "]\n";
    inputEffect(0)->externalRepresentation(ts, indent + 1);
    return ts;
}

} // namespace WebCore
