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
28struct BLPipeContextData;
29struct BLPipeFillData;
30struct BLPipeFetchData;
31struct BLPipeSignature;
32
33// ============================================================================
34// [Constants]
35// ============================================================================
36
37//! Global constants used by pipeline and affecting also rasterizers.
38enum 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.
53enum 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.
62enum 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.
74enum 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.
87enum 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.
98enum 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.
170enum 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
183typedef BLResult (BL_CDECL* BLPipeFillFunc)(void* ctxData, void* fillData, const void* fetchData) BL_NOEXCEPT;
184
185// ============================================================================
186// [BLPipeValue32]
187// ============================================================================
188
189union BLPipeValue32 {
190 uint32_t u;
191 int32_t i;
192 float f;
193};
194
195// ============================================================================
196// [BLPipeValue64]
197// ============================================================================
198
199union 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
225struct BLPipeContextData {
226 BLImageData dst;
227
228 BL_INLINE void reset() noexcept { memset(this, 0, sizeof(*this)); }
229};
230
231// ============================================================================
232// [BLPipeFillData]
233// ============================================================================
234
235struct 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.
421struct 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.
632struct 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