mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1060869 (Part 2) - Store the first frame of a RasterImage in the SurfaceCache. r=tn
This commit is contained in:
parent
e8dc7026c2
commit
9084851cc0
@ -9,6 +9,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "mozilla/Endian.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "nsICODecoder.h"
|
||||
|
||||
#include "RasterImage.h"
|
||||
@ -344,7 +345,7 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount,
|
||||
mContainedDecoder->SetSizeDecode(IsSizeDecode());
|
||||
mContainedDecoder->InitSharedDecoder(mImageData, mImageDataLength,
|
||||
mColormap, mColormapSize,
|
||||
mCurrentFrame);
|
||||
Move(mRefForContainedDecoder));
|
||||
if (!WriteToContainedDecoder(mSignature, PNGSIGNATURESIZE, aStrategy)) {
|
||||
return;
|
||||
}
|
||||
@ -422,7 +423,7 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount,
|
||||
mContainedDecoder->SetSizeDecode(IsSizeDecode());
|
||||
mContainedDecoder->InitSharedDecoder(mImageData, mImageDataLength,
|
||||
mColormap, mColormapSize,
|
||||
mCurrentFrame);
|
||||
Move(mRefForContainedDecoder));
|
||||
|
||||
// The ICO format when containing a BMP does not include the 14 byte
|
||||
// bitmap file header. To use the code of the BMP decoder we need to
|
||||
@ -640,15 +641,21 @@ nsICODecoder::NeedsNewFrame() const
|
||||
nsresult
|
||||
nsICODecoder::AllocateFrame()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (mContainedDecoder) {
|
||||
nsresult rv = mContainedDecoder->AllocateFrame();
|
||||
mCurrentFrame = mContainedDecoder->GetCurrentFrame();
|
||||
rv = mContainedDecoder->AllocateFrame();
|
||||
mCurrentFrame = mContainedDecoder->GetCurrentFrameRef();
|
||||
mProgress |= mContainedDecoder->TakeProgress();
|
||||
mInvalidRect.Union(mContainedDecoder->TakeInvalidRect());
|
||||
return rv;
|
||||
}
|
||||
|
||||
return Decoder::AllocateFrame();
|
||||
// Grab a strong ref that we'll later hand over to the contained decoder. This
|
||||
// lets us avoid creating a RawAccessFrameRef off-main-thread.
|
||||
rv = Decoder::AllocateFrame();
|
||||
mRefForContainedDecoder = GetCurrentFrameRef();
|
||||
return rv;
|
||||
}
|
||||
|
||||
} // namespace image
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "Decoder.h"
|
||||
#include "imgFrame.h"
|
||||
#include "nsBMPDecoder.h"
|
||||
#include "nsPNGDecoder.h"
|
||||
#include "ICOFileHeaders.h"
|
||||
@ -82,6 +83,7 @@ private:
|
||||
uint32_t mRowBytes; // How many bytes of the row were already received
|
||||
int32_t mOldLine; // Previous index of the line
|
||||
nsRefPtr<Decoder> mContainedDecoder; // Contains either a BMP or PNG resource
|
||||
RawAccessFrameRef mRefForContainedDecoder; // Avoid locking off-main-thread
|
||||
|
||||
char mDirEntryArray[ICODIRENTRYSIZE]; // Holds the current dir entry buffer
|
||||
IconDirEntry mDirEntry; // Holds a decoded dir entry
|
||||
|
@ -16,7 +16,6 @@ namespace image {
|
||||
|
||||
Decoder::Decoder(RasterImage &aImage)
|
||||
: mImage(aImage)
|
||||
, mCurrentFrame(nullptr)
|
||||
, mProgress(NoProgress)
|
||||
, mImageData(nullptr)
|
||||
, mColormap(nullptr)
|
||||
@ -68,18 +67,19 @@ Decoder::Init()
|
||||
// Initializes a decoder whose image and observer is already being used by a
|
||||
// parent decoder
|
||||
void
|
||||
Decoder::InitSharedDecoder(uint8_t* imageData, uint32_t imageDataLength,
|
||||
uint32_t* colormap, uint32_t colormapSize,
|
||||
imgFrame* currentFrame)
|
||||
Decoder::InitSharedDecoder(uint8_t* aImageData, uint32_t aImageDataLength,
|
||||
uint32_t* aColormap, uint32_t aColormapSize,
|
||||
RawAccessFrameRef&& aFrameRef)
|
||||
{
|
||||
// No re-initializing
|
||||
NS_ABORT_IF_FALSE(!mInitialized, "Can't re-initialize a decoder!");
|
||||
|
||||
mImageData = imageData;
|
||||
mImageDataLength = imageDataLength;
|
||||
mColormap = colormap;
|
||||
mColormapSize = colormapSize;
|
||||
mCurrentFrame = currentFrame;
|
||||
mImageData = aImageData;
|
||||
mImageDataLength = aImageDataLength;
|
||||
mColormap = aColormap;
|
||||
mColormapSize = aColormapSize;
|
||||
mCurrentFrame = Move(aFrameRef);
|
||||
|
||||
// We have all the frame data, so we've started the frame.
|
||||
if (!IsSizeDecode()) {
|
||||
PostFrameStart();
|
||||
@ -206,11 +206,13 @@ Decoder::Finish(ShutdownReason aReason)
|
||||
}
|
||||
}
|
||||
|
||||
// Set image metadata before calling DecodingComplete, because DecodingComplete calls Optimize().
|
||||
// Set image metadata before calling DecodingComplete, because
|
||||
// DecodingComplete calls Optimize().
|
||||
mImageMetadata.SetOnImage(&mImage);
|
||||
|
||||
if (mDecodeDone) {
|
||||
mImage.DecodingComplete();
|
||||
MOZ_ASSERT(HasError() || mCurrentFrame, "Should have an error or a frame");
|
||||
mImage.DecodingComplete(mCurrentFrame.get());
|
||||
}
|
||||
}
|
||||
|
||||
@ -230,34 +232,22 @@ Decoder::AllocateFrame()
|
||||
MOZ_ASSERT(mNeedsNewFrame);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsresult rv;
|
||||
nsRefPtr<imgFrame> frame;
|
||||
if (mNewFrameData.mPaletteDepth) {
|
||||
rv = mImage.EnsureFrame(mNewFrameData.mFrameNum, mNewFrameData.mOffsetX,
|
||||
mNewFrameData.mOffsetY, mNewFrameData.mWidth,
|
||||
mNewFrameData.mHeight, mNewFrameData.mFormat,
|
||||
mNewFrameData.mPaletteDepth,
|
||||
&mImageData, &mImageDataLength,
|
||||
&mColormap, &mColormapSize,
|
||||
getter_AddRefs(frame));
|
||||
} else {
|
||||
rv = mImage.EnsureFrame(mNewFrameData.mFrameNum, mNewFrameData.mOffsetX,
|
||||
mNewFrameData.mOffsetY, mNewFrameData.mWidth,
|
||||
mNewFrameData.mHeight, mNewFrameData.mFormat,
|
||||
&mImageData, &mImageDataLength,
|
||||
getter_AddRefs(frame));
|
||||
}
|
||||
mCurrentFrame = mImage.EnsureFrame(mNewFrameData.mFrameNum,
|
||||
mNewFrameData.mFrameRect,
|
||||
mDecodeFlags,
|
||||
mNewFrameData.mFormat,
|
||||
mNewFrameData.mPaletteDepth,
|
||||
mCurrentFrame.get());
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mCurrentFrame = frame;
|
||||
} else {
|
||||
mCurrentFrame = nullptr;
|
||||
}
|
||||
if (mCurrentFrame) {
|
||||
// Gather the raw pointers the decoders will use.
|
||||
mCurrentFrame->GetImageData(&mImageData, &mImageDataLength);
|
||||
mCurrentFrame->GetPaletteData(&mColormap, &mColormapSize);
|
||||
|
||||
// Notify if appropriate
|
||||
if (NS_SUCCEEDED(rv) && mNewFrameData.mFrameNum == mFrameCount) {
|
||||
PostFrameStart();
|
||||
} else if (NS_FAILED(rv)) {
|
||||
if (mNewFrameData.mFrameNum == mFrameCount) {
|
||||
PostFrameStart();
|
||||
}
|
||||
} else {
|
||||
PostDataError();
|
||||
}
|
||||
|
||||
@ -271,7 +261,7 @@ Decoder::AllocateFrame()
|
||||
mNeedsToFlushData = true;
|
||||
}
|
||||
|
||||
return rv;
|
||||
return mCurrentFrame ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
void
|
||||
@ -338,8 +328,8 @@ Decoder::PostFrameStart()
|
||||
// Decoder implementations should only call this method if they successfully
|
||||
// appended the frame to the image. So mFrameCount should always match that
|
||||
// reported by the Image.
|
||||
NS_ABORT_IF_FALSE(mFrameCount == mImage.GetNumFrames(),
|
||||
"Decoder frame count doesn't match image's!");
|
||||
MOZ_ASSERT(mFrameCount == mImage.GetNumFrames(),
|
||||
"Decoder frame count doesn't match image's!");
|
||||
}
|
||||
|
||||
void
|
||||
@ -389,7 +379,6 @@ Decoder::PostDecodeDone(int32_t aLoopCount /* = 0 */)
|
||||
mDecodeDone = true;
|
||||
|
||||
mImageMetadata.SetLoopCount(aLoopCount);
|
||||
mImageMetadata.SetIsNonPremultiplied(GetDecodeFlags() & DECODER_NO_PREMULTIPLY_ALPHA);
|
||||
|
||||
mProgress |= FLAG_DECODE_COMPLETE;
|
||||
}
|
||||
@ -424,7 +413,9 @@ Decoder::NeedNewFrame(uint32_t framenum, uint32_t x_offset, uint32_t y_offset,
|
||||
// We don't want images going back in time or skipping frames.
|
||||
MOZ_ASSERT(framenum == mFrameCount || framenum == (mFrameCount - 1));
|
||||
|
||||
mNewFrameData = NewFrameData(framenum, x_offset, y_offset, width, height, format, palette_depth);
|
||||
mNewFrameData = NewFrameData(framenum,
|
||||
nsIntRect(x_offset, y_offset, width, height),
|
||||
format, palette_depth);
|
||||
mNeedsNewFrame = true;
|
||||
}
|
||||
|
||||
|
@ -36,9 +36,9 @@ public:
|
||||
*
|
||||
* Notifications Sent: TODO
|
||||
*/
|
||||
void InitSharedDecoder(uint8_t* imageData, uint32_t imageDataLength,
|
||||
uint32_t* colormap, uint32_t colormapSize,
|
||||
imgFrame* currentFrame);
|
||||
void InitSharedDecoder(uint8_t* aImageData, uint32_t aImageDataLength,
|
||||
uint32_t* aColormap, uint32_t aColormapSize,
|
||||
RawAccessFrameRef&& aFrameRef);
|
||||
|
||||
/**
|
||||
* Writes data to the decoder.
|
||||
@ -186,12 +186,17 @@ public:
|
||||
// status code from that attempt. Clears mNewFrameData.
|
||||
virtual nsresult AllocateFrame();
|
||||
|
||||
already_AddRefed<imgFrame> GetCurrentFrame() const
|
||||
already_AddRefed<imgFrame> GetCurrentFrame()
|
||||
{
|
||||
nsRefPtr<imgFrame> frame = mCurrentFrame;
|
||||
nsRefPtr<imgFrame> frame = mCurrentFrame.get();
|
||||
return frame.forget();
|
||||
}
|
||||
|
||||
RawAccessFrameRef GetCurrentFrameRef()
|
||||
{
|
||||
return mCurrentFrame->RawAccessRef();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~Decoder();
|
||||
|
||||
@ -263,7 +268,7 @@ protected:
|
||||
*
|
||||
*/
|
||||
RasterImage &mImage;
|
||||
nsRefPtr<imgFrame> mCurrentFrame;
|
||||
RawAccessFrameRef mCurrentFrame;
|
||||
ImageMetadata mImageMetadata;
|
||||
nsIntRect mInvalidRect; // Tracks an invalidation region in the current frame.
|
||||
Progress mProgress;
|
||||
@ -289,28 +294,22 @@ private:
|
||||
|
||||
struct NewFrameData
|
||||
{
|
||||
NewFrameData()
|
||||
{}
|
||||
NewFrameData() { }
|
||||
|
||||
NewFrameData(uint32_t aFrameNum, const nsIntRect& aFrameRect,
|
||||
gfx::SurfaceFormat aFormat, uint8_t aPaletteDepth)
|
||||
: mFrameNum(aFrameNum)
|
||||
, mFrameRect(aFrameRect)
|
||||
, mFormat(aFormat)
|
||||
, mPaletteDepth(aPaletteDepth)
|
||||
{ }
|
||||
|
||||
NewFrameData(uint32_t num, uint32_t offsetx, uint32_t offsety,
|
||||
uint32_t width, uint32_t height,
|
||||
gfx::SurfaceFormat format, uint8_t paletteDepth)
|
||||
: mFrameNum(num)
|
||||
, mOffsetX(offsetx)
|
||||
, mOffsetY(offsety)
|
||||
, mWidth(width)
|
||||
, mHeight(height)
|
||||
, mFormat(format)
|
||||
, mPaletteDepth(paletteDepth)
|
||||
{}
|
||||
uint32_t mFrameNum;
|
||||
uint32_t mOffsetX;
|
||||
uint32_t mOffsetY;
|
||||
uint32_t mWidth;
|
||||
uint32_t mHeight;
|
||||
nsIntRect mFrameRect;
|
||||
gfx::SurfaceFormat mFormat;
|
||||
uint8_t mPaletteDepth;
|
||||
};
|
||||
|
||||
NewFrameData mNewFrameData;
|
||||
bool mNeedsNewFrame;
|
||||
bool mNeedsToFlushData;
|
||||
|
@ -27,10 +27,6 @@ ImageMetadata::SetOnImage(RasterImage* image)
|
||||
}
|
||||
|
||||
image->SetLoopCount(mLoopCount);
|
||||
|
||||
for (uint32_t i = 0; i < image->GetNumFrames(); i++) {
|
||||
image->SetFrameAsNonPremult(i, mIsNonPremultiplied);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace image
|
||||
|
@ -25,7 +25,6 @@ public:
|
||||
: mHotspotX(-1)
|
||||
, mHotspotY(-1)
|
||||
, mLoopCount(-1)
|
||||
, mIsNonPremultiplied(false)
|
||||
{}
|
||||
|
||||
// Set the metadata this object represents on an image.
|
||||
@ -41,11 +40,6 @@ public:
|
||||
mLoopCount = loopcount;
|
||||
}
|
||||
|
||||
void SetIsNonPremultiplied(bool nonPremult)
|
||||
{
|
||||
mIsNonPremultiplied = nonPremult;
|
||||
}
|
||||
|
||||
void SetSize(int32_t width, int32_t height, Orientation orientation)
|
||||
{
|
||||
mSize.emplace(nsIntSize(width, height));
|
||||
@ -68,9 +62,7 @@ private:
|
||||
int32_t mLoopCount;
|
||||
|
||||
Maybe<nsIntSize> mSize;
|
||||
Maybe<Orientation> mOrientation;
|
||||
|
||||
bool mIsNonPremultiplied;
|
||||
Maybe<Orientation> mOrientation;
|
||||
};
|
||||
|
||||
} // namespace image
|
||||
|
@ -233,9 +233,6 @@ public:
|
||||
mDstRef->ImageUpdated(mDstRef->GetRect());
|
||||
MOZ_ASSERT(mDstRef->ImageComplete(),
|
||||
"Incomplete, but just updated the entire frame");
|
||||
if (DiscardingEnabled()) {
|
||||
mDstRef->SetDiscardable();
|
||||
}
|
||||
}
|
||||
|
||||
// We need to send notifications and release our references on the main
|
||||
@ -322,7 +319,9 @@ RasterImage::RasterImage(ProgressTracker* aProgressTracker,
|
||||
mDiscardable(false),
|
||||
mHasSourceData(false),
|
||||
mDecoded(false),
|
||||
mHasFirstFrame(false),
|
||||
mHasBeenDecoded(false),
|
||||
mPendingAnimation(false),
|
||||
mAnimationFinished(false),
|
||||
mWantFullDecode(false),
|
||||
mPendingError(false)
|
||||
@ -364,7 +363,7 @@ RasterImage::~RasterImage()
|
||||
mDecoder = nullptr;
|
||||
}
|
||||
|
||||
// Release any HQ scaled frames from the surface cache.
|
||||
// Release all frames from the surface cache.
|
||||
SurfaceCache::RemoveImage(ImageKey(this));
|
||||
|
||||
mAnim = nullptr;
|
||||
@ -419,6 +418,11 @@ RasterImage::Init(const char* aMimeType,
|
||||
discardable_source_bytes += mSourceData.Length();
|
||||
}
|
||||
|
||||
// Lock this image's surfaces in the SurfaceCache if we're not discardable.
|
||||
if (!mDiscardable) {
|
||||
SurfaceCache::LockImage(ImageKey(this));
|
||||
}
|
||||
|
||||
// Instantiate the decoder
|
||||
nsresult rv = InitDecoder(/* aDoSizeDecode = */ true);
|
||||
CONTAINER_ENSURE_SUCCESS(rv);
|
||||
@ -558,21 +562,33 @@ RasterImage::GetType()
|
||||
return imgIContainer::TYPE_RASTER;
|
||||
}
|
||||
|
||||
already_AddRefed<imgFrame>
|
||||
RasterImage::LookupFrameNoDecode(uint32_t aFrameNum)
|
||||
DrawableFrameRef
|
||||
RasterImage::LookupFrameInternal(uint32_t aFrameNum,
|
||||
const nsIntSize& aSize,
|
||||
uint32_t aFlags)
|
||||
{
|
||||
if (!mAnim) {
|
||||
NS_ASSERTION(aFrameNum == 0, "Don't ask for a frame > 0 if we're not animated!");
|
||||
return mFrameBlender.GetFrame(0);
|
||||
if (mAnim) {
|
||||
MOZ_ASSERT(mFrameBlender, "mAnim but no mFrameBlender?");
|
||||
nsRefPtr<imgFrame> frame = mFrameBlender->GetFrame(aFrameNum);
|
||||
return frame->DrawableRef();
|
||||
}
|
||||
return mFrameBlender.GetFrame(aFrameNum);
|
||||
|
||||
NS_ASSERTION(aFrameNum == 0,
|
||||
"Don't ask for a frame > 0 if we're not animated!");
|
||||
|
||||
return SurfaceCache::Lookup(ImageKey(this),
|
||||
RasterSurfaceKey(aSize.ToIntSize(),
|
||||
DecodeFlags(aFlags)));
|
||||
}
|
||||
|
||||
DrawableFrameRef
|
||||
RasterImage::LookupFrame(uint32_t aFrameNum,
|
||||
const nsIntSize& aSize,
|
||||
uint32_t aFlags,
|
||||
bool aShouldSyncNotify /* = true */)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mMultipart &&
|
||||
aFrameNum == GetCurrentFrameIndex() &&
|
||||
mMultipartDecodedFrame) {
|
||||
@ -582,26 +598,18 @@ RasterImage::LookupFrame(uint32_t aFrameNum,
|
||||
return mMultipartDecodedFrame->DrawableRef();
|
||||
}
|
||||
|
||||
// Try our best to start decoding if it's necessary.
|
||||
nsresult rv = WantDecodedFrames(aFlags, aShouldSyncNotify);
|
||||
CONTAINER_ENSURE_TRUE(NS_SUCCEEDED(rv), DrawableFrameRef());
|
||||
DrawableFrameRef ref = LookupFrameInternal(aFrameNum, aSize, aFlags);
|
||||
|
||||
nsRefPtr<imgFrame> frame = LookupFrameNoDecode(aFrameNum);
|
||||
if (!frame) {
|
||||
return DrawableFrameRef();
|
||||
}
|
||||
|
||||
DrawableFrameRef ref = frame->DrawableRef();
|
||||
if (!ref) {
|
||||
// The OS threw this frame away. We need to discard and redecode.
|
||||
MOZ_ASSERT(!mAnim, "Animated frames should be locked");
|
||||
if (CanForciblyDiscardAndRedecode()) {
|
||||
ForceDiscard();
|
||||
Discard(/* aForce = */ true, /* aNotify = */ false);
|
||||
ApplyDecodeFlags(aFlags);
|
||||
WantDecodedFrames(aFlags, aShouldSyncNotify);
|
||||
|
||||
// See if we managed to entirely redecode the frame.
|
||||
frame = LookupFrameNoDecode(aFrameNum);
|
||||
ref = frame->DrawableRef();
|
||||
// See if we managed to redecode enough to get the frame we want.
|
||||
ref = LookupFrameInternal(aFrameNum, aSize, aFlags);
|
||||
}
|
||||
|
||||
if (!ref) {
|
||||
@ -672,9 +680,18 @@ RasterImage::FrameRect(uint32_t aWhichFrame)
|
||||
return nsIntRect();
|
||||
}
|
||||
|
||||
// Get the requested frame.
|
||||
if (!mHasFirstFrame) {
|
||||
return nsIntRect();
|
||||
}
|
||||
|
||||
if (GetNumFrames() == 1) {
|
||||
return nsIntRect(0, 0, mSize.width, mSize.height);
|
||||
}
|
||||
|
||||
// We must be animated, so get the requested frame from our FrameBlender.
|
||||
MOZ_ASSERT(mFrameBlender, "We should be animated here");
|
||||
nsRefPtr<imgFrame> frame =
|
||||
LookupFrameNoDecode(GetRequestedFrameIndex(aWhichFrame));
|
||||
mFrameBlender->RawGetFrame(GetRequestedFrameIndex(aWhichFrame));
|
||||
|
||||
// If we have the frame, use that rectangle.
|
||||
if (frame) {
|
||||
@ -692,7 +709,10 @@ RasterImage::FrameRect(uint32_t aWhichFrame)
|
||||
uint32_t
|
||||
RasterImage::GetNumFrames() const
|
||||
{
|
||||
return mFrameBlender.GetNumFrames();
|
||||
if (mFrameBlender) {
|
||||
return mFrameBlender->GetNumFrames();
|
||||
}
|
||||
return mHasFirstFrame ? 1 : 0;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
@ -734,7 +754,8 @@ RasterImage::GetFirstFrameDelay()
|
||||
if (NS_FAILED(GetAnimated(&animated)) || !animated)
|
||||
return -1;
|
||||
|
||||
return mFrameBlender.GetTimeoutForFrame(0);
|
||||
MOZ_ASSERT(mFrameBlender, "Animated images should have a FrameBlender");
|
||||
return mFrameBlender->GetTimeoutForFrame(0);
|
||||
}
|
||||
|
||||
TemporaryRef<SourceSurface>
|
||||
@ -755,7 +776,7 @@ RasterImage::CopyFrame(uint32_t aWhichFrame,
|
||||
// not waiting for the data to be loaded from the network or not passing
|
||||
// FLAG_SYNC_DECODE
|
||||
DrawableFrameRef frameRef = LookupFrame(GetRequestedFrameIndex(aWhichFrame),
|
||||
aFlags, aShouldSyncNotify);
|
||||
mSize, aFlags, aShouldSyncNotify);
|
||||
if (!frameRef) {
|
||||
// The OS threw this frame away and we couldn't redecode it right now.
|
||||
return nullptr;
|
||||
@ -832,7 +853,7 @@ RasterImage::GetFrameInternal(uint32_t aWhichFrame,
|
||||
// not waiting for the data to be loaded from the network or not passing
|
||||
// FLAG_SYNC_DECODE
|
||||
DrawableFrameRef frameRef = LookupFrame(GetRequestedFrameIndex(aWhichFrame),
|
||||
aFlags, aShouldSyncNotify);
|
||||
mSize, aFlags, aShouldSyncNotify);
|
||||
if (!frameRef) {
|
||||
// The OS threw this frame away and we couldn't redecode it.
|
||||
return nullptr;
|
||||
@ -960,7 +981,10 @@ size_t
|
||||
RasterImage::SizeOfDecodedWithComputedFallbackIfHeap(gfxMemoryLocation aLocation,
|
||||
MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
return mFrameBlender.SizeOfDecodedWithComputedFallbackIfHeap(aLocation, aMallocSizeOf);
|
||||
return mFrameBlender
|
||||
? mFrameBlender->SizeOfDecodedWithComputedFallbackIfHeap(aLocation,
|
||||
aMallocSizeOf)
|
||||
: 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
@ -984,115 +1008,114 @@ RasterImage::OutOfProcessSizeOfDecoded() const
|
||||
nullptr);
|
||||
}
|
||||
|
||||
void
|
||||
RasterImage::EnsureAnimExists()
|
||||
{
|
||||
if (!mAnim) {
|
||||
|
||||
// Create the animation context
|
||||
mAnim = MakeUnique<FrameAnimator>(mFrameBlender, mAnimationMode);
|
||||
|
||||
// We don't support discarding animated images (See bug 414259).
|
||||
// Lock the image and throw away the key.
|
||||
//
|
||||
// Note that this is inefficient, since we could get rid of the source
|
||||
// data too. However, doing this is actually hard, because we're probably
|
||||
// calling ensureAnimExists mid-decode, and thus we're decoding out of
|
||||
// the source buffer. Since we're going to fix this anyway later, and
|
||||
// since we didn't kill the source data in the old world either, locking
|
||||
// is acceptable for the moment.
|
||||
LockImage();
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
RasterImage::InternalAddFrameHelper(uint32_t framenum, imgFrame *aFrame,
|
||||
uint8_t **imageData, uint32_t *imageLength,
|
||||
uint32_t **paletteData, uint32_t *paletteLength,
|
||||
imgFrame** aRetFrame)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(framenum <= GetNumFrames(), "Invalid frame index!");
|
||||
if (framenum > GetNumFrames())
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
nsRefPtr<imgFrame> frame = aFrame;
|
||||
RawAccessFrameRef ref = frame->RawAccessRef();
|
||||
if (!ref) {
|
||||
// Probably the OS discarded the frame. Exceedingly unlikely since we just
|
||||
// created it, but it could happen.
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (paletteData && paletteLength)
|
||||
frame->GetPaletteData(paletteData, paletteLength);
|
||||
|
||||
frame->GetImageData(imageData, imageLength);
|
||||
|
||||
mFrameBlender.InsertFrame(framenum, Move(ref));
|
||||
|
||||
frame.forget(aRetFrame);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
RasterImage::InternalAddFrame(uint32_t framenum,
|
||||
int32_t aX, int32_t aY,
|
||||
int32_t aWidth, int32_t aHeight,
|
||||
RawAccessFrameRef
|
||||
RasterImage::InternalAddFrame(uint32_t aFrameNum,
|
||||
const nsIntRect& aFrameRect,
|
||||
uint32_t aDecodeFlags,
|
||||
SurfaceFormat aFormat,
|
||||
uint8_t aPaletteDepth,
|
||||
uint8_t **imageData,
|
||||
uint32_t *imageLength,
|
||||
uint32_t **paletteData,
|
||||
uint32_t *paletteLength,
|
||||
imgFrame** aRetFrame)
|
||||
imgFrame* aPreviousFrame)
|
||||
{
|
||||
// We assume that we're in the middle of decoding because we unlock the
|
||||
// previous frame when we create a new frame, and only when decoding do we
|
||||
// lock frames.
|
||||
NS_ABORT_IF_FALSE(mDecoder, "Only decoders may add frames!");
|
||||
MOZ_ASSERT(mDecoder, "Only decoders may add frames!");
|
||||
|
||||
NS_ABORT_IF_FALSE(framenum <= GetNumFrames(), "Invalid frame index!");
|
||||
if (framenum > GetNumFrames())
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
MOZ_ASSERT(aFrameNum <= GetNumFrames(), "Invalid frame index!");
|
||||
if (aFrameNum > GetNumFrames()) {
|
||||
return RawAccessFrameRef();
|
||||
}
|
||||
|
||||
nsRefPtr<imgFrame> frame(new imgFrame());
|
||||
if (mSize.width <= 0 || mSize.height <= 0) {
|
||||
NS_WARNING("Trying to add frame with zero or negative size");
|
||||
return RawAccessFrameRef();
|
||||
}
|
||||
|
||||
nsIntRect frameRect(aX, aY, aWidth, aHeight);
|
||||
nsresult rv = frame->InitForDecoder(frameRect, aFormat, aPaletteDepth);
|
||||
if (!(mSize.width > 0 && mSize.height > 0))
|
||||
NS_WARNING("Shouldn't call InternalAddFrame with zero size");
|
||||
if (!NS_SUCCEEDED(rv))
|
||||
if (!SurfaceCache::CanHold(mSize.ToIntSize())) {
|
||||
NS_WARNING("Trying to add frame that's too large for the SurfaceCache");
|
||||
return RawAccessFrameRef();
|
||||
}
|
||||
|
||||
nsRefPtr<imgFrame> frame = new imgFrame();
|
||||
if (NS_FAILED(frame->InitForDecoder(mSize, aFrameRect, aFormat,
|
||||
aPaletteDepth))) {
|
||||
NS_WARNING("imgFrame::Init should succeed");
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return RawAccessFrameRef();
|
||||
}
|
||||
frame->SetAsNonPremult(aDecodeFlags & FLAG_DECODE_NO_PREMULTIPLY_ALPHA);
|
||||
|
||||
RawAccessFrameRef ref = frame->RawAccessRef();
|
||||
if (!ref) {
|
||||
return RawAccessFrameRef();
|
||||
}
|
||||
|
||||
if (GetNumFrames() == 0) {
|
||||
return InternalAddFrameHelper(framenum, frame, imageData, imageLength,
|
||||
paletteData, paletteLength, aRetFrame);
|
||||
bool succeeded =
|
||||
SurfaceCache::Insert(frame, ImageKey(this),
|
||||
RasterSurfaceKey(mSize.ToIntSize(), aDecodeFlags),
|
||||
Lifetime::Persistent);
|
||||
if (!succeeded) {
|
||||
return RawAccessFrameRef();
|
||||
}
|
||||
mHasFirstFrame = true;
|
||||
return ref;
|
||||
}
|
||||
|
||||
if (GetNumFrames() == 1) {
|
||||
// Since we're about to add our second frame, initialize animation stuff
|
||||
EnsureAnimExists();
|
||||
// We're becoming animated, so initialize animation stuff.
|
||||
MOZ_ASSERT(!mFrameBlender, "Already have a FrameBlender?");
|
||||
MOZ_ASSERT(!mAnim, "Already have animation state?");
|
||||
mFrameBlender.emplace();
|
||||
mFrameBlender->SetSize(mSize);
|
||||
mAnim = MakeUnique<FrameAnimator>(*mFrameBlender, mAnimationMode);
|
||||
|
||||
// If we dispose of the first frame by clearing it, then the
|
||||
// First Frame's refresh area is all of itself.
|
||||
// RESTORE_PREVIOUS is invalid (assumed to be DISPOSE_CLEAR)
|
||||
nsRefPtr<imgFrame> firstFrame = mFrameBlender.RawGetFrame(0);
|
||||
int32_t frameDisposalMethod = firstFrame->GetFrameDisposalMethod();
|
||||
// We don't support discarding animated images (See bug 414259).
|
||||
// Lock the image and throw away the key.
|
||||
//
|
||||
// Note that this is inefficient, since we could get rid of the source data
|
||||
// too. However, doing this is actually hard, because we're probably
|
||||
// mid-decode, and thus we're decoding out of the source buffer. Since we're
|
||||
// going to fix this anyway later, and since we didn't kill the source data
|
||||
// in the old world either, locking is acceptable for the moment.
|
||||
LockImage();
|
||||
|
||||
// Insert the first frame into the FrameBlender.
|
||||
MOZ_ASSERT(aPreviousFrame, "Must provide a previous frame when animated");
|
||||
RawAccessFrameRef ref = aPreviousFrame->RawAccessRef();
|
||||
if (!ref) {
|
||||
return RawAccessFrameRef(); // Let's keep the FrameBlender consistent...
|
||||
}
|
||||
mFrameBlender->InsertFrame(0, Move(ref));
|
||||
|
||||
// Remove it from the SurfaceCache. (It's not really doing any harm there,
|
||||
// but keeping it there could cause it to be counted twice in our memory
|
||||
// statistics.)
|
||||
SurfaceCache::RemoveSurface(ImageKey(this),
|
||||
RasterSurfaceKey(mSize.ToIntSize(),
|
||||
aDecodeFlags));
|
||||
|
||||
// If we dispose of the first frame by clearing it, then the first frame's
|
||||
// refresh area is all of itself.
|
||||
// RESTORE_PREVIOUS is invalid (assumed to be DISPOSE_CLEAR).
|
||||
int32_t frameDisposalMethod = aPreviousFrame->GetFrameDisposalMethod();
|
||||
if (frameDisposalMethod == FrameBlender::kDisposeClear ||
|
||||
frameDisposalMethod == FrameBlender::kDisposeRestorePrevious)
|
||||
mAnim->SetFirstFrameRefreshArea(firstFrame->GetRect());
|
||||
frameDisposalMethod == FrameBlender::kDisposeRestorePrevious) {
|
||||
mAnim->SetFirstFrameRefreshArea(aPreviousFrame->GetRect());
|
||||
}
|
||||
|
||||
if (mPendingAnimation && ShouldAnimate()) {
|
||||
StartAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate firstFrameRefreshArea
|
||||
// Some gifs are huge but only have a small area that they animate
|
||||
// We only need to refresh that small area when Frame 0 comes around again
|
||||
// Some GIFs are huge but only have a small area that they animate. We only
|
||||
// need to refresh that small area when frame 0 comes around again.
|
||||
mAnim->UnionFirstFrameRefreshArea(frame->GetRect());
|
||||
|
||||
rv = InternalAddFrameHelper(framenum, frame, imageData, imageLength,
|
||||
paletteData, paletteLength, aRetFrame);
|
||||
MOZ_ASSERT(mFrameBlender, "Should have a FrameBlender by now");
|
||||
mFrameBlender->InsertFrame(aFrameNum, frame->RawAccessRef());
|
||||
|
||||
return rv;
|
||||
return ref;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -1162,121 +1185,70 @@ RasterImage::SetSize(int32_t aWidth, int32_t aHeight, Orientation aOrientation)
|
||||
mOrientation = aOrientation;
|
||||
mHasSize = true;
|
||||
|
||||
mFrameBlender.SetSize(mSize);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
RasterImage::EnsureFrame(uint32_t aFrameNum, int32_t aX, int32_t aY,
|
||||
int32_t aWidth, int32_t aHeight,
|
||||
RawAccessFrameRef
|
||||
RasterImage::EnsureFrame(uint32_t aFrameNum,
|
||||
const nsIntRect& aFrameRect,
|
||||
uint32_t aDecodeFlags,
|
||||
SurfaceFormat aFormat,
|
||||
uint8_t aPaletteDepth,
|
||||
uint8_t **imageData, uint32_t *imageLength,
|
||||
uint32_t **paletteData, uint32_t *paletteLength,
|
||||
imgFrame** aRetFrame)
|
||||
imgFrame* aPreviousFrame)
|
||||
{
|
||||
if (mError)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NS_ENSURE_ARG_POINTER(imageData);
|
||||
NS_ENSURE_ARG_POINTER(imageLength);
|
||||
NS_ENSURE_ARG_POINTER(aRetFrame);
|
||||
NS_ABORT_IF_FALSE(aFrameNum <= GetNumFrames(), "Invalid frame index!");
|
||||
|
||||
if (aPaletteDepth > 0) {
|
||||
NS_ENSURE_ARG_POINTER(paletteData);
|
||||
NS_ENSURE_ARG_POINTER(paletteLength);
|
||||
if (mError) {
|
||||
return RawAccessFrameRef();
|
||||
}
|
||||
|
||||
if (aFrameNum > GetNumFrames())
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
MOZ_ASSERT(aFrameNum <= GetNumFrames(), "Invalid frame index!");
|
||||
if (aFrameNum > GetNumFrames()) {
|
||||
return RawAccessFrameRef();
|
||||
}
|
||||
|
||||
// Adding a frame that doesn't already exist.
|
||||
// Adding a frame that doesn't already exist. This is the normal case.
|
||||
if (aFrameNum == GetNumFrames()) {
|
||||
return InternalAddFrame(aFrameNum, aX, aY, aWidth, aHeight, aFormat,
|
||||
aPaletteDepth, imageData, imageLength,
|
||||
paletteData, paletteLength, aRetFrame);
|
||||
return InternalAddFrame(aFrameNum, aFrameRect, aDecodeFlags, aFormat,
|
||||
aPaletteDepth, aPreviousFrame);
|
||||
}
|
||||
|
||||
nsRefPtr<imgFrame> frame = mFrameBlender.RawGetFrame(aFrameNum);
|
||||
if (!frame) {
|
||||
return InternalAddFrame(aFrameNum, aX, aY, aWidth, aHeight, aFormat,
|
||||
aPaletteDepth, imageData, imageLength,
|
||||
paletteData, paletteLength, aRetFrame);
|
||||
// We're replacing a frame. It must be the first frame; there's no reason to
|
||||
// ever replace any other frame, since the first frame is the only one we
|
||||
// speculatively allocate without knowing what the decoder really needs.
|
||||
// XXX(seth): I'm not convinced there's any reason to support this at all. We
|
||||
// should figure out how to avoid triggering this and rip it out.
|
||||
MOZ_ASSERT(mHasFirstFrame, "Should have the first frame");
|
||||
MOZ_ASSERT(aFrameNum == 0, "Replacing a frame other than the first?");
|
||||
MOZ_ASSERT(GetNumFrames() == 1, "Should have only one frame");
|
||||
MOZ_ASSERT(aPreviousFrame, "Need the previous frame to replace");
|
||||
MOZ_ASSERT(!mFrameBlender && !mAnim, "Shouldn't be animated");
|
||||
if (aFrameNum != 0 || !aPreviousFrame || GetNumFrames() != 1) {
|
||||
return RawAccessFrameRef();
|
||||
}
|
||||
|
||||
// See if we can re-use the frame that already exists.
|
||||
nsIntRect rect = frame->GetRect();
|
||||
if (rect.x == aX && rect.y == aY && rect.width == aWidth &&
|
||||
rect.height == aHeight && frame->GetFormat() == aFormat &&
|
||||
frame->GetPaletteDepth() == aPaletteDepth) {
|
||||
frame->GetImageData(imageData, imageLength);
|
||||
if (paletteData) {
|
||||
frame->GetPaletteData(paletteData, paletteLength);
|
||||
}
|
||||
MOZ_ASSERT(!aPreviousFrame->GetRect().IsEqualEdges(aFrameRect) ||
|
||||
aPreviousFrame->GetFormat() != aFormat ||
|
||||
aPreviousFrame->GetPaletteDepth() != aPaletteDepth,
|
||||
"Replacing first frame with the same kind of frame?");
|
||||
|
||||
// We can re-use the frame if it has image data.
|
||||
if (*imageData && paletteData && *paletteData) {
|
||||
frame.forget(aRetFrame);
|
||||
return NS_OK;
|
||||
}
|
||||
if (*imageData && !paletteData) {
|
||||
frame.forget(aRetFrame);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
// Remove the old frame from the SurfaceCache.
|
||||
IntSize prevFrameSize = aPreviousFrame->GetImageSize();
|
||||
SurfaceCache::RemoveSurface(ImageKey(this),
|
||||
RasterSurfaceKey(prevFrameSize, aDecodeFlags));
|
||||
mHasFirstFrame = false;
|
||||
|
||||
// Not reusable, so replace the frame directly.
|
||||
mFrameBlender.RemoveFrame(aFrameNum);
|
||||
nsRefPtr<imgFrame> newFrame(new imgFrame());
|
||||
nsIntRect frameRect(aX, aY, aWidth, aHeight);
|
||||
nsresult rv = newFrame->InitForDecoder(frameRect, aFormat, aPaletteDepth);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return InternalAddFrameHelper(aFrameNum, newFrame, imageData, imageLength,
|
||||
paletteData, paletteLength, aRetFrame);
|
||||
// Add the new frame as usual.
|
||||
return InternalAddFrame(aFrameNum, aFrameRect, aDecodeFlags, aFormat,
|
||||
aPaletteDepth, nullptr);
|
||||
}
|
||||
|
||||
nsresult
|
||||
RasterImage::EnsureFrame(uint32_t aFramenum, int32_t aX, int32_t aY,
|
||||
int32_t aWidth, int32_t aHeight,
|
||||
SurfaceFormat aFormat,
|
||||
uint8_t** imageData, uint32_t* imageLength,
|
||||
imgFrame** aFrame)
|
||||
{
|
||||
return EnsureFrame(aFramenum, aX, aY, aWidth, aHeight, aFormat,
|
||||
/* aPaletteDepth = */ 0, imageData, imageLength,
|
||||
/* aPaletteData = */ nullptr,
|
||||
/* aPaletteLength = */ nullptr,
|
||||
aFrame);
|
||||
}
|
||||
|
||||
nsresult
|
||||
RasterImage::SetFrameAsNonPremult(uint32_t aFrameNum, bool aIsNonPremult)
|
||||
{
|
||||
if (mError)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NS_ABORT_IF_FALSE(aFrameNum < GetNumFrames(), "Invalid frame index!");
|
||||
if (aFrameNum >= GetNumFrames())
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
nsRefPtr<imgFrame> frame = mFrameBlender.RawGetFrame(aFrameNum);
|
||||
NS_ABORT_IF_FALSE(frame, "Calling SetFrameAsNonPremult on frame that doesn't exist!");
|
||||
NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
|
||||
|
||||
frame->SetAsNonPremult(aIsNonPremult);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
RasterImage::DecodingComplete()
|
||||
void
|
||||
RasterImage::DecodingComplete(imgFrame* aFinalFrame)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mError)
|
||||
return NS_ERROR_FAILURE;
|
||||
if (mError) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Flag that we're done decoding.
|
||||
// XXX - these should probably be combined when we fix animated image
|
||||
@ -1284,48 +1256,42 @@ RasterImage::DecodingComplete()
|
||||
mDecoded = true;
|
||||
mHasBeenDecoded = true;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// We now have one of the qualifications for discarding. Re-evaluate.
|
||||
if (CanDiscard()) {
|
||||
NS_ABORT_IF_FALSE(!DiscardingActive(),
|
||||
"We shouldn't have been discardable before this");
|
||||
rv = DiscardTracker::Reset(&mDiscardTrackerNode);
|
||||
CONTAINER_ENSURE_SUCCESS(rv);
|
||||
DiscardTracker::Reset(&mDiscardTrackerNode);
|
||||
}
|
||||
|
||||
bool singleFrame = GetNumFrames() == 1;
|
||||
|
||||
// If there's only 1 frame, mark it as optimizable. Optimizing animated images
|
||||
// is not supported.
|
||||
//
|
||||
// We don't optimize the frame for multipart images because we reuse
|
||||
// the frame.
|
||||
if ((GetNumFrames() == 1) && !mMultipart) {
|
||||
nsRefPtr<imgFrame> firstFrame = mFrameBlender.RawGetFrame(0);
|
||||
firstFrame->SetOptimizable();
|
||||
if (DiscardingEnabled() && CanForciblyDiscard()) {
|
||||
firstFrame->SetDiscardable();
|
||||
}
|
||||
if (singleFrame && !mMultipart && aFinalFrame) {
|
||||
aFinalFrame->SetOptimizable();
|
||||
}
|
||||
|
||||
// Double-buffer our frame in the multipart case, since we'll start decoding
|
||||
// into the first frame again immediately and this produces severe tearing.
|
||||
if (mMultipart) {
|
||||
if (GetNumFrames() == 1) {
|
||||
mMultipartDecodedFrame = mFrameBlender.GetFrame(GetCurrentFrameIndex());
|
||||
if (singleFrame && aFinalFrame) {
|
||||
// aFinalFrame must be the first frame since we only have one.
|
||||
mMultipartDecodedFrame = aFinalFrame->DrawableRef();
|
||||
} else {
|
||||
// Don't double buffer for animated multipart images. It entails more
|
||||
// complexity and it's not really needed since we already are smart about
|
||||
// not displaying the still-decoding frame of an animated image. We may
|
||||
// have already stored an extra frame, though, so we'll release it here.
|
||||
mMultipartDecodedFrame = nullptr;
|
||||
mMultipartDecodedFrame.reset();
|
||||
}
|
||||
}
|
||||
|
||||
if (mAnim) {
|
||||
mAnim->SetDoneDecoding(true);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -1347,12 +1313,17 @@ RasterImage::StartAnimation()
|
||||
|
||||
NS_ABORT_IF_FALSE(ShouldAnimate(), "Should not animate!");
|
||||
|
||||
EnsureAnimExists();
|
||||
// If we don't have mAnim yet, then we're not ready to animate. Setting
|
||||
// mPendingAnimation will cause us to start animating as soon as we have a
|
||||
// second frame, which causes mAnim to be constructed.
|
||||
mPendingAnimation = !mAnim;
|
||||
if (mPendingAnimation) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<imgFrame> currentFrame = LookupFrameNoDecode(GetCurrentFrameIndex());
|
||||
// A timeout of -1 means we should display this frame forever.
|
||||
if (currentFrame &&
|
||||
mFrameBlender.GetTimeoutForFrame(GetCurrentFrameIndex()) < 0) {
|
||||
MOZ_ASSERT(mFrameBlender, "Have an animation but no FrameBlender?");
|
||||
if (mFrameBlender->GetTimeoutForFrame(GetCurrentFrameIndex()) < 0) {
|
||||
mAnimationFinished = true;
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
@ -1392,16 +1363,20 @@ RasterImage::ResetAnimation()
|
||||
if (mError)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (mAnimationMode == kDontAnimMode ||
|
||||
!mAnim || mAnim->GetCurrentAnimationFrameIndex() == 0)
|
||||
mPendingAnimation = false;
|
||||
|
||||
if (mAnimationMode == kDontAnimMode || !mAnim ||
|
||||
mAnim->GetCurrentAnimationFrameIndex() == 0) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mAnimationFinished = false;
|
||||
|
||||
if (mAnimating)
|
||||
StopAnimation();
|
||||
|
||||
mFrameBlender.ResetAnimation();
|
||||
MOZ_ASSERT(mFrameBlender, "Should have a FrameBlender");
|
||||
mFrameBlender->ResetAnimation();
|
||||
mAnim->ResetAnimation();
|
||||
|
||||
UpdateImageContainer();
|
||||
@ -1450,7 +1425,8 @@ RasterImage::SetLoopCount(int32_t aLoopCount)
|
||||
|
||||
if (mAnim) {
|
||||
// No need to set this if we're not an animation
|
||||
mFrameBlender.SetLoopCount(aLoopCount);
|
||||
MOZ_ASSERT(mFrameBlender, "Should have a FrameBlender");
|
||||
mFrameBlender->SetLoopCount(aLoopCount);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1489,18 +1465,26 @@ RasterImage::AddSourceData(const char *aBuffer, uint32_t aCount)
|
||||
// This needs to happen just before we start getting EnsureFrame() call(s),
|
||||
// so that there's no gap for anything to miss us.
|
||||
if (mMultipart && (!mDecoder || mDecoder->BytesDecoded() == 0)) {
|
||||
// Our previous state may have been animated, so let's clean up
|
||||
if (mAnimating)
|
||||
// Our previous state may have been animated, so let's clean up.
|
||||
if (mAnimating) {
|
||||
StopAnimation();
|
||||
}
|
||||
mAnimationFinished = false;
|
||||
mPendingAnimation = false;
|
||||
if (mAnim) {
|
||||
mAnim = nullptr;
|
||||
}
|
||||
// If there's only one frame, this could cause flickering
|
||||
int old_frame_count = GetNumFrames();
|
||||
if (old_frame_count > 1) {
|
||||
mFrameBlender.ClearFrames();
|
||||
|
||||
// If we had a FrameBlender, clean it up. We'll hold on to the first frame
|
||||
// so we have something to draw until the next frame is decoded.
|
||||
if (mFrameBlender) {
|
||||
nsRefPtr<imgFrame> firstFrame = mFrameBlender->RawGetFrame(0);
|
||||
mMultipartDecodedFrame = firstFrame->DrawableRef();
|
||||
mFrameBlender.reset();
|
||||
}
|
||||
|
||||
// Remove everything stored in the surface cache for this image.
|
||||
SurfaceCache::RemoveImage(ImageKey(this));
|
||||
}
|
||||
|
||||
// If we're not storing source data and we've previously gotten the size,
|
||||
@ -1693,6 +1677,7 @@ RasterImage::OnNewSourceData()
|
||||
mDecoded = false;
|
||||
mHasSourceData = false;
|
||||
mHasSize = false;
|
||||
mHasFirstFrame = false;
|
||||
mWantFullDecode = true;
|
||||
mDecodeStatus = DecodeStatus::INACTIVE;
|
||||
|
||||
@ -1771,12 +1756,12 @@ RasterImage::GetKeys(uint32_t *count, char ***keys)
|
||||
}
|
||||
|
||||
void
|
||||
RasterImage::Discard(bool force)
|
||||
RasterImage::Discard(bool aForce, bool aNotify)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// We should be ok for discard
|
||||
NS_ABORT_IF_FALSE(force ? CanForciblyDiscard() : CanDiscard(), "Asked to discard but can't!");
|
||||
NS_ABORT_IF_FALSE(aForce ? CanForciblyDiscard() : CanDiscard(), "Asked to discard but can't!");
|
||||
|
||||
// We should never discard when we have an active decoder
|
||||
NS_ABORT_IF_FALSE(!mDecoder, "Asked to discard with open decoder!");
|
||||
@ -1789,22 +1774,26 @@ RasterImage::Discard(bool force)
|
||||
int old_frame_count = GetNumFrames();
|
||||
|
||||
// Delete all the decoded frames
|
||||
mFrameBlender.Discard();
|
||||
mFrameBlender.reset();
|
||||
SurfaceCache::RemoveImage(ImageKey(this));
|
||||
|
||||
// Clear the last decoded multipart frame.
|
||||
mMultipartDecodedFrame = nullptr;
|
||||
mMultipartDecodedFrame.reset();
|
||||
|
||||
// Flag that we no longer have decoded frames for this image
|
||||
mDecoded = false;
|
||||
mHasFirstFrame = false;
|
||||
|
||||
// Notify that we discarded
|
||||
if (mProgressTracker)
|
||||
if (aNotify && mProgressTracker) {
|
||||
mProgressTracker->OnDiscard();
|
||||
}
|
||||
|
||||
mDecodeStatus = DecodeStatus::INACTIVE;
|
||||
|
||||
if (force)
|
||||
if (aForce) {
|
||||
DiscardTracker::Remove(&mDiscardTrackerNode);
|
||||
}
|
||||
|
||||
// Log
|
||||
PR_LOG(GetCompressedImageAccountingLog(), PR_LOG_DEBUG,
|
||||
@ -1834,14 +1823,12 @@ RasterImage::CanDiscard() {
|
||||
|
||||
bool
|
||||
RasterImage::CanForciblyDiscard() {
|
||||
return mDiscardable && // ...Enabled at creation time...
|
||||
mHasSourceData; // ...have the source data...
|
||||
return mHasSourceData; // ...have the source data...
|
||||
}
|
||||
|
||||
bool
|
||||
RasterImage::CanForciblyDiscardAndRedecode() {
|
||||
return mDiscardable && // ...Enabled at creation time...
|
||||
mHasSourceData && // ...have the source data...
|
||||
return mHasSourceData && // ...have the source data...
|
||||
!mDecoder && // Can't discard with an open decoder
|
||||
!mAnim; // Can never discard animated images
|
||||
}
|
||||
@ -1857,7 +1844,7 @@ RasterImage::DiscardingActive() {
|
||||
// or just writing it directly to the decoder
|
||||
bool
|
||||
RasterImage::StoringSourceData() const {
|
||||
return (mDecodeOnDraw || mDiscardable);
|
||||
return !mMultipart;
|
||||
}
|
||||
|
||||
|
||||
@ -2431,26 +2418,15 @@ RasterImage::DrawWithPreDownscaleIfNeeded(DrawableFrameRef&& aFrameRef,
|
||||
|
||||
// By now we may have a frame with the requested size. If not, we need to
|
||||
// adjust the drawing parameters accordingly.
|
||||
nsIntRect finalFrameRect = frameRef->GetRect();
|
||||
if (finalFrameRect.Size() != aSize) {
|
||||
gfx::Size scale(double(aSize.width) / mSize.width,
|
||||
double(aSize.height) / mSize.height);
|
||||
IntSize finalSize = frameRef->GetImageSize();
|
||||
if (ThebesIntSize(finalSize) != aSize) {
|
||||
gfx::Size scale(double(aSize.width) / finalSize.width,
|
||||
double(aSize.height) / finalSize.height);
|
||||
aContext->Multiply(gfxMatrix::Scaling(scale.width, scale.height));
|
||||
region.Scale(1.0 / scale.width, 1.0 / scale.height);
|
||||
}
|
||||
|
||||
// We can only use padding if we're using the original |aFrameRef|, unscaled.
|
||||
// (If so, we moved it into |frameRef|, so |aFrameRef| is empty.) Because of
|
||||
// this restriction, we don't scale frames that require padding.
|
||||
nsIntMargin padding(0, 0, 0, 0);
|
||||
if (!aFrameRef) {
|
||||
padding = nsIntMargin(finalFrameRect.y,
|
||||
mSize.width - finalFrameRect.XMost(),
|
||||
mSize.height - finalFrameRect.YMost(),
|
||||
finalFrameRect.x);
|
||||
}
|
||||
|
||||
frameRef->Draw(aContext, region, padding, aFilter, aFlags);
|
||||
frameRef->Draw(aContext, region, aFilter, aFlags);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
@ -2528,13 +2504,20 @@ RasterImage::Draw(gfxContext* aContext,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// XXX(seth): For now, we deliberately don't look up a frame of size aSize
|
||||
// (though DrawWithPreDownscaleIfNeeded will do so later). It doesn't make
|
||||
// sense to do so until we support downscale-during-decode. Right now we need
|
||||
// to make sure that we always touch an mSize-sized frame so that we have
|
||||
// something to HQ scale.
|
||||
DrawableFrameRef ref = LookupFrame(GetRequestedFrameIndex(aWhichFrame),
|
||||
aFlags);
|
||||
mSize, aFlags);
|
||||
if (!ref) {
|
||||
return NS_OK; // Getting the frame (above) touches the image and kicks off decoding
|
||||
// Getting the frame (above) touches the image and kicks off decoding.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
DrawWithPreDownscaleIfNeeded(Move(ref), aContext, aSize, aRegion, aFilter, aFlags);
|
||||
DrawWithPreDownscaleIfNeeded(Move(ref), aContext, aSize,
|
||||
aRegion, aFilter, aFlags);
|
||||
|
||||
if (mDecoded && !mDrawStartTime.IsNull()) {
|
||||
TimeDuration drawLatency = TimeStamp::Now() - mDrawStartTime;
|
||||
@ -2562,6 +2545,11 @@ RasterImage::LockImage()
|
||||
// Increment the lock count
|
||||
mLockCount++;
|
||||
|
||||
// Lock this image's surfaces in the SurfaceCache.
|
||||
if (mLockCount == 1) {
|
||||
SurfaceCache::LockImage(ImageKey(this));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -2587,6 +2575,11 @@ RasterImage::UnlockImage()
|
||||
// Decrement our lock count
|
||||
mLockCount--;
|
||||
|
||||
// Unlock this image's surfaces in the SurfaceCache.
|
||||
if (mLockCount == 0) {
|
||||
SurfaceCache::UnlockImage(ImageKey(this));
|
||||
}
|
||||
|
||||
// If we've decoded this image once before, we're currently decoding again,
|
||||
// and our lock count is now zero (so nothing is forcing us to keep the
|
||||
// decoded data around), try to cancel the decode and throw away whatever
|
||||
@ -2974,7 +2967,8 @@ RasterImage::OptimalImageSizeForDest(const gfxSize& aDest, uint32_t aWhichFrame,
|
||||
}
|
||||
if (!frameRef) {
|
||||
// We could HQ scale to this size, but we haven't. Request a scale now.
|
||||
frameRef = LookupFrame(GetRequestedFrameIndex(aWhichFrame), aFlags);
|
||||
frameRef = LookupFrame(GetRequestedFrameIndex(aWhichFrame),
|
||||
mSize, aFlags);
|
||||
if (frameRef) {
|
||||
RequestScale(frameRef.get(), aFlags, destSize);
|
||||
}
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "DiscardTracker.h"
|
||||
#include "Orientation.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/ReentrantMonitor.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
@ -180,12 +181,10 @@ public:
|
||||
}
|
||||
|
||||
/* Triggers discarding. */
|
||||
void Discard(bool force = false);
|
||||
void ForceDiscard() { Discard(/* force = */ true); }
|
||||
void Discard(bool aForce = false, bool aNotify = true);
|
||||
void ForceDiscard() { Discard(/* aForce = */ true); }
|
||||
|
||||
/* Callbacks for decoders */
|
||||
nsresult SetFrameAsNonPremult(uint32_t aFrameNum, bool aIsNonPremult);
|
||||
|
||||
/** Sets the size and inherent orientation of the container. This should only
|
||||
* be called by the decoder. This function may be called multiple times, but
|
||||
* will throw an error if subsequent calls do not match the first.
|
||||
@ -194,33 +193,21 @@ public:
|
||||
|
||||
/**
|
||||
* Ensures that a given frame number exists with the given parameters, and
|
||||
* returns pointers to the data storage for that frame.
|
||||
* returns a RawAccessFrameRef for that frame.
|
||||
* It is not possible to create sparse frame arrays; you can only append
|
||||
* frames to the current frame array.
|
||||
* frames to the current frame array, or if there is only one frame in the
|
||||
* array, replace that frame.
|
||||
* If a non-paletted frame is desired, pass 0 for aPaletteDepth.
|
||||
*/
|
||||
nsresult EnsureFrame(uint32_t aFramenum, int32_t aX, int32_t aY,
|
||||
int32_t aWidth, int32_t aHeight,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
uint8_t aPaletteDepth,
|
||||
uint8_t** imageData,
|
||||
uint32_t* imageLength,
|
||||
uint32_t** paletteData,
|
||||
uint32_t* paletteLength,
|
||||
imgFrame** aFrame);
|
||||
|
||||
/**
|
||||
* A shorthand for EnsureFrame, above, with aPaletteDepth = 0 and paletteData
|
||||
* and paletteLength set to null.
|
||||
*/
|
||||
nsresult EnsureFrame(uint32_t aFramenum, int32_t aX, int32_t aY,
|
||||
int32_t aWidth, int32_t aHeight,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
uint8_t** imageData,
|
||||
uint32_t* imageLength,
|
||||
imgFrame** aFrame);
|
||||
RawAccessFrameRef EnsureFrame(uint32_t aFrameNum,
|
||||
const nsIntRect& aFrameRect,
|
||||
uint32_t aDecodeFlags,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
uint8_t aPaletteDepth,
|
||||
imgFrame* aPreviousFrame);
|
||||
|
||||
/* notification that the entire image has been decoded */
|
||||
nsresult DecodingComplete();
|
||||
void DecodingComplete(imgFrame* aFinalFrame);
|
||||
|
||||
/**
|
||||
* Number of times to loop the image.
|
||||
@ -314,8 +301,13 @@ private:
|
||||
uint32_t aFlags,
|
||||
bool aShouldSyncNotify = true);
|
||||
|
||||
already_AddRefed<imgFrame> LookupFrameNoDecode(uint32_t aFrameNum);
|
||||
DrawableFrameRef LookupFrame(uint32_t aFrameNum, uint32_t aFlags, bool aShouldSyncNotify = true);
|
||||
DrawableFrameRef LookupFrameInternal(uint32_t aFrameNum,
|
||||
const nsIntSize& aSize,
|
||||
uint32_t aFlags);
|
||||
DrawableFrameRef LookupFrame(uint32_t aFrameNum,
|
||||
const nsIntSize& aSize,
|
||||
uint32_t aFlags,
|
||||
bool aShouldSyncNotify = true);
|
||||
uint32_t GetCurrentFrameIndex() const;
|
||||
uint32_t GetRequestedFrameIndex(uint32_t aWhichFrame) const;
|
||||
|
||||
@ -324,18 +316,12 @@ private:
|
||||
size_t SizeOfDecodedWithComputedFallbackIfHeap(gfxMemoryLocation aLocation,
|
||||
MallocSizeOf aMallocSizeOf) const;
|
||||
|
||||
void EnsureAnimExists();
|
||||
|
||||
nsresult InternalAddFrameHelper(uint32_t framenum, imgFrame *frame,
|
||||
uint8_t **imageData, uint32_t *imageLength,
|
||||
uint32_t **paletteData, uint32_t *paletteLength,
|
||||
imgFrame** aRetFrame);
|
||||
nsresult InternalAddFrame(uint32_t framenum, int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight,
|
||||
gfx::SurfaceFormat aFormat, uint8_t aPaletteDepth,
|
||||
uint8_t **imageData, uint32_t *imageLength,
|
||||
uint32_t **paletteData, uint32_t *paletteLength,
|
||||
imgFrame** aRetFrame);
|
||||
|
||||
RawAccessFrameRef InternalAddFrame(uint32_t aFrameNum,
|
||||
const nsIntRect& aFrameRect,
|
||||
uint32_t aDecodeFlags,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
uint8_t aPaletteDepth,
|
||||
imgFrame* aPreviousFrame);
|
||||
nsresult DoImageDataComplete();
|
||||
|
||||
bool ApplyDecodeFlags(uint32_t aNewFlags);
|
||||
@ -370,11 +356,11 @@ private: // data
|
||||
// and imgIContainer::FLAG_DECODE_NO_COLORSPACE_CONVERSION.
|
||||
uint32_t mFrameDecodeFlags;
|
||||
|
||||
//! All the frames of the image
|
||||
FrameBlender mFrameBlender;
|
||||
//! All the frames of the image.
|
||||
Maybe<FrameBlender> mFrameBlender;
|
||||
|
||||
// The last frame we decoded for multipart images.
|
||||
nsRefPtr<imgFrame> mMultipartDecodedFrame;
|
||||
//! The last frame we decoded for multipart images.
|
||||
DrawableFrameRef mMultipartDecodedFrame;
|
||||
|
||||
nsCOMPtr<nsIProperties> mProperties;
|
||||
|
||||
@ -439,8 +425,13 @@ private: // data
|
||||
|
||||
// Do we have the frames in decoded form?
|
||||
bool mDecoded:1;
|
||||
bool mHasFirstFrame:1;
|
||||
bool mHasBeenDecoded:1;
|
||||
|
||||
// Whether we're waiting to start animation. If we get a StartAnimation() call
|
||||
// but we don't yet have more than one frame, mPendingAnimation is set so that
|
||||
// we know to start animation later if/when we have more frames.
|
||||
bool mPendingAnimation:1;
|
||||
|
||||
// Whether the animation can stop, due to running out
|
||||
// of frames, or no more owning request
|
||||
|
@ -111,6 +111,23 @@ static bool AllowedImageSize(int32_t aWidth, int32_t aHeight)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool AllowedImageAndFrameDimensions(const nsIntSize& aImageSize,
|
||||
const nsIntRect& aFrameRect)
|
||||
{
|
||||
if (!AllowedImageSize(aImageSize.width, aImageSize.height)) {
|
||||
return false;
|
||||
}
|
||||
if (!AllowedImageSize(aFrameRect.width, aFrameRect.height)) {
|
||||
return false;
|
||||
}
|
||||
nsIntRect imageRect(0, 0, aImageSize.width, aImageSize.height);
|
||||
if (!imageRect.Contains(aFrameRect)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
imgFrame::imgFrame() :
|
||||
mDecoded(0, 0, 0, 0),
|
||||
mDecodedMutex("imgFrame::mDecoded"),
|
||||
@ -123,7 +140,6 @@ imgFrame::imgFrame() :
|
||||
mCompositingFailed(false),
|
||||
mHasNoAlpha(false),
|
||||
mNonPremult(false),
|
||||
mDiscardable(false),
|
||||
mOptimizable(false),
|
||||
mInformedDiscardTracker(false)
|
||||
{
|
||||
@ -147,17 +163,19 @@ imgFrame::~imgFrame()
|
||||
}
|
||||
|
||||
nsresult
|
||||
imgFrame::InitForDecoder(const nsIntRect& aRect,
|
||||
imgFrame::InitForDecoder(const nsIntSize& aImageSize,
|
||||
const nsIntRect& aRect,
|
||||
SurfaceFormat aFormat,
|
||||
uint8_t aPaletteDepth /* = 0 */)
|
||||
{
|
||||
// Assert for properties that should be verified by decoders,
|
||||
// warn for properties related to bad content.
|
||||
if (!AllowedImageSize(aRect.width, aRect.height)) {
|
||||
if (!AllowedImageAndFrameDimensions(aImageSize, aRect)) {
|
||||
NS_WARNING("Should have legal image size");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mImageSize = aImageSize.ToIntSize();
|
||||
mOffset.MoveTo(aRect.x, aRect.y);
|
||||
mSize.SizeTo(aRect.width, aRect.height);
|
||||
|
||||
@ -221,6 +239,7 @@ imgFrame::InitWithDrawable(gfxDrawable* aDrawable,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mImageSize = aSize.ToIntSize();
|
||||
mOffset.MoveTo(0, 0);
|
||||
mSize.SizeTo(aSize.width, aSize.height);
|
||||
|
||||
@ -415,9 +434,7 @@ nsresult imgFrame::Optimize()
|
||||
// allows the operating system to free our volatile buffer.
|
||||
// XXX(seth): We'd eventually like to do this on all platforms, but right now
|
||||
// converting raw memory to a SourceSurface is expensive on some backends.
|
||||
if (mDiscardable) {
|
||||
mImageSurface = nullptr;
|
||||
}
|
||||
mImageSurface = nullptr;
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
@ -492,8 +509,7 @@ imgFrame::SurfaceForDrawing(bool aDoPadding,
|
||||
}
|
||||
|
||||
bool imgFrame::Draw(gfxContext* aContext, const ImageRegion& aRegion,
|
||||
const nsIntMargin& aPadding, GraphicsFilter aFilter,
|
||||
uint32_t aImageFlags)
|
||||
GraphicsFilter aFilter, uint32_t aImageFlags)
|
||||
{
|
||||
PROFILER_LABEL("imgFrame", "Draw",
|
||||
js::ProfileEntry::Category::GRAPHICS);
|
||||
@ -504,7 +520,12 @@ bool imgFrame::Draw(gfxContext* aContext, const ImageRegion& aRegion,
|
||||
"We must be allowed to sample *some* source pixels!");
|
||||
NS_ASSERTION(!mPalettedImageData, "Directly drawing a paletted image!");
|
||||
|
||||
bool doPadding = aPadding != nsIntMargin(0,0,0,0);
|
||||
nsIntMargin padding(mOffset.y,
|
||||
mImageSize.width - (mOffset.x + mSize.width),
|
||||
mImageSize.height - (mOffset.y + mSize.height),
|
||||
mOffset.x);
|
||||
|
||||
bool doPadding = padding != nsIntMargin(0,0,0,0);
|
||||
bool doPartialDecode = !ImageComplete();
|
||||
|
||||
if (mSinglePixel && !doPadding && !doPartialDecode) {
|
||||
@ -519,14 +540,12 @@ bool imgFrame::Draw(gfxContext* aContext, const ImageRegion& aRegion,
|
||||
return true;
|
||||
}
|
||||
|
||||
gfxRect imageRect(0, 0, mSize.width + aPadding.LeftRight(),
|
||||
mSize.height + aPadding.TopBottom());
|
||||
|
||||
RefPtr<SourceSurface> surf = GetSurface();
|
||||
if (!surf && !mSinglePixel) {
|
||||
return false;
|
||||
}
|
||||
|
||||
gfxRect imageRect(0, 0, mImageSize.width, mImageSize.height);
|
||||
bool doTile = !imageRect.Contains(aRegion.Rect()) &&
|
||||
!(aImageFlags & imgIContainer::FLAG_CLAMP);
|
||||
ImageRegion region(aRegion);
|
||||
@ -539,7 +558,7 @@ bool imgFrame::Draw(gfxContext* aContext, const ImageRegion& aRegion,
|
||||
gfxContextMatrixAutoSaveRestore autoSR(aContext);
|
||||
SurfaceWithFormat surfaceResult =
|
||||
SurfaceForDrawing(doPadding, doPartialDecode, doTile, aContext,
|
||||
aPadding, imageRect, region, surf);
|
||||
padding, imageRect, region, surf);
|
||||
|
||||
if (surfaceResult.IsValid()) {
|
||||
gfxUtils::DrawPixelSnapped(aContext, surfaceResult.mDrawable,
|
||||
@ -579,34 +598,9 @@ imgFrame::GetStride() const
|
||||
return VolatileSurfaceStride(mSize, mFormat);
|
||||
}
|
||||
|
||||
<<<<<<< found
|
||||
SurfaceFormat imgFrame::GetFormat() const
|
||||
{
|
||||
||||||| expected
|
||||
bool imgFrame::GetNeedsBackground() const
|
||||
{
|
||||
// We need a background painted if we have alpha or we're incomplete.
|
||||
=======
|
||||
bool imgFrame::GetNeedsBackground() const
|
||||
{
|
||||
// We need a background painted if we're incomplete.
|
||||
if (!ImageComplete()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// We need a background painted if we might not be opaque.
|
||||
>>>>>>> replacement
|
||||
<<<<<<< found
|
||||
return mFormat;
|
||||
||||||| expected
|
||||
return (mFormat == SurfaceFormat::B8G8R8A8 || !ImageComplete());
|
||||
=======
|
||||
if (mFormat == SurfaceFormat::B8G8R8A8 && !mHasNoAlpha) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
>>>>>>> replacement
|
||||
}
|
||||
|
||||
uint32_t imgFrame::GetImageBytesPerRow() const
|
||||
@ -804,13 +798,6 @@ nsresult imgFrame::UnlockImageData()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
imgFrame::SetDiscardable()
|
||||
{
|
||||
MOZ_ASSERT(mLockCount, "Expected to be locked when SetDiscardable is called");
|
||||
mDiscardable = true;
|
||||
}
|
||||
|
||||
void
|
||||
imgFrame::SetOptimizable()
|
||||
{
|
||||
|
@ -44,7 +44,8 @@ public:
|
||||
* when drawing content into an imgFrame, as it may use a different graphics
|
||||
* backend than normal content drawing.
|
||||
*/
|
||||
nsresult InitForDecoder(const nsIntRect& aRect,
|
||||
nsresult InitForDecoder(const nsIntSize& aImageSize,
|
||||
const nsIntRect& aRect,
|
||||
SurfaceFormat aFormat,
|
||||
uint8_t aPaletteDepth = 0);
|
||||
|
||||
@ -52,7 +53,7 @@ public:
|
||||
SurfaceFormat aFormat,
|
||||
uint8_t aPaletteDepth = 0)
|
||||
{
|
||||
return InitForDecoder(nsIntRect(0, 0, aSize.width, aSize.height),
|
||||
return InitForDecoder(aSize, nsIntRect(0, 0, aSize.width, aSize.height),
|
||||
aFormat, aPaletteDepth);
|
||||
}
|
||||
|
||||
@ -77,11 +78,11 @@ public:
|
||||
RawAccessFrameRef RawAccessRef();
|
||||
|
||||
bool Draw(gfxContext* aContext, const ImageRegion& aRegion,
|
||||
const nsIntMargin& aPadding, GraphicsFilter aFilter,
|
||||
uint32_t aImageFlags);
|
||||
GraphicsFilter aFilter, uint32_t aImageFlags);
|
||||
|
||||
nsresult ImageUpdated(const nsIntRect &aUpdateRect);
|
||||
|
||||
IntSize GetImageSize() { return mImageSize; }
|
||||
nsIntRect GetRect() const;
|
||||
IntSize GetSize() const { return mSize; }
|
||||
bool NeedsPadding() const { return mOffset != nsIntPoint(0, 0); }
|
||||
@ -112,7 +113,6 @@ public:
|
||||
bool GetCompositingFailed() const;
|
||||
void SetCompositingFailed(bool val);
|
||||
|
||||
void SetDiscardable();
|
||||
void SetOptimizable();
|
||||
|
||||
TemporaryRef<SourceSurface> GetSurface();
|
||||
@ -173,6 +173,7 @@ private: // data
|
||||
RefPtr<DataSourceSurface> mImageSurface;
|
||||
RefPtr<SourceSurface> mOptSurface;
|
||||
|
||||
IntSize mImageSize;
|
||||
IntSize mSize;
|
||||
nsIntPoint mOffset;
|
||||
|
||||
@ -205,7 +206,6 @@ private: // data
|
||||
bool mCompositingFailed;
|
||||
bool mHasNoAlpha;
|
||||
bool mNonPremult;
|
||||
bool mDiscardable;
|
||||
bool mOptimizable;
|
||||
|
||||
/** Have we called DiscardTracker::InformAllocation()? */
|
||||
|
Loading…
Reference in New Issue
Block a user