From 8a2a4a11c81d029ff737980b883c62dfbb4b44c6 Mon Sep 17 00:00:00 2001 From: Jozef Bastek Date: Tue, 8 Dec 2020 10:38:19 +0100 Subject: [PATCH 1/3] fix(pxp): update for v8 includes updates from NXP MCU SDK 2.10 with adaptation for lvgl v8: Updated cache handling - range limited cache flushing changed to complete cache flush, which is faster and shold be safe - flushing done via callback system, so OS specific code is removed from LVGL Signed-off-by: Jozef Bastek gpu: pxp: Buffer sync with BLITs Added buffer synchronisation with BLITs instead of memcpy for PXP. In LVGL v8, buffer synchronisation acceleration is moved to littlevgl_support.c. Signed-off-by: Jozef Bastek gpu: pxp: updates for v8 cache callback type changed in display driver struct chroma key name changed Signed-off-by: Seb Fagard gpu: pxp: new log header file for v8 Signed-off-by: Seb Fagard core: init PXP accelerator Signed-off-by: Seb Fagard --- src/core/lv_obj.c | 12 ++++++++++ src/gpu/lv_gpu_nxp_pxp.c | 46 +++++++----------------------------- src/gpu/lv_gpu_nxp_pxp.h | 5 ++++ src/gpu/lv_gpu_nxp_pxp_osa.c | 1 + 4 files changed, 27 insertions(+), 37 deletions(-) diff --git a/src/core/lv_obj.c b/src/core/lv_obj.c index 296d733cc..b7c95b307 100644 --- a/src/core/lv_obj.c +++ b/src/core/lv_obj.c @@ -30,6 +30,11 @@ #include "../gpu/lv_gpu_stm32_dma2d.h" #endif +#if LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT + #include "../gpu/lv_gpu_nxp_pxp.h" + #include "../gpu/lv_gpu_nxp_pxp_osa.h" +#endif + /********************* * DEFINES *********************/ @@ -105,6 +110,13 @@ void lv_init(void) lv_gpu_stm32_dma2d_init(); #endif +#if LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT + if(lv_gpu_nxp_pxp_init(&pxp_default_cfg) != LV_RES_OK) { + LV_LOG_ERROR("PXP init error. STOP.\n"); + for(; ;) ; + } +#endif + _lv_obj_style_init(); _lv_ll_init(&LV_GC_ROOT(_lv_disp_ll), sizeof(lv_disp_t)); _lv_ll_init(&LV_GC_ROOT(_lv_indev_ll), sizeof(lv_indev_t)); diff --git a/src/gpu/lv_gpu_nxp_pxp.c b/src/gpu/lv_gpu_nxp_pxp.c index 97753e822..1b669d861 100644 --- a/src/gpu/lv_gpu_nxp_pxp.c +++ b/src/gpu/lv_gpu_nxp_pxp.c @@ -71,8 +71,6 @@ static void lv_gpu_nxp_pxp_run(void); static void lv_gpu_nxp_pxp_blit_recolor(lv_color_t * dest, lv_coord_t dest_width, const lv_color_t * src, lv_coord_t src_width, lv_coord_t copy_width, lv_coord_t copy_height, lv_opa_t opa, lv_color_t recolor, lv_opa_t recolorOpa); -static void lv_gpu_nxp_invalidate_cache(uint32_t address, uint32_t width, uint32_t height, uint32_t stride, - uint32_t pxSize); /********************** * STATIC VARIABLES @@ -160,8 +158,7 @@ void lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, lv_coord_t dest_width, const lv_ .width = fill_area->x2 - fill_area->x1 + 1, .height = fill_area->y2 - fill_area->y1 + 1, }; - lv_gpu_nxp_invalidate_cache(outputConfig.buffer0Addr, outputConfig.width, outputConfig.height, outputConfig.pitchBytes, - sizeof(lv_color_t)); + PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputConfig); if(opa > LV_OPA_MAX) { @@ -272,9 +269,6 @@ void lv_gpu_nxp_pxp_blit(lv_color_t * dest, lv_coord_t dest_width, const lv_colo PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, copy_width - 1U, copy_height - 1U); PXP_SetAlphaSurfaceBlendConfig(LV_GPU_NXP_PXP_ID, &asBlendConfig); - lv_gpu_nxp_invalidate_cache(asBufferConfig.bufferAddr, copy_width, copy_height, asBufferConfig.pitchBytes, - sizeof(lv_color_t)); - if(colorKeyEnabled) { PXP_SetAlphaSurfaceOverlayColorKey(LV_GPU_NXP_PXP_ID, colorKey, colorKey); } @@ -290,10 +284,7 @@ void lv_gpu_nxp_pxp_blit(lv_color_t * dest, lv_coord_t dest_width, const lv_colo outputBufferConfig.height = copy_height; PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig); - lv_gpu_nxp_invalidate_cache(outputBufferConfig.buffer0Addr, outputBufferConfig.width, outputBufferConfig.height, - outputBufferConfig.pitchBytes, sizeof(lv_color_t)); - - lv_gpu_nxp_pxp_run(); /*Start PXP task*/ + lv_gpu_nxp_pxp_run(); /* Start PXP task */ } /** @@ -349,6 +340,12 @@ void lv_gpu_nxp_pxp_disable_recolor(void) */ static void lv_gpu_nxp_pxp_run(void) { + lv_disp_t * disp = _lv_refr_get_disp_refreshing(); + + if(disp && disp->driver->clean_dcache_cb) { /* Clean & invalidate cache */ + disp->driver->clean_dcache_cb(disp->driver); + } + pxp_cfg.pxp_run(); } @@ -396,9 +393,6 @@ static void lv_gpu_nxp_pxp_blit_recolor(lv_color_t * dest, lv_coord_t dest_width PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig); PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, copy_width - 1U, copy_height - 1U); - lv_gpu_nxp_invalidate_cache(asBufferConfig.bufferAddr, copy_width, copy_height, asBufferConfig.pitchBytes, - sizeof(lv_color_t)); - /*Disable PS buffer, use as color generator*/ PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U); PXP_SetProcessSurfaceBackGroundColor(LV_GPU_NXP_PXP_ID, lv_color_to32(recolor)); @@ -413,9 +407,6 @@ static void lv_gpu_nxp_pxp_blit_recolor(lv_color_t * dest, lv_coord_t dest_width outputBufferConfig.height = copy_height; PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig); - lv_gpu_nxp_invalidate_cache(outputBufferConfig.buffer0Addr, outputBufferConfig.width, outputBufferConfig.height, - outputBufferConfig.pitchBytes, sizeof(lv_color_t)); - pxp_porter_duff_config_t pdConfig; /*Configure Porter-Duff blending - For RGB 565 only!*/ @@ -454,23 +445,4 @@ static void lv_gpu_nxp_pxp_blit_recolor(lv_color_t * dest, lv_coord_t dest_width } } -/** - * @brief Invalidate cache for rectangular area of memory - * - * @param[in] address starting address of area - * @param[in] width width of area in pixels - * @param[in] height height of area in pixels - * @param[in] stride stride in bytes - * @param[in] pxSize pixel size in bytes - */ -static void lv_gpu_nxp_invalidate_cache(uint32_t address, uint32_t width, uint32_t height, uint32_t stride, - uint32_t pxSize) -{ - int y; - - for(y = 0; y < height; y++) { - DCACHE_CleanInvalidateByRange(address, width * pxSize); - address += stride; - } -} -#endif /*LV_USE_GPU && LV_USE_GPU_NXP_PXP*/ +#endif /* LV_USE_GPU_NXP_PXP */ diff --git a/src/gpu/lv_gpu_nxp_pxp.h b/src/gpu/lv_gpu_nxp_pxp.h index 9d3957246..9aba7c27d 100644 --- a/src/gpu/lv_gpu_nxp_pxp.h +++ b/src/gpu/lv_gpu_nxp_pxp.h @@ -61,6 +61,11 @@ extern "C" { #define LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT 16 #endif +#ifndef LV_GPU_NXP_PXP_BUFF_SYNC_BLIT_SIZE_LIMIT +/** Minimum invalidated area (in pixels) to be synchronized by PXP during buffer sync */ +#define LV_GPU_NXP_PXP_BUFF_SYNC_BLIT_SIZE_LIMIT 32 +#endif + #ifndef LV_GPU_NXP_PXP_FILL_SIZE_LIMIT /** Minimum area (in pixels) to be filled by PXP with 100% opacity*/ #define LV_GPU_NXP_PXP_FILL_SIZE_LIMIT 64 diff --git a/src/gpu/lv_gpu_nxp_pxp_osa.c b/src/gpu/lv_gpu_nxp_pxp_osa.c index 8e56efbf5..5a16db864 100644 --- a/src/gpu/lv_gpu_nxp_pxp_osa.c +++ b/src/gpu/lv_gpu_nxp_pxp_osa.c @@ -32,6 +32,7 @@ *********************/ #include "../lv_conf_internal.h" +#include "../misc/lv_log.h" #if LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT From e3e3eeaf8c1593d384c6537244a301cdc1abd3d9 Mon Sep 17 00:00:00 2001 From: Jozef Bastek Date: Fri, 4 Dec 2020 10:02:22 +0100 Subject: [PATCH 2/3] fix(vglite): update for v8 includes updates coming from NXP MCU SDK 2.10 with adaptation for lvgl v8: Fixed BLIT offset computation Previous implementation didn't take into account a possibility of non-zero offset in source image, so output was wrong if offset was used. With this fix, CPU and VG-Lite output is the same even with offsets. Signed-off-by: Jozef Bastek gpu: vglite: Buffer sync with BLITs Added buffer synchronisation with BLITs instead of memcpy for VG-Lite. In LVGL v8, buffer synchronisation acceleration is moved to littlevgl_support.c. Signed-off-by: Jozef Bastek gpu: vglite: Fixed BLIT boundary Fixed artifact issue revealed by buffer sync with BLIT feature. Caused by wrong BLIT boundary. Signed-off-by: Jozef Bastek gpu: vglite: BLIT quality degradation workaround for RT595 Limitation in RT595 causes BLIT image quality degradation when coordinates are above 368 px. This patch implements workaround that will break the BLIT into multiple smaller BLITs, so the quality is not affected for higher resolutions. Signed-off-by: Jozef Bastek gpu: vglite: Fix address alignment and stride requirements Fixed multiple issues: - The VGLite alignment requirement checks for the pixel destination buffer are not applicable in our case of Linear (non-tiled) format. - Some VGLite stride requirement requirement should be expressed in bytes, not in pixels. - Fix the Y alignment function to ensure that line starts at an address that the respects the alignment requirement of VG-Lite. Such mistakes do not break application, but cause a fallback to non-accelerated Blit by CPU. See MGG-741. Signed-off-by: Seb Fagard gpu: vglite: fix some MISRA C 2012 violations fixed 56 violations: mainly implicit format casts and unchecked returned values. see JIRA MCUX-43327 Signed-off-by: Seb Fagard gpu: vglite: fix stride requirement in _init_vg_buf() fix unit: need to convert the alignment requirement into bytes when checking stride parameter. fix condition: stride requirement applies only on source buffers. Signed-off-by: Seb Fagard gpu: vglite: updates for v8 cache callback type changed in display driver struct Signed-off-by: Seb Fagard gpu: vglite: update parameter type for v8 display driver is now a pointer in structure. Signed-off-by: Seb Fagard --- src/draw/lv_draw_blend.c | 16 +- src/gpu/lv_gpu_nxp_vglite.c | 570 ++++++++++++++++++++++++++++++++---- src/gpu/lv_gpu_nxp_vglite.h | 12 +- 3 files changed, 533 insertions(+), 65 deletions(-) diff --git a/src/draw/lv_draw_blend.c b/src/draw/lv_draw_blend.c index 31ca6ba0d..46ba49891 100644 --- a/src/draw/lv_draw_blend.c +++ b/src/draw/lv_draw_blend.c @@ -701,8 +701,8 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(const lv_area_t * disp_area, lv_col blit.src_stride = lv_area_get_width(map_area) * sizeof(lv_color_t); blit.src_area.x1 = (draw_area->x1 - (map_area->x1 - disp_area->x1)); blit.src_area.y1 = (draw_area->y1 - (map_area->y1 - disp_area->y1)); - blit.src_area.x2 = blit.src_area.x1 + draw_area_w; - blit.src_area.y2 = blit.src_area.y1 + draw_area_h; + blit.src_area.x2 = blit.src_area.x1 + draw_area_w - 1; + blit.src_area.y2 = blit.src_area.y1 + draw_area_h - 1; blit.dst = disp_buf; blit.dst_width = lv_area_get_width(disp_area); @@ -710,8 +710,8 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(const lv_area_t * disp_area, lv_col blit.dst_stride = lv_area_get_width(disp_area) * sizeof(lv_color_t); blit.dst_area.x1 = draw_area->x1; blit.dst_area.y1 = draw_area->y1; - blit.dst_area.x2 = blit.dst_area.x1 + draw_area_w; - blit.dst_area.y2 = blit.dst_area.y1 + draw_area_h; + blit.dst_area.x2 = blit.dst_area.x1 + draw_area_w - 1; + blit.dst_area.y2 = blit.dst_area.y1 + draw_area_h - 1; blit.opa = opa; @@ -751,8 +751,8 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(const lv_area_t * disp_area, lv_col blit.src_stride = lv_area_get_width(map_area) * sizeof(lv_color_t); blit.src_area.x1 = (draw_area->x1 - (map_area->x1 - disp_area->x1)); blit.src_area.y1 = (draw_area->y1 - (map_area->y1 - disp_area->y1)); - blit.src_area.x2 = blit.src_area.x1 + draw_area_w; - blit.src_area.y2 = blit.src_area.y1 + draw_area_h; + blit.src_area.x2 = blit.src_area.x1 + draw_area_w - 1; + blit.src_area.y2 = blit.src_area.y1 + draw_area_h - 1; blit.dst = disp_buf; blit.dst_width = lv_area_get_width(disp_area); @@ -760,8 +760,8 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(const lv_area_t * disp_area, lv_col blit.dst_stride = lv_area_get_width(disp_area) * sizeof(lv_color_t); blit.dst_area.x1 = draw_area->x1; blit.dst_area.y1 = draw_area->y1; - blit.dst_area.x2 = blit.dst_area.x1 + draw_area_w; - blit.dst_area.y2 = blit.dst_area.y1 + draw_area_h; + blit.dst_area.x2 = blit.dst_area.x1 + draw_area_w - 1; + blit.dst_area.y2 = blit.dst_area.y1 + draw_area_h - 1; blit.opa = opa; diff --git a/src/gpu/lv_gpu_nxp_vglite.c b/src/gpu/lv_gpu_nxp_vglite.c index 94ab5ca9a..6021300e7 100644 --- a/src/gpu/lv_gpu_nxp_vglite.c +++ b/src/gpu/lv_gpu_nxp_vglite.c @@ -40,27 +40,78 @@ #include "../misc/lv_log.h" #include "fsl_cache.h" #include "vg_lite.h" +#include "fsl_debug_console.h" /********************* * DEFINES *********************/ -/********************** - * TYPEDEFS - **********************/ - #if LV_COLOR_DEPTH==16 #define VGLITE_PX_FMT VG_LITE_RGB565 #else #error Only 16bit color depth is supported. Set LV_COLOR_DEPTH to 16. #endif +/* Enable BLIT quality degradation workaround for RT595 */ +#define RT595_BLIT_WRKRND_ENABLED 1 + +/* If LV_HOR_RES_MAX/LV_VER_RES_MAX is higher than this value, workaround will be enabled */ +#define RT595_BLIT_WRKRND_THR 352 + +/* Print detailed info to SDK console (NOT to LVGL log system) */ +#define BLIT_DBG_VERBOSE 0 + +/* Draw rectangles around BLIT tiles */ +#define BLIT_DBG_AREAS 0 + +/* Redirect PRINT to SDK PRINTF */ +#define PRINT PRINTF + +/* Verbose debug print */ +#if BLIT_DBG_VERBOSE + #define PRINT_BLT PRINTF +#else + #define PRINT_BLT(...) +#endif + +/* Internal compound symbol */ +#if (defined(CPU_MIMXRT595SFFOB) || defined(CPU_MIMXRT595SFFOB_cm33) || \ + defined(CPU_MIMXRT595SFFOC) || defined(CPU_MIMXRT595SFFOC_cm33)) && \ + ((LV_HOR_RES_MAX > RT595_BLIT_WRKRND_THR) || (LV_VER_RES_MAX > RT595_BLIT_WRKRND_THR)) && \ + RT595_BLIT_WRKRND_ENABLED + #define _BLIT_SPLIT_ENABLED 1 +#else + #define _BLIT_SPLIT_ENABLED 0 +#endif + +/* BLIT split threshold - BLITs with width or height higher than this value will be done + * in multiple steps. Value must be 16-aligned. Don't change. + * */ +#define LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR 352 + + +/********************** + * TYPEDEFS + **********************/ + /********************** * STATIC PROTOTYPES **********************/ -static lv_res_t init_vg_buf(vg_lite_buffer_t * dst, uint32_t width, uint32_t height, uint32_t stride, - const lv_color_t * ptr); +static lv_res_t _init_vg_buf(vg_lite_buffer_t * dst, uint32_t width, uint32_t height, uint32_t stride, + const lv_color_t * ptr, bool source); + +static lv_res_t _lv_gpu_nxp_vglite_blit_single(lv_gpu_nxp_vglite_blit_info_t * blit); +#if _BLIT_SPLIT_ENABLED +static void _align_x(lv_area_t * area, lv_color_t ** buf); +static void _align_y(lv_area_t * area, lv_color_t ** buf, uint32_t stridePx); +static void _sw_blit(lv_gpu_nxp_vglite_blit_info_t * blit); +#if BLIT_DBG_AREAS +static void _draw_rectangle(lv_color_t * dest_buf, lv_coord_t dest_width, lv_coord_t dest_height, + lv_area_t * fill_area, lv_color_t color); +#endif +static lv_res_t _lv_gpu_nxp_vglite_check_blit(lv_gpu_nxp_vglite_blit_info_t * blit); +#endif /********************** * STATIC VARIABLES @@ -70,6 +121,14 @@ static lv_res_t init_vg_buf(vg_lite_buffer_t * dst, uint32_t width, uint32_t hei * MACROS **********************/ +#define CHECK(cond, txt) \ + do { \ + if (cond) { \ + PRINT("%s. STOP!\n", txt); \ + for ( ; ; ); \ + } \ + } while(0) + /********************** * GLOBAL FUNCTIONS **********************/ @@ -94,25 +153,37 @@ lv_res_t lv_gpu_nxp_vglite_fill(lv_color_t * dest_buf, lv_coord_t dest_width, lv lv_color32_t col32 = {.full = lv_color_to32(color)}; /*Convert color to RGBA8888*/ lv_disp_t * disp = _lv_refr_get_disp_refreshing(); - if(init_vg_buf(&rt, dest_width, dest_height, dest_width * sizeof(lv_color_t), dest_buf) != LV_RES_OK) { + if(_init_vg_buf(&rt, (uint32_t) dest_width, (uint32_t) dest_height, (uint32_t) dest_width * sizeof(lv_color_t), (const lv_color_t *) dest_buf, false) != LV_RES_OK) { #if LV_GPU_NXP_VG_LITE_LOG_ERRORS LV_LOG_ERROR("init_vg_buf reported error. Fill failed."); #endif return LV_RES_INV; } - if(opa >= LV_OPA_MAX) { /*Opaque fill*/ + if(opa >= (lv_opa_t) LV_OPA_MAX) { /*Opaque fill*/ rect.x = fill_area->x1; rect.y = fill_area->y1; - rect.width = (fill_area->x2 - fill_area->x1) + 1; - rect.height = (fill_area->y2 - fill_area->y1) + 1; + rect.width = (int32_t) fill_area->x2 - (int32_t) fill_area->x1 + 1; + rect.height = (int32_t) fill_area->y2 - (int32_t) fill_area->y1 + 1; - if(disp && disp->driver->clean_dcache_cb) { /*Clean & invalidate cache*/ + if(disp != NULL && disp->driver->clean_dcache_cb != NULL) { /*Clean & invalidate cache*/ disp->driver->clean_dcache_cb(disp->driver); } - err |= vg_lite_clear(&rt, &rect, col32.full); - err |= vg_lite_finish(); + err = vg_lite_clear(&rt, &rect, col32.full); + if (err != VG_LITE_SUCCESS) { + #if LV_GPU_NXP_VG_LITE_LOG_ERRORS + LV_LOG_ERROR("vg_lite_clear reported error. Fill failed."); + #endif + return LV_RES_INV; + } + err = vg_lite_finish(); + if (err != VG_LITE_SUCCESS) { + #if LV_GPU_NXP_VG_LITE_LOG_ERRORS + LV_LOG_ERROR("vg_lite_finish reported error. Fill failed."); + #endif + return LV_RES_INV; + } } else { /*fill with transparency*/ @@ -127,8 +198,8 @@ lv_res_t lv_gpu_nxp_vglite_fill(lv_color_t * dest_buf, lv_coord_t dest_width, lv VLC_OP_END }; - err |= vg_lite_init_path(&path, VG_LITE_S16, VG_LITE_LOW, sizeof(path_data), path_data, - fill_area->x1, fill_area->y1, fill_area->x2 + 1, fill_area->y2 + 1); + err = vg_lite_init_path(&path, VG_LITE_S16, VG_LITE_LOW, sizeof(path_data), path_data, + (vg_lite_float_t) fill_area->x1, (vg_lite_float_t) fill_area->y1, ((vg_lite_float_t) fill_area->x2) + 1.0f, ((vg_lite_float_t) fill_area->y2) + 1.0f); if(err != VG_LITE_SUCCESS) { #if LV_GPU_NXP_VG_LITE_LOG_ERRORS LV_LOG_ERROR("vg_lite_init_path() failed."); @@ -136,12 +207,12 @@ lv_res_t lv_gpu_nxp_vglite_fill(lv_color_t * dest_buf, lv_coord_t dest_width, lv return LV_RES_INV; } - colMix.ch.red = ((uint16_t)col32.ch.red * opa) >> 8; /*Pre-multiply color*/ - colMix.ch.green = ((uint16_t)col32.ch.green * opa) >> 8; - colMix.ch.blue = ((uint16_t)col32.ch.blue * opa) >> 8; + colMix.ch.red = (uint8_t)(((uint16_t)col32.ch.red * opa) >> 8); /*Pre-multiply color*/ + colMix.ch.green = (uint8_t)(((uint16_t)col32.ch.green * opa) >> 8); + colMix.ch.blue = (uint8_t)(((uint16_t)col32.ch.blue * opa) >> 8); colMix.ch.alpha = opa; - if(disp && disp->driver->clean_dcache_cb) { /*Clean & invalidate cache*/ + if((disp != NULL) && (disp->driver->clean_dcache_cb != NULL)) { /*Clean & invalidate cache*/ disp->driver->clean_dcache_cb(disp->driver); } @@ -149,8 +220,8 @@ lv_res_t lv_gpu_nxp_vglite_fill(lv_color_t * dest_buf, lv_coord_t dest_width, lv vg_lite_identity(&matrix); /*Draw rectangle*/ - err |= vg_lite_draw(&rt, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, colMix.full); - if(err) { + err = vg_lite_draw(&rt, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, colMix.full); + if(err != VG_LITE_SUCCESS) { #if LV_GPU_NXP_VG_LITE_LOG_ERRORS LV_LOG_ERROR("vg_lite_draw() failed."); #endif @@ -158,8 +229,21 @@ lv_res_t lv_gpu_nxp_vglite_fill(lv_color_t * dest_buf, lv_coord_t dest_width, lv return LV_RES_INV; } - err |= vg_lite_finish(); - err |= vg_lite_clear_path(&path); + err = vg_lite_finish(); + if(err != VG_LITE_SUCCESS) { +#if LV_GPU_NXP_VG_LITE_LOG_ERRORS + LV_LOG_ERROR("vg_lite_finish() failed."); +#endif + return LV_RES_INV; + } + + err = vg_lite_clear_path(&path); + if(err != VG_LITE_SUCCESS) { +#if LV_GPU_NXP_VG_LITE_LOG_ERRORS + LV_LOG_ERROR("vg_lite_clear_path() failed."); +#endif + return LV_RES_INV; + } } if(err == VG_LITE_SUCCESS) { @@ -180,63 +264,255 @@ lv_res_t lv_gpu_nxp_vglite_fill(lv_color_t * dest_buf, lv_coord_t dest_width, lv * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) */ lv_res_t lv_gpu_nxp_vglite_blit(lv_gpu_nxp_vglite_blit_info_t * blit) +{ +#if _BLIT_SPLIT_ENABLED + + lv_res_t rv = LV_RES_INV; + + if(_lv_gpu_nxp_vglite_check_blit(blit) != LV_RES_OK) { + PRINT_BLT("Blit check failed\n"); + return LV_RES_INV; + } + + PRINT_BLT("BLIT from: " + "Area: %03d,%03d - %03d,%03d " + "Addr: %d\n\n", + blit->src_area.x1, blit->src_area.y1, + blit->src_area.x2, blit->src_area.y2, + (uintptr_t) blit->src); + + PRINT_BLT("BLIT to: " + "Area: %03d,%03d - %03d,%03d " + "Addr: %d\n\n", + blit->dst_area.x1, blit->dst_area.y1, + blit->dst_area.x2, blit->dst_area.y2, + (uintptr_t) blit->src); + + /* Stage 1: Move starting pointers as close as possible to [x1, y1], so coordinates are as small as possible. */ + _align_x(&blit->src_area, (lv_color_t **)&blit->src); + _align_y(&blit->src_area, (lv_color_t **)&blit->src, blit->src_stride / sizeof(lv_color_t)); + _align_x(&blit->dst_area, (lv_color_t **)&blit->dst); + _align_y(&blit->dst_area, (lv_color_t **)&blit->dst, blit->dst_stride / sizeof(lv_color_t)); + + /* Stage 2: If we're in limit, do a single BLIT */ + if((blit->src_area.x2 < LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) && + (blit->src_area.y2 < LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR)) { + PRINT_BLT("Simple blit!\n"); + return _lv_gpu_nxp_vglite_blit_single(blit); + }; + + /* Stage 3: Split the BLIT into multiple tiles */ + PRINT_BLT("Split blit!\n"); + + PRINT_BLT("Blit " + "([%03d,%03d], [%03d,%03d]) -> " + "([%03d,%03d], [%03d,%03d]) | " + "([%03dx%03d] -> [%03dx%03d]) | " + "A:(%d -> %d)\n", + blit->src_area.x1, blit->src_area.y1, blit->src_area.x2, blit->src_area.y2, + blit->dst_area.x1, blit->dst_area.y1, blit->dst_area.x2, blit->dst_area.y2, + lv_area_get_width(&blit->src_area), lv_area_get_height(&blit->src_area), + lv_area_get_width(&blit->dst_area), lv_area_get_height(&blit->dst_area), + (uintptr_t) blit->src, (uintptr_t) blit->dst); + + + uint32_t totalWidth = lv_area_get_width(&blit->src_area); + uint32_t totalHeight = lv_area_get_height(&blit->src_area); + + lv_gpu_nxp_vglite_blit_info_t tileBlit; + + /* Number of tiles needed */ + int totalTilesX = (blit->src_area.x1 + totalWidth + LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1) / + LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR; + int totalTilesY = (blit->src_area.y1 + totalHeight + LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1) / + LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR; + + /* src and dst buffer shift against each other. Src buffer real data [0,0] may start actually at [3,0] in buffer, as + * the buffer pointer has to be aligned, while dst buffer real data [0,0] may start at [1,0] in buffer. alignment may be + * different */ + int shiftSrcX = (blit->src_area.x1 > blit->dst_area.x1) ? (blit->src_area.x1 - blit->dst_area.x1) : 0; + int shiftDstX = (blit->src_area.x1 < blit->dst_area.x1) ? (blit->dst_area.x1 - blit->src_area.x1) : 0; + + PRINT_BLT("\n"); + PRINT_BLT("Align shift: src: %d, dst: %d\n", shiftSrcX, shiftDstX); + + tileBlit = *blit; + + for(int tileY = 0; tileY < totalTilesY; tileY++) { + + tileBlit.src_area.y1 = 0; /* no vertical alignment, always start from 0 */ + tileBlit.src_area.y2 = totalHeight - tileY * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; + if(tileBlit.src_area.y2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) { + tileBlit.src_area.y2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; /* Should never happen */ + } + tileBlit.src = blit->src + tileY * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR * blit->src_stride / sizeof( + lv_color_t); /* stride in px! */ + + tileBlit.dst_area.y1 = tileBlit.src_area.y1; /* y has no alignment, always in sync with src */ + tileBlit.dst_area.y2 = tileBlit.src_area.y2; + + tileBlit.dst = blit->dst + tileY * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR * blit->dst_stride / sizeof( + lv_color_t); /* stride in px! */ + + for(int tileX = 0; tileX < totalTilesX; tileX++) { + + if(tileX == 0) { + /* 1st tile is special - there may be a gap between buffer start pointer + * and area.x1 value, as the pointer has to be aligned. + * tileBlit.src pointer - keep init value from Y-loop. + * Also, 1st tile start is not shifted! shift is applied from 2nd tile */ + tileBlit.src_area.x1 = blit->src_area.x1; + tileBlit.dst_area.x1 = blit->dst_area.x1; + } + else { + /* subsequent tiles always starts from 0, but shifted*/ + tileBlit.src_area.x1 = 0 + shiftSrcX; + tileBlit.dst_area.x1 = 0 + shiftDstX; + /* and advance start pointer + 1 tile size */ + tileBlit.src += LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR; + tileBlit.dst += LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR; + } + + /* Clip tile end coordinates */ + tileBlit.src_area.x2 = totalWidth + blit->src_area.x1 - tileX * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; + if(tileBlit.src_area.x2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) { + tileBlit.src_area.x2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; + } + + tileBlit.dst_area.x2 = totalWidth + blit->dst_area.x1 - tileX * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; + if(tileBlit.dst_area.x2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) { + tileBlit.dst_area.x2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; + } + + if(tileX < (totalTilesX - 1)) { + /* And adjust end coords if shifted, but not for last tile! */ + tileBlit.src_area.x2 += shiftSrcX; + tileBlit.dst_area.x2 += shiftDstX; + } + + rv = _lv_gpu_nxp_vglite_blit_single(&tileBlit); + +#if BLIT_DBG_AREAS + _draw_rectangle((lv_color_t *) tileBlit.dst, tileBlit.dst_width, tileBlit.dst_height, &tileBlit.dst_area, LV_COLOR_RED); + _draw_rectangle((lv_color_t *) tileBlit.src, tileBlit.src_width, tileBlit.src_height, &tileBlit.src_area, + LV_COLOR_GREEN); +#endif + + PRINT_BLT("Tile [%d, %d]: " + "([%d,%d], [%d,%d]) -> " + "([%d,%d], [%d,%d]) | " + "([%dx%d] -> [%dx%d]) | " + "A:(0x%8X -> 0x%8X) %s\n", + tileX, tileY, + tileBlit.src_area.x1, tileBlit.src_area.y1, tileBlit.src_area.x2, tileBlit.src_area.y2, + tileBlit.dst_area.x1, tileBlit.dst_area.y1, tileBlit.dst_area.x2, tileBlit.dst_area.y2, + lv_area_get_width(&tileBlit.src_area), lv_area_get_height(&tileBlit.src_area), + lv_area_get_width(&tileBlit.dst_area), lv_area_get_height(&tileBlit.dst_area), + (uintptr_t) tileBlit.src, (uintptr_t) tileBlit.dst, + rv == LV_RES_OK ? "OK!" : "!!! FAILED !!!"); + + if(rv != LV_RES_OK) { /* if anything goes wrong... */ +#if LV_GPU_NXP_VG_LITE_LOG_ERRORS + LV_LOG_ERROR("Split BLIT failed. Trying SW BLIT instead."); +#endif + _sw_blit(&tileBlit); + rv = LV_RES_OK; /* Don't report error, as SW BLIT was performed */ + } + + } + PRINT_BLT(" \n"); + } + + return rv; /* should never fail */ + +#else /* non RT595 */ + /* Just pass down */ + return _lv_gpu_nxp_vglite_blit_single(blit); +#endif +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +/*** + * BLock Image Transfer - single direct BLIT. + * @param[in] blit Description of the transfer + * @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_gpu_nxp_vglite_blit_single(lv_gpu_nxp_vglite_blit_info_t * blit) { vg_lite_buffer_t src_vgbuf, dst_vgbuf; vg_lite_error_t err = VG_LITE_SUCCESS; uint32_t rect[4]; lv_disp_t * disp = _lv_refr_get_disp_refreshing(); - if(blit->opa < LV_OPA_MIN) { + if(blit == NULL) { + /*Wrong parameter*/ + return LV_RES_INV; + } + + if(blit->opa < (lv_opa_t) LV_OPA_MIN) { return LV_RES_OK; /*Nothing to BLIT*/ } - if(!blit) { - /*Wrong parameter*/ - return LV_RES_INV; - } - /*Wrap src/dst buffer into VG-Lite buffer*/ - if(init_vg_buf(&src_vgbuf, blit->src_width, blit->src_height, blit->src_stride, blit->src) != LV_RES_OK) { + if(_init_vg_buf(&src_vgbuf, (uint32_t) blit->src_width, (uint32_t) blit->src_height, (uint32_t) blit->src_stride, blit->src, true) != LV_RES_OK) { #if LV_GPU_NXP_VG_LITE_LOG_ERRORS LV_LOG_ERROR("init_vg_buf reported error. BLIT failed."); #endif return LV_RES_INV; } - if(init_vg_buf(&dst_vgbuf, blit->dst_width, blit->dst_height, blit->dst_stride, blit->dst) != LV_RES_OK) { + if(_init_vg_buf(&dst_vgbuf, (uint32_t) blit->dst_width, (uint32_t) blit->dst_height, (uint32_t) blit->dst_stride, blit->dst, false) != LV_RES_OK) { #if LV_GPU_NXP_VG_LITE_LOG_ERRORS LV_LOG_ERROR("init_vg_buf reported error. BLIT failed."); #endif return LV_RES_INV; } - rect[0] = 0; /*Crop*/ - rect[1] = 0; - rect[2] = blit->src_width; - rect[3] = blit->src_height; + rect[0] = (uint32_t) blit->src_area.x1; /* start x */ + rect[1] = (uint32_t) blit->src_area.y1; /* start y */ + rect[2] = (uint32_t) blit->src_area.x2 - (uint32_t) blit->src_area.x1 + 1U; /* width */ + rect[3] = (uint32_t) blit->src_area.y2 - (uint32_t) blit->src_area.y1 + 1U; /* height */ vg_lite_matrix_t matrix; vg_lite_identity(&matrix); - vg_lite_translate(blit->dst_area.x1, blit->dst_area.y1, &matrix); + vg_lite_translate((vg_lite_float_t)blit->dst_area.x1, (vg_lite_float_t)blit->dst_area.y1, &matrix); - if(disp && disp->driver->clean_dcache_cb) { /*Clean & invalidate cache*/ + if((disp != NULL) && (disp->driver->clean_dcache_cb != NULL)) { /*Clean & invalidate cache*/ disp->driver->clean_dcache_cb(disp->driver); } uint32_t color; vg_lite_blend_t blend; - if(blit->opa >= LV_OPA_MAX) { + if(blit->opa >= (uint8_t) LV_OPA_MAX) { color = 0x0; blend = VG_LITE_BLEND_NONE; } else { - color = ((blit->opa) << 24) | ((blit->opa) << 16) | ((blit->opa) << 8) | (blit->opa); + uint32_t opa = (uint32_t) blit->opa; + color = (opa << 24) | (opa << 16) | (opa << 8) | opa; blend = VG_LITE_BLEND_SRC_OVER; src_vgbuf.image_mode = VG_LITE_MULTIPLY_IMAGE_MODE; } - err |= vg_lite_blit_rect(&dst_vgbuf, &src_vgbuf, rect, &matrix, blend, color, VG_LITE_FILTER_POINT); - err |= vg_lite_finish(); + err = vg_lite_blit_rect(&dst_vgbuf, &src_vgbuf, rect, &matrix, blend, color, VG_LITE_FILTER_POINT); + if(err != VG_LITE_SUCCESS) { +#if LV_GPU_NXP_VG_LITE_LOG_ERRORS + LV_LOG_ERROR("vg_lite_blit_rect() failed."); +#endif + return LV_RES_INV; + } + + err = vg_lite_finish(); + if(err != VG_LITE_SUCCESS) { +#if LV_GPU_NXP_VG_LITE_LOG_ERRORS + LV_LOG_ERROR("vg_lite_finish() failed."); +#endif + return LV_RES_INV; + } if(err == VG_LITE_SUCCESS) { return LV_RES_OK; @@ -249,10 +525,6 @@ lv_res_t lv_gpu_nxp_vglite_blit(lv_gpu_nxp_vglite_blit_info_t * blit) } } -/********************** - * STATIC FUNCTIONS - **********************/ - /*** * Fills vg_lite_buffer_t structure according given parameters. * @param[out] dst Buffer structure to be filled @@ -261,19 +533,19 @@ lv_res_t lv_gpu_nxp_vglite_blit(lv_gpu_nxp_vglite_blit_info_t * blit) * @param[in] stride Stride of the buffer in bytes * @param[in] ptr Pointer to the buffer (must be aligned according VG-Lite requirements) */ -static lv_res_t init_vg_buf(vg_lite_buffer_t * dst, uint32_t width, uint32_t height, uint32_t stride, - const lv_color_t * ptr) +static lv_res_t _init_vg_buf(vg_lite_buffer_t * dst, uint32_t width, uint32_t height, uint32_t stride, + const lv_color_t * ptr, bool source) { - if((((uintptr_t)ptr) % LV_ATTRIBUTE_MEM_ALIGN_SIZE) != 0x0) { /*Test for alignment*/ + if((((uintptr_t)ptr) % (uintptr_t)LV_ATTRIBUTE_MEM_ALIGN_SIZE) != 0x0U) { /*Test for alignment*/ #if LV_GPU_NXP_VG_LITE_LOG_ERRORS LV_LOG_ERROR("ptr (0x%X) not aligned to %d.", (size_t) ptr, LV_ATTRIBUTE_MEM_ALIGN_SIZE); #endif return LV_RES_INV; } - if((stride % LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX) != 0x0) { /*Test for stride alignment*/ + if(source && (stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * sizeof(lv_color_t))) != 0x0U) { /*Test for stride alignment*/ #if LV_GPU_NXP_VG_LITE_LOG_ERRORS - LV_LOG_ERROR("Buffer stride (%d px) not aligned to %d px.", stride, LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); + LV_LOG_ERROR("Buffer stride (%d px) not aligned to %d bytes.", stride, LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * sizeof(lv_color_t)); #endif return LV_RES_INV; } @@ -283,17 +555,205 @@ static lv_res_t init_vg_buf(vg_lite_buffer_t * dst, uint32_t width, uint32_t hei dst->image_mode = VG_LITE_NORMAL_IMAGE_MODE; dst->transparency_mode = VG_LITE_IMAGE_OPAQUE; - dst->width = width; - dst->height = height; - dst->stride = stride; + dst->width = (int32_t) width; + dst->height = (int32_t) height; + dst->stride = (int32_t) stride; - memset(&dst->yuv, 0, sizeof(dst->yuv)); + void *r_ptr = memset(&dst->yuv, 0, sizeof(dst->yuv)); + if (r_ptr == NULL) { + return LV_RES_INV; + } dst->memory = (void *)ptr; dst->address = (uint32_t) dst->memory; - dst->handle = 0x0; + dst->handle = NULL; return LV_RES_OK; } +#if _BLIT_SPLIT_ENABLED + +/** + * Software BLIT as a fall-back scenario + * @param[in] blit BLIT configuration + */ +static void _sw_blit(lv_gpu_nxp_vglite_blit_info_t * blit) +{ + int x, y; + + lv_coord_t w = lv_area_get_width(&blit->src_area); + lv_coord_t h = lv_area_get_height(&blit->src_area); + + uint32_t srcStridePx = blit->src_stride / sizeof(lv_color_t); + uint32_t dstStridePx = blit->dst_stride / sizeof(lv_color_t); + + lv_color_t * src = (lv_color_t *)blit->src + blit->src_area.y1 * srcStridePx + blit->src_area.x1; + lv_color_t * dst = (lv_color_t *)blit->dst + blit->dst_area.y1 * dstStridePx + blit->dst_area.x1; + + if(blit->opa >= LV_OPA_MAX) { + /* simple copy */ + for(y = 0; y < h; y++) { + _lv_memcpy(dst, src, w * sizeof(lv_color_t)); + src += srcStridePx; + dst += dstStridePx; + } + } + else if(blit->opa >= LV_OPA_MIN) { + /* alpha blending */ + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + dst[x] = lv_color_mix(src[x], dst[x], blit->opa); + } + src += srcStridePx; + dst += dstStridePx; + } + } +} + +/** + * Verify BLIT structure - widths, stride, pointer alignment + * @param[in] blit + * @return + */ +static lv_res_t _lv_gpu_nxp_vglite_check_blit(lv_gpu_nxp_vglite_blit_info_t * blit) +{ + + if(lv_area_get_width(&blit->src_area) < LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX) { /* Test for minimal width */ +#if LV_GPU_NXP_VG_LITE_LOG_ERRORS + LV_LOG_ERROR("source area width (%d) is smaller than required (%d).", lv_area_get_width(&blit->src_area), + LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); +#endif + return LV_RES_INV; + } + + if(lv_area_get_width(&blit->dst_area) < LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX) { /* Test for minimal width */ +#if LV_GPU_NXP_VG_LITE_LOG_ERRORS + LV_LOG_ERROR("destination area width (%d) is smaller than required (%d).", lv_area_get_width(&blit->dst_area), + LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); +#endif + return LV_RES_INV; + } + + if((((uintptr_t) blit->src) % LV_ATTRIBUTE_MEM_ALIGN_SIZE) != 0x0) { /* Test for pointer alignment */ +#if LV_GPU_NXP_VG_LITE_LOG_ERRORS + LV_LOG_ERROR("source buffer ptr (0x%X) not aligned to %d.", (size_t) blit->src, LV_ATTRIBUTE_MEM_ALIGN_SIZE); +#endif + return LV_RES_INV; + } + /* No alignment requirement for destination pixel buffer when using mode VG_LITE_LINEAR */ + + if((blit->src_stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * LV_COLOR_DEPTH / 8)) != 0x0) { /* Test for stride alignment */ +#if LV_GPU_NXP_VG_LITE_LOG_ERRORS + LV_LOG_ERROR("source buffer stride (%d px) not aligned to %d px.", blit->src_stride, LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); +#endif + return LV_RES_INV; + } + + if((blit->dst_stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * LV_COLOR_DEPTH / 8)) != 0x0) { /* Test for stride alignment */ +#if LV_GPU_NXP_VG_LITE_LOG_ERRORS + LV_LOG_ERROR("destination buffer stride (%d px) not aligned to %d px.", blit->dst_stride, LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); +#endif + return LV_RES_INV; + } + + if((lv_area_get_width(&blit->src_area) != lv_area_get_width(&blit->dst_area)) || + (lv_area_get_height(&blit->src_area) != lv_area_get_height(&blit->dst_area))) { +#if LV_GPU_NXP_VG_LITE_LOG_ERRORS + LV_LOG_ERROR("source and destination buffer areas are not equal."); +#endif + return LV_RES_INV; + } + + return LV_RES_OK; +} + +/*** + * Move buffer pointer as close as possible to area, but with respect to alignment requirements. X-axis only. + * @param[in,out] area Area to be updated + * @param[in,out] buf Pointer to be updated + */ +static void _align_x(lv_area_t * area, lv_color_t ** buf) +{ + + int alignedAreaStartPx = area->x1 - (area->x1 % (LV_ATTRIBUTE_MEM_ALIGN_SIZE * 8 / LV_COLOR_DEPTH) ); + CHECK(alignedAreaStartPx < 0, "Should never happen."); + + area->x1 -= alignedAreaStartPx; + area->x2 -= alignedAreaStartPx; + *buf += alignedAreaStartPx; +} + +/*** + * Move buffer pointer to the area start and update variables, Y-axis only. + * @param[in,out] area Area to be updated + * @param[in,out] buf Pointer to be updated + * @param[in] stridePx Buffer stride in pixels + */ +static void _align_y(lv_area_t * area, lv_color_t ** buf, uint32_t stridePx) +{ + int LineToAlignMem; + int alignedAreaStartPy; + /* find how many lines of pixels will respect memory alignment requirement */ + if(stridePx % LV_ATTRIBUTE_MEM_ALIGN_SIZE == 0) { + alignedAreaStartPy = area->y1; + } else { + LineToAlignMem = LV_ATTRIBUTE_MEM_ALIGN_SIZE / (sizeof(lv_color_t) * LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); + CHECK(LV_ATTRIBUTE_MEM_ALIGN_SIZE % (sizeof(lv_color_t) * LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX) != 0, "Complex case: need gcd function."); + alignedAreaStartPy = area->y1 - (area->y1 % LineToAlignMem); + CHECK(alignedAreaStartPy < 0, "Should never happen."); + } + + area->y1 -= alignedAreaStartPy; + area->y2 -= alignedAreaStartPy; + *buf += alignedAreaStartPy * stridePx; +} + +#if BLIT_DBG_AREAS +/*** + * Draws a simple rectangle, 1 px line width. + * @param dest_buf Destination buffer + * @param dest_width Destination buffer width (must be aligned on 16px) + * @param dest_height Destination buffer height + * @param fill_area Rectangle coordinates + * @param color Rectangle color + */ +static void _draw_rectangle(lv_color_t * dest_buf, lv_coord_t dest_width, lv_coord_t dest_height, + lv_area_t * fill_area, lv_color_t color) +{ + + lv_area_t a; + + /* top line */ + a.x1 = fill_area->x1; + a.x2 = fill_area->x2; + a.y1 = fill_area->y1; + a.y2 = fill_area->y1; + lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER); + + + /* bottom line */ + a.x1 = fill_area->x1; + a.x2 = fill_area->x2; + a.y1 = fill_area->y2; + a.y2 = fill_area->y2; + lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER); + + /* left line */ + a.x1 = fill_area->x1; + a.x2 = fill_area->x1; + a.y1 = fill_area->y1; + a.y2 = fill_area->y2; + lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER); + + /* right line */ + a.x1 = fill_area->x2; + a.x2 = fill_area->x2; + a.y1 = fill_area->y1; + a.y2 = fill_area->y2; + lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER); +} +#endif /* BLIT_DBG_AREAS */ + +#endif /* _BLIT_SPLIT_ENABLED */ + #endif /*LV_USE_GPU_NXP_VG_LITE*/ diff --git a/src/gpu/lv_gpu_nxp_vglite.h b/src/gpu/lv_gpu_nxp_vglite.h index 3f8b71734..31416598e 100644 --- a/src/gpu/lv_gpu_nxp_vglite.h +++ b/src/gpu/lv_gpu_nxp_vglite.h @@ -43,8 +43,11 @@ extern "C" { * DEFINES *********************/ -/** Stride in px required by VG-Lite HW. Don't change this.*/ -#define LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX 16 +/** Use this symbol as limit to disable feature (value has to be larger than supported resolution) */ +#define LV_GPU_NXP_VG_LITE_FEATURE_DISABLED (1920*1080+1) + +/** Stride in px required by VG-Lite HW. Don't change this. */ +#define LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX 16U #ifndef LV_GPU_NXP_VG_LITE_FILL_SIZE_LIMIT /** Minimum area (in pixels) to be filled by VG-Lite with 100% opacity*/ @@ -61,6 +64,11 @@ extern "C" { #define LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT 32 #endif +#ifndef LV_GPU_NXP_VG_LITE_BUFF_SYNC_BLIT_SIZE_LIMIT +/** Minimum invalidated area (in pixels) to be synchronized by VG-Lite during buffer sync */ +#define LV_GPU_NXP_VG_LITE_BUFF_SYNC_BLIT_SIZE_LIMIT 32 +#endif + #ifndef LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT /** Minimum area (in pixels) for image copy with transparency to be handled by VG-Lite*/ #define LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT 32 From 00c3eb197cb85e480809d97eb722589d75d81d94 Mon Sep 17 00:00:00 2001 From: Seb Fagard Date: Tue, 16 Mar 2021 16:42:01 +0100 Subject: [PATCH 3/3] fix(pxp): update RTOS macro for SDK 2.10 replace FSL_RTOS_FREE_RTOS by SDK_OS_FREE_RTOS in order to be aligned with MCU SDK 2.10. See MCUX-41577. Signed-off-by: Seb Fagard --- Kconfig | 2 +- lv_conf_template.h | 2 +- src/gpu/lv_gpu_nxp_pxp_osa.c | 16 ++++++++-------- src/lv_conf_internal.h | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Kconfig b/Kconfig index f509d9654..f0e629532 100644 --- a/Kconfig +++ b/Kconfig @@ -166,7 +166,7 @@ menu "LVGL configuration" 1: Add default bare metal and FreeRTOS interrupt handling routines for PXP (lv_gpu_nxp_pxp_osa.c) and call lv_gpu_nxp_pxp_init() automatically during lv_init(). - Note that symbol FSL_RTOS_FREE_RTOS has to be defined in order + Note that symbol SDK_OS_FREE_RTOS has to be defined in order to use FreeRTOS OSA, otherwise bare-metal implementation is selected. 0: lv_gpu_nxp_pxp_init() has to be called manually before diff --git a/lv_conf_template.h b/lv_conf_template.h index 36a380cba..2e2f7e36a 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -122,7 +122,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ #define LV_USE_GPU_NXP_PXP 0 #if LV_USE_GPU_NXP_PXP /*1: Add default bare metal and FreeRTOS interrupt handling routines for PXP (lv_gpu_nxp_pxp_osa.c) - * and call lv_gpu_nxp_pxp_init() automatically during lv_init(). Note that symbol FSL_RTOS_FREE_RTOS + * and call lv_gpu_nxp_pxp_init() automatically during lv_init(). Note that symbol SDK_OS_FREE_RTOS * has to be defined in order to use FreeRTOS OSA, otherwise bare-metal implementation is selected. *0: lv_gpu_nxp_pxp_init() has to be called manually before lv_init() */ diff --git a/src/gpu/lv_gpu_nxp_pxp_osa.c b/src/gpu/lv_gpu_nxp_pxp_osa.c index 5a16db864..d247f2b74 100644 --- a/src/gpu/lv_gpu_nxp_pxp_osa.c +++ b/src/gpu/lv_gpu_nxp_pxp_osa.c @@ -39,7 +39,7 @@ #include "lv_gpu_nxp_pxp.h" #include "fsl_pxp.h" -#if defined(FSL_RTOS_FREE_RTOS) +#if defined(SDK_OS_FREE_RTOS) #include "FreeRTOS.h" #include "semphr.h" #endif @@ -63,7 +63,7 @@ static void _lv_gpu_nxp_pxp_run(void); * STATIC VARIABLES **********************/ -#if defined(FSL_RTOS_FREE_RTOS) +#if defined(SDK_OS_FREE_RTOS) static SemaphoreHandle_t s_pxpIdle; #else static volatile bool s_pxpIdle; @@ -82,13 +82,13 @@ static void _lv_gpu_nxp_pxp_run(void); */ void PXP_IRQHandler(void) { -#if defined(FSL_RTOS_FREE_RTOS) +#if defined(SDK_OS_FREE_RTOS) BaseType_t taskAwake = pdFALSE; #endif if(kPXP_CompleteFlag & PXP_GetStatusFlags(LV_GPU_NXP_PXP_ID)) { PXP_ClearStatusFlags(LV_GPU_NXP_PXP_ID, kPXP_CompleteFlag); -#if defined(FSL_RTOS_FREE_RTOS) +#if defined(SDK_OS_FREE_RTOS) xSemaphoreGiveFromISR(s_pxpIdle, &taskAwake); portYIELD_FROM_ISR(taskAwake); #else @@ -107,7 +107,7 @@ void PXP_IRQHandler(void) */ static lv_res_t _lv_gpu_nxp_pxp_interrupt_init(void) { -#if defined(FSL_RTOS_FREE_RTOS) +#if defined(SDK_OS_FREE_RTOS) s_pxpIdle = xSemaphoreCreateBinary(); if(s_pxpIdle == NULL) { return LV_RES_INV; @@ -129,7 +129,7 @@ static lv_res_t _lv_gpu_nxp_pxp_interrupt_init(void) static void _lv_gpu_nxp_pxp_interrupt_deinit(void) { NVIC_DisableIRQ(LV_GPU_NXP_PXP_IRQ_ID); -#if defined(FSL_RTOS_FREE_RTOS) +#if defined(SDK_OS_FREE_RTOS) vSemaphoreDelete(s_pxpIdle); #endif } @@ -139,14 +139,14 @@ static void _lv_gpu_nxp_pxp_interrupt_deinit(void) */ static void _lv_gpu_nxp_pxp_run(void) { -#if !defined(FSL_RTOS_FREE_RTOS) +#if !defined(SDK_OS_FREE_RTOS) s_pxpIdle = false; #endif PXP_EnableInterrupts(LV_GPU_NXP_PXP_ID, kPXP_CompleteInterruptEnable); PXP_Start(LV_GPU_NXP_PXP_ID); -#if defined(FSL_RTOS_FREE_RTOS) +#if defined(SDK_OS_FREE_RTOS) if(xSemaphoreTake(s_pxpIdle, portMAX_DELAY) != pdTRUE) { LV_LOG_ERROR("xSemaphoreTake error. Task halted."); for(; ;) ; diff --git a/src/lv_conf_internal.h b/src/lv_conf_internal.h index 8f8a58691..6abd8bdc6 100644 --- a/src/lv_conf_internal.h +++ b/src/lv_conf_internal.h @@ -307,7 +307,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ #endif #if LV_USE_GPU_NXP_PXP /*1: Add default bare metal and FreeRTOS interrupt handling routines for PXP (lv_gpu_nxp_pxp_osa.c) - * and call lv_gpu_nxp_pxp_init() automatically during lv_init(). Note that symbol FSL_RTOS_FREE_RTOS + * and call lv_gpu_nxp_pxp_init() automatically during lv_init(). Note that symbol SDK_OS_FREE_RTOS * has to be defined in order to use FreeRTOS OSA, otherwise bare-metal implementation is selected. *0: lv_gpu_nxp_pxp_init() has to be called manually before lv_init() */