Backed out 2 changesets (bug 1855992) for causing talos failures @ mozilla::net:...
[gecko.git] / gfx / 2d / RecordedEvent.h
bloba3a3a43ba0ec2c25865c017bca6e347cd0cbf7d6
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(ReferencePtr aDrawTarget, uint64_t aKey,
106 const Rect& aRect);
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,
127 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 nsRefPtrHashtable<nsUint64HashKey, RecordedDependentSurface>*
153 mDependentSurfaces = nullptr;
156 struct ColorPatternStorage {
157 DeviceColor mColor;
160 struct LinearGradientPatternStorage {
161 Point mBegin;
162 Point mEnd;
163 ReferencePtr mStops;
164 Matrix mMatrix;
167 struct RadialGradientPatternStorage {
168 Point mCenter1;
169 Point mCenter2;
170 Float mRadius1;
171 Float mRadius2;
172 ReferencePtr mStops;
173 Matrix mMatrix;
176 struct ConicGradientPatternStorage {
177 Point mCenter;
178 Float mAngle;
179 Float mStartOffset;
180 Float mEndOffset;
181 ReferencePtr mStops;
182 Matrix mMatrix;
185 struct SurfacePatternStorage {
186 ExtendMode mExtend;
187 SamplingFilter mSamplingFilter;
188 ReferencePtr mSurface;
189 Matrix mMatrix;
190 IntRect mSamplingRect;
193 struct PatternStorage {
194 PatternType mType;
195 union {
196 char* mStorage;
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
209 * size. */
210 struct SizeCollector {
211 SizeCollector() : mTotalSize(0) {}
212 void write(const char*, size_t s) { mTotalSize += s; }
213 size_t mTotalSize;
216 struct MemWriter {
217 explicit MemWriter(char* aPtr) : mPtr(aPtr) {}
218 void write(const char* aData, size_t aSize) {
219 memcpy(mPtr, aData, aSize);
220 mPtr += aSize;
222 char* mPtr;
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 {
228 public:
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
235 template <class RE>
236 void RecordEvent(const RE* aRecordedEvent) {
237 SizeCollector size;
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);
248 } else {
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;
274 protected:
276 * Wait until space is available for writing and then set mBufPos and
277 * mAvailable.
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;
292 struct MemStream {
293 char* mData;
294 size_t mLength;
295 size_t mCapacity;
296 bool mValid = true;
297 bool Resize(size_t aSize) {
298 if (!mValid) {
299 return false;
301 mLength = 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);
310 if (!data) {
311 free(mData);
313 mData = data;
315 if (mData) {
316 return true;
318 NS_ERROR("Failed to allocate MemStream!");
319 mValid = false;
320 mLength = 0;
321 mCapacity = 0;
322 return false;
325 void reset() {
326 free(mData);
327 mData = nullptr;
328 mValid = true;
329 mLength = 0;
330 mCapacity = 0;
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); }
348 class EventStream {
349 public:
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 {
357 public:
358 enum EventType : uint8_t {
359 DRAWTARGETCREATION = 0,
360 DRAWTARGETDESTRUCTION,
361 FILLRECT,
362 STROKERECT,
363 STROKELINE,
364 STROKECIRCLE,
365 CLEARRECT,
366 COPYSURFACE,
367 SETTRANSFORM,
368 PUSHCLIP,
369 PUSHCLIPRECT,
370 POPCLIP,
371 FILL,
372 FILLCIRCLE,
373 FILLGLYPHS,
374 MASK,
375 STROKE,
376 DRAWSURFACE,
377 DRAWDEPENDENTSURFACE,
378 DRAWSURFACEWITHSHADOW,
379 PATHCREATION,
380 PATHDESTRUCTION,
381 SOURCESURFACECREATION,
382 SOURCESURFACEDESTRUCTION,
383 GRADIENTSTOPSCREATION,
384 GRADIENTSTOPSDESTRUCTION,
385 SNAPSHOT,
386 SCALEDFONTCREATION,
387 SCALEDFONTDESTRUCTION,
388 MASKSURFACE,
389 FILTERNODECREATION,
390 FILTERNODEDESTRUCTION,
391 DRAWFILTER,
392 FILTERNODESETATTRIBUTE,
393 FILTERNODESETINPUT,
394 CREATESIMILARDRAWTARGET,
395 CREATECLIPPEDDRAWTARGET,
396 CREATEDRAWTARGETFORFILTER,
397 FONTDATA,
398 FONTDESC,
399 PUSHLAYER,
400 PUSHLAYERWITHBLEND,
401 POPLAYER,
402 UNSCALEDFONTCREATION,
403 UNSCALEDFONTDESTRUCTION,
404 INTOLUMINANCE,
405 EXTERNALSURFACECREATION,
406 FLUSH,
407 DETACHALLSNAPSHOTS,
408 OPTIMIZESOURCESURFACE,
409 LINK,
410 DESTINATION,
411 LAST,
414 virtual ~RecordedEvent() = default;
416 static std::string GetEventName(EventType aType);
419 * Play back this event using the translator. Note that derived classes
420 * should
421 * only return false when there is a fatal error, as it will probably mean
422 * the
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
427 * abort.
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 {}
438 template <class S>
439 void RecordPatternData(S& aStream,
440 const PatternStorage& aPatternStorage) const;
441 template <class S>
442 void ReadPatternData(S& aStream, PatternStorage& aPatternStorage) const;
443 void StorePattern(PatternStorage& aDestination, const Pattern& aSource) const;
444 template <class S>
445 void RecordStrokeOptions(S& aStream,
446 const StrokeOptions& aStrokeOptions) const;
447 template <class S>
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;
457 template <class S>
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; }
469 protected:
470 friend class DrawEventRecorderPrivate;
471 friend class DrawEventRecorderMemory;
472 static void RecordUnscaledFont(UnscaledFont* aUnscaledFont,
473 std::ostream* aOutput);
474 static void RecordUnscaledFont(UnscaledFont* aUnscaledFont,
475 MemStream& aOutput);
476 template <class S>
477 static void RecordUnscaledFontImpl(UnscaledFont* aUnscaledFont, S& aOutput);
479 MOZ_IMPLICIT RecordedEvent(EventType aType) : mType(aType) {}
481 EventType mType;
482 std::vector<Float> mDashPatternStorage;
485 template <class Derived>
486 class RecordedEventDerived : public RecordedEvent {
487 using RecordedEvent::RecordedEvent;
489 public:
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 {
502 SizeCollector size;
503 WriteElement(size, this->mType);
504 static_cast<const Derived*>(this)->Record(size);
506 if (!aStream.Resize(aStream.mLength + size.mTotalSize)) {
507 return;
510 MemWriter writer(aStream.mData + aStream.mLength - size.mTotalSize);
511 WriteElement(writer, this->mType);
512 static_cast<const Derived*>(this)->Record(writer);
516 } // namespace gfx
517 } // namespace mozilla
519 #endif