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

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

Issue 1774193002: New paint invalidation using paint property tree walk (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 9 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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/PaintPropertyTreeBuilder.h" 5 #include "core/paint/PrePaintTreeWalk.h"
6 6
7 #include "core/frame/FrameView.h" 7 #include "core/frame/FrameView.h"
8 #include "core/layout/LayoutPart.h" 8 #include "core/layout/LayoutPart.h"
9 #include "core/layout/LayoutView.h" 9 #include "core/layout/LayoutView.h"
10 #include "core/paint/ObjectPaintProperties.h" 10 #include "core/paint/ObjectPaintProperties.h"
11 #include "core/paint/PaintLayer.h" 11 #include "core/paint/PaintLayer.h"
12 #include "platform/graphics/paint/ClipPaintPropertyNode.h" 12 #include "platform/graphics/paint/ClipPaintPropertyNode.h"
13 #include "platform/graphics/paint/TransformPaintPropertyNode.h" 13 #include "platform/graphics/paint/TransformPaintPropertyNode.h"
14 #include "platform/transforms/TransformationMatrix.h" 14 #include "platform/transforms/TransformationMatrix.h"
15 15
16 namespace blink { 16 namespace blink {
17 17
18 // The context for layout tree walk. 18 // The context for layout tree walk.
19 // The walk will be done in the primary tree order (= DOM order), thus the conte xt will also be 19 // The walk will be done in the primary tree order (= DOM order), thus the conte xt will also be
20 // responsible for bookkeeping tree state in other order, for example, the most recent position 20 // responsible for bookkeeping tree state in other order, for example, the most recent position
21 // container seen. 21 // container seen.
22 struct PaintPropertyTreeBuilderContext { 22 struct PrePaintTreeWalkContext {
23 PaintPropertyTreeBuilderContext() 23 PrePaintTreeWalkContext()
24 : currentTransform(nullptr) 24 : paintInvalidationContainer(nullptr)
25 , currentClip(nullptr) 25 , paintInvalidationContainerForOutOfFlowPositioned(nullptr)
trchen 2016/03/11 23:09:39 The name of the variable isn't accurate. Paint inv
26 , transformForAbsolutePosition(nullptr) 26 { }
27 , clipForAbsolutePosition(nullptr) 27
28 , transformForFixedPosition(nullptr) 28 // TODO(wangxianzhu): The RefPtrs are needed for SPv1 which doesn't save the properties
29 , clipForFixedPosition(nullptr) 29 // into LayoutObjects. Change them to normal pointers for SPv2.
30 , currentEffect(nullptr) { }
31 30
32 // The combination of a transform and paint offset describes a linear space. 31 // The combination of a transform and paint offset describes a linear space.
33 // When a layout object recur to its children, the main context is expected to refer 32 // When a layout object recur to its children, the main context is expected to refer
34 // the object's border box, then the callee will derive its own border box b y translating 33 // the object's border box, then the callee will derive its own border box b y translating
35 // the space with its own layout location. 34 // the space with its own layout location.
36 TransformPaintPropertyNode* currentTransform; 35 RefPtr<TransformPaintPropertyNode> currentTransform;
37 LayoutPoint paintOffset; 36 LayoutPoint paintOffset;
38 // The clip node describes the accumulated raster clip for the current subtr ee. 37 // The clip node describes the accumulated raster clip for the current subtr ee.
39 // Note that the computed raster region in canvas space for a clip node is i ndependent from 38 // Note that the computed raster region in canvas space for a clip node is i ndependent from
40 // the transform and paint offset above. Also the actual raster region may b e affected 39 // the transform and paint offset above. Also the actual raster region may b e affected
41 // by layerization and occlusion tracking. 40 // by layerization and occlusion tracking.
42 ClipPaintPropertyNode* currentClip; 41 RefPtr<ClipPaintPropertyNode> currentClip;
43 42
44 // Separate context for out-of-flow positioned and fixed positioned elements are needed 43 // Separate context for out-of-flow positioned and fixed positioned elements are needed
45 // because they don't use DOM parent as their containing block. 44 // because they don't use DOM parent as their containing block.
46 // These additional contexts normally pass through untouched, and are only c opied from 45 // These additional contexts normally pass through untouched, and are only c opied from
47 // the main context when the current element serves as the containing block of corresponding 46 // the main context when the current element serves as the containing block of corresponding
48 // positioned descendants. 47 // positioned descendants.
49 // Overflow clips are also inherited by containing block tree instead of DOM tree, thus they 48 // Overflow clips are also inherited by containing block tree instead of DOM tree, thus they
50 // are included in the additional context too. 49 // are included in the additional context too.
51 TransformPaintPropertyNode* transformForAbsolutePosition; 50 RefPtr<TransformPaintPropertyNode> transformForAbsolutePosition;
52 LayoutPoint paintOffsetForAbsolutePosition; 51 LayoutPoint paintOffsetForAbsolutePosition;
53 ClipPaintPropertyNode* clipForAbsolutePosition; 52 RefPtr<ClipPaintPropertyNode> clipForAbsolutePosition;
54 53
55 TransformPaintPropertyNode* transformForFixedPosition; 54 RefPtr<TransformPaintPropertyNode> transformForFixedPosition;
56 LayoutPoint paintOffsetForFixedPosition; 55 LayoutPoint paintOffsetForFixedPosition;
57 ClipPaintPropertyNode* clipForFixedPosition; 56 RefPtr<ClipPaintPropertyNode> clipForFixedPosition;
58 57
59 // The effect hierarchy is applied by the stacking context tree. It is guara nteed that every 58 // The effect hierarchy is applied by the stacking context tree. It is guara nteed that every
60 // DOM descendant is also a stacking context descendant. Therefore, we don't need extra 59 // DOM descendant is also a stacking context descendant. Therefore, we don't need extra
61 // bookkeeping for effect nodes and can generate the effect tree from a DOM- order traversal. 60 // bookkeeping for effect nodes and can generate the effect tree from a DOM- order traversal.
62 EffectPaintPropertyNode* currentEffect; 61 RefPtr<EffectPaintPropertyNode> currentEffect;
62
63 // For SPv1 only.
64 const LayoutBoxModelObject* paintInvalidationContainer;
65 const LayoutBoxModelObject* paintInvalidationContainerForOutOfFlowPositioned ;
63 }; 66 };
64 67
65 void PaintPropertyTreeBuilder::buildPropertyTrees(FrameView& rootFrame) 68 void PrePaintTreeWalk::buildPropertyTreesAndInvalidatePaint(FrameView& rootFrame )
66 { 69 {
67 walk(rootFrame, PaintPropertyTreeBuilderContext()); 70 walk(rootFrame, PrePaintTreeWalkContext(), nullptr);
68 } 71 }
69 72
70 void PaintPropertyTreeBuilder::walk(FrameView& frameView, const PaintPropertyTre eBuilderContext& context) 73 void PrePaintTreeWalk::walk(FrameView& frameView, const PrePaintTreeWalkContext& context, const PaintInvalidationState* paintInvalidationState)
71 { 74 {
72 PaintPropertyTreeBuilderContext localContext(context); 75 PrePaintTreeWalkContext localContext(context);
73 76
74 // TODO(pdr): Creating paint properties for FrameView here will not be 77 // TODO(pdr): Creating paint properties for FrameView here will not be
75 // needed once settings()->rootLayerScrolls() is enabled. 78 // needed once settings()->rootLayerScrolls() is enabled.
76 // TODO(pdr): Make this conditional on the rootLayerScrolls setting. 79 // TODO(pdr): Make this conditional on the rootLayerScrolls setting.
77 80
78 TransformationMatrix frameTranslate; 81 TransformationMatrix frameTranslate;
79 frameTranslate.translate(frameView.x() + context.paintOffset.x(), frameView. y() + context.paintOffset.y()); 82 frameTranslate.translate(frameView.x() + context.paintOffset.x(), frameView. y() + context.paintOffset.y());
80 RefPtr<TransformPaintPropertyNode> newTransformNodeForPreTranslation = Trans formPaintPropertyNode::create(frameTranslate, FloatPoint3D(), context.currentTra nsform); 83 RefPtr<TransformPaintPropertyNode> newTransformNodeForPreTranslation = Trans formPaintPropertyNode::create(frameTranslate, FloatPoint3D(), context.currentTra nsform);
81 localContext.transformForFixedPosition = newTransformNodeForPreTranslation.g et(); 84 localContext.transformForFixedPosition = newTransformNodeForPreTranslation.g et();
82 localContext.paintOffsetForFixedPosition = LayoutPoint(); 85 localContext.paintOffsetForFixedPosition = LayoutPoint();
83 86
84 FloatRoundedRect contentClip(IntRect(IntPoint(), frameView.visibleContentSiz e())); 87 FloatRoundedRect contentClip(IntRect(IntPoint(), frameView.visibleContentSiz e()));
85 RefPtr<ClipPaintPropertyNode> newClipNodeForContentClip = ClipPaintPropertyN ode::create(newTransformNodeForPreTranslation.get(), contentClip, localContext.c urrentClip); 88 RefPtr<ClipPaintPropertyNode> newClipNodeForContentClip = ClipPaintPropertyN ode::create(newTransformNodeForPreTranslation.get(), contentClip, localContext.c urrentClip);
86 localContext.currentClip = localContext.clipForAbsolutePosition = localConte xt.clipForFixedPosition = newClipNodeForContentClip.get(); 89 localContext.currentClip = localContext.clipForAbsolutePosition = localConte xt.clipForFixedPosition = newClipNodeForContentClip.get();
87 90
88 DoubleSize scrollOffset = frameView.scrollOffsetDouble(); 91 DoubleSize scrollOffset = frameView.scrollOffsetDouble();
89 TransformationMatrix frameScroll; 92 TransformationMatrix frameScroll;
90 frameScroll.translate(-scrollOffset.width(), -scrollOffset.height()); 93 frameScroll.translate(-scrollOffset.width(), -scrollOffset.height());
91 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = Tr ansformPaintPropertyNode::create(frameScroll, FloatPoint3D(), newTransformNodeFo rPreTranslation); 94 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = Tr ansformPaintPropertyNode::create(frameScroll, FloatPoint3D(), newTransformNodeFo rPreTranslation);
92 localContext.currentTransform = localContext.transformForAbsolutePosition = newTransformNodeForScrollTranslation.get(); 95 localContext.currentTransform = localContext.transformForAbsolutePosition = newTransformNodeForScrollTranslation.get();
93 localContext.paintOffset = localContext.paintOffsetForAbsolutePosition = Lay outPoint(); 96 localContext.paintOffset = localContext.paintOffsetForAbsolutePosition = Lay outPoint();
94 97
95 frameView.setPreTranslation(newTransformNodeForPreTranslation.release()); 98 frameView.setPreTranslation(newTransformNodeForPreTranslation.release());
96 frameView.setScrollTranslation(newTransformNodeForScrollTranslation.release( )); 99 frameView.setScrollTranslation(newTransformNodeForScrollTranslation.release( ));
97 frameView.setContentClip(newClipNodeForContentClip.release()); 100 frameView.setContentClip(newClipNodeForContentClip.release());
98 101
99 if (LayoutView* layoutView = frameView.layoutView()) 102 if (LayoutView* layoutView = frameView.layoutView())
100 walk(*layoutView, localContext); 103 walk(*layoutView, localContext, paintInvalidationState);
101 } 104 }
102 105
103 static void deriveBorderBoxFromContainerContext(const LayoutObject& object, Pain tPropertyTreeBuilderContext& context) 106 static void adjustContainerContextForPosition(const LayoutObject& object, PrePai ntTreeWalkContext& context)
107 {
108 switch (object.styleRef().position()) {
109 case AbsolutePosition:
110 context.currentTransform = context.transformForAbsolutePosition;
111 context.paintOffset = context.paintOffsetForAbsolutePosition;
112 context.currentClip = context.clipForAbsolutePosition;
113 context.paintInvalidationContainer = context.paintInvalidationContainerF orOutOfFlowPositioned;
trchen 2016/03/11 23:36:19 Per the previous comment, it is not the right plac
114 break;
115 case FixedPosition:
116 context.currentTransform = context.transformForFixedPosition;
117 context.paintOffset = context.paintOffsetForFixedPosition;
118 context.currentClip = context.clipForFixedPosition;
119 context.paintInvalidationContainer = context.paintInvalidationContainerF orOutOfFlowPositioned;
trchen 2016/03/11 23:36:19 Ditto.
120 break;
121 default:
122 break;
123 }
124 }
125
126 static void deriveBorderBoxFromContainerContext(const LayoutObject& object, PreP aintTreeWalkContext& context)
104 { 127 {
105 if (!object.isBoxModelObject()) 128 if (!object.isBoxModelObject())
106 return; 129 return;
107 130
108 const LayoutBoxModelObject& boxModelObject = toLayoutBoxModelObject(object); 131 const LayoutBoxModelObject& boxModelObject = toLayoutBoxModelObject(object);
109 132
110 // TODO(trchen): There is some insanity going on with tables. Double check r esults. 133 // TODO(trchen): There is some insanity going on with tables. Double check r esults.
111 switch (object.styleRef().position()) { 134 if (object.isInFlowPositioned())
trchen 2016/03/11 23:36:19 While this refactoring is appreciated, can we do t
112 case StaticPosition:
113 break;
114 case RelativePosition:
115 context.paintOffset += boxModelObject.offsetForInFlowPosition(); 135 context.paintOffset += boxModelObject.offsetForInFlowPosition();
116 break; 136
117 case AbsolutePosition:
118 context.currentTransform = context.transformForAbsolutePosition;
119 context.paintOffset = context.paintOffsetForAbsolutePosition;
120 context.currentClip = context.clipForAbsolutePosition;
121 break;
122 case StickyPosition:
123 context.paintOffset += boxModelObject.offsetForInFlowPosition();
124 break;
125 case FixedPosition:
126 context.currentTransform = context.transformForFixedPosition;
127 context.paintOffset = context.paintOffsetForFixedPosition;
128 context.currentClip = context.clipForFixedPosition;
129 break;
130 default:
131 ASSERT_NOT_REACHED();
132 }
133 if (boxModelObject.isBox()) 137 if (boxModelObject.isBox())
134 context.paintOffset += toLayoutBox(boxModelObject).locationOffset(); 138 context.paintOffset += toLayoutBox(boxModelObject).locationOffset();
135 } 139 }
136 140
137 static PassRefPtr<TransformPaintPropertyNode> createPaintOffsetTranslationIfNeed ed(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) 141 static PassRefPtr<TransformPaintPropertyNode> createPaintOffsetTranslationIfNeed ed(const LayoutObject& object, PrePaintTreeWalkContext& context)
138 { 142 {
139 bool shouldCreatePaintOffsetTranslationNode = false; 143 bool shouldCreatePaintOffsetTranslationNode = false;
140 if (object.isSVGRoot()) { 144 if (object.isSVGRoot()) {
141 // SVG doesn't use paint offset internally so emit a paint offset at the html->svg boundary. 145 // SVG doesn't use paint offset internally so emit a paint offset at the html->svg boundary.
142 shouldCreatePaintOffsetTranslationNode = true; 146 shouldCreatePaintOffsetTranslationNode = true;
143 } else if (object.isBoxModelObject()) { 147 } else if (object.isBoxModelObject()) {
144 // TODO(trchen): Eliminate PaintLayer dependency. 148 // TODO(trchen): Eliminate PaintLayer dependency.
145 PaintLayer* layer = toLayoutBoxModelObject(object).layer(); 149 PaintLayer* layer = toLayoutBoxModelObject(object).layer();
146 shouldCreatePaintOffsetTranslationNode = layer && layer->paintsWithTrans form(GlobalPaintNormalPhase); 150 shouldCreatePaintOffsetTranslationNode = layer && layer->paintsWithTrans form(GlobalPaintNormalPhase);
147 } 151 }
(...skipping 12 matching lines...) Expand all
160 static FloatPoint3D transformOrigin(const LayoutBox& box) 164 static FloatPoint3D transformOrigin(const LayoutBox& box)
161 { 165 {
162 const ComputedStyle& style = box.styleRef(); 166 const ComputedStyle& style = box.styleRef();
163 FloatSize borderBoxSize(box.size()); 167 FloatSize borderBoxSize(box.size());
164 return FloatPoint3D( 168 return FloatPoint3D(
165 floatValueForLength(style.transformOriginX(), borderBoxSize.width()), 169 floatValueForLength(style.transformOriginX(), borderBoxSize.width()),
166 floatValueForLength(style.transformOriginY(), borderBoxSize.height()), 170 floatValueForLength(style.transformOriginY(), borderBoxSize.height()),
167 style.transformOriginZ()); 171 style.transformOriginZ());
168 } 172 }
169 173
170 static PassRefPtr<TransformPaintPropertyNode> createTransformIfNeeded(const Layo utObject& object, PaintPropertyTreeBuilderContext& context) 174 static PassRefPtr<TransformPaintPropertyNode> createTransformIfNeeded(const Layo utObject& object, PrePaintTreeWalkContext& context)
171 { 175 {
172 if (object.isSVG() && !object.isSVGRoot()) { 176 if (object.isSVG() && !object.isSVGRoot()) {
173 const AffineTransform& transform = object.localToParentTransform(); 177 const AffineTransform& transform = object.localToParentTransform();
174 if (transform.isIdentity()) 178 if (transform.isIdentity())
175 return nullptr; 179 return nullptr;
176 180
177 // SVG's transform origin is baked into the localToParentTransform. 181 // SVG's transform origin is baked into the localToParentTransform.
178 RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = Transf ormPaintPropertyNode::create( 182 RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = Transf ormPaintPropertyNode::create(
179 transform, FloatPoint3D(0, 0, 0), context.currentTransform); 183 transform, FloatPoint3D(0, 0, 0), context.currentTransform);
180 context.currentTransform = newTransformNodeForTransform.get(); 184 context.currentTransform = newTransformNodeForTransform.get();
181 return newTransformNodeForTransform.release(); 185 return newTransformNodeForTransform.release();
182 } 186 }
183 187
184 const ComputedStyle& style = object.styleRef(); 188 const ComputedStyle& style = object.styleRef();
185 if (!object.isBox() || !style.hasTransform()) 189 if (!object.isBox() || !style.hasTransform())
186 return nullptr; 190 return nullptr;
187 191
188 ASSERT(context.paintOffset == LayoutPoint()); 192 ASSERT(context.paintOffset == LayoutPoint());
189 193
190 TransformationMatrix matrix; 194 TransformationMatrix matrix;
191 style.applyTransform(matrix, toLayoutBox(object).size(), ComputedStyle::Excl udeTransformOrigin, 195 style.applyTransform(matrix, toLayoutBox(object).size(), ComputedStyle::Excl udeTransformOrigin,
192 ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentTrans formProperties); 196 ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentTrans formProperties);
193 RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = TransformP aintPropertyNode::create( 197 RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = TransformP aintPropertyNode::create(
194 matrix, transformOrigin(toLayoutBox(object)), context.currentTransform); 198 matrix, transformOrigin(toLayoutBox(object)), context.currentTransform);
195 context.currentTransform = newTransformNodeForTransform.get(); 199 context.currentTransform = newTransformNodeForTransform.get();
196 return newTransformNodeForTransform.release(); 200 return newTransformNodeForTransform.release();
197 } 201 }
198 202
199 static PassRefPtr<EffectPaintPropertyNode> createEffectIfNeeded(const LayoutObje ct& object, PaintPropertyTreeBuilderContext& context) 203 static PassRefPtr<EffectPaintPropertyNode> createEffectIfNeeded(const LayoutObje ct& object, PrePaintTreeWalkContext& context)
200 { 204 {
201 const ComputedStyle& style = object.styleRef(); 205 const ComputedStyle& style = object.styleRef();
202 if (!style.hasOpacity()) 206 if (!style.hasOpacity())
203 return nullptr; 207 return nullptr;
204 RefPtr<EffectPaintPropertyNode> newEffectNode = EffectPaintPropertyNode::cre ate(style.opacity(), context.currentEffect); 208 RefPtr<EffectPaintPropertyNode> newEffectNode = EffectPaintPropertyNode::cre ate(style.opacity(), context.currentEffect);
205 context.currentEffect = newEffectNode.get(); 209 context.currentEffect = newEffectNode.get();
206 return newEffectNode.release(); 210 return newEffectNode.release();
207 } 211 }
208 212
209 static PassRefPtr<ClipPaintPropertyNode> createOverflowClipIfNeeded(const Layout Object& object, PaintPropertyTreeBuilderContext& context) 213 static PassRefPtr<ClipPaintPropertyNode> createOverflowClipIfNeeded(const Layout Object& object, PrePaintTreeWalkContext& context)
210 { 214 {
211 if (!object.isBox()) 215 if (!object.isBox())
212 return nullptr; 216 return nullptr;
213 const LayoutBox& box = toLayoutBox(object); 217 const LayoutBox& box = toLayoutBox(object);
214 218
215 // The <input> elements can't have contents thus CSS overflow property doesn 't apply. 219 // The <input> elements can't have contents thus CSS overflow property doesn 't apply.
216 // However for layout purposes we do generate child layout objects for them, e.g. button label. 220 // However for layout purposes we do generate child layout objects for them, e.g. button label.
217 // We should clip the overflow from those children. This is called control c lip and we 221 // We should clip the overflow from those children. This is called control c lip and we
218 // technically treat them like overflow clip. 222 // technically treat them like overflow clip.
219 LayoutRect clipRect; 223 LayoutRect clipRect;
220 if (box.hasControlClip()) 224 if (box.hasControlClip())
221 clipRect = box.controlClipRect(context.paintOffset); 225 clipRect = box.controlClipRect(context.paintOffset);
222 else if (box.hasOverflowClip()) 226 else if (box.hasOverflowClip())
223 clipRect = box.overflowClipRect(context.paintOffset); 227 clipRect = box.overflowClipRect(context.paintOffset);
224 else 228 else
225 return nullptr; 229 return nullptr;
226 230
227 RefPtr<ClipPaintPropertyNode> newClipNodeForBorderRadiusClip; 231 RefPtr<ClipPaintPropertyNode> newClipNodeForBorderRadiusClip;
228 const ComputedStyle& style = box.styleRef(); 232 const ComputedStyle& style = box.styleRef();
229 if (style.hasBorderRadius()) { 233 if (style.hasBorderRadius()) {
230 newClipNodeForBorderRadiusClip = ClipPaintPropertyNode::create( 234 newClipNodeForBorderRadiusClip = ClipPaintPropertyNode::create(
231 context.currentTransform, 235 context.currentTransform,
232 style.getRoundedInnerBorderFor(LayoutRect(context.paintOffset, box.s ize())), 236 style.getRoundedInnerBorderFor(LayoutRect(context.paintOffset, box.s ize())),
233 context.currentClip); 237 context.currentClip);
234 } 238 }
235 239
236 RefPtr<ClipPaintPropertyNode> newClipNodeForOverflowClip = ClipPaintProperty Node::create( 240 RefPtr<ClipPaintPropertyNode> newClipNodeForOverflowClip = ClipPaintProperty Node::create(
237 context.currentTransform, 241 context.currentTransform,
238 FloatRoundedRect(FloatRect(clipRect)), 242 FloatRoundedRect(FloatRect(clipRect)),
239 newClipNodeForBorderRadiusClip ? newClipNodeForBorderRadiusClip.release( ) : context.currentClip); 243 newClipNodeForBorderRadiusClip ? newClipNodeForBorderRadiusClip.release( ) : PassRefPtr<ClipPaintPropertyNode>(context.currentClip));
240 context.currentClip = newClipNodeForOverflowClip.get(); 244 context.currentClip = newClipNodeForOverflowClip.get();
241 return newClipNodeForOverflowClip.release(); 245 return newClipNodeForOverflowClip.release();
242 } 246 }
243 247
244 static FloatPoint perspectiveOrigin(const LayoutBox& box) 248 static FloatPoint perspectiveOrigin(const LayoutBox& box)
245 { 249 {
246 const ComputedStyle& style = box.styleRef(); 250 const ComputedStyle& style = box.styleRef();
247 FloatSize borderBoxSize(box.size()); 251 FloatSize borderBoxSize(box.size());
248 return FloatPoint( 252 return FloatPoint(
249 floatValueForLength(style.perspectiveOriginX(), borderBoxSize.width()), 253 floatValueForLength(style.perspectiveOriginX(), borderBoxSize.width()),
250 floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height())) ; 254 floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height())) ;
251 } 255 }
252 256
253 static PassRefPtr<TransformPaintPropertyNode> createPerspectiveIfNeeded(const La youtObject& object, PaintPropertyTreeBuilderContext& context) 257 static PassRefPtr<TransformPaintPropertyNode> createPerspectiveIfNeeded(const La youtObject& object, PrePaintTreeWalkContext& context)
254 { 258 {
255 const ComputedStyle& style = object.styleRef(); 259 const ComputedStyle& style = object.styleRef();
256 if (!object.isBox() || !style.hasPerspective()) 260 if (!object.isBox() || !style.hasPerspective())
257 return nullptr; 261 return nullptr;
258 262
259 RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = Transfor mPaintPropertyNode::create( 263 RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = Transfor mPaintPropertyNode::create(
260 TransformationMatrix().applyPerspective(style.perspective()), 264 TransformationMatrix().applyPerspective(style.perspective()),
261 perspectiveOrigin(toLayoutBox(object)) + toLayoutSize(context.paintOffse t), context.currentTransform); 265 perspectiveOrigin(toLayoutBox(object)) + toLayoutSize(context.paintOffse t), context.currentTransform);
262 context.currentTransform = newTransformNodeForPerspective.get(); 266 context.currentTransform = newTransformNodeForPerspective.get();
263 return newTransformNodeForPerspective.release(); 267 return newTransformNodeForPerspective.release();
264 } 268 }
265 269
266 static PassRefPtr<TransformPaintPropertyNode> createScrollTranslationIfNeeded(co nst LayoutObject& object, PaintPropertyTreeBuilderContext& context) 270 static PassRefPtr<TransformPaintPropertyNode> createScrollTranslationIfNeeded(co nst LayoutObject& object, PrePaintTreeWalkContext& context)
267 { 271 {
268 if (!object.isBoxModelObject() || !object.hasOverflowClip()) 272 if (!object.isBoxModelObject() || !object.hasOverflowClip())
269 return nullptr; 273 return nullptr;
270 274
271 PaintLayer* layer = toLayoutBoxModelObject(object).layer(); 275 PaintLayer* layer = toLayoutBoxModelObject(object).layer();
272 ASSERT(layer); 276 ASSERT(layer);
273 DoubleSize scrollOffset = layer->getScrollableArea()->scrollOffset(); 277 DoubleSize scrollOffset = layer->getScrollableArea()->scrollOffset();
274 if (scrollOffset.isZero() && !layer->scrollsOverflow()) 278 if (scrollOffset.isZero() && !layer->scrollsOverflow())
275 return nullptr; 279 return nullptr;
276 280
277 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = Tr ansformPaintPropertyNode::create( 281 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = Tr ansformPaintPropertyNode::create(
278 TransformationMatrix().translate(-scrollOffset.width(), -scrollOffset.he ight()), 282 TransformationMatrix().translate(-scrollOffset.width(), -scrollOffset.he ight()),
279 FloatPoint3D(), context.currentTransform); 283 FloatPoint3D(), context.currentTransform);
280 context.currentTransform = newTransformNodeForScrollTranslation.get(); 284 context.currentTransform = newTransformNodeForScrollTranslation.get();
281 return newTransformNodeForScrollTranslation.release(); 285 return newTransformNodeForScrollTranslation.release();
282 } 286 }
283 287
284 static void updateOutOfFlowContext(const LayoutObject& object, PaintPropertyTree BuilderContext& context) 288 static void updateOutOfFlowContext(const LayoutObject& object, PrePaintTreeWalkC ontext& context)
285 { 289 {
286 // At the html->svg boundary (see: createPaintOffsetTranslationIfNeeded) the currentTransform is 290 // At the html->svg boundary (see: createPaintOffsetTranslationIfNeeded) the currentTransform is
287 // up-to-date for all children of the svg root element. Additionally, inside SVG, all positioning 291 // up-to-date for all children of the svg root element. Additionally, inside SVG, all positioning
288 // uses transforms. Therefore, we only need to check createdNewTransform and isSVGRoot() to 292 // uses transforms. Therefore, we only need to check createdNewTransform and isSVGRoot() to
289 // ensure out-of-flow and fixed positioning is correct at the svg->html boun dary. 293 // ensure out-of-flow and fixed positioning is correct at the svg->html boun dary.
290 294
291 if (object.canContainAbsolutePositionObjects()) { 295 if (object.canContainAbsolutePositionObjects()) {
292 context.transformForAbsolutePosition = context.currentTransform; 296 context.transformForAbsolutePosition = context.currentTransform;
293 context.paintOffsetForAbsolutePosition = context.paintOffset; 297 context.paintOffsetForAbsolutePosition = context.paintOffset;
294 context.clipForAbsolutePosition = context.currentClip; 298 context.clipForAbsolutePosition = context.currentClip;
295 } 299 }
296 300
297 // TODO(pdr): Remove the !object.isLayoutView() condition when removing Fram eView 301 // TODO(pdr): Remove the !object.isLayoutView() condition when removing Fram eView
298 // paint properties for rootLayerScrolls. 302 // paint properties for rootLayerScrolls.
299 if (!object.isLayoutView() && object.canContainFixedPositionObjects()) { 303 if (!object.isLayoutView() && object.canContainFixedPositionObjects()) {
300 context.transformForFixedPosition = context.currentTransform; 304 context.transformForFixedPosition = context.currentTransform;
301 context.paintOffsetForFixedPosition = context.paintOffset; 305 context.paintOffsetForFixedPosition = context.paintOffset;
302 context.clipForFixedPosition = context.currentClip; 306 context.clipForFixedPosition = context.currentClip;
303 } 307 }
304 } 308 }
305 309
306 static PassOwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> recordTreeCon textIfNeeded(LayoutObject& object, const PaintPropertyTreeBuilderContext& contex t) 310 static PassOwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> recordTreeCon textIfNeeded(const LayoutObject& object, const PrePaintTreeWalkContext& context)
307 { 311 {
308 // Note: Currently only layer painter makes use of the pre-computed context. 312 // Note: Currently only layer painter makes use of the pre-computed context.
309 // This condition may be loosened with no adverse effects beside memory use. 313 // This condition may be loosened with no adverse effects beside memory use.
310 if (!object.hasLayer()) 314 if (!object.hasLayer())
311 return nullptr; 315 return nullptr;
312 316
313 OwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> recordedContext = ad optPtr(new ObjectPaintProperties::LocalBorderBoxProperties); 317 OwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> recordedContext = ad optPtr(new ObjectPaintProperties::LocalBorderBoxProperties);
314 recordedContext->paintOffset = context.paintOffset; 318 recordedContext->paintOffset = context.paintOffset;
315 recordedContext->transform = context.currentTransform; 319 recordedContext->transform = context.currentTransform;
316 recordedContext->clip = context.currentClip; 320 recordedContext->clip = context.currentClip;
317 recordedContext->effect = context.currentEffect; 321 recordedContext->effect = context.currentEffect;
318 return recordedContext.release(); 322 return recordedContext.release();
319 } 323 }
320 324
321 void PaintPropertyTreeBuilder::walk(LayoutObject& object, const PaintPropertyTre eBuilderContext& context) 325 static void updatePaintInvalidationContainer(const LayoutObject& object, PrePain tTreeWalkContext& context)
322 { 326 {
323 PaintPropertyTreeBuilderContext localContext(context); 327 // Paint invalidation container is a SPv1-only concept.
328 ASSERT(!RuntimeEnabledFeatures::slimmingPaintV2Enabled());
324 329
325 deriveBorderBoxFromContainerContext(object, localContext); 330 if (!object.isPaintInvalidationContainer()) {
trchen 2016/03/11 23:36:19 This doesn't look right. I think it should be if
326 RefPtr<TransformPaintPropertyNode> newTransformNodeForPaintOffsetTranslation = createPaintOffsetTranslationIfNeeded(object, localContext); 331 if (context.paintInvalidationContainer)
327 RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = createTran sformIfNeeded(object, localContext); 332 return;
328 RefPtr<EffectPaintPropertyNode> newEffectNode = createEffectIfNeeded(object, localContext); 333 ASSERT(object.isLayoutView());
329 OwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> newRecordedContext = recordTreeContextIfNeeded(object, localContext);
330 RefPtr<ClipPaintPropertyNode> newClipNodeForOverflowClip = createOverflowCli pIfNeeded(object, localContext);
331 // TODO(trchen): Insert flattening transform here, as specified by
332 // http://www.w3.org/TR/css3-transforms/#transform-style-property
333 RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = createPe rspectiveIfNeeded(object, localContext);
334 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = cr eateScrollTranslationIfNeeded(object, localContext);
335 updateOutOfFlowContext(object, localContext);
336
337 if (newTransformNodeForPaintOffsetTranslation || newTransformNodeForTransfor m || newEffectNode || newClipNodeForOverflowClip || newTransformNodeForPerspecti ve || newTransformNodeForScrollTranslation || newRecordedContext) {
338 OwnPtr<ObjectPaintProperties> updatedPaintProperties = ObjectPaintProper ties::create(
339 newTransformNodeForPaintOffsetTranslation.release(),
340 newTransformNodeForTransform.release(),
341 newEffectNode.release(),
342 newClipNodeForOverflowClip.release(),
343 newTransformNodeForPerspective.release(),
344 newTransformNodeForScrollTranslation.release(),
345 newRecordedContext.release());
346 object.setObjectPaintProperties(updatedPaintProperties.release());
347 } else {
348 object.clearObjectPaintProperties();
349 } 334 }
350 335
351 for (LayoutObject* child = object.slowFirstChild(); child; child = child->ne xtSibling()) { 336 context.currentTransform = nullptr;
352 if (child->isBoxModelObject() || child->isSVG()) 337 context.paintOffset = LayoutPoint();
353 walk(*child, localContext); 338 context.currentClip = nullptr;
339 context.paintInvalidationContainer = &toLayoutBoxModelObject(object);
340
341 // A composited stacking context establishes new paint invalidation containe r for
342 // out-of-flow-positioned descendants.
343 if (object.styleRef().isStackingContext() || !context.paintInvalidationConta inerForOutOfFlowPositioned) {
344 // TODO(wangxianzhu): The following may be incorrect for some complex ca ses. Investigate if we could
345 // make it correct for all cases or have to use ForceHorriblySlowRectMap ping.
trchen 2016/03/11 23:36:19 As pdr@ already pointed out, I don't think it make
346 context.transformForAbsolutePosition = nullptr;
347 context.paintOffsetForAbsolutePosition = LayoutPoint();
348 context.clipForAbsolutePosition = nullptr;
349 context.transformForFixedPosition = nullptr;
350 context.paintOffsetForFixedPosition = LayoutPoint();
351 context.clipForFixedPosition = nullptr;
352 context.paintInvalidationContainerForOutOfFlowPositioned = &toLayoutBoxM odelObject(object);
353 }
354 }
355
356 void PrePaintTreeWalk::walk(const LayoutObject& object, const PrePaintTreeWalkCo ntext& context, const PaintInvalidationState* parentPaintInvalidationState)
357 {
358 PrePaintTreeWalkContext localContext(context);
359 adjustContainerContextForPosition(object, localContext);
360
361 Optional<PaintInvalidationState> paintInvalidationState;
362 if (RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled()) {
363 if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled())
364 updatePaintInvalidationContainer(object, localContext);
365 paintInvalidationState.emplace(parentPaintInvalidationState, object, *lo calContext.paintInvalidationContainer, localContext.paintOffset);
366 if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled() && !object.shouldC heckForPaintInvalidation(*paintInvalidationState))
367 return;
trchen 2016/03/11 23:36:19 The early return check is too late, and the semant
368
369 PaintInvalidationReason reason = object.getMutableForPainting().invalida tePaintIfNeeded(*paintInvalidationState, *localContext.paintInvalidationContaine r);
370 object.getMutableForPainting().clearPaintInvalidationState(*paintInvalid ationState);
371 if (reason == PaintInvalidationDelayedFull)
372 m_pendingDelayedPaintInvalidations.append(const_cast<LayoutObject*>( &object));
373 }
374
375 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() || !object.isPaintInval idationContainer()) {
376 deriveBorderBoxFromContainerContext(object, localContext);
377 RefPtr<TransformPaintPropertyNode> newTransformNodeForPaintOffsetTransla tion = createPaintOffsetTranslationIfNeeded(object, localContext);
378 RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = create TransformIfNeeded(object, localContext);
379 RefPtr<EffectPaintPropertyNode> newEffectNode = createEffectIfNeeded(obj ect, localContext);
380 OwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> newRecordedConte xt = recordTreeContextIfNeeded(object, localContext);
381 RefPtr<ClipPaintPropertyNode> newClipNodeForOverflowClip = createOverflo wClipIfNeeded(object, localContext);
382 // TODO(trchen): Insert flattening transform here, as specified by
383 // http://www.w3.org/TR/css3-transforms/#transform-style-property
384 RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = crea tePerspectiveIfNeeded(object, localContext);
385 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = createScrollTranslationIfNeeded(object, localContext);
386 updateOutOfFlowContext(object, localContext);
387
388 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
389 if (newTransformNodeForPaintOffsetTranslation || newTransformNodeFor Transform || newEffectNode || newClipNodeForOverflowClip || newTransformNodeForP erspective || newTransformNodeForScrollTranslation || newRecordedContext) {
390 OwnPtr<ObjectPaintProperties> updatedPaintProperties = ObjectPai ntProperties::create(
391 newTransformNodeForPaintOffsetTranslation.release(),
392 newTransformNodeForTransform.release(),
393 newEffectNode.release(),
394 newClipNodeForOverflowClip.release(),
395 newTransformNodeForPerspective.release(),
396 newTransformNodeForScrollTranslation.release(),
397 newRecordedContext.release());
398 object.getMutableForPainting().setObjectPaintProperties(updatedP aintProperties.release());
399 } else {
400 object.getMutableForPainting().clearObjectPaintProperties();
401 }
402 }
403 }
404
405 for (const LayoutObject* child = object.slowFirstChild(); child; child = chi ld->nextSibling()) {
406 if (child->isBoxModelObject() || child->isSVG()) {
407 walk(*child, localContext, paintInvalidationState.get());
408 } else if (RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled() && child->shouldCheckForPaintInvalidation(*paintInvalidationState)) {
409 child->getMutableForPainting().invalidatePaintIfNeeded(*paintInvalid ationState, *localContext.paintInvalidationContainer);
410 child->getMutableForPainting().clearPaintInvalidationState(*paintInv alidationState);
411 }
354 } 412 }
355 413
356 if (object.isLayoutPart()) { 414 if (object.isLayoutPart()) {
357 Widget* widget = toLayoutPart(object).widget(); 415 Widget* widget = toLayoutPart(object).widget();
358 if (widget && widget->isFrameView()) 416 if (widget && widget->isFrameView())
359 walk(*toFrameView(widget), localContext); 417 walk(*toFrameView(widget), localContext, paintInvalidationState.get( ));
360 // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281). 418 // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281).
361 } 419 }
362 } 420 }
363 421
364 } // namespace blink 422 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/paint/PrePaintTreeWalk.h ('k') | third_party/WebKit/Source/core/paint/PrePaintTreeWalkTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698