mirx 0.45.0

MIRX binary image format — flat & chunk-based container for ahead-of-time UI assets
Documentation
use super::*;
use crate::{
    image::{
        ColorDescription, PlaneMemoryFlags, PlaneMemoryLayout, RawImageAsset, RegionError,
        SampleLayout, SurfaceCopyError, SurfaceFlags, UnitGroup,
    },
    media::{CodingRecord, UnitSelection},
};
use alloc::{vec, vec::Vec};

#[repr(align(64))]
struct Buffer([u8; 1024]);

#[test]
fn all_layouts_preserve_exact_samples_metadata_and_aligned_crop_geometry() {
    let mut layouts = 0;
    for id in 0..=u16::MAX {
        let layout = SampleLayout::new(id);
        if !layout.is_known() {
            continue;
        }
        let color = if layout.is_yuv() {
            ColorDescription::BT709_YUV_LIMITED
        } else if layout.is_alpha() {
            ColorDescription::NONE
        } else {
            ColorDescription::SRGB
        };
        let surface = SurfaceDescriptor::new(9, 5, layout, color)
            .unwrap()
            .with_flags(SurfaceFlags::from_bits_retain(0x8000))
            .with_pixel_aspect(4, 3)
            .unwrap();
        let buffers: Vec<Vec<u8>> = surface
            .planes()
            .enumerate()
            .map(|(index, plane)| {
                (0..plane.minimum_stride().unwrap() * plane.height())
                    .map(|n| {
                        (n as u8)
                            .wrapping_mul(59)
                            .wrapping_add(index as u8 * 31 + 0x97)
                    })
                    .collect()
            })
            .collect();
        let planes: Vec<_> = buffers.iter().map(Vec::as_slice).collect();
        let samples: Vec<_> = buffers.iter().flatten().copied().collect();
        let palette = vec![0; layout.color_table_entries().unwrap_or(0) as usize * 4];
        let mut asset = RawImageAsset::new(surface, &planes);
        if !palette.is_empty() {
            asset = asset.with_color_table(&palette);
        }
        let source = asset.view().unwrap();
        let region = if layout.is_yuv() {
            surface.region(2, 2, 7, 3).unwrap()
        } else {
            surface.region(3, 1, 5, 3).unwrap()
        };
        let plan = surface
            .region_plan(
                region,
                SurfaceRequirements::new()
                    .with_base_alignment(crate::ByteAlignment::new(64).unwrap())
                    .with_plane_alignment(crate::ByteAlignment::new(64).unwrap())
                    .with_stride_multiple(64)
                    .with_width_multiple(4)
                    .with_height_multiple(4),
            )
            .unwrap();
        let memory = plan.memory_plan();
        assert_eq!(
            memory.surface(),
            surface.with_extent(region.width(), region.height())
        );
        let mut expected = Buffer([0xa5; 1024]);
        expected.0[..memory.byte_len() as usize].fill(0);
        for (index, plane) in source.planes().enumerate() {
            let crop = plan.plane_region(index as u8).unwrap();
            let target = memory.plane(index as u8).unwrap();
            let bpp = u64::from(plane.geometry().bits_per_element());
            for y in 0..crop.height() {
                let row = plane.row(y + crop.y()).unwrap().unwrap();
                for bit in 0..u64::from(crop.width()) * bpp {
                    let s = (u64::from(crop.x()) * bpp + bit) as usize;
                    let t = target.data_offset() as usize
                        + y as usize * target.stride() as usize
                        + bit as usize / 8;
                    expected.0[t] |= (row[s / 8] >> (7 - s % 8) & 1) << (7 - bit % 8);
                }
            }
        }
        let mut output = Buffer([0xa5; 1024]);
        let copied = source.copy_region_into(&mut output.0, plan).unwrap();
        assert!(copied.data_addresses_are_aligned());
        assert_eq!(copied.color_table(), source.color_table());
        assert_eq!(output.0, expected.0, "RAW {layout:?}");
        let group = UnitGroup::builder(surface, CodingRecord::RAW, &samples)
            .build()
            .unwrap();
        let unit = group
            .get(0)
            .unwrap()
            .decode_plan(SurfaceRequirements::new())
            .unwrap();
        let mut workspace = vec![0; unit.memory_plan().byte_len() as usize];
        let decoded = unit.decode_into(&mut workspace).unwrap();
        let mut output = Buffer([0xa5; 1024]);
        output.0[..memory.byte_len() as usize].fill(0);
        decoded.copy_region_into(&mut output.0, plan).unwrap();
        assert_eq!(output.0, expected.0, "unit {layout:?}");
        layouts += 1;
    }
    assert_eq!(layouts, 22);
}

#[test]
fn clipped_sub_byte_units_preserve_neighbours_and_skip_nonintersections() {
    let surface = SurfaceDescriptor::new(9, 1, SampleLayout::A1, ColorDescription::NONE).unwrap();
    let cells = 1u32.to_le_bytes();
    let selection = UnitSelection::list(3, &cells).unwrap();
    let group = UnitGroup::builder(surface, CodingRecord::RAW, &[0xe0])
        .with_tiles(3, 1)
        .with_selection(selection)
        .build()
        .unwrap();
    let mut workspace = [0; 1];
    let unit = group
        .get(0)
        .unwrap()
        .decode_plan(SurfaceRequirements::new())
        .unwrap();
    let decoded = unit.decode_into(&mut workspace).unwrap();
    for (x, width, expected) in [(2, 6, 0x7a), (4, 4, 0xda), (5, 4, 0xda), (0, 3, 0x5a)] {
        let plan = surface
            .region_plan(
                surface.region(x, 0, width, 1).unwrap(),
                SurfaceRequirements::new().with_stride_multiple(8),
            )
            .unwrap();
        let mut output = [0x5a; 16];
        decoded.copy_region_into(&mut output, plan).unwrap();
        assert_eq!(output[0], expected, "x={x}");
        assert_eq!(&output[1..], &[0x5a; 15]);
    }
}

#[test]
fn region_and_buffer_errors_never_change_output() {
    let surface = SurfaceDescriptor::new(
        5,
        3,
        SampleLayout::NV12,
        ColorDescription::BT709_YUV_LIMITED,
    )
    .unwrap();
    for region in [
        Region::new(1, 0, 2, 2).unwrap(),
        Region::new(0, 0, 3, 2).unwrap(),
        Region::new(0, 1, 2, 2).unwrap(),
        Region::new(0, 0, 2, 1).unwrap(),
    ] {
        assert!(matches!(
            surface.region_plan(region, SurfaceRequirements::new()),
            Err(SurfacePlanError::Region(
                RegionError::UnalignedPlaneRegion { .. }
            ))
        ));
    }
    assert!(matches!(
        surface.region_plan(Region::new(4, 0, 2, 2).unwrap(), SurfaceRequirements::new()),
        Err(SurfacePlanError::Region(RegionError::OutOfBounds))
    ));
    assert!(
        SurfaceDescriptor::new(0, 0, SampleLayout::new(u16::MAX), ColorDescription::NONE).is_err()
    );
    let surface = SurfaceDescriptor::new(4, 1, SampleLayout::A8, ColorDescription::NONE).unwrap();
    let source = RawImageAsset::new(surface, &[&[1, 2, 3, 4]])
        .view()
        .unwrap();
    let plan = surface
        .region_plan(
            surface.region(1, 0, 2, 1).unwrap(),
            SurfaceRequirements::new().with_base_alignment(crate::ByteAlignment::new(64).unwrap()),
        )
        .unwrap();
    let mut output = Buffer([0xa5; 1024]);
    assert!(matches!(
        source.copy_region_into(&mut output.0[..1], plan),
        Err(SurfaceCopyError::Output(_))
    ));
    assert!(matches!(
        source.copy_region_into(&mut output.0[1..], plan),
        Err(SurfaceCopyError::Output(_))
    ));
    let other = surface
        .with_extent(5, 1)
        .region_plan(Region::new(1, 0, 2, 1).unwrap(), SurfaceRequirements::new())
        .unwrap();
    assert_eq!(
        source.copy_region_into(&mut output.0, other),
        Err(SurfaceCopyError::SurfaceMismatch)
    );
    let layout = PlaneMemoryLayout::builder(surface.plane(0).unwrap())
        .with_flags(PlaneMemoryFlags::from_bits_retain(0x80))
        .build()
        .unwrap();
    let layouts = [layout];
    let source = RawImageAsset::new(surface, &[&[1, 2, 3, 4]])
        .with_memory_layouts(&layouts)
        .view()
        .unwrap();
    assert!(matches!(
        source.copy_region_into(&mut output.0, plan),
        Err(SurfaceCopyError::UnsupportedPlaneFlags { .. })
    ));
    assert_eq!(output.0, [0xa5; 1024]);
}

#[test]
fn empty_extents_do_not_visit_rows_or_require_storage() {
    for (width, height) in [(0, u32::MAX), (u32::MAX, 0)] {
        let surface =
            SurfaceDescriptor::new(width, height, SampleLayout::A1, ColorDescription::NONE)
                .unwrap();
        let plan = surface
            .region_plan(
                surface.region(0, 0, width, height).unwrap(),
                SurfaceRequirements::new(),
            )
            .unwrap();
        let source = RawImageAsset::new(surface, &[&[]]).view().unwrap();
        let mut output = [0xa5; 8];
        assert_eq!(plan.memory_plan().byte_len(), 0);
        source.copy_region_into(&mut output, plan).unwrap();
        assert_eq!(output, [0xa5; 8]);
    }
}