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 "DrawTargetRecording.h"
8 #include "DrawTargetSkia.h"
9 #include "PathRecording.h"
15 #include "mozilla/gfx/DataSurfaceHelpers.h"
16 #include "mozilla/layers/SourceSurfaceSharedData.h"
17 #include "mozilla/UniquePtr.h"
18 #include "nsXULAppAPI.h" // for XRE_IsContentProcess()
19 #include "RecordingTypes.h"
20 #include "RecordedEventImpl.h"
25 struct RecordingSourceSurfaceUserData
{
27 RefPtr
<DrawEventRecorderPrivate
> recorder
;
30 static void RecordingSourceSurfaceUserDataFunc(void* aUserData
) {
31 RecordingSourceSurfaceUserData
* userData
=
32 static_cast<RecordingSourceSurfaceUserData
*>(aUserData
);
34 userData
->recorder
->RecordSourceSurfaceDestruction(
35 static_cast<SourceSurface
*>(userData
->refPtr
));
40 static void EnsureSurfaceStoredRecording(DrawEventRecorderPrivate
* aRecorder
,
41 SourceSurface
* aSurface
,
43 if (aRecorder
->HasStoredObject(aSurface
)) {
47 aRecorder
->StoreSourceSurfaceRecording(aSurface
, reason
);
48 aRecorder
->AddStoredObject(aSurface
);
49 aRecorder
->AddSourceSurface(aSurface
);
51 RecordingSourceSurfaceUserData
* userData
= new RecordingSourceSurfaceUserData
;
52 userData
->refPtr
= aSurface
;
53 userData
->recorder
= aRecorder
;
54 aSurface
->AddUserData(reinterpret_cast<UserDataKey
*>(aRecorder
), userData
,
55 &RecordingSourceSurfaceUserDataFunc
);
58 class SourceSurfaceRecording
: public SourceSurface
{
60 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceRecording
, override
)
62 SourceSurfaceRecording(IntSize aSize
, SurfaceFormat aFormat
,
63 DrawEventRecorderPrivate
* aRecorder
,
64 SourceSurface
* aOriginalSurface
= nullptr)
68 mOriginalSurface(aOriginalSurface
) {
69 mRecorder
->AddStoredObject(this);
72 ~SourceSurfaceRecording() {
73 mRecorder
->RemoveStoredObject(this);
74 mRecorder
->RecordEvent(
75 RecordedSourceSurfaceDestruction(ReferencePtr(this)));
78 SurfaceType
GetType() const override
{ return SurfaceType::RECORDING
; }
79 IntSize
GetSize() const override
{ return mSize
; }
80 SurfaceFormat
GetFormat() const override
{ return mFormat
; }
81 already_AddRefed
<DataSourceSurface
> GetDataSurface() override
{
82 if (mOriginalSurface
) {
83 return mOriginalSurface
->GetDataSurface();
90 SurfaceFormat mFormat
;
91 RefPtr
<DrawEventRecorderPrivate
> mRecorder
;
92 // If a SourceSurfaceRecording is returned from an OptimizeSourceSurface call
93 // we need GetDataSurface to work, so we hold the original surface we
94 // optimized to return its GetDataSurface.
95 RefPtr
<SourceSurface
> mOriginalSurface
;
98 class GradientStopsRecording
: public GradientStops
{
100 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStopsRecording
, override
)
102 explicit GradientStopsRecording(DrawEventRecorderPrivate
* aRecorder
)
103 : mRecorder(aRecorder
) {
104 mRecorder
->AddStoredObject(this);
107 virtual ~GradientStopsRecording() {
108 mRecorder
->RemoveStoredObject(this);
109 mRecorder
->RecordEvent(
110 RecordedGradientStopsDestruction(ReferencePtr(this)));
113 BackendType
GetBackendType() const override
{ return BackendType::RECORDING
; }
115 RefPtr
<DrawEventRecorderPrivate
> mRecorder
;
118 class FilterNodeRecording
: public FilterNode
{
120 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeRecording
, override
)
121 using FilterNode::SetAttribute
;
123 explicit FilterNodeRecording(DrawEventRecorderPrivate
* aRecorder
)
124 : mRecorder(aRecorder
) {
125 mRecorder
->AddStoredObject(this);
128 virtual ~FilterNodeRecording() {
129 mRecorder
->RemoveStoredObject(this);
130 mRecorder
->RecordEvent(RecordedFilterNodeDestruction(ReferencePtr(this)));
133 void SetInput(uint32_t aIndex
, SourceSurface
* aSurface
) override
{
134 EnsureSurfaceStoredRecording(mRecorder
, aSurface
, "SetInput");
136 mRecorder
->RecordEvent(RecordedFilterNodeSetInput(this, aIndex
, aSurface
));
138 void SetInput(uint32_t aIndex
, FilterNode
* aFilter
) override
{
139 MOZ_ASSERT(mRecorder
->HasStoredObject(aFilter
));
141 mRecorder
->RecordEvent(RecordedFilterNodeSetInput(this, aIndex
, aFilter
));
144 #define FORWARD_SET_ATTRIBUTE(type, argtype) \
145 void SetAttribute(uint32_t aIndex, type aValue) override { \
146 mRecorder->RecordEvent(RecordedFilterNodeSetAttribute( \
147 this, aIndex, aValue, \
148 RecordedFilterNodeSetAttribute::ARGTYPE_##argtype)); \
151 FORWARD_SET_ATTRIBUTE(bool, BOOL
);
152 FORWARD_SET_ATTRIBUTE(uint32_t, UINT32
);
153 FORWARD_SET_ATTRIBUTE(Float
, FLOAT
);
154 FORWARD_SET_ATTRIBUTE(const Size
&, SIZE
);
155 FORWARD_SET_ATTRIBUTE(const IntSize
&, INTSIZE
);
156 FORWARD_SET_ATTRIBUTE(const IntPoint
&, INTPOINT
);
157 FORWARD_SET_ATTRIBUTE(const Rect
&, RECT
);
158 FORWARD_SET_ATTRIBUTE(const IntRect
&, INTRECT
);
159 FORWARD_SET_ATTRIBUTE(const Point
&, POINT
);
160 FORWARD_SET_ATTRIBUTE(const Matrix
&, MATRIX
);
161 FORWARD_SET_ATTRIBUTE(const Matrix5x4
&, MATRIX5X4
);
162 FORWARD_SET_ATTRIBUTE(const Point3D
&, POINT3D
);
163 FORWARD_SET_ATTRIBUTE(const DeviceColor
&, COLOR
);
165 #undef FORWARD_SET_ATTRIBUTE
167 void SetAttribute(uint32_t aIndex
, const Float
* aFloat
,
168 uint32_t aSize
) override
{
169 mRecorder
->RecordEvent(
170 RecordedFilterNodeSetAttribute(this, aIndex
, aFloat
, aSize
));
173 FilterBackend
GetBackendType() override
{ return FILTER_BACKEND_RECORDING
; }
175 RefPtr
<DrawEventRecorderPrivate
> mRecorder
;
178 DrawTargetRecording::DrawTargetRecording(DrawEventRecorder
* aRecorder
,
179 DrawTarget
* aDT
, IntRect aRect
,
181 : mRecorder(static_cast<DrawEventRecorderPrivate
*>(aRecorder
)),
184 RefPtr
<SourceSurface
> snapshot
= aHasData
? mFinalDT
->Snapshot() : nullptr;
185 mRecorder
->RecordEvent(
186 RecordedDrawTargetCreation(this, mFinalDT
->GetBackendType(), mRect
,
187 mFinalDT
->GetFormat(), aHasData
, snapshot
));
188 mFormat
= mFinalDT
->GetFormat();
191 DrawTargetRecording::DrawTargetRecording(const DrawTargetRecording
* aDT
,
192 IntRect aRect
, SurfaceFormat aFormat
)
193 : mRecorder(aDT
->mRecorder
), mFinalDT(aDT
->mFinalDT
), mRect(aRect
) {
197 DrawTargetRecording::~DrawTargetRecording() {
198 mRecorder
->RecordEvent(RecordedDrawTargetDestruction(ReferencePtr(this)));
201 void DrawTargetRecording::FillRect(const Rect
& aRect
, const Pattern
& aPattern
,
202 const DrawOptions
& aOptions
) {
203 EnsurePatternDependenciesStored(aPattern
);
205 mRecorder
->RecordEvent(RecordedFillRect(this, aRect
, aPattern
, aOptions
));
208 void DrawTargetRecording::StrokeRect(const Rect
& aRect
, const Pattern
& aPattern
,
209 const StrokeOptions
& aStrokeOptions
,
210 const DrawOptions
& aOptions
) {
211 EnsurePatternDependenciesStored(aPattern
);
213 mRecorder
->RecordEvent(
214 RecordedStrokeRect(this, aRect
, aPattern
, aStrokeOptions
, aOptions
));
217 void DrawTargetRecording::StrokeLine(const Point
& aBegin
, const Point
& aEnd
,
218 const Pattern
& aPattern
,
219 const StrokeOptions
& aStrokeOptions
,
220 const DrawOptions
& aOptions
) {
221 EnsurePatternDependenciesStored(aPattern
);
223 mRecorder
->RecordEvent(RecordedStrokeLine(this, aBegin
, aEnd
, aPattern
,
224 aStrokeOptions
, aOptions
));
227 void DrawTargetRecording::Fill(const Path
* aPath
, const Pattern
& aPattern
,
228 const DrawOptions
& aOptions
) {
229 RefPtr
<PathRecording
> pathRecording
= EnsurePathStored(aPath
);
230 EnsurePatternDependenciesStored(aPattern
);
232 mRecorder
->RecordEvent(RecordedFill(this, pathRecording
, aPattern
, aOptions
));
235 struct RecordingFontUserData
{
238 RefPtr
<DrawEventRecorderPrivate
> recorder
;
241 static void RecordingFontUserDataDestroyFunc(void* aUserData
) {
242 RecordingFontUserData
* userData
=
243 static_cast<RecordingFontUserData
*>(aUserData
);
245 userData
->recorder
->RecordEvent(
246 RecordedScaledFontDestruction(ReferencePtr(userData
->refPtr
)));
247 userData
->recorder
->RemoveScaledFont((ScaledFont
*)userData
->refPtr
);
248 userData
->recorder
->DecrementUnscaledFontRefCount(userData
->unscaledFont
);
252 void DrawTargetRecording::FillGlyphs(ScaledFont
* aFont
,
253 const GlyphBuffer
& aBuffer
,
254 const Pattern
& aPattern
,
255 const DrawOptions
& aOptions
) {
256 EnsurePatternDependenciesStored(aPattern
);
258 UserDataKey
* userDataKey
= reinterpret_cast<UserDataKey
*>(mRecorder
.get());
259 if (mRecorder
->WantsExternalFonts()) {
260 mRecorder
->AddScaledFont(aFont
);
261 } else if (!aFont
->GetUserData(userDataKey
)) {
262 UnscaledFont
* unscaledFont
= aFont
->GetUnscaledFont();
263 if (mRecorder
->IncrementUnscaledFontRefCount(unscaledFont
) == 0) {
264 RecordedFontData
fontData(unscaledFont
);
265 RecordedFontDetails fontDetails
;
266 if (fontData
.GetFontDetails(fontDetails
)) {
267 // Try to serialise the whole font, just in case this is a web font that
268 // is not present on the system.
269 if (!mRecorder
->HasStoredFontData(fontDetails
.fontDataKey
)) {
270 mRecorder
->RecordEvent(fontData
);
271 mRecorder
->AddStoredFontData(fontDetails
.fontDataKey
);
273 mRecorder
->RecordEvent(
274 RecordedUnscaledFontCreation(unscaledFont
, fontDetails
));
276 // If that fails, record just the font description and try to load it
277 // from the system on the other side.
278 RecordedFontDescriptor
fontDesc(unscaledFont
);
279 if (fontDesc
.IsValid()) {
280 mRecorder
->RecordEvent(fontDesc
);
282 gfxWarning() << "DrawTargetRecording::FillGlyphs failed to serialise "
287 mRecorder
->RecordEvent(RecordedScaledFontCreation(aFont
, unscaledFont
));
288 RecordingFontUserData
* userData
= new RecordingFontUserData
;
289 userData
->refPtr
= aFont
;
290 userData
->unscaledFont
= unscaledFont
;
291 userData
->recorder
= mRecorder
;
292 aFont
->AddUserData(userDataKey
, userData
,
293 &RecordingFontUserDataDestroyFunc
);
294 userData
->recorder
->AddScaledFont(aFont
);
297 mRecorder
->RecordEvent(RecordedFillGlyphs(
298 this, aFont
, aPattern
, aOptions
, aBuffer
.mGlyphs
, aBuffer
.mNumGlyphs
));
301 void DrawTargetRecording::Mask(const Pattern
& aSource
, const Pattern
& aMask
,
302 const DrawOptions
& aOptions
) {
303 EnsurePatternDependenciesStored(aSource
);
304 EnsurePatternDependenciesStored(aMask
);
306 mRecorder
->RecordEvent(RecordedMask(this, aSource
, aMask
, aOptions
));
309 void DrawTargetRecording::MaskSurface(const Pattern
& aSource
,
310 SourceSurface
* aMask
, Point aOffset
,
311 const DrawOptions
& aOptions
) {
312 EnsurePatternDependenciesStored(aSource
);
313 EnsureSurfaceStoredRecording(mRecorder
, aMask
, "MaskSurface");
315 mRecorder
->RecordEvent(
316 RecordedMaskSurface(this, aSource
, aMask
, aOffset
, aOptions
));
319 void DrawTargetRecording::Stroke(const Path
* aPath
, const Pattern
& aPattern
,
320 const StrokeOptions
& aStrokeOptions
,
321 const DrawOptions
& aOptions
) {
322 RefPtr
<PathRecording
> pathRecording
= EnsurePathStored(aPath
);
323 EnsurePatternDependenciesStored(aPattern
);
325 mRecorder
->RecordEvent(
326 RecordedStroke(this, pathRecording
, aPattern
, aStrokeOptions
, aOptions
));
329 already_AddRefed
<SourceSurface
> DrawTargetRecording::Snapshot() {
330 RefPtr
<SourceSurface
> retSurf
=
331 new SourceSurfaceRecording(mRect
.Size(), mFormat
, mRecorder
);
333 mRecorder
->RecordEvent(RecordedSnapshot(retSurf
, this));
335 return retSurf
.forget();
338 already_AddRefed
<SourceSurface
> DrawTargetRecording::IntoLuminanceSource(
339 LuminanceType aLuminanceType
, float aOpacity
) {
340 RefPtr
<SourceSurface
> retSurf
=
341 new SourceSurfaceRecording(mRect
.Size(), SurfaceFormat::A8
, mRecorder
);
343 mRecorder
->RecordEvent(
344 RecordedIntoLuminanceSource(retSurf
, this, aLuminanceType
, aOpacity
));
346 return retSurf
.forget();
349 void DrawTargetRecording::Flush() {
350 mRecorder
->RecordEvent(RecordedFlush(this));
353 void DrawTargetRecording::DetachAllSnapshots() {
354 mRecorder
->RecordEvent(RecordedDetachAllSnapshots(this));
357 void DrawTargetRecording::DrawSurface(SourceSurface
* aSurface
,
358 const Rect
& aDest
, const Rect
& aSource
,
359 const DrawSurfaceOptions
& aSurfOptions
,
360 const DrawOptions
& aOptions
) {
361 EnsureSurfaceStoredRecording(mRecorder
, aSurface
, "DrawSurface");
363 mRecorder
->RecordEvent(RecordedDrawSurface(this, aSurface
, aDest
, aSource
,
364 aSurfOptions
, aOptions
));
367 void DrawTargetRecording::DrawDependentSurface(
368 uint64_t aId
, const Rect
& aDest
, const DrawSurfaceOptions
& aSurfOptions
,
369 const DrawOptions
& aOptions
) {
370 mRecorder
->AddDependentSurface(aId
);
371 mRecorder
->RecordEvent(
372 RecordedDrawDependentSurface(this, aId
, aDest
, aSurfOptions
, aOptions
));
375 void DrawTargetRecording::DrawSurfaceWithShadow(
376 SourceSurface
* aSurface
, const Point
& aDest
, const DeviceColor
& aColor
,
377 const Point
& aOffset
, Float aSigma
, CompositionOp aOp
) {
378 EnsureSurfaceStoredRecording(mRecorder
, aSurface
, "DrawSurfaceWithShadow");
380 mRecorder
->RecordEvent(RecordedDrawSurfaceWithShadow(
381 this, aSurface
, aDest
, aColor
, aOffset
, aSigma
, aOp
));
384 void DrawTargetRecording::DrawFilter(FilterNode
* aNode
, const Rect
& aSourceRect
,
385 const Point
& aDestPoint
,
386 const DrawOptions
& aOptions
) {
387 MOZ_ASSERT(mRecorder
->HasStoredObject(aNode
));
389 mRecorder
->RecordEvent(
390 RecordedDrawFilter(this, aNode
, aSourceRect
, aDestPoint
, aOptions
));
393 already_AddRefed
<FilterNode
> DrawTargetRecording::CreateFilter(
395 RefPtr
<FilterNode
> retNode
= new FilterNodeRecording(mRecorder
);
397 mRecorder
->RecordEvent(RecordedFilterNodeCreation(retNode
, aType
));
399 return retNode
.forget();
402 void DrawTargetRecording::ClearRect(const Rect
& aRect
) {
403 mRecorder
->RecordEvent(RecordedClearRect(this, aRect
));
406 void DrawTargetRecording::CopySurface(SourceSurface
* aSurface
,
407 const IntRect
& aSourceRect
,
408 const IntPoint
& aDestination
) {
409 EnsureSurfaceStoredRecording(mRecorder
, aSurface
, "CopySurface");
411 mRecorder
->RecordEvent(
412 RecordedCopySurface(this, aSurface
, aSourceRect
, aDestination
));
415 void DrawTargetRecording::PushClip(const Path
* aPath
) {
416 RefPtr
<PathRecording
> pathRecording
= EnsurePathStored(aPath
);
418 mRecorder
->RecordEvent(RecordedPushClip(this, pathRecording
));
421 void DrawTargetRecording::PushClipRect(const Rect
& aRect
) {
422 mRecorder
->RecordEvent(RecordedPushClipRect(this, aRect
));
425 void DrawTargetRecording::PopClip() {
426 mRecorder
->RecordEvent(RecordedPopClip(static_cast<DrawTarget
*>(this)));
429 void DrawTargetRecording::PushLayer(bool aOpaque
, Float aOpacity
,
430 SourceSurface
* aMask
,
431 const Matrix
& aMaskTransform
,
432 const IntRect
& aBounds
,
433 bool aCopyBackground
) {
435 EnsureSurfaceStoredRecording(mRecorder
, aMask
, "PushLayer");
438 mRecorder
->RecordEvent(RecordedPushLayer(this, aOpaque
, aOpacity
, aMask
,
439 aMaskTransform
, aBounds
,
443 void DrawTargetRecording::PushLayerWithBlend(bool aOpaque
, Float aOpacity
,
444 SourceSurface
* aMask
,
445 const Matrix
& aMaskTransform
,
446 const IntRect
& aBounds
,
447 bool aCopyBackground
,
448 CompositionOp aCompositionOp
) {
450 EnsureSurfaceStoredRecording(mRecorder
, aMask
, "PushLayer");
453 mRecorder
->RecordEvent(
454 RecordedPushLayerWithBlend(this, aOpaque
, aOpacity
, aMask
, aMaskTransform
,
455 aBounds
, aCopyBackground
, aCompositionOp
));
458 void DrawTargetRecording::PopLayer() {
459 mRecorder
->RecordEvent(RecordedPopLayer(static_cast<DrawTarget
*>(this)));
462 already_AddRefed
<SourceSurface
>
463 DrawTargetRecording::CreateSourceSurfaceFromData(unsigned char* aData
,
464 const IntSize
& aSize
,
466 SurfaceFormat aFormat
) const {
467 RefPtr
<SourceSurface
> surface
= CreateDataSourceSurfaceWithStrideFromData(
468 aSize
, aFormat
, aStride
, aData
, aStride
);
473 return OptimizeSourceSurface(surface
);
476 already_AddRefed
<SourceSurface
> DrawTargetRecording::OptimizeSourceSurface(
477 SourceSurface
* aSurface
) const {
478 if (aSurface
->GetType() == SurfaceType::RECORDING
&&
479 static_cast<SourceSurfaceRecording
*>(aSurface
)->mRecorder
== mRecorder
) {
480 // aSurface is already optimized for our recorder.
481 return do_AddRef(aSurface
);
484 EnsureSurfaceStoredRecording(mRecorder
, aSurface
, "OptimizeSourceSurface");
486 RefPtr
<SourceSurface
> retSurf
= new SourceSurfaceRecording(
487 aSurface
->GetSize(), aSurface
->GetFormat(), mRecorder
, aSurface
);
489 mRecorder
->RecordEvent(
490 RecordedOptimizeSourceSurface(aSurface
, this, retSurf
));
492 return retSurf
.forget();
495 already_AddRefed
<SourceSurface
>
496 DrawTargetRecording::CreateSourceSurfaceFromNativeSurface(
497 const NativeSurface
& aSurface
) const {
502 already_AddRefed
<DrawTarget
>
503 DrawTargetRecording::CreateSimilarDrawTargetWithBacking(
504 const IntSize
& aSize
, SurfaceFormat aFormat
) const {
505 RefPtr
<DrawTarget
> similarDT
;
506 if (mFinalDT
->CanCreateSimilarDrawTarget(aSize
, aFormat
)) {
507 // If the requested similar draw target is too big, then we should try to
508 // rasterize on the content side to avoid duplicating the effort when a
509 // blob image gets tiled. If we fail somehow to produce it, we can fall
510 // back to recording.
511 constexpr int32_t kRasterThreshold
= 256 * 256 * 4;
512 int32_t stride
= aSize
.width
* BytesPerPixel(aFormat
);
513 int32_t surfaceBytes
= aSize
.height
* stride
;
514 if (surfaceBytes
>= kRasterThreshold
) {
515 auto surface
= MakeRefPtr
<SourceSurfaceSharedData
>();
516 if (surface
->Init(aSize
, stride
, aFormat
)) {
517 auto dt
= MakeRefPtr
<DrawTargetSkia
>();
518 if (dt
->Init(std::move(surface
))) {
521 MOZ_ASSERT_UNREACHABLE("Skia should initialize given surface!");
527 return CreateSimilarDrawTarget(aSize
, aFormat
);
530 already_AddRefed
<DrawTarget
> DrawTargetRecording::CreateSimilarDrawTarget(
531 const IntSize
& aSize
, SurfaceFormat aFormat
) const {
532 RefPtr
<DrawTarget
> similarDT
;
533 if (mFinalDT
->CanCreateSimilarDrawTarget(aSize
, aFormat
)) {
535 new DrawTargetRecording(this, IntRect(IntPoint(0, 0), aSize
), aFormat
);
536 mRecorder
->RecordEvent(
537 RecordedCreateSimilarDrawTarget(similarDT
.get(), aSize
, aFormat
));
538 } else if (XRE_IsContentProcess()) {
539 // Crash any content process that calls this function with arguments that
540 // would fail to create a similar draw target. We do this to root out bad
541 // callers. We don't want to crash any important processes though so for
542 // for those we'll just gracefully return nullptr.
544 "Content-process DrawTargetRecording can't create requested similar "
547 return similarDT
.forget();
550 bool DrawTargetRecording::CanCreateSimilarDrawTarget(
551 const IntSize
& aSize
, SurfaceFormat aFormat
) const {
552 return mFinalDT
->CanCreateSimilarDrawTarget(aSize
, aFormat
);
555 RefPtr
<DrawTarget
> DrawTargetRecording::CreateClippedDrawTarget(
556 const Rect
& aBounds
, SurfaceFormat aFormat
) {
557 RefPtr
<DrawTarget
> similarDT
;
558 similarDT
= new DrawTargetRecording(this, mRect
, aFormat
);
559 mRecorder
->RecordEvent(
560 RecordedCreateClippedDrawTarget(this, similarDT
.get(), aBounds
, aFormat
));
561 similarDT
->SetTransform(mTransform
);
565 already_AddRefed
<DrawTarget
>
566 DrawTargetRecording::CreateSimilarDrawTargetForFilter(
567 const IntSize
& aMaxSize
, SurfaceFormat aFormat
, FilterNode
* aFilter
,
568 FilterNode
* aSource
, const Rect
& aSourceRect
, const Point
& aDestPoint
) {
569 RefPtr
<DrawTarget
> similarDT
;
570 if (mFinalDT
->CanCreateSimilarDrawTarget(aMaxSize
, aFormat
)) {
571 similarDT
= new DrawTargetRecording(this, IntRect(IntPoint(0, 0), aMaxSize
),
573 mRecorder
->RecordEvent(RecordedCreateDrawTargetForFilter(
574 this, similarDT
.get(), aMaxSize
, aFormat
, aFilter
, aSource
, aSourceRect
,
576 } else if (XRE_IsContentProcess()) {
577 // See CreateSimilarDrawTarget
579 "Content-process DrawTargetRecording can't create requested clipped "
582 return similarDT
.forget();
585 already_AddRefed
<PathBuilder
> DrawTargetRecording::CreatePathBuilder(
586 FillRule aFillRule
) const {
587 RefPtr
<PathBuilder
> builder
= mFinalDT
->CreatePathBuilder(aFillRule
);
588 return MakeAndAddRef
<PathBuilderRecording
>(builder
, aFillRule
);
591 already_AddRefed
<GradientStops
> DrawTargetRecording::CreateGradientStops(
592 GradientStop
* aStops
, uint32_t aNumStops
, ExtendMode aExtendMode
) const {
593 RefPtr
<GradientStops
> retStops
= new GradientStopsRecording(mRecorder
);
595 mRecorder
->RecordEvent(
596 RecordedGradientStopsCreation(retStops
, aStops
, aNumStops
, aExtendMode
));
598 return retStops
.forget();
601 void DrawTargetRecording::SetTransform(const Matrix
& aTransform
) {
602 mRecorder
->RecordEvent(RecordedSetTransform(this, aTransform
));
603 DrawTarget::SetTransform(aTransform
);
606 already_AddRefed
<PathRecording
> DrawTargetRecording::EnsurePathStored(
608 RefPtr
<PathRecording
> pathRecording
;
609 if (aPath
->GetBackendType() == BackendType::RECORDING
) {
611 const_cast<PathRecording
*>(static_cast<const PathRecording
*>(aPath
));
612 if (mRecorder
->HasStoredObject(aPath
)) {
613 return pathRecording
.forget();
616 MOZ_ASSERT(!mRecorder
->HasStoredObject(aPath
));
617 FillRule fillRule
= aPath
->GetFillRule();
618 RefPtr
<PathBuilder
> builder
= mFinalDT
->CreatePathBuilder(fillRule
);
619 RefPtr
<PathBuilderRecording
> builderRecording
=
620 new PathBuilderRecording(builder
, fillRule
);
621 aPath
->StreamToSink(builderRecording
);
622 pathRecording
= builderRecording
->Finish().downcast
<PathRecording
>();
625 mRecorder
->RecordEvent(RecordedPathCreation(pathRecording
.get()));
626 mRecorder
->AddStoredObject(pathRecording
);
627 pathRecording
->mStoredRecorders
.push_back(mRecorder
);
629 return pathRecording
.forget();
632 // This should only be called on the 'root' DrawTargetRecording.
633 // Calling it on a child DrawTargetRecordings will cause confusion.
634 void DrawTargetRecording::FlushItem(const IntRect
& aBounds
) {
635 mRecorder
->FlushItem(aBounds
);
636 // Reinitialize the recorder (FlushItem will write a new recording header)
637 // Tell the new recording about our draw target
638 // This code should match what happens in the DrawTargetRecording constructor.
639 mRecorder
->RecordEvent(
640 RecordedDrawTargetCreation(this, mFinalDT
->GetBackendType(), mRect
,
641 mFinalDT
->GetFormat(), false, nullptr));
642 // Add the current transform to the new recording
643 mRecorder
->RecordEvent(
644 RecordedSetTransform(this, DrawTarget::GetTransform()));
647 void DrawTargetRecording::EnsurePatternDependenciesStored(
648 const Pattern
& aPattern
) {
649 switch (aPattern
.GetType()) {
650 case PatternType::COLOR
:
651 // No dependencies here.
653 case PatternType::LINEAR_GRADIENT
: {
655 static_cast<const LinearGradientPattern
*>(&aPattern
)->mStops
,
656 mRecorder
->HasStoredObject(
657 static_cast<const LinearGradientPattern
*>(&aPattern
)->mStops
));
660 case PatternType::RADIAL_GRADIENT
: {
662 static_cast<const RadialGradientPattern
*>(&aPattern
)->mStops
,
663 mRecorder
->HasStoredObject(
664 static_cast<const RadialGradientPattern
*>(&aPattern
)->mStops
));
667 case PatternType::CONIC_GRADIENT
: {
669 static_cast<const ConicGradientPattern
*>(&aPattern
)->mStops
,
670 mRecorder
->HasStoredObject(
671 static_cast<const ConicGradientPattern
*>(&aPattern
)->mStops
));
674 case PatternType::SURFACE
: {
675 const SurfacePattern
* pat
= static_cast<const SurfacePattern
*>(&aPattern
);
676 EnsureSurfaceStoredRecording(mRecorder
, pat
->mSurface
,
677 "EnsurePatternDependenciesStored");
684 } // namespace mozilla