Changeset 141039 in webkit


Ignore:
Timestamp:
Jan 28, 2013 8:16:56 PM (11 years ago)
Author:
Simon Fraser
Message:

position:fixed that doesn't render any content should not force compositing
https://bugs.webkit.org/show_bug.cgi?id=108112

Source/WebCore:

Reviewed by Beth Dakin.

It's not uncommon for pages to have position:fixed elements with no content.
When these are behind other elements, they can cause those other elements
to become composited, using lots of backing store memory.

Optimize for the case where the position:fixed element has no rendered
content and no children by not making it composited in that case.

Test: compositing/layer-creation/fixed-position-no-content.html

  • rendering/RenderLayer.cpp:

(WebCore::RenderLayer::hasNonEmptyChildRenderers): Moved from RenderLayerBacking.cpp.
(WebCore::hasBoxDecorations): Ditto.
(WebCore::RenderLayer::hasBoxDecorationsOrBackground): Ditto.
(WebCore::RenderLayer::hasVisibleBoxDecorations): Check for visibility:visible, box decorations and
overflow controls.
(WebCore::RenderLayer::isVisuallyNonEmpty): Returns true if this layer has some visible
representation.

  • rendering/RenderLayer.h:
  • rendering/RenderLayerBacking.cpp:

(WebCore::RenderLayerBacking::updateGraphicsLayerConfiguration): Need to call updateDescendantDependentFlags()
to ensure that the visibility flags are up to date.
(WebCore::RenderLayerBacking::updateDrawsContent): Call RenderLayer::hasBoxDecorationsOrBackground() now.
(WebCore::RenderLayerBacking::paintsBoxDecorations): Call RenderLayer::hasVisibleBoxDecorations() now.
(WebCore::RenderLayerBacking::paintsChildren): Call RenderLayer::hasNonEmptyChildRenderers().
(WebCore::RenderLayerBacking::isSimpleContainerCompositingLayer): Whitespace.
(WebCore::RenderLayerBacking::containsPaintedContent): Call RenderLayer::hasBoxDecorationsOrBackground().
(WebCore::RenderLayerBacking::isDirectlyCompositedImage): Ditto.

  • rendering/RenderLayerBacking.h:

(RenderLayerBacking):

  • rendering/RenderLayerCompositor.cpp:

(WebCore::RenderLayerCompositor::requiresCompositingForPosition): If the layer has no content to paint,
or visible descendant layers, then don't make it composited.

LayoutTests:

Reviewed by Beth Dakin.

Change tests to put a background color on position:fixed elements that need to be composited.
New test with an empty fixed position element.

  • compositing/layer-creation/fixed-position-change-out-of-view-in-view.html:
  • compositing/layer-creation/fixed-position-no-content-expected.txt: Added.
  • compositing/layer-creation/fixed-position-no-content.html: Copied from LayoutTests/compositing/layer-creation/fixed-position-out-of-view.html.
  • compositing/layer-creation/fixed-position-out-of-view-scaled-scroll.html:
  • compositing/layer-creation/fixed-position-out-of-view-scaled.html:
  • compositing/layer-creation/fixed-position-out-of-view.html:
  • platform/mac/tiled-drawing/fixed/fixed-position-out-of-view-negative-zindex.html:
  • platform/mac/tiled-drawing/fixed/fixed-position-out-of-view.html:
Location:
trunk
Files:
1 added
13 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r141038 r141039  
     12013-01-28  Simon Fraser  <simon.fraser@apple.com>
     2
     3        position:fixed that doesn't render any content should not force compositing
     4        https://bugs.webkit.org/show_bug.cgi?id=108112
     5
     6        Reviewed by Beth Dakin.
     7       
     8        Change tests to put a background color on position:fixed elements that need to be composited.
     9        New test with an empty fixed position element.
     10
     11        * compositing/layer-creation/fixed-position-change-out-of-view-in-view.html:
     12        * compositing/layer-creation/fixed-position-no-content-expected.txt: Added.
     13        * compositing/layer-creation/fixed-position-no-content.html: Copied from LayoutTests/compositing/layer-creation/fixed-position-out-of-view.html.
     14        * compositing/layer-creation/fixed-position-out-of-view-scaled-scroll.html:
     15        * compositing/layer-creation/fixed-position-out-of-view-scaled.html:
     16        * compositing/layer-creation/fixed-position-out-of-view.html:
     17        * platform/mac/tiled-drawing/fixed/fixed-position-out-of-view-negative-zindex.html:
     18        * platform/mac/tiled-drawing/fixed/fixed-position-out-of-view.html:
     19
    1202013-01-28  Keishi Hattori  <keishi@webkit.org>
    221
  • trunk/LayoutTests/compositing/layer-creation/fixed-position-change-out-of-view-in-view.html

    r140593 r141039  
    33<html>
    44<head>
     5  <style>
     6    #fixed1, #fixed2 {
     7        background-color: silver;
     8    }
     9  </style>
    510  <script type="text/javascript">
    611    if (window.testRunner && window.internals) {
  • trunk/LayoutTests/compositing/layer-creation/fixed-position-no-content.html

    r141038 r141039  
    66    .fixed {
    77      position: fixed;
    8       width: 10px;
    9       height: 10px;
     8      width: 50px;
     9      height: 50px;
     10    }
     11   
     12    .absolute {
     13        position: absolute;
     14        top: 40px;
     15        left: 40px;
     16        height: 100px;
     17        width: 100px;
     18        background-color: gray;
    1019    }
    1120  </style>
     
    2736<body>
    2837  <div style="height: 1000px">
     38    <p>There should be no layers.</p>
    2939    <pre id="layertree"></pre>
    3040  </div>
    3141
    32   <!-- Neither of the following elements gets its own layer. -->
    33   <div class="fixed" style="z-index: -1"></div>
    34   <div class="fixed" style="z-index: -1; top: -100px"></div>
    35   <div class="fixed" style="z-index: -1; top: 0px; left: 1000px"></div>
    36 
    37   <!-- This element gets its own layer because it intersects with the viewport. -->
    38   <div class="fixed" style="z-index: -1; top: 0px; left: 0px"></div>
     42  <!-- This should not be composited -->
     43  <div class="fixed" style="top: 10px; left: 10px"></div>
     44  <!-- And this should not be promoted into a layer -->
     45  <div class="absolute"></div>
    3946</body>
    4047</html>
  • trunk/LayoutTests/compositing/layer-creation/fixed-position-out-of-view-scaled-scroll.html

    r138840 r141039  
    77    width: 10px;
    88    height: 10px;
     9    background-color: silver;
    910  }
    1011</style>
  • trunk/LayoutTests/compositing/layer-creation/fixed-position-out-of-view-scaled.html

    r138840 r141039  
    77    width: 10px;
    88    height: 10px;
     9    background-color: silver;
    910  }
    1011</style>
  • trunk/LayoutTests/compositing/layer-creation/fixed-position-out-of-view.html

    r138840 r141039  
    88      width: 10px;
    99      height: 10px;
     10      background-color: silver;
    1011    }
    1112  </style>
  • trunk/LayoutTests/platform/mac/tiled-drawing/fixed/fixed-position-out-of-view-negative-zindex.html

    r133536 r141039  
    88      width: 10px;
    99      height: 10px;
     10      background-color: silver;
    1011    }
    1112  </style>
  • trunk/LayoutTests/platform/mac/tiled-drawing/fixed/fixed-position-out-of-view.html

    r133536 r141039  
    88      width: 10px;
    99      height: 10px;
     10      background-color: silver;
    1011    }
    1112  </style>
  • trunk/Source/WebCore/ChangeLog

    r141036 r141039  
     12013-01-28  Simon Fraser  <simon.fraser@apple.com>
     2
     3        position:fixed that doesn't render any content should not force compositing
     4        https://bugs.webkit.org/show_bug.cgi?id=108112
     5
     6        Reviewed by Beth Dakin.
     7       
     8        It's not uncommon for pages to have position:fixed elements with no content.
     9        When these are behind other elements, they can cause those other elements
     10        to become composited, using lots of backing store memory.
     11       
     12        Optimize for the case where the position:fixed element has no rendered
     13        content and no children by not making it composited in that case.
     14
     15        Test: compositing/layer-creation/fixed-position-no-content.html
     16
     17        * rendering/RenderLayer.cpp:
     18        (WebCore::RenderLayer::hasNonEmptyChildRenderers): Moved from RenderLayerBacking.cpp.
     19        (WebCore::hasBoxDecorations): Ditto.
     20        (WebCore::RenderLayer::hasBoxDecorationsOrBackground): Ditto.
     21        (WebCore::RenderLayer::hasVisibleBoxDecorations): Check for visibility:visible, box decorations and
     22        overflow controls.
     23        (WebCore::RenderLayer::isVisuallyNonEmpty): Returns true if this layer has some visible
     24        representation.
     25        * rendering/RenderLayer.h:
     26        * rendering/RenderLayerBacking.cpp:
     27        (WebCore::RenderLayerBacking::updateGraphicsLayerConfiguration): Need to call updateDescendantDependentFlags()
     28        to ensure that the visibility flags are up to date.
     29        (WebCore::RenderLayerBacking::updateDrawsContent): Call RenderLayer::hasBoxDecorationsOrBackground() now.
     30        (WebCore::RenderLayerBacking::paintsBoxDecorations): Call RenderLayer::hasVisibleBoxDecorations() now.
     31        (WebCore::RenderLayerBacking::paintsChildren): Call RenderLayer::hasNonEmptyChildRenderers().
     32        (WebCore::RenderLayerBacking::isSimpleContainerCompositingLayer): Whitespace.
     33        (WebCore::RenderLayerBacking::containsPaintedContent): Call RenderLayer::hasBoxDecorationsOrBackground().
     34        (WebCore::RenderLayerBacking::isDirectlyCompositedImage): Ditto.
     35        * rendering/RenderLayerBacking.h:
     36        (RenderLayerBacking):
     37        * rendering/RenderLayerCompositor.cpp:
     38        (WebCore::RenderLayerCompositor::requiresCompositingForPosition): If the layer has no content to paint,
     39        or visible descendant layers, then don't make it composited.
     40
    1412013-01-28  Simon Fraser  <simon.fraser@apple.com>
    242
  • trunk/Source/WebCore/rendering/RenderLayer.cpp

    r140999 r141039  
    54055405}
    54065406
     5407bool RenderLayer::hasNonEmptyChildRenderers() const
     5408{
     5409    // Some HTML can cause whitespace text nodes to have renderers, like:
     5410    // <div>
     5411    // <img src=...>
     5412    // </div>
     5413    // so test for 0x0 RenderTexts here
     5414    for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
     5415        if (!child->hasLayer()) {
     5416            if (child->isRenderInline() || !child->isBox())
     5417                return true;
     5418       
     5419            if (toRenderBox(child)->width() > 0 || toRenderBox(child)->height() > 0)
     5420                return true;
     5421        }
     5422    }
     5423    return false;
     5424}
     5425
     5426static bool hasBoxDecorations(const RenderStyle* style)
     5427{
     5428    return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow() || style->hasFilter();
     5429}
     5430
     5431bool RenderLayer::hasBoxDecorationsOrBackground() const
     5432{
     5433    return hasBoxDecorations(renderer()->style()) || renderer()->hasBackground();
     5434}
     5435
     5436bool RenderLayer::hasVisibleBoxDecorations() const
     5437{
     5438    if (!hasVisibleContent())
     5439        return false;
     5440
     5441    return hasBoxDecorationsOrBackground() || hasOverflowControls();
     5442}
     5443
     5444bool RenderLayer::isVisuallyNonEmpty() const
     5445{
     5446    ASSERT(!m_visibleDescendantStatusDirty);
     5447
     5448    if (hasVisibleContent() && hasNonEmptyChildRenderers())
     5449        return true;
     5450
     5451    if (renderer()->isReplaced() || renderer()->hasMask())
     5452        return true;
     5453
     5454    if (hasVisibleBoxDecorations())
     5455        return true;
     5456
     5457    return false;
     5458}
     5459
    54075460void RenderLayer::updateStackingContextsAfterStyleChange(const RenderStyle* oldStyle)
    54085461{
  • trunk/Source/WebCore/rendering/RenderLayer.h

    r140999 r141039  
    474474    void dirtyVisibleContentStatus();
    475475
     476    bool hasBoxDecorationsOrBackground() const;
     477    bool hasVisibleBoxDecorations() const;
     478    // Returns true if this layer has visible content (ignoring any child layers).
     479    bool isVisuallyNonEmpty() const;
     480    // True if this layer container renderers that paint.
     481    bool hasNonEmptyChildRenderers() const;
     482
    476483    // FIXME: We should ASSERT(!m_hasSelfPaintingLayerDescendantDirty); here but we hit the same bugs as visible content above.
    477484    // Part of the issue is with subtree relayout: we don't check if our ancestors have some descendant flags dirty, missing some updates.
  • trunk/Source/WebCore/rendering/RenderLayerBacking.cpp

    r140873 r141039  
    7777using namespace HTMLNames;
    7878
    79 static bool hasBoxDecorations(const RenderStyle*);
    80 static bool hasBoxDecorationsOrBackground(const RenderObject*);
    8179static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle*);
    8280static IntRect clipBox(RenderBox* renderer);
     
    475473    RenderObject* renderer = this->renderer();
    476474
     475    m_owningLayer->updateDescendantDependentFlags();
    477476    m_owningLayer->updateZOrderLists();
    478477
     
    913912        // m_scrollingLayer never has backing store.
    914913        // m_scrollingContentsLayer only needs backing store if the scrolled contents need to paint.
    915         bool hasNonScrollingPaintedContent = m_owningLayer->hasVisibleContent() && hasBoxDecorationsOrBackground(renderer());
     914        bool hasNonScrollingPaintedContent = m_owningLayer->hasVisibleContent() && m_owningLayer->hasBoxDecorationsOrBackground();
    916915        m_graphicsLayer->setDrawsContent(hasNonScrollingPaintedContent);
    917916
     
    12851284}
    12861285
    1287 static bool hasBoxDecorationsOrBackground(const RenderObject* renderer)
    1288 {
    1289     return hasBoxDecorations(renderer->style()) || renderer->hasBackground();
    1290 }
    1291 
    12921286static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle* style)
    12931287{
     
    13661360bool RenderLayerBacking::paintsBoxDecorations() const
    13671361{
    1368     if (!m_owningLayer->hasVisibleContent())
    1369         return false;
    1370 
    1371     if (!hasBoxDecorationsOrBackground(renderer()))
     1362    if (!m_owningLayer->hasVisibleBoxDecorations())
    13721363        return false;
    13731364
     
    13751366        return true;
    13761367
    1377     if (m_owningLayer->hasOverflowControls())
    1378         return true;
    1379 
    13801368    return false;
    13811369}
     
    13831371bool RenderLayerBacking::paintsChildren() const
    13841372{
    1385     if (m_owningLayer->hasVisibleContent() && containsNonEmptyRenderers())
     1373    if (m_owningLayer->hasVisibleContent() && m_owningLayer->hasNonEmptyChildRenderers())
    13861374        return true;
    13871375       
     
    14071395
    14081396    if (renderObject->isReplaced() && !isCompositedPlugin(renderObject))
    1409             return false;
     1397        return false;
    14101398   
    14111399    if (paintsBoxDecorations() || paintsChildren())
     
    14401428}
    14411429
    1442 bool RenderLayerBacking::containsNonEmptyRenderers() const
    1443 {
    1444     // Some HTML can cause whitespace text nodes to have renderers, like:
    1445     // <div>
    1446     // <img src=...>
    1447     // </div>
    1448     // so test for 0x0 RenderTexts here
    1449     for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
    1450         if (!child->hasLayer()) {
    1451             if (child->isRenderInline() || !child->isBox())
    1452                 return true;
    1453            
    1454             if (toRenderBox(child)->width() > 0 || toRenderBox(child)->height() > 0)
    1455                 return true;
    1456         }
    1457     }
    1458     return false;
    1459 }
    1460 
    14611430// Conservative test for having no rendered children.
    14621431bool RenderLayerBacking::hasVisibleNonCompositingDescendantLayers() const
     
    15171486#if ENABLE(VIDEO)
    15181487    if (renderer()->isVideo() && toRenderVideo(renderer())->shouldDisplayVideo())
    1519         return hasBoxDecorationsOrBackground(renderer());
     1488        return m_owningLayer->hasBoxDecorationsOrBackground();
    15201489#endif
    15211490#if PLATFORM(MAC) && USE(CA) && (PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
    15221491#elif ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
    15231492    if (isAcceleratedCanvas(renderer()))
    1524         return hasBoxDecorationsOrBackground(renderer());
     1493        return m_owningLayer->hasBoxDecorationsOrBackground();
    15251494#endif
    15261495
     
    15341503    RenderObject* renderObject = renderer();
    15351504   
    1536     if (!renderObject->isImage() || hasBoxDecorationsOrBackground(renderObject) || renderObject->hasClip())
     1505    if (!renderObject->isImage() || m_owningLayer->hasBoxDecorationsOrBackground() || renderObject->hasClip())
    15371506        return false;
    15381507
  • trunk/Source/WebCore/rendering/RenderLayerBacking.h

    r140291 r141039  
    153153   
    154154    void updateDebugIndicators(bool showBorder, bool showRepaintCounter);
    155    
     155
    156156    // GraphicsLayerClient interface
    157157    virtual bool shouldUseTileCache(const GraphicsLayer*) const OVERRIDE;
     
    257257    void updateContentsRect(bool isSimpleContainer);
    258258
    259     bool containsNonEmptyRenderers() const;
    260259    bool hasVisibleNonCompositingDescendantLayers() const;
    261260
  • trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp

    r140758 r141039  
    20782078        }
    20792079    }
     2080   
     2081    bool paintsContent = layer->isVisuallyNonEmpty() || layer->hasVisibleDescendant();
     2082    if (!paintsContent) {
     2083        // isVisuallyNonEmpty() depends on layout.
     2084        m_reevaluateCompositingAfterLayout = true;
     2085        return false;
     2086    }
    20802087
    20812088    return true;
Note: See TracChangeset for help on using the changeset viewer.