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

Commit c0f2262

Browse files
committed
add tests for state tracking after a platform layer and fix a bug
1 parent a7b615b commit c0f2262

9 files changed

+125
-11
lines changed

flow/layers/layer_state_stack.cc

+10-5
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,19 @@ namespace flutter {
1111
using AutoRestore = LayerStateStack::AutoRestore;
1212
using MutatorContext = LayerStateStack::MutatorContext;
1313

14-
void LayerStateStack::set_canvas_delegate(SkCanvas* canvas) {
14+
void LayerStateStack::clear_delegates() {
1515
if (canvas_) {
1616
canvas_->restoreToCount(canvas_restore_count_);
1717
canvas_ = nullptr;
1818
}
19+
if (builder_) {
20+
builder_->restoreToCount(builder_restore_count_);
21+
builder_ = nullptr;
22+
}
23+
}
24+
25+
void LayerStateStack::set_canvas_delegate(SkCanvas* canvas) {
26+
clear_delegates();
1927
if (canvas) {
2028
canvas_restore_count_ = canvas->getSaveCount();
2129
canvas_ = canvas;
@@ -24,10 +32,7 @@ void LayerStateStack::set_canvas_delegate(SkCanvas* canvas) {
2432
}
2533

2634
void LayerStateStack::set_builder_delegate(DisplayListBuilder* builder) {
27-
if (builder_) {
28-
builder_->restoreToCount(builder_restore_count_);
29-
builder_ = nullptr;
30-
}
35+
clear_delegates();
3136
if (builder) {
3237
builder_restore_count_ = builder->getSaveCount();
3338
builder_ = builder;

flow/layers/layer_state_stack.h

+12-3
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,23 @@ class LayerStateStack {
1919
do_checkerboard_ = checkerboard;
2020
}
2121

22+
// Clears out any old delegate to make room for a new one.
23+
void clear_delegates();
24+
2225
SkCanvas* canvas_delegate() { return canvas_; }
26+
// Clears the old delegate and sets the canvas delegate to the indicated
27+
// canvas (if not nullptr). This ensures that only one delegate - either
28+
// a canvas or a builder - is present at any one time.
2329
void set_canvas_delegate(SkCanvas* canvas);
24-
void set_builder_delegate(sk_sp<DisplayListBuilder> builder) {
25-
set_builder_delegate(builder.get());
26-
}
2730

2831
DisplayListBuilder* builder_delegate() { return builder_; }
32+
// Clears the old delegate and sets the builder delegate to the indicated
33+
// buider (if not nullptr). This ensures that only one delegate - either
34+
// a canvas or a builder - is present at any one time.
2935
void set_builder_delegate(DisplayListBuilder* builder);
36+
void set_builder_delegate(sk_sp<DisplayListBuilder> builder) {
37+
set_builder_delegate(builder.get());
38+
}
3039
void set_builder_delegate(DisplayListCanvasRecorder& recorder) {
3140
set_builder_delegate(recorder.builder().get());
3241
}

flow/layers/layer_state_stack_unittests.cc

+26
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "flutter/display_list/display_list_image_filter.h"
99
#include "flutter/flow/layers/layer_state_stack.h"
1010
#include "flutter/testing/display_list_testing.h"
11+
#include "flutter/testing/mock_canvas.h"
1112

1213
namespace flutter {
1314
namespace testing {
@@ -32,6 +33,31 @@ TEST(LayerStateStack, Defaults) {
3233
ASSERT_EQ(dl_paint, DlPaint());
3334
}
3435

36+
TEST(LayerStateStack, OneDelegateAtATime) {
37+
LayerStateStack state_stack;
38+
ASSERT_EQ(state_stack.canvas_delegate(), nullptr);
39+
ASSERT_EQ(state_stack.builder_delegate(), nullptr);
40+
41+
DisplayListBuilder builder;
42+
state_stack.set_builder_delegate(&builder);
43+
ASSERT_EQ(state_stack.canvas_delegate(), nullptr);
44+
ASSERT_EQ(state_stack.builder_delegate(), &builder);
45+
46+
MockCanvas canvas;
47+
state_stack.set_canvas_delegate(&canvas);
48+
ASSERT_EQ(state_stack.canvas_delegate(), &canvas);
49+
ASSERT_EQ(state_stack.builder_delegate(), nullptr);
50+
51+
state_stack.clear_delegates();
52+
ASSERT_EQ(state_stack.canvas_delegate(), nullptr);
53+
ASSERT_EQ(state_stack.builder_delegate(), nullptr);
54+
55+
state_stack.set_builder_delegate(&builder);
56+
state_stack.clear_delegates();
57+
ASSERT_EQ(state_stack.canvas_delegate(), nullptr);
58+
ASSERT_EQ(state_stack.builder_delegate(), nullptr);
59+
}
60+
3561
TEST(LayerStateStack, Opacity) {
3662
SkRect rect = {10, 10, 20, 20};
3763

flow/layers/platform_view_layer.cc

+5-2
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,12 @@ void PlatformViewLayer::Paint(PaintContext& context) const {
4141
EmbedderPaintContext embedder_context =
4242
context.view_embedder->CompositeEmbeddedView(view_id_);
4343
context.canvas = embedder_context.canvas;
44-
context.state_stack.set_canvas_delegate(context.canvas);
4544
context.builder = embedder_context.builder;
46-
context.state_stack.set_builder_delegate(context.builder);
45+
if (context.builder) {
46+
context.state_stack.set_builder_delegate(context.builder);
47+
} else {
48+
context.state_stack.set_canvas_delegate(context.canvas);
49+
}
4750
}
4851

4952
} // namespace flutter

flow/layers/platform_view_layer_unittests.cc

+42
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include "flutter/flow/layers/clip_rect_layer.h"
66
#include "flutter/flow/layers/platform_view_layer.h"
7+
#include "flutter/flow/layers/transform_layer.h"
78

89
#include "flutter/flow/testing/layer_test.h"
910
#include "flutter/flow/testing/mock_embedder.h"
@@ -95,5 +96,46 @@ TEST_F(PlatformViewLayerTest, OpacityInheritance) {
9596
EXPECT_EQ(context->renderable_state_flags, 0);
9697
}
9798

99+
TEST_F(PlatformViewLayerTest, StateTransfer) {
100+
const SkMatrix transform1 = SkMatrix::Translate(5, 5);
101+
const SkMatrix transform2 = SkMatrix::Translate(15, 15);
102+
const SkMatrix combined_transform = SkMatrix::Translate(20, 20);
103+
const SkPoint layer_offset = SkPoint::Make(0.0f, 0.0f);
104+
const SkSize layer_size = SkSize::Make(8.0f, 8.0f);
105+
const int64_t view_id = 0;
106+
const SkPath path1 = SkPath().addOval({10, 10, 20, 20});
107+
const SkPath path2 = SkPath().addOval({15, 15, 30, 30});
108+
109+
// transform_layer1
110+
// |- child1
111+
// |- platform_layer
112+
// |- transform_layer2
113+
// |- child2
114+
auto transform_layer1 = std::make_shared<TransformLayer>(transform1);
115+
auto transform_layer2 = std::make_shared<TransformLayer>(transform2);
116+
auto platform_layer =
117+
std::make_shared<PlatformViewLayer>(layer_offset, layer_size, view_id);
118+
auto child1 = std::make_shared<MockLayer>(path1);
119+
child1->set_expected_paint_matrix(transform1);
120+
auto child2 = std::make_shared<MockLayer>(path2);
121+
child2->set_expected_paint_matrix(combined_transform);
122+
transform_layer1->Add(child1);
123+
transform_layer1->Add(platform_layer);
124+
transform_layer1->Add(transform_layer2);
125+
transform_layer2->Add(child2);
126+
127+
auto embedder = MockViewEmbedder();
128+
DisplayListCanvasRecorder recorder({0, 0, 500, 500});
129+
embedder.AddRecorder(&recorder);
130+
131+
PrerollContext* preroll_ctx = preroll_context();
132+
preroll_ctx->view_embedder = &embedder;
133+
transform_layer1->Preroll(preroll_ctx, SkMatrix());
134+
135+
PaintContext& paint_ctx = paint_context();
136+
paint_ctx.view_embedder = &embedder;
137+
transform_layer1->Paint(paint_ctx);
138+
}
139+
98140
} // namespace testing
99141
} // namespace flutter

flow/testing/mock_embedder.cc

+12-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,15 @@ MockViewEmbedder::MockViewEmbedder() = default;
1111

1212
MockViewEmbedder::~MockViewEmbedder() = default;
1313

14+
void MockViewEmbedder::AddCanvas(SkCanvas* canvas) {
15+
contexts_.emplace_back(EmbedderPaintContext{canvas, nullptr});
16+
}
17+
18+
void MockViewEmbedder::AddRecorder(DisplayListCanvasRecorder* recorder) {
19+
contexts_.emplace_back(
20+
EmbedderPaintContext{recorder, recorder->builder().get()});
21+
}
22+
1423
// |ExternalViewEmbedder|
1524
SkCanvas* MockViewEmbedder::GetRootCanvas() {
1625
return nullptr;
@@ -43,7 +52,9 @@ std::vector<DisplayListBuilder*> MockViewEmbedder::GetCurrentBuilders() {
4352

4453
// |ExternalViewEmbedder|
4554
EmbedderPaintContext MockViewEmbedder::CompositeEmbeddedView(int view_id) {
46-
return {nullptr, nullptr};
55+
EmbedderPaintContext context = contexts_.front();
56+
contexts_.pop_front();
57+
return context;
4758
}
4859

4960
} // namespace testing

flow/testing/mock_embedder.h

+6
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ class MockViewEmbedder : public ExternalViewEmbedder {
1616

1717
~MockViewEmbedder();
1818

19+
void AddCanvas(SkCanvas* canvas);
20+
void AddRecorder(DisplayListCanvasRecorder* recorder);
21+
1922
// |ExternalViewEmbedder|
2023
SkCanvas* GetRootCanvas() override;
2124

@@ -42,6 +45,9 @@ class MockViewEmbedder : public ExternalViewEmbedder {
4245

4346
// |ExternalViewEmbedder|
4447
EmbedderPaintContext CompositeEmbeddedView(int view_id) override;
48+
49+
private:
50+
std::deque<EmbedderPaintContext> contexts_;
4551
};
4652

4753
} // namespace testing

flow/testing/mock_layer.cc

+7
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ void MockLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
5252
void MockLayer::Paint(PaintContext& context) const {
5353
FML_DCHECK(needs_painting(context));
5454

55+
if (expected_paint_matrix_.has_value()) {
56+
SkMatrix matrix = context.builder ? context.builder->getTransform()
57+
: context.canvas->getTotalMatrix();
58+
59+
ASSERT_EQ(matrix, expected_paint_matrix_.value());
60+
}
61+
5562
SkPaint sk_paint = fake_paint_;
5663
context.state_stack.fill(sk_paint);
5764
context.canvas->drawPath(fake_paint_path_, sk_paint);

flow/testing/mock_layer.h

+5
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,17 @@ class MockLayer : public Layer {
102102
return *this;
103103
}
104104

105+
void set_expected_paint_matrix(const SkMatrix& matrix) {
106+
expected_paint_matrix_ = matrix;
107+
}
108+
105109
private:
106110
MutatorsStack parent_mutators_;
107111
SkMatrix parent_matrix_;
108112
SkRect parent_cull_rect_ = SkRect::MakeEmpty();
109113
SkPath fake_paint_path_;
110114
SkPaint fake_paint_;
115+
std::optional<SkMatrix> expected_paint_matrix_;
111116

112117
static constexpr int kParentHasPlatformView = 1 << 0;
113118
static constexpr int kParentHasTextureLayer = 1 << 1;

0 commit comments

Comments
 (0)