Commit ce731513 authored by Chris Harrelson's avatar Chris Harrelson Committed by Commit Bot

[Regression] Invalidate compositing inputs when changing background alpha.

This is because the ContentsOpaque property of a cc::Layer can depend
on alpha.

Bug: 896716

Change-Id: Ica063db2860e0a6ba2bc9ffdf45b5cca06e26e84
Reviewed-on: https://chromium-review.googlesource.com/c/1327158
Commit-Queue: Chris Harrelson <chrishtr@chromium.org>
Reviewed-by: default avatarStephen Chenney <schenney@chromium.org>
Cr-Commit-Position: refs/heads/master@{#607305}
parent 3cb1d430
...@@ -55,6 +55,8 @@ class StyleColor { ...@@ -55,6 +55,8 @@ class StyleColor {
return current_color_ ? current_color : color_; return current_color_ ? current_color : color_;
} }
bool HasAlpha() const { return !current_color_ && color_.HasAlpha(); }
static Color ColorFromKeyword(CSSValueID); static Color ColorFromKeyword(CSSValueID);
static bool IsColorKeyword(CSSValueID); static bool IsColorKeyword(CSSValueID);
static bool IsSystemColor(CSSValueID); static bool IsSystemColor(CSSValueID);
......
...@@ -3144,7 +3144,8 @@ void PaintLayer::StyleDidChange(StyleDifference diff, ...@@ -3144,7 +3144,8 @@ void PaintLayer::StyleDidChange(StyleDifference diff,
SetNeedsCompositingInputsUpdate(); SetNeedsCompositingInputsUpdate();
} }
if (diff.NeedsLayout()) // HasAlphaChanged can affect whether a composited layer is opaque.
if (diff.NeedsLayout() || diff.HasAlphaChanged())
SetNeedsCompositingInputsUpdate(); SetNeedsCompositingInputsUpdate();
// A scroller that changes background color might become opaque or not // A scroller that changes background color might become opaque or not
......
...@@ -1742,4 +1742,24 @@ TEST_P(PaintLayerTest, HitTestFirstLetterPseudoElementDisplayContents) { ...@@ -1742,4 +1742,24 @@ TEST_P(PaintLayerTest, HitTestFirstLetterPseudoElementDisplayContents) {
result.InnerPossiblyPseudoNode()); result.InnerPossiblyPseudoNode());
} }
TEST_P(PaintLayerTest, ChangeAlphaNeedsCompositingInputs) {
SetBodyInnerHTML(R"HTML(
<style>
#target {
background: white;
width: 100px;
height: 100px;
position: relative;
}
</style>
<div id='target'>
</div>
)HTML");
PaintLayer* target = GetPaintLayerByElementId("target");
StyleDifference diff;
diff.SetHasAlphaChanged();
target->StyleDidChange(diff, target->GetLayoutObject().Style());
EXPECT_TRUE(target->NeedsCompositingInputsUpdate());
}
} // namespace blink } // namespace blink
...@@ -536,8 +536,8 @@ StyleDifference ComputedStyle::VisualInvalidationDiff( ...@@ -536,8 +536,8 @@ StyleDifference ComputedStyle::VisualInvalidationDiff(
if (DiffNeedsPaintInvalidationSubtree(other)) if (DiffNeedsPaintInvalidationSubtree(other))
diff.SetNeedsPaintInvalidationSubtree(); diff.SetNeedsPaintInvalidationSubtree();
else if (DiffNeedsPaintInvalidationObject(other)) else
diff.SetNeedsPaintInvalidationObject(); AdjustDiffForNeedsPaintInvalidationObject(other, diff);
if (DiffNeedsVisualRectUpdate(other)) if (DiffNeedsVisualRectUpdate(other))
diff.SetNeedsVisualRectUpdate(); diff.SetNeedsVisualRectUpdate();
...@@ -699,24 +699,46 @@ bool ComputedStyle::DiffNeedsPaintInvalidationSubtree( ...@@ -699,24 +699,46 @@ bool ComputedStyle::DiffNeedsPaintInvalidationSubtree(
return ComputedStyleBase::DiffNeedsPaintInvalidationSubtree(*this, other); return ComputedStyleBase::DiffNeedsPaintInvalidationSubtree(*this, other);
} }
bool ComputedStyle::DiffNeedsPaintInvalidationObject( void ComputedStyle::AdjustDiffForNeedsPaintInvalidationObject(
const ComputedStyle& other) const { const ComputedStyle& other,
if (ComputedStyleBase::DiffNeedsPaintInvalidationObject(*this, other)) StyleDifference& diff) const {
return true; if (ComputedStyleBase::DiffNeedsPaintInvalidationObject(*this, other) ||
!BorderVisuallyEqual(other) || !RadiiEqual(other))
diff.SetNeedsPaintInvalidationObject();
if (!BorderVisuallyEqual(other) || !RadiiEqual(other) || AdjustDiffForBackgroundVisuallyEqual(other, diff);
!BackgroundVisuallyEqual(other))
return true; if (diff.NeedsPaintInvalidationObject())
return;
if (PaintImagesInternal()) { if (PaintImagesInternal()) {
for (const auto& image : *PaintImagesInternal()) { for (const auto& image : *PaintImagesInternal()) {
DCHECK(image); DCHECK(image);
if (DiffNeedsPaintInvalidationObjectForPaintImage(*image, other)) if (DiffNeedsPaintInvalidationObjectForPaintImage(*image, other)) {
return true; diff.SetNeedsPaintInvalidationObject();
return;
}
} }
} }
}
return false; void ComputedStyle::AdjustDiffForBackgroundVisuallyEqual(
const ComputedStyle& other,
StyleDifference& diff) const {
if (BackgroundColorInternal() != other.BackgroundColorInternal()) {
diff.SetNeedsPaintInvalidationObject();
if (BackgroundColorInternal().HasAlpha() !=
other.BackgroundColorInternal().HasAlpha()) {
diff.SetHasAlphaChanged();
return;
}
}
if (!BackgroundInternal().VisuallyEqual(other.BackgroundInternal())) {
diff.SetNeedsPaintInvalidationObject();
// Changes of background fill layers, such as images, may have
// changed alpha.
diff.SetHasAlphaChanged();
}
} }
bool ComputedStyle::DiffNeedsPaintInvalidationObjectForPaintImage( bool ComputedStyle::DiffNeedsPaintInvalidationObjectForPaintImage(
......
...@@ -1706,10 +1706,9 @@ class ComputedStyle : public ComputedStyleBase, ...@@ -1706,10 +1706,9 @@ class ComputedStyle : public ComputedStyleBase,
return BorderImage().Outset() == o.BorderImage().Outset(); return BorderImage().Outset() == o.BorderImage().Outset();
} }
bool BackgroundVisuallyEqual(const ComputedStyle& o) const { CORE_EXPORT void AdjustDiffForBackgroundVisuallyEqual(
return BackgroundColorInternal() == o.BackgroundColorInternal() && const ComputedStyle& o,
BackgroundInternal().VisuallyEqual(o.BackgroundInternal()); StyleDifference& diff) const;
}
void ResetBorder() { void ResetBorder() {
ResetBorderImage(); ResetBorderImage();
...@@ -2513,7 +2512,8 @@ class ComputedStyle : public ComputedStyleBase, ...@@ -2513,7 +2512,8 @@ class ComputedStyle : public ComputedStyleBase,
const Document&, const Document&,
const ComputedStyle& other) const; const ComputedStyle& other) const;
bool DiffNeedsPaintInvalidationSubtree(const ComputedStyle& other) const; bool DiffNeedsPaintInvalidationSubtree(const ComputedStyle& other) const;
bool DiffNeedsPaintInvalidationObject(const ComputedStyle& other) const; void AdjustDiffForNeedsPaintInvalidationObject(const ComputedStyle& other,
StyleDifference&) const;
bool DiffNeedsPaintInvalidationObjectForPaintImage( bool DiffNeedsPaintInvalidationObjectForPaintImage(
const StyleImage&, const StyleImage&,
const ComputedStyle& other) const; const ComputedStyle& other) const;
...@@ -2603,6 +2603,8 @@ class ComputedStyle : public ComputedStyleBase, ...@@ -2603,6 +2603,8 @@ class ComputedStyle : public ComputedStyleBase,
FRIEND_TEST_ALL_PREFIXES( FRIEND_TEST_ALL_PREFIXES(
ComputedStyleTest, ComputedStyleTest,
UpdatePropertySpecificDifferencesCompositingReasonsContainsPaint); UpdatePropertySpecificDifferencesCompositingReasonsContainsPaint);
FRIEND_TEST_ALL_PREFIXES(ComputedStyleTest,
UpdatePropertySpecificDifferencesHasAlpha);
}; };
inline bool ComputedStyle::SetEffectiveZoom(float f) { inline bool ComputedStyle::SetEffectiveZoom(float f) {
......
...@@ -243,6 +243,39 @@ TEST(ComputedStyleTest, ...@@ -243,6 +243,39 @@ TEST(ComputedStyleTest,
EXPECT_TRUE(diff.CompositingReasonsChanged()); EXPECT_TRUE(diff.CompositingReasonsChanged());
} }
TEST(ComputedStyleTest, UpdateBackgroundColorDifferencesHasAlpha) {
scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
scoped_refptr<ComputedStyle> other = ComputedStyle::Clone(*style);
StyleDifference diff;
style->AdjustDiffForBackgroundVisuallyEqual(*other, diff);
EXPECT_FALSE(diff.HasAlphaChanged());
style->SetBackgroundColor(StyleColor(Color(255, 255, 255, 255)));
other->SetBackgroundColor(StyleColor(Color(255, 255, 255, 128)));
EXPECT_FALSE(
style->VisitedDependentColor(GetCSSPropertyBackgroundColor()).HasAlpha());
EXPECT_TRUE(
other->VisitedDependentColor(GetCSSPropertyBackgroundColor()).HasAlpha());
style->AdjustDiffForBackgroundVisuallyEqual(*other, diff);
EXPECT_TRUE(diff.HasAlphaChanged());
}
TEST(ComputedStyleTest, UpdateBackgroundLayerDifferencesHasAlpha) {
scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
scoped_refptr<ComputedStyle> other = ComputedStyle::Clone(*style);
StyleDifference diff;
style->AdjustDiffForBackgroundVisuallyEqual(*other, diff);
EXPECT_FALSE(diff.HasAlphaChanged());
other->AccessBackgroundLayers().EnsureNext();
style->AdjustDiffForBackgroundVisuallyEqual(*other, diff);
EXPECT_TRUE(diff.HasAlphaChanged());
}
TEST(ComputedStyleTest, HasOutlineWithCurrentColor) { TEST(ComputedStyleTest, HasOutlineWithCurrentColor) {
scoped_refptr<ComputedStyle> style = ComputedStyle::Create(); scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
EXPECT_FALSE(style->HasOutline()); EXPECT_FALSE(style->HasOutline());
......
...@@ -28,6 +28,8 @@ class StyleDifference { ...@@ -28,6 +28,8 @@ class StyleDifference {
kTextDecorationOrColorChanged = 1 << 6, kTextDecorationOrColorChanged = 1 << 6,
kBlendModeChanged = 1 << 7, kBlendModeChanged = 1 << 7,
kMaskChanged = 1 << 8, kMaskChanged = 1 << 8,
// Whether background-color changed alpha to or from 1.
kHasAlphaChanged = 1 << 9,
// If you add a value here, be sure to update kPropertyDifferenceCount. // If you add a value here, be sure to update kPropertyDifferenceCount.
}; };
...@@ -152,6 +154,13 @@ class StyleDifference { ...@@ -152,6 +154,13 @@ class StyleDifference {
} }
void SetMaskChanged() { property_specific_differences_ |= kMaskChanged; } void SetMaskChanged() { property_specific_differences_ |= kMaskChanged; }
bool HasAlphaChanged() const {
return property_specific_differences_ & kHasAlphaChanged;
}
void SetHasAlphaChanged() {
property_specific_differences_ |= kHasAlphaChanged;
}
bool ScrollAnchorDisablingPropertyChanged() const { bool ScrollAnchorDisablingPropertyChanged() const {
return scroll_anchor_disabling_property_changed_; return scroll_anchor_disabling_property_changed_;
} }
...@@ -162,7 +171,7 @@ class StyleDifference { ...@@ -162,7 +171,7 @@ class StyleDifference {
void SetCompositingReasonsChanged() { composited_reasons_changed_ = true; } void SetCompositingReasonsChanged() { composited_reasons_changed_ = true; }
private: private:
static constexpr int kPropertyDifferenceCount = 9; static constexpr int kPropertyDifferenceCount = 10;
friend CORE_EXPORT std::ostream& operator<<(std::ostream&, friend CORE_EXPORT std::ostream& operator<<(std::ostream&,
const StyleDifference&); const StyleDifference&);
......
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