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

Commit bba39d2

Browse files
christopherfujinoLongCatIsLooonggaaclarkeChris Yang
authored
[flutter_releases] Flutter 1.22.4 engine cherrypicks (#22449)
* Update 1.22 engine to use Dart 2.10.4 * [iOS TextInput] Avoid Unnecessary UndateEditingClient Calls (#21303) * added unit tests to the rasterizer (#22282) * Reland "Do not involve external_view_embedder in submit frame process if threads are not merged. #22275" (#22372) Co-authored-by: LongCatIsLooong <31859944+LongCatIsLooong@users.noreply.github.com> Co-authored-by: gaaclarke <30870216+gaaclarke@users.noreply.github.com> Co-authored-by: Chris Yang <ychris@google.com>
1 parent a1440ca commit bba39d2

File tree

11 files changed

+400
-50
lines changed

11 files changed

+400
-50
lines changed

DEPS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ vars = {
3434
# Dart is: https://github.com/dart-lang/sdk/blob/master/DEPS.
3535
# You can use //tools/dart/create_updated_flutter_deps.py to produce
3636
# updated revision list of existing dependencies.
37-
'dart_revision': 'ecf9ce8ef42de11033801b2870e8b310c3722902',
37+
'dart_revision': '7c148d029de32590a8d0d332bf807d25929f080e',
3838

3939
# WARNING: DO NOT EDIT MANUALLY
4040
# The lines between blank lines above and below are generated by a script. See create_updated_flutter_deps.py

ci/licenses_golden/licenses_flutter

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,7 @@ FILE: ../../../flutter/shell/common/pointer_data_dispatcher.cc
620620
FILE: ../../../flutter/shell/common/pointer_data_dispatcher.h
621621
FILE: ../../../flutter/shell/common/rasterizer.cc
622622
FILE: ../../../flutter/shell/common/rasterizer.h
623+
FILE: ../../../flutter/shell/common/rasterizer_unittests.cc
623624
FILE: ../../../flutter/shell/common/run_configuration.cc
624625
FILE: ../../../flutter/shell/common/run_configuration.h
625626
FILE: ../../../flutter/shell/common/serialization_callbacks.cc

ci/licenses_golden/licenses_third_party

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Signature: 35f962fd83423ee7de3761729e0c25c4
1+
Signature: 07e2f9b6ddb8b3f757d8a0f88f0bcfba
22

33
UNUSED LICENSES:
44

shell/common/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ if (enable_unittests) {
252252
"input_events_unittests.cc",
253253
"persistent_cache_unittests.cc",
254254
"pipeline_unittests.cc",
255+
"rasterizer_unittests.cc",
255256
"shell_unittests.cc",
256257
"skp_shader_warmup_unittests.cc",
257258
]

shell/common/rasterizer.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,7 @@ void Rasterizer::Draw(fml::RefPtr<Pipeline<flutter::LayerTree>> pipeline) {
186186
consume_result = PipelineConsumeResult::MoreAvailable;
187187
}
188188

189-
// Merging the thread as we know the next `Draw` should be run on the platform
190-
// thread.
189+
// EndFrame should perform cleanups for the external_view_embedder.
191190
if (surface_ != nullptr && surface_->GetExternalViewEmbedder() != nullptr) {
192191
surface_->GetExternalViewEmbedder()->EndFrame(should_resubmit_frame,
193192
raster_thread_merger_);
@@ -464,7 +463,8 @@ RasterStatus Rasterizer::DrawToSurface(flutter::LayerTree& layer_tree) {
464463
raster_status == RasterStatus::kSkipAndRetry) {
465464
return raster_status;
466465
}
467-
if (external_view_embedder != nullptr) {
466+
if (external_view_embedder != nullptr &&
467+
(!raster_thread_merger_ || raster_thread_merger_->IsMerged())) {
468468
FML_DCHECK(!frame->IsSubmitted());
469469
external_view_embedder->SubmitFrame(surface_->GetContext(),
470470
std::move(frame));
Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#define FML_USED_ON_EMBEDDER
6+
7+
#include "flutter/shell/common/rasterizer.h"
8+
9+
#include "flutter/shell/common/thread_host.h"
10+
#include "flutter/testing/testing.h"
11+
#include "gmock/gmock.h"
12+
13+
using testing::_;
14+
using testing::ByMove;
15+
using testing::Return;
16+
using testing::ReturnRef;
17+
18+
namespace flutter {
19+
namespace {
20+
class MockDelegate : public Rasterizer::Delegate {
21+
public:
22+
MOCK_METHOD1(OnFrameRasterized, void(const FrameTiming& frame_timing));
23+
MOCK_METHOD0(GetFrameBudget, fml::Milliseconds());
24+
MOCK_CONST_METHOD0(GetLatestFrameTargetTime, fml::TimePoint());
25+
MOCK_CONST_METHOD0(GetTaskRunners, const TaskRunners&());
26+
MOCK_CONST_METHOD0(GetIsGpuDisabledSyncSwitch,
27+
std::shared_ptr<fml::SyncSwitch>());
28+
};
29+
30+
class MockSurface : public Surface {
31+
public:
32+
MOCK_METHOD0(IsValid, bool());
33+
MOCK_METHOD1(AcquireFrame,
34+
std::unique_ptr<SurfaceFrame>(const SkISize& size));
35+
MOCK_CONST_METHOD0(GetRootTransformation, SkMatrix());
36+
MOCK_METHOD0(GetContext, GrDirectContext*());
37+
MOCK_METHOD0(GetExternalViewEmbedder, ExternalViewEmbedder*());
38+
MOCK_METHOD0(MakeRenderContextCurrent, std::unique_ptr<GLContextResult>());
39+
MOCK_METHOD0(ClearRenderContext, bool());
40+
};
41+
42+
class MockExternalViewEmbedder : public ExternalViewEmbedder {
43+
public:
44+
MOCK_METHOD0(GetRootCanvas, SkCanvas*());
45+
MOCK_METHOD0(CancelFrame, void());
46+
MOCK_METHOD4(BeginFrame,
47+
void(SkISize frame_size,
48+
GrDirectContext* context,
49+
double device_pixel_ratio,
50+
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger));
51+
MOCK_METHOD2(PrerollCompositeEmbeddedView,
52+
void(int view_id, std::unique_ptr<EmbeddedViewParams> params));
53+
MOCK_METHOD1(PostPrerollAction,
54+
PostPrerollResult(
55+
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger));
56+
MOCK_METHOD0(GetCurrentCanvases, std::vector<SkCanvas*>());
57+
MOCK_METHOD1(CompositeEmbeddedView, SkCanvas*(int view_id));
58+
MOCK_METHOD2(SubmitFrame,
59+
void(GrDirectContext* context,
60+
std::unique_ptr<SurfaceFrame> frame));
61+
MOCK_METHOD2(EndFrame,
62+
void(bool should_resubmit_frame,
63+
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger));
64+
MOCK_METHOD0(SupportsDynamicThreadMerging, bool());
65+
};
66+
} // namespace
67+
68+
TEST(RasterizerTest, create) {
69+
MockDelegate delegate;
70+
auto rasterizer = std::make_unique<Rasterizer>(delegate);
71+
EXPECT_TRUE(rasterizer != nullptr);
72+
}
73+
74+
TEST(RasterizerTest, drawEmptyPipeline) {
75+
std::string test_name =
76+
::testing::UnitTest::GetInstance()->current_test_info()->name();
77+
ThreadHost thread_host("io.flutter.test." + test_name + ".",
78+
ThreadHost::Type::Platform | ThreadHost::Type::GPU |
79+
ThreadHost::Type::IO | ThreadHost::Type::UI);
80+
TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
81+
thread_host.raster_thread->GetTaskRunner(),
82+
thread_host.ui_thread->GetTaskRunner(),
83+
thread_host.io_thread->GetTaskRunner());
84+
MockDelegate delegate;
85+
ON_CALL(delegate, GetTaskRunners()).WillByDefault(ReturnRef(task_runners));
86+
auto rasterizer = std::make_unique<Rasterizer>(delegate);
87+
auto surface = std::make_unique<MockSurface>();
88+
rasterizer->Setup(std::move(surface));
89+
fml::AutoResetWaitableEvent latch;
90+
thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
91+
auto pipeline = fml::AdoptRef(new Pipeline<LayerTree>(/*depth=*/10));
92+
rasterizer->Draw(pipeline);
93+
latch.Signal();
94+
});
95+
latch.Wait();
96+
}
97+
98+
TEST(RasterizerTest,
99+
drawWithExternalViewEmbedderExternalViewEmbedderSubmitFrameCalled) {
100+
std::string test_name =
101+
::testing::UnitTest::GetInstance()->current_test_info()->name();
102+
ThreadHost thread_host("io.flutter.test." + test_name + ".",
103+
ThreadHost::Type::Platform | ThreadHost::Type::GPU |
104+
ThreadHost::Type::IO | ThreadHost::Type::UI);
105+
TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
106+
thread_host.raster_thread->GetTaskRunner(),
107+
thread_host.ui_thread->GetTaskRunner(),
108+
thread_host.io_thread->GetTaskRunner());
109+
MockDelegate delegate;
110+
EXPECT_CALL(delegate, GetTaskRunners())
111+
.WillRepeatedly(ReturnRef(task_runners));
112+
EXPECT_CALL(delegate, OnFrameRasterized(_));
113+
auto rasterizer = std::make_unique<Rasterizer>(delegate);
114+
auto surface = std::make_unique<MockSurface>();
115+
116+
MockExternalViewEmbedder external_view_embedder;
117+
EXPECT_CALL(*surface, GetExternalViewEmbedder())
118+
.WillRepeatedly(Return(&external_view_embedder));
119+
120+
auto surface_frame = std::make_unique<SurfaceFrame>(
121+
/*surface=*/nullptr, /*supports_readback=*/true,
122+
/*submit_callback=*/[](const SurfaceFrame&, SkCanvas*) { return true; });
123+
EXPECT_CALL(*surface, AcquireFrame(SkISize()))
124+
.WillOnce(Return(ByMove(std::move(surface_frame))));
125+
126+
EXPECT_CALL(external_view_embedder,
127+
BeginFrame(/*frame_size=*/SkISize(), /*context=*/nullptr,
128+
/*device_pixel_ratio=*/2.0,
129+
/*raster_thread_merger=*/
130+
fml::RefPtr<fml::RasterThreadMerger>(nullptr)))
131+
.Times(1);
132+
EXPECT_CALL(external_view_embedder, SubmitFrame).Times(1);
133+
EXPECT_CALL(
134+
external_view_embedder,
135+
EndFrame(/*should_resubmit_frame=*/false,
136+
/*raster_thread_merger=*/fml::RefPtr<fml::RasterThreadMerger>(
137+
nullptr)))
138+
.Times(1);
139+
140+
rasterizer->Setup(std::move(surface));
141+
fml::AutoResetWaitableEvent latch;
142+
thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
143+
auto pipeline = fml::AdoptRef(new Pipeline<LayerTree>(/*depth=*/10));
144+
auto layer_tree = std::make_unique<LayerTree>(/*frame_size=*/SkISize(),
145+
/*device_pixel_ratio=*/2.0f);
146+
bool result = pipeline->Produce().Complete(std::move(layer_tree));
147+
EXPECT_TRUE(result);
148+
rasterizer->Draw(pipeline);
149+
latch.Signal();
150+
});
151+
latch.Wait();
152+
}
153+
154+
TEST(
155+
RasterizerTest,
156+
drawWithExternalViewEmbedderAndThreadMergerNotMergedExternalViewEmbedderSubmitFrameNotCalled) {
157+
std::string test_name =
158+
::testing::UnitTest::GetInstance()->current_test_info()->name();
159+
ThreadHost thread_host("io.flutter.test." + test_name + ".",
160+
ThreadHost::Type::Platform | ThreadHost::Type::GPU |
161+
ThreadHost::Type::IO | ThreadHost::Type::UI);
162+
TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
163+
thread_host.raster_thread->GetTaskRunner(),
164+
thread_host.ui_thread->GetTaskRunner(),
165+
thread_host.io_thread->GetTaskRunner());
166+
MockDelegate delegate;
167+
EXPECT_CALL(delegate, GetTaskRunners())
168+
.WillRepeatedly(ReturnRef(task_runners));
169+
EXPECT_CALL(delegate, OnFrameRasterized(_));
170+
auto rasterizer = std::make_unique<Rasterizer>(delegate);
171+
auto surface = std::make_unique<MockSurface>();
172+
MockExternalViewEmbedder external_view_embedder;
173+
EXPECT_CALL(*surface, GetExternalViewEmbedder())
174+
.WillRepeatedly(Return(&external_view_embedder));
175+
EXPECT_CALL(external_view_embedder, SupportsDynamicThreadMerging)
176+
.WillRepeatedly(Return(true));
177+
auto surface_frame = std::make_unique<SurfaceFrame>(
178+
/*surface=*/nullptr, /*supports_readback=*/true,
179+
/*submit_callback=*/[](const SurfaceFrame&, SkCanvas*) { return true; });
180+
EXPECT_CALL(*surface, AcquireFrame(SkISize()))
181+
.WillOnce(Return(ByMove(std::move(surface_frame))));
182+
183+
EXPECT_CALL(external_view_embedder,
184+
BeginFrame(/*frame_size=*/SkISize(), /*context=*/nullptr,
185+
/*device_pixel_ratio=*/2.0,
186+
/*raster_thread_merger=*/_))
187+
.Times(1);
188+
EXPECT_CALL(external_view_embedder, SubmitFrame).Times(0);
189+
EXPECT_CALL(external_view_embedder, EndFrame(/*should_resubmit_frame=*/false,
190+
/*raster_thread_merger=*/_))
191+
.Times(1);
192+
193+
rasterizer->Setup(std::move(surface));
194+
fml::AutoResetWaitableEvent latch;
195+
thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
196+
auto pipeline = fml::AdoptRef(new Pipeline<LayerTree>(/*depth=*/10));
197+
auto layer_tree = std::make_unique<LayerTree>(/*frame_size=*/SkISize(),
198+
/*device_pixel_ratio=*/2.0f);
199+
bool result = pipeline->Produce().Complete(std::move(layer_tree));
200+
EXPECT_TRUE(result);
201+
rasterizer->Draw(pipeline);
202+
latch.Signal();
203+
});
204+
latch.Wait();
205+
}
206+
207+
TEST(
208+
RasterizerTest,
209+
drawWithExternalViewEmbedderAndThreadsMergedExternalViewEmbedderSubmitFrameCalled) {
210+
std::string test_name =
211+
::testing::UnitTest::GetInstance()->current_test_info()->name();
212+
ThreadHost thread_host("io.flutter.test." + test_name + ".",
213+
ThreadHost::Type::Platform | ThreadHost::Type::GPU |
214+
ThreadHost::Type::IO | ThreadHost::Type::UI);
215+
fml::MessageLoop::EnsureInitializedForCurrentThread();
216+
TaskRunners task_runners("test",
217+
fml::MessageLoop::GetCurrent().GetTaskRunner(),
218+
fml::MessageLoop::GetCurrent().GetTaskRunner(),
219+
thread_host.ui_thread->GetTaskRunner(),
220+
thread_host.io_thread->GetTaskRunner());
221+
222+
MockDelegate delegate;
223+
EXPECT_CALL(delegate, GetTaskRunners())
224+
.WillRepeatedly(ReturnRef(task_runners));
225+
EXPECT_CALL(delegate, OnFrameRasterized(_));
226+
227+
auto rasterizer = std::make_unique<Rasterizer>(delegate);
228+
auto surface = std::make_unique<MockSurface>();
229+
230+
MockExternalViewEmbedder external_view_embedder;
231+
EXPECT_CALL(*surface, GetExternalViewEmbedder())
232+
.WillRepeatedly(Return(&external_view_embedder));
233+
234+
auto surface_frame = std::make_unique<SurfaceFrame>(
235+
/*surface=*/nullptr, /*supports_readback=*/true,
236+
/*submit_callback=*/[](const SurfaceFrame&, SkCanvas*) { return true; });
237+
EXPECT_CALL(*surface, AcquireFrame(SkISize()))
238+
.WillOnce(Return(ByMove(std::move(surface_frame))));
239+
EXPECT_CALL(external_view_embedder, SupportsDynamicThreadMerging)
240+
.WillRepeatedly(Return(true));
241+
242+
EXPECT_CALL(external_view_embedder,
243+
BeginFrame(/*frame_size=*/SkISize(), /*context=*/nullptr,
244+
/*device_pixel_ratio=*/2.0,
245+
/*raster_thread_merger=*/_))
246+
.Times(1);
247+
EXPECT_CALL(external_view_embedder, SubmitFrame).Times(1);
248+
EXPECT_CALL(external_view_embedder, EndFrame(/*should_resubmit_frame=*/false,
249+
/*raster_thread_merger=*/_))
250+
.Times(1);
251+
252+
rasterizer->Setup(std::move(surface));
253+
254+
auto pipeline = fml::AdoptRef(new Pipeline<LayerTree>(/*depth=*/10));
255+
auto layer_tree = std::make_unique<LayerTree>(/*frame_size=*/SkISize(),
256+
/*device_pixel_ratio=*/2.0f);
257+
bool result = pipeline->Produce().Complete(std::move(layer_tree));
258+
EXPECT_TRUE(result);
259+
rasterizer->Draw(pipeline);
260+
}
261+
} // namespace flutter

shell/common/shell_unittests.cc

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -996,13 +996,7 @@ TEST_F(ShellTest,
996996
}
997997

998998
// TODO(https://github.com/flutter/flutter/issues/59816): Enable on fuchsia.
999-
TEST_F(ShellTest,
1000-
#if defined(OS_FUCHSIA)
1001-
DISABLED_SkipAndSubmitFrame
1002-
#else
1003-
SkipAndSubmitFrame
1004-
#endif
1005-
) {
999+
TEST_F(ShellTest, DISABLED_SkipAndSubmitFrame) {
10061000
auto settings = CreateSettingsForFixture();
10071001
fml::AutoResetWaitableEvent end_frame_latch;
10081002
std::shared_ptr<ShellTestExternalViewEmbedder> external_view_embedder;
@@ -1052,20 +1046,25 @@ TEST_F(ShellTest,
10521046
auto settings = CreateSettingsForFixture();
10531047
fml::AutoResetWaitableEvent end_frame_latch;
10541048
std::shared_ptr<ShellTestExternalViewEmbedder> external_view_embedder;
1055-
1049+
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger_ref;
10561050
auto end_frame_callback =
10571051
[&](bool should_resubmit_frame,
10581052
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) {
1059-
external_view_embedder->UpdatePostPrerollResult(
1060-
PostPrerollResult::kSuccess);
1053+
if (!raster_thread_merger_ref) {
1054+
raster_thread_merger_ref = raster_thread_merger;
1055+
}
1056+
if (should_resubmit_frame && !raster_thread_merger->IsMerged()) {
1057+
raster_thread_merger->MergeWithLease(10);
1058+
external_view_embedder->UpdatePostPrerollResult(
1059+
PostPrerollResult::kSuccess);
1060+
}
10611061
end_frame_latch.Signal();
10621062
};
10631063
external_view_embedder = std::make_shared<ShellTestExternalViewEmbedder>(
10641064
end_frame_callback, PostPrerollResult::kResubmitFrame, true);
10651065

10661066
auto shell = CreateShell(std::move(settings), GetTaskRunnersForFixture(),
10671067
false, external_view_embedder);
1068-
10691068
PlatformViewNotifyCreated(shell.get());
10701069

10711070
auto configuration = RunConfiguration::InferFromSettings(settings);
@@ -1075,13 +1074,18 @@ TEST_F(ShellTest,
10751074
ASSERT_EQ(0, external_view_embedder->GetSubmittedFrameCount());
10761075

10771076
PumpOneFrame(shell.get());
1078-
// `EndFrame` changed the post preroll result to `kSuccess`.
1077+
// `EndFrame` changed the post preroll result to `kSuccess` and merged the
1078+
// threads. During the frame, the threads are not merged, So no
1079+
// `external_view_embedder->GetSubmittedFrameCount()` is called.
10791080
end_frame_latch.Wait();
1080-
ASSERT_EQ(1, external_view_embedder->GetSubmittedFrameCount());
1081+
ASSERT_TRUE(raster_thread_merger_ref->IsMerged());
1082+
ASSERT_EQ(0, external_view_embedder->GetSubmittedFrameCount());
10811083

1084+
// This is the resubmitted frame, which threads are also merged.
10821085
end_frame_latch.Wait();
1083-
ASSERT_EQ(2, external_view_embedder->GetSubmittedFrameCount());
1086+
ASSERT_EQ(1, external_view_embedder->GetSubmittedFrameCount());
10841087

1088+
PlatformViewNotifyDestroyed(shell.get());
10851089
DestroyShell(std::move(shell));
10861090
}
10871091

0 commit comments

Comments
 (0)