[SVG] Cached filter results are not invalidated on repaint rect change
authorfmalita@chromium.org <fmalita@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 15 Feb 2013 03:58:18 +0000 (03:58 +0000)
committerfmalita@chromium.org <fmalita@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 15 Feb 2013 03:58:18 +0000 (03:58 +0000)
https://bugs.webkit.org/show_bug.cgi?id=106221

Reviewed by Dean Jackson.

Source/WebCore:

Since the cached filter results are not invalidated for different repaint rects, we need
to render the content of the whole filter region upfront (otherwise elements not visible
during the initial paint due to scrolling/window size/etc. are never redrawn).

Tests: svg/filters/filter-hidden-content-expected.svg
       svg/filters/filter-hidden-content.svg

* rendering/svg/RenderSVGResourceFilter.cpp:
(WebCore::RenderSVGResourceFilter::applyResource):
(WebCore::RenderSVGResourceFilter::drawingRegion):
(WebCore):
* rendering/svg/RenderSVGResourceFilter.h:
(FilterData):
(RenderSVGResourceFilter):
Track the filter drawing region in FilterData.

* rendering/svg/SVGRenderingContext.cpp:
(WebCore::SVGRenderingContext::~SVGRenderingContext):
(WebCore::SVGRenderingContext::prepareToRenderSVGContent):
* rendering/svg/SVGRenderingContext.h:
Update paintInfo.rect to cover the whole drawing region while rendering filter content, and
restore it when done.

LayoutTests:

* svg/filters/filter-hidden-content-expected.svg: Added.
* svg/filters/filter-hidden-content.svg: Added.

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

14 files changed:
LayoutTests/ChangeLog
LayoutTests/platform/chromium-linux/svg/filters/filter-hidden-content-expected.png [new file with mode: 0644]
LayoutTests/platform/chromium-linux/svg/filters/filter-hidden-content-expected.txt [new file with mode: 0644]
LayoutTests/platform/chromium/TestExpectations
LayoutTests/platform/efl/TestExpectations
LayoutTests/platform/gtk/TestExpectations
LayoutTests/platform/mac/TestExpectations
LayoutTests/platform/qt/TestExpectations
LayoutTests/svg/filters/filter-hidden-content.svg [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp
Source/WebCore/rendering/svg/RenderSVGResourceFilter.h
Source/WebCore/rendering/svg/SVGRenderingContext.cpp
Source/WebCore/rendering/svg/SVGRenderingContext.h

index ce62ca6..6173cd9 100644 (file)
@@ -1,3 +1,13 @@
+2013-02-14  Florin Malita  <fmalita@chromium.org>
+
+        [SVG] Cached filter results are not invalidated on repaint rect change
+        https://bugs.webkit.org/show_bug.cgi?id=106221
+
+        Reviewed by Dean Jackson.
+
+        * svg/filters/filter-hidden-content-expected.svg: Added.
+        * svg/filters/filter-hidden-content.svg: Added.
+
 2013-02-14  Hajime Morrita  <morrita@google.com>
 
         Unreviewed rebaselining following r142940.
diff --git a/LayoutTests/platform/chromium-linux/svg/filters/filter-hidden-content-expected.png b/LayoutTests/platform/chromium-linux/svg/filters/filter-hidden-content-expected.png
new file mode 100644 (file)
index 0000000..421beb0
Binary files /dev/null and b/LayoutTests/platform/chromium-linux/svg/filters/filter-hidden-content-expected.png differ
diff --git a/LayoutTests/platform/chromium-linux/svg/filters/filter-hidden-content-expected.txt b/LayoutTests/platform/chromium-linux/svg/filters/filter-hidden-content-expected.txt
new file mode 100644 (file)
index 0000000..e8bf2b5
--- /dev/null
@@ -0,0 +1,16 @@
+layer at (0,0) size 794x594
+  RenderView at (0,0) size 794x594
+layer at (0,0) size 400x400
+  RenderSVGRoot {svg} at (0,0) size 400x205
+    RenderSVGHiddenContainer {defs} at (0,0) size 0x0
+      RenderSVGResourceFilter {filter} [id="f1"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+        [feGaussianBlur stdDeviation="0.00, 0.00"]
+          [SourceGraphic]
+    RenderSVGContainer {g} at (0,0) size 275x56
+      [filter="f1"] RenderSVGResourceFilter {filter} at (-25,-5) size 300x60
+      RenderSVGRect {rect} at (0,0) size 50x50 [fill={[type=SOLID] [color=#008000]}] [x=0.00] [y=0.00] [width=50.00] [height=50.00]
+      RenderSVGRect {rect} at (200,0) size 50x50 [fill={[type=SOLID] [color=#008000]}] [x=200.00] [y=0.00] [width=50.00] [height=50.00]
+    RenderSVGContainer {g} at (125,145) size 275x60 [transform={m=((1.00,0.00)(0.00,1.00)) t=(150.00,150.00)}]
+      [filter="f1"] RenderSVGResourceFilter {filter} at (-25,-5) size 300x60
+      RenderSVGRect {rect} at (150,150) size 50x50 [fill={[type=SOLID] [color=#008000]}] [x=0.00] [y=0.00] [width=50.00] [height=50.00]
+      RenderSVGRect {rect} at (350,150) size 50x50 [fill={[type=SOLID] [color=#008000]}] [x=200.00] [y=0.00] [width=50.00] [height=50.00]
index 9be673a..e58b355 100644 (file)
@@ -3944,6 +3944,9 @@ webkit.org/b/98192 fast/js/post-message-numeric-property.html [ Failure Pass ]
 
 webkit.org/b/98275 media/event-queue-crash.html [ Skip ]
 
+# Needs platform results after webkit.org/b/106221
+webkit.org/b/106221 svg/filters/filter-hidden-content.svg [ Failure Pass ]
+
 # Needs rebaselining on after webkit.org/b/107339
 webkit.org/b/107339 [ Mac Android Win ] platform/chromium/fast/events/touch/compositor-touch-hit-rects.html [ Pass Failure ]
 
index c70b8db..e778ed6 100644 (file)
@@ -1860,6 +1860,9 @@ webkit.org/b/107476 fast/block/margin-collapse/empty-clear-blocks.html [ Failure
 # Needs a rebaseline after WK108429 lands.
 webkit.org/b/108429 svg/custom/text-ctm.svg [ Pass Failure ]
 
+# New test, needs platform results
+webkit.org/b/106221 svg/filters/filter-hidden-content.svg [ Failure Pass ]
+
 # New ruby selection test (in r140613) fails to render correctly, not generating an expected result
 webkit.org/b/108315 fast/ruby/select-ruby.html [ Missing ]
 
index dbf25ab..14f752d 100644 (file)
@@ -88,6 +88,9 @@ webkit.org/b/109775 media/video-controls-rendering.html [ Failure ]
 webkit.org/b/109775 media/video-display-toggle.html [ Failure ]
 webkit.org/b/109775 media/video-playing-and-pause.html [ Failure ]
 
+# New test, needs platform results
+webkit.org/b/106221 svg/filters/filter-hidden-content.svg [ Failure Pass ]
+
 #////////////////////////////////////////////////////////////////////////////////////////
 # Expected failures
 #////////////////////////////////////////////////////////////////////////////////////////
index ca845eb..09ea12a 100644 (file)
@@ -804,6 +804,9 @@ svg/filters/color-space-conversion.svg
 svg/filters/container-with-filters.svg
 svg/filters/feSpecularLight-premultiplied.svg
 
+# New test, needs platform results
+webkit.org/b/106221 svg/filters/filter-hidden-content.svg [ Failure Pass ]
+
 # https://bugs.webkit.org/show_bug.cgi?id=89680
 fast/canvas/canvas-imageSmoothingEnabled-repaint.html
 
index 32f09c7..3bc9327 100644 (file)
@@ -1412,6 +1412,8 @@ webkit.org/b/105437 svg/filters/feImage-target-style-change.svg [ ImageOnlyFailu
 
 webkit.org/b/106957 svg/dom/SVGViewSpec-invalid-ref-crash.html [ Failure ]
 
+# New test, needs platform results
+webkit.org/b/106221 svg/filters/filter-hidden-content.svg [ Failure Pass ]
 
 # ============================================================================= #
 # Failing CSS Tests
diff --git a/LayoutTests/svg/filters/filter-hidden-content.svg b/LayoutTests/svg/filters/filter-hidden-content.svg
new file mode 100644 (file)
index 0000000..5f03dfb
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0" standalone="no"?>
+<svg width="400" height="400" version="1.1" xmlns="http://www.w3.org/2000/svg">
+  <!-- Test for https://bugs.webkit.org/show_bug.cgi?id=106221 -->
+  <defs>
+    <filter id="f1">
+      <feGaussianBlur stdDeviation="0"/>
+    </filter>
+  </defs>
+
+  <g filter="url(#f1)">
+    <rect width="50" height="50" fill="green"/>
+    <rect x="200" width="50" height="50" fill="green"/>
+  </g>
+
+  <g filter="url(#f1)" transform="translate(150, 150)">
+    <rect width="50" height="50" fill="green"/>
+    <rect x="200" width="50" height="50" fill="green"/>
+  </g>
+
+  <script>
+    if (window.testRunner)
+      testRunner.waitUntilDone();
+
+    window.resizeTo(180, 600);
+    window.setTimeout(function() {
+      window.resizeTo(800, 600);
+
+      if (window.testRunner)
+        testRunner.notifyDone();
+    }, 0);
+  </script>
+</svg>
index 55fcad7..0806dbd 100644 (file)
@@ -1,3 +1,33 @@
+2013-02-14  Florin Malita  <fmalita@chromium.org>
+
+        [SVG] Cached filter results are not invalidated on repaint rect change
+        https://bugs.webkit.org/show_bug.cgi?id=106221
+
+        Reviewed by Dean Jackson.
+
+        Since the cached filter results are not invalidated for different repaint rects, we need
+        to render the content of the whole filter region upfront (otherwise elements not visible
+        during the initial paint due to scrolling/window size/etc. are never redrawn).
+
+        Tests: svg/filters/filter-hidden-content-expected.svg
+               svg/filters/filter-hidden-content.svg
+
+        * rendering/svg/RenderSVGResourceFilter.cpp:
+        (WebCore::RenderSVGResourceFilter::applyResource):
+        (WebCore::RenderSVGResourceFilter::drawingRegion):
+        (WebCore):
+        * rendering/svg/RenderSVGResourceFilter.h:
+        (FilterData):
+        (RenderSVGResourceFilter):
+        Track the filter drawing region in FilterData.
+
+        * rendering/svg/SVGRenderingContext.cpp:
+        (WebCore::SVGRenderingContext::~SVGRenderingContext):
+        (WebCore::SVGRenderingContext::prepareToRenderSVGContent):
+        * rendering/svg/SVGRenderingContext.h:
+        Update paintInfo.rect to cover the whole drawing region while rendering filter content, and
+        restore it when done.
+
 2013-02-14  Jinwoo Song  <jinwoo7.song@samsung.com>
 
         [EFL] Correct the mismatched cursor map
index 9899096..6933d61 100644 (file)
@@ -175,9 +175,9 @@ bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*,
 
     // Determine absolute boundaries of the filter and the drawing region.
     FloatRect absoluteFilterBoundaries = filterData->shearFreeAbsoluteTransform.mapRect(filterData->boundaries);
-    FloatRect drawingRegion = object->strokeBoundingBox();
-    drawingRegion.intersect(filterData->boundaries);
-    FloatRect absoluteDrawingRegion = filterData->shearFreeAbsoluteTransform.mapRect(drawingRegion);
+    filterData->drawingRegion = object->strokeBoundingBox();
+    filterData->drawingRegion.intersect(filterData->boundaries);
+    FloatRect absoluteDrawingRegion = filterData->shearFreeAbsoluteTransform.mapRect(filterData->drawingRegion);
 
     // Create the SVGFilter object.
     bool primitiveBoundingBoxMode = filterElement->primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
@@ -222,7 +222,7 @@ bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*,
 
     // If the drawingRegion is empty, we have something like <g filter=".."/>.
     // Even if the target objectBoundingBox() is empty, we still have to draw the last effect result image in postApplyResource.
-    if (drawingRegion.isEmpty()) {
+    if (filterData->drawingRegion.isEmpty()) {
         ASSERT(!m_filter.contains(object));
         filterData->savedContext = context;
         m_filter.set(object, filterData.leakPtr());
@@ -236,7 +236,7 @@ bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*,
 
     OwnPtr<ImageBuffer> sourceGraphic;
     RenderingMode renderingMode = object->document()->page()->settings()->acceleratedFiltersEnabled() ? Accelerated : Unaccelerated;
-    if (!SVGRenderingContext::createImageBuffer(drawingRegion, effectiveTransform, sourceGraphic, ColorSpaceLinearRGB, renderingMode)) {
+    if (!SVGRenderingContext::createImageBuffer(filterData->drawingRegion, effectiveTransform, sourceGraphic, ColorSpaceLinearRGB, renderingMode)) {
         ASSERT(!m_filter.contains(object));
         filterData->savedContext = context;
         m_filter.set(object, filterData.leakPtr());
@@ -364,5 +364,11 @@ void RenderSVGResourceFilter::primitiveAttributeChanged(RenderObject* object, co
     markAllClientLayersForInvalidation();
 }
 
+FloatRect RenderSVGResourceFilter::drawingRegion(RenderObject* object) const
+{
+    FilterData* filterData = m_filter.get(object);
+    return filterData ? filterData->drawingRegion : FloatRect();
+}
+
 }
 #endif
index db422c1..41dc73c 100644 (file)
@@ -56,6 +56,7 @@ public:
     GraphicsContext* savedContext;
     AffineTransform shearFreeAbsoluteTransform;
     FloatRect boundaries;
+    FloatRect drawingRegion;
     FloatSize scale;
     FilterDataState state;
 };
@@ -88,6 +89,7 @@ public:
     virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
     static RenderSVGResourceType s_resourceType;
 
+    FloatRect drawingRegion(RenderObject*) const;
 private:
     bool fitsInMaximumImageSize(const FloatSize&, FloatSize&);
 
index 257e829..e275932 100644 (file)
@@ -61,6 +61,7 @@ SVGRenderingContext::~SVGRenderingContext()
         ASSERT(m_filter);
         m_filter->postApplyResource(static_cast<RenderSVGShape*>(m_object), m_paintInfo->context, ApplyToDefaultMode, 0, 0);
         m_paintInfo->context = m_savedContext;
+        m_paintInfo->rect = m_savedPaintRect;
     }
 #endif
 
@@ -157,11 +158,18 @@ void SVGRenderingContext::prepareToRenderSVGContent(RenderObject* object, PaintI
         m_filter = resources->filter();
         if (m_filter) {
             m_savedContext = m_paintInfo->context;
+            m_savedPaintRect = m_paintInfo->rect;
             // Return with false here may mean that we don't need to draw the content
             // (because it was either drawn before or empty) but we still need to apply the filter.
             m_renderingFlags |= EndFilterLayer;
             if (!m_filter->applyResource(m_object, style, m_paintInfo->context, ApplyToDefaultMode))
                 return;
+
+            // Since we're caching the resulting bitmap and do not invalidate it on repaint rect
+            // changes, we need to paint the whole filter region. Otherwise, elements not visible
+            // at the time of the initial paint (due to scrolling, window size, etc.) will never
+            // be drawn.
+            m_paintInfo->rect = IntRect(m_filter->drawingRegion(m_object));
         }
     }
 #endif
index c881689..4eb9c25 100644 (file)
@@ -111,6 +111,7 @@ private:
     RenderObject* m_object;
     PaintInfo* m_paintInfo;
     GraphicsContext* m_savedContext;
+    IntRect m_savedPaintRect;
 #if ENABLE(FILTERS)
     RenderSVGResourceFilter* m_filter;
 #endif