diff --git a/src/screencast_thread.rs b/src/screencast_thread.rs index 8fd948c..541a98c 100644 --- a/src/screencast_thread.rs +++ b/src/screencast_thread.rs @@ -4,6 +4,7 @@ // Dmabuf modifier negotiation is described in https://docs.pipewire.org/page_dma_buf.html +use cosmic_client_toolkit::screencopy::Formats; use futures::executor::block_on; use pipewire::{ spa::{ @@ -70,6 +71,7 @@ struct StreamData { wayland_helper: WaylandHelper, modifier: gbm::Modifier, session: Session, + formats: Formats, width: u32, height: u32, node_id_tx: Option>>, @@ -175,6 +177,7 @@ impl StreamData { plane_count, self.dmabuf_helper.as_ref(), Some(modifier), + &self.formats, ); let mut params: Vec<_> = params .iter() @@ -314,7 +317,11 @@ fn start_stream( }, )?; - let initial_params = params(width, height, 1, dmabuf_helper.as_ref(), None); + let session = wayland_helper.capture_source_session(capture_source, overlay_cursor); + + let formats = session.wait_for_formats(|formats| formats.clone()); + + let initial_params = params(width, height, 1, dmabuf_helper.as_ref(), None, &formats); let mut initial_params: Vec<_> = initial_params .iter() .map(|x| Pod::from_bytes(x.as_slice()).unwrap()) @@ -329,12 +336,11 @@ fn start_stream( &mut initial_params, )?; - let session = wayland_helper.capture_source_session(capture_source, overlay_cursor); - let data = StreamData { wayland_helper, dmabuf_helper, session, + formats, // XXX Should use implicit modifier if none set? modifier: gbm::Modifier::Linear, width, @@ -360,13 +366,14 @@ fn params( blocks: u32, dmabuf: Option<&DmabufHelper>, fixated_modifier: Option, + formats: &Formats, ) -> Vec> { [ Some(buffers(width, height, blocks)), - fixated_modifier.map(|x| format(width, height, None, Some(x))), + fixated_modifier.map(|x| format(width, height, None, Some(x), formats)), // Favor dmabuf over shm by listing it first - dmabuf.map(|x| format(width, height, Some(x), None)), - Some(format(width, height, None, None)), + dmabuf.map(|x| format(width, height, Some(x), None, formats)), + Some(format(width, height, None, None, formats)), ] .into_iter() .flatten() @@ -438,6 +445,7 @@ fn format( height: u32, dmabuf: Option<&DmabufHelper>, fixated_modifier: Option, + formats: &Formats, ) -> Vec { let mut properties = vec![ pod::Property { @@ -474,8 +482,17 @@ fn format( value: pod::Value::Long(u64::from(modifier) as i64), }); } else if let Some(dmabuf) = dmabuf { + // TODO: Support other formats + let format = gbm::Format::Abgr8888 as u32; + let screencopy_modifiers = formats + .dmabuf_formats + .iter() + .find(|(x, _)| *x == format) + .map(|(_, modifiers)| modifiers.as_slice()) + .unwrap_or_default(); let mut modifiers: Vec<_> = dmabuf - .modifiers_for_format(gbm::Format::Abgr8888 as u32) + .modifiers_for_format(format) + .filter(|x| screencopy_modifiers.contains(x)) .map(|x| x as i64) .collect(); if modifiers.is_empty() { diff --git a/src/wayland/mod.rs b/src/wayland/mod.rs index 8f218d0..35b546f 100644 --- a/src/wayland/mod.rs +++ b/src/wayland/mod.rs @@ -202,7 +202,7 @@ impl Session { self.0.condvar.notify_all(); } - fn wait_for_formats T>(&self, mut cb: F) -> T { + pub fn wait_for_formats T>(&self, mut cb: F) -> T { let data = self .0 .condvar