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_
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"
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;
37 ReferencePtr() : mLongPtr(0) {}
39 MOZ_IMPLICIT
ReferencePtr(const void* aLongPtr
)
40 : mLongPtr(uint64_t(aLongPtr
)) {}
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
);
52 ReferencePtr
& operator=(const RefPtr
<T
>& aPtr
) {
53 mLongPtr
= uint64_t(aPtr
.get());
57 operator void*() const { return (void*)mLongPtr
; }
62 struct RecordedFontDetails
{
63 uint64_t fontDataKey
= 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
)) {}
76 mozilla::ipc::ByteBuf mRecording
;
79 ~RecordedDependentSurface() = default;
82 // Used by the Azure drawing debugger (player2d)
83 inline std::string
StringFromPtr(ReferencePtr aPtr
) {
84 std::stringstream stream
;
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
) {
105 virtual already_AddRefed
<SourceSurface
>
106 LookupSourceSurfaceFromSurfaceDescriptor(
107 const layers::SurfaceDescriptor
& aDesc
) {
108 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
111 void DrawDependentSurface(uint64_t aKey
, const Rect
& aRect
);
112 virtual void AddDrawTarget(ReferencePtr aRefPtr
, DrawTarget
* aDT
) = 0;
113 virtual void RemoveDrawTarget(ReferencePtr aRefPtr
) = 0;
114 virtual bool SetCurrentDrawTarget(ReferencePtr aRefPtr
) = 0;
115 virtual void AddPath(ReferencePtr aRefPtr
, Path
* aPath
) = 0;
116 virtual void RemovePath(ReferencePtr aRefPtr
) = 0;
117 virtual void AddSourceSurface(ReferencePtr aRefPtr
, SourceSurface
* aPath
) = 0;
118 virtual void RemoveSourceSurface(ReferencePtr aRefPtr
) = 0;
119 virtual void AddFilterNode(mozilla::gfx::ReferencePtr aRefPtr
,
120 FilterNode
* aSurface
) = 0;
121 virtual void RemoveFilterNode(mozilla::gfx::ReferencePtr aRefPtr
) = 0;
124 * Get GradientStops compatible with the translation DrawTarget type.
125 * @param aRawStops array of raw gradient stops required
126 * @param aNumStops length of aRawStops
127 * @param aExtendMode extend mode required
128 * @return an already addrefed GradientStops for our DrawTarget type
130 virtual already_AddRefed
<GradientStops
> GetOrCreateGradientStops(
131 DrawTarget
* aDrawTarget
, GradientStop
* aRawStops
, uint32_t aNumStops
,
132 ExtendMode aExtendMode
) {
133 return aDrawTarget
->CreateGradientStops(aRawStops
, aNumStops
, aExtendMode
);
135 virtual void AddGradientStops(ReferencePtr aRefPtr
, GradientStops
* aPath
) = 0;
136 virtual void RemoveGradientStops(ReferencePtr aRefPtr
) = 0;
137 virtual void AddScaledFont(ReferencePtr aRefPtr
, ScaledFont
* aScaledFont
) = 0;
138 virtual void RemoveScaledFont(ReferencePtr aRefPtr
) = 0;
139 virtual void AddUnscaledFont(ReferencePtr aRefPtr
,
140 UnscaledFont
* aUnscaledFont
) = 0;
141 virtual void RemoveUnscaledFont(ReferencePtr aRefPtr
) = 0;
142 virtual void AddNativeFontResource(
143 uint64_t aKey
, NativeFontResource
* aNativeFontResource
) = 0;
145 virtual already_AddRefed
<DrawTarget
> CreateDrawTarget(ReferencePtr aRefPtr
,
146 const IntSize
& aSize
,
147 SurfaceFormat aFormat
);
148 virtual DrawTarget
* GetReferenceDrawTarget() = 0;
149 virtual Matrix
GetReferenceDrawTargetTransform() { return Matrix(); }
150 virtual void* GetFontContext() { return nullptr; }
152 void SetDependentSurfaces(
153 nsRefPtrHashtable
<nsUint64HashKey
, RecordedDependentSurface
>*
154 aDependentSurfaces
) {
155 mDependentSurfaces
= aDependentSurfaces
;
158 DrawTarget
* GetCurrentDrawTarget() const { return mCurrentDT
; }
160 nsRefPtrHashtable
<nsUint64HashKey
, RecordedDependentSurface
>*
161 mDependentSurfaces
= nullptr;
162 DrawTarget
* mCurrentDT
= nullptr;
165 struct ColorPatternStorage
{
169 struct LinearGradientPatternStorage
{
176 struct RadialGradientPatternStorage
{
185 struct ConicGradientPatternStorage
{
194 struct SurfacePatternStorage
{
196 SamplingFilter mSamplingFilter
;
197 ReferencePtr mSurface
;
199 IntRect mSamplingRect
;
202 struct PatternStorage
{
206 char mColor
[sizeof(ColorPatternStorage
)];
207 char mLinear
[sizeof(LinearGradientPatternStorage
)];
208 char mRadial
[sizeof(RadialGradientPatternStorage
)];
209 char mConic
[sizeof(ConicGradientPatternStorage
)];
210 char mSurface
[sizeof(SurfacePatternStorage
)];
214 /* SizeCollector and MemWriter are used
215 * in a pair to first collect the size of the
216 * event that we're going to write and then
217 * to write it without checking each individual
219 struct SizeCollector
{
220 SizeCollector() : mTotalSize(0) {}
221 void write(const char*, size_t s
) { mTotalSize
+= s
; }
226 constexpr explicit MemWriter(char* aPtr
) : mPtr(aPtr
) {}
227 void write(const char* aData
, size_t aSize
) {
228 memcpy(mPtr
, aData
, aSize
);
234 // An istream like class for reading from memory
236 constexpr MemReader(char* aData
, size_t aLen
)
237 : mData(aData
), mEnd(aData
+ aLen
) {}
238 void read(char* s
, std::streamsize n
) {
239 if (n
<= (mEnd
- mData
)) {
243 // We've requested more data than is available
244 // set the Reader into an eof state
248 bool eof() { return mData
> mEnd
; }
249 bool good() { return !eof(); }
250 void SetIsBad() { mData
= mEnd
+ 1; }
256 class ContiguousBuffer
{
258 ContiguousBuffer(char* aStart
, size_t aSize
)
259 : mWriter(aStart
), mEnd(aStart
+ aSize
) {}
261 constexpr MOZ_IMPLICIT
ContiguousBuffer(std::nullptr_t
) : mWriter(nullptr) {}
263 MemWriter
& Writer() { return mWriter
; }
265 size_t SizeRemaining() { return mWriter
.mPtr
? mEnd
- mWriter
.mPtr
: 0; }
267 bool IsValid() { return !!mWriter
.mPtr
; }
271 char* mEnd
= nullptr;
274 // Allows a derived class to provide guaranteed contiguous buffer.
275 class ContiguousBufferStream
{
278 * Templated RecordEvent function so that we can record into the buffer
279 * quickly using MemWriter.
281 * @param aRecordedEvent the event to record
284 void RecordEvent(const RE
* aRecordedEvent
) {
286 WriteElement(size
, aRecordedEvent
->GetType());
287 aRecordedEvent
->Record(size
);
288 auto& buffer
= GetContiguousBuffer(size
.mTotalSize
);
289 if (!buffer
.IsValid()) {
293 MOZ_ASSERT(size
.mTotalSize
<= buffer
.SizeRemaining());
295 WriteElement(buffer
.Writer(), aRecordedEvent
->GetType());
296 aRecordedEvent
->Record(buffer
.Writer());
297 IncrementEventCount();
302 * Provide a contiguous buffer with at least aSize remaining.
304 virtual ContiguousBuffer
& GetContiguousBuffer(size_t aSize
) = 0;
306 virtual void IncrementEventCount() = 0;
314 bool Resize(size_t aSize
) {
319 if (mLength
> mCapacity
) {
320 mCapacity
= mCapacity
* 2;
321 // check if the doubled capacity is enough
322 // otherwise use double mLength
323 if (mLength
> mCapacity
) {
324 mCapacity
= mLength
* 2;
326 char* data
= (char*)realloc(mData
, mCapacity
);
335 NS_ERROR("Failed to allocate MemStream!");
350 MemStream(const MemStream
&) = delete;
351 MemStream(MemStream
&&) = delete;
352 MemStream
& operator=(const MemStream
&) = delete;
353 MemStream
& operator=(MemStream
&&) = delete;
355 void write(const char* aData
, size_t aSize
) {
356 if (Resize(mLength
+ aSize
)) {
357 memcpy(mData
+ mLength
- aSize
, aData
, aSize
);
361 MemStream() : mData(nullptr), mLength(0), mCapacity(0) {}
362 ~MemStream() { free(mData
); }
367 virtual void write(const char* aData
, size_t aSize
) = 0;
368 virtual void read(char* aOut
, size_t aSize
) = 0;
369 virtual bool good() = 0;
370 virtual void SetIsBad() = 0;
373 class RecordedEvent
{
375 enum EventType
: uint8_t {
378 DRAWTARGETDESTRUCTION
,
379 SETCURRENTDRAWTARGET
,
398 DRAWSURFACEDESCRIPTOR
,
399 DRAWDEPENDENTSURFACE
,
400 DRAWSURFACEWITHSHADOW
,
404 SOURCESURFACECREATION
,
405 SOURCESURFACEDESTRUCTION
,
406 GRADIENTSTOPSCREATION
,
407 GRADIENTSTOPSDESTRUCTION
,
410 SCALEDFONTDESTRUCTION
,
413 FILTERNODEDESTRUCTION
,
415 FILTERNODESETATTRIBUTE
,
417 CREATESIMILARDRAWTARGET
,
418 CREATECLIPPEDDRAWTARGET
,
419 CREATEDRAWTARGETFORFILTER
,
425 UNSCALEDFONTCREATION
,
426 UNSCALEDFONTDESTRUCTION
,
429 EXTERNALSURFACECREATION
,
432 OPTIMIZESOURCESURFACE
,
438 virtual ~RecordedEvent() = default;
440 static std::string
GetEventName(EventType aType
);
443 * Play back this event using the translator. Note that derived classes
445 * only return false when there is a fatal error, as it will probably mean
447 * translation will abort.
448 * @param aTranslator Translator to be used for retrieving other referenced
449 * objects and making playback decisions.
450 * @return true unless a fatal problem has occurred and playback should
453 virtual bool PlayEvent(Translator
* aTranslator
) const { return true; }
455 virtual void RecordToStream(std::ostream
& aStream
) const = 0;
456 virtual void RecordToStream(EventStream
& aStream
) const = 0;
457 virtual void RecordToStream(ContiguousBufferStream
& aStream
) const = 0;
458 virtual void RecordToStream(MemStream
& aStream
) const = 0;
460 virtual void OutputSimpleEventInfo(std::stringstream
& aStringStream
) const {}
463 void RecordPatternData(S
& aStream
,
464 const PatternStorage
& aPatternStorage
) const;
466 void ReadPatternData(S
& aStream
, PatternStorage
& aPatternStorage
) const;
467 void StorePattern(PatternStorage
& aDestination
, const Pattern
& aSource
) const;
469 void RecordStrokeOptions(S
& aStream
,
470 const StrokeOptions
& aStrokeOptions
) const;
472 void ReadStrokeOptions(S
& aStream
, StrokeOptions
& aStrokeOptions
);
474 virtual std::string
GetName() const = 0;
476 virtual ReferencePtr
GetDestinedDT() { return nullptr; }
478 void OutputSimplePatternInfo(const PatternStorage
& aStorage
,
479 std::stringstream
& aOutput
) const;
482 static bool DoWithEvent(S
& aStream
, EventType aType
,
483 const std::function
<bool(RecordedEvent
*)>& aAction
);
484 static bool DoWithEventFromStream(
485 EventStream
& aStream
, EventType aType
,
486 const std::function
<bool(RecordedEvent
*)>& aAction
);
487 static bool DoWithEventFromReader(
488 MemReader
& aReader
, EventType aType
,
489 const std::function
<bool(RecordedEvent
*)>& aAction
);
491 EventType
GetType() const { return (EventType
)mType
; }
494 friend class DrawEventRecorderPrivate
;
495 friend class DrawEventRecorderMemory
;
496 static void RecordUnscaledFont(UnscaledFont
* aUnscaledFont
,
497 std::ostream
* aOutput
);
498 static void RecordUnscaledFont(UnscaledFont
* aUnscaledFont
,
501 static void RecordUnscaledFontImpl(UnscaledFont
* aUnscaledFont
, S
& aOutput
);
503 MOZ_IMPLICIT
RecordedEvent(EventType aType
) : mType(aType
) {}
506 std::vector
<Float
> mDashPatternStorage
;
509 template <class Derived
>
510 class RecordedEventDerived
: public RecordedEvent
{
511 using RecordedEvent::RecordedEvent
;
514 void RecordToStream(std::ostream
& aStream
) const override
{
515 WriteElement(aStream
, this->mType
);
516 static_cast<const Derived
*>(this)->Record(aStream
);
518 void RecordToStream(EventStream
& aStream
) const override
{
519 WriteElement(aStream
, this->mType
);
520 static_cast<const Derived
*>(this)->Record(aStream
);
522 void RecordToStream(ContiguousBufferStream
& aStream
) const final
{
523 aStream
.RecordEvent(static_cast<const Derived
*>(this));
525 void RecordToStream(MemStream
& aStream
) const override
{
527 WriteElement(size
, this->mType
);
528 static_cast<const Derived
*>(this)->Record(size
);
530 if (!aStream
.Resize(aStream
.mLength
+ size
.mTotalSize
)) {
534 MemWriter
writer(aStream
.mData
+ aStream
.mLength
- size
.mTotalSize
);
535 WriteElement(writer
, this->mType
);
536 static_cast<const Derived
*>(this)->Record(writer
);
541 } // namespace mozilla