/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef MOZILLA_GFX_RECORDEDEVENT_H_ #define MOZILLA_GFX_RECORDEDEVENT_H_ #include "2D.h" #include #include #include #include namespace mozilla { namespace gfx { struct PathOp; class PathRecording; const uint32_t kMagicInt = 0xc001feed; // A change in major revision means a change in event binary format, causing // loss of backwards compatibility. Old streams will not work in a player // using a newer major revision. And new streams will not work in a player // using an older major revision. const uint16_t kMajorRevision = 10; // A change in minor revision means additions of new events. New streams will // not play in older players. const uint16_t kMinorRevision = 0; struct ReferencePtr { ReferencePtr() : mLongPtr(0) {} MOZ_IMPLICIT ReferencePtr(const void* aLongPtr) : mLongPtr(uint64_t(aLongPtr)) {} template MOZ_IMPLICIT ReferencePtr(const RefPtr& aPtr) : mLongPtr(uint64_t(aPtr.get())) {} ReferencePtr &operator =(const void* aLongPtr) { mLongPtr = uint64_t(aLongPtr); return *this; } template ReferencePtr &operator =(const RefPtr& aPtr) { mLongPtr = uint64_t(aPtr.get()); return *this; } operator void*() const { return (void*)mLongPtr; } uint64_t mLongPtr; }; struct RecordedFontDetails { uint64_t fontDataKey; uint32_t size; uint32_t index; }; // Used by the Azure drawing debugger (player2d) inline std::string StringFromPtr(ReferencePtr aPtr) { std::stringstream stream; stream << aPtr; return stream.str(); } class Translator { public: virtual ~Translator() {} virtual DrawTarget *LookupDrawTarget(ReferencePtr aRefPtr) = 0; virtual Path *LookupPath(ReferencePtr aRefPtr) = 0; virtual SourceSurface *LookupSourceSurface(ReferencePtr aRefPtr) = 0; virtual FilterNode *LookupFilterNode(ReferencePtr aRefPtr) = 0; virtual GradientStops *LookupGradientStops(ReferencePtr aRefPtr) = 0; virtual ScaledFont *LookupScaledFont(ReferencePtr aRefPtr) = 0; virtual UnscaledFont* LookupUnscaledFont(ReferencePtr aRefPtr) = 0; virtual NativeFontResource *LookupNativeFontResource(uint64_t aKey) = 0; virtual void AddDrawTarget(ReferencePtr aRefPtr, DrawTarget *aDT) = 0; virtual void RemoveDrawTarget(ReferencePtr aRefPtr) = 0; virtual void AddPath(ReferencePtr aRefPtr, Path *aPath) = 0; virtual void RemovePath(ReferencePtr aRefPtr) = 0; virtual void AddSourceSurface(ReferencePtr aRefPtr, SourceSurface *aPath) = 0; virtual void RemoveSourceSurface(ReferencePtr aRefPtr) = 0; virtual void AddFilterNode(mozilla::gfx::ReferencePtr aRefPtr, FilterNode *aSurface) = 0; virtual void RemoveFilterNode(mozilla::gfx::ReferencePtr aRefPtr) = 0; virtual void AddGradientStops(ReferencePtr aRefPtr, GradientStops *aPath) = 0; virtual void RemoveGradientStops(ReferencePtr aRefPtr) = 0; virtual void AddScaledFont(ReferencePtr aRefPtr, ScaledFont *aScaledFont) = 0; virtual void RemoveScaledFont(ReferencePtr aRefPtr) = 0; virtual void AddUnscaledFont(ReferencePtr aRefPtr, UnscaledFont* aUnscaledFont) = 0; virtual void RemoveUnscaledFont(ReferencePtr aRefPtr) = 0; virtual void AddNativeFontResource(uint64_t aKey, NativeFontResource *aNativeFontResource) = 0; virtual already_AddRefed CreateDrawTarget(ReferencePtr aRefPtr, const IntSize &aSize, SurfaceFormat aFormat); virtual DrawTarget *GetReferenceDrawTarget() = 0; virtual void* GetFontContext() { return nullptr; } }; struct ColorPatternStorage { Color mColor; }; struct LinearGradientPatternStorage { Point mBegin; Point mEnd; ReferencePtr mStops; Matrix mMatrix; }; struct RadialGradientPatternStorage { Point mCenter1; Point mCenter2; Float mRadius1; Float mRadius2; ReferencePtr mStops; Matrix mMatrix; }; struct SurfacePatternStorage { ExtendMode mExtend; SamplingFilter mSamplingFilter; ReferencePtr mSurface; Matrix mMatrix; IntRect mSamplingRect; }; struct PatternStorage { PatternType mType; union { char *mStorage; char mColor[sizeof(ColorPatternStorage)]; char mLinear[sizeof(LinearGradientPatternStorage)]; char mRadial[sizeof(RadialGradientPatternStorage)]; char mSurface[sizeof(SurfacePatternStorage)]; }; }; /* SizeCollector and MemWriter are used * in a pair to first collect the size of the * event that we're going to write and then * to write it without checking each individual * size. */ struct SizeCollector { SizeCollector() : mTotalSize(0) {} void write(const char*, size_t s) { mTotalSize += s; } size_t mTotalSize; }; struct MemWriter { explicit MemWriter(char* aPtr) : mPtr(aPtr) {} void write(const char* aData, size_t aSize) { memcpy(mPtr, aData, aSize); mPtr += aSize; } char* mPtr; }; struct MemStream { char *mData; size_t mLength; size_t mCapacity; void Resize(size_t aSize) { mLength = aSize; if (mLength > mCapacity) { mCapacity = mCapacity * 2; // check if the doubled capacity is enough // otherwise use mLength if (mLength > mCapacity) { mCapacity = mLength; } mData = (char*)realloc(mData, mCapacity * 2); } } void write(const char* aData, size_t aSize) { Resize(mLength + aSize); memcpy(mData + mLength - aSize, aData, aSize); } MemStream() : mData(nullptr), mLength(0), mCapacity(0) {} ~MemStream() { free(mData); } }; class RecordedEvent { public: enum EventType { DRAWTARGETCREATION = 0, DRAWTARGETDESTRUCTION, FILLRECT, STROKERECT, STROKELINE, CLEARRECT, COPYSURFACE, SETTRANSFORM, PUSHCLIP, PUSHCLIPRECT, POPCLIP, FILL, FILLGLYPHS, MASK, STROKE, DRAWSURFACE, DRAWSURFACEWITHSHADOW, PATHCREATION, PATHDESTRUCTION, SOURCESURFACECREATION, SOURCESURFACEDESTRUCTION, GRADIENTSTOPSCREATION, GRADIENTSTOPSDESTRUCTION, SNAPSHOT, SCALEDFONTCREATION, SCALEDFONTDESTRUCTION, MASKSURFACE, FILTERNODECREATION, FILTERNODEDESTRUCTION, DRAWFILTER, FILTERNODESETATTRIBUTE, FILTERNODESETINPUT, CREATESIMILARDRAWTARGET, FONTDATA, FONTDESC, PUSHLAYER, POPLAYER, UNSCALEDFONTCREATION, UNSCALEDFONTDESTRUCTION, }; static const uint32_t kTotalEventTypes = RecordedEvent::FILTERNODESETINPUT + 1; virtual ~RecordedEvent() {} static std::string GetEventName(EventType aType); /** * Play back this event using the translator. Note that derived classes should * only return false when there is a fatal error, as it will probably mean the * translation will abort. * @param aTranslator Translator to be used for retrieving other referenced * objects and making playback decisions. * @return true unless a fatal problem has occurred and playback should abort. */ virtual bool PlayEvent(Translator *aTranslator) const { return true; } virtual void RecordToStream(std::ostream &aStream) const {} virtual void RecordToStream(MemStream &aStream) const = 0; virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const { } template void RecordPatternData(S &aStream, const PatternStorage &aPatternStorage) const; template void ReadPatternData(S &aStream, PatternStorage &aPatternStorage) const; void StorePattern(PatternStorage &aDestination, const Pattern &aSource) const; template void RecordStrokeOptions(S &aStream, const StrokeOptions &aStrokeOptions) const; template void ReadStrokeOptions(S &aStream, StrokeOptions &aStrokeOptions); virtual std::string GetName() const = 0; virtual ReferencePtr GetObjectRef() const = 0; virtual ReferencePtr GetDestinedDT() { return nullptr; } void OutputSimplePatternInfo(const PatternStorage &aStorage, std::stringstream &aOutput) const; template static RecordedEvent *LoadEvent(S &aStream, EventType aType); static RecordedEvent *LoadEventFromStream(std::istream &aStream, EventType aType); // An alternative to LoadEvent that avoids a heap allocation for the event. // This accepts a callable `f' that will take a RecordedEvent* as a single parameter template static bool DoWithEvent(S &aStream, EventType aType, F f); EventType GetType() { return (EventType)mType; } protected: friend class DrawEventRecorderPrivate; friend class DrawEventRecorderFile; friend class DrawEventRecorderMemory; MOZ_IMPLICIT RecordedEvent(int32_t aType) : mType(aType) {} int32_t mType; std::vector mDashPatternStorage; }; } // namespace gfx } // namespace mozilla #endif