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_PIPEGEN_FETCHPART_P_H
8 #define BLEND2D_PIPEGEN_FETCHPART_P_H
9 
10 #include "../pipegen/pipepart_p.h"
11 
12 //! \cond INTERNAL
13 //! \addtogroup blend2d_internal_pipegen
14 //! \{
15 
16 namespace BLPipeGen {
17 
18 // ============================================================================
19 // [BLPipeGen::FetchPart]
20 // ============================================================================
21 
22 //! Pipeline fetch part.
23 class FetchPart : public PipePart {
24 public:
25   BL_NONCOPYABLE(FetchPart)
26 
27   enum : uint32_t {
28     kUnlimitedMaxPixels = 64
29   };
30 
31   //! Fetch type.
32   uint32_t _fetchType;
33   //! Fetch extra (different meaning for each fetch type).
34   uint32_t _fetchPayload;
35 
36   //! Source pixel format, see `BLFormat`.
37   uint8_t _format;
38   //! Source bytes-per-pixel (only required by pattern fetcher).
39   uint8_t _bpp;
40   //! Maximum pixel step that the fetcher can fetch at a time (0=unlimited).
41   uint8_t _maxPixels;
42   //! Pixel type.
43   uint8_t _pixelType;
44   //! Pixel granularity passed to init().
45   uint8_t _pixelGranularity;
46 
47   //! True if the fetching should happen in alpha mode (no RGB).
48   uint8_t _alphaFetch;
49   //! Alpha channel [memory] offset, only used when `_alphaFetch` is true
50   uint8_t _alphaOffset;
51 
52   //! Fetcher is in a rectangle fill mode, set and cleared by `init...()`.
53   bool _isRectFill;
54   //! If the fetch-type is complex (used to limit the maximum number of pixels).
55   bool _isComplexFetch;
56 
57   //! If the fetched pixels contain RGB channels.
58   bool _hasRGB;
59   //! If the fetched pixels contain alpha channel.
60   bool _hasAlpha;
61 
62   FetchPart(PipeCompiler* pc, uint32_t fetchType, uint32_t fetchPayload, uint32_t format) noexcept;
63 
64   //! Returns the fetch type.
fetchType()65   BL_INLINE uint32_t fetchType() const noexcept { return _fetchType; }
66 
67   //! Tests whether the fetch-type equals `ft`.
isFetchType(uint32_t ft)68   BL_INLINE bool isFetchType(uint32_t ft) const noexcept { return _fetchType == ft; }
69   //! Tests whether the fetch-type is between `first..last`, inclusive.
isFetchType(uint32_t first,uint32_t last)70   BL_INLINE bool isFetchType(uint32_t first, uint32_t last) const noexcept { return _fetchType >= first && _fetchType <= last; }
71 
72   //! Tests whether the fetch-type is solid.
isSolid()73   BL_INLINE bool isSolid() const noexcept { return isFetchType(BL_PIPE_FETCH_TYPE_SOLID); }
74 
75   //! Tests whether the fetch-type is gradient.
isGradient()76   BL_INLINE bool isGradient() const noexcept { return isFetchType(BL_PIPE_FETCH_TYPE_GRADIENT_ANY_FIRST, BL_PIPE_FETCH_TYPE_GRADIENT_ANY_LAST); }
77   //! Tests whether the fetch-type is linear gradient.
isLinearGradient()78   BL_INLINE bool isLinearGradient() const noexcept { return isFetchType(BL_PIPE_FETCH_TYPE_GRADIENT_LINEAR_FIRST, BL_PIPE_FETCH_TYPE_GRADIENT_LINEAR_LAST); }
79   //! Tests whether the fetch-type is radial gradient.
isRadialGradient()80   BL_INLINE bool isRadialGradient() const noexcept { return isFetchType(BL_PIPE_FETCH_TYPE_GRADIENT_RADIAL_FIRST, BL_PIPE_FETCH_TYPE_GRADIENT_RADIAL_LAST); }
81   //! Tests whether the fetch-type is conical gradient.
isConicalGradient()82   BL_INLINE bool isConicalGradient() const noexcept { return isFetchType(BL_PIPE_FETCH_TYPE_GRADIENT_CONICAL_FIRST, BL_PIPE_FETCH_TYPE_GRADIENT_CONICAL_LAST); }
83 
84   //! Tests whether the fetch-type is pattern.
isPattern()85   BL_INLINE bool isPattern() const noexcept { return isFetchType(BL_PIPE_FETCH_TYPE_PATTERN_ANY_FIRST, BL_PIPE_FETCH_TYPE_PATTERN_ANY_LAST); }
86   //! Tests whether the fetch is the destination (special type).
isPixelPtr()87   BL_INLINE bool isPixelPtr() const noexcept { return isFetchType(BL_PIPE_FETCH_TYPE_PIXEL_PTR); }
88 
89   //! Returns source pixel format.
format()90   BL_INLINE uint32_t format() const noexcept { return _format; }
91   //! Returns source pixel format information.
formatInfo()92   BL_INLINE BLFormatInfo formatInfo() const noexcept { return blFormatInfo[_format]; }
93 
94   //! Returns source bytes-per-pixel (only used when `isPattern()` is true).
bpp()95   BL_INLINE uint32_t bpp() const noexcept { return _bpp; }
96 
97   //! Returns the maximum pixels the fetch part can fetch at a time.
maxPixels()98   BL_INLINE uint32_t maxPixels() const noexcept { return _maxPixels; }
99 
100   //! Tests whether the fetched pixels contain RGB channels.
hasRGB()101   BL_INLINE bool hasRGB() const noexcept { return _hasRGB; }
102   //! Tests whether the fetched pixels contain Alpha channel.
hasAlpha()103   BL_INLINE bool hasAlpha() const noexcept { return _hasAlpha; }
104 
105   //! Tests whether the fetching should happen in alpha-only mode.
isAlphaFetch()106   BL_INLINE bool isAlphaFetch() const noexcept { return _alphaFetch != 0; }
107   //! Returns a byte offset of alpha channel (if provided), used when fetching alpha from memory.
alphaOffset()108   BL_INLINE uint32_t alphaOffset() const noexcept { return _alphaOffset; }
109 
110   //! Tests whether the fetch is currently initialized for a rectangular fill.
isRectFill()111   BL_INLINE bool isRectFill() const noexcept { return _isRectFill; }
112   //! Returns the pixel granularity passed to `FetchPath::init()`.
pixelGranularity()113   BL_INLINE uint32_t pixelGranularity() const noexcept { return _pixelGranularity; }
114 
isComplexFetch()115   BL_INLINE bool isComplexFetch() const noexcept { return _isComplexFetch; }
setComplexFetch(bool value)116   BL_INLINE void setComplexFetch(bool value) noexcept { _isComplexFetch = value; }
117 
118   void init(x86::Gp& x, x86::Gp& y, uint32_t pixelType, uint32_t pixelGranularity) noexcept;
119   void fini() noexcept;
120 
121   virtual void _initPart(x86::Gp& x, x86::Gp& y) noexcept;
122   virtual void _finiPart() noexcept;
123 
124   //! Advances the current y coordinate by one pixel.
125   virtual void advanceY() noexcept;
126 
127   //! Initializes the current horizontal cursor of the current scanline to `x`.
128   //!
129   //! \note This initializer is generally called once per scanline to setup the
130   //! current position by initializing it to `x`. The position is then advanced
131   //! automatically by pixel fetchers and by `advanceX()`, which is used when
132   //! there is a gap in the scanline that has to be skipped.
133   virtual void startAtX(x86::Gp& x) noexcept;
134 
135   //! Advances the current x coordinate by `diff` pixels. The final x position
136   //! after advance will be `x`. The fetcher can decide whether to use `x`,
137   //! `diff`, or both.
138   virtual void advanceX(x86::Gp& x, x86::Gp& diff) noexcept;
139 
140   //! Called before `fetch1()`.
141   virtual void prefetch1() noexcept;
142 
143   //! Fetches 1 RGBA pixel to `p` and advances by 1.
144   virtual void fetch1(Pixel& p, uint32_t flags) noexcept = 0;
145 
146   //! Called as a prolog before fetching multiple fixels at once. This must be
147   //! called before any loop that would call `fetch4()` or `fetch8()` unless the
148   //! fetcher is in a vector mode because of `pixelGranularity`.
149   virtual void enterN() noexcept;
150 
151   //! Called as an epilog after fetching multiple fixels at once. This must be
152   //! called after a loop that uses `fetch4()` or `fetch8()` unless the fetcher
153   //! is in a vector mode because of `pixelGranularity`.
154   virtual void leaveN() noexcept;
155 
156   //! Called before a loop that calls `fetch4()` or `fetch8()`. In some cases
157   //! there will be some instructions placed between `prefetch` and `fetch`,
158   //! which means that if the fetcher requires an expensive operation that has
159   //! greater latency then it would be better to place that code into the prefetch
160   //! area.
161   virtual void prefetchN() noexcept;
162 
163   //! Cancels the effect of `prefetchN()` and also automatic prefetch that happens
164   //! inside `fetch4()` or `fetch8()`. Must be called after a loop that calls
165   //! `fetch4()`, `fetch8()`, or immediately after `prefetchN()` if no loop has
166   //! been entered.
167   virtual void postfetchN() noexcept;
168 
169   //! Fetches 4 pixels to `p` and advances by 4.
170   virtual void fetch4(Pixel& p, uint32_t flags) noexcept = 0;
171 
172   //! Fetches 8 pixels to `p` and advances by 8.
173   //!
174   //! \note The default implementation uses `fetch4()` twice.
175   virtual void fetch8(Pixel& p, uint32_t flags) noexcept;
176 };
177 
178 } // {BLPipeGen}
179 
180 //! \}
181 //! \endcond
182 
183 #endif // BLEND2D_PIPEGEN_FETCHPART_P_H
184