diff --git a/src/backends/metal/video.rs b/src/backends/metal/video.rs index b33c9b0c..441da79c 100644 --- a/src/backends/metal/video.rs +++ b/src/backends/metal/video.rs @@ -609,7 +609,6 @@ impl MetalConnector { if try_direct_scanout { if let Some(dsd) = self.prepare_direct_scanout(&pass, plane) { output.perform_screencopies( - None, &dsd.tex, !render_hw_cursor, dsd.position.crtc_x, @@ -634,14 +633,7 @@ impl MetalConnector { if let Some(tex) = &buffer.dev_tex { buffer.dev_fb.copy_texture(tex, 0, 0); } - output.perform_screencopies( - Some(&*buffer_fb), - &buffer.render_tex, - !render_hw_cursor, - 0, - 0, - None, - ); + output.perform_screencopies(&buffer.render_tex, !render_hw_cursor, 0, 0, None); buffer.drm.clone() } Some(dsd) => dsd.fb.clone(), diff --git a/src/gfx_api.rs b/src/gfx_api.rs index 26c3ae2f..72b5eeae 100644 --- a/src/gfx_api.rs +++ b/src/gfx_api.rs @@ -150,12 +150,13 @@ pub trait GfxFramebuffer: Debug { fn render(&self, ops: Vec, clear: Option<&Color>); fn copy_to_shm( - &self, + self: Rc, x: i32, y: i32, width: i32, height: i32, - format: &Format, + stride: i32, + format: &'static Format, shm: &[Cell], ) -> Result<(), GfxError>; diff --git a/src/gfx_apis/gl.rs b/src/gfx_apis/gl.rs index 908f12d9..43922354 100644 --- a/src/gfx_apis/gl.rs +++ b/src/gfx_apis/gl.rs @@ -178,8 +178,8 @@ enum RenderError { ExternalUnsupported, #[error("OpenGL context does not support any formats")] NoSupportedFormats, - #[error("Unsupported operation")] - UnsupportedOperation, + #[error("Cannot convert a shm texture into a framebuffer")] + ShmTextureToFb, } #[derive(Default)] diff --git a/src/gfx_apis/gl/renderer/context.rs b/src/gfx_apis/gl/renderer/context.rs index b77cd4c1..b9f78e66 100644 --- a/src/gfx_apis/gl/renderer/context.rs +++ b/src/gfx_apis/gl/renderer/context.rs @@ -6,7 +6,7 @@ use { ResetStatus, }, gfx_apis::gl::{ - egl::{context::EglContext, display::EglDisplay}, + egl::{context::EglContext, display::EglDisplay, image::EglImage}, ext::GL_OES_EGL_IMAGE_EXTERNAL, gl::{ program::GlProgram, render_buffer::GlRenderBuffer, sys::GLint, texture::GlTexture, @@ -190,6 +190,20 @@ impl GlRenderContext { format, })) } + + pub fn image_to_fb( + self: &Rc, + img: &Rc, + ) -> Result, RenderError> { + self.ctx.with_current(|| unsafe { + let rb = GlRenderBuffer::from_image(img, &self.ctx)?; + let fb = rb.create_framebuffer()?; + Ok(Rc::new(Framebuffer { + ctx: self.clone(), + gl: fb, + })) + }) + } } impl GfxContext for GlRenderContext { diff --git a/src/gfx_apis/gl/renderer/framebuffer.rs b/src/gfx_apis/gl/renderer/framebuffer.rs index 3be56f86..8c371137 100644 --- a/src/gfx_apis/gl/renderer/framebuffer.rs +++ b/src/gfx_apis/gl/renderer/framebuffer.rs @@ -106,15 +106,16 @@ impl GfxFramebuffer for Framebuffer { } fn copy_to_shm( - &self, + self: Rc, x: i32, y: i32, width: i32, height: i32, - format: &Format, + _stride: i32, + format: &'static Format, shm: &[Cell], ) -> Result<(), GfxError> { - self.copy_to_shm(x, y, width, height, format, shm); + (*self).copy_to_shm(x, y, width, height, format, shm); Ok(()) } diff --git a/src/gfx_apis/gl/renderer/image.rs b/src/gfx_apis/gl/renderer/image.rs index 50295260..4044206d 100644 --- a/src/gfx_apis/gl/renderer/image.rs +++ b/src/gfx_apis/gl/renderer/image.rs @@ -2,9 +2,8 @@ use { crate::{ gfx_api::{GfxError, GfxFramebuffer, GfxImage, GfxTexture}, gfx_apis::gl::{ - egl::image::EglImage, - gl::{render_buffer::GlRenderBuffer, texture::GlTexture}, - Framebuffer, GlRenderContext, RenderError, Texture, + egl::image::EglImage, gl::texture::GlTexture, Framebuffer, GlRenderContext, + RenderError, Texture, }, }, std::rc::Rc, @@ -34,14 +33,7 @@ impl Image { } fn to_framebuffer(&self) -> Result, RenderError> { - self.ctx.ctx.with_current(|| unsafe { - let rb = GlRenderBuffer::from_image(&self.gl, &self.ctx.ctx)?; - let fb = rb.create_framebuffer()?; - Ok(Rc::new(Framebuffer { - ctx: self.ctx.clone(), - gl: fb, - })) - }) + self.ctx.image_to_fb(&self.gl) } } diff --git a/src/gfx_apis/gl/renderer/texture.rs b/src/gfx_apis/gl/renderer/texture.rs index c2d479d5..efe2b029 100644 --- a/src/gfx_apis/gl/renderer/texture.rs +++ b/src/gfx_apis/gl/renderer/texture.rs @@ -2,7 +2,11 @@ use { crate::{ format::Format, gfx_api::{GfxError, GfxTexture, TextureReservations}, - gfx_apis::gl::{gl::texture::GlTexture, renderer::context::GlRenderContext, RenderError}, + gfx_apis::gl::{ + gl::texture::GlTexture, + renderer::{context::GlRenderContext, framebuffer::Framebuffer}, + RenderError, + }, video::dmabuf::DmaBuf, }, std::{ @@ -34,6 +38,13 @@ impl Texture { pub fn height(&self) -> i32 { self.gl.height } + + pub fn to_framebuffer(&self) -> Result, RenderError> { + match &self.gl.img { + Some(img) => self.ctx.image_to_fb(img), + _ => Err(RenderError::ShmTextureToFb), + } + } } impl GfxTexture for Texture { @@ -51,15 +62,17 @@ impl GfxTexture for Texture { fn read_pixels( self: Rc, - _x: i32, - _y: i32, - _width: i32, - _height: i32, + x: i32, + y: i32, + width: i32, + height: i32, _stride: i32, - _format: &Format, - _shm: &[Cell], + format: &Format, + shm: &[Cell], ) -> Result<(), GfxError> { - Err(RenderError::UnsupportedOperation.into()) + self.to_framebuffer()? + .copy_to_shm(x, y, width, height, format, shm); + Ok(()) } fn dmabuf(&self) -> Option<&DmaBuf> { diff --git a/src/gfx_apis/vulkan.rs b/src/gfx_apis/vulkan.rs index 5dfc8e91..17429782 100644 --- a/src/gfx_apis/vulkan.rs +++ b/src/gfx_apis/vulkan.rs @@ -173,8 +173,6 @@ pub enum VulkanError { height: i32, stride: i32, }, - #[error("Unsupported operation")] - UnsupportedOperation, } impl From for GfxError { diff --git a/src/gfx_apis/vulkan/image.rs b/src/gfx_apis/vulkan/image.rs index 6754133e..6bcdaef2 100644 --- a/src/gfx_apis/vulkan/image.rs +++ b/src/gfx_apis/vulkan/image.rs @@ -533,15 +533,18 @@ impl GfxFramebuffer for VulkanImage { } fn copy_to_shm( - &self, - _x: i32, - _y: i32, - _width: i32, - _height: i32, - _format: &Format, - _shm: &[Cell], + self: Rc, + x: i32, + y: i32, + width: i32, + height: i32, + stride: i32, + format: &'static Format, + shm: &[Cell], ) -> Result<(), GfxError> { - return Err(VulkanError::UnsupportedOperation.into()); + self.renderer + .read_pixels(&self, x, y, width, height, stride, format, shm) + .map_err(|e| e.into()) } fn format(&self) -> &'static Format { diff --git a/src/ifs/wl_output.rs b/src/ifs/wl_output.rs index 9c3d6d52..ef9f5477 100644 --- a/src/ifs/wl_output.rs +++ b/src/ifs/wl_output.rs @@ -2,8 +2,7 @@ use { crate::{ backend, client::{Client, ClientError, ClientId}, - format::XRGB8888, - gfx_api::{GfxFramebuffer, GfxTexture}, + gfx_api::GfxTexture, globals::{Global, GlobalName}, ifs::{ wl_buffer::WlBufferStorage, wl_surface::WlSurface, @@ -208,7 +207,6 @@ impl WlOutputGlobal { pub fn perform_screencopies( &self, - fb: Option<&dyn GfxFramebuffer>, tex: &Rc, render_hardware_cursors: bool, x_off: i32, @@ -234,7 +232,6 @@ impl WlOutputGlobal { capture.send_failed(); continue; } - let rect = capture.rect; if let Some(WlBufferStorage::Shm { mem, stride }) = wl_buffer.storage.borrow_mut().deref() { @@ -249,34 +246,13 @@ impl WlOutputGlobal { mem, ) }); - let mut res = match acc { + let res = match acc { Ok(res) => res, Err(e) => { capture.client.error(e); continue; } }; - if res.is_err() { - if let Some(fb) = fb { - let acc = mem.access(|mem| { - fb.copy_to_shm( - rect.x1(), - rect.y1(), - rect.width(), - rect.height(), - XRGB8888, - mem, - ) - }); - res = match acc { - Ok(res) => res, - Err(e) => { - capture.client.error(e); - continue; - } - }; - } - } if let Err(e) = res { log::warn!("Could not read texture to memory: {}", ErrorFmt(e)); capture.send_failed(); diff --git a/src/state.rs b/src/state.rs index 7a4895ec..279bbc5a 100644 --- a/src/state.rs +++ b/src/state.rs @@ -751,7 +751,7 @@ impl State { output.global.preferred_scale.get(), render_hw_cursor, ); - output.perform_screencopies(Some(&**fb), tex, !render_hw_cursor, 0, 0, None); + output.perform_screencopies(tex, !render_hw_cursor, 0, 0, None); rr.dispatch_frame_requests(); } diff --git a/src/tree/output.rs b/src/tree/output.rs index 3c7e4f99..4d7e7ce5 100644 --- a/src/tree/output.rs +++ b/src/tree/output.rs @@ -4,7 +4,7 @@ use { client::ClientId, cursor::KnownCursor, fixed::Fixed, - gfx_api::{GfxFramebuffer, GfxTexture}, + gfx_api::GfxTexture, ifs::{ jay_output::JayOutput, jay_screencast::JayScreencast, @@ -80,7 +80,6 @@ pub async fn output_render_data(state: Rc) { impl OutputNode { pub fn perform_screencopies( &self, - fb: Option<&dyn GfxFramebuffer>, tex: &Rc, render_hardware_cursor: bool, x_off: i32, @@ -93,7 +92,7 @@ impl OutputNode { } } self.global - .perform_screencopies(fb, tex, render_hardware_cursor, x_off, y_off, size); + .perform_screencopies(tex, render_hardware_cursor, x_off, y_off, size); for sc in self.screencasts.lock().values() { sc.copy_texture(self, tex, render_hardware_cursor, x_off, y_off, size); }