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_BLPIPEDEFS_P_H |
8 | #define BLEND2D_BLPIPEDEFS_P_H |
9 | |
10 | #include "./blapi-internal_p.h" |
11 | #include "./blformat_p.h" |
12 | #include "./blgradient_p.h" |
13 | #include "./blmatrix_p.h" |
14 | #include "./blpattern_p.h" |
15 | #include "./blruntime_p.h" |
16 | #include "./blsupport_p.h" |
17 | #include "./bltables_p.h" |
18 | #include "./blsimd_p.h" |
19 | |
20 | //! \cond INTERNAL |
21 | //! \addtogroup blend2d_internal |
22 | //! \{ |
23 | |
24 | // ============================================================================ |
25 | // [Forward Declarations] |
26 | // ============================================================================ |
27 | |
28 | struct BLPipeContextData; |
29 | struct BLPipeFillData; |
30 | struct BLPipeFetchData; |
31 | struct BLPipeSignature; |
32 | |
33 | // ============================================================================ |
34 | // [Constants] |
35 | // ============================================================================ |
36 | |
37 | //! Global constants used by pipeline and affecting also rasterizers. |
38 | enum BLPipeGlobalConsts : uint32_t { |
39 | //! How many pixels are represented by a single bit of a `BLBitWord`. |
40 | //! |
41 | //! This is a hardcoded value as it's required by both rasterizer and compositor. |
42 | //! Before establishing `4` the values [4, 8, 16, 32] were tested. Candidates |
43 | //! were `4` and `8` where `8` sometimes surpassed `4` in specific workloads, |
44 | //! but `4` was stable across all tests. |
45 | //! |
46 | //! In general increasing `BL_PIPE_PIXELS_PER_ONE_BIT` would result in less |
47 | //! memory consumed by bit vectors, but would increase the work compositors |
48 | //! have to do to process cells produced by analytic rasterizer. |
49 | BL_PIPE_PIXELS_PER_ONE_BIT = 4 |
50 | }; |
51 | |
52 | //! 8-bit alpha constants used by pipelines and affecting also rasterizers. |
53 | enum BLPipeA8Consts : uint32_t { |
54 | BL_PIPE_A8_SHIFT = 8, // 8. |
55 | BL_PIPE_A8_SCALE = 1 << BL_PIPE_A8_SHIFT, // 256. |
56 | BL_PIPE_A8_MASK = BL_PIPE_A8_SCALE - 1 // 255. |
57 | }; |
58 | |
59 | //! Pipeline extend modes (non-combined). |
60 | //! |
61 | //! Pipeline sees extend modes a bit differently in most cases. |
62 | enum BLPipeExtendMode : uint32_t { |
63 | BL_PIPE_EXTEND_MODE_PAD = 0, //!< Pad, same as `BL_EXTEND_MODE_PAD`. |
64 | BL_PIPE_EXTEND_MODE_REPEAT = 1, //!< Repeat, same as `BL_EXTEND_MODE_REPEAT`. |
65 | BL_PIPE_EXTEND_MODE_REFLECT = 2, //!< Reflect, same as `BL_EXTEND_MODE_REFLECT`. |
66 | BL_PIPE_EXTEND_MODE_ROR = 3, //!< Repeat-or-reflect (the same code-path for both cases). |
67 | |
68 | BL_PIPE_EXTEND_MODE_COUNT = 4 //! Count of pipeline-specific extend modes. |
69 | }; |
70 | |
71 | //! Pipeline fill-type. |
72 | //! |
73 | //! A unique id describing how a mask of each filled pixel is calculated. |
74 | enum BLPipeFillType : uint32_t { |
75 | BL_PIPE_FILL_TYPE_NONE = 0, //!< None or uninitialized. |
76 | BL_PIPE_FILL_TYPE_BOX_AA = 1, //!< Fill axis-aligned box. |
77 | BL_PIPE_FILL_TYPE_BOX_AU = 2, //!< Fill axis-unaligned box. |
78 | BL_PIPE_FILL_TYPE_ANALYTIC = 3, //!< Fill analytic non-zero/even-odd. |
79 | |
80 | BL_PIPE_FILL_TYPE_COUNT = 4 //!< Count of fill types. |
81 | }; |
82 | |
83 | //! Fill rule mask used during composition of mask produced by analytic-rasterizer. |
84 | //! |
85 | //! See blfillpart.cpp how this is used. What you see in these values is |
86 | //! mask shifted left by one bit as we expect such values in the pipeline. |
87 | enum BLPipeFillRuleMask : uint32_t { |
88 | BL_PIPE_FILL_RULE_MASK_NON_ZERO = uint32_t(0xFFFFFFFFu << 1), |
89 | BL_PIPE_FILL_RULE_MASK_EVEN_ODD = uint32_t(0x000001FFu << 1) |
90 | }; |
91 | |
92 | //! Pipeline fetch-type. |
93 | //! |
94 | //! A unique id describing how pixels are fetched - supported fetchers include |
95 | //! solid pixels, patterns (sometimes referred as blits), and gradients. |
96 | //! |
97 | //! \note RoR is a shurtcut for repeat-or-reflect - an universal fetcher for both. |
98 | enum BLPipeFetchType : uint32_t { |
99 | BL_PIPE_FETCH_TYPE_SOLID = 0, //!< Solid fetch. |
100 | |
101 | BL_PIPE_FETCH_TYPE_PATTERN_AA_BLIT, //!< Pattern {aligned} (blit) [Base]. |
102 | BL_PIPE_FETCH_TYPE_PATTERN_AA_PAD, //!< Pattern {aligned} (pad-x) [Base]. |
103 | BL_PIPE_FETCH_TYPE_PATTERN_AA_REPEAT, //!< Pattern {aligned} (repeat-large-x) [Optimized]. |
104 | BL_PIPE_FETCH_TYPE_PATTERN_AA_ROR, //!< Pattern {aligned} (ror-x) [Base]. |
105 | BL_PIPE_FETCH_TYPE_PATTERN_FX_PAD, //!< Pattern {frac-x} (pad-x) [Optimized]. |
106 | BL_PIPE_FETCH_TYPE_PATTERN_FX_ROR, //!< Pattern {frac-x} (ror-x) [Optimized]. |
107 | BL_PIPE_FETCH_TYPE_PATTERN_FY_PAD, //!< Pattern {frac-y} (pad-x) [Optimized]. |
108 | BL_PIPE_FETCH_TYPE_PATTERN_FY_ROR, //!< Pattern {frac-x} (ror-x) [Optimized]. |
109 | BL_PIPE_FETCH_TYPE_PATTERN_FX_FY_PAD, //!< Pattern {frac-xy} (pad-x) [Base]. |
110 | BL_PIPE_FETCH_TYPE_PATTERN_FX_FY_ROR, //!< Pattern {frac-xy} (ror-x) [Base]. |
111 | BL_PIPE_FETCH_TYPE_PATTERN_AFFINE_NN_ANY, //!< Pattern {affine-nearest} (any) [Base]. |
112 | BL_PIPE_FETCH_TYPE_PATTERN_AFFINE_NN_OPT, //!< Pattern {affine-nearest} (any) [Optimized]. |
113 | BL_PIPE_FETCH_TYPE_PATTERN_AFFINE_BI_ANY, //!< Pattern {affine-bilinear} (any) [Base]. |
114 | BL_PIPE_FETCH_TYPE_PATTERN_AFFINE_BI_OPT, //!< Pattern {affine-bilinear} (any) [Optimized]. |
115 | |
116 | BL_PIPE_FETCH_TYPE_GRADIENT_LINEAR_PAD, //!< Linear gradient (pad) [Base]. |
117 | BL_PIPE_FETCH_TYPE_GRADIENT_LINEAR_ROR, //!< Linear gradient (ror) [Base]. |
118 | BL_PIPE_FETCH_TYPE_GRADIENT_RADIAL_PAD, //!< Radial gradient (pad) [Base]. |
119 | BL_PIPE_FETCH_TYPE_GRADIENT_RADIAL_REPEAT, //!< Radial gradient (repeat) [Base]. |
120 | BL_PIPE_FETCH_TYPE_GRADIENT_RADIAL_REFLECT, //!< Radial gradient (reflect) [Base]. |
121 | BL_PIPE_FETCH_TYPE_GRADIENT_CONICAL, //!< Conical gradient (any) [Base]. |
122 | |
123 | BL_PIPE_FETCH_TYPE_COUNT, //!< Number of fetch types. |
124 | |
125 | BL_PIPE_FETCH_TYPE_PIXEL_PTR = 0xFF, //!< Pixel pointer, not a valid fetch type. |
126 | |
127 | BL_PIPE_FETCH_TYPE_PATTERN_ANY_FIRST = BL_PIPE_FETCH_TYPE_PATTERN_AA_BLIT, |
128 | BL_PIPE_FETCH_TYPE_PATTERN_ANY_LAST = BL_PIPE_FETCH_TYPE_PATTERN_AFFINE_BI_OPT, |
129 | |
130 | BL_PIPE_FETCH_TYPE_PATTERN_AA_FIRST = BL_PIPE_FETCH_TYPE_PATTERN_AA_BLIT, |
131 | BL_PIPE_FETCH_TYPE_PATTERN_AA_LAST = BL_PIPE_FETCH_TYPE_PATTERN_AA_ROR, |
132 | |
133 | BL_PIPE_FETCH_TYPE_PATTERN_AU_FIRST = BL_PIPE_FETCH_TYPE_PATTERN_FX_PAD, |
134 | BL_PIPE_FETCH_TYPE_PATTERN_AU_LAST = BL_PIPE_FETCH_TYPE_PATTERN_FX_FY_ROR, |
135 | |
136 | BL_PIPE_FETCH_TYPE_PATTERN_FX_FIRST = BL_PIPE_FETCH_TYPE_PATTERN_FX_PAD, |
137 | BL_PIPE_FETCH_TYPE_PATTERN_FX_LAST = BL_PIPE_FETCH_TYPE_PATTERN_FX_ROR, |
138 | |
139 | BL_PIPE_FETCH_TYPE_PATTERN_FY_FIRST = BL_PIPE_FETCH_TYPE_PATTERN_FY_PAD, |
140 | BL_PIPE_FETCH_TYPE_PATTERN_FY_LAST = BL_PIPE_FETCH_TYPE_PATTERN_FY_ROR, |
141 | |
142 | BL_PIPE_FETCH_TYPE_PATTERN_FX_FY_FIRST = BL_PIPE_FETCH_TYPE_PATTERN_FX_FY_PAD, |
143 | BL_PIPE_FETCH_TYPE_PATTERN_FX_FY_LAST = BL_PIPE_FETCH_TYPE_PATTERN_FX_FY_ROR, |
144 | |
145 | BL_PIPE_FETCH_TYPE_PATTERN_SIMPLE_FIRST = BL_PIPE_FETCH_TYPE_PATTERN_AA_BLIT, |
146 | BL_PIPE_FETCH_TYPE_PATTERN_SIMPLE_LAST = BL_PIPE_FETCH_TYPE_PATTERN_FX_FY_ROR, |
147 | |
148 | BL_PIPE_FETCH_TYPE_PATTERN_AFFINE_FIRST = BL_PIPE_FETCH_TYPE_PATTERN_AFFINE_NN_ANY, |
149 | BL_PIPE_FETCH_TYPE_PATTERN_AFFINE_LAST = BL_PIPE_FETCH_TYPE_PATTERN_AFFINE_BI_OPT, |
150 | |
151 | BL_PIPE_FETCH_TYPE_GRADIENT_ANY_FIRST = BL_PIPE_FETCH_TYPE_GRADIENT_LINEAR_PAD, |
152 | BL_PIPE_FETCH_TYPE_GRADIENT_ANY_LAST = BL_PIPE_FETCH_TYPE_GRADIENT_CONICAL, |
153 | |
154 | BL_PIPE_FETCH_TYPE_GRADIENT_LINEAR_FIRST = BL_PIPE_FETCH_TYPE_GRADIENT_LINEAR_PAD, |
155 | BL_PIPE_FETCH_TYPE_GRADIENT_LINEAR_LAST = BL_PIPE_FETCH_TYPE_GRADIENT_LINEAR_ROR, |
156 | |
157 | BL_PIPE_FETCH_TYPE_GRADIENT_RADIAL_FIRST = BL_PIPE_FETCH_TYPE_GRADIENT_RADIAL_PAD, |
158 | BL_PIPE_FETCH_TYPE_GRADIENT_RADIAL_LAST = BL_PIPE_FETCH_TYPE_GRADIENT_RADIAL_REFLECT, |
159 | |
160 | BL_PIPE_FETCH_TYPE_GRADIENT_CONICAL_FIRST = BL_PIPE_FETCH_TYPE_GRADIENT_CONICAL, |
161 | BL_PIPE_FETCH_TYPE_GRADIENT_CONICAL_LAST = BL_PIPE_FETCH_TYPE_GRADIENT_CONICAL |
162 | }; |
163 | |
164 | //! Masks used by `BLPipeSignature`. |
165 | //! |
166 | //! Each mask represents one value in a signature. Each value describes a part |
167 | //! in a signature like format, composition operator, etc. All parts packed |
168 | //! together form a 32-bit integer that can be used to uniquely describe the |
169 | //! whole pipeline and can act as a key or hash-code in pipeline function caches. |
170 | enum BLPipeSignatureMasks : uint32_t { |
171 | BL_PIPE_SIGNATURE_DST_FORMAT = 0x0000000Fu << 0, // [00..03] {16 values} |
172 | BL_PIPE_SIGNATURE_SRC_FORMAT = 0x0000000Fu << 4, // [04..07] {16 values} |
173 | BL_PIPE_SIGNATURE_COMP_OP = 0x0000003Fu << 8, // [08..13] {64 values} |
174 | BL_PIPE_SIGNATURE_FILL_TYPE = 0x00000003u << 14, // [14..15] {4 values} |
175 | BL_PIPE_SIGNATURE_FETCH_TYPE = 0x0000001Fu << 16, // [16..20] {32 values} |
176 | BL_PIPE_SIGNATURE_FETCH_PAYLOAD = 0x000007FFu << 21 // [21..31] {2048 values} |
177 | }; |
178 | |
179 | // ============================================================================ |
180 | // [Typedefs] |
181 | // ============================================================================ |
182 | |
183 | typedef BLResult (BL_CDECL* BLPipeFillFunc)(void* ctxData, void* fillData, const void* fetchData) BL_NOEXCEPT; |
184 | |
185 | // ============================================================================ |
186 | // [BLPipeValue32] |
187 | // ============================================================================ |
188 | |
189 | union BLPipeValue32 { |
190 | uint32_t u; |
191 | int32_t i; |
192 | float f; |
193 | }; |
194 | |
195 | // ============================================================================ |
196 | // [BLPipeValue64] |
197 | // ============================================================================ |
198 | |
199 | union BLPipeValue64 { |
200 | uint64_t u64; |
201 | int64_t i64; |
202 | double d; |
203 | |
204 | int32_t i32[2]; |
205 | uint32_t u32[2]; |
206 | |
207 | int16_t i16[4]; |
208 | uint16_t u16[4]; |
209 | |
210 | #if BL_BYTE_ORDER == 1234 |
211 | struct { int32_t i32Lo, i32Hi; }; |
212 | struct { uint32_t u32Lo, u32Hi; }; |
213 | #else |
214 | struct { int32_t i32Hi, i32Lo; }; |
215 | struct { uint32_t u32Hi, u32Lo; }; |
216 | #endif |
217 | |
218 | BL_INLINE void expandLoToHi() noexcept { u32Hi = u32Lo; } |
219 | }; |
220 | |
221 | // ============================================================================ |
222 | // [BLPipeContextData] |
223 | // ============================================================================ |
224 | |
225 | struct BLPipeContextData { |
226 | BLImageData dst; |
227 | |
228 | BL_INLINE void reset() noexcept { memset(this, 0, sizeof(*this)); } |
229 | }; |
230 | |
231 | // ============================================================================ |
232 | // [BLPipeFillData] |
233 | // ============================================================================ |
234 | |
235 | struct BLPipeFillData { |
236 | struct Common { |
237 | //! Rectangle to fill. |
238 | BLBoxI box; |
239 | //! Alpha value (range depends on target pixel format). |
240 | BLPipeValue32 alpha; |
241 | }; |
242 | |
243 | //! Rectangle (axis-aligned). |
244 | struct BoxAA { |
245 | //! Rectangle to fill. |
246 | BLBoxI box; |
247 | //! Alpha value (range depends on target pixel format). |
248 | BLPipeValue32 alpha; |
249 | }; |
250 | |
251 | //! Rectangle (axis-unaligned). |
252 | struct BoxAU { |
253 | //! Rectangle to fill. |
254 | BLBoxI box; |
255 | //! Alpha value (range depends on target pixel format). |
256 | BLPipeValue32 alpha; |
257 | |
258 | //! Masks of top, middle and bottom part of the rect. |
259 | uint32_t masks[3]; |
260 | //! Start width (from 1 to 3). |
261 | uint32_t startWidth; |
262 | //! Inner width (from 0 to width). |
263 | uint32_t innerWidth; |
264 | }; |
265 | |
266 | struct Analytic { |
267 | //! Fill boundary (x0 is ignored, x1 acts as maxWidth, y0/y1 are used normally). |
268 | BLBoxI box; |
269 | //! Alpha value (range depends on format). |
270 | BLPipeValue32 alpha; |
271 | //! All ones if NonZero or 0x01FF if EvenOdd. |
272 | uint32_t fillRuleMask; |
273 | |
274 | //! Shadow bit-buffer (marks a group of cells which are non-zero). |
275 | BLBitWord* bitTopPtr; |
276 | //! Bit-buffer stride (in bytes). |
277 | size_t bitStride; |
278 | |
279 | //! Cell buffer. |
280 | uint32_t* cellTopPtr; |
281 | //! Cell stride (in bytes). |
282 | size_t cellStride; |
283 | }; |
284 | |
285 | union { |
286 | Common common; |
287 | BoxAA boxAA; |
288 | BoxAU boxAU; |
289 | Analytic analytic; |
290 | }; |
291 | |
292 | inline void reset() noexcept { memset(this, 0, sizeof(*this)); } |
293 | |
294 | // -------------------------------------------------------------------------- |
295 | // [Init] |
296 | // -------------------------------------------------------------------------- |
297 | |
298 | inline uint32_t initBoxAA8bpc(uint32_t alpha, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1) noexcept { |
299 | // The rendering engine should never pass out-of-range alpha. |
300 | BL_ASSERT(alpha <= 256); |
301 | |
302 | // The rendering engine should never pass invalid box to the pipeline. |
303 | BL_ASSERT(x0 < x1); |
304 | BL_ASSERT(y0 < y1); |
305 | |
306 | boxAA.alpha.u = alpha; |
307 | boxAA.box.reset(int(x0), int(y0), int(x1), int(y1)); |
308 | return BL_PIPE_FILL_TYPE_BOX_AA; |
309 | } |
310 | |
311 | template<typename T> |
312 | inline uint32_t initBoxAU8bpcT(uint32_t alpha, T x0, T y0, T x1, T y1) noexcept { |
313 | return initBoxAU8bpc24x8(alpha, uint32_t(blTruncToInt(x0 * T(256))), |
314 | uint32_t(blTruncToInt(y0 * T(256))), |
315 | uint32_t(blTruncToInt(x1 * T(256))), |
316 | uint32_t(blTruncToInt(y1 * T(256)))); |
317 | } |
318 | |
319 | uint32_t initBoxAU8bpc24x8(uint32_t alpha, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1) noexcept { |
320 | // The rendering engine should never pass out-of-range alpha. |
321 | BL_ASSERT(alpha <= 256); |
322 | |
323 | uint32_t ax0 = x0 >> 8; |
324 | uint32_t ay0 = y0 >> 8; |
325 | uint32_t ax1 = x1 >> 8; |
326 | uint32_t ay1 = y1 >> 8; |
327 | |
328 | boxAU.alpha.u = alpha; |
329 | boxAU.box.reset(int(ax0), int(ay0), int(ax1), int(ay1)); |
330 | |
331 | // Special case - coordinates are very close (nothing to render). |
332 | if (x0 >= x1 || y0 >= y1) |
333 | return BL_PIPE_FILL_TYPE_NONE; |
334 | |
335 | // Special case - aligned box. |
336 | if (((x0 | x1 | y0 | y1) & 0xFFu) == 0u) |
337 | return BL_PIPE_FILL_TYPE_BOX_AA; |
338 | |
339 | uint32_t fx0 = x0 & 0xFFu; |
340 | uint32_t fy0 = y0 & 0xFFu; |
341 | uint32_t fx1 = x1 & 0xFFu; |
342 | uint32_t fy1 = y1 & 0xFFu; |
343 | |
344 | boxAU.box.x1 += fx1 != 0; |
345 | boxAU.box.y1 += fy1 != 0; |
346 | |
347 | if (fx1 == 0) fx1 = 256; |
348 | if (fy1 == 0) fy1 = 256; |
349 | |
350 | fx0 = 256 - fx0; |
351 | fy0 = 256 - fy0; |
352 | |
353 | if ((x0 & ~0xFFu) == (x1 & ~0xFFu)) { fx0 = fx1 - fx0; fx1 = 0; } |
354 | if ((y0 & ~0xFFu) == (y1 & ~0xFFu)) { fy0 = fy1 - fy0; fy1 = 0; } |
355 | |
356 | uint32_t iw = uint32_t(boxAU.box.x1 - boxAU.box.x0); |
357 | uint32_t m0 = ((fx1 * fy0) >> 8); |
358 | uint32_t m1 = ( fx1 ); |
359 | uint32_t m2 = ((fx1 * fy1) >> 8); |
360 | |
361 | if (iw > 2) { |
362 | m0 = (m0 << 9) + fy0; |
363 | m1 = (m1 << 9) + 256; |
364 | m2 = (m2 << 9) + fy1; |
365 | } |
366 | |
367 | if (iw > 1) { |
368 | m0 = (m0 << 9) + ((fx0 * fy0) >> 8); |
369 | m1 = (m1 << 9) + fx0; |
370 | m2 = (m2 << 9) + ((fx0 * fy1) >> 8); |
371 | } |
372 | |
373 | if (alpha != 256) { |
374 | m0 = mulPackedMaskByAlpha(m0, alpha); |
375 | m1 = mulPackedMaskByAlpha(m1, alpha); |
376 | m2 = mulPackedMaskByAlpha(m2, alpha); |
377 | } |
378 | |
379 | boxAU.masks[0] = m0; |
380 | boxAU.masks[1] = m1; |
381 | boxAU.masks[2] = m2; |
382 | |
383 | if (iw > 3) { |
384 | boxAU.startWidth = 1; |
385 | boxAU.innerWidth = iw - 2; |
386 | } |
387 | else { |
388 | boxAU.startWidth = iw; |
389 | boxAU.innerWidth = 0; |
390 | } |
391 | |
392 | return BL_PIPE_FILL_TYPE_BOX_AU; |
393 | } |
394 | |
395 | inline uint32_t initAnalytic(uint32_t alpha, BLBitWord* bitTopPtr, size_t bitStride, uint32_t* cellTopPtr, size_t cellStride) noexcept { |
396 | analytic.alpha.u = alpha; |
397 | analytic.bitTopPtr = bitTopPtr; |
398 | analytic.bitStride = bitStride; |
399 | analytic.cellTopPtr = cellTopPtr; |
400 | analytic.cellStride = cellStride; |
401 | |
402 | return BL_PIPE_FILL_TYPE_ANALYTIC; |
403 | } |
404 | |
405 | // -------------------------------------------------------------------------- |
406 | // [Helpers] |
407 | // -------------------------------------------------------------------------- |
408 | |
409 | static inline uint32_t mulPackedMaskByAlpha(uint32_t m, uint32_t alpha) noexcept { |
410 | return (((((m >> 18) ) * alpha) >> 8) << 18) | |
411 | (((((m >> 9) & 0x1FF) * alpha) >> 8) << 9) | |
412 | (((((m ) & 0x1FF) * alpha) >> 8) ) ; |
413 | } |
414 | }; |
415 | |
416 | // ============================================================================ |
417 | // [BLPipeFetchData] |
418 | // ============================================================================ |
419 | |
420 | //! Blend2D pipeline fetch data. |
421 | struct alignas(16) BLPipeFetchData { |
422 | //! Solid fetch data. |
423 | struct Solid { |
424 | union { |
425 | //! 32-bit ARGB, premultiplied. |
426 | uint32_t prgb32; |
427 | //! 64-bit ARGB, premultiplied. |
428 | uint64_t prgb64; |
429 | }; |
430 | |
431 | BL_INLINE void reset() noexcept { memset(this, 0, sizeof(*this)); } |
432 | }; |
433 | |
434 | //! Pattern fetch data. |
435 | struct alignas(16) Pattern { |
436 | //! Source image data. |
437 | struct SourceData { |
438 | const uint8_t* pixelData; |
439 | intptr_t stride; |
440 | BLSizeI size; |
441 | }; |
442 | |
443 | //! Simple pattern data (only identity or translation matrix). |
444 | struct alignas(16) Simple { |
445 | //! Translate by x/y (inverted). |
446 | int32_t tx, ty; |
447 | //! Repeat/Reflect w/h. |
448 | int32_t rx, ry; |
449 | //! Safe X increments by 1..16 (fetchN). |
450 | BLModuloTable ix; |
451 | //! 9-bit or 17-bit weight at [0, 0] (A). |
452 | uint32_t wa; |
453 | //! 9-bit or 17-bit weight at [1, 0] (B). |
454 | uint32_t wb; |
455 | //! 9-bit or 17-bit weight at [0, 1] (C). |
456 | uint32_t wc; |
457 | //! 9-bit or 17-bit weight at [1, 1] (D). |
458 | uint32_t wd; |
459 | }; |
460 | |
461 | //! Affine pattern data. |
462 | struct alignas(16) Affine { |
463 | //! Single X/Y step in X direction. |
464 | BLPipeValue64 xx, xy; |
465 | //! Single X/Y step in Y direction. |
466 | BLPipeValue64 yx, yy; |
467 | //! Pattern offset at [0, 0]. |
468 | BLPipeValue64 tx, ty; |
469 | //! Pattern overflow check. |
470 | BLPipeValue64 ox, oy; |
471 | //! Pattern overflow correction (repeat/reflect). |
472 | BLPipeValue64 rx, ry; |
473 | //! Two X/Y steps in X direction, used by `fetch4()`. |
474 | BLPipeValue64 xx2, xy2; |
475 | //! Pattern padding minimum (0 for PAD, INT32_MIN for other modes). |
476 | int32_t minX, minY; |
477 | //! Pattern padding maximum (width-1 and height-1). |
478 | int32_t maxX, maxY; |
479 | //! Pattern correction X/Y in case that maxX/maxY was exceeded (PAD, BILINEAR) |
480 | int32_t corX, corY; |
481 | //! Repeated tile width/height (doubled if reflected). |
482 | double tw, th; |
483 | |
484 | //! 32-bit value to be used by [V]PMADDWD instruction to calculate address from Y/X pairs. |
485 | int16_t addrMul[2]; |
486 | }; |
487 | |
488 | //! Source image data. |
489 | SourceData src; |
490 | |
491 | union { |
492 | //! Simple pattern data. |
493 | Simple simple; |
494 | //! Affine pattern data. |
495 | Affine affine; |
496 | }; |
497 | |
498 | BL_INLINE void reset() noexcept { memset(this, 0, sizeof(*this)); } |
499 | }; |
500 | |
501 | //! Gradient fetch data. |
502 | struct alignas(16) Gradient { |
503 | //! Precomputed lookup table, used by all gradient fetchers. |
504 | struct LUT { |
505 | //! Pixel data, array of either 32-bit or 64-bit pixels. |
506 | const void* data; |
507 | //! Number of pixels stored in `data`, must be a power of 2. |
508 | uint32_t size; |
509 | }; |
510 | |
511 | //! Linear gradient data. |
512 | struct alignas(16) Linear { |
513 | //! Gradient offset of the pixel at [0, 0]. |
514 | BLPipeValue64 pt[2]; |
515 | //! One Y step. |
516 | BLPipeValue64 dy; |
517 | //! One X step. |
518 | BLPipeValue64 dt; |
519 | //! Two X steps. |
520 | BLPipeValue64 dt2; |
521 | //! Reflect/Repeat mask (repeated/reflected size - 1). |
522 | BLPipeValue64 rep; |
523 | //! Size mask (gradient size - 1). |
524 | BLPipeValue32 msk; |
525 | }; |
526 | |
527 | //! Radial gradient data. |
528 | struct alignas(16) Radial { |
529 | //! Gradient X/Y increments (horizontal). |
530 | double xx, xy; |
531 | //! Gradient X/Y increments (vertical). |
532 | double yx, yy; |
533 | //! Gradient X/Y offsets of the pixel at [0, 0]. |
534 | double ox, oy; |
535 | |
536 | double ax, ay; |
537 | double fx, fy; |
538 | |
539 | double dd, bd; |
540 | double ddx, ddy; |
541 | double ddd, scale; |
542 | |
543 | int maxi; |
544 | }; |
545 | |
546 | //! Conical gradient data. |
547 | struct alignas(16) Conical { |
548 | //! Gradient X/Y increments (horizontal). |
549 | double xx, xy; |
550 | //! Gradient X/Y increments (vertical). |
551 | double yx, yy; |
552 | //! Gradient X/Y offsets of the pixel at [0, 0]. |
553 | double ox, oy; |
554 | //! Atan2 approximation constants. |
555 | const BLCommonTable::Conical* consts; |
556 | |
557 | int maxi; |
558 | }; |
559 | |
560 | //! Precomputed lookup table. |
561 | LUT lut; |
562 | //! Union of all possible gradient data types. |
563 | union { |
564 | //! Linear gradient specific data. |
565 | Linear linear; |
566 | //! Radial gradient specific data. |
567 | Radial radial; |
568 | //! Conical gradient specific data. |
569 | Conical conical; |
570 | }; |
571 | |
572 | BL_INLINE void reset() noexcept { memset(this, 0, sizeof(*this)); } |
573 | }; |
574 | |
575 | //! Union of all possible fetch data types. |
576 | union { |
577 | //! Solid fetch data. |
578 | Solid solid; |
579 | //! Pattern fetch data. |
580 | Pattern pattern; |
581 | //! Gradient fetch data. |
582 | Gradient gradient; |
583 | }; |
584 | |
585 | BL_INLINE void reset() noexcept { memset(this, 0, sizeof(*this)); } |
586 | |
587 | BL_INLINE void initPatternSource(const uint8_t* pixelData, intptr_t stride, int w, int h) noexcept { |
588 | pattern.src.pixelData = pixelData; |
589 | pattern.src.stride = stride; |
590 | pattern.src.size.reset(w, h); |
591 | } |
592 | |
593 | BL_INLINE uint32_t initPatternBlit() noexcept { |
594 | pattern.simple.tx = 0; |
595 | pattern.simple.ty = 0; |
596 | pattern.simple.rx = 0; |
597 | pattern.simple.ry = 0; |
598 | return BL_PIPE_FETCH_TYPE_PATTERN_AA_BLIT; |
599 | } |
600 | |
601 | BL_HIDDEN uint32_t initPatternAxAy( |
602 | uint32_t extendMode, |
603 | int x, int y) noexcept; |
604 | |
605 | BL_HIDDEN uint32_t initPatternFxFy( |
606 | uint32_t extendMode, |
607 | uint32_t filter, |
608 | int64_t tx64, int64_t ty64) noexcept; |
609 | |
610 | BL_HIDDEN uint32_t initPatternAffine( |
611 | uint32_t extendMode, |
612 | uint32_t filter, |
613 | const BLMatrix2D& m, |
614 | const BLMatrix2D& mInv) noexcept; |
615 | |
616 | BL_HIDDEN uint32_t initGradient( |
617 | uint32_t gradientType, |
618 | const void* values, |
619 | uint32_t extendMode, |
620 | const BLGradientLUT* lut, |
621 | const BLMatrix2D& m, |
622 | const BLMatrix2D& mInv) noexcept; |
623 | }; |
624 | |
625 | // ============================================================================ |
626 | // [BLPipeSignature] |
627 | // ============================================================================ |
628 | |
629 | //! Pipeline signature packed to a single `uint32_t` value. |
630 | //! |
631 | //! Can be used to build signatures as well as it offers the required functionality. |
632 | struct BLPipeSignature { |
633 | //! Signature as a 32-bit value. |
634 | uint32_t value; |
635 | |
636 | BL_INLINE BLPipeSignature() noexcept = default; |
637 | BL_INLINE BLPipeSignature(const BLPipeSignature&) noexcept = default; |
638 | BL_INLINE explicit BLPipeSignature(uint32_t value) : value(value) {} |
639 | |
640 | BL_INLINE uint32_t _get(uint32_t mask) const noexcept { |
641 | return (this->value & mask) >> blBitShiftOf(mask); |
642 | } |
643 | |
644 | BL_INLINE void _set(uint32_t mask, uint32_t v) noexcept { |
645 | BL_ASSERT(v <= (mask >> blBitShiftOf(mask))); |
646 | this->value = (this->value & ~mask) | (v << blBitShiftOf(mask)); |
647 | } |
648 | |
649 | BL_INLINE void _add(uint32_t mask, uint32_t v) noexcept { |
650 | BL_ASSERT(v <= (mask >> blBitShiftOf(mask))); |
651 | this->value |= (v << blBitShiftOf(mask)); |
652 | } |
653 | |
654 | //! Reset all values to zero. |
655 | BL_INLINE void reset() noexcept { this->value = 0; } |
656 | //! Reset all values to other signature. |
657 | BL_INLINE void reset(uint32_t v) noexcept { this->value = v; } |
658 | |
659 | //! Set the signature from a packed 32-bit integer. |
660 | BL_INLINE void setValue(uint32_t v) noexcept { this->value = v; } |
661 | //! Set the signature from another `BLPipeSignature`. |
662 | BL_INLINE void setValue(const BLPipeSignature& other) noexcept { this->value = other.value; } |
663 | |
664 | //! Extracts destination pixel format from the signature. |
665 | BL_INLINE uint32_t dstFormat() const noexcept { return _get(BL_PIPE_SIGNATURE_DST_FORMAT); } |
666 | //! Extracts source pixel format from the signature. |
667 | BL_INLINE uint32_t srcFormat() const noexcept { return _get(BL_PIPE_SIGNATURE_SRC_FORMAT); } |
668 | //! Extracts composition operator from the signature. |
669 | BL_INLINE uint32_t compOp() const noexcept { return _get(BL_PIPE_SIGNATURE_COMP_OP); } |
670 | //! Extracts sweep type from the signature. |
671 | BL_INLINE uint32_t fillType() const noexcept { return _get(BL_PIPE_SIGNATURE_FILL_TYPE); } |
672 | //! Extracts fetch type from the signature. |
673 | BL_INLINE uint32_t fetchType() const noexcept { return _get(BL_PIPE_SIGNATURE_FETCH_TYPE); } |
674 | //! Extracts fetch data from the signature. |
675 | BL_INLINE uint32_t fetchPayload() const noexcept { return _get(BL_PIPE_SIGNATURE_FETCH_PAYLOAD); } |
676 | |
677 | //! Add destination pixel format. |
678 | BL_INLINE void setDstFormat(uint32_t v) noexcept { _set(BL_PIPE_SIGNATURE_DST_FORMAT, v); } |
679 | //! Add source pixel format. |
680 | BL_INLINE void setSrcFormat(uint32_t v) noexcept { _set(BL_PIPE_SIGNATURE_SRC_FORMAT, v); } |
681 | //! Add clip mode. |
682 | BL_INLINE void setCompOp(uint32_t v) noexcept { _set(BL_PIPE_SIGNATURE_COMP_OP, v); } |
683 | //! Add sweep type. |
684 | BL_INLINE void setFillType(uint32_t v) noexcept { _set(BL_PIPE_SIGNATURE_FILL_TYPE, v); } |
685 | //! Add fetch type. |
686 | BL_INLINE void setFetchType(uint32_t v) noexcept { _set(BL_PIPE_SIGNATURE_FETCH_TYPE, v); } |
687 | //! Add fetch data. |
688 | BL_INLINE void setFetchPayload(uint32_t v) noexcept { _set(BL_PIPE_SIGNATURE_FETCH_PAYLOAD, v); } |
689 | |
690 | // The following methods are used to build the signature. They use '|' operator |
691 | // which doesn't clear the previous value, each function is expected to be called |
692 | // only once when building a new signature. |
693 | |
694 | //! Combine with other signature. |
695 | BL_INLINE void add(uint32_t v) noexcept { this->value |= v; } |
696 | //! Combine with other signature. |
697 | BL_INLINE void add(const BLPipeSignature& other) noexcept { this->value |= other.value; } |
698 | |
699 | //! Add destination pixel format. |
700 | BL_INLINE void addDstFormat(uint32_t v) noexcept { _add(BL_PIPE_SIGNATURE_DST_FORMAT, v); } |
701 | //! Add source pixel format. |
702 | BL_INLINE void addSrcFormat(uint32_t v) noexcept { _add(BL_PIPE_SIGNATURE_SRC_FORMAT, v); } |
703 | //! Add clip mode. |
704 | BL_INLINE void addCompOp(uint32_t v) noexcept { _add(BL_PIPE_SIGNATURE_COMP_OP, v); } |
705 | //! Add sweep type. |
706 | BL_INLINE void addFillType(uint32_t v) noexcept { _add(BL_PIPE_SIGNATURE_FILL_TYPE, v); } |
707 | //! Add fetch type. |
708 | BL_INLINE void addFetchType(uint32_t v) noexcept { _add(BL_PIPE_SIGNATURE_FETCH_TYPE, v); } |
709 | //! Add fetch data. |
710 | BL_INLINE void addFetchPayload(uint32_t v) noexcept { _add(BL_PIPE_SIGNATURE_FETCH_PAYLOAD, v); } |
711 | }; |
712 | |
713 | //! \} |
714 | //! \endcond |
715 | |
716 | #endif // BLEND2D_BLPIPEDEFS_P_H |
717 | |