Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/layout/painting/nsDisplayListInvalidation.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 NSDISPLAYLISTINVALIDATION_H_
8
#define NSDISPLAYLISTINVALIDATION_H_
9
10
#include "mozilla/Attributes.h"
11
#include "FrameLayerBuilder.h"
12
#include "imgIContainer.h"
13
#include "nsRect.h"
14
#include "nsColor.h"
15
#include "gfxRect.h"
16
#include "mozilla/gfx/MatrixFwd.h"
17
18
class nsDisplayBackgroundImage;
19
class nsCharClipDisplayItem;
20
class nsDisplayItem;
21
class nsDisplayListBuilder;
22
class nsDisplayTableItem;
23
class nsDisplayThemedBackground;
24
class nsDisplaySVGEffects;
25
class nsDisplayMask;
26
class nsDisplayFilter;
27
28
namespace mozilla {
29
namespace gfx {
30
struct Color;
31
}
32
}
33
34
/**
35
 * This stores the geometry of an nsDisplayItem, and the area
36
 * that will be affected when painting the item.
37
 *
38
 * It is used to retain information about display items so they
39
 * can be compared against new display items in the next paint.
40
 */
41
class nsDisplayItemGeometry
42
{
43
public:
44
  nsDisplayItemGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder);
45
  virtual ~nsDisplayItemGeometry();
46
47
  /**
48
   * Compute the area required to be invalidated if this
49
   * display item is removed.
50
   */
51
  const nsRect& ComputeInvalidationRegion() { return mBounds; }
52
53
  /**
54
   * Shifts all retained areas of the nsDisplayItemGeometry by the given offset.
55
   *
56
   * This is used to compensate for scrolling, since the destination buffer
57
   * can scroll without requiring a full repaint.
58
   *
59
   * @param aOffset Offset to shift by.
60
   */
61
0
  virtual void MoveBy(const nsPoint& aOffset) { mBounds.MoveBy(aOffset); }
62
63
0
  virtual bool InvalidateForSyncDecodeImages() const { return false; }
64
65
  /**
66
   * Bounds of the display item
67
   */
68
  nsRect mBounds;
69
};
70
71
/**
72
 * A default geometry implementation, used by nsDisplayItem. Retains
73
 * and compares the bounds, and border rect.
74
 *
75
 * This should be sufficient for the majority of display items.
76
 */
77
class nsDisplayItemGenericGeometry : public nsDisplayItemGeometry
78
{
79
public:
80
  nsDisplayItemGenericGeometry(nsDisplayItem* aItem,
81
                               nsDisplayListBuilder* aBuilder);
82
83
  void MoveBy(const nsPoint& aOffset) override;
84
85
  nsRect mBorderRect;
86
};
87
88
bool
89
ShouldSyncDecodeImages(nsDisplayListBuilder* aBuilder);
90
91
/**
92
 * nsImageGeometryMixin is a mixin for geometry items that draw images.
93
 * Geometry items that include this mixin can track drawing results and use
94
 * that information to inform invalidation decisions.
95
 *
96
 * This mixin uses CRTP; its template parameter should be the type of the class
97
 * that is inheriting from it. See nsDisplayItemGenericImageGeometry for an
98
 * example.
99
 */
100
template<typename T>
101
class nsImageGeometryMixin
102
{
103
public:
104
  nsImageGeometryMixin(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder)
105
    : mLastDrawResult(mozilla::image::ImgDrawResult::NOT_READY)
106
    , mWaitingForPaint(false)
107
0
  {
108
0
    // Transfer state from the previous version of this geometry item.
109
0
    auto lastGeometry =
110
0
      static_cast<T*>(mozilla::FrameLayerBuilder::GetMostRecentGeometry(aItem));
111
0
    if (lastGeometry) {
112
0
      mLastDrawResult = lastGeometry->mLastDrawResult;
113
0
      mWaitingForPaint = lastGeometry->mWaitingForPaint;
114
0
    }
115
0
116
0
    // If our display item is going to invalidate to trigger sync decoding of
117
0
    // images, mark ourselves as waiting for a paint. If we actually get
118
0
    // painted, UpdateDrawResult will get called, and we'll clear the flag.
119
0
    if (ShouldSyncDecodeImages(aBuilder) &&
120
0
        ShouldInvalidateToSyncDecodeImages()) {
121
0
      mWaitingForPaint = true;
122
0
    }
123
0
  }
Unexecuted instantiation: nsImageGeometryMixin<nsDisplayBulletGeometry>::nsImageGeometryMixin(nsDisplayItem*, nsDisplayListBuilder*)
Unexecuted instantiation: nsImageGeometryMixin<nsDisplayItemGenericImageGeometry>::nsImageGeometryMixin(nsDisplayItem*, nsDisplayListBuilder*)
Unexecuted instantiation: nsImageGeometryMixin<nsDisplayBorderGeometry>::nsImageGeometryMixin(nsDisplayItem*, nsDisplayListBuilder*)
Unexecuted instantiation: nsImageGeometryMixin<nsDisplayBackgroundGeometry>::nsImageGeometryMixin(nsDisplayItem*, nsDisplayListBuilder*)
Unexecuted instantiation: nsImageGeometryMixin<nsDisplayMaskGeometry>::nsImageGeometryMixin(nsDisplayItem*, nsDisplayListBuilder*)
Unexecuted instantiation: nsImageGeometryMixin<nsDisplayFilterGeometry>::nsImageGeometryMixin(nsDisplayItem*, nsDisplayListBuilder*)
Unexecuted instantiation: nsImageGeometryMixin<nsDisplayTableItemGeometry>::nsImageGeometryMixin(nsDisplayItem*, nsDisplayListBuilder*)
124
125
  static void UpdateDrawResult(nsDisplayItem* aItem,
126
                               mozilla::image::ImgDrawResult aResult)
127
0
  {
128
0
    MOZ_ASSERT(aResult != mozilla::image::ImgDrawResult::NOT_SUPPORTED,
129
0
               "ImgDrawResult::NOT_SUPPORTED should be handled already!");
130
0
131
0
    auto lastGeometry =
132
0
      static_cast<T*>(mozilla::FrameLayerBuilder::GetMostRecentGeometry(aItem));
133
0
    if (lastGeometry) {
134
0
      lastGeometry->mLastDrawResult = aResult;
135
0
      lastGeometry->mWaitingForPaint = false;
136
0
    }
137
0
  }
Unexecuted instantiation: nsImageGeometryMixin<nsDisplayBackgroundGeometry>::UpdateDrawResult(nsDisplayItem*, mozilla::image::ImgDrawResult)
Unexecuted instantiation: nsImageGeometryMixin<nsDisplayItemGenericImageGeometry>::UpdateDrawResult(nsDisplayItem*, mozilla::image::ImgDrawResult)
Unexecuted instantiation: nsImageGeometryMixin<nsDisplayBulletGeometry>::UpdateDrawResult(nsDisplayItem*, mozilla::image::ImgDrawResult)
Unexecuted instantiation: nsImageGeometryMixin<nsDisplayTableItemGeometry>::UpdateDrawResult(nsDisplayItem*, mozilla::image::ImgDrawResult)
Unexecuted instantiation: nsImageGeometryMixin<nsDisplayBorderGeometry>::UpdateDrawResult(nsDisplayItem*, mozilla::image::ImgDrawResult)
Unexecuted instantiation: nsImageGeometryMixin<nsDisplayMaskGeometry>::UpdateDrawResult(nsDisplayItem*, mozilla::image::ImgDrawResult)
Unexecuted instantiation: nsImageGeometryMixin<nsDisplayFilterGeometry>::UpdateDrawResult(nsDisplayItem*, mozilla::image::ImgDrawResult)
138
139
  bool ShouldInvalidateToSyncDecodeImages() const
140
0
  {
141
0
    if (mWaitingForPaint) {
142
0
      // We previously invalidated for sync decoding and haven't gotten painted
143
0
      // since them. This suggests that our display item is completely occluded
144
0
      // and there's no point in invalidating again - and because the reftest
145
0
      // harness takes a new snapshot every time we invalidate, doing so might
146
0
      // lead to an invalidation loop if we're in a reftest.
147
0
      return false;
148
0
    }
149
0
150
0
    if (mLastDrawResult == mozilla::image::ImgDrawResult::SUCCESS ||
151
0
        mLastDrawResult == mozilla::image::ImgDrawResult::BAD_IMAGE) {
152
0
      return false;
153
0
    }
154
0
155
0
    return true;
156
0
  }
Unexecuted instantiation: nsImageGeometryMixin<nsDisplayItemGenericImageGeometry>::ShouldInvalidateToSyncDecodeImages() const
Unexecuted instantiation: nsImageGeometryMixin<nsDisplayBorderGeometry>::ShouldInvalidateToSyncDecodeImages() const
Unexecuted instantiation: nsImageGeometryMixin<nsDisplayBackgroundGeometry>::ShouldInvalidateToSyncDecodeImages() const
Unexecuted instantiation: nsImageGeometryMixin<nsDisplayMaskGeometry>::ShouldInvalidateToSyncDecodeImages() const
Unexecuted instantiation: nsImageGeometryMixin<nsDisplayFilterGeometry>::ShouldInvalidateToSyncDecodeImages() const
Unexecuted instantiation: nsImageGeometryMixin<nsDisplayTableItemGeometry>::ShouldInvalidateToSyncDecodeImages() const
Unexecuted instantiation: nsImageGeometryMixin<nsDisplayBulletGeometry>::ShouldInvalidateToSyncDecodeImages() const
157
158
private:
159
  mozilla::image::ImgDrawResult mLastDrawResult;
160
  bool mWaitingForPaint;
161
};
162
163
/**
164
 * nsDisplayItemGenericImageGeometry is a generic geometry item class that
165
 * includes nsImageGeometryMixin.
166
 *
167
 * This should be sufficient for most display items that draw images.
168
 */
169
class nsDisplayItemGenericImageGeometry
170
  : public nsDisplayItemGenericGeometry
171
  , public nsImageGeometryMixin<nsDisplayItemGenericImageGeometry>
172
{
173
public:
174
  nsDisplayItemGenericImageGeometry(nsDisplayItem* aItem,
175
                                    nsDisplayListBuilder* aBuilder)
176
    : nsDisplayItemGenericGeometry(aItem, aBuilder)
177
    , nsImageGeometryMixin(aItem, aBuilder)
178
0
  {
179
0
  }
180
181
  bool InvalidateForSyncDecodeImages() const override
182
0
  {
183
0
    return ShouldInvalidateToSyncDecodeImages();
184
0
  }
185
};
186
187
class nsDisplayItemBoundsGeometry : public nsDisplayItemGeometry
188
{
189
public:
190
  nsDisplayItemBoundsGeometry(nsDisplayItem* aItem,
191
                              nsDisplayListBuilder* aBuilder);
192
193
  bool mHasRoundedCorners;
194
};
195
196
class nsDisplayBorderGeometry
197
  : public nsDisplayItemGeometry
198
  , public nsImageGeometryMixin<nsDisplayBorderGeometry>
199
{
200
public:
201
  nsDisplayBorderGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder);
202
203
  bool InvalidateForSyncDecodeImages() const override
204
0
  {
205
0
    return ShouldInvalidateToSyncDecodeImages();
206
0
  }
207
};
208
209
class nsDisplayBackgroundGeometry
210
  : public nsDisplayItemGeometry
211
  , public nsImageGeometryMixin<nsDisplayBackgroundGeometry>
212
{
213
public:
214
  nsDisplayBackgroundGeometry(nsDisplayBackgroundImage* aItem,
215
                              nsDisplayListBuilder* aBuilder);
216
217
  void MoveBy(const nsPoint& aOffset) override;
218
219
  bool InvalidateForSyncDecodeImages() const override
220
0
  {
221
0
    return ShouldInvalidateToSyncDecodeImages();
222
0
  }
223
224
  nsRect mPositioningArea;
225
  nsRect mDestRect;
226
};
227
228
class nsDisplayThemedBackgroundGeometry : public nsDisplayItemGeometry
229
{
230
public:
231
  nsDisplayThemedBackgroundGeometry(nsDisplayThemedBackground* aItem,
232
                                    nsDisplayListBuilder* aBuilder);
233
234
  void MoveBy(const nsPoint& aOffset) override;
235
236
  nsRect mPositioningArea;
237
  bool mWindowIsActive;
238
};
239
240
class nsDisplayBoxShadowInnerGeometry : public nsDisplayItemGeometry
241
{
242
public:
243
  nsDisplayBoxShadowInnerGeometry(nsDisplayItem* aItem,
244
                                  nsDisplayListBuilder* aBuilder);
245
246
  void MoveBy(const nsPoint& aOffset) override;
247
248
  nsRect mPaddingRect;
249
};
250
251
class nsDisplayBoxShadowOuterGeometry : public nsDisplayItemGenericGeometry
252
{
253
public:
254
  nsDisplayBoxShadowOuterGeometry(nsDisplayItem* aItem,
255
                                  nsDisplayListBuilder* aBuilder,
256
                                  float aOpacity);
257
258
  float mOpacity;
259
};
260
261
class nsDisplaySolidColorGeometry : public nsDisplayItemBoundsGeometry
262
{
263
public:
264
  nsDisplaySolidColorGeometry(nsDisplayItem* aItem,
265
                              nsDisplayListBuilder* aBuilder,
266
                              nscolor aColor)
267
    : nsDisplayItemBoundsGeometry(aItem, aBuilder)
268
    , mColor(aColor)
269
0
  {
270
0
  }
271
272
  nscolor mColor;
273
};
274
275
class nsDisplaySolidColorRegionGeometry : public nsDisplayItemBoundsGeometry
276
{
277
public:
278
  nsDisplaySolidColorRegionGeometry(nsDisplayItem* aItem,
279
                                    nsDisplayListBuilder* aBuilder,
280
                                    const nsRegion& aRegion,
281
                                    mozilla::gfx::Color aColor)
282
    : nsDisplayItemBoundsGeometry(aItem, aBuilder)
283
    , mRegion(aRegion)
284
    , mColor(aColor)
285
0
  {
286
0
  }
287
288
  void MoveBy(const nsPoint& aOffset) override;
289
290
  nsRegion mRegion;
291
  mozilla::gfx::Color mColor;
292
};
293
294
class nsDisplaySVGEffectGeometry : public nsDisplayItemGeometry
295
{
296
public:
297
  nsDisplaySVGEffectGeometry(nsDisplaySVGEffects* aItem,
298
                             nsDisplayListBuilder* aBuilder);
299
300
  void MoveBy(const nsPoint& aOffset) override;
301
302
  gfxRect mBBox;
303
  gfxPoint mUserSpaceOffset;
304
  nsPoint mFrameOffsetToReferenceFrame;
305
};
306
307
class nsDisplayMaskGeometry
308
  : public nsDisplaySVGEffectGeometry
309
  , public nsImageGeometryMixin<nsDisplayMaskGeometry>
310
{
311
public:
312
  nsDisplayMaskGeometry(nsDisplayMask* aItem, nsDisplayListBuilder* aBuilder);
313
314
  bool InvalidateForSyncDecodeImages() const override
315
0
  {
316
0
    return ShouldInvalidateToSyncDecodeImages();
317
0
  }
318
319
  nsTArray<nsRect> mDestRects;
320
  float mOpacity;
321
  bool mHandleOpacity;
322
};
323
324
class nsDisplayFilterGeometry
325
  : public nsDisplaySVGEffectGeometry
326
  , public nsImageGeometryMixin<nsDisplayFilterGeometry>
327
{
328
public:
329
  nsDisplayFilterGeometry(nsDisplayFilter* aItem,
330
                          nsDisplayListBuilder* aBuilder);
331
332
  bool InvalidateForSyncDecodeImages() const override
333
0
  {
334
0
    return ShouldInvalidateToSyncDecodeImages();
335
0
  }
336
};
337
338
class nsCharClipGeometry : public nsDisplayItemGenericGeometry
339
{
340
public:
341
  nsCharClipGeometry(nsCharClipDisplayItem* aItem,
342
                     nsDisplayListBuilder* aBuilder);
343
344
  nscoord mVisIStartEdge;
345
  nscoord mVisIEndEdge;
346
};
347
348
class nsDisplayTableItemGeometry
349
  : public nsDisplayItemGenericGeometry
350
  , public nsImageGeometryMixin<nsDisplayTableItemGeometry>
351
{
352
public:
353
  nsDisplayTableItemGeometry(nsDisplayTableItem* aItem,
354
                             nsDisplayListBuilder* aBuilder,
355
                             const nsPoint& aFrameOffsetToViewport);
356
357
  bool InvalidateForSyncDecodeImages() const override
358
0
  {
359
0
    return ShouldInvalidateToSyncDecodeImages();
360
0
  }
361
362
  nsPoint mFrameOffsetToViewport;
363
};
364
365
class nsDisplayOpacityGeometry : public nsDisplayItemGenericGeometry
366
{
367
public:
368
  nsDisplayOpacityGeometry(nsDisplayItem* aItem,
369
                           nsDisplayListBuilder* aBuilder,
370
                           float aOpacity)
371
    : nsDisplayItemGenericGeometry(aItem, aBuilder)
372
    , mOpacity(aOpacity)
373
0
  {
374
0
  }
375
376
  float mOpacity;
377
};
378
379
class nsDisplayTransformGeometry : public nsDisplayItemGeometry
380
{
381
public:
382
  nsDisplayTransformGeometry(nsDisplayItem* aItem,
383
                             nsDisplayListBuilder* aBuilder,
384
                             const mozilla::gfx::Matrix4x4Flagged& aTransform,
385
                             int32_t aAppUnitsPerDevPixel)
386
    : nsDisplayItemGeometry(aItem, aBuilder)
387
    , mTransform(aTransform)
388
    , mAppUnitsPerDevPixel(aAppUnitsPerDevPixel)
389
0
  {
390
0
  }
391
392
  void MoveBy(const nsPoint& aOffset) override
393
0
  {
394
0
    nsDisplayItemGeometry::MoveBy(aOffset);
395
0
    mTransform.PostTranslate(
396
0
      NSAppUnitsToFloatPixels(aOffset.x, mAppUnitsPerDevPixel),
397
0
      NSAppUnitsToFloatPixels(aOffset.y, mAppUnitsPerDevPixel),
398
0
      0.0f);
399
0
  }
400
401
  mozilla::gfx::Matrix4x4Flagged mTransform;
402
  int32_t mAppUnitsPerDevPixel;
403
};
404
405
#endif /*NSDISPLAYLISTINVALIDATION_H_*/