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:
parent
5bb719f617
commit
15e73830fa
4 changed files with 64 additions and 38 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
43
src/backend/wayland/gbm_devices.rs
Normal file
43
src/backend/wayland/gbm_devices.rs
Normal 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)
|
||||
}
|
||||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue