Bug 1336480 - Part 1. Apply suface limitation in nsFilterInstance::ComputeNeededBoxes. draft
authorcku <cku@mozilla.com>
Tue, 21 Feb 2017 00:08:38 +0800
changeset 487084 d14c90bf3a048c19699f11443c0985425d7f85d8
parent 487063 24931c1b6d9e5c0b1e496a2428f2012428715956
child 487085 45da6f0452821f4455213b54291d15b47a3e2392
push id46123
push userbmo:cku@mozilla.com
push dateMon, 20 Feb 2017 16:11:02 +0000
bugs1336480
milestone54.0a1
Bug 1336480 - Part 1. Apply suface limitation in nsFilterInstance::ComputeNeededBoxes. There is no need to limit output space bounds in nsFilterInstance::OutputFilterSpaceBounds(), it's just far too early. MozReview-Commit-ID: 9i9huKDGxq6
layout/svg/nsFilterInstance.cpp
layout/svg/nsSVGUtils.cpp
--- a/layout/svg/nsFilterInstance.cpp
+++ b/layout/svg/nsFilterInstance.cpp
@@ -354,42 +354,58 @@ nsFilterInstance::BuildPrimitivesForFilt
     mTargetFrame ? mTargetFrame->StyleColor()->mColor : NS_RGB(0,0,0);
 
   nsCSSFilterInstance cssFilterInstance(aFilter, shadowFallbackColor,
                                         mTargetBounds,
                                         mFrameSpaceInCSSPxToFilterSpaceTransform);
   return cssFilterInstance.BuildPrimitives(mPrimitiveDescriptions, aInputIsTainted);
 }
 
+static void
+UpdateNeededBounds(const nsIntRegion& aRegion, nsIntRect& aBounds)
+{
+  aBounds = aRegion.GetBounds();
+
+  bool overflow;
+  IntSize surfaceSize =
+   nsSVGUtils::ConvertToSurfaceSize(aBounds.Size(), &overflow);
+  if (overflow) {
+    aBounds.SizeTo(surfaceSize);
+  }
+}
+
 void
 nsFilterInstance::ComputeNeededBoxes()
 {
   if (mPrimitiveDescriptions.IsEmpty())
     return;
 
   nsIntRegion sourceGraphicNeededRegion;
   nsIntRegion fillPaintNeededRegion;
   nsIntRegion strokePaintNeededRegion;
 
   FilterSupport::ComputeSourceNeededRegions(
     mFilterDescription, mPostFilterDirtyRegion,
     sourceGraphicNeededRegion, fillPaintNeededRegion, strokePaintNeededRegion);
 
   sourceGraphicNeededRegion.And(sourceGraphicNeededRegion, mTargetBounds);
 
-  mSourceGraphic.mNeededBounds = sourceGraphicNeededRegion.GetBounds();
-  mFillPaint.mNeededBounds = fillPaintNeededRegion.GetBounds();
-  mStrokePaint.mNeededBounds = strokePaintNeededRegion.GetBounds();
+  UpdateNeededBounds(sourceGraphicNeededRegion, mSourceGraphic.mNeededBounds);
+  UpdateNeededBounds(fillPaintNeededRegion, mFillPaint.mNeededBounds);
+  UpdateNeededBounds(strokePaintNeededRegion, mStrokePaint.mNeededBounds);
 }
 
 DrawResult
 nsFilterInstance::BuildSourcePaint(SourceInfo *aSource)
 {
   MOZ_ASSERT(mTargetFrame);
   nsIntRect neededRect = aSource->mNeededBounds;
+  if (neededRect.IsEmpty()) {
+    return DrawResult::SUCCESS;
+  }
 
   RefPtr<DrawTarget> offscreenDT =
     gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
       neededRect.Size(), SurfaceFormat::B8G8R8A8);
   if (!offscreenDT || !offscreenDT->IsValid()) {
     return DrawResult::TEMPORARY_ERROR;
   }
 
@@ -570,23 +586,17 @@ nsFilterInstance::ComputeSourceNeededRec
 
 nsIntRect
 nsFilterInstance::OutputFilterSpaceBounds() const
 {
   uint32_t numPrimitives = mPrimitiveDescriptions.Length();
   if (numPrimitives <= 0)
     return nsIntRect();
 
-  nsIntRect bounds =
-    mPrimitiveDescriptions[numPrimitives - 1].PrimitiveSubregion();
-  bool overflow;
-  IntSize surfaceSize =
-    nsSVGUtils::ConvertToSurfaceSize(bounds.Size(), &overflow);
-  bounds.SizeTo(surfaceSize);
-  return bounds;
+  return mPrimitiveDescriptions[numPrimitives - 1].PrimitiveSubregion();
 }
 
 nsIntRect
 nsFilterInstance::FrameSpaceToFilterSpace(const nsRect* aRect) const
 {
   nsIntRect rect = OutputFilterSpaceBounds();
   if (aRect) {
     if (aRect->IsEmpty()) {
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -1002,17 +1002,17 @@ IntSize
 nsSVGUtils::ConvertToSurfaceSize(const gfxSize& aSize,
                                  bool *aResultOverflows)
 {
   IntSize surfaceSize(ClampToInt(ceil(aSize.width)), ClampToInt(ceil(aSize.height)));
 
   *aResultOverflows = surfaceSize.width != ceil(aSize.width) ||
     surfaceSize.height != ceil(aSize.height);
 
-  if (!Factory::CheckSurfaceSize(surfaceSize)) {
+  if (!Factory::AllowedSurfaceSize(surfaceSize)) {
     surfaceSize.width = std::min(NS_SVG_OFFSCREEN_MAX_DIMENSION,
                                surfaceSize.width);
     surfaceSize.height = std::min(NS_SVG_OFFSCREEN_MAX_DIMENSION,
                                 surfaceSize.height);
     *aResultOverflows = true;
   }
 
   return surfaceSize;