aboutsummaryrefslogtreecommitdiff
path: root/src/app/pane_graphics.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/pane_graphics.rs')
-rw-r--r--src/app/pane_graphics.rs350
1 files changed, 0 insertions, 350 deletions
diff --git a/src/app/pane_graphics.rs b/src/app/pane_graphics.rs
deleted file mode 100644
index 71f998d8..00000000
--- a/src/app/pane_graphics.rs
+++ /dev/null
@@ -1,350 +0,0 @@
-use std::collections::HashMap;
-use std::hash::{Hash, Hasher};
-
-use crate::api::schema::{PaneGraphicsFormat, PaneGraphicsPlacementParams};
-use crate::layout::PaneId;
-
-pub(crate) type Key = (PaneId, String);
-
-pub(crate) const DIRECT_DELIVERY_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(5);
-pub(crate) const DIRECT_RESPONSE_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(3);
-pub(crate) const DIRECT_OUTER_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(9);
-
-#[derive(Debug)]
-pub(crate) enum Backing {
- Inline(Vec<u8>),
- Direct(crate::pane_graphics_files::Lease),
- Resident { len: usize, client_id: u64 },
-}
-
-#[derive(Debug)]
-pub(crate) struct Layer {
- pub(crate) format: PaneGraphicsFormat,
- pub(crate) image_width: u32,
- pub(crate) image_height: u32,
- pub(crate) backing: Backing,
- pub(crate) data_fingerprint: u64,
- pub(crate) render: PaneGraphicsPlacementParams,
- pub(crate) z_index: i32,
-}
-
-#[derive(Debug)]
-pub(crate) struct DirectGate {
- pub(crate) transfer_id: u64,
- pub(crate) image_id: u32,
- pub(crate) client_id: u64,
- pub(crate) deadline: std::time::Instant,
- pub(crate) written: bool,
- pub(crate) success_response: String,
- pub(crate) respond_to: std::sync::mpsc::Sender<String>,
-}
-
-#[derive(Debug)]
-pub(crate) struct Slot {
- pub(crate) host_image_id: u32,
- pub(crate) layer: Option<Layer>,
- pub(crate) stream_owner: Option<String>,
- pub(crate) stream_active: Option<std::sync::Arc<std::sync::atomic::AtomicBool>>,
- pub(crate) direct_gate: Option<DirectGate>,
-}
-
-impl Slot {
- #[cfg(test)]
- pub(crate) fn test(host_image_id: u32, layer: Option<Layer>) -> Self {
- Self {
- host_image_id,
- layer,
- stream_owner: None,
- stream_active: None,
- direct_gate: None,
- }
- }
-
- pub(crate) fn stream_is_active(&self) -> bool {
- self.stream_active
- .as_ref()
- .is_some_and(|active| active.load(std::sync::atomic::Ordering::Acquire))
- }
-
- pub(crate) fn direct_client(&self) -> Option<u64> {
- self.direct_gate
- .as_ref()
- .map(|gate| gate.client_id)
- .or_else(|| self.layer.as_ref().and_then(Layer::resident_client))
- }
-}
-
-impl Drop for Slot {
- fn drop(&mut self) {
- if let Some(active) = &self.stream_active {
- active.store(false, std::sync::atomic::Ordering::Release);
- }
- }
-}
-
-#[derive(Debug)]
-pub(crate) struct Runtime {
- pub(crate) slots: HashMap<Key, Slot>,
- revision: u64,
- next_host_image_id: u32,
-}
-
-impl Default for Runtime {
- fn default() -> Self {
- Self {
- slots: HashMap::new(),
- revision: 0,
- next_host_image_id: 1 << 31,
- }
- }
-}
-
-impl Runtime {
- pub(crate) fn revision(&self) -> u64 {
- self.revision
- }
-
- pub(crate) fn mark_changed(&mut self) {
- self.revision = self.revision.wrapping_add(1);
- }
-
- #[cfg(test)]
- pub(crate) fn clear(&mut self) {
- self.slots.clear();
- self.mark_changed();
- }
-
- pub(crate) fn reserve_image_id(&mut self, key: &Key) -> Option<u32> {
- if let Some(id) = self.slots.get(key).map(|slot| slot.host_image_id) {
- return Some(id);
- }
- for _ in 0..=self.slots.len() {
- let id = self.next_host_image_id | (1 << 31);
- self.next_host_image_id = id.wrapping_add(1) | (1 << 31);
- if self.slots.values().all(|slot| slot.host_image_id != id) {
- return Some(id);
- }
- }
- None
- }
-
- pub(crate) fn layer_count(&self, pane_id: PaneId) -> usize {
- self.slots.keys().filter(|(id, _)| *id == pane_id).count()
- }
-
- pub(crate) fn can_add_slot(&self, key: &Key) -> bool {
- self.slots.contains_key(key)
- || self.slots.len() < crate::api::schema::panes::PANE_GRAPHICS_MAX_LAYERS_TOTAL
- }
-
- pub(crate) fn can_store_inline(&self, key: &Key, len: usize) -> bool {
- let replaced = self
- .slots
- .get(key)
- .and_then(|slot| slot.layer.as_ref())
- .and_then(Layer::inline_data)
- .map_or(0, <[u8]>::len);
- self.inline_bytes()
- .saturating_sub(replaced)
- .saturating_add(len)
- <= crate::api::schema::panes::PANE_GRAPHICS_MAX_INLINE_BYTES_TOTAL
- }
-
- fn inline_bytes(&self) -> usize {
- self.slots
- .values()
- .filter_map(|slot| slot.layer.as_ref())
- .filter_map(Layer::inline_data)
- .map(<[u8]>::len)
- .sum()
- }
-
- pub(crate) fn attach_stream_active(
- &mut self,
- key: &Key,
- owner: &str,
- active: std::sync::Arc<std::sync::atomic::AtomicBool>,
- ) {
- if let Some(slot) = self
- .slots
- .get_mut(key)
- .filter(|slot| slot.stream_owner.as_deref() == Some(owner))
- {
- slot.stream_active = Some(active);
- }
- }
-
- pub(crate) fn retain_live_panes(&mut self, state: &crate::app::state::AppState) -> bool {
- if self.slots.is_empty() {
- return false;
- }
- let before = self.slots.len();
- self.slots.retain(|(pane_id, _), _| {
- state
- .workspaces
- .iter()
- .any(|workspace| workspace.pane_state(*pane_id).is_some())
- });
- if self.slots.len() == before {
- return false;
- }
- self.mark_changed();
- true
- }
-}
-
-impl Layer {
- pub(crate) fn inline(
- format: PaneGraphicsFormat,
- image_width: u32,
- image_height: u32,
- data: Vec<u8>,
- render: PaneGraphicsPlacementParams,
- z_index: i32,
- ) -> Self {
- let mut hasher = std::collections::hash_map::DefaultHasher::new();
- data.hash(&mut hasher);
- Self {
- format,
- image_width,
- image_height,
- backing: Backing::Inline(data),
- data_fingerprint: hasher.finish(),
- render,
- z_index,
- }
- }
-
- pub(crate) fn direct(
- image_width: u32,
- image_height: u32,
- lease: crate::pane_graphics_files::Lease,
- render: PaneGraphicsPlacementParams,
- z_index: i32,
- ) -> Self {
- let data_fingerprint = lease.fingerprint();
- Self {
- format: PaneGraphicsFormat::Rgba,
- image_width,
- image_height,
- backing: Backing::Direct(lease),
- data_fingerprint,
- render,
- z_index,
- }
- }
-
- pub(crate) fn data_len(&self) -> usize {
- match &self.backing {
- Backing::Inline(data) => data.len(),
- Backing::Direct(lease) => lease.len(),
- Backing::Resident { len, .. } => *len,
- }
- }
-
- pub(crate) fn inline_data(&self) -> Option<&[u8]> {
- match &self.backing {
- Backing::Inline(data) => Some(data),
- Backing::Direct(_) | Backing::Resident { .. } => None,
- }
- }
-
- pub(crate) fn direct_lease(&self) -> Option<&crate::pane_graphics_files::Lease> {
- match &self.backing {
- Backing::Direct(lease) => Some(lease),
- Backing::Inline(_) | Backing::Resident { .. } => None,
- }
- }
-
- pub(crate) fn mark_resident(&mut self, client_id: u64) -> bool {
- let Backing::Direct(lease) = &self.backing else {
- return false;
- };
- self.backing = Backing::Resident {
- len: lease.len(),
- client_id,
- };
- true
- }
-
- pub(crate) fn resident_client(&self) -> Option<u64> {
- match self.backing {
- Backing::Resident { client_id, .. } => Some(client_id),
- Backing::Inline(_) | Backing::Direct(_) => None,
- }
- }
-
- pub(crate) fn terminal_only(&self) -> bool {
- matches!(self.backing, Backing::Direct(_) | Backing::Resident { .. })
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn stream_liveness_attaches_only_to_the_exact_owned_layer() {
- let mut runtime = Runtime::default();
- let first = (PaneId::from_raw(1), "first".into());
- let second = (PaneId::from_raw(2), "second".into());
- for (key, id) in [(&first, 1), (&second, 2)] {
- runtime.slots.insert(
- key.clone(),
- Slot {
- host_image_id: (1 << 31) | id,
- layer: None,
- stream_owner: Some("shared-owner".into()),
- stream_active: None,
- direct_gate: None,
- },
- );
- }
- let active = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(true));
-
- runtime.attach_stream_active(&second, "shared-owner", active.clone());
-
- assert!(runtime.slots[&first].stream_active.is_none());
- assert!(std::sync::Arc::ptr_eq(
- runtime.slots[&second].stream_active.as_ref().unwrap(),
- &active
- ));
- }
-
- #[test]
- fn runtime_bounds_total_slots_and_inline_bytes() {
- let mut runtime = Runtime::default();
- for index in 0..crate::api::schema::panes::PANE_GRAPHICS_MAX_LAYERS_TOTAL {
- let key = (PaneId::from_raw(1), format!("layer-{index}"));
- runtime
- .slots
- .insert(key, Slot::test((1 << 31) | index as u32, None));
- }
- assert!(!runtime.can_add_slot(&(PaneId::from_raw(2), "extra".into())));
-
- let mut runtime = Runtime::default();
- let key = (PaneId::from_raw(1), "primary".into());
- runtime.slots.insert(
- key.clone(),
- Slot::test(
- 1 << 31,
- Some(Layer::inline(
- PaneGraphicsFormat::Rgba,
- 1,
- 1,
- vec![0; 4],
- PaneGraphicsPlacementParams::default(),
- 0,
- )),
- ),
- );
- assert!(runtime.can_store_inline(
- &key,
- crate::api::schema::panes::PANE_GRAPHICS_MAX_INLINE_BYTES_TOTAL,
- ));
- assert!(!runtime.can_store_inline(
- &(PaneId::from_raw(2), "primary".into()),
- crate::api::schema::panes::PANE_GRAPHICS_MAX_INLINE_BYTES_TOTAL,
- ));
- }
-}