Add sve2 acceleration for blit2to2 key (#15953)

This commit is contained in:
Gabriel Wang
2026-07-07 22:36:07 +08:00
committed by GitHub
parent c0efc5862c
commit 7afd6c3497
6 changed files with 309 additions and 18 deletions

View File

@@ -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

View File

@@ -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 =

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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, \
...) \

View File

@@ -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(); \