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_PIPEPART_P_H
8 #define BLEND2D_PIPEGEN_PIPEPART_P_H
9 
10 #include "../pipegen/pipegencore_p.h"
11 #include "../pipegen/piperegusage_p.h"
12 
13 //! \cond INTERNAL
14 //! \addtogroup blend2d_internal_pipegen
15 //! \{
16 
17 namespace BLPipeGen {
18 
19 // ============================================================================
20 // [BLPipeGen::PipePart]
21 // ============================================================================
22 
23 //! A base interface of a pipeline part.
24 //!
25 //! This class has basically no functionality, it just defines members that all
26 //! parts inherit and can use. Also, since many parts use virtual functions to
27 //! make them extensible `Part` must contain at least one virtual function
28 //! too.
29 class PipePart {
30 public:
31   BL_OVERRIDE_NEW_DELETE(PipePart)
32 
33   //! PipePart type.
34   enum Type {
35     kTypeComposite        = 0,           //!< Composite two `FetchPart` parts.
36     kTypeFetch            = 1,           //!< Fetch part.
37     kTypeFill             = 2            //!< Fill part.
38   };
39 
40   //! PipePart flags.
41   enum Flags : uint32_t {
42     kFlagPrepareDone      = 0x00000001u, //!< Prepare was already called().
43     kFlagPreInitDone      = 0x00000002u, //!< Part was already pre-initialized.
44     kFlagPostInitDone     = 0x00000004u  //!< Part was already post-initialized.
45   };
46 
47   //! Reference to `PipeCompiler`.
48   PipeCompiler* pc;
49   //! Reference to `asmjit::x86::Compiler`.
50   x86::Compiler* cc;
51 
52   //! Part type.
53   uint8_t _partType;
54   //! Count of children parts, cannot be greater than the capacity of `_children`.
55   uint8_t _childrenCount;
56 
57   //! Maximum SIMD width this part supports.
58   uint8_t _maxSimdWidthSupported;
59   //! Informs to conserve a particular group of registers.
60   uint8_t _hasLowRegs[kNumVirtGroups];
61 
62   //! Part flags, see `Part::Flags`.
63   uint32_t _flags;
64 
65   //! Used to store children parts, can be introspected as well.
66   PipePart* _children[2];
67 
68   //! Number of persistent registers the part requires.
69   PipeRegUsage _persistentRegs;
70   //! Number of persistent registers the part can spill to decrease the pressure.
71   PipeRegUsage _spillableRegs;
72   //! Number of temporary registers the part uses.
73   PipeRegUsage _temporaryRegs;
74 
75   //! A global initialization hook.
76   //!
77   //! This hook is acquired during initialization phase of the part. Please do
78   //! not confuse this with loop initializers that contain another hook that
79   //! is used during the loop only. Initialization hooks define an entry for
80   //! the part where an additional  code can be injected at any time during
81   //! pipeline construction.
82   asmjit::BaseNode* _globalHook;
83 
84   PipePart(PipeCompiler* pc, uint32_t partType) noexcept;
85 
86   template<typename T>
as()87   inline T* as() noexcept { return static_cast<T*>(this); }
88   template<typename T>
as()89   inline const T* as() const noexcept { return static_cast<const T*>(this); }
90 
91   //! Tests whether the part is initialized
isPartInitialized()92   inline bool isPartInitialized() const noexcept { return _globalHook != nullptr; }
93   //! Returns the part type.
partType()94   inline uint32_t partType() const noexcept { return _partType; }
95 
96   //! Tests whether the part should restrict using GP registers.
hasLowRegs(uint32_t rKind)97   inline uint8_t hasLowRegs(uint32_t rKind) const noexcept { return _hasLowRegs[rKind]; }
98 
99   //! Tests whether the part should restrict using GP registers.
hasLowGpRegs()100   inline uint8_t hasLowGpRegs() const noexcept { return hasLowRegs(x86::Reg::kGroupGp); }
101   //! Tests whether the part should restrict using MM registers.
hasLowMmRegs()102   inline uint8_t hasLowMmRegs() const noexcept { return hasLowRegs(x86::Reg::kGroupMm); }
103   //! Tests whether the part should restrict using XMM/YMM registers.
hasLowVecRegs()104   inline uint8_t hasLowVecRegs() const noexcept { return hasLowRegs(x86::Reg::kGroupVec); }
105 
flags()106   inline uint32_t flags() const noexcept { return _flags; }
107 
108   //! Returns the number children parts.
childrenCount()109   inline uint32_t childrenCount() const noexcept { return _childrenCount; }
110   //! Returns children parts as an array.
children()111   inline PipePart** children() const noexcept { return (PipePart**)_children; }
112 
113   //! Prepares the part - it would call `prepare()` on all child parts.
114   virtual void preparePart() noexcept;
115 
116   //! Calls `preparePart()` on all children and also prevents calling it
117   //! multiple times.
118   void prepareChildren() noexcept;
119 
_initGlobalHook(asmjit::BaseNode * node)120   inline void _initGlobalHook(asmjit::BaseNode* node) noexcept {
121     // Can be initialized only once.
122     BL_ASSERT(_globalHook == nullptr);
123     _globalHook = node;
124   }
125 
_finiGlobalHook()126   inline void _finiGlobalHook() noexcept {
127     // Initialized by `_initGlobalHook()`, cannot be null here.
128     BL_ASSERT(_globalHook != nullptr);
129     _globalHook = nullptr;
130   }
131 };
132 
133 } // {BLPipeGen}
134 
135 //! \}
136 //! \endcond
137 
138 #endif // BLEND2D_PIPEGEN_PIPEPART_P_H
139