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

Commit f582c03

Browse files
committed
Reland "Remove pipeline in favor of layer tree holder (#18901)"
This reverts commit eba7627.
1 parent 2e10a97 commit f582c03

17 files changed

+281
-536
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -638,10 +638,10 @@ FILE: ../../../flutter/shell/common/engine_unittests.cc
638638
FILE: ../../../flutter/shell/common/fixtures/shell_test.dart
639639
FILE: ../../../flutter/shell/common/fixtures/shelltest_screenshot.png
640640
FILE: ../../../flutter/shell/common/input_events_unittests.cc
641+
FILE: ../../../flutter/shell/common/layer_tree_holder.cc
642+
FILE: ../../../flutter/shell/common/layer_tree_holder.h
643+
FILE: ../../../flutter/shell/common/layer_tree_holder_unittests.cc
641644
FILE: ../../../flutter/shell/common/persistent_cache_unittests.cc
642-
FILE: ../../../flutter/shell/common/pipeline.cc
643-
FILE: ../../../flutter/shell/common/pipeline.h
644-
FILE: ../../../flutter/shell/common/pipeline_unittests.cc
645645
FILE: ../../../flutter/shell/common/platform_view.cc
646646
FILE: ../../../flutter/shell/common/platform_view.h
647647
FILE: ../../../flutter/shell/common/pointer_data_dispatcher.cc

shell/common/BUILD.gn

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ source_set("common") {
6969
"display_manager.h",
7070
"engine.cc",
7171
"engine.h",
72-
"pipeline.cc",
73-
"pipeline.h",
72+
"layer_tree_holder.cc",
73+
"layer_tree_holder.h",
7474
"platform_view.cc",
7575
"platform_view.h",
7676
"pointer_data_dispatcher.cc",
@@ -242,8 +242,8 @@ if (enable_unittests) {
242242
"canvas_spy_unittests.cc",
243243
"engine_unittests.cc",
244244
"input_events_unittests.cc",
245+
"layer_tree_holder_unittests.cc",
245246
"persistent_cache_unittests.cc",
246-
"pipeline_unittests.cc",
247247
"rasterizer_unittests.cc",
248248
"shell_unittests.cc",
249249
"skp_shader_warmup_unittests.cc",

shell/common/animator.cc

Lines changed: 4 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -29,27 +29,15 @@ Animator::Animator(Delegate& delegate,
2929
last_vsync_start_time_(),
3030
last_frame_target_time_(),
3131
dart_frame_deadline_(0),
32-
#if SHELL_ENABLE_METAL
33-
layer_tree_pipeline_(fml::MakeRefCounted<LayerTreePipeline>(2)),
34-
#else // SHELL_ENABLE_METAL
35-
// TODO(dnfield): We should remove this logic and set the pipeline depth
36-
// back to 2 in this case. See
37-
// https://github.com/flutter/engine/pull/9132 for discussion.
38-
layer_tree_pipeline_(fml::MakeRefCounted<LayerTreePipeline>(
39-
task_runners.GetPlatformTaskRunner() ==
40-
task_runners.GetRasterTaskRunner()
41-
? 1
42-
: 2)),
43-
#endif // SHELL_ENABLE_METAL
32+
layer_tree_holder_(std::make_shared<LayerTreeHolder>()),
4433
pending_frame_semaphore_(1),
4534
frame_number_(1),
4635
paused_(false),
4736
regenerate_layer_tree_(false),
4837
frame_scheduled_(false),
4938
notify_idle_task_id_(0),
5039
dimension_change_pending_(false),
51-
weak_factory_(this) {
52-
}
40+
weak_factory_(this) {}
5341

5442
Animator::~Animator() = default;
5543

@@ -111,25 +99,6 @@ void Animator::BeginFrame(fml::TimePoint vsync_start_time,
11199
regenerate_layer_tree_ = false;
112100
pending_frame_semaphore_.Signal();
113101

114-
if (!producer_continuation_) {
115-
// We may already have a valid pipeline continuation in case a previous
116-
// begin frame did not result in an Animation::Render. Simply reuse that
117-
// instead of asking the pipeline for a fresh continuation.
118-
producer_continuation_ = layer_tree_pipeline_->Produce();
119-
120-
if (!producer_continuation_) {
121-
// If we still don't have valid continuation, the pipeline is currently
122-
// full because the consumer is being too slow. Try again at the next
123-
// frame interval.
124-
RequestFrame();
125-
return;
126-
}
127-
}
128-
129-
// We have acquired a valid continuation from the pipeline and are ready
130-
// to service potential frame.
131-
FML_DCHECK(producer_continuation_);
132-
133102
last_frame_begin_time_ = fml::TimePoint::Now();
134103
last_vsync_start_time_ = vsync_start_time;
135104
fml::tracing::TraceEventAsyncComplete("flutter", "VsyncSchedulingOverhead",
@@ -183,13 +152,8 @@ void Animator::Render(std::unique_ptr<flutter::LayerTree> layer_tree) {
183152
layer_tree->RecordBuildTime(last_vsync_start_time_, last_frame_begin_time_,
184153
last_frame_target_time_);
185154

186-
// Commit the pending continuation.
187-
bool result = producer_continuation_.Complete(std::move(layer_tree));
188-
if (!result) {
189-
FML_DLOG(INFO) << "No pending continuation to commit";
190-
}
191-
192-
delegate_.OnAnimatorDraw(layer_tree_pipeline_, last_frame_target_time_);
155+
layer_tree_holder_->PushIfNewer(std::move(layer_tree));
156+
delegate_.OnAnimatorDraw(layer_tree_holder_, last_frame_target_time_);
193157
}
194158

195159
bool Animator::CanReuseLastLayerTree() {

shell/common/animator.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@
66
#define FLUTTER_SHELL_COMMON_ANIMATOR_H_
77

88
#include <deque>
9+
#include <memory>
910

1011
#include "flutter/common/task_runners.h"
1112
#include "flutter/fml/memory/ref_ptr.h"
1213
#include "flutter/fml/memory/weak_ptr.h"
1314
#include "flutter/fml/synchronization/semaphore.h"
1415
#include "flutter/fml/time/time_point.h"
15-
#include "flutter/shell/common/pipeline.h"
16+
#include "flutter/shell/common/layer_tree_holder.h"
1617
#include "flutter/shell/common/rasterizer.h"
1718
#include "flutter/shell/common/vsync_waiter.h"
1819

@@ -35,7 +36,7 @@ class Animator final {
3536
virtual void OnAnimatorNotifyIdle(int64_t deadline) = 0;
3637

3738
virtual void OnAnimatorDraw(
38-
fml::RefPtr<Pipeline<flutter::LayerTree>> pipeline,
39+
std::shared_ptr<LayerTreeHolder> layer_tree_holder,
3940
fml::TimePoint frame_target_time) = 0;
4041

4142
virtual void OnAnimatorDrawLastLayerTree() = 0;
@@ -79,8 +80,6 @@ class Animator final {
7980
void EnqueueTraceFlowId(uint64_t trace_flow_id);
8081

8182
private:
82-
using LayerTreePipeline = Pipeline<flutter::LayerTree>;
83-
8483
void BeginFrame(fml::TimePoint frame_start_time,
8584
fml::TimePoint frame_target_time);
8685

@@ -99,9 +98,8 @@ class Animator final {
9998
fml::TimePoint last_vsync_start_time_;
10099
fml::TimePoint last_frame_target_time_;
101100
int64_t dart_frame_deadline_;
102-
fml::RefPtr<LayerTreePipeline> layer_tree_pipeline_;
101+
std::shared_ptr<LayerTreeHolder> layer_tree_holder_;
103102
fml::Semaphore pending_frame_semaphore_;
104-
LayerTreePipeline::ProducerContinuation producer_continuation_;
105103
int64_t frame_number_;
106104
bool paused_;
107105
bool regenerate_layer_tree_;

shell/common/engine.h

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -476,25 +476,18 @@ class Engine final : public RuntimeDelegate,
476476
/// will cause the jank in the Flutter application:
477477
/// * The time taken by this method to create a layer-tree exceeds
478478
/// on frame interval (for example, 16.66 ms on a 60Hz display).
479-
/// * The time take by this method to generate a new layer-tree
480-
/// causes the current layer-tree pipeline depth to change. To
481-
/// illustrate this point, note that maximum pipeline depth used
482-
/// by layer tree in the engine is 2. If both the UI and GPU
483-
/// task runner tasks finish within one frame interval, the
484-
/// pipeline depth is one. If the UI thread happens to be
485-
/// working on a frame when the raster thread is still not done
486-
/// with the previous frame, the pipeline depth is 2. When the
487-
/// pipeline depth changes from 1 to 2, animations and UI
488-
/// interactions that cause the generation of the new layer tree
489-
/// appropriate for (frame_time + one frame interval) will
490-
/// actually end up at (frame_time + two frame intervals). This
491-
/// is not what code running on the UI thread expected would
492-
/// happen. This causes perceptible jank.
479+
/// * A new layer-tree produced by this method replaces a stale
480+
/// layer tree in `LayerTreeHolder`. See:
481+
/// `LayerTreeHolder::ReplaceIfNewer`. This could happen if
482+
/// rasterizer takes more than one frame interval to rasterize a
483+
/// layer tree. This would cause some frames to be skipped and
484+
/// could result in perceptible jank.
493485
///
494486
/// @param[in] frame_time The point at which the current frame interval
495487
/// began. May be used by animation interpolators,
496488
/// physics simulations, etc..
497489
///
490+
/// @see `LayerTreeHolder::ReplaceIfNewer`
498491
void BeginFrame(fml::TimePoint frame_time);
499492

500493
// |HintFreedDelegate|

shell/common/layer_tree_holder.cc

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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+
#include "flutter/shell/common/layer_tree_holder.h"
6+
7+
namespace flutter {
8+
9+
LayerTreeHolder::LayerTreeHolder() = default;
10+
11+
LayerTreeHolder::~LayerTreeHolder() = default;
12+
13+
std::unique_ptr<LayerTree> LayerTreeHolder::Pop() {
14+
std::scoped_lock lock(layer_tree_mutex);
15+
return std::move(layer_tree_);
16+
}
17+
18+
void LayerTreeHolder::PushIfNewer(
19+
std::unique_ptr<LayerTree> proposed_layer_tree) {
20+
std::scoped_lock lock(layer_tree_mutex);
21+
if (!layer_tree_ ||
22+
layer_tree_->target_time() < proposed_layer_tree->target_time()) {
23+
layer_tree_ = std::move(proposed_layer_tree);
24+
}
25+
}
26+
27+
bool LayerTreeHolder::IsEmpty() const {
28+
std::scoped_lock lock(layer_tree_mutex);
29+
return !layer_tree_;
30+
}
31+
32+
}; // namespace flutter

shell/common/layer_tree_holder.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
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_COMMON_LAYER_TREE_HOLDER_H_
6+
#define FLUTTER_SHELL_COMMON_LAYER_TREE_HOLDER_H_
7+
8+
#include <memory>
9+
10+
#include "flow/layers/layer_tree.h"
11+
12+
namespace flutter {
13+
14+
/**
15+
* @brief Holds the next `flutter::LayerTree` that needs to be rasterized. The
16+
* accesses to `LayerTreeHolder` are thread safe. This is important as this
17+
* component is accessed from both the UI and the Raster threads.
18+
*
19+
* A typical flow of events through this component would be:
20+
* 1. `flutter::Animator` pushed a layer tree to be rendered during each
21+
* `Animator::Render` call.
22+
* 2. `flutter::Rasterizer::Draw` consumes the pushed layer tree via `Pop`.
23+
*
24+
* It is important to note that if a layer tree held by this class is yet to be
25+
* consumed, it can be overriden by a newer layer tree produced by the
26+
* `Animator`. The newness of the layer tree is determined by the target time.
27+
*/
28+
class LayerTreeHolder {
29+
public:
30+
LayerTreeHolder();
31+
32+
~LayerTreeHolder();
33+
34+
/**
35+
* @brief Checks if a layer tree is currently held.
36+
*
37+
* @return true is no layer tree is held.
38+
* @return false if there is a layer tree waiting to be consumed.
39+
*/
40+
bool IsEmpty() const;
41+
42+
[[nodiscard]] std::unique_ptr<LayerTree> Pop();
43+
44+
void PushIfNewer(std::unique_ptr<LayerTree> proposed_layer_tree);
45+
46+
private:
47+
mutable std::mutex layer_tree_mutex;
48+
std::unique_ptr<LayerTree> layer_tree_;
49+
50+
FML_DISALLOW_COPY_AND_ASSIGN(LayerTreeHolder);
51+
};
52+
53+
}; // namespace flutter
54+
55+
#endif // FLUTTER_SHELL_COMMON_LAYER_TREE_HOLDER_H_
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
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 <functional>
8+
#include <future>
9+
#include <memory>
10+
11+
#include "flutter/shell/common/layer_tree_holder.h"
12+
#include "gtest/gtest.h"
13+
14+
namespace flutter {
15+
namespace testing {
16+
17+
TEST(LayerTreeHolder, EmptyOnInit) {
18+
const LayerTreeHolder layer_tree_holder;
19+
ASSERT_TRUE(layer_tree_holder.IsEmpty());
20+
}
21+
22+
TEST(LayerTreeHolder, PutOneAndGet) {
23+
LayerTreeHolder layer_tree_holder;
24+
const auto frame_size = SkISize::Make(64, 64);
25+
auto layer_tree = std::make_unique<LayerTree>(frame_size, 1.0f);
26+
layer_tree_holder.PushIfNewer(std::move(layer_tree));
27+
ASSERT_FALSE(layer_tree_holder.IsEmpty());
28+
const auto stored = layer_tree_holder.Pop();
29+
ASSERT_EQ(stored->frame_size(), frame_size);
30+
ASSERT_TRUE(layer_tree_holder.IsEmpty());
31+
}
32+
33+
TEST(LayerTreeHolder, PutMultiGetsLatest) {
34+
const auto build_begin = fml::TimePoint::Now();
35+
const auto target_time_1 = build_begin + fml::TimeDelta::FromSeconds(2);
36+
const auto target_time_2 = build_begin + fml::TimeDelta::FromSeconds(5);
37+
38+
LayerTreeHolder layer_tree_holder;
39+
const auto frame_size_1 = SkISize::Make(64, 64);
40+
auto layer_tree_1 = std::make_unique<LayerTree>(frame_size_1, 1.0f);
41+
layer_tree_1->RecordBuildTime(build_begin, build_begin, target_time_1);
42+
layer_tree_holder.PushIfNewer(std::move(layer_tree_1));
43+
44+
const auto frame_size_2 = SkISize::Make(128, 128);
45+
auto layer_tree_2 = std::make_unique<LayerTree>(frame_size_2, 1.0f);
46+
layer_tree_2->RecordBuildTime(build_begin, build_begin, target_time_2);
47+
layer_tree_holder.PushIfNewer(std::move(layer_tree_2));
48+
49+
const auto stored = layer_tree_holder.Pop();
50+
ASSERT_EQ(stored->frame_size(), frame_size_2);
51+
ASSERT_TRUE(layer_tree_holder.IsEmpty());
52+
}
53+
54+
TEST(LayerTreeHolder, RetainsOlderIfNewerFrameHasEarlierTargetTime) {
55+
const auto build_begin = fml::TimePoint::Now();
56+
const auto target_time_1 = build_begin + fml::TimeDelta::FromSeconds(5);
57+
const auto target_time_2 = build_begin + fml::TimeDelta::FromSeconds(2);
58+
59+
LayerTreeHolder layer_tree_holder;
60+
const auto frame_size_1 = SkISize::Make(64, 64);
61+
auto layer_tree_1 = std::make_unique<LayerTree>(frame_size_1, 1.0f);
62+
layer_tree_1->RecordBuildTime(build_begin, build_begin, target_time_1);
63+
layer_tree_holder.PushIfNewer(std::move(layer_tree_1));
64+
65+
const auto frame_size_2 = SkISize::Make(128, 128);
66+
auto layer_tree_2 = std::make_unique<LayerTree>(frame_size_2, 1.0f);
67+
layer_tree_2->RecordBuildTime(build_begin, build_begin, target_time_2);
68+
layer_tree_holder.PushIfNewer(std::move(layer_tree_2));
69+
70+
const auto stored = layer_tree_holder.Pop();
71+
ASSERT_EQ(stored->frame_size(), frame_size_1);
72+
ASSERT_TRUE(layer_tree_holder.IsEmpty());
73+
}
74+
75+
} // namespace testing
76+
} // namespace flutter

shell/common/pipeline.cc

Lines changed: 0 additions & 14 deletions
This file was deleted.

0 commit comments

Comments
 (0)