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_GFX_IMAGEBRIDGECHILD_H 8 #define MOZILLA_GFX_IMAGEBRIDGECHILD_H 9 10 #include <stddef.h> // for size_t 11 #include <stdint.h> // for uint32_t, uint64_t 12 #include "mozilla/Attributes.h" // for override 13 #include "mozilla/Atomics.h" 14 #include "mozilla/RefPtr.h" // for already_AddRefed 15 #include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc 16 #include "mozilla/layers/CanvasClient.h" 17 #include "mozilla/layers/CompositableForwarder.h" 18 #include "mozilla/layers/CompositorTypes.h" 19 #include "mozilla/layers/PImageBridgeChild.h" 20 #include "mozilla/Mutex.h" 21 #include "mozilla/webrender/WebRenderTypes.h" 22 #include "nsIObserver.h" 23 #include "nsRegion.h" // for nsIntRegion 24 #include "nsRefPtrHashtable.h" 25 #include "mozilla/gfx/Rect.h" 26 #include "mozilla/ReentrantMonitor.h" // for ReentrantMonitor, etc 27 28 class MessageLoop; 29 30 namespace base { 31 class Thread; 32 } // namespace base 33 34 namespace mozilla { 35 namespace ipc { 36 class Shmem; 37 } // namespace ipc 38 39 namespace layers { 40 41 class AsyncCanvasRenderer; 42 class ImageClient; 43 class ImageContainer; 44 class ImageContainerListener; 45 class ImageBridgeParent; 46 class CompositableClient; 47 struct CompositableTransaction; 48 class Image; 49 class TextureClient; 50 class SynchronousTask; 51 struct AllocShmemParams; 52 53 /** 54 * Returns true if the current thread is the ImageBrdigeChild's thread. 55 * 56 * Can be called from any thread. 57 */ 58 bool InImageBridgeChildThread(); 59 60 /** 61 * The ImageBridge protocol is meant to allow ImageContainers to forward images 62 * directly to the compositor thread/process without using the main thread. 63 * 64 * ImageBridgeChild is a CompositableForwarder just like ShadowLayerForwarder. 65 * This means it also does transactions with the compositor thread/process, 66 * except that the transactions are restricted to operations on the 67 * Compositables and cannot contain messages affecting layers directly. 68 * 69 * ImageBridgeChild is also a ISurfaceAllocator. It can be used to allocate or 70 * deallocate data that is shared with the compositor. The main differerence 71 * with other ISurfaceAllocators is that some of its overriden methods can be 72 * invoked from any thread. 73 * 74 * There are three important phases in the ImageBridge protocol. These three 75 * steps can do different things depending if (A) the ImageContainer uses 76 * ImageBridge or (B) it does not use ImageBridge: 77 * 78 * - When an ImageContainer calls its method SetCurrentImage: 79 * - (A) The image is sent directly to the compositor process through the 80 * ImageBridge IPDL protocol. 81 * On the compositor side the image is stored in a global table that 82 * associates the image with an ID corresponding to the ImageContainer, and a 83 * composition is triggered. 84 * - (B) Since it does not have an ImageBridge, the image is not sent yet. 85 * instead the will be sent to the compositor during the next layer 86 * transaction (on the main thread). 87 * 88 * - During a Layer transaction: 89 * - (A) The ImageContainer uses ImageBridge. The image is already available 90 * to the compositor process because it has been sent with SetCurrentImage. 91 * Yet, the CompositableHost on the compositor side will needs the ID 92 * referring to the ImageContainer to access the Image. So during the Swap 93 * operation that happens in the transaction, we swap the container ID rather 94 * than the image data. 95 * - (B) Since the ImageContainer does not use ImageBridge, the image data is 96 * swaped. 97 * 98 * - During composition: 99 * - (A) The CompositableHost has an AsyncID, it looks up the ID in the 100 * global table to see if there is an image. If there is no image, nothing is 101 * rendered. 102 * - (B) The CompositableHost has image data rather than an ID (meaning it is 103 * not using ImageBridge), then it just composites the image data normally. 104 * 105 * This means that there might be a possibility for the ImageBridge to send the 106 * first frame before the first layer transaction that will pass the container 107 * ID to the CompositableHost happens. In this (unlikely) case the layer is not 108 * composited until the layer transaction happens. This means this scenario is 109 * not harmful. 110 * 111 * Since sending an image through imageBridge triggers compositing, the main 112 * thread is not used at all (except for the very first transaction that 113 * provides the CompositableHost with an AsyncID). 114 */ 115 class ImageBridgeChild final : public PImageBridgeChild, 116 public CompositableForwarder, 117 public TextureForwarder { 118 friend class ImageContainer; 119 120 typedef InfallibleTArray<AsyncParentMessageData> AsyncParentMessageArray; 121 122 public: 123 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageBridgeChild, override); 124 GetTextureForwarder()125 TextureForwarder* GetTextureForwarder() override { return this; } GetLayersIPCActor()126 LayersIPCActor* GetLayersIPCActor() override { return this; } 127 128 /** 129 * Creates the image bridge with a dedicated thread for ImageBridgeChild. 130 * 131 * We may want to use a specifi thread in the future. In this case, use 132 * CreateWithThread instead. 133 */ 134 static void InitSameProcess(uint32_t aNamespace); 135 136 static void InitWithGPUProcess(Endpoint<PImageBridgeChild>&& aEndpoint, 137 uint32_t aNamespace); 138 static bool InitForContent(Endpoint<PImageBridgeChild>&& aEndpoint, 139 uint32_t aNamespace); 140 static bool ReinitForContent(Endpoint<PImageBridgeChild>&& aEndpoint, 141 uint32_t aNamespace); 142 143 /** 144 * Destroys the image bridge by calling DestroyBridge, and destroys the 145 * ImageBridge's thread. 146 * 147 * If you don't want to destroy the thread, call DestroyBridge directly 148 * instead. 149 */ 150 static void ShutDown(); 151 152 /** 153 * returns the singleton instance. 154 * 155 * can be called from any thread. 156 */ 157 static RefPtr<ImageBridgeChild> GetSingleton(); 158 159 static void IdentifyCompositorTextureHost( 160 const TextureFactoryIdentifier& aIdentifier); 161 162 void BeginTransaction(); 163 void EndTransaction(); 164 165 /** 166 * Returns the ImageBridgeChild's thread. 167 * 168 * Can be called from any thread. 169 */ 170 base::Thread* GetThread() const; 171 172 /** 173 * Returns the ImageBridgeChild's message loop. 174 * 175 * Can be called from any thread. 176 */ 177 virtual MessageLoop* GetMessageLoop() const override; 178 GetParentPid()179 virtual base::ProcessId GetParentPid() const override { return OtherPid(); } 180 181 virtual PTextureChild* AllocPTextureChild( 182 const SurfaceDescriptor& aSharedData, const ReadLockDescriptor& aReadLock, 183 const LayersBackend& aLayersBackend, const TextureFlags& aFlags, 184 const uint64_t& aSerial, 185 const wr::MaybeExternalImageId& aExternalImageId) override; 186 187 virtual bool DeallocPTextureChild(PTextureChild* actor) override; 188 189 PMediaSystemResourceManagerChild* AllocPMediaSystemResourceManagerChild() 190 override; 191 bool DeallocPMediaSystemResourceManagerChild( 192 PMediaSystemResourceManagerChild* aActor) override; 193 194 virtual mozilla::ipc::IPCResult RecvParentAsyncMessages( 195 InfallibleTArray<AsyncParentMessageData>&& aMessages) override; 196 197 virtual mozilla::ipc::IPCResult RecvDidComposite( 198 InfallibleTArray<ImageCompositeNotification>&& aNotifications) override; 199 200 // Create an ImageClient from any thread. 201 RefPtr<ImageClient> CreateImageClient(CompositableType aType, 202 ImageContainer* aImageContainer); 203 204 // Create an ImageClient from the ImageBridge thread. 205 RefPtr<ImageClient> CreateImageClientNow(CompositableType aType, 206 ImageContainer* aImageContainer); 207 208 already_AddRefed<CanvasClient> CreateCanvasClient( 209 CanvasClient::CanvasClientType aType, TextureFlags aFlag); 210 void UpdateAsyncCanvasRenderer(AsyncCanvasRenderer* aClient); 211 void UpdateImageClient(RefPtr<ImageContainer> aContainer); 212 213 /** 214 * Flush all Images sent to CompositableHost. 215 */ 216 void FlushAllImages(ImageClient* aClient, ImageContainer* aContainer); 217 IPCOpen()218 virtual bool IPCOpen() const override { return mCanSend; } 219 220 private: 221 /** 222 * This must be called by the static function DeleteImageBridgeSync defined 223 * in ImageBridgeChild.cpp ONLY. 224 */ 225 ~ImageBridgeChild(); 226 227 // Helpers for dispatching. 228 already_AddRefed<CanvasClient> CreateCanvasClientNow( 229 CanvasClient::CanvasClientType aType, TextureFlags aFlags); 230 void CreateCanvasClientSync(SynchronousTask* aTask, 231 CanvasClient::CanvasClientType aType, 232 TextureFlags aFlags, 233 RefPtr<CanvasClient>* const outResult); 234 235 void CreateImageClientSync(SynchronousTask* aTask, 236 RefPtr<ImageClient>* result, 237 CompositableType aType, 238 ImageContainer* aImageContainer); 239 240 void UpdateAsyncCanvasRendererNow(AsyncCanvasRenderer* aClient); 241 void UpdateAsyncCanvasRendererSync(SynchronousTask* aTask, 242 AsyncCanvasRenderer* aWrapper); 243 244 void FlushAllImagesSync(SynchronousTask* aTask, ImageClient* aClient, 245 ImageContainer* aContainer); 246 247 void ProxyAllocShmemNow(SynchronousTask* aTask, AllocShmemParams* aParams); 248 void ProxyDeallocShmemNow(SynchronousTask* aTask, Shmem* aShmem, 249 bool* aResult); 250 251 void UpdateTextureFactoryIdentifier( 252 const TextureFactoryIdentifier& aIdentifier); 253 254 public: 255 // CompositableForwarder 256 257 virtual void Connect(CompositableClient* aCompositable, 258 ImageContainer* aImageContainer) override; 259 UsesImageBridge()260 virtual bool UsesImageBridge() const override { return true; } 261 262 /** 263 * See CompositableForwarder::UseTextures 264 */ 265 virtual void UseTextures( 266 CompositableClient* aCompositable, 267 const nsTArray<TimedTextureClient>& aTextures) override; 268 virtual void UseComponentAlphaTextures( 269 CompositableClient* aCompositable, TextureClient* aClientOnBlack, 270 TextureClient* aClientOnWhite) override; 271 272 void ReleaseCompositable(const CompositableHandle& aHandle) override; 273 274 void ForgetImageContainer(const CompositableHandle& aHandle); 275 276 /** 277 * Hold TextureClient ref until end of usage on host side if 278 * TextureFlags::RECYCLE is set. Host side's usage is checked via 279 * CompositableRef. 280 */ 281 void HoldUntilCompositableRefReleasedIfNecessary(TextureClient* aClient); 282 283 /** 284 * Notify id of Texture When host side end its use. Transaction id is used to 285 * make sure if there is no newer usage. 286 */ 287 void NotifyNotUsed(uint64_t aTextureId, uint64_t aFwdTransactionId); 288 289 virtual void CancelWaitForRecycle(uint64_t aTextureId) override; 290 291 virtual bool DestroyInTransaction(PTextureChild* aTexture) override; 292 bool DestroyInTransaction(const CompositableHandle& aHandle); 293 294 virtual void RemoveTextureFromCompositable(CompositableClient* aCompositable, 295 TextureClient* aTexture) override; 296 UseTiledLayerBuffer(CompositableClient * aCompositable,const SurfaceDescriptorTiles & aTileLayerDescriptor)297 virtual void UseTiledLayerBuffer( 298 CompositableClient* aCompositable, 299 const SurfaceDescriptorTiles& aTileLayerDescriptor) override { 300 MOZ_CRASH("should not be called"); 301 } 302 UpdateTextureRegion(CompositableClient * aCompositable,const ThebesBufferData & aThebesBufferData,const nsIntRegion & aUpdatedRegion)303 virtual void UpdateTextureRegion(CompositableClient* aCompositable, 304 const ThebesBufferData& aThebesBufferData, 305 const nsIntRegion& aUpdatedRegion) override { 306 MOZ_CRASH("should not be called"); 307 } 308 309 // ISurfaceAllocator 310 311 /** 312 * See ISurfaceAllocator.h 313 * Can be used from any thread. 314 * If used outside the ImageBridgeChild thread, it will proxy a synchronous 315 * call on the ImageBridgeChild thread. 316 */ 317 virtual bool AllocUnsafeShmem( 318 size_t aSize, mozilla::ipc::SharedMemory::SharedMemoryType aShmType, 319 mozilla::ipc::Shmem* aShmem) override; 320 virtual bool AllocShmem(size_t aSize, 321 mozilla::ipc::SharedMemory::SharedMemoryType aShmType, 322 mozilla::ipc::Shmem* aShmem) override; 323 324 /** 325 * See ISurfaceAllocator.h 326 * Can be used from any thread. 327 * If used outside the ImageBridgeChild thread, it will proxy a synchronous 328 * call on the ImageBridgeChild thread. 329 */ 330 virtual bool DeallocShmem(mozilla::ipc::Shmem& aShmem) override; 331 332 virtual PTextureChild* CreateTexture( 333 const SurfaceDescriptor& aSharedData, const ReadLockDescriptor& aReadLock, 334 LayersBackend aLayersBackend, TextureFlags aFlags, uint64_t aSerial, 335 wr::MaybeExternalImageId& aExternalImageId, 336 nsIEventTarget* aTarget = nullptr) override; 337 338 virtual bool IsSameProcess() const override; 339 UpdateFwdTransactionId()340 virtual void UpdateFwdTransactionId() override { ++mFwdTransactionId; } GetFwdTransactionId()341 virtual uint64_t GetFwdTransactionId() override { return mFwdTransactionId; } 342 InForwarderThread()343 bool InForwarderThread() override { return InImageBridgeChildThread(); } 344 345 virtual void HandleFatalError(const char* aName, 346 const char* aMsg) const override; 347 348 virtual wr::MaybeExternalImageId GetNextExternalImageId() override; 349 350 protected: 351 explicit ImageBridgeChild(uint32_t aNamespace); 352 bool DispatchAllocShmemInternal(size_t aSize, 353 SharedMemory::SharedMemoryType aType, 354 Shmem* aShmem, bool aUnsafe); 355 356 void Bind(Endpoint<PImageBridgeChild>&& aEndpoint); 357 void BindSameProcess(RefPtr<ImageBridgeParent> aParent); 358 359 void SendImageBridgeThreadId(); 360 361 void WillShutdown(); 362 void ShutdownStep1(SynchronousTask* aTask); 363 void ShutdownStep2(SynchronousTask* aTask); 364 void MarkShutDown(); 365 366 void ActorDestroy(ActorDestroyReason aWhy) override; 367 void DeallocPImageBridgeChild() override; 368 369 bool CanSend() const; 370 bool CanPostTask() const; 371 372 static void ShutdownSingleton(); 373 374 private: 375 uint32_t mNamespace; 376 377 CompositableTransaction* mTxn; 378 379 bool mCanSend; 380 mozilla::Atomic<bool> mDestroyed; 381 382 /** 383 * Transaction id of CompositableForwarder. 384 * It is incrementaed by UpdateFwdTransactionId() in each BeginTransaction() 385 * call. 386 */ 387 uint64_t mFwdTransactionId; 388 389 /** 390 * Hold TextureClients refs until end of their usages on host side. 391 * It defer calling of TextureClient recycle callback. 392 */ 393 nsRefPtrHashtable<nsUint64HashKey, TextureClient> mTexturesWaitingRecycled; 394 395 /** 396 * Mapping from async compositable IDs to image containers. 397 */ 398 Mutex mContainerMapLock; 399 nsRefPtrHashtable<nsUint64HashKey, ImageContainerListener> 400 mImageContainerListeners; 401 }; 402 403 } // namespace layers 404 } // namespace mozilla 405 406 #endif 407