Title: [141039] trunk
Revision
141039
Author
simon.fra...@apple.com
Date
2013-01-28 20:16:56 -0800 (Mon, 28 Jan 2013)

Log 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:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (141038 => 141039)


--- trunk/LayoutTests/ChangeLog	2013-01-29 03:51:54 UTC (rev 141038)
+++ trunk/LayoutTests/ChangeLog	2013-01-29 04:16:56 UTC (rev 141039)
@@ -1,3 +1,22 @@
+2013-01-28  Simon Fraser  <simon.fra...@apple.com>
+
+        position:fixed that doesn't render any content should not force compositing
+        https://bugs.webkit.org/show_bug.cgi?id=108112
+
+        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:
+
 2013-01-28  Keishi Hattori  <kei...@webkit.org>
 
         [Chromium] Skipping mathml tests because MATHML was disasbled.

Modified: trunk/LayoutTests/compositing/layer-creation/fixed-position-change-out-of-view-in-view.html (141038 => 141039)


--- trunk/LayoutTests/compositing/layer-creation/fixed-position-change-out-of-view-in-view.html	2013-01-29 03:51:54 UTC (rev 141038)
+++ trunk/LayoutTests/compositing/layer-creation/fixed-position-change-out-of-view-in-view.html	2013-01-29 04:16:56 UTC (rev 141039)
@@ -2,6 +2,11 @@
 
 <html>
 <head>
+  <style>
+    #fixed1, #fixed2 {
+        background-color: silver;
+    }
+  </style>
   <script type="text/_javascript_">
     if (window.testRunner && window.internals) {
       testRunner.dumpAsText();

Added: trunk/LayoutTests/compositing/layer-creation/fixed-position-no-content-expected.txt (0 => 141039)


--- trunk/LayoutTests/compositing/layer-creation/fixed-position-no-content-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/compositing/layer-creation/fixed-position-no-content-expected.txt	2013-01-29 04:16:56 UTC (rev 141039)
@@ -0,0 +1,3 @@
+There should be no layers.
+
+

Copied: trunk/LayoutTests/compositing/layer-creation/fixed-position-no-content.html (from rev 141038, trunk/LayoutTests/compositing/layer-creation/fixed-position-out-of-view.html) (0 => 141039)


--- trunk/LayoutTests/compositing/layer-creation/fixed-position-no-content.html	                        (rev 0)
+++ trunk/LayoutTests/compositing/layer-creation/fixed-position-no-content.html	2013-01-29 04:16:56 UTC (rev 141039)
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+  <style>
+    .fixed {
+      position: fixed;
+      width: 50px;
+      height: 50px;
+    }
+    
+    .absolute {
+        position: absolute;
+        top: 40px;
+        left: 40px;
+        height: 100px;
+        width: 100px;
+        background-color: gray;
+    }
+  </style>
+
+  <script type="text/_javascript_">
+    if (window.internals)
+      window.internals.settings.setAcceleratedCompositingForFixedPositionEnabled(true);
+
+    if (window.testRunner) {
+      testRunner.dumpAsText();
+
+      window.addEventListener("load", function() {
+        document.getElementById("layertree").innerText = window.internals.layerTreeAsText(document);
+      }, false);
+    }
+  </script>
+</head>
+
+<body>
+  <div style="height: 1000px">
+    <p>There should be no layers.</p>
+    <pre id="layertree"></pre>
+  </div>
+
+  <!-- This should not be composited -->
+  <div class="fixed" style="top: 10px; left: 10px"></div>
+  <!-- And this should not be promoted into a layer -->
+  <div class="absolute"></div>
+</body>
+</html>
+

Modified: trunk/LayoutTests/compositing/layer-creation/fixed-position-out-of-view-scaled-scroll.html (141038 => 141039)


--- trunk/LayoutTests/compositing/layer-creation/fixed-position-out-of-view-scaled-scroll.html	2013-01-29 03:51:54 UTC (rev 141038)
+++ trunk/LayoutTests/compositing/layer-creation/fixed-position-out-of-view-scaled-scroll.html	2013-01-29 04:16:56 UTC (rev 141039)
@@ -6,6 +6,7 @@
     position: fixed;
     width: 10px;
     height: 10px;
+    background-color: silver;
   }
 </style>
 <script>

Modified: trunk/LayoutTests/compositing/layer-creation/fixed-position-out-of-view-scaled.html (141038 => 141039)


--- trunk/LayoutTests/compositing/layer-creation/fixed-position-out-of-view-scaled.html	2013-01-29 03:51:54 UTC (rev 141038)
+++ trunk/LayoutTests/compositing/layer-creation/fixed-position-out-of-view-scaled.html	2013-01-29 04:16:56 UTC (rev 141039)
@@ -6,6 +6,7 @@
     position: fixed;
     width: 10px;
     height: 10px;
+    background-color: silver;
   }
 </style>
 <script>

Modified: trunk/LayoutTests/compositing/layer-creation/fixed-position-out-of-view.html (141038 => 141039)


--- trunk/LayoutTests/compositing/layer-creation/fixed-position-out-of-view.html	2013-01-29 03:51:54 UTC (rev 141038)
+++ trunk/LayoutTests/compositing/layer-creation/fixed-position-out-of-view.html	2013-01-29 04:16:56 UTC (rev 141039)
@@ -7,6 +7,7 @@
       position: fixed;
       width: 10px;
       height: 10px;
+      background-color: silver;
     }
   </style>
 

Modified: trunk/LayoutTests/platform/mac/tiled-drawing/fixed/fixed-position-out-of-view-negative-zindex.html (141038 => 141039)


--- trunk/LayoutTests/platform/mac/tiled-drawing/fixed/fixed-position-out-of-view-negative-zindex.html	2013-01-29 03:51:54 UTC (rev 141038)
+++ trunk/LayoutTests/platform/mac/tiled-drawing/fixed/fixed-position-out-of-view-negative-zindex.html	2013-01-29 04:16:56 UTC (rev 141039)
@@ -7,6 +7,7 @@
       position: fixed;
       width: 10px;
       height: 10px;
+      background-color: silver;
     }
   </style>
 

Modified: trunk/LayoutTests/platform/mac/tiled-drawing/fixed/fixed-position-out-of-view.html (141038 => 141039)


--- trunk/LayoutTests/platform/mac/tiled-drawing/fixed/fixed-position-out-of-view.html	2013-01-29 03:51:54 UTC (rev 141038)
+++ trunk/LayoutTests/platform/mac/tiled-drawing/fixed/fixed-position-out-of-view.html	2013-01-29 04:16:56 UTC (rev 141039)
@@ -7,6 +7,7 @@
       position: fixed;
       width: 10px;
       height: 10px;
+      background-color: silver;
     }
   </style>
 

Modified: trunk/Source/WebCore/ChangeLog (141038 => 141039)


--- trunk/Source/WebCore/ChangeLog	2013-01-29 03:51:54 UTC (rev 141038)
+++ trunk/Source/WebCore/ChangeLog	2013-01-29 04:16:56 UTC (rev 141039)
@@ -1,5 +1,45 @@
 2013-01-28  Simon Fraser  <simon.fra...@apple.com>
 
+        position:fixed that doesn't render any content should not force compositing
+        https://bugs.webkit.org/show_bug.cgi?id=108112
+
+        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.
+
+2013-01-28  Simon Fraser  <simon.fra...@apple.com>
+
         Avoid doing work at 60fps for tiled layers when not necessary
         https://bugs.webkit.org/show_bug.cgi?id=108135
 

Modified: trunk/Source/WebCore/rendering/RenderLayer.cpp (141038 => 141039)


--- trunk/Source/WebCore/rendering/RenderLayer.cpp	2013-01-29 03:51:54 UTC (rev 141038)
+++ trunk/Source/WebCore/rendering/RenderLayer.cpp	2013-01-29 04:16:56 UTC (rev 141039)
@@ -5404,6 +5404,59 @@
         parent()->dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
 }
 
+bool RenderLayer::hasNonEmptyChildRenderers() const
+{
+    // Some HTML can cause whitespace text nodes to have renderers, like:
+    // <div>
+    // <img src=""
+    // </div>
+    // so test for 0x0 RenderTexts here
+    for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
+        if (!child->hasLayer()) {
+            if (child->isRenderInline() || !child->isBox())
+                return true;
+        
+            if (toRenderBox(child)->width() > 0 || toRenderBox(child)->height() > 0)
+                return true;
+        }
+    }
+    return false;
+}
+
+static bool hasBoxDecorations(const RenderStyle* style)
+{
+    return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow() || style->hasFilter();
+}
+
+bool RenderLayer::hasBoxDecorationsOrBackground() const
+{
+    return hasBoxDecorations(renderer()->style()) || renderer()->hasBackground();
+}
+
+bool RenderLayer::hasVisibleBoxDecorations() const
+{
+    if (!hasVisibleContent())
+        return false;
+
+    return hasBoxDecorationsOrBackground() || hasOverflowControls();
+}
+
+bool RenderLayer::isVisuallyNonEmpty() const
+{
+    ASSERT(!m_visibleDescendantStatusDirty);
+
+    if (hasVisibleContent() && hasNonEmptyChildRenderers())
+        return true;
+
+    if (renderer()->isReplaced() || renderer()->hasMask())
+        return true;
+
+    if (hasVisibleBoxDecorations())
+        return true;
+
+    return false;
+}
+
 void RenderLayer::updateStackingContextsAfterStyleChange(const RenderStyle* oldStyle)
 {
     if (!oldStyle)

Modified: trunk/Source/WebCore/rendering/RenderLayer.h (141038 => 141039)


--- trunk/Source/WebCore/rendering/RenderLayer.h	2013-01-29 03:51:54 UTC (rev 141038)
+++ trunk/Source/WebCore/rendering/RenderLayer.h	2013-01-29 04:16:56 UTC (rev 141039)
@@ -473,6 +473,13 @@
     void setHasVisibleContent();
     void dirtyVisibleContentStatus();
 
+    bool hasBoxDecorationsOrBackground() const;
+    bool hasVisibleBoxDecorations() const;
+    // Returns true if this layer has visible content (ignoring any child layers).
+    bool isVisuallyNonEmpty() const;
+    // True if this layer container renderers that paint.
+    bool hasNonEmptyChildRenderers() const;
+
     // FIXME: We should ASSERT(!m_hasSelfPaintingLayerDescendantDirty); here but we hit the same bugs as visible content above.
     // Part of the issue is with subtree relayout: we don't check if our ancestors have some descendant flags dirty, missing some updates.
     bool hasSelfPaintingLayerDescendant() const { return m_hasSelfPaintingLayerDescendant; }

Modified: trunk/Source/WebCore/rendering/RenderLayerBacking.cpp (141038 => 141039)


--- trunk/Source/WebCore/rendering/RenderLayerBacking.cpp	2013-01-29 03:51:54 UTC (rev 141038)
+++ trunk/Source/WebCore/rendering/RenderLayerBacking.cpp	2013-01-29 04:16:56 UTC (rev 141039)
@@ -76,8 +76,6 @@
 
 using namespace HTMLNames;
 
-static bool hasBoxDecorations(const RenderStyle*);
-static bool hasBoxDecorationsOrBackground(const RenderObject*);
 static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle*);
 static IntRect clipBox(RenderBox* renderer);
 
@@ -474,6 +472,7 @@
     RenderLayerCompositor* compositor = this->compositor();
     RenderObject* renderer = this->renderer();
 
+    m_owningLayer->updateDescendantDependentFlags();
     m_owningLayer->updateZOrderLists();
 
     bool layerConfigChanged = false;
@@ -912,7 +911,7 @@
         // m_graphicsLayer only needs backing store if the non-scrolling parts (background, outlines, borders, shadows etc) need to paint.
         // m_scrollingLayer never has backing store.
         // m_scrollingContentsLayer only needs backing store if the scrolled contents need to paint.
-        bool hasNonScrollingPaintedContent = m_owningLayer->hasVisibleContent() && hasBoxDecorationsOrBackground(renderer());
+        bool hasNonScrollingPaintedContent = m_owningLayer->hasVisibleContent() && m_owningLayer->hasBoxDecorationsOrBackground();
         m_graphicsLayer->setDrawsContent(hasNonScrollingPaintedContent);
 
         bool hasScrollingPaintedContent = m_owningLayer->hasVisibleContent() && (renderer()->hasBackground() || paintsChildren());
@@ -1284,11 +1283,6 @@
     return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow() || style->hasFilter();
 }
 
-static bool hasBoxDecorationsOrBackground(const RenderObject* renderer)
-{
-    return hasBoxDecorations(renderer->style()) || renderer->hasBackground();
-}
-
 static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle* style)
 {
     return hasBoxDecorations(style) || style->hasBackgroundImage();
@@ -1365,24 +1359,18 @@
 
 bool RenderLayerBacking::paintsBoxDecorations() const
 {
-    if (!m_owningLayer->hasVisibleContent())
+    if (!m_owningLayer->hasVisibleBoxDecorations())
         return false;
 
-    if (!hasBoxDecorationsOrBackground(renderer()))
-        return false;
-
     if (!supportsDirectBoxDecorationsComposition(renderer()))
         return true;
 
-    if (m_owningLayer->hasOverflowControls())
-        return true;
-
     return false;
 }
 
 bool RenderLayerBacking::paintsChildren() const
 {
-    if (m_owningLayer->hasVisibleContent() && containsNonEmptyRenderers())
+    if (m_owningLayer->hasVisibleContent() && m_owningLayer->hasNonEmptyChildRenderers())
         return true;
         
     if (hasVisibleNonCompositingDescendantLayers())
@@ -1406,7 +1394,7 @@
         return false;
 
     if (renderObject->isReplaced() && !isCompositedPlugin(renderObject))
-            return false;
+        return false;
     
     if (paintsBoxDecorations() || paintsChildren())
         return false;
@@ -1439,25 +1427,6 @@
     return true;
 }
 
-bool RenderLayerBacking::containsNonEmptyRenderers() const
-{
-    // Some HTML can cause whitespace text nodes to have renderers, like:
-    // <div>
-    // <img src=""
-    // </div>
-    // so test for 0x0 RenderTexts here
-    for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
-        if (!child->hasLayer()) {
-            if (child->isRenderInline() || !child->isBox())
-                return true;
-            
-            if (toRenderBox(child)->width() > 0 || toRenderBox(child)->height() > 0)
-                return true;
-        }
-    }
-    return false;
-}
-
 // Conservative test for having no rendered children.
 bool RenderLayerBacking::hasVisibleNonCompositingDescendantLayers() const
 {
@@ -1516,12 +1485,12 @@
     // and set background color on the layer in that case, instead of allocating backing store and painting.
 #if ENABLE(VIDEO)
     if (renderer()->isVideo() && toRenderVideo(renderer())->shouldDisplayVideo())
-        return hasBoxDecorationsOrBackground(renderer());
+        return m_owningLayer->hasBoxDecorationsOrBackground();
 #endif
 #if PLATFORM(MAC) && USE(CA) && (PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
 #elif ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
     if (isAcceleratedCanvas(renderer()))
-        return hasBoxDecorationsOrBackground(renderer());
+        return m_owningLayer->hasBoxDecorationsOrBackground();
 #endif
 
     return true;
@@ -1533,7 +1502,7 @@
 {
     RenderObject* renderObject = renderer();
     
-    if (!renderObject->isImage() || hasBoxDecorationsOrBackground(renderObject) || renderObject->hasClip())
+    if (!renderObject->isImage() || m_owningLayer->hasBoxDecorationsOrBackground() || renderObject->hasClip())
         return false;
 
     RenderImage* imageRenderer = toRenderImage(renderObject);

Modified: trunk/Source/WebCore/rendering/RenderLayerBacking.h (141038 => 141039)


--- trunk/Source/WebCore/rendering/RenderLayerBacking.h	2013-01-29 03:51:54 UTC (rev 141038)
+++ trunk/Source/WebCore/rendering/RenderLayerBacking.h	2013-01-29 04:16:56 UTC (rev 141039)
@@ -152,7 +152,7 @@
     void adjustTileCacheCoverage();
     
     void updateDebugIndicators(bool showBorder, bool showRepaintCounter);
-    
+
     // GraphicsLayerClient interface
     virtual bool shouldUseTileCache(const GraphicsLayer*) const OVERRIDE;
     virtual void notifyAnimationStarted(const GraphicsLayer*, double startTime) OVERRIDE;
@@ -256,7 +256,6 @@
     void updateBackgroundColor(bool isSimpleContainer);
     void updateContentsRect(bool isSimpleContainer);
 
-    bool containsNonEmptyRenderers() const;
     bool hasVisibleNonCompositingDescendantLayers() const;
 
     bool shouldClipCompositedBounds() const;

Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp (141038 => 141039)


--- trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp	2013-01-29 03:51:54 UTC (rev 141038)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp	2013-01-29 04:16:56 UTC (rev 141039)
@@ -2077,6 +2077,13 @@
             return false;
         }
     }
+    
+    bool paintsContent = layer->isVisuallyNonEmpty() || layer->hasVisibleDescendant();
+    if (!paintsContent) {
+        // isVisuallyNonEmpty() depends on layout.
+        m_reevaluateCompositingAfterLayout = true;
+        return false;
+    }
 
     return true;
 }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to