mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 23:02:20 +00:00
Bug 1337111 - Part 5. Add pref to force decoding of full frames, disabled by default. r=tnikkel
This commit is contained in:
parent
8d1ec5a066
commit
8be55f0165
@ -543,6 +543,7 @@ private:
|
||||
|
||||
DECL_GFX_PREF(Live, "image.animated.decode-on-demand.threshold-kb", ImageAnimatedDecodeOnDemandThresholdKB, uint32_t, 20480);
|
||||
DECL_GFX_PREF(Live, "image.animated.decode-on-demand.batch-size", ImageAnimatedDecodeOnDemandBatchSize, uint32_t, 6);
|
||||
DECL_GFX_PREF(Live, "image.animated.generate-full-frames", ImageAnimatedGenerateFullFrames, bool, false);
|
||||
DECL_GFX_PREF(Live, "image.animated.resume-from-last-displayed", ImageAnimatedResumeFromLastDisplayed, bool, false);
|
||||
DECL_GFX_PREF(Live, "image.cache.factor2.threshold-surfaces", ImageCacheFactor2ThresholdSurfaces, int32_t, -1);
|
||||
DECL_GFX_PREF(Once, "image.cache.size", ImageCacheSize, int32_t, 5*1024*1024);
|
||||
|
@ -32,10 +32,10 @@ AnimationSurfaceProvider::AnimationSurfaceProvider(NotNull<RasterImage*> aImage,
|
||||
MOZ_ASSERT(!mDecoder->IsFirstFrameDecode(),
|
||||
"Use DecodedSurfaceProvider for single-frame image decodes");
|
||||
|
||||
// We still produce paletted surfaces for GIF which means the frames are
|
||||
// smaller than one would expect for APNG. This may be removed if/when
|
||||
// bug 1337111 lands and it is enabled by default.
|
||||
size_t pixelSize = aDecoder->GetType() == DecoderType::GIF
|
||||
// We may produce paletted surfaces for GIF which means the frames are smaller
|
||||
// than one would expect.
|
||||
size_t pixelSize = !aDecoder->ShouldBlendAnimation() &&
|
||||
aDecoder->GetType() == DecoderType::GIF
|
||||
? sizeof(uint8_t) : sizeof(uint32_t);
|
||||
|
||||
// Calculate how many frames we need to decode in this animation before we
|
||||
|
@ -343,7 +343,7 @@ Decoder::AllocateFrameInternal(const gfx::IntSize& aOutputSize,
|
||||
bool nonPremult = bool(mSurfaceFlags & SurfaceFlags::NO_PREMULTIPLY_ALPHA);
|
||||
if (NS_FAILED(frame->InitForDecoder(aOutputSize, aFrameRect, aFormat,
|
||||
aPaletteDepth, nonPremult,
|
||||
aAnimParams))) {
|
||||
aAnimParams, ShouldBlendAnimation()))) {
|
||||
NS_WARNING("imgFrame::Init should succeed");
|
||||
return RawAccessFrameRef();
|
||||
}
|
||||
|
@ -316,10 +316,10 @@ FrameAnimator::AdvanceFrame(AnimationState& aState,
|
||||
}
|
||||
|
||||
if (nextFrameIndex == 0) {
|
||||
MOZ_ASSERT(nextFrame->IsFullFrame());
|
||||
ret.mDirtyRect = aState.FirstFrameRefreshArea();
|
||||
} else {
|
||||
} else if (!nextFrame->IsFullFrame()) {
|
||||
MOZ_ASSERT(nextFrameIndex == currentFrameIndex + 1);
|
||||
|
||||
// Change frame
|
||||
if (!DoBlend(aCurrentFrame, nextFrame, nextFrameIndex, &ret.mDirtyRect)) {
|
||||
// something went wrong, move on to next
|
||||
@ -336,6 +336,8 @@ FrameAnimator::AdvanceFrame(AnimationState& aState,
|
||||
}
|
||||
|
||||
nextFrame->SetCompositingFailed(false);
|
||||
} else {
|
||||
ret.mDirtyRect = nextFrame->GetDirtyRect();
|
||||
}
|
||||
|
||||
aState.mCurrentAnimationFrameTime =
|
||||
@ -483,8 +485,13 @@ FrameAnimator::RequestRefresh(AnimationState& aState,
|
||||
}
|
||||
}
|
||||
|
||||
// Advanced to the correct frame, the composited frame is now valid to be drawn.
|
||||
if (currentFrameEndTime > aTime) {
|
||||
// We should only mark the composited frame as valid and reset the dirty rect
|
||||
// if we advanced (meaning the next frame was actually produced somehow), the
|
||||
// composited frame was previously invalid (so we may need to repaint
|
||||
// everything) and the frame index is valid (to know we were doing blending
|
||||
// on the main thread, instead of on the decoder threads in advance).
|
||||
if (currentFrameEndTime > aTime && aState.mCompositedFrameInvalid &&
|
||||
mLastCompositedFrameIndex >= 0) {
|
||||
aState.mCompositedFrameInvalid = false;
|
||||
ret.mDirtyRect = IntRect(IntPoint(0,0), mSize);
|
||||
}
|
||||
|
@ -1286,6 +1286,10 @@ RasterImage::Decode(const IntSize& aSize,
|
||||
nsresult rv;
|
||||
bool animated = mAnimationState && aPlaybackType == PlaybackType::eAnimated;
|
||||
if (animated) {
|
||||
if (gfxPrefs::ImageAnimatedGenerateFullFrames()) {
|
||||
decoderFlags |= DecoderFlags::BLEND_ANIMATION;
|
||||
}
|
||||
|
||||
size_t currentFrame = mAnimationState->GetCurrentAnimationFrameIndex();
|
||||
rv = DecoderFactory::CreateAnimationDecoder(mDecoderType, WrapNotNull(this),
|
||||
mSourceBuffer, mSize,
|
||||
|
@ -213,6 +213,7 @@ imgFrame::imgFrame()
|
||||
, mPalettedImageData(nullptr)
|
||||
, mPaletteDepth(0)
|
||||
, mNonPremult(false)
|
||||
, mIsFullFrame(false)
|
||||
, mCompositingFailed(false)
|
||||
{
|
||||
}
|
||||
@ -235,7 +236,8 @@ imgFrame::InitForDecoder(const nsIntSize& aImageSize,
|
||||
SurfaceFormat aFormat,
|
||||
uint8_t aPaletteDepth /* = 0 */,
|
||||
bool aNonPremult /* = false */,
|
||||
const Maybe<AnimationParams>& aAnimParams /* = Nothing() */)
|
||||
const Maybe<AnimationParams>& aAnimParams /* = Nothing() */,
|
||||
bool aIsFullFrame /* = false */)
|
||||
{
|
||||
// Assert for properties that should be verified by decoders,
|
||||
// warn for properties related to bad content.
|
||||
@ -258,8 +260,10 @@ imgFrame::InitForDecoder(const nsIntSize& aImageSize,
|
||||
mTimeout = aAnimParams->mTimeout;
|
||||
mBlendMethod = aAnimParams->mBlendMethod;
|
||||
mDisposalMethod = aAnimParams->mDisposalMethod;
|
||||
mIsFullFrame = aAnimParams->mFrameNum == 0 || aIsFullFrame;
|
||||
} else {
|
||||
mBlendRect = aRect;
|
||||
mIsFullFrame = true;
|
||||
}
|
||||
|
||||
// We only allow a non-trivial frame rect (i.e., a frame rect that doesn't
|
||||
|
@ -59,7 +59,8 @@ public:
|
||||
SurfaceFormat aFormat,
|
||||
uint8_t aPaletteDepth = 0,
|
||||
bool aNonPremult = false,
|
||||
const Maybe<AnimationParams>& aAnimParams = Nothing());
|
||||
const Maybe<AnimationParams>& aAnimParams = Nothing(),
|
||||
bool aIsFullFrame = false);
|
||||
|
||||
nsresult InitForAnimator(const nsIntSize& aSize,
|
||||
SurfaceFormat aFormat)
|
||||
@ -68,8 +69,12 @@ public:
|
||||
AnimationParams animParams { frameRect, FrameTimeout::Forever(),
|
||||
/* aFrameNum */ 1, BlendMethod::OVER,
|
||||
DisposalMethod::NOT_SPECIFIED };
|
||||
return InitForDecoder(aSize, frameRect,
|
||||
aFormat, 0, false, Some(animParams));
|
||||
// We set aIsFullFrame to false because we don't want the compositing frame
|
||||
// to be allocated into shared memory for WebRender. mIsFullFrame is only
|
||||
// otherwise used for frames produced by Decoder, so it isn't relevant.
|
||||
return InitForDecoder(aSize, frameRect, aFormat, /* aPaletteDepth */ 0,
|
||||
/* aNonPremult */ false, Some(animParams),
|
||||
/* aIsFullFrame */ false);
|
||||
}
|
||||
|
||||
|
||||
@ -191,6 +196,8 @@ public:
|
||||
const IntRect& GetDirtyRect() const { return mDirtyRect; }
|
||||
void SetDirtyRect(const IntRect& aDirtyRect) { mDirtyRect = aDirtyRect; }
|
||||
|
||||
bool IsFullFrame() const { return mIsFullFrame; }
|
||||
|
||||
bool GetCompositingFailed() const;
|
||||
void SetCompositingFailed(bool val);
|
||||
|
||||
@ -340,6 +347,9 @@ private: // data
|
||||
|
||||
bool mNonPremult;
|
||||
|
||||
//! True if the frame has all of the data stored in it, false if it needs to
|
||||
//! be combined with another frame (e.g. the previous frame) to be complete.
|
||||
bool mIsFullFrame;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Main-thread-only mutable data.
|
||||
|
@ -4608,6 +4608,10 @@ pref("image.animated.decode-on-demand.threshold-kb", 20480);
|
||||
// animation's currently displayed frame.
|
||||
pref("image.animated.decode-on-demand.batch-size", 6);
|
||||
|
||||
// Whether we should generate full frames at decode time or partial frames which
|
||||
// are combined at display time (historical behavior and default).
|
||||
pref("image.animated.generate-full-frames", false);
|
||||
|
||||
// Resume an animated image from the last displayed frame rather than
|
||||
// advancing when out of view.
|
||||
pref("image.animated.resume-from-last-displayed", true);
|
||||
|
Loading…
Reference in New Issue
Block a user