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 ©_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 ©_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 ©_size, 724 (color_int *)dest_buf, 725 dest_stride, 726 ©_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 ©_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 ©_size, 746 (color_int *)dest_buf, 747 dest_stride, 748 ©_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 ©_size, 844 (color_int *)dest_buf, 845 dest_stride, 846 ©_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