Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/2d/DrawTargetCapture.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 "DrawTargetCapture.h"
8
#include "DrawCommand.h"
9
#include "DrawCommands.h"
10
#include "gfxPlatform.h"
11
#include "SourceSurfaceCapture.h"
12
#include "FilterNodeCapture.h"
13
14
namespace mozilla {
15
namespace gfx {
16
17
18
DrawTargetCaptureImpl::~DrawTargetCaptureImpl()
19
0
{
20
0
  if (mSnapshot && !mSnapshot->hasOneRef()) {
21
0
    mSnapshot->DrawTargetWillDestroy();
22
0
    mSnapshot = nullptr;
23
0
  }
24
0
}
25
26
DrawTargetCaptureImpl::DrawTargetCaptureImpl(gfx::DrawTarget* aTarget, size_t aFlushBytes)
27
  : mSnapshot(nullptr),
28
    mStride(0),
29
    mSurfaceAllocationSize(0),
30
    mFlushBytes(aFlushBytes)
31
0
{
32
0
  mSize = aTarget->GetSize();
33
0
  mFormat = aTarget->GetFormat();
34
0
  SetPermitSubpixelAA(aTarget->GetPermitSubpixelAA());
35
0
36
0
  mRefDT = aTarget;
37
0
}
38
39
DrawTargetCaptureImpl::DrawTargetCaptureImpl(BackendType aBackend,
40
                                             const IntSize& aSize,
41
                                             SurfaceFormat aFormat)
42
  : mSize(aSize),
43
    mSnapshot(nullptr),
44
    mStride(0),
45
    mSurfaceAllocationSize(0),
46
    mFlushBytes(0)
47
0
{
48
0
  RefPtr<DrawTarget> screenRefDT =
49
0
      gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
50
0
51
0
  mFormat = aFormat;
52
0
  SetPermitSubpixelAA(IsOpaque(mFormat));
53
0
  if (aBackend == screenRefDT->GetBackendType()) {
54
0
    mRefDT = screenRefDT;
55
0
  } else {
56
0
    // This situation can happen if a blur operation decides to
57
0
    // use an unaccelerated path even if the system backend is
58
0
    // Direct2D.
59
0
    //
60
0
    // We don't really want to encounter the reverse scenario:
61
0
    // we shouldn't pick an accelerated backend if the system
62
0
    // backend is skia.
63
0
    if (aBackend == BackendType::DIRECT2D1_1) {
64
0
      gfxWarning() << "Creating a RefDT in DrawTargetCapture.";
65
0
    }
66
0
67
0
    // Create a 1x1 size ref dt to create assets
68
0
    // If we have to snapshot, we'll just create the real DT
69
0
    IntSize size(1, 1);
70
0
    mRefDT = Factory::CreateDrawTarget(aBackend, size, mFormat);
71
0
  }
72
0
}
73
74
bool
75
DrawTargetCaptureImpl::Init(const IntSize& aSize, DrawTarget* aRefDT)
76
0
{
77
0
  if (!aRefDT) {
78
0
    return false;
79
0
  }
80
0
81
0
  mRefDT = aRefDT;
82
0
83
0
  mSize = aSize;
84
0
  mFormat = aRefDT->GetFormat();
85
0
  SetPermitSubpixelAA(IsOpaque(mFormat));
86
0
  return true;
87
0
}
88
89
void
90
DrawTargetCaptureImpl::InitForData(int32_t aStride, size_t aSurfaceAllocationSize)
91
0
{
92
0
  MOZ_ASSERT(!mFlushBytes);
93
0
  mStride = aStride;
94
0
  mSurfaceAllocationSize = aSurfaceAllocationSize;
95
0
}
96
97
already_AddRefed<SourceSurface>
98
DrawTargetCaptureImpl::Snapshot()
99
0
{
100
0
  if (!mSnapshot) {
101
0
    mSnapshot = new SourceSurfaceCapture(this);
102
0
  }
103
0
104
0
  RefPtr<SourceSurface> surface = mSnapshot;
105
0
  return surface.forget();
106
0
}
107
108
already_AddRefed<SourceSurface>
109
DrawTargetCaptureImpl::IntoLuminanceSource(LuminanceType aLuminanceType,
110
                                           float aOpacity)
111
0
{
112
0
  RefPtr<SourceSurface> surface = new SourceSurfaceCapture(this, aLuminanceType, aOpacity);
113
0
  return surface.forget();
114
0
}
115
116
already_AddRefed<SourceSurface>
117
DrawTargetCaptureImpl::OptimizeSourceSurface(SourceSurface *aSurface) const
118
0
{
119
0
  // If the surface is a recording, make sure it gets resolved on the paint thread.
120
0
  if (aSurface->GetType() == SurfaceType::CAPTURE) {
121
0
    RefPtr<SourceSurface> surface = aSurface;
122
0
    return surface.forget();
123
0
  }
124
0
  return mRefDT->OptimizeSourceSurface(aSurface);
125
0
}
126
127
void
128
DrawTargetCaptureImpl::DetachAllSnapshots()
129
0
{
130
0
  MarkChanged();
131
0
}
132
133
0
#define AppendCommand(arg) new (AppendToCommandList<arg>()) arg
134
0
#define ReuseOrAppendCommand(arg) new (ReuseOrAppendToCommandList<arg>()) arg
135
136
void
137
DrawTargetCaptureImpl::SetPermitSubpixelAA(bool aPermitSubpixelAA)
138
0
{
139
0
  // Save memory by eliminating state changes with no effect
140
0
  if (mPermitSubpixelAA == aPermitSubpixelAA) {
141
0
    return;
142
0
  }
143
0
144
0
  ReuseOrAppendCommand(SetPermitSubpixelAACommand)(aPermitSubpixelAA);
145
0
146
0
  // Have to update mPermitSubpixelAA for this DT
147
0
  // because some code paths query the current setting
148
0
  // to determine subpixel AA eligibility.
149
0
  DrawTarget::SetPermitSubpixelAA(aPermitSubpixelAA);
150
0
}
151
152
void
153
DrawTargetCaptureImpl::DrawSurface(SourceSurface *aSurface,
154
                                   const Rect &aDest,
155
                                   const Rect &aSource,
156
                                   const DrawSurfaceOptions &aSurfOptions,
157
                                   const DrawOptions &aOptions)
158
0
{
159
0
  aSurface->GuaranteePersistance();
160
0
  AppendCommand(DrawSurfaceCommand)(aSurface, aDest, aSource, aSurfOptions, aOptions);
161
0
}
162
163
void
164
DrawTargetCaptureImpl::DrawSurfaceWithShadow(SourceSurface *aSurface,
165
                                             const Point &aDest,
166
                                             const Color &aColor,
167
                                             const Point &aOffset,
168
                                             Float aSigma,
169
                                             CompositionOp aOperator)
170
0
{
171
0
  aSurface->GuaranteePersistance();
172
0
  AppendCommand(DrawSurfaceWithShadowCommand)(aSurface, aDest, aColor, aOffset, aSigma, aOperator);
173
0
}
174
175
void
176
DrawTargetCaptureImpl::DrawFilter(FilterNode *aNode,
177
                                  const Rect &aSourceRect,
178
                                  const Point &aDestPoint,
179
                                  const DrawOptions &aOptions)
180
0
{
181
0
  // @todo XXX - this won't work properly long term yet due to filternodes not
182
0
  // being immutable.
183
0
  AppendCommand(DrawFilterCommand)(aNode, aSourceRect, aDestPoint, aOptions);
184
0
}
185
186
void
187
DrawTargetCaptureImpl::ClearRect(const Rect &aRect)
188
0
{
189
0
  AppendCommand(ClearRectCommand)(aRect);
190
0
}
191
192
void
193
DrawTargetCaptureImpl::MaskSurface(const Pattern &aSource,
194
                                   SourceSurface *aMask,
195
                                   Point aOffset,
196
                                   const DrawOptions &aOptions)
197
0
{
198
0
  aMask->GuaranteePersistance();
199
0
  AppendCommand(MaskSurfaceCommand)(aSource, aMask, aOffset, aOptions);
200
0
}
201
202
void
203
DrawTargetCaptureImpl::CopySurface(SourceSurface* aSurface,
204
                                   const IntRect& aSourceRect,
205
                                   const IntPoint& aDestination)
206
0
{
207
0
  aSurface->GuaranteePersistance();
208
0
  AppendCommand(CopySurfaceCommand)(aSurface, aSourceRect, aDestination);
209
0
}
210
211
void
212
DrawTargetCaptureImpl::CopyRect(const IntRect &aSourceRect,
213
                                const IntPoint &aDestination)
214
0
{
215
0
  AppendCommand(CopyRectCommand)(aSourceRect, aDestination);
216
0
}
217
218
void
219
DrawTargetCaptureImpl::FillRect(const Rect& aRect,
220
                                const Pattern& aPattern,
221
                                const DrawOptions& aOptions)
222
0
{
223
0
  AppendCommand(FillRectCommand)(aRect, aPattern, aOptions);
224
0
}
225
226
void
227
DrawTargetCaptureImpl::StrokeRect(const Rect& aRect,
228
                                  const Pattern& aPattern,
229
                                  const StrokeOptions& aStrokeOptions,
230
                                  const DrawOptions& aOptions)
231
0
{
232
0
  AppendCommand(StrokeRectCommand)(aRect, aPattern, aStrokeOptions, aOptions);
233
0
}
234
235
void
236
DrawTargetCaptureImpl::StrokeLine(const Point& aStart,
237
                                  const Point& aEnd,
238
                                  const Pattern& aPattern,
239
                                  const StrokeOptions& aStrokeOptions,
240
                                  const DrawOptions& aOptions)
241
0
{
242
0
  AppendCommand(StrokeLineCommand)(aStart, aEnd, aPattern, aStrokeOptions, aOptions);
243
0
}
244
245
void
246
DrawTargetCaptureImpl::Stroke(const Path* aPath,
247
                              const Pattern& aPattern,
248
                              const StrokeOptions& aStrokeOptions,
249
                              const DrawOptions& aOptions)
250
0
{
251
0
  AppendCommand(StrokeCommand)(aPath, aPattern, aStrokeOptions, aOptions);
252
0
}
253
254
void
255
DrawTargetCaptureImpl::Fill(const Path* aPath,
256
                            const Pattern& aPattern,
257
                            const DrawOptions& aOptions)
258
0
{
259
0
  AppendCommand(FillCommand)(aPath, aPattern, aOptions);
260
0
}
261
262
void
263
DrawTargetCaptureImpl::FillGlyphs(ScaledFont* aFont,
264
                                  const GlyphBuffer& aBuffer,
265
                                  const Pattern& aPattern,
266
                                  const DrawOptions& aOptions)
267
0
{
268
0
  AppendCommand(FillGlyphsCommand)(aFont, aBuffer, aPattern, aOptions);
269
0
}
270
271
void DrawTargetCaptureImpl::StrokeGlyphs(ScaledFont* aFont,
272
                                         const GlyphBuffer& aBuffer,
273
                                         const Pattern& aPattern,
274
                                         const StrokeOptions& aStrokeOptions,
275
                                         const DrawOptions& aOptions)
276
0
{
277
0
  AppendCommand(StrokeGlyphsCommand)(aFont, aBuffer, aPattern, aStrokeOptions, aOptions);
278
0
}
279
280
void
281
DrawTargetCaptureImpl::Mask(const Pattern &aSource,
282
                            const Pattern &aMask,
283
                            const DrawOptions &aOptions)
284
0
{
285
0
  AppendCommand(MaskCommand)(aSource, aMask, aOptions);
286
0
}
287
288
void
289
DrawTargetCaptureImpl::PushClip(const Path* aPath)
290
0
{
291
0
  AppendCommand(PushClipCommand)(aPath);
292
0
}
293
294
void
295
DrawTargetCaptureImpl::PushClipRect(const Rect& aRect)
296
0
{
297
0
  AppendCommand(PushClipRectCommand)(aRect);
298
0
}
299
300
void
301
DrawTargetCaptureImpl::PushLayer(bool aOpaque,
302
                                 Float aOpacity,
303
                                 SourceSurface* aMask,
304
                                 const Matrix& aMaskTransform,
305
                                 const IntRect& aBounds,
306
                                 bool aCopyBackground)
307
0
{
308
0
  // Have to update mPermitSubpixelAA for this DT
309
0
  // because some code paths query the current setting
310
0
  // to determine subpixel AA eligibility.
311
0
  PushedLayer layer(GetPermitSubpixelAA());
312
0
  mPushedLayers.push_back(layer);
313
0
  DrawTarget::SetPermitSubpixelAA(aOpaque);
314
0
315
0
  if (aMask) {
316
0
    aMask->GuaranteePersistance();
317
0
  }
318
0
319
0
  AppendCommand(PushLayerCommand)(aOpaque,
320
0
                                  aOpacity,
321
0
                                  aMask,
322
0
                                  aMaskTransform,
323
0
                                  aBounds,
324
0
                                  aCopyBackground);
325
0
}
326
327
void
328
DrawTargetCaptureImpl::PopLayer()
329
0
{
330
0
  MOZ_ASSERT(mPushedLayers.size());
331
0
  DrawTarget::SetPermitSubpixelAA(mPushedLayers.back().mOldPermitSubpixelAA);
332
0
  mPushedLayers.pop_back();
333
0
334
0
  AppendCommand(PopLayerCommand)();
335
0
}
336
337
void
338
DrawTargetCaptureImpl::PopClip()
339
0
{
340
0
  AppendCommand(PopClipCommand)();
341
0
}
342
343
void
344
DrawTargetCaptureImpl::SetTransform(const Matrix& aTransform)
345
0
{
346
0
  // Save memory by eliminating state changes with no effect
347
0
  if (mTransform.ExactlyEquals(aTransform)) {
348
0
    return;
349
0
  }
350
0
351
0
  ReuseOrAppendCommand(SetTransformCommand)(aTransform);
352
0
353
0
  // Have to update the transform for this DT
354
0
  // because some code paths query the current transform
355
0
  // to render specific things.
356
0
  DrawTarget::SetTransform(aTransform);
357
0
}
358
359
void
360
DrawTargetCaptureImpl::Blur(const AlphaBoxBlur& aBlur)
361
0
{
362
0
  // gfxAlphaBoxBlur should not use this if it takes the accelerated path.
363
0
  MOZ_ASSERT(GetBackendType() == BackendType::SKIA);
364
0
365
0
  AppendCommand(BlurCommand)(aBlur);
366
0
}
367
368
void
369
DrawTargetCaptureImpl::PadEdges(const IntRegion& aRegion)
370
0
{
371
0
  AppendCommand(PadEdgesCommand)(aRegion);
372
0
}
373
374
void
375
DrawTargetCaptureImpl::ReplayToDrawTarget(DrawTarget* aDT, const Matrix& aTransform)
376
0
{
377
0
  for (CaptureCommandList::iterator iter(mCommands); !iter.Done(); iter.Next()) {
378
0
    DrawingCommand* cmd = iter.Get();
379
0
    cmd->ExecuteOnDT(aDT, &aTransform);
380
0
  }
381
0
}
382
383
void
384
DrawTargetCaptureImpl::MarkChanged()
385
0
{
386
0
  if (!mSnapshot) {
387
0
    return;
388
0
  }
389
0
390
0
  if (mSnapshot->hasOneRef()) {
391
0
    mSnapshot = nullptr;
392
0
    return;
393
0
  }
394
0
395
0
  mSnapshot->DrawTargetWillChange();
396
0
  mSnapshot = nullptr;
397
0
}
398
399
already_AddRefed<DrawTarget>
400
DrawTargetCaptureImpl::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const
401
0
{
402
0
  return MakeAndAddRef<DrawTargetCaptureImpl>(GetBackendType(), aSize, aFormat);
403
0
}
404
405
RefPtr<DrawTarget>
406
DrawTargetCaptureImpl::CreateSimilarRasterTarget(const IntSize& aSize, SurfaceFormat aFormat) const
407
0
{
408
0
  MOZ_ASSERT(!mRefDT->IsCaptureDT());
409
0
  return mRefDT->CreateSimilarDrawTarget(aSize, aFormat);
410
0
}
411
412
already_AddRefed<FilterNode>
413
DrawTargetCaptureImpl::CreateFilter(FilterType aType)
414
0
{
415
0
  if (mRefDT->GetBackendType() == BackendType::DIRECT2D1_1) {
416
0
    return MakeRefPtr<FilterNodeCapture>(aType).forget();
417
0
  } else {
418
0
    return mRefDT->CreateFilter(aType);
419
0
  }
420
0
}
421
422
bool
423
DrawTargetCaptureImpl::IsEmpty() const
424
0
{
425
0
  return mCommands.IsEmpty();
426
0
}
427
428
void
429
DrawTargetCaptureImpl::Dump()
430
0
{
431
0
  TreeLog output;
432
0
  output << "DrawTargetCapture(" << (void*)(this) << ")\n";
433
0
  TreeAutoIndent indent(output);
434
0
  mCommands.Log(output);
435
0
  output << "\n";
436
0
}
437
438
} // namespace gfx
439
} // namespace mozilla