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_draw_sw_img.c (12267B)

      1 /**
      2  * @file lv_draw_img.c
      3  *
      4  */
      5 
      6 /*********************
      7  *      INCLUDES
      8  *********************/
      9 #include "lv_draw_sw.h"
     10 #include "../lv_img_cache.h"
     11 #include "../../hal/lv_hal_disp.h"
     12 #include "../../misc/lv_log.h"
     13 #include "../../core/lv_refr.h"
     14 #include "../../misc/lv_mem.h"
     15 #include "../../misc/lv_math.h"
     16 
     17 /*********************
     18  *      DEFINES
     19  *********************/
     20 
     21 /**********************
     22  *      TYPEDEFS
     23  **********************/
     24 
     25 /**********************
     26  *  STATIC PROTOTYPES
     27  **********************/
     28 
     29 /**********************
     30  *  STATIC VARIABLES
     31  **********************/
     32 
     33 /**********************
     34  *      MACROS
     35  **********************/
     36 
     37 /**********************
     38  *   GLOBAL FUNCTIONS
     39  **********************/
     40 
     41 LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_img_decoded(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * draw_dsc,
     42                                                   const lv_area_t * coords, const uint8_t * src_buf, lv_img_cf_t cf)
     43 {
     44     /*Use the clip area as draw area*/
     45     lv_area_t draw_area;
     46     lv_area_copy(&draw_area, draw_ctx->clip_area);
     47 
     48     bool mask_any = lv_draw_mask_is_any(&draw_area);
     49 
     50     lv_draw_sw_blend_dsc_t blend_dsc;
     51     lv_memset_00(&blend_dsc, sizeof(blend_dsc));
     52     blend_dsc.opa = draw_dsc->opa;
     53     blend_dsc.blend_mode = draw_dsc->blend_mode;
     54 
     55     /*The simplest case just copy the pixels into the draw_buf*/
     56     if(!mask_any && draw_dsc->angle == 0 && draw_dsc->zoom == LV_IMG_ZOOM_NONE &&
     57        cf == LV_IMG_CF_TRUE_COLOR && draw_dsc->recolor_opa == LV_OPA_TRANSP) {
     58         blend_dsc.blend_area = coords;
     59         blend_dsc.src_buf = (const lv_color_t *)src_buf;
     60         lv_draw_sw_blend(draw_ctx, &blend_dsc);
     61     }
     62     /*In the other cases every pixel need to be checked one-by-one*/
     63     else {
     64         //#if LV_DRAW_COMPLEX
     65         /*The pixel size in byte is different if an alpha byte is added too*/
     66         uint8_t px_size_byte = cf == LV_IMG_CF_TRUE_COLOR_ALPHA ? LV_IMG_PX_SIZE_ALPHA_BYTE : sizeof(lv_color_t);
     67 
     68         /*Go to the first displayed pixel of the map*/
     69         int32_t src_stride = lv_area_get_width(coords);
     70 
     71         lv_color_t c;
     72         lv_color_t chroma_keyed_color = LV_COLOR_CHROMA_KEY;
     73         uint32_t px_i = 0;
     74 
     75         const uint8_t * map_px;
     76 
     77         lv_coord_t draw_area_h = lv_area_get_height(&draw_area);
     78         lv_coord_t draw_area_w = lv_area_get_width(&draw_area);
     79 
     80         lv_area_t blend_area;
     81         blend_area.x1 = draw_area.x1;
     82         blend_area.x2 = draw_area.x2;
     83         blend_area.y1 = draw_area.y1;
     84         blend_area.y2 = blend_area.y1;
     85         blend_dsc.blend_area = &blend_area;
     86 
     87         bool transform = draw_dsc->angle != 0 || draw_dsc->zoom != LV_IMG_ZOOM_NONE ? true : false;
     88         /*Simple ARGB image. Handle it as special case because it's very common*/
     89         if(!mask_any && !transform && cf == LV_IMG_CF_TRUE_COLOR_ALPHA && draw_dsc->recolor_opa == LV_OPA_TRANSP) {
     90             uint32_t hor_res = (uint32_t) lv_disp_get_hor_res(_lv_refr_get_disp_refreshing());
     91             uint32_t mask_buf_size = lv_area_get_size(&draw_area) > (uint32_t) hor_res ? hor_res : lv_area_get_size(&draw_area);
     92             lv_color_t * src_buf_rgb = lv_mem_buf_get(mask_buf_size * sizeof(lv_color_t));
     93             lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size);
     94             blend_dsc.mask_buf = mask_buf;
     95             blend_dsc.mask_area = &blend_area;
     96             blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED;
     97             blend_dsc.src_buf = src_buf_rgb;
     98 
     99             const uint8_t * src_buf_tmp = src_buf;
    100             src_buf_tmp += src_stride * (draw_area.y1 - coords->y1) * px_size_byte;
    101             src_buf_tmp += (draw_area.x1 - coords->x1) * px_size_byte;
    102 
    103             int32_t x;
    104             int32_t y;
    105             for(y = 0; y < draw_area_h; y++) {
    106                 map_px = src_buf_tmp;
    107                 for(x = 0; x < draw_area_w; x++, map_px += px_size_byte, px_i++) {
    108                     lv_opa_t px_opa = map_px[LV_IMG_PX_SIZE_ALPHA_BYTE - 1];
    109                     mask_buf[px_i] = px_opa;
    110                     if(px_opa) {
    111 #if LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1
    112                         src_buf_rgb[px_i].full = map_px[0];
    113 #elif LV_COLOR_DEPTH == 16
    114                         src_buf_rgb[px_i].full = map_px[0] + (map_px[1] << 8);
    115 #elif LV_COLOR_DEPTH == 32
    116                         src_buf_rgb[px_i].full = *((uint32_t *)map_px);
    117 #endif
    118                     }
    119 #if LV_COLOR_DEPTH == 32
    120                     src_buf_rgb[px_i].ch.alpha = 0xFF;
    121 #endif
    122                 }
    123 
    124                 src_buf_tmp += src_stride * px_size_byte;
    125                 if(px_i + draw_area_w <= mask_buf_size) {
    126                     blend_area.y2 ++;
    127                 }
    128                 else {
    129                     lv_draw_sw_blend(draw_ctx, &blend_dsc);
    130 
    131                     blend_area.y1 = blend_area.y2 + 1;
    132                     blend_area.y2 = blend_area.y1;
    133 
    134                     px_i = 0;
    135                 }
    136             }
    137             /*Flush the last part*/
    138             if(blend_area.y1 != blend_area.y2) {
    139                 blend_area.y2--;
    140                 lv_draw_sw_blend(draw_ctx, &blend_dsc);
    141             }
    142 
    143             lv_mem_buf_release(mask_buf);
    144             lv_mem_buf_release(src_buf_rgb);
    145         }
    146         /*Most complicated case: transform or other mask or chroma keyed*/
    147         else {
    148             /*Build the image and a mask line-by-line*/
    149             uint32_t hor_res = (uint32_t) lv_disp_get_hor_res(_lv_refr_get_disp_refreshing());
    150             uint32_t mask_buf_size = lv_area_get_size(&draw_area) > hor_res ? hor_res : lv_area_get_size(&draw_area);
    151             lv_color_t * src_buf_rgb = lv_mem_buf_get(mask_buf_size * sizeof(lv_color_t));
    152             lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size);
    153             blend_dsc.mask_buf = mask_buf;
    154             blend_dsc.mask_area = &blend_area;
    155             blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED;
    156             blend_dsc.src_buf = src_buf_rgb;
    157 
    158             const uint8_t * src_buf_tmp = NULL;
    159 #if LV_DRAW_COMPLEX
    160             lv_img_transform_dsc_t trans_dsc;
    161             lv_memset_00(&trans_dsc, sizeof(lv_img_transform_dsc_t));
    162             if(transform) {
    163                 trans_dsc.cfg.angle = draw_dsc->angle;
    164                 trans_dsc.cfg.zoom = draw_dsc->zoom;
    165                 trans_dsc.cfg.src = src_buf;
    166                 trans_dsc.cfg.src_w = src_stride;
    167                 trans_dsc.cfg.src_h = lv_area_get_height(coords);
    168                 trans_dsc.cfg.cf = cf;
    169                 trans_dsc.cfg.pivot_x = draw_dsc->pivot.x;
    170                 trans_dsc.cfg.pivot_y = draw_dsc->pivot.y;
    171                 trans_dsc.cfg.color = draw_dsc->recolor;
    172                 trans_dsc.cfg.antialias = draw_dsc->antialias;
    173 
    174                 _lv_img_buf_transform_init(&trans_dsc);
    175             }
    176             else
    177 #endif
    178             {
    179                 src_buf_tmp = src_buf;
    180                 src_buf_tmp += src_stride * (draw_area.y1 - coords->y1) * px_size_byte;
    181                 src_buf_tmp += (draw_area.x1 - coords->x1) * px_size_byte;
    182             }
    183 
    184             uint16_t recolor_premult[3] = {0};
    185             lv_opa_t recolor_opa_inv = 255 - draw_dsc->recolor_opa;
    186             if(draw_dsc->recolor_opa != 0) {
    187                 lv_color_premult(draw_dsc->recolor, draw_dsc->recolor_opa, recolor_premult);
    188             }
    189 
    190             blend_dsc.mask_res = (cf != LV_IMG_CF_TRUE_COLOR || draw_dsc->angle ||
    191                                   draw_dsc->zoom != LV_IMG_ZOOM_NONE) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER;
    192 
    193             /*Prepare the `mask_buf`if there are other masks*/
    194             if(mask_any) {
    195                 lv_memset_ff(mask_buf, mask_buf_size);
    196             }
    197 
    198             int32_t x;
    199             int32_t y;
    200 #if LV_DRAW_COMPLEX
    201             int32_t rot_y = blend_area.y1 - coords->y1;
    202 #endif
    203             for(y = 0; y < draw_area_h; y++) {
    204                 map_px = src_buf_tmp;
    205 #if LV_DRAW_COMPLEX
    206                 uint32_t px_i_start = px_i;
    207                 int32_t rot_x = blend_area.x1 - coords->x1;
    208 #endif
    209 
    210                 for(x = 0; x < draw_area_w; x++, px_i++, map_px += px_size_byte) {
    211 
    212 #if LV_DRAW_COMPLEX
    213                     if(transform) {
    214 
    215                         /*Transform*/
    216                         bool ret;
    217                         ret = _lv_img_buf_transform(&trans_dsc, rot_x + x, rot_y + y);
    218                         if(ret == false) {
    219                             mask_buf[px_i] = LV_OPA_TRANSP;
    220                             continue;
    221                         }
    222                         else {
    223                             mask_buf[px_i] = trans_dsc.res.opa;
    224                             c.full = trans_dsc.res.color.full;
    225                         }
    226                     }
    227                     /*No transform*/
    228                     else
    229 #endif
    230                     {
    231                         if(cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
    232                             lv_opa_t px_opa = map_px[LV_IMG_PX_SIZE_ALPHA_BYTE - 1];
    233                             mask_buf[px_i] = px_opa;
    234                             if(px_opa == 0) {
    235 #if  LV_COLOR_DEPTH == 32
    236                                 src_buf_rgb[px_i].full = 0;
    237 #endif
    238                                 continue;
    239                             }
    240                         }
    241                         else {
    242                             mask_buf[px_i] = 0xFF;
    243                         }
    244 
    245 #if LV_COLOR_DEPTH == 1
    246                         c.full = map_px[0];
    247 #elif LV_COLOR_DEPTH == 8
    248                         c.full = map_px[0];
    249 #elif LV_COLOR_DEPTH == 16
    250                         c.full = map_px[0] + (map_px[1] << 8);
    251 #elif LV_COLOR_DEPTH == 32
    252                         c.full = *((uint32_t *)map_px);
    253                         c.ch.alpha = 0xFF;
    254 #endif
    255                         if(cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) {
    256                             if(c.full == chroma_keyed_color.full) {
    257                                 mask_buf[px_i] = LV_OPA_TRANSP;
    258 #if  LV_COLOR_DEPTH == 32
    259                                 src_buf_rgb[px_i].full = 0;
    260 #endif
    261                                 continue;
    262                             }
    263                         }
    264 
    265                     }
    266                     if(draw_dsc->recolor_opa != 0) {
    267                         c = lv_color_mix_premult(recolor_premult, c, recolor_opa_inv);
    268                     }
    269 
    270                     src_buf_rgb[px_i].full = c.full;
    271                 }
    272 #if LV_DRAW_COMPLEX
    273                 /*Apply the masks if any*/
    274                 if(mask_any) {
    275                     lv_draw_mask_res_t mask_res_sub;
    276                     mask_res_sub = lv_draw_mask_apply(mask_buf + px_i_start, blend_area.x1,
    277                                                       y + draw_area.y1, draw_area_w);
    278                     if(mask_res_sub == LV_DRAW_MASK_RES_TRANSP) {
    279                         lv_memset_00(mask_buf + px_i_start, draw_area_w);
    280                         blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED;
    281                     }
    282                     else if(mask_res_sub == LV_DRAW_MASK_RES_CHANGED) {
    283                         blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED;
    284                     }
    285                 }
    286 #endif
    287 
    288                 src_buf_tmp += src_stride * px_size_byte;
    289                 if(px_i + draw_area_w < mask_buf_size) {
    290                     blend_area.y2 ++;
    291                 }
    292                 else {
    293                     lv_draw_sw_blend(draw_ctx, &blend_dsc);
    294 
    295                     blend_area.y1 = blend_area.y2 + 1;
    296                     blend_area.y2 = blend_area.y1;
    297 
    298                     px_i = 0;
    299                     blend_dsc.mask_res = (cf != LV_IMG_CF_TRUE_COLOR || draw_dsc->angle ||
    300                                           draw_dsc->zoom != LV_IMG_ZOOM_NONE) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER;
    301 
    302                     /*Prepare the `mask_buf`if there are other masks*/
    303                     if(mask_any) {
    304                         lv_memset_ff(mask_buf, mask_buf_size);
    305                     }
    306                 }
    307             }
    308 
    309             /*Flush the last part*/
    310             if(blend_area.y1 != blend_area.y2) {
    311                 blend_area.y2--;
    312                 lv_draw_sw_blend(draw_ctx, &blend_dsc);
    313             }
    314 
    315             lv_mem_buf_release(mask_buf);
    316             lv_mem_buf_release(src_buf_rgb);
    317         }
    318     }
    319 }
    320 
    321 /**********************
    322  *   STATIC FUNCTIONS
    323  **********************/