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 |