screencopy: Pass the node we're using to attach_buffer

Seems to make sure the compositor renders workspace with that GPU, so it
actually captures successfully.
This commit is contained in:
Ian Douglas Scott 2023-11-09 13:45:28 -08:00
parent a5f2be7e88
commit 39401bf3c3
4 changed files with 42 additions and 11 deletions

View file

@ -8,14 +8,23 @@ use cctk::{
}, },
}; };
use cosmic::iced::widget::image; use cosmic::iced::widget::image;
use std::os::fd::{AsFd, OwnedFd}; use std::{
os::fd::{AsFd, OwnedFd},
path::{Path, PathBuf},
};
use wayland_protocols::wp::linux_dmabuf::zv1::client::zwp_linux_buffer_params_v1; use wayland_protocols::wp::linux_dmabuf::zv1::client::zwp_linux_buffer_params_v1;
use super::AppData; use super::AppData;
enum BufferBacking { enum BufferBacking {
Shm { pool: RawPool }, Shm {
Dmabuf { fd: OwnedFd, stride: u32 }, pool: RawPool,
},
Dmabuf {
fd: OwnedFd,
node: PathBuf,
stride: u32,
},
} }
pub struct Buffer { pub struct Buffer {
@ -53,7 +62,7 @@ impl AppData {
needs_linear: bool, needs_linear: bool,
) -> Option<(BufferBacking, wl_buffer::WlBuffer)> { ) -> Option<(BufferBacking, wl_buffer::WlBuffer)> {
// TODO Handle errors in some way // TODO Handle errors in some way
let gbm = self.gbm.as_ref()?; let (node, gbm) = self.gbm.as_ref()?;
let feedback = self.dmabuf_feedback.as_ref()?; let feedback = self.dmabuf_feedback.as_ref()?;
let formats = feedback.format_table(); let formats = feedback.format_table();
let format_info = feedback let format_info = feedback
@ -90,7 +99,14 @@ impl AppData {
) )
.0; .0;
Some((BufferBacking::Dmabuf { fd, stride }, buffer)) Some((
BufferBacking::Dmabuf {
fd,
node: node.clone(),
stride,
},
buffer,
))
} }
pub fn create_buffer(&self, buffer_infos: &[BufferInfo]) -> Buffer { pub fn create_buffer(&self, buffer_infos: &[BufferInfo]) -> Buffer {
@ -135,7 +151,11 @@ impl Buffer {
let pixels = match &mut self.backing { let pixels = match &mut self.backing {
BufferBacking::Shm { pool } => pool.mmap().to_vec(), BufferBacking::Shm { pool } => pool.mmap().to_vec(),
// NOTE: Only will work with linear modifier // NOTE: Only will work with linear modifier
BufferBacking::Dmabuf { fd, stride } => { BufferBacking::Dmabuf {
fd,
node: _,
stride,
} => {
// XXX Error handling? // XXX Error handling?
let mmap = memmap2::Mmap::map(&*fd).unwrap(); let mmap = memmap2::Mmap::map(&*fd).unwrap();
if self.buffer_info.stride == self.buffer_info.width * 4 { if self.buffer_info.stride == self.buffer_info.width * 4 {
@ -156,6 +176,13 @@ impl Buffer {
}; };
image::Handle::from_pixels(self.buffer_info.width, self.buffer_info.height, pixels) image::Handle::from_pixels(self.buffer_info.width, self.buffer_info.height, pixels)
} }
pub fn node(&self) -> Option<&Path> {
match &self.backing {
BufferBacking::Shm { .. } => None,
BufferBacking::Dmabuf { node, .. } => Some(node),
}
}
} }
impl Drop for Buffer { impl Drop for Buffer {

View file

@ -6,7 +6,7 @@ use cctk::{
wayland_client::{protocol::wl_buffer, Connection, QueueHandle}, wayland_client::{protocol::wl_buffer, Connection, QueueHandle},
}; };
use std::{fs, io, os::unix::fs::MetadataExt}; use std::{fs, io, os::unix::fs::MetadataExt, path::PathBuf};
use wayland_protocols::wp::linux_dmabuf::zv1::client::{ use wayland_protocols::wp::linux_dmabuf::zv1::client::{
zwp_linux_buffer_params_v1::ZwpLinuxBufferParamsV1, zwp_linux_buffer_params_v1::ZwpLinuxBufferParamsV1,
@ -65,13 +65,13 @@ impl DmabufHandler for AppData {
} }
} }
fn find_gbm_device(dev: u64) -> io::Result<Option<gbm::Device<fs::File>>> { fn find_gbm_device(dev: u64) -> io::Result<Option<(PathBuf, gbm::Device<fs::File>)>> {
for i in std::fs::read_dir("/dev/dri")? { for i in std::fs::read_dir("/dev/dri")? {
let i = i?; let i = i?;
if i.metadata()?.rdev() == dev { if i.metadata()?.rdev() == dev {
let file = fs::File::options().read(true).write(true).open(i.path())?; let file = fs::File::options().read(true).write(true).open(i.path())?;
eprintln!("Opened gbm main device '{}'", i.path().display()); eprintln!("Opened gbm main device '{}'", i.path().display());
return Ok(Some(gbm::Device::new(file)?)); return Ok(Some((i.path(), gbm::Device::new(file)?)));
} }
} }
Ok(None) Ok(None)

View file

@ -40,6 +40,7 @@ use std::{
cell::RefCell, cell::RefCell,
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
fs, fs,
path::PathBuf,
sync::Arc, sync::Arc,
thread, thread,
}; };
@ -108,7 +109,7 @@ pub struct AppData {
capture_filter: CaptureFilter, capture_filter: CaptureFilter,
captures: RefCell<HashMap<CaptureSource, Arc<Capture>>>, captures: RefCell<HashMap<CaptureSource, Arc<Capture>>>,
dmabuf_feedback: Option<DmabufFeedback>, dmabuf_feedback: Option<DmabufFeedback>,
gbm: Option<gbm::Device<fs::File>>, gbm: Option<(PathBuf, gbm::Device<fs::File>)>,
} }
impl AppData { impl AppData {

View file

@ -34,7 +34,10 @@ impl ScreencopyHandler for AppData {
} }
let buffer = buffer.as_ref().unwrap(); let buffer = buffer.as_ref().unwrap();
session.attach_buffer(&buffer.buffer, None, 0); // XXX age? let node = buffer
.node()
.and_then(|x| x.to_str().map(|x| x.to_string()));
session.attach_buffer(&buffer.buffer, node, 0); // XXX age?
if capture.first_frame() { if capture.first_frame() {
session.commit(zcosmic_screencopy_session_v1::Options::empty()); session.commit(zcosmic_screencopy_session_v1::Options::empty());
} else { } else {