Bug 1764201 Part 3: Remove screen info stuff from gfxPlatform. r=jgilbert,geckoview...
[gecko.git] / gfx / layers / apz / src / APZSampler.cpp
blobd0e251cec43170d3acd824a9439fd40efba02a07
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/. */
7 #include "mozilla/layers/APZSampler.h"
9 #include "AsyncPanZoomController.h"
10 #include "mozilla/ClearOnShutdown.h"
11 #include "mozilla/layers/APZThreadUtils.h"
12 #include "mozilla/layers/APZUtils.h"
13 #include "mozilla/layers/CompositorThread.h"
14 #include "mozilla/layers/SynchronousTask.h"
15 #include "TreeTraversal.h"
16 #include "mozilla/webrender/WebRenderAPI.h"
18 namespace mozilla {
19 namespace layers {
21 StaticMutex APZSampler::sWindowIdLock;
22 StaticAutoPtr<std::unordered_map<uint64_t, RefPtr<APZSampler>>>
23 APZSampler::sWindowIdMap;
25 APZSampler::APZSampler(const RefPtr<APZCTreeManager>& aApz,
26 bool aIsUsingWebRender)
27 : mApz(aApz),
28 mIsUsingWebRender(aIsUsingWebRender),
29 mThreadIdLock("APZSampler::mThreadIdLock"),
30 mSampleTimeLock("APZSampler::mSampleTimeLock") {
31 MOZ_ASSERT(aApz);
32 mApz->SetSampler(this);
35 APZSampler::~APZSampler() { mApz->SetSampler(nullptr); }
37 void APZSampler::Destroy() {
38 StaticMutexAutoLock lock(sWindowIdLock);
39 if (mWindowId) {
40 MOZ_ASSERT(sWindowIdMap);
41 sWindowIdMap->erase(wr::AsUint64(*mWindowId));
45 void APZSampler::SetWebRenderWindowId(const wr::WindowId& aWindowId) {
46 StaticMutexAutoLock lock(sWindowIdLock);
47 MOZ_ASSERT(!mWindowId);
48 mWindowId = Some(aWindowId);
49 if (!sWindowIdMap) {
50 sWindowIdMap = new std::unordered_map<uint64_t, RefPtr<APZSampler>>();
51 NS_DispatchToMainThread(NS_NewRunnableFunction(
52 "APZSampler::ClearOnShutdown", [] { ClearOnShutdown(&sWindowIdMap); }));
54 (*sWindowIdMap)[wr::AsUint64(aWindowId)] = this;
57 /*static*/
58 void APZSampler::SetSamplerThread(const wr::WrWindowId& aWindowId) {
59 if (RefPtr<APZSampler> sampler = GetSampler(aWindowId)) {
60 MutexAutoLock lock(sampler->mThreadIdLock);
61 sampler->mSamplerThreadId = Some(PlatformThread::CurrentId());
65 /*static*/
66 void APZSampler::SampleForWebRender(const wr::WrWindowId& aWindowId,
67 const uint64_t* aGeneratedFrameId,
68 wr::Transaction* aTransaction) {
69 if (RefPtr<APZSampler> sampler = GetSampler(aWindowId)) {
70 wr::TransactionWrapper txn(aTransaction);
71 Maybe<VsyncId> vsyncId =
72 aGeneratedFrameId ? Some(VsyncId{*aGeneratedFrameId}) : Nothing();
73 sampler->SampleForWebRender(vsyncId, txn);
77 void APZSampler::SetSampleTime(const SampleTime& aSampleTime) {
78 MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
79 MutexAutoLock lock(mSampleTimeLock);
80 // This only gets called with WR, and the time provided is going to be
81 // the time at which the current vsync interval ends. i.e. it is the timestamp
82 // for the next vsync that will occur.
83 mSampleTime = aSampleTime;
86 void APZSampler::SampleForWebRender(const Maybe<VsyncId>& aVsyncId,
87 wr::TransactionWrapper& aTxn) {
88 AssertOnSamplerThread();
89 SampleTime sampleTime;
90 { // scope lock
91 MutexAutoLock lock(mSampleTimeLock);
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 now = SampleTime::FromNow();
98 sampleTime = mSampleTime.IsNull() ? now : mSampleTime;
100 mApz->SampleForWebRender(aVsyncId, aTxn, sampleTime);
103 AsyncTransform APZSampler::GetCurrentAsyncTransform(
104 const LayersId& aLayersId, const ScrollableLayerGuid::ViewID& aScrollId,
105 AsyncTransformComponents aComponents,
106 const MutexAutoLock& aProofOfMapLock) const {
107 MOZ_ASSERT(!CompositorThreadHolder::IsInCompositorThread());
108 AssertOnSamplerThread();
110 RefPtr<AsyncPanZoomController> apzc =
111 mApz->GetTargetAPZC(aLayersId, aScrollId, aProofOfMapLock);
112 if (!apzc) {
113 // It's possible that this function can get called even after the target
114 // APZC has been already destroyed because destroying the animation which
115 // triggers this function call is basically processed later than the APZC,
116 // i.e. queue mCompositorAnimationsToDelete in WebRenderBridgeParent and
117 // then remove in WebRenderBridgeParent::RemoveEpochDataPriorTo.
118 return AsyncTransform{};
121 return apzc->GetCurrentAsyncTransform(AsyncPanZoomController::eForCompositing,
122 aComponents);
125 ParentLayerRect APZSampler::GetCompositionBounds(
126 const LayersId& aLayersId, const ScrollableLayerGuid::ViewID& aScrollId,
127 const MutexAutoLock& aProofOfMapLock) const {
128 // This function can get called on the compositor in case of non WebRender
129 // get called on the sampler thread in case of WebRender.
130 AssertOnSamplerThread();
132 RefPtr<AsyncPanZoomController> apzc =
133 mApz->GetTargetAPZC(aLayersId, aScrollId, aProofOfMapLock);
134 if (!apzc) {
135 // On WebRender it's possible that this function can get called even after
136 // the target APZC has been already destroyed because destroying the
137 // animation which triggers this function call is basically processed later
138 // than the APZC one, i.e. queue mCompositorAnimationsToDelete in
139 // WebRenderBridgeParent and then remove them in
140 // WebRenderBridgeParent::RemoveEpochDataPriorTo.
141 return ParentLayerRect();
144 return apzc->GetCompositionBounds();
147 Maybe<APZSampler::ScrollOffsetAndRange>
148 APZSampler::GetCurrentScrollOffsetAndRange(
149 const LayersId& aLayersId, const ScrollableLayerGuid::ViewID& aScrollId,
150 const MutexAutoLock& aProofOfMapLock) const {
151 // Note: This is called from OMTA Sampler thread, or Compositor thread for
152 // testing.
154 RefPtr<AsyncPanZoomController> apzc =
155 mApz->GetTargetAPZC(aLayersId, aScrollId, aProofOfMapLock);
156 if (!apzc) {
157 return Nothing();
160 return Some(ScrollOffsetAndRange{
161 // FIXME: Use the one-frame delayed offset now. This doesn't take
162 // scroll-linked effets into accounts, so we have to fix this in the
163 // future.
164 apzc->GetCurrentAsyncVisualViewport(
165 AsyncTransformConsumer::eForCompositing)
166 .TopLeft(),
167 apzc->GetCurrentScrollRangeInCssPixels()});
170 void APZSampler::AssertOnSamplerThread() const {
171 if (APZThreadUtils::GetThreadAssertionsEnabled()) {
172 MOZ_ASSERT(IsSamplerThread());
176 bool APZSampler::IsSamplerThread() const {
177 if (mIsUsingWebRender) {
178 // If the sampler thread id isn't set yet then we cannot be running on the
179 // sampler thread (because we will have the thread id before we run any
180 // other C++ code on it, and this function is only ever invoked from C++
181 // code), so return false in that scenario.
182 MutexAutoLock lock(mThreadIdLock);
183 return mSamplerThreadId && PlatformThread::CurrentId() == *mSamplerThreadId;
185 return CompositorThreadHolder::IsInCompositorThread();
188 /*static*/
189 already_AddRefed<APZSampler> APZSampler::GetSampler(
190 const wr::WrWindowId& aWindowId) {
191 RefPtr<APZSampler> sampler;
192 StaticMutexAutoLock lock(sWindowIdLock);
193 if (sWindowIdMap) {
194 auto it = sWindowIdMap->find(wr::AsUint64(aWindowId));
195 if (it != sWindowIdMap->end()) {
196 sampler = it->second;
199 return sampler.forget();
202 } // namespace layers
203 } // namespace mozilla
205 void apz_register_sampler(mozilla::wr::WrWindowId aWindowId) {
206 mozilla::layers::APZSampler::SetSamplerThread(aWindowId);
209 void apz_sample_transforms(mozilla::wr::WrWindowId aWindowId,
210 const uint64_t* aGeneratedFrameId,
211 mozilla::wr::Transaction* aTransaction) {
212 mozilla::layers::APZSampler::SampleForWebRender(aWindowId, aGeneratedFrameId,
213 aTransaction);
216 void apz_deregister_sampler(mozilla::wr::WrWindowId aWindowId) {}