Index: Source/core/rendering/RenderLayer.cpp |
diff --git a/Source/core/rendering/RenderLayer.cpp b/Source/core/rendering/RenderLayer.cpp |
index ef40889fb15879f48508ec0638e98382c9c74ccb..c564aa75a1f60d85ddc62382416319ea3a383fb9 100644 |
--- a/Source/core/rendering/RenderLayer.cpp |
+++ b/Source/core/rendering/RenderLayer.cpp |
@@ -1133,23 +1133,49 @@ RenderLayer* RenderLayer::enclosingCompositingLayerForRepaint(IncludeSelfOrNot i |
return 0; |
} |
-RenderLayer* RenderLayer::ancestorCompositedScrollingLayer() const |
+void RenderLayer::clearAncestorDependentPropertyCache() |
{ |
- ASSERT(isAllowedToQueryCompositingState()); |
+ ASSERT(isInCompositingUpdate()); |
+ m_ancestorDependentPropertyCache.clear(); |
+} |
+ |
+void RenderLayer::ensureAncestorDependentPropertyCache() const |
+{ |
+ ASSERT(isInCompositingUpdate()); |
+ if (m_ancestorDependentPropertyCache) |
+ return; |
+ m_ancestorDependentPropertyCache = adoptPtr(new AncestorDependentPropertyCache()); |
+} |
+RenderLayer* RenderLayer::ancestorCompositedScrollingLayer() const |
+{ |
if (!renderer()->acceleratedCompositingForOverflowScrollEnabled()) |
return 0; |
+ ASSERT(isInCompositingUpdate() || !m_ancestorDependentPropertyCache); |
+ |
+ if (m_ancestorDependentPropertyCache && !m_ancestorDependentPropertyCache->ancestorCompositedScrollingLayerDirty()) |
+ return m_ancestorDependentPropertyCache->ancestorCompositedScrollingLayer(); |
+ |
RenderObject* containingBlock = renderer()->containingBlock(); |
if (!containingBlock) |
return 0; |
+ if (isInCompositingUpdate()) |
+ ensureAncestorDependentPropertyCache(); |
+ |
+ RenderLayer* ancestorCompositedScrollingLayer = 0; |
for (RenderLayer* ancestorLayer = containingBlock->enclosingLayer(); ancestorLayer; ancestorLayer = ancestorLayer->parent()) { |
- if (ancestorLayer->needsCompositedScrolling()) |
- return ancestorLayer; |
+ if (ancestorLayer->needsCompositedScrolling()) { |
+ ancestorCompositedScrollingLayer = ancestorLayer; |
+ break; |
+ } |
} |
- return 0; |
+ if (m_ancestorDependentPropertyCache) |
+ m_ancestorDependentPropertyCache->setAncestorCompositedScrollingLayer(ancestorCompositedScrollingLayer); |
+ |
+ return ancestorCompositedScrollingLayer; |
} |
RenderLayer* RenderLayer::ancestorScrollingLayer() const |
@@ -1677,6 +1703,10 @@ RenderLayer* RenderLayer::scrollParent() const |
if (stackingNode()->isNormalFlowOnly()) |
return 0; |
+ // We should never have an ancestor dependent property cache outside of the |
+ // compositing update phase. |
+ ASSERT(isInCompositingUpdate() || !m_ancestorDependentPropertyCache); |
+ |
// A layer scrolls with its containing block. So to find the overflow scrolling layer |
// that we scroll with respect to, we must ascend the layer tree until we reach the |
// first overflow scrolling div at or above our containing block. I will refer to this |
@@ -1689,8 +1719,10 @@ RenderLayer* RenderLayer::scrollParent() const |
// our scrolling ancestor, and we will therefore not scroll with it. In this case, we must |
// be a composited layer since the compositor will need to take special measures to ensure |
// that we scroll with our scrolling ancestor and it cannot do this if we do not promote. |
- RenderLayer* scrollParent = ancestorCompositedScrollingLayer(); |
+ if (m_ancestorDependentPropertyCache && !m_ancestorDependentPropertyCache->scrollParentDirty()) |
+ return m_ancestorDependentPropertyCache->scrollParent(); |
+ RenderLayer* scrollParent = ancestorCompositedScrollingLayer(); |
if (!scrollParent || scrollParent->stackingNode()->isStackingContainer()) |
return 0; |
@@ -1699,8 +1731,18 @@ RenderLayer* RenderLayer::scrollParent() const |
for (RenderLayer* ancestor = parent(); ancestor && ancestor != scrollParent; ancestor = ancestor->parent()) { |
if (ancestor->stackingNode()->isStackingContainer()) |
return 0; |
+ if (!isInCompositingUpdate()) |
+ continue; |
+ if (AncestorDependentPropertyCache* ancestorCache = ancestor->m_ancestorDependentPropertyCache.get()) { |
+ if (!ancestorCache->ancestorCompositedScrollingLayerDirty() && ancestorCache->ancestorCompositedScrollingLayer() == scrollParent) { |
+ scrollParent = ancestorCache->scrollParent(); |
+ break; |
+ } |
+ } |
} |
+ if (m_ancestorDependentPropertyCache) |
+ m_ancestorDependentPropertyCache->setScrollParent(scrollParent); |
return scrollParent; |
} |
@@ -3520,6 +3562,11 @@ bool RenderLayer::isAllowedToQueryCompositingState() const |
return renderer()->document().lifecycle().state() >= DocumentLifecycle::InCompositingUpdate; |
} |
+bool RenderLayer::isInCompositingUpdate() const |
+{ |
+ return renderer()->document().lifecycle().state() == DocumentLifecycle::InCompositingUpdate; |
+} |
+ |
CompositedLayerMappingPtr RenderLayer::compositedLayerMapping() const |
{ |
ASSERT(isAllowedToQueryCompositingState()); |
@@ -4059,6 +4106,36 @@ DisableCompositingQueryAsserts::DisableCompositingQueryAsserts() |
COMPILE_ASSERT(1 << RenderLayer::ViewportConstrainedNotCompositedReasonBits >= RenderLayer::NumNotCompositedReasons, too_many_viewport_constrained_not_compositing_reasons); |
+RenderLayer::AncestorDependentPropertyCache::AncestorDependentPropertyCache() |
+ : m_ancestorCompositedScrollingLayer(0) |
+ , m_scrollParent(0) |
+ , m_ancestorCompositedScrollingLayerDirty(true) |
+ , m_scrollParentDirty(true) { } |
+ |
+RenderLayer* RenderLayer::AncestorDependentPropertyCache::scrollParent() const |
+{ |
+ ASSERT(!m_scrollParentDirty); |
+ return m_scrollParent; |
+} |
+ |
+void RenderLayer::AncestorDependentPropertyCache::setScrollParent(RenderLayer* scrollParent) |
+{ |
+ m_scrollParent = scrollParent; |
+ m_scrollParentDirty = false; |
+} |
+ |
+RenderLayer* RenderLayer::AncestorDependentPropertyCache::ancestorCompositedScrollingLayer() const |
+{ |
+ ASSERT(!m_ancestorCompositedScrollingLayerDirty); |
+ return m_ancestorCompositedScrollingLayer; |
+} |
+ |
+void RenderLayer::AncestorDependentPropertyCache::setAncestorCompositedScrollingLayer(RenderLayer* layer) |
+{ |
+ m_ancestorCompositedScrollingLayer = layer; |
+ m_ancestorCompositedScrollingLayerDirty = false; |
+} |
+ |
} // namespace WebCore |
#ifndef NDEBUG |