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