Bug 1145560 - During downscale-during-decode, compute the original size invalid rect based on the target size invalid rect. r=tn
authorSeth Fowler <mark.seth.fowler@gmail.com>
Tue, 05 May 2015 15:35:34 -0700
changeset 273859 8fb4d69e9f44d67d754cbf2ce8d7a81ffb66a6e8
parent 273858 522de3d0ee4ec864348f93d7ceba8e80408143af
child 273860 fdec95a4cc199c8e85f46a3bed37e4593467be23
push id863
push userraliiev@mozilla.com
push dateMon, 03 Aug 2015 13:22:43 +0000
treeherdermozilla-release@f6321b14228d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstn
bugs1145560
milestone40.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1145560 - During downscale-during-decode, compute the original size invalid rect based on the target size invalid rect. r=tn
image/decoders/nsJPEGDecoder.cpp
image/src/Downscaler.cpp
image/src/Downscaler.h
--- a/image/decoders/nsJPEGDecoder.cpp
+++ b/image/decoders/nsJPEGDecoder.cpp
@@ -714,26 +714,26 @@ nsJPEGDecoder::OutputScanlines(bool* sus
         sampleRow += 3;
       }
 
       if (mDownscaler) {
         mDownscaler->CommitRow();
       }
   }
 
-  if (top != mInfo.output_scanline) {
+  if (mDownscaler && mDownscaler->HasInvalidation()) {
+    DownscalerInvalidRect invalidRect = mDownscaler->TakeInvalidRect();
+    PostInvalidation(invalidRect.mOriginalSizeRect,
+                     Some(invalidRect.mTargetSizeRect));
+    MOZ_ASSERT(!mDownscaler->HasInvalidation());
+  } else if (!mDownscaler && top != mInfo.output_scanline) {
     PostInvalidation(nsIntRect(0, top,
                                mInfo.output_width,
-                               mInfo.output_scanline - top),
-                     mDownscaler ? Some(mDownscaler->TakeInvalidRect())
-                                 : Nothing());
+                               mInfo.output_scanline - top));
   }
-
-  MOZ_ASSERT(!mDownscaler || !mDownscaler->HasInvalidation(),
-             "Didn't send downscaler's invalidation");
 }
 
 // Override the standard error method in the IJG JPEG decoder code.
 METHODDEF(void)
 my_error_exit (j_common_ptr cinfo)
 {
   decoder_error_mgr* err = (decoder_error_mgr*) cinfo->err;
 
--- a/image/src/Downscaler.cpp
+++ b/image/src/Downscaler.cpp
@@ -64,16 +64,18 @@ Downscaler::BeginFrame(const nsIntSize& 
   MOZ_ASSERT(mTargetSize.width <= aOriginalSize.width,
              "Created a downscaler, but width is larger");
   MOZ_ASSERT(mTargetSize.height <= aOriginalSize.height,
              "Created a downscaler, but height is larger");
   MOZ_ASSERT(aOriginalSize.width > 0 && aOriginalSize.height > 0,
              "Invalid original size");
 
   mOriginalSize = aOriginalSize;
+  mScale = gfxSize(double(mOriginalSize.width) / mTargetSize.width,
+                   double(mOriginalSize.height) / mTargetSize.height);
   mOutputBuffer = aOutputBuffer;
   mHasAlpha = aHasAlpha;
 
   ResetForNextProgressivePass();
   ReleaseWindow();
 
   auto resizeMethod = skia::ImageOperations::RESIZE_LANCZOS3;
 
@@ -178,27 +180,35 @@ Downscaler::CommitRow()
 }
 
 bool
 Downscaler::HasInvalidation() const
 {
   return mCurrentOutLine > mPrevInvalidatedLine;
 }
 
-nsIntRect
+DownscalerInvalidRect
 Downscaler::TakeInvalidRect()
 {
   if (MOZ_UNLIKELY(!HasInvalidation())) {
-    return nsIntRect();
+    return DownscalerInvalidRect();
   }
 
-  nsIntRect invalidRect(0, mPrevInvalidatedLine,
-                        mTargetSize.width,
-                        mCurrentOutLine - mPrevInvalidatedLine);
+  DownscalerInvalidRect invalidRect;
+
+  // Compute the target size invalid rect.
+  invalidRect.mTargetSizeRect =
+    nsIntRect(0, mPrevInvalidatedLine,
+              mTargetSize.width, mCurrentOutLine - mPrevInvalidatedLine);
   mPrevInvalidatedLine = mCurrentOutLine;
+
+  // Compute the original size invalid rect.
+  invalidRect.mOriginalSizeRect = invalidRect.mTargetSizeRect;
+  invalidRect.mOriginalSizeRect.ScaleRoundOut(mScale.width, mScale.height);
+
   return invalidRect;
 }
 
 void
 Downscaler::DownscaleInputLine()
 {
   typedef skia::ConvolutionFilter1D::Fixed FilterValue;
 
--- a/image/src/Downscaler.h
+++ b/image/src/Downscaler.h
@@ -20,16 +20,26 @@
 namespace skia {
   class ConvolutionFilter1D;
 } // namespace skia
 
 namespace mozilla {
 namespace image {
 
 /**
+ * DownscalerInvalidRect wraps two invalidation rects: one in terms of the
+ * original image size, and one in terms of the target size.
+ */
+struct DownscalerInvalidRect
+{
+  nsIntRect mOriginalSizeRect;
+  nsIntRect mTargetSizeRect;
+};
+
+/**
  * Downscaler is a high-quality, streaming image downscaler based upon Skia's
  * scaling implementation.
  *
  * Decoders can construct a Downscaler once they know their target size, then
  * call BeginFrame() for each frame they decode. They should write a decoded row
  * into the buffer returned by RowBuffer(), and then call CommitRow() to signal
  * that they have finished.
  *
@@ -42,16 +52,17 @@ class Downscaler
 {
 public:
   /// Constructs a new Downscaler which to scale to size @aTargetSize.
   explicit Downscaler(const nsIntSize& aTargetSize);
   ~Downscaler();
 
   const nsIntSize& OriginalSize() const { return mOriginalSize; }
   const nsIntSize& TargetSize() const { return mTargetSize; }
+  const gfxSize& Scale() const { return mScale; }
 
   /**
    * Begins a new frame and reinitializes the Downscaler.
    *
    * @param aOriginalSize The original size of this frame, before scaling.
    * @param aOutputBuffer The buffer to which the Downscaler should write its
    *                      output; this is the same buffer where the Decoder
    *                      would write its output when not downscaling during
@@ -68,31 +79,32 @@ public:
 
   /// Signals that the decoder has finished writing a row into the row buffer.
   void CommitRow();
 
   /// Returns true if there is a non-empty invalid rect available.
   bool HasInvalidation() const;
 
   /// Takes the Downscaler's current invalid rect and resets it.
-  nsIntRect TakeInvalidRect();
+  DownscalerInvalidRect TakeInvalidRect();
 
   /**
    * Resets the Downscaler's position in the image, for a new progressive pass
    * over the same frame. Because the same data structures can be reused, this
    * is more efficient than calling BeginFrame.
    */
   void ResetForNextProgressivePass();
 
 private:
   void DownscaleInputLine();
   void ReleaseWindow();
 
   nsIntSize mOriginalSize;
   nsIntSize mTargetSize;
+  gfxSize mScale;
 
   uint8_t* mOutputBuffer;
 
   UniquePtr<uint8_t[]> mRowBuffer;
   UniquePtr<uint8_t*[]> mWindow;
 
   UniquePtr<skia::ConvolutionFilter1D> mXFilter;
   UniquePtr<skia::ConvolutionFilter1D> mYFilter;