Skip to content

Commit

Permalink
Bug 1337111 - Part 5. Add pref to force decoding of full frames, disa…
Browse files Browse the repository at this point in the history
…bled by default. r=tnikkel
  • Loading branch information
aosmond committed Sep 17, 2018
1 parent 8d1ec5a commit 8be55f0
Show file tree
Hide file tree
Showing 8 changed files with 43 additions and 13 deletions.
1 change: 1 addition & 0 deletions gfx/thebes/gfxPrefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,7 @@ class gfxPrefs final

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);
Expand Down
8 changes: 4 additions & 4 deletions image/AnimationSurfaceProvider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion image/Decoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
15 changes: 11 additions & 4 deletions image/FrameAnimator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -336,6 +336,8 @@ FrameAnimator::AdvanceFrame(AnimationState& aState,
}

nextFrame->SetCompositingFailed(false);
} else {
ret.mDirtyRect = nextFrame->GetDirtyRect();
}

aState.mCurrentAnimationFrameTime =
Expand Down Expand Up @@ -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);
}
Expand Down
4 changes: 4 additions & 0 deletions image/RasterImage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
6 changes: 5 additions & 1 deletion image/imgFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ imgFrame::imgFrame()
, mPalettedImageData(nullptr)
, mPaletteDepth(0)
, mNonPremult(false)
, mIsFullFrame(false)
, mCompositingFailed(false)
{
}
Expand All @@ -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.
Expand All @@ -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
Expand Down
16 changes: 13 additions & 3 deletions image/imgFrame.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ class imgFrame
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)
Expand All @@ -68,8 +69,12 @@ class imgFrame
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);
}


Expand Down Expand Up @@ -191,6 +196,8 @@ class imgFrame
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);

Expand Down Expand Up @@ -340,6 +347,9 @@ class imgFrame

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.
Expand Down
4 changes: 4 additions & 0 deletions modules/libpref/init/all.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 8be55f0

Please sign in to comment.