1use crate::error::Result;
6use crate::pixel_format::PixelFormat;
7use fidl_fuchsia_hardware_display::{
8 BufferCollectionId as FidlBufferCollectionId, EventId as FidlEventId, ImageId as FidlImageId,
9 Info, LayerId as FidlLayerId,
10};
11use fidl_fuchsia_hardware_display_types::{
12 Color as FidlColor, DisplayId as FidlDisplayId, INVALID_DISP_ID,
13};
14use fuchsia_async::OnSignals;
15use std::fmt;
16use zx::{self as zx, AsHandleRef};
17
18#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
20pub struct DisplayId(pub u64);
21
22pub const INVALID_DISPLAY_ID: DisplayId = DisplayId(INVALID_DISP_ID);
24
25impl Default for DisplayId {
26 fn default() -> Self {
27 INVALID_DISPLAY_ID
28 }
29}
30
31impl From<FidlDisplayId> for DisplayId {
32 fn from(fidl_display_id: FidlDisplayId) -> Self {
33 DisplayId(fidl_display_id.value)
34 }
35}
36
37impl From<DisplayId> for FidlDisplayId {
38 fn from(display_id: DisplayId) -> Self {
39 FidlDisplayId { value: display_id.0 }
40 }
41}
42
43#[derive(Clone, Copy, Debug, Eq, PartialEq)]
45pub struct EventId(pub u64);
46
47pub const INVALID_EVENT_ID: EventId = EventId(INVALID_DISP_ID);
49
50impl Default for EventId {
51 fn default() -> Self {
52 INVALID_EVENT_ID
53 }
54}
55
56impl From<FidlEventId> for EventId {
57 fn from(fidl_event_id: FidlEventId) -> Self {
58 EventId(fidl_event_id.value)
59 }
60}
61
62impl From<EventId> for FidlEventId {
63 fn from(event_id: EventId) -> Self {
64 FidlEventId { value: event_id.0 }
65 }
66}
67
68#[derive(Clone, Copy, Debug, Eq, PartialEq)]
70pub struct LayerId(pub u64);
71
72pub const INVALID_LAYER_ID: LayerId = LayerId(INVALID_DISP_ID);
74
75impl Default for LayerId {
76 fn default() -> Self {
77 INVALID_LAYER_ID
78 }
79}
80
81impl From<FidlLayerId> for LayerId {
82 fn from(fidl_layer_id: FidlLayerId) -> Self {
83 LayerId(fidl_layer_id.value)
84 }
85}
86
87impl From<LayerId> for FidlLayerId {
88 fn from(layer_id: LayerId) -> Self {
89 FidlLayerId { value: layer_id.0 }
90 }
91}
92
93#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
95pub struct ImageId(pub u64);
96
97pub const INVALID_IMAGE_ID: ImageId = ImageId(INVALID_DISP_ID);
99
100impl Default for ImageId {
101 fn default() -> Self {
102 INVALID_IMAGE_ID
103 }
104}
105
106impl From<FidlImageId> for ImageId {
107 fn from(fidl_image_id: FidlImageId) -> Self {
108 ImageId(fidl_image_id.value)
109 }
110}
111
112impl From<ImageId> for FidlImageId {
113 fn from(image_id: ImageId) -> Self {
114 FidlImageId { value: image_id.0 }
115 }
116}
117
118#[derive(Clone, Copy, Debug, Eq, PartialEq)]
120pub struct BufferCollectionId(pub u64);
121
122impl From<FidlBufferCollectionId> for BufferCollectionId {
123 fn from(fidl_buffer_collection_id: FidlBufferCollectionId) -> Self {
124 BufferCollectionId(fidl_buffer_collection_id.value)
125 }
126}
127
128impl From<BufferCollectionId> for FidlBufferCollectionId {
129 fn from(buffer_collection_id: BufferCollectionId) -> Self {
130 FidlBufferCollectionId { value: buffer_collection_id.0 }
131 }
132}
133
134#[derive(Clone, Debug)]
136pub struct DisplayInfo(pub Info);
137
138impl DisplayInfo {
139 pub fn id(&self) -> DisplayId {
141 self.0.id.into()
142 }
143}
144
145impl fmt::Display for DisplayInfo {
147 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
148 writeln!(f, "Display (id: {})", self.0.id.value)?;
149 writeln!(f, "\tManufacturer Name: \"{}\"", self.0.manufacturer_name)?;
150 writeln!(f, "\tMonitor Name: \"{}\"", self.0.monitor_name)?;
151 writeln!(f, "\tMonitor Serial: \"{}\"", self.0.monitor_serial)?;
152 writeln!(
153 f,
154 "\tPhysical Dimensions: {}mm x {}mm",
155 self.0.horizontal_size_mm, self.0.vertical_size_mm
156 )?;
157
158 writeln!(f, "\tPixel Formats:")?;
159 for (i, format) in self.0.pixel_format.iter().map(PixelFormat::from).enumerate() {
160 writeln!(f, "\t\t{}:\t{}", i, format)?;
161 }
162
163 writeln!(f, "\tDisplay Modes:")?;
164 for (i, mode) in self.0.modes.iter().enumerate() {
165 writeln!(
166 f,
167 "\t\t{}:\t{:.2} Hz @ {}x{}",
168 i,
169 (mode.refresh_rate_millihertz as f32) / 1000.,
170 mode.active_area.width,
171 mode.active_area.height
172 )?;
173 }
174
175 write!(f, "")
176 }
177}
178
179pub struct Event {
181 id: EventId,
182 event: zx::Event,
183}
184
185impl Event {
186 pub(crate) fn new(id: EventId, event: zx::Event) -> Event {
187 Event { id, event }
188 }
189
190 pub fn id(&self) -> EventId {
192 self.id
193 }
194
195 pub async fn wait(&self) -> Result<()> {
197 OnSignals::new(&self.event, zx::Signals::EVENT_SIGNALED).await?;
198 self.event.as_handle_ref().signal(zx::Signals::EVENT_SIGNALED, zx::Signals::NONE)?;
199 Ok(())
200 }
201
202 pub fn signal(&self) -> Result<()> {
204 self.event.as_handle_ref().signal(zx::Signals::NONE, zx::Signals::EVENT_SIGNALED)?;
205 Ok(())
206 }
207}
208
209#[derive(Clone, Copy, Debug, PartialEq)]
211pub struct Color {
212 pub format: PixelFormat,
214
215 pub bytes: [u8; 8],
217}
218
219impl From<FidlColor> for Color {
220 fn from(fidl_color: FidlColor) -> Self {
221 Color { format: fidl_color.format.into(), bytes: fidl_color.bytes }
222 }
223}
224
225impl From<&FidlColor> for Color {
226 fn from(fidl_color: &FidlColor) -> Self {
227 Self::from(*fidl_color)
228 }
229}
230
231impl From<Color> for FidlColor {
232 fn from(color: Color) -> Self {
233 FidlColor { format: color.format.into(), bytes: color.bytes }
234 }
235}
236
237impl From<&Color> for FidlColor {
238 fn from(color: &Color) -> Self {
239 Self::from(*color)
240 }
241}
242
243#[cfg(test)]
244mod tests {
245 use super::*;
246 use fidl_fuchsia_images2::PixelFormat as FidlPixelFormat;
247
248 #[fuchsia::test]
249 fn layer_id_from_fidl_layer_id() {
250 assert_eq!(LayerId(1), LayerId::from(FidlLayerId { value: 1 }));
251 assert_eq!(LayerId(2), LayerId::from(FidlLayerId { value: 2 }));
252 const LARGE: u64 = 1 << 63;
253 assert_eq!(LayerId(LARGE), LayerId::from(FidlLayerId { value: LARGE }));
254 assert_eq!(INVALID_LAYER_ID, LayerId::from(FidlLayerId { value: INVALID_DISP_ID }));
255 }
256
257 #[fuchsia::test]
258 fn fidl_layer_id_from_layer_id() {
259 assert_eq!(FidlLayerId { value: 1 }, FidlLayerId::from(LayerId(1)));
260 assert_eq!(FidlLayerId { value: 2 }, FidlLayerId::from(LayerId(2)));
261 const LARGE: u64 = 1 << 63;
262 assert_eq!(FidlLayerId { value: LARGE }, FidlLayerId::from(LayerId(LARGE)));
263 assert_eq!(FidlLayerId { value: INVALID_DISP_ID }, FidlLayerId::from(INVALID_LAYER_ID));
264 }
265
266 #[fuchsia::test]
267 fn fidl_layer_id_to_layer_id() {
268 assert_eq!(LayerId(1), FidlLayerId { value: 1 }.into());
269 assert_eq!(LayerId(2), FidlLayerId { value: 2 }.into());
270 const LARGE: u64 = 1 << 63;
271 assert_eq!(LayerId(LARGE), FidlLayerId { value: LARGE }.into());
272 assert_eq!(INVALID_LAYER_ID, FidlLayerId { value: INVALID_DISP_ID }.into());
273 }
274
275 #[fuchsia::test]
276 fn layer_id_to_fidl_layer_id() {
277 assert_eq!(FidlLayerId { value: 1 }, LayerId(1).into());
278 assert_eq!(FidlLayerId { value: 2 }, LayerId(2).into());
279 const LARGE: u64 = 1 << 63;
280 assert_eq!(FidlLayerId { value: LARGE }, LayerId(LARGE).into());
281 assert_eq!(FidlLayerId { value: INVALID_DISP_ID }, INVALID_LAYER_ID.into());
282 }
283
284 #[fuchsia::test]
285 fn layer_id_default() {
286 let default: LayerId = Default::default();
287 assert_eq!(default, INVALID_LAYER_ID);
288 }
289
290 #[fuchsia::test]
291 fn display_id_from_fidl_display_id() {
292 assert_eq!(DisplayId(1), DisplayId::from(FidlDisplayId { value: 1 }));
293 assert_eq!(DisplayId(2), DisplayId::from(FidlDisplayId { value: 2 }));
294 const LARGE: u64 = 1 << 63;
295 assert_eq!(DisplayId(LARGE), DisplayId::from(FidlDisplayId { value: LARGE }));
296 assert_eq!(INVALID_DISPLAY_ID, DisplayId::from(FidlDisplayId { value: INVALID_DISP_ID }));
297 }
298
299 #[fuchsia::test]
300 fn fidl_display_id_from_display_id() {
301 assert_eq!(FidlDisplayId { value: 1 }, FidlDisplayId::from(DisplayId(1)));
302 assert_eq!(FidlDisplayId { value: 2 }, FidlDisplayId::from(DisplayId(2)));
303 const LARGE: u64 = 1 << 63;
304 assert_eq!(FidlDisplayId { value: LARGE }, FidlDisplayId::from(DisplayId(LARGE)));
305 assert_eq!(
306 FidlDisplayId { value: INVALID_DISP_ID },
307 FidlDisplayId::from(INVALID_DISPLAY_ID)
308 );
309 }
310
311 #[fuchsia::test]
312 fn fidl_display_id_to_display_id() {
313 assert_eq!(DisplayId(1), FidlDisplayId { value: 1 }.into());
314 assert_eq!(DisplayId(2), FidlDisplayId { value: 2 }.into());
315 const LARGE: u64 = 1 << 63;
316 assert_eq!(DisplayId(LARGE), FidlDisplayId { value: LARGE }.into());
317 assert_eq!(INVALID_DISPLAY_ID, FidlDisplayId { value: INVALID_DISP_ID }.into());
318 }
319
320 #[fuchsia::test]
321 fn display_id_to_fidl_display_id() {
322 assert_eq!(FidlDisplayId { value: 1 }, DisplayId(1).into());
323 assert_eq!(FidlDisplayId { value: 2 }, DisplayId(2).into());
324 const LARGE: u64 = 1 << 63;
325 assert_eq!(FidlDisplayId { value: LARGE }, DisplayId(LARGE).into());
326 assert_eq!(FidlDisplayId { value: INVALID_DISP_ID }, INVALID_DISPLAY_ID.into());
327 }
328
329 #[fuchsia::test]
330 fn display_id_default() {
331 let default: DisplayId = Default::default();
332 assert_eq!(default, INVALID_DISPLAY_ID);
333 }
334
335 #[fuchsia::test]
336 fn buffer_collection_id_from_fidl_buffer_collection_id() {
337 assert_eq!(
338 BufferCollectionId(1),
339 BufferCollectionId::from(FidlBufferCollectionId { value: 1 })
340 );
341 assert_eq!(
342 BufferCollectionId(2),
343 BufferCollectionId::from(FidlBufferCollectionId { value: 2 })
344 );
345 const LARGE: u64 = 1 << 63;
346 assert_eq!(
347 BufferCollectionId(LARGE),
348 BufferCollectionId::from(FidlBufferCollectionId { value: LARGE })
349 );
350 }
351
352 #[fuchsia::test]
353 fn fidl_buffer_collection_id_from_buffer_collection_id() {
354 assert_eq!(
355 FidlBufferCollectionId { value: 1 },
356 FidlBufferCollectionId::from(BufferCollectionId(1))
357 );
358 assert_eq!(
359 FidlBufferCollectionId { value: 2 },
360 FidlBufferCollectionId::from(BufferCollectionId(2))
361 );
362 const LARGE: u64 = 1 << 63;
363 assert_eq!(
364 FidlBufferCollectionId { value: LARGE },
365 FidlBufferCollectionId::from(BufferCollectionId(LARGE))
366 );
367 }
368
369 #[fuchsia::test]
370 fn fidl_buffer_collection_id_to_buffer_collection_id() {
371 assert_eq!(BufferCollectionId(1), FidlBufferCollectionId { value: 1 }.into());
372 assert_eq!(BufferCollectionId(2), FidlBufferCollectionId { value: 2 }.into());
373 const LARGE: u64 = 1 << 63;
374 assert_eq!(BufferCollectionId(LARGE), FidlBufferCollectionId { value: LARGE }.into());
375 }
376
377 #[fuchsia::test]
378 fn buffer_collection_id_to_fidl_buffer_collection_id() {
379 assert_eq!(FidlBufferCollectionId { value: 1 }, BufferCollectionId(1).into());
380 assert_eq!(FidlBufferCollectionId { value: 2 }, BufferCollectionId(2).into());
381 const LARGE: u64 = 1 << 63;
382 assert_eq!(FidlBufferCollectionId { value: LARGE }, BufferCollectionId(LARGE).into());
383 }
384
385 #[fuchsia::test]
386 fn event_id_from_fidl_event_id() {
387 assert_eq!(EventId(1), EventId::from(FidlEventId { value: 1 }));
388 assert_eq!(EventId(2), EventId::from(FidlEventId { value: 2 }));
389 const LARGE: u64 = 1 << 63;
390 assert_eq!(EventId(LARGE), EventId::from(FidlEventId { value: LARGE }));
391 assert_eq!(INVALID_EVENT_ID, EventId::from(FidlEventId { value: INVALID_DISP_ID }));
392 }
393
394 #[fuchsia::test]
395 fn fidl_event_id_from_event_id() {
396 assert_eq!(FidlEventId { value: 1 }, FidlEventId::from(EventId(1)));
397 assert_eq!(FidlEventId { value: 2 }, FidlEventId::from(EventId(2)));
398 const LARGE: u64 = 1 << 63;
399 assert_eq!(FidlEventId { value: LARGE }, FidlEventId::from(EventId(LARGE)));
400 assert_eq!(FidlEventId { value: INVALID_DISP_ID }, FidlEventId::from(INVALID_EVENT_ID));
401 }
402
403 #[fuchsia::test]
404 fn fidl_event_id_to_event_id() {
405 assert_eq!(EventId(1), FidlEventId { value: 1 }.into());
406 assert_eq!(EventId(2), FidlEventId { value: 2 }.into());
407 const LARGE: u64 = 1 << 63;
408 assert_eq!(EventId(LARGE), FidlEventId { value: LARGE }.into());
409 assert_eq!(INVALID_EVENT_ID, FidlEventId { value: INVALID_DISP_ID }.into());
410 }
411
412 #[fuchsia::test]
413 fn event_id_to_fidl_event_id() {
414 assert_eq!(FidlEventId { value: 1 }, EventId(1).into());
415 assert_eq!(FidlEventId { value: 2 }, EventId(2).into());
416 const LARGE: u64 = 1 << 63;
417 assert_eq!(FidlEventId { value: LARGE }, EventId(LARGE).into());
418 assert_eq!(FidlEventId { value: INVALID_DISP_ID }, INVALID_EVENT_ID.into());
419 }
420
421 #[fuchsia::test]
422 fn event_id_default() {
423 let default: EventId = Default::default();
424 assert_eq!(default, INVALID_EVENT_ID);
425 }
426
427 #[fuchsia::test]
428 fn image_id_from_fidl_image_id() {
429 assert_eq!(ImageId(1), ImageId::from(FidlImageId { value: 1 }));
430 assert_eq!(ImageId(2), ImageId::from(FidlImageId { value: 2 }));
431 const LARGE: u64 = 1 << 63;
432 assert_eq!(ImageId(LARGE), ImageId::from(FidlImageId { value: LARGE }));
433 assert_eq!(INVALID_IMAGE_ID, ImageId::from(FidlImageId { value: INVALID_DISP_ID }));
434 }
435
436 #[fuchsia::test]
437 fn fidl_image_id_from_image_id() {
438 assert_eq!(FidlImageId { value: 1 }, FidlImageId::from(ImageId(1)));
439 assert_eq!(FidlImageId { value: 2 }, FidlImageId::from(ImageId(2)));
440 const LARGE: u64 = 1 << 63;
441 assert_eq!(FidlImageId { value: LARGE }, FidlImageId::from(ImageId(LARGE)));
442 assert_eq!(FidlImageId { value: INVALID_DISP_ID }, FidlImageId::from(INVALID_IMAGE_ID));
443 }
444
445 #[fuchsia::test]
446 fn fidl_image_id_to_image_id() {
447 assert_eq!(ImageId(1), FidlImageId { value: 1 }.into());
448 assert_eq!(ImageId(2), FidlImageId { value: 2 }.into());
449 const LARGE: u64 = 1 << 63;
450 assert_eq!(ImageId(LARGE), FidlImageId { value: LARGE }.into());
451 assert_eq!(INVALID_IMAGE_ID, FidlImageId { value: INVALID_DISP_ID }.into());
452 }
453
454 #[fuchsia::test]
455 fn image_id_to_fidl_image_id() {
456 assert_eq!(FidlImageId { value: 1 }, ImageId(1).into());
457 assert_eq!(FidlImageId { value: 2 }, ImageId(2).into());
458 const LARGE: u64 = 1 << 63;
459 assert_eq!(FidlImageId { value: LARGE }, ImageId(LARGE).into());
460 assert_eq!(FidlImageId { value: INVALID_DISP_ID }, INVALID_IMAGE_ID.into());
461 }
462
463 #[fuchsia::test]
464 fn image_id_default() {
465 let default: ImageId = Default::default();
466 assert_eq!(default, INVALID_IMAGE_ID);
467 }
468
469 #[fuchsia::test]
470 fn color_from_fidl_color() {
471 assert_eq!(
472 Color {
473 format: PixelFormat::R8G8B8A8,
474 bytes: [0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48]
475 },
476 Color::from(FidlColor {
477 format: FidlPixelFormat::R8G8B8A8,
478 bytes: [0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48],
479 })
480 );
481 }
482
483 #[fuchsia::test]
484 fn fidl_color_from_color() {
485 assert_eq!(
486 FidlColor {
487 format: FidlPixelFormat::R8G8B8A8,
488 bytes: [0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48]
489 },
490 FidlColor::from(Color {
491 format: PixelFormat::R8G8B8A8,
492 bytes: [0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48],
493 })
494 );
495 }
496
497 #[fuchsia::test]
498 fn fidl_color_to_color() {
499 assert_eq!(
500 Color {
501 format: PixelFormat::R8G8B8A8,
502 bytes: [0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48]
503 },
504 FidlColor {
505 format: FidlPixelFormat::R8G8B8A8,
506 bytes: [0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48]
507 }
508 .into()
509 );
510 }
511
512 #[fuchsia::test]
513 fn color_to_fidl_color() {
514 assert_eq!(
515 FidlColor {
516 format: FidlPixelFormat::R8G8B8A8,
517 bytes: [0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48]
518 },
519 Color {
520 format: PixelFormat::R8G8B8A8,
521 bytes: [0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48]
522 }
523 .into()
524 );
525 }
526}