aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/niri.rs7
-rw-r--r--src/pw_utils.rs67
2 files changed, 55 insertions, 19 deletions
diff --git a/src/niri.rs b/src/niri.rs
index 57fa455c..5b6b1df0 100644
--- a/src/niri.rs
+++ b/src/niri.rs
@@ -1229,7 +1229,7 @@ impl State {
return;
};
- let (target, size, refresh) = match target {
+ let (target, size, refresh, alpha) = match target {
StreamTargetId::Output { name } => {
let global_space = &self.niri.global_space;
let output = global_space.outputs().find(|out| out.name() == name);
@@ -1243,7 +1243,7 @@ impl State {
let transform = output.current_transform();
let size = transform.transform_size(mode.size);
let refresh = mode.refresh as u32;
- (CastTarget::Output(output.downgrade()), size, refresh)
+ (CastTarget::Output(output.downgrade()), size, refresh, false)
}
StreamTargetId::Window { id } => {
let mut window = None;
@@ -1274,7 +1274,7 @@ impl State {
let size = bbox.size.to_physical_precise_ceil(scale);
let refresh = output.current_mode().unwrap().refresh as u32;
- (CastTarget::Window { id }, size, refresh)
+ (CastTarget::Window { id }, size, refresh, true)
}
};
@@ -1284,6 +1284,7 @@ impl State {
target,
size,
refresh,
+ alpha,
cursor_mode,
signal_ctx,
);
diff --git a/src/pw_utils.rs b/src/pw_utils.rs
index eedd0f03..309edca5 100644
--- a/src/pw_utils.rs
+++ b/src/pw_utils.rs
@@ -59,6 +59,7 @@ pub struct Cast {
pub target: CastTarget,
pub size: Rc<Cell<CastSize>>,
pub refresh: u32,
+ offer_alpha: bool,
pub cursor_mode: CursorMode,
pub last_frame_time: Duration,
pub min_time_between_frames: Rc<Cell<Duration>>,
@@ -87,6 +88,20 @@ pub enum CastTarget {
Window { id: u64 },
}
+macro_rules! make_params {
+ ($size:expr, $refresh:expr, $alpha:expr, $b1:expr, $b2:expr) => {{
+ let o1 = make_video_params($size, $refresh, false);
+ let pod1 = make_pod($b1, o1);
+
+ if $alpha {
+ let o2 = make_video_params($size, $refresh, true);
+ &mut [pod1, make_pod($b2, o2)][..]
+ } else {
+ &mut [pod1][..]
+ }
+ }};
+}
+
impl PipeWire {
pub fn new(event_loop: &LoopHandle<'static, State>) -> anyhow::Result<Self> {
let main_loop = MainLoop::new(None).context("error creating MainLoop")?;
@@ -139,6 +154,7 @@ impl PipeWire {
target: CastTarget,
size: Size<i32, Physical>,
refresh: u32,
+ alpha: bool,
cursor_mode: CursorMode,
signal_ctx: SignalContext<'static>,
) -> anyhow::Result<Cast> {
@@ -167,6 +183,7 @@ impl PipeWire {
let is_active = Rc::new(Cell::new(false));
let min_time_between_frames = Rc::new(Cell::new(Duration::ZERO));
let dmabufs = Rc::new(RefCell::new(HashMap::new()));
+ let negotiated_alpha = Rc::new(Cell::new(false));
let pending_size = size;
let size = Rc::new(Cell::new(CastSize::InitialPending(size)));
@@ -221,6 +238,7 @@ impl PipeWire {
.param_changed({
let min_time_between_frames = min_time_between_frames.clone();
let size = size.clone();
+ let negotiated_alpha = negotiated_alpha.clone();
move |stream, (), id, pod| {
let id = ParamType::from_raw(id);
trace!(?id, "pw stream: param_changed");
@@ -260,6 +278,8 @@ impl PipeWire {
});
}
+ negotiated_alpha.set(format.format() == VideoFormat::BGRA);
+
let max_frame_rate = format.max_framerate();
// Subtract 0.5 ms to improve edge cases when equal to refresh rate.
let min_frame_time = Duration::from_secs_f64(
@@ -325,9 +345,11 @@ impl PipeWire {
let dmabufs = dmabufs.clone();
let stop_cast = stop_cast.clone();
let size = size.clone();
+ let negotiated_alpha = negotiated_alpha.clone();
move |stream, (), buffer| {
let size = size.get().negotiated_size();
- trace!("pw stream: add_buffer, size={:?}", size);
+ let alpha = negotiated_alpha.get();
+ trace!("pw stream: add_buffer, size={:?}, alpha={alpha}", size);
let size = size.expect("size must be negotiated to allocate buffers");
unsafe {
@@ -336,10 +358,16 @@ impl PipeWire {
assert!((*spa_buffer).n_datas > 0);
assert!((*spa_data).type_ & (1 << DataType::DmaBuf.as_raw()) > 0);
+ let fourcc = if alpha {
+ Fourcc::Argb8888
+ } else {
+ Fourcc::Xrgb8888
+ };
+
let bo = match gbm.create_buffer_object::<()>(
size.w as u32,
size.h as u32,
- Fourcc::Xrgb8888,
+ fourcc,
GbmBufferFlags::RENDERING | GbmBufferFlags::LINEAR,
) {
Ok(bo) => bo,
@@ -396,15 +424,15 @@ impl PipeWire {
trace!("starting pw stream with size={pending_size:?}, refresh={refresh}");
- let object = make_video_params(pending_size, refresh);
- let mut buffer = vec![];
- let mut params = [make_pod(&mut buffer, object)];
+ let mut b1 = Vec::new();
+ let mut b2 = Vec::new();
+ let params = make_params!(pending_size, refresh, alpha, &mut b1, &mut b2);
stream
.connect(
Direction::Output,
None,
StreamFlags::DRIVER | StreamFlags::ALLOC_BUFFERS,
- &mut params,
+ params,
)
.context("error connecting stream")?;
@@ -416,6 +444,7 @@ impl PipeWire {
target,
size,
refresh,
+ offer_alpha: alpha,
cursor_mode,
last_frame_time: Duration::ZERO,
min_time_between_frames,
@@ -442,11 +471,11 @@ impl Cast {
self.size.set(current_size.with_pending(size));
- let object = make_video_params(size, self.refresh);
- let mut buffer = vec![];
- let mut params = [make_pod(&mut buffer, object)];
+ let mut b1 = Vec::new();
+ let mut b2 = Vec::new();
+ let params = make_params!(size, self.refresh, self.offer_alpha, &mut b1, &mut b2);
self.stream
- .update_params(&mut params)
+ .update_params(params)
.context("error updating stream params")?;
Ok(CastSizeChange::Pending)
@@ -462,11 +491,11 @@ impl Cast {
self.refresh = refresh;
let size = self.size.get().expected_format_size();
- let object = make_video_params(size, self.refresh);
- let mut buffer = vec![];
- let mut params = [make_pod(&mut buffer, object)];
+ let mut b1 = Vec::new();
+ let mut b2 = Vec::new();
+ let params = make_params!(size, self.refresh, self.offer_alpha, &mut b1, &mut b2);
self.stream
- .update_params(&mut params)
+ .update_params(params)
.context("error updating stream params")?;
Ok(())
@@ -583,13 +612,19 @@ impl CastSize {
}
}
-fn make_video_params(size: Size<i32, Physical>, refresh: u32) -> pod::Object {
+fn make_video_params(size: Size<i32, Physical>, refresh: u32, alpha: bool) -> pod::Object {
+ let format = if alpha {
+ VideoFormat::BGRA
+ } else {
+ VideoFormat::BGRx
+ };
+
pod::object!(
SpaTypes::ObjectParamFormat,
ParamType::EnumFormat,
pod::property!(FormatProperties::MediaType, Id, MediaType::Video),
pod::property!(FormatProperties::MediaSubtype, Id, MediaSubtype::Raw),
- pod::property!(FormatProperties::VideoFormat, Id, VideoFormat::BGRx),
+ pod::property!(FormatProperties::VideoFormat, Id, format),
Property {
key: FormatProperties::VideoModifier.as_raw(),
value: pod::Value::Long(u64::from(Modifier::Invalid) as i64),