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 {
return current_color_ ? current_color : color_;
}
bool HasAlpha() const { return !current_color_ && color_.HasAlpha(); }
static Color ColorFromKeyword(CSSValueID);
static bool IsColorKeyword(CSSValueID);
static bool IsSystemColor(CSSValueID);
......
......@@ -3144,7 +3144,8 @@ void PaintLayer::StyleDidChange(StyleDifference diff,
SetNeedsCompositingInputsUpdate();
}
if (diff.NeedsLayout())
// HasAlphaChanged can affect whether a composited layer is opaque.
if (diff.NeedsLayout() || diff.HasAlphaChanged())
SetNeedsCompositingInputsUpdate();
// A scroller that changes background color might become opaque or not
......
......@@ -1742,4 +1742,24 @@ TEST_P(PaintLayerTest, HitTestFirstLetterPseudoElementDisplayContents) {
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
......@@ -536,8 +536,8 @@ StyleDifference ComputedStyle::VisualInvalidationDiff(
if (DiffNeedsPaintInvalidationSubtree(other))
diff.SetNeedsPaintInvalidationSubtree();
else if (DiffNeedsPaintInvalidationObject(other))
diff.SetNeedsPaintInvalidationObject();
else
AdjustDiffForNeedsPaintInvalidationObject(other, diff);
if (DiffNeedsVisualRectUpdate(other))
diff.SetNeedsVisualRectUpdate();
......@@ -699,24 +699,46 @@ bool ComputedStyle::DiffNeedsPaintInvalidationSubtree(
return ComputedStyleBase::DiffNeedsPaintInvalidationSubtree(*this, other);
}
bool ComputedStyle::DiffNeedsPaintInvalidationObject(
const ComputedStyle& other) const {
if (ComputedStyleBase::DiffNeedsPaintInvalidationObject(*this, other))
return true;
void ComputedStyle::AdjustDiffForNeedsPaintInvalidationObject(
const ComputedStyle& other,
StyleDifference& diff) const {
if (ComputedStyleBase::DiffNeedsPaintInvalidationObject(*this, other) ||
!BorderVisuallyEqual(other) || !RadiiEqual(other))
diff.SetNeedsPaintInvalidationObject();
if (!BorderVisuallyEqual(other) || !RadiiEqual(other) ||
!BackgroundVisuallyEqual(other))
return true;
AdjustDiffForBackgroundVisuallyEqual(other, diff);
if (diff.NeedsPaintInvalidationObject())
return;
if (PaintImagesInternal()) {
for (const auto& image : *PaintImagesInternal()) {
DCHECK(image);
if (DiffNeedsPaintInvalidationObjectForPaintImage(*image, other))
return true;
if (DiffNeedsPaintInvalidationObjectForPaintImage(*image, other)) {
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(
......
......@@ -1706,10 +1706,9 @@ class ComputedStyle : public ComputedStyleBase,
return BorderImage().Outset() == o.BorderImage().Outset();
}
bool BackgroundVisuallyEqual(const ComputedStyle& o) const {
return BackgroundColorInternal() == o.BackgroundColorInternal() &&
BackgroundInternal().VisuallyEqual(o.BackgroundInternal());
}
CORE_EXPORT void AdjustDiffForBackgroundVisuallyEqual(
const ComputedStyle& o,
StyleDifference& diff) const;
void ResetBorder() {
ResetBorderImage();
......@@ -2513,7 +2512,8 @@ class ComputedStyle : public ComputedStyleBase,
const Document&,
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(
const StyleImage&,
const ComputedStyle& other) const;
......@@ -2603,6 +2603,8 @@ class ComputedStyle : public ComputedStyleBase,
FRIEND_TEST_ALL_PREFIXES(
ComputedStyleTest,
UpdatePropertySpecificDifferencesCompositingReasonsContainsPaint);
FRIEND_TEST_ALL_PREFIXES(ComputedStyleTest,
UpdatePropertySpecificDifferencesHasAlpha);
};
inline bool ComputedStyle::SetEffectiveZoom(float f) {
......
......@@ -243,6 +243,39 @@ TEST(ComputedStyleTest,
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) {
scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
EXPECT_FALSE(style->HasOutline());
......
......@@ -28,6 +28,8 @@ class StyleDifference {
kTextDecorationOrColorChanged = 1 << 6,
kBlendModeChanged = 1 << 7,
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.
};
......@@ -152,6 +154,13 @@ class StyleDifference {
}
void SetMaskChanged() { property_specific_differences_ |= kMaskChanged; }
bool HasAlphaChanged() const {
return property_specific_differences_ & kHasAlphaChanged;
}
void SetHasAlphaChanged() {
property_specific_differences_ |= kHasAlphaChanged;
}
bool ScrollAnchorDisablingPropertyChanged() const {
return scroll_anchor_disabling_property_changed_;
}
......@@ -162,7 +171,7 @@ class StyleDifference {
void SetCompositingReasonsChanged() { composited_reasons_changed_ = true; }
private:
static constexpr int kPropertyDifferenceCount = 9;
static constexpr int kPropertyDifferenceCount = 10;
friend CORE_EXPORT std::ostream& operator<<(std::ostream&,
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