Title: [132591] trunk
Revision
132591
Author
[email protected]
Date
2012-10-26 02:34:07 -0700 (Fri, 26 Oct 2012)

Log Message

Generate less repaint calls during subtree detaching
https://bugs.webkit.org/show_bug.cgi?id=99741

Reviewed by Eric Seidel.

Source/WebCore:

Following bug 98336, detach is now a subtree top-down operation. Because we
track visual overflow from our children during layout for most cases, we can
generate a repaint only on the subtree root.

On http://dglazkov.github.com/performance-tests/redraw.html, this ups the FPS to
26 fps from 22 fps on my MBP (+ 15%). On PerformanceTests/layout/subtree-detach.html,
it decreases the time by 35%. This is due to being the best case and we now generate
only one repaint per detach phase.

Covered by existing pixels tests (including but not limited to repaint ones).

* rendering/RenderObject.cpp:
(WebCore::RenderObject::destroyAndCleanupAnonymousWrappers):
Changed the function not to be recursive anymore to generate one painting for
our root only. Added a FIXME about using our RenderLayer for repainting to avoid
the cost of computing our absolute repaint rectangle.

* rendering/RenderObjectChildList.cpp:
(WebCore::RenderObjectChildList::removeChildNode):
Removed the logic for repainting in the general case. However we still force a repaint
if we have a RenderLayer as we don't track their overflow in some cases (e.g. positioned
objects). This check is conservative and could be narrowed down (e.g overflow RenderLayers
are properly accounted for in our clipppedOverflowRectForRepaint).

LayoutTests:

* platform/chromium-linux/fast/repaint/selection-after-remove-expected.png:
Rebaselined this test after the change. It is progressing as we still properly repaint
the selection, but repaint less (ie don't repaint the top border which didn't change).

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (132590 => 132591)


--- trunk/LayoutTests/ChangeLog	2012-10-26 09:33:48 UTC (rev 132590)
+++ trunk/LayoutTests/ChangeLog	2012-10-26 09:34:07 UTC (rev 132591)
@@ -1,3 +1,14 @@
+2012-10-26  Julien Chaffraix  <[email protected]>
+
+        Generate less repaint calls during subtree detaching
+        https://bugs.webkit.org/show_bug.cgi?id=99741
+
+        Reviewed by Eric Seidel.
+
+        * platform/chromium-linux/fast/repaint/selection-after-remove-expected.png:
+        Rebaselined this test after the change. It is progressing as we still properly repaint
+        the selection, but repaint less (ie don't repaint the top border which didn't change).
+
 2012-10-26  Kent Tamura  <[email protected]>
 
         [Chromium] Test expectation update.

Modified: trunk/LayoutTests/platform/chromium-linux/fast/repaint/selection-after-remove-expected.png


(Binary files differ)

Modified: trunk/Source/WebCore/ChangeLog (132590 => 132591)


--- trunk/Source/WebCore/ChangeLog	2012-10-26 09:33:48 UTC (rev 132590)
+++ trunk/Source/WebCore/ChangeLog	2012-10-26 09:34:07 UTC (rev 132591)
@@ -1,3 +1,34 @@
+2012-10-26  Julien Chaffraix  <[email protected]>
+
+        Generate less repaint calls during subtree detaching
+        https://bugs.webkit.org/show_bug.cgi?id=99741
+
+        Reviewed by Eric Seidel.
+
+        Following bug 98336, detach is now a subtree top-down operation. Because we
+        track visual overflow from our children during layout for most cases, we can
+        generate a repaint only on the subtree root.
+
+        On http://dglazkov.github.com/performance-tests/redraw.html, this ups the FPS to
+        26 fps from 22 fps on my MBP (+ 15%). On PerformanceTests/layout/subtree-detach.html,
+        it decreases the time by 35%. This is due to being the best case and we now generate
+        only one repaint per detach phase.
+
+        Covered by existing pixels tests (including but not limited to repaint ones).
+
+        * rendering/RenderObject.cpp:
+        (WebCore::RenderObject::destroyAndCleanupAnonymousWrappers):
+        Changed the function not to be recursive anymore to generate one painting for
+        our root only. Added a FIXME about using our RenderLayer for repainting to avoid
+        the cost of computing our absolute repaint rectangle.
+
+        * rendering/RenderObjectChildList.cpp:
+        (WebCore::RenderObjectChildList::removeChildNode):
+        Removed the logic for repainting in the general case. However we still force a repaint
+        if we have a RenderLayer as we don't track their overflow in some cases (e.g. positioned
+        objects). This check is conservative and could be narrowed down (e.g overflow RenderLayers
+        are properly accounted for in our clipppedOverflowRectForRepaint).
+
 2012-10-26  Kenichi Ishibashi  <[email protected]>
 
         local(Helvetica) in src descriptor prevent fallback

Modified: trunk/Source/WebCore/rendering/RenderObject.cpp (132590 => 132591)


--- trunk/Source/WebCore/rendering/RenderObject.cpp	2012-10-26 09:33:48 UTC (rev 132590)
+++ trunk/Source/WebCore/rendering/RenderObject.cpp	2012-10-26 09:34:07 UTC (rev 132591)
@@ -2450,29 +2450,36 @@
 
 void RenderObject::destroyAndCleanupAnonymousWrappers()
 {
-    RenderObject* parent = this->parent();
-
-    // If the tree is destroyed or our parent is not anonymous, there is no need for a clean-up phase.
-    if (documentBeingDestroyed() || !parent || !parent->isAnonymous()) {
+    // If the tree is destroyed, there is no need for a clean-up phase.
+    if (documentBeingDestroyed()) {
         destroy();
         return;
     }
 
-    bool parentIsLeftOverAnonymousWrapper = false;
+    RenderObject* destroyRoot = this;
+    for (RenderObject* destroyRootParent = destroyRoot->parent(); destroyRootParent && destroyRootParent->isAnonymous(); destroyRoot = destroyRootParent, destroyRootParent = destroyRootParent->parent()) {
+        // Currently we only remove anonymous cells' wrapper but we should remove all unneeded
+        // wrappers. See http://webkit.org/b/52123 as an example where this is needed.
+        if (!destroyRootParent->isTableCell())
+            break;
 
-    // Currently we only remove anonymous cells' wrapper but we should remove all unneeded
-    // wrappers. See http://webkit.org/b/52123 as an example where this is needed.
-    if (parent->isTableCell())
-        parentIsLeftOverAnonymousWrapper = parent->firstChild() == this && parent->lastChild() == this;
+        if (destroyRootParent->firstChild() != this || destroyRootParent->lastChild() != this)
+            break;
+    }
 
-    destroy();
+    // We repaint, so that the area exposed when this object disappears gets repainted properly.
+    // FIXME: A RenderObject with RenderLayer should probably repaint through it as getting the
+    // repaint rects is O(1) through a RenderLayer (assuming it's up-to-date).
+    if (destroyRoot->everHadLayout()) {
+        if (destroyRoot->isBody())
+            destroyRoot->view()->repaint();
+        else
+            destroyRoot->repaint();
+    }
 
+    destroyRoot->destroy();
+
     // WARNING: |this| is deleted here.
-
-    if (parentIsLeftOverAnonymousWrapper) {
-        ASSERT(!parent->firstChild());
-        parent->destroyAndCleanupAnonymousWrappers();
-    }
 }
 
 void RenderObject::destroy()

Modified: trunk/Source/WebCore/rendering/RenderObjectChildList.cpp (132590 => 132591)


--- trunk/Source/WebCore/rendering/RenderObjectChildList.cpp	2012-10-26 09:33:48 UTC (rev 132590)
+++ trunk/Source/WebCore/rendering/RenderObjectChildList.cpp	2012-10-26 09:34:07 UTC (rev 132591)
@@ -65,13 +65,11 @@
         toRenderBox(oldChild)->removeFloatingOrPositionedChildFromBlockLists();
 
     // So that we'll get the appropriate dirty bit set (either that a normal flow child got yanked or
-    // that a positioned child got yanked).  We also repaint, so that the area exposed when the child
-    // disappears gets repainted properly.
+    // that a positioned child got yanked).
     if (!owner->documentBeingDestroyed() && notifyRenderer && oldChild->everHadLayout()) {
         oldChild->setNeedsLayoutAndPrefWidthsRecalc();
-        if (oldChild->isBody())
-            owner->view()->repaint();
-        else
+        // We only repaint |oldChild| if we have a RenderLayer as its visual overflow may not be tracked by its parent.
+        if (oldChild->hasLayer())
             oldChild->repaint();
     }
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to