use std::{num::NonZeroUsize, ptr::copy_nonoverlapping};
use crate::util::Pixel;
pub type CopyFn = unsafe fn(
dest: *mut u8,
dest_stride_bytes: NonZeroUsize,
src: *const u8,
src_stride_bytes: NonZeroUsize,
);
#[must_use]
#[inline]
pub fn select_copy<T: Pixel>(width: NonZeroUsize, height: NonZeroUsize) -> CopyFn {
match (width.get(), height.get()) {
(2, 2) => copy_impl::<T, 2, 2>,
(2, 4) => copy_impl::<T, 2, 4>,
(4, 2) => copy_impl::<T, 4, 2>,
(4, 4) => copy_impl::<T, 4, 4>,
(4, 8) => copy_impl::<T, 4, 8>,
(8, 1) => copy_impl::<T, 8, 1>,
(8, 2) => copy_impl::<T, 8, 2>,
(8, 4) => copy_impl::<T, 8, 4>,
(8, 8) => copy_impl::<T, 8, 8>,
(8, 16) => copy_impl::<T, 8, 16>,
(16, 1) => copy_impl::<T, 16, 1>,
(16, 2) => copy_impl::<T, 16, 2>,
(16, 4) => copy_impl::<T, 16, 4>,
(16, 8) => copy_impl::<T, 16, 8>,
(16, 16) => copy_impl::<T, 16, 16>,
(16, 32) => copy_impl::<T, 16, 32>,
(32, 8) => copy_impl::<T, 32, 8>,
(32, 16) => copy_impl::<T, 32, 16>,
(32, 32) => copy_impl::<T, 32, 32>,
(32, 64) => copy_impl::<T, 32, 64>,
(64, 16) => copy_impl::<T, 64, 16>,
(64, 32) => copy_impl::<T, 64, 32>,
(64, 64) => copy_impl::<T, 64, 64>,
(64, 128) => copy_impl::<T, 64, 128>,
(128, 32) => copy_impl::<T, 128, 32>,
(128, 64) => copy_impl::<T, 128, 64>,
(128, 128) => copy_impl::<T, 128, 128>,
_ => panic!("unsupported block size for copy: {}x{}", width, height),
}
}
unsafe fn copy_impl<T: Pixel, const WIDTH: usize, const HEIGHT: usize>(
dest: *mut u8,
dest_stride_bytes: NonZeroUsize,
src: *const u8,
src_stride_bytes: NonZeroUsize,
) {
for j in 0..HEIGHT {
copy_nonoverlapping(
src.add(src_stride_bytes.get() * j),
dest.add(dest_stride_bytes.get() * j),
WIDTH * size_of::<T>(),
);
}
}