Simplify RenderLayer filter code
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 4 Sep 2018 20:27:09 +0000 (20:27 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 4 Sep 2018 20:27:09 +0000 (20:27 +0000)
https://bugs.webkit.org/show_bug.cgi?id=189248

Reviewed by Dean Jackson.

Painting filters in RenderLayer involved the confusingly named RenderLayer::FilterInfo,
and FilterEffectRenderer/FilterEffectRendererHelper. Reduce confusion by just collapsing
these together into RenderLayerFilters. RenderLayerFilters stores a reference to the
CSSFilter, and knows how to set it up, and vend a GraphicsContext* for painting the content
to be filtered.

It's also simpler to just give RenderLayer a member variable for RenderLayerFilters, rather
than using a side hash (we can recoup the space in other ways layer).

* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* css/CSSFilterImageValue.cpp:
* rendering/CSSFilter.h:
* rendering/FilterEffectRenderer.cpp: Removed.
* rendering/FilterEffectRenderer.h: Removed.
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::RenderLayer):
(WebCore::RenderLayer::~RenderLayer):
(WebCore::RenderLayer::paintsWithFilters const):
(WebCore::RenderLayer::requiresFullLayerImageForFilters const):
(WebCore::RenderLayer::setFilterBackendNeedsRepaintingInRect):
(WebCore::RenderLayer::filtersForPainting const):
(WebCore::RenderLayer::setupFilters):
(WebCore::RenderLayer::applyFilters):
(WebCore::RenderLayer::paintLayerContents):
(WebCore::RenderLayer::calculateClipRects const):
(WebCore::RenderLayer::filter const): Deleted.
(WebCore::RenderLayer::filterPainter const): Deleted.
(WebCore::RenderLayer::hasFilterThatIsPainting const): Deleted.
* rendering/RenderLayer.h:
* rendering/RenderLayerFilterInfo.cpp: Removed.
* rendering/RenderLayerFilters.cpp: Added.
(WebCore::RenderLayerFilters::RenderLayerFilters):
(WebCore::RenderLayerFilters::~RenderLayerFilters):
(WebCore::RenderLayerFilters::setFilter):
(WebCore::RenderLayerFilters::hasFilterThatMovesPixels const):
(WebCore::RenderLayerFilters::hasFilterThatShouldBeRestrictedBySecurityOrigin const):
(WebCore::RenderLayerFilters::notifyFinished):
(WebCore::RenderLayerFilters::updateReferenceFilterClients):
(WebCore::RenderLayerFilters::removeReferenceFilterClients):
(WebCore::RenderLayerFilters::buildFilter):
(WebCore::RenderLayerFilters::beginFilterEffect):
(WebCore::RenderLayerFilters::applyFilterEffect):
* rendering/RenderLayerFilters.h: Renamed from Source/WebCore/rendering/RenderLayerFilterInfo.h.

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

12 files changed:
Source/WebCore/ChangeLog
Source/WebCore/Sources.txt
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/css/CSSFilterImageValue.cpp
Source/WebCore/rendering/CSSFilter.h
Source/WebCore/rendering/FilterEffectRenderer.cpp [deleted file]
Source/WebCore/rendering/FilterEffectRenderer.h [deleted file]
Source/WebCore/rendering/RenderLayer.cpp
Source/WebCore/rendering/RenderLayer.h
Source/WebCore/rendering/RenderLayerFilterInfo.cpp [deleted file]
Source/WebCore/rendering/RenderLayerFilters.cpp [new file with mode: 0644]
Source/WebCore/rendering/RenderLayerFilters.h [moved from Source/WebCore/rendering/RenderLayerFilterInfo.h with 75% similarity]

index b772515..d665b79 100644 (file)
@@ -1,3 +1,55 @@
+2018-09-04  Simon Fraser  <simon.fraser@apple.com>
+
+        Simplify RenderLayer filter code
+        https://bugs.webkit.org/show_bug.cgi?id=189248
+
+        Reviewed by Dean Jackson.
+        
+        Painting filters in RenderLayer involved the confusingly named RenderLayer::FilterInfo,
+        and FilterEffectRenderer/FilterEffectRendererHelper. Reduce confusion by just collapsing
+        these together into RenderLayerFilters. RenderLayerFilters stores a reference to the
+        CSSFilter, and knows how to set it up, and vend a GraphicsContext* for painting the content
+        to be filtered.
+        
+        It's also simpler to just give RenderLayer a member variable for RenderLayerFilters, rather
+        than using a side hash (we can recoup the space in other ways layer).
+
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * css/CSSFilterImageValue.cpp:
+        * rendering/CSSFilter.h:
+        * rendering/FilterEffectRenderer.cpp: Removed.
+        * rendering/FilterEffectRenderer.h: Removed.
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::RenderLayer):
+        (WebCore::RenderLayer::~RenderLayer):
+        (WebCore::RenderLayer::paintsWithFilters const):
+        (WebCore::RenderLayer::requiresFullLayerImageForFilters const):
+        (WebCore::RenderLayer::setFilterBackendNeedsRepaintingInRect):
+        (WebCore::RenderLayer::filtersForPainting const):
+        (WebCore::RenderLayer::setupFilters):
+        (WebCore::RenderLayer::applyFilters):
+        (WebCore::RenderLayer::paintLayerContents):
+        (WebCore::RenderLayer::calculateClipRects const):
+        (WebCore::RenderLayer::filter const): Deleted.
+        (WebCore::RenderLayer::filterPainter const): Deleted.
+        (WebCore::RenderLayer::hasFilterThatIsPainting const): Deleted.
+        * rendering/RenderLayer.h:
+        * rendering/RenderLayerFilterInfo.cpp: Removed.
+        * rendering/RenderLayerFilters.cpp: Added.
+        (WebCore::RenderLayerFilters::RenderLayerFilters):
+        (WebCore::RenderLayerFilters::~RenderLayerFilters):
+        (WebCore::RenderLayerFilters::setFilter):
+        (WebCore::RenderLayerFilters::hasFilterThatMovesPixels const):
+        (WebCore::RenderLayerFilters::hasFilterThatShouldBeRestrictedBySecurityOrigin const):
+        (WebCore::RenderLayerFilters::notifyFinished):
+        (WebCore::RenderLayerFilters::updateReferenceFilterClients):
+        (WebCore::RenderLayerFilters::removeReferenceFilterClients):
+        (WebCore::RenderLayerFilters::buildFilter):
+        (WebCore::RenderLayerFilters::beginFilterEffect):
+        (WebCore::RenderLayerFilters::applyFilterEffect):
+        * rendering/RenderLayerFilters.h: Renamed from Source/WebCore/rendering/RenderLayerFilterInfo.h.
+
 2018-09-04  Dean Jackson  <dino@apple.com>
 
         Build fix.
index 26fbe21..d4cf50d 100644 (file)
@@ -1841,7 +1841,6 @@ rendering/CSSFilter.cpp
 rendering/ClipRect.cpp
 rendering/CounterNode.cpp
 rendering/EllipsisBox.cpp
-rendering/FilterEffectRenderer.cpp
 rendering/FlexibleBoxAlgorithm.cpp
 rendering/FixedTableLayout.cpp
 rendering/FloatingObjects.cpp
@@ -1896,7 +1895,7 @@ rendering/RenderInline.cpp
 rendering/RenderLayer.cpp
 rendering/RenderLayerBacking.cpp
 rendering/RenderLayerCompositor.cpp
-rendering/RenderLayerFilterInfo.cpp
+rendering/RenderLayerFilters.cpp
 rendering/RenderLayerModelObject.cpp
 rendering/RenderLineBoxList.cpp
 rendering/RenderLineBreak.cpp
index 908305e..68ce908 100644 (file)
                31288E750E3005D6003619AE /* CSSKeyframesRule.h in Headers */ = {isa = PBXBuildFile; fileRef = 31288E710E3005D6003619AE /* CSSKeyframesRule.h */; };
                3128CA6B147331630074C72A /* NotificationController.h in Headers */ = {isa = PBXBuildFile; fileRef = 3128CA6A147331630074C72A /* NotificationController.h */; settings = {ATTRIBUTES = (Private, ); }; };
                312C0C41146DC6CC0016C911 /* Notification.h in Headers */ = {isa = PBXBuildFile; fileRef = 333F704F0FB49CA2008E12A6 /* Notification.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               31313F661443B35F006E2A90 /* FilterEffectRenderer.h in Headers */ = {isa = PBXBuildFile; fileRef = 31313F641443B35E006E2A90 /* FilterEffectRenderer.h */; };
                313171561FB079E5008D91FC /* CanvasBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 313171541FB079D1008D91FC /* CanvasBase.h */; settings = {ATTRIBUTES = (Private, ); }; };
                313591061E7DDC7300F30630 /* RTCIceConnectionState.h in Headers */ = {isa = PBXBuildFile; fileRef = 313591001E7DDC6000F30630 /* RTCIceConnectionState.h */; };
                313591071E7DDC7300F30630 /* RTCIceGatheringState.h in Headers */ = {isa = PBXBuildFile; fileRef = 313591011E7DDC6000F30630 /* RTCIceGatheringState.h */; };
                504AACCE1834455900E3D9BC /* InspectorNodeFinder.h in Headers */ = {isa = PBXBuildFile; fileRef = 504AACCC1834455900E3D9BC /* InspectorNodeFinder.h */; };
                5081E3E03CFF80C16EF8B48B /* CachedResourceRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 5081E3E13D0280C16EF8B48B /* CachedResourceRequest.h */; settings = {ATTRIBUTES = (Private, ); }; };
                508CCA4F13CF106B003151F3 /* RenderFragmentedFlow.h in Headers */ = {isa = PBXBuildFile; fileRef = 508CCA4D13CF106B003151F3 /* RenderFragmentedFlow.h */; };
-               50D10D9A1545F5760096D288 /* RenderLayerFilterInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 50D10D981545F5760096D288 /* RenderLayerFilterInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
                510184690B08602A004A825F /* CachedPage.h in Headers */ = {isa = PBXBuildFile; fileRef = 510184670B08602A004A825F /* CachedPage.h */; settings = {ATTRIBUTES = (Private, ); }; };
                510192D218B6B9AB007FC7A1 /* ImageControlsRootElementMac.h in Headers */ = {isa = PBXBuildFile; fileRef = 510192D018B6B9AB007FC7A1 /* ImageControlsRootElementMac.h */; };
                510192D618B6B9B7007FC7A1 /* ImageControlsRootElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 510192D418B6B9B7007FC7A1 /* ImageControlsRootElement.h */; };
                0F4966A91DB40C4300A274BB /* JSDOMPointReadOnly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMPointReadOnly.h; sourceTree = "<group>"; };
                0F53FB81213B1BB800C40D34 /* CSSFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSFilter.cpp; sourceTree = "<group>"; };
                0F53FB83213B1BB800C40D34 /* CSSFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSFilter.h; sourceTree = "<group>"; };
+               0F53FB89213B768400C40D34 /* RenderLayerFilters.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RenderLayerFilters.h; sourceTree = "<group>"; };
+               0F53FB8B213B768400C40D34 /* RenderLayerFilters.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RenderLayerFilters.cpp; sourceTree = "<group>"; };
                0F54DCE31881051D003EEDBB /* TextAutoSizing.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextAutoSizing.cpp; sourceTree = "<group>"; };
                0F54DCE41881051D003EEDBB /* TextAutoSizing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextAutoSizing.h; sourceTree = "<group>"; };
                0F54DD051881D5F5003EEDBB /* Touch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Touch.h; sourceTree = "<group>"; };
                31288E710E3005D6003619AE /* CSSKeyframesRule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSKeyframesRule.h; sourceTree = "<group>"; };
                3128CA67147331520074C72A /* NotificationController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NotificationController.cpp; sourceTree = "<group>"; };
                3128CA6A147331630074C72A /* NotificationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NotificationController.h; sourceTree = "<group>"; };
-               31313F631443B35E006E2A90 /* FilterEffectRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FilterEffectRenderer.cpp; sourceTree = "<group>"; };
-               31313F641443B35E006E2A90 /* FilterEffectRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FilterEffectRenderer.h; sourceTree = "<group>"; };
                313171541FB079D1008D91FC /* CanvasBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CanvasBase.h; sourceTree = "<group>"; };
                313171571FB0969E008D91FC /* CanvasBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CanvasBase.cpp; sourceTree = "<group>"; };
                313591001E7DDC6000F30630 /* RTCIceConnectionState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RTCIceConnectionState.h; sourceTree = "<group>"; };
                5081E3E13D0280C16EF8B48B /* CachedResourceRequest.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CachedResourceRequest.h; sourceTree = "<group>"; };
                508CCA4D13CF106B003151F3 /* RenderFragmentedFlow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderFragmentedFlow.h; sourceTree = "<group>"; };
                508CCA4E13CF106B003151F3 /* RenderFragmentedFlow.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderFragmentedFlow.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>"; };
                510184670B08602A004A825F /* CachedPage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CachedPage.h; sourceTree = "<group>"; };
                510184680B08602A004A825F /* CachedPage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CachedPage.cpp; sourceTree = "<group>"; };
                510192CF18B6B9AB007FC7A1 /* ImageControlsRootElementMac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageControlsRootElementMac.cpp; sourceTree = "<group>"; };
                                0F53FB83213B1BB800C40D34 /* CSSFilter.h */,
                                A8CFF6CA0A1561CD000A4234 /* EllipsisBox.cpp */,
                                A8CFF6BD0A156118000A4234 /* EllipsisBox.h */,
-                               31313F631443B35E006E2A90 /* FilterEffectRenderer.cpp */,
-                               31313F641443B35E006E2A90 /* FilterEffectRenderer.h */,
                                A8CFF0480A154F09000A4234 /* FixedTableLayout.cpp */,
                                A8CFF04A0A154F09000A4234 /* FixedTableLayout.h */,
                                94DD79721E54E3A20058FB80 /* FlexibleBoxAlgorithm.cpp */,
                                0F580CFB0F12DE9B0051D689 /* RenderLayerBacking.h */,
                                0F580CFA0F12DE9B0051D689 /* RenderLayerCompositor.cpp */,
                                0F580CF90F12DE9B0051D689 /* RenderLayerCompositor.h */,
-                               50D10D971545F5760096D288 /* RenderLayerFilterInfo.cpp */,
-                               50D10D981545F5760096D288 /* RenderLayerFilterInfo.h */,
+                               0F53FB8B213B768400C40D34 /* RenderLayerFilters.cpp */,
+                               0F53FB89213B768400C40D34 /* RenderLayerFilters.h */,
                                3C244FE5A375AC633F88BE6F /* RenderLayerModelObject.cpp */,
                                3C244FE4A375AC633F88BE6F /* RenderLayerModelObject.h */,
                                BC33FB1A0F30EE85002CDD7C /* RenderLineBoxList.cpp */,
                                712BE4831FE865DD002031CC /* FillMode.h in Headers */,
                                845E72F80FD261EE00A87D79 /* Filter.h in Headers */,
                                08C9251A0FCC7C4A00480DEC /* FilterEffect.h in Headers */,
-                               31313F661443B35F006E2A90 /* FilterEffectRenderer.h in Headers */,
                                49ECEB6E1499790D00CDD3A4 /* FilterOperation.h in Headers */,
                                49ECEB701499790D00CDD3A4 /* FilterOperations.h in Headers */,
                                372C00D9129619F8005C9575 /* FindOptions.h in Headers */,
                                BCEA487A097D93020094C9E4 /* RenderLayer.h in Headers */,
                                0F580CFF0F12DE9B0051D689 /* RenderLayerBacking.h in Headers */,
                                0F580CFD0F12DE9B0051D689 /* RenderLayerCompositor.h in Headers */,
-                               50D10D9A1545F5760096D288 /* RenderLayerFilterInfo.h in Headers */,
                                3C244FEAA375AC633F88BE6F /* RenderLayerModelObject.h in Headers */,
                                0BE030A20F3112FB003C1A46 /* RenderLineBoxList.h in Headers */,
                                BCEA4864097D93020094C9E4 /* RenderLineBreak.h in Headers */,
index 6f253d1..7348282 100644 (file)
@@ -30,7 +30,6 @@
 #include "CSSFilter.h"
 #include "CachedImage.h"
 #include "CachedResourceLoader.h"
-#include "FilterEffectRenderer.h"
 #include "GraphicsContext.h"
 #include "ImageBuffer.h"
 #include "RenderElement.h"
index c2a2387..493729f 100644 (file)
@@ -43,9 +43,8 @@ enum class FilterConsumer { FilterProperty, FilterFunction };
 
 class CSSFilter final : public Filter {
     WTF_MAKE_FAST_ALLOCATED;
+    friend class RenderLayerFilters;
 public:
-    friend class FilterEffectRendererHelper;
-
     static Ref<CSSFilter> create();
 
     void setSourceImageRect(const FloatRect&);
diff --git a/Source/WebCore/rendering/FilterEffectRenderer.cpp b/Source/WebCore/rendering/FilterEffectRenderer.cpp
deleted file mode 100644 (file)
index d3b5d25..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (C) 2011-2017 Apple Inc. All rights reserved.
- * Copyright (C) 2013 Google Inc. 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 APPLE INC. ``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 APPLE INC. OR
- * CONTRIBUTORS 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"
-#include "FilterEffectRenderer.h"
-
-#include "CSSFilter.h"
-#include "CachedSVGDocument.h"
-#include "CachedSVGDocumentReference.h"
-#include "ElementIterator.h"
-#include "FEColorMatrix.h"
-#include "FEComponentTransfer.h"
-#include "FEDropShadow.h"
-#include "FEGaussianBlur.h"
-#include "FEMerge.h"
-#include "Logging.h"
-#include "RenderLayer.h"
-#include "SVGElement.h"
-#include "SVGFilterBuilder.h"
-#include "SVGFilterPrimitiveStandardAttributes.h"
-#include "SourceGraphic.h"
-#include <algorithm>
-#include <wtf/MathExtras.h>
-
-#if USE(DIRECT2D)
-#include <d2d1.h>
-#endif
-
-namespace WebCore {
-
-bool FilterEffectRendererHelper::prepareFilterEffect(RenderLayer& layer, const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect, const LayoutRect& layerRepaintRect)
-{
-    ASSERT(m_haveFilterEffect);
-    ASSERT(layer.filter());
-
-    auto& filter = *layer.filter();
-    auto filterSourceRect = filter.computeSourceImageRectForDirtyRect(filterBoxRect, dirtyRect);
-
-    if (filterSourceRect.isEmpty()) {
-        // The dirty rect is not in view, just bail out.
-        m_haveFilterEffect = false;
-        return false;
-    }
-
-    bool hasUpdatedBackingStore = filter.updateBackingStoreRect(filterSourceRect);
-
-    m_renderLayer = &layer;
-    if (!filter.hasFilterThatMovesPixels())
-        m_repaintRect = dirtyRect;
-    else {
-        if (hasUpdatedBackingStore)
-            m_repaintRect = filterSourceRect;
-        else {
-            m_repaintRect = dirtyRect;
-            m_repaintRect.unite(layerRepaintRect);
-            m_repaintRect.intersect(filterSourceRect);
-        }
-    }
-    m_paintOffset = filterSourceRect.location();
-
-    return true;
-}
-
-GraphicsContext* FilterEffectRendererHelper::filterContext() const
-{
-    if (!m_haveFilterEffect)
-        return nullptr;
-    return m_renderLayer->filter()->inputContext();
-}
-
-bool FilterEffectRendererHelper::beginFilterEffect()
-{
-    ASSERT(m_renderLayer);
-    ASSERT(m_renderLayer->filter());
-
-    auto& filter = *m_renderLayer->filter();
-    filter.allocateBackingStoreIfNeeded(m_targetContext);
-    // Paint into the context that represents the SourceGraphic of the filter.
-    auto* sourceGraphicsContext = filter.inputContext();
-    if (!sourceGraphicsContext || filter.filterRegion().isEmpty() || ImageBuffer::sizeNeedsClamping(filter.filterRegion().size())) {
-        // Disable the filters and continue.
-        m_haveFilterEffect = false;
-        return false;
-    }
-
-    // Translate the context so that the contents of the layer is captured in the offscreen memory buffer.
-    sourceGraphicsContext->save();
-    sourceGraphicsContext->translate(-m_paintOffset);
-    sourceGraphicsContext->clearRect(m_repaintRect);
-    sourceGraphicsContext->clip(m_repaintRect);
-
-    m_startedFilterEffect = true;
-    return true;
-}
-
-void FilterEffectRendererHelper::applyFilterEffect(GraphicsContext& destinationContext)
-{
-    ASSERT(m_haveFilterEffect);
-    ASSERT(m_renderLayer);
-    ASSERT(m_renderLayer->filter());
-    ASSERT(m_renderLayer->filter()->inputContext());
-
-    LOG_WITH_STREAM(Filters, stream << "\nFilterEffectRendererHelper " << this << " applyFilterEffect");
-
-    auto& filter = *m_renderLayer->filter();
-    filter.inputContext()->restore();
-
-    filter.apply();
-
-    // Get the filtered output and draw it in place.
-    LayoutRect destRect = filter.outputRect();
-    destRect.move(m_paintOffset.x(), m_paintOffset.y());
-
-    if (auto* outputBuffer = filter.output())
-        destinationContext.drawImageBuffer(*outputBuffer, snapRectToDevicePixels(destRect, m_renderLayer->renderer().document().deviceScaleFactor()));
-
-    filter.clearIntermediateResults();
-
-    LOG_WITH_STREAM(Filters, stream << "FilterEffectRendererHelper " << this << " applyFilterEffect done\n");
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/rendering/FilterEffectRenderer.h b/Source/WebCore/rendering/FilterEffectRenderer.h
deleted file mode 100644 (file)
index 3fb1a34..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2011-2017 Apple Inc. 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 APPLE INC. ``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 APPLE INC. OR
- * CONTRIBUTORS 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. 
- */
-
-#pragma once
-
-#include "LayoutRect.h"
-
-namespace WebCore {
-
-class Document;
-class GraphicsContext;
-class RenderLayer;
-
-class FilterEffectRendererHelper {
-    WTF_MAKE_FAST_ALLOCATED;
-public:
-    FilterEffectRendererHelper(bool haveFilterEffect, GraphicsContext& targetContext)
-        : m_targetContext(targetContext)
-        , m_haveFilterEffect(haveFilterEffect)
-    {
-    }
-
-    bool haveFilterEffect() const { return m_haveFilterEffect; }
-    bool hasStartedFilterEffect() const { return m_startedFilterEffect; }
-
-    bool prepareFilterEffect(RenderLayer&, const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect, const LayoutRect& layerRepaintRect);
-    bool beginFilterEffect();
-    void applyFilterEffect(GraphicsContext& destinationContext);
-    
-    GraphicsContext* filterContext() const;
-
-    const LayoutRect& repaintRect() const { return m_repaintRect; }
-
-private:
-    RenderLayer* m_renderLayer { nullptr }; // FIXME: this is mainly used to get the CSSFilter. FilterEffectRendererHelper should be weaned off it.
-    LayoutPoint m_paintOffset;
-    LayoutRect m_repaintRect;
-    const GraphicsContext& m_targetContext;
-    bool m_haveFilterEffect { false };
-    bool m_startedFilterEffect { false };
-};
-
-} // namespace WebCore
index 8a074b4..d390c13 100644 (file)
@@ -59,7 +59,6 @@
 #include "EventHandler.h"
 #include "FEColorMatrix.h"
 #include "FEMerge.h"
-#include "FilterEffectRenderer.h"
 #include "FloatConversion.h"
 #include "FloatPoint3D.h"
 #include "FloatRect.h"
@@ -96,7 +95,7 @@
 #include "RenderIterator.h"
 #include "RenderLayerBacking.h"
 #include "RenderLayerCompositor.h"
-#include "RenderLayerFilterInfo.h"
+#include "RenderLayerFilters.h"
 #include "RenderMarquee.h"
 #include "RenderMultiColumnFlow.h"
 #include "RenderReplica.h"
@@ -312,7 +311,6 @@ RenderLayer::RenderLayer(RenderLayerModelObject& rendererLayerModelObject)
 #if !ASSERT_DISABLED
     , m_layerListMutationAllowed(true)
 #endif
-    , m_hasFilterInfo(false)
 #if ENABLE(CSS_COMPOSITING)
     , m_blendMode(static_cast<unsigned>(BlendMode::Normal))
     , m_hasNotIsolatedCompositedBlendingDescendants(false)
@@ -370,7 +368,7 @@ RenderLayer::~RenderLayer()
     clearScrollCorner();
     clearResizer();
 
-    FilterInfo::remove(*this);
+    clearLayerFilters();
 
     // Child layers will be deleted by their corresponding render objects, so
     // we don't need to delete them ourselves.
@@ -452,24 +450,15 @@ bool RenderLayer::paintsWithFilters() const
     if (!isComposited())
         return true;
 
-    if (!m_backing || !m_backing->canCompositeFilters())
-        return true;
-
-    return false;
+    return !m_backing->canCompositeFilters();
 }
 
 bool RenderLayer::requiresFullLayerImageForFilters() const 
 {
     if (!paintsWithFilters())
         return false;
-    auto* cssFilter = filter();
-    return cssFilter && cssFilter->hasFilterThatMovesPixels();
-}
 
-CSSFilter* RenderLayer::filter() const
-{
-    auto* filterInfo = FilterInfo::getIfExists(*this);
-    return filterInfo ? filterInfo->filter() : nullptr;
+    return m_filters && m_filters->hasFilterThatMovesPixels();
 }
 
 void RenderLayer::updateLayerPositionsAfterLayout(const RenderLayer* rootLayer, OptionSet<UpdateLayerPositionsFlag> flags)
@@ -1608,16 +1597,19 @@ RenderLayer* RenderLayer::enclosingFilterRepaintLayer() const
     return nullptr;
 }
 
+// FIXME: This neeeds a better name.
 void RenderLayer::setFilterBackendNeedsRepaintingInRect(const LayoutRect& rect)
 {
+    ASSERT(requiresFullLayerImageForFilters());
+    ASSERT(m_filters);
+
     if (rect.isEmpty())
         return;
     
     LayoutRect rectForRepaint = rect;
     renderer().style().filterOutsets().expandRect(rectForRepaint);
 
-    FilterInfo& filterInfo = FilterInfo::get(*this);
-    filterInfo.expandDirtySourceRect(rectForRepaint);
+    m_filters->expandDirtySourceRect(rectForRepaint);
     
     RenderLayer* parentLayer = enclosingFilterRepaintLayer();
     ASSERT(parentLayer);
@@ -4196,43 +4188,30 @@ bool RenderLayer::setupClipPath(GraphicsContext& context, const LayerPaintingInf
     return false;
 }
 
-std::pair<RenderLayer::FilterInfo*, std::unique_ptr<FilterEffectRendererHelper>> RenderLayer::filterPainter(GraphicsContext& context, OptionSet<PaintLayerFlag> paintFlags) const
+RenderLayerFilters* RenderLayer::filtersForPainting(GraphicsContext& context, OptionSet<PaintLayerFlag> paintFlags) const
 {
     if (context.paintingDisabled())
-        return { };
+        return nullptr;
 
     if (paintFlags & PaintLayerPaintingOverlayScrollbars)
-        return { };
+        return nullptr;
 
     if (!paintsWithFilters())
-        return { };
-
-    auto* info = FilterInfo::getIfExists(*this);
-    if (!info || !info->filter())
-        return { };
-
-    auto helper = std::make_unique<FilterEffectRendererHelper>(true, context);
-    if (!helper->haveFilterEffect())
-        return { };
+        return nullptr;
 
-    return { info, WTFMove(helper) };
-}
+    if (m_filters && m_filters->filter())
+        return m_filters.get();
 
-bool RenderLayer::hasFilterThatIsPainting(GraphicsContext& context, OptionSet<PaintLayerFlag> paintFlags) const
-{
-    return !!filterPainter(context, paintFlags).first;
+    return nullptr;
 }
 
-std::unique_ptr<FilterEffectRendererHelper> RenderLayer::setupFilters(GraphicsContext& context, LayerPaintingInfo& paintingInfo, OptionSet<PaintLayerFlag> paintFlags, const LayoutSize& offsetFromRoot, LayoutRect& rootRelativeBounds, bool& rootRelativeBoundsComputed)
+GraphicsContext* RenderLayer::setupFilters(GraphicsContext& destinationContext, LayerPaintingInfo& paintingInfo, OptionSet<PaintLayerFlag> paintFlags, const LayoutSize& offsetFromRoot, LayoutRect& rootRelativeBounds, bool& rootRelativeBoundsComputed)
 {
-    auto painter = filterPainter(context, paintFlags);
-    if (!painter.first)
+    auto* paintingFilters = filtersForPainting(destinationContext, paintFlags);
+    if (!paintingFilters)
         return nullptr;
 
-    auto& filterInfo = *painter.first;
-    auto& filterPainter = *painter.second;
-
-    LayoutRect filterRepaintRect = filterInfo.dirtySourceRect();
+    LayoutRect filterRepaintRect = paintingFilters->dirtySourceRect();
     filterRepaintRect.move(offsetFromRoot);
 
     if (!rootRelativeBoundsComputed) {
@@ -4240,35 +4219,28 @@ std::unique_ptr<FilterEffectRendererHelper> RenderLayer::setupFilters(GraphicsCo
         rootRelativeBoundsComputed = true;
     }
 
-    if (!filterPainter.prepareFilterEffect(*this, enclosingIntRect(rootRelativeBounds), enclosingIntRect(paintingInfo.paintDirtyRect), enclosingIntRect(filterRepaintRect)))
-        return nullptr;
-
-    // Now we know for sure that the source image will be updated, so we can revert our tracking repaint rect back to zero.
-    filterInfo.resetDirtySourceRect();
-
-    if (!filterPainter.beginFilterEffect())
+    GraphicsContext* filterContext = paintingFilters->beginFilterEffect(destinationContext, enclosingIntRect(rootRelativeBounds), enclosingIntRect(paintingInfo.paintDirtyRect), enclosingIntRect(filterRepaintRect));
+    if (!filterContext)
         return nullptr;
 
-    paintingInfo.paintDirtyRect = filterPainter.repaintRect();
+    paintingInfo.paintDirtyRect = paintingFilters->repaintRect();
 
     // 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.
-    paintingInfo.clipToDirtyRect = !filterInfo.filter()->hasFilterThatMovesPixels();
+    paintingInfo.clipToDirtyRect = !paintingFilters->hasFilterThatMovesPixels();
 
-    paintingInfo.requireSecurityOriginAccessForWidgets = filterInfo.filter()->hasFilterThatShouldBeRestrictedBySecurityOrigin();
+    paintingInfo.requireSecurityOriginAccessForWidgets = paintingFilters->hasFilterThatShouldBeRestrictedBySecurityOrigin();
 
-    return WTFMove(painter.second);
+    return filterContext;
 }
 
-void RenderLayer::applyFilters(FilterEffectRendererHelper* filterPainter, GraphicsContext& originalContext, const LayerPaintingInfo& paintingInfo, const LayerFragments& layerFragments)
+void RenderLayer::applyFilters(GraphicsContext& originalContext, const LayerPaintingInfo& paintingInfo, const LayerFragments& layerFragments)
 {
-    ASSERT(filterPainter->hasStartedFilterEffect());
-
     // FIXME: Handle more than one fragment.
     ClipRect backgroundRect = layerFragments.isEmpty() ? ClipRect() : layerFragments[0].backgroundRect;
     clipToRect(originalContext, paintingInfo, backgroundRect);
-    filterPainter->applyFilterEffect(originalContext);
+    m_filters->applyFilterEffect(originalContext);
     restoreClip(originalContext, paintingInfo, backgroundRect);
 }
 
@@ -4318,7 +4290,7 @@ void RenderLayer::paintLayerContents(GraphicsContext& context, const LayerPainti
 
     // Apply clip-path to context.
     LayoutSize columnAwareOffsetFromRoot = offsetFromRoot;
-    if (renderer().enclosingFragmentedFlow() && (renderer().hasClipPath() || hasFilterThatIsPainting(context, paintFlags)))
+    if (renderer().enclosingFragmentedFlow() && (renderer().hasClipPath() || filtersForPainting(context, paintFlags)))
         columnAwareOffsetFromRoot = toLayoutSize(convertToLayerCoords(paintingInfo.rootLayer, LayoutPoint(), AdjustForColumns));
 
     bool hasClipPath = false;
@@ -4335,9 +4307,7 @@ void RenderLayer::paintLayerContents(GraphicsContext& context, const LayerPainti
 
     { // Scope for filter-related state changes.
         LayerPaintingInfo localPaintingInfo(paintingInfo);
-        std::unique_ptr<FilterEffectRendererHelper> filterPainter = setupFilters(context, localPaintingInfo, paintFlags, columnAwareOffsetFromRoot, rootRelativeBounds, rootRelativeBoundsComputed);
-
-        GraphicsContext* filterContext = filterPainter ? filterPainter->filterContext() : nullptr;
+        GraphicsContext* filterContext = setupFilters(context, localPaintingInfo, paintFlags, columnAwareOffsetFromRoot, rootRelativeBounds, rootRelativeBoundsComputed);
         if (filterContext && haveTransparency) {
             // If we have a filter and transparency, we have to eagerly start a transparency layer here, rather than risk a child layer lazily starts one with the wrong context.
             beginTransparencyLayers(context, localPaintingInfo, paintingInfo.paintDirtyRect);
@@ -4431,8 +4401,7 @@ void RenderLayer::paintLayerContents(GraphicsContext& context, const LayerPainti
                 (isPaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip, offsetFromRoot);
             updatePaintingInfoForFragments(layerFragments, paintingInfo, localPaintFlags, shouldPaintContent, offsetFromRoot);
 
-            applyFilters(filterPainter.get(), context, paintingInfo, layerFragments);
-            filterPainter = nullptr;
+            applyFilters(context, paintingInfo, layerFragments);
         }
     }
     
@@ -5966,7 +5935,7 @@ RenderLayerBacking* RenderLayer::ensureBacking()
         m_backing = std::make_unique<RenderLayerBacking>(*this);
         compositor().layerBecameComposited(*this);
 
-        updateOrRemoveFilterEffectRenderer();
+        updateFilterPaintingStrategy();
     }
     return m_backing.get();
 }
@@ -5978,7 +5947,7 @@ void RenderLayer::clearBacking(bool layerBeingDestroyed)
     m_backing = nullptr;
 
     if (!layerBeingDestroyed)
-        updateOrRemoveFilterEffectRenderer();
+        updateFilterPaintingStrategy();
 }
 
 bool RenderLayer::hasCompositedMask() const
@@ -6688,13 +6657,13 @@ void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle* oldStyle
 #if ENABLE(CSS_COMPOSITING)
     updateBlendMode();
 #endif
-    updateOrRemoveFilterClients();
+    updateFiltersAfterStyleChange();
 
     updateNeedsCompositedScrolling();
 
     compositor().layerStyleChanged(diff, *this, oldStyle);
 
-    updateOrRemoveFilterEffectRenderer();
+    updateFilterPaintingStrategy();
 
 #if PLATFORM(IOS) && ENABLE(TOUCH_EVENTS)
     if (diff == StyleDifference::RecompositeLayer || diff >= StyleDifference::LayoutPositionedMovementOnly)
@@ -6860,30 +6829,45 @@ RenderStyle RenderLayer::createReflectionStyle()
     return newStyle;
 }
 
-void RenderLayer::updateOrRemoveFilterClients()
+void RenderLayer::ensureLayerFilters()
+{
+    if (m_filters)
+        return;
+    
+    m_filters = std::make_unique<RenderLayerFilters>(*this);
+}
+
+void RenderLayer::clearLayerFilters()
+{
+    m_filters = nullptr;
+}
+
+void RenderLayer::updateFiltersAfterStyleChange()
 {
     if (!hasFilter()) {
-        FilterInfo::remove(*this);
+        clearLayerFilters();
         return;
     }
+
     // Add the filter as a client to this renderer, unless we are a RenderLayer accommodating
     // an SVG. In that case it takes care of its own resource management for filters.
-    if (renderer().style().filter().hasReferenceFilter() && !renderer().isSVGRoot())
-        FilterInfo::get(*this).updateReferenceFilterClients(renderer().style().filter());
-    else if (FilterInfo* filterInfo = FilterInfo::getIfExists(*this))
-        filterInfo->removeReferenceFilterClients();
+    if (renderer().style().filter().hasReferenceFilter() && !renderer().isSVGRoot()) {
+        ensureLayerFilters();
+        m_filters->updateReferenceFilterClients(renderer().style().filter());
+    } else if (m_filters)
+        m_filters->removeReferenceFilterClients();
 }
 
-void RenderLayer::updateOrRemoveFilterEffectRenderer()
+void RenderLayer::updateFilterPaintingStrategy()
 {
-    // FilterEffectRenderer is only used to render the filters in software mode,
-    // so we always need to run updateOrRemoveFilterEffectRenderer after the composited
+    // RenderLayerFilters is only used to render the filters in software mode,
+    // so we always need to run updateFilterPaintingStrategy() after the composited
     // mode might have changed for this layer.
     if (!paintsWithFilters()) {
         // Don't delete the whole filter info here, because we might use it
         // for loading SVG reference filter files.
-        if (FilterInfo* filterInfo = FilterInfo::getIfExists(*this))
-            filterInfo->setFilter(nullptr);
+        if (m_filters)
+            m_filters->setFilter(nullptr);
 
         // Early-return only if we *don't* have reference filters.
         // For reference filters, we still want the FilterEffect graph built
@@ -6892,24 +6876,8 @@ void RenderLayer::updateOrRemoveFilterEffectRenderer()
             return;
     }
     
-    FilterInfo& filterInfo = FilterInfo::get(*this);
-    if (!filterInfo.filter()) {
-        auto cssFilter = CSSFilter::create();
-        cssFilter->setFilterScale(page().deviceScaleFactor());
-        cssFilter->setRenderingMode(renderer().settings().acceleratedFiltersEnabled() ? Accelerated : Unaccelerated);
-        filterInfo.setFilter(WTFMove(cssFilter));
-        
-        // We can optimize away code paths in other places if we know that there are no software filters.
-        renderer().view().setHasSoftwareFilters(true);
-    } else if (filterInfo.filter()->filterScale() != page().deviceScaleFactor()) {
-        filterInfo.filter()->setFilterScale(page().deviceScaleFactor());
-        filterInfo.filter()->clearIntermediateResults();
-    }
-
-    // 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.filter()->build(renderer(), renderer().style().filter(), FilterConsumer::FilterProperty))
-        filterInfo.setFilter(nullptr);
+    ensureLayerFilters();
+    m_filters->buildFilter(renderer(), page().deviceScaleFactor(), renderer().settings().acceleratedFiltersEnabled() ? Accelerated : Unaccelerated);
 }
 
 void RenderLayer::filterNeedsRepaint()
index 820ab45..eb683cc 100644 (file)
@@ -63,8 +63,6 @@ namespace WebCore {
 class CSSFilter;
 class ClipRects;
 class ClipRectsCache;
-class FilterEffectRendererHelper;
-class FilterOperations;
 class HitTestRequest;
 class HitTestResult;
 class HitTestingTransformState;
@@ -72,6 +70,7 @@ class RenderFragmentedFlow;
 class RenderGeometryMap;
 class RenderLayerBacking;
 class RenderLayerCompositor;
+class RenderLayerFilters;
 class RenderMarquee;
 class RenderReplica;
 class RenderScrollbarPart;
@@ -125,6 +124,7 @@ class RenderLayer final : public ScrollableArea {
     WTF_MAKE_FAST_ALLOCATED;
 public:
     friend class RenderReplica;
+    friend class RenderLayerFilters;
 
     explicit RenderLayer(RenderLayerModelObject&);
     virtual ~RenderLayer();
@@ -645,7 +645,7 @@ public:
     bool hasNotIsolatedBlendingDescendantsStatusDirty() const { return false; }
 #endif
 
-    bool isComposited() const { return m_backing != 0; }
+    bool isComposited() const { return m_backing != nullptr; }
     bool hasCompositingDescendant() const { return m_hasCompositingDescendant; }
     bool hasCompositedMask() const;
     RenderLayerBacking* backing() const { return m_backing.get(); }
@@ -679,7 +679,6 @@ public:
 
     bool paintsWithFilters() const;
     bool requiresFullLayerImageForFilters() const;
-    CSSFilter* filter() const;
 
 #if !ASSERT_DISABLED
     bool layerListMutationAllowed() const { return m_layerListMutationAllowed; }
@@ -823,11 +822,12 @@ private:
 
     bool setupClipPath(GraphicsContext&, const LayerPaintingInfo&, const LayoutSize& offsetFromRoot, LayoutRect& rootRelativeBounds, bool& rootRelativeBoundsComputed);
 
-    class FilterInfo;
-    std::pair<FilterInfo*, std::unique_ptr<FilterEffectRendererHelper>> filterPainter(GraphicsContext&, OptionSet<PaintLayerFlag>) const;
-    bool hasFilterThatIsPainting(GraphicsContext&, OptionSet<PaintLayerFlag>) const;
-    std::unique_ptr<FilterEffectRendererHelper> setupFilters(GraphicsContext&, LayerPaintingInfo&, OptionSet<PaintLayerFlag>, const LayoutSize& offsetFromRoot, LayoutRect& rootRelativeBounds, bool& rootRelativeBoundsComputed);
-    void applyFilters(FilterEffectRendererHelper*, GraphicsContext& originalContext, const LayerPaintingInfo&, const LayerFragments&);
+    void ensureLayerFilters();
+    void clearLayerFilters();
+
+    RenderLayerFilters* filtersForPainting(GraphicsContext&, OptionSet<PaintLayerFlag>) const;
+    GraphicsContext* setupFilters(GraphicsContext& destinationContext, LayerPaintingInfo&, OptionSet<PaintLayerFlag>, const LayoutSize& offsetFromRoot, LayoutRect& rootRelativeBounds, bool& rootRelativeBoundsComputed);
+    void applyFilters(GraphicsContext& originalContext, const LayerPaintingInfo&, const LayerFragments&);
 
     void paintLayer(GraphicsContext&, const LayerPaintingInfo&, OptionSet<PaintLayerFlag>);
     void paintLayerContentsAndReflection(GraphicsContext&, const LayerPaintingInfo&, OptionSet<PaintLayerFlag>);
@@ -955,8 +955,8 @@ private:
     bool paintingInsideReflection() const { return m_paintingInsideReflection; }
     void setPaintingInsideReflection(bool b) { m_paintingInsideReflection = b; }
 
-    void updateOrRemoveFilterClients();
-    void updateOrRemoveFilterEffectRenderer();
+    void updateFiltersAfterStyleChange();
+    void updateFilterPaintingStrategy();
 
 #if ENABLE(CSS_COMPOSITING)
     void updateAncestorChainHasBlendingDescendants();
@@ -1092,8 +1092,6 @@ private:
     bool m_layerListMutationAllowed : 1;
 #endif
 
-    bool m_hasFilterInfo : 1;
-
 #if ENABLE(CSS_COMPOSITING)
     unsigned m_blendMode : 5;
     bool m_hasNotIsolatedCompositedBlendingDescendants : 1;
@@ -1163,6 +1161,7 @@ private:
 
     IntRect m_blockSelectionGapsBounds;
 
+    std::unique_ptr<RenderLayerFilters> m_filters;
     std::unique_ptr<RenderLayerBacking> m_backing;
     
     PaintFrequencyTracker m_paintFrequencyTracker;
diff --git a/Source/WebCore/rendering/RenderLayerFilterInfo.cpp b/Source/WebCore/rendering/RenderLayerFilterInfo.cpp
deleted file mode 100644 (file)
index ba16580..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- * Copyright (C) 2013 Apple Inc. 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"
-#include "RenderLayerFilterInfo.h"
-
-#include "CachedSVGDocument.h"
-#include "CachedSVGDocumentReference.h"
-#include "FilterEffectRenderer.h"
-#include "RenderSVGResourceFilter.h"
-#include <wtf/NeverDestroyed.h>
-
-namespace WebCore {
-
-HashMap<const RenderLayer*, std::unique_ptr<RenderLayer::FilterInfo>>& RenderLayer::FilterInfo::map()
-{
-    static NeverDestroyed<HashMap<const RenderLayer*, std::unique_ptr<FilterInfo>>> map;
-    return map;
-}
-
-RenderLayer::FilterInfo* RenderLayer::FilterInfo::getIfExists(const RenderLayer& layer)
-{
-    ASSERT(layer.m_hasFilterInfo == map().contains(&layer));
-
-    return layer.m_hasFilterInfo ? map().get(&layer) : nullptr;
-}
-
-RenderLayer::FilterInfo& RenderLayer::FilterInfo::get(RenderLayer& layer)
-{
-    ASSERT(layer.m_hasFilterInfo == map().contains(&layer));
-
-    auto& info = map().add(&layer, nullptr).iterator->value;
-    if (!info) {
-        info = std::make_unique<FilterInfo>(layer);
-        layer.m_hasFilterInfo = true;
-    }
-    return *info;
-}
-
-void RenderLayer::FilterInfo::remove(RenderLayer& layer)
-{
-    ASSERT(layer.m_hasFilterInfo == map().contains(&layer));
-    if (!layer.m_hasFilterInfo)
-        return;
-
-    map().remove(&layer);
-    layer.m_hasFilterInfo = false;
-}
-
-RenderLayer::FilterInfo::FilterInfo(RenderLayer& layer)
-    : m_layer(layer)
-{
-}
-
-RenderLayer::FilterInfo::~FilterInfo()
-{
-    removeReferenceFilterClients();
-}
-
-void RenderLayer::FilterInfo::setFilter(RefPtr<CSSFilter>&& filter)
-{
-    m_filter = filter;
-}
-
-void RenderLayer::FilterInfo::notifyFinished(CachedResource&)
-{
-    m_layer.filterNeedsRepaint();
-}
-
-void RenderLayer::FilterInfo::updateReferenceFilterClients(const FilterOperations& operations)
-{
-    removeReferenceFilterClients();
-    for (auto& operation : operations.operations()) {
-        if (!is<ReferenceFilterOperation>(*operation))
-            continue;
-        auto& referenceOperation = downcast<ReferenceFilterOperation>(*operation);
-        auto* documentReference = referenceOperation.cachedSVGDocumentReference();
-        if (auto* cachedSVGDocument = documentReference ? documentReference->document() : nullptr) {
-            // Reference is external; wait for notifyFinished().
-            cachedSVGDocument->addClient(*this);
-            m_externalSVGReferences.append(cachedSVGDocument);
-        } else {
-            // Reference is internal; add layer as a client so we can trigger filter repaint on SVG attribute change.
-            auto* filterElement = m_layer.renderer().document().getElementById(referenceOperation.fragment());
-            if (!filterElement)
-                continue;
-            auto* renderer = filterElement->renderer();
-            if (!is<RenderSVGResourceFilter>(renderer))
-                continue;
-            downcast<RenderSVGResourceFilter>(*renderer).addClientRenderLayer(&m_layer);
-            m_internalSVGReferences.append(filterElement);
-        }
-    }
-}
-
-void RenderLayer::FilterInfo::removeReferenceFilterClients()
-{
-    for (auto& resourceHandle : m_externalSVGReferences)
-        resourceHandle->removeClient(*this);
-
-    m_externalSVGReferences.clear();
-
-    for (auto& filterElement : m_internalSVGReferences) {
-        if (auto* renderer = filterElement->renderer())
-            downcast<RenderSVGResourceContainer>(*renderer).removeClientRenderLayer(&m_layer);
-    }
-    m_internalSVGReferences.clear();
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderLayerFilters.cpp b/Source/WebCore/rendering/RenderLayerFilters.cpp
new file mode 100644 (file)
index 0000000..77d99c9
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
+ * Copyright (C) 2013 Apple Inc. 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"
+#include "RenderLayerFilters.h"
+
+#include "CachedSVGDocument.h"
+#include "CachedSVGDocumentReference.h"
+#include "RenderSVGResourceFilter.h"
+#include <wtf/NeverDestroyed.h>
+
+namespace WebCore {
+
+RenderLayerFilters::RenderLayerFilters(RenderLayer& layer)
+    : m_layer(layer)
+{
+    WTFLogAlways("RenderLayerFilters %p ctor", this);
+}
+
+RenderLayerFilters::~RenderLayerFilters()
+{
+    WTFLogAlways("RenderLayerFilters %p dtor", this);
+    removeReferenceFilterClients();
+}
+
+void RenderLayerFilters::setFilter(RefPtr<CSSFilter>&& filter)
+{
+    m_filter = WTFMove(filter);
+}
+
+bool RenderLayerFilters::hasFilterThatMovesPixels() const
+{
+    return m_filter && m_filter->hasFilterThatMovesPixels();
+}
+
+bool RenderLayerFilters::hasFilterThatShouldBeRestrictedBySecurityOrigin() const
+{
+    return m_filter && m_filter->hasFilterThatShouldBeRestrictedBySecurityOrigin();
+}
+
+void RenderLayerFilters::notifyFinished(CachedResource&)
+{
+    m_layer.filterNeedsRepaint();
+}
+
+void RenderLayerFilters::updateReferenceFilterClients(const FilterOperations& operations)
+{
+    removeReferenceFilterClients();
+
+    for (auto& operation : operations.operations()) {
+        if (!is<ReferenceFilterOperation>(*operation))
+            continue;
+
+        auto& referenceOperation = downcast<ReferenceFilterOperation>(*operation);
+        auto* documentReference = referenceOperation.cachedSVGDocumentReference();
+        if (auto* cachedSVGDocument = documentReference ? documentReference->document() : nullptr) {
+            // Reference is external; wait for notifyFinished().
+            cachedSVGDocument->addClient(*this);
+            m_externalSVGReferences.append(cachedSVGDocument);
+        } else {
+            // Reference is internal; add layer as a client so we can trigger filter repaint on SVG attribute change.
+            auto* filterElement = m_layer.renderer().document().getElementById(referenceOperation.fragment());
+            if (!filterElement)
+                continue;
+            auto* renderer = filterElement->renderer();
+            if (!is<RenderSVGResourceFilter>(renderer))
+                continue;
+            downcast<RenderSVGResourceFilter>(*renderer).addClientRenderLayer(&m_layer);
+            m_internalSVGReferences.append(filterElement);
+        }
+    }
+}
+
+void RenderLayerFilters::removeReferenceFilterClients()
+{
+    for (auto& resourceHandle : m_externalSVGReferences)
+        resourceHandle->removeClient(*this);
+
+    m_externalSVGReferences.clear();
+
+    for (auto& filterElement : m_internalSVGReferences) {
+        if (auto* renderer = filterElement->renderer())
+            downcast<RenderSVGResourceContainer>(*renderer).removeClientRenderLayer(&m_layer);
+    }
+    m_internalSVGReferences.clear();
+}
+
+void RenderLayerFilters::buildFilter(RenderElement& renderer, float scaleFactor, RenderingMode renderingMode)
+{
+    if (!m_filter) {
+        m_filter = CSSFilter::create();
+        m_filter->setFilterScale(scaleFactor);
+        m_filter->setRenderingMode(renderingMode);
+    } else if (m_filter->filterScale() != scaleFactor) {
+        m_filter->setFilterScale(scaleFactor);
+        m_filter->clearIntermediateResults();
+    }
+
+    // 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.
+    // FIXME: this rebuilds the entire effects chain even if the filter style didn't change.
+    if (!m_filter->build(renderer, renderer.style().filter(), FilterConsumer::FilterProperty))
+        m_filter = nullptr;
+}
+
+GraphicsContext* RenderLayerFilters::beginFilterEffect(GraphicsContext& destinationContext, const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect, const LayoutRect& layerRepaintRect)
+{
+    if (!m_filter)
+        return nullptr;
+
+    auto& filter = *m_filter;
+    auto filterSourceRect = filter.computeSourceImageRectForDirtyRect(filterBoxRect, dirtyRect);
+    if (filterSourceRect.isEmpty())
+        return nullptr;
+
+    bool hasUpdatedBackingStore = filter.updateBackingStoreRect(filterSourceRect);
+    if (!filter.hasFilterThatMovesPixels())
+        m_repaintRect = dirtyRect;
+    else {
+        if (hasUpdatedBackingStore)
+            m_repaintRect = filterSourceRect;
+        else {
+            m_repaintRect = dirtyRect;
+            m_repaintRect.unite(layerRepaintRect);
+            m_repaintRect.intersect(filterSourceRect);
+        }
+    }
+    m_paintOffset = filterSourceRect.location();
+    resetDirtySourceRect();
+
+    filter.allocateBackingStoreIfNeeded(destinationContext);
+    auto* sourceGraphicsContext = filter.inputContext();
+    if (!sourceGraphicsContext || filter.filterRegion().isEmpty() || ImageBuffer::sizeNeedsClamping(filter.filterRegion().size()))
+        return nullptr;
+
+    // Translate the context so that the contents of the layer is captured in the offscreen memory buffer.
+    sourceGraphicsContext->save();
+    sourceGraphicsContext->translate(-m_paintOffset);
+    sourceGraphicsContext->clearRect(m_repaintRect);
+    sourceGraphicsContext->clip(m_repaintRect);
+
+    return sourceGraphicsContext;
+}
+
+void RenderLayerFilters::applyFilterEffect(GraphicsContext& destinationContext)
+{
+    ASSERT(m_filter->inputContext());
+
+    LOG_WITH_STREAM(Filters, stream << "\nRenderLayerFilters " << this << " applyFilterEffect");
+
+    auto& filter = *m_filter;
+    filter.inputContext()->restore();
+
+    filter.apply();
+
+    // Get the filtered output and draw it in place.
+    LayoutRect destRect = filter.outputRect();
+    destRect.move(m_paintOffset.x(), m_paintOffset.y());
+
+    if (auto* outputBuffer = filter.output())
+        destinationContext.drawImageBuffer(*outputBuffer, snapRectToDevicePixels(destRect, m_layer.renderer().document().deviceScaleFactor()));
+
+    filter.clearIntermediateResults();
+
+    LOG_WITH_STREAM(Filters, stream << "RenderLayerFilters " << this << " applyFilterEffect done\n");
+}
+
+} // namespace WebCore
@@ -38,41 +38,49 @@ namespace WebCore {
 
 class CachedSVGDocument;
 class Element;
+class FilterOperations;
 
-class RenderLayer::FilterInfo final : private CachedSVGDocumentClient {
-#if !COMPILER(MSVC)
+class RenderLayerFilters final : private CachedSVGDocumentClient {
     WTF_MAKE_FAST_ALLOCATED;
-#endif
 public:
-    static FilterInfo& get(RenderLayer&);
-    static FilterInfo* getIfExists(const RenderLayer&);
-    static void remove(RenderLayer&);
-
-    explicit FilterInfo(RenderLayer&);
-    virtual ~FilterInfo();
+    explicit RenderLayerFilters(RenderLayer&);
+    virtual ~RenderLayerFilters();
 
     const LayoutRect& dirtySourceRect() const { return m_dirtySourceRect; }
     void expandDirtySourceRect(const LayoutRect& rect) { m_dirtySourceRect.unite(rect); }
-    void resetDirtySourceRect() { m_dirtySourceRect = LayoutRect(); }
 
     CSSFilter* filter() const { return m_filter.get(); }
     void setFilter(RefPtr<CSSFilter>&&);
+    
+    bool hasFilterThatMovesPixels() const;
+    bool hasFilterThatShouldBeRestrictedBySecurityOrigin() const;
 
     void updateReferenceFilterClients(const FilterOperations&);
     void removeReferenceFilterClients();
 
+    void buildFilter(RenderElement&, float scaleFactor, RenderingMode);
+
+    // Per render
+    LayoutRect repaintRect() const { return m_repaintRect; }
+
+    GraphicsContext* beginFilterEffect(GraphicsContext& destinationContext, const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect, const LayoutRect& layerRepaintRect);
+    void applyFilterEffect(GraphicsContext& destinationContext);
+
 private:
     void notifyFinished(CachedResource&) final;
-
-    static HashMap<const RenderLayer*, std::unique_ptr<FilterInfo>>& map();
+    void resetDirtySourceRect() { m_dirtySourceRect = LayoutRect(); }
 
     RenderLayer& m_layer;
 
-    RefPtr<CSSFilter> m_filter;
-    LayoutRect m_dirtySourceRect;
-
     Vector<RefPtr<Element>> m_internalSVGReferences;
     Vector<CachedResourceHandle<CachedSVGDocument>> m_externalSVGReferences;
+
+    RefPtr<CSSFilter> m_filter;
+    LayoutRect m_dirtySourceRect;
+    
+    // Data used per paint
+    LayoutPoint m_paintOffset;
+    LayoutRect m_repaintRect;
 };
 
 } // namespace WebCore