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/. */
6 
7 #include "DrawTargetWrapAndRecord.h"
8 #include "PathRecording.h"
9 #include <stdio.h>
10 
11 #include "Logging.h"
12 #include "Tools.h"
13 #include "Filters.h"
14 #include "mozilla/UniquePtr.h"
15 #include "RecordingTypes.h"
16 #include "RecordedEventImpl.h"
17 
18 namespace mozilla {
19 namespace gfx {
20 
21 struct WrapAndRecordSourceSurfaceUserData {
22   void* refPtr;
23   RefPtr<DrawEventRecorderPrivate> recorder;
24 };
25 
WrapAndRecordSourceSurfaceUserDataFunc(void * aUserData)26 static void WrapAndRecordSourceSurfaceUserDataFunc(void* aUserData) {
27   WrapAndRecordSourceSurfaceUserData* userData =
28       static_cast<WrapAndRecordSourceSurfaceUserData*>(aUserData);
29 
30   userData->recorder->RecordSourceSurfaceDestruction(
31       static_cast<SourceSurface*>(userData->refPtr));
32 
33   delete userData;
34 }
35 
StoreSourceSurface(DrawEventRecorderPrivate * aRecorder,SourceSurface * aSurface,DataSourceSurface * aDataSurf,const char * reason)36 static void StoreSourceSurface(DrawEventRecorderPrivate* aRecorder,
37                                SourceSurface* aSurface,
38                                DataSourceSurface* aDataSurf,
39                                const char* reason) {
40   if (!aDataSurf) {
41     gfxWarning() << "Recording failed to record SourceSurface for " << reason;
42     // Insert a bogus source surface.
43     int32_t stride =
44         aSurface->GetSize().width * BytesPerPixel(aSurface->GetFormat());
45     UniquePtr<uint8_t[]> sourceData(
46         new uint8_t[stride * aSurface->GetSize().height]());
47     aRecorder->RecordEvent(RecordedSourceSurfaceCreation(
48         aSurface, sourceData.get(), stride, aSurface->GetSize(),
49         aSurface->GetFormat()));
50   } else {
51     DataSourceSurface::ScopedMap map(aDataSurf, DataSourceSurface::READ);
52     aRecorder->RecordEvent(RecordedSourceSurfaceCreation(
53         aSurface, map.GetData(), map.GetStride(), aDataSurf->GetSize(),
54         aDataSurf->GetFormat()));
55   }
56 }
57 
EnsureSurfaceStored(DrawEventRecorderPrivate * aRecorder,SourceSurface * aSurface,const char * reason)58 static void EnsureSurfaceStored(DrawEventRecorderPrivate* aRecorder,
59                                 SourceSurface* aSurface, const char* reason) {
60   if (aRecorder->HasStoredObject(aSurface)) {
61     return;
62   }
63 
64   RefPtr<DataSourceSurface> dataSurf = aSurface->GetDataSurface();
65   StoreSourceSurface(aRecorder, aSurface, dataSurf, reason);
66   aRecorder->AddStoredObject(aSurface);
67   aRecorder->AddSourceSurface(aSurface);
68 
69   WrapAndRecordSourceSurfaceUserData* userData =
70       new WrapAndRecordSourceSurfaceUserData;
71   userData->refPtr = aSurface;
72   userData->recorder = aRecorder;
73   aSurface->AddUserData(reinterpret_cast<UserDataKey*>(aRecorder), userData,
74                         &WrapAndRecordSourceSurfaceUserDataFunc);
75 }
76 
77 class SourceSurfaceWrapAndRecord : public SourceSurface {
78  public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceWrapAndRecord,override)79   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceWrapAndRecord, override)
80 
81   SourceSurfaceWrapAndRecord(SourceSurface* aFinalSurface,
82                              DrawEventRecorderPrivate* aRecorder)
83       : mFinalSurface(aFinalSurface), mRecorder(aRecorder) {
84     mRecorder->AddStoredObject(this);
85   }
86 
~SourceSurfaceWrapAndRecord()87   ~SourceSurfaceWrapAndRecord() {
88     mRecorder->RemoveStoredObject(this);
89     mRecorder->RecordEvent(
90         RecordedSourceSurfaceDestruction(ReferencePtr(this)));
91   }
92 
GetType() const93   SurfaceType GetType() const override { return SurfaceType::WRAP_AND_RECORD; }
GetSize() const94   IntSize GetSize() const override { return mFinalSurface->GetSize(); }
GetFormat() const95   SurfaceFormat GetFormat() const override {
96     return mFinalSurface->GetFormat();
97   }
GetDataSurface()98   already_AddRefed<DataSourceSurface> GetDataSurface() override {
99     return mFinalSurface->GetDataSurface();
100   }
101 
102   RefPtr<SourceSurface> mFinalSurface;
103   RefPtr<DrawEventRecorderPrivate> mRecorder;
104 };
105 
106 class GradientStopsWrapAndRecord : public GradientStops {
107  public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStopsWrapAndRecord,override)108   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStopsWrapAndRecord, override)
109 
110   GradientStopsWrapAndRecord(GradientStops* aFinalGradientStops,
111                              DrawEventRecorderPrivate* aRecorder)
112       : mFinalGradientStops(aFinalGradientStops), mRecorder(aRecorder) {
113     mRecorder->AddStoredObject(this);
114   }
115 
~GradientStopsWrapAndRecord()116   ~GradientStopsWrapAndRecord() {
117     mRecorder->RemoveStoredObject(this);
118     mRecorder->RecordEvent(
119         RecordedGradientStopsDestruction(ReferencePtr(this)));
120   }
121 
GetBackendType() const122   BackendType GetBackendType() const override { return BackendType::RECORDING; }
123 
124   RefPtr<GradientStops> mFinalGradientStops;
125   RefPtr<DrawEventRecorderPrivate> mRecorder;
126 };
127 
GetSourceSurface(SourceSurface * aSurface)128 static SourceSurface* GetSourceSurface(SourceSurface* aSurface) {
129   if (aSurface->GetType() != SurfaceType::WRAP_AND_RECORD) {
130     return aSurface;
131   }
132 
133   return static_cast<SourceSurfaceWrapAndRecord*>(aSurface)->mFinalSurface;
134 }
135 
GetGradientStops(GradientStops * aStops)136 static already_AddRefed<GradientStops> GetGradientStops(GradientStops* aStops) {
137   if (aStops->GetBackendType() != BackendType::RECORDING) {
138     return do_AddRef(aStops);
139   }
140 
141   return do_AddRef(
142       static_cast<GradientStopsWrapAndRecord*>(aStops)->mFinalGradientStops);
143 }
144 
145 class FilterNodeWrapAndRecord : public FilterNode {
146  public:
147   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeWrapAndRecord, override)
148   using FilterNode::SetAttribute;
149 
FilterNodeWrapAndRecord(FilterNode * aFinalFilterNode,DrawEventRecorderPrivate * aRecorder)150   FilterNodeWrapAndRecord(FilterNode* aFinalFilterNode,
151                           DrawEventRecorderPrivate* aRecorder)
152       : mFinalFilterNode(aFinalFilterNode), mRecorder(aRecorder) {
153     mRecorder->AddStoredObject(this);
154   }
155 
~FilterNodeWrapAndRecord()156   ~FilterNodeWrapAndRecord() {
157     mRecorder->RemoveStoredObject(this);
158     mRecorder->RecordEvent(RecordedFilterNodeDestruction(ReferencePtr(this)));
159   }
160 
GetFilterNode(FilterNode * aNode)161   static FilterNode* GetFilterNode(FilterNode* aNode) {
162     if (aNode->GetBackendType() != FILTER_BACKEND_RECORDING) {
163       gfxWarning()
164           << "Non recording filter node used with recording DrawTarget!";
165       return aNode;
166     }
167 
168     return static_cast<FilterNodeWrapAndRecord*>(aNode)->mFinalFilterNode;
169   }
170 
SetInput(uint32_t aIndex,SourceSurface * aSurface)171   void SetInput(uint32_t aIndex, SourceSurface* aSurface) override {
172     EnsureSurfaceStored(mRecorder, aSurface, "SetInput");
173 
174     mRecorder->RecordEvent(RecordedFilterNodeSetInput(this, aIndex, aSurface));
175     mFinalFilterNode->SetInput(aIndex, GetSourceSurface(aSurface));
176   }
SetInput(uint32_t aIndex,FilterNode * aFilter)177   void SetInput(uint32_t aIndex, FilterNode* aFilter) override {
178     MOZ_ASSERT(mRecorder->HasStoredObject(aFilter));
179 
180     mRecorder->RecordEvent(RecordedFilterNodeSetInput(this, aIndex, aFilter));
181     mFinalFilterNode->SetInput(aIndex, GetFilterNode(aFilter));
182   }
183 
184 #define FORWARD_SET_ATTRIBUTE(type, argtype)                 \
185   void SetAttribute(uint32_t aIndex, type aValue) override { \
186     mRecorder->RecordEvent(RecordedFilterNodeSetAttribute(   \
187         this, aIndex, aValue,                                \
188         RecordedFilterNodeSetAttribute::ARGTYPE_##argtype)); \
189     mFinalFilterNode->SetAttribute(aIndex, aValue);          \
190   }
191 
192   FORWARD_SET_ATTRIBUTE(bool, BOOL);
193   FORWARD_SET_ATTRIBUTE(uint32_t, UINT32);
194   FORWARD_SET_ATTRIBUTE(Float, FLOAT);
195   FORWARD_SET_ATTRIBUTE(const Size&, SIZE);
196   FORWARD_SET_ATTRIBUTE(const IntSize&, INTSIZE);
197   FORWARD_SET_ATTRIBUTE(const IntPoint&, INTPOINT);
198   FORWARD_SET_ATTRIBUTE(const Rect&, RECT);
199   FORWARD_SET_ATTRIBUTE(const IntRect&, INTRECT);
200   FORWARD_SET_ATTRIBUTE(const Point&, POINT);
201   FORWARD_SET_ATTRIBUTE(const Matrix&, MATRIX);
202   FORWARD_SET_ATTRIBUTE(const Matrix5x4&, MATRIX5X4);
203   FORWARD_SET_ATTRIBUTE(const Point3D&, POINT3D);
204   FORWARD_SET_ATTRIBUTE(const DeviceColor&, COLOR);
205 
206 #undef FORWARD_SET_ATTRIBUTE
207 
SetAttribute(uint32_t aIndex,const Float * aFloat,uint32_t aSize)208   virtual void SetAttribute(uint32_t aIndex, const Float* aFloat,
209                             uint32_t aSize) override {
210     mRecorder->RecordEvent(
211         RecordedFilterNodeSetAttribute(this, aIndex, aFloat, aSize));
212     mFinalFilterNode->SetAttribute(aIndex, aFloat, aSize);
213   }
214 
GetBackendType()215   FilterBackend GetBackendType() override { return FILTER_BACKEND_RECORDING; }
216 
217   RefPtr<FilterNode> mFinalFilterNode;
218   RefPtr<DrawEventRecorderPrivate> mRecorder;
219 };
220 
221 struct AdjustedPattern final {
AdjustedPatternmozilla::gfx::AdjustedPattern222   explicit AdjustedPattern(const Pattern& aPattern) : mPattern(nullptr) {
223     mOrigPattern = const_cast<Pattern*>(&aPattern);
224   }
225 
~AdjustedPatternmozilla::gfx::AdjustedPattern226   ~AdjustedPattern() {
227     if (mPattern) {
228       mPattern->~Pattern();
229     }
230   }
231 
operator Pattern*mozilla::gfx::AdjustedPattern232   operator Pattern*() {
233     switch (mOrigPattern->GetType()) {
234       case PatternType::COLOR:
235         return mOrigPattern;
236       case PatternType::SURFACE: {
237         SurfacePattern* surfPat = static_cast<SurfacePattern*>(mOrigPattern);
238         mPattern = new (mSurfPat) SurfacePattern(
239             GetSourceSurface(surfPat->mSurface), surfPat->mExtendMode,
240             surfPat->mMatrix, surfPat->mSamplingFilter, surfPat->mSamplingRect);
241         return mPattern;
242       }
243       case PatternType::LINEAR_GRADIENT: {
244         LinearGradientPattern* linGradPat =
245             static_cast<LinearGradientPattern*>(mOrigPattern);
246         mPattern = new (mLinGradPat) LinearGradientPattern(
247             linGradPat->mBegin, linGradPat->mEnd,
248             GetGradientStops(linGradPat->mStops), linGradPat->mMatrix);
249         return mPattern;
250       }
251       case PatternType::RADIAL_GRADIENT: {
252         RadialGradientPattern* radGradPat =
253             static_cast<RadialGradientPattern*>(mOrigPattern);
254         mPattern = new (mRadGradPat) RadialGradientPattern(
255             radGradPat->mCenter1, radGradPat->mCenter2, radGradPat->mRadius1,
256             radGradPat->mRadius2, GetGradientStops(radGradPat->mStops),
257             radGradPat->mMatrix);
258         return mPattern;
259       }
260       case PatternType::CONIC_GRADIENT: {
261         ConicGradientPattern* conGradPat =
262             static_cast<ConicGradientPattern*>(mOrigPattern);
263         mPattern = new (mConGradPat) ConicGradientPattern(
264             conGradPat->mCenter, conGradPat->mAngle, conGradPat->mStartOffset,
265             conGradPat->mEndOffset, GetGradientStops(conGradPat->mStops),
266             conGradPat->mMatrix);
267         return mPattern;
268       }
269       default:
270         return new (mColPat) ColorPattern(DeviceColor());
271     }
272 
273     return mPattern;
274   }
275 
276   union {
277     char mColPat[sizeof(ColorPattern)];
278     char mLinGradPat[sizeof(LinearGradientPattern)];
279     char mRadGradPat[sizeof(RadialGradientPattern)];
280     char mConGradPat[sizeof(ConicGradientPattern)];
281     char mSurfPat[sizeof(SurfacePattern)];
282   };
283 
284   Pattern* mOrigPattern;
285   Pattern* mPattern;
286 };
287 
DrawTargetWrapAndRecord(DrawEventRecorder * aRecorder,DrawTarget * aDT,bool aHasData)288 DrawTargetWrapAndRecord::DrawTargetWrapAndRecord(DrawEventRecorder* aRecorder,
289                                                  DrawTarget* aDT, bool aHasData)
290     : mRecorder(static_cast<DrawEventRecorderPrivate*>(aRecorder)),
291       mFinalDT(aDT) {
292   RefPtr<SourceSurface> snapshot = aHasData ? mFinalDT->Snapshot() : nullptr;
293   mRecorder->RecordEvent(RecordedDrawTargetCreation(
294       this, mFinalDT->GetBackendType(), mFinalDT->GetRect(),
295       mFinalDT->GetFormat(), aHasData, snapshot));
296   mFormat = mFinalDT->GetFormat();
297 }
298 
DrawTargetWrapAndRecord(const DrawTargetWrapAndRecord * aDT,DrawTarget * aSimilarDT)299 DrawTargetWrapAndRecord::DrawTargetWrapAndRecord(
300     const DrawTargetWrapAndRecord* aDT, DrawTarget* aSimilarDT)
301     : mRecorder(aDT->mRecorder), mFinalDT(aSimilarDT) {
302   mRecorder->RecordEvent(RecordedCreateSimilarDrawTarget(
303       this, mFinalDT->GetSize(), mFinalDT->GetFormat()));
304   mFormat = mFinalDT->GetFormat();
305 }
306 
~DrawTargetWrapAndRecord()307 DrawTargetWrapAndRecord::~DrawTargetWrapAndRecord() {
308   mRecorder->RecordEvent(
309       RecordedDrawTargetDestruction(static_cast<DrawTarget*>(this)));
310 }
311 
FillRect(const Rect & aRect,const Pattern & aPattern,const DrawOptions & aOptions)312 void DrawTargetWrapAndRecord::FillRect(const Rect& aRect,
313                                        const Pattern& aPattern,
314                                        const DrawOptions& aOptions) {
315   EnsurePatternDependenciesStored(aPattern);
316 
317   mRecorder->RecordEvent(RecordedFillRect(this, aRect, aPattern, aOptions));
318   mFinalDT->FillRect(aRect, *AdjustedPattern(aPattern), aOptions);
319 }
320 
StrokeRect(const Rect & aRect,const Pattern & aPattern,const StrokeOptions & aStrokeOptions,const DrawOptions & aOptions)321 void DrawTargetWrapAndRecord::StrokeRect(const Rect& aRect,
322                                          const Pattern& aPattern,
323                                          const StrokeOptions& aStrokeOptions,
324                                          const DrawOptions& aOptions) {
325   EnsurePatternDependenciesStored(aPattern);
326 
327   mRecorder->RecordEvent(
328       RecordedStrokeRect(this, aRect, aPattern, aStrokeOptions, aOptions));
329   mFinalDT->StrokeRect(aRect, *AdjustedPattern(aPattern), aStrokeOptions,
330                        aOptions);
331 }
332 
StrokeLine(const Point & aBegin,const Point & aEnd,const Pattern & aPattern,const StrokeOptions & aStrokeOptions,const DrawOptions & aOptions)333 void DrawTargetWrapAndRecord::StrokeLine(const Point& aBegin, const Point& aEnd,
334                                          const Pattern& aPattern,
335                                          const StrokeOptions& aStrokeOptions,
336                                          const DrawOptions& aOptions) {
337   EnsurePatternDependenciesStored(aPattern);
338 
339   mRecorder->RecordEvent(RecordedStrokeLine(this, aBegin, aEnd, aPattern,
340                                             aStrokeOptions, aOptions));
341   mFinalDT->StrokeLine(aBegin, aEnd, *AdjustedPattern(aPattern), aStrokeOptions,
342                        aOptions);
343 }
344 
Fill(const Path * aPath,const Pattern & aPattern,const DrawOptions & aOptions)345 void DrawTargetWrapAndRecord::Fill(const Path* aPath, const Pattern& aPattern,
346                                    const DrawOptions& aOptions) {
347   RefPtr<PathRecording> pathWrapAndRecord = EnsurePathStored(aPath);
348   EnsurePatternDependenciesStored(aPattern);
349 
350   mRecorder->RecordEvent(
351       RecordedFill(this, pathWrapAndRecord, aPattern, aOptions));
352   mFinalDT->Fill(pathWrapAndRecord->mPath, *AdjustedPattern(aPattern),
353                  aOptions);
354 }
355 
356 struct WrapAndRecordFontUserData {
357   void* refPtr;
358   void* unscaledFont;
359   RefPtr<DrawEventRecorderPrivate> recorder;
360 };
361 
WrapAndRecordFontUserDataDestroyFunc(void * aUserData)362 static void WrapAndRecordFontUserDataDestroyFunc(void* aUserData) {
363   WrapAndRecordFontUserData* userData =
364       static_cast<WrapAndRecordFontUserData*>(aUserData);
365 
366   userData->recorder->RecordEvent(
367       RecordedScaledFontDestruction(ReferencePtr(userData->refPtr)));
368   userData->recorder->RemoveScaledFont((ScaledFont*)userData->refPtr);
369   userData->recorder->DecrementUnscaledFontRefCount(userData->unscaledFont);
370   delete userData;
371 }
372 
FillGlyphs(ScaledFont * aFont,const GlyphBuffer & aBuffer,const Pattern & aPattern,const DrawOptions & aOptions)373 void DrawTargetWrapAndRecord::FillGlyphs(ScaledFont* aFont,
374                                          const GlyphBuffer& aBuffer,
375                                          const Pattern& aPattern,
376                                          const DrawOptions& aOptions) {
377   EnsurePatternDependenciesStored(aPattern);
378 
379   UserDataKey* userDataKey = reinterpret_cast<UserDataKey*>(mRecorder.get());
380   if (!aFont->GetUserData(userDataKey)) {
381     UnscaledFont* unscaledFont = aFont->GetUnscaledFont();
382     if (mRecorder->IncrementUnscaledFontRefCount(unscaledFont) == 0) {
383       RecordedFontData fontData(unscaledFont);
384       RecordedFontDetails fontDetails;
385       if (fontData.GetFontDetails(fontDetails)) {
386         // Try to serialise the whole font, just in case this is a web font that
387         // is not present on the system.
388         if (!mRecorder->HasStoredFontData(fontDetails.fontDataKey)) {
389           mRecorder->RecordEvent(fontData);
390           mRecorder->AddStoredFontData(fontDetails.fontDataKey);
391         }
392         mRecorder->RecordEvent(
393             RecordedUnscaledFontCreation(unscaledFont, fontDetails));
394       } else {
395         // If that fails, record just the font description and try to load it
396         // from the system on the other side.
397         RecordedFontDescriptor fontDesc(unscaledFont);
398         if (fontDesc.IsValid()) {
399           mRecorder->RecordEvent(fontDesc);
400         } else {
401           gfxWarning() << "DrawTargetWrapAndRecord::FillGlyphs failed to "
402                           "serialise UnscaledFont";
403         }
404       }
405     }
406 
407     mRecorder->RecordEvent(RecordedScaledFontCreation(aFont, unscaledFont));
408 
409     WrapAndRecordFontUserData* userData = new WrapAndRecordFontUserData;
410     userData->refPtr = aFont;
411     userData->unscaledFont = unscaledFont;
412     userData->recorder = mRecorder;
413     aFont->AddUserData(userDataKey, userData,
414                        &WrapAndRecordFontUserDataDestroyFunc);
415     userData->recorder->AddScaledFont(aFont);
416   }
417 
418   mRecorder->RecordEvent(RecordedFillGlyphs(
419       this, aFont, aPattern, aOptions, aBuffer.mGlyphs, aBuffer.mNumGlyphs));
420   mFinalDT->FillGlyphs(aFont, aBuffer, *AdjustedPattern(aPattern), aOptions);
421 }
422 
Mask(const Pattern & aSource,const Pattern & aMask,const DrawOptions & aOptions)423 void DrawTargetWrapAndRecord::Mask(const Pattern& aSource, const Pattern& aMask,
424                                    const DrawOptions& aOptions) {
425   EnsurePatternDependenciesStored(aSource);
426   EnsurePatternDependenciesStored(aMask);
427 
428   mRecorder->RecordEvent(RecordedMask(this, aSource, aMask, aOptions));
429   mFinalDT->Mask(*AdjustedPattern(aSource), *AdjustedPattern(aMask), aOptions);
430 }
431 
MaskSurface(const Pattern & aSource,SourceSurface * aMask,Point aOffset,const DrawOptions & aOptions)432 void DrawTargetWrapAndRecord::MaskSurface(const Pattern& aSource,
433                                           SourceSurface* aMask, Point aOffset,
434                                           const DrawOptions& aOptions) {
435   EnsurePatternDependenciesStored(aSource);
436   EnsureSurfaceStored(mRecorder, aMask, "MaskSurface");
437 
438   mRecorder->RecordEvent(
439       RecordedMaskSurface(this, aSource, aMask, aOffset, aOptions));
440   mFinalDT->MaskSurface(*AdjustedPattern(aSource), GetSourceSurface(aMask),
441                         aOffset, aOptions);
442 }
443 
Stroke(const Path * aPath,const Pattern & aPattern,const StrokeOptions & aStrokeOptions,const DrawOptions & aOptions)444 void DrawTargetWrapAndRecord::Stroke(const Path* aPath, const Pattern& aPattern,
445                                      const StrokeOptions& aStrokeOptions,
446                                      const DrawOptions& aOptions) {
447   RefPtr<PathRecording> pathWrapAndRecord = EnsurePathStored(aPath);
448   EnsurePatternDependenciesStored(aPattern);
449 
450   mRecorder->RecordEvent(RecordedStroke(this, pathWrapAndRecord, aPattern,
451                                         aStrokeOptions, aOptions));
452   mFinalDT->Stroke(pathWrapAndRecord->mPath, *AdjustedPattern(aPattern),
453                    aStrokeOptions, aOptions);
454 }
455 
Snapshot()456 already_AddRefed<SourceSurface> DrawTargetWrapAndRecord::Snapshot() {
457   RefPtr<SourceSurface> surf = mFinalDT->Snapshot();
458 
459   RefPtr<SourceSurface> retSurf =
460       new SourceSurfaceWrapAndRecord(surf, mRecorder);
461 
462   mRecorder->RecordEvent(RecordedSnapshot(retSurf, this));
463 
464   return retSurf.forget();
465 }
466 
IntoLuminanceSource(LuminanceType aLuminanceType,float aOpacity)467 already_AddRefed<SourceSurface> DrawTargetWrapAndRecord::IntoLuminanceSource(
468     LuminanceType aLuminanceType, float aOpacity) {
469   RefPtr<SourceSurface> surf =
470       mFinalDT->IntoLuminanceSource(aLuminanceType, aOpacity);
471 
472   RefPtr<SourceSurface> retSurf =
473       new SourceSurfaceWrapAndRecord(surf, mRecorder);
474 
475   mRecorder->RecordEvent(
476       RecordedIntoLuminanceSource(retSurf, this, aLuminanceType, aOpacity));
477 
478   return retSurf.forget();
479 }
480 
DetachAllSnapshots()481 void DrawTargetWrapAndRecord::DetachAllSnapshots() {
482   mFinalDT->DetachAllSnapshots();
483 }
484 
DrawSurface(SourceSurface * aSurface,const Rect & aDest,const Rect & aSource,const DrawSurfaceOptions & aSurfOptions,const DrawOptions & aOptions)485 void DrawTargetWrapAndRecord::DrawSurface(
486     SourceSurface* aSurface, const Rect& aDest, const Rect& aSource,
487     const DrawSurfaceOptions& aSurfOptions, const DrawOptions& aOptions) {
488   EnsureSurfaceStored(mRecorder, aSurface, "DrawSurface");
489 
490   mRecorder->RecordEvent(RecordedDrawSurface(this, aSurface, aDest, aSource,
491                                              aSurfOptions, aOptions));
492   mFinalDT->DrawSurface(GetSourceSurface(aSurface), aDest, aSource,
493                         aSurfOptions, aOptions);
494 }
495 
DrawDependentSurface(uint64_t aId,const Rect & aDest,const DrawSurfaceOptions & aSurfOptions,const DrawOptions & aOptions)496 void DrawTargetWrapAndRecord::DrawDependentSurface(
497     uint64_t aId, const Rect& aDest, const DrawSurfaceOptions& aSurfOptions,
498     const DrawOptions& aOptions) {
499   mRecorder->AddDependentSurface(aId);
500   mRecorder->RecordEvent(
501       RecordedDrawDependentSurface(this, aId, aDest, aSurfOptions, aOptions));
502 }
503 
DrawSurfaceWithShadow(SourceSurface * aSurface,const Point & aDest,const DeviceColor & aColor,const Point & aOffset,Float aSigma,CompositionOp aOp)504 void DrawTargetWrapAndRecord::DrawSurfaceWithShadow(
505     SourceSurface* aSurface, const Point& aDest, const DeviceColor& aColor,
506     const Point& aOffset, Float aSigma, CompositionOp aOp) {
507   EnsureSurfaceStored(mRecorder, aSurface, "DrawSurfaceWithShadow");
508 
509   mRecorder->RecordEvent(RecordedDrawSurfaceWithShadow(
510       this, aSurface, aDest, aColor, aOffset, aSigma, aOp));
511   mFinalDT->DrawSurfaceWithShadow(GetSourceSurface(aSurface), aDest, aColor,
512                                   aOffset, aSigma, aOp);
513 }
514 
DrawFilter(FilterNode * aNode,const Rect & aSourceRect,const Point & aDestPoint,const DrawOptions & aOptions)515 void DrawTargetWrapAndRecord::DrawFilter(FilterNode* aNode,
516                                          const Rect& aSourceRect,
517                                          const Point& aDestPoint,
518                                          const DrawOptions& aOptions) {
519   MOZ_ASSERT(mRecorder->HasStoredObject(aNode));
520 
521   mRecorder->RecordEvent(
522       RecordedDrawFilter(this, aNode, aSourceRect, aDestPoint, aOptions));
523   mFinalDT->DrawFilter(FilterNodeWrapAndRecord::GetFilterNode(aNode),
524                        aSourceRect, aDestPoint, aOptions);
525 }
526 
CreateFilter(FilterType aType)527 already_AddRefed<FilterNode> DrawTargetWrapAndRecord::CreateFilter(
528     FilterType aType) {
529   RefPtr<FilterNode> node = mFinalDT->CreateFilter(aType);
530 
531   RefPtr<FilterNode> retNode = new FilterNodeWrapAndRecord(node, mRecorder);
532 
533   mRecorder->RecordEvent(RecordedFilterNodeCreation(retNode, aType));
534 
535   return retNode.forget();
536 }
537 
ClearRect(const Rect & aRect)538 void DrawTargetWrapAndRecord::ClearRect(const Rect& aRect) {
539   mRecorder->RecordEvent(RecordedClearRect(this, aRect));
540   mFinalDT->ClearRect(aRect);
541 }
542 
CopySurface(SourceSurface * aSurface,const IntRect & aSourceRect,const IntPoint & aDestination)543 void DrawTargetWrapAndRecord::CopySurface(SourceSurface* aSurface,
544                                           const IntRect& aSourceRect,
545                                           const IntPoint& aDestination) {
546   EnsureSurfaceStored(mRecorder, aSurface, "CopySurface");
547 
548   mRecorder->RecordEvent(
549       RecordedCopySurface(this, aSurface, aSourceRect, aDestination));
550   mFinalDT->CopySurface(GetSourceSurface(aSurface), aSourceRect, aDestination);
551 }
552 
PushClip(const Path * aPath)553 void DrawTargetWrapAndRecord::PushClip(const Path* aPath) {
554   RefPtr<PathRecording> pathWrapAndRecord = EnsurePathStored(aPath);
555 
556   mRecorder->RecordEvent(RecordedPushClip(this, pathWrapAndRecord));
557   mFinalDT->PushClip(pathWrapAndRecord->mPath);
558 }
559 
PushClipRect(const Rect & aRect)560 void DrawTargetWrapAndRecord::PushClipRect(const Rect& aRect) {
561   mRecorder->RecordEvent(RecordedPushClipRect(this, aRect));
562   mFinalDT->PushClipRect(aRect);
563 }
564 
PopClip()565 void DrawTargetWrapAndRecord::PopClip() {
566   mRecorder->RecordEvent(RecordedPopClip(static_cast<DrawTarget*>(this)));
567   mFinalDT->PopClip();
568 }
569 
PushLayer(bool aOpaque,Float aOpacity,SourceSurface * aMask,const Matrix & aMaskTransform,const IntRect & aBounds,bool aCopyBackground)570 void DrawTargetWrapAndRecord::PushLayer(bool aOpaque, Float aOpacity,
571                                         SourceSurface* aMask,
572                                         const Matrix& aMaskTransform,
573                                         const IntRect& aBounds,
574                                         bool aCopyBackground) {
575   if (aMask) {
576     EnsureSurfaceStored(mRecorder, aMask, "PushLayer");
577   }
578 
579   mRecorder->RecordEvent(RecordedPushLayer(this, aOpaque, aOpacity, aMask,
580                                            aMaskTransform, aBounds,
581                                            aCopyBackground));
582   mFinalDT->PushLayer(aOpaque, aOpacity, aMask, aMaskTransform, aBounds,
583                       aCopyBackground);
584 }
585 
PopLayer()586 void DrawTargetWrapAndRecord::PopLayer() {
587   mRecorder->RecordEvent(RecordedPopLayer(static_cast<DrawTarget*>(this)));
588   mFinalDT->PopLayer();
589 }
590 
591 already_AddRefed<SourceSurface>
CreateSourceSurfaceFromData(unsigned char * aData,const IntSize & aSize,int32_t aStride,SurfaceFormat aFormat) const592 DrawTargetWrapAndRecord::CreateSourceSurfaceFromData(
593     unsigned char* aData, const IntSize& aSize, int32_t aStride,
594     SurfaceFormat aFormat) const {
595   RefPtr<SourceSurface> surf =
596       mFinalDT->CreateSourceSurfaceFromData(aData, aSize, aStride, aFormat);
597 
598   RefPtr<SourceSurface> retSurf =
599       new SourceSurfaceWrapAndRecord(surf, mRecorder);
600 
601   mRecorder->RecordEvent(
602       RecordedSourceSurfaceCreation(retSurf, aData, aStride, aSize, aFormat));
603 
604   return retSurf.forget();
605 }
606 
OptimizeSourceSurface(SourceSurface * aSurface) const607 already_AddRefed<SourceSurface> DrawTargetWrapAndRecord::OptimizeSourceSurface(
608     SourceSurface* aSurface) const {
609   RefPtr<SourceSurface> surf = mFinalDT->OptimizeSourceSurface(aSurface);
610 
611   RefPtr<SourceSurface> retSurf =
612       new SourceSurfaceWrapAndRecord(surf, mRecorder);
613 
614   RefPtr<DataSourceSurface> dataSurf = surf->GetDataSurface();
615 
616   if (!dataSurf) {
617     // Let's try get it off the original surface.
618     dataSurf = aSurface->GetDataSurface();
619   }
620 
621   StoreSourceSurface(mRecorder, retSurf, dataSurf, "OptimizeSourceSurface");
622 
623   return retSurf.forget();
624 }
625 
626 already_AddRefed<SourceSurface>
CreateSourceSurfaceFromNativeSurface(const NativeSurface & aSurface) const627 DrawTargetWrapAndRecord::CreateSourceSurfaceFromNativeSurface(
628     const NativeSurface& aSurface) const {
629   RefPtr<SourceSurface> surf =
630       mFinalDT->CreateSourceSurfaceFromNativeSurface(aSurface);
631 
632   RefPtr<SourceSurface> retSurf =
633       new SourceSurfaceWrapAndRecord(surf, mRecorder);
634 
635   RefPtr<DataSourceSurface> dataSurf = surf->GetDataSurface();
636   StoreSourceSurface(mRecorder, retSurf, dataSurf,
637                      "CreateSourceSurfaceFromNativeSurface");
638 
639   return retSurf.forget();
640 }
641 
CreateSimilarDrawTarget(const IntSize & aSize,SurfaceFormat aFormat) const642 already_AddRefed<DrawTarget> DrawTargetWrapAndRecord::CreateSimilarDrawTarget(
643     const IntSize& aSize, SurfaceFormat aFormat) const {
644   RefPtr<DrawTarget> similarDT =
645       mFinalDT->CreateSimilarDrawTarget(aSize, aFormat);
646   if (!similarDT) {
647     return nullptr;
648   }
649 
650   similarDT = new DrawTargetWrapAndRecord(this, similarDT);
651   return similarDT.forget();
652 }
653 
CanCreateSimilarDrawTarget(const IntSize & aSize,SurfaceFormat aFormat) const654 bool DrawTargetWrapAndRecord::CanCreateSimilarDrawTarget(
655     const IntSize& aSize, SurfaceFormat aFormat) const {
656   return mFinalDT->CanCreateSimilarDrawTarget(aSize, aFormat);
657 }
658 
CreateClippedDrawTarget(const Rect & aBounds,SurfaceFormat aFormat)659 RefPtr<DrawTarget> DrawTargetWrapAndRecord::CreateClippedDrawTarget(
660     const Rect& aBounds, SurfaceFormat aFormat) {
661   RefPtr<DrawTarget> similarDT;
662   RefPtr<DrawTarget> innerDT =
663       mFinalDT->CreateClippedDrawTarget(aBounds, aFormat);
664   similarDT = new DrawTargetWrapAndRecord(this->mRecorder, innerDT);
665   mRecorder->RecordEvent(
666       RecordedCreateClippedDrawTarget(this, similarDT.get(), aBounds, aFormat));
667   similarDT->SetTransform(mTransform);
668   return similarDT;
669 }
670 
CreatePathBuilder(FillRule aFillRule) const671 already_AddRefed<PathBuilder> DrawTargetWrapAndRecord::CreatePathBuilder(
672     FillRule aFillRule) const {
673   RefPtr<PathBuilder> builder = mFinalDT->CreatePathBuilder(aFillRule);
674   return MakeAndAddRef<PathBuilderRecording>(builder, aFillRule);
675 }
676 
CreateGradientStops(GradientStop * aStops,uint32_t aNumStops,ExtendMode aExtendMode) const677 already_AddRefed<GradientStops> DrawTargetWrapAndRecord::CreateGradientStops(
678     GradientStop* aStops, uint32_t aNumStops, ExtendMode aExtendMode) const {
679   RefPtr<GradientStops> stops =
680       mFinalDT->CreateGradientStops(aStops, aNumStops, aExtendMode);
681 
682   RefPtr<GradientStops> retStops =
683       new GradientStopsWrapAndRecord(stops, mRecorder);
684 
685   mRecorder->RecordEvent(
686       RecordedGradientStopsCreation(retStops, aStops, aNumStops, aExtendMode));
687 
688   return retStops.forget();
689 }
690 
SetTransform(const Matrix & aTransform)691 void DrawTargetWrapAndRecord::SetTransform(const Matrix& aTransform) {
692   mRecorder->RecordEvent(RecordedSetTransform(this, aTransform));
693   DrawTarget::SetTransform(aTransform);
694   mFinalDT->SetTransform(aTransform);
695 }
696 
EnsurePathStored(const Path * aPath)697 already_AddRefed<PathRecording> DrawTargetWrapAndRecord::EnsurePathStored(
698     const Path* aPath) {
699   RefPtr<PathRecording> pathWrapAndRecord;
700   if (aPath->GetBackendType() == BackendType::RECORDING) {
701     pathWrapAndRecord =
702         const_cast<PathRecording*>(static_cast<const PathRecording*>(aPath));
703     if (mRecorder->HasStoredObject(aPath)) {
704       return pathWrapAndRecord.forget();
705     }
706   } else {
707     MOZ_ASSERT(!mRecorder->HasStoredObject(aPath));
708     FillRule fillRule = aPath->GetFillRule();
709     RefPtr<PathBuilder> builder = mFinalDT->CreatePathBuilder(fillRule);
710     RefPtr<PathBuilderRecording> builderWrapAndRecord =
711         new PathBuilderRecording(builder, fillRule);
712     aPath->StreamToSink(builderWrapAndRecord);
713     pathWrapAndRecord =
714         builderWrapAndRecord->Finish().downcast<PathRecording>();
715   }
716 
717   mRecorder->RecordEvent(RecordedPathCreation(pathWrapAndRecord.get()));
718   mRecorder->AddStoredObject(pathWrapAndRecord);
719   pathWrapAndRecord->mStoredRecorders.push_back(mRecorder);
720 
721   return pathWrapAndRecord.forget();
722 }
723 
EnsurePatternDependenciesStored(const Pattern & aPattern)724 void DrawTargetWrapAndRecord::EnsurePatternDependenciesStored(
725     const Pattern& aPattern) {
726   switch (aPattern.GetType()) {
727     case PatternType::COLOR:
728       // No dependencies here.
729       return;
730     case PatternType::LINEAR_GRADIENT: {
731       MOZ_ASSERT(mRecorder->HasStoredObject(
732           static_cast<const LinearGradientPattern*>(&aPattern)->mStops));
733       return;
734     }
735     case PatternType::RADIAL_GRADIENT: {
736       MOZ_ASSERT(mRecorder->HasStoredObject(
737           static_cast<const RadialGradientPattern*>(&aPattern)->mStops));
738       return;
739     }
740     case PatternType::CONIC_GRADIENT: {
741       MOZ_ASSERT(mRecorder->HasStoredObject(
742           static_cast<const ConicGradientPattern*>(&aPattern)->mStops));
743       return;
744     }
745     case PatternType::SURFACE: {
746       const SurfacePattern* pat = static_cast<const SurfacePattern*>(&aPattern);
747       EnsureSurfaceStored(mRecorder, pat->mSurface,
748                           "EnsurePatternDependenciesStored");
749       return;
750     }
751   }
752 }
753 
754 }  // namespace gfx
755 }  // namespace mozilla
756