7#include <zircon/status.h>
9#include "flutter/fml/logging.h"
10#include "flutter/fml/trace_event.h"
19 return (time - now).ToNanoseconds();
25 std::string debug_label,
26 fuchsia::ui::composition::FlatlandHandle flatland,
29 : flatland_(flatland.Bind()),
30 error_callback_(error_callback),
31 on_frame_presented_callback_(
std::move(on_frame_presented_callback)) {
32 flatland_.set_error_handler([
callback = error_callback_](zx_status_t status) {
33 FML_LOG(
ERROR) <<
"Flatland disconnected: " << zx_status_get_string(status);
36 debug_label_ = debug_label;
37 flatland_->SetDebugName(debug_label);
38 flatland_.events().OnError =
39 fit::bind_member(
this, &FlatlandConnection::OnError);
40 flatland_.events().OnFramePresented =
41 fit::bind_member(
this, &FlatlandConnection::OnFramePresented);
42 flatland_.events().OnNextFrameBegin =
43 fit::bind_member(
this, &FlatlandConnection::OnNextFrameBegin);
50 TRACE_DURATION(
"flutter",
"FlatlandConnection::Present");
51 std::scoped_lock<std::mutex> lock(threadsafe_state_.mutex_);
52 if (threadsafe_state_.present_credits_ > 0) {
55 present_waiting_for_credit_ =
true;
60void FlatlandConnection::DoPresent() {
61 TRACE_DURATION(
"flutter",
"FlatlandConnection::DoPresent");
63 std::string per_app_tracing_name =
64 "Flatland::PerAppPresent[" + debug_label_ +
"]";
65 TRACE_FLOW_BEGIN(
"gfx", per_app_tracing_name.c_str(), next_present_trace_id_);
66 ++next_present_trace_id_;
68 FML_CHECK(threadsafe_state_.present_credits_ > 0);
69 --threadsafe_state_.present_credits_;
71 fuchsia::ui::composition::PresentArgs present_args;
72 present_args.set_requested_presentation_time(0);
73 present_args.set_acquire_fences(std::move(acquire_fences_));
74 present_args.set_release_fences(std::move(previous_present_release_fences_));
76 present_args.set_unsquashable(
true);
77 flatland_->Present(std::move(present_args));
82 previous_present_release_fences_.clear();
83 previous_present_release_fences_.swap(current_present_release_fences_);
84 acquire_fences_.clear();
89 TRACE_DURATION(
"flutter",
"FlatlandConnection::AwaitVsync");
91 std::scoped_lock<std::mutex> lock(threadsafe_state_.mutex_);
92 threadsafe_state_.pending_fire_callback_ =
nullptr;
96 if (MaybeRunInitialVsyncCallback(now,
callback))
100 if (threadsafe_state_.present_credits_ == 0) {
101 threadsafe_state_.pending_fire_callback_ =
callback;
112 TRACE_DURATION(
"flutter",
113 "FlatlandConnection::AwaitVsyncForSecondaryCallback");
115 std::scoped_lock<std::mutex> lock(threadsafe_state_.mutex_);
119 if (MaybeRunInitialVsyncCallback(now,
callback))
127void FlatlandConnection::OnError(
128 fuchsia::ui::composition::FlatlandError
error) {
134void FlatlandConnection::OnNextFrameBegin(
135 fuchsia::ui::composition::OnNextFrameBeginValues values) {
140 std::scoped_lock<std::mutex> lock(threadsafe_state_.mutex_);
141 threadsafe_state_.first_feedback_received_ =
true;
142 threadsafe_state_.present_credits_ += values.additional_present_credits();
143 TRACE_DURATION(
"flutter",
"FlatlandConnection::OnNextFrameBegin",
144 "present_credits", threadsafe_state_.present_credits_);
146 if (present_waiting_for_credit_ && threadsafe_state_.present_credits_ > 0) {
148 present_waiting_for_credit_ =
false;
154 if (
values.has_future_presentation_infos() &&
155 values.future_presentation_infos().size() > 1) {
157 values.future_presentation_infos().at(1).presentation_time() -
158 values.future_presentation_infos().at(0).presentation_time());
161 <<
"Flatland didn't send enough future_presentation_infos to update "
166 std::queue<fml::TimePoint> new_times;
167 for (
const auto&
info :
values.future_presentation_infos()) {
171 threadsafe_state_.next_presentation_times_.swap(new_times);
178 values.future_presentation_infos().front().presentation_time())) -
180 threadsafe_state_.vsync_interval_;
184 threadsafe_state_.vsync_offset_ = vsync_offset;
188 if (threadsafe_state_.pending_fire_callback_ &&
189 threadsafe_state_.present_credits_ > 0) {
190 RunVsyncCallback(now, threadsafe_state_.pending_fire_callback_);
191 threadsafe_state_.pending_fire_callback_ =
nullptr;
196void FlatlandConnection::OnFramePresented(
197 fuchsia::scenic::scheduling::FramePresentedInfo
info) {
198 on_frame_presented_callback_(std::move(
info));
205 now > threadsafe_state_.last_presentation_time_
207 : threadsafe_state_.last_presentation_time_;
211 while (!threadsafe_state_.next_presentation_times_.empty() &&
212 threadsafe_state_.next_presentation_times_.front() <= cutoff) {
213 threadsafe_state_.next_presentation_times_.pop();
220 if (threadsafe_state_.next_presentation_times_.empty()) {
221 auto result = threadsafe_state_.last_presentation_time_;
222 while (
result <= cutoff) {
229 const auto result = threadsafe_state_.next_presentation_times_.front();
230 threadsafe_state_.next_presentation_times_.pop();
235bool FlatlandConnection::MaybeRunInitialVsyncCallback(
238 if (!threadsafe_state_.first_feedback_received_) {
239 TRACE_DURATION(
"flutter",
240 "FlatlandConnection::MaybeRunInitialVsyncCallback");
242 threadsafe_state_.last_presentation_time_ = frame_end;
251void FlatlandConnection::RunVsyncCallback(
const fml::TimePoint& now,
253 const auto& frame_end = GetNextPresentationTime(now);
254 const auto&
frame_start = frame_end - threadsafe_state_.vsync_offset_;
255 threadsafe_state_.last_presentation_time_ = frame_end;
256 TRACE_DURATION(
"flutter",
"FlatlandConnection::RunVsyncCallback",
258 DeltaFromNowInNanoseconds(now, frame_start),
"frame_end_delta",
259 DeltaFromNowInNanoseconds(now, frame_end));
265 acquire_fences_.push_back(std::move(fence));
270 current_present_release_fences_.push_back(std::move(fence));
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
FlatlandConnection(std::string debug_label, fuchsia::ui::composition::FlatlandHandle flatland, fml::closure error_callback, on_frame_presented_event on_frame_presented_callback)
void EnqueueReleaseFence(zx::event fence)
void AwaitVsyncForSecondaryCallback(FireCallbackCallback callback)
void EnqueueAcquireFence(zx::event fence)
void AwaitVsync(FireCallbackCallback callback)
static constexpr TimeDelta FromNanoseconds(int64_t nanos)
static constexpr TimeDelta Zero()
static constexpr TimePoint FromEpochDelta(TimeDelta ticks)
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
const uint8_t uint32_t uint32_t GError ** error
#define FML_LOG(severity)
#define FML_CHECK(condition)
std::function< void(fuchsia::scenic::scheduling::FramePresentedInfo)> on_frame_presented_event
std::function< void(fml::TimePoint, fml::TimePoint)> FireCallbackCallback
static constexpr fml::TimeDelta kInitialFlatlandVsyncOffset
std::function< void()> closure
#define TRACE_FLOW_BEGIN(category, name, id)