Bug 1839315: part 4) Link from `SheetLoadData::mWasAlternate` to spec. r=emilio DONTBUILD
[gecko.git] / gfx / layers / CanvasDrawEventRecorder.h
blob65ad577489755e1c8055e529508e86df4cd68902
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
10 #include "mozilla/gfx/DrawEventRecorder.h"
11 #include "mozilla/ipc/CrossProcessSemaphore.h"
12 #include "mozilla/ipc/SharedMemoryBasic.h"
14 namespace mozilla {
15 namespace layers {
17 static const uint8_t kCheckpointEventType = -1;
18 static const uint8_t kDropBufferEventType = -2;
20 class CanvasEventRingBuffer final : public gfx::EventRingBuffer {
21 public:
22 /**
23 * WriterServices allows consumers of CanvasEventRingBuffer to provide
24 * functions required by the write side of a CanvasEventRingBuffer without
25 * introducing unnecessary dependencies on IPC code.
27 class WriterServices {
28 public:
29 virtual ~WriterServices() = default;
31 /**
32 * @returns true if the reader of the CanvasEventRingBuffer has permanently
33 * stopped processing, otherwise returns false.
35 virtual bool ReaderClosed() = 0;
37 /**
38 * Causes the reader to resume processing when it is in a stopped state.
40 virtual void ResumeReader() = 0;
43 /**
44 * ReaderServices allows consumers of CanvasEventRingBuffer to provide
45 * functions required by the read side of a CanvasEventRingBuffer without
46 * introducing unnecessary dependencies on IPC code.
48 class ReaderServices {
49 public:
50 virtual ~ReaderServices() = default;
52 /**
53 * @returns true if the writer of the CanvasEventRingBuffer has permanently
54 * stopped processing, otherwise returns false.
56 virtual bool WriterClosed() = 0;
59 CanvasEventRingBuffer() {}
61 /**
62 * Initializes the shared memory used for the ringbuffer and footers.
63 * @param aOtherPid process ID to share the handles to
64 * @param aReadHandle handle to the shared memory for the buffer
66 bool InitBuffer(base::ProcessId aOtherPid,
67 ipc::SharedMemoryBasic::Handle* aReadHandle);
69 /**
70 * Initialize the write side of a CanvasEventRingBuffer returning handles to
71 * the shared memory for the buffer and the two semaphores for waiting in the
72 * reader and the writer.
74 * @param aOtherPid process ID to share the handles to
75 * @param aReadHandle handle to the shared memory for the buffer
76 * @param aReaderSem reading blocked semaphore
77 * @param aWriterSem writing blocked semaphore
78 * @param aWriterServices provides functions required by the writer
79 * @returns true if initialization succeeds
81 bool InitWriter(base::ProcessId aOtherPid,
82 ipc::SharedMemoryBasic::Handle* aReadHandle,
83 CrossProcessSemaphoreHandle* aReaderSem,
84 CrossProcessSemaphoreHandle* aWriterSem,
85 UniquePtr<WriterServices> aWriterServices);
87 /**
88 * Initialize the read side of a CanvasEventRingBuffer.
90 * @param aReadHandle handle to the shared memory for the buffer
91 * @param aReaderSem reading blocked semaphore
92 * @param aWriterSem writing blocked semaphore
93 * @param aReaderServices provides functions required by the reader
94 * @returns true if initialization succeeds
96 bool InitReader(ipc::SharedMemoryBasic::Handle aReadHandle,
97 CrossProcessSemaphoreHandle aReaderSem,
98 CrossProcessSemaphoreHandle aWriterSem,
99 UniquePtr<ReaderServices> aReaderServices);
102 * Set a new buffer to resume after we have been stopped by the writer.
104 * @param aReadHandle handle to the shared memory for the buffer
105 * @returns true if initialization succeeds
107 bool SetNewBuffer(ipc::SharedMemoryBasic::Handle aReadHandle);
109 bool IsValid() const { return mSharedMemory; }
111 bool good() const final { return mGood; }
113 bool WriterFailed() const { return mWrite && mWrite->state == State::Failed; }
115 void SetIsBad() final {
116 mGood = false;
117 mRead->state = State::Failed;
120 void write(const char* const aData, const size_t aSize) final;
122 bool HasDataToRead();
125 * This will put the reader into a stopped state if there is no more data to
126 * read. If this returns false the caller is responsible for continuing
127 * translation at a later point. If it returns false the writer will start the
128 * translation again when more data is written.
130 * @returns true if stopped
132 bool StopIfEmpty();
135 * Waits for data to become available. This will wait for aTimeout duration
136 * aRetryCount number of times, checking to see if the other side is closed in
137 * between each one.
139 * @param aTimeout duration to wait
140 * @param aRetryCount number of times to retry
141 * @returns true if data is available to read.
143 bool WaitForDataToRead(TimeDuration aTimeout, int32_t aRetryCount);
145 uint8_t ReadNextEvent();
147 void read(char* const aOut, const size_t aSize) final;
150 * Writes a checkpoint event to the buffer.
152 * @returns the write count after the checkpoint has been written
154 uint32_t CreateCheckpoint();
157 * Waits until the given checkpoint has been read from the buffer.
159 * @params aCheckpoint the checkpoint to wait for
160 * @params aTimeout duration to wait while reader is not active
161 * @returns true if the checkpoint was reached, false if the reader is closed
162 * or we timeout.
164 bool WaitForCheckpoint(uint32_t aCheckpoint);
167 * Switch to a different sized buffer.
169 bool SwitchBuffer(base::ProcessId aOtherPid,
170 ipc::SharedMemoryBasic::Handle* aHandle);
173 * Used to send data back to the writer. This is done through the same shared
174 * memory so the writer must wait and read the response after it has submitted
175 * the event that uses this.
177 * @param aData the data to be written back to the writer
178 * @param aSize the number of chars to write
180 void ReturnWrite(const char* aData, size_t aSize);
183 * Used to read data sent back from the reader via ReturnWrite. This is done
184 * through the same shared memory so the writer must wait until all expected
185 * data is read before writing new events to the buffer.
187 * @param aOut the pointer to read into
188 * @param aSize the number of chars to read
190 void ReturnRead(char* aOut, size_t aSize);
192 bool UsingLargeStream() { return mLargeStream; }
194 protected:
195 bool WaitForAndRecalculateAvailableSpace() final;
196 void UpdateWriteTotalsBy(uint32_t aCount) final;
198 private:
199 enum class State : uint32_t {
200 Processing,
203 * This is the important state to make sure the other side signals or starts
204 * us as soon as data or space is available. We set AboutToWait first and
205 * then re-check the condition. If we went straight to Waiting or Stopped
206 * then in between the last check and setting the state, the other side
207 * could have used all available data or space and never have signaled us
208 * because it didn't know we were about to wait, causing a deadlock.
209 * While we are in this state, the other side must wait until we resolve the
210 * AboutToWait state to one of the other states and then signal or start us
211 * if it needs to.
213 AboutToWait,
214 Waiting,
215 Stopped,
216 Failed,
219 struct ReadFooter {
220 Atomic<uint32_t> count;
221 Atomic<uint32_t> returnCount;
222 Atomic<State> state;
225 struct WriteFooter {
226 Atomic<uint32_t> count;
227 Atomic<uint32_t> returnCount;
228 Atomic<uint32_t> requiredDifference;
229 Atomic<State> state;
232 CanvasEventRingBuffer(const CanvasEventRingBuffer&) = delete;
233 void operator=(const CanvasEventRingBuffer&) = delete;
235 void IncrementWriteCountBy(uint32_t aCount);
237 bool WaitForReadCount(uint32_t aReadCount, TimeDuration aTimeout);
239 bool WaitForAndRecalculateAvailableData();
241 void UpdateReadTotalsBy(uint32_t aCount);
242 void IncrementReadCountBy(uint32_t aCount);
244 void CheckAndSignalReader();
246 void CheckAndSignalWriter();
248 uint32_t WaitForBytesToWrite();
250 uint32_t WaitForBytesToRead();
252 uint32_t StreamSize();
254 RefPtr<ipc::SharedMemoryBasic> mSharedMemory;
255 UniquePtr<CrossProcessSemaphore> mReaderSemaphore;
256 UniquePtr<CrossProcessSemaphore> mWriterSemaphore;
257 UniquePtr<WriterServices> mWriterServices;
258 UniquePtr<ReaderServices> mReaderServices;
259 char* mBuf = nullptr;
260 uint32_t mOurCount = 0;
261 WriteFooter* mWrite = nullptr;
262 ReadFooter* mRead = nullptr;
263 bool mGood = false;
264 bool mLargeStream = true;
267 class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate {
268 public:
269 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(CanvasDrawEventRecorder, final)
270 explicit CanvasDrawEventRecorder(){};
272 bool Init(base::ProcessId aOtherPid, ipc::SharedMemoryBasic::Handle* aHandle,
273 CrossProcessSemaphoreHandle* aReaderSem,
274 CrossProcessSemaphoreHandle* aWriterSem,
275 UniquePtr<CanvasEventRingBuffer::WriterServices> aWriterServices) {
276 return mOutputStream.InitWriter(aOtherPid, aHandle, aReaderSem, aWriterSem,
277 std::move(aWriterServices));
280 void RecordEvent(const gfx::RecordedEvent& aEvent) final {
281 if (!mOutputStream.good()) {
282 return;
285 aEvent.RecordToStream(mOutputStream);
288 void StoreSourceSurfaceRecording(gfx::SourceSurface* aSurface,
289 const char* aReason) final;
291 void Flush() final {}
293 void ReturnRead(char* aOut, size_t aSize) {
294 mOutputStream.ReturnRead(aOut, aSize);
297 uint32_t CreateCheckpoint() { return mOutputStream.CreateCheckpoint(); }
300 * Waits until the given checkpoint has been read by the translator.
302 * @params aCheckpoint the checkpoint to wait for
303 * @returns true if the checkpoint was reached, false if the reader is closed
304 * or we timeout.
306 bool WaitForCheckpoint(uint32_t aCheckpoint) {
307 return mOutputStream.WaitForCheckpoint(aCheckpoint);
310 bool UsingLargeStream() { return mOutputStream.UsingLargeStream(); }
312 bool SwitchBuffer(base::ProcessId aOtherPid,
313 ipc::SharedMemoryBasic::Handle* aHandle) {
314 return mOutputStream.SwitchBuffer(aOtherPid, aHandle);
317 private:
318 CanvasEventRingBuffer mOutputStream;
321 } // namespace layers
322 } // namespace mozilla
324 #endif // mozilla_layers_CanvasDrawEventRecorder_h