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