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

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
« no previous file with comments | « third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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; 232 }
233
234 if (!usesPaintOffsetTranslation) {
235 if (auto* properties = object.getMutableForPainting().paintProperties())
236 context.forceSubtreeUpdate |= properties->clearPaintOffsetTranslation();
237 return;
233 } 238 }
234 239
235 // We should use the same subpixel paint offset values for snapping 240 // We should use the same subpixel paint offset values for snapping
236 // regardless of whether a transform is present. If there is a transform 241 // regardless of whether a transform is present. If there is a transform
237 // we round the paint offset but keep around the residual fractional 242 // we round the paint offset but keep around the residual fractional
238 // component for the transformed content to paint with. In spv1 this was 243 // component for the transformed content to paint with. In spv1 this was
239 // called "subpixel accumulation". For more information, see 244 // called "subpixel accumulation". For more information, see
240 // PaintLayer::subpixelAccumulation() and 245 // PaintLayer::subpixelAccumulation() and
241 // PaintLayerPainter::paintFragmentByApplyingTransform. 246 // PaintLayerPainter::paintFragmentByApplyingTransform.
242 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset); 247 IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset);
243 LayoutPoint fractionalPaintOffset = 248 LayoutPoint fractionalPaintOffset =
244 LayoutPoint(context.current.paintOffset - roundedPaintOffset); 249 LayoutPoint(context.current.paintOffset - roundedPaintOffset);
245 250
246 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) { 251 auto& properties = object.getMutableForPainting().ensurePaintProperties();
247 if (usesPaintOffsetTranslation) { 252 context.forceSubtreeUpdate |= properties.updatePaintOffsetTranslation(
248 auto& properties = object.getMutableForPainting().ensurePaintProperties(); 253 context.current.transform,
249 context.forceSubtreeUpdate |= properties.updatePaintOffsetTranslation( 254 TransformationMatrix().translate(roundedPaintOffset.x(),
250 context.current.transform, 255 roundedPaintOffset.y()),
251 TransformationMatrix().translate(roundedPaintOffset.x(), 256 FloatPoint3D(), context.current.shouldFlattenInheritedTransform,
252 roundedPaintOffset.y()), 257 context.current.renderingContextId);
253 FloatPoint3D(), context.current.shouldFlattenInheritedTransform,
254 context.current.renderingContextId);
255 } else {
256 if (auto* properties = object.getMutableForPainting().paintProperties())
257 context.forceSubtreeUpdate |= properties->clearPaintOffsetTranslation();
258 }
259 }
260 258
261 const auto* properties = object.paintProperties(); 259 context.current.transform = properties.paintOffsetTranslation();
262 if (properties && properties->paintOffsetTranslation()) { 260 context.current.paintOffset = fractionalPaintOffset;
263 context.current.transform = properties->paintOffsetTranslation(); 261 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled() &&
264 context.current.paintOffset = fractionalPaintOffset; 262 object.isLayoutView()) {
265 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled() && 263 context.absolutePosition.transform = properties.paintOffsetTranslation();
266 object.isLayoutView()) { 264 context.fixedPosition.transform = properties.paintOffsetTranslation();
267 context.absolutePosition.transform = properties->paintOffsetTranslation(); 265 context.absolutePosition.paintOffset = LayoutPoint();
268 context.fixedPosition.transform = properties->paintOffsetTranslation(); 266 context.fixedPosition.paintOffset = LayoutPoint();
269 context.absolutePosition.paintOffset = LayoutPoint();
270 context.fixedPosition.paintOffset = LayoutPoint();
271 }
272 } 267 }
273 } 268 }
274 269
275 // SVG does not use the general transform update of |updateTransform|, instead 270 // SVG does not use the general transform update of |updateTransform|, instead
276 // creating a transform node for SVG-specific transforms without 3D. 271 // creating a transform node for SVG-specific transforms without 3D.
277 void PaintPropertyTreeBuilder::updateTransformForNonRootSVG( 272 void PaintPropertyTreeBuilder::updateTransformForNonRootSVG(
278 const LayoutObject& object, 273 const LayoutObject& object,
279 PaintPropertyTreeBuilderContext& context) { 274 PaintPropertyTreeBuilderContext& context) {
280 DCHECK(object.isSVGChild()); 275 DCHECK(object.isSVGChild());
281 // SVG does not use paint offset internally, except for SVGForeignObject which 276 // SVG does not use paint offset internally, except for SVGForeignObject which
(...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after
856 return; 851 return;
857 } 852 }
858 } 853 }
859 854
860 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) { 855 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) {
861 if (auto* properties = object.getMutableForPainting().paintProperties()) 856 if (auto* properties = object.getMutableForPainting().paintProperties())
862 context.forceSubtreeUpdate |= properties->clearCssClipFixedPosition(); 857 context.forceSubtreeUpdate |= properties->clearCssClipFixedPosition();
863 } 858 }
864 } 859 }
865 860
866 void PaintPropertyTreeBuilder::updateContextForBoxPosition( 861 void PaintPropertyTreeBuilder::updatePaintOffset(
867 const LayoutObject& object, 862 const LayoutBoxModelObject& object,
868 PaintPropertyTreeBuilderContext& context) { 863 PaintPropertyTreeBuilderContext& context) {
869 if (!object.isBoxModelObject()) 864 if (object.isFloating())
870 return;
871
872 const LayoutBoxModelObject& boxModelObject = toLayoutBoxModelObject(object);
873
874 if (boxModelObject.isFloating())
875 context.current.paintOffset = context.paintOffsetForFloat; 865 context.current.paintOffset = context.paintOffsetForFloat;
876 866
877 // Multicolumn spanners are painted starting at the multicolumn container (but 867 // Multicolumn spanners are painted starting at the multicolumn container (but
878 // still inherit properties in layout-tree order) so reset the paint offset. 868 // still inherit properties in layout-tree order) so reset the paint offset.
879 if (boxModelObject.isColumnSpanAll()) 869 if (object.isColumnSpanAll())
880 context.current.paintOffset = boxModelObject.container()->paintOffset(); 870 context.current.paintOffset = object.container()->paintOffset();
881 871
882 switch (object.styleRef().position()) { 872 switch (object.styleRef().position()) {
883 case EPosition::kStatic: 873 case EPosition::kStatic:
884 break; 874 break;
885 case EPosition::kRelative: 875 case EPosition::kRelative:
886 context.current.paintOffset += boxModelObject.offsetForInFlowPosition(); 876 context.current.paintOffset += object.offsetForInFlowPosition();
887 break; 877 break;
888 case EPosition::kAbsolute: { 878 case EPosition::kAbsolute: {
889 DCHECK(context.containerForAbsolutePosition == 879 DCHECK(context.containerForAbsolutePosition == object.container());
890 boxModelObject.container());
891 context.current = context.absolutePosition; 880 context.current = context.absolutePosition;
892 881
893 // Absolutely positioned content in an inline should be positioned 882 // Absolutely positioned content in an inline should be positioned
894 // relative to the inline. 883 // relative to the inline.
895 const LayoutObject* container = context.containerForAbsolutePosition; 884 const LayoutObject* container = context.containerForAbsolutePosition;
896 if (container && container->isInFlowPositioned() && 885 if (container && container->isInFlowPositioned() &&
897 container->isLayoutInline()) { 886 container->isLayoutInline()) {
898 DCHECK(object.isBox()); 887 DCHECK(object.isBox());
899 context.current.paintOffset += 888 context.current.paintOffset +=
900 toLayoutInline(container)->offsetForInFlowPositionedInline( 889 toLayoutInline(container)->offsetForInFlowPositionedInline(
901 toLayoutBox(object)); 890 toLayoutBox(object));
902 } 891 }
903 break; 892 break;
904 } 893 }
905 case EPosition::kSticky: 894 case EPosition::kSticky:
906 context.current.paintOffset += boxModelObject.offsetForInFlowPosition(); 895 context.current.paintOffset += object.offsetForInFlowPosition();
907 break; 896 break;
908 case EPosition::kFixed: 897 case EPosition::kFixed:
909 context.current = context.fixedPosition; 898 context.current = context.fixedPosition;
910 break; 899 break;
911 default: 900 default:
912 ASSERT_NOT_REACHED(); 901 ASSERT_NOT_REACHED();
913 } 902 }
914 903
915 if (boxModelObject.isBox()) { 904 if (object.isBox()) {
916 // TODO(pdr): Several calls in this function walk back up the tree to 905 // TODO(pdr): Several calls in this function walk back up the tree to
917 // calculate containers (e.g., physicalLocation, offsetForInFlowPosition*). 906 // calculate containers (e.g., physicalLocation, offsetForInFlowPosition*).
918 // The containing block and other containers can be stored on 907 // The containing block and other containers can be stored on
919 // PaintPropertyTreeBuilderContext instead of recomputing them. 908 // PaintPropertyTreeBuilderContext instead of recomputing them.
920 context.current.paintOffset.moveBy( 909 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, 910 // 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. 911 // but their location have the row's location baked-in.
924 // Similar adjustment is done in LayoutTableCell::offsetFromContainer(). 912 // Similar adjustment is done in LayoutTableCell::offsetFromContainer().
925 if (boxModelObject.isTableCell()) { 913 if (object.isTableCell()) {
926 LayoutObject* parentRow = boxModelObject.parent(); 914 LayoutObject* parentRow = object.parent();
927 DCHECK(parentRow && parentRow->isTableRow()); 915 DCHECK(parentRow && parentRow->isTableRow());
928 context.current.paintOffset.moveBy( 916 context.current.paintOffset.moveBy(
929 -toLayoutBox(parentRow)->physicalLocation()); 917 -toLayoutBox(parentRow)->physicalLocation());
930 } 918 }
931 } 919 }
920 }
921
922 void PaintPropertyTreeBuilder::updateContextForBoxPosition(
923 const LayoutObject& object,
924 PaintPropertyTreeBuilderContext& context) {
925 if (object.isBoxModelObject()) {
926 updatePaintOffset(toLayoutBoxModelObject(object), context);
927 updatePaintOffsetTranslation(toLayoutBoxModelObject(object), context);
928 }
929
930 if (object.paintOffset() == context.current.paintOffset)
931 return;
932 932
933 // Many paint properties depend on paint offset so we force an update of 933 // Many paint properties depend on paint offset so we force an update of
934 // the entire subtree on paint offset changes. 934 // the entire subtree on paint offset changes.
935 if (object.paintOffset() != context.current.paintOffset) 935 context.forceSubtreeUpdate = true;
936 context.forceSubtreeUpdate = true; 936
937 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
938 object.getMutableForPainting().setShouldDoFullPaintInvalidation(
939 PaintInvalidationLocationChange);
940 }
941 object.getMutableForPainting().setPaintOffset(context.current.paintOffset);
937 } 942 }
938 943
939 void PaintPropertyTreeBuilder::updatePropertiesForSelf( 944 void PaintPropertyTreeBuilder::updatePropertiesForSelf(
940 const LayoutObject& object, 945 const LayoutObject& object,
941 PaintPropertyTreeBuilderContext& context) { 946 PaintPropertyTreeBuilderContext& context) {
942 #if DCHECK_IS_ON() 947 #if DCHECK_IS_ON()
943 FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object, context); 948 FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object, context);
944 #endif 949 #endif
945 950
946 if (object.isBoxModelObject() || object.isSVG()) { 951 if (object.isBoxModelObject() || object.isSVG()) {
947 updatePaintOffsetTranslation(object, context);
948 updateTransform(object, context); 952 updateTransform(object, context);
949 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) 953 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
950 updateEffect(object, context); 954 updateEffect(object, context);
951 updateCssClip(object, context); 955 updateCssClip(object, context);
952 updateLocalBorderBoxContext(object, context); 956 updateLocalBorderBoxContext(object, context);
953 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) 957 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
954 updateScrollbarPaintOffset(object, context); 958 updateScrollbarPaintOffset(object, context);
955 } 959 }
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 } 960 }
966 961
967 void PaintPropertyTreeBuilder::updatePropertiesForChildren( 962 void PaintPropertyTreeBuilder::updatePropertiesForChildren(
968 const LayoutObject& object, 963 const LayoutObject& object,
969 PaintPropertyTreeBuilderContext& context) { 964 PaintPropertyTreeBuilderContext& context) {
970 #if DCHECK_IS_ON() 965 #if DCHECK_IS_ON()
971 FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object, context); 966 FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object, context);
972 #endif 967 #endif
973 968
974 if (!object.isBoxModelObject() && !object.isSVG()) 969 if (!object.isBoxModelObject() && !object.isSVG())
975 return; 970 return;
976 971
977 updateOverflowClip(object, context); 972 updateOverflowClip(object, context);
978 updatePerspective(object, context); 973 updatePerspective(object, context);
979 updateSvgLocalToBorderBoxTransform(object, context); 974 updateSvgLocalToBorderBoxTransform(object, context);
980 updateScrollAndScrollTranslation(object, context); 975 updateScrollAndScrollTranslation(object, context);
981 updateOutOfFlowContext(object, context); 976 updateOutOfFlowContext(object, context);
982 977
983 context.forceSubtreeUpdate |= object.subtreeNeedsPaintPropertyUpdate(); 978 context.forceSubtreeUpdate |= object.subtreeNeedsPaintPropertyUpdate();
984 } 979 }
985 980
986 } // namespace blink 981 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698