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/. */
7 #ifndef NSDISPLAYLISTINVALIDATION_H_
8 #define NSDISPLAYLISTINVALIDATION_H_
10 #include "mozilla/Attributes.h"
11 #include "FrameLayerBuilder.h"
15 #include "mozilla/gfx/MatrixFwd.h"
17 class nsDisplayBackgroundImage
;
18 class nsCharClipDisplayItem
;
20 class nsDisplayListBuilder
;
21 class nsDisplayTableItem
;
22 class nsDisplayThemedBackground
;
23 class nsDisplayEffectsBase
;
24 class nsDisplayMasksAndClipPaths
;
25 class nsDisplayFilters
;
31 } // namespace mozilla
34 * This stores the geometry of an nsDisplayItem, and the area
35 * that will be affected when painting the item.
37 * It is used to retain information about display items so they
38 * can be compared against new display items in the next paint.
40 class nsDisplayItemGeometry
{
42 nsDisplayItemGeometry(nsDisplayItem
* aItem
, nsDisplayListBuilder
* aBuilder
);
43 virtual ~nsDisplayItemGeometry();
46 * Compute the area required to be invalidated if this
47 * display item is removed.
49 const nsRect
& ComputeInvalidationRegion() { return mBounds
; }
52 * Shifts all retained areas of the nsDisplayItemGeometry by the given offset.
54 * This is used to compensate for scrolling, since the destination buffer
55 * can scroll without requiring a full repaint.
57 * @param aOffset Offset to shift by.
59 virtual void MoveBy(const nsPoint
& aOffset
) { mBounds
.MoveBy(aOffset
); }
61 virtual bool InvalidateForSyncDecodeImages() const { return false; }
64 * Bounds of the display item
70 * A default geometry implementation, used by nsDisplayItem. Retains
71 * and compares the bounds, and border rect.
73 * This should be sufficient for the majority of display items.
75 class nsDisplayItemGenericGeometry
: public nsDisplayItemGeometry
{
77 nsDisplayItemGenericGeometry(nsDisplayItem
* aItem
,
78 nsDisplayListBuilder
* aBuilder
);
80 void MoveBy(const nsPoint
& aOffset
) override
;
85 bool ShouldSyncDecodeImages(nsDisplayListBuilder
* aBuilder
);
88 * nsImageGeometryMixin is a mixin for geometry items that draw images.
89 * Geometry items that include this mixin can track drawing results and use
90 * that information to inform invalidation decisions.
92 * This mixin uses CRTP; its template parameter should be the type of the class
93 * that is inheriting from it. See nsDisplayItemGenericImageGeometry for an
97 class nsImageGeometryMixin
{
99 nsImageGeometryMixin(nsDisplayItem
* aItem
, nsDisplayListBuilder
* aBuilder
)
100 : mLastDrawResult(mozilla::image::ImgDrawResult::NOT_READY
),
101 mWaitingForPaint(false) {
102 // Transfer state from the previous version of this geometry item.
103 auto lastGeometry
= static_cast<T
*>(
104 mozilla::FrameLayerBuilder::GetMostRecentGeometry(aItem
));
106 mLastDrawResult
= lastGeometry
->mLastDrawResult
;
107 mWaitingForPaint
= lastGeometry
->mWaitingForPaint
;
110 // If our display item is going to invalidate to trigger sync decoding of
111 // images, mark ourselves as waiting for a paint. If we actually get
112 // painted, UpdateDrawResult will get called, and we'll clear the flag.
113 if (ShouldSyncDecodeImages(aBuilder
) &&
114 ShouldInvalidateToSyncDecodeImages()) {
115 mWaitingForPaint
= true;
119 static void UpdateDrawResult(nsDisplayItem
* aItem
,
120 mozilla::image::ImgDrawResult aResult
) {
121 MOZ_ASSERT(aResult
!= mozilla::image::ImgDrawResult::NOT_SUPPORTED
,
122 "ImgDrawResult::NOT_SUPPORTED should be handled already!");
124 auto lastGeometry
= static_cast<T
*>(
125 mozilla::FrameLayerBuilder::GetMostRecentGeometry(aItem
));
127 lastGeometry
->mLastDrawResult
= aResult
;
128 lastGeometry
->mWaitingForPaint
= false;
132 bool ShouldInvalidateToSyncDecodeImages() const {
133 if (mWaitingForPaint
) {
134 // We previously invalidated for sync decoding and haven't gotten painted
135 // since them. This suggests that our display item is completely occluded
136 // and there's no point in invalidating again - and because the reftest
137 // harness takes a new snapshot every time we invalidate, doing so might
138 // lead to an invalidation loop if we're in a reftest.
142 if (mLastDrawResult
== mozilla::image::ImgDrawResult::SUCCESS
||
143 mLastDrawResult
== mozilla::image::ImgDrawResult::BAD_IMAGE
) {
151 mozilla::image::ImgDrawResult mLastDrawResult
;
152 bool mWaitingForPaint
;
156 * nsDisplayItemGenericImageGeometry is a generic geometry item class that
157 * includes nsImageGeometryMixin.
159 * This should be sufficient for most display items that draw images.
161 class nsDisplayItemGenericImageGeometry
162 : public nsDisplayItemGenericGeometry
,
163 public nsImageGeometryMixin
<nsDisplayItemGenericImageGeometry
> {
165 nsDisplayItemGenericImageGeometry(nsDisplayItem
* aItem
,
166 nsDisplayListBuilder
* aBuilder
)
167 : nsDisplayItemGenericGeometry(aItem
, aBuilder
),
168 nsImageGeometryMixin(aItem
, aBuilder
) {}
170 bool InvalidateForSyncDecodeImages() const override
{
171 return ShouldInvalidateToSyncDecodeImages();
175 class nsDisplayItemBoundsGeometry
: public nsDisplayItemGeometry
{
177 nsDisplayItemBoundsGeometry(nsDisplayItem
* aItem
,
178 nsDisplayListBuilder
* aBuilder
);
180 bool mHasRoundedCorners
;
183 class nsDisplayBorderGeometry
184 : public nsDisplayItemGeometry
,
185 public nsImageGeometryMixin
<nsDisplayBorderGeometry
> {
187 nsDisplayBorderGeometry(nsDisplayItem
* aItem
, nsDisplayListBuilder
* aBuilder
);
189 bool InvalidateForSyncDecodeImages() const override
{
190 return ShouldInvalidateToSyncDecodeImages();
194 class nsDisplayBackgroundGeometry
195 : public nsDisplayItemGeometry
,
196 public nsImageGeometryMixin
<nsDisplayBackgroundGeometry
> {
198 nsDisplayBackgroundGeometry(nsDisplayBackgroundImage
* aItem
,
199 nsDisplayListBuilder
* aBuilder
);
201 void MoveBy(const nsPoint
& aOffset
) override
;
203 bool InvalidateForSyncDecodeImages() const override
{
204 return ShouldInvalidateToSyncDecodeImages();
207 nsRect mPositioningArea
;
211 class nsDisplayThemedBackgroundGeometry
: public nsDisplayItemGeometry
{
213 nsDisplayThemedBackgroundGeometry(nsDisplayThemedBackground
* aItem
,
214 nsDisplayListBuilder
* aBuilder
);
216 void MoveBy(const nsPoint
& aOffset
) override
;
218 nsRect mPositioningArea
;
219 bool mWindowIsActive
;
222 class nsDisplayTreeBodyGeometry
223 : public nsDisplayItemGenericGeometry
,
224 public nsImageGeometryMixin
<nsDisplayTreeBodyGeometry
> {
226 nsDisplayTreeBodyGeometry(nsDisplayItem
* aItem
,
227 nsDisplayListBuilder
* aBuilder
,
228 bool aWindowIsActive
)
229 : nsDisplayItemGenericGeometry(aItem
, aBuilder
),
230 nsImageGeometryMixin(aItem
, aBuilder
),
231 mWindowIsActive(aWindowIsActive
) {}
233 bool InvalidateForSyncDecodeImages() const override
{
234 return ShouldInvalidateToSyncDecodeImages();
237 bool mWindowIsActive
= false;
240 class nsDisplayBoxShadowInnerGeometry
: public nsDisplayItemGeometry
{
242 nsDisplayBoxShadowInnerGeometry(nsDisplayItem
* aItem
,
243 nsDisplayListBuilder
* aBuilder
);
245 void MoveBy(const nsPoint
& aOffset
) override
;
250 class nsDisplayBoxShadowOuterGeometry
: public nsDisplayItemGenericGeometry
{
252 nsDisplayBoxShadowOuterGeometry(nsDisplayItem
* aItem
,
253 nsDisplayListBuilder
* aBuilder
,
259 class nsDisplaySolidColorGeometry
: public nsDisplayItemBoundsGeometry
{
261 nsDisplaySolidColorGeometry(nsDisplayItem
* aItem
,
262 nsDisplayListBuilder
* aBuilder
, nscolor aColor
)
263 : nsDisplayItemBoundsGeometry(aItem
, aBuilder
), mColor(aColor
) {}
268 class nsDisplaySolidColorRegionGeometry
: public nsDisplayItemBoundsGeometry
{
270 nsDisplaySolidColorRegionGeometry(nsDisplayItem
* aItem
,
271 nsDisplayListBuilder
* aBuilder
,
272 const nsRegion
& aRegion
,
273 mozilla::gfx::sRGBColor aColor
)
274 : nsDisplayItemBoundsGeometry(aItem
, aBuilder
),
278 void MoveBy(const nsPoint
& aOffset
) override
;
281 mozilla::gfx::sRGBColor mColor
;
284 class nsDisplaySVGEffectGeometry
: public nsDisplayItemGeometry
{
286 nsDisplaySVGEffectGeometry(nsDisplayEffectsBase
* aItem
,
287 nsDisplayListBuilder
* aBuilder
);
289 void MoveBy(const nsPoint
& aOffset
) override
;
292 gfxPoint mUserSpaceOffset
;
293 nsPoint mFrameOffsetToReferenceFrame
;
298 class nsDisplayMasksAndClipPathsGeometry
299 : public nsDisplaySVGEffectGeometry
,
300 public nsImageGeometryMixin
<nsDisplayMasksAndClipPathsGeometry
> {
302 nsDisplayMasksAndClipPathsGeometry(nsDisplayMasksAndClipPaths
* aItem
,
303 nsDisplayListBuilder
* aBuilder
);
305 bool InvalidateForSyncDecodeImages() const override
{
306 return ShouldInvalidateToSyncDecodeImages();
309 nsTArray
<nsRect
> mDestRects
;
312 class nsDisplayFiltersGeometry
313 : public nsDisplaySVGEffectGeometry
,
314 public nsImageGeometryMixin
<nsDisplayFiltersGeometry
> {
316 nsDisplayFiltersGeometry(nsDisplayFilters
* aItem
,
317 nsDisplayListBuilder
* aBuilder
);
319 bool InvalidateForSyncDecodeImages() const override
{
320 return ShouldInvalidateToSyncDecodeImages();
324 class nsDisplayTableItemGeometry
325 : public nsDisplayItemGenericGeometry
,
326 public nsImageGeometryMixin
<nsDisplayTableItemGeometry
> {
328 nsDisplayTableItemGeometry(nsDisplayTableItem
* aItem
,
329 nsDisplayListBuilder
* aBuilder
,
330 const nsPoint
& aFrameOffsetToViewport
);
332 bool InvalidateForSyncDecodeImages() const override
{
333 return ShouldInvalidateToSyncDecodeImages();
336 nsPoint mFrameOffsetToViewport
;
339 class nsDisplayOpacityGeometry
: public nsDisplayItemGenericGeometry
{
341 nsDisplayOpacityGeometry(nsDisplayItem
* aItem
, nsDisplayListBuilder
* aBuilder
,
343 : nsDisplayItemGenericGeometry(aItem
, aBuilder
), mOpacity(aOpacity
) {}
348 class nsDisplayTransformGeometry
: public nsDisplayItemGeometry
{
350 nsDisplayTransformGeometry(nsDisplayItem
* aItem
,
351 nsDisplayListBuilder
* aBuilder
,
352 const mozilla::gfx::Matrix4x4Flagged
& aTransform
,
353 int32_t aAppUnitsPerDevPixel
)
354 : nsDisplayItemGeometry(aItem
, aBuilder
),
355 mTransform(aTransform
),
356 mAppUnitsPerDevPixel(aAppUnitsPerDevPixel
) {}
358 void MoveBy(const nsPoint
& aOffset
) override
{
359 nsDisplayItemGeometry::MoveBy(aOffset
);
360 mTransform
.PostTranslate(
361 NSAppUnitsToFloatPixels(aOffset
.x
, mAppUnitsPerDevPixel
),
362 NSAppUnitsToFloatPixels(aOffset
.y
, mAppUnitsPerDevPixel
), 0.0f
);
365 mozilla::gfx::Matrix4x4Flagged mTransform
;
366 int32_t mAppUnitsPerDevPixel
;
369 #endif /*NSDISPLAYLISTINVALIDATION_H_*/