Use double-buffering for screencopy

Currently this is unnecesssary, but it's needed if we use subsurfaces
(or import) instead of immedaitely converting to an image.
This commit is contained in:
Ian Douglas Scott 2024-01-25 15:58:34 -08:00
parent 6262329635
commit 89910b8e75
2 changed files with 24 additions and 21 deletions

View file

@ -8,10 +8,7 @@ use cctk::{
};
use cosmic::cctk;
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc, Mutex,
};
use std::sync::{Arc, Mutex};
use super::{AppData, ScreencopySession, SessionData};

View file

@ -9,12 +9,15 @@ use cosmic::cctk::{
},
wayland_client::{Connection, QueueHandle, WEnum},
};
use std::sync::{Arc, Weak};
use std::{
mem,
sync::{Arc, Weak},
};
use super::{AppData, Buffer, Capture, CaptureImage, CaptureSource, Event};
pub struct ScreencopySession {
buffer: Option<Buffer>,
buffers: Option<(Buffer, Buffer)>,
session: zcosmic_screencopy_session_v1::ZcosmicScreencopySessionV1,
first_frame: bool,
}
@ -47,22 +50,20 @@ impl ScreencopySession {
};
Self {
buffer: None,
buffers: None,
session,
first_frame: true,
}
}
fn attach_buffer_and_commit(&mut self, capture: &Capture, conn: &Connection) {
let Some(buffer) = self.buffer.as_ref() else {
let Some((front, back)) = self.buffers.as_mut() else {
return;
};
let node = buffer
.node()
.and_then(|x| x.to_str().map(|x| x.to_string()));
let node = front.node().and_then(|x| x.to_str().map(|x| x.to_string()));
self.session.attach_buffer(&buffer.buffer, node, 0); // XXX age?
self.session.attach_buffer(&back.buffer, node, 0); // XXX age?
if self.first_frame {
self.session
.commit(zcosmic_screencopy_session_v1::Options::empty());
@ -115,12 +116,13 @@ impl ScreencopyHandler for AppData {
};
// Create new buffer if none, or different format
if !session
.buffer
.as_ref()
.map_or(false, |x| buffer_infos.contains(&x.buffer_info))
{
session.buffer = Some(self.create_buffer(buffer_infos));
if !session.buffers.as_ref().map_or(false, |(front, _)| {
buffer_infos.contains(&front.buffer_info)
}) {
session.buffers = Some((
self.create_buffer(buffer_infos),
self.create_buffer(buffer_infos),
));
}
session.attach_buffer_and_commit(&capture, conn);
@ -140,11 +142,15 @@ impl ScreencopyHandler for AppData {
return;
};
if session.buffer.is_none() {
eprintln!("Error: No capture buffer?");
if session.buffers.is_none() {
eprintln!("Error: No capture buffers?");
return;
}
let img = unsafe { session.buffer.as_mut().unwrap().to_image() };
let (front, back) = session.buffers.as_mut().unwrap();
mem::swap(front, back);
let img = unsafe { front.to_image() };
let image = CaptureImage { img };
match &capture.source {
CaptureSource::Toplevel(toplevel) => {