use crate::alpha::AlphaMode;
use crate::error::{Error, Result};
use crate::format_kind::{FormatFamily, FormatKind, classify};
use crate::surface::{ColorSpace, Surface};
use super::alpha;
use super::buffer::Buffer;
use super::load_kernels as k;
pub fn load_f32(surface: &Surface) -> Result<Buffer<f32>> {
profiling::scope!("load_f32");
let info = classify(surface.format, surface.color_space).ok_or_else(|| {
Error::UnsupportedFormat(format!(
"float pipeline: unsupported input format {:?}",
surface.format
))
})?;
if info.family.is_integer() {
return Err(Error::UnsupportedConversion(format!(
"cannot load integer format {:?} into float pipeline",
surface.format,
)));
}
let (mut buf, srgb_decoded_by_kernel) = match info.kind {
FormatKind::U8 => (k::load_u8_unorm_f32(surface, info.channels)?, false),
FormatKind::I8 => (k::load_i8_snorm_f32(surface, info.channels)?, false),
FormatKind::Srgb8 => (k::load_srgb8_f32(surface, info.channels)?, true),
FormatKind::Bgra8 => (k::load_bgra8_unorm_f32(surface)?, false),
FormatKind::Bgra8Srgb => (k::load_bgra8_srgb_f32(surface)?, true),
FormatKind::Bgr8 => (k::load_bgr8_unorm_f32(surface)?, false),
FormatKind::Bgr8Srgb => (k::load_bgr8_srgb_f32(surface)?, true),
FormatKind::U16 => (k::load_u16_unorm_f32(surface, info.channels)?, false),
FormatKind::I16 => (k::load_i16_snorm_f32(surface, info.channels)?, false),
FormatKind::F16 => (k::load_f16_f32(surface, info.channels)?, false),
FormatKind::F32 => (k::load_f32_f32(surface, info.channels)?, false),
FormatKind::E5b9g9r9Ufloat => (k::load_e5b9g9r9_f32(surface)?, false),
FormatKind::B10g11r11Ufloat => (k::load_b10g11r11_f32(surface)?, false),
FormatKind::A2b10g10r10Unorm => (k::load_a2b10g10r10_unorm_f32(surface)?, false),
FormatKind::A2b10g10r10Snorm => (k::load_a2b10g10r10_snorm_f32(surface)?, false),
FormatKind::A2r10g10b10Unorm => (k::load_a2r10g10b10_unorm_f32(surface)?, false),
FormatKind::A2r10g10b10Snorm => (k::load_a2r10g10b10_snorm_f32(surface)?, false),
other => {
return Err(Error::UnsupportedFormat(format!(
"float pipeline: unsupported format kind {other:?}"
)));
}
};
if !srgb_decoded_by_kernel && surface.color_space == ColorSpace::Srgb {
k::srgb_eotf_in_place_f32(&mut buf.pixels);
}
if surface.alpha == AlphaMode::Straight {
alpha::premultiply_f32(&mut buf);
}
Ok(buf)
}
pub fn load_f64(surface: &Surface) -> Result<Buffer<f64>> {
profiling::scope!("load_f64");
let info = classify(surface.format, surface.color_space).ok_or_else(|| {
Error::UnsupportedFormat(format!(
"f64 pipeline: unsupported input format {:?}",
surface.format
))
})?;
if !matches!(info.family, FormatFamily::Float) {
return Err(Error::UnsupportedConversion(format!(
"f64 pipeline requires a float-family source, got {:?}",
surface.format,
)));
}
let mut buf = match info.kind {
FormatKind::F32 => k::load_f32_f64(surface, info.channels)?,
FormatKind::F64 => k::load_f64_f64(surface, info.channels)?,
other => {
return Err(Error::UnsupportedFormat(format!(
"f64 pipeline: unsupported format kind {other:?}"
)));
}
};
if surface.alpha == AlphaMode::Straight {
alpha::premultiply_f64(&mut buf);
}
Ok(buf)
}
pub fn load_u32(surface: &Surface) -> Result<Buffer<u32>> {
profiling::scope!("load_u32");
let info = classify(surface.format, surface.color_space).ok_or_else(|| {
Error::UnsupportedFormat(format!(
"u32 pipeline: unsupported input format {:?}",
surface.format
))
})?;
if !info.family.is_integer() {
return Err(Error::UnsupportedConversion(format!(
"u32 pipeline requires an integer-family source, got {:?}",
surface.format,
)));
}
match info.kind {
FormatKind::U8 => k::load_u8_uint_u32(surface, info.channels),
FormatKind::I8 => k::load_i8_sint_u32(surface, info.channels),
FormatKind::U16 => k::load_u16_uint_u32(surface, info.channels),
FormatKind::I16 => k::load_i16_sint_u32(surface, info.channels),
FormatKind::U32 => k::load_u32_uint_u32(surface, info.channels),
FormatKind::I32 => k::load_i32_sint_u32(surface, info.channels),
FormatKind::A2b10g10r10Uint => k::load_a2b10g10r10_uint_u32(surface),
FormatKind::A2b10g10r10Sint => k::load_a2b10g10r10_sint_u32(surface),
FormatKind::A2r10g10b10Uint => k::load_a2r10g10b10_uint_u32(surface),
FormatKind::A2r10g10b10Sint => k::load_a2r10g10b10_sint_u32(surface),
other => Err(Error::UnsupportedFormat(format!(
"u32 pipeline: unsupported format kind {other:?}"
))),
}
}
pub fn load_u64(surface: &Surface) -> Result<Buffer<u64>> {
profiling::scope!("load_u64");
let info = classify(surface.format, surface.color_space).ok_or_else(|| {
Error::UnsupportedFormat(format!(
"u64 pipeline: unsupported input format {:?}",
surface.format
))
})?;
if !info.family.is_integer() {
return Err(Error::UnsupportedConversion(format!(
"u64 pipeline requires an integer-family source, got {:?}",
surface.format,
)));
}
match info.kind {
FormatKind::U64 => k::load_u64_uint_u64(surface, info.channels),
FormatKind::I64 => k::load_i64_sint_u64(surface, info.channels),
other => Err(Error::UnsupportedFormat(format!(
"u64 pipeline: unsupported format kind {other:?}"
))),
}
}