From b19d4e2f0cef1a270719aa504d2a41ea3e1c43dc Mon Sep 17 00:00:00 2001 From: Oleg Romashin Date: Wed, 24 Nov 2010 11:35:21 +0200 Subject: [PATCH] Bug 607653 - avoid temporary fbos/textures on transformed layers, when possible. part1 r=roc a=apporval2.0 --- content/svg/content/src/nsSVGFilters.cpp | 7 +-- gfx/thebes/Makefile.in | 2 - gfx/thebes/gfxBlur.cpp | 5 +- gfx/thebes/gfxBlur.h | 3 +- gfx/thebes/gfxMatrix.h | 9 ++++ gfx/thebes/gfxThebesUtils.cpp | 49 ------------------- gfx/thebes/gfxThebesUtils.h | 53 --------------------- gfx/thebes/gfxUtils.cpp | 9 ++++ gfx/thebes/gfxUtils.h | 8 ++++ layout/base/FrameLayerBuilder.cpp | 3 +- layout/base/nsLayoutUtils.cpp | 9 ---- layout/base/nsLayoutUtils.h | 7 --- layout/svg/base/src/nsSVGFilterFrame.cpp | 8 ++-- layout/svg/base/src/nsSVGFilterInstance.cpp | 8 ++-- layout/svg/base/src/nsSVGUtils.cpp | 5 +- 15 files changed, 48 insertions(+), 137 deletions(-) delete mode 100644 gfx/thebes/gfxThebesUtils.cpp delete mode 100644 gfx/thebes/gfxThebesUtils.h diff --git a/content/svg/content/src/nsSVGFilters.cpp b/content/svg/content/src/nsSVGFilters.cpp index c219abcdf6cc..3d32904e7135 100644 --- a/content/svg/content/src/nsSVGFilters.cpp +++ b/content/svg/content/src/nsSVGFilters.cpp @@ -68,6 +68,7 @@ #include "nsSVGFilterElement.h" #include "nsSVGString.h" #include "nsSVGEffects.h" +#include "gfxUtils.h" #if defined(XP_WIN) // Prevent Windows redefining LoadImage @@ -179,7 +180,7 @@ nsSVGFE::SetupScalingFilter(nsSVGFilterInstance *aInstance, 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 @@ -2949,9 +2950,9 @@ nsSVGFETileElement::Filter(nsSVGFilterInstance *instance, // but nothing clips mFilterPrimitiveSubregion so this should be changed. nsIntRect tile; - nsresult res = nsLayoutUtils::GfxRectToIntRect(aSources[0]->mFilterPrimitiveSubregion, &tile); + PRBool res = gfxUtils::GfxRectToIntRect(aSources[0]->mFilterPrimitiveSubregion, &tile); - NS_ENSURE_SUCCESS(res, res); // asserts on failure (not + NS_ENSURE_TRUE(res, NS_ERROR_FAILURE); // asserts on failure (not if (tile.IsEmpty()) return NS_OK; diff --git a/gfx/thebes/Makefile.in b/gfx/thebes/Makefile.in index b2b41726f598..44eaa6bd4d35 100644 --- a/gfx/thebes/Makefile.in +++ b/gfx/thebes/Makefile.in @@ -35,7 +35,6 @@ EXPORTS = \ gfxTypes.h \ gfxTextRunCache.h \ gfxTextRunWordCache.h \ - gfxThebesUtils.h \ gfxUtils.h \ gfxUserFontSet.h \ GLDefs.h \ @@ -184,7 +183,6 @@ CPPSRCS = \ gfxSkipChars.cpp \ gfxTextRunCache.cpp \ gfxTextRunWordCache.cpp \ - gfxThebesUtils.cpp \ gfxUserFontSet.cpp \ gfxUtils.cpp \ gfxUnicodeProperties.cpp \ diff --git a/gfx/thebes/gfxBlur.cpp b/gfx/thebes/gfxBlur.cpp index 9bc54490b738..6bfdf5f93cd7 100644 --- a/gfx/thebes/gfxBlur.cpp +++ b/gfx/thebes/gfxBlur.cpp @@ -88,8 +88,9 @@ gfxAlphaBoxBlur::Init(const gfxRect& aRect, 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; diff --git a/gfx/thebes/gfxBlur.h b/gfx/thebes/gfxBlur.h index 6ae7a09bef68..e1f3d37ebc8d 100644 --- a/gfx/thebes/gfxBlur.h +++ b/gfx/thebes/gfxBlur.h @@ -41,7 +41,8 @@ #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. diff --git a/gfx/thebes/gfxMatrix.h b/gfx/thebes/gfxMatrix.h index 839b4cfe5c31..6064c876bfe5 100644 --- a/gfx/thebes/gfxMatrix.h +++ b/gfx/thebes/gfxMatrix.h @@ -265,6 +265,15 @@ public: */ 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; diff --git a/gfx/thebes/gfxThebesUtils.cpp b/gfx/thebes/gfxThebesUtils.cpp deleted file mode 100644 index 10b9e5bdf0c0..000000000000 --- 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 - * - * 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; -} diff --git a/gfx/thebes/gfxThebesUtils.h b/gfx/thebes/gfxThebesUtils.h deleted file mode 100644 index c6db49a75ea3..000000000000 --- 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 - * - * 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 */ diff --git a/gfx/thebes/gfxUtils.cpp b/gfx/thebes/gfxUtils.cpp index 051cd109f118..a15ca26a2652 100644 --- a/gfx/thebes/gfxUtils.cpp +++ b/gfx/thebes/gfxUtils.cpp @@ -458,3 +458,12 @@ 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; +} + diff --git a/gfx/thebes/gfxUtils.h b/gfx/thebes/gfxUtils.h index cac6cfb7165a..14430685b756 100644 --- a/gfx/thebes/gfxUtils.h +++ b/gfx/thebes/gfxUtils.h @@ -44,6 +44,7 @@ class gfxDrawable; class nsIntRegion; +class nsIntRect; class THEBES_API gfxUtils { public: @@ -99,6 +100,13 @@ public: * 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 diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index b3ec258f57e7..1b0aa495b90a 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -45,6 +45,7 @@ #include "nsSubDocumentFrame.h" #include "nsCSSRendering.h" #include "nsCSSFrameConstructor.h" +#include "gfxUtils.h" #ifdef DEBUG #include @@ -747,7 +748,7 @@ SetVisibleRectForLayer(Layer* aLayer, const nsIntRect& aRect) 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"); } diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 15650ca43ac7..c171d9767c69 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -985,15 +985,6 @@ nsLayoutUtils::InvertTransformsToRoot(nsIFrame *aFrame, 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(); diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index f2d79735d263..893766d81247 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -512,13 +512,6 @@ public: */ 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, diff --git a/layout/svg/base/src/nsSVGFilterFrame.cpp b/layout/svg/base/src/nsSVGFilterFrame.cpp index a75ac5d97f9d..7361ac975556 100644 --- a/layout/svg/base/src/nsSVGFilterFrame.cpp +++ b/layout/svg/base/src/nsSVGFilterFrame.cpp @@ -47,6 +47,7 @@ #include "nsSVGFilterPaintCallback.h" #include "nsSVGRect.h" #include "nsSVGFilterInstance.h" +#include "gfxUtils.h" nsIFrame* NS_NewSVGFilterFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) @@ -67,7 +68,7 @@ MapDeviceRectToFilterSpace(const gfxMatrix& aMatrix, aDeviceRect->width, aDeviceRect->height)); r.RoundOut(); nsIntRect intRect; - if (NS_SUCCEEDED(nsLayoutUtils::GfxRectToIntRect(r, &intRect))) { + if (gfxUtils::GfxRectToIntRect(r, &intRect)) { rect = intRect; } } @@ -236,9 +237,8 @@ TransformFilterSpaceToDeviceSpace(nsSVGFilterInstance *aInstance, nsIntRect *aRe 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; } diff --git a/layout/svg/base/src/nsSVGFilterInstance.cpp b/layout/svg/base/src/nsSVGFilterInstance.cpp index f34b82803893..88e58eb87f22 100644 --- a/layout/svg/base/src/nsSVGFilterInstance.cpp +++ b/layout/svg/base/src/nsSVGFilterInstance.cpp @@ -41,6 +41,7 @@ #include "nsSVGFilterPaintCallback.h" #include "nsSVGFilterElement.h" #include "nsLayoutUtils.h" +#include "gfxUtils.h" static double Square(double aX) { @@ -165,7 +166,7 @@ nsSVGFilterInstance::BuildSources() 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; @@ -356,9 +357,8 @@ nsSVGFilterInstance::BuildSourceImages() 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 diff --git a/layout/svg/base/src/nsSVGUtils.cpp b/layout/svg/base/src/nsSVGUtils.cpp index 8a89a3032344..e78e6630f4d6 100644 --- a/layout/svg/base/src/nsSVGUtils.cpp +++ b/layout/svg/base/src/nsSVGUtils.cpp @@ -91,6 +91,7 @@ #include "nsSVGPathGeometryFrame.h" #include "prdtoa.h" #include "mozilla/dom/Element.h" +#include "gfxUtils.h" using namespace mozilla::dom; @@ -636,7 +637,7 @@ nsSVGUtils::FindFilterInvalidation(nsIFrame *aFrame, const nsRect& aRect) 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"); @@ -955,7 +956,7 @@ public: 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; } }