Skip to content

Commit

Permalink
move drm lease stuff to wlr-screencopy
Browse files Browse the repository at this point in the history
* not needed for ext-image-copy-capture
  • Loading branch information
russelltg committed Oct 13, 2024
1 parent 3d31d66 commit ee5fde0
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 83 deletions.
64 changes: 61 additions & 3 deletions src/cap_wlr_screencopy.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
use std::sync::atomic::Ordering::SeqCst;
use std::{ffi::CStr, os::fd::AsRawFd, path::PathBuf, sync::atomic::Ordering::SeqCst};

use anyhow::Context;
use drm::buffer::DrmFourcc;
use log::debug;
use wayland_client::{
event_created_child,
globals::GlobalList,
protocol::{wl_buffer::WlBuffer, wl_output::WlOutput},
Connection, Dispatch, Proxy, QueueHandle,
};
use wayland_protocols::wp::drm_lease::v1::client::{
wp_drm_lease_connector_v1::WpDrmLeaseConnectorV1,
wp_drm_lease_device_v1::{self, WpDrmLeaseDeviceV1},
};
use wayland_protocols_wlr::screencopy::v1::client::{
zwlr_screencopy_frame_v1::{self, ZwlrScreencopyFrameV1},
zwlr_screencopy_manager_v1::ZwlrScreencopyManagerV1,
};

use crate::{CaptureSource, DmabufPotentialFormat, DrmModifier, State};
use crate::{
drmGetRenderDeviceNameFromFd, CaptureSource, DmabufPotentialFormat, DrmModifier, State,
};

impl Dispatch<ZwlrScreencopyManagerV1, ()> for State<CapWlrScreencopy> {
fn event(
Expand Down Expand Up @@ -55,13 +62,14 @@ impl Dispatch<ZwlrScreencopyFrameV1, ()> for State<CapWlrScreencopy> {
let cap = state.enc.unwrap_cap();
if !cap.sent_format {
cap.sent_format = true;
let device = cap.drm_device.clone();
state.negotiate_format(
&[DmabufPotentialFormat {
fourcc,
modifiers: vec![DrmModifier::LINEAR],
}],
(dmabuf_width, dmabuf_height),
None,
device.as_deref(),
);
}
state.on_copy_src_ready(dmabuf_width, dmabuf_height, fourcc, qhandle, capture);
Expand All @@ -78,10 +86,52 @@ impl Dispatch<ZwlrScreencopyFrameV1, ()> for State<CapWlrScreencopy> {
}
}

impl Dispatch<WpDrmLeaseDeviceV1, ()> for State<CapWlrScreencopy> {
fn event(
state: &mut Self,
proxy: &WpDrmLeaseDeviceV1,
event: <WpDrmLeaseDeviceV1 as Proxy>::Event,
_data: &(),
_conn: &Connection,
_qhandle: &QueueHandle<Self>,
) {
debug!("zwp-drm-lease-device event: {:?} {event:?}", proxy.id());
if let wp_drm_lease_device_v1::Event::DrmFd { fd } = event {
unsafe {
let ptr = drmGetRenderDeviceNameFromFd(fd.as_raw_fd());

if !ptr.is_null() {
let ret = CStr::from_ptr(ptr).to_string_lossy().to_string();
libc::free(ptr as *mut _);

state.enc.unwrap_cap().drm_device = Some(PathBuf::from(ret));
}
};
}
}

event_created_child!(State<CapWlrScreencopy>, WpDrmLeaseDeviceV1, [
wp_drm_lease_device_v1::EVT_CONNECTOR_OPCODE => (WpDrmLeaseConnectorV1, ()),
]);
}

impl Dispatch<WpDrmLeaseConnectorV1, ()> for State<CapWlrScreencopy> {
fn event(
_state: &mut Self,
_proxy: &WpDrmLeaseConnectorV1,
_event: <WpDrmLeaseConnectorV1 as Proxy>::Event,
_data: &(),
_conn: &Connection,
_qhandle: &QueueHandle<Self>,
) {
}
}

pub struct CapWlrScreencopy {
screencopy_manager: ZwlrScreencopyManagerV1,
output: WlOutput,
sent_format: bool,
drm_device: Option<PathBuf>,
}
impl CaptureSource for CapWlrScreencopy {
fn new(
Expand All @@ -92,10 +142,18 @@ impl CaptureSource for CapWlrScreencopy {
let man: ZwlrScreencopyManagerV1 = gm
.bind(eq, 3..=ZwlrScreencopyManagerV1::interface().version, ()).context("your compositor does not support zwlr-screencopy-manager and therefore is not support by wl-screenrec. See the README for supported compositors")?;

// if this doesn't exist, it will get logged later anyways
let _ = gm.bind::<WpDrmLeaseDeviceV1, _, _>(
&eq,
WpDrmLeaseDeviceV1::interface().version..=WpDrmLeaseDeviceV1::interface().version,
(),
);

Ok(Self {
screencopy_manager: man,
output,
sent_format: false,
drm_device: None,
})
}

Expand Down
96 changes: 16 additions & 80 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use std::{
marker::PhantomData,
mem::{self, swap},
num::ParseIntError,
os::fd::{AsRawFd, BorrowedFd},
path::{Path, PathBuf},
os::fd::BorrowedFd,
path::Path,
process::exit,
ptr::null_mut,
str::from_utf8_unchecked,
Expand Down Expand Up @@ -62,15 +62,9 @@ use wayland_client::{
ConnectError, Connection, Dispatch, EventQueue, Proxy, QueueHandle, WEnum,
};
use wayland_protocols::{
wp::{
drm_lease::v1::client::{
wp_drm_lease_connector_v1::WpDrmLeaseConnectorV1,
wp_drm_lease_device_v1::{self, WpDrmLeaseDeviceV1},
},
linux_dmabuf::zv1::client::{
zwp_linux_buffer_params_v1::{self, ZwpLinuxBufferParamsV1},
zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1,
},
wp::linux_dmabuf::zv1::client::{
zwp_linux_buffer_params_v1::{self, ZwpLinuxBufferParamsV1},
zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1,
},
xdg::xdg_output::zv1::client::{
zxdg_output_manager_v1::ZxdgOutputManagerV1,
Expand Down Expand Up @@ -138,7 +132,7 @@ pub struct Args {

#[clap(
long,
help = "which dri device to use for vaapi. by default, this is obtained from the drm-lease-v1 protocol, if present. if not present, /dev/dri/renderD128 is guessed"
help = "which dri device to use for vaapi. by default, this is obtained from the drm-lease-v1 protocol when using wlr-screencopy, and from ext-image-copy-capture-session if using ext-image-copy-capture, if present. if not present, /dev/dri/renderD128 is guessed"
)]
dri_device: Option<String>,

Expand Down Expand Up @@ -530,53 +524,6 @@ extern "C" {
pub fn drmGetFormatModifierName(modifier: u64) -> *mut libc::c_char;
}

impl<S> Dispatch<WpDrmLeaseDeviceV1, ()> for State<S>
where
S: CaptureSource + 'static,
{
fn event(
state: &mut Self,
proxy: &WpDrmLeaseDeviceV1,
event: <WpDrmLeaseDeviceV1 as Proxy>::Event,
_data: &(),
_conn: &Connection,
_qhandle: &QueueHandle<Self>,
) {
debug!("zwp-drm-lease-device event: {:?} {event:?}", proxy.id());
if let wp_drm_lease_device_v1::Event::DrmFd { fd } = event {
unsafe {
let ptr = drmGetRenderDeviceNameFromFd(fd.as_raw_fd());
state.dri_device = Some(if ptr.is_null() {
warn!(
"drmGetRenderDeviceNameFromFd returned null, guessing /dev/dri/renderD128. pass --dri-device if this is not correct or to suppress this warning"
);
PathBuf::from("/dev/dri/renderD128".to_owned())
} else {
let ret = CStr::from_ptr(ptr).to_string_lossy().to_string();
libc::free(ptr as *mut _);
PathBuf::from(ret)
});
};
}
}

event_created_child!(State<S>, WpDrmLeaseDeviceV1, [
wp_drm_lease_device_v1::EVT_CONNECTOR_OPCODE => (WpDrmLeaseConnectorV1, ()),
]);
}

impl<S: CaptureSource> Dispatch<WpDrmLeaseConnectorV1, ()> for State<S> {
fn event(
_state: &mut Self,
_proxy: &WpDrmLeaseConnectorV1,
_event: <WpDrmLeaseConnectorV1 as Proxy>::Event,
_data: &(),
_conn: &Connection,
_qhandle: &QueueHandle<Self>,
) {
}
}

struct State<S: CaptureSource> {
pub(crate) surfaces_owned_by_compositor: VecDeque<(
frame::Video,
Expand All @@ -593,7 +540,6 @@ struct State<S: CaptureSource> {
args: Args,
quit_flag: Arc<AtomicUsize>,
sigusr1_flag: Arc<AtomicBool>,
dri_device: Option<PathBuf>,
gm: GlobalList,
}

Expand Down Expand Up @@ -885,22 +831,6 @@ impl<S: CaptureSource + 'static> State<S> {
)
.context("your compositor does not support zwlr-output-manager and therefore is not support by wl-screenrec. See the README for supported compositors")?;

let dri_device = if let Some(dev) = &args.dri_device {
Some(PathBuf::from(dev.clone()))
} else if gm
.bind::<WpDrmLeaseDeviceV1, _, _>(
&eq,
WpDrmLeaseDeviceV1::interface().version..=WpDrmLeaseDeviceV1::interface().version,
(),
)
.is_err()
{
warn!("Your compositor does not support wp_drm_lease_device_v1, so guessing that dri device is /dev/dri/renderD128. pass --dri-device if this is incorrect or to suppress this warning");
Some(PathBuf::from("/dev/dri/renderD128".to_owned()))
} else {
None // will be filled by the callback
};

let mut partial_outputs = HashMap::new();
for g in gm.contents().clone_list() {
if g.interface == WlOutput::interface().name {
Expand Down Expand Up @@ -941,7 +871,6 @@ impl<S: CaptureSource + 'static> State<S> {
wl_output: None,
quit_flag,
sigusr1_flag,
dri_device,
gm,
},
queue,
Expand Down Expand Up @@ -1305,6 +1234,15 @@ impl<S: CaptureSource + 'static> State<S> {
dri_device: Option<&Path>,
) -> Option<DmabufFormat> {
debug!("Supported capture formats are {capture_formats:?}");
let dri_device = if let Some(dev) = &self.args.dri_device {
Path::new(dev)
} else if let Some(dev) = dri_device {
dev
} else {
warn!("dri device could not be auto-detected, using /dev/dri/renderD128. Pass --dri-device if this isn't correct or to suppress this warning");
Path::new("/dev/dri/renderD128")
};

match mem::replace(&mut self.enc, EncConstructionStage::Intermediate) {
EncConstructionStage::EverythingButFormat { output, roi, cap } => {
let (enc, fmt) = match EncState::new(
Expand All @@ -1315,9 +1253,7 @@ impl<S: CaptureSource + 'static> State<S> {
(w as i32, h as i32),
roi,
Arc::clone(&self.sigusr1_flag),
dri_device
.or_else(|| self.dri_device.as_deref())
.expect("somehow got screenrec before getting DRI device?"),
dri_device,
) {
Ok(enc) => enc,
Err(e) => {
Expand Down

0 comments on commit ee5fde0

Please sign in to comment.