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