atagen

monolith

public
Star0
Watch0
d47a99c6ac9f1476ff7711cca507138558ffa2e9
1
ssh://brewery@pls.lobotomise.me:33/atagen/monolith.git
crates/render-vk/tests/dmabuf.rsRust168 lines5.3 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, DmabufFlags};
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 samples_an_imported_dmabuf() {
59
    let Some(mut r) = renderer() else { return };
60
    let mut buf = dmabuf(&r);
61
    fill(&mut r, &mut buf, [0.0, 0.0, 1.0, 1.0]).wait().unwrap();
62
    let texture = r.import_dmabuf(&buf, None).unwrap();
63
    let mut out = r
64
        .create_buffer(Fourcc::Argb8888, (SIZE, SIZE).into())
65
        .unwrap();
66
    let mut target = r.bind(&mut out).unwrap();
67
    {
68
        let full = Rectangle::from_size((SIZE, SIZE).into());
69
        let mut frame = r
70
            .render(&mut target, (SIZE, SIZE).into(), Transform::Normal)
71
            .unwrap();
72
        frame
73
            .render_texture_from_to(
74
                &texture,
75
                Rectangle::from_size((SIZE as f64, SIZE as f64).into()),
76
                full,
77
                &[full],
78
                &[],
79
                Transform::Normal,
80
                1.0,
81
            )
82
            .unwrap();
83
        frame.finish().unwrap().wait().unwrap();
84
    }
85
    let mapping = r
86
        .copy_framebuffer(
87
            &target,
88
            Rectangle::from_size((SIZE, SIZE).into()),
89
            Fourcc::Abgr8888,
90
        )
91
        .unwrap();
92
    assert!(all_rgba(r.map_texture(&mapping).unwrap(), [0, 0, 255, 255]));
93
}
94
95
#[test]
96
fn frame_fences_export_as_sync_files() {
97
    let Some(mut r) = renderer() else { return };
98
    let mut buf = dmabuf(&r);
99
    let sync = fill(&mut r, &mut buf, [0.0, 1.0, 0.0, 1.0]);
100
    assert!(sync.is_exportable());
101
    let _fd = sync.export();
102
    sync.wait().unwrap();
103
    assert!(sync.is_reached());
104
}
105
106
#[test]
107
fn y_inverted_dmabuf_is_sampled_upside_down() {
108
    let Some(mut r) = renderer() else { return };
109
    let mut buf = dmabuf(&r);
110
    {
111
        let mut target = r.bind(&mut buf).unwrap();
112
        let mut frame = r
113
            .render(&mut target, (SIZE, SIZE).into(), Transform::Normal)
114
            .unwrap();
115
        let half = SIZE / 2;
116
        frame
117
            .clear(
118
                Color32F::from([1.0, 0.0, 0.0, 1.0]),
119
                &[Rectangle::from_size((SIZE, SIZE).into())],
120
            )
121
            .unwrap();
122
        frame
123
            .clear(
124
                Color32F::from([0.0, 1.0, 0.0, 1.0]),
125
                &[Rectangle::new((0, half).into(), (SIZE, half).into())],
126
            )
127
            .unwrap();
128
        frame.finish().unwrap().wait().unwrap();
129
    }
130
    let mut inverted = Dmabuf::builder_from_buffer(&buf, DmabufFlags::Y_INVERT);
131
    for ((fd, offset), stride) in buf.handles().zip(buf.offsets()).zip(buf.strides()) {
132
        inverted.add_plane(fd.try_clone_to_owned().unwrap(), offset, stride);
133
    }
134
    let texture = r.import_dmabuf(&inverted.build().unwrap(), None).unwrap();
135
    let mut out = r
136
        .create_buffer(Fourcc::Argb8888, (SIZE, SIZE).into())
137
        .unwrap();
138
    let mut target = r.bind(&mut out).unwrap();
139
    {
140
        let full = Rectangle::from_size((SIZE, SIZE).into());
141
        let mut frame = r
142
            .render(&mut target, (SIZE, SIZE).into(), Transform::Normal)
143
            .unwrap();
144
        frame
145
            .render_texture_from_to(
146
                &texture,
147
                Rectangle::from_size((SIZE as f64, SIZE as f64).into()),
148
                full,
149
                &[full],
150
                &[],
151
                Transform::Normal,
152
                1.0,
153
            )
154
            .unwrap();
155
        frame.finish().unwrap().wait().unwrap();
156
    }
157
    let mapping = r
158
        .copy_framebuffer(
159
            &target,
160
            Rectangle::from_size((SIZE, SIZE).into()),
161
            Fourcc::Abgr8888,
162
        )
163
        .unwrap();
164
    let pixels = r.map_texture(&mapping).unwrap().as_chunks::<4>().0;
165
    let at = |y: i32| pixels[(y * SIZE + SIZE / 2) as usize];
166
    assert_eq!(at(1), [0, 255, 0, 255]);
167
    assert_eq!(at(SIZE - 2), [255, 0, 0, 255]);
168
}