Bug 1951735 - Fix ImageContainer::ClearAllImages() r=gfx-reviewers,media-playback-reviewers,alwu,aosmond
The ClearAllImages() does not actually clear all images in WebRenderImageHost. Update the function as to have a capability to clear all images in WebRenderImageHost. And re-name it to ImageContainer::ClearImagesInHost(). Differential Revision: https://phabricator.services.mozilla.com/D240360
This commit is contained in:
@@ -39,7 +39,7 @@ void OffscreenCanvasDisplayHelper::DestroyElement() {
|
||||
|
||||
MutexAutoLock lock(mMutex);
|
||||
if (mImageContainer) {
|
||||
mImageContainer->ClearAllImages();
|
||||
mImageContainer->ClearImagesInHost(layers::ClearImagesType::All);
|
||||
mImageContainer = nullptr;
|
||||
}
|
||||
mFrontBufferSurface = nullptr;
|
||||
@@ -53,7 +53,7 @@ void OffscreenCanvasDisplayHelper::DestroyCanvas() {
|
||||
|
||||
MutexAutoLock lock(mMutex);
|
||||
if (mImageContainer) {
|
||||
mImageContainer->ClearAllImages();
|
||||
mImageContainer->ClearImagesInHost(layers::ClearImagesType::All);
|
||||
mImageContainer = nullptr;
|
||||
}
|
||||
mFrontBufferSurface = nullptr;
|
||||
@@ -309,7 +309,7 @@ bool OffscreenCanvasDisplayHelper::CommitFrameToCompositor(
|
||||
image, TimeStamp(), mLastFrameID++, mImageProducerID));
|
||||
mImageContainer->SetCurrentImages(imageList);
|
||||
} else {
|
||||
mImageContainer->ClearAllImages();
|
||||
mImageContainer->ClearImagesInHost(layers::ClearImagesType::All);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -144,7 +144,7 @@ void VideoFrameContainer::SetCurrentFramesLocked(
|
||||
}
|
||||
|
||||
if (aImages.IsEmpty()) {
|
||||
mImageContainer->ClearAllImages();
|
||||
mImageContainer->ClearImagesInHost(layers::ClearImagesType::All);
|
||||
} else {
|
||||
mImageContainer->SetCurrentImages(aImages);
|
||||
}
|
||||
@@ -196,6 +196,11 @@ void VideoFrameContainer::ClearCachedResources() {
|
||||
mImageContainer->ClearCachedResources();
|
||||
}
|
||||
|
||||
void VideoFrameContainer::ClearImagesInHost(layers::ClearImagesType aType) {
|
||||
MutexAutoLock lock(mMutex);
|
||||
mImageContainer->ClearImagesInHost(aType);
|
||||
}
|
||||
|
||||
ImageContainer* VideoFrameContainer::GetImageContainer() {
|
||||
// Note - you'll need the lock to manipulate this. The pointer is not
|
||||
// modified from multiple threads, just the data pointed to by it.
|
||||
|
||||
@@ -68,9 +68,12 @@ class VideoFrameContainer {
|
||||
// but was actually painted at t+n, this returns n in seconds. Threadsafe.
|
||||
double GetFrameDelay();
|
||||
|
||||
// Clear any resources that are not immediately necessary.
|
||||
// Clear any resources in client that are not immediately necessary.
|
||||
void ClearCachedResources();
|
||||
|
||||
// Clear images in host.
|
||||
void ClearImagesInHost(layers::ClearImagesType aType);
|
||||
|
||||
// Returns a new frame ID for SetCurrentFrames(). The client must either
|
||||
// call this on only one thread or provide barriers. Do not use together
|
||||
// with SetCurrentFrame().
|
||||
|
||||
@@ -709,7 +709,7 @@ void VideoSink::SetSecondaryVideoContainer(VideoFrameContainer* aSecondary) {
|
||||
if (mSecondaryContainer && aSecondary != mSecondaryContainer) {
|
||||
ImageContainer* secondaryImageContainer =
|
||||
mSecondaryContainer->GetImageContainer();
|
||||
secondaryImageContainer->ClearAllImages();
|
||||
secondaryImageContainer->ClearImagesInHost(layers::ClearImagesType::All);
|
||||
}
|
||||
mSecondaryContainer = aSecondary;
|
||||
if (!IsPlaying() && mSecondaryContainer) {
|
||||
|
||||
@@ -371,17 +371,22 @@ void ImageContainer::SetCurrentImages(const nsTArray<NonOwningImage>& aImages) {
|
||||
SetCurrentImageInternal(aImages);
|
||||
}
|
||||
|
||||
void ImageContainer::ClearAllImages() {
|
||||
void ImageContainer::ClearImagesInHost(ClearImagesType aType) {
|
||||
MOZ_ASSERT(mIsAsync);
|
||||
if (!mIsAsync) {
|
||||
return;
|
||||
}
|
||||
|
||||
mRecursiveMutex.Lock();
|
||||
if (mImageClient) {
|
||||
RefPtr<ImageClient> imageClient = mImageClient;
|
||||
mRecursiveMutex.Unlock();
|
||||
|
||||
// Let ImageClient release all TextureClients. This doesn't return
|
||||
// until ImageBridge has called ClearCurrentImageFromImageBridge.
|
||||
// Let ImageClient clear Images(TextureClients). This doesn't return
|
||||
// until ImageBridge has called ImageClient::ClearImagesInHost.
|
||||
if (RefPtr<ImageBridgeChild> imageBridge =
|
||||
ImageBridgeChild::GetSingleton()) {
|
||||
imageBridge->FlushAllImages(imageClient, this);
|
||||
imageBridge->ClearImagesInHost(imageClient, this, aType);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -293,6 +293,8 @@ class ImageContainerListener final {
|
||||
ImageContainer* mImageContainer MOZ_GUARDED_BY(mLock);
|
||||
};
|
||||
|
||||
enum class ClearImagesType { All, CacheOnly };
|
||||
|
||||
/**
|
||||
* A class that manages Images for an ImageLayer. The only reason
|
||||
* we need a separate class here is that ImageLayers aren't threadsafe
|
||||
@@ -397,11 +399,11 @@ class ImageContainer final : public SupportsThreadSafeWeakPtr<ImageContainer> {
|
||||
void SetCurrentImages(const nsTArray<NonOwningImage>& aImages);
|
||||
|
||||
/**
|
||||
* Clear all images. Let ImageClient release all TextureClients. Because we
|
||||
* may release the lock after acquiring it in this method, it cannot be called
|
||||
* with the lock held.
|
||||
* Clear images in host. It could be used only with async ImageContainer.
|
||||
* Because we may release the lock after acquiring it in this method, it
|
||||
* cannot be called with the lock held.
|
||||
*/
|
||||
void ClearAllImages() MOZ_EXCLUDES(mRecursiveMutex);
|
||||
void ClearImagesInHost(ClearImagesType aType) MOZ_EXCLUDES(mRecursiveMutex);
|
||||
|
||||
/**
|
||||
* Clear any resources that are not immediately necessary. This may be called
|
||||
|
||||
@@ -75,14 +75,8 @@ TextureInfo ImageClientSingle::GetTextureInfo() const {
|
||||
TextureFlags::DEFAULT);
|
||||
}
|
||||
|
||||
void ImageClientSingle::FlushAllImages() {
|
||||
for (auto& b : mBuffers) {
|
||||
// It should be safe to just assume a default render root here, even if
|
||||
// the texture actually presents in a content render root, as the only
|
||||
// risk would be if the content render root has not / is not going to
|
||||
// generate a frame before the texture gets cleared.
|
||||
RemoveTexture(b.mTextureClient);
|
||||
}
|
||||
void ImageClientSingle::ClearImagesInHost(ClearImagesType aType) {
|
||||
GetForwarder()->ClearImagesFromCompositable(this, aType);
|
||||
mBuffers.Clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -54,10 +54,10 @@ class ImageClient : public CompositableClient {
|
||||
virtual bool UpdateImage(ImageContainer* aContainer) = 0;
|
||||
|
||||
/**
|
||||
* asynchronously remove all the textures used by the image client.
|
||||
* asynchronously clear Images(textures) in host.
|
||||
*
|
||||
*/
|
||||
virtual void FlushAllImages() {}
|
||||
virtual void ClearImagesInHost(ClearImagesType aType) {}
|
||||
|
||||
virtual void RemoveTexture(TextureClient* aTexture) override;
|
||||
|
||||
@@ -98,7 +98,7 @@ class ImageClientSingle : public ImageClient {
|
||||
|
||||
TextureInfo GetTextureInfo() const override;
|
||||
|
||||
void FlushAllImages() override;
|
||||
void ClearImagesInHost(ClearImagesType aType) override;
|
||||
|
||||
ImageClientSingle* AsImageClientSingle() override { return this; }
|
||||
|
||||
|
||||
@@ -88,6 +88,8 @@ class CompositableHost {
|
||||
virtual void UseTextureHost(const nsTArray<TimedTexture>& aTextures);
|
||||
virtual void RemoveTextureHost(TextureHost* aTexture);
|
||||
|
||||
virtual void ClearImages(ClearImagesType aType) {}
|
||||
|
||||
const AsyncCompositableRef& GetAsyncRef() const { return mAsyncRef; }
|
||||
void SetAsyncRef(const AsyncCompositableRef& aRef) { mAsyncRef = aRef; }
|
||||
|
||||
|
||||
@@ -166,7 +166,6 @@ const ImageComposite::TimedImage* ImageComposite::ChooseImage() {
|
||||
void ImageComposite::RemoveImagesWithTextureHost(TextureHost* aTexture) {
|
||||
for (int32_t i = mImages.Length() - 1; i >= 0; --i) {
|
||||
if (mImages[i].mTextureHost == aTexture) {
|
||||
aTexture->UnbindTextureSource();
|
||||
mImages.RemoveElementAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#define MOZILLA_LAYERS_COMPOSITABLEFORWARDER
|
||||
|
||||
#include <stdint.h> // for int32_t, uint32_t, uint64_t
|
||||
|
||||
#include "ImageContainer.h"
|
||||
#include "mozilla/Assertions.h" // for AssertionConditionType, MOZ_ASSERT, MOZ_ASSERT_HELPER1
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/RefPtr.h" // for RefPtr
|
||||
@@ -22,7 +24,6 @@ namespace mozilla {
|
||||
namespace layers {
|
||||
class CompositableClient;
|
||||
class CompositableHandle;
|
||||
class ImageContainer;
|
||||
class PTextureChild;
|
||||
class SurfaceDescriptorTiles;
|
||||
class TextureClient;
|
||||
@@ -137,6 +138,13 @@ class CompositableForwarder : public KnowsCompositor {
|
||||
virtual void RemoveTextureFromCompositable(CompositableClient* aCompositable,
|
||||
TextureClient* aTexture) = 0;
|
||||
|
||||
/**
|
||||
* Tell the CompositableHost on the compositor side to clear Images
|
||||
* from the CompositableHost.
|
||||
*/
|
||||
virtual void ClearImagesFromCompositable(CompositableClient* aCompositable,
|
||||
ClearImagesType aType) {}
|
||||
|
||||
struct TimedTextureClient {
|
||||
TimedTextureClient()
|
||||
: mTextureClient(nullptr), mFrameID(0), mProducerID(0) {}
|
||||
|
||||
@@ -51,6 +51,12 @@ bool CompositableParentManager::ReceiveCompositableUpdate(
|
||||
aCompositable->RemoveTextureHost(tex);
|
||||
break;
|
||||
}
|
||||
case CompositableOperationDetail::TOpClearImages: {
|
||||
const OpClearImages& op = aDetail.get_OpClearImages();
|
||||
|
||||
aCompositable->ClearImages(op.type());
|
||||
break;
|
||||
}
|
||||
case CompositableOperationDetail::TOpUseTexture: {
|
||||
const OpUseTexture& op = aDetail.get_OpUseTexture();
|
||||
|
||||
|
||||
@@ -357,9 +357,10 @@ void ImageBridgeChild::UpdateCompositable(
|
||||
EndTransaction();
|
||||
}
|
||||
|
||||
void ImageBridgeChild::FlushAllImagesSync(SynchronousTask* aTask,
|
||||
ImageClient* aClient,
|
||||
ImageContainer* aContainer) {
|
||||
void ImageBridgeChild::ClearImagesInHostSync(SynchronousTask* aTask,
|
||||
ImageClient* aClient,
|
||||
ImageContainer* aContainer,
|
||||
ClearImagesType aType) {
|
||||
AutoCompleteTask complete(aTask);
|
||||
|
||||
if (!CanSend()) {
|
||||
@@ -371,27 +372,29 @@ void ImageBridgeChild::FlushAllImagesSync(SynchronousTask* aTask,
|
||||
if (aContainer) {
|
||||
aContainer->ClearImagesFromImageBridge();
|
||||
}
|
||||
aClient->FlushAllImages();
|
||||
aClient->ClearImagesInHost(aType);
|
||||
EndTransaction();
|
||||
}
|
||||
|
||||
void ImageBridgeChild::FlushAllImages(ImageClient* aClient,
|
||||
ImageContainer* aContainer) {
|
||||
void ImageBridgeChild::ClearImagesInHost(ImageClient* aClient,
|
||||
ImageContainer* aContainer,
|
||||
ClearImagesType aType) {
|
||||
MOZ_ASSERT(aClient);
|
||||
MOZ_ASSERT(!InImageBridgeChildThread());
|
||||
|
||||
if (InImageBridgeChildThread()) {
|
||||
NS_ERROR(
|
||||
"ImageBridgeChild::FlushAllImages() is called on ImageBridge thread.");
|
||||
"ImageBridgeChild::ClearImagesInHost() is called on ImageBridge "
|
||||
"thread.");
|
||||
return;
|
||||
}
|
||||
|
||||
SynchronousTask task("FlushAllImages Lock");
|
||||
SynchronousTask task("ClearImagesInHost Lock");
|
||||
|
||||
// RefPtrs on arguments are not needed since this dispatches synchronously.
|
||||
RefPtr<Runnable> runnable = WrapRunnable(
|
||||
RefPtr<ImageBridgeChild>(this), &ImageBridgeChild::FlushAllImagesSync,
|
||||
&task, aClient, aContainer);
|
||||
RefPtr<ImageBridgeChild>(this), &ImageBridgeChild::ClearImagesInHostSync,
|
||||
&task, aClient, aContainer, aType);
|
||||
GetThread()->Dispatch(runnable.forget());
|
||||
|
||||
task.Wait();
|
||||
@@ -905,6 +908,18 @@ void ImageBridgeChild::RemoveTextureFromCompositable(
|
||||
OpRemoveTexture(WrapNotNull(aTexture->GetIPDLActor()))));
|
||||
}
|
||||
|
||||
void ImageBridgeChild::ClearImagesFromCompositable(
|
||||
CompositableClient* aCompositable, ClearImagesType aType) {
|
||||
MOZ_ASSERT(CanSend());
|
||||
MOZ_ASSERT(aCompositable->IsConnected());
|
||||
if (!aCompositable->IsConnected()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mTxn->AddNoSwapEdit(CompositableOperation(aCompositable->GetIPCHandle(),
|
||||
OpClearImages(aType)));
|
||||
}
|
||||
|
||||
bool ImageBridgeChild::IsSameProcess() const {
|
||||
return OtherPid() == base::GetCurrentProcId();
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <stdint.h> // for uint32_t, uint64_t
|
||||
#include <unordered_map>
|
||||
|
||||
#include "ImageContainer.h"
|
||||
#include "mozilla/Attributes.h" // for override
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/RefPtr.h" // for already_AddRefed
|
||||
@@ -206,9 +207,10 @@ class ImageBridgeChild final : public PImageBridgeChild,
|
||||
const RefPtr<FwdTransactionTracker> aTracker);
|
||||
|
||||
/**
|
||||
* Flush all Images sent to CompositableHost.
|
||||
* Clear Images in host.
|
||||
*/
|
||||
void FlushAllImages(ImageClient* aClient, ImageContainer* aContainer);
|
||||
void ClearImagesInHost(ImageClient* aClient, ImageContainer* aContainer,
|
||||
ClearImagesType aType);
|
||||
|
||||
bool IPCOpen() const override { return mCanSend; }
|
||||
|
||||
@@ -225,8 +227,8 @@ class ImageBridgeChild final : public PImageBridgeChild,
|
||||
CompositableType aType,
|
||||
ImageContainer* aImageContainer);
|
||||
|
||||
void FlushAllImagesSync(SynchronousTask* aTask, ImageClient* aClient,
|
||||
ImageContainer* aContainer);
|
||||
void ClearImagesInHostSync(SynchronousTask* aTask, ImageClient* aClient,
|
||||
ImageContainer* aContainer, ClearImagesType aType);
|
||||
|
||||
void ProxyAllocShmemNow(SynchronousTask* aTask, size_t aSize,
|
||||
mozilla::ipc::Shmem* aShmem, bool aUnsafe,
|
||||
@@ -282,6 +284,9 @@ class ImageBridgeChild final : public PImageBridgeChild,
|
||||
void RemoveTextureFromCompositable(CompositableClient* aCompositable,
|
||||
TextureClient* aTexture) override;
|
||||
|
||||
void ClearImagesFromCompositable(CompositableClient* aCompositable,
|
||||
ClearImagesType aType) override;
|
||||
|
||||
// ISurfaceAllocator
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "FrameMetrics.h"
|
||||
#include "VsyncSource.h"
|
||||
#include "chrome/common/ipc_message_utils.h"
|
||||
#include "ImageContainer.h"
|
||||
#include "ipc/EnumSerializer.h"
|
||||
#include "ipc/IPCMessageUtils.h"
|
||||
#include "mozilla/ScrollSnapInfo.h"
|
||||
@@ -1130,6 +1131,13 @@ struct ParamTraits<mozilla::layers::CompositionPayload> {
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::layers::ClearImagesType>
|
||||
: public ContiguousEnumSerializerInclusive<
|
||||
mozilla::layers::ClearImagesType,
|
||||
mozilla::layers::ClearImagesType::All,
|
||||
mozilla::layers::ClearImagesType::CacheOnly> {};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::layers::CantZoomOutBehavior>
|
||||
: public ContiguousEnumSerializerInclusive<
|
||||
|
||||
@@ -49,6 +49,7 @@ using mozilla::ParentLayerRect from "Units.h";
|
||||
using mozilla::LayoutDeviceIntRect from "Units.h";
|
||||
using mozilla::LayoutDevicePoint from "Units.h";
|
||||
using mozilla::LayoutDeviceRect from "Units.h";
|
||||
using mozilla::layers::ClearImagesType from "ImageContainer.h";
|
||||
using mozilla::layers::ScaleMode from "mozilla/layers/LayersTypes.h";
|
||||
using mozilla::layers::EventRegionsOverride from "mozilla/layers/LayersTypes.h";
|
||||
using mozilla::layers::DiagnosticTypes from "mozilla/layers/CompositorTypes.h";
|
||||
@@ -278,6 +279,13 @@ struct OpRemoveTexture {
|
||||
PTexture texture;
|
||||
};
|
||||
|
||||
/**
|
||||
* Tells the CompositableHost to clear Images
|
||||
*/
|
||||
struct OpClearImages {
|
||||
ClearImagesType type;
|
||||
};
|
||||
|
||||
struct TimedTexture {
|
||||
PTexture texture;
|
||||
TimeStamp timeStamp;
|
||||
@@ -322,6 +330,8 @@ struct OpNotifyNotUsed {
|
||||
union CompositableOperationDetail {
|
||||
OpRemoveTexture;
|
||||
|
||||
OpClearImages;
|
||||
|
||||
OpUseTexture;
|
||||
|
||||
OpUseRemoteTexture;
|
||||
|
||||
@@ -252,15 +252,34 @@ void WebRenderImageHost::UseRemoteTexture() {
|
||||
}
|
||||
|
||||
void WebRenderImageHost::CleanupResources() {
|
||||
ClearImages();
|
||||
ImageComposite::ClearImages();
|
||||
SetCurrentTextureHost(nullptr);
|
||||
}
|
||||
|
||||
void WebRenderImageHost::RemoveTextureHost(TextureHost* aTexture) {
|
||||
CompositableHost::RemoveTextureHost(aTexture);
|
||||
RemoveImagesWithTextureHost(aTexture);
|
||||
}
|
||||
|
||||
void WebRenderImageHost::ClearImages(ClearImagesType aType) {
|
||||
ImageComposite::ClearImages();
|
||||
if (aType == ClearImagesType::All) {
|
||||
if (!mPendingRemoteTextureWrappers.empty()) {
|
||||
mPendingRemoteTextureWrappers.clear();
|
||||
}
|
||||
SetCurrentTextureHost(nullptr);
|
||||
|
||||
if (GetAsyncRef()) {
|
||||
for (const auto& it : mWrBridges) {
|
||||
RefPtr<WebRenderBridgeParent> wrBridge = it.second->WrBridge();
|
||||
if (wrBridge && wrBridge->CompositorScheduler()) {
|
||||
wrBridge->CompositorScheduler()->ScheduleComposition(
|
||||
wr::RenderReasons::ASYNC_IMAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TimeStamp WebRenderImageHost::GetCompositionTime() const {
|
||||
TimeStamp time;
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ class WebRenderImageHost : public CompositableHost, public ImageComposite {
|
||||
void UseTextureHost(const nsTArray<TimedTexture>& aTextures) override;
|
||||
void RemoveTextureHost(TextureHost* aTexture) override;
|
||||
|
||||
void ClearImages(ClearImagesType aType) override;
|
||||
|
||||
void Dump(std::stringstream& aStream, const char* aPrefix = "",
|
||||
bool aDumpHtml = false) override;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user