Changeset 132591 in webkit


Ignore:
Timestamp:
Oct 26, 2012 2:34:07 AM (12 years ago)
Author:
jchaffraix@webkit.org
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).

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r132587 r132591  
     12012-10-26  Julien Chaffraix  <jchaffraix@webkit.org>
     2
     3        Generate less repaint calls during subtree detaching
     4        https://bugs.webkit.org/show_bug.cgi?id=99741
     5
     6        Reviewed by Eric Seidel.
     7
     8        * platform/chromium-linux/fast/repaint/selection-after-remove-expected.png:
     9        Rebaselined this test after the change. It is progressing as we still properly repaint
     10        the selection, but repaint less (ie don't repaint the top border which didn't change).
     11
    1122012-10-26  Kent Tamura  <tkent@chromium.org>
    213
  • trunk/Source/WebCore/ChangeLog

    r132589 r132591  
     12012-10-26  Julien Chaffraix  <jchaffraix@webkit.org>
     2
     3        Generate less repaint calls during subtree detaching
     4        https://bugs.webkit.org/show_bug.cgi?id=99741
     5
     6        Reviewed by Eric Seidel.
     7
     8        Following bug 98336, detach is now a subtree top-down operation. Because we
     9        track visual overflow from our children during layout for most cases, we can
     10        generate a repaint only on the subtree root.
     11
     12        On http://dglazkov.github.com/performance-tests/redraw.html, this ups the FPS to
     13        26 fps from 22 fps on my MBP (+ 15%). On PerformanceTests/layout/subtree-detach.html,
     14        it decreases the time by 35%. This is due to being the best case and we now generate
     15        only one repaint per detach phase.
     16
     17        Covered by existing pixels tests (including but not limited to repaint ones).
     18
     19        * rendering/RenderObject.cpp:
     20        (WebCore::RenderObject::destroyAndCleanupAnonymousWrappers):
     21        Changed the function not to be recursive anymore to generate one painting for
     22        our root only. Added a FIXME about using our RenderLayer for repainting to avoid
     23        the cost of computing our absolute repaint rectangle.
     24
     25        * rendering/RenderObjectChildList.cpp:
     26        (WebCore::RenderObjectChildList::removeChildNode):
     27        Removed the logic for repainting in the general case. However we still force a repaint
     28        if we have a RenderLayer as we don't track their overflow in some cases (e.g. positioned
     29        objects). This check is conservative and could be narrowed down (e.g overflow RenderLayers
     30        are properly accounted for in our clipppedOverflowRectForRepaint).
     31
    1322012-10-26  Kenichi Ishibashi  <bashi@chromium.org>
    233
  • trunk/Source/WebCore/rendering/RenderObject.cpp

    r132549 r132591  
    24512451void RenderObject::destroyAndCleanupAnonymousWrappers()
    24522452{
    2453     RenderObject* parent = this->parent();
    2454 
    2455     // If the tree is destroyed or our parent is not anonymous, there is no need for a clean-up phase.
    2456     if (documentBeingDestroyed() || !parent || !parent->isAnonymous()) {
     2453    // If the tree is destroyed, there is no need for a clean-up phase.
     2454    if (documentBeingDestroyed()) {
    24572455        destroy();
    24582456        return;
    24592457    }
    24602458
    2461     bool parentIsLeftOverAnonymousWrapper = false;
    2462 
    2463     // Currently we only remove anonymous cells' wrapper but we should remove all unneeded
    2464     // wrappers. See http://webkit.org/b/52123 as an example where this is needed.
    2465     if (parent->isTableCell())
    2466         parentIsLeftOverAnonymousWrapper = parent->firstChild() == this && parent->lastChild() == this;
    2467 
    2468     destroy();
     2459    RenderObject* destroyRoot = this;
     2460    for (RenderObject* destroyRootParent = destroyRoot->parent(); destroyRootParent && destroyRootParent->isAnonymous(); destroyRoot = destroyRootParent, destroyRootParent = destroyRootParent->parent()) {
     2461        // Currently we only remove anonymous cells' wrapper but we should remove all unneeded
     2462        // wrappers. See http://webkit.org/b/52123 as an example where this is needed.
     2463        if (!destroyRootParent->isTableCell())
     2464            break;
     2465
     2466        if (destroyRootParent->firstChild() != this || destroyRootParent->lastChild() != this)
     2467            break;
     2468    }
     2469
     2470    // We repaint, so that the area exposed when this object disappears gets repainted properly.
     2471    // FIXME: A RenderObject with RenderLayer should probably repaint through it as getting the
     2472    // repaint rects is O(1) through a RenderLayer (assuming it's up-to-date).
     2473    if (destroyRoot->everHadLayout()) {
     2474        if (destroyRoot->isBody())
     2475            destroyRoot->view()->repaint();
     2476        else
     2477            destroyRoot->repaint();
     2478    }
     2479
     2480    destroyRoot->destroy();
    24692481
    24702482    // WARNING: |this| is deleted here.
    2471 
    2472     if (parentIsLeftOverAnonymousWrapper) {
    2473         ASSERT(!parent->firstChild());
    2474         parent->destroyAndCleanupAnonymousWrappers();
    2475     }
    24762483}
    24772484
  • trunk/Source/WebCore/rendering/RenderObjectChildList.cpp

    r132529 r132591  
    6666
    6767    // So that we'll get the appropriate dirty bit set (either that a normal flow child got yanked or
    68     // that a positioned child got yanked).  We also repaint, so that the area exposed when the child
    69     // disappears gets repainted properly.
     68    // that a positioned child got yanked).
    7069    if (!owner->documentBeingDestroyed() && notifyRenderer && oldChild->everHadLayout()) {
    7170        oldChild->setNeedsLayoutAndPrefWidthsRecalc();
    72         if (oldChild->isBody())
    73             owner->view()->repaint();
    74         else
     71        // We only repaint |oldChild| if we have a RenderLayer as its visual overflow may not be tracked by its parent.
     72        if (oldChild->hasLayer())
    7573            oldChild->repaint();
    7674    }
Note: See TracChangeset for help on using the changeset viewer.