diff --git a/image/BlobSurfaceProvider.cpp b/image/BlobSurfaceProvider.cpp index b50ed5bf2537..c0d60573543a 100644 --- a/image/BlobSurfaceProvider.cpp +++ b/image/BlobSurfaceProvider.cpp @@ -123,7 +123,7 @@ nsresult BlobSurfaceProvider::UpdateKey( return NS_ERROR_FAILURE; } -void BlobSurfaceProvider::InvalidateRecording() { +void BlobSurfaceProvider::InvalidateSurface() { MOZ_ASSERT(NS_IsMainThread()); auto i = mKeys.Length(); diff --git a/image/BlobSurfaceProvider.h b/image/BlobSurfaceProvider.h index 8222450b39c3..1ea1cf1cb738 100644 --- a/image/BlobSurfaceProvider.h +++ b/image/BlobSurfaceProvider.h @@ -97,7 +97,7 @@ class BlobSurfaceProvider final : public ISurfaceProvider { wr::IpcResourceUpdateQueue& aResources, wr::ImageKey& aKey) override; - void InvalidateRecording() override; + void InvalidateSurface() override; void AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf, const AddSizeOfCb& aCallback) override { diff --git a/image/DecodedSurfaceProvider.cpp b/image/DecodedSurfaceProvider.cpp index cdfc27bcda03..f60b52018e02 100644 --- a/image/DecodedSurfaceProvider.cpp +++ b/image/DecodedSurfaceProvider.cpp @@ -222,6 +222,10 @@ nsresult DecodedSurfaceProvider::UpdateKey( nsresult SimpleSurfaceProvider::UpdateKey( layers::RenderRootStateManager* aManager, wr::IpcResourceUpdateQueue& aResources, wr::ImageKey& aKey) { + if (mDirty) { + return NS_ERROR_FAILURE; + } + RefPtr surface = mSurface->GetSourceSurface(); if (!surface) { return NS_ERROR_FAILURE; @@ -230,5 +234,7 @@ nsresult SimpleSurfaceProvider::UpdateKey( return SharedSurfacesChild::Share(surface, aManager, aResources, aKey); } +void SimpleSurfaceProvider::InvalidateSurface() { mDirty = true; } + } // namespace image } // namespace mozilla diff --git a/image/ISurfaceProvider.h b/image/ISurfaceProvider.h index 03ab713238ac..b9241f80a5d6 100644 --- a/image/ISurfaceProvider.h +++ b/image/ISurfaceProvider.h @@ -314,6 +314,8 @@ class SimpleSurfaceProvider final : public ISurfaceProvider { wr::IpcResourceUpdateQueue& aResources, wr::ImageKey& aKey) override; + void InvalidateSurface() override; + protected: DrawableFrameRef DrawableRef(size_t aFrame) override { MOZ_ASSERT(aFrame == 0, @@ -338,6 +340,7 @@ class SimpleSurfaceProvider final : public ISurfaceProvider { NotNull> mSurface; DrawableFrameRef mLockRef; + bool mDirty = false; }; } // namespace image diff --git a/image/SurfaceCache.cpp b/image/SurfaceCache.cpp index 6f05bce6ff6b..cccbd505f5ee 100644 --- a/image/SurfaceCache.cpp +++ b/image/SurfaceCache.cpp @@ -181,7 +181,7 @@ class CachedSurface { return aMallocSizeOf(this) + aMallocSizeOf(mProvider.get()); } - void InvalidateRecording() { mProvider->InvalidateRecording(); } + void InvalidateSurface() { mProvider->InvalidateSurface(); } // A helper type used by SurfaceCacheImpl::CollectSizeOfSurfaces. struct MOZ_STACK_CLASS SurfaceMemoryReport { @@ -543,13 +543,14 @@ class ImageSurfaceCache { bool Invalidate(Function&& aRemoveCallback) { // Remove all non-blob recordings from the cache. Invalidate any blob // recordings. - bool foundRecording = false; + bool found = false; for (auto iter = mSurfaces.Iter(); !iter.Done(); iter.Next()) { NotNull current = WrapNotNull(iter.UserData()); + found = true; + current->InvalidateSurface(); + if (current->GetSurfaceKey().Flags() & SurfaceFlags::RECORD_BLOB) { - foundRecording = true; - current->InvalidateRecording(); continue; } @@ -558,7 +559,7 @@ class ImageSurfaceCache { } AfterMaybeRemove(); - return foundRecording; + return found; } IntSize SuggestedSize(const IntSize& aSize) const { diff --git a/image/SurfaceCache.h b/image/SurfaceCache.h index 864a6ffbc475..de4d448b0094 100644 --- a/image/SurfaceCache.h +++ b/image/SurfaceCache.h @@ -424,12 +424,14 @@ struct SurfaceCache { /** * Removes all rasterized cache entries (including placeholders) associated - * with the given image from the cache. Any blob recordings are marked as - * dirty and must be regenerated. + * with the given image from the cache and marks their surface providers as + * dirty and should not be drawn again. Any blob recordings are left in th + * cache but marked as dirty and must be regenerated. * * @param aImageKey The image whose cache which should be regenerated. * - * @returns true if any recordings were invalidated, else false. + * @returns true if any surface providers were present in the cache, else + * false. */ static bool InvalidateImage(const ImageKey aImageKey); diff --git a/image/VectorImage.cpp b/image/VectorImage.cpp index eccd04e3cfc0..11fb99082404 100644 --- a/image/VectorImage.cpp +++ b/image/VectorImage.cpp @@ -513,7 +513,7 @@ void VectorImage::SendInvalidationNotifications() { mHasPendingInvalidation = false; if (SurfaceCache::InvalidateImage(ImageKey(this))) { - // If we still have recordings in the cache, make sure we handle future + // If we had any surface providers in the cache, make sure we handle future // invalidations. MOZ_ASSERT(mRenderingObserver, "Should have a rendering observer by now"); mRenderingObserver->ResumeHonoringInvalidations(); diff --git a/image/WebRenderImageProvider.h b/image/WebRenderImageProvider.h index 84fee8cb47b3..af60bbf357a1 100644 --- a/image/WebRenderImageProvider.h +++ b/image/WebRenderImageProvider.h @@ -48,9 +48,10 @@ class WebRenderImageProvider { } /** - * Invalidate if a blob recording, requiring it to be regenerated. + * Invalidate if a blob recording or simple surface provider (both are only + * used by vector images), requiring it to be regenerated. */ - virtual void InvalidateRecording() {} + virtual void InvalidateSurface() {} protected: WebRenderImageProvider(const ImageResource* aImage); diff --git a/image/test/reftest/generic/1805599-1-ref.html b/image/test/reftest/generic/1805599-1-ref.html new file mode 100644 index 000000000000..701235661907 --- /dev/null +++ b/image/test/reftest/generic/1805599-1-ref.html @@ -0,0 +1,2 @@ + + diff --git a/image/test/reftest/generic/1805599-1.html b/image/test/reftest/generic/1805599-1.html new file mode 100644 index 000000000000..ee5295dab538 --- /dev/null +++ b/image/test/reftest/generic/1805599-1.html @@ -0,0 +1,34 @@ + + + + + + diff --git a/image/test/reftest/generic/1805599-1.png b/image/test/reftest/generic/1805599-1.png new file mode 100644 index 000000000000..a4fc33db03b1 Binary files /dev/null and b/image/test/reftest/generic/1805599-1.png differ diff --git a/image/test/reftest/generic/1805599-1.svg b/image/test/reftest/generic/1805599-1.svg new file mode 100644 index 000000000000..efc2fa561736 --- /dev/null +++ b/image/test/reftest/generic/1805599-1.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/image/test/reftest/generic/reftest.list b/image/test/reftest/generic/reftest.list index 5190b52a0ec6..6729286168a6 100644 --- a/image/test/reftest/generic/reftest.list +++ b/image/test/reftest/generic/reftest.list @@ -4,3 +4,4 @@ skip-if(Android) != moz-icon-1.html about:blank skip-if(Android) != moz-icon-blank-1-ref.html moz-icon-blank-1-antiref.html skip-if(Android) != moz-icon-blank-1-ref.html moz-icon-blank-1-antiref2.html fuzzy-if(cocoaWidget,44-49,335-348) fuzzy-if(winWidget,64-140,45-191) == moz-icon-blank-1-almostref.html moz-icon-blank-1-ref.html +pref(image.testing.decode-sync.enabled,false) == 1805599-1.html 1805599-1-ref.html