Use gbm device from image copy protocol instead of default node

This fixes `BufferConstraints` errors for workspace capture on Nvidia
outputs of a Intel+Nvidia system. (That didn't happen on Amd+Nvidia;
maybe a linear stride alignment issue?)
This commit is contained in:
Ian Douglas Scott 2025-04-09 11:58:15 -07:00 committed by Ian Douglas Scott
parent 5bb719f617
commit 15e73830fa
4 changed files with 64 additions and 38 deletions

View file

@ -79,15 +79,18 @@ impl AppData {
#[cfg(not(feature = "force-shm-screencopy"))]
fn create_gbm_buffer(
&self,
&mut self,
format: u32,
modifiers: &[u64],
(width, height): (u32, u32),
needs_linear: bool,
drm_dev: Option<u64>,
) -> anyhow::Result<Option<Buffer>> {
let (Some((node, gbm)), Some(feedback)) =
(self.gbm.as_ref(), self.dmabuf_feedback.as_ref())
else {
let Some(feedback) = self.dmabuf_feedback.as_ref() else {
return Ok(None);
};
let drm_dev = drm_dev.unwrap_or(feedback.main_device() as u64);
let Some((node, gbm)) = self.gbm_devices.gbm_device(drm_dev)? else {
return Ok(None);
};
let formats = feedback.format_table();
@ -171,12 +174,12 @@ impl AppData {
.into(),
),
buffer,
node: Some(node.clone()),
node: Some(node.to_owned()),
size: (width, height),
}))
}
pub fn create_buffer(&self, formats: &Formats) -> Buffer {
pub fn create_buffer(&mut self, formats: &Formats) -> Buffer {
// XXX Handle other formats?
let format = wl_shm::Format::Abgr8888;
@ -186,7 +189,13 @@ impl AppData {
.iter()
.find(|(f, _)| *f == u32::from(format))
{
match self.create_gbm_buffer(u32::from(format), modifiers, formats.buffer_size, false) {
match self.create_gbm_buffer(
u32::from(format),
modifiers,
formats.buffer_size,
false,
formats.dmabuf_device.map(|dev| dev as u64),
) {
Ok(Some(buffer)) => {
return buffer;
}

View file

@ -7,8 +7,6 @@ use cctk::{
};
use cosmic::cctk;
use std::{fs, io, os::unix::fs::MetadataExt, path::PathBuf};
use wayland_protocols::wp::linux_dmabuf::zv1::client::{
zwp_linux_buffer_params_v1::ZwpLinuxBufferParamsV1,
zwp_linux_dmabuf_feedback_v1::ZwpLinuxDmabufFeedbackV1,
@ -27,20 +25,6 @@ impl DmabufHandler for AppData {
_proxy: &ZwpLinuxDmabufFeedbackV1,
feedback: DmabufFeedback,
) {
if self.gbm.is_none() {
#[allow(clippy::unnecessary_cast)]
match find_gbm_device(feedback.main_device() as u64) {
Ok(Some(gbm)) => {
self.gbm = Some(gbm);
}
Ok(None) => {
log::error!("Gbm main device '{}' not found", feedback.main_device());
}
Err(err) => {
log::error!("Failed to open gbm main device: {}", err);
}
}
}
self.dmabuf_feedback = Some(feedback);
}
fn created(
@ -67,16 +51,4 @@ impl DmabufHandler for AppData {
}
}
fn find_gbm_device(dev: u64) -> io::Result<Option<(PathBuf, gbm::Device<fs::File>)>> {
for i in std::fs::read_dir("/dev/dri")? {
let i = i?;
if i.metadata()?.rdev() == dev {
let file = fs::File::options().read(true).write(true).open(i.path())?;
log::info!("Opened gbm main device '{}'", i.path().display());
return Ok(Some((i.path(), gbm::Device::new(file)?)));
}
}
Ok(None)
}
sctk::delegate_dmabuf!(AppData);

View file

@ -0,0 +1,43 @@
use std::{
collections::hash_map::{self, HashMap},
fs, io,
os::unix::fs::MetadataExt,
path::{Path, PathBuf},
};
// TODO Purge gbm devices that are no longer needed/valid?
#[derive(Default)]
pub struct GbmDevices {
devices: HashMap<u64, (PathBuf, gbm::Device<fs::File>)>,
}
impl GbmDevices {
pub fn gbm_device(&mut self, dev: u64) -> io::Result<Option<(&Path, &gbm::Device<fs::File>)>> {
Ok(match self.devices.entry(dev) {
hash_map::Entry::Occupied(entry) => {
let (path, gbm) = entry.into_mut();
Some((path, gbm))
}
hash_map::Entry::Vacant(entry) => {
if let Some(value) = find_gbm_device(dev)? {
let (path, gbm) = entry.insert(value);
Some((path, gbm))
} else {
None
}
}
})
}
}
fn find_gbm_device(dev: u64) -> io::Result<Option<(PathBuf, gbm::Device<fs::File>)>> {
for i in std::fs::read_dir("/dev/dri")? {
let i = i?;
if i.metadata()?.rdev() == dev {
let file = fs::File::options().read(true).write(true).open(i.path())?;
log::info!("Opened gbm main device '{}'", i.path().display());
return Ok(Some((i.path(), gbm::Device::new(file)?)));
}
}
Ok(None)
}

View file

@ -27,13 +27,15 @@ use cosmic::{
},
};
use futures_channel::mpsc;
use std::{cell::RefCell, collections::HashMap, fs, path::PathBuf, sync::Arc, thread};
use std::{cell::RefCell, collections::HashMap, sync::Arc, thread};
mod buffer;
use buffer::Buffer;
mod capture;
use capture::Capture;
mod dmabuf;
mod gbm_devices;
use gbm_devices::GbmDevices;
mod screencopy;
use screencopy::{ScreencopySession, SessionData};
mod toplevel;
@ -59,7 +61,7 @@ pub struct AppData {
capture_filter: CaptureFilter,
captures: RefCell<HashMap<CaptureSource, Arc<Capture>>>,
dmabuf_feedback: Option<DmabufFeedback>,
gbm: Option<(PathBuf, gbm::Device<fs::File>)>,
gbm_devices: GbmDevices,
thread_pool: futures_executor::ThreadPool,
}
@ -310,7 +312,7 @@ fn start(conn: Connection) -> mpsc::Receiver<Event> {
capture_filter: CaptureFilter::default(),
captures: RefCell::new(HashMap::new()),
dmabuf_feedback: None,
gbm: None,
gbm_devices: GbmDevices::default(),
thread_pool,
};