blob: 390e2c0634d26516b8aac115d053ee75ed61e312 [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use flatland_frame_scheduling_lib::*;
use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender};
use futures::channel::oneshot;
use futures::prelude::*;
use std::rc::Weak;
use tracing::warn;
use {fidl_fuchsia_ui_composition as ui_comp, fuchsia_async as fasync, fuchsia_zircon as zx};
/// Unbounded sender used for presentation messages.
pub type PresentationSender = UnboundedSender<oneshot::Sender<()>>;
/// Unbounded receiver used for presentation messages.
pub type PresentationReceiver = UnboundedReceiver<oneshot::Sender<()>>;
pub fn start_flatland_presentation_loop(
mut receiver: PresentationReceiver,
weak_flatland: Weak<ui_comp::FlatlandProxy>,
) {
fasync::Task::local(async move {
let scheduler = ThroughputScheduler::new();
let mut flatland_event_stream = {
if let Some(flatland) = weak_flatland.upgrade() {
flatland.take_event_stream()
} else {
panic!(
"failed to upgrade Flatand weak ref"
);
}
};
let mut pingback_channel: Option<oneshot::Sender<()>> = None;
loop {
futures::select! {
message = receiver.next() => {
match message {
Some(channel) => {
assert!(pingback_channel.is_none());
pingback_channel = Some(channel);
scheduler.request_present();
}
None => {}
}
}
flatland_event = flatland_event_stream.next() => {
match flatland_event {
Some(Ok(ui_comp::FlatlandEvent::OnNextFrameBegin{ values })) => {
let credits = values
.additional_present_credits
.expect("Present credits must exist");
let infos = values
.future_presentation_infos
.expect("Future presentation infos must exist")
.iter()
.map(
|x| PresentationInfo{
latch_point: zx::Time::from_nanos(x.latch_point.unwrap()),
presentation_time: zx::Time::from_nanos(
x.presentation_time.unwrap())
})
.collect();
scheduler.on_next_frame_begin(credits, infos);
}
Some(Ok(ui_comp::FlatlandEvent::OnFramePresented{ frame_presented_info })) => {
let actual_presentation_time =
zx::Time::from_nanos(frame_presented_info.actual_presentation_time);
let presented_infos: Vec<PresentedInfo> =
frame_presented_info.presentation_infos
.into_iter()
.map(|x| x.into())
.collect();
if let Some(channel) = pingback_channel.take() {
_ = channel.send(());
}
scheduler.on_frame_presented(actual_presentation_time, presented_infos);
}
Some(Ok(ui_comp::FlatlandEvent::OnError{ error })) => {
panic!(
"Received FlatlandError code: {}",
error.into_primitive()
);
}
_ => {
warn!(
"Flatland event stream closed; exiting. This message may be expected during test teardown");
return;
}
}
}
present_parameters = scheduler.wait_to_update().fuse() => {
if let Some(flatland) = weak_flatland.upgrade() {
flatland
.present(present_parameters.into())
.expect("Present failed");
} else {
warn!(
"Failed to upgrade Flatand weak ref; exiting listener loop"
);
return;
}
}
}
}})
.detach()
}