Bug 1638136 [wpt PR 23617] - Clipboard API Tests: Move permissions tests to WPT....
[gecko.git] / gfx / 2d / DrawTargetRecording.cpp
blob6a74fa75d792dd0c5e8911b0e6518fe81fd77185
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"
10 #include <stdio.h>
12 #include "Logging.h"
13 #include "Tools.h"
14 #include "Filters.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"
22 namespace mozilla {
23 namespace gfx {
25 struct RecordingSourceSurfaceUserData {
26 void* refPtr;
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));
37 delete userData;
40 static void EnsureSurfaceStoredRecording(DrawEventRecorderPrivate* aRecorder,
41 SourceSurface* aSurface,
42 const char* reason) {
43 if (aRecorder->HasStoredObject(aSurface)) {
44 return;
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 {
59 public:
60 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceRecording, override)
62 SourceSurfaceRecording(IntSize aSize, SurfaceFormat aFormat,
63 DrawEventRecorderPrivate* aRecorder,
64 SourceSurface* aOriginalSurface = nullptr)
65 : mSize(aSize),
66 mFormat(aFormat),
67 mRecorder(aRecorder),
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();
86 return nullptr;
89 IntSize mSize;
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 {
99 public:
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 {
119 public:
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,
180 bool aHasData)
181 : mRecorder(static_cast<DrawEventRecorderPrivate*>(aRecorder)),
182 mFinalDT(aDT),
183 mRect(aRect) {
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) {
194 mFormat = aFormat;
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 {
236 void* refPtr;
237 void* unscaledFont;
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);
249 delete userData;
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));
275 } else {
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);
281 } else {
282 gfxWarning() << "DrawTargetRecording::FillGlyphs failed to serialise "
283 "UnscaledFont";
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(
394 FilterType aType) {
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) {
434 if (aMask) {
435 EnsureSurfaceStoredRecording(mRecorder, aMask, "PushLayer");
438 mRecorder->RecordEvent(RecordedPushLayer(this, aOpaque, aOpacity, aMask,
439 aMaskTransform, aBounds,
440 aCopyBackground));
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) {
449 if (aMask) {
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,
465 int32_t aStride,
466 SurfaceFormat aFormat) const {
467 RefPtr<SourceSurface> surface = CreateDataSourceSurfaceWithStrideFromData(
468 aSize, aFormat, aStride, aData, aStride);
469 if (!surface) {
470 return nullptr;
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 {
498 MOZ_ASSERT(false);
499 return nullptr;
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))) {
519 return dt.forget();
520 } else {
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)) {
534 similarDT =
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.
543 MOZ_CRASH(
544 "Content-process DrawTargetRecording can't create requested similar "
545 "drawtarget");
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);
562 return similarDT;
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),
572 aFormat);
573 mRecorder->RecordEvent(RecordedCreateDrawTargetForFilter(
574 this, similarDT.get(), aMaxSize, aFormat, aFilter, aSource, aSourceRect,
575 aDestPoint));
576 } else if (XRE_IsContentProcess()) {
577 // See CreateSimilarDrawTarget
578 MOZ_CRASH(
579 "Content-process DrawTargetRecording can't create requested clipped "
580 "drawtarget");
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(
607 const Path* aPath) {
608 RefPtr<PathRecording> pathRecording;
609 if (aPath->GetBackendType() == BackendType::RECORDING) {
610 pathRecording =
611 const_cast<PathRecording*>(static_cast<const PathRecording*>(aPath));
612 if (mRecorder->HasStoredObject(aPath)) {
613 return pathRecording.forget();
615 } else {
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.
652 return;
653 case PatternType::LINEAR_GRADIENT: {
654 MOZ_ASSERT_IF(
655 static_cast<const LinearGradientPattern*>(&aPattern)->mStops,
656 mRecorder->HasStoredObject(
657 static_cast<const LinearGradientPattern*>(&aPattern)->mStops));
658 return;
660 case PatternType::RADIAL_GRADIENT: {
661 MOZ_ASSERT_IF(
662 static_cast<const RadialGradientPattern*>(&aPattern)->mStops,
663 mRecorder->HasStoredObject(
664 static_cast<const RadialGradientPattern*>(&aPattern)->mStops));
665 return;
667 case PatternType::CONIC_GRADIENT: {
668 MOZ_ASSERT_IF(
669 static_cast<const ConicGradientPattern*>(&aPattern)->mStops,
670 mRecorder->HasStoredObject(
671 static_cast<const ConicGradientPattern*>(&aPattern)->mStops));
672 return;
674 case PatternType::SURFACE: {
675 const SurfacePattern* pat = static_cast<const SurfacePattern*>(&aPattern);
676 EnsureSurfaceStoredRecording(mRecorder, pat->mSurface,
677 "EnsurePatternDependenciesStored");
678 return;
683 } // namespace gfx
684 } // namespace mozilla