ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
pack.c
Go to the documentation of this file.
1// RGB packing is the pixel-processing stage used by every half-block mode.
2#include "vector.h"
3void FN(simd_pack_)(const uint8_t *rgb, uint32_t *out, size_t count) {
4 size_t i = 0;
5#if defined(SIMD_CELL_NEON)
6 // Retain the original NEON half-block renderer's interleaved RGB vector loads.
7 for (; count - i >= 16; i += 16) {
8 uint8x16x3_t pixel = vld3q_u8(rgb + 3 * i);
9 uint8x16x4_t packed = {{pixel.val[2], pixel.val[1], pixel.val[0], vdupq_n_u8(0)}};
10 vst4q_u8((uint8_t *)(out + i), packed);
11 }
12#elif defined(SIMD_CELL_SVE)
13 for (; i < count; i += svcntw()) {
14 size_t active = count - i < svcntw() ? count - i : svcntw();
15 svbool_t bytes = svwhilelt_b8((uint64_t)0, (uint64_t)active);
16 svbool_t pg = svwhilelt_b32((uint64_t)i, (uint64_t)count);
17 svuint8x3_t pixel = svld3_u8(bytes, rgb + 3 * i);
18 svuint32_t r = svunpklo_u32(svunpklo_u16(svget3_u8(pixel, 0)));
19 svuint32_t g = svunpklo_u32(svunpklo_u16(svget3_u8(pixel, 1)));
20 svuint32_t b = svunpklo_u32(svunpklo_u16(svget3_u8(pixel, 2)));
21 svuint32_t packed = svorr_u32_x(pg, svlsl_n_u32_x(pg, r, 16), svorr_u32_x(pg, svlsl_n_u32_x(pg, g, 8), b));
22 svst1_u32(pg, out + i, packed);
23 }
24#elif defined(SIMD_CELL_AVX2) || defined(SIMD_CELL_SSSE3)
25#if defined(SIMD_CELL_AVX2)
26 const size_t pixels = 8;
27#else
28 const size_t pixels = 4;
29#endif
30 const __m128i shuffle = _mm_setr_epi8(2, 1, 0, -128, 5, 4, 3, -128, 8, 7, 6, -128, 11, 10, 9, -128);
31 for (; count - i >= pixels; i += pixels) {
32 uint8_t low[16] = {0};
33 memcpy(low, rgb + 3 * i, 12);
34 __m128i first = _mm_loadu_si128((const __m128i *)low);
35#if defined(SIMD_CELL_AVX2)
36 uint8_t high[16] = {0};
37 memcpy(high, rgb + 3 * i + 12, 12);
38 __m256i both = _mm256_inserti128_si256(_mm256_castsi128_si256(first), _mm_loadu_si128((const __m128i *)high), 1);
39 __m256i mask = _mm256_broadcastsi128_si256(shuffle);
40 _mm256_storeu_si256((__m256i *)(out + i), _mm256_shuffle_epi8(both, mask));
41#else
42 _mm_storeu_si128((__m128i *)(out + i), _mm_shuffle_epi8(first, shuffle));
43#endif
44 }
45#else
46 for (; count - i >= 4; i += 4) {
47 // SSE2 retains its deinterleave stage, then packs four RGB cells together.
48 int32_t r[4], g[4], b[4];
49 for (unsigned j = 0; j < 4; ++j) {
50 r[j] = rgb[3 * (i + j)];
51 g[j] = rgb[3 * (i + j) + 1];
52 b[j] = rgb[3 * (i + j) + 2];
53 }
54 vec_t packed = OR(SHL(LOAD(r), 16), OR(SHL(LOAD(g), 8), LOAD(b)));
55 STORE(out + i, packed);
56 }
57#endif
58 if (i < count)
59 simd_pack_scalar(rgb + 3 * i, out + i, count - i);
60}
61
62void FN(simd_halfblock_)(const uint32_t *top, const uint32_t *bottom, uint32_t *glyph, uint32_t *fg, uint32_t *bg,
63 size_t count, unsigned mode, const uint32_t keys[5]) {
64 size_t i = 0;
65 for (; HAS_BLOCK; i += LANES) {
67 (void)active;
68 vec_t t = LOAD(top + i), b = LOAD(bottom + i), key = SET((int32_t)keys[4]);
69#if defined(SIMD_CELL_SVE)
70 svbool_t transparent;
71#else
72 vec_t transparent;
73#endif
74 if (mode == 0) {
75 vec_t yt = SHR(
76 ADD(ADD(MUL(SHR(t, 16), SET(76)), MUL(AND(SHR(t, 8), SET(255)), SET(150))), MUL(AND(t, SET(255)), SET(29))),
77 8);
78 vec_t yb = SHR(
79 ADD(ADD(MUL(SHR(b, 16), SET(76)), MUL(AND(SHR(b, 8), SET(255)), SET(150))), MUL(AND(b, SET(255)), SET(29))),
80 8);
81 transparent = BOTH(LT(yt, SET(16)), LT(yb, SET(16)));
82 vec_t shade = SHR(yt, 6);
83 key = SET((int32_t)keys[0]);
84 for (int k = 1; k < 4; ++k)
85 key = SELECT(EQ(shade, SET(k)), SET((int32_t)keys[k]), key);
86 STORE(fg + i, SET(-1));
87 STORE(bg + i, SET(-1));
88 } else {
89 transparent = BOTH(EQ(t, SET(0)), EQ(b, SET(0)));
90 STORE(fg + i, SELECT(transparent, SET(-1), LOAD(fg + i)));
91 STORE(bg + i, SELECT(transparent, SET(-1), LOAD(bg + i)));
92 }
93 STORE(glyph + i, SELECT(transparent, SET(' '), key));
94 }
95 if (i < count)
96 simd_halfblock_scalar(top + i, bottom + i, glyph + i, fg + i, bg + i, count - i, mode, keys);
97}
void simd_halfblock_scalar(const uint32_t *top, const uint32_t *bottom, uint32_t *glyph, uint32_t *fg, uint32_t *bg, size_t count, unsigned mode, const uint32_t keys[5])
Definition cells.c:30
void simd_pack_scalar(const uint8_t *rgb, uint32_t *out, size_t count)
Definition cells.c:10
unsigned int uint32_t
Definition common.h:62
unsigned long long uint64_t
Definition common.h:63
unsigned char uint8_t
Definition common.h:60
static bool size_t gotel_query_t * out
Definition queries.h:8
#define STORE(p, v)
Definition vector.h:71
#define BEGIN_BLOCK
Definition vector.h:72
#define LOAD(p)
Definition vector.h:70
#define MUL(a, b)
Definition vector.h:60
#define SHL(a, n)
Definition vector.h:62
#define BOTH(a, b)
Definition vector.h:68
#define AND(a, b)
Definition vector.h:64
#define SET(n)
Definition vector.h:57
#define SELECT(mask, a, b)
Definition vector.h:69
#define SHR(a, n)
Definition vector.h:63
#define FN(name)
Definition vector.h:6
#define EQ(a, b)
Definition vector.h:67
#define LT(a, b)
Definition vector.h:66
#define LANES
Definition vector.h:35
#define ADD(a, b)
Definition vector.h:58
#define HAS_BLOCK
Definition vector.h:73
#define OR(a, b)
Definition vector.h:65