diff --git a/src/cli/screenshot.rs b/src/cli/screenshot.rs index 1804d653..42379582 100644 --- a/src/cli/screenshot.rs +++ b/src/cli/screenshot.rs @@ -3,7 +3,7 @@ use { cli::{GlobalArgs, ScreenshotArgs, ScreenshotFormat}, format::XRGB8888, tools::tool_client::{with_tool_client, Handle, ToolClient}, - utils::{errorfmt::ErrorFmt, queue::AsyncQueue}, + utils::{errorfmt::ErrorFmt, queue::AsyncQueue, windows::WindowsExt}, video::{ dmabuf::{DmaBuf, DmaBufIds, DmaBufPlane, PlaneVec}, drm::Drm, @@ -107,7 +107,7 @@ pub fn buf_to_bytes(dma_buf_ids: &DmaBufIds, buf: &Dmabuf, format: ScreenshotFor fatal!("Could not import screenshot dmabuf: {}", ErrorFmt(e)); } }; - let bo_map = match bo.map() { + let bo_map = match bo.map_read() { Ok(map) => map, Err(e) => { fatal!("Could not map dmabuf: {}", ErrorFmt(e)); @@ -115,14 +115,18 @@ pub fn buf_to_bytes(dma_buf_ids: &DmaBufIds, buf: &Dmabuf, format: ScreenshotFor }; let data = unsafe { bo_map.data() }; if format == ScreenshotFormat::Qoi { - return xrgb8888_encode_qoi(data, buf.width, buf.height, buf.stride); + return xrgb8888_encode_qoi(data, buf.width, buf.height, bo_map.stride() as u32); } let mut out = vec![]; { - let mut image_data = Vec::with_capacity(data.len()); - for i in 0..data.len() / 4 { - image_data.extend_from_slice(&[data[4 * i + 2], data[4 * i + 1], data[4 * i + 0], 255]) + let mut image_data = Vec::with_capacity((buf.width * buf.height * 4) as usize); + let lines = data[..(buf.height as usize * bo_map.stride() as usize)] + .chunks_exact(bo_map.stride() as usize); + for line in lines { + for pixel in line[..(buf.width as usize * 4)].array_chunks_ext::<4>() { + image_data.extend_from_slice(&[pixel[2], pixel[1], pixel[0], 255]) + } } let mut encoder = Encoder::new(&mut out, buf.width, buf.height); encoder.set_color(ColorType::Rgba); diff --git a/src/video/gbm.rs b/src/video/gbm.rs index bc7c04f0..8a19363d 100644 --- a/src/video/gbm.rs +++ b/src/video/gbm.rs @@ -148,12 +148,22 @@ pub struct GbmBoMap { bo: Rc, data: *mut [u8], opaque: *mut u8, + stride: i32, } impl GbmBoMap { pub unsafe fn data(&self) -> &[u8] { &*self.data } + + #[allow(dead_code)] + pub fn data_ptr(&self) -> *mut u8 { + self.data as _ + } + + pub fn stride(&self) -> i32 { + self.stride + } } unsafe fn export_bo(dmabuf_ids: &DmaBufIds, bo: *mut Bo) -> Result { @@ -293,7 +303,16 @@ impl GbmBo { &self.dmabuf } - pub fn map(self: &Rc) -> Result { + pub fn map_read(self: &Rc) -> Result { + self.map2(GBM_BO_TRANSFER_READ) + } + + #[allow(dead_code)] + pub fn map_write(self: &Rc) -> Result { + self.map2(GBM_BO_TRANSFER_READ_WRITE) + } + + fn map2(self: &Rc, flags: u32) -> Result { let mut stride = 0; let mut map_data = ptr::null_mut(); unsafe { @@ -303,7 +322,7 @@ impl GbmBo { 0, self.dmabuf.width as _, self.dmabuf.height as _, - GBM_BO_TRANSFER_READ, + flags, &mut stride, &mut map_data, ); @@ -315,6 +334,7 @@ impl GbmBo { bo: self.clone(), data: map, opaque: map_data, + stride: stride as i32, }) } }