ui_puppet_lib/
presentation_loop.rs
1use flatland_frame_scheduling_lib::*;
6use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender};
7use futures::channel::oneshot;
8use futures::prelude::*;
9use log::warn;
10use std::rc::Weak;
11use {fidl_fuchsia_ui_composition as ui_comp, fuchsia_async as fasync};
12
13pub type PresentationSender = UnboundedSender<oneshot::Sender<()>>;
15
16pub type PresentationReceiver = UnboundedReceiver<oneshot::Sender<()>>;
18
19pub fn start_flatland_presentation_loop(
20 mut receiver: PresentationReceiver,
21 weak_flatland: Weak<ui_comp::FlatlandProxy>,
22) {
23 fasync::Task::local(async move {
24 let scheduler = ThroughputScheduler::new();
25 let mut flatland_event_stream = {
26 if let Some(flatland) = weak_flatland.upgrade() {
27 flatland.take_event_stream()
28 } else {
29 panic!(
30 "failed to upgrade Flatand weak ref"
31 );
32 }
33 };
34
35 let mut pingback_channel: Option<oneshot::Sender<()>> = None;
36
37 loop {
38 futures::select! {
39 message = receiver.next() => {
40 match message {
41 Some(channel) => {
42 assert!(pingback_channel.is_none());
43 pingback_channel = Some(channel);
44 scheduler.request_present();
45 }
46 None => {}
47 }
48 }
49 flatland_event = flatland_event_stream.next() => {
50 match flatland_event {
51 Some(Ok(ui_comp::FlatlandEvent::OnNextFrameBegin{ values })) => {
52 let credits = values
53 .additional_present_credits
54 .expect("Present credits must exist");
55 let infos = values
56 .future_presentation_infos
57 .expect("Future presentation infos must exist")
58 .iter()
59 .map(
60 |x| PresentationInfo{
61 latch_point: zx::MonotonicInstant::from_nanos(x.latch_point.unwrap()),
62 presentation_time: zx::MonotonicInstant::from_nanos(
63 x.presentation_time.unwrap())
64 })
65 .collect();
66 scheduler.on_next_frame_begin(credits, infos);
67 }
68 Some(Ok(ui_comp::FlatlandEvent::OnFramePresented{ frame_presented_info })) => {
69 let actual_presentation_time =
70 zx::MonotonicInstant::from_nanos(frame_presented_info.actual_presentation_time);
71 let presented_infos: Vec<PresentedInfo> =
72 frame_presented_info.presentation_infos
73 .into_iter()
74 .map(|x| x.into())
75 .collect();
76
77 if let Some(channel) = pingback_channel.take() {
78 _ = channel.send(());
79 }
80
81 scheduler.on_frame_presented(actual_presentation_time, presented_infos);
82 }
83 Some(Ok(ui_comp::FlatlandEvent::OnError{ error })) => {
84 panic!(
85 "Received FlatlandError code: {}",
86 error.into_primitive()
87 );
88 }
89 _ => {
90 warn!(
91 "Flatland event stream closed; exiting. This message may be expected during test teardown");
92 return;
93 }
94 }
95 }
96 present_parameters = scheduler.wait_to_update().fuse() => {
97 if let Some(flatland) = weak_flatland.upgrade() {
98 flatland
99 .present(present_parameters.into())
100 .expect("Present failed");
101 } else {
102 warn!(
103 "Failed to upgrade Flatand weak ref; exiting listener loop"
104 );
105 return;
106 }
107 }
108 }
109 }})
110 .detach()
111}