Skip to content

Commit

Permalink
Bug 1353299. Make sure to invalidate when composited frame becomes va…
Browse files Browse the repository at this point in the history
…lid. r=aosmond

We draw nothing when the composited frame is invalid, so when we mark it valid we should invalidate. Usually the action that causes the composited frame to be valid will invalidate (ie RequestRefresh).
  • Loading branch information
tnikkel committed Apr 6, 2017
1 parent fbb79c8 commit 91e6c26
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 14 deletions.
22 changes: 17 additions & 5 deletions image/FrameAnimator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ namespace image {
// AnimationState implementation.
///////////////////////////////////////////////////////////////////////////////

void
const gfx::IntRect
AnimationState::UpdateState(bool aAnimationFinished,
RasterImage *aImage,
const gfx::IntSize& aSize)
Expand All @@ -36,12 +36,13 @@ AnimationState::UpdateState(bool aAnimationFinished,
DefaultSurfaceFlags(),
PlaybackType::eAnimated));

UpdateStateInternal(result, aAnimationFinished);
return UpdateStateInternal(result, aAnimationFinished, aSize);
}

void
const gfx::IntRect
AnimationState::UpdateStateInternal(LookupResult& aResult,
bool aAnimationFinished)
bool aAnimationFinished,
const gfx::IntSize& aSize)
{
// Update mDiscarded and mIsCurrentlyDecoded.
if (aResult.Type() == MatchType::NOT_FOUND) {
Expand Down Expand Up @@ -73,6 +74,8 @@ AnimationState::UpdateStateInternal(LookupResult& aResult,
}
}

gfx::IntRect ret;

// Update the value of mCompositedFrameInvalid.
if (mIsCurrentlyDecoded || aAnimationFinished) {
// Animated images that have finished their animation (ie because it is a
Expand All @@ -84,6 +87,10 @@ AnimationState::UpdateStateInternal(LookupResult& aResult,
// to do for images that aren't finished animating because before we paint
// the refresh driver will call into us to advance to the correct frame,
// and that will succeed because we have all the frames.
if (mCompositedFrameInvalid) {
// Invalidate if we are marking the composited frame valid.
ret.SizeTo(aSize);
}
mCompositedFrameInvalid = false;
} else if (aResult.Type() == MatchType::NOT_FOUND ||
aResult.Type() == MatchType::PENDING) {
Expand All @@ -94,6 +101,8 @@ AnimationState::UpdateStateInternal(LookupResult& aResult,
}
// Otherwise don't change the value of mCompositedFrameInvalid, it will be
// updated by RequestRefresh.

return ret;
}

void
Expand Down Expand Up @@ -372,8 +381,11 @@ FrameAnimator::RequestRefresh(AnimationState& aState,
DefaultSurfaceFlags(),
PlaybackType::eAnimated));

aState.UpdateStateInternal(result, aAnimationFinished);
ret.mDirtyRect = aState.UpdateStateInternal(result, aAnimationFinished, mSize);
if (aState.IsDiscarded() || !result) {
if (!ret.mDirtyRect.IsEmpty()) {
ret.mFrameAdvanced = true;
}
return ret;
}

Expand Down
14 changes: 8 additions & 6 deletions image/FrameAnimator.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,16 @@ class AnimationState
/**
* Call this whenever a decode completes, a decode starts, or the image is
* discarded. It will update the internal state. Specifically mDiscarded,
* mCompositedFrameInvalid, and mIsCurrentlyDecoded.
* mCompositedFrameInvalid, and mIsCurrentlyDecoded. Returns a rect to
* invalidate.
*/
void UpdateState(bool aAnimationFinished,
RasterImage *aImage,
const gfx::IntSize& aSize);
const gfx::IntRect UpdateState(bool aAnimationFinished,
RasterImage *aImage,
const gfx::IntSize& aSize);
private:
void UpdateStateInternal(LookupResult& aResult,
bool aAnimationFinished);
const gfx::IntRect UpdateStateInternal(LookupResult& aResult,
bool aAnimationFinished,
const gfx::IntSize& aSize);

public:
/**
Expand Down
18 changes: 15 additions & 3 deletions image/RasterImage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,9 @@ RasterImage::OnSurfaceDiscardedInternal(bool aAnimatedFramesDiscarded)

if (aAnimatedFramesDiscarded && mAnimationState) {
MOZ_ASSERT(gfxPrefs::ImageMemAnimatedDiscardable());
mAnimationState->UpdateState(mAnimationFinished, this, mSize);
gfx::IntRect rect =
mAnimationState->UpdateState(mAnimationFinished, this, mSize);
NotifyProgress(NoProgress, rect);
}

if (mProgressTracker) {
Expand Down Expand Up @@ -1084,7 +1086,9 @@ RasterImage::Discard()
SurfaceCache::RemoveImage(ImageKey(this));

if (mAnimationState) {
mAnimationState->UpdateState(mAnimationFinished, this, mSize);
gfx::IntRect rect =
mAnimationState->UpdateState(mAnimationFinished, this, mSize);
NotifyProgress(NoProgress, rect);
}

// Notify that we discarded.
Expand Down Expand Up @@ -1257,6 +1261,11 @@ RasterImage::Decode(const IntSize& aSize,
task = DecoderFactory::CreateAnimationDecoder(mDecoderType, WrapNotNull(this),
mSourceBuffer, mSize,
decoderFlags, surfaceFlags);
// We may not be able to send an invalidation right here because of async
// notifications but that's not a problem because the first frame
// invalidation (when it comes) will invalidate for us. So we can ignore
// the return value of UpdateState. This also handles the invalidation
// from setting the composited frame as valid below.
mAnimationState->UpdateState(mAnimationFinished, this, mSize);
// If the animation is finished we can draw right away because we just draw
// the final frame all the time from now on. See comment in
Expand Down Expand Up @@ -1721,7 +1730,10 @@ RasterImage::NotifyDecodeComplete(const DecoderFinalStatus& aStatus,
// We've finished a full decode of all animation frames and our AnimationState
// has been notified about them all, so let it know not to expect anymore.
mAnimationState->NotifyDecodeComplete();
mAnimationState->UpdateState(mAnimationFinished, this, mSize);
gfx::IntRect rect = mAnimationState->UpdateState(mAnimationFinished, this, mSize);
if (!rect.IsEmpty()) {
NotifyProgress(NoProgress, rect);
}
}

// Do some telemetry if this isn't a metadata decode.
Expand Down

0 comments on commit 91e6c26

Please sign in to comment.