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