зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1119774 (Part 3) - Make it possible to propagate a target size to the decoder. r=tn
This commit is contained in:
Родитель
e518285564
Коммит
38cc052b30
|
@ -599,12 +599,15 @@ Decoder::PostFrameStop(Opacity aFrameOpacity /* = Opacity::TRANSPARENT */,
|
|||
// If we're not sending partial invalidations, then we send an invalidation
|
||||
// here when the first frame is complete.
|
||||
if (!mSendPartialInvalidations && !mIsAnimated) {
|
||||
mInvalidRect.UnionRect(mInvalidRect, mCurrentFrame->GetRect());
|
||||
mInvalidRect.UnionRect(mInvalidRect,
|
||||
nsIntRect(nsIntPoint(0, 0), GetSize()));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Decoder::PostInvalidation(nsIntRect& aRect)
|
||||
Decoder::PostInvalidation(const nsIntRect& aRect,
|
||||
const Maybe<nsIntRect>& aRectAtTargetSize
|
||||
/* = Nothing() */)
|
||||
{
|
||||
// We should be mid-frame
|
||||
NS_ABORT_IF_FALSE(mInFrame, "Can't invalidate when not mid-frame!");
|
||||
|
@ -614,7 +617,7 @@ Decoder::PostInvalidation(nsIntRect& aRect)
|
|||
// or we're past the first frame.
|
||||
if (mSendPartialInvalidations && !mIsAnimated) {
|
||||
mInvalidRect.UnionRect(mInvalidRect, aRect);
|
||||
mCurrentFrame->ImageUpdated(aRect);
|
||||
mCurrentFrame->ImageUpdated(aRectAtTargetSize.valueOr(aRect));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -127,6 +127,24 @@ public:
|
|||
mSizeDecode = aSizeDecode;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this decoder supports downscale-during-decode, sets the target size that
|
||||
* this image should be decoded to.
|
||||
*
|
||||
* If this decoder *doesn't* support downscale-during-decode, returns
|
||||
* NS_ERROR_NOT_AVAILABLE. If the provided size is unacceptable, returns
|
||||
* another error.
|
||||
*
|
||||
* Returning NS_OK from this method is a promise that the decoder will decode
|
||||
* the image to the requested target size unless it encounters an error.
|
||||
*
|
||||
* This must be called before Init() is called.
|
||||
*/
|
||||
virtual nsresult SetTargetSize(const nsIntSize& aSize)
|
||||
{
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether should send partial invalidations.
|
||||
*
|
||||
|
@ -233,6 +251,12 @@ public:
|
|||
PostSize(aSize.width, aSize.height, aOrientation);
|
||||
}
|
||||
|
||||
nsIntSize GetSize() const
|
||||
{
|
||||
MOZ_ASSERT(HasSize());
|
||||
return mImageMetadata.GetSize();
|
||||
}
|
||||
|
||||
// Use HistogramCount as an invalid Histogram ID
|
||||
virtual Telemetry::ID SpeedHistogram() { return Telemetry::HistogramCount; }
|
||||
|
||||
|
@ -332,9 +356,19 @@ protected:
|
|||
int32_t aTimeout = 0,
|
||||
BlendMethod aBlendMethod = BlendMethod::OVER);
|
||||
|
||||
// Called by the decoders when they have a region to invalidate. We may not
|
||||
// actually pass these invalidations on right away.
|
||||
void PostInvalidation(nsIntRect& aRect);
|
||||
/**
|
||||
* Called by the decoders when they have a region to invalidate. We may not
|
||||
* actually pass these invalidations on right away.
|
||||
*
|
||||
* @param aRect The invalidation rect in the coordinate system of the unscaled
|
||||
* image (that is, the image at its intrinsic size).
|
||||
* @param aRectAtTargetSize If not Nothing(), the invalidation rect in the
|
||||
* coordinate system of the scaled image (that is,
|
||||
* the image at our target decoding size). This must
|
||||
* be supplied if we're downscaling during decode.
|
||||
*/
|
||||
void PostInvalidation(const nsIntRect& aRect,
|
||||
const Maybe<nsIntRect>& aRectAtTargetSize = Nothing());
|
||||
|
||||
// Called by the decoders when they have successfully decoded the image. This
|
||||
// may occur as the result of the decoder getting to the appropriate point in
|
||||
|
|
|
@ -53,6 +53,7 @@ public:
|
|||
|
||||
int32_t GetWidth() const { return mSize->width; }
|
||||
int32_t GetHeight() const { return mSize->height; }
|
||||
nsIntSize GetSize() const { return *mSize; }
|
||||
Orientation GetOrientation() const { return *mOrientation; }
|
||||
|
||||
private:
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "gfxContext.h"
|
||||
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
|
@ -337,8 +338,7 @@ RasterImage::Init(const char* aMimeType,
|
|||
}
|
||||
|
||||
// Create the initial size decoder.
|
||||
nsresult rv = Decode(DecodeStrategy::ASYNC, DECODE_FLAGS_DEFAULT,
|
||||
/* aDoSizeDecode = */ true);
|
||||
nsresult rv = Decode(DecodeStrategy::ASYNC, Nothing(), DECODE_FLAGS_DEFAULT);
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -509,11 +509,18 @@ RasterImage::LookupFrame(uint32_t aFrameNum,
|
|||
aFlags ^ FLAG_DECODE_NO_PREMULTIPLY_ALPHA);
|
||||
}
|
||||
|
||||
if (!ref && !mHasSize) {
|
||||
// We can't request a decode without knowing our intrinsic size. Give up.
|
||||
return DrawableFrameRef();
|
||||
}
|
||||
|
||||
if (!ref) {
|
||||
// The OS threw this frame away. We need to redecode if we can.
|
||||
MOZ_ASSERT(!mAnim, "Animated frames should be locked");
|
||||
|
||||
WantDecodedFrames(aFlags, aShouldSyncNotify);
|
||||
// XXX(seth): We'll add downscale-during-decode-related logic here in a
|
||||
// later part, but for now we just use our intrinsic size.
|
||||
WantDecodedFrames(mSize, aFlags, aShouldSyncNotify);
|
||||
|
||||
// If we were able to sync decode, we should already have the frame. If we
|
||||
// had to decode asynchronously, maybe we've gotten lucky.
|
||||
|
@ -1129,8 +1136,7 @@ RasterImage::OnImageDataComplete(nsIRequest*, nsISupports*, nsresult aStatus,
|
|||
// We need to guarantee that we've gotten the image's size, or at least
|
||||
// determined that we won't be able to get it, before we deliver the load
|
||||
// event. That means we have to do a synchronous size decode here.
|
||||
Decode(DecodeStrategy::SYNC_IF_POSSIBLE, DECODE_FLAGS_DEFAULT,
|
||||
/* aDoSizeDecode = */ true);
|
||||
Decode(DecodeStrategy::SYNC_IF_POSSIBLE, Nothing(), DECODE_FLAGS_DEFAULT);
|
||||
}
|
||||
|
||||
// Determine our final status, giving precedence to Necko failure codes. We
|
||||
|
@ -1256,13 +1262,16 @@ RasterImage::CanDiscard() {
|
|||
|
||||
// Sets up a decoder for this image.
|
||||
already_AddRefed<Decoder>
|
||||
RasterImage::CreateDecoder(bool aDoSizeDecode, uint32_t aFlags)
|
||||
RasterImage::CreateDecoder(const Maybe<nsIntSize>& aSize, uint32_t aFlags)
|
||||
{
|
||||
// Make sure we actually get size before doing a full decode.
|
||||
if (aDoSizeDecode) {
|
||||
MOZ_ASSERT(!mHasSize, "Should not do unnecessary size decodes");
|
||||
} else {
|
||||
if (aSize) {
|
||||
MOZ_ASSERT(mHasSize, "Must do a size decode before a full decode!");
|
||||
MOZ_ASSERT(mDownscaleDuringDecode || *aSize == mSize,
|
||||
"Can only decode to our intrinsic size if we're not allowed to "
|
||||
"downscale-during-decode");
|
||||
} else {
|
||||
MOZ_ASSERT(!mHasSize, "Should not do unnecessary size decodes");
|
||||
}
|
||||
|
||||
// Figure out which decoder we want.
|
||||
|
@ -1303,27 +1312,36 @@ RasterImage::CreateDecoder(bool aDoSizeDecode, uint32_t aFlags)
|
|||
MOZ_ASSERT(decoder, "Should have a decoder now");
|
||||
|
||||
// Initialize the decoder.
|
||||
decoder->SetSizeDecode(aDoSizeDecode);
|
||||
decoder->SetSizeDecode(!aSize);
|
||||
decoder->SetSendPartialInvalidations(!mHasBeenDecoded);
|
||||
decoder->SetImageIsTransient(mTransient);
|
||||
decoder->SetDecodeFlags(DecodeFlags(aFlags));
|
||||
if (!aDoSizeDecode) {
|
||||
if (aSize) {
|
||||
// We already have the size; tell the decoder so it can preallocate a
|
||||
// frame. By default, we create an ARGB frame with no offset. If decoders
|
||||
// need a different type, they need to ask for it themselves.
|
||||
decoder->SetSize(mSize, mOrientation);
|
||||
decoder->NeedNewFrame(0, 0, 0, mSize.width, mSize.height,
|
||||
decoder->NeedNewFrame(0, 0, 0, aSize->width, aSize->height,
|
||||
SurfaceFormat::B8G8R8A8);
|
||||
decoder->AllocateFrame();
|
||||
}
|
||||
decoder->SetIterator(mSourceBuffer->Iterator());
|
||||
|
||||
// Set a target size for downscale-during-decode if applicable.
|
||||
if (mDownscaleDuringDecode && aSize && *aSize != mSize) {
|
||||
DebugOnly<nsresult> rv = decoder->SetTargetSize(*aSize);
|
||||
MOZ_ASSERT(nsresult(rv) != NS_ERROR_NOT_AVAILABLE,
|
||||
"We're downscale-during-decode but decoder doesn't support it?");
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv), "Bad downscale-during-decode target size?");
|
||||
}
|
||||
|
||||
decoder->Init();
|
||||
|
||||
if (NS_FAILED(decoder->GetDecoderError())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!aDoSizeDecode) {
|
||||
if (!aSize) {
|
||||
Telemetry::GetHistogramById(Telemetry::IMAGE_DECODE_COUNT)->Subtract(mDecodeCount);
|
||||
mDecodeCount++;
|
||||
Telemetry::GetHistogramById(Telemetry::IMAGE_DECODE_COUNT)->Add(mDecodeCount);
|
||||
|
@ -1343,12 +1361,13 @@ RasterImage::CreateDecoder(bool aDoSizeDecode, uint32_t aFlags)
|
|||
}
|
||||
|
||||
void
|
||||
RasterImage::WantDecodedFrames(uint32_t aFlags, bool aShouldSyncNotify)
|
||||
RasterImage::WantDecodedFrames(const nsIntSize& aSize, uint32_t aFlags,
|
||||
bool aShouldSyncNotify)
|
||||
{
|
||||
if (aShouldSyncNotify) {
|
||||
// We can sync notify, which means we can also sync decode.
|
||||
if (aFlags & FLAG_SYNC_DECODE) {
|
||||
Decode(DecodeStrategy::SYNC_IF_POSSIBLE, aFlags);
|
||||
Decode(DecodeStrategy::SYNC_IF_POSSIBLE, Some(aSize), aFlags);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1356,12 +1375,12 @@ RasterImage::WantDecodedFrames(uint32_t aFlags, bool aShouldSyncNotify)
|
|||
// case that we're redecoding an image (see bug 845147).
|
||||
Decode(mHasBeenDecoded ? DecodeStrategy::ASYNC
|
||||
: DecodeStrategy::SYNC_FOR_SMALL_IMAGES,
|
||||
aFlags);
|
||||
Some(aSize), aFlags);
|
||||
return;
|
||||
}
|
||||
|
||||
// We can't sync notify, so do an async decode.
|
||||
Decode(DecodeStrategy::ASYNC, aFlags);
|
||||
Decode(DecodeStrategy::ASYNC, Some(aSize), aFlags);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
@ -1426,29 +1445,30 @@ RasterImage::IsDecoded()
|
|||
|
||||
NS_IMETHODIMP
|
||||
RasterImage::Decode(DecodeStrategy aStrategy,
|
||||
uint32_t aFlags,
|
||||
bool aDoSizeDecode /* = false */)
|
||||
const Maybe<nsIntSize>& aSize,
|
||||
uint32_t aFlags)
|
||||
{
|
||||
MOZ_ASSERT(aDoSizeDecode || NS_IsMainThread());
|
||||
MOZ_ASSERT(!aSize || NS_IsMainThread());
|
||||
|
||||
if (mError) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// If we don't have a size yet, we can't do any other decoding.
|
||||
if (!mHasSize && !aDoSizeDecode) {
|
||||
if (!mHasSize && aSize) {
|
||||
mWantFullDecode = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Create a decoder.
|
||||
nsRefPtr<Decoder> decoder = CreateDecoder(aDoSizeDecode, aFlags);
|
||||
nsRefPtr<Decoder> decoder = CreateDecoder(aSize, aFlags);
|
||||
if (!decoder) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (!aDoSizeDecode) {
|
||||
// Send out early notifications right away.
|
||||
if (aSize) {
|
||||
// This isn't a size decode (which doesn't send any early notifications), so
|
||||
// send out notifications right away.
|
||||
NotifyProgress(decoder->TakeProgress(),
|
||||
decoder->TakeInvalidRect(),
|
||||
decoder->GetDecodeFlags());
|
||||
|
|
|
@ -325,12 +325,26 @@ private:
|
|||
// Decoding.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
already_AddRefed<Decoder> CreateDecoder(bool aDoSizeDecode, uint32_t aFlags);
|
||||
/**
|
||||
* Creates and runs a decoder, either synchronously or asynchronously
|
||||
* according to @aStrategy. Passes the provided target size @aSize and decode
|
||||
* flags @aFlags to CreateDecoder. If a size decode is desired, pass Nothing
|
||||
* for @aSize.
|
||||
*/
|
||||
NS_IMETHOD Decode(DecodeStrategy aStrategy,
|
||||
const Maybe<nsIntSize>& aSize,
|
||||
uint32_t aFlags);
|
||||
|
||||
void WantDecodedFrames(uint32_t aFlags, bool aShouldSyncNotify);
|
||||
/**
|
||||
* Creates a new decoder with a target size of @aSize and decode flags
|
||||
* specified by @aFlags. If a size decode is desired, pass Nothing() for
|
||||
* @aSize.
|
||||
*/
|
||||
already_AddRefed<Decoder> CreateDecoder(const Maybe<nsIntSize>& aSize,
|
||||
uint32_t aFlags);
|
||||
|
||||
NS_IMETHOD Decode(DecodeStrategy aStrategy, uint32_t aFlags,
|
||||
bool aDoSizeDecode = false);
|
||||
void WantDecodedFrames(const nsIntSize& aSize, uint32_t aFlags,
|
||||
bool aShouldSyncNotify);
|
||||
|
||||
private: // data
|
||||
nsIntSize mSize;
|
||||
|
|
Загрузка…
Ссылка в новой задаче