1// [Blend2D]
2// 2D Vector Graphics Powered by a JIT Compiler.
3//
4// [License]
5// Zlib - See LICENSE.md file in the package.
6
7#ifndef BLEND2D_BLPIXELOPS_P_H
8#define BLEND2D_BLPIXELOPS_P_H
9
10#include "./blapi-internal_p.h"
11#include "./blrgba_p.h"
12#include "./blsimd_p.h"
13#include "./bltables_p.h"
14
15//! \cond INTERNAL
16//! \addtogroup blend2d_internal
17//! \{
18
19namespace {
20
21// ============================================================================
22// [PixelOps - Conversion]
23// ============================================================================
24
25static BL_INLINE uint32_t bl_xrgb32_0888_from_xrgb16_0555(uint32_t src) noexcept {
26 uint32_t t0 = src; // [00000000] [00000000] [XRRRRRGG] [GGGBBBBB]
27 uint32_t t1;
28 uint32_t t2;
29
30 t0 = (t0 * 0x00080008u); // [RRRGGGGG] [BBBBBXRR] [RRRGGGGG] [BBBBB000]
31 t0 = (t0 & 0x1F03E0F8u); // [000GGGGG] [000000RR] [RRR00000] [BBBBB000]
32 t0 = (t0 | (t0 >> 5)); // [000GGGGG] [GGGGG0RR] [RRRRRRRR] [BBBBBBBB]
33
34 t1 = t0 >> 13; // [00000000] [00000000] [GGGGGGGG] [GG0RRRRR]
35 t2 = t0 << 6; // [GGGGGGG0] [RRRRRRRR] [RRBBBBBB] [BB000000]
36
37 t0 &= 0x000000FFu; // [00000000] [00000000] [00000000] [BBBBBBBB]
38 t1 &= 0x0000FF00u; // [00000000] [00000000] [GGGGGGGG] [00000000]
39 t2 &= 0x00FF0000u; // [00000000] [RRRRRRRR] [00000000] [00000000]
40
41 return 0xFF000000u | t0 | t1 | t2;
42}
43
44static BL_INLINE uint32_t bl_xrgb32_0888_from_xrgb16_0565(uint32_t src) noexcept {
45 uint32_t t0 = src; // [00000000] [00000000] [RRRRRGGG] [GGGBBBBB]
46 uint32_t t1 = src;
47 uint32_t t2;
48
49 t0 = (t0 & 0x0000F81Fu); // [00000000] [00000000] [RRRRR000] [000BBBBB]
50 t1 = (t1 & 0x000007E0u); // [00000000] [00000000] [00000GGG] [GGG00000]
51
52 t0 = (t0 * 0x21u); // [00000000] [000RRRRR] [RRRRR0BB] [BBBBBBBB]
53 t1 = (t1 * 0x41u); // [00000000] [0000000G] [GGGGGGGG] [GGG00000]
54
55 t2 = (t0 << 3); // [00000000] [RRRRRRRR] [RR0BBBBB] [BBBBB000]
56 t0 = (t0 >> 2); // [00000000] [00000RRR] [RRRRRRR0] [BBBBBBBB]
57 t1 = (t1 >> 1); // [00000000] [00000000] [GGGGGGGG] [GGGG0000]
58
59 t0 = t0 & 0x000000FFu; // [00000000] [00000000] [00000000] [BBBBBBBB]
60 t1 = t1 & 0x0000FF00u; // [00000000] [00000000] [GGGGGGGG] [00000000]
61 t2 = t2 & 0x00FF0000u; // [00000000] [RRRRRRRR] [00000000] [00000000]
62
63 return 0xFF000000u | t0 | t1 | t2;
64}
65
66static BL_INLINE uint32_t bl_argb32_8888_from_argb16_4444(uint32_t src) noexcept {
67 uint32_t t0 = src; // [00000000] [00000000] [AAAARRRR] [GGGGBBBB]
68 uint32_t t1;
69 uint32_t t2;
70
71 t1 = t0 << 12; // [0000AAAA] [RRRRGGGG] [BBBB0000] [00000000]
72 t2 = t0 << 4; // [00000000] [0000AAAA] [RRRRGGGG] [BBBB0000]
73
74 t0 = t0 | t1; // [0000AAAA] [RRRRGGGG] [XXXXRRRR] [GGGGBBBB]
75 t1 = t2 << 4; // [00000000] [AAAARRRR] [GGGGBBBB] [00000000]
76
77 t0 &= 0x0F00000Fu; // [0000AAAA] [00000000] [00000000] [0000BBBB]
78 t1 &= 0x000F0000u; // [00000000] [0000RRRR] [00000000] [00000000]
79 t2 &= 0x00000F00u; // [00000000] [00000000] [0000GGGG] [00000000]
80
81 t0 += t1; // [0000AAAA] [0000RRRR] [00000000] [0000BBBB]
82 t0 += t2; // [0000AAAA] [0000RRRR] [0000GGGG] [0000BBBB]
83
84 return t0 * 0x11u; // [AAAAAAAA] [RRRRRRRR] [GGGGGGGG] [BBBBBBBB]
85}
86
87// --------------------------------------------------------------------------
88// [Premultiply / Demultiply]
89// --------------------------------------------------------------------------
90
91static BL_INLINE uint32_t bl_prgb32_8888_from_argb32_8888(uint32_t val32, uint32_t _a) noexcept {
92#if BL_TARGET_SIMD_I
93 using namespace SIMD;
94
95 I128 p0 = vcvtu32i128(val32);
96 I128 a0 = vcvtu32i128(_a | 0x00FF0000u);
97
98 p0 = vmovli64u8u16(p0);
99 a0 = vswizli16<1, 0, 0, 0>(a0);
100 p0 = vdiv255u16(vmuli16(p0, a0));
101 p0 = vpackzzwb(p0);
102 return vcvti128u32(p0);
103#else
104 uint32_t rb = val32;
105 uint32_t ag = val32;
106
107 ag |= 0xFF000000u;
108 ag >>= 8;
109
110 rb = (rb & 0x00FF00FFu) * _a;
111 ag = (ag & 0x00FF00FFu) * _a;
112
113 rb += 0x00800080u;
114 ag += 0x00800080u;
115
116 rb = (rb + ((rb >> 8) & 0x00FF00FFu)) & 0xFF00FF00u;
117 ag = (ag + ((ag >> 8) & 0x00FF00FFu)) & 0xFF00FF00u;
118
119 rb >>= 8;
120 return ag | rb;
121#endif
122}
123
124static BL_INLINE uint32_t bl_prgb32_8888_from_argb32_8888(uint32_t val32) noexcept {
125#if BL_TARGET_SIMD_I
126 using namespace SIMD;
127
128 I128 p0 = vmovli64u8u16(vcvtu32i128(val32));
129 I128 a0 = vswizli16<3, 3, 3, 3>(p0);
130
131 p0 = vor(p0, v_const_as<I128>(blCommonTable.i128_00FF000000000000));
132 p0 = vdiv255u16(vmuli16(p0, a0));
133 p0 = vpackzzwb(p0);
134 return vcvti128u32(p0);
135#else
136 return bl_prgb32_8888_from_argb32_8888(val32, val32 >> 24);
137#endif
138}
139
140static BL_INLINE uint32_t bl_argb32_8888_from_prgb32_8888(uint32_t val32) noexcept {
141 uint32_t a, r, g, b;
142 a = ((val32 >> 24));
143 r = ((val32 >> 16) & 0xFFu);
144 g = ((val32 >> 8) & 0xFFu);
145 b = ((val32 ) & 0xFFu);
146
147 uint32_t recip = blCommonTable.div24bit[a];
148 r = (r * recip) >> 16;
149 g = (g * recip) >> 16;
150 b = (b * recip) >> 16;
151
152 return (a << 24) | (r << 16) | (g << 8) | b;
153}
154
155static BL_INLINE uint32_t bl_abgr32_8888_from_prgb32_8888(uint32_t val32) noexcept {
156 uint32_t a, r, g, b;
157 a = ((val32 >> 24));
158 r = ((val32 >> 16) & 0xFFu);
159 g = ((val32 >> 8) & 0xFFu);
160 b = ((val32 ) & 0xFFu);
161
162 uint32_t recip = blCommonTable.div24bit[a];
163 r = (r * recip) >> 16;
164 g = (g * recip) >> 16;
165 b = (b * recip) >> 16;
166
167 return (a << 24) | (b << 16) | (g << 8) | r;
168}
169
170} // {anonymous}
171
172//! \}
173//! \endcond
174
175#endif // BLEND2D_BLPIXELOPS_P_H
176