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/. */
7 #ifndef mozilla_layers_CanvasDrawEventRecorder_h
8 #define mozilla_layers_CanvasDrawEventRecorder_h
12 #include "mozilla/Atomics.h"
13 #include "mozilla/gfx/DrawEventRecorder.h"
14 #include "mozilla/ipc/CrossProcessSemaphore.h"
15 #include "mozilla/ipc/SharedMemoryBasic.h"
16 #include "mozilla/layers/LayersTypes.h"
17 #include "mozilla/RefPtr.h"
18 #include "mozilla/UniquePtr.h"
22 using EventType
= gfx::RecordedEvent::EventType
;
25 class ThreadSafeWorkerRef
;
30 typedef mozilla::ipc::SharedMemoryBasic::Handle Handle
;
31 typedef mozilla::CrossProcessSemaphoreHandle CrossProcessSemaphoreHandle
;
33 class CanvasDrawEventRecorder final
: public gfx::DrawEventRecorderPrivate
,
34 public gfx::ContiguousBufferStream
{
36 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(CanvasDrawEventRecorder
, final
)
38 explicit CanvasDrawEventRecorder(dom::ThreadSafeWorkerRef
* aWorkerRef
);
39 ~CanvasDrawEventRecorder() override
;
41 enum class State
: uint32_t {
45 * This is the important state to make sure the other side signals or starts
46 * us as soon as data or space is available. We set AboutToWait first and
47 * then re-check the condition. If we went straight to Waiting or Stopped
48 * then in between the last check and setting the state, the other side
49 * could have used all available data or space and never have signaled us
50 * because it didn't know we were about to wait, causing a deadlock.
51 * While we are in this state, the other side must wait until we resolve the
52 * AboutToWait state to one of the other states and then signal or start us
63 Atomic
<int64_t> eventCount
;
64 Atomic
<int64_t> writerWaitCount
;
65 Atomic
<State
> writerState
;
67 Atomic
<int64_t> processedCount
;
68 Atomic
<State
> readerState
;
73 virtual ~Helpers() = default;
75 virtual bool InitTranslator(TextureType aTextureType
,
76 TextureType aWebglTextureType
,
77 gfx::BackendType aBackendType
,
79 nsTArray
<Handle
>&& aBufferHandles
,
81 CrossProcessSemaphoreHandle
&& aReaderSem
,
82 CrossProcessSemaphoreHandle
&& aWriterSem
) = 0;
84 virtual bool AddBuffer(Handle
&& aBufferHandle
, uint64_t aBufferSize
) = 0;
87 * @returns true if the reader of the CanvasEventRingBuffer has permanently
88 * stopped processing, otherwise returns false.
90 virtual bool ReaderClosed() = 0;
93 * Causes the reader to resume processing when it is in a stopped state.
95 virtual bool RestartReader() = 0;
98 bool Init(TextureType aTextureType
, TextureType aWebglTextureType
,
99 gfx::BackendType aBackendType
, UniquePtr
<Helpers
> aHelpers
);
102 * Record an event for processing by the CanvasParent's CanvasTranslator.
103 * @param aEvent the event to record
105 void RecordEvent(const gfx::RecordedEvent
& aEvent
) final
;
107 void DetachResources() final
;
109 void AddPendingDeletion(std::function
<void()>&& aPendingDeletion
) override
;
111 void StoreSourceSurfaceRecording(gfx::SourceSurface
* aSurface
,
112 const char* aReason
) final
;
114 gfx::RecorderType
GetRecorderType() const override
{
115 return gfx::RecorderType::CANVAS
;
118 void Flush() final
{ NS_ASSERT_OWNINGTHREAD(CanvasDrawEventRecorder
); }
120 int64_t CreateCheckpoint();
123 * Waits until the given checkpoint has been read by the translator.
125 * @params aCheckpoint the checkpoint to wait for
126 * @returns true if the checkpoint was reached, false if the reader is closed
129 bool WaitForCheckpoint(int64_t aCheckpoint
);
131 TextureType
GetTextureType() { return mTextureType
; }
133 void DropFreeBuffers();
135 void ClearProcessedExternalSurfaces();
138 gfx::ContiguousBuffer
& GetContiguousBuffer(size_t aSize
) final
;
140 void IncrementEventCount() final
;
143 void WriteInternalEvent(EventType aEventType
);
145 void CheckAndSignalReader();
147 void QueueProcessPendingDeletions(
148 RefPtr
<CanvasDrawEventRecorder
>&& aRecorder
);
149 void QueueProcessPendingDeletionsLocked(
150 RefPtr
<CanvasDrawEventRecorder
>&& aRecorder
);
152 size_t mDefaultBufferSize
;
153 size_t mMaxDefaultBuffers
;
154 uint32_t mMaxSpinCount
;
155 uint32_t mDropBufferLimit
;
156 uint32_t mDropBufferOnZero
;
158 UniquePtr
<Helpers
> mHelpers
;
160 TextureType mTextureType
= TextureType::Unknown
;
161 RefPtr
<ipc::SharedMemoryBasic
> mHeaderShmem
;
162 Header
* mHeader
= nullptr;
164 struct CanvasBuffer
: public gfx::ContiguousBuffer
{
165 RefPtr
<ipc::SharedMemoryBasic
> shmem
;
167 CanvasBuffer() : ContiguousBuffer(nullptr) {}
169 explicit CanvasBuffer(RefPtr
<ipc::SharedMemoryBasic
>&& aShmem
)
170 : ContiguousBuffer(static_cast<char*>(aShmem
->memory()),
172 shmem(std::move(aShmem
)) {}
174 size_t Capacity() { return shmem
? shmem
->Size() : 0; }
177 struct RecycledBuffer
{
178 RefPtr
<ipc::SharedMemoryBasic
> shmem
;
179 int64_t eventCount
= 0;
180 explicit RecycledBuffer(RefPtr
<ipc::SharedMemoryBasic
>&& aShmem
,
182 : shmem(std::move(aShmem
)), eventCount(aEventCount
) {}
183 size_t Capacity() { return shmem
->Size(); }
186 CanvasBuffer mCurrentBuffer
;
187 std::queue
<RecycledBuffer
> mRecycledBuffers
;
189 UniquePtr
<CrossProcessSemaphore
> mWriterSemaphore
;
190 UniquePtr
<CrossProcessSemaphore
> mReaderSemaphore
;
192 RefPtr
<dom::ThreadSafeWorkerRef
> mWorkerRef
;
193 bool mIsOnWorker
= false;
196 } // namespace layers
197 } // namespace mozilla
199 #endif // mozilla_layers_CanvasDrawEventRecorder_h