Coverage Report

Created: 2018-09-25 14:53

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