From a9ce9a466499288216800a2c8cba4e2392b44474 Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Sun, 13 May 2018 14:35:27 +0200 Subject: [PATCH] anvil: fix shm buffer loading --- anvil/src/glium_drawer.rs | 46 +++++++++++++++---------------- anvil/src/main.rs | 7 +++-- anvil/src/shell.rs | 15 +++------- anvil/src/shm_load.rs | 58 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 89 insertions(+), 37 deletions(-) create mode 100644 anvil/src/shm_load.rs diff --git a/anvil/src/glium_drawer.rs b/anvil/src/glium_drawer.rs index 30c5e3c..10790b4 100644 --- a/anvil/src/glium_drawer.rs +++ b/anvil/src/glium_drawer.rs @@ -70,32 +70,32 @@ impl> + EGLGraphicsBackend + 'static> From fo // compiling shaders and linking them together let program = program!(&display, - 100 => { - vertex: " - #version 100 - uniform lowp mat4 matrix; - attribute lowp vec2 position; - attribute lowp vec2 tex_coords; - varying lowp vec2 v_tex_coords; - void main() { - gl_Position = matrix * vec4(position, 0.0, 1.0); - v_tex_coords = tex_coords; - } - ", + 100 => { + vertex: " + #version 100 + uniform lowp mat4 matrix; + attribute lowp vec2 position; + attribute lowp vec2 tex_coords; + varying lowp vec2 v_tex_coords; + void main() { + gl_Position = matrix * vec4(position, 0.0, 1.0); + v_tex_coords = tex_coords; + } + ", - fragment: " - #version 100 - uniform lowp sampler2D tex; - varying lowp vec2 v_tex_coords; - void main() { - lowp vec4 color = texture2D(tex, v_tex_coords); - gl_FragColor.r = color.z; + fragment: " + #version 100 + uniform lowp sampler2D tex; + varying lowp vec2 v_tex_coords; + void main() { + lowp vec4 color = texture2D(tex, v_tex_coords); + gl_FragColor.r = color.x; gl_FragColor.g = color.y; - gl_FragColor.b = color.x; + gl_FragColor.b = color.z; gl_FragColor.a = color.w; - } - ", - }, + } + ", + }, ).unwrap(); GliumDrawer { diff --git a/anvil/src/main.rs b/anvil/src/main.rs index e108950..86676ea 100644 --- a/anvil/src/main.rs +++ b/anvil/src/main.rs @@ -13,15 +13,16 @@ use slog::Drain; use smithay::wayland_server::Display; mod glium_drawer; +mod input_handler; +#[cfg(feature = "tty_launch")] +mod raw_drm; mod shell; +mod shm_load; #[cfg(feature = "udev")] mod udev; mod window_map; #[cfg(feature = "winit")] mod winit; -mod input_handler; -#[cfg(feature = "tty_launch")] -mod raw_drm; static POSSIBLE_BACKENDS: &'static [&'static str] = &[ #[cfg(feature = "winit")] diff --git a/anvil/src/shell.rs b/anvil/src/shell.rs index ad5940e..be4f66b 100644 --- a/anvil/src/shell.rs +++ b/anvil/src/shell.rs @@ -39,11 +39,12 @@ pub fn init_shell( ) { // Create the compositor let c_egl_display = egl_display.clone(); + let log2 = log.clone(); let (compositor_token, _, _) = compositor_init( display, looptoken.clone(), move |request, (surface, ctoken)| match request { - SurfaceEvent::Commit => surface_commit(&surface, ctoken, &*c_egl_display), + SurfaceEvent::Commit => surface_commit(&surface, ctoken, &*c_egl_display, &log2), SurfaceEvent::Frame { callback } => callback .implement(|e, _| match e {}, None::) .send(wl_callback::Event::Done { callback_data: 0 }), @@ -140,6 +141,7 @@ fn surface_commit( surface: &Resource, token: CompositorToken, display: &RefCell>, + log: &::slog::Logger, ) { // we retrieve the contents of the associated buffer and copy it token.with_surface_data(surface, |attributes| { @@ -167,17 +169,8 @@ fn surface_commit( } Err(BufferAccessError::NotManaged(buffer)) => { shm_buffer_contents(&buffer, |slice, data| { - let offset = data.offset as usize; - let stride = data.stride as usize; - let width = data.width as usize; - let height = data.height as usize; - let mut new_vec = Vec::with_capacity(width * height * 4); - for i in 0..height { - new_vec - .extend(&slice[(offset + i * stride)..(offset + i * stride + width * 4)]); - } attributes.user_data.texture = None; - attributes.user_data.buffer = Some(Buffer::Shm { data: new_vec, size: (data.width as u32, data.height as u32) }); + attributes.user_data.buffer = Some(::shm_load::load_shm_buffer(data, slice, log)); }).expect("Got EGL buffer with no set EGLDisplay. You need to unbind your EGLContexts before dropping them!"); buffer.send(wl_buffer::Event::Release); } diff --git a/anvil/src/shm_load.rs b/anvil/src/shm_load.rs new file mode 100644 index 0000000..01a9c9f --- /dev/null +++ b/anvil/src/shm_load.rs @@ -0,0 +1,58 @@ +use shell::Buffer; +use smithay::wayland::shm::BufferData; +use smithay::wayland_server::protocol::wl_shm::Format; + +pub fn load_shm_buffer(data: BufferData, pool: &[u8], log: &::slog::Logger) -> Buffer { + // ensure consistency, the SHM handler of smithay should ensure this + debug_assert!(((data.offset + data.stride * data.height) as usize) <= pool.len()); + + let mut out = Vec::with_capacity((data.width * data.height * 4) as usize); + + let offset = data.offset as usize; + let width = data.width as usize; + let height = data.height as usize; + let stride = data.stride as usize; + + match data.format { + Format::Argb8888 => { + // TODO: this is so slooooow + for j in 0..height { + for i in 0..width { + // value must be read as native endianness + let val: u32 = + unsafe { *(&pool[offset + j * stride + i * 4] as *const u8 as *const u32) }; + out.push(((val & 0x00FF0000) >> 16) as u8); //r + out.push(((val & 0x0000FF00) >> 8) as u8); //g + out.push(((val & 0x000000FF) >> 0) as u8); //b + out.push(((val & 0xFF000000) >> 24) as u8); //a + } + } + } + Format::Xrgb8888 => { + // TODO: this is so slooooow + for j in 0..height { + for i in 0..width { + // value must be read as native endianness + let val: u32 = + unsafe { *(&pool[offset + j * stride + i * 4] as *const u8 as *const u32) }; + out.push(((val & 0x00FF0000) >> 16) as u8); //r + out.push(((val & 0x0000FF00) >> 8) as u8); //g + out.push(((val & 0x000000FF) >> 0) as u8); //b + out.push(255); // a + } + } + } + _ => { + error!(log, "Unsupported buffer format"; "format" => format!("{:?}", data.format)); + // fill in with black + for _ in 0..(data.height * data.width) { + out.extend(&[0, 0, 0, 255]) + } + } + } + + Buffer::Shm { + data: out, + size: (data.width as u32, data.height as u32), + } +}