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