diff options
Diffstat (limited to 'gfx/layers/wr/RenderRootStateManager.cpp')
-rw-r--r-- | gfx/layers/wr/RenderRootStateManager.cpp | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/gfx/layers/wr/RenderRootStateManager.cpp b/gfx/layers/wr/RenderRootStateManager.cpp new file mode 100644 index 0000000000..8ddaa601a9 --- /dev/null +++ b/gfx/layers/wr/RenderRootStateManager.cpp @@ -0,0 +1,210 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/layers/RenderRootStateManager.h" + +#include "mozilla/layers/WebRenderBridgeChild.h" +#include "mozilla/layers/WebRenderLayerManager.h" + +namespace mozilla { +namespace layers { + +// RenderRootStateManager shares its ref count with the WebRenderLayerManager +// that created it. You can think of the two classes as being one unit, except +// there are multiple RenderRootStateManagers per WebRenderLayerManager. Since +// we need to reference the WebRenderLayerManager and it needs to reference us, +// this avoids us needing to involve the cycle collector. +void RenderRootStateManager::AddRef() { mLayerManager->AddRef(); } + +void RenderRootStateManager::Release() { mLayerManager->Release(); } + +WebRenderBridgeChild* RenderRootStateManager::WrBridge() const { + return mLayerManager->WrBridge(); +} + +WebRenderCommandBuilder& RenderRootStateManager::CommandBuilder() { + return mLayerManager->CommandBuilder(); +} + +RenderRootStateManager::WebRenderUserDataRefTable* +RenderRootStateManager::GetWebRenderUserDataTable() { + return mLayerManager->GetWebRenderUserDataTable(); +} + +wr::IpcResourceUpdateQueue& RenderRootStateManager::AsyncResourceUpdates() { + MOZ_ASSERT(NS_IsMainThread()); + + if (!mAsyncResourceUpdates) { + mAsyncResourceUpdates.emplace(WrBridge()); + + RefPtr<Runnable> task = NewRunnableMethod( + "RenderRootStateManager::FlushAsyncResourceUpdates", this, + &RenderRootStateManager::FlushAsyncResourceUpdates); + NS_DispatchToMainThread(task.forget()); + } + + return mAsyncResourceUpdates.ref(); +} + +void RenderRootStateManager::Destroy() { + ClearAsyncAnimations(); + + if (WrBridge()) { + // Just clear ImageKeys, they are deleted during WebRenderAPI destruction. + DiscardLocalImages(); + // CompositorAnimations are cleared by WebRenderBridgeParent. + mDiscardedCompositorAnimationsIds.Clear(); + } + + mActiveCompositorAnimationIds.clear(); + + mDestroyed = true; +} + +void RenderRootStateManager::FlushAsyncResourceUpdates() { + MOZ_ASSERT(NS_IsMainThread()); + + if (!mAsyncResourceUpdates) { + return; + } + + if (!IsDestroyed() && WrBridge()) { + WrBridge()->UpdateResources(mAsyncResourceUpdates.ref()); + } + + mAsyncResourceUpdates.reset(); +} + +void RenderRootStateManager::AddImageKeyForDiscard(wr::ImageKey key) { + mImageKeysToDelete.AppendElement(key); +} + +void RenderRootStateManager::AddBlobImageKeyForDiscard(wr::BlobImageKey key) { + mBlobImageKeysToDelete.AppendElement(key); +} + +void RenderRootStateManager::DiscardImagesInTransaction( + wr::IpcResourceUpdateQueue& aResources) { + for (const auto& key : mImageKeysToDelete) { + aResources.DeleteImage(key); + } + for (const auto& key : mBlobImageKeysToDelete) { + aResources.DeleteBlobImage(key); + } + mImageKeysToDelete.Clear(); + mBlobImageKeysToDelete.Clear(); +} + +void RenderRootStateManager::DiscardLocalImages() { + // Removes images but doesn't tell the parent side about them + // This is useful in empty / failed transactions where we created + // image keys but didn't tell the parent about them yet. + mImageKeysToDelete.Clear(); + mBlobImageKeysToDelete.Clear(); +} + +void RenderRootStateManager::ClearCachedResources() { + mActiveCompositorAnimationIds.clear(); + mDiscardedCompositorAnimationsIds.Clear(); +} + +void RenderRootStateManager::AddActiveCompositorAnimationId(uint64_t aId) { + // In layers-free mode we track the active compositor animation ids on the + // client side so that we don't try to discard the same animation id multiple + // times. We could just ignore the multiple-discard on the parent side, but + // checking on the content side reduces IPC traffic. + mActiveCompositorAnimationIds.insert(aId); +} + +void RenderRootStateManager::AddCompositorAnimationsIdForDiscard(uint64_t aId) { + if (mActiveCompositorAnimationIds.erase(aId)) { + // For layers-free ensure we don't try to discard an animation id that + // wasn't active. We also remove it from mActiveCompositorAnimationIds so we + // don't discard it again unless it gets re-activated. + mDiscardedCompositorAnimationsIds.AppendElement(aId); + } +} + +void RenderRootStateManager::DiscardCompositorAnimations() { + if (WrBridge()->IPCOpen() && !mDiscardedCompositorAnimationsIds.IsEmpty()) { + WrBridge()->SendDeleteCompositorAnimations( + mDiscardedCompositorAnimationsIds); + } + mDiscardedCompositorAnimationsIds.Clear(); +} + +void RenderRootStateManager::RegisterAsyncAnimation( + const wr::ImageKey& aKey, SharedSurfacesAnimation* aAnimation) { + mAsyncAnimations.insert(std::make_pair(wr::AsUint64(aKey), aAnimation)); +} + +void RenderRootStateManager::DeregisterAsyncAnimation( + const wr::ImageKey& aKey) { + mAsyncAnimations.erase(wr::AsUint64(aKey)); +} + +void RenderRootStateManager::ClearAsyncAnimations() { + for (const auto& i : mAsyncAnimations) { + i.second->Invalidate(this); + } + mAsyncAnimations.clear(); +} + +void RenderRootStateManager::WrReleasedImages( + const nsTArray<wr::ExternalImageKeyPair>& aPairs) { + // A SharedSurfaceAnimation object's lifetime is tied to its owning + // ImageContainer. When the ImageContainer is released, + // SharedSurfaceAnimation::Destroy is called which should ensure it is removed + // from the layer manager. Whenever the namespace for the + // WebRenderLayerManager itself is invalidated (e.g. we changed windows, or + // were destroyed ourselves), we callback into the SharedSurfaceAnimation + // object to remove its image key for us and any bound surfaces. If, for any + // reason, we somehow missed an WrReleasedImages call before the animation + // was bound to the layer manager, it will free those associated surfaces on + // the next ReleasePreviousFrame call. + for (const auto& pair : aPairs) { + auto i = mAsyncAnimations.find(wr::AsUint64(pair.key)); + if (i != mAsyncAnimations.end()) { + i->second->ReleasePreviousFrame(this, pair.id); + } + } +} + +void RenderRootStateManager::AddWebRenderParentCommand( + const WebRenderParentCommand& aCmd) { + WrBridge()->AddWebRenderParentCommand(aCmd); +} +void RenderRootStateManager::UpdateResources( + wr::IpcResourceUpdateQueue& aResources) { + WrBridge()->UpdateResources(aResources); +} +void RenderRootStateManager::AddPipelineIdForCompositable( + const wr::PipelineId& aPipelineId, const CompositableHandle& aHandle, + CompositableHandleOwner aOwner) { + WrBridge()->AddPipelineIdForCompositable(aPipelineId, aHandle, aOwner); +} +void RenderRootStateManager::RemovePipelineIdForCompositable( + const wr::PipelineId& aPipelineId) { + WrBridge()->RemovePipelineIdForCompositable(aPipelineId); +} +/// Release TextureClient that is bounded to ImageKey. +/// It is used for recycling TextureClient. +void RenderRootStateManager::ReleaseTextureOfImage(const wr::ImageKey& aKey) { + WrBridge()->ReleaseTextureOfImage(aKey); +} + +Maybe<wr::FontInstanceKey> RenderRootStateManager::GetFontKeyForScaledFont( + gfx::ScaledFont* aScaledFont, wr::IpcResourceUpdateQueue& aResources) { + return WrBridge()->GetFontKeyForScaledFont(aScaledFont, aResources); +} + +Maybe<wr::FontKey> RenderRootStateManager::GetFontKeyForUnscaledFont( + gfx::UnscaledFont* aUnscaledFont, wr::IpcResourceUpdateQueue& aResources) { + return WrBridge()->GetFontKeyForUnscaledFont(aUnscaledFont, aResources); +} + +} // namespace layers +} // namespace mozilla |