Line data Source code
1 : /*-*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this file,
4 : * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #ifndef NSDISPLAYLISTINVALIDATION_H_
7 : #define NSDISPLAYLISTINVALIDATION_H_
8 :
9 : #include "mozilla/Attributes.h"
10 : #include "FrameLayerBuilder.h"
11 : #include "imgIContainer.h"
12 : #include "nsRect.h"
13 : #include "nsColor.h"
14 : #include "gfxRect.h"
15 :
16 : class nsDisplayBackgroundImage;
17 : class nsCharClipDisplayItem;
18 : class nsDisplayItem;
19 : class nsDisplayListBuilder;
20 : class nsDisplayTableItem;
21 : class nsDisplayThemedBackground;
22 : class nsDisplaySVGEffects;
23 : class nsDisplayMask;
24 : class nsDisplayFilter;
25 :
26 : namespace mozilla {
27 : namespace gfx {
28 : struct Color;
29 : }
30 : }
31 :
32 : /**
33 : * This stores the geometry of an nsDisplayItem, and the area
34 : * that will be affected when painting the item.
35 : *
36 : * It is used to retain information about display items so they
37 : * can be compared against new display items in the next paint.
38 : */
39 : class nsDisplayItemGeometry
40 : {
41 : public:
42 : nsDisplayItemGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder);
43 : virtual ~nsDisplayItemGeometry();
44 :
45 : /**
46 : * Compute the area required to be invalidated if this
47 : * display item is removed.
48 : */
49 2420 : const nsRect& ComputeInvalidationRegion() { return mBounds; }
50 :
51 : /**
52 : * Shifts all retained areas of the nsDisplayItemGeometry by the given offset.
53 : *
54 : * This is used to compensate for scrolling, since the destination buffer
55 : * can scroll without requiring a full repaint.
56 : *
57 : * @param aOffset Offset to shift by.
58 : */
59 1105 : virtual void MoveBy(const nsPoint& aOffset)
60 : {
61 1105 : mBounds.MoveBy(aOffset);
62 1105 : }
63 :
64 : /**
65 : * Bounds of the display item
66 : */
67 : nsRect mBounds;
68 : };
69 :
70 : /**
71 : * A default geometry implementation, used by nsDisplayItem. Retains
72 : * and compares the bounds, and border rect.
73 : *
74 : * This should be sufficient for the majority of display items.
75 : */
76 475 : class nsDisplayItemGenericGeometry : public nsDisplayItemGeometry
77 : {
78 : public:
79 : nsDisplayItemGenericGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder);
80 :
81 : virtual void MoveBy(const nsPoint& aOffset) override;
82 :
83 : nsRect mBorderRect;
84 : };
85 :
86 : bool ShouldSyncDecodeImages(nsDisplayListBuilder* aBuilder);
87 :
88 : /**
89 : * nsImageGeometryMixin is a mixin for geometry items that draw images.
90 : * Geometry items that include this mixin can track drawing results and use
91 : * that information to inform invalidation decisions.
92 : *
93 : * This mixin uses CRTP; its template parameter should be the type of the class
94 : * that is inheriting from it. See nsDisplayItemGenericImageGeometry for an
95 : * example.
96 : */
97 : template <typename T>
98 : class nsImageGeometryMixin
99 : {
100 : public:
101 111 : nsImageGeometryMixin(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder)
102 : : mLastDrawResult(mozilla::image::DrawResult::NOT_READY)
103 111 : , mWaitingForPaint(false)
104 : {
105 : // Transfer state from the previous version of this geometry item.
106 : auto lastGeometry =
107 111 : static_cast<T*>(mozilla::FrameLayerBuilder::GetMostRecentGeometry(aItem));
108 111 : if (lastGeometry) {
109 72 : mLastDrawResult = lastGeometry->mLastDrawResult;
110 72 : mWaitingForPaint = lastGeometry->mWaitingForPaint;
111 : }
112 :
113 : // If our display item is going to invalidate to trigger sync decoding of
114 : // images, mark ourselves as waiting for a paint. If we actually get
115 : // painted, UpdateDrawResult will get called, and we'll clear the flag.
116 111 : if (ShouldSyncDecodeImages(aBuilder) &&
117 0 : ShouldInvalidateToSyncDecodeImages()) {
118 0 : mWaitingForPaint = true;
119 : }
120 111 : }
121 :
122 214 : static void UpdateDrawResult(nsDisplayItem* aItem,
123 : mozilla::image::DrawResult aResult)
124 : {
125 : auto lastGeometry =
126 214 : static_cast<T*>(mozilla::FrameLayerBuilder::GetMostRecentGeometry(aItem));
127 214 : if (lastGeometry) {
128 176 : lastGeometry->mLastDrawResult = aResult;
129 176 : lastGeometry->mWaitingForPaint = false;
130 : }
131 214 : }
132 :
133 0 : bool ShouldInvalidateToSyncDecodeImages() const
134 : {
135 0 : if (mWaitingForPaint) {
136 : // We previously invalidated for sync decoding and haven't gotten painted
137 : // since them. This suggests that our display item is completely occluded
138 : // and there's no point in invalidating again - and because the reftest
139 : // harness takes a new snapshot every time we invalidate, doing so might
140 : // lead to an invalidation loop if we're in a reftest.
141 0 : return false;
142 : }
143 :
144 0 : if (mLastDrawResult == mozilla::image::DrawResult::SUCCESS ||
145 0 : mLastDrawResult == mozilla::image::DrawResult::BAD_IMAGE) {
146 0 : return false;
147 : }
148 :
149 0 : return true;
150 : }
151 :
152 : private:
153 : mozilla::image::DrawResult mLastDrawResult;
154 : bool mWaitingForPaint;
155 : };
156 :
157 : /**
158 : * nsDisplayItemGenericImageGeometry is a generic geometry item class that
159 : * includes nsImageGeometryMixin.
160 : *
161 : * This should be sufficient for most display items that draw images.
162 : */
163 171 : class nsDisplayItemGenericImageGeometry
164 : : public nsDisplayItemGenericGeometry
165 : , public nsImageGeometryMixin<nsDisplayItemGenericImageGeometry>
166 : {
167 : public:
168 71 : nsDisplayItemGenericImageGeometry(nsDisplayItem* aItem,
169 : nsDisplayListBuilder* aBuilder)
170 71 : : nsDisplayItemGenericGeometry(aItem, aBuilder)
171 71 : , nsImageGeometryMixin(aItem, aBuilder)
172 71 : { }
173 : };
174 :
175 14 : class nsDisplayItemBoundsGeometry : public nsDisplayItemGeometry
176 : {
177 : public:
178 : nsDisplayItemBoundsGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder);
179 :
180 : bool mHasRoundedCorners;
181 : };
182 :
183 45 : class nsDisplayBorderGeometry
184 : : public nsDisplayItemGeometry
185 : , public nsImageGeometryMixin<nsDisplayBorderGeometry>
186 : {
187 : public:
188 : nsDisplayBorderGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder);
189 :
190 : virtual void MoveBy(const nsPoint& aOffset) override;
191 :
192 : nsRect mContentRect;
193 : };
194 :
195 24 : class nsDisplayBackgroundGeometry
196 : : public nsDisplayItemGeometry
197 : , public nsImageGeometryMixin<nsDisplayBackgroundGeometry>
198 : {
199 : public:
200 : nsDisplayBackgroundGeometry(nsDisplayBackgroundImage* aItem, nsDisplayListBuilder* aBuilder);
201 :
202 : virtual void MoveBy(const nsPoint& aOffset) override;
203 :
204 : nsRect mPositioningArea;
205 : nsRect mDestRect;
206 : };
207 :
208 6 : class nsDisplayThemedBackgroundGeometry : public nsDisplayItemGeometry
209 : {
210 : public:
211 : nsDisplayThemedBackgroundGeometry(nsDisplayThemedBackground* aItem, nsDisplayListBuilder* aBuilder);
212 :
213 : virtual void MoveBy(const nsPoint& aOffset) override;
214 :
215 : nsRect mPositioningArea;
216 : bool mWindowIsActive;
217 : };
218 :
219 3 : class nsDisplayBoxShadowInnerGeometry : public nsDisplayItemGeometry
220 : {
221 : public:
222 : nsDisplayBoxShadowInnerGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder);
223 :
224 : virtual void MoveBy(const nsPoint& aOffset) override;
225 :
226 : nsRect mPaddingRect;
227 : };
228 :
229 18 : class nsDisplayBoxShadowOuterGeometry : public nsDisplayItemGenericGeometry
230 : {
231 : public:
232 : nsDisplayBoxShadowOuterGeometry(nsDisplayItem* aItem,
233 : nsDisplayListBuilder* aBuilder,
234 : float aOpacity);
235 :
236 : float mOpacity;
237 : };
238 :
239 42 : class nsDisplaySolidColorGeometry : public nsDisplayItemBoundsGeometry
240 : {
241 : public:
242 22 : nsDisplaySolidColorGeometry(nsDisplayItem* aItem,
243 : nsDisplayListBuilder* aBuilder,
244 : nscolor aColor)
245 22 : : nsDisplayItemBoundsGeometry(aItem, aBuilder)
246 22 : , mColor(aColor)
247 22 : { }
248 :
249 : nscolor mColor;
250 : };
251 :
252 0 : class nsDisplaySolidColorRegionGeometry : public nsDisplayItemBoundsGeometry
253 : {
254 : public:
255 0 : nsDisplaySolidColorRegionGeometry(nsDisplayItem* aItem,
256 : nsDisplayListBuilder* aBuilder,
257 : const nsRegion& aRegion,
258 : mozilla::gfx::Color aColor)
259 0 : : nsDisplayItemBoundsGeometry(aItem, aBuilder)
260 : , mRegion(aRegion)
261 0 : , mColor(aColor)
262 0 : { }
263 :
264 : virtual void MoveBy(const nsPoint& aOffset) override;
265 :
266 : nsRegion mRegion;
267 : mozilla::gfx::Color mColor;
268 : };
269 :
270 1 : class nsDisplaySVGEffectGeometry : public nsDisplayItemGeometry
271 : {
272 : public:
273 : nsDisplaySVGEffectGeometry(nsDisplaySVGEffects* aItem,
274 : nsDisplayListBuilder* aBuilder);
275 :
276 : virtual void MoveBy(const nsPoint& aOffset) override;
277 :
278 : gfxRect mBBox;
279 : gfxPoint mUserSpaceOffset;
280 : nsPoint mFrameOffsetToReferenceFrame;
281 : };
282 :
283 3 : class nsDisplayMaskGeometry : public nsDisplaySVGEffectGeometry
284 : , public nsImageGeometryMixin<nsDisplayMaskGeometry>
285 : {
286 : public:
287 : nsDisplayMaskGeometry(nsDisplayMask* aItem, nsDisplayListBuilder* aBuilder);
288 :
289 : nsTArray<nsRect> mDestRects;
290 : };
291 :
292 0 : class nsDisplayFilterGeometry : public nsDisplaySVGEffectGeometry
293 : , public nsImageGeometryMixin<nsDisplayFilterGeometry>
294 : {
295 : public:
296 : nsDisplayFilterGeometry(nsDisplayFilter* aItem,
297 : nsDisplayListBuilder* aBuilder);
298 : };
299 :
300 10 : class nsCharClipGeometry : public nsDisplayItemGenericGeometry
301 : {
302 : public:
303 : nsCharClipGeometry(nsCharClipDisplayItem* aItem,
304 : nsDisplayListBuilder* aBuilder);
305 :
306 : nscoord mVisIStartEdge;
307 : nscoord mVisIEndEdge;
308 : };
309 :
310 0 : class nsDisplayTableItemGeometry
311 : : public nsDisplayItemGenericGeometry
312 : , public nsImageGeometryMixin<nsDisplayTableItemGeometry>
313 : {
314 : public:
315 : nsDisplayTableItemGeometry(nsDisplayTableItem* aItem,
316 : nsDisplayListBuilder* aBuilder,
317 : const nsPoint& aFrameOffsetToViewport);
318 :
319 : nsPoint mFrameOffsetToViewport;
320 : };
321 :
322 : #endif /*NSDISPLAYLISTINVALIDATION_H_*/
|