1 /**
2  * @file vg_lite_tvg.cpp
3  *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 #include "../../lv_conf_internal.h"
10 #if LV_USE_DRAW_VG_LITE && LV_USE_VG_LITE_THORVG
11 
12 #include "vg_lite.h"
13 #include "../../lvgl.h"
14 #include "../../libs/thorvg/thorvg.h"
15 #include <float.h>
16 #include <math.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <thread>
20 #include <vector>
21 
22 #if LV_VG_LITE_THORVG_YUV_SUPPORT
23     #include <libyuv/convert_argb.h>
24 #endif
25 
26 /*********************
27  *      DEFINES
28  *********************/
29 
30 #define TVG_CANVAS_ENGINE CanvasEngine::Sw
31 #define TVG_COLOR(COLOR) B(COLOR), G(COLOR), R(COLOR), A(COLOR)
32 #define TVG_IS_VG_FMT_SUPPORT(fmt) ((fmt) == VG_LITE_BGRA8888 || (fmt) == VG_LITE_BGRX8888)
33 
34 #define TVG_CHECK_RETURN_VG_ERROR(FUNC)                               \
35     do {                                                              \
36         Result res = FUNC;                                            \
37         if (res != Result::Success) {                                 \
38             LV_LOG_ERROR("Executed '" #FUNC "' error: %d", (int)res);                        \
39             return vg_lite_error_conv(res);                           \
40         }                                                             \
41     } while (0)
42 #define TVG_CHECK_RETURN_RESULT(FUNC)                                 \
43     do {                                                              \
44         Result res = FUNC;                                            \
45         if (res != Result::Success) {                                 \
46             LV_LOG_ERROR("Executed '" #FUNC "' error: %d", (int)res);\
47             return res;                                               \
48         }                                                             \
49     } while (0)
50 
51 /* clang-format off */
52 
53 #define IS_INDEX_FMT(fmt)           \
54     ((fmt) == VG_LITE_INDEX_1       \
55      || (fmt) == VG_LITE_INDEX_2 \
56      || (fmt) == VG_LITE_INDEX_4 \
57      || (fmt) == VG_LITE_INDEX_8)
58 
59 #define VLC_GET_ARG(CUR, INDEX) vlc_get_arg((cur + (INDEX) * fmt_len), path->format);
60 #define VLC_GET_OP_CODE(ptr) (*((uint8_t*)ptr))
61 #define VLC_OP_ARG_LEN(OP, LEN) \
62     case VLC_OP_##OP:           \
63     return (LEN)
64 
65 #define A(color) ((color) >> 24)
66 #define R(color) (((color) & 0x00ff0000) >> 16)
67 #define G(color) (((color) & 0x0000ff00) >> 8)
68 #define B(color) ((color) & 0xff)
69 #define ARGB(a, r, g, b) ((a) << 24) | ((r) << 16) | ((g) << 8) | (b)
70 #define MIN(a, b) (a) > (b) ? (b) : (a)
71 #define MAX(a, b) (a) > (b) ? (a) : (b)
72 #define UDIV255(x) (((x) * 0x8081U) >> 0x17)
73 #define LERP(v1, v2, w) ((v1) * (w) + (v2) * (1.0f - (w)))
74 #define CLAMP(x, min, max) (((x) < (min)) ? (min) : ((x) > (max)) ? (max) : (x))
75 #define COLOR_FROM_RAMP(ColorRamp) (((vg_lite_float_t*)ColorRamp) + 1)
76 
77 #define VG_LITE_RETURN_ERROR(func)         \
78     if ((error = func) != VG_LITE_SUCCESS) \
79         return error
80 
81 #define VG_LITE_ALIGN(number, align_bytes) \
82     (((number) + ((align_bytes)-1)) & ~((align_bytes)-1))
83 
84 #define VG_LITE_IS_ALIGNED(num, align) (((uintptr_t)(num) & ((align)-1)) == 0)
85 
86 #define VG_LITE_IS_ALPHA_FORMAT(format) \
87     ((format) == VG_LITE_A8 || (format) == VG_LITE_A4)
88 
89 /* clang-format on */
90 
91 /**********************
92  *      TYPEDEFS
93  **********************/
94 
95 using namespace tvg;
96 
97 #pragma pack(1)
98 typedef struct {
99     uint8_t blue;
100     uint8_t green;
101     uint8_t red;
102 } vg_color24_t;
103 
104 typedef struct {
105     uint16_t blue : 5;
106     uint16_t green : 6;
107     uint16_t red : 5;
108 } vg_color16_t;
109 
110 typedef struct {
111     vg_color16_t c;
112     uint8_t alpha;
113 } vg_color16_alpha_t;
114 
115 typedef struct {
116     uint8_t blue;
117     uint8_t green;
118     uint8_t red;
119     uint8_t alpha;
120 } vg_color32_t;
121 
122 typedef struct {
123     uint8_t blue : 4;
124     uint8_t green : 4;
125     uint8_t red : 4;
126     uint8_t alpha : 4;
127 } vg_color_bgra4444_t;
128 
129 typedef struct {
130     uint8_t blue : 2;
131     uint8_t green : 2;
132     uint8_t red : 2;
133     uint8_t alpha : 2;
134 } vg_color_bgra2222_t;
135 
136 typedef struct {
137     uint8_t blue : 5;
138     uint8_t green : 5;
139     uint8_t red : 5;
140     uint8_t alpha : 1;
141 } vg_color_bgra5551_t;
142 
143 typedef struct {
144     vg_lite_float_t x;
145     vg_lite_float_t y;
146 } vg_lite_fpoint_t;
147 
148 #pragma pack()
149 
150 class vg_lite_ctx
151 {
152     public:
153         std::unique_ptr<SwCanvas> canvas;
154         void * target_buffer;
155         void * tvg_target_buffer;
156         vg_lite_uint32_t target_px_size;
157         vg_lite_buffer_format_t target_format;
158         vg_lite_rectangle_t scissor_rect;
159         bool scissor_is_set;
160 
161     public:
vg_lite_ctx()162         vg_lite_ctx()
163             : target_buffer { nullptr }
164             , tvg_target_buffer { nullptr }
165             , target_px_size { 0 }
166             , target_format { VG_LITE_BGRA8888 }
167             , scissor_rect { 0, 0, 0, 0 }
168             , scissor_is_set { false }
169             , clut_2colors { 0 }
170             , clut_4colors { 0 }
171             , clut_16colors { 0 }
172             , clut_256colors { 0 }
173         {
174             canvas = SwCanvas::gen();
175         }
176 
get_image_buffer(vg_lite_uint32_t w,vg_lite_uint32_t h)177         vg_lite_uint32_t * get_image_buffer(vg_lite_uint32_t w, vg_lite_uint32_t h)
178         {
179             src_buffer.resize(w * h);
180             return src_buffer.data();
181         }
182 
get_temp_target_buffer(vg_lite_uint32_t w,vg_lite_uint32_t h)183         vg_lite_uint32_t * get_temp_target_buffer(vg_lite_uint32_t w, vg_lite_uint32_t h)
184         {
185             vg_lite_uint32_t px_size = w * h;
186             if(px_size > dest_buffer.size()) {
187                 dest_buffer.resize(w * h);
188             }
189             return dest_buffer.data();
190         }
191 
get_temp_target_buffer()192         vg_lite_uint32_t * get_temp_target_buffer()
193         {
194             return dest_buffer.data();
195         }
196 
set_CLUT(vg_lite_uint32_t count,const vg_lite_uint32_t * colors)197         void set_CLUT(vg_lite_uint32_t count, const vg_lite_uint32_t * colors)
198         {
199             switch(count) {
200                 case 2:
201                     memcpy(clut_2colors, colors, sizeof(clut_2colors));
202                     break;
203                 case 4:
204                     memcpy(clut_4colors, colors, sizeof(clut_4colors));
205                     break;
206                 case 16:
207                     memcpy(clut_16colors, colors, sizeof(clut_16colors));
208                     break;
209                 case 256:
210                     memcpy(clut_256colors, colors, sizeof(clut_256colors));
211                     break;
212                 default:
213                     LV_ASSERT(false);
214                     break;
215             }
216         }
217 
get_CLUT(vg_lite_buffer_format_t format)218         const vg_lite_uint32_t * get_CLUT(vg_lite_buffer_format_t format)
219         {
220             switch(format) {
221                 case VG_LITE_INDEX_1:
222                     return clut_2colors;
223 
224                 case VG_LITE_INDEX_2:
225                     return clut_2colors;
226 
227                 case VG_LITE_INDEX_4:
228                     return clut_4colors;
229 
230                 case VG_LITE_INDEX_8:
231                     return clut_256colors;
232 
233                 default:
234                     break;
235             }
236 
237             LV_ASSERT(false);
238             return nullptr;
239         }
240 
get_instance()241         static vg_lite_ctx * get_instance()
242         {
243             static vg_lite_ctx instance;
244             return &instance;
245         }
246 
247     private:
248         /*  */
249         std::vector<vg_lite_uint32_t> src_buffer;
250         std::vector<vg_lite_uint32_t> dest_buffer;
251 
252         vg_lite_uint32_t clut_2colors[2];
253         vg_lite_uint32_t clut_4colors[4];
254         vg_lite_uint32_t clut_16colors[16];
255         vg_lite_uint32_t clut_256colors[256];
256 };
257 
258 template <typename DEST_TYPE, typename SRC_TYPE>
259 class vg_lite_converter
260 {
261     public:
262         typedef void (*converter_cb_t)(DEST_TYPE * dest, const SRC_TYPE * src, vg_lite_uint32_t px_size,
263                                        vg_lite_uint32_t color);
264 
265     public:
vg_lite_converter(converter_cb_t converter)266         vg_lite_converter(converter_cb_t converter)
267             : _converter_cb(converter)
268         {
269         }
270 
convert(vg_lite_buffer_t * dest_buf,const vg_lite_buffer_t * src_buf,vg_lite_uint32_t color=0)271         void convert(vg_lite_buffer_t * dest_buf, const vg_lite_buffer_t * src_buf, vg_lite_uint32_t color = 0)
272         {
273             LV_ASSERT(_converter_cb);
274             uint8_t * dest = (uint8_t *)dest_buf->memory;
275             const uint8_t * src = (const uint8_t *)src_buf->memory;
276             vg_lite_uint32_t h = src_buf->height;
277 
278             while(h--) {
279                 _converter_cb((DEST_TYPE *)dest, (const SRC_TYPE *)src, src_buf->width, color);
280                 dest += dest_buf->stride;
281                 src += src_buf->stride;
282             }
283         }
284 
285     private:
286         converter_cb_t _converter_cb;
287 };
288 
289 typedef vg_lite_float_t FLOATVECTOR4[4];
290 
291 /**********************
292  *  STATIC PROTOTYPES
293  **********************/
294 
295 static vg_lite_error_t vg_lite_error_conv(Result result);
296 static Matrix matrix_conv(const vg_lite_matrix_t * matrix);
297 static FillRule fill_rule_conv(vg_lite_fill_t fill);
298 static BlendMethod blend_method_conv(vg_lite_blend_t blend);
299 static StrokeCap stroke_cap_conv(vg_lite_cap_style_t cap);
300 static StrokeJoin stroke_join_conv(vg_lite_join_style_t join);
301 static FillSpread fill_spread_conv(vg_lite_gradient_spreadmode_t spread);
302 static Result shape_append_path(std::unique_ptr<Shape> & shape, vg_lite_path_t * path, vg_lite_matrix_t * matrix);
303 static Result shape_append_rect(std::unique_ptr<Shape> & shape, const vg_lite_buffer_t * target,
304                                 const vg_lite_rectangle_t * rect);
305 static Result canvas_set_target(vg_lite_ctx * ctx, vg_lite_buffer_t * target);
306 static Result picture_load(vg_lite_ctx * ctx, std::unique_ptr<Picture> & picture, const vg_lite_buffer_t * source,
307                            vg_lite_color_t color = 0);
308 
math_zero(float a)309 static inline bool math_zero(float a)
310 {
311     return (fabs(a) < FLT_EPSILON);
312 }
313 
math_equal(float a,float b)314 static inline bool math_equal(float a, float b)
315 {
316     return math_zero(a - b);
317 }
318 
319 static void ClampColor(FLOATVECTOR4 Source, FLOATVECTOR4 Target, uint8_t Premultiplied);
320 static uint8_t PackColorComponent(vg_lite_float_t value);
321 static void get_format_bytes(vg_lite_buffer_format_t format,
322                              vg_lite_uint32_t * mul,
323                              vg_lite_uint32_t * div,
324                              vg_lite_uint32_t * bytes_align);
325 
326 static vg_lite_fpoint_t matrix_transform_point(const vg_lite_matrix_t * matrix, const vg_lite_fpoint_t * point);
327 static bool vg_lite_matrix_inverse(vg_lite_matrix_t * result, const vg_lite_matrix_t * matrix);
328 static void vg_lite_matrix_multiply(vg_lite_matrix_t * matrix, const vg_lite_matrix_t * mult);
329 
330 /**********************
331  *  STATIC VARIABLES
332  **********************/
333 
334 /* color converters */
335 
336 static vg_lite_converter<vg_color16_t, vg_color32_t> conv_bgra8888_to_bgr565(
337     [](vg_color16_t * dest, const vg_color32_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t /* color */)
__anone335e65f0902(vg_color16_t * dest, const vg_color32_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t ) 338 {
339     while(px_size--) {
340         dest->red = src->red * 0x1F / 0xFF;
341         dest->green = src->green * 0x3F / 0xFF;
342         dest->blue = src->blue * 0x1F / 0xFF;
343         src++;
344         dest++;
345     }
346 });
347 
348 static vg_lite_converter<vg_color16_alpha_t, vg_color32_t> conv_bgra8888_to_bgra5658(
349     [](vg_color16_alpha_t * dest, const vg_color32_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t /* color */)
__anone335e65f0a02(vg_color16_alpha_t * dest, const vg_color32_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t ) 350 {
351     while(px_size--) {
352         dest->c.red = src->red * 0x1F / 0xFF;
353         dest->c.green = src->green * 0x3F / 0xFF;
354         dest->c.blue = src->blue * 0x1F / 0xFF;
355         dest->alpha = src->alpha;
356         src++;
357         dest++;
358     }
359 });
360 
361 static vg_lite_converter<vg_color32_t, vg_color16_t> conv_bgr565_to_bgra8888(
362     [](vg_color32_t * dest, const vg_color16_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t /* color */)
__anone335e65f0b02(vg_color32_t * dest, const vg_color16_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t ) 363 {
364     while(px_size--) {
365         dest->red = src->red * 0xFF / 0x1F;
366         dest->green = src->green * 0xFF / 0x3F;
367         dest->blue = src->blue * 0xFF / 0x1F;
368         dest->alpha = 0xFF;
369         src++;
370         dest++;
371     }
372 });
373 
374 static vg_lite_converter<vg_color32_t, vg_color16_alpha_t> conv_bgra5658_to_bgra8888(
375     [](vg_color32_t * dest, const vg_color16_alpha_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t /* color */)
__anone335e65f0c02(vg_color32_t * dest, const vg_color16_alpha_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t ) 376 {
377     while(px_size--) {
378         dest->red = src->c.red * 0xFF / 0x1F;
379         dest->green = src->c.green * 0xFF / 0x3F;
380         dest->blue = src->c.blue * 0xFF / 0x1F;
381         dest->alpha = src->alpha;
382         src++;
383         dest++;
384     }
385 });
386 
387 static vg_lite_converter<vg_color32_t, vg_color32_t> conv_bgrx8888_to_bgra8888(
388     [](vg_color32_t * dest, const vg_color32_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t /* color */)
__anone335e65f0d02(vg_color32_t * dest, const vg_color32_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t ) 389 {
390     while(px_size--) {
391         *dest = *src;
392         dest->alpha = 0xFF;
393         dest++;
394         src++;
395     }
396 });
397 
398 static vg_lite_converter<vg_color32_t, vg_color24_t> conv_bgr888_to_bgra8888(
399     [](vg_color32_t * dest, const vg_color24_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t /* color */)
__anone335e65f0e02(vg_color32_t * dest, const vg_color24_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t ) 400 {
401     while(px_size--) {
402         dest->red = src->red;
403         dest->green = src->green;
404         dest->blue = src->blue;
405         dest->alpha = 0xFF;
406         src++;
407         dest++;
408     }
409 });
410 
411 static vg_lite_converter<vg_color32_t, uint8_t> conv_alpha8_to_bgra8888(
412     [](vg_color32_t * dest, const uint8_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t color)
__anone335e65f0f02(vg_color32_t * dest, const uint8_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t color) 413 {
414     while(px_size--) {
415         uint8_t alpha = *src;
416         dest->alpha = alpha;
417         dest->red = UDIV255(B(color) * alpha);
418         dest->green = UDIV255(G(color) * alpha);
419         dest->blue = UDIV255(R(color) * alpha);
420         dest++;
421         src++;
422     }
423 });
424 
425 static vg_lite_converter<vg_color32_t, uint8_t> conv_alpha4_to_bgra8888(
426     [](vg_color32_t * dest, const uint8_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t color)
__anone335e65f1002(vg_color32_t * dest, const uint8_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t color) 427 {
428     /* 1 byte -> 2 px */
429     px_size /= 2;
430 
431     while(px_size--) {
432         /* high 4bit */
433         uint8_t alpha = (*src & 0xF0);
434         dest->alpha = alpha;
435         dest->red = UDIV255(B(color) * alpha);
436         dest->green = UDIV255(G(color) * alpha);
437         dest->blue = UDIV255(R(color) * alpha);
438         dest++;
439 
440         /* low 4bit */
441         alpha = (*src & 0x0F) << 4;
442         dest->alpha = alpha;
443         dest->red = UDIV255(B(color) * alpha);
444         dest->green = UDIV255(G(color) * alpha);
445         dest->blue = UDIV255(R(color) * alpha);
446 
447         dest++;
448         src++;
449     }
450 });
451 
452 static vg_lite_converter<vg_color32_t, uint8_t> conv_l8_to_bgra8888(
453     [](vg_color32_t * dest, const uint8_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t /* color */)
__anone335e65f1102(vg_color32_t * dest, const uint8_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t ) 454 {
455     while(px_size--) {
456         dest->alpha = 0xFF;
457         dest->red = *src;
458         dest->green = *src;
459         dest->blue = *src;
460         dest++;
461         src++;
462     }
463 });
464 
465 static vg_lite_converter<vg_color32_t, vg_color_bgra5551_t> conv_bgra5551_to_bgra8888(
466     [](vg_color32_t * dest, const vg_color_bgra5551_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t /* color */)
__anone335e65f1202(vg_color32_t * dest, const vg_color_bgra5551_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t ) 467 {
468     while(px_size--) {
469         dest->red = src->red * 0xFF / 0x1F;
470         dest->green = src->green * 0xFF / 0x1F;
471         dest->blue = src->blue * 0xFF / 0x1F;
472         dest->alpha = src->alpha ? 0xFF : 0;
473         src++;
474         dest++;
475     }
476 });
477 
478 static vg_lite_converter<vg_color32_t, vg_color_bgra4444_t> conv_bgra4444_to_bgra8888(
479     [](vg_color32_t * dest, const vg_color_bgra4444_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t /* color */)
__anone335e65f1302(vg_color32_t * dest, const vg_color_bgra4444_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t ) 480 {
481     while(px_size--) {
482         dest->red = src->red * 0xFF / 0xF;
483         dest->green = src->green * 0xFF / 0xF;
484         dest->blue = src->blue * 0xFF / 0xF;
485         dest->alpha = src->alpha * 0xFF / 0xF;
486         src++;
487         dest++;
488     }
489 });
490 
491 static vg_lite_converter<vg_color32_t, vg_color_bgra2222_t> conv_bgra2222_to_bgra8888(
492     [](vg_color32_t * dest, const vg_color_bgra2222_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t /* color */)
__anone335e65f1402(vg_color32_t * dest, const vg_color_bgra2222_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t ) 493 {
494     while(px_size--) {
495         dest->red = src->red * 0xFF / 0x3;
496         dest->green = src->green * 0xFF / 0x3;
497         dest->blue = src->blue * 0xFF / 0x3;
498         dest->alpha = src->alpha * 0xFF / 0x3;
499         src++;
500         dest++;
501     }
502 });
503 
504 /**********************
505  *      MACROS
506  **********************/
507 
508 /**********************
509  *   GLOBAL FUNCTIONS
510  **********************/
511 
512 extern "C" {
513 
gpu_init(void)514     void gpu_init(void)
515     {
516         vg_lite_init(0, 0);
517     }
518 
vg_lite_allocate(vg_lite_buffer_t * buffer)519     vg_lite_error_t vg_lite_allocate(vg_lite_buffer_t * buffer)
520     {
521         if(buffer->format == VG_LITE_RGBA8888_ETC2_EAC && (buffer->width % 16 || buffer->height % 4)) {
522             return VG_LITE_INVALID_ARGUMENT;
523         }
524 
525         /* Reset planar. */
526         buffer->yuv.uv_planar = buffer->yuv.v_planar = buffer->yuv.alpha_planar = 0;
527 
528         /* Align height in case format is tiled. */
529         if(buffer->format >= VG_LITE_YUY2 && buffer->format <= VG_LITE_NV16) {
530             buffer->height = VG_LITE_ALIGN(buffer->height, 4);
531             buffer->yuv.swizzle = VG_LITE_SWIZZLE_UV;
532         }
533 
534         if(buffer->format >= VG_LITE_YUY2_TILED && buffer->format <= VG_LITE_AYUY2_TILED) {
535             buffer->height = VG_LITE_ALIGN(buffer->height, 4);
536             buffer->tiled = VG_LITE_TILED;
537             buffer->yuv.swizzle = VG_LITE_SWIZZLE_UV;
538         }
539 
540         vg_lite_uint32_t mul, div, align;
541         get_format_bytes(buffer->format, &mul, &div, &align);
542         vg_lite_uint32_t stride = VG_LITE_ALIGN((buffer->width * mul / div), align);
543 
544         buffer->stride = stride;
545 
546         /* Size must be multiple of align, See: https://en.cppreference.com/w/c/memory/aligned_alloc */
547         size_t size = VG_LITE_ALIGN(buffer->height * stride, LV_VG_LITE_THORVG_BUF_ADDR_ALIGN);
548 #ifndef _WIN32
549         buffer->memory = aligned_alloc(LV_VG_LITE_THORVG_BUF_ADDR_ALIGN, size);
550 #else
551         buffer->memory = _aligned_malloc(size, LV_VG_LITE_THORVG_BUF_ADDR_ALIGN);
552 #endif
553         LV_ASSERT(buffer->memory);
554         buffer->address = (vg_lite_uint32_t)(uintptr_t)buffer->memory;
555         buffer->handle = buffer->memory;
556         return VG_LITE_SUCCESS;
557     }
558 
vg_lite_free(vg_lite_buffer_t * buffer)559     vg_lite_error_t vg_lite_free(vg_lite_buffer_t * buffer)
560     {
561         LV_ASSERT(buffer->memory);
562 #ifndef _WIN32
563         free(buffer->memory);
564 #else
565         _aligned_free(buffer->memory);
566 #endif
567         memset(buffer, 0, sizeof(vg_lite_buffer_t));
568         return VG_LITE_SUCCESS;
569     }
570 
vg_lite_upload_buffer(vg_lite_buffer_t * buffer,vg_lite_uint8_t * data[3],vg_lite_uint32_t stride[3])571     vg_lite_error_t vg_lite_upload_buffer(vg_lite_buffer_t * buffer, vg_lite_uint8_t * data[3], vg_lite_uint32_t stride[3])
572     {
573         LV_UNUSED(buffer);
574         LV_UNUSED(data);
575         LV_UNUSED(stride);
576         return VG_LITE_NOT_SUPPORT;
577     }
578 
vg_lite_map(vg_lite_buffer_t * buffer,vg_lite_map_flag_t flag,int32_t fd)579     vg_lite_error_t vg_lite_map(vg_lite_buffer_t * buffer, vg_lite_map_flag_t flag, int32_t fd)
580     {
581         LV_UNUSED(buffer);
582         LV_UNUSED(flag);
583         LV_UNUSED(fd);
584         return VG_LITE_NOT_SUPPORT;
585     }
586 
vg_lite_unmap(vg_lite_buffer_t * buffer)587     vg_lite_error_t vg_lite_unmap(vg_lite_buffer_t * buffer)
588     {
589         LV_UNUSED(buffer);
590         return VG_LITE_NOT_SUPPORT;
591     }
592 
vg_lite_clear(vg_lite_buffer_t * target,vg_lite_rectangle_t * rectangle,vg_lite_color_t color)593     vg_lite_error_t vg_lite_clear(vg_lite_buffer_t * target, vg_lite_rectangle_t * rectangle, vg_lite_color_t color)
594     {
595         auto ctx = vg_lite_ctx::get_instance();
596         TVG_CHECK_RETURN_VG_ERROR(canvas_set_target(ctx, target));
597 
598         auto shape = Shape::gen();
599         TVG_CHECK_RETURN_VG_ERROR(shape_append_rect(shape, target, rectangle));
600         TVG_CHECK_RETURN_VG_ERROR(shape->blend(BlendMethod::SrcOver));
601         TVG_CHECK_RETURN_VG_ERROR(shape->fill(TVG_COLOR(color)));
602         TVG_CHECK_RETURN_VG_ERROR(ctx->canvas->push(std::move(shape)));
603 
604         return VG_LITE_SUCCESS;
605     }
606 
vg_lite_blit(vg_lite_buffer_t * target,vg_lite_buffer_t * source,vg_lite_matrix_t * matrix,vg_lite_blend_t blend,vg_lite_color_t color,vg_lite_filter_t filter)607     vg_lite_error_t vg_lite_blit(vg_lite_buffer_t * target,
608                                  vg_lite_buffer_t * source,
609                                  vg_lite_matrix_t * matrix,
610                                  vg_lite_blend_t blend,
611                                  vg_lite_color_t color,
612                                  vg_lite_filter_t filter)
613     {
614         LV_UNUSED(filter);
615         auto ctx = vg_lite_ctx::get_instance();
616         canvas_set_target(ctx, target);
617 
618         auto picture = Picture::gen();
619 
620         TVG_CHECK_RETURN_VG_ERROR(picture_load(ctx, picture, source, color));
621         TVG_CHECK_RETURN_VG_ERROR(picture->transform(matrix_conv(matrix)));
622         TVG_CHECK_RETURN_VG_ERROR(picture->blend(blend_method_conv(blend)));
623         TVG_CHECK_RETURN_VG_ERROR(ctx->canvas->push(std::move(picture)));
624 
625         return VG_LITE_SUCCESS;
626     }
627 
vg_lite_blit2(vg_lite_buffer_t * target,vg_lite_buffer_t * source0,vg_lite_buffer_t * source1,vg_lite_matrix_t * matrix0,vg_lite_matrix_t * matrix1,vg_lite_blend_t blend,vg_lite_filter_t filter)628     vg_lite_error_t vg_lite_blit2(vg_lite_buffer_t * target,
629                                   vg_lite_buffer_t * source0,
630                                   vg_lite_buffer_t * source1,
631                                   vg_lite_matrix_t * matrix0,
632                                   vg_lite_matrix_t * matrix1,
633                                   vg_lite_blend_t blend,
634                                   vg_lite_filter_t filter)
635     {
636         if(!vg_lite_query_feature(gcFEATURE_BIT_VG_DOUBLE_IMAGE)) {
637             return VG_LITE_NOT_SUPPORT;
638         }
639 
640         vg_lite_error_t error;
641 
642         VG_LITE_RETURN_ERROR(vg_lite_blit(target, source0, matrix0, blend, 0, filter));
643         VG_LITE_RETURN_ERROR(vg_lite_blit(target, source1, matrix1, blend, 0, filter));
644 
645         return VG_LITE_SUCCESS;
646     }
647 
vg_lite_blit_rect(vg_lite_buffer_t * target,vg_lite_buffer_t * source,vg_lite_rectangle_t * rect,vg_lite_matrix_t * matrix,vg_lite_blend_t blend,vg_lite_color_t color,vg_lite_filter_t filter)648     vg_lite_error_t vg_lite_blit_rect(vg_lite_buffer_t * target,
649                                       vg_lite_buffer_t * source,
650                                       vg_lite_rectangle_t * rect,
651                                       vg_lite_matrix_t * matrix,
652                                       vg_lite_blend_t blend,
653                                       vg_lite_color_t color,
654                                       vg_lite_filter_t filter)
655     {
656         LV_UNUSED(filter);
657         auto ctx = vg_lite_ctx::get_instance();
658         TVG_CHECK_RETURN_VG_ERROR(canvas_set_target(ctx, target));
659 
660         auto shape = Shape::gen();
661         TVG_CHECK_RETURN_VG_ERROR(shape_append_rect(shape, target, rect));
662         TVG_CHECK_RETURN_VG_ERROR(shape->transform(matrix_conv(matrix)));
663 
664         auto picture = tvg::Picture::gen();
665         TVG_CHECK_RETURN_VG_ERROR(picture_load(ctx, picture, source, color));
666         TVG_CHECK_RETURN_VG_ERROR(picture->transform(matrix_conv(matrix)));
667         TVG_CHECK_RETURN_VG_ERROR(picture->blend(blend_method_conv(blend)));
668         TVG_CHECK_RETURN_VG_ERROR(picture->composite(std::move(shape), CompositeMethod::ClipPath));
669         TVG_CHECK_RETURN_VG_ERROR(ctx->canvas->push(std::move(picture)));
670 
671         return VG_LITE_SUCCESS;
672     }
673 
vg_lite_init(int32_t tessellation_width,int32_t tessellation_height)674     vg_lite_error_t vg_lite_init(int32_t tessellation_width, int32_t tessellation_height)
675     {
676         LV_UNUSED(tessellation_width);
677         LV_UNUSED(tessellation_height);
678 #if LV_VG_LITE_THORVG_THREAD_RENDER
679         /* Threads Count */
680         auto threads = std::thread::hardware_concurrency();
681         if(threads > 0) {
682             --threads; /* Allow the designated main thread capacity */
683         }
684 #endif
685 
686         /* Initialize ThorVG Engine */
687         TVG_CHECK_RETURN_VG_ERROR(Initializer::init(TVG_CANVAS_ENGINE, 0));
688         return VG_LITE_SUCCESS;
689     }
690 
vg_lite_close(void)691     vg_lite_error_t vg_lite_close(void)
692     {
693         TVG_CHECK_RETURN_VG_ERROR(Initializer::term(TVG_CANVAS_ENGINE));
694         return VG_LITE_SUCCESS;
695     }
696 
picture_bgra8888_to_bgr565(vg_color16_t * dest,const vg_color32_t * src,vg_lite_uint32_t px_size)697     static void picture_bgra8888_to_bgr565(vg_color16_t * dest, const vg_color32_t * src, vg_lite_uint32_t px_size)
698     {
699         while(px_size--) {
700             dest->red = src->red * 0x1F / 0xFF;
701             dest->green = src->green * 0x3F / 0xFF;
702             dest->blue = src->blue * 0x1F / 0xFF;
703             src++;
704             dest++;
705         }
706     }
707 
picture_bgra8888_to_bgra5658(vg_color16_alpha_t * dest,const vg_color32_t * src,vg_lite_uint32_t px_size)708     static void picture_bgra8888_to_bgra5658(vg_color16_alpha_t * dest, const vg_color32_t * src, vg_lite_uint32_t px_size)
709     {
710         while(px_size--) {
711             dest->c.red = src->red * 0x1F / 0xFF;
712             dest->c.green = src->green * 0x3F / 0xFF;
713             dest->c.blue = src->blue * 0x1F / 0xFF;
714             dest->alpha = src->alpha;
715             src++;
716             dest++;
717         }
718     }
719 
picture_bgra8888_to_bgr888(vg_color24_t * dest,const vg_color32_t * src,vg_lite_uint32_t px_size)720     static void picture_bgra8888_to_bgr888(vg_color24_t * dest, const vg_color32_t * src, vg_lite_uint32_t px_size)
721     {
722         while(px_size--) {
723             dest->red = src->red;
724             dest->green = src->green;
725             dest->blue = src->blue;
726             src++;
727             dest++;
728         }
729     }
730 
picture_bgra8888_to_l8(uint8_t * dest,const vg_color32_t * src,vg_lite_uint32_t px_size)731     static void picture_bgra8888_to_l8(uint8_t * dest, const vg_color32_t * src, vg_lite_uint32_t px_size)
732     {
733         while(px_size--) {
734             *dest = (src->red * 19595 + src->green * 38469 + src->blue * 7472) >> 16;
735             src++;
736             dest++;
737         }
738     }
739 
picture_bgra8888_to_alpha8(uint8_t * dest,const vg_color32_t * src,vg_lite_uint32_t px_size)740     static void picture_bgra8888_to_alpha8(uint8_t * dest, const vg_color32_t * src, vg_lite_uint32_t px_size)
741     {
742         while(px_size--) {
743             *dest = src->alpha;
744             src++;
745             dest++;
746         }
747     }
748 
picture_bgra8888_to_bgra5551(vg_color_bgra5551_t * dest,const vg_color32_t * src,vg_lite_uint32_t px_size)749     static void picture_bgra8888_to_bgra5551(vg_color_bgra5551_t * dest, const vg_color32_t * src, vg_lite_uint32_t px_size)
750     {
751         while(px_size--) {
752             dest->red = src->red * 0x1F / 0xFF;
753             dest->green = src->green * 0x1F / 0xFF;
754             dest->blue = src->blue * 0x1F / 0xFF;
755             dest->alpha = src->alpha > (0xFF / 2) ? 1 : 0;
756             src++;
757             dest++;
758         }
759     }
760 
picture_bgra8888_to_bgra4444(vg_color_bgra4444_t * dest,const vg_color32_t * src,vg_lite_uint32_t px_size)761     static void picture_bgra8888_to_bgra4444(vg_color_bgra4444_t * dest, const vg_color32_t * src, vg_lite_uint32_t px_size)
762     {
763         while(px_size--) {
764             dest->red = src->red * 0xF / 0xFF;
765             dest->green = src->green * 0xF / 0xFF;
766             dest->blue = src->blue * 0xF / 0xFF;
767             dest->alpha = src->alpha * 0xF / 0xFF;
768             src++;
769             dest++;
770         }
771     }
772 
picture_bgra8888_to_bgra2222(vg_color_bgra2222_t * dest,const vg_color32_t * src,vg_lite_uint32_t px_size)773     static void picture_bgra8888_to_bgra2222(vg_color_bgra2222_t * dest, const vg_color32_t * src, vg_lite_uint32_t px_size)
774     {
775         while(px_size--) {
776             dest->red = src->red * 0x3 / 0xFF;
777             dest->green = src->green * 0x3 / 0xFF;
778             dest->blue = src->blue * 0x3 / 0xFF;
779             dest->alpha = src->alpha * 0x3 / 0xFF;
780             src++;
781             dest++;
782         }
783     }
784 
785 
vg_lite_finish(void)786     vg_lite_error_t vg_lite_finish(void)
787     {
788         vg_lite_ctx * ctx = vg_lite_ctx::get_instance();
789 
790         if(ctx->canvas->draw() == Result::InsufficientCondition) {
791             return VG_LITE_SUCCESS;
792         }
793 
794         TVG_CHECK_RETURN_VG_ERROR(ctx->canvas->sync());
795         TVG_CHECK_RETURN_VG_ERROR(ctx->canvas->clear(true));
796 
797         /* make sure target buffer is valid */
798         LV_ASSERT_NULL(ctx->target_buffer);
799 
800         /* If target_buffer is not in a format supported by thorvg, software conversion is required. */
801         switch(ctx->target_format) {
802             case VG_LITE_BGR565:
803                 picture_bgra8888_to_bgr565(
804                     (vg_color16_t *)ctx->target_buffer,
805                     (const vg_color32_t *)ctx->get_temp_target_buffer(),
806                     ctx->target_px_size);
807                 break;
808             case VG_LITE_BGRA5658:
809                 picture_bgra8888_to_bgra5658(
810                     (vg_color16_alpha_t *)ctx->target_buffer,
811                     (const vg_color32_t *)ctx->get_temp_target_buffer(),
812                     ctx->target_px_size);
813                 break;
814             case VG_LITE_BGR888:
815                 picture_bgra8888_to_bgr888(
816                     (vg_color24_t *)ctx->target_buffer,
817                     (const vg_color32_t *)ctx->get_temp_target_buffer(),
818                     ctx->target_px_size);
819                 break;
820             case VG_LITE_L8:
821                 picture_bgra8888_to_l8(
822                     (uint8_t *)ctx->target_buffer,
823                     (const vg_color32_t *)ctx->get_temp_target_buffer(),
824                     ctx->target_px_size);
825                 break;
826             case VG_LITE_A8:
827                 picture_bgra8888_to_alpha8(
828                     (uint8_t *)ctx->target_buffer,
829                     (const vg_color32_t *)ctx->get_temp_target_buffer(),
830                     ctx->target_px_size);
831                 break;
832             case VG_LITE_BGRA5551:
833                 picture_bgra8888_to_bgra5551((vg_color_bgra5551_t *)ctx->target_buffer,
834                                              (const vg_color32_t *)ctx->get_temp_target_buffer(),
835                                              ctx->target_px_size);
836                 break;
837             case VG_LITE_BGRA4444:
838                 picture_bgra8888_to_bgra4444((vg_color_bgra4444_t *)ctx->target_buffer,
839                                              (const vg_color32_t *)ctx->get_temp_target_buffer(),
840                                              ctx->target_px_size);
841                 break;
842             case VG_LITE_BGRA2222:
843                 picture_bgra8888_to_bgra2222((vg_color_bgra2222_t *)ctx->target_buffer,
844                                              (const vg_color32_t *)ctx->get_temp_target_buffer(),
845                                              ctx->target_px_size);
846                 break;
847             case VG_LITE_BGRA8888:
848             case VG_LITE_BGRX8888:
849                 /* No conversion required. */
850                 break;
851             default:
852                 LV_LOG_ERROR("unsupported format: %d", ctx->target_format);
853                 LV_ASSERT(false);
854                 break;
855         }
856 
857         /* finish convert, clean target buffer info */
858         ctx->target_buffer = nullptr;
859         ctx->tvg_target_buffer = nullptr;
860         ctx->target_px_size = 0;
861 
862         return VG_LITE_SUCCESS;
863     }
864 
vg_lite_flush(void)865     vg_lite_error_t vg_lite_flush(void)
866     {
867         return vg_lite_finish();
868     }
869 
vg_lite_draw(vg_lite_buffer_t * target,vg_lite_path_t * path,vg_lite_fill_t fill_rule,vg_lite_matrix_t * matrix,vg_lite_blend_t blend,vg_lite_color_t color)870     vg_lite_error_t vg_lite_draw(vg_lite_buffer_t * target,
871                                  vg_lite_path_t * path,
872                                  vg_lite_fill_t fill_rule,
873                                  vg_lite_matrix_t * matrix,
874                                  vg_lite_blend_t blend,
875                                  vg_lite_color_t color)
876     {
877         auto ctx = vg_lite_ctx::get_instance();
878         TVG_CHECK_RETURN_VG_ERROR(canvas_set_target(ctx, target));
879 
880         auto shape = Shape::gen();
881         TVG_CHECK_RETURN_VG_ERROR(shape_append_path(shape, path, matrix));
882         TVG_CHECK_RETURN_VG_ERROR(shape->transform(matrix_conv(matrix)));
883         TVG_CHECK_RETURN_VG_ERROR(shape->fill(fill_rule_conv(fill_rule)););
884         TVG_CHECK_RETURN_VG_ERROR(shape->blend(blend_method_conv(blend)));
885         TVG_CHECK_RETURN_VG_ERROR(shape->fill(TVG_COLOR(color)));
886         TVG_CHECK_RETURN_VG_ERROR(ctx->canvas->push(std::move(shape)));
887 
888         return VG_LITE_SUCCESS;
889     }
890 
vg_lite_set_stroke(vg_lite_path_t * path,vg_lite_cap_style_t cap_style,vg_lite_join_style_t join_style,vg_lite_float_t line_width,vg_lite_float_t miter_limit,vg_lite_float_t * dash_pattern,vg_lite_uint32_t pattern_count,vg_lite_float_t dash_phase,vg_lite_color_t color)891     vg_lite_error_t vg_lite_set_stroke(vg_lite_path_t * path,
892                                        vg_lite_cap_style_t cap_style,
893                                        vg_lite_join_style_t join_style,
894                                        vg_lite_float_t line_width,
895                                        vg_lite_float_t miter_limit,
896                                        vg_lite_float_t * dash_pattern,
897                                        vg_lite_uint32_t pattern_count,
898                                        vg_lite_float_t dash_phase,
899                                        vg_lite_color_t color)
900     {
901         if(!path || line_width <= 0) {
902             return VG_LITE_INVALID_ARGUMENT;
903         }
904 
905         if(miter_limit < 1.0f) {
906             miter_limit = 1.0f;
907         }
908 
909         if(!path->stroke) {
910             path->stroke = (vg_lite_stroke_t *)lv_malloc_zeroed(sizeof(vg_lite_stroke_t));
911 
912             if(!path->stroke) {
913                 return VG_LITE_OUT_OF_RESOURCES;
914             }
915         }
916 
917         path->stroke->cap_style = cap_style;
918         path->stroke->join_style = join_style;
919         path->stroke->line_width = line_width;
920         path->stroke->miter_limit = miter_limit;
921         path->stroke->half_width = line_width / 2.0f;
922         path->stroke->miter_square = path->stroke->miter_limit * path->stroke->miter_limit;
923         path->stroke->dash_pattern = dash_pattern;
924         path->stroke->pattern_count = pattern_count;
925         path->stroke->dash_phase = dash_phase;
926         path->stroke_color = color;
927         return VG_LITE_SUCCESS;
928     }
929 
vg_lite_update_stroke(vg_lite_path_t * path)930     vg_lite_error_t vg_lite_update_stroke(vg_lite_path_t * path)
931     {
932         LV_UNUSED(path);
933         return VG_LITE_SUCCESS;
934     }
935 
vg_lite_set_path_type(vg_lite_path_t * path,vg_lite_path_type_t path_type)936     vg_lite_error_t vg_lite_set_path_type(vg_lite_path_t * path, vg_lite_path_type_t path_type)
937     {
938         if(!path ||
939            (path_type != VG_LITE_DRAW_FILL_PATH &&
940             path_type != VG_LITE_DRAW_STROKE_PATH &&
941             path_type != VG_LITE_DRAW_FILL_STROKE_PATH)
942           )
943             return VG_LITE_INVALID_ARGUMENT;
944 
945         path->path_type = path_type;
946 
947         return VG_LITE_SUCCESS;
948     }
949 
vg_lite_get_register(vg_lite_uint32_t address,vg_lite_uint32_t * result)950     vg_lite_error_t vg_lite_get_register(vg_lite_uint32_t address, vg_lite_uint32_t * result)
951     {
952         LV_UNUSED(address);
953         LV_UNUSED(result);
954         return VG_LITE_NOT_SUPPORT;
955     }
956 
vg_lite_get_info(vg_lite_info_t * info)957     vg_lite_error_t vg_lite_get_info(vg_lite_info_t * info)
958     {
959         info->api_version = VGLITE_API_VERSION_3_0;
960         info->header_version = VGLITE_HEADER_VERSION;
961         info->release_version = VGLITE_RELEASE_VERSION;
962         info->reserved = 0;
963         return VG_LITE_SUCCESS;
964     }
965 
vg_lite_get_product_info(char * name,vg_lite_uint32_t * chip_id,vg_lite_uint32_t * chip_rev)966     vg_lite_uint32_t vg_lite_get_product_info(char * name, vg_lite_uint32_t * chip_id, vg_lite_uint32_t * chip_rev)
967     {
968         strcpy(name, "GCNanoLiteV");
969         *chip_id = 0x265;
970         *chip_rev = 0x2000;
971         return 1;
972     }
973 
vg_lite_query_feature(vg_lite_feature_t feature)974     vg_lite_uint32_t vg_lite_query_feature(vg_lite_feature_t feature)
975     {
976         switch(feature) {
977             case gcFEATURE_BIT_VG_IM_INDEX_FORMAT:
978             case gcFEATURE_BIT_VG_BORDER_CULLING:
979             case gcFEATURE_BIT_VG_RGBA2_FORMAT:
980             case gcFEATURE_BIT_VG_IM_FASTCLAER:
981             case gcFEATURE_BIT_VG_GLOBAL_ALPHA:
982             case gcFEATURE_BIT_VG_COLOR_KEY:
983             case gcFEATURE_BIT_VG_24BIT:
984             case gcFEATURE_BIT_VG_DITHER:
985             case gcFEATURE_BIT_VG_USE_DST:
986             case gcFEATURE_BIT_VG_RADIAL_GRADIENT:
987             case gcFEATURE_BIT_VG_IM_REPEAT_REFLECT:
988             case gcFEATURE_BIT_VG_SCISSOR:
989 
990 #if LV_VG_LITE_THORVG_LVGL_BLEND_SUPPORT
991             case gcFEATURE_BIT_VG_LVGL_SUPPORT:
992 #endif
993 
994 #if LV_VG_LITE_THORVG_YUV_SUPPORT
995             case gcFEATURE_BIT_VG_YUV_INPUT:
996 #endif
997 
998 #if LV_VG_LITE_THORVG_LINEAR_GRADIENT_EXT_SUPPORT
999             case gcFEATURE_BIT_VG_LINEAR_GRADIENT_EXT:
1000 #endif
1001 
1002 #if LV_VG_LITE_THORVG_16PIXELS_ALIGN
1003             case gcFEATURE_BIT_VG_16PIXELS_ALIGN:
1004 #endif
1005                 return 1;
1006             default:
1007                 break;
1008         }
1009         return 0;
1010     }
1011 
vg_lite_init_path(vg_lite_path_t * path,vg_lite_format_t data_format,vg_lite_quality_t quality,vg_lite_uint32_t path_length,void * path_data,vg_lite_float_t min_x,vg_lite_float_t min_y,vg_lite_float_t max_x,vg_lite_float_t max_y)1012     vg_lite_error_t vg_lite_init_path(vg_lite_path_t * path,
1013                                       vg_lite_format_t data_format,
1014                                       vg_lite_quality_t quality,
1015                                       vg_lite_uint32_t path_length,
1016                                       void * path_data,
1017                                       vg_lite_float_t min_x, vg_lite_float_t min_y,
1018                                       vg_lite_float_t max_x, vg_lite_float_t max_y)
1019     {
1020         if(!path) {
1021             return VG_LITE_INVALID_ARGUMENT;
1022         }
1023 
1024         lv_memzero(path, sizeof(vg_lite_path_t));
1025 
1026         path->format = data_format;
1027         path->quality = quality;
1028         path->bounding_box[0] = min_x;
1029         path->bounding_box[1] = min_y;
1030         path->bounding_box[2] = max_x;
1031         path->bounding_box[3] = max_y;
1032 
1033         path->path_length = path_length;
1034         path->path = path_data;
1035 
1036         path->path_changed = 1;
1037         path->uploaded.address = 0;
1038         path->uploaded.bytes = 0;
1039         path->uploaded.handle = NULL;
1040         path->uploaded.memory = NULL;
1041         path->pdata_internal = 0;
1042 
1043         return VG_LITE_SUCCESS;
1044     }
1045 
vg_lite_init_arc_path(vg_lite_path_t * path,vg_lite_format_t data_format,vg_lite_quality_t quality,vg_lite_uint32_t path_length,void * path_data,vg_lite_float_t min_x,vg_lite_float_t min_y,vg_lite_float_t max_x,vg_lite_float_t max_y)1046     vg_lite_error_t vg_lite_init_arc_path(vg_lite_path_t * path,
1047                                           vg_lite_format_t data_format,
1048                                           vg_lite_quality_t quality,
1049                                           vg_lite_uint32_t path_length,
1050                                           void * path_data,
1051                                           vg_lite_float_t min_x, vg_lite_float_t min_y,
1052                                           vg_lite_float_t max_x, vg_lite_float_t max_y)
1053     {
1054         LV_UNUSED(path);
1055         LV_UNUSED(data_format);
1056         LV_UNUSED(quality);
1057         LV_UNUSED(path_length);
1058         LV_UNUSED(path_data);
1059         LV_UNUSED(min_x);
1060         LV_UNUSED(min_y);
1061         LV_UNUSED(max_x);
1062         LV_UNUSED(max_y);
1063         return VG_LITE_NOT_SUPPORT;
1064     }
1065 
vg_lite_clear_path(vg_lite_path_t * path)1066     vg_lite_error_t vg_lite_clear_path(vg_lite_path_t * path)
1067     {
1068         LV_ASSERT_NULL(path);
1069 
1070         if(path->stroke) {
1071             lv_free(path->stroke);
1072             path->stroke = NULL;
1073         }
1074 
1075         return VG_LITE_SUCCESS;
1076     }
1077 
vg_lite_get_path_length(vg_lite_uint8_t * opcode,vg_lite_uint32_t count,vg_lite_format_t format)1078     vg_lite_uint32_t vg_lite_get_path_length(vg_lite_uint8_t * opcode,
1079                                              vg_lite_uint32_t count,
1080                                              vg_lite_format_t format)
1081     {
1082         LV_UNUSED(opcode);
1083         LV_UNUSED(count);
1084         LV_UNUSED(format);
1085         return 0;
1086     }
1087 
vg_lite_append_path(vg_lite_path_t * path,uint8_t * cmd,void * data,vg_lite_uint32_t seg_count)1088     vg_lite_error_t vg_lite_append_path(vg_lite_path_t * path,
1089                                         uint8_t * cmd,
1090                                         void * data,
1091                                         vg_lite_uint32_t seg_count)
1092     {
1093         LV_UNUSED(path);
1094         LV_UNUSED(cmd);
1095         LV_UNUSED(data);
1096         LV_UNUSED(seg_count);
1097         return VG_LITE_NOT_SUPPORT;
1098     }
1099 
vg_lite_upload_path(vg_lite_path_t * path)1100     vg_lite_error_t vg_lite_upload_path(vg_lite_path_t * path)
1101     {
1102         LV_UNUSED(path);
1103         return VG_LITE_NOT_SUPPORT;
1104     }
1105 
vg_lite_set_CLUT(vg_lite_uint32_t count,vg_lite_uint32_t * colors)1106     vg_lite_error_t vg_lite_set_CLUT(vg_lite_uint32_t count,
1107                                      vg_lite_uint32_t * colors)
1108     {
1109         if(!vg_lite_query_feature(gcFEATURE_BIT_VG_IM_INDEX_FORMAT)) {
1110             return VG_LITE_NOT_SUPPORT;
1111         }
1112         LV_ASSERT(colors);
1113 
1114         auto ctx = vg_lite_ctx::get_instance();
1115         ctx->set_CLUT(count, colors);
1116         return VG_LITE_SUCCESS;
1117     }
1118 
vg_lite_draw_pattern(vg_lite_buffer_t * target,vg_lite_path_t * path,vg_lite_fill_t fill_rule,vg_lite_matrix_t * path_matrix,vg_lite_buffer_t * pattern_image,vg_lite_matrix_t * pattern_matrix,vg_lite_blend_t blend,vg_lite_pattern_mode_t pattern_mode,vg_lite_color_t pattern_color,vg_lite_color_t color,vg_lite_filter_t filter)1119     vg_lite_error_t vg_lite_draw_pattern(vg_lite_buffer_t * target,
1120                                          vg_lite_path_t * path,
1121                                          vg_lite_fill_t fill_rule,
1122                                          vg_lite_matrix_t * path_matrix,
1123                                          vg_lite_buffer_t * pattern_image,
1124                                          vg_lite_matrix_t * pattern_matrix,
1125                                          vg_lite_blend_t blend,
1126                                          vg_lite_pattern_mode_t pattern_mode,
1127                                          vg_lite_color_t pattern_color,
1128                                          vg_lite_color_t color,
1129                                          vg_lite_filter_t filter)
1130     {
1131         LV_UNUSED(pattern_mode);
1132         LV_UNUSED(pattern_color);
1133         LV_UNUSED(filter);
1134 
1135         auto ctx = vg_lite_ctx::get_instance();
1136         TVG_CHECK_RETURN_VG_ERROR(canvas_set_target(ctx, target));
1137 
1138         auto shape = Shape::gen();
1139         TVG_CHECK_RETURN_VG_ERROR(shape_append_path(shape, path, path_matrix));
1140         TVG_CHECK_RETURN_VG_ERROR(shape->fill(fill_rule_conv(fill_rule)));
1141         TVG_CHECK_RETURN_VG_ERROR(shape->transform(matrix_conv(path_matrix)));
1142 
1143         auto picture = tvg::Picture::gen();
1144         TVG_CHECK_RETURN_VG_ERROR(picture_load(ctx, picture, pattern_image, color));
1145         TVG_CHECK_RETURN_VG_ERROR(picture->transform(matrix_conv(pattern_matrix)));
1146         TVG_CHECK_RETURN_VG_ERROR(picture->blend(blend_method_conv(blend)));
1147         TVG_CHECK_RETURN_VG_ERROR(picture->composite(std::move(shape), CompositeMethod::ClipPath));
1148         TVG_CHECK_RETURN_VG_ERROR(ctx->canvas->push(std::move(picture)));
1149 
1150         return VG_LITE_SUCCESS;
1151     }
1152 
vg_lite_init_grad(vg_lite_linear_gradient_t * grad)1153     vg_lite_error_t vg_lite_init_grad(vg_lite_linear_gradient_t * grad)
1154     {
1155         vg_lite_error_t error = VG_LITE_SUCCESS;
1156 
1157         /* Set the member values according to driver defaults. */
1158         grad->image.width = VLC_GRADIENT_BUFFER_WIDTH;
1159         grad->image.height = 1;
1160         grad->image.stride = 0;
1161         grad->image.format = VG_LITE_BGRA8888;
1162 
1163         /* Allocate the image for gradient. */
1164         error = vg_lite_allocate(&grad->image);
1165 
1166         grad->count = 0;
1167 
1168         return error;
1169     }
1170 
vg_lite_set_linear_grad(vg_lite_ext_linear_gradient_t * grad,vg_lite_uint32_t count,vg_lite_color_ramp_t * color_ramp,vg_lite_linear_gradient_parameter_t linear_gradient,vg_lite_gradient_spreadmode_t spread_mode,vg_lite_uint8_t pre_multiplied)1171     vg_lite_error_t vg_lite_set_linear_grad(vg_lite_ext_linear_gradient_t * grad,
1172                                             vg_lite_uint32_t count,
1173                                             vg_lite_color_ramp_t * color_ramp,
1174                                             vg_lite_linear_gradient_parameter_t linear_gradient,
1175                                             vg_lite_gradient_spreadmode_t spread_mode,
1176                                             vg_lite_uint8_t pre_multiplied)
1177     {
1178         static vg_lite_color_ramp_t default_ramp[] = {
1179             {
1180                 0.0f,
1181                 0.0f, 0.0f, 0.0f, 1.0f
1182             },
1183             {
1184                 1.0f,
1185                 1.0f, 1.0f, 1.0f, 1.0f
1186             }
1187         };
1188 
1189         vg_lite_uint32_t i, trg_count;
1190         vg_lite_float_t prev_stop;
1191         vg_lite_color_ramp_t * src_ramp;
1192         vg_lite_color_ramp_t * src_ramp_last;
1193         vg_lite_color_ramp_t * trg_ramp;
1194 
1195         /* Reset the count. */
1196         trg_count = 0;
1197 
1198         if((linear_gradient.X0 == linear_gradient.X1) && (linear_gradient.Y0 == linear_gradient.Y1))
1199             return VG_LITE_INVALID_ARGUMENT;
1200 
1201         grad->linear_grad = linear_gradient;
1202         grad->pre_multiplied = pre_multiplied;
1203         grad->spread_mode = spread_mode;
1204 
1205         if(!count || count > VLC_MAX_COLOR_RAMP_STOPS || color_ramp == NULL)
1206             goto Empty_sequence_handler;
1207 
1208         for(i = 0; i < count; i++)
1209             grad->color_ramp[i] = color_ramp[i];
1210         grad->ramp_length = count;
1211 
1212         /* Determine the last source ramp. */
1213         src_ramp_last
1214             = grad->color_ramp
1215               + grad->ramp_length;
1216 
1217         /* Set the initial previous stop. */
1218         prev_stop = -1;
1219 
1220         /* Reset the count. */
1221         trg_count = 0;
1222 
1223         /* Walk through the source ramp. */
1224         for(
1225             src_ramp = grad->color_ramp, trg_ramp = grad->converted_ramp;
1226             (src_ramp < src_ramp_last) && (trg_count < VLC_MAX_COLOR_RAMP_STOPS + 2);
1227             src_ramp += 1) {
1228             /* Must be in increasing order. */
1229             if(src_ramp->stop < prev_stop) {
1230                 /* Ignore the entire sequence. */
1231                 trg_count = 0;
1232                 break;
1233             }
1234 
1235             /* Update the previous stop value. */
1236             prev_stop = src_ramp->stop;
1237 
1238             /* Must be within [0..1] range. */
1239             if((src_ramp->stop < 0.0f) || (src_ramp->stop > 1.0f)) {
1240                 /* Ignore. */
1241                 continue;
1242             }
1243 
1244             /* Clamp color. */
1245             ClampColor(COLOR_FROM_RAMP(src_ramp), COLOR_FROM_RAMP(trg_ramp), 0);
1246 
1247             /* First stop greater than zero? */
1248             if((trg_count == 0) && (src_ramp->stop > 0.0f)) {
1249                 /* Force the first stop to 0.0f. */
1250                 trg_ramp->stop = 0.0f;
1251 
1252                 /* Replicate the entry. */
1253                 trg_ramp[1] = *trg_ramp;
1254                 trg_ramp[1].stop = src_ramp->stop;
1255 
1256                 /* Advance. */
1257                 trg_ramp += 2;
1258                 trg_count += 2;
1259             }
1260             else {
1261                 /* Set the stop value. */
1262                 trg_ramp->stop = src_ramp->stop;
1263 
1264                 /* Advance. */
1265                 trg_ramp += 1;
1266                 trg_count += 1;
1267             }
1268         }
1269 
1270         /* Empty sequence? */
1271         if(trg_count == 0) {
1272             memcpy(grad->converted_ramp, default_ramp, sizeof(default_ramp));
1273             grad->converted_length = sizeof(default_ramp) / 5;
1274         }
1275         else {
1276             /* The last stop must be at 1.0. */
1277             if(trg_ramp[-1].stop != 1.0f) {
1278                 /* Replicate the last entry. */
1279                 *trg_ramp = trg_ramp[-1];
1280 
1281                 /* Force the last stop to 1.0f. */
1282                 trg_ramp->stop = 1.0f;
1283 
1284                 /* Update the final entry count. */
1285                 trg_count += 1;
1286             }
1287 
1288             /* Set new length. */
1289             grad->converted_length = trg_count;
1290         }
1291         return VG_LITE_SUCCESS;
1292 
1293 Empty_sequence_handler:
1294         memcpy(grad->converted_ramp, default_ramp, sizeof(default_ramp));
1295         grad->converted_length = sizeof(default_ramp) / 5;
1296 
1297         return VG_LITE_SUCCESS;
1298     }
1299 
vg_lite_update_linear_grad(vg_lite_ext_linear_gradient_t * grad)1300     vg_lite_error_t vg_lite_update_linear_grad(vg_lite_ext_linear_gradient_t * grad)
1301     {
1302         vg_lite_uint32_t ramp_length;
1303         vg_lite_color_ramp_t * color_ramp;
1304         vg_lite_uint32_t common, stop;
1305         vg_lite_uint32_t i, width;
1306         uint8_t * bits;
1307         vg_lite_float_t x0, y0, x1, y1, length;
1308         vg_lite_error_t error = VG_LITE_SUCCESS;
1309 
1310         /* Get shortcuts to the color ramp. */
1311         ramp_length = grad->converted_length;
1312         color_ramp = grad->converted_ramp;
1313 
1314         x0 = grad->linear_grad.X0;
1315         y0 = grad->linear_grad.Y0;
1316         x1 = grad->linear_grad.X1;
1317         y1 = grad->linear_grad.Y1;
1318         length = (vg_lite_float_t)sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
1319 
1320         if(length <= 0)
1321             return VG_LITE_INVALID_ARGUMENT;
1322         /* Find the common denominator of the color ramp stops. */
1323         if(length < 1) {
1324             common = 1;
1325         }
1326         else {
1327             common = (vg_lite_uint32_t)length;
1328         }
1329 
1330         for(i = 0; i < ramp_length; ++i) {
1331             if(color_ramp[i].stop != 0.0f) {
1332                 vg_lite_float_t mul = common * color_ramp[i].stop;
1333                 vg_lite_float_t frac = mul - (vg_lite_float_t)floor(mul);
1334                 if(frac > 0.00013f) { /* Suppose error for zero is 0.00013 */
1335                     common = MAX(common, (vg_lite_uint32_t)(1.0f / frac + 0.5f));
1336                 }
1337             }
1338         }
1339 
1340         /* Compute the width of the required color array. */
1341         width = common + 1;
1342 
1343         /* Allocate the color ramp surface. */
1344         memset(&grad->image, 0, sizeof(grad->image));
1345         grad->image.width = width;
1346         grad->image.height = 1;
1347         grad->image.stride = 0;
1348         grad->image.image_mode = VG_LITE_NONE_IMAGE_MODE;
1349         grad->image.format = VG_LITE_ABGR8888;
1350 
1351         /* Allocate the image for gradient. */
1352         VG_LITE_RETURN_ERROR(vg_lite_allocate(&grad->image));
1353         memset(grad->image.memory, 0, grad->image.stride * grad->image.height);
1354         width = common + 1;
1355         /* Set pointer to color array. */
1356         bits = (uint8_t *)grad->image.memory;
1357 
1358         /* Start filling the color array. */
1359         stop = 0;
1360         for(i = 0; i < width; ++i) {
1361             vg_lite_float_t gradient;
1362             vg_lite_float_t color[4];
1363             vg_lite_float_t color1[4];
1364             vg_lite_float_t color2[4];
1365             vg_lite_float_t weight;
1366 
1367             if(i == 241)
1368                 i = 241;
1369             /* Compute gradient for current color array entry. */
1370             gradient = (vg_lite_float_t)i / (vg_lite_float_t)(width - 1);
1371 
1372             /* Find the entry in the color ramp that matches or exceeds this
1373             ** gradient. */
1374             while(gradient > color_ramp[stop].stop) {
1375                 ++stop;
1376             }
1377 
1378             if(gradient == color_ramp[stop].stop) {
1379                 /* Perfect match weight 1.0. */
1380                 weight = 1.0f;
1381 
1382                 /* Use color ramp color. */
1383                 color1[3] = color_ramp[stop].alpha;
1384                 color1[2] = color_ramp[stop].blue;
1385                 color1[1] = color_ramp[stop].green;
1386                 color1[0] = color_ramp[stop].red;
1387 
1388                 color2[3] = color2[2] = color2[1] = color2[0] = 0.0f;
1389             }
1390             else {
1391                 if(stop == 0) {
1392                     return VG_LITE_INVALID_ARGUMENT;
1393                 }
1394                 /* Compute weight. */
1395                 weight = (color_ramp[stop].stop - gradient)
1396                          / (color_ramp[stop].stop - color_ramp[stop - 1].stop);
1397 
1398                 /* Grab color ramp color of previous stop. */
1399                 color1[3] = color_ramp[stop - 1].alpha;
1400                 color1[2] = color_ramp[stop - 1].blue;
1401                 color1[1] = color_ramp[stop - 1].green;
1402                 color1[0] = color_ramp[stop - 1].red;
1403 
1404                 /* Grab color ramp color of current stop. */
1405                 color2[3] = color_ramp[stop].alpha;
1406                 color2[2] = color_ramp[stop].blue;
1407                 color2[1] = color_ramp[stop].green;
1408                 color2[0] = color_ramp[stop].red;
1409             }
1410 
1411             if(grad->pre_multiplied) {
1412                 /* Pre-multiply the first color. */
1413                 color1[2] *= color1[3];
1414                 color1[1] *= color1[3];
1415                 color1[0] *= color1[3];
1416 
1417                 /* Pre-multiply the second color. */
1418                 color2[2] *= color2[3];
1419                 color2[1] *= color2[3];
1420                 color2[0] *= color2[3];
1421             }
1422 
1423             /* Filter the colors per channel. */
1424             color[3] = LERP(color1[3], color2[3], weight);
1425             color[2] = LERP(color1[2], color2[2], weight);
1426             color[1] = LERP(color1[1], color2[1], weight);
1427             color[0] = LERP(color1[0], color2[0], weight);
1428 
1429             /* Pack the final color. */
1430             *bits++ = PackColorComponent(color[3]);
1431             *bits++ = PackColorComponent(color[2]);
1432             *bits++ = PackColorComponent(color[1]);
1433             *bits++ = PackColorComponent(color[0]);
1434         }
1435 
1436         return VG_LITE_SUCCESS;
1437     }
1438 
vg_lite_draw_linear_grad(vg_lite_buffer_t * target,vg_lite_path_t * path,vg_lite_fill_t fill_rule,vg_lite_matrix_t * path_matrix,vg_lite_ext_linear_gradient_t * grad,vg_lite_color_t paint_color,vg_lite_blend_t blend,vg_lite_filter_t filter)1439     vg_lite_error_t vg_lite_draw_linear_grad(vg_lite_buffer_t * target,
1440                                              vg_lite_path_t * path,
1441                                              vg_lite_fill_t fill_rule,
1442                                              vg_lite_matrix_t * path_matrix,
1443                                              vg_lite_ext_linear_gradient_t * grad,
1444                                              vg_lite_color_t paint_color,
1445                                              vg_lite_blend_t blend,
1446                                              vg_lite_filter_t filter)
1447     {
1448         LV_UNUSED(paint_color);
1449         LV_UNUSED(filter);
1450 
1451         auto ctx = vg_lite_ctx::get_instance();
1452         TVG_CHECK_RETURN_VG_ERROR(canvas_set_target(ctx, target));
1453 
1454         auto shape = Shape::gen();
1455         TVG_CHECK_RETURN_VG_ERROR(shape_append_path(shape, path, path_matrix));
1456         TVG_CHECK_RETURN_VG_ERROR(shape->transform(matrix_conv(path_matrix)));
1457         TVG_CHECK_RETURN_VG_ERROR(shape->fill(fill_rule_conv(fill_rule)););
1458         TVG_CHECK_RETURN_VG_ERROR(shape->blend(blend_method_conv(blend)));
1459 
1460         auto linearGrad = LinearGradient::gen();
1461         TVG_CHECK_RETURN_VG_ERROR(linearGrad->linear(grad->linear_grad.X0, grad->linear_grad.Y0, grad->linear_grad.X1,
1462                                                      grad->linear_grad.Y1));
1463         TVG_CHECK_RETURN_VG_ERROR(linearGrad->transform(matrix_conv(&grad->matrix)));
1464         TVG_CHECK_RETURN_VG_ERROR(linearGrad->spread(fill_spread_conv(grad->spread_mode)));
1465 
1466         tvg::Fill::ColorStop colorStops[VLC_MAX_COLOR_RAMP_STOPS];
1467         for(vg_lite_uint32_t i = 0; i < grad->ramp_length; i++) {
1468             colorStops[i].offset = grad->color_ramp[i].stop;
1469             colorStops[i].r = grad->color_ramp[i].red * 255.0f;
1470             colorStops[i].g = grad->color_ramp[i].green * 255.0f;
1471             colorStops[i].b = grad->color_ramp[i].blue * 255.0f;
1472             colorStops[i].a = grad->color_ramp[i].alpha * 255.0f;
1473         }
1474         TVG_CHECK_RETURN_VG_ERROR(linearGrad->colorStops(colorStops, grad->ramp_length));
1475 
1476         TVG_CHECK_RETURN_VG_ERROR(shape->fill(std::move(linearGrad)));
1477         TVG_CHECK_RETURN_VG_ERROR(ctx->canvas->push(std::move(shape)));
1478 
1479         return VG_LITE_SUCCESS;
1480     }
1481 
vg_lite_set_radial_grad(vg_lite_radial_gradient_t * grad,vg_lite_uint32_t count,vg_lite_color_ramp_t * color_ramp,vg_lite_radial_gradient_parameter_t radial_grad,vg_lite_gradient_spreadmode_t spread_mode,vg_lite_uint8_t pre_multiplied)1482     vg_lite_error_t vg_lite_set_radial_grad(vg_lite_radial_gradient_t * grad,
1483                                             vg_lite_uint32_t count,
1484                                             vg_lite_color_ramp_t * color_ramp,
1485                                             vg_lite_radial_gradient_parameter_t radial_grad,
1486                                             vg_lite_gradient_spreadmode_t spread_mode,
1487                                             vg_lite_uint8_t pre_multiplied)
1488     {
1489         static vg_lite_color_ramp_t defaultRamp[] = {
1490             {
1491                 0.0f,
1492                 0.0f, 0.0f, 0.0f, 1.0f
1493             },
1494             {
1495                 1.0f,
1496                 1.0f, 1.0f, 1.0f, 1.0f
1497             }
1498         };
1499 
1500         vg_lite_uint32_t i, trgCount;
1501         vg_lite_float_t prevStop;
1502         vg_lite_color_ramp_t * srcRamp;
1503         vg_lite_color_ramp_t * srcRampLast;
1504         vg_lite_color_ramp_t * trgRamp;
1505 
1506         /* Reset the count. */
1507         trgCount = 0;
1508 
1509         if(radial_grad.r <= 0)
1510             return VG_LITE_INVALID_ARGUMENT;
1511 
1512         grad->radial_grad = radial_grad;
1513         grad->pre_multiplied = pre_multiplied;
1514         grad->spread_mode = spread_mode;
1515 
1516         if(!count || count > VLC_MAX_COLOR_RAMP_STOPS || color_ramp == NULL)
1517             goto Empty_sequence_handler;
1518 
1519         for(i = 0; i < count; i++)
1520             grad->color_ramp[i] = color_ramp[i];
1521         grad->ramp_length = count;
1522 
1523         /* Determine the last source ramp. */
1524         srcRampLast
1525             = grad->color_ramp
1526               + grad->ramp_length;
1527 
1528         /* Set the initial previous stop. */
1529         prevStop = -1;
1530 
1531         /* Reset the count. */
1532         trgCount = 0;
1533 
1534         /* Walk through the source ramp. */
1535         for(
1536             srcRamp = grad->color_ramp, trgRamp = grad->converted_ramp;
1537             (srcRamp < srcRampLast) && (trgCount < VLC_MAX_COLOR_RAMP_STOPS + 2);
1538             srcRamp += 1) {
1539             /* Must be in increasing order. */
1540             if(srcRamp->stop < prevStop) {
1541                 /* Ignore the entire sequence. */
1542                 trgCount = 0;
1543                 break;
1544             }
1545 
1546             /* Update the previous stop value. */
1547             prevStop = srcRamp->stop;
1548 
1549             /* Must be within [0..1] range. */
1550             if((srcRamp->stop < 0.0f) || (srcRamp->stop > 1.0f)) {
1551                 /* Ignore. */
1552                 continue;
1553             }
1554 
1555             /* Clamp color. */
1556             ClampColor(COLOR_FROM_RAMP(srcRamp), COLOR_FROM_RAMP(trgRamp), 0);
1557 
1558             /* First stop greater than zero? */
1559             if((trgCount == 0) && (srcRamp->stop > 0.0f)) {
1560                 /* Force the first stop to 0.0f. */
1561                 trgRamp->stop = 0.0f;
1562 
1563                 /* Replicate the entry. */
1564                 trgRamp[1] = *trgRamp;
1565                 trgRamp[1].stop = srcRamp->stop;
1566 
1567                 /* Advance. */
1568                 trgRamp += 2;
1569                 trgCount += 2;
1570             }
1571             else {
1572                 /* Set the stop value. */
1573                 trgRamp->stop = srcRamp->stop;
1574 
1575                 /* Advance. */
1576                 trgRamp += 1;
1577                 trgCount += 1;
1578             }
1579         }
1580 
1581         /* Empty sequence? */
1582         if(trgCount == 0) {
1583             memcpy(grad->converted_ramp, defaultRamp, sizeof(defaultRamp));
1584             grad->converted_length = sizeof(defaultRamp) / 5;
1585         }
1586         else {
1587             /* The last stop must be at 1.0. */
1588             if(trgRamp[-1].stop != 1.0f) {
1589                 /* Replicate the last entry. */
1590                 *trgRamp = trgRamp[-1];
1591 
1592                 /* Force the last stop to 1.0f. */
1593                 trgRamp->stop = 1.0f;
1594 
1595                 /* Update the final entry count. */
1596                 trgCount += 1;
1597             }
1598 
1599             /* Set new length. */
1600             grad->converted_length = trgCount;
1601         }
1602         return VG_LITE_SUCCESS;
1603 
1604 Empty_sequence_handler:
1605         memcpy(grad->converted_ramp, defaultRamp, sizeof(defaultRamp));
1606         grad->converted_length = sizeof(defaultRamp) / 5;
1607 
1608         return VG_LITE_SUCCESS;
1609     }
1610 
vg_lite_update_radial_grad(vg_lite_radial_gradient_t * grad)1611     vg_lite_error_t vg_lite_update_radial_grad(vg_lite_radial_gradient_t * grad)
1612     {
1613         vg_lite_uint32_t ramp_length;
1614         vg_lite_color_ramp_t * colorRamp;
1615         vg_lite_uint32_t common, stop;
1616         vg_lite_uint32_t i, width;
1617         uint8_t * bits;
1618         vg_lite_error_t error = VG_LITE_SUCCESS;
1619         vg_lite_uint32_t align, mul, div;
1620 
1621         /* Get shortcuts to the color ramp. */
1622         ramp_length = grad->converted_length;
1623         colorRamp = grad->converted_ramp;
1624 
1625         if(grad->radial_grad.r <= 0)
1626             return VG_LITE_INVALID_ARGUMENT;
1627 
1628         /* Find the common denominator of the color ramp stops. */
1629         if(grad->radial_grad.r < 1) {
1630             common = 1;
1631         }
1632         else {
1633             common = (vg_lite_uint32_t)grad->radial_grad.r;
1634         }
1635 
1636         for(i = 0; i < ramp_length; ++i) {
1637             if(colorRamp[i].stop != 0.0f) {
1638                 vg_lite_float_t m = common * colorRamp[i].stop;
1639                 vg_lite_float_t frac = m - (vg_lite_float_t)floor(m);
1640                 if(frac > 0.00013f) { /* Suppose error for zero is 0.00013 */
1641                     common = MAX(common, (vg_lite_uint32_t)(1.0f / frac + 0.5f));
1642                 }
1643             }
1644         }
1645 
1646         /* Compute the width of the required color array. */
1647         width = common + 1;
1648         width = (width + 15) & (~0xf);
1649 
1650         /* Allocate the color ramp surface. */
1651         memset(&grad->image, 0, sizeof(grad->image));
1652         grad->image.width = width;
1653         grad->image.height = 1;
1654         grad->image.stride = 0;
1655         grad->image.image_mode = VG_LITE_NONE_IMAGE_MODE;
1656         grad->image.format = VG_LITE_ABGR8888;
1657 
1658         /* Allocate the image for gradient. */
1659         VG_LITE_RETURN_ERROR(vg_lite_allocate(&grad->image));
1660 
1661         get_format_bytes(VG_LITE_ABGR8888, &mul, &div, &align);
1662         width = grad->image.stride * div / mul;
1663 
1664         /* Set pointer to color array. */
1665         bits = (uint8_t *)grad->image.memory;
1666 
1667         /* Start filling the color array. */
1668         stop = 0;
1669         for(i = 0; i < width; ++i) {
1670             vg_lite_float_t gradient;
1671             vg_lite_float_t color[4];
1672             vg_lite_float_t color1[4];
1673             vg_lite_float_t color2[4];
1674             vg_lite_float_t weight;
1675 
1676             /* Compute gradient for current color array entry. */
1677             gradient = (vg_lite_float_t)i / (vg_lite_float_t)(width - 1);
1678 
1679             /* Find the entry in the color ramp that matches or exceeds this
1680             ** gradient. */
1681             while(gradient > colorRamp[stop].stop) {
1682                 ++stop;
1683             }
1684 
1685             if(gradient == colorRamp[stop].stop) {
1686                 /* Perfect match weight 1.0. */
1687                 weight = 1.0f;
1688 
1689                 /* Use color ramp color. */
1690                 color1[3] = colorRamp[stop].alpha;
1691                 color1[2] = colorRamp[stop].blue;
1692                 color1[1] = colorRamp[stop].green;
1693                 color1[0] = colorRamp[stop].red;
1694 
1695                 color2[3] = color2[2] = color2[1] = color2[0] = 0.0f;
1696             }
1697             else {
1698                 /* Compute weight. */
1699                 weight = (colorRamp[stop].stop - gradient)
1700                          / (colorRamp[stop].stop - colorRamp[stop - 1].stop);
1701 
1702                 /* Grab color ramp color of previous stop. */
1703                 color1[3] = colorRamp[stop - 1].alpha;
1704                 color1[2] = colorRamp[stop - 1].blue;
1705                 color1[1] = colorRamp[stop - 1].green;
1706                 color1[0] = colorRamp[stop - 1].red;
1707 
1708                 /* Grab color ramp color of current stop. */
1709                 color2[3] = colorRamp[stop].alpha;
1710                 color2[2] = colorRamp[stop].blue;
1711                 color2[1] = colorRamp[stop].green;
1712                 color2[0] = colorRamp[stop].red;
1713             }
1714 
1715             if(grad->pre_multiplied) {
1716                 /* Pre-multiply the first color. */
1717                 color1[2] *= color1[3];
1718                 color1[1] *= color1[3];
1719                 color1[0] *= color1[3];
1720 
1721                 /* Pre-multiply the second color. */
1722                 color2[2] *= color2[3];
1723                 color2[1] *= color2[3];
1724                 color2[0] *= color2[3];
1725             }
1726 
1727             /* Filter the colors per channel. */
1728             color[3] = LERP(color1[3], color2[3], weight);
1729             color[2] = LERP(color1[2], color2[2], weight);
1730             color[1] = LERP(color1[1], color2[1], weight);
1731             color[0] = LERP(color1[0], color2[0], weight);
1732 
1733             /* Pack the final color. */
1734             *bits++ = PackColorComponent(color[3]);
1735             *bits++ = PackColorComponent(color[2]);
1736             *bits++ = PackColorComponent(color[1]);
1737             *bits++ = PackColorComponent(color[0]);
1738         }
1739 
1740         return VG_LITE_SUCCESS;
1741     }
1742 
vg_lite_set_grad(vg_lite_linear_gradient_t * grad,vg_lite_uint32_t count,vg_lite_uint32_t * colors,vg_lite_uint32_t * stops)1743     vg_lite_error_t vg_lite_set_grad(vg_lite_linear_gradient_t * grad,
1744                                      vg_lite_uint32_t count,
1745                                      vg_lite_uint32_t * colors,
1746                                      vg_lite_uint32_t * stops)
1747     {
1748         vg_lite_uint32_t i;
1749 
1750         grad->count = 0; /* Opaque B&W gradient */
1751         if(!count || count > VLC_MAX_GRADIENT_STOPS || colors == NULL || stops == NULL)
1752             return VG_LITE_SUCCESS;
1753 
1754         /* Check stops validity */
1755         for(i = 0; i < count; i++)
1756             if(stops[i] < VLC_GRADIENT_BUFFER_WIDTH) {
1757                 if(!grad->count || stops[i] > grad->stops[grad->count - 1]) {
1758                     grad->stops[grad->count] = stops[i];
1759                     grad->colors[grad->count] = colors[i];
1760                     grad->count++;
1761                 }
1762                 else if(stops[i] == grad->stops[grad->count - 1]) {
1763                     /* Equal stops : use the color corresponding to the last stop
1764                     in the sequence */
1765                     grad->colors[grad->count - 1] = colors[i];
1766                 }
1767             }
1768 
1769         return VG_LITE_SUCCESS;
1770     }
1771 
vg_lite_update_grad(vg_lite_linear_gradient_t * grad)1772     vg_lite_error_t vg_lite_update_grad(vg_lite_linear_gradient_t * grad)
1773     {
1774         vg_lite_error_t error = VG_LITE_SUCCESS;
1775         int32_t r0, g0, b0, a0;
1776         int32_t r1, g1, b1, a1;
1777         int32_t lr, lg, lb, la;
1778         vg_lite_uint32_t i;
1779         int32_t j;
1780         int32_t ds, dr, dg, db, da;
1781         vg_lite_uint32_t * buffer = (vg_lite_uint32_t *)grad->image.memory;
1782 
1783         if(grad->count == 0) {
1784             /* If no valid stops have been specified (e.g., due to an empty input
1785              * array, out-of-range, or out-of-order stops), a stop at 0 with color
1786              * 0xFF000000 (opaque black) and a stop at 255 with color 0xFFFFFFFF
1787              * (opaque white) are implicitly defined. */
1788             grad->stops[0] = 0;
1789             grad->colors[0] = 0xFF000000; /* Opaque black */
1790             grad->stops[1] = 255;
1791             grad->colors[1] = 0xFFFFFFFF; /* Opaque white */
1792             grad->count = 2;
1793         }
1794         else if(grad->count && grad->stops[0] != 0) {
1795             /* If at least one valid stop has been specified, but none has been
1796              * defined with an offset of 0, an implicit stop is added with an
1797              * offset of 0 and the same color as the first user-defined stop. */
1798             for(i = 0; i < grad->stops[0]; i++)
1799                 buffer[i] = grad->colors[0];
1800         }
1801         a0 = A(grad->colors[0]);
1802         r0 = R(grad->colors[0]);
1803         g0 = G(grad->colors[0]);
1804         b0 = B(grad->colors[0]);
1805 
1806         /* Calculate the colors for each pixel of the image. */
1807         for(i = 0; i < grad->count - 1; i++) {
1808             buffer[grad->stops[i]] = grad->colors[i];
1809             ds = grad->stops[i + 1] - grad->stops[i];
1810             a1 = A(grad->colors[i + 1]);
1811             r1 = R(grad->colors[i + 1]);
1812             g1 = G(grad->colors[i + 1]);
1813             b1 = B(grad->colors[i + 1]);
1814 
1815             da = a1 - a0;
1816             dr = r1 - r0;
1817             dg = g1 - g0;
1818             db = b1 - b0;
1819 
1820             for(j = 1; j < ds; j++) {
1821                 la = a0 + da * j / ds;
1822                 lr = r0 + dr * j / ds;
1823                 lg = g0 + dg * j / ds;
1824                 lb = b0 + db * j / ds;
1825 
1826                 buffer[grad->stops[i] + j] = ARGB(la, lr, lg, lb);
1827             }
1828 
1829             a0 = a1;
1830             r0 = r1;
1831             g0 = g1;
1832             b0 = b1;
1833         }
1834 
1835         /* If at least one valid stop has been specified, but none has been defined
1836          * with an offset of 255, an implicit stop is added with an offset of 255
1837          * and the same color as the last user-defined stop. */
1838         for(i = grad->stops[grad->count - 1]; i < VLC_GRADIENT_BUFFER_WIDTH; i++)
1839             buffer[i] = grad->colors[grad->count - 1];
1840 
1841         return error;
1842     }
1843 
vg_lite_clear_linear_grad(vg_lite_ext_linear_gradient_t * grad)1844     vg_lite_error_t vg_lite_clear_linear_grad(vg_lite_ext_linear_gradient_t * grad)
1845     {
1846         vg_lite_error_t error = VG_LITE_SUCCESS;
1847 
1848         grad->count = 0;
1849         /* Release the image resource. */
1850         if(grad->image.handle != NULL) {
1851             error = vg_lite_free(&grad->image);
1852         }
1853 
1854         return error;
1855     }
1856 
vg_lite_clear_grad(vg_lite_linear_gradient_t * grad)1857     vg_lite_error_t vg_lite_clear_grad(vg_lite_linear_gradient_t * grad)
1858     {
1859         vg_lite_error_t error = VG_LITE_SUCCESS;
1860 
1861         grad->count = 0;
1862         /* Release the image resource. */
1863         if(grad->image.handle != NULL) {
1864             error = vg_lite_free(&grad->image);
1865         }
1866 
1867         return error;
1868     }
1869 
vg_lite_clear_radial_grad(vg_lite_radial_gradient_t * grad)1870     vg_lite_error_t vg_lite_clear_radial_grad(vg_lite_radial_gradient_t * grad)
1871     {
1872         vg_lite_error_t error = VG_LITE_SUCCESS;
1873 
1874         grad->count = 0;
1875         /* Release the image resource. */
1876         if(grad->image.handle != NULL) {
1877             error = vg_lite_free(&grad->image);
1878         }
1879 
1880         return error;
1881     }
1882 
vg_lite_get_linear_grad_matrix(vg_lite_ext_linear_gradient_t * grad)1883     vg_lite_matrix_t * vg_lite_get_linear_grad_matrix(vg_lite_ext_linear_gradient_t * grad)
1884     {
1885         return &grad->matrix;
1886     }
1887 
vg_lite_get_grad_matrix(vg_lite_linear_gradient_t * grad)1888     vg_lite_matrix_t * vg_lite_get_grad_matrix(vg_lite_linear_gradient_t * grad)
1889     {
1890         return &grad->matrix;
1891     }
1892 
vg_lite_get_radial_grad_matrix(vg_lite_radial_gradient_t * grad)1893     vg_lite_matrix_t * vg_lite_get_radial_grad_matrix(vg_lite_radial_gradient_t * grad)
1894     {
1895         return &grad->matrix;
1896     }
1897 
vg_lite_draw_grad(vg_lite_buffer_t * target,vg_lite_path_t * path,vg_lite_fill_t fill_rule,vg_lite_matrix_t * matrix,vg_lite_linear_gradient_t * grad,vg_lite_blend_t blend)1898     vg_lite_error_t vg_lite_draw_grad(vg_lite_buffer_t * target,
1899                                       vg_lite_path_t * path,
1900                                       vg_lite_fill_t fill_rule,
1901                                       vg_lite_matrix_t * matrix,
1902                                       vg_lite_linear_gradient_t * grad,
1903                                       vg_lite_blend_t blend)
1904     {
1905         auto ctx = vg_lite_ctx::get_instance();
1906         TVG_CHECK_RETURN_VG_ERROR(canvas_set_target(ctx, target));
1907 
1908         auto shape = Shape::gen();
1909         TVG_CHECK_RETURN_VG_ERROR(shape_append_path(shape, path, matrix));
1910         TVG_CHECK_RETURN_VG_ERROR(shape->transform(matrix_conv(matrix)));
1911         TVG_CHECK_RETURN_VG_ERROR(shape->fill(fill_rule_conv(fill_rule)););
1912         TVG_CHECK_RETURN_VG_ERROR(shape->blend(blend_method_conv(blend)));
1913 
1914         vg_lite_matrix_t grad_matrix;
1915         vg_lite_identity(&grad_matrix);
1916         vg_lite_matrix_inverse(&grad_matrix, matrix);
1917         vg_lite_matrix_multiply(&grad_matrix, &grad->matrix);
1918 
1919         vg_lite_fpoint_t p1 = {0.0f, 0.0f};
1920         vg_lite_fpoint_t p2 = {1.0f, 0};
1921 
1922         vg_lite_fpoint_t p1_trans = p1;
1923         vg_lite_fpoint_t p2_trans = p2;
1924 
1925         p1_trans = matrix_transform_point(&grad_matrix, &p1);
1926         p2_trans = matrix_transform_point(&grad_matrix, &p2);
1927         float dx = (p2_trans.x - p1_trans.x);
1928         float dy = (p2_trans.y - p1_trans.y);
1929         float scale = sqrtf(dx * dx + dy * dy);
1930         float angle = (float)(atan2f(dy, dx));
1931         float dlen = 256 * scale;
1932         float x_min = grad_matrix.m[0][2];
1933         float y_min = grad_matrix.m[1][2];
1934         float x_max = x_min + dlen * cosf(angle);
1935         float y_max = y_min + dlen * sinf(angle);
1936         LV_LOG_TRACE("linear gradient {%.2f, %.2f} ~ {%.2f, %.2f}", x_min, y_min, x_max, y_max);
1937         auto linearGrad = LinearGradient::gen();
1938         TVG_CHECK_RETURN_VG_ERROR(linearGrad->linear(x_min, y_min, x_max, y_max));
1939         TVG_CHECK_RETURN_VG_ERROR(linearGrad->spread(FillSpread::Pad));
1940 
1941         tvg::Fill::ColorStop colorStops[VLC_MAX_GRADIENT_STOPS];
1942         for(vg_lite_uint32_t i = 0; i < grad->count; i++) {
1943             colorStops[i].offset = grad->stops[i] / 255.0f;
1944             colorStops[i].r = R(grad->colors[i]);
1945             colorStops[i].g = G(grad->colors[i]);
1946             colorStops[i].b = B(grad->colors[i]);
1947             colorStops[i].a = A(grad->colors[i]);
1948         }
1949         TVG_CHECK_RETURN_VG_ERROR(linearGrad->colorStops(colorStops, grad->count));
1950 
1951         TVG_CHECK_RETURN_VG_ERROR(shape->fill(std::move(linearGrad)));
1952         TVG_CHECK_RETURN_VG_ERROR(ctx->canvas->push(std::move(shape)));
1953 
1954         return VG_LITE_SUCCESS;
1955     }
1956 
vg_lite_draw_radial_grad(vg_lite_buffer_t * target,vg_lite_path_t * path,vg_lite_fill_t fill_rule,vg_lite_matrix_t * path_matrix,vg_lite_radial_gradient_t * grad,vg_lite_color_t paint_color,vg_lite_blend_t blend,vg_lite_filter_t filter)1957     vg_lite_error_t vg_lite_draw_radial_grad(vg_lite_buffer_t * target,
1958                                              vg_lite_path_t * path,
1959                                              vg_lite_fill_t fill_rule,
1960                                              vg_lite_matrix_t * path_matrix,
1961                                              vg_lite_radial_gradient_t * grad,
1962                                              vg_lite_color_t paint_color,
1963                                              vg_lite_blend_t blend,
1964                                              vg_lite_filter_t filter)
1965     {
1966         LV_UNUSED(paint_color);
1967         LV_UNUSED(filter);
1968 
1969         auto ctx = vg_lite_ctx::get_instance();
1970         TVG_CHECK_RETURN_VG_ERROR(canvas_set_target(ctx, target));
1971 
1972         auto shape = Shape::gen();
1973         TVG_CHECK_RETURN_VG_ERROR(shape_append_path(shape, path, path_matrix));
1974         TVG_CHECK_RETURN_VG_ERROR(shape->transform(matrix_conv(path_matrix)));
1975         TVG_CHECK_RETURN_VG_ERROR(shape->fill(fill_rule_conv(fill_rule)););
1976         TVG_CHECK_RETURN_VG_ERROR(shape->blend(blend_method_conv(blend)));
1977 
1978         auto radialGrad = RadialGradient::gen();
1979         TVG_CHECK_RETURN_VG_ERROR(radialGrad->transform(matrix_conv(&grad->matrix)));
1980         TVG_CHECK_RETURN_VG_ERROR(radialGrad->radial(grad->radial_grad.cx, grad->radial_grad.cy, grad->radial_grad.r));
1981         TVG_CHECK_RETURN_VG_ERROR(radialGrad->spread(fill_spread_conv(grad->spread_mode)));
1982 
1983         tvg::Fill::ColorStop colorStops[VLC_MAX_COLOR_RAMP_STOPS];
1984         for(vg_lite_uint32_t i = 0; i < grad->ramp_length; i++) {
1985             colorStops[i].offset = grad->color_ramp[i].stop;
1986             colorStops[i].r = grad->color_ramp[i].red * 255.0f;
1987             colorStops[i].g = grad->color_ramp[i].green * 255.0f;
1988             colorStops[i].b = grad->color_ramp[i].blue * 255.0f;
1989             colorStops[i].a = grad->color_ramp[i].alpha * 255.0f;
1990         }
1991         TVG_CHECK_RETURN_VG_ERROR(radialGrad->colorStops(colorStops, grad->ramp_length));
1992 
1993         TVG_CHECK_RETURN_VG_ERROR(shape->fill(std::move(radialGrad)));
1994         TVG_CHECK_RETURN_VG_ERROR(ctx->canvas->push(std::move(shape)));
1995 
1996         return VG_LITE_SUCCESS;
1997     }
1998 
vg_lite_set_command_buffer_size(vg_lite_uint32_t size)1999     vg_lite_error_t vg_lite_set_command_buffer_size(vg_lite_uint32_t size)
2000     {
2001         LV_UNUSED(size);
2002         return VG_LITE_NOT_SUPPORT;
2003     }
2004 
vg_lite_set_scissor(vg_lite_int32_t x,vg_lite_int32_t y,vg_lite_int32_t right,vg_lite_int32_t bottom)2005     vg_lite_error_t vg_lite_set_scissor(vg_lite_int32_t x, vg_lite_int32_t y, vg_lite_int32_t right, vg_lite_int32_t bottom)
2006     {
2007         auto ctx = vg_lite_ctx::get_instance();
2008         vg_lite_int32_t width = right - x;
2009         vg_lite_int32_t height = bottom - y;
2010 
2011         if(width <= 0 || height <= 0) {
2012             return VG_LITE_INVALID_ARGUMENT;
2013         }
2014 
2015         if(ctx->scissor_rect.x == x && ctx->scissor_rect.y == y &&
2016            ctx->scissor_rect.width == width && ctx->scissor_rect.height == height) {
2017             return VG_LITE_SUCCESS;
2018         }
2019 
2020         /*Finish the previous rendering before setting the new scissor*/
2021         vg_lite_error_t error;
2022         VG_LITE_RETURN_ERROR(vg_lite_finish());
2023 
2024         ctx->scissor_rect.x = x;
2025         ctx->scissor_rect.y = y;
2026         ctx->scissor_rect.width = width;
2027         ctx->scissor_rect.height = height;
2028         ctx->scissor_is_set = true;
2029         return VG_LITE_SUCCESS;
2030     }
2031 
vg_lite_enable_scissor(void)2032     vg_lite_error_t vg_lite_enable_scissor(void)
2033     {
2034         return VG_LITE_SUCCESS;
2035     }
2036 
vg_lite_disable_scissor(void)2037     vg_lite_error_t vg_lite_disable_scissor(void)
2038     {
2039         return VG_LITE_SUCCESS;
2040     }
2041 
vg_lite_get_mem_size(vg_lite_uint32_t * size)2042     vg_lite_error_t vg_lite_get_mem_size(vg_lite_uint32_t * size)
2043     {
2044         *size = 0;
2045         return VG_LITE_SUCCESS;
2046     }
2047 
vg_lite_source_global_alpha(vg_lite_global_alpha_t alpha_mode,uint8_t alpha_value)2048     vg_lite_error_t vg_lite_source_global_alpha(vg_lite_global_alpha_t alpha_mode, uint8_t alpha_value)
2049     {
2050         LV_UNUSED(alpha_mode);
2051         LV_UNUSED(alpha_value);
2052         return VG_LITE_NOT_SUPPORT;
2053     }
2054 
vg_lite_dest_global_alpha(vg_lite_global_alpha_t alpha_mode,uint8_t alpha_value)2055     vg_lite_error_t vg_lite_dest_global_alpha(vg_lite_global_alpha_t alpha_mode, uint8_t alpha_value)
2056     {
2057         LV_UNUSED(alpha_mode);
2058         LV_UNUSED(alpha_value);
2059         return VG_LITE_NOT_SUPPORT;
2060     }
2061 
vg_lite_set_color_key(vg_lite_color_key4_t colorkey)2062     vg_lite_error_t vg_lite_set_color_key(vg_lite_color_key4_t colorkey)
2063     {
2064         LV_UNUSED(colorkey);
2065         return VG_LITE_NOT_SUPPORT;
2066     }
2067 
vg_lite_set_flexa_stream_id(uint8_t stream_id)2068     vg_lite_error_t vg_lite_set_flexa_stream_id(uint8_t stream_id)
2069     {
2070         LV_UNUSED(stream_id);
2071         return VG_LITE_NOT_SUPPORT;
2072     }
2073 
vg_lite_set_flexa_current_background_buffer(uint8_t stream_id,vg_lite_buffer_t * buffer,vg_lite_uint32_t background_segment_count,vg_lite_uint32_t background_segment_size)2074     vg_lite_error_t vg_lite_set_flexa_current_background_buffer(uint8_t stream_id,
2075                                                                 vg_lite_buffer_t * buffer,
2076                                                                 vg_lite_uint32_t background_segment_count,
2077                                                                 vg_lite_uint32_t background_segment_size)
2078     {
2079         LV_UNUSED(stream_id);
2080         LV_UNUSED(buffer);
2081         LV_UNUSED(background_segment_count);
2082         LV_UNUSED(background_segment_size);
2083         return VG_LITE_NOT_SUPPORT;
2084     }
2085 
vg_lite_enable_flexa(void)2086     vg_lite_error_t vg_lite_enable_flexa(void)
2087     {
2088         return VG_LITE_NOT_SUPPORT;
2089     }
2090 
vg_lite_disable_flexa(void)2091     vg_lite_error_t vg_lite_disable_flexa(void)
2092     {
2093         return VG_LITE_NOT_SUPPORT;
2094     }
2095 
vg_lite_set_flexa_stop_frame(void)2096     vg_lite_error_t vg_lite_set_flexa_stop_frame(void)
2097     {
2098         return VG_LITE_NOT_SUPPORT;
2099     }
2100 
vg_lite_enable_dither(void)2101     vg_lite_error_t vg_lite_enable_dither(void)
2102     {
2103         return VG_LITE_NOT_SUPPORT;
2104     }
2105 
vg_lite_disable_dither(void)2106     vg_lite_error_t vg_lite_disable_dither(void)
2107     {
2108         return VG_LITE_NOT_SUPPORT;
2109     }
2110 
vg_lite_set_tess_buffer(vg_lite_uint32_t physical,vg_lite_uint32_t size)2111     vg_lite_error_t vg_lite_set_tess_buffer(vg_lite_uint32_t physical, vg_lite_uint32_t size)
2112     {
2113         LV_UNUSED(physical);
2114         LV_UNUSED(size);
2115         return VG_LITE_NOT_SUPPORT;
2116     }
2117 
vg_lite_set_command_buffer(vg_lite_uint32_t physical,vg_lite_uint32_t size)2118     vg_lite_error_t vg_lite_set_command_buffer(vg_lite_uint32_t physical, vg_lite_uint32_t size)
2119     {
2120         LV_UNUSED(physical);
2121         LV_UNUSED(size);
2122         return VG_LITE_NOT_SUPPORT;
2123     }
2124 
vg_lite_get_parameter(vg_lite_param_type_t type,vg_lite_int32_t count,vg_lite_float_t * params)2125     vg_lite_error_t vg_lite_get_parameter(vg_lite_param_type_t type,
2126                                           vg_lite_int32_t count,
2127                                           vg_lite_float_t * params)
2128     {
2129         switch(type) {
2130             case VG_LITE_GPU_IDLE_STATE:
2131                 if(count != 1 || params == NULL) {
2132                     return VG_LITE_INVALID_ARGUMENT;
2133                 }
2134 
2135                 *(vg_lite_uint32_t *)params = 1;
2136                 return VG_LITE_SUCCESS;
2137 
2138             default:
2139                 break;
2140         }
2141 
2142         return VG_LITE_NOT_SUPPORT;
2143     }
2144 
vg_lite_dump_command_buffer(void)2145     vg_lite_error_t vg_lite_dump_command_buffer(void)
2146     {
2147         LV_LOG_USER("command:");
2148         LV_LOG_USER("@[commit]");
2149         return VG_LITE_SUCCESS;
2150     }
2151 } /* extern "C" */
2152 
2153 /**********************
2154  *   STATIC FUNCTIONS
2155  **********************/
2156 
vg_lite_error_conv(Result result)2157 static vg_lite_error_t vg_lite_error_conv(Result result)
2158 {
2159     switch(result) {
2160         case Result::Success:
2161             return VG_LITE_SUCCESS;
2162 
2163         case Result::InvalidArguments:
2164             return VG_LITE_INVALID_ARGUMENT;
2165 
2166         case Result::InsufficientCondition:
2167             return VG_LITE_OUT_OF_RESOURCES;
2168 
2169         case Result::FailedAllocation:
2170             return VG_LITE_OUT_OF_MEMORY;
2171 
2172         case Result::NonSupport:
2173             return VG_LITE_NOT_SUPPORT;
2174 
2175         default:
2176             break;
2177     }
2178 
2179     return VG_LITE_TIMEOUT;
2180 }
2181 
matrix_conv(const vg_lite_matrix_t * matrix)2182 static Matrix matrix_conv(const vg_lite_matrix_t * matrix)
2183 {
2184     return *(Matrix *)matrix;
2185 }
2186 
fill_rule_conv(vg_lite_fill_t fill)2187 static FillRule fill_rule_conv(vg_lite_fill_t fill)
2188 {
2189     if(fill == VG_LITE_FILL_EVEN_ODD) {
2190         return FillRule::EvenOdd;
2191     }
2192 
2193     return FillRule::Winding;
2194 }
2195 
blend_method_conv(vg_lite_blend_t blend)2196 static BlendMethod blend_method_conv(vg_lite_blend_t blend)
2197 {
2198     switch(blend) {
2199         case VG_LITE_BLEND_NONE:
2200             return BlendMethod::SrcOver;
2201 
2202         case VG_LITE_BLEND_NORMAL_LVGL:
2203             return BlendMethod::Normal;
2204 
2205         case VG_LITE_BLEND_SRC_OVER:
2206             return BlendMethod::Normal;
2207 
2208         case VG_LITE_BLEND_SCREEN:
2209             return BlendMethod::Screen;
2210 
2211         case VG_LITE_BLEND_ADDITIVE:
2212             return BlendMethod::Add;
2213 
2214         case VG_LITE_BLEND_MULTIPLY:
2215             return BlendMethod::Multiply;
2216 
2217         default:
2218             break;
2219     }
2220 
2221     return BlendMethod::Normal;
2222 }
2223 
stroke_cap_conv(vg_lite_cap_style_t cap)2224 static StrokeCap stroke_cap_conv(vg_lite_cap_style_t cap)
2225 {
2226     switch(cap) {
2227         case VG_LITE_CAP_SQUARE:
2228             return StrokeCap::Square;
2229         case VG_LITE_CAP_ROUND:
2230             return StrokeCap::Round;
2231         case VG_LITE_CAP_BUTT:
2232             return StrokeCap::Butt;
2233         default:
2234             break;
2235     }
2236 
2237     return StrokeCap::Square;
2238 }
2239 
stroke_join_conv(vg_lite_join_style_t join)2240 static StrokeJoin stroke_join_conv(vg_lite_join_style_t join)
2241 {
2242     switch(join) {
2243         case VG_LITE_JOIN_BEVEL:
2244             return StrokeJoin::Bevel;
2245         case VG_LITE_JOIN_ROUND:
2246             return StrokeJoin::Round;
2247         case VG_LITE_JOIN_MITER:
2248             return StrokeJoin::Miter;
2249         default:
2250             break;
2251     }
2252 
2253     return StrokeJoin::Bevel;
2254 }
2255 
fill_spread_conv(vg_lite_gradient_spreadmode_t spread)2256 static FillSpread fill_spread_conv(vg_lite_gradient_spreadmode_t spread)
2257 {
2258     switch(spread) {
2259         case VG_LITE_GRADIENT_SPREAD_PAD:
2260             return FillSpread::Pad;
2261         case VG_LITE_GRADIENT_SPREAD_REPEAT:
2262             return FillSpread::Repeat;
2263         case VG_LITE_GRADIENT_SPREAD_REFLECT:
2264             return FillSpread::Reflect;
2265         default:
2266             return FillSpread::Pad;
2267     }
2268 }
2269 
vlc_get_arg(const void * data,vg_lite_format_t format)2270 static float vlc_get_arg(const void * data, vg_lite_format_t format)
2271 {
2272     switch(format) {
2273         case VG_LITE_S8:
2274             return *((int8_t *)data);
2275 
2276         case VG_LITE_S16:
2277             return *((int16_t *)data);
2278 
2279         case VG_LITE_S32:
2280             return *((int32_t *)data);
2281 
2282         case VG_LITE_FP32:
2283             return *((float *)data);
2284 
2285         default:
2286             LV_LOG_ERROR("UNKNOW_FORMAT: %d", format);
2287             break;
2288     }
2289 
2290     return 0;
2291 }
2292 
vlc_format_len(vg_lite_format_t format)2293 static uint8_t vlc_format_len(vg_lite_format_t format)
2294 {
2295     switch(format) {
2296         case VG_LITE_S8:
2297             return 1;
2298         case VG_LITE_S16:
2299             return 2;
2300         case VG_LITE_S32:
2301             return 4;
2302         case VG_LITE_FP32:
2303             return 4;
2304         default:
2305             LV_LOG_ERROR("UNKNOW_FORMAT: %d", format);
2306             LV_ASSERT(false);
2307             break;
2308     }
2309 
2310     return 0;
2311 }
2312 
vlc_op_arg_len(uint8_t vlc_op)2313 static uint8_t vlc_op_arg_len(uint8_t vlc_op)
2314 {
2315     switch(vlc_op) {
2316             VLC_OP_ARG_LEN(END, 0);
2317             VLC_OP_ARG_LEN(CLOSE, 0);
2318             VLC_OP_ARG_LEN(MOVE, 2);
2319             VLC_OP_ARG_LEN(MOVE_REL, 2);
2320             VLC_OP_ARG_LEN(LINE, 2);
2321             VLC_OP_ARG_LEN(LINE_REL, 2);
2322             VLC_OP_ARG_LEN(QUAD, 4);
2323             VLC_OP_ARG_LEN(QUAD_REL, 4);
2324             VLC_OP_ARG_LEN(CUBIC, 6);
2325             VLC_OP_ARG_LEN(CUBIC_REL, 6);
2326             VLC_OP_ARG_LEN(SCCWARC, 5);
2327             VLC_OP_ARG_LEN(SCCWARC_REL, 5);
2328             VLC_OP_ARG_LEN(SCWARC, 5);
2329             VLC_OP_ARG_LEN(SCWARC_REL, 5);
2330             VLC_OP_ARG_LEN(LCCWARC, 5);
2331             VLC_OP_ARG_LEN(LCCWARC_REL, 5);
2332             VLC_OP_ARG_LEN(LCWARC, 5);
2333             VLC_OP_ARG_LEN(LCWARC_REL, 5);
2334         default:
2335             LV_LOG_ERROR("UNKNOW_VLC_OP: 0x%x", vlc_op);
2336             LV_ASSERT(false);
2337             break;
2338     }
2339 
2340     return 0;
2341 }
2342 
shape_set_stroke(std::unique_ptr<Shape> & shape,const vg_lite_path_t * path)2343 static Result shape_set_stroke(std::unique_ptr<Shape> & shape, const vg_lite_path_t * path)
2344 {
2345     switch(path->path_type) {
2346         case VG_LITE_DRAW_ZERO:
2347         case VG_LITE_DRAW_FILL_PATH:
2348             /* if path is not a stroke, return */
2349             return Result::Success;
2350 
2351         case VG_LITE_DRAW_STROKE_PATH:
2352         case VG_LITE_DRAW_FILL_STROKE_PATH:
2353             break;
2354 
2355         default:
2356             LV_LOG_ERROR("unknown path type: %d", path->path_type);
2357             return Result::InvalidArguments;
2358     }
2359 
2360     LV_ASSERT_NULL(path->stroke);
2361     TVG_CHECK_RETURN_RESULT(shape->stroke(path->stroke->line_width));
2362     TVG_CHECK_RETURN_RESULT(shape->strokeMiterlimit(path->stroke->miter_limit));
2363     TVG_CHECK_RETURN_RESULT(shape->stroke(stroke_cap_conv(path->stroke->cap_style)));
2364     TVG_CHECK_RETURN_RESULT(shape->stroke(stroke_join_conv(path->stroke->join_style)));
2365     TVG_CHECK_RETURN_RESULT(shape->stroke(TVG_COLOR(path->stroke_color)));
2366 
2367     if(path->stroke->pattern_count) {
2368         LV_ASSERT_NULL(path->stroke->dash_pattern);
2369         TVG_CHECK_RETURN_RESULT(shape->stroke(path->stroke->dash_pattern, path->stroke->pattern_count));
2370     }
2371 
2372     return Result::Success;
2373 }
2374 
shape_append_path(std::unique_ptr<Shape> & shape,vg_lite_path_t * path,vg_lite_matrix_t * matrix)2375 static Result shape_append_path(std::unique_ptr<Shape> & shape, vg_lite_path_t * path, vg_lite_matrix_t * matrix)
2376 {
2377     uint8_t fmt_len = vlc_format_len(path->format);
2378     uint8_t * cur = (uint8_t *)path->path;
2379     uint8_t * end = cur + path->path_length;
2380 
2381     while(cur < end) {
2382         /* get op code */
2383         uint8_t op_code = VLC_GET_OP_CODE(cur);
2384 
2385         /* get arguments length */
2386         uint8_t arg_len = vlc_op_arg_len(op_code);
2387 
2388         /* skip op code */
2389         cur += fmt_len;
2390 
2391         switch(op_code) {
2392             case VLC_OP_MOVE: {
2393                     float x = VLC_GET_ARG(cur, 0);
2394                     float y = VLC_GET_ARG(cur, 1);
2395                     TVG_CHECK_RETURN_RESULT(shape->moveTo(x, y));
2396                 }
2397                 break;
2398 
2399             case VLC_OP_LINE: {
2400                     float x = VLC_GET_ARG(cur, 0);
2401                     float y = VLC_GET_ARG(cur, 1);
2402                     TVG_CHECK_RETURN_RESULT(shape->lineTo(x, y));
2403                 }
2404                 break;
2405 
2406             case VLC_OP_QUAD: {
2407                     /* hack pre point */
2408                     float qcx0 = VLC_GET_ARG(cur, -3);
2409                     float qcy0 = VLC_GET_ARG(cur, -2);
2410                     float qcx1 = VLC_GET_ARG(cur, 0);
2411                     float qcy1 = VLC_GET_ARG(cur, 1);
2412                     float x = VLC_GET_ARG(cur, 2);
2413                     float y = VLC_GET_ARG(cur, 3);
2414 
2415                     qcx0 += (qcx1 - qcx0) * 2 / 3;
2416                     qcy0 += (qcy1 - qcy0) * 2 / 3;
2417                     qcx1 = x + (qcx1 - x) * 2 / 3;
2418                     qcy1 = y + (qcy1 - y) * 2 / 3;
2419 
2420                     TVG_CHECK_RETURN_RESULT(shape->cubicTo(qcx0, qcy0, qcx1, qcy1, x, y));
2421                 }
2422                 break;
2423 
2424             case VLC_OP_CUBIC: {
2425                     float cx1 = VLC_GET_ARG(cur, 0);
2426                     float cy1 = VLC_GET_ARG(cur, 1);
2427                     float cx2 = VLC_GET_ARG(cur, 2);
2428                     float cy2 = VLC_GET_ARG(cur, 3);
2429                     float x = VLC_GET_ARG(cur, 4);
2430                     float y = VLC_GET_ARG(cur, 5);
2431                     TVG_CHECK_RETURN_RESULT(shape->cubicTo(cx1, cy1, cx2, cy2, x, y));
2432                 }
2433                 break;
2434 
2435             case VLC_OP_CLOSE:
2436                 TVG_CHECK_RETURN_RESULT(shape->close());
2437                 break;
2438 
2439             default:
2440                 break;
2441         }
2442 
2443         cur += arg_len * fmt_len;
2444     }
2445 
2446     TVG_CHECK_RETURN_RESULT(shape_set_stroke(shape, path));
2447 
2448     float x_min = path->bounding_box[0];
2449     float y_min = path->bounding_box[1];
2450     float x_max = path->bounding_box[2];
2451     float y_max = path->bounding_box[3];
2452 
2453     if(math_equal(x_min, FLT_MIN) && math_equal(y_min, FLT_MIN)
2454        && math_equal(x_max, FLT_MAX) && math_equal(y_max, FLT_MAX)) {
2455         return Result::Success;
2456     }
2457 
2458     auto cilp = Shape::gen();
2459     TVG_CHECK_RETURN_RESULT(cilp->appendRect(x_min, y_min, x_max - x_min, y_max - y_min, 0, 0));
2460     TVG_CHECK_RETURN_RESULT(cilp->transform(matrix_conv(matrix)));
2461     TVG_CHECK_RETURN_RESULT(shape->composite(std::move(cilp), CompositeMethod::ClipPath));
2462 
2463     return Result::Success;
2464 }
2465 
shape_append_rect(std::unique_ptr<Shape> & shape,const vg_lite_buffer_t * target,const vg_lite_rectangle_t * rect)2466 static Result shape_append_rect(std::unique_ptr<Shape> & shape, const vg_lite_buffer_t * target,
2467                                 const vg_lite_rectangle_t * rect)
2468 {
2469     if(rect) {
2470         TVG_CHECK_RETURN_RESULT(shape->appendRect(rect->x, rect->y, rect->width, rect->height, 0, 0));
2471     }
2472     else if(target) {
2473         TVG_CHECK_RETURN_RESULT(shape->appendRect(0, 0, target->width, target->height, 0, 0));
2474     }
2475     else {
2476         return Result::InvalidArguments;
2477     }
2478 
2479     return Result::Success;
2480 }
2481 
canvas_set_target(vg_lite_ctx * ctx,vg_lite_buffer_t * target)2482 static Result canvas_set_target(vg_lite_ctx * ctx, vg_lite_buffer_t * target)
2483 {
2484     /* if target_buffer needs to be changed, finish current drawing */
2485     if(ctx->target_buffer && ctx->target_buffer != target->memory) {
2486         vg_lite_finish();
2487     }
2488 
2489     ctx->target_buffer = target->memory;
2490     ctx->target_format = target->format;
2491     ctx->target_px_size = target->width * target->height;
2492 
2493     void * canvas_target_buffer;
2494     if(TVG_IS_VG_FMT_SUPPORT(target->format)) {
2495         /* if target format is supported by VG, use target buffer directly */
2496         canvas_target_buffer = target->memory;
2497     }
2498     else {
2499         /* if target format is not supported by VG, use internal buffer */
2500         canvas_target_buffer = ctx->get_temp_target_buffer(target->width, target->height);
2501     }
2502 
2503     /* Prevent repeated target setting */
2504     if(ctx->tvg_target_buffer == canvas_target_buffer) {
2505         return Result::Success;
2506     }
2507 
2508     ctx->tvg_target_buffer = canvas_target_buffer;
2509 
2510     TVG_CHECK_RETURN_RESULT(ctx->canvas->target(
2511                                 (uint32_t *)ctx->tvg_target_buffer,
2512                                 target->width,
2513                                 target->width,
2514                                 target->height,
2515                                 SwCanvas::ARGB8888));
2516 
2517     if(ctx->scissor_is_set) {
2518         TVG_CHECK_RETURN_RESULT(
2519             ctx->canvas->viewport(
2520                 ctx->scissor_rect.x, ctx->scissor_rect.y,
2521                 ctx->scissor_rect.width, ctx->scissor_rect.height));
2522     }
2523 
2524     return Result::Success;
2525 }
2526 
width_to_stride(vg_lite_uint32_t w,vg_lite_buffer_format_t color_format)2527 static vg_lite_uint32_t width_to_stride(vg_lite_uint32_t w, vg_lite_buffer_format_t color_format)
2528 {
2529     if(vg_lite_query_feature(gcFEATURE_BIT_VG_16PIXELS_ALIGN)) {
2530         w = VG_LITE_ALIGN(w, 16);
2531     }
2532 
2533     vg_lite_uint32_t mul, div, align;
2534     get_format_bytes(color_format, &mul, &div, &align);
2535     return VG_LITE_ALIGN((w * mul / div), align);
2536 }
2537 
decode_indexed_line(vg_lite_buffer_format_t color_format,const vg_lite_uint32_t * palette,int32_t x,int32_t y,int32_t w_px,const uint8_t * in,vg_lite_uint32_t * out)2538 static bool decode_indexed_line(
2539     vg_lite_buffer_format_t color_format,
2540     const vg_lite_uint32_t * palette,
2541     int32_t x, int32_t y,
2542     int32_t w_px, const uint8_t * in, vg_lite_uint32_t * out)
2543 {
2544     uint8_t px_size;
2545     uint16_t mask;
2546 
2547     vg_lite_uint32_t w_byte = width_to_stride(w_px, color_format);
2548 
2549     in += w_byte * y; /*First pixel*/
2550     out += w_px * y;
2551 
2552     int8_t shift = 0;
2553     switch(color_format) {
2554         case VG_LITE_INDEX_1:
2555             px_size = 1;
2556             in += x / 8; /*8pixel per byte*/
2557             shift = 7 - (x & 0x7);
2558             break;
2559         case VG_LITE_INDEX_2:
2560             px_size = 2;
2561             in += x / 4; /*4pixel per byte*/
2562             shift = 6 - 2 * (x & 0x3);
2563             break;
2564         case VG_LITE_INDEX_4:
2565             px_size = 4;
2566             in += x / 2; /*2pixel per byte*/
2567             shift = 4 - 4 * (x & 0x1);
2568             break;
2569         case VG_LITE_INDEX_8:
2570             px_size = 8;
2571             in += x;
2572             shift = 0;
2573             break;
2574         default:
2575             LV_ASSERT(false);
2576             return false;
2577     }
2578 
2579     mask = (1 << px_size) - 1; /*E.g. px_size = 2; mask = 0x03*/
2580 
2581     int32_t i;
2582     for(i = 0; i < w_px; i++) {
2583         uint8_t val_act = (*in >> shift) & mask;
2584         out[i] = palette[val_act];
2585 
2586         shift -= px_size;
2587         if(shift < 0) {
2588             shift = 8 - px_size;
2589             in++;
2590         }
2591     }
2592     return true;
2593 }
2594 
picture_load(vg_lite_ctx * ctx,std::unique_ptr<Picture> & picture,const vg_lite_buffer_t * source,vg_lite_color_t color)2595 static Result picture_load(vg_lite_ctx * ctx, std::unique_ptr<Picture> & picture, const vg_lite_buffer_t * source,
2596                            vg_lite_color_t color)
2597 {
2598     vg_lite_uint32_t * image_buffer;
2599     LV_ASSERT(VG_LITE_IS_ALIGNED(source->memory, LV_VG_LITE_THORVG_BUF_ADDR_ALIGN));
2600 
2601 #if LV_VG_LITE_THORVG_16PIXELS_ALIGN
2602     LV_ASSERT(VG_LITE_IS_ALIGNED(source->width, 16));
2603 #endif
2604 
2605     if(source->format == VG_LITE_BGRA8888 && source->image_mode == VG_LITE_NORMAL_IMAGE_MODE) {
2606         image_buffer = (vg_lite_uint32_t *)source->memory;
2607     }
2608     else {
2609         vg_lite_uint32_t width = source->width;
2610         vg_lite_uint32_t height = source->height;
2611         vg_lite_uint32_t px_size = width * height;
2612         image_buffer = ctx->get_image_buffer(width, height);
2613 
2614         vg_lite_buffer_t target;
2615         memset(&target, 0, sizeof(target));
2616         target.memory = image_buffer;
2617         target.format = VG_LITE_BGRA8888;
2618         target.width = width;
2619         target.height = height;
2620         target.stride = width_to_stride(width, target.format);
2621 
2622         switch(source->format) {
2623             case VG_LITE_INDEX_1:
2624             case VG_LITE_INDEX_2:
2625             case VG_LITE_INDEX_4:
2626             case VG_LITE_INDEX_8: {
2627                     const vg_lite_uint32_t * clut_colors = ctx->get_CLUT(source->format);
2628                     for(vg_lite_uint32_t y = 0; y < height; y++) {
2629                         decode_indexed_line(source->format, clut_colors, 0, y, width, (uint8_t *)source->memory, image_buffer);
2630                     }
2631                 }
2632                 break;
2633 
2634             case VG_LITE_A4: {
2635                     conv_alpha4_to_bgra8888.convert(&target, source, color);
2636                 }
2637                 break;
2638 
2639             case VG_LITE_A8: {
2640                     conv_alpha8_to_bgra8888.convert(&target, source, color);
2641                 }
2642                 break;
2643 
2644             case VG_LITE_L8: {
2645                     conv_l8_to_bgra8888.convert(&target, source);
2646                 }
2647                 break;
2648 
2649             case VG_LITE_BGRX8888: {
2650                     conv_bgrx8888_to_bgra8888.convert(&target, source);
2651                 }
2652                 break;
2653 
2654             case VG_LITE_BGR888: {
2655                     conv_bgr888_to_bgra8888.convert(&target, source);
2656                 }
2657                 break;
2658 
2659             case VG_LITE_BGRA5658: {
2660                     conv_bgra5658_to_bgra8888.convert(&target, source);
2661                 }
2662                 break;
2663 
2664             case VG_LITE_BGR565: {
2665                     conv_bgr565_to_bgra8888.convert(&target, source);
2666                 }
2667                 break;
2668 
2669             case VG_LITE_BGRA5551: {
2670                     conv_bgra5551_to_bgra8888.convert(&target, source);
2671                 }
2672                 break;
2673 
2674             case VG_LITE_BGRA4444: {
2675                     conv_bgra4444_to_bgra8888.convert(&target, source);
2676                 }
2677                 break;
2678 
2679             case VG_LITE_BGRA2222: {
2680                     conv_bgra2222_to_bgra8888.convert(&target, source);
2681                 }
2682                 break;
2683 
2684 #if LV_VG_LITE_THORVG_YUV_SUPPORT
2685             case VG_LITE_NV12: {
2686                     libyuv::NV12ToARGB((const uint8_t *)source->memory, source->stride, (const uint8_t *)source->yuv.uv_memory,
2687                                        source->yuv.uv_stride,
2688                                        (uint8_t *)image_buffer, source->width * sizeof(vg_lite_uint32_t), width, height);
2689                 }
2690                 break;
2691 #endif
2692 
2693             case VG_LITE_BGRA8888: {
2694                     memcpy(image_buffer, source->memory, px_size * sizeof(vg_color32_t));
2695                 }
2696                 break;
2697 
2698             default:
2699                 LV_LOG_ERROR("unsupported format: %d", source->format);
2700                 LV_ASSERT(false);
2701                 break;
2702         }
2703 
2704         /* multiply color */
2705         if(source->image_mode == VG_LITE_MULTIPLY_IMAGE_MODE && !VG_LITE_IS_ALPHA_FORMAT(source->format)) {
2706             vg_color32_t * dest = (vg_color32_t *)image_buffer;
2707             while(px_size--) {
2708                 dest->alpha = UDIV255(dest->alpha * A(color));
2709                 dest->red = UDIV255(dest->red * B(color));
2710                 dest->green = UDIV255(dest->green * G(color));
2711                 dest->blue = UDIV255(dest->blue * R(color));
2712                 dest++;
2713             }
2714         }
2715     }
2716 
2717     TVG_CHECK_RETURN_RESULT(picture->load((uint32_t *)image_buffer, source->width, source->height, true));
2718 
2719     return Result::Success;
2720 }
2721 
ClampColor(FLOATVECTOR4 Source,FLOATVECTOR4 Target,uint8_t Premultiplied)2722 static void ClampColor(FLOATVECTOR4 Source, FLOATVECTOR4 Target, uint8_t Premultiplied)
2723 {
2724     vg_lite_float_t colorMax;
2725     /* Clamp the alpha channel. */
2726     Target[3] = CLAMP(Source[3], 0.0f, 1.0f);
2727 
2728     /* Determine the maximum value for the color channels. */
2729     colorMax = Premultiplied ? Target[3] : 1.0f;
2730 
2731     /* Clamp the color channels. */
2732     Target[0] = CLAMP(Source[0], 0.0f, colorMax);
2733     Target[1] = CLAMP(Source[1], 0.0f, colorMax);
2734     Target[2] = CLAMP(Source[2], 0.0f, colorMax);
2735 }
2736 
PackColorComponent(vg_lite_float_t value)2737 static uint8_t PackColorComponent(vg_lite_float_t value)
2738 {
2739     /* Compute the rounded normalized value. */
2740     vg_lite_float_t rounded = value * 255.0f + 0.5f;
2741 
2742     /* Get the integer part. */
2743     int32_t roundedInt = (int32_t)rounded;
2744 
2745     /* Clamp to 0..1 range. */
2746     uint8_t clamped = (uint8_t)CLAMP(roundedInt, 0, 255);
2747 
2748     /* Return result. */
2749     return clamped;
2750 }
2751 
2752 /* Get the bpp information of a color format. */
get_format_bytes(vg_lite_buffer_format_t format,vg_lite_uint32_t * mul,vg_lite_uint32_t * div,vg_lite_uint32_t * bytes_align)2753 static void get_format_bytes(vg_lite_buffer_format_t format,
2754                              vg_lite_uint32_t * mul,
2755                              vg_lite_uint32_t * div,
2756                              vg_lite_uint32_t * bytes_align)
2757 {
2758     *mul = *div = 1;
2759     *bytes_align = 4;
2760     switch(format) {
2761         case VG_LITE_L8:
2762         case VG_LITE_A8:
2763         case VG_LITE_RGBA8888_ETC2_EAC:
2764             break;
2765 
2766         case VG_LITE_A4:
2767             *div = 2;
2768             break;
2769 
2770         case VG_LITE_ABGR1555:
2771         case VG_LITE_ARGB1555:
2772         case VG_LITE_BGRA5551:
2773         case VG_LITE_RGBA5551:
2774         case VG_LITE_RGBA4444:
2775         case VG_LITE_BGRA4444:
2776         case VG_LITE_ABGR4444:
2777         case VG_LITE_ARGB4444:
2778         case VG_LITE_RGB565:
2779         case VG_LITE_BGR565:
2780         case VG_LITE_YUYV:
2781         case VG_LITE_YUY2:
2782         case VG_LITE_YUY2_TILED:
2783         /* AYUY2 buffer memory = YUY2 + alpha. */
2784         case VG_LITE_AYUY2:
2785         case VG_LITE_AYUY2_TILED:
2786         /* ABGR8565_PLANAR buffer memory = RGB565 + alpha. */
2787         case VG_LITE_ABGR8565_PLANAR:
2788         case VG_LITE_ARGB8565_PLANAR:
2789         case VG_LITE_RGBA5658_PLANAR:
2790         case VG_LITE_BGRA5658_PLANAR:
2791             *mul = 2;
2792             break;
2793 
2794         case VG_LITE_RGBA8888:
2795         case VG_LITE_BGRA8888:
2796         case VG_LITE_ABGR8888:
2797         case VG_LITE_ARGB8888:
2798         case VG_LITE_RGBX8888:
2799         case VG_LITE_BGRX8888:
2800         case VG_LITE_XBGR8888:
2801         case VG_LITE_XRGB8888:
2802             *mul = 4;
2803             break;
2804 
2805         case VG_LITE_NV12:
2806         case VG_LITE_NV12_TILED:
2807             *mul = 3;
2808             break;
2809 
2810         case VG_LITE_ANV12:
2811         case VG_LITE_ANV12_TILED:
2812             *mul = 4;
2813             break;
2814 
2815         case VG_LITE_INDEX_1:
2816             *div = 8;
2817             *bytes_align = 8;
2818             break;
2819 
2820         case VG_LITE_INDEX_2:
2821             *div = 4;
2822             *bytes_align = 8;
2823             break;
2824 
2825         case VG_LITE_INDEX_4:
2826             *div = 2;
2827             *bytes_align = 8;
2828             break;
2829 
2830         case VG_LITE_INDEX_8:
2831             *bytes_align = 1;
2832             break;
2833 
2834         case VG_LITE_RGBA2222:
2835         case VG_LITE_BGRA2222:
2836         case VG_LITE_ABGR2222:
2837         case VG_LITE_ARGB2222:
2838             *mul = 1;
2839             break;
2840 
2841         case VG_LITE_RGB888:
2842         case VG_LITE_BGR888:
2843         case VG_LITE_ABGR8565:
2844         case VG_LITE_BGRA5658:
2845         case VG_LITE_ARGB8565:
2846         case VG_LITE_RGBA5658:
2847             *mul = 3;
2848             break;
2849 
2850         /* OpenVG format*/
2851         case VG_sRGBX_8888:
2852         case VG_sRGBA_8888:
2853         case VG_sRGBA_8888_PRE:
2854         case VG_lRGBX_8888:
2855         case VG_lRGBA_8888:
2856         case VG_lRGBA_8888_PRE:
2857         case VG_sXRGB_8888:
2858         case VG_sARGB_8888:
2859         case VG_sARGB_8888_PRE:
2860         case VG_lXRGB_8888:
2861         case VG_lARGB_8888:
2862         case VG_lARGB_8888_PRE:
2863         case VG_sBGRX_8888:
2864         case VG_sBGRA_8888:
2865         case VG_sBGRA_8888_PRE:
2866         case VG_lBGRX_8888:
2867         case VG_lBGRA_8888:
2868         case VG_sXBGR_8888:
2869         case VG_sABGR_8888:
2870         case VG_lBGRA_8888_PRE:
2871         case VG_sABGR_8888_PRE:
2872         case VG_lXBGR_8888:
2873         case VG_lABGR_8888:
2874         case VG_lABGR_8888_PRE:
2875             *mul = 4;
2876             break;
2877 
2878         case VG_sRGBA_5551:
2879         case VG_sRGBA_4444:
2880         case VG_sARGB_1555:
2881         case VG_sARGB_4444:
2882         case VG_sBGRA_5551:
2883         case VG_sBGRA_4444:
2884         case VG_sABGR_1555:
2885         case VG_sABGR_4444:
2886         case VG_sRGB_565:
2887         case VG_sBGR_565:
2888             *mul = 2;
2889             break;
2890 
2891         case VG_sL_8:
2892         case VG_lL_8:
2893         case VG_A_8:
2894             break;
2895 
2896         case VG_BW_1:
2897         case VG_A_4:
2898         case VG_A_1:
2899             *div = 2;
2900             break;
2901 
2902         default:
2903             break;
2904     }
2905 }
2906 
matrix_transform_point(const vg_lite_matrix_t * matrix,const vg_lite_fpoint_t * point)2907 static vg_lite_fpoint_t matrix_transform_point(const vg_lite_matrix_t * matrix, const vg_lite_fpoint_t * point)
2908 {
2909     vg_lite_fpoint_t p;
2910     p.x = (vg_lite_float_t)(point->x * matrix->m[0][0] + point->y * matrix->m[0][1] + matrix->m[0][2]);
2911     p.y = (vg_lite_float_t)(point->x * matrix->m[1][0] + point->y * matrix->m[1][1] + matrix->m[1][2]);
2912     return p;
2913 }
2914 
vg_lite_matrix_inverse(vg_lite_matrix_t * result,const vg_lite_matrix_t * matrix)2915 static bool vg_lite_matrix_inverse(vg_lite_matrix_t * result, const vg_lite_matrix_t * matrix)
2916 {
2917     vg_lite_float_t det00, det01, det02;
2918     vg_lite_float_t d;
2919     bool is_affine;
2920 
2921     /* Test for identity matrix. */
2922     if(matrix == NULL) {
2923         result->m[0][0] = 1.0f;
2924         result->m[0][1] = 0.0f;
2925         result->m[0][2] = 0.0f;
2926         result->m[1][0] = 0.0f;
2927         result->m[1][1] = 1.0f;
2928         result->m[1][2] = 0.0f;
2929         result->m[2][0] = 0.0f;
2930         result->m[2][1] = 0.0f;
2931         result->m[2][2] = 1.0f;
2932 
2933         /* Success. */
2934         return true;
2935     }
2936 
2937     det00 = (matrix->m[1][1] * matrix->m[2][2]) - (matrix->m[2][1] * matrix->m[1][2]);
2938     det01 = (matrix->m[2][0] * matrix->m[1][2]) - (matrix->m[1][0] * matrix->m[2][2]);
2939     det02 = (matrix->m[1][0] * matrix->m[2][1]) - (matrix->m[2][0] * matrix->m[1][1]);
2940 
2941     /* Compute determinant. */
2942     d = (matrix->m[0][0] * det00) + (matrix->m[0][1] * det01) + (matrix->m[0][2] * det02);
2943 
2944     /* Return 0 if there is no inverse matrix. */
2945     if(d == 0.0f)
2946         return false;
2947 
2948     /* Compute reciprocal. */
2949     d = 1.0f / d;
2950 
2951     /* Determine if the matrix is affine. */
2952     is_affine = (matrix->m[2][0] == 0.0f) && (matrix->m[2][1] == 0.0f) && (matrix->m[2][2] == 1.0f);
2953 
2954     result->m[0][0] = d * det00;
2955     result->m[0][1] = d * ((matrix->m[2][1] * matrix->m[0][2]) - (matrix->m[0][1] * matrix->m[2][2]));
2956     result->m[0][2] = d * ((matrix->m[0][1] * matrix->m[1][2]) - (matrix->m[1][1] * matrix->m[0][2]));
2957     result->m[1][0] = d * det01;
2958     result->m[1][1] = d * ((matrix->m[0][0] * matrix->m[2][2]) - (matrix->m[2][0] * matrix->m[0][2]));
2959     result->m[1][2] = d * ((matrix->m[1][0] * matrix->m[0][2]) - (matrix->m[0][0] * matrix->m[1][2]));
2960     result->m[2][0] = is_affine ? 0.0f : d * det02;
2961     result->m[2][1] = is_affine ? 0.0f : d * ((matrix->m[2][0] * matrix->m[0][1]) - (matrix->m[0][0] * matrix->m[2][1]));
2962     result->m[2][2] = is_affine ? 1.0f : d * ((matrix->m[0][0] * matrix->m[1][1]) - (matrix->m[1][0] * matrix->m[0][1]));
2963 
2964     /* Success. */
2965     return true;
2966 }
2967 
vg_lite_matrix_multiply(vg_lite_matrix_t * matrix,const vg_lite_matrix_t * mult)2968 static void vg_lite_matrix_multiply(vg_lite_matrix_t * matrix, const vg_lite_matrix_t * mult)
2969 {
2970     vg_lite_matrix_t temp;
2971     int row, column;
2972 
2973     /* Process all rows. */
2974     for(row = 0; row < 3; row++) {
2975         /* Process all columns. */
2976         for(column = 0; column < 3; column++) {
2977             /* Compute matrix entry. */
2978             temp.m[row][column] = (matrix->m[row][0] * mult->m[0][column])
2979                                   + (matrix->m[row][1] * mult->m[1][column])
2980                                   + (matrix->m[row][2] * mult->m[2][column]);
2981         }
2982     }
2983 
2984     /* Copy temporary matrix into result. */
2985     lv_memcpy(matrix->m, &temp.m, sizeof(temp.m));
2986 }
2987 
2988 #endif
2989