Skip to content

Commit d30e23a

Browse files
Chris Yanggoderbauer
authored andcommitted
Reland "Improve iOS PlatformViews to better handle thread merging. flutter#16935" (flutter#17609)
1 parent 3821082 commit d30e23a

20 files changed

+345
-31
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,8 @@ FILE: ../../../flutter/shell/common/shell_io_manager.cc
592592
FILE: ../../../flutter/shell/common/shell_io_manager.h
593593
FILE: ../../../flutter/shell/common/shell_test.cc
594594
FILE: ../../../flutter/shell/common/shell_test.h
595+
FILE: ../../../flutter/shell/common/shell_test_external_view_embedder.cc
596+
FILE: ../../../flutter/shell/common/shell_test_external_view_embedder.h
595597
FILE: ../../../flutter/shell/common/shell_test_platform_view.cc
596598
FILE: ../../../flutter/shell/common/shell_test_platform_view.h
597599
FILE: ../../../flutter/shell/common/shell_test_platform_view_gl.cc

flow/embedded_views.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,18 @@ class ExternalViewEmbedder {
253253
// This is called after submitting the embedder frame and the surface frame.
254254
virtual void FinishFrame();
255255

256+
// This should only be called after |SubmitFrame|.
257+
// This method provides the embedder a way to do additional tasks after
258+
// |SubmitFrame|. After invoking this method, the current task on the
259+
// TaskRunner should end immediately.
260+
//
261+
// For example on the iOS embedder, threads are merged in this call.
262+
// A new frame on the platform thread starts immediately. If the GPU thread
263+
// still has some task running, there could be two frames being rendered
264+
// concurrently, which causes undefined behaviors.
265+
virtual void EndFrame(
266+
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) {}
267+
256268
FML_DISALLOW_COPY_AND_ASSIGN(ExternalViewEmbedder);
257269

258270
}; // ExternalViewEmbedder

shell/common/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,8 @@ if (enable_unittests) {
191191
"pipeline_unittests.cc",
192192
"shell_test.cc",
193193
"shell_test.h",
194+
"shell_test_external_view_embedder.cc",
195+
"shell_test_external_view_embedder.h",
194196
"shell_test_platform_view.cc",
195197
"shell_test_platform_view.h",
196198
"shell_unittests.cc",

shell/common/animator_unittests.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ TEST_F(ShellTest, VSyncTargetTime) {
5555
return ShellTestPlatformView::Create(
5656
shell, shell.GetTaskRunners(), vsync_clock,
5757
std::move(create_vsync_waiter),
58-
ShellTestPlatformView::BackendType::kDefaultBackend);
58+
ShellTestPlatformView::BackendType::kDefaultBackend, nullptr);
5959
},
6060
[](Shell& shell) {
6161
return std::make_unique<Rasterizer>(shell, shell.GetTaskRunners());

shell/common/rasterizer.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,16 @@ void Rasterizer::Draw(fml::RefPtr<Pipeline<flutter::LayerTree>> pipeline) {
136136
consume_result = PipelineConsumeResult::MoreAvailable;
137137
}
138138

139+
// Merging the thread as we know the next `Draw` should be run on the platform
140+
// thread.
141+
if (raster_status == RasterStatus::kResubmit) {
142+
auto* external_view_embedder = surface_->GetExternalViewEmbedder();
143+
// We know only the `external_view_embedder` can
144+
// causes|RasterStatus::kResubmit|. Check to make sure.
145+
FML_DCHECK(external_view_embedder != nullptr);
146+
external_view_embedder->EndFrame(raster_thread_merger_);
147+
}
148+
139149
// Consume as many pipeline items as possible. But yield the event loop
140150
// between successive tries.
141151
switch (consume_result) {

shell/common/shell_test.cc

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -271,9 +271,12 @@ std::unique_ptr<Shell> ShellTest::CreateShell(Settings settings,
271271
simulate_vsync);
272272
}
273273

274-
std::unique_ptr<Shell> ShellTest::CreateShell(Settings settings,
275-
TaskRunners task_runners,
276-
bool simulate_vsync) {
274+
std::unique_ptr<Shell> ShellTest::CreateShell(
275+
Settings settings,
276+
TaskRunners task_runners,
277+
bool simulate_vsync,
278+
std::shared_ptr<ShellTestExternalViewEmbedder>
279+
shell_test_external_view_embedder) {
277280
const auto vsync_clock = std::make_shared<ShellTestVsyncClock>();
278281
CreateVsyncWaiter create_vsync_waiter = [&]() {
279282
if (simulate_vsync) {
@@ -286,17 +289,18 @@ std::unique_ptr<Shell> ShellTest::CreateShell(Settings settings,
286289
};
287290
return Shell::Create(
288291
task_runners, settings,
289-
[vsync_clock, &create_vsync_waiter](Shell& shell) {
292+
[vsync_clock, &create_vsync_waiter,
293+
shell_test_external_view_embedder](Shell& shell) {
290294
return ShellTestPlatformView::Create(
291295
shell, shell.GetTaskRunners(), vsync_clock,
292296
std::move(create_vsync_waiter),
293-
ShellTestPlatformView::BackendType::kDefaultBackend);
297+
ShellTestPlatformView::BackendType::kDefaultBackend,
298+
shell_test_external_view_embedder);
294299
},
295300
[](Shell& shell) {
296301
return std::make_unique<Rasterizer>(shell, shell.GetTaskRunners());
297302
});
298303
}
299-
300304
void ShellTest::DestroyShell(std::unique_ptr<Shell> shell) {
301305
DestroyShell(std::move(shell), GetTaskRunnersForFixture());
302306
}

shell/common/shell_test.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "flutter/shell/common/persistent_cache.h"
1717
#include "flutter/shell/common/run_configuration.h"
1818
#include "flutter/shell/common/shell.h"
19+
#include "flutter/shell/common/shell_test_external_view_embedder.h"
1920
#include "flutter/shell/common/thread_host.h"
2021
#include "flutter/shell/common/vsync_waiters_test.h"
2122
#include "flutter/testing/elf_loader.h"
@@ -32,9 +33,12 @@ class ShellTest : public ThreadTest {
3233
Settings CreateSettingsForFixture();
3334
std::unique_ptr<Shell> CreateShell(Settings settings,
3435
bool simulate_vsync = false);
35-
std::unique_ptr<Shell> CreateShell(Settings settings,
36-
TaskRunners task_runners,
37-
bool simulate_vsync = false);
36+
std::unique_ptr<Shell> CreateShell(
37+
Settings settings,
38+
TaskRunners task_runners,
39+
bool simulate_vsync = false,
40+
std::shared_ptr<ShellTestExternalViewEmbedder>
41+
shell_test_external_view_embedder = nullptr);
3842
void DestroyShell(std::unique_ptr<Shell> shell);
3943
void DestroyShell(std::unique_ptr<Shell> shell, TaskRunners task_runners);
4044
TaskRunners GetTaskRunnersForFixture();
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#include "shell_test_external_view_embedder.h"
2+
3+
namespace flutter {
4+
5+
// |ExternalViewEmbedder|
6+
void ShellTestExternalViewEmbedder::CancelFrame() {}
7+
8+
// |ExternalViewEmbedder|
9+
void ShellTestExternalViewEmbedder::BeginFrame(SkISize frame_size,
10+
GrContext* context,
11+
double device_pixel_ratio) {}
12+
13+
// |ExternalViewEmbedder|
14+
void ShellTestExternalViewEmbedder::PrerollCompositeEmbeddedView(
15+
int view_id,
16+
std::unique_ptr<EmbeddedViewParams> params) {}
17+
18+
// |ExternalViewEmbedder|
19+
PostPrerollResult ShellTestExternalViewEmbedder::PostPrerollAction(
20+
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) {
21+
FML_DCHECK(raster_thread_merger);
22+
return post_preroll_result_;
23+
}
24+
25+
// |ExternalViewEmbedder|
26+
std::vector<SkCanvas*> ShellTestExternalViewEmbedder::GetCurrentCanvases() {
27+
return {};
28+
}
29+
30+
// |ExternalViewEmbedder|
31+
SkCanvas* ShellTestExternalViewEmbedder::CompositeEmbeddedView(int view_id) {
32+
return nullptr;
33+
}
34+
35+
// |ExternalViewEmbedder|
36+
bool ShellTestExternalViewEmbedder::SubmitFrame(GrContext* context,
37+
SkCanvas* background_canvas) {
38+
return true;
39+
}
40+
41+
// |ExternalViewEmbedder|
42+
void ShellTestExternalViewEmbedder::FinishFrame() {}
43+
44+
// |ExternalViewEmbedder|
45+
void ShellTestExternalViewEmbedder::EndFrame(
46+
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) {
47+
end_frame_call_back_();
48+
}
49+
50+
// |ExternalViewEmbedder|
51+
SkCanvas* ShellTestExternalViewEmbedder::GetRootCanvas() {
52+
return nullptr;
53+
}
54+
55+
} // namespace flutter
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
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+
#ifndef FLUTTER_SHELL_TEST_EXTERNAL_VIEW_EMBEDDER_H_
6+
#define FLUTTER_SHELL_TEST_EXTERNAL_VIEW_EMBEDDER_H_
7+
8+
#include "flutter/flow/embedded_views.h"
9+
#include "flutter/fml/raster_thread_merger.h"
10+
11+
namespace flutter {
12+
13+
//------------------------------------------------------------------------------
14+
/// @brief The external view embedder used by |ShellTestPlatformViewGL|
15+
///
16+
class ShellTestExternalViewEmbedder final : public ExternalViewEmbedder {
17+
public:
18+
using EndFrameCallBack = std::function<void(void)>;
19+
20+
ShellTestExternalViewEmbedder(const EndFrameCallBack& end_frame_call_back,
21+
PostPrerollResult post_preroll_result)
22+
: end_frame_call_back_(end_frame_call_back),
23+
post_preroll_result_(post_preroll_result) {}
24+
25+
~ShellTestExternalViewEmbedder() = default;
26+
27+
private:
28+
// |ExternalViewEmbedder|
29+
void CancelFrame() override;
30+
31+
// |ExternalViewEmbedder|
32+
void BeginFrame(SkISize frame_size,
33+
GrContext* context,
34+
double device_pixel_ratio) override;
35+
36+
// |ExternalViewEmbedder|
37+
void PrerollCompositeEmbeddedView(
38+
int view_id,
39+
std::unique_ptr<EmbeddedViewParams> params) override;
40+
41+
// |ExternalViewEmbedder|
42+
PostPrerollResult PostPrerollAction(
43+
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) override;
44+
45+
// |ExternalViewEmbedder|
46+
std::vector<SkCanvas*> GetCurrentCanvases() override;
47+
48+
// |ExternalViewEmbedder|
49+
SkCanvas* CompositeEmbeddedView(int view_id) override;
50+
51+
// |ExternalViewEmbedder|
52+
bool SubmitFrame(GrContext* context, SkCanvas* background_canvas) override;
53+
54+
// |ExternalViewEmbedder|
55+
void FinishFrame() override;
56+
57+
// |ExternalViewEmbedder|
58+
void EndFrame(
59+
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) override;
60+
61+
// |ExternalViewEmbedder|
62+
SkCanvas* GetRootCanvas() override;
63+
64+
const EndFrameCallBack end_frame_call_back_;
65+
const PostPrerollResult post_preroll_result_;
66+
67+
FML_DISALLOW_COPY_AND_ASSIGN(ShellTestExternalViewEmbedder);
68+
};
69+
70+
} // namespace flutter
71+
72+
#endif // FLUTTER_SHELL_TEST_EXTERNAL_VIEW_EMBEDDER_H_

shell/common/shell_test_platform_view.cc

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,24 @@ std::unique_ptr<ShellTestPlatformView> ShellTestPlatformView::Create(
1919
TaskRunners task_runners,
2020
std::shared_ptr<ShellTestVsyncClock> vsync_clock,
2121
CreateVsyncWaiter create_vsync_waiter,
22-
BackendType backend) {
22+
BackendType backend,
23+
std::shared_ptr<ShellTestExternalViewEmbedder>
24+
shell_test_external_view_embedder) {
2325
// TODO(gw280): https://github.com/flutter/flutter/issues/50298
2426
// Make this fully runtime configurable
2527
switch (backend) {
2628
case BackendType::kDefaultBackend:
2729
#ifdef SHELL_ENABLE_GL
2830
case BackendType::kGLBackend:
2931
return std::make_unique<ShellTestPlatformViewGL>(
30-
delegate, task_runners, vsync_clock, create_vsync_waiter);
32+
delegate, task_runners, vsync_clock, create_vsync_waiter,
33+
shell_test_external_view_embedder);
3134
#endif // SHELL_ENABLE_GL
3235
#ifdef SHELL_ENABLE_VULKAN
3336
case BackendType::kVulkanBackend:
3437
return std::make_unique<ShellTestPlatformViewVulkan>(
35-
delegate, task_runners, vsync_clock, create_vsync_waiter);
38+
delegate, task_runners, vsync_clock, create_vsync_waiter,
39+
shell_test_external_view_embedder);
3640
#endif // SHELL_ENABLE_VULKAN
3741
default:
3842
FML_LOG(FATAL) << "No backends supported for ShellTestPlatformView";

0 commit comments

Comments
 (0)