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/. */
7 #include "DrawTargetWrapAndRecord.h"
8 #include "PathRecording.h"
14 #include "mozilla/UniquePtr.h"
15 #include "RecordingTypes.h"
16 #include "RecordedEventImpl.h"
21 struct WrapAndRecordSourceSurfaceUserData
{
23 RefPtr
<DrawEventRecorderPrivate
> recorder
;
26 static void WrapAndRecordSourceSurfaceUserDataFunc(void* aUserData
) {
27 WrapAndRecordSourceSurfaceUserData
* userData
=
28 static_cast<WrapAndRecordSourceSurfaceUserData
*>(aUserData
);
30 userData
->recorder
->RecordSourceSurfaceDestruction(
31 static_cast<SourceSurface
*>(userData
->refPtr
));
36 static void StoreSourceSurface(DrawEventRecorderPrivate
* aRecorder
,
37 SourceSurface
* aSurface
,
38 DataSourceSurface
* aDataSurf
,
41 gfxWarning() << "Recording failed to record SourceSurface for " << reason
;
42 // Insert a bogus source surface.
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()));
51 DataSourceSurface::ScopedMap
map(aDataSurf
, DataSourceSurface::READ
);
52 aRecorder
->RecordEvent(RecordedSourceSurfaceCreation(
53 aSurface
, map
.GetData(), map
.GetStride(), aDataSurf
->GetSize(),
54 aDataSurf
->GetFormat()));
58 static void EnsureSurfaceStored(DrawEventRecorderPrivate
* aRecorder
,
59 SourceSurface
* aSurface
, const char* reason
) {
60 if (aRecorder
->HasStoredObject(aSurface
)) {
64 RefPtr
<DataSourceSurface
> dataSurf
= aSurface
->GetDataSurface();
65 StoreSourceSurface(aRecorder
, aSurface
, dataSurf
, reason
);
66 aRecorder
->AddStoredObject(aSurface
);
67 aRecorder
->AddSourceSurface(aSurface
);
69 WrapAndRecordSourceSurfaceUserData
* userData
=
70 new WrapAndRecordSourceSurfaceUserData
;
71 userData
->refPtr
= aSurface
;
72 userData
->recorder
= aRecorder
;
73 aSurface
->AddUserData(reinterpret_cast<UserDataKey
*>(aRecorder
), userData
,
74 &WrapAndRecordSourceSurfaceUserDataFunc
);
77 class SourceSurfaceWrapAndRecord
: public SourceSurface
{
79 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceWrapAndRecord
, override
)
81 SourceSurfaceWrapAndRecord(SourceSurface
* aFinalSurface
,
82 DrawEventRecorderPrivate
* aRecorder
)
83 : mFinalSurface(aFinalSurface
), mRecorder(aRecorder
) {
84 mRecorder
->AddStoredObject(this);
87 ~SourceSurfaceWrapAndRecord() {
88 mRecorder
->RemoveStoredObject(this);
89 mRecorder
->RecordEvent(
90 RecordedSourceSurfaceDestruction(ReferencePtr(this)));
93 SurfaceType
GetType() const override
{ return SurfaceType::WRAP_AND_RECORD
; }
94 IntSize
GetSize() const override
{ return mFinalSurface
->GetSize(); }
95 SurfaceFormat
GetFormat() const override
{
96 return mFinalSurface
->GetFormat();
98 already_AddRefed
<DataSourceSurface
> GetDataSurface() override
{
99 return mFinalSurface
->GetDataSurface();
102 RefPtr
<SourceSurface
> mFinalSurface
;
103 RefPtr
<DrawEventRecorderPrivate
> mRecorder
;
106 class GradientStopsWrapAndRecord
: public GradientStops
{
108 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStopsWrapAndRecord
, override
)
110 GradientStopsWrapAndRecord(GradientStops
* aFinalGradientStops
,
111 DrawEventRecorderPrivate
* aRecorder
)
112 : mFinalGradientStops(aFinalGradientStops
), mRecorder(aRecorder
) {
113 mRecorder
->AddStoredObject(this);
116 ~GradientStopsWrapAndRecord() {
117 mRecorder
->RemoveStoredObject(this);
118 mRecorder
->RecordEvent(
119 RecordedGradientStopsDestruction(ReferencePtr(this)));
122 BackendType
GetBackendType() const override
{ return BackendType::RECORDING
; }
124 RefPtr
<GradientStops
> mFinalGradientStops
;
125 RefPtr
<DrawEventRecorderPrivate
> mRecorder
;
128 static SourceSurface
* GetSourceSurface(SourceSurface
* aSurface
) {
129 if (aSurface
->GetType() != SurfaceType::WRAP_AND_RECORD
) {
133 return static_cast<SourceSurfaceWrapAndRecord
*>(aSurface
)->mFinalSurface
;
136 static GradientStops
* GetGradientStops(GradientStops
* aStops
) {
137 if (aStops
->GetBackendType() != BackendType::RECORDING
) {
141 return static_cast<GradientStopsWrapAndRecord
*>(aStops
)->mFinalGradientStops
;
144 class FilterNodeWrapAndRecord
: public FilterNode
{
146 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeWrapAndRecord
, override
)
147 using FilterNode::SetAttribute
;
149 FilterNodeWrapAndRecord(FilterNode
* aFinalFilterNode
,
150 DrawEventRecorderPrivate
* aRecorder
)
151 : mFinalFilterNode(aFinalFilterNode
), mRecorder(aRecorder
) {
152 mRecorder
->AddStoredObject(this);
155 ~FilterNodeWrapAndRecord() {
156 mRecorder
->RemoveStoredObject(this);
157 mRecorder
->RecordEvent(RecordedFilterNodeDestruction(ReferencePtr(this)));
160 static FilterNode
* GetFilterNode(FilterNode
* aNode
) {
161 if (aNode
->GetBackendType() != FILTER_BACKEND_RECORDING
) {
163 << "Non recording filter node used with recording DrawTarget!";
167 return static_cast<FilterNodeWrapAndRecord
*>(aNode
)->mFinalFilterNode
;
170 void SetInput(uint32_t aIndex
, SourceSurface
* aSurface
) override
{
171 EnsureSurfaceStored(mRecorder
, aSurface
, "SetInput");
173 mRecorder
->RecordEvent(RecordedFilterNodeSetInput(this, aIndex
, aSurface
));
174 mFinalFilterNode
->SetInput(aIndex
, GetSourceSurface(aSurface
));
176 void SetInput(uint32_t aIndex
, FilterNode
* aFilter
) override
{
177 MOZ_ASSERT(mRecorder
->HasStoredObject(aFilter
));
179 mRecorder
->RecordEvent(RecordedFilterNodeSetInput(this, aIndex
, aFilter
));
180 mFinalFilterNode
->SetInput(aIndex
, GetFilterNode(aFilter
));
183 #define FORWARD_SET_ATTRIBUTE(type, argtype) \
184 void SetAttribute(uint32_t aIndex, type aValue) override { \
185 mRecorder->RecordEvent(RecordedFilterNodeSetAttribute( \
186 this, aIndex, aValue, \
187 RecordedFilterNodeSetAttribute::ARGTYPE_##argtype)); \
188 mFinalFilterNode->SetAttribute(aIndex, aValue); \
191 FORWARD_SET_ATTRIBUTE(bool, BOOL
);
192 FORWARD_SET_ATTRIBUTE(uint32_t, UINT32
);
193 FORWARD_SET_ATTRIBUTE(Float
, FLOAT
);
194 FORWARD_SET_ATTRIBUTE(const Size
&, SIZE
);
195 FORWARD_SET_ATTRIBUTE(const IntSize
&, INTSIZE
);
196 FORWARD_SET_ATTRIBUTE(const IntPoint
&, INTPOINT
);
197 FORWARD_SET_ATTRIBUTE(const Rect
&, RECT
);
198 FORWARD_SET_ATTRIBUTE(const IntRect
&, INTRECT
);
199 FORWARD_SET_ATTRIBUTE(const Point
&, POINT
);
200 FORWARD_SET_ATTRIBUTE(const Matrix
&, MATRIX
);
201 FORWARD_SET_ATTRIBUTE(const Matrix5x4
&, MATRIX5X4
);
202 FORWARD_SET_ATTRIBUTE(const Point3D
&, POINT3D
);
203 FORWARD_SET_ATTRIBUTE(const DeviceColor
&, COLOR
);
205 #undef FORWARD_SET_ATTRIBUTE
207 virtual void SetAttribute(uint32_t aIndex
, const Float
* aFloat
,
208 uint32_t aSize
) override
{
209 mRecorder
->RecordEvent(
210 RecordedFilterNodeSetAttribute(this, aIndex
, aFloat
, aSize
));
211 mFinalFilterNode
->SetAttribute(aIndex
, aFloat
, aSize
);
214 FilterBackend
GetBackendType() override
{ return FILTER_BACKEND_RECORDING
; }
216 RefPtr
<FilterNode
> mFinalFilterNode
;
217 RefPtr
<DrawEventRecorderPrivate
> mRecorder
;
220 struct AdjustedPattern final
{
221 explicit AdjustedPattern(const Pattern
& aPattern
) : mPattern(nullptr) {
222 mOrigPattern
= const_cast<Pattern
*>(&aPattern
);
227 mPattern
->~Pattern();
231 operator Pattern
*() {
232 switch (mOrigPattern
->GetType()) {
233 case PatternType::COLOR
:
235 case PatternType::SURFACE
: {
236 SurfacePattern
* surfPat
= static_cast<SurfacePattern
*>(mOrigPattern
);
237 mPattern
= new (mSurfPat
) SurfacePattern(
238 GetSourceSurface(surfPat
->mSurface
), surfPat
->mExtendMode
,
239 surfPat
->mMatrix
, surfPat
->mSamplingFilter
, surfPat
->mSamplingRect
);
242 case PatternType::LINEAR_GRADIENT
: {
243 LinearGradientPattern
* linGradPat
=
244 static_cast<LinearGradientPattern
*>(mOrigPattern
);
245 mPattern
= new (mLinGradPat
) LinearGradientPattern(
246 linGradPat
->mBegin
, linGradPat
->mEnd
,
247 GetGradientStops(linGradPat
->mStops
), linGradPat
->mMatrix
);
250 case PatternType::RADIAL_GRADIENT
: {
251 RadialGradientPattern
* radGradPat
=
252 static_cast<RadialGradientPattern
*>(mOrigPattern
);
253 mPattern
= new (mRadGradPat
) RadialGradientPattern(
254 radGradPat
->mCenter1
, radGradPat
->mCenter2
, radGradPat
->mRadius1
,
255 radGradPat
->mRadius2
, GetGradientStops(radGradPat
->mStops
),
256 radGradPat
->mMatrix
);
259 case PatternType::CONIC_GRADIENT
: {
260 ConicGradientPattern
* conGradPat
=
261 static_cast<ConicGradientPattern
*>(mOrigPattern
);
262 mPattern
= new (mConGradPat
) ConicGradientPattern(
263 conGradPat
->mCenter
, conGradPat
->mAngle
, conGradPat
->mStartOffset
,
264 conGradPat
->mEndOffset
, GetGradientStops(conGradPat
->mStops
),
265 conGradPat
->mMatrix
);
269 return new (mColPat
) ColorPattern(DeviceColor());
276 char mColPat
[sizeof(ColorPattern
)];
277 char mLinGradPat
[sizeof(LinearGradientPattern
)];
278 char mRadGradPat
[sizeof(RadialGradientPattern
)];
279 char mConGradPat
[sizeof(ConicGradientPattern
)];
280 char mSurfPat
[sizeof(SurfacePattern
)];
283 Pattern
* mOrigPattern
;
287 DrawTargetWrapAndRecord::DrawTargetWrapAndRecord(DrawEventRecorder
* aRecorder
,
288 DrawTarget
* aDT
, bool aHasData
)
289 : mRecorder(static_cast<DrawEventRecorderPrivate
*>(aRecorder
)),
291 RefPtr
<SourceSurface
> snapshot
= aHasData
? mFinalDT
->Snapshot() : nullptr;
292 mRecorder
->RecordEvent(RecordedDrawTargetCreation(
293 this, mFinalDT
->GetBackendType(), mFinalDT
->GetRect(),
294 mFinalDT
->GetFormat(), aHasData
, snapshot
));
295 mFormat
= mFinalDT
->GetFormat();
298 DrawTargetWrapAndRecord::DrawTargetWrapAndRecord(
299 const DrawTargetWrapAndRecord
* aDT
, DrawTarget
* aSimilarDT
)
300 : mRecorder(aDT
->mRecorder
), mFinalDT(aSimilarDT
) {
301 mRecorder
->RecordEvent(RecordedCreateSimilarDrawTarget(
302 this, mFinalDT
->GetSize(), mFinalDT
->GetFormat()));
303 mFormat
= mFinalDT
->GetFormat();
306 DrawTargetWrapAndRecord::~DrawTargetWrapAndRecord() {
307 mRecorder
->RecordEvent(
308 RecordedDrawTargetDestruction(static_cast<DrawTarget
*>(this)));
311 void DrawTargetWrapAndRecord::FillRect(const Rect
& aRect
,
312 const Pattern
& aPattern
,
313 const DrawOptions
& aOptions
) {
314 EnsurePatternDependenciesStored(aPattern
);
316 mRecorder
->RecordEvent(RecordedFillRect(this, aRect
, aPattern
, aOptions
));
317 mFinalDT
->FillRect(aRect
, *AdjustedPattern(aPattern
), aOptions
);
320 void DrawTargetWrapAndRecord::StrokeRect(const Rect
& aRect
,
321 const Pattern
& aPattern
,
322 const StrokeOptions
& aStrokeOptions
,
323 const DrawOptions
& aOptions
) {
324 EnsurePatternDependenciesStored(aPattern
);
326 mRecorder
->RecordEvent(
327 RecordedStrokeRect(this, aRect
, aPattern
, aStrokeOptions
, aOptions
));
328 mFinalDT
->StrokeRect(aRect
, *AdjustedPattern(aPattern
), aStrokeOptions
,
332 void DrawTargetWrapAndRecord::StrokeLine(const Point
& aBegin
, const Point
& aEnd
,
333 const Pattern
& aPattern
,
334 const StrokeOptions
& aStrokeOptions
,
335 const DrawOptions
& aOptions
) {
336 EnsurePatternDependenciesStored(aPattern
);
338 mRecorder
->RecordEvent(RecordedStrokeLine(this, aBegin
, aEnd
, aPattern
,
339 aStrokeOptions
, aOptions
));
340 mFinalDT
->StrokeLine(aBegin
, aEnd
, *AdjustedPattern(aPattern
), aStrokeOptions
,
344 void DrawTargetWrapAndRecord::Fill(const Path
* aPath
, const Pattern
& aPattern
,
345 const DrawOptions
& aOptions
) {
346 RefPtr
<PathRecording
> pathWrapAndRecord
= EnsurePathStored(aPath
);
347 EnsurePatternDependenciesStored(aPattern
);
349 mRecorder
->RecordEvent(
350 RecordedFill(this, pathWrapAndRecord
, aPattern
, aOptions
));
351 mFinalDT
->Fill(pathWrapAndRecord
->mPath
, *AdjustedPattern(aPattern
),
355 struct WrapAndRecordFontUserData
{
358 RefPtr
<DrawEventRecorderPrivate
> recorder
;
361 static void WrapAndRecordFontUserDataDestroyFunc(void* aUserData
) {
362 WrapAndRecordFontUserData
* userData
=
363 static_cast<WrapAndRecordFontUserData
*>(aUserData
);
365 userData
->recorder
->RecordEvent(
366 RecordedScaledFontDestruction(ReferencePtr(userData
->refPtr
)));
367 userData
->recorder
->RemoveScaledFont((ScaledFont
*)userData
->refPtr
);
368 userData
->recorder
->DecrementUnscaledFontRefCount(userData
->unscaledFont
);
372 void DrawTargetWrapAndRecord::FillGlyphs(ScaledFont
* aFont
,
373 const GlyphBuffer
& aBuffer
,
374 const Pattern
& aPattern
,
375 const DrawOptions
& aOptions
) {
376 EnsurePatternDependenciesStored(aPattern
);
378 UserDataKey
* userDataKey
= reinterpret_cast<UserDataKey
*>(mRecorder
.get());
379 if (!aFont
->GetUserData(userDataKey
)) {
380 UnscaledFont
* unscaledFont
= aFont
->GetUnscaledFont();
381 if (mRecorder
->IncrementUnscaledFontRefCount(unscaledFont
) == 0) {
382 RecordedFontData
fontData(unscaledFont
);
383 RecordedFontDetails fontDetails
;
384 if (fontData
.GetFontDetails(fontDetails
)) {
385 // Try to serialise the whole font, just in case this is a web font that
386 // is not present on the system.
387 if (!mRecorder
->HasStoredFontData(fontDetails
.fontDataKey
)) {
388 mRecorder
->RecordEvent(fontData
);
389 mRecorder
->AddStoredFontData(fontDetails
.fontDataKey
);
391 mRecorder
->RecordEvent(
392 RecordedUnscaledFontCreation(unscaledFont
, fontDetails
));
394 // If that fails, record just the font description and try to load it
395 // from the system on the other side.
396 RecordedFontDescriptor
fontDesc(unscaledFont
);
397 if (fontDesc
.IsValid()) {
398 mRecorder
->RecordEvent(fontDesc
);
400 gfxWarning() << "DrawTargetWrapAndRecord::FillGlyphs failed to "
401 "serialise UnscaledFont";
406 mRecorder
->RecordEvent(RecordedScaledFontCreation(aFont
, unscaledFont
));
408 WrapAndRecordFontUserData
* userData
= new WrapAndRecordFontUserData
;
409 userData
->refPtr
= aFont
;
410 userData
->unscaledFont
= unscaledFont
;
411 userData
->recorder
= mRecorder
;
412 aFont
->AddUserData(userDataKey
, userData
,
413 &WrapAndRecordFontUserDataDestroyFunc
);
414 userData
->recorder
->AddScaledFont(aFont
);
417 mRecorder
->RecordEvent(RecordedFillGlyphs(
418 this, aFont
, aPattern
, aOptions
, aBuffer
.mGlyphs
, aBuffer
.mNumGlyphs
));
419 mFinalDT
->FillGlyphs(aFont
, aBuffer
, *AdjustedPattern(aPattern
), aOptions
);
422 void DrawTargetWrapAndRecord::Mask(const Pattern
& aSource
, const Pattern
& aMask
,
423 const DrawOptions
& aOptions
) {
424 EnsurePatternDependenciesStored(aSource
);
425 EnsurePatternDependenciesStored(aMask
);
427 mRecorder
->RecordEvent(RecordedMask(this, aSource
, aMask
, aOptions
));
428 mFinalDT
->Mask(*AdjustedPattern(aSource
), *AdjustedPattern(aMask
), aOptions
);
431 void DrawTargetWrapAndRecord::MaskSurface(const Pattern
& aSource
,
432 SourceSurface
* aMask
, Point aOffset
,
433 const DrawOptions
& aOptions
) {
434 EnsurePatternDependenciesStored(aSource
);
435 EnsureSurfaceStored(mRecorder
, aMask
, "MaskSurface");
437 mRecorder
->RecordEvent(
438 RecordedMaskSurface(this, aSource
, aMask
, aOffset
, aOptions
));
439 mFinalDT
->MaskSurface(*AdjustedPattern(aSource
), GetSourceSurface(aMask
),
443 void DrawTargetWrapAndRecord::Stroke(const Path
* aPath
, const Pattern
& aPattern
,
444 const StrokeOptions
& aStrokeOptions
,
445 const DrawOptions
& aOptions
) {
446 RefPtr
<PathRecording
> pathWrapAndRecord
= EnsurePathStored(aPath
);
447 EnsurePatternDependenciesStored(aPattern
);
449 mRecorder
->RecordEvent(RecordedStroke(this, pathWrapAndRecord
, aPattern
,
450 aStrokeOptions
, aOptions
));
451 mFinalDT
->Stroke(pathWrapAndRecord
->mPath
, *AdjustedPattern(aPattern
),
452 aStrokeOptions
, aOptions
);
455 already_AddRefed
<SourceSurface
> DrawTargetWrapAndRecord::Snapshot() {
456 RefPtr
<SourceSurface
> surf
= mFinalDT
->Snapshot();
458 RefPtr
<SourceSurface
> retSurf
=
459 new SourceSurfaceWrapAndRecord(surf
, mRecorder
);
461 mRecorder
->RecordEvent(RecordedSnapshot(retSurf
, this));
463 return retSurf
.forget();
466 already_AddRefed
<SourceSurface
> DrawTargetWrapAndRecord::IntoLuminanceSource(
467 LuminanceType aLuminanceType
, float aOpacity
) {
468 RefPtr
<SourceSurface
> surf
=
469 mFinalDT
->IntoLuminanceSource(aLuminanceType
, aOpacity
);
471 RefPtr
<SourceSurface
> retSurf
=
472 new SourceSurfaceWrapAndRecord(surf
, mRecorder
);
474 mRecorder
->RecordEvent(
475 RecordedIntoLuminanceSource(retSurf
, this, aLuminanceType
, aOpacity
));
477 return retSurf
.forget();
480 void DrawTargetWrapAndRecord::DetachAllSnapshots() {
481 mFinalDT
->DetachAllSnapshots();
484 void DrawTargetWrapAndRecord::DrawSurface(
485 SourceSurface
* aSurface
, const Rect
& aDest
, const Rect
& aSource
,
486 const DrawSurfaceOptions
& aSurfOptions
, const DrawOptions
& aOptions
) {
487 EnsureSurfaceStored(mRecorder
, aSurface
, "DrawSurface");
489 mRecorder
->RecordEvent(RecordedDrawSurface(this, aSurface
, aDest
, aSource
,
490 aSurfOptions
, aOptions
));
491 mFinalDT
->DrawSurface(GetSourceSurface(aSurface
), aDest
, aSource
,
492 aSurfOptions
, aOptions
);
495 void DrawTargetWrapAndRecord::DrawSurfaceWithShadow(
496 SourceSurface
* aSurface
, const Point
& aDest
, const DeviceColor
& aColor
,
497 const Point
& aOffset
, Float aSigma
, CompositionOp aOp
) {
498 EnsureSurfaceStored(mRecorder
, aSurface
, "DrawSurfaceWithShadow");
500 mRecorder
->RecordEvent(RecordedDrawSurfaceWithShadow(
501 this, aSurface
, aDest
, aColor
, aOffset
, aSigma
, aOp
));
502 mFinalDT
->DrawSurfaceWithShadow(GetSourceSurface(aSurface
), aDest
, aColor
,
503 aOffset
, aSigma
, aOp
);
506 void DrawTargetWrapAndRecord::DrawFilter(FilterNode
* aNode
,
507 const Rect
& aSourceRect
,
508 const Point
& aDestPoint
,
509 const DrawOptions
& aOptions
) {
510 MOZ_ASSERT(mRecorder
->HasStoredObject(aNode
));
512 mRecorder
->RecordEvent(
513 RecordedDrawFilter(this, aNode
, aSourceRect
, aDestPoint
, aOptions
));
514 mFinalDT
->DrawFilter(FilterNodeWrapAndRecord::GetFilterNode(aNode
),
515 aSourceRect
, aDestPoint
, aOptions
);
518 already_AddRefed
<FilterNode
> DrawTargetWrapAndRecord::CreateFilter(
520 RefPtr
<FilterNode
> node
= mFinalDT
->CreateFilter(aType
);
522 RefPtr
<FilterNode
> retNode
= new FilterNodeWrapAndRecord(node
, mRecorder
);
524 mRecorder
->RecordEvent(RecordedFilterNodeCreation(retNode
, aType
));
526 return retNode
.forget();
529 void DrawTargetWrapAndRecord::ClearRect(const Rect
& aRect
) {
530 mRecorder
->RecordEvent(RecordedClearRect(this, aRect
));
531 mFinalDT
->ClearRect(aRect
);
534 void DrawTargetWrapAndRecord::CopySurface(SourceSurface
* aSurface
,
535 const IntRect
& aSourceRect
,
536 const IntPoint
& aDestination
) {
537 EnsureSurfaceStored(mRecorder
, aSurface
, "CopySurface");
539 mRecorder
->RecordEvent(
540 RecordedCopySurface(this, aSurface
, aSourceRect
, aDestination
));
541 mFinalDT
->CopySurface(GetSourceSurface(aSurface
), aSourceRect
, aDestination
);
544 void DrawTargetWrapAndRecord::PushClip(const Path
* aPath
) {
545 RefPtr
<PathRecording
> pathWrapAndRecord
= EnsurePathStored(aPath
);
547 mRecorder
->RecordEvent(RecordedPushClip(this, pathWrapAndRecord
));
548 mFinalDT
->PushClip(pathWrapAndRecord
->mPath
);
551 void DrawTargetWrapAndRecord::PushClipRect(const Rect
& aRect
) {
552 mRecorder
->RecordEvent(RecordedPushClipRect(this, aRect
));
553 mFinalDT
->PushClipRect(aRect
);
556 void DrawTargetWrapAndRecord::PopClip() {
557 mRecorder
->RecordEvent(RecordedPopClip(static_cast<DrawTarget
*>(this)));
561 void DrawTargetWrapAndRecord::PushLayer(bool aOpaque
, Float aOpacity
,
562 SourceSurface
* aMask
,
563 const Matrix
& aMaskTransform
,
564 const IntRect
& aBounds
,
565 bool aCopyBackground
) {
567 EnsureSurfaceStored(mRecorder
, aMask
, "PushLayer");
570 mRecorder
->RecordEvent(RecordedPushLayer(this, aOpaque
, aOpacity
, aMask
,
571 aMaskTransform
, aBounds
,
573 mFinalDT
->PushLayer(aOpaque
, aOpacity
, aMask
, aMaskTransform
, aBounds
,
577 void DrawTargetWrapAndRecord::PopLayer() {
578 mRecorder
->RecordEvent(RecordedPopLayer(static_cast<DrawTarget
*>(this)));
579 mFinalDT
->PopLayer();
582 already_AddRefed
<SourceSurface
>
583 DrawTargetWrapAndRecord::CreateSourceSurfaceFromData(
584 unsigned char* aData
, const IntSize
& aSize
, int32_t aStride
,
585 SurfaceFormat aFormat
) const {
586 RefPtr
<SourceSurface
> surf
=
587 mFinalDT
->CreateSourceSurfaceFromData(aData
, aSize
, aStride
, aFormat
);
589 RefPtr
<SourceSurface
> retSurf
=
590 new SourceSurfaceWrapAndRecord(surf
, mRecorder
);
592 mRecorder
->RecordEvent(
593 RecordedSourceSurfaceCreation(retSurf
, aData
, aStride
, aSize
, aFormat
));
595 return retSurf
.forget();
598 already_AddRefed
<SourceSurface
> DrawTargetWrapAndRecord::OptimizeSourceSurface(
599 SourceSurface
* aSurface
) const {
600 RefPtr
<SourceSurface
> surf
= mFinalDT
->OptimizeSourceSurface(aSurface
);
602 RefPtr
<SourceSurface
> retSurf
=
603 new SourceSurfaceWrapAndRecord(surf
, mRecorder
);
605 RefPtr
<DataSourceSurface
> dataSurf
= surf
->GetDataSurface();
608 // Let's try get it off the original surface.
609 dataSurf
= aSurface
->GetDataSurface();
612 StoreSourceSurface(mRecorder
, retSurf
, dataSurf
, "OptimizeSourceSurface");
614 return retSurf
.forget();
617 already_AddRefed
<SourceSurface
>
618 DrawTargetWrapAndRecord::CreateSourceSurfaceFromNativeSurface(
619 const NativeSurface
& aSurface
) const {
620 RefPtr
<SourceSurface
> surf
=
621 mFinalDT
->CreateSourceSurfaceFromNativeSurface(aSurface
);
623 RefPtr
<SourceSurface
> retSurf
=
624 new SourceSurfaceWrapAndRecord(surf
, mRecorder
);
626 RefPtr
<DataSourceSurface
> dataSurf
= surf
->GetDataSurface();
627 StoreSourceSurface(mRecorder
, retSurf
, dataSurf
,
628 "CreateSourceSurfaceFromNativeSurface");
630 return retSurf
.forget();
633 already_AddRefed
<DrawTarget
> DrawTargetWrapAndRecord::CreateSimilarDrawTarget(
634 const IntSize
& aSize
, SurfaceFormat aFormat
) const {
635 RefPtr
<DrawTarget
> similarDT
=
636 mFinalDT
->CreateSimilarDrawTarget(aSize
, aFormat
);
641 similarDT
= new DrawTargetWrapAndRecord(this, similarDT
);
642 return similarDT
.forget();
645 bool DrawTargetWrapAndRecord::CanCreateSimilarDrawTarget(
646 const IntSize
& aSize
, SurfaceFormat aFormat
) const {
647 return mFinalDT
->CanCreateSimilarDrawTarget(aSize
, aFormat
);
650 RefPtr
<DrawTarget
> DrawTargetWrapAndRecord::CreateClippedDrawTarget(
651 const Rect
& aBounds
, SurfaceFormat aFormat
) {
652 RefPtr
<DrawTarget
> similarDT
;
653 RefPtr
<DrawTarget
> innerDT
=
654 mFinalDT
->CreateClippedDrawTarget(aBounds
, aFormat
);
655 similarDT
= new DrawTargetWrapAndRecord(this->mRecorder
, innerDT
);
656 mRecorder
->RecordEvent(
657 RecordedCreateClippedDrawTarget(this, similarDT
.get(), aBounds
, aFormat
));
661 already_AddRefed
<PathBuilder
> DrawTargetWrapAndRecord::CreatePathBuilder(
662 FillRule aFillRule
) const {
663 RefPtr
<PathBuilder
> builder
= mFinalDT
->CreatePathBuilder(aFillRule
);
664 return MakeAndAddRef
<PathBuilderRecording
>(builder
, aFillRule
);
667 already_AddRefed
<GradientStops
> DrawTargetWrapAndRecord::CreateGradientStops(
668 GradientStop
* aStops
, uint32_t aNumStops
, ExtendMode aExtendMode
) const {
669 RefPtr
<GradientStops
> stops
=
670 mFinalDT
->CreateGradientStops(aStops
, aNumStops
, aExtendMode
);
672 RefPtr
<GradientStops
> retStops
=
673 new GradientStopsWrapAndRecord(stops
, mRecorder
);
675 mRecorder
->RecordEvent(
676 RecordedGradientStopsCreation(retStops
, aStops
, aNumStops
, aExtendMode
));
678 return retStops
.forget();
681 void DrawTargetWrapAndRecord::SetTransform(const Matrix
& aTransform
) {
682 mRecorder
->RecordEvent(RecordedSetTransform(this, aTransform
));
683 DrawTarget::SetTransform(aTransform
);
684 mFinalDT
->SetTransform(aTransform
);
687 already_AddRefed
<PathRecording
> DrawTargetWrapAndRecord::EnsurePathStored(
689 RefPtr
<PathRecording
> pathWrapAndRecord
;
690 if (aPath
->GetBackendType() == BackendType::RECORDING
) {
692 const_cast<PathRecording
*>(static_cast<const PathRecording
*>(aPath
));
693 if (mRecorder
->HasStoredObject(aPath
)) {
694 return pathWrapAndRecord
.forget();
697 MOZ_ASSERT(!mRecorder
->HasStoredObject(aPath
));
698 FillRule fillRule
= aPath
->GetFillRule();
699 RefPtr
<PathBuilder
> builder
= mFinalDT
->CreatePathBuilder(fillRule
);
700 RefPtr
<PathBuilderRecording
> builderWrapAndRecord
=
701 new PathBuilderRecording(builder
, fillRule
);
702 aPath
->StreamToSink(builderWrapAndRecord
);
704 builderWrapAndRecord
->Finish().downcast
<PathRecording
>();
707 mRecorder
->RecordEvent(RecordedPathCreation(pathWrapAndRecord
.get()));
708 mRecorder
->AddStoredObject(pathWrapAndRecord
);
709 pathWrapAndRecord
->mStoredRecorders
.push_back(mRecorder
);
711 return pathWrapAndRecord
.forget();
714 void DrawTargetWrapAndRecord::EnsurePatternDependenciesStored(
715 const Pattern
& aPattern
) {
716 switch (aPattern
.GetType()) {
717 case PatternType::COLOR
:
718 // No dependencies here.
720 case PatternType::LINEAR_GRADIENT
: {
721 MOZ_ASSERT(mRecorder
->HasStoredObject(
722 static_cast<const LinearGradientPattern
*>(&aPattern
)->mStops
));
725 case PatternType::RADIAL_GRADIENT
: {
726 MOZ_ASSERT(mRecorder
->HasStoredObject(
727 static_cast<const RadialGradientPattern
*>(&aPattern
)->mStops
));
730 case PatternType::CONIC_GRADIENT
: {
731 MOZ_ASSERT(mRecorder
->HasStoredObject(
732 static_cast<const ConicGradientPattern
*>(&aPattern
)->mStops
));
735 case PatternType::SURFACE
: {
736 const SurfacePattern
* pat
= static_cast<const SurfacePattern
*>(&aPattern
);
737 EnsureSurfaceStored(mRecorder
, pat
->mSurface
,
738 "EnsurePatternDependenciesStored");
745 } // namespace mozilla