use crate::settings::{LiveComputeTarget, LiveTransfer};
#[must_use]
pub(super) const fn wants_display_only(
target: LiveComputeTarget,
transfer: LiveTransfer,
refused_on_this_connection: bool,
) -> bool {
matches!(transfer, LiveTransfer::FinalPicture)
&& !matches!(target, LiveComputeTarget::LocalOnly)
&& !refused_on_this_connection
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(super) struct RedispatchInputs {
pub(super) handoff_idle: bool,
pub(super) tab_visible: bool,
pub(super) epoch_live: bool,
pub(super) scene_stable: bool,
pub(super) gave_up_for_this_scene: bool,
}
#[must_use]
pub(super) const fn should_redispatch(inputs: RedispatchInputs) -> bool {
inputs.handoff_idle
&& inputs.tab_visible
&& !inputs.epoch_live
&& inputs.scene_stable
&& !inputs.gave_up_for_this_scene
}
#[must_use]
pub(super) fn served_by_label(
mode: LiveComputeTarget,
handoff_says_remote: bool,
combined_remote_samples: u32,
worker_label: &str,
) -> Option<String> {
match mode {
LiveComputeTarget::Both => (combined_remote_samples > 0).then(|| {
if worker_label.is_empty() {
"Local + Remote".to_string()
} else {
format!("Local + Remote ({worker_label})")
}
}),
LiveComputeTarget::RemoteOnly => handoff_says_remote.then(|| worker_label.to_string()),
LiveComputeTarget::LocalOnly => None,
}
}
#[cfg(test)]
mod tests {
use super::*;
const READY: RedispatchInputs = RedispatchInputs {
handoff_idle: true,
tab_visible: true,
epoch_live: false,
scene_stable: true,
gave_up_for_this_scene: false,
};
#[test]
fn a_settled_visible_view_with_a_released_epoch_redispatches() {
assert!(should_redispatch(READY));
}
#[test]
fn each_blocking_condition_alone_prevents_a_redispatch() {
let blocked = [
RedispatchInputs {
handoff_idle: false,
..READY
},
RedispatchInputs {
tab_visible: false,
..READY
},
RedispatchInputs {
epoch_live: true,
..READY
},
RedispatchInputs {
scene_stable: false,
..READY
},
RedispatchInputs {
gave_up_for_this_scene: true,
..READY
},
];
for inputs in blocked {
assert!(!should_redispatch(inputs), "{inputs:?}");
}
}
#[test]
fn a_given_up_scene_is_not_retried_but_a_new_scene_is() {
let same_scene = RedispatchInputs {
gave_up_for_this_scene: true,
..READY
};
assert!(!should_redispatch(same_scene));
assert!(should_redispatch(RedispatchInputs {
gave_up_for_this_scene: false,
..same_scene
}));
}
#[test]
fn both_mode_names_the_combination_and_never_flips_to_remote_only() {
let label = served_by_label(LiveComputeTarget::Both, false, 40, "GPU (X)");
assert_eq!(label.as_deref(), Some("Local + Remote (GPU (X))"));
let finished = served_by_label(LiveComputeTarget::Both, true, 256, "GPU (X)");
assert_eq!(finished.as_deref(), Some("Local + Remote (GPU (X))"));
assert_eq!(
served_by_label(LiveComputeTarget::Both, true, 0, "GPU (X)"),
None
);
assert_eq!(
served_by_label(LiveComputeTarget::Both, false, 3, "").as_deref(),
Some("Local + Remote")
);
}
#[test]
fn display_only_follows_the_live_transfer_until_the_connection_refuses_it() {
use LiveComputeTarget::{Both, LocalOnly, RemoteOnly};
use LiveTransfer::{FinalPicture, FullData};
assert!(wants_display_only(Both, FinalPicture, false));
assert!(wants_display_only(RemoteOnly, FinalPicture, false));
assert!(!wants_display_only(LocalOnly, FinalPicture, false));
assert!(!wants_display_only(Both, FullData, false));
assert!(
!wants_display_only(Both, FinalPicture, true),
"an UNSUPPORTED_REQUEST refusal falls back to full data"
);
}
#[test]
fn remote_only_and_local_only_keep_their_labels() {
assert_eq!(
served_by_label(LiveComputeTarget::RemoteOnly, true, 0, "CPU, 8 threads").as_deref(),
Some("CPU, 8 threads")
);
assert_eq!(
served_by_label(LiveComputeTarget::RemoteOnly, false, 99, "CPU"),
None
);
assert_eq!(
served_by_label(LiveComputeTarget::LocalOnly, true, 99, "CPU"),
None
);
}
}