summaryrefslogtreecommitdiffstats
path: root/cc/LayerChromium.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cc/LayerChromium.cpp')
-rw-r--r--cc/LayerChromium.cpp717
1 files changed, 717 insertions, 0 deletions
diff --git a/cc/LayerChromium.cpp b/cc/LayerChromium.cpp
new file mode 100644
index 0000000..8dc15ad
--- /dev/null
+++ b/cc/LayerChromium.cpp
@@ -0,0 +1,717 @@
+// Copyright 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+#include "LayerChromium.h"
+
+#include "CCActiveAnimation.h"
+#include "CCAnimationEvents.h"
+#include "CCLayerAnimationController.h"
+#include "CCLayerImpl.h"
+#include "CCLayerTreeHost.h"
+#include "CCSettings.h"
+#include "TextStream.h"
+
+#include <public/WebAnimationDelegate.h>
+
+using namespace std;
+using WebKit::WebTransformationMatrix;
+
+namespace WebCore {
+
+static int s_nextLayerId = 1;
+
+PassRefPtr<LayerChromium> LayerChromium::create()
+{
+ return adoptRef(new LayerChromium());
+}
+
+LayerChromium::LayerChromium()
+ : m_needsDisplay(false)
+ , m_stackingOrderChanged(false)
+ , m_layerId(s_nextLayerId++)
+ , m_parent(0)
+ , m_layerTreeHost(0)
+ , m_layerAnimationController(CCLayerAnimationController::create(this))
+ , m_scrollable(false)
+ , m_shouldScrollOnMainThread(false)
+ , m_haveWheelEventHandlers(false)
+ , m_nonFastScrollableRegionChanged(false)
+ , m_anchorPoint(0.5, 0.5)
+ , m_backgroundColor(0)
+ , m_debugBorderColor(0)
+ , m_debugBorderWidth(0)
+ , m_opacity(1.0)
+ , m_anchorPointZ(0)
+ , m_isContainerForFixedPositionLayers(false)
+ , m_fixedToContainerLayer(false)
+ , m_isDrawable(false)
+ , m_masksToBounds(false)
+ , m_opaque(false)
+ , m_doubleSided(true)
+ , m_useLCDText(false)
+ , m_preserves3D(false)
+ , m_useParentBackfaceVisibility(false)
+ , m_drawCheckerboardForMissingTiles(false)
+ , m_forceRenderSurface(false)
+ , m_replicaLayer(0)
+ , m_drawOpacity(0)
+ , m_drawOpacityIsAnimating(false)
+ , m_renderTarget(0)
+ , m_drawTransformIsAnimating(false)
+ , m_screenSpaceTransformIsAnimating(false)
+ , m_contentsScale(1.0)
+ , m_layerAnimationDelegate(0)
+ , m_layerScrollDelegate(0)
+{
+ if (m_layerId < 0) {
+ s_nextLayerId = 1;
+ m_layerId = s_nextLayerId++;
+ }
+}
+
+LayerChromium::~LayerChromium()
+{
+ // Our parent should be holding a reference to us so there should be no
+ // way for us to be destroyed while we still have a parent.
+ ASSERT(!parent());
+
+ // Remove the parent reference from all children.
+ removeAllChildren();
+}
+
+void LayerChromium::setUseLCDText(bool useLCDText)
+{
+ m_useLCDText = useLCDText;
+}
+
+void LayerChromium::setLayerTreeHost(CCLayerTreeHost* host)
+{
+ if (m_layerTreeHost == host)
+ return;
+
+ m_layerTreeHost = host;
+
+ for (size_t i = 0; i < m_children.size(); ++i)
+ m_children[i]->setLayerTreeHost(host);
+
+ if (m_maskLayer)
+ m_maskLayer->setLayerTreeHost(host);
+ if (m_replicaLayer)
+ m_replicaLayer->setLayerTreeHost(host);
+
+ // If this layer already has active animations, the host needs to be notified.
+ if (host && m_layerAnimationController->hasActiveAnimation())
+ host->didAddAnimation();
+}
+
+void LayerChromium::setNeedsCommit()
+{
+ if (m_layerTreeHost)
+ m_layerTreeHost->setNeedsCommit();
+}
+
+void LayerChromium::setParent(LayerChromium* layer)
+{
+ ASSERT(!layer || !layer->hasAncestor(this));
+ m_parent = layer;
+ setLayerTreeHost(m_parent ? m_parent->layerTreeHost() : 0);
+}
+
+bool LayerChromium::hasAncestor(LayerChromium* ancestor) const
+{
+ for (LayerChromium* layer = parent(); layer; layer = layer->parent()) {
+ if (layer == ancestor)
+ return true;
+ }
+ return false;
+}
+
+void LayerChromium::addChild(PassRefPtr<LayerChromium> child)
+{
+ insertChild(child, numChildren());
+}
+
+void LayerChromium::insertChild(PassRefPtr<LayerChromium> child, size_t index)
+{
+ index = min(index, m_children.size());
+ child->removeFromParent();
+ child->setParent(this);
+ child->m_stackingOrderChanged = true;
+ m_children.insert(index, child);
+ setNeedsCommit();
+}
+
+void LayerChromium::removeFromParent()
+{
+ if (m_parent)
+ m_parent->removeChild(this);
+}
+
+void LayerChromium::removeChild(LayerChromium* child)
+{
+ int foundIndex = indexOfChild(child);
+ if (foundIndex == -1)
+ return;
+
+ child->setParent(0);
+ m_children.remove(foundIndex);
+ setNeedsCommit();
+}
+
+void LayerChromium::replaceChild(LayerChromium* reference, PassRefPtr<LayerChromium> newLayer)
+{
+ ASSERT_ARG(reference, reference);
+ ASSERT_ARG(reference, reference->parent() == this);
+
+ if (reference == newLayer)
+ return;
+
+ int referenceIndex = indexOfChild(reference);
+ if (referenceIndex == -1) {
+ ASSERT_NOT_REACHED();
+ return;
+ }
+
+ reference->removeFromParent();
+
+ if (newLayer) {
+ newLayer->removeFromParent();
+ insertChild(newLayer, referenceIndex);
+ }
+}
+
+int LayerChromium::indexOfChild(const LayerChromium* reference)
+{
+ for (size_t i = 0; i < m_children.size(); i++) {
+ if (m_children[i] == reference)
+ return i;
+ }
+ return -1;
+}
+
+void LayerChromium::setBounds(const IntSize& size)
+{
+ if (bounds() == size)
+ return;
+
+ bool firstResize = bounds().isEmpty() && !size.isEmpty();
+
+ m_bounds = size;
+
+ if (firstResize)
+ setNeedsDisplay();
+ else
+ setNeedsCommit();
+}
+
+LayerChromium* LayerChromium::rootLayer()
+{
+ LayerChromium* layer = this;
+ while (layer->parent())
+ layer = layer->parent();
+ return layer;
+}
+
+void LayerChromium::removeAllChildren()
+{
+ while (m_children.size()) {
+ LayerChromium* layer = m_children[0].get();
+ ASSERT(layer->parent());
+ layer->removeFromParent();
+ }
+}
+
+void LayerChromium::setChildren(const Vector<RefPtr<LayerChromium> >& children)
+{
+ if (children == m_children)
+ return;
+
+ removeAllChildren();
+ size_t listSize = children.size();
+ for (size_t i = 0; i < listSize; i++)
+ addChild(children[i]);
+}
+
+void LayerChromium::setAnchorPoint(const FloatPoint& anchorPoint)
+{
+ if (m_anchorPoint == anchorPoint)
+ return;
+ m_anchorPoint = anchorPoint;
+ setNeedsCommit();
+}
+
+void LayerChromium::setAnchorPointZ(float anchorPointZ)
+{
+ if (m_anchorPointZ == anchorPointZ)
+ return;
+ m_anchorPointZ = anchorPointZ;
+ setNeedsCommit();
+}
+
+void LayerChromium::setBackgroundColor(SkColor backgroundColor)
+{
+ if (m_backgroundColor == backgroundColor)
+ return;
+ m_backgroundColor = backgroundColor;
+ setNeedsCommit();
+}
+
+void LayerChromium::setMasksToBounds(bool masksToBounds)
+{
+ if (m_masksToBounds == masksToBounds)
+ return;
+ m_masksToBounds = masksToBounds;
+ setNeedsCommit();
+}
+
+void LayerChromium::setMaskLayer(LayerChromium* maskLayer)
+{
+ if (m_maskLayer == maskLayer)
+ return;
+ if (m_maskLayer)
+ m_maskLayer->setLayerTreeHost(0);
+ m_maskLayer = maskLayer;
+ if (m_maskLayer) {
+ m_maskLayer->setLayerTreeHost(m_layerTreeHost);
+ m_maskLayer->setIsMask(true);
+ }
+ setNeedsCommit();
+}
+
+void LayerChromium::setReplicaLayer(LayerChromium* layer)
+{
+ if (m_replicaLayer == layer)
+ return;
+ if (m_replicaLayer)
+ m_replicaLayer->setLayerTreeHost(0);
+ m_replicaLayer = layer;
+ if (m_replicaLayer)
+ m_replicaLayer->setLayerTreeHost(m_layerTreeHost);
+ setNeedsCommit();
+}
+
+void LayerChromium::setFilters(const WebKit::WebFilterOperations& filters)
+{
+ if (m_filters == filters)
+ return;
+ m_filters = filters;
+ setNeedsCommit();
+ if (!filters.isEmpty())
+ CCLayerTreeHost::setNeedsFilterContext(true);
+}
+
+void LayerChromium::setBackgroundFilters(const WebKit::WebFilterOperations& backgroundFilters)
+{
+ if (m_backgroundFilters == backgroundFilters)
+ return;
+ m_backgroundFilters = backgroundFilters;
+ setNeedsCommit();
+ if (!backgroundFilters.isEmpty())
+ CCLayerTreeHost::setNeedsFilterContext(true);
+}
+
+void LayerChromium::setOpacity(float opacity)
+{
+ if (m_opacity == opacity)
+ return;
+ m_opacity = opacity;
+ setNeedsCommit();
+}
+
+bool LayerChromium::opacityIsAnimating() const
+{
+ return m_layerAnimationController->isAnimatingProperty(CCActiveAnimation::Opacity);
+}
+
+void LayerChromium::setOpaque(bool opaque)
+{
+ if (m_opaque == opaque)
+ return;
+ m_opaque = opaque;
+ setNeedsDisplay();
+}
+
+void LayerChromium::setPosition(const FloatPoint& position)
+{
+ if (m_position == position)
+ return;
+ m_position = position;
+ setNeedsCommit();
+}
+
+void LayerChromium::setSublayerTransform(const WebTransformationMatrix& sublayerTransform)
+{
+ if (m_sublayerTransform == sublayerTransform)
+ return;
+ m_sublayerTransform = sublayerTransform;
+ setNeedsCommit();
+}
+
+void LayerChromium::setTransform(const WebTransformationMatrix& transform)
+{
+ if (m_transform == transform)
+ return;
+ m_transform = transform;
+ setNeedsCommit();
+}
+
+bool LayerChromium::transformIsAnimating() const
+{
+ return m_layerAnimationController->isAnimatingProperty(CCActiveAnimation::Transform);
+}
+
+void LayerChromium::setScrollPosition(const IntPoint& scrollPosition)
+{
+ if (m_scrollPosition == scrollPosition)
+ return;
+ m_scrollPosition = scrollPosition;
+ setNeedsCommit();
+}
+
+void LayerChromium::setMaxScrollPosition(const IntSize& maxScrollPosition)
+{
+ if (m_maxScrollPosition == maxScrollPosition)
+ return;
+ m_maxScrollPosition = maxScrollPosition;
+ setNeedsCommit();
+}
+
+void LayerChromium::setScrollable(bool scrollable)
+{
+ if (m_scrollable == scrollable)
+ return;
+ m_scrollable = scrollable;
+ setNeedsCommit();
+}
+
+void LayerChromium::setShouldScrollOnMainThread(bool shouldScrollOnMainThread)
+{
+ if (m_shouldScrollOnMainThread == shouldScrollOnMainThread)
+ return;
+ m_shouldScrollOnMainThread = shouldScrollOnMainThread;
+ setNeedsCommit();
+}
+
+void LayerChromium::setHaveWheelEventHandlers(bool haveWheelEventHandlers)
+{
+ if (m_haveWheelEventHandlers == haveWheelEventHandlers)
+ return;
+ m_haveWheelEventHandlers = haveWheelEventHandlers;
+ setNeedsCommit();
+}
+
+void LayerChromium::setNonFastScrollableRegion(const Region& region)
+{
+ if (m_nonFastScrollableRegion == region)
+ return;
+ m_nonFastScrollableRegion = region;
+ m_nonFastScrollableRegionChanged = true;
+ setNeedsCommit();
+}
+
+void LayerChromium::scrollBy(const IntSize& scrollDelta)
+{
+ setScrollPosition(scrollPosition() + scrollDelta);
+ if (m_layerScrollDelegate)
+ m_layerScrollDelegate->didScroll(scrollDelta);
+}
+
+void LayerChromium::setDrawCheckerboardForMissingTiles(bool checkerboard)
+{
+ if (m_drawCheckerboardForMissingTiles == checkerboard)
+ return;
+ m_drawCheckerboardForMissingTiles = checkerboard;
+ setNeedsCommit();
+}
+
+void LayerChromium::setForceRenderSurface(bool force)
+{
+ if (m_forceRenderSurface == force)
+ return;
+ m_forceRenderSurface = force;
+ setNeedsCommit();
+}
+
+void LayerChromium::setDoubleSided(bool doubleSided)
+{
+ if (m_doubleSided == doubleSided)
+ return;
+ m_doubleSided = doubleSided;
+ setNeedsCommit();
+}
+
+void LayerChromium::setIsDrawable(bool isDrawable)
+{
+ if (m_isDrawable == isDrawable)
+ return;
+
+ m_isDrawable = isDrawable;
+ setNeedsCommit();
+}
+
+LayerChromium* LayerChromium::parent() const
+{
+ return m_parent;
+}
+
+void LayerChromium::setNeedsDisplayRect(const FloatRect& dirtyRect)
+{
+ m_updateRect.unite(dirtyRect);
+
+ // Simply mark the contents as dirty. For non-root layers, the call to
+ // setNeedsCommit will schedule a fresh compositing pass.
+ // For the root layer, setNeedsCommit has no effect.
+ if (!dirtyRect.isEmpty())
+ m_needsDisplay = true;
+
+ setNeedsCommit();
+}
+
+bool LayerChromium::descendantIsFixedToContainerLayer() const
+{
+ for (size_t i = 0; i < m_children.size(); ++i) {
+ if (m_children[i]->fixedToContainerLayer() || m_children[i]->descendantIsFixedToContainerLayer())
+ return true;
+ }
+ return false;
+}
+
+void LayerChromium::setIsContainerForFixedPositionLayers(bool isContainerForFixedPositionLayers)
+{
+ if (m_isContainerForFixedPositionLayers == isContainerForFixedPositionLayers)
+ return;
+ m_isContainerForFixedPositionLayers = isContainerForFixedPositionLayers;
+
+ if (m_layerTreeHost && m_layerTreeHost->commitRequested())
+ return;
+
+ // Only request a commit if we have a fixed positioned descendant.
+ if (descendantIsFixedToContainerLayer())
+ setNeedsCommit();
+}
+
+void LayerChromium::setFixedToContainerLayer(bool fixedToContainerLayer)
+{
+ if (m_fixedToContainerLayer == fixedToContainerLayer)
+ return;
+ m_fixedToContainerLayer = fixedToContainerLayer;
+ setNeedsCommit();
+}
+
+void LayerChromium::pushPropertiesTo(CCLayerImpl* layer)
+{
+ layer->setAnchorPoint(m_anchorPoint);
+ layer->setAnchorPointZ(m_anchorPointZ);
+ layer->setBackgroundColor(m_backgroundColor);
+ layer->setBounds(m_bounds);
+ layer->setContentBounds(contentBounds());
+ layer->setDebugBorderColor(m_debugBorderColor);
+ layer->setDebugBorderWidth(m_debugBorderWidth);
+ layer->setDebugName(m_debugName.isolatedCopy()); // We have to use isolatedCopy() here to safely pass ownership to another thread.
+ layer->setDoubleSided(m_doubleSided);
+ layer->setDrawCheckerboardForMissingTiles(m_drawCheckerboardForMissingTiles);
+ layer->setForceRenderSurface(m_forceRenderSurface);
+ layer->setDrawsContent(drawsContent());
+ layer->setFilters(filters());
+ layer->setBackgroundFilters(backgroundFilters());
+ layer->setUseLCDText(m_useLCDText);
+ layer->setMasksToBounds(m_masksToBounds);
+ layer->setScrollable(m_scrollable);
+ layer->setShouldScrollOnMainThread(m_shouldScrollOnMainThread);
+ layer->setHaveWheelEventHandlers(m_haveWheelEventHandlers);
+ // Copying a Region is more expensive than most layer properties, since it involves copying two Vectors that may be
+ // arbitrarily large depending on page content, so we only push the property if it's changed.
+ if (m_nonFastScrollableRegionChanged) {
+ layer->setNonFastScrollableRegion(m_nonFastScrollableRegion);
+ m_nonFastScrollableRegionChanged = false;
+ }
+ layer->setOpaque(m_opaque);
+ if (!opacityIsAnimating())
+ layer->setOpacity(m_opacity);
+ layer->setPosition(m_position);
+ layer->setIsContainerForFixedPositionLayers(m_isContainerForFixedPositionLayers);
+ layer->setFixedToContainerLayer(m_fixedToContainerLayer);
+ layer->setPreserves3D(preserves3D());
+ layer->setUseParentBackfaceVisibility(m_useParentBackfaceVisibility);
+ layer->setScrollPosition(m_scrollPosition);
+ layer->setMaxScrollPosition(m_maxScrollPosition);
+ layer->setSublayerTransform(m_sublayerTransform);
+ if (!transformIsAnimating())
+ layer->setTransform(m_transform);
+
+ // If the main thread commits multiple times before the impl thread actually draws, then damage tracking
+ // will become incorrect if we simply clobber the updateRect here. The CCLayerImpl's updateRect needs to
+ // accumulate (i.e. union) any update changes that have occurred on the main thread.
+ m_updateRect.uniteIfNonZero(layer->updateRect());
+ layer->setUpdateRect(m_updateRect);
+
+ layer->setScrollDelta(layer->scrollDelta() - layer->sentScrollDelta());
+ layer->setSentScrollDelta(IntSize());
+
+ layer->setStackingOrderChanged(m_stackingOrderChanged);
+
+ if (maskLayer())
+ maskLayer()->pushPropertiesTo(layer->maskLayer());
+ if (replicaLayer())
+ replicaLayer()->pushPropertiesTo(layer->replicaLayer());
+
+ m_layerAnimationController->pushAnimationUpdatesTo(layer->layerAnimationController());
+
+ // Reset any state that should be cleared for the next update.
+ m_stackingOrderChanged = false;
+ m_updateRect = FloatRect();
+}
+
+PassOwnPtr<CCLayerImpl> LayerChromium::createCCLayerImpl()
+{
+ return CCLayerImpl::create(m_layerId);
+}
+
+void LayerChromium::setDebugBorderColor(SkColor color)
+{
+ m_debugBorderColor = color;
+ setNeedsCommit();
+}
+
+void LayerChromium::setDebugBorderWidth(float width)
+{
+ m_debugBorderWidth = width;
+ setNeedsCommit();
+}
+
+void LayerChromium::setDebugName(const String& debugName)
+{
+ m_debugName = debugName;
+ setNeedsCommit();
+}
+
+void LayerChromium::setContentsScale(float contentsScale)
+{
+ if (!needsContentsScale() || m_contentsScale == contentsScale)
+ return;
+ m_contentsScale = contentsScale;
+ setNeedsDisplay();
+}
+
+void LayerChromium::createRenderSurface()
+{
+ ASSERT(!m_renderSurface);
+ m_renderSurface = adoptPtr(new RenderSurfaceChromium(this));
+ setRenderTarget(this);
+}
+
+bool LayerChromium::descendantDrawsContent()
+{
+ for (size_t i = 0; i < m_children.size(); ++i) {
+ if (m_children[i]->drawsContent() || m_children[i]->descendantDrawsContent())
+ return true;
+ }
+ return false;
+}
+
+void LayerChromium::setOpacityFromAnimation(float opacity)
+{
+ // This is called due to an ongoing accelerated animation. Since this animation is
+ // also being run on the impl thread, there is no need to request a commit to push
+ // this value over, so set the value directly rather than calling setOpacity.
+ m_opacity = opacity;
+}
+
+void LayerChromium::setTransformFromAnimation(const WebTransformationMatrix& transform)
+{
+ // This is called due to an ongoing accelerated animation. Since this animation is
+ // also being run on the impl thread, there is no need to request a commit to push
+ // this value over, so set this value directly rather than calling setTransform.
+ m_transform = transform;
+}
+
+bool LayerChromium::addAnimation(PassOwnPtr<CCActiveAnimation> animation)
+{
+ if (!CCSettings::acceleratedAnimationEnabled())
+ return false;
+
+ m_layerAnimationController->addAnimation(animation);
+ if (m_layerTreeHost) {
+ m_layerTreeHost->didAddAnimation();
+ setNeedsCommit();
+ }
+ return true;
+}
+
+void LayerChromium::pauseAnimation(int animationId, double timeOffset)
+{
+ m_layerAnimationController->pauseAnimation(animationId, timeOffset);
+ setNeedsCommit();
+}
+
+void LayerChromium::removeAnimation(int animationId)
+{
+ m_layerAnimationController->removeAnimation(animationId);
+ setNeedsCommit();
+}
+
+void LayerChromium::suspendAnimations(double monotonicTime)
+{
+ m_layerAnimationController->suspendAnimations(monotonicTime);
+ setNeedsCommit();
+}
+
+void LayerChromium::resumeAnimations(double monotonicTime)
+{
+ m_layerAnimationController->resumeAnimations(monotonicTime);
+ setNeedsCommit();
+}
+
+void LayerChromium::setLayerAnimationController(PassOwnPtr<CCLayerAnimationController> layerAnimationController)
+{
+ m_layerAnimationController = layerAnimationController;
+ if (m_layerAnimationController) {
+ m_layerAnimationController->setClient(this);
+ m_layerAnimationController->setForceSync();
+ }
+ setNeedsCommit();
+}
+
+PassOwnPtr<CCLayerAnimationController> LayerChromium::releaseLayerAnimationController()
+{
+ OwnPtr<CCLayerAnimationController> toReturn = m_layerAnimationController.release();
+ m_layerAnimationController = CCLayerAnimationController::create(this);
+ return toReturn.release();
+}
+
+bool LayerChromium::hasActiveAnimation() const
+{
+ return m_layerAnimationController->hasActiveAnimation();
+}
+
+void LayerChromium::notifyAnimationStarted(const CCAnimationEvent& event, double wallClockTime)
+{
+ m_layerAnimationController->notifyAnimationStarted(event);
+ if (m_layerAnimationDelegate)
+ m_layerAnimationDelegate->notifyAnimationStarted(wallClockTime);
+}
+
+void LayerChromium::notifyAnimationFinished(double wallClockTime)
+{
+ if (m_layerAnimationDelegate)
+ m_layerAnimationDelegate->notifyAnimationFinished(wallClockTime);
+}
+
+Region LayerChromium::visibleContentOpaqueRegion() const
+{
+ if (opaque())
+ return visibleContentRect();
+ return Region();
+}
+
+void sortLayers(Vector<RefPtr<LayerChromium> >::iterator, Vector<RefPtr<LayerChromium> >::iterator, void*)
+{
+ // Currently we don't use z-order to decide what to paint, so there's no need to actually sort LayerChromiums.
+}
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)