From fd79a4f42712f5640d43e46f245498e99705f6d8 Mon Sep 17 00:00:00 2001 From: Akos Becsey Date: Wed, 19 Jun 2024 15:34:31 +0200 Subject: [PATCH] feat(glcdc): screen rotation support --- .../driver/display/renesas_glcdc.rst | 20 ++++++++++++ .../display/renesas_glcdc/lv_renesas_glcdc.c | 32 +++++++++++++++++-- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/docs/integration/driver/display/renesas_glcdc.rst b/docs/integration/driver/display/renesas_glcdc.rst index de7cfe019..b3d4dbd65 100644 --- a/docs/integration/driver/display/renesas_glcdc.rst +++ b/docs/integration/driver/display/renesas_glcdc.rst @@ -59,3 +59,23 @@ Buffer swapping can be activated by passing a second buffer of same size instead lv_display_t * disp = lv_renesas_glcdc_partial_create(partial_draw_buf, NULL, sizeof(partial_draw_buf)); lv_display_set_default(disp); + +.. note:: + + Partial mode can be activated via the macro in ``src/board_init.c`` file of the demo projects. + + +Screen rotation +""""""""""""""" + +Software based screen rotation is supported in partial mode. It uses the common API, no extra configuration is required: + +.. code:: c + + lv_display_set_rotation(lv_display_get_default(), LV_DISP_ROTATION_90); + /* OR */ + lv_display_set_rotation(lv_display_get_default(), LV_DISP_ROTATION_180); + /* OR */ + lv_display_set_rotation(lv_display_get_default(), LV_DISP_ROTATION_270); + +Make sure the heap is large enough, as a buffer with the same size as the partial buffer will be allocated. diff --git a/src/drivers/display/renesas_glcdc/lv_renesas_glcdc.c b/src/drivers/display/renesas_glcdc/lv_renesas_glcdc.c index 342286a1d..16de73472 100644 --- a/src/drivers/display/renesas_glcdc/lv_renesas_glcdc.c +++ b/src/drivers/display/renesas_glcdc/lv_renesas_glcdc.c @@ -36,6 +36,7 @@ #include #include "../../../display/lv_display_private.h" +#include "../../../draw/sw/lv_draw_sw.h" /********************* * DEFINES @@ -76,6 +77,9 @@ static glcdc_runtime_cfg_t g_layer_change; display_t g_display0_cfg; #endif /*_RENESAS_RX_*/ +static void * rotation_buffer = NULL; +static uint32_t partial_buffer_size = 0; + /********************** * MACROS **********************/ @@ -92,6 +96,7 @@ lv_display_t * lv_renesas_glcdc_direct_create(void) lv_display_t * lv_renesas_glcdc_partial_create(void * buf1, void * buf2, size_t buf_size) { + partial_buffer_size = buf_size; return glcdc_create(buf1, buf2, buf_size, LV_DISPLAY_RENDER_MODE_PARTIAL); } @@ -277,13 +282,36 @@ static void flush_wait_direct(lv_display_t * display) static void flush_partial(lv_display_t * display, const lv_area_t * area, uint8_t * px_map) { - LV_UNUSED(display); + uint16_t * img = (uint16_t *)px_map; + + lv_color_format_t cf = lv_display_get_color_format(display); + lv_display_rotation_t rotation = lv_display_get_rotation(display); + + if(rotation != LV_DISPLAY_ROTATION_0) { + int32_t w = lv_area_get_width(area); + int32_t h = lv_area_get_height(area); + uint32_t w_stride = lv_draw_buf_width_to_stride(w, cf); + uint32_t h_stride = lv_draw_buf_width_to_stride(h, cf); + + // only allocate if rotation is actually being used + if(!rotation_buffer) { + rotation_buffer = lv_malloc(partial_buffer_size); + LV_ASSERT_MALLOC(rotation_buffer); + } + + if(rotation == LV_DISPLAY_ROTATION_180) + lv_draw_sw_rotate(img, rotation_buffer, w, h, w_stride, w_stride, rotation, cf); + else /* 90 or 270 */ + lv_draw_sw_rotate(img, rotation_buffer, w, h, w_stride, h_stride, rotation, cf); + + img = rotation_buffer; + lv_display_rotate_area(display, (lv_area_t *)area); + } int32_t w = lv_area_get_width(area); int32_t h = lv_area_get_height(area); uint16_t * fb = (uint16_t *)fb_background[1]; - uint16_t * img = (uint16_t *)px_map; fb = fb + area->y1 * DISPLAY_HSIZE_INPUT0; fb = fb + area->x1;