mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-07 23:43:37 +00:00
Bug 1363092. Don't update the state of an animated image that requires an invalidation when creating a new decoder because we may not be able to send invalidations. r=aosmond
This commit is contained in:
parent
eadf9e9411
commit
5dbb032f4f
@ -30,7 +30,8 @@ namespace image {
|
||||
const gfx::IntRect
|
||||
AnimationState::UpdateState(bool aAnimationFinished,
|
||||
RasterImage *aImage,
|
||||
const gfx::IntSize& aSize)
|
||||
const gfx::IntSize& aSize,
|
||||
bool aAllowInvalidation /* = true */)
|
||||
{
|
||||
LookupResult result =
|
||||
SurfaceCache::Lookup(ImageKey(aImage),
|
||||
@ -44,7 +45,8 @@ AnimationState::UpdateState(bool aAnimationFinished,
|
||||
const gfx::IntRect
|
||||
AnimationState::UpdateStateInternal(LookupResult& aResult,
|
||||
bool aAnimationFinished,
|
||||
const gfx::IntSize& aSize)
|
||||
const gfx::IntSize& aSize,
|
||||
bool aAllowInvalidation /* = true */)
|
||||
{
|
||||
// Update mDiscarded and mIsCurrentlyDecoded.
|
||||
if (aResult.Type() == MatchType::NOT_FOUND) {
|
||||
@ -78,31 +80,33 @@ 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
|
||||
// finite length animation) don't have RequestRefresh called on them, and so
|
||||
// mCompositedFrameInvalid would never get cleared. We clear it here (and
|
||||
// also in RasterImage::Decode when we create a decoder for an image that
|
||||
// has finished animated so it can display sooner than waiting until the
|
||||
// decode completes). We also do it if we are fully decoded. This is safe
|
||||
// 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) {
|
||||
if (mHasBeenDecoded) {
|
||||
MOZ_ASSERT(gfxPrefs::ImageMemAnimatedDiscardable());
|
||||
mCompositedFrameInvalid = true;
|
||||
if (aAllowInvalidation) {
|
||||
// Update the value of mCompositedFrameInvalid.
|
||||
if (mIsCurrentlyDecoded || aAnimationFinished) {
|
||||
// Animated images that have finished their animation (ie because it is a
|
||||
// finite length animation) don't have RequestRefresh called on them, and so
|
||||
// mCompositedFrameInvalid would never get cleared. We clear it here (and
|
||||
// also in RasterImage::Decode when we create a decoder for an image that
|
||||
// has finished animated so it can display sooner than waiting until the
|
||||
// decode completes). We also do it if we are fully decoded. This is safe
|
||||
// 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) {
|
||||
if (mHasBeenDecoded) {
|
||||
MOZ_ASSERT(gfxPrefs::ImageMemAnimatedDiscardable());
|
||||
mCompositedFrameInvalid = true;
|
||||
}
|
||||
}
|
||||
// Otherwise don't change the value of mCompositedFrameInvalid, it will be
|
||||
// updated by RequestRefresh.
|
||||
}
|
||||
// Otherwise don't change the value of mCompositedFrameInvalid, it will be
|
||||
// updated by RequestRefresh.
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -42,16 +42,18 @@ public:
|
||||
/**
|
||||
* 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. Returns a rect to
|
||||
* invalidate.
|
||||
* mCompositedFrameInvalid, and mIsCurrentlyDecoded. If aAllowInvalidation
|
||||
* is true then returns a rect to invalidate.
|
||||
*/
|
||||
const gfx::IntRect UpdateState(bool aAnimationFinished,
|
||||
RasterImage *aImage,
|
||||
const gfx::IntSize& aSize);
|
||||
const gfx::IntSize& aSize,
|
||||
bool aAllowInvalidation = true);
|
||||
private:
|
||||
const gfx::IntRect UpdateStateInternal(LookupResult& aResult,
|
||||
bool aAnimationFinished,
|
||||
const gfx::IntSize& aSize);
|
||||
const gfx::IntSize& aSize,
|
||||
bool aAllowInvalidation = true);
|
||||
|
||||
public:
|
||||
/**
|
||||
|
@ -1261,20 +1261,13 @@ 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 shouldn't be a problem because we shouldn't be
|
||||
// getting a non-empty rect back from UpdateState. This is because UpdateState
|
||||
// will only return a non-empty rect if we are currently decoded, or the
|
||||
// animation is finished. We can't be decoded because we are creating a decoder
|
||||
// here. If the animation is finished then the composited frame would have
|
||||
// been valid when the animation finished, and it's not possible to mark
|
||||
// the composited frame as invalid when the animation is finished. So
|
||||
// the composited frame can't change from invalid to valid in this UpdateState
|
||||
// call, and hence no rect can be returned.
|
||||
// We pass false for aAllowInvalidation because we may be asked to use
|
||||
// async notifications. Any potential invalidation here will be sent when
|
||||
// RequestRefresh is called, or NotifyDecodeComplete.
|
||||
#ifdef DEBUG
|
||||
gfx::IntRect rect =
|
||||
#endif
|
||||
mAnimationState->UpdateState(mAnimationFinished, this, mSize);
|
||||
mAnimationState->UpdateState(mAnimationFinished, this, mSize, false);
|
||||
MOZ_ASSERT(rect.IsEmpty());
|
||||
} else {
|
||||
task = DecoderFactory::CreateDecoder(mDecoderType, WrapNotNull(this),
|
||||
|
Loading…
x
Reference in New Issue
Block a user