no bug - Import translations from android-l10n r=release a=l10n CLOSED TREE
[gecko.git] / gfx / 2d / RecordedEvent.h
bloba8801ddd1fb0efd598789208b4c875c6a3ba0052
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 SETPERMITSUBPIXELAA,
381 SETTRANSFORM,
382 PUSHCLIP,
383 PUSHCLIPRECT,
384 POPCLIP,
385 FILL,
386 FILLCIRCLE,
387 FILLGLYPHS,
388 STROKEGLYPHS,
389 MASK,
390 STROKE,
391 DRAWSURFACE,
392 DRAWDEPENDENTSURFACE,
393 DRAWSURFACEWITHSHADOW,
394 DRAWSHADOW,
395 PATHCREATION,
396 PATHDESTRUCTION,
397 SOURCESURFACECREATION,
398 SOURCESURFACEDESTRUCTION,
399 GRADIENTSTOPSCREATION,
400 GRADIENTSTOPSDESTRUCTION,
401 SNAPSHOT,
402 SCALEDFONTCREATION,
403 SCALEDFONTDESTRUCTION,
404 MASKSURFACE,
405 FILTERNODECREATION,
406 FILTERNODEDESTRUCTION,
407 DRAWFILTER,
408 FILTERNODESETATTRIBUTE,
409 FILTERNODESETINPUT,
410 CREATESIMILARDRAWTARGET,
411 CREATECLIPPEDDRAWTARGET,
412 CREATEDRAWTARGETFORFILTER,
413 FONTDATA,
414 FONTDESC,
415 PUSHLAYER,
416 PUSHLAYERWITHBLEND,
417 POPLAYER,
418 UNSCALEDFONTCREATION,
419 UNSCALEDFONTDESTRUCTION,
420 INTOLUMINANCE,
421 EXTRACTSUBRECT,
422 EXTERNALSURFACECREATION,
423 FLUSH,
424 DETACHALLSNAPSHOTS,
425 OPTIMIZESOURCESURFACE,
426 LINK,
427 DESTINATION,
428 LAST,
431 virtual ~RecordedEvent() = default;
433 static std::string GetEventName(EventType aType);
436 * Play back this event using the translator. Note that derived classes
437 * should
438 * only return false when there is a fatal error, as it will probably mean
439 * the
440 * translation will abort.
441 * @param aTranslator Translator to be used for retrieving other referenced
442 * objects and making playback decisions.
443 * @return true unless a fatal problem has occurred and playback should
444 * abort.
446 virtual bool PlayEvent(Translator* aTranslator) const { return true; }
448 virtual void RecordToStream(std::ostream& aStream) const = 0;
449 virtual void RecordToStream(EventStream& aStream) const = 0;
450 virtual void RecordToStream(ContiguousBufferStream& aStream) const = 0;
451 virtual void RecordToStream(MemStream& aStream) const = 0;
453 virtual void OutputSimpleEventInfo(std::stringstream& aStringStream) const {}
455 template <class S>
456 void RecordPatternData(S& aStream,
457 const PatternStorage& aPatternStorage) const;
458 template <class S>
459 void ReadPatternData(S& aStream, PatternStorage& aPatternStorage) const;
460 void StorePattern(PatternStorage& aDestination, const Pattern& aSource) const;
461 template <class S>
462 void RecordStrokeOptions(S& aStream,
463 const StrokeOptions& aStrokeOptions) const;
464 template <class S>
465 void ReadStrokeOptions(S& aStream, StrokeOptions& aStrokeOptions);
467 virtual std::string GetName() const = 0;
469 virtual ReferencePtr GetDestinedDT() { return nullptr; }
471 void OutputSimplePatternInfo(const PatternStorage& aStorage,
472 std::stringstream& aOutput) const;
474 template <class S>
475 static bool DoWithEvent(S& aStream, EventType aType,
476 const std::function<bool(RecordedEvent*)>& aAction);
477 static bool DoWithEventFromStream(
478 EventStream& aStream, EventType aType,
479 const std::function<bool(RecordedEvent*)>& aAction);
480 static bool DoWithEventFromReader(
481 MemReader& aReader, EventType aType,
482 const std::function<bool(RecordedEvent*)>& aAction);
484 EventType GetType() const { return (EventType)mType; }
486 protected:
487 friend class DrawEventRecorderPrivate;
488 friend class DrawEventRecorderMemory;
489 static void RecordUnscaledFont(UnscaledFont* aUnscaledFont,
490 std::ostream* aOutput);
491 static void RecordUnscaledFont(UnscaledFont* aUnscaledFont,
492 MemStream& aOutput);
493 template <class S>
494 static void RecordUnscaledFontImpl(UnscaledFont* aUnscaledFont, S& aOutput);
496 MOZ_IMPLICIT RecordedEvent(EventType aType) : mType(aType) {}
498 EventType mType;
499 std::vector<Float> mDashPatternStorage;
502 template <class Derived>
503 class RecordedEventDerived : public RecordedEvent {
504 using RecordedEvent::RecordedEvent;
506 public:
507 void RecordToStream(std::ostream& aStream) const override {
508 WriteElement(aStream, this->mType);
509 static_cast<const Derived*>(this)->Record(aStream);
511 void RecordToStream(EventStream& aStream) const override {
512 WriteElement(aStream, this->mType);
513 static_cast<const Derived*>(this)->Record(aStream);
515 void RecordToStream(ContiguousBufferStream& aStream) const final {
516 aStream.RecordEvent(static_cast<const Derived*>(this));
518 void RecordToStream(MemStream& aStream) const override {
519 SizeCollector size;
520 WriteElement(size, this->mType);
521 static_cast<const Derived*>(this)->Record(size);
523 if (!aStream.Resize(aStream.mLength + size.mTotalSize)) {
524 return;
527 MemWriter writer(aStream.mData + aStream.mLength - size.mTotalSize);
528 WriteElement(writer, this->mType);
529 static_cast<const Derived*>(this)->Record(writer);
533 } // namespace gfx
534 } // namespace mozilla
536 #endif