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 **********************/