/*
 * Copyright (C) 2010 Google Inc. All rights reserved.
 * Copyright (C) 2009 Apple 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "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
 * OWNER OR CONTRIBUTORS 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.
 */


/** FIXME
 * This file borrows code heavily from platform/graphics/win/GraphicsLayerCACF.cpp
 * (and hence it includes both copyrights)
 * Ideally the common code (mostly the code that keeps track of the layer hierarchy)
 * should be kept separate and shared between platforms. It would be a well worthwhile
 * effort once the Windows implementation (binaries and headers) of CoreAnimation is
 * checked in to the WebKit repository. Until then only Apple can make this happen.
 */

#include "config.h"

#if USE(ACCELERATED_COMPOSITING)

#include "GraphicsLayerChromium.h"

#include "AnimationTranslationUtil.h"
#include "FloatConversion.h"
#include "FloatRect.h"
#include "GraphicsContext.h"
#include "GraphicsLayerFactory.h"
#include "Image.h"
#include "NativeImageSkia.h"
#include "PlatformContextSkia.h"
#include "ScrollableArea.h"
#include "SkImageFilter.h"
#include "SkMatrix44.h"
#include "SkiaImageFilterBuilder.h"
#include "SystemTime.h"
#include <public/Platform.h>
#include <public/WebAnimation.h>
#include <public/WebCompositorSupport.h>
#include <public/WebFilterOperation.h>
#include <public/WebFilterOperations.h>
#include <public/WebFloatPoint.h>
#include <public/WebFloatRect.h>
#include <public/WebImageLayer.h>
#include <public/WebSize.h>
#include <public/WebTransformationMatrix.h>
#include <wtf/CurrentTime.h>
#include <wtf/HashSet.h>
#include <wtf/StringExtras.h>
#include <wtf/text/CString.h>
#include <wtf/text/StringHash.h>
#include <wtf/text/WTFString.h>

using namespace std;
using namespace WebKit;

namespace WebCore {

PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient* client)
{
    if (!factory)
        return adoptPtr(new GraphicsLayerChromium(client));

    return factory->createGraphicsLayer(client);
}

PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
{
    return adoptPtr(new GraphicsLayerChromium(client));
}

GraphicsLayerChromium::GraphicsLayerChromium(GraphicsLayerClient* client)
    : GraphicsLayer(client)
    , m_contentsLayer(0)
    , m_contentsLayerId(0)
    , m_linkHighlight(0)
    , m_contentsLayerPurpose(NoContentsLayer)
    , m_contentsLayerHasBackgroundColor(false)
    , m_inSetChildren(false)
    , m_scrollableArea(0)
{
    m_opaqueRectTrackingContentLayerDelegate = adoptPtr(new OpaqueRectTrackingContentLayerDelegate(this));
    m_layer = adoptPtr(Platform::current()->compositorSupport()->createContentLayer(m_opaqueRectTrackingContentLayerDelegate.get()));
    m_layer->layer()->setDrawsContent(m_drawsContent && m_contentsVisible);
    m_layer->layer()->setScrollClient(this);
    m_layer->setAutomaticallyComputeRasterScale(true);
    updateDebugIndicators();
}

GraphicsLayerChromium::~GraphicsLayerChromium()
{
    willBeDestroyed();
}

void GraphicsLayerChromium::willBeDestroyed()
{
    if (m_linkHighlight) {
        m_linkHighlight->clearCurrentGraphicsLayer();
        m_linkHighlight = 0;
    }

    GraphicsLayer::willBeDestroyed();
}

void GraphicsLayerChromium::setName(const String& inName)
{
    m_nameBase = inName;
    String name = String::format("GraphicsLayer(%p) ", this) + inName;
    GraphicsLayer::setName(name);
    updateNames();
}

void GraphicsLayerChromium::updateNames()
{
    String debugName = "Layer for " + m_nameBase;
    m_layer->layer()->setDebugName(debugName);

    if (m_transformLayer) {
        String debugName = "TransformLayer for " + m_nameBase;
        m_transformLayer->setDebugName(debugName);
    }
    if (WebLayer* contentsLayer = contentsLayerIfRegistered()) {
        String debugName = "ContentsLayer for " + m_nameBase;
        contentsLayer->setDebugName(debugName);
    }
    if (m_linkHighlight) {
        String debugName = "LinkHighlight for " + m_nameBase;
        m_linkHighlight->layer()->setDebugName(debugName);
    }
}

bool GraphicsLayerChromium::setChildren(const Vector<GraphicsLayer*>& children)
{
    m_inSetChildren = true;
    bool childrenChanged = GraphicsLayer::setChildren(children);

    if (childrenChanged)
        updateChildList();
    m_inSetChildren = false;

    return childrenChanged;
}

void GraphicsLayerChromium::addChild(GraphicsLayer* childLayer)
{
    GraphicsLayer::addChild(childLayer);
    if (!m_inSetChildren)
        updateChildList();
}

void GraphicsLayerChromium::addChildAtIndex(GraphicsLayer* childLayer, int index)
{
    GraphicsLayer::addChildAtIndex(childLayer, index);
    updateChildList();
}

void GraphicsLayerChromium::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
{
    GraphicsLayer::addChildBelow(childLayer, sibling);
    updateChildList();
}

void GraphicsLayerChromium::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer *sibling)
{
    GraphicsLayer::addChildAbove(childLayer, sibling);
    updateChildList();
}

bool GraphicsLayerChromium::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
{
    if (GraphicsLayer::replaceChild(oldChild, newChild)) {
        updateChildList();
        return true;
    }
    return false;
}

void GraphicsLayerChromium::removeFromParent()
{
    GraphicsLayer::removeFromParent();
    platformLayer()->removeFromParent();
}

void GraphicsLayerChromium::setPosition(const FloatPoint& point)
{
    GraphicsLayer::setPosition(point);
    updateLayerPosition();
}

void GraphicsLayerChromium::setAnchorPoint(const FloatPoint3D& point)
{
    GraphicsLayer::setAnchorPoint(point);
    updateAnchorPoint();
}

void GraphicsLayerChromium::setSize(const FloatSize& size)
{
    // We are receiving negative sizes here that cause assertions to fail in the compositor. Clamp them to 0 to
    // avoid those assertions.
    // FIXME: This should be an ASSERT instead, as negative sizes should not exist in WebCore.
    FloatSize clampedSize = size;
    if (clampedSize.width() < 0 || clampedSize.height() < 0)
        clampedSize = FloatSize();

    if (clampedSize == m_size)
        return;

    GraphicsLayer::setSize(clampedSize);
    updateLayerSize();
}

void GraphicsLayerChromium::setTransform(const TransformationMatrix& transform)
{
    GraphicsLayer::setTransform(transform);
    updateTransform();
}

void GraphicsLayerChromium::setChildrenTransform(const TransformationMatrix& transform)
{
    GraphicsLayer::setChildrenTransform(transform);
    updateChildrenTransform();
}

void GraphicsLayerChromium::setPreserves3D(bool preserves3D)
{
    if (preserves3D == m_preserves3D)
        return;

    GraphicsLayer::setPreserves3D(preserves3D);
    updateLayerPreserves3D();
}

void GraphicsLayerChromium::setMasksToBounds(bool masksToBounds)
{
    GraphicsLayer::setMasksToBounds(masksToBounds);
    updateMasksToBounds();
}

void GraphicsLayerChromium::setDrawsContent(bool drawsContent)
{
    // Note carefully this early-exit is only correct because we also properly call
    // WebLayer::setDrawsContent whenever m_contentsLayer is set to a new layer in setupContentsLayer().
    if (drawsContent == m_drawsContent)
        return;

    GraphicsLayer::setDrawsContent(drawsContent);
    updateLayerIsDrawable();
}

void GraphicsLayerChromium::setContentsVisible(bool contentsVisible)
{
    // Note carefully this early-exit is only correct because we also properly call
    // WebLayer::setDrawsContent whenever m_contentsLayer is set to a new layer in setupContentsLayer().
    if (contentsVisible == m_contentsVisible)
        return;

    GraphicsLayer::setContentsVisible(contentsVisible);
    updateLayerIsDrawable();
}

void GraphicsLayerChromium::setBackgroundColor(const Color& color)
{
    GraphicsLayer::setBackgroundColor(color.rgb());

    m_contentsLayerHasBackgroundColor = true;
    updateLayerBackgroundColor();
}

void GraphicsLayerChromium::clearBackgroundColor()
{
    GraphicsLayer::clearBackgroundColor();

    if (WebLayer* contentsLayer = contentsLayerIfRegistered())
        contentsLayer->setBackgroundColor(static_cast<RGBA32>(0));
}

void GraphicsLayerChromium::setContentsOpaque(bool opaque)
{
    GraphicsLayer::setContentsOpaque(opaque);
    m_layer->layer()->setOpaque(m_contentsOpaque);
    m_opaqueRectTrackingContentLayerDelegate->setOpaque(m_contentsOpaque);
}

static bool copyWebCoreFilterOperationsToWebFilterOperations(const FilterOperations& filters, WebFilterOperations& webFilters)
{
    for (size_t i = 0; i < filters.size(); ++i) {
        const FilterOperation& op = *filters.at(i);
        switch (op.getOperationType()) {
        case FilterOperation::REFERENCE:
            return false; // Not supported.
        case FilterOperation::GRAYSCALE:
        case FilterOperation::SEPIA:
        case FilterOperation::SATURATE:
        case FilterOperation::HUE_ROTATE: {
            float amount = static_cast<const BasicColorMatrixFilterOperation*>(&op)->amount();
            switch (op.getOperationType()) {
            case FilterOperation::GRAYSCALE:
                webFilters.append(WebFilterOperation::createGrayscaleFilter(amount));
                break;
            case FilterOperation::SEPIA:
                webFilters.append(WebFilterOperation::createSepiaFilter(amount));
                break;
            case FilterOperation::SATURATE:
                webFilters.append(WebFilterOperation::createSaturateFilter(amount));
                break;
            case FilterOperation::HUE_ROTATE:
                webFilters.append(WebFilterOperation::createHueRotateFilter(amount));
                break;
            default:
                ASSERT_NOT_REACHED();
            }
            break;
        }
        case FilterOperation::INVERT:
        case FilterOperation::OPACITY:
        case FilterOperation::BRIGHTNESS:
        case FilterOperation::CONTRAST: {
            float amount = static_cast<const BasicComponentTransferFilterOperation*>(&op)->amount();
            switch (op.getOperationType()) {
            case FilterOperation::INVERT:
                webFilters.append(WebFilterOperation::createInvertFilter(amount));
                break;
            case FilterOperation::OPACITY:
                webFilters.append(WebFilterOperation::createOpacityFilter(amount));
                break;
            case FilterOperation::BRIGHTNESS:
                webFilters.append(WebFilterOperation::createBrightnessFilter(amount));
                break;
            case FilterOperation::CONTRAST:
                webFilters.append(WebFilterOperation::createContrastFilter(amount));
                break;
            default:
                ASSERT_NOT_REACHED();
            }
            break;
        }
        case FilterOperation::BLUR: {
            float pixelRadius = static_cast<const BlurFilterOperation*>(&op)->stdDeviation().getFloatValue();
            webFilters.append(WebFilterOperation::createBlurFilter(pixelRadius));
            break;
        }
        case FilterOperation::DROP_SHADOW: {
            const DropShadowFilterOperation& dropShadowOp = *static_cast<const DropShadowFilterOperation*>(&op);
            webFilters.append(WebFilterOperation::createDropShadowFilter(WebPoint(dropShadowOp.x(), dropShadowOp.y()), dropShadowOp.stdDeviation(), dropShadowOp.color().rgb()));
            break;
        }
#if ENABLE(CSS_SHADERS)
        case FilterOperation::CUSTOM:
        case FilterOperation::VALIDATED_CUSTOM:
            return false; // Not supported.
#endif
        case FilterOperation::PASSTHROUGH:
        case FilterOperation::NONE:
            break;
        }
    }
    return true;
}

bool GraphicsLayerChromium::setFilters(const FilterOperations& filters)
{
    // FIXME: For now, we only use SkImageFilters if there is a reference
    // filter in the chain. Once all issues have been ironed out, we should
    // switch all filtering over to this path, and remove setFilters() and
    // WebFilterOperations altogether.
    if (filters.hasReferenceFilter()) {
        SkiaImageFilterBuilder builder;
        SkAutoTUnref<SkImageFilter> imageFilter(builder.build(filters));
        m_layer->layer()->setFilter(imageFilter);
    } else {
        WebFilterOperations webFilters;
        if (!copyWebCoreFilterOperationsToWebFilterOperations(filters, webFilters)) {
            // Make sure the filters are removed from the platform layer, as they are
            // going to fallback to software mode.
            m_layer->layer()->setFilters(WebFilterOperations());
            GraphicsLayer::setFilters(FilterOperations());
            return false;
        }
        m_layer->layer()->setFilters(webFilters);
    }
    return GraphicsLayer::setFilters(filters);
}

void GraphicsLayerChromium::setBackgroundFilters(const FilterOperations& filters)
{
    WebFilterOperations webFilters;
    if (!copyWebCoreFilterOperationsToWebFilterOperations(filters, webFilters))
        return;
    m_layer->layer()->setBackgroundFilters(webFilters);
}

void GraphicsLayerChromium::setMaskLayer(GraphicsLayer* maskLayer)
{
    if (maskLayer == m_maskLayer)
        return;

    GraphicsLayer::setMaskLayer(maskLayer);

    WebLayer* maskWebLayer = m_maskLayer ? m_maskLayer->platformLayer() : 0;
    m_layer->layer()->setMaskLayer(maskWebLayer);
}

void GraphicsLayerChromium::setBackfaceVisibility(bool visible)
{
    GraphicsLayer::setBackfaceVisibility(visible);
    m_layer->setDoubleSided(m_backfaceVisibility);
}

void GraphicsLayerChromium::setOpacity(float opacity)
{
    float clampedOpacity = max(min(opacity, 1.0f), 0.0f);
    GraphicsLayer::setOpacity(clampedOpacity);
    platformLayer()->setOpacity(opacity);
}

void GraphicsLayerChromium::setReplicatedByLayer(GraphicsLayer* layer)
{
    GraphicsLayerChromium* layerChromium = static_cast<GraphicsLayerChromium*>(layer);
    GraphicsLayer::setReplicatedByLayer(layer);

    WebLayer* webReplicaLayer = layerChromium ? layerChromium->platformLayer() : 0;
    platformLayer()->setReplicaLayer(webReplicaLayer);
}


void GraphicsLayerChromium::setContentsNeedsDisplay()
{
    if (WebLayer* contentsLayer = contentsLayerIfRegistered()) {
        contentsLayer->invalidate();
        addRepaintRect(contentsRect());
    }
}

void GraphicsLayerChromium::setNeedsDisplay()
{
    if (drawsContent()) {
        m_layer->layer()->invalidate();
        addRepaintRect(FloatRect(FloatPoint(), m_size));
        if (m_linkHighlight)
            m_linkHighlight->invalidate();
    }
}

void GraphicsLayerChromium::setNeedsDisplayInRect(const FloatRect& rect)
{
    if (drawsContent()) {
        m_layer->layer()->invalidateRect(rect);
        addRepaintRect(rect);
        if (m_linkHighlight)
            m_linkHighlight->invalidate();
    }
}

void GraphicsLayerChromium::setContentsRect(const IntRect& rect)
{
    if (rect == m_contentsRect)
        return;

    GraphicsLayer::setContentsRect(rect);
    updateContentsRect();
}

void GraphicsLayerChromium::setContentsToImage(Image* image)
{
    bool childrenChanged = false;
    NativeImageSkia* nativeImage = image ? image->nativeImageForCurrentFrame() : 0;
    if (nativeImage) {
        if (m_contentsLayerPurpose != ContentsLayerForImage) {
            m_imageLayer = adoptPtr(Platform::current()->compositorSupport()->createImageLayer());
            registerContentsLayer(m_imageLayer->layer());

            setupContentsLayer(m_imageLayer->layer());
            m_contentsLayerPurpose = ContentsLayerForImage;
            childrenChanged = true;
        }
        m_imageLayer->setBitmap(nativeImage->bitmap());
        m_imageLayer->layer()->setOpaque(image->isBitmapImage() && !image->currentFrameHasAlpha());
        updateContentsRect();
    } else {
        if (m_imageLayer) {
            childrenChanged = true;

            unregisterContentsLayer(m_imageLayer->layer());
            m_imageLayer.clear();
        }
        // The old contents layer will be removed via updateChildList.
        m_contentsLayer = 0;
    }

    if (childrenChanged)
        updateChildList();
}

static HashSet<int>* s_registeredLayerSet;

void GraphicsLayerChromium::registerContentsLayer(WebLayer* layer)
{
    if (!s_registeredLayerSet)
        s_registeredLayerSet = new HashSet<int>;
    if (s_registeredLayerSet->contains(layer->id()))
        CRASH();
    s_registeredLayerSet->add(layer->id());
}

void GraphicsLayerChromium::unregisterContentsLayer(WebLayer* layer)
{
    ASSERT(s_registeredLayerSet);
    if (!s_registeredLayerSet->contains(layer->id()))
        CRASH();
    s_registeredLayerSet->remove(layer->id());
}

void GraphicsLayerChromium::clearContentsLayerIfUnregistered()
{
    if (!m_contentsLayerId || s_registeredLayerSet->contains(m_contentsLayerId))
        return;

    m_contentsLayer = 0;
    m_contentsLayerId = 0;
}

WebLayer* GraphicsLayerChromium::contentsLayerIfRegistered()
{
    clearContentsLayerIfUnregistered();
    return m_contentsLayer;
}

void GraphicsLayerChromium::setContentsToCanvas(PlatformLayer* layer)
{
    setContentsTo(ContentsLayerForCanvas, layer);
}

void GraphicsLayerChromium::setContentsToMedia(PlatformLayer* layer)
{
    setContentsTo(ContentsLayerForVideo, layer);
}

void GraphicsLayerChromium::setContentsTo(ContentsLayerPurpose purpose, WebLayer* layer)
{
    bool childrenChanged = false;
    if (layer) {
        ASSERT(s_registeredLayerSet);
        if (!s_registeredLayerSet->contains(layer->id()))
            CRASH();
        if (m_contentsLayerId != layer->id()) {
            setupContentsLayer(layer);
            m_contentsLayerPurpose = purpose;
            childrenChanged = true;
        }
        updateContentsRect();
    } else {
        if (m_contentsLayer) {
            childrenChanged = true;

            // The old contents layer will be removed via updateChildList.
            m_contentsLayer = 0;
        }
    }

    if (childrenChanged)
        updateChildList();
}

bool GraphicsLayerChromium::addAnimation(const KeyframeValueList& values, const IntSize& boxSize, const Animation* animation, const String& animationName, double timeOffset)
{
    platformLayer()->setAnimationDelegate(this);

    int animationId = 0;

    if (m_animationIdMap.contains(animationName))
        animationId = m_animationIdMap.get(animationName);

    OwnPtr<WebAnimation> toAdd(createWebAnimation(values, animation, animationId, timeOffset, boxSize));

    if (toAdd) {
        animationId = toAdd->id();
        m_animationIdMap.set(animationName, animationId);

        // Remove any existing animations with the same animation id and target property.
        platformLayer()->removeAnimation(animationId, toAdd->targetProperty());
        return platformLayer()->addAnimation(toAdd.get());
    }

    return false;
}

void GraphicsLayerChromium::pauseAnimation(const String& animationName, double timeOffset)
{
    if (m_animationIdMap.contains(animationName))
        platformLayer()->pauseAnimation(m_animationIdMap.get(animationName), timeOffset);
}

void GraphicsLayerChromium::removeAnimation(const String& animationName)
{
    if (m_animationIdMap.contains(animationName))
        platformLayer()->removeAnimation(m_animationIdMap.get(animationName));
}

void GraphicsLayerChromium::suspendAnimations(double wallClockTime)
{
    // |wallClockTime| is in the wrong time base. Need to convert here.
    // FIXME: find a more reliable way to do this.
    double monotonicTime = wallClockTime + monotonicallyIncreasingTime() - currentTime();
    platformLayer()->suspendAnimations(monotonicTime);
}

void GraphicsLayerChromium::resumeAnimations()
{
    platformLayer()->resumeAnimations(monotonicallyIncreasingTime());
}

void GraphicsLayerChromium::setLinkHighlight(LinkHighlightClient* linkHighlight)
{
    m_linkHighlight = linkHighlight;
    updateChildList();
}

PlatformLayer* GraphicsLayerChromium::platformLayer() const
{
    return m_transformLayer ? m_transformLayer.get() : m_layer->layer();
}

void GraphicsLayerChromium::setDebugBackgroundColor(const Color& color)
{
    if (color.isValid())
        m_layer->layer()->setBackgroundColor(color.rgb());
    else
        m_layer->layer()->setBackgroundColor(static_cast<RGBA32>(0));
}

void GraphicsLayerChromium::setDebugBorder(const Color& color, float borderWidth)
{
    if (color.isValid()) {
        m_layer->layer()->setDebugBorderColor(color.rgb());
        m_layer->layer()->setDebugBorderWidth(borderWidth);
    } else {
        m_layer->layer()->setDebugBorderColor(static_cast<RGBA32>(0));
        m_layer->layer()->setDebugBorderWidth(0);
    }
}

void GraphicsLayerChromium::updateChildList()
{
    WebLayer* childHost = m_transformLayer ? m_transformLayer.get() : m_layer->layer();
    childHost->removeAllChildren();

    clearContentsLayerIfUnregistered();

    if (m_transformLayer) {
        // Add the primary layer first. Even if we have negative z-order children, the primary layer always comes behind.
        childHost->addChild(m_layer->layer());
    } else if (m_contentsLayer) {
        // FIXME: add the contents layer in the correct order with negative z-order children.
        // This does not cause visible rendering issues because currently contents layers are only used
        // for replaced elements that don't have children.
        childHost->addChild(m_contentsLayer);
    }

    const Vector<GraphicsLayer*>& childLayers = children();
    size_t numChildren = childLayers.size();
    for (size_t i = 0; i < numChildren; ++i) {
        GraphicsLayerChromium* curChild = static_cast<GraphicsLayerChromium*>(childLayers[i]);

        childHost->addChild(curChild->platformLayer());
    }

    if (m_linkHighlight)
        childHost->addChild(m_linkHighlight->layer());

    if (m_transformLayer && m_contentsLayer) {
        // If we have a transform layer, then the contents layer is parented in the
        // primary layer (which is itself a child of the transform layer).
        m_layer->layer()->removeAllChildren();
        m_layer->layer()->addChild(m_contentsLayer);
    }
}

void GraphicsLayerChromium::updateLayerPosition()
{
    platformLayer()->setPosition(m_position);
}

void GraphicsLayerChromium::updateLayerSize()
{
    IntSize layerSize(m_size.width(), m_size.height());
    if (m_transformLayer) {
        m_transformLayer->setBounds(layerSize);
        m_layer->layer()->setPosition(FloatPoint());
    }

    m_layer->layer()->setBounds(layerSize);

    // Note that we don't resize m_contentsLayer-> It's up the caller to do that.
}

void GraphicsLayerChromium::updateAnchorPoint()
{
    platformLayer()->setAnchorPoint(FloatPoint(m_anchorPoint.x(), m_anchorPoint.y()));
    platformLayer()->setAnchorPointZ(m_anchorPoint.z());
}

void GraphicsLayerChromium::updateTransform()
{
    platformLayer()->setTransform(WebTransformationMatrix(m_transform));
}

void GraphicsLayerChromium::updateChildrenTransform()
{
    platformLayer()->setSublayerTransform(WebTransformationMatrix(m_childrenTransform));
}

void GraphicsLayerChromium::updateMasksToBounds()
{
    m_layer->layer()->setMasksToBounds(m_masksToBounds);
    updateDebugIndicators();
}

void GraphicsLayerChromium::updateLayerPreserves3D()
{
    if (m_preserves3D && !m_transformLayer) {
        m_transformLayer = adoptPtr(Platform::current()->compositorSupport()->createLayer());
        m_transformLayer->setPreserves3D(true);
        m_transformLayer->setAnimationDelegate(this);
        m_layer->layer()->transferAnimationsTo(m_transformLayer.get());

        // Copy the position from this layer.
        updateLayerPosition();
        updateLayerSize();
        updateAnchorPoint();
        updateTransform();
        updateChildrenTransform();

        m_layer->layer()->setPosition(FloatPoint::zero());

        m_layer->layer()->setAnchorPoint(FloatPoint(0.5f, 0.5f));
        m_layer->layer()->setTransform(SkMatrix44());

        // Set the old layer to opacity of 1. Further down we will set the opacity on the transform layer.
        m_layer->layer()->setOpacity(1);

        // Move this layer to be a child of the transform layer.
        if (parent())
            parent()->platformLayer()->replaceChild(m_layer->layer(), m_transformLayer.get());
        m_transformLayer->addChild(m_layer->layer());

        updateChildList();
    } else if (!m_preserves3D && m_transformLayer) {
        // Replace the transformLayer in the parent with this layer.
        m_layer->layer()->removeFromParent();
        if (parent())
            parent()->platformLayer()->replaceChild(m_transformLayer.get(), m_layer->layer());

        m_layer->layer()->setAnimationDelegate(this);
        m_transformLayer->transferAnimationsTo(m_layer->layer());

        // Release the transform layer.
        m_transformLayer->setAnimationDelegate(0);
        m_transformLayer.clear();

        updateLayerPosition();
        updateLayerSize();
        updateAnchorPoint();
        updateTransform();
        updateChildrenTransform();

        updateChildList();
    }

    m_layer->layer()->setPreserves3D(m_preserves3D);
    platformLayer()->setOpacity(m_opacity);
    updateNames();
}

void GraphicsLayerChromium::updateLayerIsDrawable()
{
    // For the rest of the accelerated compositor code, there is no reason to make a
    // distinction between drawsContent and contentsVisible. So, for m_layer->layer(), these two
    // flags are combined here. m_contentsLayer shouldn't receive the drawsContent flag
    // so it is only given contentsVisible.

    m_layer->layer()->setDrawsContent(m_drawsContent && m_contentsVisible);
    if (WebLayer* contentsLayer = contentsLayerIfRegistered())
        contentsLayer->setDrawsContent(m_contentsVisible);

    if (m_drawsContent) {
        m_layer->layer()->invalidate();
        if (m_linkHighlight)
            m_linkHighlight->invalidate();
    }

    updateDebugIndicators();
}

void GraphicsLayerChromium::updateLayerBackgroundColor()
{
    WebLayer* contentsLayer = contentsLayerIfRegistered();
    if (!contentsLayer)
        return;

    // We never create the contents layer just for background color yet.
    if (m_backgroundColorSet)
        contentsLayer->setBackgroundColor(m_backgroundColor.rgb());
    else
        contentsLayer->setBackgroundColor(static_cast<RGBA32>(0));
}

void GraphicsLayerChromium::updateContentsVideo()
{
    // FIXME: Implement
}

void GraphicsLayerChromium::updateContentsRect()
{
    WebLayer* contentsLayer = contentsLayerIfRegistered();
    if (!contentsLayer)
        return;

    contentsLayer->setPosition(FloatPoint(m_contentsRect.x(), m_contentsRect.y()));
    contentsLayer->setBounds(IntSize(m_contentsRect.width(), m_contentsRect.height()));
}

void GraphicsLayerChromium::setupContentsLayer(WebLayer* contentsLayer)
{
    m_contentsLayer = contentsLayer;
    m_contentsLayerId = m_contentsLayer->id();

    if (m_contentsLayer) {
        m_contentsLayer->setAnchorPoint(FloatPoint(0, 0));
        m_contentsLayer->setUseParentBackfaceVisibility(true);

        // It is necessary to call setDrawsContent as soon as we receive the new contentsLayer, for
        // the correctness of early exit conditions in setDrawsContent() and setContentsVisible().
        m_contentsLayer->setDrawsContent(m_contentsVisible);

        // Insert the content layer first. Video elements require this, because they have
        // shadow content that must display in front of the video.
        m_layer->layer()->insertChild(m_contentsLayer, 0);

        if (isShowingDebugBorder()) {
            m_contentsLayer->setDebugBorderColor(Color(0, 0, 128, 180).rgb());
            m_contentsLayer->setDebugBorderWidth(1);
        }
    }
    updateDebugIndicators();
    updateNames();
}

void GraphicsLayerChromium::setAppliesPageScale(bool appliesScale)
{
    m_layer->setBoundsContainPageScale(appliesScale);
}

bool GraphicsLayerChromium::appliesPageScale() const
{
    return m_layer->boundsContainPageScale();
}

void GraphicsLayerChromium::paint(GraphicsContext& context, const IntRect& clip)
{
    paintGraphicsLayerContents(context, clip);
}

void GraphicsLayerChromium::notifyAnimationStarted(double startTime)
{
    if (m_client)
        m_client->notifyAnimationStarted(this, startTime);
}

void GraphicsLayerChromium::notifyAnimationFinished(double)
{
    // Do nothing.
}

void GraphicsLayerChromium::didScroll()
{
    if (m_scrollableArea)
        m_scrollableArea->scrollToOffsetWithoutAnimation(IntPoint(m_layer->layer()->scrollPosition()));
}

} // namespace WebCore

#endif // USE(ACCELERATED_COMPOSITING)
