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 #include "../api-build_p.h"
8 #if BL_TARGET_ARCH_X86 && !defined(BL_BUILD_NO_JIT)
9 
10 #include "../pipegen/compoppart_p.h"
11 #include "../pipegen/fetchsolidpart_p.h"
12 #include "../pipegen/pipecompiler_p.h"
13 
14 namespace BLPipeGen {
15 
16 #define REL_SOLID(FIELD) BL_OFFSET_OF(BLPipeFetchData::Solid, FIELD)
17 
18 // ============================================================================
19 // [BLPipeGen::FetchSolidPart - Construction / Destruction]
20 // ============================================================================
21 
FetchSolidPart(PipeCompiler * pc,uint32_t fetchType,uint32_t fetchPayload,uint32_t format)22 FetchSolidPart::FetchSolidPart(PipeCompiler* pc, uint32_t fetchType, uint32_t fetchPayload, uint32_t format) noexcept
23   : FetchPart(pc, fetchType, fetchPayload, format) {
24 
25   _maxPixels = kUnlimitedMaxPixels;
26   _maxSimdWidthSupported = 16;
27 
28   _pixel.reset();
29   _pixel.setCount(1);
30 }
31 
32 // ============================================================================
33 // [BLPipeGen::FetchSolidPart - Init / Fini]
34 // ============================================================================
35 
_initPart(x86::Gp & x,x86::Gp & y)36 void FetchSolidPart::_initPart(x86::Gp& x, x86::Gp& y) noexcept {
37   if (_pixel.type() != _pixelType) {
38     _pixel.setType(_pixelType);
39   }
40   else {
41     // The type should never change after it's been assigned.
42     BL_ASSERT(_pixel.type() == _pixelType);
43   }
44 
45   BL_UNUSED(x);
46   BL_UNUSED(y);
47 }
48 
_finiPart()49 void FetchSolidPart::_finiPart() noexcept {}
50 
51 // ============================================================================
52 // [BLPipeGen::FetchSolidPart - InitSolidFlags]
53 // ============================================================================
54 
initSolidFlags(uint32_t flags)55 void FetchSolidPart::initSolidFlags(uint32_t flags) noexcept {
56   ScopedInjector injector(cc, &_globalHook);
57   Pixel& s = _pixel;
58 
59   switch (s.type()) {
60     case Pixel::kTypeRGBA:
61       if ((flags & (Pixel::kPC | Pixel::kUC | Pixel::kUA | Pixel::kUIA)) && s.pc.empty()) {
62         s.pc.init(cc->newXmm("pixel.pc"));
63         x86::Vec& pix = s.pc[0];
64         pc->vbroadcast_u32(pix, x86::ptr_32(pc->_fetchData));
65       }
66       break;
67 
68     case Pixel::kTypeAlpha:
69       if ((flags & (Pixel::kSA | Pixel::kPA | Pixel::kUA | Pixel::kUIA)) && !s.sa.isValid()) {
70         s.sa = cc->newUInt32("pixel.sa");
71         pc->load8(s.sa, x86::ptr_8(pc->_fetchData, 3));
72       }
73 
74       if (flags & (Pixel::kPA | Pixel::kUA | Pixel::kUIA) && s.ua.empty()) {
75         s.ua.init(cc->newXmm("pixel.ua"));
76         pc->vbroadcast_u16(s.ua[0], s.sa);
77       }
78       break;
79   }
80 
81   pc->xSatisfySolid(s, flags);
82 }
83 
84 // ============================================================================
85 // [BLPipeGen::FetchSolidPart - Fetch]
86 // ============================================================================
87 
fetch1(Pixel & p,uint32_t flags)88 void FetchSolidPart::fetch1(Pixel& p, uint32_t flags) noexcept {
89   BL_ASSERT(_pixel.type() == p.type());
90 
91   p.setCount(1);
92   if (p.isRGBA()) {
93     if (flags & Pixel::kAny) {
94       initSolidFlags(flags & Pixel::kAny);
95       Pixel& s = _pixel;
96 
97       if (flags & Pixel::kImmutable) {
98         if (flags & Pixel::kPC ) { p.pc.init(s.pc); }
99         if (flags & Pixel::kUC ) { p.uc.init(s.uc); }
100         if (flags & Pixel::kUA ) { p.ua.init(s.ua); }
101         if (flags & Pixel::kUIA) { p.uia.init(s.uia); }
102       }
103       else {
104         if (flags & Pixel::kPC) {
105           p.pc.init(cc->newXmm("p.pc0"));
106           pc->vmov(p.pc[0], s.pc[0]);
107         }
108 
109         if (flags & Pixel::kUC) {
110           p.uc.init(cc->newXmm("p.uc0"));
111           pc->vmov(p.uc[0], s.uc[0]);
112         }
113 
114         if (flags & Pixel::kUA) {
115           p.ua.init(cc->newXmm("p.ua0"));
116           pc->vmov(p.ua[0], s.ua[0]);
117         }
118 
119         if (flags & Pixel::kUIA) {
120           p.uia.init(cc->newXmm("p.uia0"));
121           pc->vmov(p.uia[0], s.uia[0]);
122         }
123       }
124     }
125   }
126   else if (p.isAlpha()) {
127     if (flags & Pixel::kSA) {
128       initSolidFlags(Pixel::kSA);
129       Pixel& s = _pixel;
130 
131       if (flags & Pixel::kImmutable) {
132         if (flags & Pixel::kSA ) { p.sa = s.sa; }
133       }
134       else {
135         if (flags & Pixel::kSA) {
136           p.sa = cc->newUInt32("p.sa");
137           cc->mov(p.sa, s.sa);
138         }
139       }
140     }
141   }
142 
143   pc->xSatisfyPixel(p, flags);
144 }
145 
fetch4(Pixel & p,uint32_t flags)146 void FetchSolidPart::fetch4(Pixel& p, uint32_t flags) noexcept {
147   BL_ASSERT(_pixel.type() == p.type());
148 
149   p.setCount(4);
150   if (p.isRGBA()) {
151     initSolidFlags(flags & (Pixel::kPC | Pixel::kUC | Pixel::kUA | Pixel::kUIA));
152     Pixel& s = _pixel;
153 
154     uint32_t pCount = 1;
155     uint32_t uCount = 2;
156 
157     if (flags & Pixel::kImmutable) {
158       if (flags & Pixel::kPC) { p.pc.init(s.pc); }
159       if (flags & Pixel::kUC) { p.uc.init(s.uc); }
160       if (flags & Pixel::kUA) { p.ua.init(s.ua); }
161       if (flags & Pixel::kUIA) { p.uia.init(s.uia); }
162     }
163     else {
164       if (flags & Pixel::kPC) {
165         pc->newXmmArray(p.pc, pCount, "p.pc");
166         pc->vmov(p.pc, s.pc[0]);
167       }
168 
169       if (flags & Pixel::kUC) {
170         pc->newXmmArray(p.uc, uCount, "p.uc");
171         pc->vmov(p.uc, s.uc[0]);
172       }
173 
174       if (flags & Pixel::kUA) {
175         pc->newXmmArray(p.ua, uCount, "p.ua");
176         pc->vmov(p.ua, s.ua[0]);
177       }
178 
179       if (flags & Pixel::kUIA) {
180         pc->newXmmArray(p.uia, uCount, "p.uia");
181         pc->vmov(p.uia, s.uia[0]);
182       }
183     }
184   }
185   else if (p.isAlpha()) {
186     initSolidFlags(flags & (Pixel::kPA | Pixel::kUA | Pixel::kUIA));
187     Pixel& s = _pixel;
188 
189     uint32_t pCount = 1;
190     uint32_t uCount = 1;
191 
192     if (flags & Pixel::kImmutable) {
193       if (flags & Pixel::kPA) { p.pa.init(s.pa); }
194       if (flags & Pixel::kUA) { p.ua.init(s.ua); }
195       if (flags & Pixel::kUIA) { p.uia.init(s.uia); }
196     }
197     else {
198       if (flags & Pixel::kPA) {
199         pc->newXmmArray(p.pa, pCount, "p.pa");
200         pc->vmov(p.pa[0], s.pa[0]);
201       }
202 
203       if (flags & Pixel::kUA) {
204         pc->newXmmArray(p.ua, uCount, "p.ua");
205         pc->vmov(p.ua, s.ua[0]);
206       }
207 
208       if (flags & Pixel::kUIA) {
209         pc->newXmmArray(p.uia, uCount, "p.uia");
210         pc->vmov(p.uia, s.uia[0]);
211       }
212     }
213   }
214 
215   pc->xSatisfyPixel(p, flags);
216 }
217 
218 } // {BLPipeGen}
219 
220 #endif
221