summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering/RenderLayerBacking.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/rendering/RenderLayerBacking.cpp')
-rw-r--r--Source/WebCore/rendering/RenderLayerBacking.cpp1070
1 files changed, 725 insertions, 345 deletions
diff --git a/Source/WebCore/rendering/RenderLayerBacking.cpp b/Source/WebCore/rendering/RenderLayerBacking.cpp
index 88be08dfe..955315eef 100644
--- a/Source/WebCore/rendering/RenderLayerBacking.cpp
+++ b/Source/WebCore/rendering/RenderLayerBacking.cpp
@@ -32,6 +32,7 @@
#include "AnimationController.h"
#include "CanvasRenderingContext.h"
#include "CSSPropertyNames.h"
+#include "CachedImage.h"
#include "Chrome.h"
#include "FontCache.h"
#include "FrameView.h"
@@ -41,9 +42,11 @@
#include "HTMLIFrameElement.h"
#include "HTMLMediaElement.h"
#include "HTMLNames.h"
+#include "HTMLPlugInElement.h"
#include "InspectorInstrumentation.h"
#include "KeyframeList.h"
#include "PluginViewBase.h"
+#include "ProgressTracker.h"
#include "RenderApplet.h"
#include "RenderIFrame.h"
#include "RenderImage.h"
@@ -55,7 +58,6 @@
#include "Settings.h"
#include "StyleResolver.h"
#include "TiledBacking.h"
-#include <wtf/CurrentTime.h>
#include <wtf/text/StringBuilder.h>
#if ENABLE(CSS_FILTERS)
@@ -75,8 +77,6 @@ namespace WebCore {
using namespace HTMLNames;
-static bool hasBoxDecorations(const RenderStyle*);
-static bool hasBoxDecorationsOrBackground(const RenderObject*);
static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle*);
static IntRect clipBox(RenderBox* renderer);
@@ -94,18 +94,31 @@ static inline bool isAcceleratedCanvas(RenderObject* renderer)
return false;
}
+// Get the scrolling coordinator in a way that works inside RenderLayerBacking's destructor.
+static ScrollingCoordinator* scrollingCoordinatorFromLayer(RenderLayer* layer)
+{
+ Page* page = layer->renderer()->frame()->page();
+ if (!page)
+ return 0;
+
+ return page->scrollingCoordinator();
+}
+
bool RenderLayerBacking::m_creatingPrimaryGraphicsLayer = false;
RenderLayerBacking::RenderLayerBacking(RenderLayer* layer)
: m_owningLayer(layer)
, m_scrollLayerID(0)
, m_artificiallyInflatedBounds(false)
+ , m_boundsConstrainedByClipping(false)
, m_isMainFrameRenderViewLayer(false)
, m_usingTiledCacheLayer(false)
, m_requiresOwnBackingStore(true)
#if ENABLE(CSS_FILTERS)
, m_canCompositeFilters(false)
#endif
+ , m_backgroundLayerPaintsFixedRootBackground(false)
+ , m_didSwitchToFullTileCoverageDuringLoading(false)
{
if (layer->isRootLayer()) {
Frame* frame = toRenderView(renderer())->frameView()->frame();
@@ -127,9 +140,13 @@ RenderLayerBacking::RenderLayerBacking(RenderLayer* layer)
TiledBacking* tiledBacking = this->tiledBacking();
if (Page* page = renderer()->frame()->page()) {
Frame* frame = renderer()->frame();
- tiledBacking->setIsInWindow(page->isOnscreen());
+ tiledBacking->setIsInWindow(page->isInWindow());
+
+ if (m_isMainFrameRenderViewLayer)
+ tiledBacking->setUnparentsOffscreenTiles(true);
+
tiledBacking->setScrollingPerformanceLoggingEnabled(frame->settings() && frame->settings()->scrollingPerformanceLoggingEnabled());
- adjustTileCacheCoverage();
+ adjustTiledBackingCoverage();
}
}
}
@@ -139,17 +156,26 @@ RenderLayerBacking::~RenderLayerBacking()
updateClippingLayers(false, false);
updateOverflowControlsLayers(false, false, false);
updateForegroundLayer(false);
+ updateBackgroundLayer(false);
updateMaskLayer(false);
updateScrollingLayers(false);
detachFromScrollingCoordinator();
destroyGraphicsLayers();
}
+void RenderLayerBacking::willDestroyLayer(const GraphicsLayer* layer)
+{
+ if (layer && layer->usingTiledBacking()) {
+ if (RenderLayerCompositor* compositor = this->compositor())
+ compositor->layerTiledBackingUsageChanged(layer, false);
+ }
+}
+
PassOwnPtr<GraphicsLayer> RenderLayerBacking::createGraphicsLayer(const String& name)
{
GraphicsLayerFactory* graphicsLayerFactory = 0;
if (Page* page = renderer()->frame()->page())
- graphicsLayerFactory = page->chrome()->client()->graphicsLayerFactory();
+ graphicsLayerFactory = page->chrome().client()->graphicsLayerFactory();
OwnPtr<GraphicsLayer> graphicsLayer = GraphicsLayer::create(graphicsLayerFactory, this);
@@ -167,39 +193,61 @@ PassOwnPtr<GraphicsLayer> RenderLayerBacking::createGraphicsLayer(const String&
return graphicsLayer.release();
}
-bool RenderLayerBacking::shouldUseTileCache(const GraphicsLayer*) const
+bool RenderLayerBacking::shouldUseTiledBacking(const GraphicsLayer*) const
{
return m_usingTiledCacheLayer && m_creatingPrimaryGraphicsLayer;
}
+void RenderLayerBacking::tiledBackingUsageChanged(const GraphicsLayer* layer, bool usingTiledBacking)
+{
+ compositor()->layerTiledBackingUsageChanged(layer, usingTiledBacking);
+}
+
TiledBacking* RenderLayerBacking::tiledBacking() const
{
return m_graphicsLayer->tiledBacking();
}
-void RenderLayerBacking::adjustTileCacheCoverage()
+static TiledBacking::TileCoverage computeTileCoverage(RenderLayerBacking* backing)
{
- if (!m_usingTiledCacheLayer)
- return;
+ // FIXME: When we use TiledBacking for overflow, this should look at RenderView scrollability.
+ Frame* frame = backing->owningLayer()->renderer()->frame();
+ if (!frame)
+ return TiledBacking::CoverageForVisibleArea;
TiledBacking::TileCoverage tileCoverage = TiledBacking::CoverageForVisibleArea;
-
- // FIXME: When we use TiledBacking for overflow, this should look at RenderView scrollability.
- Frame* frame = renderer()->frame();
- if (frame) {
- FrameView* frameView = frame->view();
- if (frameView->horizontalScrollbarMode() != ScrollbarAlwaysOff)
+ FrameView* frameView = frame->view();
+ bool useMinimalTilesDuringLiveResize = frameView->inLiveResize();
+ bool useMinimalTilesDuringLoading = false;
+ // Avoid churn.
+ if (!backing->didSwitchToFullTileCoverageDuringLoading()) {
+ useMinimalTilesDuringLoading = !frameView->isVisuallyNonEmpty() || (frame->page()->progress()->isMainLoadProgressing() && !frameView->wasScrolledByUser());
+ if (!useMinimalTilesDuringLoading)
+ backing->setDidSwitchToFullTileCoverageDuringLoading();
+ }
+ if (!(useMinimalTilesDuringLoading || useMinimalTilesDuringLiveResize)) {
+ bool clipsToExposedRect = backing->tiledBacking()->clipsToExposedRect();
+ if (frameView->horizontalScrollbarMode() != ScrollbarAlwaysOff || clipsToExposedRect)
tileCoverage |= TiledBacking::CoverageForHorizontalScrolling;
- if (frameView->verticalScrollbarMode() != ScrollbarAlwaysOff)
+ if (frameView->verticalScrollbarMode() != ScrollbarAlwaysOff || clipsToExposedRect)
tileCoverage |= TiledBacking::CoverageForVerticalScrolling;
-
- if (ScrollingCoordinator* scrollingCoordinator = frame->page()->scrollingCoordinator()) {
- if (scrollingCoordinator->shouldUpdateScrollLayerPositionOnMainThread())
- tileCoverage |= TiledBacking::CoverageForSlowScrolling;
- }
}
+ if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(backing->owningLayer())) {
+ // Ask our TiledBacking for large tiles unless the only reason we're main-thread-scrolling
+ // is a page overlay (find-in-page, the Web Inspector highlight mechanism, etc.).
+ if (scrollingCoordinator->mainThreadScrollingReasons() & ~ScrollingCoordinator::ForcedOnMainThread)
+ tileCoverage |= TiledBacking::CoverageForSlowScrolling;
+ }
+ return tileCoverage;
+}
+
+void RenderLayerBacking::adjustTiledBackingCoverage()
+{
+ if (!m_usingTiledCacheLayer)
+ return;
+ TiledBacking::TileCoverage tileCoverage = computeTileCoverage(this);
tiledBacking()->setTileCoverage(tileCoverage);
}
@@ -215,6 +263,14 @@ void RenderLayerBacking::updateDebugIndicators(bool showBorder, bool showRepaint
m_foregroundLayer->setShowDebugBorder(showBorder);
m_foregroundLayer->setShowRepaintCounter(showRepaintCounter);
}
+
+ if (m_contentsContainmentLayer)
+ m_contentsContainmentLayer->setShowDebugBorder(showBorder);
+
+ if (m_backgroundLayer) {
+ m_backgroundLayer->setShowDebugBorder(showBorder);
+ m_backgroundLayer->setShowRepaintCounter(showRepaintCounter);
+ }
if (m_maskLayer) {
m_maskLayer->setShowDebugBorder(showBorder);
@@ -243,11 +299,11 @@ void RenderLayerBacking::createPrimaryGraphicsLayer()
{
String layerName;
#ifndef NDEBUG
- layerName = nameForLayer();
+ layerName = m_owningLayer->name();
#endif
// The call to createGraphicsLayer ends calling back into here as
- // a GraphicsLayerClient to ask if it shouldUseTileCache(). We only want
+ // a GraphicsLayerClient to ask if it shouldUseTiledBacking(). We only want
// the tile cache on our main layer. This is pretty ugly, but saves us from
// exposing the API to all clients.
@@ -256,14 +312,10 @@ void RenderLayerBacking::createPrimaryGraphicsLayer()
m_creatingPrimaryGraphicsLayer = false;
if (m_usingTiledCacheLayer)
- m_containmentLayer = createGraphicsLayer("TileCache Flattening Layer");
+ m_childContainmentLayer = createGraphicsLayer("TiledBacking Flattening Layer");
if (m_isMainFrameRenderViewLayer) {
- bool isTransparent = false;
- if (FrameView* frameView = toRenderView(renderer())->frameView())
- isTransparent = frameView->isTransparent();
-
- m_graphicsLayer->setContentsOpaque(!isTransparent);
+ m_graphicsLayer->setContentsOpaque(true);
m_graphicsLayer->setAppliesPageScale();
}
@@ -287,12 +339,17 @@ void RenderLayerBacking::createPrimaryGraphicsLayer()
void RenderLayerBacking::destroyGraphicsLayers()
{
- if (m_graphicsLayer)
+ if (m_graphicsLayer) {
+ willDestroyLayer(m_graphicsLayer.get());
m_graphicsLayer->removeFromParent();
+ }
+ m_ancestorClippingLayer = nullptr;
+ m_contentsContainmentLayer = nullptr;
m_graphicsLayer = nullptr;
m_foregroundLayer = nullptr;
- m_containmentLayer = nullptr;
+ m_backgroundLayer = nullptr;
+ m_childContainmentLayer = nullptr;
m_maskLayer = nullptr;
m_scrollingLayer = nullptr;
@@ -314,7 +371,11 @@ void RenderLayerBacking::updateTransform(const RenderStyle* style)
makeMatrixRenderable(t, compositor()->canRender3DTransforms());
}
- m_graphicsLayer->setTransform(t);
+ if (m_contentsContainmentLayer) {
+ m_contentsContainmentLayer->setTransform(t);
+ m_graphicsLayer->setTransform(TransformationMatrix());
+ } else
+ m_graphicsLayer->setTransform(t);
}
#if ENABLE(CSS_FILTERS)
@@ -340,7 +401,7 @@ static bool hasNonZeroTransformOrigin(const RenderObject* renderer)
static bool layerOrAncestorIsTransformedOrUsingCompositedScrolling(RenderLayer* layer)
{
for (RenderLayer* curr = layer; curr; curr = curr->parent()) {
- if (curr->hasTransform() || curr->usesCompositedScrolling())
+ if (curr->hasTransform() || curr->needsCompositedScrolling())
return true;
}
@@ -354,9 +415,6 @@ bool RenderLayerBacking::shouldClipCompositedBounds() const
return false;
if (m_usingTiledCacheLayer)
- return true;
-
- if (!compositor()->compositingConsultsOverlap())
return false;
if (layerOrAncestorIsTransformedOrUsingCompositedScrolling(m_owningLayer))
@@ -365,10 +423,9 @@ bool RenderLayerBacking::shouldClipCompositedBounds() const
return true;
}
-
void RenderLayerBacking::updateCompositedBounds()
{
- IntRect layerBounds = compositor()->calculateCompositedBounds(m_owningLayer, m_owningLayer);
+ LayoutRect layerBounds = compositor()->calculateCompositedBounds(m_owningLayer, m_owningLayer);
// Clip to the size of the document or enclosing overflow-scroll layer.
// If this or an ancestor is transformed, we can't currently compute the correct rect to intersect with.
@@ -377,18 +434,23 @@ void RenderLayerBacking::updateCompositedBounds()
RenderView* view = m_owningLayer->renderer()->view();
RenderLayer* rootLayer = view->layer();
- // Start by clipping to the view's bounds.
- LayoutRect clippingBounds = view->unscaledDocumentRect();
+ LayoutRect clippingBounds;
+ if (renderer()->style()->position() == FixedPosition && renderer()->container() == view)
+ clippingBounds = view->frameView()->viewportConstrainedVisibleContentRect();
+ else
+ clippingBounds = view->unscaledDocumentRect();
if (m_owningLayer != rootLayer)
clippingBounds.intersect(m_owningLayer->backgroundClipRect(RenderLayer::ClipRectsContext(rootLayer, 0, AbsoluteClipRects)).rect()); // FIXME: Incorrect for CSS regions.
LayoutPoint delta;
- m_owningLayer->convertToLayerCoords(rootLayer, delta);
+ m_owningLayer->convertToLayerCoords(rootLayer, delta, RenderLayer::AdjustForColumns);
clippingBounds.move(-delta.x(), -delta.y());
- layerBounds.intersect(pixelSnappedIntRect(clippingBounds));
- }
+ layerBounds.intersect(clippingBounds);
+ m_boundsConstrainedByClipping = true;
+ } else
+ m_boundsConstrainedByClipping = false;
// If the element has a transform-origin that has fixed lengths, and the renderer has zero size,
// then we need to ensure that the compositing layer has non-zero size so that we can apply
@@ -408,12 +470,12 @@ void RenderLayerBacking::updateAfterWidgetResize()
if (renderer()->isRenderPart()) {
if (RenderLayerCompositor* innerCompositor = RenderLayerCompositor::frameContentsCompositor(toRenderPart(renderer()))) {
innerCompositor->frameViewDidChangeSize();
- innerCompositor->frameViewDidChangeLocation(contentsBox().location());
+ innerCompositor->frameViewDidChangeLocation(flooredIntPoint(contentsBox().location()));
}
}
}
-void RenderLayerBacking::updateAfterLayout(UpdateDepth updateDepth, bool isUpdateRoot)
+void RenderLayerBacking::updateAfterLayout(UpdateAfterLayoutFlags flags)
{
RenderLayerCompositor* layerCompositor = compositor();
if (!layerCompositor->compositingLayersNeedRebuild()) {
@@ -425,13 +487,19 @@ void RenderLayerBacking::updateAfterLayout(UpdateDepth updateDepth, bool isUpdat
// The solution is to update compositing children of this layer here,
// via updateCompositingChildrenGeometry().
updateCompositedBounds();
- layerCompositor->updateCompositingDescendantGeometry(m_owningLayer, m_owningLayer, updateDepth);
+ layerCompositor->updateCompositingDescendantGeometry(m_owningLayer, m_owningLayer, flags & CompositingChildrenOnly);
- if (isUpdateRoot) {
+ if (flags & IsUpdateRoot) {
updateGraphicsLayerGeometry();
layerCompositor->updateRootLayerPosition();
+ RenderLayer* stackingContainer = m_owningLayer->enclosingStackingContainer();
+ if (!layerCompositor->compositingLayersNeedRebuild() && stackingContainer && (stackingContainer != m_owningLayer))
+ layerCompositor->updateCompositingDescendantGeometry(stackingContainer, stackingContainer, flags & CompositingChildrenOnly);
}
}
+
+ if (flags & NeedsFullRepaint && !paintsIntoWindow() && !paintsIntoCompositedAncestor())
+ setContentsNeedDisplay();
}
bool RenderLayerBacking::updateGraphicsLayerConfiguration()
@@ -439,16 +507,23 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration()
RenderLayerCompositor* compositor = this->compositor();
RenderObject* renderer = this->renderer();
+ m_owningLayer->updateDescendantDependentFlags();
m_owningLayer->updateZOrderLists();
bool layerConfigChanged = false;
+ setBackgroundLayerPaintsFixedRootBackground(compositor->needsFixedRootBackgroundLayer(m_owningLayer));
+
+ // The background layer is currently only used for fixed root backgrounds.
+ if (updateBackgroundLayer(m_backgroundLayerPaintsFixedRootBackground))
+ layerConfigChanged = true;
+
if (updateForegroundLayer(compositor->needsContentsCompositingLayer(m_owningLayer)))
layerConfigChanged = true;
bool needsDescendentsClippingLayer = compositor->clipsCompositingDescendants(m_owningLayer);
// Our scrolling layer will clip.
- if (m_owningLayer->usesCompositedScrolling())
+ if (m_owningLayer->needsCompositedScrolling())
needsDescendentsClippingLayer = false;
if (updateClippingLayers(compositor->clippedByAncestor(m_owningLayer), needsDescendentsClippingLayer))
@@ -457,7 +532,7 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration()
if (updateOverflowControlsLayers(requiresHorizontalScrollbarLayer(), requiresVerticalScrollbarLayer(), requiresScrollCornerLayer()))
layerConfigChanged = true;
- if (updateScrollingLayers(m_owningLayer->usesCompositedScrolling()))
+ if (updateScrollingLayers(m_owningLayer->needsCompositedScrolling()))
layerConfigChanged = true;
if (layerConfigChanged)
@@ -479,16 +554,23 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration()
} else
m_graphicsLayer->setReplicatedByLayer(0);
+ bool isSimpleContainer = isSimpleContainerCompositingLayer();
+ bool didUpdateContentsRect = false;
+ updateDirectlyCompositedContents(isSimpleContainer, didUpdateContentsRect);
+
+ updateRootLayerConfiguration();
+
if (isDirectlyCompositedImage())
updateImageContents();
if (renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->allowsAcceleratedCompositing()) {
- PluginViewBase* pluginViewBase = static_cast<PluginViewBase*>(toRenderWidget(renderer)->widget());
- m_graphicsLayer->setContentsToMedia(pluginViewBase->platformLayer());
+ PluginViewBase* pluginViewBase = toPluginViewBase(toRenderWidget(renderer)->widget());
+ if (!pluginViewBase->shouldNotAddLayer())
+ m_graphicsLayer->setContentsToMedia(pluginViewBase->platformLayer());
}
#if ENABLE(VIDEO)
else if (renderer->isVideo()) {
- HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(renderer->node());
+ HTMLMediaElement* mediaElement = toHTMLMediaElement(renderer->node());
m_graphicsLayer->setContentsToMedia(mediaElement->platformLayer());
}
#endif
@@ -500,19 +582,6 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration()
layerConfigChanged = true;
}
#endif
-#if ENABLE(FULLSCREEN_API)
- else if (renderer->isRenderFullScreen()) {
- // RenderFullScreen renderers have no content, and only a solid
- // background color. They also can be large enough to trigger the
- // creation of a tiled-layer, which can cause flashing problems
- // during repainting. Special case the RenderFullScreen case because
- // we know its style does not come from CSS and it is therefore will
- // not contain paintable content (e.g. background images, gradients,
- // etc), so safe to set the layer's background color to the renderer's
- // style's background color.
- updateBackgroundColor();
- }
-#endif
if (renderer->isRenderPart())
layerConfigChanged = RenderLayerCompositor::parentFrameContentLayers(toRenderPart(renderer));
@@ -534,7 +603,7 @@ static IntRect clipBox(RenderBox* renderer)
void RenderLayerBacking::updateGraphicsLayerGeometry()
{
// If we haven't built z-order lists yet, wait until later.
- if (m_owningLayer->isStackingContext() && m_owningLayer->m_zOrderListsDirty)
+ if (m_owningLayer->isStackingContainer() && m_owningLayer->m_zOrderListsDirty)
return;
// Set transform property, if it is not animating. We have to do this here because the transform
@@ -553,6 +622,8 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
#if ENABLE(CSS_COMPOSITING)
updateLayerBlendMode(renderer()->style());
#endif
+
+ bool isSimpleContainer = isSimpleContainerCompositingLayer();
m_owningLayer->updateDescendantDependentFlags();
@@ -562,26 +633,11 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
m_graphicsLayer->setContentsVisible(m_owningLayer->hasVisibleContent() || hasVisibleNonCompositingDescendantLayers());
RenderStyle* style = renderer()->style();
- m_graphicsLayer->setPreserves3D(style->transformStyle3D() == TransformStyle3DPreserve3D && !renderer()->hasReflection());
+ // FIXME: reflections should force transform-style to be flat in the style: https://bugs.webkit.org/show_bug.cgi?id=106959
+ bool preserves3D = style->transformStyle3D() == TransformStyle3DPreserve3D && !renderer()->hasReflection();
+ m_graphicsLayer->setPreserves3D(preserves3D);
m_graphicsLayer->setBackfaceVisibility(style->backfaceVisibility() == BackfaceVisibilityVisible);
- // Register fixed position layers and their containers with the scrolling coordinator.
- if (Page* page = renderer()->frame()->page()) {
- if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) {
- if (style->position() == FixedPosition || compositor()->fixedPositionedByAncestor(m_owningLayer))
- scrollingCoordinator->setLayerIsFixedToContainerLayer(childForSuperlayers(), true);
- else {
- if (m_ancestorClippingLayer)
- scrollingCoordinator->setLayerIsFixedToContainerLayer(m_ancestorClippingLayer.get(), false);
- scrollingCoordinator->setLayerIsFixedToContainerLayer(m_graphicsLayer.get(), false);
- }
- // Page scale is applied as a transform on the root render view layer. Because the scroll
- // layer is further up in the hierarchy, we need to avoid marking the root render view
- // layer as a container.
- bool isContainer = m_owningLayer->hasTransform() && !m_owningLayer->isRootLayer();
- scrollingCoordinator->setLayerIsContainerForFixedPositionLayers(childForSuperlayers(), isContainer);
- }
- }
RenderLayer* compAncestor = m_owningLayer->ancestorCompositingLayer();
// We compute everything relative to the enclosing compositing layer.
@@ -591,11 +647,16 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
ancestorCompositingBounds = pixelSnappedIntRect(compAncestor->backing()->compositedBounds());
}
- IntRect localCompositingBounds = pixelSnappedIntRect(compositedBounds());
+ LayoutRect localRawCompositingBounds = compositedBounds();
+ LayoutPoint rawDelta;
+ m_owningLayer->convertToLayerCoords(compAncestor, rawDelta, RenderLayer::AdjustForColumns);
+ IntPoint delta = flooredIntPoint(rawDelta);
+ m_subpixelAccumulation = toLayoutSize(rawDelta.fraction());
+ // Move the bounds by the subpixel accumulation so that it pixel-snaps relative to absolute pixels instead of local coordinates.
+ localRawCompositingBounds.move(m_subpixelAccumulation);
+ IntRect localCompositingBounds = pixelSnappedIntRect(localRawCompositingBounds);
IntRect relativeCompositingBounds(localCompositingBounds);
- IntPoint delta;
- m_owningLayer->convertToPixelSnappedLayerCoords(compAncestor, delta);
relativeCompositingBounds.moveBy(delta);
IntPoint graphicsLayerParentLocation;
@@ -609,7 +670,7 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
else
graphicsLayerParentLocation = renderer()->view()->documentRect().location();
- if (compAncestor && compAncestor->usesCompositedScrolling()) {
+ if (compAncestor && compAncestor->needsCompositedScrolling()) {
RenderBox* renderBox = toRenderBox(compAncestor->renderer());
IntSize scrollOffset = compAncestor->scrolledContentOffset();
IntPoint scrollOrigin(renderBox->borderLeft(), renderBox->borderTop());
@@ -620,10 +681,10 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
// Call calculateRects to get the backgroundRect which is what is used to clip the contents of this
// layer. Note that we call it with temporaryClipRects = true because normally when computing clip rects
// for a compositing layer, rootLayer is the layer itself.
- RenderLayer::ClipRectsContext clipRectsContext(compAncestor, 0, TemporaryClipRects, IgnoreOverlayScrollbarSize, RenderLayer::IgnoreOverflowClip);
+ RenderLayer::ClipRectsContext clipRectsContext(compAncestor, 0, TemporaryClipRects, IgnoreOverlayScrollbarSize, IgnoreOverflowClip);
IntRect parentClipRect = pixelSnappedIntRect(m_owningLayer->backgroundClipRect(clipRectsContext).rect()); // FIXME: Incorrect for CSS regions.
ASSERT(parentClipRect != PaintInfo::infiniteRect());
- m_ancestorClippingLayer->setPosition(FloatPoint() + (parentClipRect.location() - graphicsLayerParentLocation));
+ m_ancestorClippingLayer->setPosition(FloatPoint(parentClipRect.location() - graphicsLayerParentLocation));
m_ancestorClippingLayer->setSize(parentClipRect.size());
// backgroundRect is relative to compAncestor, so subtract deltaX/deltaY to get back to local coords.
@@ -633,26 +694,41 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
graphicsLayerParentLocation = parentClipRect.location();
}
- m_graphicsLayer->setPosition(FloatPoint() + (relativeCompositingBounds.location() - graphicsLayerParentLocation));
- m_graphicsLayer->setOffsetFromRenderer(localCompositingBounds.location() - IntPoint());
+ FloatSize contentsSize = relativeCompositingBounds.size();
+ if (m_contentsContainmentLayer) {
+ m_contentsContainmentLayer->setPreserves3D(preserves3D);
+ m_contentsContainmentLayer->setPosition(FloatPoint(relativeCompositingBounds.location() - graphicsLayerParentLocation));
+ // Use the same size as m_graphicsLayer so transforms behave correctly.
+ m_contentsContainmentLayer->setSize(contentsSize);
+ graphicsLayerParentLocation = relativeCompositingBounds.location();
+ }
+
+ m_graphicsLayer->setPosition(FloatPoint(relativeCompositingBounds.location() - graphicsLayerParentLocation));
+ m_graphicsLayer->setOffsetFromRenderer(toIntSize(localCompositingBounds.location()));
+
FloatSize oldSize = m_graphicsLayer->size();
- FloatSize newSize = relativeCompositingBounds.size();
- if (oldSize != newSize) {
- m_graphicsLayer->setSize(newSize);
- // A bounds change will almost always require redisplay. Usually that redisplay
- // will happen because of a repaint elsewhere, but not always:
- // e.g. see RenderView::setMaximalOutlineSize()
- m_graphicsLayer->setNeedsDisplay();
+ if (oldSize != contentsSize) {
+ m_graphicsLayer->setSize(contentsSize);
+ // Usually invalidation will happen via layout etc, but if we've affected the layer
+ // size by constraining relative to a clipping ancestor or the viewport, we
+ // have to invalidate to avoid showing stretched content.
+ if (m_boundsConstrainedByClipping)
+ m_graphicsLayer->setNeedsDisplay();
+ }
+ if (!m_isMainFrameRenderViewLayer) {
+ // For non-root layers, background is always painted by the primary graphics layer.
+ ASSERT(!m_backgroundLayer);
+ m_graphicsLayer->setContentsOpaque(m_owningLayer->backgroundIsKnownToBeOpaqueInRect(localCompositingBounds));
}
// If we have a layer that clips children, position it.
IntRect clippingBox;
if (GraphicsLayer* clipLayer = clippingLayer()) {
clippingBox = clipBox(toRenderBox(renderer()));
- clipLayer->setPosition(FloatPoint() + (clippingBox.location() - localCompositingBounds.location()));
+ clipLayer->setPosition(FloatPoint(clippingBox.location() - localCompositingBounds.location()));
clipLayer->setSize(clippingBox.size());
- clipLayer->setOffsetFromRenderer(clippingBox.location() - IntPoint());
+ clipLayer->setOffsetFromRenderer(toIntSize(clippingBox.location()));
}
if (m_maskLayer) {
@@ -668,7 +744,7 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
const IntRect borderBox = toRenderBox(renderer())->pixelSnappedBorderBoxRect();
// Get layout bounds in the coords of compAncestor to match relativeCompositingBounds.
- IntRect layerBounds = IntRect(delta, borderBox.size());
+ IntRect layerBounds(delta, borderBox.size());
// Update properties that depend on layer dimensions
FloatPoint3D transformOrigin = computeTransformOrigin(borderBox);
@@ -676,7 +752,10 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
FloatPoint3D anchor(relativeCompositingBounds.width() != 0.0f ? ((layerBounds.x() - relativeCompositingBounds.x()) + transformOrigin.x()) / relativeCompositingBounds.width() : 0.5f,
relativeCompositingBounds.height() != 0.0f ? ((layerBounds.y() - relativeCompositingBounds.y()) + transformOrigin.y()) / relativeCompositingBounds.height() : 0.5f,
transformOrigin.z());
- m_graphicsLayer->setAnchorPoint(anchor);
+ if (m_contentsContainmentLayer)
+ m_contentsContainmentLayer->setAnchorPoint(anchor);
+ else
+ m_graphicsLayer->setAnchorPoint(anchor);
RenderStyle* style = renderer()->style();
GraphicsLayer* clipLayer = clippingLayer();
@@ -697,17 +776,19 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
}
} else {
m_graphicsLayer->setAnchorPoint(FloatPoint3D(0.5f, 0.5f, 0));
+ if (m_contentsContainmentLayer)
+ m_contentsContainmentLayer->setAnchorPoint(FloatPoint3D(0.5f, 0.5f, 0));
}
if (m_foregroundLayer) {
FloatPoint foregroundPosition;
- FloatSize foregroundSize = newSize;
+ FloatSize foregroundSize = contentsSize;
IntSize foregroundOffset = m_graphicsLayer->offsetFromRenderer();
if (hasClippingLayer()) {
// If we have a clipping layer (which clips descendants), then the foreground layer is a child of it,
// so that it gets correctly sorted with children. In that case, position relative to the clipping layer.
foregroundSize = FloatSize(clippingBox.size());
- foregroundOffset = clippingBox.location() - IntPoint();
+ foregroundOffset = toIntSize(clippingBox.location());
}
m_foregroundLayer->setPosition(foregroundPosition);
@@ -718,6 +799,22 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
m_foregroundLayer->setOffsetFromRenderer(foregroundOffset);
}
+ if (m_backgroundLayer) {
+ FloatPoint backgroundPosition;
+ FloatSize backgroundSize = contentsSize;
+ if (backgroundLayerPaintsFixedRootBackground()) {
+ FrameView* frameView = toRenderView(renderer())->frameView();
+ backgroundPosition = IntPoint(frameView->scrollOffsetForFixedPosition());
+ backgroundSize = frameView->visibleContentRect().size();
+ }
+ m_backgroundLayer->setPosition(backgroundPosition);
+ if (backgroundSize != m_backgroundLayer->size()) {
+ m_backgroundLayer->setSize(backgroundSize);
+ m_backgroundLayer->setNeedsDisplay();
+ }
+ m_backgroundLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
+ }
+
if (m_owningLayer->reflectionLayer() && m_owningLayer->reflectionLayer()->isComposited()) {
RenderLayerBacking* reflectionBacking = m_owningLayer->reflectionLayer()->backing();
reflectionBacking->updateGraphicsLayerGeometry();
@@ -726,22 +823,22 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
// but the reflected layer is the bounds of this layer, so we need to position it appropriately.
FloatRect layerBounds = compositedBounds();
FloatRect reflectionLayerBounds = reflectionBacking->compositedBounds();
- reflectionBacking->graphicsLayer()->setReplicatedLayerPosition(FloatPoint() + (layerBounds.location() - reflectionLayerBounds.location()));
+ reflectionBacking->graphicsLayer()->setReplicatedLayerPosition(FloatPoint(layerBounds.location() - reflectionLayerBounds.location()));
}
if (m_scrollingLayer) {
ASSERT(m_scrollingContentsLayer);
RenderBox* renderBox = toRenderBox(renderer());
IntRect paddingBox(renderBox->borderLeft(), renderBox->borderTop(), renderBox->width() - renderBox->borderLeft() - renderBox->borderRight(), renderBox->height() - renderBox->borderTop() - renderBox->borderBottom());
- IntSize scrollOffset = m_owningLayer->scrolledContentOffset();
+ IntSize scrollOffset = m_owningLayer->scrollOffset();
- m_scrollingLayer->setPosition(FloatPoint() + (paddingBox.location() - localCompositingBounds.location()));
+ m_scrollingLayer->setPosition(FloatPoint(paddingBox.location() - localCompositingBounds.location()));
m_scrollingLayer->setSize(paddingBox.size());
m_scrollingContentsLayer->setPosition(FloatPoint(-scrollOffset.width(), -scrollOffset.height()));
IntSize oldScrollingLayerOffset = m_scrollingLayer->offsetFromRenderer();
- m_scrollingLayer->setOffsetFromRenderer(IntPoint() - paddingBox.location());
+ m_scrollingLayer->setOffsetFromRenderer(-toIntSize(paddingBox.location()));
bool paddingBoxOffsetChanged = oldScrollingLayerOffset != m_scrollingLayer->offsetFromRenderer();
@@ -749,41 +846,96 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
if (scrollSize != m_scrollingContentsLayer->size() || paddingBoxOffsetChanged)
m_scrollingContentsLayer->setNeedsDisplay();
- IntSize scrollingContentsOffset = paddingBox.location() - IntPoint() - scrollOffset;
+ IntSize scrollingContentsOffset = toIntSize(paddingBox.location() - scrollOffset);
if (scrollingContentsOffset != m_scrollingContentsLayer->offsetFromRenderer() || scrollSize != m_scrollingContentsLayer->size())
compositor()->scrollingLayerDidChange(m_owningLayer);
m_scrollingContentsLayer->setSize(scrollSize);
// FIXME: The paint offset and the scroll offset should really be separate concepts.
m_scrollingContentsLayer->setOffsetFromRenderer(scrollingContentsOffset, GraphicsLayer::DontSetNeedsDisplay);
- }
- m_graphicsLayer->setContentsRect(contentsBox());
+ if (m_foregroundLayer) {
+ if (m_foregroundLayer->size() != m_scrollingContentsLayer->size())
+ m_foregroundLayer->setSize(m_scrollingContentsLayer->size());
+ m_foregroundLayer->setNeedsDisplay();
+ m_foregroundLayer->setOffsetFromRenderer(m_scrollingContentsLayer->offsetFromRenderer());
+ }
+ }
// If this layer was created just for clipping or to apply perspective, it doesn't need its own backing store.
- setRequiresOwnBackingStore(compositor()->requiresOwnBackingStore(m_owningLayer, compAncestor));
+ setRequiresOwnBackingStore(compositor()->requiresOwnBackingStore(m_owningLayer, compAncestor, relativeCompositingBounds, ancestorCompositingBounds));
+
+ bool didUpdateContentsRect = false;
+ updateDirectlyCompositedContents(isSimpleContainer, didUpdateContentsRect);
+ if (!didUpdateContentsRect && m_graphicsLayer->hasContentsLayer())
+ resetContentsRect();
- updateDrawsContent();
+ updateDrawsContent(isSimpleContainer);
updateAfterWidgetResize();
+ registerScrollingLayers();
+}
+
+void RenderLayerBacking::updateDirectlyCompositedContents(bool isSimpleContainer, bool& didUpdateContentsRect)
+{
+ if (!m_owningLayer->hasVisibleContent())
+ return;
+
+ // The order of operations here matters, since the last valid type of contents needs
+ // to also update the contentsRect.
+ updateDirectlyCompositedBackgroundColor(isSimpleContainer, didUpdateContentsRect);
+ updateDirectlyCompositedBackgroundImage(isSimpleContainer, didUpdateContentsRect);
+}
+
+void RenderLayerBacking::registerScrollingLayers()
+{
+ // Register fixed position layers and their containers with the scrolling coordinator.
+ ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer);
+ if (!scrollingCoordinator)
+ return;
+
+ compositor()->updateViewportConstraintStatus(m_owningLayer);
+
+ if (!scrollingCoordinator->supportsFixedPositionLayers())
+ return;
+
+ scrollingCoordinator->updateLayerPositionConstraint(m_owningLayer);
+
+ // Page scale is applied as a transform on the root render view layer. Because the scroll
+ // layer is further up in the hierarchy, we need to avoid marking the root render view
+ // layer as a container.
+ bool isContainer = m_owningLayer->hasTransform() && !m_owningLayer->isRootLayer();
+ scrollingCoordinator->setLayerIsContainerForFixedPositionLayers(childForSuperlayers(), isContainer);
}
void RenderLayerBacking::updateInternalHierarchy()
{
// m_foregroundLayer has to be inserted in the correct order with child layers,
// so it's not inserted here.
- if (m_ancestorClippingLayer) {
+ if (m_ancestorClippingLayer)
m_ancestorClippingLayer->removeAllChildren();
- m_graphicsLayer->removeFromParent();
- m_ancestorClippingLayer->addChild(m_graphicsLayer.get());
+
+ if (m_contentsContainmentLayer) {
+ m_contentsContainmentLayer->removeAllChildren();
+ if (m_ancestorClippingLayer)
+ m_ancestorClippingLayer->addChild(m_contentsContainmentLayer.get());
}
+
+ if (m_backgroundLayer)
+ m_contentsContainmentLayer->addChild(m_backgroundLayer.get());
- if (m_containmentLayer) {
- m_containmentLayer->removeFromParent();
- m_graphicsLayer->addChild(m_containmentLayer.get());
+ m_graphicsLayer->removeFromParent();
+ if (m_contentsContainmentLayer)
+ m_contentsContainmentLayer->addChild(m_graphicsLayer.get());
+ else if (m_ancestorClippingLayer)
+ m_ancestorClippingLayer->addChild(m_graphicsLayer.get());
+
+ if (m_childContainmentLayer) {
+ m_childContainmentLayer->removeFromParent();
+ m_graphicsLayer->addChild(m_childContainmentLayer.get());
}
if (m_scrollingLayer) {
- GraphicsLayer* superlayer = m_containmentLayer ? m_containmentLayer.get() : m_graphicsLayer.get();
+ GraphicsLayer* superlayer = m_childContainmentLayer ? m_childContainmentLayer.get() : m_graphicsLayer.get();
m_scrollingLayer->removeFromParent();
superlayer->addChild(m_scrollingLayer.get());
}
@@ -805,14 +957,27 @@ void RenderLayerBacking::updateInternalHierarchy()
}
}
+void RenderLayerBacking::resetContentsRect()
+{
+ IntRect rect = pixelSnappedIntRect(contentsBox());
+ m_graphicsLayer->setContentsRect(rect);
+ m_graphicsLayer->setContentsTileSize(IntSize());
+ m_graphicsLayer->setContentsTilePhase(IntPoint());
+}
+
void RenderLayerBacking::updateDrawsContent()
{
+ updateDrawsContent(isSimpleContainerCompositingLayer());
+}
+
+void RenderLayerBacking::updateDrawsContent(bool isSimpleContainer)
+{
if (m_scrollingLayer) {
// We don't have to consider overflow controls, because we know that the scrollbars are drawn elsewhere.
// m_graphicsLayer only needs backing store if the non-scrolling parts (background, outlines, borders, shadows etc) need to paint.
// m_scrollingLayer never has backing store.
// m_scrollingContentsLayer only needs backing store if the scrolled contents need to paint.
- bool hasNonScrollingPaintedContent = m_owningLayer->hasVisibleContent() && hasBoxDecorationsOrBackground(renderer());
+ bool hasNonScrollingPaintedContent = m_owningLayer->hasVisibleContent() && m_owningLayer->hasBoxDecorationsOrBackground();
m_graphicsLayer->setDrawsContent(hasNonScrollingPaintedContent);
bool hasScrollingPaintedContent = m_owningLayer->hasVisibleContent() && (renderer()->hasBackground() || paintsChildren());
@@ -820,12 +985,15 @@ void RenderLayerBacking::updateDrawsContent()
return;
}
- bool hasPaintedContent = containsPaintedContent();
+ bool hasPaintedContent = containsPaintedContent(isSimpleContainer);
// FIXME: we could refine this to only allocate backing for one of these layers if possible.
m_graphicsLayer->setDrawsContent(hasPaintedContent);
if (m_foregroundLayer)
m_foregroundLayer->setDrawsContent(hasPaintedContent);
+
+ if (m_backgroundLayer)
+ m_backgroundLayer->setDrawsContent(hasPaintedContent);
}
// Return true if the layers changed.
@@ -840,87 +1008,100 @@ bool RenderLayerBacking::updateClippingLayers(bool needsAncestorClip, bool needs
layersChanged = true;
}
} else if (m_ancestorClippingLayer) {
+ willDestroyLayer(m_ancestorClippingLayer.get());
m_ancestorClippingLayer->removeFromParent();
m_ancestorClippingLayer = nullptr;
layersChanged = true;
}
if (needsDescendantClip) {
- if (!m_containmentLayer && !m_usingTiledCacheLayer) {
- m_containmentLayer = createGraphicsLayer("Child clipping Layer");
- m_containmentLayer->setMasksToBounds(true);
+ if (!m_childContainmentLayer && !m_usingTiledCacheLayer) {
+ m_childContainmentLayer = createGraphicsLayer("Child clipping Layer");
+ m_childContainmentLayer->setMasksToBounds(true);
layersChanged = true;
}
} else if (hasClippingLayer()) {
- m_containmentLayer->removeFromParent();
- m_containmentLayer = nullptr;
+ willDestroyLayer(m_childContainmentLayer.get());
+ m_childContainmentLayer->removeFromParent();
+ m_childContainmentLayer = nullptr;
layersChanged = true;
}
return layersChanged;
}
+void RenderLayerBacking::setBackgroundLayerPaintsFixedRootBackground(bool backgroundLayerPaintsFixedRootBackground)
+{
+ m_backgroundLayerPaintsFixedRootBackground = backgroundLayerPaintsFixedRootBackground;
+}
+
bool RenderLayerBacking::requiresHorizontalScrollbarLayer() const
{
-#if !PLATFORM(CHROMIUM)
- if (!m_owningLayer->hasOverlayScrollbars())
+ if (!m_owningLayer->hasOverlayScrollbars() && !m_owningLayer->needsCompositedScrolling())
return false;
-#endif
return m_owningLayer->horizontalScrollbar();
}
bool RenderLayerBacking::requiresVerticalScrollbarLayer() const
{
-#if !PLATFORM(CHROMIUM)
- if (!m_owningLayer->hasOverlayScrollbars())
+ if (!m_owningLayer->hasOverlayScrollbars() && !m_owningLayer->needsCompositedScrolling())
return false;
-#endif
return m_owningLayer->verticalScrollbar();
}
bool RenderLayerBacking::requiresScrollCornerLayer() const
{
-#if !PLATFORM(CHROMIUM)
- if (!m_owningLayer->hasOverlayScrollbars())
+ if (!m_owningLayer->hasOverlayScrollbars() && !m_owningLayer->needsCompositedScrolling())
return false;
-#endif
return !m_owningLayer->scrollCornerAndResizerRect().isEmpty();
}
bool RenderLayerBacking::updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer, bool needsVerticalScrollbarLayer, bool needsScrollCornerLayer)
{
- bool layersChanged = false;
+ bool horizontalScrollbarLayerChanged = false;
if (needsHorizontalScrollbarLayer) {
if (!m_layerForHorizontalScrollbar) {
m_layerForHorizontalScrollbar = createGraphicsLayer("horizontal scrollbar");
- layersChanged = true;
+ horizontalScrollbarLayerChanged = true;
}
} else if (m_layerForHorizontalScrollbar) {
- m_layerForHorizontalScrollbar.clear();
- layersChanged = true;
+ willDestroyLayer(m_layerForHorizontalScrollbar.get());
+ m_layerForHorizontalScrollbar = nullptr;
+ horizontalScrollbarLayerChanged = true;
}
+ bool verticalScrollbarLayerChanged = false;
if (needsVerticalScrollbarLayer) {
if (!m_layerForVerticalScrollbar) {
m_layerForVerticalScrollbar = createGraphicsLayer("vertical scrollbar");
- layersChanged = true;
+ verticalScrollbarLayerChanged = true;
}
} else if (m_layerForVerticalScrollbar) {
- m_layerForVerticalScrollbar.clear();
- layersChanged = true;
+ willDestroyLayer(m_layerForVerticalScrollbar.get());
+ m_layerForVerticalScrollbar = nullptr;
+ verticalScrollbarLayerChanged = true;
}
+ bool scrollCornerLayerChanged = false;
if (needsScrollCornerLayer) {
if (!m_layerForScrollCorner) {
m_layerForScrollCorner = createGraphicsLayer("scroll corner");
- layersChanged = true;
+ scrollCornerLayerChanged = true;
}
} else if (m_layerForScrollCorner) {
- m_layerForScrollCorner.clear();
- layersChanged = true;
+ willDestroyLayer(m_layerForScrollCorner.get());
+ m_layerForScrollCorner = nullptr;
+ scrollCornerLayerChanged = true;
}
- return layersChanged;
+ if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer)) {
+ if (horizontalScrollbarLayerChanged)
+ scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_owningLayer, HorizontalScrollbar);
+ if (verticalScrollbarLayerChanged)
+ scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_owningLayer, VerticalScrollbar);
+ }
+
+ return horizontalScrollbarLayerChanged || verticalScrollbarLayerChanged || scrollCornerLayerChanged;
}
void RenderLayerBacking::positionOverflowControlsLayers(const IntSize& offsetFromRoot)
@@ -931,8 +1112,10 @@ void RenderLayerBacking::positionOverflowControlsLayers(const IntSize& offsetFro
if (hBar) {
layer->setPosition(hBar->frameRect().location() - offsetFromRoot - offsetFromRenderer);
layer->setSize(hBar->frameRect().size());
+ if (layer->hasContentsLayer())
+ layer->setContentsRect(IntRect(IntPoint(), hBar->frameRect().size()));
}
- layer->setDrawsContent(hBar);
+ layer->setDrawsContent(hBar && !layer->hasContentsLayer());
}
if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
@@ -940,8 +1123,10 @@ void RenderLayerBacking::positionOverflowControlsLayers(const IntSize& offsetFro
if (vBar) {
layer->setPosition(vBar->frameRect().location() - offsetFromRoot - offsetFromRenderer);
layer->setSize(vBar->frameRect().size());
+ if (layer->hasContentsLayer())
+ layer->setContentsRect(IntRect(IntPoint(), vBar->frameRect().size()));
}
- layer->setDrawsContent(vBar);
+ layer->setDrawsContent(vBar && !layer->hasContentsLayer());
}
if (GraphicsLayer* layer = layerForScrollCorner()) {
@@ -952,6 +1137,23 @@ void RenderLayerBacking::positionOverflowControlsLayers(const IntSize& offsetFro
}
}
+bool RenderLayerBacking::hasUnpositionedOverflowControlsLayers() const
+{
+ if (GraphicsLayer* layer = layerForHorizontalScrollbar())
+ if (!layer->drawsContent())
+ return true;
+
+ if (GraphicsLayer* layer = layerForVerticalScrollbar())
+ if (!layer->drawsContent())
+ return true;
+
+ if (GraphicsLayer* layer = layerForScrollCorner())
+ if (!layer->drawsContent())
+ return true;
+
+ return false;
+}
+
bool RenderLayerBacking::updateForegroundLayer(bool needsForegroundLayer)
{
bool layerChanged = false;
@@ -959,7 +1161,7 @@ bool RenderLayerBacking::updateForegroundLayer(bool needsForegroundLayer)
if (!m_foregroundLayer) {
String layerName;
#ifndef NDEBUG
- layerName = nameForLayer() + " (foreground)";
+ layerName = m_owningLayer->name() + " (foreground)";
#endif
m_foregroundLayer = createGraphicsLayer(layerName);
m_foregroundLayer->setDrawsContent(true);
@@ -967,17 +1169,72 @@ bool RenderLayerBacking::updateForegroundLayer(bool needsForegroundLayer)
layerChanged = true;
}
} else if (m_foregroundLayer) {
+ willDestroyLayer(m_foregroundLayer.get());
m_foregroundLayer->removeFromParent();
m_foregroundLayer = nullptr;
layerChanged = true;
}
- if (layerChanged)
+ if (layerChanged) {
+ m_graphicsLayer->setNeedsDisplay();
m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
+ }
return layerChanged;
}
+bool RenderLayerBacking::updateBackgroundLayer(bool needsBackgroundLayer)
+{
+ bool layerChanged = false;
+ if (needsBackgroundLayer) {
+ if (!m_backgroundLayer) {
+ String layerName;
+#ifndef NDEBUG
+ layerName = m_owningLayer->name() + " (background)";
+#endif
+ m_backgroundLayer = createGraphicsLayer(layerName);
+ m_backgroundLayer->setDrawsContent(true);
+ m_backgroundLayer->setAnchorPoint(FloatPoint3D());
+ m_backgroundLayer->setPaintingPhase(GraphicsLayerPaintBackground);
+ layerChanged = true;
+ }
+
+ if (!m_contentsContainmentLayer) {
+ String layerName;
+#ifndef NDEBUG
+ layerName = m_owningLayer->name() + " (contents containment)";
+#endif
+ m_contentsContainmentLayer = createGraphicsLayer(layerName);
+ m_contentsContainmentLayer->setAppliesPageScale(true);
+ m_graphicsLayer->setAppliesPageScale(false);
+ layerChanged = true;
+ }
+ } else {
+ if (m_backgroundLayer) {
+ willDestroyLayer(m_backgroundLayer.get());
+ m_backgroundLayer->removeFromParent();
+ m_backgroundLayer = nullptr;
+ layerChanged = true;
+ }
+ if (m_contentsContainmentLayer) {
+ willDestroyLayer(m_contentsContainmentLayer.get());
+ m_contentsContainmentLayer->removeFromParent();
+ m_contentsContainmentLayer = nullptr;
+ layerChanged = true;
+ m_graphicsLayer->setAppliesPageScale(true);
+ }
+ }
+
+ if (layerChanged) {
+ m_graphicsLayer->setNeedsDisplay();
+ // This assumes that the background layer is only used for fixed backgrounds, which is currently a correct assumption.
+ if (renderer()->view())
+ compositor()->fixedRootBackgroundLayerChanged();
+ }
+
+ return layerChanged;
+}
+
bool RenderLayerBacking::updateMaskLayer(bool needsMaskLayer)
{
bool layerChanged = false;
@@ -989,6 +1246,7 @@ bool RenderLayerBacking::updateMaskLayer(bool needsMaskLayer)
layerChanged = true;
}
} else if (m_maskLayer) {
+ willDestroyLayer(m_maskLayer.get());
m_maskLayer = nullptr;
layerChanged = true;
}
@@ -1001,6 +1259,8 @@ bool RenderLayerBacking::updateMaskLayer(bool needsMaskLayer)
bool RenderLayerBacking::updateScrollingLayers(bool needsScrollingLayers)
{
+ ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer);
+
bool layerChanged = false;
if (needsScrollingLayers) {
if (!m_scrollingLayer) {
@@ -1012,15 +1272,24 @@ bool RenderLayerBacking::updateScrollingLayers(bool needsScrollingLayers)
// Inner layer which renders the content that scrolls.
m_scrollingContentsLayer = createGraphicsLayer("Scrolled Contents");
m_scrollingContentsLayer->setDrawsContent(true);
- m_scrollingContentsLayer->setPaintingPhase(GraphicsLayerPaintForeground | GraphicsLayerPaintOverflowContents);
+ GraphicsLayerPaintingPhase paintPhase = GraphicsLayerPaintOverflowContents | GraphicsLayerPaintCompositedScroll;
+ if (!m_foregroundLayer)
+ paintPhase |= GraphicsLayerPaintForeground;
+ m_scrollingContentsLayer->setPaintingPhase(paintPhase);
m_scrollingLayer->addChild(m_scrollingContentsLayer.get());
layerChanged = true;
+ if (scrollingCoordinator)
+ scrollingCoordinator->scrollableAreaScrollLayerDidChange(m_owningLayer);
}
} else if (m_scrollingLayer) {
+ willDestroyLayer(m_scrollingLayer.get());
+ willDestroyLayer(m_scrollingContentsLayer.get());
m_scrollingLayer = nullptr;
m_scrollingContentsLayer = nullptr;
layerChanged = true;
+ if (scrollingCoordinator)
+ scrollingCoordinator->scrollableAreaScrollLayerDidChange(m_owningLayer);
}
if (layerChanged) {
@@ -1034,17 +1303,9 @@ bool RenderLayerBacking::updateScrollingLayers(bool needsScrollingLayers)
return layerChanged;
}
-void RenderLayerBacking::attachToScrollingCoordinator(RenderLayerBacking* parent)
+void RenderLayerBacking::attachToScrollingCoordinatorWithParent(RenderLayerBacking* parent)
{
- // If m_scrollLayerID non-zero, then this backing is already attached to the ScrollingCoordinator.
- if (m_scrollLayerID)
- return;
-
- Page* page = renderer()->frame()->page();
- if (!page)
- return;
-
- ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator();
+ ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer);
if (!scrollingCoordinator)
return;
@@ -1053,11 +1314,13 @@ void RenderLayerBacking::attachToScrollingCoordinator(RenderLayerBacking* parent
ScrollingNodeType nodeType;
if (renderer()->style()->position() == FixedPosition)
nodeType = FixedNode;
+ else if (renderer()->style()->position() == StickyPosition)
+ nodeType = StickyNode;
else
nodeType = ScrollingNode;
ScrollingNodeID parentID = parent ? parent->scrollLayerID() : 0;
- m_scrollLayerID = scrollingCoordinator->attachToStateTree(nodeType, scrollingCoordinator->uniqueScrollLayerID(), parentID);
+ m_scrollLayerID = scrollingCoordinator->attachToStateTree(nodeType, m_scrollLayerID ? m_scrollLayerID : scrollingCoordinator->uniqueScrollLayerID(), parentID);
}
void RenderLayerBacking::detachFromScrollingCoordinator()
@@ -1066,11 +1329,7 @@ void RenderLayerBacking::detachFromScrollingCoordinator()
if (!m_scrollLayerID)
return;
- Page* page = renderer()->frame()->page();
- if (!page)
- return;
-
- ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator();
+ ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer);
if (!scrollingCoordinator)
return;
@@ -1080,14 +1339,18 @@ void RenderLayerBacking::detachFromScrollingCoordinator()
GraphicsLayerPaintingPhase RenderLayerBacking::paintingPhaseForPrimaryLayer() const
{
- unsigned phase = GraphicsLayerPaintBackground;
+ unsigned phase = 0;
+ if (!m_backgroundLayer)
+ phase |= GraphicsLayerPaintBackground;
if (!m_foregroundLayer)
phase |= GraphicsLayerPaintForeground;
if (!m_maskLayer)
phase |= GraphicsLayerPaintMask;
- if (m_scrollingContentsLayer)
+ if (m_scrollingContentsLayer) {
phase &= ~GraphicsLayerPaintForeground;
+ phase |= GraphicsLayerPaintCompositedScroll;
+ }
return static_cast<GraphicsLayerPaintingPhase>(phase);
}
@@ -1099,7 +1362,7 @@ float RenderLayerBacking::compositingOpacity(float rendererOpacity) const
for (RenderLayer* curr = m_owningLayer->parent(); curr; curr = curr->parent()) {
// We only care about parents that are stacking contexts.
// Recall that opacity creates stacking context.
- if (!curr->isStackingContext())
+ if (!curr->isStackingContainer())
continue;
// If we found a compositing layer, we want to compute opacity
@@ -1118,14 +1381,17 @@ static bool hasBoxDecorations(const RenderStyle* style)
return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow() || style->hasFilter();
}
-static bool hasBoxDecorationsOrBackground(const RenderObject* renderer)
-{
- return hasBoxDecorations(renderer->style()) || renderer->hasBackground();
-}
+static bool canCreateTiledImage(const RenderStyle*);
static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle* style)
{
- return hasBoxDecorations(style) || style->hasBackgroundImage();
+ if (hasBoxDecorations(style))
+ return true;
+
+ if (!style->hasBackgroundImage())
+ return false;
+
+ return !GraphicsLayer::supportsContentsTiling() || !canCreateTiledImage(style);
}
Color RenderLayerBacking::rendererBackgroundColor() const
@@ -1137,20 +1403,128 @@ Color RenderLayerBacking::rendererBackgroundColor() const
return backgroundRenderer->style()->visitedDependentColor(CSSPropertyBackgroundColor);
}
-void RenderLayerBacking::updateBackgroundColor()
+void RenderLayerBacking::updateDirectlyCompositedBackgroundColor(bool isSimpleContainer, bool& didUpdateContentsRect)
{
- m_graphicsLayer->setContentsToBackgroundColor(rendererBackgroundColor());
+ if (!isSimpleContainer) {
+ m_graphicsLayer->setContentsToSolidColor(Color());
+ return;
+ }
+
+ Color backgroundColor = rendererBackgroundColor();
+
+ // An unset (invalid) color will remove the solid color.
+ m_graphicsLayer->setContentsToSolidColor(backgroundColor);
+ m_graphicsLayer->setContentsRect(backgroundBox());
+ didUpdateContentsRect = true;
}
-bool RenderLayerBacking::paintsBoxDecorations() const
+bool canCreateTiledImage(const RenderStyle* style)
{
- if (!m_owningLayer->hasVisibleContent())
+ const FillLayer* fillLayer = style->backgroundLayers();
+ if (fillLayer->next())
return false;
- if (hasBoxDecorationsOrBackground(renderer()))
- return true;
+ if (!fillLayer->imagesAreLoaded())
+ return false;
+
+ if (fillLayer->attachment() != ScrollBackgroundAttachment)
+ return false;
+
+ Color color = style->visitedDependentColor(CSSPropertyBackgroundColor);
+
+ // FIXME: Allow color+image compositing when it makes sense.
+ // For now bailing out.
+ if (color.isValid() && color.alpha())
+ return false;
+
+ StyleImage* styleImage = fillLayer->image();
+
+ // FIXME: support gradients with isGeneratedImage.
+ if (!styleImage->isCachedImage())
+ return false;
+
+ Image* image = styleImage->cachedImage()->image();
+ if (!image->isBitmapImage())
+ return false;
+
+ return true;
+}
+
+void RenderLayerBacking::updateDirectlyCompositedBackgroundImage(bool isSimpleContainer, bool& didUpdateContentsRect)
+{
+ if (!GraphicsLayer::supportsContentsTiling())
+ return;
+
+ if (isDirectlyCompositedImage())
+ return;
+
+ const RenderStyle* style = renderer()->style();
+
+ if (!isSimpleContainer || !style->hasBackgroundImage()) {
+ m_graphicsLayer->setContentsToImage(0);
+ return;
+ }
+
+ IntRect destRect = backgroundBox();
+ IntPoint phase;
+ IntSize tileSize;
+
+ RefPtr<Image> image = style->backgroundLayers()->image()->cachedImage()->image();
+ toRenderBox(renderer())->getGeometryForBackgroundImage(m_owningLayer->renderer(), destRect, phase, tileSize);
+ m_graphicsLayer->setContentsTileSize(tileSize);
+ m_graphicsLayer->setContentsTilePhase(phase);
+ m_graphicsLayer->setContentsRect(destRect);
+ m_graphicsLayer->setContentsToImage(image.get());
+ didUpdateContentsRect = true;
+}
+
+void RenderLayerBacking::updateRootLayerConfiguration()
+{
+ if (!m_usingTiledCacheLayer)
+ return;
+
+ Color backgroundColor;
+ bool viewIsTransparent = compositor()->viewHasTransparentBackground(&backgroundColor);
+
+ if (m_backgroundLayerPaintsFixedRootBackground && m_backgroundLayer) {
+ m_backgroundLayer->setBackgroundColor(backgroundColor);
+ m_backgroundLayer->setContentsOpaque(!viewIsTransparent);
+
+ m_graphicsLayer->setBackgroundColor(Color());
+ m_graphicsLayer->setContentsOpaque(false);
+ } else {
+ m_graphicsLayer->setBackgroundColor(backgroundColor);
+ m_graphicsLayer->setContentsOpaque(!viewIsTransparent);
+ }
+}
+
+static bool supportsDirectBoxDecorationsComposition(const RenderObject* renderer)
+{
+ if (!GraphicsLayer::supportsBackgroundColorContent())
+ return false;
+
+ if (renderer->hasClip())
+ return false;
+
+ if (hasBoxDecorationsOrBackgroundImage(renderer->style()))
+ return false;
+
+ // FIXME: we should be able to allow backgroundComposite; However since this is not a common use case it has been deferred for now.
+ if (renderer->style()->backgroundComposite() != CompositeSourceOver)
+ return false;
- if (m_owningLayer->hasOverflowControls())
+ if (renderer->style()->backgroundClip() == TextFillBox)
+ return false;
+
+ return true;
+}
+
+bool RenderLayerBacking::paintsBoxDecorations() const
+{
+ if (!m_owningLayer->hasVisibleBoxDecorations())
+ return false;
+
+ if (!supportsDirectBoxDecorationsComposition(renderer()))
return true;
return false;
@@ -1158,15 +1532,27 @@ bool RenderLayerBacking::paintsBoxDecorations() const
bool RenderLayerBacking::paintsChildren() const
{
- if (m_owningLayer->hasVisibleContent() && containsNonEmptyRenderers())
+ if (m_owningLayer->hasVisibleContent() && m_owningLayer->hasNonEmptyChildRenderers())
return true;
-
+
if (hasVisibleNonCompositingDescendantLayers())
return true;
return false;
}
+static bool isRestartedPlugin(RenderObject* renderer)
+{
+ if (!renderer->isEmbeddedObject())
+ return false;
+
+ Element* element = toElement(renderer->node());
+ if (!element || !element->isPluginElement())
+ return false;
+
+ return toHTMLPlugInElement(element)->isRestartedPlugin();
+}
+
static bool isCompositedPlugin(RenderObject* renderer)
{
return renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->allowsAcceleratedCompositing();
@@ -1181,12 +1567,15 @@ bool RenderLayerBacking::isSimpleContainerCompositingLayer() const
if (renderObject->hasMask()) // masks require special treatment
return false;
- if (renderObject->isReplaced() && !isCompositedPlugin(renderObject))
- return false;
-
+ if (renderObject->isReplaced() && (!isCompositedPlugin(renderObject) || isRestartedPlugin(renderObject)))
+ return false;
+
if (paintsBoxDecorations() || paintsChildren())
return false;
-
+
+ if (renderObject->isRenderRegion())
+ return false;
+
if (renderObject->node() && renderObject->node()->isDocumentNode()) {
// Look to see if the root object has a non-simple background
RenderObject* rootObject = renderObject->document()->documentElement() ? renderObject->document()->documentElement()->renderer() : 0;
@@ -1215,63 +1604,46 @@ bool RenderLayerBacking::isSimpleContainerCompositingLayer() const
return true;
}
-bool RenderLayerBacking::containsNonEmptyRenderers() const
-{
- // Some HTML can cause whitespace text nodes to have renderers, like:
- // <div>
- // <img src=...>
- // </div>
- // so test for 0x0 RenderTexts here
- for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
- if (!child->hasLayer()) {
- if (child->isRenderInline() || !child->isBox())
- return true;
-
- if (toRenderBox(child)->width() > 0 || toRenderBox(child)->height() > 0)
- return true;
- }
- }
- return false;
-}
-
-// Conservative test for having no rendered children.
-bool RenderLayerBacking::hasVisibleNonCompositingDescendantLayers() const
+static bool hasVisibleNonCompositingDescendant(RenderLayer* parent)
{
// FIXME: We shouldn't be called with a stale z-order lists. See bug 85512.
- m_owningLayer->updateLayerListsIfNeeded();
+ parent->updateLayerListsIfNeeded();
#if !ASSERT_DISABLED
- LayerListMutationDetector mutationChecker(m_owningLayer);
+ LayerListMutationDetector mutationChecker(parent);
#endif
- if (Vector<RenderLayer*>* normalFlowList = m_owningLayer->normalFlowList()) {
+ if (Vector<RenderLayer*>* normalFlowList = parent->normalFlowList()) {
size_t listSize = normalFlowList->size();
for (size_t i = 0; i < listSize; ++i) {
RenderLayer* curLayer = normalFlowList->at(i);
- if (!curLayer->isComposited() && curLayer->hasVisibleContent())
+ if (!curLayer->isComposited()
+ && (curLayer->hasVisibleContent() || hasVisibleNonCompositingDescendant(curLayer)))
return true;
}
}
- if (m_owningLayer->isStackingContext()) {
- if (!m_owningLayer->hasVisibleDescendant())
+ if (parent->isStackingContainer()) {
+ if (!parent->hasVisibleDescendant())
return false;
// Use the m_hasCompositingDescendant bit to optimize?
- if (Vector<RenderLayer*>* negZOrderList = m_owningLayer->negZOrderList()) {
+ if (Vector<RenderLayer*>* negZOrderList = parent->negZOrderList()) {
size_t listSize = negZOrderList->size();
for (size_t i = 0; i < listSize; ++i) {
RenderLayer* curLayer = negZOrderList->at(i);
- if (!curLayer->isComposited() && curLayer->hasVisibleContent())
+ if (!curLayer->isComposited()
+ && (curLayer->hasVisibleContent() || hasVisibleNonCompositingDescendant(curLayer)))
return true;
}
}
- if (Vector<RenderLayer*>* posZOrderList = m_owningLayer->posZOrderList()) {
+ if (Vector<RenderLayer*>* posZOrderList = parent->posZOrderList()) {
size_t listSize = posZOrderList->size();
for (size_t i = 0; i < listSize; ++i) {
RenderLayer* curLayer = posZOrderList->at(i);
- if (!curLayer->isComposited() && curLayer->hasVisibleContent())
+ if (!curLayer->isComposited()
+ && (curLayer->hasVisibleContent() || hasVisibleNonCompositingDescendant(curLayer)))
return true;
}
}
@@ -1280,9 +1652,15 @@ bool RenderLayerBacking::hasVisibleNonCompositingDescendantLayers() const
return false;
}
-bool RenderLayerBacking::containsPaintedContent() const
+// Conservative test for having no rendered children.
+bool RenderLayerBacking::hasVisibleNonCompositingDescendantLayers() const
{
- if (isSimpleContainerCompositingLayer() || paintsIntoWindow() || paintsIntoCompositedAncestor() || m_artificiallyInflatedBounds || m_owningLayer->isReflection())
+ return hasVisibleNonCompositingDescendant(m_owningLayer);
+}
+
+bool RenderLayerBacking::containsPaintedContent(bool isSimpleContainer) const
+{
+ if (isSimpleContainer || paintsIntoWindow() || paintsIntoCompositedAncestor() || m_artificiallyInflatedBounds || m_owningLayer->isReflection())
return false;
if (isDirectlyCompositedImage())
@@ -1292,12 +1670,12 @@ bool RenderLayerBacking::containsPaintedContent() const
// and set background color on the layer in that case, instead of allocating backing store and painting.
#if ENABLE(VIDEO)
if (renderer()->isVideo() && toRenderVideo(renderer())->shouldDisplayVideo())
- return hasBoxDecorationsOrBackground(renderer());
+ return m_owningLayer->hasBoxDecorationsOrBackground();
#endif
#if PLATFORM(MAC) && USE(CA) && (PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
#elif ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
if (isAcceleratedCanvas(renderer()))
- return hasBoxDecorationsOrBackground(renderer());
+ return m_owningLayer->hasBoxDecorationsOrBackground();
#endif
return true;
@@ -1308,8 +1686,8 @@ bool RenderLayerBacking::containsPaintedContent() const
bool RenderLayerBacking::isDirectlyCompositedImage() const
{
RenderObject* renderObject = renderer();
-
- if (!renderObject->isImage() || hasBoxDecorationsOrBackground(renderObject) || renderObject->hasClip())
+
+ if (!renderObject->isImage() || m_owningLayer->hasBoxDecorationsOrBackground() || renderObject->hasClip())
return false;
RenderImage* imageRenderer = toRenderImage(renderObject);
@@ -1333,12 +1711,14 @@ void RenderLayerBacking::contentChanged(ContentChangeType changeType)
updateImageContents();
return;
}
-
+
+ if ((changeType == BackgroundImageChanged) && canCreateTiledImage(renderer()->style()))
+ updateGraphicsLayerGeometry();
+
if ((changeType == MaskImageChanged) && m_maskLayer) {
// The composited layer bounds relies on box->maskClipRect(), which changes
// when the mask image becomes available.
- bool isUpdateRoot = true;
- updateAfterLayout(CompositingChildren, isUpdateRoot);
+ updateAfterLayout(CompositingChildrenOnly | IsUpdateRoot);
}
#if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
@@ -1367,8 +1747,10 @@ void RenderLayerBacking::updateImageContents()
return;
// This is a no-op if the layer doesn't have an inner layer for the image.
+ m_graphicsLayer->setContentsRect(pixelSnappedIntRect(contentsBox()));
m_graphicsLayer->setContentsToImage(image);
- updateDrawsContent();
+ bool isSimpleContainer = false;
+ updateDrawsContent(isSimpleContainer);
// Image animation is "lazy", in that it automatically stops unless someone is drawing
// the image. So we have to kick the animation each time; this has the downside that the
@@ -1403,36 +1785,73 @@ FloatPoint RenderLayerBacking::computePerspectiveOrigin(const IntRect& borderBox
}
// Return the offset from the top-left of this compositing layer at which the renderer's contents are painted.
-IntSize RenderLayerBacking::contentOffsetInCompostingLayer() const
+LayoutSize RenderLayerBacking::contentOffsetInCompostingLayer() const
{
- return IntSize(-m_compositedBounds.x(), -m_compositedBounds.y());
+ return LayoutSize(-m_compositedBounds.x(), -m_compositedBounds.y());
}
-IntRect RenderLayerBacking::contentsBox() const
+LayoutRect RenderLayerBacking::contentsBox() const
{
if (!renderer()->isBox())
- return IntRect();
+ return LayoutRect();
- IntRect contentsRect;
+ LayoutRect contentsRect;
#if ENABLE(VIDEO)
if (renderer()->isVideo()) {
RenderVideo* videoRenderer = toRenderVideo(renderer());
contentsRect = videoRenderer->videoBox();
} else
#endif
- contentsRect = pixelSnappedIntRect(toRenderBox(renderer())->contentBoxRect());
+ contentsRect = toRenderBox(renderer())->contentBoxRect();
- IntSize contentOffset = contentOffsetInCompostingLayer();
- contentsRect.move(contentOffset);
+ contentsRect.move(contentOffsetInCompostingLayer());
return contentsRect;
}
+static LayoutRect backgroundRectForBox(const RenderBox* box)
+{
+ switch (box->style()->backgroundClip()) {
+ case BorderFillBox:
+ return box->borderBoxRect();
+ case PaddingFillBox:
+ return box->paddingBoxRect();
+ case ContentFillBox:
+ return box->contentBoxRect();
+ case TextFillBox:
+ break;
+ }
+
+ ASSERT_NOT_REACHED();
+ return LayoutRect();
+}
+
+IntRect RenderLayerBacking::backgroundBox() const
+{
+ if (!renderer()->isBox())
+ return IntRect();
+
+ LayoutRect backgroundBox = backgroundRectForBox(toRenderBox(renderer()));
+ backgroundBox.move(contentOffsetInCompostingLayer());
+ return pixelSnappedIntRect(backgroundBox);
+}
+
GraphicsLayer* RenderLayerBacking::parentForSublayers() const
{
if (m_scrollingContentsLayer)
return m_scrollingContentsLayer.get();
- return m_containmentLayer ? m_containmentLayer.get() : m_graphicsLayer.get();
+ return m_childContainmentLayer ? m_childContainmentLayer.get() : m_graphicsLayer.get();
+}
+
+GraphicsLayer* RenderLayerBacking::childForSuperlayers() const
+{
+ if (m_ancestorClippingLayer)
+ return m_ancestorClippingLayer.get();
+
+ if (m_contentsContainmentLayer)
+ return m_contentsContainmentLayer.get();
+
+ return m_graphicsLayer.get();
}
bool RenderLayerBacking::paintsIntoWindow() const
@@ -1441,7 +1860,7 @@ bool RenderLayerBacking::paintsIntoWindow() const
return false;
if (m_owningLayer->isRootLayer()) {
-#if PLATFORM(BLACKBERRY)
+#if PLATFORM(BLACKBERRY) || USE(COORDINATED_GRAPHICS)
if (compositor()->inForcedCompositingMode())
return false;
#endif
@@ -1483,6 +1902,9 @@ void RenderLayerBacking::setContentsNeedDisplay()
if (m_foregroundLayer && m_foregroundLayer->drawsContent())
m_foregroundLayer->setNeedsDisplay();
+ if (m_backgroundLayer && m_backgroundLayer->drawsContent())
+ m_backgroundLayer->setNeedsDisplay();
+
if (m_maskLayer && m_maskLayer->drawsContent())
m_maskLayer->setNeedsDisplay();
@@ -1507,6 +1929,13 @@ void RenderLayerBacking::setContentsNeedDisplayInRect(const IntRect& r)
m_foregroundLayer->setNeedsDisplayInRect(layerDirtyRect);
}
+ // FIXME: need to split out repaints for the background.
+ if (m_backgroundLayer && m_backgroundLayer->drawsContent()) {
+ IntRect layerDirtyRect = r;
+ layerDirtyRect.move(-m_backgroundLayer->offsetFromRenderer());
+ m_backgroundLayer->setNeedsDisplayInRect(layerDirtyRect);
+ }
+
if (m_maskLayer && m_maskLayer->drawsContent()) {
IntRect layerDirtyRect = r;
layerDirtyRect.move(-m_maskLayer->offsetFromRenderer());
@@ -1520,7 +1949,7 @@ void RenderLayerBacking::setContentsNeedDisplayInRect(const IntRect& r)
}
}
-void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* context,
+void RenderLayerBacking::paintIntoLayer(const GraphicsLayer* graphicsLayer, GraphicsContext* context,
const IntRect& paintDirtyRect, // In the coords of rootLayer.
PaintBehavior paintBehavior, GraphicsLayerPaintingPhase paintingPhase)
{
@@ -1540,14 +1969,23 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*
paintFlags |= RenderLayer::PaintLayerPaintingCompositingMaskPhase;
if (paintingPhase & GraphicsLayerPaintOverflowContents)
paintFlags |= RenderLayer::PaintLayerPaintingOverflowContents;
+ if (paintingPhase & GraphicsLayerPaintCompositedScroll)
+ paintFlags |= RenderLayer::PaintLayerPaintingCompositingScrollingPhase;
+
+ if (graphicsLayer == m_backgroundLayer)
+ paintFlags |= (RenderLayer::PaintLayerPaintingRootBackgroundOnly | RenderLayer::PaintLayerPaintingCompositingForegroundPhase); // Need PaintLayerPaintingCompositingForegroundPhase to walk child layers.
+ else if (compositor()->fixedRootBackgroundLayer())
+ paintFlags |= RenderLayer::PaintLayerPaintingSkipRootBackground;
// FIXME: GraphicsLayers need a way to split for RenderRegions.
- RenderLayer::LayerPaintingInfo paintingInfo(rootLayer, paintDirtyRect, paintBehavior, LayoutSize());
+ RenderLayer::LayerPaintingInfo paintingInfo(m_owningLayer, paintDirtyRect, paintBehavior, m_subpixelAccumulation);
m_owningLayer->paintLayerContents(context, paintingInfo, paintFlags);
if (m_owningLayer->containsDirtyOverlayScrollbars())
m_owningLayer->paintLayerContents(context, paintingInfo, paintFlags | RenderLayer::PaintLayerPaintingOverlayScrollbars);
+ compositor()->didPaintBacking(this);
+
ASSERT(!m_owningLayer->m_usedTransparency);
}
@@ -1573,21 +2011,22 @@ void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, Graph
page->setIsPainting(true);
#endif
- if (graphicsLayer == m_graphicsLayer.get() || graphicsLayer == m_foregroundLayer.get() || graphicsLayer == m_maskLayer.get() || graphicsLayer == m_scrollingContentsLayer.get()) {
- InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_owningLayer->renderer()->frame());
+ if (graphicsLayer == m_graphicsLayer.get()
+ || graphicsLayer == m_foregroundLayer.get()
+ || graphicsLayer == m_backgroundLayer.get()
+ || graphicsLayer == m_maskLayer.get()
+ || graphicsLayer == m_scrollingContentsLayer.get()) {
+ InspectorInstrumentation::willPaint(renderer());
// The dirtyRect is in the coords of the painting root.
IntRect dirtyRect = clip;
if (!(paintingPhase & GraphicsLayerPaintOverflowContents))
- dirtyRect.intersect(compositedBounds());
+ dirtyRect.intersect(enclosingIntRect(compositedBounds()));
// We have to use the same root as for hit testing, because both methods can compute and cache clipRects.
- paintIntoLayer(m_owningLayer, &context, dirtyRect, PaintBehaviorNormal, paintingPhase);
-
- if (m_usingTiledCacheLayer)
- m_owningLayer->renderer()->frame()->view()->setLastPaintTime(currentTime());
+ paintIntoLayer(graphicsLayer, &context, dirtyRect, PaintBehaviorNormal, paintingPhase);
- InspectorInstrumentation::didPaint(cookie, &context, clip);
+ InspectorInstrumentation::didPaint(renderer(), &context, clip);
} else if (graphicsLayer == layerForHorizontalScrollbar()) {
paintScrollbar(m_owningLayer->horizontalScrollbar(), context, clip);
} else if (graphicsLayer == layerForVerticalScrollbar()) {
@@ -1618,14 +2057,15 @@ float RenderLayerBacking::deviceScaleFactor() const
return compositor()->deviceScaleFactor();
}
-void RenderLayerBacking::didCommitChangesForLayer(const GraphicsLayer*) const
+void RenderLayerBacking::didCommitChangesForLayer(const GraphicsLayer* layer) const
{
- compositor()->didFlushChangesForLayer(m_owningLayer);
+ compositor()->didFlushChangesForLayer(m_owningLayer, layer);
}
bool RenderLayerBacking::getCurrentTransform(const GraphicsLayer* graphicsLayer, TransformationMatrix& transform) const
{
- if (graphicsLayer != m_graphicsLayer)
+ GraphicsLayer* transformedLayer = m_contentsContainmentLayer.get() ? m_contentsContainmentLayer.get() : m_graphicsLayer.get();
+ if (graphicsLayer != transformedLayer)
return false;
if (m_owningLayer->hasTransform()) {
@@ -1681,39 +2121,31 @@ bool RenderLayerBacking::startAnimation(double timeOffset, const Animation* anim
bool isFirstOrLastKeyframe = key == 0 || key == 1;
if ((hasTransform && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyWebkitTransform))
- transformVector.insert(new TransformAnimationValue(key, &(keyframeStyle->transform()), tf));
-
+ transformVector.insert(TransformAnimationValue::create(key, keyframeStyle->transform(), tf));
+
if ((hasOpacity && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyOpacity))
- opacityVector.insert(new FloatAnimationValue(key, keyframeStyle->opacity(), tf));
+ opacityVector.insert(FloatAnimationValue::create(key, keyframeStyle->opacity(), tf));
#if ENABLE(CSS_FILTERS)
if ((hasFilter && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyWebkitFilter))
- filterVector.insert(new FilterAnimationValue(key, &(keyframeStyle->filter()), tf));
+ filterVector.insert(FilterAnimationValue::create(key, keyframeStyle->filter(), tf));
#endif
}
- bool didAnimateTransform = false;
- bool didAnimateOpacity = false;
-#if ENABLE(CSS_FILTERS)
- bool didAnimateFilter = false;
-#endif
+ bool didAnimate = false;
if (hasTransform && m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->pixelSnappedBorderBoxRect().size(), anim, keyframes.animationName(), timeOffset))
- didAnimateTransform = true;
+ didAnimate = true;
if (hasOpacity && m_graphicsLayer->addAnimation(opacityVector, IntSize(), anim, keyframes.animationName(), timeOffset))
- didAnimateOpacity = true;
+ didAnimate = true;
#if ENABLE(CSS_FILTERS)
if (hasFilter && m_graphicsLayer->addAnimation(filterVector, IntSize(), anim, keyframes.animationName(), timeOffset))
- didAnimateFilter = true;
+ didAnimate = true;
#endif
-#if ENABLE(CSS_FILTERS)
- return didAnimateTransform || didAnimateOpacity || didAnimateFilter;
-#else
- return didAnimateTransform || didAnimateOpacity;
-#endif
+ return didAnimate;
}
void RenderLayerBacking::animationPaused(double timeOffset, const String& animationName)
@@ -1728,11 +2160,7 @@ void RenderLayerBacking::animationFinished(const String& animationName)
bool RenderLayerBacking::startTransition(double timeOffset, CSSPropertyID property, const RenderStyle* fromStyle, const RenderStyle* toStyle)
{
- bool didAnimateOpacity = false;
- bool didAnimateTransform = false;
-#if ENABLE(CSS_FILTERS)
- bool didAnimateFilter = false;
-#endif
+ bool didAnimate = false;
ASSERT(property != CSSPropertyInvalid);
@@ -1740,13 +2168,13 @@ bool RenderLayerBacking::startTransition(double timeOffset, CSSPropertyID proper
const Animation* opacityAnim = toStyle->transitionForProperty(CSSPropertyOpacity);
if (opacityAnim && !opacityAnim->isEmptyOrZeroDuration()) {
KeyframeValueList opacityVector(AnimatedPropertyOpacity);
- opacityVector.insert(new FloatAnimationValue(0, compositingOpacity(fromStyle->opacity())));
- opacityVector.insert(new FloatAnimationValue(1, compositingOpacity(toStyle->opacity())));
+ opacityVector.insert(FloatAnimationValue::create(0, compositingOpacity(fromStyle->opacity())));
+ opacityVector.insert(FloatAnimationValue::create(1, compositingOpacity(toStyle->opacity())));
// The boxSize param is only used for transform animations (which can only run on RenderBoxes), so we pass an empty size here.
if (m_graphicsLayer->addAnimation(opacityVector, IntSize(), opacityAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyOpacity), timeOffset)) {
// To ensure that the correct opacity is visible when the animation ends, also set the final opacity.
updateOpacity(toStyle);
- didAnimateOpacity = true;
+ didAnimate = true;
}
}
}
@@ -1755,12 +2183,12 @@ bool RenderLayerBacking::startTransition(double timeOffset, CSSPropertyID proper
const Animation* transformAnim = toStyle->transitionForProperty(CSSPropertyWebkitTransform);
if (transformAnim && !transformAnim->isEmptyOrZeroDuration()) {
KeyframeValueList transformVector(AnimatedPropertyWebkitTransform);
- transformVector.insert(new TransformAnimationValue(0, &fromStyle->transform()));
- transformVector.insert(new TransformAnimationValue(1, &toStyle->transform()));
+ transformVector.insert(TransformAnimationValue::create(0, fromStyle->transform()));
+ transformVector.insert(TransformAnimationValue::create(1, toStyle->transform()));
if (m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->pixelSnappedBorderBoxRect().size(), transformAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitTransform), timeOffset)) {
// To ensure that the correct transform is visible when the animation ends, also set the final transform.
updateTransform(toStyle);
- didAnimateTransform = true;
+ didAnimate = true;
}
}
}
@@ -1770,22 +2198,18 @@ bool RenderLayerBacking::startTransition(double timeOffset, CSSPropertyID proper
const Animation* filterAnim = toStyle->transitionForProperty(CSSPropertyWebkitFilter);
if (filterAnim && !filterAnim->isEmptyOrZeroDuration()) {
KeyframeValueList filterVector(AnimatedPropertyWebkitFilter);
- filterVector.insert(new FilterAnimationValue(0, &fromStyle->filter()));
- filterVector.insert(new FilterAnimationValue(1, &toStyle->filter()));
+ filterVector.insert(FilterAnimationValue::create(0, fromStyle->filter()));
+ filterVector.insert(FilterAnimationValue::create(1, toStyle->filter()));
if (m_graphicsLayer->addAnimation(filterVector, IntSize(), filterAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitFilter), timeOffset)) {
// To ensure that the correct filter is visible when the animation ends, also set the final filter.
updateFilters(toStyle);
- didAnimateFilter = true;
+ didAnimate = true;
}
}
}
#endif
-#if ENABLE(CSS_FILTERS)
- return didAnimateOpacity || didAnimateTransform || didAnimateFilter;
-#else
- return didAnimateOpacity || didAnimateTransform;
-#endif
+ return didAnimate;
}
void RenderLayerBacking::transitionPaused(double timeOffset, CSSPropertyID property)
@@ -1807,10 +2231,11 @@ void RenderLayerBacking::notifyAnimationStarted(const GraphicsLayer*, double tim
renderer()->animation()->notifyAnimationStarted(renderer(), time);
}
-void RenderLayerBacking::notifyFlushRequired(const GraphicsLayer*)
+void RenderLayerBacking::notifyFlushRequired(const GraphicsLayer* layer)
{
- if (!renderer()->documentBeingDestroyed())
- compositor()->scheduleLayerFlush();
+ if (renderer()->documentBeingDestroyed())
+ return;
+ compositor()->scheduleLayerFlush(layer->canThrottleLayerFlush());
}
void RenderLayerBacking::notifyFlushBeforeDisplayRefresh(const GraphicsLayer* layer)
@@ -1829,12 +2254,12 @@ void RenderLayerBacking::resumeAnimations()
m_graphicsLayer->resumeAnimations();
}
-IntRect RenderLayerBacking::compositedBounds() const
+LayoutRect RenderLayerBacking::compositedBounds() const
{
return m_compositedBounds;
}
-void RenderLayerBacking::setCompositedBounds(const IntRect& bounds)
+void RenderLayerBacking::setCompositedBounds(const LayoutRect& bounds)
{
m_compositedBounds = bounds;
}
@@ -1885,46 +2310,13 @@ AnimatedPropertyID RenderLayerBacking::cssToGraphicsLayerProperty(CSSPropertyID
return AnimatedPropertyInvalid;
}
-String RenderLayerBacking::nameForLayer() const
-{
- StringBuilder name;
- name.append(renderer()->renderName());
- if (Node* node = renderer()->node()) {
- if (node->isElementNode()) {
- name.append(' ');
- name.append(static_cast<Element*>(node)->tagName());
- }
- if (node->hasID()) {
- name.appendLiteral(" id=\'");
- name.append(static_cast<Element*>(node)->getIdAttribute());
- name.append('\'');
- }
-
- if (node->hasClass()) {
- name.appendLiteral(" class=\'");
- StyledElement* styledElement = static_cast<StyledElement*>(node);
- for (size_t i = 0; i < styledElement->classNames().size(); ++i) {
- if (i > 0)
- name.append(' ');
- name.append(styledElement->classNames()[i]);
- }
- name.append('\'');
- }
- }
-
- if (m_owningLayer->isReflection())
- name.appendLiteral(" (reflection)");
-
- return name.toString();
-}
-
CompositingLayerType RenderLayerBacking::compositingLayerType() const
{
if (m_graphicsLayer->hasContentsLayer())
return MediaCompositingLayer;
if (m_graphicsLayer->drawsContent())
- return m_graphicsLayer->usingTiledLayer() ? TiledCompositingLayer : NormalCompositingLayer;
+ return m_graphicsLayer->usingTiledBacking() ? TiledCompositingLayer : NormalCompositingLayer;
return ContainerCompositingLayer;
}
@@ -1933,10 +2325,12 @@ double RenderLayerBacking::backingStoreMemoryEstimate() const
{
double backingMemory;
- // m_ancestorClippingLayer and m_containmentLayer are just used for masking or containment, so have no backing.
+ // m_ancestorClippingLayer, m_contentsContainmentLayer and m_childContainmentLayer are just used for masking or containment, so have no backing.
backingMemory = m_graphicsLayer->backingStoreMemoryEstimate();
if (m_foregroundLayer)
backingMemory += m_foregroundLayer->backingStoreMemoryEstimate();
+ if (m_backgroundLayer)
+ backingMemory += m_backgroundLayer->backingStoreMemoryEstimate();
if (m_maskLayer)
backingMemory += m_maskLayer->backingStoreMemoryEstimate();
@@ -1955,20 +2349,6 @@ double RenderLayerBacking::backingStoreMemoryEstimate() const
return backingMemory;
}
-#if PLATFORM(BLACKBERRY)
-bool RenderLayerBacking::contentsVisible(const GraphicsLayer*, const IntRect& localContentRect) const
-{
- Frame* frame = renderer()->frame();
- FrameView* view = frame ? frame->view() : 0;
- if (!view)
- return false;
-
- IntRect visibleContentRect(view->visibleContentRect());
- FloatQuad absoluteContentQuad = renderer()->localToAbsoluteQuad(FloatRect(localContentRect), SnapOffsetForTransforms);
- return absoluteContentQuad.enclosingBoundingBox().intersects(visibleContentRect);
-}
-#endif
-
} // namespace WebCore
#endif // USE(ACCELERATED_COMPOSITING)