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