#[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, rgba_row_bytes, scalar},
};
#[cfg_attr(not(tarpaulin), inline(always))]
#[allow(clippy::too_many_arguments)]
pub fn nv12_to_rgb_row(
y: &[u8],
uv_half: &[u8],
rgb_out: &mut [u8],
width: usize,
matrix: ColorMatrix,
full_range: bool,
use_simd: bool,
) {
assert_eq!(width & 1, 0, "NV12 requires even width");
let rgb_min = rgb_row_bytes(width);
assert!(y.len() >= width, "y row too short");
assert!(uv_half.len() >= width, "uv_half row too short");
assert!(rgb_out.len() >= rgb_min, "rgb_out row too short");
if use_simd {
cfg_select! {
target_arch = "aarch64" => {
if neon_available() {
unsafe {
arch::neon::nv12_to_rgb_row(y, uv_half, rgb_out, width, matrix, full_range);
}
return;
}
},
target_arch = "x86_64" => {
if avx512_available() {
unsafe {
arch::x86_avx512::nv12_to_rgb_row(y, uv_half, rgb_out, width, matrix, full_range);
}
return;
}
if avx2_available() {
unsafe {
arch::x86_avx2::nv12_to_rgb_row(y, uv_half, rgb_out, width, matrix, full_range);
}
return;
}
if sse41_available() {
unsafe {
arch::x86_sse41::nv12_to_rgb_row(y, uv_half, rgb_out, width, matrix, full_range);
}
return;
}
},
target_arch = "wasm32" => {
if simd128_available() {
unsafe {
arch::wasm_simd128::nv12_to_rgb_row(y, uv_half, rgb_out, width, matrix, full_range);
}
return;
}
},
_ => {
}
}
}
scalar::nv12_to_rgb_row(y, uv_half, rgb_out, width, matrix, full_range);
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[allow(clippy::too_many_arguments)]
pub fn nv21_to_rgb_row(
y: &[u8],
vu_half: &[u8],
rgb_out: &mut [u8],
width: usize,
matrix: ColorMatrix,
full_range: bool,
use_simd: bool,
) {
assert_eq!(width & 1, 0, "NV21 requires even width");
let rgb_min = rgb_row_bytes(width);
assert!(y.len() >= width, "y row too short");
assert!(vu_half.len() >= width, "vu_half row too short");
assert!(rgb_out.len() >= rgb_min, "rgb_out row too short");
if use_simd {
cfg_select! {
target_arch = "aarch64" => {
if neon_available() {
unsafe {
arch::neon::nv21_to_rgb_row(y, vu_half, rgb_out, width, matrix, full_range);
}
return;
}
},
target_arch = "x86_64" => {
if avx512_available() {
unsafe {
arch::x86_avx512::nv21_to_rgb_row(y, vu_half, rgb_out, width, matrix, full_range);
}
return;
}
if avx2_available() {
unsafe {
arch::x86_avx2::nv21_to_rgb_row(y, vu_half, rgb_out, width, matrix, full_range);
}
return;
}
if sse41_available() {
unsafe {
arch::x86_sse41::nv21_to_rgb_row(y, vu_half, rgb_out, width, matrix, full_range);
}
return;
}
},
target_arch = "wasm32" => {
if simd128_available() {
unsafe {
arch::wasm_simd128::nv21_to_rgb_row(y, vu_half, rgb_out, width, matrix, full_range);
}
return;
}
},
_ => {
}
}
}
scalar::nv21_to_rgb_row(y, vu_half, rgb_out, width, matrix, full_range);
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[allow(clippy::too_many_arguments)]
pub fn nv12_to_rgba_row(
y: &[u8],
uv_half: &[u8],
rgba_out: &mut [u8],
width: usize,
matrix: ColorMatrix,
full_range: bool,
use_simd: bool,
) {
assert_eq!(width & 1, 0, "NV12 requires even width");
let rgba_min = rgba_row_bytes(width);
assert!(y.len() >= width, "y row too short");
assert!(uv_half.len() >= width, "uv_half row too short");
assert!(rgba_out.len() >= rgba_min, "rgba_out row too short");
if use_simd {
cfg_select! {
target_arch = "aarch64" => {
if neon_available() {
unsafe {
arch::neon::nv12_to_rgba_row(y, uv_half, rgba_out, width, matrix, full_range);
}
return;
}
},
target_arch = "x86_64" => {
if avx512_available() {
unsafe {
arch::x86_avx512::nv12_to_rgba_row(y, uv_half, rgba_out, width, matrix, full_range);
}
return;
}
if avx2_available() {
unsafe {
arch::x86_avx2::nv12_to_rgba_row(y, uv_half, rgba_out, width, matrix, full_range);
}
return;
}
if sse41_available() {
unsafe {
arch::x86_sse41::nv12_to_rgba_row(y, uv_half, rgba_out, width, matrix, full_range);
}
return;
}
},
target_arch = "wasm32" => {
if simd128_available() {
unsafe {
arch::wasm_simd128::nv12_to_rgba_row(y, uv_half, rgba_out, width, matrix, full_range);
}
return;
}
},
_ => {}
}
}
scalar::nv12_to_rgba_row(y, uv_half, rgba_out, width, matrix, full_range);
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[allow(clippy::too_many_arguments)]
pub fn nv21_to_rgba_row(
y: &[u8],
vu_half: &[u8],
rgba_out: &mut [u8],
width: usize,
matrix: ColorMatrix,
full_range: bool,
use_simd: bool,
) {
assert_eq!(width & 1, 0, "NV21 requires even width");
let rgba_min = rgba_row_bytes(width);
assert!(y.len() >= width, "y row too short");
assert!(vu_half.len() >= width, "vu_half row too short");
assert!(rgba_out.len() >= rgba_min, "rgba_out row too short");
if use_simd {
cfg_select! {
target_arch = "aarch64" => {
if neon_available() {
unsafe {
arch::neon::nv21_to_rgba_row(y, vu_half, rgba_out, width, matrix, full_range);
}
return;
}
},
target_arch = "x86_64" => {
if avx512_available() {
unsafe {
arch::x86_avx512::nv21_to_rgba_row(y, vu_half, rgba_out, width, matrix, full_range);
}
return;
}
if avx2_available() {
unsafe {
arch::x86_avx2::nv21_to_rgba_row(y, vu_half, rgba_out, width, matrix, full_range);
}
return;
}
if sse41_available() {
unsafe {
arch::x86_sse41::nv21_to_rgba_row(y, vu_half, rgba_out, width, matrix, full_range);
}
return;
}
},
target_arch = "wasm32" => {
if simd128_available() {
unsafe {
arch::wasm_simd128::nv21_to_rgba_row(y, vu_half, rgba_out, width, matrix, full_range);
}
return;
}
},
_ => {}
}
}
scalar::nv21_to_rgba_row(y, vu_half, rgba_out, width, matrix, full_range);
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[allow(clippy::too_many_arguments)]
pub fn nv24_to_rgb_row(
y: &[u8],
uv: &[u8],
rgb_out: &mut [u8],
width: usize,
matrix: ColorMatrix,
full_range: bool,
use_simd: bool,
) {
let rgb_min = rgb_row_bytes(width);
let uv_min = match width.checked_mul(2) {
Some(n) => n,
None => panic!("width ({width}) x 2 overflows usize"),
};
assert!(y.len() >= width, "y row too short");
assert!(uv.len() >= uv_min, "uv row too short");
assert!(rgb_out.len() >= rgb_min, "rgb_out row too short");
if use_simd {
cfg_select! {
target_arch = "aarch64" => {
if neon_available() {
unsafe {
arch::neon::nv24_to_rgb_row(y, uv, rgb_out, width, matrix, full_range);
}
return;
}
},
target_arch = "x86_64" => {
if avx512_available() {
unsafe {
arch::x86_avx512::nv24_to_rgb_row(y, uv, rgb_out, width, matrix, full_range);
}
return;
}
if avx2_available() {
unsafe {
arch::x86_avx2::nv24_to_rgb_row(y, uv, rgb_out, width, matrix, full_range);
}
return;
}
if sse41_available() {
unsafe {
arch::x86_sse41::nv24_to_rgb_row(y, uv, rgb_out, width, matrix, full_range);
}
return;
}
},
target_arch = "wasm32" => {
if simd128_available() {
unsafe {
arch::wasm_simd128::nv24_to_rgb_row(y, uv, rgb_out, width, matrix, full_range);
}
return;
}
},
_ => {
}
}
}
scalar::nv24_to_rgb_row(y, uv, rgb_out, width, matrix, full_range);
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[allow(clippy::too_many_arguments)]
pub fn nv42_to_rgb_row(
y: &[u8],
vu: &[u8],
rgb_out: &mut [u8],
width: usize,
matrix: ColorMatrix,
full_range: bool,
use_simd: bool,
) {
let rgb_min = rgb_row_bytes(width);
let vu_min = match width.checked_mul(2) {
Some(n) => n,
None => panic!("width ({width}) x 2 overflows usize"),
};
assert!(y.len() >= width, "y row too short");
assert!(vu.len() >= vu_min, "vu row too short");
assert!(rgb_out.len() >= rgb_min, "rgb_out row too short");
if use_simd {
cfg_select! {
target_arch = "aarch64" => {
if neon_available() {
unsafe {
arch::neon::nv42_to_rgb_row(y, vu, rgb_out, width, matrix, full_range);
}
return;
}
},
target_arch = "x86_64" => {
if avx512_available() {
unsafe {
arch::x86_avx512::nv42_to_rgb_row(y, vu, rgb_out, width, matrix, full_range);
}
return;
}
if avx2_available() {
unsafe {
arch::x86_avx2::nv42_to_rgb_row(y, vu, rgb_out, width, matrix, full_range);
}
return;
}
if sse41_available() {
unsafe {
arch::x86_sse41::nv42_to_rgb_row(y, vu, rgb_out, width, matrix, full_range);
}
return;
}
},
target_arch = "wasm32" => {
if simd128_available() {
unsafe {
arch::wasm_simd128::nv42_to_rgb_row(y, vu, rgb_out, width, matrix, full_range);
}
return;
}
},
_ => {
}
}
}
scalar::nv42_to_rgb_row(y, vu, rgb_out, width, matrix, full_range);
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[allow(clippy::too_many_arguments)]
pub fn nv24_to_rgba_row(
y: &[u8],
uv: &[u8],
rgba_out: &mut [u8],
width: usize,
matrix: ColorMatrix,
full_range: bool,
use_simd: bool,
) {
let rgba_min = rgba_row_bytes(width);
let uv_min = match width.checked_mul(2) {
Some(n) => n,
None => panic!("width ({width}) x 2 overflows usize"),
};
assert!(y.len() >= width, "y row too short");
assert!(uv.len() >= uv_min, "uv row too short");
assert!(rgba_out.len() >= rgba_min, "rgba_out row too short");
if use_simd {
cfg_select! {
target_arch = "aarch64" => {
if neon_available() {
unsafe {
arch::neon::nv24_to_rgba_row(y, uv, rgba_out, width, matrix, full_range);
}
return;
}
},
target_arch = "x86_64" => {
if avx512_available() {
unsafe {
arch::x86_avx512::nv24_to_rgba_row(y, uv, rgba_out, width, matrix, full_range);
}
return;
}
if avx2_available() {
unsafe {
arch::x86_avx2::nv24_to_rgba_row(y, uv, rgba_out, width, matrix, full_range);
}
return;
}
if sse41_available() {
unsafe {
arch::x86_sse41::nv24_to_rgba_row(y, uv, rgba_out, width, matrix, full_range);
}
return;
}
},
target_arch = "wasm32" => {
if simd128_available() {
unsafe {
arch::wasm_simd128::nv24_to_rgba_row(y, uv, rgba_out, width, matrix, full_range);
}
return;
}
},
_ => {}
}
}
scalar::nv24_to_rgba_row(y, uv, rgba_out, width, matrix, full_range);
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[allow(clippy::too_many_arguments)]
pub fn nv42_to_rgba_row(
y: &[u8],
vu: &[u8],
rgba_out: &mut [u8],
width: usize,
matrix: ColorMatrix,
full_range: bool,
use_simd: bool,
) {
let rgba_min = rgba_row_bytes(width);
let vu_min = match width.checked_mul(2) {
Some(n) => n,
None => panic!("width ({width}) x 2 overflows usize"),
};
assert!(y.len() >= width, "y row too short");
assert!(vu.len() >= vu_min, "vu row too short");
assert!(rgba_out.len() >= rgba_min, "rgba_out row too short");
if use_simd {
cfg_select! {
target_arch = "aarch64" => {
if neon_available() {
unsafe {
arch::neon::nv42_to_rgba_row(y, vu, rgba_out, width, matrix, full_range);
}
return;
}
},
target_arch = "x86_64" => {
if avx512_available() {
unsafe {
arch::x86_avx512::nv42_to_rgba_row(y, vu, rgba_out, width, matrix, full_range);
}
return;
}
if avx2_available() {
unsafe {
arch::x86_avx2::nv42_to_rgba_row(y, vu, rgba_out, width, matrix, full_range);
}
return;
}
if sse41_available() {
unsafe {
arch::x86_sse41::nv42_to_rgba_row(y, vu, rgba_out, width, matrix, full_range);
}
return;
}
},
target_arch = "wasm32" => {
if simd128_available() {
unsafe {
arch::wasm_simd128::nv42_to_rgba_row(y, vu, rgba_out, width, matrix, full_range);
}
return;
}
},
_ => {}
}
}
scalar::nv42_to_rgba_row(y, vu, rgba_out, width, matrix, full_range);
}