From e0aa068729e4558f198f02f9217b11a05fe3d1d3 Mon Sep 17 00:00:00 2001 From: Nicolas Roard Date: Wed, 20 Jul 2011 12:58:10 -0700 Subject: Reduce the number of layers - overflow elements triggered all layers before them to be composited; this is not needed at all... - fixed elements will trigger layers after them to be composited, but we don't need to composite all of them -- the one fully contained into previous composited layers don't need to... bug:5069090 Change-Id: I65f789f490b837a16096b4cb186c45ade1605b41 --- Source/WebCore/rendering/RenderLayer.cpp | 3 + Source/WebCore/rendering/RenderLayer.h | 9 +- Source/WebCore/rendering/RenderLayerCompositor.cpp | 135 +++++++++++++++------ Source/WebCore/rendering/RenderLayerCompositor.h | 4 + 4 files changed, 112 insertions(+), 39 deletions(-) (limited to 'Source/WebCore/rendering') diff --git a/Source/WebCore/rendering/RenderLayer.cpp b/Source/WebCore/rendering/RenderLayer.cpp index 4e1c875..ce5bf27 100644 --- a/Source/WebCore/rendering/RenderLayer.cpp +++ b/Source/WebCore/rendering/RenderLayer.cpp @@ -177,6 +177,9 @@ RenderLayer::RenderLayer(RenderBoxModelObject* renderer) #if USE(ACCELERATED_COMPOSITING) , m_hasCompositingDescendant(false) , m_mustOverlapCompositedLayers(false) +#if ENABLE(COMPOSITED_FIXED_ELEMENTS) + , m_shouldComposite(false) +#endif #endif , m_containsDirtyOverlayScrollbars(false) #if ENABLE(ANDROID_OVERFLOW_SCROLL) diff --git a/Source/WebCore/rendering/RenderLayer.h b/Source/WebCore/rendering/RenderLayer.h index 2174920..f257593 100644 --- a/Source/WebCore/rendering/RenderLayer.h +++ b/Source/WebCore/rendering/RenderLayer.h @@ -354,7 +354,7 @@ public: if (hasOverflowScroll()) return true; #endif - return !hasAutoZIndex() || renderer()->isRenderView() || (isComposited() && isFixed()); + return !hasAutoZIndex() || renderer()->isRenderView() || (isComposited() && isFixed()) || m_shouldComposite; } #else #if ENABLE(ANDROID_OVERFLOW_SCROLL) @@ -641,6 +641,10 @@ private: bool mustOverlapCompositedLayers() const { return m_mustOverlapCompositedLayers; } void setMustOverlapCompositedLayers(bool b) { m_mustOverlapCompositedLayers = b; } +#if ENABLE(COMPOSITED_FIXED_ELEMENTS) + bool shouldComposite() { return m_shouldComposite; } + void setShouldComposite(bool b) { m_shouldComposite = b; } +#endif #endif void updateContentsScale(float); @@ -743,6 +747,9 @@ protected: #if USE(ACCELERATED_COMPOSITING) bool m_hasCompositingDescendant : 1; // In the z-order tree. bool m_mustOverlapCompositedLayers : 1; +#if ENABLE(COMPOSITED_FIXED_ELEMENTS) + bool m_shouldComposite : 1; +#endif #endif bool m_containsDirtyOverlayScrollbars : 1; diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp index 786f806..8d066e9 100644 --- a/Source/WebCore/rendering/RenderLayerCompositor.cpp +++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp @@ -80,6 +80,9 @@ struct CompositingState { #if ENABLE(COMPOSITED_FIXED_ELEMENTS) , m_fixedSibling(false) #endif +#if ENABLE(ANDROID_OVERFLOW_SCROLL) + , m_hasScrollableElement(false) +#endif #ifndef NDEBUG , m_depth(0) #endif @@ -91,6 +94,9 @@ struct CompositingState { #if ENABLE(COMPOSITED_FIXED_ELEMENTS) bool m_fixedSibling; #endif +#if ENABLE(ANDROID_OVERFLOW_SCROLL) + bool m_hasScrollableElement; +#endif #ifndef NDEBUG int m_depth; #endif @@ -288,6 +294,10 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update // FIXME: we could maybe do this and the hierarchy udpate in one pass, but the parenting logic would be more complex. CompositingState compState(updateRoot); bool layersChanged = false; + +#if ENABLE(ANDROID_OVERFLOW_SCROLL) + compState.m_hasScrollableElement = false; +#endif if (m_compositingConsultsOverlap) { OverlapMap overlapTestRequestMap; computeCompositingRequirements(updateRoot, &overlapTestRequestMap, compState, layersChanged); @@ -589,14 +599,6 @@ bool RenderLayerCompositor::overlapsCompositedLayers(OverlapMap& overlapMap, con for (RenderLayerCompositor::OverlapMap::const_iterator it = overlapMap.begin(); it != end; ++it) { const IntRect& bounds = it->second; if (layerBounds.intersects(bounds)) { -#if ENABLE(COMPOSITED_FIXED_ELEMENTS) - RenderLayer* intersectedLayer = it->first; - if (intersectedLayer && intersectedLayer->isFixed()) { - if (bounds.contains(layerBounds)) { - continue; - } - } -#endif return true; } } @@ -604,6 +606,53 @@ bool RenderLayerCompositor::overlapsCompositedLayers(OverlapMap& overlapMap, con return false; } +#if ENABLE(COMPOSITED_FIXED_ELEMENTS) + +// to properly support z-index with composited fixed elements, we need to turn +// layers following a fixed layer into compositing mode; but if a layer is fully +// contained into a previous layer already composited (that is not the fixed +// layer), we don't need to composite it. This saves up quite a bit on the +// number of layers we have to composite. +// +bool RenderLayerCompositor::checkForFixedLayers(Vector* list, bool stopAtFixedLayer) +{ + size_t listSize = list->size(); + int haveFixedLayer = -1; + bool fixedSibling = false; + for (size_t j = 0; j < listSize; ++j) { + RenderLayer* currentLayer = list->at(j); + if (currentLayer->isFixed() && needsToBeComposited(currentLayer)) { + haveFixedLayer = j; + fixedSibling = true; + } + if (haveFixedLayer != -1 && haveFixedLayer != j) { + IntRect currentLayerBounds = currentLayer->renderer()->localToAbsoluteQuad( + FloatRect(currentLayer->localBoundingBox())).enclosingBoundingBox(); + bool needComposite = true; + int stop = 0; + if (stopAtFixedLayer) + stop = haveFixedLayer + 1; + + for (size_t k = j - 1; k >= stop; --k) { + RenderLayer* aLayer = list->at(k); + if (aLayer && aLayer->renderer()) { + IntRect bounds = aLayer->renderer()->localToAbsoluteQuad( + FloatRect(aLayer->localBoundingBox())).enclosingBoundingBox(); + if (bounds.contains(currentLayerBounds) + && needsToBeComposited(aLayer)) { + needComposite = false; + break; + } + } + } + currentLayer->setShouldComposite(needComposite); + } + } + return fixedSibling; +} + +#endif + // Recurse through the layers in z-index and overflow order (which is equivalent to painting order) // For the z-order children of a compositing layer: // If a child layers has a compositing layer, then all subsequent layers must @@ -636,7 +685,14 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O mustOverlapCompositedLayers = overlapsCompositedLayers(*overlapMap, absBounds); } +#if ENABLE(COMPOSITED_FIXED_ELEMENTS) + if (compositingState.m_fixedSibling) + layer->setMustOverlapCompositedLayers(layer->shouldComposite()); + else + layer->setMustOverlapCompositedLayers(mustOverlapCompositedLayers); +#else layer->setMustOverlapCompositedLayers(mustOverlapCompositedLayers); +#endif // The children of this layer don't need to composite, unless there is // a compositing layer among them, so start by inheriting the compositing @@ -648,17 +704,20 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O bool willBeComposited = needsToBeComposited(layer); -#if ENABLE(COMPOSITED_FIXED_ELEMENTS) - // If we are a fixed layer, signal it to our siblings - if (willBeComposited && layer->isFixed()) - compositingState.m_fixedSibling = true; - - if (!willBeComposited && compositingState.m_fixedSibling) { - layer->setMustOverlapCompositedLayers(true); - willBeComposited = true; - } +#if ENABLE(ANDROID_OVERFLOW_SCROLL) + // tell the parent it has scrollable descendants. + if (layer->hasOverflowScroll()) + compositingState.m_hasScrollableElement = true; #endif + +#if ENABLE(ANDROID_OVERFLOW_SCROLL) + // we don't want to signal that the subtree is compositing if the reason + // is because the layer is an overflow layer -- doing so would trigger + // all the above layers to be composited unnecessarily + if (willBeComposited && !layer->hasOverflowScroll()) { +#else if (willBeComposited) { +#endif // Tell the parent it has compositing descendants. compositingState.m_subtreeIsCompositing = true; // This layer now acts as the ancestor for kids. @@ -680,25 +739,10 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O if (Vector* negZOrderList = layer->negZOrderList()) { size_t listSize = negZOrderList->size(); #if ENABLE(COMPOSITED_FIXED_ELEMENTS) - childState.m_fixedSibling = false; - - // For the negative z-order, if we have a fixed layer - // we need to make all the siblings composited layers. - // Otherwise a negative layer (below the fixed layer) could - // still be drawn onto a higher z-order layer (e.g. the body) - // if not immediately intersecting with our fixed layer. - // So it's not enough here to only set m_fixedSibling for - // subsequent siblings as we do for the normal flow - // and positive z-order. - for (size_t j = 0; j < listSize; ++j) { - if ((negZOrderList->at(j))->isFixed() && - needsToBeComposited(negZOrderList->at(j))) { - childState.m_fixedSibling = true; - break; - } - } + childState.m_fixedSibling = compositingState.m_fixedSibling; + if (checkForFixedLayers(negZOrderList, false)) + childState.m_fixedSibling = true; #endif - for (size_t i = 0; i < listSize; ++i) { RenderLayer* curLayer = negZOrderList->at(i); computeCompositingRequirements(curLayer, overlapMap, childState, layersChanged); @@ -716,12 +760,14 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O } } } - + ASSERT(!layer->m_normalFlowListDirty); if (Vector* normalFlowList = layer->normalFlowList()) { size_t listSize = normalFlowList->size(); #if ENABLE(COMPOSITED_FIXED_ELEMENTS) - childState.m_fixedSibling = false; + childState.m_fixedSibling = compositingState.m_fixedSibling; + if (checkForFixedLayers(normalFlowList, true)) + childState.m_fixedSibling = true; #endif for (size_t i = 0; i < listSize; ++i) { RenderLayer* curLayer = normalFlowList->at(i); @@ -733,7 +779,9 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O if (Vector* posZOrderList = layer->posZOrderList()) { size_t listSize = posZOrderList->size(); #if ENABLE(COMPOSITED_FIXED_ELEMENTS) - childState.m_fixedSibling = false; + childState.m_fixedSibling = compositingState.m_fixedSibling; + if (checkForFixedLayers(posZOrderList, true)) + childState.m_fixedSibling = true; #endif for (size_t i = 0; i < listSize; ++i) { RenderLayer* curLayer = posZOrderList->at(i); @@ -768,6 +816,11 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O if (childState.m_subtreeIsCompositing) compositingState.m_subtreeIsCompositing = true; +#if ENABLE(ANDROID_OVERFLOW_SCROLL) + if (childState.m_hasScrollableElement) + compositingState.m_hasScrollableElement = true; +#endif + // Set the flag to say that this SC has compositing children. layer->setHasCompositingDescendant(childState.m_subtreeIsCompositing); @@ -781,7 +834,13 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O // If we're back at the root, and no other layers need to be composited, and the root layer itself doesn't need // to be composited, then we can drop out of compositing mode altogether. +#if ENABLE(ANDROID_OVERFLOW_SCROLL) + // We also need to check that we don't have a scrollable layer, as this + // would not have set the m_subtreeIsCompositing flag + if (layer->isRootLayer() && !childState.m_subtreeIsCompositing && !childState.m_hasScrollableElement && !requiresCompositingLayer(layer) && !m_forceCompositingMode) { +#else if (layer->isRootLayer() && !childState.m_subtreeIsCompositing && !requiresCompositingLayer(layer) && !m_forceCompositingMode) { +#endif enableCompositingMode(false); willBeComposited = false; } diff --git a/Source/WebCore/rendering/RenderLayerCompositor.h b/Source/WebCore/rendering/RenderLayerCompositor.h index 0315050..813e265 100644 --- a/Source/WebCore/rendering/RenderLayerCompositor.h +++ b/Source/WebCore/rendering/RenderLayerCompositor.h @@ -218,6 +218,10 @@ private: void updateCompositingLayersTimerFired(Timer*); +#if ENABLE(COMPOSITED_FIXED_ELEMENTS) + bool checkForFixedLayers(Vector* list, bool stopAtFixedLayer); +#endif + // Returns true if any layer's compositing changed void computeCompositingRequirements(RenderLayer*, OverlapMap*, struct CompositingState&, bool& layersChanged); -- cgit v1.1