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"))]
|
#[cfg(not(feature = "force-shm-screencopy"))]
|
||||||
fn create_gbm_buffer(
|
fn create_gbm_buffer(
|
||||||
&self,
|
&mut self,
|
||||||
format: u32,
|
format: u32,
|
||||||
modifiers: &[u64],
|
modifiers: &[u64],
|
||||||
(width, height): (u32, u32),
|
(width, height): (u32, u32),
|
||||||
needs_linear: bool,
|
needs_linear: bool,
|
||||||
|
drm_dev: Option<u64>,
|
||||||
) -> anyhow::Result<Option<Buffer>> {
|
) -> anyhow::Result<Option<Buffer>> {
|
||||||
let (Some((node, gbm)), Some(feedback)) =
|
let Some(feedback) = self.dmabuf_feedback.as_ref() else {
|
||||||
(self.gbm.as_ref(), self.dmabuf_feedback.as_ref())
|
return Ok(None);
|
||||||
else {
|
};
|
||||||
|
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);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
let formats = feedback.format_table();
|
let formats = feedback.format_table();
|
||||||
|
|
@ -171,12 +174,12 @@ impl AppData {
|
||||||
.into(),
|
.into(),
|
||||||
),
|
),
|
||||||
buffer,
|
buffer,
|
||||||
node: Some(node.clone()),
|
node: Some(node.to_owned()),
|
||||||
size: (width, height),
|
size: (width, height),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_buffer(&self, formats: &Formats) -> Buffer {
|
pub fn create_buffer(&mut self, formats: &Formats) -> Buffer {
|
||||||
// XXX Handle other formats?
|
// XXX Handle other formats?
|
||||||
let format = wl_shm::Format::Abgr8888;
|
let format = wl_shm::Format::Abgr8888;
|
||||||
|
|
||||||
|
|
@ -186,7 +189,13 @@ impl AppData {
|
||||||
.iter()
|
.iter()
|
||||||
.find(|(f, _)| *f == u32::from(format))
|
.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)) => {
|
Ok(Some(buffer)) => {
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,6 @@ use cctk::{
|
||||||
};
|
};
|
||||||
use cosmic::cctk;
|
use cosmic::cctk;
|
||||||
|
|
||||||
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,
|
||||||
zwp_linux_dmabuf_feedback_v1::ZwpLinuxDmabufFeedbackV1,
|
zwp_linux_dmabuf_feedback_v1::ZwpLinuxDmabufFeedbackV1,
|
||||||
|
|
@ -27,20 +25,6 @@ impl DmabufHandler for AppData {
|
||||||
_proxy: &ZwpLinuxDmabufFeedbackV1,
|
_proxy: &ZwpLinuxDmabufFeedbackV1,
|
||||||
feedback: DmabufFeedback,
|
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);
|
self.dmabuf_feedback = Some(feedback);
|
||||||
}
|
}
|
||||||
fn created(
|
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);
|
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 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;
|
mod buffer;
|
||||||
use buffer::Buffer;
|
use buffer::Buffer;
|
||||||
mod capture;
|
mod capture;
|
||||||
use capture::Capture;
|
use capture::Capture;
|
||||||
mod dmabuf;
|
mod dmabuf;
|
||||||
|
mod gbm_devices;
|
||||||
|
use gbm_devices::GbmDevices;
|
||||||
mod screencopy;
|
mod screencopy;
|
||||||
use screencopy::{ScreencopySession, SessionData};
|
use screencopy::{ScreencopySession, SessionData};
|
||||||
mod toplevel;
|
mod toplevel;
|
||||||
|
|
@ -59,7 +61,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<(PathBuf, gbm::Device<fs::File>)>,
|
gbm_devices: GbmDevices,
|
||||||
thread_pool: futures_executor::ThreadPool,
|
thread_pool: futures_executor::ThreadPool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -310,7 +312,7 @@ fn start(conn: Connection) -> mpsc::Receiver<Event> {
|
||||||
capture_filter: CaptureFilter::default(),
|
capture_filter: CaptureFilter::default(),
|
||||||
captures: RefCell::new(HashMap::new()),
|
captures: RefCell::new(HashMap::new()),
|
||||||
dmabuf_feedback: None,
|
dmabuf_feedback: None,
|
||||||
gbm: None,
|
gbm_devices: GbmDevices::default(),
|
||||||
thread_pool,
|
thread_pool,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue