aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2025-08-02 13:29:08 +0300
committerIvan Molodetskikh <yalterz@gmail.com>2025-08-04 14:36:34 +0200
commit2e3935d77d42d99e1c2ed865b210ec5c6a9203d6 (patch)
tree69b1bae678f011750b4e682bc8f6f0871274d091 /src
parent53b7c08363393f6553dc0657b1e1f8d2a5384b77 (diff)
downloadniri-2e3935d77d42d99e1c2ed865b210ec5c6a9203d6.tar.gz
niri-2e3935d77d42d99e1c2ed865b210ec5c6a9203d6.tar.bz2
niri-2e3935d77d42d99e1c2ed865b210ec5c6a9203d6.zip
pw_utils: Extract shared state to CastInner
Diffstat (limited to 'src')
-rw-r--r--src/niri.rs4
-rw-r--r--src/pw_utils.rs126
2 files changed, 76 insertions, 54 deletions
diff --git a/src/niri.rs b/src/niri.rs
index 1d82ba6e..0b8fa58b 100644
--- a/src/niri.rs
+++ b/src/niri.rs
@@ -5002,7 +5002,7 @@ impl Niri {
let mut casts = mem::take(&mut self.casts);
for cast in &mut casts {
- if !cast.is_active.get() {
+ if !cast.is_active() {
continue;
}
@@ -5058,7 +5058,7 @@ impl Niri {
let mut casts = mem::take(&mut self.casts);
for cast in &mut casts {
- if !cast.is_active.get() {
+ if !cast.is_active() {
continue;
}
diff --git a/src/pw_utils.rs b/src/pw_utils.rs
index 66f9a983..541c9084 100644
--- a/src/pw_utils.rs
+++ b/src/pw_utils.rs
@@ -1,4 +1,4 @@
-use std::cell::{Cell, RefCell};
+use std::cell::RefCell;
use std::collections::HashMap;
use std::io::Cursor;
use std::iter::zip;
@@ -69,18 +69,25 @@ pub struct Cast {
pub stream_id: usize,
pub stream: Stream,
_listener: StreamListener<()>,
- pub is_active: Rc<Cell<bool>>,
pub target: CastTarget,
pub dynamic_target: bool,
formats: FormatSet,
- state: Rc<RefCell<CastState>>,
- refresh: Rc<Cell<u32>>,
offer_alpha: bool,
pub cursor_mode: CursorMode,
pub last_frame_time: Duration,
- min_time_between_frames: Rc<Cell<Duration>>,
- dmabufs: Rc<RefCell<HashMap<i64, Dmabuf>>>,
scheduled_redraw: Option<RegistrationToken>,
+ inner: Rc<RefCell<CastInner>>,
+}
+
+/// Mutable `Cast` state shared with PipeWire callbacks.
+#[derive(Debug)]
+struct CastInner {
+ is_active: bool,
+ node_id: Option<u32>,
+ state: CastState,
+ refresh: u32,
+ min_time_between_frames: Duration,
+ dmabufs: HashMap<i64, Dmabuf>,
}
#[allow(clippy::large_enum_variant)]
@@ -214,29 +221,32 @@ impl PipeWire {
let stream = Stream::new(&self.core, "niri-screen-cast-src", Properties::new())
.context("error creating Stream")?;
- // Like in good old wayland-rs times...
- let node_id = Rc::new(Cell::new(None));
- 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 refresh = Rc::new(Cell::new(refresh));
-
let pending_size = Size::from((size.w as u32, size.h as u32));
- let state = Rc::new(RefCell::new(CastState::ResizePending { pending_size }));
+
+ // Like in good old wayland-rs times...
+ let inner = Rc::new(RefCell::new(CastInner {
+ is_active: false,
+ node_id: None,
+ state: CastState::ResizePending { pending_size },
+ refresh,
+ min_time_between_frames: Duration::ZERO,
+ dmabufs: HashMap::new(),
+ }));
let listener = stream
.add_local_listener_with_user_data(())
.state_changed({
- let is_active = is_active.clone();
+ let inner = inner.clone();
let stop_cast = stop_cast.clone();
move |stream, (), old, new| {
debug!("pw stream: state changed: {old:?} -> {new:?}");
+ let mut inner = inner.borrow_mut();
match new {
StreamState::Paused => {
- if node_id.get().is_none() {
+ if inner.node_id.is_none() {
let id = stream.node_id();
- node_id.set(Some(id));
+ inner.node_id = Some(id);
debug!("pw stream: sending signal with {id}");
let _span = tracy_client::span!("sending PipeWireStreamAdded");
@@ -254,33 +264,33 @@ impl PipeWire {
});
}
- is_active.set(false);
+ inner.is_active = false;
}
StreamState::Error(_) => {
- if is_active.get() {
- is_active.set(false);
+ if inner.is_active {
+ inner.is_active = false;
stop_cast();
}
}
StreamState::Unconnected => (),
StreamState::Connecting => (),
StreamState::Streaming => {
- is_active.set(true);
+ inner.is_active = true;
redraw();
}
}
}
})
.param_changed({
- let min_time_between_frames = min_time_between_frames.clone();
+ let inner = inner.clone();
let stop_cast = stop_cast.clone();
- let state = state.clone();
let gbm = gbm.clone();
let formats = formats.clone();
- let refresh = refresh.clone();
move |stream, (), id, pod| {
let id = ParamType::from_raw(id);
trace!(?id, "pw stream: param_changed");
+ let mut inner = inner.borrow_mut();
+ let inner = &mut *inner;
if id != ParamType::Format {
return;
@@ -306,7 +316,7 @@ impl PipeWire {
let format_size = Size::from((format.size().width, format.size().height));
- let mut state = state.borrow_mut();
+ let state = &mut inner.state;
if format_size != state.expected_format_size() {
if !matches!(&*state, CastState::ResizePending { .. }) {
warn!("pw stream: wrong size, but we're not resizing");
@@ -329,7 +339,7 @@ impl PipeWire {
let min_frame_time = Duration::from_micros(
1_000_000 * u64::from(max_frame_rate.denom) / u64::from(max_frame_rate.num),
);
- min_time_between_frames.set(min_frame_time);
+ inner.min_time_between_frames = min_frame_time;
let object = pod.as_object().unwrap();
let Some(prop_modifier) =
@@ -396,7 +406,7 @@ impl PipeWire {
let o1 = make_video_params(
&fixated_format,
format_size,
- refresh.get(),
+ inner.refresh,
format_has_alpha,
);
let pod1 = make_pod(&mut b1, o1);
@@ -404,7 +414,7 @@ impl PipeWire {
let o2 = make_video_params(
&formats,
format_size,
- refresh.get(),
+ inner.refresh,
format_has_alpha,
);
let mut params = [pod1, make_pod(&mut b2, o2)];
@@ -552,16 +562,17 @@ impl PipeWire {
}
})
.add_buffer({
- let dmabufs = dmabufs.clone();
+ let inner = inner.clone();
let stop_cast = stop_cast.clone();
- let state = state.clone();
move |stream, (), buffer| {
+ let mut inner = inner.borrow_mut();
+
let (size, alpha, modifier) = if let CastState::Ready {
size,
alpha,
modifier,
..
- } = &*state.borrow()
+ } = &inner.state
{
(*size, *alpha, *modifier)
} else {
@@ -610,20 +621,21 @@ impl PipeWire {
}
let fd = (*(*spa_buffer).datas).fd;
- assert!(dmabufs.borrow_mut().insert(fd, dmabuf).is_none());
+ assert!(inner.dmabufs.insert(fd, dmabuf).is_none());
}
// During size re-negotiation, the stream sometimes just keeps running, in
// which case we may need to force a redraw once we got a newly sized buffer.
- if dmabufs.borrow().len() == 1 && stream.state() == StreamState::Streaming {
+ if inner.dmabufs.len() == 1 && stream.state() == StreamState::Streaming {
redraw_();
}
}
})
.remove_buffer({
- let dmabufs = dmabufs.clone();
+ let inner = inner.clone();
move |_stream, (), buffer| {
trace!("pw stream: remove_buffer");
+ let mut inner = inner.borrow_mut();
unsafe {
let spa_buffer = (*buffer).buffer;
@@ -631,7 +643,7 @@ impl PipeWire {
assert!((*spa_buffer).n_datas > 0);
let fd = (*spa_data).fd;
- dmabufs.borrow_mut().remove(&fd);
+ inner.dmabufs.remove(&fd);
}
}
})
@@ -641,7 +653,7 @@ impl PipeWire {
trace!("starting pw stream with size={pending_size:?}, refresh={refresh:?}");
let params;
- make_params!(params, &formats, pending_size, refresh.get(), alpha);
+ make_params!(params, &formats, pending_size, refresh, alpha);
stream
.connect(
Direction::Output,
@@ -656,29 +668,31 @@ impl PipeWire {
stream_id,
stream,
_listener: listener,
- is_active,
target,
dynamic_target,
formats,
- state,
- refresh,
offer_alpha: alpha,
cursor_mode,
last_frame_time: Duration::ZERO,
- min_time_between_frames,
- dmabufs,
scheduled_redraw: None,
+ inner,
};
Ok(cast)
}
}
impl Cast {
+ pub fn is_active(&self) -> bool {
+ self.inner.borrow().is_active
+ }
+
pub fn ensure_size(&self, size: Size<i32, Physical>) -> anyhow::Result<CastSizeChange> {
+ let mut inner = self.inner.borrow_mut();
+
let new_size = Size::from((size.w as u32, size.h as u32));
- let mut state = self.state.borrow_mut();
- if matches!(&*state, CastState::Ready { size, .. } if *size == new_size) {
+ let state = &mut inner.state;
+ if matches!(state, CastState::Ready { size, .. } if *size == new_size) {
return Ok(CastSizeChange::Ready);
}
@@ -699,7 +713,7 @@ impl Cast {
params,
&self.formats,
new_size,
- self.refresh.get(),
+ inner.refresh,
self.offer_alpha
);
self.stream
@@ -710,15 +724,17 @@ impl Cast {
}
pub fn set_refresh(&mut self, refresh: u32) -> anyhow::Result<()> {
- if self.refresh.get() == refresh {
+ let mut inner = self.inner.borrow_mut();
+
+ if inner.refresh == refresh {
return Ok(());
}
let _span = tracy_client::span!("Cast::set_refresh");
debug!("cast FPS changed, updating stream FPS");
- self.refresh.set(refresh);
+ inner.refresh = refresh;
- let size = self.state.borrow().expected_format_size();
+ let size = inner.state.expected_format_size();
let params;
make_params!(params, &self.formats, size, refresh, self.offer_alpha);
self.stream
@@ -729,8 +745,10 @@ impl Cast {
}
fn compute_extra_delay(&self, target_frame_time: Duration) -> Duration {
+ let inner = self.inner.borrow();
+
let last = self.last_frame_time;
- let min = self.min_time_between_frames.get();
+ let min = inner.min_time_between_frames;
if last.is_zero() {
trace!(?target_frame_time, ?last, "last is zero, recording");
@@ -828,7 +846,9 @@ impl Cast {
scale: Scale<f64>,
wait_for_sync: bool,
) -> bool {
- let CastState::Ready { damage_tracker, .. } = &mut *self.state.borrow_mut() else {
+ let mut inner = self.inner.borrow_mut();
+
+ let CastState::Ready { damage_tracker, .. } = &mut inner.state else {
error!("cast must be in Ready state to render");
return false;
};
@@ -855,7 +875,7 @@ impl Cast {
};
let fd = buffer.datas_mut()[0].as_raw().fd;
- let dmabuf = &self.dmabufs.borrow()[&fd];
+ let dmabuf = &inner.dmabufs[&fd];
match render_to_dmabuf(
renderer,
@@ -909,8 +929,10 @@ impl Cast {
renderer: &mut GlesRenderer,
wait_for_sync: bool,
) -> bool {
+ let mut inner = self.inner.borrow_mut();
+
// Clear out the damage tracker if we're in Ready state.
- if let CastState::Ready { damage_tracker, .. } = &mut *self.state.borrow_mut() {
+ if let CastState::Ready { damage_tracker, .. } = &mut inner.state {
*damage_tracker = None;
};
@@ -920,7 +942,7 @@ impl Cast {
};
let fd = buffer.datas_mut()[0].as_raw().fd;
- let dmabuf = &self.dmabufs.borrow()[&fd];
+ let dmabuf = &inner.dmabufs[&fd];
match clear_dmabuf(renderer, dmabuf.clone()) {
Ok(sync_point) => {