Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/2d/DrawTargetRecording.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 "DrawTargetRecording.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 RecordingSourceSurfaceUserData
22
{
23
  void *refPtr;
24
  RefPtr<DrawEventRecorderPrivate> recorder;
25
};
26
27
void RecordingSourceSurfaceUserDataFunc(void *aUserData)
28
0
{
29
0
  RecordingSourceSurfaceUserData *userData =
30
0
    static_cast<RecordingSourceSurfaceUserData*>(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
EnsureSurfaceStoredRecording(DrawEventRecorderPrivate *aRecorder, SourceSurface *aSurface,
42
                    const char *reason)
43
0
{
44
0
  if (aRecorder->HasStoredObject(aSurface)) {
45
0
    return;
46
0
  }
47
0
48
0
  aRecorder->StoreSourceSurfaceRecording(aSurface, reason);
49
0
  aRecorder->AddStoredObject(aSurface);
50
0
  aRecorder->AddSourceSurface(aSurface);
51
0
52
0
  RecordingSourceSurfaceUserData *userData = new RecordingSourceSurfaceUserData;
53
0
  userData->refPtr = aSurface;
54
0
  userData->recorder = aRecorder;
55
0
  aSurface->AddUserData(reinterpret_cast<UserDataKey*>(aRecorder),
56
0
                        userData, &RecordingSourceSurfaceUserDataFunc);
57
0
}
58
59
class SourceSurfaceRecording : public SourceSurface
60
{
61
public:
62
  MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceRecording, override)
63
64
  SourceSurfaceRecording(IntSize aSize, SurfaceFormat aFormat, DrawEventRecorderPrivate *aRecorder)
65
    : mSize(aSize), mFormat(aFormat), mRecorder(aRecorder)
66
0
  {
67
0
    mRecorder->AddStoredObject(this);
68
0
  }
69
70
  ~SourceSurfaceRecording()
71
0
  {
72
0
    mRecorder->RemoveStoredObject(this);
73
0
    mRecorder->RecordEvent(RecordedSourceSurfaceDestruction(ReferencePtr(this)));
74
0
  }
75
76
0
  virtual SurfaceType GetType() const override { return SurfaceType::RECORDING; }
77
0
  virtual IntSize GetSize() const override { return mSize; }
78
0
  virtual SurfaceFormat GetFormat() const override { return mFormat; }
79
0
  virtual already_AddRefed<DataSourceSurface> GetDataSurface() override { return nullptr; }
80
81
  IntSize mSize;
82
  SurfaceFormat mFormat;
83
  RefPtr<DrawEventRecorderPrivate> mRecorder;
84
};
85
86
class DataSourceSurfaceRecording : public DataSourceSurface
87
{
88
public:
89
  MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceRecording, override)
90
  DataSourceSurfaceRecording(UniquePtr<uint8_t[]> aData, IntSize aSize,
91
                             int32_t aStride, SurfaceFormat aFormat)
92
    : mData(std::move(aData))
93
    , mSize(aSize)
94
    , mStride(aStride)
95
    , mFormat(aFormat)
96
0
  {
97
0
  }
98
99
  ~DataSourceSurfaceRecording()
100
0
  {
101
0
  }
102
103
  static already_AddRefed<DataSourceSurface>
104
  Init(uint8_t *aData, IntSize aSize, int32_t aStride, SurfaceFormat aFormat)
105
0
  {
106
0
    //XXX: do we need to ensure any alignment here?
107
0
    auto data = MakeUnique<uint8_t[]>(aStride * aSize.height);
108
0
    if (data) {
109
0
      memcpy(data.get(), aData, aStride * aSize.height);
110
0
      RefPtr<DataSourceSurfaceRecording> surf = new DataSourceSurfaceRecording(std::move(data), aSize, aStride, aFormat);
111
0
      return surf.forget();
112
0
    }
113
0
    return nullptr;
114
0
  }
115
116
0
  virtual SurfaceType GetType() const override { return SurfaceType::RECORDING; }
117
0
  virtual IntSize GetSize() const override { return mSize; }
118
0
  virtual int32_t Stride() override { return mStride; }
119
0
  virtual SurfaceFormat GetFormat() const override { return mFormat; }
120
0
  virtual uint8_t* GetData() override { return mData.get(); }
121
122
  UniquePtr<uint8_t[]> mData;
123
  IntSize mSize;
124
  int32_t mStride;
125
  SurfaceFormat mFormat;
126
};
127
128
129
class GradientStopsRecording : public GradientStops
130
{
131
public:
132
  MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStopsRecording, override)
133
134
  explicit GradientStopsRecording(DrawEventRecorderPrivate *aRecorder)
135
    : mRecorder(aRecorder)
136
0
  {
137
0
    mRecorder->AddStoredObject(this);
138
0
  }
139
140
  ~GradientStopsRecording()
141
0
  {
142
0
    mRecorder->RemoveStoredObject(this);
143
0
    mRecorder->RecordEvent(RecordedGradientStopsDestruction(ReferencePtr(this)));
144
0
  }
145
146
0
  virtual BackendType GetBackendType() const override { return BackendType::RECORDING; }
147
148
  RefPtr<DrawEventRecorderPrivate> mRecorder;
149
};
150
151
class FilterNodeRecording : public FilterNode
152
{
153
public:
154
  MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeRecording, override)
155
  using FilterNode::SetAttribute;
156
157
  explicit FilterNodeRecording(DrawEventRecorderPrivate *aRecorder)
158
    : mRecorder(aRecorder)
159
0
  {
160
0
    mRecorder->AddStoredObject(this);
161
0
  }
162
163
  ~FilterNodeRecording()
164
0
  {
165
0
    mRecorder->RemoveStoredObject(this);
166
0
    mRecorder->RecordEvent(RecordedFilterNodeDestruction(ReferencePtr(this)));
167
0
  }
168
169
  virtual void SetInput(uint32_t aIndex, SourceSurface *aSurface) override
170
0
  {
171
0
    EnsureSurfaceStoredRecording(mRecorder, aSurface,  "SetInput");
172
0
173
0
    mRecorder->RecordEvent(RecordedFilterNodeSetInput(this, aIndex, aSurface));
174
0
  }
175
  virtual void SetInput(uint32_t aIndex, FilterNode *aFilter) override
176
0
  {
177
0
    MOZ_ASSERT(mRecorder->HasStoredObject(aFilter));
178
0
179
0
    mRecorder->RecordEvent(RecordedFilterNodeSetInput(this, aIndex, aFilter));
180
0
  }
181
182
#define FORWARD_SET_ATTRIBUTE(type, argtype) \
183
0
  virtual void SetAttribute(uint32_t aIndex, type aValue) override { \
184
0
    mRecorder->RecordEvent(RecordedFilterNodeSetAttribute(this, aIndex, aValue, RecordedFilterNodeSetAttribute::ARGTYPE_##argtype)); \
185
0
  }
Unexecuted instantiation: mozilla::gfx::FilterNodeRecording::SetAttribute(unsigned int, bool)
Unexecuted instantiation: mozilla::gfx::FilterNodeRecording::SetAttribute(unsigned int, unsigned int)
Unexecuted instantiation: mozilla::gfx::FilterNodeRecording::SetAttribute(unsigned int, float)
Unexecuted instantiation: mozilla::gfx::FilterNodeRecording::SetAttribute(unsigned int, mozilla::gfx::SizeTyped<mozilla::gfx::UnknownUnits, float> const&)
Unexecuted instantiation: mozilla::gfx::FilterNodeRecording::SetAttribute(unsigned int, mozilla::gfx::IntSizeTyped<mozilla::gfx::UnknownUnits> const&)
Unexecuted instantiation: mozilla::gfx::FilterNodeRecording::SetAttribute(unsigned int, mozilla::gfx::IntPointTyped<mozilla::gfx::UnknownUnits> const&)
Unexecuted instantiation: mozilla::gfx::FilterNodeRecording::SetAttribute(unsigned int, mozilla::gfx::RectTyped<mozilla::gfx::UnknownUnits, float> const&)
Unexecuted instantiation: mozilla::gfx::FilterNodeRecording::SetAttribute(unsigned int, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&)
Unexecuted instantiation: mozilla::gfx::FilterNodeRecording::SetAttribute(unsigned int, mozilla::gfx::PointTyped<mozilla::gfx::UnknownUnits, float> const&)
Unexecuted instantiation: mozilla::gfx::FilterNodeRecording::SetAttribute(unsigned int, mozilla::gfx::BaseMatrix<float> const&)
Unexecuted instantiation: mozilla::gfx::FilterNodeRecording::SetAttribute(unsigned int, mozilla::gfx::Matrix5x4 const&)
Unexecuted instantiation: mozilla::gfx::FilterNodeRecording::SetAttribute(unsigned int, mozilla::gfx::Point3DTyped<mozilla::gfx::UnknownUnits, float> const&)
Unexecuted instantiation: mozilla::gfx::FilterNodeRecording::SetAttribute(unsigned int, mozilla::gfx::Color const&)
186
187
  FORWARD_SET_ATTRIBUTE(bool, BOOL);
188
  FORWARD_SET_ATTRIBUTE(uint32_t, UINT32);
189
  FORWARD_SET_ATTRIBUTE(Float, FLOAT);
190
  FORWARD_SET_ATTRIBUTE(const Size&, SIZE);
191
  FORWARD_SET_ATTRIBUTE(const IntSize&, INTSIZE);
192
  FORWARD_SET_ATTRIBUTE(const IntPoint&, INTPOINT);
193
  FORWARD_SET_ATTRIBUTE(const Rect&, RECT);
194
  FORWARD_SET_ATTRIBUTE(const IntRect&, INTRECT);
195
  FORWARD_SET_ATTRIBUTE(const Point&, POINT);
196
  FORWARD_SET_ATTRIBUTE(const Matrix&, MATRIX);
197
  FORWARD_SET_ATTRIBUTE(const Matrix5x4&, MATRIX5X4);
198
  FORWARD_SET_ATTRIBUTE(const Point3D&, POINT3D);
199
  FORWARD_SET_ATTRIBUTE(const Color&, COLOR);
200
201
#undef FORWARD_SET_ATTRIBUTE
202
203
0
  virtual void SetAttribute(uint32_t aIndex, const Float* aFloat, uint32_t aSize) override {
204
0
    mRecorder->RecordEvent(RecordedFilterNodeSetAttribute(this, aIndex, aFloat, aSize));
205
0
  }
206
207
0
  virtual FilterBackend GetBackendType() override { return FILTER_BACKEND_RECORDING; }
208
209
  RefPtr<DrawEventRecorderPrivate> mRecorder;
210
};
211
212
DrawTargetRecording::DrawTargetRecording(DrawEventRecorder *aRecorder, DrawTarget *aDT, IntSize aSize, bool aHasData)
213
  : mRecorder(static_cast<DrawEventRecorderPrivate*>(aRecorder))
214
  , mFinalDT(aDT)
215
  , mSize(aSize)
216
0
{
217
0
  RefPtr<SourceSurface> snapshot = aHasData ? mFinalDT->Snapshot() : nullptr;
218
0
  mRecorder->RecordEvent(RecordedDrawTargetCreation(this,
219
0
                                                    mFinalDT->GetBackendType(),
220
0
                                                    mSize,
221
0
                                                    mFinalDT->GetFormat(),
222
0
                                                    aHasData, snapshot));
223
0
  mFormat = mFinalDT->GetFormat();
224
0
}
225
226
DrawTargetRecording::DrawTargetRecording(const DrawTargetRecording *aDT,
227
                                         IntSize aSize,
228
                                         SurfaceFormat aFormat)
229
  : mRecorder(aDT->mRecorder)
230
  , mFinalDT(aDT->mFinalDT)
231
  , mSize(aSize)
232
0
{
233
0
  mFormat = aFormat;
234
0
}
235
236
DrawTargetRecording::~DrawTargetRecording()
237
0
{
238
0
  mRecorder->RecordEvent(RecordedDrawTargetDestruction(ReferencePtr(this)));
239
0
}
240
241
void
242
DrawTargetRecording::FillRect(const Rect &aRect,
243
                              const Pattern &aPattern,
244
                              const DrawOptions &aOptions)
245
0
{
246
0
  EnsurePatternDependenciesStored(aPattern);
247
0
248
0
  mRecorder->RecordEvent(RecordedFillRect(this, aRect, aPattern, aOptions));
249
0
}
250
251
void
252
DrawTargetRecording::StrokeRect(const Rect &aRect,
253
                                const Pattern &aPattern,
254
                                const StrokeOptions &aStrokeOptions,
255
                                const DrawOptions &aOptions)
256
0
{
257
0
  EnsurePatternDependenciesStored(aPattern);
258
0
259
0
  mRecorder->RecordEvent(RecordedStrokeRect(this, aRect, aPattern, aStrokeOptions, aOptions));
260
0
}
261
262
void
263
DrawTargetRecording::StrokeLine(const Point &aBegin,
264
                                const Point &aEnd,
265
                                const Pattern &aPattern,
266
                                const StrokeOptions &aStrokeOptions,
267
                                const DrawOptions &aOptions)
268
0
{
269
0
  EnsurePatternDependenciesStored(aPattern);
270
0
271
0
  mRecorder->RecordEvent(RecordedStrokeLine(this, aBegin, aEnd, aPattern, aStrokeOptions, aOptions));
272
0
}
273
274
void
275
DrawTargetRecording::Fill(const Path *aPath,
276
                          const Pattern &aPattern,
277
                          const DrawOptions &aOptions)
278
0
{
279
0
  RefPtr<PathRecording> pathRecording = EnsurePathStored(aPath);
280
0
  EnsurePatternDependenciesStored(aPattern);
281
0
282
0
  mRecorder->RecordEvent(RecordedFill(this, pathRecording, aPattern, aOptions));
283
0
}
284
285
struct RecordingFontUserData
286
{
287
  void *refPtr;
288
  RefPtr<DrawEventRecorderPrivate> recorder;
289
};
290
291
void RecordingFontUserDataDestroyFunc(void *aUserData)
292
0
{
293
0
  RecordingFontUserData *userData =
294
0
    static_cast<RecordingFontUserData*>(aUserData);
295
0
296
0
  userData->recorder->RecordEvent(RecordedScaledFontDestruction(ReferencePtr(userData->refPtr)));
297
0
  userData->recorder->RemoveScaledFont((ScaledFont*)userData->refPtr);
298
0
  delete userData;
299
0
}
300
301
void
302
DrawTargetRecording::FillGlyphs(ScaledFont *aFont,
303
                                const GlyphBuffer &aBuffer,
304
                                const Pattern &aPattern,
305
                                const DrawOptions &aOptions)
306
0
{
307
0
  EnsurePatternDependenciesStored(aPattern);
308
0
309
0
  UserDataKey* userDataKey = reinterpret_cast<UserDataKey*>(mRecorder.get());
310
0
  if (mRecorder->WantsExternalFonts()) {
311
0
    mRecorder->AddScaledFont(aFont);
312
0
  } else if (!aFont->GetUserData(userDataKey)) {
313
0
    UnscaledFont* unscaledFont = aFont->GetUnscaledFont();
314
0
    if (!mRecorder->HasStoredObject(unscaledFont)) {
315
0
      RecordedFontData fontData(unscaledFont);
316
0
      RecordedFontDetails fontDetails;
317
0
      if (fontData.GetFontDetails(fontDetails)) {
318
0
        // Try to serialise the whole font, just in case this is a web font that
319
0
        // is not present on the system.
320
0
        if (!mRecorder->HasStoredFontData(fontDetails.fontDataKey)) {
321
0
          mRecorder->RecordEvent(fontData);
322
0
          mRecorder->AddStoredFontData(fontDetails.fontDataKey);
323
0
        }
324
0
        mRecorder->RecordEvent(RecordedUnscaledFontCreation(unscaledFont, fontDetails));
325
0
      } else {
326
0
        // If that fails, record just the font description and try to load it from
327
0
        // the system on the other side.
328
0
        RecordedFontDescriptor fontDesc(unscaledFont);
329
0
        if (fontDesc.IsValid()) {
330
0
          mRecorder->RecordEvent(fontDesc);
331
0
        } else {
332
0
          gfxWarning() << "DrawTargetRecording::FillGlyphs failed to serialise UnscaledFont";
333
0
        }
334
0
      }
335
0
      mRecorder->AddStoredObject(unscaledFont);
336
0
    }
337
0
    mRecorder->RecordEvent(RecordedScaledFontCreation(aFont, unscaledFont));
338
0
    RecordingFontUserData *userData = new RecordingFontUserData;
339
0
    userData->refPtr = aFont;
340
0
    userData->recorder = mRecorder;
341
0
    aFont->AddUserData(userDataKey, userData, &RecordingFontUserDataDestroyFunc);
342
0
    userData->recorder->AddScaledFont(aFont);
343
0
  }
344
0
345
0
  mRecorder->RecordEvent(RecordedFillGlyphs(this, aFont, aPattern, aOptions, aBuffer.mGlyphs, aBuffer.mNumGlyphs));
346
0
}
347
348
void
349
DrawTargetRecording::Mask(const Pattern &aSource,
350
                          const Pattern &aMask,
351
                          const DrawOptions &aOptions)
352
0
{
353
0
  EnsurePatternDependenciesStored(aSource);
354
0
  EnsurePatternDependenciesStored(aMask);
355
0
356
0
  mRecorder->RecordEvent(RecordedMask(this, aSource, aMask, aOptions));
357
0
}
358
359
void
360
DrawTargetRecording::MaskSurface(const Pattern &aSource,
361
                                 SourceSurface *aMask,
362
                                 Point aOffset,
363
                                 const DrawOptions &aOptions)
364
0
{
365
0
  EnsurePatternDependenciesStored(aSource);
366
0
  EnsureSurfaceStoredRecording(mRecorder, aMask, "MaskSurface");
367
0
368
0
  mRecorder->RecordEvent(RecordedMaskSurface(this, aSource, aMask, aOffset, aOptions));
369
0
}
370
371
void
372
DrawTargetRecording::Stroke(const Path *aPath,
373
                            const Pattern &aPattern,
374
                            const StrokeOptions &aStrokeOptions,
375
                            const DrawOptions &aOptions)
376
0
{
377
0
  RefPtr<PathRecording> pathRecording = EnsurePathStored(aPath);
378
0
  EnsurePatternDependenciesStored(aPattern);
379
0
380
0
  mRecorder->RecordEvent(RecordedStroke(this, pathRecording, aPattern, aStrokeOptions, aOptions));
381
0
}
382
383
already_AddRefed<SourceSurface>
384
DrawTargetRecording::Snapshot()
385
0
{
386
0
  RefPtr<SourceSurface> retSurf = new SourceSurfaceRecording(mSize, mFormat, mRecorder);
387
0
388
0
  mRecorder->RecordEvent(RecordedSnapshot(retSurf, this));
389
0
390
0
  return retSurf.forget();
391
0
}
392
393
already_AddRefed<SourceSurface>
394
DrawTargetRecording::IntoLuminanceSource(LuminanceType aLuminanceType, float aOpacity)
395
0
{
396
0
  RefPtr<SourceSurface> retSurf = new SourceSurfaceRecording(mSize, SurfaceFormat::A8, mRecorder);
397
0
398
0
  mRecorder->RecordEvent(RecordedIntoLuminanceSource(retSurf, this, aLuminanceType, aOpacity));
399
0
400
0
  return retSurf.forget();
401
0
}
402
403
void
404
DrawTargetRecording::DetachAllSnapshots()
405
0
{
406
0
}
407
408
void
409
DrawTargetRecording::DrawSurface(SourceSurface *aSurface,
410
                                 const Rect &aDest,
411
                                 const Rect &aSource,
412
                                 const DrawSurfaceOptions &aSurfOptions,
413
                                 const DrawOptions &aOptions)
414
0
{
415
0
  EnsureSurfaceStoredRecording(mRecorder, aSurface, "DrawSurface");
416
0
417
0
  mRecorder->RecordEvent(RecordedDrawSurface(this, aSurface, aDest, aSource, aSurfOptions, aOptions));
418
0
}
419
420
void
421
DrawTargetRecording::DrawSurfaceWithShadow(SourceSurface *aSurface,
422
                                           const Point &aDest,
423
                                           const Color &aColor,
424
                                           const Point &aOffset,
425
                                           Float aSigma,
426
                                           CompositionOp aOp)
427
0
{
428
0
  EnsureSurfaceStoredRecording(mRecorder, aSurface, "DrawSurfaceWithShadow");
429
0
430
0
  mRecorder->RecordEvent(RecordedDrawSurfaceWithShadow(this, aSurface, aDest, aColor, aOffset, aSigma, aOp));
431
0
}
432
433
void
434
DrawTargetRecording::DrawFilter(FilterNode *aNode,
435
                                const Rect &aSourceRect,
436
                                const Point &aDestPoint,
437
                                const DrawOptions &aOptions)
438
0
{
439
0
  MOZ_ASSERT(mRecorder->HasStoredObject(aNode));
440
0
441
0
  mRecorder->RecordEvent(RecordedDrawFilter(this, aNode, aSourceRect, aDestPoint, aOptions));
442
0
}
443
444
already_AddRefed<FilterNode>
445
DrawTargetRecording::CreateFilter(FilterType aType)
446
0
{
447
0
  RefPtr<FilterNode> retNode = new FilterNodeRecording(mRecorder);
448
0
449
0
  mRecorder->RecordEvent(RecordedFilterNodeCreation(retNode, aType));
450
0
451
0
  return retNode.forget();
452
0
}
453
454
void
455
DrawTargetRecording::ClearRect(const Rect &aRect)
456
0
{
457
0
  mRecorder->RecordEvent(RecordedClearRect(this, aRect));
458
0
}
459
460
void
461
DrawTargetRecording::CopySurface(SourceSurface *aSurface,
462
                                 const IntRect &aSourceRect,
463
                                 const IntPoint &aDestination)
464
0
{
465
0
  EnsureSurfaceStoredRecording(mRecorder, aSurface, "CopySurface");
466
0
467
0
  mRecorder->RecordEvent(RecordedCopySurface(this, aSurface, aSourceRect, aDestination));
468
0
}
469
470
void
471
DrawTargetRecording::PushClip(const Path *aPath)
472
0
{
473
0
  RefPtr<PathRecording> pathRecording = EnsurePathStored(aPath);
474
0
475
0
  mRecorder->RecordEvent(RecordedPushClip(this, pathRecording));
476
0
}
477
478
void
479
DrawTargetRecording::PushClipRect(const Rect &aRect)
480
0
{
481
0
  mRecorder->RecordEvent(RecordedPushClipRect(this, aRect));
482
0
}
483
484
void
485
DrawTargetRecording::PopClip()
486
0
{
487
0
  mRecorder->RecordEvent(RecordedPopClip(static_cast<DrawTarget*>(this)));
488
0
}
489
490
void
491
DrawTargetRecording::PushLayer(bool aOpaque, Float aOpacity,
492
                               SourceSurface* aMask,
493
                               const Matrix& aMaskTransform,
494
                               const IntRect& aBounds, bool aCopyBackground)
495
0
{
496
0
  if (aMask) {
497
0
    EnsureSurfaceStoredRecording(mRecorder, aMask, "PushLayer");
498
0
  }
499
0
500
0
  mRecorder->RecordEvent(RecordedPushLayer(this, aOpaque, aOpacity, aMask,
501
0
                                           aMaskTransform, aBounds,
502
0
                                           aCopyBackground));
503
0
}
504
505
void
506
DrawTargetRecording::PushLayerWithBlend(bool aOpaque, Float aOpacity,
507
                                        SourceSurface* aMask,
508
                                        const Matrix& aMaskTransform,
509
                                        const IntRect& aBounds,
510
                                        bool aCopyBackground,
511
                                        CompositionOp aCompositionOp)
512
0
{
513
0
  if (aMask) {
514
0
    EnsureSurfaceStoredRecording(mRecorder, aMask, "PushLayer");
515
0
  }
516
0
517
0
  mRecorder->RecordEvent(RecordedPushLayerWithBlend(this, aOpaque, aOpacity, aMask,
518
0
                                           aMaskTransform, aBounds,
519
0
                                           aCopyBackground, aCompositionOp));
520
0
}
521
522
void
523
DrawTargetRecording::PopLayer()
524
0
{
525
0
  mRecorder->RecordEvent(RecordedPopLayer(static_cast<DrawTarget*>(this)));
526
0
}
527
528
already_AddRefed<SourceSurface>
529
DrawTargetRecording::CreateSourceSurfaceFromData(unsigned char *aData,
530
                                                 const IntSize &aSize,
531
                                                 int32_t aStride,
532
                                                 SurfaceFormat aFormat) const
533
0
{
534
0
  RefPtr<SourceSurface> surf = DataSourceSurfaceRecording::Init(aData, aSize, aStride, aFormat);
535
0
536
0
  RefPtr<SourceSurface> retSurf = new SourceSurfaceRecording(aSize, aFormat, mRecorder);
537
0
538
0
  mRecorder->RecordEvent(RecordedSourceSurfaceCreation(retSurf, aData, aStride, aSize, aFormat));
539
0
540
0
  return retSurf.forget();
541
0
}
542
543
already_AddRefed<SourceSurface>
544
DrawTargetRecording::OptimizeSourceSurface(SourceSurface *aSurface) const
545
0
{
546
0
  RefPtr<SourceSurface> surf(aSurface);
547
0
  return surf.forget();
548
0
}
549
550
already_AddRefed<SourceSurface>
551
DrawTargetRecording::CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const
552
0
{
553
0
  MOZ_ASSERT(false);
554
0
  return nullptr;
555
0
}
556
557
already_AddRefed<DrawTarget>
558
DrawTargetRecording::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const
559
0
{
560
0
  RefPtr<DrawTarget> similarDT = new DrawTargetRecording(this, aSize, aFormat);
561
0
  mRecorder->RecordEvent(RecordedCreateSimilarDrawTarget(similarDT.get(),
562
0
                                                         aSize,
563
0
                                                         aFormat));
564
0
  return similarDT.forget();
565
0
}
566
567
RefPtr<DrawTarget>
568
DrawTargetRecording::CreateClippedDrawTarget(const IntSize& aMaxSize, const Matrix& aTransform, SurfaceFormat aFormat) const
569
0
{
570
0
  RefPtr<DrawTarget> similarDT = new DrawTargetRecording(this, aMaxSize, aFormat);
571
0
  mRecorder->RecordEvent(RecordedCreateClippedDrawTarget(similarDT.get(), aMaxSize, aTransform, aFormat));
572
0
  return similarDT;
573
0
}
574
575
already_AddRefed<PathBuilder>
576
DrawTargetRecording::CreatePathBuilder(FillRule aFillRule) const
577
0
{
578
0
  RefPtr<PathBuilder> builder = mFinalDT->CreatePathBuilder(aFillRule);
579
0
  return MakeAndAddRef<PathBuilderRecording>(builder, aFillRule);
580
0
}
581
582
already_AddRefed<GradientStops>
583
DrawTargetRecording::CreateGradientStops(GradientStop *aStops,
584
                                         uint32_t aNumStops,
585
                                         ExtendMode aExtendMode) const
586
0
{
587
0
  RefPtr<GradientStops> retStops = new GradientStopsRecording(mRecorder);
588
0
589
0
  mRecorder->RecordEvent(RecordedGradientStopsCreation(retStops, aStops, aNumStops, aExtendMode));
590
0
591
0
  return retStops.forget();
592
0
}
593
594
void
595
DrawTargetRecording::SetTransform(const Matrix &aTransform)
596
0
{
597
0
  mRecorder->RecordEvent(RecordedSetTransform(this, aTransform));
598
0
  DrawTarget::SetTransform(aTransform);
599
0
}
600
601
already_AddRefed<PathRecording>
602
DrawTargetRecording::EnsurePathStored(const Path *aPath)
603
0
{
604
0
  RefPtr<PathRecording> pathRecording;
605
0
  if (aPath->GetBackendType() == BackendType::RECORDING) {
606
0
    pathRecording = const_cast<PathRecording*>(static_cast<const PathRecording*>(aPath));
607
0
    if (mRecorder->HasStoredObject(aPath)) {
608
0
      return pathRecording.forget();
609
0
    }
610
0
  } else {
611
0
    MOZ_ASSERT(!mRecorder->HasStoredObject(aPath));
612
0
    FillRule fillRule = aPath->GetFillRule();
613
0
    RefPtr<PathBuilder> builder = mFinalDT->CreatePathBuilder(fillRule);
614
0
    RefPtr<PathBuilderRecording> builderRecording =
615
0
      new PathBuilderRecording(builder, fillRule);
616
0
    aPath->StreamToSink(builderRecording);
617
0
    pathRecording = builderRecording->Finish().downcast<PathRecording>();
618
0
  }
619
0
620
0
  mRecorder->RecordEvent(RecordedPathCreation(pathRecording.get()));
621
0
  mRecorder->AddStoredObject(pathRecording);
622
0
  pathRecording->mStoredRecorders.push_back(mRecorder);
623
0
624
0
  return pathRecording.forget();
625
0
}
626
627
// This should only be called on the 'root' DrawTargetRecording.
628
// Calling it on a child DrawTargetRecordings will cause confusion.
629
void
630
DrawTargetRecording::FlushItem(const IntRect &aBounds)
631
0
{
632
0
  mRecorder->FlushItem(aBounds);
633
0
  // Reinitialize the recorder (FlushItem will write a new recording header)
634
0
  // Tell the new recording about our draw target
635
0
  // This code should match what happens in the DrawTargetRecording constructor.
636
0
  mRecorder->RecordEvent(RecordedDrawTargetCreation(this,
637
0
                                                    mFinalDT->GetBackendType(),
638
0
                                                    mSize,
639
0
                                                    mFinalDT->GetFormat(),
640
0
                                                    false, nullptr));
641
0
  // Add the current transform to the new recording
642
0
  mRecorder->RecordEvent(RecordedSetTransform(this, DrawTarget::GetTransform()));
643
0
}
644
645
void
646
DrawTargetRecording::EnsurePatternDependenciesStored(const Pattern &aPattern)
647
0
{
648
0
  switch (aPattern.GetType()) {
649
0
  case PatternType::COLOR:
650
0
    // No dependencies here.
651
0
    return;
652
0
  case PatternType::LINEAR_GRADIENT:
653
0
    {
654
0
      MOZ_ASSERT(mRecorder->HasStoredObject(static_cast<const LinearGradientPattern*>(&aPattern)->mStops));
655
0
      return;
656
0
    }
657
0
  case PatternType::RADIAL_GRADIENT:
658
0
    {
659
0
      MOZ_ASSERT(mRecorder->HasStoredObject(static_cast<const RadialGradientPattern*>(&aPattern)->mStops));
660
0
      return;
661
0
    }
662
0
  case PatternType::SURFACE:
663
0
    {
664
0
      const SurfacePattern *pat = static_cast<const SurfacePattern*>(&aPattern);
665
0
      EnsureSurfaceStoredRecording(mRecorder, pat->mSurface, "EnsurePatternDependenciesStored");
666
0
      return;
667
0
    }
668
0
  }
669
0
}
670
671
} // namespace gfx
672
} // namespace mozilla