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

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

Issue 2401343002: Tracking filter mutation via SVGElementProxy (Closed)
Patch Set: Tweak lifecycle checks Created 4 years, 1 month 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 /* 1 /*
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights
3 * reserved. 3 * reserved.
4 * 4 *
5 * Portions are Copyright (C) 1998 Netscape Communications Corporation. 5 * Portions are Copyright (C) 1998 Netscape Communications Corporation.
6 * 6 *
7 * Other contributors: 7 * Other contributors:
8 * Robert O'Callahan <roc+@cs.cmu.edu> 8 * Robert O'Callahan <roc+@cs.cmu.edu>
9 * David Baron <dbaron@fas.harvard.edu> 9 * David Baron <dbaron@fas.harvard.edu>
10 * Christian Biesinger <cbiesinger@web.de> 10 * Christian Biesinger <cbiesinger@web.de>
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 if (!layoutObject->slowFirstChild() && layoutObject->style()) { 181 if (!layoutObject->slowFirstChild() && layoutObject->style()) {
182 m_isVisibleContentDirty = false; 182 m_isVisibleContentDirty = false;
183 m_hasVisibleContent = 183 m_hasVisibleContent =
184 layoutObject->style()->visibility() == EVisibility::Visible; 184 layoutObject->style()->visibility() == EVisibility::Visible;
185 } 185 }
186 186
187 updateScrollableArea(); 187 updateScrollableArea();
188 } 188 }
189 189
190 PaintLayer::~PaintLayer() { 190 PaintLayer::~PaintLayer() {
191 if (m_rareData && m_rareData->filterInfo) 191 if (m_rareData && m_rareData->filterInfo) {
192 layoutObject()->styleRef().filter().removeClient(m_rareData->filterInfo);
192 m_rareData->filterInfo->clearLayer(); 193 m_rareData->filterInfo->clearLayer();
194 }
193 if (layoutObject()->frame() && layoutObject()->frame()->page()) { 195 if (layoutObject()->frame() && layoutObject()->frame()->page()) {
194 if (ScrollingCoordinator* scrollingCoordinator = 196 if (ScrollingCoordinator* scrollingCoordinator =
195 layoutObject()->frame()->page()->scrollingCoordinator()) 197 layoutObject()->frame()->page()->scrollingCoordinator())
196 scrollingCoordinator->willDestroyLayer(this); 198 scrollingCoordinator->willDestroyLayer(this);
197 } 199 }
198 200
199 if (groupedMapping()) { 201 if (groupedMapping()) {
200 DisableCompositingQueryAsserts disabler; 202 DisableCompositingQueryAsserts disabler;
201 setGroupedMapping(0, InvalidateLayerAndRemoveFromMapping); 203 setGroupedMapping(0, InvalidateLayerAndRemoveFromMapping);
202 } 204 }
(...skipping 2441 matching lines...) Expand 10 before | Expand all | Expand 10 after
2644 2646
2645 void PaintLayer::ensureCompositedLayerMapping() { 2647 void PaintLayer::ensureCompositedLayerMapping() {
2646 if (m_rareData && m_rareData->compositedLayerMapping) 2648 if (m_rareData && m_rareData->compositedLayerMapping)
2647 return; 2649 return;
2648 2650
2649 ensureRareData().compositedLayerMapping = 2651 ensureRareData().compositedLayerMapping =
2650 wrapUnique(new CompositedLayerMapping(*this)); 2652 wrapUnique(new CompositedLayerMapping(*this));
2651 m_rareData->compositedLayerMapping->setNeedsGraphicsLayerUpdate( 2653 m_rareData->compositedLayerMapping->setNeedsGraphicsLayerUpdate(
2652 GraphicsLayerUpdateSubtree); 2654 GraphicsLayerUpdateSubtree);
2653 2655
2654 updateOrRemoveFilterEffect(); 2656 if (PaintLayerFilterInfo* filterInfo = this->filterInfo())
2657 filterInfo->invalidateFilterChain();
2655 } 2658 }
2656 2659
2657 void PaintLayer::clearCompositedLayerMapping(bool layerBeingDestroyed) { 2660 void PaintLayer::clearCompositedLayerMapping(bool layerBeingDestroyed) {
2658 if (!layerBeingDestroyed) { 2661 if (!layerBeingDestroyed) {
2659 // We need to make sure our decendants get a geometry update. In principle, 2662 // We need to make sure our decendants get a geometry update. In principle,
2660 // we could call setNeedsGraphicsLayerUpdate on our children, but that would 2663 // we could call setNeedsGraphicsLayerUpdate on our children, but that would
2661 // require walking the z-order lists to find them. Instead, we 2664 // require walking the z-order lists to find them. Instead, we
2662 // over-invalidate by marking our parent as needing a geometry update. 2665 // over-invalidate by marking our parent as needing a geometry update.
2663 if (PaintLayer* compositingParent = 2666 if (PaintLayer* compositingParent =
2664 enclosingLayerWithCompositedLayerMapping(ExcludeSelf)) 2667 enclosingLayerWithCompositedLayerMapping(ExcludeSelf))
2665 compositingParent->compositedLayerMapping()->setNeedsGraphicsLayerUpdate( 2668 compositingParent->compositedLayerMapping()->setNeedsGraphicsLayerUpdate(
2666 GraphicsLayerUpdateSubtree); 2669 GraphicsLayerUpdateSubtree);
2667 } 2670 }
2668 2671
2669 if (m_rareData) 2672 if (m_rareData)
2670 m_rareData->compositedLayerMapping.reset(); 2673 m_rareData->compositedLayerMapping.reset();
2671 2674
2672 if (!layerBeingDestroyed) 2675 if (layerBeingDestroyed)
2673 updateOrRemoveFilterEffect(); 2676 return;
2677
2678 if (PaintLayerFilterInfo* filterInfo = this->filterInfo())
2679 filterInfo->invalidateFilterChain();
2674 } 2680 }
2675 2681
2676 void PaintLayer::setGroupedMapping(CompositedLayerMapping* groupedMapping, 2682 void PaintLayer::setGroupedMapping(CompositedLayerMapping* groupedMapping,
2677 SetGroupMappingOptions options) { 2683 SetGroupMappingOptions options) {
2678 CompositedLayerMapping* oldGroupedMapping = this->groupedMapping(); 2684 CompositedLayerMapping* oldGroupedMapping = this->groupedMapping();
2679 if (groupedMapping == oldGroupedMapping) 2685 if (groupedMapping == oldGroupedMapping)
2680 return; 2686 return;
2681 2687
2682 if (options == InvalidateLayerAndRemoveFromMapping && oldGroupedMapping) { 2688 if (options == InvalidateLayerAndRemoveFromMapping && oldGroupedMapping) {
2683 oldGroupedMapping->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateSubtree); 2689 oldGroupedMapping->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateSubtree);
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
2866 return false; 2872 return false;
2867 2873
2868 return hasBoxDecorationsOrBackground() || hasOverflowControls(); 2874 return hasBoxDecorationsOrBackground() || hasOverflowControls();
2869 } 2875 }
2870 2876
2871 void PaintLayer::updateFilters(const ComputedStyle* oldStyle, 2877 void PaintLayer::updateFilters(const ComputedStyle* oldStyle,
2872 const ComputedStyle& newStyle) { 2878 const ComputedStyle& newStyle) {
2873 if (!newStyle.hasFilterInducingProperty() && 2879 if (!newStyle.hasFilterInducingProperty() &&
2874 (!oldStyle || !oldStyle->hasFilterInducingProperty())) 2880 (!oldStyle || !oldStyle->hasFilterInducingProperty()))
2875 return; 2881 return;
2876 2882 const bool hadFilterInfo = filterInfo();
2877 updateOrRemoveFilterClients(); 2883 if (newStyle.hasFilterInducingProperty())
2878 updateOrRemoveFilterEffect(); 2884 newStyle.filter().addClient(&ensureFilterInfo());
2885 if (hadFilterInfo && oldStyle)
2886 oldStyle->filter().removeClient(filterInfo());
2887 if (!newStyle.hasFilterInducingProperty()) {
2888 removeFilterInfo();
2889 return;
2890 }
2891 if (PaintLayerFilterInfo* filterInfo = this->filterInfo())
2892 filterInfo->invalidateFilterChain();
2879 } 2893 }
2880 2894
2881 bool PaintLayer::attemptDirectCompositingUpdate(StyleDifference diff, 2895 bool PaintLayer::attemptDirectCompositingUpdate(StyleDifference diff,
2882 const ComputedStyle* oldStyle) { 2896 const ComputedStyle* oldStyle) {
2883 CompositingReasons oldPotentialCompositingReasonsFromStyle = 2897 CompositingReasons oldPotentialCompositingReasonsFromStyle =
2884 potentialCompositingReasonsFromStyle(); 2898 potentialCompositingReasonsFromStyle();
2885 compositor()->updatePotentialCompositingReasonsFromStyle(this); 2899 compositor()->updatePotentialCompositingReasonsFromStyle(this);
2886 2900
2887 // This function implements an optimization for transforms and opacity. 2901 // This function implements an optimization for transforms and opacity.
2888 // A common pattern is for a touchmove handler to update the transform 2902 // A common pattern is for a touchmove handler to update the transform
2889 // and/or an opacity of an element every frame while the user moves their 2903 // and/or an opacity of an element every frame while the user moves their
2890 // finger across the screen. The conditions below recognize when the 2904 // finger across the screen. The conditions below recognize when the
2891 // compositing state is set up to receive a direct transform or opacity 2905 // compositing state is set up to receive a direct transform or opacity
2892 // update. 2906 // update.
2893 2907
2894 if (!diff.hasAtMostPropertySpecificDifferences( 2908 if (!diff.hasAtMostPropertySpecificDifferences(
2895 StyleDifference::TransformChanged | StyleDifference::OpacityChanged)) 2909 StyleDifference::TransformChanged | StyleDifference::OpacityChanged))
2896 return false; 2910 return false;
2897 // The potentialCompositingReasonsFromStyle could have changed without 2911 // The potentialCompositingReasonsFromStyle could have changed without
2898 // a corresponding StyleDifference if an animation started or ended. 2912 // a corresponding StyleDifference if an animation started or ended.
2899 if (potentialCompositingReasonsFromStyle() != 2913 if (potentialCompositingReasonsFromStyle() !=
2900 oldPotentialCompositingReasonsFromStyle) 2914 oldPotentialCompositingReasonsFromStyle)
2901 return false; 2915 return false;
2902 // If we're unwinding a scheduleSVGFilterLayerUpdateHack(), then we can't
2903 // perform a direct compositing update because the filters code is going
2904 // to produce different output this time around. We can remove this code
2905 // once we fix the chicken/egg bugs in the filters code and delete the
2906 // scheduleSVGFilterLayerUpdateHack().
2907 if (layoutObject()->node() &&
2908 layoutObject()->node()->svgFilterNeedsLayerUpdate())
2909 return false;
2910 if (!m_rareData || !m_rareData->compositedLayerMapping) 2916 if (!m_rareData || !m_rareData->compositedLayerMapping)
2911 return false; 2917 return false;
2912 2918
2913 // To cut off almost all the work in the compositing update for 2919 // To cut off almost all the work in the compositing update for
2914 // this case, we treat inline transforms has having assumed overlap 2920 // this case, we treat inline transforms has having assumed overlap
2915 // (similar to how we treat animated transforms). Notice that we read 2921 // (similar to how we treat animated transforms). Notice that we read
2916 // CompositingReasonInlineTransform from the m_compositingReasons, which 2922 // CompositingReasonInlineTransform from the m_compositingReasons, which
2917 // means that the inline transform actually triggered assumed overlap in 2923 // means that the inline transform actually triggered assumed overlap in
2918 // the overlap map. 2924 // the overlap map.
2919 if (diff.transformChanged() && 2925 if (diff.transformChanged() &&
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
3013 return builder.buildFilterOperations(style.backdropFilter()); 3019 return builder.buildFilterOperations(style.backdropFilter());
3014 } 3020 }
3015 3021
3016 PaintLayerFilterInfo& PaintLayer::ensureFilterInfo() { 3022 PaintLayerFilterInfo& PaintLayer::ensureFilterInfo() {
3017 PaintLayerRareData& rareData = ensureRareData(); 3023 PaintLayerRareData& rareData = ensureRareData();
3018 if (!rareData.filterInfo) 3024 if (!rareData.filterInfo)
3019 rareData.filterInfo = new PaintLayerFilterInfo(this); 3025 rareData.filterInfo = new PaintLayerFilterInfo(this);
3020 return *rareData.filterInfo; 3026 return *rareData.filterInfo;
3021 } 3027 }
3022 3028
3029 void PaintLayer::removeFilterInfo() {
3030 if (!m_rareData || !m_rareData->filterInfo)
3031 return;
3032 m_rareData->filterInfo->clearLayer();
3033 m_rareData->filterInfo = nullptr;
3034 }
3035
3023 void PaintLayer::removeAncestorOverflowLayer(const PaintLayer* removedLayer) { 3036 void PaintLayer::removeAncestorOverflowLayer(const PaintLayer* removedLayer) {
3024 // If the current ancestor overflow layer does not match the removed layer 3037 // If the current ancestor overflow layer does not match the removed layer
3025 // the ancestor overflow layer has changed so we can stop searching. 3038 // the ancestor overflow layer has changed so we can stop searching.
3026 if (ancestorOverflowLayer() && ancestorOverflowLayer() != removedLayer) 3039 if (ancestorOverflowLayer() && ancestorOverflowLayer() != removedLayer)
3027 return; 3040 return;
3028 3041
3029 if (ancestorOverflowLayer()) { 3042 if (ancestorOverflowLayer()) {
3030 // TODO(pdr): When slimming paint v2 is enabled, we will need to 3043 // TODO(pdr): When slimming paint v2 is enabled, we will need to
3031 // invalidate the scroll paint property subtree for this so main 3044 // invalidate the scroll paint property subtree for this so main
3032 // thread scroll reasons are recomputed. 3045 // thread scroll reasons are recomputed.
3033 ancestorOverflowLayer() 3046 ancestorOverflowLayer()
3034 ->getScrollableArea() 3047 ->getScrollableArea()
3035 ->invalidateStickyConstraintsFor(this); 3048 ->invalidateStickyConstraintsFor(this);
3036 } 3049 }
3037 updateAncestorOverflowLayer(nullptr); 3050 updateAncestorOverflowLayer(nullptr);
3038 PaintLayer* current = m_first; 3051 PaintLayer* current = m_first;
3039 while (current) { 3052 while (current) {
3040 current->removeAncestorOverflowLayer(removedLayer); 3053 current->removeAncestorOverflowLayer(removedLayer);
3041 current = current->nextSibling(); 3054 current = current->nextSibling();
3042 } 3055 }
3043 } 3056 }
3044 3057
3045 void PaintLayer::updateOrRemoveFilterClients() { 3058 FilterEffect* PaintLayer::lastFilterEffect() const {
3046 const auto& filter = layoutObject()->style()->filter();
3047 if (filter.isEmpty() && m_rareData && m_rareData->filterInfo) {
3048 m_rareData->filterInfo->clearLayer();
3049 m_rareData->filterInfo = nullptr;
3050 } else if (filter.hasReferenceFilter()) {
3051 ensureFilterInfo().updateReferenceFilterClients(filter);
3052 } else if (filterInfo()) {
3053 filterInfo()->clearFilterReferences();
3054 }
3055 }
3056
3057 FilterEffect* PaintLayer::updateFilterEffect() const {
3058 // TODO(chrishtr): ensure (and assert) that compositing is clean here. 3059 // TODO(chrishtr): ensure (and assert) that compositing is clean here.
3059
3060 if (!paintsWithFilters()) 3060 if (!paintsWithFilters())
3061 return nullptr; 3061 return nullptr;
3062
3063 PaintLayerFilterInfo* filterInfo = this->filterInfo(); 3062 PaintLayerFilterInfo* filterInfo = this->filterInfo();
3064
3065 // Should have been added by updateOrRemoveFilterEffect().
3066 DCHECK(filterInfo); 3063 DCHECK(filterInfo);
3067 3064
3068 if (filterInfo->lastEffect()) 3065 if (filterInfo->lastEffect())
3069 return filterInfo->lastEffect(); 3066 return filterInfo->lastEffect();
3070 3067
3071 const ComputedStyle& style = layoutObject()->styleRef(); 3068 const ComputedStyle& style = layoutObject()->styleRef();
3072 FloatRect zoomedReferenceBox; 3069 FloatRect zoomedReferenceBox;
3073 if (style.filter().hasReferenceFilter()) 3070 if (style.filter().hasReferenceFilter())
3074 zoomedReferenceBox = boxForFilter(); 3071 zoomedReferenceBox = boxForFilter();
3075 FilterEffectBuilder builder(enclosingNode(), zoomedReferenceBox, 3072 FilterEffectBuilder builder(enclosingNode(), zoomedReferenceBox,
3076 style.effectiveZoom()); 3073 style.effectiveZoom());
3077 filterInfo->setLastEffect( 3074 filterInfo->setLastEffect(
3078 builder.buildFilterEffect(addReflectionToFilterOperations(style))); 3075 builder.buildFilterEffect(addReflectionToFilterOperations(style)));
3079 return filterInfo->lastEffect(); 3076 return filterInfo->lastEffect();
3080 } 3077 }
3081 3078
3082 FilterEffect* PaintLayer::lastFilterEffect() const {
3083 return updateFilterEffect();
3084 }
3085
3086 FloatRect PaintLayer::mapRectForFilter(const FloatRect& rect) const { 3079 FloatRect PaintLayer::mapRectForFilter(const FloatRect& rect) const {
3087 if (!hasFilterThatMovesPixels()) 3080 if (!hasFilterThatMovesPixels())
3088 return rect; 3081 return rect;
3089 3082
3090 // Ensure the filter-chain is refreshed wrt reference filters. 3083 // Ensure the filter-chain is refreshed wrt reference filters.
3091 updateFilterEffect(); 3084 // TODO(fs): Avoid having this side-effect inducing call.
3085 lastFilterEffect();
3092 3086
3093 FilterOperations filterOperations = 3087 FilterOperations filterOperations =
3094 addReflectionToFilterOperations(layoutObject()->styleRef()); 3088 addReflectionToFilterOperations(layoutObject()->styleRef());
3095 return filterOperations.mapRect(rect); 3089 return filterOperations.mapRect(rect);
3096 } 3090 }
3097 3091
3098 LayoutRect PaintLayer::mapLayoutRectForFilter(const LayoutRect& rect) const { 3092 LayoutRect PaintLayer::mapLayoutRectForFilter(const LayoutRect& rect) const {
3099 if (!hasFilterThatMovesPixels()) 3093 if (!hasFilterThatMovesPixels())
3100 return rect; 3094 return rect;
3101 return enclosingLayoutRect(mapRectForFilter(FloatRect(rect))); 3095 return enclosingLayoutRect(mapRectForFilter(FloatRect(rect)));
3102 } 3096 }
3103 3097
3104 bool PaintLayer::hasFilterThatMovesPixels() const { 3098 bool PaintLayer::hasFilterThatMovesPixels() const {
3105 if (!hasFilterInducingProperty()) 3099 if (!hasFilterInducingProperty())
3106 return false; 3100 return false;
3107 const ComputedStyle& style = layoutObject()->styleRef(); 3101 const ComputedStyle& style = layoutObject()->styleRef();
3108 if (style.hasFilter() && style.filter().hasFilterThatMovesPixels()) 3102 if (style.hasFilter() && style.filter().hasFilterThatMovesPixels())
3109 return true; 3103 return true;
3110 if (style.hasBoxReflect()) 3104 if (style.hasBoxReflect())
3111 return true; 3105 return true;
3112 return false; 3106 return false;
3113 } 3107 }
3114 3108
3115 void PaintLayer::updateOrRemoveFilterEffect() {
3116 // FilterEffectBuilder is only used to render the filters in software mode,
3117 // so we always need to run updateOrRemoveFilterEffect after the composited
3118 // mode might have changed for this layer.
3119 if (!paintsWithFilters()) {
3120 if (PaintLayerFilterInfo* filterInfo = this->filterInfo())
3121 filterInfo->setLastEffect(nullptr);
3122 return;
3123 }
3124
3125 ensureFilterInfo().setLastEffect(nullptr);
3126 }
3127
3128 void PaintLayer::filterNeedsPaintInvalidation() {
3129 {
3130 DeprecatedScheduleStyleRecalcDuringLayout marker(
3131 layoutObject()->document().lifecycle());
3132 // It's possible for scheduleSVGFilterLayerUpdateHack to schedule a style
3133 // recalc, which is a problem because this function can be called right
3134 // before performing layout but after style recalc.
3135 //
3136 // See LayoutView::layout() and the call to
3137 // invalidateSVGRootsWithRelativeLengthDescendents(). This violation is
3138 // worked around in FrameView::updateStyleAndLayoutIfNeededRecursive() by
3139 // doing an extra style recalc and layout in case it's needed.
3140 toElement(layoutObject()->node())->scheduleSVGFilterLayerUpdateHack();
3141 }
3142
3143 layoutObject()->setShouldDoFullPaintInvalidation();
3144 }
3145
3146 void PaintLayer::addLayerHitTestRects(LayerHitTestRects& rects) const { 3109 void PaintLayer::addLayerHitTestRects(LayerHitTestRects& rects) const {
3147 computeSelfHitTestRects(rects); 3110 computeSelfHitTestRects(rects);
3148 for (PaintLayer* child = firstChild(); child; child = child->nextSibling()) 3111 for (PaintLayer* child = firstChild(); child; child = child->nextSibling())
3149 child->addLayerHitTestRects(rects); 3112 child->addLayerHitTestRects(rects);
3150 } 3113 }
3151 3114
3152 void PaintLayer::computeSelfHitTestRects(LayerHitTestRects& rects) const { 3115 void PaintLayer::computeSelfHitTestRects(LayerHitTestRects& rects) const {
3153 if (!size().isEmpty()) { 3116 if (!size().isEmpty()) {
3154 Vector<LayoutRect> rect; 3117 Vector<LayoutRect> rect;
3155 3118
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
3274 } 3237 }
3275 3238
3276 void showLayerTree(const blink::LayoutObject* layoutObject) { 3239 void showLayerTree(const blink::LayoutObject* layoutObject) {
3277 if (!layoutObject) { 3240 if (!layoutObject) {
3278 fprintf(stderr, "Cannot showLayerTree. Root is (nil)\n"); 3241 fprintf(stderr, "Cannot showLayerTree. Root is (nil)\n");
3279 return; 3242 return;
3280 } 3243 }
3281 showLayerTree(layoutObject->enclosingLayer()); 3244 showLayerTree(layoutObject->enclosingLayer());
3282 } 3245 }
3283 #endif 3246 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698