[CSS Filters] Move m_filter and related fields from RenderLayer to a different struct...
authorachicu@adobe.com <achicu@adobe.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 24 Apr 2012 17:17:45 +0000 (17:17 +0000)
committerachicu@adobe.com <achicu@adobe.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 24 Apr 2012 17:17:45 +0000 (17:17 +0000)
https://bugs.webkit.org/show_bug.cgi?id=84460

Reviewed by Dean Jackson.

The new RenderLayerFilterInfo is meant to be allocated only when needed by filters. The link to the RenderLayerFilterInfo
is maintained using a HashMap and a single boolean in the RenderLayer class.

No new tests, just extracted a couple of fields inside the RenderLayer to a separate class.

* GNUmakefile.list.am:
* Target.pri:
* WebCore.gypi:
* WebCore.vcproj/WebCore.vcproj:
* WebCore.xcodeproj/project.pbxproj:
* rendering/FilterEffectRenderer.cpp:
(WebCore::FilterEffectRendererHelper::prepareFilterEffect):
(WebCore::FilterEffectRendererHelper::beginFilterEffect):
(WebCore::FilterEffectRendererHelper::applyFilterEffect):
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::RenderLayer):
(WebCore::RenderLayer::~RenderLayer):
(WebCore::RenderLayer::paintsWithFilters):
(WebCore::RenderLayer::requiresFullLayerImageForFilters):
(WebCore::RenderLayer::setFilterBackendNeedsRepaintingInRect):
(WebCore::RenderLayer::paintLayerContents):
(WebCore::RenderLayer::updateOrRemoveFilterEffect):
* rendering/RenderLayer.h:
(WebCore::RenderLayer::filterRenderer):
(RenderLayer):
(WebCore::RenderLayer::filterInfo):
(WebCore::RenderLayer::ensureFilterInfo):
(WebCore::RenderLayer::removeFilterInfoIfNeeded):
(WebCore::RenderLayer::hasFilterInfo):
(WebCore::RenderLayer::setHasFilterInfo):
* rendering/RenderLayerFilterInfo.cpp: Added.
(WebCore):
(WebCore::RenderLayerFilterInfo::filterInfoForRenderLayer):
(WebCore::RenderLayerFilterInfo::createFilterInfoForRenderLayerIfNeeded):
(WebCore::RenderLayerFilterInfo::removeFilterInfoForRenderLayer):
(WebCore::RenderLayerFilterInfo::RenderLayerFilterInfo):
(WebCore::RenderLayerFilterInfo::~RenderLayerFilterInfo):
(WebCore::RenderLayerFilterInfo::setRenderer):
* rendering/RenderLayerFilterInfo.h: Added.
(WebCore):
(RenderLayerFilterInfo):
(WebCore::RenderLayerFilterInfo::dirtySourceRect):
(WebCore::RenderLayerFilterInfo::addDirtySourceRect):
(WebCore::RenderLayerFilterInfo::resetDirtySourceRect):
(WebCore::RenderLayerFilterInfo::renderer):

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

Source/WebCore/ChangeLog
Source/WebCore/GNUmakefile.list.am
Source/WebCore/Target.pri
Source/WebCore/WebCore.gypi
Source/WebCore/WebCore.vcproj/WebCore.vcproj
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/rendering/FilterEffectRenderer.cpp
Source/WebCore/rendering/RenderLayer.cpp
Source/WebCore/rendering/RenderLayer.h
Source/WebCore/rendering/RenderLayerFilterInfo.cpp [new file with mode: 0644]
Source/WebCore/rendering/RenderLayerFilterInfo.h [new file with mode: 0644]

index da9352c..a1a4c56 100644 (file)
@@ -1,3 +1,56 @@
+2012-04-24  Alexandru Chiculita  <achicu@adobe.com>
+
+        [CSS Filters] Move m_filter and related fields from RenderLayer to a different structure and only allocate it when needed
+        https://bugs.webkit.org/show_bug.cgi?id=84460
+
+        Reviewed by Dean Jackson.
+
+        The new RenderLayerFilterInfo is meant to be allocated only when needed by filters. The link to the RenderLayerFilterInfo
+        is maintained using a HashMap and a single boolean in the RenderLayer class.
+
+        No new tests, just extracted a couple of fields inside the RenderLayer to a separate class.
+
+        * GNUmakefile.list.am:
+        * Target.pri:
+        * WebCore.gypi:
+        * WebCore.vcproj/WebCore.vcproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        * rendering/FilterEffectRenderer.cpp:
+        (WebCore::FilterEffectRendererHelper::prepareFilterEffect):
+        (WebCore::FilterEffectRendererHelper::beginFilterEffect):
+        (WebCore::FilterEffectRendererHelper::applyFilterEffect):
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::RenderLayer):
+        (WebCore::RenderLayer::~RenderLayer):
+        (WebCore::RenderLayer::paintsWithFilters):
+        (WebCore::RenderLayer::requiresFullLayerImageForFilters):
+        (WebCore::RenderLayer::setFilterBackendNeedsRepaintingInRect):
+        (WebCore::RenderLayer::paintLayerContents):
+        (WebCore::RenderLayer::updateOrRemoveFilterEffect):
+        * rendering/RenderLayer.h:
+        (WebCore::RenderLayer::filterRenderer):
+        (RenderLayer):
+        (WebCore::RenderLayer::filterInfo):
+        (WebCore::RenderLayer::ensureFilterInfo):
+        (WebCore::RenderLayer::removeFilterInfoIfNeeded):
+        (WebCore::RenderLayer::hasFilterInfo):
+        (WebCore::RenderLayer::setHasFilterInfo):
+        * rendering/RenderLayerFilterInfo.cpp: Added.
+        (WebCore):
+        (WebCore::RenderLayerFilterInfo::filterInfoForRenderLayer):
+        (WebCore::RenderLayerFilterInfo::createFilterInfoForRenderLayerIfNeeded):
+        (WebCore::RenderLayerFilterInfo::removeFilterInfoForRenderLayer):
+        (WebCore::RenderLayerFilterInfo::RenderLayerFilterInfo):
+        (WebCore::RenderLayerFilterInfo::~RenderLayerFilterInfo):
+        (WebCore::RenderLayerFilterInfo::setRenderer):
+        * rendering/RenderLayerFilterInfo.h: Added.
+        (WebCore):
+        (RenderLayerFilterInfo):
+        (WebCore::RenderLayerFilterInfo::dirtySourceRect):
+        (WebCore::RenderLayerFilterInfo::addDirtySourceRect):
+        (WebCore::RenderLayerFilterInfo::resetDirtySourceRect):
+        (WebCore::RenderLayerFilterInfo::renderer):
+
 2012-04-24  Kentaro Hara  <haraken@chromium.org>
 
         [V8] Pass Isolate around in SerializedScriptValue.cpp (Part1)
index 1abace8..72b1ad3 100644 (file)
@@ -3782,6 +3782,8 @@ webcore_sources += \
        Source/WebCore/rendering/RenderLayerBacking.h \
        Source/WebCore/rendering/RenderLayerCompositor.cpp \
        Source/WebCore/rendering/RenderLayerCompositor.h \
+       Source/WebCore/rendering/RenderLayerFilterInfo.cpp \
+       Source/WebCore/rendering/RenderLayerFilterInfo.h \
        Source/WebCore/rendering/RenderLineBoxList.cpp \
        Source/WebCore/rendering/RenderLineBoxList.h \
        Source/WebCore/rendering/RenderListBox.cpp \
index 637bb78..2dbc02d 100644 (file)
@@ -1259,6 +1259,7 @@ SOURCES += \
     rendering/RenderLayer.cpp \
     rendering/RenderLayerBacking.cpp \
     rendering/RenderLayerCompositor.cpp \
+    rendering/RenderLayerFilterInfo.cpp \
     rendering/RenderLineBoxList.cpp \
     rendering/RenderListBox.cpp \
     rendering/RenderListItem.cpp \
index 5225d9c..04d6612 100644 (file)
             'rendering/RenderImageResourceStyleImage.h',
             'rendering/RenderLayer.h',
             'rendering/RenderLayerBacking.h',
+            'rendering/RenderLayerFilterInfo.h',
             'rendering/RenderLineBoxList.h',
             'rendering/RenderListItem.h',
             'rendering/RenderNamedFlowThread.h',
             'rendering/RenderLayerBacking.cpp',
             'rendering/RenderLayerCompositor.cpp',
             'rendering/RenderLayerCompositor.h',
+            'rendering/RenderLayerFilterInfo.cpp',
+            'rendering/RenderLayerFilterInfo.h',
             'rendering/RenderLineBoxList.cpp',
             'rendering/RenderListBox.cpp',
             'rendering/RenderListBox.h',
index a31d70d..4fccb04 100755 (executable)
                                >
                        </File>
                        <File
+                               RelativePath="..\rendering\RenderLayerFilterInfo.cpp"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\rendering\RenderLayerFilterInfo.h"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\rendering\RenderLineBoxList.cpp"
                                >
                                <FileConfiguration
index febdf30..8f182e0 100644 (file)
                50ACE2CB14B5D79300446666 /* CustomFilterOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 50ACE2CA14B5D79300446666 /* CustomFilterOperation.h */; };
                50CC089A14C6E99C0017AB51 /* CustomFilterNumberParameter.h in Headers */ = {isa = PBXBuildFile; fileRef = 50CC089914C6E99C0017AB51 /* CustomFilterNumberParameter.h */; };
                50CC0A3914C6F5B10017AB51 /* CustomFilterOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 50CC0A3814C6F5B10017AB51 /* CustomFilterOperation.cpp */; };
+               50D10D991545F5760096D288 /* RenderLayerFilterInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 50D10D971545F5760096D288 /* RenderLayerFilterInfo.cpp */; };
+               50D10D9A1545F5760096D288 /* RenderLayerFilterInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 50D10D981545F5760096D288 /* RenderLayerFilterInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
                50D403C714768C9400D30BB5 /* FECustomFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 50D403C514768C9400D30BB5 /* FECustomFilter.cpp */; };
                50D403C814768C9400D30BB5 /* FECustomFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 50D403C614768C9400D30BB5 /* FECustomFilter.h */; };
                50D405F9147D31F300D30BB5 /* CustomFilterMesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 50D405F7147D31F300D30BB5 /* CustomFilterMesh.cpp */; };
                50B42157146976960087E604 /* WebKitCSSShaderValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebKitCSSShaderValue.h; sourceTree = "<group>"; };
                50CC089914C6E99C0017AB51 /* CustomFilterNumberParameter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CustomFilterNumberParameter.h; path = filters/CustomFilterNumberParameter.h; sourceTree = "<group>"; };
                50CC0A3814C6F5B10017AB51 /* CustomFilterOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CustomFilterOperation.cpp; path = filters/CustomFilterOperation.cpp; sourceTree = "<group>"; };
+               50D10D971545F5760096D288 /* RenderLayerFilterInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderLayerFilterInfo.cpp; sourceTree = "<group>"; };
+               50D10D981545F5760096D288 /* RenderLayerFilterInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderLayerFilterInfo.h; sourceTree = "<group>"; };
                50D403C514768C9400D30BB5 /* FECustomFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FECustomFilter.cpp; path = filters/FECustomFilter.cpp; sourceTree = "<group>"; };
                50D403C614768C9400D30BB5 /* FECustomFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FECustomFilter.h; path = filters/FECustomFilter.h; sourceTree = "<group>"; };
                50D405F7147D31F300D30BB5 /* CustomFilterMesh.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CustomFilterMesh.cpp; path = filters/CustomFilterMesh.cpp; sourceTree = "<group>"; };
                F523D2F302DE443B018635CA /* rendering */ = {
                        isa = PBXGroup;
                        children = (
+                               50D10D971545F5760096D288 /* RenderLayerFilterInfo.cpp */,
+                               50D10D981545F5760096D288 /* RenderLayerFilterInfo.h */,
                                439046C212DA25CE00AF80A2 /* mathml */,
                                BC8C8FAA0DDCD2F200B592F4 /* style */,
                                088C2F7412390080003D65CE /* svg */,
                                CECADFC9153778FF00E37068 /* DictationCommand.h in Headers */,
                                CECADFCE1537791D00E37068 /* TextInsertionBaseCommand.h in Headers */,
                                9831AE4A154225C900FE2644 /* ReferrerPolicy.h in Headers */,
+                               50D10D9A1545F5760096D288 /* RenderLayerFilterInfo.h in Headers */,
                                B658FFA21522EF3A00DD5595 /* JSRadioNodeList.h in Headers */,
                                B658FFA61522EFAA00DD5595 /* RadioNodeList.h in Headers */,
                                E100EE761546EAC100BA11D1 /* StyleBuilder.h in Headers */,
                                CECADFC6153778FF00E37068 /* DictationAlternative.cpp in Sources */,
                                CECADFC8153778FF00E37068 /* DictationCommand.cpp in Sources */,
                                CECADFCD1537791D00E37068 /* TextInsertionBaseCommand.cpp in Sources */,
+                               50D10D991545F5760096D288 /* RenderLayerFilterInfo.cpp in Sources */,
                                B658FFA11522EF3A00DD5595 /* JSRadioNodeList.cpp in Sources */,
                                B658FFA51522EFAA00DD5595 /* RadioNodeList.cpp in Sources */,
                                E100EE751546EAC100BA11D1 /* StyleBuilder.cpp in Sources */,
index be43904..404168a 100644 (file)
@@ -378,11 +378,11 @@ LayoutRect FilterEffectRenderer::computeSourceImageRectForDirtyRect(const Layout
 
 bool FilterEffectRendererHelper::prepareFilterEffect(RenderLayer* renderLayer, const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect, const LayoutRect& layerRepaintRect)
 {
-    ASSERT(m_haveFilterEffect && renderLayer->filter());
+    ASSERT(m_haveFilterEffect && renderLayer->filterRenderer());
     m_renderLayer = renderLayer;
     m_repaintRect = dirtyRect;
 
-    FilterEffectRenderer* filter = renderLayer->filter();
+    FilterEffectRenderer* filter = renderLayer->filterRenderer();
     LayoutRect filterSourceRect = filter->computeSourceImageRectForDirtyRect(filterBoxRect, dirtyRect);
     m_paintOffset = filterSourceRect.location();
 
@@ -408,7 +408,7 @@ GraphicsContext* FilterEffectRendererHelper::beginFilterEffect(GraphicsContext*
 {
     ASSERT(m_renderLayer);
     
-    FilterEffectRenderer* filter = m_renderLayer->filter();
+    FilterEffectRenderer* filter = m_renderLayer->filterRenderer();
     filter->allocateBackingStoreIfNeeded();
     // Paint into the context that represents the SourceGraphic of the filter.
     GraphicsContext* sourceGraphicsContext = filter->inputContext();
@@ -431,8 +431,8 @@ GraphicsContext* FilterEffectRendererHelper::beginFilterEffect(GraphicsContext*
 
 GraphicsContext* FilterEffectRendererHelper::applyFilterEffect()
 {
-    ASSERT(m_haveFilterEffect && m_renderLayer->filter());
-    FilterEffectRenderer* filter = m_renderLayer->filter();
+    ASSERT(m_haveFilterEffect && m_renderLayer->filterRenderer());
+    FilterEffectRenderer* filter = m_renderLayer->filterRenderer();
     filter->inputContext()->restore();
 
     filter->apply();
index 6681327..e40e880 100644 (file)
@@ -169,6 +169,9 @@ RenderLayer::RenderLayer(RenderBoxModelObject* renderer)
     , m_layerListMutationAllowed(true)
 #endif
     , m_canSkipRepaintRectsUpdateOnScroll(renderer->isTableCell())
+#if ENABLE(CSS_FILTERS)
+    , m_hasFilterInfo(false)
+#endif
     , m_renderer(renderer)
     , m_parent(0)
     , m_previous(0)
@@ -230,6 +233,10 @@ RenderLayer::~RenderLayer()
 
     if (m_reflection)
         removeReflection();
+    
+#if ENABLE(CSS_FILTERS)
+    removeFilterInfoIfNeeded();
+#endif
 
     // Child layers will be deleted by their corresponding render objects, so
     // we don't need to delete them ourselves.
@@ -286,20 +293,23 @@ bool RenderLayer::paintsWithFilters() const
     if (!renderer()->hasFilter())
         return false;
         
+#if USE(ACCELERATED_COMPOSITING)
     if (!isComposited())
         return true;
 
     if (!m_backing || !m_backing->canCompositeFilters())
         return true;
+#endif
 
     return false;
 }
     
 bool RenderLayer::requiresFullLayerImageForFilters() const 
 {
-    // FIXME: This can be optimized to enlarge the repaint rect exactly with the amount that is going to be used.
-    // https://bugs.webkit.org/show_bug.cgi?id=81263
-    return paintsWithFilters() && filter() && filter()->hasFilterThatMovesPixels();
+    if (!paintsWithFilters())
+        return false;
+    FilterEffectRenderer* filter = filterRenderer();
+    return filter ? filter->hasFilterThatMovesPixels() : false;
 }
 #endif
 
@@ -1004,8 +1014,10 @@ void RenderLayer::setFilterBackendNeedsRepaintingInRect(const LayoutRect& rect,
         rectForRepaint.expand(leftOutset + rightOutset, topOutset + bottomOutset);
     }
 #endif
-    
-    m_filterRepaintRect.unite(rectForRepaint);
+
+    RenderLayerFilterInfo* filterInfo = this->filterInfo();
+    ASSERT(filterInfo);
+    filterInfo->expandDirtySourceRect(rectForRepaint);
     
     RenderLayer* parentLayer = enclosingFilterRepaintLayer();
     ASSERT(parentLayer);
@@ -2978,14 +2990,17 @@ void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* co
     updateLayerListsIfNeeded();
 
 #if ENABLE(CSS_FILTERS)
-    FilterEffectRendererHelper filterPainter(filter() && paintsWithFilters());
+    FilterEffectRendererHelper filterPainter(filterRenderer() && paintsWithFilters());
     if (filterPainter.haveFilterEffect() && !context->paintingDisabled()) {
         LayoutPoint rootLayerOffset;
         convertToLayerCoords(rootLayer, rootLayerOffset);
-        m_filterRepaintRect.move(rootLayerOffset.x(), rootLayerOffset.y());
-        if (filterPainter.prepareFilterEffect(this, calculateLayerBounds(this, rootLayer, 0), parentPaintDirtyRect, m_filterRepaintRect)) {
+        RenderLayerFilterInfo* filterInfo = this->filterInfo();
+        ASSERT(filterInfo);
+        LayoutRect filterRepaintRect = filterInfo->dirtySourceRect();
+        filterRepaintRect.move(rootLayerOffset.x(), rootLayerOffset.y());
+        if (filterPainter.prepareFilterEffect(this, calculateLayerBounds(this, rootLayer, 0), parentPaintDirtyRect, filterRepaintRect)) {
             // Now we know for sure, that the source image will be updated, so we can revert our tracking repaint rect back to zero.
-            m_filterRepaintRect = IntRect();
+            filterInfo->resetDirtySourceRect();
 
             // Rewire the old context to a memory buffer, so that we can capture the contents of the layer.
             // NOTE: We saved the old context in the "transparencyLayerContext" local variable, to be able to start a transparency layer
@@ -2999,7 +3014,7 @@ void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* co
                 // If the filter needs the full source image, we need to avoid using the clip rectangles.
                 // Otherwise, if for example this layer has overflow:hidden, a drop shadow will not compute correctly.
                 // Note that we will still apply the clipping on the final rendering of the filter.
-                useClipRect = !filter()->hasFilterThatMovesPixels();
+                useClipRect = !filterRenderer()->hasFilterThatMovesPixels();
             }
         }
     }
@@ -4854,20 +4869,31 @@ void RenderLayer::updateReflectionStyle()
 #if ENABLE(CSS_FILTERS)
 void RenderLayer::updateOrRemoveFilterEffect()
 {
-    if (paintsWithFilters() && renderer()->style()->filter().size()) {
-        if (!m_filter) {
-            m_filter = FilterEffectRenderer::create(this);
-            RenderingMode renderingMode = renderer()->frame()->page()->settings()->acceleratedFiltersEnabled() ? Accelerated : Unaccelerated;
-            m_filter->setRenderingMode(renderingMode);
-        }
-
-        // If the filter fails to build, remove it from the layer. It will still attempt to
-        // go through regular processing (e.g. compositing), but never apply anything.
-        if (!m_filter->build(renderer()->document(), renderer()->style()->filter()))
-            m_filter = 0;
-    } else {
-        m_filter = 0;
+    if (!hasFilter()) {
+        removeFilterInfoIfNeeded();
+        return;
     }
+    
+    if (!paintsWithFilters()) {
+        // Don't delete the whole filter info here, because we might use it
+        // for loading CSS shader files.
+        if (RenderLayerFilterInfo* filterInfo = this->filterInfo())
+            filterInfo->setRenderer(0);
+        return;
+    }
+    
+    RenderLayerFilterInfo* filterInfo = ensureFilterInfo();
+    if (!filterInfo->renderer()) {
+        RefPtr<FilterEffectRenderer> filterRenderer = FilterEffectRenderer::create(this);
+        RenderingMode renderingMode = renderer()->frame()->page()->settings()->acceleratedFiltersEnabled() ? Accelerated : Unaccelerated;
+        filterRenderer->setRenderingMode(renderingMode);
+        filterInfo->setRenderer(filterRenderer.release());
+    }
+
+    // If the filter fails to build, remove it from the layer. It will still attempt to
+    // go through regular processing (e.g. compositing), but never apply anything.
+    if (!filterInfo->renderer()->build(renderer()->document(), renderer()->style()->filter()))
+        filterInfo->setRenderer(0);
 }
 
 void RenderLayer::filterNeedsRepaint()
index 9b7b2c4..cbe4432 100644 (file)
 #ifndef RenderLayer_h
 #define RenderLayer_h
 
-#if ENABLE(CSS_FILTERS)
-#include "FilterEffectObserver.h"
-#endif
 #include "PaintInfo.h"
 #include "RenderBox.h"
 #include "ScrollableArea.h"
 #include <wtf/OwnPtr.h>
 
+#if ENABLE(CSS_FILTERS)
+#include "FilterEffectObserver.h"
+#include "RenderLayerFilterInfo.h"
+#endif
+
 namespace WebCore {
 
 #if ENABLE(CSS_FILTERS)
@@ -576,7 +578,22 @@ public:
 #if ENABLE(CSS_FILTERS)
     bool paintsWithFilters() const;
     bool requiresFullLayerImageForFilters() const;
-    FilterEffectRenderer* filter() const { return m_filter.get(); }
+    FilterEffectRenderer* filterRenderer() const 
+    {
+        RenderLayerFilterInfo* filterInfo = this->filterInfo();
+        return filterInfo ? filterInfo->renderer() : 0;
+    }
+    
+    RenderLayerFilterInfo* filterInfo() const { return hasFilterInfo() ? RenderLayerFilterInfo::filterInfoForRenderLayer(this) : 0; }
+    RenderLayerFilterInfo* ensureFilterInfo() { return RenderLayerFilterInfo::createFilterInfoForRenderLayerIfNeeded(this); }
+    void removeFilterInfoIfNeeded() 
+    {
+        if (hasFilterInfo())
+            RenderLayerFilterInfo::removeFilterInfoForRenderLayer(this); 
+    }
+    
+    bool hasFilterInfo() const { return m_hasFilterInfo; }
+    void setHasFilterInfo(bool hasFilterInfo) { m_hasFilterInfo = hasFilterInfo; }
 #endif
 
 #if !ASSERT_DISABLED
@@ -825,6 +842,10 @@ protected:
     // saves a lot of time when scrolling on a table.
     bool m_canSkipRepaintRectsUpdateOnScroll : 1;
 
+#if ENABLE(CSS_FILTERS)
+    bool m_hasFilterInfo : 1;
+#endif
+
     RenderBoxModelObject* m_renderer;
 
     RenderLayer* m_parent;
@@ -885,11 +906,6 @@ protected:
     
     // May ultimately be extended to many replicas (with their own paint order).
     RenderReplica* m_reflection;
-  
-#if ENABLE(CSS_FILTERS)
-    RefPtr<FilterEffectRenderer> m_filter;
-    LayoutRect m_filterRepaintRect;
-#endif
         
     // Renderers to hold our custom scroll corner and resizer.
     RenderScrollbarPart* m_scrollCorner;
diff --git a/Source/WebCore/rendering/RenderLayerFilterInfo.cpp b/Source/WebCore/rendering/RenderLayerFilterInfo.cpp
new file mode 100644 (file)
index 0000000..0479c2a
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(CSS_FILTERS)
+#include "RenderLayerFilterInfo.h"
+
+#include "FilterEffectRenderer.h"
+#include "RenderLayer.h"
+
+namespace WebCore {
+
+RenderLayerFilterInfoMap* RenderLayerFilterInfo::s_filterMap = 0;
+
+RenderLayerFilterInfo* RenderLayerFilterInfo::filterInfoForRenderLayer(const RenderLayer* layer)
+{
+    if (!s_filterMap)
+        return 0;
+    RenderLayerFilterInfoMap::iterator iter = s_filterMap->find(layer);
+    return (iter != s_filterMap->end()) ? iter->second : 0;
+}
+
+RenderLayerFilterInfo* RenderLayerFilterInfo::createFilterInfoForRenderLayerIfNeeded(RenderLayer* layer)
+{
+    if (!s_filterMap)
+        s_filterMap = new RenderLayerFilterInfoMap();
+    
+    RenderLayerFilterInfoMap::iterator iter = s_filterMap->find(layer);
+    if (iter != s_filterMap->end()) {
+        ASSERT(layer->hasFilterInfo());
+        return iter->second;
+    }
+    
+    RenderLayerFilterInfo* filter = new RenderLayerFilterInfo(layer);
+    s_filterMap->set(layer, filter);
+    layer->setHasFilterInfo(true);
+    return filter;
+}
+
+void RenderLayerFilterInfo::removeFilterInfoForRenderLayer(RenderLayer* layer)
+{
+    if (!s_filterMap)
+        return;
+    RenderLayerFilterInfo* filter = s_filterMap->take(layer);
+    if (s_filterMap->isEmpty()) {
+        delete s_filterMap;
+        s_filterMap = 0;
+    }
+    if (!filter) {
+        ASSERT(!layer->hasFilterInfo());
+        return;
+    }
+    layer->setHasFilterInfo(false);
+    delete filter;
+}
+
+RenderLayerFilterInfo::RenderLayerFilterInfo(RenderLayer* layer)
+    : m_layer(layer)
+{
+}
+
+RenderLayerFilterInfo::~RenderLayerFilterInfo()
+{
+    // Keeping the destructor here because there's a ref to FilterEffectRenderer that might get deleted.
+}
+
+void RenderLayerFilterInfo::setRenderer(PassRefPtr<FilterEffectRenderer> renderer)
+{ 
+    m_renderer = renderer; 
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_FILTERS)
diff --git a/Source/WebCore/rendering/RenderLayerFilterInfo.h b/Source/WebCore/rendering/RenderLayerFilterInfo.h
new file mode 100644 (file)
index 0000000..2b705e6
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef RenderLayerFilterInfo_h
+#define RenderLayerFilterInfo_h
+
+#if ENABLE(CSS_FILTERS)
+
+#include "LayoutTypes.h"
+#include <wtf/HashMap.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class FilterEffectRenderer;
+class RenderLayer;
+class RenderLayerFilterInfo;
+
+typedef HashMap<const RenderLayer*, RenderLayerFilterInfo*> RenderLayerFilterInfoMap;
+    
+class RenderLayerFilterInfo {
+public:
+    static RenderLayerFilterInfo* filterInfoForRenderLayer(const RenderLayer*);
+    static RenderLayerFilterInfo* createFilterInfoForRenderLayerIfNeeded(RenderLayer*);
+    static void removeFilterInfoForRenderLayer(RenderLayer*);
+
+    const LayoutRect& dirtySourceRect() const { return m_dirtySourceRect; }
+    void expandDirtySourceRect(const LayoutRect& rect) { m_dirtySourceRect.unite(rect); }
+    void resetDirtySourceRect() { m_dirtySourceRect = LayoutRect(); }
+    
+    FilterEffectRenderer* renderer() const { return m_renderer.get(); }
+    void setRenderer(PassRefPtr<FilterEffectRenderer>);
+private:
+    RenderLayerFilterInfo(RenderLayer*);
+    ~RenderLayerFilterInfo();
+    
+    RenderLayer* m_layer;
+    
+    RefPtr<FilterEffectRenderer> m_renderer;
+    LayoutRect m_dirtySourceRect;
+    
+    static RenderLayerFilterInfoMap* s_filterMap;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_FILTERS)
+
+#endif // RenderLayerFilterInfo_h