Bug 607653 - avoid temporary fbos/textures on transformed layers, when possible. part1 r=roc a=apporval2.0
authorOleg Romashin <romaxa@gmail.com>
Wed, 24 Nov 2010 11:35:21 +0200
changeset 58579 566832c6b2845b2c54c12c940ce871d7a3d2ea32
parent 58578 bb9d8fb1805feca56f48d846376c65b7d28d99ee
child 58580 557ce7926eba28e6b86b9a8883f106c530ad9601
push idunknown
push userunknown
push dateunknown
reviewersroc, apporval2
bugs607653
milestone2.0b8pre
Bug 607653 - avoid temporary fbos/textures on transformed layers, when possible. part1 r=roc a=apporval2.0
content/svg/content/src/nsSVGFilters.cpp
gfx/thebes/Makefile.in
gfx/thebes/gfxBlur.cpp
gfx/thebes/gfxBlur.h
gfx/thebes/gfxMatrix.h
gfx/thebes/gfxThebesUtils.cpp
gfx/thebes/gfxThebesUtils.h
gfx/thebes/gfxUtils.cpp
gfx/thebes/gfxUtils.h
layout/base/FrameLayerBuilder.cpp
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/svg/base/src/nsSVGFilterFrame.cpp
layout/svg/base/src/nsSVGFilterInstance.cpp
layout/svg/base/src/nsSVGUtils.cpp
--- a/content/svg/content/src/nsSVGFilters.cpp
+++ b/content/svg/content/src/nsSVGFilters.cpp
@@ -63,16 +63,17 @@
 #include "nsImageLoadingContent.h"
 #include "imgIContainer.h"
 #include "nsNetUtil.h"
 #include "nsSVGPreserveAspectRatio.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsSVGFilterElement.h"
 #include "nsSVGString.h"
 #include "nsSVGEffects.h"
+#include "gfxUtils.h"
 
 #if defined(XP_WIN) 
 // Prevent Windows redefining LoadImage
 #ifndef WINCE
 #undef LoadImage
 #endif
 #endif
 
@@ -174,17 +175,17 @@ nsSVGFE::SetupScalingFilter(nsSVGFilterI
   // overflow) or zero size (large kernel unit)
   if (overflow || scaledSize.width <= 0 || scaledSize.height <= 0)
     return result;
 
   gfxRect r(aDataRect.x, aDataRect.y, aDataRect.width, aDataRect.height);
   r.Scale(gfxFloat(scaledSize.width)/aTarget->mImage->Width(),
           gfxFloat(scaledSize.height)/aTarget->mImage->Height());
   r.RoundOut();
-  if (NS_FAILED(nsLayoutUtils::GfxRectToIntRect(r, &result.mDataRect)))
+  if (!gfxUtils::GfxRectToIntRect(r, &result.mDataRect))
     return result;
   
 #ifdef DEBUG_tor
   fprintf(stderr, "scaled size %d %d\n", scaledSize.width, scaledSize.height);
 #endif
   result.mSource = new gfxImageSurface(scaledSize,
                                        gfxASurface::ImageFormatARGB32);
   result.mTarget = new gfxImageSurface(scaledSize,
@@ -2944,19 +2945,19 @@ nsSVGFETileElement::Filter(nsSVGFilterIn
           rect.x, rect.y, rect.width, rect.height);
 #endif
   // XXX This code depends on the surface rect containing the filter
   // primitive subregion. ComputeTargetBBox, ComputeNeededSourceBBoxes
   // and ComputeChangeBBox are all pessimal, so that will normally be OK,
   // but nothing clips mFilterPrimitiveSubregion so this should be changed.
 
   nsIntRect tile;
-  nsresult res = nsLayoutUtils::GfxRectToIntRect(aSources[0]->mFilterPrimitiveSubregion, &tile);
-
-  NS_ENSURE_SUCCESS(res, res); // asserts on failure (not 
+  PRBool res = gfxUtils::GfxRectToIntRect(aSources[0]->mFilterPrimitiveSubregion, &tile);
+
+  NS_ENSURE_TRUE(res, NS_ERROR_FAILURE); // asserts on failure (not 
   if (tile.IsEmpty())
     return NS_OK;
 
   const nsIntRect &surfaceRect = instance->GetSurfaceRect();
   if (!tile.Intersects(surfaceRect)) {
     // nothing to draw
     return NS_OK;
   }
--- a/gfx/thebes/Makefile.in
+++ b/gfx/thebes/Makefile.in
@@ -30,17 +30,16 @@ EXPORTS	= \
 	gfxPattern.h \
 	gfxPlatform.h \
 	gfxPoint.h \
 	gfxRect.h \
 	gfxSkipChars.h \
 	gfxTypes.h \
 	gfxTextRunCache.h \
 	gfxTextRunWordCache.h \
-	gfxThebesUtils.h \
 	gfxUtils.h \
 	gfxUserFontSet.h \
 	GLDefs.h \
 	GLContext.h \
 	GLContextSymbols.h \
 	GLContextProvider.h \
 	GLContextProviderImpl.h \
 	nsCoreAnimationSupport.h \
@@ -179,17 +178,16 @@ CPPSRCS	= \
 	gfxPath.cpp \
 	gfxPattern.cpp \
 	gfxPlatform.cpp \
 	gfxPlatformFontList.cpp \
 	gfxRect.cpp \
 	gfxSkipChars.cpp \
 	gfxTextRunCache.cpp \
 	gfxTextRunWordCache.cpp \
-	gfxThebesUtils.cpp \
 	gfxUserFontSet.cpp \
 	gfxUtils.cpp \
 	gfxUnicodeProperties.cpp \
 	gfxScriptItemizer.cpp \
 	gfxHarfBuzzShaper.cpp \
 	GLContext.cpp \
 	GLContextProviderOSMesa.cpp \
 	$(NULL)
--- a/gfx/thebes/gfxBlur.cpp
+++ b/gfx/thebes/gfxBlur.cpp
@@ -83,18 +83,19 @@ gfxAlphaBoxBlur::Init(const gfxRect& aRe
 
     if (aSkipRect) {
         // If we get passed a skip rect, we can lower the amount of
         // blurring/spreading we need to do. We convert it to nsIntRect to avoid
         // expensive int<->float conversions if we were to use gfxRect instead.
         gfxRect skipRect = *aSkipRect;
         skipRect.RoundIn();
         skipRect.Inset(aBlurRadius + aSpreadRadius);
-        mSkipRect = gfxThebesUtils::GfxRectToIntRect(skipRect);
-        nsIntRect shadowIntRect = gfxThebesUtils::GfxRectToIntRect(rect);
+        gfxUtils::GfxRectToIntRect(skipRect, &mSkipRect);
+        nsIntRect shadowIntRect;
+        gfxUtils::GfxRectToIntRect(rect, &shadowIntRect);
         mSkipRect.IntersectRect(mSkipRect, shadowIntRect);
         if (mSkipRect == shadowIntRect)
           return nsnull;
 
         mSkipRect -= shadowIntRect.TopLeft();
     } else {
         mSkipRect = nsIntRect(0, 0, 0, 0);
     }
--- a/gfx/thebes/gfxBlur.h
+++ b/gfx/thebes/gfxBlur.h
@@ -36,17 +36,18 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef GFX_BLUR_H
 #define GFX_BLUR_H
 
 #include "gfxContext.h"
 #include "gfxImageSurface.h"
 #include "gfxTypes.h"
-#include "gfxThebesUtils.h"
+#include "gfxUtils.h"
+#include "nsRect.h"
 
 /**
  * Implementation of a triple box blur approximation of a Gaussian blur.
  *
  * A Gaussian blur is good for blurring because, when done independently
  * in the horizontal and vertical directions, it matches the result that
  * would be obtained using a different (rotated) set of axes.  A triple
  * box blur is a very close approximation of a Gaussian.
--- a/gfx/thebes/gfxMatrix.h
+++ b/gfx/thebes/gfxMatrix.h
@@ -260,15 +260,24 @@ public:
 
     /**
      * Snap matrix components that are close to integers
      * to integers. In particular, components that are integral when
      * converted to single precision are set to those integers.
      */
     void NudgeToIntegers(void);
 
+    /**
+     * Returns true if matrix is multiple of 90 degrees rotation with flipping,
+     * scaling and translation.
+     */
+    PRBool PreservesAxisAlignedRectangles() const {
+        return ((FuzzyEqual(xx, 0.0) && FuzzyEqual(yy, 0.0))
+            || (FuzzyEqual(xy, 0.0) && FuzzyEqual(yx, 0.0)));
+    }
+
 private:
     static PRBool FuzzyEqual(gfxFloat aV1, gfxFloat aV2) {
         return fabs(aV2 - aV1) < 1e-6;
     }
 };
 
 #endif /* GFX_MATRIX_H */
deleted file mode 100644
--- a/gfx/thebes/gfxThebesUtils.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is gfx thebes code.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Michael Ventnor <m.ventnor@gmail.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "gfxThebesUtils.h"
-
-// Converts a gfxRect to an nsIntRect for speed
-nsIntRect
-gfxThebesUtils::GfxRectToIntRect(const gfxRect& aIn)
-{
-  nsIntRect result(PRInt32(aIn.X()), PRInt32(aIn.Y()),
-                   PRInt32(aIn.Width()), PRInt32(aIn.Height()));
-  NS_ASSERTION(gfxRect(result.x, result.y, result.width, result.height) == aIn,
-               "The given gfxRect isn't rounded properly!");
-  return result;
-}
deleted file mode 100644
--- a/gfx/thebes/gfxThebesUtils.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is gfx thebes code.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Michael Ventnor <m.ventnor@gmail.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "gfxRect.h"
-#include "nsRect.h"
-
-#ifndef GFX_THEBES_UTILS_H
-#define GFX_THEBES_UTILS_H
-
-class THEBES_API gfxThebesUtils
-{
-public:
-    /**
-     * Converts a gfxRect into nsIntRect for speed reasons.
-     */
-    static nsIntRect GfxRectToIntRect(const gfxRect& aIn);
-};
-
-#endif /* GFX_THEBES_UTILS_H */
--- a/gfx/thebes/gfxUtils.cpp
+++ b/gfx/thebes/gfxUtils.cpp
@@ -453,8 +453,17 @@ gfxUtils::ClipToRegion(gfxContext* aCont
   ClipToRegionInternal(aContext, aRegion, PR_FALSE);
 }
 
 /*static*/ void
 gfxUtils::ClipToRegionSnapped(gfxContext* aContext, const nsIntRegion& aRegion)
 {
   ClipToRegionInternal(aContext, aRegion, PR_TRUE);
 }
+
+PRBool
+gfxUtils::GfxRectToIntRect(const gfxRect& aIn, nsIntRect* aOut)
+{
+  *aOut = nsIntRect(PRInt32(aIn.X()), PRInt32(aIn.Y()),
+  PRInt32(aIn.Width()), PRInt32(aIn.Height()));
+  return gfxRect(aOut->x, aOut->y, aOut->width, aOut->height) == aIn;
+}
+
--- a/gfx/thebes/gfxUtils.h
+++ b/gfx/thebes/gfxUtils.h
@@ -39,16 +39,17 @@
 #define GFX_UTILS_H
 
 #include "gfxTypes.h"
 #include "gfxPattern.h"
 #include "gfxImageSurface.h"
 
 class gfxDrawable;
 class nsIntRegion;
+class nsIntRect;
 
 class THEBES_API gfxUtils {
 public:
     /*
      * Premultiply or Unpremultiply aSourceSurface, writing the result
      * to aDestSurface or back into aSourceSurface if aDestSurface is null.
      *
      * If aDestSurface is given, it must have identical format, dimensions, and
@@ -94,11 +95,18 @@ public:
      * Clip aContext to the region aRegion, snapping the rectangles.
      */
     static void ClipToRegionSnapped(gfxContext* aContext, const nsIntRegion& aRegion);
 
     /*
      * Convert image format to depth value
      */
     static int ImageFormatToDepth(gfxASurface::gfxImageFormat aFormat);
+
+    /**
+     * If aIn can be represented exactly using an nsIntRect (i.e.
+     * integer-aligned edges and coordinates in the PRInt32 range) then we
+     * set aOut to that rectangle, otherwise return failure.
+    */
+    static PRBool GfxRectToIntRect(const gfxRect& aIn, nsIntRect* aOut);
 };
 
 #endif
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -40,16 +40,17 @@
 #include "nsDisplayList.h"
 #include "nsPresContext.h"
 #include "nsLayoutUtils.h"
 #include "Layers.h"
 #include "BasicLayers.h"
 #include "nsSubDocumentFrame.h"
 #include "nsCSSRendering.h"
 #include "nsCSSFrameConstructor.h"
+#include "gfxUtils.h"
 
 #ifdef DEBUG
 #include <stdio.h>
 #endif
 
 using namespace mozilla::layers;
 
 namespace mozilla {
@@ -742,17 +743,17 @@ SetVisibleRectForLayer(Layer* aLayer, co
   if (aLayer->GetTransform().Is2D(&transform)) {
     // if 'transform' is not invertible, then nothing will be displayed
     // for the layer, so it doesn't really matter what we do here
     transform.Invert();
     gfxRect layerVisible = transform.TransformBounds(
         gfxRect(aRect.x, aRect.y, aRect.width, aRect.height));
     layerVisible.RoundOut();
     nsIntRect visibleRect;
-    if (NS_FAILED(nsLayoutUtils::GfxRectToIntRect(layerVisible, &visibleRect))) {
+    if (!gfxUtils::GfxRectToIntRect(layerVisible, &visibleRect)) {
       visibleRect = nsIntRect(0, 0, 0, 0);
       NS_WARNING("Visible rect transformed out of bounds");
     }
     aLayer->SetVisibleRegion(visibleRect);
   } else {
     NS_ERROR("Only 2D transformations currently supported");
   }
 }
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -980,25 +980,16 @@ nsLayoutUtils::InvertTransformsToRoot(ns
   /* If the ctm is singular, hand back (0, 0) as a sentinel. */
   if (ctm.IsSingular())
     return nsPoint(0, 0);
 
   /* Otherwise, invert the CTM and use it to transform the point. */
   return MatrixTransformPoint(aPoint, ctm.Invert(), aFrame->PresContext()->AppUnitsPerDevPixel());
 }
 
-nsresult
-nsLayoutUtils::GfxRectToIntRect(const gfxRect& aIn, nsIntRect* aOut)
-{
-  *aOut = nsIntRect(PRInt32(aIn.X()), PRInt32(aIn.Y()),
-                    PRInt32(aIn.Width()), PRInt32(aIn.Height()));
-  return gfxRect(aOut->x, aOut->y, aOut->width, aOut->height) == aIn
-    ? NS_OK : NS_ERROR_FAILURE;
-}
-
 static nsIntPoint GetWidgetOffset(nsIWidget* aWidget, nsIWidget*& aRootWidget) {
   nsIntPoint offset(0, 0);
   nsIWidget* parent = aWidget->GetParent();
   while (parent) {
     nsIntRect bounds;
     aWidget->GetBounds(bounds);
     offset += bounds.TopLeft();
     aWidget = parent;
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -507,23 +507,16 @@ public:
    * app space that contains the graphics rectangle, rounding out as necessary.
    *
    * @param aRect The graphics rect to round outward.
    * @param aFactor The number of app units per graphics unit.
    * @return The smallest rectangle in app space that contains aRect.
    */
   static nsRect RoundGfxRectToAppRect(const gfxRect &aRect, float aFactor);
 
-  /**
-   * If aIn can be represented exactly using an nsIntRect (i.e.
-   * integer-aligned edges and coordinates in the PRInt32 range) then we
-   * set aOut to that rectangle, otherwise return failure.
-   */
-  static nsresult GfxRectToIntRect(const gfxRect& aIn, nsIntRect* aOut);
-
   enum {
     PAINT_IN_TRANSFORM = 0x01,
     PAINT_SYNC_DECODE_IMAGES = 0x02,
     PAINT_WIDGET_LAYERS = 0x04,
     PAINT_IGNORE_SUPPRESSION = 0x08,
     PAINT_DOCUMENT_RELATIVE = 0x10,
     PAINT_HIDE_CARET = 0x20,
     PAINT_ALL_CONTINUATIONS = 0x40,
--- a/layout/svg/base/src/nsSVGFilterFrame.cpp
+++ b/layout/svg/base/src/nsSVGFilterFrame.cpp
@@ -42,16 +42,17 @@
 #include "nsSVGFilterElement.h"
 #include "nsSVGFilters.h"
 #include "gfxASurface.h"
 #include "gfxContext.h"
 #include "gfxImageSurface.h"
 #include "nsSVGFilterPaintCallback.h"
 #include "nsSVGRect.h"
 #include "nsSVGFilterInstance.h"
+#include "gfxUtils.h"
 
 nsIFrame*
 NS_NewSVGFilterFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsSVGFilterFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsSVGFilterFrame)
@@ -62,17 +63,17 @@ MapDeviceRectToFilterSpace(const gfxMatr
                            const nsIntRect* aDeviceRect)
 {
   nsIntRect rect(0, 0, aFilterSize.width, aFilterSize.height);
   if (aDeviceRect) {
     gfxRect r = aMatrix.TransformBounds(gfxRect(aDeviceRect->x, aDeviceRect->y,
                                                 aDeviceRect->width, aDeviceRect->height));
     r.RoundOut();
     nsIntRect intRect;
-    if (NS_SUCCEEDED(nsLayoutUtils::GfxRectToIntRect(r, &intRect))) {
+    if (gfxUtils::GfxRectToIntRect(r, &intRect)) {
       rect = intRect;
     }
   }
   return rect;
 }
 
 class NS_STACK_CLASS nsAutoFilterInstance {
 public:
@@ -231,19 +232,18 @@ nsSVGFilterFrame::FilterPaint(nsSVGRende
 static nsresult
 TransformFilterSpaceToDeviceSpace(nsSVGFilterInstance *aInstance, nsIntRect *aRect)
 {
   gfxMatrix m = aInstance->GetFilterSpaceToDeviceSpaceTransform();
   gfxRect r(aRect->x, aRect->y, aRect->width, aRect->height);
   r = m.TransformBounds(r);
   r.RoundOut();
   nsIntRect deviceRect;
-  nsresult rv = nsLayoutUtils::GfxRectToIntRect(r, &deviceRect);
-  if (NS_FAILED(rv))
-    return rv;
+  if (!gfxUtils::GfxRectToIntRect(r, &deviceRect))
+    return NS_ERROR_FAILURE;
   *aRect = deviceRect;
   return NS_OK;
 }
 
 nsIntRect
 nsSVGFilterFrame::GetInvalidationBBox(nsIFrame *aTarget, const nsIntRect& aRect)
 {
   nsAutoFilterInstance instance(aTarget, this, nsnull, nsnull, &aRect, nsnull);
--- a/layout/svg/base/src/nsSVGFilterInstance.cpp
+++ b/layout/svg/base/src/nsSVGFilterInstance.cpp
@@ -36,16 +36,17 @@
 
 #include "nsSVGFilterInstance.h"
 #include "nsSVGUtils.h"
 #include "nsIDOMSVGUnitTypes.h"
 #include "gfxPlatform.h"
 #include "nsSVGFilterPaintCallback.h"
 #include "nsSVGFilterElement.h"
 #include "nsLayoutUtils.h"
+#include "gfxUtils.h"
 
 static double Square(double aX)
 {
   return aX*aX;
 }
 
 float
 nsSVGFilterInstance::GetPrimitiveLength(nsSVGLength2 *aLength) const
@@ -160,17 +161,17 @@ nsSVGFilterInstance::BuildSources()
   gfxRect filterRegion = gfxRect(0, 0, mFilterSpaceSize.width, mFilterSpaceSize.height);
   mSourceColorAlpha.mImage.mFilterPrimitiveSubregion = filterRegion;
   mSourceAlpha.mImage.mFilterPrimitiveSubregion = filterRegion;
 
   nsIntRect sourceBoundsInt;
   gfxRect sourceBounds = UserSpaceToFilterSpace(mTargetBBox);
   sourceBounds.RoundOut();
   // Detect possible float->int overflow
-  if (NS_FAILED(nsLayoutUtils::GfxRectToIntRect(sourceBounds, &sourceBoundsInt)))
+  if (!gfxUtils::GfxRectToIntRect(sourceBounds, &sourceBoundsInt))
     return NS_ERROR_FAILURE;
 
   mSourceColorAlpha.mResultBoundingBox = sourceBoundsInt;
   mSourceAlpha.mResultBoundingBox = sourceBoundsInt;
   return NS_OK;
 }
 
 nsresult
@@ -351,19 +352,18 @@ nsSVGFilterInstance::BuildSourceImages()
     gfxMatrix userSpaceToFilterSpace = GetUserSpaceToFilterSpaceTransform();
 
     gfxRect r(neededRect.x, neededRect.y, neededRect.width, neededRect.height);
     gfxMatrix m = userSpaceToFilterSpace;
     m.Invert();
     r = m.TransformBounds(r);
     r.RoundOut();
     nsIntRect dirty;
-    nsresult rv = nsLayoutUtils::GfxRectToIntRect(r, &dirty);
-    if (NS_FAILED(rv))
-      return rv;
+    if (!gfxUtils::GfxRectToIntRect(r, &dirty))
+      return NS_ERROR_FAILURE;
 
     // SVG graphics paint to device space, so we need to set an initial device
     // space to filter space transform on the gfxContext that SourceGraphic
     // and SourceAlpha will paint to.
     //
     // (In theory it would be better to minimize error by having filtered SVG
     // graphics temporarily paint to user space when painting the sources and
     // only set a user space to filter space transform on the gfxContext
--- a/layout/svg/base/src/nsSVGUtils.cpp
+++ b/layout/svg/base/src/nsSVGUtils.cpp
@@ -86,16 +86,17 @@
 #include "nsMathUtils.h"
 #include "nsSVGIntegrationUtils.h"
 #include "nsSVGFilterPaintCallback.h"
 #include "nsSVGGeometryFrame.h"
 #include "nsComputedDOMStyle.h"
 #include "nsSVGPathGeometryFrame.h"
 #include "prdtoa.h"
 #include "mozilla/dom/Element.h"
+#include "gfxUtils.h"
 
 using namespace mozilla::dom;
 
 gfxASurface *nsSVGUtils::gThebesComputationalSurface = nsnull;
 
 // c = n / 255
 // (c <= 0.0031308 ? c * 12.92 : 1.055 * pow(c, 1 / 2.4) - 0.055) * 255 + 0.5
 static const PRUint8 glinearRGBTosRGBMap[256] = {
@@ -631,17 +632,17 @@ nsSVGUtils::FindFilterInvalidation(nsIFr
       nsSVGDisplayContainerFrame* innerSvgParent = do_QueryFrame(viewportFrame->GetParent());
       float x, y, width, height;
       static_cast<nsSVGSVGElement*>(innerSvg->GetContent())->
         GetAnimatedLengthValues(&x, &y, &width, &height, nsnull);
       gfxRect bounds = nsSVGUtils::GetCanvasTM(innerSvgParent).
                          TransformBounds(gfxRect(x, y, width, height));
       bounds.RoundOut();
       nsIntRect r;
-      if (NS_SUCCEEDED(nsLayoutUtils::GfxRectToIntRect(bounds, &r))) {
+      if (gfxUtils::GfxRectToIntRect(bounds, &r)) {
         rect = r;
       } else {
         NS_NOTREACHED("Not going to invalidate the correct area");
       }
       aFrame = viewportFrame;
     }
     aFrame = aFrame->GetParent();
   }
@@ -950,17 +951,17 @@ public:
     if (aDirtyRect) {
       gfxMatrix userToDeviceSpace = nsSVGUtils::GetCanvasTM(aTarget);
       if (userToDeviceSpace.IsSingular()) {
         return;
       }
       gfxRect dirtyBounds = userToDeviceSpace.TransformBounds(
         gfxRect(aDirtyRect->x, aDirtyRect->y, aDirtyRect->width, aDirtyRect->height));
       dirtyBounds.RoundOut();
-      if (NS_SUCCEEDED(nsLayoutUtils::GfxRectToIntRect(dirtyBounds, &tmpDirtyRect))) {
+      if (gfxUtils::GfxRectToIntRect(dirtyBounds, &tmpDirtyRect)) {
         dirtyRect = &tmpDirtyRect;
       }
     }
 
     svgChildFrame->PaintSVG(aContext, dirtyRect);
   }
 };