Line data Source code
1 : /* -*- Mode: C++; tab-width: 20; 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/. */
6 :
7 : #include "DrawTargetWrapAndRecord.h"
8 : #include "PathRecording.h"
9 : #include <stdio.h>
10 :
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"
17 :
18 : namespace mozilla {
19 : namespace gfx {
20 :
21 0 : struct WrapAndRecordSourceSurfaceUserData
22 : {
23 : void *refPtr;
24 : RefPtr<DrawEventRecorderPrivate> recorder;
25 : };
26 :
27 0 : void WrapAndRecordSourceSurfaceUserDataFunc(void *aUserData)
28 : {
29 : WrapAndRecordSourceSurfaceUserData *userData =
30 0 : static_cast<WrapAndRecordSourceSurfaceUserData*>(aUserData);
31 :
32 0 : userData->recorder->RemoveSourceSurface((SourceSurface*)userData->refPtr);
33 0 : userData->recorder->RemoveStoredObject(userData->refPtr);
34 0 : userData->recorder->RecordEvent(
35 0 : RecordedSourceSurfaceDestruction(ReferencePtr(userData->refPtr)));
36 :
37 0 : delete userData;
38 0 : }
39 :
40 : static void
41 0 : StoreSourceSurface(DrawEventRecorderPrivate *aRecorder, SourceSurface *aSurface,
42 : DataSourceSurface *aDataSurf, const char *reason)
43 : {
44 0 : if (!aDataSurf) {
45 0 : gfxWarning() << "Recording failed to record SourceSurface for " << reason;
46 : // Insert a bogus source surface.
47 0 : int32_t stride = aSurface->GetSize().width * BytesPerPixel(aSurface->GetFormat());
48 0 : UniquePtr<uint8_t[]> sourceData(new uint8_t[stride * aSurface->GetSize().height]());
49 : aRecorder->RecordEvent(
50 0 : RecordedSourceSurfaceCreation(aSurface, sourceData.get(), stride,
51 0 : aSurface->GetSize(), aSurface->GetFormat()));
52 : } else {
53 0 : DataSourceSurface::ScopedMap map(aDataSurf, DataSourceSurface::READ);
54 : aRecorder->RecordEvent(
55 0 : RecordedSourceSurfaceCreation(aSurface, map.GetData(), map.GetStride(),
56 0 : aDataSurf->GetSize(), aDataSurf->GetFormat()));
57 : }
58 0 : }
59 :
60 : static void
61 0 : EnsureSurfaceStored(DrawEventRecorderPrivate *aRecorder, SourceSurface *aSurface,
62 : const char *reason)
63 : {
64 0 : if (aRecorder->HasStoredObject(aSurface)) {
65 0 : return;
66 : }
67 :
68 0 : RefPtr<DataSourceSurface> dataSurf = aSurface->GetDataSurface();
69 0 : StoreSourceSurface(aRecorder, aSurface, dataSurf, reason);
70 0 : aRecorder->AddStoredObject(aSurface);
71 0 : aRecorder->AddSourceSurface(aSurface);
72 :
73 0 : WrapAndRecordSourceSurfaceUserData *userData = new WrapAndRecordSourceSurfaceUserData;
74 0 : userData->refPtr = aSurface;
75 0 : userData->recorder = aRecorder;
76 : aSurface->AddUserData(reinterpret_cast<UserDataKey*>(aRecorder),
77 0 : userData, &WrapAndRecordSourceSurfaceUserDataFunc);
78 0 : return;
79 : }
80 :
81 : class SourceSurfaceWrapAndRecord : public SourceSurface
82 : {
83 : public:
84 0 : MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceWrapAndRecord)
85 0 : SourceSurfaceWrapAndRecord(SourceSurface *aFinalSurface, DrawEventRecorderPrivate *aRecorder)
86 0 : : mFinalSurface(aFinalSurface), mRecorder(aRecorder)
87 : {
88 0 : mRecorder->AddStoredObject(this);
89 0 : }
90 :
91 0 : ~SourceSurfaceWrapAndRecord()
92 0 : {
93 0 : mRecorder->RemoveStoredObject(this);
94 0 : mRecorder->RecordEvent(RecordedSourceSurfaceDestruction(ReferencePtr(this)));
95 0 : }
96 :
97 0 : virtual SurfaceType GetType() const { return SurfaceType::RECORDING; }
98 0 : virtual IntSize GetSize() const { return mFinalSurface->GetSize(); }
99 0 : virtual SurfaceFormat GetFormat() const { return mFinalSurface->GetFormat(); }
100 0 : virtual already_AddRefed<DataSourceSurface> GetDataSurface() { return mFinalSurface->GetDataSurface(); }
101 :
102 : RefPtr<SourceSurface> mFinalSurface;
103 : RefPtr<DrawEventRecorderPrivate> mRecorder;
104 : };
105 :
106 : class GradientStopsWrapAndRecord : public GradientStops
107 : {
108 : public:
109 0 : MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStopsWrapAndRecord)
110 0 : GradientStopsWrapAndRecord(GradientStops *aFinalGradientStops, DrawEventRecorderPrivate *aRecorder)
111 0 : : mFinalGradientStops(aFinalGradientStops), mRecorder(aRecorder)
112 : {
113 0 : mRecorder->AddStoredObject(this);
114 0 : }
115 :
116 0 : ~GradientStopsWrapAndRecord()
117 0 : {
118 0 : mRecorder->RemoveStoredObject(this);
119 0 : mRecorder->RecordEvent(RecordedGradientStopsDestruction(ReferencePtr(this)));
120 0 : }
121 :
122 0 : virtual BackendType GetBackendType() const { return BackendType::RECORDING; }
123 :
124 : RefPtr<GradientStops> mFinalGradientStops;
125 : RefPtr<DrawEventRecorderPrivate> mRecorder;
126 : };
127 :
128 : static SourceSurface *
129 0 : GetSourceSurface(SourceSurface *aSurface)
130 : {
131 0 : if (aSurface->GetType() != SurfaceType::RECORDING) {
132 0 : return aSurface;
133 : }
134 :
135 0 : return static_cast<SourceSurfaceWrapAndRecord*>(aSurface)->mFinalSurface;
136 : }
137 :
138 : static GradientStops *
139 0 : GetGradientStops(GradientStops *aStops)
140 : {
141 0 : if (aStops->GetBackendType() != BackendType::RECORDING) {
142 0 : return aStops;
143 : }
144 :
145 0 : return static_cast<GradientStopsWrapAndRecord*>(aStops)->mFinalGradientStops;
146 : }
147 :
148 : class FilterNodeWrapAndRecord : public FilterNode
149 : {
150 : public:
151 0 : MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeWrapAndRecord, override)
152 : using FilterNode::SetAttribute;
153 :
154 0 : FilterNodeWrapAndRecord(FilterNode *aFinalFilterNode, DrawEventRecorderPrivate *aRecorder)
155 0 : : mFinalFilterNode(aFinalFilterNode), mRecorder(aRecorder)
156 : {
157 0 : mRecorder->AddStoredObject(this);
158 0 : }
159 :
160 0 : ~FilterNodeWrapAndRecord()
161 0 : {
162 0 : mRecorder->RemoveStoredObject(this);
163 0 : mRecorder->RecordEvent(RecordedFilterNodeDestruction(ReferencePtr(this)));
164 0 : }
165 :
166 : static FilterNode*
167 0 : GetFilterNode(FilterNode* aNode)
168 : {
169 0 : if (aNode->GetBackendType() != FILTER_BACKEND_RECORDING) {
170 0 : gfxWarning() << "Non recording filter node used with recording DrawTarget!";
171 0 : return aNode;
172 : }
173 :
174 0 : return static_cast<FilterNodeWrapAndRecord*>(aNode)->mFinalFilterNode;
175 : }
176 :
177 0 : virtual void SetInput(uint32_t aIndex, SourceSurface *aSurface) override
178 : {
179 0 : EnsureSurfaceStored(mRecorder, aSurface, "SetInput");
180 :
181 0 : mRecorder->RecordEvent(RecordedFilterNodeSetInput(this, aIndex, aSurface));
182 0 : mFinalFilterNode->SetInput(aIndex, GetSourceSurface(aSurface));
183 0 : }
184 0 : virtual void SetInput(uint32_t aIndex, FilterNode *aFilter) override
185 : {
186 0 : MOZ_ASSERT(mRecorder->HasStoredObject(aFilter));
187 :
188 0 : mRecorder->RecordEvent(RecordedFilterNodeSetInput(this, aIndex, aFilter));
189 0 : mFinalFilterNode->SetInput(aIndex, GetFilterNode(aFilter));
190 0 : }
191 :
192 :
193 : #define FORWARD_SET_ATTRIBUTE(type, argtype) \
194 : virtual void SetAttribute(uint32_t aIndex, type aValue) override { \
195 : mRecorder->RecordEvent(RecordedFilterNodeSetAttribute(this, aIndex, aValue, RecordedFilterNodeSetAttribute::ARGTYPE_##argtype)); \
196 : mFinalFilterNode->SetAttribute(aIndex, aValue); \
197 : }
198 :
199 0 : FORWARD_SET_ATTRIBUTE(bool, BOOL);
200 0 : FORWARD_SET_ATTRIBUTE(uint32_t, UINT32);
201 0 : FORWARD_SET_ATTRIBUTE(Float, FLOAT);
202 0 : FORWARD_SET_ATTRIBUTE(const Size&, SIZE);
203 0 : FORWARD_SET_ATTRIBUTE(const IntSize&, INTSIZE);
204 0 : FORWARD_SET_ATTRIBUTE(const IntPoint&, INTPOINT);
205 0 : FORWARD_SET_ATTRIBUTE(const Rect&, RECT);
206 0 : FORWARD_SET_ATTRIBUTE(const IntRect&, INTRECT);
207 0 : FORWARD_SET_ATTRIBUTE(const Point&, POINT);
208 0 : FORWARD_SET_ATTRIBUTE(const Matrix&, MATRIX);
209 0 : FORWARD_SET_ATTRIBUTE(const Matrix5x4&, MATRIX5X4);
210 0 : FORWARD_SET_ATTRIBUTE(const Point3D&, POINT3D);
211 0 : FORWARD_SET_ATTRIBUTE(const Color&, COLOR);
212 :
213 : #undef FORWARD_SET_ATTRIBUTE
214 :
215 0 : virtual void SetAttribute(uint32_t aIndex, const Float* aFloat, uint32_t aSize) override {
216 0 : mRecorder->RecordEvent(RecordedFilterNodeSetAttribute(this, aIndex, aFloat, aSize));
217 0 : mFinalFilterNode->SetAttribute(aIndex, aFloat, aSize);
218 0 : }
219 :
220 0 : virtual FilterBackend GetBackendType() override { return FILTER_BACKEND_RECORDING; }
221 :
222 : RefPtr<FilterNode> mFinalFilterNode;
223 : RefPtr<DrawEventRecorderPrivate> mRecorder;
224 : };
225 :
226 : struct AdjustedPattern
227 : {
228 0 : explicit AdjustedPattern(const Pattern &aPattern)
229 0 : : mPattern(nullptr)
230 : {
231 0 : mOrigPattern = const_cast<Pattern*>(&aPattern);
232 0 : }
233 :
234 0 : ~AdjustedPattern() {
235 0 : if (mPattern) {
236 0 : mPattern->~Pattern();
237 : }
238 0 : }
239 :
240 0 : operator Pattern*()
241 : {
242 0 : switch(mOrigPattern->GetType()) {
243 : case PatternType::COLOR:
244 0 : return mOrigPattern;
245 : case PatternType::SURFACE:
246 : {
247 0 : SurfacePattern *surfPat = static_cast<SurfacePattern*>(mOrigPattern);
248 0 : mPattern =
249 0 : new (mSurfPat) SurfacePattern(GetSourceSurface(surfPat->mSurface),
250 : surfPat->mExtendMode, surfPat->mMatrix,
251 : surfPat->mSamplingFilter,
252 0 : surfPat->mSamplingRect);
253 0 : return mPattern;
254 : }
255 : case PatternType::LINEAR_GRADIENT:
256 : {
257 0 : LinearGradientPattern *linGradPat = static_cast<LinearGradientPattern*>(mOrigPattern);
258 0 : mPattern =
259 0 : new (mLinGradPat) LinearGradientPattern(linGradPat->mBegin, linGradPat->mEnd,
260 0 : GetGradientStops(linGradPat->mStops),
261 0 : linGradPat->mMatrix);
262 0 : return mPattern;
263 : }
264 : case PatternType::RADIAL_GRADIENT:
265 : {
266 0 : RadialGradientPattern *radGradPat = static_cast<RadialGradientPattern*>(mOrigPattern);
267 0 : mPattern =
268 0 : new (mRadGradPat) RadialGradientPattern(radGradPat->mCenter1, radGradPat->mCenter2,
269 : radGradPat->mRadius1, radGradPat->mRadius2,
270 0 : GetGradientStops(radGradPat->mStops),
271 0 : radGradPat->mMatrix);
272 0 : return mPattern;
273 : }
274 : default:
275 0 : return new (mColPat) ColorPattern(Color());
276 : }
277 :
278 : return mPattern;
279 : }
280 :
281 : union {
282 : char mColPat[sizeof(ColorPattern)];
283 : char mLinGradPat[sizeof(LinearGradientPattern)];
284 : char mRadGradPat[sizeof(RadialGradientPattern)];
285 : char mSurfPat[sizeof(SurfacePattern)];
286 : };
287 :
288 : Pattern *mOrigPattern;
289 : Pattern *mPattern;
290 : };
291 :
292 0 : DrawTargetWrapAndRecord::DrawTargetWrapAndRecord(DrawEventRecorder *aRecorder, DrawTarget *aDT, bool aHasData)
293 : : mRecorder(static_cast<DrawEventRecorderPrivate*>(aRecorder))
294 0 : , mFinalDT(aDT)
295 : {
296 0 : RefPtr<SourceSurface> snapshot = aHasData ? mFinalDT->Snapshot() : nullptr;
297 0 : mRecorder->RecordEvent(RecordedDrawTargetCreation(this,
298 0 : mFinalDT->GetBackendType(),
299 0 : mFinalDT->GetSize(),
300 : mFinalDT->GetFormat(),
301 0 : aHasData, snapshot));
302 0 : mFormat = mFinalDT->GetFormat();
303 0 : }
304 :
305 0 : DrawTargetWrapAndRecord::DrawTargetWrapAndRecord(const DrawTargetWrapAndRecord *aDT,
306 0 : DrawTarget *aSimilarDT)
307 : : mRecorder(aDT->mRecorder)
308 0 : , mFinalDT(aSimilarDT)
309 : {
310 0 : mRecorder->RecordEvent(RecordedCreateSimilarDrawTarget(this,
311 0 : mFinalDT->GetSize(),
312 0 : mFinalDT->GetFormat()));
313 0 : mFormat = mFinalDT->GetFormat();
314 0 : }
315 :
316 0 : DrawTargetWrapAndRecord::~DrawTargetWrapAndRecord()
317 : {
318 0 : mRecorder->RecordEvent(RecordedDrawTargetDestruction(static_cast<DrawTarget*>(this)));
319 0 : }
320 :
321 : void
322 0 : DrawTargetWrapAndRecord::FillRect(const Rect &aRect,
323 : const Pattern &aPattern,
324 : const DrawOptions &aOptions)
325 : {
326 0 : EnsurePatternDependenciesStored(aPattern);
327 :
328 0 : mRecorder->RecordEvent(RecordedFillRect(this, aRect, aPattern, aOptions));
329 0 : mFinalDT->FillRect(aRect, *AdjustedPattern(aPattern), aOptions);
330 0 : }
331 :
332 : void
333 0 : DrawTargetWrapAndRecord::StrokeRect(const Rect &aRect,
334 : const Pattern &aPattern,
335 : const StrokeOptions &aStrokeOptions,
336 : const DrawOptions &aOptions)
337 : {
338 0 : EnsurePatternDependenciesStored(aPattern);
339 :
340 0 : mRecorder->RecordEvent(RecordedStrokeRect(this, aRect, aPattern, aStrokeOptions, aOptions));
341 0 : mFinalDT->StrokeRect(aRect, *AdjustedPattern(aPattern), aStrokeOptions, aOptions);
342 0 : }
343 :
344 : void
345 0 : DrawTargetWrapAndRecord::StrokeLine(const Point &aBegin,
346 : const Point &aEnd,
347 : const Pattern &aPattern,
348 : const StrokeOptions &aStrokeOptions,
349 : const DrawOptions &aOptions)
350 : {
351 0 : EnsurePatternDependenciesStored(aPattern);
352 :
353 0 : mRecorder->RecordEvent(RecordedStrokeLine(this, aBegin, aEnd, aPattern, aStrokeOptions, aOptions));
354 0 : mFinalDT->StrokeLine(aBegin, aEnd, *AdjustedPattern(aPattern), aStrokeOptions, aOptions);
355 0 : }
356 :
357 : void
358 0 : DrawTargetWrapAndRecord::Fill(const Path *aPath,
359 : const Pattern &aPattern,
360 : const DrawOptions &aOptions)
361 : {
362 0 : RefPtr<PathRecording> pathWrapAndRecord = EnsurePathStored(aPath);
363 0 : EnsurePatternDependenciesStored(aPattern);
364 :
365 0 : mRecorder->RecordEvent(RecordedFill(this, pathWrapAndRecord, aPattern, aOptions));
366 0 : mFinalDT->Fill(pathWrapAndRecord->mPath, *AdjustedPattern(aPattern), aOptions);
367 0 : }
368 :
369 0 : struct WrapAndRecordFontUserData
370 : {
371 : void *refPtr;
372 : RefPtr<DrawEventRecorderPrivate> recorder;
373 : };
374 :
375 0 : void WrapAndRecordFontUserDataDestroyFunc(void *aUserData)
376 : {
377 : WrapAndRecordFontUserData *userData =
378 0 : static_cast<WrapAndRecordFontUserData*>(aUserData);
379 :
380 0 : userData->recorder->RecordEvent(RecordedScaledFontDestruction(ReferencePtr(userData->refPtr)));
381 0 : userData->recorder->RemoveScaledFont((ScaledFont*)userData->refPtr);
382 0 : delete userData;
383 0 : }
384 :
385 : void
386 0 : DrawTargetWrapAndRecord::FillGlyphs(ScaledFont *aFont,
387 : const GlyphBuffer &aBuffer,
388 : const Pattern &aPattern,
389 : const DrawOptions &aOptions,
390 : const GlyphRenderingOptions *aRenderingOptions)
391 : {
392 0 : EnsurePatternDependenciesStored(aPattern);
393 :
394 0 : UserDataKey* userDataKey = reinterpret_cast<UserDataKey*>(mRecorder.get());
395 0 : if (!aFont->GetUserData(userDataKey)) {
396 0 : UnscaledFont* unscaledFont = aFont->GetUnscaledFont();
397 0 : if (!mRecorder->HasStoredObject(unscaledFont)) {
398 0 : RecordedFontData fontData(unscaledFont);
399 : RecordedFontDetails fontDetails;
400 0 : if (fontData.GetFontDetails(fontDetails)) {
401 : // Try to serialise the whole font, just in case this is a web font that
402 : // is not present on the system.
403 0 : if (!mRecorder->HasStoredFontData(fontDetails.fontDataKey)) {
404 0 : mRecorder->RecordEvent(fontData);
405 0 : mRecorder->AddStoredFontData(fontDetails.fontDataKey);
406 : }
407 0 : mRecorder->RecordEvent(RecordedUnscaledFontCreation(unscaledFont, fontDetails));
408 : } else {
409 : // If that fails, record just the font description and try to load it from
410 : // the system on the other side.
411 0 : RecordedFontDescriptor fontDesc(unscaledFont);
412 0 : if (fontDesc.IsValid()) {
413 0 : mRecorder->RecordEvent(fontDesc);
414 : } else {
415 0 : gfxWarning() << "DrawTargetWrapAndRecord::FillGlyphs failed to serialise UnscaledFont";
416 : }
417 : }
418 0 : mRecorder->AddStoredObject(unscaledFont);
419 : }
420 :
421 0 : mRecorder->RecordEvent(RecordedScaledFontCreation(aFont, unscaledFont));
422 :
423 0 : WrapAndRecordFontUserData *userData = new WrapAndRecordFontUserData;
424 0 : userData->refPtr = aFont;
425 0 : userData->recorder = mRecorder;
426 0 : aFont->AddUserData(userDataKey, userData, &WrapAndRecordFontUserDataDestroyFunc);
427 0 : userData->recorder->AddScaledFont(aFont);
428 : }
429 :
430 0 : mRecorder->RecordEvent(RecordedFillGlyphs(this, aFont, aPattern, aOptions, aBuffer.mGlyphs, aBuffer.mNumGlyphs));
431 0 : mFinalDT->FillGlyphs(aFont, aBuffer, *AdjustedPattern(aPattern), aOptions, aRenderingOptions);
432 0 : }
433 :
434 : void
435 0 : DrawTargetWrapAndRecord::Mask(const Pattern &aSource,
436 : const Pattern &aMask,
437 : const DrawOptions &aOptions)
438 : {
439 0 : EnsurePatternDependenciesStored(aSource);
440 0 : EnsurePatternDependenciesStored(aMask);
441 :
442 0 : mRecorder->RecordEvent(RecordedMask(this, aSource, aMask, aOptions));
443 0 : mFinalDT->Mask(*AdjustedPattern(aSource), *AdjustedPattern(aMask), aOptions);
444 0 : }
445 :
446 : void
447 0 : DrawTargetWrapAndRecord::MaskSurface(const Pattern &aSource,
448 : SourceSurface *aMask,
449 : Point aOffset,
450 : const DrawOptions &aOptions)
451 : {
452 0 : EnsurePatternDependenciesStored(aSource);
453 0 : EnsureSurfaceStored(mRecorder, aMask, "MaskSurface");
454 :
455 0 : mRecorder->RecordEvent(RecordedMaskSurface(this, aSource, aMask, aOffset, aOptions));
456 0 : mFinalDT->MaskSurface(*AdjustedPattern(aSource), GetSourceSurface(aMask), aOffset, aOptions);
457 0 : }
458 :
459 : void
460 0 : DrawTargetWrapAndRecord::Stroke(const Path *aPath,
461 : const Pattern &aPattern,
462 : const StrokeOptions &aStrokeOptions,
463 : const DrawOptions &aOptions)
464 : {
465 0 : RefPtr<PathRecording> pathWrapAndRecord = EnsurePathStored(aPath);
466 0 : EnsurePatternDependenciesStored(aPattern);
467 :
468 0 : mRecorder->RecordEvent(RecordedStroke(this, pathWrapAndRecord, aPattern, aStrokeOptions, aOptions));
469 0 : mFinalDT->Stroke(pathWrapAndRecord->mPath, *AdjustedPattern(aPattern), aStrokeOptions, aOptions);
470 0 : }
471 :
472 : already_AddRefed<SourceSurface>
473 0 : DrawTargetWrapAndRecord::Snapshot()
474 : {
475 0 : RefPtr<SourceSurface> surf = mFinalDT->Snapshot();
476 :
477 0 : RefPtr<SourceSurface> retSurf = new SourceSurfaceWrapAndRecord(surf, mRecorder);
478 :
479 0 : mRecorder->RecordEvent(RecordedSnapshot(retSurf, this));
480 :
481 0 : return retSurf.forget();
482 : }
483 :
484 : already_AddRefed<SourceSurface>
485 0 : DrawTargetWrapAndRecord::IntoLuminanceSource(LuminanceType aLuminanceType, float aOpacity)
486 : {
487 0 : RefPtr<SourceSurface> surf = mFinalDT->IntoLuminanceSource(aLuminanceType, aOpacity);
488 :
489 0 : RefPtr<SourceSurface> retSurf = new SourceSurfaceWrapAndRecord(surf, mRecorder);
490 :
491 0 : mRecorder->RecordEvent(RecordedIntoLuminanceSource(retSurf, this, aLuminanceType, aOpacity));
492 :
493 0 : return retSurf.forget();
494 : }
495 :
496 : void
497 0 : DrawTargetWrapAndRecord::DetachAllSnapshots()
498 : {
499 0 : mFinalDT->DetachAllSnapshots();
500 0 : }
501 :
502 : void
503 0 : DrawTargetWrapAndRecord::DrawSurface(SourceSurface *aSurface,
504 : const Rect &aDest,
505 : const Rect &aSource,
506 : const DrawSurfaceOptions &aSurfOptions,
507 : const DrawOptions &aOptions)
508 : {
509 0 : EnsureSurfaceStored(mRecorder, aSurface, "DrawSurface");
510 :
511 0 : mRecorder->RecordEvent(RecordedDrawSurface(this, aSurface, aDest, aSource, aSurfOptions, aOptions));
512 0 : mFinalDT->DrawSurface(GetSourceSurface(aSurface), aDest, aSource, aSurfOptions, aOptions);
513 0 : }
514 :
515 : void
516 0 : DrawTargetWrapAndRecord::DrawSurfaceWithShadow(SourceSurface *aSurface,
517 : const Point &aDest,
518 : const Color &aColor,
519 : const Point &aOffset,
520 : Float aSigma,
521 : CompositionOp aOp)
522 : {
523 0 : EnsureSurfaceStored(mRecorder, aSurface, "DrawSurfaceWithShadow");
524 :
525 0 : mRecorder->RecordEvent(RecordedDrawSurfaceWithShadow(this, aSurface, aDest, aColor, aOffset, aSigma, aOp));
526 0 : mFinalDT->DrawSurfaceWithShadow(GetSourceSurface(aSurface), aDest, aColor, aOffset, aSigma, aOp);
527 0 : }
528 :
529 : void
530 0 : DrawTargetWrapAndRecord::DrawFilter(FilterNode *aNode,
531 : const Rect &aSourceRect,
532 : const Point &aDestPoint,
533 : const DrawOptions &aOptions)
534 : {
535 0 : MOZ_ASSERT(mRecorder->HasStoredObject(aNode));
536 :
537 0 : mRecorder->RecordEvent(RecordedDrawFilter(this, aNode, aSourceRect, aDestPoint, aOptions));
538 0 : mFinalDT->DrawFilter(FilterNodeWrapAndRecord::GetFilterNode(aNode), aSourceRect, aDestPoint, aOptions);
539 0 : }
540 :
541 : already_AddRefed<FilterNode>
542 0 : DrawTargetWrapAndRecord::CreateFilter(FilterType aType)
543 : {
544 0 : RefPtr<FilterNode> node = mFinalDT->CreateFilter(aType);
545 :
546 0 : RefPtr<FilterNode> retNode = new FilterNodeWrapAndRecord(node, mRecorder);
547 :
548 0 : mRecorder->RecordEvent(RecordedFilterNodeCreation(retNode, aType));
549 :
550 0 : return retNode.forget();
551 : }
552 :
553 : void
554 0 : DrawTargetWrapAndRecord::ClearRect(const Rect &aRect)
555 : {
556 0 : mRecorder->RecordEvent(RecordedClearRect(this, aRect));
557 0 : mFinalDT->ClearRect(aRect);
558 0 : }
559 :
560 : void
561 0 : DrawTargetWrapAndRecord::CopySurface(SourceSurface *aSurface,
562 : const IntRect &aSourceRect,
563 : const IntPoint &aDestination)
564 : {
565 0 : EnsureSurfaceStored(mRecorder, aSurface, "CopySurface");
566 :
567 0 : mRecorder->RecordEvent(RecordedCopySurface(this, aSurface, aSourceRect, aDestination));
568 0 : mFinalDT->CopySurface(GetSourceSurface(aSurface), aSourceRect, aDestination);
569 0 : }
570 :
571 : void
572 0 : DrawTargetWrapAndRecord::PushClip(const Path *aPath)
573 : {
574 0 : RefPtr<PathRecording> pathWrapAndRecord = EnsurePathStored(aPath);
575 :
576 0 : mRecorder->RecordEvent(RecordedPushClip(this, pathWrapAndRecord));
577 0 : mFinalDT->PushClip(pathWrapAndRecord->mPath);
578 0 : }
579 :
580 : void
581 0 : DrawTargetWrapAndRecord::PushClipRect(const Rect &aRect)
582 : {
583 0 : mRecorder->RecordEvent(RecordedPushClipRect(this, aRect));
584 0 : mFinalDT->PushClipRect(aRect);
585 0 : }
586 :
587 : void
588 0 : DrawTargetWrapAndRecord::PopClip()
589 : {
590 0 : mRecorder->RecordEvent(RecordedPopClip(static_cast<DrawTarget*>(this)));
591 0 : mFinalDT->PopClip();
592 0 : }
593 :
594 : void
595 0 : DrawTargetWrapAndRecord::PushLayer(bool aOpaque, Float aOpacity,
596 : SourceSurface* aMask,
597 : const Matrix& aMaskTransform,
598 : const IntRect& aBounds, bool aCopyBackground)
599 : {
600 0 : if (aMask) {
601 0 : EnsureSurfaceStored(mRecorder, aMask, "PushLayer");
602 : }
603 :
604 0 : mRecorder->RecordEvent(RecordedPushLayer(this, aOpaque, aOpacity, aMask,
605 : aMaskTransform, aBounds,
606 0 : aCopyBackground));
607 0 : mFinalDT->PushLayer(aOpaque, aOpacity, aMask, aMaskTransform, aBounds,
608 0 : aCopyBackground);
609 0 : }
610 :
611 : void
612 0 : DrawTargetWrapAndRecord::PopLayer()
613 : {
614 0 : mRecorder->RecordEvent(RecordedPopLayer(static_cast<DrawTarget*>(this)));
615 0 : mFinalDT->PopLayer();
616 0 : }
617 :
618 : already_AddRefed<SourceSurface>
619 0 : DrawTargetWrapAndRecord::CreateSourceSurfaceFromData(unsigned char *aData,
620 : const IntSize &aSize,
621 : int32_t aStride,
622 : SurfaceFormat aFormat) const
623 : {
624 0 : RefPtr<SourceSurface> surf = mFinalDT->CreateSourceSurfaceFromData(aData, aSize, aStride, aFormat);
625 :
626 0 : RefPtr<SourceSurface> retSurf = new SourceSurfaceWrapAndRecord(surf, mRecorder);
627 :
628 0 : mRecorder->RecordEvent(RecordedSourceSurfaceCreation(retSurf, aData, aStride, aSize, aFormat));
629 :
630 0 : return retSurf.forget();
631 : }
632 :
633 : already_AddRefed<SourceSurface>
634 0 : DrawTargetWrapAndRecord::OptimizeSourceSurface(SourceSurface *aSurface) const
635 : {
636 0 : RefPtr<SourceSurface> surf = mFinalDT->OptimizeSourceSurface(aSurface);
637 :
638 0 : RefPtr<SourceSurface> retSurf = new SourceSurfaceWrapAndRecord(surf, mRecorder);
639 :
640 0 : RefPtr<DataSourceSurface> dataSurf = surf->GetDataSurface();
641 :
642 0 : if (!dataSurf) {
643 : // Let's try get it off the original surface.
644 0 : dataSurf = aSurface->GetDataSurface();
645 : }
646 :
647 0 : StoreSourceSurface(mRecorder, retSurf, dataSurf, "OptimizeSourceSurface");
648 :
649 0 : return retSurf.forget();
650 : }
651 :
652 : already_AddRefed<SourceSurface>
653 0 : DrawTargetWrapAndRecord::CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const
654 : {
655 0 : RefPtr<SourceSurface> surf = mFinalDT->CreateSourceSurfaceFromNativeSurface(aSurface);
656 :
657 0 : RefPtr<SourceSurface> retSurf = new SourceSurfaceWrapAndRecord(surf, mRecorder);
658 :
659 0 : RefPtr<DataSourceSurface> dataSurf = surf->GetDataSurface();
660 0 : StoreSourceSurface(mRecorder, retSurf, dataSurf, "CreateSourceSurfaceFromNativeSurface");
661 :
662 0 : return retSurf.forget();
663 : }
664 :
665 : already_AddRefed<DrawTarget>
666 0 : DrawTargetWrapAndRecord::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const
667 : {
668 : RefPtr<DrawTarget> similarDT =
669 0 : mFinalDT->CreateSimilarDrawTarget(aSize, aFormat);
670 0 : if (!similarDT) {
671 0 : return nullptr;
672 : }
673 :
674 0 : similarDT = new DrawTargetWrapAndRecord(this, similarDT);
675 0 : return similarDT.forget();
676 : }
677 :
678 : already_AddRefed<PathBuilder>
679 0 : DrawTargetWrapAndRecord::CreatePathBuilder(FillRule aFillRule) const
680 : {
681 0 : RefPtr<PathBuilder> builder = mFinalDT->CreatePathBuilder(aFillRule);
682 0 : return MakeAndAddRef<PathBuilderRecording>(builder, aFillRule);
683 : }
684 :
685 : already_AddRefed<GradientStops>
686 0 : DrawTargetWrapAndRecord::CreateGradientStops(GradientStop *aStops,
687 : uint32_t aNumStops,
688 : ExtendMode aExtendMode) const
689 : {
690 0 : RefPtr<GradientStops> stops = mFinalDT->CreateGradientStops(aStops, aNumStops, aExtendMode);
691 :
692 0 : RefPtr<GradientStops> retStops = new GradientStopsWrapAndRecord(stops, mRecorder);
693 :
694 0 : mRecorder->RecordEvent(RecordedGradientStopsCreation(retStops, aStops, aNumStops, aExtendMode));
695 :
696 0 : return retStops.forget();
697 : }
698 :
699 : void
700 0 : DrawTargetWrapAndRecord::SetTransform(const Matrix &aTransform)
701 : {
702 0 : mRecorder->RecordEvent(RecordedSetTransform(this, aTransform));
703 0 : DrawTarget::SetTransform(aTransform);
704 0 : mFinalDT->SetTransform(aTransform);
705 0 : }
706 :
707 : already_AddRefed<PathRecording>
708 0 : DrawTargetWrapAndRecord::EnsurePathStored(const Path *aPath)
709 : {
710 0 : RefPtr<PathRecording> pathWrapAndRecord;
711 0 : if (aPath->GetBackendType() == BackendType::RECORDING) {
712 0 : pathWrapAndRecord = const_cast<PathRecording*>(static_cast<const PathRecording*>(aPath));
713 0 : if (mRecorder->HasStoredObject(aPath)) {
714 0 : return pathWrapAndRecord.forget();
715 : }
716 : } else {
717 0 : MOZ_ASSERT(!mRecorder->HasStoredObject(aPath));
718 0 : FillRule fillRule = aPath->GetFillRule();
719 0 : RefPtr<PathBuilder> builder = mFinalDT->CreatePathBuilder(fillRule);
720 : RefPtr<PathBuilderRecording> builderWrapAndRecord =
721 0 : new PathBuilderRecording(builder, fillRule);
722 0 : aPath->StreamToSink(builderWrapAndRecord);
723 0 : pathWrapAndRecord = builderWrapAndRecord->Finish().downcast<PathRecording>();
724 : }
725 :
726 0 : mRecorder->RecordEvent(RecordedPathCreation(pathWrapAndRecord.get()));
727 0 : mRecorder->AddStoredObject(pathWrapAndRecord);
728 0 : pathWrapAndRecord->mStoredRecorders.push_back(mRecorder);
729 :
730 0 : return pathWrapAndRecord.forget();
731 : }
732 :
733 : void
734 0 : DrawTargetWrapAndRecord::EnsurePatternDependenciesStored(const Pattern &aPattern)
735 : {
736 0 : switch (aPattern.GetType()) {
737 : case PatternType::COLOR:
738 : // No dependencies here.
739 0 : return;
740 : case PatternType::LINEAR_GRADIENT:
741 : {
742 0 : MOZ_ASSERT(mRecorder->HasStoredObject(static_cast<const LinearGradientPattern*>(&aPattern)->mStops));
743 0 : return;
744 : }
745 : case PatternType::RADIAL_GRADIENT:
746 : {
747 0 : MOZ_ASSERT(mRecorder->HasStoredObject(static_cast<const RadialGradientPattern*>(&aPattern)->mStops));
748 0 : return;
749 : }
750 : case PatternType::SURFACE:
751 : {
752 0 : const SurfacePattern *pat = static_cast<const SurfacePattern*>(&aPattern);
753 0 : EnsureSurfaceStored(mRecorder, pat->mSurface, "EnsurePatternDependenciesStored");
754 0 : return;
755 : }
756 : }
757 : }
758 :
759 : } // namespace gfx
760 : } // namespace mozilla
|