Bug 1638136 [wpt PR 23617] - Clipboard API Tests: Move permissions tests to WPT....
[gecko.git] / gfx / 2d / DrawTargetWrapAndRecord.cpp
blob19c4591638795374a88543474804815c6c031181
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"
9 #include <stdio.h>
11 #include "Logging.h"
12 #include "Tools.h"
13 #include "Filters.h"
14 #include "mozilla/UniquePtr.h"
15 #include "RecordingTypes.h"
16 #include "RecordedEventImpl.h"
18 namespace mozilla {
19 namespace gfx {
21 struct WrapAndRecordSourceSurfaceUserData {
22 void* refPtr;
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));
33 delete userData;
36 static void StoreSourceSurface(DrawEventRecorderPrivate* aRecorder,
37 SourceSurface* aSurface,
38 DataSourceSurface* aDataSurf,
39 const char* reason) {
40 if (!aDataSurf) {
41 gfxWarning() << "Recording failed to record SourceSurface for " << reason;
42 // Insert a bogus source surface.
43 int32_t stride =
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()));
50 } else {
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)) {
61 return;
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 {
78 public:
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 {
107 public:
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) {
130 return aSurface;
133 return static_cast<SourceSurfaceWrapAndRecord*>(aSurface)->mFinalSurface;
136 static GradientStops* GetGradientStops(GradientStops* aStops) {
137 if (aStops->GetBackendType() != BackendType::RECORDING) {
138 return aStops;
141 return static_cast<GradientStopsWrapAndRecord*>(aStops)->mFinalGradientStops;
144 class FilterNodeWrapAndRecord : public FilterNode {
145 public:
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) {
162 gfxWarning()
163 << "Non recording filter node used with recording DrawTarget!";
164 return aNode;
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);
225 ~AdjustedPattern() {
226 if (mPattern) {
227 mPattern->~Pattern();
231 operator Pattern*() {
232 switch (mOrigPattern->GetType()) {
233 case PatternType::COLOR:
234 return mOrigPattern;
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);
240 return mPattern;
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);
248 return mPattern;
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);
257 return mPattern;
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);
266 return mPattern;
268 default:
269 return new (mColPat) ColorPattern(DeviceColor());
272 return mPattern;
275 union {
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;
284 Pattern* mPattern;
287 DrawTargetWrapAndRecord::DrawTargetWrapAndRecord(DrawEventRecorder* aRecorder,
288 DrawTarget* aDT, bool aHasData)
289 : mRecorder(static_cast<DrawEventRecorderPrivate*>(aRecorder)),
290 mFinalDT(aDT) {
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,
329 aOptions);
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,
341 aOptions);
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),
352 aOptions);
355 struct WrapAndRecordFontUserData {
356 void* refPtr;
357 void* unscaledFont;
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);
369 delete userData;
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));
393 } else {
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);
399 } else {
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),
440 aOffset, aOptions);
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(
519 FilterType aType) {
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)));
558 mFinalDT->PopClip();
561 void DrawTargetWrapAndRecord::PushLayer(bool aOpaque, Float aOpacity,
562 SourceSurface* aMask,
563 const Matrix& aMaskTransform,
564 const IntRect& aBounds,
565 bool aCopyBackground) {
566 if (aMask) {
567 EnsureSurfaceStored(mRecorder, aMask, "PushLayer");
570 mRecorder->RecordEvent(RecordedPushLayer(this, aOpaque, aOpacity, aMask,
571 aMaskTransform, aBounds,
572 aCopyBackground));
573 mFinalDT->PushLayer(aOpaque, aOpacity, aMask, aMaskTransform, aBounds,
574 aCopyBackground);
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();
607 if (!dataSurf) {
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);
637 if (!similarDT) {
638 return nullptr;
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));
658 return similarDT;
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(
688 const Path* aPath) {
689 RefPtr<PathRecording> pathWrapAndRecord;
690 if (aPath->GetBackendType() == BackendType::RECORDING) {
691 pathWrapAndRecord =
692 const_cast<PathRecording*>(static_cast<const PathRecording*>(aPath));
693 if (mRecorder->HasStoredObject(aPath)) {
694 return pathWrapAndRecord.forget();
696 } else {
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);
703 pathWrapAndRecord =
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.
719 return;
720 case PatternType::LINEAR_GRADIENT: {
721 MOZ_ASSERT(mRecorder->HasStoredObject(
722 static_cast<const LinearGradientPattern*>(&aPattern)->mStops));
723 return;
725 case PatternType::RADIAL_GRADIENT: {
726 MOZ_ASSERT(mRecorder->HasStoredObject(
727 static_cast<const RadialGradientPattern*>(&aPattern)->mStops));
728 return;
730 case PatternType::CONIC_GRADIENT: {
731 MOZ_ASSERT(mRecorder->HasStoredObject(
732 static_cast<const ConicGradientPattern*>(&aPattern)->mStops));
733 return;
735 case PatternType::SURFACE: {
736 const SurfacePattern* pat = static_cast<const SurfacePattern*>(&aPattern);
737 EnsureSurfaceStored(mRecorder, pat->mSurface,
738 "EnsurePatternDependenciesStored");
739 return;
744 } // namespace gfx
745 } // namespace mozilla