atagen

monolith

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