Bumping manifests a=b2g-bump
[gecko.git] / gfx / 2d / DrawTargetRecording.cpp
blobe32250c34edfd34fa827a9136bc58f7ac6e0175e
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "DrawTargetRecording.h"
7 #include "PathRecording.h"
8 #include <stdio.h>
10 #include "Logging.h"
11 #include "Tools.h"
12 #include "Filters.h"
14 namespace mozilla {
15 namespace gfx {
17 class SourceSurfaceRecording : public SourceSurface
19 public:
20 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceRecording)
21 SourceSurfaceRecording(SourceSurface *aFinalSurface, DrawEventRecorderPrivate *aRecorder)
22 : mFinalSurface(aFinalSurface), mRecorder(aRecorder)
26 ~SourceSurfaceRecording()
28 mRecorder->RecordEvent(RecordedSourceSurfaceDestruction(this));
31 virtual SurfaceType GetType() const { return SurfaceType::RECORDING; }
32 virtual IntSize GetSize() const { return mFinalSurface->GetSize(); }
33 virtual SurfaceFormat GetFormat() const { return mFinalSurface->GetFormat(); }
34 virtual TemporaryRef<DataSourceSurface> GetDataSurface() { return mFinalSurface->GetDataSurface(); }
36 RefPtr<SourceSurface> mFinalSurface;
37 RefPtr<DrawEventRecorderPrivate> mRecorder;
40 class GradientStopsRecording : public GradientStops
42 public:
43 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStopsRecording)
44 GradientStopsRecording(GradientStops *aFinalGradientStops, DrawEventRecorderPrivate *aRecorder)
45 : mFinalGradientStops(aFinalGradientStops), mRecorder(aRecorder)
49 ~GradientStopsRecording()
51 mRecorder->RecordEvent(RecordedGradientStopsDestruction(this));
54 virtual BackendType GetBackendType() const { return BackendType::RECORDING; }
56 RefPtr<GradientStops> mFinalGradientStops;
57 RefPtr<DrawEventRecorderPrivate> mRecorder;
60 static SourceSurface *
61 GetSourceSurface(SourceSurface *aSurface)
63 if (aSurface->GetType() != SurfaceType::RECORDING) {
64 return aSurface;
67 return static_cast<SourceSurfaceRecording*>(aSurface)->mFinalSurface;
70 static GradientStops *
71 GetGradientStops(GradientStops *aStops)
73 if (aStops->GetBackendType() != BackendType::RECORDING) {
74 return aStops;
77 return static_cast<GradientStopsRecording*>(aStops)->mFinalGradientStops;
80 class FilterNodeRecording : public FilterNode
82 public:
83 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeRecording)
84 using FilterNode::SetAttribute;
86 FilterNodeRecording(FilterNode *aFinalFilterNode, DrawEventRecorderPrivate *aRecorder)
87 : mFinalFilterNode(aFinalFilterNode), mRecorder(aRecorder)
91 ~FilterNodeRecording()
93 mRecorder->RecordEvent(RecordedFilterNodeDestruction(this));
96 virtual void SetInput(uint32_t aIndex, SourceSurface *aSurface)
98 mRecorder->RecordEvent(RecordedFilterNodeSetInput(this, aIndex, aSurface));
99 mFinalFilterNode->SetInput(aIndex, GetSourceSurface(aSurface));
101 virtual void SetInput(uint32_t aIndex, FilterNode *aFilter)
103 FilterNode *finalNode = aFilter;
104 if (aFilter->GetBackendType() != FILTER_BACKEND_RECORDING) {
105 gfxWarning() << "Non recording filter node used with recording DrawTarget!";
106 } else {
107 finalNode = static_cast<FilterNodeRecording*>(aFilter)->mFinalFilterNode;
110 mRecorder->RecordEvent(RecordedFilterNodeSetInput(this, aIndex, aFilter));
111 mFinalFilterNode->SetInput(aIndex, finalNode);
115 #define FORWARD_SET_ATTRIBUTE(type, argtype) \
116 virtual void SetAttribute(uint32_t aIndex, type aValue) { \
117 mRecorder->RecordEvent(RecordedFilterNodeSetAttribute(this, aIndex, aValue, RecordedFilterNodeSetAttribute::ARGTYPE_##argtype)); \
118 mFinalFilterNode->SetAttribute(aIndex, aValue); \
121 FORWARD_SET_ATTRIBUTE(bool, BOOL);
122 FORWARD_SET_ATTRIBUTE(uint32_t, UINT32);
123 FORWARD_SET_ATTRIBUTE(Float, FLOAT);
124 FORWARD_SET_ATTRIBUTE(const Size&, SIZE);
125 FORWARD_SET_ATTRIBUTE(const IntSize&, INTSIZE);
126 FORWARD_SET_ATTRIBUTE(const IntPoint&, INTPOINT);
127 FORWARD_SET_ATTRIBUTE(const Rect&, RECT);
128 FORWARD_SET_ATTRIBUTE(const IntRect&, INTRECT);
129 FORWARD_SET_ATTRIBUTE(const Point&, POINT);
130 FORWARD_SET_ATTRIBUTE(const Matrix5x4&, MATRIX5X4);
131 FORWARD_SET_ATTRIBUTE(const Point3D&, POINT3D);
132 FORWARD_SET_ATTRIBUTE(const Color&, COLOR);
134 #undef FORWARD_SET_ATTRIBUTE
136 virtual void SetAttribute(uint32_t aIndex, const Float* aFloat, uint32_t aSize) {
137 mRecorder->RecordEvent(RecordedFilterNodeSetAttribute(this, aIndex, aFloat, aSize));
138 mFinalFilterNode->SetAttribute(aIndex, aFloat, aSize);
141 virtual FilterBackend GetBackendType() MOZ_OVERRIDE { return FILTER_BACKEND_RECORDING; }
143 RefPtr<FilterNode> mFinalFilterNode;
144 RefPtr<DrawEventRecorderPrivate> mRecorder;
147 static FilterNode*
148 GetFilterNode(FilterNode* aNode)
150 if (aNode->GetBackendType() != FILTER_BACKEND_RECORDING) {
151 gfxWarning() << "Non recording filter node used with recording DrawTarget!";
152 return aNode;
155 return static_cast<FilterNodeRecording*>(aNode)->mFinalFilterNode;
158 struct AdjustedPattern
160 explicit AdjustedPattern(const Pattern &aPattern)
161 : mPattern(nullptr)
163 mOrigPattern = const_cast<Pattern*>(&aPattern);
166 ~AdjustedPattern() {
167 if (mPattern) {
168 mPattern->~Pattern();
172 operator Pattern*()
174 switch(mOrigPattern->GetType()) {
175 case PatternType::COLOR:
176 return mOrigPattern;
177 case PatternType::SURFACE:
179 SurfacePattern *surfPat = static_cast<SurfacePattern*>(mOrigPattern);
180 mPattern =
181 new (mSurfPat) SurfacePattern(GetSourceSurface(surfPat->mSurface),
182 surfPat->mExtendMode, surfPat->mMatrix,
183 surfPat->mFilter);
184 return mPattern;
186 case PatternType::LINEAR_GRADIENT:
188 LinearGradientPattern *linGradPat = static_cast<LinearGradientPattern*>(mOrigPattern);
189 mPattern =
190 new (mLinGradPat) LinearGradientPattern(linGradPat->mBegin, linGradPat->mEnd,
191 GetGradientStops(linGradPat->mStops),
192 linGradPat->mMatrix);
193 return mPattern;
195 case PatternType::RADIAL_GRADIENT:
197 RadialGradientPattern *radGradPat = static_cast<RadialGradientPattern*>(mOrigPattern);
198 mPattern =
199 new (mRadGradPat) RadialGradientPattern(radGradPat->mCenter1, radGradPat->mCenter2,
200 radGradPat->mRadius1, radGradPat->mRadius2,
201 GetGradientStops(radGradPat->mStops),
202 radGradPat->mMatrix);
203 return mPattern;
205 default:
206 return new (mColPat) ColorPattern(Color());
209 return mPattern;
212 union {
213 char mColPat[sizeof(ColorPattern)];
214 char mLinGradPat[sizeof(LinearGradientPattern)];
215 char mRadGradPat[sizeof(RadialGradientPattern)];
216 char mSurfPat[sizeof(SurfacePattern)];
219 Pattern *mOrigPattern;
220 Pattern *mPattern;
223 DrawTargetRecording::DrawTargetRecording(DrawEventRecorder *aRecorder, DrawTarget *aDT, bool aHasData)
224 : mRecorder(static_cast<DrawEventRecorderPrivate*>(aRecorder))
225 , mFinalDT(aDT)
227 RefPtr<SourceSurface> snapshot = aHasData ? mFinalDT->Snapshot() : nullptr;
228 mRecorder->RecordEvent(RecordedDrawTargetCreation(this,
229 mFinalDT->GetBackendType(),
230 mFinalDT->GetSize(),
231 mFinalDT->GetFormat(),
232 aHasData, snapshot));
233 mFormat = mFinalDT->GetFormat();
236 DrawTargetRecording::~DrawTargetRecording()
238 mRecorder->RecordEvent(RecordedDrawTargetDestruction(this));
241 void
242 DrawTargetRecording::FillRect(const Rect &aRect,
243 const Pattern &aPattern,
244 const DrawOptions &aOptions)
246 mRecorder->RecordEvent(RecordedFillRect(this, aRect, aPattern, aOptions));
247 mFinalDT->FillRect(aRect, *AdjustedPattern(aPattern), aOptions);
250 void
251 DrawTargetRecording::StrokeRect(const Rect &aRect,
252 const Pattern &aPattern,
253 const StrokeOptions &aStrokeOptions,
254 const DrawOptions &aOptions)
256 mRecorder->RecordEvent(RecordedStrokeRect(this, aRect, aPattern, aStrokeOptions, aOptions));
257 mFinalDT->StrokeRect(aRect, *AdjustedPattern(aPattern), aStrokeOptions, aOptions);
260 void
261 DrawTargetRecording::StrokeLine(const Point &aBegin,
262 const Point &aEnd,
263 const Pattern &aPattern,
264 const StrokeOptions &aStrokeOptions,
265 const DrawOptions &aOptions)
267 mRecorder->RecordEvent(RecordedStrokeLine(this, aBegin, aEnd, aPattern, aStrokeOptions, aOptions));
268 mFinalDT->StrokeLine(aBegin, aEnd, *AdjustedPattern(aPattern), aStrokeOptions, aOptions);
271 Path*
272 DrawTargetRecording::GetPathForPathRecording(const Path *aPath) const
274 if (aPath->GetBackendType() != BackendType::RECORDING) {
275 return nullptr;
278 return static_cast<const PathRecording*>(aPath)->mPath;
281 void
282 DrawTargetRecording::Fill(const Path *aPath,
283 const Pattern &aPattern,
284 const DrawOptions &aOptions)
286 EnsureStored(aPath);
288 mRecorder->RecordEvent(RecordedFill(this, const_cast<Path*>(aPath), aPattern, aOptions));
289 mFinalDT->Fill(GetPathForPathRecording(aPath), *AdjustedPattern(aPattern), aOptions);
292 struct RecordingFontUserData
294 void *refPtr;
295 RefPtr<DrawEventRecorderPrivate> recorder;
298 void RecordingFontUserDataDestroyFunc(void *aUserData)
300 RecordingFontUserData *userData =
301 static_cast<RecordingFontUserData*>(aUserData);
303 // TODO support font in b2g recordings
304 #ifndef MOZ_WIDGET_GONK
305 userData->recorder->RecordEvent(RecordedScaledFontDestruction(userData->refPtr));
306 #endif
308 delete userData;
311 void
312 DrawTargetRecording::FillGlyphs(ScaledFont *aFont,
313 const GlyphBuffer &aBuffer,
314 const Pattern &aPattern,
315 const DrawOptions &aOptions,
316 const GlyphRenderingOptions *aRenderingOptions)
318 if (!aFont->GetUserData(reinterpret_cast<UserDataKey*>(mRecorder.get()))) {
319 // TODO support font in b2g recordings
320 #ifndef MOZ_WIDGET_GONK
321 mRecorder->RecordEvent(RecordedScaledFontCreation(aFont, aFont));
322 #endif
323 RecordingFontUserData *userData = new RecordingFontUserData;
324 userData->refPtr = aFont;
325 userData->recorder = mRecorder;
326 aFont->AddUserData(reinterpret_cast<UserDataKey*>(mRecorder.get()), userData,
327 &RecordingFontUserDataDestroyFunc);
330 // TODO support font in b2g recordings
331 #ifndef MOZ_WIDGET_GONK
332 mRecorder->RecordEvent(RecordedFillGlyphs(this, aFont, aPattern, aOptions, aBuffer.mGlyphs, aBuffer.mNumGlyphs));
333 #endif
334 mFinalDT->FillGlyphs(aFont, aBuffer, aPattern, aOptions, aRenderingOptions);
337 void
338 DrawTargetRecording::Mask(const Pattern &aSource,
339 const Pattern &aMask,
340 const DrawOptions &aOptions)
342 mRecorder->RecordEvent(RecordedMask(this, aSource, aMask, aOptions));
343 mFinalDT->Mask(*AdjustedPattern(aSource), *AdjustedPattern(aMask), aOptions);
346 void
347 DrawTargetRecording::MaskSurface(const Pattern &aSource,
348 SourceSurface *aMask,
349 Point aOffset,
350 const DrawOptions &aOptions)
352 mRecorder->RecordEvent(RecordedMaskSurface(this, aSource, aMask, aOffset, aOptions));
353 mFinalDT->MaskSurface(*AdjustedPattern(aSource), GetSourceSurface(aMask), aOffset, aOptions);
356 void
357 DrawTargetRecording::Stroke(const Path *aPath,
358 const Pattern &aPattern,
359 const StrokeOptions &aStrokeOptions,
360 const DrawOptions &aOptions)
362 EnsureStored(aPath);
364 mRecorder->RecordEvent(RecordedStroke(this, const_cast<Path*>(aPath), aPattern, aStrokeOptions, aOptions));
365 mFinalDT->Stroke(GetPathForPathRecording(aPath), *AdjustedPattern(aPattern), aStrokeOptions, aOptions);
368 TemporaryRef<SourceSurface>
369 DrawTargetRecording::Snapshot()
371 RefPtr<SourceSurface> surf = mFinalDT->Snapshot();
373 RefPtr<SourceSurface> retSurf = new SourceSurfaceRecording(surf, mRecorder);
375 mRecorder->RecordEvent(RecordedSnapshot(retSurf, this));
377 return retSurf.forget();
380 void
381 DrawTargetRecording::DrawSurface(SourceSurface *aSurface,
382 const Rect &aDest,
383 const Rect &aSource,
384 const DrawSurfaceOptions &aSurfOptions,
385 const DrawOptions &aOptions)
387 mRecorder->RecordEvent(RecordedDrawSurface(this, aSurface, aDest, aSource, aSurfOptions, aOptions));
388 mFinalDT->DrawSurface(GetSourceSurface(aSurface), aDest, aSource, aSurfOptions, aOptions);
391 void
392 DrawTargetRecording::DrawSurfaceWithShadow(SourceSurface *aSurface,
393 const Point &aDest,
394 const Color &aColor,
395 const Point &aOffset,
396 Float aSigma,
397 CompositionOp aOp)
399 mRecorder->RecordEvent(RecordedDrawSurfaceWithShadow(this, aSurface, aDest, aColor, aOffset, aSigma, aOp));
400 mFinalDT->DrawSurfaceWithShadow(GetSourceSurface(aSurface), aDest, aColor, aOffset, aSigma, aOp);
403 void
404 DrawTargetRecording::DrawFilter(FilterNode *aNode,
405 const Rect &aSourceRect,
406 const Point &aDestPoint,
407 const DrawOptions &aOptions)
409 mRecorder->RecordEvent(RecordedDrawFilter(this, aNode, aSourceRect, aDestPoint, aOptions));
410 mFinalDT->DrawFilter(GetFilterNode(aNode), aSourceRect, aDestPoint, aOptions);
413 TemporaryRef<FilterNode>
414 DrawTargetRecording::CreateFilter(FilterType aType)
416 RefPtr<FilterNode> node = mFinalDT->CreateFilter(aType);
418 RefPtr<FilterNode> retNode = new FilterNodeRecording(node, mRecorder);
420 mRecorder->RecordEvent(RecordedFilterNodeCreation(retNode, aType));
422 return retNode.forget();
425 void
426 DrawTargetRecording::ClearRect(const Rect &aRect)
428 mRecorder->RecordEvent(RecordedClearRect(this, aRect));
429 mFinalDT->ClearRect(aRect);
432 void
433 DrawTargetRecording::CopySurface(SourceSurface *aSurface,
434 const IntRect &aSourceRect,
435 const IntPoint &aDestination)
437 mRecorder->RecordEvent(RecordedCopySurface(this, aSurface, aSourceRect, aDestination));
438 mFinalDT->CopySurface(GetSourceSurface(aSurface), aSourceRect, aDestination);
441 void
442 DrawTargetRecording::PushClip(const Path *aPath)
444 EnsureStored(aPath);
446 mRecorder->RecordEvent(RecordedPushClip(this, const_cast<Path*>(aPath)));
447 mFinalDT->PushClip(GetPathForPathRecording(aPath));
450 void
451 DrawTargetRecording::PushClipRect(const Rect &aRect)
453 mRecorder->RecordEvent(RecordedPushClipRect(this, aRect));
454 mFinalDT->PushClipRect(aRect);
457 void
458 DrawTargetRecording::PopClip()
460 mRecorder->RecordEvent(RecordedPopClip(this));
461 mFinalDT->PopClip();
464 TemporaryRef<SourceSurface>
465 DrawTargetRecording::CreateSourceSurfaceFromData(unsigned char *aData,
466 const IntSize &aSize,
467 int32_t aStride,
468 SurfaceFormat aFormat) const
470 RefPtr<SourceSurface> surf = mFinalDT->CreateSourceSurfaceFromData(aData, aSize, aStride, aFormat);
472 RefPtr<SourceSurface> retSurf = new SourceSurfaceRecording(surf, mRecorder);
474 mRecorder->RecordEvent(RecordedSourceSurfaceCreation(retSurf, aData, aStride, aSize, aFormat));
476 return retSurf.forget();
479 TemporaryRef<SourceSurface>
480 DrawTargetRecording::OptimizeSourceSurface(SourceSurface *aSurface) const
482 RefPtr<SourceSurface> surf = mFinalDT->OptimizeSourceSurface(aSurface);
484 RefPtr<SourceSurface> retSurf = new SourceSurfaceRecording(surf, mRecorder);
486 RefPtr<DataSourceSurface> dataSurf = surf->GetDataSurface();
488 if (!dataSurf) {
489 // Let's try get it off the original surface.
490 dataSurf = aSurface->GetDataSurface();
493 if (!dataSurf) {
494 gfxWarning() << "Recording failed to record SourceSurface created from OptimizeSourceSurface";
495 // Insert a bogus source surface.
496 uint8_t *sourceData = new uint8_t[surf->GetSize().width * surf->GetSize().height * BytesPerPixel(surf->GetFormat())];
497 memset(sourceData, 0, surf->GetSize().width * surf->GetSize().height * BytesPerPixel(surf->GetFormat()));
498 mRecorder->RecordEvent(
499 RecordedSourceSurfaceCreation(retSurf, sourceData,
500 surf->GetSize().width * BytesPerPixel(surf->GetFormat()),
501 surf->GetSize(), surf->GetFormat()));
502 delete [] sourceData;
503 } else {
504 mRecorder->RecordEvent(
505 RecordedSourceSurfaceCreation(retSurf, dataSurf->GetData(), dataSurf->Stride(),
506 dataSurf->GetSize(), dataSurf->GetFormat()));
509 return retSurf.forget();
512 TemporaryRef<SourceSurface>
513 DrawTargetRecording::CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const
515 RefPtr<SourceSurface> surf = mFinalDT->CreateSourceSurfaceFromNativeSurface(aSurface);
517 RefPtr<SourceSurface> retSurf = new SourceSurfaceRecording(surf, mRecorder);
519 RefPtr<DataSourceSurface> dataSurf = surf->GetDataSurface();
521 if (!dataSurf) {
522 gfxWarning() << "Recording failed to record SourceSurface created from OptimizeSourceSurface";
523 // Insert a bogus source surface.
524 uint8_t *sourceData = new uint8_t[surf->GetSize().width * surf->GetSize().height * BytesPerPixel(surf->GetFormat())];
525 memset(sourceData, 0, surf->GetSize().width * surf->GetSize().height * BytesPerPixel(surf->GetFormat()));
526 mRecorder->RecordEvent(
527 RecordedSourceSurfaceCreation(retSurf, sourceData,
528 surf->GetSize().width * BytesPerPixel(surf->GetFormat()),
529 surf->GetSize(), surf->GetFormat()));
530 delete [] sourceData;
531 } else {
532 mRecorder->RecordEvent(
533 RecordedSourceSurfaceCreation(retSurf, dataSurf->GetData(), dataSurf->Stride(),
534 dataSurf->GetSize(), dataSurf->GetFormat()));
537 return retSurf.forget();
540 TemporaryRef<DrawTarget>
541 DrawTargetRecording::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const
543 RefPtr<DrawTarget> dt = mFinalDT->CreateSimilarDrawTarget(aSize, aFormat);
544 return new DrawTargetRecording(mRecorder.get(), dt);
547 TemporaryRef<PathBuilder>
548 DrawTargetRecording::CreatePathBuilder(FillRule aFillRule) const
550 RefPtr<PathBuilder> builder = mFinalDT->CreatePathBuilder(aFillRule);
551 return new PathBuilderRecording(builder, aFillRule);
554 TemporaryRef<GradientStops>
555 DrawTargetRecording::CreateGradientStops(GradientStop *aStops,
556 uint32_t aNumStops,
557 ExtendMode aExtendMode) const
559 RefPtr<GradientStops> stops = mFinalDT->CreateGradientStops(aStops, aNumStops, aExtendMode);
561 RefPtr<GradientStops> retStops = new GradientStopsRecording(stops, mRecorder);
563 mRecorder->RecordEvent(RecordedGradientStopsCreation(retStops, aStops, aNumStops, aExtendMode));
565 return retStops.forget();
568 void
569 DrawTargetRecording::SetTransform(const Matrix &aTransform)
571 mRecorder->RecordEvent(RecordedSetTransform(this, aTransform));
572 DrawTarget::SetTransform(aTransform);
573 mFinalDT->SetTransform(aTransform);
576 void
577 DrawTargetRecording::EnsureStored(const Path *aPath)
579 if (!mRecorder->HasStoredPath(aPath)) {
580 if (aPath->GetBackendType() != BackendType::RECORDING) {
581 gfxWarning() << "Cannot record this fill path properly!";
582 } else {
583 PathRecording *recPath = const_cast<PathRecording*>(static_cast<const PathRecording*>(aPath));
584 mRecorder->RecordEvent(RecordedPathCreation(recPath));
585 mRecorder->AddStoredPath(aPath);
586 recPath->mStoredRecorders.push_back(mRecorder);