Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.

Commit 418567a

Browse files
committed
Bug 1863914: Use multiple shmem buffers for remote canvas recording. r=aosmond
This replaces the use of a single large ring buffer. The buffers are still processed in parallel and are recycled to reduce allocation. Events that do not fit in the default sized buffer have a separate buffer created to fit them. These large buffers are not recycled. Separate shared memory is used for readback, with a single shmem cached for this purpose. Generally only one cached shmem should be required, because the operations that usually readback the data do it straight away. Differential Revision: https://phabricator.services.mozilla.com/D193207
1 parent 55cad8d commit 418567a

18 files changed

+983
-1080
lines changed

gfx/2d/InlineTranslator.cpp

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,26 +19,6 @@ InlineTranslator::InlineTranslator(DrawTarget* aDT, void* aFontContext)
1919
: mBaseDT(aDT), mFontContext(aFontContext) {}
2020

2121
bool InlineTranslator::TranslateRecording(char* aData, size_t aLen) {
22-
// an istream like class for reading from memory
23-
struct MemReader {
24-
MemReader(char* aData, size_t aLen) : mData(aData), mEnd(aData + aLen) {}
25-
void read(char* s, std::streamsize n) {
26-
if (n <= (mEnd - mData)) {
27-
memcpy(s, mData, n);
28-
mData += n;
29-
} else {
30-
// We've requested more data than is available
31-
// set the Reader into an eof state
32-
SetIsBad();
33-
}
34-
}
35-
bool eof() { return mData > mEnd; }
36-
bool good() { return !eof(); }
37-
void SetIsBad() { mData = mEnd + 1; }
38-
39-
char* mData;
40-
char* mEnd;
41-
};
4222
MemReader reader(aData, aLen);
4323

4424
uint32_t magicInt;

gfx/2d/RecordedEvent.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ bool RecordedEvent::DoWithEventFromStream(
2626
}
2727

2828
/* static */
29-
bool RecordedEvent::DoWithEventFromStream(
30-
EventRingBuffer& aStream, EventType aType,
29+
bool RecordedEvent::DoWithEventFromReader(
30+
MemReader& aReader, EventType aType,
3131
const std::function<bool(RecordedEvent*)>& aAction) {
32-
return DoWithEvent(aStream, aType, aAction);
32+
return DoWithEvent(aReader, aType, aAction);
3333
}
3434

3535
std::string RecordedEvent::GetEventName(EventType aType) {

gfx/2d/RecordedEvent.h

Lines changed: 60 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -214,21 +214,60 @@ struct SizeCollector {
214214
};
215215

216216
struct MemWriter {
217-
explicit MemWriter(char* aPtr) : mPtr(aPtr) {}
217+
constexpr explicit MemWriter(char* aPtr) : mPtr(aPtr) {}
218218
void write(const char* aData, size_t aSize) {
219219
memcpy(mPtr, aData, aSize);
220220
mPtr += aSize;
221221
}
222222
char* mPtr;
223223
};
224224

225-
// This is a simple interface for an EventRingBuffer, so we can use it in the
226-
// RecordedEvent reading and writing machinery.
227-
class EventRingBuffer {
225+
// An istream like class for reading from memory
226+
struct MemReader {
227+
constexpr MemReader(char* aData, size_t aLen)
228+
: mData(aData), mEnd(aData + aLen) {}
229+
void read(char* s, std::streamsize n) {
230+
if (n <= (mEnd - mData)) {
231+
memcpy(s, mData, n);
232+
mData += n;
233+
} else {
234+
// We've requested more data than is available
235+
// set the Reader into an eof state
236+
SetIsBad();
237+
}
238+
}
239+
bool eof() { return mData > mEnd; }
240+
bool good() { return !eof(); }
241+
void SetIsBad() { mData = mEnd + 1; }
242+
243+
char* mData;
244+
char* mEnd;
245+
};
246+
247+
class ContiguousBuffer {
248+
public:
249+
ContiguousBuffer(char* aStart, size_t aSize)
250+
: mWriter(aStart), mEnd(aStart + aSize) {}
251+
252+
constexpr MOZ_IMPLICIT ContiguousBuffer(std::nullptr_t) : mWriter(nullptr) {}
253+
254+
MemWriter& Writer() { return mWriter; }
255+
256+
size_t SizeRemaining() { return mWriter.mPtr ? mEnd - mWriter.mPtr : 0; }
257+
258+
bool IsValid() { return !!mWriter.mPtr; }
259+
260+
private:
261+
MemWriter mWriter;
262+
char* mEnd = nullptr;
263+
};
264+
265+
// Allows a derived class to provide guaranteed contiguous buffer.
266+
class ContiguousBufferStream {
228267
public:
229268
/**
230-
* Templated RecordEvent function so that when we have enough contiguous
231-
* space we can record into the buffer quickly using MemWriter.
269+
* Templated RecordEvent function so that we can record into the buffer
270+
* quickly using MemWriter.
232271
*
233272
* @param aRecordedEvent the event to record
234273
*/
@@ -237,56 +276,25 @@ class EventRingBuffer {
237276
SizeCollector size;
238277
WriteElement(size, aRecordedEvent->GetType());
239278
aRecordedEvent->Record(size);
240-
if (size.mTotalSize > mAvailable) {
241-
WaitForAndRecalculateAvailableSpace();
242-
}
243-
if (size.mTotalSize <= mAvailable) {
244-
MemWriter writer(mBufPos);
245-
WriteElement(writer, aRecordedEvent->GetType());
246-
aRecordedEvent->Record(writer);
247-
UpdateWriteTotalsBy(size.mTotalSize);
248-
} else {
249-
WriteElement(*this, aRecordedEvent->GetType());
250-
aRecordedEvent->Record(*this);
279+
auto& buffer = GetContiguousBuffer(size.mTotalSize);
280+
if (!buffer.IsValid()) {
281+
return;
251282
}
252-
}
253283

254-
/**
255-
* Simple write function required by WriteElement.
256-
*
257-
* @param aData the data to be written to the buffer
258-
* @param aSize the number of chars to write
259-
*/
260-
virtual void write(const char* const aData, const size_t aSize) = 0;
261-
262-
/**
263-
* Simple read function required by ReadElement.
264-
*
265-
* @param aOut the pointer to read into
266-
* @param aSize the number of chars to read
267-
*/
268-
virtual void read(char* const aOut, const size_t aSize) = 0;
284+
MOZ_ASSERT(size.mTotalSize <= buffer.SizeRemaining());
269285

270-
virtual bool good() const = 0;
271-
272-
virtual void SetIsBad() = 0;
286+
WriteElement(buffer.Writer(), aRecordedEvent->GetType());
287+
aRecordedEvent->Record(buffer.Writer());
288+
IncrementEventCount();
289+
}
273290

274291
protected:
275292
/**
276-
* Wait until space is available for writing and then set mBufPos and
277-
* mAvailable.
278-
*/
279-
virtual bool WaitForAndRecalculateAvailableSpace() = 0;
280-
281-
/**
282-
* Update write count, mBufPos and mAvailable.
283-
*
284-
* @param aCount number of bytes written
293+
* Provide a contiguous buffer with at least aSize remaining.
285294
*/
286-
virtual void UpdateWriteTotalsBy(uint32_t aCount) = 0;
295+
virtual ContiguousBuffer& GetContiguousBuffer(size_t aSize) = 0;
287296

288-
char* mBufPos = nullptr;
289-
uint32_t mAvailable = 0;
297+
virtual void IncrementEventCount() = 0;
290298
};
291299

292300
struct MemStream {
@@ -430,7 +438,7 @@ class RecordedEvent {
430438

431439
virtual void RecordToStream(std::ostream& aStream) const = 0;
432440
virtual void RecordToStream(EventStream& aStream) const = 0;
433-
virtual void RecordToStream(EventRingBuffer& aStream) const = 0;
441+
virtual void RecordToStream(ContiguousBufferStream& aStream) const = 0;
434442
virtual void RecordToStream(MemStream& aStream) const = 0;
435443

436444
virtual void OutputSimpleEventInfo(std::stringstream& aStringStream) const {}
@@ -460,8 +468,8 @@ class RecordedEvent {
460468
static bool DoWithEventFromStream(
461469
EventStream& aStream, EventType aType,
462470
const std::function<bool(RecordedEvent*)>& aAction);
463-
static bool DoWithEventFromStream(
464-
EventRingBuffer& aStream, EventType aType,
471+
static bool DoWithEventFromReader(
472+
MemReader& aReader, EventType aType,
465473
const std::function<bool(RecordedEvent*)>& aAction);
466474

467475
EventType GetType() const { return (EventType)mType; }
@@ -495,7 +503,7 @@ class RecordedEventDerived : public RecordedEvent {
495503
WriteElement(aStream, this->mType);
496504
static_cast<const Derived*>(this)->Record(aStream);
497505
}
498-
void RecordToStream(EventRingBuffer& aStream) const final {
506+
void RecordToStream(ContiguousBufferStream& aStream) const final {
499507
aStream.RecordEvent(static_cast<const Derived*>(this));
500508
}
501509
void RecordToStream(MemStream& aStream) const override {

gfx/ipc/CanvasManagerChild.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,12 @@ void CanvasManagerChild::EndCanvasTransaction() {
151151
}
152152
}
153153

154+
void CanvasManagerChild::ClearCachedResources() {
155+
if (mCanvasChild) {
156+
mCanvasChild->ClearCachedResources();
157+
}
158+
}
159+
154160
void CanvasManagerChild::DeactivateCanvas() {
155161
mActive = false;
156162
if (mCanvasChild) {

gfx/ipc/CanvasManagerChild.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class CanvasManagerChild final : public PCanvasManagerChild {
4747

4848
bool IsCanvasActive() { return mActive; }
4949
void EndCanvasTransaction();
50+
void ClearCachedResources();
5051
void DeactivateCanvas();
5152

5253
RefPtr<layers::CanvasChild> GetCanvasChild();

0 commit comments

Comments
 (0)