Chromium Code Reviews| OLD | NEW |
|---|---|
| 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/frame/FrameView.h" | 8 #include "core/frame/FrameView.h" |
| 9 #include "core/frame/LocalFrame.h" | |
| 10 #include "core/frame/Settings.h" | |
| 8 #include "core/layout/LayoutObject.h" | 11 #include "core/layout/LayoutObject.h" |
| 12 #include "core/layout/svg/SVGLayoutSupport.h" | |
| 13 #include "core/paint/PaintLayer.h" | |
| 14 #include "core/paint/PaintLayerScrollableArea.h" | |
| 9 | 15 |
| 10 namespace blink { | 16 namespace blink { |
| 11 | 17 |
| 12 void PaintInvalidator::invalidatePaintIfNeeded(FrameView& frameView, const Paint PropertyTreeBuilderContext& treeContext, Optional<PaintInvalidatorContext>& pain tInvalidatorContext) | 18 void PaintInvalidatorContext::mapLocalRectToPaintInvalidationBacking(const Layou tObject& object, LayoutRect& rect) const |
| 13 { | 19 { |
| 14 paintInvalidatorContext.emplace(*frameView.layoutView(), m_pendingDelayedPai ntInvalidations); | 20 // TODO(wangxianzhu): For now this is the same as the slow path in PaintInva lidationState. |
| 15 frameView.invalidatePaintIfNeeded(*paintInvalidatorContext); | 21 // Should implement this with GeometryMapper. |
| 16 } | 22 if (object.isBox()) |
| 17 | 23 toLayoutBox(object).flipForWritingMode(rect); |
| 18 void PaintInvalidator::invalidatePaintIfNeeded(const LayoutObject& layoutObject, const PaintPropertyTreeBuilderContext& treeContext, const PaintInvalidatorConte xt& parentPaintInvalidatorContext, Optional<PaintInvalidatorContext>& paintInval idatorContext) | 24 |
| 19 { | 25 if (object.isLayoutView()) |
| 20 if (!layoutObject.shouldCheckForPaintInvalidation(parentPaintInvalidatorCont ext)) | 26 toLayoutView(object).mapToVisualRectInAncestorSpace(paintInvalidationCon tainer, rect, InputIsInFrameCoordinates, DefaultVisualRectFlags); |
| 27 else | |
| 28 object.mapToVisualRectInAncestorSpace(paintInvalidationContainer, rect); | |
| 29 } | |
| 30 | |
| 31 static LayoutRect computePaintInvalidationRectInBacking(const LayoutObject& obje ct, const PaintInvalidatorContext& context) | |
| 32 { | |
| 33 // TODO(wangxianzhu): For now this is the same as the slow path in PaintInva lidationState. | |
| 34 // Should implement this with GeometryMapper. | |
| 35 if (object.isSVG() && !object.isSVGRoot()) { | |
| 36 LayoutRect rect = SVGLayoutSupport::clippedOverflowRectForPaintInvalidat ion(object, *context.paintInvalidationContainer); | |
| 37 if (context.paintInvalidationContainer->layer()->groupedMapping()) | |
| 38 PaintLayer::mapRectInPaintInvalidationContainerToBacking(*context.pa intInvalidationContainer, rect); | |
| 39 return rect; | |
| 40 } | |
| 41 | |
| 42 LayoutRect rect = object.localOverflowRectForPaintInvalidation(); | |
| 43 context.mapLocalRectToPaintInvalidationBacking(object, rect); | |
| 44 return rect; | |
| 45 } | |
| 46 | |
| 47 static LayoutPoint computeLocationFromPaintInvalidationBacking(const LayoutObjec t& object, const PaintInvalidatorContext& context) | |
| 48 { | |
| 49 // TODO(wangxianzhu): For now this is the same as the slow path in PaintInva lidationState. | |
| 50 // Should implement this with GeometryMapper. | |
| 51 FloatPoint point; | |
| 52 if (object != context.paintInvalidationContainer) { | |
| 53 if (object.isLayoutView()) | |
| 54 point = toLayoutView(object).localToAncestorPoint(point, context.pai ntInvalidationContainer, TraverseDocumentBoundaries | InputIsInFrameCoordinates) ; | |
| 55 else | |
| 56 point = object.localToAncestorPoint(point, context.paintInvalidation Container, TraverseDocumentBoundaries); | |
| 57 } | |
| 58 | |
| 59 if (context.paintInvalidationContainer->layer()->groupedMapping()) | |
| 60 PaintLayer::mapPointInPaintInvalidationContainerToBacking(*context.paint InvalidationContainer, point); | |
| 61 | |
| 62 return LayoutPoint(point); | |
| 63 } | |
| 64 | |
| 65 static void updatePaintingLayer(const LayoutObject& object, PaintInvalidatorCont ext& context) | |
| 66 { | |
| 67 if (object.hasLayer() && toLayoutBoxModelObject(object).hasSelfPaintingLayer ()) | |
| 68 context.paintingLayer = toLayoutBoxModelObject(object).layer(); | |
| 69 | |
| 70 if (object.isLayoutBlockFlow() && toLayoutBlockFlow(object).containsFloats() ) | |
| 71 context.paintingLayer->setNeedsPaintPhaseFloat(); | |
| 72 | |
| 73 if (object == context.paintingLayer->layoutObject()) | |
| 21 return; | 74 return; |
| 22 | 75 |
| 23 paintInvalidatorContext.emplace(parentPaintInvalidatorContext, layoutObject) ; | 76 if (object.styleRef().hasOutline()) |
| 24 | 77 context.paintingLayer->setNeedsPaintPhaseDescendantOutlines(); |
| 25 if (layoutObject.mayNeedPaintInvalidationSubtree()) | 78 |
| 26 paintInvalidatorContext->setForceSubtreeInvalidationCheckingWithinContai ner(); | 79 if (object.hasBoxDecorationBackground() |
| 27 | 80 // We also paint overflow controls in background phase. |
| 28 PaintInvalidationReason reason = layoutObject.getMutableForPainting().invali datePaintIfNeeded(*paintInvalidatorContext); | 81 || (object.hasOverflowClip() && toLayoutBox(object).getScrollableArea()- >hasOverflowControls())) { |
| 29 layoutObject.getMutableForPainting().clearPaintInvalidationFlags(*paintInval idatorContext); | 82 context.paintingLayer->setNeedsPaintPhaseDescendantBlockBackgrounds(); |
| 30 | 83 } |
| 31 paintInvalidatorContext->updateForChildren(reason); | 84 } |
| 85 | |
| 86 static void updateContext(const LayoutObject& object, PaintInvalidatorContext& c ontext) | |
| 87 { | |
| 88 if (object.isPaintInvalidationContainer()) { | |
| 89 context.paintInvalidationContainer = toLayoutBoxModelObject(&object); | |
| 90 if (object.styleRef().isStackingContext()) | |
| 91 context.paintInvalidationContainerForStackedContents = toLayoutBoxMo delObject(&object); | |
| 92 } else if (object.isLayoutView()) { | |
| 93 // paintInvalidationContainerForStackedContents is only for stacked desc endants in its own frame, | |
| 94 // because it doesn't establish stacking context for stacked contents in sub-frames. | |
|
chrishtr
2016/08/10 20:47:33
I know you're copying this comment, but is this re
Xianzhu
2016/08/10 22:16:43
No. It means a frame breaks the relationship betwe
chrishtr
2016/08/10 23:23:22
Isn't this equivalent to the situation in line 91
Xianzhu
2016/08/10 23:48:31
The case at line 91 is for a paint invalidation co
| |
| 95 // Contents stacked in the root stacking context in this frame should us e this frame's paintInvalidationContainer. | |
| 96 context.paintInvalidationContainerForStackedContents = context.paintInva lidationContainer; | |
| 97 } else if (object.styleRef().isStacked() | |
| 98 // This is to exclude some objects (e.g. LayoutText) inheriting stacked style from parent but aren't actually stacked. | |
| 99 && object.hasLayer() | |
| 100 && context.paintInvalidationContainer != context.paintInvalidationContai nerForStackedContents) { | |
| 101 // The current object is stacked, so we should use m_paintInvalidationCo ntainerForStackedContents as its | |
| 102 // paint invalidation container on which the current object is painted. | |
| 103 context.paintInvalidationContainer = context.paintInvalidationContainerF orStackedContents; | |
| 104 if (context.forcedSubtreeInvalidationFlags & PaintInvalidatorContext::Fo rcedSubtreeFullInvalidationForStackedContents) | |
| 105 context.forcedSubtreeInvalidationFlags |= PaintInvalidatorContext::F orcedSubtreeFullInvalidation; | |
| 106 } | |
| 107 | |
| 108 if (object == context.paintInvalidationContainer) { | |
| 109 // When we hit a new paint invalidation container, we don't need to | |
| 110 // continue forcing a check for paint invalidation, since we're | |
| 111 // descending into a different invalidation container. (For instance if | |
| 112 // our parents were moved, the entire container will just move.) | |
| 113 if (object != context.paintInvalidationContainerForStackedContents) { | |
| 114 // However, we need to keep the ForcedSubtreeFullInvalidationForStac kedContents flag | |
| 115 // if the current object isn't the paint invalidation container of s tacked contents. | |
| 116 context.forcedSubtreeInvalidationFlags &= PaintInvalidatorContext::F orcedSubtreeFullInvalidationForStackedContents; | |
| 117 } else { | |
| 118 context.forcedSubtreeInvalidationFlags = 0; | |
| 119 } | |
| 120 } | |
| 121 | |
| 122 DCHECK(context.paintInvalidationContainer == object.containerForPaintInvalid ation()); | |
| 123 DCHECK(context.paintingLayer == object.paintingLayer()); | |
| 124 | |
| 125 if (object.mayNeedPaintInvalidationSubtree()) | |
|
chrishtr
2016/08/10 20:47:33
This is previously in LayoutBoxModelObject::invali
Xianzhu
2016/08/10 22:16:43
The reason was that mayNeedPaintInvalidationSubtre
| |
| 126 context.forcedSubtreeInvalidationFlags |= PaintInvalidatorContext::Force dSubtreeInvalidationChecking; | |
| 127 | |
| 128 context.oldBounds = object.previousPaintInvalidationRect(); | |
| 129 context.oldLocation = object.previousPositionFromPaintInvalidationBacking(); | |
| 130 context.newBounds = computePaintInvalidationRectInBacking(object, context); | |
| 131 context.newLocation = computeLocationFromPaintInvalidationBacking(object, co ntext); | |
| 132 | |
| 133 // Composited scrolling should not be included in the bounds and position tr acking, because the graphics layer backing the scroller | |
| 134 // does not move on scroll. | |
| 135 // TODO(chrishtr): can we just avoid adding in the scroll in the first place in LayoutBox::mapScrollingContentsRectToBoxSpace? | |
|
chrishtr
2016/08/10 20:47:33
I landed the patch to remove this...
Xianzhu
2016/08/10 22:16:43
My fault when dealing with conflicts.
Fixed.
| |
| 136 if (object.compositedScrollsWithRespectTo(*context.paintInvalidationContaine r)) { | |
| 137 LayoutSize inverseOffset(toLayoutBox(context.paintInvalidationContainer) ->scrolledContentOffset()); | |
| 138 context.newLocation.move(inverseOffset); | |
| 139 context.newBounds.move(inverseOffset); | |
| 140 } | |
| 141 | |
| 142 object.getMutableForPainting().setPreviousPaintInvalidationRect(context.newB ounds); | |
| 143 object.getMutableForPainting().setPreviousPositionFromPaintInvalidationBacki ng(context.newLocation); | |
| 144 } | |
| 145 | |
| 146 void PaintInvalidator::invalidatePaintIfNeeded(FrameView& frameView, PaintInvali datorContext& context) | |
| 147 { | |
| 148 LayoutView* layoutView = frameView.layoutView(); | |
| 149 CHECK(layoutView); | |
| 150 | |
| 151 context.paintInvalidationContainer = context.paintInvalidationContainerForSt ackedContents = &layoutView->containerForPaintInvalidation(); | |
| 152 context.paintingLayer = layoutView->layer(); | |
| 153 | |
| 154 if (!frameView.frame().settings() || !frameView.frame().settings()->rootLaye rScrolls()) | |
| 155 frameView.invalidatePaintOfScrollControlsIfNeeded(context); | |
| 156 | |
| 157 if (frameView.frame().selection().isCaretBoundsDirty()) | |
| 158 frameView.frame().selection().invalidateCaretRect(); | |
| 159 | |
| 160 // Temporary callback for crbug.com/487345,402044 | |
| 161 // TODO(ojan): Make this more general to be used by PositionObserver | |
| 162 // and rAF throttling. | |
| 163 IntRect visibleRect = frameView.rootFrameToContents(frameView.computeVisible Area()); | |
| 164 layoutView->sendMediaPositionChangeNotifications(visibleRect); | |
| 165 } | |
| 166 | |
| 167 void PaintInvalidator::invalidatePaintIfNeeded(const LayoutObject& object, Paint InvalidatorContext& context) | |
| 168 { | |
| 169 if (!context.forcedSubtreeInvalidationFlags && !object.shouldCheckForPaintIn validationRegardlessOfPaintInvalidationState()) | |
| 170 return; | |
| 171 | |
| 172 updatePaintingLayer(object, context); | |
| 173 | |
| 174 if (object.document().printing()) | |
| 175 return; // Don't invalidate paints if we're printing. | |
| 176 | |
| 177 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.invalidation"), "PaintInvalida tor::invalidatePaintIfNeeded()", "object", object.debugName().ascii()); | |
| 178 | |
| 179 updateContext(object, context); | |
| 180 | |
| 181 if (!object.shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationStat e() && context.forcedSubtreeInvalidationFlags == PaintInvalidatorContext::Forced SubtreeInvalidationRectUpdate) { | |
| 182 // We are done updating the paint invalidation rect. No other paint inva lidation work to do for this object. | |
| 183 return; | |
| 184 } | |
| 185 | |
| 186 switch (object.invalidatePaintIfNeeded(context)) { | |
| 187 case PaintInvalidationDelayedFull: | |
| 188 m_pendingDelayedPaintInvalidations.append(&object); | |
| 189 break; | |
| 190 case PaintInvalidationSubtree: | |
| 191 context.forcedSubtreeInvalidationFlags |= (PaintInvalidatorContext::Forc edSubtreeFullInvalidation | PaintInvalidatorContext::ForcedSubtreeFullInvalidati onForStackedContents); | |
| 192 break; | |
| 193 case PaintInvalidationSVGResourceChange: | |
| 194 context.forcedSubtreeInvalidationFlags |= PaintInvalidatorContext::Force dSubtreeInvalidationChecking; | |
| 195 break; | |
| 196 default: | |
| 197 break; | |
| 198 } | |
| 199 | |
| 200 if (context.oldLocation != context.newLocation) | |
| 201 context.forcedSubtreeInvalidationFlags |= PaintInvalidatorContext::Force dSubtreeInvalidationChecking; | |
| 202 | |
| 203 object.getMutableForPainting().clearPaintInvalidationFlags(); | |
| 32 } | 204 } |
| 33 | 205 |
| 34 void PaintInvalidator::processPendingDelayedPaintInvalidations() | 206 void PaintInvalidator::processPendingDelayedPaintInvalidations() |
| 35 { | 207 { |
| 36 for (auto target : m_pendingDelayedPaintInvalidations) | 208 for (auto target : m_pendingDelayedPaintInvalidations) |
| 37 target->getMutableForPainting().setShouldDoDelayedFullPaintInvalidation( ); | 209 target->getMutableForPainting().setShouldDoFullPaintInvalidation(PaintIn validationDelayedFull); |
| 38 } | 210 } |
| 39 | 211 |
| 40 } // namespace blink | 212 } // namespace blink |
| OLD | NEW |