Bug 1634272 - Don't use DocumentChannel for about:newtab r=mattwoodrow
[gecko.git] / gfx / 2d / RecordedEvent.h
blob0f4a425830b90abcb88b3041e0d15eefda5c6100
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 "2D.h"
11 #include <ostream>
12 #include <sstream>
13 #include <cstring>
14 #include <functional>
15 #include <vector>
17 #include "RecordingTypes.h"
19 namespace mozilla {
20 namespace gfx {
22 const uint32_t kMagicInt = 0xc001feed;
24 // A change in major revision means a change in event binary format, causing
25 // loss of backwards compatibility. Old streams will not work in a player
26 // using a newer major revision. And new streams will not work in a player
27 // using an older major revision.
28 const uint16_t kMajorRevision = 10;
29 // A change in minor revision means additions of new events. New streams will
30 // not play in older players.
31 const uint16_t kMinorRevision = 1;
33 struct ReferencePtr {
34 ReferencePtr() : mLongPtr(0) {}
36 MOZ_IMPLICIT ReferencePtr(const void* aLongPtr)
37 : mLongPtr(uint64_t(aLongPtr)) {}
39 template <typename T>
40 MOZ_IMPLICIT ReferencePtr(const RefPtr<T>& aPtr)
41 : mLongPtr(uint64_t(aPtr.get())) {}
43 ReferencePtr& operator=(const void* aLongPtr) {
44 mLongPtr = uint64_t(aLongPtr);
45 return *this;
48 template <typename T>
49 ReferencePtr& operator=(const RefPtr<T>& aPtr) {
50 mLongPtr = uint64_t(aPtr.get());
51 return *this;
54 operator void*() const { return (void*)mLongPtr; }
56 uint64_t mLongPtr;
59 struct RecordedFontDetails {
60 uint64_t fontDataKey;
61 uint32_t size;
62 uint32_t index;
65 // Used by the Azure drawing debugger (player2d)
66 inline std::string StringFromPtr(ReferencePtr aPtr) {
67 std::stringstream stream;
68 stream << aPtr;
69 return stream.str();
72 class Translator {
73 public:
74 virtual ~Translator() = default;
76 virtual DrawTarget* LookupDrawTarget(ReferencePtr aRefPtr) = 0;
77 virtual Path* LookupPath(ReferencePtr aRefPtr) = 0;
78 virtual SourceSurface* LookupSourceSurface(ReferencePtr aRefPtr) = 0;
79 virtual FilterNode* LookupFilterNode(ReferencePtr aRefPtr) = 0;
80 virtual GradientStops* LookupGradientStops(ReferencePtr aRefPtr) = 0;
81 virtual ScaledFont* LookupScaledFont(ReferencePtr aRefPtr) = 0;
82 virtual UnscaledFont* LookupUnscaledFont(ReferencePtr aRefPtr) = 0;
83 virtual NativeFontResource* LookupNativeFontResource(uint64_t aKey) = 0;
84 virtual already_AddRefed<SourceSurface> LookupExternalSurface(uint64_t aKey) {
85 return nullptr;
87 virtual void AddDrawTarget(ReferencePtr aRefPtr, DrawTarget* aDT) = 0;
88 virtual void RemoveDrawTarget(ReferencePtr aRefPtr) = 0;
89 virtual void AddPath(ReferencePtr aRefPtr, Path* aPath) = 0;
90 virtual void RemovePath(ReferencePtr aRefPtr) = 0;
91 virtual void AddSourceSurface(ReferencePtr aRefPtr, SourceSurface* aPath) = 0;
92 virtual void RemoveSourceSurface(ReferencePtr aRefPtr) = 0;
93 virtual void AddFilterNode(mozilla::gfx::ReferencePtr aRefPtr,
94 FilterNode* aSurface) = 0;
95 virtual void RemoveFilterNode(mozilla::gfx::ReferencePtr aRefPtr) = 0;
96 virtual void AddGradientStops(ReferencePtr aRefPtr, GradientStops* aPath) = 0;
97 virtual void RemoveGradientStops(ReferencePtr aRefPtr) = 0;
98 virtual void AddScaledFont(ReferencePtr aRefPtr, ScaledFont* aScaledFont) = 0;
99 virtual void RemoveScaledFont(ReferencePtr aRefPtr) = 0;
100 virtual void AddUnscaledFont(ReferencePtr aRefPtr,
101 UnscaledFont* aUnscaledFont) = 0;
102 virtual void RemoveUnscaledFont(ReferencePtr aRefPtr) = 0;
103 virtual void AddNativeFontResource(
104 uint64_t aKey, NativeFontResource* aNativeFontResource) = 0;
106 virtual already_AddRefed<DrawTarget> CreateDrawTarget(ReferencePtr aRefPtr,
107 const IntSize& aSize,
108 SurfaceFormat aFormat);
109 virtual DrawTarget* GetReferenceDrawTarget() = 0;
110 virtual void* GetFontContext() { return nullptr; }
113 struct ColorPatternStorage {
114 DeviceColor mColor;
117 struct LinearGradientPatternStorage {
118 Point mBegin;
119 Point mEnd;
120 ReferencePtr mStops;
121 Matrix mMatrix;
124 struct RadialGradientPatternStorage {
125 Point mCenter1;
126 Point mCenter2;
127 Float mRadius1;
128 Float mRadius2;
129 ReferencePtr mStops;
130 Matrix mMatrix;
133 struct ConicGradientPatternStorage {
134 Point mCenter;
135 Float mAngle;
136 Float mStartOffset;
137 Float mEndOffset;
138 ReferencePtr mStops;
139 Matrix mMatrix;
142 struct SurfacePatternStorage {
143 ExtendMode mExtend;
144 SamplingFilter mSamplingFilter;
145 ReferencePtr mSurface;
146 Matrix mMatrix;
147 IntRect mSamplingRect;
150 struct PatternStorage {
151 PatternType mType;
152 union {
153 char* mStorage;
154 char mColor[sizeof(ColorPatternStorage)];
155 char mLinear[sizeof(LinearGradientPatternStorage)];
156 char mRadial[sizeof(RadialGradientPatternStorage)];
157 char mConic[sizeof(ConicGradientPatternStorage)];
158 char mSurface[sizeof(SurfacePatternStorage)];
162 /* SizeCollector and MemWriter are used
163 * in a pair to first collect the size of the
164 * event that we're going to write and then
165 * to write it without checking each individual
166 * size. */
167 struct SizeCollector {
168 SizeCollector() : mTotalSize(0) {}
169 void write(const char*, size_t s) { mTotalSize += s; }
170 size_t mTotalSize;
173 struct MemWriter {
174 explicit MemWriter(char* aPtr) : mPtr(aPtr) {}
175 void write(const char* aData, size_t aSize) {
176 memcpy(mPtr, aData, aSize);
177 mPtr += aSize;
179 char* mPtr;
182 // This is a simple interface for an EventRingBuffer, so we can use it in the
183 // RecordedEvent reading and writing machinery.
184 class EventRingBuffer {
185 public:
187 * Templated RecordEvent function so that when we have enough contiguous
188 * space we can record into the buffer quickly using MemWriter.
190 * @param aRecordedEvent the event to record
192 template <class RE>
193 void RecordEvent(const RE* aRecordedEvent) {
194 SizeCollector size;
195 WriteElement(size, aRecordedEvent->GetType());
196 aRecordedEvent->Record(size);
197 if (size.mTotalSize > mAvailable) {
198 WaitForAndRecalculateAvailableSpace();
200 if (size.mTotalSize <= mAvailable) {
201 MemWriter writer(mBufPos);
202 WriteElement(writer, aRecordedEvent->GetType());
203 aRecordedEvent->Record(writer);
204 UpdateWriteTotalsBy(size.mTotalSize);
205 } else {
206 WriteElement(*this, aRecordedEvent->GetType());
207 aRecordedEvent->Record(*this);
212 * Simple write function required by WriteElement.
214 * @param aData the data to be written to the buffer
215 * @param aSize the number of chars to write
217 virtual void write(const char* const aData, const size_t aSize) = 0;
220 * Simple read function required by ReadElement.
222 * @param aOut the pointer to read into
223 * @param aSize the number of chars to read
225 virtual void read(char* const aOut, const size_t aSize) = 0;
227 virtual bool good() const = 0;
229 virtual void SetIsBad() = 0;
231 protected:
233 * Wait until space is available for writing and then set mBufPos and
234 * mAvailable.
236 virtual bool WaitForAndRecalculateAvailableSpace() = 0;
239 * Update write count, mBufPos and mAvailable.
241 * @param aCount number of bytes written
243 virtual void UpdateWriteTotalsBy(uint32_t aCount) = 0;
245 char* mBufPos = nullptr;
246 uint32_t mAvailable = 0;
249 struct MemStream {
250 char* mData;
251 size_t mLength;
252 size_t mCapacity;
253 bool mValid = true;
254 bool Resize(size_t aSize) {
255 if (!mValid) {
256 return false;
258 mLength = aSize;
259 if (mLength > mCapacity) {
260 mCapacity = mCapacity * 2;
261 // check if the doubled capacity is enough
262 // otherwise use double mLength
263 if (mLength > mCapacity) {
264 mCapacity = mLength * 2;
266 mData = (char*)realloc(mData, mCapacity);
268 if (mData) {
269 return true;
271 NS_ERROR("Failed to allocate MemStream!");
272 mValid = false;
273 mLength = 0;
274 return false;
277 void write(const char* aData, size_t aSize) {
278 if (Resize(mLength + aSize)) {
279 memcpy(mData + mLength - aSize, aData, aSize);
283 MemStream() : mData(nullptr), mLength(0), mCapacity(0) {}
284 ~MemStream() { free(mData); }
287 class EventStream {
288 public:
289 virtual void write(const char* aData, size_t aSize) = 0;
290 virtual void read(char* aOut, size_t aSize) = 0;
291 virtual bool good() = 0;
292 virtual void SetIsBad() = 0;
295 class RecordedEvent {
296 public:
297 enum EventType {
298 DRAWTARGETCREATION = 0,
299 DRAWTARGETDESTRUCTION,
300 FILLRECT,
301 STROKERECT,
302 STROKELINE,
303 CLEARRECT,
304 COPYSURFACE,
305 SETTRANSFORM,
306 PUSHCLIP,
307 PUSHCLIPRECT,
308 POPCLIP,
309 FILL,
310 FILLGLYPHS,
311 MASK,
312 STROKE,
313 DRAWSURFACE,
314 DRAWDEPENDENTSURFACE,
315 DRAWSURFACEWITHSHADOW,
316 PATHCREATION,
317 PATHDESTRUCTION,
318 SOURCESURFACECREATION,
319 SOURCESURFACEDESTRUCTION,
320 GRADIENTSTOPSCREATION,
321 GRADIENTSTOPSDESTRUCTION,
322 SNAPSHOT,
323 SCALEDFONTCREATION,
324 SCALEDFONTDESTRUCTION,
325 MASKSURFACE,
326 FILTERNODECREATION,
327 FILTERNODEDESTRUCTION,
328 DRAWFILTER,
329 FILTERNODESETATTRIBUTE,
330 FILTERNODESETINPUT,
331 CREATESIMILARDRAWTARGET,
332 CREATECLIPPEDDRAWTARGET,
333 CREATEDRAWTARGETFORFILTER,
334 FONTDATA,
335 FONTDESC,
336 PUSHLAYER,
337 PUSHLAYERWITHBLEND,
338 POPLAYER,
339 UNSCALEDFONTCREATION,
340 UNSCALEDFONTDESTRUCTION,
341 INTOLUMINANCE,
342 EXTERNALSURFACECREATION,
343 FLUSH,
344 DETACHALLSNAPSHOTS,
345 OPTIMIZESOURCESURFACE,
346 LAST,
349 virtual ~RecordedEvent() = default;
351 static std::string GetEventName(EventType aType);
354 * Play back this event using the translator. Note that derived classes
355 * should
356 * only return false when there is a fatal error, as it will probably mean
357 * the
358 * translation will abort.
359 * @param aTranslator Translator to be used for retrieving other referenced
360 * objects and making playback decisions.
361 * @return true unless a fatal problem has occurred and playback should
362 * abort.
364 virtual bool PlayEvent(Translator* aTranslator) const { return true; }
366 virtual void RecordToStream(std::ostream& aStream) const = 0;
367 virtual void RecordToStream(EventStream& aStream) const = 0;
368 virtual void RecordToStream(EventRingBuffer& aStream) const = 0;
369 virtual void RecordToStream(MemStream& aStream) const = 0;
371 virtual void OutputSimpleEventInfo(std::stringstream& aStringStream) const {}
373 template <class S>
374 void RecordPatternData(S& aStream,
375 const PatternStorage& aPatternStorage) const;
376 template <class S>
377 void ReadPatternData(S& aStream, PatternStorage& aPatternStorage) const;
378 void StorePattern(PatternStorage& aDestination, const Pattern& aSource) const;
379 template <class S>
380 void RecordStrokeOptions(S& aStream,
381 const StrokeOptions& aStrokeOptions) const;
382 template <class S>
383 void ReadStrokeOptions(S& aStream, StrokeOptions& aStrokeOptions);
385 virtual std::string GetName() const = 0;
387 virtual ReferencePtr GetDestinedDT() { return nullptr; }
389 void OutputSimplePatternInfo(const PatternStorage& aStorage,
390 std::stringstream& aOutput) const;
392 template <class S>
393 static bool DoWithEvent(S& aStream, EventType aType,
394 const std::function<bool(RecordedEvent*)>& aAction);
395 static bool DoWithEventFromStream(
396 EventStream& aStream, EventType aType,
397 const std::function<bool(RecordedEvent*)>& aAction);
398 static bool DoWithEventFromStream(
399 EventRingBuffer& aStream, EventType aType,
400 const std::function<bool(RecordedEvent*)>& aAction);
402 EventType GetType() const { return (EventType)mType; }
404 protected:
405 friend class DrawEventRecorderPrivate;
406 friend class DrawEventRecorderFile;
407 friend class DrawEventRecorderMemory;
408 static void RecordUnscaledFont(UnscaledFont* aUnscaledFont,
409 std::ostream* aOutput);
410 static void RecordUnscaledFont(UnscaledFont* aUnscaledFont,
411 MemStream& aOutput);
412 template <class S>
413 static void RecordUnscaledFontImpl(UnscaledFont* aUnscaledFont, S& aOutput);
415 MOZ_IMPLICIT RecordedEvent(int32_t aType) : mType(aType) {}
417 int32_t mType;
418 std::vector<Float> mDashPatternStorage;
421 template <class Derived>
422 class RecordedEventDerived : public RecordedEvent {
423 using RecordedEvent::RecordedEvent;
425 public:
426 void RecordToStream(std::ostream& aStream) const override {
427 WriteElement(aStream, this->mType);
428 static_cast<const Derived*>(this)->Record(aStream);
430 void RecordToStream(EventStream& aStream) const override {
431 WriteElement(aStream, this->mType);
432 static_cast<const Derived*>(this)->Record(aStream);
434 void RecordToStream(EventRingBuffer& aStream) const final {
435 aStream.RecordEvent(static_cast<const Derived*>(this));
437 void RecordToStream(MemStream& aStream) const override {
438 SizeCollector size;
439 WriteElement(size, this->mType);
440 static_cast<const Derived*>(this)->Record(size);
442 if (!aStream.Resize(aStream.mLength + size.mTotalSize)) {
443 return;
446 MemWriter writer(aStream.mData + aStream.mLength - size.mTotalSize);
447 WriteElement(writer, this->mType);
448 static_cast<const Derived*>(this)->Record(writer);
452 } // namespace gfx
453 } // namespace mozilla
455 #endif