Skip to content

Commit

Permalink
Reverts "Multiview pipeline" (flutter#47174)
Browse files Browse the repository at this point in the history
Reverts flutter#44473
Initiated by: dkwingsmt
This change reverts the following previous change:
Original Description:
This PR makes `Animator` able to handle multiple views, and updates unit tests accordingly.

Before:
<img width="543" alt="image" src="https://github.com/flutter/engine/assets/1596656/f7d0e0e4-cc85-4a6e-b516-1896ac3c1b35">

After:
<img width="614" alt="image" src="https://github.com/flutter/engine/assets/1596656/68106301-66ef-4cd1-aeaf-d9c6127ccec2">

Now `Animator::Render` must be called during `Animator::BeginFrame`, which is split into `BeginFrame` and `EndFrame`. This requirement is made possible by flutter#45555. The reason to split is to allow `ShellTest::PumpOneFrame` to insert a render from C++ code.

`ShellTest::PumpOneFrame` is also refactored to allow pumping a frame without any views.

A few unit tests are tweaked to resolve racing condition.

[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
  • Loading branch information
auto-submit[bot] authored Oct 20, 2023
1 parent d9f2453 commit 4a65910
Show file tree
Hide file tree
Showing 28 changed files with 193 additions and 731 deletions.
24 changes: 1 addition & 23 deletions flow/frame_timings.cc
Original file line number Diff line number Diff line change
Expand Up @@ -254,30 +254,8 @@ const char* FrameTimingsRecorder::GetFrameNumberTraceArg() const {
return frame_number_trace_arg_val_.c_str();
}

static const char* StateToString(FrameTimingsRecorder::State state) {
#ifndef NDEBUG
switch (state) {
case FrameTimingsRecorder::State::kUninitialized:
return "kUninitialized";
case FrameTimingsRecorder::State::kVsync:
return "kVsync";
case FrameTimingsRecorder::State::kBuildStart:
return "kBuildStart";
case FrameTimingsRecorder::State::kBuildEnd:
return "kBuildEnd";
case FrameTimingsRecorder::State::kRasterStart:
return "kRasterStart";
case FrameTimingsRecorder::State::kRasterEnd:
return "kRasterEnd";
};
FML_UNREACHABLE();
#endif
return "";
}

void FrameTimingsRecorder::AssertInState(State state) const {
FML_DCHECK(state_ == state) << "Expected state " << StateToString(state)
<< ", actual state " << StateToString(state_);
FML_DCHECK(state_ == state);
}

} // namespace flutter
3 changes: 0 additions & 3 deletions flow/frame_timings.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ class FrameTimingsRecorder {
public:
/// Various states that the recorder can be in. When created the recorder is
/// in an unitialized state and transtions in sequential order of the states.
// After adding an item to this enum, modify StateToString accordingly.
enum class State : uint32_t {
kUninitialized,
kVsync,
Expand Down Expand Up @@ -122,8 +121,6 @@ class FrameTimingsRecorder {
///
/// Instead of adding a `GetState` method and asserting on the result, this
/// method prevents other logic from relying on the state.
///
/// In opt builds, this call is a no-op.
void AssertInState(State state) const;

private:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ namespace impeller {
DirectionalGaussianBlurFilterContents::DirectionalGaussianBlurFilterContents() =
default;

DirectionalGaussianBlurFilterContents::~
DirectionalGaussianBlurFilterContents() = default;
DirectionalGaussianBlurFilterContents::
~DirectionalGaussianBlurFilterContents() = default;

void DirectionalGaussianBlurFilterContents::SetSigma(Sigma sigma) {
blur_sigma_ = sigma;
Expand Down
2 changes: 1 addition & 1 deletion lib/ui/dart_ui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ typedef CanvasPath Path;
V(NativeStringAttribute::initSpellOutStringAttribute, 3) \
V(PlatformConfigurationNativeApi::DefaultRouteName, 0) \
V(PlatformConfigurationNativeApi::ScheduleFrame, 0) \
V(PlatformConfigurationNativeApi::Render, 2) \
V(PlatformConfigurationNativeApi::Render, 1) \
V(PlatformConfigurationNativeApi::UpdateSemantics, 1) \
V(PlatformConfigurationNativeApi::SetNeedsReportTimings, 1) \
V(PlatformConfigurationNativeApi::SetIsolateDebugName, 1) \
Expand Down
10 changes: 1 addition & 9 deletions lib/ui/painting/image_dispose_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#define FML_USED_ON_EMBEDDER

#include "flutter/common/task_runners.h"
#include "flutter/fml/synchronization/count_down_latch.h"
#include "flutter/fml/synchronization/waitable_event.h"
#include "flutter/lib/ui/painting/canvas.h"
#include "flutter/lib/ui/painting/image.h"
Expand Down Expand Up @@ -58,10 +57,6 @@ TEST_F(ImageDisposeTest, ImageReleasedAfterFrameAndDisposePictureAndLayer) {
};

Settings settings = CreateSettingsForFixture();
fml::CountDownLatch frame_latch{2};
settings.frame_rasterized_callback = [&frame_latch](const FrameTiming& t) {
frame_latch.CountDown();
};
auto task_runner = CreateNewThread();
TaskRunners task_runners("test", // label
GetCurrentTaskRunner(), // platform
Expand All @@ -88,15 +83,12 @@ TEST_F(ImageDisposeTest, ImageReleasedAfterFrameAndDisposePictureAndLayer) {
shell->RunEngine(std::move(configuration), [&](auto result) {
ASSERT_EQ(result, Engine::RunStatus::Success);
});

message_latch_.Wait();

ASSERT_TRUE(current_display_list_);
ASSERT_TRUE(current_image_);

// Wait for 2 frames to be rasterized. The 2nd frame releases resources of the
// 1st frame.
frame_latch.Wait();

// Force a drain the SkiaUnrefQueue. The engine does this normally as frames
// pump, but we force it here to make the test more deterministic.
message_latch_.Reset();
Expand Down
6 changes: 3 additions & 3 deletions lib/ui/window.dart
Original file line number Diff line number Diff line change
Expand Up @@ -362,12 +362,12 @@ class FlutterView {
return true;
}());
if (validRender) {
_render(viewId, scene as _NativeScene);
_render(scene as _NativeScene);
}
}

@Native<Void Function(Int64, Pointer<Void>)>(symbol: 'PlatformConfigurationNativeApi::Render')
external static void _render(int viewId, _NativeScene scene);
@Native<Void Function(Pointer<Void>)>(symbol: 'PlatformConfigurationNativeApi::Render')
external static void _render(_NativeScene scene);

/// Change the retained semantics data about this [FlutterView].
///
Expand Down
5 changes: 2 additions & 3 deletions lib/ui/window/platform_configuration.cc
Original file line number Diff line number Diff line change
Expand Up @@ -449,10 +449,9 @@ void PlatformConfiguration::CompletePlatformMessageResponse(
response->Complete(std::make_unique<fml::DataMapping>(std::move(data)));
}

void PlatformConfigurationNativeApi::Render(int64_t view_id, Scene* scene) {
void PlatformConfigurationNativeApi::Render(Scene* scene) {
UIDartState::ThrowIfUIOperationsProhibited();
UIDartState::Current()->platform_configuration()->client()->Render(view_id,
scene);
UIDartState::Current()->platform_configuration()->client()->Render(scene);
}

void PlatformConfigurationNativeApi::SetNeedsReportTimings(bool value) {
Expand Down
4 changes: 2 additions & 2 deletions lib/ui/window/platform_configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class PlatformConfigurationClient {
/// @brief Updates the client's rendering on the GPU with the newly
/// provided Scene.
///
virtual void Render(int64_t view_id, Scene* scene) = 0;
virtual void Render(Scene* scene) = 0;

//--------------------------------------------------------------------------
/// @brief Receives an updated semantics tree from the Framework.
Expand Down Expand Up @@ -557,7 +557,7 @@ class PlatformConfigurationNativeApi {

static void ScheduleFrame();

static void Render(int64_t view_id, Scene* scene);
static void Render(Scene* scene);

static void UpdateSemantics(SemanticsUpdate* update);

Expand Down
158 changes: 0 additions & 158 deletions lib/ui/window/platform_configuration_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,166 +15,8 @@
#include "flutter/shell/common/shell_test.h"
#include "flutter/shell/common/thread_host.h"
#include "flutter/testing/testing.h"
#include "gmock/gmock.h"

namespace flutter {

namespace {

static constexpr int64_t kImplicitViewId = 0;

static void PostSync(const fml::RefPtr<fml::TaskRunner>& task_runner,
const fml::closure& task) {
fml::AutoResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(task_runner, [&latch, &task] {
task();
latch.Signal();
});
latch.Wait();
}

class MockRuntimeDelegate : public RuntimeDelegate {
public:
MOCK_METHOD(std::string, DefaultRouteName, (), (override));
MOCK_METHOD(void, ScheduleFrame, (bool), (override));
MOCK_METHOD(void,
Render,
(int64_t, std::unique_ptr<flutter::LayerTree>, float),
(override));
MOCK_METHOD(void,
UpdateSemantics,
(SemanticsNodeUpdates, CustomAccessibilityActionUpdates),
(override));
MOCK_METHOD(void,
HandlePlatformMessage,
(std::unique_ptr<PlatformMessage>),
(override));
MOCK_METHOD(FontCollection&, GetFontCollection, (), (override));
MOCK_METHOD(std::shared_ptr<AssetManager>, GetAssetManager, (), (override));
MOCK_METHOD(void, OnRootIsolateCreated, (), (override));
MOCK_METHOD(void,
UpdateIsolateDescription,
(const std::string, int64_t),
(override));
MOCK_METHOD(void, SetNeedsReportTimings, (bool), (override));
MOCK_METHOD(std::unique_ptr<std::vector<std::string>>,
ComputePlatformResolvedLocale,
(const std::vector<std::string>&),
(override));
MOCK_METHOD(void, RequestDartDeferredLibrary, (intptr_t), (override));
MOCK_METHOD(std::weak_ptr<PlatformMessageHandler>,
GetPlatformMessageHandler,
(),
(const, override));
MOCK_METHOD(void, SendChannelUpdate, (std::string, bool), (override));
MOCK_METHOD(double,
GetScaledFontSize,
(double font_size, int configuration_id),
(const, override));
};

class MockPlatformMessageHandler : public PlatformMessageHandler {
public:
MOCK_METHOD(void,
HandlePlatformMessage,
(std::unique_ptr<PlatformMessage> message),
(override));
MOCK_METHOD(bool,
DoesHandlePlatformMessageOnPlatformThread,
(),
(const, override));
MOCK_METHOD(void,
InvokePlatformMessageResponseCallback,
(int response_id, std::unique_ptr<fml::Mapping> mapping),
(override));
MOCK_METHOD(void,
InvokePlatformMessageEmptyResponseCallback,
(int response_id),
(override));
};

// A class that can launch a RuntimeController with the specified
// RuntimeDelegate.
//
// To use this class, contruct this class with Create, call LaunchRootIsolate,
// and use the controller with ControllerTaskSync().
class RuntimeControllerContext {
public:
using ControllerCallback = std::function<void(RuntimeController&)>;

[[nodiscard]] static std::unique_ptr<RuntimeControllerContext> Create(
Settings settings, //
const TaskRunners& task_runners, //
RuntimeDelegate& client) {
auto [vm, isolate_snapshot] = Shell::InferVmInitDataFromSettings(settings);
FML_CHECK(vm) << "Must be able to initialize the VM.";
// Construct the class with `new` because `make_unique` has no access to the
// private constructor.
RuntimeControllerContext* raw_pointer = new RuntimeControllerContext(
settings, task_runners, client, std::move(vm), isolate_snapshot);
return std::unique_ptr<RuntimeControllerContext>(raw_pointer);
}

~RuntimeControllerContext() {
PostSync(task_runners_.GetUITaskRunner(),
[&]() { runtime_controller_.reset(); });
}

// Launch the root isolate. The post_launch callback will be executed in the
// same UI task, which can be used to create initial views.
void LaunchRootIsolate(RunConfiguration& configuration,
ControllerCallback post_launch) {
PostSync(task_runners_.GetUITaskRunner(), [&]() {
bool launch_success = runtime_controller_->LaunchRootIsolate(
settings_, //
[]() {}, //
configuration.GetEntrypoint(), //
configuration.GetEntrypointLibrary(), //
configuration.GetEntrypointArgs(), //
configuration.TakeIsolateConfiguration()); //
ASSERT_TRUE(launch_success);
post_launch(*runtime_controller_);
});
}

// Run a task that operates the RuntimeController on the UI thread, and wait
// for the task to end.
void ControllerTaskSync(ControllerCallback task) {
ASSERT_TRUE(runtime_controller_);
ASSERT_TRUE(task);
PostSync(task_runners_.GetUITaskRunner(),
[&]() { task(*runtime_controller_); });
}

private:
RuntimeControllerContext(const Settings& settings,
const TaskRunners& task_runners,
RuntimeDelegate& client,
DartVMRef vm,
fml::RefPtr<const DartSnapshot> isolate_snapshot)
: settings_(settings),
task_runners_(task_runners),
isolate_snapshot_(std::move(isolate_snapshot)),
vm_(std::move(vm)),
runtime_controller_(std::make_unique<RuntimeController>(
client,
&vm_,
std::move(isolate_snapshot_),
settings.idle_notification_callback, // idle notification callback
flutter::PlatformData(), // platform data
settings.isolate_create_callback, // isolate create callback
settings.isolate_shutdown_callback, // isolate shutdown callback
settings.persistent_isolate_data, // persistent isolate data
UIDartState::Context{task_runners})) {}

Settings settings_;
TaskRunners task_runners_;
fml::RefPtr<const DartSnapshot> isolate_snapshot_;
DartVMRef vm_;
std::unique_ptr<RuntimeController> runtime_controller_;
};
} // namespace

namespace testing {

class PlatformConfigurationTest : public ShellTest {};
Expand Down
28 changes: 14 additions & 14 deletions runtime/dart_vm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -219,22 +219,22 @@ static std::vector<const char*> ProfilingFlags(bool enable_profiling) {
// flags.
if (enable_profiling) {
return {
// This is the default. But just be explicit.
"--profiler",
// This instructs the profiler to walk C++ frames, and to include
// them in the profile.
"--profile-vm",
// This is the default. But just be explicit.
"--profiler",
// This instructs the profiler to walk C++ frames, and to include
// them in the profile.
"--profile-vm",
#if FML_OS_IOS && FML_ARCH_CPU_ARM_FAMILY && FML_ARCH_CPU_ARMEL
// Set the profiler interrupt period to 500Hz instead of the
// default 1000Hz on 32-bit iOS devices to reduce average and worst
// case frame build times.
//
// Note: profile_period is time in microseconds between sampling
// events, not frequency. Frequency is calculated 1/period (or
// 1,000,000 / 2,000 -> 500Hz in this case).
"--profile_period=2000",
// Set the profiler interrupt period to 500Hz instead of the
// default 1000Hz on 32-bit iOS devices to reduce average and worst
// case frame build times.
//
// Note: profile_period is time in microseconds between sampling
// events, not frequency. Frequency is calculated 1/period (or
// 1,000,000 / 2,000 -> 500Hz in this case).
"--profile_period=2000",
#else
"--profile_period=1000",
"--profile_period=1000",
#endif // FML_OS_IOS && FML_ARCH_CPU_ARM_FAMILY && FML_ARCH_CPU_ARMEL
};
} else {
Expand Down
7 changes: 4 additions & 3 deletions runtime/runtime_controller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -341,14 +341,15 @@ void RuntimeController::ScheduleFrame() {
}

// |PlatformConfigurationClient|
void RuntimeController::Render(int64_t view_id, Scene* scene) {
void RuntimeController::Render(Scene* scene) {
// TODO(dkwingsmt): Currently only supports a single window.
int64_t view_id = kFlutterImplicitViewId;
const ViewportMetrics* view_metrics =
UIDartState::Current()->platform_configuration()->GetMetrics(view_id);
if (view_metrics == nullptr) {
return;
}
client_.Render(view_id,
scene->takeLayerTree(view_metrics->physical_width,
client_.Render(scene->takeLayerTree(view_metrics->physical_width,
view_metrics->physical_height),
view_metrics->device_pixel_ratio);
}
Expand Down
2 changes: 1 addition & 1 deletion runtime/runtime_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ class RuntimeController : public PlatformConfigurationClient {
void ScheduleFrame() override;

// |PlatformConfigurationClient|
void Render(int64_t view_id, Scene* scene) override;
void Render(Scene* scene) override;

// |PlatformConfigurationClient|
void UpdateSemantics(SemanticsUpdate* update) override;
Expand Down
3 changes: 1 addition & 2 deletions runtime/runtime_delegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ class RuntimeDelegate {

virtual void ScheduleFrame(bool regenerate_layer_trees = true) = 0;

virtual void Render(int64_t view_id,
std::unique_ptr<flutter::LayerTree> layer_tree,
virtual void Render(std::unique_ptr<flutter::LayerTree> layer_tree,
float device_pixel_ratio) = 0;

virtual void UpdateSemantics(SemanticsNodeUpdates update,
Expand Down
Loading

0 comments on commit 4a65910

Please sign in to comment.