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