From d87737612a5c7d7966ee06f6c80f66e2a64538e3 Mon Sep 17 00:00:00 2001 From: nicusorcitu <97085059+nicusorcitu@users.noreply.github.com> Date: Thu, 18 May 2023 23:43:19 +0300 Subject: [PATCH] perf(pxp, vglite): improve performance and add more features (#4222) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nicușor Cîțu Signed-off-by: Stefan Babatie Signed-off-by: Jason Yu Co-authored-by: Stefan Babatie Co-authored-by: Jason Yu --- docs/get-started/platforms/nxp.md | 4 + src/draw/nxp/pxp/lv_draw_pxp.c | 47 +++-- src/draw/nxp/pxp/lv_draw_pxp_blend.c | 84 ++++++-- src/draw/nxp/pxp/lv_draw_pxp_blend.h | 16 +- src/draw/nxp/pxp/lv_gpu_nxp_pxp.h | 2 +- src/draw/nxp/vglite/lv_draw_vglite.c | 125 ++++++++---- src/draw/nxp/vglite/lv_draw_vglite_arc.c | 4 + src/draw/nxp/vglite/lv_draw_vglite_blend.c | 217 ++++++++++++--------- src/draw/nxp/vglite/lv_draw_vglite_blend.h | 62 +++++- src/draw/nxp/vglite/lv_draw_vglite_line.c | 4 + src/draw/nxp/vglite/lv_draw_vglite_rect.c | 16 +- src/draw/nxp/vglite/lv_vglite_buf.c | 36 ++-- src/draw/nxp/vglite/lv_vglite_buf.h | 11 ++ src/draw/nxp/vglite/lv_vglite_utils.h | 34 ++++ 14 files changed, 477 insertions(+), 185 deletions(-) diff --git a/docs/get-started/platforms/nxp.md b/docs/get-started/platforms/nxp.md index 22587c54f..48e25d254 100644 --- a/docs/get-started/platforms/nxp.md +++ b/docs/get-started/platforms/nxp.md @@ -23,6 +23,7 @@ Supported draw callbacks are available in "src/draw/nxp/pxp/lv_draw_pxp.c": pxp_draw_ctx->base_draw.draw_img_decoded = lv_draw_pxp_img_decoded; pxp_draw_ctx->blend = lv_draw_pxp_blend; pxp_draw_ctx->base_draw.wait_for_finish = lv_draw_pxp_wait_for_finish; + pxp_draw_ctx->base_draw.buffer_copy = lv_draw_pxp_buffer_copy; ``` #### Features supported: @@ -35,6 +36,7 @@ Supported draw callbacks are available in "src/draw/nxp/pxp/lv_draw_pxp.c": - Color keying - Recoloring (color tint) - Image Rotation (90, 180, 270 degree) + - Buffer copy - RTOS integration layer - Default FreeRTOS and bare metal code provided @@ -114,6 +116,7 @@ Supported draw callbacks are available in "src/draw/nxp/vglite/lv_draw_vglite.c" vglite_draw_ctx->base_draw.draw_img_decoded = lv_draw_vglite_img_decoded; vglite_draw_ctx->blend = lv_draw_vglite_blend; vglite_draw_ctx->base_draw.wait_for_finish = lv_draw_vglite_wait_for_finish; + vglite_draw_ctx->base_draw.buffer_copy = lv_draw_vglite_buffer_copy; ``` #### Features supported: @@ -129,6 +132,7 @@ Supported draw callbacks are available in "src/draw/nxp/vglite/lv_draw_vglite.c" - Draw rectangle border/outline with optional rounded corners - Draw arc with optional rounded ending - Draw line or dashed line with optional rounded ending + - Buffer copy #### Known limitations: - Source image alignment: diff --git a/src/draw/nxp/pxp/lv_draw_pxp.c b/src/draw/nxp/pxp/lv_draw_pxp.c index a7084b408..cd70f48b2 100644 --- a/src/draw/nxp/pxp/lv_draw_pxp.c +++ b/src/draw/nxp/pxp/lv_draw_pxp.c @@ -59,10 +59,14 @@ static void lv_draw_pxp_wait_for_finish(lv_draw_ctx_t * draw_ctx); +static void lv_draw_pxp_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc); + static void lv_draw_pxp_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t cf); -static void lv_draw_pxp_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc); +static void lv_draw_pxp_buffer_copy(lv_draw_ctx_t * draw_ctx, + void * dest_buf, lv_coord_t dest_stride, const lv_area_t * dest_area, + void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area); /********************** * STATIC VARIABLES @@ -84,6 +88,7 @@ void lv_draw_pxp_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) pxp_draw_ctx->base_draw.draw_img_decoded = lv_draw_pxp_img_decoded; pxp_draw_ctx->blend = lv_draw_pxp_blend; pxp_draw_ctx->base_draw.wait_for_finish = lv_draw_pxp_wait_for_finish; + pxp_draw_ctx->base_draw.buffer_copy = lv_draw_pxp_buffer_copy; } void lv_draw_pxp_ctx_deinit(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) @@ -184,22 +189,28 @@ static void lv_draw_pxp_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_ return; } - lv_area_t blend_area; - /*Let's get the blend area which is the intersection of the area to draw and the clip area.*/ - if(!_lv_area_intersect(&blend_area, coords, draw_ctx->clip_area)) - return; /*Fully clipped, nothing to do*/ + lv_area_t rel_coords; + lv_area_copy(&rel_coords, coords); + lv_area_move(&rel_coords, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); - /*Make the blend area relative to the buffer*/ - lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); + lv_area_t rel_clip_area; + lv_area_copy(&rel_clip_area, draw_ctx->clip_area); + lv_area_move(&rel_clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); - lv_coord_t src_width = lv_area_get_width(coords); - lv_coord_t src_height = lv_area_get_height(coords); - - bool has_mask = lv_draw_mask_is_any(&blend_area); bool has_scale = (dsc->zoom != LV_IMG_ZOOM_NONE); bool has_rotation = (dsc->angle != 0); bool unsup_rotation = false; + lv_area_t blend_area; + if(has_rotation) + lv_area_copy(&blend_area, &rel_coords); + else if(!_lv_area_intersect(&blend_area, &rel_coords, &rel_clip_area)) + return; /*Fully clipped, nothing to do*/ + + bool has_mask = lv_draw_mask_is_any(&blend_area); + lv_coord_t src_width = lv_area_get_width(coords); + lv_coord_t src_height = lv_area_get_height(coords); + if(has_rotation) { /* * PXP can only rotate at 90x angles. @@ -247,4 +258,18 @@ static void lv_draw_pxp_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_ dsc, cf); } +static void lv_draw_pxp_buffer_copy(lv_draw_ctx_t * draw_ctx, + void * dest_buf, lv_coord_t dest_stride, const lv_area_t * dest_area, + void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area) +{ + LV_UNUSED(draw_ctx); + + if(lv_area_get_size(dest_area) < LV_GPU_NXP_PXP_SIZE_LIMIT) { + lv_draw_sw_buffer_copy(draw_ctx, dest_buf, dest_stride, dest_area, src_buf, src_stride, src_area); + return; + } + + lv_gpu_nxp_pxp_buffer_copy(dest_buf, dest_area, dest_stride, src_buf, src_area, src_stride); +} + #endif /*LV_USE_GPU_NXP_PXP*/ diff --git a/src/draw/nxp/pxp/lv_draw_pxp_blend.c b/src/draw/nxp/pxp/lv_draw_pxp_blend.c index a32c91710..82925769a 100644 --- a/src/draw/nxp/pxp/lv_draw_pxp_blend.c +++ b/src/draw/nxp/pxp/lv_draw_pxp_blend.c @@ -40,8 +40,6 @@ * DEFINES *********************/ -#define PXP_TEMP_BUF_SIZE LCD_WIDTH * LCD_HEIGHT * LCD_FB_BYTE_PER_PIXEL - #if LV_COLOR_16_SWAP #error Color swap not implemented. Disable LV_COLOR_16_SWAP feature. #endif @@ -50,10 +48,17 @@ #define PXP_OUT_PIXEL_FORMAT kPXP_OutputPixelFormatRGB565 #define PXP_AS_PIXEL_FORMAT kPXP_AsPixelFormatRGB565 #define PXP_PS_PIXEL_FORMAT kPXP_PsPixelFormatRGB565 + #define PXP_TEMP_BUF_SIZE LCD_WIDTH * LCD_HEIGHT * 2U #elif LV_COLOR_DEPTH == 32 #define PXP_OUT_PIXEL_FORMAT kPXP_OutputPixelFormatARGB8888 #define PXP_AS_PIXEL_FORMAT kPXP_AsPixelFormatARGB8888 - #define PXP_PS_PIXEL_FORMAT kPXP_PsPixelFormatRGB888 + #if (!(defined(FSL_FEATURE_PXP_HAS_NO_EXTEND_PIXEL_FORMAT) && FSL_FEATURE_PXP_HAS_NO_EXTEND_PIXEL_FORMAT)) && \ + (!(defined(FSL_FEATURE_PXP_V3) && FSL_FEATURE_PXP_V3)) + #define PXP_PS_PIXEL_FORMAT kPXP_PsPixelFormatARGB8888 + #else + #define PXP_PS_PIXEL_FORMAT kPXP_PsPixelFormatRGB888 + #endif + #define PXP_TEMP_BUF_SIZE LCD_WIDTH * LCD_HEIGHT * 4U #elif #error Only 16bit and 32bit color depth are supported. Set LV_COLOR_DEPTH to 16 or 32. #endif @@ -100,7 +105,7 @@ static void lv_pxp_blit_opa(lv_color_t * dest_buf, const lv_area_t * dest_area, * @param[in] dsc Image descriptor * @param[in] cf Color format */ -static void lv_pxp_blit_cover(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, +static void lv_pxp_blit_cover(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride, const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride, const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf); @@ -286,7 +291,7 @@ void lv_gpu_nxp_pxp_blit(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_ lv_gpu_nxp_pxp_run(); } -void lv_gpu_nxp_pxp_blit_transform(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, +void lv_gpu_nxp_pxp_blit_transform(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride, const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride, const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf) { @@ -308,6 +313,33 @@ void lv_gpu_nxp_pxp_blit_transform(lv_color_t * dest_buf, const lv_area_t * dest lv_pxp_blit_cf(dest_buf, dest_area, dest_stride, src_buf, src_area, src_stride, dsc, cf); } +void lv_gpu_nxp_pxp_buffer_copy(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, + const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride) +{ + lv_coord_t src_width = lv_area_get_width(src_area); + lv_coord_t src_height = lv_area_get_height(src_area); + + lv_gpu_nxp_pxp_reset(); + + const pxp_pic_copy_config_t picCopyConfig = { + .srcPicBaseAddr = (uint32_t)src_buf, + .srcPitchBytes = src_stride * sizeof(lv_color_t), + .srcOffsetX = src_area->x1, + .srcOffsetY = src_area->y1, + .destPicBaseAddr = (uint32_t)dest_buf, + .destPitchBytes = dest_stride * sizeof(lv_color_t), + .destOffsetX = dest_area->x1, + .destOffsetY = dest_area->y1, + .width = src_width, + .height = src_height, + .pixelFormat = PXP_AS_PIXEL_FORMAT + }; + + PXP_StartPictureCopy(LV_GPU_NXP_PXP_ID, &picCopyConfig); + + lv_gpu_nxp_pxp_wait(); +} + /********************** * STATIC FUNCTIONS **********************/ @@ -316,22 +348,25 @@ static void lv_pxp_blit_opa(lv_color_t * dest_buf, const lv_area_t * dest_area, const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride, const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf) { - lv_coord_t temp_area_w = lv_area_get_width(dest_area); - lv_coord_t temp_area_h = lv_area_get_height(dest_area); - const lv_area_t temp_area = { - .x1 = 0, - .y1 = 0, - .x2 = temp_area_w - 1, - .y2 = temp_area_h - 1 - }; + lv_area_t temp_area; + lv_area_copy(&temp_area, dest_area); + lv_coord_t temp_stride = dest_stride; + lv_coord_t temp_w = lv_area_get_width(&temp_area); + lv_coord_t temp_h = lv_area_get_height(&temp_area); /*Step 1: Transform with full opacity to temporary buffer*/ - lv_pxp_blit_cover((lv_color_t *)temp_buf, &temp_area, temp_area_w, src_buf, src_area, src_stride, dsc, cf); + lv_pxp_blit_cover((lv_color_t *)temp_buf, &temp_area, temp_stride, src_buf, src_area, src_stride, dsc, cf); + + /*Switch width and height if angle requires it*/ + if(dsc->angle == 900 || dsc->angle == 2700) { + temp_area.x2 = temp_area.x1 + temp_h - 1; + temp_area.y2 = temp_area.y1 + temp_w - 1; + } /*Step 2: Blit temporary result with required opacity to output*/ - lv_pxp_blit_cf(dest_buf, dest_area, dest_stride, (lv_color_t *)temp_buf, &temp_area, temp_area_w, dsc, cf); + lv_pxp_blit_cf(dest_buf, &temp_area, dest_stride, (lv_color_t *)temp_buf, &temp_area, temp_stride, dsc, cf); } -static void lv_pxp_blit_cover(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, +static void lv_pxp_blit_cover(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride, const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride, const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf) { @@ -343,28 +378,43 @@ static void lv_pxp_blit_cover(lv_color_t * dest_buf, const lv_area_t * dest_area bool has_recolor = (dsc->recolor_opa != LV_OPA_TRANSP); bool has_rotation = (dsc->angle != 0); + lv_point_t pivot = dsc->pivot; + lv_coord_t piv_offset_x; + lv_coord_t piv_offset_y; + lv_gpu_nxp_pxp_reset(); if(has_rotation) { - /*Convert rotation angle*/ + /*Convert rotation angle and calculate offsets caused by pivot*/ pxp_rotate_degree_t pxp_angle; switch(dsc->angle) { case 0: pxp_angle = kPXP_Rotate0; + piv_offset_x = 0; + piv_offset_y = 0; break; case 900: + piv_offset_x = pivot.x + pivot.y - dest_h; + piv_offset_y = pivot.y - pivot.x; pxp_angle = kPXP_Rotate90; break; case 1800: + piv_offset_x = 2 * pivot.x - dest_w; + piv_offset_y = 2 * pivot.y - dest_h; pxp_angle = kPXP_Rotate180; break; case 2700: + piv_offset_x = pivot.x - pivot.y; + piv_offset_y = pivot.x + pivot.y - dest_w; pxp_angle = kPXP_Rotate270; break; default: + piv_offset_x = 0; + piv_offset_y = 0; pxp_angle = kPXP_Rotate0; } PXP_SetRotateConfig(LV_GPU_NXP_PXP_ID, kPXP_RotateOutputBuffer, pxp_angle, kPXP_FlipDisable); + lv_area_move(dest_area, piv_offset_x, piv_offset_y); } /*AS buffer - source image*/ diff --git a/src/draw/nxp/pxp/lv_draw_pxp_blend.h b/src/draw/nxp/pxp/lv_draw_pxp_blend.h index 9fe9192f7..961566726 100644 --- a/src/draw/nxp/pxp/lv_draw_pxp_blend.h +++ b/src/draw/nxp/pxp/lv_draw_pxp_blend.h @@ -99,10 +99,24 @@ void lv_gpu_nxp_pxp_blit(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_ * @param[in] dsc Image descriptor * @param[in] cf Color format */ -void lv_gpu_nxp_pxp_blit_transform(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, +void lv_gpu_nxp_pxp_blit_transform(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride, const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride, const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf); +/** + * BLock Image Transfer - copy rectangular image from src_buf to dst_buf, no transformation or blending. + * + * + * @param[in/out] dest_buf Destination buffer + * @param[in] dest_area Area with relative coordinates of destination buffer + * @param[in] dest_stride Stride of destination buffer in pixels + * @param[in] src_buf Source buffer + * @param[in] src_area Area with relative coordinates of source buffer + * @param[in] src_stride Stride of source buffer in pixels + */ +void lv_gpu_nxp_pxp_buffer_copy(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, + const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride); + /********************** * MACROS **********************/ diff --git a/src/draw/nxp/pxp/lv_gpu_nxp_pxp.h b/src/draw/nxp/pxp/lv_gpu_nxp_pxp.h index 10a67215a..46f4a0ba1 100644 --- a/src/draw/nxp/pxp/lv_gpu_nxp_pxp.h +++ b/src/draw/nxp/pxp/lv_gpu_nxp_pxp.h @@ -149,7 +149,7 @@ void lv_gpu_nxp_pxp_wait(void); #if LV_GPU_NXP_PXP_LOG_TRACES #define PXP_LOG_TRACE(fmt, ...) \ do { \ - LV_LOG_ERROR(fmt, ##__VA_ARGS__); \ + LV_LOG(fmt, ##__VA_ARGS__); \ } while (0) #else #define PXP_LOG_TRACE(fmt, ...) \ diff --git a/src/draw/nxp/vglite/lv_draw_vglite.c b/src/draw/nxp/vglite/lv_draw_vglite.c index eae1b8a58..031f57e4e 100644 --- a/src/draw/nxp/vglite/lv_draw_vglite.c +++ b/src/draw/nxp/vglite/lv_draw_vglite.c @@ -69,6 +69,10 @@ static void lv_draw_vglite_wait_for_finish(lv_draw_ctx_t * draw_ctx); static void lv_draw_vglite_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t cf); +static void lv_draw_vglite_buffer_copy(lv_draw_ctx_t * draw_ctx, + void * dest_buf, lv_coord_t dest_stride, const lv_area_t * dest_area, + void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area); + static void lv_draw_vglite_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc); static void lv_draw_vglite_line(lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, const lv_point_t * point1, @@ -111,6 +115,7 @@ void lv_draw_vglite_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) vglite_draw_ctx->base_draw.draw_img_decoded = lv_draw_vglite_img_decoded; vglite_draw_ctx->blend = lv_draw_vglite_blend; vglite_draw_ctx->base_draw.wait_for_finish = lv_draw_vglite_wait_for_finish; + vglite_draw_ctx->base_draw.buffer_copy = lv_draw_vglite_buffer_copy; } void lv_draw_vglite_ctx_deinit(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) @@ -166,11 +171,9 @@ static void lv_draw_vglite_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blen } lv_area_t blend_area; - /*Let's get the blend area which is the intersection of the area to draw and the clip area*/ if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area)) return; /*Fully clipped, nothing to do*/ - /*Make the blend area relative to the buffer*/ lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); bool done = false; @@ -185,9 +188,6 @@ static void lv_draw_vglite_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blen VG_LITE_LOG_TRACE("VG-Lite fill failed. Fallback."); } else { - lv_color_t * dest_buf = draw_ctx->buf; - lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area); - lv_area_t src_area; src_area.x1 = blend_area.x1 - (dsc->blend_area->x1 - draw_ctx->buf_area->x1); src_area.y1 = blend_area.y1 - (dsc->blend_area->y1 - draw_ctx->buf_area->y1); @@ -195,8 +195,15 @@ static void lv_draw_vglite_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blen src_area.y2 = src_area.y1 + lv_area_get_height(dsc->blend_area) - 1; lv_coord_t src_stride = lv_area_get_width(dsc->blend_area); - done = (lv_gpu_nxp_vglite_blit(dest_buf, &blend_area, dest_stride, - src_buf, &src_area, src_stride, dsc->opa) == LV_RES_OK); +#if VG_LITE_BLIT_SPLIT_ENABLED + lv_color_t * dest_buf = draw_ctx->buf; + lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area); + + done = (lv_gpu_nxp_vglite_blit_split(dest_buf, &blend_area, dest_stride, + src_buf, &src_area, src_stride, dsc->opa) == LV_RES_OK); +#else + done = (lv_gpu_nxp_vglite_blit(&blend_area, src_buf, &src_area, src_stride, dsc->opa) == LV_RES_OK); +#endif if(!done) VG_LITE_LOG_TRACE("VG-Lite blit failed. Fallback."); @@ -224,13 +231,21 @@ static void lv_draw_vglite_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_i return; } - lv_area_t blend_area; - /*Let's get the blend area which is the intersection of the area to draw and the clip area*/ - if(!_lv_area_intersect(&blend_area, coords, draw_ctx->clip_area)) - return; /*Fully clipped, nothing to do*/ + lv_area_t rel_coords; + lv_area_copy(&rel_coords, coords); + lv_area_move(&rel_coords, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); - /*Make the blend area relative to the buffer*/ - lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); + lv_area_t rel_clip_area; + lv_area_copy(&rel_clip_area, draw_ctx->clip_area); + lv_area_move(&rel_clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); + + lv_area_t blend_area; + bool has_transform = dsc->angle != 0 || dsc->zoom != LV_IMG_ZOOM_NONE; + + if(has_transform) + lv_area_copy(&blend_area, &rel_coords); + else if(!_lv_area_intersect(&blend_area, &rel_coords, &rel_clip_area)) + return; /*Fully clipped, nothing to do*/ bool has_mask = lv_draw_mask_is_any(&blend_area); bool has_recolor = (dsc->recolor_opa != LV_OPA_TRANSP); @@ -242,9 +257,6 @@ static void lv_draw_vglite_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_i && !lv_img_cf_has_alpha(cf) #endif ) { - lv_color_t * dest_buf = draw_ctx->buf; - lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area); - lv_area_t src_area; src_area.x1 = blend_area.x1 - (coords->x1 - draw_ctx->buf_area->x1); src_area.y1 = blend_area.y1 - (coords->y1 - draw_ctx->buf_area->y1); @@ -252,17 +264,48 @@ static void lv_draw_vglite_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_i src_area.y2 = src_area.y1 + lv_area_get_height(coords) - 1; lv_coord_t src_stride = lv_area_get_width(coords); - done = (lv_gpu_nxp_vglite_blit_transform(dest_buf, &blend_area, dest_stride, - src_buf, &src_area, src_stride, dsc) == LV_RES_OK); +#if VG_LITE_BLIT_SPLIT_ENABLED + lv_color_t * dest_buf = draw_ctx->buf; + lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area); + + if(has_transform) + /* VG-Lite blit split with transformation is not supported! */ + done = false; + else + done = (lv_gpu_nxp_vglite_blit_split(dest_buf, &blend_area, dest_stride, + src_buf, &src_area, src_stride, dsc->opa) == LV_RES_OK); +#else + if(has_transform) + done = (lv_gpu_nxp_vglite_blit_transform(&blend_area, &rel_clip_area, + src_buf, &src_area, src_stride, dsc) == LV_RES_OK); + else + done = (lv_gpu_nxp_vglite_blit(&blend_area, src_buf, &src_area, src_stride, dsc->opa) == LV_RES_OK); +#endif if(!done) - VG_LITE_LOG_TRACE("VG-Lite blit transform failed. Fallback."); + VG_LITE_LOG_TRACE("VG-Lite blit %sfailed. Fallback.", has_transform ? "transform " : ""); } if(!done) lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf); } +static void lv_draw_vglite_buffer_copy(lv_draw_ctx_t * draw_ctx, + void * dest_buf, lv_coord_t dest_stride, const lv_area_t * dest_area, + void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area) +{ + bool done = false; + + if(lv_area_get_size(dest_area) >= LV_GPU_NXP_VG_LITE_SIZE_LIMIT) { + done = lv_gpu_nxp_vglite_buffer_copy(dest_buf, dest_area, dest_stride, src_buf, src_area, src_stride); + if(!done) + VG_LITE_LOG_TRACE("VG-Lite buffer copy failed. Fallback."); + } + + if(!done) + lv_draw_sw_buffer_copy(draw_ctx, dest_buf, dest_stride, dest_area, src_buf, src_stride, src_area); +} + static void lv_draw_vglite_line(lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, const lv_point_t * point1, const lv_point_t * point2) { @@ -284,21 +327,19 @@ static void lv_draw_vglite_line(lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc rel_clip_area.y1 = LV_MIN(point1->y, point2->y) - dsc->width / 2; rel_clip_area.y2 = LV_MAX(point1->y, point2->y) + dsc->width / 2; - bool is_common; - is_common = _lv_area_intersect(&rel_clip_area, &rel_clip_area, draw_ctx->clip_area); - if(!is_common) - return; + lv_area_t clipped_coords; + if(!_lv_area_intersect(&clipped_coords, &rel_clip_area, draw_ctx->clip_area)) + return; /*Fully clipped, nothing to do*/ - /* Make coordinates relative to the draw buffer */ lv_area_move(&rel_clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); lv_point_t rel_point1 = { point1->x - draw_ctx->buf_area->x1, point1->y - draw_ctx->buf_area->y1 }; lv_point_t rel_point2 = { point2->x - draw_ctx->buf_area->x1, point2->y - draw_ctx->buf_area->y1 }; bool done = false; - bool mask_any = lv_draw_mask_is_any(&rel_clip_area); + bool has_mask = lv_draw_mask_is_any(&rel_clip_area); - if(!mask_any) { + if(!has_mask) { done = (lv_gpu_nxp_vglite_draw_line(&rel_point1, &rel_point2, &rel_clip_area, dsc) == LV_RES_OK); if(!done) VG_LITE_LOG_TRACE("VG-Lite draw line failed. Fallback."); @@ -369,8 +410,6 @@ static lv_res_t lv_draw_vglite_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_d rel_coords.x2 -= (dsc->border_side & LV_BORDER_SIDE_RIGHT) ? 1 : 0; rel_coords.y2 -= (dsc->border_side & LV_BORDER_SIDE_BOTTOM) ? 1 : 0; } - - /* Make coordinates relative to draw buffer */ lv_area_move(&rel_coords, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); lv_area_t rel_clip_area; @@ -379,9 +418,9 @@ static lv_res_t lv_draw_vglite_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_d lv_area_t clipped_coords; if(!_lv_area_intersect(&clipped_coords, &rel_coords, &rel_clip_area)) - return LV_RES_INV; + return LV_RES_OK; /*Fully clipped, nothing to do*/ - bool mask_any = lv_draw_mask_is_any(&rel_coords); + bool has_mask = lv_draw_mask_is_any(&rel_coords); lv_grad_dir_t grad_dir = dsc->bg_grad.dir; lv_color_t bg_color = (grad_dir == (lv_grad_dir_t)LV_GRAD_DIR_NONE) ? dsc->bg_color : dsc->bg_grad.stops[0].color; @@ -394,7 +433,7 @@ static lv_res_t lv_draw_vglite_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_d * * Complex case: gradient or radius but no mask. */ - if(!mask_any && ((dsc->radius != 0) || (grad_dir != (lv_grad_dir_t)LV_GRAD_DIR_NONE))) { + if(!has_mask && ((dsc->radius != 0) || (grad_dir != (lv_grad_dir_t)LV_GRAD_DIR_NONE))) { lv_res_t res = lv_gpu_nxp_vglite_draw_bg(&rel_coords, &rel_clip_area, dsc); if(res != LV_RES_OK) VG_LITE_LOG_TRACE("VG-Lite draw bg failed. Fallback."); @@ -426,13 +465,16 @@ static lv_res_t lv_draw_vglite_border(lv_draw_ctx_t * draw_ctx, const lv_draw_re rel_coords.y1 = coords->y1 + ceil(border_width / 2.0f); rel_coords.y2 = coords->y2 - floor(border_width / 2.0f); - /* Make coordinates relative to the draw buffer */ lv_area_move(&rel_coords, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); lv_area_t rel_clip_area; lv_area_copy(&rel_clip_area, draw_ctx->clip_area); lv_area_move(&rel_clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); + lv_area_t clipped_coords; + if(!_lv_area_intersect(&clipped_coords, &rel_coords, &rel_clip_area)) + return LV_RES_OK; /*Fully clipped, nothing to do*/ + lv_res_t res = lv_gpu_nxp_vglite_draw_border_generic(&rel_coords, &rel_clip_area, dsc, true); if(res != LV_RES_OK) VG_LITE_LOG_TRACE("VG-Lite draw border failed. Fallback."); @@ -456,13 +498,16 @@ static lv_res_t lv_draw_vglite_outline(lv_draw_ctx_t * draw_ctx, const lv_draw_r rel_coords.y1 = coords->y1 - outline_pad - floor(dsc->outline_width / 2.0f); rel_coords.y2 = coords->y2 + outline_pad + ceil(dsc->outline_width / 2.0f); - /* Make coordinates relative to the draw buffer */ lv_area_move(&rel_coords, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); lv_area_t rel_clip_area; lv_area_copy(&rel_clip_area, draw_ctx->clip_area); lv_area_move(&rel_clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); + lv_area_t clipped_coords; + if(!_lv_area_intersect(&clipped_coords, &rel_coords, &rel_clip_area)) + return LV_RES_OK; /*Fully clipped, nothing to do*/ + lv_res_t res = lv_gpu_nxp_vglite_draw_border_generic(&rel_coords, &rel_clip_area, dsc, false); if(res != LV_RES_OK) VG_LITE_LOG_TRACE("VG-Lite draw outline failed. Fallback."); @@ -488,17 +533,21 @@ static void lv_draw_vglite_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t return; } - /* Make coordinates relative to the draw buffer */ lv_point_t rel_center = {center->x - draw_ctx->buf_area->x1, center->y - draw_ctx->buf_area->y1}; lv_area_t rel_clip_area; lv_area_copy(&rel_clip_area, draw_ctx->clip_area); lv_area_move(&rel_clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); - done = (lv_gpu_nxp_vglite_draw_arc(&rel_center, (int32_t)radius, (int32_t)start_angle, (int32_t)end_angle, - &rel_clip_area, dsc) == LV_RES_OK); - if(!done) - VG_LITE_LOG_TRACE("VG-Lite draw arc failed. Fallback."); + bool has_mask = lv_draw_mask_is_any(&rel_clip_area); + + if(!has_mask) { + done = (lv_gpu_nxp_vglite_draw_arc(&rel_center, (int32_t)radius, (int32_t)start_angle, (int32_t)end_angle, + &rel_clip_area, dsc) == LV_RES_OK); + if(!done) + VG_LITE_LOG_TRACE("VG-Lite draw arc failed. Fallback."); + } + #endif/*LV_DRAW_COMPLEX*/ if(!done) diff --git a/src/draw/nxp/vglite/lv_draw_vglite_arc.c b/src/draw/nxp/vglite/lv_draw_vglite_arc.c index 775bf734b..39470527d 100644 --- a/src/draw/nxp/vglite/lv_draw_vglite_arc.c +++ b/src/draw/nxp/vglite/lv_draw_vglite_arc.c @@ -216,6 +216,8 @@ lv_res_t lv_gpu_nxp_vglite_draw_arc(const lv_point_t * center, int32_t radius, i vg_lite_matrix_t matrix; vg_lite_identity(&matrix); + lv_vglite_set_scissor(clip_area); + /*** Draw arc ***/ err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol); VG_LITE_ERR_RETURN_INV(err, "Draw arc failed."); @@ -223,6 +225,8 @@ lv_res_t lv_gpu_nxp_vglite_draw_arc(const lv_point_t * center, int32_t radius, i if(lv_vglite_run() != LV_RES_OK) VG_LITE_RETURN_INV("Run failed."); + lv_vglite_disable_scissor(); + err = vg_lite_clear_path(&path); VG_LITE_ERR_RETURN_INV(err, "Clear path failed."); diff --git a/src/draw/nxp/vglite/lv_draw_vglite_blend.c b/src/draw/nxp/vglite/lv_draw_vglite_blend.c index e1408b760..4a15fd55c 100644 --- a/src/draw/nxp/vglite/lv_draw_vglite_blend.c +++ b/src/draw/nxp/vglite/lv_draw_vglite_blend.c @@ -35,6 +35,7 @@ #if LV_USE_GPU_NXP_VG_LITE #include "lv_vglite_buf.h" +#include "lv_vglite_utils.h" /********************* * DEFINES @@ -43,21 +44,6 @@ /** Stride in px required by VG-Lite HW*/ #define LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX 16U -/** - * Enable BLIT quality degradation workaround for RT595, - * recommended for screen's dimension > 352 pixels. - */ -#define RT595_BLIT_WRKRND_ENABLED 1 - -/* Internal compound symbol */ -#if (defined(CPU_MIMXRT595SFFOB) || defined(CPU_MIMXRT595SFFOB_cm33) || \ - defined(CPU_MIMXRT595SFFOC) || defined(CPU_MIMXRT595SFFOC_cm33)) && \ - RT595_BLIT_WRKRND_ENABLED -#define VG_LITE_BLIT_SPLIT_ENABLED 1 -#else -#define VG_LITE_BLIT_SPLIT_ENABLED 0 -#endif - #if VG_LITE_BLIT_SPLIT_ENABLED /** * BLIT split threshold - BLITs with width or height higher than this value will be done @@ -75,16 +61,15 @@ **********************/ /** - * Blit single image, with optional opacity. + * Blit image, with optional opacity. * - * @param[in] dest_area Area with relative coordinates of destination buffer * @param[in] src_area Source area with relative coordinates of source buffer * @param[in] opa Opacity * * @retval LV_RES_OK Transfer complete * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) */ -static lv_res_t lv_vglite_blit_single(const lv_area_t * dest_area, const lv_area_t * src_area, lv_opa_t opa); +static lv_res_t lv_vglite_blit(const lv_area_t * src_area, lv_opa_t opa); /** * Check source memory and stride alignment. @@ -113,7 +98,6 @@ static inline void lv_vglite_set_translation_matrix(const lv_area_t * dest_area) static inline void lv_vglite_set_transformation_matrix(const lv_area_t * dest_area, const lv_draw_img_dsc_t * dsc); #if VG_LITE_BLIT_SPLIT_ENABLED - /** * Move buffer pointer as close as possible to area, but with respect to alignment requirements. X-axis only. * @@ -148,7 +132,7 @@ static void align_y(lv_area_t * area, lv_color_t ** buf, lv_coord_t stride); static lv_res_t lv_vglite_blit_split(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride, const lv_color_t * src_buf, lv_area_t * src_area, lv_coord_t src_stride, lv_opa_t opa); -#endif +#endif /*VG_LITE_BLIT_SPLIT_ENABLED*/ /********************** * STATIC VARIABLES @@ -223,17 +207,14 @@ lv_res_t lv_gpu_nxp_vglite_fill(const lv_area_t * dest_area, lv_color_t color, l return LV_RES_OK; } -lv_res_t lv_gpu_nxp_vglite_blit(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, lv_area_t * src_area, lv_coord_t src_stride, - lv_opa_t opa) +#if VG_LITE_BLIT_SPLIT_ENABLED +lv_res_t lv_gpu_nxp_vglite_blit_split(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride, + const lv_color_t * src_buf, lv_area_t * src_area, lv_coord_t src_stride, + lv_opa_t opa) { - /* Set vgmatrix. */ - lv_vglite_set_translation_matrix(dest_area); - /* Set src_vgbuf structure. */ lv_vglite_set_src_buf(src_buf, src_area, src_stride); -#if VG_LITE_BLIT_SPLIT_ENABLED lv_color_t * orig_dest_buf = dest_buf; lv_res_t rv = lv_vglite_blit_split(dest_buf, dest_area, dest_stride, src_buf, src_area, src_stride, opa); @@ -242,45 +223,112 @@ lv_res_t lv_gpu_nxp_vglite_blit(lv_color_t * dest_buf, lv_area_t * dest_area, lv lv_vglite_set_dest_buf_ptr(orig_dest_buf); return rv; +} #else - LV_UNUSED(dest_buf); - LV_UNUSED(dest_stride); - +lv_res_t lv_gpu_nxp_vglite_blit(const lv_area_t * dest_area, + const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride, + lv_opa_t opa) +{ if(check_src_alignment(src_buf, src_stride) != LV_RES_OK) VG_LITE_RETURN_INV("Check src alignment failed."); - return lv_vglite_blit_single(dest_area, src_area, opa); -#endif -} - -lv_res_t lv_gpu_nxp_vglite_blit_transform(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, lv_area_t * src_area, lv_coord_t src_stride, - const lv_draw_img_dsc_t * dsc) -{ - /* Set vgmatrix. */ - lv_vglite_set_transformation_matrix(dest_area, dsc); - /* Set src_vgbuf structure. */ lv_vglite_set_src_buf(src_buf, src_area, src_stride); -#if VG_LITE_BLIT_SPLIT_ENABLED - lv_color_t * orig_dest_buf = dest_buf; + /* Set scissor. */ + lv_vglite_set_scissor(dest_area); - lv_res_t rv = lv_vglite_blit_split(dest_buf, dest_area, dest_stride, src_buf, src_area, src_stride, dsc->opa); + /* Set vgmatrix. */ + lv_vglite_set_translation_matrix(dest_area); - /* Restore the original dest_vgbuf memory address. */ - lv_vglite_set_dest_buf_ptr(orig_dest_buf); + /* Start blit. */ + lv_res_t rv = lv_vglite_blit(src_area, opa); + + /* Disable scissor. */ + lv_vglite_disable_scissor(); return rv; -#else - LV_UNUSED(dest_buf); - LV_UNUSED(dest_stride); +} + +lv_res_t lv_gpu_nxp_vglite_blit_transform(const lv_area_t * dest_area, const lv_area_t * clip_area, + const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride, + const lv_draw_img_dsc_t * dsc) +{ + lv_res_t rv = LV_RES_INV; if(check_src_alignment(src_buf, src_stride) != LV_RES_OK) VG_LITE_RETURN_INV("Check src alignment failed."); - return lv_vglite_blit_single(dest_area, src_area, dsc->opa); -#endif + /* Set src_vgbuf structure. */ + lv_vglite_set_src_buf(src_buf, src_area, src_stride); + + /* Set scissor */ + lv_vglite_set_scissor(clip_area); + + /* Set vgmatrix. */ + lv_vglite_set_transformation_matrix(dest_area, dsc); + + /* Start blit. */ + rv = lv_vglite_blit(src_area, dsc->opa); + + /* Disable scissor. */ + lv_vglite_disable_scissor(); + + return rv; +} +#endif /*VG_LITE_BLIT_SPLIT_ENABLED*/ + +lv_res_t lv_gpu_nxp_vglite_buffer_copy(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, + const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride) +{ + vg_lite_error_t err = VG_LITE_SUCCESS; + + if(check_src_alignment(src_buf, src_stride) != LV_RES_OK) + VG_LITE_RETURN_INV("Check src alignment failed."); + + vg_lite_buffer_t src_vgbuf; + /* Set src_vgbuf structure. */ + lv_vglite_set_buf(&src_vgbuf, src_buf, src_area, src_stride); + + vg_lite_buffer_t dest_vgbuf; + /* Set dest_vgbuf structure. */ + lv_vglite_set_buf(&dest_vgbuf, dest_buf, dest_area, dest_stride); + + uint32_t rect[] = { + (uint32_t)src_area->x1, /* start x */ + (uint32_t)src_area->y1, /* start y */ + (uint32_t)lv_area_get_width(src_area), /* width */ + (uint32_t)lv_area_get_height(src_area) /* height */ + }; + + /* Set scissor. */ + lv_vglite_set_scissor(dest_area); + + /* Set vgmatrix. */ + lv_vglite_set_translation_matrix(dest_area); + + err = vg_lite_blit_rect(&dest_vgbuf, &src_vgbuf, rect, &vgmatrix, + VG_LITE_BLEND_NONE, 0xFFFFFFFFU, VG_LITE_FILTER_POINT); + if(err != VG_LITE_SUCCESS) { + LV_LOG_ERROR("Blit rectangle failed."); + /* Disable scissor. */ + lv_vglite_disable_scissor(); + + return LV_RES_INV; + } + + if(lv_vglite_run() != LV_RES_OK) { + LV_LOG_ERROR("Run failed."); + /* Disable scissor. */ + lv_vglite_disable_scissor(); + + return LV_RES_INV; + } + + /* Disable scissor. */ + lv_vglite_disable_scissor(); + + return LV_RES_OK; } /********************** @@ -320,10 +368,17 @@ static lv_res_t lv_vglite_blit_split(lv_color_t * dest_buf, lv_area_t * dest_are lv_vglite_set_dest_buf_ptr(dest_buf); lv_vglite_set_src_buf_ptr(src_buf); + /* Set scissor */ + lv_vglite_set_scissor(dest_area); + /* Set vgmatrix. */ lv_vglite_set_translation_matrix(dest_area); - rv = lv_vglite_blit_single(dest_area, src_area, opa); + /* Start blit. */ + rv = lv_vglite_blit(src_area, opa); + + /* Disable scissor. */ + lv_vglite_disable_scissor(); VG_LITE_LOG_TRACE("Single " "Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | " @@ -426,14 +481,21 @@ static lv_res_t lv_vglite_blit_split(lv_color_t * dest_buf, lv_area_t * dest_are if(check_src_alignment(tile_src_buf, src_stride) != LV_RES_OK) VG_LITE_RETURN_INV("Check src alignment failed."); - /* Set vgmatrix. */ - lv_vglite_set_translation_matrix(&tile_dest_area); - /* Set new dest_vgbuf and src_vgbuf memory addresses. */ lv_vglite_set_dest_buf_ptr(tile_dest_buf); lv_vglite_set_src_buf_ptr(tile_src_buf); - rv = lv_vglite_blit_single(&tile_dest_area, &tile_src_area, opa); + /* Set scissor */ + lv_vglite_set_scissor(&tile_dest_area); + + /* Set vgmatrix. */ + lv_vglite_set_translation_matrix(&tile_dest_area); + + /* Start blit. */ + rv = lv_vglite_blit(&tile_src_area, opa); + + /* Disable scissor. */ + lv_vglite_disable_scissor(); VG_LITE_LOG_TRACE("Tile [%d, %d] " "Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | " @@ -455,9 +517,9 @@ static lv_res_t lv_vglite_blit_split(lv_color_t * dest_buf, lv_area_t * dest_are return rv; } -#endif /* VG_LITE_BLIT_SPLIT_ENABLED */ +#endif /*VG_LITE_BLIT_SPLIT_ENABLED*/ -static lv_res_t lv_vglite_blit_single(const lv_area_t * dest_area, const lv_area_t * src_area, lv_opa_t opa) +static lv_res_t lv_vglite_blit(const lv_area_t * src_area, lv_opa_t opa) { vg_lite_error_t err = VG_LITE_SUCCESS; vg_lite_buffer_t * dst_vgbuf = lv_vglite_get_dest_buf(); @@ -489,30 +551,11 @@ static lv_res_t lv_vglite_blit_single(const lv_area_t * dest_area, const lv_area src_vgbuf->transparency_mode = VG_LITE_IMAGE_TRANSPARENT; } - bool scissoring = lv_area_get_width(dest_area) < lv_area_get_width(src_area) || - lv_area_get_height(dest_area) < lv_area_get_height(src_area); - if(scissoring) { - vg_lite_enable_scissor(); - vg_lite_set_scissor((int32_t)dest_area->x1, (int32_t)dest_area->y1, - (int32_t)lv_area_get_width(dest_area), - (int32_t)lv_area_get_height(dest_area)); - } - err = vg_lite_blit_rect(dst_vgbuf, src_vgbuf, rect, &vgmatrix, blend, color, VG_LITE_FILTER_POINT); - if(err != VG_LITE_SUCCESS) { - if(scissoring) - vg_lite_disable_scissor(); - VG_LITE_RETURN_INV("Blit rectangle failed."); - } + VG_LITE_ERR_RETURN_INV(err, "Blit rectangle failed."); - if(lv_vglite_run() != LV_RES_OK) { - if(scissoring) - vg_lite_disable_scissor(); + if(lv_vglite_run() != LV_RES_OK) VG_LITE_RETURN_INV("Run failed."); - } - - if(scissoring) - vg_lite_disable_scissor(); return LV_RES_OK; } @@ -546,16 +589,14 @@ static inline void lv_vglite_set_transformation_matrix(const lv_area_t * dest_ar bool has_scale = (dsc->zoom != LV_IMG_ZOOM_NONE); bool has_rotation = (dsc->angle != 0); - if(has_scale || has_rotation) { - vg_lite_translate(dsc->pivot.x, dsc->pivot.y, &vgmatrix); - if(has_rotation) - vg_lite_rotate(dsc->angle / 10.0f, &vgmatrix); /* angle is 1/10 degree */ - if(has_scale) { - vg_lite_float_t scale = 1.0f * dsc->zoom / LV_IMG_ZOOM_NONE; - vg_lite_scale(scale, scale, &vgmatrix); - } - vg_lite_translate(0.0f - dsc->pivot.x, 0.0f - dsc->pivot.y, &vgmatrix); + vg_lite_translate(dsc->pivot.x, dsc->pivot.y, &vgmatrix); + if(has_rotation) + vg_lite_rotate(dsc->angle / 10.0f, &vgmatrix); /* angle is 1/10 degree */ + if(has_scale) { + vg_lite_float_t scale = 1.0f * dsc->zoom / LV_IMG_ZOOM_NONE; + vg_lite_scale(scale, scale, &vgmatrix); } + vg_lite_translate(0.0f - dsc->pivot.x, 0.0f - dsc->pivot.y, &vgmatrix); } #if VG_LITE_BLIT_SPLIT_ENABLED diff --git a/src/draw/nxp/vglite/lv_draw_vglite_blend.h b/src/draw/nxp/vglite/lv_draw_vglite_blend.h index 025d2b5cc..1aae34bd9 100644 --- a/src/draw/nxp/vglite/lv_draw_vglite_blend.h +++ b/src/draw/nxp/vglite/lv_draw_vglite_blend.h @@ -47,6 +47,21 @@ extern "C" { * DEFINES *********************/ +/** + * Enable BLIT quality degradation workaround for RT595, + * recommended for screen's dimension > 352 pixels. + */ +#define RT595_BLIT_WRKRND_ENABLED 1 + +/* Internal compound symbol */ +#if (defined(CPU_MIMXRT595SFFOB) || defined(CPU_MIMXRT595SFFOB_cm33) || \ + defined(CPU_MIMXRT595SFFOC) || defined(CPU_MIMXRT595SFFOC_cm33)) && \ + RT595_BLIT_WRKRND_ENABLED +#define VG_LITE_BLIT_SPLIT_ENABLED 1 +#else +#define VG_LITE_BLIT_SPLIT_ENABLED 0 +#endif + /********************** * TYPEDEFS **********************/ @@ -67,6 +82,7 @@ extern "C" { */ lv_res_t lv_gpu_nxp_vglite_fill(const lv_area_t * dest_area, lv_color_t color, lv_opa_t opa); +#if VG_LITE_BLIT_SPLIT_ENABLED /** * BLock Image Transfer - copy rectangular image from src_buf to dst_buf with effects. * By default, image is copied directly, with optional opacity. @@ -82,17 +98,33 @@ lv_res_t lv_gpu_nxp_vglite_fill(const lv_area_t * dest_area, lv_color_t color, l * @retval LV_RES_OK Transfer complete * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) */ -lv_res_t lv_gpu_nxp_vglite_blit(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, lv_area_t * src_area, lv_coord_t src_stride, +lv_res_t lv_gpu_nxp_vglite_blit_split(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride, + const lv_color_t * src_buf, lv_area_t * src_area, lv_coord_t src_stride, + lv_opa_t opa); +#else +/** + * BLock Image Transfer - copy rectangular image from src_buf to dst_buf with effects. + * By default, image is copied directly, with optional opacity. + * + * @param[in] dest_stride Stride of destination buffer in pixels + * @param[in] src_buf Source buffer + * @param[in] src_area Source area with relative coordinates of source buffer + * @param[in] src_stride Stride of source buffer in pixels + * @param[in] opa Opacity + * + * @retval LV_RES_OK Transfer complete + * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) + */ +lv_res_t lv_gpu_nxp_vglite_blit(const lv_area_t * dest_area, + const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride, lv_opa_t opa); /** * BLock Image Transfer - copy rectangular image from src_buf to dst_buf with transformation. * By default, image is copied directly, with optional opacity. * - * @param[in/out] dest_buf Destination buffer * @param[in] dest_area Area with relative coordinates of destination buffer - * @param[in] dest_stride Stride of destination buffer in pixels + * @param[in] clip_area Clip area with relative coordinates of destination buffer * @param[in] src_buf Source buffer * @param[in] src_area Source area with relative coordinates of source buffer * @param[in] src_stride Stride of source buffer in pixels @@ -101,10 +133,28 @@ lv_res_t lv_gpu_nxp_vglite_blit(lv_color_t * dest_buf, lv_area_t * dest_area, lv * @retval LV_RES_OK Transfer complete * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) */ -lv_res_t lv_gpu_nxp_vglite_blit_transform(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, lv_area_t * src_area, lv_coord_t src_stride, +lv_res_t lv_gpu_nxp_vglite_blit_transform(const lv_area_t * dest_area, const lv_area_t * clip_area, + const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride, const lv_draw_img_dsc_t * dsc); +#endif /*VG_LITE_BLIT_SPLIT_ENABLED*/ + +/** + * BLock Image Transfer - simple copy of rectangular image from source to destination. + * + * @param[in] dest_buf Destination buffer + * @param[in] dest_area Area with relative coordinates of destination buffer + * @param[in] dest_stride Stride of destination buffer in pixels + * @param[in] src_buf Source buffer + * @param[in] src_area Source area with relative coordinates of source buffer + * @param[in] src_stride Stride of source buffer in pixels + * + * @retval LV_RES_OK Transfer complete + * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) + */ +lv_res_t lv_gpu_nxp_vglite_buffer_copy(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, + const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride); + /********************** * MACROS **********************/ diff --git a/src/draw/nxp/vglite/lv_draw_vglite_line.c b/src/draw/nxp/vglite/lv_draw_vglite_line.c index f6e1c4352..bf7bee11a 100644 --- a/src/draw/nxp/vglite/lv_draw_vglite_line.c +++ b/src/draw/nxp/vglite/lv_draw_vglite_line.c @@ -119,12 +119,16 @@ lv_res_t lv_gpu_nxp_vglite_draw_line(const lv_point_t * point1, const lv_point_t err = vg_lite_update_stroke(&path); VG_LITE_ERR_RETURN_INV(err, "Update stroke failed."); + lv_vglite_set_scissor(clip_area); + err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, vglite_blend_mode, vgcol); VG_LITE_ERR_RETURN_INV(err, "Draw line failed."); if(lv_vglite_run() != LV_RES_OK) VG_LITE_RETURN_INV("Run failed."); + lv_vglite_disable_scissor(); + err = vg_lite_clear_path(&path); VG_LITE_ERR_RETURN_INV(err, "Clear path failed."); diff --git a/src/draw/nxp/vglite/lv_draw_vglite_rect.c b/src/draw/nxp/vglite/lv_draw_vglite_rect.c index 39ccaa481..e9db57da9 100644 --- a/src/draw/nxp/vglite/lv_draw_vglite_rect.c +++ b/src/draw/nxp/vglite/lv_draw_vglite_rect.c @@ -166,6 +166,8 @@ lv_res_t lv_gpu_nxp_vglite_draw_bg(const lv_area_t * coords, const lv_area_t * c if(lv_vglite_premult_and_swizzle(&vgcol, bg_col32, dsc->bg_opa, color_format) != LV_RES_OK) VG_LITE_RETURN_INV("Premultiplication and swizzle failed."); + lv_vglite_set_scissor(clip_area); + /*** Draw rectangle ***/ if(dsc->bg_grad.dir == (lv_grad_dir_t)LV_GRAD_DIR_NONE) { err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol); @@ -178,6 +180,8 @@ lv_res_t lv_gpu_nxp_vglite_draw_bg(const lv_area_t * coords, const lv_area_t * c if(lv_vglite_run() != LV_RES_OK) VG_LITE_RETURN_INV("Run failed."); + lv_vglite_disable_scissor(); + err = vg_lite_clear_path(&path); VG_LITE_ERR_RETURN_INV(err, "Clear path failed."); @@ -263,12 +267,16 @@ lv_res_t lv_gpu_nxp_vglite_draw_border_generic(const lv_area_t * coords, const l err = vg_lite_update_stroke(&path); VG_LITE_ERR_RETURN_INV(err, "Update stroke failed."); + lv_vglite_set_scissor(clip_area); + err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, vglite_blend_mode, vgcol); VG_LITE_ERR_RETURN_INV(err, "Draw border failed."); if(lv_vglite_run() != LV_RES_OK) VG_LITE_RETURN_INV("Run failed."); + lv_vglite_disable_scissor(); + err = vg_lite_clear_path(&path); VG_LITE_ERR_RETURN_INV(err, "Clear path failed."); @@ -276,6 +284,10 @@ lv_res_t lv_gpu_nxp_vglite_draw_border_generic(const lv_area_t * coords, const l } +/********************** + * STATIC FUNCTIONS + **********************/ + static void lv_vglite_create_rect_path_data(int32_t * path_data, uint32_t * path_data_size, lv_coord_t radius, const lv_area_t * coords) @@ -444,8 +456,4 @@ static void lv_vglite_create_rect_path_data(int32_t * path_data, uint32_t * path *path_data_size = pidx * sizeof(int32_t); } -/********************** - * STATIC FUNCTIONS - **********************/ - #endif /*LV_USE_GPU_NXP_VG_LITE*/ diff --git a/src/draw/nxp/vglite/lv_vglite_buf.c b/src/draw/nxp/vglite/lv_vglite_buf.c index f6325ab2a..e1ff6a297 100644 --- a/src/draw/nxp/vglite/lv_vglite_buf.c +++ b/src/draw/nxp/vglite/lv_vglite_buf.c @@ -57,8 +57,6 @@ static inline void lv_vglite_set_dest_buf(const lv_color_t * buf, const lv_area_t * area, lv_coord_t stride); static inline void lv_vglite_set_buf_ptr(vg_lite_buffer_t * vgbuf, const lv_color_t * buf); -static inline void lv_vglite_set_buf(vg_lite_buffer_t * vgbuf, const lv_color_t * buf, - const lv_area_t * area, lv_coord_t stride); /********************** * STATIC VARIABLES @@ -106,23 +104,8 @@ void lv_vglite_set_src_buf(const lv_color_t * buf, const lv_area_t * area, lv_co lv_vglite_set_buf(&src_vgbuf, buf, area, stride); } -/********************** - * STATIC FUNCTIONS - **********************/ - -static inline void lv_vglite_set_dest_buf(const lv_color_t * buf, const lv_area_t * area, lv_coord_t stride) -{ - lv_vglite_set_buf(&dest_vgbuf, buf, area, stride); -} - -static inline void lv_vglite_set_buf_ptr(vg_lite_buffer_t * vgbuf, const lv_color_t * buf) -{ - vgbuf->memory = (void *)buf; - vgbuf->address = (uint32_t)vgbuf->memory; -} - -static inline void lv_vglite_set_buf(vg_lite_buffer_t * vgbuf, const lv_color_t * buf, - const lv_area_t * area, lv_coord_t stride) +void lv_vglite_set_buf(vg_lite_buffer_t * vgbuf, const lv_color_t * buf, + const lv_area_t * area, lv_coord_t stride) { vgbuf->format = VG_LITE_PX_FMT; vgbuf->tiled = VG_LITE_LINEAR; @@ -140,4 +123,19 @@ static inline void lv_vglite_set_buf(vg_lite_buffer_t * vgbuf, const lv_color_t vgbuf->handle = NULL; } +/********************** + * STATIC FUNCTIONS + **********************/ + +static inline void lv_vglite_set_dest_buf(const lv_color_t * buf, const lv_area_t * area, lv_coord_t stride) +{ + lv_vglite_set_buf(&dest_vgbuf, buf, area, stride); +} + +static inline void lv_vglite_set_buf_ptr(vg_lite_buffer_t * vgbuf, const lv_color_t * buf) +{ + vgbuf->memory = (void *)buf; + vgbuf->address = (uint32_t)vgbuf->memory; +} + #endif /*LV_USE_GPU_NXP_VG_LITE*/ diff --git a/src/draw/nxp/vglite/lv_vglite_buf.h b/src/draw/nxp/vglite/lv_vglite_buf.h index 9219dca05..e89af1c87 100644 --- a/src/draw/nxp/vglite/lv_vglite_buf.h +++ b/src/draw/nxp/vglite/lv_vglite_buf.h @@ -100,6 +100,17 @@ void lv_vglite_set_src_buf_ptr(const lv_color_t * buf); */ void lv_vglite_set_src_buf(const lv_color_t * buf, const lv_area_t * area, lv_coord_t stride); +/** + * Set vglite buffer. + * + * @param[in] vgbuf Address of the VGLite buffer object + * @param[in] buf Address of the memory for the VGLite buffer + * @param[in] area buffer area (for width and height) + * @param[in] stride buffer stride + */ +void lv_vglite_set_buf(vg_lite_buffer_t * vgbuf, const lv_color_t * buf, + const lv_area_t * area, lv_coord_t stride); + /********************** * MACROS **********************/ diff --git a/src/draw/nxp/vglite/lv_vglite_utils.h b/src/draw/nxp/vglite/lv_vglite_utils.h index 9ff4de02f..219396b10 100644 --- a/src/draw/nxp/vglite/lv_vglite_utils.h +++ b/src/draw/nxp/vglite/lv_vglite_utils.h @@ -71,6 +71,23 @@ extern "C" { * TYPEDEFS **********************/ +/********************** + * STATIC PROTOTYPES + **********************/ + +/** + * Enable scissor and set the clipping box. + * + * @param[in] clip_area Clip area with relative coordinates of destination buffer + */ +static inline void lv_vglite_set_scissor(const lv_area_t * clip_area); + +/** + * Disable scissor. + */ +static inline void lv_vglite_disable_scissor(void); + + /********************** * GLOBAL PROTOTYPES **********************/ @@ -157,6 +174,23 @@ lv_res_t lv_vglite_run(void); }while(0) #endif /*LV_GPU_NXP_VG_LITE_LOG_TRACES*/ +/********************** + * STATIC FUNCTIONS + **********************/ + +static inline void lv_vglite_set_scissor(const lv_area_t * clip_area) +{ + vg_lite_enable_scissor(); + vg_lite_set_scissor((int32_t)clip_area->x1, (int32_t)clip_area->y1, + (int32_t)lv_area_get_width(clip_area), + (int32_t)lv_area_get_height(clip_area)); +} + +static inline void lv_vglite_disable_scissor(void) +{ + vg_lite_disable_scissor(); +} + #endif /*LV_USE_GPU_NXP_VG_LITE*/ #ifdef __cplusplus