mod consumer;
mod damage;
mod draw;
mod held;
#[doc(hidden)]
pub mod internal;
mod lock;
mod meta;
mod mips;
mod mirror;
mod pass;
mod siblings;
mod source;
mod stats;
mod writer;
pub use crate::image_geometry::{ImageOrientation, PixelRect};
pub use consumer::LiveImageConsumer;
pub use draw::{LiveImageDraw, LiveImageQuad};
pub use pass::LiveTextureStats;
pub use source::{LiveImageSource, LiveImageSourceBuilder};
pub use stats::{LiveImageAttachmentStats, LiveImageSourceStats, LiveImageStats};
pub use writer::{LiveImageDiffWriter, LiveImageWriteGuard, LiveImageWriter, RowsMut};
pub mod testing {
pub use super::mirror::{LiveImageMirror, MirrorReport};
pub use crate::wake::CountingWaker;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
#[non_exhaustive]
pub enum LivePixelFormat {
#[default]
Rgba8,
Bgra8,
Rgbx8,
Bgrx8,
}
impl LivePixelFormat {
pub const fn bytes_per_pixel(self) -> usize {
4
}
pub const fn is_opaque(self) -> bool {
matches!(self, Self::Rgbx8 | Self::Bgrx8)
}
pub const fn is_bgr(self) -> bool {
matches!(self, Self::Bgra8 | Self::Bgrx8)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
#[non_exhaustive]
pub enum ScalingFilter {
#[default]
Linear,
Nearest,
Trilinear,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum LiveImageStatus {
#[default]
Disconnected,
Waiting,
Live,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct LiveImageId(u64);
impl LiveImageId {
fn next() -> Self {
static NEXT: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(1);
Self(NEXT.fetch_add(1, std::sync::atomic::Ordering::Relaxed))
}
pub fn get(self) -> u64 {
self.0
}
}
impl std::fmt::Debug for LiveImageId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "#{}", self.0)
}
}
impl std::fmt::Display for LiveImageId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "#{}", self.0)
}
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[non_exhaustive]
pub enum LiveImageError {
#[error("a live image cannot be {width}x{height}: both sides must be at least 1")]
ZeroSize { width: u32, height: u32 },
#[error(
"a live image cannot be {width}x{height}: the largest side is {} pixels",
LiveImageSource::MAX_DIMENSION
)]
TooLarge { width: u32, height: u32 },
#[error("no memory for a live image buffer of {bytes} bytes")]
OutOfMemory { bytes: u64 },
#[error("the live image has no frame yet: resize it or write a whole frame first")]
NoFrame,
#[error("{rect:?} is not inside the {width}x{height} live image")]
OutOfBounds {
rect: PixelRect,
width: u32,
height: u32,
},
#[error("a stride of {stride} bytes is shorter than a row of {min}")]
StrideTooSmall { stride: usize, min: usize },
#[error("a buffer of {len} bytes is shorter than the {needed} the rows need")]
BufferTooSmall { len: usize, needed: usize },
#[error("the live image is locked")]
WouldBlock,
#[error("this writer's session was revoked by a newer one")]
Revoked,
}
#[derive(thiserror::Error)]
#[error("frame refused: {error}")]
pub struct RejectedFrame {
pub error: LiveImageError,
pub pixels: Vec<u8>,
}
impl std::fmt::Debug for RejectedFrame {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RejectedFrame")
.field("error", &self.error)
.field("pixels", &format_args!("{} bytes", self.pixels.len()))
.finish()
}
}
#[cfg(all(test, not(teksilo_loom)))]
mod tests;
#[cfg(all(test, teksilo_loom))]
mod loom_tests;