7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 1 | //! Dmabuf allocation, rendering, import and fence export. Skips on devices |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 2 | //! without dmabuf support, such as lavapipe inside the nix sandbox. |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 3 | |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 4 | use monolith_render_vk::VulkanRenderer; |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 5 | use smithay::backend::allocator::dmabuf::Dmabuf; |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 6 | use smithay::backend::allocator::{Allocator, Fourcc, Modifier}; |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 7 | use smithay::backend::renderer::{ |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 8 | Bind, Color32F, ExportMem, Frame, ImportDma, Offscreen, Renderer, |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 9 | }; |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 10 | use smithay::utils::{Rectangle, Transform}; |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 11 | |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 12 | const SIZE: i32 = 32; |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 13 | |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 14 | fn renderer() -> Option<VulkanRenderer> { |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 15 | let r = VulkanRenderer::new().expect("no usable Vulkan device"); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 16 | if !r.supports_dmabuf() { |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 17 | eprintln!("skipping, {} cannot share dmabufs", r.device_name()); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 18 | return None; |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 19 | } |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 20 | Some(r) |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 21 | } |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 22 | |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 23 | fn dmabuf(r: &VulkanRenderer) -> Dmabuf { |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 24 | let modifiers: Vec<Modifier> = r |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 25 | .render_formats() |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 26 | .iter() |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 27 | .filter(|f| f.code == Fourcc::Argb8888) |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 28 | .map(|f| f.modifier) |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 29 | .collect(); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 30 | r.allocator() |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 31 | .create_buffer(SIZE as u32, SIZE as u32, Fourcc::Argb8888, &modifiers) |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 32 | .unwrap() |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 33 | } |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 34 | |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 35 | fn fill( |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 36 | r: &mut VulkanRenderer, |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 37 | buf: &mut Dmabuf, |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 38 | colour: [f32; 4], |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 39 | ) -> smithay::backend::renderer::sync::SyncPoint { |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 40 | let mut target = r.bind(buf).unwrap(); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 41 | let mut frame = r |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 42 | .render(&mut target, (SIZE, SIZE).into(), Transform::Normal) |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 43 | .unwrap(); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 44 | frame |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 45 | .clear( |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 46 | Color32F::from(colour), |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 47 | &[Rectangle::from_size((SIZE, SIZE).into())], |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 48 | ) |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 49 | .unwrap(); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 50 | frame.finish().unwrap() |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 51 | } |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 52 | |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 53 | fn all_rgba(bytes: &[u8], want: [u8; 4]) -> bool { |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 54 | bytes.as_chunks::<4>().0.iter().all(|p| *p == want) |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 55 | } |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 56 | |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 57 | #[test] |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 58 | fn renders_into_an_allocated_dmabuf_and_reads_it_back() { |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 59 | let Some(mut r) = renderer() else { return }; |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 60 | let mut buf = dmabuf(&r); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 61 | fill(&mut r, &mut buf, [1.0, 0.0, 0.0, 1.0]).wait().unwrap(); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 62 | let target = r.bind(&mut buf).unwrap(); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 63 | let mapping = r |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 64 | .copy_framebuffer( |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 65 | &target, |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 66 | Rectangle::from_size((SIZE, SIZE).into()), |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 67 | Fourcc::Abgr8888, |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 68 | ) |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 69 | .unwrap(); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 70 | assert!(all_rgba(r.map_texture(&mapping).unwrap(), [255, 0, 0, 255])); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 71 | } |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 72 | |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 73 | #[test] |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 74 | fn samples_an_imported_dmabuf() { |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 75 | let Some(mut r) = renderer() else { return }; |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 76 | let mut buf = dmabuf(&r); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 77 | fill(&mut r, &mut buf, [0.0, 0.0, 1.0, 1.0]).wait().unwrap(); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 78 | let texture = r.import_dmabuf(&buf, None).unwrap(); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 79 | let mut out = r |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 80 | .create_buffer(Fourcc::Argb8888, (SIZE, SIZE).into()) |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 81 | .unwrap(); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 82 | let mut target = r.bind(&mut out).unwrap(); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 83 | { |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 84 | let full = Rectangle::from_size((SIZE, SIZE).into()); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 85 | let mut frame = r |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 86 | .render(&mut target, (SIZE, SIZE).into(), Transform::Normal) |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 87 | .unwrap(); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 88 | frame |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 89 | .render_texture_from_to( |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 90 | &texture, |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 91 | Rectangle::from_size((SIZE as f64, SIZE as f64).into()), |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 92 | full, |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 93 | &[full], |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 94 | &[], |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 95 | Transform::Normal, |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 96 | 1.0, |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 97 | ) |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 98 | .unwrap(); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 99 | frame.finish().unwrap().wait().unwrap(); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 100 | } |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 101 | let mapping = r |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 102 | .copy_framebuffer( |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 103 | &target, |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 104 | Rectangle::from_size((SIZE, SIZE).into()), |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 105 | Fourcc::Abgr8888, |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 106 | ) |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 107 | .unwrap(); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 108 | assert!(all_rgba(r.map_texture(&mapping).unwrap(), [0, 0, 255, 255])); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 109 | } |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 110 | |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 111 | #[test] |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 112 | fn imports_are_cached_per_buffer() { |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 113 | let Some(mut r) = renderer() else { return }; |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 114 | let buf = dmabuf(&r); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 115 | let a = r.import_dmabuf(&buf, None).unwrap(); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 116 | let b = r.import_dmabuf(&buf, None).unwrap(); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 117 | assert_eq!(format!("{a:?}"), format!("{b:?}")); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 118 | } |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 119 | |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 120 | #[test] |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 121 | fn frame_fences_export_as_sync_files() { |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 122 | let Some(mut r) = renderer() else { return }; |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 123 | let mut buf = dmabuf(&r); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 124 | let sync = fill(&mut r, &mut buf, [0.0, 1.0, 0.0, 1.0]); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 125 | assert!(sync.is_exportable()); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 126 | let _fd = sync.export(); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 127 | sync.wait().unwrap(); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 128 | assert!(sync.is_reached()); |
7de49c2aa70b | atagen | 2026-10-16 09:27 UTC | 129 | } |