feat(nxp): release NXP PXP and VG-Lite for LVGL v9.0 (#5288)

Signed-off-by: Nicușor Cîțu <nicusor.citu@nxp.com>
Signed-off-by: Ana Grad <ana.grad@nxp.com>
Co-authored-by: Ana Grad <ana.grad@nxp.com>
This commit is contained in:
nicusorcitu
2024-01-12 12:54:42 +02:00
committed by GitHub
parent 39cb1ddc4a
commit ee8de1e1a0
38 changed files with 1735 additions and 1271 deletions
File diff suppressed because it is too large Load Diff
+35 -17
View File
@@ -67,6 +67,23 @@
*(Not so important, you can adjust it to modify default sizes and spaces)*/
#define LV_DPI_DEF 130 /*[px/inch]*/
/*=================
* OPERATING SYSTEM
*=================*/
/*Select an operating system to use. Possible options:
* - LV_OS_NONE
* - LV_OS_PTHREAD
* - LV_OS_FREERTOS
* - LV_OS_CMSIS_RTOS2
* - LV_OS_RTTHREAD
* - LV_OS_WINDOWS
* - LV_OS_CUSTOM */
#define LV_USE_OS LV_OS_NONE
#if LV_USE_OS == LV_OS_CUSTOM
#define LV_OS_CUSTOM_INCLUDE <stdint.h>
#endif
/*========================
* RENDERING CONFIGURATION
*========================*/
@@ -122,9 +139,27 @@
/* Use NXP's VG-Lite GPU on iMX RTxxx platforms. */
#define LV_USE_DRAW_VGLITE 0
#if LV_USE_DRAW_VGLITE
/* Enable blit quality degradation workaround recommended for screen's dimension > 352 pixels. */
#define LV_USE_VGLITE_BLIT_SPLIT 0
#if LV_USE_OS
/* Enable VGLite draw async. Queue multiple tasks and flash them once to the GPU. */
#define LV_USE_VGLITE_DRAW_ASYNC 1
#endif
/* Enable VGLite asserts. */
#define LV_USE_VGLITE_ASSERT 0
#endif
/* Use NXP's PXP on iMX RTxxx platforms. */
#define LV_USE_DRAW_PXP 0
#if LV_USE_DRAW_PXP
/* Enable PXP asserts. */
#define LV_USE_PXP_ASSERT 0
#endif
/* Use Renesas Dave2D on RA platforms. */
#define LV_USE_DRAW_DAVE2D 0
@@ -143,23 +178,6 @@
#endif
/*=================
* OPERATING SYSTEM
*=================*/
/*Select an operating system to use. Possible options:
* - LV_OS_NONE
* - LV_OS_PTHREAD
* - LV_OS_FREERTOS
* - LV_OS_CMSIS_RTOS2
* - LV_OS_RTTHREAD
* - LV_OS_WINDOWS
* - LV_OS_CUSTOM */
#define LV_USE_OS LV_OS_NONE
#if LV_USE_OS == LV_OS_CUSTOM
#define LV_OS_CUSTOM_INCLUDE <stdint.h>
#endif
/*=======================
* FEATURE CONFIGURATION
*=======================*/
+43 -38
View File
@@ -4,7 +4,7 @@
*/
/**
* Copyright 2023 NXP
* Copyright 2023-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
@@ -33,7 +33,7 @@
* STATIC PROTOTYPES
**********************/
static void _invalidate_cache(lv_draw_buf_t * draw_buf, const char * area);
static void _invalidate_cache(void * buf, uint32_t stride, lv_color_format_t cf, const lv_area_t * area);
/**********************
* STATIC VARIABLES
@@ -58,44 +58,49 @@ void lv_draw_buf_pxp_init_handlers(void)
* STATIC FUNCTIONS
**********************/
static void _invalidate_cache(lv_draw_buf_t * draw_buf, const char * area)
static void _invalidate_cache(void * buf, uint32_t stride, lv_color_format_t cf, const lv_area_t * area)
{
LV_UNUSED(draw_buf);
LV_UNUSED(area);
if(area->y1 == 0) {
uint16_t size = stride * lv_area_get_height(area);
DEMO_CleanInvalidateCache();
/* Invalidate full buffer. */
DEMO_CleanInvalidateCacheByAddr((void *)buf, size);
return;
}
const uint8_t * buf_u8 = buf;
/* ARM require a 32 byte aligned address. */
uint8_t align_bytes = 32;
uint8_t bits_per_pixel = lv_color_format_get_bpp(cf);
uint16_t align_pixels = align_bytes * 8 / bits_per_pixel;
uint16_t offset_x = 0;
if(area->x1 >= (int32_t)(area->x1 % align_pixels)) {
uint16_t shift_x = area->x1 - (area->x1 % align_pixels);
offset_x = area->x1 - shift_x;
buf_u8 += (shift_x * bits_per_pixel) / 8;
}
if(area->y1) {
uint16_t shift_y = area->y1;
buf_u8 += shift_y * stride;
}
/* Area to clear can start from a different offset in buffer.
* Invalidate the area line by line.
*/
uint16_t line_pixels = offset_x + lv_area_get_width(area);
uint16_t line_size = (line_pixels * bits_per_pixel) / 8;
uint16_t area_height = lv_area_get_height(area);
for(uint16_t y = 0; y < area_height; y++) {
const void * line_addr = buf_u8 + y * stride;
DEMO_CleanInvalidateCacheByAddr((void *)line_addr, line_size);
}
}
#if 0
/**
* @todo
* LVGL needs to use hardware acceleration for buf_copy and do not affect GPU rendering.
*/
void _pxp_buf_copy(void * dest_buf, uint32_t dest_stride, const lv_area_t * dest_area,
void * src_buf, uint32_t src_stride, const lv_area_t * src_area,
lv_color_format_t cf)
{
lv_pxp_reset();
const pxp_pic_copy_config_t picCopyConfig = {
.srcPicBaseAddr = (uint32_t)src_buf,
.srcPitchBytes = src_stride,
.srcOffsetX = src_area->x1,
.srcOffsetY = src_area->y1,
.destPicBaseAddr = (uint32_t)dest_buf,
.destPitchBytes = dest_stride,
.destOffsetX = dest_area->x1,
.destOffsetY = dest_area->y1,
.width = lv_area_get_width(src_area),
.height = lv_area_get_height(src_area),
.pixelFormat = pxp_get_as_px_format(cf)
};
PXP_StartPictureCopy(PXP_ID, &picCopyConfig);
lv_pxp_run();
}
#endif
#endif /*LV_USE_DRAW_PXP*/
+212 -50
View File
@@ -4,7 +4,7 @@
*/
/**
* Copyright 2022, 2023 NXP
* Copyright 2022-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
@@ -17,7 +17,11 @@
#if LV_USE_DRAW_PXP
#include "lv_pxp_cfg.h"
#include "../../../display/lv_display_private.h"
#include "lv_pxp_utils.h"
#if LV_USE_PARALLEL_DRAW_DEBUG
#include "../../../core/lv_global.h"
#endif
/*********************
* DEFINES
@@ -33,6 +37,12 @@
* STATIC PROTOTYPES
**********************/
/*
* Evaluate a task and set the score and preferred PXP unit.
* Return 1 if task is preferred, 0 otherwise (task is not supported).
*/
static int32_t _pxp_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task);
/*
* Dispatch a task to the PXP unit.
* Return 1 if task was dispatched, 0 otherwise (task not supported).
@@ -40,10 +50,9 @@
static int32_t _pxp_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer);
/*
* Evaluate a task and set the score and preferred PXP unit.
* Return 1 if task is preferred, 0 otherwise (task is not supported).
* Delete the PXP draw unit.
*/
static int32_t _pxp_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task);
static int32_t _pxp_delete(lv_draw_unit_t * draw_unit);
#if LV_USE_OS
static void _pxp_render_thread_cb(void * ptr);
@@ -59,6 +68,10 @@ static void _pxp_execute_drawing(lv_draw_pxp_unit_t * u);
* STATIC VARIABLES
**********************/
#if LV_USE_PARALLEL_DRAW_DEBUG
#define _draw_info LV_GLOBAL_DEFAULT()->draw_info
#endif
/**********************
* MACROS
**********************/
@@ -72,13 +85,14 @@ void lv_draw_pxp_init(void)
lv_draw_buf_pxp_init_handlers();
lv_draw_pxp_unit_t * draw_pxp_unit = lv_draw_create_unit(sizeof(lv_draw_pxp_unit_t));
draw_pxp_unit->base_unit.dispatch_cb = _pxp_dispatch;
draw_pxp_unit->base_unit.evaluate_cb = _pxp_evaluate;
draw_pxp_unit->base_unit.dispatch_cb = _pxp_dispatch;
draw_pxp_unit->base_unit.delete_cb = _pxp_delete;
lv_pxp_init();
#if LV_USE_OS
lv_thread_init(&draw_pxp_unit->thread, LV_THREAD_PRIO_HIGH, _pxp_render_thread_cb, 8 * 1024, draw_pxp_unit);
lv_thread_init(&draw_pxp_unit->thread, LV_THREAD_PRIO_HIGH, _pxp_render_thread_cb, 2 * 1024, draw_pxp_unit);
#endif
}
@@ -87,14 +101,96 @@ void lv_draw_pxp_deinit(void)
lv_pxp_deinit();
}
void lv_draw_pxp_rotate(const void * src_buf, void * dest_buf, int32_t src_width, int32_t src_height,
int32_t src_stride, int32_t dest_stride, lv_display_rotation_t rotation,
lv_color_format_t cf)
{
lv_pxp_reset();
/* convert rotation angle */
pxp_rotate_degree_t pxp_rotation;
switch(rotation) {
case LV_DISPLAY_ROTATION_0:
pxp_rotation = kPXP_Rotate0;
break;
case LV_DISPLAY_ROTATION_90:
pxp_rotation = kPXP_Rotate90;
break;
case LV_DISPLAY_ROTATION_180:
pxp_rotation = kPXP_Rotate180;
break;
case LV_DISPLAY_ROTATION_270:
pxp_rotation = kPXP_Rotate270;
break;
default:
pxp_rotation = kPXP_Rotate0;
break;
}
PXP_SetRotateConfig(PXP_ID, kPXP_RotateOutputBuffer, pxp_rotation, kPXP_FlipDisable);
/*Simple blit, no effect - Disable PS buffer*/
PXP_SetProcessSurfacePosition(PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
/*AS buffer - source image*/
pxp_as_buffer_config_t asBufferConfig = {
.pixelFormat = pxp_get_as_px_format(cf),
.bufferAddr = (uint32_t)src_buf,
.pitchBytes = src_stride
};
PXP_SetAlphaSurfaceBufferConfig(PXP_ID, &asBufferConfig);
PXP_SetAlphaSurfacePosition(PXP_ID, 0U, 0U, src_width - 1U, src_height - 1U);
PXP_EnableAlphaSurfaceOverlayColorKey(PXP_ID, false);
/*Output buffer.*/
pxp_output_buffer_config_t outputBufferConfig = {
.pixelFormat = pxp_get_out_px_format(cf),
.interlacedMode = kPXP_OutputProgressive,
.buffer0Addr = (uint32_t)dest_buf,
.buffer1Addr = (uint32_t)0U,
.pitchBytes = dest_stride,
.width = src_width,
.height = src_height
};
PXP_SetOutputBufferConfig(PXP_ID, &outputBufferConfig);
lv_pxp_run();
}
/**********************
* STATIC FUNCTIONS
**********************/
static inline bool _pxp_cf_supported(lv_color_format_t cf)
static inline bool _pxp_src_cf_supported(lv_color_format_t cf)
{
bool is_cf_supported = (cf == LV_COLOR_FORMAT_RGB565 || cf == LV_COLOR_FORMAT_RGB888 ||
cf == LV_COLOR_FORMAT_ARGB8888 || cf == LV_COLOR_FORMAT_XRGB8888);
bool is_cf_supported = false;
switch(cf) {
case LV_COLOR_FORMAT_RGB565:
case LV_COLOR_FORMAT_ARGB8888:
case LV_COLOR_FORMAT_XRGB8888:
is_cf_supported = true;
break;
default:
break;
}
return is_cf_supported;
}
static inline bool _pxp_dest_cf_supported(lv_color_format_t cf)
{
bool is_cf_supported = false;
switch(cf) {
case LV_COLOR_FORMAT_RGB565:
case LV_COLOR_FORMAT_RGB888:
case LV_COLOR_FORMAT_ARGB8888:
case LV_COLOR_FORMAT_XRGB8888:
is_cf_supported = true;
break;
default:
break;
}
return is_cf_supported;
}
@@ -103,8 +199,9 @@ static bool _pxp_draw_img_supported(const lv_draw_image_dsc_t * draw_dsc)
{
const lv_image_dsc_t * img_dsc = draw_dsc->src;
bool has_recolor = (draw_dsc->recolor_opa != LV_OPA_TRANSP);
bool has_transform = (draw_dsc->rotation != 0 || draw_dsc->zoom != LV_SCALE_NONE);
bool has_recolor = (draw_dsc->recolor_opa > LV_OPA_MIN);
bool has_transform = (draw_dsc->rotation != 0 || draw_dsc->scale_x != LV_SCALE_NONE ||
draw_dsc->scale_y != LV_SCALE_NONE);
/* Recolor and transformation are not supported at the same time. */
if(has_recolor && has_transform)
@@ -146,6 +243,11 @@ static int32_t _pxp_evaluate(lv_draw_unit_t * u, lv_draw_task_t * t)
{
LV_UNUSED(u);
const lv_draw_dsc_base_t * draw_dsc_base = (lv_draw_dsc_base_t *) t->draw_dsc;
if(!_pxp_dest_cf_supported(draw_dsc_base->layer->color_format))
return 0;
switch(t->type) {
case LV_DRAW_TASK_TYPE_FILL: {
const lv_draw_fill_dsc_t * draw_dsc = (lv_draw_fill_dsc_t *) t->draw_dsc;
@@ -161,29 +263,11 @@ static int32_t _pxp_evaluate(lv_draw_unit_t * u, lv_draw_task_t * t)
return 1;
}
case LV_DRAW_TASK_TYPE_BG_IMG: {
const lv_draw_bg_image_dsc_t * draw_dsc = (lv_draw_bg_image_dsc_t *) t->draw_dsc;
lv_image_src_t src_type = lv_image_src_get_type(draw_dsc->src);
if(src_type == LV_IMAGE_SRC_SYMBOL)
return 0;
if(!_pxp_cf_supported(draw_dsc->img_header.cf))
return 0;
if(t->preference_score > 70) {
t->preference_score = 70;
t->preferred_draw_unit_id = DRAW_UNIT_ID_PXP;
}
return 1;
}
case LV_DRAW_TASK_TYPE_LAYER: {
const lv_draw_image_dsc_t * draw_dsc = (lv_draw_image_dsc_t *) t->draw_dsc;
lv_layer_t * layer_to_draw = (lv_layer_t *)draw_dsc->src;
lv_draw_buf_t * draw_buf = &layer_to_draw->draw_buf;
if(!_pxp_cf_supported(draw_buf->color_format))
if(!_pxp_src_cf_supported(layer_to_draw->color_format))
return 0;
if(!_pxp_draw_img_supported(draw_dsc))
@@ -200,7 +284,8 @@ static int32_t _pxp_evaluate(lv_draw_unit_t * u, lv_draw_task_t * t)
lv_draw_image_dsc_t * draw_dsc = (lv_draw_image_dsc_t *) t->draw_dsc;
const lv_image_dsc_t * img_dsc = draw_dsc->src;
if(!_pxp_cf_supported(img_dsc->header.cf))
if((!_pxp_src_cf_supported(img_dsc->header.cf)) ||
(!pxp_buf_aligned(img_dsc->data, img_dsc->header.stride)))
return 0;
if(!_pxp_draw_img_supported(draw_dsc))
@@ -227,16 +312,11 @@ static int32_t _pxp_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
if(draw_pxp_unit->task_act)
return 0;
/* Return if target buffer format is not supported. */
if(!_pxp_cf_supported(layer->draw_buf.color_format))
return 0;
/* Try to get an ready to draw. */
lv_draw_task_t * t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_PXP);
/* Return 0 is no selection, some tasks can be supported only by other units. */
if(t == NULL || t->preferred_draw_unit_id != DRAW_UNIT_ID_PXP)
return 0;
return -1;
void * buf = lv_draw_layer_alloc_buf(layer);
if(buf == NULL)
@@ -249,7 +329,8 @@ static int32_t _pxp_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
#if LV_USE_OS
/* Let the render thread work. */
lv_thread_sync_signal(&draw_pxp_unit->sync);
if(draw_pxp_unit->inited)
lv_thread_sync_signal(&draw_pxp_unit->sync);
#else
_pxp_execute_drawing(draw_pxp_unit);
@@ -263,22 +344,46 @@ static int32_t _pxp_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
return 1;
}
static int32_t _pxp_delete(lv_draw_unit_t * draw_unit)
{
#if LV_USE_OS
lv_draw_pxp_unit_t * draw_pxp_unit = (lv_draw_pxp_unit_t *) draw_unit;
LV_LOG_INFO("Cancel PXP draw thread.");
draw_pxp_unit->exit_status = true;
if(draw_pxp_unit->inited)
lv_thread_sync_signal(&draw_pxp_unit->sync);
lv_result_t res = lv_thread_delete(&draw_pxp_unit->thread);
return res;
#else
LV_UNUSED(draw_unit);
return 0;
#endif
}
static void _pxp_execute_drawing(lv_draw_pxp_unit_t * u)
{
lv_draw_task_t * t = u->task_act;
lv_draw_unit_t * draw_unit = (lv_draw_unit_t *)u;
/* Invalidate cache */
lv_layer_t * layer = draw_unit->target_layer;
lv_draw_buf_invalidate_cache(&layer->draw_buf, (const char *)&t->area);
lv_area_t draw_area;
if(!_lv_area_intersect(&draw_area, &t->area, draw_unit->clip_area))
return; /*Fully clipped, nothing to do*/
/* Make area relative to the buffer */
lv_area_move(&draw_area, -layer->buf_area.x1, -layer->buf_area.y1);
/* Invalidate only the drawing area */
lv_draw_buf_invalidate_cache(layer->buf, layer->buf_stride, layer->color_format, &draw_area);
switch(t->type) {
case LV_DRAW_TASK_TYPE_FILL:
lv_draw_pxp_fill(draw_unit, t->draw_dsc, &t->area);
break;
case LV_DRAW_TASK_TYPE_BG_IMG:
lv_draw_pxp_bg_img(draw_unit, t->draw_dsc, &t->area);
break;
case LV_DRAW_TASK_TYPE_IMAGE:
lv_draw_pxp_img(draw_unit, t->draw_dsc, &t->area);
break;
@@ -288,6 +393,51 @@ static void _pxp_execute_drawing(lv_draw_pxp_unit_t * u)
default:
break;
}
#if LV_USE_PARALLEL_DRAW_DEBUG
/*Layers manage it for themselves*/
if(t->type != LV_DRAW_TASK_TYPE_LAYER) {
lv_area_t draw_area;
if(!_lv_area_intersect(&draw_area, &t->area, u->base_unit.clip_area))
return;
int32_t idx = 0;
lv_draw_unit_t * draw_unit_tmp = _draw_info.unit_head;
while(draw_unit_tmp != (lv_draw_unit_t *)u) {
draw_unit_tmp = draw_unit_tmp->next;
idx++;
}
lv_draw_rect_dsc_t rect_dsc;
lv_draw_rect_dsc_init(&rect_dsc);
rect_dsc.bg_color = lv_palette_main(idx % _LV_PALETTE_LAST);
rect_dsc.border_color = rect_dsc.bg_color;
rect_dsc.bg_opa = LV_OPA_10;
rect_dsc.border_opa = LV_OPA_80;
rect_dsc.border_width = 1;
lv_draw_sw_fill((lv_draw_unit_t *)u, &rect_dsc, &draw_area);
lv_point_t txt_size;
lv_text_get_size(&txt_size, "W", LV_FONT_DEFAULT, 0, 0, 100, LV_TEXT_FLAG_NONE);
lv_area_t txt_area;
txt_area.x1 = draw_area.x1;
txt_area.y1 = draw_area.y1;
txt_area.x2 = draw_area.x1 + txt_size.x - 1;
txt_area.y2 = draw_area.y1 + txt_size.y - 1;
lv_draw_rect_dsc_init(&rect_dsc);
rect_dsc.bg_color = lv_color_white();
lv_draw_sw_fill((lv_draw_unit_t *)u, &rect_dsc, &txt_area);
char buf[8];
lv_snprintf(buf, sizeof(buf), "%d", idx);
lv_draw_label_dsc_t label_dsc;
lv_draw_label_dsc_init(&label_dsc);
label_dsc.color = lv_color_black();
label_dsc.text = buf;
lv_draw_sw_label((lv_draw_unit_t *)u, &label_dsc, &txt_area);
}
#endif
}
#if LV_USE_OS
@@ -296,25 +446,37 @@ static void _pxp_render_thread_cb(void * ptr)
lv_draw_pxp_unit_t * u = ptr;
lv_thread_sync_init(&u->sync);
u->inited = true;
while(1) {
/*
* Wait for sync if no task received or _draw_task_buf is empty.
* The thread will have to run as much as there are pending tasks.
*/
/* Wait for sync if there is no task set. */
while(u->task_act == NULL) {
if(u->exit_status)
break;
lv_thread_sync_wait(&u->sync);
}
if(u->exit_status) {
LV_LOG_INFO("Ready to exit PXP draw thread.");
break;
}
_pxp_execute_drawing(u);
/* Cleanup. */
/* Signal the ready state to dispatcher. */
u->task_act->state = LV_DRAW_TASK_STATE_READY;
/* Cleanup. */
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();
}
u->inited = false;
lv_thread_sync_delete(&u->sync);
LV_LOG_INFO("Exit PXP draw thread.");
}
#endif
+5 -13
View File
@@ -4,7 +4,7 @@
*/
/**
* Copyright 2022, 2023 NXP
* Copyright 2022-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
@@ -33,16 +33,7 @@ extern "C" {
* TYPEDEFS
**********************/
typedef lv_layer_t lv_pxp_layer_t;
typedef struct {
lv_draw_unit_t base_unit;
lv_draw_task_t * task_act;
#if LV_USE_OS
lv_thread_sync_t sync;
lv_thread_t thread;
#endif
} lv_draw_pxp_unit_t;
typedef lv_draw_sw_unit_t lv_draw_pxp_unit_t;
/**********************
* GLOBAL PROTOTYPES
@@ -54,8 +45,9 @@ void lv_draw_pxp_init(void);
void lv_draw_pxp_deinit(void);
void lv_draw_pxp_bg_img(lv_draw_unit_t * draw_unit, const lv_draw_bg_image_dsc_t * dsc,
const lv_area_t * coords);
void lv_draw_pxp_rotate(const void * src_buf, void * dest_buf, int32_t src_width, int32_t src_height,
int32_t src_stride, int32_t dest_stride, lv_display_rotation_t rotation,
lv_color_format_t cf);
void lv_draw_pxp_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc,
const lv_area_t * coords);
-93
View File
@@ -1,93 +0,0 @@
/**
* @file lv_draw_pxp_bg_img.c
*
*/
/**
* Copyright 2023 NXP
*
* SPDX-License-Identifier: MIT
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_pxp.h"
#if LV_USE_DRAW_PXP
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_pxp_bg_img(lv_draw_unit_t * draw_unit, const lv_draw_bg_image_dsc_t * dsc,
const lv_area_t * coords)
{
if(dsc->src == NULL) return;
if(dsc->opa <= LV_OPA_MIN) return;
lv_area_t clip_area;
if(!_lv_area_intersect(&clip_area, coords, draw_unit->clip_area)) {
return;
}
const lv_area_t * clip_area_ori = draw_unit->clip_area;
draw_unit->clip_area = &clip_area;
lv_draw_image_dsc_t img_dsc;
lv_draw_image_dsc_init(&img_dsc);
img_dsc.recolor = dsc->recolor;
img_dsc.recolor_opa = dsc->recolor_opa;
img_dsc.opa = dsc->opa;
img_dsc.src = dsc->src;
/*Center align*/
if(dsc->tiled == false) {
lv_area_t area;
area.x1 = coords->x1 + lv_area_get_width(coords) / 2 - dsc->img_header.w / 2;
area.y1 = coords->y1 + lv_area_get_height(coords) / 2 - dsc->img_header.h / 2;
area.x2 = area.x1 + dsc->img_header.w - 1;
area.y2 = area.y1 + dsc->img_header.h - 1;
lv_draw_pxp_img(draw_unit, &img_dsc, &area);
}
else {
lv_area_t area;
area.y1 = coords->y1;
area.y2 = area.y1 + dsc->img_header.h - 1;
for(; area.y1 <= coords->y2; area.y1 += dsc->img_header.h, area.y2 += dsc->img_header.h) {
area.x1 = coords->x1;
area.x2 = area.x1 + dsc->img_header.w - 1;
for(; area.x1 <= coords->x2; area.x1 += dsc->img_header.w, area.x2 += dsc->img_header.w) {
lv_draw_pxp_img(draw_unit, &img_dsc, &area);
}
}
}
draw_unit->clip_area = clip_area_ori;
}
#endif /*LV_USE_DRAW_PXP*/
+4 -8
View File
@@ -4,7 +4,7 @@
*/
/**
* Copyright 2020-2023 NXP
* Copyright 2020-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
@@ -56,21 +56,17 @@ void lv_draw_pxp_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc
lv_area_t rel_coords;
lv_area_copy(&rel_coords, coords);
lv_area_move(&rel_coords, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
lv_area_move(&rel_coords, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_t rel_clip_area;
lv_area_copy(&rel_clip_area, draw_unit->clip_area);
lv_area_move(&rel_clip_area, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
lv_area_move(&rel_clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_t blend_area;
if(!_lv_area_intersect(&blend_area, &rel_coords, &rel_clip_area))
return; /*Fully clipped, nothing to do*/
uint8_t * dest_buf = layer->draw_buf.buf;
int32_t dest_stride = lv_draw_buf_get_stride(&layer->draw_buf);
lv_color_format_t dest_cf = layer->draw_buf.color_format;
_pxp_fill(dest_buf, &blend_area, dest_stride, dest_cf, dsc);
_pxp_fill(layer->buf, &blend_area, layer->buf_stride, layer->color_format, dsc);
}
/**********************
+26 -25
View File
@@ -4,7 +4,7 @@
*/
/**
* Copyright 2020-2023 NXP
* Copyright 2020-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
@@ -71,14 +71,14 @@ void lv_draw_pxp_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dsc
lv_area_t rel_coords;
lv_area_copy(&rel_coords, coords);
lv_area_move(&rel_coords, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
lv_area_move(&rel_coords, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_t rel_clip_area;
lv_area_copy(&rel_clip_area, draw_unit->clip_area);
lv_area_move(&rel_clip_area, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
lv_area_move(&rel_clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_t blend_area;
bool has_transform = dsc->rotation != 0 || dsc->zoom != LV_SCALE_NONE;
bool has_transform = (dsc->rotation != 0 || dsc->scale_x != LV_SCALE_NONE || dsc->scale_y != LV_SCALE_NONE);
if(has_transform)
lv_area_copy(&blend_area, &rel_coords);
else if(!_lv_area_intersect(&blend_area, &rel_coords, &rel_clip_area))
@@ -87,17 +87,17 @@ void lv_draw_pxp_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dsc
const uint8_t * src_buf = img_dsc->data;
lv_area_t src_area;
src_area.x1 = blend_area.x1 - (coords->x1 - layer->draw_buf_ofs.x);
src_area.y1 = blend_area.y1 - (coords->y1 - layer->draw_buf_ofs.y);
src_area.x1 = blend_area.x1 - (coords->x1 - layer->buf_area.x1);
src_area.y1 = blend_area.y1 - (coords->y1 - layer->buf_area.y1);
src_area.x2 = src_area.x1 + lv_area_get_width(coords) - 1;
src_area.y2 = src_area.y1 + lv_area_get_height(coords) - 1;
int32_t src_stride = img_dsc->header.stride;
lv_color_format_t src_cf = img_dsc->header.cf;
uint8_t * dest_buf = layer->draw_buf.buf;
int32_t dest_stride = lv_draw_buf_get_stride(&layer->draw_buf);
lv_color_format_t dest_cf = layer->draw_buf.color_format;
bool has_recolor = (dsc->recolor_opa != LV_OPA_TRANSP);
uint8_t * dest_buf = layer->buf;
int32_t dest_stride = layer->buf_stride;
lv_color_format_t dest_cf = layer->color_format;
bool has_recolor = (dsc->recolor_opa > LV_OPA_MIN);
if(has_recolor && !has_transform)
_pxp_blit_recolor(dest_buf, &blend_area, dest_stride, dest_cf,
@@ -194,10 +194,11 @@ static void _pxp_blit_transform(uint8_t * dest_buf, const lv_area_t * dest_area,
int32_t piv_offset_x = 0;
int32_t piv_offset_y = 0;
int32_t trim_size = 0;
int32_t trim_x = 0;
int32_t trim_y = 0;
bool has_rotation = (dsc->rotation != 0);
bool has_scale = (dsc->zoom != LV_SCALE_NONE);
bool has_scale = (dsc->scale_x != LV_SCALE_NONE || dsc->scale_y != LV_SCALE_NONE);
uint8_t src_px_size = lv_color_format_get_size(src_cf);
uint8_t dest_px_size = lv_color_format_get_size(dest_cf);
@@ -237,21 +238,21 @@ static void _pxp_blit_transform(uint8_t * dest_buf, const lv_area_t * dest_area,
}
if(has_scale) {
float scale_factor_fp = (float)dsc->zoom / LV_SCALE_NONE;
int32_t scale_factor_int = (int32_t)scale_factor_fp;
float fp_scale_x = (float)dsc->scale_x / LV_SCALE_NONE;
float fp_scale_y = (float)dsc->scale_y / LV_SCALE_NONE;
int32_t int_scale_x = (int32_t)fp_scale_x;
int32_t int_scale_y = (int32_t)fp_scale_y;
/*Any scale_factor in (k, k + 1] will result in a trim equal to k*/
if(scale_factor_fp == scale_factor_int)
trim_size = scale_factor_int - 1;
else
trim_size = scale_factor_int;
trim_x = (fp_scale_x == int_scale_x) ? int_scale_x - 1 : int_scale_x;
trim_y = (fp_scale_y == int_scale_y) ? int_scale_y - 1 : int_scale_y;
dest_w = src_w * scale_factor_fp + trim_size;
dest_h = src_h * scale_factor_fp + trim_size;
dest_w = src_w * fp_scale_x + trim_x;
dest_h = src_h * fp_scale_y + trim_y;
/*Final pivot offset = scale_factor * rotation_pivot_offset + scaling_pivot_offset*/
piv_offset_x = floor(scale_factor_fp * piv_offset_x) - floor((scale_factor_fp - 1) * pivot.x);
piv_offset_y = floor(scale_factor_fp * piv_offset_y) - floor((scale_factor_fp - 1) * pivot.y);
piv_offset_x = floor(fp_scale_x * piv_offset_x) - floor((fp_scale_x - 1) * pivot.x);
piv_offset_y = floor(fp_scale_y * piv_offset_y) - floor((fp_scale_y - 1) * pivot.y);
}
/*PS buffer - source image*/
@@ -264,7 +265,7 @@ static void _pxp_blit_transform(uint8_t * dest_buf, const lv_area_t * dest_area,
.pitchBytes = src_stride
};
PXP_SetProcessSurfaceBufferConfig(PXP_ID, &psBufferConfig);
PXP_SetProcessSurfacePosition(PXP_ID, 0U, 0U, dest_w - trim_size - 1U, dest_h - trim_size - 1U);
PXP_SetProcessSurfacePosition(PXP_ID, 0U, 0U, dest_w - trim_x - 1U, dest_h - trim_y - 1U);
if(has_scale)
PXP_SetProcessSurfaceScaler(PXP_ID, src_w, src_h, dest_w, dest_h);
@@ -279,8 +280,8 @@ static void _pxp_blit_transform(uint8_t * dest_buf, const lv_area_t * dest_area,
.buffer0Addr = (uint32_t)(dest_buf + dest_stride * (dest_area->y1 + piv_offset_y) + dest_px_size * (dest_area->x1 + piv_offset_x)),
.buffer1Addr = (uint32_t)0U,
.pitchBytes = dest_stride,
.width = dest_w - trim_size,
.height = dest_h - trim_size
.width = dest_w - trim_x,
.height = dest_h - trim_y
};
PXP_SetOutputBufferConfig(PXP_ID, &outputBufferConfig);
+103 -7
View File
@@ -4,7 +4,7 @@
*/
/**
* Copyright 2023 NXP
* Copyright 2023-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
@@ -18,6 +18,9 @@
#if LV_USE_DRAW_PXP
#include "../../../stdlib/lv_string.h"
#if LV_USE_PARALLEL_DRAW_DEBUG
#include "../../../core/lv_global.h"
#endif
/*********************
* DEFINES
@@ -35,6 +38,10 @@
* STATIC VARIABLES
**********************/
#if LV_USE_PARALLEL_DRAW_DEBUG
#define _draw_info LV_GLOBAL_DEFAULT()->draw_info
#endif
/**********************
* MACROS
**********************/
@@ -50,20 +57,109 @@ void lv_draw_pxp_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * d
/*It can happen that nothing was draw on a layer and therefore its buffer is not allocated.
*In this case just return. */
if(layer_to_draw->draw_buf.buf == NULL)
if(layer_to_draw->buf == NULL)
return;
lv_image_dsc_t img_dsc = { 0 };
img_dsc.header.w = layer_to_draw->draw_buf.width;
img_dsc.header.h = layer_to_draw->draw_buf.height;
img_dsc.header.cf = layer_to_draw->draw_buf.color_format;
img_dsc.data = lv_draw_buf_get_buf(&layer_to_draw->draw_buf);
uint32_t width = lv_area_get_width(&layer_to_draw->buf_area);
uint32_t height = lv_area_get_height(&layer_to_draw->buf_area);
const lv_area_t area = {
.x1 = 0,
.y1 = 0,
.x2 = width - 1,
.y2 = height - 1
};
lv_draw_buf_invalidate_cache(layer_to_draw->buf, layer_to_draw->buf_stride, layer_to_draw->color_format, &area);
lv_image_dsc_t img_dsc = {0};
img_dsc.header.w = width;
img_dsc.header.h = height;
img_dsc.header.cf = layer_to_draw->color_format;
img_dsc.header.stride = layer_to_draw->buf_stride;
img_dsc.data = layer_to_draw->buf;
lv_draw_image_dsc_t new_draw_dsc;
lv_memcpy(&new_draw_dsc, draw_dsc, sizeof(lv_draw_image_dsc_t));
new_draw_dsc.src = &img_dsc;
lv_draw_pxp_img(draw_unit, &new_draw_dsc, coords);
#if LV_USE_LAYER_DEBUG || LV_USE_PARALLEL_DRAW_DEBUG
lv_area_t area_rot;
lv_area_copy(&area_rot, 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(&area_rot, w, h, draw_dsc->rotation, draw_dsc->scale_x, draw_dsc->scale_y,
&draw_dsc->pivot);
area_rot.x1 += coords->x1;
area_rot.y1 += coords->y1;
area_rot.x2 += coords->x1;
area_rot.y2 += coords->y1;
}
lv_area_t draw_area;
if(!_lv_area_intersect(&draw_area, &area_rot, draw_unit->clip_area)) return;
#endif
#if LV_USE_LAYER_DEBUG
lv_draw_fill_dsc_t fill_dsc;
lv_draw_fill_dsc_init(&fill_dsc);
fill_dsc.color = lv_color_hex(layer_to_draw->color_format == LV_COLOR_FORMAT_ARGB8888 ? 0xff0000 : 0x00ff00);
fill_dsc.opa = LV_OPA_20;
lv_draw_sw_fill(draw_unit, &fill_dsc, &area_rot);
lv_draw_border_dsc_t border_dsc;
lv_draw_border_dsc_init(&border_dsc);
border_dsc.color = fill_dsc.color;
border_dsc.opa = LV_OPA_60;
border_dsc.width = 2;
lv_draw_sw_border(draw_unit, &border_dsc, &area_rot);
#endif
#if LV_USE_PARALLEL_DRAW_DEBUG
uint32_t idx = 0;
lv_draw_unit_t * draw_unit_tmp = _draw_info.unit_head;
while(draw_unit_tmp != draw_unit) {
draw_unit_tmp = draw_unit_tmp->next;
idx++;
}
lv_draw_fill_dsc_t fill_dsc;
lv_draw_rect_dsc_init(&fill_dsc);
fill_dsc.color = lv_palette_main(idx % _LV_PALETTE_LAST);
fill_dsc.opa = LV_OPA_10;
lv_draw_sw_fill(draw_unit, &fill_dsc, &area_rot);
lv_draw_border_dsc_t border_dsc;
lv_draw_border_dsc_init(&border_dsc);
border_dsc.color = lv_palette_main(idx % _LV_PALETTE_LAST);
border_dsc.opa = LV_OPA_100;
border_dsc.width = 2;
lv_draw_sw_border(draw_unit, &border_dsc, &area_rot);
lv_point_t txt_size;
lv_text_get_size(&txt_size, "W", LV_FONT_DEFAULT, 0, 0, 100, LV_TEXT_FLAG_NONE);
lv_area_t txt_area;
txt_area.x1 = draw_area.x1;
txt_area.x2 = draw_area.x1 + txt_size.x - 1;
txt_area.y2 = draw_area.y2;
txt_area.y1 = draw_area.y2 - txt_size.y + 1;
lv_draw_fill_dsc_init(&fill_dsc);
fill_dsc.color = lv_color_black();
lv_draw_sw_fill(draw_unit, &fill_dsc, &txt_area);
char buf[8];
lv_snprintf(buf, sizeof(buf), "%d", idx);
lv_draw_label_dsc_t label_dsc;
lv_draw_label_dsc_init(&label_dsc);
label_dsc.color = lv_color_white();
label_dsc.text = buf;
lv_draw_sw_label(draw_unit, &label_dsc, &txt_area);
#endif
}
#endif /*LV_USE_DRAW_PXP*/
-4
View File
@@ -48,10 +48,6 @@ void lv_pxp_init(void)
{
_pxp_cfg = pxp_get_default_cfg();
if(!_pxp_cfg || !_pxp_cfg->pxp_interrupt_deinit || !_pxp_cfg->pxp_interrupt_init ||
!_pxp_cfg->pxp_run || !_pxp_cfg->pxp_wait)
LV_LOG_ERROR("PXP configuration error.");
PXP_Init(PXP_ID);
PXP_EnableCsc1(PXP_ID, false); /*Disable CSC1, it is enabled by default.*/
+3 -5
View File
@@ -4,7 +4,7 @@
*/
/**
* Copyright 2020, 2022, 2023 NXP
* Copyright 2020, 2022-2023 NXP
*
* SPDX-License-Identifier: MIT
*/
@@ -16,6 +16,7 @@
#include "lv_pxp_osa.h"
#if LV_USE_DRAW_PXP
#include "lv_pxp_utils.h"
#include "../../../misc/lv_log.h"
#include "fsl_pxp.h"
@@ -115,10 +116,7 @@ static void _pxp_interrupt_init(void)
{
#if defined(SDK_OS_FREE_RTOS)
xPXPIdleSemaphore = xSemaphoreCreateBinary();
if(xPXPIdleSemaphore == NULL) {
LV_LOG_ERROR("xSemaphoreCreateBinary failed!");
return;
}
PXP_ASSERT_MSG(xPXPIdleSemaphore, "xSemaphoreCreateBinary failed!");
NVIC_SetPriority(PXP_IRQ_ID, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1);
#endif
+1 -1
View File
@@ -4,7 +4,7 @@
*/
/**
* Copyright 2020, 2022, 2023 NXP
* Copyright 2020, 2022-2023 NXP
*
* SPDX-License-Identifier: MIT
*/
+20 -25
View File
@@ -4,7 +4,7 @@
*/
/**
* Copyright 2023 NXP
* Copyright 2023-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
@@ -42,15 +42,9 @@ pxp_output_pixel_format_t pxp_get_out_px_format(lv_color_format_t cf)
pxp_output_pixel_format_t out_px_format = kPXP_OutputPixelFormatRGB565;
switch(cf) {
/*2 byte (+alpha) formats*/
case LV_COLOR_FORMAT_RGB565:
out_px_format = kPXP_OutputPixelFormatRGB565;
break;
case LV_COLOR_FORMAT_RGB565A8:
LV_ASSERT_MSG(false, "Unsupported color format.");
break;
/*3 byte (+alpha) formats*/
case LV_COLOR_FORMAT_RGB888:
out_px_format = kPXP_OutputPixelFormatRGB888P;
break;
@@ -62,7 +56,7 @@ pxp_output_pixel_format_t pxp_get_out_px_format(lv_color_format_t cf)
break;
default:
LV_ASSERT_MSG(false, "Unsupported color format.");
PXP_ASSERT_MSG(false, "Unsupported color format.");
break;
}
@@ -74,17 +68,11 @@ pxp_as_pixel_format_t pxp_get_as_px_format(lv_color_format_t cf)
pxp_as_pixel_format_t as_px_format = kPXP_AsPixelFormatRGB565;
switch(cf) {
/*2 byte (+alpha) formats*/
case LV_COLOR_FORMAT_RGB565:
as_px_format = kPXP_AsPixelFormatRGB565;
break;
case LV_COLOR_FORMAT_RGB565A8:
LV_ASSERT_MSG(false, "Unsupported color format.");
break;
/*3 byte (+alpha) formats*/
case LV_COLOR_FORMAT_RGB888:
LV_ASSERT_MSG(false, "Unsupported color format.");
PXP_ASSERT_MSG(false, "Unsupported color format.");
break;
case LV_COLOR_FORMAT_ARGB8888:
as_px_format = kPXP_AsPixelFormatARGB8888;
@@ -94,7 +82,7 @@ pxp_as_pixel_format_t pxp_get_as_px_format(lv_color_format_t cf)
break;
default:
LV_ASSERT_MSG(false, "Unsupported color format.");
PXP_ASSERT_MSG(false, "Unsupported color format.");
break;
}
@@ -106,24 +94,18 @@ pxp_ps_pixel_format_t pxp_get_ps_px_format(lv_color_format_t cf)
pxp_ps_pixel_format_t ps_px_format = kPXP_PsPixelFormatRGB565;
switch(cf) {
/*2 byte (+alpha) formats*/
case LV_COLOR_FORMAT_RGB565:
ps_px_format = kPXP_PsPixelFormatRGB565;
break;
case LV_COLOR_FORMAT_RGB565A8:
LV_ASSERT_MSG(false, "Unsupported color format.");
break;
/*3 byte (+alpha) formats*/
case LV_COLOR_FORMAT_RGB888:
LV_ASSERT_MSG(false, "Unsupported color format.");
PXP_ASSERT_MSG(false, "Unsupported color format.");
break;
case LV_COLOR_FORMAT_ARGB8888:
#if (!(defined(FSL_FEATURE_PXP_HAS_NO_EXTEND_PIXEL_FORMAT) && FSL_FEATURE_PXP_HAS_NO_EXTEND_PIXEL_FORMAT)) && \
(!(defined(FSL_FEATURE_PXP_V3) && FSL_FEATURE_PXP_V3))
ps_px_format = kPXP_PsPixelFormatARGB8888;
#else
LV_ASSERT_MSG(false, "Unsupported color format.");
PXP_ASSERT_MSG(false, "Unsupported color format.");
#endif
break;
case LV_COLOR_FORMAT_XRGB8888:
@@ -136,13 +118,26 @@ pxp_ps_pixel_format_t pxp_get_ps_px_format(lv_color_format_t cf)
break;
default:
LV_ASSERT_MSG(false, "Unsupported color format.");
PXP_ASSERT_MSG(false, "Unsupported color format.");
break;
}
return ps_px_format;
}
bool pxp_buf_aligned(const void * buf, uint32_t stride)
{
/* Test for pointer alignment */
if((uintptr_t)buf % 64)
return false;
/* Test for invalid stride (no stride alignment required) */
if(stride == 0)
return false;
return true;
}
/**********************
* STATIC FUNCTIONS
**********************/
+11 -1
View File
@@ -4,7 +4,7 @@
*/
/**
* Copyright 2023 NXP
* Copyright 2023-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
@@ -29,6 +29,14 @@ extern "C" {
* DEFINES
*********************/
#if LV_USE_PXP_ASSERT
#define PXP_ASSERT(expr) LV_ASSERT(expr)
#define PXP_ASSERT_MSG(expr, msg) LV_ASSERT_MSG(expr, msg)
#else
#define PXP_ASSERT(expr)
#define PXP_ASSERT_MSG(expr, msg) LV_LOG_ERROR(msg)
#endif
/**********************
* TYPEDEFS
**********************/
@@ -47,6 +55,8 @@ pxp_as_pixel_format_t pxp_get_as_px_format(lv_color_format_t cf);
pxp_ps_pixel_format_t pxp_get_ps_px_format(lv_color_format_t cf);
bool pxp_buf_aligned(const void * buf, uint32_t stride);
/**********************
* MACROS
**********************/
+47 -79
View File
@@ -4,7 +4,7 @@
*/
/**
* Copyright 2023 NXP
* Copyright 2023-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
@@ -17,7 +17,6 @@
#if LV_USE_DRAW_VGLITE
#include "lv_vglite_buf.h"
#include "lv_vglite_matrix.h"
#include "lv_vglite_utils.h"
#include "lvgl_support.h"
@@ -36,14 +35,12 @@
static void * _buf_malloc(size_t size_bytes, lv_color_format_t cf);
static void * _align_buf(void * buf, lv_color_format_t cf);
static void * _buf_align(void * buf, lv_color_format_t cf);
static void _invalidate_cache(lv_draw_buf_t * draw_buf, const char * area);
static void _invalidate_cache(void * buf, uint32_t stride, lv_color_format_t cf, const lv_area_t * area);
static uint32_t _width_to_stride(uint32_t w, lv_color_format_t cf);
static void * _go_to_xy(lv_draw_buf_t * draw_buf, int32_t x, int32_t y);
/**********************
* STATIC VARIABLES
**********************/
@@ -61,7 +58,7 @@ void lv_draw_buf_vglite_init_handlers(void)
lv_draw_buf_handlers_t * handlers = lv_draw_buf_get_handlers();
handlers->buf_malloc_cb = _buf_malloc;
handlers->align_pointer_cb = _align_buf;
handlers->align_pointer_cb = _buf_align;
handlers->invalidate_cache_cb = _invalidate_cache;
handlers->width_to_stride_cb = _width_to_stride;
}
@@ -80,7 +77,7 @@ static void * _buf_malloc(size_t size_bytes, lv_color_format_t cf)
return lv_malloc(size_bytes);
}
static void * _align_buf(void * buf, lv_color_format_t cf)
static void * _buf_align(void * buf, lv_color_format_t cf)
{
uint8_t align_bytes = vglite_get_alignment(cf);
@@ -93,17 +90,54 @@ static void * _align_buf(void * buf, lv_color_format_t cf)
return buf_u8;
}
static void _invalidate_cache(lv_draw_buf_t * draw_buf, const char * area)
static void _invalidate_cache(void * buf, uint32_t stride, lv_color_format_t cf, const lv_area_t * area)
{
LV_UNUSED(draw_buf);
LV_UNUSED(area);
if(area->y1 == 0) {
uint16_t size = stride * lv_area_get_height(area);
DEMO_CleanInvalidateCache();
/* Invalidate full buffer. */
DEMO_CleanInvalidateCacheByAddr((void *)buf, size);
return;
}
const uint8_t * buf_u8 = buf;
/* ARM require a 32 byte aligned address. */
uint8_t align_bytes = 32;
uint8_t bits_per_pixel = lv_color_format_get_bpp(cf);
uint16_t align_pixels = align_bytes * 8 / bits_per_pixel;
uint16_t offset_x = 0;
if(area->x1 >= (int32_t)(area->x1 % align_pixels)) {
uint16_t shift_x = area->x1 - (area->x1 % align_pixels);
offset_x = area->x1 - shift_x;
buf_u8 += (shift_x * bits_per_pixel) / 8;
}
if(area->y1) {
uint16_t shift_y = area->y1;
buf_u8 += shift_y * stride;
}
/* Area to clear can start from a different offset in buffer.
* Invalidate the area line by line.
*/
uint16_t line_pixels = offset_x + lv_area_get_width(area);
uint16_t line_size = (line_pixels * bits_per_pixel) / 8;
uint16_t area_height = lv_area_get_height(area);
for(uint16_t y = 0; y < area_height; y++) {
const void * line_addr = buf_u8 + y * stride;
DEMO_CleanInvalidateCacheByAddr((void *)line_addr, line_size);
}
}
static uint32_t _width_to_stride(uint32_t w, lv_color_format_t cf)
{
uint8_t bits_per_pixel = vglite_get_px_size(cf);
uint8_t bits_per_pixel = lv_color_format_get_bpp(cf);
uint32_t width_bits = (w * bits_per_pixel + 7) & ~7;
uint32_t width_bytes = width_bits / 8;
uint8_t align_bytes = vglite_get_alignment(cf);
@@ -111,70 +145,4 @@ static uint32_t _width_to_stride(uint32_t w, lv_color_format_t cf)
return (width_bytes + align_bytes - 1) & ~(align_bytes - 1);
}
/**
* @todo
* LVGL needs to use hardware acceleration for buf_copy and do not affect GPU rendering.
*/
#if 0
static void _vglite_buf_clear(lv_draw_buf_t * draw_buf, const lv_area_t * area)
{
uint32_t stride = lv_draw_buf_get_stride(draw_buf);
/* Set vgbuf structure. */
vg_lite_buffer_t vgbuf;
vglite_set_buf(&vgbuf, draw_buf->buf, draw_buf->width, draw_buf->height, stride, draw_buf->color_format);
vg_lite_color_t vgcol = 0;
vg_lite_rectangle_t rect = {
.x = area->x1,
.y = area->y1,
.width = lv_area_get_width(area),
.height = lv_area_get_height(area)
};
vg_lite_error_t err = vg_lite_clear(&vgbuf, &rect, vgcol);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Clear failed.");
vglite_run();
}
static void _vglite_buf_copy(void * dest_buf, uint32_t dest_stride, const lv_area_t * dest_area,
void * src_buf, uint32_t src_stride, const lv_area_t * src_area,
lv_color_format_t cf)
{
/* Set src_vgbuf structure. */
vg_lite_buffer_t src_vgbuf;
vglite_set_buf(&src_vgbuf, src_buf, lv_area_get_width(src_area), lv_area_get_height(src_area), src_stride, cf);
/* Set dest_vgbuf structure. */
vg_lite_buffer_t dest_vgbuf;
vglite_set_buf(&dest_vgbuf, dest_buf, lv_area_get_width(dest_area), lv_area_get_height(dest_area), dest_stride, cf);
uint32_t rect[] = {
(uint32_t)src_area->x1, /* start x */
(uint32_t)src_area->y1, /* start y */
(uint32_t)lv_area_get_width(src_area), /* width */
(uint32_t)lv_area_get_height(src_area) /* height */
};
/* Set scissor. */
vglite_set_scissor(dest_area);
/* Set vgmatrix. */
vglite_set_translation_matrix(dest_area);
vg_lite_matrix_t * vgmatrix = vglite_get_matrix();
vg_lite_error_t err = vg_lite_blit_rect(&dest_vgbuf, &src_vgbuf, rect, vgmatrix,
VG_LITE_BLEND_NONE, 0xFFFFFFFFU, VG_LITE_FILTER_POINT);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Blit rectangle failed.");
vglite_run();
/* Disable scissor. */
vglite_disable_scissor();
}
#endif
#endif /*LV_USE_DRAW_VGLITE*/
+179 -83
View File
@@ -4,7 +4,7 @@
*/
/**
* Copyright 2023 NXP
* Copyright 2023-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
@@ -19,7 +19,9 @@
#include "lv_vglite_buf.h"
#include "lv_vglite_utils.h"
#include "../../../display/lv_display_private.h"
#if LV_USE_PARALLEL_DRAW_DEBUG
#include "../../../core/lv_global.h"
#endif
/*********************
* DEFINES
@@ -27,7 +29,7 @@
#define DRAW_UNIT_ID_VGLITE 2
#if LV_USE_OS
#if LV_USE_VGLITE_DRAW_ASYNC
#define VGLITE_TASK_BUF_SIZE 10
#endif
@@ -35,7 +37,7 @@
* TYPEDEFS
**********************/
#if LV_USE_OS
#if LV_USE_VGLITE_DRAW_ASYNC
/**
* Structure of pending vglite draw task
*/
@@ -50,16 +52,21 @@ typedef struct _vglite_draw_task_t {
**********************/
/*
* Dispatch a task to the VGLite unit.
* Evaluate a task and set the score and preferred VGLite draw unit.
* Return 1 if task is preferred, 0 otherwise (task is not supported).
*/
static int32_t _vglite_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task);
/*
* Dispatch (assign) a task to VGLite draw unit (itself).
* Return 1 if task was dispatched, 0 otherwise (task not supported).
*/
static int32_t _vglite_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer);
/*
* Evaluate a task and set the score and preferred VGLite unit.
* Return 1 if task is preferred, 0 otherwise (task is not supported).
* Delete the VGLite draw unit.
*/
static int32_t _vglite_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task);
static int32_t _vglite_delete(lv_draw_unit_t * draw_unit);
#if LV_USE_OS
static void _vglite_render_thread_cb(void * ptr);
@@ -71,7 +78,11 @@ static void _vglite_execute_drawing(lv_draw_vglite_unit_t * u);
* STATIC VARIABLES
**********************/
#if LV_USE_OS
#if LV_USE_PARALLEL_DRAW_DEBUG
#define _draw_info LV_GLOBAL_DEFAULT()->draw_info
#endif
#if LV_USE_VGLITE_DRAW_ASYNC
/*
* Circular buffer to hold the queued and the flushed tasks.
* Two indexes, _head and _tail, are used to signal the beginning
@@ -95,11 +106,12 @@ void lv_draw_vglite_init(void)
lv_draw_buf_vglite_init_handlers();
lv_draw_vglite_unit_t * draw_vglite_unit = lv_draw_create_unit(sizeof(lv_draw_vglite_unit_t));
draw_vglite_unit->base_unit.dispatch_cb = _vglite_dispatch;
draw_vglite_unit->base_unit.evaluate_cb = _vglite_evaluate;
draw_vglite_unit->base_unit.dispatch_cb = _vglite_dispatch;
draw_vglite_unit->base_unit.delete_cb = _vglite_delete;
#if LV_USE_OS
lv_thread_init(&draw_vglite_unit->thread, LV_THREAD_PRIO_HIGH, _vglite_render_thread_cb, 8 * 1024, draw_vglite_unit);
lv_thread_init(&draw_vglite_unit->thread, LV_THREAD_PRIO_HIGH, _vglite_render_thread_cb, 2 * 1024, draw_vglite_unit);
#endif
}
@@ -111,19 +123,70 @@ void lv_draw_vglite_deinit(void)
* STATIC FUNCTIONS
**********************/
static inline bool _vglite_cf_supported(lv_color_format_t cf)
static inline bool _vglite_src_cf_supported(lv_color_format_t cf)
{
/*Add here the platform specific code for supported formats.*/
bool is_cf_supported = false;
bool is_cf_unsupported = (cf == LV_COLOR_FORMAT_RGB565A8 || cf == LV_COLOR_FORMAT_RGB888);
switch(cf) {
#if CHIPID == 0x255 || CHIPID == 0x555
case LV_COLOR_FORMAT_I1:
case LV_COLOR_FORMAT_I2:
case LV_COLOR_FORMAT_I4:
case LV_COLOR_FORMAT_I8:
#endif
case LV_COLOR_FORMAT_A4:
case LV_COLOR_FORMAT_A8:
case LV_COLOR_FORMAT_L8:
case LV_COLOR_FORMAT_RGB565:
#if CHIPID == 0x555
case LV_COLOR_FORMAT_RGB565A8:
case LV_COLOR_FORMAT_RGB888:
#endif
case LV_COLOR_FORMAT_ARGB8888:
case LV_COLOR_FORMAT_XRGB8888:
is_cf_supported = true;
break;
default:
break;
}
return (!is_cf_unsupported);
return is_cf_supported;
}
static inline bool _vglite_dest_cf_supported(lv_color_format_t cf)
{
bool is_cf_supported = false;
switch(cf) {
case LV_COLOR_FORMAT_A8:
#if CHIPID == 0x255 || CHIPID == 0x555
case LV_COLOR_FORMAT_L8:
#endif
case LV_COLOR_FORMAT_RGB565:
#if CHIPTID == 0x555
case LV_COLOR_FORMAT_RGB565A8:
case LV_COLOR_FORMAT_RGB888:
#endif
case LV_COLOR_FORMAT_ARGB8888:
case LV_COLOR_FORMAT_XRGB8888:
is_cf_supported = true;
break;
default:
break;
}
return is_cf_supported;
}
static int32_t _vglite_evaluate(lv_draw_unit_t * u, lv_draw_task_t * t)
{
LV_UNUSED(u);
const lv_draw_dsc_base_t * draw_dsc_base = (lv_draw_dsc_base_t *) t->draw_dsc;
if(!_vglite_dest_cf_supported(draw_dsc_base->layer->color_format))
return 0;
switch(t->type) {
case LV_DRAW_TASK_TYPE_FILL:
if(t->preference_score > 80) {
@@ -134,6 +197,7 @@ static int32_t _vglite_evaluate(lv_draw_unit_t * u, lv_draw_task_t * t)
case LV_DRAW_TASK_TYPE_LINE:
case LV_DRAW_TASK_TYPE_ARC:
case LV_DRAW_TASK_TYPE_TRIANGLE:
if(t->preference_score > 90) {
t->preference_score = 90;
t->preferred_draw_unit_id = DRAW_UNIT_ID_VGLITE;
@@ -160,37 +224,11 @@ static int32_t _vglite_evaluate(lv_draw_unit_t * u, lv_draw_task_t * t)
return 1;
}
case LV_DRAW_TASK_TYPE_BG_IMG: {
const lv_draw_bg_image_dsc_t * draw_dsc = (lv_draw_bg_image_dsc_t *) t->draw_dsc;
lv_image_src_t src_type = lv_image_src_get_type(draw_dsc->src);
if(src_type != LV_IMAGE_SRC_SYMBOL) {
bool has_recolor = (draw_dsc->recolor_opa != LV_OPA_TRANSP);
if(has_recolor
|| (!_vglite_cf_supported(draw_dsc->img_header.cf))
|| (!vglite_buf_aligned(draw_dsc->src, draw_dsc->img_header.stride, draw_dsc->img_header.cf))
)
return 0;
}
if(t->preference_score > 80) {
t->preference_score = 80;
t->preferred_draw_unit_id = DRAW_UNIT_ID_VGLITE;
}
return 1;
}
case LV_DRAW_TASK_TYPE_LAYER: {
const lv_draw_image_dsc_t * draw_dsc = (lv_draw_image_dsc_t *) t->draw_dsc;
lv_layer_t * layer_to_draw = (lv_layer_t *)draw_dsc->src;
lv_draw_buf_t * draw_buf = &layer_to_draw->draw_buf;
bool has_recolor = (draw_dsc->recolor_opa != LV_OPA_TRANSP);
if(has_recolor
|| (!_vglite_cf_supported(draw_buf->color_format))
)
if(!_vglite_src_cf_supported(layer_to_draw->color_format))
return 0;
if(t->preference_score > 80) {
@@ -204,16 +242,15 @@ static int32_t _vglite_evaluate(lv_draw_unit_t * u, lv_draw_task_t * t)
lv_draw_image_dsc_t * draw_dsc = (lv_draw_image_dsc_t *) t->draw_dsc;
const lv_image_dsc_t * img_dsc = draw_dsc->src;
bool has_recolor = (draw_dsc->recolor_opa != LV_OPA_TRANSP);
#if VGLITE_BLIT_SPLIT_ENABLED
bool has_transform = (draw_dsc->angle != 0 || draw_dsc->zoom != LV_ZOOM_NONE);
#if LV_USE_VGLITE_BLIT_SPLIT
bool has_transform = (draw_dsc->rotation != 0 || draw_dsc->scale_x != LV_SCALE_NONE ||
draw_dsc->scale_y != LV_SCALE_NONE);
#endif
if(has_recolor
#if VGLITE_BLIT_SPLIT_ENABLED
if((!_vglite_src_cf_supported(img_dsc->header.cf))
#if LV_USE_VGLITE_BLIT_SPLIT
|| has_transform
#endif
|| (!_vglite_cf_supported(img_dsc->header.cf))
|| (!vglite_buf_aligned(img_dsc->data, img_dsc->header.stride, img_dsc->header.cf))
)
return 0;
@@ -239,19 +276,11 @@ static int32_t _vglite_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
if(draw_vglite_unit->task_act)
return 0;
/* Return if target buffer format is not supported.
*
* FIXME: Source format and destination format support is different!
*/
if(!_vglite_cf_supported(layer->draw_buf.color_format))
return 0;
/* Try to get an ready to draw. */
lv_draw_task_t * t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_VGLITE);
/* Return 0 is no selection, some tasks can be supported by other units. */
if(t == NULL || t->preferred_draw_unit_id != DRAW_UNIT_ID_VGLITE)
return 0;
return -1;
void * buf = lv_draw_layer_alloc_buf(layer);
if(buf == NULL)
@@ -264,7 +293,8 @@ static int32_t _vglite_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
#if LV_USE_OS
/* Let the render thread work. */
lv_thread_sync_signal(&draw_vglite_unit->sync);
if(draw_vglite_unit->inited)
lv_thread_sync_signal(&draw_vglite_unit->sync);
#else
_vglite_execute_drawing(draw_vglite_unit);
@@ -278,17 +308,55 @@ static int32_t _vglite_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
return 1;
}
static int32_t _vglite_delete(lv_draw_unit_t * draw_unit)
{
#if LV_USE_OS
lv_draw_vglite_unit_t * draw_vglite_unit = (lv_draw_vglite_unit_t *) draw_unit;
LV_LOG_INFO("Cancel VGLite draw thread.");
draw_vglite_unit->exit_status = true;
if(draw_vglite_unit->inited)
lv_thread_sync_signal(&draw_vglite_unit->sync);
lv_result_t res = lv_thread_delete(&draw_vglite_unit->thread);
return res;
#else
LV_UNUSED(draw_unit);
return 0;
#endif
}
static void _vglite_execute_drawing(lv_draw_vglite_unit_t * u)
{
lv_draw_task_t * t = u->task_act;
lv_draw_unit_t * draw_unit = (lv_draw_unit_t *)u;
lv_layer_t * layer = draw_unit->target_layer;
/* Set target buffer */
lv_layer_t * layer = draw_unit->target_layer;
vglite_set_dest_buf(&layer->draw_buf);
uint32_t buf_width = lv_area_get_width(&layer->buf_area);
uint32_t buf_height = lv_area_get_height(&layer->buf_area);
/* Invalidate cache */
lv_draw_buf_invalidate_cache(&layer->draw_buf, (const char *)&t->area);
vglite_set_dest_buf(layer->buf, buf_width, buf_height, layer->buf_stride, layer->color_format);
lv_area_t clip_area;
lv_area_copy(&clip_area, draw_unit->clip_area);
lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_t draw_area;
lv_area_copy(&draw_area, &t->area);
lv_area_move(&draw_area, -layer->buf_area.x1, -layer->buf_area.y1);
if(!_lv_area_intersect(&draw_area, &draw_area, &clip_area))
return; /*Fully clipped, nothing to do*/
/* Invalidate the drawing area */
lv_draw_buf_invalidate_cache(layer->buf, layer->buf_stride, layer->color_format, &draw_area);
/* Set scissor area */
vglite_set_scissor(&clip_area);
switch(t->type) {
case LV_DRAW_TASK_TYPE_LABEL:
@@ -300,9 +368,6 @@ static void _vglite_execute_drawing(lv_draw_vglite_unit_t * u)
case LV_DRAW_TASK_TYPE_BORDER:
lv_draw_vglite_border(draw_unit, t->draw_dsc, &t->area);
break;
case LV_DRAW_TASK_TYPE_BG_IMG:
lv_draw_vglite_bg_img(draw_unit, t->draw_dsc, &t->area);
break;
case LV_DRAW_TASK_TYPE_IMAGE:
lv_draw_vglite_img(draw_unit, t->draw_dsc, &t->area);
break;
@@ -315,20 +380,25 @@ static void _vglite_execute_drawing(lv_draw_vglite_unit_t * u)
case LV_DRAW_TASK_TYPE_LAYER:
lv_draw_vglite_layer(draw_unit, t->draw_dsc, &t->area);
break;
case LV_DRAW_TASK_TYPE_TRIANGLE:
lv_draw_vglite_triangle(draw_unit, t->draw_dsc);
break;
default:
break;
}
/* Disable scissor */
vglite_set_scissor(&layer->buf_area);
#if LV_USE_PARALLEL_DRAW_DEBUG
/* Layers manage it for themselves. */
/*Layers manage it for themselves*/
if(t->type != LV_DRAW_TASK_TYPE_LAYER) {
lv_area_t draw_area;
if(!_lv_area_intersect(&draw_area, &t->area, u->base_unit.clip_area))
return;
int32_t idx = 0;
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
lv_draw_unit_t * draw_unit_tmp = disp->draw_unit_head;
lv_draw_unit_t * draw_unit_tmp = _draw_info.unit_head;
while(draw_unit_tmp != (lv_draw_unit_t *)u) {
draw_unit_tmp = draw_unit_tmp->next;
idx++;
@@ -340,10 +410,10 @@ static void _vglite_execute_drawing(lv_draw_vglite_unit_t * u)
rect_dsc.bg_opa = LV_OPA_10;
rect_dsc.border_opa = LV_OPA_80;
rect_dsc.border_width = 1;
lv_draw_vglite_rect((lv_draw_unit_t *)u, &rect_dsc, &draw_area);
lv_draw_sw_fill((lv_draw_unit_t *)u, &rect_dsc, &draw_area);
lv_point_t txt_size;
lv_txt_get_size(&txt_size, "W", LV_FONT_DEFAULT, 0, 0, 100, LV_TEXT_FLAG_NONE);
lv_text_get_size(&txt_size, "W", LV_FONT_DEFAULT, 0, 0, 100, LV_TEXT_FLAG_NONE);
lv_area_t txt_area;
txt_area.x1 = draw_area.x1;
@@ -353,7 +423,7 @@ static void _vglite_execute_drawing(lv_draw_vglite_unit_t * u)
lv_draw_rect_dsc_init(&rect_dsc);
rect_dsc.bg_color = lv_color_white();
lv_draw_vglite_rect((lv_draw_unit_t *)u, &rect_dsc, &txt_area);
lv_draw_sw_fill((lv_draw_unit_t *)u, &rect_dsc, &txt_area);
char buf[8];
lv_snprintf(buf, sizeof(buf), "%d", idx);
@@ -361,12 +431,12 @@ static void _vglite_execute_drawing(lv_draw_vglite_unit_t * u)
lv_draw_label_dsc_init(&label_dsc);
label_dsc.color = lv_color_black();
label_dsc.text = buf;
lv_draw_vglite_label((lv_draw_unit_t *)u, &label_dsc, &txt_area);
lv_draw_sw_label((lv_draw_unit_t *)u, &label_dsc, &txt_area);
}
#endif
}
#if LV_USE_OS
#if LV_USE_VGLITE_DRAW_ASYNC
static inline void _vglite_queue_task(lv_draw_task_t * task_act)
{
_draw_task_buf[_tail].task = task_act;
@@ -397,29 +467,47 @@ static inline void _vglite_signal_task_ready(lv_draw_task_t * task_act)
}
if(task_act)
LV_ASSERT_MSG(_tail != _head, "VGLite task buffer full.");
VGLITE_ASSERT_MSG(_tail != _head, "VGLite task buffer full.");
}
#endif
#if LV_USE_OS
static void _vglite_render_thread_cb(void * ptr)
{
lv_draw_vglite_unit_t * u = ptr;
lv_thread_sync_init(&u->sync);
u->inited = true;
while(1) {
/*
* Wait for sync if no task received or _draw_task_buf is empty.
* The thread will have to run as much as there are pending tasks.
*/
while(u->task_act == NULL && _head == _tail) {
/* Wait for sync if there is no task set. */
while(u->task_act == NULL
#if LV_USE_VGLITE_DRAW_ASYNC
/*
* Wait for sync if _draw_task_buf is empty.
* The thread will have to run as much as there are pending tasks.
*/
&& _head == _tail
#endif
) {
if(u->exit_status)
break;
lv_thread_sync_wait(&u->sync);
}
if(u->task_act) {
_vglite_queue_task((void *)u->task_act);
if(u->exit_status) {
LV_LOG_INFO("Ready to exit VGLite draw thread.");
break;
}
if(u->task_act) {
#if LV_USE_VGLITE_DRAW_ASYNC
_vglite_queue_task((void *)u->task_act);
#endif
_vglite_execute_drawing(u);
}
#if LV_USE_VGLITE_DRAW_ASYNC
else {
/*
* Update the flush status for last pending tasks.
@@ -427,15 +515,23 @@ static void _vglite_render_thread_cb(void * ptr)
*/
vglite_run();
}
#endif
#if LV_USE_VGLITE_DRAW_ASYNC
_vglite_signal_task_ready((void *)u->task_act);
#else
/* Signal the ready state to dispatcher. */
u->task_act->state = LV_DRAW_TASK_STATE_READY;
#endif
/* Cleanup. */
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();
}
u->inited = false;
lv_thread_sync_delete(&u->sync);
LV_LOG_INFO("Exit VGLite draw thread.");
}
#endif
+4 -27
View File
@@ -4,7 +4,7 @@
*/
/**
* Copyright 2023 NXP
* Copyright 2023-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
@@ -29,33 +29,11 @@ extern "C" {
* DEFINES
*********************/
/**
* Enable BLIT quality degradation workaround for RT595,
* recommended for screen's dimension > 352 pixels.
*/
#define RT595_BLIT_WRKRND_ENABLED 1
/* Internal compound symbol */
#if (defined(CPU_MIMXRT595SFFOB) || defined(CPU_MIMXRT595SFFOB_cm33) || \
defined(CPU_MIMXRT595SFFOC) || defined(CPU_MIMXRT595SFFOC_cm33)) && \
RT595_BLIT_WRKRND_ENABLED
#define VGLITE_BLIT_SPLIT_ENABLED 1
#else
#define VGLITE_BLIT_SPLIT_ENABLED 0
#endif
/**********************
* TYPEDEFS
**********************/
typedef struct {
lv_draw_unit_t base_unit;
lv_draw_task_t * task_act;
#if LV_USE_OS
lv_thread_sync_t sync;
lv_thread_t thread;
#endif
} lv_draw_vglite_unit_t;
typedef lv_draw_sw_unit_t lv_draw_vglite_unit_t;
/**********************
* GLOBAL PROTOTYPES
@@ -70,9 +48,6 @@ void lv_draw_vglite_deinit(void);
void lv_draw_vglite_arc(lv_draw_unit_t * draw_unit, const lv_draw_arc_dsc_t * dsc,
const lv_area_t * coords);
void lv_draw_vglite_bg_img(lv_draw_unit_t * draw_unit, const lv_draw_bg_image_dsc_t * dsc,
const lv_area_t * coords);
void lv_draw_vglite_border(lv_draw_unit_t * draw_unit, const lv_draw_border_dsc_t * dsc,
const lv_area_t * coords);
@@ -90,6 +65,8 @@ void lv_draw_vglite_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t
void lv_draw_vglite_line(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc);
void lv_draw_vglite_triangle(lv_draw_unit_t * draw_unit, const lv_draw_triangle_dsc_t * dsc);
/**********************
* MACROS
**********************/
+18 -21
View File
@@ -4,7 +4,7 @@
*/
/**
* Copyright 2021-2023 NXP
* Copyright 2021-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
@@ -77,7 +77,7 @@ typedef struct _cubic_cont_pt {
* Draw arc shape with effects
*
* @param[in] center Arc center with relative coordinates
* @param[in] clip_area Clipping area with relative coordinates to dest buff
* @param[in] clip_area Clip area with relative coordinates to dest buff
* @param[in] dsc Arc description structure (width, rounded ending, opacity)
*
*/
@@ -109,13 +109,13 @@ void lv_draw_vglite_arc(lv_draw_unit_t * draw_unit, const lv_draw_arc_dsc_t * ds
return;
lv_layer_t * layer = draw_unit->target_layer;
lv_point_t rel_center = {dsc->center.x - layer->draw_buf_ofs.x, dsc->center.y - layer->draw_buf_ofs.y};
lv_point_t center = {dsc->center.x - layer->buf_area.x1, dsc->center.y - layer->buf_area.y1};
lv_area_t rel_clip_area;
lv_area_copy(&rel_clip_area, draw_unit->clip_area);
lv_area_move(&rel_clip_area, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
lv_area_t clip_area;
lv_area_copy(&clip_area, draw_unit->clip_area);
lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
_vglite_draw_arc(&rel_center, &rel_clip_area, dsc);
_vglite_draw_arc(&center, &clip_area, dsc);
}
/**********************
@@ -207,7 +207,7 @@ static void _set_full_arc(vg_arc * fullarc)
fullarc->p3y = 0;
break;
default:
LV_ASSERT_MSG(false, "Invalid arc quarter.");
VGLITE_ASSERT_MSG(false, "Invalid arc quarter.");
break;
}
}
@@ -562,10 +562,14 @@ static void _add_arc_path(int32_t * arc_path, int * pidx, int32_t radius,
static void _vglite_draw_arc(const lv_point_t * center, const lv_area_t * clip_area,
const lv_draw_arc_dsc_t * dsc)
{
vg_lite_error_t err = VG_LITE_SUCCESS;
vg_lite_path_t path;
uint16_t start_angle = dsc->start_angle;
uint16_t end_angle = dsc->end_angle;
/* be sure end_angle > start_angle */
if(end_angle < start_angle)
end_angle += 360;
bool donut = ((end_angle - start_angle) % 360 == 0) ? true : false;
vg_lite_buffer_t * vgbuf = vglite_get_dest_buf();
@@ -662,10 +666,9 @@ static void _vglite_draw_arc(const lv_point_t * center, const lv_area_t * clip_a
arc_path[pidx++] = VLC_OP_END;
err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, (uint32_t)pidx * sizeof(int32_t), arc_path,
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Init path failed.");
VGLITE_CHECK_ERROR(vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, (uint32_t)pidx * sizeof(int32_t), arc_path,
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f));
lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->opa);
vg_lite_color_t vgcol = vglite_get_color(col32, false);
@@ -673,18 +676,12 @@ static void _vglite_draw_arc(const lv_point_t * center, const lv_area_t * clip_a
vg_lite_matrix_t matrix;
vg_lite_identity(&matrix);
vglite_set_scissor(clip_area);
/*** Draw arc ***/
err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Draw arc failed.");
VGLITE_CHECK_ERROR(vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol));
vglite_run();
vglite_disable_scissor();
err = vg_lite_clear_path(&path);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Clear path failed.");
VGLITE_CHECK_ERROR(vg_lite_clear_path(&path));
}
#endif /*LV_USE_DRAW_VGLITE*/
-113
View File
@@ -1,113 +0,0 @@
/**
* @file lv_draw_vglite_bg_img.c
*
*/
/**
* Copyright 2022, 2023 NXP
*
* SPDX-License-Identifier: MIT
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_vglite.h"
#if LV_USE_DRAW_VGLITE
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_vglite_bg_img(lv_draw_unit_t * draw_unit, const lv_draw_bg_image_dsc_t * dsc,
const lv_area_t * coords)
{
if(dsc->src == NULL) return;
if(dsc->opa <= LV_OPA_MIN) return;
lv_area_t clip_area;
if(!_lv_area_intersect(&clip_area, coords, draw_unit->clip_area)) {
return;
}
const lv_area_t * clip_area_ori = draw_unit->clip_area;
draw_unit->clip_area = &clip_area;
lv_image_src_t src_type = lv_image_src_get_type(dsc->src);
if(src_type == LV_IMAGE_SRC_SYMBOL) {
lv_point_t size;
lv_text_get_size(&size, dsc->src, dsc->font, 0, 0, LV_COORD_MAX, LV_TEXT_FLAG_NONE);
lv_area_t a;
a.x1 = coords->x1 + lv_area_get_width(coords) / 2 - size.x / 2;
a.x2 = a.x1 + size.x - 1;
a.y1 = coords->y1 + lv_area_get_height(coords) / 2 - size.y / 2;
a.y2 = a.y1 + size.y - 1;
lv_draw_label_dsc_t label_draw_dsc;
lv_draw_label_dsc_init(&label_draw_dsc);
label_draw_dsc.font = dsc->font;
label_draw_dsc.color = dsc->recolor;
label_draw_dsc.opa = dsc->opa;
label_draw_dsc.text = dsc->src;
lv_draw_vglite_label(draw_unit, &label_draw_dsc, &a);
}
else {
lv_draw_image_dsc_t img_dsc;
lv_draw_image_dsc_init(&img_dsc);
img_dsc.recolor = dsc->recolor;
img_dsc.recolor_opa = dsc->recolor_opa;
img_dsc.opa = dsc->opa;
img_dsc.src = dsc->src;
/*Center align*/
if(dsc->tiled == false) {
lv_area_t area;
area.x1 = coords->x1 + lv_area_get_width(coords) / 2 - dsc->img_header.w / 2;
area.y1 = coords->y1 + lv_area_get_height(coords) / 2 - dsc->img_header.h / 2;
area.x2 = area.x1 + dsc->img_header.w - 1;
area.y2 = area.y1 + dsc->img_header.h - 1;
lv_draw_vglite_img(draw_unit, &img_dsc, &area);
}
else {
lv_area_t area;
area.y1 = coords->y1;
area.y2 = area.y1 + dsc->img_header.h - 1;
for(; area.y1 <= coords->y2; area.y1 += dsc->img_header.h, area.y2 += dsc->img_header.h) {
area.x1 = coords->x1;
area.x2 = area.x1 + dsc->img_header.w - 1;
for(; area.x1 <= coords->x2; area.x1 += dsc->img_header.w, area.x2 += dsc->img_header.w) {
lv_draw_vglite_img(draw_unit, &img_dsc, &area);
}
}
}
}
draw_unit->clip_area = clip_area_ori;
}
#endif /*LV_USE_DRAW_VGLITE*/
+21 -46
View File
@@ -4,7 +4,7 @@
*/
/**
* Copyright 2022, 2023 NXP
* Copyright 2022-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
@@ -42,7 +42,7 @@
* Draw rectangle border/outline shape with effects (rounded corners, opacity)
*
* @param[in] coords Coordinates of the rectangle border/outline (relative to dest buff)
* @param[in] clip_area Clipping area with relative coordinates to dest buff
* @param[in] clip_area Clip area with relative coordinates to dest buff
* @param[in] dsc Description of the rectangle border/outline
*
*/
@@ -72,33 +72,26 @@ void lv_draw_vglite_border(lv_draw_unit_t * draw_unit, const lv_draw_border_dsc_
return;
lv_layer_t * layer = draw_unit->target_layer;
lv_area_t rel_coords;
lv_area_t inward_coords;
int32_t width = dsc->width;
/* Move border inwards to align with software rendered border */
rel_coords.x1 = coords->x1 + ceil(width / 2.0f);
rel_coords.x2 = coords->x2 - floor(width / 2.0f);
rel_coords.y1 = coords->y1 + ceil(width / 2.0f);
rel_coords.y2 = coords->y2 - floor(width / 2.0f);
inward_coords.x1 = coords->x1 + ceil(width / 2.0f);
inward_coords.x2 = coords->x2 - floor(width / 2.0f);
inward_coords.y1 = coords->y1 + ceil(width / 2.0f);
inward_coords.y2 = coords->y2 - floor(width / 2.0f);
/* Move outline outwards to align with software rendered outline */
//int32_t outline_pad = dsc->outline_pad - 1;
//rel_coords.x1 = coords->x1 - outline_pad - floor(dsc->outline_width / 2.0f);
//rel_coords.x2 = coords->x2 + outline_pad + ceil(dsc->outline_width / 2.0f);
//rel_coords.y1 = coords->y1 - outline_pad - floor(dsc->outline_width / 2.0f);
//rel_coords.y2 = coords->y2 + outline_pad + ceil(dsc->outline_width / 2.0f);
lv_area_move(&inward_coords, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_move(&rel_coords, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
lv_area_t rel_clip_area;
lv_area_copy(&rel_clip_area, draw_unit->clip_area);
lv_area_move(&rel_clip_area, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
lv_area_t clip_area;
lv_area_copy(&clip_area, draw_unit->clip_area);
lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_t clipped_coords;
if(!_lv_area_intersect(&clipped_coords, &rel_coords, &rel_clip_area))
if(!_lv_area_intersect(&clipped_coords, &inward_coords, &clip_area))
return; /*Fully clipped, nothing to do*/
_vglite_draw_border(&rel_coords, &rel_clip_area, dsc);
_vglite_draw_border(&inward_coords, &clip_area, dsc);
}
/**********************
@@ -108,7 +101,6 @@ void lv_draw_vglite_border(lv_draw_unit_t * draw_unit, const lv_draw_border_dsc_
static void _vglite_draw_border(const lv_area_t * coords, const lv_area_t * clip_area,
const lv_draw_border_dsc_t * dsc)
{
vg_lite_error_t err = VG_LITE_SUCCESS;
int32_t radius = dsc->radius;
vg_lite_buffer_t * vgbuf = vglite_get_dest_buf();
@@ -119,13 +111,6 @@ static void _vglite_draw_border(const lv_area_t * coords, const lv_area_t * clip
if(radius > border_half)
radius = radius - border_half;
//else {
// /* Draw outline - always has radius, leave the same radius in the circle case */
// int32_t outline_half = (int32_t)ceil(dsc->outline_width / 2.0f);
// if(radius < (int32_t)LV_RADIUS_CIRCLE - outline_half)
// radius = radius + outline_half;
//}
vg_lite_cap_style_t cap_style = (radius) ? VG_LITE_CAP_ROUND : VG_LITE_CAP_BUTT;
vg_lite_join_style_t join_style = (radius) ? VG_LITE_JOIN_ROUND : VG_LITE_JOIN_MITER;
@@ -136,10 +121,9 @@ static void _vglite_draw_border(const lv_area_t * coords, const lv_area_t * clip
vg_lite_quality_t path_quality = radius > 0 ? VG_LITE_HIGH : VG_LITE_MEDIUM;
vg_lite_path_t path;
err = vg_lite_init_path(&path, VG_LITE_S32, path_quality, path_data_size, path_data,
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Init path failed.");
VGLITE_CHECK_ERROR(vg_lite_init_path(&path, VG_LITE_S32, path_quality, path_data_size, path_data,
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f));
lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->opa);
vg_lite_color_t vgcol = vglite_get_color(col32, false);
@@ -150,26 +134,17 @@ static void _vglite_draw_border(const lv_area_t * coords, const lv_area_t * clip
int32_t line_width = dsc->width;
/*** Draw border ***/
err = vg_lite_set_draw_path_type(&path, VG_LITE_DRAW_STROKE_PATH);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Set draw path type failed.");
VGLITE_CHECK_ERROR(vg_lite_set_draw_path_type(&path, VG_LITE_DRAW_STROKE_PATH));
err = vg_lite_set_stroke(&path, cap_style, join_style, line_width, 8, NULL, 0, 0, vgcol);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Set stroke failed.");
VGLITE_CHECK_ERROR(vg_lite_set_stroke(&path, cap_style, join_style, line_width, 8, NULL, 0, 0, vgcol));
err = vg_lite_update_stroke(&path);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Update stroke failed.");
VGLITE_CHECK_ERROR(vg_lite_update_stroke(&path));
vglite_set_scissor(clip_area);
err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Draw border failed.");
VGLITE_CHECK_ERROR(vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol));
vglite_run();
vglite_disable_scissor();
err = vg_lite_clear_path(&path);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Clear path failed.");
VGLITE_CHECK_ERROR(vg_lite_clear_path(&path));
}
#endif /*LV_USE_DRAW_VGLITE*/
+39 -60
View File
@@ -4,7 +4,7 @@
*/
/**
* Copyright 2020-2023 NXP
* Copyright 2020-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
@@ -47,7 +47,7 @@ static void _vglite_fill(const lv_area_t * dest_area, const lv_draw_fill_dsc_t *
* Draw rectangle background with effects (rounded corners, gradient)
*
* @param[in] coords Coordinates of the rectangle background (relative to dest buff)
* @param[in] clip_area Clipping area with relative coordinates to dest buff
* @param[in] clip_area Clip area with relative coordinates to dest buff
* @param[in] dsc Description of the rectangle background
*
*/
@@ -73,24 +73,16 @@ void lv_draw_vglite_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t *
return;
lv_layer_t * layer = draw_unit->target_layer;
lv_area_t rel_coords;
lv_area_copy(&rel_coords, coords);
lv_area_t relative_coords;
lv_area_copy(&relative_coords, coords);
lv_area_move(&relative_coords, -layer->buf_area.x1, -layer->buf_area.y1);
/*If the border fully covers make the bg area 1px smaller to avoid artifacts on the corners*/
//if(dsc->border_width > 1 && dsc->border_opa >= (lv_opa_t)LV_OPA_MAX && dsc->radius != 0) {
// rel_coords.x1 += (dsc->border_side & LV_BORDER_SIDE_LEFT) ? 1 : 0;
// rel_coords.y1 += (dsc->border_side & LV_BORDER_SIDE_TOP) ? 1 : 0;
// rel_coords.x2 -= (dsc->border_side & LV_BORDER_SIDE_RIGHT) ? 1 : 0;
// rel_coords.y2 -= (dsc->border_side & LV_BORDER_SIDE_BOTTOM) ? 1 : 0;
//}
lv_area_move(&rel_coords, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
lv_area_t rel_clip_area;
lv_area_copy(&rel_clip_area, draw_unit->clip_area);
lv_area_move(&rel_clip_area, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
lv_area_t clip_area;
lv_area_copy(&clip_area, draw_unit->clip_area);
lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_t clipped_coords;
if(!_lv_area_intersect(&clipped_coords, &rel_coords, &rel_clip_area))
if(!_lv_area_intersect(&clipped_coords, &relative_coords, &clip_area))
return; /*Fully clipped, nothing to do*/
/*
@@ -99,7 +91,7 @@ void lv_draw_vglite_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t *
if((dsc->radius == 0) && (dsc->grad.dir == (lv_grad_dir_t)LV_GRAD_DIR_NONE))
_vglite_fill(&clipped_coords, dsc);
else
_vglite_draw_rect(&rel_coords, &rel_clip_area, dsc);
_vglite_draw_rect(&relative_coords, &clip_area, dsc);
}
/**********************
@@ -108,7 +100,6 @@ void lv_draw_vglite_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t *
static void _vglite_fill(const lv_area_t * dest_area, const lv_draw_fill_dsc_t * dsc)
{
vg_lite_error_t err = VG_LITE_SUCCESS;
vg_lite_buffer_t * vgbuf = vglite_get_dest_buf();
lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->opa);
@@ -122,8 +113,7 @@ static void _vglite_fill(const lv_area_t * dest_area, const lv_draw_fill_dsc_t *
.height = lv_area_get_height(dest_area)
};
err = vg_lite_clear(vgbuf, &rect, vgcol);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Clear failed.");
VGLITE_CHECK_ERROR(vg_lite_clear(vgbuf, &rect, vgcol));
vglite_run();
}
@@ -139,32 +129,29 @@ static void _vglite_fill(const lv_area_t * dest_area, const lv_draw_fill_dsc_t *
VLC_OP_END
};
err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_MEDIUM, sizeof(path_data), path_data,
(vg_lite_float_t) dest_area->x1, (vg_lite_float_t) dest_area->y1,
((vg_lite_float_t) dest_area->x2) + 1.0f, ((vg_lite_float_t) dest_area->y2) + 1.0f);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Init path failed.");
VGLITE_CHECK_ERROR(vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_MEDIUM, sizeof(path_data), path_data,
(vg_lite_float_t) dest_area->x1, (vg_lite_float_t) dest_area->y1,
((vg_lite_float_t) dest_area->x2) + 1.0f, ((vg_lite_float_t) dest_area->y2) + 1.0f));
vg_lite_matrix_t matrix;
vg_lite_identity(&matrix);
/*Draw rectangle*/
err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Draw rectangle failed.");
VGLITE_CHECK_ERROR(vg_lite_draw(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol));
vglite_run();
err = vg_lite_clear_path(&path);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Clear path failed.");
VGLITE_CHECK_ERROR(vg_lite_clear_path(&path));
}
}
static void _vglite_draw_rect(const lv_area_t * coords, const lv_area_t * clip_area,
const lv_draw_fill_dsc_t * dsc)
{
vg_lite_error_t err = VG_LITE_SUCCESS;
int32_t width = lv_area_get_width(coords);
int32_t height = lv_area_get_height(coords);
int32_t radius = dsc->radius;
lv_opa_t opa = dsc->opa;
vg_lite_buffer_t * vgbuf = vglite_get_dest_buf();
if(dsc->radius < 0)
@@ -177,20 +164,17 @@ static void _vglite_draw_rect(const lv_area_t * coords, const lv_area_t * clip_a
vg_lite_quality_t path_quality = dsc->radius > 0 ? VG_LITE_HIGH : VG_LITE_MEDIUM;
vg_lite_path_t path;
err = vg_lite_init_path(&path, VG_LITE_S32, path_quality, path_data_size, path_data,
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Init path failed.");
VGLITE_CHECK_ERROR(vg_lite_init_path(&path, VG_LITE_S32, path_quality, path_data_size, path_data,
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f));
vg_lite_matrix_t matrix;
vg_lite_identity(&matrix);
/*** Init Color ***/
lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->opa);
lv_color32_t col32 = lv_color_to_32(dsc->color, opa);
vg_lite_color_t vgcol = vglite_get_color(col32, false);
vglite_set_scissor(clip_area);
vg_lite_linear_gradient_t gradient;
bool has_gradient = (dsc->grad.dir != (lv_grad_dir_t)LV_GRAD_DIR_NONE);
@@ -198,29 +182,30 @@ static void _vglite_draw_rect(const lv_area_t * coords, const lv_area_t * clip_a
if(has_gradient) {
vg_lite_matrix_t * grad_matrix;
uint32_t colors[2];
uint32_t stops[2];
lv_color32_t col32[2];
vg_lite_uint32_t colors[LV_GRADIENT_MAX_STOPS];
vg_lite_uint32_t stops[LV_GRADIENT_MAX_STOPS];
lv_color32_t col32[LV_GRADIENT_MAX_STOPS];
/* Gradient setup */
uint8_t cnt = LV_MAX(dsc->grad.stops_count, 2);
vg_lite_uint32_t cnt = LV_MAX(dsc->grad.stops_count, LV_GRADIENT_MAX_STOPS);
lv_opa_t opa;
for(uint8_t i = 0; i < cnt; i++) {
stops[i] = dsc->grad.stops[i].frac;
col32[i] = lv_color_to_32(dsc->grad.stops[i].color, dsc->opa);
opa = LV_OPA_MIX2(dsc->grad.stops[i].opa, dsc->opa);
col32[i] = lv_color_to_32(dsc->grad.stops[i].color, opa);
colors[i] = vglite_get_color(col32[i], true);
}
lv_memzero(&gradient, sizeof(vg_lite_linear_gradient_t));
err = vg_lite_init_grad(&gradient);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Init gradient failed");
VGLITE_CHECK_ERROR(vg_lite_init_grad(&gradient));
err = vg_lite_set_grad(&gradient, cnt, colors, stops);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Set gradient failed.");
VGLITE_CHECK_ERROR(vg_lite_set_grad(&gradient, cnt, colors, stops));
err = vg_lite_update_grad(&gradient);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Update gradient failed.");
VGLITE_CHECK_ERROR(vg_lite_update_grad(&gradient));
grad_matrix = vg_lite_get_grad_matrix(&gradient);
vg_lite_identity(grad_matrix);
@@ -234,25 +219,19 @@ static void _vglite_draw_rect(const lv_area_t * coords, const lv_area_t * clip_a
vg_lite_scale((float)width / 256.0f, 1.0f, grad_matrix);
}
err = vg_lite_draw_gradient(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, &gradient, VG_LITE_BLEND_SRC_OVER);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Draw gradient failed.");
VGLITE_CHECK_ERROR(vg_lite_draw_gradient(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, &gradient,
VG_LITE_BLEND_SRC_OVER));
}
else {
err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Draw rectangle failed.");
VGLITE_CHECK_ERROR(vg_lite_draw(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol));
}
vglite_run();
vglite_disable_scissor();
VGLITE_CHECK_ERROR(vg_lite_clear_path(&path));
err = vg_lite_clear_path(&path);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Clear path failed.");
if(has_gradient) {
err = vg_lite_clear_grad(&gradient);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Clear gradient failed.");
}
if(has_gradient)
VGLITE_CHECK_ERROR(vg_lite_clear_grad(&gradient));
}
#endif /*LV_USE_DRAW_VGLITE*/
+73 -83
View File
@@ -4,7 +4,7 @@
*/
/**
* Copyright 2020-2023 NXP
* Copyright 2020-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
@@ -26,7 +26,7 @@
* DEFINES
*********************/
#if VGLITE_BLIT_SPLIT_ENABLED
#if LV_USE_VGLITE_BLIT_SPLIT
/**
* BLIT split threshold - BLITs with width or height higher than this value will
* be done in multiple steps. Value must be multiple of stride alignment in px.
@@ -47,7 +47,7 @@
do { \
} while (0)
#endif
#endif
#endif /*LV_USE_VGLITE_BLIT_SPLIT*/
/**********************
* TYPEDEFS
@@ -63,12 +63,13 @@
*
* @param[in] dest_area Destination area with relative coordinates to dest buffer
* @param[in] src_area Source area with relative coordinates to src buffer
* @param[in] opa Opacity
* @param[in] dsc Image descriptor
*
*/
static void _vglite_blit_single(const lv_area_t * dest_area, const lv_area_t * src_area, lv_opa_t opa);
static void _vglite_blit_single(const lv_area_t * dest_area, const lv_area_t * src_area,
const lv_draw_image_dsc_t * dsc);
#if VGLITE_BLIT_SPLIT_ENABLED
#if LV_USE_VGLITE_BLIT_SPLIT
/**
* Move buffer pointer as close as possible to area, but with respect to alignment requirements.
*
@@ -91,26 +92,25 @@ static void _move_buf_close_to_area(void ** buf, lv_area_t * area, uint32_t stri
* @param[in] src_area Source area with relative coordinates to src buffer
* @param[in] src_stride Stride of source buffer in bytes
* @param[in] src_cf Color format of source buffer
* @param[in] opa Opacity
* @param[in] dsc Image descriptor
*
*/
static void _vglite_blit_split(void * dest_buf, lv_area_t * dest_area, uint32_t dest_stride, lv_color_format_t dest_cf,
const void * src_buf, lv_area_t * src_area, uint32_t src_stride, lv_color_format_t src_cf,
lv_opa_t opa);
const lv_draw_image_dsc_t * dsc);
#else
/**
* BLock Image Transfer - copy rectangular image from src_buf to dst_buf with transformation.
* By default, image is copied directly, with optional opacity.
*
* @param[in] dest_area Area with relative coordinates to dest buffer
* @param[in] clip_area Clip area with relative coordinates to dest buffer
* @param[in] src_area Source area with relative coordinates to src buffer
* @param[in] dsc Image descriptor
*
*/
static void _vglite_blit_transform(const lv_area_t * dest_area, const lv_area_t * clip_area,
const lv_area_t * src_area, const lv_draw_image_dsc_t * dsc);
#endif /*VGLITE_BLIT_SPLIT_ENABLED*/
static void _vglite_blit_transform(const lv_area_t * dest_area, const lv_area_t * src_area,
const lv_draw_image_dsc_t * dsc);
#endif /*LV_USE_VGLITE_BLIT_SPLIT*/
/**********************
* STATIC VARIABLES
@@ -133,28 +133,28 @@ void lv_draw_vglite_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t *
lv_layer_t * layer = draw_unit->target_layer;
const lv_image_dsc_t * img_dsc = dsc->src;
lv_area_t rel_coords;
lv_area_copy(&rel_coords, coords);
lv_area_move(&rel_coords, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
lv_area_t relative_coords;
lv_area_copy(&relative_coords, coords);
lv_area_move(&relative_coords, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_t rel_clip_area;
lv_area_copy(&rel_clip_area, draw_unit->clip_area);
lv_area_move(&rel_clip_area, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
lv_area_t clip_area;
lv_area_copy(&clip_area, draw_unit->clip_area);
lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_t blend_area;
bool has_transform = dsc->rotation != 0 || dsc->zoom != LV_SCALE_NONE;
bool has_transform = (dsc->rotation != 0 || dsc->scale_x != LV_SCALE_NONE || dsc->scale_y != LV_SCALE_NONE);
if(has_transform)
lv_area_copy(&blend_area, &rel_coords);
else if(!_lv_area_intersect(&blend_area, &rel_coords, &rel_clip_area))
lv_area_copy(&blend_area, &relative_coords);
else if(!_lv_area_intersect(&blend_area, &relative_coords, &clip_area))
return; /*Fully clipped, nothing to do*/
const void * src_buf = img_dsc->data;
lv_area_t src_area;
src_area.x1 = blend_area.x1 - (coords->x1 - layer->draw_buf_ofs.x);
src_area.y1 = blend_area.y1 - (coords->y1 - layer->draw_buf_ofs.y);
src_area.x2 = src_area.x1 + lv_area_get_width(coords) - 1;
src_area.y2 = src_area.y1 + lv_area_get_height(coords) - 1;
src_area.x1 = blend_area.x1 - (coords->x1 - layer->buf_area.x1);
src_area.y1 = blend_area.y1 - (coords->y1 - layer->buf_area.y1);
src_area.x2 = img_dsc->header.w - 1;
src_area.y2 = img_dsc->header.h - 1;
lv_color_format_t src_cf = img_dsc->header.cf;
uint32_t src_stride = img_dsc->header.stride;
@@ -162,86 +162,82 @@ void lv_draw_vglite_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t *
/* Set src_vgbuf structure. */
vglite_set_src_buf(src_buf, lv_area_get_width(&src_area), lv_area_get_height(&src_area), src_stride, src_cf);
#if VGLITE_BLIT_SPLIT_ENABLED
void * dest_buf = lv_draw_buf_get_buf(&layer->draw_buf);
uint32_t dest_stride = lv_draw_buf_get_stride(&layer->draw_buf);
lv_color_format_t dest_cf = layer->draw_buf.color_format;
#if LV_USE_VGLITE_BLIT_SPLIT
void * dest_buf = layer->buf;
uint32_t dest_stride = layer->buf_stride;
lv_color_format_t dest_cf = layer->color_format;
if(!has_transform)
_vglite_blit_split(dest_buf, &blend_area, dest_stride, dest_cf,
src_buf, &src_area, src_stride, src_cf, dsc->opa);
src_buf, &src_area, src_stride, src_cf, dsc);
#else
if(has_transform)
_vglite_blit_transform(&blend_area, &rel_clip_area, &src_area, dsc);
_vglite_blit_transform(&blend_area, &src_area, dsc);
else
_vglite_blit_single(&blend_area, &src_area, dsc->opa);
#endif
_vglite_blit_single(&blend_area, &src_area, dsc);
#endif /*LV_USE_VGLITE_BLIT_SPLIT*/
}
/**********************
* STATIC FUNCTIONS
**********************/
static void _vglite_blit(const lv_area_t * src_area, lv_opa_t opa)
static void _vglite_blit(const lv_area_t * src_area, const lv_draw_image_dsc_t * dsc)
{
vg_lite_error_t err = VG_LITE_SUCCESS;
vg_lite_buffer_t * dst_vgbuf = vglite_get_dest_buf();
vg_lite_buffer_t * src_vgbuf = vglite_get_src_buf();
uint32_t rect[] = {
(uint32_t)src_area->x1, /* start x */
(uint32_t)src_area->y1, /* start y */
(uint32_t)lv_area_get_width(src_area), /* width */
(uint32_t)lv_area_get_height(src_area) /* height */
vg_lite_rectangle_t rect = {
.x = (vg_lite_int32_t)src_area->x1,
.y = (vg_lite_int32_t)src_area->y1,
.width = (vg_lite_int32_t)lv_area_get_width(src_area),
.height = (vg_lite_int32_t)lv_area_get_height(src_area)
};
uint32_t color;
vg_lite_blend_t blend;
if(opa >= (lv_opa_t)LV_OPA_MAX) {
color = 0xFFFFFFFFU;
blend = VG_LITE_BLEND_SRC_OVER;
src_vgbuf->transparency_mode = VG_LITE_IMAGE_TRANSPARENT;
src_vgbuf->image_mode = VG_LITE_MULTIPLY_IMAGE_MODE;
src_vgbuf->transparency_mode = VG_LITE_IMAGE_TRANSPARENT;
lv_color_t color;
lv_opa_t opa;
bool has_recolor = (dsc->recolor_opa > LV_OPA_MIN);
if(has_recolor) {
color = dsc->recolor;
opa = LV_OPA_MIX2(dsc->recolor_opa, dsc->opa);
}
else {
if(vg_lite_query_feature(gcFEATURE_BIT_VG_PE_PREMULTIPLY)) {
color = (opa << 24) | 0x00FFFFFFU;
}
else {
color = (opa << 24) | (opa << 16) | (opa << 8) | opa;
}
blend = VG_LITE_BLEND_SRC_OVER;
src_vgbuf->image_mode = VG_LITE_MULTIPLY_IMAGE_MODE;
src_vgbuf->transparency_mode = VG_LITE_IMAGE_TRANSPARENT;
color.red = 0xFF;
color.green = 0xFF;
color.blue = 0xFF;
opa = dsc->opa;
}
vg_lite_matrix_t * vgmatrix = vglite_get_matrix();
lv_color32_t col32 = lv_color_to_32(color, opa);
vg_lite_color_t vgcol = vglite_get_color(col32, false);
err = vg_lite_blit_rect(dst_vgbuf, src_vgbuf, rect, vgmatrix, blend, color, VG_LITE_FILTER_POINT);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Blit rectangle failed.");
vg_lite_matrix_t * vgmatrix = vglite_get_matrix();
vg_lite_blend_t vgblend = vglite_get_blend_mode(dsc->blend_mode);
VGLITE_CHECK_ERROR(vg_lite_blit_rect(dst_vgbuf, src_vgbuf, &rect, vgmatrix, vgblend, vgcol, VG_LITE_FILTER_POINT));
vglite_run();
}
static void _vglite_blit_single(const lv_area_t * dest_area, const lv_area_t * src_area, lv_opa_t opa)
static void _vglite_blit_single(const lv_area_t * dest_area, const lv_area_t * src_area,
const lv_draw_image_dsc_t * dsc)
{
/* Set scissor. */
vglite_set_scissor(dest_area);
/* Set vgmatrix. */
vglite_set_translation_matrix(dest_area);
/* Start blit. */
_vglite_blit(src_area, opa);
/* Disable scissor. */
vglite_disable_scissor();
_vglite_blit(src_area, dsc);
}
#if VGLITE_BLIT_SPLIT_ENABLED
#if LV_USE_VGLITE_BLIT_SPLIT
static void _move_buf_close_to_area(void ** buf, lv_area_t * area, uint32_t stride, lv_color_format_t cf)
{
uint8_t ** buf_u8 = (uint8_t **)buf;
uint8_t align_bytes = vglite_get_alignment(cf);
uint8_t bits_per_pixel = vglite_get_px_size(cf);
uint8_t bits_per_pixel = lv_color_format_get_bpp(cf);
uint16_t align_pixels = align_bytes * 8 / bits_per_pixel;
@@ -264,7 +260,7 @@ static void _move_buf_close_to_area(void ** buf, lv_area_t * area, uint32_t stri
static void _vglite_blit_split(void * dest_buf, lv_area_t * dest_area, uint32_t dest_stride, lv_color_format_t dest_cf,
const void * src_buf, lv_area_t * src_area, uint32_t src_stride, lv_color_format_t src_cf,
lv_opa_t opa)
const lv_draw_image_dsc_t * dsc)
{
VGLITE_TRACE("Blit "
"Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | "
@@ -288,7 +284,7 @@ static void _vglite_blit_split(void * dest_buf, lv_area_t * dest_area, uint32_t
vglite_set_dest_buf_ptr(dest_buf);
vglite_set_src_buf_ptr(src_buf);
_vglite_blit_single(dest_area, src_area, opa);
_vglite_blit_single(dest_area, src_area, dsc);
VGLITE_TRACE("Single "
"Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | "
@@ -355,8 +351,8 @@ static void _vglite_blit_split(void * dest_buf, lv_area_t * dest_area, uint32_t
tile_dest_area.x1 = shift_dest_x;
if(x > 0) {
/* Advance start pointer for every tile, except the first raw (x = 0) */
tile_src_buf += VGLITE_BLIT_SPLIT_THR * vglite_get_px_size(src_cf) / 8;
tile_dest_buf += VGLITE_BLIT_SPLIT_THR * vglite_get_px_size(dest_cf) / 8;
tile_src_buf += VGLITE_BLIT_SPLIT_THR * lv_color_format_get_bpp(src_cf) / 8;
tile_dest_buf += VGLITE_BLIT_SPLIT_THR * lv_color_format_get_bpp(dest_cf) / 8;
}
/* Calculate x2 coordinates */
@@ -375,7 +371,7 @@ static void _vglite_blit_split(void * dest_buf, lv_area_t * dest_area, uint32_t
vglite_set_dest_buf_ptr(tile_dest_buf);
vglite_set_src_buf_ptr(tile_src_buf);
_vglite_blit_single(&tile_dest_area, &tile_src_area, opa);
_vglite_blit_single(&tile_dest_area, &tile_src_area, dsc);
VGLITE_TRACE("Tile [%d, %d] "
"Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | "
@@ -391,21 +387,15 @@ static void _vglite_blit_split(void * dest_buf, lv_area_t * dest_area, uint32_t
}
}
#else
static void _vglite_blit_transform(const lv_area_t * dest_area, const lv_area_t * clip_area,
const lv_area_t * src_area, const lv_draw_image_dsc_t * dsc)
static void _vglite_blit_transform(const lv_area_t * dest_area, const lv_area_t * src_area,
const lv_draw_image_dsc_t * dsc)
{
/* Set scissor. */
vglite_set_scissor(clip_area);
/* Set vgmatrix. */
vglite_set_transformation_matrix(dest_area, dsc);
/* Start blit. */
_vglite_blit(src_area, dsc->opa);
/* Disable scissor. */
vglite_disable_scissor();
_vglite_blit(src_area, dsc);
}
#endif /*VGLITE_BLIT_SPLIT_ENABLED*/
#endif /*LV_USE_VGLITE_BLIT_SPLIT*/
#endif /*LV_USE_DRAW_VGLITE*/
+32 -52
View File
@@ -4,7 +4,7 @@
*/
/**
* Copyright 2023 NXP
* Copyright 2023-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
@@ -40,17 +40,12 @@ static void _draw_vglite_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t
/**
* Draw letter (character bitmap blend) with optional color and opacity
*
* @param[in] dest_area Area with relative coordinates of destination buffer
* @param[in] mask_buf Mask buffer
* @param[in] mask_area Mask area with relative coordinates of source buffer
* @param[in] mask_stride Stride of mask buffer in bytes
* @param[in] color Color
* @param[in] opa Opacity
*
*/
static void _vglite_draw_letter(const lv_area_t * dest_area,
const void * mask_buf, const lv_area_t * mask_area, uint32_t mask_stride,
lv_color_t color, lv_opa_t opa);
static void _vglite_draw_letter(const lv_area_t * mask_area, lv_color_t color, lv_opa_t opa);
/**********************
* STATIC VARIABLES
@@ -105,24 +100,20 @@ static void _draw_vglite_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t
lv_area_t blend_area;
if(!_lv_area_intersect(&blend_area, glyph_draw_dsc->letter_coords, draw_unit->clip_area))
return;
lv_area_move(&blend_area, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
lv_area_move(&blend_area, -layer->buf_area.x1, -layer->buf_area.y1);
const lv_draw_buf_t * draw_buf = glyph_draw_dsc->glyph_data;
const uint8_t * mask_buf = draw_buf->data;
lv_area_t mask_area;
lv_area_copy(&mask_area, glyph_draw_dsc->letter_coords);
lv_area_move(&mask_area, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
const void * mask_buf = draw_buf->data;
/**
* @todo check if we can use draw_buf->header.stride directly.
*/
uint32_t mask_stride = lv_draw_buf_width_to_stride(
lv_area_get_width(glyph_draw_dsc->letter_coords),
LV_COLOR_FORMAT_A8);
if(mask_buf) {
mask_buf += mask_stride * (blend_area.y1 - glyph_draw_dsc->letter_coords->y1) +
(blend_area.x1 - glyph_draw_dsc->letter_coords->x1);
}
uint32_t mask_width = lv_area_get_width(glyph_draw_dsc->letter_coords);
uint32_t mask_height = lv_area_get_height(glyph_draw_dsc->letter_coords);
uint32_t mask_stride = draw_buf->header.stride;
lv_area_t mask_area;
mask_area.x1 = blend_area.x1 - (glyph_draw_dsc->letter_coords->x1 - layer->buf_area.x1);
mask_area.y1 = blend_area.y1 - (glyph_draw_dsc->letter_coords->y1 - layer->buf_area.y1);
mask_area.x2 = mask_width - 1;
mask_area.y2 = mask_height - 1;
if(!vglite_buf_aligned(mask_buf, mask_stride, LV_COLOR_FORMAT_A8)) {
/* Draw a placeholder rectangle*/
@@ -134,9 +125,15 @@ static void _draw_vglite_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t
lv_draw_vglite_border(draw_unit, &border_draw_dsc, glyph_draw_dsc->bg_coords);
}
else {
/* Set src_vgbuf structure. */
vglite_set_src_buf(mask_buf, mask_width, mask_height, mask_stride, LV_COLOR_FORMAT_A8);
_vglite_draw_letter(&blend_area, mask_buf, &mask_area, mask_stride,
glyph_draw_dsc->color, glyph_draw_dsc->opa);
/* Set vgmatrix. */
vglite_set_translation_matrix(&blend_area);
lv_draw_buf_invalidate_cache((void *)mask_buf, mask_stride, LV_COLOR_FORMAT_A8, &mask_area);
_vglite_draw_letter(&mask_area, glyph_draw_dsc->color, glyph_draw_dsc->opa);
}
}
else if(glyph_draw_dsc->format == LV_DRAW_LETTER_BITMAP_FORMAT_IMAGE) {
@@ -157,46 +154,29 @@ static void _draw_vglite_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t
}
}
static void _vglite_draw_letter(const lv_area_t * dest_area,
const void * mask_buf, const lv_area_t * mask_area, uint32_t mask_stride,
lv_color_t color, lv_opa_t opa)
static void _vglite_draw_letter(const lv_area_t * mask_area, lv_color_t color, lv_opa_t opa)
{
vg_lite_error_t err = VG_LITE_SUCCESS;
vg_lite_buffer_t * dst_vgbuf = vglite_get_dest_buf();
vg_lite_buffer_t * mask_vgbuf = vglite_get_src_buf();
vg_lite_buffer_t mask_vgbuf;
mask_vgbuf.format = VG_LITE_A8;
mask_vgbuf.tiled = VG_LITE_LINEAR;
mask_vgbuf.image_mode = VG_LITE_MULTIPLY_IMAGE_MODE;
mask_vgbuf.transparency_mode = VG_LITE_IMAGE_TRANSPARENT;
mask_vgbuf.width = (int32_t)lv_area_get_width(mask_area);
mask_vgbuf.height = (int32_t)lv_area_get_height(mask_area);
mask_vgbuf.stride = (int32_t)mask_stride;
mask_vgbuf->image_mode = VG_LITE_MULTIPLY_IMAGE_MODE;
mask_vgbuf->transparency_mode = VG_LITE_IMAGE_TRANSPARENT;
lv_memzero(&mask_vgbuf.yuv, sizeof(mask_vgbuf.yuv));
mask_vgbuf.memory = (void *)mask_buf;
mask_vgbuf.address = (uint32_t)mask_vgbuf.memory;
mask_vgbuf.handle = NULL;
uint32_t rect[] = {
(uint32_t)0, /* start x */
(uint32_t)0, /* start y */
(uint32_t)lv_area_get_width(mask_area), /* width */
(uint32_t)lv_area_get_height(mask_area) /* height */
vg_lite_rectangle_t rect = {
.x = (vg_lite_int32_t)mask_area->x1,
.y = (vg_lite_int32_t)mask_area->y1,
.width = (vg_lite_int32_t)lv_area_get_width(mask_area),
.height = (vg_lite_int32_t)lv_area_get_height(mask_area)
};
lv_color32_t col32 = lv_color_to_32(color, opa);
vg_lite_color_t vgcol = vglite_get_color(col32, false);
/* Set vgmatrix. */
vglite_set_translation_matrix(dest_area);
vg_lite_matrix_t * vgmatrix = vglite_get_matrix();
/*Blit with font color as paint color*/
err = vg_lite_blit_rect(dst_vgbuf, &mask_vgbuf, rect, vgmatrix, VG_LITE_BLEND_SRC_OVER, vgcol,
VG_LITE_FILTER_POINT);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Draw letter failed.");
VGLITE_CHECK_ERROR(vg_lite_blit_rect(dst_vgbuf, mask_vgbuf, &rect, vgmatrix, VG_LITE_BLEND_SRC_OVER, vgcol,
VG_LITE_FILTER_POINT));
vglite_run();
}
+106 -7
View File
@@ -4,7 +4,7 @@
*/
/**
* Copyright 2023 NXP
* Copyright 2023-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
@@ -18,6 +18,9 @@
#if LV_USE_DRAW_VGLITE
#include "../../../stdlib/lv_string.h"
#if LV_USE_PARALLEL_DRAW_DEBUG
#include "../../../core/lv_global.h"
#endif
/*********************
* DEFINES
@@ -35,6 +38,10 @@
* STATIC VARIABLES
**********************/
#if LV_USE_PARALLEL_DRAW_DEBUG
#define _draw_info LV_GLOBAL_DEFAULT()->draw_info
#endif
/**********************
* MACROS
**********************/
@@ -50,20 +57,112 @@ void lv_draw_vglite_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t
/*It can happen that nothing was draw on a layer and therefore its buffer is not allocated.
*In this case just return. */
if(layer_to_draw->draw_buf.buf == NULL)
if(layer_to_draw->buf == NULL)
return;
lv_image_dsc_t img_dsc = { 0 };
img_dsc.header.w = layer_to_draw->draw_buf.width;
img_dsc.header.h = layer_to_draw->draw_buf.height;
img_dsc.header.cf = layer_to_draw->draw_buf.color_format;
img_dsc.data = lv_draw_buf_get_buf(&layer_to_draw->draw_buf);
uint32_t width = lv_area_get_width(&layer_to_draw->buf_area);
uint32_t height = lv_area_get_height(&layer_to_draw->buf_area);
const lv_area_t area = {
.x1 = 0,
.y1 = 0,
.x2 = width - 1,
.y2 = height - 1
};
lv_draw_buf_invalidate_cache(layer_to_draw->buf, layer_to_draw->buf_stride, layer_to_draw->color_format, &area);
lv_image_dsc_t img_dsc = {0};
img_dsc.header.w = width;
img_dsc.header.h = height;
img_dsc.header.cf = layer_to_draw->color_format;
img_dsc.header.stride = layer_to_draw->buf_stride;
img_dsc.data = layer_to_draw->buf;
lv_draw_image_dsc_t new_draw_dsc;
lv_memcpy(&new_draw_dsc, draw_dsc, sizeof(lv_draw_image_dsc_t));
new_draw_dsc.src = &img_dsc;
lv_draw_vglite_img(draw_unit, &new_draw_dsc, coords);
#if LV_USE_LAYER_DEBUG || LV_USE_PARALLEL_DRAW_DEBUG
lv_area_t area_rot;
lv_area_copy(&area_rot, coords);
bool has_transform = (draw_dsc->rotation != 0 || draw_dsc->scale_x != LV_SCALE_NONE ||
draw_dsc->scale_y != LV_SCALE_NONE);
if(has_transform) {
int32_t w = lv_area_get_width(coords);
int32_t h = lv_area_get_height(coords);
_lv_image_buf_get_transformed_area(&area_rot, w, h, draw_dsc->rotation, draw_dsc->scale_x, draw_dsc->scale_y,
&draw_dsc->pivot);
area_rot.x1 += coords->x1;
area_rot.y1 += coords->y1;
area_rot.x2 += coords->x1;
area_rot.y2 += coords->y1;
}
lv_area_t draw_area;
if(!_lv_area_intersect(&draw_area, &area_rot, draw_unit->clip_area)) return;
#endif
#if LV_USE_LAYER_DEBUG
lv_draw_fill_dsc_t fill_dsc;
lv_draw_fill_dsc_init(&fill_dsc);
fill_dsc.color = lv_color_hex(layer_to_draw->color_format == LV_COLOR_FORMAT_ARGB8888 ? 0xff0000 : 0x00ff00);
fill_dsc.opa = LV_OPA_20;
lv_draw_sw_fill(draw_unit, &fill_dsc, &area_rot);
lv_draw_border_dsc_t border_dsc;
lv_draw_border_dsc_init(&border_dsc);
border_dsc.color = fill_dsc.color;
border_dsc.opa = LV_OPA_60;
border_dsc.width = 2;
lv_draw_sw_border(draw_unit, &border_dsc, &area_rot);
#endif
#if LV_USE_PARALLEL_DRAW_DEBUG
uint32_t idx = 0;
lv_draw_unit_t * draw_unit_tmp = _draw_info.unit_head;
while(draw_unit_tmp != draw_unit) {
draw_unit_tmp = draw_unit_tmp->next;
idx++;
}
lv_draw_fill_dsc_t fill_dsc;
lv_draw_rect_dsc_init(&fill_dsc);
fill_dsc.color = lv_palette_main(idx % _LV_PALETTE_LAST);
fill_dsc.opa = LV_OPA_10;
lv_draw_sw_fill(draw_unit, &fill_dsc, &area_rot);
lv_draw_border_dsc_t border_dsc;
lv_draw_border_dsc_init(&border_dsc);
border_dsc.color = lv_palette_main(idx % _LV_PALETTE_LAST);
border_dsc.opa = LV_OPA_100;
border_dsc.width = 2;
lv_draw_sw_border(draw_unit, &border_dsc, &area_rot);
lv_point_t txt_size;
lv_text_get_size(&txt_size, "W", LV_FONT_DEFAULT, 0, 0, 100, LV_TEXT_FLAG_NONE);
lv_area_t txt_area;
txt_area.x1 = draw_area.x1;
txt_area.x2 = draw_area.x1 + txt_size.x - 1;
txt_area.y2 = draw_area.y2;
txt_area.y1 = draw_area.y2 - txt_size.y + 1;
lv_draw_fill_dsc_init(&fill_dsc);
fill_dsc.color = lv_color_black();
lv_draw_sw_fill(draw_unit, &fill_dsc, &txt_area);
char buf[8];
lv_snprintf(buf, sizeof(buf), "%d", idx);
lv_draw_label_dsc_t label_dsc;
lv_draw_label_dsc_init(&label_dsc);
label_dsc.color = lv_color_white();
label_dsc.text = buf;
lv_draw_sw_label(draw_unit, &label_dsc, &txt_area);
#endif
}
#endif /*LV_USE_DRAW_VGLITE*/
+22 -34
View File
@@ -4,7 +4,7 @@
*/
/**
* Copyright 2022, 2023 NXP
* Copyright 2022-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
@@ -36,7 +36,7 @@
*
* @param[in] point1 Starting point with relative coordinates
* @param[in] point2 Ending point with relative coordinates
* @param[in] clip_area Clipping area with relative coordinates to dest buff
* @param[in] clip_area Clip area with relative coordinates to dest buff
* @param[in] dsc Line description structure (width, rounded ending, opacity, ...)
*
*/
@@ -65,21 +65,21 @@ void lv_draw_vglite_line(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t *
return;
lv_layer_t * layer = draw_unit->target_layer;
lv_area_t rel_clip_area;
rel_clip_area.x1 = LV_MIN(dsc->p1.x, dsc->p2.x) - dsc->width / 2;
rel_clip_area.x2 = LV_MAX(dsc->p1.x, dsc->p2.x) + dsc->width / 2;
rel_clip_area.y1 = LV_MIN(dsc->p1.y, dsc->p2.y) - dsc->width / 2;
rel_clip_area.y2 = LV_MAX(dsc->p1.y, dsc->p2.y) + dsc->width / 2;
lv_area_t clip_area;
clip_area.x1 = LV_MIN(dsc->p1.x, dsc->p2.x) - dsc->width / 2;
clip_area.x2 = LV_MAX(dsc->p1.x, dsc->p2.x) + dsc->width / 2;
clip_area.y1 = LV_MIN(dsc->p1.y, dsc->p2.y) - dsc->width / 2;
clip_area.y2 = LV_MAX(dsc->p1.y, dsc->p2.y) + dsc->width / 2;
if(!_lv_area_intersect(&rel_clip_area, &rel_clip_area, draw_unit->clip_area))
if(!_lv_area_intersect(&clip_area, &clip_area, draw_unit->clip_area))
return; /*Fully clipped, nothing to do*/
lv_area_move(&rel_clip_area, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
lv_point_t rel_point1 = {dsc->p1.x - layer->draw_buf_ofs.x, dsc->p1.y - layer->draw_buf_ofs.y};
lv_point_t rel_point2 = {dsc->p2.x - layer->draw_buf_ofs.x, dsc->p2.y - layer->draw_buf_ofs.y};
lv_point_t point1 = {dsc->p1.x - layer->buf_area.x1, dsc->p1.y - layer->buf_area.y1};
lv_point_t point2 = {dsc->p2.x - layer->buf_area.x1, dsc->p2.y - layer->buf_area.y1};
_vglite_draw_line(&rel_point1, &rel_point2, &rel_clip_area, dsc);
_vglite_draw_line(&point1, &point2, &clip_area, dsc);
}
/**********************
@@ -89,7 +89,6 @@ void lv_draw_vglite_line(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t *
static void _vglite_draw_line(const lv_point_t * point1, const lv_point_t * point2,
const lv_area_t * clip_area, const lv_draw_line_dsc_t * dsc)
{
vg_lite_error_t err = VG_LITE_SUCCESS;
vg_lite_path_t path;
vg_lite_buffer_t * vgbuf = vglite_get_dest_buf();
vg_lite_cap_style_t cap_style = (dsc->round_start || dsc->round_end) ? VG_LITE_CAP_ROUND : VG_LITE_CAP_BUTT;
@@ -107,8 +106,7 @@ static void _vglite_draw_line(const lv_point_t * point1, const lv_point_t * poin
stroke_dash_phase = (vg_lite_float_t)dsc->dash_width / 2;
}
/* Choose vglite blend mode based on given lvgl blend mode */
vg_lite_blend_t vglite_blend_mode = vglite_get_blend_mode(dsc->blend_mode);
vg_lite_blend_t vgblend = vglite_get_blend_mode(dsc->blend_mode);
/*** Init path ***/
int32_t width = dsc->width;
@@ -119,10 +117,9 @@ static void _vglite_draw_line(const lv_point_t * point1, const lv_point_t * poin
VLC_OP_END
};
err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, sizeof(line_path), line_path,
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Init path failed.");
VGLITE_CHECK_ERROR(vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, sizeof(line_path), line_path,
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f));
lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->opa);
vg_lite_color_t vgcol = vglite_get_color(col32, false);
@@ -131,27 +128,18 @@ static void _vglite_draw_line(const lv_point_t * point1, const lv_point_t * poin
vg_lite_identity(&matrix);
/*** Draw line ***/
err = vg_lite_set_draw_path_type(&path, VG_LITE_DRAW_STROKE_PATH);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Set draw path type failed.");
VGLITE_CHECK_ERROR(vg_lite_set_draw_path_type(&path, VG_LITE_DRAW_STROKE_PATH));
err = vg_lite_set_stroke(&path, cap_style, join_style, width, 8, stroke_dash_pattern, stroke_dash_count,
stroke_dash_phase, vgcol);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Set stroke failed.");
VGLITE_CHECK_ERROR(vg_lite_set_stroke(&path, cap_style, join_style, width, 8, stroke_dash_pattern, stroke_dash_count,
stroke_dash_phase, vgcol));
err = vg_lite_update_stroke(&path);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Update stroke failed.");
VGLITE_CHECK_ERROR(vg_lite_update_stroke(&path));
vglite_set_scissor(clip_area);
err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, vglite_blend_mode, vgcol);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Draw line failed.");
VGLITE_CHECK_ERROR(vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, vgblend, vgcol));
vglite_run();
vglite_disable_scissor();
err = vg_lite_clear_path(&path);
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Clear path failed.");
VGLITE_CHECK_ERROR(vg_lite_clear_path(&path));
}
#endif /*LV_USE_DRAW_VGLITE*/
@@ -0,0 +1,179 @@
/**
* @file lv_draw_vglite_triangle.c
*
*/
/**
* Copyright 2023-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_vglite.h"
#if LV_USE_DRAW_VGLITE
#include "lv_vglite_buf.h"
#include "lv_vglite_path.h"
#include "lv_vglite_utils.h"
#include "../../../stdlib/lv_string.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**
* Draw triangle shape with effects (opacity, gradient)
*
* @param[in] coords Coordinates of the triangle (relative to dest buff)
* @param[in] clip_area Clipping area with relative coordinates to dest buff
* @param[in] dsc Description of the triangle
*
*/
static void _vglite_draw_triangle(const lv_area_t * coords, const lv_area_t * clip_area,
const lv_draw_triangle_dsc_t * dsc);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_vglite_triangle(lv_draw_unit_t * draw_unit, const lv_draw_triangle_dsc_t * dsc)
{
if(dsc->bg_opa <= (lv_opa_t)LV_OPA_MIN)
return;
lv_layer_t * layer = draw_unit->target_layer;
lv_area_t clip_area;
lv_area_copy(&clip_area, draw_unit->clip_area);
lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_t coords;
coords.x1 = (int32_t)LV_MIN3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x);
coords.y1 = (int32_t)LV_MIN3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y);
coords.x2 = (int32_t)LV_MAX3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x);
coords.y2 = (int32_t)LV_MAX3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y);
lv_area_move(&coords, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_t clipped_coords;
if(!_lv_area_intersect(&clipped_coords, &coords, &clip_area))
return; /* Fully clipped, nothing to do */
_vglite_draw_triangle(&coords, &clip_area, dsc);
}
/**********************
* STATIC FUNCTIONS
**********************/
static void _vglite_draw_triangle(const lv_area_t * coords, const lv_area_t * clip_area,
const lv_draw_triangle_dsc_t * dsc)
{
vg_lite_buffer_t * vgbuf = vglite_get_dest_buf();
lv_area_t tri_area;
tri_area.x1 = (int32_t)LV_MIN3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x);
tri_area.y1 = (int32_t)LV_MIN3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y);
tri_area.x2 = (int32_t)LV_MAX3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x);
tri_area.y2 = (int32_t)LV_MAX3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y);
uint32_t width = tri_area.x2 - tri_area.x1;
uint32_t height = tri_area.y2 - tri_area.y1;
/* Init path */
int32_t triangle_path[] = { /*VG line path*/
VLC_OP_MOVE, dsc->p[0].x, dsc->p[0].y,
VLC_OP_LINE, dsc->p[1].x, dsc->p[1].y,
VLC_OP_LINE, dsc->p[2].x, dsc->p[2].y,
VLC_OP_LINE, dsc->p[0].x, dsc->p[0].y,
VLC_OP_END
};
vg_lite_path_t path;
VGLITE_CHECK_ERROR(vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, sizeof(triangle_path), triangle_path,
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f));
vg_lite_matrix_t matrix;
vg_lite_identity(&matrix);
/* Init Color */
lv_color32_t col32 = lv_color_to_32(dsc->bg_color, dsc->bg_opa);
vg_lite_color_t vgcol = vglite_get_color(col32, false);
vg_lite_linear_gradient_t gradient;
bool has_gradient = (dsc->bg_grad.dir != (lv_grad_dir_t)LV_GRAD_DIR_NONE);
/* Init Gradient*/
if(has_gradient) {
vg_lite_matrix_t * grad_matrix;
vg_lite_uint32_t colors[LV_GRADIENT_MAX_STOPS];
vg_lite_uint32_t stops[LV_GRADIENT_MAX_STOPS];
lv_color32_t col32[LV_GRADIENT_MAX_STOPS];
/* Gradient Setup */
vg_lite_uint32_t cnt = LV_MAX(dsc->bg_grad.stops_count, LV_GRADIENT_MAX_STOPS);
for(uint8_t i = 0; i < cnt; i++) {
stops[i] = dsc->bg_grad.stops[i].frac;
col32[i] = lv_color_to_32(dsc->bg_grad.stops[i].color, dsc->bg_grad.stops[i].opa);
colors[i] = vglite_get_color(col32[i], true);
}
lv_memzero(&gradient, sizeof(vg_lite_linear_gradient_t));
VGLITE_CHECK_ERROR(vg_lite_init_grad(&gradient));
VGLITE_CHECK_ERROR(vg_lite_set_grad(&gradient, cnt, colors, stops));
VGLITE_CHECK_ERROR(vg_lite_update_grad(&gradient));
grad_matrix = vg_lite_get_grad_matrix(&gradient);
vg_lite_identity(grad_matrix);
vg_lite_translate((float)coords->x1, (float)coords->y1, grad_matrix);
if(dsc->bg_grad.dir == (lv_grad_dir_t)LV_GRAD_DIR_VER) {
vg_lite_scale(1.0f, (float)height / 256.0f, grad_matrix);
vg_lite_rotate(90.0f, grad_matrix);
}
else { /*LV_GRAD_DIR_HOR*/
vg_lite_scale((float)width / 256.0f, 1.0f, grad_matrix);
}
VGLITE_CHECK_ERROR(vg_lite_draw_gradient(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, &gradient,
VG_LITE_BLEND_SRC_OVER));
}
else {
VGLITE_CHECK_ERROR(vg_lite_draw(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol));
}
vglite_run();
VGLITE_CHECK_ERROR(vg_lite_clear_path(&path));
if(has_gradient)
VGLITE_CHECK_ERROR(vg_lite_clear_grad(&gradient));
}
#endif /*LV_USE_DRAW_VGLITE*/
+5 -5
View File
@@ -69,20 +69,20 @@ void vglite_set_src_buf_ptr(const void * buf)
_set_vgbuf_ptr(&_src_vgbuf, (void *)buf);
}
void vglite_set_dest_buf(const lv_draw_buf_t * draw_buf)
void vglite_set_dest_buf(const void * buf, uint32_t width, uint32_t height, uint32_t stride,
lv_color_format_t cf)
{
vglite_set_buf(&_dest_vgbuf, draw_buf->buf, draw_buf->width, draw_buf->height,
lv_draw_buf_get_stride(draw_buf), draw_buf->color_format);
vglite_set_buf(&_dest_vgbuf, (void *)buf, width, height, stride, cf);
}
void vglite_set_src_buf(const void * buf, int32_t width, int32_t height, uint32_t stride,
void vglite_set_src_buf(const void * buf, uint32_t width, uint32_t height, uint32_t stride,
lv_color_format_t cf)
{
vglite_set_buf(&_src_vgbuf, (void *)buf, width, height, stride, cf);
}
void vglite_set_buf(vg_lite_buffer_t * vgbuf, void * buf,
int32_t width, int32_t height, uint32_t stride,
uint32_t width, uint32_t height, uint32_t stride,
lv_color_format_t cf)
{
vg_lite_buffer_format_t vgformat = vglite_get_buf_format(cf);
+10 -5
View File
@@ -71,12 +71,17 @@ void vglite_set_dest_buf_ptr(void * buf);
void vglite_set_src_buf_ptr(const void * buf);
/**
* Set vglite target (destination) buffer.
* Set vglite destination buffer.
*
* @param[in] draw_buf Destination draw buffer descriptor
* @param[in] buf Destination buffer address
* @param[in] width Destination buffer width
* @param[in] height Destination buffer height
* @param[in] stride Destination buffer stride in bytes
* @param[in] cf Destination buffer color format
*
*/
void vglite_set_dest_buf(const lv_draw_buf_t * draw_buf);
void vglite_set_dest_buf(const void * buf, uint32_t width, uint32_t height, uint32_t stride,
lv_color_format_t cf);
/**
* Set vglite source buffer.
@@ -88,7 +93,7 @@ void vglite_set_dest_buf(const lv_draw_buf_t * draw_buf);
* @param[in] cf Source buffer color format
*
*/
void vglite_set_src_buf(const void * buf, int32_t width, int32_t height, uint32_t stride,
void vglite_set_src_buf(const void * buf, uint32_t width, uint32_t height, uint32_t stride,
lv_color_format_t cf);
/**
@@ -103,7 +108,7 @@ void vglite_set_src_buf(const void * buf, int32_t width, int32_t height, uint32_
*
*/
void vglite_set_buf(vg_lite_buffer_t * vgbuf, void * buf,
int32_t width, int32_t height, uint32_t stride,
uint32_t width, uint32_t height, uint32_t stride,
lv_color_format_t cf);
/**********************
+4 -3
View File
@@ -58,15 +58,16 @@ void vglite_set_transformation_matrix(const lv_area_t * dest_area, const lv_draw
{
vglite_set_translation_matrix(dest_area);
bool has_scale = (dsc->zoom != LV_SCALE_NONE);
bool has_scale = (dsc->scale_x != LV_SCALE_NONE || dsc->scale_y != LV_SCALE_NONE);
bool has_rotation = (dsc->rotation != 0);
vg_lite_translate(dsc->pivot.x, dsc->pivot.y, &_vgmatrix);
if(has_rotation)
vg_lite_rotate(dsc->rotation / 10.0f, &_vgmatrix); /* angle is 1/10 degree */
if(has_scale) {
vg_lite_float_t scale = 1.0f * dsc->zoom / LV_SCALE_NONE;
vg_lite_scale(scale, scale, &_vgmatrix);
vg_lite_float_t scale_x = 1.0f * dsc->scale_x / LV_SCALE_NONE;
vg_lite_float_t scale_y = 1.0f * dsc->scale_y / LV_SCALE_NONE;
vg_lite_scale(scale_x, scale_y, &_vgmatrix);
}
vg_lite_translate(0.0f - dsc->pivot.x, 0.0f - dsc->pivot.y, &_vgmatrix);
}
+94 -94
View File
@@ -4,7 +4,7 @@
*/
/**
* Copyright 2022, 2023 NXP
* Copyright 2022-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
@@ -20,10 +20,6 @@
#include "../../../core/lv_refr.h"
#if LV_USE_OS
#include "vg_lite_gpu.h"
#endif
/*********************
* DEFINES
*********************/
@@ -40,7 +36,7 @@
* STATIC VARIABLES
**********************/
#if LV_USE_OS
#if LV_USE_VGLITE_DRAW_ASYNC
static volatile bool _cmd_buf_flushed = false;
#endif
@@ -52,7 +48,29 @@
* GLOBAL FUNCTIONS
**********************/
#if LV_USE_OS
const char * vglite_error_to_string(vg_lite_error_t error)
{
switch(error) {
ENUM_TO_STRING(VG_LITE_SUCCESS);
ENUM_TO_STRING(VG_LITE_INVALID_ARGUMENT);
ENUM_TO_STRING(VG_LITE_OUT_OF_MEMORY);
ENUM_TO_STRING(VG_LITE_NO_CONTEXT);
ENUM_TO_STRING(VG_LITE_TIMEOUT);
ENUM_TO_STRING(VG_LITE_OUT_OF_RESOURCES);
ENUM_TO_STRING(VG_LITE_GENERIC_IO);
ENUM_TO_STRING(VG_LITE_NOT_SUPPORT);
ENUM_TO_STRING(VG_LITE_ALREADY_EXISTS);
ENUM_TO_STRING(VG_LITE_NOT_ALIGNED);
ENUM_TO_STRING(VG_LITE_FLEXA_TIME_OUT);
ENUM_TO_STRING(VG_LITE_FLEXA_HANDSHAKE_FAIL);
default:
break;
}
return "VG_LITE_UKNOWN_ERROR";
}
#if LV_USE_VGLITE_DRAW_ASYNC
bool vglite_cmd_buf_is_flushed(void)
{
return _cmd_buf_flushed;
@@ -61,10 +79,12 @@ bool vglite_cmd_buf_is_flushed(void)
void vglite_run(void)
{
#if LV_USE_OS
vg_lite_gpu_state_t gpu_state = vg_lite_get_gpu_state();
#if LV_USE_VGLITE_DRAW_ASYNC
vg_lite_uint32_t gpu_idle = 0;
if(gpu_state == VG_LITE_GPU_BUSY) {
VGLITE_CHECK_ERROR(vg_lite_get_parameter(VG_LITE_GPU_IDLE_STATE, 1, (vg_lite_pointer)&gpu_idle));
if(!gpu_idle) {
_cmd_buf_flushed = false;
return;
@@ -72,15 +92,15 @@ void vglite_run(void)
#endif
/*
* For multithreading version (with OS), we simply flush the command buffer
* and the vglite draw thread will signal the dispatcher for completed tasks.
* Without OS, we process the tasks and signal them as complete one by one.
* If LV_USE_VGLITE_DRAW_ASYNC is enabled, simply flush the command buffer and the
* vglite draw thread will signal asynchronous the dispatcher for completed tasks.
* Without draw async, process the tasks and signal them as complete one by one.
*/
#if LV_USE_OS
LV_ASSERT_MSG(vg_lite_flush() == VG_LITE_SUCCESS, "Flush failed.");
#if LV_USE_VGLITE_DRAW_ASYNC
VGLITE_CHECK_ERROR(vg_lite_flush());
_cmd_buf_flushed = true;
#else
LV_ASSERT_MSG(vg_lite_finish() == VG_LITE_SUCCESS, "Finish failed.");
VGLITE_CHECK_ERROR(vg_lite_finish());
#endif
}
@@ -88,12 +108,10 @@ vg_lite_color_t vglite_get_color(lv_color32_t lv_col32, bool gradient)
{
vg_lite_color_t vg_col32;
/* Only pre-multiply color if hardware pre-multiplication is not present */
if(!vg_lite_query_feature(gcFEATURE_BIT_VG_PE_PREMULTIPLY)) {
lv_col32.red = (uint8_t)((lv_col32.red * lv_col32.alpha) >> 8);
lv_col32.green = (uint8_t)((lv_col32.green * lv_col32.alpha) >> 8);
lv_col32.blue = (uint8_t)((lv_col32.blue * lv_col32.alpha) >> 8);
}
/* Pre-multiply alpha */
lv_col32.red = LV_UDIV255(lv_col32.red * lv_col32.alpha);
lv_col32.green = LV_UDIV255(lv_col32.green * lv_col32.alpha);
lv_col32.blue = LV_UDIV255(lv_col32.blue * lv_col32.alpha);
if(!gradient)
/* The color is in ABGR8888 format with red channel in the lower 8 bits. */
@@ -109,21 +127,45 @@ vg_lite_color_t vglite_get_color(lv_color32_t lv_col32, bool gradient)
vg_lite_blend_t vglite_get_blend_mode(lv_blend_mode_t lv_blend_mode)
{
vg_lite_blend_t vg_blend_mode;
vg_lite_blend_t vg_blend_mode = VG_LITE_BLEND_NONE;
switch(lv_blend_mode) {
case LV_BLEND_MODE_ADDITIVE:
vg_blend_mode = VG_LITE_BLEND_ADDITIVE;
break;
case LV_BLEND_MODE_SUBTRACTIVE:
vg_blend_mode = VG_LITE_BLEND_SUBTRACT;
break;
case LV_BLEND_MODE_MULTIPLY:
vg_blend_mode = VG_LITE_BLEND_MULTIPLY;
break;
default:
vg_blend_mode = VG_LITE_BLEND_SRC_OVER;
break;
if(vg_lite_query_feature(gcFEATURE_BIT_VG_LVGL_SUPPORT)) {
switch(lv_blend_mode) {
case LV_BLEND_MODE_NORMAL:
vg_blend_mode = VG_LITE_BLEND_NORMAL_LVGL;
break;
case LV_BLEND_MODE_ADDITIVE:
vg_blend_mode = VG_LITE_BLEND_ADDITIVE_LVGL;
break;
case LV_BLEND_MODE_SUBTRACTIVE:
vg_blend_mode = VG_LITE_BLEND_SUBTRACT_LVGL;
break;
case LV_BLEND_MODE_MULTIPLY:
vg_blend_mode = VG_LITE_BLEND_MULTIPLY_LVGL;
break;
default:
VGLITE_ASSERT_MSG(false, "Unsupported blend mode.");
break;
}
}
else {
switch(lv_blend_mode) {
case LV_BLEND_MODE_NORMAL:
vg_blend_mode = VG_LITE_BLEND_SRC_OVER;
break;
case LV_BLEND_MODE_ADDITIVE:
vg_blend_mode = VG_LITE_BLEND_ADDITIVE;
break;
case LV_BLEND_MODE_SUBTRACTIVE:
vg_blend_mode = VG_LITE_BLEND_SUBTRACT;
break;
case LV_BLEND_MODE_MULTIPLY:
vg_blend_mode = VG_LITE_BLEND_MULTIPLY;
break;
default:
VGLITE_ASSERT_MSG(false, "Unsupported blend mode.");
break;
}
}
return vg_blend_mode;
@@ -134,7 +176,6 @@ vg_lite_buffer_format_t vglite_get_buf_format(lv_color_format_t cf)
vg_lite_buffer_format_t vg_buffer_format = VG_LITE_BGR565;
switch(cf) {
/*<=1 byte (+alpha) formats*/
case LV_COLOR_FORMAT_L8:
vg_buffer_format = VG_LITE_L8;
break;
@@ -153,18 +194,14 @@ vg_lite_buffer_format_t vglite_get_buf_format(lv_color_format_t cf)
case LV_COLOR_FORMAT_I8:
vg_buffer_format = VG_LITE_INDEX_8;
break;
/*2 byte (+alpha) formats*/
case LV_COLOR_FORMAT_RGB565:
vg_buffer_format = VG_LITE_BGR565;
break;
case LV_COLOR_FORMAT_RGB565A8:
LV_ASSERT_MSG(false, "Unsupported color format.");
vg_buffer_format = VG_LITE_ABGR8565;
break;
/*3 byte (+alpha) formats*/
case LV_COLOR_FORMAT_RGB888:
LV_ASSERT_MSG(false, "Unsupported color format.");
vg_buffer_format = VG_LITE_BGR888;
break;
case LV_COLOR_FORMAT_ARGB8888:
vg_buffer_format = VG_LITE_BGRA8888;
@@ -174,52 +211,13 @@ vg_lite_buffer_format_t vglite_get_buf_format(lv_color_format_t cf)
break;
default:
LV_ASSERT_MSG(false, "Unsupported color format.");
VGLITE_ASSERT_MSG(false, "Unsupported color format.");
break;
}
return vg_buffer_format;
}
uint8_t vglite_get_px_size(lv_color_format_t cf)
{
uint8_t bits_per_pixel = LV_COLOR_DEPTH;
switch(cf) {
case LV_COLOR_FORMAT_I1:
bits_per_pixel = 1;
break;
case LV_COLOR_FORMAT_I2:
bits_per_pixel = 2;
break;
case LV_COLOR_FORMAT_I4:
bits_per_pixel = 4;
break;
case LV_COLOR_FORMAT_I8:
case LV_COLOR_FORMAT_A8:
case LV_COLOR_FORMAT_L8:
bits_per_pixel = 8;
break;
case LV_COLOR_FORMAT_RGB565:
bits_per_pixel = 16;
break;
case LV_COLOR_FORMAT_RGB565A8:
case LV_COLOR_FORMAT_RGB888:
bits_per_pixel = 24;
break;
case LV_COLOR_FORMAT_ARGB8888:
case LV_COLOR_FORMAT_XRGB8888:
bits_per_pixel = 32;
break;
default:
LV_ASSERT_MSG(false, "Unsupported buffer format.");
break;
}
return bits_per_pixel;
}
uint8_t vglite_get_alignment(lv_color_format_t cf)
{
uint8_t align_bytes = LV_COLOR_DEPTH / 8 * 16; /*16 pixels*/
@@ -228,12 +226,20 @@ uint8_t vglite_get_alignment(lv_color_format_t cf)
case LV_COLOR_FORMAT_I1:
case LV_COLOR_FORMAT_I2:
case LV_COLOR_FORMAT_I4:
align_bytes = 8;
/*
* VGLite alignment require 8 bytes.
* But ARM clean and invalidate cache needs 32 bytes address alignment.
*/
align_bytes = 32;
break;
case LV_COLOR_FORMAT_I8:
case LV_COLOR_FORMAT_A8:
case LV_COLOR_FORMAT_L8:
align_bytes = 16;
/*
* VGLite alignment require 16 bytes.
* But ARM clean and invalidate cache needs 32 bytes address alignment.
*/
align_bytes = 32;
break;
case LV_COLOR_FORMAT_RGB565:
align_bytes = 32;
@@ -248,7 +254,7 @@ uint8_t vglite_get_alignment(lv_color_format_t cf)
break;
default:
LV_ASSERT_MSG(false, "Unsupported buffer format.");
VGLITE_ASSERT_MSG(false, "Unsupported buffer format.");
break;
}
@@ -262,18 +268,12 @@ bool vglite_buf_aligned(const void * buf, uint32_t stride, lv_color_format_t cf)
/* No alignment requirement for destination buffer when using mode VG_LITE_LINEAR */
/* Test for pointer alignment */
if((uintptr_t)buf % align_bytes) {
LV_LOG_ERROR("Buffer address (0x%x) not aligned to %d bytes.",
(size_t)buf, align_bytes);
if((uintptr_t)buf % align_bytes)
return false;
}
/* Test for stride alignment */
if(stride % align_bytes) {
LV_LOG_ERROR("Buffer stride (%d bytes) not aligned to %d bytes.",
stride, align_bytes);
if(stride == 0 || stride % align_bytes)
return false;
}
return true;
}
+30 -29
View File
@@ -4,7 +4,7 @@
*/
/**
* Copyright 2022, 2023 NXP
* Copyright 2022-2024 NXP
*
* SPDX-License-Identifier: MIT
*/
@@ -25,11 +25,34 @@ extern "C" {
#include "../../sw/lv_draw_sw.h"
#include "vg_lite.h"
#include "vg_lite_options.h"
/*********************
* DEFINES
*********************/
#define ENUM_TO_STRING(e) \
case (e): \
return #e
#if LV_USE_VGLITE_ASSERT
#define VGLITE_ASSERT(expr) LV_ASSERT(expr)
#define VGLITE_ASSERT_MSG(expr, msg) LV_ASSERT_MSG(expr, msg)
#else
#define VGLITE_ASSERT(expr)
#define VGLITE_ASSERT_MSG(expr, msg) LV_LOG_ERROR(msg)
#endif
#define VGLITE_CHECK_ERROR(function) \
do { \
vg_lite_error_t error = function; \
if(error != VG_LITE_SUCCESS) { \
LV_LOG_ERROR("Execute '" #function "' error(%d): %s", \
(int)error, vglite_error_to_string(error)); \
VGLITE_ASSERT(false); \
} \
} while (0)
/**********************
* TYPEDEFS
**********************/
@@ -39,24 +62,20 @@ extern "C" {
**********************/
/**
* Enable scissor and set the clipping box.
* Set the clipping box.
*
* @param[in] clip_area Clip area with relative coordinates of destination buffer
*
*/
static inline void vglite_set_scissor(const lv_area_t * clip_area);
/**
* Disable scissor.
*
*/
static inline void vglite_disable_scissor(void);
/**********************
* GLOBAL PROTOTYPES
**********************/
#if LV_USE_OS
const char * vglite_error_to_string(vg_lite_error_t error);
#if LV_USE_VGLITE_DRAW_ASYNC
/**
* Get VG-Lite command buffer flushed status.
*
@@ -65,7 +84,7 @@ bool vglite_cmd_buf_is_flushed(void);
#endif
/**
* Clear cache and flush command to VG-Lite.
* Flush command to VG-Lite.
*
*/
void vglite_run(void);
@@ -102,16 +121,6 @@ vg_lite_blend_t vglite_get_blend_mode(lv_blend_mode_t lv_blend_mode);
*/
vg_lite_buffer_format_t vglite_get_buf_format(lv_color_format_t cf);
/**
* Get vglite buffer pixel size.
*
* @param[in] cf Color format
*
* @retval Bits per pixel
*
*/
uint8_t vglite_get_px_size(lv_color_format_t cf);
/**
* Get vglite buffer alignment.
*
@@ -144,15 +153,7 @@ bool vglite_buf_aligned(const void * buf, uint32_t stride, lv_color_format_t cf)
static inline void vglite_set_scissor(const lv_area_t * clip_area)
{
vg_lite_enable_scissor();
vg_lite_set_scissor((int32_t)clip_area->x1, (int32_t)clip_area->y1,
(int32_t)lv_area_get_width(clip_area),
(int32_t)lv_area_get_height(clip_area));
}
static inline void vglite_disable_scissor(void)
{
vg_lite_disable_scissor();
vg_lite_set_scissor(clip_area->x1, clip_area->y1, clip_area->x2 + 1, clip_area->y2 + 1);
}
#endif /*LV_USE_DRAW_VGLITE*/
+75 -29
View File
@@ -189,6 +189,35 @@
#endif
#endif
/*=================
* OPERATING SYSTEM
*=================*/
/*Select an operating system to use. Possible options:
* - LV_OS_NONE
* - LV_OS_PTHREAD
* - LV_OS_FREERTOS
* - LV_OS_CMSIS_RTOS2
* - LV_OS_RTTHREAD
* - LV_OS_WINDOWS
* - LV_OS_CUSTOM */
#ifndef LV_USE_OS
#ifdef CONFIG_LV_USE_OS
#define LV_USE_OS CONFIG_LV_USE_OS
#else
#define LV_USE_OS LV_OS_NONE
#endif
#endif
#if LV_USE_OS == LV_OS_CUSTOM
#ifndef LV_OS_CUSTOM_INCLUDE
#ifdef CONFIG_LV_OS_CUSTOM_INCLUDE
#define LV_OS_CUSTOM_INCLUDE CONFIG_LV_OS_CUSTOM_INCLUDE
#else
#define LV_OS_CUSTOM_INCLUDE <stdint.h>
#endif
#endif
#endif
/*========================
* RENDERING CONFIGURATION
*========================*/
@@ -332,6 +361,41 @@
#endif
#endif
#if LV_USE_DRAW_VGLITE
/* Enable blit quality degradation workaround recommended for screen's dimension > 352 pixels. */
#ifndef LV_USE_VGLITE_BLIT_SPLIT
#ifdef CONFIG_LV_USE_VGLITE_BLIT_SPLIT
#define LV_USE_VGLITE_BLIT_SPLIT CONFIG_LV_USE_VGLITE_BLIT_SPLIT
#else
#define LV_USE_VGLITE_BLIT_SPLIT 0
#endif
#endif
#if LV_USE_OS
/* Enable VGLite draw async. Queue multiple tasks and flash them once to the GPU. */
#ifndef LV_USE_VGLITE_DRAW_ASYNC
#ifdef _LV_KCONFIG_PRESENT
#ifdef CONFIG_LV_USE_VGLITE_DRAW_ASYNC
#define LV_USE_VGLITE_DRAW_ASYNC CONFIG_LV_USE_VGLITE_DRAW_ASYNC
#else
#define LV_USE_VGLITE_DRAW_ASYNC 0
#endif
#else
#define LV_USE_VGLITE_DRAW_ASYNC 1
#endif
#endif
#endif
/* Enable VGLite asserts. */
#ifndef LV_USE_VGLITE_ASSERT
#ifdef CONFIG_LV_USE_VGLITE_ASSERT
#define LV_USE_VGLITE_ASSERT CONFIG_LV_USE_VGLITE_ASSERT
#else
#define LV_USE_VGLITE_ASSERT 0
#endif
#endif
#endif
/* Use NXP's PXP on iMX RTxxx platforms. */
#ifndef LV_USE_DRAW_PXP
#ifdef CONFIG_LV_USE_DRAW_PXP
@@ -341,6 +405,17 @@
#endif
#endif
#if LV_USE_DRAW_PXP
/* Enable PXP asserts. */
#ifndef LV_USE_PXP_ASSERT
#ifdef CONFIG_LV_USE_PXP_ASSERT
#define LV_USE_PXP_ASSERT CONFIG_LV_USE_PXP_ASSERT
#else
#define LV_USE_PXP_ASSERT 0
#endif
#endif
#endif
/* Use Renesas Dave2D on RA platforms. */
#ifndef LV_USE_DRAW_DAVE2D
#ifdef CONFIG_LV_USE_DRAW_DAVE2D
@@ -389,35 +464,6 @@
#endif
/*=================
* OPERATING SYSTEM
*=================*/
/*Select an operating system to use. Possible options:
* - LV_OS_NONE
* - LV_OS_PTHREAD
* - LV_OS_FREERTOS
* - LV_OS_CMSIS_RTOS2
* - LV_OS_RTTHREAD
* - LV_OS_WINDOWS
* - LV_OS_CUSTOM */
#ifndef LV_USE_OS
#ifdef CONFIG_LV_USE_OS
#define LV_USE_OS CONFIG_LV_USE_OS
#else
#define LV_USE_OS LV_OS_NONE
#endif
#endif
#if LV_USE_OS == LV_OS_CUSTOM
#ifndef LV_OS_CUSTOM_INCLUDE
#ifdef CONFIG_LV_OS_CUSTOM_INCLUDE
#define LV_OS_CUSTOM_INCLUDE CONFIG_LV_OS_CUSTOM_INCLUDE
#else
#define LV_OS_CUSTOM_INCLUDE <stdint.h>
#endif
#endif
#endif
/*=======================
* FEATURE CONFIGURATION
*=======================*/
+4 -4
View File
@@ -70,6 +70,10 @@ static void lv_mem_walker(void * ptr, size_t size, int used, void * user);
void lv_mem_init(void)
{
#if LV_USE_OS
lv_mutex_init(&state.mutex);
#endif
#if LV_MEM_ADR == 0
#ifdef LV_MEM_POOL_ALLOC
state.tlsf = lv_tlsf_create_with_pool((void *)LV_MEM_POOL_ALLOC(LV_MEM_SIZE), LV_MEM_SIZE);
@@ -82,10 +86,6 @@ void lv_mem_init(void)
state.tlsf = lv_tlsf_create_with_pool((void *)LV_MEM_ADR, LV_MEM_SIZE);
#endif
#if LV_USE_OS
lv_mutex_init(&state.mutex);
#endif
_lv_ll_init(&state.pool_ll, sizeof(lv_pool_t));
/*Record the first pool*/
@@ -1,4 +1,4 @@
#if LV_BUILD_TEST || 1
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "unity/unity.h"
+1 -1
View File
@@ -1,4 +1,4 @@
#if LV_BUILD_TEST || 1
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "unity/unity.h"
+1 -1
View File
@@ -1,4 +1,4 @@
#if LV_BUILD_TEST || 1
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "unity/unity.h"
+1 -1
View File
@@ -1,4 +1,4 @@
#if LV_BUILD_TEST || 1
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "unity/unity.h"
+1 -1
View File
@@ -1,4 +1,4 @@
#if LV_BUILD_TEST || 1
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "unity/unity.h"