Bug 948265 - [CSS Filters] Make nsSVGIntegrationUtils and nsSVGUtils call nsSVGFilterInstance directly instead of through nsSVGFilterFrame. r=roc
authorMax Vujovic <mvujovic@adobe.com>
Thu, 06 Feb 2014 10:42:35 -0800
changeset 184768 5d252c7bbea4fe1b66f1d2aac81530ba93a64d4b
parent 184767 4e44b26f3c6705259c85e7d98af89df42634b03e
child 184769 e85f83f352deed1d6be2ddf2a820a9844a7bf285
push id3503
push userraliiev@mozilla.com
push dateMon, 28 Apr 2014 18:51:11 +0000
treeherdermozilla-beta@c95ac01e332e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs948265
milestone30.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 948265 - [CSS Filters] Make nsSVGIntegrationUtils and nsSVGUtils call nsSVGFilterInstance directly instead of through nsSVGFilterFrame. r=roc
layout/svg/nsSVGFilterFrame.cpp
layout/svg/nsSVGFilterFrame.h
layout/svg/nsSVGFilterInstance.cpp
layout/svg/nsSVGFilterInstance.h
layout/svg/nsSVGIntegrationUtils.cpp
layout/svg/nsSVGUtils.cpp
--- a/layout/svg/nsSVGFilterFrame.cpp
+++ b/layout/svg/nsSVGFilterFrame.cpp
@@ -198,111 +198,16 @@ nsSVGFilterFrame::AttributeChanged(int32
     mNoHRefURI = false;
     // And update whoever references us
     nsSVGEffects::InvalidateDirectRenderingObservers(this);
   }
   return nsSVGFilterFrameBase::AttributeChanged(aNameSpaceID,
                                                 aAttribute, aModType);
 }
 
-nsresult
-nsSVGFilterFrame::PaintFilteredFrame(nsRenderingContext *aContext,
-                                     nsIFrame *aFilteredFrame,
-                                     nsSVGFilterPaintCallback *aPaintCallback,
-                                     const nsRect *aDirtyArea,
-                                     nsIFrame* aTransformRoot)
-{
-  nsSVGFilterInstance instance(aFilteredFrame, this, aPaintCallback,
-                               aDirtyArea, nullptr, nullptr, nullptr,
-                               aTransformRoot);
-  if (!instance.IsInitialized()) {
-    return NS_OK;
-  }
-  return instance.Render(aContext->ThebesContext());
-}
-
-static nsRect
-TransformFilterSpaceToFrameSpace(nsSVGFilterInstance *aInstance,
-                                 nsIntRect *aRect)
-{
-  if (aRect->IsEmpty()) {
-    return nsRect();
-  }
-  gfxMatrix m = aInstance->GetFilterSpaceToFrameSpaceInCSSPxTransform();
-  gfxRect r(aRect->x, aRect->y, aRect->width, aRect->height);
-  r = m.TransformBounds(r);
-  return nsLayoutUtils::RoundGfxRectToAppRect(r, aInstance->AppUnitsPerCSSPixel());
-}
-
-nsRect
-nsSVGFilterFrame::GetPostFilterDirtyArea(nsIFrame *aFilteredFrame,
-                                         const nsRect& aPreFilterDirtyRect)
-{
-  if (aPreFilterDirtyRect.IsEmpty()) {
-    return nsRect();
-  }
-
-  nsSVGFilterInstance instance(aFilteredFrame, this, nullptr, nullptr,
-                               &aPreFilterDirtyRect);
-  if (!instance.IsInitialized()) {
-    return nsRect();
-  }
-  // We've passed in the source's dirty area so the instance knows about it.
-  // Now we can ask the instance to compute the area of the filter output
-  // that's dirty.
-  nsIntRect dirtyRect;
-  nsresult rv = instance.ComputePostFilterDirtyRect(&dirtyRect);
-  if (NS_SUCCEEDED(rv)) {
-    return TransformFilterSpaceToFrameSpace(&instance, &dirtyRect);
-  }
-  return nsRect();
-}
-
-nsRect
-nsSVGFilterFrame::GetPreFilterNeededArea(nsIFrame *aFilteredFrame,
-                                         const nsRect& aPostFilterDirtyRect)
-{
-  nsSVGFilterInstance instance(aFilteredFrame, this, nullptr,
-                               &aPostFilterDirtyRect);
-  if (!instance.IsInitialized()) {
-    return nsRect();
-  }
-  // Now we can ask the instance to compute the area of the source
-  // that's needed.
-  nsIntRect neededRect;
-  nsresult rv = instance.ComputeSourceNeededRect(&neededRect);
-  if (NS_SUCCEEDED(rv)) {
-    return TransformFilterSpaceToFrameSpace(&instance, &neededRect);
-  }
-  return nsRect();
-}
-
-nsRect
-nsSVGFilterFrame::GetPostFilterBounds(nsIFrame *aFilteredFrame,
-                                      const gfxRect *aOverrideBBox,
-                                      const nsRect *aPreFilterBounds)
-{
-  MOZ_ASSERT(!(aFilteredFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT) ||
-             !(aFilteredFrame->GetStateBits() & NS_FRAME_IS_NONDISPLAY),
-             "Non-display SVG do not maintain visual overflow rects");
-
-  nsSVGFilterInstance instance(aFilteredFrame, this, nullptr, nullptr,
-                               aPreFilterBounds, aPreFilterBounds,
-                               aOverrideBBox);
-  if (!instance.IsInitialized()) {
-    return nsRect();
-  }
-  nsIntRect bbox;
-  nsresult rv = instance.ComputePostFilterExtents(&bbox);
-  if (NS_SUCCEEDED(rv)) {
-    return TransformFilterSpaceToFrameSpace(&instance, &bbox);
-  }
-  return nsRect();
-}
-
 #ifdef DEBUG
 void
 nsSVGFilterFrame::Init(nsIContent* aContent,
                        nsIFrame* aParent,
                        nsIFrame* aPrevInFlow)
 {
   NS_ASSERTION(aContent->IsSVG(nsGkAtoms::filter),
                "Content is not an SVG filter");
--- a/layout/svg/nsSVGFilterFrame.h
+++ b/layout/svg/nsSVGFilterFrame.h
@@ -52,58 +52,16 @@ public:
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) MOZ_OVERRIDE {}
 
   NS_IMETHOD AttributeChanged(int32_t         aNameSpaceID,
                               nsIAtom*        aAttribute,
                               int32_t         aModType) MOZ_OVERRIDE;
 
-  /**
-   * Paint the given filtered frame.
-   * @param aDirtyArea The area than needs to be painted, in aFilteredFrame's
-   *   frame space (i.e. relative to its origin, the top-left corner of its
-   *   border box).
-   */
-  nsresult PaintFilteredFrame(nsRenderingContext *aContext,
-                              nsIFrame *aFilteredFrame,
-                              nsSVGFilterPaintCallback *aPaintCallback,
-                              const nsRect* aDirtyArea,
-                              nsIFrame* aTransformRoot);
-
-  /**
-   * Returns the post-filter area that could be dirtied when the given
-   * pre-filter area of aFilteredFrame changes.
-   * @param aPreFilterDirtyRect The pre-filter area of aFilteredFrame that has
-   *   changed, relative to aFilteredFrame, in app units.
-   */
-  nsRect GetPostFilterDirtyArea(nsIFrame *aFilteredFrame,
-                                const nsRect& aPreFilterDirtyRect);
-
-  /**
-   * Returns the pre-filter area that is needed from aFilteredFrame when the
-   * given post-filter area needs to be repainted.
-   * @param aPostFilterDirtyRect The post-filter area that is dirty, relative
-   *   to aFilteredFrame, in app units.
-   */
-  nsRect GetPreFilterNeededArea(nsIFrame *aFilteredFrame,
-                                const nsRect& aPostFilterDirtyRect);
-
-  /**
-   * Returns the post-filter visual overflow rect (paint bounds) of
-   * aFilteredFrame.
-   * @param aOverrideBBox A user space rect, in user units, that should be used
-   *   as aFilteredFrame's bbox ('bbox' is a specific SVG term), if non-null.
-   * @param aPreFilterBounds The pre-filter visual overflow rect of
-   *   aFilteredFrame, if non-null.
-   */
-  nsRect GetPostFilterBounds(nsIFrame *aFilteredFrame,
-                             const gfxRect *aOverrideBBox = nullptr,
-                             const nsRect *aPreFilterBounds = nullptr);
-
 #ifdef DEBUG
   virtual void Init(nsIContent*      aContent,
                     nsIFrame*        aParent,
                     nsIFrame*        aPrevInFlow) MOZ_OVERRIDE;
 #endif
 
   /**
    * Get the "type" of the frame
--- a/layout/svg/nsSVGFilterInstance.cpp
+++ b/layout/svg/nsSVGFilterInstance.cpp
@@ -18,16 +18,102 @@
 #include "SVGContentUtils.h"
 #include "FilterSupport.h"
 #include "gfx2DGlue.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::gfx;
 
+nsresult
+nsSVGFilterInstance::PaintFilteredFrame(nsSVGFilterFrame* aFilterFrame,
+                                        nsRenderingContext *aContext,
+                                        nsIFrame *aFilteredFrame,
+                                        nsSVGFilterPaintCallback *aPaintCallback,
+                                        const nsRect *aDirtyArea,
+                                        nsIFrame* aTransformRoot)
+{
+  nsSVGFilterInstance instance(aFilteredFrame, aFilterFrame, aPaintCallback,
+                               aDirtyArea, nullptr, nullptr, nullptr,
+                               aTransformRoot);
+  if (!instance.IsInitialized()) {
+    return NS_OK;
+  }
+  return instance.Render(aContext->ThebesContext());
+}
+
+nsRect
+nsSVGFilterInstance::GetPostFilterDirtyArea(nsSVGFilterFrame* aFilterFrame,
+                                            nsIFrame *aFilteredFrame,
+                                            const nsRect& aPreFilterDirtyRect)
+{
+  if (aPreFilterDirtyRect.IsEmpty()) {
+    return nsRect();
+  }
+
+  nsSVGFilterInstance instance(aFilteredFrame, aFilterFrame, nullptr, nullptr,
+                               &aPreFilterDirtyRect);
+  if (!instance.IsInitialized()) {
+    return nsRect();
+  }
+  // We've passed in the source's dirty area so the instance knows about it.
+  // Now we can ask the instance to compute the area of the filter output
+  // that's dirty.
+  nsRect dirtyRect;
+  nsresult rv = instance.ComputePostFilterDirtyRect(&dirtyRect);
+  if (NS_SUCCEEDED(rv)) {
+    return dirtyRect;
+  }
+  return nsRect();
+}
+
+nsRect
+nsSVGFilterInstance::GetPreFilterNeededArea(nsSVGFilterFrame* aFilterFrame,
+                                            nsIFrame *aFilteredFrame,
+                                            const nsRect& aPostFilterDirtyRect)
+{
+  nsSVGFilterInstance instance(aFilteredFrame, aFilterFrame, nullptr,
+                               &aPostFilterDirtyRect);
+  if (!instance.IsInitialized()) {
+    return nsRect();
+  }
+  // Now we can ask the instance to compute the area of the source
+  // that's needed.
+  nsRect neededRect;
+  nsresult rv = instance.ComputeSourceNeededRect(&neededRect);
+  if (NS_SUCCEEDED(rv)) {
+    return neededRect;
+  }
+  return nsRect();
+}
+
+nsRect
+nsSVGFilterInstance::GetPostFilterBounds(nsSVGFilterFrame* aFilterFrame,
+                                         nsIFrame *aFilteredFrame,
+                                         const gfxRect *aOverrideBBox,
+                                         const nsRect *aPreFilterBounds)
+{
+  MOZ_ASSERT(!(aFilteredFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT) ||
+             !(aFilteredFrame->GetStateBits() & NS_FRAME_IS_NONDISPLAY),
+             "Non-display SVG do not maintain visual overflow rects");
+
+  nsSVGFilterInstance instance(aFilteredFrame, aFilterFrame, nullptr, nullptr,
+                               aPreFilterBounds, aPreFilterBounds,
+                               aOverrideBBox);
+  if (!instance.IsInitialized()) {
+    return nsRect();
+  }
+  nsRect bbox;
+  nsresult rv = instance.ComputePostFilterExtents(&bbox);
+  if (NS_SUCCEEDED(rv)) {
+    return bbox;
+  }
+  return nsRect();
+}
+
 nsSVGFilterInstance::nsSVGFilterInstance(nsIFrame *aTargetFrame,
                                          nsSVGFilterFrame *aFilterFrame,
                                          nsSVGFilterPaintCallback *aPaintCallback,
                                          const nsRect *aPostFilterDirtyRect,
                                          const nsRect *aPreFilterDirtyRect,
                                          const nsRect *aPreFilterVisualOverflowRectOverride,
                                          const gfxRect *aOverrideBBox,
                                          nsIFrame* aTransformRoot) :
@@ -659,19 +745,19 @@ nsSVGFilterInstance::Render(gfxContext* 
   } else {
     dt->SetTransform(oldDTMatrix);
   }
 
   return NS_OK;
 }
 
 nsresult
-nsSVGFilterInstance::ComputePostFilterDirtyRect(nsIntRect* aPostFilterDirtyRect)
+nsSVGFilterInstance::ComputePostFilterDirtyRect(nsRect* aPostFilterDirtyRect)
 {
-  *aPostFilterDirtyRect = nsIntRect();
+  *aPostFilterDirtyRect = nsRect();
   if (mPreFilterDirtyRect.IsEmpty()) {
     return NS_OK;
   }
 
   nsresult rv = BuildPrimitives();
   if (NS_FAILED(rv))
     return rv;
 
@@ -680,24 +766,25 @@ nsSVGFilterInstance::ComputePostFilterDi
     return NS_OK;
   }
 
   IntRect filterSpaceBounds = ToIntRect(mFilterSpaceBounds);
   FilterDescription filter(mPrimitiveDescriptions, filterSpaceBounds);
   nsIntRegion resultChangeRegion =
     FilterSupport::ComputeResultChangeRegion(filter,
       mPreFilterDirtyRect, nsIntRegion(), nsIntRegion());
-  *aPostFilterDirtyRect = resultChangeRegion.GetBounds();
+  *aPostFilterDirtyRect =
+    FilterSpaceToFrameSpace(resultChangeRegion.GetBounds());
   return NS_OK;
 }
 
 nsresult
-nsSVGFilterInstance::ComputePostFilterExtents(nsIntRect* aPostFilterExtents)
+nsSVGFilterInstance::ComputePostFilterExtents(nsRect* aPostFilterExtents)
 {
-  *aPostFilterExtents = nsIntRect();
+  *aPostFilterExtents = nsRect();
 
   nsresult rv = BuildPrimitives();
   if (NS_FAILED(rv))
     return rv;
 
   if (mPrimitiveDescriptions.IsEmpty()) {
     return NS_OK;
   }
@@ -709,34 +796,34 @@ nsSVGFilterInstance::ComputePostFilterEx
   if (!gfxUtils::GfxRectToIntRect(sourceBounds, &sourceBoundsInt))
     return NS_ERROR_FAILURE;
   sourceBoundsInt.UnionRect(sourceBoundsInt, mTargetBounds);
 
   IntRect filterSpaceBounds = ToIntRect(mFilterSpaceBounds);
   FilterDescription filter(mPrimitiveDescriptions, filterSpaceBounds);
   nsIntRegion postFilterExtents =
     FilterSupport::ComputePostFilterExtents(filter, sourceBoundsInt);
-  *aPostFilterExtents = postFilterExtents.GetBounds();
+  *aPostFilterExtents = FilterSpaceToFrameSpace(postFilterExtents.GetBounds());
   return NS_OK;
 }
 
 nsresult
-nsSVGFilterInstance::ComputeSourceNeededRect(nsIntRect* aDirty)
+nsSVGFilterInstance::ComputeSourceNeededRect(nsRect* aDirty)
 {
   nsresult rv = BuildPrimitives();
   if (NS_FAILED(rv))
     return rv;
 
   if (mPrimitiveDescriptions.IsEmpty()) {
     // Nothing should be rendered, so nothing is needed.
     return NS_OK;
   }
 
   ComputeNeededBoxes();
-  *aDirty = mSourceGraphic.mNeededBounds;
+  *aDirty = FilterSpaceToFrameSpace(mSourceGraphic.mNeededBounds);
 
   return NS_OK;
 }
 
 nsIntRect
 nsSVGFilterInstance::FrameSpaceToFilterSpace(const nsRect* aRect) const
 {
   nsIntRect rect = mFilterSpaceBounds;
@@ -752,16 +839,27 @@ nsSVGFilterInstance::FrameSpaceToFilterS
     nsIntRect intRect;
     if (gfxUtils::GfxRectToIntRect(rectInFilterSpace, &intRect)) {
       rect = intRect;
     }
   }
   return rect;
 }
 
+nsRect
+nsSVGFilterInstance::FilterSpaceToFrameSpace(const nsIntRect& aRect) const
+{
+  if (aRect.IsEmpty()) {
+    return nsRect();
+  }
+  gfxRect r(aRect.x, aRect.y, aRect.width, aRect.height);
+  r = mFilterSpaceToFrameSpaceInCSSPxTransform.TransformBounds(r);
+  return nsLayoutUtils::RoundGfxRectToAppRect(r, mAppUnitsPerCSSPx);
+}
+
 gfxMatrix
 nsSVGFilterInstance::GetUserSpaceToFrameSpaceInCSSPxTransform() const
 {
   gfxMatrix userToFrameSpaceInCSSPx;
 
   if ((mTargetFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT)) {
     // As currently implemented by Mozilla for the purposes of filters, user
     // space is the coordinate system established by GetCanvasTM(), since
--- a/layout/svg/nsSVGFilterInstance.h
+++ b/layout/svg/nsSVGFilterInstance.h
@@ -55,16 +55,62 @@ class nsSVGFilterInstance
   typedef mozilla::gfx::Point3D Point3D;
   typedef mozilla::gfx::IntRect IntRect;
   typedef mozilla::gfx::SourceSurface SourceSurface;
   typedef mozilla::gfx::DrawTarget DrawTarget;
   typedef mozilla::gfx::FilterPrimitiveDescription FilterPrimitiveDescription;
 
 public:
   /**
+   * Paint the given filtered frame.
+   * @param aDirtyArea The area than needs to be painted, in aFilteredFrame's
+   *   frame space (i.e. relative to its origin, the top-left corner of its
+   *   border box).
+   */
+  static nsresult PaintFilteredFrame(nsSVGFilterFrame* aFilterFrame,
+                                     nsRenderingContext *aContext,
+                                     nsIFrame *aFilteredFrame,
+                                     nsSVGFilterPaintCallback *aPaintCallback,
+                                     const nsRect* aDirtyArea,
+                                     nsIFrame* aTransformRoot = nullptr);
+
+  /**
+   * Returns the post-filter area that could be dirtied when the given
+   * pre-filter area of aFilteredFrame changes.
+   * @param aPreFilterDirtyRect The pre-filter area of aFilteredFrame that has
+   *   changed, relative to aFilteredFrame, in app units.
+   */
+  static nsRect GetPostFilterDirtyArea(nsSVGFilterFrame* aFilterFrame,
+                                       nsIFrame *aFilteredFrame,
+                                       const nsRect& aPreFilterDirtyRect);
+
+  /**
+   * Returns the pre-filter area that is needed from aFilteredFrame when the
+   * given post-filter area needs to be repainted.
+   * @param aPostFilterDirtyRect The post-filter area that is dirty, relative
+   *   to aFilteredFrame, in app units.
+   */
+  static nsRect GetPreFilterNeededArea(nsSVGFilterFrame* aFilterFrame,
+                                       nsIFrame *aFilteredFrame,
+                                       const nsRect& aPostFilterDirtyRect);
+
+  /**
+   * Returns the post-filter visual overflow rect (paint bounds) of
+   * aFilteredFrame.
+   * @param aOverrideBBox A user space rect, in user units, that should be used
+   *   as aFilteredFrame's bbox ('bbox' is a specific SVG term), if non-null.
+   * @param aPreFilterBounds The pre-filter visual overflow rect of
+   *   aFilteredFrame, if non-null.
+   */
+  static nsRect GetPostFilterBounds(nsSVGFilterFrame* aFilterFrame,
+                                    nsIFrame *aFilteredFrame,
+                                    const gfxRect *aOverrideBBox = nullptr,
+                                    const nsRect *aPreFilterBounds = nullptr);
+
+  /**
    * @param aTargetFrame The frame of the filtered element under consideration.
    * @param aFilterFrame The frame of the SVG filter element.
    * @param aPaintCallback [optional] The callback that Render() should use to
    *   paint. Only required if you will call Render().
    * @param aPostFilterDirtyRect [optional] The bounds of the post-filter area
    *   that has to be repainted, in filter space. Only required if you will
    *   call ComputeSourceNeededRect() or Render().
    * @param aPreFilterDirtyRect [optional] The bounds of the pre-filter area of
@@ -113,41 +159,41 @@ public:
    * Draws the filter output into aContext. The area that
    * needs to be painted must have been specified before calling this method
    * by passing it as the aPostFilterDirtyRect argument to the
    * nsSVGFilterInstance constructor.
    */
   nsresult Render(gfxContext* aContext);
 
   /**
-   * Sets the aPostFilterDirtyRect outparam to the post-filter bounds in filter
+   * Sets the aPostFilterDirtyRect outparam to the post-filter bounds in frame
    * space of the area that would be dirtied by mTargetFrame when a given
    * pre-filter area of mTargetFrame is dirtied. The pre-filter area must have
    * been specified before calling this method by passing it as the
    * aPreFilterDirtyRect argument to the nsSVGFilterInstance constructor.
    */
-  nsresult ComputePostFilterDirtyRect(nsIntRect* aPostFilterDirtyRect);
+  nsresult ComputePostFilterDirtyRect(nsRect* aPostFilterDirtyRect);
 
   /**
-   * Sets the aPostFilterExtents outparam to the post-filter bounds in filter
+   * Sets the aPostFilterExtents outparam to the post-filter bounds in frame
    * space for the whole filter output. This is not necessarily equivalent to
    * the area that would be dirtied in the result when the entire pre-filter
    * area is dirtied, because some filter primitives can generate output
    * without any input.
    */
-  nsresult ComputePostFilterExtents(nsIntRect* aPostFilterExtents);
+  nsresult ComputePostFilterExtents(nsRect* aPostFilterExtents);
 
   /**
-   * Sets the aDirty outparam to the pre-filter bounds in filter space of the
+   * Sets the aDirty outparam to the pre-filter bounds in frame space of the
    * area of mTargetFrame that is needed in order to paint the filtered output
    * for a given post-filter dirtied area. The post-filter area must have been
    * specified before calling this method by passing it as the aPostFilterDirtyRect
    * argument to the nsSVGFilterInstance constructor.
    */
-  nsresult ComputeSourceNeededRect(nsIntRect* aDirty);
+  nsresult ComputeSourceNeededRect(nsRect* aDirty);
 
   float GetPrimitiveNumber(uint8_t aCtxType, const nsSVGNumber2 *aNumber) const
   {
     return GetPrimitiveNumber(aCtxType, aNumber->GetAnimValue());
   }
   float GetPrimitiveNumber(uint8_t aCtxType, const nsSVGNumberPair *aNumberPair,
                            nsSVGNumberPair::PairIndex aIndex) const
   {
@@ -264,16 +310,17 @@ private:
 
   /**
    * Converts an nsRect that is relative to a filtered frame's origin (i.e. the
    * top-left corner of its border box) into filter space.
    * Returns the entire filter region if aRect is null, or if the result is too
    * large to be stored in an nsIntRect.
    */
   nsIntRect FrameSpaceToFilterSpace(const nsRect* aRect) const;
+  nsRect FilterSpaceToFrameSpace(const nsIntRect& aRect) const;
 
   /**
    * Returns the transform from frame space to the coordinate space that
    * GetCanvasTM transforms to. "Frame space" is the origin of a frame, aka the
    * top-left corner of its border box, aka the top left corner of its mRect.
    */
   gfxMatrix GetUserSpaceToFrameSpaceInCSSPxTransform() const;
 
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -11,16 +11,17 @@
 #include "nsCSSAnonBoxes.h"
 #include "nsDisplayList.h"
 #include "nsLayoutUtils.h"
 #include "nsRenderingContext.h"
 #include "nsSVGClipPathFrame.h"
 #include "nsSVGEffects.h"
 #include "nsSVGElement.h"
 #include "nsSVGFilterFrame.h"
+#include "nsSVGFilterInstance.h"
 #include "nsSVGFilterPaintCallback.h"
 #include "nsSVGMaskFrame.h"
 #include "nsSVGPaintServerFrame.h"
 #include "nsSVGUtils.h"
 #include "FrameLayerBuilder.h"
 #include "BasicLayers.h"
 #include "mozilla/gfx/Point.h"
 
@@ -271,17 +272,17 @@ nsRect
     nsLayoutUtils::RectToGfxRect(
       GetPreEffectsVisualOverflowUnion(firstFrame, aFrame,
                                        aPreEffectsOverflowRect,
                                        firstFrameToUserSpace),
       aFrame->PresContext()->AppUnitsPerCSSPixel());
   overrideBBox.RoundOut();
 
   nsRect overflowRect =
-    filterFrame->GetPostFilterBounds(firstFrame, &overrideBBox);
+    nsSVGFilterInstance::GetPostFilterBounds(filterFrame, firstFrame, &overrideBBox);
 
   // Return overflowRect relative to aFrame, rather than "user space":
   return overflowRect - (aFrame->GetOffsetTo(firstFrame) + firstFrameToUserSpace);
 }
 
 nsIntRect
 nsSVGIntegrationUtils::AdjustInvalidAreaForSVGEffects(nsIFrame* aFrame,
                                                       const nsPoint& aToReferenceFrame,
@@ -322,18 +323,18 @@ nsSVGIntegrationUtils::AdjustInvalidArea
     aFrame->GetOffsetTo(firstFrame) + GetOffsetToUserSpace(firstFrame);
   // The initial rect was relative to the reference frame, so we need to
   // remove that offset to get a rect relative to the current frame.
   toUserSpace -= aToReferenceFrame;
   nsRect preEffectsRect = aInvalidRect.ToAppUnits(appUnitsPerDevPixel) + toUserSpace;
 
   // Adjust the dirty area for effects, and shift it back to being relative to
   // the reference frame.
-  nsRect result = filterFrame->GetPostFilterDirtyArea(firstFrame, preEffectsRect) -
-           toUserSpace;
+  nsRect result = nsSVGFilterInstance::GetPostFilterDirtyArea(filterFrame,
+    firstFrame, preEffectsRect) - toUserSpace;
   // Return the result, in pixels relative to the reference frame.
   return result.ToOutsidePixels(appUnitsPerDevPixel);
 }
 
 nsRect
 nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(nsIFrame* aFrame,
                                                        const nsRect& aDirtyRect)
 {
@@ -347,18 +348,18 @@ nsSVGIntegrationUtils::GetRequiredSource
     return aDirtyRect;
   
   // Convert aDirtyRect into "user space" in app units:
   nsPoint toUserSpace =
     aFrame->GetOffsetTo(firstFrame) + GetOffsetToUserSpace(firstFrame);
   nsRect postEffectsRect = aDirtyRect + toUserSpace;
 
   // Return ther result, relative to aFrame, not in user space:
-  return filterFrame->GetPreFilterNeededArea(firstFrame, postEffectsRect) -
-           toUserSpace;
+  return nsSVGFilterInstance::GetPreFilterNeededArea(filterFrame, firstFrame,
+    postEffectsRect) - toUserSpace;
 }
 
 bool
 nsSVGIntegrationUtils::HitTestFrameForEffects(nsIFrame* aFrame, const nsPoint& aPt)
 {
   nsIFrame* firstFrame =
     nsLayoutUtils::FirstContinuationOrIBSplitSibling(aFrame);
   // Convert aPt to user space:
@@ -512,17 +513,18 @@ nsSVGIntegrationUtils::PaintFramesWithEf
     clipPathFrame->ClipPaint(aCtx, aFrame, cssPxToDevPxMatrix);
   }
 
   /* Paint the child */
   if (filterFrame) {
     RegularFramePaintCallback callback(aBuilder, aLayerManager,
                                        offsetWithoutSVGGeomFramePos);
     nsRect dirtyRect = aDirtyRect - offset;
-    filterFrame->PaintFilteredFrame(aCtx, aFrame, &callback, &dirtyRect, nullptr);
+    nsSVGFilterInstance::PaintFilteredFrame(filterFrame, aCtx, aFrame,
+                                            &callback, &dirtyRect);
   } else {
     gfx->SetMatrix(matrixAutoSaveRestore.Matrix());
     aLayerManager->EndTransaction(FrameLayerBuilder::DrawThebesLayer, aBuilder);
     aCtx->Translate(offsetWithoutSVGGeomFramePos);
   }
 
   if (clipPathFrame && isTrivialClip) {
     gfx->Restore();
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -31,16 +31,17 @@
 #include "nsPresContext.h"
 #include "nsRenderingContext.h"
 #include "nsStyleCoord.h"
 #include "nsStyleStruct.h"
 #include "nsSVGClipPathFrame.h"
 #include "nsSVGContainerFrame.h"
 #include "nsSVGEffects.h"
 #include "nsSVGFilterFrame.h"
+#include "nsSVGFilterInstance.h"
 #include "nsSVGFilterPaintCallback.h"
 #include "nsSVGForeignObjectFrame.h"
 #include "gfxSVGGlyphs.h"
 #include "nsSVGInnerSVGFrame.h"
 #include "nsSVGIntegrationUtils.h"
 #include "nsSVGLength2.h"
 #include "nsSVGMaskFrame.h"
 #include "nsSVGOuterSVGFrame.h"
@@ -154,22 +155,23 @@ nsSVGUtils::GetNearestSVGViewport(nsIFra
 
 nsRect
 nsSVGUtils::GetPostFilterVisualOverflowRect(nsIFrame *aFrame,
                                             const nsRect &aPreFilterRect)
 {
   NS_ABORT_IF_FALSE(aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT,
                     "Called on invalid frame type");
 
-  nsSVGFilterFrame *filter = nsSVGEffects::GetFilterFrame(aFrame);
-  if (!filter) {
+  nsSVGFilterFrame *filterFrame = nsSVGEffects::GetFilterFrame(aFrame);
+  if (!filterFrame) {
     return aPreFilterRect;
   }
 
-  return filter->GetPostFilterBounds(aFrame, nullptr, &aPreFilterRect);
+  return nsSVGFilterInstance::GetPostFilterBounds(filterFrame, aFrame, nullptr,
+                                                  &aPreFilterRect);
 }
 
 bool
 nsSVGUtils::OuterSVGIsCallingReflowSVG(nsIFrame *aFrame)
 {
   return GetOuterSVGFrame(aFrame)->IsCallingReflowSVG();
 }
 
@@ -616,17 +618,19 @@ nsSVGUtils::PaintFrameWithEffects(nsRend
                                       aDirtyRect->width, aDirtyRect->height));
       tmpDirtyRect =
         nsLayoutUtils::RoundGfxRectToAppRect(
           dirtyBounds, aFrame->PresContext()->AppUnitsPerCSSPixel()) -
         aFrame->GetPosition();
       dirtyRect = &tmpDirtyRect;
     }
     SVGPaintCallback paintCallback;
-    filterFrame->PaintFilteredFrame(aContext, aFrame, &paintCallback, dirtyRect, aTransformRoot);
+    nsSVGFilterInstance::PaintFilteredFrame(filterFrame, aContext, aFrame,
+                                            &paintCallback, dirtyRect,
+                                            aTransformRoot);
   } else {
     svgChildFrame->PaintSVG(aContext, aDirtyRect, aTransformRoot);
   }
 
   if (clipPathFrame && isTrivialClip) {
     gfx->Restore();
   }