Avoid using backing store for compositing layers that just need to clip
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 16 Apr 2012 18:32:13 +0000 (18:32 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 16 Apr 2012 18:32:13 +0000 (18:32 +0000)
https://bugs.webkit.org/show_bug.cgi?id=40547

Source/WebCore:

Reviewed by Dean Jackson.

If a layer becomes composited because it needs to clip composited
descendants, or if it has perspective, then it doesn't actually
needs its own backing store; its contents can be painted by an
ancestor, and we can just have an empty layer that does the clipping
or applies the perspective transform.

This saves backing store memory on some pages.

Tests: compositing/backing/no-backing-for-clip-overlap.html
       compositing/backing/no-backing-for-clip.html
       compositing/backing/no-backing-for-perspective.html

* rendering/RenderLayer.cpp:
(WebCore):
(WebCore::RenderLayer::enclosingCompositingLayerForRepaint):
(WebCore::RenderLayer::paintLayer):
* rendering/RenderLayer.h:
(RenderLayer):
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::RenderLayerBacking):
(WebCore::RenderLayerBacking::updateGraphicsLayerGeometry):
(WebCore::RenderLayerBacking::containsPaintedContent):
(WebCore::RenderLayerBacking::setContentsNeedDisplay):
(WebCore::RenderLayerBacking::setContentsNeedDisplayInRect):
(WebCore::RenderLayerBacking::paintIntoLayer):
* rendering/RenderLayerBacking.h:
(RenderLayerBacking):
(WebCore::RenderLayerBacking::paintsIntoCompositedAncestor):
(WebCore::RenderLayerBacking::setRequiresOwnBackingStore):
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::layerWillBeRemoved):
(WebCore::RenderLayerCompositor::recursiveRepaintLayerRect):
(WebCore::RenderLayerCompositor::requiresCompositingLayer):
(WebCore::RenderLayerCompositor::requiresOwnBackingStore):
(WebCore):
* rendering/RenderLayerCompositor.h:
* rendering/RenderObject.cpp:
(WebCore::RenderObject::containerForRepaint):
* rendering/RenderTreeAsText.cpp:
(WebCore::write):
* rendering/RenderView.cpp:
(WebCore::RenderView::paintBoxDecorations):

LayoutTests:

Reviewed by Dean Jackson.

New tests for backing store elimination with clip or perspective.

New results for some tests that no longer have backing store on some
layers.

* compositing/backing/no-backing-for-clip-expected.txt: Added.
* compositing/backing/no-backing-for-clip-overlap-expected.txt: Added.
* compositing/backing/no-backing-for-clip-overlap.html: Added.
* compositing/backing/no-backing-for-clip.html: Added.
* compositing/backing/no-backing-for-perspective-expected.txt: Added.
* compositing/backing/no-backing-for-perspective.html: Added.
* compositing/geometry/preserve-3d-switching-expected.txt:
* compositing/visibility/layer-visible-content-expected.png:
* compositing/visibility/layer-visible-content-expected.txt:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@114283 268f45cc-cd09-0410-ab3c-d52691b4dbfc

20 files changed:
LayoutTests/ChangeLog
LayoutTests/compositing/backing/no-backing-for-clip-expected.txt [new file with mode: 0644]
LayoutTests/compositing/backing/no-backing-for-clip-overlap-expected.txt [new file with mode: 0644]
LayoutTests/compositing/backing/no-backing-for-clip-overlap.html [new file with mode: 0644]
LayoutTests/compositing/backing/no-backing-for-clip.html [new file with mode: 0644]
LayoutTests/compositing/backing/no-backing-for-perspective-expected.txt [new file with mode: 0644]
LayoutTests/compositing/backing/no-backing-for-perspective.html [new file with mode: 0644]
LayoutTests/compositing/geometry/preserve-3d-switching-expected.txt
LayoutTests/compositing/visibility/layer-visible-content-expected.png
LayoutTests/compositing/visibility/layer-visible-content-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderLayer.cpp
Source/WebCore/rendering/RenderLayer.h
Source/WebCore/rendering/RenderLayerBacking.cpp
Source/WebCore/rendering/RenderLayerBacking.h
Source/WebCore/rendering/RenderLayerCompositor.cpp
Source/WebCore/rendering/RenderLayerCompositor.h
Source/WebCore/rendering/RenderObject.cpp
Source/WebCore/rendering/RenderTreeAsText.cpp
Source/WebCore/rendering/RenderView.cpp

index 94f1213..d7841ec 100644 (file)
@@ -1,3 +1,25 @@
+2012-04-13  Simon Fraser  <simon.fraser@apple.com>
+
+        Avoid using backing store for compositing layers that just need to clip
+        https://bugs.webkit.org/show_bug.cgi?id=40547
+
+        Reviewed by Dean Jackson.
+        
+        New tests for backing store elimination with clip or perspective.
+        
+        New results for some tests that no longer have backing store on some
+        layers.
+
+        * compositing/backing/no-backing-for-clip-expected.txt: Added.
+        * compositing/backing/no-backing-for-clip-overlap-expected.txt: Added.
+        * compositing/backing/no-backing-for-clip-overlap.html: Added.
+        * compositing/backing/no-backing-for-clip.html: Added.
+        * compositing/backing/no-backing-for-perspective-expected.txt: Added.
+        * compositing/backing/no-backing-for-perspective.html: Added.
+        * compositing/geometry/preserve-3d-switching-expected.txt:
+        * compositing/visibility/layer-visible-content-expected.png:
+        * compositing/visibility/layer-visible-content-expected.txt:
+
 2012-04-16  Vincent Scheib  <scheib@chromium.org>
 
         [Chromium] Marking css3/filters/huge-region.html and composited version MISSING, CRASH.
diff --git a/LayoutTests/compositing/backing/no-backing-for-clip-expected.txt b/LayoutTests/compositing/backing/no-backing-for-clip-expected.txt
new file mode 100644 (file)
index 0000000..e50aa5c
--- /dev/null
@@ -0,0 +1,42 @@
+This layer should not have backing store.
+This layer should not have backing store.
+(GraphicsLayer
+  (bounds 800.00 600.00)
+  (children 1
+    (GraphicsLayer
+      (bounds 800.00 600.00)
+      (children 1
+        (GraphicsLayer
+          (position 8.00 8.00)
+          (bounds 342.00 240.00)
+          (children 1
+            (GraphicsLayer
+              (position 1.00 1.00)
+              (bounds 340.00 238.00)
+              (children 1
+                (GraphicsLayer
+                  (position 20.00 38.00)
+                  (bounds 320.00 180.00)
+                  (children 1
+                    (GraphicsLayer
+                      (position 1.00 1.00)
+                      (bounds 340.00 178.00)
+                      (children 1
+                        (GraphicsLayer
+                          (position 30.00 48.00)
+                          (bounds 100.00 100.00)
+                          (drawsContent 1)
+                        )
+                      )
+                    )
+                  )
+                )
+              )
+            )
+          )
+        )
+      )
+    )
+  )
+)
+
diff --git a/LayoutTests/compositing/backing/no-backing-for-clip-overlap-expected.txt b/LayoutTests/compositing/backing/no-backing-for-clip-overlap-expected.txt
new file mode 100644 (file)
index 0000000..b260d0a
--- /dev/null
@@ -0,0 +1,48 @@
+This layer should not have backing store.
+This layer should have backing store.
+(GraphicsLayer
+  (bounds 800.00 600.00)
+  (children 1
+    (GraphicsLayer
+      (bounds 800.00 600.00)
+      (children 2
+        (GraphicsLayer
+          (position 8.00 8.00)
+          (bounds 342.00 180.00)
+          (children 1
+            (GraphicsLayer
+              (position 1.00 1.00)
+              (bounds 340.00 178.00)
+              (children 1
+                (GraphicsLayer
+                  (position 30.00 48.00)
+                  (bounds 100.00 100.00)
+                  (drawsContent 1)
+                )
+              )
+            )
+          )
+        )
+        (GraphicsLayer
+          (position 8.00 178.00)
+          (bounds 342.00 180.00)
+          (drawsContent 1)
+          (children 1
+            (GraphicsLayer
+              (position 1.00 1.00)
+              (bounds 340.00 178.00)
+              (children 1
+                (GraphicsLayer
+                  (position 30.00 48.00)
+                  (bounds 100.00 100.00)
+                  (drawsContent 1)
+                )
+              )
+            )
+          )
+        )
+      )
+    )
+  )
+)
+
diff --git a/LayoutTests/compositing/backing/no-backing-for-clip-overlap.html b/LayoutTests/compositing/backing/no-backing-for-clip-overlap.html
new file mode 100644 (file)
index 0000000..685de81
--- /dev/null
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+  <style type="text/css" media="screen">
+    .box {
+      position: relative;
+      height: 100px;
+      width: 100px;
+      margin: 10px;
+      left: 0;
+      top: 0;
+      background-color: silver;
+    }
+    
+    .clipping {
+      position: relative;
+      z-index: 0;
+      width: 300px;
+      border: 1px solid black;
+      padding: 20px;
+      overflow: hidden;
+    }
+    
+    .composited {
+      -webkit-transform: translateZ(0);
+    }
+  </style>
+
+  <script>
+  if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+    
+  function dumpLayers()
+  {
+    var layersResult = document.getElementById('layers');
+    if (window.layoutTestController)
+      layersResult.innerText = layoutTestController.layerTreeAsText();
+    
+  }
+  window.addEventListener('load', dumpLayers, false)
+  </script>
+
+</head>
+<body>
+
+  <div class="clipping">
+      This layer should not have backing store.
+      <div class="box composited"></div>
+  </div>
+  <div class="clipping" style="margin-top: -10px;">
+      This layer should have backing store.
+      <div class="box composited"></div>
+  </div>
+
+<pre id="layers">Layer tree goes here in DRT</pre>
+
+</body>
+</html>
diff --git a/LayoutTests/compositing/backing/no-backing-for-clip.html b/LayoutTests/compositing/backing/no-backing-for-clip.html
new file mode 100644 (file)
index 0000000..4604802
--- /dev/null
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+  <style type="text/css" media="screen">
+    .box {
+      position: relative;
+      height: 100px;
+      width: 100px;
+      margin: 10px;
+      left: 0;
+      top: 0;
+      background-color: silver;
+    }
+    
+    .clipping {
+      position: relative;
+      z-index: 0;
+      width: 300px;
+      border: 1px solid black;
+      padding: 20px;
+      overflow: hidden;
+    }
+    
+    .composited {
+      -webkit-transform: translateZ(0);
+    }
+  </style>
+
+  <script>
+  if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+    
+  function dumpLayers()
+  {
+    var layersResult = document.getElementById('layers');
+    if (window.layoutTestController)
+      layersResult.innerText = layoutTestController.layerTreeAsText();
+    
+  }
+  window.addEventListener('load', dumpLayers, false)
+  </script>
+
+</head>
+<body>
+
+  <div class="clipping">
+    This layer should not have backing store.
+    <div class="clipping">
+      This layer should not have backing store.
+      <div class="box composited">
+      </div>
+    </div>
+  </div>
+
+<pre id="layers">Layer tree goes here in DRT</pre>
+
+</body>
+</html>
diff --git a/LayoutTests/compositing/backing/no-backing-for-perspective-expected.txt b/LayoutTests/compositing/backing/no-backing-for-perspective-expected.txt
new file mode 100644 (file)
index 0000000..24e7306
--- /dev/null
@@ -0,0 +1,32 @@
+This layer should not have backing store.
+This layer should not have backing store.
+(GraphicsLayer
+  (bounds 800.00 600.00)
+  (children 1
+    (GraphicsLayer
+      (bounds 800.00 600.00)
+      (children 1
+        (GraphicsLayer
+          (position 8.00 8.00)
+          (bounds 342.00 240.00)
+          (childrenTransform [1.00 0.00 0.00 0.00] [0.00 1.00 0.00 0.00] [0.00 0.00 1.00 -0.00] [0.00 0.00 0.00 1.00])
+          (children 1
+            (GraphicsLayer
+              (position 21.00 39.00)
+              (bounds 342.00 180.00)
+              (childrenTransform [1.00 0.00 0.00 0.00] [0.00 1.00 0.00 0.00] [0.00 0.00 1.00 -0.00] [0.00 0.00 0.00 1.00])
+              (children 1
+                (GraphicsLayer
+                  (position 31.00 49.00)
+                  (bounds 100.00 100.00)
+                  (drawsContent 1)
+                )
+              )
+            )
+          )
+        )
+      )
+    )
+  )
+)
+
diff --git a/LayoutTests/compositing/backing/no-backing-for-perspective.html b/LayoutTests/compositing/backing/no-backing-for-perspective.html
new file mode 100644 (file)
index 0000000..31e3689
--- /dev/null
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+  <style type="text/css" media="screen">
+    .box {
+      position: relative;
+      height: 100px;
+      width: 100px;
+      margin: 10px;
+      left: 0;
+      top: 0;
+      background-color: silver;
+    }
+    
+    .perspective {
+      width: 300px;
+      border: 1px solid black;
+      padding: 20px;
+      -webkit-perspective: 500px;
+    }
+    
+    .composited {
+      -webkit-transform: translateZ(0);
+    }
+  </style>
+
+  <script>
+  if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+    
+  function dumpLayers()
+  {
+    var layersResult = document.getElementById('layers');
+    if (window.layoutTestController)
+      layersResult.innerText = layoutTestController.layerTreeAsText();
+    
+  }
+  window.addEventListener('load', dumpLayers, false)
+  </script>
+
+</head>
+<body>
+
+  <div class="perspective">
+    This layer should not have backing store.
+    <div class="perspective">
+      This layer should not have backing store.
+      <div class="box composited">
+      </div>
+    </div>
+  </div>
+
+<pre id="layers">Layer tree goes here in DRT</pre>
+
+</body>
+</html>
index 1e4762e..791dda2 100644 (file)
@@ -10,7 +10,6 @@ The green box appear angled out from the yellow box and embedded in it.
         (GraphicsLayer
           (position 108.00 73.00)
           (bounds 304.00 304.00)
-          (drawsContent 1)
           (childrenTransform [1.00 0.00 0.00 0.00] [0.00 1.00 0.00 0.00] [0.00 0.00 1.00 -0.00] [0.00 0.00 0.00 1.00])
           (children 1
             (GraphicsLayer
index b6da2f3..0fb366e 100644 (file)
Binary files a/LayoutTests/compositing/visibility/layer-visible-content-expected.png and b/LayoutTests/compositing/visibility/layer-visible-content-expected.png differ
index 97b92e5..7e96af6 100644 (file)
@@ -6,7 +6,6 @@
       (children 2
         (GraphicsLayer
           (bounds 200.00 200.00)
-          (drawsContent 1)
           (children 1
             (GraphicsLayer
               (bounds 200.00 200.00)
index 5efbce2..ae49c53 100644 (file)
@@ -1,3 +1,53 @@
+2012-04-13  Simon Fraser  <simon.fraser@apple.com>
+
+        Avoid using backing store for compositing layers that just need to clip
+        https://bugs.webkit.org/show_bug.cgi?id=40547
+
+        Reviewed by Dean Jackson.
+        
+        If a layer becomes composited because it needs to clip composited
+        descendants, or if it has perspective, then it doesn't actually
+        needs its own backing store; its contents can be painted by an
+        ancestor, and we can just have an empty layer that does the clipping
+        or applies the perspective transform.
+        
+        This saves backing store memory on some pages.
+
+        Tests: compositing/backing/no-backing-for-clip-overlap.html
+               compositing/backing/no-backing-for-clip.html
+               compositing/backing/no-backing-for-perspective.html
+
+        * rendering/RenderLayer.cpp:
+        (WebCore):
+        (WebCore::RenderLayer::enclosingCompositingLayerForRepaint):
+        (WebCore::RenderLayer::paintLayer):
+        * rendering/RenderLayer.h:
+        (RenderLayer):
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::RenderLayerBacking):
+        (WebCore::RenderLayerBacking::updateGraphicsLayerGeometry):
+        (WebCore::RenderLayerBacking::containsPaintedContent):
+        (WebCore::RenderLayerBacking::setContentsNeedDisplay):
+        (WebCore::RenderLayerBacking::setContentsNeedDisplayInRect):
+        (WebCore::RenderLayerBacking::paintIntoLayer):
+        * rendering/RenderLayerBacking.h:
+        (RenderLayerBacking):
+        (WebCore::RenderLayerBacking::paintsIntoCompositedAncestor):
+        (WebCore::RenderLayerBacking::setRequiresOwnBackingStore):
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::layerWillBeRemoved):
+        (WebCore::RenderLayerCompositor::recursiveRepaintLayerRect):
+        (WebCore::RenderLayerCompositor::requiresCompositingLayer):
+        (WebCore::RenderLayerCompositor::requiresOwnBackingStore):
+        (WebCore):
+        * rendering/RenderLayerCompositor.h:
+        * rendering/RenderObject.cpp:
+        (WebCore::RenderObject::containerForRepaint):
+        * rendering/RenderTreeAsText.cpp:
+        (WebCore::write):
+        * rendering/RenderView.cpp:
+        (WebCore::RenderView::paintBoxDecorations):
+
 2012-04-16  Brady Eidson  <beidson@apple.com>
 
         <rdar://problem/11249336> and https://bugs.webkit.org/show_bug.cgi?id=84050
index 77b7011..4a2d37d 100644 (file)
@@ -959,6 +959,19 @@ RenderLayer* RenderLayer::enclosingCompositingLayer(bool includeSelf) const
          
     return 0;
 }
+
+RenderLayer* RenderLayer::enclosingCompositingLayerForRepaint(bool includeSelf) const
+{
+    if (includeSelf && isComposited() && !backing()->paintsIntoCompositedAncestor())
+        return const_cast<RenderLayer*>(this);
+
+    for (const RenderLayer* curr = compositingContainer(this); curr; curr = compositingContainer(curr)) {
+        if (curr->isComposited() && !curr->backing()->paintsIntoCompositedAncestor())
+            return const_cast<RenderLayer*>(curr);
+    }
+         
+    return 0;
+}
 #endif
 
 #if ENABLE(CSS_FILTERS)
@@ -2857,7 +2870,7 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* context,
         // but we need to ensure that we don't cache clip rects computed with the wrong root in this case.
         if (context->updatingControlTints() || (paintBehavior & PaintBehaviorFlattenCompositingLayers))
             paintFlags |= PaintLayerTemporaryClipRects;
-        else if (!backing()->paintsIntoWindow() && !shouldDoSoftwarePaint(this, paintFlags & PaintLayerPaintingReflection)) {
+        else if (!backing()->paintsIntoWindow() && !backing()->paintsIntoCompositedAncestor() && !shouldDoSoftwarePaint(this, paintFlags & PaintLayerPaintingReflection)) {
             // If this RenderLayer should paint into its backing, that will be done via RenderLayerBacking::paintIntoLayer().
             return;
         }
index 90b011a..e67fb2c 100644 (file)
@@ -420,6 +420,7 @@ public:
 #if USE(ACCELERATED_COMPOSITING)
     // Enclosing compositing layer; if includeSelf is true, may return this.
     RenderLayer* enclosingCompositingLayer(bool includeSelf = true) const;
+    RenderLayer* enclosingCompositingLayerForRepaint(bool includeSelf = true) const;
     // Ancestor compositing layer, excluding this.
     RenderLayer* ancestorCompositingLayer() const { return enclosingCompositingLayer(false); }
 #endif
index 8c79fd3..c98bafd 100644 (file)
@@ -92,6 +92,7 @@ RenderLayerBacking::RenderLayerBacking(RenderLayer* layer)
     , m_artificiallyInflatedBounds(false)
     , m_isMainFrameRenderViewLayer(false)
     , m_usingTiledCacheLayer(false)
+    , m_requiresOwnBackingStore(true)
 #if ENABLE(CSS_FILTERS)
     , m_canCompositeFilters(false)
 #endif
@@ -563,6 +564,10 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
     }
 
     m_graphicsLayer->setContentsRect(contentsBox());
+
+    // If this layer was created just for clipping or to apply perspective, it doesn't need its own backing store.
+    setRequiresOwnBackingStore(compositor()->requiresOwnBackingStore(m_owningLayer, compAncestor));
+
     updateDrawsContent();
     updateAfterWidgetResize();
 }
@@ -937,7 +942,7 @@ bool RenderLayerBacking::hasVisibleNonCompositingDescendantLayers() const
 
 bool RenderLayerBacking::containsPaintedContent() const
 {
-    if (isSimpleContainerCompositingLayer() || paintsIntoWindow() || m_artificiallyInflatedBounds || m_owningLayer->isReflection())
+    if (isSimpleContainerCompositingLayer() || paintsIntoWindow() || paintsIntoCompositedAncestor() || m_artificiallyInflatedBounds || m_owningLayer->isReflection())
         return false;
 
     if (isDirectlyCompositedImage())
@@ -1095,6 +1100,8 @@ bool RenderLayerBacking::paintsIntoWindow() const
 
 void RenderLayerBacking::setContentsNeedDisplay()
 {
+    ASSERT(!paintsIntoCompositedAncestor());
+    
     if (m_graphicsLayer && m_graphicsLayer->drawsContent())
         m_graphicsLayer->setNeedsDisplay();
     
@@ -1108,6 +1115,8 @@ void RenderLayerBacking::setContentsNeedDisplay()
 // r is in the coordinate space of the layer's render object
 void RenderLayerBacking::setContentsNeedDisplayInRect(const IntRect& r)
 {
+    ASSERT(!paintsIntoCompositedAncestor());
+
     if (m_graphicsLayer && m_graphicsLayer->drawsContent()) {
         IntRect layerDirtyRect = r;
         layerDirtyRect.move(-m_graphicsLayer->offsetFromRenderer());
@@ -1132,7 +1141,7 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*
                     PaintBehavior paintBehavior, GraphicsLayerPaintingPhase paintingPhase,
                     RenderObject* paintingRoot)
 {
-    if (paintsIntoWindow()) {
+    if (paintsIntoWindow() || paintsIntoCompositedAncestor()) {
         ASSERT_NOT_REACHED();
         return;
     }
index 4244dca..c11336c 100644 (file)
@@ -96,6 +96,12 @@ public:
     // This returns false for other layers, and when the document layer actually needs to paint into its backing store
     // for some reason.
     bool paintsIntoWindow() const;
+    
+    // Returns true for a composited layer that has no backing store of its own, so
+    // paints into some ancestor layer.
+    bool paintsIntoCompositedAncestor() const { return !m_requiresOwnBackingStore; }
+
+    void setRequiresOwnBackingStore(bool flag) { m_requiresOwnBackingStore = flag; }
 
     void setContentsNeedDisplay();
     // r is in the coordinate space of the layer's render object
@@ -235,6 +241,7 @@ private:
     bool m_artificiallyInflatedBounds;      // bounds had to be made non-zero to make transform-origin work
     bool m_isMainFrameRenderViewLayer;
     bool m_usingTiledCacheLayer;
+    bool m_requiresOwnBackingStore;
 #if ENABLE(CSS_FILTERS)
     bool m_canCompositeFilters;
 #endif
index fb47da4..52d3616 100644 (file)
@@ -525,7 +525,7 @@ void RenderLayerCompositor::layerWillBeRemoved(RenderLayer* parent, RenderLayer*
 
     setCompositingParent(child, 0);
     
-    RenderLayer* compLayer = parent->enclosingCompositingLayer();
+    RenderLayer* compLayer = parent->enclosingCompositingLayerForRepaint();
     if (compLayer) {
         ASSERT(compLayer->backing());
         LayoutRect compBounds = child->backing()->compositedBounds();
@@ -1130,7 +1130,7 @@ void RenderLayerCompositor::repaintCompositedLayersAbsoluteRect(const IntRect& a
 void RenderLayerCompositor::recursiveRepaintLayerRect(RenderLayer* layer, const IntRect& rect)
 {
     // FIXME: This method does not work correctly with transforms.
-    if (layer->isComposited())
+    if (layer->isComposited() && !layer->backing()->paintsIntoCompositedAncestor())
         layer->setBackingNeedsRepaintInRect(rect);
 
 #if !ASSERT_DISABLED
@@ -1325,15 +1325,15 @@ bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer* layer) c
     }
     // The root layer always has a compositing layer, but it may not have backing.
     return requiresCompositingForTransform(renderer)
-             || requiresCompositingForVideo(renderer)
-             || requiresCompositingForCanvas(renderer)
-             || requiresCompositingForPlugin(renderer)
-             || requiresCompositingForFrame(renderer)
-             || (canRender3DTransforms() && renderer->style()->backfaceVisibility() == BackfaceVisibilityHidden)
-             || clipsCompositingDescendants(layer)
-             || requiresCompositingForAnimation(renderer)
-             || requiresCompositingForFilters(renderer)
-             || requiresCompositingForPosition(renderer, layer);
+        || requiresCompositingForVideo(renderer)
+        || requiresCompositingForCanvas(renderer)
+        || requiresCompositingForPlugin(renderer)
+        || requiresCompositingForFrame(renderer)
+        || (canRender3DTransforms() && renderer->style()->backfaceVisibility() == BackfaceVisibilityHidden)
+        || clipsCompositingDescendants(layer)
+        || requiresCompositingForAnimation(renderer)
+        || requiresCompositingForFilters(renderer)
+        || requiresCompositingForPosition(renderer, layer);
 }
 
 bool RenderLayerCompositor::canBeComposited(const RenderLayer* layer) const
@@ -1341,6 +1341,32 @@ bool RenderLayerCompositor::canBeComposited(const RenderLayer* layer) const
     return m_hasAcceleratedCompositing && layer->isSelfPaintingLayer();
 }
 
+bool RenderLayerCompositor::requiresOwnBackingStore(const RenderLayer* layer, const RenderLayer* compositingAncestorLayer) const
+{
+    RenderObject* renderer = layer->renderer();
+    if (compositingAncestorLayer
+        && !(compositingAncestorLayer->backing()->graphicsLayer()->drawsContent()
+            || compositingAncestorLayer->backing()->paintsIntoWindow()
+            || compositingAncestorLayer->backing()->paintsIntoCompositedAncestor()))
+        return true;
+
+    return layer->isRootLayer()
+        || layer->transform() // note: excludes perspective and transformStyle3D.
+        || requiresCompositingForVideo(renderer)
+        || requiresCompositingForCanvas(renderer)
+        || requiresCompositingForPlugin(renderer)
+        || requiresCompositingForFrame(renderer)
+        || (canRender3DTransforms() && renderer->style()->backfaceVisibility() == BackfaceVisibilityHidden)
+        || requiresCompositingForAnimation(renderer)
+        || requiresCompositingForFilters(renderer)
+        || requiresCompositingForPosition(renderer, layer)
+        || renderer->isTransparent()
+        || renderer->hasMask()
+        || renderer->hasReflection()
+        || renderer->hasFilter()
+        || layer->mustOverlapCompositedLayers();
+}
+
 // Return true if the given layer has some ancestor in the RenderLayer hierarchy that clips,
 // up to the enclosing compositing ancestor. This is required because compositing layers are parented
 // according to the z-order hierarchy, yet clipping goes down the renderer hierarchy.
index a62afd4..cb207f0 100644 (file)
@@ -136,6 +136,9 @@ public:
     // Repaint parts of all composited layers that intersect the given absolute rectangle.
     void repaintCompositedLayersAbsoluteRect(const IntRect&);
 
+    // Returns true if the given layer needs it own backing store.
+    bool requiresOwnBackingStore(const RenderLayer*, const RenderLayer* compositingAncestorLayer) const;
+
     RenderLayer* rootRenderLayer() const;
     GraphicsLayer* rootGraphicsLayer() const;
     GraphicsLayer* scrollLayer() const;
index 3bea353..bf9201a 100755 (executable)
@@ -1243,7 +1243,7 @@ RenderBoxModelObject* RenderObject::containerForRepaint() const
 
 #if USE(ACCELERATED_COMPOSITING)
     if (v->usesCompositing()) {
-        RenderLayer* compLayer = enclosingLayer()->enclosingCompositingLayer();
+        RenderLayer* compLayer = enclosingLayer()->enclosingCompositingLayerForRepaint();
         if (compLayer)
             repaintContainer = compLayer->renderer();
     }
index 265b59a..55d68ed 100644 (file)
@@ -631,7 +631,7 @@ static void write(TextStream& ts, RenderLayer& l,
 #if USE(ACCELERATED_COMPOSITING)
     if (behavior & RenderAsTextShowCompositedLayers) {
         if (l.isComposited())
-            ts << " (composited, bounds " << l.backing()->compositedBounds() << ")";
+            ts << " (composited, bounds=" << l.backing()->compositedBounds() << ", drawsContent=" << l.backing()->graphicsLayer()->drawsContent() << ", paints into ancestor=" << l.backing()->paintsIntoCompositedAncestor() << ")";
     }
 #else
     UNUSED_PARAM(behavior);
index 8f76afb..7f27098 100644 (file)
@@ -255,7 +255,7 @@ void RenderView::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint&)
         }
 
 #if USE(ACCELERATED_COMPOSITING)
-        if (RenderLayer* compositingLayer = layer->enclosingCompositingLayer()) {
+        if (RenderLayer* compositingLayer = layer->enclosingCompositingLayerForRepaint()) {
             if (!compositingLayer->backing()->paintsIntoWindow()) {
                 frameView()->setCannotBlitToWindow();
                 break;