Bug 1256603. Only mark images as used in the surface cache if we actually use them. r=aosmond

We were marking them used even if only a decode was requested.

This can cause us to hold extra decoded copies of the image around because we have a tendency to request decode at the intrinsic size.
This commit is contained in:
Timothy Nikkel 2018-10-13 00:31:02 -05:00
Родитель da38782e5c
Коммит df61b9e8ff
6 изменённых файлов: 45 добавлений и 26 удалений

Просмотреть файл

@ -37,7 +37,8 @@ AnimationState::UpdateState(bool aAnimationFinished,
SurfaceCache::Lookup(ImageKey(aImage), SurfaceCache::Lookup(ImageKey(aImage),
RasterSurfaceKey(aSize, RasterSurfaceKey(aSize,
DefaultSurfaceFlags(), DefaultSurfaceFlags(),
PlaybackType::eAnimated)); PlaybackType::eAnimated),
/* aMarkUsed = */ false);
return UpdateStateInternal(result, aAnimationFinished, aSize, aAllowInvalidation); return UpdateStateInternal(result, aAnimationFinished, aSize, aAllowInvalidation);
} }
@ -398,7 +399,8 @@ FrameAnimator::ResetAnimation(AnimationState& aState)
SurfaceCache::Lookup(ImageKey(mImage), SurfaceCache::Lookup(ImageKey(mImage),
RasterSurfaceKey(mSize, RasterSurfaceKey(mSize,
DefaultSurfaceFlags(), DefaultSurfaceFlags(),
PlaybackType::eAnimated)); PlaybackType::eAnimated),
/* aMarkUsed = */ false);
if (!result) { if (!result) {
return; return;
} }
@ -427,7 +429,8 @@ FrameAnimator::RequestRefresh(AnimationState& aState,
SurfaceCache::Lookup(ImageKey(mImage), SurfaceCache::Lookup(ImageKey(mImage),
RasterSurfaceKey(mSize, RasterSurfaceKey(mSize,
DefaultSurfaceFlags(), DefaultSurfaceFlags(),
PlaybackType::eAnimated)); PlaybackType::eAnimated),
/* aMarkUsed = */ true);
ret.mDirtyRect = aState.UpdateStateInternal(result, aAnimationFinished, mSize); ret.mDirtyRect = aState.UpdateStateInternal(result, aAnimationFinished, mSize);
if (aState.IsDiscarded() || !result) { if (aState.IsDiscarded() || !result) {
@ -502,7 +505,7 @@ FrameAnimator::RequestRefresh(AnimationState& aState,
} }
LookupResult LookupResult
FrameAnimator::GetCompositedFrame(AnimationState& aState) FrameAnimator::GetCompositedFrame(AnimationState& aState, bool aMarkUsed)
{ {
aState.mCompositedFrameRequested = true; aState.mCompositedFrameRequested = true;
@ -517,7 +520,8 @@ FrameAnimator::GetCompositedFrame(AnimationState& aState)
SurfaceCache::Lookup(ImageKey(mImage), SurfaceCache::Lookup(ImageKey(mImage),
RasterSurfaceKey(mSize, RasterSurfaceKey(mSize,
DefaultSurfaceFlags(), DefaultSurfaceFlags(),
PlaybackType::eAnimated)); PlaybackType::eAnimated),
aMarkUsed);
if (aState.mCompositedFrameInvalid) { if (aState.mCompositedFrameInvalid) {
MOZ_ASSERT(gfxPrefs::ImageMemAnimatedDiscardable()); MOZ_ASSERT(gfxPrefs::ImageMemAnimatedDiscardable());

Просмотреть файл

@ -323,7 +323,8 @@ public:
* not have required compositing). It may not be available because it hasn't * not have required compositing). It may not be available because it hasn't
* been decoded yet, in which case we return an empty LookupResult. * been decoded yet, in which case we return an empty LookupResult.
*/ */
LookupResult GetCompositedFrame(AnimationState& aState); LookupResult GetCompositedFrame(AnimationState& aState,
bool aMarkUsed);
/** /**
* Collect an accounting of the memory occupied by the compositing surfaces we * Collect an accounting of the memory occupied by the compositing surfaces we

Просмотреть файл

@ -298,13 +298,14 @@ RasterImage::GetType(uint16_t* aType)
LookupResult LookupResult
RasterImage::LookupFrameInternal(const IntSize& aSize, RasterImage::LookupFrameInternal(const IntSize& aSize,
uint32_t aFlags, uint32_t aFlags,
PlaybackType aPlaybackType) PlaybackType aPlaybackType,
bool aMarkUsed)
{ {
if (mAnimationState && aPlaybackType == PlaybackType::eAnimated) { if (mAnimationState && aPlaybackType == PlaybackType::eAnimated) {
MOZ_ASSERT(mFrameAnimator); MOZ_ASSERT(mFrameAnimator);
MOZ_ASSERT(ToSurfaceFlags(aFlags) == DefaultSurfaceFlags(), MOZ_ASSERT(ToSurfaceFlags(aFlags) == DefaultSurfaceFlags(),
"Can't composite frames with non-default surface flags"); "Can't composite frames with non-default surface flags");
return mFrameAnimator->GetCompositedFrame(*mAnimationState); return mFrameAnimator->GetCompositedFrame(*mAnimationState, aMarkUsed);
} }
SurfaceFlags surfaceFlags = ToSurfaceFlags(aFlags); SurfaceFlags surfaceFlags = ToSurfaceFlags(aFlags);
@ -316,20 +317,23 @@ RasterImage::LookupFrameInternal(const IntSize& aSize,
return SurfaceCache::Lookup(ImageKey(this), return SurfaceCache::Lookup(ImageKey(this),
RasterSurfaceKey(aSize, RasterSurfaceKey(aSize,
surfaceFlags, surfaceFlags,
PlaybackType::eStatic)); PlaybackType::eStatic),
aMarkUsed);
} }
// We'll return the best match we can find to the requested frame. // We'll return the best match we can find to the requested frame.
return SurfaceCache::LookupBestMatch(ImageKey(this), return SurfaceCache::LookupBestMatch(ImageKey(this),
RasterSurfaceKey(aSize, RasterSurfaceKey(aSize,
surfaceFlags, surfaceFlags,
PlaybackType::eStatic)); PlaybackType::eStatic),
aMarkUsed);
} }
LookupResult LookupResult
RasterImage::LookupFrame(const IntSize& aSize, RasterImage::LookupFrame(const IntSize& aSize,
uint32_t aFlags, uint32_t aFlags,
PlaybackType aPlaybackType) PlaybackType aPlaybackType,
bool aMarkUsed /* = true */)
{ {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
@ -347,7 +351,7 @@ RasterImage::LookupFrame(const IntSize& aSize,
} }
LookupResult result = LookupResult result =
LookupFrameInternal(requestedSize, aFlags, aPlaybackType); LookupFrameInternal(requestedSize, aFlags, aPlaybackType, aMarkUsed);
if (!result && !mHasSize) { if (!result && !mHasSize) {
// We can't request a decode without knowing our intrinsic size. Give up. // We can't request a decode without knowing our intrinsic size. Give up.
@ -377,7 +381,7 @@ RasterImage::LookupFrame(const IntSize& aSize,
// If we can or did sync decode, we should already have the frame. // If we can or did sync decode, we should already have the frame.
if (ranSync || (aFlags & FLAG_SYNC_DECODE)) { if (ranSync || (aFlags & FLAG_SYNC_DECODE)) {
result = LookupFrameInternal(requestedSize, aFlags, aPlaybackType); result = LookupFrameInternal(requestedSize, aFlags, aPlaybackType, aMarkUsed);
} }
} }
@ -462,7 +466,8 @@ RasterImage::WillDrawOpaqueNow()
SurfaceCache::LookupBestMatch(ImageKey(this), SurfaceCache::LookupBestMatch(ImageKey(this),
RasterSurfaceKey(mSize, RasterSurfaceKey(mSize,
DefaultSurfaceFlags(), DefaultSurfaceFlags(),
PlaybackType::eStatic)); PlaybackType::eStatic),
/* aMarkUsed = */ false);
MatchType matchType = result.Type(); MatchType matchType = result.Type();
if (matchType == MatchType::NOT_FOUND || matchType == MatchType::PENDING || if (matchType == MatchType::NOT_FOUND || matchType == MatchType::PENDING ||
!result.Surface()->IsFinished()) { !result.Surface()->IsFinished()) {
@ -1200,7 +1205,7 @@ RasterImage::RequestDecodeForSizeInternal(const IntSize& aSize, uint32_t aFlags)
// Perform a frame lookup, which will implicitly start decoding if needed. // Perform a frame lookup, which will implicitly start decoding if needed.
PlaybackType playbackType = mAnimationState ? PlaybackType::eAnimated PlaybackType playbackType = mAnimationState ? PlaybackType::eAnimated
: PlaybackType::eStatic; : PlaybackType::eStatic;
LookupResult result = LookupFrame(aSize, flags, playbackType); LookupResult result = LookupFrame(aSize, flags, playbackType, /* aMarkUsed = */ false);
return std::move(result.Surface()); return std::move(result.Surface());
} }

Просмотреть файл

@ -284,19 +284,22 @@ private:
* data, we'll attempt a sync decode if no matching surface is found. If * data, we'll attempt a sync decode if no matching surface is found. If
* FLAG_SYNC_DECODE was not specified and no matching surface was found, we'll * FLAG_SYNC_DECODE was not specified and no matching surface was found, we'll
* kick off an async decode so that the surface is (hopefully) available next * kick off an async decode so that the surface is (hopefully) available next
* time it's requested. * time it's requested. aMarkUsed determines if we mark the surface used in
* the surface cache or not.
* *
* @return a drawable surface, which may be empty if the requested surface * @return a drawable surface, which may be empty if the requested surface
* could not be found. * could not be found.
*/ */
LookupResult LookupFrame(const gfx::IntSize& aSize, LookupResult LookupFrame(const gfx::IntSize& aSize,
uint32_t aFlags, uint32_t aFlags,
PlaybackType aPlaybackType); PlaybackType aPlaybackType,
bool aMarkUsed = true);
/// Helper method for LookupFrame(). /// Helper method for LookupFrame().
LookupResult LookupFrameInternal(const gfx::IntSize& aSize, LookupResult LookupFrameInternal(const gfx::IntSize& aSize,
uint32_t aFlags, uint32_t aFlags,
PlaybackType aPlaybackType); PlaybackType aPlaybackType,
bool aMarkUsed);
ImgDrawResult DrawInternal(DrawableSurface&& aFrameRef, ImgDrawResult DrawInternal(DrawableSurface&& aFrameRef,
gfxContext* aContext, gfxContext* aContext,

Просмотреть файл

@ -999,7 +999,8 @@ public:
LookupResult LookupBestMatch(const ImageKey aImageKey, LookupResult LookupBestMatch(const ImageKey aImageKey,
const SurfaceKey& aSurfaceKey, const SurfaceKey& aSurfaceKey,
const StaticMutexAutoLock& aAutoLock) const StaticMutexAutoLock& aAutoLock,
bool aMarkUsed /* = true */)
{ {
RefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey); RefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey);
if (!cache) { if (!cache) {
@ -1045,7 +1046,8 @@ public:
if (matchType == MatchType::EXACT || if (matchType == MatchType::EXACT ||
matchType == MatchType::SUBSTITUTE_BECAUSE_BEST) { matchType == MatchType::SUBSTITUTE_BECAUSE_BEST) {
if (!MarkUsed(WrapNotNull(surface), WrapNotNull(cache), aAutoLock)) { if (aMarkUsed &&
!MarkUsed(WrapNotNull(surface), WrapNotNull(cache), aAutoLock)) {
Remove(WrapNotNull(surface), /* aStopTracking */ false, aAutoLock); Remove(WrapNotNull(surface), /* aStopTracking */ false, aAutoLock);
} }
} }
@ -1516,7 +1518,8 @@ SurfaceCache::Shutdown()
/* static */ LookupResult /* static */ LookupResult
SurfaceCache::Lookup(const ImageKey aImageKey, SurfaceCache::Lookup(const ImageKey aImageKey,
const SurfaceKey& aSurfaceKey) const SurfaceKey& aSurfaceKey,
bool aMarkUsed /* = true */)
{ {
nsTArray<RefPtr<CachedSurface>> discard; nsTArray<RefPtr<CachedSurface>> discard;
LookupResult rv(MatchType::NOT_FOUND); LookupResult rv(MatchType::NOT_FOUND);
@ -1527,7 +1530,7 @@ SurfaceCache::Lookup(const ImageKey aImageKey,
return rv; return rv;
} }
rv = sInstance->Lookup(aImageKey, aSurfaceKey, lock); rv = sInstance->Lookup(aImageKey, aSurfaceKey, lock, aMarkUsed);
sInstance->TakeDiscard(discard, lock); sInstance->TakeDiscard(discard, lock);
} }
@ -1536,7 +1539,8 @@ SurfaceCache::Lookup(const ImageKey aImageKey,
/* static */ LookupResult /* static */ LookupResult
SurfaceCache::LookupBestMatch(const ImageKey aImageKey, SurfaceCache::LookupBestMatch(const ImageKey aImageKey,
const SurfaceKey& aSurfaceKey) const SurfaceKey& aSurfaceKey,
bool aMarkUsed /* = true */)
{ {
nsTArray<RefPtr<CachedSurface>> discard; nsTArray<RefPtr<CachedSurface>> discard;
LookupResult rv(MatchType::NOT_FOUND); LookupResult rv(MatchType::NOT_FOUND);
@ -1547,7 +1551,7 @@ SurfaceCache::LookupBestMatch(const ImageKey aImageKey,
return rv; return rv;
} }
rv = sInstance->LookupBestMatch(aImageKey, aSurfaceKey, lock); rv = sInstance->LookupBestMatch(aImageKey, aSurfaceKey, lock, aMarkUsed);
sInstance->TakeDiscard(discard, lock); sInstance->TakeDiscard(discard, lock);
} }

Просмотреть файл

@ -232,7 +232,8 @@ struct SurfaceCache
* if the cache entry was found. * if the cache entry was found.
*/ */
static LookupResult Lookup(const ImageKey aImageKey, static LookupResult Lookup(const ImageKey aImageKey,
const SurfaceKey& aSurfaceKey); const SurfaceKey& aSurfaceKey,
bool aMarkUsed = true);
/** /**
* Looks up the best matching cache entry and returns a drawable reference to * Looks up the best matching cache entry and returns a drawable reference to
@ -251,7 +252,8 @@ struct SurfaceCache
* returned surface exactly matches @aSurfaceKey. * returned surface exactly matches @aSurfaceKey.
*/ */
static LookupResult LookupBestMatch(const ImageKey aImageKey, static LookupResult LookupBestMatch(const ImageKey aImageKey,
const SurfaceKey& aSurfaceKey); const SurfaceKey& aSurfaceKey,
bool aMarkUsed = true);
/** /**
* Insert an ISurfaceProvider into the cache. If an entry with the same * Insert an ISurfaceProvider into the cache. If an entry with the same