add(gpu): add renesas-ra6m3 gpu adaptation (#4270)

This commit is contained in:
Rbb666
2023-06-08 16:42:34 +08:00
committed by GitHub
parent 75e6ef4e1d
commit 78cbdfc151
9 changed files with 1150 additions and 2 deletions

10
Kconfig
View File

@@ -228,6 +228,16 @@ menu "LVGL configuration"
Must be defined to include path of CMSIS header of target processor Must be defined to include path of CMSIS header of target processor
e.g. "stm32f769xx.h" or "stm32f429xx.h" e.g. "stm32f769xx.h" or "stm32f429xx.h"
config LV_USE_GPU_RA6M3_G2D
bool "Enable RA6M3 G2D GPU."
config LV_GPU_RA6M3_G2D_INCLUDE
string "include path of target processor"
depends on LV_USE_GPU_RA6M3_G2D
default "hal_data.h"
help
Must be defined to include path of target processor
e.g. "hal_data.h"
config LV_USE_GPU_SWM341_DMA2D config LV_USE_GPU_SWM341_DMA2D
bool "Enable SWM341 DMA2D GPU." bool "Enable SWM341 DMA2D GPU."
config LV_GPU_SWM341_DMA2D_INCLUDE config LV_GPU_SWM341_DMA2D_INCLUDE

View File

@@ -187,6 +187,14 @@
#define LV_GPU_DMA2D_CMSIS_INCLUDE #define LV_GPU_DMA2D_CMSIS_INCLUDE
#endif #endif
/*Enable RA6M3 G2D GPU*/
#define LV_USE_GPU_RA6M3_G2D 0
#if LV_USE_GPU_RA6M3_G2D
/*include path of target processor
e.g. "hal_data.h"*/
#define LV_GPU_RA6M3_G2D_INCLUDE "hal_data.h"
#endif
/*Use SWM341's DMA2D GPU*/ /*Use SWM341's DMA2D GPU*/
#define LV_USE_GPU_SWM341_DMA2D 0 #define LV_USE_GPU_SWM341_DMA2D 0
#if LV_USE_GPU_SWM341_DMA2D #if LV_USE_GPU_SWM341_DMA2D

View File

@@ -30,6 +30,10 @@
#include "../draw/stm32_dma2d/lv_gpu_stm32_dma2d.h" #include "../draw/stm32_dma2d/lv_gpu_stm32_dma2d.h"
#endif #endif
#if LV_USE_GPU_RA6M3_G2D
#include "../draw/renesas/lv_gpu_d2_ra6m3.h"
#endif
#if LV_USE_GPU_SWM341_DMA2D #if LV_USE_GPU_SWM341_DMA2D
#include "../draw/swm341_dma2d/lv_gpu_swm341_dma2d.h" #include "../draw/swm341_dma2d/lv_gpu_swm341_dma2d.h"
#endif #endif
@@ -119,6 +123,11 @@ void lv_init(void)
lv_draw_stm32_dma2d_init(); lv_draw_stm32_dma2d_init();
#endif #endif
#if LV_USE_GPU_RA6M3_G2D
/*Initialize G2D GPU*/
lv_draw_ra6m3_g2d_init();
#endif
#if LV_USE_GPU_SWM341_DMA2D #if LV_USE_GPU_SWM341_DMA2D
/*Initialize DMA2D GPU*/ /*Initialize DMA2D GPU*/
lv_draw_swm341_dma2d_init(); lv_draw_swm341_dma2d_init();

View File

@@ -0,0 +1,7 @@
CSRCS += lv_gpu_d2_ra6m3.c
CSRCS += lv_gpu_d2_draw_label.c
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/renesas
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/renesas
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/renesas"

View File

@@ -0,0 +1,292 @@
/**
* @file lv_gpu_d2_draw_label.c
*
* @description HAL layer for display driver
*
*/
/*********************
* INCLUDES
*********************/
#include "../../draw/lv_draw_label.h"
#include "../../misc/lv_assert.h"
#include "../../core/lv_refr.h"
#include "lv_gpu_d2_ra6m3.h"
#if LV_USE_GPU_RA6M3_G2D
#include LV_GPU_RA6M3_G2D_INCLUDE
/**********************
* STATIC VARIABLES
**********************/
/**********************
* GLOBAL VARIABLES
**********************/
extern const uint8_t _lv_bpp1_opa_table[2];
extern const uint8_t _lv_bpp2_opa_table[4];
extern const uint8_t _lv_bpp4_opa_table[16];
extern const uint8_t _lv_bpp8_opa_table[256];
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**********************
* STATIC FUNCTIONS
**********************/
LV_ATTRIBUTE_FAST_MEM static void draw_letter_normal(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc,
const lv_point_t * pos, lv_font_glyph_dsc_t * g, const uint8_t * map_p)
{
const uint8_t * bpp_opa_table_p;
uint32_t bitmask_init;
uint32_t bitmask;
uint32_t bpp = g->bpp;
lv_opa_t opa = dsc->opa;
uint32_t shades;
if(bpp == 3) bpp = 4;
#if LV_USE_IMGFONT
if(bpp == LV_IMGFONT_BPP) { //is imgfont
lv_area_t fill_area;
fill_area.x1 = pos->x;
fill_area.y1 = pos->y;
fill_area.x2 = pos->x + g->box_w - 1;
fill_area.y2 = pos->y + g->box_h - 1;
lv_draw_img_dsc_t img_dsc;
lv_draw_img_dsc_init(&img_dsc);
img_dsc.angle = 0;
img_dsc.zoom = LV_IMG_ZOOM_NONE;
img_dsc.opa = dsc->opa;
img_dsc.blend_mode = dsc->blend_mode;
lv_draw_img(draw_ctx, &img_dsc, &fill_area, map_p);
return;
}
#endif
switch(bpp) {
case 1:
bpp_opa_table_p = _lv_bpp1_opa_table;
bitmask_init = 0x80;
shades = 2;
break;
case 2:
bpp_opa_table_p = _lv_bpp2_opa_table;
bitmask_init = 0xC0;
shades = 4;
break;
case 4:
bpp_opa_table_p = _lv_bpp4_opa_table;
bitmask_init = 0xF0;
shades = 16;
break;
case 8:
bpp_opa_table_p = _lv_bpp8_opa_table;
bitmask_init = 0xFF;
shades = 256;
break; /*No opa table, pixel value will be used directly*/
default:
LV_LOG_WARN("lv_draw_letter: invalid bpp");
return; /*Invalid bpp. Can't render the letter*/
}
static lv_opa_t opa_table[256];
static lv_opa_t prev_opa = LV_OPA_TRANSP;
static uint32_t prev_bpp = 0;
if(opa < LV_OPA_MAX) {
if(prev_opa != opa || prev_bpp != bpp) {
uint32_t i;
for(i = 0; i < shades; i++) {
opa_table[i] = bpp_opa_table_p[i] == LV_OPA_COVER ? opa : ((bpp_opa_table_p[i] * opa) >> 8);
}
}
bpp_opa_table_p = opa_table;
prev_opa = opa;
prev_bpp = bpp;
}
int32_t col, row;
int32_t box_w = g->box_w;
int32_t box_h = g->box_h;
int32_t width_bit = box_w * bpp; /*Letter width in bits*/
/*Calculate the col/row start/end on the map*/
int32_t col_start = pos->x >= draw_ctx->clip_area->x1 ? 0 : draw_ctx->clip_area->x1 - pos->x;
int32_t col_end = pos->x + box_w <= draw_ctx->clip_area->x2 ? box_w : draw_ctx->clip_area->x2 - pos->x + 1;
int32_t row_start = pos->y >= draw_ctx->clip_area->y1 ? 0 : draw_ctx->clip_area->y1 - pos->y;
int32_t row_end = pos->y + box_h <= draw_ctx->clip_area->y2 ? box_h : draw_ctx->clip_area->y2 - pos->y + 1;
/*Move on the map too*/
uint32_t bit_ofs = (row_start * width_bit) + (col_start * bpp);
map_p += bit_ofs >> 3;
uint8_t letter_px;
uint32_t col_bit;
col_bit = bit_ofs & 0x7; /*"& 0x7" equals to "% 8" just faster*/
lv_draw_sw_blend_dsc_t blend_dsc;
lv_memset_00(&blend_dsc, sizeof(blend_dsc));
blend_dsc.color = dsc->color;
blend_dsc.opa = LV_OPA_COVER;
blend_dsc.blend_mode = dsc->blend_mode;
lv_coord_t hor_res = lv_disp_get_hor_res(_lv_refr_get_disp_refreshing());
uint32_t mask_buf_size = box_w * box_h > hor_res ? hor_res : box_w * box_h;
lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size);
blend_dsc.mask_buf = mask_buf;
int32_t mask_p = 0;
lv_area_t fill_area;
fill_area.x1 = col_start + pos->x;
fill_area.x2 = col_end + pos->x - 1;
fill_area.y1 = row_start + pos->y;
fill_area.y2 = fill_area.y1;
#if LV_DRAW_COMPLEX
lv_coord_t fill_w = lv_area_get_width(&fill_area);
lv_area_t mask_area;
lv_area_copy(&mask_area, &fill_area);
mask_area.y2 = mask_area.y1 + row_end;
bool mask_any = lv_draw_mask_is_any(&mask_area);
#endif
blend_dsc.blend_area = &fill_area;
blend_dsc.mask_area = &fill_area;
uint32_t col_bit_max = 8 - bpp;
uint32_t col_bit_row_ofs = (box_w + col_start - col_end) * bpp;
for(row = row_start ; row < row_end; row++) {
#if LV_DRAW_COMPLEX
int32_t mask_p_start = mask_p;
#endif
bitmask = bitmask_init >> col_bit;
for(col = col_start; col < col_end; col++) {
/*Load the pixel's opacity into the mask*/
letter_px = (*map_p & bitmask) >> (col_bit_max - col_bit);
if(letter_px) {
mask_buf[mask_p] = bpp_opa_table_p[letter_px];
}
else {
mask_buf[mask_p] = 0;
}
/*Go to the next column*/
if(col_bit < col_bit_max) {
col_bit += bpp;
bitmask = bitmask >> bpp;
}
else {
col_bit = 0;
bitmask = bitmask_init;
map_p++;
}
/*Next mask byte*/
mask_p++;
}
#if LV_DRAW_COMPLEX
/*Apply masks if any*/
if(mask_any) {
blend_dsc.mask_res = lv_draw_mask_apply(mask_buf + mask_p_start, fill_area.x1, fill_area.y2,
fill_w);
if(blend_dsc.mask_res == LV_DRAW_MASK_RES_TRANSP) {
lv_memset_00(mask_buf + mask_p_start, fill_w);
}
}
#endif
if((uint32_t) mask_p + (col_end - col_start) < mask_buf_size) {
fill_area.y2 ++;
}
else {
blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED;
lv_draw_ra6m3_2d_blend(draw_ctx, &blend_dsc);
fill_area.y1 = fill_area.y2 + 1;
fill_area.y2 = fill_area.y1;
mask_p = 0;
}
col_bit += col_bit_row_ofs;
map_p += (col_bit >> 3);
col_bit = col_bit & 0x7;
}
/*Flush the last part*/
if(fill_area.y1 != fill_area.y2) {
fill_area.y2--;
blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED;
lv_draw_ra6m3_2d_blend(draw_ctx, &blend_dsc);
mask_p = 0;
}
lv_mem_buf_release(mask_buf);
}
void lv_draw_gpu_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p,
uint32_t letter)
{
const lv_font_t * font_p = dsc->font;
lv_opa_t opa = dsc->opa;
if(opa < LV_OPA_MIN) return;
if(opa > LV_OPA_MAX) opa = LV_OPA_COVER;
if(font_p == NULL) {
LV_LOG_WARN("lv_draw_letter: font is NULL");
return;
}
lv_font_glyph_dsc_t g;
bool g_ret = lv_font_get_glyph_dsc(font_p, &g, letter, '\0');
if(g_ret == false) {
/*Add warning if the dsc is not found
*but do not print warning for non printable ASCII chars (e.g. '\n')*/
if(letter >= 0x20 &&
letter != 0xf8ff && /*LV_SYMBOL_DUMMY*/
letter != 0x200c) { /*ZERO WIDTH NON-JOINER*/
LV_LOG_WARN("lv_draw_letter: glyph dsc. not found for U+%X", letter);
}
return;
}
/*Don't draw anything if the character is empty. E.g. space*/
if((g.box_h == 0) || (g.box_w == 0)) return;
lv_point_t gpos;
gpos.x = pos_p->x + g.ofs_x;
gpos.y = pos_p->y + (dsc->font->line_height - dsc->font->base_line) - g.box_h - g.ofs_y;
/*If the letter is completely out of mask don't draw it*/
if(gpos.x + g.box_w < draw_ctx->clip_area->x1 ||
gpos.x > draw_ctx->clip_area->x2 ||
gpos.y + g.box_h < draw_ctx->clip_area->y1 ||
gpos.y > draw_ctx->clip_area->y2) {
return;
}
const uint8_t * map_p = lv_font_get_glyph_bitmap(font_p, letter);
if(map_p == NULL) {
LV_LOG_WARN("lv_draw_letter: character's bitmap not found");
return;
}
if(font_p->subpx) {
#if LV_DRAW_COMPLEX && LV_USE_FONT_SUBPX
draw_letter_subpx(pos_x, pos_y, &g, clip_area, map_p, color, opa, blend_mode);
#else
LV_LOG_WARN("Can't draw sub-pixel rendered letter because LV_USE_FONT_SUBPX == 0 in lv_conf.h");
#endif
}
else {
draw_letter_normal(draw_ctx, dsc, &gpos, &g, map_p);
}
}
#endif

View File

@@ -0,0 +1,742 @@
/**
* @file lv_gpu_d2_ra6m3.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_gpu_d2_ra6m3.h"
#include "../../core/lv_refr.h"
#include <math.h>
#if LV_USE_GPU_RA6M3_G2D
#include LV_GPU_RA6M3_G2D_INCLUDE
/*********************
* DEFINES
*********************/
#define LOG_ERRORS
#ifdef LOG_ERRORS
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define ERROR_LIST_SIZE (4)
#define D2_EXEC(a) lv_port_gpu_log_error(a, __func__, __LINE__)
#else
/* here is error logging not enabled */
#define D2_EXEC(a) a;
#endif
/**********************
* TYPEDEFS
**********************/
typedef struct {
d2_s32 error;
const char * func;
int line;
} log_error_entry;
/**********************
* STATIC PROTOTYPES
**********************/
#ifdef LOG_ERRORS
static void lv_port_gpu_log_error(d2_s32 status, const char * func, int line);
#endif
static void invalidate_cache(void);
void lv_draw_gpu_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p,
uint32_t letter);
/**********************
* STATIC VARIABLES
**********************/
#ifdef LOG_ERRORS
static log_error_entry log_error_list[ERROR_LIST_SIZE];
static int error_list_index;
static int error_count;
#endif
static d2_device * _d2_handle;
static d2_renderbuffer * renderbuffer;
static d2_s32 src_cf_val, dst_cf_val;
static lv_draw_img_dsc_t img_dsc;
static bool color_key_enabled, alpha_enabled, blend_enabled, colorize_enabled;
/**********************
* STATIC FUNCTIONS
**********************/
static d2_s32 lv_port_gpu_cf_lv_to_d2(lv_img_cf_t cf)
{
d2_s32 d2_cf;
#if (DLG_LVGL_CF == 1)
switch(cf & ~(1 << 5)) {
#else
switch(cf) {
#endif /* (DLG_LVGL_CF == 1) */
case LV_IMG_CF_TRUE_COLOR:
d2_cf = d2_mode_rgb565;
break;
case LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED:
d2_cf = d2_mode_rgb565;
break;
case LV_IMG_CF_ALPHA_1BIT:
d2_cf = d2_mode_alpha1;
break;
case LV_IMG_CF_ALPHA_2BIT:
d2_cf = d2_mode_alpha2;
break;
case LV_IMG_CF_ALPHA_4BIT:
d2_cf = d2_mode_alpha4;
break;
case LV_IMG_CF_ALPHA_8BIT:
d2_cf = d2_mode_alpha8;
break;
case LV_IMG_CF_INDEXED_1BIT:
d2_cf = d2_mode_i1 | d2_mode_clut;
break;
case LV_IMG_CF_INDEXED_2BIT:
d2_cf = d2_mode_i2 | d2_mode_clut;
break;
case LV_IMG_CF_INDEXED_4BIT:
d2_cf = d2_mode_i4 | d2_mode_clut;
break;
case LV_IMG_CF_INDEXED_8BIT:
d2_cf = d2_mode_i8 | d2_mode_clut;
break;
#if (DLG_LVGL_CF == 1)
case LV_IMG_CF_RGB565:
d2_cf = d2_mode_rgb565;
break;
case LV_IMG_CF_RGB888:
d2_cf = d2_mode_rgb888;
break;
case LV_IMG_CF_RGBA8888:
d2_cf = d2_mode_rgba8888;
break;
#endif /* DLG_LVGL_CF */
default:
return -1;
}
#if (DLG_LVGL_CF == 1)
return d2_cf | (cf & (1 << 5) ? d2_mode_rle : 0);
#else
return d2_cf;
#endif /* (DLG_LVGL_CF == 1) */
}
static bool lv_port_gpu_cf_fb_valid(d2_s32 cf)
{
if((cf & (d2_mode_rle | d2_mode_clut)) || cf < 0) {
return false;
}
switch(cf) {
case d2_mode_alpha8:
case d2_mode_rgb565:
case d2_mode_argb8888:
case d2_mode_argb4444:
case d2_mode_rgba8888:
case d2_mode_rgba4444:
return true;
default:
return false;
}
}
static bool lv_port_gpu_cf_has_alpha(d2_s32 cf)
{
switch(cf & ~(d2_mode_clut | d2_mode_rle)) {
case d2_mode_argb8888:
case d2_mode_rgba8888:
case d2_mode_argb4444:
case d2_mode_rgba4444:
case d2_mode_argb1555:
case d2_mode_rgba5551:
case d2_mode_ai44:
case d2_mode_i8:
case d2_mode_i4:
case d2_mode_i2:
case d2_mode_i1:
case d2_mode_alpha8:
case d2_mode_alpha4:
case d2_mode_alpha2:
case d2_mode_alpha1:
return true;
default:
return false;
}
}
static bool lv_port_gpu_cf_is_alpha(d2_s32 cf)
{
switch(cf & ~d2_mode_rle) {
case d2_mode_alpha8:
case d2_mode_alpha4:
case d2_mode_alpha2:
case d2_mode_alpha1:
return true;
default:
return false;
}
}
static d2_color lv_port_gpu_color_lv_to_d2(lv_color_t color)
{
uint8_t alpha, red, green, blue;
alpha = 0xFF;
red = color.ch.red << 3 | color.ch.red >> 2;
green = color.ch.green << 2 | color.ch.green >> 4;
blue = color.ch.blue << 3 | color.ch.blue >> 2;
return (alpha) << 24UL
| (red) << 16UL
| (green) << 8UL
| (blue) << 0UL;
}
static void lv_port_gpu_get_recolor_consts(d2_color * cl, d2_color * ch)
{
d2_color c = lv_port_gpu_color_lv_to_d2(img_dsc.recolor);
d2_alpha r, g, b, opa = img_dsc.recolor_opa > LV_OPA_MAX ? LV_OPA_COVER : img_dsc.recolor_opa;
r = ((uint32_t)((uint8_t)(c >> 16UL)) * opa) / 255;
g = ((uint32_t)((uint8_t)(c >> 8UL)) * opa) / 255;
b = ((uint32_t)((uint8_t)(c >> 0UL)) * opa) / 255;
*cl = r << 16UL | g << 8UL | b << 0UL;
r += 255 - opa;
g += 255 - opa;
b += 255 - opa;
*ch = r << 16UL | g << 8UL | b << 0UL;
}
static int lv_port_gpu_handle_indexed_color(const lv_color_t ** src, const d2_color ** clut, d2_s32 cf)
{
int clut_len = 0;
if(cf & d2_mode_clut) {
/* Calculate CLUT length in entries */
switch(cf & ~(d2_mode_clut | d2_mode_rle)) {
case d2_mode_i1:
clut_len = 2;
break;
case d2_mode_i2:
clut_len = 4;
break;
case d2_mode_i4:
clut_len = 16;
break;
case d2_mode_i8:
clut_len = 256;
break;
case d2_mode_ai44:
clut_len = 16;
break;
default:
return 0;
}
*clut = (const d2_color *)*src;
*src = (const lv_color_t *)((const uint32_t *)*src + clut_len);
}
return clut_len;
}
static int lv_port_gpu_cf_bpp(d2_s32 cf)
{
switch(cf & ~(d2_mode_clut | d2_mode_rle)) {
case d2_mode_argb8888:
return 32;
case d2_mode_rgba8888:
return 32;
case d2_mode_rgb888:
return 32;
case d2_mode_argb4444:
return 16;
case d2_mode_rgba4444:
return 16;
case d2_mode_argb1555:
return 16;
case d2_mode_rgba5551:
return 16;
case d2_mode_rgb565:
return 16;
case d2_mode_ai44:
return 8;
case d2_mode_i8:
return 8;
case d2_mode_i4:
return 4;
case d2_mode_i2:
return 2;
case d2_mode_i1:
return 1;
case d2_mode_alpha8:
return 8;
case d2_mode_alpha4:
return 4;
case d2_mode_alpha2:
return 2;
case d2_mode_alpha1:
return 1;
default:
return 0;
}
}
static d2_s32 lv_port_gpu_cf_get_default(void)
{
return d2_mode_rgb565;
}
static void lv_port_gpu_config_blit_clear(void)
{
alpha_enabled = false;
color_key_enabled = false;
blend_enabled = true;
colorize_enabled = false;
lv_draw_img_dsc_init(&img_dsc);
src_cf_val = lv_port_gpu_cf_get_default();
dst_cf_val = lv_port_gpu_cf_get_default();
}
void lv_port_gpu_init(void)
{
lv_port_gpu_config_blit_clear();
}
static void lv_port_gpu_rotate_point(int * x, int * y, float cos_angle, float sin_angle, int pivot_x, int pivot_y)
{
float fx, fy;
*x -= pivot_x;
*y -= pivot_y;
fx = ((float) * x) / 16.0f;
fy = ((float) * y) / 16.0f;
*x = (int)(((fx * cos_angle) - (fy * sin_angle)) * 16.0f);
*y = (int)(((fx * sin_angle) + (fy * cos_angle)) * 16.0f);
*x += pivot_x;
*y += pivot_y;
}
void lv_draw_ra6m3_g2d_init(void)
{
if(_d2_handle != NULL) {
return;
}
_d2_handle = d2_opendevice(0);
if(_d2_handle == NULL)
return;
/* set blocksize for default displaylist */
if(d2_setdlistblocksize(_d2_handle, 25) != D2_OK) {
LV_LOG_ERROR("Could NOT d2_setdlistblocksize\n");
d2_closedevice(_d2_handle);
return;
}
/* bind the hardware */
if(d2_inithw(_d2_handle, 0) != D2_OK) {
LV_LOG_ERROR("Could NOT d2_inithw\n");
d2_closedevice(_d2_handle);
return;
}
renderbuffer = d2_newrenderbuffer(_d2_handle, 20, 20);
if(!renderbuffer) {
LV_LOG_ERROR("NO renderbuffer\n");
d2_closedevice(_d2_handle);
return;
}
}
static void lv_port_gpu_hw_deinit(void)
{
if(_d2_handle == NULL)
return;
D2_EXEC(d2_freerenderbuffer(_d2_handle, renderbuffer));
D2_EXEC(d2_closedevice(_d2_handle));
renderbuffer = NULL;
_d2_handle = NULL;
}
void lv_port_gpu_flush(void)
{
lv_port_gpu_hw_deinit();
}
static void lv_port_gpu_start_render(void)
{
D2_EXEC(d2_selectrenderbuffer(_d2_handle, renderbuffer));
}
static void lv_port_gpu_complete_render(void)
{
D2_EXEC(d2_flushframe(_d2_handle));
}
void lv_port_gpu_wait(lv_draw_ctx_t * draw_ctx)
{
lv_port_gpu_complete_render();
lv_draw_sw_wait_for_finish(draw_ctx);
}
static void lv_port_gpu_execute_render(void)
{
if(_d2_handle) {
D2_EXEC(d2_executerenderbuffer(_d2_handle, renderbuffer, 0));
}
}
void lv_port_gpu_blit(int32_t x, int32_t y, lv_color_t * dst, const lv_area_t * fill_area)
{
uint32_t ModeSrc;
ModeSrc = d2_mode_rgb565;
lv_coord_t dst_width, dst_hight;
dst_width = lv_area_get_width(fill_area);
dst_hight = lv_area_get_height(fill_area);
d2_selectrenderbuffer(_d2_handle, renderbuffer);
// Generate render operations
d2_framebuffer(_d2_handle, (uint16_t *)&fb_background[0], LV_HOR_RES_MAX, LV_HOR_RES_MAX,
MAX(fill_area->y2 + 1, 2), lv_port_gpu_cf_get_default());
d2_cliprect(_d2_handle, 0, 0, LV_HOR_RES_MAX - 1, fill_area->y2);
d2_setblitsrc(_d2_handle, (void *) dst, dst_width, dst_width, dst_hight, ModeSrc);
d2_blitcopy(_d2_handle, dst_width, dst_hight, 0, 0, D2_FIX4(dst_width), D2_FIX4(dst_hight),
D2_FIX4(fill_area->x1), D2_FIX4(fill_area->y1), 0);
// Execute render operations
d2_executerenderbuffer(_d2_handle, renderbuffer, 0);
}
void lv_port_gpu_fill(lv_color_t * dest_buf, const lv_area_t * fill_area, lv_coord_t dst_width,
lv_color_t color, lv_opa_t opa)
{
invalidate_cache();
lv_port_gpu_start_render();
D2_EXEC(d2_framebuffer(_d2_handle, d1_maptovidmem(_d2_handle, dest_buf), MAX(dst_width, 2), MAX(dst_width, 2),
MAX(fill_area->y2 + 1, 2), lv_port_gpu_cf_get_default()));
D2_EXEC(d2_cliprect(_d2_handle, 0, 0, dst_width - 1, fill_area->y2));
D2_EXEC(d2_setalpha(_d2_handle, opa > LV_OPA_MAX ? 0xFF : opa));
D2_EXEC(d2_setcolor(_d2_handle, 0, lv_port_gpu_color_lv_to_d2(color)));
D2_EXEC(d2_renderbox(_d2_handle, D2_FIX4(fill_area->x1), D2_FIX4(fill_area->y1),
D2_FIX4(lv_area_get_width(fill_area)), D2_FIX4(lv_area_get_height(fill_area))));
lv_port_gpu_execute_render();
}
bool lv_port_gpu_config_blit(const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t dst_cf,
lv_img_cf_t src_cf, bool alpha_en, bool color_key_en, bool blend_en, bool colorize_en)
{
d2_s32 d2_src_cf, d2_dst_cf;
if(blend_en && draw_dsc->blend_mode != LV_BLEND_MODE_NORMAL
&& draw_dsc->blend_mode != LV_BLEND_MODE_ADDITIVE) {
return false;
}
d2_src_cf = lv_port_gpu_cf_lv_to_d2(src_cf);
d2_dst_cf = lv_port_gpu_cf_lv_to_d2(dst_cf);
if(d2_src_cf < 0 || !lv_port_gpu_cf_fb_valid(d2_dst_cf)) {
return false;
}
src_cf_val = d2_src_cf;
dst_cf_val = d2_dst_cf;
img_dsc = *draw_dsc;
/* Disable alpha if alpha channel does not exist */
alpha_enabled = lv_port_gpu_cf_has_alpha(src_cf_val) ? alpha_en : 0;
color_key_enabled = color_key_en;
blend_enabled = blend_en;
colorize_enabled = colorize_en | lv_port_gpu_cf_is_alpha(src_cf_val);
return true;
}
static void lv_port_gpu_blit_internal(const lv_area_t * dest_area, const lv_color_t * src_buf,
const lv_area_t * src_area, d2_u32 flags)
{
const lv_area_t * img_area = src_area;
lv_area_t img_area_scaled;
lv_coord_t w, h, img_w, img_h;
d2_s32 pitch;
int bpp = lv_port_gpu_cf_bpp(src_cf_val);
D2_EXEC(d2_cliprect(_d2_handle, dest_area->x1, dest_area->y1, dest_area->x2, dest_area->y2));
pitch = w = lv_area_get_width(src_area);
h = lv_area_get_height(src_area);
if(img_dsc.zoom != LV_IMG_ZOOM_NONE) {
img_area_scaled.x1 = src_area->x1 + ((((int32_t)0 - img_dsc.pivot.x) * img_dsc.zoom) >> 8) + img_dsc.pivot.x;
img_area_scaled.x2 = src_area->x1 + ((((int32_t)w - img_dsc.pivot.x) * img_dsc.zoom) >> 8) + img_dsc.pivot.x;
img_area_scaled.y1 = src_area->y1 + ((((int32_t)0 - img_dsc.pivot.y) * img_dsc.zoom) >> 8) + img_dsc.pivot.y;
img_area_scaled.y2 = src_area->y1 + ((((int32_t)h - img_dsc.pivot.y) * img_dsc.zoom) >> 8) + img_dsc.pivot.y;
img_area = &img_area_scaled;
}
img_w = lv_area_get_width(img_area);
img_h = lv_area_get_height(img_area);
if(0 < bpp && bpp < 8) {
pitch = (w + (8 - bpp)) & (~(8 - bpp));
}
if(img_dsc.angle == 0) {
D2_EXEC(d2_setblitsrc(_d2_handle, (void *) src_buf, pitch, w, h, src_cf_val));
D2_EXEC(d2_blitcopy(_d2_handle, w, h, 0, 0,
D2_FIX4(img_w), D2_FIX4(img_h), D2_FIX4(img_area->x1), D2_FIX4(img_area->y1), flags));
}
else {
int x, y, x1, y1, x2, y2, x3, y3, x4, y4, dxu, dxv, dyu, dyv, xx, xy, yx, yy;
int pivot_scaled_x, pivot_scaled_y;
int tex_offset = (flags & d2_bf_filter) ? -32767 : 0;
d2_u8 amode, cmode = d2_to_copy;
float angle = ((float)img_dsc.angle / 10) * M_PI / 180;
float cos_angle = cosf(angle);
float sin_angle = sinf(angle);
d2_u8 fillmode_backup;
/* setup texture params */
fillmode_backup = d2_getfillmode(_d2_handle);
D2_EXEC(d2_setfillmode(_d2_handle, d2_fm_texture));
D2_EXEC(d2_settexture(_d2_handle, (void *) src_buf, pitch, w, h, src_cf_val));
D2_EXEC(d2_settexturemode(_d2_handle, flags & (d2_bf_filter | d2_bf_wrap)));
amode = flags & d2_bf_usealpha ? d2_to_copy : d2_to_one;
cmode = flags & d2_bf_colorize2 ? d2_to_blend : d2_to_copy;
D2_EXEC(d2_settextureoperation(_d2_handle, amode, cmode, cmode, cmode));
if(flags & d2_bf_colorize2) {
d2_color cl = d2_getcolor(_d2_handle, 0), ch = d2_getcolor(_d2_handle, 1);
D2_EXEC(d2_settexopparam(_d2_handle, d2_cc_red, (uint8_t)(cl >> 16UL),
(uint8_t)(ch >> 16UL)));
D2_EXEC(d2_settexopparam(_d2_handle, d2_cc_green, (uint8_t)(cl >> 8UL),
(uint8_t)(ch >> 8UL)));
D2_EXEC(d2_settexopparam(_d2_handle, d2_cc_blue, (uint8_t)(cl >> 0UL),
(uint8_t)(ch >> 0UL)));
}
x = D2_FIX4(img_area->x1);
y = D2_FIX4(img_area->y1);
/* define quad points */
x1 = D2_FIX4(0);
y1 = D2_FIX4(0);
x2 = D2_FIX4(img_w);
y2 = D2_FIX4(0);
x3 = D2_FIX4(img_w);
y3 = D2_FIX4(img_h);
x4 = D2_FIX4(0);
y4 = D2_FIX4(img_h);
/* rotate points for quad */
pivot_scaled_x = (img_dsc.pivot.x * img_dsc.zoom) >> 4;
pivot_scaled_y = (img_dsc.pivot.y * img_dsc.zoom) >> 4;
lv_port_gpu_rotate_point(&x1, &y1, cos_angle, sin_angle, pivot_scaled_x, pivot_scaled_y);
lv_port_gpu_rotate_point(&x2, &y2, cos_angle, sin_angle, pivot_scaled_x, pivot_scaled_y);
lv_port_gpu_rotate_point(&x3, &y3, cos_angle, sin_angle, pivot_scaled_x, pivot_scaled_y);
lv_port_gpu_rotate_point(&x4, &y4, cos_angle, sin_angle, pivot_scaled_x, pivot_scaled_y);
/* compute texture increments */
xx = (int)(cos_angle * 65536.0f);
xy = (int)(sin_angle * 65536.0f);
yx = (int)(-sin_angle * 65536.0f);
yy = (int)(cos_angle * 65536.0f);
dxu = ((D2_FIX16(w) / D2_FIX4(img_w)) * xx) >> 12;
dxv = ((D2_FIX16(w) / D2_FIX4(img_w)) * xy) >> 12;
dyu = ((D2_FIX16(h) / D2_FIX4(img_h)) * yx) >> 12;
dyv = ((D2_FIX16(h) / D2_FIX4(img_h)) * yy) >> 12;
/* map texture exactly to rotated quad, so texel center is always (0/0) top-left */
D2_EXEC(d2_settexelcenter(_d2_handle, 0, 0));
D2_EXEC(d2_settexturemapping(_d2_handle, (d2_point)(x + x1), (d2_point)(y + y1),
tex_offset, tex_offset, dxu, dxv, dyu, dyv));
int minx = MAX(dest_area->x1, D2_INT4(x + MIN(x1, MIN(x2, MIN(x3, x4)))));
int maxx = MIN(dest_area->x2, D2_INT4(x + MAX(x1, MAX(x2, MAX(x3, x4)))));
int slice = (flags & d2_bf_filter) ? 6 : 8;
/* Perform render operation in slices to acheive better performance */
for(int posx = minx; posx < maxx; posx += slice) {
D2_EXEC(d2_cliprect(_d2_handle, posx, dest_area->y1, MIN(posx + slice - 1, maxx), dest_area->y2));
D2_EXEC(d2_renderquad(_d2_handle, (d2_point)(x + x1), (d2_point)(y + y1),
(d2_point)(x + x2), (d2_point)(y + y2),
(d2_point)(x + x3), (d2_point)(y + y3),
(d2_point)(x + x4), (d2_point)(y + y4), 0));
}
D2_EXEC(d2_setfillmode(_d2_handle, fillmode_backup));
}
}
void lv_port_ra_gpu_blit(lv_color_t * dst, const lv_area_t * dst_area, lv_coord_t dest_stride,
const lv_color_t * src, const lv_area_t * src_area, lv_opa_t opa)
{
d2_u32 flags = 0;
const d2_color * clut = NULL;
int clut_len = 0;
invalidate_cache();
clut_len = lv_port_gpu_handle_indexed_color(&src, &clut, src_cf_val);
lv_port_gpu_start_render();
D2_EXEC(d2_framebuffer(_d2_handle, d1_maptovidmem(_d2_handle, dst), MAX(dest_stride, 2),
MAX(dst_area->x2 + 1, 2), MAX(dst_area->y2 + 1, 2), dst_cf_val));
flags |= alpha_enabled ? d2_bf_usealpha : 0;
D2_EXEC(d2_setalpha(_d2_handle, opa > LV_OPA_MAX ? LV_OPA_COVER : opa));
if(clut) {
D2_EXEC(d2_writetexclut_direct(_d2_handle, clut, 0, clut_len));
}
flags |= color_key_enabled ? d2_bf_usealpha : 0;
flags |= (colorize_enabled || img_dsc.recolor_opa != LV_OPA_TRANSP) ? d2_bf_colorize2 : 0;
if(colorize_enabled) {
D2_EXEC(d2_setcolor(_d2_handle, 0, lv_port_gpu_color_lv_to_d2(img_dsc.recolor)));
D2_EXEC(d2_setcolor(_d2_handle, 1, lv_port_gpu_color_lv_to_d2(img_dsc.recolor)));
}
else if(img_dsc.recolor_opa != LV_OPA_TRANSP) {
d2_color cl = 0, ch = 0;
lv_port_gpu_get_recolor_consts(&cl, &ch);
D2_EXEC(d2_setcolor(_d2_handle, 0, cl));
D2_EXEC(d2_setcolor(_d2_handle, 1, ch));
}
flags |= ((img_dsc.angle || img_dsc.zoom != LV_IMG_ZOOM_NONE) && img_dsc.antialias) ? d2_bf_filter : 0;
if(blend_enabled) {
D2_EXEC(d2_setblendmode(_d2_handle, d2_bm_alpha,
img_dsc.blend_mode != LV_BLEND_MODE_NORMAL ? d2_bm_one : d2_bm_one_minus_alpha));
D2_EXEC(d2_setalphablendmode(_d2_handle, d2_bm_one, d2_bm_one_minus_alpha));
}
else {
D2_EXEC(d2_setblendmode(_d2_handle, d2_bm_one, d2_bm_zero));
D2_EXEC(d2_setalphablendmode(_d2_handle, d2_bm_one, d2_bm_zero));
}
lv_port_gpu_blit_internal(dst_area, src, src_area, flags);
lv_port_gpu_execute_render();
}
void lv_draw_ra6m3_2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc)
{
lv_area_t blend_area;
if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area)) return;
bool done = false;
if(dsc->mask_buf == NULL && dsc->blend_mode == LV_BLEND_MODE_NORMAL && lv_area_get_size(&blend_area) > 100) {
lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area);
lv_color_t * dest_buf = draw_ctx->buf;
const lv_color_t * src_buf = dsc->src_buf;
if(src_buf) {
lv_draw_sw_blend_basic(draw_ctx, dsc);
lv_area_t src_area;
src_area.x1 = blend_area.x1 - (dsc->blend_area->x1 - draw_ctx->buf_area->x1);
src_area.y1 = blend_area.y1 - (dsc->blend_area->y1 - draw_ctx->buf_area->y1);
src_area.x2 = src_area.x1 + lv_area_get_width(dsc->blend_area) - 1;
src_area.y2 = src_area.y1 + lv_area_get_height(dsc->blend_area) - 1;
lv_port_ra_gpu_blit(dest_buf, &blend_area, dest_stride, src_buf, &src_area, dsc->opa);
done = true;
}
else if(dsc->opa >= LV_OPA_MAX) {
lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
lv_port_gpu_fill(dest_buf, &blend_area, dest_stride, dsc->color, dsc->opa);
done = true;
}
}
if(!done) lv_draw_sw_blend_basic(draw_ctx, dsc);
}
static void lv_port_gpu_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc,
const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t color_format)
{
/*TODO basic ARGB8888 image can be handles here*/
lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, color_format);
}
void lv_draw_ra6m3_2d_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
{
lv_draw_sw_init_ctx(drv, draw_ctx);
lv_draw_ra6m3_dma2d_ctx_t * ra_2d_draw_ctx = (lv_draw_sw_ctx_t *)draw_ctx;
ra_2d_draw_ctx->blend = lv_draw_ra6m3_2d_blend;
ra_2d_draw_ctx->base_draw.draw_img_decoded = lv_port_gpu_img_decoded;
ra_2d_draw_ctx->base_draw.wait_for_finish = lv_port_gpu_wait;
ra_2d_draw_ctx->base_draw.draw_letter = lv_draw_gpu_letter;
//ra_2d_draw_ctx->base_draw.buffer_copy = lv_draw_ra6m3_2d_buffer_copy;
}
void lv_draw_stm32_dma2d_ctx_deinit(lv_disp_t * disp, lv_draw_ctx_t * draw_ctx)
{
LV_UNUSED(disp);
LV_UNUSED(draw_ctx);
}
static void invalidate_cache(void)
{
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
if(disp->driver->clean_dcache_cb) disp->driver->clean_dcache_cb(disp->driver);
}
#ifdef LOG_ERRORS
static void lv_port_gpu_log_error(d2_s32 status, const char * func, int line)
{
if(status) {
log_error_list[error_list_index].error = status;
log_error_list[error_list_index].func = func;
log_error_list[error_list_index].line = line;
LV_LOG_ERROR("%s\r\n", d2_geterrorstring(_d2_handle));
LV_LOG_ERROR("%d:\t%d - %s : %d\r\n", error_count,
log_error_list[error_list_index].error,
log_error_list[error_list_index].func,
log_error_list[error_list_index].line);
error_count++;
error_list_index++;
if(error_list_index >= ERROR_LIST_SIZE) {
error_list_index = 0;
}
}
}
#endif
#endif /* LV_USE_GPU_RA6M3_G2D */

View File

@@ -0,0 +1,56 @@
/**
* @file lv_gpu_d2_ra6m3.h
*
*/
#ifndef LV_GPU_D2_RA6M3_H
#define LV_GPU_D2_RA6M3_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../misc/lv_color.h"
#if LV_USE_GPU_RA6M3_G2D
#include "../../core/lv_disp.h"
#include "../sw/lv_draw_sw.h"
/**********************
* DEFINE
**********************/
#define MIN(A, B) ((A) < (B) ? (A) : (B))
#define MAX(A, B) ((A) > (B) ? (A) : (B))
#define M_PI 3.1415926
/**********************
* TYPEDEFS
**********************/
typedef lv_draw_sw_ctx_t lv_draw_ra6m3_dma2d_ctx_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_draw_ra6m3_g2d_init(void);
void lv_port_gpu_init(void);
void lv_port_gpu_flush(void);
void lv_port_gpu_blit(int32_t x, int32_t y, lv_color_t * dst, const lv_area_t * fill_area);
void lv_draw_ra6m3_2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc);
void lv_draw_ra6m3_2d_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
void lv_draw_ra6m3_2d_ctx_deinit(lv_disp_drv_t * disp, lv_draw_ctx_t * draw_ctx);
#endif /*LV_USE_GPU_GD32_IPA*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif

View File

@@ -25,6 +25,7 @@
#include "../draw/arm2d/lv_gpu_arm2d.h" #include "../draw/arm2d/lv_gpu_arm2d.h"
#include "../draw/nxp/vglite/lv_draw_vglite.h" #include "../draw/nxp/vglite/lv_draw_vglite.h"
#include "../draw/nxp/pxp/lv_draw_pxp.h" #include "../draw/nxp/pxp/lv_draw_pxp.h"
#include "../draw/renesas/lv_gpu_d2_ra6m3.h"
#if LV_USE_THEME_DEFAULT #if LV_USE_THEME_DEFAULT
#include "../extra/themes/default/lv_theme_default.h" #include "../extra/themes/default/lv_theme_default.h"
@@ -95,8 +96,11 @@ void lv_disp_drv_init(lv_disp_drv_t * driver)
driver->dpi = LV_DPI_DEF; driver->dpi = LV_DPI_DEF;
driver->color_chroma_key = LV_COLOR_CHROMA_KEY; driver->color_chroma_key = LV_COLOR_CHROMA_KEY;
#if LV_USE_GPU_RA6M3_G2D
#if LV_USE_GPU_STM32_DMA2D driver->draw_ctx_init = lv_draw_ra6m3_2d_ctx_init;
driver->draw_ctx_deinit = lv_draw_ra6m3_2d_ctx_init;
driver->draw_ctx_size = sizeof(lv_draw_ra6m3_dma2d_ctx_t);
#elif LV_USE_GPU_STM32_DMA2D
driver->draw_ctx_init = lv_draw_stm32_dma2d_ctx_init; driver->draw_ctx_init = lv_draw_stm32_dma2d_ctx_init;
driver->draw_ctx_deinit = lv_draw_stm32_dma2d_ctx_init; driver->draw_ctx_deinit = lv_draw_stm32_dma2d_ctx_init;
driver->draw_ctx_size = sizeof(lv_draw_stm32_dma2d_ctx_t); driver->draw_ctx_size = sizeof(lv_draw_stm32_dma2d_ctx_t);

View File

@@ -445,6 +445,26 @@
#endif #endif
#endif #endif
/*Enable RA6M3 G2D GPU*/
#ifndef LV_USE_GPU_RA6M3_G2D
#ifdef CONFIG_LV_USE_GPU_RA6M3_G2D
#define LV_USE_GPU_RA6M3_G2D CONFIG_LV_USE_GPU_RA6M3_G2D
#else
#define LV_USE_GPU_RA6M3_G2D 0
#endif
#endif
#if LV_USE_GPU_RA6M3_G2D
/*include path of target processor
e.g. "hal_data.h"*/
#ifndef LV_GPU_RA6M3_G2D_INCLUDE
#ifdef CONFIG_LV_GPU_RA6M3_G2D_INCLUDE
#define LV_GPU_RA6M3_G2D_INCLUDE CONFIG_LV_GPU_RA6M3_G2D_INCLUDE
#else
#define LV_GPU_RA6M3_G2D_INCLUDE "hal_data.h"
#endif
#endif
#endif
/*Use SWM341's DMA2D GPU*/ /*Use SWM341's DMA2D GPU*/
#ifndef LV_USE_GPU_SWM341_DMA2D #ifndef LV_USE_GPU_SWM341_DMA2D
#ifdef CONFIG_LV_USE_GPU_SWM341_DMA2D #ifdef CONFIG_LV_USE_GPU_SWM341_DMA2D