#[cfg(any(
target_arch = "aarch64",
target_arch = "x86_64",
target_arch = "wasm32"
))]
use crate::row::arch;
#[cfg(target_arch = "aarch64")]
use crate::row::neon_available;
#[cfg(target_arch = "wasm32")]
use crate::row::simd128_available;
#[cfg(target_arch = "x86_64")]
use crate::row::{avx2_available, avx512_available, sse41_available};
use crate::{
ColorMatrix,
row::{rgb_row_bytes, rgb_row_elems, rgba_row_bytes, rgba_row_elems, scalar},
};
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn gbr_to_rgb_high_bit_row<const BITS: u32, const BE: bool>(
g: &[u16],
b: &[u16],
r: &[u16],
rgb_out: &mut [u8],
width: usize,
use_simd: bool,
) {
const {
assert!(
matches!(BITS, 9 | 10 | 12 | 14 | 16),
"BITS must be one of 9, 10, 12, 14, or 16"
)
};
let out_min = rgb_row_bytes(width);
assert!(g.len() >= width, "g row too short");
assert!(b.len() >= width, "b row too short");
assert!(r.len() >= width, "r row too short");
assert!(rgb_out.len() >= out_min, "rgb_out row too short");
if use_simd {
cfg_select! {
target_arch = "aarch64" => {
if neon_available() {
unsafe { arch::neon::gbr_to_rgb_high_bit_row::<BITS, BE>(g, b, r, rgb_out, width); }
return;
}
},
target_arch = "x86_64" => {
if avx512_available() {
unsafe { arch::x86_avx512::gbr_to_rgb_high_bit_row::<BITS, BE>(g, b, r, rgb_out, width); }
return;
}
if avx2_available() {
unsafe { arch::x86_avx2::gbr_to_rgb_high_bit_row::<BITS, BE>(g, b, r, rgb_out, width); }
return;
}
if sse41_available() {
unsafe { arch::x86_sse41::gbr_to_rgb_high_bit_row::<BITS, BE>(g, b, r, rgb_out, width); }
return;
}
},
target_arch = "wasm32" => {
if simd128_available() {
unsafe {
arch::wasm_simd128::gbr_to_rgb_high_bit_row::<BITS, BE>(g, b, r, rgb_out, width);
}
return;
}
},
_ => {}
}
}
scalar::gbr_to_rgb_high_bit_row::<BITS, BE>(g, b, r, rgb_out, width);
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn gbr_to_rgb_u16_high_bit_row<const BITS: u32, const BE: bool>(
g: &[u16],
b: &[u16],
r: &[u16],
rgb_u16_out: &mut [u16],
width: usize,
use_simd: bool,
) {
const {
assert!(
matches!(BITS, 9 | 10 | 12 | 14 | 16),
"BITS must be one of 9, 10, 12, 14, or 16"
)
};
let out_min = rgb_row_elems(width);
assert!(g.len() >= width, "g row too short");
assert!(b.len() >= width, "b row too short");
assert!(r.len() >= width, "r row too short");
assert!(rgb_u16_out.len() >= out_min, "rgb_u16_out row too short");
if use_simd {
cfg_select! {
target_arch = "aarch64" => {
if neon_available() {
unsafe {
arch::neon::gbr_to_rgb_u16_high_bit_row::<BITS, BE>(g, b, r, rgb_u16_out, width);
}
return;
}
},
target_arch = "x86_64" => {
if avx512_available() {
unsafe {
arch::x86_avx512::gbr_to_rgb_u16_high_bit_row::<BITS, BE>(
g, b, r, rgb_u16_out, width,
);
}
return;
}
if avx2_available() {
unsafe {
arch::x86_avx2::gbr_to_rgb_u16_high_bit_row::<BITS, BE>(
g, b, r, rgb_u16_out, width,
);
}
return;
}
if sse41_available() {
unsafe {
arch::x86_sse41::gbr_to_rgb_u16_high_bit_row::<BITS, BE>(
g, b, r, rgb_u16_out, width,
);
}
return;
}
},
target_arch = "wasm32" => {
if simd128_available() {
unsafe {
arch::wasm_simd128::gbr_to_rgb_u16_high_bit_row::<BITS, BE>(
g, b, r, rgb_u16_out, width,
);
}
return;
}
},
_ => {}
}
}
scalar::gbr_to_rgb_u16_high_bit_row::<BITS, BE>(g, b, r, rgb_u16_out, width);
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn gbr_to_rgba_opaque_high_bit_row<const BITS: u32, const BE: bool>(
g: &[u16],
b: &[u16],
r: &[u16],
rgba_out: &mut [u8],
width: usize,
use_simd: bool,
) {
const {
assert!(
matches!(BITS, 9 | 10 | 12 | 14 | 16),
"BITS must be one of 9, 10, 12, 14, or 16"
)
};
let out_min = rgba_row_bytes(width);
assert!(g.len() >= width, "g row too short");
assert!(b.len() >= width, "b row too short");
assert!(r.len() >= width, "r row too short");
assert!(rgba_out.len() >= out_min, "rgba_out row too short");
if use_simd {
cfg_select! {
target_arch = "aarch64" => {
if neon_available() {
unsafe {
arch::neon::gbr_to_rgba_opaque_high_bit_row::<BITS, BE>(g, b, r, rgba_out, width);
}
return;
}
},
target_arch = "x86_64" => {
if avx512_available() {
unsafe {
arch::x86_avx512::gbr_to_rgba_opaque_high_bit_row::<BITS, BE>(
g, b, r, rgba_out, width,
);
}
return;
}
if avx2_available() {
unsafe {
arch::x86_avx2::gbr_to_rgba_opaque_high_bit_row::<BITS, BE>(
g, b, r, rgba_out, width,
);
}
return;
}
if sse41_available() {
unsafe {
arch::x86_sse41::gbr_to_rgba_opaque_high_bit_row::<BITS, BE>(
g, b, r, rgba_out, width,
);
}
return;
}
},
target_arch = "wasm32" => {
if simd128_available() {
unsafe {
arch::wasm_simd128::gbr_to_rgba_opaque_high_bit_row::<BITS, BE>(
g, b, r, rgba_out, width,
);
}
return;
}
},
_ => {}
}
}
scalar::gbr_to_rgba_opaque_high_bit_row::<BITS, BE>(g, b, r, rgba_out, width);
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn gbr_to_rgba_opaque_u16_high_bit_row<const BITS: u32, const BE: bool>(
g: &[u16],
b: &[u16],
r: &[u16],
rgba_u16_out: &mut [u16],
width: usize,
use_simd: bool,
) {
const {
assert!(
matches!(BITS, 9 | 10 | 12 | 14 | 16),
"BITS must be one of 9, 10, 12, 14, or 16"
)
};
let out_min = rgba_row_elems(width);
assert!(g.len() >= width, "g row too short");
assert!(b.len() >= width, "b row too short");
assert!(r.len() >= width, "r row too short");
assert!(rgba_u16_out.len() >= out_min, "rgba_u16_out row too short");
if use_simd {
cfg_select! {
target_arch = "aarch64" => {
if neon_available() {
unsafe {
arch::neon::gbr_to_rgba_opaque_u16_high_bit_row::<BITS, BE>(
g, b, r, rgba_u16_out, width,
);
}
return;
}
},
target_arch = "x86_64" => {
if avx512_available() {
unsafe {
arch::x86_avx512::gbr_to_rgba_opaque_u16_high_bit_row::<BITS, BE>(
g, b, r, rgba_u16_out, width,
);
}
return;
}
if avx2_available() {
unsafe {
arch::x86_avx2::gbr_to_rgba_opaque_u16_high_bit_row::<BITS, BE>(
g, b, r, rgba_u16_out, width,
);
}
return;
}
if sse41_available() {
unsafe {
arch::x86_sse41::gbr_to_rgba_opaque_u16_high_bit_row::<BITS, BE>(
g, b, r, rgba_u16_out, width,
);
}
return;
}
},
target_arch = "wasm32" => {
if simd128_available() {
unsafe {
arch::wasm_simd128::gbr_to_rgba_opaque_u16_high_bit_row::<BITS, BE>(
g, b, r, rgba_u16_out, width,
);
}
return;
}
},
_ => {}
}
}
scalar::gbr_to_rgba_opaque_u16_high_bit_row::<BITS, BE>(g, b, r, rgba_u16_out, width);
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[allow(clippy::too_many_arguments)]
pub fn gbra_to_rgba_high_bit_row<const BITS: u32, const BE: bool>(
g: &[u16],
b: &[u16],
r: &[u16],
a: &[u16],
rgba_out: &mut [u8],
width: usize,
use_simd: bool,
) {
const {
assert!(
matches!(BITS, 10 | 12 | 14 | 16),
"BITS must be one of 10, 12, 14, or 16 (FFmpeg has no GBRAP9)"
)
};
let out_min = rgba_row_bytes(width);
assert!(g.len() >= width, "g row too short");
assert!(b.len() >= width, "b row too short");
assert!(r.len() >= width, "r row too short");
assert!(a.len() >= width, "a row too short");
assert!(rgba_out.len() >= out_min, "rgba_out row too short");
if use_simd {
cfg_select! {
target_arch = "aarch64" => {
if neon_available() {
unsafe {
arch::neon::gbra_to_rgba_high_bit_row::<BITS, BE>(g, b, r, a, rgba_out, width);
}
return;
}
},
target_arch = "x86_64" => {
if avx512_available() {
unsafe {
arch::x86_avx512::gbra_to_rgba_high_bit_row::<BITS, BE>(g, b, r, a, rgba_out, width);
}
return;
}
if avx2_available() {
unsafe {
arch::x86_avx2::gbra_to_rgba_high_bit_row::<BITS, BE>(g, b, r, a, rgba_out, width);
}
return;
}
if sse41_available() {
unsafe {
arch::x86_sse41::gbra_to_rgba_high_bit_row::<BITS, BE>(g, b, r, a, rgba_out, width);
}
return;
}
},
target_arch = "wasm32" => {
if simd128_available() {
unsafe {
arch::wasm_simd128::gbra_to_rgba_high_bit_row::<BITS, BE>(
g, b, r, a, rgba_out, width,
);
}
return;
}
},
_ => {}
}
}
scalar::gbra_to_rgba_high_bit_row::<BITS, BE>(g, b, r, a, rgba_out, width);
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[allow(clippy::too_many_arguments)]
pub fn gbra_to_rgba_u16_high_bit_row<const BITS: u32, const BE: bool>(
g: &[u16],
b: &[u16],
r: &[u16],
a: &[u16],
rgba_u16_out: &mut [u16],
width: usize,
use_simd: bool,
) {
const {
assert!(
matches!(BITS, 10 | 12 | 14 | 16),
"BITS must be one of 10, 12, 14, or 16 (FFmpeg has no GBRAP9)"
)
};
let out_min = rgba_row_elems(width);
assert!(g.len() >= width, "g row too short");
assert!(b.len() >= width, "b row too short");
assert!(r.len() >= width, "r row too short");
assert!(a.len() >= width, "a row too short");
assert!(rgba_u16_out.len() >= out_min, "rgba_u16_out row too short");
if use_simd {
cfg_select! {
target_arch = "aarch64" => {
if neon_available() {
unsafe {
arch::neon::gbra_to_rgba_u16_high_bit_row::<BITS, BE>(
g, b, r, a, rgba_u16_out, width,
);
}
return;
}
},
target_arch = "x86_64" => {
if avx512_available() {
unsafe {
arch::x86_avx512::gbra_to_rgba_u16_high_bit_row::<BITS, BE>(
g, b, r, a, rgba_u16_out, width,
);
}
return;
}
if avx2_available() {
unsafe {
arch::x86_avx2::gbra_to_rgba_u16_high_bit_row::<BITS, BE>(
g, b, r, a, rgba_u16_out, width,
);
}
return;
}
if sse41_available() {
unsafe {
arch::x86_sse41::gbra_to_rgba_u16_high_bit_row::<BITS, BE>(
g, b, r, a, rgba_u16_out, width,
);
}
return;
}
},
target_arch = "wasm32" => {
if simd128_available() {
unsafe {
arch::wasm_simd128::gbra_to_rgba_u16_high_bit_row::<BITS, BE>(
g, b, r, a, rgba_u16_out, width,
);
}
return;
}
},
_ => {}
}
}
scalar::gbra_to_rgba_u16_high_bit_row::<BITS, BE>(g, b, r, a, rgba_u16_out, width);
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[allow(clippy::too_many_arguments)]
pub fn gbr_to_luma_u16_high_bit_row<const BITS: u32, const BE: bool>(
g: &[u16],
b: &[u16],
r: &[u16],
luma_out: &mut [u16],
width: usize,
matrix: ColorMatrix,
full_range: bool,
_use_simd: bool,
) {
const {
assert!(
matches!(BITS, 9 | 10 | 12 | 14 | 16),
"BITS must be one of 9, 10, 12, 14, or 16"
)
};
assert!(g.len() >= width, "g row too short");
assert!(b.len() >= width, "b row too short");
assert!(r.len() >= width, "r row too short");
assert!(luma_out.len() >= width, "luma_out row too short");
scalar::gbr_to_luma_u16_high_bit_row::<BITS, BE>(g, b, r, luma_out, width, matrix, full_range);
}