Bug 1758688 [wpt PR 33067] - [FedCM] Make revoke a non-static method, a=testonly
[gecko.git] / gfx / 2d / DrawTargetRecording.cpp
blob3eb72e3016497e25ea24723005825faedea4a8a7
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::Link(const char* aDestination, const Rect& aRect) {
202 mRecorder->RecordEvent(RecordedLink(this, aDestination, aRect));
205 void DrawTargetRecording::Destination(const char* aDestination,
206 const Point& aPoint) {
207 mRecorder->RecordEvent(RecordedDestination(this, aDestination, aPoint));
210 void DrawTargetRecording::FillRect(const Rect& aRect, const Pattern& aPattern,
211 const DrawOptions& aOptions) {
212 EnsurePatternDependenciesStored(aPattern);
214 mRecorder->RecordEvent(RecordedFillRect(this, aRect, aPattern, aOptions));
217 void DrawTargetRecording::StrokeRect(const Rect& aRect, const Pattern& aPattern,
218 const StrokeOptions& aStrokeOptions,
219 const DrawOptions& aOptions) {
220 EnsurePatternDependenciesStored(aPattern);
222 mRecorder->RecordEvent(
223 RecordedStrokeRect(this, aRect, aPattern, aStrokeOptions, aOptions));
226 void DrawTargetRecording::StrokeLine(const Point& aBegin, const Point& aEnd,
227 const Pattern& aPattern,
228 const StrokeOptions& aStrokeOptions,
229 const DrawOptions& aOptions) {
230 EnsurePatternDependenciesStored(aPattern);
232 mRecorder->RecordEvent(RecordedStrokeLine(this, aBegin, aEnd, aPattern,
233 aStrokeOptions, aOptions));
236 void DrawTargetRecording::Fill(const Path* aPath, const Pattern& aPattern,
237 const DrawOptions& aOptions) {
238 RefPtr<PathRecording> pathRecording = EnsurePathStored(aPath);
239 EnsurePatternDependenciesStored(aPattern);
241 mRecorder->RecordEvent(RecordedFill(this, pathRecording, aPattern, aOptions));
244 struct RecordingFontUserData {
245 void* refPtr;
246 void* unscaledFont;
247 RefPtr<DrawEventRecorderPrivate> recorder;
250 static void RecordingFontUserDataDestroyFunc(void* aUserData) {
251 RecordingFontUserData* userData =
252 static_cast<RecordingFontUserData*>(aUserData);
254 userData->recorder->RecordEvent(
255 RecordedScaledFontDestruction(ReferencePtr(userData->refPtr)));
256 userData->recorder->RemoveScaledFont((ScaledFont*)userData->refPtr);
257 userData->recorder->DecrementUnscaledFontRefCount(userData->unscaledFont);
258 delete userData;
261 void DrawTargetRecording::FillGlyphs(ScaledFont* aFont,
262 const GlyphBuffer& aBuffer,
263 const Pattern& aPattern,
264 const DrawOptions& aOptions) {
265 EnsurePatternDependenciesStored(aPattern);
267 UserDataKey* userDataKey = reinterpret_cast<UserDataKey*>(mRecorder.get());
268 if (mRecorder->WantsExternalFonts()) {
269 mRecorder->AddScaledFont(aFont);
270 } else if (!aFont->GetUserData(userDataKey)) {
271 UnscaledFont* unscaledFont = aFont->GetUnscaledFont();
272 if (mRecorder->IncrementUnscaledFontRefCount(unscaledFont) == 0) {
273 // Prefer sending the description, if we can create one. This ensures
274 // we don't record the data of system fonts which saves time and can
275 // prevent duplicate copies from accumulating in the OS cache during
276 // playback.
277 RecordedFontDescriptor fontDesc(unscaledFont);
278 if (fontDesc.IsValid()) {
279 mRecorder->RecordEvent(fontDesc);
280 } else {
281 RecordedFontData fontData(unscaledFont);
282 RecordedFontDetails fontDetails;
283 if (fontData.GetFontDetails(fontDetails)) {
284 // Try to serialise the whole font, just in case this is a web font
285 // that is not present on the system.
286 if (!mRecorder->HasStoredFontData(fontDetails.fontDataKey)) {
287 mRecorder->RecordEvent(fontData);
288 mRecorder->AddStoredFontData(fontDetails.fontDataKey);
290 mRecorder->RecordEvent(
291 RecordedUnscaledFontCreation(unscaledFont, fontDetails));
292 } else {
293 gfxWarning() << "DrawTargetRecording::FillGlyphs failed to serialise "
294 "UnscaledFont";
298 mRecorder->RecordEvent(RecordedScaledFontCreation(aFont, unscaledFont));
299 RecordingFontUserData* userData = new RecordingFontUserData;
300 userData->refPtr = aFont;
301 userData->unscaledFont = unscaledFont;
302 userData->recorder = mRecorder;
303 aFont->AddUserData(userDataKey, userData,
304 &RecordingFontUserDataDestroyFunc);
305 userData->recorder->AddScaledFont(aFont);
308 mRecorder->RecordEvent(RecordedFillGlyphs(
309 this, aFont, aPattern, aOptions, aBuffer.mGlyphs, aBuffer.mNumGlyphs));
312 void DrawTargetRecording::Mask(const Pattern& aSource, const Pattern& aMask,
313 const DrawOptions& aOptions) {
314 EnsurePatternDependenciesStored(aSource);
315 EnsurePatternDependenciesStored(aMask);
317 mRecorder->RecordEvent(RecordedMask(this, aSource, aMask, aOptions));
320 void DrawTargetRecording::MaskSurface(const Pattern& aSource,
321 SourceSurface* aMask, Point aOffset,
322 const DrawOptions& aOptions) {
323 EnsurePatternDependenciesStored(aSource);
324 EnsureSurfaceStoredRecording(mRecorder, aMask, "MaskSurface");
326 mRecorder->RecordEvent(
327 RecordedMaskSurface(this, aSource, aMask, aOffset, aOptions));
330 void DrawTargetRecording::Stroke(const Path* aPath, const Pattern& aPattern,
331 const StrokeOptions& aStrokeOptions,
332 const DrawOptions& aOptions) {
333 RefPtr<PathRecording> pathRecording = EnsurePathStored(aPath);
334 EnsurePatternDependenciesStored(aPattern);
336 mRecorder->RecordEvent(
337 RecordedStroke(this, pathRecording, aPattern, aStrokeOptions, aOptions));
340 already_AddRefed<SourceSurface> DrawTargetRecording::Snapshot() {
341 RefPtr<SourceSurface> retSurf =
342 new SourceSurfaceRecording(mRect.Size(), mFormat, mRecorder);
344 mRecorder->RecordEvent(RecordedSnapshot(retSurf, this));
346 return retSurf.forget();
349 already_AddRefed<SourceSurface> DrawTargetRecording::IntoLuminanceSource(
350 LuminanceType aLuminanceType, float aOpacity) {
351 RefPtr<SourceSurface> retSurf =
352 new SourceSurfaceRecording(mRect.Size(), SurfaceFormat::A8, mRecorder);
354 mRecorder->RecordEvent(
355 RecordedIntoLuminanceSource(retSurf, this, aLuminanceType, aOpacity));
357 return retSurf.forget();
360 void DrawTargetRecording::Flush() {
361 mRecorder->RecordEvent(RecordedFlush(this));
364 void DrawTargetRecording::DetachAllSnapshots() {
365 mRecorder->RecordEvent(RecordedDetachAllSnapshots(this));
368 void DrawTargetRecording::DrawSurface(SourceSurface* aSurface,
369 const Rect& aDest, const Rect& aSource,
370 const DrawSurfaceOptions& aSurfOptions,
371 const DrawOptions& aOptions) {
372 EnsureSurfaceStoredRecording(mRecorder, aSurface, "DrawSurface");
374 mRecorder->RecordEvent(RecordedDrawSurface(this, aSurface, aDest, aSource,
375 aSurfOptions, aOptions));
378 void DrawTargetRecording::DrawDependentSurface(uint64_t aId,
379 const Rect& aDest) {
380 mRecorder->AddDependentSurface(aId);
381 mRecorder->RecordEvent(RecordedDrawDependentSurface(this, aId, aDest));
384 void DrawTargetRecording::DrawSurfaceWithShadow(
385 SourceSurface* aSurface, const Point& aDest, const DeviceColor& aColor,
386 const Point& aOffset, Float aSigma, CompositionOp aOp) {
387 EnsureSurfaceStoredRecording(mRecorder, aSurface, "DrawSurfaceWithShadow");
389 mRecorder->RecordEvent(RecordedDrawSurfaceWithShadow(
390 this, aSurface, aDest, aColor, aOffset, aSigma, aOp));
393 void DrawTargetRecording::DrawFilter(FilterNode* aNode, const Rect& aSourceRect,
394 const Point& aDestPoint,
395 const DrawOptions& aOptions) {
396 MOZ_ASSERT(mRecorder->HasStoredObject(aNode));
398 mRecorder->RecordEvent(
399 RecordedDrawFilter(this, aNode, aSourceRect, aDestPoint, aOptions));
402 already_AddRefed<FilterNode> DrawTargetRecording::CreateFilter(
403 FilterType aType) {
404 RefPtr<FilterNode> retNode = new FilterNodeRecording(mRecorder);
406 mRecorder->RecordEvent(RecordedFilterNodeCreation(retNode, aType));
408 return retNode.forget();
411 void DrawTargetRecording::ClearRect(const Rect& aRect) {
412 mRecorder->RecordEvent(RecordedClearRect(this, aRect));
415 void DrawTargetRecording::CopySurface(SourceSurface* aSurface,
416 const IntRect& aSourceRect,
417 const IntPoint& aDestination) {
418 EnsureSurfaceStoredRecording(mRecorder, aSurface, "CopySurface");
420 mRecorder->RecordEvent(
421 RecordedCopySurface(this, aSurface, aSourceRect, aDestination));
424 void DrawTargetRecording::PushClip(const Path* aPath) {
425 RefPtr<PathRecording> pathRecording = EnsurePathStored(aPath);
427 mRecorder->RecordEvent(RecordedPushClip(this, pathRecording));
430 void DrawTargetRecording::PushClipRect(const Rect& aRect) {
431 mRecorder->RecordEvent(RecordedPushClipRect(this, aRect));
434 void DrawTargetRecording::PopClip() {
435 mRecorder->RecordEvent(RecordedPopClip(static_cast<DrawTarget*>(this)));
438 void DrawTargetRecording::PushLayer(bool aOpaque, Float aOpacity,
439 SourceSurface* aMask,
440 const Matrix& aMaskTransform,
441 const IntRect& aBounds,
442 bool aCopyBackground) {
443 if (aMask) {
444 EnsureSurfaceStoredRecording(mRecorder, aMask, "PushLayer");
447 mRecorder->RecordEvent(RecordedPushLayer(this, aOpaque, aOpacity, aMask,
448 aMaskTransform, aBounds,
449 aCopyBackground));
452 void DrawTargetRecording::PushLayerWithBlend(bool aOpaque, Float aOpacity,
453 SourceSurface* aMask,
454 const Matrix& aMaskTransform,
455 const IntRect& aBounds,
456 bool aCopyBackground,
457 CompositionOp aCompositionOp) {
458 if (aMask) {
459 EnsureSurfaceStoredRecording(mRecorder, aMask, "PushLayer");
462 mRecorder->RecordEvent(
463 RecordedPushLayerWithBlend(this, aOpaque, aOpacity, aMask, aMaskTransform,
464 aBounds, aCopyBackground, aCompositionOp));
467 void DrawTargetRecording::PopLayer() {
468 mRecorder->RecordEvent(RecordedPopLayer(static_cast<DrawTarget*>(this)));
471 already_AddRefed<SourceSurface>
472 DrawTargetRecording::CreateSourceSurfaceFromData(unsigned char* aData,
473 const IntSize& aSize,
474 int32_t aStride,
475 SurfaceFormat aFormat) const {
476 RefPtr<SourceSurface> surface = CreateDataSourceSurfaceWithStrideFromData(
477 aSize, aFormat, aStride, aData, aStride);
478 if (!surface) {
479 return nullptr;
482 return OptimizeSourceSurface(surface);
485 already_AddRefed<SourceSurface> DrawTargetRecording::OptimizeSourceSurface(
486 SourceSurface* aSurface) const {
487 if (aSurface->GetType() == SurfaceType::RECORDING &&
488 static_cast<SourceSurfaceRecording*>(aSurface)->mRecorder == mRecorder) {
489 // aSurface is already optimized for our recorder.
490 return do_AddRef(aSurface);
493 EnsureSurfaceStoredRecording(mRecorder, aSurface, "OptimizeSourceSurface");
495 RefPtr<SourceSurface> retSurf = new SourceSurfaceRecording(
496 aSurface->GetSize(), aSurface->GetFormat(), mRecorder, aSurface);
498 mRecorder->RecordEvent(
499 RecordedOptimizeSourceSurface(aSurface, this, retSurf));
501 return retSurf.forget();
504 already_AddRefed<SourceSurface>
505 DrawTargetRecording::CreateSourceSurfaceFromNativeSurface(
506 const NativeSurface& aSurface) const {
507 MOZ_ASSERT(false);
508 return nullptr;
511 already_AddRefed<DrawTarget>
512 DrawTargetRecording::CreateSimilarDrawTargetWithBacking(
513 const IntSize& aSize, SurfaceFormat aFormat) const {
514 RefPtr<DrawTarget> similarDT;
515 if (mFinalDT->CanCreateSimilarDrawTarget(aSize, aFormat)) {
516 // If the requested similar draw target is too big, then we should try to
517 // rasterize on the content side to avoid duplicating the effort when a
518 // blob image gets tiled. If we fail somehow to produce it, we can fall
519 // back to recording.
520 constexpr int32_t kRasterThreshold = 256 * 256 * 4;
521 int32_t stride = aSize.width * BytesPerPixel(aFormat);
522 int32_t surfaceBytes = aSize.height * stride;
523 if (surfaceBytes >= kRasterThreshold) {
524 auto surface = MakeRefPtr<SourceSurfaceSharedData>();
525 if (surface->Init(aSize, stride, aFormat)) {
526 auto dt = MakeRefPtr<DrawTargetSkia>();
527 if (dt->Init(std::move(surface))) {
528 return dt.forget();
529 } else {
530 MOZ_ASSERT_UNREACHABLE("Skia should initialize given surface!");
536 return CreateSimilarDrawTarget(aSize, aFormat);
539 already_AddRefed<DrawTarget> DrawTargetRecording::CreateSimilarDrawTarget(
540 const IntSize& aSize, SurfaceFormat aFormat) const {
541 RefPtr<DrawTarget> similarDT;
542 if (mFinalDT->CanCreateSimilarDrawTarget(aSize, aFormat)) {
543 similarDT =
544 new DrawTargetRecording(this, IntRect(IntPoint(0, 0), aSize), aFormat);
545 mRecorder->RecordEvent(
546 RecordedCreateSimilarDrawTarget(similarDT.get(), aSize, aFormat));
547 } else if (XRE_IsContentProcess()) {
548 // Crash any content process that calls this function with arguments that
549 // would fail to create a similar draw target. We do this to root out bad
550 // callers. We don't want to crash any important processes though so for
551 // for those we'll just gracefully return nullptr.
552 MOZ_CRASH(
553 "Content-process DrawTargetRecording can't create requested similar "
554 "drawtarget");
556 return similarDT.forget();
559 bool DrawTargetRecording::CanCreateSimilarDrawTarget(
560 const IntSize& aSize, SurfaceFormat aFormat) const {
561 return mFinalDT->CanCreateSimilarDrawTarget(aSize, aFormat);
564 RefPtr<DrawTarget> DrawTargetRecording::CreateClippedDrawTarget(
565 const Rect& aBounds, SurfaceFormat aFormat) {
566 RefPtr<DrawTarget> similarDT;
567 similarDT = new DrawTargetRecording(this, mRect, aFormat);
568 mRecorder->RecordEvent(
569 RecordedCreateClippedDrawTarget(this, similarDT.get(), aBounds, aFormat));
570 similarDT->SetTransform(mTransform);
571 return similarDT;
574 already_AddRefed<DrawTarget>
575 DrawTargetRecording::CreateSimilarDrawTargetForFilter(
576 const IntSize& aMaxSize, SurfaceFormat aFormat, FilterNode* aFilter,
577 FilterNode* aSource, const Rect& aSourceRect, const Point& aDestPoint) {
578 RefPtr<DrawTarget> similarDT;
579 if (mFinalDT->CanCreateSimilarDrawTarget(aMaxSize, aFormat)) {
580 similarDT = new DrawTargetRecording(this, IntRect(IntPoint(0, 0), aMaxSize),
581 aFormat);
582 mRecorder->RecordEvent(RecordedCreateDrawTargetForFilter(
583 this, similarDT.get(), aMaxSize, aFormat, aFilter, aSource, aSourceRect,
584 aDestPoint));
585 } else if (XRE_IsContentProcess()) {
586 // See CreateSimilarDrawTarget
587 MOZ_CRASH(
588 "Content-process DrawTargetRecording can't create requested clipped "
589 "drawtarget");
591 return similarDT.forget();
594 already_AddRefed<PathBuilder> DrawTargetRecording::CreatePathBuilder(
595 FillRule aFillRule) const {
596 RefPtr<PathBuilder> builder = mFinalDT->CreatePathBuilder(aFillRule);
597 return MakeAndAddRef<PathBuilderRecording>(builder, aFillRule);
600 already_AddRefed<GradientStops> DrawTargetRecording::CreateGradientStops(
601 GradientStop* aStops, uint32_t aNumStops, ExtendMode aExtendMode) const {
602 RefPtr<GradientStops> retStops = new GradientStopsRecording(mRecorder);
604 mRecorder->RecordEvent(
605 RecordedGradientStopsCreation(retStops, aStops, aNumStops, aExtendMode));
607 return retStops.forget();
610 void DrawTargetRecording::SetTransform(const Matrix& aTransform) {
611 mRecorder->RecordEvent(RecordedSetTransform(this, aTransform));
612 DrawTarget::SetTransform(aTransform);
615 already_AddRefed<PathRecording> DrawTargetRecording::EnsurePathStored(
616 const Path* aPath) {
617 RefPtr<PathRecording> pathRecording;
618 if (aPath->GetBackendType() == BackendType::RECORDING) {
619 pathRecording =
620 const_cast<PathRecording*>(static_cast<const PathRecording*>(aPath));
621 if (mRecorder->HasStoredObject(aPath)) {
622 return pathRecording.forget();
624 } else {
625 MOZ_ASSERT(!mRecorder->HasStoredObject(aPath));
626 FillRule fillRule = aPath->GetFillRule();
627 RefPtr<PathBuilder> builder = mFinalDT->CreatePathBuilder(fillRule);
628 RefPtr<PathBuilderRecording> builderRecording =
629 new PathBuilderRecording(builder, fillRule);
630 aPath->StreamToSink(builderRecording);
631 pathRecording = builderRecording->Finish().downcast<PathRecording>();
634 mRecorder->RecordEvent(RecordedPathCreation(pathRecording.get()));
635 mRecorder->AddStoredObject(pathRecording);
636 pathRecording->mStoredRecorders.push_back(mRecorder);
638 return pathRecording.forget();
641 // This should only be called on the 'root' DrawTargetRecording.
642 // Calling it on a child DrawTargetRecordings will cause confusion.
643 void DrawTargetRecording::FlushItem(const IntRect& aBounds) {
644 mRecorder->FlushItem(aBounds);
645 // Reinitialize the recorder (FlushItem will write a new recording header)
646 // Tell the new recording about our draw target
647 // This code should match what happens in the DrawTargetRecording constructor.
648 mRecorder->RecordEvent(
649 RecordedDrawTargetCreation(this, mFinalDT->GetBackendType(), mRect,
650 mFinalDT->GetFormat(), false, nullptr));
651 // Add the current transform to the new recording
652 mRecorder->RecordEvent(
653 RecordedSetTransform(this, DrawTarget::GetTransform()));
656 void DrawTargetRecording::EnsurePatternDependenciesStored(
657 const Pattern& aPattern) {
658 switch (aPattern.GetType()) {
659 case PatternType::COLOR:
660 // No dependencies here.
661 return;
662 case PatternType::LINEAR_GRADIENT: {
663 MOZ_ASSERT_IF(
664 static_cast<const LinearGradientPattern*>(&aPattern)->mStops,
665 mRecorder->HasStoredObject(
666 static_cast<const LinearGradientPattern*>(&aPattern)->mStops));
667 return;
669 case PatternType::RADIAL_GRADIENT: {
670 MOZ_ASSERT_IF(
671 static_cast<const RadialGradientPattern*>(&aPattern)->mStops,
672 mRecorder->HasStoredObject(
673 static_cast<const RadialGradientPattern*>(&aPattern)->mStops));
674 return;
676 case PatternType::CONIC_GRADIENT: {
677 MOZ_ASSERT_IF(
678 static_cast<const ConicGradientPattern*>(&aPattern)->mStops,
679 mRecorder->HasStoredObject(
680 static_cast<const ConicGradientPattern*>(&aPattern)->mStops));
681 return;
683 case PatternType::SURFACE: {
684 const SurfacePattern* pat = static_cast<const SurfacePattern*>(&aPattern);
685 EnsureSurfaceStoredRecording(mRecorder, pat->mSurface,
686 "EnsurePatternDependenciesStored");
687 return;
692 } // namespace gfx
693 } // namespace mozilla