REGRESSION(112745) [CSS Filters] Memory use explosion for offscreen filtered elements
authorachicu@adobe.com <achicu@adobe.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 12 Apr 2012 23:55:25 +0000 (23:55 +0000)
committerachicu@adobe.com <achicu@adobe.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 12 Apr 2012 23:55:25 +0000 (23:55 +0000)
https://bugs.webkit.org/show_bug.cgi?id=83815

Reviewed by Simon Fraser.

Source/WebCore:

The filtered area used to be the dirty rect intersected by the bounding box of the
layer. During a previous change that behavior was lost, so adding it back now.

Also, removing the memory buffers used to compute filters after the filter is computed.
They are deleted next time the filter is applied anyway, so there's no need to keep the
memory for them.

Test: css3/filters/offscreen-filters-memory-usage.html

* rendering/FilterEffectRenderer.cpp:
(WebCore::FilterEffectRenderer::prepare):
(WebCore):
(WebCore::FilterEffectRenderer::clearIntermediateResults):
(WebCore::FilterEffectRendererHelper::prepareFilterEffect):
(WebCore::FilterEffectRendererHelper::applyFilterEffect):
* rendering/FilterEffectRenderer.h:
(FilterEffectRenderer):

LayoutTests:

Adding a test that creates a lot of layers outside the viewport. The memory should not grow
and the browser should not crash.

* css3/filters/offscreen-filters-memory-usage-expected.txt: Added.
* css3/filters/offscreen-filters-memory-usage.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/css3/filters/offscreen-filters-memory-usage-expected.txt [new file with mode: 0644]
LayoutTests/css3/filters/offscreen-filters-memory-usage.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/rendering/FilterEffectRenderer.cpp
Source/WebCore/rendering/FilterEffectRenderer.h

index d1895df..0bba039 100644 (file)
@@ -1,3 +1,16 @@
+2012-04-12  Alexandru Chiculita  <achicu@adobe.com>
+
+        REGRESSION(112745) [CSS Filters] Memory use explosion for offscreen filtered elements
+        https://bugs.webkit.org/show_bug.cgi?id=83815
+
+        Reviewed by Simon Fraser.
+
+        Adding a test that creates a lot of layers outside the viewport. The memory should not grow
+        and the browser should not crash.
+
+        * css3/filters/offscreen-filters-memory-usage-expected.txt: Added.
+        * css3/filters/offscreen-filters-memory-usage.html: Added.
+
 2012-04-12  Vincent Scheib  <scheib@chromium.org>
 
         Image failures due to text rendering change.
diff --git a/LayoutTests/css3/filters/offscreen-filters-memory-usage-expected.txt b/LayoutTests/css3/filters/offscreen-filters-memory-usage-expected.txt
new file mode 100644 (file)
index 0000000..456b4cd
--- /dev/null
@@ -0,0 +1,3 @@
+This test passes if memory usage is not so hight that it crashes the browser. It should be less than 100MB.
+
+
diff --git a/LayoutTests/css3/filters/offscreen-filters-memory-usage.html b/LayoutTests/css3/filters/offscreen-filters-memory-usage.html
new file mode 100644 (file)
index 0000000..f53b209
--- /dev/null
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <style>
+            .offscreen_filter_area {
+                -webkit-filter: grayscale(1);
+                position: absolute;
+                left: -3000px;
+                width: 2048px;
+                height: 2048px;
+                background-color: blue;
+            }
+        </style>
+    </head>
+    <body>
+        <p>This test passes if memory usage is not so hight that it crashes the browser. It should be less than 100MB.</p>
+        <script>
+            function createLayer() {
+                var el = document.createElement("div");
+                el.className = "offscreen_filter_area";
+                return el;
+            }
+
+            if (window.layoutTestController)
+                window.layoutTestController.dumpAsText(false);
+            for (var i = 0; i < 2000; ++i)
+                document.body.appendChild(createLayer());
+        </script>
+    </body>
+</html>
index a06e841..40a2024 100644 (file)
@@ -1,3 +1,28 @@
+2012-04-12  Alexandru Chiculita  <achicu@adobe.com>
+
+        REGRESSION(112745) [CSS Filters] Memory use explosion for offscreen filtered elements
+        https://bugs.webkit.org/show_bug.cgi?id=83815
+
+        Reviewed by Simon Fraser.
+
+        The filtered area used to be the dirty rect intersected by the bounding box of the
+        layer. During a previous change that behavior was lost, so adding it back now.
+
+        Also, removing the memory buffers used to compute filters after the filter is computed.
+        They are deleted next time the filter is applied anyway, so there's no need to keep the
+        memory for them.
+
+        Test: css3/filters/offscreen-filters-memory-usage.html
+
+        * rendering/FilterEffectRenderer.cpp:
+        (WebCore::FilterEffectRenderer::prepare):
+        (WebCore):
+        (WebCore::FilterEffectRenderer::clearIntermediateResults):
+        (WebCore::FilterEffectRendererHelper::prepareFilterEffect):
+        (WebCore::FilterEffectRendererHelper::applyFilterEffect):
+        * rendering/FilterEffectRenderer.h:
+        (FilterEffectRenderer):
+
 2012-04-12  Brent Fulgham  <bfulgham@webkit.org>
 
         [WinCairo] Build fix after addition of openTypeTable.
index 87420ce..9c16196 100644 (file)
@@ -332,6 +332,11 @@ void FilterEffectRenderer::prepare()
         setSourceImage(ImageBuffer::create(logicalSize, 1, ColorSpaceDeviceRGB, renderingMode()));
         m_graphicsBufferAttached = true;
     }
+    clearIntermediateResults();
+}
+
+void FilterEffectRenderer::clearIntermediateResults()
+{
     m_sourceGraphic->clearResult();
     for (size_t i = 0; i < m_effects.size(); ++i)
         m_effects[i]->clearResult();
@@ -347,6 +352,7 @@ const LayoutRect& FilterEffectRendererHelper::prepareFilterEffect(RenderLayer* r
     ASSERT(m_haveFilterEffect && renderLayer->filter());
     m_renderLayer = renderLayer;
     m_dirtyRect = dirtyRect;
+    m_dirtyRect.intersect(filterBoxRect);
 
     FilterEffectRenderer* filter = renderLayer->filter();
 
@@ -354,7 +360,7 @@ const LayoutRect& FilterEffectRendererHelper::prepareFilterEffect(RenderLayer* r
     // Such filters include blur, drop-shadow and shaders. For that reason,
     // we keep the whole image buffer in memory and repaint only dirty areas.
     bool hasFilterThatMovesPixels = filter->hasFilterThatMovesPixels();
-    LayoutRect filterSourceRect = hasFilterThatMovesPixels ? filterBoxRect : dirtyRect;
+    LayoutRect filterSourceRect = hasFilterThatMovesPixels ? filterBoxRect : m_dirtyRect;
     m_paintOffset = filterSourceRect.location();
     filterSourceRect.setLocation(LayoutPoint());
 
@@ -405,6 +411,8 @@ GraphicsContext* FilterEffectRendererHelper::applyFilterEffect()
     
     m_savedGraphicsContext->drawImageBuffer(filter->output(), m_renderLayer->renderer()->style()->colorSpace(), pixelSnappedIntRect(destRect), CompositeSourceOver);
     
+    filter->clearIntermediateResults();
+    
     return m_savedGraphicsContext;
 }
 
index 600e042..df23a40 100644 (file)
@@ -108,6 +108,7 @@ public:
 
     void build(Document*, const FilterOperations&);
     bool updateBackingStore(const FloatRect& filterRect);
+    void clearIntermediateResults();
     void prepare();
     void apply();