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

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

Issue 2792863002: Revert of Skip paint property update and visual rect update if no geometry change (Closed)
Patch Set: Created 3 years, 8 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/PaintInvalidator.h" 5 #include "core/paint/PaintInvalidator.h"
6 6
7 #include "core/editing/FrameSelection.h" 7 #include "core/editing/FrameSelection.h"
8 #include "core/frame/FrameView.h" 8 #include "core/frame/FrameView.h"
9 #include "core/frame/LocalFrame.h" 9 #include "core/frame/LocalFrame.h"
10 #include "core/frame/Settings.h" 10 #include "core/frame/Settings.h"
11 #include "core/layout/LayoutBlockFlow.h" 11 #include "core/layout/LayoutBlockFlow.h"
12 #include "core/layout/LayoutObject.h"
12 #include "core/layout/LayoutTable.h" 13 #include "core/layout/LayoutTable.h"
13 #include "core/layout/LayoutView.h" 14 #include "core/layout/LayoutView.h"
14 #include "core/layout/svg/SVGLayoutSupport.h" 15 #include "core/layout/svg/SVGLayoutSupport.h"
15 #include "core/paint/FindPaintOffsetAndVisualRectNeedingUpdate.h"
16 #include "core/paint/ObjectPaintProperties.h" 16 #include "core/paint/ObjectPaintProperties.h"
17 #include "core/paint/PaintLayer.h" 17 #include "core/paint/PaintLayer.h"
18 #include "core/paint/PaintLayerScrollableArea.h" 18 #include "core/paint/PaintLayerScrollableArea.h"
19 #include "core/paint/PaintPropertyTreeBuilder.h"
19 #include "wtf/Optional.h" 20 #include "wtf/Optional.h"
20 21
21 namespace blink { 22 namespace blink {
22 23
23 template <typename Rect> 24 template <typename Rect>
24 static LayoutRect slowMapToVisualRectInAncestorSpace( 25 static LayoutRect slowMapToVisualRectInAncestorSpace(
25 const LayoutObject& object, 26 const LayoutObject& object,
26 const LayoutBoxModelObject& ancestor, 27 const LayoutBoxModelObject& ancestor,
27 const Rect& rect) { 28 const Rect& rect) {
28 if (object.isSVGChild()) { 29 if (object.isSVGChild()) {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 result = LayoutRect(rect); 100 result = LayoutRect(rect);
100 } else { 101 } else {
101 // For non-root SVG, the input rect is in local SVG coordinates in which 102 // For non-root SVG, the input rect is in local SVG coordinates in which
102 // paint offset doesn't apply. 103 // paint offset doesn't apply.
103 if (!isSVGChild) 104 if (!isSVGChild)
104 rect.moveBy(Point(object.paintOffset())); 105 rect.moveBy(Point(object.paintOffset()));
105 106
106 const auto* containerContentsProperties = 107 const auto* containerContentsProperties =
107 context.paintInvalidationContainer->contentsProperties(); 108 context.paintInvalidationContainer->contentsProperties();
108 109
109 if (context.m_treeBuilderContext->current.transform == 110 if (context.m_treeBuilderContext.current.transform ==
110 containerContentsProperties->transform() && 111 containerContentsProperties->transform() &&
111 context.m_treeBuilderContext->current.clip == 112 context.m_treeBuilderContext.current.clip ==
112 containerContentsProperties->clip()) { 113 containerContentsProperties->clip()) {
113 result = LayoutRect(rect); 114 result = LayoutRect(rect);
114 } else { 115 } else {
115 // Use enclosingIntRect to ensure the final visual rect will cover the 116 // Use enclosingIntRect to ensure the final visual rect will cover the
116 // rect in source coordinates no matter if the painting will use pixel 117 // rect in source coordinates no matter if the painting will use pixel
117 // snapping, when transforms are applied. If there is no transform, 118 // snapping, when transforms are applied. If there is no transform,
118 // enclosingIntRect is applied in the last step of paint invalidation 119 // enclosingIntRect is applied in the last step of paint invalidation
119 // (see CompositedLayerMapping::setContentsNeedDisplayInRect()). 120 // (see CompositedLayerMapping::setContentsNeedDisplayInRect()).
120 if (!isSVGChild && context.m_treeBuilderContext->current.transform != 121 if (!isSVGChild && context.m_treeBuilderContext.current.transform !=
121 containerContentsProperties->transform()) 122 containerContentsProperties->transform())
122 rect = Rect(enclosingIntRect(rect)); 123 rect = Rect(enclosingIntRect(rect));
123 124
124 PropertyTreeState currentTreeState( 125 PropertyTreeState currentTreeState(
125 context.m_treeBuilderContext->current.transform, 126 context.m_treeBuilderContext.current.transform,
126 context.m_treeBuilderContext->current.clip, nullptr); 127 context.m_treeBuilderContext.current.clip, nullptr);
127 128
128 FloatRect floatRect(rect); 129 FloatRect floatRect(rect);
129 context.m_geometryMapper.sourceToDestinationVisualRect( 130 context.m_geometryMapper.sourceToDestinationVisualRect(
130 currentTreeState, *containerContentsProperties, floatRect); 131 currentTreeState, *containerContentsProperties, floatRect);
131 result = LayoutRect(floatRect); 132 result = LayoutRect(floatRect);
132 } 133 }
133 134
134 // Convert the result to the container's contents space. 135 // Convert the result to the container's contents space.
135 result.moveBy(-context.paintInvalidationContainer->paintOffset()); 136 result.moveBy(-context.paintInvalidationContainer->paintOffset());
136 } 137 }
137 138
138 object.adjustVisualRectForRasterEffects(result); 139 object.adjustVisualRectForRasterEffects(result);
139 140
140 PaintLayer::mapRectInPaintInvalidationContainerToBacking( 141 PaintLayer::mapRectInPaintInvalidationContainerToBacking(
141 *context.paintInvalidationContainer, result); 142 *context.paintInvalidationContainer, result);
142 143
143 result.move(object.scrollAdjustmentForPaintInvalidation( 144 result.move(object.scrollAdjustmentForPaintInvalidation(
144 *context.paintInvalidationContainer)); 145 *context.paintInvalidationContainer));
145 146
146 return result; 147 return result;
147 } 148 }
148 149
149 void PaintInvalidatorContext::mapLocalRectToVisualRectInBacking( 150 void PaintInvalidatorContext::mapLocalRectToVisualRectInBacking(
150 const LayoutObject& object, 151 const LayoutObject& object,
151 LayoutRect& rect) const { 152 LayoutRect& rect) const {
152 DCHECK(needsVisualRectUpdate(object));
153 std::unique_ptr<GeometryMapper> geometryMapper = GeometryMapper::create();
154 rect = PaintInvalidator::mapLocalRectToVisualRectInBacking<LayoutRect, 153 rect = PaintInvalidator::mapLocalRectToVisualRectInBacking<LayoutRect,
155 LayoutPoint>( 154 LayoutPoint>(
156 object, rect, *this); 155 object, rect, *this);
157 } 156 }
158 157
159 LayoutRect PaintInvalidator::computeVisualRectInBacking( 158 LayoutRect PaintInvalidator::computeVisualRectInBacking(
160 const LayoutObject& object, 159 const LayoutObject& object,
161 const PaintInvalidatorContext& context) { 160 const PaintInvalidatorContext& context) {
162 if (object.isSVGChild()) { 161 if (object.isSVGChild()) {
163 FloatRect localRect = SVGLayoutSupport::localVisualRect(object); 162 FloatRect localRect = SVGLayoutSupport::localVisualRect(object);
(...skipping 10 matching lines...) Expand all
174 // In SPv2, locationInBacking is in the space of their local transform node. 173 // In SPv2, locationInBacking is in the space of their local transform node.
175 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) 174 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
176 return object.paintOffset(); 175 return object.paintOffset();
177 176
178 LayoutPoint point; 177 LayoutPoint point;
179 if (object != context.paintInvalidationContainer) { 178 if (object != context.paintInvalidationContainer) {
180 point.moveBy(object.paintOffset()); 179 point.moveBy(object.paintOffset());
181 180
182 const auto* containerTransform = 181 const auto* containerTransform =
183 context.paintInvalidationContainer->contentsProperties()->transform(); 182 context.paintInvalidationContainer->contentsProperties()->transform();
184 if (context.m_treeBuilderContext->current.transform != containerTransform) { 183 if (context.m_treeBuilderContext.current.transform != containerTransform) {
185 FloatRect rect = FloatRect(FloatPoint(point), FloatSize()); 184 FloatRect rect = FloatRect(FloatPoint(point), FloatSize());
186 context.m_geometryMapper.sourceToDestinationRect( 185 context.m_geometryMapper.sourceToDestinationRect(
187 context.m_treeBuilderContext->current.transform, containerTransform, 186 context.m_treeBuilderContext.current.transform, containerTransform,
188 rect); 187 rect);
189 point = LayoutPoint(rect.location()); 188 point = LayoutPoint(rect.location());
190 } 189 }
191 190
192 // Convert the result to the container's contents space. 191 // Convert the result to the container's contents space.
193 point.moveBy(-context.paintInvalidationContainer->paintOffset()); 192 point.moveBy(-context.paintInvalidationContainer->paintOffset());
194 } 193 }
195 194
196 if (context.paintInvalidationContainer->layer()->groupedMapping()) { 195 if (context.paintInvalidationContainer->layer()->groupedMapping()) {
197 FloatPoint floatPoint(point); 196 FloatPoint floatPoint(point);
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 context.forcedSubtreeInvalidationFlags |= 322 context.forcedSubtreeInvalidationFlags |=
324 PaintInvalidatorContext::ForcedSubtreeFullInvalidation; 323 PaintInvalidatorContext::ForcedSubtreeFullInvalidation;
325 } 324 }
326 325
327 if (object == context.paintInvalidationContainer) { 326 if (object == context.paintInvalidationContainer) {
328 // When we hit a new paint invalidation container, we don't need to 327 // When we hit a new paint invalidation container, we don't need to
329 // continue forcing a check for paint invalidation, since we're 328 // continue forcing a check for paint invalidation, since we're
330 // descending into a different invalidation container. (For instance if 329 // descending into a different invalidation container. (For instance if
331 // our parents were moved, the entire container will just move.) 330 // our parents were moved, the entire container will just move.)
332 if (object != context.paintInvalidationContainerForStackedContents) { 331 if (object != context.paintInvalidationContainerForStackedContents) {
333 // However, we need to keep ForcedSubtreeVisualRectUpdate and 332 // However, we need to keep the
334 // ForcedSubtreeFullInvalidationForStackedContents flags if the current 333 // ForcedSubtreeFullInvalidationForStackedContents flag if the current
335 // object isn't the paint invalidation container of stacked contents. 334 // object isn't the paint invalidation container of stacked contents.
336 context.forcedSubtreeInvalidationFlags &= 335 context.forcedSubtreeInvalidationFlags &= PaintInvalidatorContext::
337 (PaintInvalidatorContext::ForcedSubtreeVisualRectUpdate | 336 ForcedSubtreeFullInvalidationForStackedContents;
338 PaintInvalidatorContext::
339 ForcedSubtreeFullInvalidationForStackedContents);
340 } else { 337 } else {
341 context.forcedSubtreeInvalidationFlags = 0; 338 context.forcedSubtreeInvalidationFlags = 0;
342 } 339 }
343 } 340 }
344 341
345 DCHECK(context.paintInvalidationContainer == 342 DCHECK(context.paintInvalidationContainer ==
346 object.containerForPaintInvalidation()); 343 object.containerForPaintInvalidation());
347 DCHECK(context.paintingLayer == object.paintingLayer()); 344 DCHECK(context.paintingLayer == object.paintingLayer());
348 } 345 }
349 346
350 void PaintInvalidator::updateVisualRectIfNeeded(
351 const LayoutObject& object,
352 PaintInvalidatorContext& context) {
353 context.oldVisualRect = object.visualRect();
354 context.oldLocation = ObjectPaintInvalidator(object).locationInBacking();
355
356 #if DCHECK_IS_ON()
357 FindObjectVisualRectNeedingUpdateScope finder(object, context);
358 #endif
359
360 if (!context.needsVisualRectUpdate(object)) {
361 context.newLocation = context.oldLocation;
362 return;
363 }
364
365 updateVisualRect(object, context);
366 }
367
368 void PaintInvalidator::updateVisualRect(const LayoutObject& object, 347 void PaintInvalidator::updateVisualRect(const LayoutObject& object,
369 PaintInvalidatorContext& context) { 348 PaintInvalidatorContext& context) {
370 // The paint offset should already be updated through
371 // PaintPropertyTreeBuilder::updatePropertiesForSelf.
372 DCHECK(context.m_treeBuilderContext);
373 DCHECK(context.m_treeBuilderContext->current.paintOffset ==
374 object.paintOffset());
375
376 Optional<ScopedUndoFrameViewContentClipAndScroll> 349 Optional<ScopedUndoFrameViewContentClipAndScroll>
377 undoFrameViewContentClipAndScroll; 350 undoFrameViewContentClipAndScroll;
378 351
379 if (!RuntimeEnabledFeatures::rootLayerScrollingEnabled() && 352 if (!RuntimeEnabledFeatures::rootLayerScrollingEnabled() &&
380 object.isLayoutView() && !object.isPaintInvalidationContainer()) { 353 object.isLayoutView() && !object.isPaintInvalidationContainer()) {
381 undoFrameViewContentClipAndScroll.emplace(*toLayoutView(object).frameView(), 354 undoFrameViewContentClipAndScroll.emplace(*toLayoutView(object).frameView(),
382 *context.m_treeBuilderContext); 355 context.m_treeBuilderContext);
383 } 356 }
384 357
358 // TODO(crbug.com/637313): Use GeometryMapper which now supports filter
359 // geometry effects, after skia optimizes filter's mapRect operation.
360 // TODO(crbug.com/648274): This is a workaround for multi-column contents.
361 if (object.hasFilterInducingProperty() || object.isLayoutFlowThread()) {
362 context.forcedSubtreeInvalidationFlags |=
363 PaintInvalidatorContext::ForcedSubtreeSlowPathRect;
364 }
365
366 ObjectPaintInvalidator objectPaintInvalidator(object);
367 context.oldVisualRect = object.visualRect();
368 context.oldLocation = objectPaintInvalidator.locationInBacking();
369
385 LayoutRect newVisualRect = computeVisualRectInBacking(object, context); 370 LayoutRect newVisualRect = computeVisualRectInBacking(object, context);
386 if (object.isBoxModelObject()) { 371 if (object.isBoxModelObject()) {
387 context.newLocation = computeLocationInBacking(object, context); 372 context.newLocation = computeLocationInBacking(object, context);
373
388 // Location of empty visual rect doesn't affect paint invalidation. Set it 374 // Location of empty visual rect doesn't affect paint invalidation. Set it
389 // to newLocation to avoid saving the previous location separately in 375 // to newLocation to avoid saving the previous location separately in
390 // ObjectPaintInvalidator. 376 // ObjectPaintInvalidator.
391 if (newVisualRect.isEmpty()) 377 if (newVisualRect.isEmpty())
392 newVisualRect.setLocation(context.newLocation); 378 newVisualRect.setLocation(context.newLocation);
393 } else { 379 } else {
394 // Use visual rect location for non-LayoutBoxModelObject because it suffices 380 // Use visual rect location for non-LayoutBoxModelObject because it suffices
395 // to check whether a visual rect changes for layout caused invalidation. 381 // to check whether a visual rect changes for layout caused invalidation.
396 context.newLocation = newVisualRect.location(); 382 context.newLocation = newVisualRect.location();
397 } 383 }
398 384
399 object.getMutableForPainting().setVisualRect(newVisualRect); 385 object.getMutableForPainting().setVisualRect(newVisualRect);
400 ObjectPaintInvalidator(object).setLocationInBacking(context.newLocation); 386 objectPaintInvalidator.setLocationInBacking(context.newLocation);
401 } 387 }
402 388
403 void PaintInvalidator::invalidatePaintIfNeeded( 389 void PaintInvalidator::invalidatePaintIfNeeded(
404 FrameView& frameView, 390 FrameView& frameView,
405 PaintInvalidatorContext& context) { 391 PaintInvalidatorContext& context) {
406 LayoutView* layoutView = frameView.layoutView(); 392 LayoutView* layoutView = frameView.layoutView();
407 CHECK(layoutView); 393 CHECK(layoutView);
408 394
409 context.paintInvalidationContainer = 395 context.paintInvalidationContainer =
410 context.paintInvalidationContainerForStackedContents = 396 context.paintInvalidationContainerForStackedContents =
411 &layoutView->containerForPaintInvalidation(); 397 &layoutView->containerForPaintInvalidation();
412 context.paintingLayer = layoutView->layer(); 398 context.paintingLayer = layoutView->layer();
413 399
414 if (!RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { 400 if (!RuntimeEnabledFeatures::rootLayerScrollingEnabled()) {
415 Optional<ScopedUndoFrameViewContentClipAndScroll> undo; 401 ScopedUndoFrameViewContentClipAndScroll undo(frameView,
416 if (context.m_treeBuilderContext) 402 context.m_treeBuilderContext);
417 undo.emplace(frameView, *context.m_treeBuilderContext);
418 frameView.invalidatePaintOfScrollControlsIfNeeded(context); 403 frameView.invalidatePaintOfScrollControlsIfNeeded(context);
419 } 404 }
420 } 405 }
421 406
422 void PaintInvalidator::invalidatePaintIfNeeded( 407 void PaintInvalidator::invalidatePaintIfNeeded(
423 const LayoutObject& object, 408 const LayoutObject& object,
424 PaintInvalidatorContext& context) { 409 PaintInvalidatorContext& context) {
425 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.invalidation"), 410 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.invalidation"),
426 "PaintInvalidator::invalidatePaintIfNeeded()", "object", 411 "PaintInvalidator::invalidatePaintIfNeeded()", "object",
427 object.debugName().ascii()); 412 object.debugName().ascii());
428 413
429 object.getMutableForPainting().ensureIsReadyForPaintInvalidation(); 414 object.getMutableForPainting().ensureIsReadyForPaintInvalidation();
430 415
416 // The paint offset should already be updated through
417 // PaintPropertyTreeBuilder::updatePropertiesForSelf.
418 DCHECK(context.m_treeBuilderContext.current.paintOffset ==
419 object.paintOffset());
420
431 updatePaintingLayer(object, context); 421 updatePaintingLayer(object, context);
432 422
433 if (object.document().printing() && 423 if (object.document().printing() &&
434 !RuntimeEnabledFeatures::printBrowserEnabled()) 424 !RuntimeEnabledFeatures::printBrowserEnabled())
435 return; // Don't invalidate paints if we're printing. 425 return; // Don't invalidate paints if we're printing.
436 426
437 // TODO(crbug.com/637313): Use GeometryMapper which now supports filter 427 updatePaintInvalidationContainer(object, context);
438 // geometry effects, after skia optimizes filter's mapRect operation. 428
439 // TODO(crbug.com/648274): This is a workaround for multi-column contents. 429 bool objectShouldCheckForPaintInvalidation =
440 if (object.hasFilterInducingProperty() || object.isLayoutFlowThread()) { 430 object.shouldCheckForPaintInvalidation();
441 context.forcedSubtreeInvalidationFlags |= 431 if (!context.forcedSubtreeInvalidationFlags &&
442 PaintInvalidatorContext::ForcedSubtreeSlowPathRect; 432 !objectShouldCheckForPaintInvalidation) {
433 #if CHECK_VISUAL_RECT_UPDATE
434 updateVisualRect(object, context);
435 DCHECK(
436 (context.oldVisualRect.isEmpty() && context.newVisualRect.isEmpty()) ||
437 enclosingIntRect(context.oldVisualRect) ==
438 enclosingIntRect(context.newVisualRect))
439 << "Visual rect changed without needing paint invalidation:"
440 << " object=" << object.debugName()
441 << " old=" << context.oldVisualRect.toString()
442 << " new=" << context.newVisualRect.toString();
443 DCHECK(object.isText() || context.oldLocation == context.newLocation)
444 << "Location changed without needing paint invalidation:"
445 << " old=" << context.oldLocation.toString()
446 << " new=" << context.newLocation.toString();
447 #endif
448 return;
443 } 449 }
444 450
445 updatePaintInvalidationContainer(object, context); 451 updateVisualRect(object, context);
446 updateVisualRectIfNeeded(object, context);
447 452
448 if (!object.shouldCheckForPaintInvalidation() && 453 if (!objectShouldCheckForPaintInvalidation &&
449 !(context.forcedSubtreeInvalidationFlags & 454 context.forcedSubtreeInvalidationFlags ==
450 ~PaintInvalidatorContext::ForcedSubtreeVisualRectUpdate)) { 455 PaintInvalidatorContext::ForcedSubtreeInvalidationRectUpdate) {
451 // We are done updating anything needed. No other paint invalidation work to 456 // We are done updating the visual rect. No other paint invalidation work to
452 // do for this object. 457 // do for this object.
453 return; 458 return;
454 } 459 }
455 460
456 if (object.isSVGHiddenContainer()) { 461 if (object.isSVGHiddenContainer()) {
457 context.forcedSubtreeInvalidationFlags |= 462 context.forcedSubtreeInvalidationFlags |=
458 PaintInvalidatorContext::ForcedSubtreeNoRasterInvalidation; 463 PaintInvalidatorContext::ForcedSubtreeNoRasterInvalidation;
459 } 464 }
460 465
461 PaintInvalidationReason reason = object.invalidatePaintIfNeeded(context); 466 PaintInvalidationReason reason = object.invalidatePaintIfNeeded(context);
(...skipping 17 matching lines...) Expand all
479 484
480 if (object.mayNeedPaintInvalidationSubtree()) { 485 if (object.mayNeedPaintInvalidationSubtree()) {
481 context.forcedSubtreeInvalidationFlags |= 486 context.forcedSubtreeInvalidationFlags |=
482 PaintInvalidatorContext::ForcedSubtreeInvalidationChecking; 487 PaintInvalidatorContext::ForcedSubtreeInvalidationChecking;
483 } 488 }
484 489
485 if (context.oldLocation != context.newLocation) { 490 if (context.oldLocation != context.newLocation) {
486 context.forcedSubtreeInvalidationFlags |= 491 context.forcedSubtreeInvalidationFlags |=
487 PaintInvalidatorContext::ForcedSubtreeInvalidationChecking; 492 PaintInvalidatorContext::ForcedSubtreeInvalidationChecking;
488 } 493 }
489
490 if (context.forcedSubtreeInvalidationFlags &&
491 context.needsVisualRectUpdate(object)) {
492 // If any subtree flag is set, we also need to pass needsVisualRectUpdate
493 // requirement to the subtree.
494 context.forcedSubtreeInvalidationFlags |=
495 PaintInvalidatorContext::ForcedSubtreeVisualRectUpdate;
496 }
497 } 494 }
498 495
499 void PaintInvalidator::processPendingDelayedPaintInvalidations() { 496 void PaintInvalidator::processPendingDelayedPaintInvalidations() {
500 for (auto target : m_pendingDelayedPaintInvalidations) { 497 for (auto target : m_pendingDelayedPaintInvalidations)
501 target->getMutableForPainting().setShouldDoFullPaintInvalidation( 498 target->getMutableForPainting().setShouldDoFullPaintInvalidation(
502 PaintInvalidationDelayedFull); 499 PaintInvalidationDelayedFull);
503 }
504 } 500 }
505 501
506 } // namespace blink 502 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698