mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-29 11:57:32 +09:00
Issue #2073 - m-c 1651587: Make image::Image release efficient on main thread
This commit is contained in:
parent
03a4a17ccf
commit
9a39001cc3
6 changed files with 75 additions and 13 deletions
|
|
@ -61,14 +61,8 @@ AnimationSurfaceProvider::DropImageReference()
|
||||||
return; // Nothing to do.
|
return; // Nothing to do.
|
||||||
}
|
}
|
||||||
|
|
||||||
// RasterImage objects need to be destroyed on the main thread. We also need
|
// RasterImage objects need to be destroyed on the main thread.
|
||||||
// to destroy them asynchronously, because if our surface cache entry is
|
SurfaceCache::ReleaseImageOnMainThread(mImage.forget());
|
||||||
// destroyed and we were the only thing keeping |mImage| alive, RasterImage's
|
|
||||||
// destructor may call into the surface cache while whatever code caused us to
|
|
||||||
// get evicted is holding the surface cache lock, causing deadlock.
|
|
||||||
RefPtr<RasterImage> image = mImage;
|
|
||||||
mImage = nullptr;
|
|
||||||
NS_ReleaseOnMainThread(image.forget(), /* aAlwaysProxy = */ true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,8 @@ DecodedSurfaceProvider::DropImageReference()
|
||||||
// get evicted is holding the surface cache lock, causing deadlock.
|
// get evicted is holding the surface cache lock, causing deadlock.
|
||||||
RefPtr<RasterImage> image = mImage;
|
RefPtr<RasterImage> image = mImage;
|
||||||
mImage = nullptr;
|
mImage = nullptr;
|
||||||
NS_ReleaseOnMainThread(image.forget(), /* aAlwaysProxy = */ true);
|
SurfaceCache::ReleaseImageOnMainThread(image.forget(),
|
||||||
|
/* aAlwaysProxy = */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawableFrameRef
|
DrawableFrameRef
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ Decoder::~Decoder()
|
||||||
if (mImage && !NS_IsMainThread()) {
|
if (mImage && !NS_IsMainThread()) {
|
||||||
// Dispatch mImage to main thread to prevent it from being destructed by the
|
// Dispatch mImage to main thread to prevent it from being destructed by the
|
||||||
// decode thread.
|
// decode thread.
|
||||||
NS_ReleaseOnMainThread(mImage.forget());
|
SurfaceCache::ReleaseImageOnMainThread(mImage.forget());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -434,8 +434,7 @@ RasterImage::OnSurfaceDiscarded(const SurfaceKey& aSurfaceKey)
|
||||||
mAnimationState && aSurfaceKey.Playback() == PlaybackType::eAnimated;
|
mAnimationState && aSurfaceKey.Playback() == PlaybackType::eAnimated;
|
||||||
|
|
||||||
RefPtr<RasterImage> image = this;
|
RefPtr<RasterImage> image = this;
|
||||||
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
NS_DispatchToMainThread(NS_NewRunnableFunction([=]() -> void {
|
||||||
[=]() -> void {
|
|
||||||
image->OnSurfaceDiscardedInternal(animatedFramesDiscarded);
|
image->OnSurfaceDiscardedInternal(animatedFramesDiscarded);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -835,6 +835,32 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ReleaseImageOnMainThread(already_AddRefed<image::Image>&& aImage,
|
||||||
|
const StaticMutexAutoLock& aAutoLock) {
|
||||||
|
RefPtr<image::Image> image = aImage;
|
||||||
|
if (!image) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool needsDispatch = mReleasingImagesOnMainThread.IsEmpty();
|
||||||
|
mReleasingImagesOnMainThread.AppendElement(image);
|
||||||
|
|
||||||
|
if (!needsDispatch) {
|
||||||
|
// There is already a ongoing task for ClearReleasingImages().
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_DispatchToMainThread(NS_NewRunnableFunction([]() -> void {
|
||||||
|
SurfaceCache::ClearReleasingImages();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TakeReleasingImages(nsTArray<RefPtr<image::Image>>& aImage,
|
||||||
|
const StaticMutexAutoLock& aAutoLock) {
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
aImage.SwapElements(mReleasingImagesOnMainThread);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
already_AddRefed<ImageSurfaceCache> GetImageCache(const ImageKey aImageKey)
|
already_AddRefed<ImageSurfaceCache> GetImageCache(const ImageKey aImageKey)
|
||||||
{
|
{
|
||||||
|
|
@ -943,6 +969,7 @@ private:
|
||||||
ImageSurfaceCache> mImageCaches;
|
ImageSurfaceCache> mImageCaches;
|
||||||
SurfaceTracker mExpirationTracker;
|
SurfaceTracker mExpirationTracker;
|
||||||
RefPtr<MemoryPressureObserver> mMemoryPressureObserver;
|
RefPtr<MemoryPressureObserver> mMemoryPressureObserver;
|
||||||
|
nsTArray<RefPtr<image::Image>> mReleasingImagesOnMainThread;
|
||||||
const uint32_t mDiscardFactor;
|
const uint32_t mDiscardFactor;
|
||||||
const Cost mMaxCost;
|
const Cost mMaxCost;
|
||||||
Cost mAvailableCost;
|
Cost mAvailableCost;
|
||||||
|
|
@ -1160,5 +1187,34 @@ SurfaceCache::MaximumCapacity()
|
||||||
return sInstance->MaximumCapacity();
|
return sInstance->MaximumCapacity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
void SurfaceCache::ReleaseImageOnMainThread(
|
||||||
|
already_AddRefed<image::Image> aImage, bool aAlwaysProxy) {
|
||||||
|
if (NS_IsMainThread() && !aAlwaysProxy) {
|
||||||
|
RefPtr<image::Image> image = std::move(aImage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
StaticMutexAutoLock lock(sInstanceMutex);
|
||||||
|
if (sInstance) {
|
||||||
|
sInstance->ReleaseImageOnMainThread(std::move(aImage), lock);
|
||||||
|
} else {
|
||||||
|
NS_ReleaseOnMainThread(std::move(aImage), /* aAlwaysProxy */ true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
void SurfaceCache::ClearReleasingImages() {
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
nsTArray<RefPtr<image::Image>> images;
|
||||||
|
{
|
||||||
|
StaticMutexAutoLock lock(sInstanceMutex);
|
||||||
|
if (sInstance) {
|
||||||
|
sInstance->TakeReleasingImages(images, lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace image
|
} // namespace image
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
||||||
|
|
@ -417,6 +417,18 @@ struct SurfaceCache
|
||||||
*/
|
*/
|
||||||
static size_t MaximumCapacity();
|
static size_t MaximumCapacity();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release image on main thread.
|
||||||
|
* The function uses SurfaceCache to release pending releasing images quickly.
|
||||||
|
*/
|
||||||
|
static void ReleaseImageOnMainThread(already_AddRefed<image::Image> aImage,
|
||||||
|
bool aAlwaysProxy = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear all pending releasing images.
|
||||||
|
*/
|
||||||
|
static void ClearReleasingImages();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual ~SurfaceCache() = 0; // Forbid instantiation.
|
virtual ~SurfaceCache() = 0; // Forbid instantiation.
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue