Bug 1118655 - Use decode-on-draw only, and ignore RequestDecode and the like, when APZ and downscale-during-decode are enabled. r=tn

This commit is contained in:
Seth Fowler 2015-01-19 15:46:55 -08:00
parent 066c6a4768
commit 6bbece46f8
10 changed files with 93 additions and 18 deletions

View File

@ -322,7 +322,7 @@ pref("media.fragmented-mp4.gonk.enabled", true);
pref("media.video-queue.default-size", 3);
// optimize images' memory usage
pref("image.mem.decodeondraw", true);
pref("image.mem.decodeondraw", false);
pref("image.mem.allow_locking_in_content_processes", false); /* don't allow image locking */
// Limit the surface cache to 1/8 of main memory or 128MB, whichever is smaller.
// Almost everything that was factored into 'max_decoded_image_kb' is now stored

View File

@ -45,7 +45,8 @@ ComputeImageFlags(ImageURL* uri, const nsCString& aMimeType, bool isMultiPart)
// We default to the static globals.
bool isDiscardable = gfxPrefs::ImageMemDiscardable();
bool doDecodeOnDraw = gfxPrefs::ImageMemDecodeOnDraw();
bool doDecodeOnDraw = gfxPrefs::ImageMemDecodeOnDraw() &&
gfxPrefs::AsyncPanZoomEnabled();
bool doDownscaleDuringDecode = gfxPrefs::ImageDownscaleDuringDecodeEnabled();
// We want UI to be as snappy as possible and not to flicker. Disable
@ -64,9 +65,12 @@ ComputeImageFlags(ImageURL* uri, const nsCString& aMimeType, bool isMultiPart)
isDiscardable = doDecodeOnDraw = false;
}
// Downscale-during-decode is only enabled for certain content types.
if (doDownscaleDuringDecode && !ShouldDownscaleDuringDecode(aMimeType)) {
// Downscale-during-decode and decode-on-draw are only enabled for certain
// content types.
if ((doDownscaleDuringDecode || doDecodeOnDraw) &&
!ShouldDownscaleDuringDecode(aMimeType)) {
doDownscaleDuringDecode = false;
doDecodeOnDraw = false;
}
// For multipart/x-mixed-replace, we basically want a direct channel to the

View File

@ -35,6 +35,7 @@
#include "mozilla/gfx/2D.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/Likely.h"
#include "mozilla/RefPtr.h"
#include "mozilla/Move.h"
#include "mozilla/MemoryReporting.h"
@ -271,6 +272,7 @@ RasterImage::RasterImage(ProgressTracker* aProgressTracker,
mSourceBuffer(new SourceBuffer()),
mFrameCount(0),
mHasSize(false),
mBlockedOnload(false),
mDecodeOnDraw(false),
mTransient(false),
mDiscardable(false),
@ -1166,26 +1168,58 @@ RasterImage::OnImageDataComplete(nsIRequest*, nsISupports*, nsresult aStatus,
DoError();
}
// Notify our listeners, which will fire this image's load event.
MOZ_ASSERT(mHasSize || mError, "Need to know size before firing load event");
MOZ_ASSERT(!mHasSize ||
(mProgressTracker->GetProgress() & FLAG_SIZE_AVAILABLE),
"Should have notified that the size is available if we have it");
Progress loadProgress = LoadCompleteProgress(aLastPart, mError, finalStatus);
if (mBlockedOnload) {
// For decode-on-draw images, we want to send notifications as if we've
// already finished decoding. Otherwise some observers will never even try
// to draw.
MOZ_ASSERT(mDecodeOnDraw, "Blocked onload but not decode-on-draw");
loadProgress |= FLAG_FRAME_COMPLETE |
FLAG_DECODE_COMPLETE |
FLAG_ONLOAD_UNBLOCKED;
}
// Notify our listeners, which will fire this image's load event.
NotifyProgress(loadProgress);
return finalStatus;
}
void
RasterImage::BlockOnloadForDecodeOnDraw()
{
if (mHasSourceData) {
// OnImageDataComplete got called before we got to run. No point in blocking
// onload now.
return;
}
// Block onload. We'll unblock it in OnImageDataComplete.
mBlockedOnload = true;
NotifyProgress(FLAG_DECODE_STARTED | FLAG_ONLOAD_BLOCKED);
}
nsresult
RasterImage::OnImageDataAvailable(nsIRequest*,
nsISupports*,
nsIInputStream* aInStr,
uint64_t,
uint64_t aOffset,
uint32_t aCount)
{
nsresult rv;
if (MOZ_UNLIKELY(mDecodeOnDraw && aOffset == 0)) {
nsCOMPtr<nsIRunnable> runnable =
NS_NewRunnableMethod(this, &RasterImage::BlockOnloadForDecodeOnDraw);
NS_DispatchToMainThread(runnable);
}
// WriteToSourceBuffer always consumes everything it gets if it doesn't run
// out of memory.
uint32_t bytesRead;
@ -1405,6 +1439,11 @@ RasterImage::WantDecodedFrames(const nsIntSize& aSize, uint32_t aFlags,
NS_IMETHODIMP
RasterImage::RequestDecode()
{
// For decode-on-draw images, we only act on RequestDecodeForSize.
if (mDecodeOnDraw) {
return NS_OK;
}
return RequestDecodeForSize(mSize, DECODE_FLAGS_DEFAULT);
}
@ -1417,6 +1456,11 @@ RasterImage::StartDecoding()
NS_NewRunnableMethod(this, &RasterImage::StartDecoding));
}
// For decode-on-draw images, we only act on RequestDecodeForSize.
if (mDecodeOnDraw) {
return NS_OK;
}
return RequestDecodeForSize(mSize, FLAG_SYNC_DECODE);
}
@ -1457,7 +1501,7 @@ bool
RasterImage::IsDecoded()
{
// XXX(seth): We need to get rid of this; it's not reliable.
return mHasBeenDecoded || mError;
return mHasBeenDecoded || mError || (mDecodeOnDraw && mHasSourceData);
}
NS_IMETHODIMP

View File

@ -242,6 +242,8 @@ public:
nsresult aStatus,
bool aLastPart) MOZ_OVERRIDE;
void BlockOnloadForDecodeOnDraw();
/**
* A hint of the number of bytes of source data that the image contains. If
* called early on, this can help reduce copying and reallocations by
@ -387,6 +389,7 @@ private: // data
// Boolean flags (clustered together to conserve space):
bool mHasSize:1; // Has SetSize() been called?
bool mBlockedOnload:1; // Did send BLOCK_ONLOAD?
bool mDecodeOnDraw:1; // Decoding on draw?
bool mTransient:1; // Is the image short-lived?
bool mDiscardable:1; // Is container discardable?

View File

@ -1425,8 +1425,7 @@ nsDisplayImage::GetContainer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder)
{
nsRefPtr<ImageContainer> container;
nsresult rv = mImage->GetImageContainer(aManager, getter_AddRefs(container));
NS_ENSURE_SUCCESS(rv, nullptr);
mImage->GetImageContainer(aManager, getter_AddRefs(container));
return container.forget();
}

View File

@ -434,8 +434,7 @@ nsImageBoxFrame::GetContainer(LayerManager* aManager)
}
nsRefPtr<ImageContainer> container;
nsresult rv = imgCon->GetImageContainer(aManager, getter_AddRefs(container));
NS_ENSURE_SUCCESS(rv, nullptr);
imgCon->GetImageContainer(aManager, getter_AddRefs(container));
return container.forget();
}

View File

@ -563,7 +563,7 @@ pref("media.fragmented-mp4.android-media-codec.enabled", true);
pref("media.fragmented-mp4.android-media-codec.preferred", true);
// optimize images memory usage
pref("image.mem.decodeondraw", true);
pref("image.mem.decodeondraw", false);
#ifdef NIGHTLY_BUILD
// Shumway component (SWF player) is disabled by default. Also see bug 904346.

View File

@ -3789,7 +3789,7 @@ pref("image.mem.discardable", true);
// Prevents images from automatically being decoded on load, instead allowing
// them to be decoded on demand when they are drawn.
pref("image.mem.decodeondraw", true);
pref("image.mem.decodeondraw", false);
// Allows image locking of decoded image data in content processes.
pref("image.mem.allow_locking_in_content_processes", true);

View File

@ -135,6 +135,16 @@ nsAlertsIconListener::OnLoadComplete(imgIRequest* aRequest)
mIconRequest = nullptr;
}
nsCOMPtr<imgIContainer> image;
rv = aRequest->GetImage(getter_AddRefs(image));
MOZ_ASSERT(image);
// Ask the image to decode at its intrinsic size.
int32_t width = 0, height = 0;
image->GetWidth(&width);
image->GetHeight(&height);
image->RequestDecodeForSize(nsIntSize(width, height), imgIContainer::FLAG_NONE);
return NS_OK;
}
@ -227,8 +237,6 @@ nsAlertsIconListener::StartRequest(const nsAString & aImageUrl, bool aInPrivateB
if (NS_FAILED(rv))
return rv;
mIconRequest->StartDecoding();
return NS_OK;
}

View File

@ -314,9 +314,6 @@ nsMenuItemIconX::LoadIcon(nsIURI* aIconURI)
getter_AddRefs(mIconRequest));
if (NS_FAILED(rv)) return rv;
// We need to request the icon be decoded (bug 573583, bug 705516).
mIconRequest->StartDecoding();
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
@ -331,6 +328,27 @@ nsMenuItemIconX::Notify(imgIRequest* aRequest,
int32_t aType,
const nsIntRect* aData)
{
if (aType == imgINotificationObserver::LOAD_COMPLETE) {
// Make sure the image loaded successfully.
uint32_t status = imgIRequest::STATUS_ERROR;
if (NS_FAILED(aRequest->GetImageStatus(&status)) ||
(status & imgIRequest::STATUS_ERROR)) {
mIconRequest->Cancel(NS_BINDING_ABORTED);
mIconRequest = nullptr;
return NS_ERROR_FAILURE;
}
nsCOMPtr<imgIContainer> image;
aRequest->GetImage(getter_AddRefs(image));
MOZ_ASSERT(image);
// Ask the image to decode at its intrinsic size.
int32_t width = 0, height = 0;
image->GetWidth(&width);
image->GetHeight(&height);
image->RequestDecodeForSize(nsIntSize(width, height), imgIContainer::FLAG_NONE);
}
if (aType == imgINotificationObserver::FRAME_COMPLETE) {
return OnFrameComplete(aRequest);
}