Backed out 5 changesets (bug 1290292, bug 1290293) for gfx assertions
authorPhil Ringnalda <philringnalda@gmail.com>
Mon, 13 Feb 2017 19:28:45 -0800
changeset 342674 6098f45a8745953c08811a9a1076667587c4d952
parent 342673 b4273424e32d5090c7982075b426f6b5454e4a4d
child 342675 5d98b2c08929b681b217937bc2cac82cb5e000a3
push id86928
push userphilringnalda@gmail.com
push dateTue, 14 Feb 2017 03:28:56 +0000
treeherdermozilla-inbound@6098f45a8745 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1290292, 1290293
milestone54.0a1
backs out652c909b75ad19af508537f71f82dd8cc2fa6e70
90a284ea19e34c8d26d3d95fe69f2352162f511c
8401d12fe93637f11fe8acffba79c16ee192183e
d87488b69c186a55bec1f021b6c02a5f663c8c4b
7368aa665fae4ab34b690485f86f180ad8a324dd
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
Backed out 5 changesets (bug 1290292, bug 1290293) for gfx assertions CLOSED TREE Backed out changeset 652c909b75ad (bug 1290293) Backed out changeset 90a284ea19e3 (bug 1290292) Backed out changeset 8401d12fe936 (bug 1290293) Backed out changeset d87488b69c18 (bug 1290293) Backed out changeset 7368aa665fae (bug 1290293)
image/Downscaler.cpp
image/Downscaler.h
image/DownscalingFilter.h
image/SurfaceFilters.h
image/SurfacePipe.cpp
image/SurfacePipe.h
image/decoders/nsBMPDecoder.cpp
image/decoders/nsGIFDecoder2.cpp
image/decoders/nsIconDecoder.cpp
image/decoders/nsIconDecoder.h
image/decoders/nsJPEGDecoder.cpp
image/decoders/nsJPEGDecoder.h
image/decoders/nsPNGDecoder.cpp
image/decoders/nsPNGDecoder.h
image/imgFrame.cpp
image/imgFrame.h
image/test/gtest/Common.cpp
image/test/gtest/Common.h
image/test/gtest/TestDecoders.cpp
image/test/gtest/TestSurfaceSink.cpp
--- a/image/Downscaler.cpp
+++ b/image/Downscaler.cpp
@@ -26,17 +26,16 @@ using gfx::IntRect;
 namespace image {
 
 Downscaler::Downscaler(const nsIntSize& aTargetSize)
   : mTargetSize(aTargetSize)
   , mOutputBuffer(nullptr)
   , mXFilter(MakeUnique<skia::ConvolutionFilter1D>())
   , mYFilter(MakeUnique<skia::ConvolutionFilter1D>())
   , mWindowCapacity(0)
-  , mClearValue(0)
   , mHasAlpha(true)
   , mFlipVertically(false)
 {
   MOZ_ASSERT(gfxPrefs::ImageDownscaleDuringDecodeEnabled(),
              "Downscaling even though downscale-during-decode is disabled?");
   MOZ_ASSERT(mTargetSize.width > 0 && mTargetSize.height > 0,
              "Invalid target size");
 }
@@ -95,17 +94,16 @@ Downscaler::BeginFrame(const nsIntSize& 
   MOZ_ASSERT_IF(!nsIntRect(0, 0, aOriginalSize.width, aOriginalSize.height)
                   .IsEqualEdges(mFrameRect),
                 aHasAlpha);
 
   mOriginalSize = aOriginalSize;
   mScale = gfxSize(double(mOriginalSize.width) / mTargetSize.width,
                    double(mOriginalSize.height) / mTargetSize.height);
   mOutputBuffer = aOutputBuffer;
-  mClearValue = aHasAlpha ? 0 : 0xFF;
   mHasAlpha = aHasAlpha;
   mFlipVertically = aFlipVertically;
 
   ReleaseWindow();
 
   auto resizeMethod = skia::ImageOperations::RESIZE_LANCZOS3;
 
   skia::resize::ComputeFilters(resizeMethod,
@@ -204,32 +202,23 @@ GetFilterOffsetAndLength(UniquePtr<skia:
 {
   MOZ_ASSERT(aOutputImagePosition < aFilter->num_values());
   aFilter->FilterForValue(aOutputImagePosition,
                           aFilterOffsetOut,
                           aFilterLengthOut);
 }
 
 void
-Downscaler::ClearRemainingRows()
-{
-  while (!IsFrameComplete()) {
-    ClearRow();
-    CommitRow();
-  }
-}
-
-void
 Downscaler::ClearRestOfRow(uint32_t aStartingAtCol)
 {
   MOZ_ASSERT(int64_t(aStartingAtCol) <= int64_t(mOriginalSize.width));
   uint32_t bytesToClear = (mOriginalSize.width - aStartingAtCol)
                         * sizeof(uint32_t);
   memset(mRowBuffer.get() + (aStartingAtCol * sizeof(uint32_t)),
-         mClearValue, bytesToClear);
+         0, bytesToClear);
 }
 
 void
 Downscaler::CommitRow()
 {
   MOZ_ASSERT(mOutputBuffer, "Should have a current frame");
   MOZ_ASSERT(mCurrentInLine < mOriginalSize.height, "Past end of input");
 
--- a/image/Downscaler.h
+++ b/image/Downscaler.h
@@ -88,19 +88,16 @@ public:
   bool IsFrameComplete() const { return mCurrentInLine >= mOriginalSize.height; }
 
   /// Retrieves the buffer into which the Decoder should write each row.
   uint8_t* RowBuffer()
   {
     return mRowBuffer.get() + mFrameRect.x * sizeof(uint32_t);
   }
 
-  /// Clears the remaining unset rows.
-  void ClearRemainingRows();
-
   /// Clears the current row buffer.
   void ClearRow() { ClearRestOfRow(0); }
 
   /// Clears the current row buffer starting at @aStartingAtCol.
   void ClearRestOfRow(uint32_t aStartingAtCol);
 
   /// Signals that the decoder has finished writing a row into the row buffer.
   void CommitRow();
@@ -137,17 +134,16 @@ private:
   UniquePtr<skia::ConvolutionFilter1D> mYFilter;
 
   int32_t mWindowCapacity;
 
   int32_t mLinesInBuffer;
   int32_t mPrevInvalidatedLine;
   int32_t mCurrentOutLine;
   int32_t mCurrentInLine;
-  uint8_t mClearValue;
 
   bool mHasAlpha : 1;
   bool mFlipVertically : 1;
 };
 
 #else
 
 /**
--- a/image/DownscalingFilter.h
+++ b/image/DownscalingFilter.h
@@ -67,26 +67,24 @@ struct DownscalingConfig
  * should avoid this by ensuring that they do not request downscaling in
  * non-Skia builds.
  */
 template <typename Next>
 class DownscalingFilter final : public SurfaceFilter
 {
 public:
   Maybe<SurfaceInvalidRect> TakeInvalidRect() override { return Nothing(); }
-  bool GetClearValue(uint8_t& aValue) const override { return false; }
 
   template <typename... Rest>
   nsresult Configure(const DownscalingConfig& aConfig, Rest... aRest)
   {
     return NS_ERROR_FAILURE;
   }
 
 protected:
-  void DoZeroOutRestOfSurface() override { }
   uint8_t* DoResetToFirstRow() override { MOZ_CRASH(); return nullptr; }
   uint8_t* DoAdvanceRow() override { MOZ_CRASH(); return nullptr; }
 };
 
 #else
 
 /**
  * DownscalingFilter performs Lanczos downscaling, taking image input data at one size
@@ -168,19 +166,17 @@ public:
     // Allocate the buffer, which contains scanlines of the input image.
     mRowBuffer.reset(new (fallible)
                        uint8_t[PaddedWidthInBytes(mInputSize.width)]);
     if (MOZ_UNLIKELY(!mRowBuffer)) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
     // Clear the buffer to avoid writing uninitialized memory to the output.
-    uint8_t clear = 0;
-    GetClearValue(clear);
-    memset(mRowBuffer.get(), clear, PaddedWidthInBytes(mInputSize.width));
+    memset(mRowBuffer.get(), 0, PaddedWidthInBytes(mInputSize.width));
 
     // Allocate the window, which contains horizontally downscaled scanlines. (We
     // can store scanlines which are already downscaled because our downscaling
     // filter is separable.)
     mWindowCapacity = mYFilter->max_filter();
     mWindow.reset(new (fallible) uint8_t*[mWindowCapacity]);
     if (MOZ_UNLIKELY(!mWindow)) {
       return NS_ERROR_OUT_OF_MEMORY;
@@ -213,29 +209,17 @@ public:
     if (invalidRect) {
       // Compute the input space invalid rect by scaling.
       invalidRect->mInputSpaceRect.ScaleRoundOut(mScale.width, mScale.height);
     }
 
     return invalidRect;
   }
 
-  bool GetClearValue(uint8_t& aValue) const override
-  {
-    return mNext.GetClearValue(aValue);
-  }
-
 protected:
-  void DoZeroOutRestOfSurface() override
-  {
-    mNext.ZeroOutRestOfSurface();
-    mInputRow = mInputSize.height;
-    mOutputRow = mNext.InputSize().height;
-  }
-
   uint8_t* DoResetToFirstRow() override
   {
     mNext.ResetToFirstRow();
 
     mInputRow = 0;
     mOutputRow = 0;
     mRowsInWindow = 0;
 
--- a/image/SurfaceFilters.h
+++ b/image/SurfaceFilters.h
@@ -108,47 +108,33 @@ public:
     // downscaling them), the rows may no longer exist in their original form on
     // the surface itself.
     mBuffer.reset(new (fallible) uint8_t[bufferSize]);
     if (MOZ_UNLIKELY(!mBuffer)) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
     // Clear the buffer to avoid writing uninitialized memory to the output.
-    uint8_t clear = 0;
-    GetClearValue(clear);
-    memset(mBuffer.get(), clear, bufferSize);
+    memset(mBuffer.get(), 0, bufferSize);
 
     ConfigureFilter(outputSize, sizeof(PixelType));
     return NS_OK;
   }
 
   bool IsValidPalettedPipe() const override
   {
     return sizeof(PixelType) == 1 && mNext.IsValidPalettedPipe();
   }
 
   Maybe<SurfaceInvalidRect> TakeInvalidRect() override
   {
     return mNext.TakeInvalidRect();
   }
 
-  bool GetClearValue(uint8_t& aValue) const override
-  {
-    return mNext.GetClearValue(aValue);
-  }
-
 protected:
-  void DoZeroOutRestOfSurface() override
-  {
-    mNext.ZeroOutRestOfSurface();
-    mInputRow = InputSize().height;
-    mPass = 4;
-  }
-
   uint8_t* DoResetToFirstRow() override
   {
     mNext.ResetToFirstRow();
     mPass = 0;
     mInputRow = 0;
     mOutputRow = InterlaceOffset(mPass);
     return GetRowPointer(mOutputRow);
   }
@@ -411,42 +397,29 @@ public:
     // all, and we'll need a buffer to give that data a place to go.
     if (mFrameRect.width < mUnclampedFrameRect.width) {
       mBuffer.reset(new (fallible) uint8_t[mUnclampedFrameRect.width *
                                            sizeof(uint32_t)]);
       if (MOZ_UNLIKELY(!mBuffer)) {
         return NS_ERROR_OUT_OF_MEMORY;
       }
 
-      uint8_t clear = 0;
-      GetClearValue(clear);
-      memset(mBuffer.get(), clear, mUnclampedFrameRect.width * sizeof(uint32_t));
+      memset(mBuffer.get(), 0, mUnclampedFrameRect.width * sizeof(uint32_t));
     }
 
     ConfigureFilter(mUnclampedFrameRect.Size(), sizeof(uint32_t));
     return NS_OK;
   }
 
   Maybe<SurfaceInvalidRect> TakeInvalidRect() override
   {
     return mNext.TakeInvalidRect();
   }
 
-  bool GetClearValue(uint8_t& aValue) const override
-  {
-    return mNext.GetClearValue(aValue);
-  }
-
 protected:
-  void DoZeroOutRestOfSurface() override
-  {
-    mNext.ZeroOutRestOfSurface();
-    mRow = mFrameRect.YMost();
-  }
-
   uint8_t* DoResetToFirstRow() override
   {
     uint8_t* rowPtr = mNext.ResetToFirstRow();
     if (rowPtr == nullptr) {
       mRow = mFrameRect.YMost();
       return nullptr;
     }
 
@@ -490,48 +463,33 @@ protected:
       // This row is outside of the frame rect, so just drop it on the floor.
       rowPtr = mBuffer ? mBuffer.get() : mNext.CurrentRowPointer();
       return AdjustRowPointer(rowPtr);
     } else if (currentRow >= mFrameRect.YMost()) {
       NS_WARNING("RemoveFrameRectFilter: Advancing past end of frame rect");
       return nullptr;
     }
 
-    // If we had to buffer, copy the data.
+    // If we had to buffer, copy the data. Otherwise, just advance the row.
     if (mBuffer) {
       // We write from the beginning of the buffer unless |mUnclampedFrameRect.x|
       // is negative; if that's the case, we have to skip the portion of the
       // unclamped frame rect that's outside the row.
       uint32_t* source = reinterpret_cast<uint32_t*>(mBuffer.get()) -
                          std::min(mUnclampedFrameRect.x, 0);
 
       // We write |mFrameRect.width| columns starting at |mFrameRect.x|; we've
       // already clamped these values to the size of the output, so we don't
       // have to worry about bounds checking here (though WriteBuffer() will do
       // it for us in any case).
       WriteState state = mNext.WriteBuffer(source, mFrameRect.x, mFrameRect.width);
 
       rowPtr = state == WriteState::NEED_MORE_DATA ? mBuffer.get()
                                                    : nullptr;
     } else {
-      // We need to manually clear the pixels that are not written to before we
-      // advance the row.
-      uint8_t* currentRowPtr = CurrentRowPointer();
-      if (currentRowPtr) {
-        uint8_t clear = 0;
-        if (GetClearValue(clear)) {
-          gfx::IntSize outputSize = mNext.InputSize();
-          const size_t pixelSize = sizeof(uint32_t);
-          const size_t prefixOffset = mFrameRect.x * pixelSize;
-          const size_t postfixOffset = mFrameRect.width * pixelSize;
-          const size_t postfixLength = (outputSize.width - mFrameRect.XMost()) * pixelSize;
-          memset(currentRowPtr - prefixOffset, clear, prefixOffset);
-          memset(currentRowPtr + postfixOffset, clear, postfixLength);
-        }
-      }
       rowPtr = mNext.AdvanceRow();
     }
 
     // If there's still more data coming or we're already done, just adjust the
     // pointer and return.
     if (mRow < mFrameRect.YMost() || rowPtr == nullptr) {
       return AdjustRowPointer(rowPtr);
     }
@@ -653,43 +611,29 @@ public:
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
     mCurrentRow.reset(new (fallible) uint8_t[inputWidthInBytes]);
     if (MOZ_UNLIKELY(!mCurrentRow)) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
-    uint8_t clear = 0;
-    GetClearValue(clear);
-    memset(mPreviousRow.get(), clear, inputWidthInBytes);
-    memset(mCurrentRow.get(), clear, inputWidthInBytes);
+    memset(mPreviousRow.get(), 0, inputWidthInBytes);
+    memset(mCurrentRow.get(), 0, inputWidthInBytes);
 
     ConfigureFilter(mNext.InputSize(), sizeof(uint32_t));
     return NS_OK;
   }
 
   Maybe<SurfaceInvalidRect> TakeInvalidRect() override
   {
     return mNext.TakeInvalidRect();
   }
 
-  bool GetClearValue(uint8_t& aValue) const override
-  {
-    return mNext.GetClearValue(aValue);
-  }
-
 protected:
-  void DoZeroOutRestOfSurface() override
-  {
-    mNext.ZeroOutRestOfSurface();
-    mRow = InputSize().height;
-    mPass = 7;
-  }
-
   uint8_t* DoResetToFirstRow() override
   {
     mRow = 0;
     mPass = std::min(mPass + 1, 7);
 
     uint8_t* rowPtr = mNext.ResetToFirstRow();
     if (mPass == 7) {
       // Short circuit this filter on the final pass, since all pixels have
--- a/image/SurfacePipe.cpp
+++ b/image/SurfacePipe.cpp
@@ -57,69 +57,16 @@ AbstractSurfaceSink::TakeInvalidRect()
   invalidRect.mInputSpaceRect = invalidRect.mOutputSpaceRect = mInvalidRect;
 
   // Forget about the invalid rect we're returning.
   mInvalidRect = IntRect();
 
   return Some(invalidRect);
 }
 
-void
-AbstractSurfaceSink::DoZeroOutRestOfSurface()
-{
-  // If there is no explicit clear value, we know the surface was already
-  // zeroed out by default.
-  if (!mClearRequired) {
-    return;
-  }
-
-  // The reason we do not use the typical WritePixels methods here is
-  // because if it is a progressively decoded image, we know that we
-  // already have valid data written to the buffer, just not the final
-  // result. There is no need to clear the buffers in that case.
-  const int32_t width = InputSize().width;
-  const int32_t height = InputSize().height;
-  const int32_t pixelSize = IsValidPalettedPipe() ? sizeof(uint8_t)
-                                                  : sizeof(uint32_t);
-  const int32_t stride = width * pixelSize;
-
-  // In addition to fully unwritten rows, the current row may be partially
-  // written (i.e. mCol > 0). Since the row was not advanced, we have yet to
-  // update mWrittenRect so it would be cleared without the exception below.
-  const int32_t col = CurrentColumn();
-  if (MOZ_UNLIKELY(col > 0 && col <= width)) {
-    uint8_t* rowPtr = CurrentRowPointer();
-    MOZ_ASSERT(rowPtr);
-    memset(rowPtr + col * pixelSize, mClearValue, (width - col) * pixelSize);
-    AdvanceRow(); // updates mInvalidRect and mWrittenRect
-  }
-
-  MOZ_ASSERT(mWrittenRect.x == 0);
-  MOZ_ASSERT(mWrittenRect.width == 0 || mWrittenRect.width == width);
-
-  if (MOZ_UNLIKELY(mWrittenRect.y > 0)) {
-    const uint32_t length = mWrittenRect.y * stride;
-    auto updateRect = IntRect(0, 0, width, mWrittenRect.y);
-    MOZ_ASSERT(mImageDataLength >= length);
-    memset(mImageData, mClearValue, length);
-    mInvalidRect.UnionRect(mInvalidRect, updateRect);
-    mWrittenRect.UnionRect(mWrittenRect, updateRect);
-  }
-
-  const int32_t top = mWrittenRect.y + mWrittenRect.height;
-  if (MOZ_UNLIKELY(top < height)) {
-    const int32_t remainder = height - top;
-    auto updateRect = IntRect(0, top, width, remainder);
-    MOZ_ASSERT(mImageDataLength >= (uint32_t)(height * stride));
-    memset(mImageData + top * stride, mClearValue, remainder * stride);
-    mInvalidRect.UnionRect(mInvalidRect, updateRect);
-    mWrittenRect.UnionRect(mWrittenRect, updateRect);
-  }
-}
-
 uint8_t*
 AbstractSurfaceSink::DoResetToFirstRow()
 {
   mRow = 0;
   return GetRowPointer();
 }
 
 uint8_t*
@@ -131,17 +78,16 @@ AbstractSurfaceSink::DoAdvanceRow()
 
   // If we're vertically flipping the output, we need to flip the invalid rect. Since we're
   // dealing with an axis-aligned rect, only the y coordinate needs to change.
   int32_t invalidY = mFlipVertically
                    ? InputSize().height - (mRow + 1)
                    : mRow;
   mInvalidRect.UnionRect(mInvalidRect,
                          IntRect(0, invalidY, InputSize().width, 1));
-  mWrittenRect.UnionRect(mWrittenRect, mInvalidRect);
 
   mRow = min(uint32_t(InputSize().height), mRow + 1);
 
   return mRow < uint32_t(InputSize().height) ? GetRowPointer()
                                              : nullptr;
 }
 
 nsresult
@@ -165,24 +111,16 @@ SurfaceSink::Configure(const SurfaceConf
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   mImageData = aConfig.mDecoder->mImageData;
   mImageDataLength = aConfig.mDecoder->mImageDataLength;
   mFlipVertically = aConfig.mFlipVertically;
 
-  if (aConfig.mFormat == SurfaceFormat::B8G8R8X8) {
-    mClearRequired = true;
-    mClearValue = 0xFF;
-  } else if (aConfig.mDecoder->mCurrentFrame->OnHeap()) {
-    mClearRequired = true;
-    mClearValue = 0;
-  }
-
   MOZ_ASSERT(mImageData);
   MOZ_ASSERT(mImageDataLength ==
                uint32_t(surfaceSize.width * surfaceSize.height * sizeof(uint32_t)));
 
   ConfigureFilter(surfaceSize, sizeof(uint32_t));
   return NS_OK;
 }
 
@@ -205,17 +143,16 @@ SurfaceSink::GetRowPointer() const
   return rowPtr;
 }
 
 
 nsresult
 PalettedSurfaceSink::Configure(const PalettedSurfaceConfig& aConfig)
 {
   MOZ_ASSERT(aConfig.mFormat == SurfaceFormat::B8G8R8A8);
-  MOZ_ASSERT(mClearValue == 0);
 
   // For paletted surfaces, the surface size is the size of the frame rect.
   IntSize surfaceSize = aConfig.mFrameRect.Size();
 
   // Allocate the frame.
   // XXX(seth): Once every Decoder subclass uses SurfacePipe, we probably want
   // to allocate the frame directly here and get rid of Decoder::AllocateFrame
   // altogether.
@@ -227,17 +164,16 @@ PalettedSurfaceSink::Configure(const Pal
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   mImageData = aConfig.mDecoder->mImageData;
   mImageDataLength = aConfig.mDecoder->mImageDataLength;
   mFlipVertically = aConfig.mFlipVertically;
   mFrameRect = aConfig.mFrameRect;
-  mClearRequired = true;
 
   MOZ_ASSERT(mImageData);
   MOZ_ASSERT(mImageDataLength ==
                uint32_t(mFrameRect.width * mFrameRect.height * sizeof(uint8_t)));
 
   ConfigureFilter(surfaceSize, sizeof(uint8_t));
   return NS_OK;
 }
--- a/image/SurfacePipe.h
+++ b/image/SurfacePipe.h
@@ -101,27 +101,16 @@ public:
     : mRowPointer(nullptr)
     , mCol(0)
     , mPixelSize(0)
   { }
 
   virtual ~SurfaceFilter() { }
 
   /**
-   * Called when there are no more pixels from the caller to write. It will
-   * ensure that any unwritten pixels are cleared with an appropriate value.
-   */
-  void ZeroOutRestOfSurface()
-  {
-    DoZeroOutRestOfSurface();
-    mCol = 0;
-    mRowPointer = nullptr;
-  }
-
-  /**
    * Reset this surface to the first row. It's legal for this filter to throw
    * away any previously written data at this point, as all rows must be written
    * to on every pass.
    *
    * @return a pointer to the buffer for the first row.
    */
   uint8_t* ResetToFirstRow()
   {
@@ -305,38 +294,32 @@ public:
     PixelType* dest = reinterpret_cast<PixelType*>(mRowPointer);
 
     // Clear the area before |aStartColumn|.
     const size_t prefixLength = std::min<size_t>(mInputSize.width, aStartColumn);
     if (MOZ_UNLIKELY(prefixLength != aStartColumn)) {
       NS_WARNING("Provided starting column is out-of-bounds in WriteBuffer");
     }
 
-    uint8_t clear = 0;
-    bool clearRequired = GetClearValue(clear);
-    if (clearRequired) {
-      memset(dest, clear, mInputSize.width * sizeof(PixelType));
-    }
+    memset(dest, 0, mInputSize.width * sizeof(PixelType));
     dest += prefixLength;
 
     // Write |aLength| pixels from |aSource| into the row, with bounds checking.
     const size_t bufferLength =
       std::min<size_t>(mInputSize.width - prefixLength, aLength);
     if (MOZ_UNLIKELY(bufferLength != aLength)) {
       NS_WARNING("Provided buffer length is out-of-bounds in WriteBuffer");
     }
 
     memcpy(dest, aSource, bufferLength * sizeof(PixelType));
     dest += bufferLength;
 
     // Clear the rest of the row.
     const size_t suffixLength = mInputSize.width - (prefixLength + bufferLength);
-    if (clearRequired) {
-      memset(dest, clear, suffixLength * sizeof(PixelType));
-    }
+    memset(dest, 0, suffixLength * sizeof(PixelType));
 
     AdvanceRow();
 
     return IsSurfaceFinished() ? WriteState::FINISHED
                                : WriteState::NEED_MORE_DATA;
   }
 
   /**
@@ -347,28 +330,23 @@ public:
    *         Otherwise, returns WriteState::NEED_MORE_DATA.
    */
   WriteState WriteEmptyRow()
   {
     if (IsSurfaceFinished()) {
       return WriteState::FINISHED;  // Already done.
     }
 
-    uint8_t clear = 0;
-    if (GetClearValue(clear)) {
-      memset(mRowPointer, clear, mInputSize.width * mPixelSize);
-    }
+    memset(mRowPointer, 0, mInputSize.width * mPixelSize);
     AdvanceRow();
 
     return IsSurfaceFinished() ? WriteState::FINISHED
                                : WriteState::NEED_MORE_DATA;
   }
 
-  virtual bool GetClearValue(uint8_t& aValue) const = 0;
-
   /**
    * Write a row to the surface by calling a lambda that uses a pointer to
    * directly write to the row. This is unsafe because SurfaceFilter can't
    * provide any bounds checking; that's up to the lambda itself. For this
    * reason, the other Write*() methods should be preferred whenever it's
    * possible to use them; WriteUnsafeComputedRow() should be used only when
    * it's absolutely necessary to avoid extra copies or other performance
    * penalties.
@@ -423,39 +401,33 @@ public:
    * @return a SurfaceInvalidRect representing the region of the surface that
    *         has been written to since the last time TakeInvalidRect() was
    *         called, or Nothing() if the region is empty (i.e. nothing has been
    *         written).
    */
   virtual Maybe<SurfaceInvalidRect> TakeInvalidRect() = 0;
 
 protected:
-  /// @return the column for the next pixel to be written in the current row.
-  int32_t CurrentColumn() const { return mCol; }
-
-  /* Called by ZeroOutRestOfSurface() to actually perform the clearing of the
-   * unwritten pixels.
-   */
-  virtual void DoZeroOutRestOfSurface() = 0;
 
   /**
    * Called by ResetToFirstRow() to actually perform the reset. It's legal to
    * throw away any previously written data at this point, as all rows must be
    * written to on every pass.
    */
   virtual uint8_t* DoResetToFirstRow() = 0;
 
   /**
    * Called by AdvanceRow() to actually advance this filter to the next row.
    *
    * @return a pointer to the buffer for the next row, or nullptr to indicate
    *         that we've finished the entire surface.
    */
   virtual uint8_t* DoAdvanceRow() = 0;
 
+
   //////////////////////////////////////////////////////////////////////////////
   // Methods For Internal Use By Subclasses
   //////////////////////////////////////////////////////////////////////////////
 
   /**
    * Called by subclasses' Configure() methods to initialize the configuration
    * of this filter. After the filter is configured, calls ResetToFirstRow().
    *
@@ -507,17 +479,17 @@ private:
         continue;
       }
 
       switch (result.template as<WriteState>()) {
         case WriteState::NEED_MORE_DATA:
           return Some(WriteState::NEED_MORE_DATA);
 
         case WriteState::FINISHED:
-          ZeroOutRestOfSurface();
+          ZeroOutRestOfSurface<PixelType>();
           return Some(WriteState::FINISHED);
 
         case WriteState::FAILURE:
           // Note that we don't need to record this anywhere, because this
           // indicates an error in aFunc, and there's nothing wrong with our
           // machinery. The caller can recover as needed and continue writing to
           // the row.
           return Some(WriteState::FAILURE);
@@ -525,16 +497,22 @@ private:
     }
 
     AdvanceRow();  // We've finished the row.
 
     return IsSurfaceFinished() ? Some(WriteState::FINISHED)
                                : Nothing();
   }
 
+  template <typename PixelType>
+  void ZeroOutRestOfSurface()
+  {
+    WritePixels<PixelType>([]{ return AsVariant(PixelType(0)); });
+  }
+
   gfx::IntSize mInputSize;  /// The size of the input this filter expects.
   uint8_t* mRowPointer;     /// Pointer to the current row or null if finished.
   int32_t mCol;             /// The current column we're writing to. (0-indexed)
   uint8_t  mPixelSize;      /// How large each pixel in the surface is, in bytes.
 };
 
 class NullSurfaceSink;
 
@@ -560,20 +538,17 @@ public:
   static NullSurfaceSink* Singleton();
 
   virtual ~NullSurfaceSink() { }
 
   nsresult Configure(const NullSurfaceConfig& aConfig);
 
   Maybe<SurfaceInvalidRect> TakeInvalidRect() override { return Nothing(); }
 
-  bool GetClearValue(uint8_t& aValue) const override { return false; }
-
 protected:
-  void DoZeroOutRestOfSurface() override { }
   uint8_t* DoResetToFirstRow() override { return nullptr; }
   uint8_t* DoAdvanceRow() override { return nullptr; }
 
 private:
   static UniquePtr<NullSurfaceSink> sSingleton;  /// The singleton instance.
 };
 
 
@@ -683,32 +658,16 @@ public:
    *
    * @see SurfaceFilter::WriteEmptyRow() for the canonical documentation.
    */
   WriteState WriteEmptyRow()
   {
     return mHead->WriteEmptyRow();
   }
 
-  /**
-   * Write all remaining unset rows to an empty row to the surface. If some pixels
-   * have already been written to this row, they'll be discarded.
-   *
-   * @see SurfaceFilter::WriteEmptyRow() for the canonical documentation.
-   */
-  void ZeroOutRestOfSurface()
-  {
-    mHead->ZeroOutRestOfSurface();
-  }
-
-  bool GetClearValue(uint8_t& aValue) const
-  {
-    return mHead->GetClearValue(aValue);
-  }
-
   /// @return true if we've finished writing to the surface.
   bool IsSurfaceFinished() const { return mHead->IsSurfaceFinished(); }
 
   /// @see SurfaceFilter::TakeInvalidRect() for the canonical documentation.
   Maybe<SurfaceInvalidRect> TakeInvalidRect() const
   {
     return mHead->TakeInvalidRect();
   }
@@ -734,44 +693,31 @@ private:
 class AbstractSurfaceSink : public SurfaceFilter
 {
 public:
   AbstractSurfaceSink()
     : mImageData(nullptr)
     , mImageDataLength(0)
     , mRow(0)
     , mFlipVertically(false)
-    , mClearRequired(false)
-    , mClearValue(0)
   { }
 
   Maybe<SurfaceInvalidRect> TakeInvalidRect() override final;
 
-  bool GetClearValue(uint8_t& aValue) const override final
-  {
-    aValue = mClearValue;
-    return mClearRequired;
-  }
-
 protected:
-  void DoZeroOutRestOfSurface() override final;
   uint8_t* DoResetToFirstRow() override final;
   uint8_t* DoAdvanceRow() override final;
   virtual uint8_t* GetRowPointer() const = 0;
 
   gfx::IntRect mInvalidRect;  /// The region of the surface that has been written
                               /// to since the last call to TakeInvalidRect().
-  gfx::IntRect mWrittenRect;  /// The region of the surface that has been written
-                              /// to at least once.
   uint8_t*  mImageData;       /// A pointer to the beginning of the surface data.
   uint32_t  mImageDataLength; /// The length of the surface data.
   uint32_t  mRow;             /// The row to which we're writing. (0-indexed)
   bool      mFlipVertically;  /// If true, write the rows from top to bottom.
-  bool      mClearRequired;   /// If true, pixels need to be cleared to given.
-  uint8_t   mClearValue;      /// Value written to cleared pixels.
 };
 
 class SurfaceSink;
 
 /// A configuration struct for SurfaceSink.
 struct SurfaceConfig
 {
   using Filter = SurfaceSink;
--- a/image/decoders/nsBMPDecoder.cpp
+++ b/image/decoders/nsBMPDecoder.cpp
@@ -989,46 +989,43 @@ nsBMPDecoder::ReadRLESegment(const char*
 LexerTransition<nsBMPDecoder::State>
 nsBMPDecoder::ReadRLEDelta(const char* aData)
 {
   // Delta encoding makes it possible to skip pixels making part of the image
   // transparent.
   MOZ_ASSERT(mMayHaveTransparency);
   mDoesHaveTransparency = true;
 
-  // Handle the XDelta. This clears to the end of the row, which
-  // which is perfect if there's a Y delta and harmless if not.
-  uint8_t xDelta = uint8_t(aData[0]);
-  int32_t finalPos = std::min<int32_t>(mH.mWidth, mCurrentPos + xDelta);
-  uint32_t* dst = RowBuffer();
-  while (mCurrentPos < mH.mWidth) {
-    SetPixel(dst, 0, 0, 0, 0);
-    ++mCurrentPos;
+  if (mDownscaler) {
+    // Clear the skipped pixels. (This clears to the end of the row,
+    // which is perfect if there's a Y delta and harmless if not).
+    mDownscaler->ClearRestOfRow(/* aStartingAtCol = */ mCurrentPos);
+  }
+
+  // Handle the XDelta.
+  mCurrentPos += uint8_t(aData[0]);
+  if (mCurrentPos > mH.mWidth) {
+    mCurrentPos = mH.mWidth;
   }
 
   // Handle the Y Delta.
   int32_t yDelta = std::min<int32_t>(uint8_t(aData[1]), mCurrentRow);
-  if (yDelta > 0) {
+  mCurrentRow -= yDelta;
+
+  if (mDownscaler && yDelta > 0) {
     // Commit the current row (the first of the skipped rows).
-    mCurrentPos = 0;
-    FinishRow();
+    mDownscaler->CommitRow();
 
     // Clear and commit the remaining skipped rows.
     for (int32_t line = 1; line < yDelta; line++) {
-      dst = RowBuffer();
-      while (mCurrentPos < mH.mWidth) {
-        SetPixel(dst, 0, 0, 0, 0);
-        ++mCurrentPos;
-      }
-      mCurrentPos = 0;
-      FinishRow();
+      mDownscaler->ClearRow();
+      mDownscaler->CommitRow();
     }
   }
 
-  mCurrentPos = finalPos;
   return mCurrentRow == 0
        ? Transition::TerminateSuccess()
        : Transition::To(State::RLE_SEGMENT, RLE::SEGMENT_LENGTH);
 }
 
 LexerTransition<nsBMPDecoder::State>
 nsBMPDecoder::ReadRLEAbsolute(const char* aData, size_t aLength)
 {
--- a/image/decoders/nsGIFDecoder2.cpp
+++ b/image/decoders/nsGIFDecoder2.cpp
@@ -100,17 +100,16 @@ nsGIFDecoder2::~nsGIFDecoder2()
 {
   free(mGIFStruct.local_colormap);
 }
 
 nsresult
 nsGIFDecoder2::FinishInternal()
 {
   MOZ_ASSERT(!HasError(), "Shouldn't call FinishInternal after error!");
-  mPipe.ZeroOutRestOfSurface();
 
   // If the GIF got cut off, handle it anyway
   if (!IsMetadataDecode() && mGIFOpen) {
     if (mCurrentFrameIndex == mGIFStruct.images_decoded) {
       EndImageFrame();
     }
     PostDecodeDone(mGIFStruct.loop_count - 1);
     mGIFOpen = false;
@@ -231,17 +230,16 @@ nsGIFDecoder2::BeginImageFrame(const Int
   return NS_OK;
 }
 
 
 //******************************************************************************
 void
 nsGIFDecoder2::EndImageFrame()
 {
-  mPipe.ZeroOutRestOfSurface();
   Opacity opacity = Opacity::SOME_TRANSPARENCY;
 
   if (mGIFStruct.images_decoded == 0) {
     // We need to send invalidations for the first frame.
     FlushImageData();
 
     // The first frame was preallocated with alpha; if it wasn't transparent, we
     // should fix that. We can also mark it opaque unconditionally if we didn't
--- a/image/decoders/nsIconDecoder.cpp
+++ b/image/decoders/nsIconDecoder.cpp
@@ -22,23 +22,16 @@ nsIconDecoder::nsIconDecoder(RasterImage
  , mBytesPerRow()   // set by ReadHeader()
 {
   // Nothing to do
 }
 
 nsIconDecoder::~nsIconDecoder()
 { }
 
-nsresult
-nsIconDecoder::FinishInternal()
-{
-  mPipe.ZeroOutRestOfSurface();
-  return NS_OK;
-}
-
 LexerResult
 nsIconDecoder::DoDecode(SourceBufferIterator& aIterator, IResumable* aOnResume)
 {
   MOZ_ASSERT(!HasError(), "Shouldn't call DoDecode after error!");
 
   return mLexer.Lex(aIterator, aOnResume,
                     [=](State aState, const char* aData, size_t aLength) {
     switch (aState) {
--- a/image/decoders/nsIconDecoder.h
+++ b/image/decoders/nsIconDecoder.h
@@ -32,20 +32,18 @@ class RasterImage;
 //
 ////////////////////////////////////////////////////////////////////////////////
 
 class nsIconDecoder : public Decoder
 {
 public:
   virtual ~nsIconDecoder();
 
-protected:
   LexerResult DoDecode(SourceBufferIterator& aIterator,
                        IResumable* aOnResume) override;
-  nsresult FinishInternal() override;
 
 private:
   friend class DecoderFactory;
 
   // Decoders should only be instantiated via DecoderFactory.
   explicit nsIconDecoder(RasterImage* aImage);
 
   enum class State {
--- a/image/decoders/nsJPEGDecoder.cpp
+++ b/image/decoders/nsJPEGDecoder.cpp
@@ -164,61 +164,19 @@ nsJPEGDecoder::InitInternal()
   // Record app markers for ICC data
   for (uint32_t m = 0; m < 16; m++) {
     jpeg_save_markers(&mInfo, JPEG_APP0 + m, 0xFFFF);
   }
 
   return NS_OK;
 }
 
-void
-nsJPEGDecoder::ClearRemainingRows()
-{
-  if (mDownscaler) {
-    mDownscaler->ClearRemainingRows();
-    return;
-  }
-
-  if (!mImageData) {
-    return;
-  }
-
-  uint32_t offset = 0;
-  switch (mState) {
-    case JPEG_DECOMPRESS_PROGRESSIVE:
-      // If we already made one progressive pass, then we know we have written
-      // something valid to the output buffer.
-      if (mInfo.output_scan_number > 0) {
-        return;
-      }
-      MOZ_FALLTHROUGH;
-    case JPEG_DECOMPRESS_SEQUENTIAL:
-    case JPEG_HEADER:
-    case JPEG_START_DECOMPRESS:
-      offset = mInfo.output_scanline * mInfo.output_width * sizeof(uint32_t);
-      if (offset < mImageDataLength) {
-        break;
-      }
-      MOZ_FALLTHROUGH;
-    default:
-      return;
-  }
-
-  uint32_t length = mImageDataLength - offset;
-  MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
-         ("nsJPEGDecoder::ClearRemainingRows: %p clear %u unset bytes",
-          this, length));
-  memset(mImageData + offset, 0xFF, length);
-}
-
 nsresult
 nsJPEGDecoder::FinishInternal()
 {
-  ClearRemainingRows();
-
   // If we're not in any sort of error case, force our state to JPEG_DONE.
   if ((mState != JPEG_DONE && mState != JPEG_SINK_NON_JPEG_TRAILER) &&
       (mState != JPEG_ERROR) &&
       !IsMetadataDecode()) {
     mState = JPEG_DONE;
   }
 
   return NS_OK;
--- a/image/decoders/nsJPEGDecoder.h
+++ b/image/decoders/nsJPEGDecoder.h
@@ -75,17 +75,16 @@ private:
   enum class State
   {
     JPEG_DATA,
     FINISHED_JPEG_DATA
   };
 
   LexerTransition<State> ReadJPEGData(const char* aData, size_t aLength);
   LexerTransition<State> FinishedJPEGData();
-  void ClearRemainingRows();
 
   StreamingLexer<State> mLexer;
 
 public:
   struct jpeg_decompress_struct mInfo;
   struct jpeg_source_mgr mSourceMgr;
   decoder_error_mgr mErr;
   jstate mState;
--- a/image/decoders/nsPNGDecoder.cpp
+++ b/image/decoders/nsPNGDecoder.cpp
@@ -250,17 +250,16 @@ nsPNGDecoder::CreateFrame(const FrameInf
 // set timeout and frame disposal method for the current frame
 void
 nsPNGDecoder::EndImageFrame()
 {
   if (mFrameIsHidden) {
     return;
   }
 
-  mPipe.ZeroOutRestOfSurface();
   mNumFrames++;
 
   Opacity opacity = mFormat == SurfaceFormat::B8G8R8X8
                   ? Opacity::FULLY_OPAQUE
                   : Opacity::SOME_TRANSPARENCY;
 
   PostFrameStop(opacity, mAnimInfo.mDispose,
                 FrameTimeout::FromRawMilliseconds(mAnimInfo.mTimeout),
@@ -356,23 +355,16 @@ nsPNGDecoder::InitInternal()
   png_set_progressive_read_fn(mPNG, static_cast<png_voidp>(this),
                               nsPNGDecoder::info_callback,
                               nsPNGDecoder::row_callback,
                               nsPNGDecoder::end_callback);
 
   return NS_OK;
 }
 
-nsresult
-nsPNGDecoder::FinishInternal()
-{
-  mPipe.ZeroOutRestOfSurface();
-  return NS_OK;
-}
-
 LexerResult
 nsPNGDecoder::DoDecode(SourceBufferIterator& aIterator, IResumable* aOnResume)
 {
   MOZ_ASSERT(!HasError(), "Shouldn't call DoDecode after error!");
 
   return mLexer.Lex(aIterator, aOnResume,
                     [=](State aState, const char* aData, size_t aLength) {
     switch (aState) {
--- a/image/decoders/nsPNGDecoder.h
+++ b/image/decoders/nsPNGDecoder.h
@@ -24,17 +24,16 @@ public:
 
   /// @return true if this PNG is a valid ICO resource.
   bool IsValidICO() const;
 
 protected:
   nsresult InitInternal() override;
   LexerResult DoDecode(SourceBufferIterator& aIterator,
                        IResumable* aOnResume) override;
-  nsresult FinishInternal() override;
 
   Maybe<Telemetry::ID> SpeedHistogram() const override;
 
 private:
   friend class DecoderFactory;
 
   // Decoders should only be instantiated via DecoderFactory.
   explicit nsPNGDecoder(RasterImage* aImage);
--- a/image/imgFrame.cpp
+++ b/image/imgFrame.cpp
@@ -249,16 +249,22 @@ imgFrame::InitForDecoder(const nsIntSize
     }
 
     mLockedSurface = CreateLockedSurface(mRawSurface, mFrameRect.Size(), mFormat);
     if (!mLockedSurface) {
       NS_WARNING("Failed to create LockedSurface");
       mAborted = true;
       return NS_ERROR_OUT_OF_MEMORY;
     }
+
+    if (!ClearSurface(mRawSurface, mFrameRect.Size(), mFormat)) {
+      NS_WARNING("Could not clear allocated buffer");
+      mAborted = true;
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
   }
 
   return NS_OK;
 }
 
 nsresult
 imgFrame::InitWithDrawable(gfxDrawable* aDrawable,
                            const nsIntSize& aSize,
@@ -648,23 +654,16 @@ imgFrame::GetImageData() const
 {
   uint8_t* data;
   uint32_t length;
   GetImageData(&data, &length);
   return data;
 }
 
 bool
-imgFrame::OnHeap() const
-{
-  MonitorAutoLock lock(mMonitor);
-  return mRawSurface ? mRawSurface->OnHeap() : true;
-}
-
-bool
 imgFrame::GetIsPaletted() const
 {
   return mPalettedImageData != nullptr;
 }
 
 void
 imgFrame::GetPaletteData(uint32_t** aPalette, uint32_t* length) const
 {
--- a/image/imgFrame.h
+++ b/image/imgFrame.h
@@ -324,18 +324,16 @@ public:
   uint32_t GetBytesPerPixel() const { return GetIsPaletted() ? 1 : 4; }
 
   IntSize GetImageSize() const { return mImageSize; }
   IntRect GetRect() const { return mFrameRect; }
   IntSize GetSize() const { return mFrameRect.Size(); }
   void GetImageData(uint8_t** aData, uint32_t* length) const;
   uint8_t* GetImageData() const;
 
-  bool OnHeap() const;
-
   bool GetIsPaletted() const;
   void GetPaletteData(uint32_t** aPalette, uint32_t* length) const;
   uint32_t* GetPaletteData() const;
   uint8_t GetPaletteDepth() const { return mPaletteDepth; }
 
   AnimationData GetAnimationData() const;
 
   bool GetCompositingFailed() const;
--- a/image/test/gtest/Common.cpp
+++ b/image/test/gtest/Common.cpp
@@ -280,18 +280,17 @@ AssertCorrectPipelineFinalState(SurfaceF
   EXPECT_TRUE(invalidRect.isSome());
   EXPECT_EQ(aInputSpaceRect, invalidRect->mInputSpaceRect);
   EXPECT_EQ(aOutputSpaceRect, invalidRect->mOutputSpaceRect);
 }
 
 void
 CheckGeneratedImage(Decoder* aDecoder,
                     const IntRect& aRect,
-                    uint8_t aFuzz /* = 0 */,
-                    bool aPartial /* = false */)
+                    uint8_t aFuzz /* = 0 */)
 {
   RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
   RefPtr<SourceSurface> surface = currentFrame->GetSourceSurface();
   const IntSize surfaceSize = surface->GetSize();
 
   // This diagram shows how the surface is divided into regions that the code
   // below tests for the correct content. The output rect is the bounds of the
   // region labeled 'C'.
@@ -302,21 +301,16 @@ CheckGeneratedImage(Decoder* aDecoder,
   // |    B    |   C    |   D    |
   // +---------+--------+--------+
   // |             E             |
   // +---------------------------+
 
   // Check that the output rect itself is green. (Region 'C'.)
   EXPECT_TRUE(RectIsSolidColor(surface, aRect, BGRAColor::Green(), aFuzz));
 
-  // We only assume everything is written if it is a complete image.
-  if (aPartial) {
-    return;
-  }
-
   // Check that the area above the output rect is transparent. (Region 'A'.)
   EXPECT_TRUE(RectIsSolidColor(surface,
                                IntRect(0, 0, surfaceSize.width, aRect.y),
                                BGRAColor::Transparent(), aFuzz));
 
   // Check that the area to the left of the output rect is transparent. (Region 'B'.)
   EXPECT_TRUE(RectIsSolidColor(surface,
                                IntRect(0, aRect.y, aRect.x, aRect.YMost()),
@@ -331,17 +325,17 @@ CheckGeneratedImage(Decoder* aDecoder,
   // Check that the area below the output rect is transparent. (Region 'E'.)
   const int32_t heightBelow = surfaceSize.height - aRect.YMost();
   EXPECT_TRUE(RectIsSolidColor(surface,
                                IntRect(0, aRect.YMost(), surfaceSize.width, heightBelow),
                                BGRAColor::Transparent(), aFuzz));
 }
 
 void
-CheckGeneratedPalettedImage(Decoder* aDecoder, const IntRect& aRect, bool aPartial /* = false */)
+CheckGeneratedPalettedImage(Decoder* aDecoder, const IntRect& aRect)
 {
   RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
   IntSize imageSize = currentFrame->GetImageSize();
 
   // This diagram shows how the surface is divided into regions that the code
   // below tests for the correct content. The output rect is the bounds of the
   // region labeled 'C'.
   //
@@ -351,20 +345,16 @@ CheckGeneratedPalettedImage(Decoder* aDe
   // |    B    |   C    |   D    |
   // +---------+--------+--------+
   // |             E             |
   // +---------------------------+
 
   // Check that the output rect itself is all 255's. (Region 'C'.)
   EXPECT_TRUE(PalettedRectIsSolidColor(aDecoder, aRect, 255));
 
-  if (aPartial) {
-    return;
-  }
-
   // Check that the area above the output rect is all 0's. (Region 'A'.)
   EXPECT_TRUE(PalettedRectIsSolidColor(aDecoder,
                                        IntRect(0, 0, imageSize.width, aRect.y),
                                        0));
 
   // Check that the area to the left of the output rect is all 0's. (Region 'B'.)
   EXPECT_TRUE(PalettedRectIsSolidColor(aDecoder,
                                        IntRect(0, aRect.y, aRect.x, aRect.YMost()),
@@ -683,62 +673,10 @@ ImageTestCase DownscaledTransparentICOWi
                        TEST_CASE_IS_TRANSPARENT | TEST_CASE_IGNORE_OUTPUT);
 }
 
 ImageTestCase TruncatedSmallGIFTestCase()
 {
   return ImageTestCase("green-1x1-truncated.gif", "image/gif", IntSize(1, 1));
 }
 
-ImageTestCase TruncatedJPGTestCase()
-{
-  auto test = ImageTestCase("green.jpg", "image/jpeg", IntSize(100, 100),
-                            TEST_CASE_IS_TRANSPARENT | TEST_CASE_IS_FUZZY);
-  test.Truncate(1, IntRect(0, 0, 100, 94));
-  return test;
-}
-
-ImageTestCase TruncatedPNGTestCase()
-{
-  auto test = ImageTestCase("green.png", "image/png", IntSize(100, 100),
-                            TEST_CASE_IS_TRANSPARENT);
-  test.Truncate(32, IntRect(0, 0, 100, 91));
-  return test;
-}
-
-ImageTestCase TruncatedGIFTestCase()
-{
-  auto test = GreenGIFTestCase();
-  test.Truncate(32, IntRect(0, 0, 100, 62),
-                    IntRect(0, 62, 16, 1));
-  return test;
-}
-
-ImageTestCase TruncatedIconTestCase()
-{
-  auto test = GreenIconTestCase();
-  test.Truncate(32, IntRect(0, 0, 100, 99));
-  return test;
-}
-
-ImageTestCase TruncatedBMPTestCase()
-{
-  auto test = ImageTestCase("green.bmp", "image/bmp", IntSize(100, 100),
-                            TEST_CASE_HAS_TRUNCATED_COLOR);
-  test.Truncate(32, IntRect(0, 1, 100, 99),
-                IntRect(), BGRAColor::Black());
-  return test;
-}
-
-ImageTestCase TruncatedICOTestCase()
-{
-  // This ICO contains a 32-bit BMP, and we use a BMP's alpha data by default
-  // when the BMP is embedded in an ICO, so it's transparent.
-  auto test = ImageTestCase("green.ico", "image/x-icon", IntSize(100, 100),
-                            TEST_CASE_IS_TRANSPARENT |
-                            TEST_CASE_HAS_TRUNCATED_COLOR);
-  test.Truncate(2048, IntRect(0, 2, 100, 98),
-                IntRect(), BGRAColor::Black());
-  return test;
-}
-
 } // namespace image
 } // namespace mozilla
--- a/image/test/gtest/Common.h
+++ b/image/test/gtest/Common.h
@@ -26,100 +26,80 @@ namespace mozilla {
 namespace image {
 
 ///////////////////////////////////////////////////////////////////////////////
 // Types
 ///////////////////////////////////////////////////////////////////////////////
 
 enum TestCaseFlags
 {
-  TEST_CASE_DEFAULT_FLAGS       = 0,
-  TEST_CASE_IS_FUZZY            = 1 << 0,
-  TEST_CASE_HAS_ERROR           = 1 << 1,
-  TEST_CASE_IS_TRANSPARENT      = 1 << 2,
-  TEST_CASE_IS_ANIMATED         = 1 << 3,
-  TEST_CASE_IGNORE_OUTPUT       = 1 << 4,
-  TEST_CASE_HAS_TRUNCATED_COLOR = 1 << 5,
+  TEST_CASE_DEFAULT_FLAGS   = 0,
+  TEST_CASE_IS_FUZZY        = 1 << 0,
+  TEST_CASE_HAS_ERROR       = 1 << 1,
+  TEST_CASE_IS_TRANSPARENT  = 1 << 2,
+  TEST_CASE_IS_ANIMATED     = 1 << 3,
+  TEST_CASE_IGNORE_OUTPUT   = 1 << 4,
+};
+
+struct ImageTestCase
+{
+  ImageTestCase(const char* aPath,
+                const char* aMimeType,
+                gfx::IntSize aSize,
+                uint32_t aFlags = TEST_CASE_DEFAULT_FLAGS)
+    : mPath(aPath)
+    , mMimeType(aMimeType)
+    , mSize(aSize)
+    , mOutputSize(aSize)
+    , mFlags(aFlags)
+  { }
+
+  ImageTestCase(const char* aPath,
+                const char* aMimeType,
+                gfx::IntSize aSize,
+                gfx::IntSize aOutputSize,
+                uint32_t aFlags = TEST_CASE_DEFAULT_FLAGS)
+    : mPath(aPath)
+    , mMimeType(aMimeType)
+    , mSize(aSize)
+    , mOutputSize(aOutputSize)
+    , mFlags(aFlags)
+  { }
+
+  const char* mPath;
+  const char* mMimeType;
+  gfx::IntSize mSize;
+  gfx::IntSize mOutputSize;
+  uint32_t mFlags;
 };
 
 struct BGRAColor
 {
   BGRAColor() : BGRAColor(0, 0, 0, 0) { }
 
   BGRAColor(uint8_t aBlue, uint8_t aGreen, uint8_t aRed, uint8_t aAlpha)
     : mBlue(aBlue)
     , mGreen(aGreen)
     , mRed(aRed)
     , mAlpha(aAlpha)
   { }
 
   static BGRAColor Green() { return BGRAColor(0x00, 0xFF, 0x00, 0xFF); }
   static BGRAColor Red()   { return BGRAColor(0x00, 0x00, 0xFF, 0xFF); }
   static BGRAColor Blue()   { return BGRAColor(0xFF, 0x00, 0x00, 0xFF); }
-  static BGRAColor White() { return BGRAColor(0xFF, 0xFF, 0xFF, 0xFF); }
-  static BGRAColor Black() { return BGRAColor(0x00, 0x00, 0x00, 0xFF); }
   static BGRAColor Transparent() { return BGRAColor(0x00, 0x00, 0x00, 0x00); }
 
   uint32_t AsPixel() const { return gfxPackedPixel(mAlpha, mRed, mGreen, mBlue); }
 
   uint8_t mBlue;
   uint8_t mGreen;
   uint8_t mRed;
   uint8_t mAlpha;
 };
 
-struct ImageTestCase
-{
-  ImageTestCase(const char* aPath,
-                const char* aMimeType,
-                gfx::IntSize aSize,
-                uint32_t aFlags = TEST_CASE_DEFAULT_FLAGS)
-    : mPath(aPath)
-    , mMimeType(aMimeType)
-    , mSize(aSize)
-    , mOutputSize(aSize)
-    , mTruncatedBytes(0)
-    , mFlags(aFlags)
-  { }
-
-  ImageTestCase(const char* aPath,
-                const char* aMimeType,
-                gfx::IntSize aSize,
-                gfx::IntSize aOutputSize,
-                uint32_t aFlags = TEST_CASE_DEFAULT_FLAGS)
-    : mPath(aPath)
-    , mMimeType(aMimeType)
-    , mSize(aSize)
-    , mOutputSize(aOutputSize)
-    , mTruncatedBytes(0)
-    , mFlags(aFlags)
-  { }
-
-  void Truncate(uint32_t aTruncatedBytes,
-                gfx::IntRect aTruncatedRect,
-                gfx::IntRect aTruncatedPartialRow = gfx::IntRect(),
-                BGRAColor aTruncatedColor = BGRAColor::Transparent())
-  {
-    mTruncatedBytes = aTruncatedBytes;
-    mTruncatedRect = aTruncatedRect;
-    mTruncatedPartialRow = aTruncatedPartialRow;
-    mTruncatedColor = aTruncatedColor;
-  }
-
-  const char* mPath;
-  const char* mMimeType;
-  gfx::IntSize mSize;
-  gfx::IntSize mOutputSize;
-  gfx::IntRect mTruncatedRect;
-  gfx::IntRect mTruncatedPartialRow;
-  BGRAColor mTruncatedColor;
-  uint32_t mTruncatedBytes;
-  uint32_t mFlags;
-};
-
 
 ///////////////////////////////////////////////////////////////////////////////
 // General Helpers
 ///////////////////////////////////////////////////////////////////////////////
 
 /**
  * A RAII class that ensure that ImageLib services are available. Any tests that
  * require ImageLib to be initialized (for example, any test that uses the
@@ -321,40 +301,33 @@ void AssertCorrectPipelineFinalState(Sur
  *
  * @param aDecoder The decoder which contains the image. The decoder's current
  *                 frame will be checked.
  * @param aRect The region in the space of the output surface that the filter
  *              pipeline will actually write to. It's expected that pixels in
  *              this region are green, while pixels outside this region are
  *              transparent.
  * @param aFuzz The amount of fuzz to use in pixel comparisons.
- * @param aPartial Whether or not to assume the transparent / incomplete regions
- *                 have been written to yet.
  */
 void CheckGeneratedImage(Decoder* aDecoder,
                          const gfx::IntRect& aRect,
-                         uint8_t aFuzz = 0,
-                         bool aPartial = false);
+                         uint8_t aFuzz = 0);
 
 /**
  * Checks a generated paletted image for correctness. Reports any unexpected
  * deviation from the expected image as GTest failures.
  *
  * @param aDecoder The decoder which contains the image. The decoder's current
  *                 frame will be checked.
  * @param aRect The region in the space of the output surface that the filter
  *              pipeline will actually write to. It's expected that pixels in
  *              this region have a palette index of 255, while pixels outside
  *              this region have a palette index of 0.
- * @param aPartial Whether or not to assume the transparent / incomplete regions
- *                 have been written to yet.
  */
-void CheckGeneratedPalettedImage(Decoder* aDecoder,
-                                 const gfx::IntRect& aRect,
-                                 bool aPartial = false);
+void CheckGeneratedPalettedImage(Decoder* aDecoder, const gfx::IntRect& aRect);
 
 /**
  * Tests the result of calling WritePixels() using the provided SurfaceFilter
  * pipeline. The pipeline must be a normal (i.e., non-paletted) pipeline.
  *
  * The arguments are specified in the an order intended to minimize the number
  * of arguments that most test cases need to pass.
  *
--- a/image/test/gtest/TestDecoders.cpp
+++ b/image/test/gtest/TestDecoders.cpp
@@ -1,10 +1,8 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "gtest/gtest.h"
 
 #include "Common.h"
 #include "Decoder.h"
@@ -82,62 +80,33 @@ CheckDecoderResults(const ImageTestCase&
     return;
   }
 
   if (aTestCase.mFlags & TEST_CASE_IGNORE_OUTPUT) {
     return;
   }
 
   // Check the output.
-  uint8_t fuzz = aTestCase.mFlags & TEST_CASE_IS_FUZZY ? 1 : 0;
-  IntRect truncRect = aTestCase.mTruncatedRect;
-  auto colored = BGRAColor::Green();
-  if (truncRect.IsEmpty()) {
-    EXPECT_TRUE(IsSolidColor(surface, colored, fuzz));
-  } else {
-    IntSize size = surface->GetSize();
-    IntRect partialRow = aTestCase.mTruncatedPartialRow;
-    auto cleared = BGRAColor::Transparent();
-    if (aTestCase.mFlags & TEST_CASE_HAS_TRUNCATED_COLOR) {
-      cleared = aTestCase.mTruncatedColor;
-    } else if (surface->GetFormat() == SurfaceFormat::B8G8R8X8) {
-      cleared = BGRAColor::White();
-    }
-
-    EXPECT_TRUE(RowsAreSolidColor(surface, 0, truncRect.y, cleared, 0));
-    EXPECT_TRUE(RowsAreSolidColor(surface, truncRect.y, truncRect.height,
-                                  colored, fuzz));
-    EXPECT_TRUE(RowsAreSolidColor(surface,
-                                  truncRect.y + truncRect.height +
-                                    partialRow.height,
-                                  size.height, cleared, 0));
-    if (!partialRow.IsEmpty()) {
-      EXPECT_TRUE(RectIsSolidColor(surface, partialRow, colored, fuzz));
-      partialRow.x += partialRow.width;
-      partialRow.width = size.width - partialRow.x;
-      EXPECT_TRUE(RectIsSolidColor(surface, partialRow, cleared, 0));
-    }
-  }
+  EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Green(),
+                           aTestCase.mFlags & TEST_CASE_IS_FUZZY ? 1 : 0));
 }
 
 template <typename Func>
 void WithSingleChunkDecode(const ImageTestCase& aTestCase,
                            const Maybe<IntSize>& aOutputSize,
                            Func aResultChecker)
 {
   nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath);
   ASSERT_TRUE(inputStream != nullptr);
 
   // Figure out how much data we have.
   uint64_t length;
   nsresult rv = inputStream->Available(&length);
   ASSERT_TRUE(NS_SUCCEEDED(rv));
 
-  length -= aTestCase.mTruncatedBytes;
-
   // Write the data into a SourceBuffer.
   NotNull<RefPtr<SourceBuffer>> sourceBuffer = WrapNotNull(new SourceBuffer());
   sourceBuffer->ExpectLength(length);
   rv = sourceBuffer->AppendFromInputStream(inputStream, length);
   ASSERT_TRUE(NS_SUCCEEDED(rv));
   sourceBuffer->Complete(NS_OK);
 
   // Create a decoder.
@@ -250,56 +219,41 @@ TEST_F(ImageDecoders, PNGMultiChunk)
   CheckDecoderMultiChunk(GreenPNGTestCase());
 }
 
 TEST_F(ImageDecoders, PNGDownscaleDuringDecode)
 {
   CheckDownscaleDuringDecode(DownscaledPNGTestCase());
 }
 
-TEST_F(ImageDecoders, PNGTruncated)
-{
-  CheckDecoderSingleChunk(TruncatedPNGTestCase());
-}
-
 TEST_F(ImageDecoders, GIFSingleChunk)
 {
   CheckDecoderSingleChunk(GreenGIFTestCase());
 }
 
 TEST_F(ImageDecoders, GIFMultiChunk)
 {
   CheckDecoderMultiChunk(GreenGIFTestCase());
 }
 
 TEST_F(ImageDecoders, GIFDownscaleDuringDecode)
 {
   CheckDownscaleDuringDecode(DownscaledGIFTestCase());
 }
 
-TEST_F(ImageDecoders, GIFTruncated)
-{
-  CheckDecoderSingleChunk(TruncatedGIFTestCase());
-}
-
 TEST_F(ImageDecoders, JPGSingleChunk)
 {
   CheckDecoderSingleChunk(GreenJPGTestCase());
 }
 
 TEST_F(ImageDecoders, JPGMultiChunk)
 {
   CheckDecoderMultiChunk(GreenJPGTestCase());
 }
 
-TEST_F(ImageDecoders, JPGTruncated)
-{
-  CheckDecoderSingleChunk(TruncatedJPGTestCase());
-}
-
 TEST_F(ImageDecoders, JPGDownscaleDuringDecode)
 {
   CheckDownscaleDuringDecode(DownscaledJPGTestCase());
 }
 
 TEST_F(ImageDecoders, BMPSingleChunk)
 {
   CheckDecoderSingleChunk(GreenBMPTestCase());
@@ -310,21 +264,16 @@ TEST_F(ImageDecoders, BMPMultiChunk)
   CheckDecoderMultiChunk(GreenBMPTestCase());
 }
 
 TEST_F(ImageDecoders, BMPDownscaleDuringDecode)
 {
   CheckDownscaleDuringDecode(DownscaledBMPTestCase());
 }
 
-TEST_F(ImageDecoders, BMPTruncated)
-{
-  CheckDecoderSingleChunk(TruncatedBMPTestCase());
-}
-
 TEST_F(ImageDecoders, ICOSingleChunk)
 {
   CheckDecoderSingleChunk(GreenICOTestCase());
 }
 
 TEST_F(ImageDecoders, ICOMultiChunk)
 {
   CheckDecoderMultiChunk(GreenICOTestCase());
@@ -335,41 +284,31 @@ TEST_F(ImageDecoders, ICODownscaleDuring
   CheckDownscaleDuringDecode(DownscaledICOTestCase());
 }
 
 TEST_F(ImageDecoders, ICOWithANDMaskDownscaleDuringDecode)
 {
   CheckDownscaleDuringDecode(DownscaledTransparentICOWithANDMaskTestCase());
 }
 
-TEST_F(ImageDecoders, ICOTruncated)
-{
-  CheckDecoderSingleChunk(TruncatedICOTestCase());
-}
-
 TEST_F(ImageDecoders, IconSingleChunk)
 {
   CheckDecoderSingleChunk(GreenIconTestCase());
 }
 
 TEST_F(ImageDecoders, IconMultiChunk)
 {
   CheckDecoderMultiChunk(GreenIconTestCase());
 }
 
 TEST_F(ImageDecoders, IconDownscaleDuringDecode)
 {
   CheckDownscaleDuringDecode(DownscaledIconTestCase());
 }
 
-TEST_F(ImageDecoders, IconTruncated)
-{
-  CheckDecoderSingleChunk(TruncatedIconTestCase());
-}
-
 TEST_F(ImageDecoders, AnimatedGIFSingleChunk)
 {
   CheckDecoderSingleChunk(GreenFirstFrameAnimatedGIFTestCase());
 }
 
 TEST_F(ImageDecoders, AnimatedGIFMultiChunk)
 {
   CheckDecoderMultiChunk(GreenFirstFrameAnimatedGIFTestCase());
--- a/image/test/gtest/TestSurfaceSink.cpp
+++ b/image/test/gtest/TestSurfaceSink.cpp
@@ -80,26 +80,25 @@ DoCheckIterativeWrite(SurfaceFilter* aSi
   // Check that the generated image is correct.
   aCheckFunc();
 }
 
 template <typename WriteFunc> void
 CheckIterativeWrite(Decoder* aDecoder,
                     SurfaceSink* aSink,
                     const IntRect& aOutputRect,
-                    WriteFunc aWriteFunc,
-                    bool aPartial = false)
+                    WriteFunc aWriteFunc)
 {
   // Ignore the row passed to WriteFunc, since no callers use it.
   auto writeFunc = [&](uint32_t) {
     return aWriteFunc();
   };
 
   DoCheckIterativeWrite(aSink, writeFunc, [&]{
-    CheckGeneratedImage(aDecoder, aOutputRect, 0, aPartial);
+    CheckGeneratedImage(aDecoder, aOutputRect);
   });
 }
 
 template <typename WriteFunc> void
 CheckPalettedIterativeWrite(Decoder* aDecoder,
                             PalettedSurfaceSink* aSink,
                             const IntRect& aOutputRect,
                             WriteFunc aWriteFunc)
@@ -187,17 +186,16 @@ TEST(ImageSurfaceSink, SurfaceSinkInitia
     Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
     EXPECT_TRUE(invalidRect.isNothing());
 
     // Check that the surface is zero-initialized. We verify this by calling
     // CheckGeneratedImage() and telling it that we didn't write to the surface
     // anyway (i.e., we wrote to the empty rect); it will then expect the entire
     // surface to be transparent, which is what it should be if it was
     // zero-initialied.
-    aSink->ZeroOutRestOfSurface();
     CheckGeneratedImage(aDecoder, IntRect(0, 0, 0, 0));
   });
 }
 
 TEST(ImageSurfaceSink, SurfaceSinkWritePixels)
 {
   WithSurfaceSink<Orient::NORMAL>([](Decoder* aDecoder, SurfaceSink* aSink) {
     CheckWritePixels(aDecoder, aSink);
@@ -250,17 +248,17 @@ TEST(ImageSurfaceSink, SurfaceSinkWriteP
         return AsVariant(aState);
       }
       return count++ < 50 ? AsVariant(BGRAColor::Green().AsPixel())
                           : AsVariant(BGRAColor::Red().AsPixel());
     });
 
     EXPECT_EQ(aState, result);
     EXPECT_EQ(50u, count);
-    CheckGeneratedImage(aDecoder, IntRect(0, 0, 50, 1), 0, true);
+    CheckGeneratedImage(aDecoder, IntRect(0, 0, 50, 1));
 
     if (aState != WriteState::FINISHED) {
       // We should still be able to write more at this point.
       EXPECT_FALSE(aSink->IsSurfaceFinished());
 
       // Verify that we can resume writing. We'll finish up the same row.
       count = 0;
       result = aSink->WritePixels<uint32_t>([&]() -> NextPixel<uint32_t> {
@@ -269,17 +267,17 @@ TEST(ImageSurfaceSink, SurfaceSinkWriteP
         }
         ++count;
         return AsVariant(BGRAColor::Green().AsPixel());
       });
 
       EXPECT_EQ(WriteState::NEED_MORE_DATA, result);
       EXPECT_EQ(50u, count);
       EXPECT_FALSE(aSink->IsSurfaceFinished());
-      CheckGeneratedImage(aDecoder, IntRect(0, 0, 100, 1), 0, true);
+      CheckGeneratedImage(aDecoder, IntRect(0, 0, 100, 1));
 
       return;
     }
 
     // We should've finished the surface at this point.
     AssertCorrectPipelineFinalState(aSink,
                                     IntRect(0, 0, 100, 100),
                                     IntRect(0, 0, 100, 100));
@@ -329,17 +327,17 @@ TEST(ImageSurfaceSink, SurfaceSinkWriteP
       EXPECT_EQ(100u, count);
       EXPECT_FALSE(aSink->IsSurfaceFinished());
 
       Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
       EXPECT_TRUE(invalidRect.isSome());
       EXPECT_EQ(IntRect(0, row, 100, 1), invalidRect->mInputSpaceRect);
       EXPECT_EQ(IntRect(0, row, 100, 1), invalidRect->mOutputSpaceRect);
 
-      CheckGeneratedImage(aDecoder, IntRect(0, 0, 100, row + 1), 0, true);
+      CheckGeneratedImage(aDecoder, IntRect(0, 0, 100, row + 1));
     }
 
     // Write the final line, which should finish the surface.
     uint32_t count = 0;
     WriteState result = aSink->WritePixelsToRow<uint32_t>([&]{
       ++count;
       return AsVariant(BGRAColor::Green().AsPixel());
     });
@@ -385,33 +383,33 @@ TEST(ImageSurfaceSink, SurfaceSinkWriteP
         return AsVariant(aState);
       }
       return count++ < 50 ? AsVariant(BGRAColor::Green().AsPixel())
                           : AsVariant(BGRAColor::Red().AsPixel());
     });
 
     EXPECT_EQ(aState, result);
     EXPECT_EQ(50u, count);
-    CheckGeneratedImage(aDecoder, IntRect(0, 0, 50, 1), 0, true);
+    CheckGeneratedImage(aDecoder, IntRect(0, 0, 50, 1));
 
     if (aState != WriteState::FINISHED) {
       // We should still be able to write more at this point.
       EXPECT_FALSE(aSink->IsSurfaceFinished());
 
       // Verify that we can resume the same row and still stop at the end.
       count = 0;
       WriteState result = aSink->WritePixelsToRow<uint32_t>([&]{
         ++count;
         return AsVariant(BGRAColor::Green().AsPixel());
       });
 
       EXPECT_EQ(WriteState::NEED_MORE_DATA, result);
       EXPECT_EQ(50u, count);
       EXPECT_FALSE(aSink->IsSurfaceFinished());
-      CheckGeneratedImage(aDecoder, IntRect(0, 0, 100, 1), 0, true);
+      CheckGeneratedImage(aDecoder, IntRect(0, 0, 100, 1));
 
       return;
     }
 
     // We should've finished the surface at this point.
     AssertCorrectPipelineFinalState(aSink,
                                     IntRect(0, 0, 100, 100),
                                     IntRect(0, 0, 100, 100));
@@ -565,17 +563,16 @@ TEST(ImageSurfaceSink, SurfaceSinkWriteB
     WriteState result = aSink->WriteBuffer(nullBuffer);
 
     EXPECT_EQ(WriteState::FAILURE, result);
     EXPECT_FALSE(aSink->IsSurfaceFinished());
     Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
     EXPECT_TRUE(invalidRect.isNothing());
 
     // Check that nothing got written to the surface.
-    aSink->ZeroOutRestOfSurface();
     CheckGeneratedImage(aDecoder, IntRect(0, 0, 0, 0));
   });
 }
 
 TEST(ImageSurfaceSink, SurfaceSinkWriteEmptyRow)
 {
   WithSurfaceSink<Orient::NORMAL>([](Decoder* aDecoder, SurfaceSink* aSink) {
     {
@@ -661,17 +658,17 @@ TEST(ImageSurfaceSink, SurfaceSinkWriteU
     // check that the left side of the generated image is transparent and the
     // right side is green.
     CheckIterativeWrite(aDecoder, aSink, IntRect(50, 0, 50, 100), [&]{
       return aSink->WriteUnsafeComputedRow<uint32_t>([&](uint32_t* aRow,
                                                          uint32_t aLength) {
         EXPECT_EQ(100u, aLength );
         memcpy(aRow + 50, buffer, 50 * sizeof(uint32_t));
       });
-    }, true);
+    });
   });
 }
 
 TEST(ImageSurfaceSink, SurfaceSinkProgressivePasses)
 {
   WithSurfaceSink<Orient::NORMAL>([](Decoder* aDecoder, SurfaceSink* aSink) {
     {
       // Fill the image with a first pass of red.