Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/layers/LayerMetricsWrapper.h
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
#ifndef GFX_LAYERMETRICSWRAPPER_H
8
#define GFX_LAYERMETRICSWRAPPER_H
9
10
#include "Layers.h"
11
#include "UnitTransforms.h"
12
13
namespace mozilla {
14
namespace layers {
15
16
/**
17
 * A wrapper class around a target Layer with that allows user code to
18
 * walk through the FrameMetrics objects on the layer the same way it
19
 * would walk through a ContainerLayer hierarchy. Consider the following
20
 * layer tree:
21
 *
22
 *                    +---+
23
 *                    | A |
24
 *                    +---+
25
 *                   /  |  \
26
 *                  /   |   \
27
 *                 /    |    \
28
 *            +---+  +-----+  +---+
29
 *            | B |  |  C  |  | D |
30
 *            +---+  +-----+  +---+
31
 *                   | FMn |
32
 *                   |  .  |
33
 *                   |  .  |
34
 *                   |  .  |
35
 *                   | FM1 |
36
 *                   | FM0 |
37
 *                   +-----+
38
 *                   /     \
39
 *                  /       \
40
 *             +---+         +---+
41
 *             | E |         | F |
42
 *             +---+         +---+
43
 *
44
 * In this layer tree, there are six layers with A being the root and B,D,E,F
45
 * being leaf nodes. Layer C is in the middle and has n+1 FrameMetrics, labelled
46
 * FM0...FMn. FM0 is the FrameMetrics you get by calling c->GetFrameMetrics(0)
47
 * and FMn is the FrameMetrics you can obtain by calling
48
 * c->GetFrameMetrics(c->GetScrollMetadataCount() - 1). This layer tree is
49
 * conceptually equivalent to this one below:
50
 *
51
 *                    +---+
52
 *                    | A |
53
 *                    +---+
54
 *                   /  |  \
55
 *                  /   |   \
56
 *                 /    |    \
57
 *            +---+  +-----+  +---+
58
 *            | B |  | Cn  |  | D |
59
 *            +---+  +-----+  +---+
60
 *                      |
61
 *                      .
62
 *                      .
63
 *                      .
64
 *                      |
65
 *                   +-----+
66
 *                   | C1  |
67
 *                   +-----+
68
 *                      |
69
 *                   +-----+
70
 *                   | C0  |
71
 *                   +-----+
72
 *                   /     \
73
 *                  /       \
74
 *             +---+         +---+
75
 *             | E |         | F |
76
 *             +---+         +---+
77
 *
78
 * In this layer tree, the layer C has been expanded into a stack of container
79
 * layers C1...Cn, where C1 has FrameMetrics FM1 and Cn has FrameMetrics Fn.
80
 * Although in this example C (in the first layer tree) and C0 (in the second
81
 * layer tree) are both ContainerLayers (because they have children), they
82
 * do not have to be. They may just be PaintedLayers or ColorLayers, for example,
83
 * which do not have any children. However, the type of C will always be the
84
 * same as the type of C0.
85
 *
86
 * The LayerMetricsWrapper class allows client code to treat the first layer
87
 * tree as though it were the second. That is, instead of client code having
88
 * to iterate through the FrameMetrics objects directly, it can use a
89
 * LayerMetricsWrapper to encapsulate that aspect of the layer tree and just
90
 * walk the tree as if it were a stack of ContainerLayers.
91
 *
92
 * The functions on this class do different things depending on which
93
 * simulated ContainerLayer is being wrapped. For example, if the
94
 * LayerMetricsWrapper is pretending to be C0, the GetNextSibling() function
95
 * will return null even though the underlying layer C does actually have
96
 * a next sibling. The LayerMetricsWrapper pretending to be Cn will return
97
 * D as the next sibling.
98
 *
99
 * Implementation notes:
100
 *
101
 * The AtTopLayer() and AtBottomLayer() functions in this class refer to
102
 * Cn and C0 in the second layer tree above; that is, they are predicates
103
 * to test if the LayerMetricsWrapper is simulating the topmost or bottommost
104
 * layer, as those will have special behaviour.
105
 *
106
 * It is possible to wrap a nullptr in a LayerMetricsWrapper, in which case
107
 * the IsValid() function will return false. This is required to allow
108
 * LayerMetricsWrapper to be a MOZ_STACK_CLASS (desirable because it is used
109
 * in loops and recursion).
110
 *
111
 * This class purposely does not expose the wrapped layer directly to avoid
112
 * user code from accidentally calling functions directly on it. Instead
113
 * any necessary functions should be wrapped in this class. It does expose
114
 * the wrapped layer as a void* for printf purposes.
115
 *
116
 * The implementation may look like it special-cases mIndex == 0 and/or
117
 * GetScrollMetadataCount() == 0. This is an artifact of the fact that both
118
 * mIndex and GetScrollMetadataCount() are uint32_t and GetScrollMetadataCount()
119
 * can return 0 but mIndex cannot store -1. This seems better than the
120
 * alternative of making mIndex a int32_t that can store -1, but then having
121
 * to cast to uint32_t all over the place.
122
 */
123
class MOZ_STACK_CLASS LayerMetricsWrapper {
124
public:
125
  enum StartAt {
126
    TOP,
127
    BOTTOM,
128
  };
129
130
  LayerMetricsWrapper()
131
    : mLayer(nullptr)
132
    , mIndex(0)
133
0
  {
134
0
  }
135
136
  explicit LayerMetricsWrapper(Layer* aRoot, StartAt aStart = StartAt::TOP)
137
    : mLayer(aRoot)
138
    , mIndex(0)
139
0
  {
140
0
    if (!mLayer) {
141
0
      return;
142
0
    }
143
0
144
0
    switch (aStart) {
145
0
      case StartAt::TOP:
146
0
        mIndex = mLayer->GetScrollMetadataCount();
147
0
        if (mIndex > 0) {
148
0
          mIndex--;
149
0
        }
150
0
        break;
151
0
      case StartAt::BOTTOM:
152
0
        mIndex = 0;
153
0
        break;
154
0
      default:
155
0
        MOZ_ASSERT_UNREACHABLE("Unknown startAt value");
156
0
        break;
157
0
    }
158
0
  }
159
160
  explicit LayerMetricsWrapper(Layer* aLayer, uint32_t aMetricsIndex)
161
    : mLayer(aLayer)
162
    , mIndex(aMetricsIndex)
163
0
  {
164
0
    MOZ_ASSERT(mLayer);
165
0
    MOZ_ASSERT(mIndex == 0 || mIndex < mLayer->GetScrollMetadataCount());
166
0
  }
167
168
  bool IsValid() const
169
0
  {
170
0
    return mLayer != nullptr;
171
0
  }
172
173
  explicit operator bool() const
174
0
  {
175
0
    return IsValid();
176
0
  }
177
178
  LayerMetricsWrapper GetParent() const
179
0
  {
180
0
    MOZ_ASSERT(IsValid());
181
0
182
0
    if (!AtTopLayer()) {
183
0
      return LayerMetricsWrapper(mLayer, mIndex + 1);
184
0
    }
185
0
    if (mLayer->GetParent()) {
186
0
      return LayerMetricsWrapper(mLayer->GetParent(), StartAt::BOTTOM);
187
0
    }
188
0
    return LayerMetricsWrapper(nullptr);
189
0
  }
190
191
  LayerMetricsWrapper GetFirstChild() const
192
0
  {
193
0
    MOZ_ASSERT(IsValid());
194
0
195
0
    if (!AtBottomLayer()) {
196
0
      return LayerMetricsWrapper(mLayer, mIndex - 1);
197
0
    }
198
0
    return LayerMetricsWrapper(mLayer->GetFirstChild());
199
0
  }
200
201
  LayerMetricsWrapper GetLastChild() const
202
0
  {
203
0
    MOZ_ASSERT(IsValid());
204
0
205
0
    if (!AtBottomLayer()) {
206
0
      return LayerMetricsWrapper(mLayer, mIndex - 1);
207
0
    }
208
0
    return LayerMetricsWrapper(mLayer->GetLastChild());
209
0
  }
210
211
  LayerMetricsWrapper GetPrevSibling() const
212
0
  {
213
0
    MOZ_ASSERT(IsValid());
214
0
215
0
    if (AtTopLayer()) {
216
0
      return LayerMetricsWrapper(mLayer->GetPrevSibling());
217
0
    }
218
0
    return LayerMetricsWrapper(nullptr);
219
0
  }
220
221
  LayerMetricsWrapper GetNextSibling() const
222
0
  {
223
0
    MOZ_ASSERT(IsValid());
224
0
225
0
    if (AtTopLayer()) {
226
0
      return LayerMetricsWrapper(mLayer->GetNextSibling());
227
0
    }
228
0
    return LayerMetricsWrapper(nullptr);
229
0
  }
230
231
  const ScrollMetadata& Metadata() const
232
0
  {
233
0
    MOZ_ASSERT(IsValid());
234
0
235
0
    if (mIndex >= mLayer->GetScrollMetadataCount()) {
236
0
      return *ScrollMetadata::sNullMetadata;
237
0
    }
238
0
    return mLayer->GetScrollMetadata(mIndex);
239
0
  }
240
241
  const FrameMetrics& Metrics() const
242
0
  {
243
0
    return Metadata().GetMetrics();
244
0
  }
245
246
  AsyncPanZoomController* GetApzc() const
247
0
  {
248
0
    MOZ_ASSERT(IsValid());
249
0
250
0
    if (mIndex >= mLayer->GetScrollMetadataCount()) {
251
0
      return nullptr;
252
0
    }
253
0
    return mLayer->GetAsyncPanZoomController(mIndex);
254
0
  }
255
256
  void SetApzc(AsyncPanZoomController* aApzc) const
257
0
  {
258
0
    MOZ_ASSERT(IsValid());
259
0
260
0
    if (mLayer->GetScrollMetadataCount() == 0) {
261
0
      MOZ_ASSERT(mIndex == 0);
262
0
      MOZ_ASSERT(aApzc == nullptr);
263
0
      return;
264
0
    }
265
0
    MOZ_ASSERT(mIndex < mLayer->GetScrollMetadataCount());
266
0
    mLayer->SetAsyncPanZoomController(mIndex, aApzc);
267
0
  }
268
269
  const char* Name() const
270
0
  {
271
0
    MOZ_ASSERT(IsValid());
272
0
273
0
    if (AtBottomLayer()) {
274
0
      return mLayer->Name();
275
0
    }
276
0
    return "DummyContainerLayer";
277
0
  }
278
279
  LayerManager* Manager() const
280
0
  {
281
0
    MOZ_ASSERT(IsValid());
282
0
283
0
    return mLayer->Manager();
284
0
  }
285
286
  gfx::Matrix4x4 GetTransform() const
287
0
  {
288
0
    MOZ_ASSERT(IsValid());
289
0
290
0
    if (AtBottomLayer()) {
291
0
      return mLayer->GetTransform();
292
0
    }
293
0
    return gfx::Matrix4x4();
294
0
  }
295
296
  CSSTransformMatrix GetTransformTyped() const
297
0
  {
298
0
    return ViewAs<CSSTransformMatrix>(GetTransform());
299
0
  }
300
301
  bool TransformIsPerspective() const
302
0
  {
303
0
    MOZ_ASSERT(IsValid());
304
0
305
0
    // mLayer->GetTransformIsPerspective() tells us whether
306
0
    // mLayer->GetTransform() is a perspective transform. Since
307
0
    // mLayer->GetTransform() is only used at the bottom layer, we only
308
0
    // need to check GetTransformIsPerspective() at the bottom layer too.
309
0
    if (AtBottomLayer()) {
310
0
      return mLayer->GetTransformIsPerspective();
311
0
    }
312
0
    return false;
313
0
  }
314
315
  EventRegions GetEventRegions() const
316
0
  {
317
0
    MOZ_ASSERT(IsValid());
318
0
319
0
    if (AtBottomLayer()) {
320
0
      return mLayer->GetEventRegions();
321
0
    }
322
0
    return EventRegions();
323
0
  }
324
325
  LayerIntRegion GetVisibleRegion() const
326
0
  {
327
0
    MOZ_ASSERT(IsValid());
328
0
329
0
    if (AtBottomLayer()) {
330
0
      return mLayer->GetVisibleRegion();
331
0
    }
332
0
333
0
    return ViewAs<LayerPixel>(
334
0
        TransformBy(mLayer->GetTransformTyped(), mLayer->GetVisibleRegion()),
335
0
        PixelCastJustification::MovingDownToChildren);
336
0
  }
337
338
  bool HasTransformAnimation() const
339
0
  {
340
0
    MOZ_ASSERT(IsValid());
341
0
342
0
    if (AtBottomLayer()) {
343
0
      return mLayer->HasTransformAnimation();
344
0
    }
345
0
    return false;
346
0
  }
347
348
  RefLayer* AsRefLayer() const
349
0
  {
350
0
    MOZ_ASSERT(IsValid());
351
0
352
0
    if (AtBottomLayer()) {
353
0
      return mLayer->AsRefLayer();
354
0
    }
355
0
    return nullptr;
356
0
  }
357
358
  Maybe<LayersId> GetReferentId() const
359
0
  {
360
0
    MOZ_ASSERT(IsValid());
361
0
362
0
    if (AtBottomLayer()) {
363
0
      return mLayer->AsRefLayer()
364
0
           ? Some(mLayer->AsRefLayer()->GetReferentId())
365
0
           : Nothing();
366
0
    }
367
0
    return Nothing();
368
0
  }
369
370
  Maybe<ParentLayerIntRect> GetClipRect() const
371
0
  {
372
0
    MOZ_ASSERT(IsValid());
373
0
374
0
    Maybe<ParentLayerIntRect> result;
375
0
376
0
    // The layer can have a clip rect and a scrolled clip, which are considered
377
0
    // to apply only to the bottommost LayerMetricsWrapper.
378
0
    // TODO: These actually apply in a different coordinate space than the
379
0
    // scroll clip of the bottommost metrics, so we shouldn't be intersecting
380
0
    // them with the scroll clip; bug 1269537 tracks fixing this.
381
0
    if (AtBottomLayer()) {
382
0
      result = mLayer->GetClipRect();
383
0
      result = IntersectMaybeRects(result, mLayer->GetScrolledClipRect());
384
0
    }
385
0
386
0
    // The scroll metadata can have a clip rect as well.
387
0
    result = IntersectMaybeRects(result, Metadata().GetClipRect());
388
0
389
0
    return result;
390
0
  }
391
392
  float GetPresShellResolution() const
393
0
  {
394
0
    MOZ_ASSERT(IsValid());
395
0
396
0
    if (AtTopLayer() && mLayer->AsContainerLayer()) {
397
0
      return mLayer->AsContainerLayer()->GetPresShellResolution();
398
0
    }
399
0
400
0
    return 1.0f;
401
0
  }
402
403
  EventRegionsOverride GetEventRegionsOverride() const
404
0
  {
405
0
    MOZ_ASSERT(IsValid());
406
0
407
0
    if (mLayer->AsRefLayer()) {
408
0
      return mLayer->AsRefLayer()->GetEventRegionsOverride();
409
0
    }
410
0
    return EventRegionsOverride::NoOverride;
411
0
  }
412
413
  const ScrollbarData& GetScrollbarData() const
414
0
  {
415
0
    MOZ_ASSERT(IsValid());
416
0
417
0
    return mLayer->GetScrollbarData();
418
0
  }
419
420
  uint64_t GetScrollbarAnimationId() const
421
0
  {
422
0
    MOZ_ASSERT(IsValid());
423
0
    // This function is only really needed for template-compatibility with
424
0
    // WebRenderScrollDataWrapper. Although it will be called, the return
425
0
    // value is not used.
426
0
    return 0;
427
0
  }
428
429
  FrameMetrics::ViewID GetFixedPositionScrollContainerId() const
430
0
  {
431
0
    MOZ_ASSERT(IsValid());
432
0
433
0
    return mLayer->GetFixedPositionScrollContainerId();
434
0
  }
435
436
  bool IsBackfaceHidden() const
437
0
  {
438
0
    MOZ_ASSERT(IsValid());
439
0
440
0
    return mLayer->IsBackfaceHidden();
441
0
  }
442
443
  // Expose an opaque pointer to the layer. Mostly used for printf
444
  // purposes. This is not intended to be a general-purpose accessor
445
  // for the underlying layer.
446
  const void* GetLayer() const
447
0
  {
448
0
    MOZ_ASSERT(IsValid());
449
0
450
0
    return (void*)mLayer;
451
0
  }
452
453
  bool operator==(const LayerMetricsWrapper& aOther) const
454
0
  {
455
0
    return mLayer == aOther.mLayer
456
0
        && mIndex == aOther.mIndex;
457
0
  }
458
459
  bool operator!=(const LayerMetricsWrapper& aOther) const
460
0
  {
461
0
    return !(*this == aOther);
462
0
  }
463
464
private:
465
  bool AtBottomLayer() const
466
0
  {
467
0
    return mIndex == 0;
468
0
  }
469
470
  bool AtTopLayer() const
471
0
  {
472
0
    return mLayer->GetScrollMetadataCount() == 0 || mIndex == mLayer->GetScrollMetadataCount() - 1;
473
0
  }
474
475
private:
476
  Layer* mLayer;
477
  uint32_t mIndex;
478
};
479
480
} // namespace layers
481
} // namespace mozilla
482
483
#endif /* GFX_LAYERMETRICSWRAPPER_H */