Line data Source code
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/CompositorBridgeParent.h"
8 :
9 : #include <stdio.h> // for fprintf, stdout
10 : #include <stdint.h> // for uint64_t
11 : #include <map> // for _Rb_tree_iterator, etc
12 : #include <utility> // for pair
13 :
14 : #include "apz/src/APZCTreeManager.h" // for APZCTreeManager
15 : #include "LayerTransactionParent.h" // for LayerTransactionParent
16 : #include "RenderTrace.h" // for RenderTraceLayers
17 : #include "base/message_loop.h" // for MessageLoop
18 : #include "base/process.h" // for ProcessId
19 : #include "base/task.h" // for CancelableTask, etc
20 : #include "base/thread.h" // for Thread
21 : #include "gfxContext.h" // for gfxContext
22 : #include "gfxPlatform.h" // for gfxPlatform
23 : #include "TreeTraversal.h" // for ForEachNode
24 : #ifdef MOZ_WIDGET_GTK
25 : #include "gfxPlatformGtk.h" // for gfxPlatform
26 : #endif
27 : #include "gfxPrefs.h" // for gfxPrefs
28 : #include "mozilla/AutoRestore.h" // for AutoRestore
29 : #include "mozilla/ClearOnShutdown.h" // for ClearOnShutdown
30 : #include "mozilla/DebugOnly.h" // for DebugOnly
31 : #include "mozilla/dom/ContentParent.h"
32 : #include "mozilla/dom/TabParent.h"
33 : #include "mozilla/gfx/2D.h" // for DrawTarget
34 : #include "mozilla/gfx/GPUChild.h" // for GfxPrefValue
35 : #include "mozilla/gfx/Point.h" // for IntSize
36 : #include "mozilla/gfx/Rect.h" // for IntSize
37 : #include "mozilla/gfx/gfxVars.h" // for gfxVars
38 : #include "VRManager.h" // for VRManager
39 : #include "mozilla/ipc/Transport.h" // for Transport
40 : #include "mozilla/gfx/gfxVars.h"
41 : #include "mozilla/gfx/GPUParent.h"
42 : #include "mozilla/layers/AnimationHelper.h" // for CompositorAnimationStorage
43 : #include "mozilla/layers/APZCTreeManagerParent.h" // for APZCTreeManagerParent
44 : #include "mozilla/layers/APZSampler.h" // for APZSampler
45 : #include "mozilla/layers/APZThreadUtils.h" // for APZThreadUtils
46 : #include "mozilla/layers/APZUpdater.h" // for APZUpdater
47 : #include "mozilla/layers/AsyncCompositionManager.h"
48 : #include "mozilla/layers/BasicCompositor.h" // for BasicCompositor
49 : #include "mozilla/layers/Compositor.h" // for Compositor
50 : #include "mozilla/layers/CompositorManagerParent.h" // for CompositorManagerParent
51 : #include "mozilla/layers/CompositorOGL.h" // for CompositorOGL
52 : #include "mozilla/layers/CompositorThread.h"
53 : #include "mozilla/layers/CompositorTypes.h"
54 : #include "mozilla/layers/CompositorVsyncScheduler.h"
55 : #include "mozilla/layers/CrossProcessCompositorBridgeParent.h"
56 : #include "mozilla/layers/FrameUniformityData.h"
57 : #include "mozilla/layers/ImageBridgeParent.h"
58 : #include "mozilla/layers/LayerManagerComposite.h"
59 : #include "mozilla/layers/LayerManagerMLGPU.h"
60 : #include "mozilla/layers/LayerTreeOwnerTracker.h"
61 : #include "mozilla/layers/LayersTypes.h"
62 : #include "mozilla/layers/PLayerTransactionParent.h"
63 : #include "mozilla/layers/RemoteContentController.h"
64 : #include "mozilla/layers/WebRenderBridgeParent.h"
65 : #include "mozilla/layers/AsyncImagePipelineManager.h"
66 : #include "mozilla/layout/RenderFrameParent.h"
67 : #include "mozilla/webrender/WebRenderAPI.h"
68 : #include "mozilla/media/MediaSystemResourceService.h" // for MediaSystemResourceService
69 : #include "mozilla/mozalloc.h" // for operator new, etc
70 : #include "mozilla/Telemetry.h"
71 : #ifdef MOZ_WIDGET_GTK
72 : #include "basic/X11BasicCompositor.h" // for X11BasicCompositor
73 : #endif
74 : #include "nsCOMPtr.h" // for already_AddRefed
75 : #include "nsDebug.h" // for NS_ASSERTION, etc
76 : #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
77 : #include "nsIWidget.h" // for nsIWidget
78 : #include "nsTArray.h" // for nsTArray
79 : #include "nsThreadUtils.h" // for NS_IsMainThread
80 : #include "nsXULAppAPI.h" // for XRE_GetIOMessageLoop
81 : #ifdef XP_WIN
82 : #include "mozilla/layers/CompositorD3D11.h"
83 : #include "mozilla/widget/WinCompositorWidget.h"
84 : #endif
85 : #include "GeckoProfiler.h"
86 : #include "mozilla/ipc/ProtocolTypes.h"
87 : #include "mozilla/Unused.h"
88 : #include "mozilla/Hal.h"
89 : #include "mozilla/HalTypes.h"
90 : #include "mozilla/StaticPtr.h"
91 : #include "mozilla/Telemetry.h"
92 : #ifdef MOZ_GECKO_PROFILER
93 : # include "ProfilerMarkerPayload.h"
94 : #endif
95 : #include "mozilla/VsyncDispatcher.h"
96 : #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
97 : # include "VsyncSource.h"
98 : #endif
99 : #include "mozilla/widget/CompositorWidget.h"
100 : #ifdef MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING
101 : # include "mozilla/widget/CompositorWidgetParent.h"
102 : #endif
103 : #ifdef XP_WIN
104 : # include "mozilla/gfx/DeviceManagerDx.h"
105 : #endif
106 :
107 : #include "LayerScope.h"
108 :
109 : namespace mozilla {
110 :
111 : namespace layers {
112 :
113 : using namespace mozilla::ipc;
114 : using namespace mozilla::gfx;
115 : using namespace std;
116 :
117 : using base::ProcessId;
118 : using base::Thread;
119 :
120 0 : CompositorBridgeParentBase::CompositorBridgeParentBase(CompositorManagerParent* aManager)
121 : : mCanSend(true)
122 0 : , mCompositorManager(aManager)
123 : {
124 0 : }
125 :
126 0 : CompositorBridgeParentBase::~CompositorBridgeParentBase()
127 : {
128 0 : }
129 :
130 : ProcessId
131 0 : CompositorBridgeParentBase::GetChildProcessId()
132 : {
133 0 : return OtherPid();
134 : }
135 :
136 : void
137 0 : CompositorBridgeParentBase::NotifyNotUsed(PTextureParent* aTexture, uint64_t aTransactionId)
138 : {
139 0 : RefPtr<TextureHost> texture = TextureHost::AsTextureHost(aTexture);
140 0 : if (!texture) {
141 0 : return;
142 : }
143 :
144 0 : if (!(texture->GetFlags() & TextureFlags::RECYCLE)) {
145 : return;
146 : }
147 :
148 0 : uint64_t textureId = TextureHost::GetTextureSerial(aTexture);
149 0 : mPendingAsyncMessage.push_back(
150 0 : OpNotifyNotUsed(textureId, aTransactionId));
151 : }
152 :
153 : void
154 0 : CompositorBridgeParentBase::SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage)
155 : {
156 0 : Unused << SendParentAsyncMessages(aMessage);
157 0 : }
158 :
159 : bool
160 0 : CompositorBridgeParentBase::AllocShmem(size_t aSize,
161 : ipc::SharedMemory::SharedMemoryType aType,
162 : ipc::Shmem* aShmem)
163 : {
164 0 : return PCompositorBridgeParent::AllocShmem(aSize, aType, aShmem);
165 : }
166 :
167 : bool
168 0 : CompositorBridgeParentBase::AllocUnsafeShmem(size_t aSize,
169 : ipc::SharedMemory::SharedMemoryType aType,
170 : ipc::Shmem* aShmem)
171 : {
172 0 : return PCompositorBridgeParent::AllocUnsafeShmem(aSize, aType, aShmem);
173 : }
174 :
175 : void
176 0 : CompositorBridgeParentBase::DeallocShmem(ipc::Shmem& aShmem)
177 : {
178 0 : PCompositorBridgeParent::DeallocShmem(aShmem);
179 0 : }
180 :
181 : static inline MessageLoop*
182 : CompositorLoop()
183 : {
184 0 : return CompositorThreadHolder::Loop();
185 : }
186 :
187 : base::ProcessId
188 0 : CompositorBridgeParentBase::RemotePid()
189 : {
190 0 : return OtherPid();
191 : }
192 :
193 : bool
194 0 : CompositorBridgeParentBase::StartSharingMetrics(ipc::SharedMemoryBasic::Handle aHandle,
195 : CrossProcessMutexHandle aMutexHandle,
196 : LayersId aLayersId,
197 : uint32_t aApzcId)
198 : {
199 0 : if (!CompositorThreadHolder::IsInCompositorThread()) {
200 0 : MOZ_ASSERT(CompositorLoop());
201 0 : CompositorLoop()->PostTask(
202 : NewRunnableMethod<ipc::SharedMemoryBasic::Handle,
203 : CrossProcessMutexHandle,
204 : LayersId,
205 0 : uint32_t>(
206 : "layers::CompositorBridgeParent::StartSharingMetrics",
207 : this,
208 : &CompositorBridgeParentBase::StartSharingMetrics,
209 0 : aHandle, aMutexHandle, aLayersId, aApzcId));
210 0 : return true;
211 : }
212 :
213 0 : MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
214 0 : if (!mCanSend) {
215 : return false;
216 : }
217 0 : return PCompositorBridgeParent::SendSharedCompositorFrameMetrics(
218 0 : aHandle, aMutexHandle, aLayersId, aApzcId);
219 : }
220 :
221 : bool
222 0 : CompositorBridgeParentBase::StopSharingMetrics(FrameMetrics::ViewID aScrollId,
223 : uint32_t aApzcId)
224 : {
225 0 : if (!CompositorThreadHolder::IsInCompositorThread()) {
226 0 : MOZ_ASSERT(CompositorLoop());
227 0 : CompositorLoop()->PostTask(
228 0 : NewRunnableMethod<FrameMetrics::ViewID, uint32_t>(
229 : "layers::CompositorBridgeParent::StopSharingMetrics",
230 : this,
231 : &CompositorBridgeParentBase::StopSharingMetrics,
232 0 : aScrollId, aApzcId));
233 0 : return true;
234 : }
235 :
236 0 : MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
237 0 : if (!mCanSend) {
238 : return false;
239 : }
240 0 : return PCompositorBridgeParent::SendReleaseSharedCompositorFrameMetrics(
241 0 : aScrollId, aApzcId);
242 : }
243 :
244 0 : CompositorBridgeParent::LayerTreeState::LayerTreeState()
245 : : mApzcTreeManagerParent(nullptr)
246 : , mParent(nullptr)
247 : , mLayerManager(nullptr)
248 : , mCrossProcessParent(nullptr)
249 : , mLayerTree(nullptr)
250 0 : , mUpdatedPluginDataAvailable(false)
251 : {
252 0 : }
253 :
254 0 : CompositorBridgeParent::LayerTreeState::~LayerTreeState()
255 : {
256 0 : if (mController) {
257 0 : mController->Destroy();
258 : }
259 0 : }
260 :
261 : typedef map<LayersId, CompositorBridgeParent::LayerTreeState> LayerTreeMap;
262 : LayerTreeMap sIndirectLayerTrees;
263 : StaticAutoPtr<mozilla::Monitor> sIndirectLayerTreesLock;
264 :
265 0 : static void EnsureLayerTreeMapReady()
266 : {
267 0 : MOZ_ASSERT(NS_IsMainThread());
268 0 : if (!sIndirectLayerTreesLock) {
269 0 : sIndirectLayerTreesLock = new Monitor("IndirectLayerTree");
270 0 : mozilla::ClearOnShutdown(&sIndirectLayerTreesLock);
271 : }
272 0 : }
273 :
274 : template <typename Lambda>
275 : inline void
276 0 : CompositorBridgeParent::ForEachIndirectLayerTree(const Lambda& aCallback)
277 : {
278 0 : sIndirectLayerTreesLock->AssertCurrentThreadOwns();
279 0 : for (auto it = sIndirectLayerTrees.begin(); it != sIndirectLayerTrees.end(); it++) {
280 0 : LayerTreeState* state = &it->second;
281 0 : if (state->mParent == this) {
282 0 : aCallback(state, it->first);
283 : }
284 : }
285 0 : }
286 :
287 : /**
288 : * A global map referencing each compositor by ID.
289 : *
290 : * This map is used by the ImageBridge protocol to trigger
291 : * compositions without having to keep references to the
292 : * compositor
293 : */
294 : typedef map<uint64_t,CompositorBridgeParent*> CompositorMap;
295 0 : static StaticAutoPtr<CompositorMap> sCompositorMap;
296 :
297 : void
298 0 : CompositorBridgeParent::Setup()
299 : {
300 0 : EnsureLayerTreeMapReady();
301 :
302 0 : MOZ_ASSERT(!sCompositorMap);
303 0 : sCompositorMap = new CompositorMap;
304 0 : }
305 :
306 : void
307 0 : CompositorBridgeParent::Shutdown()
308 : {
309 0 : MOZ_ASSERT(sCompositorMap);
310 0 : MOZ_ASSERT(sCompositorMap->empty());
311 0 : sCompositorMap = nullptr;
312 0 : }
313 :
314 : void
315 0 : CompositorBridgeParent::FinishShutdown()
316 : {
317 : // TODO: this should be empty by now...
318 0 : sIndirectLayerTrees.clear();
319 0 : }
320 :
321 : #ifdef COMPOSITOR_PERFORMANCE_WARNING
322 : static int32_t
323 : CalculateCompositionFrameRate()
324 : {
325 : // Used when layout.frame_rate is -1. Needs to be kept in sync with
326 : // DEFAULT_FRAME_RATE in nsRefreshDriver.cpp.
327 : // TODO: This should actually return the vsync rate.
328 : const int32_t defaultFrameRate = 60;
329 : int32_t compositionFrameRatePref = gfxPrefs::LayersCompositionFrameRate();
330 : if (compositionFrameRatePref < 0) {
331 : // Use the same frame rate for composition as for layout.
332 : int32_t layoutFrameRatePref = gfxPrefs::LayoutFrameRate();
333 : if (layoutFrameRatePref < 0) {
334 : // TODO: The main thread frame scheduling code consults the actual
335 : // monitor refresh rate in this case. We should do the same.
336 : return defaultFrameRate;
337 : }
338 : return layoutFrameRatePref;
339 : }
340 : return compositionFrameRatePref;
341 : }
342 : #endif
343 :
344 0 : CompositorBridgeParent::CompositorBridgeParent(CompositorManagerParent* aManager,
345 : CSSToLayoutDeviceScale aScale,
346 : const TimeDuration& aVsyncRate,
347 : const CompositorOptions& aOptions,
348 : bool aUseExternalSurfaceSize,
349 0 : const gfx::IntSize& aSurfaceSize)
350 : : CompositorBridgeParentBase(aManager)
351 : , mWidget(nullptr)
352 : , mScale(aScale)
353 : , mVsyncRate(aVsyncRate)
354 : , mPendingTransaction{0}
355 : , mPaused(false)
356 : , mUseExternalSurfaceSize(aUseExternalSurfaceSize)
357 : , mEGLSurfaceSize(aSurfaceSize)
358 : , mOptions(aOptions)
359 : , mPauseCompositionMonitor("PauseCompositionMonitor")
360 : , mResumeCompositionMonitor("ResumeCompositionMonitor")
361 : , mRootLayerTreeID{0}
362 : , mOverrideComposeReadiness(false)
363 : , mForceCompositionTask(nullptr)
364 : , mCompositorScheduler(nullptr)
365 : , mAnimationStorage(nullptr)
366 : , mPaintTime(TimeDuration::Forever())
367 : #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
368 : , mLastPluginUpdateLayerTreeId{0}
369 : , mDeferPluginWindows(false)
370 0 : , mPluginWindowsHidden(false)
371 : #endif
372 : {
373 0 : }
374 :
375 : void
376 0 : CompositorBridgeParent::InitSameProcess(widget::CompositorWidget* aWidget,
377 : const LayersId& aLayerTreeId)
378 : {
379 0 : MOZ_ASSERT(XRE_IsParentProcess());
380 0 : MOZ_ASSERT(NS_IsMainThread());
381 :
382 0 : mWidget = aWidget;
383 0 : mRootLayerTreeID = aLayerTreeId;
384 :
385 0 : Initialize();
386 0 : }
387 :
388 : mozilla::ipc::IPCResult
389 0 : CompositorBridgeParent::RecvInitialize(const LayersId& aRootLayerTreeId)
390 : {
391 0 : MOZ_ASSERT(XRE_IsGPUProcess());
392 :
393 0 : mRootLayerTreeID = aRootLayerTreeId;
394 :
395 0 : Initialize();
396 0 : return IPC_OK();
397 : }
398 :
399 : void
400 0 : CompositorBridgeParent::Initialize()
401 : {
402 0 : MOZ_ASSERT(CompositorThread(),
403 : "The compositor thread must be Initialized before instanciating a CompositorBridgeParent.");
404 :
405 0 : if (mOptions.UseAPZ()) {
406 0 : MOZ_ASSERT(!mApzcTreeManager);
407 0 : MOZ_ASSERT(!mApzSampler);
408 0 : MOZ_ASSERT(!mApzUpdater);
409 0 : mApzcTreeManager = new APZCTreeManager(mRootLayerTreeID);
410 0 : mApzSampler = new APZSampler(mApzcTreeManager, mOptions.UseWebRender());
411 0 : mApzUpdater = new APZUpdater(mApzcTreeManager, mOptions.UseWebRender());
412 : }
413 :
414 0 : mPaused = mOptions.InitiallyPaused();
415 :
416 0 : mCompositorBridgeID = 0;
417 : // FIXME: This holds on the the fact that right now the only thing that
418 : // can destroy this instance is initialized on the compositor thread after
419 : // this task has been processed.
420 0 : MOZ_ASSERT(CompositorLoop());
421 0 : CompositorLoop()->PostTask(NewRunnableFunction("AddCompositorRunnable",
422 : &AddCompositor,
423 0 : this, &mCompositorBridgeID));
424 :
425 :
426 : { // scope lock
427 0 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
428 0 : sIndirectLayerTrees[mRootLayerTreeID].mParent = this;
429 : }
430 :
431 0 : LayerScope::SetPixelScale(mScale.scale);
432 :
433 0 : if (!mOptions.UseWebRender()) {
434 0 : mCompositorScheduler = new CompositorVsyncScheduler(this, mWidget);
435 : }
436 0 : }
437 :
438 : LayersId
439 0 : CompositorBridgeParent::RootLayerTreeId()
440 : {
441 0 : MOZ_ASSERT(mRootLayerTreeID.IsValid());
442 0 : return mRootLayerTreeID;
443 : }
444 :
445 0 : CompositorBridgeParent::~CompositorBridgeParent()
446 : {
447 0 : InfallibleTArray<PTextureParent*> textures;
448 0 : ManagedPTextureParent(textures);
449 : // We expect all textures to be destroyed by now.
450 0 : MOZ_DIAGNOSTIC_ASSERT(textures.Length() == 0);
451 0 : for (unsigned int i = 0; i < textures.Length(); ++i) {
452 0 : RefPtr<TextureHost> tex = TextureHost::AsTextureHost(textures[i]);
453 0 : tex->DeallocateDeviceData();
454 : }
455 0 : }
456 :
457 : mozilla::ipc::IPCResult
458 0 : CompositorBridgeParent::RecvForceIsFirstPaint()
459 : {
460 0 : mCompositionManager->ForceIsFirstPaint();
461 0 : return IPC_OK();
462 : }
463 :
464 : void
465 0 : CompositorBridgeParent::StopAndClearResources()
466 : {
467 0 : if (mForceCompositionTask) {
468 0 : mForceCompositionTask->Cancel();
469 0 : mForceCompositionTask = nullptr;
470 : }
471 :
472 0 : mPaused = true;
473 :
474 : // We need to clear the APZ tree before we destroy the WebRender API below,
475 : // because in the case of async scene building that will shut down the updater
476 : // thread and we need to run the task before that happens.
477 0 : MOZ_ASSERT((mApzSampler != nullptr) == (mApzcTreeManager != nullptr));
478 0 : MOZ_ASSERT((mApzUpdater != nullptr) == (mApzcTreeManager != nullptr));
479 0 : if (mApzUpdater) {
480 0 : mApzSampler = nullptr;
481 0 : mApzUpdater->ClearTree(mRootLayerTreeID);
482 0 : mApzUpdater = nullptr;
483 0 : mApzcTreeManager = nullptr;
484 : }
485 :
486 : // Ensure that the layer manager is destroyed before CompositorBridgeChild.
487 0 : if (mLayerManager) {
488 0 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
489 0 : ForEachIndirectLayerTree([this] (LayerTreeState* lts, LayersId) -> void {
490 0 : mLayerManager->ClearCachedResources(lts->mRoot);
491 0 : lts->mLayerManager = nullptr;
492 0 : lts->mParent = nullptr;
493 0 : });
494 0 : mLayerManager->Destroy();
495 0 : mLayerManager = nullptr;
496 0 : mCompositionManager = nullptr;
497 : }
498 :
499 0 : if (mWrBridge) {
500 : // Ensure we are not holding the sIndirectLayerTreesLock when destroying
501 : // the WebRenderBridgeParent instances because it may block on WR.
502 0 : std::vector<RefPtr<WebRenderBridgeParent>> indirectBridgeParents;
503 : { // scope lock
504 0 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
505 0 : ForEachIndirectLayerTree([&] (LayerTreeState* lts, LayersId) -> void {
506 0 : if (lts->mWrBridge) {
507 0 : indirectBridgeParents.emplace_back(lts->mWrBridge.forget());
508 : }
509 0 : lts->mParent = nullptr;
510 0 : });
511 : }
512 0 : for (const RefPtr<WebRenderBridgeParent>& bridge : indirectBridgeParents) {
513 0 : bridge->Destroy();
514 : }
515 0 : indirectBridgeParents.clear();
516 :
517 : // Ensure we are not holding the sIndirectLayerTreesLock here because we
518 : // are going to block on WR threads in order to shut it down properly.
519 0 : mWrBridge->Destroy();
520 0 : mWrBridge = nullptr;
521 0 : if (mAsyncImageManager) {
522 0 : mAsyncImageManager->Destroy();
523 : // WebRenderAPI should be already destructed
524 0 : mAsyncImageManager = nullptr;
525 : }
526 : }
527 :
528 0 : if (mCompositor) {
529 0 : mCompositor->DetachWidget();
530 0 : mCompositor->Destroy();
531 0 : mCompositor = nullptr;
532 : }
533 :
534 : // This must be destroyed now since it accesses the widget.
535 0 : if (mCompositorScheduler) {
536 0 : mCompositorScheduler->Destroy();
537 0 : mCompositorScheduler = nullptr;
538 : }
539 :
540 : // After this point, it is no longer legal to access the widget.
541 0 : mWidget = nullptr;
542 :
543 : // Clear mAnimationStorage here to ensure that the compositor thread
544 : // still exists when we destroy it.
545 0 : mAnimationStorage = nullptr;
546 0 : }
547 :
548 : mozilla::ipc::IPCResult
549 0 : CompositorBridgeParent::RecvWillClose()
550 : {
551 0 : StopAndClearResources();
552 : // Once we get the WillClose message, the client side is going to go away
553 : // soon and we can't be guaranteed that sending messages will work.
554 0 : mCanSend = false;
555 0 : return IPC_OK();
556 : }
557 :
558 0 : void CompositorBridgeParent::DeferredDestroy()
559 : {
560 0 : MOZ_ASSERT(!NS_IsMainThread());
561 0 : mSelfRef = nullptr;
562 0 : }
563 :
564 : mozilla::ipc::IPCResult
565 0 : CompositorBridgeParent::RecvPause()
566 : {
567 0 : PauseComposition();
568 0 : return IPC_OK();
569 : }
570 :
571 : mozilla::ipc::IPCResult
572 0 : CompositorBridgeParent::RecvResume()
573 : {
574 0 : ResumeComposition();
575 0 : return IPC_OK();
576 : }
577 :
578 : mozilla::ipc::IPCResult
579 0 : CompositorBridgeParent::RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
580 : const gfx::IntRect& aRect)
581 : {
582 0 : RefPtr<DrawTarget> target = GetDrawTargetForDescriptor(aInSnapshot, gfx::BackendType::CAIRO);
583 0 : MOZ_ASSERT(target);
584 0 : if (!target) {
585 : // We kill the content process rather than have it continue with an invalid
586 : // snapshot, that may be too harsh and we could decide to return some sort
587 : // of error to the child process and let it deal with it...
588 0 : return IPC_FAIL_NO_REASON(this);
589 : }
590 0 : ForceComposeToTarget(target, &aRect);
591 : return IPC_OK();
592 : }
593 :
594 : mozilla::ipc::IPCResult
595 0 : CompositorBridgeParent::RecvWaitOnTransactionProcessed()
596 : {
597 0 : return IPC_OK();
598 : }
599 :
600 : mozilla::ipc::IPCResult
601 0 : CompositorBridgeParent::RecvFlushRendering()
602 : {
603 0 : if (mWrBridge) {
604 0 : mWrBridge->FlushRendering();
605 : return IPC_OK();
606 : }
607 :
608 0 : if (mCompositorScheduler->NeedsComposite()) {
609 0 : CancelCurrentCompositeTask();
610 0 : ForceComposeToTarget(nullptr);
611 : }
612 : return IPC_OK();
613 : }
614 :
615 : mozilla::ipc::IPCResult
616 0 : CompositorBridgeParent::RecvFlushRenderingAsync()
617 : {
618 0 : if (mWrBridge) {
619 0 : mWrBridge->FlushRenderingAsync();
620 : return IPC_OK();
621 : }
622 :
623 0 : return RecvFlushRendering();
624 : }
625 :
626 : mozilla::ipc::IPCResult
627 0 : CompositorBridgeParent::RecvForcePresent()
628 : {
629 0 : if (mWrBridge) {
630 0 : mWrBridge->ScheduleGenerateFrame();
631 : }
632 : // During the shutdown sequence mLayerManager may be null
633 0 : if (mLayerManager) {
634 0 : mLayerManager->ForcePresent();
635 : }
636 0 : return IPC_OK();
637 : }
638 :
639 : mozilla::ipc::IPCResult
640 0 : CompositorBridgeParent::RecvNotifyRegionInvalidated(const nsIntRegion& aRegion)
641 : {
642 0 : if (mLayerManager) {
643 0 : mLayerManager->AddInvalidRegion(aRegion);
644 : }
645 0 : return IPC_OK();
646 : }
647 :
648 : void
649 0 : CompositorBridgeParent::Invalidate()
650 : {
651 0 : if (mLayerManager) {
652 0 : mLayerManager->InvalidateAll();
653 : }
654 0 : }
655 :
656 : mozilla::ipc::IPCResult
657 0 : CompositorBridgeParent::RecvStartFrameTimeRecording(const int32_t& aBufferSize, uint32_t* aOutStartIndex)
658 : {
659 0 : if (mLayerManager) {
660 0 : *aOutStartIndex = mLayerManager->StartFrameTimeRecording(aBufferSize);
661 : } else {
662 0 : *aOutStartIndex = 0;
663 : }
664 0 : return IPC_OK();
665 : }
666 :
667 : mozilla::ipc::IPCResult
668 0 : CompositorBridgeParent::RecvStopFrameTimeRecording(const uint32_t& aStartIndex,
669 : InfallibleTArray<float>* intervals)
670 : {
671 0 : if (mLayerManager) {
672 0 : mLayerManager->StopFrameTimeRecording(aStartIndex, *intervals);
673 : }
674 0 : return IPC_OK();
675 : }
676 :
677 : void
678 0 : CompositorBridgeParent::ActorDestroy(ActorDestroyReason why)
679 : {
680 0 : mCanSend = false;
681 :
682 0 : StopAndClearResources();
683 :
684 0 : RemoveCompositor(mCompositorBridgeID);
685 :
686 0 : mCompositionManager = nullptr;
687 :
688 : { // scope lock
689 0 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
690 0 : sIndirectLayerTrees.erase(mRootLayerTreeID);
691 : }
692 :
693 : // There are chances that the ref count reaches zero on the main thread shortly
694 : // after this function returns while some ipdl code still needs to run on
695 : // this thread.
696 : // We must keep the compositor parent alive untill the code handling message
697 : // reception is finished on this thread.
698 0 : mSelfRef = this;
699 0 : MessageLoop::current()->PostTask(
700 0 : NewRunnableMethod("layers::CompositorBridgeParent::DeferredDestroy",
701 : this,
702 0 : &CompositorBridgeParent::DeferredDestroy));
703 0 : }
704 :
705 : void
706 0 : CompositorBridgeParent::ScheduleRenderOnCompositorThread()
707 : {
708 0 : MOZ_ASSERT(CompositorLoop());
709 0 : CompositorLoop()->PostTask(
710 0 : NewRunnableMethod("layers::CompositorBridgeParent::ScheduleComposition",
711 : this,
712 0 : &CompositorBridgeParent::ScheduleComposition));
713 0 : }
714 :
715 : void
716 0 : CompositorBridgeParent::InvalidateOnCompositorThread()
717 : {
718 0 : MOZ_ASSERT(CompositorLoop());
719 0 : CompositorLoop()->PostTask(
720 0 : NewRunnableMethod("layers::CompositorBridgeParent::Invalidate",
721 : this,
722 0 : &CompositorBridgeParent::Invalidate));
723 0 : }
724 :
725 : void
726 0 : CompositorBridgeParent::PauseComposition()
727 : {
728 0 : MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread(),
729 : "PauseComposition() can only be called on the compositor thread");
730 :
731 0 : MonitorAutoLock lock(mPauseCompositionMonitor);
732 :
733 0 : if (!mPaused) {
734 0 : mPaused = true;
735 :
736 0 : if (mCompositor) {
737 0 : mCompositor->Pause();
738 0 : } else if (mWrBridge) {
739 0 : mWrBridge->Pause();
740 : }
741 0 : TimeStamp now = TimeStamp::Now();
742 0 : DidComposite(now, now);
743 : }
744 :
745 : // if anyone's waiting to make sure that composition really got paused, tell them
746 0 : lock.NotifyAll();
747 0 : }
748 :
749 : void
750 0 : CompositorBridgeParent::ResumeComposition()
751 : {
752 0 : MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread(),
753 : "ResumeComposition() can only be called on the compositor thread");
754 :
755 0 : MonitorAutoLock lock(mResumeCompositionMonitor);
756 :
757 0 : bool resumed = mOptions.UseWebRender() ? mWrBridge->Resume() : mCompositor->Resume();
758 0 : if (!resumed) {
759 : #ifdef MOZ_WIDGET_ANDROID
760 : // We can't get a surface. This could be because the activity changed between
761 : // the time resume was scheduled and now.
762 : __android_log_print(ANDROID_LOG_INFO, "CompositorBridgeParent", "Unable to renew compositor surface; remaining in paused state");
763 : #endif
764 0 : lock.NotifyAll();
765 0 : return;
766 : }
767 :
768 0 : mPaused = false;
769 :
770 0 : Invalidate();
771 0 : mCompositorScheduler->ForceComposeToTarget(nullptr, nullptr);
772 :
773 : // if anyone's waiting to make sure that composition really got resumed, tell them
774 0 : lock.NotifyAll();
775 : }
776 :
777 : void
778 0 : CompositorBridgeParent::ForceComposition()
779 : {
780 : // Cancel the orientation changed state to force composition
781 0 : mForceCompositionTask = nullptr;
782 0 : ScheduleRenderOnCompositorThread();
783 0 : }
784 :
785 : void
786 0 : CompositorBridgeParent::CancelCurrentCompositeTask()
787 : {
788 0 : mCompositorScheduler->CancelCurrentCompositeTask();
789 0 : }
790 :
791 : void
792 0 : CompositorBridgeParent::SetEGLSurfaceSize(int width, int height)
793 : {
794 0 : NS_ASSERTION(mUseExternalSurfaceSize, "Compositor created without UseExternalSurfaceSize provided");
795 0 : mEGLSurfaceSize.SizeTo(width, height);
796 0 : if (mCompositor) {
797 0 : mCompositor->SetDestinationSurfaceSize(gfx::IntSize(mEGLSurfaceSize.width, mEGLSurfaceSize.height));
798 : }
799 0 : }
800 :
801 : void
802 0 : CompositorBridgeParent::ResumeCompositionAndResize(int width, int height)
803 : {
804 0 : SetEGLSurfaceSize(width, height);
805 0 : ResumeComposition();
806 0 : }
807 :
808 : /*
809 : * This will execute a pause synchronously, waiting to make sure that the compositor
810 : * really is paused.
811 : */
812 : void
813 0 : CompositorBridgeParent::SchedulePauseOnCompositorThread()
814 : {
815 0 : MonitorAutoLock lock(mPauseCompositionMonitor);
816 :
817 0 : MOZ_ASSERT(CompositorLoop());
818 0 : CompositorLoop()->PostTask(
819 0 : NewRunnableMethod("layers::CompositorBridgeParent::PauseComposition",
820 : this,
821 0 : &CompositorBridgeParent::PauseComposition));
822 :
823 : // Wait until the pause has actually been processed by the compositor thread
824 0 : lock.Wait();
825 0 : }
826 :
827 : bool
828 0 : CompositorBridgeParent::ScheduleResumeOnCompositorThread()
829 : {
830 0 : MonitorAutoLock lock(mResumeCompositionMonitor);
831 :
832 0 : MOZ_ASSERT(CompositorLoop());
833 0 : CompositorLoop()->PostTask(
834 0 : NewRunnableMethod("layers::CompositorBridgeParent::ResumeComposition",
835 : this,
836 0 : &CompositorBridgeParent::ResumeComposition));
837 :
838 : // Wait until the resume has actually been processed by the compositor thread
839 0 : lock.Wait();
840 :
841 0 : return !mPaused;
842 : }
843 :
844 : bool
845 0 : CompositorBridgeParent::ScheduleResumeOnCompositorThread(int width, int height)
846 : {
847 0 : MonitorAutoLock lock(mResumeCompositionMonitor);
848 :
849 0 : MOZ_ASSERT(CompositorLoop());
850 0 : CompositorLoop()->PostTask(NewRunnableMethod<int, int>(
851 : "layers::CompositorBridgeParent::ResumeCompositionAndResize",
852 : this,
853 : &CompositorBridgeParent::ResumeCompositionAndResize,
854 : width,
855 0 : height));
856 :
857 : // Wait until the resume has actually been processed by the compositor thread
858 0 : lock.Wait();
859 :
860 0 : return !mPaused;
861 : }
862 :
863 : void
864 0 : CompositorBridgeParent::ScheduleTask(already_AddRefed<CancelableRunnable> task, int time)
865 : {
866 0 : if (time == 0) {
867 0 : MessageLoop::current()->PostTask(std::move(task));
868 : } else {
869 0 : MessageLoop::current()->PostDelayedTask(std::move(task), time);
870 : }
871 0 : }
872 :
873 : void
874 0 : CompositorBridgeParent::UpdatePaintTime(LayerTransactionParent* aLayerTree,
875 : const TimeDuration& aPaintTime)
876 : {
877 : // We get a lot of paint timings for things with empty transactions.
878 0 : if (!mLayerManager || aPaintTime.ToMilliseconds() < 1.0) {
879 : return;
880 : }
881 :
882 0 : mLayerManager->SetPaintTime(aPaintTime);
883 : }
884 :
885 : void
886 0 : CompositorBridgeParent::NotifyShadowTreeTransaction(LayersId aId, bool aIsFirstPaint,
887 : const FocusTarget& aFocusTarget,
888 : bool aScheduleComposite, uint32_t aPaintSequenceNumber,
889 : bool aIsRepeatTransaction, bool aHitTestUpdate)
890 : {
891 4 : if (!aIsRepeatTransaction &&
892 0 : mLayerManager &&
893 4 : mLayerManager->GetRoot()) {
894 : // Process plugin data here to give time for them to update before the next
895 : // composition.
896 0 : bool pluginsUpdatedFlag = true;
897 : AutoResolveRefLayers resolve(mCompositionManager, this, nullptr,
898 0 : &pluginsUpdatedFlag);
899 :
900 : #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
901 : // If plugins haven't been updated, stop waiting.
902 0 : if (!pluginsUpdatedFlag) {
903 0 : mWaitForPluginsUntil = TimeStamp();
904 0 : mHaveBlockedForPlugins = false;
905 : }
906 : #endif
907 :
908 0 : if (mApzUpdater) {
909 0 : mApzUpdater->UpdateFocusState(mRootLayerTreeID, aId, aFocusTarget);
910 0 : if (aHitTestUpdate) {
911 0 : mApzUpdater->UpdateHitTestingTree(mRootLayerTreeID,
912 0 : mLayerManager->GetRoot(), aIsFirstPaint, aId, aPaintSequenceNumber);
913 : }
914 : }
915 :
916 0 : mLayerManager->NotifyShadowTreeTransaction();
917 : }
918 0 : if (aScheduleComposite) {
919 2 : ScheduleComposition();
920 : }
921 0 : }
922 :
923 : void
924 10 : CompositorBridgeParent::ScheduleComposition()
925 : {
926 1 : MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
927 10 : if (mPaused) {
928 : return;
929 : }
930 :
931 20 : if (mWrBridge) {
932 0 : mWrBridge->ScheduleGenerateFrame();
933 : } else {
934 10 : mCompositorScheduler->ScheduleComposition();
935 : }
936 : }
937 :
938 : // Go down the composite layer tree, setting properties to match their
939 : // content-side counterparts.
940 : /* static */ void
941 0 : CompositorBridgeParent::SetShadowProperties(Layer* aLayer)
942 : {
943 17 : ForEachNode<ForwardIterator>(
944 : aLayer,
945 0 : [] (Layer *layer)
946 : {
947 40 : if (Layer* maskLayer = layer->GetMaskLayer()) {
948 0 : SetShadowProperties(maskLayer);
949 : }
950 40 : for (size_t i = 0; i < layer->GetAncestorMaskLayerCount(); i++) {
951 0 : SetShadowProperties(layer->GetAncestorMaskLayerAt(i));
952 : }
953 :
954 : // FIXME: Bug 717688 -- Do these updates in LayerTransactionParent::RecvUpdate.
955 0 : HostLayer* layerCompositor = layer->AsHostLayer();
956 : // Set the layerComposite's base transform to the layer's base transform.
957 0 : AnimationArray& animations = layer->GetAnimations();
958 : // If there is any animation, the animation value will override
959 : // non-animated value later, so we don't need to set the non-animated
960 : // value here.
961 0 : if (animations.IsEmpty()) {
962 0 : layerCompositor->SetShadowBaseTransform(layer->GetBaseTransform());
963 0 : layerCompositor->SetShadowTransformSetByAnimation(false);
964 0 : layerCompositor->SetShadowOpacity(layer->GetOpacity());
965 : layerCompositor->SetShadowOpacitySetByAnimation(false);
966 : }
967 80 : layerCompositor->SetShadowVisibleRegion(layer->GetVisibleRegion());
968 0 : layerCompositor->SetShadowClipRect(layer->GetClipRect());
969 40 : }
970 0 : );
971 0 : }
972 :
973 : void
974 9 : CompositorBridgeParent::CompositeToTarget(DrawTarget* aTarget, const gfx::IntRect* aRect)
975 : {
976 16 : AUTO_PROFILER_TRACING("Paint", "Composite");
977 0 : AUTO_PROFILER_LABEL("CompositorBridgeParent::CompositeToTarget", GRAPHICS);
978 :
979 0 : MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread(),
980 : "Composite can only be called on the compositor thread");
981 9 : TimeStamp start = TimeStamp::Now();
982 :
983 9 : if (!CanComposite()) {
984 0 : TimeStamp end = TimeStamp::Now();
985 1 : DidComposite(start, end);
986 : return;
987 : }
988 :
989 : #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
990 14 : if (!mWaitForPluginsUntil.IsNull() &&
991 0 : mWaitForPluginsUntil > start) {
992 0 : mHaveBlockedForPlugins = true;
993 0 : ScheduleComposition();
994 0 : return;
995 : }
996 : #endif
997 :
998 : /*
999 : * AutoResolveRefLayers handles two tasks related to Windows and Linux
1000 : * plugin window management:
1001 : * 1) calculating if we have remote content in the view. If we do not have
1002 : * remote content, all plugin windows for this CompositorBridgeParent (window)
1003 : * can be hidden since we do not support plugins in chrome when running
1004 : * under e10s.
1005 : * 2) Updating plugin position, size, and clip. We do this here while the
1006 : * remote layer tree is hooked up to to chrome layer tree. This is needed
1007 : * since plugin clipping can depend on chrome (for example, due to tab modal
1008 : * prompts). Updates in step 2 are applied via an async ipc message sent
1009 : * to the main thread.
1010 : */
1011 7 : bool hasRemoteContent = false;
1012 7 : bool updatePluginsFlag = true;
1013 : AutoResolveRefLayers resolve(mCompositionManager, this,
1014 : &hasRemoteContent,
1015 0 : &updatePluginsFlag);
1016 :
1017 : #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
1018 : // We do not support plugins in local content. When switching tabs
1019 : // to local pages, hide every plugin associated with the window.
1020 14 : if (!hasRemoteContent && gfxVars::BrowserTabsRemoteAutostart() &&
1021 0 : mCachedPluginData.Length()) {
1022 0 : Unused << SendHideAllPlugins(GetWidget()->GetWidgetKey());
1023 0 : mCachedPluginData.Clear();
1024 : }
1025 : #endif
1026 :
1027 0 : if (aTarget) {
1028 0 : mLayerManager->BeginTransactionWithDrawTarget(aTarget, *aRect);
1029 : } else {
1030 1 : mLayerManager->BeginTransaction();
1031 : }
1032 :
1033 14 : SetShadowProperties(mLayerManager->GetRoot());
1034 :
1035 14 : if (mForceCompositionTask && !mOverrideComposeReadiness) {
1036 0 : if (mCompositionManager->ReadyForCompose()) {
1037 0 : mForceCompositionTask->Cancel();
1038 0 : mForceCompositionTask = nullptr;
1039 : } else {
1040 0 : return;
1041 : }
1042 : }
1043 :
1044 7 : mCompositionManager->ComputeRotation();
1045 :
1046 7 : TimeStamp time = mTestTime.valueOr(mCompositorScheduler->GetLastComposeTime());
1047 0 : bool requestNextFrame = mCompositionManager->TransformShadowTree(time, mVsyncRate);
1048 1 : if (requestNextFrame) {
1049 0 : ScheduleComposition();
1050 : #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
1051 : // If we have visible windowed plugins then we need to wait for content (and
1052 : // then the plugins) to have been updated by the active animation.
1053 0 : if (!mPluginWindowsHidden && mCachedPluginData.Length()) {
1054 0 : mWaitForPluginsUntil = mCompositorScheduler->GetLastComposeTime() + (mVsyncRate * 2);
1055 : }
1056 : #endif
1057 : }
1058 :
1059 14 : RenderTraceLayers(mLayerManager->GetRoot(), "0000");
1060 :
1061 : #ifdef MOZ_DUMP_PAINTING
1062 0 : if (gfxPrefs::DumpHostLayers()) {
1063 0 : printf_stderr("Painting --- compositing layer tree:\n");
1064 0 : mLayerManager->Dump(/* aSorted = */ true);
1065 : }
1066 : #endif
1067 14 : mLayerManager->SetDebugOverlayWantsNextFrame(false);
1068 7 : mLayerManager->EndTransaction(time);
1069 :
1070 7 : if (!aTarget) {
1071 7 : TimeStamp end = TimeStamp::Now();
1072 7 : DidComposite(start, end);
1073 : }
1074 :
1075 : // We're not really taking advantage of the stored composite-again-time here.
1076 : // We might be able to skip the next few composites altogether. However,
1077 : // that's a bit complex to implement and we'll get most of the advantage
1078 : // by skipping compositing when we detect there's nothing invalid. This is why
1079 : // we do "composite until" rather than "composite again at".
1080 : //
1081 : // TODO(bug 1328602) Figure out what we should do here with the render thread.
1082 14 : if (!mLayerManager->GetCompositeUntilTime().IsNull() ||
1083 7 : mLayerManager->DebugOverlayWantsNextFrame())
1084 : {
1085 0 : ScheduleComposition();
1086 : }
1087 :
1088 : #ifdef COMPOSITOR_PERFORMANCE_WARNING
1089 : TimeDuration executionTime = TimeStamp::Now() - mCompositorScheduler->GetLastComposeTime();
1090 : TimeDuration frameBudget = TimeDuration::FromMilliseconds(15);
1091 : int32_t frameRate = CalculateCompositionFrameRate();
1092 : if (frameRate > 0) {
1093 : frameBudget = TimeDuration::FromSeconds(1.0 / frameRate);
1094 : }
1095 : if (executionTime > frameBudget) {
1096 : printf_stderr("Compositor: Composite execution took %4.1f ms\n",
1097 : executionTime.ToMilliseconds());
1098 : }
1099 : #endif
1100 :
1101 : // 0 -> Full-tilt composite
1102 14 : if (gfxPrefs::LayersCompositionFrameRate() == 0 ||
1103 7 : mLayerManager->AlwaysScheduleComposite())
1104 : {
1105 : // Special full-tilt composite mode for performance testing
1106 0 : ScheduleComposition();
1107 : }
1108 :
1109 : // TODO(bug 1328602) Need an equivalent that works with the rende thread.
1110 1 : mLayerManager->SetCompositionTime(TimeStamp());
1111 :
1112 7 : mozilla::Telemetry::AccumulateTimeDelta(mozilla::Telemetry::COMPOSITE_TIME, start);
1113 : }
1114 :
1115 : mozilla::ipc::IPCResult
1116 0 : CompositorBridgeParent::RecvRemotePluginsReady()
1117 : {
1118 : #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
1119 0 : mWaitForPluginsUntil = TimeStamp();
1120 0 : if (mHaveBlockedForPlugins) {
1121 0 : mHaveBlockedForPlugins = false;
1122 0 : ForceComposeToTarget(nullptr);
1123 : } else {
1124 0 : ScheduleComposition();
1125 : }
1126 0 : return IPC_OK();
1127 : #else
1128 : NS_NOTREACHED("CompositorBridgeParent::RecvRemotePluginsReady calls "
1129 : "unexpected on this platform.");
1130 : return IPC_FAIL_NO_REASON(this);
1131 : #endif
1132 : }
1133 :
1134 : void
1135 0 : CompositorBridgeParent::ForceComposeToTarget(DrawTarget* aTarget, const gfx::IntRect* aRect)
1136 : {
1137 0 : AUTO_PROFILER_LABEL("CompositorBridgeParent::ForceComposeToTarget", GRAPHICS);
1138 :
1139 0 : AutoRestore<bool> override(mOverrideComposeReadiness);
1140 0 : mOverrideComposeReadiness = true;
1141 0 : mCompositorScheduler->ForceComposeToTarget(aTarget, aRect);
1142 0 : }
1143 :
1144 : PAPZCTreeManagerParent*
1145 0 : CompositorBridgeParent::AllocPAPZCTreeManagerParent(const LayersId& aLayersId)
1146 : {
1147 : // This should only ever get called in the GPU process.
1148 0 : MOZ_ASSERT(XRE_IsGPUProcess());
1149 : // We should only ever get this if APZ is enabled in this compositor.
1150 0 : MOZ_ASSERT(mOptions.UseAPZ());
1151 : // The mApzcTreeManager and mApzUpdater should have been created via RecvInitialize()
1152 0 : MOZ_ASSERT(mApzcTreeManager);
1153 0 : MOZ_ASSERT(mApzUpdater);
1154 : // The main process should pass in 0 because we assume mRootLayerTreeID
1155 0 : MOZ_ASSERT(!aLayersId.IsValid());
1156 :
1157 0 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
1158 0 : CompositorBridgeParent::LayerTreeState& state = sIndirectLayerTrees[mRootLayerTreeID];
1159 0 : MOZ_ASSERT(state.mParent.get() == this);
1160 0 : MOZ_ASSERT(!state.mApzcTreeManagerParent);
1161 0 : state.mApzcTreeManagerParent = new APZCTreeManagerParent(mRootLayerTreeID, mApzcTreeManager, mApzUpdater);
1162 :
1163 0 : return state.mApzcTreeManagerParent;
1164 : }
1165 :
1166 : bool
1167 0 : CompositorBridgeParent::DeallocPAPZCTreeManagerParent(PAPZCTreeManagerParent* aActor)
1168 : {
1169 0 : delete aActor;
1170 0 : return true;
1171 : }
1172 :
1173 : void
1174 0 : CompositorBridgeParent::AllocateAPZCTreeManagerParent(const MonitorAutoLock& aProofOfLayerTreeStateLock,
1175 : const LayersId& aLayersId,
1176 : LayerTreeState& aState)
1177 : {
1178 2 : MOZ_ASSERT(aState.mParent == this);
1179 2 : MOZ_ASSERT(mApzcTreeManager);
1180 1 : MOZ_ASSERT(mApzUpdater);
1181 1 : MOZ_ASSERT(!aState.mApzcTreeManagerParent);
1182 2 : aState.mApzcTreeManagerParent = new APZCTreeManagerParent(aLayersId, mApzcTreeManager, mApzUpdater);
1183 1 : }
1184 :
1185 : PAPZParent*
1186 0 : CompositorBridgeParent::AllocPAPZParent(const LayersId& aLayersId)
1187 : {
1188 : // The main process should pass in 0 because we assume mRootLayerTreeID
1189 0 : MOZ_ASSERT(!aLayersId.IsValid());
1190 :
1191 0 : RemoteContentController* controller = new RemoteContentController();
1192 :
1193 : // Increment the controller's refcount before we return it. This will keep the
1194 : // controller alive until it is released by IPDL in DeallocPAPZParent.
1195 0 : controller->AddRef();
1196 :
1197 0 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
1198 0 : CompositorBridgeParent::LayerTreeState& state = sIndirectLayerTrees[mRootLayerTreeID];
1199 0 : MOZ_ASSERT(!state.mController);
1200 0 : state.mController = controller;
1201 :
1202 0 : return controller;
1203 : }
1204 :
1205 : bool
1206 0 : CompositorBridgeParent::DeallocPAPZParent(PAPZParent* aActor)
1207 : {
1208 0 : RemoteContentController* controller = static_cast<RemoteContentController*>(aActor);
1209 0 : controller->Release();
1210 0 : return true;
1211 : }
1212 :
1213 : #if defined(MOZ_WIDGET_ANDROID)
1214 : AndroidDynamicToolbarAnimator*
1215 : CompositorBridgeParent::GetAndroidDynamicToolbarAnimator()
1216 : {
1217 : return mApzcTreeManager ? mApzcTreeManager->GetAndroidDynamicToolbarAnimator() : nullptr;
1218 : }
1219 : #endif
1220 :
1221 : RefPtr<APZSampler>
1222 1 : CompositorBridgeParent::GetAPZSampler()
1223 : {
1224 0 : return mApzSampler;
1225 : }
1226 :
1227 : RefPtr<APZUpdater>
1228 0 : CompositorBridgeParent::GetAPZUpdater()
1229 : {
1230 0 : return mApzUpdater;
1231 : }
1232 :
1233 : CompositorBridgeParent*
1234 0 : CompositorBridgeParent::GetCompositorBridgeParentFromLayersId(const LayersId& aLayersId)
1235 : {
1236 0 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
1237 0 : return sIndirectLayerTrees[aLayersId].mParent;
1238 : }
1239 :
1240 : /*static*/ RefPtr<CompositorBridgeParent>
1241 0 : CompositorBridgeParent::GetCompositorBridgeParentFromWindowId(const wr::WindowId& aWindowId)
1242 : {
1243 0 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
1244 0 : for (auto it = sIndirectLayerTrees.begin(); it != sIndirectLayerTrees.end(); it++) {
1245 0 : LayerTreeState* state = &it->second;
1246 0 : if (!state->mWrBridge) {
1247 : continue;
1248 : }
1249 : // state->mWrBridge might be a root WebRenderBridgeParent or one of a content
1250 : // process, but in either case the state->mParent will be the same. So we
1251 : // don't need to distinguish between the two.
1252 0 : if (RefPtr<wr::WebRenderAPI> api = state->mWrBridge->GetWebRenderAPI()) {
1253 0 : if (api->GetId() == aWindowId) {
1254 0 : return state->mParent;
1255 : }
1256 : }
1257 : }
1258 : return nullptr;
1259 : }
1260 :
1261 : bool
1262 9 : CompositorBridgeParent::CanComposite()
1263 : {
1264 0 : return mLayerManager &&
1265 34 : mLayerManager->GetRoot() &&
1266 16 : !mPaused;
1267 : }
1268 :
1269 : void
1270 0 : CompositorBridgeParent::ScheduleRotationOnCompositorThread(const TargetConfig& aTargetConfig,
1271 : bool aIsFirstPaint)
1272 : {
1273 1 : MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
1274 :
1275 0 : if (!aIsFirstPaint &&
1276 16 : !mCompositionManager->IsFirstPaint() &&
1277 12 : mCompositionManager->RequiresReorientation(aTargetConfig.orientation())) {
1278 0 : if (mForceCompositionTask != nullptr) {
1279 0 : mForceCompositionTask->Cancel();
1280 : }
1281 0 : RefPtr<CancelableRunnable> task = NewCancelableRunnableMethod(
1282 : "layers::CompositorBridgeParent::ForceComposition",
1283 : this,
1284 0 : &CompositorBridgeParent::ForceComposition);
1285 0 : mForceCompositionTask = task;
1286 0 : ScheduleTask(task.forget(), gfxPrefs::OrientationSyncMillis());
1287 : }
1288 10 : }
1289 :
1290 : void
1291 0 : CompositorBridgeParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
1292 : const TransactionInfo& aInfo,
1293 : bool aHitTestUpdate)
1294 : {
1295 8 : const TargetConfig& targetConfig = aInfo.targetConfig();
1296 :
1297 0 : ScheduleRotationOnCompositorThread(targetConfig, aInfo.isFirstPaint());
1298 :
1299 : // Instruct the LayerManager to update its render bounds now. Since all the orientation
1300 : // change, dimension change would be done at the stage, update the size here is free of
1301 : // race condition.
1302 0 : mLayerManager->UpdateRenderBounds(targetConfig.naturalBounds());
1303 0 : mLayerManager->SetRegionToClear(targetConfig.clearRegion());
1304 0 : if (mLayerManager->GetCompositor()) {
1305 8 : mLayerManager->GetCompositor()->SetScreenRotation(targetConfig.rotation());
1306 : }
1307 :
1308 8 : mCompositionManager->Updated(aInfo.isFirstPaint(), targetConfig);
1309 0 : Layer* root = aLayerTree->GetRoot();
1310 8 : mLayerManager->SetRoot(root);
1311 :
1312 0 : if (mApzUpdater && !aInfo.isRepeatTransaction()) {
1313 8 : mApzUpdater->UpdateFocusState(mRootLayerTreeID,
1314 : mRootLayerTreeID,
1315 0 : aInfo.focusTarget());
1316 :
1317 8 : if (aHitTestUpdate) {
1318 3 : AutoResolveRefLayers resolve(mCompositionManager);
1319 :
1320 2 : mApzUpdater->UpdateHitTestingTree(
1321 1 : mRootLayerTreeID, root, aInfo.isFirstPaint(),
1322 2 : mRootLayerTreeID, aInfo.paintSequenceNumber());
1323 : }
1324 : }
1325 :
1326 : // The transaction ID might get reset to 1 if the page gets reloaded, see
1327 : // https://bugzilla.mozilla.org/show_bug.cgi?id=1145295#c41
1328 : // Otherwise, it should be continually increasing.
1329 0 : MOZ_ASSERT(aInfo.id() == TransactionId{1} || aInfo.id() > mPendingTransaction);
1330 8 : mPendingTransaction = aInfo.id();
1331 0 : mTxnStartTime = aInfo.transactionStart();
1332 0 : mFwdTime = aInfo.fwdTime();
1333 :
1334 1 : if (root) {
1335 1 : SetShadowProperties(root);
1336 : }
1337 8 : if (aInfo.scheduleComposite()) {
1338 0 : ScheduleComposition();
1339 0 : if (mPaused) {
1340 0 : TimeStamp now = TimeStamp::Now();
1341 0 : DidComposite(now, now);
1342 : }
1343 : }
1344 0 : mLayerManager->NotifyShadowTreeTransaction();
1345 0 : }
1346 :
1347 : void
1348 0 : CompositorBridgeParent::ScheduleComposite(LayerTransactionParent* aLayerTree)
1349 : {
1350 0 : ScheduleComposition();
1351 0 : }
1352 :
1353 : bool
1354 0 : CompositorBridgeParent::SetTestSampleTime(const LayersId& aId,
1355 : const TimeStamp& aTime)
1356 : {
1357 0 : MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
1358 :
1359 0 : if (aTime.IsNull()) {
1360 : return false;
1361 : }
1362 :
1363 0 : mTestTime = Some(aTime);
1364 :
1365 0 : if (mWrBridge) {
1366 0 : mWrBridge->FlushRendering();
1367 0 : return true;
1368 : }
1369 :
1370 0 : bool testComposite = mCompositionManager &&
1371 0 : mCompositorScheduler->NeedsComposite();
1372 :
1373 : // Update but only if we were already scheduled to animate
1374 0 : if (testComposite) {
1375 0 : AutoResolveRefLayers resolve(mCompositionManager);
1376 0 : bool requestNextFrame = mCompositionManager->TransformShadowTree(aTime, mVsyncRate);
1377 0 : if (!requestNextFrame) {
1378 0 : CancelCurrentCompositeTask();
1379 : // Pretend we composited in case someone is wating for this event.
1380 0 : TimeStamp now = TimeStamp::Now();
1381 0 : DidComposite(now, now);
1382 : }
1383 : }
1384 :
1385 : return true;
1386 : }
1387 :
1388 : void
1389 0 : CompositorBridgeParent::LeaveTestMode(const LayersId& aId)
1390 : {
1391 0 : mTestTime = Nothing();
1392 0 : }
1393 :
1394 : void
1395 0 : CompositorBridgeParent::ApplyAsyncProperties(LayerTransactionParent* aLayerTree,
1396 : TransformsToSkip aSkip)
1397 : {
1398 : // NOTE: This should only be used for testing. For example, when mTestTime is
1399 : // non-empty, or when called from test-only methods like
1400 : // LayerTransactionParent::RecvGetAnimationTransform.
1401 :
1402 : // Synchronously update the layer tree
1403 0 : if (aLayerTree->GetRoot()) {
1404 0 : AutoResolveRefLayers resolve(mCompositionManager);
1405 0 : SetShadowProperties(mLayerManager->GetRoot());
1406 :
1407 0 : TimeStamp time = mTestTime.valueOr(mCompositorScheduler->GetLastComposeTime());
1408 : bool requestNextFrame =
1409 0 : mCompositionManager->TransformShadowTree(time, mVsyncRate, aSkip);
1410 0 : if (!requestNextFrame) {
1411 0 : CancelCurrentCompositeTask();
1412 : // Pretend we composited in case someone is waiting for this event.
1413 0 : TimeStamp now = TimeStamp::Now();
1414 0 : DidComposite(now, now);
1415 : }
1416 : }
1417 0 : }
1418 :
1419 : CompositorAnimationStorage*
1420 9 : CompositorBridgeParent::GetAnimationStorage()
1421 : {
1422 18 : if (!mAnimationStorage) {
1423 1 : mAnimationStorage = new CompositorAnimationStorage();
1424 : }
1425 1 : return mAnimationStorage;
1426 : }
1427 :
1428 : mozilla::ipc::IPCResult
1429 0 : CompositorBridgeParent::RecvGetFrameUniformity(FrameUniformityData* aOutData)
1430 : {
1431 0 : mCompositionManager->GetFrameUniformity(aOutData);
1432 0 : return IPC_OK();
1433 : }
1434 :
1435 : void
1436 0 : CompositorBridgeParent::SetTestAsyncScrollOffset(
1437 : const LayersId& aLayersId,
1438 : const FrameMetrics::ViewID& aScrollId,
1439 : const CSSPoint& aPoint)
1440 : {
1441 0 : if (mApzUpdater) {
1442 0 : MOZ_ASSERT(aLayersId.IsValid());
1443 0 : mApzUpdater->SetTestAsyncScrollOffset(aLayersId, aScrollId, aPoint);
1444 : }
1445 0 : }
1446 :
1447 : void
1448 0 : CompositorBridgeParent::SetTestAsyncZoom(
1449 : const LayersId& aLayersId,
1450 : const FrameMetrics::ViewID& aScrollId,
1451 : const LayerToParentLayerScale& aZoom)
1452 : {
1453 0 : if (mApzUpdater) {
1454 0 : MOZ_ASSERT(aLayersId.IsValid());
1455 0 : mApzUpdater->SetTestAsyncZoom(aLayersId, aScrollId, aZoom);
1456 : }
1457 0 : }
1458 :
1459 : void
1460 0 : CompositorBridgeParent::FlushApzRepaints(const LayersId& aLayersId)
1461 : {
1462 0 : MOZ_ASSERT(mApzcTreeManager);
1463 0 : MOZ_ASSERT(mApzUpdater);
1464 0 : MOZ_ASSERT(aLayersId.IsValid());
1465 0 : RefPtr<CompositorBridgeParent> self = this;
1466 0 : mApzUpdater->RunOnControllerThread(aLayersId, NS_NewRunnableFunction(
1467 : "layers::CompositorBridgeParent::FlushApzRepaints",
1468 0 : [=]() { self->mApzcTreeManager->FlushApzRepaints(aLayersId); }));
1469 0 : }
1470 :
1471 : void
1472 0 : CompositorBridgeParent::GetAPZTestData(const LayersId& aLayersId,
1473 : APZTestData* aOutData)
1474 : {
1475 0 : if (mApzUpdater) {
1476 0 : MOZ_ASSERT(aLayersId.IsValid());
1477 0 : mApzUpdater->GetAPZTestData(aLayersId, aOutData);
1478 : }
1479 0 : }
1480 :
1481 : void
1482 0 : CompositorBridgeParent::SetConfirmedTargetAPZC(const LayersId& aLayersId,
1483 : const uint64_t& aInputBlockId,
1484 : const nsTArray<ScrollableLayerGuid>& aTargets)
1485 : {
1486 0 : if (!mApzcTreeManager || !mApzUpdater) {
1487 0 : return;
1488 : }
1489 : // Need to specifically bind this since it's overloaded.
1490 : void (APZCTreeManager::*setTargetApzcFunc)
1491 : (uint64_t, const nsTArray<ScrollableLayerGuid>&) =
1492 0 : &APZCTreeManager::SetTargetAPZC;
1493 : RefPtr<Runnable> task =
1494 : NewRunnableMethod<uint64_t,
1495 0 : StoreCopyPassByConstLRef<nsTArray<ScrollableLayerGuid>>>(
1496 : "layers::CompositorBridgeParent::SetConfirmedTargetAPZC",
1497 0 : mApzcTreeManager.get(),
1498 : setTargetApzcFunc,
1499 : aInputBlockId,
1500 0 : aTargets);
1501 0 : mApzUpdater->RunOnControllerThread(aLayersId, task.forget());
1502 : }
1503 :
1504 : void
1505 0 : CompositorBridgeParent::InitializeLayerManager(const nsTArray<LayersBackend>& aBackendHints)
1506 : {
1507 1 : NS_ASSERTION(!mLayerManager, "Already initialised mLayerManager");
1508 2 : NS_ASSERTION(!mCompositor, "Already initialised mCompositor");
1509 :
1510 1 : if (!InitializeAdvancedLayers(aBackendHints, nullptr)) {
1511 0 : mCompositor = NewCompositor(aBackendHints);
1512 2 : if (!mCompositor) {
1513 0 : return;
1514 : }
1515 3 : mLayerManager = new LayerManagerComposite(mCompositor);
1516 : }
1517 1 : mLayerManager->SetCompositorBridgeID(mCompositorBridgeID);
1518 :
1519 3 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
1520 2 : sIndirectLayerTrees[mRootLayerTreeID].mLayerManager = mLayerManager;
1521 : }
1522 :
1523 : bool
1524 0 : CompositorBridgeParent::InitializeAdvancedLayers(const nsTArray<LayersBackend>& aBackendHints,
1525 : TextureFactoryIdentifier* aOutIdentifier)
1526 : {
1527 : #ifdef XP_WIN
1528 : if (!mOptions.UseAdvancedLayers()) {
1529 : return false;
1530 : }
1531 :
1532 : // Currently LayerManagerMLGPU hardcodes a D3D11 device, so we reject using
1533 : // AL if LAYERS_D3D11 isn't in the backend hints.
1534 : if (!aBackendHints.Contains(LayersBackend::LAYERS_D3D11)) {
1535 : return false;
1536 : }
1537 :
1538 : RefPtr<LayerManagerMLGPU> manager = new LayerManagerMLGPU(mWidget);
1539 : if (!manager->Initialize()) {
1540 : return false;
1541 : }
1542 :
1543 : if (aOutIdentifier) {
1544 : *aOutIdentifier = manager->GetTextureFactoryIdentifier();
1545 : }
1546 : mLayerManager = manager;
1547 : return true;
1548 : #else
1549 0 : return false;
1550 : #endif
1551 : }
1552 :
1553 : RefPtr<Compositor>
1554 1 : CompositorBridgeParent::NewCompositor(const nsTArray<LayersBackend>& aBackendHints)
1555 : {
1556 2 : for (size_t i = 0; i < aBackendHints.Length(); ++i) {
1557 0 : RefPtr<Compositor> compositor;
1558 0 : if (aBackendHints[i] == LayersBackend::LAYERS_OPENGL) {
1559 : compositor = new CompositorOGL(this,
1560 : mWidget,
1561 : mEGLSurfaceSize.width,
1562 : mEGLSurfaceSize.height,
1563 0 : mUseExternalSurfaceSize);
1564 1 : } else if (aBackendHints[i] == LayersBackend::LAYERS_BASIC) {
1565 : #ifdef MOZ_WIDGET_GTK
1566 1 : if (gfxVars::UseXRender()) {
1567 0 : compositor = new X11BasicCompositor(this, mWidget);
1568 : } else
1569 : #endif
1570 : {
1571 1 : compositor = new BasicCompositor(this, mWidget);
1572 : }
1573 : #ifdef XP_WIN
1574 : } else if (aBackendHints[i] == LayersBackend::LAYERS_D3D11) {
1575 : compositor = new CompositorD3D11(this, mWidget);
1576 : #endif
1577 : }
1578 1 : nsCString failureReason;
1579 :
1580 : // Some software GPU emulation implementations will happily try to create
1581 : // unreasonably big surfaces and then fail in awful ways.
1582 : // Let's at least limit this to the default max texture size we use for content,
1583 : // anything larger than that will fail to render on the content side anyway.
1584 : // We can revisit this value and make it even tighter if need be.
1585 1 : const int max_fb_size = 32767;
1586 0 : const LayoutDeviceIntSize size = mWidget->GetClientSize();
1587 0 : if (size.width > max_fb_size || size.height > max_fb_size) {
1588 0 : failureReason = "FEATURE_FAILURE_MAX_FRAMEBUFFER_SIZE";
1589 1 : return nullptr;
1590 : }
1591 :
1592 1 : MOZ_ASSERT(!gfxVars::UseWebRender() || aBackendHints[i] == LayersBackend::LAYERS_BASIC);
1593 0 : if (compositor && compositor->Initialize(&failureReason)) {
1594 0 : if (failureReason.IsEmpty()){
1595 : failureReason = "SUCCESS";
1596 : }
1597 :
1598 : // should only report success here
1599 2 : if (aBackendHints[i] == LayersBackend::LAYERS_OPENGL){
1600 0 : Telemetry::Accumulate(Telemetry::OPENGL_COMPOSITING_FAILURE_ID, failureReason);
1601 : }
1602 : #ifdef XP_WIN
1603 : else if (aBackendHints[i] == LayersBackend::LAYERS_D3D11){
1604 : Telemetry::Accumulate(Telemetry::D3D11_COMPOSITING_FAILURE_ID, failureReason);
1605 : }
1606 : #endif
1607 :
1608 : return compositor;
1609 : }
1610 :
1611 : // report any failure reasons here
1612 0 : if (aBackendHints[i] == LayersBackend::LAYERS_OPENGL){
1613 0 : gfxCriticalNote << "[OPENGL] Failed to init compositor with reason: "
1614 0 : << failureReason.get();
1615 0 : Telemetry::Accumulate(Telemetry::OPENGL_COMPOSITING_FAILURE_ID, failureReason);
1616 : }
1617 : #ifdef XP_WIN
1618 : else if (aBackendHints[i] == LayersBackend::LAYERS_D3D11){
1619 : gfxCriticalNote << "[D3D11] Failed to init compositor with reason: "
1620 : << failureReason.get();
1621 : Telemetry::Accumulate(Telemetry::D3D11_COMPOSITING_FAILURE_ID, failureReason);
1622 : }
1623 : #endif
1624 : }
1625 :
1626 : return nullptr;
1627 : }
1628 :
1629 : PLayerTransactionParent*
1630 1 : CompositorBridgeParent::AllocPLayerTransactionParent(const nsTArray<LayersBackend>& aBackendHints,
1631 : const LayersId& aId)
1632 : {
1633 1 : MOZ_ASSERT(!aId.IsValid());
1634 :
1635 1 : InitializeLayerManager(aBackendHints);
1636 :
1637 2 : if (!mLayerManager) {
1638 0 : NS_WARNING("Failed to initialise Compositor");
1639 0 : LayerTransactionParent* p = new LayerTransactionParent(/* aManager */ nullptr, this, /* aAnimStorage */ nullptr, mRootLayerTreeID);
1640 0 : p->AddIPDLReference();
1641 0 : return p;
1642 : }
1643 :
1644 4 : mCompositionManager = new AsyncCompositionManager(this, mLayerManager);
1645 :
1646 0 : LayerTransactionParent* p = new LayerTransactionParent(mLayerManager, this, GetAnimationStorage(), mRootLayerTreeID);
1647 1 : p->AddIPDLReference();
1648 0 : return p;
1649 : }
1650 :
1651 : bool
1652 0 : CompositorBridgeParent::DeallocPLayerTransactionParent(PLayerTransactionParent* actor)
1653 : {
1654 0 : static_cast<LayerTransactionParent*>(actor)->ReleaseIPDLReference();
1655 0 : return true;
1656 : }
1657 :
1658 0 : CompositorBridgeParent* CompositorBridgeParent::GetCompositorBridgeParent(uint64_t id)
1659 : {
1660 0 : MOZ_RELEASE_ASSERT(CompositorThreadHolder::IsInCompositorThread());
1661 :
1662 0 : CompositorMap::iterator it = sCompositorMap->find(id);
1663 0 : return it != sCompositorMap->end() ? it->second : nullptr;
1664 : }
1665 :
1666 0 : void CompositorBridgeParent::AddCompositor(CompositorBridgeParent* compositor, uint64_t* outID)
1667 : {
1668 0 : MOZ_RELEASE_ASSERT(CompositorThreadHolder::IsInCompositorThread());
1669 :
1670 : static uint64_t sNextID = 1;
1671 :
1672 1 : ++sNextID;
1673 0 : (*sCompositorMap)[sNextID] = compositor;
1674 1 : *outID = sNextID;
1675 0 : }
1676 :
1677 0 : CompositorBridgeParent* CompositorBridgeParent::RemoveCompositor(uint64_t id)
1678 : {
1679 0 : MOZ_RELEASE_ASSERT(CompositorThreadHolder::IsInCompositorThread());
1680 :
1681 0 : CompositorMap::iterator it = sCompositorMap->find(id);
1682 0 : if (it == sCompositorMap->end()) {
1683 : return nullptr;
1684 : }
1685 0 : CompositorBridgeParent *retval = it->second;
1686 0 : sCompositorMap->erase(it);
1687 0 : return retval;
1688 : }
1689 :
1690 : void
1691 0 : CompositorBridgeParent::NotifyVsync(const TimeStamp& aTimeStamp, const LayersId& aLayersId)
1692 : {
1693 0 : MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_GPU);
1694 0 : MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
1695 :
1696 0 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
1697 0 : auto it = sIndirectLayerTrees.find(aLayersId);
1698 0 : if (it == sIndirectLayerTrees.end())
1699 0 : return;
1700 :
1701 0 : CompositorBridgeParent* cbp = it->second.mParent;
1702 0 : if (!cbp || !cbp->mWidget)
1703 : return;
1704 :
1705 0 : RefPtr<VsyncObserver> obs = cbp->mWidget->GetVsyncObserver();
1706 0 : if (!obs)
1707 0 : return;
1708 :
1709 0 : obs->NotifyVsync(aTimeStamp);
1710 : }
1711 :
1712 : mozilla::ipc::IPCResult
1713 0 : CompositorBridgeParent::RecvNotifyChildCreated(const LayersId& child,
1714 : CompositorOptions* aOptions)
1715 : {
1716 3 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
1717 1 : NotifyChildCreated(child);
1718 1 : *aOptions = mOptions;
1719 1 : return IPC_OK();
1720 : }
1721 :
1722 : mozilla::ipc::IPCResult
1723 0 : CompositorBridgeParent::RecvNotifyChildRecreated(const LayersId& aChild,
1724 : CompositorOptions* aOptions)
1725 : {
1726 0 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
1727 :
1728 0 : if (sIndirectLayerTrees.find(aChild) != sIndirectLayerTrees.end()) {
1729 0 : NS_WARNING("Invalid to register the same layer tree twice");
1730 0 : return IPC_FAIL_NO_REASON(this);
1731 : }
1732 :
1733 0 : NotifyChildCreated(aChild);
1734 0 : *aOptions = mOptions;
1735 : return IPC_OK();
1736 : }
1737 :
1738 : void
1739 2 : CompositorBridgeParent::NotifyChildCreated(LayersId aChild)
1740 : {
1741 1 : sIndirectLayerTreesLock->AssertCurrentThreadOwns();
1742 4 : sIndirectLayerTrees[aChild].mParent = this;
1743 4 : sIndirectLayerTrees[aChild].mLayerManager = mLayerManager;
1744 2 : }
1745 :
1746 : mozilla::ipc::IPCResult
1747 0 : CompositorBridgeParent::RecvMapAndNotifyChildCreated(const LayersId& aChild,
1748 : const base::ProcessId& aOwnerPid,
1749 : CompositorOptions* aOptions)
1750 : {
1751 : // We only use this message when the remote compositor is in the GPU process.
1752 : // It is harmless to call it, though.
1753 0 : MOZ_ASSERT(XRE_IsGPUProcess());
1754 :
1755 0 : LayerTreeOwnerTracker::Get()->Map(aChild, aOwnerPid);
1756 :
1757 0 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
1758 0 : NotifyChildCreated(aChild);
1759 0 : *aOptions = mOptions;
1760 0 : return IPC_OK();
1761 : }
1762 :
1763 : mozilla::ipc::IPCResult
1764 0 : CompositorBridgeParent::RecvAdoptChild(const LayersId& child)
1765 : {
1766 2 : RefPtr<APZUpdater> oldApzUpdater;
1767 : APZCTreeManagerParent* parent;
1768 0 : bool scheduleComposition = false;
1769 2 : RefPtr<CrossProcessCompositorBridgeParent> cpcp;
1770 2 : RefPtr<WebRenderBridgeParent> childWrBridge;
1771 :
1772 : { // scope lock
1773 3 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
1774 0 : if (sIndirectLayerTrees[child].mParent) {
1775 : // We currently don't support adopting children from one compositor to
1776 : // another if the two compositors don't have the same options.
1777 1 : MOZ_ASSERT(sIndirectLayerTrees[child].mParent->mOptions == mOptions);
1778 1 : oldApzUpdater = sIndirectLayerTrees[child].mParent->mApzUpdater;
1779 : }
1780 1 : NotifyChildCreated(child);
1781 0 : if (sIndirectLayerTrees[child].mLayerTree) {
1782 0 : sIndirectLayerTrees[child].mLayerTree->SetLayerManager(mLayerManager, GetAnimationStorage());
1783 : // Trigger composition to handle a case that mLayerTree was not composited yet
1784 : // by previous CompositorBridgeParent, since nsRefreshDriver might wait composition complete.
1785 0 : scheduleComposition = true;
1786 : }
1787 2 : if (mWrBridge) {
1788 0 : childWrBridge = sIndirectLayerTrees[child].mWrBridge;
1789 0 : cpcp = sIndirectLayerTrees[child].mCrossProcessParent;
1790 : }
1791 1 : parent = sIndirectLayerTrees[child].mApzcTreeManagerParent;
1792 : }
1793 :
1794 1 : if (scheduleComposition) {
1795 0 : ScheduleComposition();
1796 : }
1797 :
1798 1 : if (childWrBridge) {
1799 0 : MOZ_ASSERT(mWrBridge);
1800 0 : RefPtr<wr::WebRenderAPI> api = mWrBridge->GetWebRenderAPI();
1801 0 : api = api->Clone();
1802 0 : childWrBridge->UpdateWebRender(mWrBridge->CompositorScheduler(),
1803 : api,
1804 : mWrBridge->AsyncImageManager(),
1805 0 : GetAnimationStorage());
1806 : // Pretend we composited, since parent CompositorBridgeParent was replaced.
1807 0 : if (cpcp) {
1808 0 : TimeStamp now = TimeStamp::Now();
1809 0 : cpcp->DidComposite(child, now, now);
1810 : }
1811 : }
1812 :
1813 1 : if (oldApzUpdater) {
1814 : // We don't support moving a child from an APZ-enabled compositor to a
1815 : // APZ-disabled compositor. The mOptions assertion above should already
1816 : // ensure this, since APZ-ness is one of the things in mOptions. Note
1817 : // however it is possible for mApzUpdater to be non-null here with
1818 : // oldApzUpdater null, because the child may not have been previously
1819 : // composited.
1820 2 : MOZ_ASSERT(mApzUpdater);
1821 : }
1822 2 : if (mApzUpdater) {
1823 0 : if (parent) {
1824 0 : MOZ_ASSERT(mApzcTreeManager);
1825 0 : parent->ChildAdopted(mApzcTreeManager, mApzUpdater);
1826 : }
1827 1 : mApzUpdater->NotifyLayerTreeAdopted(child, oldApzUpdater);
1828 : }
1829 1 : return IPC_OK();
1830 : }
1831 :
1832 : PWebRenderBridgeParent*
1833 0 : CompositorBridgeParent::AllocPWebRenderBridgeParent(const wr::PipelineId& aPipelineId,
1834 : const LayoutDeviceIntSize& aSize,
1835 : TextureFactoryIdentifier* aTextureFactoryIdentifier,
1836 : wr::IdNamespace* aIdNamespace)
1837 : {
1838 : #ifndef MOZ_BUILD_WEBRENDER
1839 : // Extra guard since this in the parent process and we don't want a malicious
1840 : // child process invoking this codepath before it's ready
1841 : MOZ_RELEASE_ASSERT(false);
1842 : #endif
1843 0 : MOZ_ASSERT(wr::AsLayersId(aPipelineId) == mRootLayerTreeID);
1844 0 : MOZ_ASSERT(!mWrBridge);
1845 0 : MOZ_ASSERT(!mCompositor);
1846 0 : MOZ_ASSERT(!mCompositorScheduler);
1847 0 : MOZ_ASSERT(mWidget);
1848 :
1849 0 : RefPtr<widget::CompositorWidget> widget = mWidget;
1850 0 : wr::WrWindowId windowId = wr::NewWindowId();
1851 0 : if (mApzUpdater) {
1852 : // If APZ is enabled, we need to register the APZ updater with the window id
1853 : // before the updater thread is created in WebRenderAPI::Create, so
1854 : // that the callback from the updater thread can find the right APZUpdater.
1855 0 : mApzUpdater->SetWebRenderWindowId(windowId);
1856 : }
1857 0 : if (mApzSampler) {
1858 : // Same as for mApzUpdater, but for the sampler thread.
1859 0 : mApzSampler->SetWebRenderWindowId(windowId);
1860 : }
1861 0 : RefPtr<wr::WebRenderAPI> api = wr::WebRenderAPI::Create(this, std::move(widget), windowId, aSize);
1862 0 : if (!api) {
1863 0 : mWrBridge = WebRenderBridgeParent::CreateDestroyed(aPipelineId);
1864 0 : mWrBridge.get()->AddRef(); // IPDL reference
1865 0 : *aIdNamespace = mWrBridge->GetIdNamespace();
1866 0 : *aTextureFactoryIdentifier = TextureFactoryIdentifier(LayersBackend::LAYERS_NONE);
1867 0 : return mWrBridge;
1868 : }
1869 0 : mAsyncImageManager = new AsyncImagePipelineManager(api->Clone());
1870 0 : RefPtr<AsyncImagePipelineManager> asyncMgr = mAsyncImageManager;
1871 0 : wr::TransactionBuilder txn;
1872 0 : txn.SetRootPipeline(aPipelineId);
1873 0 : api->SendTransaction(txn);
1874 0 : RefPtr<CompositorAnimationStorage> animStorage = GetAnimationStorage();
1875 0 : mWrBridge = new WebRenderBridgeParent(this, aPipelineId, mWidget, nullptr, std::move(api), std::move(asyncMgr), std::move(animStorage));
1876 0 : mWrBridge.get()->AddRef(); // IPDL reference
1877 :
1878 0 : *aIdNamespace = mWrBridge->GetIdNamespace();
1879 0 : mCompositorScheduler = mWrBridge->CompositorScheduler();
1880 0 : MOZ_ASSERT(mCompositorScheduler);
1881 : { // scope lock
1882 0 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
1883 0 : MOZ_ASSERT(sIndirectLayerTrees[mRootLayerTreeID].mWrBridge == nullptr);
1884 0 : sIndirectLayerTrees[mRootLayerTreeID].mWrBridge = mWrBridge;
1885 : }
1886 0 : *aTextureFactoryIdentifier = mWrBridge->GetTextureFactoryIdentifier();
1887 0 : return mWrBridge;
1888 : }
1889 :
1890 : bool
1891 0 : CompositorBridgeParent::DeallocPWebRenderBridgeParent(PWebRenderBridgeParent* aActor)
1892 : {
1893 : #ifndef MOZ_BUILD_WEBRENDER
1894 : // Extra guard since this in the parent process and we don't want a malicious
1895 : // child process invoking this codepath before it's ready
1896 : MOZ_RELEASE_ASSERT(false);
1897 : #endif
1898 0 : WebRenderBridgeParent* parent = static_cast<WebRenderBridgeParent*>(aActor);
1899 : {
1900 0 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
1901 0 : auto it = sIndirectLayerTrees.find(wr::AsLayersId(parent->PipelineId()));
1902 0 : if (it != sIndirectLayerTrees.end()) {
1903 0 : it->second.mWrBridge = nullptr;
1904 : }
1905 : }
1906 0 : parent->Release(); // IPDL reference
1907 0 : return true;
1908 : }
1909 :
1910 : RefPtr<WebRenderBridgeParent>
1911 0 : CompositorBridgeParent::GetWebRenderBridgeParent() const
1912 : {
1913 0 : return mWrBridge;
1914 : }
1915 :
1916 : Maybe<TimeStamp>
1917 0 : CompositorBridgeParent::GetTestingTimeStamp() const
1918 : {
1919 0 : return mTestTime;
1920 : }
1921 :
1922 : void
1923 0 : EraseLayerState(LayersId aId)
1924 : {
1925 0 : RefPtr<APZUpdater> apz;
1926 :
1927 : { // scope lock
1928 0 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
1929 0 : auto iter = sIndirectLayerTrees.find(aId);
1930 0 : if (iter != sIndirectLayerTrees.end()) {
1931 0 : CompositorBridgeParent* parent = iter->second.mParent;
1932 0 : if (parent) {
1933 0 : apz = parent->GetAPZUpdater();
1934 : }
1935 : sIndirectLayerTrees.erase(iter);
1936 : }
1937 : }
1938 :
1939 0 : if (apz) {
1940 0 : apz->NotifyLayerTreeRemoved(aId);
1941 : }
1942 0 : }
1943 :
1944 : /*static*/ void
1945 0 : CompositorBridgeParent::DeallocateLayerTreeId(LayersId aId)
1946 : {
1947 0 : MOZ_ASSERT(NS_IsMainThread());
1948 : // Here main thread notifies compositor to remove an element from
1949 : // sIndirectLayerTrees. This removed element might be queried soon.
1950 : // Checking the elements of sIndirectLayerTrees exist or not before using.
1951 0 : if (!CompositorLoop()) {
1952 0 : gfxCriticalError() << "Attempting to post to a invalid Compositor Loop";
1953 0 : return;
1954 : }
1955 0 : CompositorLoop()->PostTask(NewRunnableFunction("EraseLayerStateRunnable",
1956 0 : &EraseLayerState, aId));
1957 : }
1958 :
1959 : static void
1960 0 : UpdateControllerForLayersId(LayersId aLayersId,
1961 : GeckoContentController* aController)
1962 : {
1963 : // Adopt ref given to us by SetControllerForLayerTree()
1964 3 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
1965 1 : sIndirectLayerTrees[aLayersId].mController =
1966 0 : already_AddRefed<GeckoContentController>(aController);
1967 0 : }
1968 :
1969 0 : ScopedLayerTreeRegistration::ScopedLayerTreeRegistration(APZCTreeManager* aApzctm,
1970 : LayersId aLayersId,
1971 : Layer* aRoot,
1972 0 : GeckoContentController* aController)
1973 0 : : mLayersId(aLayersId)
1974 : {
1975 0 : EnsureLayerTreeMapReady();
1976 0 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
1977 0 : sIndirectLayerTrees[aLayersId].mRoot = aRoot;
1978 0 : sIndirectLayerTrees[aLayersId].mController = aController;
1979 0 : }
1980 :
1981 0 : ScopedLayerTreeRegistration::~ScopedLayerTreeRegistration()
1982 : {
1983 0 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
1984 0 : sIndirectLayerTrees.erase(mLayersId);
1985 0 : }
1986 :
1987 : /*static*/ void
1988 1 : CompositorBridgeParent::SetControllerForLayerTree(LayersId aLayersId,
1989 : GeckoContentController* aController)
1990 : {
1991 : // This ref is adopted by UpdateControllerForLayersId().
1992 1 : aController->AddRef();
1993 3 : CompositorLoop()->PostTask(NewRunnableFunction("UpdateControllerForLayersIdRunnable",
1994 : &UpdateControllerForLayersId,
1995 : aLayersId,
1996 0 : aController));
1997 0 : }
1998 :
1999 : /*static*/ already_AddRefed<IAPZCTreeManager>
2000 1 : CompositorBridgeParent::GetAPZCTreeManager(LayersId aLayersId)
2001 : {
2002 0 : EnsureLayerTreeMapReady();
2003 3 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
2004 1 : LayerTreeMap::iterator cit = sIndirectLayerTrees.find(aLayersId);
2005 0 : if (sIndirectLayerTrees.end() == cit) {
2006 : return nullptr;
2007 : }
2008 1 : LayerTreeState* lts = &cit->second;
2009 :
2010 : RefPtr<IAPZCTreeManager> apzctm = lts->mParent
2011 1 : ? lts->mParent->mApzcTreeManager.get()
2012 0 : : nullptr;
2013 1 : return apzctm.forget();
2014 : }
2015 :
2016 : #if defined(MOZ_GECKO_PROFILER)
2017 : static void
2018 0 : InsertVsyncProfilerMarker(TimeStamp aVsyncTimestamp)
2019 : {
2020 0 : MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
2021 0 : profiler_add_marker(
2022 : "VsyncTimestamp",
2023 0 : MakeUnique<VsyncMarkerPayload>(aVsyncTimestamp));
2024 0 : }
2025 : #endif
2026 :
2027 : /*static */ void
2028 0 : CompositorBridgeParent::PostInsertVsyncProfilerMarker(TimeStamp aVsyncTimestamp)
2029 : {
2030 : #if defined(MOZ_GECKO_PROFILER)
2031 : // Called in the vsync thread
2032 0 : if (profiler_is_active() && CompositorThreadHolder::IsActive()) {
2033 0 : CompositorLoop()->PostTask(
2034 0 : NewRunnableFunction("InsertVsyncProfilerMarkerRunnable", InsertVsyncProfilerMarker,
2035 0 : aVsyncTimestamp));
2036 : }
2037 : #endif
2038 1 : }
2039 :
2040 : widget::PCompositorWidgetParent*
2041 0 : CompositorBridgeParent::AllocPCompositorWidgetParent(const CompositorWidgetInitData& aInitData)
2042 : {
2043 : #if defined(MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING)
2044 0 : if (mWidget) {
2045 : // Should not create two widgets on the same compositor.
2046 : return nullptr;
2047 : }
2048 :
2049 : widget::CompositorWidgetParent* widget =
2050 0 : new widget::CompositorWidgetParent(aInitData, mOptions);
2051 0 : widget->AddRef();
2052 :
2053 : #ifdef XP_WIN
2054 : if (mOptions.UseWebRender() && DeviceManagerDx::Get()->CanUseDComp()) {
2055 : widget->AsWindows()->EnsureCompositorWindow();
2056 : }
2057 : #endif
2058 :
2059 : // Sending the constructor acts as initialization as well.
2060 0 : mWidget = widget;
2061 0 : return widget;
2062 : #else
2063 : return nullptr;
2064 : #endif
2065 : }
2066 :
2067 : bool
2068 0 : CompositorBridgeParent::DeallocPCompositorWidgetParent(PCompositorWidgetParent* aActor)
2069 : {
2070 : #if defined(MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING)
2071 0 : static_cast<widget::CompositorWidgetParent*>(aActor)->Release();
2072 0 : return true;
2073 : #else
2074 : return false;
2075 : #endif
2076 : }
2077 :
2078 : bool
2079 0 : CompositorBridgeParent::IsPendingComposite()
2080 : {
2081 87 : MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
2082 174 : if (!mCompositor) {
2083 : return false;
2084 : }
2085 1 : return mCompositor->IsPendingComposite();
2086 : }
2087 :
2088 : void
2089 0 : CompositorBridgeParent::FinishPendingComposite()
2090 : {
2091 0 : MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
2092 0 : if (!mCompositor) {
2093 : return;
2094 : }
2095 0 : return mCompositor->FinishPendingComposite();
2096 : }
2097 :
2098 : CompositorController*
2099 0 : CompositorBridgeParent::LayerTreeState::GetCompositorController() const
2100 : {
2101 0 : return mParent;
2102 : }
2103 :
2104 : MetricsSharingController*
2105 0 : CompositorBridgeParent::LayerTreeState::CrossProcessSharingController() const
2106 : {
2107 0 : return mCrossProcessParent;
2108 : }
2109 :
2110 : MetricsSharingController*
2111 1 : CompositorBridgeParent::LayerTreeState::InProcessSharingController() const
2112 : {
2113 1 : return mParent;
2114 : }
2115 :
2116 : void
2117 0 : CompositorBridgeParent::DidComposite(LayersId aId, TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd)
2118 : {
2119 0 : MOZ_ASSERT(aId == mRootLayerTreeID);
2120 0 : DidComposite(aCompositeStart, aCompositeEnd);
2121 0 : }
2122 :
2123 : void
2124 0 : CompositorBridgeParent::DidComposite(TimeStamp& aCompositeStart,
2125 : TimeStamp& aCompositeEnd)
2126 : {
2127 18 : if (mWrBridge) {
2128 0 : NotifyDidComposite(mWrBridge->FlushPendingTransactionIds(), aCompositeStart, aCompositeEnd);
2129 : } else {
2130 9 : NotifyDidComposite(mPendingTransaction, aCompositeStart, aCompositeEnd);
2131 : #if defined(ENABLE_FRAME_LATENCY_LOG)
2132 : if (mPendingTransaction.IsValid()) {
2133 : if (mTxnStartTime) {
2134 : uint32_t latencyMs = round((aCompositeEnd - mTxnStartTime).ToMilliseconds());
2135 : printf_stderr("From transaction start to end of generate frame latencyMs %d this %p\n", latencyMs, this);
2136 : }
2137 : if (mFwdTime) {
2138 : uint32_t latencyMs = round((aCompositeEnd - mFwdTime).ToMilliseconds());
2139 : printf_stderr("From forwarding transaction to end of generate frame latencyMs %d this %p\n", latencyMs, this);
2140 : }
2141 : }
2142 : mTxnStartTime = TimeStamp();
2143 : mFwdTime = TimeStamp();
2144 : #endif
2145 9 : mPendingTransaction = TransactionId{0};
2146 : }
2147 9 : }
2148 :
2149 : void
2150 0 : CompositorBridgeParent::NotifyPipelineRendered(const wr::PipelineId& aPipelineId,
2151 : const wr::Epoch& aEpoch,
2152 : TimeStamp& aCompositeStart,
2153 : TimeStamp& aCompositeEnd)
2154 : {
2155 0 : if (!mWrBridge) {
2156 0 : return;
2157 : }
2158 :
2159 0 : if (mWrBridge->PipelineId() == aPipelineId) {
2160 0 : mWrBridge->RemoveEpochDataPriorTo(aEpoch);
2161 :
2162 0 : if (!mPaused) {
2163 0 : TransactionId transactionId = mWrBridge->FlushTransactionIdsForEpoch(aEpoch, aCompositeEnd);
2164 0 : Unused << SendDidComposite(LayersId{0}, transactionId, aCompositeStart, aCompositeEnd);
2165 :
2166 0 : nsTArray<ImageCompositeNotificationInfo> notifications;
2167 0 : mWrBridge->ExtractImageCompositeNotifications(¬ifications);
2168 0 : if (!notifications.IsEmpty()) {
2169 0 : Unused << ImageBridgeParent::NotifyImageComposites(notifications);
2170 : }
2171 : }
2172 : return;
2173 : }
2174 :
2175 0 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
2176 0 : ForEachIndirectLayerTree([&] (LayerTreeState* lts, const LayersId& aLayersId) -> void {
2177 0 : if (lts->mCrossProcessParent &&
2178 0 : lts->mWrBridge &&
2179 0 : lts->mWrBridge->PipelineId() == aPipelineId) {
2180 :
2181 0 : lts->mWrBridge->RemoveEpochDataPriorTo(aEpoch);
2182 :
2183 0 : if (!mPaused) {
2184 0 : CrossProcessCompositorBridgeParent* cpcp = lts->mCrossProcessParent;
2185 0 : TransactionId transactionId = lts->mWrBridge->FlushTransactionIdsForEpoch(aEpoch, aCompositeEnd);
2186 0 : Unused << cpcp->SendDidComposite(aLayersId, transactionId, aCompositeStart, aCompositeEnd);
2187 : }
2188 : }
2189 0 : });
2190 : }
2191 :
2192 : RefPtr<AsyncImagePipelineManager>
2193 0 : CompositorBridgeParent::GetAsyncImagePipelineManager() const
2194 : {
2195 0 : return mAsyncImageManager;
2196 : }
2197 :
2198 : void
2199 0 : CompositorBridgeParent::NotifyDidComposite(TransactionId aTransactionId, TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd)
2200 : {
2201 0 : Unused << SendDidComposite(LayersId{0}, aTransactionId, aCompositeStart, aCompositeEnd);
2202 :
2203 18 : if (mLayerManager) {
2204 18 : nsTArray<ImageCompositeNotificationInfo> notifications;
2205 0 : mLayerManager->ExtractImageCompositeNotifications(¬ifications);
2206 1 : if (!notifications.IsEmpty()) {
2207 0 : Unused << ImageBridgeParent::NotifyImageComposites(notifications);
2208 : }
2209 : }
2210 :
2211 18 : if (mWrBridge) {
2212 0 : nsTArray<ImageCompositeNotificationInfo> notifications;
2213 0 : mWrBridge->ExtractImageCompositeNotifications(¬ifications);
2214 0 : if (!notifications.IsEmpty()) {
2215 0 : Unused << ImageBridgeParent::NotifyImageComposites(notifications);
2216 : }
2217 : }
2218 :
2219 0 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
2220 0 : ForEachIndirectLayerTree([&] (LayerTreeState* lts, const LayersId& aLayersId) -> void {
2221 27 : if (lts->mCrossProcessParent && lts->mParent == this) {
2222 9 : CrossProcessCompositorBridgeParent* cpcp = lts->mCrossProcessParent;
2223 1 : cpcp->DidCompositeLocked(aLayersId, aCompositeStart, aCompositeEnd);
2224 : }
2225 1 : });
2226 9 : }
2227 :
2228 : void
2229 0 : CompositorBridgeParent::InvalidateRemoteLayers()
2230 : {
2231 0 : MOZ_ASSERT(CompositorLoop() == MessageLoop::current());
2232 :
2233 0 : Unused << PCompositorBridgeParent::SendInvalidateLayers(LayersId{0});
2234 :
2235 0 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
2236 0 : ForEachIndirectLayerTree([] (LayerTreeState* lts, const LayersId& aLayersId) -> void {
2237 0 : if (lts->mCrossProcessParent) {
2238 0 : CrossProcessCompositorBridgeParent* cpcp = lts->mCrossProcessParent;
2239 0 : Unused << cpcp->SendInvalidateLayers(aLayersId);
2240 : }
2241 0 : });
2242 0 : }
2243 :
2244 : void
2245 2 : UpdateIndirectTree(LayersId aId, Layer* aRoot, const TargetConfig& aTargetConfig)
2246 : {
2247 0 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
2248 4 : sIndirectLayerTrees[aId].mRoot = aRoot;
2249 2 : sIndirectLayerTrees[aId].mTargetConfig = aTargetConfig;
2250 0 : }
2251 :
2252 : /* static */ CompositorBridgeParent::LayerTreeState*
2253 0 : CompositorBridgeParent::GetIndirectShadowTree(LayersId aId)
2254 : {
2255 : // Only the compositor thread should use this method variant
2256 6 : MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
2257 :
2258 18 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
2259 6 : LayerTreeMap::iterator cit = sIndirectLayerTrees.find(aId);
2260 6 : if (sIndirectLayerTrees.end() == cit) {
2261 : return nullptr;
2262 : }
2263 6 : return &cit->second;
2264 : }
2265 :
2266 : /* static */ bool
2267 3 : CompositorBridgeParent::CallWithIndirectShadowTree(LayersId aId,
2268 : const std::function<void(CompositorBridgeParent::LayerTreeState&)>& aFunc)
2269 : {
2270 : // Note that this does not make things universally threadsafe just because the
2271 : // sIndirectLayerTreesLock mutex is held. This is because the compositor
2272 : // thread can mutate the LayerTreeState outside the lock. It does however
2273 : // ensure that the *storage* for the LayerTreeState remains stable, since we
2274 : // should always hold the lock when adding/removing entries to the map.
2275 0 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
2276 3 : LayerTreeMap::iterator cit = sIndirectLayerTrees.find(aId);
2277 3 : if (sIndirectLayerTrees.end() == cit) {
2278 : return false;
2279 : }
2280 3 : aFunc(cit->second);
2281 1 : return true;
2282 : }
2283 :
2284 : static CompositorBridgeParent::LayerTreeState*
2285 0 : GetStateForRoot(LayersId aContentLayersId, const MonitorAutoLock& aProofOfLock)
2286 : {
2287 0 : CompositorBridgeParent::LayerTreeState* state = nullptr;
2288 0 : LayerTreeMap::iterator itr = sIndirectLayerTrees.find(aContentLayersId);
2289 0 : if (sIndirectLayerTrees.end() != itr) {
2290 0 : state = &itr->second;
2291 : }
2292 :
2293 : // |state| is the state for the content process, but we want the APZCTMParent
2294 : // for the parent process owning that content process. So we have to jump to
2295 : // the LayerTreeState for the root layer tree id for that layer tree, and use
2296 : // the mApzcTreeManagerParent from that. This should also work with nested
2297 : // content processes, because RootLayerTreeId() will bypass any intermediate
2298 : // processes' ids and go straight to the root.
2299 0 : if (state) {
2300 0 : LayersId rootLayersId = state->mParent->RootLayerTreeId();
2301 0 : itr = sIndirectLayerTrees.find(rootLayersId);
2302 0 : state = (sIndirectLayerTrees.end() != itr) ? &itr->second : nullptr;
2303 : }
2304 :
2305 0 : return state;
2306 : }
2307 :
2308 : /* static */ APZCTreeManagerParent*
2309 0 : CompositorBridgeParent::GetApzcTreeManagerParentForRoot(LayersId aContentLayersId)
2310 : {
2311 0 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
2312 : CompositorBridgeParent::LayerTreeState* state =
2313 0 : GetStateForRoot(aContentLayersId, lock);
2314 0 : return state ? state->mApzcTreeManagerParent : nullptr;
2315 : }
2316 :
2317 : /* static */ GeckoContentController*
2318 0 : CompositorBridgeParent::GetGeckoContentControllerForRoot(LayersId aContentLayersId)
2319 : {
2320 0 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
2321 : CompositorBridgeParent::LayerTreeState* state =
2322 0 : GetStateForRoot(aContentLayersId, lock);
2323 0 : return state ? state->mController.get() : nullptr;
2324 : }
2325 :
2326 : PTextureParent*
2327 2 : CompositorBridgeParent::AllocPTextureParent(const SurfaceDescriptor& aSharedData,
2328 : const ReadLockDescriptor& aReadLock,
2329 : const LayersBackend& aLayersBackend,
2330 : const TextureFlags& aFlags,
2331 : const LayersId& aId,
2332 : const uint64_t& aSerial,
2333 : const wr::MaybeExternalImageId& aExternalImageId)
2334 : {
2335 0 : return TextureHost::CreateIPDLActor(this, aSharedData, aReadLock, aLayersBackend, aFlags, aSerial, aExternalImageId);
2336 : }
2337 :
2338 : bool
2339 0 : CompositorBridgeParent::DeallocPTextureParent(PTextureParent* actor)
2340 : {
2341 0 : return TextureHost::DestroyIPDLActor(actor);
2342 : }
2343 :
2344 : bool
2345 1 : CompositorBridgeParent::IsSameProcess() const
2346 : {
2347 1 : return OtherPid() == base::GetCurrentProcId();
2348 : }
2349 :
2350 : void
2351 0 : CompositorBridgeParent::NotifyWebRenderError(wr::WebRenderError aError)
2352 : {
2353 0 : MOZ_ASSERT(CompositorLoop() == MessageLoop::current());
2354 0 : Unused << SendNotifyWebRenderError(aError);
2355 0 : }
2356 :
2357 : #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
2358 : //#define PLUGINS_LOG(...) printf_stderr("CP [%s]: ", __FUNCTION__);
2359 : // printf_stderr(__VA_ARGS__);
2360 : // printf_stderr("\n");
2361 : #define PLUGINS_LOG(...)
2362 :
2363 : bool
2364 0 : CompositorBridgeParent::UpdatePluginWindowState(LayersId aId)
2365 : {
2366 0 : MonitorAutoLock lock(*sIndirectLayerTreesLock);
2367 0 : CompositorBridgeParent::LayerTreeState& lts = sIndirectLayerTrees[aId];
2368 0 : if (!lts.mParent) {
2369 : PLUGINS_LOG("[%" PRIu64 "] layer tree compositor parent pointer is null", aId);
2370 : return false;
2371 : }
2372 :
2373 : // Check if this layer tree has received any shadow layer updates
2374 0 : if (!lts.mUpdatedPluginDataAvailable) {
2375 : PLUGINS_LOG("[%" PRIu64 "] no plugin data", aId);
2376 : return false;
2377 : }
2378 :
2379 : // pluginMetricsChanged tracks whether we need to send plugin update
2380 : // data to the main thread. If we do we'll have to block composition,
2381 : // which we want to avoid if at all possible.
2382 0 : bool pluginMetricsChanged = false;
2383 :
2384 : // Same layer tree checks
2385 0 : if (mLastPluginUpdateLayerTreeId == aId) {
2386 : // no plugin data and nothing has changed, bail.
2387 0 : if (!mCachedPluginData.Length() && !lts.mPluginData.Length()) {
2388 : PLUGINS_LOG("[%" PRIu64 "] no data, no changes", aId);
2389 : return false;
2390 : }
2391 :
2392 0 : if (mCachedPluginData.Length() == lts.mPluginData.Length()) {
2393 : // check for plugin data changes
2394 0 : for (uint32_t idx = 0; idx < lts.mPluginData.Length(); idx++) {
2395 0 : if (!(mCachedPluginData[idx] == lts.mPluginData[idx])) {
2396 : pluginMetricsChanged = true;
2397 : break;
2398 : }
2399 : }
2400 : } else {
2401 : // array lengths don't match, need to update
2402 : pluginMetricsChanged = true;
2403 : }
2404 : } else {
2405 : // exchanging layer trees, we need to update
2406 : pluginMetricsChanged = true;
2407 : }
2408 :
2409 : // Check if plugin windows are currently hidden due to scrolling
2410 0 : if (mDeferPluginWindows) {
2411 : PLUGINS_LOG("[%" PRIu64 "] suppressing", aId);
2412 : return false;
2413 : }
2414 :
2415 : // If the plugin windows were hidden but now are not, we need to force
2416 : // update the metrics to make sure they are visible again.
2417 0 : if (mPluginWindowsHidden) {
2418 : PLUGINS_LOG("[%" PRIu64 "] re-showing", aId);
2419 0 : mPluginWindowsHidden = false;
2420 0 : pluginMetricsChanged = true;
2421 : }
2422 :
2423 0 : if (!lts.mPluginData.Length()) {
2424 : // Don't hide plugins if the previous remote layer tree didn't contain any.
2425 0 : if (!mCachedPluginData.Length()) {
2426 : PLUGINS_LOG("[%" PRIu64 "] nothing to hide", aId);
2427 0 : return false;
2428 : }
2429 :
2430 0 : uintptr_t parentWidget = GetWidget()->GetWidgetKey();
2431 :
2432 : // We will pass through here in cases where the previous shadow layer
2433 : // tree contained visible plugins and the new tree does not. All we need
2434 : // to do here is hide the plugins for the old tree, so don't waste time
2435 : // calculating clipping.
2436 0 : mPluginsLayerOffset = nsIntPoint(0,0);
2437 0 : mPluginsLayerVisibleRegion.SetEmpty();
2438 0 : Unused << lts.mParent->SendHideAllPlugins(parentWidget);
2439 0 : lts.mUpdatedPluginDataAvailable = false;
2440 : PLUGINS_LOG("[%" PRIu64 "] hide all", aId);
2441 : } else {
2442 : // Retrieve the offset and visible region of the layer that hosts
2443 : // the plugins, CompositorBridgeChild needs these in calculating proper
2444 : // plugin clipping.
2445 0 : LayerTransactionParent* layerTree = lts.mLayerTree;
2446 0 : Layer* contentRoot = layerTree->GetRoot();
2447 0 : if (contentRoot) {
2448 0 : nsIntPoint offset;
2449 0 : nsIntRegion visibleRegion;
2450 0 : if (contentRoot->GetVisibleRegionRelativeToRootLayer(visibleRegion,
2451 : &offset)) {
2452 : // Check to see if these values have changed, if so we need to
2453 : // update plugin window position within the window.
2454 0 : if (!pluginMetricsChanged &&
2455 0 : mPluginsLayerVisibleRegion == visibleRegion &&
2456 0 : mPluginsLayerOffset == offset) {
2457 : PLUGINS_LOG("[%" PRIu64 "] no change", aId);
2458 0 : return false;
2459 : }
2460 0 : mPluginsLayerOffset = offset;
2461 0 : mPluginsLayerVisibleRegion = visibleRegion;
2462 0 : Unused << lts.mParent->SendUpdatePluginConfigurations(
2463 0 : LayoutDeviceIntPoint::FromUnknownPoint(offset),
2464 0 : LayoutDeviceIntRegion::FromUnknownRegion(visibleRegion),
2465 : lts.mPluginData);
2466 0 : lts.mUpdatedPluginDataAvailable = false;
2467 : PLUGINS_LOG("[%" PRIu64 "] updated", aId);
2468 : } else {
2469 : PLUGINS_LOG("[%" PRIu64 "] no visibility data", aId);
2470 : return false;
2471 : }
2472 : } else {
2473 : PLUGINS_LOG("[%" PRIu64 "] no content root", aId);
2474 : return false;
2475 : }
2476 : }
2477 :
2478 0 : mLastPluginUpdateLayerTreeId = aId;
2479 0 : mCachedPluginData = lts.mPluginData;
2480 0 : return true;
2481 : }
2482 :
2483 : void
2484 0 : CompositorBridgeParent::ScheduleShowAllPluginWindows()
2485 : {
2486 0 : MOZ_ASSERT(CompositorLoop());
2487 0 : CompositorLoop()->PostTask(
2488 0 : NewRunnableMethod("layers::CompositorBridgeParent::ShowAllPluginWindows",
2489 : this,
2490 0 : &CompositorBridgeParent::ShowAllPluginWindows));
2491 0 : }
2492 :
2493 : void
2494 0 : CompositorBridgeParent::ShowAllPluginWindows()
2495 : {
2496 0 : MOZ_ASSERT(!NS_IsMainThread());
2497 0 : mDeferPluginWindows = false;
2498 0 : ScheduleComposition();
2499 0 : }
2500 :
2501 : void
2502 0 : CompositorBridgeParent::ScheduleHideAllPluginWindows()
2503 : {
2504 0 : MOZ_ASSERT(CompositorLoop());
2505 0 : CompositorLoop()->PostTask(
2506 0 : NewRunnableMethod("layers::CompositorBridgeParent::HideAllPluginWindows",
2507 : this,
2508 0 : &CompositorBridgeParent::HideAllPluginWindows));
2509 0 : }
2510 :
2511 : void
2512 0 : CompositorBridgeParent::HideAllPluginWindows()
2513 : {
2514 0 : MOZ_ASSERT(!NS_IsMainThread());
2515 : // No plugins in the cache implies no plugins to manage
2516 : // in this content.
2517 0 : if (!mCachedPluginData.Length() || mDeferPluginWindows) {
2518 0 : return;
2519 : }
2520 :
2521 0 : uintptr_t parentWidget = GetWidget()->GetWidgetKey();
2522 :
2523 0 : mDeferPluginWindows = true;
2524 0 : mPluginWindowsHidden = true;
2525 :
2526 : #if defined(XP_WIN)
2527 : // We will get an async reply that this has happened and then send hide.
2528 : mWaitForPluginsUntil = TimeStamp::Now() + mVsyncRate;
2529 : Unused << SendCaptureAllPlugins(parentWidget);
2530 : #else
2531 0 : Unused << SendHideAllPlugins(parentWidget);
2532 0 : ScheduleComposition();
2533 : #endif
2534 : }
2535 : #endif // #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
2536 :
2537 : mozilla::ipc::IPCResult
2538 0 : CompositorBridgeParent::RecvAllPluginsCaptured()
2539 : {
2540 : #if defined(XP_WIN)
2541 : mWaitForPluginsUntil = TimeStamp();
2542 : mHaveBlockedForPlugins = false;
2543 : ForceComposeToTarget(nullptr);
2544 : Unused << SendHideAllPlugins(GetWidget()->GetWidgetKey());
2545 : return IPC_OK();
2546 : #else
2547 : MOZ_ASSERT_UNREACHABLE(
2548 : "CompositorBridgeParent::RecvAllPluginsCaptured calls unexpected.");
2549 : return IPC_FAIL_NO_REASON(this);
2550 : #endif
2551 : }
2552 :
2553 : } // namespace layers
2554 : } // namespace mozilla
|