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_BLGRADIENT_P_H |
8 | #define BLEND2D_BLGRADIENT_P_H |
9 | |
10 | #include "./blapi-internal_p.h" |
11 | #include "./blgradient.h" |
12 | |
13 | //! \cond INTERNAL |
14 | //! \addtogroup blend2d_internal |
15 | //! \{ |
16 | |
17 | // ============================================================================ |
18 | // [BLGradient - LUT] |
19 | // ============================================================================ |
20 | |
21 | //! Lookup table that contains interpolated pixels of the gradient in either |
22 | //! PRGB32 or PRGB64 format (no other format is ever used). |
23 | struct BLGradientLUT { |
24 | //! Reference count. |
25 | volatile size_t refCount; |
26 | //! Table size - must be power of 2! |
27 | size_t size; |
28 | |
29 | template<typename T = void> |
30 | BL_INLINE T* data() noexcept { return reinterpret_cast<T*>(this + 1); } |
31 | |
32 | template<typename T = void> |
33 | const BL_INLINE T* data() const noexcept { return reinterpret_cast<const T*>(this + 1); } |
34 | |
35 | BL_INLINE BLGradientLUT* incRef() noexcept { |
36 | blAtomicFetchAdd(&refCount); |
37 | return this; |
38 | } |
39 | |
40 | BL_INLINE bool decRefAndTest() noexcept { |
41 | return blAtomicFetchSub(&refCount) == 1; |
42 | } |
43 | |
44 | BL_INLINE void release() noexcept { |
45 | if (decRefAndTest()) |
46 | destroy(this); |
47 | } |
48 | |
49 | static BL_INLINE BLGradientLUT* alloc(size_t size, uint32_t pixelSize) noexcept { |
50 | BLGradientLUT* self = static_cast<BLGradientLUT*>( |
51 | malloc(sizeof(BLGradientLUT) + size * pixelSize)); |
52 | |
53 | if (BL_UNLIKELY(!self)) |
54 | return nullptr; |
55 | |
56 | self->refCount = 1; |
57 | self->size = size; |
58 | |
59 | return self; |
60 | } |
61 | |
62 | static BL_INLINE void destroy(BLGradientLUT* self) noexcept { |
63 | free(self); |
64 | } |
65 | }; |
66 | |
67 | // ============================================================================ |
68 | // [BLGradient - Info] |
69 | // ============================================================================ |
70 | |
71 | //! Additional information maintained by `BLGradient` that is cached and is |
72 | //! useful when deciding how to render the gradient and how big the LUT should |
73 | //! be. |
74 | struct BLGradientInfo { |
75 | union { |
76 | uint32_t packed; |
77 | |
78 | struct { |
79 | //! True if the gradient is a solid color. |
80 | uint8_t solid; |
81 | //! Gradient format (either 32-bit or 64-bit). |
82 | uint8_t format; |
83 | //! Optimal LUT size. |
84 | uint16_t lutSize; |
85 | }; |
86 | }; |
87 | |
88 | BL_INLINE bool empty() const noexcept { return this->packed == 0; } |
89 | BL_INLINE void reset() noexcept { this->packed = 0; } |
90 | }; |
91 | |
92 | // ============================================================================ |
93 | // [BLGradient - Internal] |
94 | // ============================================================================ |
95 | |
96 | //! Internal implementation that extends `BLGradientImpl` and adds LUT cache to it. |
97 | struct BLInternalGradientImpl : public BLGradientImpl { |
98 | //! Gradient lookup table (32-bit). |
99 | BLGradientLUT* volatile lut32; |
100 | volatile BLGradientInfo info32; |
101 | }; |
102 | |
103 | template<> |
104 | struct BLInternalCastImpl<BLGradientImpl> { typedef BLInternalGradientImpl Type; }; |
105 | |
106 | BL_HIDDEN BLResult blGradientImplDelete(BLGradientImpl* impl) noexcept; |
107 | |
108 | BL_HIDDEN BLGradientInfo blGradientImplEnsureInfo32(BLGradientImpl* impl_) noexcept; |
109 | BL_HIDDEN BLGradientLUT* blGradientImplEnsureLut32(BLGradientImpl* impl_) noexcept; |
110 | |
111 | // ============================================================================ |
112 | // [BLGradient - Ops] |
113 | // ============================================================================ |
114 | |
115 | struct BLGradientOps { |
116 | void (BL_CDECL* interpolate32)(uint32_t* dst, uint32_t dstSize, const BLGradientStop* stops, size_t stopCount) BL_NOEXCEPT; |
117 | }; |
118 | BL_HIDDEN extern BLGradientOps blGradientOps; |
119 | |
120 | #ifdef BL_BUILD_OPT_SSE2 |
121 | BL_HIDDEN void BL_CDECL blGradientInterpolate32_SSE2(uint32_t* dPtr, uint32_t dSize, const BLGradientStop* sPtr, size_t sSize) noexcept; |
122 | #endif |
123 | |
124 | #ifdef BL_BUILD_OPT_AVX2 |
125 | BL_HIDDEN void BL_CDECL blGradientInterpolate32_AVX2(uint32_t* dPtr, uint32_t dWidth, const BLGradientStop* sPtr, size_t sSize) noexcept; |
126 | #endif |
127 | |
128 | //! \} |
129 | //! \endcond |
130 | |
131 | #endif // BLEND2D_BLGRADIENT_P_H |
132 | |