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

Trigger render surfaces always for rotated clips.

Previously, we skipped a render surface for a rotated clip
(rounded or not) when the FastBorderMask runtime feature was enabled.

Also, made the unittests in paint_artifact_compositor_test work
with FastBorderRadius mode.

Bug: 947715

Change-Id: Ib5d0afd645c10cf219e2db7cb9c19a7155be97e5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1594333
Commit-Queue: Chris Harrelson <chrishtr@chromium.org>
Reviewed-by: default avatarXianzhu Wang <wangxianzhu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#656455}
parent f00c5e6b
......@@ -2584,12 +2584,46 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipSimple) {
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
if (RuntimeEnabledFeatures::FastBorderRadiusEnabled()) {
// Expectation in effect stack diagram:
// l1
// l0
// [ mask_isolation_0 ]
// [ e0 ]
// One content layer.
ASSERT_EQ(1u, RootLayer()->children().size());
ASSERT_EQ(1u, ContentLayerCount());
// There is still a "synthesized layer" but it's null.
ASSERT_EQ(1u, SynthesizedClipLayerCount());
EXPECT_FALSE(SynthesizedClipLayerAt(0));
const cc::Layer* content0 = RootLayer()->children()[0].get();
constexpr int c0_id = 1;
constexpr int e0_id = 1;
EXPECT_EQ(ContentLayerAt(0), content0);
int c1_id = content0->clip_tree_index();
const cc::ClipNode& cc_c1 = *GetPropertyTrees().clip_tree.Node(c1_id);
EXPECT_EQ(gfx::RectF(50, 50, 300, 200), cc_c1.clip);
ASSERT_EQ(c0_id, cc_c1.parent_id);
int mask_isolation_0_id = content0->effect_tree_index();
const cc::EffectNode& mask_isolation_0 =
*GetPropertyTrees().effect_tree.Node(mask_isolation_0_id);
ASSERT_EQ(e0_id, mask_isolation_0.parent_id);
EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode);
EXPECT_TRUE(mask_isolation_0.is_fast_rounded_corner);
EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
mask_isolation_0.rounded_corner_bounds);
return;
}
// Expectation in effect stack diagram:
// l1
// l0 [ mask_effect_0 ]
// [ mask_isolation_0 ]
// [ e0 ]
// One content layer, one clip mask.
// One content layer.
ASSERT_EQ(2u, RootLayer()->children().size());
ASSERT_EQ(1u, ContentLayerCount());
ASSERT_EQ(1u, SynthesizedClipLayerCount());
......@@ -2725,6 +2759,44 @@ TEST_P(PaintArtifactCompositorTest,
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
if (RuntimeEnabledFeatures::FastBorderRadiusEnabled()) {
// Expectation in effect stack diagram:
// l0 l1
// [ e1 ]
// [ mask_isolation_0 ]
// [ e0 ]
// One content layer, one clip mask.
ASSERT_EQ(1u, RootLayer()->children().size());
ASSERT_EQ(1u, ContentLayerCount());
// There is still a "synthesized layer" but it's null.
ASSERT_EQ(1u, SynthesizedClipLayerCount());
EXPECT_FALSE(SynthesizedClipLayerAt(0));
const cc::Layer* content0 = RootLayer()->children()[0].get();
constexpr int c0_id = 1;
constexpr int e0_id = 1;
EXPECT_EQ(ContentLayerAt(0), content0);
int c1_id = content0->clip_tree_index();
const cc::ClipNode& cc_c1 = *GetPropertyTrees().clip_tree.Node(c1_id);
EXPECT_EQ(gfx::RectF(50, 50, 300, 200), cc_c1.clip);
ASSERT_EQ(c0_id, cc_c1.parent_id);
int e1_id = content0->effect_tree_index();
const cc::EffectNode& cc_e1 = *GetPropertyTrees().effect_tree.Node(e1_id);
EXPECT_EQ(c1_id, cc_e1.clip_id);
int mask_isolation_0_id = cc_e1.parent_id;
const cc::EffectNode& mask_isolation_0 =
*GetPropertyTrees().effect_tree.Node(mask_isolation_0_id);
ASSERT_EQ(e0_id, mask_isolation_0.parent_id);
EXPECT_EQ(c1_id, mask_isolation_0.clip_id);
EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode);
EXPECT_TRUE(mask_isolation_0.is_fast_rounded_corner);
EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 0),
mask_isolation_0.rounded_corner_bounds);
return;
}
// Expectation in effect stack diagram:
// l0 l1
// [ e1 ][ mask_effect_0 ]
......@@ -2785,6 +2857,52 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipContiguous) {
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
if (RuntimeEnabledFeatures::FastBorderRadiusEnabled()) {
// Expectation in effect stack diagram:
// l2
// l0 l1
// [ mask_isolation_0 ]
// [ e0 ]
// Two content layers, one clip mask.
ASSERT_EQ(2u, RootLayer()->children().size());
ASSERT_EQ(2u, ContentLayerCount());
// There is still a "synthesized layer" but it's null.
ASSERT_EQ(1u, SynthesizedClipLayerCount());
EXPECT_FALSE(SynthesizedClipLayerAt(0));
const cc::Layer* content0 = RootLayer()->children()[0].get();
const cc::Layer* content1 = RootLayer()->children()[1].get();
constexpr int t0_id = 1;
constexpr int c0_id = 1;
constexpr int e0_id = 1;
EXPECT_EQ(ContentLayerAt(0), content0);
EXPECT_EQ(t0_id, content0->transform_tree_index());
int c1_id = content0->clip_tree_index();
const cc::ClipNode& cc_c1 = *GetPropertyTrees().clip_tree.Node(c1_id);
EXPECT_EQ(gfx::RectF(50, 50, 300, 200), cc_c1.clip);
ASSERT_EQ(c0_id, cc_c1.parent_id);
int mask_isolation_0_id = content0->effect_tree_index();
const cc::EffectNode& mask_isolation_0 =
*GetPropertyTrees().effect_tree.Node(mask_isolation_0_id);
ASSERT_EQ(e0_id, mask_isolation_0.parent_id);
EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode);
EXPECT_EQ(ContentLayerAt(1), content1);
int t1_id = content1->transform_tree_index();
const cc::TransformNode& cc_t1 =
*GetPropertyTrees().transform_tree.Node(t1_id);
ASSERT_EQ(t0_id, cc_t1.parent_id);
EXPECT_EQ(c1_id, content1->clip_tree_index());
EXPECT_EQ(mask_isolation_0_id, content1->effect_tree_index());
EXPECT_TRUE(mask_isolation_0.is_fast_rounded_corner);
EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
mask_isolation_0.rounded_corner_bounds);
return;
}
// Expectation in effect stack diagram:
// l2
// l0 l1 [ mask_effect_0 ]
......@@ -2855,6 +2973,66 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipDiscontiguous) {
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
if (RuntimeEnabledFeatures::FastBorderRadiusEnabled()) {
// Expectation in effect stack diagram:
// l1 l4
// l0 l3
// [ mask_isolation_0 ] l2 [ mask_isolation_1 ]
// [ e0 ]
// Three content layers.
ASSERT_EQ(3u, RootLayer()->children().size());
ASSERT_EQ(3u, ContentLayerCount());
// There are still "synthesized layers" but they're null.
ASSERT_EQ(2u, SynthesizedClipLayerCount());
EXPECT_FALSE(SynthesizedClipLayerAt(0));
EXPECT_FALSE(SynthesizedClipLayerAt(1));
const cc::Layer* content0 = RootLayer()->children()[0].get();
const cc::Layer* content1 = RootLayer()->children()[1].get();
const cc::Layer* content2 = RootLayer()->children()[2].get();
constexpr int t0_id = 1;
constexpr int c0_id = 1;
constexpr int e0_id = 1;
EXPECT_EQ(ContentLayerAt(0), content0);
EXPECT_EQ(t0_id, content0->transform_tree_index());
int c1_id = content0->clip_tree_index();
const cc::ClipNode& cc_c1 = *GetPropertyTrees().clip_tree.Node(c1_id);
EXPECT_EQ(gfx::RectF(50, 50, 300, 200), cc_c1.clip);
ASSERT_EQ(c0_id, cc_c1.parent_id);
int mask_isolation_0_id = content0->effect_tree_index();
const cc::EffectNode& mask_isolation_0 =
*GetPropertyTrees().effect_tree.Node(mask_isolation_0_id);
ASSERT_EQ(e0_id, mask_isolation_0.parent_id);
EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode);
EXPECT_TRUE(mask_isolation_0.is_fast_rounded_corner);
EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
mask_isolation_0.rounded_corner_bounds);
EXPECT_EQ(ContentLayerAt(1), content1);
int t1_id = content1->transform_tree_index();
const cc::TransformNode& cc_t1 =
*GetPropertyTrees().transform_tree.Node(t1_id);
ASSERT_EQ(t0_id, cc_t1.parent_id);
EXPECT_EQ(c0_id, content1->clip_tree_index());
EXPECT_EQ(e0_id, content1->effect_tree_index());
EXPECT_EQ(ContentLayerAt(2), content2);
EXPECT_EQ(t0_id, content2->transform_tree_index());
EXPECT_EQ(c1_id, content2->clip_tree_index());
int mask_isolation_1_id = content2->effect_tree_index();
const cc::EffectNode& mask_isolation_1 =
*GetPropertyTrees().effect_tree.Node(mask_isolation_1_id);
EXPECT_NE(mask_isolation_0_id, mask_isolation_1_id);
ASSERT_EQ(e0_id, mask_isolation_1.parent_id);
EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_1.blend_mode);
EXPECT_TRUE(mask_isolation_1.is_fast_rounded_corner);
EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
mask_isolation_1.rounded_corner_bounds);
return;
}
// Expectation in effect stack diagram:
// l1 l4
// l0 [ mask_effect_0 ] l3 [ mask_effect_1 ]
......@@ -2945,6 +3123,56 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipAcrossChildEffect) {
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
if (RuntimeEnabledFeatures::FastBorderRadiusEnabled()) {
// Expectation in effect stack diagram:
// l1 l3
// l0 [ e1 ] l2
// [ mask_isolation_0 ]
// [ e0 ]
// Three content layers.
ASSERT_EQ(3u, RootLayer()->children().size());
ASSERT_EQ(3u, ContentLayerCount());
// There is still a "synthesized layer" but it's null.
ASSERT_EQ(1u, SynthesizedClipLayerCount());
EXPECT_FALSE(SynthesizedClipLayerAt(0));
const cc::Layer* content0 = RootLayer()->children()[0].get();
const cc::Layer* content1 = RootLayer()->children()[1].get();
const cc::Layer* content2 = RootLayer()->children()[2].get();
constexpr int c0_id = 1;
constexpr int e0_id = 1;
EXPECT_EQ(ContentLayerAt(0), content0);
int c1_id = content0->clip_tree_index();
const cc::ClipNode& cc_c1 = *GetPropertyTrees().clip_tree.Node(c1_id);
EXPECT_EQ(gfx::RectF(50, 50, 300, 200), cc_c1.clip);
ASSERT_EQ(c0_id, cc_c1.parent_id);
int mask_isolation_0_id = content0->effect_tree_index();
const cc::EffectNode& mask_isolation_0 =
*GetPropertyTrees().effect_tree.Node(mask_isolation_0_id);
ASSERT_EQ(e0_id, mask_isolation_0.parent_id);
EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode);
EXPECT_EQ(ContentLayerAt(1), content1);
EXPECT_EQ(c1_id, content1->clip_tree_index());
int e1_id = content1->effect_tree_index();
const cc::EffectNode& cc_e1 = *GetPropertyTrees().effect_tree.Node(e1_id);
ASSERT_EQ(mask_isolation_0_id, cc_e1.parent_id);
EXPECT_EQ(ContentLayerAt(2), content2);
EXPECT_EQ(c1_id, content2->clip_tree_index());
EXPECT_EQ(mask_isolation_0_id, content2->effect_tree_index());
int e2_id = content2->effect_tree_index();
const cc::EffectNode& cc_e2 = *GetPropertyTrees().effect_tree.Node(e2_id);
EXPECT_TRUE(cc_e2.is_fast_rounded_corner);
EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
mask_isolation_0.rounded_corner_bounds);
return;
}
// Expectation in effect stack diagram:
// l1 l3
// l0 [ e1 ] l2 [ mask_effect_0 ]
......@@ -3017,6 +3245,72 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipRespectOutputClip) {
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
if (RuntimeEnabledFeatures::FastBorderRadiusEnabled()) {
// Expectation in effect stack diagram:
// l3
// l1 l2 l5
// l0 [ mask_isolation_1 ] l4
// [ mask_isolation_0 ][ e1 ][ mask_isolation_2 ]
// [ e0 ]
// Three content layers.
ASSERT_EQ(3u, RootLayer()->children().size());
ASSERT_EQ(3u, ContentLayerCount());
// There are still "synthesized layers" but they're null.
ASSERT_EQ(3u, SynthesizedClipLayerCount());
EXPECT_FALSE(SynthesizedClipLayerAt(0));
EXPECT_FALSE(SynthesizedClipLayerAt(1));
EXPECT_FALSE(SynthesizedClipLayerAt(2));
const cc::Layer* content0 = RootLayer()->children()[0].get();
const cc::Layer* content1 = RootLayer()->children()[1].get();
const cc::Layer* content2 = RootLayer()->children()[2].get();
constexpr int c0_id = 1;
constexpr int e0_id = 1;
EXPECT_EQ(ContentLayerAt(0), content0);
int c1_id = content0->clip_tree_index();
const cc::ClipNode& cc_c1 = *GetPropertyTrees().clip_tree.Node(c1_id);
EXPECT_EQ(gfx::RectF(50, 50, 300, 200), cc_c1.clip);
ASSERT_EQ(c0_id, cc_c1.parent_id);
int mask_isolation_0_id = content0->effect_tree_index();
const cc::EffectNode& mask_isolation_0 =
*GetPropertyTrees().effect_tree.Node(mask_isolation_0_id);
ASSERT_EQ(e0_id, mask_isolation_0.parent_id);
EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode);
EXPECT_TRUE(mask_isolation_0.is_fast_rounded_corner);
EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
mask_isolation_0.rounded_corner_bounds);
EXPECT_EQ(ContentLayerAt(1), content1);
EXPECT_EQ(c1_id, content1->clip_tree_index());
int mask_isolation_1_id = content1->effect_tree_index();
const cc::EffectNode& mask_isolation_1 =
*GetPropertyTrees().effect_tree.Node(mask_isolation_1_id);
EXPECT_NE(mask_isolation_0_id, mask_isolation_1_id);
EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_1.blend_mode);
int e1_id = mask_isolation_1.parent_id;
const cc::EffectNode& cc_e1 = *GetPropertyTrees().effect_tree.Node(e1_id);
ASSERT_EQ(e0_id, cc_e1.parent_id);
EXPECT_TRUE(mask_isolation_1.is_fast_rounded_corner);
EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
mask_isolation_1.rounded_corner_bounds);
EXPECT_EQ(ContentLayerAt(2), content2);
EXPECT_EQ(c1_id, content2->clip_tree_index());
int mask_isolation_2_id = content2->effect_tree_index();
const cc::EffectNode& mask_isolation_2 =
*GetPropertyTrees().effect_tree.Node(mask_isolation_2_id);
EXPECT_NE(mask_isolation_0_id, mask_isolation_2_id);
EXPECT_NE(mask_isolation_1_id, mask_isolation_2_id);
ASSERT_EQ(e0_id, mask_isolation_2.parent_id);
EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_2.blend_mode);
EXPECT_TRUE(mask_isolation_2.is_fast_rounded_corner);
EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
mask_isolation_2.rounded_corner_bounds);
return;
}
// Expectation in effect stack diagram:
// l3
// l1 l2 [ mask_effect_1 ] l5
......@@ -3123,6 +3417,73 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipDelegateBlending) {
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
if (RuntimeEnabledFeatures::FastBorderRadiusEnabled()) {
// Expectation in effect stack diagram:
// l1 l2 l3 l5
// l0 [ e1 ] l4
// [ mask_isolation_0 ][ mask_isolation_1 ][ mask_isolation_2 ]
// [ e0 ]
// Three content layers.
ASSERT_EQ(3u, RootLayer()->children().size());
ASSERT_EQ(3u, ContentLayerCount());
// There are still "synthesized layers" but they're null.
ASSERT_EQ(3u, SynthesizedClipLayerCount());
EXPECT_FALSE(SynthesizedClipLayerAt(0));
EXPECT_FALSE(SynthesizedClipLayerAt(1));
EXPECT_FALSE(SynthesizedClipLayerAt(2));
const cc::Layer* content0 = RootLayer()->children()[0].get();
const cc::Layer* content1 = RootLayer()->children()[1].get();
const cc::Layer* content2 = RootLayer()->children()[2].get();
constexpr int c0_id = 1;
constexpr int e0_id = 1;
EXPECT_EQ(ContentLayerAt(0), content0);
int c1_id = content0->clip_tree_index();
const cc::ClipNode& cc_c1 = *GetPropertyTrees().clip_tree.Node(c1_id);
EXPECT_EQ(gfx::RectF(50, 50, 300, 200), cc_c1.clip);
ASSERT_EQ(c0_id, cc_c1.parent_id);
int mask_isolation_0_id = content0->effect_tree_index();
const cc::EffectNode& mask_isolation_0 =
*GetPropertyTrees().effect_tree.Node(mask_isolation_0_id);
ASSERT_EQ(e0_id, mask_isolation_0.parent_id);
EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode);
EXPECT_TRUE(mask_isolation_0.is_fast_rounded_corner);
EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
mask_isolation_0.rounded_corner_bounds);
EXPECT_EQ(ContentLayerAt(1), content1);
EXPECT_EQ(c1_id, content1->clip_tree_index());
int e1_id = content1->effect_tree_index();
const cc::EffectNode& cc_e1 = *GetPropertyTrees().effect_tree.Node(e1_id);
EXPECT_EQ(SkBlendMode::kSrcOver, cc_e1.blend_mode);
int mask_isolation_1_id = cc_e1.parent_id;
const cc::EffectNode& mask_isolation_1 =
*GetPropertyTrees().effect_tree.Node(mask_isolation_1_id);
EXPECT_NE(mask_isolation_0_id, mask_isolation_1_id);
ASSERT_EQ(e0_id, mask_isolation_1.parent_id);
EXPECT_EQ(SkBlendMode::kMultiply, mask_isolation_1.blend_mode);
EXPECT_TRUE(mask_isolation_1.is_fast_rounded_corner);
EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
mask_isolation_1.rounded_corner_bounds);
EXPECT_EQ(ContentLayerAt(2), content2);
EXPECT_EQ(c1_id, content2->clip_tree_index());
int mask_isolation_2_id = content2->effect_tree_index();
const cc::EffectNode& mask_isolation_2 =
*GetPropertyTrees().effect_tree.Node(mask_isolation_2_id);
EXPECT_NE(mask_isolation_0_id, mask_isolation_2_id);
EXPECT_NE(mask_isolation_1_id, mask_isolation_2_id);
ASSERT_EQ(e0_id, mask_isolation_2.parent_id);
EXPECT_EQ(SkBlendMode::kSrcOver, mask_isolation_0.blend_mode);
EXPECT_TRUE(mask_isolation_2.is_fast_rounded_corner);
EXPECT_EQ(gfx::RRectF(50, 50, 300, 200, 5),
mask_isolation_2.rounded_corner_bounds);
return;
}
// Expectation in effect stack diagram:
// l1 l2 l3 l5
// l0 [ mask_effect_0 ][ e1 ][ mask_effect_1 ] l4 [ mask_effect_2 ]
......@@ -3898,6 +4259,31 @@ TEST_P(PaintArtifactCompositorTest, Non2dAxisAlignedClip) {
EXPECT_EQ(cc_effect->clip_id, cc_clip->parent_id);
}
TEST_P(PaintArtifactCompositorTest, Non2dAxisAlignedRoundedRectClip) {
auto rotate = CreateTransform(t0(), TransformationMatrix().Rotate(45));
FloatSize corner(5, 5);
FloatRoundedRect rounded_clip(FloatRect(50, 50, 50, 50), corner, corner,
corner, corner);
auto clip = CreateClip(c0(), *rotate, rounded_clip);
auto opacity = CreateOpacityEffect(
e0(), 0.5f, CompositingReason::kActiveOpacityAnimation);
TestPaintArtifact artifact;
artifact.Chunk(t0(), *clip, *opacity)
.RectDrawing(FloatRect(50, 50, 50, 50), Color::kWhite);
Update(artifact.Build());
ASSERT_EQ(1u, ContentLayerCount());
// We should create a synthetic effect node for the non-2d-axis-aligned clip.
int clip_id = ContentLayerAt(0)->clip_tree_index();
const auto* cc_clip = GetPropertyTrees().clip_tree.Node(clip_id);
int effect_id = ContentLayerAt(0)->effect_tree_index();
const auto* cc_effect = GetPropertyTrees().effect_tree.Node(effect_id);
EXPECT_OPACITY(effect_id, 1.f, kHasRenderSurface);
EXPECT_OPACITY(cc_effect->parent_id, 0.5f, kNoRenderSurface);
EXPECT_EQ(cc_effect->clip_id, cc_clip->id);
}
TEST_P(PaintArtifactCompositorTest,
Non2dAxisAlignedClipUnderLaterRenderSurface) {
auto rotate1 =
......
......@@ -761,20 +761,19 @@ static bool IsNodeOnAncestorChain(const ClipPaintPropertyNode& find,
return false;
}
base::Optional<PropertyTreeManager::CcEffectType>
PropertyTreeManager::NeedsSyntheticEffect(
PropertyTreeManager::CcEffectType PropertyTreeManager::SyntheticEffectType(
const ClipPaintPropertyNode& clip) const {
unsigned effect_type = CcEffectType::kEffect;
if (clip.ClipRect().IsRounded() || clip.ClipPath())
return CcEffectType::kSyntheticForNonTrivialClip;
effect_type |= CcEffectType::kSyntheticForNonTrivialClip;
// Cc requires that a rectangluar clip is 2d-axis-aligned with the render
// surface to correctly apply the clip.
if (current_.may_be_2d_axis_misaligned_to_render_surface |
TransformsMayBe2dAxisMisaligned(clip.LocalTransformSpace(),
current_.Transform()))
return CcEffectType::kSyntheticFor2dAxisAlignment;
return base::nullopt;
effect_type |= CcEffectType::kSyntheticFor2dAxisAlignment;
return static_cast<CcEffectType>(effect_type);
}
SkBlendMode PropertyTreeManager::SynthesizeCcEffectsForClipsIfNeeded(
......@@ -821,8 +820,8 @@ SkBlendMode PropertyTreeManager::SynthesizeCcEffectsForClipsIfNeeded(
Vector<PendingClip> pending_clips;
for (; target_clip && target_clip != current_.clip;
target_clip = SafeUnalias(target_clip->Parent())) {
if (auto type = NeedsSyntheticEffect(*target_clip))
pending_clips.emplace_back(PendingClip{target_clip, *type});
if (auto type = SyntheticEffectType(*target_clip))
pending_clips.emplace_back(PendingClip{target_clip, type});
}
if (!target_clip) {
......@@ -844,7 +843,7 @@ SkBlendMode PropertyTreeManager::SynthesizeCcEffectsForClipsIfNeeded(
// surface which is axis-aligned with the clip.
cc::EffectNode& synthetic_effect = *GetEffectTree().Node(
GetEffectTree().Insert(cc::EffectNode(), current_.effect_id));
if (pending_clip.type == CcEffectType::kSyntheticForNonTrivialClip) {
if (pending_clip.type & CcEffectType::kSyntheticForNonTrivialClip) {
synthetic_effect.clip_id = EnsureCompositorClipNode(*pending_clip.clip);
// For non-trivial clip, isolation_effect.stable_id will be assigned later
// when the effect is closed. For now the default value INVALID_STABLE_ID
......@@ -863,23 +862,23 @@ SkBlendMode PropertyTreeManager::SynthesizeCcEffectsForClipsIfNeeded(
synthetic_effect.transform_id = EnsureCompositorTransformNode(transform);
synthetic_effect.double_sided = !transform.IsBackfaceHidden();
if (pending_clip.type & CcEffectType::kSyntheticForNonTrivialClip) {
if (RuntimeEnabledFeatures::FastBorderRadiusEnabled()) {
synthetic_effect.rounded_corner_bounds =
gfx::RRectF(pending_clip.clip->ClipRect());
synthetic_effect.is_fast_rounded_corner = true;
} else {
if (pending_clip.type == CcEffectType::kSyntheticForNonTrivialClip) {
synthetic_effect.render_surface_reason =
pending_clip.clip->ClipRect().IsRounded()
? cc::RenderSurfaceReason::kRoundedCorner
: cc::RenderSurfaceReason::kClipPath;
} else {
synthetic_effect.render_surface_reason =
cc::RenderSurfaceReason::kClipAxisAlignment;
}
pending_synthetic_mask_layers_.insert(synthetic_effect.id);
}
if (pending_clip.type & CcEffectType::kSyntheticFor2dAxisAlignment) {
synthetic_effect.render_surface_reason =
cc::RenderSurfaceReason::kClipAxisAlignment;
}
// Clip and kDstIn do not commute. This shall never be reached because
// kDstIn is only used internally to implement CSS clip-path and mask,
......
......@@ -173,31 +173,28 @@ class PropertyTreeManager {
cc::TransformNode&,
const TransformPaintPropertyNode&);
bool IsCurrentCcEffectSynthetic() const {
return current_.effect_type != CcEffectType::kEffect;
}
bool IsCurrentCcEffectSynthetic() const { return current_.effect_type; }
bool IsCurrentCcEffectSyntheticForNonTrivialClip() const {
return current_.effect_type == CcEffectType::kSyntheticForNonTrivialClip;
return current_.effect_type & CcEffectType::kSyntheticForNonTrivialClip;
}
// The type of operation the current cc effect node applies.
enum class CcEffectType {
enum CcEffectType {
// The cc effect corresponds to a Blink effect node.
kEffect,
kEffect = 0,
// The cc effect is synthetic for a blink clip node that has to be
// rasterized because the clip is non-trivial.
kSyntheticForNonTrivialClip,
kSyntheticForNonTrivialClip = 1 << 0,
// The cc effect is synthetic to create a render surface that is
// 2d-axis-aligned with a blink clip node that is non-2d-axis-aligned
// in the the original render surface. Cc requires a rectangular clip to be
// 2d-axis-aligned with the render surface to correctly apply the clip.
// TODO(crbug.com/504464): This will be changed when we move render surface
// decision logic into the cc compositor thread.
kSyntheticFor2dAxisAlignment,
kSyntheticFor2dAxisAlignment = 1 << 1
};
base::Optional<CcEffectType> NeedsSyntheticEffect(
const ClipPaintPropertyNode&) const;
CcEffectType SyntheticEffectType(const ClipPaintPropertyNode&) const;
void SetCurrentEffectState(const cc::EffectNode&,
CcEffectType,
......
......@@ -15,19 +15,22 @@ enum {
kBlinkGenPropertyTrees = 1 << 0,
kCompositeAfterPaint = 1 << 1,
kUnderInvalidationChecking = 1 << 2,
kFastBorderRadius = 1 << 3,
};
class PaintTestConfigurations
: public testing::WithParamInterface<unsigned>,
private ScopedBlinkGenPropertyTreesForTest,
private ScopedCompositeAfterPaintForTest,
private ScopedPaintUnderInvalidationCheckingForTest {
private ScopedPaintUnderInvalidationCheckingForTest,
private ScopedFastBorderRadiusForTest {
public:
PaintTestConfigurations()
: ScopedBlinkGenPropertyTreesForTest(GetParam() & kBlinkGenPropertyTrees),
ScopedCompositeAfterPaintForTest(GetParam() & kCompositeAfterPaint),
ScopedPaintUnderInvalidationCheckingForTest(
GetParam() & kUnderInvalidationChecking) {}
ScopedPaintUnderInvalidationCheckingForTest(GetParam() &
kUnderInvalidationChecking),
ScopedFastBorderRadiusForTest(GetParam() & kFastBorderRadius) {}
~PaintTestConfigurations() {
// Must destruct all objects before toggling back feature flags.
WebHeap::CollectAllGarbageForTesting();
......@@ -49,7 +52,8 @@ class PaintTestConfigurations
INSTANTIATE_TEST_SUITE_P( \
All, test_class, \
::testing::Values(kBlinkGenPropertyTrees, \
kBlinkGenPropertyTrees | kCompositeAfterPaint))
kBlinkGenPropertyTrees | kCompositeAfterPaint, \
kBlinkGenPropertyTrees | kFastBorderRadius))
} // 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