Source code

Revision control

Other Tools

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/APZSampler.h"
8
9
#include "APZCTreeManager.h"
10
#include "AsyncPanZoomController.h"
11
#include "mozilla/ClearOnShutdown.h"
12
#include "mozilla/layers/APZThreadUtils.h"
13
#include "mozilla/layers/APZUtils.h"
14
#include "mozilla/layers/CompositorThread.h"
15
#include "mozilla/layers/LayerMetricsWrapper.h"
16
#include "mozilla/layers/SynchronousTask.h"
17
#include "TreeTraversal.h"
18
#include "mozilla/webrender/WebRenderAPI.h"
19
20
namespace mozilla {
21
namespace layers {
22
23
StaticMutex APZSampler::sWindowIdLock;
24
StaticAutoPtr<std::unordered_map<uint64_t, RefPtr<APZSampler>>>
25
APZSampler::sWindowIdMap;
26
27
APZSampler::APZSampler(const RefPtr<APZCTreeManager>& aApz,
28
bool aIsUsingWebRender)
29
: mApz(aApz),
30
mIsUsingWebRender(aIsUsingWebRender),
31
mThreadIdLock("APZSampler::mThreadIdLock"),
32
mSampleTimeLock("APZSampler::mSampleTimeLock") {
33
MOZ_ASSERT(aApz);
34
mApz->SetSampler(this);
35
}
36
37
APZSampler::~APZSampler() { mApz->SetSampler(nullptr); }
38
39
void APZSampler::Destroy() {
40
StaticMutexAutoLock lock(sWindowIdLock);
41
if (mWindowId) {
42
MOZ_ASSERT(sWindowIdMap);
43
sWindowIdMap->erase(wr::AsUint64(*mWindowId));
44
}
45
}
46
47
void APZSampler::SetWebRenderWindowId(const wr::WindowId& aWindowId) {
48
StaticMutexAutoLock lock(sWindowIdLock);
49
MOZ_ASSERT(!mWindowId);
50
mWindowId = Some(aWindowId);
51
if (!sWindowIdMap) {
52
sWindowIdMap = new std::unordered_map<uint64_t, RefPtr<APZSampler>>();
53
NS_DispatchToMainThread(NS_NewRunnableFunction(
54
"APZUpdater::ClearOnShutdown", [] { ClearOnShutdown(&sWindowIdMap); }));
55
}
56
(*sWindowIdMap)[wr::AsUint64(aWindowId)] = this;
57
}
58
59
/*static*/
60
void APZSampler::SetSamplerThread(const wr::WrWindowId& aWindowId) {
61
if (RefPtr<APZSampler> sampler = GetSampler(aWindowId)) {
62
MutexAutoLock lock(sampler->mThreadIdLock);
63
sampler->mSamplerThreadId = Some(PlatformThread::CurrentId());
64
}
65
}
66
67
/*static*/
68
void APZSampler::SampleForWebRender(
69
const wr::WrWindowId& aWindowId, wr::Transaction* aTransaction,
70
const wr::DocumentId& aRenderRootId,
71
const wr::WrPipelineIdEpochs* aEpochsBeingRendered) {
72
if (RefPtr<APZSampler> sampler = GetSampler(aWindowId)) {
73
wr::TransactionWrapper txn(aTransaction);
74
sampler->SampleForWebRender(txn, wr::RenderRootFromId(aRenderRootId),
75
aEpochsBeingRendered);
76
}
77
}
78
79
void APZSampler::SetSampleTime(const TimeStamp& aSampleTime) {
80
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
81
MutexAutoLock lock(mSampleTimeLock);
82
mSampleTime = aSampleTime;
83
}
84
85
void APZSampler::SampleForWebRender(
86
wr::TransactionWrapper& aTxn, wr::RenderRoot aRenderRoot,
87
const wr::WrPipelineIdEpochs* aEpochsBeingRendered) {
88
AssertOnSamplerThread();
89
TimeStamp sampleTime;
90
{ // scope lock
91
MutexAutoLock lock(mSampleTimeLock);
92
93
// If mSampleTime is null we're in a startup phase where the
94
// WebRenderBridgeParent hasn't yet provided us with a sample time.
95
// If we're that early there probably aren't any APZ animations happening
96
// anyway, so using Timestamp::Now() should be fine.
97
sampleTime = mSampleTime.IsNull() ? TimeStamp::Now() : mSampleTime;
98
}
99
mApz->SampleForWebRender(aTxn, sampleTime, aRenderRoot, aEpochsBeingRendered);
100
}
101
102
bool APZSampler::AdvanceAnimations(const TimeStamp& aSampleTime) {
103
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
104
AssertOnSamplerThread();
105
return mApz->AdvanceAnimations(Nothing(), aSampleTime);
106
}
107
108
LayerToParentLayerMatrix4x4 APZSampler::ComputeTransformForScrollThumb(
109
const LayerToParentLayerMatrix4x4& aCurrentTransform,
110
const LayerMetricsWrapper& aContent, const ScrollbarData& aThumbData,
111
bool aScrollbarIsDescendant,
112
AsyncTransformComponentMatrix* aOutClipTransform) {
113
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
114
AssertOnSamplerThread();
115
116
return mApz->ComputeTransformForScrollThumb(
117
aCurrentTransform, aContent.GetTransform(), aContent.GetApzc(),
118
aContent.Metrics(), aThumbData, aScrollbarIsDescendant,
119
aOutClipTransform);
120
}
121
122
CSSRect APZSampler::GetCurrentAsyncLayoutViewport(
123
const LayerMetricsWrapper& aLayer) {
124
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
125
AssertOnSamplerThread();
126
127
MOZ_ASSERT(aLayer.GetApzc());
128
return aLayer.GetApzc()->GetCurrentAsyncLayoutViewport(
129
AsyncPanZoomController::eForCompositing);
130
}
131
132
ParentLayerPoint APZSampler::GetCurrentAsyncScrollOffset(
133
const LayerMetricsWrapper& aLayer) {
134
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
135
AssertOnSamplerThread();
136
137
MOZ_ASSERT(aLayer.GetApzc());
138
return aLayer.GetApzc()->GetCurrentAsyncScrollOffset(
139
AsyncPanZoomController::eForCompositing);
140
}
141
142
AsyncTransform APZSampler::GetCurrentAsyncTransform(
143
const LayerMetricsWrapper& aLayer, AsyncTransformComponents aComponents) {
144
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
145
AssertOnSamplerThread();
146
147
MOZ_ASSERT(aLayer.GetApzc());
148
return aLayer.GetApzc()->GetCurrentAsyncTransform(
149
AsyncPanZoomController::eForCompositing, aComponents);
150
}
151
152
Maybe<CompositionPayload> APZSampler::NotifyScrollSampling(
153
const LayerMetricsWrapper& aLayer) {
154
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
155
AssertOnSamplerThread();
156
MOZ_ASSERT(aLayer.GetApzc());
157
return aLayer.GetApzc()->NotifyScrollSampling();
158
}
159
160
AsyncTransformComponentMatrix APZSampler::GetOverscrollTransform(
161
const LayerMetricsWrapper& aLayer) {
162
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
163
AssertOnSamplerThread();
164
165
MOZ_ASSERT(aLayer.GetApzc());
166
return aLayer.GetApzc()->GetOverscrollTransform(
167
AsyncPanZoomController::eForCompositing);
168
}
169
170
AsyncTransformComponentMatrix
171
APZSampler::GetCurrentAsyncTransformWithOverscroll(
172
const LayerMetricsWrapper& aLayer) {
173
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
174
AssertOnSamplerThread();
175
176
MOZ_ASSERT(aLayer.GetApzc());
177
return aLayer.GetApzc()->GetCurrentAsyncTransformWithOverscroll(
178
AsyncPanZoomController::eForCompositing);
179
}
180
181
void APZSampler::MarkAsyncTransformAppliedToContent(
182
const LayerMetricsWrapper& aLayer) {
183
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
184
AssertOnSamplerThread();
185
186
MOZ_ASSERT(aLayer.GetApzc());
187
aLayer.GetApzc()->MarkAsyncTransformAppliedToContent();
188
}
189
190
bool APZSampler::HasUnusedAsyncTransform(const LayerMetricsWrapper& aLayer) {
191
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
192
AssertOnSamplerThread();
193
194
AsyncPanZoomController* apzc = aLayer.GetApzc();
195
return apzc && !apzc->GetAsyncTransformAppliedToContent() &&
196
!AsyncTransformComponentMatrix(
197
apzc->GetCurrentAsyncTransform(
198
AsyncPanZoomController::eForCompositing))
199
.IsIdentity();
200
}
201
202
ScrollableLayerGuid APZSampler::GetGuid(const LayerMetricsWrapper& aLayer) {
203
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
204
AssertOnSamplerThread();
205
206
MOZ_ASSERT(aLayer.GetApzc());
207
return aLayer.GetApzc()->GetGuid();
208
}
209
210
ScreenMargin APZSampler::GetGeckoFixedLayerMargins() const {
211
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
212
AssertOnSamplerThread();
213
214
return mApz->GetGeckoFixedLayerMargins();
215
}
216
217
void APZSampler::AssertOnSamplerThread() const {
218
if (APZThreadUtils::GetThreadAssertionsEnabled()) {
219
MOZ_ASSERT(IsSamplerThread());
220
}
221
}
222
223
bool APZSampler::IsSamplerThread() const {
224
if (mIsUsingWebRender) {
225
// If the sampler thread id isn't set yet then we cannot be running on the
226
// sampler thread (because we will have the thread id before we run any
227
// other C++ code on it, and this function is only ever invoked from C++
228
// code), so return false in that scenario.
229
MutexAutoLock lock(mThreadIdLock);
230
return mSamplerThreadId && PlatformThread::CurrentId() == *mSamplerThreadId;
231
}
232
return CompositorThreadHolder::IsInCompositorThread();
233
}
234
235
/*static*/
236
already_AddRefed<APZSampler> APZSampler::GetSampler(
237
const wr::WrWindowId& aWindowId) {
238
RefPtr<APZSampler> sampler;
239
StaticMutexAutoLock lock(sWindowIdLock);
240
if (sWindowIdMap) {
241
auto it = sWindowIdMap->find(wr::AsUint64(aWindowId));
242
if (it != sWindowIdMap->end()) {
243
sampler = it->second;
244
}
245
}
246
return sampler.forget();
247
}
248
249
} // namespace layers
250
} // namespace mozilla
251
252
void apz_register_sampler(mozilla::wr::WrWindowId aWindowId) {
253
mozilla::layers::APZSampler::SetSamplerThread(aWindowId);
254
}
255
256
void apz_sample_transforms(
257
mozilla::wr::WrWindowId aWindowId, mozilla::wr::Transaction* aTransaction,
258
mozilla::wr::DocumentId aDocumentId,
259
const mozilla::wr::WrPipelineIdEpochs* aEpochsBeingRendered) {
260
mozilla::layers::APZSampler::SampleForWebRender(
261
aWindowId, aTransaction, aDocumentId, aEpochsBeingRendered);
262
}
263
264
void apz_deregister_sampler(mozilla::wr::WrWindowId aWindowId) {}