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