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 cosmic::cctk;
use std::sync::{ use std::sync::{Arc, Mutex};
atomic::{AtomicBool, Ordering},
Arc, Mutex,
};
use super::{AppData, ScreencopySession, SessionData}; use super::{AppData, ScreencopySession, SessionData};

View file

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