diff --git a/Kconfig b/Kconfig index 5d206a426b..f6be478bc6 100644 --- a/Kconfig +++ b/Kconfig @@ -397,14 +397,24 @@ menu "LVGL configuration" bool "Enable PXP asserts" depends on LV_USE_DRAW_PXP - config LV_USE_DRAW_G2D + config LV_USE_G2D bool "Use NXP's G2D on MPU platforms" default n + + config LV_USE_DRAW_G2D + bool "Use G2D for drawing." + depends on LV_USE_G2D + default y + + config LV_USE_ROTATE_G2D + bool "Use G2D to rotate display." + depends on LV_USE_G2D + default n config LV_G2D_HASH_TABLE_SIZE bool "Maximum number of buffers that can be stored for G2D draw unit." default 50 - depends on LV_USE_DRAW_G2D + depends on LV_USE_G2D help Includes the frame buffers and assets. @@ -415,7 +425,7 @@ menu "LVGL configuration" config LV_USE_G2D_ASSERT bool "Enable G2D asserts" - depends on LV_USE_DRAW_G2D + depends on LV_USE_G2D default n config LV_USE_DRAW_DAVE2D @@ -1890,7 +1900,7 @@ menu "LVGL configuration" config LV_WAYLAND_USE_DMABUF bool "Use DMA buffers for frame buffers" - depends on LV_USE_WAYLAND && LV_USE_DRAW_G2D + depends on LV_USE_WAYLAND && LV_USE_G2D config LV_USE_LINUX_FBDEV bool "Use Linux framebuffer device" diff --git a/lv_conf_template.h b/lv_conf_template.h index 332d18b184..9de7395bdc 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -270,14 +270,20 @@ #endif /** Use NXP's G2D on MPU platforms. */ -#define LV_USE_DRAW_G2D 0 +#define LV_USE_G2D 0 + +#if LV_USE_G2D + /** Use G2D for drawing. **/ + #define LV_USE_DRAW_G2D 1 + + /** Use G2D to rotate display. **/ + #define LV_USE_ROTATE_G2D 0 -#if LV_USE_DRAW_G2D /** Maximum number of buffers that can be stored for G2D draw unit. * Includes the frame buffers and assets. */ #define LV_G2D_HASH_TABLE_SIZE 50 - #if LV_USE_OS + #if LV_USE_DRAW_G2D && LV_USE_OS /** Use additional draw thread for G2D processing.*/ #define LV_USE_G2D_DRAW_THREAD 1 #endif diff --git a/src/draw/nxp/g2d/lv_draw_buf_g2d.c b/src/draw/nxp/g2d/lv_draw_buf_g2d.c index 8653ea5296..e729e9b08c 100644 --- a/src/draw/nxp/g2d/lv_draw_buf_g2d.c +++ b/src/draw/nxp/g2d/lv_draw_buf_g2d.c @@ -15,7 +15,8 @@ #include "lv_draw_g2d.h" -#if LV_USE_DRAW_G2D +#if LV_USE_G2D +#if LV_USE_DRAW_G2D || LV_USE_ROTATE_G2D #include "../../lv_draw_buf_private.h" #include "g2d.h" #include "lv_g2d_buf_map.h" @@ -89,4 +90,5 @@ static void _invalidate_cache(const lv_draw_buf_t * draw_buf, const lv_area_t * g2d_cache_op(buf, G2D_CACHE_FLUSH); } -#endif /*LV_USE_DRAW_G2D*/ +#endif /*LV_USE_DRAW_G2D || LV_USE_ROTATE_G2D*/ +#endif /*LV_USE_G2D*/ diff --git a/src/draw/nxp/g2d/lv_draw_g2d.c b/src/draw/nxp/g2d/lv_draw_g2d.c index 3a00e53e8b..5c44ad2279 100644 --- a/src/draw/nxp/g2d/lv_draw_g2d.c +++ b/src/draw/nxp/g2d/lv_draw_g2d.c @@ -11,10 +11,11 @@ #include "lv_draw_g2d.h" -#if LV_USE_DRAW_G2D +#if LV_USE_G2D #include "../../../misc/lv_area_private.h" #include "g2d.h" #include "lv_g2d_buf_map.h" +#include "lv_g2d_utils.h" /********************* * DEFINES @@ -57,6 +58,8 @@ static void _g2d_execute_drawing(lv_draw_task_t * t); * STATIC VARIABLES **********************/ +static int32_t is_hw_pxp = 0; + /********************** * MACROS **********************/ @@ -68,16 +71,13 @@ static void _g2d_execute_drawing(lv_draw_task_t * t); void lv_draw_g2d_init(void) { lv_draw_buf_g2d_init_handlers(); - +#if LV_USE_DRAW_G2D lv_draw_g2d_unit_t * draw_g2d_unit = lv_draw_create_unit(sizeof(lv_draw_g2d_unit_t)); draw_g2d_unit->base_unit.evaluate_cb = _g2d_evaluate; draw_g2d_unit->base_unit.dispatch_cb = _g2d_dispatch; draw_g2d_unit->base_unit.delete_cb = _g2d_delete; draw_g2d_unit->base_unit.name = "G2D"; - g2d_create_buf_map(); - if(g2d_open(&draw_g2d_unit->g2d_handle)) { - LV_LOG_ERROR("g2d_open fail.\n"); - } + #if LV_USE_G2D_DRAW_THREAD lv_draw_sw_thread_dsc_t * thread_dsc = &draw_g2d_unit->thread_dsc; thread_dsc->idx = 0; @@ -85,6 +85,12 @@ void lv_draw_g2d_init(void) lv_thread_init(&thread_dsc->thread, "g2ddraw", LV_DRAW_THREAD_PRIO, _g2d_render_thread_cb, LV_DRAW_THREAD_STACK_SIZE, thread_dsc); #endif +#endif + g2d_create_buf_map(); + void * handle; + LV_ASSERT_MSG(!g2d_open(&handle), "Cannot open G2D handle\r\n"); + g2d_query_hardware(handle, G2D_HARDWARE_PXP_V1, &is_hw_pxp); + g2d_set_handle(handle); } void lv_draw_g2d_deinit(void) @@ -95,7 +101,7 @@ void lv_draw_g2d_deinit(void) /********************** * STATIC FUNCTIONS **********************/ - +#if LV_USE_DRAW_G2D static inline bool _g2d_dest_cf_supported(lv_color_format_t cf) { bool is_cf_supported = false; @@ -105,6 +111,12 @@ static inline bool _g2d_dest_cf_supported(lv_color_format_t cf) case LV_COLOR_FORMAT_XRGB8888: is_cf_supported = true; break; + case LV_COLOR_FORMAT_RGB565: { + if(!is_hw_pxp) { + is_cf_supported = true; + } + } + break; default: break; } @@ -112,7 +124,7 @@ static inline bool _g2d_dest_cf_supported(lv_color_format_t cf) return is_cf_supported; } -static inline bool _g2d_src_cf_supported(lv_draw_unit_t * drawunit, lv_color_format_t cf) +static inline bool _g2d_src_cf_supported(lv_color_format_t cf) { bool is_cf_supported = false; @@ -122,10 +134,7 @@ static inline bool _g2d_src_cf_supported(lv_draw_unit_t * drawunit, lv_color_for is_cf_supported = true; break; case LV_COLOR_FORMAT_RGB565: { - int32_t hw_pxp = 0; - lv_draw_g2d_unit_t * u = (lv_draw_g2d_unit_t *)drawunit; - g2d_query_hardware(u->g2d_handle, G2D_HARDWARE_PXP, &hw_pxp); - if(!hw_pxp) { + if(!is_hw_pxp) { is_cf_supported = true; } } @@ -139,16 +148,13 @@ static inline bool _g2d_src_cf_supported(lv_draw_unit_t * drawunit, lv_color_for static bool _g2d_draw_img_supported(const lv_draw_image_dsc_t * draw_dsc) { - bool is_tiled = draw_dsc->tile; - /* Tiled image (repeat image) is currently not supported. */ - if(is_tiled) + bool has_recolor = (draw_dsc->recolor_opa > LV_OPA_MIN); + /* Recolor is not supported. */ + if(has_recolor) return false; - bool has_recolor = (draw_dsc->recolor_opa > LV_OPA_MIN); - bool has_rotation = (draw_dsc->rotation != 0); - - /* Recolor or rotation are not supported. */ - if(has_recolor || has_rotation) + /* G2D can only rotate at 90x angles. */ + if(draw_dsc->rotation % 900) return false; return true; @@ -184,7 +190,7 @@ static int32_t _g2d_evaluate(lv_draw_unit_t * u, lv_draw_task_t * t) case LV_DRAW_TASK_TYPE_IMAGE: { const lv_draw_image_dsc_t * draw_dsc = (lv_draw_image_dsc_t *) t->draw_dsc; - if(!_g2d_src_cf_supported(u, draw_dsc->header.cf)) + if(!_g2d_src_cf_supported(draw_dsc->header.cf)) return 0; if(!_g2d_draw_img_supported(draw_dsc)) @@ -255,10 +261,12 @@ static int32_t _g2d_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer) static int32_t _g2d_delete(lv_draw_unit_t * draw_unit) { - lv_draw_g2d_unit_t * draw_g2d_unit = (lv_draw_g2d_unit_t *) draw_unit; lv_result_t res = LV_RESULT_OK; -#if LV_USE_G2D_DRAW_THREAD +#if !LV_USE_G2D_DRAW_THREAD + LV_UNUSED(draw_unit); +#else + lv_draw_g2d_unit_t * draw_g2d_unit = (lv_draw_g2d_unit_t *) draw_unit; lv_draw_sw_thread_dsc_t * thread_dsc = &draw_g2d_unit->thread_dsc; LV_LOG_INFO("Cancel G2D draw thread."); thread_dsc->exit_status = true; @@ -268,7 +276,7 @@ static int32_t _g2d_delete(lv_draw_unit_t * draw_unit) res = lv_thread_delete(&thread_dsc->thread); #endif - g2d_close(draw_g2d_unit->g2d_handle); + g2d_close(g2d_get_handle()); return res; } @@ -333,4 +341,5 @@ static void _g2d_render_thread_cb(void * ptr) } #endif -#endif /*LV_USE_DRAW_G2D*/ +#endif /*LV_USE_DRAW_G2D || LV_USE_ROTATE_G2D*/ +#endif /*LV_USE_G2D*/ diff --git a/src/draw/nxp/g2d/lv_draw_g2d.h b/src/draw/nxp/g2d/lv_draw_g2d.h index 061aa3c316..59d9a62c51 100644 --- a/src/draw/nxp/g2d/lv_draw_g2d.h +++ b/src/draw/nxp/g2d/lv_draw_g2d.h @@ -22,7 +22,8 @@ extern "C" { #include "../../../lv_conf_internal.h" -#if LV_USE_DRAW_G2D +#if LV_USE_G2D +#if LV_USE_DRAW_G2D || LV_USE_ROTATE_G2D #include "../../sw/lv_draw_sw_private.h" /********************* @@ -40,8 +41,6 @@ typedef struct lv_draw_g2d_unit { #else lv_draw_task_t * task_act; #endif - - void * g2d_handle; } lv_draw_g2d_unit_t; /********************** @@ -62,7 +61,8 @@ void lv_draw_g2d_img(lv_draw_task_t * t); * MACROS **********************/ -#endif /*LV_USE_DRAW_G2D*/ +#endif /*LV_USE_DRAW_G2D || LV_USE_ROTATE_G2D*/ +#endif /*LV_USE_G2D*/ #ifdef __cplusplus } /*extern "C"*/ diff --git a/src/draw/nxp/g2d/lv_draw_g2d_fill.c b/src/draw/nxp/g2d/lv_draw_g2d_fill.c index 5863e4d6c6..73dda3fc68 100644 --- a/src/draw/nxp/g2d/lv_draw_g2d_fill.c +++ b/src/draw/nxp/g2d/lv_draw_g2d_fill.c @@ -15,6 +15,7 @@ #include "lv_draw_g2d.h" +#if LV_USE_G2D #if LV_USE_DRAW_G2D #include #include "g2d.h" @@ -35,14 +36,14 @@ **********************/ /* Blit simple w/ opa and alpha channel */ -static void _g2d_fill(void * g2d_handle, struct g2d_surface * dst_surf); -static void _g2d_fill_with_opa(void * g2d_handle, struct g2d_surface * dst_surf, struct g2d_surface * src_surf); +static void _g2d_fill(void * handle, struct g2d_surface * dst_surf); +static void _g2d_fill_with_opa(void * handle, struct g2d_surface * dst_surf, struct g2d_surface * src_surf); static void _g2d_set_src_surf(struct g2d_surface * src_surf, struct g2d_buf * buf, const lv_area_t * area, - lv_color_t color, lv_opa_t opa); + lv_color_t color, lv_opa_t opa, lv_color_format_t cf); static void _g2d_set_dst_surf(struct g2d_surface * dst_surf, struct g2d_buf * buf, const lv_area_t * area, - int32_t stride, lv_color_t color); + int32_t stride, lv_color_t color, lv_color_format_t cf); /********************** * STATIC VARIABLES @@ -63,7 +64,6 @@ void lv_draw_g2d_fill(lv_draw_task_t * t) if(dsc->opa <= (lv_opa_t)LV_OPA_MIN) return; - lv_draw_g2d_unit_t * u = (lv_draw_g2d_unit_t *)t->draw_unit; lv_layer_t * layer = t->target_layer; lv_draw_buf_t * draw_buf = layer->draw_buf; lv_area_t * coords = &t->area; @@ -88,19 +88,21 @@ void lv_draw_g2d_fill(lv_draw_task_t * t) bool has_opa = (dsc->opa < (lv_opa_t)LV_OPA_MAX); struct g2d_surface dst_surf; - _g2d_set_dst_surf(&dst_surf, dst_buf, &blend_area, stride, dsc->color); + _g2d_set_dst_surf(&dst_surf, dst_buf, &blend_area, stride, dsc->color, draw_buf->header.cf); + + void * handle = g2d_get_handle(); if(has_opa) { - struct g2d_buf * tmp_buf = g2d_alloc(lv_area_get_width(&blend_area) * lv_area_get_height(&blend_area) * sizeof( - lv_color32_t), 1); + struct g2d_buf * tmp_buf = g2d_alloc(lv_area_get_width(&blend_area) * lv_area_get_height( + &blend_area) * lv_color_format_get_size(draw_buf->header.cf), 1); G2D_ASSERT_MSG(tmp_buf, "Failed to alloc temporary buffer."); struct g2d_surface src_surf; - _g2d_set_src_surf(&src_surf, tmp_buf, &blend_area, dsc->color, dsc->opa); - _g2d_fill_with_opa(u->g2d_handle, &dst_surf, &src_surf); + _g2d_set_src_surf(&src_surf, tmp_buf, &blend_area, dsc->color, dsc->opa, draw_buf->header.cf); + _g2d_fill_with_opa(handle, &dst_surf, &src_surf); g2d_free(tmp_buf); } else { - _g2d_fill(u->g2d_handle, &dst_surf); + _g2d_fill(handle, &dst_surf); } } @@ -109,12 +111,12 @@ void lv_draw_g2d_fill(lv_draw_task_t * t) **********************/ static void _g2d_set_src_surf(struct g2d_surface * src_surf, struct g2d_buf * buf, const lv_area_t * area, - lv_color_t color, lv_opa_t opa) + lv_color_t color, lv_opa_t opa, lv_color_format_t cf) { int32_t width = lv_area_get_width(area); int32_t height = lv_area_get_height(area); - src_surf->format = G2D_RGBA8888; + src_surf->format = g2d_get_buf_format(cf); src_surf->left = 0; src_surf->top = 0; @@ -133,12 +135,12 @@ static void _g2d_set_src_surf(struct g2d_surface * src_surf, struct g2d_buf * bu } static void _g2d_set_dst_surf(struct g2d_surface * dst_surf, struct g2d_buf * buf, const lv_area_t * area, - int32_t stride, lv_color_t color) + int32_t stride, lv_color_t color, lv_color_format_t cf) { int32_t width = lv_area_get_width(area); int32_t height = lv_area_get_height(area); - dst_surf->format = G2D_RGBA8888; + dst_surf->format = g2d_get_buf_format(cf); dst_surf->left = area->x1; dst_surf->top = area->y1; @@ -156,23 +158,24 @@ static void _g2d_set_dst_surf(struct g2d_surface * dst_surf, struct g2d_buf * bu dst_surf->blendfunc = G2D_ONE_MINUS_SRC_ALPHA | G2D_PRE_MULTIPLIED_ALPHA; } -static void _g2d_fill_with_opa(void * g2d_handle, struct g2d_surface * dst_surf, struct g2d_surface * src_surf) +static void _g2d_fill_with_opa(void * handle, struct g2d_surface * dst_surf, struct g2d_surface * src_surf) { - g2d_clear(g2d_handle, src_surf); + g2d_clear(handle, src_surf); - g2d_enable(g2d_handle, G2D_BLEND); - g2d_enable(g2d_handle, G2D_GLOBAL_ALPHA); - g2d_blit(g2d_handle, src_surf, dst_surf); - g2d_finish(g2d_handle); - g2d_disable(g2d_handle, G2D_GLOBAL_ALPHA); - g2d_disable(g2d_handle, G2D_BLEND); + g2d_enable(handle, G2D_BLEND); + g2d_enable(handle, G2D_GLOBAL_ALPHA); + g2d_blit(handle, src_surf, dst_surf); + g2d_finish(handle); + g2d_disable(handle, G2D_GLOBAL_ALPHA); + g2d_disable(handle, G2D_BLEND); } -static void _g2d_fill(void * g2d_handle, struct g2d_surface * dst_surf) +static void _g2d_fill(void * handle, struct g2d_surface * dst_surf) { - g2d_clear(g2d_handle, dst_surf); + g2d_clear(handle, dst_surf); - g2d_finish(g2d_handle); + g2d_finish(handle); } -#endif /*LV_USE_DRAW_G2D*/ \ No newline at end of file +#endif /*LV_USE_DRAW_G2D*/ +#endif /*LV_USE_G2D*/ diff --git a/src/draw/nxp/g2d/lv_draw_g2d_img.c b/src/draw/nxp/g2d/lv_draw_g2d_img.c index c24f2324e3..2e7d6bea49 100644 --- a/src/draw/nxp/g2d/lv_draw_g2d_img.c +++ b/src/draw/nxp/g2d/lv_draw_g2d_img.c @@ -15,10 +15,13 @@ #include "lv_draw_g2d.h" +#if LV_USE_G2D #if LV_USE_DRAW_G2D #include #include "g2d.h" #include "../../../misc/lv_area_private.h" +#include "../../lv_draw_image_private.h" +#include "../../lv_image_decoder_private.h" #include "lv_g2d_utils.h" #include "lv_g2d_buf_map.h" @@ -34,16 +37,26 @@ * STATIC PROTOTYPES **********************/ -static struct g2d_buf * _g2d_handle_src_buf(const lv_image_dsc_t * data); +static void _g2d_draw_core_cb(lv_draw_task_t * t, const lv_draw_image_dsc_t * draw_dsc, + const lv_image_decoder_dsc_t * decoder_dsc, lv_draw_image_sup_t * sup, const lv_area_t * img_coords, + const lv_area_t * clipped_img_area); + +static struct g2d_buf * _g2d_handle_src_buf(const lv_draw_buf_t * data); static void _g2d_set_src_surf(struct g2d_surface * src_surf, struct g2d_buf * buf, const lv_area_t * area, - int32_t stride, lv_color_format_t cf, lv_opa_t opa); - -static void _g2d_set_dst_surf(struct g2d_surface * dst_surf, struct g2d_buf * buf, const lv_area_t * area, int32_t stride, lv_color_format_t cf, const lv_draw_image_dsc_t * dsc); +static void _g2d_set_tmp_surf(struct g2d_surface * tmp_surf, struct g2d_buf * buf, const lv_area_t * area, + lv_color_format_t cf); + +static void _g2d_set_dst_surf(struct g2d_surface * dst_surf, struct g2d_buf * buf, const lv_area_t * area, + lv_draw_buf_t * draw_buf); + /* Blit simple w/ opa and alpha channel */ -static void _g2d_blit(void * g2d_handle, struct g2d_surface * dst_surf, struct g2d_surface * src_surf); +static void _g2d_blit(void * handle, struct g2d_surface * dst_surf, struct g2d_surface * src_surf); + +static void _g2d_blit_two_steps(void * handle, struct g2d_surface * dst_surf, struct g2d_surface * src_surf, + struct g2d_surface * tmp_surf); /********************** * STATIC VARIABLES @@ -64,68 +77,89 @@ void lv_draw_g2d_img(lv_draw_task_t * t) if(dsc->opa <= (lv_opa_t)LV_OPA_MIN) return; - lv_draw_g2d_unit_t * u = (lv_draw_g2d_unit_t *)t->draw_unit; - lv_layer_t * layer = t->target_layer; - lv_draw_buf_t * draw_buf = layer->draw_buf; - const lv_image_dsc_t * img_dsc = dsc->src; lv_area_t * coords = &t->area; - lv_area_t rel_coords; - lv_area_copy(&rel_coords, coords); - lv_area_move(&rel_coords, -layer->buf_area.x1, -layer->buf_area.y1); + bool is_tiled = (dsc->tile != 0); - lv_area_t clip_area; - lv_area_copy(&clip_area, &t->clip_area); - lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1); - - lv_area_t blend_area; - bool has_transform = (dsc->rotation != 0 || dsc->scale_x != LV_SCALE_NONE || dsc->scale_y != LV_SCALE_NONE); - if(has_transform) - lv_area_copy(&blend_area, &rel_coords); - else if(!lv_area_intersect(&blend_area, &rel_coords, &clip_area)) - return; /*Fully clipped, nothing to do*/ - - lv_area_t src_area; - src_area.x1 = blend_area.x1 - (coords->x1 - layer->buf_area.x1); - src_area.y1 = blend_area.y1 - (coords->y1 - layer->buf_area.y1); - src_area.x2 = src_area.x1 + lv_area_get_width(&blend_area); - src_area.y2 = src_area.y1 + lv_area_get_height(&blend_area); - lv_color_format_t src_cf = img_dsc->header.cf; - - /* G2D takes stride in pixels. */ - const uint8_t pixel_size = lv_color_format_get_size(src_cf); - - uint32_t src_stride = img_dsc->header.stride == 0 ? - lv_color_format_get_size(img_dsc->header.cf) * img_dsc->header.w : - img_dsc->header.stride; - LV_ASSERT(pixel_size != 0); - src_stride /= pixel_size; - - - /* Source image */ - struct g2d_buf * src_buf = _g2d_handle_src_buf(img_dsc); - - /* Destination buffer */ - struct g2d_buf * dst_buf = g2d_search_buf_map(draw_buf->data); - - /* G2D takes stride in pixels. */ - int32_t dest_stride = draw_buf->header.stride / (lv_color_format_get_bpp(draw_buf->header.cf) / 8); - lv_color_format_t dest_cf = draw_buf->header.cf; - - struct g2d_surface src_surf; - struct g2d_surface dst_surf; - - _g2d_set_src_surf(&src_surf, src_buf, &src_area, src_stride, src_cf, dsc->opa); - _g2d_set_dst_surf(&dst_surf, dst_buf, &blend_area, dest_stride, dest_cf, dsc); - - _g2d_blit(u->g2d_handle, &dst_surf, &src_surf); + if(is_tiled) + lv_draw_image_tiled_helper(t, dsc, coords, _g2d_draw_core_cb); + else + lv_draw_image_normal_helper(t, dsc, coords, _g2d_draw_core_cb); } /********************** * STATIC FUNCTIONS **********************/ -static struct g2d_buf * _g2d_handle_src_buf(const lv_image_dsc_t * img_dsc) +static void _g2d_draw_core_cb(lv_draw_task_t * t, const lv_draw_image_dsc_t * draw_dsc, + const lv_image_decoder_dsc_t * decoder_dsc, lv_draw_image_sup_t * sup, const lv_area_t * img_coords, + const lv_area_t * clipped_img_area) +{ + LV_UNUSED(sup); + lv_draw_buf_t * draw_buf = t->target_layer->draw_buf; + + const lv_draw_buf_t * decoded = decoder_dsc->decoded; + + lv_area_t rel_clip_area; + lv_area_copy(&rel_clip_area, clipped_img_area); + lv_area_move(&rel_clip_area, -img_coords->x1, -img_coords->y1); + + lv_area_t rel_img_coords; + lv_area_copy(&rel_img_coords, img_coords); + lv_area_move(&rel_img_coords, -img_coords->x1, -img_coords->y1); + + lv_area_t src_area; + if(!lv_area_intersect(&src_area, &rel_clip_area, &rel_img_coords)) + return; + + lv_color_format_t src_cf = draw_dsc->header.cf; + + /* G2D takes stride in pixels. */ + const uint8_t pixel_size = lv_color_format_get_size(src_cf); + + uint32_t src_stride = draw_dsc->header.stride == 0 ? + lv_color_format_get_size(draw_dsc->header.cf) * draw_dsc->header.w : + draw_dsc->header.stride; + LV_ASSERT(pixel_size != 0); + src_stride /= pixel_size; + + /* Source image */ + struct g2d_buf * src_buf = _g2d_handle_src_buf(decoded); + + /* Destination buffer */ + struct g2d_buf * dst_buf = g2d_search_buf_map(draw_buf->data); + + + void * handle = g2d_get_handle(); + + struct g2d_surface src_surf; + struct g2d_surface dst_surf; + + _g2d_set_src_surf(&src_surf, src_buf, &src_area, src_stride, src_cf, draw_dsc); + _g2d_set_dst_surf(&dst_surf, dst_buf, clipped_img_area, draw_buf); + + bool has_rotation = (draw_dsc->rotation != 0); + + if(has_rotation) { + /** If the image has rotation, then blit in two steps: + * 1. Source with rotation to temporary surface. + * 2. Temporary with other transformations (if any) to destination (frame buffer). + */ + struct g2d_buf * tmp_buf = g2d_alloc(lv_area_get_width(&src_area) * lv_area_get_height( + &src_area) * lv_color_format_get_size(src_cf), 1); + G2D_ASSERT_MSG(tmp_buf, "Failed to alloc temporary buffer."); + struct g2d_surface tmp_surf; + _g2d_set_tmp_surf(&tmp_surf, tmp_buf, &src_area, src_cf); + _g2d_blit_two_steps(handle, &dst_surf, &src_surf, &tmp_surf); + g2d_free(tmp_buf); + } + else { + // If rotation is not involved, blit in one step. + _g2d_blit(handle, &dst_surf, &src_surf); + } +} + +static struct g2d_buf * _g2d_handle_src_buf(const lv_draw_buf_t * img_dsc) { struct g2d_buf * src_buf = g2d_search_buf_map((void *)img_dsc->data); @@ -141,66 +175,95 @@ static struct g2d_buf * _g2d_handle_src_buf(const lv_image_dsc_t * img_dsc) } static void _g2d_set_src_surf(struct g2d_surface * src_surf, struct g2d_buf * buf, const lv_area_t * area, - int32_t stride, lv_color_format_t cf, lv_opa_t opa) + int32_t stride, lv_color_format_t cf, const lv_draw_image_dsc_t * dsc) { src_surf->format = g2d_get_buf_format(cf); + int32_t src_w = lv_area_get_width(area); + int32_t src_h = lv_area_get_height(area); + + bool has_rotation = (dsc->rotation != 0); + enum g2d_rotation g2d_angle = G2D_ROTATION_0; + + if(has_rotation) { + switch(dsc->rotation) { + case 0: + g2d_angle = G2D_ROTATION_0; + break; + case 900: + g2d_angle = G2D_ROTATION_270; + break; + case 1800: + g2d_angle = G2D_ROTATION_180; + break; + case 2700: + g2d_angle = G2D_ROTATION_90; + break; + default: + g2d_angle = G2D_ROTATION_0; + } + } + src_surf->left = area->x1; src_surf->top = area->y1; - src_surf->right = area->x2; - src_surf->bottom = area->y2; + src_surf->right = area->x1 + src_w; + src_surf->bottom = area->y1 + src_h; src_surf->stride = stride; - src_surf->width = area->x2 - area->x1; - src_surf->height = area->y2 - area->y1; + src_surf->width = src_w; + src_surf->height = src_h; src_surf->planes[0] = buf->buf_paddr; - src_surf->rot = G2D_ROTATION_0; + src_surf->rot = g2d_angle; src_surf->clrcolor = g2d_rgba_to_u32(lv_color_black()); - src_surf->global_alpha = opa; + src_surf->global_alpha = dsc->opa; src_surf->blendfunc = G2D_ONE | G2D_PRE_MULTIPLIED_ALPHA; } -static void _g2d_set_dst_surf(struct g2d_surface * dst_surf, struct g2d_buf * buf, const lv_area_t * area, - int32_t stride, lv_color_format_t cf, const lv_draw_image_dsc_t * dsc) +static void _g2d_set_tmp_surf(struct g2d_surface * tmp_surf, struct g2d_buf * buf, const lv_area_t * area, + lv_color_format_t cf) { - int32_t width = lv_area_get_width(area); - int32_t height = lv_area_get_height(area); + tmp_surf->format = g2d_get_buf_format(cf); - lv_point_t pivot = dsc->pivot; - /*The offsets are now relative to the transformation result with pivot ULC*/ - int32_t piv_offset_x = 0; - int32_t piv_offset_y = 0; - int32_t trim_x = 0; - int32_t trim_y = 0; - int32_t dest_w; - int32_t dest_h; + int32_t dest_w = lv_area_get_width(area); + int32_t dest_h = lv_area_get_height(area); - float fp_scale_x = (float)dsc->scale_x / LV_SCALE_NONE; - float fp_scale_y = (float)dsc->scale_y / LV_SCALE_NONE; - int32_t int_scale_x = (int32_t)fp_scale_x; - int32_t int_scale_y = (int32_t)fp_scale_y; + tmp_surf->left = area->x1; + tmp_surf->top = area->y1; + tmp_surf->right = area->x1 + dest_w; + tmp_surf->bottom = area->y1 + dest_h; + tmp_surf->stride = dest_w; + tmp_surf->width = dest_w; + tmp_surf->height = dest_h; - /*Any scale_factor in (k, k + 1] will result in a trim equal to k*/ - trim_x = (fp_scale_x == int_scale_x) ? int_scale_x - 1 : int_scale_x; - trim_y = (fp_scale_y == int_scale_y) ? int_scale_y - 1 : int_scale_y; + tmp_surf->planes[0] = buf->buf_paddr; + tmp_surf->rot = G2D_ROTATION_0; - dest_w = width * fp_scale_x + trim_x; - dest_h = height * fp_scale_y + trim_y; + tmp_surf->clrcolor = g2d_rgba_to_u32(lv_color_black()); + tmp_surf->global_alpha = 0x00; + tmp_surf->blendfunc = G2D_ONE_MINUS_SRC_ALPHA | G2D_PRE_MULTIPLIED_ALPHA; +} - /*Final pivot offset = scale_factor * rotation_pivot_offset + scaling_pivot_offset*/ - piv_offset_x = floor(fp_scale_x * piv_offset_x) - floor((fp_scale_x - 1) * pivot.x); - piv_offset_y = floor(fp_scale_y * piv_offset_y) - floor((fp_scale_y - 1) * pivot.y); +static void _g2d_set_dst_surf(struct g2d_surface * dst_surf, struct g2d_buf * buf, const lv_area_t * area, + lv_draw_buf_t * draw_buf) +{ + int32_t stride = draw_buf->header.stride / (lv_color_format_get_bpp(draw_buf->header.cf) / 8); + lv_color_format_t cf = draw_buf->header.cf; + uint32_t width = draw_buf->header.w; + uint32_t height = draw_buf->header.h; + + int32_t blend_w = lv_area_get_width(area); + int32_t blend_h = lv_area_get_height(area); dst_surf->format = g2d_get_buf_format(cf); - dst_surf->left = area->x1 + piv_offset_x; - dst_surf->top = area->y1 + piv_offset_y; - dst_surf->right = area->x1 + piv_offset_x + dest_w - trim_x; - dst_surf->bottom = area->y1 + piv_offset_y + dest_h - trim_y; + dst_surf->left = area->x1; + dst_surf->top = area->y1; + dst_surf->right = area->x1 + blend_w; + dst_surf->bottom = area->y1 + blend_h; dst_surf->stride = stride; - dst_surf->width = dest_w - trim_x; - dst_surf->height = dest_h - trim_y; + dst_surf->width = width; + dst_surf->height = height; dst_surf->planes[0] = buf->buf_paddr; dst_surf->rot = G2D_ROTATION_0; @@ -210,13 +273,40 @@ static void _g2d_set_dst_surf(struct g2d_surface * dst_surf, struct g2d_buf * bu dst_surf->blendfunc = G2D_ONE_MINUS_SRC_ALPHA | G2D_PRE_MULTIPLIED_ALPHA; } -static void _g2d_blit(void * g2d_handle, struct g2d_surface * dst_surf, struct g2d_surface * src_surf) +static void _g2d_blit(void * handle, struct g2d_surface * dst_surf, struct g2d_surface * src_surf) { - g2d_enable(g2d_handle, G2D_BLEND); - g2d_enable(g2d_handle, G2D_GLOBAL_ALPHA); - g2d_blit(g2d_handle, src_surf, dst_surf); - g2d_finish(g2d_handle); - g2d_disable(g2d_handle, G2D_GLOBAL_ALPHA); - g2d_disable(g2d_handle, G2D_BLEND); + g2d_enable(handle, G2D_BLEND); + g2d_enable(handle, G2D_GLOBAL_ALPHA); + g2d_blit(handle, src_surf, dst_surf); + g2d_finish(handle); + g2d_disable(handle, G2D_GLOBAL_ALPHA); + g2d_disable(handle, G2D_BLEND); +} + +static void _g2d_blit_two_steps(void * handle, struct g2d_surface * dst_surf, struct g2d_surface * src_surf, + struct g2d_surface * tmp_surf) +{ + g2d_clear(handle, tmp_surf); + + g2d_enable(handle, G2D_BLEND); + g2d_enable(handle, G2D_GLOBAL_ALPHA); + g2d_blit(handle, src_surf, tmp_surf); + g2d_finish(handle); + g2d_disable(handle, G2D_GLOBAL_ALPHA); + g2d_disable(handle, G2D_BLEND); + + /**After first blit, change blending and global alpha for temporary surface + * since the surface now acts as source. + */ + tmp_surf->blendfunc = G2D_ONE | G2D_PRE_MULTIPLIED_ALPHA; + tmp_surf->global_alpha = 0xFF; + + g2d_enable(handle, G2D_BLEND); + g2d_enable(handle, G2D_GLOBAL_ALPHA); + g2d_blit(handle, tmp_surf, dst_surf); + g2d_finish(handle); + g2d_disable(handle, G2D_GLOBAL_ALPHA); + g2d_disable(handle, G2D_BLEND); } #endif /*LV_USE_DRAW_G2D*/ +#endif /*LV_USE_G2D*/ diff --git a/src/draw/nxp/g2d/lv_g2d_buf_map.c b/src/draw/nxp/g2d/lv_g2d_buf_map.c index 9f851ac155..dcea161026 100644 --- a/src/draw/nxp/g2d/lv_g2d_buf_map.c +++ b/src/draw/nxp/g2d/lv_g2d_buf_map.c @@ -11,7 +11,8 @@ #include "lv_g2d_buf_map.h" -#if LV_USE_DRAW_G2D +#if LV_USE_G2D +#if LV_USE_DRAW_G2D || LV_USE_ROTATE_G2D #include #include "lv_g2d_utils.h" #include "g2d.h" @@ -155,6 +156,7 @@ void g2d_free_item(void * key) for(uint32_t i = 0; i < lv_array_size(list); i++) { item = (lv_map_item_t *)lv_array_at(list, i); if(item->key == key) { + g2d_free(item->value); lv_array_remove(list, i); return; } @@ -244,4 +246,5 @@ static void _map_free_item(lv_map_item_t * item) item = NULL; } -#endif /*LV_USE_DRAW_G2D*/ +#endif /*LV_USE_DRAW_G2D || LV_USE_ROTATE_G2D*/ +#endif /*LV_USE_G2D*/ diff --git a/src/draw/nxp/g2d/lv_g2d_buf_map.h b/src/draw/nxp/g2d/lv_g2d_buf_map.h index 6e2196d30d..c1d1f86343 100644 --- a/src/draw/nxp/g2d/lv_g2d_buf_map.h +++ b/src/draw/nxp/g2d/lv_g2d_buf_map.h @@ -23,7 +23,8 @@ extern "C" { #include "../../../lv_conf_internal.h" -#if LV_USE_DRAW_G2D +#if LV_USE_G2D +#if LV_USE_DRAW_G2D || LV_USE_ROTATE_G2D #include "../../../misc/lv_array.h" #include @@ -72,7 +73,8 @@ void g2d_print_table(void); * MACROS **********************/ -#endif /*LV_USE_DRAW_G2D*/ +#endif /*LV_USE_DRAW_G2D || LV_USE_ROTATE_G2D*/ +#endif /*LV_USE_G2D*/ #ifdef __cplusplus } /*extern "C"*/ diff --git a/src/draw/nxp/g2d/lv_g2d_utils.c b/src/draw/nxp/g2d/lv_g2d_utils.c index c353040d23..81ef9a5449 100644 --- a/src/draw/nxp/g2d/lv_g2d_utils.c +++ b/src/draw/nxp/g2d/lv_g2d_utils.c @@ -15,7 +15,8 @@ #include "lv_g2d_utils.h" -#if LV_USE_DRAW_G2D +#if LV_USE_G2D +#if LV_USE_DRAW_G2D || LV_USE_ROTATE_G2D #include "lv_g2d_buf_map.h" #include "lv_draw_g2d.h" @@ -30,7 +31,7 @@ /********************** * STATIC PROTOTYPES **********************/ - +static void * g2d_handle; /********************** * MACROS **********************/ @@ -90,8 +91,88 @@ int32_t g2d_get_buf_fd(const lv_draw_buf_t * draw_buf) return g2d_buf_export_fd(buf); } +void g2d_set_handle(void * handle) +{ + g2d_handle = handle; +} +void * g2d_get_handle(void) +{ + return g2d_handle; +} + +#if LV_USE_ROTATE_G2D +void g2d_rotate(lv_draw_buf_t * buf1, lv_draw_buf_t * buf2, int32_t width, int32_t height, uint32_t rotation, + lv_color_format_t cf) +{ + struct g2d_surface src_surf, dst_surf; + struct g2d_buf * src_buf = g2d_search_buf_map(buf1->data); + struct g2d_buf * dst_buf = g2d_search_buf_map(buf2->data); + bool has_rotation = (rotation != 0); + + int32_t src_width = width; + int32_t src_height = height; + if(has_rotation) { + if(rotation == LV_DISPLAY_ROTATION_90 || rotation == LV_DISPLAY_ROTATION_270) { + src_width = height; + src_height = width; + } + } + + src_surf.format = g2d_get_buf_format(cf); + + src_surf.left = 0; + src_surf.top = 0; + src_surf.right = src_width; + src_surf.bottom = src_height; + src_surf.stride = src_width; + src_surf.width = src_width; + src_surf.height = src_height; + + src_surf.planes[0] = src_buf->buf_paddr; + src_surf.rot = G2D_ROTATION_0; + + enum g2d_rotation g2d_angle = G2D_ROTATION_0; + if(has_rotation) { + switch(rotation) { + case LV_DISPLAY_ROTATION_0: + g2d_angle = G2D_ROTATION_0; + break; + case LV_DISPLAY_ROTATION_90: + g2d_angle = G2D_ROTATION_90; + break; + case LV_DISPLAY_ROTATION_180: + g2d_angle = G2D_ROTATION_180; + break; + case LV_DISPLAY_ROTATION_270: + g2d_angle = G2D_ROTATION_270; + break; + default: + g2d_angle = G2D_ROTATION_0; + } + } + + dst_surf.format = g2d_get_buf_format(cf); + + dst_surf.left = 0; + dst_surf.top = 0; + dst_surf.right = width; + dst_surf.bottom = height; + dst_surf.stride = width; + dst_surf.width = width; + dst_surf.height = height; + + dst_surf.planes[0] = dst_buf->buf_paddr; + dst_surf.rot = g2d_angle; + + void * handle = g2d_get_handle(); + g2d_blit(handle, &src_surf, &dst_surf); + g2d_finish(handle); +} +#endif + /********************** * STATIC FUNCTIONS **********************/ -#endif /*LV_USE_DRAW_G2D*/ \ No newline at end of file +#endif /*LV_USE_DRAW_G2D || LV_USE_ROTATE_G2D*/ +#endif /*LV_USE_G2D*/ diff --git a/src/draw/nxp/g2d/lv_g2d_utils.h b/src/draw/nxp/g2d/lv_g2d_utils.h index f3923e1503..af23b27dfd 100644 --- a/src/draw/nxp/g2d/lv_g2d_utils.h +++ b/src/draw/nxp/g2d/lv_g2d_utils.h @@ -21,7 +21,8 @@ extern "C" { *********************/ #include "../../../lv_conf_internal.h" -#if LV_USE_DRAW_G2D +#if LV_USE_G2D +#if LV_USE_DRAW_G2D || LV_USE_ROTATE_G2D #include "../../sw/lv_draw_sw_private.h" #include "g2d.h" #include "g2dExt.h" @@ -59,11 +60,21 @@ g2d_format_t g2d_get_buf_format(lv_color_format_t cf); uint32_t g2d_rgba_to_u32(lv_color_t color); int32_t g2d_get_buf_fd(const lv_draw_buf_t * draw_buf); + +void g2d_set_handle(void * handle); + +void * g2d_get_handle(void); + +#if LV_USE_ROTATE_G2D +void g2d_rotate(lv_draw_buf_t * buf1, lv_draw_buf_t * buf2, int32_t width, int32_t height, uint32_t rotation, + lv_color_format_t cf); +#endif /********************** * MACROS **********************/ -#endif /*LV_USE_DRAW_G2D*/ +#endif /*LV_USE_DRAW_G2D || LV_USE_ROTATE_G2D*/ +#endif /*LV_USE_G2D*/ #ifdef __cplusplus } /*extern "C"*/ diff --git a/src/drivers/wayland/lv_wayland.c b/src/drivers/wayland/lv_wayland.c index 65475d70b2..10cee82b9b 100644 --- a/src/drivers/wayland/lv_wayland.c +++ b/src/drivers/wayland/lv_wayland.c @@ -10,20 +10,34 @@ #if LV_USE_WAYLAND -#if LV_WAYLAND_BUF_COUNT < 1 || LV_WAYLAND_BUF_COUNT > 2 - #error "Invalid LV_WAYLAND_BUF_COUNT. Expected either 1 or 2" +#if LV_USE_G2D + #if LV_USE_ROTATE_G2D + #if !LV_WAYLAND_USE_DMABUF + #error "LV_USE_ROTATE_G2D is supported only with DMABUF" + #endif + #if LV_WAYLAND_BUF_COUNT != 3 + #error "LV_WAYLAND_BUF_COUNT must be 3 when LV_USE_ROTATE_G2D is enabled" + #endif + #define LV_WAYLAND_CHECK_BUF_COUNT 0 + #endif #endif -#if !LV_WAYLAND_USE_DMABUF && LV_WAYLAND_BUF_COUNT != 1 - #error "Wayland doesn't support more than 1 LV_WAYLAND_BUF_COUNT without DMABUF" +#ifndef LV_WAYLAND_CHECK_BUF_COUNT + #if LV_WAYLAND_BUF_COUNT < 1 || LV_WAYLAND_BUF_COUNT > 2 + #error "Invalid LV_WAYLAND_BUF_COUNT. Expected either 1 or 2" + #endif + + #if !LV_WAYLAND_USE_DMABUF && LV_WAYLAND_BUF_COUNT != 1 + #error "Wayland doesn't support more than 1 LV_WAYLAND_BUF_COUNT without DMABUF" + #endif + + #if LV_WAYLAND_USE_DMABUF && LV_WAYLAND_BUF_COUNT != 2 + #error "Wayland with DMABUF only supports 2 LV_WAYLAND_BUF_COUNT" + #endif #endif -#if LV_WAYLAND_USE_DMABUF && LV_WAYLAND_BUF_COUNT != 2 - #error "Wayland with DMABUF only supports 2 LV_WAYLAND_BUF_COUNT" -#endif - -#if LV_WAYLAND_USE_DMABUF && !LV_USE_DRAW_G2D - #error "LV_WAYLAND_USE_DMABUF requires LV_USE_DRAW_G2D" +#if LV_WAYLAND_USE_DMABUF && !LV_USE_G2D + #error "LV_WAYLAND_USE_DMABUF requires LV_USE_G2D" #endif #ifndef LV_DISPLAY_RENDER_MODE_PARTIAL @@ -333,6 +347,37 @@ void lv_wayland_wait_flush_cb(lv_display_t * disp) } } +void lv_wayland_event_cb(lv_event_t * e) +{ + lv_event_code_t code = lv_event_get_code(e); + struct window * window = lv_event_get_user_data(e); + lv_display_t * display = (lv_display_t *) lv_event_get_target(e); + + switch(code) { + case LV_EVENT_RESOLUTION_CHANGED: { + uint32_t rotation = lv_display_get_rotation(window->lv_disp); + int width, height; + if(rotation == LV_DISPLAY_ROTATION_90 || rotation == LV_DISPLAY_ROTATION_270) { + width = lv_display_get_vertical_resolution(display); + height = lv_display_get_horizontal_resolution(display); + } + else { + width = lv_display_get_horizontal_resolution(display); + height = lv_display_get_vertical_resolution(display); + } +#if LV_WAYLAND_USE_DMABUF + dmabuf_ctx_t * context = &window->wl_ctx->dmabuf_ctx; + lv_wayland_dmabuf_resize_window(context, window, width, height); +#else + lv_wayland_shm_resize_window(&window->wl_ctx->shm_ctx, window, width, height); +#endif + break; + } + default: + return; + } +} + /********************** * STATIC FUNCTIONS **********************/ diff --git a/src/drivers/wayland/lv_wayland_private.h b/src/drivers/wayland/lv_wayland_private.h index ce98169456..92b3a08706 100644 --- a/src/drivers/wayland/lv_wayland_private.h +++ b/src/drivers/wayland/lv_wayland_private.h @@ -280,6 +280,7 @@ extern struct lv_wayland_context lv_wl_ctx; void lv_wayland_init(void); void lv_wayland_deinit(void); void lv_wayland_wait_flush_cb(lv_display_t * disp); +void lv_wayland_event_cb(lv_event_t * e); /********************** * Window diff --git a/src/drivers/wayland/lv_wl_dmabuf.c b/src/drivers/wayland/lv_wl_dmabuf.c index 78215c8899..0d8ff0b44a 100644 --- a/src/drivers/wayland/lv_wl_dmabuf.c +++ b/src/drivers/wayland/lv_wl_dmabuf.c @@ -51,11 +51,15 @@ static void dmabuf_tranche_flags(void * data, struct zwp_linux_dmabuf_feedback_v static void dmabuf_modifiers(void * data, struct zwp_linux_dmabuf_v1 * zwp_linux_dmabuf, uint32_t format, uint32_t modifier_hi, uint32_t modifier_lo); static void dmabuf_format(void * data, struct zwp_linux_dmabuf_v1 * zwp_linux_dmabuf, uint32_t format); -static struct buffer * dmabuf_acquire_buffer(dmabuf_ctx_t * context, unsigned char * color_p); static struct buffer * lv_wayland_dmabuf_create_draw_buffers_internal(struct window * window, int width, int height); static void buffer_free(struct buffer * buf); static void dmabuf_wait_swap_buf(lv_display_t * disp); +#if !LV_USE_ROTATE_G2D + static struct buffer * dmabuf_acquire_buffer(dmabuf_ctx_t * context, unsigned char * color_p); +#else + static struct buffer * get_next_buffer(dmabuf_ctx_t * context); +#endif /********************** * STATIC VARIABLES **********************/ @@ -91,9 +95,14 @@ void lv_wayland_dmabuf_initalize_context(dmabuf_ctx_t * context) { memset(context, 0, sizeof(*context)); context->format = DRM_FORMAT_INVALID; + context->last_used = 0; } lv_result_t lv_wayland_dmabuf_set_draw_buffers(dmabuf_ctx_t * context, lv_display_t * display) { + if(LV_USE_ROTATE_G2D == 1) { + lv_display_set_draw_buffers(display, context->buffers[2].lv_draw_buf, NULL); + return LV_RESULT_OK; + } if(LV_WAYLAND_BUF_COUNT == 2) { lv_display_set_draw_buffers(display, context->buffers[0].lv_draw_buf, context->buffers[1].lv_draw_buf); return LV_RESULT_OK; @@ -162,7 +171,11 @@ static void dmabuf_wait_swap_buf(lv_display_t * disp) return; } +#if LV_USE_ROTATE_G2D + int buf_nr = (window->wl_ctx->dmabuf_ctx.last_used + 1) % (LV_WAYLAND_BUF_COUNT - 1); +#else int buf_nr = (window->wl_ctx->dmabuf_ctx.last_used + 1) % LV_WAYLAND_BUF_COUNT; +#endif while(window->wl_ctx->dmabuf_ctx.buffers[buf_nr].busy) { wl_display_roundtrip(lv_wl_ctx.display); @@ -173,21 +186,46 @@ static void dmabuf_wait_swap_buf(lv_display_t * disp) void lv_wayland_dmabuf_flush_full_mode(lv_display_t * disp, const lv_area_t * area, unsigned char * color_p) { struct window * window = lv_display_get_driver_data(disp); - struct buffer * buf = dmabuf_acquire_buffer(&window->wl_ctx->dmabuf_ctx, color_p); + struct buffer * buf; + int32_t src_width = lv_area_get_width(area); + int32_t src_height = lv_area_get_height(area); + uint32_t rotation = lv_display_get_rotation(window->lv_disp); +#if LV_USE_ROTATE_G2D + LV_UNUSED(color_p); + buf = get_next_buffer(&window->wl_ctx->dmabuf_ctx); + if(rotation == LV_DISPLAY_ROTATION_90 || rotation == LV_DISPLAY_ROTATION_270) { + src_width = lv_area_get_height(area); + src_height = lv_area_get_width(area); + } +#else + buf = dmabuf_acquire_buffer(&window->wl_ctx->dmabuf_ctx, color_p); +#endif if(!buf) { LV_LOG_ERROR("Failed to acquire a wayland window body buffer"); return; } - int32_t src_width = lv_area_get_width(area); - int32_t src_height = lv_area_get_height(area); - lv_draw_buf_invalidate_cache(buf->lv_draw_buf, NULL); +#if LV_USE_ROTATE_G2D + lv_draw_buf_invalidate_cache(window->wl_ctx->dmabuf_ctx.buffers[2].lv_draw_buf, NULL); +#endif + const bool force_full_flush = LV_WAYLAND_RENDER_MODE == LV_DISPLAY_RENDER_MODE_DIRECT && + rotation != LV_DISPLAY_ROTATION_0; /* Mark surface damage */ - wl_surface_damage(window->body->surface, area->x1, area->y1, src_width, src_height); + if(!force_full_flush) { + wl_surface_damage(window->body->surface, area->x1, area->y1, src_width, src_height); + } if(lv_display_flush_is_last(disp)) { + if(force_full_flush) { + wl_surface_damage(window->body->surface, 0, 0, lv_display_get_original_horizontal_resolution(disp), + lv_display_get_original_vertical_resolution(disp)); + } +#if LV_USE_ROTATE_G2D + g2d_rotate(window->wl_ctx->dmabuf_ctx.buffers[2].lv_draw_buf, buf->lv_draw_buf, window->width, window->height, + lv_display_get_rotation(window->lv_disp), lv_display_get_color_format(window->lv_disp)); +#endif /* Finally, attach buffer and commit to surface */ wl_surface_attach(window->body->surface, buf->buffer, 0, 0); wl_surface_commit(window->body->surface); @@ -335,14 +373,25 @@ static struct buffer * lv_wayland_dmabuf_create_draw_buffers_internal(struct win const uint32_t flags = 0; struct zwp_linux_buffer_params_v1 * params; uint32_t drmcf = lv_wayland_dmabuf_get_format(window); - const int stride = lv_draw_buf_width_to_stride(width, lv_display_get_color_format(window->lv_disp)); + int stride = lv_draw_buf_width_to_stride(window->width, lv_display_get_color_format(window->lv_disp)); struct buffer * buffers = (struct buffer *)calloc(LV_WAYLAND_BUF_COUNT, sizeof(struct buffer)); LV_ASSERT_MALLOC(buffers); for(int i = 0; i < LV_WAYLAND_BUF_COUNT; i++) { + uint32_t w = width; + uint32_t h = height; +#if LV_USE_ROTATE_G2D + uint32_t rotation = lv_display_get_rotation(window->lv_disp); + if(i == 2 && (rotation == LV_DISPLAY_ROTATION_90 || rotation == LV_DISPLAY_ROTATION_270)) { + w = height; + h = width; + } +#endif + stride = lv_draw_buf_width_to_stride(w, lv_display_get_color_format(window->lv_disp)); + buffers[i].window = window; buffers[i].lv_draw_buf = - lv_draw_buf_create(width, height, lv_display_get_color_format(window->lv_disp), stride); + lv_draw_buf_create(w, h, lv_display_get_color_format(window->lv_disp), stride); buffers[i].strides[0] = stride; buffers[i].dmabuf_fds[0] = g2d_get_buf_fd(buffers[i].lv_draw_buf); buffers[i].buf_base[0] = buffers[i].lv_draw_buf->data; @@ -352,7 +401,7 @@ static struct buffer * lv_wayland_dmabuf_create_draw_buffers_internal(struct win 0); zwp_linux_buffer_params_v1_add_listener(params, ¶ms_listener, &buffers[i]); - zwp_linux_buffer_params_v1_create(params, width, height, drmcf, flags); + zwp_linux_buffer_params_v1_create(params, w, h, drmcf, flags); } wl_display_roundtrip(lv_wl_ctx.display); @@ -538,6 +587,7 @@ static void dmabuf_format(void * data, struct zwp_linux_dmabuf_v1 * zwp_linux_dm } } +#if !LV_USE_ROTATE_G2D static struct buffer * dmabuf_acquire_buffer(dmabuf_ctx_t * context, unsigned char * color_p) { @@ -565,6 +615,15 @@ static struct buffer * dmabuf_acquire_buffer(dmabuf_ctx_t * context, unsigned ch return NULL; } +#else +static struct buffer * get_next_buffer(dmabuf_ctx_t * context) +{ + int next_buf = (context->last_used + 1) % (LV_WAYLAND_BUF_COUNT - 1); + context->buffers[next_buf].busy = 1; + context->last_used = next_buf; + return &context->buffers[next_buf]; +} +#endif #if LV_WAYLAND_WINDOW_DECORATIONS static void create_decorators_buf(struct window * window, struct graphic_object * decoration) @@ -615,18 +674,15 @@ struct buffer * dmabuf_acquire_pool_buffer(struct window * window, struct graphi { uint8_t id = decoration->type; - if(window->decorators_buf[id] == NULL || (window->decorators_buf[id]->width == (uint32_t)decoration->width && - window->decorators_buf[id]->height == (uint32_t)decoration->height)) { + if(window->decorators_buf[id] == NULL) { create_decorators_buf(window, decoration); - - return window->decorators_buf[id]; } - else { + else if(window->decorators_buf[id]->width != (uint32_t)decoration->width || + window->decorators_buf[id]->height != (uint32_t)decoration->height) { destroy_decorators_buf(window, decoration); create_decorators_buf(window, decoration); - - return window->decorators_buf[id]; } + return window->decorators_buf[id]; } #endif diff --git a/src/drivers/wayland/lv_wl_window.c b/src/drivers/wayland/lv_wl_window.c index 86dab07850..4bf4ee20d0 100644 --- a/src/drivers/wayland/lv_wl_window.c +++ b/src/drivers/wayland/lv_wl_window.c @@ -83,6 +83,9 @@ lv_display_t * lv_wayland_window_create(uint32_t hor_res, uint32_t ver_res, char int32_t window_width; int32_t window_height; + uint32_t width = hor_res; + uint32_t height = ver_res; + lv_wayland_init(); window_width = hor_res; @@ -104,7 +107,7 @@ lv_display_t * lv_wayland_window_create(uint32_t hor_res, uint32_t ver_res, char window->close_cb = close_cb; /* Initialize display driver */ - window->lv_disp = lv_display_create(hor_res, ver_res); + window->lv_disp = lv_display_create(width, height); if(window->lv_disp == NULL) { LV_LOG_ERROR("failed to create lvgl display"); return NULL; @@ -137,6 +140,8 @@ lv_display_t * lv_wayland_window_create(uint32_t hor_res, uint32_t ver_res, char lv_display_set_flush_cb(window->lv_disp, lv_wayland_shm_flush_partial_mode); #endif + lv_display_add_event_cb(window->lv_disp, lv_wayland_event_cb, LV_EVENT_RESOLUTION_CHANGED, window); + /* Register input */ window->lv_indev_pointer = lv_wayland_pointer_create(); @@ -319,22 +324,26 @@ lv_result_t lv_wayland_window_resize(struct window * window, int width, int heig height -= (TITLE_BAR_HEIGHT + (2 * BORDER_SIZE)); } #endif + if(window->lv_disp) { + lv_display_set_resolution(window->lv_disp, width, height); + window->body->input.pointer.x = LV_MIN((int32_t)window->body->input.pointer.x, (width - 1)); + window->body->input.pointer.y = LV_MIN((int32_t)window->body->input.pointer.y, (height - 1)); + } + /* On the first resize call, the resolution of the display is already set, so there won't be a trigger on the resolution changed event.*/ + if(!window->is_window_configured) { #if LV_WAYLAND_USE_DMABUF - { lv_result_t err = lv_wayland_dmabuf_resize_window(&window->wl_ctx->dmabuf_ctx, window, width, height); if(err != LV_RESULT_OK) { return err; } - } #else - { lv_result_t err = lv_wayland_shm_resize_window(&window->wl_ctx->shm_ctx, window, width, height); if(err != LV_RESULT_OK) { return err; } - } #endif + } #if LV_WAYLAND_WINDOW_DECORATIONS if(!window->wl_ctx->opt_disable_decorations && !window->fullscreen) { @@ -347,11 +356,6 @@ lv_result_t lv_wayland_window_resize(struct window * window, int width, int heig } #endif - if(window->lv_disp) { - lv_display_set_resolution(window->lv_disp, width, height); - window->body->input.pointer.x = LV_MIN((int32_t)window->body->input.pointer.x, (width - 1)); - window->body->input.pointer.y = LV_MIN((int32_t)window->body->input.pointer.y, (height - 1)); - } window->width = width; window->height = height; return LV_RESULT_OK; diff --git a/src/lv_conf_internal.h b/src/lv_conf_internal.h index d6bc01ce30..fb70b3e207 100644 --- a/src/lv_conf_internal.h +++ b/src/lv_conf_internal.h @@ -759,15 +759,37 @@ #endif /** Use NXP's G2D on MPU platforms. */ -#ifndef LV_USE_DRAW_G2D - #ifdef CONFIG_LV_USE_DRAW_G2D - #define LV_USE_DRAW_G2D CONFIG_LV_USE_DRAW_G2D +#ifndef LV_USE_G2D + #ifdef CONFIG_LV_USE_G2D + #define LV_USE_G2D CONFIG_LV_USE_G2D #else - #define LV_USE_DRAW_G2D 0 + #define LV_USE_G2D 0 #endif #endif -#if LV_USE_DRAW_G2D +#if LV_USE_G2D + /** Use G2D for drawing. **/ + #ifndef LV_USE_DRAW_G2D + #ifdef LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_DRAW_G2D + #define LV_USE_DRAW_G2D CONFIG_LV_USE_DRAW_G2D + #else + #define LV_USE_DRAW_G2D 0 + #endif + #else + #define LV_USE_DRAW_G2D 1 + #endif + #endif + + /** Use G2D to rotate display. **/ + #ifndef LV_USE_ROTATE_G2D + #ifdef CONFIG_LV_USE_ROTATE_G2D + #define LV_USE_ROTATE_G2D CONFIG_LV_USE_ROTATE_G2D + #else + #define LV_USE_ROTATE_G2D 0 + #endif + #endif + /** Maximum number of buffers that can be stored for G2D draw unit. * Includes the frame buffers and assets. */ #ifndef LV_G2D_HASH_TABLE_SIZE @@ -778,7 +800,7 @@ #endif #endif - #if LV_USE_OS + #if LV_USE_DRAW_G2D && LV_USE_OS /** Use additional draw thread for G2D processing.*/ #ifndef LV_USE_G2D_DRAW_THREAD #ifdef LV_KCONFIG_PRESENT diff --git a/src/lv_init.c b/src/lv_init.c index b74289c56e..eaf4e74a4d 100644 --- a/src/lv_init.c +++ b/src/lv_init.c @@ -54,8 +54,10 @@ #include "draw/nxp/pxp/lv_draw_pxp.h" #endif #endif -#if LV_USE_DRAW_G2D - #include "draw/nxp/g2d/lv_draw_g2d.h" +#if LV_USE_G2D + #if LV_USE_DRAW_G2D || LV_USE_ROTATE_G2D + #include "draw/nxp/g2d/lv_draw_g2d.h" + #endif #endif #if LV_USE_DRAW_DAVE2D #include "draw/renesas/dave2d/lv_draw_dave2d.h" @@ -244,9 +246,11 @@ void lv_init(void) #endif #endif -#if LV_USE_DRAW_G2D +#if LV_USE_G2D +#if LV_USE_DRAW_G2D || LV_USE_ROTATE_G2D lv_draw_g2d_init(); #endif +#endif #if LV_USE_DRAW_DAVE2D lv_draw_dave2d_init(); @@ -475,9 +479,11 @@ void lv_deinit(void) #endif #endif -#if LV_USE_DRAW_G2D +#if LV_USE_G2D +#if LV_USE_DRAW_G2D || LV_USE_ROTATE_G2D lv_draw_g2d_deinit(); #endif +#endif #if LV_USE_DRAW_VG_LITE lv_draw_vg_lite_deinit();