tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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