Commit 42c48698 authored by wangxianzhu's avatar wangxianzhu Committed by Commit bot

Skip PaintPhaseDescendantOutlinesOnly if no descendant outlines in the layer

BUG=574938
TEST=PaintLayerPainterTest.PaintPhaseOutline
TEST=fast/multicol/span/outline.html

Review URL: https://codereview.chromium.org/1584493002

Cr-Commit-Position: refs/heads/master@{#371652}
parent c91e967e
<!DOCTYPE html>
<p>Test an outlined element inside a spanner. Passes if there is a complete blue rectangle below.</p>
<div style=" outline: 2px solid blue; width: 300px; height: 100px"></div>
<!DOCTYPE html>
<p>Test an outlined element inside a spanner. Passes if there is a complete blue rectangle below.</p>
<div style="width:300px; -webkit-columns:3; -webkit-column-gap:20px;">
<div style="position: relative">
<div style="-webkit-column-span:all">
<div style=" outline: 2px solid blue; height: 100px"></div>
</div>
</div>
</div>
...@@ -1406,6 +1406,12 @@ inline void LayoutObject::invalidateSelectionIfNeeded(const LayoutBoxModelObject ...@@ -1406,6 +1406,12 @@ inline void LayoutObject::invalidateSelectionIfNeeded(const LayoutBoxModelObject
PaintInvalidationReason LayoutObject::invalidatePaintIfNeeded(PaintInvalidationState& paintInvalidationState, const LayoutBoxModelObject& paintInvalidationContainer) PaintInvalidationReason LayoutObject::invalidatePaintIfNeeded(PaintInvalidationState& paintInvalidationState, const LayoutBoxModelObject& paintInvalidationContainer)
{ {
if (styleRef().hasOutline()) {
PaintLayer& layer = paintInvalidationState.enclosingSelfPaintingLayer(*this);
if (layer.layoutObject() != this)
layer.setNeedsPaintPhaseDescendantOutlines();
}
LayoutView* v = view(); LayoutView* v = view();
if (v->document().printing()) if (v->document().printing())
return PaintInvalidationNone; // Don't invalidate paints if we're printing. return PaintInvalidationNone; // Don't invalidate paints if we're printing.
......
...@@ -83,6 +83,15 @@ protected: ...@@ -83,6 +83,15 @@ protected:
commit(); commit();
} }
bool displayItemListContains(const DisplayItemList& displayItemList, DisplayItemClient& client, DisplayItem::Type type)
{
for (auto& item : displayItemList) {
if (item.client() == client && item.type() == type)
return true;
}
return false;
}
private: private:
bool m_originalSlimmingPaintOffsetCachingEnabled; bool m_originalSlimmingPaintOffsetCachingEnabled;
bool m_originalSlimmingPaintV2Enabled; bool m_originalSlimmingPaintV2Enabled;
......
...@@ -127,6 +127,7 @@ PaintLayer::PaintLayer(LayoutBoxModelObject* layoutObject, PaintLayerType type) ...@@ -127,6 +127,7 @@ PaintLayer::PaintLayer(LayoutBoxModelObject* layoutObject, PaintLayerType type)
, m_lostGroupedMapping(false) , m_lostGroupedMapping(false)
, m_needsRepaint(false) , m_needsRepaint(false)
, m_previousPaintResult(PaintLayerPainter::FullyPainted) , m_previousPaintResult(PaintLayerPainter::FullyPainted)
, m_needsPaintPhaseDescendantOutlines(false)
, m_layoutObject(layoutObject) , m_layoutObject(layoutObject)
, m_parent(0) , m_parent(0)
, m_previous(0) , m_previous(0)
......
...@@ -621,6 +621,11 @@ public: ...@@ -621,6 +621,11 @@ public:
PaintLayerPainter::PaintResult previousPaintResult() const { return static_cast<PaintLayerPainter::PaintResult>(m_previousPaintResult); } PaintLayerPainter::PaintResult previousPaintResult() const { return static_cast<PaintLayerPainter::PaintResult>(m_previousPaintResult); }
void setPreviousPaintResult(PaintLayerPainter::PaintResult result) { m_previousPaintResult = static_cast<unsigned>(result); ASSERT(m_previousPaintResult == static_cast<unsigned>(result)); } void setPreviousPaintResult(PaintLayerPainter::PaintResult result) { m_previousPaintResult = static_cast<unsigned>(result); ASSERT(m_previousPaintResult == static_cast<unsigned>(result)); }
// Used to skip PaintPhaseDescendantOutlinesOnly for layers that have never had descendant outlines.
// Once it's set we never clear it because it's not easy to track if all outlines have been removed.
bool needsPaintPhaseDescendantOutlines() const { return m_needsPaintPhaseDescendantOutlines; }
void setNeedsPaintPhaseDescendantOutlines() { ASSERT(isSelfPaintingLayer()); m_needsPaintPhaseDescendantOutlines = true; }
PaintTiming* paintTiming(); PaintTiming* paintTiming();
private: private:
...@@ -753,6 +758,8 @@ private: ...@@ -753,6 +758,8 @@ private:
unsigned m_needsRepaint : 1; unsigned m_needsRepaint : 1;
unsigned m_previousPaintResult : 1; // PaintLayerPainter::PaintResult unsigned m_previousPaintResult : 1; // PaintLayerPainter::PaintResult
unsigned m_needsPaintPhaseDescendantOutlines : 1;
LayoutBoxModelObject* m_layoutObject; LayoutBoxModelObject* m_layoutObject;
PaintLayer* m_parent; PaintLayer* m_parent;
......
...@@ -673,7 +673,8 @@ void PaintLayerPainter::paintForegroundForFragments(const PaintLayerFragments& l ...@@ -673,7 +673,8 @@ void PaintLayerPainter::paintForegroundForFragments(const PaintLayerFragments& l
if (!selectionOnly) { if (!selectionOnly) {
paintForegroundForFragmentsWithPhase(PaintPhaseFloat, layerFragments, context, localPaintingInfo, paintFlags, clipState); paintForegroundForFragmentsWithPhase(PaintPhaseFloat, layerFragments, context, localPaintingInfo, paintFlags, clipState);
paintForegroundForFragmentsWithPhase(PaintPhaseForeground, layerFragments, context, localPaintingInfo, paintFlags, clipState); paintForegroundForFragmentsWithPhase(PaintPhaseForeground, layerFragments, context, localPaintingInfo, paintFlags, clipState);
paintForegroundForFragmentsWithPhase(PaintPhaseDescendantOutlinesOnly, layerFragments, context, localPaintingInfo, paintFlags, clipState); if (m_paintLayer.needsPaintPhaseDescendantOutlines())
paintForegroundForFragmentsWithPhase(PaintPhaseDescendantOutlinesOnly, layerFragments, context, localPaintingInfo, paintFlags, clipState);
} }
} }
......
...@@ -242,4 +242,46 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceOnStyleChangeWithInterestRectClip ...@@ -242,4 +242,46 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceOnStyleChangeWithInterestRectClip
TestDisplayItem(htmlLayer, DisplayItem::EndSubsequence)); TestDisplayItem(htmlLayer, DisplayItem::EndSubsequence));
} }
TEST_P(PaintLayerPainterTest, PaintPhaseOutline)
{
AtomicString styleWithoutOutline = "width: 50px; height: 50px; background-color: green";
AtomicString styleWithOutline = "outline: 1px solid blue; " + styleWithoutOutline;
setBodyInnerHTML(
"<div id='self-painting-layer' style='position: absolute'>"
" <div id='non-self-painting-layer' style='overflow: hidden'>"
" <div>"
" <div id='outline'></div>"
" </div>"
" </div>"
"</div>");
LayoutObject& outlineDiv = *document().getElementById("outline")->layoutObject();
toHTMLElement(outlineDiv.node())->setAttribute(HTMLNames::styleAttr, styleWithoutOutline);
document().view()->updateAllLifecyclePhases();
LayoutBlock& selfPaintingLayerObject = *toLayoutBlock(document().getElementById("self-painting-layer")->layoutObject());
PaintLayer& selfPaintingLayer = *selfPaintingLayerObject.layer();
ASSERT_TRUE(selfPaintingLayer.isSelfPaintingLayer());
PaintLayer& nonSelfPaintingLayer = *toLayoutBoxModelObject(document().getElementById("non-self-painting-layer")->layoutObject())->layer();
ASSERT_FALSE(nonSelfPaintingLayer.isSelfPaintingLayer());
ASSERT_TRUE(&nonSelfPaintingLayer == outlineDiv.enclosingLayer());
EXPECT_FALSE(selfPaintingLayer.needsPaintPhaseDescendantOutlines());
EXPECT_FALSE(nonSelfPaintingLayer.needsPaintPhaseDescendantOutlines());
// Outline on the self-painting-layer node itself doesn't affect PaintPhaseDescendantOutlines.
toHTMLElement(selfPaintingLayerObject.node())->setAttribute(HTMLNames::styleAttr, "position: absolute; outline: 1px solid green");
document().view()->updateAllLifecyclePhases();
EXPECT_FALSE(selfPaintingLayer.needsPaintPhaseDescendantOutlines());
EXPECT_FALSE(nonSelfPaintingLayer.needsPaintPhaseDescendantOutlines());
EXPECT_TRUE(displayItemListContains(rootPaintController().displayItemList(), selfPaintingLayerObject, DisplayItem::paintPhaseToDrawingType(PaintPhaseSelfOutlineOnly)));
// needsPaintPhaseDescendantOutlines should be set when any descendant on the same layer has outline.
toHTMLElement(outlineDiv.node())->setAttribute(HTMLNames::styleAttr, styleWithOutline);
updateLifecyclePhasesBeforePaint();
EXPECT_TRUE(selfPaintingLayer.needsPaintPhaseDescendantOutlines());
EXPECT_FALSE(nonSelfPaintingLayer.needsPaintPhaseDescendantOutlines());
paint();
EXPECT_TRUE(displayItemListContains(rootPaintController().displayItemList(), outlineDiv, DisplayItem::paintPhaseToDrawingType(PaintPhaseSelfOutlineOnly)));
}
} // namespace blink } // namespace blink
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment