Title: [98152] branches/safari-534.52-branch

Diff

Modified: branches/safari-534.52-branch/LayoutTests/ChangeLog (98151 => 98152)


--- branches/safari-534.52-branch/LayoutTests/ChangeLog	2011-10-21 21:16:03 UTC (rev 98151)
+++ branches/safari-534.52-branch/LayoutTests/ChangeLog	2011-10-21 21:22:50 UTC (rev 98152)
@@ -1,5 +1,21 @@
 2011-10-21  Lucas Forschler  <lforsch...@apple.com>
 
+    Merge 98060
+
+    2011-10-20  Simon Fraser  <simon.fra...@apple.com>
+
+            Hidden composited iframes cause infinite loop
+            https://bugs.webkit.org/show_bug.cgi?id=52655
+
+            Reviewed by Darin Adler.
+
+            Test with a visibility:hidden iframe, whose subframe becomes composited.
+
+            * compositing/visibility/hidden-iframe-expected.txt: Added.
+            * compositing/visibility/hidden-iframe.html: Added.
+
+2011-10-21  Lucas Forschler  <lforsch...@apple.com>
+
     Merge 97821
 
     2011-10-18  Anders Carlsson  <ander...@apple.com>

Deleted: branches/safari-534.52-branch/LayoutTests/compositing/visibility/hidden-iframe-expected.txt (98060 => 98152)


--- trunk/LayoutTests/compositing/visibility/hidden-iframe-expected.txt	2011-10-21 03:02:05 UTC (rev 98060)
+++ branches/safari-534.52-branch/LayoutTests/compositing/visibility/hidden-iframe-expected.txt	2011-10-21 21:22:50 UTC (rev 98152)
@@ -1,3 +0,0 @@
-PASS: test did not hang.
-
-

Copied: branches/safari-534.52-branch/LayoutTests/compositing/visibility/hidden-iframe-expected.txt (from rev 98060, trunk/LayoutTests/compositing/visibility/hidden-iframe-expected.txt) (0 => 98152)


--- branches/safari-534.52-branch/LayoutTests/compositing/visibility/hidden-iframe-expected.txt	                        (rev 0)
+++ branches/safari-534.52-branch/LayoutTests/compositing/visibility/hidden-iframe-expected.txt	2011-10-21 21:22:50 UTC (rev 98152)
@@ -0,0 +1,3 @@
+PASS: test did not hang.
+
+

Deleted: branches/safari-534.52-branch/LayoutTests/compositing/visibility/hidden-iframe.html (98060 => 98152)


--- trunk/LayoutTests/compositing/visibility/hidden-iframe.html	2011-10-21 03:02:05 UTC (rev 98060)
+++ branches/safari-534.52-branch/LayoutTests/compositing/visibility/hidden-iframe.html	2011-10-21 21:22:50 UTC (rev 98152)
@@ -1,31 +0,0 @@
-<html>
-  <head>
-    <style>
-      iframe {
-        visibility: hidden;
-        position: absolute;
-      }
-    </style>
-    <script>
-      if (window.layoutTestController) {
-          layoutTestController.dumpAsText();
-          layoutTestController.waitUntilDone();
-      }
-
-      // Called from subframe.
-      function testDone()
-      {
-        // This timeout is necessary to detect the hang.
-        window.setTimeout(function() {
-          document.getElementById('results').innerText = 'PASS: test did not hang.';
-          if (window.layoutTestController)
-            layoutTestController.notifyDone();
-        }, 0);
-      }
-    </script>
-  </head>
-  <body>
-    <p id="results">This test should not hang.</p>
-    <iframe src=""
-  </body>
-</html>

Copied: branches/safari-534.52-branch/LayoutTests/compositing/visibility/hidden-iframe.html (from rev 98060, trunk/LayoutTests/compositing/visibility/hidden-iframe.html) (0 => 98152)


--- branches/safari-534.52-branch/LayoutTests/compositing/visibility/hidden-iframe.html	                        (rev 0)
+++ branches/safari-534.52-branch/LayoutTests/compositing/visibility/hidden-iframe.html	2011-10-21 21:22:50 UTC (rev 98152)
@@ -0,0 +1,31 @@
+<html>
+  <head>
+    <style>
+      iframe {
+        visibility: hidden;
+        position: absolute;
+      }
+    </style>
+    <script>
+      if (window.layoutTestController) {
+          layoutTestController.dumpAsText();
+          layoutTestController.waitUntilDone();
+      }
+
+      // Called from subframe.
+      function testDone()
+      {
+        // This timeout is necessary to detect the hang.
+        window.setTimeout(function() {
+          document.getElementById('results').innerText = 'PASS: test did not hang.';
+          if (window.layoutTestController)
+            layoutTestController.notifyDone();
+        }, 0);
+      }
+    </script>
+  </head>
+  <body>
+    <p id="results">This test should not hang.</p>
+    <iframe src=""
+  </body>
+</html>

Modified: branches/safari-534.52-branch/Source/WebCore/ChangeLog (98151 => 98152)


--- branches/safari-534.52-branch/Source/WebCore/ChangeLog	2011-10-21 21:16:03 UTC (rev 98151)
+++ branches/safari-534.52-branch/Source/WebCore/ChangeLog	2011-10-21 21:22:50 UTC (rev 98152)
@@ -1,5 +1,50 @@
 2011-10-21  Lucas Forschler  <lforsch...@apple.com>
 
+    Merge 98060
+
+    2011-10-20  Simon Fraser  <simon.fra...@apple.com>
+
+            Hidden composited iframes cause infinite loop
+            https://bugs.webkit.org/show_bug.cgi?id=52655
+
+            Reviewed by Darin Adler.
+
+            visibility:hidden is problematic for compositing, because it causes
+            RenderLayers to be removed from the z-order layer tree. This confuses
+            RenderLayerCompositor in several ways; it never sees these layers
+            when traversing the tree as it computes compositing requirements, or
+            rebuilds the layer tree.
+
+            This is a particular problem with composited iframes. When an iframe
+            becomes composited, scheduleSetNeedsStyleRecalc() is called on that
+            iframe's ownerElement in the parent document. If this happens inside
+            Document::updateStyleForAllDocuments(), we get into an infinite loop
+            because notifyIFramesOfCompositingChange() queues up style update as we
+            bounce in and out of compositing mode, so documentsThatNeedStyleRecalc
+            never empties out.
+
+            This is an initial, conservative fix that doesn't attempt to fix all
+            the issues with visibility. It changes RenderLayerCompositor to count
+            the number of compositing RenderLayers, and to not leave compositing
+            mode if there are any (even if they are hidden, so not hit while
+            traversing the z-order tree). This avoids the infinite loop.
+
+            Test: compositing/visibility/hidden-iframe.html
+
+            * rendering/RenderLayer.cpp:
+            (WebCore::RenderLayer::ensureBacking):
+            (WebCore::RenderLayer::clearBacking):
+            * rendering/RenderLayerCompositor.cpp:
+            (WebCore::RenderLayerCompositor::RenderLayerCompositor):
+            (WebCore::RenderLayerCompositor::hasAnyAdditionalCompositedLayers):
+            (WebCore::RenderLayerCompositor::updateCompositingLayers):
+            (WebCore::RenderLayerCompositor::computeCompositingRequirements):
+            * rendering/RenderLayerCompositor.h:
+            (WebCore::RenderLayerCompositor::layerBecameComposited):
+            (WebCore::RenderLayerCompositor::layerBecameNonComposited):
+
+2011-10-21  Lucas Forschler  <lforsch...@apple.com>
+
     Merge 97821
 
     2011-10-18  Anders Carlsson  <ander...@apple.com>

Modified: branches/safari-534.52-branch/Source/WebCore/rendering/RenderLayer.cpp (98151 => 98152)


--- branches/safari-534.52-branch/Source/WebCore/rendering/RenderLayer.cpp	2011-10-21 21:16:03 UTC (rev 98151)
+++ branches/safari-534.52-branch/Source/WebCore/rendering/RenderLayer.cpp	2011-10-21 21:22:50 UTC (rev 98152)
@@ -3657,13 +3657,17 @@
 #if USE(ACCELERATED_COMPOSITING)
 RenderLayerBacking* RenderLayer::ensureBacking()
 {
-    if (!m_backing)
+    if (!m_backing) {
         m_backing = adoptPtr(new RenderLayerBacking(this));
+        compositor()->layerBecameComposited(this);
+    }
     return m_backing.get();
 }
 
 void RenderLayer::clearBacking()
 {
+    if (m_backing && !renderer()->documentBeingDestroyed())
+        compositor()->layerBecameNonComposited(this);
     m_backing.clear();
 }
 

Modified: branches/safari-534.52-branch/Source/WebCore/rendering/RenderLayerCompositor.cpp (98151 => 98152)


--- branches/safari-534.52-branch/Source/WebCore/rendering/RenderLayerCompositor.cpp	2011-10-21 21:16:03 UTC (rev 98151)
+++ branches/safari-534.52-branch/Source/WebCore/rendering/RenderLayerCompositor.cpp	2011-10-21 21:22:50 UTC (rev 98152)
@@ -95,6 +95,7 @@
     , m_updateCompositingLayersTimer(this, &RenderLayerCompositor::updateCompositingLayersTimerFired)
     , m_hasAcceleratedCompositing(true)
     , m_compositingTriggers(static_cast<ChromeClient::CompositingTriggerFlags>(ChromeClient::AllTriggers))
+    , m_compositedLayerCount(0)
     , m_showDebugBorders(false)
     , m_showRepaintCounter(false)
     , m_compositingConsultsOverlap(true)
@@ -237,6 +238,11 @@
     updateCompositingLayers();
 }
 
+bool RenderLayerCompositor::hasAnyAdditionalCompositedLayers(const RenderLayer* rootLayer) const
+{
+    return m_compositedLayerCount > rootLayer->isComposited();
+}
+
 void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType updateType, RenderLayer* updateRoot)
 {
     m_updateCompositingLayersTimer.stop();
@@ -298,7 +304,9 @@
 
         // Host the document layer in the RenderView's root layer.
         if (updateRoot == rootRenderLayer()) {
-            if (childList.isEmpty())
+            // Even when childList is empty, don't drop out of compositing mode if there are
+            // composited layers that we didn't hit in our traversal (e.g. because of visibility:hidden).
+            if (childList.isEmpty() && !hasAnyAdditionalCompositedLayers(updateRoot))
                 destroyRootPlatformLayer();
             else
                 m_rootPlatformLayer->setChildren(childList);
@@ -720,8 +728,9 @@
     }
 
     // If we're back at the root, and no other layers need to be composited, and the root layer itself doesn't need
-    // to be composited, then we can drop out of compositing mode altogether.
-    if (layer->isRootLayer() && !childState.m_subtreeIsCompositing && !requiresCompositingLayer(layer) && !m_forceCompositingMode) {
+    // to be composited, then we can drop out of compositing mode altogether. However, don't drop out of compositing mode
+    // if there are composited layers that we didn't hit in our traversal (e.g. because of visibility:hidden).
+    if (layer->isRootLayer() && !childState.m_subtreeIsCompositing && !requiresCompositingLayer(layer) && !m_forceCompositingMode && !hasAnyAdditionalCompositedLayers(layer)) {
         enableCompositingMode(false);
         willBeComposited = false;
     }

Modified: branches/safari-534.52-branch/Source/WebCore/rendering/RenderLayerCompositor.h (98151 => 98152)


--- branches/safari-534.52-branch/Source/WebCore/rendering/RenderLayerCompositor.h	2011-10-21 21:16:03 UTC (rev 98151)
+++ branches/safari-534.52-branch/Source/WebCore/rendering/RenderLayerCompositor.h	2011-10-21 21:22:50 UTC (rev 98152)
@@ -148,6 +148,13 @@
     void didMoveOnscreen();
     void willMoveOffscreen();
     
+    void layerBecameComposited(const RenderLayer*) { ++m_compositedLayerCount; }
+    void layerBecameNonComposited(const RenderLayer*)
+    {
+        ASSERT(m_compositedLayerCount > 0);
+        --m_compositedLayerCount;
+    }
+    
     void didStartAcceleratedAnimation(CSSPropertyID);
     
 #if ENABLE(VIDEO)
@@ -232,6 +239,8 @@
     void removeCompositedChildren(RenderLayer*);
 
     bool layerHas3DContent(const RenderLayer*) const;
+    
+    bool hasAnyAdditionalCompositedLayers(const RenderLayer* rootLayer) const;
 
     void ensureRootPlatformLayer();
     void destroyRootPlatformLayer();
@@ -269,6 +278,7 @@
     bool m_hasAcceleratedCompositing;
     ChromeClient::CompositingTriggerFlags m_compositingTriggers;
 
+    int m_compositedLayerCount;
     bool m_showDebugBorders;
     bool m_showRepaintCounter;
     bool m_compositingConsultsOverlap;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to