sw_engine common: Added neon version of rasterRGBA32 API.
[platform/core/graphics/tizenvg.git] / src / lib / sw_engine / tvgSwCommon.h
1 /*
2  * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
3
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10
11  * The above copyright notice and this permission notice shall be included in all
12  * copies or substantial portions of the Software.
13
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  */
22 #ifndef _TVG_SW_COMMON_H_
23 #define _TVG_SW_COMMON_H_
24
25 #include "tvgCommon.h"
26 #include "tvgRender.h"
27
28 #ifdef THORVG_AVX_VECTOR_SUPPORT
29     #include <immintrin.h>
30 #endif
31
32 #ifdef THORVG_NEON_VECTOR_SUPPORT
33     #include <arm_neon.h>
34 #endif
35
36 #if 0
37 #include <sys/time.h>
38 static double timeStamp()
39 {
40    struct timeval tv;
41    gettimeofday(&tv, NULL);
42    return (tv.tv_sec + tv.tv_usec / 1000000.0);
43 }
44 #endif
45
46 #define SW_CURVE_TYPE_POINT 0
47 #define SW_CURVE_TYPE_CUBIC 1
48 #define SW_ANGLE_PI (180L << 16)
49 #define SW_ANGLE_2PI (SW_ANGLE_PI << 1)
50 #define SW_ANGLE_PI2 (SW_ANGLE_PI >> 1)
51 #define SW_ANGLE_PI4 (SW_ANGLE_PI >> 2)
52
53 using SwCoord = signed long;
54 using SwFixed = signed long long;
55
56 struct SwPoint
57 {
58     SwCoord x, y;
59
60     SwPoint& operator+=(const SwPoint& rhs)
61     {
62         x += rhs.x;
63         y += rhs.y;
64         return *this;
65     }
66
67     SwPoint operator+(const SwPoint& rhs) const
68     {
69         return {x + rhs.x, y + rhs.y};
70     }
71
72     SwPoint operator-(const SwPoint& rhs) const
73     {
74         return {x - rhs.x, y - rhs.y};
75     }
76
77     bool operator==(const SwPoint& rhs) const
78     {
79         return (x == rhs.x && y == rhs.y);
80     }
81
82     bool operator!=(const SwPoint& rhs) const
83     {
84         return (x != rhs.x || y != rhs.y);
85     }
86
87     bool zero() const
88     {
89         if (x == 0 && y == 0) return true;
90         else return false;
91     }
92
93     bool small() const
94     {
95         //2 is epsilon...
96         if (abs(x) < 2 && abs(y) < 2) return true;
97         else return false;
98     }
99
100 };
101
102 struct SwSize
103 {
104     SwCoord w, h;
105 };
106
107 struct SwOutline
108 {
109     uint32_t*     cntrs;            //the contour end points
110     uint32_t      cntrsCnt;         //number of contours in glyph
111     uint32_t      reservedCntrsCnt;
112     SwPoint*      pts;              //the outline's points
113     uint32_t      ptsCnt;           //number of points in the glyph
114     uint32_t      reservedPtsCnt;
115     uint8_t*      types;            //curve type
116     FillRule      fillRule;
117     bool          opened;           //opened path?
118 };
119
120 struct SwSpan
121 {
122     int16_t x, y;
123     uint16_t len;
124     uint8_t coverage;
125 };
126
127 struct SwRleData
128 {
129     SwSpan *spans;
130     uint32_t alloc;
131     uint32_t size;
132 };
133
134 struct SwBBox
135 {
136     SwPoint min, max;
137
138     void reset()
139     {
140         min.x = min.y = max.x = max.y = 0;
141     }
142 };
143
144 struct SwFill
145 {
146     struct SwLinear {
147         float dx, dy;
148         float len;
149         float offset;
150     };
151
152     struct SwRadial {
153         float cx, cy;
154         float a;
155         float inva;
156     };
157
158     union {
159         SwLinear linear;
160         SwRadial radial;
161     };
162
163     uint32_t* ctable;
164     FillSpread spread;
165     float sx, sy;
166
167     bool translucent;
168 };
169
170 struct SwStrokeBorder
171 {
172     uint32_t ptsCnt;
173     uint32_t maxPts;
174     SwPoint* pts;
175     uint8_t* tags;
176     int32_t start;     //index of current sub-path start point
177     bool movable;      //true: for ends of lineto borders
178 };
179
180 struct SwStroke
181 {
182     SwFixed angleIn;
183     SwFixed angleOut;
184     SwPoint center;
185     SwFixed lineLength;
186     SwFixed subPathAngle;
187     SwPoint ptStartSubPath;
188     SwFixed subPathLineLength;
189     SwFixed width;
190
191     StrokeCap cap;
192     StrokeJoin join;
193     StrokeJoin joinSaved;
194     SwFill* fill = nullptr;
195
196     SwStrokeBorder borders[2];
197
198     float sx, sy;
199
200     bool firstPt;
201     bool openSubPath;
202     bool handleWideStrokes;
203 };
204
205 struct SwDashStroke
206 {
207     SwOutline* outline;
208     float curLen;
209     int32_t curIdx;
210     Point ptStart;
211     Point ptCur;
212     float* pattern;
213     uint32_t cnt;
214     bool curOpGap;
215 };
216
217 struct SwShape
218 {
219     SwOutline*   outline = nullptr;
220     SwStroke*    stroke = nullptr;
221     SwFill*      fill = nullptr;
222     SwRleData*   rle = nullptr;
223     SwRleData*   strokeRle = nullptr;
224     SwBBox       bbox;           //Keep it boundary without stroke region. Using for optimal filling.
225
226     bool         rect = false;   //Fast Track: Othogonal rectangle?
227 };
228
229 struct SwImage
230 {
231     SwOutline*   outline = nullptr;
232     SwRleData*   rle = nullptr;
233     uint32_t*    data = nullptr;
234     uint32_t     w, h;
235 };
236
237 struct SwBlender
238 {
239     uint32_t (*join)(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
240     uint32_t (*alpha)(uint32_t rgba);
241 };
242
243 struct SwCompositor;
244
245 struct SwSurface : Surface
246 {
247     SwBlender blender;                    //mandatory
248     SwCompositor* compositor = nullptr;   //compositor (optional)
249 };
250
251 struct SwCompositor : Compositor
252 {
253     SwSurface* recoverSfc;                  //Recover surface when composition is started
254     SwCompositor* recoverCmp;               //Recover compositor when composition is done
255     SwImage image;
256     SwBBox bbox;
257     bool valid;
258 };
259
260 struct SwMpool
261 {
262     SwOutline* outline = nullptr;
263     SwOutline* strokeOutline = nullptr;
264     unsigned allocSize = 0;
265 };
266
267 static inline SwCoord TO_SWCOORD(float val)
268 {
269     return SwCoord(val * 64);
270 }
271
272 static inline uint32_t ALPHA_BLEND(uint32_t c, uint32_t a)
273 {
274     return (((((c >> 8) & 0x00ff00ff) * a + 0x00ff00ff) & 0xff00ff00) +
275             ((((c & 0x00ff00ff) * a + 0x00ff00ff) >> 8) & 0x00ff00ff));
276 }
277
278 static inline uint32_t COLOR_INTERPOLATE(uint32_t c1, uint32_t a1, uint32_t c2, uint32_t a2)
279 {
280     auto t = (((c1 & 0xff00ff) * a1 + (c2 & 0xff00ff) * a2) >> 8) & 0xff00ff;
281     c1 = (((c1 >> 8) & 0xff00ff) * a1 + ((c2 >> 8) & 0xff00ff) * a2) & 0xff00ff00;
282     return (c1 |= t);
283 }
284
285 static inline uint32_t ALPHA_MULTIPLY(uint32_t c, uint32_t a)
286 {
287     return ((c * a + 0xff) >> 8);
288 }
289
290 static inline SwCoord HALF_STROKE(float width)
291 {
292     return TO_SWCOORD(width * 0.5);
293 }
294
295 int64_t mathMultiply(int64_t a, int64_t b);
296 int64_t mathDivide(int64_t a, int64_t b);
297 int64_t mathMulDiv(int64_t a, int64_t b, int64_t c);
298 void mathRotate(SwPoint& pt, SwFixed angle);
299 SwFixed mathTan(SwFixed angle);
300 SwFixed mathAtan(const SwPoint& pt);
301 SwFixed mathCos(SwFixed angle);
302 SwFixed mathSin(SwFixed angle);
303 void mathSplitCubic(SwPoint* base);
304 SwFixed mathDiff(SwFixed angle1, SwFixed angle2);
305 SwFixed mathLength(const SwPoint& pt);
306 bool mathSmallCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut);
307 SwFixed mathMean(SwFixed angle1, SwFixed angle2);
308 SwPoint mathTransform(const Point* to, const Matrix* transform);
309 bool mathUpdateOutlineBBox(const SwOutline* outline, const SwBBox& clipRegion, SwBBox& renderRegion);
310
311 void shapeReset(SwShape* shape);
312 bool shapePrepare(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid);
313 bool shapePrepared(const SwShape* shape);
314 bool shapeGenRle(SwShape* shape, const Shape* sdata, bool antiAlias, bool hasComposite);
315 void shapeDelOutline(SwShape* shape, SwMpool* mpool, uint32_t tid);
316 void shapeResetStroke(SwShape* shape, const Shape* sdata, const Matrix* transform);
317 bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid);
318 void shapeFree(SwShape* shape);
319 void shapeDelStroke(SwShape* shape);
320 bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, SwSurface* surface, uint32_t opacity, bool ctable);
321 bool shapeGenStrokeFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, SwSurface* surface, uint32_t opacity, bool ctable);
322 void shapeResetFill(SwShape* shape);
323 void shapeResetStrokeFill(SwShape* shape);
324 void shapeDelFill(SwShape* shape);
325 void shapeDelStrokeFill(SwShape* shape);
326
327 void strokeReset(SwStroke* stroke, const Shape* shape, const Matrix* transform);
328 bool strokeParseOutline(SwStroke* stroke, const SwOutline& outline);
329 SwOutline* strokeExportOutline(SwStroke* stroke, SwMpool* mpool, unsigned tid);
330 void strokeFree(SwStroke* stroke);
331
332 bool imagePrepare(SwImage* image, const Picture* pdata, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid);
333 bool imagePrepared(const SwImage* image);
334 bool imageGenRle(SwImage* image, TVG_UNUSED const Picture* pdata, const SwBBox& renderRegion, bool antiAlias);
335 void imageDelOutline(SwImage* image, SwMpool* mpool, uint32_t tid);
336 void imageReset(SwImage* image);
337 void imageFree(SwImage* image);
338
339 bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, SwSurface* surface, uint32_t opacity, bool ctable);
340 void fillReset(SwFill* fill);
341 void fillFree(SwFill* fill);
342 void fillFetchLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len);
343 void fillFetchRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len);
344
345 SwRleData* rleRender(SwRleData* rle, const SwOutline* outline, const SwBBox& renderRegion, bool antiAlias);
346 void rleFree(SwRleData* rle);
347 void rleReset(SwRleData* rle);
348 void rleClipPath(SwRleData *rle, const SwRleData *clip);
349 void rleClipRect(SwRleData *rle, const SwBBox* clip);
350
351 SwMpool* mpoolInit(uint32_t threads);
352 bool mpoolTerm(SwMpool* mpool);
353 bool mpoolClear(SwMpool* mpool);
354 SwOutline* mpoolReqOutline(SwMpool* mpool, unsigned idx);
355 void mpoolRetOutline(SwMpool* mpool, unsigned idx);
356 SwOutline* mpoolReqStrokeOutline(SwMpool* mpool, unsigned idx);
357 void mpoolRetStrokeOutline(SwMpool* mpool, unsigned idx);
358
359 bool rasterCompositor(SwSurface* surface);
360 bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id);
361 bool rasterSolidShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
362 bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, const SwBBox& bbox, uint32_t opacity);
363 bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
364 bool rasterGradientStroke(SwSurface* surface, SwShape* shape, unsigned id);
365 bool rasterClear(SwSurface* surface);
366
367 static inline void rasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len)
368 {
369 #if defined(THORVG_AVX_VECTOR_SUPPORT)
370     //1. calculate how many iterations we need to cover length
371     uint32_t iterations = len / 8;
372     uint32_t avxFilled = iterations * 8;
373     int32_t leftovers = 0;
374
375     //2. set beginning of the array
376     dst+=offset;
377     __m256i_u* avxDst = (__m256i_u*) dst;
378
379     //3. fill octets
380     for (uint32_t i = 0; i < iterations; ++i) {
381         *avxDst = _mm256_set1_epi32(val);
382         avxDst++;
383     }
384
385     //4. fill leftovers (in first step we have to set pointer to place where avx job is done)
386     leftovers = len - avxFilled;
387     dst+= avxFilled;
388
389     while (leftovers--) *dst++ = val;
390 #elif defined(THORVG_NEON_VECTOR_SUPPORT)
391     uint32_t iterations = len / 4;
392     uint32_t neonFilled = iterations * 4;
393     int32_t leftovers = 0;
394
395     dst+=offset;
396     uint32x4_t vectorVal = { val, val, val, val };
397
398     for (uint32_t i = 0; i < iterations; ++i) {
399         vst1q_u32(dst, vectorVal);
400         dst += 4;
401     }
402
403     leftovers = len - neonFilled;
404     while (leftovers--) *dst++ = val;
405 #else
406     dst += offset;
407     while (len--) *dst++ = val;
408 #endif
409 }
410
411 #endif /* _TVG_SW_COMMON_H_ */