Skip to content

Commit

Permalink
[fuchsia] Set presentation interval
Browse files Browse the repository at this point in the history
  • Loading branch information
uysalere committed Dec 29, 2022
1 parent 606e77f commit 406e59d
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 20 deletions.
36 changes: 27 additions & 9 deletions shell/platform/fuchsia/flutter/flatland_connection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@

namespace flutter_runner {

namespace {

fml::TimePoint GetNextPresentationTime(fml::TimePoint now,
fml::TimePoint next_presentation_time) {
return now > next_presentation_time
? now + flutter_runner::kDefaultFlatlandPresentationInterval
: next_presentation_time;
}

} // namespace

FlatlandConnection::FlatlandConnection(
std::string debug_label,
fuchsia::ui::composition::FlatlandHandle flatland,
Expand Down Expand Up @@ -54,7 +65,6 @@ void FlatlandConnection::DoPresent() {
--present_credits_;

fuchsia::ui::composition::PresentArgs present_args;
// TODO(fxbug.dev/114588): compute a better presentation time;
present_args.set_requested_presentation_time(0);
present_args.set_acquire_fences(std::move(acquire_fences_));
present_args.set_release_fences(std::move(previous_present_release_fences_));
Expand Down Expand Up @@ -85,10 +95,10 @@ void FlatlandConnection::AwaitVsync(FireCallbackCallback callback) {
threadsafe_state_.fire_callback_ = callback;

if (threadsafe_state_.fire_callback_pending_) {
fml::TimePoint now = fml::TimePoint::Now();
// TODO(fxbug.dev/114588): Calculate correct frame times.
const fml::TimePoint now = fml::TimePoint::Now();
threadsafe_state_.fire_callback_(
now, now + kDefaultFlatlandPresentationInterval);
now, GetNextPresentationTime(
now, threadsafe_state_.next_presentation_time_));
threadsafe_state_.fire_callback_ = nullptr;
threadsafe_state_.fire_callback_pending_ = false;
}
Expand All @@ -97,8 +107,10 @@ void FlatlandConnection::AwaitVsync(FireCallbackCallback callback) {
// This method is called from the UI thread.
void FlatlandConnection::AwaitVsyncForSecondaryCallback(
FireCallbackCallback callback) {
fml::TimePoint now = fml::TimePoint::Now();
callback(now, now);
const fml::TimePoint now = fml::TimePoint::Now();
std::scoped_lock<std::mutex> lock(threadsafe_state_.mutex_);
callback(now, GetNextPresentationTime(
now, threadsafe_state_.next_presentation_time_));
}

void FlatlandConnection::OnError(
Expand All @@ -118,15 +130,21 @@ void FlatlandConnection::OnNextFrameBegin(
}

if (present_credits_ > 0) {
FML_CHECK(values.has_future_presentation_infos() &&
!values.future_presentation_infos().empty());
const auto next_presentation_time =
fml::TimePoint::FromEpochDelta(fml::TimeDelta::FromNanoseconds(
values.future_presentation_infos().front().presentation_time()));

std::scoped_lock<std::mutex> lock(threadsafe_state_.mutex_);
if (threadsafe_state_.fire_callback_) {
fml::TimePoint now = fml::TimePoint::Now();
// TODO(fxbug.dev/114588): Calculate correct frame times.
threadsafe_state_.fire_callback_(
now, now + kDefaultFlatlandPresentationInterval);
/*frame_start=*/fml::TimePoint::Now(),
/*frame_target=*/next_presentation_time);
threadsafe_state_.fire_callback_ = nullptr;
} else {
threadsafe_state_.fire_callback_pending_ = true;
threadsafe_state_.next_presentation_time_ = next_presentation_time;
}
}
}
Expand Down
7 changes: 5 additions & 2 deletions shell/platform/fuchsia/flutter/flatland_connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "flutter/fml/closure.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/time/time_delta.h"
#include "flutter/fml/time/time_point.h"

#include "vsync_waiter.h"

Expand All @@ -22,9 +23,10 @@ namespace flutter_runner {
using on_frame_presented_event =
std::function<void(fuchsia::scenic::scheduling::FramePresentedInfo)>;

// Set to zero for now for maximum simplicity until we have real values.
// 2ms interval to target vsync is only used until Scenic sends presentation
// feedback, or when we run out of present credits.
static constexpr fml::TimeDelta kDefaultFlatlandPresentationInterval =
fml::TimeDelta::FromSecondsF(0);
fml::TimeDelta::FromMilliseconds(2);

// The component residing on the raster thread that is responsible for
// maintaining the Flatland instance connection and presenting updates.
Expand Down Expand Up @@ -87,6 +89,7 @@ class FlatlandConnection final {
FireCallbackCallback fire_callback_;
bool fire_callback_pending_ = false;
bool first_present_called_ = false;
fml::TimePoint next_presentation_time_;
} threadsafe_state_;

std::vector<zx::event> acquire_fences_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,26 @@ void AwaitVsyncChecked(FlatlandConnection& flatland_connection,
});
}

void AwaitVsyncChecked(FlatlandConnection& flatland_connection,
bool& condition_variable,
fml::TimePoint expected_frame_end) {
flatland_connection.AwaitVsync(
[&condition_variable, expected_frame_end = std::move(expected_frame_end)](
fml::TimePoint frame_start, fml::TimePoint frame_end) {
EXPECT_EQ(frame_end, expected_frame_end);
condition_variable = true;
});
}

std::vector<fuchsia::scenic::scheduling::PresentationInfo>
CreateFuturePresentationInfos(int presentation_time) {
fuchsia::scenic::scheduling::PresentationInfo info_1;
info_1.set_presentation_time(presentation_time);
std::vector<fuchsia::scenic::scheduling::PresentationInfo> infos;
infos.push_back(std::move(info_1));
return infos;
}

} // namespace

class FlatlandConnectionTest : public ::testing::Test {
Expand All @@ -61,10 +81,12 @@ class FlatlandConnectionTest : public ::testing::Test {
}

// Syntactic sugar for OnNextFrameBegin
void OnNextFrameBegin(int num_present_credits) {
void OnNextFrameBegin(int num_present_credits, int presentation_time = 345) {
fuchsia::ui::composition::OnNextFrameBeginValues on_next_frame_begin_values;
on_next_frame_begin_values.set_additional_present_credits(
num_present_credits);
on_next_frame_begin_values.set_future_presentation_infos(
CreateFuturePresentationInfos(presentation_time));
fake_flatland().FireOnNextFrameBeginEvent(
std::move(on_next_frame_begin_values));
}
Expand Down Expand Up @@ -171,10 +193,14 @@ TEST_F(FlatlandConnectionTest, BasicPresent) {
EXPECT_FALSE(await_vsync_fired);

// Fire the `OnNextFrameBegin` event. AwaitVsync should be fired.
const int kPresentationTime = 123;
AwaitVsyncChecked(flatland_connection, await_vsync_fired,
kDefaultFlatlandPresentationInterval);
fml::TimePoint::FromEpochDelta(
fml::TimeDelta::FromNanoseconds(kPresentationTime)));
fuchsia::ui::composition::OnNextFrameBeginValues on_next_frame_begin_values;
on_next_frame_begin_values.set_additional_present_credits(3);
on_next_frame_begin_values.set_future_presentation_infos(
CreateFuturePresentationInfos(kPresentationTime));
fake_flatland().FireOnNextFrameBeginEvent(
std::move(on_next_frame_begin_values));
loop().RunUntilIdle();
Expand Down Expand Up @@ -275,24 +301,29 @@ TEST_F(FlatlandConnectionTest, OutOfOrderAwait) {

// Set the callback with AwaitVsync, callback should not be fired
await_vsync_callback_fired = false;
const int kPresentationTime1 = 567;
AwaitVsyncChecked(flatland_connection, await_vsync_callback_fired,
kDefaultFlatlandPresentationInterval);
fml::TimePoint::FromEpochDelta(
fml::TimeDelta::FromNanoseconds(kPresentationTime1)));
EXPECT_FALSE(await_vsync_callback_fired);

// Fire the `OnNextFrameBegin` event. AwaitVsync callback should be fired.
// Fire the `OnNextFrameBegin` event. AwaitVsync callback should be fired with
// the given presentation time.
await_vsync_callback_fired = false;
OnNextFrameBegin(1);
OnNextFrameBegin(1, kPresentationTime1);
loop().RunUntilIdle();
EXPECT_TRUE(await_vsync_callback_fired);

// Second consecutive ONFB should not call the fire callback and should
// instead set it to be pending to fire on next AwaitVsync
await_vsync_callback_fired = false;
OnNextFrameBegin(1);
const int kPresentationTime2 = 678;
OnNextFrameBegin(1, kPresentationTime2);
loop().RunUntilIdle();
EXPECT_FALSE(await_vsync_callback_fired);

// Now an AwaitVsync should immediately fire the pending callback
// Now an AwaitVsync should immediately fire the pending callback with the
// default presentation interval.
await_vsync_callback_fired = false;
AwaitVsyncChecked(flatland_connection, await_vsync_callback_fired,
kDefaultFlatlandPresentationInterval);
Expand All @@ -301,13 +332,15 @@ TEST_F(FlatlandConnectionTest, OutOfOrderAwait) {
// With the pending callback fired, The new callback should be set for the
// next OnNextFrameBegin to call
await_vsync_callback_fired = false;
const int kPresentationTime3 = 789;
AwaitVsyncChecked(flatland_connection, await_vsync_callback_fired,
kDefaultFlatlandPresentationInterval);
fml::TimePoint::FromEpochDelta(
fml::TimeDelta::FromNanoseconds(kPresentationTime3)));
EXPECT_FALSE(await_vsync_callback_fired);

// Now OnNextFrameBegin should fire the callback
await_vsync_callback_fired = false;
OnNextFrameBegin(1);
OnNextFrameBegin(1, kPresentationTime3);
loop().RunUntilIdle();
EXPECT_TRUE(await_vsync_callback_fired);
}
Expand Down

0 comments on commit 406e59d

Please sign in to comment.