mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-14 06:42:58 +08:00
feat(vglite, pxp): add beta version of NXP's PXP and VG-Lite acceleration (#4568)
Signed-off-by: Nicușor Cîțu <nicusor.citu@nxp.com>
This commit is contained in:
parent
97dad61dd8
commit
733e11d86d
20
Kconfig
20
Kconfig
@ -298,23 +298,11 @@ menu "LVGL configuration"
|
||||
Must be defined to include path of CMSIS header of target processor
|
||||
e.g. "SWM341.h"
|
||||
|
||||
config LV_USE_GPU_NXP_PXP
|
||||
bool "Use NXP's PXP GPU iMX RTxxx platforms."
|
||||
config LV_USE_GPU_NXP_PXP_AUTO_INIT
|
||||
bool "Call lv_gpu_nxp_pxp_init() automatically or manually."
|
||||
depends on LV_USE_GPU_NXP_PXP
|
||||
help
|
||||
1: Add default bare metal and FreeRTOS interrupt handling
|
||||
routines for PXP (lv_gpu_nxp_pxp_osa.c) and call
|
||||
lv_gpu_nxp_pxp_init() automatically during lv_init().
|
||||
Note that symbol SDK_OS_FREE_RTOS has to be defined in order
|
||||
to use FreeRTOS OSA, otherwise bare-metal implementation is
|
||||
selected.
|
||||
0: lv_gpu_nxp_pxp_init() has to be called manually before
|
||||
lv_init().
|
||||
config LV_USE_DRAW_VGLITE
|
||||
bool "Use NXP's VG-Lite GPU on iMX RTxxx platforms."
|
||||
|
||||
config LV_USE_GPU_NXP_VG_LITE
|
||||
bool "Use NXP's VG-Lite GPU iMX RTxxx platforms."
|
||||
config LV_USE_DRAW_PXP
|
||||
bool "Use NXP's PXP on iMX RTxxx platforms."
|
||||
|
||||
config LV_USE_GPU_SDL
|
||||
bool "Use SDL renderer API"
|
||||
|
@ -123,6 +123,12 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Use NXP's VG-Lite GPU on iMX RTxxx platforms. */
|
||||
#define LV_USE_DRAW_VGLITE 0
|
||||
|
||||
/* Use NXP's PXP on iMX RTxxx platforms. */
|
||||
#define LV_USE_DRAW_PXP 0
|
||||
|
||||
/*=================
|
||||
* OPERATING SYSTEM
|
||||
*=================*/
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include "../draw/sw/lv_draw_sw.h"
|
||||
#endif
|
||||
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
99
src/draw/nxp/pxp/lv_draw_buf_pxp.c
Normal file
99
src/draw/nxp/pxp/lv_draw_buf_pxp.c
Normal file
@ -0,0 +1,99 @@
|
||||
/**
|
||||
* @file lv_draw_buf_pxp.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_pxp.h"
|
||||
|
||||
#if LV_USE_DRAW_PXP
|
||||
#include "lv_pxp_cfg.h"
|
||||
#include "lv_pxp_utils.h"
|
||||
|
||||
#include "lvgl_support.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void _invalidate_cache(lv_draw_buf_t * draw_buf, const char * area);
|
||||
|
||||
static 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);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_buf_pxp_init_handlers(void)
|
||||
{
|
||||
lv_draw_buf_handlers_t * handlers = lv_draw_buf_get_handlers();
|
||||
|
||||
handlers->invalidate_cache_cb = _invalidate_cache;
|
||||
handlers->buf_copy_cb = _pxp_buf_copy;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void _invalidate_cache(lv_draw_buf_t * draw_buf, const char * area)
|
||||
{
|
||||
LV_UNUSED(draw_buf);
|
||||
LV_UNUSED(area);
|
||||
|
||||
DEMO_CleanInvalidateCache();
|
||||
}
|
||||
|
||||
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 /*LV_USE_DRAW_PXP*/
|
317
src/draw/nxp/pxp/lv_draw_pxp.c
Normal file
317
src/draw/nxp/pxp/lv_draw_pxp.c
Normal file
@ -0,0 +1,317 @@
|
||||
/**
|
||||
* @file lv_draw_pxp.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2022, 2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_pxp.h"
|
||||
|
||||
#if LV_USE_DRAW_PXP
|
||||
#include "lv_pxp_cfg.h"
|
||||
#include "../../../display/lv_display_private.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define DRAW_UNIT_ID_PXP 3
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/*
|
||||
* Dispatch a task to the PXP unit.
|
||||
* Return 1 if task was dispatched, 0 otherwise (task not supported).
|
||||
*/
|
||||
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).
|
||||
*/
|
||||
static int32_t _pxp_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task);
|
||||
|
||||
#if LV_USE_OS
|
||||
static void _pxp_render_thread_cb(void * ptr);
|
||||
#endif
|
||||
|
||||
static void _pxp_execute_drawing(lv_draw_pxp_unit_t * u);
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static inline bool _pxp_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);
|
||||
|
||||
return is_cf_supported;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/* Recolor and transformation are not supported at the same time. */
|
||||
if(has_recolor && has_transform)
|
||||
return false;
|
||||
|
||||
bool has_opa = (draw_dsc->opa < (lv_opa_t)LV_OPA_MAX);
|
||||
bool src_has_alpha = (img_dsc->header.cf == LV_COLOR_FORMAT_ARGB8888);
|
||||
|
||||
/*
|
||||
* Recolor or transformation for images w/ opa or alpha channel can't
|
||||
* be obtained in a single PXP configuration. Two steps are required.
|
||||
*/
|
||||
if((has_recolor || has_transform) && (has_opa || src_has_alpha))
|
||||
return false;
|
||||
|
||||
/* PXP can only rotate at 90x angles. */
|
||||
if(draw_dsc->rotation % 900)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* PXP is set to process 16x16 blocks to optimize the system for memory
|
||||
* bandwidth and image processing time.
|
||||
* The output engine essentially truncates any output pixels after the
|
||||
* desired number of pixels has been written.
|
||||
* When rotating a source image and the output is not divisible by the block
|
||||
* size, the incorrect pixels could be truncated and the final output image
|
||||
* can look shifted.
|
||||
*
|
||||
* No combination of rotate with flip, scaling or decimation is possible
|
||||
* if buffer is unaligned.
|
||||
*/
|
||||
if(has_transform && (img_dsc->header.w % 16 || img_dsc->header.h % 16))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int32_t _pxp_evaluate(lv_draw_unit_t * u, lv_draw_task_t * t)
|
||||
{
|
||||
LV_UNUSED(u);
|
||||
|
||||
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;
|
||||
|
||||
/* Most simple case: just a plain rectangle (no radius, no gradient). */
|
||||
if((draw_dsc->radius != 0) || (draw_dsc->grad.dir != (lv_grad_dir_t)LV_GRAD_DIR_NONE))
|
||||
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_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))
|
||||
return 0;
|
||||
|
||||
if(!_pxp_draw_img_supported(draw_dsc))
|
||||
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_IMAGE: {
|
||||
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))
|
||||
return 0;
|
||||
|
||||
if(!_pxp_draw_img_supported(draw_dsc))
|
||||
return 0;
|
||||
|
||||
if(t->preference_score > 70) {
|
||||
t->preference_score = 70;
|
||||
t->preferred_draw_unit_id = DRAW_UNIT_ID_PXP;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t _pxp_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
|
||||
{
|
||||
lv_draw_pxp_unit_t * draw_pxp_unit = (lv_draw_pxp_unit_t *) draw_unit;
|
||||
|
||||
/* Return immediately if it's busy with draw task. */
|
||||
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;
|
||||
|
||||
void * buf = lv_draw_layer_alloc_buf(layer);
|
||||
if(buf == NULL)
|
||||
return -1;
|
||||
|
||||
t->state = LV_DRAW_TASK_STATE_IN_PROGRESS;
|
||||
draw_pxp_unit->base_unit.target_layer = layer;
|
||||
draw_pxp_unit->base_unit.clip_area = &t->clip_area;
|
||||
draw_pxp_unit->task_act = t;
|
||||
|
||||
#if LV_USE_OS
|
||||
/* Let the render thread work. */
|
||||
lv_thread_sync_signal(&draw_pxp_unit->sync);
|
||||
#else
|
||||
_pxp_execute_drawing(draw_pxp_unit);
|
||||
|
||||
draw_pxp_unit->task_act->state = LV_DRAW_TASK_STATE_READY;
|
||||
draw_pxp_unit->task_act = NULL;
|
||||
|
||||
/* The draw unit is free now. Request a new dispatching as it can get a new task. */
|
||||
lv_draw_dispatch_request();
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
case LV_DRAW_TASK_TYPE_LAYER:
|
||||
lv_draw_pxp_layer(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if LV_USE_OS
|
||||
static void _pxp_render_thread_cb(void * ptr)
|
||||
{
|
||||
lv_draw_pxp_unit_t * u = ptr;
|
||||
|
||||
lv_thread_sync_init(&u->sync);
|
||||
|
||||
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) {
|
||||
lv_thread_sync_wait(&u->sync);
|
||||
}
|
||||
|
||||
_pxp_execute_drawing(u);
|
||||
|
||||
/* Cleanup. */
|
||||
u->task_act->state = LV_DRAW_TASK_STATE_READY;
|
||||
u->task_act = NULL;
|
||||
|
||||
/* The draw unit is free now. Request a new dispatching as it can get a new task. */
|
||||
lv_draw_dispatch_request();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*LV_USE_DRAW_PXP*/
|
77
src/draw/nxp/pxp/lv_draw_pxp.h
Normal file
77
src/draw/nxp/pxp/lv_draw_pxp.h
Normal file
@ -0,0 +1,77 @@
|
||||
/**
|
||||
* @file lv_draw_pxp.h
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2022, 2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LV_DRAW_PXP_H
|
||||
#define LV_DRAW_PXP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_DRAW_PXP
|
||||
#include "../../sw/lv_draw_sw.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef lv_layer_t lv_pxp_layer_t;
|
||||
|
||||
typedef struct {
|
||||
lv_draw_unit_t base_unit;
|
||||
struct _lv_draw_task_t * task_act;
|
||||
#if LV_USE_OS
|
||||
lv_thread_sync_t sync;
|
||||
lv_thread_t thread;
|
||||
#endif
|
||||
} lv_draw_pxp_unit_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_draw_buf_pxp_init_handlers(void);
|
||||
|
||||
void lv_draw_pxp_init(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_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc,
|
||||
const lv_area_t * coords);
|
||||
|
||||
void lv_draw_pxp_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dsc,
|
||||
const lv_area_t * coords);
|
||||
|
||||
void lv_draw_pxp_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
|
||||
const lv_area_t * coords);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#endif /*LV_USE_DRAW_PXP*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_PXP_H*/
|
94
src/draw/nxp/pxp/lv_draw_pxp_bg_img.c
Normal file
94
src/draw/nxp/pxp/lv_draw_pxp_bg_img.c
Normal file
@ -0,0 +1,94 @@
|
||||
/**
|
||||
* @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*/
|
151
src/draw/nxp/pxp/lv_draw_pxp_fill.c
Normal file
151
src/draw/nxp/pxp/lv_draw_pxp_fill.c
Normal file
@ -0,0 +1,151 @@
|
||||
/**
|
||||
* @file lv_draw_pxp_fill.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2020-2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_pxp.h"
|
||||
|
||||
#if LV_USE_DRAW_PXP
|
||||
#include "lv_pxp_cfg.h"
|
||||
#include "lv_pxp_utils.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void _pxp_fill(uint8_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||
lv_color_format_t dest_cf, const lv_draw_fill_dsc_t * dsc);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_pxp_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc,
|
||||
const lv_area_t * coords)
|
||||
{
|
||||
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
|
||||
return;
|
||||
|
||||
lv_layer_t * layer = draw_unit->target_layer;
|
||||
|
||||
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 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 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;
|
||||
lv_coord_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);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void _pxp_fill(uint8_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||
lv_color_format_t dest_cf, const lv_draw_fill_dsc_t * dsc)
|
||||
{
|
||||
lv_coord_t dest_w = lv_area_get_width(dest_area);
|
||||
lv_coord_t dest_h = lv_area_get_height(dest_area);
|
||||
|
||||
lv_pxp_reset();
|
||||
|
||||
uint8_t px_size = lv_color_format_get_size(dest_cf);
|
||||
|
||||
/*OUT buffer configure*/
|
||||
pxp_output_buffer_config_t outputConfig = {
|
||||
.pixelFormat = pxp_get_out_px_format(dest_cf),
|
||||
.interlacedMode = kPXP_OutputProgressive,
|
||||
.buffer0Addr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + px_size * dest_area->x1),
|
||||
.buffer1Addr = (uint32_t)NULL,
|
||||
.pitchBytes = dest_stride,
|
||||
.width = dest_w,
|
||||
.height = dest_h
|
||||
};
|
||||
|
||||
PXP_SetOutputBufferConfig(PXP_ID, &outputConfig);
|
||||
|
||||
if(dsc->opa >= (lv_opa_t)LV_OPA_MAX) {
|
||||
/*Simple color fill without opacity - AS disabled*/
|
||||
PXP_SetAlphaSurfacePosition(PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
|
||||
|
||||
}
|
||||
else {
|
||||
/*Fill with opacity - AS used as source (same as OUT)*/
|
||||
pxp_as_buffer_config_t asBufferConfig = {
|
||||
.pixelFormat = pxp_get_as_px_format(dest_cf),
|
||||
.bufferAddr = outputConfig.buffer0Addr,
|
||||
.pitchBytes = outputConfig.pitchBytes
|
||||
};
|
||||
|
||||
PXP_SetAlphaSurfaceBufferConfig(PXP_ID, &asBufferConfig);
|
||||
PXP_SetAlphaSurfacePosition(PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U);
|
||||
}
|
||||
|
||||
/*Disable PS, use as color generator*/
|
||||
PXP_SetProcessSurfacePosition(PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
|
||||
PXP_SetProcessSurfaceBackGroundColor(PXP_ID, lv_color_to_u32(dsc->color));
|
||||
|
||||
/**
|
||||
* Configure Porter-Duff blending - src settings are unused for fill without opacity (opa = 0xff).
|
||||
*
|
||||
* Note: srcFactorMode and dstFactorMode are inverted in fsl_pxp.h:
|
||||
* srcFactorMode is actually applied on PS alpha value
|
||||
* dstFactorMode is actually applied on AS alpha value
|
||||
*/
|
||||
pxp_porter_duff_config_t pdConfig = {
|
||||
.enable = 1,
|
||||
.dstColorMode = kPXP_PorterDuffColorNoAlpha,
|
||||
.srcColorMode = kPXP_PorterDuffColorNoAlpha,
|
||||
.dstGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha,
|
||||
.srcGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha,
|
||||
.dstFactorMode = kPXP_PorterDuffFactorStraight,
|
||||
.srcFactorMode = (dsc->opa >= (lv_opa_t)LV_OPA_MAX) ? kPXP_PorterDuffFactorStraight : kPXP_PorterDuffFactorInversed,
|
||||
.dstGlobalAlpha = dsc->opa,
|
||||
.srcGlobalAlpha = dsc->opa,
|
||||
.dstAlphaMode = kPXP_PorterDuffAlphaStraight, /*don't care*/
|
||||
.srcAlphaMode = kPXP_PorterDuffAlphaStraight /*don't care*/
|
||||
};
|
||||
|
||||
PXP_SetPorterDuffConfig(PXP_ID, &pdConfig);
|
||||
|
||||
lv_pxp_run();
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_PXP*/
|
364
src/draw/nxp/pxp/lv_draw_pxp_img.c
Normal file
364
src/draw/nxp/pxp/lv_draw_pxp_img.c
Normal file
@ -0,0 +1,364 @@
|
||||
/**
|
||||
* @file lv_draw_pxp_img.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2020-2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_pxp.h"
|
||||
|
||||
#if LV_USE_DRAW_PXP
|
||||
#include "lv_pxp_cfg.h"
|
||||
#include "lv_pxp_utils.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/* Blit w/ recolor for images w/o opa and alpha channel */
|
||||
static void _pxp_blit_recolor(uint8_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||
lv_color_format_t dest_cf, const uint8_t * src_buf, const lv_area_t * src_area,
|
||||
lv_coord_t src_stride, lv_color_format_t src_cf, const lv_draw_image_dsc_t * dsc);
|
||||
|
||||
/* Blit w/ transformation for images w/o opa and alpha channel */
|
||||
static void _pxp_blit_transform(uint8_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||
lv_color_format_t dest_cf, const uint8_t * src_buf, const lv_area_t * src_area,
|
||||
lv_coord_t src_stride, lv_color_format_t src_cf, const lv_draw_image_dsc_t * dsc);
|
||||
|
||||
/* Blit simple w/ opa and alpha channel */
|
||||
static void _pxp_blit(uint8_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||
lv_color_format_t dest_cf, const uint8_t * src_buf, const lv_area_t * src_area,
|
||||
lv_coord_t src_stride, lv_color_format_t src_cf, lv_opa_t opa);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_pxp_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dsc,
|
||||
const lv_area_t * coords)
|
||||
{
|
||||
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
|
||||
return;
|
||||
|
||||
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 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 blend_area;
|
||||
bool has_transform = dsc->rotation != 0 || dsc->zoom != 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))
|
||||
return; /*Fully clipped, nothing to do*/
|
||||
|
||||
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.x2 = src_area.x1 + lv_area_get_width(coords) - 1;
|
||||
src_area.y2 = src_area.y1 + lv_area_get_height(coords) - 1;
|
||||
lv_coord_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;
|
||||
lv_coord_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);
|
||||
|
||||
if(has_recolor && !has_transform)
|
||||
_pxp_blit_recolor(dest_buf, &blend_area, dest_stride, dest_cf,
|
||||
src_buf, &src_area, src_stride, src_cf, dsc);
|
||||
else if(has_transform)
|
||||
_pxp_blit_transform(dest_buf, &blend_area, dest_stride, dest_cf,
|
||||
src_buf, &src_area, src_stride, src_cf, dsc);
|
||||
else
|
||||
_pxp_blit(dest_buf, &blend_area, dest_stride, dest_cf,
|
||||
src_buf, &src_area, src_stride, src_cf, dsc->opa);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void _pxp_blit_recolor(uint8_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||
lv_color_format_t dest_cf, const uint8_t * src_buf, const lv_area_t * src_area,
|
||||
lv_coord_t src_stride, lv_color_format_t src_cf, const lv_draw_image_dsc_t * dsc)
|
||||
{
|
||||
|
||||
lv_coord_t dest_w = lv_area_get_width(dest_area);
|
||||
lv_coord_t dest_h = lv_area_get_height(dest_area);
|
||||
lv_coord_t src_w = lv_area_get_width(src_area);
|
||||
lv_coord_t src_h = lv_area_get_height(src_area);
|
||||
|
||||
bool src_has_alpha = (src_cf == LV_COLOR_FORMAT_ARGB8888);
|
||||
uint8_t src_px_size = lv_color_format_get_size(src_cf);
|
||||
uint8_t dest_px_size = lv_color_format_get_size(dest_cf);
|
||||
|
||||
lv_pxp_reset();
|
||||
|
||||
/*AS buffer - source image*/
|
||||
pxp_as_buffer_config_t asBufferConfig = {
|
||||
.pixelFormat = pxp_get_as_px_format(src_cf),
|
||||
.bufferAddr = (uint32_t)(src_buf + src_stride * src_area->y1 + src_px_size * src_area->x1),
|
||||
.pitchBytes = src_stride
|
||||
};
|
||||
PXP_SetAlphaSurfaceBufferConfig(PXP_ID, &asBufferConfig);
|
||||
PXP_SetAlphaSurfacePosition(PXP_ID, 0U, 0U, src_w - 1U, src_h - 1U);
|
||||
|
||||
/*Disable PS, use as color generator*/
|
||||
PXP_SetProcessSurfacePosition(PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
|
||||
PXP_SetProcessSurfaceBackGroundColor(PXP_ID, lv_color_to_u32(dsc->recolor));
|
||||
|
||||
/*Output buffer*/
|
||||
pxp_output_buffer_config_t outputBufferConfig = {
|
||||
.pixelFormat = pxp_get_out_px_format(dest_cf),
|
||||
.interlacedMode = kPXP_OutputProgressive,
|
||||
.buffer0Addr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_px_size * dest_area->x1),
|
||||
.buffer1Addr = (uint32_t)0U,
|
||||
.pitchBytes = dest_stride,
|
||||
.width = dest_w,
|
||||
.height = dest_h
|
||||
};
|
||||
PXP_SetOutputBufferConfig(PXP_ID, &outputBufferConfig);
|
||||
|
||||
/**
|
||||
* Configure Porter-Duff blending.
|
||||
*
|
||||
* Note: srcFactorMode and dstFactorMode are inverted in fsl_pxp.h:
|
||||
* srcFactorMode is actually applied on PS alpha value
|
||||
* dstFactorMode is actually applied on AS alpha value
|
||||
*/
|
||||
pxp_porter_duff_config_t pdConfig = {
|
||||
.enable = 1,
|
||||
.dstColorMode = kPXP_PorterDuffColorWithAlpha,
|
||||
.srcColorMode = kPXP_PorterDuffColorWithAlpha,
|
||||
.dstGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha,
|
||||
.srcGlobalAlphaMode = src_has_alpha ? kPXP_PorterDuffLocalAlpha : kPXP_PorterDuffGlobalAlpha,
|
||||
.dstFactorMode = kPXP_PorterDuffFactorStraight,
|
||||
.srcFactorMode = kPXP_PorterDuffFactorInversed,
|
||||
.dstGlobalAlpha = dsc->recolor_opa,
|
||||
.srcGlobalAlpha = 0xff,
|
||||
.dstAlphaMode = kPXP_PorterDuffAlphaStraight, /*don't care*/
|
||||
.srcAlphaMode = kPXP_PorterDuffAlphaStraight
|
||||
};
|
||||
PXP_SetPorterDuffConfig(PXP_ID, &pdConfig);
|
||||
|
||||
lv_pxp_run();
|
||||
}
|
||||
|
||||
static void _pxp_blit_transform(uint8_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||
lv_color_format_t dest_cf, const uint8_t * src_buf, const lv_area_t * src_area,
|
||||
lv_coord_t src_stride, lv_color_format_t src_cf, const lv_draw_image_dsc_t * dsc)
|
||||
{
|
||||
lv_coord_t src_w = lv_area_get_width(src_area);
|
||||
lv_coord_t src_h = lv_area_get_height(src_area);
|
||||
lv_coord_t dest_w = lv_area_get_width(dest_area);
|
||||
lv_coord_t dest_h = lv_area_get_height(dest_area);
|
||||
|
||||
lv_point_t pivot = dsc->pivot;
|
||||
/*The offsets are now relative to the transformation result with pivot ULC*/
|
||||
lv_coord_t piv_offset_x = 0;
|
||||
lv_coord_t piv_offset_y = 0;
|
||||
|
||||
lv_coord_t trim_size = 0;
|
||||
|
||||
bool has_rotation = (dsc->rotation != 0);
|
||||
bool has_scale = (dsc->zoom != 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);
|
||||
|
||||
lv_pxp_reset();
|
||||
|
||||
if(has_rotation) {
|
||||
/*Convert rotation angle and calculate offsets caused by pivot*/
|
||||
pxp_rotate_degree_t pxp_angle;
|
||||
switch(dsc->rotation) {
|
||||
case 0:
|
||||
pxp_angle = kPXP_Rotate0;
|
||||
piv_offset_x = 0;
|
||||
piv_offset_y = 0;
|
||||
break;
|
||||
case 900:
|
||||
pxp_angle = kPXP_Rotate90;
|
||||
piv_offset_x = pivot.x + pivot.y - src_h;
|
||||
piv_offset_y = pivot.y - pivot.x;
|
||||
break;
|
||||
case 1800:
|
||||
pxp_angle = kPXP_Rotate180;
|
||||
piv_offset_x = 2 * pivot.x - src_w;
|
||||
piv_offset_y = 2 * pivot.y - src_h;
|
||||
break;
|
||||
case 2700:
|
||||
pxp_angle = kPXP_Rotate270;
|
||||
piv_offset_x = pivot.x - pivot.y;
|
||||
piv_offset_y = pivot.x + pivot.y - src_w;
|
||||
break;
|
||||
default:
|
||||
pxp_angle = kPXP_Rotate0;
|
||||
piv_offset_x = 0;
|
||||
piv_offset_y = 0;
|
||||
}
|
||||
/*PS buffer rotation and decimation does not function at the same time*/
|
||||
PXP_SetRotateConfig(PXP_ID, kPXP_RotateOutputBuffer, pxp_angle, kPXP_FlipDisable);
|
||||
}
|
||||
|
||||
if(has_scale) {
|
||||
float scale_factor_fp = (float)dsc->zoom / LV_SCALE_NONE;
|
||||
lv_coord_t scale_factor_int = (lv_coord_t)scale_factor_fp;
|
||||
|
||||
/*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;
|
||||
|
||||
dest_w = src_w * scale_factor_fp + trim_size;
|
||||
dest_h = src_h * scale_factor_fp + trim_size;
|
||||
|
||||
/*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);
|
||||
}
|
||||
|
||||
/*PS buffer - source image*/
|
||||
pxp_ps_buffer_config_t psBufferConfig = {
|
||||
.pixelFormat = pxp_get_ps_px_format(src_cf),
|
||||
.swapByte = false,
|
||||
.bufferAddr = (uint32_t)(src_buf + src_stride * src_area->y1 + src_px_size * src_area->x1),
|
||||
.bufferAddrU = 0,
|
||||
.bufferAddrV = 0,
|
||||
.pitchBytes = src_stride
|
||||
};
|
||||
PXP_SetProcessSurfaceBufferConfig(PXP_ID, &psBufferConfig);
|
||||
PXP_SetProcessSurfacePosition(PXP_ID, 0U, 0U, dest_w - trim_size - 1U, dest_h - trim_size - 1U);
|
||||
|
||||
if(has_scale)
|
||||
PXP_SetProcessSurfaceScaler(PXP_ID, src_w, src_h, dest_w, dest_h);
|
||||
|
||||
/*AS disabled */
|
||||
PXP_SetAlphaSurfacePosition(PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
|
||||
|
||||
/*Output buffer*/
|
||||
pxp_output_buffer_config_t outputBufferConfig = {
|
||||
.pixelFormat = pxp_get_out_px_format(dest_cf),
|
||||
.interlacedMode = kPXP_OutputProgressive,
|
||||
.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
|
||||
};
|
||||
PXP_SetOutputBufferConfig(PXP_ID, &outputBufferConfig);
|
||||
|
||||
lv_pxp_run();
|
||||
}
|
||||
|
||||
static void _pxp_blit(uint8_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||
lv_color_format_t dest_cf, const uint8_t * src_buf, const lv_area_t * src_area,
|
||||
lv_coord_t src_stride, lv_color_format_t src_cf, lv_opa_t opa)
|
||||
{
|
||||
lv_coord_t dest_w = lv_area_get_width(dest_area);
|
||||
lv_coord_t dest_h = lv_area_get_height(dest_area);
|
||||
lv_coord_t src_w = lv_area_get_width(src_area);
|
||||
lv_coord_t src_h = lv_area_get_height(src_area);
|
||||
|
||||
bool src_has_alpha = (src_cf == LV_COLOR_FORMAT_ARGB8888);
|
||||
uint8_t src_px_size = lv_color_format_get_size(src_cf);
|
||||
uint8_t dest_px_size = lv_color_format_get_size(dest_cf);
|
||||
|
||||
lv_pxp_reset();
|
||||
|
||||
pxp_as_blend_config_t asBlendConfig = {
|
||||
.alpha = opa,
|
||||
.invertAlpha = false,
|
||||
.alphaMode = kPXP_AlphaRop,
|
||||
.ropMode = kPXP_RopMergeAs
|
||||
};
|
||||
|
||||
if(opa >= (lv_opa_t)LV_OPA_MAX && !src_has_alpha) {
|
||||
/*Simple blit, no effect - Disable PS buffer*/
|
||||
PXP_SetProcessSurfacePosition(PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
|
||||
}
|
||||
else {
|
||||
/*PS must be enabled to fetch background pixels.
|
||||
PS and OUT buffers are the same, blend will be done in-place*/
|
||||
pxp_ps_buffer_config_t psBufferConfig = {
|
||||
.pixelFormat = pxp_get_ps_px_format(dest_cf),
|
||||
.swapByte = false,
|
||||
.bufferAddr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_px_size * dest_area->x1),
|
||||
.bufferAddrU = 0U,
|
||||
.bufferAddrV = 0U,
|
||||
.pitchBytes = dest_stride
|
||||
};
|
||||
|
||||
if(opa >= (lv_opa_t)LV_OPA_MAX)
|
||||
asBlendConfig.alphaMode = src_has_alpha ? kPXP_AlphaEmbedded : kPXP_AlphaOverride;
|
||||
else
|
||||
asBlendConfig.alphaMode = src_has_alpha ? kPXP_AlphaMultiply : kPXP_AlphaOverride;
|
||||
|
||||
PXP_SetProcessSurfaceBufferConfig(PXP_ID, &psBufferConfig);
|
||||
PXP_SetProcessSurfacePosition(PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U);
|
||||
}
|
||||
|
||||
/*AS buffer - source image*/
|
||||
pxp_as_buffer_config_t asBufferConfig = {
|
||||
.pixelFormat = pxp_get_as_px_format(src_cf),
|
||||
.bufferAddr = (uint32_t)(src_buf + src_stride * src_area->y1 + src_px_size * src_area->x1),
|
||||
.pitchBytes = src_stride
|
||||
};
|
||||
PXP_SetAlphaSurfaceBufferConfig(PXP_ID, &asBufferConfig);
|
||||
PXP_SetAlphaSurfacePosition(PXP_ID, 0U, 0U, src_w - 1U, src_h - 1U);
|
||||
PXP_SetAlphaSurfaceBlendConfig(PXP_ID, &asBlendConfig);
|
||||
PXP_EnableAlphaSurfaceOverlayColorKey(PXP_ID, false);
|
||||
|
||||
/*Output buffer.*/
|
||||
pxp_output_buffer_config_t outputBufferConfig = {
|
||||
.pixelFormat = pxp_get_out_px_format(dest_cf),
|
||||
.interlacedMode = kPXP_OutputProgressive,
|
||||
.buffer0Addr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_px_size * dest_area->x1),
|
||||
.buffer1Addr = (uint32_t)0U,
|
||||
.pitchBytes = dest_stride,
|
||||
.width = dest_w,
|
||||
.height = dest_h
|
||||
};
|
||||
PXP_SetOutputBufferConfig(PXP_ID, &outputBufferConfig);
|
||||
|
||||
lv_pxp_run();
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_PXP*/
|
71
src/draw/nxp/pxp/lv_draw_pxp_layer.c
Normal file
71
src/draw/nxp/pxp/lv_draw_pxp_layer.c
Normal file
@ -0,0 +1,71 @@
|
||||
/**
|
||||
* @file lv_draw_pxp_layer.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_pxp.h"
|
||||
|
||||
#if LV_USE_DRAW_PXP
|
||||
|
||||
#include "../../../stdlib/lv_string.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_pxp_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
|
||||
const lv_area_t * coords)
|
||||
{
|
||||
lv_layer_t * layer_to_draw = (lv_layer_t *)draw_dsc->src;
|
||||
|
||||
/*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)
|
||||
return;
|
||||
|
||||
lv_image_dsc_t img_dsc;
|
||||
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.header.always_zero = 0;
|
||||
img_dsc.data = lv_draw_buf_get_buf(&layer_to_draw->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);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_PXP*/
|
96
src/draw/nxp/pxp/lv_pxp_cfg.c
Normal file
96
src/draw/nxp/pxp/lv_pxp_cfg.c
Normal file
@ -0,0 +1,96 @@
|
||||
/**
|
||||
* @file lv_pxp_cfg.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2020-2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_pxp_cfg.h"
|
||||
|
||||
#if LV_USE_DRAW_PXP
|
||||
#include "lv_pxp_osa.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
static pxp_cfg_t * _pxp_cfg;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
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.*/
|
||||
PXP_SetProcessBlockSize(PXP_ID, kPXP_BlockSize16); /*Block size 16x16 for higher performance*/
|
||||
|
||||
PXP_EnableInterrupts(PXP_ID, kPXP_CompleteInterruptEnable);
|
||||
|
||||
_pxp_cfg->pxp_interrupt_init();
|
||||
}
|
||||
|
||||
void lv_pxp_deinit(void)
|
||||
{
|
||||
_pxp_cfg->pxp_interrupt_deinit();
|
||||
PXP_DisableInterrupts(PXP_ID, kPXP_CompleteInterruptEnable);
|
||||
PXP_Deinit(PXP_ID);
|
||||
}
|
||||
|
||||
void lv_pxp_reset(void)
|
||||
{
|
||||
PXP_ResetControl(PXP_ID);
|
||||
|
||||
PXP_EnableCsc1(PXP_ID, false); /*Disable CSC1, it is enabled by default.*/
|
||||
PXP_SetProcessBlockSize(PXP_ID, kPXP_BlockSize16); /*Block size 16x16 for higher performance*/
|
||||
}
|
||||
|
||||
void lv_pxp_run(void)
|
||||
{
|
||||
_pxp_cfg->pxp_run();
|
||||
_pxp_cfg->pxp_wait();
|
||||
}
|
||||
|
||||
void lv_pxp_wait(void)
|
||||
{
|
||||
_pxp_cfg->pxp_wait();
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_DRAW_PXP*/
|
103
src/draw/nxp/pxp/lv_pxp_cfg.h
Normal file
103
src/draw/nxp/pxp/lv_pxp_cfg.h
Normal file
@ -0,0 +1,103 @@
|
||||
/**
|
||||
* @file lv_pxp_cfg.h
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2020-2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LV_PXP_CFG_H
|
||||
#define LV_PXP_CFG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_DRAW_PXP
|
||||
#include "fsl_cache.h"
|
||||
#include "fsl_pxp.h"
|
||||
|
||||
#include "../../../misc/lv_log.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/** PXP module instance to use*/
|
||||
#define PXP_ID PXP
|
||||
|
||||
/** PXP interrupt line ID*/
|
||||
#define PXP_IRQ_ID PXP_IRQn
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* NXP PXP device configuration.
|
||||
*/
|
||||
typedef struct {
|
||||
/** Callback for PXP interrupt initialization*/
|
||||
void (*pxp_interrupt_init)(void);
|
||||
|
||||
/** Callback for PXP interrupt de-initialization*/
|
||||
void (*pxp_interrupt_deinit)(void);
|
||||
|
||||
/** Callback for PXP start*/
|
||||
void (*pxp_run)(void);
|
||||
|
||||
/** Callback for waiting of PXP completion*/
|
||||
void (*pxp_wait)(void);
|
||||
} pxp_cfg_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Reset and initialize PXP device. This function should be called as a part
|
||||
* of display init sequence.
|
||||
*/
|
||||
void lv_pxp_init(void);
|
||||
|
||||
/**
|
||||
* Disable PXP device. Should be called during display deinit sequence.
|
||||
*/
|
||||
void lv_pxp_deinit(void);
|
||||
|
||||
/**
|
||||
* Reset PXP device.
|
||||
*/
|
||||
void lv_pxp_reset(void);
|
||||
|
||||
/**
|
||||
* Clear cache and start PXP.
|
||||
*/
|
||||
void lv_pxp_run(void);
|
||||
|
||||
/**
|
||||
* Wait for PXP completion.
|
||||
*/
|
||||
void lv_pxp_wait(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_DRAW_PXP*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_PXP_CFG_H*/
|
168
src/draw/nxp/pxp/lv_pxp_osa.c
Normal file
168
src/draw/nxp/pxp/lv_pxp_osa.c
Normal file
@ -0,0 +1,168 @@
|
||||
/**
|
||||
* @file lv_pxp_osa.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2020, 2022, 2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_pxp_osa.h"
|
||||
|
||||
#if LV_USE_DRAW_PXP
|
||||
#include "../../../misc/lv_log.h"
|
||||
#include "fsl_pxp.h"
|
||||
|
||||
#if defined(SDK_OS_FREE_RTOS)
|
||||
#include "FreeRTOS.h"
|
||||
#include "semphr.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* PXP interrupt initialization.
|
||||
*/
|
||||
static void _pxp_interrupt_init(void);
|
||||
|
||||
/**
|
||||
* PXP interrupt de-initialization.
|
||||
*/
|
||||
static void _pxp_interrupt_deinit(void);
|
||||
|
||||
/**
|
||||
* Start the PXP job.
|
||||
*/
|
||||
static void _pxp_run(void);
|
||||
|
||||
/**
|
||||
* Wait for PXP completion.
|
||||
*/
|
||||
static void _pxp_wait(void);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
#if defined(SDK_OS_FREE_RTOS)
|
||||
static SemaphoreHandle_t xPXPIdleSemaphore;
|
||||
#endif
|
||||
static volatile bool ucPXPIdle;
|
||||
|
||||
static pxp_cfg_t _pxp_default_cfg = {
|
||||
.pxp_interrupt_init = _pxp_interrupt_init,
|
||||
.pxp_interrupt_deinit = _pxp_interrupt_deinit,
|
||||
.pxp_run = _pxp_run,
|
||||
.pxp_wait = _pxp_wait,
|
||||
};
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void PXP_IRQHandler(void)
|
||||
{
|
||||
#if defined(SDK_OS_FREE_RTOS)
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
#endif
|
||||
|
||||
if(kPXP_CompleteFlag & PXP_GetStatusFlags(PXP_ID)) {
|
||||
PXP_ClearStatusFlags(PXP_ID, kPXP_CompleteFlag);
|
||||
#if defined(SDK_OS_FREE_RTOS)
|
||||
xSemaphoreGiveFromISR(xPXPIdleSemaphore, &xHigherPriorityTaskWoken);
|
||||
|
||||
/* If xHigherPriorityTaskWoken is now set to pdTRUE then a context switch
|
||||
should be performed to ensure the interrupt returns directly to the highest
|
||||
priority task. The macro used for this purpose is dependent on the port in
|
||||
use and may be called portEND_SWITCHING_ISR(). */
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
#else
|
||||
ucPXPIdle = true;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
pxp_cfg_t * pxp_get_default_cfg(void)
|
||||
{
|
||||
return &_pxp_default_cfg;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void _pxp_interrupt_init(void)
|
||||
{
|
||||
#if defined(SDK_OS_FREE_RTOS)
|
||||
xPXPIdleSemaphore = xSemaphoreCreateBinary();
|
||||
if(xPXPIdleSemaphore == NULL) {
|
||||
LV_LOG_ERROR("xSemaphoreCreateBinary failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
NVIC_SetPriority(PXP_IRQ_ID, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1);
|
||||
#endif
|
||||
ucPXPIdle = true;
|
||||
|
||||
NVIC_EnableIRQ(PXP_IRQ_ID);
|
||||
}
|
||||
|
||||
static void _pxp_interrupt_deinit(void)
|
||||
{
|
||||
NVIC_DisableIRQ(PXP_IRQ_ID);
|
||||
#if defined(SDK_OS_FREE_RTOS)
|
||||
vSemaphoreDelete(xPXPIdleSemaphore);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to start PXP job.
|
||||
*/
|
||||
static void _pxp_run(void)
|
||||
{
|
||||
ucPXPIdle = false;
|
||||
|
||||
PXP_EnableInterrupts(PXP_ID, kPXP_CompleteInterruptEnable);
|
||||
PXP_Start(PXP_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to wait for PXP completion.
|
||||
*/
|
||||
static void _pxp_wait(void)
|
||||
{
|
||||
#if defined(SDK_OS_FREE_RTOS)
|
||||
/* Return if PXP was never started, otherwise the semaphore will lock forever. */
|
||||
if(ucPXPIdle == true)
|
||||
return;
|
||||
|
||||
if(xSemaphoreTake(xPXPIdleSemaphore, portMAX_DELAY) == pdTRUE)
|
||||
ucPXPIdle = true;
|
||||
#else
|
||||
while(ucPXPIdle == false) {
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_PXP*/
|
61
src/draw/nxp/pxp/lv_pxp_osa.h
Normal file
61
src/draw/nxp/pxp/lv_pxp_osa.h
Normal file
@ -0,0 +1,61 @@
|
||||
/**
|
||||
* @file lv_pxp_osa.h
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2020, 2022, 2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LV_PXP_OSA_H
|
||||
#define LV_PXP_OSA_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_DRAW_PXP
|
||||
#include "lv_pxp_cfg.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* PXP device interrupt handler. Used to check PXP task completion status.
|
||||
*/
|
||||
void PXP_IRQHandler(void);
|
||||
|
||||
/**
|
||||
* Get the PXP default configuration.
|
||||
*/
|
||||
pxp_cfg_t * pxp_get_default_cfg(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_DRAW_PXP*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_PXP_OSA_H*/
|
151
src/draw/nxp/pxp/lv_pxp_utils.c
Normal file
151
src/draw/nxp/pxp/lv_pxp_utils.c
Normal file
@ -0,0 +1,151 @@
|
||||
/**
|
||||
* @file lv_pxp_utils.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_pxp_utils.h"
|
||||
|
||||
#if LV_USE_DRAW_PXP
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
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;
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
out_px_format = kPXP_OutputPixelFormatARGB8888;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_XRGB8888:
|
||||
out_px_format = kPXP_OutputPixelFormatRGB888;
|
||||
break;
|
||||
|
||||
default:
|
||||
LV_ASSERT_MSG(false, "Unsupported color format.");
|
||||
break;
|
||||
}
|
||||
|
||||
return out_px_format;
|
||||
}
|
||||
|
||||
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.");
|
||||
break;
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
as_px_format = kPXP_AsPixelFormatARGB8888;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_XRGB8888:
|
||||
as_px_format = kPXP_AsPixelFormatRGB888;
|
||||
break;
|
||||
|
||||
default:
|
||||
LV_ASSERT_MSG(false, "Unsupported color format.");
|
||||
break;
|
||||
}
|
||||
|
||||
return as_px_format;
|
||||
}
|
||||
|
||||
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.");
|
||||
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.");
|
||||
#endif
|
||||
break;
|
||||
case LV_COLOR_FORMAT_XRGB8888:
|
||||
#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
|
||||
ps_px_format = kPXP_PsPixelFormatRGB888;
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
LV_ASSERT_MSG(false, "Unsupported color format.");
|
||||
break;
|
||||
}
|
||||
|
||||
return ps_px_format;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_DRAW_PXP*/
|
65
src/draw/nxp/pxp/lv_pxp_utils.h
Normal file
65
src/draw/nxp/pxp/lv_pxp_utils.h
Normal file
@ -0,0 +1,65 @@
|
||||
/**
|
||||
* @file lv_pxp_utils.h
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LV_PXP_UTILS_H
|
||||
#define LV_PXP_UTILS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_DRAW_PXP
|
||||
#include "fsl_pxp.h"
|
||||
#include "../../../misc/lv_color.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
pxp_output_pixel_format_t pxp_get_out_px_format(lv_color_format_t cf);
|
||||
|
||||
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);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_DRAW_PXP*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_PXP_UTILS_H*/
|
194
src/draw/nxp/vglite/lv_draw_buf_vglite.c
Normal file
194
src/draw/nxp/vglite/lv_draw_buf_vglite.c
Normal file
@ -0,0 +1,194 @@
|
||||
/**
|
||||
* @file lv_draw_buf_vglite.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_vglite.h"
|
||||
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
#include "lv_vglite_buf.h"
|
||||
#include "lv_vglite_matrix.h"
|
||||
#include "lv_vglite_utils.h"
|
||||
|
||||
#include "lvgl_support.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
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 _invalidate_cache(lv_draw_buf_t * draw_buf, const char * 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, lv_coord_t x, lv_coord_t y);
|
||||
|
||||
static void _vglite_buf_clear(lv_draw_buf_t * draw_buf, const lv_area_t * area);
|
||||
|
||||
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);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
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->invalidate_cache_cb = _invalidate_cache;
|
||||
handlers->width_to_stride_cb = _width_to_stride;
|
||||
handlers->go_to_xy_cb = _go_to_xy;
|
||||
handlers->buf_clear_cb = _vglite_buf_clear;
|
||||
handlers->buf_copy_cb = _vglite_buf_copy;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void * _buf_malloc(size_t size_bytes, lv_color_format_t cf)
|
||||
{
|
||||
uint8_t align_bytes = vglite_get_alignment(cf);
|
||||
|
||||
/*Allocate larger memory to be sure it can be aligned as needed*/
|
||||
size_bytes += align_bytes - 1;
|
||||
|
||||
return lv_malloc(size_bytes);
|
||||
}
|
||||
|
||||
static void * _align_buf(void * buf, lv_color_format_t cf)
|
||||
{
|
||||
uint8_t align_bytes = vglite_get_alignment(cf);
|
||||
|
||||
uint8_t * buf_u8 = buf;
|
||||
if(buf_u8) {
|
||||
buf_u8 += align_bytes - 1;
|
||||
buf_u8 = (uint8_t *)((lv_uintptr_t)buf_u8 & ~(align_bytes - 1));
|
||||
}
|
||||
|
||||
return buf_u8;
|
||||
}
|
||||
|
||||
static void _invalidate_cache(lv_draw_buf_t * draw_buf, const char * area)
|
||||
{
|
||||
LV_UNUSED(draw_buf);
|
||||
LV_UNUSED(area);
|
||||
|
||||
DEMO_CleanInvalidateCache();
|
||||
}
|
||||
|
||||
static uint32_t _width_to_stride(uint32_t w, lv_color_format_t cf)
|
||||
{
|
||||
uint8_t bits_per_pixel = vglite_get_px_size(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);
|
||||
|
||||
return (width_bytes + align_bytes - 1) & ~(align_bytes - 1);
|
||||
}
|
||||
|
||||
static void * _go_to_xy(lv_draw_buf_t * draw_buf, lv_coord_t x, lv_coord_t y)
|
||||
{
|
||||
uint8_t bits_per_pixel = vglite_get_px_size(draw_buf->color_format);
|
||||
uint32_t stride = lv_draw_buf_get_stride(draw_buf);
|
||||
uint8_t * buf_tmp = lv_draw_buf_get_buf(draw_buf);
|
||||
|
||||
buf_tmp += stride * y;
|
||||
buf_tmp += (x * bits_per_pixel) / 8;
|
||||
|
||||
return buf_tmp;
|
||||
}
|
||||
|
||||
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 /*LV_USE_DRAW_VGLITE*/
|
439
src/draw/nxp/vglite/lv_draw_vglite.c
Normal file
439
src/draw/nxp/vglite/lv_draw_vglite.c
Normal file
@ -0,0 +1,439 @@
|
||||
/**
|
||||
* @file lv_draw_vglite.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_vglite.h"
|
||||
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
#include "lv_vglite_buf.h"
|
||||
#include "lv_vglite_utils.h"
|
||||
|
||||
#include "../../../display/lv_display_private.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define DRAW_UNIT_ID_VGLITE 2
|
||||
|
||||
#if LV_USE_OS
|
||||
#define VGLITE_TASK_BUF_SIZE 10
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
#if LV_USE_OS
|
||||
/**
|
||||
* Structure of pending vglite draw task
|
||||
*/
|
||||
typedef struct _vglite_draw_task_t {
|
||||
lv_draw_task_t * task;
|
||||
bool flushed;
|
||||
} vglite_draw_tasks_t;
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/*
|
||||
* Dispatch a task to the VGLite unit.
|
||||
* 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).
|
||||
*/
|
||||
static int32_t _vglite_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task);
|
||||
|
||||
#if LV_USE_OS
|
||||
static void _vglite_render_thread_cb(void * ptr);
|
||||
#endif
|
||||
|
||||
static void _vglite_execute_drawing(lv_draw_vglite_unit_t * u);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
#if LV_USE_OS
|
||||
/*
|
||||
* Circular buffer to hold the queued and the flushed tasks.
|
||||
* Two indexes, _head and _tail, are used to signal the beginning
|
||||
* and the end of the valid tasks that are pending.
|
||||
*/
|
||||
static vglite_draw_tasks_t _draw_task_buf[VGLITE_TASK_BUF_SIZE];
|
||||
static volatile int _head = 0;
|
||||
static volatile int _tail = 0;
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
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;
|
||||
|
||||
#if LV_USE_OS
|
||||
lv_thread_init(&draw_vglite_unit->thread, LV_THREAD_PRIO_HIGH, _vglite_render_thread_cb, 8 * 1024, draw_vglite_unit);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static inline bool _vglite_cf_supported(lv_color_format_t cf)
|
||||
{
|
||||
// Add here the platform specific code for supported formats.
|
||||
|
||||
bool is_cf_unsupported = (cf == LV_COLOR_FORMAT_RGB565A8 || cf == LV_COLOR_FORMAT_RGB888);
|
||||
|
||||
return (!is_cf_unsupported);
|
||||
}
|
||||
|
||||
static int32_t _vglite_evaluate(lv_draw_unit_t * u, lv_draw_task_t * t)
|
||||
{
|
||||
LV_UNUSED(u);
|
||||
|
||||
switch(t->type) {
|
||||
case LV_DRAW_TASK_TYPE_FILL:
|
||||
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_LINE:
|
||||
case LV_DRAW_TASK_TYPE_ARC:
|
||||
if(t->preference_score > 90) {
|
||||
t->preference_score = 90;
|
||||
t->preferred_draw_unit_id = DRAW_UNIT_ID_VGLITE;
|
||||
}
|
||||
return 1;
|
||||
|
||||
case LV_DRAW_TASK_TYPE_LABEL:
|
||||
if(t->preference_score > 95) {
|
||||
t->preference_score = 95;
|
||||
t->preferred_draw_unit_id = DRAW_UNIT_ID_VGLITE;
|
||||
}
|
||||
return 1;
|
||||
|
||||
case LV_DRAW_TASK_TYPE_BORDER: {
|
||||
const lv_draw_border_dsc_t * draw_dsc = (lv_draw_border_dsc_t *) t->draw_dsc;
|
||||
|
||||
if(draw_dsc->side != (lv_border_side_t)LV_BORDER_SIDE_FULL)
|
||||
return 0;
|
||||
|
||||
if(t->preference_score > 90) {
|
||||
t->preference_score = 90;
|
||||
t->preferred_draw_unit_id = DRAW_UNIT_ID_VGLITE;
|
||||
}
|
||||
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))
|
||||
)
|
||||
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_IMAGE: {
|
||||
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);
|
||||
#endif
|
||||
|
||||
if(has_recolor
|
||||
#if VGLITE_BLIT_SPLIT_ENABLED
|
||||
|| 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;
|
||||
|
||||
if(t->preference_score > 80) {
|
||||
t->preference_score = 80;
|
||||
t->preferred_draw_unit_id = DRAW_UNIT_ID_VGLITE;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t _vglite_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
|
||||
{
|
||||
lv_draw_vglite_unit_t * draw_vglite_unit = (lv_draw_vglite_unit_t *) draw_unit;
|
||||
|
||||
/* Return immediately if it's busy with draw task. */
|
||||
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;
|
||||
|
||||
void * buf = lv_draw_layer_alloc_buf(layer);
|
||||
if(buf == NULL)
|
||||
return -1;
|
||||
|
||||
t->state = LV_DRAW_TASK_STATE_IN_PROGRESS;
|
||||
draw_vglite_unit->base_unit.target_layer = layer;
|
||||
draw_vglite_unit->base_unit.clip_area = &t->clip_area;
|
||||
draw_vglite_unit->task_act = t;
|
||||
|
||||
#if LV_USE_OS
|
||||
/* Let the render thread work. */
|
||||
lv_thread_sync_signal(&draw_vglite_unit->sync);
|
||||
#else
|
||||
_vglite_execute_drawing(draw_vglite_unit);
|
||||
|
||||
draw_vglite_unit->task_act->state = LV_DRAW_TASK_STATE_READY;
|
||||
draw_vglite_unit->task_act = NULL;
|
||||
|
||||
/* The draw unit is free now. Request a new dispatching as it can get a new task. */
|
||||
lv_draw_dispatch_request();
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/* Set target buffer */
|
||||
lv_layer_t * layer = draw_unit->target_layer;
|
||||
vglite_set_dest_buf(&layer->draw_buf);
|
||||
|
||||
/* Invalidate cache */
|
||||
lv_draw_buf_invalidate_cache(&layer->draw_buf, (const char *)&t->area);
|
||||
|
||||
switch(t->type) {
|
||||
case LV_DRAW_TASK_TYPE_LABEL:
|
||||
lv_draw_vglite_label(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_FILL:
|
||||
lv_draw_vglite_fill(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
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;
|
||||
case LV_DRAW_TASK_TYPE_ARC:
|
||||
lv_draw_vglite_arc(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_LINE:
|
||||
lv_draw_vglite_line(draw_unit, t->draw_dsc);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_LAYER:
|
||||
lv_draw_vglite_layer(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
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_disp_t * disp = _lv_refr_get_disp_refreshing();
|
||||
lv_draw_unit_t * draw_unit_tmp = disp->draw_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_vglite_rect((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_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_vglite_rect((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_vglite_label((lv_draw_unit_t *)u, &label_dsc, &txt_area);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if LV_USE_OS
|
||||
static inline void _vglite_queue_task(lv_draw_task_t * task_act)
|
||||
{
|
||||
_draw_task_buf[_tail].task = task_act;
|
||||
_draw_task_buf[_tail].flushed = false;
|
||||
_tail = (_tail + 1) % VGLITE_TASK_BUF_SIZE;
|
||||
}
|
||||
|
||||
static inline void _vglite_signal_task_ready(lv_draw_task_t * task_act)
|
||||
{
|
||||
if(vglite_cmd_buf_is_flushed()) {
|
||||
int end = (_head < _tail) ? _tail : _tail + VGLITE_TASK_BUF_SIZE;
|
||||
|
||||
for(int i = _head; i < end; i++) {
|
||||
/* Previous flushed tasks are ready now. */
|
||||
if(_draw_task_buf[i % VGLITE_TASK_BUF_SIZE].flushed) {
|
||||
lv_draw_task_t * task = _draw_task_buf[i % VGLITE_TASK_BUF_SIZE].task;
|
||||
|
||||
/* Signal the ready state to dispatcher. */
|
||||
task->state = LV_DRAW_TASK_STATE_READY;
|
||||
_head = (_head + 1) % VGLITE_TASK_BUF_SIZE;
|
||||
/* No need to cleanup the tasks in buffer as we advance with the _head. */
|
||||
}
|
||||
else {
|
||||
/* Those tasks have been flushed now. */
|
||||
_draw_task_buf[i % VGLITE_TASK_BUF_SIZE].flushed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(task_act)
|
||||
LV_ASSERT_MSG(_tail != _head, "VGLite task buffer full.");
|
||||
}
|
||||
|
||||
static void _vglite_render_thread_cb(void * ptr)
|
||||
{
|
||||
lv_draw_vglite_unit_t * u = ptr;
|
||||
|
||||
lv_thread_sync_init(&u->sync);
|
||||
|
||||
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) {
|
||||
lv_thread_sync_wait(&u->sync);
|
||||
}
|
||||
|
||||
if(u->task_act) {
|
||||
_vglite_queue_task((void *)u->task_act);
|
||||
|
||||
_vglite_execute_drawing(u);
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Update the flush status for last pending tasks.
|
||||
* vg_lite_flush() will early return if there is nothing to submit.
|
||||
*/
|
||||
vglite_run();
|
||||
}
|
||||
|
||||
_vglite_signal_task_ready((void *)u->task_act);
|
||||
|
||||
/* 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();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*LV_USE_DRAW_VGLITE*/
|
101
src/draw/nxp/vglite/lv_draw_vglite.h
Normal file
101
src/draw/nxp/vglite/lv_draw_vglite.h
Normal file
@ -0,0 +1,101 @@
|
||||
/**
|
||||
* @file lv_draw_vglite.h
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LV_DRAW_VGLITE_H
|
||||
#define LV_DRAW_VGLITE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
#include "../../sw/lv_draw_sw.h"
|
||||
|
||||
/*********************
|
||||
* 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;
|
||||
struct _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;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_draw_buf_vglite_init_handlers(void);
|
||||
|
||||
void lv_draw_vglite_init(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);
|
||||
|
||||
void lv_draw_vglite_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc,
|
||||
const lv_area_t * coords);
|
||||
|
||||
void lv_draw_vglite_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dsc,
|
||||
const lv_area_t * coords);
|
||||
|
||||
void lv_draw_vglite_label(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc,
|
||||
const lv_area_t * coords);
|
||||
|
||||
void lv_draw_vglite_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
|
||||
const lv_area_t * coords);
|
||||
|
||||
void lv_draw_vglite_line(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#endif /*LV_USE_DRAW_VGLITE*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_VGLITE_H*/
|
691
src/draw/nxp/vglite/lv_draw_vglite_arc.c
Normal file
691
src/draw/nxp/vglite/lv_draw_vglite_arc.c
Normal file
@ -0,0 +1,691 @@
|
||||
/**
|
||||
* @file lv_draw_vglite_arc.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2021-2023 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"
|
||||
#include <math.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define T_FRACTION 16384.0f
|
||||
|
||||
#define DICHOTO_ITER 5
|
||||
|
||||
static const uint16_t TperDegree[90] = {
|
||||
0, 174, 348, 522, 697, 873, 1049, 1226, 1403, 1581,
|
||||
1759, 1938, 2117, 2297, 2477, 2658, 2839, 3020, 3202, 3384,
|
||||
3567, 3749, 3933, 4116, 4300, 4484, 4668, 4852, 5037, 5222,
|
||||
5407, 5592, 5777, 5962, 6148, 6334, 6519, 6705, 6891, 7077,
|
||||
7264, 7450, 7636, 7822, 8008, 8193, 8378, 8564, 8750, 8936,
|
||||
9122, 9309, 9495, 9681, 9867, 10052, 10238, 10424, 10609, 10794,
|
||||
10979, 11164, 11349, 11534, 11718, 11902, 12086, 12270, 12453, 12637,
|
||||
12819, 13002, 13184, 13366, 13547, 13728, 13909, 14089, 14269, 14448,
|
||||
14627, 14805, 14983, 15160, 15337, 15513, 15689, 15864, 16038, 16212
|
||||
};
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/* intermediate arc params */
|
||||
typedef struct _vg_arc {
|
||||
int32_t angle; /* angle <90deg */
|
||||
int32_t quarter; /* 0-3 counter-clockwise */
|
||||
int32_t rad; /* radius */
|
||||
int32_t p0x; /* point P0 */
|
||||
int32_t p0y;
|
||||
int32_t p1x; /* point P1 */
|
||||
int32_t p1y;
|
||||
int32_t p2x; /* point P2 */
|
||||
int32_t p2y;
|
||||
int32_t p3x; /* point P3 */
|
||||
int32_t p3y;
|
||||
} vg_arc;
|
||||
|
||||
typedef struct _cubic_cont_pt {
|
||||
float p0;
|
||||
float p1;
|
||||
float p2;
|
||||
float p3;
|
||||
} cubic_cont_pt;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* 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] dsc Arc description structure (width, rounded ending, opacity)
|
||||
*
|
||||
*/
|
||||
static void _vglite_draw_arc(const lv_point_t * center, const lv_area_t * clip_area,
|
||||
const lv_draw_arc_dsc_t * dsc);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_vglite_arc(lv_draw_unit_t * draw_unit, const lv_draw_arc_dsc_t * dsc,
|
||||
const lv_area_t * coords)
|
||||
{
|
||||
LV_UNUSED(coords);
|
||||
|
||||
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
|
||||
return;
|
||||
if(dsc->width == 0)
|
||||
return;
|
||||
if(dsc->start_angle == dsc->end_angle)
|
||||
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_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);
|
||||
|
||||
_vglite_draw_arc(&rel_center, &rel_clip_area, dsc);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void _copy_arc(vg_arc * dst, vg_arc * src)
|
||||
{
|
||||
dst->quarter = src->quarter;
|
||||
dst->rad = src->rad;
|
||||
dst->angle = src->angle;
|
||||
dst->p0x = src->p0x;
|
||||
dst->p1x = src->p1x;
|
||||
dst->p2x = src->p2x;
|
||||
dst->p3x = src->p3x;
|
||||
dst->p0y = src->p0y;
|
||||
dst->p1y = src->p1y;
|
||||
dst->p2y = src->p2y;
|
||||
dst->p3y = src->p3y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate the point according given rotation angle rotation center is 0,0
|
||||
*/
|
||||
static void _rotate_point(int32_t angle, int32_t * x, int32_t * y)
|
||||
{
|
||||
int32_t ori_x = *x;
|
||||
int32_t ori_y = *y;
|
||||
int16_t alpha = (int16_t)angle;
|
||||
*x = ((lv_trigo_cos(alpha) * ori_x) / LV_TRIGO_SIN_MAX) - ((lv_trigo_sin(alpha) * ori_y) / LV_TRIGO_SIN_MAX);
|
||||
*y = ((lv_trigo_sin(alpha) * ori_x) / LV_TRIGO_SIN_MAX) + ((lv_trigo_cos(alpha) * ori_y) / LV_TRIGO_SIN_MAX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set full arc control points depending on quarter.
|
||||
* Control points match the best approximation of a circle.
|
||||
* Arc Quarter position is:
|
||||
* Q2 | Q3
|
||||
* ---+---
|
||||
* Q1 | Q0
|
||||
*/
|
||||
static void _set_full_arc(vg_arc * fullarc)
|
||||
{
|
||||
/* the tangent lenght for the bezier circle approx */
|
||||
float tang = ((float)fullarc->rad) * BEZIER_OPTIM_CIRCLE;
|
||||
switch(fullarc->quarter) {
|
||||
case 0:
|
||||
/* first quarter */
|
||||
fullarc->p0x = fullarc->rad;
|
||||
fullarc->p0y = 0;
|
||||
fullarc->p1x = fullarc->rad;
|
||||
fullarc->p1y = (int32_t)tang;
|
||||
fullarc->p2x = (int32_t)tang;
|
||||
fullarc->p2y = fullarc->rad;
|
||||
fullarc->p3x = 0;
|
||||
fullarc->p3y = fullarc->rad;
|
||||
break;
|
||||
case 1:
|
||||
/* second quarter */
|
||||
fullarc->p0x = 0;
|
||||
fullarc->p0y = fullarc->rad;
|
||||
fullarc->p1x = 0 - (int32_t)tang;
|
||||
fullarc->p1y = fullarc->rad;
|
||||
fullarc->p2x = 0 - fullarc->rad;
|
||||
fullarc->p2y = (int32_t)tang;
|
||||
fullarc->p3x = 0 - fullarc->rad;
|
||||
fullarc->p3y = 0;
|
||||
break;
|
||||
case 2:
|
||||
/* third quarter */
|
||||
fullarc->p0x = 0 - fullarc->rad;
|
||||
fullarc->p0y = 0;
|
||||
fullarc->p1x = 0 - fullarc->rad;
|
||||
fullarc->p1y = 0 - (int32_t)tang;
|
||||
fullarc->p2x = 0 - (int32_t)tang;
|
||||
fullarc->p2y = 0 - fullarc->rad;
|
||||
fullarc->p3x = 0;
|
||||
fullarc->p3y = 0 - fullarc->rad;
|
||||
break;
|
||||
case 3:
|
||||
/* fourth quarter */
|
||||
fullarc->p0x = 0;
|
||||
fullarc->p0y = 0 - fullarc->rad;
|
||||
fullarc->p1x = (int32_t)tang;
|
||||
fullarc->p1y = 0 - fullarc->rad;
|
||||
fullarc->p2x = fullarc->rad;
|
||||
fullarc->p2y = 0 - (int32_t)tang;
|
||||
fullarc->p3x = fullarc->rad;
|
||||
fullarc->p3y = 0;
|
||||
break;
|
||||
default:
|
||||
LV_ASSERT_MSG(false, "Invalid arc quarter.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Linear interpolation between two points 'a' and 'b'
|
||||
* 't' parameter is the proportion ratio expressed in range [0 ; T_FRACTION ]
|
||||
*/
|
||||
static inline float _lerp(float coord_a, float coord_b, uint16_t t)
|
||||
{
|
||||
float tf = (float)t;
|
||||
return ((T_FRACTION - tf) * coord_a + tf * coord_b) / T_FRACTION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a point of bezier curve given 't' param
|
||||
*/
|
||||
static inline float _comp_bezier_point(float t, cubic_cont_pt cp)
|
||||
{
|
||||
float t_sq = t * t;
|
||||
float inv_t_sq = (1.0f - t) * (1.0f - t);
|
||||
float apt = (1.0f - t) * inv_t_sq * cp.p0 + 3.0f * inv_t_sq * t * cp.p1 + 3.0f * (1.0f - t) * t_sq * cp.p2 + t * t_sq *
|
||||
cp.p3;
|
||||
return apt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find parameter 't' in curve at point 'pt'
|
||||
* proceed by dichotomy on only 1 dimension,
|
||||
* works only if the curve is monotonic
|
||||
* bezier curve is defined by control points [p0 p1 p2 p3]
|
||||
* 'dec' tells if curve is decreasing (true) or increasing (false)
|
||||
*/
|
||||
static uint16_t _get_bez_t_from_pos(float pt, cubic_cont_pt cp, bool dec)
|
||||
{
|
||||
/* initialize dichotomy with boundary 't' values */
|
||||
float t_low = 0.0f;
|
||||
float t_mid = 0.5f;
|
||||
float t_hig = 1.0f;
|
||||
float a_pt;
|
||||
/* dichotomy loop */
|
||||
for(int i = 0; i < DICHOTO_ITER; i++) {
|
||||
a_pt = _comp_bezier_point(t_mid, cp);
|
||||
/* check mid-point position on bezier curve versus targeted point */
|
||||
if((a_pt > pt) != dec) {
|
||||
t_hig = t_mid;
|
||||
}
|
||||
else {
|
||||
t_low = t_mid;
|
||||
}
|
||||
/* define new 't' param for mid-point */
|
||||
t_mid = (t_low + t_hig) / 2.0f;
|
||||
}
|
||||
/* return parameter 't' in integer range [0 ; T_FRACTION] */
|
||||
return (uint16_t)floorf(t_mid * T_FRACTION + 0.5f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives relative coords of the control points
|
||||
* for the sub-arc starting at angle with given angle span
|
||||
*/
|
||||
static void _get_subarc_control_points(vg_arc * arc, int32_t span)
|
||||
{
|
||||
vg_arc fullarc = {0};
|
||||
fullarc.angle = arc->angle;
|
||||
fullarc.quarter = arc->quarter;
|
||||
fullarc.rad = arc->rad;
|
||||
_set_full_arc(&fullarc);
|
||||
|
||||
/* special case of full arc */
|
||||
if(arc->angle == 90) {
|
||||
_copy_arc(arc, &fullarc);
|
||||
return;
|
||||
}
|
||||
|
||||
/* compute 1st arc using the geometric construction of curve */
|
||||
uint16_t t2 = TperDegree[arc->angle + span];
|
||||
|
||||
/* lerp for A */
|
||||
float a2x = _lerp((float)fullarc.p0x, (float)fullarc.p1x, t2);
|
||||
float a2y = _lerp((float)fullarc.p0y, (float)fullarc.p1y, t2);
|
||||
/* lerp for B */
|
||||
float b2x = _lerp((float)fullarc.p1x, (float)fullarc.p2x, t2);
|
||||
float b2y = _lerp((float)fullarc.p1y, (float)fullarc.p2y, t2);
|
||||
/* lerp for C */
|
||||
float c2x = _lerp((float)fullarc.p2x, (float)fullarc.p3x, t2);
|
||||
float c2y = _lerp((float)fullarc.p2y, (float)fullarc.p3y, t2);
|
||||
|
||||
/* lerp for D */
|
||||
float d2x = _lerp(a2x, b2x, t2);
|
||||
float d2y = _lerp(a2y, b2y, t2);
|
||||
/* lerp for E */
|
||||
float e2x = _lerp(b2x, c2x, t2);
|
||||
float e2y = _lerp(b2y, c2y, t2);
|
||||
|
||||
float pt2x = _lerp(d2x, e2x, t2);
|
||||
float pt2y = _lerp(d2y, e2y, t2);
|
||||
|
||||
/* compute sub-arc using the geometric construction of curve */
|
||||
uint16_t t1 = TperDegree[arc->angle];
|
||||
|
||||
/* lerp for A */
|
||||
float a1x = _lerp((float)fullarc.p0x, (float)fullarc.p1x, t1);
|
||||
float a1y = _lerp((float)fullarc.p0y, (float)fullarc.p1y, t1);
|
||||
/* lerp for B */
|
||||
float b1x = _lerp((float)fullarc.p1x, (float)fullarc.p2x, t1);
|
||||
float b1y = _lerp((float)fullarc.p1y, (float)fullarc.p2y, t1);
|
||||
/* lerp for C */
|
||||
float c1x = _lerp((float)fullarc.p2x, (float)fullarc.p3x, t1);
|
||||
float c1y = _lerp((float)fullarc.p2y, (float)fullarc.p3y, t1);
|
||||
|
||||
/* lerp for D */
|
||||
float d1x = _lerp(a1x, b1x, t1);
|
||||
float d1y = _lerp(a1y, b1y, t1);
|
||||
/* lerp for E */
|
||||
float e1x = _lerp(b1x, c1x, t1);
|
||||
float e1y = _lerp(b1y, c1y, t1);
|
||||
|
||||
float pt1x = _lerp(d1x, e1x, t1);
|
||||
float pt1y = _lerp(d1y, e1y, t1);
|
||||
|
||||
/* find the 't3' parameter for point P(t1) on the sub-arc [P0 A2 D2 P(t2)] using dichotomy
|
||||
* use position of x axis only */
|
||||
uint16_t t3;
|
||||
t3 = _get_bez_t_from_pos(pt1x,
|
||||
(cubic_cont_pt) {
|
||||
.p0 = ((float)fullarc.p0x), .p1 = a2x, .p2 = d2x, .p3 = pt2x
|
||||
},
|
||||
(bool)(pt2x < (float)fullarc.p0x));
|
||||
|
||||
/* lerp for B */
|
||||
float b3x = _lerp(a2x, d2x, t3);
|
||||
float b3y = _lerp(a2y, d2y, t3);
|
||||
/* lerp for C */
|
||||
float c3x = _lerp(d2x, pt2x, t3);
|
||||
float c3y = _lerp(d2y, pt2y, t3);
|
||||
|
||||
/* lerp for E */
|
||||
float e3x = _lerp(b3x, c3x, t3);
|
||||
float e3y = _lerp(b3y, c3y, t3);
|
||||
|
||||
arc->p0x = (int32_t)floorf(0.5f + pt1x);
|
||||
arc->p0y = (int32_t)floorf(0.5f + pt1y);
|
||||
arc->p1x = (int32_t)floorf(0.5f + e3x);
|
||||
arc->p1y = (int32_t)floorf(0.5f + e3y);
|
||||
arc->p2x = (int32_t)floorf(0.5f + c3x);
|
||||
arc->p2y = (int32_t)floorf(0.5f + c3y);
|
||||
arc->p3x = (int32_t)floorf(0.5f + pt2x);
|
||||
arc->p3y = (int32_t)floorf(0.5f + pt2y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives relative coords of the control points
|
||||
*/
|
||||
static void _get_arc_control_points(vg_arc * arc, bool start)
|
||||
{
|
||||
vg_arc fullarc = {0};
|
||||
fullarc.angle = arc->angle;
|
||||
fullarc.quarter = arc->quarter;
|
||||
fullarc.rad = arc->rad;
|
||||
_set_full_arc(&fullarc);
|
||||
|
||||
/* special case of full arc */
|
||||
if(arc->angle == 90) {
|
||||
_copy_arc(arc, &fullarc);
|
||||
return;
|
||||
}
|
||||
|
||||
/* compute sub-arc using the geometric construction of curve */
|
||||
uint16_t t = TperDegree[arc->angle];
|
||||
/* lerp for A */
|
||||
float ax = _lerp((float)fullarc.p0x, (float)fullarc.p1x, t);
|
||||
float ay = _lerp((float)fullarc.p0y, (float)fullarc.p1y, t);
|
||||
/* lerp for B */
|
||||
float bx = _lerp((float)fullarc.p1x, (float)fullarc.p2x, t);
|
||||
float by = _lerp((float)fullarc.p1y, (float)fullarc.p2y, t);
|
||||
/* lerp for C */
|
||||
float cx = _lerp((float)fullarc.p2x, (float)fullarc.p3x, t);
|
||||
float cy = _lerp((float)fullarc.p2y, (float)fullarc.p3y, t);
|
||||
|
||||
/* lerp for D */
|
||||
float dx = _lerp(ax, bx, t);
|
||||
float dy = _lerp(ay, by, t);
|
||||
/* lerp for E */
|
||||
float ex = _lerp(bx, cx, t);
|
||||
float ey = _lerp(by, cy, t);
|
||||
|
||||
/* sub-arc's control points are tangents of DeCasteljau's algorithm */
|
||||
if(start) {
|
||||
arc->p0x = (int32_t)floorf(0.5f + _lerp(dx, ex, t));
|
||||
arc->p0y = (int32_t)floorf(0.5f + _lerp(dy, ey, t));
|
||||
arc->p1x = (int32_t)floorf(0.5f + ex);
|
||||
arc->p1y = (int32_t)floorf(0.5f + ey);
|
||||
arc->p2x = (int32_t)floorf(0.5f + cx);
|
||||
arc->p2y = (int32_t)floorf(0.5f + cy);
|
||||
arc->p3x = fullarc.p3x;
|
||||
arc->p3y = fullarc.p3y;
|
||||
}
|
||||
else {
|
||||
arc->p0x = fullarc.p0x;
|
||||
arc->p0y = fullarc.p0y;
|
||||
arc->p1x = (int32_t)floorf(0.5f + ax);
|
||||
arc->p1y = (int32_t)floorf(0.5f + ay);
|
||||
arc->p2x = (int32_t)floorf(0.5f + dx);
|
||||
arc->p2y = (int32_t)floorf(0.5f + dy);
|
||||
arc->p3x = (int32_t)floorf(0.5f + _lerp(dx, ex, t));
|
||||
arc->p3y = (int32_t)floorf(0.5f + _lerp(dy, ey, t));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the arc control points into the path data for vglite,
|
||||
* taking into account the real center of the arc (translation).
|
||||
* arc_path: (in/out) the path data array for vglite
|
||||
* pidx: (in/out) index of last element added in arc_path
|
||||
* q_arc: (in) the arc data containing control points
|
||||
* center: (in) the center of the circle in draw coordinates
|
||||
* cw: (in) true if arc is clockwise
|
||||
*/
|
||||
static void _add_split_arc_path(int32_t * arc_path, int * pidx, vg_arc * q_arc, const lv_point_t * center, bool cw)
|
||||
{
|
||||
/* assumes first control point already in array arc_path[] */
|
||||
int idx = *pidx;
|
||||
if(cw) {
|
||||
#if BEZIER_DBG_CONTROL_POINTS
|
||||
arc_path[idx++] = VLC_OP_LINE;
|
||||
arc_path[idx++] = q_arc->p1x + center->x;
|
||||
arc_path[idx++] = q_arc->p1y + center->y;
|
||||
arc_path[idx++] = VLC_OP_LINE;
|
||||
arc_path[idx++] = q_arc->p2x + center->x;
|
||||
arc_path[idx++] = q_arc->p2y + center->y;
|
||||
arc_path[idx++] = VLC_OP_LINE;
|
||||
arc_path[idx++] = q_arc->p3x + center->x;
|
||||
arc_path[idx++] = q_arc->p3y + center->y;
|
||||
#else
|
||||
arc_path[idx++] = VLC_OP_CUBIC;
|
||||
arc_path[idx++] = q_arc->p1x + center->x;
|
||||
arc_path[idx++] = q_arc->p1y + center->y;
|
||||
arc_path[idx++] = q_arc->p2x + center->x;
|
||||
arc_path[idx++] = q_arc->p2y + center->y;
|
||||
arc_path[idx++] = q_arc->p3x + center->x;
|
||||
arc_path[idx++] = q_arc->p3y + center->y;
|
||||
#endif
|
||||
}
|
||||
else { /* reverse points order when counter-clockwise */
|
||||
#if BEZIER_DBG_CONTROL_POINTS
|
||||
arc_path[idx++] = VLC_OP_LINE;
|
||||
arc_path[idx++] = q_arc->p2x + center->x;
|
||||
arc_path[idx++] = q_arc->p2y + center->y;
|
||||
arc_path[idx++] = VLC_OP_LINE;
|
||||
arc_path[idx++] = q_arc->p1x + center->x;
|
||||
arc_path[idx++] = q_arc->p1y + center->y;
|
||||
arc_path[idx++] = VLC_OP_LINE;
|
||||
arc_path[idx++] = q_arc->p0x + center->x;
|
||||
arc_path[idx++] = q_arc->p0y + center->y;
|
||||
#else
|
||||
arc_path[idx++] = VLC_OP_CUBIC;
|
||||
arc_path[idx++] = q_arc->p2x + center->x;
|
||||
arc_path[idx++] = q_arc->p2y + center->y;
|
||||
arc_path[idx++] = q_arc->p1x + center->x;
|
||||
arc_path[idx++] = q_arc->p1y + center->y;
|
||||
arc_path[idx++] = q_arc->p0x + center->x;
|
||||
arc_path[idx++] = q_arc->p0y + center->y;
|
||||
#endif
|
||||
}
|
||||
/* update index i n path array*/
|
||||
*pidx = idx;
|
||||
}
|
||||
|
||||
static void _add_arc_path(int32_t * arc_path, int * pidx, int32_t radius,
|
||||
int32_t start_angle, int32_t end_angle, const lv_point_t * center, bool cw)
|
||||
{
|
||||
/* set number of arcs to draw */
|
||||
vg_arc q_arc;
|
||||
int32_t start_arc_angle = start_angle % 90;
|
||||
int32_t end_arc_angle = end_angle % 90;
|
||||
int32_t inv_start_arc_angle = (start_arc_angle > 0) ? (90 - start_arc_angle) : 0;
|
||||
int32_t nbarc = (end_angle - start_angle - inv_start_arc_angle - end_arc_angle) / 90;
|
||||
q_arc.rad = radius;
|
||||
|
||||
/* handle special case of start & end point in the same quarter */
|
||||
if(((start_angle / 90) == (end_angle / 90)) && (nbarc <= 0)) {
|
||||
q_arc.quarter = (start_angle / 90) % 4;
|
||||
q_arc.angle = start_arc_angle;
|
||||
_get_subarc_control_points(&q_arc, end_arc_angle - start_arc_angle);
|
||||
_add_split_arc_path(arc_path, pidx, &q_arc, center, cw);
|
||||
return;
|
||||
}
|
||||
|
||||
if(cw) {
|
||||
/* partial starting arc */
|
||||
if(start_arc_angle > 0) {
|
||||
q_arc.quarter = (start_angle / 90) % 4;
|
||||
q_arc.angle = start_arc_angle;
|
||||
/* get cubic points relative to center */
|
||||
_get_arc_control_points(&q_arc, true);
|
||||
/* put cubic points in arc_path */
|
||||
_add_split_arc_path(arc_path, pidx, &q_arc, center, cw);
|
||||
}
|
||||
/* full arcs */
|
||||
for(int32_t q = 0; q < nbarc ; q++) {
|
||||
q_arc.quarter = (q + ((start_angle + 89) / 90)) % 4;
|
||||
q_arc.angle = 90;
|
||||
/* get cubic points relative to center */
|
||||
_get_arc_control_points(&q_arc, true); /* 2nd parameter 'start' ignored */
|
||||
/* put cubic points in arc_path */
|
||||
_add_split_arc_path(arc_path, pidx, &q_arc, center, cw);
|
||||
}
|
||||
/* partial ending arc */
|
||||
if(end_arc_angle > 0) {
|
||||
q_arc.quarter = (end_angle / 90) % 4;
|
||||
q_arc.angle = end_arc_angle;
|
||||
/* get cubic points relative to center */
|
||||
_get_arc_control_points(&q_arc, false);
|
||||
/* put cubic points in arc_path */
|
||||
_add_split_arc_path(arc_path, pidx, &q_arc, center, cw);
|
||||
}
|
||||
|
||||
}
|
||||
else { /* counter clockwise */
|
||||
|
||||
/* partial ending arc */
|
||||
if(end_arc_angle > 0) {
|
||||
q_arc.quarter = (end_angle / 90) % 4;
|
||||
q_arc.angle = end_arc_angle;
|
||||
/* get cubic points relative to center */
|
||||
_get_arc_control_points(&q_arc, false);
|
||||
/* put cubic points in arc_path */
|
||||
_add_split_arc_path(arc_path, pidx, &q_arc, center, cw);
|
||||
}
|
||||
/* full arcs */
|
||||
for(int32_t q = nbarc - 1; q >= 0; q--) {
|
||||
q_arc.quarter = (q + ((start_angle + 89) / 90)) % 4;
|
||||
q_arc.angle = 90;
|
||||
/* get cubic points relative to center */
|
||||
_get_arc_control_points(&q_arc, true); /* 2nd parameter 'start' ignored */
|
||||
/* put cubic points in arc_path */
|
||||
_add_split_arc_path(arc_path, pidx, &q_arc, center, cw);
|
||||
}
|
||||
/* partial starting arc */
|
||||
if(start_arc_angle > 0) {
|
||||
q_arc.quarter = (start_angle / 90) % 4;
|
||||
q_arc.angle = start_arc_angle;
|
||||
/* get cubic points relative to center */
|
||||
_get_arc_control_points(&q_arc, true);
|
||||
/* put cubic points in arc_path */
|
||||
_add_split_arc_path(arc_path, pidx, &q_arc, center, cw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
bool donut = ((end_angle - start_angle) % 360 == 0) ? true : false;
|
||||
vg_lite_buffer_t * vgbuf = vglite_get_dest_buf();
|
||||
|
||||
/* path: max size = 16 cubic bezier (7 words each) */
|
||||
int32_t arc_path[16 * 7];
|
||||
lv_memset(arc_path, 0, sizeof(arc_path));
|
||||
|
||||
/*** Init path ***/
|
||||
lv_coord_t width = dsc->width; /* inner arc radius = outer arc radius - width */
|
||||
uint16_t radius = dsc->radius;
|
||||
|
||||
if(width > radius)
|
||||
width = radius;
|
||||
|
||||
int pidx = 0;
|
||||
int32_t cp_x, cp_y; /* control point coords */
|
||||
|
||||
/* first control point of curve */
|
||||
cp_x = radius;
|
||||
cp_y = 0;
|
||||
_rotate_point(start_angle, &cp_x, &cp_y);
|
||||
arc_path[pidx++] = VLC_OP_MOVE;
|
||||
arc_path[pidx++] = center->x + cp_x;
|
||||
arc_path[pidx++] = center->y + cp_y;
|
||||
|
||||
/* draw 1-5 outer quarters */
|
||||
_add_arc_path(arc_path, &pidx, radius, start_angle, end_angle, center, true);
|
||||
|
||||
if(donut) {
|
||||
/* close outer circle */
|
||||
cp_x = radius;
|
||||
cp_y = 0;
|
||||
_rotate_point(start_angle, &cp_x, &cp_y);
|
||||
arc_path[pidx++] = VLC_OP_LINE;
|
||||
arc_path[pidx++] = center->x + cp_x;
|
||||
arc_path[pidx++] = center->y + cp_y;
|
||||
/* start inner circle */
|
||||
cp_x = radius - width;
|
||||
cp_y = 0;
|
||||
_rotate_point(start_angle, &cp_x, &cp_y);
|
||||
arc_path[pidx++] = VLC_OP_MOVE;
|
||||
arc_path[pidx++] = center->x + cp_x;
|
||||
arc_path[pidx++] = center->y + cp_y;
|
||||
|
||||
}
|
||||
else if(dsc->rounded != 0U) { /* 1st rounded arc ending */
|
||||
cp_x = radius - width / 2;
|
||||
cp_y = 0;
|
||||
_rotate_point(end_angle, &cp_x, &cp_y);
|
||||
lv_point_t round_center = {center->x + cp_x, center->y + cp_y};
|
||||
_add_arc_path(arc_path, &pidx, width / 2, end_angle, (end_angle + 180),
|
||||
&round_center, true);
|
||||
|
||||
}
|
||||
else { /* 1st flat ending */
|
||||
cp_x = radius - width;
|
||||
cp_y = 0;
|
||||
_rotate_point(end_angle, &cp_x, &cp_y);
|
||||
arc_path[pidx++] = VLC_OP_LINE;
|
||||
arc_path[pidx++] = center->x + cp_x;
|
||||
arc_path[pidx++] = center->y + cp_y;
|
||||
}
|
||||
|
||||
/* draw 1-5 inner quarters */
|
||||
_add_arc_path(arc_path, &pidx, radius - width, start_angle, end_angle, center, false);
|
||||
|
||||
/* last control point of curve */
|
||||
if(donut) { /* close the loop */
|
||||
cp_x = radius - width;
|
||||
cp_y = 0;
|
||||
_rotate_point(start_angle, &cp_x, &cp_y);
|
||||
arc_path[pidx++] = VLC_OP_LINE;
|
||||
arc_path[pidx++] = center->x + cp_x;
|
||||
arc_path[pidx++] = center->y + cp_y;
|
||||
|
||||
}
|
||||
else if(dsc->rounded != 0U) { /* 2nd rounded arc ending */
|
||||
cp_x = radius - width / 2;
|
||||
cp_y = 0;
|
||||
_rotate_point(start_angle, &cp_x, &cp_y);
|
||||
lv_point_t round_center = {center->x + cp_x, center->y + cp_y};
|
||||
_add_arc_path(arc_path, &pidx, width / 2, (start_angle + 180), (start_angle + 360),
|
||||
&round_center, true);
|
||||
|
||||
}
|
||||
else { /* 2nd flat ending */
|
||||
cp_x = radius;
|
||||
cp_y = 0;
|
||||
_rotate_point(start_angle, &cp_x, &cp_y);
|
||||
arc_path[pidx++] = VLC_OP_LINE;
|
||||
arc_path[pidx++] = center->x + cp_x;
|
||||
arc_path[pidx++] = center->y + cp_y;
|
||||
}
|
||||
|
||||
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.");
|
||||
|
||||
lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->opa);
|
||||
vg_lite_color_t vgcol = vglite_get_color(col32, false);
|
||||
|
||||
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_run();
|
||||
|
||||
vglite_disable_scissor();
|
||||
|
||||
err = vg_lite_clear_path(&path);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Clear path failed.");
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_VGLITE*/
|
114
src/draw/nxp/vglite/lv_draw_vglite_bg_img.c
Normal file
114
src/draw/nxp/vglite/lv_draw_vglite_bg_img.c
Normal file
@ -0,0 +1,114 @@
|
||||
/**
|
||||
* @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*/
|
175
src/draw/nxp/vglite/lv_draw_vglite_border.c
Normal file
175
src/draw/nxp/vglite/lv_draw_vglite_border.c
Normal file
@ -0,0 +1,175 @@
|
||||
/**
|
||||
* @file lv_draw_vglite_border.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2022, 2023 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 <math.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* 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] dsc Description of the rectangle border/outline
|
||||
*
|
||||
*/
|
||||
static void _vglite_draw_border(const lv_area_t * coords, const lv_area_t * clip_area,
|
||||
const lv_draw_border_dsc_t * dsc);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_vglite_border(lv_draw_unit_t * draw_unit, const lv_draw_border_dsc_t * dsc,
|
||||
const lv_area_t * coords)
|
||||
{
|
||||
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
|
||||
return;
|
||||
if(dsc->width == 0)
|
||||
return;
|
||||
if(dsc->side == (lv_border_side_t)LV_BORDER_SIDE_NONE)
|
||||
return;
|
||||
|
||||
lv_layer_t * layer = draw_unit->target_layer;
|
||||
lv_area_t rel_coords;
|
||||
lv_coord_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);
|
||||
|
||||
/* Move outline outwards to align with software rendered outline */
|
||||
//lv_coord_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(&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 clipped_coords;
|
||||
if(!_lv_area_intersect(&clipped_coords, &rel_coords, &rel_clip_area))
|
||||
return; /*Fully clipped, nothing to do*/
|
||||
|
||||
_vglite_draw_border(&rel_coords, &rel_clip_area, dsc);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
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;
|
||||
lv_coord_t radius = dsc->radius;
|
||||
vg_lite_buffer_t * vgbuf = vglite_get_dest_buf();
|
||||
|
||||
if(radius < 0)
|
||||
return;
|
||||
|
||||
lv_coord_t border_half = (lv_coord_t)floor(dsc->width / 2.0f);
|
||||
if(radius > border_half)
|
||||
radius = radius - border_half;
|
||||
|
||||
//else {
|
||||
// /* Draw outline - always has radius, leave the same radius in the circle case */
|
||||
// lv_coord_t outline_half = (lv_coord_t)ceil(dsc->outline_width / 2.0f);
|
||||
// if(radius < (lv_coord_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;
|
||||
|
||||
/*** Init path ***/
|
||||
int32_t path_data[RECT_PATH_DATA_MAX_SIZE];
|
||||
uint32_t path_data_size;
|
||||
vglite_create_rect_path_data(path_data, &path_data_size, radius, coords);
|
||||
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.");
|
||||
|
||||
lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->opa);
|
||||
vg_lite_color_t vgcol = vglite_get_color(col32, false);
|
||||
|
||||
vg_lite_matrix_t matrix;
|
||||
vg_lite_identity(&matrix);
|
||||
|
||||
lv_coord_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.");
|
||||
|
||||
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.");
|
||||
|
||||
err = vg_lite_update_stroke(&path);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Update stroke failed.");
|
||||
|
||||
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_run();
|
||||
|
||||
vglite_disable_scissor();
|
||||
|
||||
err = vg_lite_clear_path(&path);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Clear path failed.");
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_VGLITE*/
|
259
src/draw/nxp/vglite/lv_draw_vglite_fill.c
Normal file
259
src/draw/nxp/vglite/lv_draw_vglite_fill.c
Normal file
@ -0,0 +1,259 @@
|
||||
/**
|
||||
* @file lv_draw_vglite_fill.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2020-2023 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
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Fill area, with optional opacity.
|
||||
*
|
||||
* @param[in] dest_area Area with relative coordinates of destination buffer
|
||||
* @param[in] dsc Description of the area to fill (color, opa)
|
||||
*
|
||||
*/
|
||||
static void _vglite_fill(const lv_area_t * dest_area, const lv_draw_fill_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* 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] dsc Description of the rectangle background
|
||||
*
|
||||
*/
|
||||
static void _vglite_draw_rect(const lv_area_t * coords, const lv_area_t * clip_area,
|
||||
const lv_draw_fill_dsc_t * dsc);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_vglite_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc,
|
||||
const lv_area_t * coords)
|
||||
{
|
||||
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
|
||||
return;
|
||||
|
||||
lv_layer_t * layer = draw_unit->target_layer;
|
||||
lv_area_t rel_coords;
|
||||
lv_area_copy(&rel_coords, coords);
|
||||
|
||||
/*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 clipped_coords;
|
||||
if(!_lv_area_intersect(&clipped_coords, &rel_coords, &rel_clip_area))
|
||||
return; /*Fully clipped, nothing to do*/
|
||||
|
||||
/*
|
||||
* Most simple case: just a plain rectangle (no radius, no gradient)
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
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);
|
||||
vg_lite_color_t vgcol = vglite_get_color(col32, false);
|
||||
|
||||
if(dsc->opa >= (lv_opa_t)LV_OPA_MAX) { /*Opaque fill*/
|
||||
vg_lite_rectangle_t rect = {
|
||||
.x = dest_area->x1,
|
||||
.y = dest_area->y1,
|
||||
.width = lv_area_get_width(dest_area),
|
||||
.height = lv_area_get_height(dest_area)
|
||||
};
|
||||
|
||||
err = vg_lite_clear(vgbuf, &rect, vgcol);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Clear failed.");
|
||||
|
||||
vglite_run();
|
||||
}
|
||||
else { /*fill with transparency*/
|
||||
|
||||
vg_lite_path_t path;
|
||||
int32_t path_data[] = { /*VG rectangular path*/
|
||||
VLC_OP_MOVE, dest_area->x1, dest_area->y1,
|
||||
VLC_OP_LINE, dest_area->x2 + 1, dest_area->y1,
|
||||
VLC_OP_LINE, dest_area->x2 + 1, dest_area->y2 + 1,
|
||||
VLC_OP_LINE, dest_area->x1, dest_area->y2 + 1,
|
||||
VLC_OP_LINE, dest_area->x1, dest_area->y1,
|
||||
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.");
|
||||
|
||||
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_run();
|
||||
|
||||
err = vg_lite_clear_path(&path);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Clear path failed.");
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
lv_coord_t width = lv_area_get_width(coords);
|
||||
lv_coord_t height = lv_area_get_height(coords);
|
||||
lv_coord_t radius = dsc->radius;
|
||||
vg_lite_buffer_t * vgbuf = vglite_get_dest_buf();
|
||||
|
||||
if(dsc->radius < 0)
|
||||
return;
|
||||
|
||||
/*** Init path ***/
|
||||
int32_t path_data[RECT_PATH_DATA_MAX_SIZE];
|
||||
uint32_t path_data_size;
|
||||
vglite_create_rect_path_data(path_data, &path_data_size, radius, coords);
|
||||
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.");
|
||||
|
||||
vg_lite_matrix_t matrix;
|
||||
vg_lite_identity(&matrix);
|
||||
|
||||
/*** Init Color ***/
|
||||
lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->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);
|
||||
|
||||
/*** Init Gradient ***/
|
||||
if(has_gradient) {
|
||||
vg_lite_matrix_t * grad_matrix;
|
||||
|
||||
uint32_t colors[2];
|
||||
uint32_t stops[2];
|
||||
lv_color32_t col32[2];
|
||||
|
||||
/* Gradient setup */
|
||||
uint8_t cnt = LV_MAX(dsc->grad.stops_count, 2);
|
||||
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);
|
||||
colors[i] = vglite_get_color(col32[i], true);
|
||||
}
|
||||
|
||||
lv_memset(&gradient, 0, sizeof(vg_lite_linear_gradient_t));
|
||||
|
||||
err = vg_lite_init_grad(&gradient);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Init gradient failed");
|
||||
|
||||
err = vg_lite_set_grad(&gradient, cnt, colors, stops);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Set gradient failed.");
|
||||
|
||||
err = vg_lite_update_grad(&gradient);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Update gradient failed.");
|
||||
|
||||
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->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);
|
||||
}
|
||||
|
||||
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.");
|
||||
}
|
||||
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_run();
|
||||
|
||||
vglite_disable_scissor();
|
||||
|
||||
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.");
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_VGLITE*/
|
412
src/draw/nxp/vglite/lv_draw_vglite_img.c
Normal file
412
src/draw/nxp/vglite/lv_draw_vglite_img.c
Normal file
@ -0,0 +1,412 @@
|
||||
/**
|
||||
* @file lv_draw_vglite_blend.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2020-2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_vglite.h"
|
||||
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
#include "lv_vglite_buf.h"
|
||||
#include "lv_vglite_matrix.h"
|
||||
#include "lv_vglite_utils.h"
|
||||
|
||||
#include "../../../misc/lv_log.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#if VGLITE_BLIT_SPLIT_ENABLED
|
||||
/**
|
||||
* 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.
|
||||
* For most color formats the alignment is 16px (except the index formats).
|
||||
*/
|
||||
#define VGLITE_BLIT_SPLIT_THR 352
|
||||
|
||||
/* Enable for logging debug traces. */
|
||||
#define VGLITE_LOG_TRACE 0
|
||||
|
||||
#if VGLITE_LOG_TRACE
|
||||
#define VGLITE_TRACE(fmt, ...) \
|
||||
do { \
|
||||
LV_LOG(fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define VGLITE_TRACE(fmt, ...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* BLock Image Transfer - copy rectangular image from src_buf to dst_buf with effects.
|
||||
* By default, image is copied directly, with optional opacity.
|
||||
*
|
||||
* @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
|
||||
*
|
||||
*/
|
||||
static void _vglite_blit_single(const lv_area_t * dest_area, const lv_area_t * src_area, lv_opa_t opa);
|
||||
|
||||
#if VGLITE_BLIT_SPLIT_ENABLED
|
||||
/**
|
||||
* Move buffer pointer as close as possible to area, but with respect to alignment requirements.
|
||||
*
|
||||
* @param[in] buf Buffer address pointer
|
||||
* @param[in] area Area with relative coordinates to the buffer
|
||||
* @param[in] stride Stride of buffer in bytes
|
||||
* @param[in] cf Color format of buffer
|
||||
*/
|
||||
static void _move_buf_close_to_area(void ** buf, lv_area_t * area, uint32_t stride, lv_color_format_t cf);
|
||||
|
||||
/**
|
||||
* BLock Image Transfer - copy rectangular image from src_buf to dst_buf with effects.
|
||||
* By default, image is copied directly, with optional opacity.
|
||||
*
|
||||
* @param dest_buf Destination buffer
|
||||
* @param[in] dest_area Destination area with relative coordinates to dest buffer
|
||||
* @param[in] dest_stride Stride of destination buffer in bytes
|
||||
* @param[in] dest_cf Color format of destination buffer
|
||||
* @param[in] src_buf Source buffer
|
||||
* @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
|
||||
*
|
||||
*/
|
||||
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);
|
||||
#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 VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_vglite_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dsc,
|
||||
const lv_area_t * coords)
|
||||
{
|
||||
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
|
||||
return;
|
||||
|
||||
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 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 blend_area;
|
||||
bool has_transform = dsc->rotation != 0 || dsc->zoom != 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))
|
||||
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;
|
||||
|
||||
lv_color_format_t src_cf = img_dsc->header.cf;
|
||||
uint32_t src_stride = img_dsc->header.stride;
|
||||
|
||||
/* 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(!has_transform)
|
||||
_vglite_blit_split(dest_buf, &blend_area, dest_stride, dest_cf,
|
||||
src_buf, &src_area, src_stride, src_cf, dsc->opa);
|
||||
#else
|
||||
if(has_transform)
|
||||
_vglite_blit_transform(&blend_area, &rel_clip_area, &src_area, dsc);
|
||||
else
|
||||
_vglite_blit_single(&blend_area, &src_area, dsc->opa);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
static void _vglite_blit(const lv_area_t * src_area, 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 * 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 */
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
vg_lite_matrix_t * vgmatrix = vglite_get_matrix();
|
||||
|
||||
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.");
|
||||
|
||||
vglite_run();
|
||||
}
|
||||
|
||||
static void _vglite_blit_single(const lv_area_t * dest_area, const lv_area_t * src_area, lv_opa_t opa)
|
||||
{
|
||||
/* 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();
|
||||
}
|
||||
|
||||
#if VGLITE_BLIT_SPLIT_ENABLED
|
||||
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);
|
||||
|
||||
uint16_t align_pixels = align_bytes * 8 / bits_per_pixel;
|
||||
|
||||
if(area->x1 >= (lv_coord_t)(area->x1 % align_pixels)) {
|
||||
uint16_t shift_x = area->x1 - (area->x1 % align_pixels);
|
||||
|
||||
area->x1 -= shift_x;
|
||||
area->x2 -= shift_x;
|
||||
*buf_u8 += (shift_x * bits_per_pixel) / 8;
|
||||
}
|
||||
|
||||
if(area->y1) {
|
||||
uint16_t shift_y = area->y1;
|
||||
|
||||
area->y1 -= shift_y;
|
||||
area->y2 -= shift_y;
|
||||
*buf_u8 += shift_y * stride;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
VGLITE_TRACE("Blit "
|
||||
"Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | "
|
||||
"Size: ([%dx%d] -> [%dx%d]) | "
|
||||
"Addr: (0x%x -> 0x%x)",
|
||||
src_area->x1, src_area->y1, src_area->x2, src_area->y2,
|
||||
dest_area->x1, dest_area->y1, dest_area->x2, dest_area->y2,
|
||||
lv_area_get_width(src_area), lv_area_get_height(src_area),
|
||||
lv_area_get_width(dest_area), lv_area_get_height(dest_area),
|
||||
(uintptr_t)src_buf, (uintptr_t)dest_buf);
|
||||
|
||||
/* Move starting pointers as close as possible to [x1, y1], so coordinates are as small as possible */
|
||||
_move_buf_close_to_area((void **)&src_buf, src_area, src_stride, src_cf);
|
||||
_move_buf_close_to_area(&dest_buf, dest_area, dest_stride, dest_cf);
|
||||
|
||||
/* If we're in limit, do a single BLIT */
|
||||
if((src_area->x2 < VGLITE_BLIT_SPLIT_THR) &&
|
||||
(src_area->y2 < VGLITE_BLIT_SPLIT_THR)) {
|
||||
|
||||
/* Set new dest_vgbuf and src_vgbuf memory addresses */
|
||||
vglite_set_dest_buf_ptr(dest_buf);
|
||||
vglite_set_src_buf_ptr(src_buf);
|
||||
|
||||
_vglite_blit_single(dest_area, src_area, opa);
|
||||
|
||||
VGLITE_TRACE("Single "
|
||||
"Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | "
|
||||
"Size: ([%dx%d] -> [%dx%d]) | "
|
||||
"Addr: (0x%x -> 0x%x)",
|
||||
src_area->x1, src_area->y1, src_area->x2, src_area->y2,
|
||||
dest_area->x1, dest_area->y1, dest_area->x2, dest_area->y2,
|
||||
lv_area_get_width(src_area), lv_area_get_height(src_area),
|
||||
lv_area_get_width(dest_area), lv_area_get_height(dest_area),
|
||||
(uintptr_t)src_buf, (uintptr_t)dest_buf);
|
||||
};
|
||||
|
||||
/* Split the BLIT into multiple tiles */
|
||||
VGLITE_TRACE("Split "
|
||||
"Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | "
|
||||
"Size: ([%dx%d] -> [%dx%d]) | "
|
||||
"Addr: (0x%x -> 0x%x)",
|
||||
src_area->x1, src_area->y1, src_area->x2, src_area->y2,
|
||||
dest_area->x1, dest_area->y1, dest_area->x2, dest_area->y2,
|
||||
lv_area_get_width(src_area), lv_area_get_height(src_area),
|
||||
lv_area_get_width(dest_area), lv_area_get_height(dest_area),
|
||||
(uintptr_t)src_buf, (uintptr_t)dest_buf);
|
||||
|
||||
lv_coord_t width = LV_MIN(lv_area_get_width(src_area), lv_area_get_width(dest_area));
|
||||
lv_coord_t height = LV_MIN(lv_area_get_height(src_area), lv_area_get_height(dest_area));
|
||||
|
||||
/* Number of tiles needed */
|
||||
uint8_t total_tiles_x = (src_area->x1 + width + VGLITE_BLIT_SPLIT_THR - 1) /
|
||||
VGLITE_BLIT_SPLIT_THR;
|
||||
uint8_t total_tiles_y = (src_area->y1 + height + VGLITE_BLIT_SPLIT_THR - 1) /
|
||||
VGLITE_BLIT_SPLIT_THR;
|
||||
|
||||
uint16_t shift_src_x = src_area->x1;
|
||||
uint16_t shift_dest_x = dest_area->x1;
|
||||
|
||||
VGLITE_TRACE("X shift: src: %d, dst: %d", shift_src_x, shift_dest_x);
|
||||
|
||||
uint8_t * tile_dest_buf;
|
||||
lv_area_t tile_dest_area;
|
||||
const uint8_t * tile_src_buf;
|
||||
lv_area_t tile_src_area;
|
||||
|
||||
for(uint8_t y = 0; y < total_tiles_y; y++) {
|
||||
/* y1 always start from 0 */
|
||||
tile_src_area.y1 = 0;
|
||||
|
||||
/* Calculate y2 coordinates */
|
||||
if(y < total_tiles_y - 1)
|
||||
tile_src_area.y2 = VGLITE_BLIT_SPLIT_THR - 1;
|
||||
else
|
||||
tile_src_area.y2 = height - y * VGLITE_BLIT_SPLIT_THR - 1;
|
||||
|
||||
/* No vertical shift, dest y is always in sync with src y */
|
||||
tile_dest_area.y1 = tile_src_area.y1;
|
||||
tile_dest_area.y2 = tile_src_area.y2;
|
||||
|
||||
/* Advance start pointer for every tile, except the first column (y = 0) */
|
||||
tile_src_buf = (uint8_t *)src_buf + y * VGLITE_BLIT_SPLIT_THR * src_stride;
|
||||
tile_dest_buf = (uint8_t *)dest_buf + y * VGLITE_BLIT_SPLIT_THR * dest_stride;
|
||||
|
||||
for(uint8_t x = 0; x < total_tiles_x; x++) {
|
||||
/* x1 always start from the same shift */
|
||||
tile_src_area.x1 = shift_src_x;
|
||||
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;
|
||||
}
|
||||
|
||||
/* Calculate x2 coordinates */
|
||||
if(x < total_tiles_x - 1)
|
||||
tile_src_area.x2 = VGLITE_BLIT_SPLIT_THR - 1;
|
||||
else
|
||||
tile_src_area.x2 = width - x * VGLITE_BLIT_SPLIT_THR - 1;
|
||||
|
||||
tile_dest_area.x2 = tile_src_area.x2;
|
||||
|
||||
/* Shift x2 coordinates */
|
||||
tile_src_area.x2 += shift_src_x;
|
||||
tile_dest_area.x2 += shift_dest_x;
|
||||
|
||||
/* Set new dest_vgbuf and src_vgbuf memory addresses */
|
||||
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_TRACE("Tile [%d, %d] "
|
||||
"Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | "
|
||||
"Size: ([%dx%d] -> [%dx%d]) | "
|
||||
"Addr: (0x%x -> 0x%x)",
|
||||
x, y,
|
||||
tile_src_area.x1, tile_src_area.y1, tile_src_area.x2, tile_src_area.y2,
|
||||
tile_dest_area.x1, tile_dest_area.y1, tile_dest_area.x2, tile_dest_area.y2,
|
||||
lv_area_get_width(&tile_src_area), lv_area_get_height(&tile_src_area),
|
||||
lv_area_get_width(&tile_dest_area), lv_area_get_height(&tile_dest_area),
|
||||
(uintptr_t)tile_src_buf, (uintptr_t)tile_dest_buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
#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)
|
||||
{
|
||||
/* 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();
|
||||
}
|
||||
#endif /*VGLITE_BLIT_SPLIT_ENABLED*/
|
||||
|
||||
#endif /*LV_USE_DRAW_VGLITE*/
|
206
src/draw/nxp/vglite/lv_draw_vglite_label.c
Normal file
206
src/draw/nxp/vglite/lv_draw_vglite_label.c
Normal file
@ -0,0 +1,206 @@
|
||||
/**
|
||||
* @file lv_draw_vglite_label.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_vglite.h"
|
||||
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
#include "lv_vglite_buf.h"
|
||||
#include "lv_vglite_matrix.h"
|
||||
#include "lv_vglite_utils.h"
|
||||
|
||||
#include "../../../stdlib/lv_string.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void _draw_vglite_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * glyph_draw_dsc,
|
||||
lv_draw_fill_dsc_t * fill_draw_dsc, const lv_area_t * fill_area);
|
||||
|
||||
|
||||
/**
|
||||
* 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 VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_vglite_label(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc,
|
||||
const lv_area_t * coords)
|
||||
{
|
||||
if(dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
lv_draw_label_interate_letters(draw_unit, dsc, coords, _draw_vglite_letter);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void _draw_vglite_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * glyph_draw_dsc,
|
||||
lv_draw_fill_dsc_t * fill_draw_dsc, const lv_area_t * fill_area)
|
||||
{
|
||||
if(glyph_draw_dsc) {
|
||||
if(glyph_draw_dsc->bitmap == NULL) {
|
||||
#if LV_USE_FONT_PLACEHOLDER
|
||||
/* Draw a placeholder rectangle*/
|
||||
lv_draw_border_dsc_t border_draw_dsc;
|
||||
lv_draw_border_dsc_init(&border_draw_dsc);
|
||||
border_draw_dsc.opa = glyph_draw_dsc->opa;
|
||||
border_draw_dsc.color = glyph_draw_dsc->color;
|
||||
border_draw_dsc.width = 1;
|
||||
lv_draw_vglite_border(draw_unit, &border_draw_dsc, glyph_draw_dsc->bg_coords);
|
||||
#endif
|
||||
}
|
||||
else if(glyph_draw_dsc->format == LV_DRAW_LETTER_BITMAP_FORMAT_A8) {
|
||||
/*Do not draw transparent things*/
|
||||
if(glyph_draw_dsc->opa <= LV_OPA_MIN)
|
||||
return;
|
||||
|
||||
lv_layer_t * layer = draw_unit->target_layer;
|
||||
|
||||
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);
|
||||
|
||||
//void * dest_buf = lv_draw_buf_go_to_xy(&layer->draw_buf,
|
||||
// blend_area.x1 - layer->draw_buf_ofs.x,
|
||||
// blend_area.y1 - layer->draw_buf_ofs.y);
|
||||
|
||||
const uint8_t * mask_buf = glyph_draw_dsc->bitmap;
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if(!vglite_buf_aligned(mask_buf, mask_stride, LV_COLOR_FORMAT_A8)) {
|
||||
/* Draw a placeholder rectangle*/
|
||||
lv_draw_border_dsc_t border_draw_dsc;
|
||||
lv_draw_border_dsc_init(&border_draw_dsc);
|
||||
border_draw_dsc.opa = glyph_draw_dsc->opa;
|
||||
border_draw_dsc.color = glyph_draw_dsc->color;
|
||||
border_draw_dsc.width = 1;
|
||||
lv_draw_vglite_border(draw_unit, &border_draw_dsc, glyph_draw_dsc->bg_coords);
|
||||
}
|
||||
else {
|
||||
|
||||
_vglite_draw_letter(&blend_area, mask_buf, &mask_area, mask_stride,
|
||||
glyph_draw_dsc->color, glyph_draw_dsc->opa);
|
||||
}
|
||||
}
|
||||
else if(glyph_draw_dsc->format == LV_DRAW_LETTER_BITMAP_FORMAT_IMAGE) {
|
||||
#if LV_USE_IMGFONT
|
||||
lv_draw_img_dsc_t img_dsc;
|
||||
lv_draw_img_dsc_init(&img_dsc);
|
||||
img_dsc.angle = 0;
|
||||
img_dsc.zoom = LV_ZOOM_NONE;
|
||||
img_dsc.opa = glyph_draw_dsc->opa;
|
||||
img_dsc.src = glyph_draw_dsc->bitmap;
|
||||
lv_draw_vglite_img(draw_unit, &img_dsc, glyph_draw_dsc->letter_coords);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if(fill_draw_dsc && fill_area) {
|
||||
lv_draw_vglite_fill(draw_unit, fill_draw_dsc, fill_area);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
vg_lite_error_t err = VG_LITE_SUCCESS;
|
||||
vg_lite_buffer_t * dst_vgbuf = vglite_get_dest_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;
|
||||
|
||||
lv_memset(&mask_vgbuf.yuv, 0, 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 */
|
||||
};
|
||||
|
||||
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_run();
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_VGLITE*/
|
71
src/draw/nxp/vglite/lv_draw_vglite_layer.c
Normal file
71
src/draw/nxp/vglite/lv_draw_vglite_layer.c
Normal file
@ -0,0 +1,71 @@
|
||||
/**
|
||||
* @file lv_draw_vglite_layer.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_vglite.h"
|
||||
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
|
||||
#include "../../../stdlib/lv_string.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_vglite_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
|
||||
const lv_area_t * coords)
|
||||
{
|
||||
lv_layer_t * layer_to_draw = (lv_layer_t *)draw_dsc->src;
|
||||
|
||||
/*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)
|
||||
return;
|
||||
|
||||
lv_image_dsc_t img_dsc;
|
||||
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.header.always_zero = 0;
|
||||
img_dsc.data = lv_draw_buf_get_buf(&layer_to_draw->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);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_VGLITE*/
|
158
src/draw/nxp/vglite/lv_draw_vglite_line.c
Normal file
158
src/draw/nxp/vglite/lv_draw_vglite_line.c
Normal file
@ -0,0 +1,158 @@
|
||||
/**
|
||||
* @file lv_draw_vglite_line.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2022, 2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_vglite.h"
|
||||
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
#include "lv_vglite_buf.h"
|
||||
#include "lv_vglite_utils.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Draw line shape with effects
|
||||
*
|
||||
* @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] dsc Line description structure (width, rounded ending, opacity, ...)
|
||||
*
|
||||
*/
|
||||
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);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_vglite_line(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc)
|
||||
{
|
||||
if(dsc->width == 0)
|
||||
return;
|
||||
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
|
||||
return;
|
||||
if(dsc->p1.x == dsc->p2.x && dsc->p1.y == dsc->p2.y)
|
||||
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;
|
||||
|
||||
if(!_lv_area_intersect(&rel_clip_area, &rel_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_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};
|
||||
|
||||
_vglite_draw_line(&rel_point1, &rel_point2, &rel_clip_area, dsc);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
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;
|
||||
vg_lite_join_style_t join_style = (dsc->round_start || dsc->round_end) ? VG_LITE_JOIN_ROUND : VG_LITE_JOIN_MITER;
|
||||
|
||||
bool is_dashed = (dsc->dash_width && dsc->dash_gap);
|
||||
|
||||
vg_lite_float_t stroke_dash_pattern[2] = {0, 0};
|
||||
uint32_t stroke_dash_count = 0;
|
||||
vg_lite_float_t stroke_dash_phase = 0;
|
||||
if(is_dashed) {
|
||||
stroke_dash_pattern[0] = (vg_lite_float_t)dsc->dash_width;
|
||||
stroke_dash_pattern[1] = (vg_lite_float_t)dsc->dash_gap;
|
||||
stroke_dash_count = sizeof(stroke_dash_pattern) / sizeof(vg_lite_float_t);
|
||||
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);
|
||||
|
||||
/*** Init path ***/
|
||||
lv_coord_t width = dsc->width;
|
||||
|
||||
int32_t line_path[] = { /*VG line path*/
|
||||
VLC_OP_MOVE, point1->x, point1->y,
|
||||
VLC_OP_LINE, point2->x, point2->y,
|
||||
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.");
|
||||
|
||||
lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->opa);
|
||||
vg_lite_color_t vgcol = vglite_get_color(col32, false);
|
||||
|
||||
vg_lite_matrix_t matrix;
|
||||
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.");
|
||||
|
||||
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.");
|
||||
|
||||
err = vg_lite_update_stroke(&path);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Update stroke failed.");
|
||||
|
||||
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_run();
|
||||
|
||||
vglite_disable_scissor();
|
||||
|
||||
err = vg_lite_clear_path(&path);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Clear path failed.");
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_VGLITE*/
|
117
src/draw/nxp/vglite/lv_vglite_buf.c
Normal file
117
src/draw/nxp/vglite/lv_vglite_buf.c
Normal file
@ -0,0 +1,117 @@
|
||||
/**
|
||||
* @file lv_vglite_buf.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_vglite_buf.h"
|
||||
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
#include "lv_vglite_utils.h"
|
||||
|
||||
#include "../../../stdlib/lv_string.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static inline void _set_vgbuf_ptr(vg_lite_buffer_t * vgbuf, void * buf);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
static vg_lite_buffer_t _dest_vgbuf;
|
||||
static vg_lite_buffer_t _src_vgbuf;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
vg_lite_buffer_t * vglite_get_dest_buf(void)
|
||||
{
|
||||
return &_dest_vgbuf;
|
||||
}
|
||||
|
||||
vg_lite_buffer_t * vglite_get_src_buf(void)
|
||||
{
|
||||
return &_src_vgbuf;
|
||||
}
|
||||
|
||||
void vglite_set_dest_buf_ptr(void * buf)
|
||||
{
|
||||
_set_vgbuf_ptr(&_dest_vgbuf, buf);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
void vglite_set_src_buf(const void * buf, lv_coord_t width, lv_coord_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,
|
||||
lv_coord_t width, lv_coord_t height, uint32_t stride,
|
||||
lv_color_format_t cf)
|
||||
{
|
||||
vg_lite_buffer_format_t vgformat = vglite_get_buf_format(cf);
|
||||
|
||||
vgbuf->format = vgformat;
|
||||
vgbuf->tiled = VG_LITE_LINEAR;
|
||||
vgbuf->image_mode = VG_LITE_NORMAL_IMAGE_MODE;
|
||||
vgbuf->transparency_mode = VG_LITE_IMAGE_OPAQUE;
|
||||
|
||||
vgbuf->width = (int32_t)width;
|
||||
vgbuf->height = (int32_t)height;
|
||||
vgbuf->stride = (int32_t)stride;
|
||||
|
||||
lv_memset(&vgbuf->yuv, 0, sizeof(vgbuf->yuv));
|
||||
|
||||
vgbuf->memory = buf;
|
||||
vgbuf->address = (uint32_t)vgbuf->memory;
|
||||
vgbuf->handle = NULL;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static inline void _set_vgbuf_ptr(vg_lite_buffer_t * vgbuf, void * buf)
|
||||
{
|
||||
vgbuf->memory = buf;
|
||||
vgbuf->address = (uint32_t)vgbuf->memory;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_VGLITE*/
|
120
src/draw/nxp/vglite/lv_vglite_buf.h
Normal file
120
src/draw/nxp/vglite/lv_vglite_buf.h
Normal file
@ -0,0 +1,120 @@
|
||||
/**
|
||||
* @file lv_vglite_buf.h
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LV_VGLITE_BUF_H
|
||||
#define LV_VGLITE_BUF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
#include "../../sw/lv_draw_sw.h"
|
||||
|
||||
#include "vg_lite.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Get vglite destination buffer pointer.
|
||||
*
|
||||
* @retval The vglite destination buffer
|
||||
*
|
||||
*/
|
||||
vg_lite_buffer_t * vglite_get_dest_buf(void);
|
||||
|
||||
/**
|
||||
* Get vglite source buffer pointer.
|
||||
*
|
||||
* @retval The vglite source buffer
|
||||
*
|
||||
*/
|
||||
vg_lite_buffer_t * vglite_get_src_buf(void);
|
||||
|
||||
/**
|
||||
* Set vglite destination buffer address only.
|
||||
*
|
||||
* @param[in] buf Destination buffer address (does not require alignment for VG_LITE_LINEAR mode)
|
||||
*
|
||||
*/
|
||||
void vglite_set_dest_buf_ptr(void * buf);
|
||||
|
||||
/**
|
||||
* Set vglite source buffer address only.
|
||||
*
|
||||
* @param[in] buf Source buffer address
|
||||
*
|
||||
*/
|
||||
void vglite_set_src_buf_ptr(const void * buf);
|
||||
|
||||
/**
|
||||
* Set vglite target (destination) buffer.
|
||||
*
|
||||
* @param[in] draw_buf Destination draw buffer descriptor
|
||||
*
|
||||
*/
|
||||
void vglite_set_dest_buf(const lv_draw_buf_t * draw_buf);
|
||||
|
||||
/**
|
||||
* Set vglite source buffer.
|
||||
*
|
||||
* @param[in] buf Source buffer address
|
||||
* @param[in] width Source buffer width
|
||||
* @param[in] height Source buffer height
|
||||
* @param[in] stride Source buffer stride in bytes
|
||||
* @param[in] cf Source buffer color format
|
||||
*
|
||||
*/
|
||||
void vglite_set_src_buf(const void * buf, lv_coord_t width, lv_coord_t height, uint32_t stride,
|
||||
lv_color_format_t cf);
|
||||
|
||||
/**
|
||||
* Set vglite buffer.
|
||||
*
|
||||
* @param[in] vgbuf Address of the VGLite buffer object
|
||||
* @param[in] buf Address of the memory for the VGLite buffer
|
||||
* @param[in] width Buffer width
|
||||
* @param[in] height Buffer height
|
||||
* @param[in] stride Buffer stride in bytes
|
||||
* @param[in] cf Buffer color format
|
||||
*
|
||||
*/
|
||||
void vglite_set_buf(vg_lite_buffer_t * vgbuf, void * buf,
|
||||
lv_coord_t width, lv_coord_t height, uint32_t stride,
|
||||
lv_color_format_t cf);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_DRAW_VGLITE*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_VGLITE_BUF_H*/
|
79
src/draw/nxp/vglite/lv_vglite_matrix.c
Normal file
79
src/draw/nxp/vglite/lv_vglite_matrix.c
Normal file
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* @file lv_vglite_matrix.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_vglite_matrix.h"
|
||||
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
static vg_lite_matrix_t _vgmatrix;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
vg_lite_matrix_t * vglite_get_matrix(void)
|
||||
{
|
||||
return &_vgmatrix;
|
||||
}
|
||||
|
||||
void vglite_set_translation_matrix(const lv_area_t * dest_area)
|
||||
{
|
||||
vg_lite_identity(&_vgmatrix);
|
||||
vg_lite_translate((vg_lite_float_t)dest_area->x1, (vg_lite_float_t)dest_area->y1, &_vgmatrix);
|
||||
}
|
||||
|
||||
void vglite_set_transformation_matrix(const lv_area_t * dest_area, const lv_draw_image_dsc_t * dsc)
|
||||
{
|
||||
vglite_set_translation_matrix(dest_area);
|
||||
|
||||
bool has_scale = (dsc->zoom != 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_translate(0.0f - dsc->pivot.x, 0.0f - dsc->pivot.y, &_vgmatrix);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_DRAW_VGLITE*/
|
79
src/draw/nxp/vglite/lv_vglite_matrix.h
Normal file
79
src/draw/nxp/vglite/lv_vglite_matrix.h
Normal file
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* @file lv_vglite_matrix.h
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LV_VGLITE_MATRIX_H
|
||||
#define LV_VGLITE_MATRIX_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
#include "../../sw/lv_draw_sw.h"
|
||||
|
||||
#include "vg_lite.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
vg_lite_matrix_t * vglite_get_matrix(void);
|
||||
|
||||
/**
|
||||
* Creates matrix that translates to origin of given destination area.
|
||||
*
|
||||
* @param[in] dest_area Area with relative coordinates of destination buffer
|
||||
*
|
||||
*/
|
||||
void vglite_set_translation_matrix(const lv_area_t * dest_area);
|
||||
|
||||
/**
|
||||
* Creates matrix that translates to origin of given destination area with transformation (scale or rotate).
|
||||
*
|
||||
* @param[in] dest_area Area with relative coordinates of destination buffer
|
||||
* @param[in] dsc Image descriptor
|
||||
*
|
||||
*/
|
||||
void vglite_set_transformation_matrix(const lv_area_t * dest_area, const lv_draw_image_dsc_t * dsc);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_DRAW_VGLITE*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_VGLITE_MATRIX_H*/
|
218
src/draw/nxp/vglite/lv_vglite_path.c
Normal file
218
src/draw/nxp/vglite/lv_vglite_path.c
Normal file
@ -0,0 +1,218 @@
|
||||
/**
|
||||
* @file lv_vglite_path.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_vglite_path.h"
|
||||
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
#include "vg_lite.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void vglite_create_rect_path_data(int32_t * path_data, uint32_t * path_data_size,
|
||||
lv_coord_t radius,
|
||||
const lv_area_t * coords)
|
||||
{
|
||||
lv_coord_t rect_width = lv_area_get_width(coords);
|
||||
lv_coord_t rect_height = lv_area_get_height(coords);
|
||||
|
||||
/* Get the final radius. Can't be larger than the half of the shortest side */
|
||||
int32_t shortest_side = LV_MIN(rect_width, rect_height);
|
||||
int32_t final_radius = LV_MIN(radius, shortest_side / 2);
|
||||
|
||||
/* Path data element index */
|
||||
uint8_t pidx = 0;
|
||||
|
||||
if((radius == (lv_coord_t)LV_RADIUS_CIRCLE) && (rect_width == rect_height)) {
|
||||
|
||||
/* Get the control point offset for rounded cases */
|
||||
int32_t cpoff = (int32_t)((float)final_radius * BEZIER_OPTIM_CIRCLE);
|
||||
|
||||
/* Circle case */
|
||||
/* Starting point */
|
||||
path_data[pidx++] = VLC_OP_MOVE;
|
||||
path_data[pidx++] = coords->x1 + final_radius;
|
||||
path_data[pidx++] = coords->y1;
|
||||
|
||||
/* Top-right arc */
|
||||
path_data[pidx++] = VLC_OP_CUBIC_REL;
|
||||
path_data[pidx++] = cpoff;
|
||||
path_data[pidx++] = 0;
|
||||
path_data[pidx++] = final_radius;
|
||||
path_data[pidx++] = final_radius - cpoff;
|
||||
path_data[pidx++] = final_radius;
|
||||
path_data[pidx++] = final_radius;
|
||||
|
||||
/* Bottom-right arc*/
|
||||
path_data[pidx++] = VLC_OP_CUBIC_REL;
|
||||
path_data[pidx++] = 0;
|
||||
path_data[pidx++] = cpoff;
|
||||
path_data[pidx++] = cpoff - final_radius;
|
||||
path_data[pidx++] = final_radius;
|
||||
path_data[pidx++] = 0 - final_radius;
|
||||
path_data[pidx++] = final_radius;
|
||||
|
||||
/* Bottom-left arc */
|
||||
path_data[pidx++] = VLC_OP_CUBIC_REL;
|
||||
path_data[pidx++] = 0 - cpoff;
|
||||
path_data[pidx++] = 0;
|
||||
path_data[pidx++] = 0 - final_radius;
|
||||
path_data[pidx++] = cpoff - final_radius;
|
||||
path_data[pidx++] = 0 - final_radius;
|
||||
path_data[pidx++] = 0 - final_radius;
|
||||
|
||||
/* Top-left arc*/
|
||||
path_data[pidx++] = VLC_OP_CUBIC_REL;
|
||||
path_data[pidx++] = 0;
|
||||
path_data[pidx++] = 0 - cpoff;
|
||||
path_data[pidx++] = final_radius - cpoff;
|
||||
path_data[pidx++] = 0 - final_radius;
|
||||
path_data[pidx++] = final_radius;
|
||||
path_data[pidx++] = 0 - final_radius;
|
||||
|
||||
/* Ending point */
|
||||
path_data[pidx++] = VLC_OP_END;
|
||||
}
|
||||
else if(radius > 0) {
|
||||
/* Get the control point offset for rounded cases */
|
||||
int32_t cpoff = (int32_t)((float)final_radius * BEZIER_OPTIM_CIRCLE);
|
||||
|
||||
/* Rounded rectangle case */
|
||||
/* Starting point */
|
||||
path_data[pidx++] = VLC_OP_MOVE;
|
||||
path_data[pidx++] = coords->x1 + final_radius;
|
||||
path_data[pidx++] = coords->y1;
|
||||
|
||||
/* Top side */
|
||||
path_data[pidx++] = VLC_OP_LINE;
|
||||
path_data[pidx++] = coords->x2 - final_radius + 1; // Extended for VGLite
|
||||
path_data[pidx++] = coords->y1;
|
||||
|
||||
/* Top-right corner */
|
||||
path_data[pidx++] = VLC_OP_CUBIC_REL;
|
||||
path_data[pidx++] = cpoff;
|
||||
path_data[pidx++] = 0;
|
||||
path_data[pidx++] = final_radius;
|
||||
path_data[pidx++] = final_radius - cpoff;
|
||||
path_data[pidx++] = final_radius;
|
||||
path_data[pidx++] = final_radius;
|
||||
|
||||
/* Right side */
|
||||
path_data[pidx++] = VLC_OP_LINE;
|
||||
path_data[pidx++] = coords->x2 + 1; // Extended for VGLite
|
||||
path_data[pidx++] = coords->y2 - final_radius + 1; // Extended for VGLite
|
||||
|
||||
/* Bottom-right corner*/
|
||||
path_data[pidx++] = VLC_OP_CUBIC_REL;
|
||||
path_data[pidx++] = 0;
|
||||
path_data[pidx++] = cpoff;
|
||||
path_data[pidx++] = cpoff - final_radius;
|
||||
path_data[pidx++] = final_radius;
|
||||
path_data[pidx++] = 0 - final_radius;
|
||||
path_data[pidx++] = final_radius;
|
||||
|
||||
/* Bottom side */
|
||||
path_data[pidx++] = VLC_OP_LINE;
|
||||
path_data[pidx++] = coords->x1 + final_radius;
|
||||
path_data[pidx++] = coords->y2 + 1; // Extended for VGLite
|
||||
|
||||
/* Bottom-left corner */
|
||||
path_data[pidx++] = VLC_OP_CUBIC_REL;
|
||||
path_data[pidx++] = 0 - cpoff;
|
||||
path_data[pidx++] = 0;
|
||||
path_data[pidx++] = 0 - final_radius;
|
||||
path_data[pidx++] = cpoff - final_radius;
|
||||
path_data[pidx++] = 0 - final_radius;
|
||||
path_data[pidx++] = 0 - final_radius;
|
||||
|
||||
/* Left side*/
|
||||
path_data[pidx++] = VLC_OP_LINE;
|
||||
path_data[pidx++] = coords->x1;
|
||||
path_data[pidx++] = coords->y1 + final_radius;
|
||||
|
||||
/* Top-left corner */
|
||||
path_data[pidx++] = VLC_OP_CUBIC_REL;
|
||||
path_data[pidx++] = 0;
|
||||
path_data[pidx++] = 0 - cpoff;
|
||||
path_data[pidx++] = final_radius - cpoff;
|
||||
path_data[pidx++] = 0 - final_radius;
|
||||
path_data[pidx++] = final_radius;
|
||||
path_data[pidx++] = 0 - final_radius;
|
||||
|
||||
/* Ending point */
|
||||
path_data[pidx++] = VLC_OP_END;
|
||||
}
|
||||
else {
|
||||
/* Non-rounded rectangle case */
|
||||
/* Starting point */
|
||||
path_data[pidx++] = VLC_OP_MOVE;
|
||||
path_data[pidx++] = coords->x1;
|
||||
path_data[pidx++] = coords->y1;
|
||||
|
||||
/* Top side */
|
||||
path_data[pidx++] = VLC_OP_LINE;
|
||||
path_data[pidx++] = coords->x2 + 1; // Extended for VGLite
|
||||
path_data[pidx++] = coords->y1;
|
||||
|
||||
/* Right side */
|
||||
path_data[pidx++] = VLC_OP_LINE;
|
||||
path_data[pidx++] = coords->x2 + 1; // Extended for VGLite
|
||||
path_data[pidx++] = coords->y2 + 1; // Extended for VGLite
|
||||
|
||||
/* Bottom side */
|
||||
path_data[pidx++] = VLC_OP_LINE;
|
||||
path_data[pidx++] = coords->x1;
|
||||
path_data[pidx++] = coords->y2 + 1; // Extended for VGLite
|
||||
|
||||
/* Left side*/
|
||||
path_data[pidx++] = VLC_OP_LINE;
|
||||
path_data[pidx++] = coords->x1;
|
||||
path_data[pidx++] = coords->y1;
|
||||
|
||||
/* Ending point */
|
||||
path_data[pidx++] = VLC_OP_END;
|
||||
}
|
||||
|
||||
/* Resulting path size */
|
||||
*path_data_size = pidx * sizeof(int32_t);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_DRAW_VGLITE*/
|
92
src/draw/nxp/vglite/lv_vglite_path.h
Normal file
92
src/draw/nxp/vglite/lv_vglite_path.h
Normal file
@ -0,0 +1,92 @@
|
||||
/**
|
||||
* @file lv_vglite_path.h
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LV_VGLITE_PATH_H
|
||||
#define LV_VGLITE_PATH_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
#include "../../sw/lv_draw_sw.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/* The optimal Bezier control point offset for radial unit
|
||||
* see: https://spencermortensen.com/articles/bezier-circle/
|
||||
**/
|
||||
#define BEZIER_OPTIM_CIRCLE 0.551915024494f
|
||||
|
||||
/* Draw lines for control points of Bezier curves */
|
||||
#define BEZIER_DBG_CONTROL_POINTS 0
|
||||
|
||||
/* Path data sizes for different elements */
|
||||
#define CUBIC_PATH_DATA_SIZE 7 /* 1 opcode, 6 arguments */
|
||||
#define LINE_PATH_DATA_SIZE 3 /* 1 opcode, 2 arguments */
|
||||
#define MOVE_PATH_DATA_SIZE 3 /* 1 opcode, 2 arguments */
|
||||
#define END_PATH_DATA_SIZE 1 /* 1 opcode, 0 arguments */
|
||||
/* Maximum possible rectangle path size
|
||||
* is in the rounded rectangle case:
|
||||
* - 1 move for the path start
|
||||
* - 4 cubics for the corners
|
||||
* - 4 lines for the sides
|
||||
* - 1 end for the path end */
|
||||
#define RECT_PATH_DATA_MAX_SIZE 1 * MOVE_PATH_DATA_SIZE + 4 * CUBIC_PATH_DATA_SIZE + 4 * LINE_PATH_DATA_SIZE + 1 * END_PATH_DATA_SIZE
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Generates path data for rectangle drawing.
|
||||
*
|
||||
* @param[in/out] path The path data to initialize
|
||||
* @param[in/out] path_size The resulting size of the created path data
|
||||
* @param[in] dsc The style descriptor for the rectangle to be drawn
|
||||
* @param[in] coords The coordinates of the rectangle to be drawn
|
||||
*
|
||||
*/
|
||||
void vglite_create_rect_path_data(int32_t * path_data, uint32_t * path_data_size,
|
||||
lv_coord_t radius,
|
||||
const lv_area_t * coords);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_DRAW_VGLITE*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_VGLITE_PATH_H*/
|
292
src/draw/nxp/vglite/lv_vglite_utils.c
Normal file
292
src/draw/nxp/vglite/lv_vglite_utils.c
Normal file
@ -0,0 +1,292 @@
|
||||
/**
|
||||
* @file lv_vglite_utils.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2022, 2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_vglite_utils.h"
|
||||
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
#include "lv_vglite_buf.h"
|
||||
|
||||
#include "../../../core/lv_refr.h"
|
||||
|
||||
#if LV_USE_OS
|
||||
#include "vg_lite_gpu.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
#if LV_USE_OS
|
||||
static volatile bool _cmd_buf_flushed = false;
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#if LV_USE_OS
|
||||
bool vglite_cmd_buf_is_flushed(void)
|
||||
{
|
||||
return _cmd_buf_flushed;
|
||||
}
|
||||
#endif
|
||||
|
||||
void vglite_run(void)
|
||||
{
|
||||
#if LV_USE_OS
|
||||
vg_lite_gpu_state_t gpu_state = vg_lite_get_gpu_state();
|
||||
|
||||
if(gpu_state == VG_LITE_GPU_BUSY) {
|
||||
_cmd_buf_flushed = false;
|
||||
|
||||
return;
|
||||
}
|
||||
#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_OS
|
||||
LV_ASSERT_MSG(vg_lite_flush() == VG_LITE_SUCCESS, "Flush failed.");
|
||||
_cmd_buf_flushed = true;
|
||||
#else
|
||||
LV_ASSERT_MSG(vg_lite_finish() == VG_LITE_SUCCESS, "Finish failed.");
|
||||
#endif
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if(!gradient)
|
||||
/* The color is in ABGR8888 format with red channel in the lower 8 bits. */
|
||||
vg_col32 = ((vg_lite_color_t)lv_col32.alpha << 24) | ((vg_lite_color_t)lv_col32.blue << 16) |
|
||||
((vg_lite_color_t)lv_col32.green << 8) | (vg_lite_color_t)lv_col32.red;
|
||||
else
|
||||
/* The gradient color is in ARGB8888 format with blue channel in the lower 8 bits. */
|
||||
vg_col32 = ((vg_lite_color_t)lv_col32.alpha << 24) | ((vg_lite_color_t)lv_col32.red << 16) |
|
||||
((vg_lite_color_t)lv_col32.green << 8) | (vg_lite_color_t)lv_col32.blue;
|
||||
|
||||
return vg_col32;
|
||||
}
|
||||
|
||||
vg_lite_blend_t vglite_get_blend_mode(lv_blend_mode_t lv_blend_mode)
|
||||
{
|
||||
vg_lite_blend_t vg_blend_mode;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return vg_blend_mode;
|
||||
}
|
||||
|
||||
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;
|
||||
case LV_COLOR_FORMAT_A8:
|
||||
vg_buffer_format = VG_LITE_A8;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_I1:
|
||||
vg_buffer_format = VG_LITE_INDEX_1;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_I2:
|
||||
vg_buffer_format = VG_LITE_INDEX_2;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_I4:
|
||||
vg_buffer_format = VG_LITE_INDEX_4;
|
||||
break;
|
||||
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.");
|
||||
break;
|
||||
|
||||
/*3 byte (+alpha) formats*/
|
||||
case LV_COLOR_FORMAT_RGB888:
|
||||
LV_ASSERT_MSG(false, "Unsupported color format.");
|
||||
break;
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
vg_buffer_format = VG_LITE_BGRA8888;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_XRGB8888:
|
||||
vg_buffer_format = VG_LITE_BGRX8888;
|
||||
break;
|
||||
|
||||
default:
|
||||
LV_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;
|
||||
case LV_COLOR_FORMAT_NATIVE_REVERSED:
|
||||
bits_per_pixel = LV_COLOR_DEPTH;
|
||||
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
|
||||
|
||||
switch(cf) {
|
||||
case LV_COLOR_FORMAT_I1:
|
||||
case LV_COLOR_FORMAT_I2:
|
||||
case LV_COLOR_FORMAT_I4:
|
||||
align_bytes = 8;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_I8:
|
||||
case LV_COLOR_FORMAT_A8:
|
||||
case LV_COLOR_FORMAT_L8:
|
||||
align_bytes = 16;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
align_bytes = 32;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_RGB565A8:
|
||||
case LV_COLOR_FORMAT_RGB888:
|
||||
align_bytes = 48;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
case LV_COLOR_FORMAT_XRGB8888:
|
||||
align_bytes = 64;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_NATIVE_REVERSED:
|
||||
align_bytes = LV_COLOR_DEPTH / 8 * 16;
|
||||
break;
|
||||
|
||||
default:
|
||||
LV_ASSERT_MSG(false, "Unsupported buffer format.");
|
||||
break;
|
||||
}
|
||||
|
||||
return align_bytes;
|
||||
}
|
||||
|
||||
bool vglite_buf_aligned(const void * buf, uint32_t stride, lv_color_format_t cf)
|
||||
{
|
||||
uint8_t align_bytes = vglite_get_alignment(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);
|
||||
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);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_DRAW_VGLITE*/
|
165
src/draw/nxp/vglite/lv_vglite_utils.h
Normal file
165
src/draw/nxp/vglite/lv_vglite_utils.h
Normal file
@ -0,0 +1,165 @@
|
||||
/**
|
||||
* @file lv_vglite_utils.h
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2022, 2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LV_VGLITE_UTILS_H
|
||||
#define LV_VGLITE_UTILS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
#include "../../sw/lv_draw_sw.h"
|
||||
|
||||
#include "vg_lite.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Enable scissor and 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
|
||||
/**
|
||||
* Get VG-Lite command buffer flushed status.
|
||||
*
|
||||
*/
|
||||
bool vglite_cmd_buf_is_flushed(void);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Clear cache and flush command to VG-Lite.
|
||||
*
|
||||
*/
|
||||
void vglite_run(void);
|
||||
|
||||
/**
|
||||
* Get vglite color. Premultiplies (if not hw already) and swizzles the given
|
||||
* LVGL 32bit color to obtain vglite color.
|
||||
*
|
||||
* @param[in] lv_col32 The initial LVGL 32bit color
|
||||
* @param[in] gradient True for gradient color
|
||||
*
|
||||
* @retval The vglite 32-bit color value:
|
||||
*
|
||||
*/
|
||||
vg_lite_color_t vglite_get_color(lv_color32_t lv_col32, bool gradient);
|
||||
|
||||
/**
|
||||
* Get vglite blend mode.
|
||||
*
|
||||
* @param[in] lv_blend_mode The LVGL blend mode
|
||||
*
|
||||
* @retval The vglite blend mode
|
||||
*
|
||||
*/
|
||||
vg_lite_blend_t vglite_get_blend_mode(lv_blend_mode_t lv_blend_mode);
|
||||
|
||||
/**
|
||||
* Get vglite buffer format.
|
||||
*
|
||||
* @param[in] cf Color format
|
||||
*
|
||||
* @retval The vglite buffer format
|
||||
*
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @param[in] cf Color format
|
||||
*
|
||||
* @retval Alignment requirement in bytes
|
||||
*
|
||||
*/
|
||||
uint8_t vglite_get_alignment(lv_color_format_t cf);
|
||||
|
||||
/**
|
||||
* Check memory and stride alignment.
|
||||
*
|
||||
* @param[in] buf Buffer address
|
||||
* @param[in] stride Stride of buffer in bytes
|
||||
* @param[in] cf Color format - to calculate the expected alignment
|
||||
*
|
||||
* @retval true Alignment OK
|
||||
*
|
||||
*/
|
||||
bool vglite_buf_aligned(const void * buf, uint32_t stride, lv_color_format_t cf);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_VGLITE*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_VGLITE_UTILS_H*/
|
@ -319,6 +319,24 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Use NXP's VG-Lite GPU on iMX RTxxx platforms. */
|
||||
#ifndef LV_USE_DRAW_VGLITE
|
||||
#ifdef CONFIG_LV_USE_DRAW_VGLITE
|
||||
#define LV_USE_DRAW_VGLITE CONFIG_LV_USE_DRAW_VGLITE
|
||||
#else
|
||||
#define LV_USE_DRAW_VGLITE 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Use NXP's PXP on iMX RTxxx platforms. */
|
||||
#ifndef LV_USE_DRAW_PXP
|
||||
#ifdef CONFIG_LV_USE_DRAW_PXP
|
||||
#define LV_USE_DRAW_PXP CONFIG_LV_USE_DRAW_PXP
|
||||
#else
|
||||
#define LV_USE_DRAW_PXP 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*=================
|
||||
* OPERATING SYSTEM
|
||||
*=================*/
|
||||
|
@ -23,6 +23,12 @@
|
||||
#include "misc/lv_cache_builtin.h"
|
||||
#include "misc/lv_async.h"
|
||||
#include "misc/lv_fs.h"
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
#include "draw/nxp/vglite/lv_draw_vglite.h"
|
||||
#endif
|
||||
#if LV_USE_DRAW_PXP
|
||||
#include "draw/nxp/pxp/lv_draw_pxp.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@ -137,6 +143,14 @@ void lv_init(void)
|
||||
lv_draw_sw_init();
|
||||
#endif
|
||||
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
lv_draw_vglite_init();
|
||||
#endif
|
||||
|
||||
#if LV_USE_DRAW_PXP
|
||||
lv_draw_pxp_init();
|
||||
#endif
|
||||
|
||||
_lv_obj_style_init();
|
||||
|
||||
/*Initialize the screen refresh system*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user