image-copy: Store offscreen buffer for shm capture in session
Avoid allocating a GPU buffer every frame, and avoid re-rendering everything.
This commit is contained in:
parent
e5954de6cd
commit
40c7eb26cd
2 changed files with 48 additions and 24 deletions
|
|
@ -5,8 +5,8 @@ use smithay::{
|
||||||
backend::{
|
backend::{
|
||||||
allocator::{Buffer, Fourcc, format::get_transparent},
|
allocator::{Buffer, Fourcc, format::get_transparent},
|
||||||
renderer::{
|
renderer::{
|
||||||
BufferType, Color32F, ExportMem, ImportAll, ImportMem, Offscreen, buffer_dimensions,
|
BufferType, Color32F, ExportMem, ImportAll, ImportMem, Offscreen, Renderer,
|
||||||
buffer_type,
|
buffer_dimensions, buffer_type,
|
||||||
damage::{Error as DTError, OutputDamageTracker, RenderOutputResult},
|
damage::{Error as DTError, OutputDamageTracker, RenderOutputResult},
|
||||||
element::{
|
element::{
|
||||||
AsRenderElements, RenderElement,
|
AsRenderElements, RenderElement,
|
||||||
|
|
@ -204,37 +204,53 @@ where
|
||||||
Vec<Rectangle<i32, BufferCoords>>,
|
Vec<Rectangle<i32, BufferCoords>>,
|
||||||
) -> Result<RenderOutputResult<'d>, DTError<R::Error>>,
|
) -> Result<RenderOutputResult<'d>, DTError<R::Error>>,
|
||||||
{
|
{
|
||||||
let mut session_damage_tracking = session.lock().unwrap();
|
let mut session_user_data = session.lock().unwrap();
|
||||||
|
|
||||||
let buffer = frame.buffer();
|
let buffer = frame.buffer();
|
||||||
let mut offscreen = matches!(buffer_type(&buffer), Some(BufferType::Shm))
|
|
||||||
.then(|| {
|
|
||||||
let size = buffer_dimensions(&buffer).ok_or(DTError::OutputNoMode(OutputNoMode))?;
|
|
||||||
let format = with_buffer_contents(&buffer, |_, _, data| {
|
|
||||||
shm_format_to_fourcc(data.format)
|
|
||||||
.expect("We should be able to convert all hardcoded shm screencopy formats")
|
|
||||||
})
|
|
||||||
.map_err(|_| DTError::OutputNoMode(OutputNoMode))?;
|
|
||||||
Offscreen::<GlesRenderbuffer>::create_buffer(renderer, format, size)
|
|
||||||
.map_err(DTError::Rendering)
|
|
||||||
})
|
|
||||||
.transpose()?;
|
|
||||||
|
|
||||||
let age = if offscreen.is_some() {
|
let mut age = 1;
|
||||||
// TODO re-use offscreen buffer to damage track screencopy to shm
|
if matches!(buffer_type(&buffer), Some(BufferType::Shm)) {
|
||||||
0
|
let size = buffer_dimensions(&buffer).ok_or(DTError::OutputNoMode(OutputNoMode))?;
|
||||||
|
let format = with_buffer_contents(&buffer, |_, _, data| {
|
||||||
|
shm_format_to_fourcc(data.format)
|
||||||
|
.expect("We should be able to convert all hardcoded shm screencopy formats")
|
||||||
|
})
|
||||||
|
.map_err(|_| DTError::OutputNoMode(OutputNoMode))?;
|
||||||
|
|
||||||
|
// Re-allocate if context id, size, or format are different
|
||||||
|
session_user_data
|
||||||
|
.offscreen
|
||||||
|
.take_if(|(context_id, renderbuffer)| {
|
||||||
|
renderer.glow_renderer().context_id() != *context_id
|
||||||
|
|| renderbuffer.size() != size
|
||||||
|
|| renderbuffer.format() != Some(format)
|
||||||
|
});
|
||||||
|
|
||||||
|
if session_user_data.offscreen.is_none() {
|
||||||
|
let renderbuffer = Offscreen::<GlesRenderbuffer>::create_buffer(renderer, format, size)
|
||||||
|
.map_err(DTError::Rendering)?;
|
||||||
|
session_user_data.offscreen =
|
||||||
|
Some((renderer.glow_renderer().context_id(), renderbuffer));
|
||||||
|
// If we're allocating a new offscreen buffer, we need to re-render everything
|
||||||
|
// (or copy the contexts of the shm buffer)
|
||||||
|
age = 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
1
|
// If for some reason a capture session is used for shm, but then changes to dmabuf capture,
|
||||||
};
|
// remove the offscreen buffer.
|
||||||
|
session_user_data.offscreen = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let SessionUserData { dt, offscreen } = &mut *session_user_data;
|
||||||
let mut fb = offscreen
|
let mut fb = offscreen
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.map(|tex| renderer.bind(tex).map_err(DTError::Rendering))
|
.map(|(_, tex)| renderer.bind(tex).map_err(DTError::Rendering))
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
let res = render_fn(
|
let res = render_fn(
|
||||||
&frame.buffer(),
|
&frame.buffer(),
|
||||||
renderer,
|
renderer,
|
||||||
fb.as_mut(),
|
fb.as_mut(),
|
||||||
&mut session_damage_tracking.dt,
|
dt,
|
||||||
age,
|
age,
|
||||||
frame.damage(),
|
frame.damage(),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,11 @@
|
||||||
use std::{cell::RefCell, sync::Mutex};
|
use std::{cell::RefCell, sync::Mutex};
|
||||||
|
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::renderer::damage::OutputDamageTracker,
|
backend::renderer::{
|
||||||
|
ContextId,
|
||||||
|
damage::OutputDamageTracker,
|
||||||
|
gles::{GlesRenderbuffer, GlesTexture},
|
||||||
|
},
|
||||||
output::Output,
|
output::Output,
|
||||||
wayland::image_copy_capture::{
|
wayland::image_copy_capture::{
|
||||||
CursorSession, CursorSessionRef, Frame, FrameRef, Session, SessionRef,
|
CursorSession, CursorSessionRef, Frame, FrameRef, Session, SessionRef,
|
||||||
|
|
@ -19,11 +23,15 @@ pub type SessionData = Mutex<SessionUserData>;
|
||||||
|
|
||||||
pub struct SessionUserData {
|
pub struct SessionUserData {
|
||||||
pub dt: OutputDamageTracker,
|
pub dt: OutputDamageTracker,
|
||||||
|
pub offscreen: Option<(ContextId<GlesTexture>, GlesRenderbuffer)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SessionUserData {
|
impl SessionUserData {
|
||||||
pub fn new(tracker: OutputDamageTracker) -> SessionUserData {
|
pub fn new(tracker: OutputDamageTracker) -> SessionUserData {
|
||||||
SessionUserData { dt: tracker }
|
SessionUserData {
|
||||||
|
dt: tracker,
|
||||||
|
offscreen: None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue