tor-browser

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

CanvasDrawEventRecorder.h (6479B)


      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_CanvasDrawEventRecorder_h
      8 #define mozilla_layers_CanvasDrawEventRecorder_h
      9 
     10 #include <queue>
     11 
     12 #include "mozilla/Atomics.h"
     13 #include "mozilla/gfx/DrawEventRecorder.h"
     14 #include "mozilla/ipc/CrossProcessSemaphore.h"
     15 #include "mozilla/ipc/SharedMemoryMapping.h"
     16 #include "mozilla/layers/LayersTypes.h"
     17 #include "mozilla/RefPtr.h"
     18 #include "mozilla/UniquePtr.h"
     19 
     20 namespace mozilla {
     21 
     22 using EventType = gfx::RecordedEvent::EventType;
     23 
     24 namespace dom {
     25 class ThreadSafeWorkerRef;
     26 }
     27 
     28 namespace layers {
     29 
     30 typedef mozilla::CrossProcessSemaphoreHandle CrossProcessSemaphoreHandle;
     31 
     32 class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate,
     33                                      public gfx::ContiguousBufferStream {
     34 public:
     35  MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(CanvasDrawEventRecorder, final)
     36 
     37  explicit CanvasDrawEventRecorder(dom::ThreadSafeWorkerRef* aWorkerRef);
     38  ~CanvasDrawEventRecorder() override;
     39 
     40  enum class State : uint32_t {
     41    Processing,
     42 
     43    /**
     44     * This is the important state to make sure the other side signals or starts
     45     * us as soon as data or space is available. We set AboutToWait first and
     46     * then re-check the condition. If we went straight to Waiting or Stopped
     47     * then in between the last check and setting the state, the other side
     48     * could have used all available data or space and never have signaled us
     49     * because it didn't know we were about to wait, causing a deadlock.
     50     * While we are in this state, the other side must wait until we resolve the
     51     * AboutToWait state to one of the other states and then signal or start us
     52     * if it needs to.
     53     */
     54    AboutToWait,
     55    Waiting,
     56    Paused,
     57    Stopped,
     58    Failed,
     59  };
     60 
     61  struct Header {
     62    Atomic<int64_t> eventCount;
     63    Atomic<int64_t> writerWaitCount;
     64    Atomic<State> writerState;
     65    uint8_t padding1[44];
     66    Atomic<int64_t> processedCount;
     67    Atomic<State> readerState;
     68  };
     69 
     70  class Helpers {
     71   public:
     72    virtual ~Helpers() = default;
     73 
     74    virtual bool InitTranslator(
     75        TextureType aTextureType, TextureType aWebglTextureType,
     76        gfx::BackendType aBackendType,
     77        ipc::MutableSharedMemoryHandle&& aReadHandle,
     78        nsTArray<ipc::ReadOnlySharedMemoryHandle>&& aBufferHandles,
     79        CrossProcessSemaphoreHandle&& aReaderSem,
     80        CrossProcessSemaphoreHandle&& aWriterSem) = 0;
     81 
     82    virtual bool AddBuffer(ipc::ReadOnlySharedMemoryHandle&& aBufferHandle) = 0;
     83 
     84    /**
     85     * @returns true if the reader of the CanvasEventRingBuffer has permanently
     86     *          stopped processing, otherwise returns false.
     87     */
     88    virtual bool ReaderClosed() = 0;
     89 
     90    /**
     91     * Causes the reader to resume processing when it is in a stopped state.
     92     */
     93    virtual bool RestartReader() = 0;
     94 
     95    virtual already_AddRefed<layers::CanvasChild> GetCanvasChild() const = 0;
     96  };
     97 
     98  bool Init(TextureType aTextureType, TextureType aWebglTextureType,
     99            gfx::BackendType aBackendType, UniquePtr<Helpers> aHelpers);
    100 
    101  using DrawEventRecorderPrivate::RecordEvent;
    102 
    103  /**
    104   * Record an event for processing by the CanvasParent's CanvasTranslator.
    105   * @param aEvent the event to record
    106   */
    107  void RecordEvent(const gfx::RecordedEvent& aEvent) final;
    108 
    109  void DetachResources() final;
    110 
    111  void AddPendingDeletion(std::function<void()>&& aPendingDeletion) override;
    112 
    113  void StoreSourceSurfaceRecording(gfx::SourceSurface* aSurface,
    114                                   const char* aReason) final;
    115 
    116  void StoreImageRecording(const RefPtr<Image>& aImageOfSurfaceDescriptor,
    117                           const char* aReasony) final;
    118 
    119  gfx::RecorderType GetRecorderType() const override {
    120    return gfx::RecorderType::CANVAS;
    121  }
    122 
    123  void Flush() final { NS_ASSERT_OWNINGTHREAD(CanvasDrawEventRecorder); }
    124 
    125  int64_t CreateCheckpoint();
    126 
    127  /**
    128   * Waits until the given checkpoint has been read by the translator.
    129   *
    130   * @params aCheckpoint the checkpoint to wait for
    131   * @returns true if the checkpoint was reached, false if the reader is closed
    132   *          or we timeout.
    133   */
    134  bool WaitForCheckpoint(int64_t aCheckpoint);
    135 
    136  TextureType GetTextureType() { return mTextureType; }
    137 
    138  void DropFreeBuffers();
    139 
    140  void ClearProcessedExternalSurfaces();
    141 
    142  void ClearProcessedExternalImages();
    143 
    144  already_AddRefed<layers::CanvasChild> GetCanvasChild() const override {
    145    return mHelpers->GetCanvasChild();
    146  }
    147 
    148 protected:
    149  gfx::ContiguousBuffer& GetContiguousBuffer(size_t aSize) final;
    150 
    151  void IncrementEventCount() final;
    152 
    153 private:
    154  void WriteInternalEvent(EventType aEventType);
    155 
    156  void CheckAndSignalReader();
    157 
    158  void QueueProcessPendingDeletions(
    159      RefPtr<CanvasDrawEventRecorder>&& aRecorder);
    160  void QueueProcessPendingDeletionsLocked(
    161      RefPtr<CanvasDrawEventRecorder>&& aRecorder);
    162 
    163  size_t mDefaultBufferSize;
    164  size_t mMaxDefaultBuffers;
    165  uint32_t mMaxSpinCount;
    166  uint32_t mDropBufferLimit;
    167  uint32_t mDropBufferOnZero;
    168 
    169  UniquePtr<Helpers> mHelpers;
    170 
    171  TextureType mTextureType = TextureType::Unknown;
    172  ipc::SharedMemoryMapping mHeaderShmem;
    173  Header* mHeader = nullptr;
    174 
    175  struct CanvasBuffer : public gfx::ContiguousBuffer {
    176    ipc::SharedMemoryMapping shmem;
    177 
    178    CanvasBuffer() : ContiguousBuffer(nullptr) {}
    179 
    180    explicit CanvasBuffer(ipc::SharedMemoryMapping&& aShmem)
    181        : ContiguousBuffer(aShmem.DataAs<char>(), aShmem.Size()),
    182          shmem(std::move(aShmem)) {}
    183 
    184    size_t Capacity() { return shmem ? shmem.Size() : 0; }
    185  };
    186 
    187  struct RecycledBuffer {
    188    ipc::SharedMemoryMapping shmem;
    189    int64_t eventCount = 0;
    190    explicit RecycledBuffer(ipc::SharedMemoryMapping&& aShmem,
    191                            int64_t aEventCount)
    192        : shmem(std::move(aShmem)), eventCount(aEventCount) {}
    193    size_t Capacity() { return shmem.Size(); }
    194  };
    195 
    196  CanvasBuffer mCurrentBuffer;
    197  std::queue<RecycledBuffer> mRecycledBuffers;
    198 
    199  UniquePtr<CrossProcessSemaphore> mWriterSemaphore;
    200  UniquePtr<CrossProcessSemaphore> mReaderSemaphore;
    201 
    202  RefPtr<dom::ThreadSafeWorkerRef> mWorkerRef;
    203  bool mIsOnWorker = false;
    204 };
    205 
    206 }  // namespace layers
    207 }  // namespace mozilla
    208 
    209 #endif  // mozilla_layers_CanvasDrawEventRecorder_h