Skip to content

Commit

Permalink
Don't allow shader-based rounded corner in the presence of rotation.
Browse files Browse the repository at this point in the history
In particular, non-axis-aligned transforms are not allowed.

Bug: 968255

Change-Id: I01151d08fe1f3a6fdf1aad95950c0be672776cc8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1636437
Reviewed-by: Mason Freed <masonfreed@chromium.org>
Commit-Queue: Chris Harrelson <chrishtr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#664938}
  • Loading branch information
chrishtr authored and Commit Bot committed May 30, 2019
1 parent 904ac73 commit aa069eb
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2606,6 +2606,150 @@ TEST_P(PaintArtifactCompositorTest, SynthesizedClipSimple) {
EXPECT_TRUE(clip_mask0->DrawsContent());
}

TEST_P(PaintArtifactCompositorTest, SynthesizedClipRotatedNotSupported) {
// Synthesized clips are not currently supported when rotated (or any
// transform that is not 2D axis-aligned).
auto transform = CreateTransform(t0(), TransformationMatrix().Rotate(45),
FloatPoint3D(100, 100, 0),
CompositingReason::k3DTransform);

FloatSize corner(5, 5);
FloatRoundedRect rrect(FloatRect(50, 50, 300, 200), corner, corner, corner,
corner);
auto c1 = CreateClip(c0(), *transform, rrect);

TestPaintArtifact artifact;
artifact.Chunk(*transform, *c1, e0())
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());

// Expectation in effect stack diagram:
// l1
// l0 [ mask_effect_0 ]
// [ mask_isolation_0 ]
// [ e0 ]
// One content layer.
ASSERT_EQ(2u, RootLayer()->children().size());
ASSERT_EQ(1u, ContentLayerCount());
ASSERT_EQ(1u, SynthesizedClipLayerCount());

const cc::Layer* content0 = RootLayer()->children()[0].get();
const cc::Layer* clip_mask0 = RootLayer()->children()[1].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.HasRenderSurface());

EXPECT_EQ(SynthesizedClipLayerAt(0), clip_mask0);
EXPECT_EQ(gfx::Size(300, 200), clip_mask0->bounds());
EXPECT_EQ(c1_id, clip_mask0->clip_tree_index());
int mask_effect_0_id = clip_mask0->effect_tree_index();
const cc::EffectNode& mask_effect_0 =
*GetPropertyTrees().effect_tree.Node(mask_effect_0_id);
ASSERT_EQ(mask_isolation_0_id, mask_effect_0.parent_id);
EXPECT_EQ(SkBlendMode::kDstIn, mask_effect_0.blend_mode);
}

TEST_P(PaintArtifactCompositorTest, SynthesizedClip90DegRotationSupported) {
// 90-degree rotations are axis-aligned, and so the synthetic clip is
// supported.
auto transform = CreateTransform(t0(), TransformationMatrix().Rotate(90),
FloatPoint3D(100, 100, 0),
CompositingReason::k3DTransform);

FloatSize corner(5, 5);
FloatRoundedRect rrect(FloatRect(50, 50, 300, 200), corner, corner, corner,
corner);
auto c1 = CreateClip(c0(), *transform, rrect);

TestPaintArtifact artifact;
artifact.Chunk(*transform, *c1, e0())
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());

if (RuntimeEnabledFeatures::FastBorderRadiusEnabled()) {
// Expectation in effect stack diagram:
// 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);
EXPECT_FALSE(mask_isolation_0.HasRenderSurface());
return;
}

// Expectation in effect stack diagram:
// l1
// l0 [ mask_effect_0 ]
// [ mask_isolation_0 ]
// [ e0 ]
// One content layer.
ASSERT_EQ(2u, RootLayer()->children().size());
ASSERT_EQ(1u, ContentLayerCount());
ASSERT_EQ(1u, SynthesizedClipLayerCount());

const cc::Layer* content0 = RootLayer()->children()[0].get();
const cc::Layer* clip_mask0 = RootLayer()->children()[1].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.HasRenderSurface());

EXPECT_EQ(SynthesizedClipLayerAt(0), clip_mask0);
EXPECT_EQ(gfx::Size(300, 200), clip_mask0->bounds());
EXPECT_EQ(c1_id, clip_mask0->clip_tree_index());
int mask_effect_0_id = clip_mask0->effect_tree_index();
const cc::EffectNode& mask_effect_0 =
*GetPropertyTrees().effect_tree.Node(mask_effect_0_id);
ASSERT_EQ(mask_isolation_0_id, mask_effect_0.parent_id);
EXPECT_EQ(SkBlendMode::kDstIn, mask_effect_0.blend_mode);
}

TEST_P(PaintArtifactCompositorTest,
SynthesizedClipSimpleFastBorderNotSupported1) {
// This tests the simplist case that a single layer needs to be clipped
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -803,10 +803,15 @@ void PropertyTreeManager::ForceRenderSurfaceIfSyntheticRoundedCornerClip(
}
}

static bool SupportsShaderBasedRoundedCorner(const FloatRoundedRect& rect) {
bool PropertyTreeManager::SupportsShaderBasedRoundedCorner(
const FloatRoundedRect& rect,
PropertyTreeManager::CcEffectType type) {
if (!RuntimeEnabledFeatures::FastBorderRadiusEnabled())
return false;

if (type & CcEffectType::kSyntheticFor2dAxisAlignment)
return false;

auto WidthAndHeightAreTheSame = [](const FloatSize& size) {
return size.Width() == size.Height();
};
Expand Down Expand Up @@ -915,7 +920,8 @@ SkBlendMode PropertyTreeManager::SynthesizeCcEffectsForClipsIfNeeded(
synthetic_effect.transform_id = EnsureCompositorTransformNode(transform);
synthetic_effect.double_sided = !transform.IsBackfaceHidden();
if (pending_clip.type & CcEffectType::kSyntheticForNonTrivialClip) {
if (SupportsShaderBasedRoundedCorner(pending_clip.clip->ClipRect())) {
if (SupportsShaderBasedRoundedCorner(pending_clip.clip->ClipRect(),
pending_clip.type)) {
synthetic_effect.rounded_corner_bounds =
gfx::RRectF(pending_clip.clip->ClipRect());
synthetic_effect.is_fast_rounded_corner = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ enum class RenderSurfaceReason : uint8_t;
namespace blink {

class ClipPaintPropertyNode;
class FloatRoundedRect;
class LayerListBuilder;
class EffectPaintPropertyNode;
class ScrollPaintPropertyNode;
Expand Down Expand Up @@ -151,6 +152,9 @@ class PropertyTreeManager {
kSyntheticFor2dAxisAlignment = 1 << 1
};

static bool SupportsShaderBasedRoundedCorner(const FloatRoundedRect& rect,
CcEffectType type);

struct EffectState {
// The cc effect node that has the corresponding drawing state to the
// effect and clip state from the last
Expand Down

0 comments on commit aa069eb

Please sign in to comment.