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