1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "mozilla/layers/RenderRootStateManager.h"
8 
9 #include "mozilla/layers/WebRenderBridgeChild.h"
10 #include "mozilla/layers/WebRenderLayerManager.h"
11 
12 namespace mozilla {
13 namespace layers {
14 
15 // RenderRootStateManager shares its ref count with the WebRenderLayerManager
16 // that created it. You can think of the two classes as being one unit, except
17 // there are multiple RenderRootStateManagers per WebRenderLayerManager. Since
18 // we need to reference the WebRenderLayerManager and it needs to reference us,
19 // this avoids us needing to involve the cycle collector.
AddRef()20 void RenderRootStateManager::AddRef() { mLayerManager->AddRef(); }
21 
Release()22 void RenderRootStateManager::Release() { mLayerManager->Release(); }
23 
WrBridge() const24 WebRenderBridgeChild* RenderRootStateManager::WrBridge() const {
25   return mLayerManager->WrBridge();
26 }
27 
CommandBuilder()28 WebRenderCommandBuilder& RenderRootStateManager::CommandBuilder() {
29   return mLayerManager->CommandBuilder();
30 }
31 
32 RenderRootStateManager::WebRenderUserDataRefTable*
GetWebRenderUserDataTable()33 RenderRootStateManager::GetWebRenderUserDataTable() {
34   return mLayerManager->GetWebRenderUserDataTable();
35 }
36 
AsyncResourceUpdates()37 wr::IpcResourceUpdateQueue& RenderRootStateManager::AsyncResourceUpdates() {
38   MOZ_ASSERT(NS_IsMainThread());
39 
40   if (!mAsyncResourceUpdates) {
41     mAsyncResourceUpdates.emplace(WrBridge());
42 
43     RefPtr<Runnable> task = NewRunnableMethod(
44         "RenderRootStateManager::FlushAsyncResourceUpdates", this,
45         &RenderRootStateManager::FlushAsyncResourceUpdates);
46     NS_DispatchToMainThread(task.forget());
47   }
48 
49   return mAsyncResourceUpdates.ref();
50 }
51 
Destroy()52 void RenderRootStateManager::Destroy() {
53   ClearAsyncAnimations();
54 
55   if (WrBridge()) {
56     // Just clear ImageKeys, they are deleted during WebRenderAPI destruction.
57     DiscardLocalImages();
58     // CompositorAnimations are cleared by WebRenderBridgeParent.
59     mDiscardedCompositorAnimationsIds.Clear();
60   }
61 
62   mActiveCompositorAnimationIds.clear();
63 
64   mDestroyed = true;
65 }
66 
FlushAsyncResourceUpdates()67 void RenderRootStateManager::FlushAsyncResourceUpdates() {
68   MOZ_ASSERT(NS_IsMainThread());
69 
70   if (!mAsyncResourceUpdates) {
71     return;
72   }
73 
74   if (!IsDestroyed() && WrBridge()) {
75     WrBridge()->UpdateResources(mAsyncResourceUpdates.ref());
76   }
77 
78   mAsyncResourceUpdates.reset();
79 }
80 
AddImageKeyForDiscard(wr::ImageKey key)81 void RenderRootStateManager::AddImageKeyForDiscard(wr::ImageKey key) {
82   mImageKeysToDelete.AppendElement(key);
83 }
84 
AddBlobImageKeyForDiscard(wr::BlobImageKey key)85 void RenderRootStateManager::AddBlobImageKeyForDiscard(wr::BlobImageKey key) {
86   mBlobImageKeysToDelete.AppendElement(key);
87 }
88 
DiscardImagesInTransaction(wr::IpcResourceUpdateQueue & aResources)89 void RenderRootStateManager::DiscardImagesInTransaction(
90     wr::IpcResourceUpdateQueue& aResources) {
91   for (const auto& key : mImageKeysToDelete) {
92     aResources.DeleteImage(key);
93   }
94   for (const auto& key : mBlobImageKeysToDelete) {
95     aResources.DeleteBlobImage(key);
96   }
97   mImageKeysToDelete.Clear();
98   mBlobImageKeysToDelete.Clear();
99 }
100 
DiscardLocalImages()101 void RenderRootStateManager::DiscardLocalImages() {
102   // Removes images but doesn't tell the parent side about them
103   // This is useful in empty / failed transactions where we created
104   // image keys but didn't tell the parent about them yet.
105   mImageKeysToDelete.Clear();
106   mBlobImageKeysToDelete.Clear();
107 }
108 
ClearCachedResources()109 void RenderRootStateManager::ClearCachedResources() {
110   mActiveCompositorAnimationIds.clear();
111   mDiscardedCompositorAnimationsIds.Clear();
112 }
113 
AddActiveCompositorAnimationId(uint64_t aId)114 void RenderRootStateManager::AddActiveCompositorAnimationId(uint64_t aId) {
115   // In layers-free mode we track the active compositor animation ids on the
116   // client side so that we don't try to discard the same animation id multiple
117   // times. We could just ignore the multiple-discard on the parent side, but
118   // checking on the content side reduces IPC traffic.
119   mActiveCompositorAnimationIds.insert(aId);
120 }
121 
AddCompositorAnimationsIdForDiscard(uint64_t aId)122 void RenderRootStateManager::AddCompositorAnimationsIdForDiscard(uint64_t aId) {
123   if (mActiveCompositorAnimationIds.erase(aId)) {
124     // For layers-free ensure we don't try to discard an animation id that
125     // wasn't active. We also remove it from mActiveCompositorAnimationIds so we
126     // don't discard it again unless it gets re-activated.
127     mDiscardedCompositorAnimationsIds.AppendElement(aId);
128   }
129 }
130 
DiscardCompositorAnimations()131 void RenderRootStateManager::DiscardCompositorAnimations() {
132   if (WrBridge()->IPCOpen() && !mDiscardedCompositorAnimationsIds.IsEmpty()) {
133     WrBridge()->SendDeleteCompositorAnimations(
134         mDiscardedCompositorAnimationsIds);
135   }
136   mDiscardedCompositorAnimationsIds.Clear();
137 }
138 
RegisterAsyncAnimation(const wr::ImageKey & aKey,SharedSurfacesAnimation * aAnimation)139 void RenderRootStateManager::RegisterAsyncAnimation(
140     const wr::ImageKey& aKey, SharedSurfacesAnimation* aAnimation) {
141   mAsyncAnimations.insert(std::make_pair(wr::AsUint64(aKey), aAnimation));
142 }
143 
DeregisterAsyncAnimation(const wr::ImageKey & aKey)144 void RenderRootStateManager::DeregisterAsyncAnimation(
145     const wr::ImageKey& aKey) {
146   mAsyncAnimations.erase(wr::AsUint64(aKey));
147 }
148 
ClearAsyncAnimations()149 void RenderRootStateManager::ClearAsyncAnimations() {
150   for (const auto& i : mAsyncAnimations) {
151     i.second->Invalidate(this);
152   }
153   mAsyncAnimations.clear();
154 }
155 
WrReleasedImages(const nsTArray<wr::ExternalImageKeyPair> & aPairs)156 void RenderRootStateManager::WrReleasedImages(
157     const nsTArray<wr::ExternalImageKeyPair>& aPairs) {
158   // A SharedSurfaceAnimation object's lifetime is tied to its owning
159   // ImageContainer. When the ImageContainer is released,
160   // SharedSurfaceAnimation::Destroy is called which should ensure it is removed
161   // from the layer manager. Whenever the namespace for the
162   // WebRenderLayerManager itself is invalidated (e.g. we changed windows, or
163   // were destroyed ourselves), we callback into the SharedSurfaceAnimation
164   // object to remove its image key for us and any bound surfaces. If, for any
165   // reason, we somehow missed an WrReleasedImages call before the animation
166   // was bound to the layer manager, it will free those associated surfaces on
167   // the next ReleasePreviousFrame call.
168   for (const auto& pair : aPairs) {
169     auto i = mAsyncAnimations.find(wr::AsUint64(pair.key));
170     if (i != mAsyncAnimations.end()) {
171       i->second->ReleasePreviousFrame(this, pair.id);
172     }
173   }
174 }
175 
AddWebRenderParentCommand(const WebRenderParentCommand & aCmd)176 void RenderRootStateManager::AddWebRenderParentCommand(
177     const WebRenderParentCommand& aCmd) {
178   WrBridge()->AddWebRenderParentCommand(aCmd);
179 }
UpdateResources(wr::IpcResourceUpdateQueue & aResources)180 void RenderRootStateManager::UpdateResources(
181     wr::IpcResourceUpdateQueue& aResources) {
182   WrBridge()->UpdateResources(aResources);
183 }
AddPipelineIdForAsyncCompositable(const wr::PipelineId & aPipelineId,const CompositableHandle & aHandle)184 void RenderRootStateManager::AddPipelineIdForAsyncCompositable(
185     const wr::PipelineId& aPipelineId, const CompositableHandle& aHandle) {
186   WrBridge()->AddPipelineIdForAsyncCompositable(aPipelineId, aHandle);
187 }
AddPipelineIdForCompositable(const wr::PipelineId & aPipelineId,const CompositableHandle & aHandle)188 void RenderRootStateManager::AddPipelineIdForCompositable(
189     const wr::PipelineId& aPipelineId, const CompositableHandle& aHandle) {
190   WrBridge()->AddPipelineIdForCompositable(aPipelineId, aHandle);
191 }
RemovePipelineIdForCompositable(const wr::PipelineId & aPipelineId)192 void RenderRootStateManager::RemovePipelineIdForCompositable(
193     const wr::PipelineId& aPipelineId) {
194   WrBridge()->RemovePipelineIdForCompositable(aPipelineId);
195 }
196 /// Release TextureClient that is bounded to ImageKey.
197 /// It is used for recycling TextureClient.
ReleaseTextureOfImage(const wr::ImageKey & aKey)198 void RenderRootStateManager::ReleaseTextureOfImage(const wr::ImageKey& aKey) {
199   WrBridge()->ReleaseTextureOfImage(aKey);
200 }
201 
GetFontKeyForScaledFont(gfx::ScaledFont * aScaledFont,wr::IpcResourceUpdateQueue * aResources)202 Maybe<wr::FontInstanceKey> RenderRootStateManager::GetFontKeyForScaledFont(
203     gfx::ScaledFont* aScaledFont, wr::IpcResourceUpdateQueue* aResources) {
204   return WrBridge()->GetFontKeyForScaledFont(aScaledFont, aResources);
205 }
206 
GetFontKeyForUnscaledFont(gfx::UnscaledFont * aUnscaledFont,wr::IpcResourceUpdateQueue * aResources)207 Maybe<wr::FontKey> RenderRootStateManager::GetFontKeyForUnscaledFont(
208     gfx::UnscaledFont* aUnscaledFont, wr::IpcResourceUpdateQueue* aResources) {
209   return WrBridge()->GetFontKeyForUnscaledFont(aUnscaledFont, aResources);
210 }
211 
212 }  // namespace layers
213 }  // namespace mozilla
214