Title: [121124] trunk/Source/WebCore
Revision
121124
Author
[email protected]
Date
2012-06-24 17:14:23 -0700 (Sun, 24 Jun 2012)

Log Message

Optimize RenderGeometryMap mappings gathering
https://bugs.webkit.org/show_bug.cgi?id=89828

Reviewed by Simon Fraser.

RenderGeometryMap currently gathers mappings by climbing the rendering tree. This is slow and can produce 
large number of mapping steps. In the common case we already have the child layer coordinates available in
the layer tree and we can just use that.
        
The combination of faster mappings gathering and fewer number of applying steps reduces time spent under 
RenderLayerCompositor::computeCompositingRequirements to less than half when scrolling the mobile version
of twitter.com.
        
* rendering/RenderGeometryMap.cpp:
(WebCore):
(WebCore::RenderGeometryMap::pushMappingsToAncestor):
        
    Use pre-computed mapping from the layer tree when possible.

(WebCore::RenderGeometryMap::popMappingsToAncestor):
* rendering/RenderGeometryMap.h:
        
    Add some inline capacity.

(WebCore):
(RenderGeometryMap):
* rendering/RenderLayer.h:
(WebCore::RenderLayer::canUseConvertToLayerCoords):
(RenderLayer):
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::addToOverlapMapRecursive):
(WebCore::RenderLayerCompositor::computeCompositingRequirements):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (121123 => 121124)


--- trunk/Source/WebCore/ChangeLog	2012-06-25 00:11:30 UTC (rev 121123)
+++ trunk/Source/WebCore/ChangeLog	2012-06-25 00:14:23 UTC (rev 121124)
@@ -1,3 +1,38 @@
+2012-06-24  Antti Koivisto  <[email protected]>
+
+        Optimize RenderGeometryMap mappings gathering
+        https://bugs.webkit.org/show_bug.cgi?id=89828
+
+        Reviewed by Simon Fraser.
+
+        RenderGeometryMap currently gathers mappings by climbing the rendering tree. This is slow and can produce 
+        large number of mapping steps. In the common case we already have the child layer coordinates available in
+        the layer tree and we can just use that.
+        
+        The combination of faster mappings gathering and fewer number of applying steps reduces time spent under 
+        RenderLayerCompositor::computeCompositingRequirements to less than half when scrolling the mobile version
+        of twitter.com.
+        
+        * rendering/RenderGeometryMap.cpp:
+        (WebCore):
+        (WebCore::RenderGeometryMap::pushMappingsToAncestor):
+        
+            Use pre-computed mapping from the layer tree when possible.
+
+        (WebCore::RenderGeometryMap::popMappingsToAncestor):
+        * rendering/RenderGeometryMap.h:
+        
+            Add some inline capacity.
+
+        (WebCore):
+        (RenderGeometryMap):
+        * rendering/RenderLayer.h:
+        (WebCore::RenderLayer::canUseConvertToLayerCoords):
+        (RenderLayer):
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::addToOverlapMapRecursive):
+        (WebCore::RenderLayerCompositor::computeCompositingRequirements):
+
 2012-06-24  Simon Fraser  <[email protected]>
 
         Rename isPositioned to isOutOfFlowPositioned for clarity

Modified: trunk/Source/WebCore/rendering/RenderGeometryMap.cpp (121123 => 121124)


--- trunk/Source/WebCore/rendering/RenderGeometryMap.cpp	2012-06-25 00:11:30 UTC (rev 121123)
+++ trunk/Source/WebCore/rendering/RenderGeometryMap.cpp	2012-06-25 00:14:23 UTC (rev 121124)
@@ -26,12 +26,13 @@
 #include "config.h"
 #include "RenderGeometryMap.h"
 
+#include "RenderLayer.h"
 #include "RenderView.h"
 #include "TransformState.h"
+#include <wtf/TemporaryChange.h>
 
 namespace WebCore {
 
-
 // Stores data about how to map from one renderer to its container.
 class RenderGeometryMapStep {
     WTF_MAKE_NONCOPYABLE(RenderGeometryMapStep);
@@ -170,20 +171,35 @@
     transformState.flatten();    
 }
 
-void RenderGeometryMap::pushMappingsToAncestor(const RenderObject* renderer, const RenderBoxModelObject* ancestor)
+void RenderGeometryMap::pushMappingsToAncestor(const RenderObject* renderer, const RenderBoxModelObject* ancestorRenderer)
 {
-    const RenderObject* currRenderer = renderer;
-    
     // We need to push mappings in reverse order here, so do insertions rather than appends.
-    m_insertionPosition = m_mapping.size();
-    
+    TemporaryChange<size_t> positionChange(m_insertionPosition, m_mapping.size());
     do {
-        currRenderer = currRenderer->pushMappingToContainer(ancestor, *this);
-    } while (currRenderer && currRenderer != ancestor);
-    
-    m_insertionPosition = notFound;
+        renderer = renderer->pushMappingToContainer(ancestorRenderer, *this);
+    } while (renderer && renderer != ancestorRenderer);
 }
 
+void RenderGeometryMap::pushMappingsToAncestor(const RenderLayer* layer, const RenderLayer* ancestorLayer)
+{
+    const RenderObject* renderer = layer->renderer();
+
+    // The simple case can be handled fast in the layer tree.
+    bool canConvertInLayerTree = ancestorLayer && renderer->style()->position() != FixedPosition;
+    for (const RenderLayer* current = layer; current != ancestorLayer && canConvertInLayerTree; current = current->parent())
+        canConvertInLayerTree = current->canUseConvertToLayerCoords();
+
+    if (canConvertInLayerTree) {
+        TemporaryChange<size_t> positionChange(m_insertionPosition, m_mapping.size());
+        LayoutPoint layerOffset;
+        layer->convertToLayerCoords(ancestorLayer, layerOffset);
+        push(renderer, toLayoutSize(layerOffset), /*accumulatingTransform*/ true, /*isNonUniform*/ false, /*isFixedPosition*/ false, /*hasTransform*/ false);
+        return;
+    }
+    const RenderBoxModelObject* ancestorRenderer = ancestorLayer ? ancestorLayer->renderer() : 0;
+    pushMappingsToAncestor(renderer, ancestorRenderer);
+}
+
 void RenderGeometryMap::push(const RenderObject* renderer, const LayoutSize& offsetFromContainer, bool accumulatingTransform, bool isNonUniform, bool isFixedPosition, bool hasTransform)
 {
     ASSERT(m_insertionPosition != notFound);
@@ -220,16 +236,22 @@
     m_mapping.insert(m_insertionPosition, step.release());
 }
 
-void RenderGeometryMap::popMappingsToAncestor(const RenderBoxModelObject* ancestor)
+void RenderGeometryMap::popMappingsToAncestor(const RenderBoxModelObject* ancestorRenderer)
 {
     ASSERT(m_mapping.size());
 
-    while (m_mapping.size() && m_mapping.last()->m_renderer != ancestor) {
+    while (m_mapping.size() && m_mapping.last()->m_renderer != ancestorRenderer) {
         stepRemoved(*m_mapping.last().get());
         m_mapping.removeLast();
     }
 }
 
+void RenderGeometryMap::popMappingsToAncestor(const RenderLayer* ancestorLayer)
+{
+    const RenderBoxModelObject* ancestorRenderer = ancestorLayer ? ancestorLayer->renderer() : 0;
+    popMappingsToAncestor(ancestorRenderer);
+}
+
 void RenderGeometryMap::stepInserted(const RenderGeometryMapStep& step)
 {
     // Offset on the first step is the RenderView's offset, which is only applied when we have fixed-position.s

Modified: trunk/Source/WebCore/rendering/RenderGeometryMap.h (121123 => 121124)


--- trunk/Source/WebCore/rendering/RenderGeometryMap.h	2012-06-25 00:11:30 UTC (rev 121123)
+++ trunk/Source/WebCore/rendering/RenderGeometryMap.h	2012-06-25 00:14:23 UTC (rev 121124)
@@ -36,6 +36,7 @@
 namespace WebCore {
 
 class RenderGeometryMapStep;
+class RenderLayer;
 
 // Can be used while walking the Renderer tree to cache data about offsets and transforms.
 class RenderGeometryMap {
@@ -47,7 +48,9 @@
     FloatRect absoluteRect(const FloatRect&) const;
     
     // Called by code walking the renderer or layer trees.
-    void pushMappingsToAncestor(const RenderObject*, const RenderBoxModelObject* ancestor);
+    void pushMappingsToAncestor(const RenderLayer*, const RenderLayer* ancestorLayer);
+    void popMappingsToAncestor(const RenderLayer*);
+    void pushMappingsToAncestor(const RenderObject*, const RenderBoxModelObject* ancestorRenderer);
     void popMappingsToAncestor(const RenderBoxModelObject*);
     
     // The following methods should only be called by renderers inside a call to pushMappingsToAncestor().
@@ -70,8 +73,8 @@
     bool hasTransformStep() const { return m_transformedStepsCount; }
     bool hasFixedPositionStep() const { return m_fixedStepsCount; }
     
-    typedef Vector<OwnPtr<RenderGeometryMapStep> > RenderGeometryMapSteps; // FIXME: inline capacity?
-    
+    typedef Vector<OwnPtr<RenderGeometryMapStep>, 32> RenderGeometryMapSteps;
+
     size_t m_insertionPosition;
     int m_nonUniformStepsCount;
     int m_transformedStepsCount;

Modified: trunk/Source/WebCore/rendering/RenderLayer.h (121123 => 121124)


--- trunk/Source/WebCore/rendering/RenderLayer.h	2012-06-25 00:11:30 UTC (rev 121123)
+++ trunk/Source/WebCore/rendering/RenderLayer.h	2012-06-25 00:14:23 UTC (rev 121124)
@@ -473,6 +473,16 @@
     void setFilterBackendNeedsRepaintingInRect(const LayoutRect&, bool immediate);
 #endif
 
+    bool canUseConvertToLayerCoords() const
+    {
+        // These RenderObject have an impact on their layers' without them knowing about it.
+        return !renderer()->hasColumns() && !renderer()->hasTransform() && !isComposited()
+#if ENABLE(SVG)
+            && !renderer()->isSVGRoot()
+#endif
+            ;
+    }
+
     void convertToPixelSnappedLayerCoords(const RenderLayer* ancestorLayer, IntPoint& location) const;
     void convertToPixelSnappedLayerCoords(const RenderLayer* ancestorLayer, IntRect&) const;
     void convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutPoint& location) const;
@@ -858,16 +868,6 @@
     LayoutUnit overflowLeft() const;
     LayoutUnit overflowRight() const;
 
-    bool canUseConvertToLayerCoords() const
-    {
-        // These RenderObject have an impact on their layers' without them knowing about it.
-        return !renderer()->hasColumns() && !renderer()->hasTransform() && !isComposited()
-#if ENABLE(SVG)
-            && !renderer()->isSVGRoot()
-#endif
-            ;
-    }
-
     LayoutUnit verticalScrollbarStart(int minX, int maxX) const;
     LayoutUnit horizontalScrollbarStart(int minX) const;
 

Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp (121123 => 121124)


--- trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp	2012-06-25 00:11:30 UTC (rev 121123)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp	2012-06-25 00:14:23 UTC (rev 121124)
@@ -671,7 +671,7 @@
 
     // A null ancestorLayer is an indication that 'layer' has already been pushed.
     if (ancestorLayer)
-        overlapMap.geometryMap().pushMappingsToAncestor(layer->renderer(), ancestorLayer->renderer());
+        overlapMap.geometryMap().pushMappingsToAncestor(layer, ancestorLayer);
     
     IntRect bounds;
     bool haveComputedBounds = false;
@@ -710,7 +710,7 @@
     }
     
     if (ancestorLayer)
-        overlapMap.geometryMap().popMappingsToAncestor(ancestorLayer->renderer());
+        overlapMap.geometryMap().popMappingsToAncestor(ancestorLayer);
 }
 
 //  Recurse through the layers in z-index and overflow order (which is equivalent to painting order)
@@ -727,7 +727,7 @@
     layer->updateLayerListsIfNeeded();
     
     if (overlapMap)
-        overlapMap->geometryMap().pushMappingsToAncestor(layer->renderer(), ancestorLayer ? ancestorLayer->renderer() : 0);
+        overlapMap->geometryMap().pushMappingsToAncestor(layer, ancestorLayer);
     
     // Clear the flag
     layer->setHasCompositingDescendant(false);
@@ -910,7 +910,7 @@
     descendantHas3DTransform |= anyDescendantHas3DTransform || layer->has3DTransform();
 
     if (overlapMap)
-        overlapMap->geometryMap().popMappingsToAncestor(ancestorLayer ? ancestorLayer->renderer() : 0);
+        overlapMap->geometryMap().popMappingsToAncestor(ancestorLayer);
 }
 
 void RenderLayerCompositor::setCompositingParent(RenderLayer* childLayer, RenderLayer* parentLayer)
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to