196 lines
6.5 KiB
Rust
196 lines
6.5 KiB
Rust
use {
|
|
super::OutputNode,
|
|
crate::{
|
|
cmm::cmm_description::ColorDescription,
|
|
gfx_api::{AcquireSync, BufferResv, GfxTexture, ReleaseSync},
|
|
ifs::{jay_screencast::JayScreencast, wl_buffer::WlBufferStorage},
|
|
utils::{errorfmt::ErrorFmt, hash_map_ext::HashMapExt},
|
|
},
|
|
std::{ops::Deref, rc::Rc},
|
|
};
|
|
|
|
impl OutputNode {
|
|
pub fn captures_changed(&self) {
|
|
for ws in self.workspaces.iter() {
|
|
ws.update_has_captures();
|
|
}
|
|
}
|
|
|
|
pub fn screencast_changed(&self) {
|
|
self.captures_changed();
|
|
}
|
|
|
|
pub fn add_screencast(&self, sc: &Rc<JayScreencast>) {
|
|
self.screencasts.set((sc.client.id, sc.id), sc.clone());
|
|
self.captures_changed();
|
|
}
|
|
|
|
pub fn remove_screencast(&self, sc: &JayScreencast) {
|
|
self.screencasts.remove(&(sc.client.id, sc.id));
|
|
self.captures_changed();
|
|
}
|
|
|
|
pub fn perform_screencopies(
|
|
&self,
|
|
tex: &Rc<dyn GfxTexture>,
|
|
cd: &Rc<ColorDescription>,
|
|
resv: Option<&Rc<dyn BufferResv>>,
|
|
acquire_sync: &AcquireSync,
|
|
release_sync: ReleaseSync,
|
|
render_hardware_cursor: bool,
|
|
x_off: i32,
|
|
y_off: i32,
|
|
size: Option<(i32, i32)>,
|
|
) {
|
|
if let Some(workspace) = self.workspace.get() {
|
|
if !workspace.may_capture.get() {
|
|
return;
|
|
}
|
|
}
|
|
self.perform_wlr_screencopies(
|
|
tex,
|
|
cd,
|
|
resv,
|
|
acquire_sync,
|
|
release_sync,
|
|
render_hardware_cursor,
|
|
x_off,
|
|
y_off,
|
|
size,
|
|
);
|
|
for sc in self.screencasts.lock().values() {
|
|
sc.copy_texture(
|
|
self,
|
|
tex,
|
|
cd,
|
|
resv,
|
|
acquire_sync,
|
|
release_sync,
|
|
render_hardware_cursor,
|
|
x_off,
|
|
y_off,
|
|
size,
|
|
);
|
|
}
|
|
for sc in self.ext_copy_sessions.lock().values() {
|
|
sc.copy_texture(
|
|
self,
|
|
tex,
|
|
cd,
|
|
resv,
|
|
acquire_sync,
|
|
release_sync,
|
|
render_hardware_cursor,
|
|
x_off,
|
|
y_off,
|
|
size,
|
|
);
|
|
}
|
|
}
|
|
|
|
pub fn perform_wlr_screencopies(
|
|
&self,
|
|
tex: &Rc<dyn GfxTexture>,
|
|
cd: &Rc<ColorDescription>,
|
|
resv: Option<&Rc<dyn BufferResv>>,
|
|
acquire_sync: &AcquireSync,
|
|
release_sync: ReleaseSync,
|
|
render_hardware_cursors: bool,
|
|
x_off: i32,
|
|
y_off: i32,
|
|
size: Option<(i32, i32)>,
|
|
) {
|
|
if self.screencopies.is_empty() {
|
|
return;
|
|
}
|
|
let now = self.state.now();
|
|
for capture in self.screencopies.lock().drain_values() {
|
|
let wl_buffer = match capture.buffer.take() {
|
|
Some(b) => b,
|
|
_ => {
|
|
log::warn!("Capture frame is pending but has no buffer attached");
|
|
capture.send_failed();
|
|
continue;
|
|
}
|
|
};
|
|
if wl_buffer.destroyed() {
|
|
capture.send_failed();
|
|
continue;
|
|
}
|
|
let mut ready = true;
|
|
if let Some(storage) = wl_buffer.storage.borrow_mut().deref() {
|
|
match storage {
|
|
WlBufferStorage::Shm { mem, stride, .. } => {
|
|
let res = self.state.perform_shm_screencopy(
|
|
tex,
|
|
cd,
|
|
acquire_sync,
|
|
self.global.pos.get(),
|
|
x_off,
|
|
y_off,
|
|
size,
|
|
&capture,
|
|
mem,
|
|
*stride,
|
|
wl_buffer.format,
|
|
self.global.persistent.transform.get(),
|
|
self.global.persistent.scale.get(),
|
|
);
|
|
match res {
|
|
Ok(p) => {
|
|
ready = p.is_none();
|
|
capture.pending.set(p);
|
|
}
|
|
Err(e) => {
|
|
log::warn!("Could not perform shm screencopy: {}", ErrorFmt(e));
|
|
capture.send_failed();
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
WlBufferStorage::Dmabuf { fb, .. } => {
|
|
let fb = match fb {
|
|
Some(fb) => fb,
|
|
_ => {
|
|
log::warn!("Capture buffer has no framebuffer");
|
|
capture.send_failed();
|
|
continue;
|
|
}
|
|
};
|
|
let res = self.state.perform_screencopy(
|
|
tex,
|
|
resv,
|
|
acquire_sync,
|
|
release_sync,
|
|
cd,
|
|
&fb,
|
|
AcquireSync::Implicit,
|
|
ReleaseSync::Implicit,
|
|
self.global.persistent.transform.get(),
|
|
self.state.color_manager.srgb_gamma22(),
|
|
self.global.pos.get(),
|
|
render_hardware_cursors,
|
|
x_off - capture.rect.x1(),
|
|
y_off - capture.rect.y1(),
|
|
size,
|
|
self.global.persistent.transform.get(),
|
|
self.global.persistent.scale.get(),
|
|
);
|
|
if let Err(e) = res {
|
|
log::warn!("Could not perform screencopy: {}", ErrorFmt(e));
|
|
capture.send_failed();
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if capture.with_damage.get() {
|
|
capture.send_damage();
|
|
}
|
|
if ready {
|
|
capture.send_ready(now.0.tv_sec as _, now.0.tv_nsec as _);
|
|
}
|
|
}
|
|
self.captures_changed();
|
|
}
|
|
}
|