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 "DrawTargetRecording.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 RecordingSourceSurfaceUserData {
22   void *refPtr;
23   RefPtr<DrawEventRecorderPrivate> recorder;
24 };
25 
RecordingSourceSurfaceUserDataFunc(void * aUserData)26 void RecordingSourceSurfaceUserDataFunc(void *aUserData) {
27   RecordingSourceSurfaceUserData *userData =
28       static_cast<RecordingSourceSurfaceUserData *>(aUserData);
29 
30   userData->recorder->RemoveSourceSurface((SourceSurface *)userData->refPtr);
31   userData->recorder->RemoveStoredObject(userData->refPtr);
32   userData->recorder->RecordEvent(
33       RecordedSourceSurfaceDestruction(ReferencePtr(userData->refPtr)));
34 
35   delete userData;
36 }
37 
StoreSourceSurfaceRecording(DrawEventRecorderPrivate * aRecorder,SourceSurface * aSurface,DataSourceSurface * aDataSurf,const char * reason)38 static void StoreSourceSurfaceRecording(DrawEventRecorderPrivate *aRecorder,
39                                         SourceSurface *aSurface,
40                                         DataSourceSurface *aDataSurf,
41                                         const char *reason) {
42   if (!aDataSurf) {
43     gfxWarning() << "Recording failed to record SourceSurface for " << reason;
44     // Insert a bogus source surface.
45     int32_t stride =
46         aSurface->GetSize().width * BytesPerPixel(aSurface->GetFormat());
47     UniquePtr<uint8_t[]> sourceData(
48         new uint8_t[stride * aSurface->GetSize().height]());
49     aRecorder->RecordEvent(RecordedSourceSurfaceCreation(
50         aSurface, sourceData.get(), stride, aSurface->GetSize(),
51         aSurface->GetFormat()));
52   } else {
53     DataSourceSurface::ScopedMap map(aDataSurf, DataSourceSurface::READ);
54     aRecorder->RecordEvent(RecordedSourceSurfaceCreation(
55         aSurface, map.GetData(), map.GetStride(), aDataSurf->GetSize(),
56         aDataSurf->GetFormat()));
57   }
58 }
59 
EnsureSurfaceStoredRecording(DrawEventRecorderPrivate * aRecorder,SourceSurface * aSurface,const char * reason)60 static void EnsureSurfaceStoredRecording(DrawEventRecorderPrivate *aRecorder,
61                                          SourceSurface *aSurface,
62                                          const char *reason) {
63   if (aRecorder->HasStoredObject(aSurface)) {
64     return;
65   }
66 
67   RefPtr<DataSourceSurface> dataSurf = aSurface->GetDataSurface();
68   StoreSourceSurfaceRecording(aRecorder, aSurface, dataSurf, reason);
69   aRecorder->AddStoredObject(aSurface);
70   aRecorder->AddSourceSurface(aSurface);
71 
72   RecordingSourceSurfaceUserData *userData = new RecordingSourceSurfaceUserData;
73   userData->refPtr = aSurface;
74   userData->recorder = aRecorder;
75   aSurface->AddUserData(reinterpret_cast<UserDataKey *>(aRecorder), userData,
76                         &RecordingSourceSurfaceUserDataFunc);
77 }
78 
79 class SourceSurfaceRecording : public SourceSurface {
80  public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceRecording,override)81   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceRecording, override)
82 
83   SourceSurfaceRecording(IntSize aSize, SurfaceFormat aFormat,
84                          DrawEventRecorderPrivate *aRecorder)
85       : mSize(aSize), mFormat(aFormat), mRecorder(aRecorder) {
86     mRecorder->AddStoredObject(this);
87   }
88 
~SourceSurfaceRecording()89   ~SourceSurfaceRecording() {
90     mRecorder->RemoveStoredObject(this);
91     mRecorder->RecordEvent(
92         RecordedSourceSurfaceDestruction(ReferencePtr(this)));
93   }
94 
GetType() const95   virtual SurfaceType GetType() const override {
96     return SurfaceType::RECORDING;
97   }
GetSize() const98   virtual IntSize GetSize() const override { return mSize; }
GetFormat() const99   virtual SurfaceFormat GetFormat() const override { return mFormat; }
GetDataSurface()100   virtual already_AddRefed<DataSourceSurface> GetDataSurface() override {
101     return nullptr;
102   }
103 
104   IntSize mSize;
105   SurfaceFormat mFormat;
106   RefPtr<DrawEventRecorderPrivate> mRecorder;
107 };
108 
109 class DataSourceSurfaceRecording : public DataSourceSurface {
110  public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceRecording,override)111   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceRecording, override)
112   DataSourceSurfaceRecording(UniquePtr<uint8_t[]> aData, IntSize aSize,
113                              int32_t aStride, SurfaceFormat aFormat)
114       : mData(Move(aData)), mSize(aSize), mStride(aStride), mFormat(aFormat) {}
115 
~DataSourceSurfaceRecording()116   ~DataSourceSurfaceRecording() {}
117 
Init(uint8_t * aData,IntSize aSize,int32_t aStride,SurfaceFormat aFormat)118   static already_AddRefed<DataSourceSurface> Init(uint8_t *aData, IntSize aSize,
119                                                   int32_t aStride,
120                                                   SurfaceFormat aFormat) {
121     // XXX: do we need to ensure any alignment here?
122     auto data = MakeUnique<uint8_t[]>(aStride * aSize.height);
123     if (data) {
124       memcpy(data.get(), aData, aStride * aSize.height);
125       RefPtr<DataSourceSurfaceRecording> surf =
126           new DataSourceSurfaceRecording(Move(data), aSize, aStride, aFormat);
127       return surf.forget();
128     }
129     return nullptr;
130   }
131 
GetType() const132   virtual SurfaceType GetType() const override {
133     return SurfaceType::RECORDING;
134   }
GetSize() const135   virtual IntSize GetSize() const override { return mSize; }
Stride()136   virtual int32_t Stride() override { return mStride; }
GetFormat() const137   virtual SurfaceFormat GetFormat() const override { return mFormat; }
GetData()138   virtual uint8_t *GetData() override { return mData.get(); }
139 
140   UniquePtr<uint8_t[]> mData;
141   IntSize mSize;
142   int32_t mStride;
143   SurfaceFormat mFormat;
144 };
145 
146 class GradientStopsRecording : public GradientStops {
147  public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStopsRecording,override)148   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStopsRecording, override)
149 
150   explicit GradientStopsRecording(DrawEventRecorderPrivate *aRecorder)
151       : mRecorder(aRecorder) {
152     mRecorder->AddStoredObject(this);
153   }
154 
~GradientStopsRecording()155   ~GradientStopsRecording() {
156     mRecorder->RemoveStoredObject(this);
157     mRecorder->RecordEvent(
158         RecordedGradientStopsDestruction(ReferencePtr(this)));
159   }
160 
GetBackendType() const161   virtual BackendType GetBackendType() const override {
162     return BackendType::RECORDING;
163   }
164 
165   RefPtr<DrawEventRecorderPrivate> mRecorder;
166 };
167 
168 class FilterNodeRecording : public FilterNode {
169  public:
170   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeRecording, override)
171   using FilterNode::SetAttribute;
172 
FilterNodeRecording(DrawEventRecorderPrivate * aRecorder)173   explicit FilterNodeRecording(DrawEventRecorderPrivate *aRecorder)
174       : mRecorder(aRecorder) {
175     mRecorder->AddStoredObject(this);
176   }
177 
~FilterNodeRecording()178   ~FilterNodeRecording() {
179     mRecorder->RemoveStoredObject(this);
180     mRecorder->RecordEvent(RecordedFilterNodeDestruction(ReferencePtr(this)));
181   }
182 
SetInput(uint32_t aIndex,SourceSurface * aSurface)183   virtual void SetInput(uint32_t aIndex, SourceSurface *aSurface) override {
184     EnsureSurfaceStoredRecording(mRecorder, aSurface, "SetInput");
185 
186     mRecorder->RecordEvent(RecordedFilterNodeSetInput(this, aIndex, aSurface));
187   }
SetInput(uint32_t aIndex,FilterNode * aFilter)188   virtual void SetInput(uint32_t aIndex, FilterNode *aFilter) override {
189     MOZ_ASSERT(mRecorder->HasStoredObject(aFilter));
190 
191     mRecorder->RecordEvent(RecordedFilterNodeSetInput(this, aIndex, aFilter));
192   }
193 
194 #define FORWARD_SET_ATTRIBUTE(type, argtype)                         \
195   virtual void SetAttribute(uint32_t aIndex, type aValue) override { \
196     mRecorder->RecordEvent(RecordedFilterNodeSetAttribute(           \
197         this, aIndex, aValue,                                        \
198         RecordedFilterNodeSetAttribute::ARGTYPE_##argtype));         \
199   }
200 
201   FORWARD_SET_ATTRIBUTE(bool, BOOL);
202   FORWARD_SET_ATTRIBUTE(uint32_t, UINT32);
203   FORWARD_SET_ATTRIBUTE(Float, FLOAT);
204   FORWARD_SET_ATTRIBUTE(const Size &, SIZE);
205   FORWARD_SET_ATTRIBUTE(const IntSize &, INTSIZE);
206   FORWARD_SET_ATTRIBUTE(const IntPoint &, INTPOINT);
207   FORWARD_SET_ATTRIBUTE(const Rect &, RECT);
208   FORWARD_SET_ATTRIBUTE(const IntRect &, INTRECT);
209   FORWARD_SET_ATTRIBUTE(const Point &, POINT);
210   FORWARD_SET_ATTRIBUTE(const Matrix &, MATRIX);
211   FORWARD_SET_ATTRIBUTE(const Matrix5x4 &, MATRIX5X4);
212   FORWARD_SET_ATTRIBUTE(const Point3D &, POINT3D);
213   FORWARD_SET_ATTRIBUTE(const Color &, COLOR);
214 
215 #undef FORWARD_SET_ATTRIBUTE
216 
SetAttribute(uint32_t aIndex,const Float * aFloat,uint32_t aSize)217   virtual void SetAttribute(uint32_t aIndex, const Float *aFloat,
218                             uint32_t aSize) override {
219     mRecorder->RecordEvent(
220         RecordedFilterNodeSetAttribute(this, aIndex, aFloat, aSize));
221   }
222 
GetBackendType()223   virtual FilterBackend GetBackendType() override {
224     return FILTER_BACKEND_RECORDING;
225   }
226 
227   RefPtr<DrawEventRecorderPrivate> mRecorder;
228 };
229 
DrawTargetRecording(DrawEventRecorder * aRecorder,DrawTarget * aDT,IntSize aSize,bool aHasData)230 DrawTargetRecording::DrawTargetRecording(DrawEventRecorder *aRecorder,
231                                          DrawTarget *aDT, IntSize aSize,
232                                          bool aHasData)
233     : mRecorder(static_cast<DrawEventRecorderPrivate *>(aRecorder)),
234       mFinalDT(aDT),
235       mSize(aSize) {
236   RefPtr<SourceSurface> snapshot = aHasData ? mFinalDT->Snapshot() : nullptr;
237   mRecorder->RecordEvent(
238       RecordedDrawTargetCreation(this, mFinalDT->GetBackendType(), mSize,
239                                  mFinalDT->GetFormat(), aHasData, snapshot));
240   mFormat = mFinalDT->GetFormat();
241 }
242 
DrawTargetRecording(const DrawTargetRecording * aDT,IntSize aSize,SurfaceFormat aFormat)243 DrawTargetRecording::DrawTargetRecording(const DrawTargetRecording *aDT,
244                                          IntSize aSize, SurfaceFormat aFormat)
245     : mRecorder(aDT->mRecorder), mFinalDT(aDT->mFinalDT), mSize(aSize) {
246   mFormat = aFormat;
247 }
248 
~DrawTargetRecording()249 DrawTargetRecording::~DrawTargetRecording() {
250   mRecorder->RecordEvent(RecordedDrawTargetDestruction(ReferencePtr(this)));
251 }
252 
FillRect(const Rect & aRect,const Pattern & aPattern,const DrawOptions & aOptions)253 void DrawTargetRecording::FillRect(const Rect &aRect, const Pattern &aPattern,
254                                    const DrawOptions &aOptions) {
255   EnsurePatternDependenciesStored(aPattern);
256 
257   mRecorder->RecordEvent(RecordedFillRect(this, aRect, aPattern, aOptions));
258 }
259 
StrokeRect(const Rect & aRect,const Pattern & aPattern,const StrokeOptions & aStrokeOptions,const DrawOptions & aOptions)260 void DrawTargetRecording::StrokeRect(const Rect &aRect, const Pattern &aPattern,
261                                      const StrokeOptions &aStrokeOptions,
262                                      const DrawOptions &aOptions) {
263   EnsurePatternDependenciesStored(aPattern);
264 
265   mRecorder->RecordEvent(
266       RecordedStrokeRect(this, aRect, aPattern, aStrokeOptions, aOptions));
267 }
268 
StrokeLine(const Point & aBegin,const Point & aEnd,const Pattern & aPattern,const StrokeOptions & aStrokeOptions,const DrawOptions & aOptions)269 void DrawTargetRecording::StrokeLine(const Point &aBegin, const Point &aEnd,
270                                      const Pattern &aPattern,
271                                      const StrokeOptions &aStrokeOptions,
272                                      const DrawOptions &aOptions) {
273   EnsurePatternDependenciesStored(aPattern);
274 
275   mRecorder->RecordEvent(RecordedStrokeLine(this, aBegin, aEnd, aPattern,
276                                             aStrokeOptions, aOptions));
277 }
278 
Fill(const Path * aPath,const Pattern & aPattern,const DrawOptions & aOptions)279 void DrawTargetRecording::Fill(const Path *aPath, const Pattern &aPattern,
280                                const DrawOptions &aOptions) {
281   RefPtr<PathRecording> pathRecording = EnsurePathStored(aPath);
282   EnsurePatternDependenciesStored(aPattern);
283 
284   mRecorder->RecordEvent(RecordedFill(this, pathRecording, aPattern, aOptions));
285 }
286 
287 struct RecordingFontUserData {
288   void *refPtr;
289   RefPtr<DrawEventRecorderPrivate> recorder;
290 };
291 
RecordingFontUserDataDestroyFunc(void * aUserData)292 void RecordingFontUserDataDestroyFunc(void *aUserData) {
293   RecordingFontUserData *userData =
294       static_cast<RecordingFontUserData *>(aUserData);
295 
296   userData->recorder->RecordEvent(
297       RecordedScaledFontDestruction(ReferencePtr(userData->refPtr)));
298   userData->recorder->RemoveScaledFont((ScaledFont *)userData->refPtr);
299   delete userData;
300 }
301 
FillGlyphs(ScaledFont * aFont,const GlyphBuffer & aBuffer,const Pattern & aPattern,const DrawOptions & aOptions)302 void DrawTargetRecording::FillGlyphs(ScaledFont *aFont,
303                                      const GlyphBuffer &aBuffer,
304                                      const Pattern &aPattern,
305                                      const DrawOptions &aOptions) {
306   EnsurePatternDependenciesStored(aPattern);
307 
308   UserDataKey *userDataKey = reinterpret_cast<UserDataKey *>(mRecorder.get());
309   if (!aFont->GetUserData(userDataKey)) {
310     UnscaledFont *unscaledFont = aFont->GetUnscaledFont();
311     if (mRecorder->WantsExternalFonts()) {
312       size_t index = mRecorder->GetUnscaledFontIndex(unscaledFont);
313       mRecorder->RecordEvent(RecordedScaledFontCreationByIndex(aFont, index));
314     } else {
315       if (!mRecorder->HasStoredObject(unscaledFont)) {
316         RecordedFontData fontData(unscaledFont);
317         RecordedFontDetails fontDetails;
318         if (fontData.GetFontDetails(fontDetails)) {
319           // Try to serialise the whole font, just in case this is a web font
320           // that is not present on the system.
321           if (!mRecorder->HasStoredFontData(fontDetails.fontDataKey)) {
322             mRecorder->RecordEvent(fontData);
323             mRecorder->AddStoredFontData(fontDetails.fontDataKey);
324           }
325           mRecorder->RecordEvent(
326               RecordedUnscaledFontCreation(unscaledFont, fontDetails));
327         } else {
328           // If that fails, record just the font description and try to load it
329           // from the system on the other side.
330           RecordedFontDescriptor fontDesc(unscaledFont);
331           if (fontDesc.IsValid()) {
332             mRecorder->RecordEvent(fontDesc);
333           } else {
334             gfxWarning() << "DrawTargetRecording::FillGlyphs failed to "
335                             "serialise UnscaledFont";
336           }
337         }
338         mRecorder->AddStoredObject(unscaledFont);
339       }
340       mRecorder->RecordEvent(RecordedScaledFontCreation(aFont, unscaledFont));
341     }
342     RecordingFontUserData *userData = new RecordingFontUserData;
343     userData->refPtr = aFont;
344     userData->recorder = mRecorder;
345     aFont->AddUserData(userDataKey, userData,
346                        &RecordingFontUserDataDestroyFunc);
347     userData->recorder->AddScaledFont(aFont);
348   }
349 
350   mRecorder->RecordEvent(RecordedFillGlyphs(
351       this, aFont, aPattern, aOptions, aBuffer.mGlyphs, aBuffer.mNumGlyphs));
352 }
353 
Mask(const Pattern & aSource,const Pattern & aMask,const DrawOptions & aOptions)354 void DrawTargetRecording::Mask(const Pattern &aSource, const Pattern &aMask,
355                                const DrawOptions &aOptions) {
356   EnsurePatternDependenciesStored(aSource);
357   EnsurePatternDependenciesStored(aMask);
358 
359   mRecorder->RecordEvent(RecordedMask(this, aSource, aMask, aOptions));
360 }
361 
MaskSurface(const Pattern & aSource,SourceSurface * aMask,Point aOffset,const DrawOptions & aOptions)362 void DrawTargetRecording::MaskSurface(const Pattern &aSource,
363                                       SourceSurface *aMask, Point aOffset,
364                                       const DrawOptions &aOptions) {
365   EnsurePatternDependenciesStored(aSource);
366   EnsureSurfaceStoredRecording(mRecorder, aMask, "MaskSurface");
367 
368   mRecorder->RecordEvent(
369       RecordedMaskSurface(this, aSource, aMask, aOffset, aOptions));
370 }
371 
Stroke(const Path * aPath,const Pattern & aPattern,const StrokeOptions & aStrokeOptions,const DrawOptions & aOptions)372 void DrawTargetRecording::Stroke(const Path *aPath, const Pattern &aPattern,
373                                  const StrokeOptions &aStrokeOptions,
374                                  const DrawOptions &aOptions) {
375   RefPtr<PathRecording> pathRecording = EnsurePathStored(aPath);
376   EnsurePatternDependenciesStored(aPattern);
377 
378   mRecorder->RecordEvent(
379       RecordedStroke(this, pathRecording, aPattern, aStrokeOptions, aOptions));
380 }
381 
Snapshot()382 already_AddRefed<SourceSurface> DrawTargetRecording::Snapshot() {
383   RefPtr<SourceSurface> retSurf =
384       new SourceSurfaceRecording(mSize, mFormat, mRecorder);
385 
386   mRecorder->RecordEvent(RecordedSnapshot(retSurf, this));
387 
388   return retSurf.forget();
389 }
390 
IntoLuminanceSource(LuminanceType aLuminanceType,float aOpacity)391 already_AddRefed<SourceSurface> DrawTargetRecording::IntoLuminanceSource(
392     LuminanceType aLuminanceType, float aOpacity) {
393   RefPtr<SourceSurface> retSurf =
394       new SourceSurfaceRecording(mSize, SurfaceFormat::A8, mRecorder);
395 
396   mRecorder->RecordEvent(
397       RecordedIntoLuminanceSource(retSurf, this, aLuminanceType, aOpacity));
398 
399   return retSurf.forget();
400 }
401 
DetachAllSnapshots()402 void DrawTargetRecording::DetachAllSnapshots() {}
403 
DrawSurface(SourceSurface * aSurface,const Rect & aDest,const Rect & aSource,const DrawSurfaceOptions & aSurfOptions,const DrawOptions & aOptions)404 void DrawTargetRecording::DrawSurface(SourceSurface *aSurface,
405                                       const Rect &aDest, const Rect &aSource,
406                                       const DrawSurfaceOptions &aSurfOptions,
407                                       const DrawOptions &aOptions) {
408   EnsureSurfaceStoredRecording(mRecorder, aSurface, "DrawSurface");
409 
410   mRecorder->RecordEvent(RecordedDrawSurface(this, aSurface, aDest, aSource,
411                                              aSurfOptions, aOptions));
412 }
413 
DrawSurfaceWithShadow(SourceSurface * aSurface,const Point & aDest,const Color & aColor,const Point & aOffset,Float aSigma,CompositionOp aOp)414 void DrawTargetRecording::DrawSurfaceWithShadow(
415     SourceSurface *aSurface, const Point &aDest, const Color &aColor,
416     const Point &aOffset, Float aSigma, CompositionOp aOp) {
417   EnsureSurfaceStoredRecording(mRecorder, aSurface, "DrawSurfaceWithShadow");
418 
419   mRecorder->RecordEvent(RecordedDrawSurfaceWithShadow(
420       this, aSurface, aDest, aColor, aOffset, aSigma, aOp));
421 }
422 
DrawFilter(FilterNode * aNode,const Rect & aSourceRect,const Point & aDestPoint,const DrawOptions & aOptions)423 void DrawTargetRecording::DrawFilter(FilterNode *aNode, const Rect &aSourceRect,
424                                      const Point &aDestPoint,
425                                      const DrawOptions &aOptions) {
426   MOZ_ASSERT(mRecorder->HasStoredObject(aNode));
427 
428   mRecorder->RecordEvent(
429       RecordedDrawFilter(this, aNode, aSourceRect, aDestPoint, aOptions));
430 }
431 
CreateFilter(FilterType aType)432 already_AddRefed<FilterNode> DrawTargetRecording::CreateFilter(
433     FilterType aType) {
434   RefPtr<FilterNode> retNode = new FilterNodeRecording(mRecorder);
435 
436   mRecorder->RecordEvent(RecordedFilterNodeCreation(retNode, aType));
437 
438   return retNode.forget();
439 }
440 
ClearRect(const Rect & aRect)441 void DrawTargetRecording::ClearRect(const Rect &aRect) {
442   mRecorder->RecordEvent(RecordedClearRect(this, aRect));
443 }
444 
CopySurface(SourceSurface * aSurface,const IntRect & aSourceRect,const IntPoint & aDestination)445 void DrawTargetRecording::CopySurface(SourceSurface *aSurface,
446                                       const IntRect &aSourceRect,
447                                       const IntPoint &aDestination) {
448   EnsureSurfaceStoredRecording(mRecorder, aSurface, "CopySurface");
449 
450   mRecorder->RecordEvent(
451       RecordedCopySurface(this, aSurface, aSourceRect, aDestination));
452 }
453 
PushClip(const Path * aPath)454 void DrawTargetRecording::PushClip(const Path *aPath) {
455   RefPtr<PathRecording> pathRecording = EnsurePathStored(aPath);
456 
457   mRecorder->RecordEvent(RecordedPushClip(this, pathRecording));
458 }
459 
PushClipRect(const Rect & aRect)460 void DrawTargetRecording::PushClipRect(const Rect &aRect) {
461   mRecorder->RecordEvent(RecordedPushClipRect(this, aRect));
462 }
463 
PopClip()464 void DrawTargetRecording::PopClip() {
465   mRecorder->RecordEvent(RecordedPopClip(static_cast<DrawTarget *>(this)));
466 }
467 
PushLayer(bool aOpaque,Float aOpacity,SourceSurface * aMask,const Matrix & aMaskTransform,const IntRect & aBounds,bool aCopyBackground)468 void DrawTargetRecording::PushLayer(bool aOpaque, Float aOpacity,
469                                     SourceSurface *aMask,
470                                     const Matrix &aMaskTransform,
471                                     const IntRect &aBounds,
472                                     bool aCopyBackground) {
473   if (aMask) {
474     EnsureSurfaceStoredRecording(mRecorder, aMask, "PushLayer");
475   }
476 
477   mRecorder->RecordEvent(RecordedPushLayer(this, aOpaque, aOpacity, aMask,
478                                            aMaskTransform, aBounds,
479                                            aCopyBackground));
480 }
481 
PushLayerWithBlend(bool aOpaque,Float aOpacity,SourceSurface * aMask,const Matrix & aMaskTransform,const IntRect & aBounds,bool aCopyBackground,CompositionOp aCompositionOp)482 void DrawTargetRecording::PushLayerWithBlend(bool aOpaque, Float aOpacity,
483                                              SourceSurface *aMask,
484                                              const Matrix &aMaskTransform,
485                                              const IntRect &aBounds,
486                                              bool aCopyBackground,
487                                              CompositionOp aCompositionOp) {
488   if (aMask) {
489     EnsureSurfaceStoredRecording(mRecorder, aMask, "PushLayer");
490   }
491 
492   mRecorder->RecordEvent(
493       RecordedPushLayerWithBlend(this, aOpaque, aOpacity, aMask, aMaskTransform,
494                                  aBounds, aCopyBackground, aCompositionOp));
495 }
496 
PopLayer()497 void DrawTargetRecording::PopLayer() {
498   mRecorder->RecordEvent(RecordedPopLayer(static_cast<DrawTarget *>(this)));
499 }
500 
501 already_AddRefed<SourceSurface>
CreateSourceSurfaceFromData(unsigned char * aData,const IntSize & aSize,int32_t aStride,SurfaceFormat aFormat) const502 DrawTargetRecording::CreateSourceSurfaceFromData(unsigned char *aData,
503                                                  const IntSize &aSize,
504                                                  int32_t aStride,
505                                                  SurfaceFormat aFormat) const {
506   RefPtr<SourceSurface> surf =
507       DataSourceSurfaceRecording::Init(aData, aSize, aStride, aFormat);
508 
509   RefPtr<SourceSurface> retSurf =
510       new SourceSurfaceRecording(aSize, aFormat, mRecorder);
511 
512   mRecorder->RecordEvent(
513       RecordedSourceSurfaceCreation(retSurf, aData, aStride, aSize, aFormat));
514 
515   return retSurf.forget();
516 }
517 
OptimizeSourceSurface(SourceSurface * aSurface) const518 already_AddRefed<SourceSurface> DrawTargetRecording::OptimizeSourceSurface(
519     SourceSurface *aSurface) const {
520   RefPtr<SourceSurface> surf(aSurface);
521   return surf.forget();
522 }
523 
524 already_AddRefed<SourceSurface>
CreateSourceSurfaceFromNativeSurface(const NativeSurface & aSurface) const525 DrawTargetRecording::CreateSourceSurfaceFromNativeSurface(
526     const NativeSurface &aSurface) const {
527   MOZ_ASSERT(false);
528   return nullptr;
529 }
530 
CreateSimilarDrawTarget(const IntSize & aSize,SurfaceFormat aFormat) const531 already_AddRefed<DrawTarget> DrawTargetRecording::CreateSimilarDrawTarget(
532     const IntSize &aSize, SurfaceFormat aFormat) const {
533   RefPtr<DrawTarget> similarDT = new DrawTargetRecording(this, aSize, aFormat);
534   mRecorder->RecordEvent(
535       RecordedCreateSimilarDrawTarget(similarDT.get(), aSize, aFormat));
536   return similarDT.forget();
537 }
538 
CreateClippedDrawTarget(const IntSize & aMaxSize,const Matrix & aTransform,SurfaceFormat aFormat) const539 RefPtr<DrawTarget> DrawTargetRecording::CreateClippedDrawTarget(
540     const IntSize &aMaxSize, const Matrix &aTransform,
541     SurfaceFormat aFormat) const {
542   RefPtr<DrawTarget> similarDT =
543       new DrawTargetRecording(this, aMaxSize, aFormat);
544   mRecorder->RecordEvent(RecordedCreateClippedDrawTarget(
545       similarDT.get(), aMaxSize, aTransform, aFormat));
546   return similarDT;
547 }
548 
CreatePathBuilder(FillRule aFillRule) const549 already_AddRefed<PathBuilder> DrawTargetRecording::CreatePathBuilder(
550     FillRule aFillRule) const {
551   RefPtr<PathBuilder> builder = mFinalDT->CreatePathBuilder(aFillRule);
552   return MakeAndAddRef<PathBuilderRecording>(builder, aFillRule);
553 }
554 
CreateGradientStops(GradientStop * aStops,uint32_t aNumStops,ExtendMode aExtendMode) const555 already_AddRefed<GradientStops> DrawTargetRecording::CreateGradientStops(
556     GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode) const {
557   RefPtr<GradientStops> retStops = new GradientStopsRecording(mRecorder);
558 
559   mRecorder->RecordEvent(
560       RecordedGradientStopsCreation(retStops, aStops, aNumStops, aExtendMode));
561 
562   return retStops.forget();
563 }
564 
SetTransform(const Matrix & aTransform)565 void DrawTargetRecording::SetTransform(const Matrix &aTransform) {
566   mRecorder->RecordEvent(RecordedSetTransform(this, aTransform));
567   DrawTarget::SetTransform(aTransform);
568 }
569 
EnsurePathStored(const Path * aPath)570 already_AddRefed<PathRecording> DrawTargetRecording::EnsurePathStored(
571     const Path *aPath) {
572   RefPtr<PathRecording> pathRecording;
573   if (aPath->GetBackendType() == BackendType::RECORDING) {
574     pathRecording =
575         const_cast<PathRecording *>(static_cast<const PathRecording *>(aPath));
576     if (mRecorder->HasStoredObject(aPath)) {
577       return pathRecording.forget();
578     }
579   } else {
580     MOZ_ASSERT(!mRecorder->HasStoredObject(aPath));
581     FillRule fillRule = aPath->GetFillRule();
582     RefPtr<PathBuilder> builder = mFinalDT->CreatePathBuilder(fillRule);
583     RefPtr<PathBuilderRecording> builderRecording =
584         new PathBuilderRecording(builder, fillRule);
585     aPath->StreamToSink(builderRecording);
586     pathRecording = builderRecording->Finish().downcast<PathRecording>();
587   }
588 
589   mRecorder->RecordEvent(RecordedPathCreation(pathRecording.get()));
590   mRecorder->AddStoredObject(pathRecording);
591   pathRecording->mStoredRecorders.push_back(mRecorder);
592 
593   return pathRecording.forget();
594 }
595 
EnsurePatternDependenciesStored(const Pattern & aPattern)596 void DrawTargetRecording::EnsurePatternDependenciesStored(
597     const Pattern &aPattern) {
598   switch (aPattern.GetType()) {
599     case PatternType::COLOR:
600       // No dependencies here.
601       return;
602     case PatternType::LINEAR_GRADIENT: {
603       MOZ_ASSERT(mRecorder->HasStoredObject(
604           static_cast<const LinearGradientPattern *>(&aPattern)->mStops));
605       return;
606     }
607     case PatternType::RADIAL_GRADIENT: {
608       MOZ_ASSERT(mRecorder->HasStoredObject(
609           static_cast<const RadialGradientPattern *>(&aPattern)->mStops));
610       return;
611     }
612     case PatternType::SURFACE: {
613       const SurfacePattern *pat =
614           static_cast<const SurfacePattern *>(&aPattern);
615       EnsureSurfaceStoredRecording(mRecorder, pat->mSurface,
616                                    "EnsurePatternDependenciesStored");
617       return;
618     }
619   }
620 }
621 
622 }  // namespace gfx
623 }  // namespace mozilla
624