atagen

monolith

public
Star0
Watch0
a1f375a8b4bed2954bd4bb4deb4dc6a6efeeb217
1
ssh://brewery@pls.lobotomise.me:33/atagen/monolith.git

Blame: crates/render-vk/tests/dmabuf.rs

7de49c2aa70batagen2026-10-16 09:27 UTC1
//! Dmabuf allocation, rendering, import and fence export. Skips on devices
7de49c2aa70batagen2026-10-16 09:27 UTC2
//! without dmabuf support, such as lavapipe inside the nix sandbox.
7de49c2aa70batagen2026-10-16 09:27 UTC3
7de49c2aa70batagen2026-10-16 09:27 UTC4
use monolith_render_vk::VulkanRenderer;
b03e3b32603aatagen2026-10-19 07:40 UTC5
use smithay::backend::allocator::dmabuf::{Dmabuf, DmabufFlags};
7de49c2aa70batagen2026-10-16 09:27 UTC6
use smithay::backend::allocator::{Allocator, Fourcc, Modifier};
7de49c2aa70batagen2026-10-16 09:27 UTC7
use smithay::backend::renderer::{
7de49c2aa70batagen2026-10-16 09:27 UTC8
    Bind, Color32F, ExportMem, Frame, ImportDma, Offscreen, Renderer,
7de49c2aa70batagen2026-10-16 09:27 UTC9
};
7de49c2aa70batagen2026-10-16 09:27 UTC10
use smithay::utils::{Rectangle, Transform};
7de49c2aa70batagen2026-10-16 09:27 UTC11
7de49c2aa70batagen2026-10-16 09:27 UTC12
const SIZE: i32 = 32;
7de49c2aa70batagen2026-10-16 09:27 UTC13
7de49c2aa70batagen2026-10-16 09:27 UTC14
fn renderer() -> Option<VulkanRenderer> {
7de49c2aa70batagen2026-10-16 09:27 UTC15
    let r = VulkanRenderer::new().expect("no usable Vulkan device");
7de49c2aa70batagen2026-10-16 09:27 UTC16
    if !r.supports_dmabuf() {
7de49c2aa70batagen2026-10-16 09:27 UTC17
        eprintln!("skipping, {} cannot share dmabufs", r.device_name());
7de49c2aa70batagen2026-10-16 09:27 UTC18
        return None;
7de49c2aa70batagen2026-10-16 09:27 UTC19
    }
7de49c2aa70batagen2026-10-16 09:27 UTC20
    Some(r)
7de49c2aa70batagen2026-10-16 09:27 UTC21
}
7de49c2aa70batagen2026-10-16 09:27 UTC22
7de49c2aa70batagen2026-10-16 09:27 UTC23
fn dmabuf(r: &VulkanRenderer) -> Dmabuf {
7de49c2aa70batagen2026-10-16 09:27 UTC24
    let modifiers: Vec<Modifier> = r
7de49c2aa70batagen2026-10-16 09:27 UTC25
        .render_formats()
7de49c2aa70batagen2026-10-16 09:27 UTC26
        .iter()
7de49c2aa70batagen2026-10-16 09:27 UTC27
        .filter(|f| f.code == Fourcc::Argb8888)
7de49c2aa70batagen2026-10-16 09:27 UTC28
        .map(|f| f.modifier)
7de49c2aa70batagen2026-10-16 09:27 UTC29
        .collect();
7de49c2aa70batagen2026-10-16 09:27 UTC30
    r.allocator()
7de49c2aa70batagen2026-10-16 09:27 UTC31
        .create_buffer(SIZE as u32, SIZE as u32, Fourcc::Argb8888, &modifiers)
7de49c2aa70batagen2026-10-16 09:27 UTC32
        .unwrap()
7de49c2aa70batagen2026-10-16 09:27 UTC33
}
7de49c2aa70batagen2026-10-16 09:27 UTC34
7de49c2aa70batagen2026-10-16 09:27 UTC35
fn fill(
7de49c2aa70batagen2026-10-16 09:27 UTC36
    r: &mut VulkanRenderer,
7de49c2aa70batagen2026-10-16 09:27 UTC37
    buf: &mut Dmabuf,
7de49c2aa70batagen2026-10-16 09:27 UTC38
    colour: [f32; 4],
7de49c2aa70batagen2026-10-16 09:27 UTC39
) -> smithay::backend::renderer::sync::SyncPoint {
7de49c2aa70batagen2026-10-16 09:27 UTC40
    let mut target = r.bind(buf).unwrap();
7de49c2aa70batagen2026-10-16 09:27 UTC41
    let mut frame = r
7de49c2aa70batagen2026-10-16 09:27 UTC42
        .render(&mut target, (SIZE, SIZE).into(), Transform::Normal)
7de49c2aa70batagen2026-10-16 09:27 UTC43
        .unwrap();
7de49c2aa70batagen2026-10-16 09:27 UTC44
    frame
7de49c2aa70batagen2026-10-16 09:27 UTC45
        .clear(
7de49c2aa70batagen2026-10-16 09:27 UTC46
            Color32F::from(colour),
7de49c2aa70batagen2026-10-16 09:27 UTC47
            &[Rectangle::from_size((SIZE, SIZE).into())],
7de49c2aa70batagen2026-10-16 09:27 UTC48
        )
7de49c2aa70batagen2026-10-16 09:27 UTC49
        .unwrap();
7de49c2aa70batagen2026-10-16 09:27 UTC50
    frame.finish().unwrap()
7de49c2aa70batagen2026-10-16 09:27 UTC51
}
7de49c2aa70batagen2026-10-16 09:27 UTC52
7de49c2aa70batagen2026-10-16 09:27 UTC53
fn all_rgba(bytes: &[u8], want: [u8; 4]) -> bool {
7de49c2aa70batagen2026-10-16 09:27 UTC54
    bytes.as_chunks::<4>().0.iter().all(|p| *p == want)
7de49c2aa70batagen2026-10-16 09:27 UTC55
}
7de49c2aa70batagen2026-10-16 09:27 UTC56
7de49c2aa70batagen2026-10-16 09:27 UTC57
#[test]
7de49c2aa70batagen2026-10-16 09:27 UTC58
fn samples_an_imported_dmabuf() {
7de49c2aa70batagen2026-10-16 09:27 UTC59
    let Some(mut r) = renderer() else { return };
7de49c2aa70batagen2026-10-16 09:27 UTC60
    let mut buf = dmabuf(&r);
7de49c2aa70batagen2026-10-16 09:27 UTC61
    fill(&mut r, &mut buf, [0.0, 0.0, 1.0, 1.0]).wait().unwrap();
7de49c2aa70batagen2026-10-16 09:27 UTC62
    let texture = r.import_dmabuf(&buf, None).unwrap();
7de49c2aa70batagen2026-10-16 09:27 UTC63
    let mut out = r
7de49c2aa70batagen2026-10-16 09:27 UTC64
        .create_buffer(Fourcc::Argb8888, (SIZE, SIZE).into())
7de49c2aa70batagen2026-10-16 09:27 UTC65
        .unwrap();
7de49c2aa70batagen2026-10-16 09:27 UTC66
    let mut target = r.bind(&mut out).unwrap();
7de49c2aa70batagen2026-10-16 09:27 UTC67
    {
7de49c2aa70batagen2026-10-16 09:27 UTC68
        let full = Rectangle::from_size((SIZE, SIZE).into());
7de49c2aa70batagen2026-10-16 09:27 UTC69
        let mut frame = r
7de49c2aa70batagen2026-10-16 09:27 UTC70
            .render(&mut target, (SIZE, SIZE).into(), Transform::Normal)
7de49c2aa70batagen2026-10-16 09:27 UTC71
            .unwrap();
7de49c2aa70batagen2026-10-16 09:27 UTC72
        frame
7de49c2aa70batagen2026-10-16 09:27 UTC73
            .render_texture_from_to(
7de49c2aa70batagen2026-10-16 09:27 UTC74
                &texture,
7de49c2aa70batagen2026-10-16 09:27 UTC75
                Rectangle::from_size((SIZE as f64, SIZE as f64).into()),
7de49c2aa70batagen2026-10-16 09:27 UTC76
                full,
7de49c2aa70batagen2026-10-16 09:27 UTC77
                &[full],
7de49c2aa70batagen2026-10-16 09:27 UTC78
                &[],
7de49c2aa70batagen2026-10-16 09:27 UTC79
                Transform::Normal,
7de49c2aa70batagen2026-10-16 09:27 UTC80
                1.0,
7de49c2aa70batagen2026-10-16 09:27 UTC81
            )
7de49c2aa70batagen2026-10-16 09:27 UTC82
            .unwrap();
7de49c2aa70batagen2026-10-16 09:27 UTC83
        frame.finish().unwrap().wait().unwrap();
7de49c2aa70batagen2026-10-16 09:27 UTC84
    }
7de49c2aa70batagen2026-10-16 09:27 UTC85
    let mapping = r
7de49c2aa70batagen2026-10-16 09:27 UTC86
        .copy_framebuffer(
7de49c2aa70batagen2026-10-16 09:27 UTC87
            &target,
7de49c2aa70batagen2026-10-16 09:27 UTC88
            Rectangle::from_size((SIZE, SIZE).into()),
7de49c2aa70batagen2026-10-16 09:27 UTC89
            Fourcc::Abgr8888,
7de49c2aa70batagen2026-10-16 09:27 UTC90
        )
7de49c2aa70batagen2026-10-16 09:27 UTC91
        .unwrap();
7de49c2aa70batagen2026-10-16 09:27 UTC92
    assert!(all_rgba(r.map_texture(&mapping).unwrap(), [0, 0, 255, 255]));
7de49c2aa70batagen2026-10-16 09:27 UTC93
}
7de49c2aa70batagen2026-10-16 09:27 UTC94
7de49c2aa70batagen2026-10-16 09:27 UTC95
#[test]
7de49c2aa70batagen2026-10-16 09:27 UTC96
fn frame_fences_export_as_sync_files() {
7de49c2aa70batagen2026-10-16 09:27 UTC97
    let Some(mut r) = renderer() else { return };
7de49c2aa70batagen2026-10-16 09:27 UTC98
    let mut buf = dmabuf(&r);
7de49c2aa70batagen2026-10-16 09:27 UTC99
    let sync = fill(&mut r, &mut buf, [0.0, 1.0, 0.0, 1.0]);
7de49c2aa70batagen2026-10-16 09:27 UTC100
    assert!(sync.is_exportable());
7de49c2aa70batagen2026-10-16 09:27 UTC101
    let _fd = sync.export();
7de49c2aa70batagen2026-10-16 09:27 UTC102
    sync.wait().unwrap();
7de49c2aa70batagen2026-10-16 09:27 UTC103
    assert!(sync.is_reached());
7de49c2aa70batagen2026-10-16 09:27 UTC104
}
b03e3b32603aatagen2026-10-19 07:40 UTC105
b03e3b32603aatagen2026-10-19 07:40 UTC106
#[test]
b03e3b32603aatagen2026-10-19 07:40 UTC107
fn y_inverted_dmabuf_is_sampled_upside_down() {
b03e3b32603aatagen2026-10-19 07:40 UTC108
    let Some(mut r) = renderer() else { return };
b03e3b32603aatagen2026-10-19 07:40 UTC109
    let mut buf = dmabuf(&r);
b03e3b32603aatagen2026-10-19 07:40 UTC110
    {
b03e3b32603aatagen2026-10-19 07:40 UTC111
        let mut target = r.bind(&mut buf).unwrap();
b03e3b32603aatagen2026-10-19 07:40 UTC112
        let mut frame = r
b03e3b32603aatagen2026-10-19 07:40 UTC113
            .render(&mut target, (SIZE, SIZE).into(), Transform::Normal)
b03e3b32603aatagen2026-10-19 07:40 UTC114
            .unwrap();
b03e3b32603aatagen2026-10-19 07:40 UTC115
        let half = SIZE / 2;
b03e3b32603aatagen2026-10-19 07:40 UTC116
        frame
b03e3b32603aatagen2026-10-19 07:40 UTC117
            .clear(
b03e3b32603aatagen2026-10-19 07:40 UTC118
                Color32F::from([1.0, 0.0, 0.0, 1.0]),
b03e3b32603aatagen2026-10-19 07:40 UTC119
                &[Rectangle::from_size((SIZE, SIZE).into())],
b03e3b32603aatagen2026-10-19 07:40 UTC120
            )
b03e3b32603aatagen2026-10-19 07:40 UTC121
            .unwrap();
b03e3b32603aatagen2026-10-19 07:40 UTC122
        frame
b03e3b32603aatagen2026-10-19 07:40 UTC123
            .clear(
b03e3b32603aatagen2026-10-19 07:40 UTC124
                Color32F::from([0.0, 1.0, 0.0, 1.0]),
b03e3b32603aatagen2026-10-19 07:40 UTC125
                &[Rectangle::new((0, half).into(), (SIZE, half).into())],
b03e3b32603aatagen2026-10-19 07:40 UTC126
            )
b03e3b32603aatagen2026-10-19 07:40 UTC127
            .unwrap();
b03e3b32603aatagen2026-10-19 07:40 UTC128
        frame.finish().unwrap().wait().unwrap();
b03e3b32603aatagen2026-10-19 07:40 UTC129
    }
b03e3b32603aatagen2026-10-19 07:40 UTC130
    let mut inverted = Dmabuf::builder_from_buffer(&buf, DmabufFlags::Y_INVERT);
b03e3b32603aatagen2026-10-19 07:40 UTC131
    for ((fd, offset), stride) in buf.handles().zip(buf.offsets()).zip(buf.strides()) {
b03e3b32603aatagen2026-10-19 07:40 UTC132
        inverted.add_plane(fd.try_clone_to_owned().unwrap(), offset, stride);
b03e3b32603aatagen2026-10-19 07:40 UTC133
    }
b03e3b32603aatagen2026-10-19 07:40 UTC134
    let texture = r.import_dmabuf(&inverted.build().unwrap(), None).unwrap();
b03e3b32603aatagen2026-10-19 07:40 UTC135
    let mut out = r
b03e3b32603aatagen2026-10-19 07:40 UTC136
        .create_buffer(Fourcc::Argb8888, (SIZE, SIZE).into())
b03e3b32603aatagen2026-10-19 07:40 UTC137
        .unwrap();
b03e3b32603aatagen2026-10-19 07:40 UTC138
    let mut target = r.bind(&mut out).unwrap();
b03e3b32603aatagen2026-10-19 07:40 UTC139
    {
b03e3b32603aatagen2026-10-19 07:40 UTC140
        let full = Rectangle::from_size((SIZE, SIZE).into());
b03e3b32603aatagen2026-10-19 07:40 UTC141
        let mut frame = r
b03e3b32603aatagen2026-10-19 07:40 UTC142
            .render(&mut target, (SIZE, SIZE).into(), Transform::Normal)
b03e3b32603aatagen2026-10-19 07:40 UTC143
            .unwrap();
b03e3b32603aatagen2026-10-19 07:40 UTC144
        frame
b03e3b32603aatagen2026-10-19 07:40 UTC145
            .render_texture_from_to(
b03e3b32603aatagen2026-10-19 07:40 UTC146
                &texture,
b03e3b32603aatagen2026-10-19 07:40 UTC147
                Rectangle::from_size((SIZE as f64, SIZE as f64).into()),
b03e3b32603aatagen2026-10-19 07:40 UTC148
                full,
b03e3b32603aatagen2026-10-19 07:40 UTC149
                &[full],
b03e3b32603aatagen2026-10-19 07:40 UTC150
                &[],
b03e3b32603aatagen2026-10-19 07:40 UTC151
                Transform::Normal,
b03e3b32603aatagen2026-10-19 07:40 UTC152
                1.0,
b03e3b32603aatagen2026-10-19 07:40 UTC153
            )
b03e3b32603aatagen2026-10-19 07:40 UTC154
            .unwrap();
b03e3b32603aatagen2026-10-19 07:40 UTC155
        frame.finish().unwrap().wait().unwrap();
b03e3b32603aatagen2026-10-19 07:40 UTC156
    }
b03e3b32603aatagen2026-10-19 07:40 UTC157
    let mapping = r
b03e3b32603aatagen2026-10-19 07:40 UTC158
        .copy_framebuffer(
b03e3b32603aatagen2026-10-19 07:40 UTC159
            &target,
b03e3b32603aatagen2026-10-19 07:40 UTC160
            Rectangle::from_size((SIZE, SIZE).into()),
b03e3b32603aatagen2026-10-19 07:40 UTC161
            Fourcc::Abgr8888,
b03e3b32603aatagen2026-10-19 07:40 UTC162
        )
b03e3b32603aatagen2026-10-19 07:40 UTC163
        .unwrap();
b03e3b32603aatagen2026-10-19 07:40 UTC164
    let pixels = r.map_texture(&mapping).unwrap().as_chunks::<4>().0;
b03e3b32603aatagen2026-10-19 07:40 UTC165
    let at = |y: i32| pixels[(y * SIZE + SIZE / 2) as usize];
b03e3b32603aatagen2026-10-19 07:40 UTC166
    assert_eq!(at(1), [0, 255, 0, 255]);
b03e3b32603aatagen2026-10-19 07:40 UTC167
    assert_eq!(at(SIZE - 2), [255, 0, 0, 255]);
b03e3b32603aatagen2026-10-19 07:40 UTC168
}