1
0
Fork 0
forked from wry/wry

render: don't require framebuffer to perform shm screencopies

This commit is contained in:
Julian Orth 2024-02-28 13:41:08 +01:00
parent 69d63b7e83
commit 9de63bddf3
12 changed files with 65 additions and 76 deletions

View file

@ -609,7 +609,6 @@ impl MetalConnector {
if try_direct_scanout { if try_direct_scanout {
if let Some(dsd) = self.prepare_direct_scanout(&pass, plane) { if let Some(dsd) = self.prepare_direct_scanout(&pass, plane) {
output.perform_screencopies( output.perform_screencopies(
None,
&dsd.tex, &dsd.tex,
!render_hw_cursor, !render_hw_cursor,
dsd.position.crtc_x, dsd.position.crtc_x,
@ -634,14 +633,7 @@ impl MetalConnector {
if let Some(tex) = &buffer.dev_tex { if let Some(tex) = &buffer.dev_tex {
buffer.dev_fb.copy_texture(tex, 0, 0); buffer.dev_fb.copy_texture(tex, 0, 0);
} }
output.perform_screencopies( output.perform_screencopies(&buffer.render_tex, !render_hw_cursor, 0, 0, None);
Some(&*buffer_fb),
&buffer.render_tex,
!render_hw_cursor,
0,
0,
None,
);
buffer.drm.clone() buffer.drm.clone()
} }
Some(dsd) => dsd.fb.clone(), Some(dsd) => dsd.fb.clone(),

View file

@ -150,12 +150,13 @@ pub trait GfxFramebuffer: Debug {
fn render(&self, ops: Vec<GfxApiOpt>, clear: Option<&Color>); fn render(&self, ops: Vec<GfxApiOpt>, clear: Option<&Color>);
fn copy_to_shm( fn copy_to_shm(
&self, self: Rc<Self>,
x: i32, x: i32,
y: i32, y: i32,
width: i32, width: i32,
height: i32, height: i32,
format: &Format, stride: i32,
format: &'static Format,
shm: &[Cell<u8>], shm: &[Cell<u8>],
) -> Result<(), GfxError>; ) -> Result<(), GfxError>;

View file

@ -178,8 +178,8 @@ enum RenderError {
ExternalUnsupported, ExternalUnsupported,
#[error("OpenGL context does not support any formats")] #[error("OpenGL context does not support any formats")]
NoSupportedFormats, NoSupportedFormats,
#[error("Unsupported operation")] #[error("Cannot convert a shm texture into a framebuffer")]
UnsupportedOperation, ShmTextureToFb,
} }
#[derive(Default)] #[derive(Default)]

View file

@ -6,7 +6,7 @@ use {
ResetStatus, ResetStatus,
}, },
gfx_apis::gl::{ gfx_apis::gl::{
egl::{context::EglContext, display::EglDisplay}, egl::{context::EglContext, display::EglDisplay, image::EglImage},
ext::GL_OES_EGL_IMAGE_EXTERNAL, ext::GL_OES_EGL_IMAGE_EXTERNAL,
gl::{ gl::{
program::GlProgram, render_buffer::GlRenderBuffer, sys::GLint, texture::GlTexture, program::GlProgram, render_buffer::GlRenderBuffer, sys::GLint, texture::GlTexture,
@ -190,6 +190,20 @@ impl GlRenderContext {
format, format,
})) }))
} }
pub fn image_to_fb(
self: &Rc<Self>,
img: &Rc<EglImage>,
) -> Result<Rc<Framebuffer>, 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 { impl GfxContext for GlRenderContext {

View file

@ -106,15 +106,16 @@ impl GfxFramebuffer for Framebuffer {
} }
fn copy_to_shm( fn copy_to_shm(
&self, self: Rc<Self>,
x: i32, x: i32,
y: i32, y: i32,
width: i32, width: i32,
height: i32, height: i32,
format: &Format, _stride: i32,
format: &'static Format,
shm: &[Cell<u8>], shm: &[Cell<u8>],
) -> Result<(), GfxError> { ) -> Result<(), GfxError> {
self.copy_to_shm(x, y, width, height, format, shm); (*self).copy_to_shm(x, y, width, height, format, shm);
Ok(()) Ok(())
} }

View file

@ -2,9 +2,8 @@ use {
crate::{ crate::{
gfx_api::{GfxError, GfxFramebuffer, GfxImage, GfxTexture}, gfx_api::{GfxError, GfxFramebuffer, GfxImage, GfxTexture},
gfx_apis::gl::{ gfx_apis::gl::{
egl::image::EglImage, egl::image::EglImage, gl::texture::GlTexture, Framebuffer, GlRenderContext,
gl::{render_buffer::GlRenderBuffer, texture::GlTexture}, RenderError, Texture,
Framebuffer, GlRenderContext, RenderError, Texture,
}, },
}, },
std::rc::Rc, std::rc::Rc,
@ -34,14 +33,7 @@ impl Image {
} }
fn to_framebuffer(&self) -> Result<Rc<Framebuffer>, RenderError> { fn to_framebuffer(&self) -> Result<Rc<Framebuffer>, RenderError> {
self.ctx.ctx.with_current(|| unsafe { self.ctx.image_to_fb(&self.gl)
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,
}))
})
} }
} }

View file

@ -2,7 +2,11 @@ use {
crate::{ crate::{
format::Format, format::Format,
gfx_api::{GfxError, GfxTexture, TextureReservations}, 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, video::dmabuf::DmaBuf,
}, },
std::{ std::{
@ -34,6 +38,13 @@ impl Texture {
pub fn height(&self) -> i32 { pub fn height(&self) -> i32 {
self.gl.height self.gl.height
} }
pub fn to_framebuffer(&self) -> Result<Rc<Framebuffer>, RenderError> {
match &self.gl.img {
Some(img) => self.ctx.image_to_fb(img),
_ => Err(RenderError::ShmTextureToFb),
}
}
} }
impl GfxTexture for Texture { impl GfxTexture for Texture {
@ -51,15 +62,17 @@ impl GfxTexture for Texture {
fn read_pixels( fn read_pixels(
self: Rc<Self>, self: Rc<Self>,
_x: i32, x: i32,
_y: i32, y: i32,
_width: i32, width: i32,
_height: i32, height: i32,
_stride: i32, _stride: i32,
_format: &Format, format: &Format,
_shm: &[Cell<u8>], shm: &[Cell<u8>],
) -> Result<(), GfxError> { ) -> Result<(), GfxError> {
Err(RenderError::UnsupportedOperation.into()) self.to_framebuffer()?
.copy_to_shm(x, y, width, height, format, shm);
Ok(())
} }
fn dmabuf(&self) -> Option<&DmaBuf> { fn dmabuf(&self) -> Option<&DmaBuf> {

View file

@ -173,8 +173,6 @@ pub enum VulkanError {
height: i32, height: i32,
stride: i32, stride: i32,
}, },
#[error("Unsupported operation")]
UnsupportedOperation,
} }
impl From<VulkanError> for GfxError { impl From<VulkanError> for GfxError {

View file

@ -533,15 +533,18 @@ impl GfxFramebuffer for VulkanImage {
} }
fn copy_to_shm( fn copy_to_shm(
&self, self: Rc<Self>,
_x: i32, x: i32,
_y: i32, y: i32,
_width: i32, width: i32,
_height: i32, height: i32,
_format: &Format, stride: i32,
_shm: &[Cell<u8>], format: &'static Format,
shm: &[Cell<u8>],
) -> Result<(), GfxError> { ) -> 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 { fn format(&self) -> &'static Format {

View file

@ -2,8 +2,7 @@ use {
crate::{ crate::{
backend, backend,
client::{Client, ClientError, ClientId}, client::{Client, ClientError, ClientId},
format::XRGB8888, gfx_api::GfxTexture,
gfx_api::{GfxFramebuffer, GfxTexture},
globals::{Global, GlobalName}, globals::{Global, GlobalName},
ifs::{ ifs::{
wl_buffer::WlBufferStorage, wl_surface::WlSurface, wl_buffer::WlBufferStorage, wl_surface::WlSurface,
@ -208,7 +207,6 @@ impl WlOutputGlobal {
pub fn perform_screencopies( pub fn perform_screencopies(
&self, &self,
fb: Option<&dyn GfxFramebuffer>,
tex: &Rc<dyn GfxTexture>, tex: &Rc<dyn GfxTexture>,
render_hardware_cursors: bool, render_hardware_cursors: bool,
x_off: i32, x_off: i32,
@ -234,7 +232,6 @@ impl WlOutputGlobal {
capture.send_failed(); capture.send_failed();
continue; continue;
} }
let rect = capture.rect;
if let Some(WlBufferStorage::Shm { mem, stride }) = if let Some(WlBufferStorage::Shm { mem, stride }) =
wl_buffer.storage.borrow_mut().deref() wl_buffer.storage.borrow_mut().deref()
{ {
@ -249,34 +246,13 @@ impl WlOutputGlobal {
mem, mem,
) )
}); });
let mut res = match acc { let res = match acc {
Ok(res) => res, Ok(res) => res,
Err(e) => { Err(e) => {
capture.client.error(e); capture.client.error(e);
continue; 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 { if let Err(e) = res {
log::warn!("Could not read texture to memory: {}", ErrorFmt(e)); log::warn!("Could not read texture to memory: {}", ErrorFmt(e));
capture.send_failed(); capture.send_failed();

View file

@ -751,7 +751,7 @@ impl State {
output.global.preferred_scale.get(), output.global.preferred_scale.get(),
render_hw_cursor, 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(); rr.dispatch_frame_requests();
} }

View file

@ -4,7 +4,7 @@ use {
client::ClientId, client::ClientId,
cursor::KnownCursor, cursor::KnownCursor,
fixed::Fixed, fixed::Fixed,
gfx_api::{GfxFramebuffer, GfxTexture}, gfx_api::GfxTexture,
ifs::{ ifs::{
jay_output::JayOutput, jay_output::JayOutput,
jay_screencast::JayScreencast, jay_screencast::JayScreencast,
@ -80,7 +80,6 @@ pub async fn output_render_data(state: Rc<State>) {
impl OutputNode { impl OutputNode {
pub fn perform_screencopies( pub fn perform_screencopies(
&self, &self,
fb: Option<&dyn GfxFramebuffer>,
tex: &Rc<dyn GfxTexture>, tex: &Rc<dyn GfxTexture>,
render_hardware_cursor: bool, render_hardware_cursor: bool,
x_off: i32, x_off: i32,
@ -93,7 +92,7 @@ impl OutputNode {
} }
} }
self.global 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() { for sc in self.screencasts.lock().values() {
sc.copy_texture(self, tex, render_hardware_cursor, x_off, y_off, size); sc.copy_texture(self, tex, render_hardware_cursor, x_off, y_off, size);
} }