blob: 7a63b6801b696d4f7aebdae6a706adfcf6fda243 [file] [log] [blame]
/*
* 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)