1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
|
/* -*- 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::AddPipelineIdForAsyncCompositable(
const wr::PipelineId& aPipelineId, const CompositableHandle& aHandle) {
WrBridge()->AddPipelineIdForAsyncCompositable(aPipelineId, aHandle);
}
void RenderRootStateManager::AddPipelineIdForCompositable(
const wr::PipelineId& aPipelineId, const CompositableHandle& aHandle) {
WrBridge()->AddPipelineIdForCompositable(aPipelineId, aHandle);
}
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
|