mindustry logic execution, map- and schematic- parsing and rendering
Diffstat (limited to 'src/utils/image/overlay.rs')
| -rw-r--r-- | src/utils/image/overlay.rs | 69 |
1 files changed, 35 insertions, 34 deletions
diff --git a/src/utils/image/overlay.rs b/src/utils/image/overlay.rs index 9cad52e..4406a9b 100644 --- a/src/utils/image/overlay.rs +++ b/src/utils/image/overlay.rs @@ -1,4 +1,4 @@ -use super::{really_unsafe_index, unsafe_assert, Image}; +use super::{assert_unchecked, really_unsafe_index, Image}; use std::simd::SimdInt; use std::simd::SimdPartialOrd; use std::simd::{simd_swizzle, Simd}; @@ -28,8 +28,8 @@ pub unsafe fn blit(rgb: &mut [u8], rgba: &[u8]) { let mut srci = 0; let mut dsti = 0; while dsti + 16 <= rgb.len() { - let old: Simd<u8, 16> = Simd::from_slice(rgb.get_unchecked(dsti..dsti + 16)); - let new: Simd<u8, 16> = Simd::from_slice(rgba.get_unchecked(srci..srci + 16)); + let old: Simd<u8, 16> = Simd::from_slice(unsafe { rgb.get_unchecked(dsti..dsti + 16) }); + let new: Simd<u8, 16> = Simd::from_slice(unsafe { rgba.get_unchecked(srci..srci + 16) }); let threshold = new.simd_ge(Simd::splat(128)).to_int().cast::<u8>(); let mut mask = simd_swizzle!( @@ -40,19 +40,17 @@ pub unsafe fn blit(rgb: &mut [u8], rgba: &[u8]) { let new_rgb = simd_swizzle!(new, [0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 0, 0, 0, 0]); let blended = (new_rgb & mask) | (old & !mask); - blended.copy_to_slice(rgb.get_unchecked_mut(dsti..dsti + 16)); + blended.copy_to_slice(unsafe { rgb.get_unchecked_mut(dsti..dsti + 16) }); srci += 16; dsti += 12; } while dsti + 3 <= rgb.len() { - if *rgba.get_unchecked(srci + 3) >= 128 { - std::ptr::copy_nonoverlapping( - rgba.get_unchecked(srci..srci + 3).as_ptr(), - rgb.get_unchecked_mut(dsti..dsti + 3).as_mut_ptr(), - 3, - ); + if unsafe { *rgba.get_unchecked(srci + 3) } >= 128 { + let src = unsafe { rgba.get_unchecked(srci..srci + 3) }; + let end = unsafe { rgb.get_unchecked_mut(dsti..dsti + 3) }; + unsafe { std::ptr::copy_nonoverlapping(src.as_ptr(), end.as_mut_ptr(), 3) }; } srci += 4; @@ -62,8 +60,9 @@ pub unsafe fn blit(rgb: &mut [u8], rgba: &[u8]) { impl OverlayAt<Image<&[u8], 4>> for Image<&mut [u8], 3> { unsafe fn overlay_at(&mut self, with: &Image<&[u8], 4>, x: u32, y: u32) -> &mut Self { - unsafe_assert!(x + with.width() <= self.width()); - unsafe_assert!(y + with.height() <= self.height()); + // SAFETY: caller upholds these + unsafe { assert_unchecked!(x + with.width() <= self.width()) }; + unsafe { assert_unchecked!(y + with.height() <= self.height()) }; for j in 0..with.height() { let i_x = j as usize * with.width() as usize * 4 ..(j as usize + 1) * with.width() as usize * 4; @@ -72,10 +71,9 @@ impl OverlayAt<Image<&[u8], 4>> for Image<&mut [u8], 3> { + x as usize + with.width() as usize) * 3; - blit( - self.buffer.get_unchecked_mut(o_x), - with.buffer.get_unchecked(i_x), - ) + let rgb = unsafe { self.buffer.get_unchecked_mut(o_x) }; + let rgba = unsafe { with.buffer.get_unchecked(i_x) }; + unsafe { blit(rgb, rgba) } } self } @@ -83,19 +81,19 @@ impl OverlayAt<Image<&[u8], 4>> for Image<&mut [u8], 3> { impl Overlay<Image<&[u8], 4>> for Image<&mut [u8], 3> { unsafe fn overlay(&mut self, with: &Image<&[u8], 4>) -> &mut Self { - unsafe_assert!(self.width() == with.width()); - unsafe_assert!(self.height() == with.height()); + unsafe { assert_unchecked!(self.width() == with.width()) }; + unsafe { assert_unchecked!(self.height() == with.height()) }; for (i, chunk) in with .buffer .chunks_exact(with.width() as usize * 4) .enumerate() { - blit( + let rgb = unsafe { self.buffer.get_unchecked_mut( i * with.width() as usize * 3..(i + 1) * with.width() as usize * 3, - ), - chunk, - ); + ) + }; + unsafe { blit(rgb, chunk) }; } self } @@ -105,18 +103,21 @@ impl OverlayAt<Image<&[u8], 4>> for Image<&mut [u8], 4> { unsafe fn overlay_at(&mut self, with: &Image<&[u8], 4>, x: u32, y: u32) -> &mut Self { for j in 0..with.height() { for i in 0..with.width() { - let with_index = really_unsafe_index(i, j, with.width()).unchecked_mul(4); - let their_px = with - .buffer - .get_unchecked(with_index..with_index.unchecked_add(4)); - if *their_px.get_unchecked(3) >= 128 { - let our_index = - really_unsafe_index(i.unchecked_add(x), j.unchecked_add(y), self.width()) - .unchecked_mul(4); - let our_px = self - .buffer - .get_unchecked_mut(our_index..our_index.unchecked_add(4)); - std::ptr::copy_nonoverlapping(their_px.as_ptr(), our_px.as_mut_ptr(), 4); + // TODO: see how many unchecked maths i can get rid of + let index_begin = unsafe { really_unsafe_index(i, j, with.width()) }; + let index_begin = unsafe { index_begin.unchecked_mul(4) }; + let index_end = unsafe { index_begin.unchecked_add(4) }; + let their_px = unsafe { with.buffer.get_unchecked(index_begin..index_end) }; + if unsafe { *their_px.get_unchecked(3) } >= 128 { + let x = unsafe { i.unchecked_add(x) }; + let y = unsafe { j.unchecked_add(y) }; + let index_begin = unsafe { really_unsafe_index(x, y, self.width()) }; + let index_begin = unsafe { index_begin.unchecked_mul(4) }; + let index_end = unsafe { index_begin.unchecked_add(4) }; + let our_px = unsafe { self.buffer.get_unchecked_mut(index_begin..index_end) }; + unsafe { + std::ptr::copy_nonoverlapping(their_px.as_ptr(), our_px.as_mut_ptr(), 4) + }; } } } |