feat(nxp): add G2D support (#7625)
Signed-off-by: Ana Grad <ana.grad@nxp.com> Co-authored-by: Ana Grad <ana.grad@nxp.com>
This commit is contained in:
committed by
GitHub
parent
00df4ca7a4
commit
560364adaa
20
Kconfig
20
Kconfig
@@ -409,6 +409,26 @@ menu "LVGL configuration"
|
||||
config LV_USE_PXP_ASSERT
|
||||
bool "Enable PXP asserts"
|
||||
depends on LV_USE_DRAW_PXP
|
||||
|
||||
config LV_USE_DRAW_G2D
|
||||
bool "Use NXP's G2D on MPU platforms"
|
||||
default n
|
||||
|
||||
config LV_G2D_HASH_TABLE_SIZE
|
||||
bool "Maximum number of buffers that can be stored for G2D draw unit."
|
||||
default 50
|
||||
depends on LV_USE_DRAW_G2D
|
||||
help
|
||||
Includes the frame buffers and assets.
|
||||
|
||||
config LV_USE_G2D_DRAW_THREAD
|
||||
bool "Use additional draw thread for G2D processing"
|
||||
depends on LV_USE_DRAW_G2D && LV_USE_OS > 0
|
||||
default y
|
||||
|
||||
config LV_USE_G2D_ASSERT
|
||||
bool "Enable G2D asserts"
|
||||
depends on LV_USE_DRAW_G2D
|
||||
default n
|
||||
|
||||
config LV_USE_DRAW_DAVE2D
|
||||
|
||||
@@ -20,7 +20,7 @@ Creating new project with LVGL
|
||||
|
||||
`Download an SDK for a supported board <https://www.nxp.com/design/software/embedded-software/littlevgl-open-source-graphics-library:LITTLEVGL-OPEN-SOURCE-GRAPHICS-LIBRARY?&tid=vanLITTLEVGL-OPEN-SOURCE-GRAPHICS-LIBRARY>`__
|
||||
today and get started with your next GUI application. It comes fully configured
|
||||
with LVGL (and with PXP/VGLite support if the modules are present), no
|
||||
with LVGL (and with PXP/VGLite/G2D support if the modules are present), no
|
||||
additional integration work is required.
|
||||
|
||||
HW acceleration for NXP iMX RT platforms
|
||||
@@ -31,6 +31,13 @@ Depending on the RT platform used, the acceleration can be done by NXP PXP
|
||||
accelerator has its own context that allows them to be used individually as well
|
||||
simultaneously (in LVGL multithreading mode).
|
||||
|
||||
HW acceleration for NXP iMX platforms
|
||||
----------------------------------------
|
||||
|
||||
On MPU platforms, the acceleration can be done (hardware independent) by NXP G2D
|
||||
library. This accelerator has its own context that allows them to be used
|
||||
individually as well simultaneously with the CPU (in LVGL multithreading mode).
|
||||
|
||||
PXP accelerator
|
||||
~~~~~~~~~~~~~~~
|
||||
Basic configuration:
|
||||
@@ -327,7 +334,7 @@ is available for other operations while the GPU is running. RTOS is required to
|
||||
block the LVGL drawing thread and switch to another task or suspend the CPU for
|
||||
power savings.
|
||||
|
||||
Supported draw tasks are available in "src/draw/nxp/pxp/lv_draw_vglite.c":
|
||||
Supported draw tasks are available in "src/draw/nxp/vglite/lv_draw_vglite.c":
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
@@ -408,3 +415,122 @@ Project setup:
|
||||
- "src/draw/nxp/vglite/lv_vglite_matrix.c": set vglite matrix
|
||||
- "src/draw/nxp/vglite/lv_vglite_path.c": create vglite path data
|
||||
- "src/draw/nxp/vglite/lv_vglite_utils.c": function helpers
|
||||
|
||||
G2D accelerator
|
||||
~~~~~~~~~~~~~~~
|
||||
Basic configuration:
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Select NXP G2D engine in "lv_conf.h": Set :c:macro:`LV_USE_G2D` to `1`.
|
||||
- In order to use G2D as a draw unit, select in "lv_conf.h": Set :c:macro:`LV_USE_DRAW_G2D` to `1`.
|
||||
- Enable G2D asserts in "lv_conf.h": Set :c:macro: `LV_USE_G2D_ASSERT` to `1`.
|
||||
There are few G2D assertions that can stop the program execution in case the
|
||||
c:macro: `LV_ASSERT_HANDLER` is set to `while(1);` (Halt by default). Else,
|
||||
there will be logged just an error message via `LV_LOG_ERROR`.
|
||||
|
||||
Basic initialization:
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
G2D draw initialization is done automatically in :cpp:func:`lv_init()` once the
|
||||
G2D is enabled as a draw unit , no user code is required:
|
||||
|
||||
.. code:: c
|
||||
|
||||
#if LV_USE_DRAW_G2D
|
||||
lv_draw_g2d_init();
|
||||
#endif
|
||||
|
||||
During G2D initialization, a new draw unit `lv_draw_g2d_unit_t` will be created
|
||||
with the additional callbacks, if :c:macro:`LV_USE_DRAW_G2D` is set to `1`:
|
||||
|
||||
.. code:: c
|
||||
|
||||
lv_draw_g2d_unit_t * draw_g2d_unit = lv_draw_create_unit(sizeof(lv_draw_g2d_unit_t));
|
||||
draw_g2d_unit->base_unit.evaluate_cb = _g2d_evaluate;
|
||||
draw_g2d_unit->base_unit.dispatch_cb = _g2d_dispatch;
|
||||
draw_g2d_unit->base_unit.delete_cb = _g2d_delete;
|
||||
|
||||
and an addition thread `_g2d_render_thread_cb()` will be spawned in order to
|
||||
handle the supported draw tasks.
|
||||
|
||||
.. code:: c
|
||||
|
||||
#if LV_USE_G2D_DRAW_THREAD
|
||||
lv_thread_init(&draw_g2d_unit->thread, LV_THREAD_PRIO_HIGH, _g2d_render_thread_cb, 2 * 1024, draw_g2d_unit);
|
||||
#endif
|
||||
|
||||
If `LV_USE_G2D_DRAW_THREAD` is not defined, then no additional draw thread will be created
|
||||
and the G2D drawing task will get executed on the same LVGL main thread.
|
||||
|
||||
`_g2d_evaluate()` will get called after each task is being created and will
|
||||
analyze if the task is supported by G2D or not. If it is supported, then an
|
||||
preferred score and the draw unit id will be set to the task. An `score` equal
|
||||
to `100` is the default CPU score. Smaller score means that G2D is capable of
|
||||
drawing it faster.
|
||||
|
||||
`_g2d_dispatch()` is the G2D dispatcher callback, it will take a ready to draw
|
||||
task (having the `DRAW_UNIT_ID_G2D` set) and will pass the task to the G2D draw
|
||||
unit for processing.
|
||||
|
||||
`_g2d_delete()` will cleanup the G2D draw unit.
|
||||
|
||||
Features supported:
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Several drawing features in LVGL can be offloaded to the G2D engine. The CPU is
|
||||
available for other operations while the G2D is running. Linux OS is required to
|
||||
block the LVGL drawing thread and switch to another task or suspend the CPU for
|
||||
power savings.
|
||||
|
||||
Supported draw tasks are available in "src/draw/nx/g2d/lv_draw_g2d.c":
|
||||
|
||||
.. code:: c
|
||||
|
||||
switch(t->type) {
|
||||
case LV_DRAW_TASK_TYPE_FILL:
|
||||
lv_draw_g2d_fill(u, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_IMAGE:
|
||||
lv_draw_g2d_img(u, t->draw_dsc, &t->area);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
- Fill area with color (w/o radius, w/o gradient) + optional opacity.
|
||||
- Blit source image ARGB8888 over destination.
|
||||
ARGB8888 + optional opacity.
|
||||
- Scale source image ARGB8888.
|
||||
|
||||
Known limitations:
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- G2D/PXP can only rotate at 90x angles.
|
||||
- Rotation is not supported for images unaligned to blocks of 16x16 pixels. G2D/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.
|
||||
- Recolor or transformation for images w/ opacity or alpha channel can't be
|
||||
obtained in a single G2D/PXP pipeline configuration. Two or multiple steps would
|
||||
be required.
|
||||
- Buffer address must be aligned to 64 bytes: set :c:macro:`LV_DRAW_BUF_ALIGN`
|
||||
to `64` in "lv_conf.h".
|
||||
No stride alignment is required: set :c:macro:`LV_DRAW_BUF_STRIDE_ALIGN` to
|
||||
`1` in "lv_conf.h".
|
||||
|
||||
Project setup:
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
- Add G2D related source files (and corresponding headers if available) to
|
||||
project:
|
||||
|
||||
- "src/draw/nxp/g2d/lv_draw_buf_g2d.c": draw buffer callbacks
|
||||
- "src/draw/nxp/g2d/lv_draw_g2d_fill.c": fill area
|
||||
- "src/draw/nxp/g2d/lv_draw_g2d_img.c": blit image (w/ optional recolor or
|
||||
transformation)
|
||||
- "src/draw/nxp/g2d/lv_draw_g2d.c": draw unit initialization
|
||||
- "src/draw/nxp/g2d/lv_draw_g2d_buf_map.c": hash map for g2d buffers
|
||||
- "src/draw/nxp/g2d/lv_g2d_utils.c": function helpers
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ Renderers and GPUs
|
||||
nema_gfx
|
||||
nxp_pxp
|
||||
nxp_vglite_gpu
|
||||
nxp_g2d
|
||||
sdl
|
||||
stm32_dma2d
|
||||
vg_lite
|
||||
|
||||
8
docs/details/integration/renderers/nxp_g2d.rst
Normal file
8
docs/details/integration/renderers/nxp_g2d.rst
Normal file
@@ -0,0 +1,8 @@
|
||||
===========
|
||||
NXP G2D GPU
|
||||
===========
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
:ref:`lv_draw_g2d_h`
|
||||
@@ -8,8 +8,3 @@ API
|
||||
:ref:`lv_draw_pxp_h`
|
||||
|
||||
:ref:`lv_pxp_cfg_h`
|
||||
|
||||
:ref:`lv_pxp_osa_h`
|
||||
|
||||
:ref:`lv_pxp_utils_h`
|
||||
|
||||
|
||||
@@ -6,11 +6,3 @@ API
|
||||
---
|
||||
|
||||
:ref:`lv_draw_vglite_h`
|
||||
|
||||
:ref:`lv_vglite_buf_h`
|
||||
|
||||
:ref:`lv_vglite_matrix_h`
|
||||
|
||||
:ref:`lv_vglite_path_h`
|
||||
|
||||
:ref:`lv_vglite_utils_h`
|
||||
|
||||
@@ -59,6 +59,7 @@ remove the misleading guide above this code segment.
|
||||
- LV_USE_DRAW_VGLITE
|
||||
- LV_USE_DRAW_VG_LITE
|
||||
- LV_USE_PXP
|
||||
- LV_USE_DRAW_G2D
|
||||
- LV_USE_DRAW_SDL
|
||||
- LV_USE_DRAW_ARM2D_SYNC
|
||||
- LV_USE_DRAW_ARM2D_ASYNC
|
||||
|
||||
@@ -278,6 +278,23 @@
|
||||
#define LV_USE_PXP_ASSERT 0
|
||||
#endif
|
||||
|
||||
/** Use NXP's G2D on MPU platforms. */
|
||||
#define LV_USE_DRAW_G2D 0
|
||||
|
||||
#if LV_USE_DRAW_G2D
|
||||
/** Maximum number of buffers that can be stored for G2D draw unit.
|
||||
* Includes the frame buffers and assets. */
|
||||
#define LV_G2D_HASH_TABLE_SIZE 50
|
||||
|
||||
#if LV_USE_OS
|
||||
/** Use additional draw thread for G2D processing.*/
|
||||
#define LV_USE_G2D_DRAW_THREAD 1
|
||||
#endif
|
||||
|
||||
/** Enable G2D asserts. */
|
||||
#define LV_USE_G2D_ASSERT 0
|
||||
#endif
|
||||
|
||||
/** Use Renesas Dave2D on RA platforms. */
|
||||
#define LV_USE_DRAW_DAVE2D 0
|
||||
|
||||
|
||||
93
src/draw/nxp/g2d/lv_draw_buf_g2d.c
Normal file
93
src/draw/nxp/g2d/lv_draw_buf_g2d.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* @file lv_draw_buf_g2d.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_g2d.h"
|
||||
|
||||
#if LV_USE_DRAW_G2D
|
||||
#include "../../lv_draw_buf_private.h"
|
||||
#include "g2d.h"
|
||||
#include "lv_g2d_buf_map.h"
|
||||
#include "lv_g2d_utils.h"
|
||||
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void * _buf_malloc(size_t size_bytes, lv_color_format_t color_format);
|
||||
|
||||
static void _buf_free(void * buf);
|
||||
|
||||
static void _invalidate_cache(const lv_draw_buf_t * draw_buf, const lv_area_t * area);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_buf_g2d_init_handlers(void)
|
||||
{
|
||||
lv_draw_buf_handlers_t * handlers = lv_draw_buf_get_handlers();
|
||||
|
||||
handlers->buf_malloc_cb = _buf_malloc;
|
||||
handlers->buf_free_cb = _buf_free;
|
||||
handlers->invalidate_cache_cb = _invalidate_cache;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void * _buf_malloc(size_t size_bytes, lv_color_format_t color_format)
|
||||
{
|
||||
LV_UNUSED(color_format);
|
||||
|
||||
size_bytes += LV_DRAW_BUF_ALIGN - 1;
|
||||
struct g2d_buf * buf = g2d_alloc(size_bytes, 1);
|
||||
G2D_ASSERT_MSG(buf, "Failed to alloc buffer.");
|
||||
g2d_insert_buf_map(buf->buf_vaddr, buf);
|
||||
return buf->buf_vaddr;
|
||||
}
|
||||
|
||||
static void _buf_free(void * buf)
|
||||
{
|
||||
g2d_free_item(buf);
|
||||
}
|
||||
|
||||
static void _invalidate_cache(const lv_draw_buf_t * draw_buf, const lv_area_t * area)
|
||||
{
|
||||
|
||||
LV_UNUSED(area);
|
||||
struct g2d_buf * buf = g2d_search_buf_map(draw_buf->data);
|
||||
G2D_ASSERT_MSG(buf, "Failed to find buffer in map.");
|
||||
g2d_cache_op(buf, G2D_CACHE_FLUSH);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_G2D*/
|
||||
317
src/draw/nxp/g2d/lv_draw_g2d.c
Normal file
317
src/draw/nxp/g2d/lv_draw_g2d.c
Normal file
@@ -0,0 +1,317 @@
|
||||
/**
|
||||
* @file lv_draw_g2d.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "lv_draw_g2d.h"
|
||||
|
||||
#if LV_USE_DRAW_G2D
|
||||
#include "../../../misc/lv_area_private.h"
|
||||
#include "g2d.h"
|
||||
#include "lv_g2d_buf_map.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define DRAW_UNIT_ID_G2D 8
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Evaluate a task and set the score and preferred G2D unit.
|
||||
* Return 1 if task is preferred, 0 otherwise (task is not supported).
|
||||
*/
|
||||
static int32_t _g2d_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task);
|
||||
|
||||
/**
|
||||
* Dispatch a task to the G2D unit.
|
||||
* Return 1 if task was dispatched, 0 otherwise (task not supported).
|
||||
*/
|
||||
static int32_t _g2d_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer);
|
||||
|
||||
/**
|
||||
* Delete the G2D draw unit.
|
||||
*/
|
||||
static int32_t _g2d_delete(lv_draw_unit_t * draw_unit);
|
||||
|
||||
#if LV_USE_G2D_DRAW_THREAD
|
||||
static void _g2d_render_thread_cb(void * ptr);
|
||||
#endif
|
||||
|
||||
static void _g2d_execute_drawing(lv_draw_g2d_unit_t * u);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_g2d_init(void)
|
||||
{
|
||||
lv_draw_buf_g2d_init_handlers();
|
||||
|
||||
lv_draw_g2d_unit_t * draw_g2d_unit = lv_draw_create_unit(sizeof(lv_draw_g2d_unit_t));
|
||||
draw_g2d_unit->base_unit.evaluate_cb = _g2d_evaluate;
|
||||
draw_g2d_unit->base_unit.dispatch_cb = _g2d_dispatch;
|
||||
draw_g2d_unit->base_unit.delete_cb = _g2d_delete;
|
||||
g2d_create_buf_map();
|
||||
if(g2d_open(&draw_g2d_unit->g2d_handle)) {
|
||||
LV_LOG_ERROR("g2d_open fail.\n");
|
||||
}
|
||||
#if LV_USE_G2D_DRAW_THREAD
|
||||
lv_thread_init(&draw_g2d_unit->thread, "g2ddraw", LV_THREAD_PRIO_HIGH, _g2d_render_thread_cb, 2 * 1024, draw_g2d_unit);
|
||||
#endif
|
||||
}
|
||||
|
||||
void lv_draw_g2d_deinit(void)
|
||||
{
|
||||
g2d_free_buf_map();
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static inline bool _g2d_dest_cf_supported(lv_color_format_t cf)
|
||||
{
|
||||
bool is_cf_supported = false;
|
||||
|
||||
switch(cf) {
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
is_cf_supported = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return is_cf_supported;
|
||||
}
|
||||
|
||||
static inline bool _g2d_src_cf_supported(lv_color_format_t cf)
|
||||
{
|
||||
bool is_cf_supported = false;
|
||||
|
||||
switch(cf) {
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
is_cf_supported = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return is_cf_supported;
|
||||
}
|
||||
|
||||
static bool _g2d_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_MIN);
|
||||
bool has_rotation = (draw_dsc->rotation != 0);
|
||||
|
||||
/* Recolor or rotation are not supported. */
|
||||
if(has_recolor || has_rotation)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int32_t _g2d_evaluate(lv_draw_unit_t * u, lv_draw_task_t * t)
|
||||
{
|
||||
LV_UNUSED(u);
|
||||
|
||||
const lv_draw_dsc_base_t * draw_dsc_base = (lv_draw_dsc_base_t *) t->draw_dsc;
|
||||
lv_draw_buf_t * draw_buf = draw_dsc_base->layer->draw_buf;
|
||||
|
||||
if(!_g2d_dest_cf_supported(draw_dsc_base->layer->color_format))
|
||||
return 0;
|
||||
|
||||
if(draw_buf && !g2d_search_buf_map(draw_buf->data))
|
||||
return 0;
|
||||
|
||||
switch(t->type) {
|
||||
case LV_DRAW_TASK_TYPE_FILL: {
|
||||
const lv_draw_fill_dsc_t * draw_dsc = (lv_draw_fill_dsc_t *) t->draw_dsc;
|
||||
|
||||
/* 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_G2D;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
case LV_DRAW_TASK_TYPE_IMAGE: {
|
||||
const lv_draw_image_dsc_t * draw_dsc = (lv_draw_image_dsc_t *) t->draw_dsc;
|
||||
|
||||
if(!_g2d_src_cf_supported(draw_dsc->header.cf))
|
||||
return 0;
|
||||
|
||||
if(!_g2d_draw_img_supported(draw_dsc))
|
||||
return 0;
|
||||
|
||||
if(t->preference_score > 70) {
|
||||
t->preference_score = 70;
|
||||
t->preferred_draw_unit_id = DRAW_UNIT_ID_G2D;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int32_t _g2d_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
|
||||
{
|
||||
lv_draw_g2d_unit_t * draw_g2d_unit = (lv_draw_g2d_unit_t *) draw_unit;
|
||||
|
||||
/* Return immediately if it's busy with draw task. */
|
||||
if(draw_g2d_unit->task_act)
|
||||
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_G2D);
|
||||
|
||||
if(t == NULL || t->preferred_draw_unit_id != DRAW_UNIT_ID_G2D)
|
||||
return LV_DRAW_UNIT_IDLE;
|
||||
|
||||
if(lv_draw_layer_alloc_buf(layer) == NULL)
|
||||
return LV_DRAW_UNIT_IDLE;
|
||||
|
||||
t->state = LV_DRAW_TASK_STATE_IN_PROGRESS;
|
||||
draw_g2d_unit->task_act = t;
|
||||
|
||||
#if LV_USE_G2D_DRAW_THREAD
|
||||
/* Let the render thread work. */
|
||||
if(draw_g2d_unit->inited)
|
||||
lv_thread_sync_signal(&draw_g2d_unit->sync);
|
||||
#else
|
||||
_g2d_execute_drawing(draw_g2d_unit);
|
||||
|
||||
draw_g2d_unit->task_act->state = LV_DRAW_TASK_STATE_READY;
|
||||
draw_g2d_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 int32_t _g2d_delete(lv_draw_unit_t * draw_unit)
|
||||
{
|
||||
lv_draw_g2d_unit_t * draw_g2d_unit = (lv_draw_g2d_unit_t *) draw_unit;
|
||||
lv_result_t res = LV_RESULT_OK;
|
||||
|
||||
#if LV_USE_G2D_DRAW_THREAD
|
||||
LV_LOG_INFO("Cancel G2D draw thread.");
|
||||
draw_g2d_unit->exit_status = true;
|
||||
|
||||
if(draw_g2d_unit->inited)
|
||||
lv_thread_sync_signal(&draw_g2d_unit->sync);
|
||||
|
||||
res = lv_thread_delete(&draw_g2d_unit->thread);
|
||||
#endif
|
||||
g2d_close(draw_g2d_unit->g2d_handle);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void _g2d_execute_drawing(lv_draw_g2d_unit_t * u)
|
||||
{
|
||||
lv_draw_task_t * t = u->task_act;
|
||||
lv_layer_t * layer = t->target_layer;
|
||||
lv_draw_buf_t * draw_buf = layer->draw_buf;
|
||||
|
||||
t->draw_unit = (lv_draw_unit_t *)u;
|
||||
|
||||
lv_area_t draw_area;
|
||||
if(!lv_area_intersect(&draw_area, &t->area, &t->clip_area))
|
||||
return; /*Fully clipped, nothing to do*/
|
||||
|
||||
/* Make area relative to the buffer */
|
||||
lv_area_move(&draw_area, -layer->buf_area.x1, -layer->buf_area.y1);
|
||||
|
||||
/* Invalidate only the drawing area */
|
||||
lv_draw_buf_invalidate_cache(draw_buf, &draw_area);
|
||||
|
||||
switch(t->type) {
|
||||
case LV_DRAW_TASK_TYPE_FILL:
|
||||
lv_draw_g2d_fill(t);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_IMAGE:
|
||||
lv_draw_g2d_img(t);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Invalidate only the drawing area */
|
||||
lv_draw_buf_invalidate_cache(draw_buf, &draw_area);
|
||||
}
|
||||
|
||||
#if LV_USE_G2D_DRAW_THREAD
|
||||
static void _g2d_render_thread_cb(void * ptr)
|
||||
{
|
||||
lv_draw_g2d_unit_t * u = ptr;
|
||||
|
||||
lv_thread_sync_init(&u->sync);
|
||||
u->inited = true;
|
||||
|
||||
while(1) {
|
||||
/* Wait for sync if there is no task set. */
|
||||
while(u->task_act == NULL) {
|
||||
if(u->exit_status)
|
||||
break;
|
||||
|
||||
lv_thread_sync_wait(&u->sync);
|
||||
}
|
||||
|
||||
if(u->exit_status) {
|
||||
LV_LOG_INFO("Ready to exit G2D draw thread.");
|
||||
break;
|
||||
}
|
||||
|
||||
_g2d_execute_drawing(u);
|
||||
|
||||
/* Signal the ready state to dispatcher. */
|
||||
u->task_act->state = LV_DRAW_TASK_STATE_READY;
|
||||
|
||||
/* Cleanup. */
|
||||
u->task_act = NULL;
|
||||
|
||||
/* The draw unit is free now. Request a new dispatching as it can get a new task. */
|
||||
lv_draw_dispatch_request();
|
||||
}
|
||||
|
||||
u->inited = false;
|
||||
lv_thread_sync_delete(&u->sync);
|
||||
LV_LOG_INFO("Exit G2D draw thread.");
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*LV_USE_DRAW_G2D*/
|
||||
66
src/draw/nxp/g2d/lv_draw_g2d.h
Normal file
66
src/draw/nxp/g2d/lv_draw_g2d.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* @file lv_draw_g2d.h
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_G2D_H
|
||||
#define LV_DRAW_G2D_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_DRAW_G2D
|
||||
#include "../../sw/lv_draw_sw_private.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct lv_draw_g2d_unit {
|
||||
lv_draw_sw_unit_t;
|
||||
|
||||
void * g2d_handle;
|
||||
} lv_draw_g2d_unit_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_draw_g2d_init(void);
|
||||
|
||||
void lv_draw_g2d_deinit(void);
|
||||
|
||||
void lv_draw_buf_g2d_init_handlers(void);
|
||||
|
||||
void lv_draw_g2d_fill(lv_draw_task_t * t);
|
||||
|
||||
void lv_draw_g2d_img(lv_draw_task_t * t);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_DRAW_G2D*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_G2D_H*/
|
||||
189
src/draw/nxp/g2d/lv_draw_g2d_fill.c
Normal file
189
src/draw/nxp/g2d/lv_draw_g2d_fill.c
Normal file
@@ -0,0 +1,189 @@
|
||||
/**
|
||||
* @file lv_draw_g2d_fill.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_g2d.h"
|
||||
|
||||
#if LV_USE_DRAW_G2D
|
||||
#include <stdlib.h>
|
||||
#include "g2d.h"
|
||||
#include "../../../misc/lv_area_private.h"
|
||||
#include "lv_g2d_buf_map.h"
|
||||
#include "lv_g2d_utils.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/* Blit simple w/ opa and alpha channel */
|
||||
static void _g2d_fill(void * g2d_handle, struct g2d_buf * dst_buf, struct g2d_surface * dst_surf);
|
||||
static void _g2d_fill_with_opa(void * g2d_handle, struct g2d_buf * dst_buf, struct g2d_surface * dst_surf,
|
||||
struct g2d_buf * src_buf, struct g2d_surface * src_surf);
|
||||
|
||||
static void _g2d_set_src_surf(struct g2d_surface * src_surf, struct g2d_buf * buf, const lv_area_t * area,
|
||||
int32_t stride, lv_color_t color, lv_opa_t opa);
|
||||
|
||||
static void _g2d_set_dst_surf(struct g2d_surface * dst_surf, struct g2d_buf * buf, const lv_area_t * area,
|
||||
int32_t stride, lv_color_t color);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_g2d_fill(lv_draw_task_t * t)
|
||||
{
|
||||
lv_draw_fill_dsc_t * dsc = t->draw_dsc;
|
||||
|
||||
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
|
||||
return;
|
||||
|
||||
lv_draw_g2d_unit_t * u = (lv_draw_g2d_unit_t *)t->draw_unit;
|
||||
lv_layer_t * layer = t->target_layer;
|
||||
lv_draw_buf_t * draw_buf = layer->draw_buf;
|
||||
lv_area_t * coords = &t->area;
|
||||
|
||||
lv_area_t rel_coords;
|
||||
lv_area_copy(&rel_coords, coords);
|
||||
lv_area_move(&rel_coords, -layer->buf_area.x1, -layer->buf_area.y1);
|
||||
|
||||
lv_area_t rel_clip_area;
|
||||
lv_area_copy(&rel_clip_area, &t->clip_area);
|
||||
lv_area_move(&rel_clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
|
||||
|
||||
lv_area_t blend_area;
|
||||
if(!lv_area_intersect(&blend_area, &rel_coords, &rel_clip_area))
|
||||
return; /*Fully clipped, nothing to do*/
|
||||
|
||||
/* G2D takes stride in pixels. */
|
||||
int32_t stride = draw_buf->header.stride / (lv_color_format_get_bpp(draw_buf->header.cf) / 8);
|
||||
|
||||
/* Destination buffer */
|
||||
struct g2d_buf * dst_buf = g2d_search_buf_map(draw_buf->data);
|
||||
|
||||
bool has_opa = (dsc->opa < (lv_opa_t)LV_OPA_MAX);
|
||||
struct g2d_surface * dst_surf = lv_malloc(sizeof(struct g2d_surface));
|
||||
G2D_ASSERT_MSG(dst_surf, "Failed to alloc destination surface.");
|
||||
_g2d_set_dst_surf(dst_surf, dst_buf, &blend_area, stride, dsc->color);
|
||||
|
||||
if(has_opa) {
|
||||
struct g2d_buf * tmp_buf = g2d_alloc(lv_area_get_width(&blend_area) * lv_area_get_height(&blend_area) * sizeof(
|
||||
lv_color32_t), 1);
|
||||
G2D_ASSERT_MSG(tmp_buf, "Failed to alloc temporary buffer.");
|
||||
struct g2d_surface * src_surf = lv_malloc(sizeof(struct g2d_surface));
|
||||
G2D_ASSERT_MSG(src_surf, "Failed to alloc source surface.");
|
||||
_g2d_set_src_surf(src_surf, tmp_buf, &blend_area, stride, dsc->color, dsc->opa);
|
||||
_g2d_fill_with_opa(u->g2d_handle, dst_buf, dst_surf, tmp_buf, src_surf);
|
||||
g2d_free(tmp_buf);
|
||||
lv_free(src_surf);
|
||||
}
|
||||
else {
|
||||
_g2d_fill(u->g2d_handle, dst_buf, dst_surf);
|
||||
}
|
||||
|
||||
lv_free(dst_surf);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void _g2d_set_src_surf(struct g2d_surface * src_surf, struct g2d_buf * buf, const lv_area_t * area,
|
||||
int32_t stride, lv_color_t color, lv_opa_t opa)
|
||||
{
|
||||
int32_t width = lv_area_get_width(area);
|
||||
int32_t height = lv_area_get_height(area);
|
||||
|
||||
src_surf->format = G2D_RGBA8888;
|
||||
|
||||
src_surf->left = 0;
|
||||
src_surf->top = 0;
|
||||
src_surf->right = width;
|
||||
src_surf->bottom = height;
|
||||
src_surf->stride = stride;
|
||||
src_surf->width = width;
|
||||
src_surf->height = height;
|
||||
|
||||
src_surf->planes[0] = buf->buf_paddr;
|
||||
src_surf->rot = G2D_ROTATION_0;
|
||||
|
||||
src_surf->clrcolor = g2d_rgba_to_u32(color);
|
||||
src_surf->global_alpha = opa;
|
||||
src_surf->blendfunc = G2D_ONE | G2D_PRE_MULTIPLIED_ALPHA;
|
||||
}
|
||||
|
||||
static void _g2d_set_dst_surf(struct g2d_surface * dst_surf, struct g2d_buf * buf, const lv_area_t * area,
|
||||
int32_t stride, lv_color_t color)
|
||||
{
|
||||
int32_t width = lv_area_get_width(area);
|
||||
int32_t height = lv_area_get_height(area);
|
||||
|
||||
dst_surf->format = G2D_RGBA8888;
|
||||
|
||||
dst_surf->left = area->x1;
|
||||
dst_surf->top = area->y1;
|
||||
dst_surf->right = area->x1 + width;
|
||||
dst_surf->bottom = area->y1 + height;
|
||||
dst_surf->stride = stride;
|
||||
dst_surf->width = width;
|
||||
dst_surf->height = height;
|
||||
|
||||
dst_surf->planes[0] = buf->buf_paddr;
|
||||
dst_surf->rot = G2D_ROTATION_0;
|
||||
|
||||
dst_surf->clrcolor = g2d_rgba_to_u32(color);
|
||||
dst_surf->global_alpha = 0xff;
|
||||
dst_surf->blendfunc = G2D_ONE_MINUS_SRC_ALPHA | G2D_PRE_MULTIPLIED_ALPHA;
|
||||
}
|
||||
|
||||
static void _g2d_fill_with_opa(void * g2d_handle, struct g2d_buf * dst_buf, struct g2d_surface * dst_surf,
|
||||
struct g2d_buf * src_buf, struct g2d_surface * src_surf)
|
||||
{
|
||||
g2d_cache_op(src_buf, G2D_CACHE_FLUSH);
|
||||
|
||||
g2d_clear(g2d_handle, src_surf);
|
||||
g2d_flush(g2d_handle);
|
||||
|
||||
g2d_enable(g2d_handle, G2D_BLEND);
|
||||
g2d_enable(g2d_handle, G2D_GLOBAL_ALPHA);
|
||||
g2d_blit(g2d_handle, src_surf, dst_surf);
|
||||
g2d_finish(g2d_handle);
|
||||
g2d_disable(g2d_handle, G2D_GLOBAL_ALPHA);
|
||||
g2d_disable(g2d_handle, G2D_BLEND);
|
||||
}
|
||||
|
||||
static void _g2d_fill(void * g2d_handle, struct g2d_buf * dst_buf, struct g2d_surface * dst_surf)
|
||||
{
|
||||
g2d_clear(g2d_handle, dst_surf);
|
||||
g2d_flush(g2d_handle);
|
||||
|
||||
g2d_finish(g2d_handle);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_G2D*/
|
||||
222
src/draw/nxp/g2d/lv_draw_g2d_img.c
Normal file
222
src/draw/nxp/g2d/lv_draw_g2d_img.c
Normal file
@@ -0,0 +1,222 @@
|
||||
/**
|
||||
* @file lv_draw_g2d_img.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_g2d.h"
|
||||
|
||||
#if LV_USE_DRAW_G2D
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "g2d.h"
|
||||
#include "../../../misc/lv_area_private.h"
|
||||
#include "lv_g2d_utils.h"
|
||||
#include "lv_g2d_buf_map.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static struct g2d_buf * _g2d_handle_src_buf(const lv_image_dsc_t * data);
|
||||
|
||||
static void _g2d_set_src_surf(struct g2d_surface * src_surf, struct g2d_buf * buf, const lv_area_t * area,
|
||||
int32_t stride, lv_color_format_t cf, lv_opa_t opa);
|
||||
|
||||
static void _g2d_set_dst_surf(struct g2d_surface * dst_surf, struct g2d_buf * buf, const lv_area_t * area,
|
||||
int32_t stride, lv_color_format_t cf, const lv_draw_image_dsc_t * dsc);
|
||||
|
||||
/* Blit simple w/ opa and alpha channel */
|
||||
static void _g2d_blit(void * g2d_handle, struct g2d_buf * dst_buf, struct g2d_surface * dst_surf,
|
||||
struct g2d_buf * src_buf, struct g2d_surface * src_surf);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_g2d_img(lv_draw_task_t * t)
|
||||
{
|
||||
lv_draw_image_dsc_t * dsc = t->draw_dsc;
|
||||
|
||||
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
|
||||
return;
|
||||
|
||||
lv_draw_g2d_unit_t * u = (lv_draw_g2d_unit_t *)t->draw_unit;
|
||||
lv_layer_t * layer = t->target_layer;
|
||||
lv_draw_buf_t * draw_buf = layer->draw_buf;
|
||||
const lv_image_dsc_t * img_dsc = dsc->src;
|
||||
lv_area_t * coords = &t->area;
|
||||
|
||||
lv_area_t rel_coords;
|
||||
lv_area_copy(&rel_coords, coords);
|
||||
lv_area_move(&rel_coords, -layer->buf_area.x1, -layer->buf_area.y1);
|
||||
|
||||
lv_area_t clip_area;
|
||||
lv_area_copy(&clip_area, &t->clip_area);
|
||||
lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
|
||||
|
||||
lv_area_t blend_area;
|
||||
bool has_transform = (dsc->rotation != 0 || dsc->scale_x != LV_SCALE_NONE || dsc->scale_y != LV_SCALE_NONE);
|
||||
if(has_transform)
|
||||
lv_area_copy(&blend_area, &rel_coords);
|
||||
else if(!lv_area_intersect(&blend_area, &rel_coords, &clip_area))
|
||||
return; /*Fully clipped, nothing to do*/
|
||||
|
||||
lv_area_t src_area;
|
||||
src_area.x1 = blend_area.x1 - (coords->x1 - layer->buf_area.x1);
|
||||
src_area.y1 = blend_area.y1 - (coords->y1 - layer->buf_area.y1);
|
||||
src_area.x2 = src_area.x1 + lv_area_get_width(&blend_area);
|
||||
src_area.y2 = src_area.y1 + lv_area_get_height(&blend_area);
|
||||
int32_t src_stride = img_dsc->header.stride / (lv_color_format_get_bpp(img_dsc->header.cf) / 8);
|
||||
lv_color_format_t src_cf = img_dsc->header.cf;
|
||||
|
||||
/* Source image */
|
||||
struct g2d_buf * src_buf = _g2d_handle_src_buf(img_dsc);
|
||||
|
||||
/* Destination buffer */
|
||||
struct g2d_buf * dst_buf = g2d_search_buf_map(draw_buf->data);
|
||||
|
||||
/* G2D takes stride in pixels. */
|
||||
int32_t dest_stride = draw_buf->header.stride / (lv_color_format_get_bpp(draw_buf->header.cf) / 8);
|
||||
lv_color_format_t dest_cf = draw_buf->header.cf;
|
||||
|
||||
struct g2d_surface * src_surf = lv_malloc(sizeof(struct g2d_surface));
|
||||
G2D_ASSERT_MSG(src_surf, "Failed to alloc source surface.");
|
||||
struct g2d_surface * dst_surf = lv_malloc(sizeof(struct g2d_surface));
|
||||
G2D_ASSERT_MSG(dst_surf, "Failed to alloc destination surface.");
|
||||
|
||||
_g2d_set_src_surf(src_surf, src_buf, &src_area, src_stride, src_cf, dsc->opa);
|
||||
_g2d_set_dst_surf(dst_surf, dst_buf, &blend_area, dest_stride, dest_cf, dsc);
|
||||
|
||||
_g2d_blit(u->g2d_handle, dst_buf, dst_surf, src_buf, src_surf);
|
||||
|
||||
lv_free(src_surf);
|
||||
lv_free(dst_surf);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static struct g2d_buf * _g2d_handle_src_buf(const lv_image_dsc_t * img_dsc)
|
||||
{
|
||||
struct g2d_buf * src_buf = g2d_search_buf_map((void *)img_dsc->data);
|
||||
|
||||
if(src_buf == NULL) {
|
||||
src_buf = g2d_alloc(img_dsc->data_size, 1);
|
||||
G2D_ASSERT_MSG(src_buf, "Failed to alloc source buffer.");
|
||||
memcpy((int *)src_buf->buf_vaddr, img_dsc->data, img_dsc->data_size);
|
||||
g2d_insert_buf_map((void *)img_dsc->data, src_buf);
|
||||
}
|
||||
|
||||
return src_buf;
|
||||
}
|
||||
|
||||
static void _g2d_set_src_surf(struct g2d_surface * src_surf, struct g2d_buf * buf, const lv_area_t * area,
|
||||
int32_t stride, lv_color_format_t cf, lv_opa_t opa)
|
||||
{
|
||||
src_surf->format = g2d_get_buf_format(cf);
|
||||
|
||||
src_surf->left = area->x1;
|
||||
src_surf->top = area->y1;
|
||||
src_surf->right = area->x2;
|
||||
src_surf->bottom = area->y2;
|
||||
src_surf->stride = stride;
|
||||
src_surf->width = area->x2 - area->x1;
|
||||
src_surf->height = area->y2 - area->y1;
|
||||
|
||||
src_surf->planes[0] = buf->buf_paddr;
|
||||
src_surf->rot = G2D_ROTATION_0;
|
||||
|
||||
src_surf->clrcolor = g2d_rgba_to_u32(lv_color_black());
|
||||
src_surf->global_alpha = opa;
|
||||
src_surf->blendfunc = G2D_ONE | G2D_PRE_MULTIPLIED_ALPHA;
|
||||
}
|
||||
|
||||
static void _g2d_set_dst_surf(struct g2d_surface * dst_surf, struct g2d_buf * buf, const lv_area_t * area,
|
||||
int32_t stride, lv_color_format_t cf, const lv_draw_image_dsc_t * dsc)
|
||||
{
|
||||
int32_t width = lv_area_get_width(area);
|
||||
int32_t height = lv_area_get_height(area);
|
||||
|
||||
lv_point_t pivot = dsc->pivot;
|
||||
/*The offsets are now relative to the transformation result with pivot ULC*/
|
||||
int32_t piv_offset_x = 0;
|
||||
int32_t piv_offset_y = 0;
|
||||
int32_t trim_x = 0;
|
||||
int32_t trim_y = 0;
|
||||
int32_t dest_w;
|
||||
int32_t dest_h;
|
||||
|
||||
float fp_scale_x = (float)dsc->scale_x / LV_SCALE_NONE;
|
||||
float fp_scale_y = (float)dsc->scale_y / LV_SCALE_NONE;
|
||||
int32_t int_scale_x = (int32_t)fp_scale_x;
|
||||
int32_t int_scale_y = (int32_t)fp_scale_y;
|
||||
|
||||
/*Any scale_factor in (k, k + 1] will result in a trim equal to k*/
|
||||
trim_x = (fp_scale_x == int_scale_x) ? int_scale_x - 1 : int_scale_x;
|
||||
trim_y = (fp_scale_y == int_scale_y) ? int_scale_y - 1 : int_scale_y;
|
||||
|
||||
dest_w = width * fp_scale_x + trim_x;
|
||||
dest_h = height * fp_scale_y + trim_y;
|
||||
|
||||
/*Final pivot offset = scale_factor * rotation_pivot_offset + scaling_pivot_offset*/
|
||||
piv_offset_x = floor(fp_scale_x * piv_offset_x) - floor((fp_scale_x - 1) * pivot.x);
|
||||
piv_offset_y = floor(fp_scale_y * piv_offset_y) - floor((fp_scale_y - 1) * pivot.y);
|
||||
|
||||
dst_surf->format = g2d_get_buf_format(cf);
|
||||
|
||||
dst_surf->left = area->x1 + piv_offset_x;
|
||||
dst_surf->top = area->y1 + piv_offset_y;
|
||||
dst_surf->right = area->x1 + piv_offset_x + dest_w - trim_x;
|
||||
dst_surf->bottom = area->y1 + piv_offset_y + dest_h - trim_y;
|
||||
dst_surf->stride = stride;
|
||||
dst_surf->width = dest_w - trim_x;
|
||||
dst_surf->height = dest_h - trim_y;
|
||||
|
||||
dst_surf->planes[0] = buf->buf_paddr;
|
||||
dst_surf->rot = G2D_ROTATION_0;
|
||||
|
||||
dst_surf->clrcolor = g2d_rgba_to_u32(lv_color_black());
|
||||
dst_surf->global_alpha = 0xff;
|
||||
dst_surf->blendfunc = G2D_ONE_MINUS_SRC_ALPHA | G2D_PRE_MULTIPLIED_ALPHA;
|
||||
}
|
||||
|
||||
static void _g2d_blit(void * g2d_handle, struct g2d_buf * dst_buf, struct g2d_surface * dst_surf,
|
||||
struct g2d_buf * src_buf, struct g2d_surface * src_surf)
|
||||
{
|
||||
g2d_cache_op(src_buf, G2D_CACHE_FLUSH);
|
||||
|
||||
g2d_enable(g2d_handle, G2D_BLEND);
|
||||
g2d_enable(g2d_handle, G2D_GLOBAL_ALPHA);
|
||||
g2d_blit(g2d_handle, src_surf, dst_surf);
|
||||
g2d_finish(g2d_handle);
|
||||
g2d_disable(g2d_handle, G2D_GLOBAL_ALPHA);
|
||||
g2d_disable(g2d_handle, G2D_BLEND);
|
||||
}
|
||||
#endif /*LV_USE_DRAW_G2D*/
|
||||
254
src/draw/nxp/g2d/lv_g2d_buf_map.c
Normal file
254
src/draw/nxp/g2d/lv_g2d_buf_map.c
Normal file
@@ -0,0 +1,254 @@
|
||||
/**
|
||||
* @file lv_g2d_buf_map.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "lv_g2d_buf_map.h"
|
||||
|
||||
#if LV_USE_DRAW_G2D
|
||||
#include <stdio.h>
|
||||
#include "lv_g2d_utils.h"
|
||||
#include "g2d.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static unsigned long _map_hash_function(void * ptr);
|
||||
|
||||
static lv_map_item_t * _map_create_item(void * key, struct g2d_buf * value);
|
||||
|
||||
static void _map_free_item(lv_map_item_t * item);
|
||||
|
||||
static void _handle_collision(unsigned long index, lv_map_item_t * item);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
static lv_buf_map_t * table;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void g2d_create_buf_map(void)
|
||||
{
|
||||
table = (lv_buf_map_t *) lv_malloc(sizeof(lv_buf_map_t));
|
||||
table->size = LV_G2D_HASH_TABLE_SIZE;
|
||||
table->count = 0;
|
||||
table->items = (lv_map_item_t **) lv_malloc_zeroed(table->size * sizeof(lv_map_item_t *));
|
||||
table->overflow_list = (lv_array_t **) lv_malloc_zeroed(table->size * sizeof(lv_array_t *));
|
||||
|
||||
for(int i = 0; i < table->size; i++) {
|
||||
table->items[i] = NULL;
|
||||
table->overflow_list[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void g2d_free_buf_map(void)
|
||||
{
|
||||
for(int i = 0; i < table->size; i++) {
|
||||
if(table->overflow_list[i]) {
|
||||
lv_array_deinit(table->overflow_list[i]);
|
||||
lv_free(table->overflow_list[i]);
|
||||
}
|
||||
|
||||
lv_map_item_t * item = table->items[i];
|
||||
if(item != NULL)
|
||||
_map_free_item(item);
|
||||
}
|
||||
|
||||
lv_free(table->items);
|
||||
lv_free(table->overflow_list);
|
||||
lv_free(table);
|
||||
}
|
||||
|
||||
void g2d_insert_buf_map(void * key, struct g2d_buf * value)
|
||||
{
|
||||
lv_map_item_t * item = _map_create_item(key, value);
|
||||
int index = _map_hash_function(key);
|
||||
lv_map_item_t * curr_item = table->items[index];
|
||||
|
||||
if(table->items[index] == NULL) {
|
||||
/* Key not found. */
|
||||
if(table->count == table->size) {
|
||||
/* Table is full. */
|
||||
_map_free_item(item);
|
||||
G2D_ASSERT_MSG(false, "Hash table is full.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(table->items[index]->key == key) {
|
||||
/* Key already exists, update value. */
|
||||
table->items[index]->value = value;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
/* Handle the collision */
|
||||
_handle_collision(index, item);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Insert item. */
|
||||
table->items[index] = item;
|
||||
table->count++;
|
||||
}
|
||||
|
||||
struct g2d_buf * g2d_search_buf_map(void * key)
|
||||
{
|
||||
int index = _map_hash_function(key);
|
||||
lv_map_item_t * item = table->items[index];
|
||||
lv_array_t * list = (lv_array_t *)table->overflow_list[index];
|
||||
|
||||
if(item == NULL)
|
||||
return NULL;
|
||||
|
||||
if(item->key == key)
|
||||
return item->value;
|
||||
|
||||
if(list == NULL)
|
||||
return NULL;
|
||||
|
||||
for(uint32_t i = 0; i < lv_array_size(list); i++) {
|
||||
item = (lv_map_item_t *)lv_array_at(list, i);
|
||||
if(item->key == key)
|
||||
return item->value;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void g2d_free_item(void * key)
|
||||
{
|
||||
/* Delete an item from the table. */
|
||||
int index = _map_hash_function(key);
|
||||
lv_map_item_t * item = table->items[index];
|
||||
lv_array_t * list = (lv_array_t *)table->overflow_list[index];
|
||||
|
||||
if(item == NULL) {
|
||||
return;
|
||||
}
|
||||
else if(list == NULL && item->key == key) {
|
||||
/* No collision chain, just remove item. */
|
||||
table->items[index] = NULL;
|
||||
_map_free_item(item);
|
||||
table->count--;
|
||||
return;
|
||||
}
|
||||
else if(list != NULL) {
|
||||
/* Collision chain exists. */
|
||||
for(uint32_t i = 0; i < lv_array_size(list); i++) {
|
||||
item = (lv_map_item_t *)lv_array_at(list, i);
|
||||
if(item->key == key) {
|
||||
lv_array_remove(list, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void g2d_print_table(void)
|
||||
{
|
||||
LV_LOG("\nHash Table\n-------------------\n");
|
||||
|
||||
for(int i = 0; i < table->size; i++) {
|
||||
if(table->items[i]) {
|
||||
LV_LOG("Index:%d, Key:%p, Value:%p\n", i, table->items[i] -> key, table->items[i]->value);
|
||||
if(table->overflow_list[i]) {
|
||||
for(int j = 0 ; j < lv_array_size(table->overflow_list[i]); j++) {
|
||||
lv_map_item_t * item = (lv_map_item_t *)lv_array_at(table->overflow_list[i], j);
|
||||
LV_LOG("Index:%d, Key:%p, Value:%p\n", i, item -> key, item->value);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LV_LOG("-------------------\n\n");
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static unsigned long _map_hash_function(void * ptr)
|
||||
{
|
||||
unsigned long i = 0;
|
||||
char str[64];
|
||||
G2D_ASSERT_MSG(ptr, "Key is null.");
|
||||
sprintf(str, "%p", ptr);
|
||||
|
||||
for(int j = 0; str[j]; j++)
|
||||
i += str[j];
|
||||
|
||||
return i % LV_G2D_HASH_TABLE_SIZE;
|
||||
}
|
||||
|
||||
static void _handle_collision(unsigned long index, lv_map_item_t * item)
|
||||
{
|
||||
if(table->overflow_list[index] == NULL) {
|
||||
/* Create the list. */
|
||||
lv_array_t * list = (lv_array_t *) lv_malloc(sizeof(lv_array_t));;
|
||||
lv_array_init(list, LV_ARRAY_DEFAULT_CAPACITY, sizeof(lv_map_item_t));
|
||||
lv_array_push_back(list, item);
|
||||
table->overflow_list[index] = list;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
lv_array_t * list = (lv_array_t *)table->overflow_list[index];
|
||||
for(int i = 0; i < lv_array_size(list); i++) {
|
||||
lv_map_item_t * it = (lv_map_item_t *)lv_array_at(list, i);
|
||||
if(it->key == item->key) {
|
||||
/* Key exists, update value. */
|
||||
it->value = item->value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Insert to the list. */
|
||||
lv_array_push_back(table->overflow_list[index], item);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static lv_map_item_t * _map_create_item(void * key, struct g2d_buf * value)
|
||||
{
|
||||
lv_map_item_t * item = (lv_map_item_t *) lv_malloc(sizeof(lv_map_item_t));
|
||||
G2D_ASSERT_MSG(item, "Failed to alloc item.");
|
||||
item->key = key;
|
||||
item->value = value;
|
||||
return item;
|
||||
}
|
||||
|
||||
static void _map_free_item(lv_map_item_t * item)
|
||||
{
|
||||
/* Also free the g2d_buf. */
|
||||
lv_free(item->key);
|
||||
g2d_free(item->value);
|
||||
item->key = NULL;
|
||||
item->value = NULL;
|
||||
lv_free(item);
|
||||
item = NULL;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_G2D*/
|
||||
81
src/draw/nxp/g2d/lv_g2d_buf_map.h
Normal file
81
src/draw/nxp/g2d/lv_g2d_buf_map.h
Normal file
@@ -0,0 +1,81 @@
|
||||
|
||||
/**
|
||||
* @file lv_g2d_buf_map.h
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef LV_G2D_BUF_MAP_H
|
||||
#define LV_G2D_BUF_MAP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_DRAW_G2D
|
||||
|
||||
#include "../../../misc/lv_array.h"
|
||||
#include <string.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/* Map item definition. */
|
||||
typedef struct lv_map_item {
|
||||
/* Virtual address buffer. */
|
||||
void * key;
|
||||
struct g2d_buf * value;
|
||||
} lv_map_item_t;
|
||||
|
||||
/*Buf map definition. */
|
||||
typedef struct lv_buf_map {
|
||||
lv_map_item_t ** items;
|
||||
lv_array_t ** overflow_list;
|
||||
|
||||
int size;
|
||||
int count;
|
||||
} lv_buf_map_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void g2d_create_buf_map(void);
|
||||
|
||||
void g2d_free_buf_map(void);
|
||||
|
||||
void g2d_insert_buf_map(void * key, struct g2d_buf * value);
|
||||
|
||||
struct g2d_buf * g2d_search_buf_map(void * key);
|
||||
|
||||
void g2d_free_item(void * key);
|
||||
|
||||
void g2d_print_table(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_DRAW_G2D*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /* LV_G2D_BUF_MAP_H */
|
||||
90
src/draw/nxp/g2d/lv_g2d_utils.c
Normal file
90
src/draw/nxp/g2d/lv_g2d_utils.c
Normal file
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* @file lv_g2d_utils.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_g2d_utils.h"
|
||||
|
||||
#if LV_USE_DRAW_G2D
|
||||
#include"g2d.h"
|
||||
#include "lv_draw_g2d.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
enum g2d_format g2d_get_buf_format(lv_color_format_t cf)
|
||||
{
|
||||
enum g2d_format color_f = G2D_RGB565;
|
||||
|
||||
switch(cf) {
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
color_f = G2D_RGB565;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
color_f = G2D_BGRA8888;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_XRGB8888:
|
||||
color_f = G2D_BGRX8888;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_RGB888:
|
||||
color_f = G2D_BGR888;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_NV12:
|
||||
color_f = G2D_NV12;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_I420:
|
||||
color_f = G2D_I420;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_NV21:
|
||||
color_f = G2D_NV21;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_YUY2:
|
||||
color_f = G2D_YUYV;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_UYVY:
|
||||
color_f = G2D_UYVY;
|
||||
break;
|
||||
default:
|
||||
G2D_ASSERT_MSG(false, "Unsupported color format.");
|
||||
break;
|
||||
}
|
||||
return color_f;
|
||||
}
|
||||
|
||||
uint32_t g2d_rgba_to_u32(lv_color_t color)
|
||||
{
|
||||
return (uint32_t)((color.red) + (color.green << 8) + (color.blue << 16) + ((uint32_t)0xff << 24));
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_DRAW_G2D*/
|
||||
67
src/draw/nxp/g2d/lv_g2d_utils.h
Normal file
67
src/draw/nxp/g2d/lv_g2d_utils.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* @file lv_g2d_utils.h
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef LV_G2D_UTILS_H
|
||||
#define LV_G2D_UTILS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_DRAW_G2D
|
||||
#include "../../sw/lv_draw_sw_private.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#if LV_USE_G2D_ASSERT
|
||||
#define G2D_ASSERT(expr) LV_ASSERT(expr)
|
||||
#else
|
||||
#define G2D_ASSERT(expr)
|
||||
#endif
|
||||
|
||||
#define G2D_ASSERT_MSG(expr, msg) \
|
||||
do { \
|
||||
if(!(expr)) { \
|
||||
LV_LOG_ERROR(msg); \
|
||||
G2D_ASSERT(false); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
enum g2d_format g2d_get_buf_format(lv_color_format_t cf);
|
||||
|
||||
uint32_t g2d_rgba_to_u32(lv_color_t color);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_DRAW_G2D*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_G2D_UTILS_H*/
|
||||
@@ -779,6 +779,51 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** Use NXP's G2D on MPU platforms. */
|
||||
#ifndef LV_USE_DRAW_G2D
|
||||
#ifdef CONFIG_LV_USE_DRAW_G2D
|
||||
#define LV_USE_DRAW_G2D CONFIG_LV_USE_DRAW_G2D
|
||||
#else
|
||||
#define LV_USE_DRAW_G2D 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if LV_USE_DRAW_G2D
|
||||
/** Maximum number of buffers that can be stored for G2D draw unit.
|
||||
* Includes the frame buffers and assets. */
|
||||
#ifndef LV_G2D_HASH_TABLE_SIZE
|
||||
#ifdef CONFIG_LV_G2D_HASH_TABLE_SIZE
|
||||
#define LV_G2D_HASH_TABLE_SIZE CONFIG_LV_G2D_HASH_TABLE_SIZE
|
||||
#else
|
||||
#define LV_G2D_HASH_TABLE_SIZE 50
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if LV_USE_OS
|
||||
/** Use additional draw thread for G2D processing.*/
|
||||
#ifndef LV_USE_G2D_DRAW_THREAD
|
||||
#ifdef LV_KCONFIG_PRESENT
|
||||
#ifdef CONFIG_LV_USE_G2D_DRAW_THREAD
|
||||
#define LV_USE_G2D_DRAW_THREAD CONFIG_LV_USE_G2D_DRAW_THREAD
|
||||
#else
|
||||
#define LV_USE_G2D_DRAW_THREAD 0
|
||||
#endif
|
||||
#else
|
||||
#define LV_USE_G2D_DRAW_THREAD 1
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** Enable G2D asserts. */
|
||||
#ifndef LV_USE_G2D_ASSERT
|
||||
#ifdef CONFIG_LV_USE_G2D_ASSERT
|
||||
#define LV_USE_G2D_ASSERT CONFIG_LV_USE_G2D_ASSERT
|
||||
#else
|
||||
#define LV_USE_G2D_ASSERT 0
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** Use Renesas Dave2D on RA platforms. */
|
||||
#ifndef LV_USE_DRAW_DAVE2D
|
||||
#ifdef CONFIG_LV_USE_DRAW_DAVE2D
|
||||
|
||||
@@ -56,6 +56,9 @@
|
||||
#include "draw/nxp/pxp/lv_draw_pxp.h"
|
||||
#endif
|
||||
#endif
|
||||
#if LV_USE_DRAW_G2D
|
||||
#include "draw/nxp/g2d/lv_draw_g2d.h"
|
||||
#endif
|
||||
#if LV_USE_DRAW_DAVE2D
|
||||
#include "draw/renesas/dave2d/lv_draw_dave2d.h"
|
||||
#endif
|
||||
@@ -237,6 +240,10 @@ void lv_init(void)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if LV_USE_DRAW_G2D
|
||||
lv_draw_g2d_init();
|
||||
#endif
|
||||
|
||||
#if LV_USE_DRAW_DAVE2D
|
||||
lv_draw_dave2d_init();
|
||||
#endif
|
||||
@@ -453,6 +460,10 @@ void lv_deinit(void)
|
||||
lv_draw_vglite_deinit();
|
||||
#endif
|
||||
|
||||
#if LV_USE_DRAW_G2D
|
||||
lv_draw_g2d_deinit();
|
||||
#endif
|
||||
|
||||
#if LV_USE_DRAW_VG_LITE
|
||||
lv_draw_vg_lite_deinit();
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user