diff --git a/src/video/SDL_blit_N.c b/src/video/SDL_blit_N.c index 67ef65bb6c..58cf8f5830 100644 --- a/src/video/SDL_blit_N.c +++ b/src/video/SDL_blit_N.c @@ -3205,6 +3205,11 @@ SDL_BlitFunc SDL_CalculateBlitN(SDL_Surface *surface) If a particular case turns out to be useful we'll add it. */ if (srcfmt->bytes_per_pixel == 2 && surface->map.identity != 0) { +#ifdef SDL_SVE2_INTRINSICS + if (SDL_HasSVE2()) { + return Blit2to2KeySVE2; + } +#endif return Blit2to2Key; } else { #ifdef SDL_ALTIVEC_BLITTERS diff --git a/src/video/arm/SDL_sve2_blit_A.c b/src/video/arm/SDL_sve2_blit_A.c index ef4dd5fff5..1c4131a981 100644 --- a/src/video/arm/SDL_sve2_blit_A.c +++ b/src/video/arm/SDL_sve2_blit_A.c @@ -96,7 +96,7 @@ static inline void sdl_sve_rgb565_stride_blend_with_opacity(uint16_t *SDL_RESTRI size_t uStride, uint16_t hwOpacity) { - sdl_sve_stride_loop_rgb16(uStride, vTailPred) + sdl_sve_stride_loop_u16(uStride, vTailPred) { svuint16x3_t vSource16x3 = diff --git a/src/video/arm/SDL_sve2_blit_N.c b/src/video/arm/SDL_sve2_blit_N.c index c6ae97e53b..d954e7ecb8 100644 --- a/src/video/arm/SDL_sve2_blit_N.c +++ b/src/video/arm/SDL_sve2_blit_N.c @@ -61,4 +61,276 @@ void Blit8888to565PixelSwizzleSVE2(SDL_BlitInfo *info) sdl_sve_rgb32_to_rgb565_swizzle_dispatcher(info); } +SDL_TARGETING("arch=armv8-a+sve2") +ARM_NONNULL(1, 2) +static inline void sdl_sve_rgb16_stride_key(uint16_t *SDL_RESTRICT phwSource, + uint16_t *SDL_RESTRICT phwTarget, + size_t uStride, + uint16_t hwKey, + uint16_t hwKeyMask) +{ + sdl_sve_stride_loop_u16(uStride, vTailPred) + { + svuint16_t vSource = svld1_u16(vTailPred, phwSource); + svuint16_t vTarget = svld1_u16(vTailPred, phwTarget); + + svuint16_t vSourceMasked = svand_n_u16_m(vTailPred, + vSource, + hwKeyMask); + vTarget = svsel_u16(svcmpeq_n_u16(vTailPred, vSourceMasked, hwKey), + vTarget, + vSource); + + svst1_u16(vTailPred, phwTarget, vTarget); + + phwSource += sve_iteration_advance; + phwTarget += sve_iteration_advance; + } +} + +SDL_TARGETING("arch=armv8-a+sve2") +ARM_NONNULL(1, 3) +static inline void sdl_sve_rgb16_key(uint8_t *SDL_RESTRICT pchSource, + size_t uSourceStride, + uint8_t *SDL_RESTRICT pchTarget, + size_t uTargetStride, + int nWidth, + int nHeight, + uint16_t hwKey, + uint16_t hwKeyMask) +{ + assert(0 == ((uintptr_t)pchSource & 0x01)); + assert(0 == ((uintptr_t)pchTarget & 0x01)); + + while (nHeight--) { + sdl_sve_rgb16_stride_key((uint16_t *)pchSource, + (uint16_t *)pchTarget, + nWidth, + hwKey, + hwKeyMask); + + pchSource += uSourceStride; + pchTarget += uTargetStride; + } +} + +SDL_TARGETING("arch=armv8-a+sve2") +void Blit2to2KeySVE2(SDL_BlitInfo *info) +{ + int width = info->dst_w; + int height = info->dst_h; + uint8_t *src = info->src; + int srcskip = info->src_skip; + uint8_t *dst = info->dst; + int dstskip = info->dst_skip; + + const SDL_PixelFormatDetails *srcfmt = info->src_fmt; + const SDL_PixelFormatDetails *dstfmt = info->dst_fmt; + + // Set up some basic variables + int srcbpp = srcfmt->bytes_per_pixel; + int dstbpp = dstfmt->bytes_per_pixel; + + assert(srcbpp == 2); + assert(dstbpp == 2); + + int srcstride = srcskip + srcbpp * width; + int dststride = dstskip + dstbpp * width; + + uint32_t ckey = info->colorkey; + uint32_t rgbmask = ~srcfmt->Amask; + ckey &= rgbmask; + + sdl_sve_rgb16_key(src, + srcstride, + dst, + dststride, + width, + height, + ckey, + rgbmask); +} + +SDL_TARGETING("arch=armv8-a+sve2") +ARM_NONNULL(1, 2) +static inline void sdl_sve_rgb32_stride_key_copy_alpha( + uint32_t *SDL_RESTRICT pwSource, + uint32_t *SDL_RESTRICT pwTarget, + size_t uStride, + uint32_t wKey, + uint32_t wKeyMask, + uint32_t wOpacifyMask) +{ + sdl_sve_stride_loop_u32(uStride, vTailPred) + { + svuint32_t vSource = svld1_u32(vTailPred, pwSource); + svuint32_t vTarget = svld1_u32(vTailPred, pwTarget); + + /* + uint32_t opamask = ((uint32_t)info->a) << dstfmt->Ashift; + ... + if ((*src32 & rgbmask) != ckey) { + *dst32 = *src32 | opamask; + } + */ + svuint32_t vSourceMasked = svand_n_u32_m(vTailPred, + vSource, + wKeyMask); + vTarget = svsel_u32(svcmpeq_n_u32(vTailPred, vSourceMasked, wKey), + vTarget, + svorr_n_u32_m(vTailPred, vSource, wOpacifyMask)); + + svst1_u32(vTailPred, pwTarget, vTarget); + + pwSource += sve_iteration_advance; + pwTarget += sve_iteration_advance; + } +} + +SDL_TARGETING("arch=armv8-a+sve2") +ARM_NONNULL(1, 2) +static inline void sdl_sve_rgb32_stride_key_no_alpha( + uint32_t *SDL_RESTRICT pwSource, + uint32_t *SDL_RESTRICT pwTarget, + size_t uStride, + uint32_t wKey, + uint32_t wKeyMask, + uint32_t wActualRGBMask) +{ + sdl_sve_stride_loop_u32(uStride, vTailPred) + { + svuint32_t vSource = svld1_u32(vTailPred, pwSource); + svuint32_t vTarget = svld1_u32(vTailPred, pwTarget); + + /* + uint32_t rgbmaskactual = srcfmt->Rmask | srcfmt->Gmask | srcfmt->Bmask; + ... + if ((*src32 & rgbmask) != ckey) { + *dst32 = *src32 & rgbmaskactual; + } + */ + svuint32_t vSourceMasked = svand_n_u32_m(vTailPred, + vSource, + wKeyMask); + vTarget = svsel_u32(svcmpeq_n_u32(vTailPred, vSourceMasked, wKey), + vTarget, + svand_n_u32_m(vTailPred, vSource, wActualRGBMask)); + + svst1_u32(vTailPred, pwTarget, vTarget); + + pwSource += sve_iteration_advance; + pwTarget += sve_iteration_advance; + } +} + +SDL_TARGETING("arch=armv8-a+sve2") +ARM_NONNULL(1, 3) +static inline void sdl_sve_rgb32_key_copy_alpha(uint8_t *SDL_RESTRICT pchSource, + size_t uSourceStride, + uint8_t *SDL_RESTRICT pchTarget, + size_t uTargetStride, + int nWidth, + int nHeight, + uint32_t wKey, + uint32_t wKeyMask, + uint32_t wOpacifyMask) +{ + assert(0 == ((uintptr_t)pchSource & 0x03)); + assert(0 == ((uintptr_t)pchTarget & 0x03)); + + while (nHeight--) { + sdl_sve_rgb32_stride_key_copy_alpha((uint32_t *)pchSource, + (uint32_t *)pchTarget, + nWidth, + wKey, + wKeyMask, + wOpacifyMask); + + pchSource += uSourceStride; + pchTarget += uTargetStride; + } +} + +SDL_TARGETING("arch=armv8-a+sve2") +ARM_NONNULL(1, 3) +static inline void sdl_sve_rgb32_key_no_alpha(uint8_t *SDL_RESTRICT pchSource, + size_t uSourceStride, + uint8_t *SDL_RESTRICT pchTarget, + size_t uTargetStride, + int nWidth, + int nHeight, + uint32_t wKey, + uint32_t wKeyMask, + uint32_t wActualRGBMask) +{ + assert(0 == ((uintptr_t)pchSource & 0x03)); + assert(0 == ((uintptr_t)pchTarget & 0x03)); + + while (nHeight--) { + sdl_sve_rgb32_stride_key_no_alpha((uint32_t *)pchSource, + (uint32_t *)pchTarget, + nWidth, + wKey, + wKeyMask, + wActualRGBMask); + + pchSource += uSourceStride; + pchTarget += uTargetStride; + } +} + +SDL_TARGETING("arch=armv8-a+sve2") +void Blit4to4KeySVE2(SDL_BlitInfo *info) +{ + int width = info->dst_w; + int height = info->dst_h; + uint8_t *src = info->src; + int srcskip = info->src_skip; + uint8_t *dst = info->dst; + int dstskip = info->dst_skip; + + const SDL_PixelFormatDetails *srcfmt = info->src_fmt; + const SDL_PixelFormatDetails *dstfmt = info->dst_fmt; + + // Set up some basic variables + int srcbpp = srcfmt->bytes_per_pixel; + int dstbpp = dstfmt->bytes_per_pixel; + + assert(srcbpp == 4); + assert(dstbpp == 4); + + int srcstride = srcskip + srcbpp * width; + int dststride = dstskip + dstbpp * width; + + uint32_t ckey = info->colorkey; + uint32_t rgbmask = ~srcfmt->Amask; + ckey &= rgbmask; + + if (dstfmt->Amask) { + uint32_t opamask = ((uint32_t)info->a) << dstfmt->Ashift; + /* RGBA: set alpha from info->a */ + sdl_sve_rgb32_key_copy_alpha(src, + srcstride, + dst, + dststride, + width, + height, + ckey, + rgbmask, + opamask); + } else { + /* RGBA->RGB: only copy rgb and set alpha to zero */ + uint32_t rgbmaskactual = srcfmt->Rmask | srcfmt->Gmask | srcfmt->Bmask; + sdl_sve_rgb32_key_no_alpha(src, + srcstride, + dst, + dststride, + width, + height, + ckey, + rgbmask, + rgbmaskactual); + } +} + #endif /* SDL_SVE2_INTRINSICS */ \ No newline at end of file diff --git a/src/video/arm/SDL_sve2_blit_N.h b/src/video/arm/SDL_sve2_blit_N.h index 3868de0dbb..16e38deb03 100644 --- a/src/video/arm/SDL_sve2_blit_N.h +++ b/src/video/arm/SDL_sve2_blit_N.h @@ -29,6 +29,8 @@ void Blit8888to8888PixelSwizzleSVE2(SDL_BlitInfo *info); void Blit8888to565PixelSwizzleSVE2(SDL_BlitInfo *info); +void Blit2to2KeySVE2(SDL_BlitInfo *info); +void Blit4to4KeySVE2(SDL_BlitInfo *info); #endif /* SDL_SVE2_INTRINSICS */ diff --git a/src/video/arm/SDL_sve2_extension.h b/src/video/arm/SDL_sve2_extension.h index c18dace028..4e5c67b9c5 100644 --- a/src/video/arm/SDL_sve2_extension.h +++ b/src/video/arm/SDL_sve2_extension.h @@ -22,7 +22,7 @@ /* * IMPORTANT: Please do NOT include this header file directly or indirectly * outside the src/video/arm folder. - * + * */ #if !defined(SDL_SVE2_EXTENSION_H) //&& (defined(__ARM_FEATURE_SVE2) && __ARM_FEATURE_SVE2) @@ -31,15 +31,15 @@ #include "SDL_sve2_util.h" /* - * NOTE: Some Android builds didn't attach '-march=armv8-a+sve2' to + * NOTE: Some Android builds didn't attach '-march=armv8-a+sve2' to * SDL_sve2_*.c and hence the macro __ARM_FEATURE_SVE is not - * defined by the compiler. This might not be a problem as the + * defined by the compiler. This might not be a problem as the * SDL_TARGETING("arch=armv8-a+sve2") enables the feature for * individual functions, until some version of compilers - * provides arm_sve.h raising errors then __ARM_FEATURE_SVE - * is not defined. Although it should be avoided, as a - * workaround, we have to define the __ARM_FEATURE_SVE here as - * an ugly hack. + * provides arm_sve.h raising errors then __ARM_FEATURE_SVE + * is not defined. Although it should be avoided, as a + * workaround, we have to define the __ARM_FEATURE_SVE here as + * an ugly hack. */ #ifdef SDL_PLATFORM_ANDROID #ifndef __ARM_FEATURE_SVE @@ -66,12 +66,12 @@ #define svlens32() svlenu32() #define svlens64() svlenu64() -#define sdl_sve_stride_loop_accc8888(ma_stride_size, ma_pred_name) \ +#define sdl_sve_stride_loop_pixel(ma_stride_size, ma_pred_name) \ for (svbool_t ma_pred_name, *pTemp = &ma_pred_name; \ pTemp != NULL; \ pTemp = NULL) \ for (size_t SVE_SAFE_NAME(n) = 0, \ - sve_iteration_advance = svlenu32() * 4; \ + sve_iteration_advance = svlenu8(); \ ({ \ ma_pred_name = svwhilelt_b8((int32_t)SVE_SAFE_NAME(n), \ (int32_t)(ma_stride_size)); \ @@ -79,10 +79,9 @@ }); \ SVE_SAFE_NAME(n) += sve_iteration_advance) -#define sdl_sve_stride_loop_rgb32(ma_stride_size, ma_pred_name) \ - sdl_sve_stride_loop_accc8888(ma_stride_size, ma_pred_name) +#define sdl_sve_stride_loop_u8 sdl_sve_stride_loop_pixel -#define sdl_sve_stride_loop_rgb16(ma_stride_size, ma_pred_name) \ +#define sdl_sve_stride_loop_u16(ma_stride_size, ma_pred_name) \ for (svbool_t ma_pred_name, *pTemp = &ma_pred_name; \ pTemp != NULL; \ pTemp = NULL) \ @@ -95,6 +94,19 @@ }); \ SVE_SAFE_NAME(n) += sve_iteration_advance) +#define sdl_sve_stride_loop_u32(ma_stride_size, ma_pred_name) \ + for (svbool_t ma_pred_name, *pTemp = &ma_pred_name; \ + pTemp != NULL; \ + pTemp = NULL) \ + for (size_t SVE_SAFE_NAME(n) = 0, \ + sve_iteration_advance = svlenu32(); \ + ({ \ + ma_pred_name = svwhilelt_b16((int32_t)SVE_SAFE_NAME(n), \ + (int32_t)(ma_stride_size)); \ + SVE_SAFE_NAME(n) < (ma_stride_size); \ + }); \ + SVE_SAFE_NAME(n) += sve_iteration_advance) + #define sdl_sve_pixel_ccc_foreach_chn(ma_source_u16x3, \ ma_target_u16x3, \ ...) \ diff --git a/src/video/arm/SDL_sve2_swizzle.h b/src/video/arm/SDL_sve2_swizzle.h index 032e9d6796..f73ebb8e53 100644 --- a/src/video/arm/SDL_sve2_swizzle.h +++ b/src/video/arm/SDL_sve2_swizzle.h @@ -22,7 +22,7 @@ /* * IMPORTANT: Please do NOT include this header file directly or indirectly * outside the src/video/arm folder. - * + * */ #if !defined(SD_SVE2_SWIZZLE_H) //&& (defined(__ARM_FEATURE_SVE2) && __ARM_FEATURE_SVE2) @@ -31,7 +31,7 @@ #include "SDL_sve2_extension.h" #define sdl_sve_rgb32_stride_impl(ma_sve_chn_iterator, ...) \ - sdl_sve_stride_loop_rgb32(uStride, vTailPred) \ + sdl_sve_stride_loop_pixel(uStride, vTailPred) \ { \ \ svuint16x4_t vSourceLow16x4 = svundef4_u16(); \ @@ -71,7 +71,7 @@ ma_alpha_idx, \ ma_sve_chn_iterator, \ ...) \ - sdl_sve_stride_loop_rgb32(uStride, vTailPred) \ + sdl_sve_stride_loop_pixel(uStride, vTailPred) \ { \ \ svuint16x4_t vSourceLow16x4 = svundef4_u16(); \ @@ -115,7 +115,7 @@ } #define sdl_sve_rgb32_to_rgb565_stride_impl(ma_sve_chn_iterator, ...) \ - sdl_sve_stride_loop_rgb32(uStride, vTailPred) \ + sdl_sve_stride_loop_pixel(uStride, vTailPred) \ { \ \ svuint16x4_t vSourceLow16x4 = svundef4_u16(); \ @@ -153,7 +153,7 @@ ma_alpha_idx, \ ma_sve_chn_iterator, \ ...) \ - sdl_sve_stride_loop_rgb32(uStride, vTailPred) \ + sdl_sve_stride_loop_pixel(uStride, vTailPred) \ { \ \ svuint16x4_t vSourceLow16x4 = svundef4_u16(); \