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

Commit 0ef5caa

Browse files
authored
Reland 2: Multiview Pipeline (#47239)
The last attempt #47234 was reverted because there was another test merged in the meantime that violates the rule added in this PR. [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
1 parent dd6a653 commit 0ef5caa

28 files changed

+743
-194
lines changed

flow/frame_timings.cc

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,8 +254,30 @@ const char* FrameTimingsRecorder::GetFrameNumberTraceArg() const {
254254
return frame_number_trace_arg_val_.c_str();
255255
}
256256

257+
static const char* StateToString(FrameTimingsRecorder::State state) {
258+
#ifndef NDEBUG
259+
switch (state) {
260+
case FrameTimingsRecorder::State::kUninitialized:
261+
return "kUninitialized";
262+
case FrameTimingsRecorder::State::kVsync:
263+
return "kVsync";
264+
case FrameTimingsRecorder::State::kBuildStart:
265+
return "kBuildStart";
266+
case FrameTimingsRecorder::State::kBuildEnd:
267+
return "kBuildEnd";
268+
case FrameTimingsRecorder::State::kRasterStart:
269+
return "kRasterStart";
270+
case FrameTimingsRecorder::State::kRasterEnd:
271+
return "kRasterEnd";
272+
};
273+
FML_UNREACHABLE();
274+
#endif
275+
return "";
276+
}
277+
257278
void FrameTimingsRecorder::AssertInState(State state) const {
258-
FML_DCHECK(state_ == state);
279+
FML_DCHECK(state_ == state) << "Expected state " << StateToString(state)
280+
<< ", actual state " << StateToString(state_);
259281
}
260282

261283
} // namespace flutter

flow/frame_timings.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class FrameTimingsRecorder {
3131
public:
3232
/// Various states that the recorder can be in. When created the recorder is
3333
/// in an unitialized state and transtions in sequential order of the states.
34+
// After adding an item to this enum, modify StateToString accordingly.
3435
enum class State : uint32_t {
3536
kUninitialized,
3637
kVsync,
@@ -121,6 +122,8 @@ class FrameTimingsRecorder {
121122
///
122123
/// Instead of adding a `GetState` method and asserting on the result, this
123124
/// method prevents other logic from relying on the state.
125+
///
126+
/// In opt builds, this call is a no-op.
124127
void AssertInState(State state) const;
125128

126129
private:

impeller/entity/contents/filters/gaussian_blur_filter_contents.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ namespace impeller {
2626
DirectionalGaussianBlurFilterContents::DirectionalGaussianBlurFilterContents() =
2727
default;
2828

29-
DirectionalGaussianBlurFilterContents::
30-
~DirectionalGaussianBlurFilterContents() = default;
29+
DirectionalGaussianBlurFilterContents::~
30+
DirectionalGaussianBlurFilterContents() = default;
3131

3232
void DirectionalGaussianBlurFilterContents::SetSigma(Sigma sigma) {
3333
blur_sigma_ = sigma;

lib/ui/dart_ui.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ typedef CanvasPath Path;
9898
V(NativeStringAttribute::initSpellOutStringAttribute, 3) \
9999
V(PlatformConfigurationNativeApi::DefaultRouteName, 0) \
100100
V(PlatformConfigurationNativeApi::ScheduleFrame, 0) \
101-
V(PlatformConfigurationNativeApi::Render, 1) \
101+
V(PlatformConfigurationNativeApi::Render, 2) \
102102
V(PlatformConfigurationNativeApi::UpdateSemantics, 1) \
103103
V(PlatformConfigurationNativeApi::SetNeedsReportTimings, 1) \
104104
V(PlatformConfigurationNativeApi::SetIsolateDebugName, 1) \

lib/ui/painting/image_dispose_unittests.cc

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#define FML_USED_ON_EMBEDDER
66

77
#include "flutter/common/task_runners.h"
8+
#include "flutter/fml/synchronization/count_down_latch.h"
89
#include "flutter/fml/synchronization/waitable_event.h"
910
#include "flutter/lib/ui/painting/canvas.h"
1011
#include "flutter/lib/ui/painting/image.h"
@@ -57,6 +58,10 @@ TEST_F(ImageDisposeTest, ImageReleasedAfterFrameAndDisposePictureAndLayer) {
5758
};
5859

5960
Settings settings = CreateSettingsForFixture();
61+
fml::CountDownLatch frame_latch{2};
62+
settings.frame_rasterized_callback = [&frame_latch](const FrameTiming& t) {
63+
frame_latch.CountDown();
64+
};
6065
auto task_runner = CreateNewThread();
6166
TaskRunners task_runners("test", // label
6267
GetCurrentTaskRunner(), // platform
@@ -83,12 +88,15 @@ TEST_F(ImageDisposeTest, ImageReleasedAfterFrameAndDisposePictureAndLayer) {
8388
shell->RunEngine(std::move(configuration), [&](auto result) {
8489
ASSERT_EQ(result, Engine::RunStatus::Success);
8590
});
86-
8791
message_latch_.Wait();
8892

8993
ASSERT_TRUE(current_display_list_);
9094
ASSERT_TRUE(current_image_);
9195

96+
// Wait for 2 frames to be rasterized. The 2nd frame releases resources of the
97+
// 1st frame.
98+
frame_latch.Wait();
99+
92100
// Force a drain the SkiaUnrefQueue. The engine does this normally as frames
93101
// pump, but we force it here to make the test more deterministic.
94102
message_latch_.Reset();

lib/ui/window.dart

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -356,18 +356,20 @@ class FlutterView {
356356
void render(Scene scene) {
357357
// Duplicated calls or calls outside of onBeginFrame/onDrawFrame (indicated
358358
// by _debugRenderedViews being null) are ignored. See _debugRenderedViews.
359+
// TODO(dkwingsmt): We should change this skip into an assertion.
360+
// https://github.com/flutter/flutter/issues/137073
359361
bool validRender = true;
360362
assert(() {
361363
validRender = platformDispatcher._debugRenderedViews?.add(this) ?? false;
362364
return true;
363365
}());
364366
if (validRender) {
365-
_render(scene as _NativeScene);
367+
_render(viewId, scene as _NativeScene);
366368
}
367369
}
368370

369-
@Native<Void Function(Pointer<Void>)>(symbol: 'PlatformConfigurationNativeApi::Render')
370-
external static void _render(_NativeScene scene);
371+
@Native<Void Function(Int64, Pointer<Void>)>(symbol: 'PlatformConfigurationNativeApi::Render')
372+
external static void _render(int viewId, _NativeScene scene);
371373

372374
/// Change the retained semantics data about this [FlutterView].
373375
///

lib/ui/window/platform_configuration.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -449,9 +449,10 @@ void PlatformConfiguration::CompletePlatformMessageResponse(
449449
response->Complete(std::make_unique<fml::DataMapping>(std::move(data)));
450450
}
451451

452-
void PlatformConfigurationNativeApi::Render(Scene* scene) {
452+
void PlatformConfigurationNativeApi::Render(int64_t view_id, Scene* scene) {
453453
UIDartState::ThrowIfUIOperationsProhibited();
454-
UIDartState::Current()->platform_configuration()->client()->Render(scene);
454+
UIDartState::Current()->platform_configuration()->client()->Render(view_id,
455+
scene);
455456
}
456457

457458
void PlatformConfigurationNativeApi::SetNeedsReportTimings(bool value) {

lib/ui/window/platform_configuration.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class PlatformConfigurationClient {
6969
/// @brief Updates the client's rendering on the GPU with the newly
7070
/// provided Scene.
7171
///
72-
virtual void Render(Scene* scene) = 0;
72+
virtual void Render(int64_t view_id, Scene* scene) = 0;
7373

7474
//--------------------------------------------------------------------------
7575
/// @brief Receives an updated semantics tree from the Framework.
@@ -557,7 +557,7 @@ class PlatformConfigurationNativeApi {
557557

558558
static void ScheduleFrame();
559559

560-
static void Render(Scene* scene);
560+
static void Render(int64_t view_id, Scene* scene);
561561

562562
static void UpdateSemantics(SemanticsUpdate* update);
563563

lib/ui/window/platform_configuration_unittests.cc

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,166 @@
1515
#include "flutter/shell/common/shell_test.h"
1616
#include "flutter/shell/common/thread_host.h"
1717
#include "flutter/testing/testing.h"
18+
#include "gmock/gmock.h"
1819

1920
namespace flutter {
21+
22+
namespace {
23+
24+
static constexpr int64_t kImplicitViewId = 0;
25+
26+
static void PostSync(const fml::RefPtr<fml::TaskRunner>& task_runner,
27+
const fml::closure& task) {
28+
fml::AutoResetWaitableEvent latch;
29+
fml::TaskRunner::RunNowOrPostTask(task_runner, [&latch, &task] {
30+
task();
31+
latch.Signal();
32+
});
33+
latch.Wait();
34+
}
35+
36+
class MockRuntimeDelegate : public RuntimeDelegate {
37+
public:
38+
MOCK_METHOD(std::string, DefaultRouteName, (), (override));
39+
MOCK_METHOD(void, ScheduleFrame, (bool), (override));
40+
MOCK_METHOD(void,
41+
Render,
42+
(int64_t, std::unique_ptr<flutter::LayerTree>, float),
43+
(override));
44+
MOCK_METHOD(void,
45+
UpdateSemantics,
46+
(SemanticsNodeUpdates, CustomAccessibilityActionUpdates),
47+
(override));
48+
MOCK_METHOD(void,
49+
HandlePlatformMessage,
50+
(std::unique_ptr<PlatformMessage>),
51+
(override));
52+
MOCK_METHOD(FontCollection&, GetFontCollection, (), (override));
53+
MOCK_METHOD(std::shared_ptr<AssetManager>, GetAssetManager, (), (override));
54+
MOCK_METHOD(void, OnRootIsolateCreated, (), (override));
55+
MOCK_METHOD(void,
56+
UpdateIsolateDescription,
57+
(const std::string, int64_t),
58+
(override));
59+
MOCK_METHOD(void, SetNeedsReportTimings, (bool), (override));
60+
MOCK_METHOD(std::unique_ptr<std::vector<std::string>>,
61+
ComputePlatformResolvedLocale,
62+
(const std::vector<std::string>&),
63+
(override));
64+
MOCK_METHOD(void, RequestDartDeferredLibrary, (intptr_t), (override));
65+
MOCK_METHOD(std::weak_ptr<PlatformMessageHandler>,
66+
GetPlatformMessageHandler,
67+
(),
68+
(const, override));
69+
MOCK_METHOD(void, SendChannelUpdate, (std::string, bool), (override));
70+
MOCK_METHOD(double,
71+
GetScaledFontSize,
72+
(double font_size, int configuration_id),
73+
(const, override));
74+
};
75+
76+
class MockPlatformMessageHandler : public PlatformMessageHandler {
77+
public:
78+
MOCK_METHOD(void,
79+
HandlePlatformMessage,
80+
(std::unique_ptr<PlatformMessage> message),
81+
(override));
82+
MOCK_METHOD(bool,
83+
DoesHandlePlatformMessageOnPlatformThread,
84+
(),
85+
(const, override));
86+
MOCK_METHOD(void,
87+
InvokePlatformMessageResponseCallback,
88+
(int response_id, std::unique_ptr<fml::Mapping> mapping),
89+
(override));
90+
MOCK_METHOD(void,
91+
InvokePlatformMessageEmptyResponseCallback,
92+
(int response_id),
93+
(override));
94+
};
95+
96+
// A class that can launch a RuntimeController with the specified
97+
// RuntimeDelegate.
98+
//
99+
// To use this class, contruct this class with Create, call LaunchRootIsolate,
100+
// and use the controller with ControllerTaskSync().
101+
class RuntimeControllerContext {
102+
public:
103+
using ControllerCallback = std::function<void(RuntimeController&)>;
104+
105+
[[nodiscard]] static std::unique_ptr<RuntimeControllerContext> Create(
106+
Settings settings, //
107+
const TaskRunners& task_runners, //
108+
RuntimeDelegate& client) {
109+
auto [vm, isolate_snapshot] = Shell::InferVmInitDataFromSettings(settings);
110+
FML_CHECK(vm) << "Must be able to initialize the VM.";
111+
// Construct the class with `new` because `make_unique` has no access to the
112+
// private constructor.
113+
RuntimeControllerContext* raw_pointer = new RuntimeControllerContext(
114+
settings, task_runners, client, std::move(vm), isolate_snapshot);
115+
return std::unique_ptr<RuntimeControllerContext>(raw_pointer);
116+
}
117+
118+
~RuntimeControllerContext() {
119+
PostSync(task_runners_.GetUITaskRunner(),
120+
[&]() { runtime_controller_.reset(); });
121+
}
122+
123+
// Launch the root isolate. The post_launch callback will be executed in the
124+
// same UI task, which can be used to create initial views.
125+
void LaunchRootIsolate(RunConfiguration& configuration,
126+
ControllerCallback post_launch) {
127+
PostSync(task_runners_.GetUITaskRunner(), [&]() {
128+
bool launch_success = runtime_controller_->LaunchRootIsolate(
129+
settings_, //
130+
[]() {}, //
131+
configuration.GetEntrypoint(), //
132+
configuration.GetEntrypointLibrary(), //
133+
configuration.GetEntrypointArgs(), //
134+
configuration.TakeIsolateConfiguration()); //
135+
ASSERT_TRUE(launch_success);
136+
post_launch(*runtime_controller_);
137+
});
138+
}
139+
140+
// Run a task that operates the RuntimeController on the UI thread, and wait
141+
// for the task to end.
142+
void ControllerTaskSync(ControllerCallback task) {
143+
ASSERT_TRUE(runtime_controller_);
144+
ASSERT_TRUE(task);
145+
PostSync(task_runners_.GetUITaskRunner(),
146+
[&]() { task(*runtime_controller_); });
147+
}
148+
149+
private:
150+
RuntimeControllerContext(const Settings& settings,
151+
const TaskRunners& task_runners,
152+
RuntimeDelegate& client,
153+
DartVMRef vm,
154+
fml::RefPtr<const DartSnapshot> isolate_snapshot)
155+
: settings_(settings),
156+
task_runners_(task_runners),
157+
isolate_snapshot_(std::move(isolate_snapshot)),
158+
vm_(std::move(vm)),
159+
runtime_controller_(std::make_unique<RuntimeController>(
160+
client,
161+
&vm_,
162+
std::move(isolate_snapshot_),
163+
settings.idle_notification_callback, // idle notification callback
164+
flutter::PlatformData(), // platform data
165+
settings.isolate_create_callback, // isolate create callback
166+
settings.isolate_shutdown_callback, // isolate shutdown callback
167+
settings.persistent_isolate_data, // persistent isolate data
168+
UIDartState::Context{task_runners})) {}
169+
170+
Settings settings_;
171+
TaskRunners task_runners_;
172+
fml::RefPtr<const DartSnapshot> isolate_snapshot_;
173+
DartVMRef vm_;
174+
std::unique_ptr<RuntimeController> runtime_controller_;
175+
};
176+
} // namespace
177+
20178
namespace testing {
21179

22180
class PlatformConfigurationTest : public ShellTest {};

runtime/dart_vm.cc

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -219,22 +219,22 @@ static std::vector<const char*> ProfilingFlags(bool enable_profiling) {
219219
// flags.
220220
if (enable_profiling) {
221221
return {
222-
// This is the default. But just be explicit.
223-
"--profiler",
224-
// This instructs the profiler to walk C++ frames, and to include
225-
// them in the profile.
226-
"--profile-vm",
222+
// This is the default. But just be explicit.
223+
"--profiler",
224+
// This instructs the profiler to walk C++ frames, and to include
225+
// them in the profile.
226+
"--profile-vm",
227227
#if FML_OS_IOS && FML_ARCH_CPU_ARM_FAMILY && FML_ARCH_CPU_ARMEL
228-
// Set the profiler interrupt period to 500Hz instead of the
229-
// default 1000Hz on 32-bit iOS devices to reduce average and worst
230-
// case frame build times.
231-
//
232-
// Note: profile_period is time in microseconds between sampling
233-
// events, not frequency. Frequency is calculated 1/period (or
234-
// 1,000,000 / 2,000 -> 500Hz in this case).
235-
"--profile_period=2000",
228+
// Set the profiler interrupt period to 500Hz instead of the
229+
// default 1000Hz on 32-bit iOS devices to reduce average and worst
230+
// case frame build times.
231+
//
232+
// Note: profile_period is time in microseconds between sampling
233+
// events, not frequency. Frequency is calculated 1/period (or
234+
// 1,000,000 / 2,000 -> 500Hz in this case).
235+
"--profile_period=2000",
236236
#else
237-
"--profile_period=1000",
237+
"--profile_period=1000",
238238
#endif // FML_OS_IOS && FML_ARCH_CPU_ARM_FAMILY && FML_ARCH_CPU_ARMEL
239239
};
240240
} else {

runtime/runtime_controller.cc

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -341,15 +341,14 @@ void RuntimeController::ScheduleFrame() {
341341
}
342342

343343
// |PlatformConfigurationClient|
344-
void RuntimeController::Render(Scene* scene) {
345-
// TODO(dkwingsmt): Currently only supports a single window.
346-
int64_t view_id = kFlutterImplicitViewId;
344+
void RuntimeController::Render(int64_t view_id, Scene* scene) {
347345
const ViewportMetrics* view_metrics =
348346
UIDartState::Current()->platform_configuration()->GetMetrics(view_id);
349347
if (view_metrics == nullptr) {
350348
return;
351349
}
352-
client_.Render(scene->takeLayerTree(view_metrics->physical_width,
350+
client_.Render(view_id,
351+
scene->takeLayerTree(view_metrics->physical_width,
353352
view_metrics->physical_height),
354353
view_metrics->device_pixel_ratio);
355354
}

runtime/runtime_controller.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -658,7 +658,7 @@ class RuntimeController : public PlatformConfigurationClient {
658658
void ScheduleFrame() override;
659659

660660
// |PlatformConfigurationClient|
661-
void Render(Scene* scene) override;
661+
void Render(int64_t view_id, Scene* scene) override;
662662

663663
// |PlatformConfigurationClient|
664664
void UpdateSemantics(SemanticsUpdate* update) override;

0 commit comments

Comments
 (0)