Loading gfx/wr/swgl/src/composite.h +53 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,40 @@ ALWAYS_INLINE uint8_t convert_pixel<uint8_t>(uint16_t src) { #endif } // Apply a u8 alpha mask to a u32 texture row static inline void mask_row(uint32_t* dst, const uint8_t* mask, int span) { auto* end = dst + span; while (dst + 4 <= end) { WideRGBA8 maskpx = expand_mask(dst, unpack(unaligned_load<PackedR8>(mask))); WideRGBA8 dstpx = unpack(unaligned_load<PackedRGBA8>(dst)); PackedRGBA8 r = pack(muldiv255(dstpx, maskpx)); unaligned_store(dst, r); mask += 4; dst += 4; } if (dst < end) { WideRGBA8 maskpx = expand_mask(dst, unpack(partial_load_span<PackedR8>(mask, end - dst))); WideRGBA8 dstpx = unpack(partial_load_span<PackedRGBA8>(dst, end - dst)); auto r = pack(maskpx + dstpx - muldiv255(dstpx, maskpx)); partial_store_span(dst, r, end - dst); } } // Apply a R8 alpha mask to a RGBA8 texture static NO_INLINE void mask_blit(Texture& masktex, Texture& dsttex) { int maskStride = masktex.stride(); int destStride = dsttex.stride(); char* dest = dsttex.sample_ptr(0, 0); char* mask = masktex.sample_ptr(0, 0); int span = dsttex.width; for (int rows = dsttex.height; rows > 0; rows--) { mask_row((uint32_t*)dest, (uint8_t*)mask, span); dest += destStride; mask += maskStride; } } template <bool COMPOSITE, typename P> static inline void copy_row(P* dst, const P* src, int span) { // No scaling, so just do a fast copy. Loading Loading @@ -588,6 +622,25 @@ void Composite(LockedTexture* lockedDst, LockedTexture* lockedSrc, GLint srcX, } } // Extension used by the SWGL compositor to apply an alpha mask // to a texture. The textures must be the same size. The mask // must be R8, the texture must be RGBA8. void ApplyMask(LockedTexture* lockedDst, LockedTexture* lockedMask) { assert(lockedDst); assert(lockedMask); Texture& masktex = *lockedMask; Texture& dsttex = *lockedDst; assert(masktex.bpp() == 1); assert(dsttex.bpp() == 4); assert(masktex.width == dsttex.width); assert(masktex.height == dsttex.height); mask_blit(masktex, dsttex); } } // extern "C" // Saturated add helper for YUV conversion. Supported platforms have intrinsics Loading gfx/wr/swgl/src/swgl_fns.rs +17 −0 Original line number Diff line number Diff line Loading @@ -314,6 +314,10 @@ extern "C" { clip_width: GLsizei, clip_height: GLsizei, ); fn ApplyMask( locked_dst: *mut LockedTexture, locked_mask: *mut LockedTexture, ); fn CreateContext() -> *mut c_void; fn ReferenceContext(ctx: *mut c_void); fn DestroyContext(ctx: *mut c_void); Loading Loading @@ -2459,6 +2463,19 @@ impl LockedResource { } } /// Apply an R8 alpha mask to this surface pub fn apply_mask( &self, mask: &LockedResource, ) { unsafe { ApplyMask( self.0, mask.0, ); } } /// Get the underlying buffer for a locked resource pub fn get_buffer(&self) -> (*mut c_void, i32, i32, i32) { unsafe { Loading Loading
gfx/wr/swgl/src/composite.h +53 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,40 @@ ALWAYS_INLINE uint8_t convert_pixel<uint8_t>(uint16_t src) { #endif } // Apply a u8 alpha mask to a u32 texture row static inline void mask_row(uint32_t* dst, const uint8_t* mask, int span) { auto* end = dst + span; while (dst + 4 <= end) { WideRGBA8 maskpx = expand_mask(dst, unpack(unaligned_load<PackedR8>(mask))); WideRGBA8 dstpx = unpack(unaligned_load<PackedRGBA8>(dst)); PackedRGBA8 r = pack(muldiv255(dstpx, maskpx)); unaligned_store(dst, r); mask += 4; dst += 4; } if (dst < end) { WideRGBA8 maskpx = expand_mask(dst, unpack(partial_load_span<PackedR8>(mask, end - dst))); WideRGBA8 dstpx = unpack(partial_load_span<PackedRGBA8>(dst, end - dst)); auto r = pack(maskpx + dstpx - muldiv255(dstpx, maskpx)); partial_store_span(dst, r, end - dst); } } // Apply a R8 alpha mask to a RGBA8 texture static NO_INLINE void mask_blit(Texture& masktex, Texture& dsttex) { int maskStride = masktex.stride(); int destStride = dsttex.stride(); char* dest = dsttex.sample_ptr(0, 0); char* mask = masktex.sample_ptr(0, 0); int span = dsttex.width; for (int rows = dsttex.height; rows > 0; rows--) { mask_row((uint32_t*)dest, (uint8_t*)mask, span); dest += destStride; mask += maskStride; } } template <bool COMPOSITE, typename P> static inline void copy_row(P* dst, const P* src, int span) { // No scaling, so just do a fast copy. Loading Loading @@ -588,6 +622,25 @@ void Composite(LockedTexture* lockedDst, LockedTexture* lockedSrc, GLint srcX, } } // Extension used by the SWGL compositor to apply an alpha mask // to a texture. The textures must be the same size. The mask // must be R8, the texture must be RGBA8. void ApplyMask(LockedTexture* lockedDst, LockedTexture* lockedMask) { assert(lockedDst); assert(lockedMask); Texture& masktex = *lockedMask; Texture& dsttex = *lockedDst; assert(masktex.bpp() == 1); assert(dsttex.bpp() == 4); assert(masktex.width == dsttex.width); assert(masktex.height == dsttex.height); mask_blit(masktex, dsttex); } } // extern "C" // Saturated add helper for YUV conversion. Supported platforms have intrinsics Loading
gfx/wr/swgl/src/swgl_fns.rs +17 −0 Original line number Diff line number Diff line Loading @@ -314,6 +314,10 @@ extern "C" { clip_width: GLsizei, clip_height: GLsizei, ); fn ApplyMask( locked_dst: *mut LockedTexture, locked_mask: *mut LockedTexture, ); fn CreateContext() -> *mut c_void; fn ReferenceContext(ctx: *mut c_void); fn DestroyContext(ctx: *mut c_void); Loading Loading @@ -2459,6 +2463,19 @@ impl LockedResource { } } /// Apply an R8 alpha mask to this surface pub fn apply_mask( &self, mask: &LockedResource, ) { unsafe { ApplyMask( self.0, mask.0, ); } } /// Get the underlying buffer for a locked resource pub fn get_buffer(&self) -> (*mut c_void, i32, i32, i32) { unsafe { Loading