5#include "flutter/shell/common/animator.h"
7#include "flutter/common/constants.h"
8#include "flutter/flow/frame_timings.h"
9#include "flutter/fml/time/time_point.h"
10#include "flutter/fml/trace_event.h"
11#include "third_party/dart/runtime/include/dart_tools_api.h"
27 std::unique_ptr<VsyncWaiter> waiter)
30 waiter_(
std::move(waiter)),
38 task_runners.GetPlatformTaskRunner() ==
39 task_runners.GetRasterTaskRunner()
43 pending_frame_semaphore_(1),
52 [
self = weak_factory_.GetWeakPtr(), trace_flow_id] {
56 self->trace_flow_ids_.push_back(trace_flow_id);
57 self->ScheduleMaybeClearTraceFlowIds();
61void Animator::BeginFrame(
62 std::unique_ptr<FrameTimingsRecorder> frame_timings_recorder) {
64 frame_request_number_);
67 layer_trees_tasks_.clear();
69 frame_request_number_++;
71 frame_timings_recorder_ = std::move(frame_timings_recorder);
74 size_t flow_id_count = trace_flow_ids_.size();
75 std::unique_ptr<uint64_t[]> flow_ids =
76 std::make_unique<uint64_t[]>(flow_id_count);
77 for (
size_t i = 0;
i < flow_id_count; ++
i) {
78 flow_ids.get()[
i] = trace_flow_ids_.at(
i);
82 "Animator::BeginFrame", flow_id_count,
85 while (!trace_flow_ids_.empty()) {
86 uint64_t trace_flow_id = trace_flow_ids_.front();
88 trace_flow_ids_.pop_front();
91 frame_scheduled_ =
false;
92 regenerate_layer_trees_ =
false;
93 pending_frame_semaphore_.Signal();
95 if (!producer_continuation_) {
99 producer_continuation_ = layer_tree_pipeline_->Produce();
101 if (!producer_continuation_) {
115 frame_timings_recorder_->GetVsyncTargetTime();
116 dart_frame_deadline_ = frame_target_time.
ToEpochDelta();
117 uint64_t frame_number = frame_timings_recorder_->GetFrameNumber();
118 delegate_.OnAnimatorBeginFrame(frame_target_time, frame_number);
121void Animator::EndFrame() {
122 if (frame_timings_recorder_ ==
nullptr) {
128 if (!layer_trees_tasks_.empty()) {
132 delegate_.OnAnimatorUpdateLatestFrameTargetTime(
133 frame_timings_recorder_->GetVsyncTargetTime());
136 std::vector<std::unique_ptr<LayerTreeTask>> layer_tree_task_list;
137 layer_tree_task_list.reserve(layer_trees_tasks_.size());
138 for (
auto& [view_id, layer_tree_task] : layer_trees_tasks_) {
139 layer_tree_task_list.push_back(std::move(layer_tree_task));
141 layer_trees_tasks_.clear();
142 PipelineProduceResult
result = producer_continuation_.Complete(
143 std::make_unique<FrameItem>(std::move(layer_tree_task_list),
144 std::move(frame_timings_recorder_)));
147 FML_DLOG(INFO) <<
"Failed to commit to the pipeline";
148 }
else if (!
result.is_first_item) {
153 delegate_.OnAnimatorDraw(layer_tree_pipeline_);
156 frame_timings_recorder_ =
nullptr;
158 if (!frame_scheduled_ && has_rendered_) {
165 [
self = weak_factory_.GetWeakPtr()]() {
172 if (!
self->frame_scheduled_) {
174 fml::TimeDelta::FromMicroseconds(Dart_TimelineGetMicros());
175 if (now > self->dart_frame_deadline_) {
176 TRACE_EVENT0(
"flutter",
"BeginFrame idle callback");
177 self->delegate_.OnAnimatorNotifyIdle(
178 now + fml::TimeDelta::FromMilliseconds(100));
182 kNotifyIdleTaskWaitTime);
185 FML_DCHECK(frame_timings_recorder_ ==
nullptr);
188void Animator::Render(int64_t view_id,
189 std::unique_ptr<flutter::LayerTree> layer_tree,
190 float device_pixel_ratio) {
191 has_rendered_ =
true;
193 if (!frame_timings_recorder_) {
196 frame_timings_recorder_ = std::make_unique<FrameTimingsRecorder>();
198 frame_timings_recorder_->RecordVsync(placeholder_time, placeholder_time);
199 frame_timings_recorder_->RecordBuildStart(placeholder_time);
203 "Animator::Render", 0,
208 layer_trees_tasks_.try_emplace(
209 view_id, std::make_unique<LayerTreeTask>(view_id, std::move(layer_tree),
210 device_pixel_ratio));
213const std::weak_ptr<VsyncWaiter> Animator::GetVsyncWaiter()
const {
214 std::weak_ptr<VsyncWaiter> weak = waiter_;
218bool Animator::CanReuseLastLayerTrees() {
219 return !regenerate_layer_trees_;
222void Animator::DrawLastLayerTrees(
223 std::unique_ptr<FrameTimingsRecorder> frame_timings_recorder) {
226 TRACE_EVENT0(
"flutter",
"Animator::DrawLastLayerTrees");
228 pending_frame_semaphore_.Signal();
234 frame_timings_recorder->RecordBuildStart(now);
235 frame_timings_recorder->RecordBuildEnd(now);
236 delegate_.OnAnimatorDrawLastLayerTrees(std::move(frame_timings_recorder));
239void Animator::RequestFrame(
bool regenerate_layer_trees) {
240 if (regenerate_layer_trees && !regenerate_layer_trees_) {
246 frame_request_number_);
247 regenerate_layer_trees_ =
true;
250 if (!pending_frame_semaphore_.TryWait()) {
264 [
self = weak_factory_.GetWeakPtr()]() {
270 frame_scheduled_ =
true;
273void Animator::AwaitVSync() {
274 waiter_->AsyncWaitForVsync(
275 [
self = weak_factory_.GetWeakPtr()](
276 std::unique_ptr<FrameTimingsRecorder> frame_timings_recorder) {
278 if (self->CanReuseLastLayerTrees()) {
279 self->DrawLastLayerTrees(std::move(frame_timings_recorder));
281 self->BeginFrame(std::move(frame_timings_recorder));
287 delegate_.OnAnimatorNotifyIdle(dart_frame_deadline_);
291void Animator::OnAllViewsRendered() {
292 if (!layer_trees_tasks_.empty()) {
297void Animator::ScheduleSecondaryVsyncCallback(uintptr_t
id,
299 waiter_->ScheduleSecondaryCallback(
id,
callback);
302void Animator::ScheduleMaybeClearTraceFlowIds() {
303 waiter_->ScheduleSecondaryCallback(
304 reinterpret_cast<uintptr_t
>(
this), [
self = weak_factory_.GetWeakPtr()] {
308 if (!
self->frame_scheduled_ && !
self->trace_flow_ids_.empty()) {
309 size_t flow_id_count = self->trace_flow_ids_.size();
310 std::unique_ptr<uint64_t[]> flow_ids =
311 std::make_unique<uint64_t[]>(flow_id_count);
312 for (size_t i = 0; i < flow_id_count; ++i) {
313 flow_ids.get()[i] = self->trace_flow_ids_.at(i);
317 "flutter",
"Animator::ScheduleMaybeClearTraceFlowIds - callback",
318 flow_id_count, flow_ids.get());
320 while (!
self->trace_flow_ids_.empty()) {
321 auto flow_id = self->trace_flow_ids_.front();
322 TRACE_FLOW_END(
"flutter",
"PointerEvent", flow_id);
323 self->trace_flow_ids_.pop_front();
Animator(Delegate &delegate, const TaskRunners &task_runners, std::unique_ptr< VsyncWaiter > waiter)
void EnqueueTraceFlowId(uint64_t trace_flow_id)
fml::RefPtr< fml::TaskRunner > GetUITaskRunner() const
static void RunNowOrPostTask(const fml::RefPtr< fml::TaskRunner > &runner, const fml::closure &task)
static constexpr TimeDelta FromMilliseconds(int64_t millis)
TimeDelta ToEpochDelta() const
TaskRunners task_runners_
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
#define FML_DLOG(severity)
#define FML_DCHECK(condition)
#define TRACE_EVENT_WITH_FRAME_NUMBER(recorder, category_group, name, flow_id_count, flow_ids)
std::function< void()> closure
#define TRACE_EVENT0(category_group, name)
#define TRACE_EVENT_ASYNC_END0(category_group, name, id)
#define TRACE_FLOW_END(category, name, id)
#define TRACE_EVENT0_WITH_FLOW_IDS(category_group, name, flow_id_count, flow_ids)
#define TRACE_EVENT_ASYNC_BEGIN0(category_group, name, id)