Flutter Engine
vsync_waiter.cc
Go to the documentation of this file.
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/vsync_waiter.h"
6 
7 #include "flutter/fml/task_runner.h"
8 #include "flutter/fml/trace_event.h"
9 
10 namespace flutter {
11 
12 static constexpr const char* kVsyncFlowName = "VsyncFlow";
13 
14 #if defined(OS_FUCHSIA)
15 // ________ _________ ________ ________
16 // |\ ____\|\___ ___\\ __ \|\ __ \
17 // \ \ \___|\|___ \ \_\ \ \|\ \ \ \|\ \
18 // \ \_____ \ \ \ \ \ \ \\\ \ \ ____\
19 // \|____|\ \ \ \ \ \ \ \\\ \ \ \___|
20 // ____\_\ \ \ \__\ \ \_______\ \__\
21 // |\_________\ \|__| \|_______|\|__|
22 // \|_________|
23 //
24 // Fuchsia benchmarks depend on this trace event's name. Please do not change
25 // it without checking that the changes are compatible with Fuchsia benchmarks
26 // first!
27 static constexpr const char* kVsyncTraceName = "vsync callback";
28 #else
29 static constexpr const char* kVsyncTraceName = "VsyncProcessCallback";
30 #endif
31 
33  : task_runners_(std::move(task_runners)) {}
34 
35 VsyncWaiter::~VsyncWaiter() = default;
36 
37 // Public method invoked by the animator.
39  if (!callback) {
40  return;
41  }
42 
43  TRACE_EVENT0("flutter", "AsyncWaitForVsync");
44 
45  {
46  std::scoped_lock lock(callback_mutex_);
47  if (callback_) {
48  // The animator may request a frame more than once within a frame
49  // interval. Multiple calls to request frame must result in a single
50  // callback per frame interval.
51  TRACE_EVENT_INSTANT0("flutter", "MultipleCallsToVsyncInFrameInterval");
52  return;
53  }
54  callback_ = std::move(callback);
55  if (secondary_callback_) {
56  // Return directly as `AwaitVSync` is already called by
57  // `ScheduleSecondaryCallback`.
58  return;
59  }
60  }
61  AwaitVSync();
62 }
63 
66 
67  if (!callback) {
68  return;
69  }
70 
71  TRACE_EVENT0("flutter", "ScheduleSecondaryCallback");
72 
73  {
74  std::scoped_lock lock(callback_mutex_);
75  if (secondary_callback_) {
76  // Multiple schedules must result in a single callback per frame interval.
77  TRACE_EVENT_INSTANT0("flutter",
78  "MultipleCallsToSecondaryVsyncInFrameInterval");
79  return;
80  }
81  secondary_callback_ = std::move(callback);
82  if (callback_) {
83  // Return directly as `AwaitVSync` is already called by
84  // `AsyncWaitForVsync`.
85  return;
86  }
87  }
88  AwaitVSync();
89 }
90 
92  fml::TimePoint frame_target_time) {
93  Callback callback;
94  fml::closure secondary_callback;
95 
96  {
97  std::scoped_lock lock(callback_mutex_);
98  callback = std::move(callback_);
99  secondary_callback = std::move(secondary_callback_);
100  }
101 
102  if (!callback && !secondary_callback) {
103  // This means that the vsync waiter implementation fired a callback for a
104  // request we did not make. This is a paranoid check but we still want to
105  // make sure we catch misbehaving vsync implementations.
106  TRACE_EVENT_INSTANT0("flutter", "MismatchedFrameCallback");
107  return;
108  }
109 
110  if (callback) {
111  auto flow_identifier = fml::tracing::TraceNonce();
112 
113  // The base trace ensures that flows have a root to begin from if one does
114  // not exist. The trace viewer will ignore traces that have no base event
115  // trace. While all our message loops insert a base trace trace
116  // (MessageLoop::RunExpiredTasks), embedders may not.
117  TRACE_EVENT0("flutter", "VsyncFireCallback");
118 
119  TRACE_FLOW_BEGIN("flutter", kVsyncFlowName, flow_identifier);
120 
122  [callback, flow_identifier, frame_start_time, frame_target_time]() {
123  FML_TRACE_EVENT("flutter", kVsyncTraceName, "StartTime",
124  frame_start_time, "TargetTime", frame_target_time);
125  callback(frame_start_time, frame_target_time);
126  TRACE_FLOW_END("flutter", kVsyncFlowName, flow_identifier);
127  },
128  frame_start_time);
129  }
130 
131  if (secondary_callback) {
133  std::move(secondary_callback), frame_start_time);
134  }
135 }
136 
137 } // namespace flutter
VsyncWaiter(TaskRunners task_runners)
Definition: vsync_waiter.cc:32
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:75
#define FML_DCHECK(condition)
Definition: logging.h:86
#define TRACE_EVENT_INSTANT0(category_group, name)
Definition: trace_event.h:104
#define TRACE_FLOW_END(category, name, id)
Definition: trace_event.h:121
std::function< void(fml::TimePoint frame_start_time, fml::TimePoint frame_target_time)> Callback
Definition: vsync_waiter.h:22
Definition: ref_ptr.h:252
virtual void PostTaskForTime(const fml::closure &task, fml::TimePoint target_time)
Definition: task_runner.cc:28
TaskRunners task_runners_
static constexpr const char * kVsyncFlowName
Definition: vsync_waiter.cc:12
std::function< void()> closure
Definition: closure.h:14
#define TRACE_FLOW_BEGIN(category, name, id)
Definition: trace_event.h:115
static constexpr const char * kVsyncTraceName
Definition: vsync_waiter.cc:29
virtual void AwaitVSync()=0
void AsyncWaitForVsync(const Callback &callback)
Definition: vsync_waiter.cc:38
fml::RefPtr< fml::TaskRunner > GetUITaskRunner() const
Definition: task_runners.cc:34
void FireCallback(fml::TimePoint frame_start_time, fml::TimePoint frame_target_time)
Definition: vsync_waiter.cc:91
void ScheduleSecondaryCallback(const fml::closure &callback)
Definition: vsync_waiter.cc:64
const TaskRunners task_runners_
Definition: vsync_waiter.h:39
virtual bool RunsTasksOnCurrentThread()
Definition: task_runner.cc:43
size_t TraceNonce()
Definition: trace_event.cc:291
#define FML_TRACE_EVENT(category_group, name,...)
Definition: trace_event.h:71