diff --git a/gfx/layers/client/ImageClient.cpp b/gfx/layers/client/ImageClient.cpp index 6460bd35ec60..83978012e157 100644 --- a/gfx/layers/client/ImageClient.cpp +++ b/gfx/layers/client/ImageClient.cpp @@ -260,6 +260,15 @@ ImageClientSingle::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlag return true; } +RefPtr +ImageClientSingle::GetForwardedTexture() +{ + if (mBuffers.Length() == 0) { + return nullptr; + } + return mBuffers[0].mTextureClient; +} + bool ImageClientSingle::AddTextureClient(TextureClient* aTexture) { diff --git a/gfx/layers/client/ImageClient.h b/gfx/layers/client/ImageClient.h index 65f5eb55c320..65052f3ed15a 100644 --- a/gfx/layers/client/ImageClient.h +++ b/gfx/layers/client/ImageClient.h @@ -73,6 +73,8 @@ public: uint32_t GetLastUpdateGenerationCounter() { return mLastUpdateGenerationCounter; } + virtual RefPtr GetForwardedTexture() { return nullptr; } + protected: ImageClient(CompositableForwarder* aFwd, TextureFlags aFlags, CompositableType aType); @@ -104,6 +106,8 @@ public: ImageClientSingle* AsImageClientSingle() override { return this; } + virtual RefPtr GetForwardedTexture() override; + bool IsEmpty() { return mBuffers.IsEmpty(); } protected: diff --git a/gfx/layers/client/TextureClient.h b/gfx/layers/client/TextureClient.h index 5c6f6e3d46ef..321b1c65e1d8 100644 --- a/gfx/layers/client/TextureClient.h +++ b/gfx/layers/client/TextureClient.h @@ -653,6 +653,8 @@ public: // must only be called from the PaintThread. void DropPaintThreadRef(); + wr::MaybeExternalImageId GetExternalImageKey() { return mExternalImageId; } + private: static void TextureClientRecycleCallback(TextureClient* aClient, void* aClosure); diff --git a/gfx/layers/ipc/WebRenderMessages.ipdlh b/gfx/layers/ipc/WebRenderMessages.ipdlh index a374f564c554..daaf09f7522a 100644 --- a/gfx/layers/ipc/WebRenderMessages.ipdlh +++ b/gfx/layers/ipc/WebRenderMessages.ipdlh @@ -51,6 +51,12 @@ struct OpAddExternalImage { ImageKey key; }; +struct OpAddExternalImageForTexture { + ExternalImageId externalImageId; + ImageKey key; + PTexture texture; +}; + struct OpAddCompositorAnimations { CompositorAnimations data; }; @@ -65,15 +71,14 @@ struct OpRemovePipelineIdForCompositable { PipelineId pipelineId; }; -struct OpAddExternalImageIdForCompositable { - ExternalImageId externalImageId; - CompositableHandle handle; -}; - struct OpRemoveExternalImageId { ExternalImageId externalImageId; }; +struct OpReleaseTextureOfImage { + ImageKey key; +}; + struct OpUpdateAsyncImagePipeline { PipelineId pipelineId; LayoutDeviceRect scBounds; @@ -86,8 +91,8 @@ struct OpUpdateAsyncImagePipeline { union WebRenderParentCommand { OpAddPipelineIdForCompositable; OpRemovePipelineIdForCompositable; - OpAddExternalImageIdForCompositable; OpRemoveExternalImageId; + OpReleaseTextureOfImage; OpUpdateAsyncImagePipeline; CompositableOperation; OpAddCompositorAnimations; @@ -171,6 +176,7 @@ union OpUpdateResource { OpAddFontInstance; OpDeleteFontInstance; OpAddExternalImage; + OpAddExternalImageForTexture; }; } // namespace diff --git a/gfx/layers/wr/IpcResourceUpdateQueue.cpp b/gfx/layers/wr/IpcResourceUpdateQueue.cpp index 9ce848d87016..67ee49b0ecab 100644 --- a/gfx/layers/wr/IpcResourceUpdateQueue.cpp +++ b/gfx/layers/wr/IpcResourceUpdateQueue.cpp @@ -9,6 +9,7 @@ #include #include "mozilla/Maybe.h" #include "mozilla/ipc/SharedMemory.h" +#include "mozilla/layers/PTextureChild.h" #include "mozilla/layers/WebRenderBridgeChild.h" namespace mozilla { @@ -279,6 +280,17 @@ IpcResourceUpdateQueue::AddExternalImage(wr::ExternalImageId aExtId, wr::ImageKe mUpdates.AppendElement(layers::OpAddExternalImage(aExtId, aKey)); } +void +IpcResourceUpdateQueue::AddExternalImageForTexture(wr::ExternalImageId aExtId, + wr::ImageKey aKey, + layers::TextureClient* aTexture) +{ + MOZ_ASSERT(aTexture); + MOZ_ASSERT(aTexture->GetIPDLActor()); + MOZ_RELEASE_ASSERT(aTexture->GetIPDLActor()->GetIPCChannel() == mWriter.WrBridge()->GetIPCChannel()); + mUpdates.AppendElement(layers::OpAddExternalImageForTexture(aExtId, aKey, nullptr, aTexture->GetIPDLActor())); +} + bool IpcResourceUpdateQueue::UpdateImageBuffer(ImageKey aKey, const ImageDescriptor& aDescriptor, diff --git a/gfx/layers/wr/IpcResourceUpdateQueue.h b/gfx/layers/wr/IpcResourceUpdateQueue.h index e03e4c3b4b6d..751dc415ca25 100644 --- a/gfx/layers/wr/IpcResourceUpdateQueue.h +++ b/gfx/layers/wr/IpcResourceUpdateQueue.h @@ -37,6 +37,8 @@ public: void Clear(); bool IsEmpty() const; + layers::WebRenderBridgeChild* WrBridge() const { return mShmAllocator; } + protected: bool AllocChunk(); layers::OffsetRange AllocLargeChunk(size_t aSize); @@ -83,6 +85,10 @@ public: void AddExternalImage(wr::ExternalImageId aExtId, wr::ImageKey aKey); + void AddExternalImageForTexture(wr::ExternalImageId aExtId, + wr::ImageKey aKey, + layers::TextureClient* aTexture); + bool UpdateImageBuffer(wr::ImageKey aKey, const ImageDescriptor& aDescriptor, Range aBytes); diff --git a/gfx/layers/wr/WebRenderBridgeChild.cpp b/gfx/layers/wr/WebRenderBridgeChild.cpp index ed29556e6318..d3a0837ce989 100644 --- a/gfx/layers/wr/WebRenderBridgeChild.cpp +++ b/gfx/layers/wr/WebRenderBridgeChild.cpp @@ -221,15 +221,6 @@ WebRenderBridgeChild::GetNextExternalImageId() return id.value(); } -wr::ExternalImageId -WebRenderBridgeChild::AllocExternalImageIdForCompositable(CompositableClient* aCompositable) -{ - wr::ExternalImageId imageId = GetNextExternalImageId(); - AddWebRenderParentCommand( - OpAddExternalImageIdForCompositable(imageId, aCompositable->GetIPCHandle())); - return imageId; -} - void WebRenderBridgeChild::DeallocExternalImageId(const wr::ExternalImageId& aImageId) { @@ -237,6 +228,13 @@ WebRenderBridgeChild::DeallocExternalImageId(const wr::ExternalImageId& aImageId OpRemoveExternalImageId(aImageId)); } +void +WebRenderBridgeChild::ReleaseTextureOfImage(const wr::ImageKey& aKey) +{ + AddWebRenderParentCommand( + OpReleaseTextureOfImage(aKey)); +} + struct FontFileDataSink { wr::FontKey* mFontKey; diff --git a/gfx/layers/wr/WebRenderBridgeChild.h b/gfx/layers/wr/WebRenderBridgeChild.h index 4346ca66d264..4d31e4a5c530 100644 --- a/gfx/layers/wr/WebRenderBridgeChild.h +++ b/gfx/layers/wr/WebRenderBridgeChild.h @@ -100,9 +100,12 @@ public: const CompositableHandle& aHandlee); void RemovePipelineIdForCompositable(const wr::PipelineId& aPipelineId); - wr::ExternalImageId AllocExternalImageIdForCompositable(CompositableClient* aCompositable); void DeallocExternalImageId(const wr::ExternalImageId& aImageId); + /// Release TextureClient that is bounded to ImageKey. + /// It is used for recycling TextureClient. + void ReleaseTextureOfImage(const wr::ImageKey& aKey); + /** * Clean this up, finishing with SendShutDown() which will cause __delete__ * to be sent from the parent side. diff --git a/gfx/layers/wr/WebRenderBridgeParent.cpp b/gfx/layers/wr/WebRenderBridgeParent.cpp index 4f85f5039ed2..ea3cbfe56ed1 100644 --- a/gfx/layers/wr/WebRenderBridgeParent.cpp +++ b/gfx/layers/wr/WebRenderBridgeParent.cpp @@ -344,6 +344,15 @@ WebRenderBridgeParent::UpdateResources(const nsTArray& aResour } break; } + case OpUpdateResource::TOpAddExternalImageForTexture: { + const auto& op = cmd.get_OpAddExternalImageForTexture(); + CompositableTextureHostRef texture; + texture = TextureHost::AsTextureHost(op.textureParent()); + if (!AddExternalImageForTexture(op.externalImageId(), op.key(), texture, aUpdates)) { + return false; + } + break; + } case OpUpdateResource::TOpAddRawFont: { const auto& op = cmd.get_OpAddRawFont(); wr::Vec bytes; @@ -426,29 +435,54 @@ WebRenderBridgeParent::AddExternalImage(wr::ExternalImageId aExtId, wr::ImageKey return true; } } else { - MOZ_ASSERT(mExternalImageIds.Get(wr::AsUint64(aExtId)).get()); - - RefPtr host = mExternalImageIds.Get(wr::AsUint64(aExtId)); - if (!host) { - gfxCriticalNote << "CompositableHost does not exist for extId:" << wr::AsUint64(aExtId); - return false; - } - if (!gfxEnv::EnableWebRenderRecording()) { - TextureHost* texture = host->GetAsTextureHostForComposite(); - if (!texture) { - gfxCriticalNote << "TextureHost does not exist for extId:" << wr::AsUint64(aExtId); - return false; - } - WebRenderTextureHost* wrTexture = texture->AsWebRenderTextureHost(); - if (wrTexture) { - wrTexture->PushResourceUpdates(aResources, TextureHost::ADD_IMAGE, keys, - wrTexture->GetExternalImageKey()); - return true; - } - } - dSurf = host->GetAsSurface(); + gfxCriticalNote << "DataSourceSurface of SharedSurfaces does not exist for extId:" << wr::AsUint64(aExtId); + return false; } + DataSourceSurface::MappedSurface map; + if (!dSurf->Map(gfx::DataSourceSurface::MapType::READ, &map)) { + gfxCriticalNote << "DataSourceSurface failed to map for Image for extId:" << wr::AsUint64(aExtId); + return false; + } + + IntSize size = dSurf->GetSize(); + wr::ImageDescriptor descriptor(size, map.mStride, dSurf->GetFormat()); + wr::Vec data; + data.PushBytes(Range(map.mData, size.height * map.mStride)); + aResources.AddImage(keys[0], descriptor, data); + dSurf->Unmap(); + + return true; +} + +bool +WebRenderBridgeParent::AddExternalImageForTexture(wr::ExternalImageId aExtId, + wr::ImageKey aKey, + TextureHost* aTexture, + wr::TransactionBuilder& aResources) +{ + Range keys(&aKey, 1); + // Check if key is obsoleted. + if (keys[0].mNamespace != mIdNamespace) { + return true; + } + + if(!aTexture) { + gfxCriticalNote << "TextureHost does not exist for extId:" << wr::AsUint64(aExtId); + return false; + } + + if (!gfxEnv::EnableWebRenderRecording()) { + WebRenderTextureHost* wrTexture = aTexture->AsWebRenderTextureHost(); + if (wrTexture) { + wrTexture->PushResourceUpdates(aResources, TextureHost::ADD_IMAGE, keys, + wrTexture->GetExternalImageKey()); + MOZ_ASSERT(!mTextureHosts.Get(wr::AsUint64(aKey), nullptr)); + mTextureHosts.Put(wr::AsUint64(aKey), CompositableTextureHostRef(aTexture)); + return true; + } + } + RefPtr dSurf = aTexture->GetAsSurface(); if (!dSurf) { gfxCriticalNote << "TextureHost does not return DataSourceSurface for extId:" << wr::AsUint64(aExtId); return false; @@ -847,17 +881,16 @@ WebRenderBridgeParent::ProcessWebRenderParentCommands(const InfallibleTArrayUpdateAsyncImagePipeline(op.pipelineId(), @@ -1064,33 +1097,6 @@ WebRenderBridgeParent::RemovePipelineIdForCompositable(const wr::PipelineId& aPi return; } -void -WebRenderBridgeParent::AddExternalImageIdForCompositable(const ExternalImageId& aImageId, - const CompositableHandle& aHandle) -{ - if (mDestroyed) { - return; - } - MOZ_ASSERT(!mExternalImageIds.Get(wr::AsUint64(aImageId)).get()); - - RefPtr host = FindCompositable(aHandle); - WebRenderImageHost* wrHost = host->AsWebRenderImageHost(); - - MOZ_ASSERT(wrHost); - if (!wrHost) { - gfxCriticalNote << "Incompatible CompositableHost for external image at WebRenderBridgeParent."; - } - - if (!wrHost) { - return; - } - - wrHost->SetWrBridge(this); - mExternalImageIds.Put(wr::AsUint64(aImageId), wrHost); - - return; -} - void WebRenderBridgeParent::RemoveExternalImageId(const ExternalImageId& aImageId) { @@ -1101,18 +1107,27 @@ WebRenderBridgeParent::RemoveExternalImageId(const ExternalImageId& aImageId) uint64_t imageId = wr::AsUint64(aImageId); if (mSharedSurfaceIds.EnsureRemoved(imageId)) { mAsyncImageManager->HoldExternalImage(mPipelineId, mWrEpoch, aImageId); + } +} + +void +WebRenderBridgeParent::ReleaseTextureOfImage(const wr::ImageKey& aKey) +{ + if (mDestroyed) { return; } - WebRenderImageHost* wrHost = mExternalImageIds.Get(imageId).get(); - if (!wrHost) { - return; + uint64_t id = wr::AsUint64(aKey); + CompositableTextureHostRef texture; + WebRenderTextureHost* wrTexture = nullptr; + + if (mTextureHosts.Get(id, &texture)) { + wrTexture = texture->AsWebRenderTextureHost(); } - - wrHost->ClearWrBridge(); - mExternalImageIds.Remove(imageId); - - return; + if (wrTexture) { + mAsyncImageManager->HoldExternalImage(mPipelineId, mWrEpoch, wrTexture); + } + mTextureHosts.Remove(id); } mozilla::ipc::IPCResult @@ -1639,10 +1654,14 @@ WebRenderBridgeParent::ClearResources() // Schedule generate frame to clean up Pipeline ScheduleGenerateFrame(); // WrFontKeys and WrImageKeys are deleted during WebRenderAPI destruction. - for (auto iter = mExternalImageIds.Iter(); !iter.Done(); iter.Next()) { - iter.Data()->ClearWrBridge(); + for (auto iter = mTextureHosts.Iter(); !iter.Done(); iter.Next()) { + WebRenderTextureHost* wrTexture = iter.Data()->AsWebRenderTextureHost(); + MOZ_ASSERT(wrTexture); + if (wrTexture) { + mAsyncImageManager->HoldExternalImage(mPipelineId, wrEpoch, wrTexture); + } } - mExternalImageIds.Clear(); + mTextureHosts.Clear(); for (auto iter = mAsyncCompositables.Iter(); !iter.Done(); iter.Next()) { wr::PipelineId pipelineId = wr::AsPipelineId(iter.Key()); RefPtr host = iter.Data(); diff --git a/gfx/layers/wr/WebRenderBridgeParent.h b/gfx/layers/wr/WebRenderBridgeParent.h index 784f5b013a79..152ab2bbdf2b 100644 --- a/gfx/layers/wr/WebRenderBridgeParent.h +++ b/gfx/layers/wr/WebRenderBridgeParent.h @@ -209,15 +209,19 @@ private: bool AddExternalImage(wr::ExternalImageId aExtId, wr::ImageKey aKey, wr::TransactionBuilder& aResources); + bool AddExternalImageForTexture(wr::ExternalImageId aExtId, + wr::ImageKey aKey, + TextureHost* aTexture, + wr::TransactionBuilder& aResources); + void AddPipelineIdForCompositable(const wr::PipelineId& aPipelineIds, const CompositableHandle& aHandle, const bool& aAsync); void RemovePipelineIdForCompositable(const wr::PipelineId& aPipelineId, wr::TransactionBuilder& aTxn); - void AddExternalImageIdForCompositable(const ExternalImageId& aImageId, - const CompositableHandle& aHandle); void RemoveExternalImageId(const ExternalImageId& aImageId); + void ReleaseTextureOfImage(const wr::ImageKey& aKey); LayersId GetLayersId() const; void ProcessWebRenderParentCommands(const InfallibleTArray& aCommands, @@ -291,7 +295,7 @@ private: // destroyed abnormally and Tab move between different windows. std::unordered_set mActiveAnimations; nsDataHashtable> mAsyncCompositables; - nsDataHashtable> mExternalImageIds; + nsDataHashtable mTextureHosts; nsTHashtable mSharedSurfaceIds; TimeDuration mVsyncRate; diff --git a/gfx/layers/wr/WebRenderImageHost.cpp b/gfx/layers/wr/WebRenderImageHost.cpp index a89103deb2bf..471a89cce77a 100644 --- a/gfx/layers/wr/WebRenderImageHost.cpp +++ b/gfx/layers/wr/WebRenderImageHost.cpp @@ -196,20 +196,6 @@ WebRenderImageHost::SetCurrentTextureHost(TextureHost* aTexture) return; } - if (mWrBridge && - !mUseAsyncImagePipeline && - !!mCurrentTextureHost && - mCurrentTextureHost != aTexture && - mCurrentTextureHost->AsWebRenderTextureHost()) { - MOZ_ASSERT(mWrBridge->AsyncImageManager()); - wr::PipelineId piplineId = mWrBridge->PipelineId(); - wr::Epoch epoch = mWrBridge->WrEpoch(); - mWrBridge->AsyncImageManager()->HoldExternalImage( - piplineId, - epoch, - mCurrentTextureHost->AsWebRenderTextureHost()); - } - mCurrentTextureHost = aTexture; } diff --git a/gfx/layers/wr/WebRenderUserData.cpp b/gfx/layers/wr/WebRenderUserData.cpp index cafca3521d6b..9b6d9714a301 100644 --- a/gfx/layers/wr/WebRenderUserData.cpp +++ b/gfx/layers/wr/WebRenderUserData.cpp @@ -78,10 +78,6 @@ WebRenderImageData::~WebRenderImageData() { ClearImageKey(); - if (mExternalImageId) { - WrBridge()->DeallocExternalImageId(mExternalImageId.ref()); - } - if (mPipelineId) { WrBridge()->RemovePipelineIdForCompositable(mPipelineId.ref()); } @@ -95,10 +91,15 @@ WebRenderImageData::ClearImageKey() // key when appropriate. if (mOwnsKey) { mWRManager->AddImageKeyForDiscard(mKey.value()); + if (mTextureOfImage) { + WrBridge()->ReleaseTextureOfImage(mKey.value()); + mTextureOfImage = nullptr; + } } mKey.reset(); } mOwnsKey = false; + MOZ_ASSERT(!mTextureOfImage); } Maybe @@ -132,9 +133,7 @@ WebRenderImageData::UpdateImageKey(ImageContainer* aContainer, } CreateImageClientIfNeeded(); - CreateExternalImageIfNeeded(); - - if (!mImageClient || !mExternalImageId) { + if (!mImageClient) { return Nothing(); } @@ -144,7 +143,8 @@ WebRenderImageData::UpdateImageKey(ImageContainer* aContainer, uint32_t oldCounter = imageClient->GetLastUpdateGenerationCounter(); bool ret = imageClient->UpdateImage(aContainer, /* unused */0); - if (!ret || imageClient->IsEmpty()) { + RefPtr currentTexture = imageClient->GetForwardedTexture(); + if (!ret || !currentTexture) { // Delete old key ClearImageKey(); return Nothing(); @@ -159,8 +159,13 @@ WebRenderImageData::UpdateImageKey(ImageContainer* aContainer, // TODO(nical): noooo... we need to reuse image keys. ClearImageKey(); + wr::MaybeExternalImageId extId = currentTexture->GetExternalImageKey(); + MOZ_RELEASE_ASSERT(extId.isSome()); + MOZ_ASSERT(!mTextureOfImage); + key = WrBridge()->GetNextImageKey(); - aResources.AddExternalImage(mExternalImageId.value(), key); + aResources.AddExternalImageForTexture(extId.ref(), key, currentTexture); + mTextureOfImage = currentTexture; mKey = Some(key); mOwnsKey = true; @@ -212,7 +217,6 @@ WebRenderImageData::CreateAsyncImageWebRenderCommands(mozilla::wr::DisplayListBu mContainer = aContainer; } MOZ_ASSERT(!mImageClient); - MOZ_ASSERT(!mExternalImageId); // Push IFrame for async image pipeline. // @@ -248,14 +252,6 @@ WebRenderImageData::CreateImageClientIfNeeded() } } -void -WebRenderImageData::CreateExternalImageIfNeeded() -{ - if (!mExternalImageId) { - mExternalImageId = Some(WrBridge()->AllocExternalImageIdForCompositable(mImageClient)); - } -} - WebRenderFallbackData::WebRenderFallbackData(WebRenderLayerManager* aWRManager, nsDisplayItem* aItem) : WebRenderImageData(aWRManager, aItem) , mInvalid(false) diff --git a/gfx/layers/wr/WebRenderUserData.h b/gfx/layers/wr/WebRenderUserData.h index b69098370e13..709e55b08eb9 100644 --- a/gfx/layers/wr/WebRenderUserData.h +++ b/gfx/layers/wr/WebRenderUserData.h @@ -151,9 +151,8 @@ public: protected: void ClearImageKey(); - void CreateExternalImageIfNeeded(); - wr::MaybeExternalImageId mExternalImageId; + RefPtr mTextureOfImage; Maybe mKey; RefPtr mImageClient; Maybe mPipelineId;