Skip to main content

motion_core/
pixels.rs

1//! Immutable image sampling contracts, independent of decoding and rendering.
2
3use std::{any::Any, fmt::Debug};
4
5/// Texture reconstruction requested by a drawing command.
6#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
7#[cfg_attr(
8    feature = "serde",
9    derive(serde::Serialize, serde::Deserialize),
10    serde(rename_all = "snake_case")
11)]
12#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
13pub enum Sampling {
14    /// Nearest base-level texel.
15    Nearest,
16    /// Bilinear base-level reconstruction.
17    Bilinear,
18    /// Bilinear reconstruction between adjacent mip levels.
19    #[default]
20    Trilinear,
21}
22
23/// A predecoded immutable linear-premultiplied image mip chain.
24/// Content owns decoding/storage; backends consume this shared logical contract.
25pub trait ImagePixels: Any + Debug + Send + Sync {
26    /// Base-level width in texels.
27    fn width(&self) -> u32;
28
29    /// Base-level height in texels.
30    fn height(&self) -> u32;
31
32    /// Number of immutable mip levels.
33    fn level_count(&self) -> usize;
34
35    /// Width/height of an existing mip level.
36    fn level_size(&self, level: usize) -> (u32, u32);
37
38    /// One in-bounds finite linear-premultiplied texel.
39    fn texel(&self, level: usize, column: usize, row: usize) -> [f32; 4];
40
41    /// Appends every texel of an existing level in row-major order, four `f32` each.
42    /// Overriding this avoids one dynamic call per texel for backends that upload whole levels.
43    fn extend_level(&self, level: usize, out: &mut Vec<f32>) {
44        let (width, height) = self.level_size(level);
45        out.reserve(width as usize * height as usize * 4);
46        for row in 0..height as usize {
47            for column in 0..width as usize {
48                out.extend(self.texel(level, column, row));
49            }
50        }
51    }
52
53    /// Whether another implementation owns the same immutable pixel content.
54    fn content_eq(&self, other: &dyn ImagePixels) -> bool;
55
56    /// Concrete storage identity, resolved only by its owning content implementation.
57    fn as_any(&self) -> &dyn Any;
58}