mirror of
https://github.com/Cykooz/fast_image_resize.git
synced 2026-10-08 01:11:09 +00:00
All tests working.
This commit is contained in:
@@ -42,6 +42,9 @@ criterion = { version = "0.4.0", default-features = false, features = ["cargo_be
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
|
||||
nix = { version = "0.26.1", default-features = false, features = ["sched"] }
|
||||
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
|
||||
glassbench = "0.3.3"
|
||||
|
||||
|
||||
[[bench]]
|
||||
name = "bench_resize"
|
||||
|
||||
@@ -191,6 +191,7 @@ unsafe fn divide_alpha_4_pixels(pixels: v128) -> v128 {
|
||||
let alpha_mask = i32x4_splat(0xffff0000u32 as i32);
|
||||
let luma_mask = i32x4_splat(0xffff);
|
||||
let alpha_max = f32x4_splat(65535.0);
|
||||
let alpha_scale_max = f32x4_splat(2147483648f32);
|
||||
/*
|
||||
|L0 A0 | |L1 A1 | |L2 A2 | |L3 A3 |
|
||||
|0001 0203| |0405 0607| |0809 1011| |1213 1415|
|
||||
@@ -200,7 +201,10 @@ unsafe fn divide_alpha_4_pixels(pixels: v128) -> v128 {
|
||||
let alpha_f32x4 = f32x4_convert_i32x4(u8x16_swizzle(pixels, alpha32_sh));
|
||||
let luma_f32x4 = f32x4_convert_i32x4(v128_and(pixels, luma_mask));
|
||||
let scaled_luma_f32x4 = f32x4_mul(luma_f32x4, alpha_max);
|
||||
let divided_luma_u32x4 = u32x4_trunc_sat_f32x4(f32x4_div(scaled_luma_f32x4, alpha_f32x4));
|
||||
let divided_luma_u32x4 = u32x4_trunc_sat_f32x4(f32x4_min(
|
||||
f32x4_div(scaled_luma_f32x4, alpha_f32x4),
|
||||
alpha_scale_max,
|
||||
));
|
||||
|
||||
let alpha = v128_and(pixels, alpha_mask);
|
||||
u8x16_shuffle::<0, 1, 18, 19, 4, 5, 22, 23, 8, 9, 26, 27, 12, 13, 30, 31>(
|
||||
|
||||
@@ -11,6 +11,8 @@ mod native;
|
||||
mod neon;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
mod sse4;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
mod wasm32;
|
||||
|
||||
impl AlphaMulDiv for U16x4 {
|
||||
fn multiply_alpha(
|
||||
@@ -25,6 +27,8 @@ impl AlphaMulDiv for U16x4 {
|
||||
CpuExtensions::Sse4_1 => unsafe { sse4::multiply_alpha(src_image, dst_image) },
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
CpuExtensions::Neon => unsafe { neon::multiply_alpha(src_image, dst_image) },
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
CpuExtensions::Wasm32 => unsafe { wasm32::multiply_alpha(src_image, dst_image) },
|
||||
_ => native::multiply_alpha(src_image, dst_image),
|
||||
}
|
||||
}
|
||||
@@ -37,6 +41,8 @@ impl AlphaMulDiv for U16x4 {
|
||||
CpuExtensions::Sse4_1 => unsafe { sse4::multiply_alpha_inplace(image) },
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
CpuExtensions::Neon => unsafe { neon::multiply_alpha_inplace(image) },
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
CpuExtensions::Wasm32 => unsafe { wasm32::multiply_alpha_inplace(image) },
|
||||
_ => native::multiply_alpha_inplace(image),
|
||||
}
|
||||
}
|
||||
@@ -53,6 +59,8 @@ impl AlphaMulDiv for U16x4 {
|
||||
CpuExtensions::Sse4_1 => unsafe { sse4::divide_alpha(src_image, dst_image) },
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
CpuExtensions::Neon => unsafe { neon::divide_alpha(src_image, dst_image) },
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
CpuExtensions::Wasm32 => unsafe { wasm32::divide_alpha(src_image, dst_image) },
|
||||
_ => native::divide_alpha(src_image, dst_image),
|
||||
}
|
||||
}
|
||||
@@ -65,6 +73,8 @@ impl AlphaMulDiv for U16x4 {
|
||||
CpuExtensions::Sse4_1 => unsafe { sse4::divide_alpha_inplace(image) },
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
CpuExtensions::Neon => unsafe { neon::divide_alpha_inplace(image) },
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
CpuExtensions::Wasm32 => unsafe { wasm32::divide_alpha_inplace(image) },
|
||||
_ => native::divide_alpha_inplace(image),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
use std::arch::wasm32::*;
|
||||
|
||||
use crate::pixels::U16x4;
|
||||
use crate::utils::foreach_with_pre_reading;
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
use super::native;
|
||||
|
||||
pub(crate) unsafe fn multiply_alpha(
|
||||
src_image: &ImageView<U16x4>,
|
||||
dst_image: &mut ImageViewMut<U16x4>,
|
||||
) {
|
||||
let src_rows = src_image.iter_rows(0);
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
|
||||
for (src_row, dst_row) in src_rows.zip(dst_rows) {
|
||||
multiply_alpha_row(src_row, dst_row);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn multiply_alpha_inplace(image: &mut ImageViewMut<U16x4>) {
|
||||
for row in image.iter_rows_mut() {
|
||||
multiply_alpha_row_inplace(row);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) unsafe fn multiply_alpha_row(src_row: &[U16x4], dst_row: &mut [U16x4]) {
|
||||
let src_chunks = src_row.chunks_exact(2);
|
||||
let src_remainder = src_chunks.remainder();
|
||||
let mut dst_chunks = dst_row.chunks_exact_mut(2);
|
||||
let src_dst = src_chunks.zip(&mut dst_chunks);
|
||||
foreach_with_pre_reading(
|
||||
src_dst,
|
||||
|(src, dst)| {
|
||||
let pixels = v128_load(src.as_ptr() as *const v128);
|
||||
let dst_ptr = dst.as_mut_ptr() as *mut v128;
|
||||
(pixels, dst_ptr)
|
||||
},
|
||||
|(mut pixels, dst_ptr)| {
|
||||
pixels = multiply_alpha_2_pixels(pixels);
|
||||
v128_store(dst_ptr, pixels);
|
||||
},
|
||||
);
|
||||
|
||||
if !src_remainder.is_empty() {
|
||||
let dst_reminder = dst_chunks.into_remainder();
|
||||
native::multiply_alpha_row(src_remainder, dst_reminder);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) unsafe fn multiply_alpha_row_inplace(row: &mut [U16x4]) {
|
||||
let mut chunks = row.chunks_exact_mut(2);
|
||||
foreach_with_pre_reading(
|
||||
&mut chunks,
|
||||
|chunk| {
|
||||
let pixels = v128_load(chunk.as_ptr() as *const v128);
|
||||
let dst_ptr = chunk.as_mut_ptr() as *mut v128;
|
||||
(pixels, dst_ptr)
|
||||
},
|
||||
|(mut pixels, dst_ptr)| {
|
||||
pixels = multiply_alpha_2_pixels(pixels);
|
||||
v128_store(dst_ptr, pixels);
|
||||
},
|
||||
);
|
||||
|
||||
let remainder = chunks.into_remainder();
|
||||
if !remainder.is_empty() {
|
||||
native::multiply_alpha_row_inplace(remainder);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn multiply_alpha_2_pixels(pixels: v128) -> v128 {
|
||||
let zero = i64x2_splat(0);
|
||||
let half = i32x4_splat(0x8000);
|
||||
const MAX_A: i64 = 0xffff000000000000u64 as i64;
|
||||
let max_alpha = i64x2_splat(MAX_A);
|
||||
/*
|
||||
|R0 G0 B0 A0 | |R1 G1 B1 A1 |
|
||||
|0001 0203 0405 0607| |0809 1011 1213 1415|
|
||||
*/
|
||||
let factor_mask = i8x16(6, 7, 6, 7, 6, 7, 6, 7, 14, 15, 14, 15, 14, 15, 14, 15);
|
||||
|
||||
let factor_pixels = u8x16_swizzle(pixels, factor_mask);
|
||||
let factor_pixels = v128_or(factor_pixels, max_alpha);
|
||||
|
||||
let src_i32_lo = i16x8_shuffle::<0, 8, 1, 9, 2, 10, 3, 11>(pixels, zero);
|
||||
let factors = i16x8_shuffle::<0, 8, 1, 9, 2, 10, 3, 11>(factor_pixels, zero);
|
||||
let src_i32_lo = i32x4_add(i32x4_mul(src_i32_lo, factors), half);
|
||||
let dst_i32_lo = i32x4_add(src_i32_lo, u32x4_shr(src_i32_lo, 16));
|
||||
let dst_i32_lo = u32x4_shr(dst_i32_lo, 16);
|
||||
|
||||
let src_i32_hi = i16x8_shuffle::<4, 12, 5, 13, 6, 14, 7, 15>(pixels, zero);
|
||||
let factors = i16x8_shuffle::<4, 12, 5, 13, 6, 14, 7, 15>(factor_pixels, zero);
|
||||
let src_i32_hi = i32x4_add(i32x4_mul(src_i32_hi, factors), half);
|
||||
let dst_i32_hi = i32x4_add(src_i32_hi, u32x4_shr(src_i32_hi, 16));
|
||||
let dst_i32_hi = u32x4_shr(dst_i32_hi, 16);
|
||||
|
||||
u16x8_narrow_i32x4(dst_i32_lo, dst_i32_hi)
|
||||
}
|
||||
|
||||
// Divide
|
||||
|
||||
pub(crate) unsafe fn divide_alpha(
|
||||
src_image: &ImageView<U16x4>,
|
||||
dst_image: &mut ImageViewMut<U16x4>,
|
||||
) {
|
||||
let src_rows = src_image.iter_rows(0);
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
|
||||
for (src_row, dst_row) in src_rows.zip(dst_rows) {
|
||||
divide_alpha_row(src_row, dst_row);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn divide_alpha_inplace(image: &mut ImageViewMut<U16x4>) {
|
||||
for row in image.iter_rows_mut() {
|
||||
divide_alpha_row_inplace(row);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn divide_alpha_row(src_row: &[U16x4], dst_row: &mut [U16x4]) {
|
||||
let src_chunks = src_row.chunks_exact(2);
|
||||
let src_remainder = src_chunks.remainder();
|
||||
let mut dst_chunks = dst_row.chunks_exact_mut(2);
|
||||
let src_dst = src_chunks.zip(&mut dst_chunks);
|
||||
foreach_with_pre_reading(
|
||||
src_dst,
|
||||
|(src, dst)| {
|
||||
let pixels = v128_load(src.as_ptr() as *const v128);
|
||||
let dst_ptr = dst.as_mut_ptr() as *mut v128;
|
||||
(pixels, dst_ptr)
|
||||
},
|
||||
|(mut pixels, dst_ptr)| {
|
||||
pixels = divide_alpha_2_pixels(pixels);
|
||||
v128_store(dst_ptr, pixels);
|
||||
},
|
||||
);
|
||||
|
||||
if let Some(src) = src_remainder.first() {
|
||||
let src_pixels = [*src, U16x4::new([0, 0, 0, 0])];
|
||||
let mut dst_pixels = [U16x4::new([0, 0, 0, 0]); 2];
|
||||
|
||||
let mut pixels = v128_load(src_pixels.as_ptr() as *const v128);
|
||||
pixels = divide_alpha_2_pixels(pixels);
|
||||
v128_store(dst_pixels.as_mut_ptr() as *mut v128, pixels);
|
||||
|
||||
let dst_reminder = dst_chunks.into_remainder();
|
||||
if let Some(dst) = dst_reminder.get_mut(0) {
|
||||
*dst = dst_pixels[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn divide_alpha_row_inplace(row: &mut [U16x4]) {
|
||||
let mut chunks = row.chunks_exact_mut(2);
|
||||
foreach_with_pre_reading(
|
||||
&mut chunks,
|
||||
|chunk| {
|
||||
let pixels = v128_load(chunk.as_ptr() as *const v128);
|
||||
let dst_ptr = chunk.as_mut_ptr() as *mut v128;
|
||||
(pixels, dst_ptr)
|
||||
},
|
||||
|(mut pixels, dst_ptr)| {
|
||||
pixels = divide_alpha_2_pixels(pixels);
|
||||
v128_store(dst_ptr, pixels);
|
||||
},
|
||||
);
|
||||
|
||||
let reminder = chunks.into_remainder();
|
||||
if let Some(pixel) = reminder.first_mut() {
|
||||
let src_pixels = [*pixel, U16x4::new([0, 0, 0, 0])];
|
||||
let mut dst_pixels = [U16x4::new([0, 0, 0, 0]); 2];
|
||||
|
||||
let mut pixels = v128_load(src_pixels.as_ptr() as *const v128);
|
||||
pixels = divide_alpha_2_pixels(pixels);
|
||||
v128_store(dst_pixels.as_mut_ptr() as *mut v128, pixels);
|
||||
*pixel = dst_pixels[0];
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn divide_alpha_2_pixels(pixels: v128) -> v128 {
|
||||
let zero = i64x2_splat(0);
|
||||
let alpha_mask = i64x2_splat(0xffff000000000000u64 as i64);
|
||||
let alpha_max = f32x4_splat(65535.0);
|
||||
let alpha_scale_max = f32x4_splat(2147483648f32);
|
||||
/*
|
||||
|R0 G0 B0 A0 | |R1 G1 B1 A1 |
|
||||
|0001 0203 0405 0607| |0809 1011 1213 1415|
|
||||
*/
|
||||
let alpha32_sh0 = i8x16(6, 7, -1, -1, 6, 7, -1, -1, 6, 7, -1, -1, 6, 7, -1, -1);
|
||||
let alpha32_sh1 = i8x16(
|
||||
14, 15, -1, -1, 14, 15, -1, -1, 14, 15, -1, -1, 14, 15, -1, -1,
|
||||
);
|
||||
|
||||
let alpha0_f32x4 = f32x4_convert_i32x4(u8x16_swizzle(pixels, alpha32_sh0));
|
||||
let alpha1_f32x4 = f32x4_convert_i32x4(u8x16_swizzle(pixels, alpha32_sh1));
|
||||
|
||||
let pix0_f32x4 = f32x4_convert_i32x4(i16x8_shuffle::<0, 8, 1, 9, 2, 10, 3, 11>(pixels, zero));
|
||||
let pix1_f32x4 = f32x4_convert_i32x4(i16x8_shuffle::<4, 12, 5, 13, 6, 14, 7, 15>(pixels, zero));
|
||||
|
||||
let scaled_pix0_f32x4 = f32x4_mul(pix0_f32x4, alpha_max);
|
||||
let scaled_pix1_f32x4 = f32x4_mul(pix1_f32x4, alpha_max);
|
||||
|
||||
let divided_pix0_i32x4 = u32x4_trunc_sat_f32x4(f32x4_min(
|
||||
f32x4_div(scaled_pix0_f32x4, alpha0_f32x4),
|
||||
alpha_scale_max,
|
||||
));
|
||||
let divided_pix1_i32x4 = u32x4_trunc_sat_f32x4(f32x4_min(
|
||||
f32x4_div(scaled_pix1_f32x4, alpha1_f32x4),
|
||||
alpha_scale_max,
|
||||
));
|
||||
|
||||
let two_pixels_i16x8 = u16x8_narrow_i32x4(divided_pix0_i32x4, divided_pix1_i32x4);
|
||||
let alpha = v128_and(pixels, alpha_mask);
|
||||
u8x16_shuffle::<0, 1, 2, 3, 4, 5, 22, 23, 8, 9, 10, 11, 12, 13, 30, 31>(two_pixels_i16x8, alpha)
|
||||
}
|
||||
+13
-28
@@ -3,8 +3,6 @@ use std::arch::wasm32::*;
|
||||
use crate::pixels::U8x2;
|
||||
use crate::utils::foreach_with_pre_reading;
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use super::native;
|
||||
|
||||
@@ -128,9 +126,6 @@ pub(crate) unsafe fn divide_alpha_row(src_row: &[U8x2], dst_row: &mut [U8x2]) {
|
||||
let src_remainder = src_chunks.remainder();
|
||||
let mut dst_chunks = dst_row.chunks_exact_mut(8);
|
||||
let src_dst = src_chunks.zip(&mut dst_chunks);
|
||||
let file = "wasm32";
|
||||
let mut debugout = String::new();
|
||||
let file_exists = Path::new(file).exists();
|
||||
foreach_with_pre_reading(
|
||||
src_dst,
|
||||
|(src, dst)| {
|
||||
@@ -140,13 +135,6 @@ pub(crate) unsafe fn divide_alpha_row(src_row: &[U8x2], dst_row: &mut [U8x2]) {
|
||||
},
|
||||
|(mut pixels, dst_ptr)| {
|
||||
pixels = divide_alpha_8_pixels(pixels);
|
||||
if !file_exists {
|
||||
debugout += &format!(
|
||||
"142: {:?} {:?}\n",
|
||||
i64x2_extract_lane::<0>(pixels),
|
||||
i64x2_extract_lane::<1>(pixels)
|
||||
);
|
||||
}
|
||||
v128_store(dst_ptr, pixels);
|
||||
},
|
||||
);
|
||||
@@ -162,13 +150,6 @@ pub(crate) unsafe fn divide_alpha_row(src_row: &[U8x2], dst_row: &mut [U8x2]) {
|
||||
let mut dst_pixels = [U8x2::new(0); 8];
|
||||
let mut pixels = v128_load(src_pixels.as_ptr() as *const v128);
|
||||
pixels = divide_alpha_8_pixels(pixels);
|
||||
if !file_exists {
|
||||
debugout += &format!(
|
||||
"164: {:?} {:?}\n",
|
||||
i64x2_extract_lane::<0>(pixels),
|
||||
i64x2_extract_lane::<1>(pixels)
|
||||
);
|
||||
}
|
||||
v128_store(dst_pixels.as_mut_ptr() as *mut v128, pixels);
|
||||
|
||||
dst_pixels
|
||||
@@ -176,9 +157,6 @@ pub(crate) unsafe fn divide_alpha_row(src_row: &[U8x2], dst_row: &mut [U8x2]) {
|
||||
.zip(dst_reminder)
|
||||
.for_each(|(s, d)| *d = *s);
|
||||
}
|
||||
if !file_exists {
|
||||
fs::write(file, debugout).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -223,17 +201,24 @@ unsafe fn divide_alpha_8_pixels(pixels: v128) -> v128 {
|
||||
9, -1, -1, -1, 11, -1, -1, -1, 13, -1, -1, -1, 15, -1, -1, -1,
|
||||
);
|
||||
let alpha_scale = f32x4_splat(255.0 * 256.0);
|
||||
// Tests pass without capping inf from dividing by zero, but scaled values will not match sse4.
|
||||
let alpha_max = f32x4_splat(2147483648f32);
|
||||
// sse4 _mm_cvtps_ep32 converts inf to i32::MIN or 2147483648f32 u32.
|
||||
// wasm32 u32x4_trunc_sat_f32x4 converts inf to u32::MAX.
|
||||
// Tests pass without capping inf from dividing by zero, but scaled values will not match sse4,
|
||||
// and other potential test cases will (probably?) break.
|
||||
let alpha_scale_max = f32x4_splat(2147483648f32);
|
||||
|
||||
let alpha_lo_f32 = f32x4_convert_u32x4(i8x16_swizzle(pixels, alpha32_sh_lo));
|
||||
// trunc_sat will always round down. Adding f32x4_nearest would match _mm_cvtps_ep32 exactly,
|
||||
// but would add extra instructions.
|
||||
let scaled_alpha_lo_u32 =
|
||||
u32x4_trunc_sat_f32x4(f32x4_min(f32x4_div(alpha_scale, alpha_lo_f32), alpha_max));
|
||||
let scaled_alpha_lo_u32 = u32x4_trunc_sat_f32x4(f32x4_min(
|
||||
f32x4_div(alpha_scale, alpha_lo_f32),
|
||||
alpha_scale_max,
|
||||
));
|
||||
let alpha_hi_f32 = f32x4_convert_u32x4(i8x16_swizzle(pixels, alpha32_sh_hi));
|
||||
let scaled_alpha_hi_u32 =
|
||||
u32x4_trunc_sat_f32x4(f32x4_min(f32x4_div(alpha_scale, alpha_hi_f32), alpha_max));
|
||||
let scaled_alpha_hi_u32 = u32x4_trunc_sat_f32x4(f32x4_min(
|
||||
f32x4_div(alpha_scale, alpha_hi_f32),
|
||||
alpha_scale_max,
|
||||
));
|
||||
let scaled_alpha_u16 = u16x8_narrow_i32x4(scaled_alpha_lo_u32, scaled_alpha_hi_u32);
|
||||
|
||||
let luma_u16 = v128_and(pixels, luma_mask);
|
||||
|
||||
@@ -3,8 +3,6 @@ use std::arch::x86_64::*;
|
||||
use crate::pixels::U8x4;
|
||||
use crate::utils::foreach_with_pre_reading;
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use super::native;
|
||||
|
||||
@@ -120,11 +118,6 @@ pub(crate) unsafe fn divide_alpha_inplace(image: &mut ImageViewMut<U8x4>) {
|
||||
#[inline]
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
pub(crate) unsafe fn divide_alpha_row(src_row: &[U8x4], dst_row: &mut [U8x4]) {
|
||||
let mut file: String = "sse4r".to_string();
|
||||
let mut debugout = String::new();
|
||||
while Path::new(&file).exists() {
|
||||
file += "b";
|
||||
}
|
||||
let src_chunks = src_row.chunks_exact(4);
|
||||
let src_remainder = src_chunks.remainder();
|
||||
let mut dst_chunks = dst_row.chunks_exact_mut(4);
|
||||
@@ -138,25 +131,6 @@ pub(crate) unsafe fn divide_alpha_row(src_row: &[U8x4], dst_row: &mut [U8x4]) {
|
||||
},
|
||||
|(mut pixels, dst_ptr)| {
|
||||
pixels = divide_alpha_4_pixels(pixels);
|
||||
debugout += &format!(
|
||||
"143 pixels: {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?}\n",
|
||||
_mm_extract_epi8(pixels, 0) as u8,
|
||||
_mm_extract_epi8(pixels, 1) as u8,
|
||||
_mm_extract_epi8(pixels, 2) as u8,
|
||||
_mm_extract_epi8(pixels, 3) as u8,
|
||||
_mm_extract_epi8(pixels, 4) as u8,
|
||||
_mm_extract_epi8(pixels, 5) as u8,
|
||||
_mm_extract_epi8(pixels, 6) as u8,
|
||||
_mm_extract_epi8(pixels, 7) as u8,
|
||||
_mm_extract_epi8(pixels, 8) as u8,
|
||||
_mm_extract_epi8(pixels, 9) as u8,
|
||||
_mm_extract_epi8(pixels, 10) as u8,
|
||||
_mm_extract_epi8(pixels, 11) as u8,
|
||||
_mm_extract_epi8(pixels, 12) as u8,
|
||||
_mm_extract_epi8(pixels, 13) as u8,
|
||||
_mm_extract_epi8(pixels, 14) as u8,
|
||||
_mm_extract_epi8(pixels, 15) as u8,
|
||||
);
|
||||
_mm_storeu_si128(dst_ptr, pixels);
|
||||
},
|
||||
);
|
||||
@@ -172,13 +146,6 @@ pub(crate) unsafe fn divide_alpha_row(src_row: &[U8x4], dst_row: &mut [U8x4]) {
|
||||
let mut dst_buffer = [U8x4::new(0); 4];
|
||||
let src_pixels = _mm_loadu_si128(src_buffer.as_ptr() as *const __m128i);
|
||||
let dst_pixels = divide_alpha_4_pixels(src_pixels);
|
||||
debugout += &format!(
|
||||
"165 dst_pixels: {:?} {:?} {:?} {:?}\n",
|
||||
_mm_extract_epi32(dst_pixels, 0) as u32,
|
||||
_mm_extract_epi32(dst_pixels, 1) as u32,
|
||||
_mm_extract_epi32(dst_pixels, 2) as u32,
|
||||
_mm_extract_epi32(dst_pixels, 3) as u32,
|
||||
);
|
||||
_mm_storeu_si128(dst_buffer.as_mut_ptr() as *mut __m128i, dst_pixels);
|
||||
|
||||
dst_buffer
|
||||
@@ -186,17 +153,11 @@ pub(crate) unsafe fn divide_alpha_row(src_row: &[U8x4], dst_row: &mut [U8x4]) {
|
||||
.zip(dst_reminder)
|
||||
.for_each(|(s, d)| *d = *s);
|
||||
}
|
||||
fs::write(file, debugout).unwrap();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
pub(crate) unsafe fn divide_alpha_row_inplace(row: &mut [U8x4]) {
|
||||
let mut file: String = "sse4i".to_string();
|
||||
let mut debugout = String::new();
|
||||
while Path::new(&file).exists() {
|
||||
file += "c";
|
||||
}
|
||||
let mut chunks = row.chunks_exact_mut(4);
|
||||
foreach_with_pre_reading(
|
||||
&mut chunks,
|
||||
@@ -207,13 +168,6 @@ pub(crate) unsafe fn divide_alpha_row_inplace(row: &mut [U8x4]) {
|
||||
},
|
||||
|(mut pixels, dst_ptr)| {
|
||||
pixels = divide_alpha_4_pixels(pixels);
|
||||
debugout += &format!(
|
||||
"179 pixels: {:?} {:?} {:?} {:?}\n",
|
||||
_mm_extract_epi32(pixels, 0) as u32,
|
||||
_mm_extract_epi32(pixels, 1) as u32,
|
||||
_mm_extract_epi32(pixels, 2) as u32,
|
||||
_mm_extract_epi32(pixels, 3) as u32,
|
||||
);
|
||||
_mm_storeu_si128(dst_ptr, pixels);
|
||||
},
|
||||
);
|
||||
@@ -229,35 +183,15 @@ pub(crate) unsafe fn divide_alpha_row_inplace(row: &mut [U8x4]) {
|
||||
let mut dst_buffer = [U8x4::new(0); 4];
|
||||
let src_pixels = _mm_loadu_si128(src_buffer.as_ptr() as *const __m128i);
|
||||
let dst_pixels = divide_alpha_4_pixels(src_pixels);
|
||||
debugout += &format!(
|
||||
"201 dst_pixels: {:?} {:?} {:?} {:?}\n",
|
||||
_mm_extract_epi32(dst_pixels, 0) as u32,
|
||||
_mm_extract_epi32(dst_pixels, 1) as u32,
|
||||
_mm_extract_epi32(dst_pixels, 2) as u32,
|
||||
_mm_extract_epi32(dst_pixels, 3) as u32,
|
||||
);
|
||||
_mm_storeu_si128(dst_buffer.as_mut_ptr() as *mut __m128i, dst_pixels);
|
||||
|
||||
dst_buffer.iter().zip(tail).for_each(|(s, d)| *d = *s);
|
||||
}
|
||||
fs::write(file, debugout).unwrap();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
unsafe fn divide_alpha_4_pixels(src_pixels: __m128i) -> __m128i {
|
||||
let mut file: String = "sse48".to_string();
|
||||
let mut debugout = String::new();
|
||||
while Path::new(&file).exists() {
|
||||
file += "a";
|
||||
}
|
||||
debugout += &format!(
|
||||
"src_pixels: {:?} {:?} {:?} {:?}\n",
|
||||
_mm_extract_epi32(src_pixels, 0) as u32,
|
||||
_mm_extract_epi32(src_pixels, 1) as u32,
|
||||
_mm_extract_epi32(src_pixels, 2) as u32,
|
||||
_mm_extract_epi32(src_pixels, 3) as u32,
|
||||
);
|
||||
let zero = _mm_setzero_si128();
|
||||
let alpha_mask = _mm_set1_epi32(0xff000000u32 as i32);
|
||||
let shuffle1 = _mm_set_epi8(5, 4, 5, 4, 5, 4, 5, 4, 1, 0, 1, 0, 1, 0, 1, 0);
|
||||
@@ -265,55 +199,8 @@ unsafe fn divide_alpha_4_pixels(src_pixels: __m128i) -> __m128i {
|
||||
let alpha_scale = _mm_set1_ps(255.0 * 256.0);
|
||||
|
||||
let alpha_f32 = _mm_cvtepi32_ps(_mm_srli_epi32::<24>(src_pixels));
|
||||
debugout += &format!(
|
||||
"shift24: {:?} {:?} {:?} {:?}\n",
|
||||
_mm_extract_epi32(_mm_srli_epi32::<24>(src_pixels), 0) as u32,
|
||||
_mm_extract_epi32(_mm_srli_epi32::<24>(src_pixels), 1) as u32,
|
||||
_mm_extract_epi32(_mm_srli_epi32::<24>(src_pixels), 2) as u32,
|
||||
_mm_extract_epi32(_mm_srli_epi32::<24>(src_pixels), 3) as u32,
|
||||
);
|
||||
debugout += &format!(
|
||||
"alpha_f32: {:?} {:?} {:?} {:?}\n",
|
||||
f32::from_bits(_mm_extract_ps(alpha_f32, 0) as u32),
|
||||
f32::from_bits(_mm_extract_ps(alpha_f32, 1) as u32),
|
||||
f32::from_bits(_mm_extract_ps(alpha_f32, 2) as u32),
|
||||
f32::from_bits(_mm_extract_ps(alpha_f32, 3) as u32),
|
||||
);
|
||||
let scaled_alpha_f32 = _mm_div_ps(alpha_scale, alpha_f32);
|
||||
debugout += &format!(
|
||||
"scaled_alpha_f32: {:?} {:?} {:?} {:?}\n",
|
||||
f32::from_bits(_mm_extract_ps(scaled_alpha_f32, 0) as u32),
|
||||
f32::from_bits(_mm_extract_ps(scaled_alpha_f32, 1) as u32),
|
||||
f32::from_bits(_mm_extract_ps(scaled_alpha_f32, 2) as u32),
|
||||
f32::from_bits(_mm_extract_ps(scaled_alpha_f32, 3) as u32),
|
||||
);
|
||||
let scaled_alpha_i32 = _mm_cvtps_epi32(scaled_alpha_f32);
|
||||
debugout += &format!(
|
||||
"scaled_alpha_u32: {:?} {:?} {:?} {:?}\n",
|
||||
_mm_extract_epi32(scaled_alpha_i32, 0) as u32,
|
||||
_mm_extract_epi32(scaled_alpha_i32, 1) as u32,
|
||||
_mm_extract_epi32(scaled_alpha_i32, 2) as u32,
|
||||
_mm_extract_epi32(scaled_alpha_i32, 3) as u32,
|
||||
);
|
||||
debugout += &format!(
|
||||
"scaled_alpha_u32: {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?}\n",
|
||||
_mm_extract_epi8(scaled_alpha_i32, 0) as u8,
|
||||
_mm_extract_epi8(scaled_alpha_i32, 1) as u8,
|
||||
_mm_extract_epi8(scaled_alpha_i32, 2) as u8,
|
||||
_mm_extract_epi8(scaled_alpha_i32, 3) as u8,
|
||||
_mm_extract_epi8(scaled_alpha_i32, 4) as u8,
|
||||
_mm_extract_epi8(scaled_alpha_i32, 5) as u8,
|
||||
_mm_extract_epi8(scaled_alpha_i32, 6) as u8,
|
||||
_mm_extract_epi8(scaled_alpha_i32, 7) as u8,
|
||||
_mm_extract_epi8(scaled_alpha_i32, 8) as u8,
|
||||
_mm_extract_epi8(scaled_alpha_i32, 9) as u8,
|
||||
_mm_extract_epi8(scaled_alpha_i32, 10) as u8,
|
||||
_mm_extract_epi8(scaled_alpha_i32, 11) as u8,
|
||||
_mm_extract_epi8(scaled_alpha_i32, 12) as u8,
|
||||
_mm_extract_epi8(scaled_alpha_i32, 13) as u8,
|
||||
_mm_extract_epi8(scaled_alpha_i32, 14) as u8,
|
||||
_mm_extract_epi8(scaled_alpha_i32, 15) as u8,
|
||||
);
|
||||
let mma0 = _mm_shuffle_epi8(scaled_alpha_i32, shuffle1);
|
||||
let mma1 = _mm_shuffle_epi8(scaled_alpha_i32, shuffle2);
|
||||
|
||||
@@ -321,71 +208,10 @@ unsafe fn divide_alpha_4_pixels(src_pixels: __m128i) -> __m128i {
|
||||
let pix1 = _mm_unpackhi_epi8(zero, src_pixels);
|
||||
|
||||
let pix0 = _mm_mulhi_epu16(pix0, mma0);
|
||||
debugout += &format!(
|
||||
"pix0: {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?}\n",
|
||||
_mm_extract_epi16(pix0, 0) as u16,
|
||||
_mm_extract_epi16(pix0, 1) as u16,
|
||||
_mm_extract_epi16(pix0, 2) as u16,
|
||||
_mm_extract_epi16(pix0, 3) as u16,
|
||||
_mm_extract_epi16(pix0, 4) as u16,
|
||||
_mm_extract_epi16(pix0, 5) as u16,
|
||||
_mm_extract_epi16(pix0, 6) as u16,
|
||||
_mm_extract_epi16(pix0, 7) as u16,
|
||||
);
|
||||
let pix1 = _mm_mulhi_epu16(pix1, mma1);
|
||||
debugout += &format!(
|
||||
"pix1: {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?}\n",
|
||||
_mm_extract_epi16(pix1, 0) as u16,
|
||||
_mm_extract_epi16(pix1, 1) as u16,
|
||||
_mm_extract_epi16(pix1, 2) as u16,
|
||||
_mm_extract_epi16(pix1, 3) as u16,
|
||||
_mm_extract_epi16(pix1, 4) as u16,
|
||||
_mm_extract_epi16(pix1, 5) as u16,
|
||||
_mm_extract_epi16(pix1, 6) as u16,
|
||||
_mm_extract_epi16(pix1, 7) as u16,
|
||||
);
|
||||
|
||||
let alpha = _mm_and_si128(src_pixels, alpha_mask);
|
||||
debugout += &format!(
|
||||
"alpha: {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?}\n",
|
||||
_mm_extract_epi8(alpha, 0) as u8,
|
||||
_mm_extract_epi8(alpha, 1) as u8,
|
||||
_mm_extract_epi8(alpha, 2) as u8,
|
||||
_mm_extract_epi8(alpha, 3) as u8,
|
||||
_mm_extract_epi8(alpha, 4) as u8,
|
||||
_mm_extract_epi8(alpha, 5) as u8,
|
||||
_mm_extract_epi8(alpha, 6) as u8,
|
||||
_mm_extract_epi8(alpha, 7) as u8,
|
||||
_mm_extract_epi8(alpha, 8) as u8,
|
||||
_mm_extract_epi8(alpha, 9) as u8,
|
||||
_mm_extract_epi8(alpha, 10) as u8,
|
||||
_mm_extract_epi8(alpha, 11) as u8,
|
||||
_mm_extract_epi8(alpha, 12) as u8,
|
||||
_mm_extract_epi8(alpha, 13) as u8,
|
||||
_mm_extract_epi8(alpha, 14) as u8,
|
||||
_mm_extract_epi8(alpha, 15) as u8,
|
||||
);
|
||||
let rgb = _mm_packus_epi16(pix0, pix1);
|
||||
debugout += &format!(
|
||||
"rgb: {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?}\n",
|
||||
_mm_extract_epi8(rgb, 0) as u8,
|
||||
_mm_extract_epi8(rgb, 1) as u8,
|
||||
_mm_extract_epi8(rgb, 2) as u8,
|
||||
_mm_extract_epi8(rgb, 3) as u8,
|
||||
_mm_extract_epi8(rgb, 4) as u8,
|
||||
_mm_extract_epi8(rgb, 5) as u8,
|
||||
_mm_extract_epi8(rgb, 6) as u8,
|
||||
_mm_extract_epi8(rgb, 7) as u8,
|
||||
_mm_extract_epi8(rgb, 8) as u8,
|
||||
_mm_extract_epi8(rgb, 9) as u8,
|
||||
_mm_extract_epi8(rgb, 10) as u8,
|
||||
_mm_extract_epi8(rgb, 11) as u8,
|
||||
_mm_extract_epi8(rgb, 12) as u8,
|
||||
_mm_extract_epi8(rgb, 13) as u8,
|
||||
_mm_extract_epi8(rgb, 14) as u8,
|
||||
_mm_extract_epi8(rgb, 15) as u8,
|
||||
);
|
||||
fs::write(file, debugout).unwrap();
|
||||
|
||||
_mm_blendv_epi8(rgb, alpha, alpha_mask)
|
||||
}
|
||||
|
||||
+3
-177
@@ -4,8 +4,6 @@ use crate::pixels::U8x4;
|
||||
use crate::utils::foreach_with_pre_reading;
|
||||
use crate::wasm32_utils;
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use super::native;
|
||||
|
||||
@@ -75,7 +73,7 @@ unsafe fn multiply_alpha_4_pixels(pixels: v128) -> v128 {
|
||||
|
||||
const MAX_A: i32 = 0xff000000u32 as i32;
|
||||
let max_alpha = i32x4_splat(MAX_A);
|
||||
let factor_mask = i8x16(15, 15, 15, 15, 11, 11, 11, 11, 7, 7, 7, 7, 3, 3, 3, 3);
|
||||
let factor_mask = i8x16(3, 3, 3, 3, 7, 7, 7, 7, 11, 11, 11, 11, 15, 15, 15, 15);
|
||||
|
||||
let factor_pixels = u8x16_swizzle(pixels, factor_mask);
|
||||
let factor_pixels = v128_or(factor_pixels, max_alpha);
|
||||
@@ -121,11 +119,6 @@ pub(crate) unsafe fn divide_alpha_inplace(image: &mut ImageViewMut<U8x4>) {
|
||||
|
||||
#[inline]
|
||||
pub(crate) unsafe fn divide_alpha_row(src_row: &[U8x4], dst_row: &mut [U8x4]) {
|
||||
let mut file: String = "wasm32r".to_string();
|
||||
let mut debugout = String::new();
|
||||
while Path::new(&file).exists() {
|
||||
file += "b";
|
||||
}
|
||||
let src_chunks = src_row.chunks_exact(4);
|
||||
let src_remainder = src_chunks.remainder();
|
||||
let mut dst_chunks = dst_row.chunks_exact_mut(4);
|
||||
@@ -139,25 +132,6 @@ pub(crate) unsafe fn divide_alpha_row(src_row: &[U8x4], dst_row: &mut [U8x4]) {
|
||||
},
|
||||
|(mut pixels, dst_ptr)| {
|
||||
pixels = divide_alpha_4_pixels(pixels);
|
||||
debugout += &format!(
|
||||
"143 pixels: {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?}\n",
|
||||
u8x16_extract_lane::<0>(pixels),
|
||||
u8x16_extract_lane::<1>(pixels),
|
||||
u8x16_extract_lane::<2>(pixels),
|
||||
u8x16_extract_lane::<3>(pixels),
|
||||
u8x16_extract_lane::<4>(pixels),
|
||||
u8x16_extract_lane::<5>(pixels),
|
||||
u8x16_extract_lane::<6>(pixels),
|
||||
u8x16_extract_lane::<7>(pixels),
|
||||
u8x16_extract_lane::<8>(pixels),
|
||||
u8x16_extract_lane::<9>(pixels),
|
||||
u8x16_extract_lane::<10>(pixels),
|
||||
u8x16_extract_lane::<11>(pixels),
|
||||
u8x16_extract_lane::<12>(pixels),
|
||||
u8x16_extract_lane::<13>(pixels),
|
||||
u8x16_extract_lane::<14>(pixels),
|
||||
u8x16_extract_lane::<15>(pixels),
|
||||
);
|
||||
v128_store(dst_ptr, pixels);
|
||||
},
|
||||
);
|
||||
@@ -173,13 +147,6 @@ pub(crate) unsafe fn divide_alpha_row(src_row: &[U8x4], dst_row: &mut [U8x4]) {
|
||||
let mut dst_buffer = [U8x4::new(0); 4];
|
||||
let src_pixels = v128_load(src_buffer.as_ptr() as *const v128);
|
||||
let dst_pixels = divide_alpha_4_pixels(src_pixels);
|
||||
debugout += &format!(
|
||||
"165 dst_pixels: {:?} {:?} {:?} {:?}\n",
|
||||
u32x4_extract_lane::<0>(dst_pixels),
|
||||
u32x4_extract_lane::<1>(dst_pixels),
|
||||
u32x4_extract_lane::<2>(dst_pixels),
|
||||
u32x4_extract_lane::<3>(dst_pixels),
|
||||
);
|
||||
v128_store(dst_buffer.as_mut_ptr() as *mut v128, dst_pixels);
|
||||
|
||||
dst_buffer
|
||||
@@ -187,16 +154,10 @@ pub(crate) unsafe fn divide_alpha_row(src_row: &[U8x4], dst_row: &mut [U8x4]) {
|
||||
.zip(dst_reminder)
|
||||
.for_each(|(s, d)| *d = *s);
|
||||
}
|
||||
fs::write(file, debugout).unwrap();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) unsafe fn divide_alpha_row_inplace(row: &mut [U8x4]) {
|
||||
let mut file: String = "wasm32i".to_string();
|
||||
let mut debugout = String::new();
|
||||
while Path::new(&file).exists() {
|
||||
file += "c";
|
||||
}
|
||||
let mut chunks = row.chunks_exact_mut(4);
|
||||
foreach_with_pre_reading(
|
||||
&mut chunks,
|
||||
@@ -207,13 +168,6 @@ pub(crate) unsafe fn divide_alpha_row_inplace(row: &mut [U8x4]) {
|
||||
},
|
||||
|(mut pixels, dst_ptr)| {
|
||||
pixels = divide_alpha_4_pixels(pixels);
|
||||
debugout += &format!(
|
||||
"179 pixels: {:?} {:?} {:?} {:?}\n",
|
||||
u32x4_extract_lane::<0>(pixels),
|
||||
u32x4_extract_lane::<1>(pixels),
|
||||
u32x4_extract_lane::<2>(pixels),
|
||||
u32x4_extract_lane::<3>(pixels),
|
||||
);
|
||||
v128_store(dst_ptr, pixels);
|
||||
},
|
||||
);
|
||||
@@ -229,91 +183,24 @@ pub(crate) unsafe fn divide_alpha_row_inplace(row: &mut [U8x4]) {
|
||||
let mut dst_buffer = [U8x4::new(0); 4];
|
||||
let src_pixels = v128_load(src_buffer.as_ptr() as *const v128);
|
||||
let dst_pixels = divide_alpha_4_pixels(src_pixels);
|
||||
debugout += &format!(
|
||||
"201 dst_pixels: {:?} {:?} {:?} {:?}\n",
|
||||
u32x4_extract_lane::<0>(dst_pixels),
|
||||
u32x4_extract_lane::<1>(dst_pixels),
|
||||
u32x4_extract_lane::<2>(dst_pixels),
|
||||
u32x4_extract_lane::<3>(dst_pixels),
|
||||
);
|
||||
v128_store(dst_buffer.as_mut_ptr() as *mut v128, dst_pixels);
|
||||
|
||||
dst_buffer.iter().zip(tail).for_each(|(s, d)| *d = *s);
|
||||
}
|
||||
fs::write(file, debugout).unwrap();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn divide_alpha_4_pixels(src_pixels: v128) -> v128 {
|
||||
let mut file: String = "wasm328".to_string();
|
||||
let mut debugout = String::new();
|
||||
while Path::new(&file).exists() {
|
||||
file += "a";
|
||||
}
|
||||
debugout += &format!(
|
||||
"src_pixels: {:?} {:?} {:?} {:?}\n",
|
||||
u32x4_extract_lane::<0>(src_pixels),
|
||||
u32x4_extract_lane::<1>(src_pixels),
|
||||
u32x4_extract_lane::<2>(src_pixels),
|
||||
u32x4_extract_lane::<3>(src_pixels),
|
||||
);
|
||||
let zero = i64x2_splat(0);
|
||||
let alpha_mask = i32x4_splat(0xff000000u32 as i32);
|
||||
let shuffle1 = i8x16(0, 1, 0, 1, 0, 1, 0, 1, 4, 5, 4, 5, 4, 5, 4, 5);
|
||||
let shuffle2 = i8x16(8, 9, 8, 9, 8, 9, 8, 9, 12, 13, 12, 13, 12, 13, 12, 13);
|
||||
let alpha_scale = f32x4_splat(255.0 * 256.0);
|
||||
let alpha_max = f32x4_splat(2147483648f32);
|
||||
let alpha_scale_max = f32x4_splat(2147483648f32);
|
||||
|
||||
let alpha_f32 = f32x4_convert_i32x4(u32x4_shr(src_pixels, 24));
|
||||
debugout += &format!(
|
||||
"shift24: {:?} {:?} {:?} {:?}\n",
|
||||
i32x4_extract_lane::<0>(u32x4_shr(src_pixels, 24)),
|
||||
i32x4_extract_lane::<1>(u32x4_shr(src_pixels, 24)),
|
||||
i32x4_extract_lane::<2>(u32x4_shr(src_pixels, 24)),
|
||||
i32x4_extract_lane::<3>(u32x4_shr(src_pixels, 24)),
|
||||
);
|
||||
debugout += &format!(
|
||||
"alpha_f32: {:?} {:?} {:?} {:?}\n",
|
||||
f32x4_extract_lane::<0>(alpha_f32),
|
||||
f32x4_extract_lane::<1>(alpha_f32),
|
||||
f32x4_extract_lane::<2>(alpha_f32),
|
||||
f32x4_extract_lane::<3>(alpha_f32),
|
||||
);
|
||||
let scaled_alpha_f32 = f32x4_div(alpha_scale, alpha_f32);
|
||||
debugout += &format!(
|
||||
"scaled_alpha_f32: {:?} {:?} {:?} {:?}\n",
|
||||
f32x4_extract_lane::<0>(scaled_alpha_f32),
|
||||
f32x4_extract_lane::<1>(scaled_alpha_f32),
|
||||
f32x4_extract_lane::<2>(scaled_alpha_f32),
|
||||
f32x4_extract_lane::<3>(scaled_alpha_f32),
|
||||
);
|
||||
let scaled_alpha_u32 = u32x4_trunc_sat_f32x4(f32x4_min(scaled_alpha_f32, alpha_max));
|
||||
debugout += &format!(
|
||||
"scaled_alpha_u32: {:?} {:?} {:?} {:?}\n",
|
||||
u32x4_extract_lane::<0>(scaled_alpha_u32),
|
||||
u32x4_extract_lane::<1>(scaled_alpha_u32),
|
||||
u32x4_extract_lane::<2>(scaled_alpha_u32),
|
||||
u32x4_extract_lane::<3>(scaled_alpha_u32),
|
||||
);
|
||||
debugout += &format!(
|
||||
"scaled_alpha_u32: {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?}\n",
|
||||
u8x16_extract_lane::<0>(scaled_alpha_u32),
|
||||
u8x16_extract_lane::<1>(scaled_alpha_u32),
|
||||
u8x16_extract_lane::<2>(scaled_alpha_u32),
|
||||
u8x16_extract_lane::<3>(scaled_alpha_u32),
|
||||
u8x16_extract_lane::<4>(scaled_alpha_u32),
|
||||
u8x16_extract_lane::<5>(scaled_alpha_u32),
|
||||
u8x16_extract_lane::<6>(scaled_alpha_u32),
|
||||
u8x16_extract_lane::<7>(scaled_alpha_u32),
|
||||
u8x16_extract_lane::<8>(scaled_alpha_u32),
|
||||
u8x16_extract_lane::<9>(scaled_alpha_u32),
|
||||
u8x16_extract_lane::<10>(scaled_alpha_u32),
|
||||
u8x16_extract_lane::<11>(scaled_alpha_u32),
|
||||
u8x16_extract_lane::<12>(scaled_alpha_u32),
|
||||
u8x16_extract_lane::<13>(scaled_alpha_u32),
|
||||
u8x16_extract_lane::<14>(scaled_alpha_u32),
|
||||
u8x16_extract_lane::<15>(scaled_alpha_u32),
|
||||
);
|
||||
let scaled_alpha_u32 = u32x4_trunc_sat_f32x4(f32x4_min(scaled_alpha_f32, alpha_scale_max));
|
||||
let mma0 = u8x16_swizzle(scaled_alpha_u32, shuffle1);
|
||||
let mma1 = u8x16_swizzle(scaled_alpha_u32, shuffle2);
|
||||
|
||||
@@ -324,71 +211,10 @@ unsafe fn divide_alpha_4_pixels(src_pixels: v128) -> v128 {
|
||||
);
|
||||
|
||||
let pix0 = wasm32_utils::u16x8_mul_hi(pix0, mma0);
|
||||
debugout += &format!(
|
||||
"pix0: {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?}\n",
|
||||
u16x8_extract_lane::<0>(pix0),
|
||||
u16x8_extract_lane::<1>(pix0),
|
||||
u16x8_extract_lane::<2>(pix0),
|
||||
u16x8_extract_lane::<3>(pix0),
|
||||
u16x8_extract_lane::<4>(pix0),
|
||||
u16x8_extract_lane::<5>(pix0),
|
||||
u16x8_extract_lane::<6>(pix0),
|
||||
u16x8_extract_lane::<7>(pix0),
|
||||
);
|
||||
let pix1 = wasm32_utils::u16x8_mul_hi(pix1, mma1);
|
||||
debugout += &format!(
|
||||
"pix1: {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?}\n",
|
||||
u16x8_extract_lane::<0>(pix1),
|
||||
u16x8_extract_lane::<1>(pix1),
|
||||
u16x8_extract_lane::<2>(pix1),
|
||||
u16x8_extract_lane::<3>(pix1),
|
||||
u16x8_extract_lane::<4>(pix1),
|
||||
u16x8_extract_lane::<5>(pix1),
|
||||
u16x8_extract_lane::<6>(pix1),
|
||||
u16x8_extract_lane::<7>(pix1),
|
||||
);
|
||||
|
||||
let alpha = v128_and(src_pixels, alpha_mask);
|
||||
debugout += &format!(
|
||||
"alpha: {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?}\n",
|
||||
u8x16_extract_lane::<0>(alpha),
|
||||
u8x16_extract_lane::<1>(alpha),
|
||||
u8x16_extract_lane::<2>(alpha),
|
||||
u8x16_extract_lane::<3>(alpha),
|
||||
u8x16_extract_lane::<4>(alpha),
|
||||
u8x16_extract_lane::<5>(alpha),
|
||||
u8x16_extract_lane::<6>(alpha),
|
||||
u8x16_extract_lane::<7>(alpha),
|
||||
u8x16_extract_lane::<8>(alpha),
|
||||
u8x16_extract_lane::<9>(alpha),
|
||||
u8x16_extract_lane::<10>(alpha),
|
||||
u8x16_extract_lane::<11>(alpha),
|
||||
u8x16_extract_lane::<12>(alpha),
|
||||
u8x16_extract_lane::<13>(alpha),
|
||||
u8x16_extract_lane::<14>(alpha),
|
||||
u8x16_extract_lane::<15>(alpha),
|
||||
);
|
||||
let rgb = u8x16_narrow_i16x8(pix0, pix1);
|
||||
debugout += &format!(
|
||||
"rgb: {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?}\n",
|
||||
u8x16_extract_lane::<0>(rgb),
|
||||
u8x16_extract_lane::<1>(rgb),
|
||||
u8x16_extract_lane::<2>(rgb),
|
||||
u8x16_extract_lane::<3>(rgb),
|
||||
u8x16_extract_lane::<4>(rgb),
|
||||
u8x16_extract_lane::<5>(rgb),
|
||||
u8x16_extract_lane::<6>(rgb),
|
||||
u8x16_extract_lane::<7>(rgb),
|
||||
u8x16_extract_lane::<8>(rgb),
|
||||
u8x16_extract_lane::<9>(rgb),
|
||||
u8x16_extract_lane::<10>(rgb),
|
||||
u8x16_extract_lane::<11>(rgb),
|
||||
u8x16_extract_lane::<12>(rgb),
|
||||
u8x16_extract_lane::<13>(rgb),
|
||||
u8x16_extract_lane::<14>(rgb),
|
||||
u8x16_extract_lane::<15>(rgb),
|
||||
);
|
||||
fs::write(file, debugout).unwrap();
|
||||
|
||||
u8x16_shuffle::<0, 1, 2, 19, 4, 5, 6, 23, 8, 9, 10, 27, 12, 13, 14, 31>(rgb, alpha)
|
||||
}
|
||||
|
||||
@@ -316,13 +316,11 @@ mod multiply_alpha_u16x4 {
|
||||
mul_div_alpha_test(Oper::Mul, SRC_PIXELS, RES_PIXELS, CpuExtensions::Neon);
|
||||
}
|
||||
|
||||
/*
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[test]
|
||||
fn wasm32_test() {
|
||||
mul_div_alpha_test(Oper::Mul, SRC_PIXELS, RES_PIXELS, CpuExtensions::Wasm32);
|
||||
}
|
||||
*/
|
||||
|
||||
#[test]
|
||||
fn native_test() {
|
||||
@@ -540,13 +538,11 @@ mod divide_alpha_u16x4 {
|
||||
mul_div_alpha_test(OPER, SRC_PIXELS, SIMD_RES_PIXELS, CpuExtensions::Neon);
|
||||
}
|
||||
|
||||
/*
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[test]
|
||||
fn wasm32_test() {
|
||||
mul_div_alpha_test(OPER, SRC_PIXELS, RES_PIXELS, CpuExtensions::Wasm32);
|
||||
}
|
||||
*/
|
||||
|
||||
#[test]
|
||||
fn native_test() {
|
||||
|
||||
@@ -203,6 +203,10 @@ fn resize_to_same_width_after_cropping() {
|
||||
{
|
||||
cpu_extensions_vec.push(CpuExtensions::Neon);
|
||||
}
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
{
|
||||
cpu_extensions_vec.push(CpuExtensions::Wasm32);
|
||||
}
|
||||
for cpu_extensions in cpu_extensions_vec {
|
||||
if !cpu_extensions.is_supported() {
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user