[CSS Filters] Blur filter is not repainted correctly when applied on a parent of...
authorachicu@adobe.com <achicu@adobe.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 9 Jul 2012 19:16:12 +0000 (19:16 +0000)
committerachicu@adobe.com <achicu@adobe.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 9 Jul 2012 19:16:12 +0000 (19:16 +0000)
https://bugs.webkit.org/show_bug.cgi?id=90087

Reviewed by Simon Fraser.

Source/WebCore:

Added a new method, RenderLayer::hasAncestorWithFilterOutsets, to check that there's no filter with outsets (ie. blur)
applied on top level fixed positioned elements, nor any of its parent layers. In the event of a blur filter we need to
disable the fast scrolling optimization, otherwise the outsets of the filter will be carried around the page and
repainting will not work correctly.

Tests: css3/filters/blur-filter-page-scroll-parents.html
       css3/filters/blur-filter-page-scroll-self.html

* page/FrameView.cpp:
(WebCore::FrameView::scrollContentsFastPath):
* rendering/RenderLayer.cpp:
(WebCore):
(WebCore::RenderLayer::hasAncestorWithFilterOutsets):
* rendering/RenderLayer.h:
(RenderLayer):

LayoutTests:

Added two new tests to check that we disable fast path scrolling for fixed positioned
elements that have blur applied on them or any of the parent layers.

* css3/filters/blur-filter-page-scroll-parents.html: Added.
* css3/filters/blur-filter-page-scroll-self.html: Added.
* platform/chromium/css3/filters/blur-filter-page-scroll-parents-expected.png: Added.
* platform/chromium/css3/filters/blur-filter-page-scroll-parents-expected.txt: Added.
* platform/chromium/css3/filters/blur-filter-page-scroll-self-expected.png: Added.
* platform/chromium/css3/filters/blur-filter-page-scroll-self-expected.txt: Added.
* platform/mac/css3/filters/blur-filter-page-scroll-parents-expected.png: Added.
* platform/mac/css3/filters/blur-filter-page-scroll-parents-expected.txt: Added.
* platform/mac/css3/filters/blur-filter-page-scroll-self-expected.png: Added.
* platform/mac/css3/filters/blur-filter-page-scroll-self-expected.txt: Added.
* platform/qt/Skipped: Qt needs platform results.

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

16 files changed:
LayoutTests/ChangeLog
LayoutTests/css3/filters/blur-filter-page-scroll-parents.html [new file with mode: 0644]
LayoutTests/css3/filters/blur-filter-page-scroll-self.html [new file with mode: 0644]
LayoutTests/platform/chromium/css3/filters/blur-filter-page-scroll-parents-expected.png [new file with mode: 0644]
LayoutTests/platform/chromium/css3/filters/blur-filter-page-scroll-parents-expected.txt [new file with mode: 0644]
LayoutTests/platform/chromium/css3/filters/blur-filter-page-scroll-self-expected.png [new file with mode: 0644]
LayoutTests/platform/chromium/css3/filters/blur-filter-page-scroll-self-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/css3/filters/blur-filter-page-scroll-parents-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/css3/filters/blur-filter-page-scroll-parents-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/css3/filters/blur-filter-page-scroll-self-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/css3/filters/blur-filter-page-scroll-self-expected.txt [new file with mode: 0644]
LayoutTests/platform/qt/Skipped
Source/WebCore/ChangeLog
Source/WebCore/page/FrameView.cpp
Source/WebCore/rendering/RenderLayer.cpp
Source/WebCore/rendering/RenderLayer.h

index dca2b7f..c46be8b 100644 (file)
@@ -1,3 +1,25 @@
+2012-07-09  Alexandru Chiculita  <achicu@adobe.com>
+
+        [CSS Filters] Blur filter is not repainted correctly when applied on a parent of a fixed element
+        https://bugs.webkit.org/show_bug.cgi?id=90087
+
+        Reviewed by Simon Fraser.
+
+        Added two new tests to check that we disable fast path scrolling for fixed positioned 
+        elements that have blur applied on them or any of the parent layers.
+
+        * css3/filters/blur-filter-page-scroll-parents.html: Added.
+        * css3/filters/blur-filter-page-scroll-self.html: Added.
+        * platform/chromium/css3/filters/blur-filter-page-scroll-parents-expected.png: Added.
+        * platform/chromium/css3/filters/blur-filter-page-scroll-parents-expected.txt: Added.
+        * platform/chromium/css3/filters/blur-filter-page-scroll-self-expected.png: Added.
+        * platform/chromium/css3/filters/blur-filter-page-scroll-self-expected.txt: Added.
+        * platform/mac/css3/filters/blur-filter-page-scroll-parents-expected.png: Added.
+        * platform/mac/css3/filters/blur-filter-page-scroll-parents-expected.txt: Added.
+        * platform/mac/css3/filters/blur-filter-page-scroll-self-expected.png: Added.
+        * platform/mac/css3/filters/blur-filter-page-scroll-self-expected.txt: Added.
+        * platform/qt/Skipped: Qt needs platform results.
+
 2012-07-09  Joshua Bell  <jsbell@chromium.org>
 
         IndexedDB: Empty arrays shouldn't be valid key paths
diff --git a/LayoutTests/css3/filters/blur-filter-page-scroll-parents.html b/LayoutTests/css3/filters/blur-filter-page-scroll-parents.html
new file mode 100644 (file)
index 0000000..079357f
--- /dev/null
@@ -0,0 +1,66 @@
+<!-- This test asserts that blit-scrolling is disabled when blur is applied on a layer
+    that contains an intermediate layer which has a fixed positioned object inside.
+    One fixed black bar should be visible at the top of the page. The page should be scrolled
+    100px and no red should be visible. The rest of the page should be green.
+ -->
+<!DOCTYPE html>
+<html>
+    <head>
+        <script>
+            if (window.testRunner) {
+                // Force software rendering mode.
+                window.testRunner.overridePreference("WebKitAcceleratedCompositingEnabled", "0");
+            }
+        </script>
+        <!-- Make sure the mock scrollbars are enabled after the call to overridePreference, otherwise the setting will be overwritten. -->
+        <script src="../../compositing/resources/mock_scrollbars.js"></script>
+        <style>
+            body {
+                margin: 0px;
+                border: 0px;
+                padding: 0px;
+            }
+
+            .blur {
+                -webkit-filter: blur(1px);
+            }
+
+            .layer {
+                /* Using very subtle grayscale to keep the green & red still visible. */
+                -webkit-filter: grayscale(0.1);
+            }
+
+            #fixedBox {
+                position: fixed;
+                background-color: #000000;
+                height: 100px;
+                width: 100%;
+            }
+
+            #redBox {
+                background-color: red; 
+                height: 200px;
+            }
+
+            #greenBox {
+                background-color: green;
+                height: 1000px;
+            }
+        </style>
+        <script src="../../fast/repaint/resources/repaint.js"></script>
+        <script type="text/javascript">
+            function repaintTest() {
+                window.scrollTo(0, 100);
+            }
+        </script>
+    </head>
+    <body onload="runRepaintTest()">
+        <div class="blur">
+            <div class="layer">
+                <div id="fixedBox"></div>
+                <div id="redBox"></div>
+                <div id="greenBox"></div>
+            </div>
+        </div>
+    </body>
+</html>
diff --git a/LayoutTests/css3/filters/blur-filter-page-scroll-self.html b/LayoutTests/css3/filters/blur-filter-page-scroll-self.html
new file mode 100644 (file)
index 0000000..d9349a1
--- /dev/null
@@ -0,0 +1,54 @@
+<!-- This test asserts that blit-scrolling is disabled when blur is applied on a layer 
+    that contains a fixed positioned object.
+    One fixed black bar should be visible at the top of the page. The page should be scrolled
+    100px and no red should be visible. The rest of the page should be green.
+ -->
+<!DOCTYPE html>
+<html>
+    <head>
+        <script>
+            if (window.testRunner) {
+                // Force software rendering mode.
+                window.testRunner.overridePreference("WebKitAcceleratedCompositingEnabled", "0");
+            }
+        </script>
+        <!-- Make sure the mock scrollbars are enabled after the call to overridePreference, otherwise the setting will be overwritten. -->
+        <script src="../../compositing/resources/mock_scrollbars.js"></script>
+        <style>
+            body {
+                margin: 0px;
+                border: 0px;
+                padding: 0px;
+            }
+
+            #fixedBox {
+                position: fixed;
+                background-color: #000000;
+                height: 100px;
+                width: 100%;
+                -webkit-filter: blur(1px);
+            }
+
+            #redBox {
+                background-color: red; 
+                height: 200px;
+            }
+
+            #greenBox {
+                background-color: green;
+                height: 1000px;
+            }
+        </style>
+        <script src="../../fast/repaint/resources/repaint.js"></script>
+        <script type="text/javascript">
+            function repaintTest() {
+                window.scrollTo(0, 100);
+            }
+        </script>
+    </head>
+    <body onload="runRepaintTest()">
+        <div id="fixedBox"></div>
+        <div id="redBox"></div>
+        <div id="greenBox"></div>
+    </body>
+</html>
diff --git a/LayoutTests/platform/chromium/css3/filters/blur-filter-page-scroll-parents-expected.png b/LayoutTests/platform/chromium/css3/filters/blur-filter-page-scroll-parents-expected.png
new file mode 100644 (file)
index 0000000..83a86c1
Binary files /dev/null and b/LayoutTests/platform/chromium/css3/filters/blur-filter-page-scroll-parents-expected.png differ
diff --git a/LayoutTests/platform/chromium/css3/filters/blur-filter-page-scroll-parents-expected.txt b/LayoutTests/platform/chromium/css3/filters/blur-filter-page-scroll-parents-expected.txt
new file mode 100644 (file)
index 0000000..1f11884
--- /dev/null
@@ -0,0 +1,15 @@
+CONSOLE MESSAGE: Invalid name for preference: WebKitAcceleratedCompositingEnabled
+layer at (0,0) size 785x1200
+  RenderView at (0,0) size 785x600
+layer at (0,0) size 785x1200
+  RenderBlock {HTML} at (0,0) size 785x1200
+    RenderBody {BODY} at (0,0) size 785x1200
+layer at (0,0) size 785x1200
+  RenderBlock {DIV} at (0,0) size 785x1200
+layer at (0,0) size 785x1200
+  RenderBlock {DIV} at (0,0) size 785x1200
+    RenderBlock {DIV} at (0,0) size 785x200 [bgcolor=#FF0000]
+    RenderBlock {DIV} at (0,200) size 785x1000 [bgcolor=#008000]
+layer at (0,100) size 785x100
+  RenderBlock (positioned) {DIV} at (0,0) size 785x100 [bgcolor=#000000]
+scrolled to 0,100
diff --git a/LayoutTests/platform/chromium/css3/filters/blur-filter-page-scroll-self-expected.png b/LayoutTests/platform/chromium/css3/filters/blur-filter-page-scroll-self-expected.png
new file mode 100644 (file)
index 0000000..2f0c709
Binary files /dev/null and b/LayoutTests/platform/chromium/css3/filters/blur-filter-page-scroll-self-expected.png differ
diff --git a/LayoutTests/platform/chromium/css3/filters/blur-filter-page-scroll-self-expected.txt b/LayoutTests/platform/chromium/css3/filters/blur-filter-page-scroll-self-expected.txt
new file mode 100644 (file)
index 0000000..61b4ce8
--- /dev/null
@@ -0,0 +1,11 @@
+CONSOLE MESSAGE: Invalid name for preference: WebKitAcceleratedCompositingEnabled
+layer at (0,0) size 785x1200
+  RenderView at (0,0) size 785x600
+layer at (0,0) size 785x1200
+  RenderBlock {HTML} at (0,0) size 785x1200
+    RenderBody {BODY} at (0,0) size 785x1200
+      RenderBlock {DIV} at (0,0) size 785x200 [bgcolor=#FF0000]
+      RenderBlock {DIV} at (0,200) size 785x1000 [bgcolor=#008000]
+layer at (0,100) size 785x100
+  RenderBlock (positioned) {DIV} at (0,0) size 785x100 [bgcolor=#000000]
+scrolled to 0,100
diff --git a/LayoutTests/platform/mac/css3/filters/blur-filter-page-scroll-parents-expected.png b/LayoutTests/platform/mac/css3/filters/blur-filter-page-scroll-parents-expected.png
new file mode 100644 (file)
index 0000000..6b26f04
Binary files /dev/null and b/LayoutTests/platform/mac/css3/filters/blur-filter-page-scroll-parents-expected.png differ
diff --git a/LayoutTests/platform/mac/css3/filters/blur-filter-page-scroll-parents-expected.txt b/LayoutTests/platform/mac/css3/filters/blur-filter-page-scroll-parents-expected.txt
new file mode 100644 (file)
index 0000000..62d761a
--- /dev/null
@@ -0,0 +1,14 @@
+layer at (0,0) size 785x1200
+  RenderView at (0,0) size 785x600
+layer at (0,0) size 785x1200
+  RenderBlock {HTML} at (0,0) size 785x1200
+    RenderBody {BODY} at (0,0) size 785x1200
+layer at (0,0) size 785x1200
+  RenderBlock {DIV} at (0,0) size 785x1200
+layer at (0,0) size 785x1200
+  RenderBlock {DIV} at (0,0) size 785x1200
+    RenderBlock {DIV} at (0,0) size 785x200 [bgcolor=#FF0000]
+    RenderBlock {DIV} at (0,200) size 785x1000 [bgcolor=#008000]
+layer at (0,100) size 785x100
+  RenderBlock (positioned) {DIV} at (0,0) size 785x100 [bgcolor=#000000]
+scrolled to 0,100
diff --git a/LayoutTests/platform/mac/css3/filters/blur-filter-page-scroll-self-expected.png b/LayoutTests/platform/mac/css3/filters/blur-filter-page-scroll-self-expected.png
new file mode 100644 (file)
index 0000000..b758ede
Binary files /dev/null and b/LayoutTests/platform/mac/css3/filters/blur-filter-page-scroll-self-expected.png differ
diff --git a/LayoutTests/platform/mac/css3/filters/blur-filter-page-scroll-self-expected.txt b/LayoutTests/platform/mac/css3/filters/blur-filter-page-scroll-self-expected.txt
new file mode 100644 (file)
index 0000000..56ac1a9
--- /dev/null
@@ -0,0 +1,10 @@
+layer at (0,0) size 785x1200
+  RenderView at (0,0) size 785x600
+layer at (0,0) size 785x1200
+  RenderBlock {HTML} at (0,0) size 785x1200
+    RenderBody {BODY} at (0,0) size 785x1200
+      RenderBlock {DIV} at (0,0) size 785x200 [bgcolor=#FF0000]
+      RenderBlock {DIV} at (0,200) size 785x1000 [bgcolor=#008000]
+layer at (0,100) size 785x100
+  RenderBlock (positioned) {DIV} at (0,0) size 785x100 [bgcolor=#000000]
+scrolled to 0,100
index b4c05ec..c5d8cc2 100644 (file)
@@ -2161,6 +2161,9 @@ fast/borders/scaled-border-image.html
 css3/filters/composited-during-animation-layertree.html
 css3/filters/composited-during-transition-layertree.html
 css3/filters/composited-during-animation.html
+css3/filters/blur-filter-page-scroll.html
+css3/filters/blur-filter-page-scroll-self.html
+css3/filters/blur-filter-page-scroll-parents.html
 svg/foreignObject/fO-display-none-with-relative-pos-content.svg
 svg/foreignObject/fO-display-none.svg
 fast/speech/input-appearance-speechbutton.html
index ae089c1..1d2357f 100644 (file)
@@ -1,3 +1,26 @@
+2012-07-09  Alexandru Chiculita  <achicu@adobe.com>
+
+        [CSS Filters] Blur filter is not repainted correctly when applied on a parent of a fixed element
+        https://bugs.webkit.org/show_bug.cgi?id=90087
+
+        Reviewed by Simon Fraser.
+
+        Added a new method, RenderLayer::hasAncestorWithFilterOutsets, to check that there's no filter with outsets (ie. blur) 
+        applied on top level fixed positioned elements, nor any of its parent layers. In the event of a blur filter we need to
+        disable the fast scrolling optimization, otherwise the outsets of the filter will be carried around the page and 
+        repainting will not work correctly.
+
+        Tests: css3/filters/blur-filter-page-scroll-parents.html
+               css3/filters/blur-filter-page-scroll-self.html
+
+        * page/FrameView.cpp:
+        (WebCore::FrameView::scrollContentsFastPath):
+        * rendering/RenderLayer.cpp:
+        (WebCore):
+        (WebCore::RenderLayer::hasAncestorWithFilterOutsets):
+        * rendering/RenderLayer.h:
+        (RenderLayer):
+
 2012-07-09  Joshua Bell  <jsbell@chromium.org>
 
         IndexedDB: Empty arrays shouldn't be valid key paths
index e64ef90..ddc3c24 100644 (file)
@@ -1477,13 +1477,10 @@ bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect
         RenderLayer* layer = toRenderBoxModelObject(renderer)->layer();
         
 #if ENABLE(CSS_FILTERS)
-        if (layer->parent()) {
-            RenderBoxModelObject* renderer = layer->parent()->renderer();
-            if (renderer->style()->hasFilterOutsets()) {
-                // If the fixed layer has a blur/drop-shadow filter applied on its parent, we cannot 
-                // scroll using the fast path, otherwise the outsets of the filter will be moved around the page.
-                return false;
-            }
+        if (layer->hasAncestorWithFilterOutsets()) {
+            // If the fixed layer has a blur/drop-shadow filter applied on at least one of its parents, we cannot 
+            // scroll using the fast path, otherwise the outsets of the filter will be moved around the page.
+            return false;
         }
 #endif
         IntRect updateRect = pixelSnappedIntRect(layer->repaintRectIncludingNonCompositingDescendants());
index a9a6ee4..12794cb 100644 (file)
@@ -1088,6 +1088,16 @@ void RenderLayer::setFilterBackendNeedsRepaintingInRect(const LayoutRect& rect,
     
     ASSERT_NOT_REACHED();
 }
+
+bool RenderLayer::hasAncestorWithFilterOutsets() const
+{
+    for (const RenderLayer* curr = this; curr; curr = curr->parent()) {
+        RenderBoxModelObject* renderer = curr->renderer();
+        if (renderer->style()->hasFilterOutsets())
+            return true;
+    }
+    return false;
+}
 #endif
     
 RenderLayer* RenderLayer::clippingRootForPainting() const
index 1869659..1c32a4f 100644 (file)
@@ -471,6 +471,7 @@ public:
     RenderLayer* enclosingFilterLayer(bool includeSelf = true) const;
     RenderLayer* enclosingFilterRepaintLayer() const;
     void setFilterBackendNeedsRepaintingInRect(const LayoutRect&, bool immediate);
+    bool hasAncestorWithFilterOutsets() const;
 #endif
 
     bool canUseConvertToLayerCoords() const