1use crate::client::Client;
6use crate::object::{ObjectRef, RequestReceiver};
7use crate::scenic::{FlatlandInstanceId, FlatlandPtr};
8use anyhow::Error;
9use fidl_fuchsia_math::Size;
10use fidl_fuchsia_ui_composition::{BufferCollectionImportToken, ContentId, ImageProperties};
11use std::cell::Cell;
12use std::rc::Rc;
13use wayland_server_protocol::*;
14use zx::{self as zx, HandleBased};
15use {
16 fidl_fuchsia_math as fmath, fidl_fuchsia_ui_composition as composition, fuchsia_trace as ftrace,
17};
18
19pub type ImageInstanceId = usize;
20
21pub struct Content {
24 pub id: ContentId,
26 flatland: FlatlandPtr,
28}
29
30impl Drop for Content {
31 fn drop(&mut self) {
32 self.flatland.borrow().proxy().release_image(&self.id).expect("fidl error");
33 }
34}
35
36struct Image {
37 import_token: Rc<composition::BufferCollectionImportToken>,
39 size: Size,
41 id: Cell<Option<(Rc<Content>, ImageInstanceId, FlatlandInstanceId)>>,
51}
52
53impl Image {
54 fn size(&self) -> Size {
55 self.size
56 }
57
58 pub fn new(import_token: Rc<composition::BufferCollectionImportToken>, size: Size) -> Self {
59 Self { import_token, size, id: Cell::new(None) }
60 }
61
62 pub fn scenic_content(
63 &self,
64 instance_id: ImageInstanceId,
65 flatland: &FlatlandPtr,
66 ) -> Rc<Content> {
67 ftrace::duration!(c"wayland", c"Image::scenic_content");
68 let flatland_id = flatland.borrow().id();
69 let id = match self.id.take().filter(|id| instance_id == id.1 && flatland_id == id.2) {
70 Some(id) => id,
71 None => {
72 let raw_import_token =
73 self.import_token.value.duplicate_handle(zx::Rights::SAME_RIGHTS).unwrap();
74 let size =
75 fmath::SizeU { width: self.size.width as u32, height: self.size.height as u32 };
76 let image_props = ImageProperties { size: Some(size), ..Default::default() };
77 let content_id = flatland.borrow_mut().alloc_content_id();
78 let import_token = BufferCollectionImportToken { value: raw_import_token };
79 flatland
80 .borrow()
81 .proxy()
82 .create_image(&content_id, import_token, 0, &image_props)
83 .expect("fidl error");
84 let content = Content { id: content_id, flatland: flatland.clone() };
85
86 (Rc::new(content), instance_id, flatland_id)
87 }
88 };
89 let result = id.0.clone();
90 self.id.set(Some(id));
91 result
92 }
93}
94
95#[derive(Clone)]
97pub struct Buffer {
98 image: Rc<Image>,
100 has_alpha: bool,
102}
103
104impl Buffer {
105 pub fn from_import_token(
106 import_token: Rc<composition::BufferCollectionImportToken>,
107 image_size: Size,
108 has_alpha: bool,
109 ) -> Self {
110 let image = Image::new(import_token, image_size);
111 Buffer { image: Rc::new(image), has_alpha }
112 }
113
114 pub fn image_size(&self) -> Size {
115 self.image.size()
116 }
117
118 pub fn has_alpha(&self) -> bool {
119 self.has_alpha
120 }
121
122 pub fn image_content(
123 &self,
124 instance_id: ImageInstanceId,
125 flatland: &FlatlandPtr,
126 ) -> Rc<Content> {
127 ftrace::duration!(c"wayland", c"Buffer::image_content");
128 self.image.scenic_content(instance_id, flatland)
129 }
130}
131
132impl RequestReceiver<WlBuffer> for Buffer {
133 fn receive(
134 this: ObjectRef<Self>,
135 request: WlBufferRequest,
136 client: &mut Client,
137 ) -> Result<(), Error> {
138 let WlBufferRequest::Destroy = request;
139 client.delete_id(this.id())?;
140 Ok(())
141 }
142}