use crate::{
bitmap::{BitmapRawData, BitmapRawDataMut},
colour::{read_from_bytes, write_as_bytes, BlendMode},
formats::{PixelFormatSpec, Rgba32},
math::{PixelBox, PixelPoint},
op::binary_map_pixel_data_with,
};
use super::{
dispatch::{BinaryDispatch, GenericBinary},
BinaryOpSpec,
};
#[cfg(target_arch = "x86_64")]
mod x86_64;
pub struct CompositeOp;
#[cfg(any(test, feature = "benchmark"))]
const _: () = {
use super::generate;
impl generate::BinaryInputSpec for CompositeOp {
fn gen<'l>() -> impl generate::ValueGeneratorList<'l, OutputTuple = Self::Params<'l>> {
(
generate::src_area,
generate::dst_point,
generate::blend_mode,
)
}
}
};
impl<'l> GenericBinary<(PixelBox, PixelPoint, BlendMode)> for CompositeOp {
fn perform<Format: PixelFormatSpec, SrcFormat: PixelFormatSpec>(
write_data: &mut dyn BitmapRawDataMut,
read_data: &dyn BitmapRawData,
params: &(PixelBox, PixelPoint, BlendMode),
) {
let (read_box, dst, bmode) = params;
binary_map_pixel_data_with::<0usize, Format, SrcFormat>(
write_data,
read_data,
read_box.size(),
*dst,
read_box.min,
|dst_slice, src_slice| {
let mut dx = 0;
let mut sx = 0;
while dx < dst_slice.len() {
let existing = read_from_bytes::<Format>(&dst_slice[dx..]);
let source = read_from_bytes::<SrcFormat>(&src_slice[sx..]);
let blended = bmode.blend(&source, &existing);
write_as_bytes::<Format>(&blended, &mut dst_slice[dx..]);
dx += Format::PIXEL_STRIDE;
sx += SrcFormat::PIXEL_STRIDE;
}
},
);
}
}
impl BinaryOpSpec for CompositeOp {
type Params<'l> = (PixelBox, PixelPoint, BlendMode);
fn build<'l>() -> BinaryDispatch<Self::Params<'l>> {
BinaryDispatch::from_generic::<Self>().with_avx::<Rgba32, Rgba32>(x86_64::avx_rgba32_rgba32)
}
}