diff --git a/gfx/thebes/gfxPrefs.h b/gfx/thebes/gfxPrefs.h index d3a0b33343..c05e62b0e4 100644 --- a/gfx/thebes/gfxPrefs.h +++ b/gfx/thebes/gfxPrefs.h @@ -236,7 +236,7 @@ private: DECL_GFX_PREF(Once, "image.cache.timeweight", ImageCacheTimeWeight, int32_t, 500); DECL_GFX_PREF(Once, "image.cache.size", ImageCacheSize, int32_t, 5*1024*1024); - DECL_GFX_PREF(Live, "image.downscale-during-decode.enabled", ImageDownscaleDuringDecodeEnabled, bool, false); + DECL_GFX_PREF(Live, "image.downscale-during-decode.enabled", ImageDownscaleDuringDecodeEnabled, bool, true); DECL_GFX_PREF(Live, "image.high_quality_downscaling.enabled", ImageHQDownscalingEnabled, bool, false); DECL_GFX_PREF(Live, "image.high_quality_downscaling.min_factor", ImageHQDownscalingMinFactor, uint32_t, 1000); DECL_GFX_PREF(Live, "image.high_quality_upscaling.max_size", ImageHQUpscalingMaxSize, uint32_t, 20971520); diff --git a/image/Downscaler.cpp b/image/Downscaler.cpp index fd93f66d7b..5b9c31e8ba 100644 --- a/image/Downscaler.cpp +++ b/image/Downscaler.cpp @@ -10,6 +10,7 @@ #include #include "gfxPrefs.h" #include "image_operations.h" +#include "mozilla/SSE.h" #include "convolver.h" #include "skia/include/core/SkTypes.h" @@ -69,6 +70,8 @@ Downscaler::BeginFrame(const nsIntSize& aOriginalSize, "Invalid original size"); mOriginalSize = aOriginalSize; + mScale = gfxSize(double(mOriginalSize.width) / mTargetSize.width, + double(mOriginalSize.height) / mTargetSize.height); mOutputBuffer = aOutputBuffer; mHasAlpha = aHasAlpha; @@ -162,7 +165,7 @@ Downscaler::CommitRow() if (mCurrentInLine == inLineToRead) { skia::ConvolveHorizontally(mRowBuffer.get(), *mXFilter, mWindow[mLinesInBuffer++], mHasAlpha, - /* use_sse2 = */ true); + supports_sse2()); } MOZ_ASSERT(mCurrentOutLine < mTargetSize.height, @@ -189,17 +192,25 @@ 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; } @@ -221,7 +232,7 @@ Downscaler::DownscaleInputLine() &mOutputBuffer[mCurrentOutLine * mTargetSize.width * sizeof(uint32_t)]; skia::ConvolveVertically(static_cast(filterValues), filterLength, mWindow.get(), mXFilter->num_values(), - outputLine, mHasAlpha, /* use_sse2 = */ true); + outputLine, mHasAlpha, supports_sse2()); mCurrentOutLine += 1; diff --git a/image/Downscaler.h b/image/Downscaler.h index 95f321cb1d..d676717912 100644 --- a/image/Downscaler.h +++ b/image/Downscaler.h @@ -15,7 +15,6 @@ #include "mozilla/UniquePtr.h" #include "nsRect.h" -#ifdef MOZ_ENABLE_SKIA namespace skia { class ConvolutionFilter1D; @@ -24,6 +23,18 @@ 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; +}; + +#ifdef MOZ_ENABLE_SKIA + /** * Downscaler is a high-quality, streaming image downscaler based upon Skia's * scaling implementation. @@ -47,6 +58,7 @@ public: 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. @@ -73,7 +85,7 @@ public: 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 @@ -88,6 +100,7 @@ private: nsIntSize mOriginalSize; nsIntSize mTargetSize; + gfxSize mScale; uint8_t* mOutputBuffer; @@ -107,21 +120,13 @@ private: bool mHasAlpha; }; -} // namespace image -} // namespace mozilla - - #else - /** * Downscaler requires Skia to work, so we provide a dummy implementation if * Skia is disabled that asserts if constructed. */ -namespace mozilla { -namespace image { - class Downscaler { public: @@ -132,6 +137,7 @@ public: const nsIntSize& OriginalSize() const { return nsIntSize(); } const nsIntSize& TargetSize() const { return nsIntSize(); } + const gfxSize& Scale() const { return gfxSize(1.0, 1.0); } nsresult BeginFrame(const nsIntSize&, uint8_t*, bool) { @@ -141,14 +147,13 @@ public: uint8_t* RowBuffer() { return nullptr; } void CommitRow() { } bool HasInvalidation() const { return false; } - nsIntRect TakeInvalidRect() { return nsIntRect(); } + DownscalerInvalidRect TakeInvalidRect() { return DownscalerInvalidRect(); } void ResetForNextProgressivePass() { } }; +#endif // MOZ_ENABLE_SKIA } // namespace image } // namespace mozilla -#endif - #endif // mozilla_image_Downscaler_h diff --git a/image/RasterImage.cpp b/image/RasterImage.cpp index 111209bfe9..c42e0422cf 100644 --- a/image/RasterImage.cpp +++ b/image/RasterImage.cpp @@ -1529,12 +1529,6 @@ RasterImage::Decode(const Maybe& aSize, uint32_t aFlags) return NS_OK; } - // Create a decoder. - nsRefPtr decoder = CreateDecoder(aSize, aFlags); - if (!decoder) { - return NS_ERROR_FAILURE; - } - if (mDownscaleDuringDecode && aSize) { // We're about to decode again, which may mean that some of the previous // sizes we've decoded at aren't useful anymore. We can allow them to @@ -1546,6 +1540,12 @@ RasterImage::Decode(const Maybe& aSize, uint32_t aFlags) SurfaceCache::UnlockSurfaces(ImageKey(this)); } + // Create a decoder. + nsRefPtr decoder = CreateDecoder(aSize, aFlags); + if (!decoder) { + return NS_ERROR_FAILURE; + } + if (aSize) { // This isn't a size decode (which doesn't send any early notifications), so // send out notifications right away. diff --git a/image/SurfaceCache.cpp b/image/SurfaceCache.cpp index 08e70241af..59b9c5d505 100644 --- a/image/SurfaceCache.cpp +++ b/image/SurfaceCache.cpp @@ -257,7 +257,7 @@ public: // Try for a perfect match first. nsRefPtr surface; mSurfaces.Get(aSurfaceKey, getter_AddRefs(surface)); - if (surface) { + if (surface && surface->IsDecoded()) { return surface.forget(); } diff --git a/image/decoders/nsJPEGDecoder.cpp b/image/decoders/nsJPEGDecoder.cpp index f8c3c10446..eb045f6476 100644 --- a/image/decoders/nsJPEGDecoder.cpp +++ b/image/decoders/nsJPEGDecoder.cpp @@ -722,16 +722,16 @@ nsJPEGDecoder::OutputScanlines(bool* suspend) } } - 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"); } diff --git a/layout/base/nsDisplayListInvalidation.h b/layout/base/nsDisplayListInvalidation.h index f40ef967a3..07c94f3056 100644 --- a/layout/base/nsDisplayListInvalidation.h +++ b/layout/base/nsDisplayListInvalidation.h @@ -131,7 +131,8 @@ public: return false; } - if (mLastDrawResult == mozilla::image::DrawResult::SUCCESS) { + if (mLastDrawResult == mozilla::image::DrawResult::SUCCESS || + mLastDrawResult == mozilla::image::DrawResult::BAD_IMAGE) { return false; } diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index c6a64bbdfe..6183138031 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -4111,7 +4111,7 @@ pref("image.cache.size", 5242880); pref("image.cache.timeweight", 500); // Whether we attempt to downscale images during decoding. -pref("image.downscale-during-decode.enabled", false); +pref("image.downscale-during-decode.enabled", true); // The default Accept header sent for images loaded over HTTP(S) pref("image.http.accept", "image/webp,image/png,image/*;q=0.8,*/*;q=0.5");