1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub enum ColorModel {
23 Yuv,
25 Rgb,
27}
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31pub enum Subsampling {
32 C400,
34 C411,
36 C420,
38 C422,
40 C444,
42}
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq)]
46pub enum PlaneLayout {
47 Packed,
49 SemiPlanar,
51 Planar,
53}
54
55#[derive(Debug, Clone, Copy, PartialEq, Eq)]
57pub enum RgbOrder {
58 Rgb,
60 Bgr,
62}
63
64#[derive(Debug, Clone, Copy, PartialEq, Eq)]
66pub enum ChromaOrder {
67 CbCr,
69 CrCb,
71}
72
73#[derive(Debug, Clone, Copy, PartialEq, Eq)]
75pub enum SampleDepth {
76 Bits8,
78 Bits10,
80 Bits12,
82 Bits16,
84}
85
86#[derive(Debug, Clone, Copy, PartialEq, Eq)]
88pub enum SampleContainer {
89 U8,
91 U16,
94 U32Packed,
96}
97
98#[derive(Debug, Clone, Copy, PartialEq, Eq)]
100pub enum Alpha {
101 None,
103 Straight,
105 Premultiplied,
107}
108
109#[derive(Debug, Clone, Copy, PartialEq, Eq)]
114pub struct SurfaceFormat {
115 model: ColorModel,
116 subsampling: Subsampling,
117 layout: PlaneLayout,
118 rgb_order: RgbOrder,
119 chroma_order: ChromaOrder,
120 depth: SampleDepth,
121 container: SampleContainer,
122 alpha: Alpha,
123}
124
125impl SurfaceFormat {
126 const fn rgb(
128 order: RgbOrder,
129 depth: SampleDepth,
130 container: SampleContainer,
131 alpha: Alpha,
132 ) -> Self {
133 Self {
134 model: ColorModel::Rgb,
135 subsampling: Subsampling::C444,
136 layout: PlaneLayout::Packed,
137 rgb_order: order,
138 chroma_order: ChromaOrder::CbCr,
139 depth,
140 container,
141 alpha,
142 }
143 }
144
145 const fn yuv(
147 subsampling: Subsampling,
148 layout: PlaneLayout,
149 order: ChromaOrder,
150 depth: SampleDepth,
151 container: SampleContainer,
152 ) -> Self {
153 Self {
154 model: ColorModel::Yuv,
155 subsampling,
156 layout,
157 rgb_order: RgbOrder::Rgb,
158 chroma_order: order,
159 depth,
160 container,
161 alpha: Alpha::None,
162 }
163 }
164
165 pub const fn model(&self) -> ColorModel {
167 self.model
168 }
169
170 pub const fn subsampling(&self) -> Subsampling {
172 self.subsampling
173 }
174
175 pub const fn layout(&self) -> PlaneLayout {
177 self.layout
178 }
179
180 pub const fn rgb_order(&self) -> RgbOrder {
182 self.rgb_order
183 }
184
185 pub const fn chroma_order(&self) -> ChromaOrder {
187 self.chroma_order
188 }
189
190 pub const fn depth(&self) -> SampleDepth {
192 self.depth
193 }
194
195 pub const fn container(&self) -> SampleContainer {
197 self.container
198 }
199
200 pub const fn alpha(&self) -> Alpha {
202 self.alpha
203 }
204
205 pub const fn is_yuv(&self) -> bool {
207 matches!(self.model, ColorModel::Yuv)
208 }
209
210 pub const fn plane_count(&self) -> usize {
213 match self.subsampling {
214 Subsampling::C400 => 1,
215 _ => match self.layout {
216 PlaneLayout::Packed => 1,
217 PlaneLayout::SemiPlanar => 2,
218 PlaneLayout::Planar => 3,
219 },
220 }
221 }
222}
223
224#[derive(Debug, Clone, Copy, PartialEq, Eq)]
229pub enum SurfaceFormatKind {
230 Bgra8(SurfaceFormat),
232 Rgba8(SurfaceFormat),
234
235 Nv12(SurfaceFormat),
237 Nv21(SurfaceFormat),
239 I420(SurfaceFormat),
241 Yv12(SurfaceFormat),
243 Nv16(SurfaceFormat),
245 Nv61(SurfaceFormat),
247 Yu16(SurfaceFormat),
249 Yv16(SurfaceFormat),
251 Nv24(SurfaceFormat),
253 Yuv444(SurfaceFormat),
255 Mono8(SurfaceFormat),
257
258 P010(SurfaceFormat),
261 P012(SurfaceFormat),
263 P016(SurfaceFormat),
265 I010(SurfaceFormat),
267 I012(SurfaceFormat),
269 I016(SurfaceFormat),
271 P210(SurfaceFormat),
273 P212(SurfaceFormat),
275 P216(SurfaceFormat),
277 P410(SurfaceFormat),
279 P412(SurfaceFormat),
281 P416(SurfaceFormat),
283 Q410(SurfaceFormat),
285 Q416(SurfaceFormat),
287}
288
289impl SurfaceFormatKind {
290 pub const fn bgra8() -> Self {
292 Self::Bgra8(SurfaceFormat::rgb(
293 RgbOrder::Bgr,
294 SampleDepth::Bits8,
295 SampleContainer::U8,
296 Alpha::Straight,
297 ))
298 }
299
300 pub const fn rgba8() -> Self {
302 Self::Rgba8(SurfaceFormat::rgb(
303 RgbOrder::Rgb,
304 SampleDepth::Bits8,
305 SampleContainer::U8,
306 Alpha::Straight,
307 ))
308 }
309
310 pub const fn nv12() -> Self {
312 Self::Nv12(SurfaceFormat::yuv(
313 Subsampling::C420,
314 PlaneLayout::SemiPlanar,
315 ChromaOrder::CbCr,
316 SampleDepth::Bits8,
317 SampleContainer::U8,
318 ))
319 }
320
321 pub const fn nv21() -> Self {
323 Self::Nv21(SurfaceFormat::yuv(
324 Subsampling::C420,
325 PlaneLayout::SemiPlanar,
326 ChromaOrder::CrCb,
327 SampleDepth::Bits8,
328 SampleContainer::U8,
329 ))
330 }
331
332 pub const fn i420() -> Self {
334 Self::I420(SurfaceFormat::yuv(
335 Subsampling::C420,
336 PlaneLayout::Planar,
337 ChromaOrder::CbCr,
338 SampleDepth::Bits8,
339 SampleContainer::U8,
340 ))
341 }
342
343 pub const fn yv12() -> Self {
345 Self::Yv12(SurfaceFormat::yuv(
346 Subsampling::C420,
347 PlaneLayout::Planar,
348 ChromaOrder::CrCb,
349 SampleDepth::Bits8,
350 SampleContainer::U8,
351 ))
352 }
353
354 pub const fn nv16() -> Self {
356 Self::Nv16(SurfaceFormat::yuv(
357 Subsampling::C422,
358 PlaneLayout::SemiPlanar,
359 ChromaOrder::CbCr,
360 SampleDepth::Bits8,
361 SampleContainer::U8,
362 ))
363 }
364
365 pub const fn nv61() -> Self {
367 Self::Nv61(SurfaceFormat::yuv(
368 Subsampling::C422,
369 PlaneLayout::SemiPlanar,
370 ChromaOrder::CrCb,
371 SampleDepth::Bits8,
372 SampleContainer::U8,
373 ))
374 }
375
376 pub const fn yu16() -> Self {
378 Self::Yu16(SurfaceFormat::yuv(
379 Subsampling::C422,
380 PlaneLayout::Planar,
381 ChromaOrder::CbCr,
382 SampleDepth::Bits8,
383 SampleContainer::U8,
384 ))
385 }
386
387 pub const fn yv16() -> Self {
389 Self::Yv16(SurfaceFormat::yuv(
390 Subsampling::C422,
391 PlaneLayout::Planar,
392 ChromaOrder::CrCb,
393 SampleDepth::Bits8,
394 SampleContainer::U8,
395 ))
396 }
397
398 pub const fn nv24() -> Self {
400 Self::Nv24(SurfaceFormat::yuv(
401 Subsampling::C444,
402 PlaneLayout::SemiPlanar,
403 ChromaOrder::CbCr,
404 SampleDepth::Bits8,
405 SampleContainer::U8,
406 ))
407 }
408
409 pub const fn yuv444() -> Self {
411 Self::Yuv444(SurfaceFormat::yuv(
412 Subsampling::C444,
413 PlaneLayout::Planar,
414 ChromaOrder::CbCr,
415 SampleDepth::Bits8,
416 SampleContainer::U8,
417 ))
418 }
419
420 pub const fn mono8() -> Self {
422 Self::Mono8(SurfaceFormat::yuv(
423 Subsampling::C400,
424 PlaneLayout::Planar,
425 ChromaOrder::CbCr,
426 SampleDepth::Bits8,
427 SampleContainer::U8,
428 ))
429 }
430
431 pub const fn p010() -> Self {
433 Self::P010(SurfaceFormat::yuv(
434 Subsampling::C420,
435 PlaneLayout::SemiPlanar,
436 ChromaOrder::CbCr,
437 SampleDepth::Bits10,
438 SampleContainer::U16,
439 ))
440 }
441
442 pub const fn p012() -> Self {
444 Self::P012(SurfaceFormat::yuv(
445 Subsampling::C420,
446 PlaneLayout::SemiPlanar,
447 ChromaOrder::CbCr,
448 SampleDepth::Bits12,
449 SampleContainer::U16,
450 ))
451 }
452
453 pub const fn p016() -> Self {
455 Self::P016(SurfaceFormat::yuv(
456 Subsampling::C420,
457 PlaneLayout::SemiPlanar,
458 ChromaOrder::CbCr,
459 SampleDepth::Bits16,
460 SampleContainer::U16,
461 ))
462 }
463
464 pub const fn i010() -> Self {
466 Self::I010(SurfaceFormat::yuv(
467 Subsampling::C420,
468 PlaneLayout::Planar,
469 ChromaOrder::CbCr,
470 SampleDepth::Bits10,
471 SampleContainer::U16,
472 ))
473 }
474
475 pub const fn i012() -> Self {
477 Self::I012(SurfaceFormat::yuv(
478 Subsampling::C420,
479 PlaneLayout::Planar,
480 ChromaOrder::CbCr,
481 SampleDepth::Bits12,
482 SampleContainer::U16,
483 ))
484 }
485
486 pub const fn i016() -> Self {
488 Self::I016(SurfaceFormat::yuv(
489 Subsampling::C420,
490 PlaneLayout::Planar,
491 ChromaOrder::CbCr,
492 SampleDepth::Bits16,
493 SampleContainer::U16,
494 ))
495 }
496
497 pub const fn p210() -> Self {
499 Self::P210(SurfaceFormat::yuv(
500 Subsampling::C422,
501 PlaneLayout::SemiPlanar,
502 ChromaOrder::CbCr,
503 SampleDepth::Bits10,
504 SampleContainer::U16,
505 ))
506 }
507
508 pub const fn p212() -> Self {
510 Self::P212(SurfaceFormat::yuv(
511 Subsampling::C422,
512 PlaneLayout::SemiPlanar,
513 ChromaOrder::CbCr,
514 SampleDepth::Bits12,
515 SampleContainer::U16,
516 ))
517 }
518
519 pub const fn p216() -> Self {
521 Self::P216(SurfaceFormat::yuv(
522 Subsampling::C422,
523 PlaneLayout::SemiPlanar,
524 ChromaOrder::CbCr,
525 SampleDepth::Bits16,
526 SampleContainer::U16,
527 ))
528 }
529
530 pub const fn p410() -> Self {
532 Self::P410(SurfaceFormat::yuv(
533 Subsampling::C444,
534 PlaneLayout::SemiPlanar,
535 ChromaOrder::CbCr,
536 SampleDepth::Bits10,
537 SampleContainer::U16,
538 ))
539 }
540
541 pub const fn p412() -> Self {
543 Self::P412(SurfaceFormat::yuv(
544 Subsampling::C444,
545 PlaneLayout::SemiPlanar,
546 ChromaOrder::CbCr,
547 SampleDepth::Bits12,
548 SampleContainer::U16,
549 ))
550 }
551
552 pub const fn p416() -> Self {
554 Self::P416(SurfaceFormat::yuv(
555 Subsampling::C444,
556 PlaneLayout::SemiPlanar,
557 ChromaOrder::CbCr,
558 SampleDepth::Bits16,
559 SampleContainer::U16,
560 ))
561 }
562
563 pub const fn q410() -> Self {
565 Self::Q410(SurfaceFormat::yuv(
566 Subsampling::C444,
567 PlaneLayout::Planar,
568 ChromaOrder::CbCr,
569 SampleDepth::Bits10,
570 SampleContainer::U16,
571 ))
572 }
573
574 pub const fn q416() -> Self {
576 Self::Q416(SurfaceFormat::yuv(
577 Subsampling::C444,
578 PlaneLayout::Planar,
579 ChromaOrder::CbCr,
580 SampleDepth::Bits16,
581 SampleContainer::U16,
582 ))
583 }
584
585 pub const fn dimensions(self) -> SurfaceFormat {
587 match self {
588 Self::Bgra8(format) | Self::Rgba8(format) => format,
589 Self::Nv12(format)
590 | Self::Nv21(format)
591 | Self::I420(format)
592 | Self::Yv12(format)
593 | Self::Nv16(format)
594 | Self::Nv61(format)
595 | Self::Yu16(format)
596 | Self::Yv16(format)
597 | Self::Nv24(format)
598 | Self::Yuv444(format)
599 | Self::Mono8(format) => format,
600 Self::P010(format)
601 | Self::P012(format)
602 | Self::P016(format)
603 | Self::I010(format)
604 | Self::I012(format)
605 | Self::I016(format)
606 | Self::P210(format)
607 | Self::P212(format)
608 | Self::P216(format)
609 | Self::P410(format)
610 | Self::P412(format)
611 | Self::P416(format)
612 | Self::Q410(format)
613 | Self::Q416(format) => format,
614 }
615 }
616
617 pub const fn is_yuv(self) -> bool {
619 self.dimensions().is_yuv()
620 }
621
622 pub const fn plane_count(self) -> usize {
624 self.dimensions().plane_count()
625 }
626}
627
628impl std::fmt::Display for SurfaceFormatKind {
629 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
631 f.write_str(match self {
632 Self::Bgra8(_) => "BGRA8",
633 Self::Rgba8(_) => "RGBA8",
634 Self::Nv12(_) => "NV12",
635 Self::Nv21(_) => "NV21",
636 Self::I420(_) => "I420",
637 Self::Yv12(_) => "YV12",
638 Self::Nv16(_) => "NV16",
639 Self::Nv61(_) => "NV61",
640 Self::Yu16(_) => "YU16",
641 Self::Yv16(_) => "YV16",
642 Self::Nv24(_) => "NV24",
643 Self::Yuv444(_) => "YUV444",
644 Self::Mono8(_) => "MONO8",
645 Self::P010(_) => "P010",
646 Self::P012(_) => "P012",
647 Self::P016(_) => "P016",
648 Self::I010(_) => "I010",
649 Self::I012(_) => "I012",
650 Self::I016(_) => "I016",
651 Self::P210(_) => "P210",
652 Self::P212(_) => "P212",
653 Self::P216(_) => "P216",
654 Self::P410(_) => "P410",
655 Self::P412(_) => "P412",
656 Self::P416(_) => "P416",
657 Self::Q410(_) => "Q410",
658 Self::Q416(_) => "Q416",
659 })
660 }
661}
662
663#[derive(Debug, Clone, PartialEq, Eq)]
670pub struct DmaBufFormatCapability {
671 pub format: SurfaceFormatKind,
673 pub modifiers: Vec<u64>,
675}
676
677impl DmaBufFormatCapability {
678 pub fn supports(&self, modifier: u64) -> bool {
680 self.modifiers.contains(&modifier)
681 }
682}
683
684#[derive(Debug, Clone, PartialEq, Eq, Default)]
701pub struct DmaBufCapabilities {
702 formats: Vec<DmaBufFormatCapability>,
703}
704
705impl DmaBufCapabilities {
706 pub fn new(formats: Vec<DmaBufFormatCapability>) -> Self {
708 Self { formats }
709 }
710
711 pub fn formats(&self) -> &[DmaBufFormatCapability] {
713 &self.formats
714 }
715
716 pub fn format(&self, format: &SurfaceFormatKind) -> Option<&DmaBufFormatCapability> {
718 self.formats.iter().find(|entry| entry.format == *format)
719 }
720
721 pub fn modifiers(&self, format: &SurfaceFormatKind) -> Option<&[u64]> {
723 self.format(format).map(|entry| entry.modifiers.as_slice())
724 }
725
726 pub fn supports(&self, format: &SurfaceFormatKind, modifier: u64) -> bool {
728 self.format(format)
729 .is_some_and(|entry| entry.supports(modifier))
730 }
731}
732
733#[cfg(test)]
734mod tests {
735 use super::*;
736
737 #[test]
738 fn a_packed_rgb_format_is_one_plane_and_not_yuv() {
739 let format = SurfaceFormatKind::bgra8().dimensions();
740 assert_eq!(format.model(), ColorModel::Rgb);
741 assert_eq!(format.rgb_order(), RgbOrder::Bgr);
742 assert_eq!(format.plane_count(), 1);
743 assert!(!format.is_yuv());
744 }
745
746 #[test]
747 fn a_semi_planar_yuv_format_is_two_planes() {
748 let format = SurfaceFormatKind::nv12().dimensions();
749 assert!(format.is_yuv());
750 assert_eq!(format.subsampling(), Subsampling::C420);
751 assert_eq!(format.layout(), PlaneLayout::SemiPlanar);
752 assert_eq!(format.plane_count(), 2);
753 assert_eq!(format.depth(), SampleDepth::Bits8);
754 assert_eq!(SurfaceFormatKind::nv12().plane_count(), 2);
755 }
756
757 #[test]
758 fn a_planar_yuv_format_is_three_planes_bar_mono() {
759 assert_eq!(SurfaceFormatKind::i420().plane_count(), 3);
760 assert_eq!(SurfaceFormatKind::q416().plane_count(), 3);
761 assert_eq!(SurfaceFormatKind::mono8().plane_count(), 1);
762 }
763
764 #[test]
765 fn a_sixteen_bit_container_carries_ten_bits_in_its_high_bits() {
766 let format = SurfaceFormatKind::p010().dimensions();
767 assert_eq!(format.depth(), SampleDepth::Bits10);
768 assert_eq!(format.container(), SampleContainer::U16);
769 }
770
771 #[test]
772 fn the_chroma_orders_differ_only_in_which_component_comes_first() {
773 let cb_cr = SurfaceFormatKind::nv12().dimensions();
774 let cr_cb = SurfaceFormatKind::nv21().dimensions();
775 assert_eq!(cb_cr.chroma_order(), ChromaOrder::CbCr);
776 assert_eq!(cr_cb.chroma_order(), ChromaOrder::CrCb);
777 assert_ne!(cb_cr, cr_cb);
778 assert_eq!(cb_cr.subsampling(), cr_cb.subsampling());
779 assert_eq!(cb_cr.plane_count(), cr_cb.plane_count());
780 }
781
782 #[test]
783 fn a_kind_displays_as_its_conventional_name() {
784 assert_eq!(SurfaceFormatKind::nv12().to_string(), "NV12");
785 assert_eq!(SurfaceFormatKind::p010().to_string(), "P010");
786 assert_eq!(SurfaceFormatKind::bgra8().to_string(), "BGRA8");
787 }
788
789 #[test]
791 fn kinds_compare_by_their_shape() {
792 assert_eq!(SurfaceFormatKind::nv12(), SurfaceFormatKind::nv12());
793 assert_ne!(SurfaceFormatKind::nv12(), SurfaceFormatKind::nv21());
794 assert_ne!(SurfaceFormatKind::nv12(), SurfaceFormatKind::i420());
795 }
796}