Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(264)

Side by Side Diff: third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp

Issue 2423513002: Simplify incremental paint invalidation (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/paint/BoxPaintInvalidator.h" 5 #include "core/paint/BoxPaintInvalidator.h"
6 6
7 #include "core/frame/Settings.h" 7 #include "core/frame/Settings.h"
8 #include "core/layout/LayoutView.h" 8 #include "core/layout/LayoutView.h"
9 #include "core/paint/ObjectPaintInvalidator.h" 9 #include "core/paint/ObjectPaintInvalidator.h"
10 #include "core/paint/PaintInvalidator.h" 10 #include "core/paint/PaintInvalidator.h"
(...skipping 12 matching lines...) Expand all
23 typedef HashMap<const LayoutBox*, PreviousBoxSizes> PreviousBoxSizesMap; 23 typedef HashMap<const LayoutBox*, PreviousBoxSizes> PreviousBoxSizesMap;
24 static PreviousBoxSizesMap& previousBoxSizesMap() { 24 static PreviousBoxSizesMap& previousBoxSizesMap() {
25 DEFINE_STATIC_LOCAL(PreviousBoxSizesMap, map, ()); 25 DEFINE_STATIC_LOCAL(PreviousBoxSizesMap, map, ());
26 return map; 26 return map;
27 } 27 }
28 28
29 void BoxPaintInvalidator::boxWillBeDestroyed(const LayoutBox& box) { 29 void BoxPaintInvalidator::boxWillBeDestroyed(const LayoutBox& box) {
30 previousBoxSizesMap().remove(&box); 30 previousBoxSizesMap().remove(&box);
31 } 31 }
32 32
33 static LayoutRect computeRightDelta(const LayoutPoint& location,
34 const LayoutSize& oldSize,
35 const LayoutSize& newSize,
36 int extraWidth) {
37 LayoutUnit delta = newSize.width() - oldSize.width();
38 if (delta > 0) {
39 return LayoutRect(location.x() + oldSize.width() - extraWidth, location.y(),
40 delta + extraWidth, newSize.height());
41 }
42 if (delta < 0) {
43 return LayoutRect(location.x() + newSize.width() - extraWidth, location.y(),
44 -delta + extraWidth, oldSize.height());
45 }
46 return LayoutRect();
47 }
48
49 static LayoutRect computeBottomDelta(const LayoutPoint& location,
50 const LayoutSize& oldSize,
51 const LayoutSize& newSize,
52 int extraHeight) {
53 LayoutUnit delta = newSize.height() - oldSize.height();
54 if (delta > 0) {
55 return LayoutRect(location.x(),
56 location.y() + oldSize.height() - extraHeight,
57 newSize.width(), delta + extraHeight);
58 }
59 if (delta < 0) {
60 return LayoutRect(location.x(),
61 location.y() + newSize.height() - extraHeight,
62 oldSize.width(), -delta + extraHeight);
63 }
64 return LayoutRect();
65 }
66
33 bool BoxPaintInvalidator::incrementallyInvalidatePaint() { 67 bool BoxPaintInvalidator::incrementallyInvalidatePaint() {
34 bool result = ObjectPaintInvalidatorWithContext(m_box, m_context) 68 DCHECK(m_context.oldBounds.location() == m_context.newBounds.location());
chrishtr 2016/10/20 18:15:44 Could you add unittests to the geometric logic her
Xianzhu 2016/10/21 00:19:49 Done.
35 .incrementallyInvalidatePaint(); 69 LayoutRect rightDelta = computeRightDelta(m_context.newBounds.location(),
70 m_context.oldBounds.size(),
71 m_context.newBounds.size(), 0);
72 LayoutRect bottomDelta = computeBottomDelta(m_context.newBounds.location(),
73 m_context.oldBounds.size(),
74 m_context.newBounds.size(), 0);
36 75
37 bool hasBoxDecorations = m_box.styleRef().hasBoxDecorations(); 76 if (m_box.styleRef().hasBorder() || m_box.styleRef().hasBackground()) {
38 if (!m_box.styleRef().hasBackground() && !hasBoxDecorations) 77 LayoutSize oldBorderBoxSize =
39 return result; 78 computePreviousBorderBoxSize(m_context.oldBounds.size());
40 79 LayoutSize newBorderBoxSize = m_box.size();
41 const LayoutRect& oldBounds = m_context.oldBounds; 80 DCHECK(m_context.oldLocation == m_context.newLocation);
42 const LayoutRect& newBounds = m_context.newBounds; 81 rightDelta.unite(computeRightDelta(m_context.newLocation, oldBorderBoxSize,
43 82 newBorderBoxSize, m_box.borderRight()));
44 LayoutSize oldBorderBoxSize = computePreviousBorderBoxSize(oldBounds.size()); 83 bottomDelta.unite(computeBottomDelta(m_context.newLocation,
45 LayoutSize newBorderBoxSize = m_box.size(); 84 oldBorderBoxSize, newBorderBoxSize,
46 85 m_box.borderBottom()));
47 // If border m_box size didn't change,
48 // ObjectPaintInvalidatorWithContext::incrementallyInvalidatePaint() is good.
49 if (oldBorderBoxSize == newBorderBoxSize)
50 return result;
51
52 // If size of the paint invalidation rect equals to size of border box,
53 // ObjectPaintInvalidatorWithContext::incrementallyInvalidatePaint()
54 // is good for boxes having background without box decorations.
55 DCHECK(
56 oldBounds.location() ==
57 newBounds.location()); // Otherwise we won't do incremental invalidation.
58 if (!hasBoxDecorations && m_context.newLocation == newBounds.location() &&
59 oldBorderBoxSize == oldBounds.size() &&
60 newBorderBoxSize == newBounds.size())
61 return result;
62
63 // Invalidate the right delta part and the right border of the old or new
64 // m_box which has smaller width.
65 if (LayoutUnit deltaWidth =
66 (oldBorderBoxSize.width() - newBorderBoxSize.width()).abs()) {
67 LayoutUnit smallerWidth =
68 std::min(oldBorderBoxSize.width(), newBorderBoxSize.width());
69 LayoutUnit borderTopRightRadiusWidth = valueForLength(
70 m_box.styleRef().borderTopRightRadius().width(), smallerWidth);
71 LayoutUnit borderBottomRightRadiusWidth = valueForLength(
72 m_box.styleRef().borderBottomRightRadius().width(), smallerWidth);
73 LayoutUnit borderWidth = std::max(
74 LayoutUnit(m_box.borderRight()),
75 std::max(borderTopRightRadiusWidth, borderBottomRightRadiusWidth));
76 LayoutRect rightDeltaRect(
77 m_context.newLocation.x() + smallerWidth - borderWidth,
78 m_context.newLocation.y(), deltaWidth + borderWidth,
79 std::max(oldBorderBoxSize.height(), newBorderBoxSize.height()));
80 invalidatePaintRectClippedByOldAndNewBounds(rightDeltaRect);
81 } 86 }
82 87
83 // Invalidate the bottom delta part and the bottom border of the old or new 88 if (rightDelta.isEmpty() && bottomDelta.isEmpty())
84 // m_box which has smaller height. 89 return false;
85 if (LayoutUnit deltaHeight =
86 (oldBorderBoxSize.height() - newBorderBoxSize.height()).abs()) {
87 LayoutUnit smallerHeight =
88 std::min(oldBorderBoxSize.height(), newBorderBoxSize.height());
89 LayoutUnit borderBottomLeftRadiusHeight = valueForLength(
90 m_box.styleRef().borderBottomLeftRadius().height(), smallerHeight);
91 LayoutUnit borderBottomRightRadiusHeight = valueForLength(
92 m_box.styleRef().borderBottomRightRadius().height(), smallerHeight);
93 LayoutUnit borderHeight = std::max(
94 LayoutUnit(m_box.borderBottom()),
95 std::max(borderBottomLeftRadiusHeight, borderBottomRightRadiusHeight));
96 LayoutRect bottomDeltaRect(
97 m_context.newLocation.x(),
98 m_context.newLocation.y() + smallerHeight - borderHeight,
99 std::max(oldBorderBoxSize.width(), newBorderBoxSize.width()),
100 deltaHeight + borderHeight);
101 invalidatePaintRectClippedByOldAndNewBounds(bottomDeltaRect);
102 }
103 90
91 invalidatePaintRectClippedByOldAndNewBounds(rightDelta);
92 invalidatePaintRectClippedByOldAndNewBounds(bottomDelta);
104 return true; 93 return true;
105 } 94 }
106 95
107 void BoxPaintInvalidator::invalidatePaintRectClippedByOldAndNewBounds( 96 void BoxPaintInvalidator::invalidatePaintRectClippedByOldAndNewBounds(
108 const LayoutRect& rect) { 97 const LayoutRect& rect) {
109 if (rect.isEmpty()) 98 if (rect.isEmpty())
110 return; 99 return;
111 100
112 ObjectPaintInvalidator objectPaintInvalidator(m_box); 101 ObjectPaintInvalidator objectPaintInvalidator(m_box);
113 LayoutRect rectClippedByOldBounds = intersection(rect, m_context.oldBounds); 102 LayoutRect rectClippedByOldBounds = intersection(rect, m_context.oldBounds);
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 const ComputedStyle& style = m_box.styleRef(); 172 const ComputedStyle& style = m_box.styleRef();
184 if (style.backgroundLayers().thisOrNextLayersUseContentBox() || 173 if (style.backgroundLayers().thisOrNextLayersUseContentBox() ||
185 style.maskLayers().thisOrNextLayersUseContentBox() || 174 style.maskLayers().thisOrNextLayersUseContentBox() ||
186 style.boxSizing() == BoxSizingBorderBox) { 175 style.boxSizing() == BoxSizingBorderBox) {
187 if (previousBoxSizesMap().get(&m_box).contentBoxRect != 176 if (previousBoxSizesMap().get(&m_box).contentBoxRect !=
188 m_box.contentBoxRect()) 177 m_box.contentBoxRect())
189 return PaintInvalidationContentBoxChange; 178 return PaintInvalidationContentBoxChange;
190 } 179 }
191 180
192 if (!style.hasBackground() && !style.hasBoxDecorations()) { 181 if (!style.hasBackground() && !style.hasBoxDecorations()) {
193 // We could let incremental invalidation cover non-composited scrollbars,
194 // but just do a full invalidation because incremental invalidation will go
195 // away with slimming paint.
196 if (reason == PaintInvalidationIncremental && 182 if (reason == PaintInvalidationIncremental &&
197 m_context.oldBounds != m_context.newBounds && 183 m_context.oldBounds != m_context.newBounds &&
198 m_box.hasNonCompositedScrollbars()) 184 m_box.hasNonCompositedScrollbars())
199 return PaintInvalidationBorderBoxChange; 185 return PaintInvalidationBorderBoxChange;
200 return reason; 186 return reason;
201 } 187 }
202 188
203 if (style.backgroundLayers().thisOrNextLayersHaveLocalAttachment()) { 189 if (style.backgroundLayers().thisOrNextLayersHaveLocalAttachment()) {
204 if (previousBoxSizesMap().get(&m_box).layoutOverflowRect != 190 if (previousBoxSizesMap().get(&m_box).layoutOverflowRect !=
205 m_box.layoutOverflowRect()) 191 m_box.layoutOverflowRect())
206 return PaintInvalidationLayoutOverflowBoxChange; 192 return PaintInvalidationLayoutOverflowBoxChange;
207 } 193 }
208 194
209 LayoutSize oldBorderBoxSize = 195 LayoutSize oldBorderBoxSize =
210 computePreviousBorderBoxSize(m_context.oldBounds.size()); 196 computePreviousBorderBoxSize(m_context.oldBounds.size());
211 LayoutSize newBorderBoxSize = m_box.size(); 197 LayoutSize newBorderBoxSize = m_box.size();
212 198
213 if (oldBorderBoxSize == newBorderBoxSize) 199 if (oldBorderBoxSize == newBorderBoxSize)
214 return reason; 200 return reason;
215 201
216 // See another hasNonCompositedScrollbars() callsite above. 202 // See another hasNonCompositedScrollbars() callsite above.
217 if (m_box.hasNonCompositedScrollbars()) 203 if (m_box.hasNonCompositedScrollbars())
218 return PaintInvalidationBorderBoxChange; 204 return PaintInvalidationBorderBoxChange;
219 205
220 if (style.hasVisualOverflowingEffect() || style.hasAppearance() || 206 if (style.hasVisualOverflowingEffect() || style.hasAppearance() ||
221 style.hasFilterInducingProperty() || style.resize() != RESIZE_NONE) 207 style.hasFilterInducingProperty() || style.resize() != RESIZE_NONE)
222 return PaintInvalidationBorderBoxChange; 208 return PaintInvalidationBorderBoxChange;
223 209
224 if (style.hasBorderRadius()) { 210 if (style.hasBorderRadius())
225 // If a border-radius exists and width/height is smaller than radius 211 return PaintInvalidationBorderBoxChange;
226 // width/height, we need to fully invalidate to cover the changed radius.
227 FloatRoundedRect oldRoundedRect = style.getRoundedBorderFor(
228 LayoutRect(LayoutPoint(0, 0), oldBorderBoxSize));
229 FloatRoundedRect newRoundedRect = style.getRoundedBorderFor(
230 LayoutRect(LayoutPoint(0, 0), newBorderBoxSize));
231 if (oldRoundedRect.getRadii() != newRoundedRect.getRadii())
232 return PaintInvalidationBorderBoxChange;
233 }
234 212
235 if (oldBorderBoxSize.width() != newBorderBoxSize.width() && 213 if (oldBorderBoxSize.width() != newBorderBoxSize.width() &&
236 m_box.mustInvalidateBackgroundOrBorderPaintOnWidthChange()) 214 m_box.mustInvalidateBackgroundOrBorderPaintOnWidthChange())
237 return PaintInvalidationBorderBoxChange; 215 return PaintInvalidationBorderBoxChange;
238 if (oldBorderBoxSize.height() != newBorderBoxSize.height() && 216 if (oldBorderBoxSize.height() != newBorderBoxSize.height() &&
239 m_box.mustInvalidateBackgroundOrBorderPaintOnHeightChange()) 217 m_box.mustInvalidateBackgroundOrBorderPaintOnHeightChange())
240 return PaintInvalidationBorderBoxChange; 218 return PaintInvalidationBorderBoxChange;
241 219
242 return reason; 220 return reason;
243 } 221 }
244 222
245 PaintInvalidationReason BoxPaintInvalidator::invalidatePaintIfNeeded() { 223 PaintInvalidationReason BoxPaintInvalidator::invalidatePaintIfNeeded() {
246 PaintInvalidationReason reason = computePaintInvalidationReason(); 224 PaintInvalidationReason reason = computePaintInvalidationReason();
247 if (reason == PaintInvalidationIncremental) { 225 if (reason == PaintInvalidationIncremental) {
248 if (incrementallyInvalidatePaint()) { 226 if (incrementallyInvalidatePaint()) {
249 m_context.paintingLayer->setNeedsRepaint(); 227 m_context.paintingLayer->setNeedsRepaint();
250 m_box.invalidateDisplayItemClients(reason); 228 m_box.invalidateDisplayItemClients(reason);
251 } else { 229 } else {
252 reason = PaintInvalidationNone; 230 reason = PaintInvalidationNone;
253 } 231 }
254 // Though we have done our own version of incremental invalidation, we still 232 // Though we have done incremental invalidation, we still need to call
255 // need to call ObjectPaintInvalidator with PaintInvalidationNone to do any 233 // ObjectPaintInvalidator with PaintInvalidationNone to do any other
256 // other required operations. 234 // required operations.
257 reason = std::max( 235 reason = std::max(
258 reason, 236 reason,
259 ObjectPaintInvalidatorWithContext(m_box, m_context) 237 ObjectPaintInvalidatorWithContext(m_box, m_context)
260 .invalidatePaintIfNeededWithComputedReason(PaintInvalidationNone)); 238 .invalidatePaintIfNeededWithComputedReason(PaintInvalidationNone));
261 } else { 239 } else {
262 reason = ObjectPaintInvalidatorWithContext(m_box, m_context) 240 reason = ObjectPaintInvalidatorWithContext(m_box, m_context)
263 .invalidatePaintIfNeededWithComputedReason(reason); 241 .invalidatePaintIfNeededWithComputedReason(reason);
264 } 242 }
265 243
266 if (PaintLayerScrollableArea* area = m_box.getScrollableArea()) 244 if (PaintLayerScrollableArea* area = m_box.getScrollableArea())
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 auto it = previousBoxSizesMap().find(&m_box); 307 auto it = previousBoxSizesMap().find(&m_box);
330 if (it != previousBoxSizesMap().end()) 308 if (it != previousBoxSizesMap().end())
331 return it->value.borderBoxSize; 309 return it->value.borderBoxSize;
332 310
333 // We didn't save the old border box size because it was the same as the size 311 // We didn't save the old border box size because it was the same as the size
334 // of oldBounds. 312 // of oldBounds.
335 return previousBoundsSize; 313 return previousBoundsSize;
336 } 314 }
337 315
338 } // namespace blink 316 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/paint/BUILD.gn ('k') | third_party/WebKit/Source/core/paint/ObjectPaintInvalidator.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698