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                     &copy_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                     &copy_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                     &copy_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                     &copy_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