1 /**
2 * @file lv_draw_sw_arm2d.h
3 *
4 */
5
6 #ifndef LV_DRAW_SW_ARM2D_H
7 #define LV_DRAW_SW_ARM2D_H
8
9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12
13 /* *INDENT-OFF* */
14
15 /*********************
16 * INCLUDES
17 *********************/
18
19 #include "../../../lv_conf_internal.h"
20 #include "../../../misc/lv_area_private.h"
21
22 #if LV_USE_DRAW_ARM2D_SYNC
23
24 #define __ARM_2D_IMPL__
25 #include "arm_2d.h"
26 #include "__arm_2d_impl.h"
27
28 #if defined(__IS_COMPILER_ARM_COMPILER_5__)
29 #pragma diag_suppress 174,177,188,68,513,144,1296
30 #elif defined(__IS_COMPILER_IAR__)
31 #pragma diag_suppress=Pa093
32 #elif defined(__IS_COMPILER_GCC__)
33 #pragma GCC diagnostic ignored "-Wdiscarded-qualifiers"
34 #endif
35
36 /*********************
37 * DEFINES
38 *********************/
39 #ifndef LV_DRAW_SW_RGB565_SWAP
40 #define LV_DRAW_SW_RGB565_SWAP(__buf_ptr, __buf_size_px) \
41 lv_draw_sw_rgb565_swap_helium((__buf_ptr), (__buf_size_px))
42 #endif
43
44 #ifndef LV_DRAW_SW_IMAGE
45 #define LV_DRAW_SW_IMAGE(__transformed, \
46 __cf, \
47 __src_buf, \
48 __img_coords, \
49 __src_stride, \
50 __blend_area, \
51 __draw_unit, \
52 __draw_dsc) \
53 lv_draw_sw_image_helium( (__transformed), \
54 (__cf), \
55 (uint8_t *)(__src_buf), \
56 (__img_coords), \
57 (__src_stride), \
58 (__blend_area), \
59 (__draw_unit), \
60 (__draw_dsc))
61 #endif
62
63 #ifndef LV_DRAW_SW_RGB565_RECOLOR
64 #define LV_DRAW_SW_RGB565_RECOLOR(__src_buf, __blend_area, __color, __opa) \
65 lv_draw_sw_image_recolor_rgb565( (__src_buf), \
66 &(__blend_area), \
67 (__color), \
68 (__opa))
69 #endif
70
71 #ifndef LV_DRAW_SW_RGB888_RECOLOR
72 #define LV_DRAW_SW_RGB888_RECOLOR( __src_buf, \
73 __blend_area, \
74 __color, \
75 __opa, \
76 __cf) \
77 lv_draw_sw_image_recolor_rgb888( (__src_buf), \
78 &(__blend_area), \
79 (__color), \
80 (__opa), \
81 (__cf))
82 #endif
83
84 /**********************
85 * TYPEDEFS
86 **********************/
87
88 /**********************
89 * GLOBAL PROTOTYPES
90 **********************/
91 extern void arm_2d_helper_swap_rgb16(uint16_t * phwBuffer, uint32_t wCount);
92
93 /**********************
94 * MACROS
95 **********************/
96
97 #define __RECOLOUR_BEGIN() \
98 do { \
99 lv_color_t *rgb_tmp_buf = NULL; \
100 if(draw_dsc->recolor_opa > LV_OPA_MIN) { \
101 if(LV_COLOR_FORMAT_RGB565 == des_cf) { \
102 rgb_tmp_buf \
103 = lv_malloc(src_w * src_h * sizeof(uint16_t)); \
104 if (NULL == rgb_tmp_buf) { \
105 LV_LOG_WARN( \
106 "Failed to allocate memory for accelerating recolor, " \
107 "use normal route instead."); \
108 break; \
109 } \
110 lv_memcpy( rgb_tmp_buf, \
111 src_buf, \
112 src_w * src_h * sizeof(uint16_t)); \
113 arm_2d_size_t copy_size = { \
114 .iWidth = src_w, \
115 .iHeight = src_h, \
116 }; \
117 /* apply re-color */ \
118 __arm_2d_impl_rgb565_colour_filling_with_opacity( \
119 (uint16_t *)rgb_tmp_buf, \
120 src_w, \
121 ©_size, \
122 lv_color_to_u16(draw_dsc->recolor), \
123 draw_dsc->recolor_opa); \
124 \
125 /* replace src_buf for the following operation */ \
126 src_buf = (const uint8_t *)rgb_tmp_buf; \
127 } \
128 else if(LV_COLOR_FORMAT_XRGB8888 == des_cf) { \
129 rgb_tmp_buf \
130 = lv_malloc(src_w * src_h * sizeof(uint32_t)); \
131 if (NULL == rgb_tmp_buf) { \
132 LV_LOG_WARN( \
133 "Failed to allocate memory for accelerating recolor, " \
134 "use normal route instead."); \
135 break; \
136 } \
137 lv_memcpy( rgb_tmp_buf, \
138 src_buf, \
139 src_w * src_h * sizeof(uint32_t)); \
140 arm_2d_size_t copy_size = { \
141 .iWidth = src_w, \
142 .iHeight = src_h, \
143 }; \
144 /* apply re-color */ \
145 __arm_2d_impl_cccn888_colour_filling_with_opacity( \
146 (uint32_t *)rgb_tmp_buf, \
147 src_w, \
148 ©_size, \
149 lv_color_to_u32(draw_dsc->recolor), \
150 draw_dsc->recolor_opa); \
151 \
152 /* replace src_buf for the following operation */ \
153 src_buf = (const uint8_t *)rgb_tmp_buf; \
154 } \
155 } \
156 do {
157
158 #define __RECOLOUR_END() \
159 } while(0); \
160 if (NULL != rgb_tmp_buf) { \
161 lv_free(rgb_tmp_buf); \
162 } \
163 } while(0);
164
lv_draw_sw_rgb565_swap_helium(void * buf,uint32_t buf_size_px)165 static inline lv_result_t lv_draw_sw_rgb565_swap_helium(void * buf, uint32_t buf_size_px)
166 {
167 arm_2d_helper_swap_rgb16((uint16_t *)buf, buf_size_px);
168 return LV_RESULT_OK;
169 }
170
lv_draw_sw_image_helium(bool is_transform,lv_color_format_t src_cf,const uint8_t * src_buf,const lv_area_t * coords,int32_t src_stride,const lv_area_t * des_area,lv_draw_unit_t * draw_unit,const lv_draw_image_dsc_t * draw_dsc)171 static inline lv_result_t lv_draw_sw_image_helium(
172 bool is_transform,
173 lv_color_format_t src_cf,
174 const uint8_t *src_buf,
175 const lv_area_t * coords,
176 int32_t src_stride,
177 const lv_area_t * des_area,
178 lv_draw_unit_t * draw_unit,
179 const lv_draw_image_dsc_t * draw_dsc)
180 {
181 lv_result_t result = LV_RESULT_INVALID;
182 lv_layer_t * layer = draw_unit->target_layer;
183 lv_color_format_t des_cf = layer->color_format;
184 static bool arm_2d_initialized = false;
185
186 if (!arm_2d_initialized) {
187 arm_2d_initialized = true;
188 arm_2d_init();
189 }
190
191 do {
192 if (!is_transform) {
193 break;
194 }
195 if(draw_dsc->scale_x != draw_dsc->scale_y) {
196 break;
197 }
198 /* filter the unsupported colour format combination */
199 if((LV_COLOR_FORMAT_RGB565 == des_cf)
200 && !( (LV_COLOR_FORMAT_RGB565 == src_cf)
201 || (LV_COLOR_FORMAT_RGB565A8 == src_cf))) {
202 break;
203 }
204 #if 0 /* a temporary patch */
205 if((LV_COLOR_FORMAT_XRGB8888 == des_cf)
206 && !( (LV_COLOR_FORMAT_ARGB8888 == src_cf)
207 || (LV_COLOR_FORMAT_XRGB8888 == src_cf))) {
208 break;
209 }
210 #else
211 if((LV_COLOR_FORMAT_XRGB8888 == des_cf)
212 || (LV_COLOR_FORMAT_RGB888 == des_cf)
213 || (LV_COLOR_FORMAT_ARGB8888 == des_cf)) {
214 break;
215 }
216 #endif
217
218 /* ------------- prepare parameters for arm-2d APIs - BEGIN --------- */
219
220 lv_area_t blend_area;
221 if(!lv_area_intersect(&blend_area, des_area, draw_unit->clip_area)) {
222 break;
223 }
224
225 int32_t src_w = lv_area_get_width(coords);
226 int32_t src_h = lv_area_get_height(coords);
227
228 arm_2d_size_t src_size = {
229 .iWidth = (int16_t)src_w,
230 .iHeight = (int16_t)src_h,
231 };
232
233 // arm_2d_size_t des_size;
234
235 // do{
236 // int32_t des_w = lv_area_get_width(&blend_area);
237 // int32_t des_h = lv_area_get_height(&blend_area);
238
239 // LV_ASSERT(des_w <= INT16_MAX);
240 // LV_ASSERT(des_h <= INT16_MAX);
241
242 // des_size.iWidth = (int16_t)des_w;
243 // des_size.iHeight = (int16_t)des_h;
244 // } while(0);
245 //
246 // arm_2d_size_t copy_size = {
247 // .iWidth = MIN(des_size.iWidth, src_size.iWidth),
248 // .iHeight = MIN(des_size.iHeight, src_size.iHeight),
249 // };
250 //
251 // int32_t des_stride = lv_draw_buf_width_to_stride(
252 // lv_area_get_width(&layer->buf_area),
253 // des_cf);
254 // uint8_t *des_buf_moved = (uint8_t *)lv_draw_layer_go_to_xy(
255 // layer,
256 // blend_area.x1 - layer->buf_area.x1,
257 // blend_area.y1 - layer->buf_area.y1);
258 uint8_t *des_buf = (uint8_t *)lv_draw_layer_go_to_xy(layer, 0, 0);
259 uint8_t opa = draw_dsc->opa;
260
261 /* ------------- prepare parameters for arm-2d APIs - END ----------- */
262 __RECOLOUR_BEGIN()
263
264 static arm_2d_tile_t target_tile_origin;
265 static arm_2d_tile_t target_tile;
266 arm_2d_region_t clip_region;
267 static arm_2d_region_t target_region;
268
269 target_region = (arm_2d_region_t) {
270 .tLocation = {
271 .iX = (int16_t)(coords->x1 - draw_unit->clip_area->x1),
272 .iY = (int16_t)(coords->y1 - draw_unit->clip_area->y1),
273 },
274 .tSize = src_size,
275 };
276
277 target_tile_origin = (arm_2d_tile_t) {
278 .tRegion = {
279 .tSize = {
280 .iWidth = (int16_t)lv_area_get_width(&layer->buf_area),
281 .iHeight = (int16_t)lv_area_get_height(&layer->buf_area),
282 },
283 },
284 .tInfo = {
285 .bIsRoot = true,
286 },
287 .phwBuffer = (uint16_t *)des_buf,
288 };
289
290 clip_region = (arm_2d_region_t) {
291 .tLocation = {
292 .iX = (int16_t)(draw_unit->clip_area->x1 - layer->buf_area.x1),
293 .iY = (int16_t)(draw_unit->clip_area->y1 - layer->buf_area.y1),
294 },
295 .tSize = {
296 .iWidth = (int16_t)lv_area_get_width(draw_unit->clip_area),
297 .iHeight = (int16_t)lv_area_get_height(draw_unit->clip_area),
298 },
299 };
300
301 arm_2d_tile_generate_child(&target_tile_origin,
302 &clip_region,
303 &target_tile,
304 false);
305
306 static arm_2d_tile_t source_tile;
307
308 source_tile = (arm_2d_tile_t) {
309 .tRegion = {
310 .tSize = {
311 .iWidth = (int16_t)src_w,
312 .iHeight = (int16_t)src_h,
313 },
314 },
315 .tInfo = {
316 .bIsRoot = true,
317 },
318 .pchBuffer = (uint8_t *)src_buf,
319 };
320
321 static arm_2d_location_t source_center, target_center;
322 source_center.iX = draw_dsc->pivot.x;
323 source_center.iY = draw_dsc->pivot.y;
324 target_center = target_region.tLocation;
325 target_center.iX += draw_dsc->pivot.x;
326 target_center.iY += draw_dsc->pivot.y;
327
328 if(LV_COLOR_FORMAT_A8 == src_cf) {
329
330 source_tile.tInfo.bHasEnforcedColour = true;
331 source_tile.tInfo.tColourInfo.chScheme = ARM_2D_COLOUR_GRAY8;
332
333 if(LV_COLOR_FORMAT_RGB565 == des_cf) {
334
335 arm_2d_rgb565_fill_colour_with_mask_opacity_and_transform(
336 &source_tile,
337 &target_tile,
338 NULL,
339 source_center,
340 ARM_2D_ANGLE((draw_dsc->rotation / 10.0f)),
341 draw_dsc->scale_x / 256.0f,
342 lv_color_to_u16(draw_dsc->recolor),
343 opa,
344 &target_center
345 );
346
347 }
348 else if(LV_COLOR_FORMAT_XRGB8888 == des_cf) {
349 arm_2d_cccn888_fill_colour_with_mask_opacity_and_transform(
350 &source_tile,
351 &target_tile,
352 NULL,
353 source_center,
354 ARM_2D_ANGLE((draw_dsc->rotation / 10.0f)),
355 draw_dsc->scale_x / 256.0f,
356 lv_color_to_int(draw_dsc->recolor),
357 opa,
358 &target_center
359 );
360 }
361 else {
362 break;
363 }
364
365 }
366 else if(LV_COLOR_FORMAT_RGB565A8 == src_cf) {
367 LV_ASSERT(LV_COLOR_FORMAT_RGB565 == des_cf);
368
369 /* mask_buf = src_buf + src_stride * src_w / header->w * src_h; */
370 const uint8_t *mask_buf = src_buf + src_stride * src_h;
371 int32_t mask_stride = src_stride / 2;
372
373 static arm_2d_tile_t mask_tile;
374 mask_tile = source_tile;
375
376 mask_tile.tInfo.bHasEnforcedColour = true;
377 mask_tile.tInfo.tColourInfo.chScheme = ARM_2D_COLOUR_GRAY8;
378 mask_tile.pchBuffer = (uint8_t *)mask_buf;
379
380 if(opa >= LV_OPA_MAX) {
381 arm_2d_rgb565_tile_transform_with_src_mask(
382 &source_tile,
383 &mask_tile,
384 &target_tile,
385 NULL,
386 source_center,
387 ARM_2D_ANGLE((draw_dsc->rotation / 10.0f)),
388 draw_dsc->scale_x / 256.0f,
389 &target_center
390 );
391 }
392 else {
393 arm_2d_rgb565_tile_transform_with_src_mask_and_opacity(
394 &source_tile,
395 &mask_tile,
396 &target_tile,
397 NULL,
398 source_center,
399 ARM_2D_ANGLE((draw_dsc->rotation / 10.0f)),
400 draw_dsc->scale_x / 256.0f,
401 opa,
402 &target_center
403 );
404 }
405
406 }
407 else if(LV_COLOR_FORMAT_RGB565 == src_cf) {
408 LV_ASSERT(LV_COLOR_FORMAT_RGB565 == des_cf);
409
410 if(opa >= LV_OPA_MAX) {
411 #if ARM_2D_VERSION >= 10106
412 arm_2d_rgb565_tile_transform_only(
413 &source_tile,
414 &target_tile,
415 NULL,
416 source_center,
417 ARM_2D_ANGLE((draw_dsc->rotation / 10.0f)),
418 draw_dsc->scale_x / 256.0f,
419 &target_center);
420 #else
421
422 arm_2dp_rgb565_tile_transform_only_prepare(
423 NULL,
424 &source_tile,
425 source_center,
426 ARM_2D_ANGLE((draw_dsc->rotation / 10.0f)),
427 (float)(draw_dsc->scale_x / 256.0f));
428
429 arm_2dp_tile_transform(NULL,
430 &target_tile,
431 NULL,
432 &target_center);
433 #endif
434 }
435 else {
436 arm_2d_rgb565_tile_transform_only_with_opacity(
437 &source_tile,
438 &target_tile,
439 NULL,
440 source_center,
441 ARM_2D_ANGLE((draw_dsc->rotation / 10.0f)),
442 draw_dsc->scale_x / 256.0f,
443 opa,
444 &target_center
445 );
446 }
447
448 }
449 #if 0 /* a temporary patch */
450 else if(LV_COLOR_FORMAT_ARGB8888 == src_cf) {
451 LV_ASSERT(LV_COLOR_FORMAT_XRGB8888 == des_cf);
452
453 static arm_2d_tile_t mask_tile;
454 mask_tile = source_tile;
455
456 mask_tile.tInfo.bHasEnforcedColour = true;
457 mask_tile.tInfo.tColourInfo.chScheme = ARM_2D_CHANNEL_8in32;
458 mask_tile.pchBuffer = (uint8_t *)src_buf + 3;
459
460 if(opa >= LV_OPA_MAX) {
461 arm_2d_cccn888_tile_transform_with_src_mask(
462 &source_tile,
463 &mask_tile,
464 &target_tile,
465 NULL,
466 source_center,
467 ARM_2D_ANGLE((draw_dsc->rotation / 10.0f)),
468 draw_dsc->scale_x / 256.0f,
469 &target_center
470 );
471 }
472 else {
473 arm_2d_cccn888_tile_transform_with_src_mask_and_opacity(
474 &source_tile,
475 &mask_tile,
476 &target_tile,
477 NULL,
478 source_center,
479 ARM_2D_ANGLE((draw_dsc->rotation / 10.0f)),
480 draw_dsc->scale_x / 256.0f,
481 opa,
482 &target_center
483 );
484 }
485
486 }
487 else if(LV_COLOR_FORMAT_XRGB8888 == src_cf) {
488 LV_ASSERT(LV_COLOR_FORMAT_XRGB8888 == des_cf);
489
490 if(opa >= LV_OPA_MAX) {
491 arm_2d_cccn888_tile_transform_only(
492 &source_tile,
493 &target_tile,
494 NULL,
495 source_center,
496 ARM_2D_ANGLE((draw_dsc->rotation / 10.0f)),
497 draw_dsc->scale_x / 256.0f,
498 &target_center
499 );
500 }
501 else {
502 arm_2d_cccn888_tile_transform_only_with_opacity(
503 &source_tile,
504 &target_tile,
505 NULL,
506 source_center,
507 ARM_2D_ANGLE((draw_dsc->rotation / 10.0f)),
508 draw_dsc->scale_x / 256.0f,
509 opa,
510 &target_center
511 );
512 }
513
514 }
515 #endif
516 else {
517 break;
518 }
519
520 result = LV_RESULT_OK;
521
522 __RECOLOUR_END()
523 } while(0);
524
525 return result;
526 }
527
lv_draw_sw_image_recolor_rgb565(const uint8_t * src_buf,const lv_area_t * blend_area,lv_color_t color,lv_opa_t opa)528 static inline lv_result_t lv_draw_sw_image_recolor_rgb565(
529 const uint8_t *src_buf,
530 const lv_area_t * blend_area,
531 lv_color_t color,
532 lv_opa_t opa)
533 {
534 int32_t src_w = lv_area_get_width(blend_area);
535 int32_t src_h = lv_area_get_height(blend_area);
536
537 arm_2d_size_t copy_size = {
538 .iWidth = (int16_t)src_w,
539 .iHeight = (int16_t)src_h,
540 };
541
542 __arm_2d_impl_rgb565_colour_filling_with_opacity(
543 (uint16_t *)src_buf,
544 src_w,
545 ©_size,
546 lv_color_to_u16(color),
547 opa);
548
549 return LV_RESULT_OK;
550 }
551
lv_draw_sw_image_recolor_rgb888(const uint8_t * src_buf,const lv_area_t * blend_area,lv_color_t color,lv_opa_t opa,lv_color_format_t src_cf)552 static inline lv_result_t lv_draw_sw_image_recolor_rgb888(
553 const uint8_t *src_buf,
554 const lv_area_t * blend_area,
555 lv_color_t color,
556 lv_opa_t opa,
557 lv_color_format_t src_cf)
558 {
559 if(LV_COLOR_FORMAT_XRGB8888 != src_cf) {
560 return LV_RESULT_INVALID;
561 }
562
563 int32_t src_w = lv_area_get_width(blend_area);
564 int32_t src_h = lv_area_get_height(blend_area);
565
566 arm_2d_size_t copy_size = {
567 .iWidth = (int16_t)src_w,
568 .iHeight = (int16_t)src_h,
569 };
570
571 __arm_2d_impl_cccn888_colour_filling_with_opacity(
572 (uint32_t *)src_buf,
573 src_w,
574 ©_size,
575 lv_color_to_u32(color),
576 opa);
577
578 return LV_RESULT_OK;
579 }
580
581 #endif /* LV_USE_DRAW_ARM2D_SYNC */
582
583 /* *INDENT-ON* */
584
585 #ifdef __cplusplus
586 } /*extern "C"*/
587 #endif
588
589 #endif /*LV_DRAW_SW_ARM2D_H */
590