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 #ifndef mozilla_layers_CompositorBridgeChild_h
8 #define mozilla_layers_CompositorBridgeChild_h
9 
10 #include "base/basictypes.h"     // for DISALLOW_EVIL_CONSTRUCTORS
11 #include "mozilla/Assertions.h"  // for MOZ_ASSERT_HELPER2
12 #include "mozilla/Attributes.h"  // for override
13 #include "mozilla/Monitor.h"
14 #include "mozilla/ipc/ProtocolUtils.h"
15 #include "mozilla/layers/PCompositorBridgeChild.h"
16 #include "mozilla/layers/TextureForwarder.h"  // for TextureForwarder
17 #include "mozilla/layers/PaintThread.h"       // for PaintThread
18 #include "mozilla/webrender/WebRenderTypes.h"
19 #include "nsClassHashtable.h"  // for nsClassHashtable
20 #include "nsCOMPtr.h"          // for nsCOMPtr
21 #include "nsHashKeys.h"        // for nsUint64HashKey
22 #include "nsISupportsImpl.h"   // for NS_INLINE_DECL_REFCOUNTING
23 #include "nsIWeakReferenceUtils.h"
24 
25 #include <unordered_map>
26 
27 namespace mozilla {
28 
29 namespace dom {
30 class BrowserChild;
31 }  // namespace dom
32 
33 namespace webgpu {
34 class PWebGPUChild;
35 class WebGPUChild;
36 }  // namespace webgpu
37 
38 namespace widget {
39 class CompositorWidget;
40 }  // namespace widget
41 
42 namespace layers {
43 
44 using mozilla::dom::BrowserChild;
45 
46 class IAPZCTreeManager;
47 class APZCTreeManagerChild;
48 class CanvasChild;
49 class ClientLayerManager;
50 class CompositorBridgeParent;
51 class CompositorManagerChild;
52 class CompositorOptions;
53 class LayerManager;
54 class TextureClient;
55 class TextureClientPool;
56 struct FrameMetrics;
57 
58 class CompositorBridgeChild final : public PCompositorBridgeChild,
59                                     public TextureForwarder {
60   typedef nsTArray<AsyncParentMessageData> AsyncParentMessageArray;
61 
62   friend class PCompositorBridgeChild;
63 
64  public:
65   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorBridgeChild, override);
66 
67   explicit CompositorBridgeChild(CompositorManagerChild* aManager);
68 
69   /**
70    * Initialize the singleton compositor bridge for a content process.
71    */
72   void InitForContent(uint32_t aNamespace);
73 
74   void InitForWidget(uint64_t aProcessToken, LayerManager* aLayerManager,
75                      uint32_t aNamespace);
76 
77   void Destroy();
78 
79   /**
80    * Lookup the FrameMetrics shared by the compositor process with the
81    * associated ScrollableLayerGuid::ViewID. The returned FrameMetrics is used
82    * in progressive paint calculations.
83    */
84   bool LookupCompositorFrameMetrics(const ScrollableLayerGuid::ViewID aId,
85                                     FrameMetrics&);
86 
87   static CompositorBridgeChild* Get();
88 
89   static bool ChildProcessHasCompositorBridge();
90 
91   // Returns whether the compositor is in the GPU process (false if in the UI
92   // process). This may only be called on the main thread.
93   static bool CompositorIsInGPUProcess();
94 
95   mozilla::ipc::IPCResult RecvDidComposite(
96       const LayersId& aId, const nsTArray<TransactionId>& aTransactionIds,
97       const TimeStamp& aCompositeStart, const TimeStamp& aCompositeEnd);
98 
99   mozilla::ipc::IPCResult RecvNotifyFrameStats(
100       nsTArray<FrameStats>&& aFrameStats);
101 
102   mozilla::ipc::IPCResult RecvInvalidateLayers(const LayersId& aLayersId);
103 
104   mozilla::ipc::IPCResult RecvNotifyJankedAnimations(
105       const LayersId& aLayersId, nsTArray<uint64_t>&& aJankedAnimations);
106 
107   PTextureChild* AllocPTextureChild(
108       const SurfaceDescriptor& aSharedData, const ReadLockDescriptor& aReadLock,
109       const LayersBackend& aLayersBackend, const TextureFlags& aFlags,
110       const LayersId& aId, const uint64_t& aSerial,
111       const wr::MaybeExternalImageId& aExternalImageId);
112 
113   bool DeallocPTextureChild(PTextureChild* actor);
114 
115   mozilla::ipc::IPCResult RecvParentAsyncMessages(
116       nsTArray<AsyncParentMessageData>&& aMessages);
117   PTextureChild* CreateTexture(const SurfaceDescriptor& aSharedData,
118                                const ReadLockDescriptor& aReadLock,
119                                LayersBackend aLayersBackend,
120                                TextureFlags aFlags, uint64_t aSerial,
121                                wr::MaybeExternalImageId& aExternalImageId,
122                                nsISerialEventTarget* aTarget) override;
123 
124   already_AddRefed<CanvasChild> GetCanvasChild() final;
125 
126   void EndCanvasTransaction();
127 
128   RefPtr<webgpu::WebGPUChild> GetWebGPUChild();
129 
130   /**
131    * Request that the parent tell us when graphics are ready on GPU.
132    * When we get that message, we bounce it to the BrowserParent via
133    * the BrowserChild
134    * @param browserChild The object to bounce the note to.  Non-NULL.
135    */
136   void RequestNotifyAfterRemotePaint(BrowserChild* aBrowserChild);
137 
138   void CancelNotifyAfterRemotePaint(BrowserChild* aBrowserChild);
139 
140   // Beware that these methods don't override their super-class equivalent
141   // (which are not virtual), they just overload them. All of these Send*
142   // methods just add a sanity check (that it is not too late send a message)
143   // and forward the call to the super-class's equivalent method. This means
144   // that it is correct to call directly the super-class methods, but you won't
145   // get the extra safety provided here.
146   bool SendWillClose();
147   bool SendPause();
148   bool SendResume();
149   bool SendResumeAsync();
150   bool SendNotifyChildCreated(const LayersId& id, CompositorOptions* aOptions);
151   bool SendAdoptChild(const LayersId& id);
152   bool SendMakeSnapshot(const SurfaceDescriptor& inSnapshot,
153                         const gfx::IntRect& dirtyRect);
154   bool SendFlushRendering();
155   bool SendGetTileSize(int32_t* tileWidth, int32_t* tileHeight);
156   bool SendStartFrameTimeRecording(const int32_t& bufferSize,
157                                    uint32_t* startIndex);
158   bool SendStopFrameTimeRecording(const uint32_t& startIndex,
159                                   nsTArray<float>* intervals);
160   bool SendNotifyRegionInvalidated(const nsIntRegion& region);
161   bool SendRequestNotifyAfterRemotePaint();
162   bool IsSameProcess() const override;
163 
IPCOpen()164   bool IPCOpen() const override { return mCanSend; }
165 
166   static void ShutDown();
167 
UpdateFwdTransactionId()168   void UpdateFwdTransactionId() { ++mFwdTransactionId; }
GetFwdTransactionId()169   uint64_t GetFwdTransactionId() { return mFwdTransactionId; }
170 
171   /**
172    * Hold TextureClient ref until end of usage on host side if
173    * TextureFlags::RECYCLE is set. Host side's usage is checked via
174    * CompositableRef.
175    */
176   void HoldUntilCompositableRefReleasedIfNecessary(TextureClient* aClient);
177 
178   /**
179    * Notify id of Texture When host side end its use. Transaction id is used to
180    * make sure if there is no newer usage.
181    */
182   void NotifyNotUsed(uint64_t aTextureId, uint64_t aFwdTransactionId);
183 
184   void CancelWaitForNotifyNotUsed(uint64_t aTextureId) override;
185 
186   TextureClientPool* GetTexturePool(KnowsCompositor* aAllocator,
187                                     gfx::SurfaceFormat aFormat,
188                                     TextureFlags aFlags);
189   void ClearTexturePool();
190 
191   FixedSizeSmallShmemSectionAllocator* GetTileLockAllocator() override;
192 
193   void HandleMemoryPressure();
194 
GetThread()195   nsISerialEventTarget* GetThread() const override { return mThread; }
196 
GetParentPid()197   base::ProcessId GetParentPid() const override { return OtherPid(); }
198 
199   bool AllocUnsafeShmem(size_t aSize,
200                         mozilla::ipc::SharedMemory::SharedMemoryType aShmType,
201                         mozilla::ipc::Shmem* aShmem) override;
202   bool AllocShmem(size_t aSize,
203                   mozilla::ipc::SharedMemory::SharedMemoryType aShmType,
204                   mozilla::ipc::Shmem* aShmem) override;
205   bool DeallocShmem(mozilla::ipc::Shmem& aShmem) override;
206 
207   PCompositorWidgetChild* AllocPCompositorWidgetChild(
208       const CompositorWidgetInitData& aInitData);
209   bool DeallocPCompositorWidgetChild(PCompositorWidgetChild* aActor);
210 
211   PAPZCTreeManagerChild* AllocPAPZCTreeManagerChild(const LayersId& aLayersId);
212   bool DeallocPAPZCTreeManagerChild(PAPZCTreeManagerChild* aActor);
213 
214   PAPZChild* AllocPAPZChild(const LayersId& aLayersId);
215   bool DeallocPAPZChild(PAPZChild* aActor);
216 
217   void WillEndTransaction();
218 
219   PWebRenderBridgeChild* AllocPWebRenderBridgeChild(
220       const wr::PipelineId& aPipelineId, const LayoutDeviceIntSize&,
221       const WindowKind&);
222   bool DeallocPWebRenderBridgeChild(PWebRenderBridgeChild* aActor);
223 
224   webgpu::PWebGPUChild* AllocPWebGPUChild();
225   bool DeallocPWebGPUChild(webgpu::PWebGPUChild* aActor);
226 
227   wr::MaybeExternalImageId GetNextExternalImageId() override;
228 
229   wr::PipelineId GetNextPipelineId();
230 
231   // Must only be called from the main thread. Ensures that any paints from
232   // previous frames have been flushed. The main thread blocks until the
233   // operation completes.
234   void FlushAsyncPaints();
235 
236   // Must only be called from the main thread. Notifies the CompositorBridge
237   // that the paint thread is going to begin painting asynchronously.
238   void NotifyBeginAsyncPaint(PaintTask* aTask);
239 
240   // Must only be called from the paint thread. Notifies the CompositorBridge
241   // that the paint thread has finished an asynchronous paint request.
242   bool NotifyFinishedAsyncWorkerPaint(PaintTask* aTask);
243 
244   // Must only be called from the main thread. Notifies the CompositorBridge
245   // that all work has been submitted to the paint thread or paint worker
246   // threads, and returns whether all paints are completed. If this returns
247   // true, then an AsyncEndLayerTransaction must be queued, otherwise once
248   // NotifyFinishedAsyncWorkerPaint returns true, an AsyncEndLayerTransaction
249   // must be executed.
250   bool NotifyBeginAsyncEndLayerTransaction(SyncObjectClient* aSyncObject);
251 
252   // Must only be called from the paint thread. Notifies the CompositorBridge
253   // that the paint thread has finished all async paints and and may do the
254   // requested texture sync and resume sending messages.
255   void NotifyFinishedAsyncEndLayerTransaction();
256 
257   // Must only be called from the main thread. Notifies the CompoistorBridge
258   // that a transaction is about to be sent, and if the paint thread is
259   // currently painting, to begin delaying IPC messages.
260   void PostponeMessagesIfAsyncPainting();
261 
262  private:
263   // Private destructor, to discourage deletion outside of Release():
264   virtual ~CompositorBridgeChild();
265 
266   // Must only be called from the paint thread. If the main thread is delaying
267   // IPC messages, this forwards all such delayed IPC messages to the I/O thread
268   // and resumes IPC.
269   void ResumeIPCAfterAsyncPaint();
270 
271   void PrepareFinalDestroy();
272   void AfterDestroy();
273 
274   PLayerTransactionChild* AllocPLayerTransactionChild(
275       const nsTArray<LayersBackend>& aBackendHints, const LayersId& aId);
276 
277   bool DeallocPLayerTransactionChild(PLayerTransactionChild* aChild);
278 
279   void ActorDestroy(ActorDestroyReason aWhy) override;
280 
281   mozilla::ipc::IPCResult RecvSharedCompositorFrameMetrics(
282       const mozilla::ipc::SharedMemoryBasic::Handle& metrics,
283       const CrossProcessMutexHandle& handle, const LayersId& aLayersId,
284       const uint32_t& aAPZCId);
285 
286   mozilla::ipc::IPCResult RecvReleaseSharedCompositorFrameMetrics(
287       const ViewID& aId, const uint32_t& aAPZCId);
288 
289   mozilla::ipc::IPCResult RecvRemotePaintIsReady();
290 
291   mozilla::ipc::IPCResult RecvObserveLayersUpdate(
292       const LayersId& aLayersId, const LayersObserverEpoch& aEpoch,
293       const bool& aActive);
294 
295   mozilla::ipc::IPCResult RecvCompositorOptionsChanged(
296       const LayersId& aLayersId, const CompositorOptions& aNewOptions);
297 
298   uint64_t GetNextResourceId();
299 
300   void ClearSharedFrameMetricsData(LayersId aLayersId);
301 
302   // Class used to store the shared FrameMetrics, mutex, and APZCId  in a hash
303   // table
304   class SharedFrameMetricsData final {
305    public:
306     SharedFrameMetricsData(
307         const mozilla::ipc::SharedMemoryBasic::Handle& metrics,
308         const CrossProcessMutexHandle& handle, const LayersId& aLayersId,
309         const uint32_t& aAPZCId);
310 
311     ~SharedFrameMetricsData();
312 
313     void CopyFrameMetrics(FrameMetrics* aFrame);
314     ScrollableLayerGuid::ViewID GetViewID();
315     LayersId GetLayersId() const;
316     uint32_t GetAPZCId();
317 
318    private:
319     // Pointer to the class that allows access to the shared memory that
320     // contains the shared FrameMetrics
321     RefPtr<mozilla::ipc::SharedMemoryBasic> mBuffer;
322     CrossProcessMutex* mMutex;
323     LayersId mLayersId;
324     // Unique ID of the APZC that is sharing the FrameMetrics
325     uint32_t mAPZCId;
326   };
327 
328   RefPtr<CompositorManagerChild> mCompositorManager;
329 
330   RefPtr<LayerManager> mLayerManager;
331 
332   uint32_t mIdNamespace;
333   uint32_t mResourceId;
334 
335   // When not multi-process, hold a reference to the CompositorBridgeParent to
336   // keep it alive. This reference should be null in multi-process.
337   RefPtr<CompositorBridgeParent> mCompositorBridgeParent;
338 
339   // The ViewID of the FrameMetrics is used as the key for this hash table.
340   // While this should be safe to use since the ViewID is unique
341   nsClassHashtable<nsUint64HashKey, SharedFrameMetricsData> mFrameMetricsTable;
342 
343   // Weakly hold the BrowserChild that made a request to be alerted when
344   // the transaction has been received.
345   nsWeakPtr mWeakBrowserChild;  // type is BrowserChild
346 
347   DISALLOW_EVIL_CONSTRUCTORS(CompositorBridgeChild);
348 
349   // True until the beginning of the two-step shutdown sequence of this actor.
350   bool mCanSend;
351 
352   // False until the actor is destroyed.
353   bool mActorDestroyed;
354 
355   /**
356    * Transaction id of ShadowLayerForwarder.
357    * It is incrementaed by UpdateFwdTransactionId() in each BeginTransaction()
358    * call.
359    */
360   uint64_t mFwdTransactionId;
361 
362   /**
363    * Hold TextureClients refs until end of their usages on host side.
364    * It defer calling of TextureClient recycle callback.
365    */
366   std::unordered_map<uint64_t, RefPtr<TextureClient>>
367       mTexturesWaitingNotifyNotUsed;
368 
369   nsCOMPtr<nsISerialEventTarget> mThread;
370 
371   AutoTArray<RefPtr<TextureClientPool>, 2> mTexturePools;
372 
373   uint64_t mProcessToken;
374 
375   FixedSizeSmallShmemSectionAllocator* mSectionAllocator;
376 
377   // TextureClients that must be kept alive during async painting. This
378   // is only accessed on the main thread.
379   nsTArray<RefPtr<TextureClient>> mTextureClientsForAsyncPaint;
380 
381   // Off-Main-Thread Painting state. This covers access to the OMTP-related
382   // state below.
383   Monitor mPaintLock;
384 
385   // Contains the number of asynchronous paints that were queued since the
386   // beginning of the last async transaction, and the time stamp of when
387   // that was
388   size_t mTotalAsyncPaints;
389   TimeStamp mAsyncTransactionBegin;
390 
391   // Contains the number of outstanding asynchronous paints tied to a
392   // PLayerTransaction on this bridge. This is R/W on both the main and paint
393   // threads, and must be accessed within the paint lock.
394   size_t mOutstandingAsyncPaints;
395 
396   // Whether we are waiting for an async paint end transaction
397   bool mOutstandingAsyncEndTransaction;
398   RefPtr<SyncObjectClient> mOutstandingAsyncSyncObject;
399 
400   // True if this CompositorBridge is currently delaying its messages until the
401   // paint thread completes. This is R/W on both the main and paint threads, and
402   // must be accessed within the paint lock.
403   bool mIsDelayingForAsyncPaints;
404 
405   uintptr_t mSlowFlushCount;
406   uintptr_t mTotalFlushCount;
407 
408   RefPtr<CanvasChild> mCanvasChild;
409 
410   RefPtr<webgpu::WebGPUChild> mWebGPUChild;
411 };
412 
413 }  // namespace layers
414 }  // namespace mozilla
415 
416 #endif  // mozilla_layers_CompositorBrigedChild_h
417