Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

make sure DisplayListCanvasRecorder updates clip bounds methods #38325

Merged
merged 1 commit into from
Dec 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion display_list/display_list_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ DisplayListBuilder::DisplayListBuilder(const SkRect& cull_rect,
accumulator_ = std::make_unique<RectBoundsAccumulator>();
}

layer_stack_.emplace_back(SkM44(), SkMatrix::I(), cull_rect);
// isEmpty protects us against NaN as we normalize any empty cull rects
SkRect cull = cull_rect.isEmpty() ? SkRect::MakeEmpty() : cull_rect;
layer_stack_.emplace_back(SkM44(), SkMatrix::I(), cull);
current_layer_ = &layer_stack_.back();
}

Expand Down
11 changes: 9 additions & 2 deletions display_list/display_list_canvas_recorder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,12 @@ namespace flutter {

DisplayListCanvasRecorder::DisplayListCanvasRecorder(const SkRect& bounds,
bool prepare_rtree)
: SkCanvasVirtualEnforcer(bounds.width(), bounds.height()),
builder_(sk_make_sp<DisplayListBuilder>(bounds, prepare_rtree)) {}
: SkCanvasVirtualEnforcer(0, 0),
builder_(sk_make_sp<DisplayListBuilder>(bounds, prepare_rtree)) {
// isEmpty protects us against NaN as we normalize any empty cull rects
SkIRect cull = bounds.isEmpty() ? SkIRect::MakeEmpty() : bounds.roundOut();
SkCanvasVirtualEnforcer::resetCanvas(cull);
}

sk_sp<DisplayList> DisplayListCanvasRecorder::Build() {
CHECK_DISPOSE(nullptr);
Expand Down Expand Up @@ -57,20 +61,23 @@ void DisplayListCanvasRecorder::onClipRect(const SkRect& rect,
CHECK_DISPOSE();
builder_->clipRect(rect, clip_op,
edge_style == ClipEdgeStyle::kSoft_ClipEdgeStyle);
SkCanvasVirtualEnforcer::onClipRect(rect, clip_op, edge_style);
}
void DisplayListCanvasRecorder::onClipRRect(const SkRRect& rrect,
SkClipOp clip_op,
ClipEdgeStyle edge_style) {
CHECK_DISPOSE();
builder_->clipRRect(rrect, clip_op,
edge_style == ClipEdgeStyle::kSoft_ClipEdgeStyle);
SkCanvasVirtualEnforcer::onClipRRect(rrect, clip_op, edge_style);
}
void DisplayListCanvasRecorder::onClipPath(const SkPath& path,
SkClipOp clip_op,
ClipEdgeStyle edge_style) {
CHECK_DISPOSE();
builder_->clipPath(path, clip_op,
edge_style == ClipEdgeStyle::kSoft_ClipEdgeStyle);
SkCanvasVirtualEnforcer::onClipPath(path, clip_op, edge_style);
}

void DisplayListCanvasRecorder::willSave() {
Expand Down
106 changes: 106 additions & 0 deletions display_list/display_list_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,112 @@ TEST(DisplayList, CallMethodAfterBuild) {
}
#endif // NDEBUG

TEST(DisplayList, RecorderInitialClipBounds) {
SkRect cull_rect = SkRect::MakeWH(100, 100);
SkIRect clip_bounds = SkIRect::MakeWH(100, 100);
DisplayListCanvasRecorder recorder(cull_rect);
SkCanvas* canvas = &recorder;
ASSERT_EQ(canvas->getDeviceClipBounds(), clip_bounds);
}

TEST(DisplayList, RecorderInitialClipBoundsNaN) {
SkRect cull_rect = SkRect::MakeWH(SK_ScalarNaN, SK_ScalarNaN);
SkIRect clip_bounds = SkIRect::MakeEmpty();
DisplayListCanvasRecorder recorder(cull_rect);
SkCanvas* canvas = &recorder;
ASSERT_EQ(canvas->getDeviceClipBounds(), clip_bounds);
}

TEST(DisplayList, RecorderClipBoundsAfterClipRect) {
SkRect cull_rect = SkRect::MakeWH(100, 100);
SkRect clip_rect = SkRect::MakeLTRB(10, 10, 20, 20);
SkIRect clip_bounds = SkIRect::MakeLTRB(10, 10, 20, 20);
DisplayListCanvasRecorder recorder(cull_rect);
SkCanvas* canvas = &recorder;
canvas->clipRect(clip_rect);
ASSERT_EQ(canvas->getDeviceClipBounds(), clip_bounds);
}

TEST(DisplayList, RecorderClipBoundsAfterClipRRect) {
SkRect cull_rect = SkRect::MakeWH(100, 100);
SkRect clip_rect = SkRect::MakeLTRB(10, 10, 20, 20);
SkRRect clip_rrect = SkRRect::MakeRectXY(clip_rect, 2, 2);
SkIRect clip_bounds = SkIRect::MakeLTRB(10, 10, 20, 20);
DisplayListCanvasRecorder recorder(cull_rect);
SkCanvas* canvas = &recorder;
canvas->clipRRect(clip_rrect);
ASSERT_EQ(canvas->getDeviceClipBounds(), clip_bounds);
}

TEST(DisplayList, RecorderClipBoundsAfterClipPath) {
SkRect cull_rect = SkRect::MakeWH(100, 100);
SkPath clip_path = SkPath().addRect(10, 10, 15, 15).addRect(15, 15, 20, 20);
SkIRect clip_bounds = SkIRect::MakeLTRB(10, 10, 20, 20);
DisplayListCanvasRecorder recorder(cull_rect);
SkCanvas* canvas = &recorder;
canvas->clipPath(clip_path);
ASSERT_EQ(canvas->getDeviceClipBounds(), clip_bounds);
}

TEST(DisplayList, RecorderInitialClipBoundsNonZero) {
SkRect cull_rect = SkRect::MakeLTRB(10, 10, 100, 100);
SkIRect clip_bounds = SkIRect::MakeLTRB(10, 10, 100, 100);
DisplayListCanvasRecorder recorder(cull_rect);
SkCanvas* canvas = &recorder;
ASSERT_EQ(canvas->getDeviceClipBounds(), clip_bounds);
}

TEST(DisplayList, BuilderInitialClipBounds) {
SkRect cull_rect = SkRect::MakeWH(100, 100);
SkRect clip_bounds = SkRect::MakeWH(100, 100);
DisplayListBuilder builder(cull_rect);
ASSERT_EQ(builder.getDestinationClipBounds(), clip_bounds);
}

TEST(DisplayList, BuilderInitialClipBoundsNaN) {
SkRect cull_rect = SkRect::MakeWH(SK_ScalarNaN, SK_ScalarNaN);
SkRect clip_bounds = SkRect::MakeEmpty();
DisplayListBuilder builder(cull_rect);
ASSERT_EQ(builder.getDestinationClipBounds(), clip_bounds);
}

TEST(DisplayList, BuilderClipBoundsAfterClipRect) {
SkRect cull_rect = SkRect::MakeWH(100, 100);
SkRect clip_rect = SkRect::MakeLTRB(10, 10, 20, 20);
SkRect clip_bounds = SkRect::MakeLTRB(10, 10, 20, 20);
DisplayListBuilder builder(cull_rect);
builder.clipRect(clip_rect, SkClipOp::kIntersect, false);
ASSERT_EQ(builder.getDestinationClipBounds(), clip_bounds);
}

TEST(DisplayList, BuilderClipBoundsAfterClipRRect) {
SkRect cull_rect = SkRect::MakeWH(100, 100);
SkRect clip_rect = SkRect::MakeLTRB(10, 10, 20, 20);
SkRRect clip_rrect = SkRRect::MakeRectXY(clip_rect, 2, 2);
SkRect clip_bounds = SkRect::MakeLTRB(10, 10, 20, 20);
DisplayListBuilder builder(cull_rect);
builder.clipRRect(clip_rrect, SkClipOp::kIntersect, false);
ASSERT_EQ(builder.getDestinationClipBounds(), clip_bounds);
}

TEST(DisplayList, BuilderClipBoundsAfterClipPath) {
SkRect cull_rect = SkRect::MakeWH(100, 100);
SkPath clip_path = SkPath().addRect(10, 10, 15, 15).addRect(15, 15, 20, 20);
SkRect clip_bounds = SkRect::MakeLTRB(10, 10, 20, 20);
DisplayListCanvasRecorder recorder(cull_rect);
DisplayListBuilder builder(cull_rect);
builder.clipPath(clip_path, SkClipOp::kIntersect, false);
ASSERT_EQ(builder.getDestinationClipBounds(), clip_bounds);
}

TEST(DisplayList, BuilderInitialClipBoundsNonZero) {
SkRect cull_rect = SkRect::MakeLTRB(10, 10, 100, 100);
SkRect clip_bounds = SkRect::MakeLTRB(10, 10, 100, 100);
DisplayListCanvasRecorder recorder(cull_rect);
DisplayListBuilder builder(cull_rect);
ASSERT_EQ(builder.getDestinationClipBounds(), clip_bounds);
}

TEST(DisplayList, SingleOpSizes) {
for (auto& group : allGroups) {
for (size_t i = 0; i < group.variants.size(); i++) {
Expand Down