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_PIPEDEFS_P_H 8 #define BLEND2D_PIPEDEFS_P_H 9 10 #include "./api-internal_p.h" 11 #include "./format_p.h" 12 #include "./gradient_p.h" 13 #include "./matrix_p.h" 14 #include "./pattern_p.h" 15 #include "./runtime_p.h" 16 #include "./support_p.h" 17 #include "./tables_p.h" 18 #include "./simd_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 (special value, not a valid fetch type). 126 BL_PIPE_FETCH_TYPE_FAILURE = 0xFFFFFFFFu, //!< Invalid fetch type (special value, signalizes error). 127 128 BL_PIPE_FETCH_TYPE_PATTERN_ANY_FIRST = BL_PIPE_FETCH_TYPE_PATTERN_AA_BLIT, 129 BL_PIPE_FETCH_TYPE_PATTERN_ANY_LAST = BL_PIPE_FETCH_TYPE_PATTERN_AFFINE_BI_OPT, 130 131 BL_PIPE_FETCH_TYPE_PATTERN_AA_FIRST = BL_PIPE_FETCH_TYPE_PATTERN_AA_BLIT, 132 BL_PIPE_FETCH_TYPE_PATTERN_AA_LAST = BL_PIPE_FETCH_TYPE_PATTERN_AA_ROR, 133 134 BL_PIPE_FETCH_TYPE_PATTERN_AU_FIRST = BL_PIPE_FETCH_TYPE_PATTERN_FX_PAD, 135 BL_PIPE_FETCH_TYPE_PATTERN_AU_LAST = BL_PIPE_FETCH_TYPE_PATTERN_FX_FY_ROR, 136 137 BL_PIPE_FETCH_TYPE_PATTERN_FX_FIRST = BL_PIPE_FETCH_TYPE_PATTERN_FX_PAD, 138 BL_PIPE_FETCH_TYPE_PATTERN_FX_LAST = BL_PIPE_FETCH_TYPE_PATTERN_FX_ROR, 139 140 BL_PIPE_FETCH_TYPE_PATTERN_FY_FIRST = BL_PIPE_FETCH_TYPE_PATTERN_FY_PAD, 141 BL_PIPE_FETCH_TYPE_PATTERN_FY_LAST = BL_PIPE_FETCH_TYPE_PATTERN_FY_ROR, 142 143 BL_PIPE_FETCH_TYPE_PATTERN_FX_FY_FIRST = BL_PIPE_FETCH_TYPE_PATTERN_FX_FY_PAD, 144 BL_PIPE_FETCH_TYPE_PATTERN_FX_FY_LAST = BL_PIPE_FETCH_TYPE_PATTERN_FX_FY_ROR, 145 146 BL_PIPE_FETCH_TYPE_PATTERN_SIMPLE_FIRST = BL_PIPE_FETCH_TYPE_PATTERN_AA_BLIT, 147 BL_PIPE_FETCH_TYPE_PATTERN_SIMPLE_LAST = BL_PIPE_FETCH_TYPE_PATTERN_FX_FY_ROR, 148 149 BL_PIPE_FETCH_TYPE_PATTERN_AFFINE_FIRST = BL_PIPE_FETCH_TYPE_PATTERN_AFFINE_NN_ANY, 150 BL_PIPE_FETCH_TYPE_PATTERN_AFFINE_LAST = BL_PIPE_FETCH_TYPE_PATTERN_AFFINE_BI_OPT, 151 152 BL_PIPE_FETCH_TYPE_GRADIENT_ANY_FIRST = BL_PIPE_FETCH_TYPE_GRADIENT_LINEAR_PAD, 153 BL_PIPE_FETCH_TYPE_GRADIENT_ANY_LAST = BL_PIPE_FETCH_TYPE_GRADIENT_CONICAL, 154 155 BL_PIPE_FETCH_TYPE_GRADIENT_LINEAR_FIRST = BL_PIPE_FETCH_TYPE_GRADIENT_LINEAR_PAD, 156 BL_PIPE_FETCH_TYPE_GRADIENT_LINEAR_LAST = BL_PIPE_FETCH_TYPE_GRADIENT_LINEAR_ROR, 157 158 BL_PIPE_FETCH_TYPE_GRADIENT_RADIAL_FIRST = BL_PIPE_FETCH_TYPE_GRADIENT_RADIAL_PAD, 159 BL_PIPE_FETCH_TYPE_GRADIENT_RADIAL_LAST = BL_PIPE_FETCH_TYPE_GRADIENT_RADIAL_REFLECT, 160 161 BL_PIPE_FETCH_TYPE_GRADIENT_CONICAL_FIRST = BL_PIPE_FETCH_TYPE_GRADIENT_CONICAL, 162 BL_PIPE_FETCH_TYPE_GRADIENT_CONICAL_LAST = BL_PIPE_FETCH_TYPE_GRADIENT_CONICAL 163 }; 164 165 //! Masks used by `BLPipeSignature`. 166 //! 167 //! Each mask represents one value in a signature. Each value describes a part 168 //! in a signature like format, composition operator, etc. All parts packed 169 //! together form a 32-bit integer that can be used to uniquely describe the 170 //! whole pipeline and can act as a key or hash-code in pipeline function caches. 171 enum BLPipeSignatureMasks : uint32_t { 172 BL_PIPE_SIGNATURE_DST_FORMAT = 0x0000000Fu << 0, // [00..03] {16 values} 173 BL_PIPE_SIGNATURE_SRC_FORMAT = 0x0000000Fu << 4, // [04..07] {16 values} 174 BL_PIPE_SIGNATURE_COMP_OP = 0x0000003Fu << 8, // [08..13] {64 values} 175 BL_PIPE_SIGNATURE_FILL_TYPE = 0x00000003u << 14, // [14..15] {4 values} 176 BL_PIPE_SIGNATURE_FETCH_TYPE = 0x0000001Fu << 16, // [16..20] {32 values} 177 BL_PIPE_SIGNATURE_FETCH_PAYLOAD = 0x000007FFu << 21 // [21..31] {2048 values} 178 }; 179 180 // ============================================================================ 181 // [Typedefs] 182 // ============================================================================ 183 184 typedef void (BL_CDECL* BLPipeFillFunc)(void* ctxData, void* fillData, const void* fetchData) BL_NOEXCEPT; 185 186 // ============================================================================ 187 // [BLPipeValue32] 188 // ============================================================================ 189 190 union BLPipeValue32 { 191 uint32_t u; 192 int32_t i; 193 float f; 194 }; 195 196 // ============================================================================ 197 // [BLPipeValue64] 198 // ============================================================================ 199 200 union BLPipeValue64 { 201 uint64_t u64; 202 int64_t i64; 203 double d; 204 205 int32_t i32[2]; 206 uint32_t u32[2]; 207 208 int16_t i16[4]; 209 uint16_t u16[4]; 210 211 #if BL_BYTE_ORDER == 1234 // LITTLE ENDIAN 212 struct { int32_t i32Lo, i32Hi; }; 213 struct { uint32_t u32Lo, u32Hi; }; 214 #else 215 struct { int32_t i32Hi, i32Lo; }; 216 struct { uint32_t u32Hi, u32Lo; }; 217 #endif 218 expandLoToHi()219 BL_INLINE void expandLoToHi() noexcept { u32Hi = u32Lo; } 220 }; 221 222 // ============================================================================ 223 // [BLPipeContextData] 224 // ============================================================================ 225 226 struct BLPipeContextData { 227 BLImageData dst; 228 resetBLPipeContextData229 BL_INLINE void reset() noexcept { memset(this, 0, sizeof(*this)); } 230 }; 231 232 // ============================================================================ 233 // [BLPipeFillData] 234 // ============================================================================ 235 236 struct BLPipeFillData { 237 struct Common { 238 //! Rectangle to fill. 239 BLBoxI box; 240 //! Alpha value (range depends on target pixel format). 241 BLPipeValue32 alpha; 242 }; 243 244 //! Rectangle (axis-aligned). 245 struct BoxAA { 246 //! Rectangle to fill. 247 BLBoxI box; 248 //! Alpha value (range depends on target pixel format). 249 BLPipeValue32 alpha; 250 }; 251 252 //! Rectangle (axis-unaligned). 253 struct BoxAU { 254 //! Rectangle to fill. 255 BLBoxI box; 256 //! Alpha value (range depends on target pixel format). 257 BLPipeValue32 alpha; 258 259 //! Masks of top, middle and bottom part of the rect. 260 //! 261 //! \note The last value `masks[3]` must be zero as it's a sentinel for the pipeline. 262 uint32_t masks[4]; 263 //! Height of the middle (1) and last (2) masks. 264 uint32_t heights[2]; 265 //! Start width (from 1 to 3). 266 uint32_t startWidth; 267 //! Inner width (from 0 to width). 268 uint32_t innerWidth; 269 }; 270 271 struct Analytic { 272 //! Fill boundary (x0 is ignored, x1 acts as maxWidth, y0/y1 are used normally). 273 BLBoxI box; 274 //! Alpha value (range depends on format). 275 BLPipeValue32 alpha; 276 //! All ones if NonZero or 0x01FF if EvenOdd. 277 uint32_t fillRuleMask; 278 279 //! Shadow bit-buffer (marks a group of cells which are non-zero). 280 BLBitWord* bitTopPtr; 281 //! Bit-buffer stride (in bytes). 282 size_t bitStride; 283 284 //! Cell buffer. 285 uint32_t* cellTopPtr; 286 //! Cell stride (in bytes). 287 size_t cellStride; 288 }; 289 290 union { 291 Common common; 292 BoxAA boxAA; 293 BoxAU boxAU; 294 Analytic analytic; 295 }; 296 resetBLPipeFillData297 inline void reset() noexcept { memset(this, 0, sizeof(*this)); } 298 299 // -------------------------------------------------------------------------- 300 // [Init] 301 // -------------------------------------------------------------------------- 302 initBoxAA8bpcBLPipeFillData303 inline uint32_t initBoxAA8bpc(uint32_t alpha, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1) noexcept { 304 // The rendering engine should never pass out-of-range alpha. 305 BL_ASSERT(alpha <= 256); 306 307 // The rendering engine should never pass invalid box to the pipeline. 308 BL_ASSERT(x0 < x1); 309 BL_ASSERT(y0 < y1); 310 311 boxAA.alpha.u = alpha; 312 boxAA.box.reset(int(x0), int(y0), int(x1), int(y1)); 313 return BL_PIPE_FILL_TYPE_BOX_AA; 314 } 315 316 template<typename T> initBoxAU8bpcTBLPipeFillData317 inline uint32_t initBoxAU8bpcT(uint32_t alpha, T x0, T y0, T x1, T y1) noexcept { 318 return initBoxAU8bpc24x8(alpha, uint32_t(blTruncToInt(x0 * T(256))), 319 uint32_t(blTruncToInt(y0 * T(256))), 320 uint32_t(blTruncToInt(x1 * T(256))), 321 uint32_t(blTruncToInt(y1 * T(256)))); 322 } 323 initBoxAU8bpc24x8BLPipeFillData324 uint32_t initBoxAU8bpc24x8(uint32_t alpha, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1) noexcept { 325 // The rendering engine should never pass out-of-range alpha. 326 BL_ASSERT(alpha <= 256); 327 328 uint32_t ax0 = x0 >> 8; 329 uint32_t ay0 = y0 >> 8; 330 uint32_t ax1 = x1 >> 8; 331 uint32_t ay1 = y1 >> 8; 332 333 boxAU.alpha.u = alpha; 334 boxAU.box.reset(int(ax0), int(ay0), int(ax1), int(ay1)); 335 336 // Special case - coordinates are very close (nothing to render). 337 if (x0 >= x1 || y0 >= y1) 338 return BL_PIPE_FILL_TYPE_NONE; 339 340 // Special case - aligned box. 341 if (((x0 | x1 | y0 | y1) & 0xFFu) == 0u) 342 return BL_PIPE_FILL_TYPE_BOX_AA; 343 344 uint32_t fx0 = x0 & 0xFFu; 345 uint32_t fy0 = y0 & 0xFFu; 346 uint32_t fx1 = x1 & 0xFFu; 347 uint32_t fy1 = y1 & 0xFFu; 348 349 boxAU.box.x1 += fx1 != 0; 350 boxAU.box.y1 += fy1 != 0; 351 352 if (!fx1) fx1 = 256; 353 if (!fy1) fy1 = 256; 354 355 if (((x0 ^ x1) >> 8) == 0) { fx0 = fx1 - fx0; fx1 = 0; } else { fx0 = 256 - fx0; } 356 if (((y0 ^ y1) >> 8) == 0) { fy0 = fy1 - fy0; fy1 = 0; } else { fy0 = 256 - fy0; } 357 358 uint32_t fy0_a = fy0 * alpha; 359 uint32_t fy1_a = fy1 * alpha; 360 361 uint32_t m0 = (fx1 * fy0_a) >> 16; 362 uint32_t m1 = (fx1 * alpha) >> 8; 363 uint32_t m2 = (fx1 * fy0_a) >> 16; 364 365 uint32_t iw = uint32_t(boxAU.box.x1 - boxAU.box.x0); 366 if (iw > 2) { 367 m0 = (m0 << 8) | (fy0_a >> 8); 368 m1 = (m1 << 8) | alpha; 369 m2 = (m2 << 8) | (fy1_a >> 8); 370 } 371 372 if (iw > 1) { 373 m0 = (m0 << 8) | ((fx0 * fy0_a) >> 16); 374 m1 = (m1 << 8) | ((fx0 * alpha) >> 8); 375 m2 = (m2 << 8) | ((fx0 * fy1_a) >> 16); 376 } 377 378 if (!m1) 379 return BL_PIPE_FILL_TYPE_NONE; 380 381 // Border case - if alpha is too low it can cause `m0` or `m2` to be zero, 382 // which would then confuse the pipeline as it would think to stop instead 383 // of jumping to 'CMask' loop. So we patch `m0` 384 if (!m0) { 385 m0 = m1; 386 boxAU.box.y0++; 387 if (boxAU.box.y0 == boxAU.box.y1) 388 return BL_PIPE_FILL_TYPE_NONE; 389 } 390 391 uint32_t ih = uint32_t(boxAU.box.y1 - boxAU.box.y0); 392 393 boxAU.masks[0] = m0; 394 boxAU.masks[1] = m1; 395 boxAU.masks[2] = m2; 396 boxAU.masks[3] = 0; 397 boxAU.heights[0] = ih - 2; 398 boxAU.heights[1] = 1; 399 400 // There is no middle layer (m1) if the height is 2 pixels or less. 401 if (ih <= 2) { 402 boxAU.masks[1] = boxAU.masks[2]; 403 boxAU.masks[2] = 0; 404 boxAU.heights[0] = ih - 1; 405 boxAU.heights[1] = 0; 406 } 407 408 if (ih <= 1) { 409 boxAU.masks[1] = 0; 410 boxAU.heights[0] = 0; 411 } 412 413 if (iw > 3) { 414 boxAU.startWidth = 1; 415 boxAU.innerWidth = iw - 2; 416 } 417 else { 418 boxAU.startWidth = iw; 419 boxAU.innerWidth = 0; 420 } 421 422 return BL_PIPE_FILL_TYPE_BOX_AU; 423 } 424 initAnalyticBLPipeFillData425 inline uint32_t initAnalytic(uint32_t alpha, BLBitWord* bitTopPtr, size_t bitStride, uint32_t* cellTopPtr, size_t cellStride) noexcept { 426 analytic.alpha.u = alpha; 427 analytic.bitTopPtr = bitTopPtr; 428 analytic.bitStride = bitStride; 429 analytic.cellTopPtr = cellTopPtr; 430 analytic.cellStride = cellStride; 431 432 return BL_PIPE_FILL_TYPE_ANALYTIC; 433 } 434 }; 435 436 // ============================================================================ 437 // [BLPipeFetchData] 438 // ============================================================================ 439 440 //! Blend2D pipeline fetch data. 441 struct alignas(16) BLPipeFetchData { 442 //! Solid fetch data. 443 struct Solid { 444 union { 445 //! 32-bit ARGB, premultiplied. 446 uint32_t prgb32; 447 //! 64-bit ARGB, premultiplied. 448 uint64_t prgb64; 449 }; 450 resetBLPipeFetchData::Solid451 BL_INLINE void reset() noexcept { memset(this, 0, sizeof(*this)); } 452 }; 453 454 //! Pattern fetch data. 455 struct alignas(16) Pattern { 456 //! Source image data. 457 struct SourceData { 458 const uint8_t* pixelData; 459 intptr_t stride; 460 BLSizeI size; 461 }; 462 463 //! Simple pattern data (only identity or translation matrix). 464 struct alignas(16) Simple { 465 //! Translate by x/y (inverted). 466 int32_t tx, ty; 467 //! Repeat/Reflect w/h. 468 int32_t rx, ry; 469 //! Safe X increments by 1..16 (fetchN). 470 BLModuloTable ix; 471 //! 9-bit or 17-bit weight at [0, 0] (A). 472 uint32_t wa; 473 //! 9-bit or 17-bit weight at [1, 0] (B). 474 uint32_t wb; 475 //! 9-bit or 17-bit weight at [0, 1] (C). 476 uint32_t wc; 477 //! 9-bit or 17-bit weight at [1, 1] (D). 478 uint32_t wd; 479 }; 480 481 //! Affine pattern data. 482 struct alignas(16) Affine { 483 //! Single X/Y step in X direction. 484 BLPipeValue64 xx, xy; 485 //! Single X/Y step in Y direction. 486 BLPipeValue64 yx, yy; 487 //! Pattern offset at [0, 0]. 488 BLPipeValue64 tx, ty; 489 //! Pattern overflow check. 490 BLPipeValue64 ox, oy; 491 //! Pattern overflow correction (repeat/reflect). 492 BLPipeValue64 rx, ry; 493 //! Two X/Y steps in X direction, used by `fetch4()`. 494 BLPipeValue64 xx2, xy2; 495 //! Pattern padding minimum (0 for PAD, INT32_MIN for other modes). 496 int32_t minX, minY; 497 //! Pattern padding maximum (width-1 and height-1). 498 int32_t maxX, maxY; 499 //! Correction X/Y values in case that maxX/maxY was exceeded (PAD, BILINEAR) 500 int32_t corX, corY; 501 //! Repeated tile width/height (doubled if reflected). 502 double tw, th; 503 504 //! 32-bit value to be used by [V]PMADDWD instruction to calculate address from Y/X pairs. 505 int16_t addrMul[2]; 506 }; 507 508 //! Source image data. 509 SourceData src; 510 511 union { 512 //! Simple pattern data. 513 Simple simple; 514 //! Affine pattern data. 515 Affine affine; 516 }; 517 resetBLPipeFetchData::Pattern518 BL_INLINE void reset() noexcept { memset(this, 0, sizeof(*this)); } 519 }; 520 521 //! Gradient fetch data. 522 struct alignas(16) Gradient { 523 //! Precomputed lookup table, used by all gradient fetchers. 524 struct LUT { 525 //! Pixel data, array of either 32-bit or 64-bit pixels. 526 const void* data; 527 //! Number of pixels stored in `data`, must be a power of 2. 528 uint32_t size; 529 }; 530 531 //! Linear gradient data. 532 struct alignas(16) Linear { 533 //! Gradient offset of the pixel at [0, 0]. 534 BLPipeValue64 pt[2]; 535 //! One Y step. 536 BLPipeValue64 dy; 537 //! One X step. 538 BLPipeValue64 dt; 539 //! Two X steps. 540 BLPipeValue64 dt2; 541 //! Reflect/Repeat mask (repeated/reflected size - 1). 542 BLPipeValue64 rep; 543 //! Size mask (gradient size - 1). 544 BLPipeValue32 msk; 545 }; 546 547 //! Radial gradient data. 548 struct alignas(16) Radial { 549 //! Gradient X/Y increments (horizontal). 550 double xx, xy; 551 //! Gradient X/Y increments (vertical). 552 double yx, yy; 553 //! Gradient X/Y offsets of the pixel at [0, 0]. 554 double ox, oy; 555 556 double ax, ay; 557 double fx, fy; 558 559 double dd, bd; 560 double ddx, ddy; 561 double ddd, scale; 562 563 int maxi; 564 }; 565 566 //! Conical gradient data. 567 struct alignas(16) Conical { 568 //! Gradient X/Y increments (horizontal). 569 double xx, xy; 570 //! Gradient X/Y increments (vertical). 571 double yx, yy; 572 //! Gradient X/Y offsets of the pixel at [0, 0]. 573 double ox, oy; 574 //! Atan2 approximation constants. 575 const BLCommonTable::Conical* consts; 576 577 int maxi; 578 }; 579 580 //! Precomputed lookup table. 581 LUT lut; 582 //! Union of all possible gradient data types. 583 union { 584 //! Linear gradient specific data. 585 Linear linear; 586 //! Radial gradient specific data. 587 Radial radial; 588 //! Conical gradient specific data. 589 Conical conical; 590 }; 591 resetBLPipeFetchData::Gradient592 BL_INLINE void reset() noexcept { memset(this, 0, sizeof(*this)); } 593 }; 594 595 //! Union of all possible fetch data types. 596 union { 597 //! Solid fetch data. 598 Solid solid; 599 //! Pattern fetch data. 600 Pattern pattern; 601 //! Gradient fetch data. 602 Gradient gradient; 603 }; 604 resetBLPipeFetchData605 BL_INLINE void reset() noexcept { memset(this, 0, sizeof(*this)); } 606 initPatternSourceBLPipeFetchData607 BL_INLINE void initPatternSource(const uint8_t* pixelData, intptr_t stride, int w, int h) noexcept { 608 pattern.src.pixelData = pixelData; 609 pattern.src.stride = stride; 610 pattern.src.size.reset(w, h); 611 } 612 initPatternBlitBLPipeFetchData613 BL_INLINE uint32_t initPatternBlit() noexcept { 614 pattern.simple.tx = 0; 615 pattern.simple.ty = 0; 616 pattern.simple.rx = 0; 617 pattern.simple.ry = 0; 618 return BL_PIPE_FETCH_TYPE_PATTERN_AA_BLIT; 619 } 620 621 BL_HIDDEN uint32_t initPatternAxAy( 622 uint32_t extendMode, 623 int x, int y) noexcept; 624 625 BL_HIDDEN uint32_t initPatternFxFy( 626 uint32_t extendMode, 627 uint32_t filter, 628 uint32_t bytesPerPixel, 629 int64_t tx64, int64_t ty64) noexcept; 630 631 BL_HIDDEN uint32_t initPatternAffine( 632 uint32_t extendMode, 633 uint32_t filter, 634 uint32_t bytesPerPixel, 635 const BLMatrix2D& m) noexcept; 636 637 BL_HIDDEN uint32_t initGradient( 638 uint32_t gradientType, 639 const void* values, 640 uint32_t extendMode, 641 const BLGradientLUT* lut, 642 const BLMatrix2D& m) noexcept; 643 }; 644 645 // ============================================================================ 646 // [BLPipeSignature] 647 // ============================================================================ 648 649 //! Pipeline signature packed to a single `uint32_t` value. 650 //! 651 //! Can be used to build signatures as well as it offers the required functionality. 652 struct BLPipeSignature { 653 //! Signature as a 32-bit value. 654 uint32_t value; 655 656 BL_INLINE BLPipeSignature() noexcept = default; 657 BL_INLINE constexpr BLPipeSignature(const BLPipeSignature&) noexcept = default; BLPipeSignatureBLPipeSignature658 BL_INLINE explicit constexpr BLPipeSignature(uint32_t value) : value(value) {} 659 660 BL_INLINE bool operator==(const BLPipeSignature& other) const noexcept { return value == other.value; } 661 BL_INLINE bool operator!=(const BLPipeSignature& other) const noexcept { return value != other.value; } 662 _getBLPipeSignature663 BL_INLINE uint32_t _get(uint32_t mask) const noexcept { 664 return (this->value & mask) >> blBitShiftOf(mask); 665 } 666 _setBLPipeSignature667 BL_INLINE void _set(uint32_t mask, uint32_t v) noexcept { 668 BL_ASSERT(v <= (mask >> blBitShiftOf(mask))); 669 this->value = (this->value & ~mask) | (v << blBitShiftOf(mask)); 670 } 671 _addBLPipeSignature672 BL_INLINE void _add(uint32_t mask, uint32_t v) noexcept { 673 BL_ASSERT(v <= (mask >> blBitShiftOf(mask))); 674 this->value |= (v << blBitShiftOf(mask)); 675 } 676 677 //! Reset all values to zero. resetBLPipeSignature678 BL_INLINE void reset() noexcept { this->value = 0; } 679 //! Reset all values to other signature. resetBLPipeSignature680 BL_INLINE void reset(uint32_t v) noexcept { this->value = v; } 681 682 //! Set the signature from a packed 32-bit integer. setValueBLPipeSignature683 BL_INLINE void setValue(uint32_t v) noexcept { this->value = v; } 684 //! Set the signature from another `BLPipeSignature`. setValueBLPipeSignature685 BL_INLINE void setValue(const BLPipeSignature& other) noexcept { this->value = other.value; } 686 687 //! Extracts destination pixel format from the signature. dstFormatBLPipeSignature688 BL_INLINE uint32_t dstFormat() const noexcept { return _get(BL_PIPE_SIGNATURE_DST_FORMAT); } 689 //! Extracts source pixel format from the signature. srcFormatBLPipeSignature690 BL_INLINE uint32_t srcFormat() const noexcept { return _get(BL_PIPE_SIGNATURE_SRC_FORMAT); } 691 //! Extracts composition operator from the signature. compOpBLPipeSignature692 BL_INLINE uint32_t compOp() const noexcept { return _get(BL_PIPE_SIGNATURE_COMP_OP); } 693 //! Extracts sweep type from the signature. fillTypeBLPipeSignature694 BL_INLINE uint32_t fillType() const noexcept { return _get(BL_PIPE_SIGNATURE_FILL_TYPE); } 695 //! Extracts fetch type from the signature. fetchTypeBLPipeSignature696 BL_INLINE uint32_t fetchType() const noexcept { return _get(BL_PIPE_SIGNATURE_FETCH_TYPE); } 697 //! Extracts fetch data from the signature. fetchPayloadBLPipeSignature698 BL_INLINE uint32_t fetchPayload() const noexcept { return _get(BL_PIPE_SIGNATURE_FETCH_PAYLOAD); } 699 700 //! Add destination pixel format. setDstFormatBLPipeSignature701 BL_INLINE void setDstFormat(uint32_t v) noexcept { _set(BL_PIPE_SIGNATURE_DST_FORMAT, v); } 702 //! Add source pixel format. setSrcFormatBLPipeSignature703 BL_INLINE void setSrcFormat(uint32_t v) noexcept { _set(BL_PIPE_SIGNATURE_SRC_FORMAT, v); } 704 //! Add clip mode. setCompOpBLPipeSignature705 BL_INLINE void setCompOp(uint32_t v) noexcept { _set(BL_PIPE_SIGNATURE_COMP_OP, v); } 706 //! Add sweep type. setFillTypeBLPipeSignature707 BL_INLINE void setFillType(uint32_t v) noexcept { _set(BL_PIPE_SIGNATURE_FILL_TYPE, v); } 708 //! Add fetch type. setFetchTypeBLPipeSignature709 BL_INLINE void setFetchType(uint32_t v) noexcept { _set(BL_PIPE_SIGNATURE_FETCH_TYPE, v); } 710 //! Add fetch data. setFetchPayloadBLPipeSignature711 BL_INLINE void setFetchPayload(uint32_t v) noexcept { _set(BL_PIPE_SIGNATURE_FETCH_PAYLOAD, v); } 712 713 // The following methods are used to build the signature. They use '|' operator 714 // which doesn't clear the previous value, each function is expected to be called 715 // only once when building a new signature. 716 717 //! Combine with other signature. addBLPipeSignature718 BL_INLINE void add(uint32_t v) noexcept { this->value |= v; } 719 //! Combine with other signature. addBLPipeSignature720 BL_INLINE void add(const BLPipeSignature& other) noexcept { this->value |= other.value; } 721 722 //! Add destination pixel format. addDstFormatBLPipeSignature723 BL_INLINE void addDstFormat(uint32_t v) noexcept { _add(BL_PIPE_SIGNATURE_DST_FORMAT, v); } 724 //! Add source pixel format. addSrcFormatBLPipeSignature725 BL_INLINE void addSrcFormat(uint32_t v) noexcept { _add(BL_PIPE_SIGNATURE_SRC_FORMAT, v); } 726 //! Add clip mode. addCompOpBLPipeSignature727 BL_INLINE void addCompOp(uint32_t v) noexcept { _add(BL_PIPE_SIGNATURE_COMP_OP, v); } 728 //! Add sweep type. addFillTypeBLPipeSignature729 BL_INLINE void addFillType(uint32_t v) noexcept { _add(BL_PIPE_SIGNATURE_FILL_TYPE, v); } 730 //! Add fetch type. addFetchTypeBLPipeSignature731 BL_INLINE void addFetchType(uint32_t v) noexcept { _add(BL_PIPE_SIGNATURE_FETCH_TYPE, v); } 732 //! Add fetch data. addFetchPayloadBLPipeSignature733 BL_INLINE void addFetchPayload(uint32_t v) noexcept { _add(BL_PIPE_SIGNATURE_FETCH_PAYLOAD, v); } 734 }; 735 736 //! \} 737 //! \endcond 738 739 #endif // BLEND2D_PIPEDEFS_P_H 740