Backed out changeset 28c56a4f3af6 (bug 1874810) for causing Moz2DImageRenderer relate...
[gecko.git] / gfx / 2d / RecordedEvent.h
blobf8ebc94cdc83fd18564d678eab58a13e8b294d9e
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_GFX_RECORDEDEVENT_H_
8 #define MOZILLA_GFX_RECORDEDEVENT_H_
10 #include <ostream>
11 #include <sstream>
12 #include <cstring>
13 #include <functional>
14 #include <vector>
16 #include "RecordingTypes.h"
17 #include "mozilla/gfx/Point.h"
18 #include "mozilla/gfx/Types.h"
19 #include "mozilla/ipc/ByteBuf.h"
20 #include "nsRefPtrHashtable.h"
22 namespace mozilla {
23 namespace gfx {
25 const uint32_t kMagicInt = 0xc001feed;
27 // A change in major revision means a change in event binary format, causing
28 // loss of backwards compatibility. Old streams will not work in a player
29 // using a newer major revision. And new streams will not work in a player
30 // using an older major revision.
31 const uint16_t kMajorRevision = 10;
32 // A change in minor revision means additions of new events. New streams will
33 // not play in older players.
34 const uint16_t kMinorRevision = 3;
36 struct ReferencePtr {
37 ReferencePtr() : mLongPtr(0) {}
39 MOZ_IMPLICIT ReferencePtr(const void* aLongPtr)
40 : mLongPtr(uint64_t(aLongPtr)) {}
42 template <typename T>
43 MOZ_IMPLICIT ReferencePtr(const RefPtr<T>& aPtr)
44 : mLongPtr(uint64_t(aPtr.get())) {}
46 ReferencePtr& operator=(const void* aLongPtr) {
47 mLongPtr = uint64_t(aLongPtr);
48 return *this;
51 template <typename T>
52 ReferencePtr& operator=(const RefPtr<T>& aPtr) {
53 mLongPtr = uint64_t(aPtr.get());
54 return *this;
57 operator void*() const { return (void*)mLongPtr; }
59 uint64_t mLongPtr;
62 struct RecordedFontDetails {
63 uint64_t fontDataKey = 0;
64 uint32_t size = 0;
65 uint32_t index = 0;
68 struct RecordedDependentSurface {
69 NS_INLINE_DECL_REFCOUNTING(RecordedDependentSurface);
71 RecordedDependentSurface(const IntSize& aSize,
72 mozilla::ipc::ByteBuf&& aRecording)
73 : mSize(aSize), mRecording(std::move(aRecording)) {}
75 IntSize mSize;
76 mozilla::ipc::ByteBuf mRecording;
78 private:
79 ~RecordedDependentSurface() = default;
82 // Used by the Azure drawing debugger (player2d)
83 inline std::string StringFromPtr(ReferencePtr aPtr) {
84 std::stringstream stream;
85 stream << aPtr;
86 return stream.str();
89 class Translator {
90 public:
91 virtual ~Translator() = default;
93 virtual DrawTarget* LookupDrawTarget(ReferencePtr aRefPtr) = 0;
94 virtual Path* LookupPath(ReferencePtr aRefPtr) = 0;
95 virtual SourceSurface* LookupSourceSurface(ReferencePtr aRefPtr) = 0;
96 virtual FilterNode* LookupFilterNode(ReferencePtr aRefPtr) = 0;
97 virtual already_AddRefed<GradientStops> LookupGradientStops(
98 ReferencePtr aRefPtr) = 0;
99 virtual ScaledFont* LookupScaledFont(ReferencePtr aRefPtr) = 0;
100 virtual UnscaledFont* LookupUnscaledFont(ReferencePtr aRefPtr) = 0;
101 virtual NativeFontResource* LookupNativeFontResource(uint64_t aKey) = 0;
102 virtual already_AddRefed<SourceSurface> LookupExternalSurface(uint64_t aKey) {
103 return nullptr;
105 void DrawDependentSurface(uint64_t aKey, const Rect& aRect);
106 virtual void AddDrawTarget(ReferencePtr aRefPtr, DrawTarget* aDT) = 0;
107 virtual void RemoveDrawTarget(ReferencePtr aRefPtr) = 0;
108 virtual bool SetCurrentDrawTarget(ReferencePtr aRefPtr) = 0;
109 virtual void AddPath(ReferencePtr aRefPtr, Path* aPath) = 0;
110 virtual void RemovePath(ReferencePtr aRefPtr) = 0;
111 virtual void AddSourceSurface(ReferencePtr aRefPtr, SourceSurface* aPath) = 0;
112 virtual void RemoveSourceSurface(ReferencePtr aRefPtr) = 0;
113 virtual void AddFilterNode(mozilla::gfx::ReferencePtr aRefPtr,
114 FilterNode* aSurface) = 0;
115 virtual void RemoveFilterNode(mozilla::gfx::ReferencePtr aRefPtr) = 0;
118 * Get GradientStops compatible with the translation DrawTarget type.
119 * @param aRawStops array of raw gradient stops required
120 * @param aNumStops length of aRawStops
121 * @param aExtendMode extend mode required
122 * @return an already addrefed GradientStops for our DrawTarget type
124 virtual already_AddRefed<GradientStops> GetOrCreateGradientStops(
125 DrawTarget* aDrawTarget, GradientStop* aRawStops, uint32_t aNumStops,
126 ExtendMode aExtendMode) {
127 return aDrawTarget->CreateGradientStops(aRawStops, aNumStops, aExtendMode);
129 virtual void AddGradientStops(ReferencePtr aRefPtr, GradientStops* aPath) = 0;
130 virtual void RemoveGradientStops(ReferencePtr aRefPtr) = 0;
131 virtual void AddScaledFont(ReferencePtr aRefPtr, ScaledFont* aScaledFont) = 0;
132 virtual void RemoveScaledFont(ReferencePtr aRefPtr) = 0;
133 virtual void AddUnscaledFont(ReferencePtr aRefPtr,
134 UnscaledFont* aUnscaledFont) = 0;
135 virtual void RemoveUnscaledFont(ReferencePtr aRefPtr) = 0;
136 virtual void AddNativeFontResource(
137 uint64_t aKey, NativeFontResource* aNativeFontResource) = 0;
139 virtual already_AddRefed<DrawTarget> CreateDrawTarget(ReferencePtr aRefPtr,
140 const IntSize& aSize,
141 SurfaceFormat aFormat);
142 virtual DrawTarget* GetReferenceDrawTarget() = 0;
143 virtual Matrix GetReferenceDrawTargetTransform() { return Matrix(); }
144 virtual void* GetFontContext() { return nullptr; }
146 void SetDependentSurfaces(
147 nsRefPtrHashtable<nsUint64HashKey, RecordedDependentSurface>*
148 aDependentSurfaces) {
149 mDependentSurfaces = aDependentSurfaces;
152 DrawTarget* GetCurrentDrawTarget() const { return mCurrentDT; }
154 nsRefPtrHashtable<nsUint64HashKey, RecordedDependentSurface>*
155 mDependentSurfaces = nullptr;
156 DrawTarget* mCurrentDT = nullptr;
159 struct ColorPatternStorage {
160 DeviceColor mColor;
163 struct LinearGradientPatternStorage {
164 Point mBegin;
165 Point mEnd;
166 ReferencePtr mStops;
167 Matrix mMatrix;
170 struct RadialGradientPatternStorage {
171 Point mCenter1;
172 Point mCenter2;
173 Float mRadius1;
174 Float mRadius2;
175 ReferencePtr mStops;
176 Matrix mMatrix;
179 struct ConicGradientPatternStorage {
180 Point mCenter;
181 Float mAngle;
182 Float mStartOffset;
183 Float mEndOffset;
184 ReferencePtr mStops;
185 Matrix mMatrix;
188 struct SurfacePatternStorage {
189 ExtendMode mExtend;
190 SamplingFilter mSamplingFilter;
191 ReferencePtr mSurface;
192 Matrix mMatrix;
193 IntRect mSamplingRect;
196 struct PatternStorage {
197 PatternType mType;
198 union {
199 char* mStorage;
200 char mColor[sizeof(ColorPatternStorage)];
201 char mLinear[sizeof(LinearGradientPatternStorage)];
202 char mRadial[sizeof(RadialGradientPatternStorage)];
203 char mConic[sizeof(ConicGradientPatternStorage)];
204 char mSurface[sizeof(SurfacePatternStorage)];
208 /* SizeCollector and MemWriter are used
209 * in a pair to first collect the size of the
210 * event that we're going to write and then
211 * to write it without checking each individual
212 * size. */
213 struct SizeCollector {
214 SizeCollector() : mTotalSize(0) {}
215 void write(const char*, size_t s) { mTotalSize += s; }
216 size_t mTotalSize;
219 struct MemWriter {
220 constexpr explicit MemWriter(char* aPtr) : mPtr(aPtr) {}
221 void write(const char* aData, size_t aSize) {
222 memcpy(mPtr, aData, aSize);
223 mPtr += aSize;
225 char* mPtr;
228 // An istream like class for reading from memory
229 struct MemReader {
230 constexpr MemReader(char* aData, size_t aLen)
231 : mData(aData), mEnd(aData + aLen) {}
232 void read(char* s, std::streamsize n) {
233 if (n <= (mEnd - mData)) {
234 memcpy(s, mData, n);
235 mData += n;
236 } else {
237 // We've requested more data than is available
238 // set the Reader into an eof state
239 SetIsBad();
242 bool eof() { return mData > mEnd; }
243 bool good() { return !eof(); }
244 void SetIsBad() { mData = mEnd + 1; }
246 char* mData;
247 char* mEnd;
250 class ContiguousBuffer {
251 public:
252 ContiguousBuffer(char* aStart, size_t aSize)
253 : mWriter(aStart), mEnd(aStart + aSize) {}
255 constexpr MOZ_IMPLICIT ContiguousBuffer(std::nullptr_t) : mWriter(nullptr) {}
257 MemWriter& Writer() { return mWriter; }
259 size_t SizeRemaining() { return mWriter.mPtr ? mEnd - mWriter.mPtr : 0; }
261 bool IsValid() { return !!mWriter.mPtr; }
263 private:
264 MemWriter mWriter;
265 char* mEnd = nullptr;
268 // Allows a derived class to provide guaranteed contiguous buffer.
269 class ContiguousBufferStream {
270 public:
272 * Templated RecordEvent function so that we can record into the buffer
273 * quickly using MemWriter.
275 * @param aRecordedEvent the event to record
277 template <class RE>
278 void RecordEvent(const RE* aRecordedEvent) {
279 SizeCollector size;
280 WriteElement(size, aRecordedEvent->GetType());
281 aRecordedEvent->Record(size);
282 auto& buffer = GetContiguousBuffer(size.mTotalSize);
283 if (!buffer.IsValid()) {
284 return;
287 MOZ_ASSERT(size.mTotalSize <= buffer.SizeRemaining());
289 WriteElement(buffer.Writer(), aRecordedEvent->GetType());
290 aRecordedEvent->Record(buffer.Writer());
291 IncrementEventCount();
294 protected:
296 * Provide a contiguous buffer with at least aSize remaining.
298 virtual ContiguousBuffer& GetContiguousBuffer(size_t aSize) = 0;
300 virtual void IncrementEventCount() = 0;
303 struct MemStream {
304 char* mData;
305 size_t mLength;
306 size_t mCapacity;
307 bool mValid = true;
308 bool Resize(size_t aSize) {
309 if (!mValid) {
310 return false;
312 mLength = aSize;
313 if (mLength > mCapacity) {
314 mCapacity = mCapacity * 2;
315 // check if the doubled capacity is enough
316 // otherwise use double mLength
317 if (mLength > mCapacity) {
318 mCapacity = mLength * 2;
320 char* data = (char*)realloc(mData, mCapacity);
321 if (!data) {
322 free(mData);
324 mData = data;
326 if (mData) {
327 return true;
329 NS_ERROR("Failed to allocate MemStream!");
330 mValid = false;
331 mLength = 0;
332 mCapacity = 0;
333 return false;
336 void reset() {
337 free(mData);
338 mData = nullptr;
339 mValid = true;
340 mLength = 0;
341 mCapacity = 0;
344 MemStream(const MemStream&) = delete;
345 MemStream(MemStream&&) = delete;
346 MemStream& operator=(const MemStream&) = delete;
347 MemStream& operator=(MemStream&&) = delete;
349 void write(const char* aData, size_t aSize) {
350 if (Resize(mLength + aSize)) {
351 memcpy(mData + mLength - aSize, aData, aSize);
355 MemStream() : mData(nullptr), mLength(0), mCapacity(0) {}
356 ~MemStream() { free(mData); }
359 class EventStream {
360 public:
361 virtual void write(const char* aData, size_t aSize) = 0;
362 virtual void read(char* aOut, size_t aSize) = 0;
363 virtual bool good() = 0;
364 virtual void SetIsBad() = 0;
367 class RecordedEvent {
368 public:
369 enum EventType : uint8_t {
370 INVALID = 0,
371 DRAWTARGETCREATION,
372 DRAWTARGETDESTRUCTION,
373 SETCURRENTDRAWTARGET,
374 FILLRECT,
375 STROKERECT,
376 STROKELINE,
377 STROKECIRCLE,
378 CLEARRECT,
379 COPYSURFACE,
380 SETTRANSFORM,
381 PUSHCLIP,
382 PUSHCLIPRECT,
383 POPCLIP,
384 FILL,
385 FILLCIRCLE,
386 FILLGLYPHS,
387 MASK,
388 STROKE,
389 DRAWSURFACE,
390 DRAWDEPENDENTSURFACE,
391 DRAWSURFACEWITHSHADOW,
392 DRAWSHADOW,
393 PATHCREATION,
394 PATHDESTRUCTION,
395 SOURCESURFACECREATION,
396 SOURCESURFACEDESTRUCTION,
397 GRADIENTSTOPSCREATION,
398 GRADIENTSTOPSDESTRUCTION,
399 SNAPSHOT,
400 SCALEDFONTCREATION,
401 SCALEDFONTDESTRUCTION,
402 MASKSURFACE,
403 FILTERNODECREATION,
404 FILTERNODEDESTRUCTION,
405 DRAWFILTER,
406 FILTERNODESETATTRIBUTE,
407 FILTERNODESETINPUT,
408 CREATESIMILARDRAWTARGET,
409 CREATECLIPPEDDRAWTARGET,
410 CREATEDRAWTARGETFORFILTER,
411 FONTDATA,
412 FONTDESC,
413 PUSHLAYER,
414 PUSHLAYERWITHBLEND,
415 POPLAYER,
416 UNSCALEDFONTCREATION,
417 UNSCALEDFONTDESTRUCTION,
418 INTOLUMINANCE,
419 EXTERNALSURFACECREATION,
420 FLUSH,
421 DETACHALLSNAPSHOTS,
422 OPTIMIZESOURCESURFACE,
423 LINK,
424 DESTINATION,
425 LAST,
428 virtual ~RecordedEvent() = default;
430 static std::string GetEventName(EventType aType);
433 * Play back this event using the translator. Note that derived classes
434 * should
435 * only return false when there is a fatal error, as it will probably mean
436 * the
437 * translation will abort.
438 * @param aTranslator Translator to be used for retrieving other referenced
439 * objects and making playback decisions.
440 * @return true unless a fatal problem has occurred and playback should
441 * abort.
443 virtual bool PlayEvent(Translator* aTranslator) const { return true; }
445 virtual void RecordToStream(std::ostream& aStream) const = 0;
446 virtual void RecordToStream(EventStream& aStream) const = 0;
447 virtual void RecordToStream(ContiguousBufferStream& aStream) const = 0;
448 virtual void RecordToStream(MemStream& aStream) const = 0;
450 virtual void OutputSimpleEventInfo(std::stringstream& aStringStream) const {}
452 template <class S>
453 void RecordPatternData(S& aStream,
454 const PatternStorage& aPatternStorage) const;
455 template <class S>
456 void ReadPatternData(S& aStream, PatternStorage& aPatternStorage) const;
457 void StorePattern(PatternStorage& aDestination, const Pattern& aSource) const;
458 template <class S>
459 void RecordStrokeOptions(S& aStream,
460 const StrokeOptions& aStrokeOptions) const;
461 template <class S>
462 void ReadStrokeOptions(S& aStream, StrokeOptions& aStrokeOptions);
464 virtual std::string GetName() const = 0;
466 virtual ReferencePtr GetDestinedDT() { return nullptr; }
468 void OutputSimplePatternInfo(const PatternStorage& aStorage,
469 std::stringstream& aOutput) const;
471 template <class S>
472 static bool DoWithEvent(S& aStream, EventType aType,
473 const std::function<bool(RecordedEvent*)>& aAction);
474 static bool DoWithEventFromStream(
475 EventStream& aStream, EventType aType,
476 const std::function<bool(RecordedEvent*)>& aAction);
477 static bool DoWithEventFromReader(
478 MemReader& aReader, EventType aType,
479 const std::function<bool(RecordedEvent*)>& aAction);
481 EventType GetType() const { return (EventType)mType; }
483 protected:
484 friend class DrawEventRecorderPrivate;
485 friend class DrawEventRecorderMemory;
486 static void RecordUnscaledFont(UnscaledFont* aUnscaledFont,
487 std::ostream* aOutput);
488 static void RecordUnscaledFont(UnscaledFont* aUnscaledFont,
489 MemStream& aOutput);
490 template <class S>
491 static void RecordUnscaledFontImpl(UnscaledFont* aUnscaledFont, S& aOutput);
493 MOZ_IMPLICIT RecordedEvent(EventType aType) : mType(aType) {}
495 EventType mType;
496 std::vector<Float> mDashPatternStorage;
499 template <class Derived>
500 class RecordedEventDerived : public RecordedEvent {
501 using RecordedEvent::RecordedEvent;
503 public:
504 void RecordToStream(std::ostream& aStream) const override {
505 WriteElement(aStream, this->mType);
506 static_cast<const Derived*>(this)->Record(aStream);
508 void RecordToStream(EventStream& aStream) const override {
509 WriteElement(aStream, this->mType);
510 static_cast<const Derived*>(this)->Record(aStream);
512 void RecordToStream(ContiguousBufferStream& aStream) const final {
513 aStream.RecordEvent(static_cast<const Derived*>(this));
515 void RecordToStream(MemStream& aStream) const override {
516 SizeCollector size;
517 WriteElement(size, this->mType);
518 static_cast<const Derived*>(this)->Record(size);
520 if (!aStream.Resize(aStream.mLength + size.mTotalSize)) {
521 return;
524 MemWriter writer(aStream.mData + aStream.mLength - size.mTotalSize);
525 WriteElement(writer, this->mType);
526 static_cast<const Derived*>(this)->Record(writer);
530 } // namespace gfx
531 } // namespace mozilla
533 #endif