acid-drop

- Hacking the planet from a LilyGo T-Deck using custom firmware
git clone git://git.acid.vegas/acid-drop.git
Log | Files | Refs | Archive | README | LICENSE

lv_gpu_arm2d.c (37978B)

      1 /**
      2  * @file lv_gpu_arm2d.c
      3  *
      4  */
      5 
      6 /*********************
      7  *      INCLUDES
      8  *********************/
      9 #include "lv_gpu_arm2d.h"
     10 #include "../../core/lv_refr.h"
     11 
     12 #if LV_USE_GPU_ARM2D
     13 #include "arm_2d.h"
     14 
     15 /*********************
     16  *      DEFINES
     17  *********************/
     18 
     19 #if LV_COLOR_DEPTH == 16
     20 #define arm_2d_fill_colour              arm_2d_rgb16_fill_colour
     21 #define arm_2d_fill_colour_with_alpha   arm_2d_rgb565_fill_colour_with_alpha
     22 #define arm_2d_fill_colour_with_mask    arm_2d_rgb565_fill_colour_with_mask
     23 #define arm_2d_fill_colour_with_mask_and_opacity                                \
     24     arm_2d_rgb565_fill_colour_with_mask_and_opacity
     25 #define arm_2d_tile_copy                arm_2d_rgb16_tile_copy
     26 #define arm_2d_alpha_blending           arm_2d_rgb565_alpha_blending
     27 #define arm_2d_tile_copy_with_src_mask  arm_2d_rgb565_tile_copy_with_src_mask
     28 #define arm_2d_color_t                  arm_2d_color_rgb565_t
     29 
     30 /* arm-2d direct mode apis */
     31 #define __arm_2d_impl_colour_filling    __arm_2d_impl_rgb16_colour_filling
     32 #define __arm_2d_impl_colour_filling_with_opacity                               \
     33     __arm_2d_impl_rgb565_colour_filling_with_opacity
     34 #define __arm_2d_impl_colour_filling_mask                                       \
     35     __arm_2d_impl_rgb565_colour_filling_mask
     36 #define __arm_2d_impl_colour_filling_mask_opacity                               \
     37     __arm_2d_impl_rgb565_colour_filling_mask_opacity
     38 #define __arm_2d_impl_copy              __arm_2d_impl_rgb16_copy
     39 #define __arm_2d_impl_alpha_blending    __arm_2d_impl_rgb565_alpha_blending
     40 #define __arm_2d_impl_src_msk_copy      __arm_2d_impl_rgb565_src_msk_copy
     41 #define __arm_2d_impl_src_chn_msk_copy  __arm_2d_impl_rgb565_src_chn_msk_copy
     42 #define color_int                       uint16_t
     43 
     44 #elif LV_COLOR_DEPTH == 32
     45 #define arm_2d_fill_colour              arm_2d_rgb32_fill_colour
     46 #define arm_2d_fill_colour_with_alpha   arm_2d_cccn888_fill_colour_with_alpha
     47 #define arm_2d_fill_colour_with_mask    arm_2d_cccn888_fill_colour_with_mask
     48 #define arm_2d_fill_colour_with_mask_and_opacity                                \
     49     arm_2d_cccn888_fill_colour_with_mask_and_opacity
     50 #define arm_2d_tile_copy                arm_2d_rgb32_tile_copy
     51 #define arm_2d_alpha_blending           arm_2d_cccn888_alpha_blending
     52 #define arm_2d_tile_copy_with_src_mask  arm_2d_cccn888_tile_copy_with_src_mask
     53 #define arm_2d_color_t                  arm_2d_color_cccn888_t
     54 
     55 /* arm-2d direct mode apis */
     56 #define __arm_2d_impl_colour_filling    __arm_2d_impl_rgb32_colour_filling
     57 #define __arm_2d_impl_colour_filling_with_opacity                               \
     58     __arm_2d_impl_cccn888_colour_filling_with_opacity
     59 #define __arm_2d_impl_colour_filling_mask                                       \
     60     __arm_2d_impl_cccn888_colour_filling_mask
     61 #define __arm_2d_impl_colour_filling_mask_opacity                               \
     62     __arm_2d_impl_cccn888_colour_filling_mask_opacity
     63 #define __arm_2d_impl_copy              __arm_2d_impl_rgb32_copy
     64 #define __arm_2d_impl_alpha_blending    __arm_2d_impl_cccn888_alpha_blending
     65 #define __arm_2d_impl_src_msk_copy      __arm_2d_impl_cccn888_src_msk_copy
     66 #define __arm_2d_impl_src_chn_msk_copy  __arm_2d_impl_cccn888_src_chn_msk_copy
     67 #define color_int                       uint32_t
     68 
     69 #else
     70 #error The specified LV_COLOR_DEPTH is not supported by this version of lv_gpu_arm2d.c.
     71 #endif
     72 
     73 /**********************
     74  *      TYPEDEFS
     75  **********************/
     76 
     77 /**********************
     78  *  STATIC PROTOTYPES
     79  **********************/
     80 
     81 #if __ARM_2D_HAS_HW_ACC__
     82 LV_ATTRIBUTE_FAST_MEM
     83 static bool lv_draw_arm2d_fill_colour(const arm_2d_tile_t * target_tile,
     84                                       const arm_2d_region_t * region,
     85                                       lv_color_t color,
     86                                       lv_opa_t opa,
     87                                       const arm_2d_tile_t * mask_tile);
     88 
     89 LV_ATTRIBUTE_FAST_MEM
     90 static bool lv_draw_arm2d_tile_copy(const arm_2d_tile_t * target_tile,
     91                                     const arm_2d_region_t * region,
     92                                     arm_2d_tile_t * source_tile,
     93                                     lv_opa_t opa,
     94                                     arm_2d_tile_t * mask_tile);
     95 #else
     96 
     97 /* arm-2d direct mode APIs */
     98 extern
     99 void __arm_2d_impl_colour_filling(color_int * __RESTRICT pTarget,
    100                                   int16_t iTargetStride,
    101                                   arm_2d_size_t * __RESTRICT ptCopySize,
    102                                   color_int Colour);
    103 
    104 extern
    105 void __arm_2d_impl_colour_filling_with_opacity(
    106     color_int * __RESTRICT pTargetBase,
    107     int16_t iTargetStride,
    108     arm_2d_size_t * __RESTRICT ptCopySize,
    109     color_int Colour,
    110     uint_fast8_t chRatio);
    111 
    112 extern
    113 void __arm_2d_impl_colour_filling_mask(
    114     color_int * __RESTRICT pTarget,
    115     int16_t iTargetStride,
    116     uint8_t * __RESTRICT pchAlpha,
    117     int16_t iAlphaStride,
    118     arm_2d_size_t * __RESTRICT ptCopySize,
    119     color_int Colour);
    120 
    121 extern
    122 void __arm_2d_impl_colour_filling_mask_opacity(
    123     color_int * __RESTRICT pTarget,
    124     int16_t iTargetStride,
    125     uint8_t * __RESTRICT pchAlpha,
    126     int16_t iAlphaStride,
    127     arm_2d_size_t * __RESTRICT ptCopySize,
    128     color_int Colour,
    129     uint8_t chOpacity);
    130 
    131 extern
    132 void __arm_2d_impl_copy(color_int * __RESTRICT pSource,
    133                         int16_t iSourceStride,
    134                         color_int * __RESTRICT pTarget,
    135                         int16_t iTargetStride,
    136                         arm_2d_size_t * __RESTRICT ptCopySize);
    137 
    138 extern
    139 void __arm_2d_impl_alpha_blending(color_int * __RESTRICT pSource,
    140                                   int16_t iSourceStride,
    141                                   color_int * __RESTRICT pTarget,
    142                                   int16_t iTargetStride,
    143                                   arm_2d_size_t * __RESTRICT ptCopySize,
    144                                   uint_fast8_t chRatio);
    145 
    146 extern
    147 void __arm_2d_impl_gray8_alpha_blending(uint8_t * __RESTRICT pSource,
    148                                         int16_t iSourceStride,
    149                                         uint8_t * __RESTRICT pTarget,
    150                                         int16_t iTargetStride,
    151                                         arm_2d_size_t * __RESTRICT ptCopySize,
    152                                         uint_fast8_t chRatio);
    153 
    154 extern
    155 void __arm_2d_impl_src_msk_copy(color_int * __RESTRICT pSourceBase,
    156                                 int16_t iSourceStride,
    157                                 uint8_t * __RESTRICT ptSourceMaskBase,
    158                                 int16_t iSourceMaskStride,
    159                                 arm_2d_size_t * __RESTRICT ptSourceMaskSize,
    160                                 color_int * __RESTRICT pTargetBase,
    161                                 int16_t iTargetStride,
    162                                 arm_2d_size_t * __RESTRICT ptCopySize);
    163 
    164 extern
    165 void __arm_2d_impl_src_chn_msk_copy(color_int * __RESTRICT pSourceBase,
    166                                     int16_t iSourceStride,
    167                                     uint32_t * __RESTRICT ptSourceMaskBase,
    168                                     int16_t iSourceMaskStride,
    169                                     arm_2d_size_t * __RESTRICT ptSourceMaskSize,
    170                                     color_int * __RESTRICT pTargetBase,
    171                                     int16_t iTargetStride,
    172                                     arm_2d_size_t * __RESTRICT ptCopySize);
    173 
    174 LV_ATTRIBUTE_FAST_MEM
    175 static bool arm_2d_fill_normal(lv_color_t * dest_buf,
    176                                const lv_area_t * dest_area,
    177                                lv_coord_t dest_stride,
    178                                lv_color_t color,
    179                                lv_opa_t opa,
    180                                const lv_opa_t * mask,
    181                                lv_coord_t mask_stride);
    182 
    183 LV_ATTRIBUTE_FAST_MEM
    184 static bool arm_2d_copy_normal(lv_color_t * dest_buf,
    185                                const lv_area_t * dest_area,
    186                                lv_coord_t dest_stride,
    187                                const lv_color_t * src_buf,
    188                                lv_coord_t src_stride,
    189                                lv_opa_t opa,
    190                                const lv_opa_t * mask,
    191                                lv_coord_t mask_stride);
    192 #endif
    193 
    194 LV_ATTRIBUTE_FAST_MEM
    195 static void lv_draw_arm2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc);
    196 LV_ATTRIBUTE_FAST_MEM
    197 static void lv_gpu_arm2d_wait_cb(lv_draw_ctx_t * draw_ctx);
    198 LV_ATTRIBUTE_FAST_MEM
    199 static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx,
    200                                       const lv_draw_img_dsc_t * draw_dsc,
    201                                       const lv_area_t * coords,
    202                                       const uint8_t * src_buf,
    203                                       lv_img_cf_t cf);
    204 
    205 
    206 
    207 /**********************
    208  *  STATIC VARIABLES
    209  **********************/
    210 
    211 /**********************
    212  *      MACROS
    213  **********************/
    214 
    215 /**********************
    216  *   GLOBAL FUNCTIONS
    217  **********************/
    218 
    219 void lv_draw_arm2d_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
    220 {
    221     arm_2d_init();
    222 
    223     lv_draw_sw_init_ctx(drv, draw_ctx);
    224 
    225     lv_draw_arm2d_ctx_t * arm2d_draw_ctx = (lv_draw_sw_ctx_t *)draw_ctx;
    226 
    227     arm2d_draw_ctx->blend = lv_draw_arm2d_blend;
    228     arm2d_draw_ctx->base_draw.wait_for_finish = lv_gpu_arm2d_wait_cb;
    229 
    230 #if !__ARM_2D_HAS_HW_ACC__
    231     arm2d_draw_ctx->base_draw.draw_img_decoded = lv_draw_arm2d_img_decoded;
    232 #endif
    233 
    234 }
    235 
    236 void lv_draw_arm2d_ctx_deinit(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
    237 {
    238     LV_UNUSED(drv);
    239     LV_UNUSED(draw_ctx);
    240 }
    241 
    242 extern void test_flush(lv_color_t * color_p);
    243 
    244 #if __ARM_2D_HAS_HW_ACC__
    245 LV_ATTRIBUTE_FAST_MEM
    246 static void lv_draw_arm2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc)
    247 {
    248     const lv_opa_t * mask;
    249     if(dsc->mask_buf == NULL) mask = NULL;
    250     if(dsc->mask_buf && dsc->mask_res == LV_DRAW_MASK_RES_TRANSP) return;
    251     else if(dsc->mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask = NULL;
    252     else mask = dsc->mask_buf;
    253 
    254 
    255     lv_area_t blend_area;
    256     if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area)) {
    257         return;
    258     }
    259 
    260     static arm_2d_tile_t target_tile;
    261     static arm_2d_tile_t source_tile_orig;
    262     static arm_2d_tile_t source_tile;
    263     static arm_2d_tile_t mask_tile_orig;
    264     static arm_2d_tile_t mask_tile;
    265     static arm_2d_region_t target_region;
    266 
    267     bool is_accelerated = false;
    268 
    269     if(dsc->blend_mode == LV_BLEND_MODE_NORMAL
    270        &&    lv_area_get_size(&blend_area) > 100) {
    271 
    272         lv_color_t * dest_buf = draw_ctx->buf;
    273 
    274 
    275         target_tile = (arm_2d_tile_t) {
    276             .tRegion = {
    277                 .tSize = {
    278                     .iWidth = lv_area_get_width(draw_ctx->buf_area),
    279                     .iHeight = lv_area_get_height(draw_ctx->buf_area),
    280                 },
    281             },
    282             .tInfo.bIsRoot = true,
    283             .phwBuffer = (uint16_t *)draw_ctx->buf,
    284         };
    285 
    286         target_region = (arm_2d_region_t) {
    287             .tLocation = {
    288                 .iX = blend_area.x1 - draw_ctx->buf_area->x1,
    289                 .iY = blend_area.y1 - draw_ctx->buf_area->y1,
    290             },
    291             .tSize = {
    292                 .iWidth = lv_area_get_width(&blend_area),
    293                 .iHeight = lv_area_get_height(&blend_area),
    294             },
    295         };
    296 
    297         if(NULL != mask) {
    298             mask_tile_orig = (arm_2d_tile_t) {
    299                 .tRegion = {
    300                     .tSize = {
    301                         .iWidth = lv_area_get_width(dsc->mask_area),
    302                         .iHeight = lv_area_get_height(dsc->mask_area),
    303                     },
    304                 },
    305                 .tInfo = {
    306                     .bIsRoot = true,
    307                     .bHasEnforcedColour = true,
    308                     .tColourInfo = {
    309                         .chScheme = ARM_2D_COLOUR_8BIT,
    310                     },
    311                 },
    312                 .pchBuffer = (uint8_t *)mask,
    313             };
    314 
    315             arm_2d_tile_generate_child(
    316                 &mask_tile_orig,
    317             (arm_2d_region_t []) {
    318                 {
    319                     .tLocation = {
    320                         .iX = dsc->mask_area->x1 - blend_area.x1,
    321                         .iY = dsc->mask_area->y1 - blend_area.y1,
    322                     },
    323                     .tSize = mask_tile_orig.tRegion.tSize,
    324                 }
    325             },
    326             &mask_tile,
    327             false);
    328             mask_tile.tInfo.bDerivedResource = true;
    329         }
    330 
    331 
    332         const lv_color_t * src_buf = dsc->src_buf;
    333         if(src_buf) {
    334             source_tile_orig = (arm_2d_tile_t) {
    335                 .tRegion = {
    336                     .tSize = {
    337                         .iWidth = lv_area_get_width(dsc->blend_area),
    338                         .iHeight = lv_area_get_height(dsc->blend_area),
    339                     },
    340                 },
    341                 .tInfo.bIsRoot = true,
    342                 .phwBuffer = (uint16_t *)src_buf,
    343             };
    344 
    345             arm_2d_tile_generate_child(
    346                 &source_tile_orig,
    347             (arm_2d_region_t []) {
    348                 {
    349                     .tLocation = {
    350                         .iX = blend_area.x1 - dsc->blend_area->x1,
    351                         .iY = blend_area.y1 - dsc->blend_area->y1,
    352                     },
    353                     .tSize = source_tile_orig.tRegion.tSize,
    354                 }
    355             },
    356             &source_tile,
    357             false);
    358             source_tile.tInfo.bDerivedResource = true;
    359 
    360             is_accelerated = lv_draw_arm2d_tile_copy(
    361                                  &target_tile,
    362                                  &target_region,
    363                                  &source_tile,
    364                                  dsc->opa,
    365                                  (NULL == mask) ? NULL : &mask_tile);
    366         }
    367         else {
    368             is_accelerated = lv_draw_arm2d_fill_colour(
    369                                  &target_tile,
    370                                  &target_region,
    371                                  dsc->color,
    372                                  dsc->opa,
    373                                  (NULL == mask) ? NULL : &mask_tile);
    374         }
    375     }
    376 
    377     if(!is_accelerated) {
    378         lv_draw_sw_blend_basic(draw_ctx, dsc);
    379     }
    380 }
    381 
    382 
    383 LV_ATTRIBUTE_FAST_MEM
    384 static bool lv_draw_arm2d_fill_colour(const arm_2d_tile_t * target_tile,
    385                                       const arm_2d_region_t * region,
    386                                       lv_color_t color,
    387                                       lv_opa_t opa,
    388                                       const arm_2d_tile_t * mask_tile)
    389 {
    390     arm_fsm_rt_t result = (arm_fsm_rt_t)ARM_2D_ERR_NONE;
    391 
    392     if(NULL == mask_tile) {
    393         if(opa >= LV_OPA_MAX) {
    394             result = arm_2d_fill_colour(target_tile, region, color.full);
    395         }
    396         else {
    397 #if LV_COLOR_SCREEN_TRANSP
    398             return false;
    399 #else
    400             result = arm_2d_fill_colour_with_alpha(
    401                          target_tile,
    402                          region,
    403             (arm_2d_color_t) {
    404                 color.full
    405             },
    406             opa);
    407 #endif
    408         }
    409     }
    410     else {
    411 
    412         if(opa >= LV_OPA_MAX) {
    413             result = arm_2d_fill_colour_with_mask(
    414                          target_tile,
    415                          region,
    416                          mask_tile,
    417             (arm_2d_color_t) {
    418                 color.full
    419             });
    420         }
    421         else {
    422 #if LV_COLOR_SCREEN_TRANSP
    423             return false;
    424 #else
    425             result = arm_2d_fill_colour_with_mask_and_opacity(
    426                          target_tile,
    427                          region,
    428                          mask_tile,
    429             (arm_2d_color_t) {
    430                 color.full
    431             },
    432             opa);
    433 #endif
    434         }
    435     }
    436 
    437     if(result < 0) {
    438         /* error detected */
    439         return false;
    440     }
    441 
    442     return true;
    443 
    444 }
    445 
    446 LV_ATTRIBUTE_FAST_MEM
    447 static bool lv_draw_arm2d_tile_copy(const arm_2d_tile_t * target_tile,
    448                                     const arm_2d_region_t * region,
    449                                     arm_2d_tile_t * source_tile,
    450                                     lv_opa_t opa,
    451                                     arm_2d_tile_t * mask_tile)
    452 {
    453     arm_fsm_rt_t result = (arm_fsm_rt_t)ARM_2D_ERR_NONE;
    454 
    455     if(NULL == mask_tile) {
    456         if(opa >= LV_OPA_MAX) {
    457             result = arm_2d_tile_copy(source_tile,
    458                                       target_tile,
    459                                       region,
    460                                       ARM_2D_CP_MODE_COPY);
    461         }
    462 #if LV_COLOR_SCREEN_TRANSP
    463         else {
    464             return false;  /* not supported */
    465         }
    466 #else
    467         else {
    468             result = arm_2d_alpha_blending(source_tile,
    469                                            target_tile,
    470                                            region,
    471                                            opa);
    472         }
    473 #endif
    474     }
    475     else {
    476 #if LV_COLOR_SCREEN_TRANSP
    477         return false;       /* not support */
    478 #else
    479 
    480         if(opa >= LV_OPA_MAX) {
    481             result = arm_2d_tile_copy_with_src_mask(source_tile,
    482                                                     mask_tile,
    483                                                     target_tile,
    484                                                     region,
    485                                                     ARM_2D_CP_MODE_COPY);
    486         }
    487         else {
    488             return false;
    489         }
    490 #endif
    491     }
    492 
    493     if(result < 0) {
    494         /* error detected */
    495         return false;
    496     }
    497 
    498     return true;
    499 }
    500 
    501 static void lv_gpu_arm2d_wait_cb(lv_draw_ctx_t * draw_ctx)
    502 {
    503     lv_disp_t * disp = _lv_refr_get_disp_refreshing();
    504 
    505     arm_2d_op_wait_async(NULL);
    506     if(disp->driver && disp->driver->wait_cb) {
    507         disp->driver->wait_cb(disp->driver);
    508     }
    509     lv_draw_sw_wait_for_finish(draw_ctx);
    510 }
    511 #else
    512 
    513 
    514 LV_ATTRIBUTE_FAST_MEM
    515 static void lv_draw_arm2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc)
    516 {
    517     const lv_opa_t * mask;
    518     if(dsc->mask_buf == NULL) mask = NULL;
    519     if(dsc->mask_buf && dsc->mask_res == LV_DRAW_MASK_RES_TRANSP) return;
    520     else if(dsc->mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask = NULL;
    521     else mask = dsc->mask_buf;
    522 
    523     lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area);
    524 
    525     lv_area_t blend_area;
    526     if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area)) return;
    527 
    528     lv_disp_t * disp = _lv_refr_get_disp_refreshing();
    529 
    530     bool is_accelerated = false;
    531     do {
    532         if(NULL != disp->driver->set_px_cb) {
    533             break;
    534         }
    535 
    536         lv_color_t * dest_buf = draw_ctx->buf;
    537         dest_buf += dest_stride * (blend_area.y1 - draw_ctx->buf_area->y1)
    538                     + (blend_area.x1 - draw_ctx->buf_area->x1);
    539 
    540         const lv_color_t * src_buf = dsc->src_buf;
    541         lv_coord_t src_stride;
    542         if(src_buf) {
    543             src_stride = lv_area_get_width(dsc->blend_area);
    544             src_buf += src_stride * (blend_area.y1 - dsc->blend_area->y1) + (blend_area.x1 - dsc->blend_area->x1);
    545         }
    546         else {
    547             src_stride = 0;
    548         }
    549 
    550         lv_coord_t mask_stride;
    551         if(mask) {
    552             mask_stride = lv_area_get_width(dsc->mask_area);
    553             mask += mask_stride * (dsc->mask_area->y1 - blend_area.y1) + (dsc->mask_area->x1 - blend_area.x1);
    554         }
    555         else {
    556             mask_stride = 0;
    557         }
    558 
    559         lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
    560 
    561 
    562         if(dsc->src_buf == NULL) {
    563             if(dsc->blend_mode == LV_BLEND_MODE_NORMAL) {
    564                 is_accelerated = arm_2d_fill_normal(dest_buf,
    565                                                     &blend_area,
    566                                                     dest_stride,
    567                                                     dsc->color,
    568                                                     dsc->opa,
    569                                                     mask,
    570                                                     mask_stride);
    571             }
    572 #if LV_DRAW_COMPLEX
    573             else {
    574                 break;
    575             }
    576 #endif
    577         }
    578         else {
    579 
    580             if(dsc->blend_mode == LV_BLEND_MODE_NORMAL) {
    581                 is_accelerated = arm_2d_copy_normal(dest_buf,
    582                                                     &blend_area,
    583                                                     dest_stride,
    584                                                     src_buf,
    585                                                     src_stride,
    586                                                     dsc->opa,
    587                                                     mask,
    588                                                     mask_stride);
    589             }
    590 #if LV_DRAW_COMPLEX
    591             else {
    592                 break;
    593             }
    594 #endif
    595         }
    596     } while(0);
    597 
    598     if(!is_accelerated) lv_draw_sw_blend_basic(draw_ctx, dsc);
    599 }
    600 
    601 LV_ATTRIBUTE_FAST_MEM
    602 static bool arm_2d_fill_normal(lv_color_t * dest_buf,
    603                                const lv_area_t * dest_area,
    604                                lv_coord_t dest_stride,
    605                                lv_color_t color,
    606                                lv_opa_t opa,
    607                                const lv_opa_t * mask,
    608                                lv_coord_t mask_stride)
    609 {
    610     arm_2d_size_t target_size = {
    611         .iWidth = lv_area_get_width(dest_area),
    612         .iHeight = lv_area_get_height(dest_area),
    613     };
    614 
    615     /*No mask*/
    616     if(mask == NULL) {
    617         if(opa >= LV_OPA_MAX) {
    618             __arm_2d_impl_colour_filling((color_int *)dest_buf,
    619                                          dest_stride,
    620                                          &target_size,
    621                                          color.full);
    622         }
    623         /*Has opacity*/
    624         else {
    625 #if LV_COLOR_SCREEN_TRANSP
    626             return false;
    627 #else
    628             __arm_2d_impl_colour_filling_with_opacity((color_int *)dest_buf,
    629                                                       dest_stride,
    630                                                       &target_size,
    631                                                       color.full,
    632                                                       opa);
    633 #endif
    634         }
    635     }
    636     /*Masked*/
    637     else {
    638         /*Only the mask matters*/
    639         if(opa >= LV_OPA_MAX) {
    640             __arm_2d_impl_colour_filling_mask((color_int *)dest_buf,
    641                                               dest_stride,
    642                                               (uint8_t *)mask,
    643                                               mask_stride,
    644                                               &target_size,
    645                                               color.full);
    646         }
    647         /*With opacity*/
    648         else {
    649 #if LV_COLOR_SCREEN_TRANSP
    650             return false;
    651 #else
    652             __arm_2d_impl_colour_filling_mask_opacity((color_int *)dest_buf,
    653                                                       dest_stride,
    654                                                       (uint8_t *)mask,
    655                                                       mask_stride,
    656                                                       &target_size,
    657                                                       color.full,
    658                                                       opa);
    659 #endif
    660         }
    661     }
    662 
    663     return true;
    664 }
    665 
    666 
    667 LV_ATTRIBUTE_FAST_MEM
    668 static bool arm_2d_copy_normal(lv_color_t * dest_buf,
    669                                const lv_area_t * dest_area,
    670                                lv_coord_t dest_stride,
    671                                const lv_color_t * src_buf,
    672                                lv_coord_t src_stride,
    673                                lv_opa_t opa,
    674                                const lv_opa_t * mask,
    675                                lv_coord_t mask_stride)
    676 
    677 {
    678     int32_t w = lv_area_get_width(dest_area);
    679     int32_t h = lv_area_get_height(dest_area);
    680 
    681     arm_2d_size_t copy_size = {
    682         .iWidth = lv_area_get_width(dest_area),
    683         .iHeight = lv_area_get_height(dest_area),
    684     };
    685 
    686 #if LV_COLOR_SCREEN_TRANSP
    687     lv_disp_t * disp = _lv_refr_get_disp_refreshing();
    688 #endif
    689 
    690     /*Simple fill (maybe with opacity), no masking*/
    691     if(mask == NULL) {
    692         if(opa >= LV_OPA_MAX) {
    693             __arm_2d_impl_copy((color_int *)src_buf,
    694                                src_stride,
    695                                (color_int *)dest_buf,
    696                                dest_stride,
    697                                &copy_size);
    698         }
    699         else {
    700 #if LV_COLOR_SCREEN_TRANSP
    701             return false;
    702 #else
    703             __arm_2d_impl_alpha_blending((color_int *)src_buf,
    704                                          src_stride,
    705                                          (color_int *)dest_buf,
    706                                          dest_stride,
    707                                          &copy_size,
    708                                          opa);
    709 #endif
    710         }
    711     }
    712     /*Masked*/
    713     else {
    714         /*Only the mask matters*/
    715         if(opa > LV_OPA_MAX) {
    716 #if LV_COLOR_SCREEN_TRANSP
    717             return false;
    718 #else
    719             __arm_2d_impl_src_msk_copy((color_int *)src_buf,
    720                                        src_stride,
    721                                        (uint8_t *)mask,
    722                                        mask_stride,
    723                                        &copy_size,
    724                                        (color_int *)dest_buf,
    725                                        dest_stride,
    726                                        &copy_size);
    727 #endif
    728         }
    729         /*Handle opa and mask values too*/
    730         else {
    731 #if LV_COLOR_SCREEN_TRANSP
    732             return false;
    733 #else
    734             __arm_2d_impl_gray8_alpha_blending((uint8_t *)mask,
    735                                                mask_stride,
    736                                                (uint8_t *)mask,
    737                                                mask_stride,
    738                                                &copy_size,
    739                                                opa);
    740 
    741             __arm_2d_impl_src_msk_copy((color_int *)src_buf,
    742                                        src_stride,
    743                                        (uint8_t *)mask,
    744                                        mask_stride,
    745                                        &copy_size,
    746                                        (color_int *)dest_buf,
    747                                        dest_stride,
    748                                        &copy_size);
    749 #endif
    750         }
    751     }
    752 
    753     return true;
    754 }
    755 
    756 
    757 
    758 LV_ATTRIBUTE_FAST_MEM
    759 static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx,
    760                                       const lv_draw_img_dsc_t * draw_dsc,
    761                                       const lv_area_t * coords,
    762                                       const uint8_t * src_buf,
    763                                       lv_img_cf_t cf)
    764 {
    765     bool mask_any = lv_draw_mask_is_any(draw_ctx->clip_area);
    766 
    767     /*The simplest case just copy the pixels into the draw_buf*/
    768     if(!mask_any && draw_dsc->angle == 0 && draw_dsc->zoom == LV_IMG_ZOOM_NONE &&
    769        cf == LV_IMG_CF_TRUE_COLOR && draw_dsc->recolor_opa == LV_OPA_TRANSP) {
    770 
    771         lv_draw_sw_img_decoded(draw_ctx, draw_dsc, coords, src_buf, cf);
    772         return ;
    773     }
    774     /*In the other cases every pixel need to be checked one-by-one*/
    775     else {
    776         /*Use the clip area as draw area*/
    777         lv_area_t draw_area;
    778         lv_area_copy(&draw_area, draw_ctx->clip_area);
    779 
    780         lv_draw_sw_blend_dsc_t blend_dsc;
    781         lv_memset_00(&blend_dsc, sizeof(blend_dsc));
    782         blend_dsc.opa = draw_dsc->opa;
    783         blend_dsc.blend_mode = draw_dsc->blend_mode;
    784 
    785 
    786         //#if LV_DRAW_COMPLEX
    787         /*The pixel size in byte is different if an alpha byte is added too*/
    788         uint8_t px_size_byte = cf == LV_IMG_CF_TRUE_COLOR_ALPHA ? LV_IMG_PX_SIZE_ALPHA_BYTE : sizeof(lv_color_t);
    789 
    790         /*Go to the first displayed pixel of the map*/
    791         int32_t src_stride = lv_area_get_width(coords);
    792 
    793         lv_color_t c;
    794         lv_color_t chroma_keyed_color = LV_COLOR_CHROMA_KEY;
    795         uint32_t px_i = 0;
    796 
    797         const uint8_t * map_px;
    798 
    799         lv_coord_t draw_area_h = lv_area_get_height(&draw_area);
    800         lv_coord_t draw_area_w = lv_area_get_width(&draw_area);
    801 
    802         lv_area_t blend_area;
    803         blend_area.x1 = draw_area.x1;
    804         blend_area.x2 = draw_area.x2;
    805         blend_area.y1 = draw_area.y1;
    806         blend_area.y2 = blend_area.y1;
    807         blend_dsc.blend_area = &blend_area;
    808 
    809         bool transform = draw_dsc->angle != 0 || draw_dsc->zoom != LV_IMG_ZOOM_NONE ? true : false;
    810         /*Simple ARGB image. Handle it as special case because it's very common*/
    811         if(!mask_any && !transform && cf == LV_IMG_CF_TRUE_COLOR_ALPHA && draw_dsc->recolor_opa == LV_OPA_TRANSP) {
    812 
    813             const uint8_t * src_buf_tmp = src_buf;
    814             src_buf_tmp += src_stride * (draw_area.y1 - coords->y1) * px_size_byte;
    815             src_buf_tmp += (draw_area.x1 - coords->x1) * px_size_byte;
    816 
    817 #if LV_COLOR_DEPTH == 32
    818             if(blend_dsc.opa >= LV_OPA_MAX) {
    819                 lv_area_t blend_area2;
    820                 if(!_lv_area_intersect(&blend_area2, &draw_area, draw_ctx->clip_area)) return;
    821 
    822                 int32_t w = lv_area_get_width(&blend_area2);
    823                 int32_t h = lv_area_get_height(&blend_area2);
    824 
    825                 lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area);
    826 
    827                 lv_color_t * dest_buf = draw_ctx->buf;
    828                 dest_buf += dest_stride * (blend_area2.y1 - draw_ctx->buf_area->y1)
    829                             + (blend_area2.x1 - draw_ctx->buf_area->x1);
    830 
    831                 arm_2d_size_t copy_size = {
    832                     .iWidth = lv_area_get_width(&blend_area2),
    833                     .iHeight = lv_area_get_height(&blend_area2),
    834                 };
    835 
    836                 //lv_area_move(&blend_area2, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
    837 
    838                 __arm_2d_impl_src_chn_msk_copy(
    839                     (color_int *)src_buf_tmp,
    840                     src_stride,
    841                     (uint32_t *)((uintptr_t)src_buf_tmp + LV_IMG_PX_SIZE_ALPHA_BYTE - 1),
    842                     src_stride,
    843                     &copy_size,
    844                     (color_int *)dest_buf,
    845                     dest_stride,
    846                     &copy_size);
    847             }
    848             else
    849 #endif
    850             {
    851                 lv_draw_sw_img_decoded(draw_ctx, draw_dsc, coords, src_buf, cf);
    852                 return ;
    853             }
    854 
    855         }
    856         /*Most complicated case: transform or other mask or chroma keyed*/
    857         else {
    858             /*Build the image and a mask line-by-line*/
    859             uint32_t hor_res = (uint32_t) lv_disp_get_hor_res(_lv_refr_get_disp_refreshing());
    860             uint32_t mask_buf_size = lv_area_get_size(&draw_area) > hor_res ? hor_res : lv_area_get_size(&draw_area);
    861             lv_color_t * src_buf_rgb = lv_mem_buf_get(mask_buf_size * sizeof(lv_color_t));
    862             lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size);
    863             blend_dsc.mask_buf = mask_buf;
    864             blend_dsc.mask_area = &blend_area;
    865             blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED;
    866             blend_dsc.src_buf = src_buf_rgb;
    867 
    868             const uint8_t * src_buf_tmp = NULL;
    869 #if LV_DRAW_COMPLEX
    870             lv_img_transform_dsc_t trans_dsc;
    871             lv_memset_00(&trans_dsc, sizeof(lv_img_transform_dsc_t));
    872             if(transform) {
    873                 trans_dsc.cfg.angle = draw_dsc->angle;
    874                 trans_dsc.cfg.zoom = draw_dsc->zoom;
    875                 trans_dsc.cfg.src = src_buf;
    876                 trans_dsc.cfg.src_w = src_stride;
    877                 trans_dsc.cfg.src_h = lv_area_get_height(coords);
    878                 trans_dsc.cfg.cf = cf;
    879                 trans_dsc.cfg.pivot_x = draw_dsc->pivot.x;
    880                 trans_dsc.cfg.pivot_y = draw_dsc->pivot.y;
    881                 trans_dsc.cfg.color = draw_dsc->recolor;
    882                 trans_dsc.cfg.antialias = draw_dsc->antialias;
    883 
    884                 _lv_img_buf_transform_init(&trans_dsc);
    885             }
    886             else
    887 #endif
    888             {
    889                 src_buf_tmp = src_buf;
    890                 src_buf_tmp += src_stride * (draw_area.y1 - coords->y1) * px_size_byte;
    891                 src_buf_tmp += (draw_area.x1 - coords->x1) * px_size_byte;
    892             }
    893 
    894             uint16_t recolor_premult[3] = {0};
    895             lv_opa_t recolor_opa_inv = 255 - draw_dsc->recolor_opa;
    896             if(draw_dsc->recolor_opa != 0) {
    897                 lv_color_premult(draw_dsc->recolor, draw_dsc->recolor_opa, recolor_premult);
    898             }
    899 
    900             blend_dsc.mask_res = (cf != LV_IMG_CF_TRUE_COLOR || draw_dsc->angle ||
    901                                   draw_dsc->zoom != LV_IMG_ZOOM_NONE) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER;
    902 
    903             /*Prepare the `mask_buf`if there are other masks*/
    904             if(mask_any) {
    905                 lv_memset_ff(mask_buf, mask_buf_size);
    906             }
    907 
    908             int32_t x;
    909             int32_t y;
    910 #if LV_DRAW_COMPLEX
    911             int32_t rot_y = blend_area.y1 - coords->y1;
    912 #endif
    913             for(y = 0; y < draw_area_h; y++) {
    914                 map_px = src_buf_tmp;
    915 #if LV_DRAW_COMPLEX
    916                 uint32_t px_i_start = px_i;
    917                 int32_t rot_x = blend_area.x1 - coords->x1;
    918 #endif
    919 
    920                 for(x = 0; x < draw_area_w; x++, px_i++, map_px += px_size_byte) {
    921 
    922 #if LV_DRAW_COMPLEX
    923                     if(transform) {
    924 
    925                         /*Transform*/
    926                         bool ret;
    927                         ret = _lv_img_buf_transform(&trans_dsc, rot_x + x, rot_y + y);
    928                         if(ret == false) {
    929                             mask_buf[px_i] = LV_OPA_TRANSP;
    930                             continue;
    931                         }
    932                         else {
    933                             mask_buf[px_i] = trans_dsc.res.opa;
    934                             c.full = trans_dsc.res.color.full;
    935                         }
    936                     }
    937                     /*No transform*/
    938                     else
    939 #endif
    940                     {
    941                         if(cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
    942                             lv_opa_t px_opa = map_px[LV_IMG_PX_SIZE_ALPHA_BYTE - 1];
    943                             mask_buf[px_i] = px_opa;
    944                             if(px_opa == 0) {
    945 #if  LV_COLOR_DEPTH == 32
    946                                 src_buf_rgb[px_i].full = 0;
    947 #endif
    948                                 continue;
    949                             }
    950                         }
    951                         else {
    952                             mask_buf[px_i] = 0xFF;
    953                         }
    954 
    955 #if LV_COLOR_DEPTH == 1
    956                         c.full = map_px[0];
    957 #elif LV_COLOR_DEPTH == 8
    958                         c.full = map_px[0];
    959 #elif LV_COLOR_DEPTH == 16
    960                         c.full = map_px[0] + (map_px[1] << 8);
    961 #elif LV_COLOR_DEPTH == 32
    962                         c.full = *((uint32_t *)map_px);
    963                         c.ch.alpha = 0xFF;
    964 #endif
    965                         if(cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) {
    966                             if(c.full == chroma_keyed_color.full) {
    967                                 mask_buf[px_i] = LV_OPA_TRANSP;
    968 #if  LV_COLOR_DEPTH == 32
    969                                 src_buf_rgb[px_i].full = 0;
    970 #endif
    971                                 continue;
    972                             }
    973                         }
    974 
    975                     }
    976                     if(draw_dsc->recolor_opa != 0) {
    977                         c = lv_color_mix_premult(recolor_premult, c, recolor_opa_inv);
    978                     }
    979 
    980                     src_buf_rgb[px_i].full = c.full;
    981                 }
    982 #if LV_DRAW_COMPLEX
    983                 /*Apply the masks if any*/
    984                 if(mask_any) {
    985                     lv_draw_mask_res_t mask_res_sub;
    986                     mask_res_sub = lv_draw_mask_apply(mask_buf + px_i_start, blend_area.x1,
    987                                                       y + draw_area.y1, draw_area_w);
    988                     if(mask_res_sub == LV_DRAW_MASK_RES_TRANSP) {
    989                         lv_memset_00(mask_buf + px_i_start, draw_area_w);
    990                         blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED;
    991                     }
    992                     else if(mask_res_sub == LV_DRAW_MASK_RES_CHANGED) {
    993                         blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED;
    994                     }
    995                 }
    996 #endif
    997 
    998                 src_buf_tmp += src_stride * px_size_byte;
    999                 if(px_i + draw_area_w < mask_buf_size) {
   1000                     blend_area.y2 ++;
   1001                 }
   1002                 else {
   1003                     lv_draw_sw_blend(draw_ctx, &blend_dsc);
   1004 
   1005                     blend_area.y1 = blend_area.y2 + 1;
   1006                     blend_area.y2 = blend_area.y1;
   1007 
   1008                     px_i = 0;
   1009                     blend_dsc.mask_res = (cf != LV_IMG_CF_TRUE_COLOR || draw_dsc->angle ||
   1010                                           draw_dsc->zoom != LV_IMG_ZOOM_NONE) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER;
   1011 
   1012                     /*Prepare the `mask_buf`if there are other masks*/
   1013                     if(mask_any) {
   1014                         lv_memset_ff(mask_buf, mask_buf_size);
   1015                     }
   1016                 }
   1017             }
   1018 
   1019             /*Flush the last part*/
   1020             if(blend_area.y1 != blend_area.y2) {
   1021                 blend_area.y2--;
   1022                 lv_draw_sw_blend(draw_ctx, &blend_dsc);
   1023             }
   1024 
   1025             lv_mem_buf_release(mask_buf);
   1026             lv_mem_buf_release(src_buf_rgb);
   1027         }
   1028     }
   1029 }
   1030 
   1031 
   1032 
   1033 static void lv_gpu_arm2d_wait_cb(lv_draw_ctx_t * draw_ctx)
   1034 {
   1035     lv_disp_t * disp = _lv_refr_get_disp_refreshing();
   1036 
   1037     if(disp->driver && disp->driver->wait_cb) {
   1038         disp->driver->wait_cb(disp->driver);
   1039     }
   1040     lv_draw_sw_wait_for_finish(draw_ctx);
   1041 }
   1042 
   1043 
   1044 #endif
   1045 
   1046 
   1047 /**********************
   1048  *   STATIC FUNCTIONS
   1049  **********************/
   1050 
   1051 #if 0
   1052 static void invalidate_cache(void)
   1053 {
   1054     lv_disp_t * disp = _lv_refr_get_disp_refreshing();
   1055     if(disp->driver->clean_dcache_cb) disp->driver->clean_dcache_cb(disp->driver);
   1056     else {
   1057 #if __CORTEX_M >= 0x07
   1058         if((SCB->CCR) & (uint32_t)SCB_CCR_DC_Msk)
   1059             SCB_CleanInvalidateDCache();
   1060 #endif
   1061     }
   1062 }
   1063 #endif
   1064 
   1065 #endif