Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions config/check_macroassembler_style.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"arm64",
"loong64",
"riscv64",
"ppc64",
"wasm32",
])
all_shared_architecture_names = set([
Expand All @@ -41,6 +42,7 @@
"arm64",
"loong64",
"riscv64",
"ppc64",
"wasm32",
])

Expand Down
4 changes: 3 additions & 1 deletion gfx/2d/DrawTargetSkia.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,9 @@ static IntRect CalculateSurfaceBounds(const IntSize& aSize, const Rect* aBounds,
}

static const int kARGBAlphaOffset =
SurfaceFormat::A8R8G8B8_UINT32 == SurfaceFormat::B8G8R8A8 ? 3 : 0;
std::endian::native != std::endian::little
? 0
: (SurfaceFormat::A8R8G8B8_UINT32 == SurfaceFormat::B8G8R8A8 ? 3 : 0);

static bool VerifyRGBXFormat(uint8_t* aData, const IntSize& aSize,
const int32_t aStride, SurfaceFormat aFormat) {
Expand Down
24 changes: 12 additions & 12 deletions gfx/2d/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,12 @@ enum class SurfaceFormat : int8_t {

// The following values are endian-independent synonyms. The _UINT32 suffix
// indicates that the name reflects the layout when viewed as a uint32_t
// value.
A8R8G8B8_UINT32 = std::endian::native == std::endian::little
? B8G8R8A8
: A8R8G8B8, // 0xAARRGGBB
X8R8G8B8_UINT32 = std::endian::native == std::endian::little
? B8G8R8X8
: X8R8G8B8, // 0x00RRGGBB
// value on little-endian. Skia and the rest of the pixel pipeline only
// handle the little-endian layouts, so big-endian uses the same in-memory
// byte order and swizzles at the OS boundary instead of flipping formats
// here.
A8R8G8B8_UINT32 = B8G8R8A8, // 0xAARRGGBB
X8R8G8B8_UINT32 = B8G8R8X8, // 0x00RRGGBB

// The following values are OS and endian-independent synonyms.
//
Expand Down Expand Up @@ -283,11 +282,12 @@ enum class SurfaceFormatBit : uint32_t {
R8G8B8A8_B = std::endian::native == std::endian::little ? 16 : 8,
R8G8B8A8_A = std::endian::native == std::endian::little ? 24 : 0,

// The following values are endian-independent for A8R8G8B8_UINT32.
A8R8G8B8_UINT32_B = 0,
A8R8G8B8_UINT32_G = 8,
A8R8G8B8_UINT32_R = 16,
A8R8G8B8_UINT32_A = 24,
// Shifts to access the channels of an A8R8G8B8_UINT32 (B8G8R8A8 memory
// order) pixel when loaded as a native-endian uint32_t.
A8R8G8B8_UINT32_B = std::endian::native == std::endian::little ? 0 : 24,
A8R8G8B8_UINT32_G = std::endian::native == std::endian::little ? 8 : 16,
A8R8G8B8_UINT32_R = std::endian::native == std::endian::little ? 16 : 8,
A8R8G8B8_UINT32_A = std::endian::native == std::endian::little ? 24 : 0,

// The following values are OS and endian-independent.
//
Expand Down
58 changes: 56 additions & 2 deletions gfx/skia/skia/src/base/SkVx.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
#include <arm_neon.h>
#elif defined(__wasm_simd128__)
#include <wasm_simd128.h>
#elif defined(SK_CPU_PPC) && defined(__VSX__) && defined(SK_CPU_LENDIAN)
#include <altivec.h>
#elif SK_CPU_LSX_LEVEL >= SK_CPU_LSX_LEVEL_LASX
#include <lasxintrin.h>
#include <lsxintrin.h>
Expand Down Expand Up @@ -507,6 +509,14 @@ SINT Vec<N,T> if_then_else(const Vec<N,M<T>>& cond, const Vec<N,T>& t, const Vec
sk_bit_cast<uint8x16_t>(e)));
}
#endif
#if SKVX_USE_SIMD && defined(SK_CPU_PPC) && defined(__VSX__) && defined(SK_CPU_LENDIAN)
if constexpr (N*sizeof(T) == 16) {
return sk_bit_cast<Vec<N,T>>(
vec_sel(sk_bit_cast<__vector unsigned char>(e),
sk_bit_cast<__vector unsigned char>(t),
sk_bit_cast<__vector unsigned char>(cond)));
}
#endif
#if SKVX_USE_SIMD && SK_CPU_LSX_LEVEL >= SK_CPU_LSX_LEVEL_LASX
if constexpr (N*sizeof(T) == 32) {
return sk_bit_cast<Vec<N,T>>(__lasx_xvbitsel_v(sk_bit_cast<__m256i>(e),
Expand Down Expand Up @@ -577,6 +587,11 @@ SINT bool any(const Vec<N,T>& x) {
sk_bit_cast<__m128i>(x)));
return retv[0] != 0b0000;
}
#endif
#if SKVX_USE_SIMD && defined(SK_CPU_PPC) && defined(__VSX__) && defined(SK_CPU_LENDIAN)
if constexpr (N*sizeof(T) == 16) {
return vec_any_ne(sk_bit_cast<__vector unsigned int>(x), vec_splats(0u));
}
#endif
return any(x.lo)
|| any(x.hi);
Expand Down Expand Up @@ -620,6 +635,11 @@ SINT bool all(const Vec<N,T>& x) {
sk_bit_cast<__m128i>(x)));
return retv[0] == 0b1111;
}
#endif
#if SKVX_USE_SIMD && defined(SK_CPU_PPC) && defined(__VSX__) && defined(SK_CPU_LENDIAN)
if constexpr (N*sizeof(T) == 16) {
return vec_all_ne(sk_bit_cast<__vector unsigned int>(x), vec_splats(0u));
}
#endif
return all(x.lo)
&& all(x.hi);
Expand All @@ -645,8 +665,22 @@ SIT T max(const Vec<1,T>& x) { return x.val; }
SINT T min(const Vec<N,T>& x) { return std::min(min(x.lo), min(x.hi)); }
SINT T max(const Vec<N,T>& x) { return std::max(max(x.lo), max(x.hi)); }

SINT Vec<N,T> min(const Vec<N,T>& x, const Vec<N,T>& y) { return naive_if_then_else(y < x, y, x); }
SINT Vec<N,T> max(const Vec<N,T>& x, const Vec<N,T>& y) { return naive_if_then_else(x < y, y, x); }
SINT Vec<N,T> min(const Vec<N,T>& x, const Vec<N,T>& y) {
#if SKVX_USE_SIMD && defined(SK_CPU_PPC) && defined(__VSX__) && defined(SK_CPU_LENDIAN)
if constexpr (N*sizeof(T) == 16) {
return sk_bit_cast<Vec<N,T>>(vec_min(to_vext(x), to_vext(y)));
}
#endif
return naive_if_then_else(y < x, y, x);
}
SINT Vec<N,T> max(const Vec<N,T>& x, const Vec<N,T>& y) {
#if SKVX_USE_SIMD && defined(SK_CPU_PPC) && defined(__VSX__) && defined(SK_CPU_LENDIAN)
if constexpr (N*sizeof(T) == 16) {
return sk_bit_cast<Vec<N,T>>(vec_max(to_vext(x), to_vext(y)));
}
#endif
return naive_if_then_else(x < y, y, x);
}

SINTU Vec<N,T> min(const Vec<N,T>& x, U y) { return min(x, Vec<N,T>(y)); }
SINTU Vec<N,T> max(const Vec<N,T>& x, U y) { return max(x, Vec<N,T>(y)); }
Expand Down Expand Up @@ -958,6 +992,26 @@ SIN Vec<N,uint16_t> mulhi(const Vec<N,uint16_t>& x,
} else { // N > 8
return join(mulhi(x.lo, y.lo), mulhi(x.hi, y.hi));
}
#elif SKVX_USE_SIMD && defined(SK_CPU_PPC) && defined(__VSX__) && defined(SK_CPU_LENDIAN)
if constexpr (N == 8) {
// u16*u16 -> u32 even/odd products (vmuleuh/vmulouh), then gather the
// high 16 bits of each back into sequential lanes. Same idiom as the
// VSX scale() in SkSwizzler_opts.
__vector unsigned short xs = sk_bit_cast<__vector unsigned short>(x);
__vector unsigned short ys = sk_bit_cast<__vector unsigned short>(y);
__vector unsigned int even = vec_vmuleuh(xs, ys);
__vector unsigned int odd = vec_vmulouh(xs, ys);
const __vector unsigned char hi = {
0x02,0x03, 0x12,0x13, 0x06,0x07, 0x16,0x17,
0x0A,0x0B, 0x1A,0x1B, 0x0E,0x0F, 0x1E,0x1F
};
return sk_bit_cast<Vec<8,uint16_t>>(
vec_perm((__vector unsigned char)even, (__vector unsigned char)odd, hi));
} else if constexpr (N < 8) {
return mulhi(join(x,x), join(y,y)).lo;
} else { // N > 8
return join(mulhi(x.lo, y.lo), mulhi(x.hi, y.hi));
}
#else
return skvx::cast<uint16_t>(mull(x, y) >> 16);
#endif
Expand Down
104 changes: 102 additions & 2 deletions gfx/skia/skia/src/core/SkBlitRow_D32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,104 @@ static void blit_row_s32_opaque(SkPMColor* dst,
}
}

#elif defined(SK_CPU_PPC) && defined(__VSX__) && defined(SK_CPU_LENDIAN)
#include <altivec.h>

// dst + (((src - dst) * src_scale) >> 8), splayed into 16-bit lanes; the
// vec_* transcription of SkPMLerp_SSE2.
static inline __vector unsigned char SkPMLerp_VSX(__vector unsigned char src,
__vector unsigned char dst,
unsigned src_scale) {
const __vector unsigned int mask = vec_splats(0x00FF00FFu);
const __vector unsigned short eight = vec_splats((unsigned short)8);
__vector unsigned short src_rb = (__vector unsigned short)vec_and((__vector unsigned int)src, mask);
__vector unsigned short src_ag = vec_sr((__vector unsigned short)src, eight);
__vector unsigned short dst_rb = (__vector unsigned short)vec_and((__vector unsigned int)dst, mask);
__vector unsigned short dst_ag = vec_sr((__vector unsigned short)dst, eight);
__vector unsigned short s = vec_splats((unsigned short)src_scale);
__vector unsigned short diff_rb = vec_mul(vec_sub(src_rb, dst_rb), s);
__vector unsigned short diff_ag = vec_mul(vec_sub(src_ag, dst_ag), s);
diff_rb = vec_sr(diff_rb, eight);
__vector unsigned int diff = vec_or((__vector unsigned int)diff_rb,
vec_andc((__vector unsigned int)diff_ag, mask));
return vec_add(dst, (__vector unsigned char)diff);
}

static void blit_row_s32_blend(SkPMColor* dst, const SkPMColor* src, int count, U8CPU alpha) {
SkASSERT(alpha <= 255);
unsigned src_scale = SkAlpha255To256(alpha);
while (count >= 4) {
__vector unsigned char s = vec_xl(0, (const unsigned char*)src);
__vector unsigned char d = vec_xl(0, (const unsigned char*)dst);
vec_xst(SkPMLerp_VSX(s, d, src_scale), 0, (unsigned char*)dst);
src += 4; dst += 4; count -= 4;
}
while (count --> 0) {
*dst = SkPMLerp(*src, *dst, src_scale);
src++;
dst++;
}
}

// The vec_* transcription of SkBlendARGB32_SSE2: scale src by aa and dst by
// SkAlphaMulInv256(srcA, aa), then add the splayed halves.
static inline __vector unsigned char SkBlendARGB32_VSX(__vector unsigned char src,
__vector unsigned char dst,
unsigned aa) {
unsigned alpha = SkAlpha255To256(aa);
__vector unsigned short src_scale = vec_splats((unsigned short)alpha);
const __vector unsigned int mask = vec_splats(0x00FF00FFu);
const __vector unsigned short eight = vec_splats((unsigned short)8);

// dst_scale = SkAlphaMulInv256(SkGetPackedA32(src), alpha), per 32-bit lane.
__vector unsigned int srcA = vec_sr((__vector unsigned int)src, vec_splats(24u));
__vector unsigned int ds = (__vector unsigned int)vec_mul((__vector unsigned short)srcA, src_scale);
ds = vec_sub(vec_splats((unsigned int)0xFFFF), ds);
ds = vec_add(ds, vec_sr(ds, vec_splats(8u)));
ds = vec_sr(ds, vec_splats(8u));
// Duplicate the low 16-bit word of each 32-bit lane into both halves
// (the SSE shufflelo/shufflehi _MM_SHUFFLE(2,2,0,0)).
const __vector unsigned char dup = (__vector unsigned char){
0,1,0,1, 4,5,4,5, 8,9,8,9, 12,13,12,13
};
__vector unsigned short dst_scale =
(__vector unsigned short)vec_perm((__vector unsigned char)ds,
(__vector unsigned char)ds, dup);

__vector unsigned short src_rb = (__vector unsigned short)vec_and((__vector unsigned int)src, mask);
__vector unsigned short src_ag = vec_sr((__vector unsigned short)src, eight);
__vector unsigned short dst_rb = (__vector unsigned short)vec_and((__vector unsigned int)dst, mask);
__vector unsigned short dst_ag = vec_sr((__vector unsigned short)dst, eight);

src_rb = vec_mul(src_rb, src_scale);
src_ag = vec_mul(src_ag, src_scale);
dst_rb = vec_mul(dst_rb, dst_scale);
dst_ag = vec_mul(dst_ag, dst_scale);

dst_rb = vec_add(src_rb, dst_rb);
dst_ag = vec_add(src_ag, dst_ag);

dst_rb = vec_sr(dst_rb, eight);
__vector unsigned int out = vec_or((__vector unsigned int)dst_rb,
vec_andc((__vector unsigned int)dst_ag, mask));
return (__vector unsigned char)out;
}

static void blit_row_s32a_blend(SkPMColor* dst, const SkPMColor* src, int count, U8CPU alpha) {
SkASSERT(alpha <= 255);
while (count >= 4) {
__vector unsigned char s = vec_xl(0, (const unsigned char*)src);
__vector unsigned char d = vec_xl(0, (const unsigned char*)dst);
vec_xst(SkBlendARGB32_VSX(s, d, alpha), 0, (unsigned char*)dst);
src += 4; dst += 4; count -= 4;
}
while (count --> 0) {
*dst = SkBlendARGB32(*src, *dst, alpha);
src++;
dst++;
}
}

#else
static void blit_row_s32_blend(SkPMColor* dst, const SkPMColor* src, int count, U8CPU alpha) {
SkASSERT(alpha <= 255);
Expand Down Expand Up @@ -553,8 +651,10 @@ SkBlitRow::Proc32 SkBlitRow::Factory32(unsigned flags) {

void SkBlitRow::Color32(SkPMColor dst[], int count, SkPMColor color) {
switch (SkGetPackedA32(color)) {
case 0: /* Nothing to do */ return;
case 255: SkOpts::memset32(dst, color, count); return;
case 0: /* Nothing to do */ return;
case 255: SkOpts::memset32(dst, BE_CONVERT(color), count); return;
}
// blit_row_color32 handles the big-endian conversion internally; it needs
// the unconverted value for the alpha extraction.
return SkOpts::blit_row_color32(dst, count, color);
}
Loading