Element is displayed behind a composited layer when clipping is used on a previous...
authorachicu@adobe.com <achicu@adobe.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 11 Jan 2013 22:05:25 +0000 (22:05 +0000)
committerachicu@adobe.com <achicu@adobe.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 11 Jan 2013 22:05:25 +0000 (22:05 +0000)
https://bugs.webkit.org/show_bug.cgi?id=104981

Reviewed by Simon Fraser.

Source/WebCore:

RenderLayerCompositor::computeCompositingRequirements uses the local bounding box of the layers to optimize the number of composited
layers that are created. That's needed in order to make sure that composited layers that are displayed behind non-composited
layers are correctly promoting the layers in front to be composited. Otherwise the non-composited layers are rendered
in the parent composited layer, displaying behind the other composited layers. That might be wrong as the correct paint order might not be
preserved.

In order to make animations work, there's a flag that will disable that optimization. That's because the animations run in the platform
layer and the platform layer doesn't know about the layers that are not promoted to composited layers. When the overlapping of the layers
is computed it just uses the start or the stop state, but no intermediate states. For that reason, all the 'top' layers in front of animated
elements will become composited.

When an animation has a clipping rectangle, then we know for sure that the animation is going to be contained inside the clip area, so WebKit
uses the bounding box of the clipping area to detect the overlapping layers, so there's no need to disable the optimization in that case.

However, if there is a different animation displaying behind the clipping container, we cannot safely disable that optimization anymore. That's
because we still don't know what are the intermediate states of that particular animated layer. The bug was that the optimization was re-enabled
anyway, even in this particular case.

In order to fix it, I changed the logic, so that instead of re-enabling the optimization after a clipping container, it will just avoid to propagate
the internal state to the following layers when there's no need to so.

Note that 3D transforms behave like animations for now and disable the optimization. Because of that some of the existing tests ended up
creating more layers than needed. That's because the tests had an overflow area that recreated the issue that this patch fixes, but with
3D transforms instead of animations. 3D transforms will be treated in a separate patch.

Tests: compositing/layer-creation/overlap-animation-clipping.html
       compositing/layer-creation/overlap-animation-container.html

* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::computeCompositingRequirements):

LayoutTests:

Updated existing test results and added two new tests to check that animations respect the correct paint order,
even though they are painted with composited layers.

Note that there are side effects of this patch that will be corrected in a following bug. 3D layers are treated like animations, so they
disable the overlapping optimizations. Because of that, some of the test results were updated to include the layers that, previously,
were not created as a result of being in front of a "clipping container".

* compositing/geometry/foreground-layer-expected.txt:
* compositing/layer-creation/overlap-animation-clipping-expected.txt: Added.
* compositing/layer-creation/overlap-animation-clipping.html: Added. Checking that the animation inside a clipping container is not
affecting how we compute the animations outside the clipping container.
* compositing/layer-creation/overlap-animation-container-expected.txt: Added.
* compositing/layer-creation/overlap-animation-container.html: Added. Checking that we don't create unnecessary composited layers for layers inside
composited containers that draw in front of animated layers.
* compositing/overflow/clip-descendents-expected.txt:
* compositing/overflow/clip-descendents.html: Removed the text from the output, so that platforms can share the same expected result.
* platform/chromium-win/compositing/overflow/clip-descendents-expected.txt: Removed. Not needed anymore, all Chromium platforms can share the same results now.
* platform/chromium/compositing/geometry/foreground-layer-expected.txt:
* platform/chromium/compositing/layer-creation/overlap-animation-clipping-expected.txt: Added.
* platform/chromium/compositing/layer-creation/overlap-animation-container-expected.txt: Added.
* platform/chromium/compositing/layer-creation/overlap-transformed-3d-expected.txt: Added.
* platform/chromium/compositing/layer-creation/overlap-transforms-expected.txt:
* platform/chromium/compositing/overflow/clip-descendents-expected.txt: Renamed from LayoutTests/platform/chromium-mac/compositing/overflow/clip-descendents-expected.txt.
* platform/qt/compositing/overflow/clip-descendents-expected.txt:

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

17 files changed:
LayoutTests/ChangeLog
LayoutTests/compositing/geometry/foreground-layer-expected.txt
LayoutTests/compositing/layer-creation/overlap-animation-clipping-expected.txt [new file with mode: 0644]
LayoutTests/compositing/layer-creation/overlap-animation-clipping.html [new file with mode: 0644]
LayoutTests/compositing/layer-creation/overlap-animation-container-expected.txt [new file with mode: 0644]
LayoutTests/compositing/layer-creation/overlap-animation-container.html [new file with mode: 0644]
LayoutTests/compositing/overflow/clip-descendents-expected.txt
LayoutTests/compositing/overflow/clip-descendents.html
LayoutTests/platform/chromium-win/compositing/overflow/clip-descendents-expected.txt [deleted file]
LayoutTests/platform/chromium/compositing/geometry/foreground-layer-expected.txt
LayoutTests/platform/chromium/compositing/layer-creation/overlap-animation-clipping-expected.txt [new file with mode: 0644]
LayoutTests/platform/chromium/compositing/layer-creation/overlap-animation-container-expected.txt [new file with mode: 0644]
LayoutTests/platform/chromium/compositing/layer-creation/overlap-transformed-3d-expected.txt [new file with mode: 0644]
LayoutTests/platform/chromium/compositing/overflow/clip-descendents-expected.txt [moved from LayoutTests/platform/chromium-mac/compositing/overflow/clip-descendents-expected.txt with 91% similarity]
LayoutTests/platform/qt/compositing/overflow/clip-descendents-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderLayerCompositor.cpp

index b5308ff..036c3c0 100644 (file)
@@ -1,3 +1,35 @@
+2013-01-11  Alexandru Chiculita  <achicu@adobe.com>
+
+        Element is displayed behind a composited layer when clipping is used on a previous element
+        https://bugs.webkit.org/show_bug.cgi?id=104981
+
+        Reviewed by Simon Fraser.
+
+        Updated existing test results and added two new tests to check that animations respect the correct paint order,
+        even though they are painted with composited layers.
+
+        Note that there are side effects of this patch that will be corrected in a following bug. 3D layers are treated like animations, so they
+        disable the overlapping optimizations. Because of that, some of the test results were updated to include the layers that, previously,
+        were not created as a result of being in front of a "clipping container".
+
+        * compositing/geometry/foreground-layer-expected.txt:
+        * compositing/layer-creation/overlap-animation-clipping-expected.txt: Added.
+        * compositing/layer-creation/overlap-animation-clipping.html: Added. Checking that the animation inside a clipping container is not 
+        affecting how we compute the animations outside the clipping container. 
+        * compositing/layer-creation/overlap-animation-container-expected.txt: Added. 
+        * compositing/layer-creation/overlap-animation-container.html: Added. Checking that we don't create unnecessary composited layers for layers inside
+        composited containers that draw in front of animated layers.
+        * compositing/overflow/clip-descendents-expected.txt:
+        * compositing/overflow/clip-descendents.html: Removed the text from the output, so that platforms can share the same expected result.
+        * platform/chromium-win/compositing/overflow/clip-descendents-expected.txt: Removed. Not needed anymore, all Chromium platforms can share the same results now.
+        * platform/chromium/compositing/geometry/foreground-layer-expected.txt:
+        * platform/chromium/compositing/layer-creation/overlap-animation-clipping-expected.txt: Added.
+        * platform/chromium/compositing/layer-creation/overlap-animation-container-expected.txt: Added.
+        * platform/chromium/compositing/layer-creation/overlap-transformed-3d-expected.txt: Added.
+        * platform/chromium/compositing/layer-creation/overlap-transforms-expected.txt:
+        * platform/chromium/compositing/overflow/clip-descendents-expected.txt: Renamed from LayoutTests/platform/chromium-mac/compositing/overflow/clip-descendents-expected.txt.
+        * platform/qt/compositing/overflow/clip-descendents-expected.txt:
+
 2013-01-11  Stephen Chenney  <schenney@chromium.org>
 
         [Chromium] More test expectations for Skia changes
index 3bf769d..1a44182 100644 (file)
@@ -4,7 +4,7 @@
   (children 1
     (GraphicsLayer
       (bounds 800.00 600.00)
-      (children 2
+      (children 3
         (GraphicsLayer
           (position 18.00 18.00)
           (bounds 320.00 320.00)
             )
           )
         )
+        (GraphicsLayer
+          (position 8.00 361.00)
+          (bounds 784.00 10.00)
+          (opacity 0.00)
+        )
       )
     )
   )
diff --git a/LayoutTests/compositing/layer-creation/overlap-animation-clipping-expected.txt b/LayoutTests/compositing/layer-creation/overlap-animation-clipping-expected.txt
new file mode 100644 (file)
index 0000000..331309e
--- /dev/null
@@ -0,0 +1,51 @@
+(GraphicsLayer
+  (bounds 785.00 812.00)
+  (children 1
+    (GraphicsLayer
+      (bounds 785.00 812.00)
+      (children 3
+        (GraphicsLayer
+          (position 18.00 120.00)
+          (bounds 100.00 100.00)
+          (transform [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 -110.00 0.00 1.00])
+        )
+        (GraphicsLayer
+          (position 58.00 230.00)
+          (bounds 122.00 462.00)
+          (drawsContent 1)
+          (children 1
+            (GraphicsLayer
+              (position 1.00 1.00)
+              (bounds 120.00 460.00)
+              (children 4
+                (GraphicsLayer
+                  (position 10.00 10.00)
+                  (bounds 100.00 100.00)
+                  (transform [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 1.00 1.00])
+                )
+                (GraphicsLayer
+                  (position 10.00 120.00)
+                  (bounds 100.00 100.00)
+                )
+                (GraphicsLayer
+                  (position 10.00 230.00)
+                  (bounds 100.00 100.00)
+                  (transform [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 -220.00 0.00 1.00])
+                )
+                (GraphicsLayer
+                  (position 10.00 340.00)
+                  (bounds 100.00 100.00)
+                )
+              )
+            )
+          )
+        )
+        (GraphicsLayer
+          (position 18.00 702.00)
+          (bounds 100.00 100.00)
+        )
+      )
+    )
+  )
+)
+
diff --git a/LayoutTests/compositing/layer-creation/overlap-animation-clipping.html b/LayoutTests/compositing/layer-creation/overlap-animation-clipping.html
new file mode 100644 (file)
index 0000000..b2a2cf3
--- /dev/null
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+  <style>
+    .container {
+      height: 460px;
+      width: 120px;
+      overflow: hidden;
+      position: relative;
+      left: 50px;
+      z-index: 0; /* create stacking context */
+      border: 1px solid black;
+      background-color: white;
+    }
+    
+    .box {
+      position: relative;
+      width: 100px;
+      height: 100px;
+      margin: 10px;
+      background-color: blue;
+    }
+
+    .force-layer {
+      -webkit-transform: translateZ(1px);
+    }
+
+    .yellow {
+      background-color: yellow;
+    }
+
+    .gray {
+      background-color: gray;
+    }
+    
+    .animating1 {
+      -webkit-animation: translate1 2s linear infinite alternate;
+    }
+
+    .animating2 {
+      -webkit-animation: translate2 2s linear infinite alternate;
+    }
+    
+    @-webkit-keyframes translate1 {
+      from { -webkit-transform: translate(0px, -110px); }
+      to   { -webkit-transform: translate(0px, 590px); }
+    }
+
+    @-webkit-keyframes translate2 {
+      from { -webkit-transform: translate(0px, -220px); }
+      to   { -webkit-transform: translate(0px, 110px); }
+    }
+  </style>
+  <script>
+    if (window.testRunner) {
+      testRunner.dumpAsText();
+      testRunner.waitUntilDone();
+    }
+
+    function queueBoxForAnimation(elementId, animationClass, callback) {
+      var box = document.getElementById(elementId);
+      if (callback)
+        box.addEventListener('webkitAnimationStart', callback, false);
+      box.classList.add(animationClass);
+    }
+      
+    function runTest()
+    {
+      queueBoxForAnimation("to-animate1", "animating1");
+      queueBoxForAnimation("to-animate2", "animating2", animationStarted);
+    }
+
+    function animationStarted()
+    {
+      if (window.testRunner) {
+        var layersElement = document.getElementById('layers');
+        // Make sure we don't include the #layers element in the tree. The text size
+        // might differ between platforms.
+        layersElement.style.display = "none";
+        layersElement.innerText = window.internals.layerTreeAsText(document);
+        layersElement.style.display = "block";
+        testRunner.notifyDone();
+      }
+    }
+    window.addEventListener('load', runTest, false);
+  </script>
+</head>
+<body>
+  <!-- The test checks that composited layers are created when needed to display elements in front of animated layers. 
+       There are two animations going at the same time. The second animation is inside a clipping
+       container (white background with black border). The first animation should display behind the clipping container.
+       For both animations, the following should be true:
+       1. Yellow box should display in front of the blue box.
+       2. Gray boxes should display behind the blue box. 
+  -->
+  <!-- This div will not get a layer -->
+  <div class="box gray"></div>
+  <div id="to-animate1" class="box"></div>
+  <div class="container">
+    <!-- This div will be forced to get a layer -->
+    <div class="box gray force-layer"></div>
+    <!-- This div will not get a layer -->
+    <div class="box gray"></div>
+    <div id="to-animate2" class="box"></div>
+    <!-- This div will get a layer -->
+    <div class="box yellow"></div>
+  </div>
+  <!-- This div will also get a layer -->
+  <div class="box yellow"></div>
+  <pre id="layers">Layer tree goes here in DRT</pre>
+</body>
+</html>
diff --git a/LayoutTests/compositing/layer-creation/overlap-animation-container-expected.txt b/LayoutTests/compositing/layer-creation/overlap-animation-container-expected.txt
new file mode 100644 (file)
index 0000000..bf50bbe
--- /dev/null
@@ -0,0 +1,99 @@
+Before:
+(GraphicsLayer
+  (bounds 785.00 802.00)
+  (children 1
+    (GraphicsLayer
+      (bounds 785.00 802.00)
+      (children 3
+        (GraphicsLayer
+          (position 17.00 119.00)
+          (bounds 102.00 102.00)
+          (transform [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 -110.00 0.00 1.00])
+        )
+        (GraphicsLayer
+          (position 57.00 229.00)
+          (bounds 124.00 454.00)
+          (drawsContent 1)
+          (children 4
+            (GraphicsLayer
+              (position 11.00 11.00)
+              (bounds 102.00 102.00)
+              (transform [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 -1.00 1.00])
+            )
+            (GraphicsLayer
+              (position 11.00 121.00)
+              (bounds 102.00 102.00)
+              (drawsContent 1)
+            )
+            (GraphicsLayer
+              (position 11.00 231.00)
+              (bounds 102.00 102.00)
+              (drawsContent 1)
+              (transform [0.71 0.71 0.00 0.00] [-0.71 0.71 0.00 0.00] [0.00 0.00 1.00 0.00] [0.00 0.00 0.00 1.00])
+            )
+            (GraphicsLayer
+              (position 11.00 341.00)
+              (bounds 102.00 102.00)
+              (drawsContent 1)
+            )
+          )
+        )
+        (GraphicsLayer
+          (position 17.00 691.00)
+          (bounds 102.00 102.00)
+        )
+      )
+    )
+  )
+)
+
+After:
+(GraphicsLayer
+  (bounds 785.00 802.00)
+  (children 1
+    (GraphicsLayer
+      (bounds 785.00 802.00)
+      (children 3
+        (GraphicsLayer
+          (position 17.00 119.00)
+          (bounds 102.00 102.00)
+          (transform [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 -110.00 0.00 1.00])
+        )
+        (GraphicsLayer
+          (position 57.00 229.00)
+          (bounds 124.00 454.00)
+          (drawsContent 1)
+          (children 4
+            (GraphicsLayer
+              (position 11.00 11.00)
+              (bounds 102.00 102.00)
+              (transform [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 -1.00 1.00])
+            )
+            (GraphicsLayer
+              (position 11.00 121.00)
+              (bounds 102.00 102.00)
+              (drawsContent 1)
+              (transform [0.71 0.71 0.00 0.00] [-0.71 0.71 0.00 0.00] [0.00 0.00 1.00 0.00] [0.00 0.00 0.00 1.00])
+            )
+            (GraphicsLayer
+              (position 11.00 231.00)
+              (bounds 102.00 102.00)
+              (drawsContent 1)
+              (transform [0.71 0.71 0.00 0.00] [-0.71 0.71 0.00 0.00] [0.00 0.00 1.00 0.00] [0.00 0.00 0.00 1.00])
+            )
+            (GraphicsLayer
+              (position 11.00 341.00)
+              (bounds 102.00 102.00)
+              (drawsContent 1)
+            )
+          )
+        )
+        (GraphicsLayer
+          (position 17.00 691.00)
+          (bounds 102.00 102.00)
+        )
+      )
+    )
+  )
+)
+
diff --git a/LayoutTests/compositing/layer-creation/overlap-animation-container.html b/LayoutTests/compositing/layer-creation/overlap-animation-container.html
new file mode 100644 (file)
index 0000000..92fed15
--- /dev/null
@@ -0,0 +1,116 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+  <style>
+    .container {
+      width: 120px;
+      position: relative;
+      left: 50px;
+      z-index: 0; /* create stacking context */
+      border: 1px solid black;
+      background-color: white;
+    }
+    
+    .box {
+      position: relative;
+      width: 100px;
+      height: 100px;
+      margin: 10px;
+      background-color: blue;
+    }
+
+    .force-layer {
+      -webkit-transform: translateZ(-1px);
+    }
+
+    .rotate-45deg {
+      -webkit-transform: rotate(45deg);
+    }
+
+    .yellow {
+      background-color: yellow;
+    }
+
+    .gray {
+      background-color: gray;
+    }
+
+    .green {
+      background-color: green;
+      outline: 1px solid black;
+    }
+    
+    .animating1 {
+      -webkit-animation: translate1 2s linear infinite alternate;
+    }
+   
+    @-webkit-keyframes translate1 {
+      from { -webkit-transform: translate(0px, -110px); }
+      to   { -webkit-transform: translate(0px, 700px); }
+    }
+  </style>
+  <script>
+    if (window.testRunner) {
+      testRunner.dumpAsText();
+      testRunner.waitUntilDone();
+    }
+
+    function queueBoxForAnimation(elementId, animationClass, callback) {
+      var box = document.getElementById(elementId);
+      box.addEventListener('webkitAnimationStart', callback, false);
+      box.classList.add(animationClass);
+    }
+      
+    function runTest()
+    {
+      queueBoxForAnimation("to-animate1", "animating1", animationStarted);
+    }
+    
+    function animationStarted()
+    {
+      var layerTrees = "";
+
+      if (window.testRunner) {
+        var layersElement = document.getElementById('layers');
+        // Make sure we don't include the #layers element in the tree. The text size
+        // might differ between platforms.
+        layersElement.style.display = "none";
+        layerTrees = "Before:\n" + window.internals.layerTreeAsText(document);
+      }
+
+      // Rotate the first green box, so that it overlaps the first gray box in the container.
+      // That should force the creation of composited layers for all the other green boxes.
+      document.getElementById("first-green-box").classList.add("rotate-45deg");
+
+      if (window.testRunner) {
+        layerTrees += "\nAfter:\n" + window.internals.layerTreeAsText(document);
+        layersElement.style.display = "block";
+        layersElement.innerText = layerTrees;
+        testRunner.notifyDone();
+      }
+    }
+    window.addEventListener('load', runTest, false);
+  </script>
+</head>
+<body>
+  <!-- Testing that compositor doesn't create unnecessary composited layers when they could be drawn in parents backing texture. 
+       The green boxes should not have composited layers.
+  -->
+  <!-- This div will not get a layer -->
+  <div class="box gray"></div>
+  <div id="to-animate1" class="box"></div>
+  <div class="container">
+    <!-- Force a composited box inside the container. The fact that there's an animation going behind the parent container, 
+    should not force the remaining children of this element create their own composited layers. -->
+    <div class="box gray force-layer"></div>
+    <!-- This following have no reason to get a layer, as the parent will get one. -->
+    <div id="first-green-box" class="box green"></div>
+    <div class="box green rotate-45deg"></div>
+    <div class="box green"></div>
+  </div>
+  <!-- This div will also get a layer -->
+  <div class="box yellow"></div>
+  <pre id="layers">Layer tree goes here in DRT</pre>
+</body>
+</html>
index ef9d3bf..b3eb7a7 100644 (file)
@@ -1,5 +1,3 @@
-Test overflow clipping of composited elements in various configurations.
-
 (GraphicsLayer
   (bounds 800.00 600.00)
   (children 1
@@ -7,7 +5,7 @@ Test overflow clipping of composited elements in various configurations.
       (bounds 800.00 600.00)
       (children 6
         (GraphicsLayer
-          (position 48.00 80.00)
+          (position 48.00 38.00)
           (bounds 60.00 70.00)
           (children 1
             (GraphicsLayer
@@ -18,12 +16,12 @@ Test overflow clipping of composited elements in various configurations.
           )
         )
         (GraphicsLayer
-          (position 240.00 80.00)
+          (position 240.00 38.00)
           (bounds 60.00 70.00)
           (drawsContent 1)
         )
         (GraphicsLayer
-          (position 240.00 80.00)
+          (position 240.00 38.00)
           (bounds 60.00 70.00)
           (children 1
             (GraphicsLayer
@@ -34,7 +32,7 @@ Test overflow clipping of composited elements in various configurations.
           )
         )
         (GraphicsLayer
-          (position 240.00 80.00)
+          (position 240.00 38.00)
           (bounds 60.00 70.00)
           (children 1
             (GraphicsLayer
@@ -64,6 +62,7 @@ Test overflow clipping of composited elements in various configurations.
         (GraphicsLayer
           (position 240.00 230.00)
           (bounds 60.00 70.00)
+          (drawsContent 1)
           (children 1
             (GraphicsLayer
               (bounds 60.00 70.00)
index 9fd5cb5..091bf3c 100644 (file)
       
     function doTest() {
       if (window.testRunner) {
-        document.getElementById('layers').innerText = window.internals.layerTreeAsText(document);
+        var layersElement = document.getElementById('layers');
+        // Do not include any text in the layers output, otherwise we need expected results for each platform.
+        layersElement.style.display = "none";
+        layersElement.innerText = window.internals.layerTreeAsText(document);
+        layersElement.style.display = "block";
         testRunner.notifyDone();
       }
     }
@@ -48,7 +52,7 @@
 </head>
 <body>
 
-<p>Test overflow clipping of composited elements in various configurations.</p>
+<!-- Test overflow clipping of composited elements in various configurations. -->
 <div class="container">
   <div class="intermediate">
     <div class="box">
diff --git a/LayoutTests/platform/chromium-win/compositing/overflow/clip-descendents-expected.txt b/LayoutTests/platform/chromium-win/compositing/overflow/clip-descendents-expected.txt
deleted file mode 100644 (file)
index fd67b2c..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-Test overflow clipping of composited elements in various configurations.
-
-(GraphicsLayer
-  (bounds 800.00 600.00)
-  (children 1
-    (GraphicsLayer
-      (bounds 800.00 600.00)
-      (children 6
-        (GraphicsLayer
-          (position 48.00 82.00)
-          (bounds 60.00 70.00)
-          (children 1
-            (GraphicsLayer
-              (position 2.00 12.00)
-              (bounds 100.00 150.00)
-              (drawsContent 1)
-              (transform [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 1.00 1.00])
-            )
-          )
-        )
-        (GraphicsLayer
-          (position 240.00 82.00)
-          (bounds 60.00 70.00)
-          (drawsContent 1)
-        )
-        (GraphicsLayer
-          (position 240.00 82.00)
-          (bounds 60.00 70.00)
-          (children 1
-            (GraphicsLayer
-              (position 0.00 1.00)
-              (bounds 60.00 69.00)
-              (drawsContent 1)
-            )
-          )
-        )
-        (GraphicsLayer
-          (position 240.00 82.00)
-          (bounds 60.00 70.00)
-          (children 1
-            (GraphicsLayer
-              (position 2.00 12.00)
-              (bounds 100.00 150.00)
-              (drawsContent 1)
-              (transform [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 1.00 1.00])
-            )
-          )
-        )
-        (GraphicsLayer
-          (position 48.00 230.00)
-          (bounds 60.00 70.00)
-          (drawsContent 1)
-          (children 1
-            (GraphicsLayer
-              (bounds 60.00 70.00)
-              (children 1
-                (GraphicsLayer
-                  (position 2.00 12.00)
-                  (bounds 100.00 150.00)
-                  (drawsContent 1)
-                  (transform [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 1.00 1.00])
-                )
-              )
-            )
-          )
-        )
-        (GraphicsLayer
-          (position 240.00 230.00)
-          (bounds 60.00 70.00)
-          (children 1
-            (GraphicsLayer
-              (bounds 60.00 70.00)
-              (children 1
-                (GraphicsLayer
-                  (position 2.00 12.00)
-                  (bounds 100.00 150.00)
-                  (drawsContent 1)
-                  (transform [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 1.00 1.00])
-                )
-              )
-            )
-          )
-        )
-      )
-    )
-  )
-)
-
index 3bf769d..1a44182 100644 (file)
@@ -4,7 +4,7 @@
   (children 1
     (GraphicsLayer
       (bounds 800.00 600.00)
-      (children 2
+      (children 3
         (GraphicsLayer
           (position 18.00 18.00)
           (bounds 320.00 320.00)
             )
           )
         )
+        (GraphicsLayer
+          (position 8.00 361.00)
+          (bounds 784.00 10.00)
+          (opacity 0.00)
+        )
       )
     )
   )
diff --git a/LayoutTests/platform/chromium/compositing/layer-creation/overlap-animation-clipping-expected.txt b/LayoutTests/platform/chromium/compositing/layer-creation/overlap-animation-clipping-expected.txt
new file mode 100644 (file)
index 0000000..6856334
--- /dev/null
@@ -0,0 +1,57 @@
+(GraphicsLayer
+  (bounds 785.00 812.00)
+  (children 1
+    (GraphicsLayer
+      (bounds 785.00 812.00)
+      (children 3
+        (GraphicsLayer
+          (position 18.00 120.00)
+          (bounds 100.00 100.00)
+          (drawsContent 1)
+          (transform [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 -110.00 0.00 1.00])
+        )
+        (GraphicsLayer
+          (position 58.00 230.00)
+          (bounds 122.00 462.00)
+          (drawsContent 1)
+          (children 1
+            (GraphicsLayer
+              (position 1.00 1.00)
+              (bounds 120.00 460.00)
+              (children 4
+                (GraphicsLayer
+                  (position 10.00 10.00)
+                  (bounds 100.00 100.00)
+                  (drawsContent 1)
+                  (transform [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 1.00 1.00])
+                )
+                (GraphicsLayer
+                  (position 10.00 120.00)
+                  (bounds 100.00 100.00)
+                  (drawsContent 1)
+                )
+                (GraphicsLayer
+                  (position 10.00 230.00)
+                  (bounds 100.00 100.00)
+                  (drawsContent 1)
+                  (transform [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 -220.00 0.00 1.00])
+                )
+                (GraphicsLayer
+                  (position 10.00 340.00)
+                  (bounds 100.00 100.00)
+                  (drawsContent 1)
+                )
+              )
+            )
+          )
+        )
+        (GraphicsLayer
+          (position 18.00 702.00)
+          (bounds 100.00 100.00)
+          (drawsContent 1)
+        )
+      )
+    )
+  )
+)
+
diff --git a/LayoutTests/platform/chromium/compositing/layer-creation/overlap-animation-container-expected.txt b/LayoutTests/platform/chromium/compositing/layer-creation/overlap-animation-container-expected.txt
new file mode 100644 (file)
index 0000000..2eb1078
--- /dev/null
@@ -0,0 +1,105 @@
+Before:
+(GraphicsLayer
+  (bounds 785.00 802.00)
+  (children 1
+    (GraphicsLayer
+      (bounds 785.00 802.00)
+      (children 3
+        (GraphicsLayer
+          (position 17.00 119.00)
+          (bounds 102.00 102.00)
+          (drawsContent 1)
+          (transform [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 -110.00 0.00 1.00])
+        )
+        (GraphicsLayer
+          (position 57.00 229.00)
+          (bounds 124.00 454.00)
+          (drawsContent 1)
+          (children 4
+            (GraphicsLayer
+              (position 11.00 11.00)
+              (bounds 102.00 102.00)
+              (drawsContent 1)
+              (transform [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 -1.00 1.00])
+            )
+            (GraphicsLayer
+              (position 11.00 121.00)
+              (bounds 102.00 102.00)
+              (drawsContent 1)
+            )
+            (GraphicsLayer
+              (position 11.00 231.00)
+              (bounds 102.00 102.00)
+              (drawsContent 1)
+              (transform [0.71 0.71 0.00 0.00] [-0.71 0.71 0.00 0.00] [0.00 0.00 1.00 0.00] [0.00 0.00 0.00 1.00])
+            )
+            (GraphicsLayer
+              (position 11.00 341.00)
+              (bounds 102.00 102.00)
+              (drawsContent 1)
+            )
+          )
+        )
+        (GraphicsLayer
+          (position 17.00 691.00)
+          (bounds 102.00 102.00)
+          (drawsContent 1)
+        )
+      )
+    )
+  )
+)
+
+After:
+(GraphicsLayer
+  (bounds 785.00 802.00)
+  (children 1
+    (GraphicsLayer
+      (bounds 785.00 802.00)
+      (children 3
+        (GraphicsLayer
+          (position 17.00 119.00)
+          (bounds 102.00 102.00)
+          (drawsContent 1)
+          (transform [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 -110.00 0.00 1.00])
+        )
+        (GraphicsLayer
+          (position 57.00 229.00)
+          (bounds 124.00 454.00)
+          (drawsContent 1)
+          (children 4
+            (GraphicsLayer
+              (position 11.00 11.00)
+              (bounds 102.00 102.00)
+              (drawsContent 1)
+              (transform [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 -1.00 1.00])
+            )
+            (GraphicsLayer
+              (position 11.00 121.00)
+              (bounds 102.00 102.00)
+              (drawsContent 1)
+              (transform [0.71 0.71 0.00 0.00] [-0.71 0.71 0.00 0.00] [0.00 0.00 1.00 0.00] [0.00 0.00 0.00 1.00])
+            )
+            (GraphicsLayer
+              (position 11.00 231.00)
+              (bounds 102.00 102.00)
+              (drawsContent 1)
+              (transform [0.71 0.71 0.00 0.00] [-0.71 0.71 0.00 0.00] [0.00 0.00 1.00 0.00] [0.00 0.00 0.00 1.00])
+            )
+            (GraphicsLayer
+              (position 11.00 341.00)
+              (bounds 102.00 102.00)
+              (drawsContent 1)
+            )
+          )
+        )
+        (GraphicsLayer
+          (position 17.00 691.00)
+          (bounds 102.00 102.00)
+          (drawsContent 1)
+        )
+      )
+    )
+  )
+)
+
diff --git a/LayoutTests/platform/chromium/compositing/layer-creation/overlap-transformed-3d-expected.txt b/LayoutTests/platform/chromium/compositing/layer-creation/overlap-transformed-3d-expected.txt
new file mode 100644 (file)
index 0000000..ece0fa2
--- /dev/null
@@ -0,0 +1,56 @@
+Before:
+(GraphicsLayer
+  (bounds 800.00 600.00)
+  (children 1
+    (GraphicsLayer
+      (bounds 800.00 600.00)
+      (children 1
+        (GraphicsLayer
+          (position 108.00 108.00)
+          (bounds 100.00 100.00)
+          (drawsContent 1)
+          (transform [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 -1.00 1.00])
+        )
+      )
+    )
+  )
+)
+
+After:
+(GraphicsLayer
+  (bounds 800.00 600.00)
+  (children 1
+    (GraphicsLayer
+      (bounds 800.00 600.00)
+      (children 5
+        (GraphicsLayer
+          (position 108.00 108.00)
+          (bounds 100.00 100.00)
+          (drawsContent 1)
+          (transform [0.71 0.71 0.00 0.00] [-0.71 0.71 0.00 0.00] [0.00 0.00 1.00 0.00] [0.00 0.00 -1.00 1.00])
+        )
+        (GraphicsLayer
+          (position 8.00 8.00)
+          (bounds 100.00 150.00)
+          (drawsContent 1)
+        )
+        (GraphicsLayer
+          (position 208.00 8.00)
+          (bounds 100.00 150.00)
+          (drawsContent 1)
+        )
+        (GraphicsLayer
+          (position 8.00 158.00)
+          (bounds 100.00 150.00)
+          (drawsContent 1)
+        )
+        (GraphicsLayer
+          (position 208.00 158.00)
+          (bounds 100.00 150.00)
+          (drawsContent 1)
+        )
+      )
+    )
+  )
+)
+
@@ -1,5 +1,3 @@
-Test overflow clipping of composited elements in various configurations.
-
 (GraphicsLayer
   (bounds 800.00 600.00)
   (children 1
@@ -7,7 +5,7 @@ Test overflow clipping of composited elements in various configurations.
       (bounds 800.00 600.00)
       (children 6
         (GraphicsLayer
-          (position 48.00 80.00)
+          (position 48.00 38.00)
           (bounds 60.00 70.00)
           (children 1
             (GraphicsLayer
@@ -19,12 +17,12 @@ Test overflow clipping of composited elements in various configurations.
           )
         )
         (GraphicsLayer
-          (position 240.00 80.00)
+          (position 240.00 38.00)
           (bounds 60.00 70.00)
           (drawsContent 1)
         )
         (GraphicsLayer
-          (position 240.00 80.00)
+          (position 240.00 38.00)
           (bounds 60.00 70.00)
           (children 1
             (GraphicsLayer
@@ -35,7 +33,7 @@ Test overflow clipping of composited elements in various configurations.
           )
         )
         (GraphicsLayer
-          (position 240.00 80.00)
+          (position 240.00 38.00)
           (bounds 60.00 70.00)
           (children 1
             (GraphicsLayer
@@ -67,6 +65,7 @@ Test overflow clipping of composited elements in various configurations.
         (GraphicsLayer
           (position 240.00 230.00)
           (bounds 60.00 70.00)
+          (drawsContent 1)
           (children 1
             (GraphicsLayer
               (bounds 60.00 70.00)
index 3f11f1c..2c4dff2 100644 (file)
@@ -1,5 +1,3 @@
-Test overflow clipping of composited elements in various configurations.
-
 (GraphicsLayer
   (bounds 800.00 600.00)
   (children 1
@@ -7,7 +5,7 @@ Test overflow clipping of composited elements in various configurations.
       (bounds 800.00 600.00)
       (children 6
         (GraphicsLayer
-          (position 48.00 81.00)
+          (position 48.00 38.00)
           (bounds 60.00 70.00)
           (children 1
             (GraphicsLayer
@@ -19,12 +17,12 @@ Test overflow clipping of composited elements in various configurations.
           )
         )
         (GraphicsLayer
-          (position 240.00 81.00)
+          (position 240.00 38.00)
           (bounds 60.00 70.00)
           (drawsContent 1)
         )
         (GraphicsLayer
-          (position 240.00 81.00)
+          (position 240.00 38.00)
           (bounds 60.00 70.00)
           (children 1
             (GraphicsLayer
@@ -35,7 +33,7 @@ Test overflow clipping of composited elements in various configurations.
           )
         )
         (GraphicsLayer
-          (position 240.00 81.00)
+          (position 240.00 38.00)
           (bounds 60.00 70.00)
           (children 1
             (GraphicsLayer
@@ -67,6 +65,7 @@ Test overflow clipping of composited elements in various configurations.
         (GraphicsLayer
           (position 240.00 230.00)
           (bounds 60.00 70.00)
+          (drawsContent 1)
           (children 1
             (GraphicsLayer
               (bounds 60.00 70.00)
index 5c4dfb1..bf1d914 100644 (file)
@@ -1,3 +1,41 @@
+2013-01-11  Alexandru Chiculita  <achicu@adobe.com>
+
+        Element is displayed behind a composited layer when clipping is used on a previous element
+        https://bugs.webkit.org/show_bug.cgi?id=104981
+
+        Reviewed by Simon Fraser.
+
+        RenderLayerCompositor::computeCompositingRequirements uses the local bounding box of the layers to optimize the number of composited 
+        layers that are created. That's needed in order to make sure that composited layers that are displayed behind non-composited
+        layers are correctly promoting the layers in front to be composited. Otherwise the non-composited layers are rendered
+        in the parent composited layer, displaying behind the other composited layers. That might be wrong as the correct paint order might not be
+        preserved.
+
+        In order to make animations work, there's a flag that will disable that optimization. That's because the animations run in the platform
+        layer and the platform layer doesn't know about the layers that are not promoted to composited layers. When the overlapping of the layers
+        is computed it just uses the start or the stop state, but no intermediate states. For that reason, all the 'top' layers in front of animated 
+        elements will become composited.
+
+        When an animation has a clipping rectangle, then we know for sure that the animation is going to be contained inside the clip area, so WebKit 
+        uses the bounding box of the clipping area to detect the overlapping layers, so there's no need to disable the optimization in that case.
+
+        However, if there is a different animation displaying behind the clipping container, we cannot safely disable that optimization anymore. That's
+        because we still don't know what are the intermediate states of that particular animated layer. The bug was that the optimization was re-enabled
+        anyway, even in this particular case.
+
+        In order to fix it, I changed the logic, so that instead of re-enabling the optimization after a clipping container, it will just avoid to propagate 
+        the internal state to the following layers when there's no need to so.
+
+        Note that 3D transforms behave like animations for now and disable the optimization. Because of that some of the existing tests ended up
+        creating more layers than needed. That's because the tests had an overflow area that recreated the issue that this patch fixes, but with
+        3D transforms instead of animations. 3D transforms will be treated in a separate patch.
+
+        Tests: compositing/layer-creation/overlap-animation-clipping.html
+               compositing/layer-creation/overlap-animation-container.html
+
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::computeCompositingRequirements):
+
 2013-01-11  Philip Rogers  <pdr@google.com>
 
         Skip CachedImage::CreateImage if we don't have image data
index b039727..44c281b 100644 (file)
@@ -868,6 +868,9 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor
 
         if (overlapMap)
             overlapMap->pushCompositingContainer();
+        // This layer is going to be composited, so children can safely ignore the fact that there's an 
+        // animation running behind this layer, meaning they can rely on the overlap map testing again.
+        childState.m_testingOverlap = true;
     }
 
 #if !ASSERT_DISABLED
@@ -891,6 +894,9 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor
                     childState.m_compositingAncestor = layer;
                     if (overlapMap)
                         overlapMap->pushCompositingContainer();
+                    // This layer is going to be composited, so children can safely ignore the fact that there's an 
+                    // animation running behind this layer, meaning they can rely on the overlap map testing again
+                    childState.m_testingOverlap = true;
                     willBeComposited = true;
                 }
             }
@@ -952,16 +958,20 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor
     if (childState.m_subtreeIsCompositing)
         compositingState.m_subtreeIsCompositing = true;
 
-    // Turn overlap testing off for later layers if it's already off, or if we have a 3D transform or an animating transform.
-    if (!childState.m_testingOverlap || layer->has3DTransform() || isRunningAcceleratedTransformAnimation(layer->renderer()))
-        compositingState.m_testingOverlap = false;
-
     // Set the flag to say that this SC has compositing children.
     layer->setHasCompositingDescendant(childState.m_subtreeIsCompositing);
 
     // setHasCompositingDescendant() may have changed the answer to needsToBeComposited() when clipping,
     // so test that again.
-    if (canBeComposited(layer) && clipsCompositingDescendants(layer)) {
+    bool isCompositedClippingLayer = canBeComposited(layer) && clipsCompositingDescendants(layer);
+
+    // Turn overlap testing off for later layers if it's already off, or if we have a 3D transform or an animating transform.
+    // Note that if the layer clips its descendants, there's no reason to propagate the child animation to the parent layers. That's because
+    // we know for sure the animation is contained inside the clipping rectangle, which is already added to the overlap map.
+    if ((!childState.m_testingOverlap && !isCompositedClippingLayer) || layer->has3DTransform() || isRunningAcceleratedTransformAnimation(layer->renderer()))
+        compositingState.m_testingOverlap = false;
+    
+    if (isCompositedClippingLayer) {
         if (!willBeComposited) {
             childState.m_compositingAncestor = layer;
             if (overlapMap) {
@@ -970,9 +980,6 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor
             }
             willBeComposited = true;
          }
-
-        // We're done processing an element that clips. The container can keep testing overlap.
-        compositingState.m_testingOverlap = true;
     }
 
     if (overlapMap && childState.m_compositingAncestor == layer && !layer->isRootLayer())