Skip to content

Commit

Permalink
Manually revert: cc: Support ClipRRect in SolidColorAnalyzer
Browse files Browse the repository at this point in the history
This CL reverts a previous CL here:
https://chromium-review.googlesource.com/c/chromium/src/+/591913

The previous CL caused a regression on Mac. GL renderer has
difficulties dealing with RPDQs converted from
SolidColorDrawQuads, this CL will make mask layer produce
solid quads. We need to keep it reverted before we fix the
gl renderer bug.

NOTRY=true

Bug: 760807
Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel
Change-Id: I844d02886329acbbbebd98200f8d2f90681adb8a
Reviewed-on: https://chromium-review.googlesource.com/653317
Commit-Queue: Xida Chen <xidachen@chromium.org>
Reviewed-by: Vladimir Levin <vmpstr@chromium.org>
Reviewed-by: Xianda Sun <sunxd@chromium.org>
Cr-Commit-Position: refs/heads/master@{#500036}
  • Loading branch information
xidachen authored and Commit Bot committed Sep 6, 2017
1 parent 7232806 commit 8d1900b
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 154 deletions.
77 changes: 23 additions & 54 deletions cc/paint/solid_color_analyzer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,9 @@ bool IsSolidColorPaint(const PaintFlags& flags) {
flags.getStyle() == PaintFlags::kFill_Style;
}

// Returns true if the specified |drawn_shape| will cover the entire canvas
// and that the canvas is not clipped (i.e. it covers ALL of the canvas).
template <typename T>
bool IsFullQuad(const SkCanvas& canvas, const T& drawn_shape) {
if (!canvas.isClipRect())
return false;

// Returns true if the specified drawn_rect will cover the entire canvas, and
// that the canvas is not clipped (i.e. it covers ALL of the canvas).
bool IsFullQuad(const SkCanvas& canvas, const SkRect& drawn_rect) {
SkIRect clip_irect;
if (!canvas.getDeviceClipBounds(&clip_irect))
return false;
Expand All @@ -66,13 +62,11 @@ bool IsFullQuad(const SkCanvas& canvas, const T& drawn_shape) {
if (!matrix.rectStaysRect())
return false;

SkMatrix inverse;
if (!matrix.invert(&inverse))
return false;

SkRect clip_rect = SkRect::Make(clip_irect);
inverse.mapRect(&clip_rect, clip_rect);
return drawn_shape.contains(clip_rect);
SkRect device_rect;
matrix.mapRect(&device_rect, drawn_rect);
SkRect clip_rect;
clip_rect.set(clip_irect);
return device_rect.contains(clip_rect);
}

void CheckIfSolidColor(const SkCanvas& canvas,
Expand Down Expand Up @@ -103,19 +97,18 @@ void CheckIfSolidColor(const SkCanvas& canvas,
}
}

template <typename T>
void CheckIfSolidShape(const SkCanvas& canvas,
const T& shape,
const PaintFlags& flags,
bool* is_solid_color,
bool* is_transparent,
SkColor* color) {
void CheckIfSolidRect(const SkCanvas& canvas,
const SkRect& rect,
const PaintFlags& flags,
bool* is_solid_color,
bool* is_transparent,
SkColor* color) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
"SolidColorAnalyzer::CheckIfSolidShape");
"SolidColorAnalyzer::HandleDrawRect");
if (flags.nothingToDraw())
return;

bool does_cover_canvas = IsFullQuad(canvas, shape);
bool does_cover_canvas = IsFullQuad(canvas, rect);
SkBlendMode blendmode = flags.getBlendMode();
if (does_cover_canvas && ActsLikeClear(blendmode, flags.getAlpha()))
*is_transparent = true;
Expand All @@ -130,13 +123,6 @@ void CheckIfSolidShape(const SkCanvas& canvas,
}
}

bool CheckIfRRectClipCoversCanvas(const SkCanvas& canvas,
const SkRRect& rrect) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
"SolidColorAnalyzer::CheckIfRRectClipCoversCanvas");
return IsFullQuad(canvas, rrect);
}

} // namespace

base::Optional<SkColor> SolidColorAnalyzer::DetermineIfSolidColor(
Expand Down Expand Up @@ -174,7 +160,7 @@ base::Optional<SkColor> SolidColorAnalyzer::DetermineIfSolidColor(
stack.emplace_back(PaintOpBuffer::CompositeIterator(buffer, offsets),
canvas.getTotalMatrix(), canvas.getSaveCount());

int num_draw_ops = 0;
int num_ops = 0;
while (!stack.empty()) {
auto& frame = stack.back();
if (!frame.iter) {
Expand Down Expand Up @@ -205,15 +191,7 @@ base::Optional<SkColor> SolidColorAnalyzer::DetermineIfSolidColor(
case PaintOpType::DrawOval:
case PaintOpType::DrawPath:
return base::nullopt;
// TODO(vmpstr): Add more tests on exceeding max_ops_to_analyze.
case PaintOpType::DrawRRect: {
if (++num_draw_ops > max_ops_to_analyze)
return base::nullopt;
const DrawRRectOp* rrect_op = static_cast<const DrawRRectOp*>(op);
CheckIfSolidShape(canvas, rrect_op->rrect, rrect_op->flags, &is_solid,
&is_transparent, &color);
break;
}
case PaintOpType::DrawRRect:
case PaintOpType::DrawTextBlob:
// Anything that has to do a save layer is probably not solid. As it will
// likely need more than one draw op.
Expand All @@ -224,27 +202,18 @@ base::Optional<SkColor> SolidColorAnalyzer::DetermineIfSolidColor(
// cover the canvas.
// TODO(vmpstr): We could investigate handling these.
case PaintOpType::ClipPath:
case PaintOpType::ClipRRect:
return base::nullopt;
case PaintOpType::ClipRRect: {
const ClipRRectOp* rrect_op = static_cast<const ClipRRectOp*>(op);
bool does_cover_canvas =
CheckIfRRectClipCoversCanvas(canvas, rrect_op->rrect);
// If the clip covers the full canvas, we can treat it as if there's no
// clip at all and continue, otherwise this is no longer a solid color.
if (!does_cover_canvas)
return base::nullopt;
break;
}
case PaintOpType::DrawRect: {
if (++num_draw_ops > max_ops_to_analyze)
if (++num_ops > max_ops_to_analyze)
return base::nullopt;
const DrawRectOp* rect_op = static_cast<const DrawRectOp*>(op);
CheckIfSolidShape(canvas, rect_op->rect, rect_op->flags, &is_solid,
&is_transparent, &color);
CheckIfSolidRect(canvas, rect_op->rect, rect_op->flags, &is_solid,
&is_transparent, &color);
break;
}
case PaintOpType::DrawColor: {
if (++num_draw_ops > max_ops_to_analyze)
if (++num_ops > max_ops_to_analyze)
return base::nullopt;
const DrawColorOp* color_op = static_cast<const DrawColorOp*>(op);
CheckIfSolidColor(canvas, color_op->color, color_op->mode, &is_solid,
Expand Down
100 changes: 0 additions & 100 deletions cc/paint/solid_color_analyzer_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,6 @@ class SolidColorAnalyzerTest : public testing::Test {
buffer_ = nullptr;
}

void Reset() {
TearDown();
SetUp();
}

void Initialize(const gfx::Rect& rect = gfx::Rect(0, 0, 100, 100)) {
canvas_.emplace(display_item_list_.get(), gfx::RectToSkRect(rect));
rect_ = rect;
Expand Down Expand Up @@ -132,21 +127,6 @@ TEST_F(SolidColorAnalyzerTest, DrawRect) {
EXPECT_EQ(color, GetColor());
}

// TODO(vmpstr): Generalize the DrawRect test cases so that we can test both
// Rect and RRect.
TEST_F(SolidColorAnalyzerTest, DrawRRect) {
SkRect rect = SkRect::MakeWH(200, 200);
SkRRect rrect;
rrect.setRectXY(rect, 5, 5);
gfx::Rect canvas_rect(5, 5, 190, 190);
Initialize(canvas_rect);
PaintFlags flags;
SkColor color = SkColorSetARGB(255, 11, 22, 33);
flags.setColor(color);
canvas()->drawRRect(rrect, flags);
EXPECT_EQ(color, GetColor());
}

TEST_F(SolidColorAnalyzerTest, DrawRectClipped) {
Initialize();
PaintFlags flags;
Expand Down Expand Up @@ -298,85 +278,5 @@ TEST_F(SolidColorAnalyzerTest, SaveLayer) {
EXPECT_FALSE(IsSolidColor());
}

TEST_F(SolidColorAnalyzerTest, ClipRRectCoversCanvas) {
SkVector radii[4] = {
SkVector::Make(10.0, 15.0), SkVector::Make(20.0, 25.0),
SkVector::Make(30.0, 35.0), SkVector::Make(40.0, 45.0),
};

SkVector radii_scale[4] = {
SkVector::Make(100.0, 150.0), SkVector::Make(200.0, 250.0),
SkVector::Make(300.0, 350.0), SkVector::Make(400.0, 450.0),
};

int rr_size = 600;
int canvas_size = 255;
gfx::Rect canvas_rect(canvas_size, canvas_size);
PaintFlags flags;
flags.setColor(SK_ColorWHITE);

struct {
SkVector offset;
SkVector offset_scale;
bool expected;
} cases[] = {
// Not within bounding box of |rr|.
{SkVector::Make(100, 100), SkVector::Make(100, 100), false},

// Intersects UL corner.
{SkVector::Make(0, 0), SkVector::Make(0, 0), false},

// Between UL and UR.
{SkVector::Make(-50, 0), SkVector::Make(-50, -15), true},

// Intersects UR corner.
{SkVector::Make(canvas_size - rr_size, 0),
SkVector::Make(canvas_size - rr_size, 0), false},

// Between UR and LR.
{SkVector::Make(canvas_size - rr_size, -50), SkVector::Make(-305, -80),
true},

// Intersects LR corner.
{SkVector::Make(canvas_size - rr_size, canvas_size - rr_size),
SkVector::Make(canvas_size - rr_size, canvas_size - rr_size), false},

// Between LL and LR
{SkVector::Make(-50, canvas_size - rr_size), SkVector::Make(-205, -310),
true},

// Intersects LL corner
{SkVector::Make(0, canvas_size - rr_size),
SkVector::Make(0, canvas_size - rr_size), false},

// Between UL and LL
{SkVector::Make(0, -50), SkVector::Make(-15, -60), true},

// In center
{SkVector::Make(-100, -100), SkVector::Make(-100, -100), true},
};

for (int case_scale = 0; case_scale < 2; ++case_scale) {
bool scaled = case_scale > 0;
for (size_t i = 0; i < arraysize(cases); ++i) {
Reset();
Initialize(canvas_rect);

SkRect bounding_rect = SkRect::MakeXYWH(
scaled ? cases[i].offset_scale.x() : cases[i].offset.x(),
scaled ? cases[i].offset_scale.y() : cases[i].offset.y(), rr_size,
rr_size);

SkRRect rr;
rr.setRectRadii(bounding_rect, scaled ? radii_scale : radii);

canvas()->clipRRect(rr, SkClipOp::kIntersect, false);
canvas()->drawRect(RectToSkRect(canvas_rect), flags);
EXPECT_EQ(cases[i].expected, IsSolidColor())
<< "Case " << i << ", " << scaled << " failed.";
}
}
}

} // namespace
} // namespace cc

0 comments on commit 8d1900b

Please sign in to comment.