DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (56e7b9127e89)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_layers_CompositorBridgeChild_h
#define mozilla_layers_CompositorBridgeChild_h

#include "base/basictypes.h"            // for DISALLOW_EVIL_CONSTRUCTORS
#include "mozilla/Assertions.h"         // for MOZ_ASSERT_HELPER2
#include "mozilla/Attributes.h"         // for override
#include "mozilla/Monitor.h"
#include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/layers/PCompositorBridgeChild.h"
#include "mozilla/layers/TextureForwarder.h" // for TextureForwarder
#include "mozilla/layers/PaintThread.h" // for PaintThread
#include "mozilla/webrender/WebRenderTypes.h"
#include "nsClassHashtable.h"           // for nsClassHashtable
#include "nsCOMPtr.h"                   // for nsCOMPtr
#include "nsHashKeys.h"                 // for nsUint64HashKey
#include "nsISupportsImpl.h"            // for NS_INLINE_DECL_REFCOUNTING
#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
#include "nsWeakReference.h"

#include <unordered_map>

namespace mozilla {

namespace dom {
class TabChild;
} // namespace dom

namespace widget {
class CompositorWidget;
} // namespace widget

namespace layers {

using mozilla::dom::TabChild;

class IAPZCTreeManager;
class APZCTreeManagerChild;
class ClientLayerManager;
class CompositorBridgeParent;
class CompositorManagerChild;
class CompositorOptions;
class TextureClient;
class TextureClientPool;
struct FrameMetrics;

class CompositorBridgeChild final : public PCompositorBridgeChild,
                                    public TextureForwarder
{
  typedef InfallibleTArray<AsyncParentMessageData> AsyncParentMessageArray;

public:
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorBridgeChild, override);

  explicit CompositorBridgeChild(CompositorManagerChild* aManager);

  /**
   * Initialize the singleton compositor bridge for a content process.
   */
  void InitForContent(uint32_t aNamespace);

  void InitForWidget(uint64_t aProcessToken,
                     LayerManager* aLayerManager,
                     uint32_t aNamespace);

  void Destroy();

  /**
   * Lookup the FrameMetrics shared by the compositor process with the
   * associated FrameMetrics::ViewID. The returned FrameMetrics is used
   * in progressive paint calculations.
   */
  bool LookupCompositorFrameMetrics(const FrameMetrics::ViewID aId, FrameMetrics&);

  static CompositorBridgeChild* Get();

  static bool ChildProcessHasCompositorBridge();

  // Returns whether the compositor is in the GPU process (false if in the UI
  // process). This may only be called on the main thread.
  static bool CompositorIsInGPUProcess();

  virtual mozilla::ipc::IPCResult
  RecvDidComposite(const LayersId& aId,
                   const TransactionId& aTransactionId,
                   const TimeStamp& aCompositeStart,
                   const TimeStamp& aCompositeEnd) override;

  virtual mozilla::ipc::IPCResult
  RecvInvalidateLayers(const LayersId& aLayersId) override;

  virtual mozilla::ipc::IPCResult
  RecvUpdatePluginConfigurations(const LayoutDeviceIntPoint& aContentOffset,
                                 const LayoutDeviceIntRegion& aVisibleRegion,
                                 nsTArray<PluginWindowData>&& aPlugins) override;

  virtual mozilla::ipc::IPCResult
  RecvCaptureAllPlugins(const uintptr_t& aParentWidget) override;

  virtual mozilla::ipc::IPCResult
  RecvHideAllPlugins(const uintptr_t& aParentWidget) override;

  virtual PTextureChild* AllocPTextureChild(const SurfaceDescriptor& aSharedData,
                                            const ReadLockDescriptor& aReadLock,
                                            const LayersBackend& aLayersBackend,
                                            const TextureFlags& aFlags,
                                            const LayersId& aId,
                                            const uint64_t& aSerial,
                                            const wr::MaybeExternalImageId& aExternalImageId) override;

  virtual bool DeallocPTextureChild(PTextureChild* actor) override;

  virtual mozilla::ipc::IPCResult
  RecvParentAsyncMessages(InfallibleTArray<AsyncParentMessageData>&& aMessages) override;
  virtual PTextureChild* CreateTexture(const SurfaceDescriptor& aSharedData,
                                       const ReadLockDescriptor& aReadLock,
                                       LayersBackend aLayersBackend,
                                       TextureFlags aFlags,
                                       uint64_t aSerial,
                                       wr::MaybeExternalImageId& aExternalImageId,
                                       nsIEventTarget* aTarget) override;

  /**
   * Request that the parent tell us when graphics are ready on GPU.
   * When we get that message, we bounce it to the TabParent via
   * the TabChild
   * @param tabChild The object to bounce the note to.  Non-NULL.
   */
  void RequestNotifyAfterRemotePaint(TabChild* aTabChild);

  void CancelNotifyAfterRemotePaint(TabChild* aTabChild);

  // Beware that these methods don't override their super-class equivalent (which
  // are not virtual), they just overload them.
  // All of these Send* methods just add a sanity check (that it is not too late
  // send a message) and forward the call to the super-class's equivalent method.
  // This means that it is correct to call directly the super-class methods, but
  // you won't get the extra safety provided here.
  bool SendWillClose();
  bool SendPause();
  bool SendResume();
  bool SendNotifyChildCreated(const LayersId& id, CompositorOptions* aOptions);
  bool SendAdoptChild(const LayersId& id);
  bool SendMakeSnapshot(const SurfaceDescriptor& inSnapshot, const gfx::IntRect& dirtyRect);
  bool SendFlushRendering();
  bool SendGetTileSize(int32_t* tileWidth, int32_t* tileHeight);
  bool SendStartFrameTimeRecording(const int32_t& bufferSize, uint32_t* startIndex);
  bool SendStopFrameTimeRecording(const uint32_t& startIndex, nsTArray<float>* intervals);
  bool SendNotifyRegionInvalidated(const nsIntRegion& region);
  bool SendRequestNotifyAfterRemotePaint();
  bool SendAllPluginsCaptured();
  bool IsSameProcess() const override;

  virtual bool IPCOpen() const override { return mCanSend; }

  static void ShutDown();

  void UpdateFwdTransactionId() { ++mFwdTransactionId; }
  uint64_t GetFwdTransactionId() { return mFwdTransactionId; }

  /**
   * Hold TextureClient ref until end of usage on host side if TextureFlags::RECYCLE is set.
   * Host side's usage is checked via CompositableRef.
   */
  void HoldUntilCompositableRefReleasedIfNecessary(TextureClient* aClient);

  /**
   * Notify id of Texture When host side end its use. Transaction id is used to
   * make sure if there is no newer usage.
   */
  void NotifyNotUsed(uint64_t aTextureId, uint64_t aFwdTransactionId);

  virtual void CancelWaitForRecycle(uint64_t aTextureId) override;

  TextureClientPool* GetTexturePool(KnowsCompositor* aAllocator,
                                    gfx::SurfaceFormat aFormat,
                                    TextureFlags aFlags);
  void ClearTexturePool();

  virtual FixedSizeSmallShmemSectionAllocator* GetTileLockAllocator() override;

  void HandleMemoryPressure();

  virtual MessageLoop* GetMessageLoop() const override { return mMessageLoop; }

  virtual base::ProcessId GetParentPid() const override { return OtherPid(); }

  virtual bool AllocUnsafeShmem(size_t aSize,
                                mozilla::ipc::SharedMemory::SharedMemoryType aShmType,
                                mozilla::ipc::Shmem* aShmem) override;
  virtual bool AllocShmem(size_t aSize,
                          mozilla::ipc::SharedMemory::SharedMemoryType aShmType,
                          mozilla::ipc::Shmem* aShmem) override;
  virtual bool DeallocShmem(mozilla::ipc::Shmem& aShmem) override;

  PCompositorWidgetChild* AllocPCompositorWidgetChild(const CompositorWidgetInitData& aInitData) override;
  bool DeallocPCompositorWidgetChild(PCompositorWidgetChild* aActor) override;

  PAPZCTreeManagerChild* AllocPAPZCTreeManagerChild(const LayersId& aLayersId) override;
  bool DeallocPAPZCTreeManagerChild(PAPZCTreeManagerChild* aActor) override;

  PAPZChild* AllocPAPZChild(const LayersId& aLayersId) override;
  bool DeallocPAPZChild(PAPZChild* aActor) override;

  void WillEndTransaction();

  PWebRenderBridgeChild* AllocPWebRenderBridgeChild(const wr::PipelineId& aPipelineId,
                                                    const LayoutDeviceIntSize&,
                                                    TextureFactoryIdentifier*,
                                                    wr::IdNamespace*) override;
  bool DeallocPWebRenderBridgeChild(PWebRenderBridgeChild* aActor) override;

  wr::MaybeExternalImageId GetNextExternalImageId() override;

  wr::PipelineId GetNextPipelineId();

  // Must only be called from the main thread. Ensures that any paints from
  // previous frames have been flushed. The main thread blocks until the
  // operation completes.
  void FlushAsyncPaints();

  // Must only be called from the main thread. Notifies the CompositorBridge
  // that the paint thread is going to begin painting asynchronously.
  void NotifyBeginAsyncPaint(PaintTask* aTask);

  // Must only be called from the paint thread. Notifies the CompositorBridge
  // that the paint thread has finished an asynchronous paint request.
  bool NotifyFinishedAsyncWorkerPaint(PaintTask* aTask);

  // Must only be called from the main thread. Notifies the CompositorBridge
  // that all work has been submitted to the paint thread or paint worker
  // threads, and returns whether all paints are completed. If this returns
  // true, then an AsyncEndLayerTransaction must be queued, otherwise once
  // NotifyFinishedAsyncWorkerPaint returns true, an AsyncEndLayerTransaction
  // must be executed.
  bool NotifyBeginAsyncEndLayerTransaction(SyncObjectClient* aSyncObject);

  // Must only be called from the paint thread. Notifies the CompositorBridge
  // that the paint thread has finished all async paints and and may do the
  // requested texture sync and resume sending messages.
  void NotifyFinishedAsyncEndLayerTransaction();

  // Must only be called from the main thread. Notifies the CompoistorBridge
  // that a transaction is about to be sent, and if the paint thread is
  // currently painting, to begin delaying IPC messages.
  void PostponeMessagesIfAsyncPainting();

private:
  // Private destructor, to discourage deletion outside of Release():
  virtual ~CompositorBridgeChild();

  // Must only be called from the paint thread. If the main thread is delaying
  // IPC messages, this forwards all such delayed IPC messages to the I/O thread
  // and resumes IPC.
  void ResumeIPCAfterAsyncPaint();

  void AfterDestroy();

  virtual PLayerTransactionChild*
    AllocPLayerTransactionChild(const nsTArray<LayersBackend>& aBackendHints,
                                const LayersId& aId) override;

  virtual bool DeallocPLayerTransactionChild(PLayerTransactionChild *aChild) override;

  virtual void ActorDestroy(ActorDestroyReason aWhy) override;

  virtual mozilla::ipc::IPCResult RecvSharedCompositorFrameMetrics(const mozilla::ipc::SharedMemoryBasic::Handle& metrics,
                                                                   const CrossProcessMutexHandle& handle,
                                                                   const LayersId& aLayersId,
                                                                   const uint32_t& aAPZCId) override;

  virtual mozilla::ipc::IPCResult RecvReleaseSharedCompositorFrameMetrics(const ViewID& aId,
                                                                          const uint32_t& aAPZCId) override;

  virtual mozilla::ipc::IPCResult
  RecvRemotePaintIsReady() override;

  mozilla::ipc::IPCResult RecvObserveLayersUpdate(const LayersId& aLayersId,
                                                  const LayersObserverEpoch& aEpoch,
                                                  const bool& aActive) override;

  virtual mozilla::ipc::IPCResult
  RecvNotifyWebRenderError(const WebRenderError& aError) override;

  uint64_t GetNextResourceId();

  void ClearSharedFrameMetricsData(LayersId aLayersId);

  // Class used to store the shared FrameMetrics, mutex, and APZCId  in a hash table
  class SharedFrameMetricsData {
  public:
    SharedFrameMetricsData(
        const mozilla::ipc::SharedMemoryBasic::Handle& metrics,
        const CrossProcessMutexHandle& handle,
        const LayersId& aLayersId,
        const uint32_t& aAPZCId);

    ~SharedFrameMetricsData();

    void CopyFrameMetrics(FrameMetrics* aFrame);
    FrameMetrics::ViewID GetViewID();
    LayersId GetLayersId() const;
    uint32_t GetAPZCId();

  private:
    // Pointer to the class that allows access to the shared memory that contains
    // the shared FrameMetrics
    RefPtr<mozilla::ipc::SharedMemoryBasic> mBuffer;
    CrossProcessMutex* mMutex;
    LayersId mLayersId;
    // Unique ID of the APZC that is sharing the FrameMetrics
    uint32_t mAPZCId;
  };

  RefPtr<CompositorManagerChild> mCompositorManager;

  RefPtr<LayerManager> mLayerManager;

  uint32_t mIdNamespace;
  uint32_t mResourceId;

  // When not multi-process, hold a reference to the CompositorBridgeParent to keep it
  // alive. This reference should be null in multi-process.
  RefPtr<CompositorBridgeParent> mCompositorBridgeParent;

  // The ViewID of the FrameMetrics is used as the key for this hash table.
  // While this should be safe to use since the ViewID is unique
  nsClassHashtable<nsUint64HashKey, SharedFrameMetricsData> mFrameMetricsTable;

  // Weakly hold the TabChild that made a request to be alerted when
  // the transaction has been received.
  nsWeakPtr mWeakTabChild;      // type is TabChild

  DISALLOW_EVIL_CONSTRUCTORS(CompositorBridgeChild);

  // True until the beginning of the two-step shutdown sequence of this actor.
  bool mCanSend;

  // False until the actor is destroyed.
  bool mActorDestroyed;

  /**
   * Transaction id of ShadowLayerForwarder.
   * It is incrementaed by UpdateFwdTransactionId() in each BeginTransaction() call.
   */
  uint64_t mFwdTransactionId;

  /**
   * Hold TextureClients refs until end of their usages on host side.
   * It defer calling of TextureClient recycle callback.
   */
  std::unordered_map<uint64_t, RefPtr<TextureClient>> mTexturesWaitingRecycled;

  MessageLoop* mMessageLoop;

  AutoTArray<RefPtr<TextureClientPool>,2> mTexturePools;

  uint64_t mProcessToken;

  FixedSizeSmallShmemSectionAllocator* mSectionAllocator;

  // TextureClients that must be kept alive during async painting. This
  // is only accessed on the main thread.
  nsTArray<RefPtr<TextureClient>> mTextureClientsForAsyncPaint;

  // Off-Main-Thread Painting state. This covers access to the OMTP-related
  // state below.
  Monitor mPaintLock;

  // Contains the number of asynchronous paints that were queued since the
  // beginning of the last async transaction, and the time stamp of when
  // that was
  size_t mTotalAsyncPaints;
  TimeStamp mAsyncTransactionBegin;

  // Contains the number of outstanding asynchronous paints tied to a
  // PLayerTransaction on this bridge. This is R/W on both the main and paint
  // threads, and must be accessed within the paint lock.
  size_t mOutstandingAsyncPaints;

  // Whether we are waiting for an async paint end transaction
  bool mOutstandingAsyncEndTransaction;
  RefPtr<SyncObjectClient> mOutstandingAsyncSyncObject;

  // True if this CompositorBridge is currently delaying its messages until the
  // paint thread completes. This is R/W on both the main and paint threads, and
  // must be accessed within the paint lock.
  bool mIsDelayingForAsyncPaints;

  uintptr_t mSlowFlushCount;
  uintptr_t mTotalFlushCount;
};

} // namespace layers
} // namespace mozilla

#endif // mozilla_layers_CompositorBrigedChild_h