1use crate::pointerinjector_config::{
6 InjectorViewportChangeFn, InjectorViewportHangingGet, InjectorViewportPublisher,
7 InjectorViewportSpec, InjectorViewportSubscriber,
8};
9use crate::{DisplayMetrics, ViewingDistance};
10use anyhow::{Context, Error, Result};
11use async_trait::async_trait;
12use async_utils::hanging_get::server as hanging_get;
13use fidl::endpoints::{create_proxy, Proxy};
14use fidl_fuchsia_ui_composition::{self as ui_comp, ContentId, TransformId};
15use fidl_fuchsia_ui_pointerinjector_configuration::{
16 SetupRequest as PointerInjectorConfigurationSetupRequest,
17 SetupRequestStream as PointerInjectorConfigurationSetupRequestStream,
18};
19use flatland_frame_scheduling_lib::*;
20use fuchsia_sync::Mutex;
21use futures::channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender};
22use futures::channel::oneshot;
23use futures::prelude::*;
24use input_pipeline::Size;
25use log::{error, info, warn};
26use std::collections::VecDeque;
27use std::ffi::CStr;
28use std::process;
29use std::sync::{Arc, Weak};
30use {
31 fidl_fuchsia_accessibility_scene as a11y_scene, fidl_fuchsia_math as math,
32 fidl_fuchsia_ui_app as ui_app, fidl_fuchsia_ui_display_singleton as singleton_display,
33 fidl_fuchsia_ui_views as ui_views, fuchsia_async as fasync, fuchsia_scenic as scenic,
34 fuchsia_trace as trace, math as fmath,
35};
36
37pub enum PresentationMessage {
39 RequestPresent,
41 RequestPresentWithPingback(oneshot::Sender<()>),
44}
45
46pub type PresentationSender = UnboundedSender<PresentationMessage>;
48
49pub type PresentationReceiver = UnboundedReceiver<PresentationMessage>;
51
52const _CURSOR_SIZE: (u32, u32) = (18, 29);
53const CURSOR_HOTSPOT: (u32, u32) = (2, 4);
54
55const CURSOR_SCALE_MULTIPLIER: u32 = 5;
58const CURSOR_SCALE_DIVIDER: u32 = 4;
59
60fn physical_cursor_size(value: u32) -> u32 {
62 (CURSOR_SCALE_MULTIPLIER * value) / CURSOR_SCALE_DIVIDER
63}
64
65pub type FlatlandPtr = Arc<Mutex<ui_comp::FlatlandProxy>>;
66
67#[derive(Clone)]
68struct TransformContentIdPair {
69 transform_id: TransformId,
70 content_id: ContentId,
71}
72
73struct FlatlandInstance {
78 flatland: FlatlandPtr,
80 view_ref: ui_views::ViewRef,
81 root_transform_id: TransformId,
82 parent_viewport_watcher: ui_comp::ParentViewportWatcherProxy,
83 focuser: ui_views::FocuserProxy,
84}
85
86impl FlatlandInstance {
87 fn new(
88 flatland: ui_comp::FlatlandProxy,
89 view_creation_token: ui_views::ViewCreationToken,
90 id_generator: &mut scenic::flatland::IdGenerator,
91 ) -> Result<FlatlandInstance, Error> {
92 let (parent_viewport_watcher, parent_viewport_watcher_request) =
93 create_proxy::<ui_comp::ParentViewportWatcherMarker>();
94
95 let (focuser, focuser_request) = create_proxy::<ui_views::FocuserMarker>();
96
97 let view_bound_protocols = ui_comp::ViewBoundProtocols {
98 view_focuser: Some(focuser_request),
99 ..Default::default()
100 };
101
102 let view_identity = ui_views::ViewIdentityOnCreation::from(scenic::ViewRefPair::new()?);
103 let view_ref = scenic::duplicate_view_ref(&view_identity.view_ref)?;
104 flatland.create_view2(
105 view_creation_token,
106 view_identity,
107 view_bound_protocols,
108 parent_viewport_watcher_request,
109 )?;
110
111 let root_transform_id = id_generator.next_transform_id();
112 flatland.create_transform(&root_transform_id)?;
113 flatland.set_root_transform(&root_transform_id)?;
114
115 Ok(FlatlandInstance {
116 flatland: Arc::new(Mutex::new(flatland)),
117 view_ref,
118 root_transform_id,
119 parent_viewport_watcher,
120 focuser,
121 })
122 }
123}
124
125fn request_present_with_pingback(
126 presentation_sender: &PresentationSender,
127) -> Result<oneshot::Receiver<()>, Error> {
128 let (sender, receiver) = oneshot::channel::<()>();
129 presentation_sender.unbounded_send(PresentationMessage::RequestPresentWithPingback(sender))?;
130 Ok(receiver)
131}
132
133async fn setup_child_view(
134 parent_flatland: &FlatlandInstance,
135 viewport_creation_token: scenic::flatland::ViewportCreationToken,
136 id_generator: &mut scenic::flatland::IdGenerator,
137 client_viewport_size: math::SizeU,
138) -> Result<ui_comp::ChildViewWatcherProxy, Error> {
139 let child_viewport_transform_id = id_generator.next_transform_id();
140 let child_viewport_content_id = id_generator.next_content_id();
141
142 let (child_view_watcher, child_view_watcher_request) =
143 create_proxy::<ui_comp::ChildViewWatcherMarker>();
144
145 {
146 let flatland = parent_flatland.flatland.lock();
147 flatland.create_transform(&child_viewport_transform_id)?;
148 flatland.add_child(&parent_flatland.root_transform_id, &child_viewport_transform_id)?;
149
150 let link_properties = ui_comp::ViewportProperties {
151 logical_size: Some(client_viewport_size),
152 ..Default::default()
153 };
154
155 flatland.create_viewport(
156 &child_viewport_content_id,
157 viewport_creation_token,
158 &link_properties,
159 child_view_watcher_request,
160 )?;
161 flatland.set_content(&child_viewport_transform_id, &child_viewport_content_id)?;
162 }
163
164 Ok(child_view_watcher)
165}
166
167pub struct SceneManager {
214 _display: ui_comp::FlatlandDisplayProxy,
216
217 client_viewport_size: math::SizeU,
220
221 root_flatland: FlatlandInstance,
226
227 _pointerinjector_flatland: FlatlandInstance,
236
237 scene_flatland: FlatlandInstance,
241
242 context_view_ref: ui_views::ViewRef,
245 target_view_ref: ui_views::ViewRef,
246
247 root_flatland_presentation_sender: PresentationSender,
249 _pointerinjector_flatland_presentation_sender: PresentationSender,
250 scene_flatland_presentation_sender: PresentationSender,
251
252 scene_root_viewport_ids: Option<TransformContentIdPair>,
256
257 id_generator: scenic::flatland::IdGenerator,
260
261 viewport_hanging_get: Arc<Mutex<InjectorViewportHangingGet>>,
264
265 _viewport_publisher: Arc<Mutex<InjectorViewportPublisher>>,
268
269 cursor_transform_id: Option<TransformId>,
271
272 cursor_visibility: bool,
274
275 display_metrics: DisplayMetrics,
277
278 device_pixel_ratio: f32,
282}
283
284#[async_trait]
299pub trait SceneManagerTrait: Send {
300 async fn set_root_view(
306 &mut self,
307 viewport_creation_token: ui_views::ViewportCreationToken,
308 view_ref: Option<ui_views::ViewRef>,
309 ) -> Result<(), Error>;
310
311 async fn set_root_view_deprecated(
316 &mut self,
317 view_provider: ui_app::ViewProviderProxy,
318 ) -> Result<ui_views::ViewRef, Error>;
319
320 fn present_root_view(&self);
322
323 fn set_cursor_position(&mut self, position_physical_px: input_pipeline::Position);
335
336 fn set_cursor_visibility(&mut self, visible: bool);
341
342 fn get_pointerinjection_view_refs(&self) -> (ui_views::ViewRef, ui_views::ViewRef);
344
345 fn get_pointerinjection_display_size(&self) -> input_pipeline::Size;
348
349 fn get_pointerinjector_viewport_watcher_subscription(&self) -> InjectorViewportSubscriber;
352
353 fn get_display_metrics(&self) -> &DisplayMetrics;
354}
355
356#[async_trait]
357impl SceneManagerTrait for SceneManager {
358 async fn set_root_view(
364 &mut self,
365 viewport_creation_token: ui_views::ViewportCreationToken,
366 _view_ref: Option<ui_views::ViewRef>,
367 ) -> Result<(), Error> {
368 self.set_root_view_internal(viewport_creation_token).await.map(|_view_ref| {})
369 }
370
371 async fn set_root_view_deprecated(
376 &mut self,
377 view_provider: ui_app::ViewProviderProxy,
378 ) -> Result<ui_views::ViewRef, Error> {
379 let link_token_pair = scenic::flatland::ViewCreationTokenPair::new()?;
380
381 view_provider.create_view2(ui_app::CreateView2Args {
384 view_creation_token: Some(link_token_pair.view_creation_token),
385 ..Default::default()
386 })?;
387
388 self.set_root_view_internal(link_token_pair.viewport_creation_token).await
389 }
390
391 fn present_root_view(&self) {
393 self.root_flatland_presentation_sender
394 .unbounded_send(PresentationMessage::RequestPresent)
395 .expect("send failed");
396 }
397
398 fn get_pointerinjection_view_refs(&self) -> (ui_views::ViewRef, ui_views::ViewRef) {
400 (
401 scenic::duplicate_view_ref(&self.context_view_ref).expect("failed to copy ViewRef"),
402 scenic::duplicate_view_ref(&self.target_view_ref).expect("failed to copy ViewRef"),
403 )
404 }
405
406 fn set_cursor_position(&mut self, position_physical_px: input_pipeline::Position) {
418 if let Some(cursor_transform_id) = self.cursor_transform_id {
419 let position_logical = position_physical_px / self.device_pixel_ratio;
420 let x =
421 position_logical.x.round() as i32 - physical_cursor_size(CURSOR_HOTSPOT.0) as i32;
422 let y =
423 position_logical.y.round() as i32 - physical_cursor_size(CURSOR_HOTSPOT.1) as i32;
424 let flatland = self.root_flatland.flatland.lock();
425 flatland
426 .set_translation(&cursor_transform_id, &fmath::Vec_ { x, y })
427 .expect("fidl error");
428 self.root_flatland_presentation_sender
429 .unbounded_send(PresentationMessage::RequestPresent)
430 .expect("send failed");
431 }
432 }
433
434 fn set_cursor_visibility(&mut self, visible: bool) {
439 if let Some(cursor_transform_id) = self.cursor_transform_id {
440 if self.cursor_visibility != visible {
441 self.cursor_visibility = visible;
442 let flatland = self.root_flatland.flatland.lock();
443 if visible {
444 flatland
445 .add_child(&self.root_flatland.root_transform_id, &cursor_transform_id)
446 .expect("failed to add cursor to scene");
447 } else {
448 flatland
449 .remove_child(&self.root_flatland.root_transform_id, &cursor_transform_id)
450 .expect("failed to remove cursor from scene");
451 }
452 self.root_flatland_presentation_sender
453 .unbounded_send(PresentationMessage::RequestPresent)
454 .expect("send failed");
455 }
456 }
457 }
458
459 fn get_pointerinjection_display_size(&self) -> Size {
462 self.display_metrics.size_in_pixels()
464 }
465
466 fn get_pointerinjector_viewport_watcher_subscription(&self) -> InjectorViewportSubscriber {
469 self.viewport_hanging_get.lock().new_subscriber()
470 }
471
472 fn get_display_metrics(&self) -> &DisplayMetrics {
473 &self.display_metrics
474 }
475}
476
477const ROOT_VIEW_DEBUG_NAME: &str = "SceneManager Display";
478const POINTER_INJECTOR_DEBUG_NAME: &str = "SceneManager PointerInjector";
479const SCENE_DEBUG_NAME: &str = "SceneManager Scene";
480const ROOT_VIEW_PRESENT_TRACING_NAME: &CStr = c"Flatland::PerAppPresent[SceneManager Display]";
481const POINTER_INJECTOR_PRESENT_TRACING_NAME: &CStr =
482 c"Flatland::PerAppPresent[SceneManager PointerInjector]";
483const SCENE_TRACING_NAME: &CStr = c"Flatland::PerAppPresent[SceneManager Scene]";
484
485impl SceneManager {
486 #[allow(clippy::vec_init_then_push, reason = "mass allow for https://fxbug.dev/381896734")]
487 pub async fn new(
488 display: ui_comp::FlatlandDisplayProxy,
489 singleton_display_info: singleton_display::InfoProxy,
490 root_flatland: ui_comp::FlatlandProxy,
491 pointerinjector_flatland: ui_comp::FlatlandProxy,
492 scene_flatland: ui_comp::FlatlandProxy,
493 a11y_view_provider: Option<a11y_scene::ProviderProxy>,
494 display_rotation: u64,
495 display_pixel_density: Option<f32>,
496 viewing_distance: Option<ViewingDistance>,
497 ) -> Result<Self, Error> {
498 start_exit_on_scenic_closed_task(display.clone());
501
502 let mut id_generator = scenic::flatland::IdGenerator::new();
503
504 let pointerinjector_viewport_transform_id = id_generator.next_transform_id();
507 let pointerinjector_viewport_content_id = id_generator.next_content_id();
508
509 root_flatland.set_debug_name(ROOT_VIEW_DEBUG_NAME)?;
510 pointerinjector_flatland.set_debug_name(POINTER_INJECTOR_DEBUG_NAME)?;
511 scene_flatland.set_debug_name(SCENE_DEBUG_NAME)?;
512
513 let root_view_creation_pair = scenic::flatland::ViewCreationTokenPair::new()?;
514 let root_flatland = FlatlandInstance::new(
515 root_flatland,
516 root_view_creation_pair.view_creation_token,
517 &mut id_generator,
518 )?;
519
520 let pointerinjector_view_creation_pair = scenic::flatland::ViewCreationTokenPair::new()?;
521 let pointerinjector_flatland = FlatlandInstance::new(
522 pointerinjector_flatland,
523 pointerinjector_view_creation_pair.view_creation_token,
524 &mut id_generator,
525 )?;
526
527 let scene_view_creation_pair = scenic::flatland::ViewCreationTokenPair::new()?;
528 let scene_flatland = FlatlandInstance::new(
529 scene_flatland,
530 scene_view_creation_pair.view_creation_token,
531 &mut id_generator,
532 )?;
533
534 let info = singleton_display_info.get_metrics().await?;
536 let extent_in_px =
537 info.extent_in_px.ok_or_else(|| anyhow::anyhow!("Did not receive display size"))?;
538 let display_metrics = DisplayMetrics::new(
539 Size { width: extent_in_px.width as f32, height: extent_in_px.height as f32 },
540 display_pixel_density,
541 viewing_distance,
542 None,
543 );
544
545 display.set_device_pixel_ratio(&fmath::VecF {
546 x: display_metrics.pixels_per_pip(),
547 y: display_metrics.pixels_per_pip(),
548 })?;
549
550 {
552 let (_, child_view_watcher_request) = create_proxy::<ui_comp::ChildViewWatcherMarker>();
555
556 display.set_content(
557 root_view_creation_pair.viewport_creation_token,
558 child_view_watcher_request,
559 )?;
560 }
561
562 let layout_info = root_flatland.parent_viewport_watcher.get_layout().await?;
565 let root_viewport_size = layout_info
566 .logical_size
567 .ok_or_else(|| anyhow::anyhow!("Did not receive layout info from the display"))?;
568
569 let (
570 display_rotation_enum,
571 injector_viewport_translation,
572 flip_injector_viewport_dimensions,
573 ) = match display_rotation % 360 {
574 0 => Ok((ui_comp::Orientation::Ccw0Degrees, math::Vec_ { x: 0, y: 0 }, false)),
575 90 => Ok((
576 ui_comp::Orientation::Ccw270Degrees,
580 math::Vec_ { x: root_viewport_size.width as i32, y: 0 },
581 true,
582 )),
583 180 => Ok((
584 ui_comp::Orientation::Ccw180Degrees,
585 math::Vec_ {
586 x: root_viewport_size.width as i32,
587 y: root_viewport_size.height as i32,
588 },
589 false,
590 )),
591 270 => Ok((
592 ui_comp::Orientation::Ccw90Degrees,
596 math::Vec_ { x: 0, y: root_viewport_size.height as i32 },
597 true,
598 )),
599 _ => Err(anyhow::anyhow!("Invalid display rotation; must be {{0,90,180,270}}")),
600 }?;
601 let client_viewport_size = match flip_injector_viewport_dimensions {
602 true => {
603 math::SizeU { width: root_viewport_size.height, height: root_viewport_size.width }
604 }
605 false => {
606 math::SizeU { width: root_viewport_size.width, height: root_viewport_size.height }
607 }
608 };
609
610 {
612 let flatland = root_flatland.flatland.lock();
613 flatland.create_transform(&pointerinjector_viewport_transform_id)?;
614 flatland.add_child(
615 &root_flatland.root_transform_id,
616 &pointerinjector_viewport_transform_id,
617 )?;
618 flatland
619 .set_orientation(&pointerinjector_viewport_transform_id, display_rotation_enum)?;
620 flatland.set_translation(
621 &pointerinjector_viewport_transform_id,
622 &injector_viewport_translation,
623 )?;
624
625 let link_properties = ui_comp::ViewportProperties {
626 logical_size: Some(client_viewport_size),
627 ..Default::default()
628 };
629
630 let (_, child_view_watcher_request) = create_proxy::<ui_comp::ChildViewWatcherMarker>();
631
632 flatland.create_viewport(
633 &pointerinjector_viewport_content_id,
634 pointerinjector_view_creation_pair.viewport_creation_token,
635 &link_properties,
636 child_view_watcher_request,
637 )?;
638 flatland.set_content(
639 &pointerinjector_viewport_transform_id,
640 &pointerinjector_viewport_content_id,
641 )?;
642 }
643
644 let mut a11y_view_watcher: Option<ui_comp::ChildViewWatcherProxy> = None;
645 match a11y_view_provider {
646 Some(a11y_view_provider) => {
647 let a11y_view_creation_pair = scenic::flatland::ViewCreationTokenPair::new()?;
648
649 a11y_view_watcher = Some(
651 setup_child_view(
652 &pointerinjector_flatland,
653 a11y_view_creation_pair.viewport_creation_token,
654 &mut id_generator,
655 client_viewport_size,
656 )
657 .await?,
658 );
659
660 a11y_view_provider.create_view(
662 a11y_view_creation_pair.view_creation_token,
663 scene_view_creation_pair.viewport_creation_token,
664 )?;
665 }
666 None => {
667 let _ = setup_child_view(
669 &pointerinjector_flatland,
670 scene_view_creation_pair.viewport_creation_token,
671 &mut id_generator,
672 client_viewport_size,
673 )
674 .await?;
675 }
676 }
677
678 let (root_flatland_presentation_sender, root_receiver) = unbounded();
680 start_flatland_presentation_loop(
681 root_receiver,
682 Arc::downgrade(&root_flatland.flatland),
683 ROOT_VIEW_DEBUG_NAME.to_string(),
684 );
685 let (pointerinjector_flatland_presentation_sender, pointerinjector_receiver) = unbounded();
686 start_flatland_presentation_loop(
687 pointerinjector_receiver,
688 Arc::downgrade(&pointerinjector_flatland.flatland),
689 POINTER_INJECTOR_DEBUG_NAME.to_string(),
690 );
691 let (scene_flatland_presentation_sender, scene_receiver) = unbounded();
692 start_flatland_presentation_loop(
693 scene_receiver,
694 Arc::downgrade(&scene_flatland.flatland),
695 SCENE_DEBUG_NAME.to_string(),
696 );
697
698 let mut pingback_channels = Vec::new();
699 pingback_channels.push(request_present_with_pingback(&root_flatland_presentation_sender)?);
700 pingback_channels
701 .push(request_present_with_pingback(&pointerinjector_flatland_presentation_sender)?);
702 pingback_channels.push(request_present_with_pingback(&scene_flatland_presentation_sender)?);
703
704 if let Some(a11y_view_watcher) = a11y_view_watcher {
705 let a11y_view_status = a11y_view_watcher.get_status().await?;
707 match a11y_view_status {
708 ui_comp::ChildViewStatus::ContentHasPresented => {}
709 }
710 }
711
712 let device_pixel_ratio = display_metrics.pixels_per_pip();
714 let viewport_hanging_get: Arc<Mutex<InjectorViewportHangingGet>> =
715 create_viewport_hanging_get({
716 InjectorViewportSpec {
717 width: display_metrics.width_in_pixels() as f32,
718 height: display_metrics.height_in_pixels() as f32,
719 scale: 1. / device_pixel_ratio,
720 x_offset: 0.,
721 y_offset: 0.,
722 }
723 });
724 let viewport_publisher = Arc::new(Mutex::new(viewport_hanging_get.lock().new_publisher()));
725
726 let context_view_ref = scenic::duplicate_view_ref(&root_flatland.view_ref)?;
727 let target_view_ref = scenic::duplicate_view_ref(&pointerinjector_flatland.view_ref)?;
728
729 for receiver in pingback_channels {
731 _ = receiver.await;
732 }
733
734 Ok(SceneManager {
735 _display: display,
736 client_viewport_size,
737 root_flatland,
738 _pointerinjector_flatland: pointerinjector_flatland,
739 scene_flatland,
740 context_view_ref,
741 target_view_ref,
742 root_flatland_presentation_sender,
743 _pointerinjector_flatland_presentation_sender:
744 pointerinjector_flatland_presentation_sender,
745 scene_flatland_presentation_sender,
746 scene_root_viewport_ids: None,
747 id_generator,
748 viewport_hanging_get,
749 _viewport_publisher: viewport_publisher,
750 cursor_transform_id: None,
751 cursor_visibility: true,
752 display_metrics,
753 device_pixel_ratio,
754 })
755 }
756
757 async fn set_root_view_internal(
758 &mut self,
759 viewport_creation_token: ui_views::ViewportCreationToken,
760 ) -> Result<ui_views::ViewRef> {
761 if let Some(ids) = &self.scene_root_viewport_ids {
763 let locked = self.scene_flatland.flatland.lock();
764 locked
765 .set_content(&ids.transform_id, &ContentId { value: 0 })
766 .context("could not set content")?;
767 locked.remove_child(&self.scene_flatland.root_transform_id, &ids.transform_id)?;
768 locked.release_transform(&ids.transform_id).context("could not release transform")?;
769 let _ = locked.release_viewport(&ids.content_id);
770 self.scene_root_viewport_ids = None;
771 }
772
773 let ids = TransformContentIdPair {
775 transform_id: self.id_generator.next_transform_id(),
776 content_id: self.id_generator.next_content_id(),
777 };
778 let (child_view_watcher, child_view_watcher_request) =
779 create_proxy::<ui_comp::ChildViewWatcherMarker>();
780 {
781 let locked = self.scene_flatland.flatland.lock();
782 let viewport_properties = ui_comp::ViewportProperties {
783 logical_size: Some(self.client_viewport_size),
784 ..Default::default()
785 };
786 locked.create_viewport(
787 &ids.content_id,
788 viewport_creation_token,
789 &viewport_properties,
790 child_view_watcher_request,
791 )?;
792 locked.create_transform(&ids.transform_id).context("could not create transform")?;
793 locked.add_child(&self.scene_flatland.root_transform_id, &ids.transform_id)?;
794 locked
795 .set_content(&ids.transform_id, &ids.content_id)
796 .context("could not set content #2")?;
797 }
798 self.scene_root_viewport_ids = Some(ids);
799
800 let mut pingback_channels = Vec::new();
804 pingback_channels.push(
805 request_present_with_pingback(&self.scene_flatland_presentation_sender)
806 .context("could not request present with pingback")?,
807 );
808
809 let _child_status =
810 child_view_watcher.get_status().await.context("could not call get_status")?;
811 let child_view_ref =
812 child_view_watcher.get_view_ref().await.context("could not get view_ref")?;
813 let child_view_ref_copy =
814 scenic::duplicate_view_ref(&child_view_ref).context("could not duplicate view_ref")?;
815
816 let request_focus_result = self.root_flatland.focuser.request_focus(child_view_ref).await;
817 match request_focus_result {
818 Err(e) => warn!("Request focus failed with err: {}", e),
819 Ok(Err(value)) => warn!("Request focus failed with err: {:?}", value),
820 Ok(_) => {}
821 }
822 pingback_channels.push(
823 request_present_with_pingback(&self.root_flatland_presentation_sender)
824 .context("could not request present with pingback #2")?,
825 );
826
827 for receiver in pingback_channels {
829 _ = receiver.await;
830 }
831
832 Ok(child_view_ref_copy)
833 }
834}
835
836pub fn create_viewport_hanging_get(
837 initial_spec: InjectorViewportSpec,
838) -> Arc<Mutex<InjectorViewportHangingGet>> {
839 let notify_fn: InjectorViewportChangeFn = Box::new(|viewport_spec, responder| {
840 if let Err(fidl_error) = responder.send(&(*viewport_spec).into()) {
841 info!("Viewport hanging get notification, FIDL error: {}", fidl_error);
842 }
843 true
845 });
846
847 Arc::new(Mutex::new(hanging_get::HangingGet::new(initial_spec, notify_fn)))
848}
849
850pub fn start_exit_on_scenic_closed_task(flatland_proxy: ui_comp::FlatlandDisplayProxy) {
851 fasync::Task::local(async move {
852 let _ = flatland_proxy.on_closed().await;
853 info!("Scenic died, closing SceneManager too.");
854 process::exit(1);
855 })
856 .detach()
857}
858
859pub fn start_flatland_presentation_loop(
860 mut receiver: PresentationReceiver,
861 weak_flatland: Weak<Mutex<ui_comp::FlatlandProxy>>,
862 debug_name: String,
863) {
864 fasync::Task::local(async move {
865 let mut present_count = 0;
866 let scheduler = ThroughputScheduler::new();
867 let mut flatland_event_stream = {
868 if let Some(flatland) = weak_flatland.upgrade() {
869 flatland.lock().take_event_stream()
870 } else {
871 warn!(
872 "Failed to upgrade Flatand weak ref; exiting presentation loop for {debug_name}"
873 );
874 return;
875 }
876 };
877
878 let mut channels_awaiting_pingback = VecDeque::from([Vec::new()]);
879
880 loop {
881 futures::select! {
882 message = receiver.next() => {
883 match message {
884 Some(PresentationMessage::RequestPresent) => {
885 scheduler.request_present();
886 }
887 Some(PresentationMessage::RequestPresentWithPingback(channel)) => {
888 channels_awaiting_pingback.back_mut().unwrap().push(channel);
889 scheduler.request_present();
890 }
891 None => {}
892 }
893 }
894 flatland_event = flatland_event_stream.next() => {
895 match flatland_event {
896 Some(Ok(ui_comp::FlatlandEvent::OnNextFrameBegin{ values })) => {
897 trace::duration!(c"scene_manager", c"SceneManager::OnNextFrameBegin",
898 "debug_name" => &*debug_name);
899 let credits = values
900 .additional_present_credits
901 .expect("Present credits must exist");
902 let infos = values
903 .future_presentation_infos
904 .expect("Future presentation infos must exist")
905 .iter()
906 .map(
907 |x| PresentationInfo{
908 latch_point: zx::MonotonicInstant::from_nanos(x.latch_point.unwrap()),
909 presentation_time: zx::MonotonicInstant::from_nanos(
910 x.presentation_time.unwrap())
911 })
912 .collect();
913 scheduler.on_next_frame_begin(credits, infos);
914 }
915 Some(Ok(ui_comp::FlatlandEvent::OnFramePresented{ frame_presented_info })) => {
916 trace::duration!(c"scene_manager", c"SceneManager::OnFramePresented",
917 "debug_name" => &*debug_name);
918 let actual_presentation_time =
919 zx::MonotonicInstant::from_nanos(frame_presented_info.actual_presentation_time);
920 let presented_infos: Vec<PresentedInfo> =
921 frame_presented_info.presentation_infos
922 .into_iter()
923 .map(|x| x.into())
924 .collect();
925
926 for _ in 0..presented_infos.len() {
929 for channel in channels_awaiting_pingback.pop_back().unwrap() {
930 _ = channel.send(());
931 }
932 }
933
934 scheduler.on_frame_presented(actual_presentation_time, presented_infos);
935 }
936 Some(Ok(ui_comp::FlatlandEvent::OnError{ error })) => {
937 error!(
938 "Received FlatlandError code: {}; exiting listener loop for {debug_name}",
939 error.into_primitive()
940 );
941 return;
942 }
943 _ => {}
944 }
945 }
946 present_parameters = scheduler.wait_to_update().fuse() => {
947 trace::duration!(c"scene_manager", c"SceneManager::Present",
948 "debug_name" => &*debug_name);
949
950 match debug_name.as_str() {
951 ROOT_VIEW_DEBUG_NAME => {
952 trace::flow_begin!(c"gfx", ROOT_VIEW_PRESENT_TRACING_NAME, present_count.into());
953 }
954 POINTER_INJECTOR_DEBUG_NAME => {
955 trace::flow_begin!(c"gfx", POINTER_INJECTOR_PRESENT_TRACING_NAME, present_count.into());
956 }
957 SCENE_DEBUG_NAME => {
958 trace::flow_begin!(c"gfx", SCENE_TRACING_NAME, present_count.into());
959 }
960 _ => {
961 warn!("SceneManager::Present with unknown debug_name {:?}", debug_name);
962 }
963 }
964 present_count += 1;
965 channels_awaiting_pingback.push_front(Vec::new());
966 if let Some(flatland) = weak_flatland.upgrade() {
967 flatland
968 .lock()
969 .present(present_parameters.into())
970 .expect("Present failed for {debug_name}");
971 } else {
972 warn!(
973 "Failed to upgrade Flatand weak ref; exiting listener loop for {debug_name}"
974 );
975 return;
976 }
977 }
978 }
979 }})
980 .detach()
981}
982
983pub fn handle_pointer_injector_configuration_setup_request_stream(
984 mut request_stream: PointerInjectorConfigurationSetupRequestStream,
985 scene_manager: Arc<futures::lock::Mutex<dyn SceneManagerTrait>>,
986) {
987 fasync::Task::local(async move {
988 let subscriber =
989 scene_manager.lock().await.get_pointerinjector_viewport_watcher_subscription();
990
991 loop {
992 let request = request_stream.try_next().await;
993 match request {
994 Ok(Some(PointerInjectorConfigurationSetupRequest::GetViewRefs { responder })) => {
995 let (context_view_ref, target_view_ref) =
996 scene_manager.lock().await.get_pointerinjection_view_refs();
997 if let Err(e) = responder.send(context_view_ref, target_view_ref) {
998 warn!("Failed to send GetViewRefs() response: {}", e);
999 }
1000 }
1001 Ok(Some(PointerInjectorConfigurationSetupRequest::WatchViewport { responder })) => {
1002 if let Err(e) = subscriber.register(responder) {
1003 warn!("Failed to register WatchViewport() subscriber: {}", e);
1004 }
1005 }
1006 Ok(None) => {
1007 return;
1008 }
1009 Err(e) => {
1010 error!("Error obtaining SetupRequest: {}", e);
1011 return;
1012 }
1013 }
1014 }
1015 })
1016 .detach()
1017}