From 710e134abf6c9d908a3a1d589d3e863eed2d3a7c Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 12 Dec 2023 11:43:21 +0100 Subject: [PATCH] feat(gpu): add renesas dav2d GPU support --- lv_conf_template.h | 3 + src/draw/renesas/dave2d/lv_draw_dave2d.c | 637 ++++++++++++++++++ src/draw/renesas/dave2d/lv_draw_dave2d.h | 94 +++ src/draw/renesas/dave2d/lv_draw_dave2d_arc.c | 156 +++++ .../renesas/dave2d/lv_draw_dave2d_border.c | 396 +++++++++++ src/draw/renesas/dave2d/lv_draw_dave2d_fill.c | 290 ++++++++ .../renesas/dave2d/lv_draw_dave2d_image.c | 580 ++++++++++++++++ .../renesas/dave2d/lv_draw_dave2d_label.c | 166 +++++ src/draw/renesas/dave2d/lv_draw_dave2d_line.c | 107 +++ .../dave2d/lv_draw_dave2d_mask_rectangle.c | 69 ++ .../renesas/dave2d/lv_draw_dave2d_triangle.c | 192 ++++++ .../renesas/dave2d/lv_draw_dave2d_uitls.c | 121 ++++ .../renesas/dave2d/lv_draw_dave2d_utils.h | 43 ++ src/lv_conf_internal.h | 9 + src/lv_init.c | 8 + 15 files changed, 2871 insertions(+) create mode 100644 src/draw/renesas/dave2d/lv_draw_dave2d.c create mode 100644 src/draw/renesas/dave2d/lv_draw_dave2d.h create mode 100644 src/draw/renesas/dave2d/lv_draw_dave2d_arc.c create mode 100644 src/draw/renesas/dave2d/lv_draw_dave2d_border.c create mode 100644 src/draw/renesas/dave2d/lv_draw_dave2d_fill.c create mode 100644 src/draw/renesas/dave2d/lv_draw_dave2d_image.c create mode 100644 src/draw/renesas/dave2d/lv_draw_dave2d_label.c create mode 100644 src/draw/renesas/dave2d/lv_draw_dave2d_line.c create mode 100644 src/draw/renesas/dave2d/lv_draw_dave2d_mask_rectangle.c create mode 100644 src/draw/renesas/dave2d/lv_draw_dave2d_triangle.c create mode 100644 src/draw/renesas/dave2d/lv_draw_dave2d_uitls.c create mode 100644 src/draw/renesas/dave2d/lv_draw_dave2d_utils.h diff --git a/lv_conf_template.h b/lv_conf_template.h index f36c99f51..f004711c1 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -122,6 +122,9 @@ /* Use NXP's PXP on iMX RTxxx platforms. */ #define LV_USE_DRAW_PXP 0 +/* Use Renesas Dave2D on RA platforms. */ +#define LV_USE_DRAW_DAVE2D 0 + /* Draw using cached SDL textures*/ #define LV_USE_DRAW_SDL 0 diff --git a/src/draw/renesas/dave2d/lv_draw_dave2d.c b/src/draw/renesas/dave2d/lv_draw_dave2d.c new file mode 100644 index 000000000..895cdb7ba --- /dev/null +++ b/src/draw/renesas/dave2d/lv_draw_dave2d.c @@ -0,0 +1,637 @@ +/** + * @file lv_draw_dave2d.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_dave2d.h" +#if LV_USE_DRAW_DAVE2D + +/********************* + * DEFINES + *********************/ +#define DRAW_UNIT_ID_DAVE2D 4 + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +#if LV_USE_OS + static void _dave2d_render_thread_cb(void * ptr); +#endif + +static void execute_drawing(lv_draw_dave2d_unit_t * u); + +#if defined(RENESAS_CORTEX_M85) +#if (BSP_CFG_DCACHE_ENABLED) +static void _dave2d_buf_invalidate_cache_cb(void * buf, uint32_t stride, lv_color_format_t color_format, + const lv_area_t * area); +#endif +#endif + +static void _dave2d_buf_copy(void * dest_buf, uint32_t dest_w, uint32_t dest_h, const lv_area_t * dest_area, + void * src_buf, uint32_t src_w, uint32_t src_h, const lv_area_t * src_area, lv_color_format_t color_format); + +static int32_t _dave2d_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task); + +static int32_t lv_draw_dave2d_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer); + +static d2_s32 lv_dave2d_init(void); + +static void lv_draw_buf_dave2d_init_handlers(void); + +void dave2d_execute_dlist_and_flush(void); + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +d2_device * _d2_handle; +d2_renderbuffer * _renderbuffer; +d2_renderbuffer * _blit_renderbuffer; + +lv_ll_t _ll_Dave2D_Tasks; + +#if LV_USE_OS + lv_mutex_t xd2Semaphore; +#endif + + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_dave2d_init(void) +{ + d2_s32 result = D2_OK; + + lv_draw_buf_dave2d_init_handlers(); + + lv_draw_dave2d_unit_t * draw_dave2d_unit = lv_draw_create_unit(sizeof(lv_draw_dave2d_unit_t)); + draw_dave2d_unit->base_unit.dispatch_cb = lv_draw_dave2d_dispatch; + draw_dave2d_unit->base_unit.evaluate_cb = _dave2d_evaluate; + draw_dave2d_unit->idx = DRAW_UNIT_ID_DAVE2D; + + result = lv_dave2d_init(); + if(D2_OK != result) { + __BKPT(0); + } + +#if LV_USE_OS + lv_result_t res; + res = lv_mutex_init(&xd2Semaphore); + if(LV_RESULT_OK != res) { + __BKPT(0); + } + + draw_dave2d_unit->pd2Mutex = &xd2Semaphore; +#endif + + draw_dave2d_unit->d2_handle = _d2_handle; + draw_dave2d_unit->renderbuffer = _renderbuffer; + _lv_ll_init(&_ll_Dave2D_Tasks, 4); + +#if LV_USE_OS + lv_thread_init(&draw_dave2d_unit->thread, LV_THREAD_PRIO_HIGH, _dave2d_render_thread_cb, 8 * 1024, draw_dave2d_unit); +#endif + +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void lv_draw_buf_dave2d_init_handlers(void) +{ + lv_draw_buf_handlers_t * handlers = lv_draw_buf_get_handlers(); + +#if defined(RENESAS_CORTEX_M85) +#if (BSP_CFG_DCACHE_ENABLED) + handlers->invalidate_cache_cb = _dave2d_buf_invalidate_cache_cb; +#endif +#endif + handlers->buf_copy_cb = _dave2d_buf_copy; +} + +#if defined(RENESAS_CORTEX_M85) +#if (BSP_CFG_DCACHE_ENABLED) +static void _dave2d_buf_invalidate_cache_cb(void * buf, uint32_t stride, lv_color_format_t color_format, + const lv_area_t * area) +{ + uint8_t * address = buf; + int32_t i = 0; + uint32_t bytes_per_pixel = lv_color_format_get_size(color_format); + int32_t width = lv_area_get_width(area); + int32_t lines = lv_area_get_height(area); + int32_t bytes_to_flush_per_line = (int32_t)width * (int32_t)bytes_per_pixel; + + /* Stride is in bytes, not pixels */ + address = address + (area->x1 * (int32_t)bytes_per_pixel) + (stride * (uint32_t)area->y1); + + for(i = 0; i < lines; i++) { + SCB_CleanInvalidateDCache_by_Addr(address, bytes_to_flush_per_line); + address += stride; + } +} +#endif +#endif + +static void _dave2d_buf_copy(void * dest_buf, uint32_t dest_w, uint32_t dest_h, const lv_area_t * dest_area, + void * src_buf, uint32_t src_w, uint32_t src_h, const lv_area_t * src_area, lv_color_format_t color_format) +{ + d2_s32 result; + +#if LV_USE_OS + lv_result_t status; + + status = lv_mutex_lock(&xd2Semaphore); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + + d2_u32 src_blend_mode = d2_getblendmodesrc(_d2_handle); + d2_u32 dst_blend_mode = d2_getblendmodedst(_d2_handle); + + result = d2_selectrenderbuffer(_d2_handle, _blit_renderbuffer); + if(D2_OK != result) { + __BKPT(0); + } + + result = d2_setblendmode(_d2_handle, d2_bm_one, d2_bm_zero); + if(D2_OK != result) { + __BKPT(0); + } + + // Generate render operations + result = d2_framebuffer(_d2_handle, (uint16_t *)dest_buf, DISPLAY_HSIZE_INPUT0, DISPLAY_BUFFER_STRIDE_PIXELS_INPUT0, + DISPLAY_VSIZE_INPUT0, lv_draw_dave2d_cf_fb_get()); + if(D2_OK != result) { + __BKPT(0); + } + + result = d2_cliprect(_d2_handle, (d2_border)dest_area->x1, (d2_border)dest_area->y1, (d2_border)dest_area->x2, + (d2_border)dest_area->y2); + if(D2_OK != result) { + __BKPT(0); + } + + result = d2_setblitsrc(_d2_handle, (void *) src_buf, (d2_s32)src_w, (d2_s32)src_w, (d2_s32)src_h, + lv_draw_dave2d_lv_colour_fmt_to_d2_fmt(color_format)); + if(D2_OK != result) { + __BKPT(0); + } + + result = d2_blitcopy(_d2_handle, (d2_s32)src_w, (d2_s32)src_h, (d2_blitpos)src_area->x1, (d2_blitpos)src_area->y1, + D2_FIX4(dest_w), D2_FIX4(dest_h), + D2_FIX4(dest_area->x1), D2_FIX4(dest_area->y1), 0); + if(D2_OK != result) { + __BKPT(0); + } + + // Execute render operations + result = d2_executerenderbuffer(_d2_handle, _blit_renderbuffer, 0); + if(D2_OK != result) { + __BKPT(0); + } + + result = d2_flushframe(_d2_handle); + if(D2_OK != result) { + __BKPT(0); + } + + result = d2_selectrenderbuffer(_d2_handle, _renderbuffer); + if(D2_OK != result) { + __BKPT(0); + } + + result = d2_setblendmode(_d2_handle, src_blend_mode, dst_blend_mode); + if(D2_OK != result) { + __BKPT(0); + } + +#if LV_USE_OS + status = lv_mutex_unlock(&xd2Semaphore); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + +} + +#define USE_D2 (1) + +static int32_t _dave2d_evaluate(lv_draw_unit_t * u, lv_draw_task_t * t) +{ + LV_UNUSED(u); + int32_t ret = 0; + + switch(t->type) { + case LV_DRAW_TASK_TYPE_FILL: { +#if USE_D2 + lv_draw_fill_dsc_t * dsc = t->draw_dsc; + if(dsc->grad.dir == LV_GRAD_DIR_NONE + || ((dsc->grad.dir != LV_GRAD_DIR_NONE) + && ((dsc->grad.stops[0].color.blue == dsc->grad.stops[dsc->grad.stops_count - 1].color.blue) + && (dsc->grad.stops[0].color.red == dsc->grad.stops[dsc->grad.stops_count - 1].color.red) + && (dsc->grad.stops[0].color.green == dsc->grad.stops[dsc->grad.stops_count - 1].color.green)))) { + + t->preferred_draw_unit_id = DRAW_UNIT_ID_DAVE2D; + t->preference_score = 0; + + } + else +#endif + { + __NOP(); + } + ret = 0; + break; + } +#if 0 + case LV_DRAW_TASK_TYPE_BG_IMG: { + ret = 0; + break; + } +#endif + case LV_DRAW_TASK_TYPE_LAYER: { + ret = 0; + break; + } + + case LV_DRAW_TASK_TYPE_IMAGE: { +#if USE_D2 + t->preferred_draw_unit_id = DRAW_UNIT_ID_DAVE2D; + t->preference_score = 0; +#endif + ret = 0; + break; + } + + case LV_DRAW_TASK_TYPE_BORDER: { +#if USE_D2 + t->preferred_draw_unit_id = DRAW_UNIT_ID_DAVE2D; + t->preference_score = 0; +#endif + ret = 0; + break; + } + + case LV_DRAW_TASK_TYPE_BOX_SHADOW: { + ret = 0; + break; + } + + case LV_DRAW_TASK_TYPE_LABEL: { +#if USE_D2 + t->preferred_draw_unit_id = DRAW_UNIT_ID_DAVE2D; + t->preference_score = 0; +#endif + ret = 0; + break; + } + + case LV_DRAW_TASK_TYPE_LINE: { +#if USE_D2 + t->preferred_draw_unit_id = DRAW_UNIT_ID_DAVE2D; + t->preference_score = 0; +#endif + ret = 0; + break; + } + + case LV_DRAW_TASK_TYPE_ARC: { +#if USE_D2 + t->preferred_draw_unit_id = DRAW_UNIT_ID_DAVE2D; + t->preference_score = 0; +#endif + ret = 0; + break; + } + + case LV_DRAW_TASK_TYPE_TRIANGLE: { +#if USE_D2 + lv_draw_fill_dsc_t * dsc = t->draw_dsc; + if(dsc->grad.dir == LV_GRAD_DIR_NONE + || ((dsc->grad.dir != LV_GRAD_DIR_NONE) + && ((dsc->grad.stops[0].color.blue == dsc->grad.stops[dsc->grad.stops_count - 1].color.blue) + && (dsc->grad.stops[0].color.red == dsc->grad.stops[dsc->grad.stops_count - 1].color.red) + && (dsc->grad.stops[0].color.green == dsc->grad.stops[dsc->grad.stops_count - 1].color.green)))) { + t->preferred_draw_unit_id = DRAW_UNIT_ID_DAVE2D; + t->preference_score = 0; + } + else { + } +#endif + ret = 0; + break; + } + + case LV_DRAW_TASK_TYPE_MASK_RECTANGLE: { +#if 0//USE_D2 + t->preferred_draw_unit_id = DRAW_UNIT_ID_DAVE2D; + t->preference_score = 0; +#endif + ret = 0; + break; + } + + case LV_DRAW_TASK_TYPE_MASK_BITMAP: { + ret = 0; + break; + } + + default: + ret = 0; + break; + } + + return ret; +} + +#define DAVE2D_REFFERING_WATERMARK 10 + +static int32_t lv_draw_dave2d_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer) +{ + lv_draw_dave2d_unit_t * draw_dave2d_unit = (lv_draw_dave2d_unit_t *) draw_unit; +#if (0 == D2_RENDER_EACH_OPERATION) + static uint32_t ref_count = 0; +#endif + + /*Return immediately if it's busy with draw task*/ + if(draw_dave2d_unit->task_act) return 0; + + lv_draw_task_t * t = NULL; + t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_DAVE2D); + + /* Return 0 is no selection, some tasks can be supported by other units. */ + if(t == NULL) { +#if (0 == D2_RENDER_EACH_OPERATION) + if(false == _lv_ll_is_empty(&_ll_Dave2D_Tasks)) { + ref_count = 0; + dave2d_execute_dlist_and_flush(); + } +#endif + return 0; + } + + if(t->preferred_draw_unit_id != DRAW_UNIT_ID_DAVE2D) { + return 0; + } + +#if (0 == D2_RENDER_EACH_OPERATION) + ref_count += lv_draw_get_dependent_count(t); + + if(DAVE2D_REFFERING_WATERMARK < ref_count) { + ref_count = 0; + dave2d_execute_dlist_and_flush(); + } + + struct _lv_draw_task_t ** p_new_list_entry; + p_new_list_entry = _lv_ll_ins_tail(&_ll_Dave2D_Tasks); + *p_new_list_entry = t; +#endif + + t->state = LV_DRAW_TASK_STATE_IN_PROGRESS; + draw_dave2d_unit->base_unit.target_layer = layer; + draw_dave2d_unit->base_unit.clip_area = &t->clip_area; + draw_dave2d_unit->task_act = t; + +#if LV_USE_OS + /*Let the render thread work*/ + lv_thread_sync_signal(&draw_dave2d_unit->sync); +#else + execute_drawing(draw_dave2d_unit); +#if (D2_RENDER_EACH_OPERATION) + draw_dave2d_unit->task_act->state = LV_DRAW_TASK_STATE_READY; +#endif + draw_dave2d_unit->task_act = NULL; + + /*The draw unit is free now. Request a new dispatching as it can get a new task*/ + lv_draw_dispatch_request(); + +#endif + return 1; +} + + + +#if LV_USE_OS +static void _dave2d_render_thread_cb(void * ptr) +{ + lv_draw_dave2d_unit_t * u = ptr; + + lv_thread_sync_init(&u->sync); + + while(1) { + while(u->task_act == NULL) { + lv_thread_sync_wait(&u->sync); + } + + execute_drawing(u); + + /*Cleanup*/ +#if (D2_RENDER_EACH_OPERATION) + u->task_act->state = LV_DRAW_TASK_STATE_READY; +#endif + u->task_act = NULL; + + /*The draw unit is free now. Request a new dispatching as it can get a new task*/ + lv_draw_dispatch_request(); + } +} +#endif + +static void execute_drawing(lv_draw_dave2d_unit_t * u) +{ + /*Render the draw task*/ + lv_draw_task_t * t = u->task_act; + lv_layer_t * layer = u->base_unit.target_layer; + +#if defined(RENESAS_CORTEX_M85) +#if (BSP_CFG_DCACHE_ENABLED) + lv_area_t clipped_area; + int32_t x; + int32_t y; + + _lv_area_intersect(&clipped_area, &t->area, u->base_unit.clip_area); + + x = 0 - u->base_unit.target_layer->buf_area.x1; + y = 0 - u->base_unit.target_layer->buf_area.y1; + + lv_area_move(&clipped_area, x, y); + + /* Invalidate cache */ + lv_draw_buf_invalidate_cache(layer->buf, layer->buf_stride, layer->color_format, &clipped_area); +#endif +#endif + + switch(t->type) { + case LV_DRAW_TASK_TYPE_FILL: + lv_draw_dave2d_fill(u, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_BORDER: + lv_draw_dave2d_border(u, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_BOX_SHADOW: + //lv_draw_dave2d_box_shadow(u, t->draw_dsc, &t->area); + break; +#if 0 + case LV_DRAW_TASK_TYPE_BG_IMG: + //lv_draw_dave2d_bg_image(u, t->draw_dsc, &t->area); + break; +#endif + case LV_DRAW_TASK_TYPE_LABEL: + lv_draw_dave2d_label(u, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_IMAGE: + lv_draw_dave2d_image(u, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_LINE: + lv_draw_dave2d_line(u, t->draw_dsc); + break; + case LV_DRAW_TASK_TYPE_ARC: + lv_draw_dave2d_arc(u, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_TRIANGLE: + lv_draw_dave2d_triangle(u, t->draw_dsc); + break; + case LV_DRAW_TASK_TYPE_LAYER: + //lv_draw_dave2d_layer(u, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_MASK_RECTANGLE: + //lv_draw_dave2d_mask_rect(u, t->draw_dsc, &t->area); + break; + default: + break; + } + +} + +static d2_s32 lv_dave2d_init(void) +{ + d2_s32 result = D2_OK; + + if(_d2_handle != NULL) { + return D2_NOMEMORY; + } + + _d2_handle = d2_opendevice(0); + if(_d2_handle == NULL) { + return D2_NOMEMORY; + } + + /* bind the hardware */ + result = d2_inithw(_d2_handle, 0); + if(result != D2_OK) { + LV_LOG_ERROR("Could NOT d2_inithw\n"); + d2_closedevice(_d2_handle); + return result; + } + + // + // Set various D2 parameters + // + result = d2_setblendmode(_d2_handle, d2_bm_alpha, d2_bm_one_minus_alpha); + result = d2_setalphamode(_d2_handle, d2_am_constant); + result = d2_setalpha(_d2_handle, UINT8_MAX); + result = d2_setantialiasing(_d2_handle, 1); + result = d2_setlinecap(_d2_handle, d2_lc_butt); + result = d2_setlinejoin(_d2_handle, d2_lj_miter); + + /* set blocksize for default displaylist */ + result = d2_setdlistblocksize(_d2_handle, 25); + if(D2_OK != result) { + LV_LOG_ERROR("Could NOT d2_setdlistblocksize\n"); + d2_closedevice(_d2_handle); + return result; + } + + _blit_renderbuffer = d2_newrenderbuffer(_d2_handle, 20, 20); + if(!_blit_renderbuffer) { + LV_LOG_ERROR("NO renderbuffer\n"); + d2_closedevice(_d2_handle); + + return D2_NOMEMORY; + } + + _renderbuffer = d2_newrenderbuffer(_d2_handle, 20, 20); + if(!_renderbuffer) { + LV_LOG_ERROR("NO renderbuffer\n"); + d2_closedevice(_d2_handle); + + return D2_NOMEMORY; + } + + result = d2_selectrenderbuffer(_d2_handle, _renderbuffer); + if(D2_OK != result) { + LV_LOG_ERROR("Could NOT d2_selectrenderbuffer\n"); + d2_closedevice(_d2_handle); + } + + return result; +} + + + +void dave2d_execute_dlist_and_flush(void) +{ +#if LV_USE_OS + lv_result_t status; + + status = lv_mutex_lock(&xd2Semaphore); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + + d2_s32 result; + struct _lv_draw_task_t ** p_list_entry; + struct _lv_draw_task_t * p_list_entry1; + + // Execute render operations + result = d2_executerenderbuffer(_d2_handle, _renderbuffer, 0); + if(D2_OK != result) { + __BKPT(0); + } + + result = d2_flushframe(_d2_handle); + if(D2_OK != result) { + __BKPT(0); + } + + result = d2_selectrenderbuffer(_d2_handle, _renderbuffer); + if(D2_OK != result) { + __BKPT(0); + } + + while(false == _lv_ll_is_empty(&_ll_Dave2D_Tasks)) { + p_list_entry = _lv_ll_get_tail(&_ll_Dave2D_Tasks); + p_list_entry1 = *p_list_entry; + p_list_entry1->state = LV_DRAW_TASK_STATE_READY; + _lv_ll_remove(&_ll_Dave2D_Tasks, p_list_entry); + lv_free(p_list_entry); + } + +#if LV_USE_OS + status = lv_mutex_unlock(&xd2Semaphore); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif +} + +#endif /*LV_USE_DRAW_DAVE2D*/ diff --git a/src/draw/renesas/dave2d/lv_draw_dave2d.h b/src/draw/renesas/dave2d/lv_draw_dave2d.h new file mode 100644 index 000000000..4c3b750ec --- /dev/null +++ b/src/draw/renesas/dave2d/lv_draw_dave2d.h @@ -0,0 +1,94 @@ +#ifndef LV_DRAW_DAVE2D_H +#define LV_DRAW_DAVE2D_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lv_conf_internal.h" +#if LV_USE_DRAW_DAVE2D +#include "../../lv_draw.h" +#include "hal_data.h" +#include "lv_draw_dave2d_utils.h" + +/********************* + * DEFINES + *********************/ + +#define D2_RENDER_EACH_OPERATION (1) + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_draw_unit_t base_unit; + struct _lv_draw_task_t * task_act; +#if LV_USE_OS + lv_thread_sync_t sync; + lv_thread_t thread; +#endif + uint32_t idx; + d2_device * d2_handle; + d2_renderbuffer * renderbuffer; +#if LV_USE_OS + lv_mutex_t * pd2Mutex; +#endif +} lv_draw_dave2d_unit_t; + + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_draw_dave2d_init(void); + +void lv_draw_dave2d_image(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_area_t * coords); + +void lv_draw_dave2d_fill(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc, const lv_area_t * coords); + +void lv_draw_dave2d_border(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_border_dsc_t * dsc, + const lv_area_t * coords); + +void lv_draw_dave2d_box_shadow(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_box_shadow_dsc_t * dsc, + const lv_area_t * coords); + +//void lv_draw_dave2d_bg_image(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_bg_image_dsc_t * dsc, const lv_area_t * coords); + +void lv_draw_dave2d_label(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc, const lv_area_t * coords); + +void lv_draw_dave2d_arc(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_arc_dsc_t * dsc, const lv_area_t * coords); + +void lv_draw_dave2d_line(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc); + +void lv_draw_dave2d_layer(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_area_t * coords); + +void lv_draw_dave2d_triangle(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_triangle_dsc_t * dsc); + +void lv_draw_dave2d_mask_rect(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_mask_rect_dsc_t * dsc, + const lv_area_t * coords); + +void lv_draw_dave2d_transform(lv_draw_dave2d_unit_t * draw_unit, const lv_area_t * dest_area, const void * src_buf, + int32_t src_w, int32_t src_h, int32_t src_stride, + const lv_draw_image_dsc_t * draw_dsc, const lv_draw_image_sup_t * sup, lv_color_format_t cf, void * dest_buf); + +/*********************** + * GLOBAL VARIABLES + ***********************/ + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_DRAW_DAVE2D*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_USE_DRAW_DAVE2D*/ diff --git a/src/draw/renesas/dave2d/lv_draw_dave2d_arc.c b/src/draw/renesas/dave2d/lv_draw_dave2d_arc.c new file mode 100644 index 000000000..e5350cd9a --- /dev/null +++ b/src/draw/renesas/dave2d/lv_draw_dave2d_arc.c @@ -0,0 +1,156 @@ +#include "lv_draw_dave2d.h" +#if LV_USE_DRAW_DAVE2D + +void lv_draw_dave2d_arc(lv_draw_dave2d_unit_t * u, const lv_draw_arc_dsc_t * dsc, const lv_area_t * coords) +{ + + uint32_t flags = 0; + int32_t sin_start; + int32_t cos_start; + int32_t sin_end; + int32_t cos_end; + d2_s32 result; + lv_area_t clipped_area; + lv_area_t buffer_area; + lv_point_t arc_centre; + int32_t x; + int32_t y; + + if(!_lv_area_intersect(&clipped_area, coords, u->base_unit.clip_area)) return; + + x = 0 - u->base_unit.target_layer->buf_area.x1; + y = 0 - u->base_unit.target_layer->buf_area.y1; + + buffer_area = u->base_unit.target_layer->buf_area; + + arc_centre = dsc->center; + arc_centre.x = arc_centre.x - buffer_area.x1; + arc_centre.y = arc_centre.y - buffer_area.y1; + + lv_area_move(&clipped_area, x, y); + lv_area_move(&buffer_area, x, y); + + // + // If both angles are equal (e.g. 0 and 0 or 180 and 180) nothing has to be done + // + if(dsc->start_angle == dsc->end_angle) { + return; // Nothing to do, no angle - no arc + } + +#if LV_USE_OS + lv_result_t status; + status = lv_mutex_lock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + +#if D2_RENDER_EACH_OPERATION + d2_selectrenderbuffer(u->d2_handle, u->renderbuffer); +#endif + + // + // Generate render operations + // + d2_framebuffer(u->d2_handle, + u->base_unit.target_layer->buf, + (d2_s32)u->base_unit.target_layer->buf_stride / lv_color_format_get_size(u->base_unit.target_layer->color_format), + (d2_u32)lv_area_get_width(&buffer_area), + (d2_u32)lv_area_get_height(&buffer_area), + lv_draw_dave2d_cf_fb_get()); + + d2_setalpha(u->d2_handle, dsc->opa); + + d2_setcolor(u->d2_handle, 0, lv_draw_dave2d_lv_colour_to_d2_colour(dsc->color)); + + + result = d2_cliprect(u->d2_handle, (d2_border)clipped_area.x1, (d2_border)clipped_area.y1, (d2_border)clipped_area.x2, + (d2_border)clipped_area.y2); + if(D2_OK != result) { + __BKPT(0); + } + + if(360 <= LV_ABS(dsc->start_angle - dsc->end_angle)) { + d2_rendercircle(u->d2_handle, + (d2_point)D2_FIX4(arc_centre.x), + (d2_point) D2_FIX4(arc_centre.y), + (d2_width) D2_FIX4(dsc->radius - dsc->width / 2), + (d2_width) D2_FIX4(dsc->width)); + } + else { //An ARC, not a full circle + // + // If the difference between both is larger than 180 degrees we must use the concave flag + // + /** Set d2_wf_concave flag if the pie object to draw is concave shape. */ + if((LV_ABS(dsc->start_angle - dsc->end_angle) > 180) || ((dsc->end_angle < dsc->start_angle) && + (LV_ABS(dsc->start_angle - (dsc->end_angle + 360)) > 180))) { + flags = d2_wf_concave; + } + else { + flags = 0; + } + + sin_start = lv_trigo_sin((int16_t)dsc->start_angle); + cos_start = lv_trigo_cos((int16_t)dsc->start_angle); + + sin_end = lv_trigo_sin((int16_t)dsc->end_angle); + cos_end = lv_trigo_cos((int16_t)dsc->end_angle); + + result = d2_renderwedge(u->d2_handle, + (d2_point)D2_FIX4(arc_centre.x), + (d2_point) D2_FIX4(arc_centre.y), + (d2_width) D2_FIX4(dsc->radius - dsc->width / 2), + (d2_width) D2_FIX4(dsc->width), + -(d2_s32)(sin_start << 1), + (d2_s32)(cos_start << 1), + (d2_s32)(sin_end << 1), + -(d2_s32)(cos_end << 1), + flags); + if(D2_OK != result) { + __BKPT(0); + } + + + if(dsc->rounded) { + lv_point_t start_coord; + lv_point_t end_coord; + + start_coord.x = arc_centre.x + (int16_t)(((dsc->radius - dsc->width / 2) * cos_start) >> LV_TRIGO_SHIFT); + start_coord.y = arc_centre.y + (int16_t)(((dsc->radius - dsc->width / 2) * sin_start) >> LV_TRIGO_SHIFT); + + + /** Render a circle. */ + d2_rendercircle(u->d2_handle, + (d2_point) D2_FIX4((uint16_t)(start_coord.x)), + (d2_point) D2_FIX4((uint16_t)(start_coord.y)), + (d2_width) D2_FIX4(dsc->width / 2), 0); + + end_coord.x = arc_centre.x + (int16_t)(((dsc->radius - dsc->width / 2) * cos_end) >> LV_TRIGO_SHIFT); + end_coord.y = arc_centre.y + (int16_t)(((dsc->radius - dsc->width / 2) * sin_end) >> LV_TRIGO_SHIFT); + + /** Render a circle. */ + d2_rendercircle(u->d2_handle, + (d2_point) D2_FIX4((uint16_t)(end_coord.x)), + (d2_point) D2_FIX4((uint16_t)(end_coord.y)), + (d2_width) D2_FIX4(dsc->width / 2), 0); + } + } + + // + // Execute render operations + // + +#if D2_RENDER_EACH_OPERATION + d2_executerenderbuffer(u->d2_handle, u->renderbuffer, 0); + d2_flushframe(u->d2_handle); +#endif + +#if LV_USE_OS + status = lv_mutex_unlock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif +} + +#endif /*LV_USE_DRAW_DAVE2D*/ diff --git a/src/draw/renesas/dave2d/lv_draw_dave2d_border.c b/src/draw/renesas/dave2d/lv_draw_dave2d_border.c new file mode 100644 index 000000000..d583dde64 --- /dev/null +++ b/src/draw/renesas/dave2d/lv_draw_dave2d_border.c @@ -0,0 +1,396 @@ +#include "lv_draw_dave2d.h" +#if LV_USE_DRAW_DAVE2D + +static void dave2d_draw_border_complex(lv_draw_dave2d_unit_t * draw_unit, const lv_area_t * outer_area, + const lv_area_t * inner_area, + int32_t rout, int32_t rin, lv_color_t color, lv_opa_t opa); + +static void dave2d_draw_border_simple(lv_draw_dave2d_unit_t * draw_unit, const lv_area_t * outer_area, + const lv_area_t * inner_area, + lv_color_t color, lv_opa_t opa); + +void lv_draw_dave2d_border(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_border_dsc_t * dsc, + const lv_area_t * coords) +{ + if(dsc->opa <= LV_OPA_MIN) return; + if(dsc->width == 0) return; + if(dsc->side == LV_BORDER_SIDE_NONE) return; + + int32_t coords_w = lv_area_get_width(coords); + int32_t coords_h = lv_area_get_height(coords); + int32_t rout = dsc->radius; + int32_t short_side = LV_MIN(coords_w, coords_h); + if(rout > short_side >> 1) rout = short_side >> 1; + + /*Get the inner area*/ + lv_area_t area_inner; + lv_area_copy(&area_inner, coords); + area_inner.x1 += ((dsc->side & LV_BORDER_SIDE_LEFT) ? dsc->width : - (dsc->width + rout)); + area_inner.x2 -= ((dsc->side & LV_BORDER_SIDE_RIGHT) ? dsc->width : - (dsc->width + rout)); + area_inner.y1 += ((dsc->side & LV_BORDER_SIDE_TOP) ? dsc->width : - (dsc->width + rout)); + area_inner.y2 -= ((dsc->side & LV_BORDER_SIDE_BOTTOM) ? dsc->width : - (dsc->width + rout)); + + int32_t rin = rout - dsc->width; + if(rin < 0) rin = 0; + + if(rout == 0 && rin == 0) { + dave2d_draw_border_simple(draw_unit, coords, &area_inner, dsc->color, dsc->opa); + } + else { + dave2d_draw_border_complex(draw_unit, coords, &area_inner, rout, rin, dsc->color, dsc->opa); + } + +} + +static void dave2d_draw_border_simple(lv_draw_dave2d_unit_t * u, const lv_area_t * outer_area, + const lv_area_t * inner_area, + lv_color_t color, lv_opa_t opa) + +{ + + lv_area_t clip_area; + lv_area_t local_outer_area; + lv_area_t local_inner_area; + lv_area_t buffer_area; + int32_t x; + int32_t y; + bool is_common; + + + is_common = _lv_area_intersect(&clip_area, outer_area, u->base_unit.clip_area); + if(!is_common) return; + +#if LV_USE_OS + lv_result_t status; + status = lv_mutex_lock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + + buffer_area = u->base_unit.target_layer->buf_area; + local_outer_area = *outer_area; + local_inner_area = *inner_area; + + x = 0 - u->base_unit.target_layer->buf_area.x1; + y = 0 - u->base_unit.target_layer->buf_area.y1; + + lv_area_move(&clip_area, x, y); + lv_area_move(&buffer_area, x, y); + lv_area_move(&local_outer_area, x, y); + lv_area_move(&local_inner_area, x, y); + + +#if D2_RENDER_EACH_OPERATION + d2_selectrenderbuffer(u->d2_handle, u->renderbuffer); +#endif + // + // Generate render operations + // + d2_framebuffer(u->d2_handle, + u->base_unit.target_layer->buf, + (d2_s32)u->base_unit.target_layer->buf_stride / lv_color_format_get_size(u->base_unit.target_layer->color_format), + (d2_u32)lv_area_get_width(&buffer_area), + (d2_u32)lv_area_get_height(&buffer_area), + lv_draw_dave2d_cf_fb_get()); + + d2_setcolor(u->d2_handle, 0, lv_draw_dave2d_lv_colour_to_d2_colour(color)); + d2_setalpha(u->d2_handle, opa); + d2_cliprect(u->d2_handle, (d2_border)clip_area.x1, (d2_border)clip_area.y1, (d2_border)clip_area.x2, + (d2_border)clip_area.y2); + + lv_area_t a; + + bool top_side = local_outer_area.y1 <= local_inner_area.y1; + bool bottom_side = local_outer_area.y2 >= local_inner_area.y2; + bool left_side = local_outer_area.x1 <= local_inner_area.x1; + bool right_side = local_outer_area.x2 >= local_inner_area.x2; + + /*Top*/ + a.x1 = local_outer_area.x1; + a.x2 = local_outer_area.x2; + a.y1 = local_outer_area.y1; + a.y2 = local_inner_area.y1 - 1; + if(top_side) { + d2_renderbox(u->d2_handle, (d2_point)D2_FIX4(a.x1), + (d2_point)D2_FIX4(a.y1), + (d2_point)D2_FIX4(lv_area_get_width(&a)), + (d2_point)D2_FIX4(lv_area_get_height(&a))); + } + + /*Bottom*/ + a.y1 = local_inner_area.y2 + 1; + a.y2 = local_outer_area.y2; + if(bottom_side) { + d2_renderbox(u->d2_handle, (d2_point)D2_FIX4(a.x1), + (d2_point)D2_FIX4(a.y1), + (d2_point)D2_FIX4(lv_area_get_width(&a)), + (d2_point)D2_FIX4(lv_area_get_height(&a))); + } + + /*Left*/ + a.x1 = local_outer_area.x1; + a.x2 = local_inner_area.x1 - 1; + a.y1 = (top_side) ? local_inner_area.y1 : local_outer_area.y1; + a.y2 = (bottom_side) ? local_inner_area.y2 : local_outer_area.y2; + if(left_side) { + d2_renderbox(u->d2_handle, (d2_point)D2_FIX4(a.x1), + (d2_point)D2_FIX4(a.y1), + (d2_point)D2_FIX4(lv_area_get_width(&a)), + (d2_point)D2_FIX4(lv_area_get_height(&a))); + } + + /*Right*/ + a.x1 = local_inner_area.x2 + 1; + a.x2 = local_outer_area.x2; + if(right_side) { + d2_renderbox(u->d2_handle, (d2_point)D2_FIX4(a.x1), + (d2_point)D2_FIX4(a.y1), + (d2_point)D2_FIX4(lv_area_get_width(&a)), + (d2_point)D2_FIX4(lv_area_get_height(&a))); + } + + // + // Execute render operations + // +#if D2_RENDER_EACH_OPERATION + d2_executerenderbuffer(u->d2_handle, u->renderbuffer, 0); + d2_flushframe(u->d2_handle); +#endif + +#if LV_USE_OS + status = lv_mutex_unlock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif +} + +static void dave2d_draw_border_complex(lv_draw_dave2d_unit_t * u, const lv_area_t * orig_outer_area, + const lv_area_t * orig_inner_area, + int32_t rout, int32_t rin, lv_color_t color, lv_opa_t opa) +{ +#if LV_DRAW_SW_COMPLEX + /*Get clipped draw area which is the real draw area. + *It is always the same or inside `coords`*/ + lv_area_t draw_area; + lv_area_t outer_area; + lv_area_t inner_area; + lv_area_t buffer_area; + int32_t x; + int32_t y; + d2_s32 result; + d2_u32 flags = 0; + + outer_area = *orig_outer_area; + inner_area = *orig_inner_area; + + if(!_lv_area_intersect(&draw_area, &outer_area, u->base_unit.clip_area)) return; + int32_t draw_area_w = lv_area_get_width(&draw_area); + +#if LV_USE_OS + lv_result_t status; + status = lv_mutex_lock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + + buffer_area = u->base_unit.target_layer->buf_area; + + x = 0 - u->base_unit.target_layer->buf_area.x1; + y = 0 - u->base_unit.target_layer->buf_area.y1; + + lv_area_move(&draw_area, x, y); + lv_area_move(&buffer_area, x, y); + lv_area_move(&outer_area, x, y); + lv_area_move(&inner_area, x, y); + +#if D2_RENDER_EACH_OPERATION + d2_selectrenderbuffer(u->d2_handle, u->renderbuffer); +#endif + // + // Generate render operations + // + d2_framebuffer(u->d2_handle, + u->base_unit.target_layer->buf, + (d2_s32)u->base_unit.target_layer->buf_stride / lv_color_format_get_size(u->base_unit.target_layer->color_format), + (d2_u32)lv_area_get_width(&buffer_area), + (d2_u32)lv_area_get_height(&buffer_area), + lv_draw_dave2d_cf_fb_get()); + + d2_setcolor(u->d2_handle, 0, lv_draw_dave2d_lv_colour_to_d2_colour(color)); + d2_setalpha(u->d2_handle, opa); + d2_cliprect(u->d2_handle, (d2_border)draw_area.x1, (d2_border)draw_area.y1, (d2_border)draw_area.x2, + (d2_border)draw_area.y2); + + lv_area_t blend_area; + /*Calculate the x and y coordinates where the straight parts area are */ + lv_area_t core_area; + core_area.x1 = LV_MAX(outer_area.x1 + rout, inner_area.x1); + core_area.x2 = LV_MIN(outer_area.x2 - rout, inner_area.x2); + core_area.y1 = LV_MAX(outer_area.y1 + rout, inner_area.y1); + core_area.y2 = LV_MIN(outer_area.y2 - rout, inner_area.y2); + + bool top_side = outer_area.y1 <= inner_area.y1; + bool bottom_side = outer_area.y2 >= inner_area.y2; + + /*No masks*/ + bool left_side = outer_area.x1 <= inner_area.x1; + bool right_side = outer_area.x2 >= inner_area.x2; + + /*Draw the straight lines first */ + if(top_side) { + blend_area.x1 = core_area.x1; + blend_area.x2 = core_area.x2; + blend_area.y1 = outer_area.y1; + blend_area.y2 = inner_area.y1 - 1; + d2_renderbox(u->d2_handle, + (d2_point)D2_FIX4(blend_area.x1), + (d2_point)D2_FIX4(blend_area.y1), + (d2_point)D2_FIX4(lv_area_get_width(&blend_area)), + (d2_point)D2_FIX4(lv_area_get_height(&blend_area))); + } + + if(bottom_side) { + blend_area.x1 = core_area.x1; + blend_area.x2 = core_area.x2; + blend_area.y1 = inner_area.y2 + 1; + blend_area.y2 = outer_area.y2; + d2_renderbox(u->d2_handle, + (d2_point)D2_FIX4(blend_area.x1), + (d2_point)D2_FIX4(blend_area.y1), + (d2_point)D2_FIX4(lv_area_get_width(&blend_area)), + (d2_point)D2_FIX4(lv_area_get_height(&blend_area))); + } + + + if(left_side) { + blend_area.x1 = outer_area.x1; + blend_area.x2 = inner_area.x1 - 1; + blend_area.y1 = core_area.y1; + blend_area.y2 = core_area.y2; + d2_renderbox(u->d2_handle, + (d2_point)D2_FIX4(blend_area.x1), + (d2_point)D2_FIX4(blend_area.y1), + (d2_point)D2_FIX4(lv_area_get_width(&blend_area)), + (d2_point)D2_FIX4(lv_area_get_height(&blend_area))); + } + + if(right_side) { + blend_area.x1 = inner_area.x2 + 1; + blend_area.x2 = outer_area.x2; + blend_area.y1 = core_area.y1; + blend_area.y2 = core_area.y2; + d2_renderbox(u->d2_handle, + (d2_point)D2_FIX4(blend_area.x1), + (d2_point)D2_FIX4(blend_area.y1), + (d2_point)D2_FIX4(lv_area_get_width(&blend_area)), + (d2_point)D2_FIX4(lv_area_get_height(&blend_area))); + } + + + /*Draw the corners*/ + int32_t blend_w; + /*Left corners*/ + blend_area.x1 = draw_area.x1; + blend_area.x2 = LV_MIN(draw_area.x2, core_area.x1 - 1); + + blend_w = lv_area_get_width(&blend_area); + + if(blend_w > 0) { + if(left_side || top_side) { + result = d2_renderwedge(u->d2_handle, + (d2_point)D2_FIX4(core_area.x1), + (d2_point) D2_FIX4(core_area.y1), + (d2_width) D2_FIX4(rout), + (d2_width) D2_FIX4((rout - rin)), + (d2_s32) D2_FIX16(0), // 180 Degrees + (d2_s32) D2_FIX16((int16_t) -1), + (d2_s32) D2_FIX16((int16_t) -1),//( 270 Degrees + (d2_s32) D2_FIX16(0), + flags); + if(D2_OK != result) { + __BKPT(0); + } + + } + + if(left_side || bottom_side) { + result = d2_renderwedge(u->d2_handle, + (d2_point)D2_FIX4(core_area.x1), + (d2_point) D2_FIX4(core_area.y2), + (d2_width) D2_FIX4(rout), + (d2_width) D2_FIX4((rout - rin)), + (d2_s32) D2_FIX16((int16_t) -1), //90 degrees + (d2_s32) D2_FIX16(0), + (d2_s32) D2_FIX16(0), //180 degrees + (d2_s32) D2_FIX16(1), + flags); + if(D2_OK != result) { + __BKPT(0); + } + } + + /*Right corners*/ + blend_area.x1 = LV_MAX(draw_area.x1, blend_area.x2 + 1); /*To not overlap with the left side*/ + blend_area.x1 = LV_MAX(draw_area.x1, core_area.x2 + 1); + + blend_area.x2 = draw_area.x2; + blend_w = lv_area_get_width(&blend_area); + + if(blend_w > 0) { + if(right_side || top_side) { + result = d2_renderwedge(u->d2_handle, + (d2_point)D2_FIX4(core_area.x2), + (d2_point) D2_FIX4(core_area.y1), + (d2_width) D2_FIX4(rout), + (d2_width) D2_FIX4((rout - rin)), + (d2_s32) D2_FIX16((int16_t)1), // 270 Degrees + (d2_s32) D2_FIX16(0), + (d2_s32) D2_FIX16(0),// 0 degrees + (d2_s32) D2_FIX16(-1), + flags); + if(D2_OK != result) { + __BKPT(0); + } + + } + + if(right_side || bottom_side) { + result = d2_renderwedge(u->d2_handle, + (d2_point)D2_FIX4(core_area.x2), + (d2_point) D2_FIX4(core_area.y2), + (d2_width) D2_FIX4(rout), + (d2_width) D2_FIX4((rout - rin)), + (d2_s32) D2_FIX16(0),// 0 degrees + (d2_s32) D2_FIX16(1), + (d2_s32) D2_FIX16(1),// 90 degrees + (d2_s32) D2_FIX16(0), + flags); + if(D2_OK != result) { + __BKPT(0); + } + } + } + } + + // + // Execute render operations + // +#if D2_RENDER_EACH_OPERATION + d2_executerenderbuffer(u->d2_handle, u->renderbuffer, 0); + d2_flushframe(u->d2_handle); +#endif + +#if LV_USE_OS + status = lv_mutex_unlock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + +#endif /*LV_DRAW_SW_COMPLEX*/ +} + +#endif /*LV_USE_DRAW_DAVE2D*/ diff --git a/src/draw/renesas/dave2d/lv_draw_dave2d_fill.c b/src/draw/renesas/dave2d/lv_draw_dave2d_fill.c new file mode 100644 index 000000000..5556e7675 --- /dev/null +++ b/src/draw/renesas/dave2d/lv_draw_dave2d_fill.c @@ -0,0 +1,290 @@ +#include "lv_draw_dave2d.h" +#if LV_USE_DRAW_DAVE2D + + +void lv_draw_dave2d_fill(lv_draw_dave2d_unit_t * u, const lv_draw_fill_dsc_t * dsc, const lv_area_t * coords) +{ + lv_area_t draw_area; + lv_area_t buffer_area; + lv_area_t coordinates; + bool is_common; + int32_t x; + int32_t y; + d2_u8 current_alpha_mode = 0; + d2_s32 result; + d2_u32 flags = 0; + + lv_point_t arc_centre; + + is_common = _lv_area_intersect(&draw_area, coords, u->base_unit.clip_area); + if(!is_common) return; + +#if LV_USE_OS + lv_result_t status; + status = lv_mutex_lock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + + buffer_area = u->base_unit.target_layer->buf_area; + coordinates = *coords; + + x = 0 - u->base_unit.target_layer->buf_area.x1; + y = 0 - u->base_unit.target_layer->buf_area.y1; + + lv_area_move(&draw_area, x, y); + lv_area_move(&buffer_area, x, y); + lv_area_move(&coordinates, x, y); + + // + // Generate render operations + // +#if D2_RENDER_EACH_OPERATION + d2_selectrenderbuffer(u->d2_handle, u->renderbuffer); +#endif + + d2_framebuffer(u->d2_handle, + u->base_unit.target_layer->buf, + (d2_s32)u->base_unit.target_layer->buf_stride / lv_color_format_get_size(u->base_unit.target_layer->color_format), + (d2_u32)lv_area_get_width(&buffer_area), + (d2_u32)lv_area_get_height(&buffer_area), + lv_draw_dave2d_cf_fb_get()); + + + if(LV_GRAD_DIR_NONE != dsc->grad.dir) { + float a1; + float a2; + + float y1; + float y2; + + float y3; + float y0; + int16_t y0_i ; + int16_t y3_i ; + + if(LV_GRAD_DIR_VER == dsc->grad.dir) { + a1 = dsc->grad.stops[0].opa; + a2 = dsc->grad.stops[dsc->grad.stops_count - 1].opa; + + y1 = (float)LV_MIN(coordinates.y1, coordinates.y2); + y2 = (float)LV_MAX(coordinates.y1, coordinates.y2); + + if(a1 < a2) { + /* TODO */ + __BKPT(0); + y0 = 0.0f;//silence the compiler warning + y3 = 0.0f; + + } + else { + y0 = y2 - ((y2 - y1) / (a2 - a1) * (a2)); //point where alpha is 0 + y3 = y1 + ((y2 - y1) / (a2 - a1) * (255 - a1)); //point where alpha is 255 + } + + y0_i = (int16_t)y0; + y3_i = (int16_t)y3; + + d2_setalphagradient(u->d2_handle, 0, (d2_point)D2_FIX4(0), (d2_point)D2_FIX4(y0_i), (d2_point)D2_FIX4(0), + (d2_point)D2_FIX4((y3_i - y0_i))); + } + else if(LV_GRAD_DIR_HOR == dsc->grad.dir) { + /* TODO */ + __BKPT(0); + + float x1; + float x2; + + float x3; + float x0; + int16_t x0_i ; + int16_t x3_i ; + + a1 = dsc->grad.stops[0].opa; + a2 = dsc->grad.stops[dsc->grad.stops_count - 1].opa; + + x1 = (float)LV_MIN(coordinates.x1, coordinates.x2); + x2 = (float)LV_MAX(coordinates.x1, coordinates.x2); + + if(a1 < a2) { + /* TODO */ + __BKPT(0); + x0 = 0.0f;//silence the compiler warning + x3 = 0.0f; + + } + else { + x0 = x2 - ((x2 - x1) / (a2 - a1) * (a2)); //point where alpha is 0 + x3 = x1 + ((x2 - x1) / (a2 - a1) * (255 - a1)); //point where alpha is 255 + } + + x0_i = (int16_t)x0; + x3_i = (int16_t)x3; + + d2_setalphagradient(u->d2_handle, 0, (d2_point)D2_FIX4(x0_i), (d2_point)D2_FIX4(0), (d2_point)D2_FIX4(x3_i - x0_i), + (d2_point)D2_FIX4((0))); + } + + current_alpha_mode = d2_getalphamode(u->d2_handle); + d2_setfillmode(u->d2_handle, d2_fm_color); + d2_setcolor(u->d2_handle, 0, lv_draw_dave2d_lv_colour_to_d2_colour(dsc->grad.stops[0].color)); + d2_setalphamode(u->d2_handle, d2_am_gradient1); + } + else { + d2_setfillmode(u->d2_handle, d2_fm_color); //default + d2_setcolor(u->d2_handle, 0, lv_draw_dave2d_lv_colour_to_d2_colour(dsc->color)); + d2_setalpha(u->d2_handle, dsc->opa); + } + + + d2_cliprect(u->d2_handle, (d2_border)draw_area.x1, (d2_border)draw_area.y1, (d2_border)draw_area.x2, + (d2_border)draw_area.y2); + + if(dsc->radius == 0) { + + d2_renderbox(u->d2_handle, (d2_point)D2_FIX4(coordinates.x1), + (d2_point)D2_FIX4(coordinates.y1), + (d2_point)D2_FIX4(lv_area_get_width(&coordinates)), + (d2_point)D2_FIX4(lv_area_get_height(&coordinates))); + } + else { + /*Get the real radius. Can't be larger than the half of the shortest side */ + int32_t coords_bg_w = lv_area_get_width(&coordinates); + int32_t coords_bg_h = lv_area_get_height(&coordinates); + int32_t short_side = LV_MIN(coords_bg_w, coords_bg_h); + int32_t radius = LV_MIN(dsc->radius, short_side >> 1); + + arc_centre.x = coordinates.x1 + radius; + arc_centre.y = coordinates.y1 + radius; + + if(((2 * radius) == coords_bg_w) && ((2 * radius) == coords_bg_h)) { + result = d2_rendercircle(u->d2_handle, + (d2_point)D2_FIX4(arc_centre.x), + (d2_point) D2_FIX4(arc_centre.y), + (d2_width) D2_FIX4(radius), + (d2_width) D2_FIX4(0)); + if(D2_OK != result) { + __BKPT(0); + } + } + else { + arc_centre.x = coordinates.x1 + radius; + arc_centre.y = coordinates.y1 + radius; + + result = d2_renderwedge(u->d2_handle, + (d2_point)D2_FIX4(arc_centre.x), + (d2_point) D2_FIX4(arc_centre.y), + (d2_width) D2_FIX4(radius), + (d2_width) D2_FIX4(0), + (d2_s32) D2_FIX16(0), // 180 Degrees + (d2_s32) D2_FIX16((int16_t) -1), + (d2_s32) D2_FIX16((int16_t) -1),//( 270 Degrees + (d2_s32) D2_FIX16(0), + flags); + if(D2_OK != result) { + __BKPT(0); + } + + arc_centre.x = coordinates.x2 - radius; + arc_centre.y = coordinates.y1 + radius; + + result = d2_renderwedge(u->d2_handle, + (d2_point)D2_FIX4(arc_centre.x), + (d2_point) D2_FIX4(arc_centre.y), + (d2_width) D2_FIX4(radius), + (d2_width) D2_FIX4(0), + (d2_s32) D2_FIX16((int16_t)1), // 270 Degrees + (d2_s32) D2_FIX16(0), + (d2_s32) D2_FIX16(0),// 0 degrees + (d2_s32) D2_FIX16(-1), + flags); + if(D2_OK != result) { + __BKPT(0); + } + + arc_centre.x = coordinates.x2 - radius; + arc_centre.y = coordinates.y2 - radius; + + result = d2_renderwedge(u->d2_handle, + (d2_point)D2_FIX4(arc_centre.x), + (d2_point) D2_FIX4(arc_centre.y), + (d2_width) D2_FIX4(radius), + (d2_width) D2_FIX4(0), + (d2_s32) D2_FIX16(0),// 0 degrees + (d2_s32) D2_FIX16(1), + (d2_s32) D2_FIX16(1),// 90 degrees + (d2_s32) D2_FIX16(0), + flags); + if(D2_OK != result) { + __BKPT(0); + } + + arc_centre.x = coordinates.x1 + radius; + arc_centre.y = coordinates.y2 - radius; + + result = d2_renderwedge(u->d2_handle, + (d2_point)D2_FIX4(arc_centre.x), + (d2_point) D2_FIX4(arc_centre.y), + (d2_width) D2_FIX4(radius), + (d2_width) D2_FIX4(0), + (d2_s32) D2_FIX16((int16_t) -1), //90 degrees + (d2_s32) D2_FIX16(0), + (d2_s32) D2_FIX16(0), //180 degrees + (d2_s32) D2_FIX16(1), + flags); + if(D2_OK != result) { + __BKPT(0); + } + + result = d2_renderbox(u->d2_handle, + (d2_width)D2_FIX4(coordinates.x1 + radius), + (d2_width)D2_FIX4(coordinates.y1), + (d2_width)D2_FIX4(lv_area_get_width(&coordinates) - (2 * radius)), + (d2_width)D2_FIX4(lv_area_get_height(&coordinates))); + if(D2_OK != result) { + __BKPT(0); + } + + result = d2_renderbox(u->d2_handle, + (d2_width)D2_FIX4(coordinates.x1), + (d2_width)D2_FIX4(coordinates.y1 + radius), + (d2_width)D2_FIX4(radius), + (d2_width)D2_FIX4(lv_area_get_height(&coordinates) - (2 * radius))); + if(D2_OK != result) { + __BKPT(0); + } + + result = d2_renderbox(u->d2_handle, + (d2_width)D2_FIX4(coordinates.x2 - radius), + (d2_width)D2_FIX4(coordinates.y1 + radius), + (d2_width)D2_FIX4(radius), + (d2_width)D2_FIX4(lv_area_get_height(&coordinates) - (2 * radius))); + if(D2_OK != result) { + __BKPT(0); + } + } + } + + // + // Execute render operations + // +#if D2_RENDER_EACH_OPERATION + d2_executerenderbuffer(u->d2_handle, u->renderbuffer, 0); + d2_flushframe(u->d2_handle); +#endif + + if(LV_GRAD_DIR_NONE != dsc->grad.dir) { + d2_setalphamode(u->d2_handle, current_alpha_mode); + d2_setfillmode(u->d2_handle, d2_fm_color); //default + } + +#if LV_USE_OS + status = lv_mutex_unlock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif +} + +#endif /*LV_USE_DRAW_DAVE2D*/ diff --git a/src/draw/renesas/dave2d/lv_draw_dave2d_image.c b/src/draw/renesas/dave2d/lv_draw_dave2d_image.c new file mode 100644 index 000000000..0640872f7 --- /dev/null +++ b/src/draw/renesas/dave2d/lv_draw_dave2d_image.c @@ -0,0 +1,580 @@ +#include "lv_draw_dave2d.h" +#if LV_USE_DRAW_DAVE2D + +#include "../../sw/lv_draw_sw.h" + +#include "../../../display/lv_display.h" +#include "../../../display/lv_display_private.h" +#include "../../../misc/lv_log.h" +#include "../../../core/lv_refr.h" +#include "../../../stdlib/lv_mem.h" +#include "../../../misc/lv_cache.h" +#include "../../../misc/lv_math.h" +#include "../../../misc/lv_color.h" +#include "../../../stdlib/lv_string.h" +#include "../../../core/lv_global.h" + + + +/********************* + * DEFINES + *********************/ +#define MAX_BUF_SIZE (uint32_t) (4 * lv_display_get_horizontal_resolution(_lv_refr_get_disp_refreshing()) * lv_color_format_get_size(lv_display_get_color_format(_lv_refr_get_disp_refreshing()))) + + +static void dave2d_img_draw_normal(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_area_t * coords); + +static void dave2d_img_draw_tiled(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_area_t * coords); + +static void dave2d_img_decode_and_draw(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + lv_image_decoder_dsc_t * decoder_dsc, + const lv_area_t * img_area, const lv_area_t * clipped_img_area); + +static void dave2d_img_draw_core(lv_draw_dave2d_unit_t * draw_unit, 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 void sw_fallback_img_draw_core(lv_draw_unit_t * draw_unit, 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); + +void lv_draw_dave2d_image(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_area_t * coords) +{ + if(!draw_dsc->tile) { + dave2d_img_draw_normal(draw_unit, draw_dsc, coords); + } + else { + dave2d_img_draw_tiled(draw_unit, draw_dsc, coords); + } +} + +static void dave2d_img_draw_normal(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_area_t * coords) +{ + lv_area_t draw_area; + lv_area_copy(&draw_area, coords); + if(draw_dsc->rotation || draw_dsc->scale_x != LV_SCALE_NONE || draw_dsc->scale_y != LV_SCALE_NONE) { + int32_t w = lv_area_get_width(coords); + int32_t h = lv_area_get_height(coords); + + _lv_image_buf_get_transformed_area(&draw_area, w, h, draw_dsc->rotation, draw_dsc->scale_x, draw_dsc->scale_y, + &draw_dsc->pivot); + + draw_area.x1 += coords->x1; + draw_area.y1 += coords->y1; + draw_area.x2 += coords->x1; + draw_area.y2 += coords->y1; + } + + lv_area_t clipped_img_area; + if(!_lv_area_intersect(&clipped_img_area, &draw_area, draw_unit->base_unit.clip_area)) { + return; + } + + lv_image_decoder_dsc_t decoder_dsc; + lv_result_t res = lv_image_decoder_open(&decoder_dsc, draw_dsc->src, NULL); + if(res != LV_RESULT_OK) { + LV_LOG_ERROR("Failed to open image"); + return; + } + + dave2d_img_decode_and_draw(draw_unit, draw_dsc, &decoder_dsc, coords, &clipped_img_area); + + lv_image_decoder_close(&decoder_dsc); +} + +static void dave2d_img_draw_tiled(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_area_t * coords) +{ + lv_image_decoder_dsc_t decoder_dsc; + lv_result_t res = lv_image_decoder_open(&decoder_dsc, draw_dsc->src, NULL); + if(res != LV_RESULT_OK) { + LV_LOG_ERROR("Failed to open image"); + return; + } + + int32_t img_w = lv_area_get_width(coords); + int32_t img_h = lv_area_get_height(coords); + + lv_area_t tile_area = *coords; + int32_t tile_x_start = tile_area.x1; + + while(tile_area.y1 < draw_unit->base_unit.clip_area->y2) { + while(tile_area.x1 < draw_unit->base_unit.clip_area->x2) { + + lv_area_t clipped_img_area; + if(_lv_area_intersect(&clipped_img_area, &tile_area, draw_unit->base_unit.clip_area)) { + dave2d_img_decode_and_draw(draw_unit, draw_dsc, &decoder_dsc, &tile_area, &clipped_img_area); + } + + tile_area.x1 += img_w; + tile_area.x2 += img_w; + } + + tile_area.y1 += img_h; + tile_area.y2 += img_h; + tile_area.x1 = tile_x_start; + tile_area.x2 = tile_x_start + img_w - 1; + } + + lv_image_decoder_close(&decoder_dsc); +} + +static void dave2d_img_decode_and_draw(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + lv_image_decoder_dsc_t * decoder_dsc, + const lv_area_t * img_area, const lv_area_t * clipped_img_area) +{ + lv_draw_image_sup_t sup; + sup.alpha_color = draw_dsc->recolor; + sup.palette = decoder_dsc->palette; + sup.palette_size = decoder_dsc->palette_size; + + /*The whole image is available, just draw it*/ + if(decoder_dsc->img_data) { + dave2d_img_draw_core(draw_unit, draw_dsc, decoder_dsc, &sup, img_area, clipped_img_area); + } + /*Draw in smaller pieces*/ + else { + lv_area_t relative_full_area_to_decode = *clipped_img_area; + lv_area_move(&relative_full_area_to_decode, -img_area->x1, -img_area->y1); + + lv_area_t relative_decoded_area; + relative_decoded_area.x1 = LV_COORD_MIN; + relative_decoded_area.y1 = LV_COORD_MIN; + relative_decoded_area.x2 = LV_COORD_MIN; + relative_decoded_area.y2 = LV_COORD_MIN; + lv_result_t res = LV_RESULT_OK; + + while(res == LV_RESULT_OK) { + res = lv_image_decoder_get_area(decoder_dsc, &relative_full_area_to_decode, &relative_decoded_area); + + lv_area_t absolute_decoded_area = relative_decoded_area; + lv_area_move(&absolute_decoded_area, img_area->x1, img_area->y1); + if(res == LV_RESULT_OK) { + /*Limit draw area to the current decoded area and draw the image*/ + lv_area_t clipped_img_area_sub; + if(_lv_area_intersect(&clipped_img_area_sub, clipped_img_area, &absolute_decoded_area)) { + dave2d_img_draw_core(draw_unit, draw_dsc, decoder_dsc, &sup, + &absolute_decoded_area, &clipped_img_area_sub); + } + } + } + } +} + +static void dave2d_img_draw_core(lv_draw_dave2d_unit_t * u, 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) +{ + bool transformed = draw_dsc->rotation != 0 || draw_dsc->scale_x != LV_SCALE_NONE || + draw_dsc->scale_y != LV_SCALE_NONE ? true : false; + + const uint8_t * src_buf = decoder_dsc->img_data; + const lv_image_header_t * header = &decoder_dsc->header; + lv_area_t buffer_area; + lv_area_t draw_area; + lv_area_t clipped_area; + int32_t x; + int32_t y; + d2_u8 a_texture_op = d2_to_one; + d2_u8 r_texture_op = d2_to_copy; + d2_u8 g_texture_op = d2_to_copy; + d2_u8 b_texture_op = d2_to_copy; + d2_u8 current_fill_mode; + d2_u32 src_blend_mode; + d2_u32 dst_blend_mode; + + + if(LV_COLOR_FORMAT_RGB565A8 == header->cf) { + /* Colour format not support by Dave2D */ + sw_fallback_img_draw_core(&u->base_unit, draw_dsc, decoder_dsc, sup, img_coords, clipped_img_area); + return; + } + +#if LV_USE_OS + lv_result_t status; + status = lv_mutex_lock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + + buffer_area = u->base_unit.target_layer->buf_area; + draw_area = *img_coords; + clipped_area = *clipped_img_area; + + x = 0 - u->base_unit.target_layer->buf_area.x1; + y = 0 - u->base_unit.target_layer->buf_area.y1; + + lv_area_move(&draw_area, x, y); + lv_area_move(&buffer_area, x, y); + lv_area_move(&clipped_area, x, y); + + // + // Generate render operations + // +#if D2_RENDER_EACH_OPERATION + d2_selectrenderbuffer(u->d2_handle, u->renderbuffer); +#endif + + current_fill_mode = d2_getfillmode(u->d2_handle); + a_texture_op = d2_gettextureoperationa(u->d2_handle); + r_texture_op = d2_gettextureoperationr(u->d2_handle); + g_texture_op = d2_gettextureoperationg(u->d2_handle); + b_texture_op = d2_gettextureoperationb(u->d2_handle); + src_blend_mode = d2_getblendmodesrc(u->d2_handle); + dst_blend_mode = d2_getblendmodedst(u->d2_handle); + + d2_framebuffer(u->d2_handle, + u->base_unit.target_layer->buf, + (d2_s32)u->base_unit.target_layer->buf_stride / lv_color_format_get_size(u->base_unit.target_layer->color_format), + (d2_u32)lv_area_get_width(&buffer_area), + (d2_u32)lv_area_get_height(&buffer_area), + lv_draw_dave2d_cf_fb_get()); + + d2_cliprect(u->d2_handle, (d2_border)clipped_area.x1, (d2_border)clipped_area.y1, (d2_border)clipped_area.x2, + (d2_border)clipped_area.y2); + +#if defined(RENESAS_CORTEX_M85) +#if (BSP_CFG_DCACHE_ENABLED) + d1_cacheblockflush(u->d2_handle, 0, src_buf, + decoder_dsc->header.stride * decoder_dsc->header.h); //Stride is in bytes, not pixels/texels +#endif +#endif + + d2_settexopparam(u->d2_handle, d2_cc_alpha, draw_dsc->opa, 0); + + if(LV_COLOR_FORMAT_RGB565 == header->cf) { + d2_settextureoperation(u->d2_handle, d2_to_replace, d2_to_copy, d2_to_copy, d2_to_copy); + } + else { //Formats with an alpha channel, + d2_settextureoperation(u->d2_handle, d2_to_multiply, d2_to_copy, d2_to_copy, d2_to_copy); + } + + if(LV_BLEND_MODE_NORMAL == draw_dsc->blend_mode) { /**< Simply mix according to the opacity value*/ + d2_setblendmode(u->d2_handle, d2_bm_alpha, d2_bm_one_minus_alpha); //direct linear blend + } + else if(LV_BLEND_MODE_ADDITIVE == draw_dsc->blend_mode) { /**< Add the respective color channels*/ + /* TODO */ + d2_setblendmode(u->d2_handle, d2_bm_alpha, d2_bm_one); //Additive blending + } + else if(LV_BLEND_MODE_SUBTRACTIVE == draw_dsc->blend_mode) { /**< Subtract the foreground from the background*/ + /* TODO */ + __NOP(); + } + else { //LV_BLEND_MODE_MULTIPLY, /**< Multiply the foreground and background*/ + /* TODO */ + __NOP(); + } + + lv_point_t p[4] = { //Points in clockwise order + {0, 0}, + {decoder_dsc->header.w - 1, 0}, + {decoder_dsc->header.w - 1, decoder_dsc->header.h - 1}, + {0, decoder_dsc->header.h - 1}, + }; + + d2_settexture(u->d2_handle, (void *)src_buf, + (d2_s32)(decoder_dsc->header.stride / lv_color_format_get_size(header->cf)), + decoder_dsc->header.w, decoder_dsc->header.h, lv_draw_dave2d_lv_colour_fmt_to_d2_fmt(header->cf)); + + d2_settexturemode(u->d2_handle, d2_tm_filter); + d2_setfillmode(u->d2_handle, d2_fm_texture); + + d2_s32 dxu = D2_FIX16(1); + d2_s32 dxv = D2_FIX16(0); + d2_s32 dyu = D2_FIX16(0); + d2_s32 dyv = D2_FIX16(1); + + if(transformed) { + lv_point_transform(&p[0], draw_dsc->rotation, draw_dsc->scale_x, draw_dsc->scale_y, &draw_dsc->pivot, true); + lv_point_transform(&p[1], draw_dsc->rotation, draw_dsc->scale_x, draw_dsc->scale_y, &draw_dsc->pivot, true); + lv_point_transform(&p[2], draw_dsc->rotation, draw_dsc->scale_x, draw_dsc->scale_y, &draw_dsc->pivot, true); + lv_point_transform(&p[3], draw_dsc->rotation, draw_dsc->scale_x, draw_dsc->scale_y, &draw_dsc->pivot, true); + + int32_t sin_xv = 0; //0 degrees + int32_t cos_xu = (1 << 15); + int32_t sin_yv = (1 << 15); //90 degress + int32_t cos_yu = 0; + + int32_t angle_limited = draw_dsc->rotation; + if(angle_limited > 3600) angle_limited -= 3600; + if(angle_limited < 0) angle_limited += 3600; + + int32_t angle_low = angle_limited / 10; + + if(0 != angle_low) { + sin_xv = lv_trigo_sin((int16_t)angle_low); + cos_xu = lv_trigo_cos((int16_t)angle_low); + sin_yv = lv_trigo_sin((int16_t)angle_low + 90); + cos_yu = lv_trigo_cos((int16_t)angle_low + 90); + } + + /* LV_TRIGO_SHIFT is 15, so only need to shift by 1 to get 16:16 fixed point */ + dxu = (d2_s32)((1 << 1) * + cos_xu); /* TODO - Need to handle scaling of the texture based on draw_dsc->scale_x, draw_dsc->scale_y, currently no scaling it is 1:1 */ + dxv = (d2_s32)((1 << 1) * sin_xv); + dyu = (d2_s32)((1 << 1) * cos_yu); + dyv = (d2_s32)((1 << 1) * sin_yv); + } + + p[0].x += draw_area.x1; + p[0].y += draw_area.y1; + p[1].x += draw_area.x1; + p[1].y += draw_area.y1; + p[2].x += draw_area.x1; + p[2].y += draw_area.y1; + p[3].x += draw_area.x1; + p[3].y += draw_area.y1; + + d2_settexturemapping(u->d2_handle, D2_FIX4(p[0].x), D2_FIX4(p[0].y), D2_FIX16(0), D2_FIX16(0), dxu, dxv, dyu, dyv); + + d2_renderquad(u->d2_handle, + (d2_point)D2_FIX4(p[0].x), + (d2_point)D2_FIX4(p[0].y), + (d2_point)D2_FIX4(p[1].x), + (d2_point)D2_FIX4(p[1].y), + (d2_point)D2_FIX4(p[2].x), + (d2_point)D2_FIX4(p[2].y), + (d2_point)D2_FIX4(p[3].x), + (d2_point)D2_FIX4(p[3].y), + 0); + + // + // Execute render operations + // +#if D2_RENDER_EACH_OPERATION + d2_executerenderbuffer(u->d2_handle, u->renderbuffer, 0); + d2_flushframe(u->d2_handle); +#endif + + d2_setfillmode(u->d2_handle, current_fill_mode); + d2_settextureoperation(u->d2_handle, a_texture_op, r_texture_op, g_texture_op, b_texture_op); + d2_setblendmode(u->d2_handle, src_blend_mode, dst_blend_mode); + +#if LV_USE_OS + status = lv_mutex_unlock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + +} + +static void sw_fallback_img_draw_core(lv_draw_unit_t * draw_unit, 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) +{ + bool transformed = draw_dsc->rotation != 0 || draw_dsc->scale_x != LV_SCALE_NONE || + draw_dsc->scale_y != LV_SCALE_NONE ? true : false; + + lv_draw_sw_blend_dsc_t blend_dsc; + const uint8_t * src_buf = decoder_dsc->img_data; + const lv_image_header_t * header = &decoder_dsc->header; + uint32_t img_stride = header->stride; + lv_color_format_t cf = header->cf; + + cf = LV_COLOR_FORMAT_IS_INDEXED(cf) ? LV_COLOR_FORMAT_ARGB8888 : cf, + + lv_memzero(&blend_dsc, sizeof(lv_draw_sw_blend_dsc_t)); + blend_dsc.opa = draw_dsc->opa; + blend_dsc.blend_mode = draw_dsc->blend_mode; + blend_dsc.src_stride = img_stride; + + if(!transformed && cf == LV_COLOR_FORMAT_A8) { + lv_area_t clipped_coords; + if(!_lv_area_intersect(&clipped_coords, img_coords, draw_unit->clip_area)) return; + + blend_dsc.mask_buf = (lv_opa_t *)src_buf; + blend_dsc.mask_area = img_coords; + blend_dsc.mask_stride = img_stride; + blend_dsc.src_buf = NULL; + blend_dsc.color = draw_dsc->recolor; + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + + blend_dsc.blend_area = img_coords; + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + else if(!transformed && cf == LV_COLOR_FORMAT_RGB565A8 && draw_dsc->recolor_opa <= LV_OPA_MIN) { + int32_t src_h = lv_area_get_height(img_coords); + int32_t src_w = lv_area_get_width(img_coords); + blend_dsc.src_area = img_coords; + blend_dsc.src_buf = src_buf; + blend_dsc.mask_buf = (lv_opa_t *)src_buf; + blend_dsc.mask_buf += img_stride * src_w / header->w * src_h; + /** + * Note, for RGB565A8, lacking of stride parameter, we always use + * always half of RGB map stride as alpha map stride. The image should + * be generated in this way too. + */ + blend_dsc.mask_stride = img_stride / 2; + blend_dsc.blend_area = img_coords; + blend_dsc.mask_area = img_coords; + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + blend_dsc.src_color_format = LV_COLOR_FORMAT_RGB565; + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + /*The simplest case just copy the pixels into the draw_buf. Blending will convert the colors if needed*/ + else if(!transformed && draw_dsc->recolor_opa <= LV_OPA_MIN) { + blend_dsc.src_area = img_coords; + blend_dsc.src_buf = src_buf; + blend_dsc.blend_area = img_coords; + blend_dsc.src_color_format = cf; + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + /*In the other cases every pixel need to be checked one-by-one*/ + else { + lv_area_t blend_area = *clipped_img_area; + blend_dsc.blend_area = &blend_area; + + int32_t src_w = lv_area_get_width(img_coords); + int32_t src_h = lv_area_get_height(img_coords); + int32_t blend_w = lv_area_get_width(&blend_area); + int32_t blend_h = lv_area_get_height(&blend_area); + + lv_color_format_t cf_final = cf; + if(transformed) { + if(cf == LV_COLOR_FORMAT_RGB888 || cf == LV_COLOR_FORMAT_XRGB8888) cf_final = LV_COLOR_FORMAT_ARGB8888; + else if(cf == LV_COLOR_FORMAT_RGB565) cf_final = LV_COLOR_FORMAT_RGB565A8; + } + uint8_t * tmp_buf; + uint32_t px_size = lv_color_format_get_size(cf_final); + int32_t buf_h; + if(cf_final == LV_COLOR_FORMAT_RGB565A8) { + uint32_t buf_stride = blend_w * 3; + buf_h = MAX_BUF_SIZE / buf_stride; + if(buf_h > blend_h) buf_h = blend_h; + tmp_buf = lv_malloc(buf_stride * buf_h); + } + else { + uint32_t buf_stride = blend_w * lv_color_format_get_size(cf_final); + buf_h = MAX_BUF_SIZE / buf_stride; + if(buf_h > blend_h) buf_h = blend_h; + tmp_buf = lv_malloc(buf_stride * buf_h); + } + + blend_dsc.src_buf = tmp_buf; + blend_dsc.src_color_format = cf_final; + int32_t y_last = blend_area.y2; + blend_area.y2 = blend_area.y1 + buf_h - 1; + + blend_dsc.src_area = &blend_area; + if(cf_final == LV_COLOR_FORMAT_RGB565A8) { + /*RGB565A8 images will blended as RGB565 + mask + *Therefore the stride can be different. */ + blend_dsc.src_stride = blend_w * 2; + blend_dsc.mask_buf = tmp_buf + blend_w * 2 * buf_h; + blend_dsc.mask_stride = blend_w; + blend_dsc.mask_area = &blend_area; + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + blend_dsc.src_color_format = LV_COLOR_FORMAT_RGB565; + } + else if(cf_final == LV_COLOR_FORMAT_A8) { + blend_dsc.mask_buf = blend_dsc.src_buf; + blend_dsc.mask_stride = blend_w; + blend_dsc.mask_area = &blend_area; + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + blend_dsc.color = draw_dsc->recolor; + blend_dsc.src_buf = NULL; + } + else { + blend_dsc.src_stride = blend_w * lv_color_format_get_size(cf_final); + } + + while(blend_area.y1 <= y_last) { + /*Apply transformations if any or separate the channels*/ + lv_area_t relative_area; + lv_area_copy(&relative_area, &blend_area); + lv_area_move(&relative_area, -img_coords->x1, -img_coords->y1); + if(transformed) { + lv_draw_sw_transform(draw_unit, &relative_area, src_buf, src_w, src_h, img_stride, + draw_dsc, sup, cf, tmp_buf); + } + else if(draw_dsc->recolor_opa >= LV_OPA_MIN) { + int32_t h = lv_area_get_height(&relative_area); + if(cf_final == LV_COLOR_FORMAT_RGB565A8) { + uint32_t stride_px = img_stride / 2; + const uint8_t * rgb_src_buf = src_buf + stride_px * 2 * relative_area.y1 + relative_area.x1 * 2; + const uint8_t * a_src_buf = src_buf + stride_px * 2 * src_h + stride_px * relative_area.y1 + + relative_area.x1; + uint8_t * rgb_dest_buf = tmp_buf; + uint8_t * a_dest_buf = (uint8_t *)blend_dsc.mask_buf; + int32_t i; + for(i = 0; i < h; i++) { + lv_memcpy(rgb_dest_buf, rgb_src_buf, blend_w * 2); + lv_memcpy(a_dest_buf, a_src_buf, blend_w); + rgb_src_buf += stride_px * 2; + a_src_buf += stride_px; + rgb_dest_buf += blend_w * 2; + a_dest_buf += blend_w; + } + } + else if(cf_final != LV_COLOR_FORMAT_A8) { + const uint8_t * src_buf_tmp = src_buf + img_stride * relative_area.y1 + relative_area.x1 * px_size; + uint8_t * dest_buf_tmp = tmp_buf; + int32_t i; + for(i = 0; i < h; i++) { + lv_memcpy(dest_buf_tmp, src_buf_tmp, blend_w * px_size); + dest_buf_tmp += blend_w * px_size; + src_buf_tmp += img_stride; + } + } + } + + /*Apply recolor*/ + if(draw_dsc->recolor_opa > LV_OPA_MIN) { + lv_color_t color = draw_dsc->recolor; + lv_opa_t mix = draw_dsc->recolor_opa; + lv_opa_t mix_inv = 255 - mix; + if(cf_final == LV_COLOR_FORMAT_RGB565A8 || cf_final == LV_COLOR_FORMAT_RGB565) { + uint16_t c_mult[3]; + c_mult[0] = (color.blue >> 3) * mix; + c_mult[1] = (color.green >> 2) * mix; + c_mult[2] = (color.red >> 3) * mix; + uint16_t * buf16 = (uint16_t *)tmp_buf; + int32_t i; + int32_t size = lv_area_get_size(&blend_area); + for(i = 0; i < size; i++) { + buf16[i] = (((c_mult[2] + ((buf16[i] >> 11) & 0x1F) * mix_inv) << 3) & 0xF800) + + (((c_mult[1] + ((buf16[i] >> 5) & 0x3F) * mix_inv) >> 3) & 0x07E0) + + ((c_mult[0] + (buf16[i] & 0x1F) * mix_inv) >> 8); + } + } + else if(cf_final != LV_COLOR_FORMAT_A8) { + uint32_t size = lv_area_get_size(&blend_area); + uint32_t i; + uint16_t c_mult[3]; + c_mult[0] = color.blue * mix; + c_mult[1] = color.green * mix; + c_mult[2] = color.red * mix; + uint8_t * tmp_buf_2 = tmp_buf; + for(i = 0; i < size * px_size; i += px_size) { + tmp_buf_2[i + 0] = (c_mult[0] + (tmp_buf_2[i + 0] * mix_inv)) >> 8; + tmp_buf_2[i + 1] = (c_mult[1] + (tmp_buf_2[i + 1] * mix_inv)) >> 8; + tmp_buf_2[i + 2] = (c_mult[2] + (tmp_buf_2[i + 2] * mix_inv)) >> 8; + } + } + } + + /*Blend*/ + lv_draw_sw_blend(draw_unit, &blend_dsc); + + /*Go to the next area*/ + blend_area.y1 = blend_area.y2 + 1; + blend_area.y2 = blend_area.y1 + buf_h - 1; + if(blend_area.y2 > y_last) { + blend_area.y2 = y_last; + if(cf_final == LV_COLOR_FORMAT_RGB565A8) { + blend_dsc.mask_buf = tmp_buf + blend_w * 2 * lv_area_get_height(&blend_area); + } + } + } + + lv_free(tmp_buf); + } +} + +#endif //LV_USE_DRAW_DAVE2D diff --git a/src/draw/renesas/dave2d/lv_draw_dave2d_label.c b/src/draw/renesas/dave2d/lv_draw_dave2d_label.c new file mode 100644 index 000000000..d0d52a673 --- /dev/null +++ b/src/draw/renesas/dave2d/lv_draw_dave2d_label.c @@ -0,0 +1,166 @@ +#include "lv_draw_dave2d.h" +#if LV_USE_DRAW_DAVE2D + +static void lv_draw_dave2d_draw_letter_cb(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * glyph_draw_dsc, + lv_draw_fill_dsc_t * fill_draw_dsc, const lv_area_t * fill_area); + + +static lv_draw_dave2d_unit_t * unit = NULL; + +void lv_draw_dave2d_label(lv_draw_dave2d_unit_t * u, const lv_draw_label_dsc_t * dsc, const lv_area_t * coords) +{ + if(dsc->opa <= LV_OPA_MIN) return; + + unit = u; + + lv_draw_label_iterate_letters(&u->base_unit, dsc, coords, lv_draw_dave2d_draw_letter_cb); + +} + +static void lv_draw_dave2d_draw_letter_cb(lv_draw_unit_t * u, lv_draw_glyph_dsc_t * glyph_draw_dsc, + lv_draw_fill_dsc_t * fill_draw_dsc, const lv_area_t * fill_area) +{ + + d2_u8 current_fillmode; + lv_area_t clip_area; + lv_area_t buffer_area; + lv_area_t letter_coords; + + int32_t x; + int32_t y; + + buffer_area = unit->base_unit.target_layer->buf_area; + letter_coords = *glyph_draw_dsc->letter_coords; + + bool is_common; + is_common = _lv_area_intersect(&clip_area, glyph_draw_dsc->letter_coords, u->clip_area); + if(!is_common) return; + + x = 0 - unit->base_unit.target_layer->buf_area.x1; + y = 0 - unit->base_unit.target_layer->buf_area.y1; + + lv_area_move(&clip_area, x, y); + lv_area_move(&buffer_area, x, y); + lv_area_move(&letter_coords, x, y); + +#if LV_USE_OS + lv_result_t status; + status = lv_mutex_lock(unit->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + +#if D2_RENDER_EACH_OPERATION + d2_selectrenderbuffer(unit->d2_handle, unit->renderbuffer); +#endif + + // + // Generate render operations + // + d2_framebuffer(unit->d2_handle, + unit->base_unit.target_layer->buf, + (d2_s32)unit->base_unit.target_layer->buf_stride / lv_color_format_get_size(unit->base_unit.target_layer->color_format), + (d2_u32)lv_area_get_width(&buffer_area), + (d2_u32)lv_area_get_height(&buffer_area), + lv_draw_dave2d_cf_fb_get()); + + current_fillmode = d2_getfillmode(unit->d2_handle); + + + d2_cliprect(unit->d2_handle, (d2_border)clip_area.x1, (d2_border)clip_area.y1, (d2_border)clip_area.x2, + (d2_border)clip_area.y2); + + if(glyph_draw_dsc) { + if(glyph_draw_dsc->bitmap == NULL) { +#if LV_USE_FONT_PLACEHOLDER + /* Draw a placeholder rectangle*/ + lv_draw_border_dsc_t border_draw_dsc; + lv_draw_border_dsc_init(&border_draw_dsc); + border_draw_dsc.opa = glyph_draw_dsc->opa; + border_draw_dsc.color = glyph_draw_dsc->color; + border_draw_dsc.width = 1; + //lv_draw_sw_border(u, &border_draw_dsc, glyph_draw_dsc->bg_coords); + lv_draw_dave2d_border(unit, &border_draw_dsc, glyph_draw_dsc->bg_coords); +#endif + } + else if(glyph_draw_dsc->format == LV_DRAW_LETTER_BITMAP_FORMAT_A8) { + lv_area_t mask_area = letter_coords; + mask_area.x2 = mask_area.x1 + lv_draw_buf_width_to_stride(lv_area_get_width(&mask_area), LV_COLOR_FORMAT_A8) - 1; + // lv_draw_sw_blend_dsc_t blend_dsc; + // lv_memzero(&blend_dsc, sizeof(blend_dsc)); + // blend_dsc.color = glyph_draw_dsc->color; + // blend_dsc.opa = glyph_draw_dsc->opa; + // blend_dsc.mask_buf = glyph_draw_dsc->bitmap; + // blend_dsc.mask_area = &mask_area; + // blend_dsc.blend_area = glyph_draw_dsc->letter_coords; + // blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + //lv_draw_sw_blend(u, &blend_dsc); + +#if defined(RENESAS_CORTEX_M85) +#if (BSP_CFG_DCACHE_ENABLED) + d1_cacheblockflush(unit->d2_handle, 0, glyph_draw_dsc->bitmap, glyph_draw_dsc->_bitmap_buf_size); +#endif +#endif + d2_settexture(unit->d2_handle, (void *)glyph_draw_dsc->bitmap, + (d2_s32)lv_draw_buf_width_to_stride((uint32_t)lv_area_get_width(&letter_coords), LV_COLOR_FORMAT_A8), + lv_area_get_width(&letter_coords), lv_area_get_height(&letter_coords), d2_mode_alpha8); + d2_settexopparam(unit->d2_handle, d2_cc_red, glyph_draw_dsc->color.red, 0); + d2_settexopparam(unit->d2_handle, d2_cc_green, glyph_draw_dsc->color.green, 0); + d2_settexopparam(unit->d2_handle, d2_cc_blue, glyph_draw_dsc->color.blue, 0); + d2_settexopparam(unit->d2_handle, d2_cc_alpha, glyph_draw_dsc->opa, 0); + + d2_settextureoperation(unit->d2_handle, d2_to_multiply, d2_to_multiply, d2_to_multiply, d2_to_multiply); + + d2_settexturemapping(unit->d2_handle, D2_FIX4(letter_coords.x1), D2_FIX4(letter_coords.y1), D2_FIX16(0), D2_FIX16(0), + D2_FIX16(1), D2_FIX16(0), D2_FIX16(0), D2_FIX16(1)); + + d2_settexturemode(unit->d2_handle, d2_tm_filter); + + d2_setfillmode(unit->d2_handle, d2_fm_texture); + + d2_renderbox(unit->d2_handle, (d2_point)D2_FIX4(letter_coords.x1), + (d2_point)D2_FIX4(letter_coords.y1), + (d2_point)D2_FIX4(lv_area_get_width(&letter_coords)), + (d2_point)D2_FIX4(lv_area_get_height(&letter_coords))); + + + d2_setfillmode(unit->d2_handle, current_fillmode); + } + else if(glyph_draw_dsc->format == LV_DRAW_LETTER_BITMAP_FORMAT_IMAGE) { +#if LV_USE_IMGFONT + lv_draw_image_dsc_t img_dsc; + lv_draw_image_dsc_init(&img_dsc); + img_dsc.rotation = 0; + img_dsc.scale_x = LV_SCALE_NONE; + img_dsc.scale_y = LV_SCALE_NONE; + img_dsc.opa = glyph_draw_dsc->opa; + img_dsc.src = glyph_draw_dsc->bitmap; + //lv_draw_sw_image(draw_unit, &img_dsc, glyph_draw_dsc->letter_coords); +#endif + } + } + + // + // Execute render operations + // +#if D2_RENDER_EACH_OPERATION + d2_executerenderbuffer(unit->d2_handle, unit->renderbuffer, 0); + d2_flushframe(unit->d2_handle); +#endif + + if(fill_draw_dsc && fill_area) { + //lv_draw_sw_fill(u, fill_draw_dsc, fill_area); + lv_draw_dave2d_fill(unit, fill_draw_dsc, fill_area); + } + + +#if LV_USE_OS + status = lv_mutex_unlock(unit->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif +} + +#endif /*LV_USE_DRAW_DAVE2D*/ diff --git a/src/draw/renesas/dave2d/lv_draw_dave2d_line.c b/src/draw/renesas/dave2d/lv_draw_dave2d_line.c new file mode 100644 index 000000000..e9fecdbe1 --- /dev/null +++ b/src/draw/renesas/dave2d/lv_draw_dave2d_line.c @@ -0,0 +1,107 @@ +#include "lv_draw_dave2d.h" +#if LV_USE_DRAW_DAVE2D + + +void lv_draw_dave2d_line(lv_draw_dave2d_unit_t * u, const lv_draw_line_dsc_t * dsc) +{ + + lv_area_t clip_line; + d2_u32 mode; + d2_s32 result; + lv_area_t buffer_area; + uint32_t res; + lv_value_precise_t p1_x; + lv_value_precise_t p1_y; + lv_value_precise_t p2_x; + lv_value_precise_t p2_y; + int32_t x; + int32_t y; + + + clip_line.x1 = LV_MIN(dsc->p1.x, dsc->p2.x) - dsc->width / 2; + clip_line.x2 = LV_MAX(dsc->p1.x, dsc->p2.x) + dsc->width / 2; + clip_line.y1 = LV_MIN(dsc->p1.y, dsc->p2.y) - dsc->width / 2; + clip_line.y2 = LV_MAX(dsc->p1.y, dsc->p2.y) + dsc->width / 2; + + bool is_common; + is_common = _lv_area_intersect(&clip_line, &clip_line, u->base_unit.clip_area); + if(!is_common) return; + +#if LV_USE_OS + lv_result_t status; + status = lv_mutex_lock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + + buffer_area = u->base_unit.target_layer->buf_area; + p1_x = dsc->p1.x - buffer_area.x1; + p1_y = dsc->p1.y - buffer_area.y1; + p2_x = dsc->p2.x - buffer_area.x1; + p2_y = dsc->p2.y - buffer_area.y1; + + x = 0 - u->base_unit.target_layer->buf_area.x1; + y = 0 - u->base_unit.target_layer->buf_area.y1; + + lv_area_move(&clip_line, x, y); + lv_area_move(&buffer_area, x, y); + + bool dashed = dsc->dash_gap && dsc->dash_width; + + if(dashed) { + /* TODO */ + __BKPT(0); + } + +#if D2_RENDER_EACH_OPERATION + d2_selectrenderbuffer(u->d2_handle, u->renderbuffer); +#endif + // + // Generate render operations + // + d2_framebuffer(u->d2_handle, + u->base_unit.target_layer->buf, + (d2_s32)u->base_unit.target_layer->buf_stride / lv_color_format_get_size(u->base_unit.target_layer->color_format), + (d2_u32)lv_area_get_width(&buffer_area), + (d2_u32)lv_area_get_height(&buffer_area), + lv_draw_dave2d_cf_fb_get()); + + d2_setcolor(u->d2_handle, 0, lv_draw_dave2d_lv_colour_to_d2_colour(dsc->color)); + + + d2_setalpha(u->d2_handle, dsc->opa); + + + d2_cliprect(u->d2_handle, clip_line.x1, clip_line.y1, clip_line.x2, clip_line.y2); + + if((dsc->round_end == 1) || (dsc->round_start == 1)) { + mode = d2_lc_round; + } + else { + mode = d2_lc_butt; // lines end directly at endpoints + } + + d2_setlinecap(u->d2_handle, mode); + + + d2_renderline(u->d2_handle, D2_FIX4(p1_x), D2_FIX4(p1_y), D2_FIX4(p2_x), + D2_FIX4(p2_y), D2_FIX4(dsc->width), d2_le_exclude_none); + + // + // Execute render operations + // +#if D2_RENDER_EACH_OPERATION + d2_executerenderbuffer(u->d2_handle, u->renderbuffer, 0); + d2_flushframe(u->d2_handle); +#endif + +#if LV_USE_OS + status = lv_mutex_unlock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif +} + +#endif /*LV_USE_DRAW_DAVE2D*/ diff --git a/src/draw/renesas/dave2d/lv_draw_dave2d_mask_rectangle.c b/src/draw/renesas/dave2d/lv_draw_dave2d_mask_rectangle.c new file mode 100644 index 000000000..63ba50d3a --- /dev/null +++ b/src/draw/renesas/dave2d/lv_draw_dave2d_mask_rectangle.c @@ -0,0 +1,69 @@ +#include "lv_draw_dave2d.h" +#if LV_USE_DRAW_DAVE2D + +void lv_draw_dave2d_mask_rect(lv_draw_dave2d_unit_t * u, const lv_draw_mask_rect_dsc_t * dsc, const lv_area_t * coords) +{ + lv_area_t clipped_area; + lv_area_t buffer_area; + lv_area_t coordinates; + int32_t x; + int32_t y; + + if(!_lv_area_intersect(&clipped_area, coords, u->base_unit.clip_area)) return; + + x = 0 - u->base_unit.target_layer->buf_area.x1; + y = 0 - u->base_unit.target_layer->buf_area.y1; + + buffer_area = u->base_unit.target_layer->buf_area; + coordinates = *coords; + + lv_area_move(&clipped_area, x, y); + lv_area_move(&buffer_area, x, y); + lv_area_move(&coordinates, x, y); + + +#if LV_USE_OS + lv_result_t status; + status = lv_mutex_lock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + +#ifdef D2_RENDER_EACH_OPERATION + d2_selectrenderbuffer(u->d2_handle, u->renderbuffer); +#endif + + d2_framebuffer(u->d2_handle, + u->base_unit.target_layer->buf, + lv_area_get_width(&u->base_unit.target_layer->buf_area), + (d2_u32)lv_area_get_width(&u->base_unit.target_layer->buf_area), + (d2_u32)lv_area_get_height(&u->base_unit.target_layer->buf_area), + lv_draw_dave2d_cf_fb_get()); + + + d2_cliprect(u->d2_handle, (d2_border)clipped_area.x1, (d2_border)clipped_area.y1, (d2_border)clipped_area.x2, + (d2_border)clipped_area.y2); + + d2_renderbox(u->d2_handle, + (d2_point) D2_FIX4(coordinates.x1), + (d2_point) D2_FIX4(coordinates.y1), + (d2_width) D2_FIX4(lv_area_get_width(&coordinates)), + (d2_width) D2_FIX4(lv_area_get_height(&coordinates))); + + // + // Execute render operations + // +#ifdef D2_RENDER_EACH_OPERATION + d2_executerenderbuffer(u->d2_handle, u->renderbuffer, 0); + d2_flushframe(u->d2_handle); +#endif + +#if LV_USE_OS + status = lv_mutex_unlock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif +} +#endif //LV_USE_DRAW_DAVE2D diff --git a/src/draw/renesas/dave2d/lv_draw_dave2d_triangle.c b/src/draw/renesas/dave2d/lv_draw_dave2d_triangle.c new file mode 100644 index 000000000..c9fa9bf70 --- /dev/null +++ b/src/draw/renesas/dave2d/lv_draw_dave2d_triangle.c @@ -0,0 +1,192 @@ +#include "lv_draw_dave2d.h" +#if LV_USE_DRAW_DAVE2D + + +void lv_draw_dave2d_triangle(lv_draw_dave2d_unit_t * u, const lv_draw_triangle_dsc_t * dsc) +{ + lv_area_t clipped_area; + d2_u32 flags = 0; + d2_u8 current_alpha_mode = 0; + lv_area_t buffer_area; + int32_t x; + int32_t y; + + lv_area_t tri_area; + tri_area.x1 = LV_MIN3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x); + tri_area.y1 = LV_MIN3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y); + tri_area.x2 = LV_MAX3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x); + tri_area.y2 = LV_MAX3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y); + + + if(!_lv_area_intersect(&clipped_area, &tri_area, u->base_unit.clip_area)) return; + +#if LV_USE_OS + lv_result_t status; + status = lv_mutex_lock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + + x = 0 - u->base_unit.target_layer->buf_area.x1; + y = 0 - u->base_unit.target_layer->buf_area.y1; + + buffer_area = u->base_unit.target_layer->buf_area; + + lv_area_move(&clipped_area, x, y); + lv_area_move(&buffer_area, x, y); + +#if D2_RENDER_EACH_OPERATION + d2_selectrenderbuffer(u->d2_handle, u->renderbuffer); +#endif + + lv_point_precise_t p[3]; + p[0] = dsc->p[0]; + p[1] = dsc->p[1]; + p[2] = dsc->p[2]; + + /*Order the points like this: + * [0]: top + * [1]: right bottom + * [2]: left bottom */ + + + if(dsc->p[0].y <= dsc->p[1].y && dsc->p[0].y <= dsc->p[2].y) { + p[0] = dsc->p[0]; + if(dsc->p[1].x < dsc->p[2].x) { + p[2] = dsc->p[1]; + p[1] = dsc->p[2]; + } + else { + p[2] = dsc->p[2]; + p[1] = dsc->p[1]; + } + } + else if(dsc->p[1].y <= dsc->p[0].y && dsc->p[1].y <= dsc->p[2].y) { + p[0] = dsc->p[1]; + if(dsc->p[0].x < dsc->p[2].x) { + p[2] = dsc->p[0]; + p[1] = dsc->p[2]; + } + else { + p[2] = dsc->p[2]; + p[1] = dsc->p[0]; + } + } + else { + p[0] = dsc->p[2]; + if(dsc->p[0].x < dsc->p[1].x) { + p[2] = dsc->p[0]; + p[1] = dsc->p[1]; + } + else { + p[2] = dsc->p[1]; + p[1] = dsc->p[0]; + } + } + + p[0].x -= u->base_unit.target_layer->buf_area.x1; + p[1].x -= u->base_unit.target_layer->buf_area.x1; + p[2].x -= u->base_unit.target_layer->buf_area.x1; + + p[0].y -= u->base_unit.target_layer->buf_area.y1; + p[1].y -= u->base_unit.target_layer->buf_area.y1; + p[2].y -= u->base_unit.target_layer->buf_area.y1; + + current_alpha_mode = d2_getalphamode(u->d2_handle); + + if(LV_GRAD_DIR_NONE != dsc->bg_grad.dir) { + float a1; + float a2; + + float y1; + float y2; + + float y3; + float y0; + int32_t y0_i ; + int32_t y3_i ; + + if(LV_GRAD_DIR_VER == dsc->bg_grad.dir) { + a1 = dsc->bg_grad.stops[0].opa; + a2 = dsc->bg_grad.stops[dsc->bg_grad.stops_count - 1].opa; + + y1 = LV_MIN3(p[0].y, p[1].y, p[2].y); + y2 = LV_MAX3(p[0].y, p[1].y, p[2].y); + + if(a1 < a2) { + /* TODO */ + __BKPT(0); + y0 = 0.0f;//silence the compiler warning + y3 = 0.0f; + + } + else { + y0 = y2 - ((y2 - y1) / (a2 - a1) * (a2)); //point where alpha is 0 + y3 = y1 + ((y2 - y1) / (a2 - a1) * (255 - a1)); //point where alpha is 255 + } + + y0_i = (int16_t)y0; + y3_i = (int16_t)y3; + + d2_setalphagradient(u->d2_handle, 0, D2_FIX4(0), D2_FIX4(y0_i), D2_FIX4(0), D2_FIX4((y3_i - y0_i))); + } + else if(LV_GRAD_DIR_HOR == dsc->bg_grad.dir) { + /* TODO */ + __BKPT(0); + } + + d2_setcolor(u->d2_handle, 0, lv_draw_dave2d_lv_colour_to_d2_colour(dsc->bg_grad.stops[0].color)); + d2_setalphamode(u->d2_handle, d2_am_gradient1); + } + else { + d2_setalpha(u->d2_handle, dsc->bg_opa); + d2_setalphamode(u->d2_handle, d2_am_constant); + d2_setcolor(u->d2_handle, 0, lv_draw_dave2d_lv_colour_to_d2_colour(dsc->bg_color)); + + } + + d2_framebuffer(u->d2_handle, + u->base_unit.target_layer->buf, + (d2_s32)u->base_unit.target_layer->buf_stride / lv_color_format_get_size(u->base_unit.target_layer->color_format), + (d2_u32)lv_area_get_width(&buffer_area), + (d2_u32)lv_area_get_height(&buffer_area), + lv_draw_dave2d_cf_fb_get()); + + + d2_cliprect(u->d2_handle, (d2_border)clipped_area.x1, (d2_border)clipped_area.y1, (d2_border)clipped_area.x2, + (d2_border)clipped_area.y2); + + d2_rendertri(u->d2_handle, + (d2_point) D2_FIX4(p[0].x), + (d2_point) D2_FIX4(p[0].y), + (d2_point) D2_FIX4(p[1].x), + (d2_point) D2_FIX4(p[1].y), + (d2_point) D2_FIX4(p[2].x), + (d2_point) D2_FIX4(p[2].y), + flags); + + // + // Execute render operations + // +#if D2_RENDER_EACH_OPERATION + d2_executerenderbuffer(u->d2_handle, u->renderbuffer, 0); + d2_flushframe(u->d2_handle); +#endif + + d2_setalphamode(u->d2_handle, current_alpha_mode); + + +#if LV_USE_OS + status = lv_mutex_unlock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } + + +#endif + +} + + +#endif /*LV_USE_DRAW_DAVE2D*/ diff --git a/src/draw/renesas/dave2d/lv_draw_dave2d_uitls.c b/src/draw/renesas/dave2d/lv_draw_dave2d_uitls.c new file mode 100644 index 000000000..0586ccaf8 --- /dev/null +++ b/src/draw/renesas/dave2d/lv_draw_dave2d_uitls.c @@ -0,0 +1,121 @@ +/** + * @file lv_draw_dave2d_utils.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_dave2d.h" + +#if LV_USE_DRAW_DAVE2D + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +d2_color lv_draw_dave2d_lv_colour_to_d2_colour(lv_color_t color) +{ + uint8_t alpha, red, green, blue; + + alpha = 0x00; + red = color.red ; + green = color.green ; + blue = color.blue; + /*Color depth: 8 (A8), 16 (RGB565), 24 (RGB888), 32 (XRGB8888)*/ + switch(LV_COLOR_DEPTH) { + case(8): + __BKPT(0); + break; + case(16): + break; + case(24): + break; + case(32): + break; + + default: + break; + } + + return (alpha) << 24UL + | (red) << 16UL + | (green) << 8UL + | (blue) << 0UL; +} + +d2_s32 lv_draw_dave2d_cf_fb_get(void) +{ + d2_s32 d2_fb_mode = 0; + switch(g_display0_cfg.input->format) { + case DISPLAY_IN_FORMAT_16BITS_RGB565: ///< RGB565, 16 bits + d2_fb_mode = d2_mode_rgb565; + break; + case DISPLAY_IN_FORMAT_32BITS_ARGB8888: ///< ARGB8888, 32 bits + case DISPLAY_IN_FORMAT_32BITS_RGB888: ///< RGB888, 32 bits + case DISPLAY_IN_FORMAT_16BITS_ARGB1555: ///< ARGB1555, 16 bits + case DISPLAY_IN_FORMAT_16BITS_ARGB4444: ///< ARGB4444, 16 bits + case DISPLAY_IN_FORMAT_CLUT8 : ///< CLUT8 + case DISPLAY_IN_FORMAT_CLUT4 : ///< CLUT4 + case DISPLAY_IN_FORMAT_CLUT1 : ///< CLUT1 + break; + + default: + break; + } + + return d2_fb_mode; +} + +d2_u32 lv_draw_dave2d_lv_colour_fmt_to_d2_fmt(lv_color_format_t colour_format) +{ + d2_u32 d2_lvgl_mode = 0; + + switch(colour_format) { + case(8): + d2_lvgl_mode = d2_mode_alpha8; //? + break; + case(LV_COLOR_FORMAT_RGB565): + d2_lvgl_mode = d2_mode_rgb565; + break; + case(LV_COLOR_FORMAT_RGB888): + d2_lvgl_mode = d2_mode_argb8888; //? + break; + case(LV_COLOR_FORMAT_ARGB8888): + d2_lvgl_mode = d2_mode_argb8888; + break; + + default: + __BKPT(0); + break; + + } + return d2_lvgl_mode; +} + + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_DRAW_DAVE2D*/ diff --git a/src/draw/renesas/dave2d/lv_draw_dave2d_utils.h b/src/draw/renesas/dave2d/lv_draw_dave2d_utils.h new file mode 100644 index 000000000..6d122f522 --- /dev/null +++ b/src/draw/renesas/dave2d/lv_draw_dave2d_utils.h @@ -0,0 +1,43 @@ +/** + * @file lv_draw_dave2d_utils.h + * + */ + +#ifndef LV_DRAW_DAVE2D_UTILS_H +#define LV_DRAW_DAVE2D_UTILS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +d2_color lv_draw_dave2d_lv_colour_to_d2_colour(lv_color_t color); + +d2_s32 lv_draw_dave2d_cf_fb_get(void); + +d2_u32 lv_draw_dave2d_lv_colour_fmt_to_d2_fmt(lv_color_format_t colour_format); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_DAVE2D_UTILS_H*/ diff --git a/src/lv_conf_internal.h b/src/lv_conf_internal.h index 98d5f28aa..5a16278cb 100644 --- a/src/lv_conf_internal.h +++ b/src/lv_conf_internal.h @@ -332,6 +332,15 @@ #endif #endif +/* Use Renesas Dave2D on RA platforms. */ +#ifndef LV_USE_DRAW_DAVE2D + #ifdef CONFIG_LV_USE_DRAW_DAVE2D + #define LV_USE_DRAW_DAVE2D CONFIG_LV_USE_DRAW_DAVE2D + #else + #define LV_USE_DRAW_DAVE2D 0 + #endif +#endif + /* Draw using cached SDL textures*/ #ifndef LV_USE_DRAW_SDL #ifdef CONFIG_LV_USE_DRAW_SDL diff --git a/src/lv_init.c b/src/lv_init.c index 609619847..61b88271b 100644 --- a/src/lv_init.c +++ b/src/lv_init.c @@ -32,6 +32,9 @@ #if LV_USE_DRAW_PXP #include "draw/nxp/pxp/lv_draw_pxp.h" #endif +#if LV_USE_DRAW_DAVE2D + #include "draw/renesas/dave2d/lv_draw_dave2d.h" +#endif #if LV_USE_DRAW_SDL #include "draw/sdl/lv_draw_sdl.h" #endif @@ -169,10 +172,15 @@ void lv_init(void) lv_draw_pxp_init(); #endif +#if LV_USE_DRAW_DAVE2D + lv_draw_dave2d_init(); +#endif + #if LV_USE_DRAW_SDL lv_draw_sdl_init(); #endif + _lv_obj_style_init(); /*Initialize the screen refresh system*/