Commit b03e3b32603a
tarball4 files changed+77-3
@@ -271,6 +271,7 @@ pub(crate) fn import(
271271
size.1,272272
usage,273273
true,274
+ dmabuf.y_inverted(),274275
)275276
}276277
@@ -179,7 +179,12 @@ impl<'frame, 'buffer> VulkanFrame<'frame, 'buffer> {
179179
if scissors.is_empty() {180180
return Ok(());181181
}182
- let uvs = texture_uvs(src, dst.size, texture.size(), src_transform);182
+ let mut uvs = texture_uvs(src, dst.size, texture.size(), src_transform);183
+ if texture.0.y_inverted {184
+ for uv in &mut uvs {185
+ uv[1] = 1.0 - uv[1];186
+ }187
+ }183188
let (fb, uv) = to_framebuffer(dst, uvs, self.area, self.transform);184189
let (clip, radii, ring) = self.clip_push();185190
let push = Push {@@ -26,6 +26,8 @@ pub(crate) struct ImageInner {
2626
pub width: u32,2727
pub height: u32,2828
pub usage: vk::ImageUsageFlags,29
+ /// The rows are stored bottom to top, as a dmabuf flagged `Y_INVERT`.30
+ pub y_inverted: bool,2931
pub layout: Mutex<vk::ImageLayout>,3032
/// Shared with other devices or processes through a dmabuf. Every use3133
/// acquires the image from the foreign queue family and releases it after.@@ -118,7 +120,7 @@ impl ImageInner {
118120
Memory::Imported(m) => (*m, 0),119121
};120122
Self::finish(121
- shared, image, memory, mem, offset, fourcc, width, height, usage, false,123
+ shared, image, memory, mem, offset, fourcc, width, height, usage, false, false,122124
)123125
}124126
@@ -136,6 +138,7 @@ impl ImageInner {
136138
height: u32,137139
usage: vk::ImageUsageFlags,138140
external: bool,141
+ y_inverted: bool,139142
) -> Result<Arc<Self>, Error> {140143
let fmt = vk_format(fourcc).ok_or(Error::UnsupportedFormat(fourcc))?;141144
let d = &shared.device.device;@@ -149,6 +152,7 @@ impl ImageInner {
149152
width,150153
height,151154
usage,155
+ y_inverted,152156
layout: Mutex::new(if external {153157
vk::ImageLayout::GENERAL154158
} else {@@ -2,7 +2,7 @@
22
//! without dmabuf support, such as lavapipe inside the nix sandbox.33
44
use monolith_render_vk::VulkanRenderer;5
-use smithay::backend::allocator::dmabuf::Dmabuf;5
+use smithay::backend::allocator::dmabuf::{Dmabuf, DmabufFlags};66
use smithay::backend::allocator::{Allocator, Fourcc, Modifier};77
use smithay::backend::renderer::{88
Bind, Color32F, ExportMem, Frame, ImportDma, Offscreen, Renderer,@@ -102,3 +102,67 @@ fn frame_fences_export_as_sync_files() {
102102
sync.wait().unwrap();103103
assert!(sync.is_reached());104104
}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 = r113
+ .render(&mut target, (SIZE, SIZE).into(), Transform::Normal)114
+ .unwrap();115
+ let half = SIZE / 2;116
+ frame117
+ .clear(118
+ Color32F::from([1.0, 0.0, 0.0, 1.0]),119
+ &[Rectangle::from_size((SIZE, SIZE).into())],120
+ )121
+ .unwrap();122
+ frame123
+ .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 = r136
+ .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 = r142
+ .render(&mut target, (SIZE, SIZE).into(), Transform::Normal)143
+ .unwrap();144
+ frame145
+ .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 = r158
+ .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
+}