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

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

Issue 2695593005: Avoid false-positives of paint offset change detection (Closed)
Patch Set: Created 3 years, 10 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/PaintPropertyTreeBuilder.h"
6 6
7 #include "core/dom/DOMNodeIds.h" 7 #include "core/dom/DOMNodeIds.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"
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 context.fixedPosition = context.current; 209 context.fixedPosition = context.current;
210 context.fixedPosition.transform = fixedTransformNode; 210 context.fixedPosition.transform = fixedTransformNode;
211 context.fixedPosition.scroll = fixedScrollNode; 211 context.fixedPosition.scroll = fixedScrollNode;
212 212
213 std::unique_ptr<PropertyTreeState> contentsState(new PropertyTreeState( 213 std::unique_ptr<PropertyTreeState> contentsState(new PropertyTreeState(
214 context.current.transform, context.current.clip, context.currentEffect)); 214 context.current.transform, context.current.clip, context.currentEffect));
215 frameView.setTotalPropertyTreeStateForContents(std::move(contentsState)); 215 frameView.setTotalPropertyTreeStateForContents(std::move(contentsState));
216 } 216 }
217 217
218 void PaintPropertyTreeBuilder::updatePaintOffsetTranslation( 218 void PaintPropertyTreeBuilder::updatePaintOffsetTranslation(
219 const LayoutObject& object, 219 const LayoutBoxModelObject& object,
220 PaintPropertyTreeBuilderContext& context) { 220 PaintPropertyTreeBuilderContext& context) {
221 bool usesPaintOffsetTranslation = false; 221 bool usesPaintOffsetTranslation = false;
222 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled() && 222 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled() &&
223 object.isLayoutView()) { 223 object.isLayoutView()) {
224 // Root layer scrolling always creates a translation node for LayoutView to 224 // Root layer scrolling always creates a translation node for LayoutView to
225 // ensure fixed and absolute contexts use the correct transform space. 225 // ensure fixed and absolute contexts use the correct transform space.
226 usesPaintOffsetTranslation = true; 226 usesPaintOffsetTranslation = true;
227 } else if (object.isBoxModelObject() && 227 } else if (object.hasLayer() &&
228 context.current.paintOffset != LayoutPoint()) { 228 context.current.paintOffset != LayoutPoint() &&
229 PaintLayer* layer = toLayoutBoxModelObject(object).layer(); 229 object.layer()->paintsWithTransform(
230 if (layer && 230 GlobalPaintFlattenCompositingLayers)) {
231 layer->paintsWithTransform(GlobalPaintFlattenCompositingLayers)) 231 usesPaintOffsetTranslation = true;
232 usesPaintOffsetTranslation = true;
233 } 232 }
234 233
235 // We should use the same subpixel paint offset values for snapping 234 // We should use the same subpixel paint offset values for snapping
236 // regardless of whether a transform is present. If there is a transform 235 // regardless of whether a transform is present. If there is a transform
237 // we round the paint offset but keep around the residual fractional 236 // we round the paint offset but keep around the residual fractional
238 // component for the transformed content to paint with. In spv1 this was 237 // component for the transformed content to paint with. In spv1 this was
239 // called "subpixel accumulation". For more information, see 238 // called "subpixel accumulation". For more information, see
240 // PaintLayer::subpixelAccumulation() and 239 // PaintLayer::subpixelAccumulation() and
241 // PaintLayerPainter::paintFragmentByApplyingTransform. 240 // PaintLayerPainter::paintFragmentByApplyingTransform.
242 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset); 241 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset);
243 LayoutPoint fractionalPaintOffset = 242 LayoutPoint fractionalPaintOffset =
244 LayoutPoint(context.current.paintOffset - roundedPaintOffset); 243 LayoutPoint(context.current.paintOffset - roundedPaintOffset);
245 244
246 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) { 245 if (usesPaintOffsetTranslation) {
pdr. 2017/02/14 05:18:41 Do we need to still early-out here if !(object.nee
Xianzhu 2017/02/14 19:23:34 No, because paint offset can change without needsP
247 if (usesPaintOffsetTranslation) { 246 auto& properties = object.getMutableForPainting().ensurePaintProperties();
248 auto& properties = object.getMutableForPainting().ensurePaintProperties(); 247 context.forceSubtreeUpdate |= properties.updatePaintOffsetTranslation(
249 context.forceSubtreeUpdate |= properties.updatePaintOffsetTranslation( 248 context.current.transform,
250 context.current.transform, 249 TransformationMatrix().translate(roundedPaintOffset.x(),
251 TransformationMatrix().translate(roundedPaintOffset.x(), 250 roundedPaintOffset.y()),
252 roundedPaintOffset.y()), 251 FloatPoint3D(), context.current.shouldFlattenInheritedTransform,
253 FloatPoint3D(), context.current.shouldFlattenInheritedTransform, 252 context.current.renderingContextId);
254 context.current.renderingContextId); 253 } else {
255 } else { 254 if (auto* properties = object.getMutableForPainting().paintProperties())
256 if (auto* properties = object.getMutableForPainting().paintProperties()) 255 context.forceSubtreeUpdate |= properties->clearPaintOffsetTranslation();
257 context.forceSubtreeUpdate |= properties->clearPaintOffsetTranslation();
258 }
259 } 256 }
260 257
261 const auto* properties = object.paintProperties(); 258 const auto* properties = object.paintProperties();
262 if (properties && properties->paintOffsetTranslation()) { 259 if (properties && properties->paintOffsetTranslation()) {
263 context.current.transform = properties->paintOffsetTranslation(); 260 context.current.transform = properties->paintOffsetTranslation();
264 context.current.paintOffset = fractionalPaintOffset; 261 context.current.paintOffset = fractionalPaintOffset;
265 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled() && 262 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled() &&
266 object.isLayoutView()) { 263 object.isLayoutView()) {
267 context.absolutePosition.transform = properties->paintOffsetTranslation(); 264 context.absolutePosition.transform = properties->paintOffsetTranslation();
268 context.fixedPosition.transform = properties->paintOffsetTranslation(); 265 context.fixedPosition.transform = properties->paintOffsetTranslation();
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after
856 return; 853 return;
857 } 854 }
858 } 855 }
859 856
860 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) { 857 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
861 if (auto* properties = object.getMutableForPainting().paintProperties()) 858 if (auto* properties = object.getMutableForPainting().paintProperties())
862 context.forceSubtreeUpdate |= properties->clearCssClipFixedPosition(); 859 context.forceSubtreeUpdate |= properties->clearCssClipFixedPosition();
863 } 860 }
864 } 861 }
865 862
866 void PaintPropertyTreeBuilder::updateContextForBoxPosition( 863 void PaintPropertyTreeBuilder::updatePaintOffset(
867 const LayoutObject& object, 864 const LayoutBoxModelObject& object,
868 PaintPropertyTreeBuilderContext& context) { 865 PaintPropertyTreeBuilderContext& context) {
869 if (!object.isBoxModelObject()) 866 if (object.isFloating())
870 return;
871
872 const LayoutBoxModelObject& boxModelObject = toLayoutBoxModelObject(object);
873
874 if (boxModelObject.isFloating())
875 context.current.paintOffset = context.paintOffsetForFloat; 867 context.current.paintOffset = context.paintOffsetForFloat;
876 868
877 // Multicolumn spanners are painted starting at the multicolumn container (but 869 // Multicolumn spanners are painted starting at the multicolumn container (but
878 // still inherit properties in layout-tree order) so reset the paint offset. 870 // still inherit properties in layout-tree order) so reset the paint offset.
879 if (boxModelObject.isColumnSpanAll()) 871 if (object.isColumnSpanAll())
880 context.current.paintOffset = boxModelObject.container()->paintOffset(); 872 context.current.paintOffset = object.container()->paintOffset();
881 873
882 switch (object.styleRef().position()) { 874 switch (object.styleRef().position()) {
883 case EPosition::kStatic: 875 case EPosition::kStatic:
884 break; 876 break;
885 case EPosition::kRelative: 877 case EPosition::kRelative:
886 context.current.paintOffset += boxModelObject.offsetForInFlowPosition(); 878 context.current.paintOffset += object.offsetForInFlowPosition();
887 break; 879 break;
888 case EPosition::kAbsolute: { 880 case EPosition::kAbsolute: {
889 DCHECK(context.containerForAbsolutePosition == 881 DCHECK(context.containerForAbsolutePosition == object.container());
890 boxModelObject.container());
891 context.current = context.absolutePosition; 882 context.current = context.absolutePosition;
892 883
893 // Absolutely positioned content in an inline should be positioned 884 // Absolutely positioned content in an inline should be positioned
894 // relative to the inline. 885 // relative to the inline.
895 const LayoutObject* container = context.containerForAbsolutePosition; 886 const LayoutObject* container = context.containerForAbsolutePosition;
896 if (container && container->isInFlowPositioned() && 887 if (container && container->isInFlowPositioned() &&
897 container->isLayoutInline()) { 888 container->isLayoutInline()) {
898 DCHECK(object.isBox()); 889 DCHECK(object.isBox());
899 context.current.paintOffset += 890 context.current.paintOffset +=
900 toLayoutInline(container)->offsetForInFlowPositionedInline( 891 toLayoutInline(container)->offsetForInFlowPositionedInline(
901 toLayoutBox(object)); 892 toLayoutBox(object));
902 } 893 }
903 break; 894 break;
904 } 895 }
905 case EPosition::kSticky: 896 case EPosition::kSticky:
906 context.current.paintOffset += boxModelObject.offsetForInFlowPosition(); 897 context.current.paintOffset += object.offsetForInFlowPosition();
907 break; 898 break;
908 case EPosition::kFixed: 899 case EPosition::kFixed:
909 context.current = context.fixedPosition; 900 context.current = context.fixedPosition;
910 break; 901 break;
911 default: 902 default:
912 ASSERT_NOT_REACHED(); 903 ASSERT_NOT_REACHED();
913 } 904 }
914 905
915 if (boxModelObject.isBox()) { 906 if (object.isBox()) {
916 // TODO(pdr): Several calls in this function walk back up the tree to 907 // TODO(pdr): Several calls in this function walk back up the tree to
917 // calculate containers (e.g., physicalLocation, offsetForInFlowPosition*). 908 // calculate containers (e.g., physicalLocation, offsetForInFlowPosition*).
918 // The containing block and other containers can be stored on 909 // The containing block and other containers can be stored on
919 // PaintPropertyTreeBuilderContext instead of recomputing them. 910 // PaintPropertyTreeBuilderContext instead of recomputing them.
920 context.current.paintOffset.moveBy( 911 context.current.paintOffset.moveBy(toLayoutBox(object).physicalLocation());
921 toLayoutBox(boxModelObject).physicalLocation());
922 // This is a weird quirk that table cells paint as children of table rows, 912 // This is a weird quirk that table cells paint as children of table rows,
923 // but their location have the row's location baked-in. 913 // but their location have the row's location baked-in.
924 // Similar adjustment is done in LayoutTableCell::offsetFromContainer(). 914 // Similar adjustment is done in LayoutTableCell::offsetFromContainer().
925 if (boxModelObject.isTableCell()) { 915 if (object.isTableCell()) {
926 LayoutObject* parentRow = boxModelObject.parent(); 916 LayoutObject* parentRow = object.parent();
927 DCHECK(parentRow && parentRow->isTableRow()); 917 DCHECK(parentRow && parentRow->isTableRow());
928 context.current.paintOffset.moveBy( 918 context.current.paintOffset.moveBy(
929 -toLayoutBox(parentRow)->physicalLocation()); 919 -toLayoutBox(parentRow)->physicalLocation());
930 } 920 }
931 } 921 }
922 }
923
924 void PaintPropertyTreeBuilder::updateContextForBoxPosition(
925 const LayoutObject& object,
926 PaintPropertyTreeBuilderContext& context) {
927 if (!object.isBoxModelObject()) {
928 object.getMutableForPainting().setPaintOffset(context.current.paintOffset);
929 return;
930 }
931
932 updatePaintOffset(toLayoutBoxModelObject(object), context);
933 updatePaintOffsetTranslation(toLayoutBoxModelObject(object), context);
934
935 if (object.paintOffset() == context.current.paintOffset)
936 return;
932 937
933 // Many paint properties depend on paint offset so we force an update of 938 // Many paint properties depend on paint offset so we force an update of
934 // the entire subtree on paint offset changes. 939 // the entire subtree on paint offset changes.
935 if (object.paintOffset() != context.current.paintOffset) 940 context.forceSubtreeUpdate = true;
936 context.forceSubtreeUpdate = true; 941
942 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
943 object.getMutableForPainting().setShouldDoFullPaintInvalidation(
944 PaintInvalidationLocationChange);
945 }
946 object.getMutableForPainting().setPaintOffset(context.current.paintOffset);
937 } 947 }
938 948
939 void PaintPropertyTreeBuilder::updatePropertiesForSelf( 949 void PaintPropertyTreeBuilder::updatePropertiesForSelf(
940 const LayoutObject& object, 950 const LayoutObject& object,
941 PaintPropertyTreeBuilderContext& context) { 951 PaintPropertyTreeBuilderContext& context) {
942 #if DCHECK_IS_ON() 952 #if DCHECK_IS_ON()
943 FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object, context); 953 FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object, context);
944 #endif 954 #endif
945 955
946 if (object.isBoxModelObject() || object.isSVG()) { 956 if (object.isBoxModelObject() || object.isSVG()) {
947 updatePaintOffsetTranslation(object, context);
948 updateTransform(object, context); 957 updateTransform(object, context);
949 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) 958 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
950 updateEffect(object, context); 959 updateEffect(object, context);
951 updateCssClip(object, context); 960 updateCssClip(object, context);
952 updateLocalBorderBoxContext(object, context); 961 updateLocalBorderBoxContext(object, context);
953 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) 962 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
954 updateScrollbarPaintOffset(object, context); 963 updateScrollbarPaintOffset(object, context);
955 } 964 }
956
957 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
958 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() &&
959 object.paintOffset() != context.current.paintOffset) {
960 object.getMutableForPainting().setShouldDoFullPaintInvalidation(
961 PaintInvalidationLocationChange);
962 }
963 object.getMutableForPainting().setPaintOffset(context.current.paintOffset);
964 }
965 } 965 }
966 966
967 void PaintPropertyTreeBuilder::updatePropertiesForChildren( 967 void PaintPropertyTreeBuilder::updatePropertiesForChildren(
968 const LayoutObject& object, 968 const LayoutObject& object,
969 PaintPropertyTreeBuilderContext& context) { 969 PaintPropertyTreeBuilderContext& context) {
970 #if DCHECK_IS_ON() 970 #if DCHECK_IS_ON()
971 FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object, context); 971 FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object, context);
972 #endif 972 #endif
973 973
974 if (!object.isBoxModelObject() && !object.isSVG()) 974 if (!object.isBoxModelObject() && !object.isSVG())
975 return; 975 return;
976 976
977 updateOverflowClip(object, context); 977 updateOverflowClip(object, context);
978 updatePerspective(object, context); 978 updatePerspective(object, context);
979 updateSvgLocalToBorderBoxTransform(object, context); 979 updateSvgLocalToBorderBoxTransform(object, context);
980 updateScrollAndScrollTranslation(object, context); 980 updateScrollAndScrollTranslation(object, context);
981 updateOutOfFlowContext(object, context); 981 updateOutOfFlowContext(object, context);
982 982
983 context.forceSubtreeUpdate |= object.subtreeNeedsPaintPropertyUpdate(); 983 context.forceSubtreeUpdate |= object.subtreeNeedsPaintPropertyUpdate();
984 } 984 }
985 985
986 } // namespace blink 986 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698