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 void DrawDependentSurface(ReferencePtr aDrawTarget
, uint64_t aKey
,
107 virtual void AddDrawTarget(ReferencePtr aRefPtr
, DrawTarget
* aDT
) = 0;
108 virtual void RemoveDrawTarget(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 GradientStop
* aRawStops
, uint32_t aNumStops
, ExtendMode aExtendMode
) {
126 return GetReferenceDrawTarget()->CreateGradientStops(aRawStops
, aNumStops
,
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 nsRefPtrHashtable
<nsUint64HashKey
, RecordedDependentSurface
>*
153 mDependentSurfaces
= nullptr;
156 struct ColorPatternStorage
{
160 struct LinearGradientPatternStorage
{
167 struct RadialGradientPatternStorage
{
176 struct ConicGradientPatternStorage
{
185 struct SurfacePatternStorage
{
187 SamplingFilter mSamplingFilter
;
188 ReferencePtr mSurface
;
190 IntRect mSamplingRect
;
193 struct PatternStorage
{
197 char mColor
[sizeof(ColorPatternStorage
)];
198 char mLinear
[sizeof(LinearGradientPatternStorage
)];
199 char mRadial
[sizeof(RadialGradientPatternStorage
)];
200 char mConic
[sizeof(ConicGradientPatternStorage
)];
201 char mSurface
[sizeof(SurfacePatternStorage
)];
205 /* SizeCollector and MemWriter are used
206 * in a pair to first collect the size of the
207 * event that we're going to write and then
208 * to write it without checking each individual
210 struct SizeCollector
{
211 SizeCollector() : mTotalSize(0) {}
212 void write(const char*, size_t s
) { mTotalSize
+= s
; }
217 explicit MemWriter(char* aPtr
) : mPtr(aPtr
) {}
218 void write(const char* aData
, size_t aSize
) {
219 memcpy(mPtr
, aData
, aSize
);
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
{
230 * Templated RecordEvent function so that when we have enough contiguous
231 * space we can record into the buffer quickly using MemWriter.
233 * @param aRecordedEvent the event to record
236 void RecordEvent(const RE
* aRecordedEvent
) {
238 WriteElement(size
, aRecordedEvent
->GetType());
239 aRecordedEvent
->Record(size
);
240 if (size
.mTotalSize
> mAvailable
) {
241 WaitForAndRecalculateAvailableSpace();
243 if (size
.mTotalSize
<= mAvailable
) {
244 MemWriter
writer(mBufPos
);
245 WriteElement(writer
, aRecordedEvent
->GetType());
246 aRecordedEvent
->Record(writer
);
247 UpdateWriteTotalsBy(size
.mTotalSize
);
249 WriteElement(*this, aRecordedEvent
->GetType());
250 aRecordedEvent
->Record(*this);
255 * Simple write function required by WriteElement.
257 * @param aData the data to be written to the buffer
258 * @param aSize the number of chars to write
260 virtual void write(const char* const aData
, const size_t aSize
) = 0;
263 * Simple read function required by ReadElement.
265 * @param aOut the pointer to read into
266 * @param aSize the number of chars to read
268 virtual void read(char* const aOut
, const size_t aSize
) = 0;
270 virtual bool good() const = 0;
272 virtual void SetIsBad() = 0;
276 * Wait until space is available for writing and then set mBufPos and
279 virtual bool WaitForAndRecalculateAvailableSpace() = 0;
282 * Update write count, mBufPos and mAvailable.
284 * @param aCount number of bytes written
286 virtual void UpdateWriteTotalsBy(uint32_t aCount
) = 0;
288 char* mBufPos
= nullptr;
289 uint32_t mAvailable
= 0;
297 bool Resize(size_t aSize
) {
302 if (mLength
> mCapacity
) {
303 mCapacity
= mCapacity
* 2;
304 // check if the doubled capacity is enough
305 // otherwise use double mLength
306 if (mLength
> mCapacity
) {
307 mCapacity
= mLength
* 2;
309 char* data
= (char*)realloc(mData
, mCapacity
);
318 NS_ERROR("Failed to allocate MemStream!");
333 MemStream(const MemStream
&) = delete;
334 MemStream(MemStream
&&) = delete;
335 MemStream
& operator=(const MemStream
&) = delete;
336 MemStream
& operator=(MemStream
&&) = delete;
338 void write(const char* aData
, size_t aSize
) {
339 if (Resize(mLength
+ aSize
)) {
340 memcpy(mData
+ mLength
- aSize
, aData
, aSize
);
344 MemStream() : mData(nullptr), mLength(0), mCapacity(0) {}
345 ~MemStream() { free(mData
); }
350 virtual void write(const char* aData
, size_t aSize
) = 0;
351 virtual void read(char* aOut
, size_t aSize
) = 0;
352 virtual bool good() = 0;
353 virtual void SetIsBad() = 0;
356 class RecordedEvent
{
358 enum EventType
: uint8_t {
359 DRAWTARGETCREATION
= 0,
360 DRAWTARGETDESTRUCTION
,
377 DRAWDEPENDENTSURFACE
,
378 DRAWSURFACEWITHSHADOW
,
381 SOURCESURFACECREATION
,
382 SOURCESURFACEDESTRUCTION
,
383 GRADIENTSTOPSCREATION
,
384 GRADIENTSTOPSDESTRUCTION
,
387 SCALEDFONTDESTRUCTION
,
390 FILTERNODEDESTRUCTION
,
392 FILTERNODESETATTRIBUTE
,
394 CREATESIMILARDRAWTARGET
,
395 CREATECLIPPEDDRAWTARGET
,
396 CREATEDRAWTARGETFORFILTER
,
402 UNSCALEDFONTCREATION
,
403 UNSCALEDFONTDESTRUCTION
,
405 EXTERNALSURFACECREATION
,
408 OPTIMIZESOURCESURFACE
,
414 virtual ~RecordedEvent() = default;
416 static std::string
GetEventName(EventType aType
);
419 * Play back this event using the translator. Note that derived classes
421 * only return false when there is a fatal error, as it will probably mean
423 * translation will abort.
424 * @param aTranslator Translator to be used for retrieving other referenced
425 * objects and making playback decisions.
426 * @return true unless a fatal problem has occurred and playback should
429 virtual bool PlayEvent(Translator
* aTranslator
) const { return true; }
431 virtual void RecordToStream(std::ostream
& aStream
) const = 0;
432 virtual void RecordToStream(EventStream
& aStream
) const = 0;
433 virtual void RecordToStream(EventRingBuffer
& aStream
) const = 0;
434 virtual void RecordToStream(MemStream
& aStream
) const = 0;
436 virtual void OutputSimpleEventInfo(std::stringstream
& aStringStream
) const {}
439 void RecordPatternData(S
& aStream
,
440 const PatternStorage
& aPatternStorage
) const;
442 void ReadPatternData(S
& aStream
, PatternStorage
& aPatternStorage
) const;
443 void StorePattern(PatternStorage
& aDestination
, const Pattern
& aSource
) const;
445 void RecordStrokeOptions(S
& aStream
,
446 const StrokeOptions
& aStrokeOptions
) const;
448 void ReadStrokeOptions(S
& aStream
, StrokeOptions
& aStrokeOptions
);
450 virtual std::string
GetName() const = 0;
452 virtual ReferencePtr
GetDestinedDT() { return nullptr; }
454 void OutputSimplePatternInfo(const PatternStorage
& aStorage
,
455 std::stringstream
& aOutput
) const;
458 static bool DoWithEvent(S
& aStream
, EventType aType
,
459 const std::function
<bool(RecordedEvent
*)>& aAction
);
460 static bool DoWithEventFromStream(
461 EventStream
& aStream
, EventType aType
,
462 const std::function
<bool(RecordedEvent
*)>& aAction
);
463 static bool DoWithEventFromStream(
464 EventRingBuffer
& aStream
, EventType aType
,
465 const std::function
<bool(RecordedEvent
*)>& aAction
);
467 EventType
GetType() const { return (EventType
)mType
; }
470 friend class DrawEventRecorderPrivate
;
471 friend class DrawEventRecorderMemory
;
472 static void RecordUnscaledFont(UnscaledFont
* aUnscaledFont
,
473 std::ostream
* aOutput
);
474 static void RecordUnscaledFont(UnscaledFont
* aUnscaledFont
,
477 static void RecordUnscaledFontImpl(UnscaledFont
* aUnscaledFont
, S
& aOutput
);
479 MOZ_IMPLICIT
RecordedEvent(EventType aType
) : mType(aType
) {}
482 std::vector
<Float
> mDashPatternStorage
;
485 template <class Derived
>
486 class RecordedEventDerived
: public RecordedEvent
{
487 using RecordedEvent::RecordedEvent
;
490 void RecordToStream(std::ostream
& aStream
) const override
{
491 WriteElement(aStream
, this->mType
);
492 static_cast<const Derived
*>(this)->Record(aStream
);
494 void RecordToStream(EventStream
& aStream
) const override
{
495 WriteElement(aStream
, this->mType
);
496 static_cast<const Derived
*>(this)->Record(aStream
);
498 void RecordToStream(EventRingBuffer
& aStream
) const final
{
499 aStream
.RecordEvent(static_cast<const Derived
*>(this));
501 void RecordToStream(MemStream
& aStream
) const override
{
503 WriteElement(size
, this->mType
);
504 static_cast<const Derived
*>(this)->Record(size
);
506 if (!aStream
.Resize(aStream
.mLength
+ size
.mTotalSize
)) {
510 MemWriter
writer(aStream
.mData
+ aStream
.mLength
- size
.mTotalSize
);
511 WriteElement(writer
, this->mType
);
512 static_cast<const Derived
*>(this)->Record(writer
);
517 } // namespace mozilla