feat(gpu): improve NXP's PXP and VGLite accelerators (#3948)
Signed-off-by: Nicușor Cîțu <nicusor.citu@nxp.com> Signed-off-by: Stefan Babatie <stefan.babatie@nxp.com> Signed-off-by: Wenbin Yuan <wenbin.yuan@nxp.com> Co-authored-by: Stefan Babatie <stefan.babatie@nxp.com> Co-authored-by: Wenbin Yuan <wenbin.yuan@nxp.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# NXP
|
# NXP
|
||||||
NXP has integrated LVGL into the MCUXpresso SDK packages for several of their general purpose and crossover
|
NXP has integrated LVGL into the MCUXpresso SDK packages for general purpose and crossover microcontrollers, allowing
|
||||||
microcontrollers, allowing easy evaluation and migration into your product design.
|
easy evaluation and migration into your product design.
|
||||||
[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)
|
[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.
|
today and get started with your next GUI application.
|
||||||
|
|
||||||
@@ -10,42 +10,38 @@ with PXP/VGLite support if the modules are present), no additional integration w
|
|||||||
|
|
||||||
## HW acceleration for NXP iMX RT platforms
|
## HW acceleration for NXP iMX RT platforms
|
||||||
Depending on the RT platform used, the acceleration can be done by NXP PXP (PiXel Pipeline) and/or the Verisilicon GPU
|
Depending on the RT platform used, the acceleration can be done by NXP PXP (PiXel Pipeline) and/or the Verisilicon GPU
|
||||||
through an API named VGLite. There is a single NXP draw context that covers both GPUs allowing to have enabled either
|
through an API named VGLite. Each accelerator has its own context that allows them to be used individually as well
|
||||||
one or even both at the same time. While enableing both 2D accelerators, the VGLite can be used to accelerate widget
|
simultaneously (in LVGL multithreading mode).
|
||||||
drawing while the PXP accelerated blit and fill operations.
|
|
||||||
|
|
||||||
Supported draw callbacks are available in "src/draw/nxp/lv_gpu_nxp.c":
|
|
||||||
```c
|
|
||||||
nxp_draw_ctx->base_draw.draw_arc = lv_draw_nxp_arc;
|
|
||||||
nxp_draw_ctx->base_draw.draw_rect = lv_draw_nxp_rect;
|
|
||||||
nxp_draw_ctx->base_draw.draw_img_decoded = lv_draw_nxp_img_decoded;
|
|
||||||
nxp_draw_ctx->blend = lv_draw_nxp_blend;
|
|
||||||
```
|
|
||||||
|
|
||||||
If enabled both GPUs, the PXP is the preffered one to be used for drawing operation. A fallback mechanism is
|
|
||||||
implemented so that if the feature is not supported by PXP (or if PXP fails), the VGLite will take over to handle the
|
|
||||||
task. At the end, the CPU will assure that every widget drawing is fully covered (if not already done by GPU).
|
|
||||||
|
|
||||||
### PXP accelerator
|
### PXP accelerator
|
||||||
Several drawing features in LVGL can be offloaded to the PXP engine. The VGLite (if supported) and CPU are available for
|
Several drawing features in LVGL can be offloaded to the PXP engine. The CPU is available for other operations while the
|
||||||
other operations while the PXP is running. An RTOS is required to block the LVGL drawing thread and switch to another
|
PXP is running. RTOS is required to block the LVGL drawing thread and switch to another task or suspend the CPU for
|
||||||
task or suspend the CPU for power savings.
|
power savings.
|
||||||
|
|
||||||
|
Supported draw callbacks are available in "src/draw/nxp/pxp/lv_draw_pxp.c":
|
||||||
|
```c
|
||||||
|
pxp_draw_ctx->base_draw.draw_img_decoded = lv_draw_pxp_img_decoded;
|
||||||
|
pxp_draw_ctx->blend = lv_draw_pxp_blend;
|
||||||
|
pxp_draw_ctx->base_draw.wait_for_finish = lv_draw_pxp_wait_for_finish;
|
||||||
|
```
|
||||||
|
|
||||||
#### Features supported:
|
#### Features supported:
|
||||||
|
All operations can be used in conjunction with optional transparency.
|
||||||
|
|
||||||
- RGB565 and ARGB8888 color formats
|
- RGB565 and ARGB8888 color formats
|
||||||
- Area fill + optional transparency
|
- Area fill with color
|
||||||
- BLIT (BLock Image Transfer) + optional transparency
|
- BLIT (BLock Image Transfer)
|
||||||
- Color keying + optional transparency
|
|
||||||
- Recoloring (color tint) + optional transparency
|
|
||||||
- Image Rotation (90, 180, 270 degree) + optional transparency
|
|
||||||
- Recoloring (color tint) + Image Rotation (90, 180, 270 degree) + optional transparency
|
|
||||||
- Screen Rotation (90, 180, 270 degree)
|
- Screen Rotation (90, 180, 270 degree)
|
||||||
|
- Color keying
|
||||||
|
- Recoloring (color tint)
|
||||||
|
- Image Rotation (90, 180, 270 degree)
|
||||||
- RTOS integration layer
|
- RTOS integration layer
|
||||||
- Default FreeRTOS and bare metal code provided
|
- Default FreeRTOS and bare metal code provided
|
||||||
|
|
||||||
- Combination of recolor and/or rotation + color key/alpha blend/transparency is supported but PXP needs two steps.
|
- Combination of recolor and/or rotation + color key/alpha blend/transparency is supported.
|
||||||
First step is to recolor/rotate the image to a temporarly buffer (please check LV_MEM_SIZE value for allocation limit)
|
That is achieved by PXP in two steps:
|
||||||
and another step is required to handle color keying, alpha chanel or to apply transparency.
|
- First step is to recolor/rotate the image to a temporary buffer (statically allocated)
|
||||||
|
- Second step is required to handle color keying, alpha channel or to apply transparency
|
||||||
|
|
||||||
#### Known limitations:
|
#### Known limitations:
|
||||||
- Rotation is not supported for images unaligned to blocks of 16x16 pixels.
|
- Rotation is not supported for images unaligned to blocks of 16x16 pixels.
|
||||||
@@ -78,51 +74,69 @@ and the final output image can look shifted.
|
|||||||
|
|
||||||
#### Project setup:
|
#### Project setup:
|
||||||
- Add PXP related files to project:
|
- Add PXP related files to project:
|
||||||
- src/draw/nxp/pxp/lv_gpu_nxp_pxp.c, src/draw/nxp/pxp/lv_gpu_nxp_pxp.h: init, uninit, run/wait PXP device, log/trace
|
- src/draw/nxp/pxp/lv_draw_pxp.c[.h]: draw context callbacks
|
||||||
- src/draw/nxp/pxp/lv_draw_pxp_blend.c, src/draw/nxp/pxp/lv_draw_pxp_blend.h: fill and blit (w/o transformation)
|
- src/draw/nxp/pxp/lv_draw_pxp_blend.c[.h]: fill and blit (with optional transformation)
|
||||||
- src/draw/nxp/pxp/lv_gpu_nxp_osa.c, src/draw/nxp/pxp/lv_gpu_osa.h: default implementation of OS-specific functions
|
- src/draw/nxp/pxp/lv_gpu_nxp_pxp.c[.h]: init, uninit, run/wait PXP device
|
||||||
(bare metal and FreeRTOS only)
|
- src/draw/nxp/pxp/lv_gpu_nxp_pxp_osa.c[.h]: OS abstraction (FreeRTOS or bare metal)
|
||||||
- optional, required only if `LV_USE_GPU_NXP_PXP_AUTO_INIT` is set to 1
|
- optional, required only if `LV_USE_GPU_NXP_PXP_AUTO_INIT` is set to 1
|
||||||
- PXP related code depends on two drivers provided by MCU SDK. These drivers need to be added to project:
|
- PXP related code depends on two drivers provided by MCU SDK. These drivers need to be added to project:
|
||||||
- fsl_pxp.c, fsl_pxp.h: PXP driver
|
- fsl_pxp.c[.h]: PXP driver
|
||||||
- fsl_cache.c, fsl_cache.h: CPU cache handling functions
|
- fsl_cache.c[.h]: CPU cache handling functions
|
||||||
|
|
||||||
#### Logging:
|
#### Logging:
|
||||||
- By default, LV_GPU_NXP_PXP_LOG_ERRORS is enabled so that any PXP error will be seen on LVGL output
|
- By default, `LV_GPU_NXP_PXP_LOG_ERRORS` is enabled so that any PXP error will be seen on SDK debug console
|
||||||
- For tracing logs about the PXP limitations or size thresholds, the user can enable LV_GPU_NXP_PXP_LOG_TRACES
|
- By default, `LV_GPU_NXP_PXP_LOG_TRACES` is disabled. Enable it for tracing logs (like PXP limitations)
|
||||||
|
|
||||||
#### Advanced configuration:
|
#### Advanced configuration:
|
||||||
- Implementation depends on multiple OS-specific functions. The struct `lv_nxp_pxp_cfg_t` with callback pointers is
|
- Implementation depends on multiple OS-specific functions. The struct `lv_nxp_pxp_cfg_t` with callback pointers is
|
||||||
used as a parameter for the `lv_gpu_nxp_pxp_init()` function. Default implementation for FreeRTOS and baremetal is
|
used as a parameter for the `lv_gpu_nxp_pxp_init()` function. Default implementation for FreeRTOS and bare metal is
|
||||||
provided in lv_gpu_nxp_osa.c
|
provided in lv_gpu_nxp_pxp_osa.c
|
||||||
- `pxp_interrupt_init()`: Initialize PXP interrupt (HW setup, OS setup)
|
- `pxp_interrupt_init()`: Initialize PXP interrupt (HW setup, OS setup)
|
||||||
- `pxp_interrupt_deinit()`: Deinitialize PXP interrupt (HW setup, OS setup)
|
- `pxp_interrupt_deinit()`: Deinitialize PXP interrupt (HW setup, OS setup)
|
||||||
- `pxp_run()`: Start PXP job. Use OS-specific mechanism to block drawing thread. PXP must finish drawing before
|
- `pxp_run()`: Start PXP job. Use OS-specific mechanism to block drawing thread. PXP must finish drawing before
|
||||||
leaving this function.
|
leaving this function.
|
||||||
- There are configurable area thresholds which are used to decide whether the area will be processed by CPU or by PXP.
|
- Area threshold (size limit) is configurable and used to decide whether the area will be processed by PXP or not.
|
||||||
Areas smaller than a defined value will be processed by CPU and those bigger than the threshold will be processed by
|
Areas smaller than the defined value will be processed by CPU and those bigger than the threshold will be processed by
|
||||||
PXP. These thresholds may be defined as preprocessor variables. Default values are defined in lv_draw_pxp_blend.h
|
PXP. The threshold is defined as a macro in lv_draw_pxp.c
|
||||||
- `LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT`: size threshold for image BLIT, BLIT with color keying, BLIT with recolor and
|
- `LV_GPU_NXP_PXP_SIZE_LIMIT`: size threshold for fill/blit (with optional transformation)
|
||||||
BLIT with rotation (OPA >= LV_OPA_MAX)
|
|
||||||
- `LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT`: size threshold for image BLIT, BLIT with color keying, BLIT with recolor
|
|
||||||
and BLIT with rotation and transparency (OPA < LV_OPA_MAX)
|
|
||||||
- `LV_GPU_NXP_PXP_FILL_SIZE_LIMIT`: size threshold for fill operation (OPA >= LV_OPA_MAX)
|
|
||||||
- `LV_GPU_NXP_PXP_FILL_OPA_SIZE_LIMIT`: size threshold for fill operation with transparency (OPA < LV_OPA_MAX)
|
|
||||||
|
|
||||||
### VGLite accelerator
|
### VGLite accelerator
|
||||||
Extra drawing features in LVGL can be handled by the VGLite engine. The PXP (if supported) and CPU are available for
|
Extra drawing features in LVGL can be handled by the VGLite engine. The CPU is available for other operations while the
|
||||||
other operations while the VGLite is running. An RTOS is required to block the LVGL drawing thread and switch to another
|
VGLite is running. An RTOS is required to block the LVGL drawing thread and switch to another task or suspend the CPU
|
||||||
task or suspend the CPU for power savings.
|
for power savings.
|
||||||
|
|
||||||
|
Supported draw callbacks are available in "src/draw/nxp/vglite/lv_draw_vglite.c":
|
||||||
|
```c
|
||||||
|
vglite_draw_ctx->base_draw.init_buf = lv_draw_vglite_init_buf;
|
||||||
|
vglite_draw_ctx->base_draw.draw_line = lv_draw_vglite_line;
|
||||||
|
vglite_draw_ctx->base_draw.draw_arc = lv_draw_vglite_arc;
|
||||||
|
vglite_draw_ctx->base_draw.draw_rect = lv_draw_vglite_rect;
|
||||||
|
vglite_draw_ctx->base_draw.draw_img_decoded = lv_draw_vglite_img_decoded;
|
||||||
|
vglite_draw_ctx->blend = lv_draw_vglite_blend;
|
||||||
|
vglite_draw_ctx->base_draw.wait_for_finish = lv_draw_vglite_wait_for_finish;
|
||||||
|
```
|
||||||
|
|
||||||
#### Features supported:
|
#### Features supported:
|
||||||
|
All operations can be used in conjunction with optional transparency.
|
||||||
|
|
||||||
- RGB565 and ARGB8888 color formats
|
- RGB565 and ARGB8888 color formats
|
||||||
- Area fill + optional transparency
|
- Area fill with color
|
||||||
- BLIT (BLock Image Transfer) + optional transparency
|
- BLIT (BLock Image Transfer)
|
||||||
- Image Rotation (any degree with decimal) + optional transparency
|
- Image Rotation (any degree with decimal)
|
||||||
- Image Scale + optional transparency
|
- Image Scale
|
||||||
- Draw background rectangle with radius or gradient
|
- Draw rectangle background with optional radius or gradient
|
||||||
- Draw arc
|
- Blit rectangle background image
|
||||||
- RTOS integration layer
|
- Draw rectangle border/outline with optional rounded corners
|
||||||
|
- Draw arc with optional rounded ending
|
||||||
|
- Draw line or dashed line with optional rounded ending
|
||||||
|
|
||||||
|
#### Known limitations:
|
||||||
|
- Source image alignment:
|
||||||
|
The byte alignment requirement for a pixel depends on the specific pixel format. Both buffer address and buffer stride
|
||||||
|
must be aligned. As general rule, the alignment is set to 16 pixels. This makes the buffer address alignment to be
|
||||||
|
32 bytes for RGB565 and 64 bytes for ARGB8888.
|
||||||
|
- For pixel engine (PE) destination, the alignment should be 64 bytes for all tiled (4x4) buffer layouts.
|
||||||
|
The pixel engine has no additional alignment requirement for linear buffer layouts (`VG_LITE_LINEAR`).
|
||||||
|
|
||||||
#### Basic configuration:
|
#### Basic configuration:
|
||||||
- Select NXP VGLite engine in lv_conf.h: Set `LV_USE_GPU_NXP_VG_LITE` to 1
|
- Select NXP VGLite engine in lv_conf.h: Set `LV_USE_GPU_NXP_VG_LITE` to 1
|
||||||
@@ -130,8 +144,8 @@ task or suspend the CPU for power savings.
|
|||||||
|
|
||||||
#### Basic initialization:
|
#### Basic initialization:
|
||||||
- Initialize VGLite before calling `lv_init()` by specifying the width/height of tessellation window. Value should be
|
- Initialize VGLite before calling `lv_init()` by specifying the width/height of tessellation window. Value should be
|
||||||
a multiple of 16; minimum value is 16 pixels, maximum cannot be greater than frame width. If less than or equal to 0,
|
a multiple of 16; minimum value is 16 pixels, maximum cannot be greater than the frame width. If less than or equal
|
||||||
then no tessellation buffer is created, in which case the function is used for a blit init.
|
to 0, then no tessellation buffer is created, in which case VGLite is initialized only for blitting.
|
||||||
```c
|
```c
|
||||||
#if LV_USE_GPU_NXP_VG_LITE
|
#if LV_USE_GPU_NXP_VG_LITE
|
||||||
#include "vg_lite.h"
|
#include "vg_lite.h"
|
||||||
@@ -144,25 +158,21 @@ task or suspend the CPU for power savings.
|
|||||||
|
|
||||||
#### Project setup:
|
#### Project setup:
|
||||||
- Add VGLite related files to project:
|
- Add VGLite related files to project:
|
||||||
- src/draw/nxp/vglite/lv_gpu_nxp_vglite.c, src/draw/nxp/vglite/lv_gpu_nxp_vglite.h: buffer init, log/trace
|
- src/draw/nxp/vglite/lv_draw_vglite.c[.h]: draw context callbacks
|
||||||
- src/draw/nxp/vglite/lv_draw_vglite_blend.c, src/draw/nxp/vglite/lv_draw_vglite_blend.h: fill and blit
|
- src/draw/nxp/vglite/lv_draw_vglite_blend.c[.h]: fill and blit (with optional transformation)
|
||||||
(w/o transformation)
|
- src/draw/nxp/vglite/lv_draw_vglite_rect.c[.h]: draw rectangle
|
||||||
- src/draw/nxp/vglite/lv_draw_vglite_rect.c, src/draw/nxp/vglite/lv_draw_vglite_rect.h: rectangle draw
|
- src/draw/nxp/vglite/lv_draw_vglite_arc.c[.h]: draw arc
|
||||||
- src/draw/nxp/vglite/lv_draw_vglite_arc.c, src/draw/nxp/vglite/lv_draw_vglite_arc.h: arc draw
|
- src/draw/nxp/vglite/lv_draw_vglite_line.c[.h]: draw line
|
||||||
|
- src/draw/nxp/vglite/lv_vglite_buf.c[.h]: init/get vglite buffer
|
||||||
|
- src/draw/nxp/vglite/lv_vglite_utils.c[.h]: function helpers
|
||||||
|
|
||||||
#### Logging:
|
#### Logging:
|
||||||
- By default, LV_GPU_NXP_VG_LITE_LOG_ERRORS is enabled so that any VGLite error will be seen on LVGL output
|
- By default, `LV_GPU_NXP_VG_LITE_LOG_ERRORS` is enabled so that any VGLite error will be seen on SDK debug console
|
||||||
- For tracing logs about the VGLite limitations, size thresholds or stride alignment, the user can enable
|
- By default, `LV_GPU_NXP_VG_LITE_LOG_TRACES` is disabled. Enable it for tracing logs (like blit split workaround or
|
||||||
LV_GPU_NXP_VG_LITE_LOG_TRACES
|
VGLite fallback to CPU due to any error on the driver)
|
||||||
|
|
||||||
#### Advanced configuration:
|
#### Advanced configuration:
|
||||||
- There are configurable area thresholds which are used to decide whether the area will be processed by CPU or by
|
- Area threshold (size limit) is configurable and used to decide whether the area will be processed by VGLite or not.
|
||||||
VGLite. Areas smaller than a defined value will be processed by CPU and those bigger than the threshold will be
|
Areas smaller than the defined value will be processed by CPU and those bigger than the threshold will be processed by
|
||||||
processed by VGLite. These thresholds may be defined as preprocessor variables. Default values are defined in
|
VGLite. The threshold is defined as a macro in lv_draw_vglite.c
|
||||||
lv_draw_vglite_blend.h
|
- `LV_GPU_NXP_VG_LITE_SIZE_LIMIT`: size threshold for fill/blit (with optional transformation)
|
||||||
- `LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT`: size threshold for image BLIT, BLIT with scale and BLIT with rotation
|
|
||||||
(OPA >= LV_OPA_MAX)
|
|
||||||
- `LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT`: size threshold for image BLIT, BLIT with scale and BLIT with rotation
|
|
||||||
and transparency (OPA < LV_OPA_MAX)
|
|
||||||
- `LV_GPU_NXP_VG_LITE_FILL_SIZE_LIMIT`: size threshold for fill operation (OPA >= LV_OPA_MAX)
|
|
||||||
- `LV_GPU_NXP_VG_LITE_FILL_OPA_SIZE_LIMIT`: size threshold for fill operation with transparency (OPA < LV_OPA_MAX)
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ void lv_example_animimg_1(void)
|
|||||||
{
|
{
|
||||||
lv_obj_t * animimg0 = lv_animimg_create(lv_scr_act());
|
lv_obj_t * animimg0 = lv_animimg_create(lv_scr_act());
|
||||||
lv_obj_center(animimg0);
|
lv_obj_center(animimg0);
|
||||||
lv_animimg_set_src(animimg0, (lv_img_dsc_t **) anim_imgs, 3);
|
lv_animimg_set_src(animimg0, (const void **) anim_imgs, 3);
|
||||||
lv_animimg_set_duration(animimg0, 1000);
|
lv_animimg_set_duration(animimg0, 1000);
|
||||||
lv_animimg_set_repeat_count(animimg0, LV_ANIM_REPEAT_INFINITE);
|
lv_animimg_set_repeat_count(animimg0, LV_ANIM_REPEAT_INFINITE);
|
||||||
lv_animimg_start(animimg0);
|
lv_animimg_start(animimg0);
|
||||||
|
|||||||
@@ -624,6 +624,9 @@ static void refr_area_part(lv_draw_ctx_t * draw_ctx)
|
|||||||
{
|
{
|
||||||
lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp_refr);
|
lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp_refr);
|
||||||
|
|
||||||
|
if(draw_ctx->init_buf)
|
||||||
|
draw_ctx->init_buf(draw_ctx);
|
||||||
|
|
||||||
/* Below the `area_p` area will be redrawn into the draw buffer.
|
/* Below the `area_p` area will be redrawn into the draw buffer.
|
||||||
* In single buffered mode wait here until the buffer is freed.*/
|
* In single buffered mode wait here until the buffer is freed.*/
|
||||||
if(draw_buf->buf1 && !draw_buf->buf2) {
|
if(draw_buf->buf1 && !draw_buf->buf2) {
|
||||||
|
|||||||
@@ -84,6 +84,8 @@ typedef struct _lv_draw_ctx_t {
|
|||||||
*/
|
*/
|
||||||
lv_color_format_t color_format;
|
lv_color_format_t color_format;
|
||||||
|
|
||||||
|
void (*init_buf)(struct _lv_draw_ctx_t * draw_ctx);
|
||||||
|
|
||||||
void (*draw_rect)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
|
void (*draw_rect)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
|
||||||
|
|
||||||
void (*draw_arc)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center,
|
void (*draw_arc)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center,
|
||||||
|
|||||||
@@ -1,415 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file lv_gpu_nxp.c
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright 2022 NXP
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights to
|
|
||||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
||||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
|
||||||
* subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice (including the next paragraph)
|
|
||||||
* shall be included in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
||||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
||||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
|
||||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
|
||||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*********************
|
|
||||||
* INCLUDES
|
|
||||||
*********************/
|
|
||||||
|
|
||||||
#include "lv_gpu_nxp.h"
|
|
||||||
|
|
||||||
#if LV_USE_GPU_NXP_PXP || LV_USE_GPU_NXP_VG_LITE
|
|
||||||
|
|
||||||
/*
|
|
||||||
* allow to use both PXP and VGLITE
|
|
||||||
|
|
||||||
* both 2D accelerators can be used at the same time:
|
|
||||||
* thus VGLITE can be used to accelerate widget drawing
|
|
||||||
* while PXP accelerates Blit & Fill operations.
|
|
||||||
*/
|
|
||||||
#if LV_USE_GPU_NXP_PXP
|
|
||||||
#include "pxp/lv_draw_pxp_blend.h"
|
|
||||||
#endif
|
|
||||||
#if LV_USE_GPU_NXP_VG_LITE
|
|
||||||
#include "vglite/lv_draw_vglite_blend.h"
|
|
||||||
#include "vglite/lv_draw_vglite_rect.h"
|
|
||||||
#include "vglite/lv_draw_vglite_arc.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LV_COLOR_DEPTH != 32
|
|
||||||
#include "../../core/lv_refr.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*********************
|
|
||||||
* DEFINES
|
|
||||||
*********************/
|
|
||||||
|
|
||||||
/**********************
|
|
||||||
* TYPEDEFS
|
|
||||||
**********************/
|
|
||||||
|
|
||||||
/**********************
|
|
||||||
* STATIC PROTOTYPES
|
|
||||||
**********************/
|
|
||||||
|
|
||||||
static void lv_draw_nxp_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc,
|
|
||||||
const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t cf);
|
|
||||||
|
|
||||||
static void lv_draw_nxp_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc);
|
|
||||||
|
|
||||||
static void lv_draw_nxp_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
|
|
||||||
|
|
||||||
static lv_res_t draw_nxp_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
|
|
||||||
|
|
||||||
static void lv_draw_nxp_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center,
|
|
||||||
uint16_t radius, uint16_t start_angle, uint16_t end_angle);
|
|
||||||
|
|
||||||
/**********************
|
|
||||||
* STATIC VARIABLES
|
|
||||||
**********************/
|
|
||||||
|
|
||||||
/**********************
|
|
||||||
* MACROS
|
|
||||||
**********************/
|
|
||||||
|
|
||||||
/**********************
|
|
||||||
* GLOBAL FUNCTIONS
|
|
||||||
**********************/
|
|
||||||
|
|
||||||
void lv_draw_nxp_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
|
|
||||||
{
|
|
||||||
lv_draw_sw_init_ctx(drv, draw_ctx);
|
|
||||||
|
|
||||||
lv_draw_nxp_ctx_t * nxp_draw_ctx = (lv_draw_sw_ctx_t *)draw_ctx;
|
|
||||||
|
|
||||||
nxp_draw_ctx->base_draw.draw_arc = lv_draw_nxp_arc;
|
|
||||||
nxp_draw_ctx->base_draw.draw_rect = lv_draw_nxp_rect;
|
|
||||||
nxp_draw_ctx->base_draw.draw_img_decoded = lv_draw_nxp_img_decoded;
|
|
||||||
nxp_draw_ctx->blend = lv_draw_nxp_blend;
|
|
||||||
//nxp_draw_ctx->base_draw.wait_for_finish = lv_draw_nxp_wait_cb;
|
|
||||||
}
|
|
||||||
|
|
||||||
void lv_draw_nxp_ctx_deinit(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
|
|
||||||
{
|
|
||||||
lv_draw_sw_deinit_ctx(drv, draw_ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**********************
|
|
||||||
* STATIC FUNCTIONS
|
|
||||||
**********************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* During rendering, LVGL might initializes new draw_ctxs and start drawing into
|
|
||||||
* a separate buffer (called layer). If the content to be rendered has "holes",
|
|
||||||
* e.g. rounded corner, LVGL temporarily sets the disp_drv.screen_transp flag.
|
|
||||||
* It means the renderers should draw into an ARGB buffer.
|
|
||||||
* With 32 bit color depth it's not a big problem but with 16 bit color depth
|
|
||||||
* the target pixel format is ARGB8565 which is not supported by the GPU.
|
|
||||||
* In this case, the NXP callbacks should fallback to SW rendering.
|
|
||||||
*/
|
|
||||||
static inline bool need_argb8565_support(lv_draw_ctx_t * draw_ctx)
|
|
||||||
{
|
|
||||||
#if LV_COLOR_DEPTH != 32
|
|
||||||
if(draw_ctx->render_with_alpha) return true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void lv_draw_nxp_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc)
|
|
||||||
{
|
|
||||||
lv_area_t blend_area;
|
|
||||||
|
|
||||||
/*Let's get the blend area which is the intersection of the area to fill and the clip area.*/
|
|
||||||
if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area))
|
|
||||||
return; /*Fully clipped, nothing to do*/
|
|
||||||
|
|
||||||
/*Make the blend area relative to the buffer*/
|
|
||||||
lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
|
|
||||||
|
|
||||||
bool done = false;
|
|
||||||
|
|
||||||
/*Fill/Blend only non masked, normal blended*/
|
|
||||||
if(dsc->mask_buf == NULL && dsc->blend_mode == LV_BLEND_MODE_NORMAL && !need_argb8565_support()) {
|
|
||||||
lv_color_t * dest_buf = draw_ctx->buf;
|
|
||||||
lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area);
|
|
||||||
#if LV_USE_GPU_NXP_VG_LITE
|
|
||||||
lv_coord_t dest_width = lv_area_get_width(draw_ctx->buf_area);
|
|
||||||
lv_coord_t dest_height = lv_area_get_height(draw_ctx->buf_area);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const lv_color_t * src_buf = dsc->src_buf;
|
|
||||||
|
|
||||||
if(src_buf == NULL) {
|
|
||||||
#if LV_USE_GPU_NXP_PXP
|
|
||||||
done = (lv_gpu_nxp_pxp_fill(dest_buf, dest_stride, &blend_area,
|
|
||||||
dsc->color, dsc->opa) == LV_RES_OK);
|
|
||||||
if(!done)
|
|
||||||
PXP_LOG_TRACE("PXP fill failed. Fallback.");
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#if LV_USE_GPU_NXP_VG_LITE
|
|
||||||
if(!done) {
|
|
||||||
done = (lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &blend_area,
|
|
||||||
dsc->color, dsc->opa) == LV_RES_OK);
|
|
||||||
if(!done)
|
|
||||||
VG_LITE_LOG_TRACE("VG-Lite fill failed. Fallback.");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
#if LV_USE_GPU_NXP_PXP
|
|
||||||
done = (lv_gpu_nxp_pxp_blit(dest_buf, &blend_area, dest_stride, src_buf, dsc->blend_area,
|
|
||||||
dsc->opa, LV_DISP_ROT_NONE) == LV_RES_OK);
|
|
||||||
if(!done)
|
|
||||||
PXP_LOG_TRACE("PXP blit failed. Fallback.");
|
|
||||||
#endif
|
|
||||||
#if LV_USE_GPU_NXP_VG_LITE
|
|
||||||
if(!done) {
|
|
||||||
lv_gpu_nxp_vglite_blit_info_t blit;
|
|
||||||
lv_coord_t src_stride = lv_area_get_width(dsc->blend_area);
|
|
||||||
|
|
||||||
blit.src = src_buf;
|
|
||||||
blit.src_width = lv_area_get_width(dsc->blend_area);
|
|
||||||
blit.src_height = lv_area_get_height(dsc->blend_area);
|
|
||||||
blit.src_stride = src_stride * (int32_t)sizeof(lv_color_t);
|
|
||||||
blit.src_area.x1 = (blend_area.x1 - (dsc->blend_area->x1 - draw_ctx->buf_area->x1));
|
|
||||||
blit.src_area.y1 = (blend_area.y1 - (dsc->blend_area->y1 - draw_ctx->buf_area->y1));
|
|
||||||
blit.src_area.x2 = blit.src_area.x1 + blit.src_width - 1;
|
|
||||||
blit.src_area.y2 = blit.src_area.y1 + blit.src_height - 1;
|
|
||||||
|
|
||||||
blit.dst = dest_buf;
|
|
||||||
blit.dst_width = dest_width;
|
|
||||||
blit.dst_height = dest_height;
|
|
||||||
blit.dst_stride = dest_stride * (int32_t)sizeof(lv_color_t);
|
|
||||||
blit.dst_area.x1 = blend_area.x1;
|
|
||||||
blit.dst_area.y1 = blend_area.y1;
|
|
||||||
blit.dst_area.x2 = blend_area.x2;
|
|
||||||
blit.dst_area.y2 = blend_area.y2;
|
|
||||||
|
|
||||||
blit.opa = dsc->opa;
|
|
||||||
blit.zoom = LV_IMG_ZOOM_NONE;
|
|
||||||
blit.angle = 0;
|
|
||||||
|
|
||||||
done = (lv_gpu_nxp_vglite_blit(&blit) == LV_RES_OK);
|
|
||||||
|
|
||||||
if(!done)
|
|
||||||
VG_LITE_LOG_TRACE("VG-Lite blit failed. Fallback.");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!done)
|
|
||||||
lv_draw_sw_blend_basic(draw_ctx, dsc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void lv_draw_nxp_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc,
|
|
||||||
const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t cf)
|
|
||||||
{
|
|
||||||
/*Use the clip area as draw area*/
|
|
||||||
lv_area_t draw_area;
|
|
||||||
lv_area_copy(&draw_area, draw_ctx->clip_area);
|
|
||||||
bool mask_any = lv_draw_mask_is_any(&draw_area);
|
|
||||||
#if LV_USE_GPU_NXP_VG_LITE
|
|
||||||
bool recolor = (dsc->recolor_opa != LV_OPA_TRANSP);
|
|
||||||
#endif
|
|
||||||
#if LV_USE_GPU_NXP_PXP
|
|
||||||
bool scale = (dsc->zoom != LV_IMG_ZOOM_NONE);
|
|
||||||
#endif
|
|
||||||
bool done = false;
|
|
||||||
|
|
||||||
lv_area_t blend_area;
|
|
||||||
/*Let's get the blend area which is the intersection of the area to fill and the clip area.*/
|
|
||||||
if(!_lv_area_intersect(&blend_area, coords, draw_ctx->clip_area))
|
|
||||||
return; /*Fully clipped, nothing to do*/
|
|
||||||
|
|
||||||
/*Make the blend area relative to the buffer*/
|
|
||||||
lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
|
|
||||||
|
|
||||||
const lv_color_t * src_buf = (const lv_color_t *)map_p;
|
|
||||||
if(!src_buf) {
|
|
||||||
lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lv_color_t * dest_buf = draw_ctx->buf;
|
|
||||||
lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area);
|
|
||||||
|
|
||||||
#if LV_USE_GPU_NXP_PXP
|
|
||||||
if(!mask_any && !scale && !need_argb8565_support()
|
|
||||||
#if LV_COLOR_DEPTH!=32
|
|
||||||
&& !lv_img_cf_has_alpha(cf)
|
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
done = (lv_gpu_nxp_pxp_blit_transform(dest_buf, &blend_area, dest_stride, src_buf, coords,
|
|
||||||
dsc, cf) == LV_RES_OK);
|
|
||||||
if(!done)
|
|
||||||
PXP_LOG_TRACE("PXP blit transform failed. Fallback.");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LV_USE_GPU_NXP_VG_LITE
|
|
||||||
if(!done && !mask_any && !need_argb8565_support() &&
|
|
||||||
!lv_img_cf_is_chroma_keyed(cf) && !recolor
|
|
||||||
#if LV_COLOR_DEPTH!=32
|
|
||||||
&& !lv_img_cf_has_alpha(cf)
|
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
lv_gpu_nxp_vglite_blit_info_t blit;
|
|
||||||
lv_coord_t src_stride = lv_area_get_width(coords);
|
|
||||||
|
|
||||||
blit.src = src_buf;
|
|
||||||
blit.src_width = lv_area_get_width(coords);
|
|
||||||
blit.src_height = lv_area_get_height(coords);
|
|
||||||
blit.src_stride = src_stride * (int32_t)sizeof(lv_color_t);
|
|
||||||
blit.src_area.x1 = (blend_area.x1 - (coords->x1 - draw_ctx->buf_area->x1));
|
|
||||||
blit.src_area.y1 = (blend_area.y1 - (coords->y1 - draw_ctx->buf_area->y1));
|
|
||||||
blit.src_area.x2 = blit.src_area.x1 + blit.src_width - 1;
|
|
||||||
blit.src_area.y2 = blit.src_area.y1 + blit.src_height - 1;
|
|
||||||
|
|
||||||
blit.dst = dest_buf;
|
|
||||||
blit.dst_width = lv_area_get_width(draw_ctx->buf_area);
|
|
||||||
blit.dst_height = lv_area_get_height(draw_ctx->buf_area);
|
|
||||||
blit.dst_stride = dest_stride * (int32_t)sizeof(lv_color_t);
|
|
||||||
blit.dst_area.x1 = blend_area.x1;
|
|
||||||
blit.dst_area.y1 = blend_area.y1;
|
|
||||||
blit.dst_area.x2 = blend_area.x2;
|
|
||||||
blit.dst_area.y2 = blend_area.y2;
|
|
||||||
|
|
||||||
blit.opa = dsc->opa;
|
|
||||||
blit.angle = dsc->angle;
|
|
||||||
blit.pivot = dsc->pivot;
|
|
||||||
blit.zoom = dsc->zoom;
|
|
||||||
|
|
||||||
done = (lv_gpu_nxp_vglite_blit_transform(&blit) == LV_RES_OK);
|
|
||||||
|
|
||||||
if(!done)
|
|
||||||
VG_LITE_LOG_TRACE("VG-Lite blit transform failed. Fallback.");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(!done)
|
|
||||||
lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void lv_draw_nxp_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords)
|
|
||||||
{
|
|
||||||
bool done = false;
|
|
||||||
lv_draw_rect_dsc_t nxp_dsc;
|
|
||||||
|
|
||||||
lv_memcpy(&nxp_dsc, dsc, sizeof(nxp_dsc));
|
|
||||||
#if LV_USE_DRAW_MASKS
|
|
||||||
/* Draw only the shadow */
|
|
||||||
nxp_dsc.bg_opa = 0;
|
|
||||||
nxp_dsc.bg_img_opa = 0;
|
|
||||||
nxp_dsc.border_opa = 0;
|
|
||||||
nxp_dsc.outline_opa = 0;
|
|
||||||
|
|
||||||
lv_draw_sw_rect(draw_ctx, &nxp_dsc, coords);
|
|
||||||
|
|
||||||
/* Draw the background */
|
|
||||||
nxp_dsc.shadow_opa = 0;
|
|
||||||
nxp_dsc.bg_opa = dsc->bg_opa;
|
|
||||||
done = (draw_nxp_bg(draw_ctx, &nxp_dsc, coords) == LV_RES_OK);
|
|
||||||
#endif /*LV_USE_DRAW_MASKS*/
|
|
||||||
|
|
||||||
/* Draw the remaining parts */
|
|
||||||
nxp_dsc.shadow_opa = 0;
|
|
||||||
if(done)
|
|
||||||
nxp_dsc.bg_opa = 0;
|
|
||||||
nxp_dsc.bg_img_opa = dsc->bg_img_opa;
|
|
||||||
nxp_dsc.border_opa = dsc->border_opa;
|
|
||||||
nxp_dsc.outline_opa = dsc->outline_opa;
|
|
||||||
|
|
||||||
lv_draw_sw_rect(draw_ctx, &nxp_dsc, coords);
|
|
||||||
}
|
|
||||||
|
|
||||||
static lv_res_t draw_nxp_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords)
|
|
||||||
{
|
|
||||||
if(dsc->bg_opa <= LV_OPA_MIN)
|
|
||||||
return LV_RES_INV;
|
|
||||||
|
|
||||||
lv_area_t bg_coords;
|
|
||||||
lv_area_copy(&bg_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) {
|
|
||||||
bg_coords.x1 += (dsc->border_side & LV_BORDER_SIDE_LEFT) ? 1 : 0;
|
|
||||||
bg_coords.y1 += (dsc->border_side & LV_BORDER_SIDE_TOP) ? 1 : 0;
|
|
||||||
bg_coords.x2 -= (dsc->border_side & LV_BORDER_SIDE_RIGHT) ? 1 : 0;
|
|
||||||
bg_coords.y2 -= (dsc->border_side & LV_BORDER_SIDE_BOTTOM) ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
lv_area_t clipped_coords;
|
|
||||||
if(!_lv_area_intersect(&clipped_coords, &bg_coords, draw_ctx->clip_area))
|
|
||||||
return LV_RES_INV;
|
|
||||||
|
|
||||||
lv_grad_dir_t grad_dir = dsc->bg_grad.dir;
|
|
||||||
lv_color_t bg_color = grad_dir == LV_GRAD_DIR_NONE ? dsc->bg_color : dsc->bg_grad.stops[0].color;
|
|
||||||
if(bg_color.full == dsc->bg_grad.stops[1].color.full) grad_dir = LV_GRAD_DIR_NONE;
|
|
||||||
|
|
||||||
bool mask_any = lv_draw_mask_is_any(&bg_coords);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Most simple case: just a plain rectangle (no mask, no radius, no gradient)
|
|
||||||
* shall fallback to lv_draw_sw_blend().
|
|
||||||
*
|
|
||||||
* Complex case: gradient or radius but no mask.
|
|
||||||
*/
|
|
||||||
if(!mask_any && ((dsc->radius != 0) || (grad_dir != LV_GRAD_DIR_NONE)) && !need_argb8565_support()) {
|
|
||||||
#if LV_USE_GPU_NXP_VG_LITE
|
|
||||||
lv_res_t res = lv_gpu_nxp_vglite_draw_bg(draw_ctx, dsc, &bg_coords);
|
|
||||||
if(res != LV_RES_OK)
|
|
||||||
VG_LITE_LOG_TRACE("VG-Lite draw bg failed. Fallback.");
|
|
||||||
|
|
||||||
return res;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
return LV_RES_INV;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void lv_draw_nxp_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center,
|
|
||||||
uint16_t radius, uint16_t start_angle, uint16_t end_angle)
|
|
||||||
{
|
|
||||||
bool done = false;
|
|
||||||
|
|
||||||
#if LV_USE_DRAW_MASKS
|
|
||||||
if(dsc->opa <= LV_OPA_MIN)
|
|
||||||
return;
|
|
||||||
if(dsc->width == 0)
|
|
||||||
return;
|
|
||||||
if(start_angle == end_angle)
|
|
||||||
return;
|
|
||||||
|
|
||||||
#if LV_USE_GPU_NXP_VG_LITE
|
|
||||||
if(!need_argb8565_support()) {
|
|
||||||
done = (lv_gpu_nxp_vglite_draw_arc(draw_ctx, dsc, center, (int32_t)radius,
|
|
||||||
(int32_t)start_angle, (int32_t)end_angle) == LV_RES_OK);
|
|
||||||
if(!done)
|
|
||||||
VG_LITE_LOG_TRACE("VG-Lite draw arc failed. Fallback.");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif/*LV_USE_DRAW_MASKS*/
|
|
||||||
|
|
||||||
if(!done)
|
|
||||||
lv_draw_sw_arc(draw_ctx, dsc, center, radius, start_angle, end_angle);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /*LV_USE_GPU_NXP_PXP || LV_USE_GPU_NXP_VG_LITE*/
|
|
||||||
244
src/draw/nxp/pxp/lv_draw_pxp.c
Normal file
244
src/draw/nxp/pxp/lv_draw_pxp.c
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_draw_pxp.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright 2022, 2023 NXP
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next paragraph)
|
||||||
|
* shall be included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||||
|
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||||
|
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "lv_draw_pxp.h"
|
||||||
|
|
||||||
|
#if LV_USE_GPU_NXP_PXP
|
||||||
|
#include "lv_draw_pxp_blend.h"
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/* Minimum area (in pixels) for PXP blit/fill processing. */
|
||||||
|
#ifndef LV_GPU_NXP_PXP_SIZE_LIMIT
|
||||||
|
#define LV_GPU_NXP_PXP_SIZE_LIMIT 5000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
static void lv_draw_pxp_wait_for_finish(lv_draw_ctx_t * draw_ctx);
|
||||||
|
|
||||||
|
static void lv_draw_pxp_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc,
|
||||||
|
const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t cf);
|
||||||
|
|
||||||
|
static void lv_draw_pxp_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
void lv_draw_pxp_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
|
||||||
|
{
|
||||||
|
lv_draw_sw_init_ctx(drv, draw_ctx);
|
||||||
|
|
||||||
|
lv_draw_pxp_ctx_t * pxp_draw_ctx = (lv_draw_sw_ctx_t *)draw_ctx;
|
||||||
|
pxp_draw_ctx->base_draw.draw_img_decoded = lv_draw_pxp_img_decoded;
|
||||||
|
pxp_draw_ctx->blend = lv_draw_pxp_blend;
|
||||||
|
pxp_draw_ctx->base_draw.wait_for_finish = lv_draw_pxp_wait_for_finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_draw_pxp_ctx_deinit(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
|
||||||
|
{
|
||||||
|
lv_draw_sw_deinit_ctx(drv, draw_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* During rendering, LVGL might initializes new draw_ctxs and start drawing into
|
||||||
|
* a separate buffer (called layer). If the content to be rendered has "holes",
|
||||||
|
* e.g. rounded corner, LVGL temporarily sets the disp_drv.screen_transp flag.
|
||||||
|
* It means the renderers should draw into an ARGB buffer.
|
||||||
|
* With 32 bit color depth it's not a big problem but with 16 bit color depth
|
||||||
|
* the target pixel format is ARGB8565 which is not supported by the GPU.
|
||||||
|
* In this case, the PXP callbacks should fallback to SW rendering.
|
||||||
|
*/
|
||||||
|
static inline bool need_argb8565_support(lv_draw_ctx_t * draw_ctx)
|
||||||
|
{
|
||||||
|
#if LV_COLOR_DEPTH != 32
|
||||||
|
if(draw_ctx->render_with_alpha)
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lv_draw_pxp_wait_for_finish(lv_draw_ctx_t * draw_ctx)
|
||||||
|
{
|
||||||
|
lv_gpu_nxp_pxp_wait();
|
||||||
|
|
||||||
|
lv_draw_sw_wait_for_finish(draw_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lv_draw_pxp_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc)
|
||||||
|
{
|
||||||
|
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(need_argb8565_support(draw_ctx)) {
|
||||||
|
lv_draw_sw_blend_basic(draw_ctx, dsc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_area_t blend_area;
|
||||||
|
/*Let's get the blend area which is the intersection of the area to draw and the clip area*/
|
||||||
|
if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area))
|
||||||
|
return; /*Fully clipped, nothing to do*/
|
||||||
|
|
||||||
|
/*Make the blend area relative to the buffer*/
|
||||||
|
lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
|
||||||
|
if(dsc->mask_buf != NULL || dsc->blend_mode != LV_BLEND_MODE_NORMAL ||
|
||||||
|
lv_area_get_size(&blend_area) < LV_GPU_NXP_PXP_SIZE_LIMIT) {
|
||||||
|
lv_draw_sw_blend_basic(draw_ctx, dsc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Fill/Blend only non masked, normal blended*/
|
||||||
|
lv_color_t * dest_buf = draw_ctx->buf;
|
||||||
|
lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area);
|
||||||
|
const lv_color_t * src_buf = dsc->src_buf;
|
||||||
|
|
||||||
|
if(src_buf == NULL) {
|
||||||
|
lv_gpu_nxp_pxp_fill(dest_buf, &blend_area, dest_stride, dsc->color, dsc->opa);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lv_area_t src_area;
|
||||||
|
src_area.x1 = blend_area.x1 - (dsc->blend_area->x1 - draw_ctx->buf_area->x1);
|
||||||
|
src_area.y1 = blend_area.y1 - (dsc->blend_area->y1 - draw_ctx->buf_area->y1);
|
||||||
|
src_area.x2 = src_area.x1 + lv_area_get_width(dsc->blend_area) - 1;
|
||||||
|
src_area.y2 = src_area.y1 + lv_area_get_height(dsc->blend_area) - 1;
|
||||||
|
lv_coord_t src_stride = lv_area_get_width(dsc->blend_area);
|
||||||
|
|
||||||
|
lv_gpu_nxp_pxp_blit(dest_buf, &blend_area, dest_stride, src_buf, &src_area, src_stride,
|
||||||
|
dsc->opa, LV_DISP_ROT_NONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lv_draw_pxp_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc,
|
||||||
|
const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t cf)
|
||||||
|
{
|
||||||
|
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(need_argb8565_support(draw_ctx)) {
|
||||||
|
lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const lv_color_t * src_buf = (const lv_color_t *)map_p;
|
||||||
|
if(!src_buf) {
|
||||||
|
lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_area_t blend_area;
|
||||||
|
/*Let's get the blend area which is the intersection of the area to draw and the clip area.*/
|
||||||
|
if(!_lv_area_intersect(&blend_area, coords, draw_ctx->clip_area))
|
||||||
|
return; /*Fully clipped, nothing to do*/
|
||||||
|
|
||||||
|
/*Make the blend area relative to the buffer*/
|
||||||
|
lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
|
||||||
|
|
||||||
|
lv_coord_t src_width = lv_area_get_width(coords);
|
||||||
|
lv_coord_t src_height = lv_area_get_height(coords);
|
||||||
|
|
||||||
|
bool has_mask = lv_draw_mask_is_any(&blend_area);
|
||||||
|
bool has_scale = (dsc->zoom != LV_IMG_ZOOM_NONE);
|
||||||
|
bool has_rotation = (dsc->angle != 0);
|
||||||
|
bool unsup_rotation = false;
|
||||||
|
|
||||||
|
if(has_rotation) {
|
||||||
|
/*
|
||||||
|
* PXP can only rotate at 90x angles.
|
||||||
|
*/
|
||||||
|
if(dsc->angle % 900) {
|
||||||
|
PXP_LOG_TRACE("Rotation angle %d is not supported. PXP can rotate only 90x angle.", dsc->angle);
|
||||||
|
unsup_rotation = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
if(src_width % 16 || src_height % 16) {
|
||||||
|
PXP_LOG_TRACE("Rotation is not supported for image w/o alignment to block size 16x16.");
|
||||||
|
unsup_rotation = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(has_mask || has_scale || unsup_rotation || lv_area_get_size(&blend_area) < LV_GPU_NXP_PXP_SIZE_LIMIT
|
||||||
|
#if LV_COLOR_DEPTH != 32
|
||||||
|
|| lv_img_cf_has_alpha(cf)
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
|
lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_color_t * dest_buf = draw_ctx->buf;
|
||||||
|
lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area);
|
||||||
|
|
||||||
|
lv_area_t src_area;
|
||||||
|
src_area.x1 = blend_area.x1 - (coords->x1 - draw_ctx->buf_area->x1);
|
||||||
|
src_area.y1 = blend_area.y1 - (coords->y1 - draw_ctx->buf_area->y1);
|
||||||
|
src_area.x2 = src_area.x1 + src_width - 1;
|
||||||
|
src_area.y2 = src_area.y1 + src_height - 1;
|
||||||
|
lv_coord_t src_stride = lv_area_get_width(coords);
|
||||||
|
|
||||||
|
lv_gpu_nxp_pxp_blit_transform(dest_buf, &blend_area, dest_stride, src_buf, &src_area, src_stride,
|
||||||
|
dsc, cf);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /*LV_USE_GPU_NXP_PXP*/
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
/**
|
/**
|
||||||
* @file lv_gpu_nxp.h
|
* @file lv_draw_pxp.h
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright 2022 NXP
|
* Copyright 2022, 2023 NXP
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -27,8 +27,8 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LV_GPU_NXP_H
|
#ifndef LV_DRAW_PXP_H
|
||||||
#define LV_GPU_NXP_H
|
#define LV_DRAW_PXP_H
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -38,9 +38,10 @@ extern "C" {
|
|||||||
* INCLUDES
|
* INCLUDES
|
||||||
*********************/
|
*********************/
|
||||||
|
|
||||||
#include "../../lv_conf_internal.h"
|
#include "../../../lv_conf_internal.h"
|
||||||
#if LV_USE_GPU_NXP_PXP || LV_USE_GPU_NXP_VG_LITE
|
|
||||||
#include "../sw/lv_draw_sw.h"
|
#if LV_USE_GPU_NXP_PXP
|
||||||
|
#include "../../sw/lv_draw_sw.h"
|
||||||
|
|
||||||
/*********************
|
/*********************
|
||||||
* DEFINES
|
* DEFINES
|
||||||
@@ -49,23 +50,23 @@ extern "C" {
|
|||||||
/**********************
|
/**********************
|
||||||
* TYPEDEFS
|
* TYPEDEFS
|
||||||
**********************/
|
**********************/
|
||||||
typedef lv_draw_sw_ctx_t lv_draw_nxp_ctx_t;
|
typedef lv_draw_sw_ctx_t lv_draw_pxp_ctx_t;
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* GLOBAL PROTOTYPES
|
* GLOBAL PROTOTYPES
|
||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
void lv_draw_nxp_ctx_init(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
|
void lv_draw_pxp_ctx_init(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
|
||||||
|
|
||||||
void lv_draw_nxp_ctx_deinit(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
|
void lv_draw_pxp_ctx_deinit(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* MACROS
|
* MACROS
|
||||||
**********************/
|
**********************/
|
||||||
#endif /*LV_USE_GPU_NXP_PXP || LV_USE_GPU_NXP_VG_LITE*/
|
#endif /*LV_USE_GPU_NXP_PXP*/
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /*extern "C"*/
|
} /*extern "C"*/
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /*LV_GPU_NXP_H*/
|
#endif /*LV_DRAW_PXP_H*/
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
/**
|
/**
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright 2020-2022 NXP
|
* Copyright 2020-2023 NXP
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -34,16 +34,19 @@
|
|||||||
#include "lv_draw_pxp_blend.h"
|
#include "lv_draw_pxp_blend.h"
|
||||||
|
|
||||||
#if LV_USE_GPU_NXP_PXP
|
#if LV_USE_GPU_NXP_PXP
|
||||||
|
#include "lvgl_support.h"
|
||||||
|
|
||||||
/*********************
|
/*********************
|
||||||
* DEFINES
|
* DEFINES
|
||||||
*********************/
|
*********************/
|
||||||
|
|
||||||
#if LV_COLOR_DEPTH==16
|
#define PXP_TEMP_BUF_SIZE LCD_WIDTH * LCD_HEIGHT * LCD_FB_BYTE_PER_PIXEL
|
||||||
|
|
||||||
|
#if LV_COLOR_DEPTH == 16
|
||||||
#define PXP_OUT_PIXEL_FORMAT kPXP_OutputPixelFormatRGB565
|
#define PXP_OUT_PIXEL_FORMAT kPXP_OutputPixelFormatRGB565
|
||||||
#define PXP_AS_PIXEL_FORMAT kPXP_AsPixelFormatRGB565
|
#define PXP_AS_PIXEL_FORMAT kPXP_AsPixelFormatRGB565
|
||||||
#define PXP_PS_PIXEL_FORMAT kPXP_PsPixelFormatRGB565
|
#define PXP_PS_PIXEL_FORMAT kPXP_PsPixelFormatRGB565
|
||||||
#elif LV_COLOR_DEPTH==32
|
#elif LV_COLOR_DEPTH == 32
|
||||||
#define PXP_OUT_PIXEL_FORMAT kPXP_OutputPixelFormatARGB8888
|
#define PXP_OUT_PIXEL_FORMAT kPXP_OutputPixelFormatARGB8888
|
||||||
#define PXP_AS_PIXEL_FORMAT kPXP_AsPixelFormatARGB8888
|
#define PXP_AS_PIXEL_FORMAT kPXP_AsPixelFormatARGB8888
|
||||||
#define PXP_PS_PIXEL_FORMAT kPXP_PsPixelFormatRGB888
|
#define PXP_PS_PIXEL_FORMAT kPXP_PsPixelFormatRGB888
|
||||||
@@ -51,13 +54,6 @@
|
|||||||
#error Only 16bit and 32bit color depth are supported. Set LV_COLOR_DEPTH to 16 or 32.
|
#error Only 16bit and 32bit color depth are supported. Set LV_COLOR_DEPTH to 16 or 32.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) \
|
|
||||||
|| defined (_WIN64) || defined (__LP64__) || defined (__LLP64__)
|
|
||||||
#define ALIGN_SIZE 8
|
|
||||||
#else
|
|
||||||
#define ALIGN_SIZE 4
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* TYPEDEFS
|
* TYPEDEFS
|
||||||
**********************/
|
**********************/
|
||||||
@@ -66,63 +62,60 @@
|
|||||||
* STATIC PROTOTYPES
|
* STATIC PROTOTYPES
|
||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
|
static LV_ATTRIBUTE_MEM_ALIGN uint8_t temp_buf[PXP_TEMP_BUF_SIZE];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BLock Image Transfer - copy rectangular image from src buffer to dst buffer
|
* BLock Image Transfer - copy rectangular image from src buffer to dst buffer
|
||||||
* with combination of transformation (rotation, scale, recolor) and opacity, alpha channel
|
* with combination of transformation (rotation, scale, recolor) and opacity, alpha channel
|
||||||
* or color keying. This requires two steps. First step is used for transformation into
|
* or color keying. This requires two steps. First step is used for transformation into
|
||||||
* a temporary buffer and the second one will handle the color format or opacity.
|
* a temporary buffer and the second one will handle the color format or opacity.
|
||||||
*
|
*
|
||||||
* @param[in/out] dest_buf destination buffer
|
* @param[in/out] dest_buf Destination buffer
|
||||||
* @param[in] dest_area area to be copied from src_buf to dst_buf
|
* @param[in] dest_area Area with relative coordinates of destination buffer
|
||||||
* @param[in] dest_stride width (stride) of destination buffer in pixels
|
* @param[in] dest_stride Stride of destination buffer in pixels
|
||||||
* @param[in] src_buf source buffer
|
* @param[in] src_buf Source buffer
|
||||||
* @param[in] src_area source area with absolute coordinates to draw on destination buffer
|
* @param[in] src_area Area with relative coordinates of source buffer
|
||||||
* @param[in] dsc image descriptor
|
* @param[in] src_stride Stride of source buffer in pixels
|
||||||
* @param[in] cf color format
|
* @param[in] dsc Image descriptor
|
||||||
* @retval LV_RES_OK Fill completed
|
* @param[in] cf Color format
|
||||||
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS)
|
|
||||||
*/
|
*/
|
||||||
static lv_res_t lv_gpu_nxp_pxp_blit_opa(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
static void lv_pxp_blit_opa(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||||
const lv_color_t * src_buf, const lv_area_t * src_area,
|
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
|
||||||
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf);
|
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BLock Image Transfer - copy rectangular image from src buffer to dst buffer
|
* BLock Image Transfer - copy rectangular image from src buffer to dst buffer
|
||||||
* with transformation and full opacity.
|
* with transformation and full opacity.
|
||||||
*
|
*
|
||||||
* @param[in/out] dest_buf destination buffer
|
* @param[in/out] dest_buf Destination buffer
|
||||||
* @param[in] dest_area area to be copied from src_buf to dst_buf
|
* @param[in] dest_area Area with relative coordinates of destination buffer
|
||||||
* @param[in] dest_stride width (stride) of destination buffer in pixels
|
* @param[in] dest_stride Stride of destination buffer in pixels
|
||||||
* @param[in] src_buf source buffer
|
* @param[in] src_buf Source buffer
|
||||||
* @param[in] src_area source area with absolute coordinates to draw on destination buffer
|
* @param[in] src_area Area with relative coordinates of source buffer
|
||||||
* @param[in] dsc image descriptor
|
* @param[in] src_stride Stride of source buffer in pixels
|
||||||
* @param[in] cf color format
|
* @param[in] dsc Image descriptor
|
||||||
* @retval LV_RES_OK Fill completed
|
* @param[in] cf Color format
|
||||||
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS)
|
|
||||||
*/
|
*/
|
||||||
static lv_res_t lv_gpu_nxp_pxp_blit_cover(lv_color_t * dest_buf, const lv_area_t * dest_area,
|
static void lv_pxp_blit_cover(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||||
lv_coord_t dest_stride,
|
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
|
||||||
const lv_color_t * src_buf, const lv_area_t * src_area,
|
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf);
|
||||||
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BLock Image Transfer - copy rectangular image from src buffer to dst buffer
|
* BLock Image Transfer - copy rectangular image from src buffer to dst buffer
|
||||||
* without transformation but handling color format or opacity.
|
* without transformation but handling color format or opacity.
|
||||||
*
|
*
|
||||||
* @param[in/out] dest_buf destination buffer
|
* @param[in/out] dest_buf Destination buffer
|
||||||
* @param[in] dest_area area to be copied from src_buf to dst_buf
|
* @param[in] dest_area Area with relative coordinates of destination buffer
|
||||||
* @param[in] dest_stride width (stride) of destination buffer in pixels
|
* @param[in] dest_stride Stride of destination buffer in pixels
|
||||||
* @param[in] src_buf source buffer
|
* @param[in] src_buf Source buffer
|
||||||
* @param[in] src_area source area with absolute coordinates to draw on destination buffer
|
* @param[in] src_area Area with relative coordinates of source buffer
|
||||||
* @param[in] dsc image descriptor
|
* @param[in] src_stride Stride of source buffer in pixels
|
||||||
* @param[in] cf color format
|
* @param[in] dsc Image descriptor
|
||||||
* @retval LV_RES_OK Fill completed
|
* @param[in] cf Color format
|
||||||
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS)
|
|
||||||
*/
|
*/
|
||||||
static lv_res_t lv_gpu_nxp_pxp_blit_cf(lv_color_t * dest_buf, const lv_area_t * dest_area,
|
static void lv_pxp_blit_cf(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||||
lv_coord_t dest_stride,
|
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
|
||||||
const lv_color_t * src_buf, const lv_area_t * src_area,
|
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf);
|
||||||
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf);
|
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* STATIC VARIABLES
|
* STATIC VARIABLES
|
||||||
@@ -132,45 +125,27 @@ static lv_res_t lv_gpu_nxp_pxp_blit_cf(lv_color_t * dest_buf, const lv_area_t *
|
|||||||
* MACROS
|
* MACROS
|
||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
#define ROUND_UP(x, align) ((x + (align - 1)) & ~(align - 1))
|
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* GLOBAL FUNCTIONS
|
* GLOBAL FUNCTIONS
|
||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
lv_res_t lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, lv_coord_t dest_stride, const lv_area_t * fill_area,
|
void lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||||
lv_color_t color, lv_opa_t opa)
|
lv_color_t color, lv_opa_t opa)
|
||||||
{
|
{
|
||||||
uint32_t area_size = lv_area_get_size(fill_area);
|
lv_coord_t dest_w = lv_area_get_width(dest_area);
|
||||||
lv_coord_t area_w = lv_area_get_width(fill_area);
|
lv_coord_t dest_h = lv_area_get_height(dest_area);
|
||||||
lv_coord_t area_h = lv_area_get_height(fill_area);
|
|
||||||
|
|
||||||
if(opa >= (lv_opa_t)LV_OPA_MAX) {
|
lv_gpu_nxp_pxp_reset();
|
||||||
if(area_size < LV_GPU_NXP_PXP_FILL_SIZE_LIMIT) {
|
|
||||||
PXP_LOG_TRACE("Area size %d smaller than limit %d.", area_size, LV_GPU_NXP_PXP_FILL_SIZE_LIMIT);
|
|
||||||
return LV_RES_INV;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if(area_size < LV_GPU_NXP_PXP_FILL_OPA_SIZE_LIMIT) {
|
|
||||||
PXP_LOG_TRACE("Area size %d smaller than limit %d.", area_size, LV_GPU_NXP_PXP_FILL_OPA_SIZE_LIMIT);
|
|
||||||
return LV_RES_INV;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PXP_Init(LV_GPU_NXP_PXP_ID);
|
|
||||||
PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false); /*Disable CSC1, it is enabled by default.*/
|
|
||||||
PXP_SetProcessBlockSize(LV_GPU_NXP_PXP_ID, kPXP_BlockSize16); /*Block size 16x16 for higher performance*/
|
|
||||||
|
|
||||||
/*OUT buffer configure*/
|
/*OUT buffer configure*/
|
||||||
pxp_output_buffer_config_t outputConfig = {
|
pxp_output_buffer_config_t outputConfig = {
|
||||||
.pixelFormat = PXP_OUT_PIXEL_FORMAT,
|
.pixelFormat = PXP_OUT_PIXEL_FORMAT,
|
||||||
.interlacedMode = kPXP_OutputProgressive,
|
.interlacedMode = kPXP_OutputProgressive,
|
||||||
.buffer0Addr = (uint32_t)(dest_buf + dest_stride * fill_area->y1 + fill_area->x1),
|
.buffer0Addr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_area->x1),
|
||||||
.buffer1Addr = (uint32_t)NULL,
|
.buffer1Addr = (uint32_t)NULL,
|
||||||
.pitchBytes = dest_stride * sizeof(lv_color_t),
|
.pitchBytes = dest_stride * sizeof(lv_color_t),
|
||||||
.width = area_w,
|
.width = dest_w,
|
||||||
.height = area_h
|
.height = dest_h
|
||||||
};
|
};
|
||||||
|
|
||||||
PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputConfig);
|
PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputConfig);
|
||||||
@@ -189,7 +164,7 @@ lv_res_t lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, lv_coord_t dest_stride, cons
|
|||||||
};
|
};
|
||||||
|
|
||||||
PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig);
|
PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig);
|
||||||
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, area_w, area_h);
|
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*Disable PS, use as color generator*/
|
/*Disable PS, use as color generator*/
|
||||||
@@ -219,34 +194,19 @@ lv_res_t lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, lv_coord_t dest_stride, cons
|
|||||||
|
|
||||||
PXP_SetPorterDuffConfig(LV_GPU_NXP_PXP_ID, &pdConfig);
|
PXP_SetPorterDuffConfig(LV_GPU_NXP_PXP_ID, &pdConfig);
|
||||||
|
|
||||||
lv_gpu_nxp_pxp_run(); /*Start PXP task*/
|
lv_gpu_nxp_pxp_run();
|
||||||
|
|
||||||
return LV_RES_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lv_res_t lv_gpu_nxp_pxp_blit(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
void lv_gpu_nxp_pxp_blit(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||||
const lv_color_t * src_buf, const lv_area_t * src_area, lv_opa_t opa, lv_disp_rot_t angle)
|
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
|
||||||
|
lv_opa_t opa, lv_disp_rot_t angle)
|
||||||
{
|
{
|
||||||
uint32_t dest_size = lv_area_get_size(dest_area);
|
|
||||||
lv_coord_t dest_w = lv_area_get_width(dest_area);
|
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 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);
|
||||||
|
|
||||||
if(opa >= (lv_opa_t)LV_OPA_MAX) {
|
lv_gpu_nxp_pxp_reset();
|
||||||
if(dest_size < LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT) {
|
|
||||||
PXP_LOG_TRACE("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT);
|
|
||||||
return LV_RES_INV;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if(dest_size < LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT) {
|
|
||||||
PXP_LOG_TRACE("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT);
|
|
||||||
return LV_RES_INV;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PXP_Init(LV_GPU_NXP_PXP_ID);
|
|
||||||
PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false); /*Disable CSC1, it is enabled by default.*/
|
|
||||||
PXP_SetProcessBlockSize(LV_GPU_NXP_PXP_ID, kPXP_BlockSize16); /*block size 16x16 for higher performance*/
|
|
||||||
|
|
||||||
/* convert rotation angle */
|
/* convert rotation angle */
|
||||||
pxp_rotate_degree_t pxp_rot;
|
pxp_rotate_degree_t pxp_rot;
|
||||||
@@ -293,19 +253,17 @@ lv_res_t lv_gpu_nxp_pxp_blit(lv_color_t * dest_buf, const lv_area_t * dest_area,
|
|||||||
asBlendConfig.alphaMode = kPXP_AlphaOverride;
|
asBlendConfig.alphaMode = kPXP_AlphaOverride;
|
||||||
|
|
||||||
PXP_SetProcessSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &psBufferConfig);
|
PXP_SetProcessSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &psBufferConfig);
|
||||||
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1, dest_h - 1);
|
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U);
|
||||||
}
|
}
|
||||||
|
|
||||||
lv_coord_t src_stride = lv_area_get_width(src_area);
|
|
||||||
|
|
||||||
/*AS buffer - source image*/
|
/*AS buffer - source image*/
|
||||||
pxp_as_buffer_config_t asBufferConfig = {
|
pxp_as_buffer_config_t asBufferConfig = {
|
||||||
.pixelFormat = PXP_AS_PIXEL_FORMAT,
|
.pixelFormat = PXP_AS_PIXEL_FORMAT,
|
||||||
.bufferAddr = (uint32_t)src_buf,
|
.bufferAddr = (uint32_t)(src_buf + src_stride * src_area->y1 + src_area->x1),
|
||||||
.pitchBytes = src_stride * sizeof(lv_color_t)
|
.pitchBytes = src_stride * sizeof(lv_color_t)
|
||||||
};
|
};
|
||||||
PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig);
|
PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig);
|
||||||
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U);
|
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, src_w - 1U, src_h - 1U);
|
||||||
PXP_SetAlphaSurfaceBlendConfig(LV_GPU_NXP_PXP_ID, &asBlendConfig);
|
PXP_SetAlphaSurfaceBlendConfig(LV_GPU_NXP_PXP_ID, &asBlendConfig);
|
||||||
PXP_EnableAlphaSurfaceOverlayColorKey(LV_GPU_NXP_PXP_ID, false);
|
PXP_EnableAlphaSurfaceOverlayColorKey(LV_GPU_NXP_PXP_ID, false);
|
||||||
|
|
||||||
@@ -321,162 +279,102 @@ lv_res_t lv_gpu_nxp_pxp_blit(lv_color_t * dest_buf, const lv_area_t * dest_area,
|
|||||||
};
|
};
|
||||||
PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig);
|
PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig);
|
||||||
|
|
||||||
lv_gpu_nxp_pxp_run(); /* Start PXP task */
|
lv_gpu_nxp_pxp_run();
|
||||||
|
|
||||||
return LV_RES_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lv_res_t lv_gpu_nxp_pxp_blit_transform(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
void lv_gpu_nxp_pxp_blit_transform(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||||
const lv_color_t * src_buf, const lv_area_t * src_area,
|
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
|
||||||
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf)
|
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf)
|
||||||
{
|
{
|
||||||
uint32_t dest_size = lv_area_get_size(dest_area);
|
bool has_recolor = (dsc->recolor_opa != LV_OPA_TRANSP);
|
||||||
|
bool has_rotation = (dsc->angle != 0);
|
||||||
|
|
||||||
if(dsc->opa >= (lv_opa_t)LV_OPA_MAX) {
|
if(has_recolor || has_rotation) {
|
||||||
if(dest_size < LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT) {
|
if(dsc->opa >= (lv_opa_t)LV_OPA_MAX && !lv_img_cf_has_alpha(cf) && !lv_img_cf_is_chroma_keyed(cf)) {
|
||||||
PXP_LOG_TRACE("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT);
|
lv_pxp_blit_cover(dest_buf, dest_area, dest_stride, src_buf, src_area, src_stride, dsc, cf);
|
||||||
return LV_RES_INV;
|
return;
|
||||||
}
|
}
|
||||||
}
|
else {
|
||||||
else {
|
|
||||||
if(dest_size < LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT) {
|
|
||||||
PXP_LOG_TRACE("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT);
|
|
||||||
return LV_RES_INV;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool recolor = (dsc->recolor_opa != LV_OPA_TRANSP);
|
|
||||||
bool rotation = (dsc->angle != 0);
|
|
||||||
|
|
||||||
if(rotation) {
|
|
||||||
if(dsc->angle != 0 && dsc->angle != 900 && dsc->angle != 1800 && dsc->angle != 2700) {
|
|
||||||
PXP_LOG_TRACE("Rotation angle %d is not supported. PXP can rotate only 90x angle.", dsc->angle);
|
|
||||||
return LV_RES_INV;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(recolor || rotation) {
|
|
||||||
if(dsc->opa >= (lv_opa_t)LV_OPA_MAX && !lv_img_cf_has_alpha(cf) && !lv_img_cf_is_chroma_keyed(cf))
|
|
||||||
return lv_gpu_nxp_pxp_blit_cover(dest_buf, dest_area, dest_stride, src_buf, src_area, dsc, cf);
|
|
||||||
else
|
|
||||||
/*Recolor and/or rotation with alpha or opacity is done in two steps.*/
|
/*Recolor and/or rotation with alpha or opacity is done in two steps.*/
|
||||||
return lv_gpu_nxp_pxp_blit_opa(dest_buf, dest_area, dest_stride, src_buf, src_area, dsc, cf);
|
lv_pxp_blit_opa(dest_buf, dest_area, dest_stride, src_buf, src_area, src_stride, dsc, cf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return lv_gpu_nxp_pxp_blit_cf(dest_buf, dest_area, dest_stride, src_buf, src_area, dsc, cf);
|
lv_pxp_blit_cf(dest_buf, dest_area, dest_stride, src_buf, src_area, src_stride, dsc, cf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* STATIC FUNCTIONS
|
* STATIC FUNCTIONS
|
||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
static lv_res_t lv_gpu_nxp_pxp_blit_opa(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
static void lv_pxp_blit_opa(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||||
const lv_color_t * src_buf, const lv_area_t * src_area,
|
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
|
||||||
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf)
|
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf)
|
||||||
{
|
{
|
||||||
lv_coord_t dest_w = lv_area_get_width(dest_area);
|
lv_coord_t temp_area_w = lv_area_get_width(dest_area);
|
||||||
lv_coord_t dest_h = lv_area_get_height(dest_area);
|
lv_coord_t temp_area_h = lv_area_get_height(dest_area);
|
||||||
lv_res_t res;
|
const lv_area_t temp_area = {
|
||||||
uint32_t size = dest_w * dest_h * sizeof(lv_color_t);
|
|
||||||
|
|
||||||
if(ROUND_UP(size, ALIGN_SIZE) >= LV_MEM_SIZE)
|
|
||||||
PXP_RETURN_INV("Insufficient memory for temporary buffer. Please increase LV_MEM_SIZE.");
|
|
||||||
|
|
||||||
lv_color_t * tmp_buf = (lv_color_t *)lv_malloc(size);
|
|
||||||
if(!tmp_buf)
|
|
||||||
PXP_RETURN_INV("Allocating temporary buffer failed.");
|
|
||||||
|
|
||||||
const lv_area_t tmp_area = {
|
|
||||||
.x1 = 0,
|
.x1 = 0,
|
||||||
.y1 = 0,
|
.y1 = 0,
|
||||||
.x2 = dest_w - 1,
|
.x2 = temp_area_w - 1,
|
||||||
.y2 = dest_h - 1
|
.y2 = temp_area_h - 1
|
||||||
};
|
};
|
||||||
|
|
||||||
/*Step 1: Transform with full opacity to temporary buffer*/
|
/*Step 1: Transform with full opacity to temporary buffer*/
|
||||||
res = lv_gpu_nxp_pxp_blit_cover(tmp_buf, &tmp_area, dest_w, src_buf, src_area, dsc, cf);
|
lv_pxp_blit_cover((lv_color_t *)temp_buf, &temp_area, temp_area_w, src_buf, src_area, src_stride, dsc, cf);
|
||||||
if(res != LV_RES_OK) {
|
|
||||||
PXP_LOG_TRACE("Blit cover with full opacity failed.");
|
|
||||||
lv_free(tmp_buf);
|
|
||||||
|
|
||||||
return res;
|
/*Step 2: Blit temporary result with required opacity to output*/
|
||||||
}
|
lv_pxp_blit_cf(dest_buf, dest_area, dest_stride, (lv_color_t *)temp_buf, &temp_area, temp_area_w, dsc, cf);
|
||||||
|
|
||||||
/*Step 2: Blit temporary results with required opacity to output*/
|
|
||||||
res = lv_gpu_nxp_pxp_blit_cf(dest_buf, dest_area, dest_stride, tmp_buf, &tmp_area, dsc, cf);
|
|
||||||
|
|
||||||
/*Clean-up memory*/
|
|
||||||
lv_free(tmp_buf);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
static void lv_pxp_blit_cover(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||||
static lv_res_t lv_gpu_nxp_pxp_blit_cover(lv_color_t * dest_buf, const lv_area_t * dest_area,
|
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
|
||||||
lv_coord_t dest_stride,
|
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf)
|
||||||
const lv_color_t * src_buf, const lv_area_t * src_area,
|
|
||||||
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf)
|
|
||||||
{
|
{
|
||||||
lv_coord_t dest_w = lv_area_get_width(dest_area);
|
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 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 recolor = (dsc->recolor_opa != LV_OPA_TRANSP);
|
bool has_recolor = (dsc->recolor_opa != LV_OPA_TRANSP);
|
||||||
bool rotation = (dsc->angle != 0);
|
bool has_rotation = (dsc->angle != 0);
|
||||||
|
|
||||||
PXP_Init(LV_GPU_NXP_PXP_ID);
|
lv_gpu_nxp_pxp_reset();
|
||||||
PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false); /*Disable CSC1, it is enabled by default.*/
|
|
||||||
PXP_SetProcessBlockSize(LV_GPU_NXP_PXP_ID, kPXP_BlockSize16); /*block size 16x16 for higher performance*/
|
|
||||||
|
|
||||||
if(rotation) {
|
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
if(lv_area_get_width(src_area) % 16 || lv_area_get_height(src_area) % 16) {
|
|
||||||
PXP_LOG_TRACE("Rotation is not supported for image w/o alignment to block size 16x16.");
|
|
||||||
return LV_RES_INV;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if(has_rotation) {
|
||||||
/*Convert rotation angle*/
|
/*Convert rotation angle*/
|
||||||
pxp_rotate_degree_t pxp_rot;
|
pxp_rotate_degree_t pxp_angle;
|
||||||
switch(dsc->angle) {
|
switch(dsc->angle) {
|
||||||
case 0:
|
case 0:
|
||||||
pxp_rot = kPXP_Rotate0;
|
pxp_angle = kPXP_Rotate0;
|
||||||
break;
|
break;
|
||||||
case 900:
|
case 900:
|
||||||
pxp_rot = kPXP_Rotate90;
|
pxp_angle = kPXP_Rotate90;
|
||||||
break;
|
break;
|
||||||
case 1800:
|
case 1800:
|
||||||
pxp_rot = kPXP_Rotate180;
|
pxp_angle = kPXP_Rotate180;
|
||||||
break;
|
break;
|
||||||
case 2700:
|
case 2700:
|
||||||
pxp_rot = kPXP_Rotate270;
|
pxp_angle = kPXP_Rotate270;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
PXP_LOG_TRACE("Rotation angle %d is not supported. PXP can rotate only 90x angle.", dsc->angle);
|
pxp_angle = kPXP_Rotate0;
|
||||||
return LV_RES_INV;
|
|
||||||
}
|
}
|
||||||
PXP_SetRotateConfig(LV_GPU_NXP_PXP_ID, kPXP_RotateOutputBuffer, pxp_rot, kPXP_FlipDisable);
|
PXP_SetRotateConfig(LV_GPU_NXP_PXP_ID, kPXP_RotateOutputBuffer, pxp_angle, kPXP_FlipDisable);
|
||||||
}
|
}
|
||||||
|
|
||||||
lv_coord_t src_stride = lv_area_get_width(src_area);
|
|
||||||
|
|
||||||
/*AS buffer - source image*/
|
/*AS buffer - source image*/
|
||||||
pxp_as_buffer_config_t asBufferConfig = {
|
pxp_as_buffer_config_t asBufferConfig = {
|
||||||
.pixelFormat = PXP_AS_PIXEL_FORMAT,
|
.pixelFormat = PXP_AS_PIXEL_FORMAT,
|
||||||
.bufferAddr = (uint32_t)src_buf,
|
.bufferAddr = (uint32_t)(src_buf + src_stride * src_area->y1 + src_area->x1),
|
||||||
.pitchBytes = src_stride * sizeof(lv_color_t)
|
.pitchBytes = src_stride * sizeof(lv_color_t)
|
||||||
};
|
};
|
||||||
PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig);
|
PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig);
|
||||||
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U);
|
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, src_w - 1U, src_h - 1U);
|
||||||
|
|
||||||
/*Disable PS buffer*/
|
/*Disable PS buffer*/
|
||||||
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
|
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
|
||||||
if(recolor)
|
if(has_recolor)
|
||||||
/*Use as color generator*/
|
/*Use as color generator*/
|
||||||
PXP_SetProcessSurfaceBackGroundColor(LV_GPU_NXP_PXP_ID, lv_color_to32(dsc->recolor));
|
PXP_SetProcessSurfaceBackGroundColor(LV_GPU_NXP_PXP_ID, lv_color_to32(dsc->recolor));
|
||||||
|
|
||||||
@@ -492,7 +390,7 @@ static lv_res_t lv_gpu_nxp_pxp_blit_cover(lv_color_t * dest_buf, const lv_area_t
|
|||||||
};
|
};
|
||||||
PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig);
|
PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig);
|
||||||
|
|
||||||
if(recolor || lv_img_cf_has_alpha(cf)) {
|
if(has_recolor || lv_img_cf_has_alpha(cf)) {
|
||||||
/**
|
/**
|
||||||
* Configure Porter-Duff blending.
|
* Configure Porter-Duff blending.
|
||||||
*
|
*
|
||||||
@@ -508,7 +406,7 @@ static lv_res_t lv_gpu_nxp_pxp_blit_cover(lv_color_t * dest_buf, const lv_area_t
|
|||||||
.srcGlobalAlphaMode = lv_img_cf_has_alpha(cf) ? kPXP_PorterDuffLocalAlpha : kPXP_PorterDuffGlobalAlpha,
|
.srcGlobalAlphaMode = lv_img_cf_has_alpha(cf) ? kPXP_PorterDuffLocalAlpha : kPXP_PorterDuffGlobalAlpha,
|
||||||
.dstFactorMode = kPXP_PorterDuffFactorStraight,
|
.dstFactorMode = kPXP_PorterDuffFactorStraight,
|
||||||
.srcFactorMode = kPXP_PorterDuffFactorInversed,
|
.srcFactorMode = kPXP_PorterDuffFactorInversed,
|
||||||
.dstGlobalAlpha = recolor ? dsc->recolor_opa : 0x00,
|
.dstGlobalAlpha = has_recolor ? dsc->recolor_opa : 0x00,
|
||||||
.srcGlobalAlpha = 0xff,
|
.srcGlobalAlpha = 0xff,
|
||||||
.dstAlphaMode = kPXP_PorterDuffAlphaStraight, /*don't care*/
|
.dstAlphaMode = kPXP_PorterDuffAlphaStraight, /*don't care*/
|
||||||
.srcAlphaMode = kPXP_PorterDuffAlphaStraight
|
.srcAlphaMode = kPXP_PorterDuffAlphaStraight
|
||||||
@@ -516,22 +414,19 @@ static lv_res_t lv_gpu_nxp_pxp_blit_cover(lv_color_t * dest_buf, const lv_area_t
|
|||||||
PXP_SetPorterDuffConfig(LV_GPU_NXP_PXP_ID, &pdConfig);
|
PXP_SetPorterDuffConfig(LV_GPU_NXP_PXP_ID, &pdConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
lv_gpu_nxp_pxp_run(); /*Start PXP task*/
|
lv_gpu_nxp_pxp_run();
|
||||||
|
|
||||||
return LV_RES_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static lv_res_t lv_gpu_nxp_pxp_blit_cf(lv_color_t * dest_buf, const lv_area_t * dest_area,
|
static void lv_pxp_blit_cf(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||||
lv_coord_t dest_stride,
|
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
|
||||||
const lv_color_t * src_buf, const lv_area_t * src_area,
|
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf)
|
||||||
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf)
|
|
||||||
{
|
{
|
||||||
lv_coord_t dest_w = lv_area_get_width(dest_area);
|
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 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);
|
||||||
|
|
||||||
PXP_Init(LV_GPU_NXP_PXP_ID);
|
lv_gpu_nxp_pxp_reset();
|
||||||
PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false); /*Disable CSC1, it is enabled by default.*/
|
|
||||||
PXP_SetProcessBlockSize(LV_GPU_NXP_PXP_ID, kPXP_BlockSize16); /*block size 16x16 for higher performance*/
|
|
||||||
|
|
||||||
pxp_as_blend_config_t asBlendConfig = {
|
pxp_as_blend_config_t asBlendConfig = {
|
||||||
.alpha = dsc->opa,
|
.alpha = dsc->opa,
|
||||||
@@ -562,28 +457,26 @@ static lv_res_t lv_gpu_nxp_pxp_blit_cf(lv_color_t * dest_buf, const lv_area_t *
|
|||||||
asBlendConfig.alphaMode = lv_img_cf_has_alpha(cf) ? kPXP_AlphaMultiply : kPXP_AlphaOverride;
|
asBlendConfig.alphaMode = lv_img_cf_has_alpha(cf) ? kPXP_AlphaMultiply : kPXP_AlphaOverride;
|
||||||
}
|
}
|
||||||
PXP_SetProcessSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &psBufferConfig);
|
PXP_SetProcessSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &psBufferConfig);
|
||||||
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1, dest_h - 1);
|
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U);
|
||||||
}
|
}
|
||||||
|
|
||||||
lv_coord_t src_stride = lv_area_get_width(src_area);
|
|
||||||
|
|
||||||
/*AS buffer - source image*/
|
/*AS buffer - source image*/
|
||||||
pxp_as_buffer_config_t asBufferConfig = {
|
pxp_as_buffer_config_t asBufferConfig = {
|
||||||
.pixelFormat = PXP_AS_PIXEL_FORMAT,
|
.pixelFormat = PXP_AS_PIXEL_FORMAT,
|
||||||
.bufferAddr = (uint32_t)src_buf,
|
.bufferAddr = (uint32_t)(src_buf + src_stride * src_area->y1 + src_area->x1),
|
||||||
.pitchBytes = src_stride * sizeof(lv_color_t)
|
.pitchBytes = src_stride * sizeof(lv_color_t)
|
||||||
};
|
};
|
||||||
PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig);
|
PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig);
|
||||||
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U);
|
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, src_w - 1U, src_h - 1U);
|
||||||
PXP_SetAlphaSurfaceBlendConfig(LV_GPU_NXP_PXP_ID, &asBlendConfig);
|
PXP_SetAlphaSurfaceBlendConfig(LV_GPU_NXP_PXP_ID, &asBlendConfig);
|
||||||
|
|
||||||
if(lv_img_cf_is_chroma_keyed(cf)) {
|
if(lv_img_cf_is_chroma_keyed(cf)) {
|
||||||
lv_color_t colorKeyLow = LV_COLOR_CHROMA_KEY;
|
lv_color_t colorKeyLow = LV_COLOR_CHROMA_KEY;
|
||||||
lv_color_t colorKeyHigh = LV_COLOR_CHROMA_KEY;
|
lv_color_t colorKeyHigh = LV_COLOR_CHROMA_KEY;
|
||||||
|
|
||||||
bool recolor = (dsc->recolor_opa != LV_OPA_TRANSP);
|
bool has_recolor = (dsc->recolor_opa != LV_OPA_TRANSP);
|
||||||
|
|
||||||
if(recolor) {
|
if(has_recolor) {
|
||||||
/* New color key after recoloring */
|
/* New color key after recoloring */
|
||||||
lv_color_t colorKey = lv_color_mix(dsc->recolor, LV_COLOR_CHROMA_KEY, dsc->recolor_opa);
|
lv_color_t colorKey = lv_color_mix(dsc->recolor, LV_COLOR_CHROMA_KEY, dsc->recolor_opa);
|
||||||
|
|
||||||
@@ -591,11 +484,11 @@ static lv_res_t lv_gpu_nxp_pxp_blit_cf(lv_color_t * dest_buf, const lv_area_t *
|
|||||||
LV_COLOR_SET_G(colorKeyLow, colorKey.ch.green != 0 ? colorKey.ch.green - 1 : 0);
|
LV_COLOR_SET_G(colorKeyLow, colorKey.ch.green != 0 ? colorKey.ch.green - 1 : 0);
|
||||||
LV_COLOR_SET_B(colorKeyLow, colorKey.ch.blue != 0 ? colorKey.ch.blue - 1 : 0);
|
LV_COLOR_SET_B(colorKeyLow, colorKey.ch.blue != 0 ? colorKey.ch.blue - 1 : 0);
|
||||||
|
|
||||||
#if LV_COLOR_DEPTH==16
|
#if LV_COLOR_DEPTH == 16
|
||||||
LV_COLOR_SET_R(colorKeyHigh, colorKey.ch.red != 0x1f ? colorKey.ch.red + 1 : 0x1f);
|
LV_COLOR_SET_R(colorKeyHigh, colorKey.ch.red != 0x1f ? colorKey.ch.red + 1 : 0x1f);
|
||||||
LV_COLOR_SET_G(colorKeyHigh, colorKey.ch.green != 0x3f ? colorKey.ch.green + 1 : 0x3f);
|
LV_COLOR_SET_G(colorKeyHigh, colorKey.ch.green != 0x3f ? colorKey.ch.green + 1 : 0x3f);
|
||||||
LV_COLOR_SET_B(colorKeyHigh, colorKey.ch.blue != 0x1f ? colorKey.ch.blue + 1 : 0x1f);
|
LV_COLOR_SET_B(colorKeyHigh, colorKey.ch.blue != 0x1f ? colorKey.ch.blue + 1 : 0x1f);
|
||||||
#else /*LV_COLOR_DEPTH==32*/
|
#else /*LV_COLOR_DEPTH == 32*/
|
||||||
LV_COLOR_SET_R(colorKeyHigh, colorKey.ch.red != 0xff ? colorKey.ch.red + 1 : 0xff);
|
LV_COLOR_SET_R(colorKeyHigh, colorKey.ch.red != 0xff ? colorKey.ch.red + 1 : 0xff);
|
||||||
LV_COLOR_SET_G(colorKeyHigh, colorKey.ch.green != 0xff ? colorKey.ch.green + 1 : 0xff);
|
LV_COLOR_SET_G(colorKeyHigh, colorKey.ch.green != 0xff ? colorKey.ch.green + 1 : 0xff);
|
||||||
LV_COLOR_SET_B(colorKeyHigh, colorKey.ch.blue != 0xff ? colorKey.ch.blue + 1 : 0xff);
|
LV_COLOR_SET_B(colorKeyHigh, colorKey.ch.blue != 0xff ? colorKey.ch.blue + 1 : 0xff);
|
||||||
@@ -620,9 +513,7 @@ static lv_res_t lv_gpu_nxp_pxp_blit_cf(lv_color_t * dest_buf, const lv_area_t *
|
|||||||
};
|
};
|
||||||
PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig);
|
PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig);
|
||||||
|
|
||||||
lv_gpu_nxp_pxp_run(); /* Start PXP task */
|
lv_gpu_nxp_pxp_run();
|
||||||
|
|
||||||
return LV_RES_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /*LV_USE_GPU_NXP_PXP*/
|
#endif /*LV_USE_GPU_NXP_PXP*/
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/**
|
/**
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright 2020-2022 NXP
|
* Copyright 2020-2023 NXP
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -48,31 +48,6 @@ extern "C" {
|
|||||||
* DEFINES
|
* DEFINES
|
||||||
*********************/
|
*********************/
|
||||||
|
|
||||||
#ifndef LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT
|
|
||||||
/** Minimum area (in pixels) for image copy with 100% opacity to be handled by PXP*/
|
|
||||||
#define LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT 5000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT
|
|
||||||
/** Minimum area (in pixels) for image copy with transparency to be handled by PXP*/
|
|
||||||
#define LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT 5000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LV_GPU_NXP_PXP_BUFF_SYNC_BLIT_SIZE_LIMIT
|
|
||||||
/** Minimum invalidated area (in pixels) to be synchronized by PXP during buffer sync */
|
|
||||||
#define LV_GPU_NXP_PXP_BUFF_SYNC_BLIT_SIZE_LIMIT 5000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LV_GPU_NXP_PXP_FILL_SIZE_LIMIT
|
|
||||||
/** Minimum area (in pixels) to be filled by PXP with 100% opacity*/
|
|
||||||
#define LV_GPU_NXP_PXP_FILL_SIZE_LIMIT 5000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LV_GPU_NXP_PXP_FILL_OPA_SIZE_LIMIT
|
|
||||||
/** Minimum area (in pixels) to be filled by PXP with transparency*/
|
|
||||||
#define LV_GPU_NXP_PXP_FILL_OPA_SIZE_LIMIT 5000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* TYPEDEFS
|
* TYPEDEFS
|
||||||
**********************/
|
**********************/
|
||||||
@@ -84,51 +59,49 @@ extern "C" {
|
|||||||
/**
|
/**
|
||||||
* Fill area, with optional opacity.
|
* Fill area, with optional opacity.
|
||||||
*
|
*
|
||||||
* @param[in/out] dest_buf destination buffer
|
* @param[in/out] dest_buf Destination buffer
|
||||||
* @param[in] dest_stride width (stride) of destination buffer in pixels
|
* @param[in] dest_area Area with relative coordinates of destination buffer
|
||||||
* @param[in] fill_area area to fill
|
* @param[in] dest_stride Stride of destination buffer in pixels
|
||||||
* @param[in] color color
|
* @param[in] color Color
|
||||||
* @param[in] opa transparency of the color
|
* @param[in] opa Opacity
|
||||||
* @retval LV_RES_OK Fill completed
|
|
||||||
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS)
|
|
||||||
*/
|
*/
|
||||||
lv_res_t lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, lv_coord_t dest_stride, const lv_area_t * fill_area,
|
void lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||||
lv_color_t color, lv_opa_t opa);
|
lv_color_t color, lv_opa_t opa);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BLock Image Transfer - copy rectangular image from src_buf to dst_buf with effects.
|
* BLock Image Transfer - copy rectangular image from src_buf to dst_buf with effects.
|
||||||
* By default, image is copied directly, with optional opacity. This function can also
|
* By default, image is copied directly, with optional opacity. This function can also
|
||||||
* rotate the display output buffer to a specified angle (90x step).
|
* rotate the display output buffer to a specified angle (90x step).
|
||||||
*
|
*
|
||||||
* @param[in/out] dest_buf destination buffer
|
* @param[in/out] dest_buf Destination buffer
|
||||||
* @param[in] dest_area destination area
|
* @param[in] dest_area Area with relative coordinates of destination buffer
|
||||||
* @param[in] dest_stride width (stride) of destination buffer in pixels
|
* @param[in] dest_stride Stride of destination buffer in pixels
|
||||||
* @param[in] src_buf source buffer
|
* @param[in] src_buf Source buffer
|
||||||
* @param[in] src_area source area with absolute coordinates to draw on destination buffer
|
* @param[in] src_area Source area with relative coordinates of source buffer
|
||||||
* @param[in] opa opacity of the result
|
* @param[in] src_stride Stride of source buffer in pixels
|
||||||
* @param[in] angle display rotation angle (90x)
|
* @param[in] opa Opacity
|
||||||
* @retval LV_RES_OK Fill completed
|
* @param[in] angle Display rotation angle (90x)
|
||||||
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS)
|
|
||||||
*/
|
*/
|
||||||
lv_res_t lv_gpu_nxp_pxp_blit(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
void lv_gpu_nxp_pxp_blit(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||||
const lv_color_t * src_buf, const lv_area_t * src_area, lv_opa_t opa, lv_disp_rot_t angle);
|
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
|
||||||
|
lv_opa_t opa, lv_disp_rot_t angle);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BLock Image Transfer - copy rectangular image from src_buf to dst_buf with transformation.
|
* BLock Image Transfer - copy rectangular image from src_buf to dst_buf with transformation.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @param[in/out] dest_buf destination buffer
|
* @param[in/out] dest_buf Destination buffer
|
||||||
* @param[in] dest_area destination area
|
* @param[in] dest_area Area with relative coordinates of destination buffer
|
||||||
* @param[in] dest_stride width (stride) of destination buffer in pixels
|
* @param[in] dest_stride Stride of destination buffer in pixels
|
||||||
* @param[in] src_buf source buffer
|
* @param[in] src_buf Source buffer
|
||||||
* @param[in] src_area source area with absolute coordinates to draw on destination buffer
|
* @param[in] src_area Area with relative coordinates of source buffer
|
||||||
* @param[in] dsc image descriptor
|
* @param[in] src_stride Stride of source buffer in pixels
|
||||||
* @param[in] cf color format
|
* @param[in] dsc Image descriptor
|
||||||
* @retval LV_RES_OK Fill completed
|
* @param[in] cf Color format
|
||||||
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS)
|
|
||||||
*/
|
*/
|
||||||
lv_res_t lv_gpu_nxp_pxp_blit_transform(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
void lv_gpu_nxp_pxp_blit_transform(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||||
const lv_color_t * src_buf, const lv_area_t * src_area, const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf);
|
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
|
||||||
|
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf);
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* MACROS
|
* MACROS
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/**
|
/**
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright 2020-2022 NXP
|
* Copyright 2020-2023 NXP
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -50,9 +50,9 @@
|
|||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clean & invalidate cache.
|
* Clean and invalidate cache.
|
||||||
*/
|
*/
|
||||||
static void invalidate_cache(void);
|
static inline void invalidate_cache(void);
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* STATIC VARIABLES
|
* STATIC VARIABLES
|
||||||
@@ -70,16 +70,23 @@ static lv_nxp_pxp_cfg_t * pxp_cfg;
|
|||||||
|
|
||||||
lv_res_t lv_gpu_nxp_pxp_init(void)
|
lv_res_t lv_gpu_nxp_pxp_init(void)
|
||||||
{
|
{
|
||||||
|
#if LV_USE_GPU_NXP_PXP_AUTO_INIT
|
||||||
pxp_cfg = lv_gpu_nxp_pxp_get_cfg();
|
pxp_cfg = lv_gpu_nxp_pxp_get_cfg();
|
||||||
|
#endif
|
||||||
|
|
||||||
if(!pxp_cfg || !pxp_cfg->pxp_interrupt_deinit || !pxp_cfg->pxp_interrupt_init || !pxp_cfg->pxp_run)
|
if(!pxp_cfg || !pxp_cfg->pxp_interrupt_deinit || !pxp_cfg->pxp_interrupt_init ||
|
||||||
|
!pxp_cfg->pxp_run || !pxp_cfg->pxp_wait)
|
||||||
PXP_RETURN_INV("PXP configuration error.");
|
PXP_RETURN_INV("PXP configuration error.");
|
||||||
|
|
||||||
PXP_Init(LV_GPU_NXP_PXP_ID);
|
PXP_Init(LV_GPU_NXP_PXP_ID);
|
||||||
|
|
||||||
PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false); /*Disable CSC1, it is enabled by default.*/
|
PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false); /*Disable CSC1, it is enabled by default.*/
|
||||||
|
PXP_SetProcessBlockSize(LV_GPU_NXP_PXP_ID, kPXP_BlockSize16); /*Block size 16x16 for higher performance*/
|
||||||
|
|
||||||
PXP_EnableInterrupts(LV_GPU_NXP_PXP_ID, kPXP_CompleteInterruptEnable);
|
PXP_EnableInterrupts(LV_GPU_NXP_PXP_ID, kPXP_CompleteInterruptEnable);
|
||||||
|
|
||||||
if(pxp_cfg->pxp_interrupt_init() != LV_RES_OK) {
|
if(pxp_cfg->pxp_interrupt_init() != LV_RES_OK) {
|
||||||
|
PXP_DisableInterrupts(LV_GPU_NXP_PXP_ID, kPXP_CompleteInterruptEnable);
|
||||||
PXP_Deinit(LV_GPU_NXP_PXP_ID);
|
PXP_Deinit(LV_GPU_NXP_PXP_ID);
|
||||||
PXP_RETURN_INV("PXP interrupt init failed.");
|
PXP_RETURN_INV("PXP interrupt init failed.");
|
||||||
}
|
}
|
||||||
@@ -90,23 +97,38 @@ lv_res_t lv_gpu_nxp_pxp_init(void)
|
|||||||
void lv_gpu_nxp_pxp_deinit(void)
|
void lv_gpu_nxp_pxp_deinit(void)
|
||||||
{
|
{
|
||||||
pxp_cfg->pxp_interrupt_deinit();
|
pxp_cfg->pxp_interrupt_deinit();
|
||||||
PXP_DisableInterrupts(PXP, kPXP_CompleteInterruptEnable);
|
PXP_DisableInterrupts(LV_GPU_NXP_PXP_ID, kPXP_CompleteInterruptEnable);
|
||||||
PXP_Deinit(LV_GPU_NXP_PXP_ID);
|
PXP_Deinit(LV_GPU_NXP_PXP_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lv_gpu_nxp_pxp_reset(void)
|
||||||
|
{
|
||||||
|
/* Wait for previous command to complete before resetting the registers. */
|
||||||
|
lv_gpu_nxp_pxp_wait();
|
||||||
|
|
||||||
|
PXP_ResetControl(LV_GPU_NXP_PXP_ID);
|
||||||
|
|
||||||
|
PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false); /*Disable CSC1, it is enabled by default.*/
|
||||||
|
PXP_SetProcessBlockSize(LV_GPU_NXP_PXP_ID, kPXP_BlockSize16); /*Block size 16x16 for higher performance*/
|
||||||
|
}
|
||||||
|
|
||||||
void lv_gpu_nxp_pxp_run(void)
|
void lv_gpu_nxp_pxp_run(void)
|
||||||
{
|
{
|
||||||
/*Clean & invalidate cache*/
|
|
||||||
invalidate_cache();
|
invalidate_cache();
|
||||||
|
|
||||||
pxp_cfg->pxp_run();
|
pxp_cfg->pxp_run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lv_gpu_nxp_pxp_wait(void)
|
||||||
|
{
|
||||||
|
pxp_cfg->pxp_wait();
|
||||||
|
}
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* STATIC FUNCTIONS
|
* STATIC FUNCTIONS
|
||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
static void invalidate_cache(void)
|
static inline void invalidate_cache(void)
|
||||||
{
|
{
|
||||||
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
||||||
if(disp->driver->clean_dcache_cb)
|
if(disp->driver->clean_dcache_cb)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/**
|
/**
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright 2020-2022 NXP
|
* Copyright 2020-2023 NXP
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -81,8 +81,11 @@ typedef struct {
|
|||||||
/** Callback for PXP interrupt de-initialization*/
|
/** Callback for PXP interrupt de-initialization*/
|
||||||
void (*pxp_interrupt_deinit)(void);
|
void (*pxp_interrupt_deinit)(void);
|
||||||
|
|
||||||
/** Callback that should start PXP and wait for operation complete*/
|
/** Callback for PXP start*/
|
||||||
void (*pxp_run)(void);
|
void (*pxp_run)(void);
|
||||||
|
|
||||||
|
/** Callback for waiting of PXP completion*/
|
||||||
|
void (*pxp_wait)(void);
|
||||||
} lv_nxp_pxp_cfg_t;
|
} lv_nxp_pxp_cfg_t;
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
@@ -104,10 +107,20 @@ lv_res_t lv_gpu_nxp_pxp_init(void);
|
|||||||
void lv_gpu_nxp_pxp_deinit(void);
|
void lv_gpu_nxp_pxp_deinit(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start PXP job and wait for completion.
|
* Reset PXP device.
|
||||||
|
*/
|
||||||
|
void lv_gpu_nxp_pxp_reset(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear cache and start PXP.
|
||||||
*/
|
*/
|
||||||
void lv_gpu_nxp_pxp_run(void);
|
void lv_gpu_nxp_pxp_run(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for PXP completion.
|
||||||
|
*/
|
||||||
|
void lv_gpu_nxp_pxp_wait(void);
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* MACROS
|
* MACROS
|
||||||
**********************/
|
**********************/
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/**
|
/**
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright 2020, 2022 NXP
|
* Copyright 2020, 2022, 2023 NXP
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -65,24 +65,29 @@ static lv_res_t _lv_gpu_nxp_pxp_interrupt_init(void);
|
|||||||
static void _lv_gpu_nxp_pxp_interrupt_deinit(void);
|
static void _lv_gpu_nxp_pxp_interrupt_deinit(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start the PXP job and wait for task completion.
|
* Start the PXP job.
|
||||||
*/
|
*/
|
||||||
static void _lv_gpu_nxp_pxp_run(void);
|
static void _lv_gpu_nxp_pxp_run(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for PXP completion.
|
||||||
|
*/
|
||||||
|
static void _lv_gpu_nxp_pxp_wait(void);
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* STATIC VARIABLES
|
* STATIC VARIABLES
|
||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
#if defined(SDK_OS_FREE_RTOS)
|
#if defined(SDK_OS_FREE_RTOS)
|
||||||
static SemaphoreHandle_t s_pxpIdle;
|
static SemaphoreHandle_t s_pxpIdleSem;
|
||||||
#else
|
|
||||||
static volatile bool s_pxpIdle;
|
|
||||||
#endif
|
#endif
|
||||||
|
static volatile bool s_pxpIdle;
|
||||||
|
|
||||||
static lv_nxp_pxp_cfg_t pxp_default_cfg = {
|
static lv_nxp_pxp_cfg_t pxp_default_cfg = {
|
||||||
.pxp_interrupt_init = _lv_gpu_nxp_pxp_interrupt_init,
|
.pxp_interrupt_init = _lv_gpu_nxp_pxp_interrupt_init,
|
||||||
.pxp_interrupt_deinit = _lv_gpu_nxp_pxp_interrupt_deinit,
|
.pxp_interrupt_deinit = _lv_gpu_nxp_pxp_interrupt_deinit,
|
||||||
.pxp_run = _lv_gpu_nxp_pxp_run
|
.pxp_run = _lv_gpu_nxp_pxp_run,
|
||||||
|
.pxp_wait = _lv_gpu_nxp_pxp_wait,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
@@ -102,7 +107,7 @@ void PXP_IRQHandler(void)
|
|||||||
if(kPXP_CompleteFlag & PXP_GetStatusFlags(LV_GPU_NXP_PXP_ID)) {
|
if(kPXP_CompleteFlag & PXP_GetStatusFlags(LV_GPU_NXP_PXP_ID)) {
|
||||||
PXP_ClearStatusFlags(LV_GPU_NXP_PXP_ID, kPXP_CompleteFlag);
|
PXP_ClearStatusFlags(LV_GPU_NXP_PXP_ID, kPXP_CompleteFlag);
|
||||||
#if defined(SDK_OS_FREE_RTOS)
|
#if defined(SDK_OS_FREE_RTOS)
|
||||||
xSemaphoreGiveFromISR(s_pxpIdle, &taskAwake);
|
xSemaphoreGiveFromISR(s_pxpIdleSem, &taskAwake);
|
||||||
portYIELD_FROM_ISR(taskAwake);
|
portYIELD_FROM_ISR(taskAwake);
|
||||||
#else
|
#else
|
||||||
s_pxpIdle = true;
|
s_pxpIdle = true;
|
||||||
@@ -122,14 +127,13 @@ lv_nxp_pxp_cfg_t * lv_gpu_nxp_pxp_get_cfg(void)
|
|||||||
static lv_res_t _lv_gpu_nxp_pxp_interrupt_init(void)
|
static lv_res_t _lv_gpu_nxp_pxp_interrupt_init(void)
|
||||||
{
|
{
|
||||||
#if defined(SDK_OS_FREE_RTOS)
|
#if defined(SDK_OS_FREE_RTOS)
|
||||||
s_pxpIdle = xSemaphoreCreateBinary();
|
s_pxpIdleSem = xSemaphoreCreateBinary();
|
||||||
if(s_pxpIdle == NULL)
|
if(s_pxpIdleSem == NULL)
|
||||||
return LV_RES_INV;
|
return LV_RES_INV;
|
||||||
|
|
||||||
NVIC_SetPriority(LV_GPU_NXP_PXP_IRQ_ID, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1);
|
NVIC_SetPriority(LV_GPU_NXP_PXP_IRQ_ID, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1);
|
||||||
#else
|
|
||||||
s_pxpIdle = true;
|
|
||||||
#endif
|
#endif
|
||||||
|
s_pxpIdle = true;
|
||||||
|
|
||||||
NVIC_EnableIRQ(LV_GPU_NXP_PXP_IRQ_ID);
|
NVIC_EnableIRQ(LV_GPU_NXP_PXP_IRQ_ID);
|
||||||
|
|
||||||
@@ -140,21 +144,33 @@ static void _lv_gpu_nxp_pxp_interrupt_deinit(void)
|
|||||||
{
|
{
|
||||||
NVIC_DisableIRQ(LV_GPU_NXP_PXP_IRQ_ID);
|
NVIC_DisableIRQ(LV_GPU_NXP_PXP_IRQ_ID);
|
||||||
#if defined(SDK_OS_FREE_RTOS)
|
#if defined(SDK_OS_FREE_RTOS)
|
||||||
vSemaphoreDelete(s_pxpIdle);
|
vSemaphoreDelete(s_pxpIdleSem);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to start PXP job.
|
||||||
|
*/
|
||||||
static void _lv_gpu_nxp_pxp_run(void)
|
static void _lv_gpu_nxp_pxp_run(void)
|
||||||
{
|
{
|
||||||
#if !defined(SDK_OS_FREE_RTOS)
|
|
||||||
s_pxpIdle = false;
|
s_pxpIdle = false;
|
||||||
#endif
|
|
||||||
|
|
||||||
PXP_EnableInterrupts(LV_GPU_NXP_PXP_ID, kPXP_CompleteInterruptEnable);
|
PXP_EnableInterrupts(LV_GPU_NXP_PXP_ID, kPXP_CompleteInterruptEnable);
|
||||||
PXP_Start(LV_GPU_NXP_PXP_ID);
|
PXP_Start(LV_GPU_NXP_PXP_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to wait for PXP completion.
|
||||||
|
*/
|
||||||
|
static void _lv_gpu_nxp_pxp_wait(void)
|
||||||
|
{
|
||||||
#if defined(SDK_OS_FREE_RTOS)
|
#if defined(SDK_OS_FREE_RTOS)
|
||||||
PXP_COND_STOP(!xSemaphoreTake(s_pxpIdle, portMAX_DELAY), "xSemaphoreTake failed.");
|
/* Return if PXP was never started, otherwise the semaphore will lock forever. */
|
||||||
|
if(s_pxpIdle == true)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(xSemaphoreTake(s_pxpIdleSem, portMAX_DELAY) == pdTRUE)
|
||||||
|
s_pxpIdle = true;
|
||||||
#else
|
#else
|
||||||
while(s_pxpIdle == false) {
|
while(s_pxpIdle == false) {
|
||||||
}
|
}
|
||||||
|
|||||||
502
src/draw/nxp/vglite/lv_draw_vglite.c
Normal file
502
src/draw/nxp/vglite/lv_draw_vglite.c
Normal file
@@ -0,0 +1,502 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_draw_vglite.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright 2022, 2023 NXP
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next paragraph)
|
||||||
|
* shall be included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||||
|
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||||
|
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "lv_draw_vglite.h"
|
||||||
|
|
||||||
|
#if LV_USE_GPU_NXP_VG_LITE
|
||||||
|
#include <math.h>
|
||||||
|
#include "lv_draw_vglite_blend.h"
|
||||||
|
#include "lv_draw_vglite_line.h"
|
||||||
|
#include "lv_draw_vglite_rect.h"
|
||||||
|
#include "lv_draw_vglite_arc.h"
|
||||||
|
#include "lv_vglite_buf.h"
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/* Minimum area (in pixels) for VG-Lite blit/fill processing. */
|
||||||
|
#ifndef LV_GPU_NXP_VG_LITE_SIZE_LIMIT
|
||||||
|
#define LV_GPU_NXP_VG_LITE_SIZE_LIMIT 5000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
static void lv_draw_vglite_init_buf(lv_draw_ctx_t * draw_ctx);
|
||||||
|
|
||||||
|
static void lv_draw_vglite_wait_for_finish(lv_draw_ctx_t * draw_ctx);
|
||||||
|
|
||||||
|
static void lv_draw_vglite_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc,
|
||||||
|
const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t cf);
|
||||||
|
|
||||||
|
static void lv_draw_vglite_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc);
|
||||||
|
|
||||||
|
static void lv_draw_vglite_line(lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, const lv_point_t * point1,
|
||||||
|
const lv_point_t * point2);
|
||||||
|
|
||||||
|
static void lv_draw_vglite_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
|
||||||
|
|
||||||
|
static lv_res_t lv_draw_vglite_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
|
||||||
|
|
||||||
|
static lv_res_t lv_draw_vglite_border(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc,
|
||||||
|
const lv_area_t * coords);
|
||||||
|
|
||||||
|
static lv_res_t lv_draw_vglite_outline(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc,
|
||||||
|
const lv_area_t * coords);
|
||||||
|
|
||||||
|
static void lv_draw_vglite_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center,
|
||||||
|
uint16_t radius, uint16_t start_angle, uint16_t end_angle);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
void lv_draw_vglite_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
|
||||||
|
{
|
||||||
|
lv_draw_sw_init_ctx(drv, draw_ctx);
|
||||||
|
|
||||||
|
lv_draw_vglite_ctx_t * vglite_draw_ctx = (lv_draw_sw_ctx_t *)draw_ctx;
|
||||||
|
vglite_draw_ctx->base_draw.init_buf = lv_draw_vglite_init_buf;
|
||||||
|
vglite_draw_ctx->base_draw.draw_line = lv_draw_vglite_line;
|
||||||
|
vglite_draw_ctx->base_draw.draw_arc = lv_draw_vglite_arc;
|
||||||
|
vglite_draw_ctx->base_draw.draw_rect = lv_draw_vglite_rect;
|
||||||
|
vglite_draw_ctx->base_draw.draw_img_decoded = lv_draw_vglite_img_decoded;
|
||||||
|
vglite_draw_ctx->blend = lv_draw_vglite_blend;
|
||||||
|
vglite_draw_ctx->base_draw.wait_for_finish = lv_draw_vglite_wait_for_finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_draw_vglite_ctx_deinit(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
|
||||||
|
{
|
||||||
|
lv_draw_sw_deinit_ctx(drv, draw_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* During rendering, LVGL might initializes new draw_ctxs and start drawing into
|
||||||
|
* a separate buffer (called layer). If the content to be rendered has "holes",
|
||||||
|
* e.g. rounded corner, LVGL temporarily sets the disp_drv.screen_transp flag.
|
||||||
|
* It means the renderers should draw into an ARGB buffer.
|
||||||
|
* With 32 bit color depth it's not a big problem but with 16 bit color depth
|
||||||
|
* the target pixel format is ARGB8565 which is not supported by the GPU.
|
||||||
|
* In this case, the VG-Lite callbacks should fallback to SW rendering.
|
||||||
|
*/
|
||||||
|
static inline bool need_argb8565_support(lv_draw_ctx_t * draw_ctx)
|
||||||
|
{
|
||||||
|
#if LV_COLOR_DEPTH != 32
|
||||||
|
if(draw_ctx->render_with_alpha)
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lv_draw_vglite_init_buf(lv_draw_ctx_t * draw_ctx)
|
||||||
|
{
|
||||||
|
lv_gpu_nxp_vglite_init_buf(draw_ctx->buf, draw_ctx->buf_area, lv_area_get_width(draw_ctx->buf_area));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lv_draw_vglite_wait_for_finish(lv_draw_ctx_t * draw_ctx)
|
||||||
|
{
|
||||||
|
vg_lite_finish();
|
||||||
|
|
||||||
|
lv_draw_sw_wait_for_finish(draw_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lv_draw_vglite_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc)
|
||||||
|
{
|
||||||
|
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(need_argb8565_support(draw_ctx)) {
|
||||||
|
lv_draw_sw_blend_basic(draw_ctx, dsc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_area_t blend_area;
|
||||||
|
/*Let's get the blend area which is the intersection of the area to draw and the clip area*/
|
||||||
|
if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area))
|
||||||
|
return; /*Fully clipped, nothing to do*/
|
||||||
|
|
||||||
|
/*Make the blend area relative to the buffer*/
|
||||||
|
lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
|
||||||
|
|
||||||
|
bool done = false;
|
||||||
|
/*Fill/Blend only non masked, normal blended*/
|
||||||
|
if(dsc->mask_buf == NULL && dsc->blend_mode == LV_BLEND_MODE_NORMAL &&
|
||||||
|
lv_area_get_size(&blend_area) >= LV_GPU_NXP_VG_LITE_SIZE_LIMIT) {
|
||||||
|
const lv_color_t * src_buf = dsc->src_buf;
|
||||||
|
|
||||||
|
if(src_buf == NULL) {
|
||||||
|
done = (lv_gpu_nxp_vglite_fill(&blend_area, dsc->color, dsc->opa) == LV_RES_OK);
|
||||||
|
if(!done)
|
||||||
|
VG_LITE_LOG_TRACE("VG-Lite fill failed. Fallback.");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lv_color_t * dest_buf = draw_ctx->buf;
|
||||||
|
lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area);
|
||||||
|
|
||||||
|
lv_area_t src_area;
|
||||||
|
src_area.x1 = blend_area.x1 - (dsc->blend_area->x1 - draw_ctx->buf_area->x1);
|
||||||
|
src_area.y1 = blend_area.y1 - (dsc->blend_area->y1 - draw_ctx->buf_area->y1);
|
||||||
|
src_area.x2 = src_area.x1 + lv_area_get_width(dsc->blend_area) - 1;
|
||||||
|
src_area.y2 = src_area.y1 + lv_area_get_height(dsc->blend_area) - 1;
|
||||||
|
lv_coord_t src_stride = lv_area_get_width(dsc->blend_area);
|
||||||
|
|
||||||
|
done = (lv_gpu_nxp_vglite_blit(dest_buf, &blend_area, dest_stride,
|
||||||
|
src_buf, &src_area, src_stride, dsc->opa) == LV_RES_OK);
|
||||||
|
|
||||||
|
if(!done)
|
||||||
|
VG_LITE_LOG_TRACE("VG-Lite blit failed. Fallback.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!done)
|
||||||
|
lv_draw_sw_blend_basic(draw_ctx, dsc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lv_draw_vglite_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc,
|
||||||
|
const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t cf)
|
||||||
|
{
|
||||||
|
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(need_argb8565_support(draw_ctx)) {
|
||||||
|
lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const lv_color_t * src_buf = (const lv_color_t *)map_p;
|
||||||
|
if(!src_buf) {
|
||||||
|
lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_area_t blend_area;
|
||||||
|
/*Let's get the blend area which is the intersection of the area to draw and the clip area*/
|
||||||
|
if(!_lv_area_intersect(&blend_area, coords, draw_ctx->clip_area))
|
||||||
|
return; /*Fully clipped, nothing to do*/
|
||||||
|
|
||||||
|
/*Make the blend area relative to the buffer*/
|
||||||
|
lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
|
||||||
|
|
||||||
|
bool has_mask = lv_draw_mask_is_any(&blend_area);
|
||||||
|
bool has_recolor = (dsc->recolor_opa != LV_OPA_TRANSP);
|
||||||
|
|
||||||
|
bool done = false;
|
||||||
|
if(!has_mask && !has_recolor && !lv_img_cf_is_chroma_keyed(cf) &&
|
||||||
|
lv_area_get_size(&blend_area) >= LV_GPU_NXP_VG_LITE_SIZE_LIMIT
|
||||||
|
#if LV_COLOR_DEPTH != 32
|
||||||
|
&& !lv_img_cf_has_alpha(cf)
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
|
lv_color_t * dest_buf = draw_ctx->buf;
|
||||||
|
lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area);
|
||||||
|
|
||||||
|
lv_area_t src_area;
|
||||||
|
src_area.x1 = blend_area.x1 - (coords->x1 - draw_ctx->buf_area->x1);
|
||||||
|
src_area.y1 = blend_area.y1 - (coords->y1 - draw_ctx->buf_area->y1);
|
||||||
|
src_area.x2 = src_area.x1 + lv_area_get_width(coords) - 1;
|
||||||
|
src_area.y2 = src_area.y1 + lv_area_get_height(coords) - 1;
|
||||||
|
lv_coord_t src_stride = lv_area_get_width(coords);
|
||||||
|
|
||||||
|
done = (lv_gpu_nxp_vglite_blit_transform(dest_buf, &blend_area, dest_stride,
|
||||||
|
src_buf, &src_area, src_stride, dsc) == LV_RES_OK);
|
||||||
|
|
||||||
|
if(!done)
|
||||||
|
VG_LITE_LOG_TRACE("VG-Lite blit transform failed. Fallback.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!done)
|
||||||
|
lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lv_draw_vglite_line(lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, const lv_point_t * point1,
|
||||||
|
const lv_point_t * point2)
|
||||||
|
{
|
||||||
|
if(dsc->width == 0)
|
||||||
|
return;
|
||||||
|
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
|
||||||
|
return;
|
||||||
|
if(point1->x == point2->x && point1->y == point2->y)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(need_argb8565_support(draw_ctx)) {
|
||||||
|
lv_draw_sw_line(draw_ctx, dsc, point1, point2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_area_t rel_clip_area;
|
||||||
|
rel_clip_area.x1 = LV_MIN(point1->x, point2->x) - dsc->width / 2;
|
||||||
|
rel_clip_area.x2 = LV_MAX(point1->x, point2->x) + dsc->width / 2;
|
||||||
|
rel_clip_area.y1 = LV_MIN(point1->y, point2->y) - dsc->width / 2;
|
||||||
|
rel_clip_area.y2 = LV_MAX(point1->y, point2->y) + dsc->width / 2;
|
||||||
|
|
||||||
|
bool is_common;
|
||||||
|
is_common = _lv_area_intersect(&rel_clip_area, &rel_clip_area, draw_ctx->clip_area);
|
||||||
|
if(!is_common)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Make coordinates relative to the draw buffer */
|
||||||
|
lv_area_move(&rel_clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
|
||||||
|
|
||||||
|
lv_point_t rel_point1 = { point1->x - draw_ctx->buf_area->x1, point1->y - draw_ctx->buf_area->y1 };
|
||||||
|
lv_point_t rel_point2 = { point2->x - draw_ctx->buf_area->x1, point2->y - draw_ctx->buf_area->y1 };
|
||||||
|
|
||||||
|
bool done = false;
|
||||||
|
bool mask_any = lv_draw_mask_is_any(&rel_clip_area);
|
||||||
|
|
||||||
|
if(!mask_any) {
|
||||||
|
done = (lv_gpu_nxp_vglite_draw_line(&rel_point1, &rel_point2, &rel_clip_area, dsc) == LV_RES_OK);
|
||||||
|
if(!done)
|
||||||
|
VG_LITE_LOG_TRACE("VG-Lite draw line failed. Fallback.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!done)
|
||||||
|
lv_draw_sw_line(draw_ctx, dsc, point1, point2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lv_draw_vglite_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords)
|
||||||
|
{
|
||||||
|
if(need_argb8565_support(draw_ctx)) {
|
||||||
|
lv_draw_sw_rect(draw_ctx, dsc, coords);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_draw_rect_dsc_t vglite_dsc;
|
||||||
|
|
||||||
|
lv_memcpy(&vglite_dsc, dsc, sizeof(vglite_dsc));
|
||||||
|
vglite_dsc.bg_opa = 0;
|
||||||
|
vglite_dsc.bg_img_opa = 0;
|
||||||
|
vglite_dsc.border_opa = 0;
|
||||||
|
vglite_dsc.outline_opa = 0;
|
||||||
|
#if LV_USE_DRAW_MASKS
|
||||||
|
/* Draw the shadow with CPU */
|
||||||
|
lv_draw_sw_rect(draw_ctx, &vglite_dsc, coords);
|
||||||
|
vglite_dsc.shadow_opa = 0;
|
||||||
|
#endif /*LV_USE_DRAW_MASKS*/
|
||||||
|
|
||||||
|
/* Draw the background */
|
||||||
|
vglite_dsc.bg_opa = dsc->bg_opa;
|
||||||
|
if(lv_draw_vglite_bg(draw_ctx, &vglite_dsc, coords) != LV_RES_OK)
|
||||||
|
lv_draw_sw_rect(draw_ctx, &vglite_dsc, coords);
|
||||||
|
vglite_dsc.bg_opa = 0;
|
||||||
|
|
||||||
|
/* Draw the background image
|
||||||
|
* It will be done once draw_ctx->draw_img_decoded()
|
||||||
|
* callback gets called from lv_draw_sw_rect().
|
||||||
|
*/
|
||||||
|
vglite_dsc.bg_img_opa = dsc->bg_img_opa;
|
||||||
|
lv_draw_sw_rect(draw_ctx, &vglite_dsc, coords);
|
||||||
|
vglite_dsc.bg_img_opa = 0;
|
||||||
|
|
||||||
|
/* Draw the border */
|
||||||
|
vglite_dsc.border_opa = dsc->border_opa;
|
||||||
|
if(lv_draw_vglite_border(draw_ctx, &vglite_dsc, coords) != LV_RES_OK)
|
||||||
|
lv_draw_sw_rect(draw_ctx, &vglite_dsc, coords);
|
||||||
|
vglite_dsc.border_opa = 0;
|
||||||
|
|
||||||
|
/* Draw the outline */
|
||||||
|
vglite_dsc.outline_opa = dsc->outline_opa;
|
||||||
|
if(lv_draw_vglite_outline(draw_ctx, &vglite_dsc, coords) != LV_RES_OK)
|
||||||
|
lv_draw_sw_rect(draw_ctx, &vglite_dsc, coords);
|
||||||
|
}
|
||||||
|
|
||||||
|
static lv_res_t lv_draw_vglite_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords)
|
||||||
|
{
|
||||||
|
if(dsc->bg_opa <= (lv_opa_t)LV_OPA_MIN)
|
||||||
|
return LV_RES_INV;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make coordinates relative to draw buffer */
|
||||||
|
lv_area_move(&rel_coords, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
|
||||||
|
|
||||||
|
lv_area_t rel_clip_area;
|
||||||
|
lv_area_copy(&rel_clip_area, draw_ctx->clip_area);
|
||||||
|
lv_area_move(&rel_clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
|
||||||
|
|
||||||
|
lv_area_t clipped_coords;
|
||||||
|
if(!_lv_area_intersect(&clipped_coords, &rel_coords, &rel_clip_area))
|
||||||
|
return LV_RES_INV;
|
||||||
|
|
||||||
|
bool mask_any = lv_draw_mask_is_any(&rel_coords);
|
||||||
|
lv_grad_dir_t grad_dir = dsc->bg_grad.dir;
|
||||||
|
lv_color_t bg_color = (grad_dir == (lv_grad_dir_t)LV_GRAD_DIR_NONE) ?
|
||||||
|
dsc->bg_color : dsc->bg_grad.stops[0].color;
|
||||||
|
if(bg_color.full == dsc->bg_grad.stops[1].color.full)
|
||||||
|
grad_dir = LV_GRAD_DIR_NONE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Most simple case: just a plain rectangle (no mask, no radius, no gradient)
|
||||||
|
* shall be handled by draw_ctx->blend().
|
||||||
|
*
|
||||||
|
* Complex case: gradient or radius but no mask.
|
||||||
|
*/
|
||||||
|
if(!mask_any && ((dsc->radius != 0) || (grad_dir != (lv_grad_dir_t)LV_GRAD_DIR_NONE))) {
|
||||||
|
lv_res_t res = lv_gpu_nxp_vglite_draw_bg(&rel_coords, &rel_clip_area, dsc);
|
||||||
|
if(res != LV_RES_OK)
|
||||||
|
VG_LITE_LOG_TRACE("VG-Lite draw bg failed. Fallback.");
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LV_RES_INV;
|
||||||
|
}
|
||||||
|
|
||||||
|
static lv_res_t lv_draw_vglite_border(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc,
|
||||||
|
const lv_area_t * coords)
|
||||||
|
{
|
||||||
|
if(dsc->border_opa <= (lv_opa_t)LV_OPA_MIN)
|
||||||
|
return LV_RES_INV;
|
||||||
|
if(dsc->border_width == 0)
|
||||||
|
return LV_RES_INV;
|
||||||
|
if(dsc->border_post)
|
||||||
|
return LV_RES_INV;
|
||||||
|
if(dsc->border_side != (lv_border_side_t)LV_BORDER_SIDE_FULL)
|
||||||
|
return LV_RES_INV;
|
||||||
|
|
||||||
|
lv_area_t rel_coords;
|
||||||
|
lv_coord_t border_width = dsc->border_width;
|
||||||
|
|
||||||
|
/* Move border inwards to align with software rendered border */
|
||||||
|
rel_coords.x1 = coords->x1 + ceil(border_width / 2.0f);
|
||||||
|
rel_coords.x2 = coords->x2 - floor(border_width / 2.0f);
|
||||||
|
rel_coords.y1 = coords->y1 + ceil(border_width / 2.0f);
|
||||||
|
rel_coords.y2 = coords->y2 - floor(border_width / 2.0f);
|
||||||
|
|
||||||
|
/* Make coordinates relative to the draw buffer */
|
||||||
|
lv_area_move(&rel_coords, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
|
||||||
|
|
||||||
|
lv_area_t rel_clip_area;
|
||||||
|
lv_area_copy(&rel_clip_area, draw_ctx->clip_area);
|
||||||
|
lv_area_move(&rel_clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
|
||||||
|
|
||||||
|
lv_res_t res = lv_gpu_nxp_vglite_draw_border_generic(&rel_coords, &rel_clip_area, dsc, true);
|
||||||
|
if(res != LV_RES_OK)
|
||||||
|
VG_LITE_LOG_TRACE("VG-Lite draw border failed. Fallback.");
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static lv_res_t lv_draw_vglite_outline(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc,
|
||||||
|
const lv_area_t * coords)
|
||||||
|
{
|
||||||
|
if(dsc->outline_opa <= (lv_opa_t)LV_OPA_MIN)
|
||||||
|
return LV_RES_INV;
|
||||||
|
if(dsc->outline_width == 0)
|
||||||
|
return LV_RES_INV;
|
||||||
|
|
||||||
|
/* Move outline outwards to align with software rendered outline */
|
||||||
|
lv_coord_t outline_pad = dsc->outline_pad - 1;
|
||||||
|
lv_area_t rel_coords;
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* Make coordinates relative to the draw buffer */
|
||||||
|
lv_area_move(&rel_coords, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
|
||||||
|
|
||||||
|
lv_area_t rel_clip_area;
|
||||||
|
lv_area_copy(&rel_clip_area, draw_ctx->clip_area);
|
||||||
|
lv_area_move(&rel_clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
|
||||||
|
|
||||||
|
lv_res_t res = lv_gpu_nxp_vglite_draw_border_generic(&rel_coords, &rel_clip_area, dsc, false);
|
||||||
|
if(res != LV_RES_OK)
|
||||||
|
VG_LITE_LOG_TRACE("VG-Lite draw outline failed. Fallback.");
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lv_draw_vglite_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center,
|
||||||
|
uint16_t radius, uint16_t start_angle, uint16_t end_angle)
|
||||||
|
{
|
||||||
|
bool done = false;
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_MASKS
|
||||||
|
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
|
||||||
|
return;
|
||||||
|
if(dsc->width == 0)
|
||||||
|
return;
|
||||||
|
if(start_angle == end_angle)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(need_argb8565_support(draw_ctx)) {
|
||||||
|
lv_draw_sw_arc(draw_ctx, dsc, center, radius, start_angle, end_angle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make coordinates relative to the draw buffer */
|
||||||
|
lv_point_t rel_center = {center->x - draw_ctx->buf_area->x1, center->y - draw_ctx->buf_area->y1};
|
||||||
|
|
||||||
|
lv_area_t rel_clip_area;
|
||||||
|
lv_area_copy(&rel_clip_area, draw_ctx->clip_area);
|
||||||
|
lv_area_move(&rel_clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
|
||||||
|
|
||||||
|
done = (lv_gpu_nxp_vglite_draw_arc(&rel_center, (int32_t)radius, (int32_t)start_angle, (int32_t)end_angle,
|
||||||
|
&rel_clip_area, dsc) == LV_RES_OK);
|
||||||
|
if(!done)
|
||||||
|
VG_LITE_LOG_TRACE("VG-Lite draw arc failed. Fallback.");
|
||||||
|
#endif/*LV_USE_DRAW_MASKS*/
|
||||||
|
|
||||||
|
if(!done)
|
||||||
|
lv_draw_sw_arc(draw_ctx, dsc, center, radius, start_angle, end_angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /*LV_USE_GPU_NXP_VG_LITE*/
|
||||||
72
src/draw/nxp/vglite/lv_draw_vglite.h
Normal file
72
src/draw/nxp/vglite/lv_draw_vglite.h
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_draw_vglite.h
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright 2022, 2023 NXP
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next paragraph)
|
||||||
|
* shall be included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||||
|
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||||
|
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LV_DRAW_VGLITE_H
|
||||||
|
#define LV_DRAW_VGLITE_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "../../../lv_conf_internal.h"
|
||||||
|
|
||||||
|
#if LV_USE_GPU_NXP_VG_LITE
|
||||||
|
#include "../../sw/lv_draw_sw.h"
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
typedef lv_draw_sw_ctx_t lv_draw_vglite_ctx_t;
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
void lv_draw_vglite_ctx_init(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
|
||||||
|
|
||||||
|
void lv_draw_vglite_ctx_deinit(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
#endif /*LV_USE_GPU_NXP_VG_LITE*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /*extern "C"*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*LV_DRAW_VGLITE_H*/
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
/**
|
/**
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright 2021, 2022 NXP
|
* Copyright 2021-2023 NXP
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -34,7 +34,8 @@
|
|||||||
#include "lv_draw_vglite_arc.h"
|
#include "lv_draw_vglite_arc.h"
|
||||||
|
|
||||||
#if LV_USE_GPU_NXP_VG_LITE
|
#if LV_USE_GPU_NXP_VG_LITE
|
||||||
#include "math.h"
|
#include "lv_vglite_buf.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
/*********************
|
/*********************
|
||||||
* DEFINES
|
* DEFINES
|
||||||
@@ -88,7 +89,7 @@ typedef struct _cubic_cont_pt {
|
|||||||
|
|
||||||
static void rotate_point(int32_t angle, int32_t * x, int32_t * y);
|
static void rotate_point(int32_t angle, int32_t * x, int32_t * y);
|
||||||
static void add_arc_path(int32_t * arc_path, int * pidx, int32_t radius,
|
static void add_arc_path(int32_t * arc_path, int * pidx, int32_t radius,
|
||||||
int32_t start_angle, int32_t end_angle, lv_point_t center, bool cw);
|
int32_t start_angle, int32_t end_angle, const lv_point_t * center, bool cw);
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* STATIC VARIABLES
|
* STATIC VARIABLES
|
||||||
@@ -102,31 +103,20 @@ static void add_arc_path(int32_t * arc_path, int * pidx, int32_t radius,
|
|||||||
* GLOBAL FUNCTIONS
|
* GLOBAL FUNCTIONS
|
||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
lv_res_t lv_gpu_nxp_vglite_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center,
|
lv_res_t lv_gpu_nxp_vglite_draw_arc(const lv_point_t * center, int32_t radius, int32_t start_angle, int32_t end_angle,
|
||||||
int32_t radius, int32_t start_angle, int32_t end_angle)
|
const lv_area_t * clip_area, const lv_draw_arc_dsc_t * dsc)
|
||||||
{
|
{
|
||||||
|
|
||||||
vg_lite_buffer_t vgbuf;
|
|
||||||
vg_lite_error_t err = VG_LITE_SUCCESS;
|
vg_lite_error_t err = VG_LITE_SUCCESS;
|
||||||
lv_color32_t col32 = {.full = lv_color_to32(dsc->color)}; /*Convert color to RGBA8888*/
|
lv_color32_t col32 = {.full = lv_color_to32(dsc->color)}; /*Convert color to RGBA8888*/
|
||||||
lv_coord_t dest_width = lv_area_get_width(draw_ctx->buf_area);
|
|
||||||
lv_coord_t dest_height = lv_area_get_height(draw_ctx->buf_area);
|
|
||||||
vg_lite_path_t path;
|
vg_lite_path_t path;
|
||||||
vg_lite_color_t vgcol; /* vglite takes ABGR */
|
vg_lite_color_t vgcol; /* vglite takes ABGR */
|
||||||
vg_lite_matrix_t matrix;
|
|
||||||
lv_opa_t opa = dsc->opa;
|
|
||||||
bool donut = ((end_angle - start_angle) % 360 == 0) ? true : false;
|
bool donut = ((end_angle - start_angle) % 360 == 0) ? true : false;
|
||||||
lv_point_t clip_center = {center->x - draw_ctx->buf_area->x1, center->y - draw_ctx->buf_area->y1};
|
vg_lite_buffer_t * vgbuf = lv_vglite_get_dest_buf();
|
||||||
|
|
||||||
/* path: max size = 16 cubic bezier (7 words each) */
|
/* path: max size = 16 cubic bezier (7 words each) */
|
||||||
int32_t arc_path[16 * 7];
|
int32_t arc_path[16 * 7];
|
||||||
lv_memzero(arc_path, sizeof(arc_path));
|
lv_memzero(arc_path, sizeof(arc_path));
|
||||||
|
|
||||||
/*** Init destination buffer ***/
|
|
||||||
if(lv_vglite_init_buf(&vgbuf, (uint32_t)dest_width, (uint32_t)dest_height, (uint32_t)dest_width * sizeof(lv_color_t),
|
|
||||||
(const lv_color_t *)draw_ctx->buf, false) != LV_RES_OK)
|
|
||||||
VG_LITE_RETURN_INV("Init buffer failed.");
|
|
||||||
|
|
||||||
/*** Init path ***/
|
/*** Init path ***/
|
||||||
lv_coord_t width = dsc->width; /* inner arc radius = outer arc radius - width */
|
lv_coord_t width = dsc->width; /* inner arc radius = outer arc radius - width */
|
||||||
if(width > (lv_coord_t)radius)
|
if(width > (lv_coord_t)radius)
|
||||||
@@ -140,11 +130,11 @@ lv_res_t lv_gpu_nxp_vglite_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_
|
|||||||
cp_y = 0;
|
cp_y = 0;
|
||||||
rotate_point(start_angle, &cp_x, &cp_y);
|
rotate_point(start_angle, &cp_x, &cp_y);
|
||||||
arc_path[pidx++] = VLC_OP_MOVE;
|
arc_path[pidx++] = VLC_OP_MOVE;
|
||||||
arc_path[pidx++] = clip_center.x + cp_x;
|
arc_path[pidx++] = center->x + cp_x;
|
||||||
arc_path[pidx++] = clip_center.y + cp_y;
|
arc_path[pidx++] = center->y + cp_y;
|
||||||
|
|
||||||
/* draw 1-5 outer quarters */
|
/* draw 1-5 outer quarters */
|
||||||
add_arc_path(arc_path, &pidx, radius, start_angle, end_angle, clip_center, true);
|
add_arc_path(arc_path, &pidx, radius, start_angle, end_angle, center, true);
|
||||||
|
|
||||||
if(donut) {
|
if(donut) {
|
||||||
/* close outer circle */
|
/* close outer circle */
|
||||||
@@ -152,24 +142,24 @@ lv_res_t lv_gpu_nxp_vglite_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_
|
|||||||
cp_y = 0;
|
cp_y = 0;
|
||||||
rotate_point(start_angle, &cp_x, &cp_y);
|
rotate_point(start_angle, &cp_x, &cp_y);
|
||||||
arc_path[pidx++] = VLC_OP_LINE;
|
arc_path[pidx++] = VLC_OP_LINE;
|
||||||
arc_path[pidx++] = clip_center.x + cp_x;
|
arc_path[pidx++] = center->x + cp_x;
|
||||||
arc_path[pidx++] = clip_center.y + cp_y;
|
arc_path[pidx++] = center->y + cp_y;
|
||||||
/* start inner circle */
|
/* start inner circle */
|
||||||
cp_x = radius - width;
|
cp_x = radius - width;
|
||||||
cp_y = 0;
|
cp_y = 0;
|
||||||
rotate_point(start_angle, &cp_x, &cp_y);
|
rotate_point(start_angle, &cp_x, &cp_y);
|
||||||
arc_path[pidx++] = VLC_OP_MOVE;
|
arc_path[pidx++] = VLC_OP_MOVE;
|
||||||
arc_path[pidx++] = clip_center.x + cp_x;
|
arc_path[pidx++] = center->x + cp_x;
|
||||||
arc_path[pidx++] = clip_center.y + cp_y;
|
arc_path[pidx++] = center->y + cp_y;
|
||||||
|
|
||||||
}
|
}
|
||||||
else if(dsc->rounded != 0U) { /* 1st rounded arc ending */
|
else if(dsc->rounded != 0U) { /* 1st rounded arc ending */
|
||||||
cp_x = radius - width / 2;
|
cp_x = radius - width / 2;
|
||||||
cp_y = 0;
|
cp_y = 0;
|
||||||
rotate_point(end_angle, &cp_x, &cp_y);
|
rotate_point(end_angle, &cp_x, &cp_y);
|
||||||
lv_point_t round_center = {clip_center.x + cp_x, clip_center.y + 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),
|
add_arc_path(arc_path, &pidx, width / 2, end_angle, (end_angle + 180),
|
||||||
round_center, true);
|
&round_center, true);
|
||||||
|
|
||||||
}
|
}
|
||||||
else { /* 1st flat ending */
|
else { /* 1st flat ending */
|
||||||
@@ -177,12 +167,12 @@ lv_res_t lv_gpu_nxp_vglite_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_
|
|||||||
cp_y = 0;
|
cp_y = 0;
|
||||||
rotate_point(end_angle, &cp_x, &cp_y);
|
rotate_point(end_angle, &cp_x, &cp_y);
|
||||||
arc_path[pidx++] = VLC_OP_LINE;
|
arc_path[pidx++] = VLC_OP_LINE;
|
||||||
arc_path[pidx++] = clip_center.x + cp_x;
|
arc_path[pidx++] = center->x + cp_x;
|
||||||
arc_path[pidx++] = clip_center.y + cp_y;
|
arc_path[pidx++] = center->y + cp_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* draw 1-5 inner quarters */
|
/* draw 1-5 inner quarters */
|
||||||
add_arc_path(arc_path, &pidx, radius - width, start_angle, end_angle, clip_center, false);
|
add_arc_path(arc_path, &pidx, radius - width, start_angle, end_angle, center, false);
|
||||||
|
|
||||||
/* last control point of curve */
|
/* last control point of curve */
|
||||||
if(donut) { /* close the loop */
|
if(donut) { /* close the loop */
|
||||||
@@ -190,17 +180,17 @@ lv_res_t lv_gpu_nxp_vglite_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_
|
|||||||
cp_y = 0;
|
cp_y = 0;
|
||||||
rotate_point(start_angle, &cp_x, &cp_y);
|
rotate_point(start_angle, &cp_x, &cp_y);
|
||||||
arc_path[pidx++] = VLC_OP_LINE;
|
arc_path[pidx++] = VLC_OP_LINE;
|
||||||
arc_path[pidx++] = clip_center.x + cp_x;
|
arc_path[pidx++] = center->x + cp_x;
|
||||||
arc_path[pidx++] = clip_center.y + cp_y;
|
arc_path[pidx++] = center->y + cp_y;
|
||||||
|
|
||||||
}
|
}
|
||||||
else if(dsc->rounded != 0U) { /* 2nd rounded arc ending */
|
else if(dsc->rounded != 0U) { /* 2nd rounded arc ending */
|
||||||
cp_x = radius - width / 2;
|
cp_x = radius - width / 2;
|
||||||
cp_y = 0;
|
cp_y = 0;
|
||||||
rotate_point(start_angle, &cp_x, &cp_y);
|
rotate_point(start_angle, &cp_x, &cp_y);
|
||||||
lv_point_t round_center = {clip_center.x + cp_x, clip_center.y + 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),
|
add_arc_path(arc_path, &pidx, width / 2, (start_angle + 180), (start_angle + 360),
|
||||||
round_center, true);
|
&round_center, true);
|
||||||
|
|
||||||
}
|
}
|
||||||
else { /* 2nd flat ending */
|
else { /* 2nd flat ending */
|
||||||
@@ -208,46 +198,30 @@ lv_res_t lv_gpu_nxp_vglite_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_
|
|||||||
cp_y = 0;
|
cp_y = 0;
|
||||||
rotate_point(start_angle, &cp_x, &cp_y);
|
rotate_point(start_angle, &cp_x, &cp_y);
|
||||||
arc_path[pidx++] = VLC_OP_LINE;
|
arc_path[pidx++] = VLC_OP_LINE;
|
||||||
arc_path[pidx++] = clip_center.x + cp_x;
|
arc_path[pidx++] = center->x + cp_x;
|
||||||
arc_path[pidx++] = clip_center.y + cp_y;
|
arc_path[pidx++] = center->y + cp_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
arc_path[pidx++] = VLC_OP_END;
|
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,
|
err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, (uint32_t)pidx * sizeof(int32_t), arc_path,
|
||||||
(vg_lite_float_t) draw_ctx->clip_area->x1, (vg_lite_float_t) draw_ctx->clip_area->y1,
|
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
|
||||||
((vg_lite_float_t) draw_ctx->clip_area->x2) + 1.0f, ((vg_lite_float_t) draw_ctx->clip_area->y2) + 1.0f);
|
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f);
|
||||||
VG_LITE_ERR_RETURN_INV(err, "Init path failed.");
|
VG_LITE_ERR_RETURN_INV(err, "Init path failed.");
|
||||||
|
|
||||||
/* set rotation angle */
|
vg_lite_buffer_format_t color_format = LV_COLOR_DEPTH == 16 ? VG_LITE_BGRA8888 : VG_LITE_ABGR8888;
|
||||||
|
if(lv_vglite_premult_and_swizzle(&vgcol, col32, dsc->opa, color_format) != LV_RES_OK)
|
||||||
|
VG_LITE_RETURN_INV("Premultiplication and swizzle failed.");
|
||||||
|
|
||||||
|
vg_lite_matrix_t matrix;
|
||||||
vg_lite_identity(&matrix);
|
vg_lite_identity(&matrix);
|
||||||
|
|
||||||
if(opa <= (lv_opa_t)LV_OPA_MAX) {
|
|
||||||
/* Only pre-multiply color if hardware pre-multiplication is not present */
|
|
||||||
if(!vg_lite_query_feature(gcFEATURE_BIT_VG_PE_PREMULTIPLY)) {
|
|
||||||
col32.ch.red = (uint8_t)(((uint16_t)col32.ch.red * opa) >> 8);
|
|
||||||
col32.ch.green = (uint8_t)(((uint16_t)col32.ch.green * opa) >> 8);
|
|
||||||
col32.ch.blue = (uint8_t)(((uint16_t)col32.ch.blue * opa) >> 8);
|
|
||||||
}
|
|
||||||
col32.ch.alpha = opa;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if LV_COLOR_DEPTH==16
|
|
||||||
vgcol = col32.full;
|
|
||||||
#else /*LV_COLOR_DEPTH==32*/
|
|
||||||
vgcol = ((uint32_t)col32.ch.alpha << 24) | ((uint32_t)col32.ch.blue << 16) | ((uint32_t)col32.ch.green << 8) |
|
|
||||||
(uint32_t)col32.ch.red;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*Clean & invalidate cache*/
|
|
||||||
lv_vglite_invalidate_cache();
|
|
||||||
|
|
||||||
/*** Draw arc ***/
|
/*** Draw arc ***/
|
||||||
err = vg_lite_draw(&vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol);
|
err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol);
|
||||||
VG_LITE_ERR_RETURN_INV(err, "Draw arc failed.");
|
VG_LITE_ERR_RETURN_INV(err, "Draw arc failed.");
|
||||||
|
|
||||||
err = vg_lite_finish();
|
if(lv_vglite_run() != LV_RES_OK)
|
||||||
VG_LITE_ERR_RETURN_INV(err, "Finish failed.");
|
VG_LITE_RETURN_INV("Run failed.");
|
||||||
|
|
||||||
err = vg_lite_clear_path(&path);
|
err = vg_lite_clear_path(&path);
|
||||||
VG_LITE_ERR_RETURN_INV(err, "Clear path failed.");
|
VG_LITE_ERR_RETURN_INV(err, "Clear path failed.");
|
||||||
@@ -564,50 +538,50 @@ static void get_arc_control_points(vg_arc * arc, bool start)
|
|||||||
* center: (in) the center of the circle in draw coordinates
|
* center: (in) the center of the circle in draw coordinates
|
||||||
* cw: (in) true if arc is clockwise
|
* cw: (in) true if arc is clockwise
|
||||||
*/
|
*/
|
||||||
static void add_split_arc_path(int32_t * arc_path, int * pidx, vg_arc * q_arc, lv_point_t center, bool cw)
|
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[] */
|
/* assumes first control point already in array arc_path[] */
|
||||||
int idx = *pidx;
|
int idx = *pidx;
|
||||||
if(cw) {
|
if(cw) {
|
||||||
#if BEZIER_DBG_CONTROL_POINTS
|
#if BEZIER_DBG_CONTROL_POINTS
|
||||||
arc_path[idx++] = VLC_OP_LINE;
|
arc_path[idx++] = VLC_OP_LINE;
|
||||||
arc_path[idx++] = q_arc->p1x + center.x;
|
arc_path[idx++] = q_arc->p1x + center->x;
|
||||||
arc_path[idx++] = q_arc->p1y + center.y;
|
arc_path[idx++] = q_arc->p1y + center->y;
|
||||||
arc_path[idx++] = VLC_OP_LINE;
|
arc_path[idx++] = VLC_OP_LINE;
|
||||||
arc_path[idx++] = q_arc->p2x + center.x;
|
arc_path[idx++] = q_arc->p2x + center->x;
|
||||||
arc_path[idx++] = q_arc->p2y + center.y;
|
arc_path[idx++] = q_arc->p2y + center->y;
|
||||||
arc_path[idx++] = VLC_OP_LINE;
|
arc_path[idx++] = VLC_OP_LINE;
|
||||||
arc_path[idx++] = q_arc->p3x + center.x;
|
arc_path[idx++] = q_arc->p3x + center->x;
|
||||||
arc_path[idx++] = q_arc->p3y + center.y;
|
arc_path[idx++] = q_arc->p3y + center->y;
|
||||||
#else
|
#else
|
||||||
arc_path[idx++] = VLC_OP_CUBIC;
|
arc_path[idx++] = VLC_OP_CUBIC;
|
||||||
arc_path[idx++] = q_arc->p1x + center.x;
|
arc_path[idx++] = q_arc->p1x + center->x;
|
||||||
arc_path[idx++] = q_arc->p1y + center.y;
|
arc_path[idx++] = q_arc->p1y + center->y;
|
||||||
arc_path[idx++] = q_arc->p2x + center.x;
|
arc_path[idx++] = q_arc->p2x + center->x;
|
||||||
arc_path[idx++] = q_arc->p2y + center.y;
|
arc_path[idx++] = q_arc->p2y + center->y;
|
||||||
arc_path[idx++] = q_arc->p3x + center.x;
|
arc_path[idx++] = q_arc->p3x + center->x;
|
||||||
arc_path[idx++] = q_arc->p3y + center.y;
|
arc_path[idx++] = q_arc->p3y + center->y;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else { /* reverse points order when counter-clockwise */
|
else { /* reverse points order when counter-clockwise */
|
||||||
#if BEZIER_DBG_CONTROL_POINTS
|
#if BEZIER_DBG_CONTROL_POINTS
|
||||||
arc_path[idx++] = VLC_OP_LINE;
|
arc_path[idx++] = VLC_OP_LINE;
|
||||||
arc_path[idx++] = q_arc->p2x + center.x;
|
arc_path[idx++] = q_arc->p2x + center->x;
|
||||||
arc_path[idx++] = q_arc->p2y + center.y;
|
arc_path[idx++] = q_arc->p2y + center->y;
|
||||||
arc_path[idx++] = VLC_OP_LINE;
|
arc_path[idx++] = VLC_OP_LINE;
|
||||||
arc_path[idx++] = q_arc->p1x + center.x;
|
arc_path[idx++] = q_arc->p1x + center->x;
|
||||||
arc_path[idx++] = q_arc->p1y + center.y;
|
arc_path[idx++] = q_arc->p1y + center->y;
|
||||||
arc_path[idx++] = VLC_OP_LINE;
|
arc_path[idx++] = VLC_OP_LINE;
|
||||||
arc_path[idx++] = q_arc->p0x + center.x;
|
arc_path[idx++] = q_arc->p0x + center->x;
|
||||||
arc_path[idx++] = q_arc->p0y + center.y;
|
arc_path[idx++] = q_arc->p0y + center->y;
|
||||||
#else
|
#else
|
||||||
arc_path[idx++] = VLC_OP_CUBIC;
|
arc_path[idx++] = VLC_OP_CUBIC;
|
||||||
arc_path[idx++] = q_arc->p2x + center.x;
|
arc_path[idx++] = q_arc->p2x + center->x;
|
||||||
arc_path[idx++] = q_arc->p2y + center.y;
|
arc_path[idx++] = q_arc->p2y + center->y;
|
||||||
arc_path[idx++] = q_arc->p1x + center.x;
|
arc_path[idx++] = q_arc->p1x + center->x;
|
||||||
arc_path[idx++] = q_arc->p1y + center.y;
|
arc_path[idx++] = q_arc->p1y + center->y;
|
||||||
arc_path[idx++] = q_arc->p0x + center.x;
|
arc_path[idx++] = q_arc->p0x + center->x;
|
||||||
arc_path[idx++] = q_arc->p0y + center.y;
|
arc_path[idx++] = q_arc->p0y + center->y;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
/* update index i n path array*/
|
/* update index i n path array*/
|
||||||
@@ -615,7 +589,7 @@ static void add_split_arc_path(int32_t * arc_path, int * pidx, vg_arc * q_arc, l
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void add_arc_path(int32_t * arc_path, int * pidx, int32_t radius,
|
static void add_arc_path(int32_t * arc_path, int * pidx, int32_t radius,
|
||||||
int32_t start_angle, int32_t end_angle, lv_point_t center, bool cw)
|
int32_t start_angle, int32_t end_angle, const lv_point_t * center, bool cw)
|
||||||
{
|
{
|
||||||
/* set number of arcs to draw */
|
/* set number of arcs to draw */
|
||||||
vg_arc q_arc;
|
vg_arc q_arc;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/**
|
/**
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright 2021, 2022 NXP
|
* Copyright 2021-2023 NXP
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -40,7 +40,7 @@ extern "C" {
|
|||||||
#include "../../../lv_conf_internal.h"
|
#include "../../../lv_conf_internal.h"
|
||||||
|
|
||||||
#if LV_USE_GPU_NXP_VG_LITE
|
#if LV_USE_GPU_NXP_VG_LITE
|
||||||
#include "lv_gpu_nxp_vglite.h"
|
#include "lv_vglite_utils.h"
|
||||||
|
|
||||||
/*********************
|
/*********************
|
||||||
* DEFINES
|
* DEFINES
|
||||||
@@ -54,17 +54,21 @@ extern "C" {
|
|||||||
* GLOBAL PROTOTYPES
|
* GLOBAL PROTOTYPES
|
||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
/***
|
/**
|
||||||
* Draw arc shape with effects
|
* Draw arc shape with effects
|
||||||
* @param draw_ctx drawing context
|
*
|
||||||
* @param dsc the arc description structure (width, rounded ending, opacity)
|
* @param[in] center Arc center with relative coordinates
|
||||||
* @param center the coordinates of the arc center
|
* @param[in] radius Radius of external arc
|
||||||
* @param radius the radius of external arc
|
* @param[in] start_angle Starting angle in degrees
|
||||||
* @param start_angle the starting angle in degrees
|
* @param[in] end_angle Ending angle in degrees
|
||||||
* @param end_angle the ending angle in degrees
|
* @param[in] clip_area Clipping area with relative coordinates to dest buff
|
||||||
|
* @param[in] dsc Arc description structure (width, rounded ending, opacity)
|
||||||
|
*
|
||||||
|
* @retval LV_RES_OK Draw completed
|
||||||
|
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
|
||||||
*/
|
*/
|
||||||
lv_res_t lv_gpu_nxp_vglite_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center,
|
lv_res_t lv_gpu_nxp_vglite_draw_arc(const lv_point_t * center, int32_t radius, int32_t start_angle, int32_t end_angle,
|
||||||
int32_t radius, int32_t start_angle, int32_t end_angle);
|
const lv_area_t * clip_area, const lv_draw_arc_dsc_t * dsc);
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* MACROS
|
* MACROS
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/**
|
/**
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright 2020-2022 NXP
|
* Copyright 2020-2023 NXP
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -34,12 +34,19 @@
|
|||||||
#include "lv_draw_vglite_blend.h"
|
#include "lv_draw_vglite_blend.h"
|
||||||
|
|
||||||
#if LV_USE_GPU_NXP_VG_LITE
|
#if LV_USE_GPU_NXP_VG_LITE
|
||||||
|
#include "lv_vglite_buf.h"
|
||||||
|
|
||||||
/*********************
|
/*********************
|
||||||
* DEFINES
|
* DEFINES
|
||||||
*********************/
|
*********************/
|
||||||
|
|
||||||
/* Enable BLIT quality degradation workaround for RT595, recommended for screen's dimension > 352 pixels */
|
/** Stride in px required by VG-Lite HW*/
|
||||||
|
#define LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX 16U
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable BLIT quality degradation workaround for RT595,
|
||||||
|
* recommended for screen's dimension > 352 pixels.
|
||||||
|
*/
|
||||||
#define RT595_BLIT_WRKRND_ENABLED 1
|
#define RT595_BLIT_WRKRND_ENABLED 1
|
||||||
|
|
||||||
/* Internal compound symbol */
|
/* Internal compound symbol */
|
||||||
@@ -51,12 +58,13 @@
|
|||||||
#define VG_LITE_BLIT_SPLIT_ENABLED 0
|
#define VG_LITE_BLIT_SPLIT_ENABLED 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
#if VG_LITE_BLIT_SPLIT_ENABLED
|
||||||
* BLIT split threshold - BLITs with width or height higher than this value will be done
|
/**
|
||||||
* in multiple steps. Value must be 16-aligned. Don't change.
|
* BLIT split threshold - BLITs with width or height higher than this value will be done
|
||||||
*/
|
* in multiple steps. Value must be 16-aligned. Don't change.
|
||||||
#define LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR 352
|
*/
|
||||||
|
#define LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR 352
|
||||||
|
#endif
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* TYPEDEFS
|
* TYPEDEFS
|
||||||
@@ -67,63 +75,87 @@
|
|||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BLock Image Transfer - single direct BLIT.
|
* Blit single image, with optional opacity.
|
||||||
|
*
|
||||||
|
* @param[in] dest_area Area with relative coordinates of destination buffer
|
||||||
|
* @param[in] src_area Source area with relative coordinates of source buffer
|
||||||
|
* @param[in] opa Opacity
|
||||||
*
|
*
|
||||||
* @param[in] blit Description of the transfer
|
|
||||||
* @retval LV_RES_OK Transfer complete
|
* @retval LV_RES_OK Transfer complete
|
||||||
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
|
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
|
||||||
*/
|
*/
|
||||||
static lv_res_t _lv_gpu_nxp_vglite_blit_single(lv_gpu_nxp_vglite_blit_info_t * blit);
|
static lv_res_t lv_vglite_blit_single(const lv_area_t * dest_area, const lv_area_t * src_area, lv_opa_t opa);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check source memory and stride alignment.
|
||||||
|
*
|
||||||
|
* @param[in] src_buf Source buffer
|
||||||
|
* @param[in] src_stride Stride of source buffer in pixels
|
||||||
|
*
|
||||||
|
* @retval LV_RES_OK Alignment OK
|
||||||
|
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
|
||||||
|
*/
|
||||||
|
static lv_res_t check_src_alignment(const lv_color_t * src_buf, lv_coord_t src_stride);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates matrix that translates to origin of given destination area.
|
||||||
|
*
|
||||||
|
* @param[in] dest_area Area with relative coordinates of destination buffer
|
||||||
|
*/
|
||||||
|
static inline void lv_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
|
||||||
|
*/
|
||||||
|
static inline void lv_vglite_set_transformation_matrix(const lv_area_t * dest_area, const lv_draw_img_dsc_t * dsc);
|
||||||
|
|
||||||
#if VG_LITE_BLIT_SPLIT_ENABLED
|
#if VG_LITE_BLIT_SPLIT_ENABLED
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move buffer pointer as close as possible to area, but with respect to alignment requirements. X-axis only.
|
* Move buffer pointer as close as possible to area, but with respect to alignment requirements. X-axis only.
|
||||||
*
|
*
|
||||||
* @param[in,out] area Area to be updated
|
* @param[in/out] area Area to be updated
|
||||||
* @param[in,out] buf Pointer to be updated
|
* @param[in/out] buf Pointer to be updated
|
||||||
*/
|
*/
|
||||||
static void _align_x(lv_area_t * area, lv_color_t ** buf);
|
static void align_x(lv_area_t * area, lv_color_t ** buf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move buffer pointer to the area start and update variables, Y-axis only.
|
* Move buffer pointer to the area start and update variables, Y-axis only.
|
||||||
*
|
*
|
||||||
* @param[in,out] area Area to be updated
|
* @param[in/out] area Area to be updated
|
||||||
* @param[in,out] buf Pointer to be updated
|
* @param[in/out] buf Pointer to be updated
|
||||||
* @param[in] stridePx Buffer stride in pixels
|
* @param[in] stride Buffer stride in pixels
|
||||||
*/
|
*/
|
||||||
static void _align_y(lv_area_t * area, lv_color_t ** buf, uint32_t stridePx);
|
static void align_y(lv_area_t * area, lv_color_t ** buf, lv_coord_t stride);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Software BLIT as a fall-back scenario.
|
* Blit image split in tiles, with optional opacity.
|
||||||
*
|
*
|
||||||
* @param[in] blit BLIT configuration
|
* @param[in/out] dest_buf Destination buffer
|
||||||
*/
|
* @param[in] dest_area Area with relative coordinates of destination buffer
|
||||||
static void _sw_blit(lv_gpu_nxp_vglite_blit_info_t * blit);
|
* @param[in] dest_stride Stride of destination buffer in pixels
|
||||||
|
* @param[in] src_buf Source buffer
|
||||||
/**
|
* @param[in] src_area Source area with relative coordinates of source buffer
|
||||||
* Verify BLIT structure - widths, stride, pointer alignment
|
* @param[in] src_stride Stride of source buffer in pixels
|
||||||
*
|
* @param[in] opa Opacity
|
||||||
* @param[in] blit BLIT configuration
|
*
|
||||||
* @retval LV_RES_OK
|
* @retval LV_RES_OK Transfer complete
|
||||||
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
|
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
|
||||||
*/
|
*/
|
||||||
static lv_res_t _lv_gpu_nxp_vglite_check_blit(lv_gpu_nxp_vglite_blit_info_t * blit);
|
static lv_res_t lv_vglite_blit_split(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||||
|
const lv_color_t * src_buf, lv_area_t * src_area, lv_coord_t src_stride,
|
||||||
/**
|
lv_opa_t opa);
|
||||||
* BLock Image Transfer - split BLIT.
|
|
||||||
*
|
|
||||||
* @param[in] blit BLIT configuration
|
|
||||||
* @retval LV_RES_OK Transfer complete
|
|
||||||
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
|
|
||||||
*/
|
|
||||||
static lv_res_t _lv_gpu_nxp_vglite_blit_split(lv_gpu_nxp_vglite_blit_info_t * blit);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* STATIC VARIABLES
|
* STATIC VARIABLES
|
||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
|
static vg_lite_matrix_t vgmatrix;
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* MACROS
|
* MACROS
|
||||||
**********************/
|
**********************/
|
||||||
@@ -132,98 +164,57 @@ static lv_res_t _lv_gpu_nxp_vglite_blit_single(lv_gpu_nxp_vglite_blit_info_t * b
|
|||||||
* GLOBAL FUNCTIONS
|
* GLOBAL FUNCTIONS
|
||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
lv_res_t lv_gpu_nxp_vglite_fill(lv_color_t * dest_buf, lv_coord_t dest_width, lv_coord_t dest_height,
|
lv_res_t lv_gpu_nxp_vglite_fill(const lv_area_t * dest_area, lv_color_t color, lv_opa_t opa)
|
||||||
const lv_area_t * fill_area, lv_color_t color, lv_opa_t opa)
|
|
||||||
{
|
{
|
||||||
uint32_t area_size = lv_area_get_size(fill_area);
|
|
||||||
lv_coord_t area_w = lv_area_get_width(fill_area);
|
|
||||||
lv_coord_t area_h = lv_area_get_height(fill_area);
|
|
||||||
|
|
||||||
if(opa >= (lv_opa_t)LV_OPA_MAX) {
|
|
||||||
if(area_size < LV_GPU_NXP_VG_LITE_FILL_SIZE_LIMIT)
|
|
||||||
VG_LITE_RETURN_INV("Area size %d smaller than limit %d.", area_size, LV_GPU_NXP_VG_LITE_FILL_SIZE_LIMIT);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if(area_size < LV_GPU_NXP_VG_LITE_FILL_OPA_SIZE_LIMIT)
|
|
||||||
VG_LITE_RETURN_INV("Area size %d smaller than limit %d.", area_size, LV_GPU_NXP_VG_LITE_FILL_OPA_SIZE_LIMIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
vg_lite_buffer_t vgbuf;
|
|
||||||
vg_lite_rectangle_t rect;
|
|
||||||
vg_lite_error_t err = VG_LITE_SUCCESS;
|
vg_lite_error_t err = VG_LITE_SUCCESS;
|
||||||
lv_color32_t col32 = {.full = lv_color_to32(color)}; /*Convert color to RGBA8888*/
|
lv_color32_t col32 = {.full = lv_color_to32(color)}; /*Convert color to RGBA8888*/
|
||||||
vg_lite_color_t vgcol; /* vglite takes ABGR */
|
vg_lite_color_t vgcol; /* vglite takes ABGR */
|
||||||
|
vg_lite_buffer_t * vgbuf = lv_vglite_get_dest_buf();
|
||||||
|
|
||||||
if(lv_vglite_init_buf(&vgbuf, (uint32_t)dest_width, (uint32_t)dest_height, (uint32_t)dest_width * sizeof(lv_color_t),
|
vg_lite_buffer_format_t color_format = LV_COLOR_DEPTH == 16 ? VG_LITE_BGRA8888 : VG_LITE_ABGR8888;
|
||||||
(const lv_color_t *)dest_buf, false) != LV_RES_OK)
|
if(lv_vglite_premult_and_swizzle(&vgcol, col32, opa, color_format) != LV_RES_OK)
|
||||||
VG_LITE_RETURN_INV("Init buffer failed.");
|
VG_LITE_RETURN_INV("Premultiplication and swizzle failed.");
|
||||||
|
|
||||||
if(opa >= (lv_opa_t)LV_OPA_MAX) { /*Opaque fill*/
|
if(opa >= (lv_opa_t)LV_OPA_MAX) { /*Opaque fill*/
|
||||||
rect.x = fill_area->x1;
|
vg_lite_rectangle_t rect = {
|
||||||
rect.y = fill_area->y1;
|
.x = dest_area->x1,
|
||||||
rect.width = area_w;
|
.y = dest_area->y1,
|
||||||
rect.height = area_h;
|
.width = lv_area_get_width(dest_area),
|
||||||
|
.height = lv_area_get_height(dest_area)
|
||||||
|
};
|
||||||
|
|
||||||
/*Clean & invalidate cache*/
|
err = vg_lite_clear(vgbuf, &rect, vgcol);
|
||||||
lv_vglite_invalidate_cache();
|
|
||||||
|
|
||||||
#if LV_COLOR_DEPTH==16
|
|
||||||
vgcol = col32.full;
|
|
||||||
#else /*LV_COLOR_DEPTH==32*/
|
|
||||||
vgcol = ((uint32_t)col32.ch.alpha << 24) | ((uint32_t)col32.ch.blue << 16) | ((uint32_t)col32.ch.green << 8) |
|
|
||||||
(uint32_t)col32.ch.red;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
err = vg_lite_clear(&vgbuf, &rect, vgcol);
|
|
||||||
VG_LITE_ERR_RETURN_INV(err, "Clear failed.");
|
VG_LITE_ERR_RETURN_INV(err, "Clear failed.");
|
||||||
|
|
||||||
err = vg_lite_finish();
|
if(lv_vglite_run() != LV_RES_OK)
|
||||||
VG_LITE_ERR_RETURN_INV(err, "Finish failed.");
|
VG_LITE_RETURN_INV("Run failed.");
|
||||||
}
|
}
|
||||||
else { /*fill with transparency*/
|
else { /*fill with transparency*/
|
||||||
|
|
||||||
vg_lite_path_t path;
|
vg_lite_path_t path;
|
||||||
int32_t path_data[] = { /*VG rectangular path*/
|
int32_t path_data[] = { /*VG rectangular path*/
|
||||||
VLC_OP_MOVE, fill_area->x1, fill_area->y1,
|
VLC_OP_MOVE, dest_area->x1, dest_area->y1,
|
||||||
VLC_OP_LINE, fill_area->x2 + 1, fill_area->y1,
|
VLC_OP_LINE, dest_area->x2 + 1, dest_area->y1,
|
||||||
VLC_OP_LINE, fill_area->x2 + 1, fill_area->y2 + 1,
|
VLC_OP_LINE, dest_area->x2 + 1, dest_area->y2 + 1,
|
||||||
VLC_OP_LINE, fill_area->x1, fill_area->y2 + 1,
|
VLC_OP_LINE, dest_area->x1, dest_area->y2 + 1,
|
||||||
VLC_OP_LINE, fill_area->x1, fill_area->y1,
|
VLC_OP_LINE, dest_area->x1, dest_area->y1,
|
||||||
VLC_OP_END
|
VLC_OP_END
|
||||||
};
|
};
|
||||||
|
|
||||||
err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_LOW, sizeof(path_data), path_data,
|
err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_LOW, sizeof(path_data), path_data,
|
||||||
(vg_lite_float_t) fill_area->x1, (vg_lite_float_t) fill_area->y1,
|
(vg_lite_float_t) dest_area->x1, (vg_lite_float_t) dest_area->y1,
|
||||||
((vg_lite_float_t) fill_area->x2) + 1.0f, ((vg_lite_float_t) fill_area->y2) + 1.0f);
|
((vg_lite_float_t) dest_area->x2) + 1.0f, ((vg_lite_float_t) dest_area->y2) + 1.0f);
|
||||||
VG_LITE_ERR_RETURN_INV(err, "Init path failed.");
|
VG_LITE_ERR_RETURN_INV(err, "Init path failed.");
|
||||||
|
|
||||||
/* Only pre-multiply color if hardware pre-multiplication is not present */
|
|
||||||
if(!vg_lite_query_feature(gcFEATURE_BIT_VG_PE_PREMULTIPLY)) {
|
|
||||||
col32.ch.red = (uint8_t)(((uint16_t)col32.ch.red * opa) >> 8);
|
|
||||||
col32.ch.green = (uint8_t)(((uint16_t)col32.ch.green * opa) >> 8);
|
|
||||||
col32.ch.blue = (uint8_t)(((uint16_t)col32.ch.blue * opa) >> 8);
|
|
||||||
}
|
|
||||||
col32.ch.alpha = opa;
|
|
||||||
|
|
||||||
#if LV_COLOR_DEPTH==16
|
|
||||||
vgcol = col32.full;
|
|
||||||
#else /*LV_COLOR_DEPTH==32*/
|
|
||||||
vgcol = ((uint32_t)col32.ch.alpha << 24) | ((uint32_t)col32.ch.blue << 16) | ((uint32_t)col32.ch.green << 8) |
|
|
||||||
(uint32_t)col32.ch.red;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*Clean & invalidate cache*/
|
|
||||||
lv_vglite_invalidate_cache();
|
|
||||||
|
|
||||||
vg_lite_matrix_t matrix;
|
vg_lite_matrix_t matrix;
|
||||||
vg_lite_identity(&matrix);
|
vg_lite_identity(&matrix);
|
||||||
|
|
||||||
/*Draw rectangle*/
|
/*Draw rectangle*/
|
||||||
err = vg_lite_draw(&vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol);
|
err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol);
|
||||||
VG_LITE_ERR_RETURN_INV(err, "Draw rectangle failed.");
|
VG_LITE_ERR_RETURN_INV(err, "Draw rectangle failed.");
|
||||||
|
|
||||||
err = vg_lite_finish();
|
if(lv_vglite_run() != LV_RES_OK)
|
||||||
VG_LITE_ERR_RETURN_INV(err, "Finish failed.");
|
VG_LITE_RETURN_INV("Run failed.");
|
||||||
|
|
||||||
err = vg_lite_clear_path(&path);
|
err = vg_lite_clear_path(&path);
|
||||||
VG_LITE_ERR_RETURN_INV(err, "Clear path failed.");
|
VG_LITE_ERR_RETURN_INV(err, "Clear path failed.");
|
||||||
@@ -232,41 +223,64 @@ lv_res_t lv_gpu_nxp_vglite_fill(lv_color_t * dest_buf, lv_coord_t dest_width, lv
|
|||||||
return LV_RES_OK;
|
return LV_RES_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
lv_res_t lv_gpu_nxp_vglite_blit(lv_gpu_nxp_vglite_blit_info_t * blit)
|
lv_res_t lv_gpu_nxp_vglite_blit(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||||
|
const lv_color_t * src_buf, lv_area_t * src_area, lv_coord_t src_stride,
|
||||||
|
lv_opa_t opa)
|
||||||
{
|
{
|
||||||
uint32_t dest_size = lv_area_get_size(&blit->dst_area);
|
/* Set vgmatrix. */
|
||||||
|
lv_vglite_set_translation_matrix(dest_area);
|
||||||
|
|
||||||
if(blit->opa >= (lv_opa_t)LV_OPA_MAX) {
|
/* Set src_vgbuf structure. */
|
||||||
if(dest_size < LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT)
|
lv_vglite_set_src_buf(src_buf, src_area, src_stride);
|
||||||
VG_LITE_RETURN_INV("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if(dest_size < LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT)
|
|
||||||
VG_LITE_RETURN_INV("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if VG_LITE_BLIT_SPLIT_ENABLED
|
#if VG_LITE_BLIT_SPLIT_ENABLED
|
||||||
return _lv_gpu_nxp_vglite_blit_split(blit);
|
lv_color_t * orig_dest_buf = dest_buf;
|
||||||
#endif /* non RT595 */
|
|
||||||
|
|
||||||
/* Just pass down */
|
lv_res_t rv = lv_vglite_blit_split(dest_buf, dest_area, dest_stride, src_buf, src_area, src_stride, opa);
|
||||||
return _lv_gpu_nxp_vglite_blit_single(blit);
|
|
||||||
|
/* Restore the original dest_vgbuf memory address. */
|
||||||
|
lv_vglite_set_dest_buf_ptr(orig_dest_buf);
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
#else
|
||||||
|
LV_UNUSED(dest_buf);
|
||||||
|
LV_UNUSED(dest_stride);
|
||||||
|
|
||||||
|
if(check_src_alignment(src_buf, src_stride) != LV_RES_OK)
|
||||||
|
VG_LITE_RETURN_INV("Check src alignment failed.");
|
||||||
|
|
||||||
|
return lv_vglite_blit_single(dest_area, src_area, opa);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
lv_res_t lv_gpu_nxp_vglite_blit_transform(lv_gpu_nxp_vglite_blit_info_t * blit)
|
lv_res_t lv_gpu_nxp_vglite_blit_transform(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||||
|
const lv_color_t * src_buf, lv_area_t * src_area, lv_coord_t src_stride,
|
||||||
|
const lv_draw_img_dsc_t * dsc)
|
||||||
{
|
{
|
||||||
uint32_t dest_size = lv_area_get_size(&blit->dst_area);
|
/* Set vgmatrix. */
|
||||||
|
lv_vglite_set_transformation_matrix(dest_area, dsc);
|
||||||
|
|
||||||
if(blit->opa >= (lv_opa_t)LV_OPA_MAX) {
|
/* Set src_vgbuf structure. */
|
||||||
if(dest_size < LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT)
|
lv_vglite_set_src_buf(src_buf, src_area, src_stride);
|
||||||
VG_LITE_RETURN_INV("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if(dest_size < LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT)
|
|
||||||
VG_LITE_RETURN_INV("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
return _lv_gpu_nxp_vglite_blit_single(blit);
|
#if VG_LITE_BLIT_SPLIT_ENABLED
|
||||||
|
lv_color_t * orig_dest_buf = dest_buf;
|
||||||
|
|
||||||
|
lv_res_t rv = lv_vglite_blit_split(dest_buf, dest_area, dest_stride, src_buf, src_area, src_stride, dsc->opa);
|
||||||
|
|
||||||
|
/* Restore the original dest_vgbuf memory address. */
|
||||||
|
lv_vglite_set_dest_buf_ptr(orig_dest_buf);
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
#else
|
||||||
|
LV_UNUSED(dest_buf);
|
||||||
|
LV_UNUSED(dest_stride);
|
||||||
|
|
||||||
|
if(check_src_alignment(src_buf, src_stride) != LV_RES_OK)
|
||||||
|
VG_LITE_RETURN_INV("Check src alignment failed.");
|
||||||
|
|
||||||
|
return lv_vglite_blit_single(dest_area, src_area, dsc->opa);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
@@ -274,223 +288,196 @@ lv_res_t lv_gpu_nxp_vglite_blit_transform(lv_gpu_nxp_vglite_blit_info_t * blit)
|
|||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
#if VG_LITE_BLIT_SPLIT_ENABLED
|
#if VG_LITE_BLIT_SPLIT_ENABLED
|
||||||
static lv_res_t _lv_gpu_nxp_vglite_blit_split(lv_gpu_nxp_vglite_blit_info_t * blit)
|
static lv_res_t lv_vglite_blit_split(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||||
|
const lv_color_t * src_buf, lv_area_t * src_area, lv_coord_t src_stride,
|
||||||
|
lv_opa_t opa)
|
||||||
{
|
{
|
||||||
lv_res_t rv = LV_RES_INV;
|
lv_res_t rv = LV_RES_INV;
|
||||||
|
|
||||||
if(_lv_gpu_nxp_vglite_check_blit(blit) != LV_RES_OK) {
|
VG_LITE_LOG_TRACE("Blit "
|
||||||
PRINT_BLT("Blit check failed\n");
|
"Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | "
|
||||||
return LV_RES_INV;
|
"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);
|
||||||
|
|
||||||
PRINT_BLT("BLIT from: "
|
/* Stage 1: Move starting pointers as close as possible to [x1, y1], so coordinates are as small as possible. */
|
||||||
"Area: %03d,%03d - %03d,%03d "
|
align_x(src_area, (lv_color_t **)&src_buf);
|
||||||
"Addr: %d\n\n",
|
align_y(src_area, (lv_color_t **)&src_buf, src_stride);
|
||||||
blit->src_area.x1, blit->src_area.y1,
|
align_x(dest_area, (lv_color_t **)&dest_buf);
|
||||||
blit->src_area.x2, blit->src_area.y2,
|
align_y(dest_area, (lv_color_t **)&dest_buf, dest_stride);
|
||||||
(uintptr_t) blit->src);
|
|
||||||
|
|
||||||
PRINT_BLT("BLIT to: "
|
|
||||||
"Area: %03d,%03d - %03d,%03d "
|
|
||||||
"Addr: %d\n\n",
|
|
||||||
blit->dst_area.x1, blit->dst_area.y1,
|
|
||||||
blit->dst_area.x2, blit->dst_area.y2,
|
|
||||||
(uintptr_t) blit->src);
|
|
||||||
|
|
||||||
/* Stage 1: Move starting pointers as close as possible to [x1, y1], so coordinates are as small as possible. */
|
|
||||||
_align_x(&blit->src_area, (lv_color_t **)&blit->src);
|
|
||||||
_align_y(&blit->src_area, (lv_color_t **)&blit->src, blit->src_stride / sizeof(lv_color_t));
|
|
||||||
_align_x(&blit->dst_area, (lv_color_t **)&blit->dst);
|
|
||||||
_align_y(&blit->dst_area, (lv_color_t **)&blit->dst, blit->dst_stride / sizeof(lv_color_t));
|
|
||||||
|
|
||||||
/* Stage 2: If we're in limit, do a single BLIT */
|
/* Stage 2: If we're in limit, do a single BLIT */
|
||||||
if((blit->src_area.x2 < LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) &&
|
if((src_area->x2 < LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) &&
|
||||||
(blit->src_area.y2 < LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR)) {
|
(src_area->y2 < LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR)) {
|
||||||
PRINT_BLT("Simple blit!\n");
|
if(check_src_alignment(src_buf, src_stride) != LV_RES_OK)
|
||||||
return _lv_gpu_nxp_vglite_blit_single(blit);
|
VG_LITE_RETURN_INV("Check src alignment failed.");
|
||||||
|
|
||||||
|
/* Set new dest_vgbuf and src_vgbuf memory addresses. */
|
||||||
|
lv_vglite_set_dest_buf_ptr(dest_buf);
|
||||||
|
lv_vglite_set_src_buf_ptr(src_buf);
|
||||||
|
|
||||||
|
/* Set vgmatrix. */
|
||||||
|
lv_vglite_set_translation_matrix(dest_area);
|
||||||
|
|
||||||
|
rv = lv_vglite_blit_single(dest_area, src_area, opa);
|
||||||
|
|
||||||
|
VG_LITE_LOG_TRACE("Single "
|
||||||
|
"Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | "
|
||||||
|
"Size: ([%dx%d] -> [%dx%d]) | "
|
||||||
|
"Addr: (0x%x -> 0x%x) %s",
|
||||||
|
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,
|
||||||
|
rv == LV_RES_OK ? "OK!" : "FAILED!");
|
||||||
|
|
||||||
|
return rv;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Stage 3: Split the BLIT into multiple tiles */
|
/* Stage 3: Split the BLIT into multiple tiles */
|
||||||
PRINT_BLT("Split blit!\n");
|
VG_LITE_LOG_TRACE("Split "
|
||||||
|
"Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | "
|
||||||
PRINT_BLT("Blit "
|
"Size: ([%dx%d] -> [%dx%d]) | "
|
||||||
"([%03d,%03d], [%03d,%03d]) -> "
|
"Addr: (0x%x -> 0x%x)",
|
||||||
"([%03d,%03d], [%03d,%03d]) | "
|
src_area->x1, src_area->y1, src_area->x2, src_area->y2,
|
||||||
"([%03dx%03d] -> [%03dx%03d]) | "
|
dest_area->x1, dest_area->y1, dest_area->x2, dest_area->y2,
|
||||||
"A:(%d -> %d)\n",
|
lv_area_get_width(src_area), lv_area_get_height(src_area),
|
||||||
blit->src_area.x1, blit->src_area.y1, blit->src_area.x2, blit->src_area.y2,
|
lv_area_get_width(dest_area), lv_area_get_height(dest_area),
|
||||||
blit->dst_area.x1, blit->dst_area.y1, blit->dst_area.x2, blit->dst_area.y2,
|
(uintptr_t)src_buf, (uintptr_t)dest_buf);
|
||||||
lv_area_get_width(&blit->src_area), lv_area_get_height(&blit->src_area),
|
|
||||||
lv_area_get_width(&blit->dst_area), lv_area_get_height(&blit->dst_area),
|
|
||||||
(uintptr_t) blit->src, (uintptr_t) blit->dst);
|
|
||||||
|
|
||||||
|
|
||||||
lv_coord_t totalWidth = lv_area_get_width(&blit->src_area);
|
lv_coord_t width = lv_area_get_width(src_area);
|
||||||
lv_coord_t totalHeight = lv_area_get_height(&blit->src_area);
|
lv_coord_t height = lv_area_get_height(src_area);
|
||||||
|
|
||||||
lv_gpu_nxp_vglite_blit_info_t tileBlit;
|
|
||||||
|
|
||||||
/* Number of tiles needed */
|
/* Number of tiles needed */
|
||||||
int totalTilesX = (blit->src_area.x1 + totalWidth + LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1) /
|
int total_tiles_x = (src_area->x1 + width + LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1) /
|
||||||
LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR;
|
LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR;
|
||||||
int totalTilesY = (blit->src_area.y1 + totalHeight + LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1) /
|
int total_tiles_y = (src_area->y1 + height + LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1) /
|
||||||
LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR;
|
LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR;
|
||||||
|
|
||||||
/* src and dst buffer shift against each other. Src buffer real data [0,0] may start actually at [3,0] in buffer, as
|
/* src and dst buffer shift against each other. Src buffer real data [0,0] may start actually at [3,0] in buffer, as
|
||||||
* the buffer pointer has to be aligned, while dst buffer real data [0,0] may start at [1,0] in buffer. alignment may be
|
* the buffer pointer has to be aligned, while dst buffer real data [0,0] may start at [1,0] in buffer. alignment may be
|
||||||
* different */
|
* different */
|
||||||
int shiftSrcX = (blit->src_area.x1 > blit->dst_area.x1) ? (blit->src_area.x1 - blit->dst_area.x1) : 0;
|
int shift_src_x = (src_area->x1 > dest_area->x1) ? (src_area->x1 - dest_area->x1) : 0;
|
||||||
int shiftDstX = (blit->src_area.x1 < blit->dst_area.x1) ? (blit->dst_area.x1 - blit->src_area.x1) : 0;
|
int shift_dest_x = (src_area->x1 < dest_area->x1) ? (dest_area->x1 - src_area->x1) : 0;
|
||||||
|
|
||||||
PRINT_BLT("\n");
|
VG_LITE_LOG_TRACE("X shift: src: %d, dst: %d", shift_src_x, shift_dest_x);
|
||||||
PRINT_BLT("Align shift: src: %d, dst: %d\n", shiftSrcX, shiftDstX);
|
|
||||||
|
|
||||||
tileBlit = *blit;
|
lv_color_t * tile_dest_buf;
|
||||||
|
lv_area_t tile_dest_area;
|
||||||
|
const lv_color_t * tile_src_buf;
|
||||||
|
lv_area_t tile_src_area;
|
||||||
|
|
||||||
for(int tileY = 0; tileY < totalTilesY; tileY++) {
|
for(int y = 0; y < total_tiles_y; y++) {
|
||||||
|
|
||||||
tileBlit.src_area.y1 = 0; /* no vertical alignment, always start from 0 */
|
tile_src_area.y1 = 0; /* no vertical alignment, always start from 0 */
|
||||||
tileBlit.src_area.y2 = totalHeight - tileY * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
|
tile_src_area.y2 = height - y * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
|
||||||
if(tileBlit.src_area.y2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) {
|
if(tile_src_area.y2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) {
|
||||||
tileBlit.src_area.y2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; /* Should never happen */
|
tile_src_area.y2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; /* Should never happen */
|
||||||
}
|
}
|
||||||
tileBlit.src = blit->src + tileY * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR * blit->src_stride / sizeof(
|
tile_src_buf = src_buf + y * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR * src_stride;
|
||||||
lv_color_t); /* stride in px! */
|
|
||||||
|
|
||||||
tileBlit.dst_area.y1 = tileBlit.src_area.y1; /* y has no alignment, always in sync with src */
|
tile_dest_area.y1 = tile_src_area.y1; /* y has no alignment, always in sync with src */
|
||||||
tileBlit.dst_area.y2 = tileBlit.src_area.y2;
|
tile_dest_area.y2 = tile_src_area.y2;
|
||||||
|
|
||||||
tileBlit.dst = blit->dst + tileY * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR * blit->dst_stride / sizeof(
|
tile_dest_buf = dest_buf + y * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR * dest_stride;
|
||||||
lv_color_t); /* stride in px! */
|
|
||||||
|
|
||||||
for(int tileX = 0; tileX < totalTilesX; tileX++) {
|
for(int x = 0; x < total_tiles_x; x++) {
|
||||||
|
|
||||||
if(tileX == 0) {
|
if(x == 0) {
|
||||||
/* 1st tile is special - there may be a gap between buffer start pointer
|
/* 1st tile is special - there may be a gap between buffer start pointer
|
||||||
* and area.x1 value, as the pointer has to be aligned.
|
* and area.x1 value, as the pointer has to be aligned.
|
||||||
* tileBlit.src pointer - keep init value from Y-loop.
|
* tile_src_buf pointer - keep init value from Y-loop.
|
||||||
* Also, 1st tile start is not shifted! shift is applied from 2nd tile */
|
* Also, 1st tile start is not shifted! shift is applied from 2nd tile */
|
||||||
tileBlit.src_area.x1 = blit->src_area.x1;
|
tile_src_area.x1 = src_area->x1;
|
||||||
tileBlit.dst_area.x1 = blit->dst_area.x1;
|
tile_dest_area.x1 = dest_area->x1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* subsequent tiles always starts from 0, but shifted*/
|
/* subsequent tiles always starts from 0, but shifted*/
|
||||||
tileBlit.src_area.x1 = 0 + shiftSrcX;
|
tile_src_area.x1 = 0 + shift_src_x;
|
||||||
tileBlit.dst_area.x1 = 0 + shiftDstX;
|
tile_dest_area.x1 = 0 + shift_dest_x;
|
||||||
/* and advance start pointer + 1 tile size */
|
/* and advance start pointer + 1 tile size */
|
||||||
tileBlit.src += LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR;
|
tile_src_buf += LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR;
|
||||||
tileBlit.dst += LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR;
|
tile_dest_buf += LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clip tile end coordinates */
|
/* Clip tile end coordinates */
|
||||||
tileBlit.src_area.x2 = totalWidth + blit->src_area.x1 - tileX * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
|
tile_src_area.x2 = width + src_area->x1 - x * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
|
||||||
if(tileBlit.src_area.x2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) {
|
if(tile_src_area.x2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) {
|
||||||
tileBlit.src_area.x2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
|
tile_src_area.x2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
tileBlit.dst_area.x2 = totalWidth + blit->dst_area.x1 - tileX * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
|
tile_dest_area.x2 = width + dest_area->x1 - x * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
|
||||||
if(tileBlit.dst_area.x2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) {
|
if(tile_dest_area.x2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) {
|
||||||
tileBlit.dst_area.x2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
|
tile_dest_area.x2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tileX < (totalTilesX - 1)) {
|
if(x < (total_tiles_x - 1)) {
|
||||||
/* And adjust end coords if shifted, but not for last tile! */
|
/* And adjust end coords if shifted, but not for last tile! */
|
||||||
tileBlit.src_area.x2 += shiftSrcX;
|
tile_src_area.x2 += shift_src_x;
|
||||||
tileBlit.dst_area.x2 += shiftDstX;
|
tile_dest_area.x2 += shift_dest_x;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = _lv_gpu_nxp_vglite_blit_single(&tileBlit);
|
if(check_src_alignment(tile_src_buf, src_stride) != LV_RES_OK)
|
||||||
|
VG_LITE_RETURN_INV("Check src alignment failed.");
|
||||||
|
|
||||||
#if BLIT_DBG_AREAS
|
/* Set vgmatrix. */
|
||||||
lv_vglite_dbg_draw_rectangle((lv_color_t *) tileBlit.dst, tileBlit.dst_width, tileBlit.dst_height, &tileBlit.dst_area,
|
lv_vglite_set_translation_matrix(&tile_dest_area);
|
||||||
LV_COLOR_RED);
|
|
||||||
lv_vglite_dbg_draw_rectangle((lv_color_t *) tileBlit.src, tileBlit.src_width, tileBlit.src_height, &tileBlit.src_area,
|
|
||||||
LV_COLOR_GREEN);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PRINT_BLT("Tile [%d, %d]: "
|
/* Set new dest_vgbuf and src_vgbuf memory addresses. */
|
||||||
"([%d,%d], [%d,%d]) -> "
|
lv_vglite_set_dest_buf_ptr(tile_dest_buf);
|
||||||
"([%d,%d], [%d,%d]) | "
|
lv_vglite_set_src_buf_ptr(tile_src_buf);
|
||||||
"([%dx%d] -> [%dx%d]) | "
|
|
||||||
"A:(0x%8X -> 0x%8X) %s\n",
|
|
||||||
tileX, tileY,
|
|
||||||
tileBlit.src_area.x1, tileBlit.src_area.y1, tileBlit.src_area.x2, tileBlit.src_area.y2,
|
|
||||||
tileBlit.dst_area.x1, tileBlit.dst_area.y1, tileBlit.dst_area.x2, tileBlit.dst_area.y2,
|
|
||||||
lv_area_get_width(&tileBlit.src_area), lv_area_get_height(&tileBlit.src_area),
|
|
||||||
lv_area_get_width(&tileBlit.dst_area), lv_area_get_height(&tileBlit.dst_area),
|
|
||||||
(uintptr_t) tileBlit.src, (uintptr_t) tileBlit.dst,
|
|
||||||
rv == LV_RES_OK ? "OK!" : "!!! FAILED !!!");
|
|
||||||
|
|
||||||
if(rv != LV_RES_OK) { /* if anything goes wrong... */
|
rv = lv_vglite_blit_single(&tile_dest_area, &tile_src_area, opa);
|
||||||
#if LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
|
||||||
LV_LOG_ERROR("Split blit failed. Trying SW blit instead.");
|
VG_LITE_LOG_TRACE("Tile [%d, %d] "
|
||||||
#endif
|
"Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | "
|
||||||
_sw_blit(&tileBlit);
|
"Size: ([%dx%d] -> [%dx%d]) | "
|
||||||
rv = LV_RES_OK; /* Don't report error, as SW BLIT was performed */
|
"Addr: (0x%x -> 0x%x) %s",
|
||||||
|
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,
|
||||||
|
rv == LV_RES_OK ? "OK!" : "FAILED!");
|
||||||
|
|
||||||
|
if(rv != LV_RES_OK) {
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
PRINT_BLT(" \n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv; /* should never fail */
|
return rv;
|
||||||
}
|
}
|
||||||
#endif /* VG_LITE_BLIT_SPLIT_ENABLED */
|
#endif /* VG_LITE_BLIT_SPLIT_ENABLED */
|
||||||
|
|
||||||
static lv_res_t _lv_gpu_nxp_vglite_blit_single(lv_gpu_nxp_vglite_blit_info_t * blit)
|
static lv_res_t lv_vglite_blit_single(const lv_area_t * dest_area, const lv_area_t * src_area, lv_opa_t opa)
|
||||||
{
|
{
|
||||||
vg_lite_buffer_t src_vgbuf, dst_vgbuf;
|
|
||||||
vg_lite_error_t err = VG_LITE_SUCCESS;
|
vg_lite_error_t err = VG_LITE_SUCCESS;
|
||||||
uint32_t rect[4];
|
vg_lite_buffer_t * dst_vgbuf = lv_vglite_get_dest_buf();
|
||||||
vg_lite_float_t scale = 1.0;
|
vg_lite_buffer_t * src_vgbuf = lv_vglite_get_src_buf();
|
||||||
|
|
||||||
if(blit == NULL) {
|
uint32_t rect[] = {
|
||||||
/*Wrong parameter*/
|
(uint32_t)src_area->x1, /* start x */
|
||||||
return LV_RES_INV;
|
(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 */
|
||||||
if(blit->opa < (lv_opa_t) LV_OPA_MIN) {
|
};
|
||||||
return LV_RES_OK; /*Nothing to BLIT*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Wrap src/dst buffer into VG-Lite buffer*/
|
|
||||||
if(lv_vglite_init_buf(&src_vgbuf, (uint32_t)blit->src_width, (uint32_t)blit->src_height, (uint32_t)blit->src_stride,
|
|
||||||
blit->src, true) != LV_RES_OK)
|
|
||||||
VG_LITE_RETURN_INV("Init buffer failed.");
|
|
||||||
|
|
||||||
if(lv_vglite_init_buf(&dst_vgbuf, (uint32_t)blit->dst_width, (uint32_t)blit->dst_height, (uint32_t)blit->dst_stride,
|
|
||||||
blit->dst, false) != LV_RES_OK)
|
|
||||||
VG_LITE_RETURN_INV("Init buffer failed.");
|
|
||||||
|
|
||||||
rect[0] = (uint32_t)blit->src_area.x1; /* start x */
|
|
||||||
rect[1] = (uint32_t)blit->src_area.y1; /* start y */
|
|
||||||
rect[2] = (uint32_t)blit->src_area.x2 - (uint32_t)blit->src_area.x1 + 1U; /* width */
|
|
||||||
rect[3] = (uint32_t)blit->src_area.y2 - (uint32_t)blit->src_area.y1 + 1U; /* height */
|
|
||||||
|
|
||||||
vg_lite_matrix_t matrix;
|
|
||||||
vg_lite_identity(&matrix);
|
|
||||||
vg_lite_translate((vg_lite_float_t)blit->dst_area.x1, (vg_lite_float_t)blit->dst_area.y1, &matrix);
|
|
||||||
|
|
||||||
if((blit->angle != 0) || (blit->zoom != LV_IMG_ZOOM_NONE)) {
|
|
||||||
vg_lite_translate(blit->pivot.x, blit->pivot.y, &matrix);
|
|
||||||
vg_lite_rotate(blit->angle / 10.0f, &matrix); /* angle is 1/10 degree */
|
|
||||||
scale = 1.0f * blit->zoom / LV_IMG_ZOOM_NONE;
|
|
||||||
vg_lite_scale(scale, scale, &matrix);
|
|
||||||
vg_lite_translate(0.0f - blit->pivot.x, 0.0f - blit->pivot.y, &matrix);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Clean & invalidate cache*/
|
|
||||||
lv_vglite_invalidate_cache();
|
|
||||||
|
|
||||||
uint32_t color;
|
uint32_t color;
|
||||||
vg_lite_blend_t blend;
|
vg_lite_blend_t blend;
|
||||||
if(blit->opa >= (lv_opa_t)LV_OPA_MAX) {
|
if(opa >= (lv_opa_t)LV_OPA_MAX) {
|
||||||
color = 0xFFFFFFFFU;
|
color = 0xFFFFFFFFU;
|
||||||
blend = VG_LITE_BLEND_SRC_OVER;
|
blend = VG_LITE_BLEND_SRC_OVER;
|
||||||
src_vgbuf.transparency_mode = VG_LITE_IMAGE_TRANSPARENT;
|
src_vgbuf->transparency_mode = VG_LITE_IMAGE_TRANSPARENT;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
uint32_t opa = (uint32_t)blit->opa;
|
|
||||||
if(vg_lite_query_feature(gcFEATURE_BIT_VG_PE_PREMULTIPLY)) {
|
if(vg_lite_query_feature(gcFEATURE_BIT_VG_PE_PREMULTIPLY)) {
|
||||||
color = (opa << 24) | 0x00FFFFFFU;
|
color = (opa << 24) | 0x00FFFFFFU;
|
||||||
}
|
}
|
||||||
@@ -498,94 +485,83 @@ static lv_res_t _lv_gpu_nxp_vglite_blit_single(lv_gpu_nxp_vglite_blit_info_t * b
|
|||||||
color = (opa << 24) | (opa << 16) | (opa << 8) | opa;
|
color = (opa << 24) | (opa << 16) | (opa << 8) | opa;
|
||||||
}
|
}
|
||||||
blend = VG_LITE_BLEND_SRC_OVER;
|
blend = VG_LITE_BLEND_SRC_OVER;
|
||||||
src_vgbuf.image_mode = VG_LITE_MULTIPLY_IMAGE_MODE;
|
src_vgbuf->image_mode = VG_LITE_MULTIPLY_IMAGE_MODE;
|
||||||
src_vgbuf.transparency_mode = VG_LITE_IMAGE_TRANSPARENT;
|
src_vgbuf->transparency_mode = VG_LITE_IMAGE_TRANSPARENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = vg_lite_blit_rect(&dst_vgbuf, &src_vgbuf, rect, &matrix, blend, color, VG_LITE_FILTER_POINT);
|
bool scissoring = lv_area_get_width(dest_area) < lv_area_get_width(src_area) ||
|
||||||
VG_LITE_ERR_RETURN_INV(err, "Blit rectangle failed.");
|
lv_area_get_height(dest_area) < lv_area_get_height(src_area);
|
||||||
|
if(scissoring) {
|
||||||
|
vg_lite_enable_scissor();
|
||||||
|
vg_lite_set_scissor((int32_t)dest_area->x1, (int32_t)dest_area->y1,
|
||||||
|
(int32_t)lv_area_get_width(dest_area),
|
||||||
|
(int32_t)lv_area_get_height(dest_area));
|
||||||
|
}
|
||||||
|
|
||||||
err = vg_lite_finish();
|
err = vg_lite_blit_rect(dst_vgbuf, src_vgbuf, rect, &vgmatrix, blend, color, VG_LITE_FILTER_POINT);
|
||||||
VG_LITE_ERR_RETURN_INV(err, "Finish failed.");
|
if(err != VG_LITE_SUCCESS) {
|
||||||
|
if(scissoring)
|
||||||
|
vg_lite_disable_scissor();
|
||||||
|
VG_LITE_RETURN_INV("Blit rectangle failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lv_vglite_run() != LV_RES_OK) {
|
||||||
|
if(scissoring)
|
||||||
|
vg_lite_disable_scissor();
|
||||||
|
VG_LITE_RETURN_INV("Run failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(scissoring)
|
||||||
|
vg_lite_disable_scissor();
|
||||||
|
|
||||||
return LV_RES_OK;
|
return LV_RES_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static lv_res_t check_src_alignment(const lv_color_t * src_buf, lv_coord_t src_stride)
|
||||||
|
{
|
||||||
|
/* No alignment requirement for destination pixel buffer when using mode VG_LITE_LINEAR */
|
||||||
|
|
||||||
|
/* Test for pointer alignment */
|
||||||
|
if((((uintptr_t)src_buf) % (uintptr_t)LV_ATTRIBUTE_MEM_ALIGN_SIZE) != (uintptr_t)0x0U)
|
||||||
|
VG_LITE_RETURN_INV("Src buffer ptr (0x%x) not aligned to 0x%x bytes.",
|
||||||
|
(size_t)src_buf, LV_ATTRIBUTE_MEM_ALIGN_SIZE);
|
||||||
|
|
||||||
|
/* Test for stride alignment */
|
||||||
|
if((src_stride % (lv_coord_t)LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX) != 0x0U)
|
||||||
|
VG_LITE_RETURN_INV("Src buffer stride (%d px) not aligned to %d px.",
|
||||||
|
src_stride, LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX);
|
||||||
|
return LV_RES_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void lv_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void lv_vglite_set_transformation_matrix(const lv_area_t * dest_area, const lv_draw_img_dsc_t * dsc)
|
||||||
|
{
|
||||||
|
lv_vglite_set_translation_matrix(dest_area);
|
||||||
|
|
||||||
|
bool has_scale = (dsc->zoom != LV_IMG_ZOOM_NONE);
|
||||||
|
bool has_rotation = (dsc->angle != 0);
|
||||||
|
|
||||||
|
if(has_scale || has_rotation) {
|
||||||
|
vg_lite_translate(dsc->pivot.x, dsc->pivot.y, &vgmatrix);
|
||||||
|
if(has_rotation)
|
||||||
|
vg_lite_rotate(dsc->angle / 10.0f, &vgmatrix); /* angle is 1/10 degree */
|
||||||
|
if(has_scale) {
|
||||||
|
vg_lite_float_t scale = 1.0f * dsc->zoom / LV_IMG_ZOOM_NONE;
|
||||||
|
vg_lite_scale(scale, scale, &vgmatrix);
|
||||||
|
}
|
||||||
|
vg_lite_translate(0.0f - dsc->pivot.x, 0.0f - dsc->pivot.y, &vgmatrix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if VG_LITE_BLIT_SPLIT_ENABLED
|
#if VG_LITE_BLIT_SPLIT_ENABLED
|
||||||
|
static void align_x(lv_area_t * area, lv_color_t ** buf)
|
||||||
static void _sw_blit(lv_gpu_nxp_vglite_blit_info_t * blit)
|
|
||||||
{
|
{
|
||||||
int x, y;
|
int alignedAreaStartPx = area->x1 - (area->x1 % (LV_ATTRIBUTE_MEM_ALIGN_SIZE / sizeof(lv_color_t)));
|
||||||
|
|
||||||
lv_coord_t w = lv_area_get_width(&blit->src_area);
|
|
||||||
lv_coord_t h = lv_area_get_height(&blit->src_area);
|
|
||||||
|
|
||||||
int32_t srcStridePx = blit->src_stride / (int32_t)sizeof(lv_color_t);
|
|
||||||
int32_t dstStridePx = blit->dst_stride / (int32_t)sizeof(lv_color_t);
|
|
||||||
|
|
||||||
lv_color_t * src = (lv_color_t *)blit->src + blit->src_area.y1 * srcStridePx + blit->src_area.x1;
|
|
||||||
lv_color_t * dst = (lv_color_t *)blit->dst + blit->dst_area.y1 * dstStridePx + blit->dst_area.x1;
|
|
||||||
|
|
||||||
if(blit->opa >= (lv_opa_t)LV_OPA_MAX) {
|
|
||||||
/* simple copy */
|
|
||||||
for(y = 0; y < h; y++) {
|
|
||||||
lv_memcpy(dst, src, (uint32_t)w * sizeof(lv_color_t));
|
|
||||||
src += srcStridePx;
|
|
||||||
dst += dstStridePx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(blit->opa >= LV_OPA_MIN) {
|
|
||||||
/* alpha blending */
|
|
||||||
for(y = 0; y < h; y++) {
|
|
||||||
for(x = 0; x < w; x++) {
|
|
||||||
dst[x] = lv_color_mix(src[x], dst[x], blit->opa);
|
|
||||||
}
|
|
||||||
src += srcStridePx;
|
|
||||||
dst += dstStridePx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static lv_res_t _lv_gpu_nxp_vglite_check_blit(lv_gpu_nxp_vglite_blit_info_t * blit)
|
|
||||||
{
|
|
||||||
|
|
||||||
/* Test for minimal width */
|
|
||||||
if(lv_area_get_width(&blit->src_area) < (lv_coord_t)LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX)
|
|
||||||
VG_LITE_RETURN_INV("Src area width (%d) is smaller than required (%d).", lv_area_get_width(&blit->src_area),
|
|
||||||
LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX);
|
|
||||||
|
|
||||||
/* Test for minimal width */
|
|
||||||
if(lv_area_get_width(&blit->dst_area) < (lv_coord_t)LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX)
|
|
||||||
VG_LITE_RETURN_INV("Dest area width (%d) is smaller than required (%d).", lv_area_get_width(&blit->dst_area),
|
|
||||||
LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX);
|
|
||||||
|
|
||||||
/* Test for pointer alignment */
|
|
||||||
if((((uintptr_t) blit->src) % LV_ATTRIBUTE_MEM_ALIGN_SIZE) != 0x0)
|
|
||||||
VG_LITE_RETURN_INV("Src buffer ptr (0x%X) not aligned to %d.", (size_t) blit->src, LV_ATTRIBUTE_MEM_ALIGN_SIZE);
|
|
||||||
|
|
||||||
/* No alignment requirement for destination pixel buffer when using mode VG_LITE_LINEAR */
|
|
||||||
|
|
||||||
/* Test for stride alignment */
|
|
||||||
if((blit->src_stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * LV_COLOR_DEPTH / 8)) != 0x0)
|
|
||||||
VG_LITE_RETURN_INV("Src buffer stride (%d px) not aligned to %d px.", blit->src_stride,
|
|
||||||
LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX);
|
|
||||||
|
|
||||||
/* Test for stride alignment */
|
|
||||||
if((blit->dst_stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * LV_COLOR_DEPTH / 8)) != 0x0)
|
|
||||||
VG_LITE_RETURN_INV("Dest buffer stride (%d px) not aligned to %d px.", blit->dst_stride,
|
|
||||||
LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX);
|
|
||||||
|
|
||||||
if((lv_area_get_width(&blit->src_area) != lv_area_get_width(&blit->dst_area)) ||
|
|
||||||
(lv_area_get_height(&blit->src_area) != lv_area_get_height(&blit->dst_area)))
|
|
||||||
VG_LITE_RETURN_INV("Src and dest buffer areas are not equal.");
|
|
||||||
|
|
||||||
return LV_RES_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _align_x(lv_area_t * area, lv_color_t ** buf)
|
|
||||||
{
|
|
||||||
|
|
||||||
int alignedAreaStartPx = area->x1 - (area->x1 % (LV_ATTRIBUTE_MEM_ALIGN_SIZE * 8 / LV_COLOR_DEPTH));
|
|
||||||
VG_LITE_COND_STOP(alignedAreaStartPx < 0, "Negative X alignment.");
|
VG_LITE_COND_STOP(alignedAreaStartPx < 0, "Negative X alignment.");
|
||||||
|
|
||||||
area->x1 -= alignedAreaStartPx;
|
area->x1 -= alignedAreaStartPx;
|
||||||
@@ -593,17 +569,17 @@ static void _align_x(lv_area_t * area, lv_color_t ** buf)
|
|||||||
*buf += alignedAreaStartPx;
|
*buf += alignedAreaStartPx;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _align_y(lv_area_t * area, lv_color_t ** buf, uint32_t stridePx)
|
static void align_y(lv_area_t * area, lv_color_t ** buf, lv_coord_t stride)
|
||||||
{
|
{
|
||||||
int LineToAlignMem;
|
int LineToAlignMem;
|
||||||
int alignedAreaStartPy;
|
int alignedAreaStartPy;
|
||||||
/* find how many lines of pixels will respect memory alignment requirement */
|
/* find how many lines of pixels will respect memory alignment requirement */
|
||||||
if(stridePx % (uint32_t)LV_ATTRIBUTE_MEM_ALIGN_SIZE == 0U) {
|
if((stride % (lv_coord_t)LV_ATTRIBUTE_MEM_ALIGN_SIZE) == 0x0U) {
|
||||||
alignedAreaStartPy = area->y1;
|
alignedAreaStartPy = area->y1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LineToAlignMem = LV_ATTRIBUTE_MEM_ALIGN_SIZE / (sizeof(lv_color_t) * LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX);
|
LineToAlignMem = LV_ATTRIBUTE_MEM_ALIGN_SIZE / (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * sizeof(lv_color_t));
|
||||||
VG_LITE_COND_STOP(LV_ATTRIBUTE_MEM_ALIGN_SIZE % (sizeof(lv_color_t) * LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX),
|
VG_LITE_COND_STOP(LV_ATTRIBUTE_MEM_ALIGN_SIZE % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * sizeof(lv_color_t)),
|
||||||
"Complex case: need gcd function.");
|
"Complex case: need gcd function.");
|
||||||
alignedAreaStartPy = area->y1 - (area->y1 % LineToAlignMem);
|
alignedAreaStartPy = area->y1 - (area->y1 % LineToAlignMem);
|
||||||
VG_LITE_COND_STOP(alignedAreaStartPy < 0, "Negative Y alignment.");
|
VG_LITE_COND_STOP(alignedAreaStartPy < 0, "Negative Y alignment.");
|
||||||
@@ -611,7 +587,7 @@ static void _align_y(lv_area_t * area, lv_color_t ** buf, uint32_t stridePx)
|
|||||||
|
|
||||||
area->y1 -= alignedAreaStartPy;
|
area->y1 -= alignedAreaStartPy;
|
||||||
area->y2 -= alignedAreaStartPy;
|
area->y2 -= alignedAreaStartPy;
|
||||||
*buf += (uint32_t)alignedAreaStartPy * stridePx;
|
*buf += (uint32_t)(alignedAreaStartPy * stride);
|
||||||
}
|
}
|
||||||
#endif /*VG_LITE_BLIT_SPLIT_ENABLED*/
|
#endif /*VG_LITE_BLIT_SPLIT_ENABLED*/
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/**
|
/**
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright 2020-2022 NXP
|
* Copyright 2020-2023 NXP
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -41,64 +41,16 @@ extern "C" {
|
|||||||
#include "../../../lv_conf_internal.h"
|
#include "../../../lv_conf_internal.h"
|
||||||
|
|
||||||
#if LV_USE_GPU_NXP_VG_LITE
|
#if LV_USE_GPU_NXP_VG_LITE
|
||||||
#include "lv_gpu_nxp_vglite.h"
|
#include "lv_vglite_utils.h"
|
||||||
|
|
||||||
/*********************
|
/*********************
|
||||||
* DEFINES
|
* DEFINES
|
||||||
*********************/
|
*********************/
|
||||||
|
|
||||||
#ifndef LV_GPU_NXP_VG_LITE_FILL_SIZE_LIMIT
|
|
||||||
/** Minimum area (in pixels) to be filled by VG-Lite with 100% opacity*/
|
|
||||||
#define LV_GPU_NXP_VG_LITE_FILL_SIZE_LIMIT 5000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LV_GPU_NXP_VG_LITE_FILL_OPA_SIZE_LIMIT
|
|
||||||
/** Minimum area (in pixels) to be filled by VG-Lite with transparency*/
|
|
||||||
#define LV_GPU_NXP_VG_LITE_FILL_OPA_SIZE_LIMIT 5000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT
|
|
||||||
/** Minimum area (in pixels) for image copy with 100% opacity to be handled by VG-Lite*/
|
|
||||||
#define LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT 5000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LV_GPU_NXP_VG_LITE_BUFF_SYNC_BLIT_SIZE_LIMIT
|
|
||||||
/** Minimum invalidated area (in pixels) to be synchronized by VG-Lite during buffer sync */
|
|
||||||
#define LV_GPU_NXP_VG_LITE_BUFF_SYNC_BLIT_SIZE_LIMIT 5000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT
|
|
||||||
/** Minimum area (in pixels) for image copy with transparency to be handled by VG-Lite*/
|
|
||||||
#define LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT 5000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* TYPEDEFS
|
* TYPEDEFS
|
||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
/**
|
|
||||||
* BLock Image Transfer descriptor structure
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
|
|
||||||
const lv_color_t * src; /**< Source buffer pointer (must be aligned on 32 bytes)*/
|
|
||||||
lv_area_t src_area; /**< Area to be copied from source*/
|
|
||||||
lv_coord_t src_width; /**< Source buffer width*/
|
|
||||||
lv_coord_t src_height; /**< Source buffer height*/
|
|
||||||
int32_t src_stride; /**< Source buffer stride in bytes (must be aligned on 16 px)*/
|
|
||||||
|
|
||||||
const lv_color_t * dst; /**< Destination buffer pointer (must be aligned on 32 bytes)*/
|
|
||||||
lv_area_t dst_area; /**< Target area in destination buffer (must be the same as src_area)*/
|
|
||||||
lv_coord_t dst_width; /**< Destination buffer width*/
|
|
||||||
lv_coord_t dst_height; /**< Destination buffer height*/
|
|
||||||
int32_t dst_stride; /**< Destination buffer stride in bytes (must be aligned on 16 px)*/
|
|
||||||
|
|
||||||
lv_opa_t opa; /**< Opacity - alpha mix (0 = source not copied, 255 = 100% opaque)*/
|
|
||||||
uint32_t angle; /**< Rotation angle (1/10 of degree)*/
|
|
||||||
uint32_t zoom; /**< 256 = no zoom (1:1 scale ratio)*/
|
|
||||||
lv_point_t pivot; /**< The coordinates of rotation pivot in source image buffer*/
|
|
||||||
} lv_gpu_nxp_vglite_blit_info_t;
|
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* GLOBAL PROTOTYPES
|
* GLOBAL PROTOTYPES
|
||||||
**********************/
|
**********************/
|
||||||
@@ -106,35 +58,52 @@ typedef struct {
|
|||||||
/**
|
/**
|
||||||
* Fill area, with optional opacity.
|
* Fill area, with optional opacity.
|
||||||
*
|
*
|
||||||
* @param[in/out] dest_buf Destination buffer pointer (must be aligned on 32 bytes)
|
* @param[in] dest_area Area with relative coordinates of destination buffer
|
||||||
* @param[in] dest_width Destination buffer width in pixels (must be aligned on 16 px)
|
* @param[in] color Color
|
||||||
* @param[in] dest_height Destination buffer height in pixels
|
|
||||||
* @param[in] fill_area Area to be filled
|
|
||||||
* @param[in] color Fill color
|
|
||||||
* @param[in] opa Opacity (255 = full, 128 = 50% background/50% color, 0 = no fill)
|
* @param[in] opa Opacity (255 = full, 128 = 50% background/50% color, 0 = no fill)
|
||||||
|
*
|
||||||
* @retval LV_RES_OK Fill completed
|
* @retval LV_RES_OK Fill completed
|
||||||
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
|
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
|
||||||
*/
|
*/
|
||||||
lv_res_t lv_gpu_nxp_vglite_fill(lv_color_t * dest_buf, lv_coord_t dest_width, lv_coord_t dest_height,
|
lv_res_t lv_gpu_nxp_vglite_fill(const lv_area_t * dest_area, lv_color_t color, lv_opa_t opa);
|
||||||
const lv_area_t * fill_area, lv_color_t color, lv_opa_t opa);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BLock Image Transfer.
|
* 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/out] dest_buf Destination buffer
|
||||||
|
* @param[in] dest_area Area with relative coordinates of destination buffer
|
||||||
|
* @param[in] dest_stride Stride of destination buffer in pixels
|
||||||
|
* @param[in] src_buf Source buffer
|
||||||
|
* @param[in] src_area Source area with relative coordinates of source buffer
|
||||||
|
* @param[in] src_stride Stride of source buffer in pixels
|
||||||
|
* @param[in] opa Opacity
|
||||||
*
|
*
|
||||||
* @param[in] blit Description of the transfer
|
|
||||||
* @retval LV_RES_OK Transfer complete
|
* @retval LV_RES_OK Transfer complete
|
||||||
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
|
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
|
||||||
*/
|
*/
|
||||||
lv_res_t lv_gpu_nxp_vglite_blit(lv_gpu_nxp_vglite_blit_info_t * blit);
|
lv_res_t lv_gpu_nxp_vglite_blit(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||||
|
const lv_color_t * src_buf, lv_area_t * src_area, lv_coord_t src_stride,
|
||||||
|
lv_opa_t opa);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BLock Image Transfer with transformation.
|
* 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/out] dest_buf Destination buffer
|
||||||
|
* @param[in] dest_area Area with relative coordinates of destination buffer
|
||||||
|
* @param[in] dest_stride Stride of destination buffer in pixels
|
||||||
|
* @param[in] src_buf Source buffer
|
||||||
|
* @param[in] src_area Source area with relative coordinates of source buffer
|
||||||
|
* @param[in] src_stride Stride of source buffer in pixels
|
||||||
|
* @param[in] dsc Image descriptor
|
||||||
*
|
*
|
||||||
* @param[in] blit Description of the transfer
|
|
||||||
* @retval LV_RES_OK Transfer complete
|
* @retval LV_RES_OK Transfer complete
|
||||||
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
|
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
|
||||||
*/
|
*/
|
||||||
lv_res_t lv_gpu_nxp_vglite_blit_transform(lv_gpu_nxp_vglite_blit_info_t * blit);
|
lv_res_t lv_gpu_nxp_vglite_blit_transform(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride,
|
||||||
|
const lv_color_t * src_buf, lv_area_t * src_area, lv_coord_t src_stride,
|
||||||
|
const lv_draw_img_dsc_t * dsc);
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* MACROS
|
* MACROS
|
||||||
|
|||||||
138
src/draw/nxp/vglite/lv_draw_vglite_line.c
Normal file
138
src/draw/nxp/vglite/lv_draw_vglite_line.c
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_draw_vglite_line.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright 2022, 2023 NXP
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next paragraph)
|
||||||
|
* shall be included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||||
|
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||||
|
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "lv_draw_vglite_line.h"
|
||||||
|
|
||||||
|
#if LV_USE_GPU_NXP_VG_LITE
|
||||||
|
#include "lv_vglite_buf.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
lv_res_t lv_gpu_nxp_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_color_t vgcol; /* vglite takes ABGR */
|
||||||
|
vg_lite_buffer_t * vgbuf = lv_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 = lv_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);
|
||||||
|
VG_LITE_ERR_RETURN_INV(err, "Init path failed.");
|
||||||
|
|
||||||
|
vg_lite_matrix_t matrix;
|
||||||
|
vg_lite_identity(&matrix);
|
||||||
|
|
||||||
|
lv_color32_t col32 = { .full = lv_color_to32(dsc->color) }; /*Convert color to RGBA8888*/
|
||||||
|
vg_lite_buffer_format_t color_format = LV_COLOR_DEPTH == 16 ? VG_LITE_BGRA8888 : VG_LITE_ABGR8888;
|
||||||
|
if(lv_vglite_premult_and_swizzle(&vgcol, col32, dsc->opa, color_format) != LV_RES_OK)
|
||||||
|
VG_LITE_RETURN_INV("Premultiplication and swizzle failed.");
|
||||||
|
|
||||||
|
/*** Draw line ***/
|
||||||
|
err = vg_lite_set_draw_path_type(&path, VG_LITE_DRAW_STROKE_PATH);
|
||||||
|
VG_LITE_ERR_RETURN_INV(err, "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);
|
||||||
|
VG_LITE_ERR_RETURN_INV(err, "Set stroke failed.");
|
||||||
|
|
||||||
|
err = vg_lite_update_stroke(&path);
|
||||||
|
VG_LITE_ERR_RETURN_INV(err, "Update stroke failed.");
|
||||||
|
|
||||||
|
err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, vglite_blend_mode, vgcol);
|
||||||
|
VG_LITE_ERR_RETURN_INV(err, "Draw line failed.");
|
||||||
|
|
||||||
|
if(lv_vglite_run() != LV_RES_OK)
|
||||||
|
VG_LITE_RETURN_INV("Run failed.");
|
||||||
|
|
||||||
|
err = vg_lite_clear_path(&path);
|
||||||
|
VG_LITE_ERR_RETURN_INV(err, "Clear path failed.");
|
||||||
|
|
||||||
|
return LV_RES_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
#endif /*LV_USE_GPU_NXP_VG_LITE*/
|
||||||
83
src/draw/nxp/vglite/lv_draw_vglite_line.h
Normal file
83
src/draw/nxp/vglite/lv_draw_vglite_line.h
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_draw_vglite_line.h
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright 2022, 2023 NXP
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next paragraph)
|
||||||
|
* shall be included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||||
|
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||||
|
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LV_DRAW_VGLITE_LINE_H
|
||||||
|
#define LV_DRAW_VGLITE_LINE_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
#include "../../../lv_conf_internal.h"
|
||||||
|
|
||||||
|
#if LV_USE_GPU_NXP_VG_LITE
|
||||||
|
#include "lv_vglite_utils.h"
|
||||||
|
#include "../../lv_draw_line.h"
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL 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, ...)
|
||||||
|
*
|
||||||
|
* @retval LV_RES_OK Draw completed
|
||||||
|
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
|
||||||
|
*/
|
||||||
|
lv_res_t lv_gpu_nxp_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);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
#endif /*LV_USE_GPU_NXP_VG_LITE*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /*extern "C"*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*LV_DRAW_VGLITE_RECT_H*/
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
/**
|
/**
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright 2021, 2022 NXP
|
* Copyright 2021-2023 NXP
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -34,10 +34,28 @@
|
|||||||
#include "lv_draw_vglite_rect.h"
|
#include "lv_draw_vglite_rect.h"
|
||||||
|
|
||||||
#if LV_USE_GPU_NXP_VG_LITE
|
#if LV_USE_GPU_NXP_VG_LITE
|
||||||
|
#include "lv_vglite_buf.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
/*********************
|
/*********************
|
||||||
* DEFINES
|
* DEFINES
|
||||||
*********************/
|
*********************/
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/* 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
|
* TYPEDEFS
|
||||||
@@ -47,6 +65,18 @@
|
|||||||
* STATIC PROTOTYPES
|
* STATIC 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
|
||||||
|
*/
|
||||||
|
static void lv_vglite_create_rect_path_data(int32_t * path_data, uint32_t * path_data_size,
|
||||||
|
lv_coord_t radius,
|
||||||
|
const lv_area_t * coords);
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* STATIC VARIABLES
|
* STATIC VARIABLES
|
||||||
**********************/
|
**********************/
|
||||||
@@ -59,94 +89,37 @@
|
|||||||
* GLOBAL FUNCTIONS
|
* GLOBAL FUNCTIONS
|
||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
lv_res_t lv_gpu_nxp_vglite_draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords)
|
lv_res_t lv_gpu_nxp_vglite_draw_bg(const lv_area_t * coords, const lv_area_t * clip_area,
|
||||||
|
const lv_draw_rect_dsc_t * dsc)
|
||||||
{
|
{
|
||||||
vg_lite_buffer_t vgbuf;
|
|
||||||
vg_lite_error_t err = VG_LITE_SUCCESS;
|
vg_lite_error_t err = VG_LITE_SUCCESS;
|
||||||
lv_coord_t dest_width = lv_area_get_width(draw_ctx->buf_area);
|
|
||||||
lv_coord_t dest_height = lv_area_get_height(draw_ctx->buf_area);
|
|
||||||
vg_lite_path_t path;
|
|
||||||
vg_lite_color_t vgcol; /* vglite takes ABGR */
|
|
||||||
vg_lite_matrix_t matrix;
|
|
||||||
lv_coord_t width = lv_area_get_width(coords);
|
lv_coord_t width = lv_area_get_width(coords);
|
||||||
lv_coord_t height = lv_area_get_height(coords);
|
lv_coord_t height = lv_area_get_height(coords);
|
||||||
vg_lite_linear_gradient_t gradient;
|
vg_lite_color_t vgcol;
|
||||||
vg_lite_matrix_t * grad_matrix;
|
lv_coord_t radius = dsc->radius;
|
||||||
|
vg_lite_buffer_t * vgbuf = lv_vglite_get_dest_buf();
|
||||||
|
|
||||||
if(dsc->radius < 0)
|
if(dsc->radius < 0)
|
||||||
return LV_RES_INV;
|
return LV_RES_INV;
|
||||||
|
|
||||||
/* Make areas relative to draw buffer */
|
|
||||||
lv_area_t rel_coords;
|
|
||||||
lv_area_copy(&rel_coords, coords);
|
|
||||||
lv_area_move(&rel_coords, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
|
|
||||||
|
|
||||||
lv_area_t rel_clip;
|
|
||||||
lv_area_copy(&rel_clip, draw_ctx->clip_area);
|
|
||||||
lv_area_move(&rel_clip, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
|
|
||||||
|
|
||||||
/*** Init destination buffer ***/
|
|
||||||
if(lv_vglite_init_buf(&vgbuf, (uint32_t)dest_width, (uint32_t)dest_height, (uint32_t)dest_width * sizeof(lv_color_t),
|
|
||||||
(const lv_color_t *)draw_ctx->buf, false) != LV_RES_OK)
|
|
||||||
VG_LITE_RETURN_INV("Init buffer failed.");
|
|
||||||
|
|
||||||
/*** Init path ***/
|
/*** Init path ***/
|
||||||
int32_t rad = dsc->radius;
|
int32_t path_data[RECT_PATH_DATA_MAX_SIZE];
|
||||||
if(dsc->radius == LV_RADIUS_CIRCLE) {
|
uint32_t path_data_size;
|
||||||
rad = (width > height) ? height / 2 : width / 2;
|
lv_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_LOW;
|
||||||
|
|
||||||
if((dsc->radius == LV_RADIUS_CIRCLE) && (width == height)) {
|
|
||||||
float tang = ((float)rad * BEZIER_OPTIM_CIRCLE);
|
|
||||||
int32_t cpoff = (int32_t)tang;
|
|
||||||
int32_t circle_path[] = { /*VG circle path*/
|
|
||||||
VLC_OP_MOVE, rel_coords.x1 + rad, rel_coords.y1,
|
|
||||||
VLC_OP_CUBIC_REL, cpoff, 0, rad, rad - cpoff, rad, rad, /* top-right */
|
|
||||||
VLC_OP_CUBIC_REL, 0, cpoff, cpoff - rad, rad, 0 - rad, rad, /* bottom-right */
|
|
||||||
VLC_OP_CUBIC_REL, 0 - cpoff, 0, 0 - rad, cpoff - rad, 0 - rad, 0 - rad, /* bottom-left */
|
|
||||||
VLC_OP_CUBIC_REL, 0, 0 - cpoff, rad - cpoff, 0 - rad, rad, 0 - rad, /* top-left */
|
|
||||||
VLC_OP_END
|
|
||||||
};
|
|
||||||
err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, sizeof(circle_path), circle_path,
|
|
||||||
(vg_lite_float_t) rel_clip.x1, (vg_lite_float_t) rel_clip.y1,
|
|
||||||
((vg_lite_float_t) rel_clip.x2) + 1.0f, ((vg_lite_float_t) rel_clip.y2) + 1.0f);
|
|
||||||
}
|
|
||||||
else if(dsc->radius > 0) {
|
|
||||||
float tang = ((float)rad * BEZIER_OPTIM_CIRCLE);
|
|
||||||
int32_t cpoff = (int32_t)tang;
|
|
||||||
int32_t rounded_path[] = { /*VG rounded rectangular path*/
|
|
||||||
VLC_OP_MOVE, rel_coords.x1 + rad, rel_coords.y1,
|
|
||||||
VLC_OP_LINE, rel_coords.x2 - rad + 1, rel_coords.y1, /* top */
|
|
||||||
VLC_OP_CUBIC_REL, cpoff, 0, rad, rad - cpoff, rad, rad, /* top-right */
|
|
||||||
VLC_OP_LINE, rel_coords.x2 + 1, rel_coords.y2 - rad + 1, /* right */
|
|
||||||
VLC_OP_CUBIC_REL, 0, cpoff, cpoff - rad, rad, 0 - rad, rad, /* bottom-right */
|
|
||||||
VLC_OP_LINE, rel_coords.x1 + rad, rel_coords.y2 + 1, /* bottom */
|
|
||||||
VLC_OP_CUBIC_REL, 0 - cpoff, 0, 0 - rad, cpoff - rad, 0 - rad, 0 - rad, /* bottom-left */
|
|
||||||
VLC_OP_LINE, rel_coords.x1, rel_coords.y1 + rad, /* left */
|
|
||||||
VLC_OP_CUBIC_REL, 0, 0 - cpoff, rad - cpoff, 0 - rad, rad, 0 - rad, /* top-left */
|
|
||||||
VLC_OP_END
|
|
||||||
};
|
|
||||||
err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, sizeof(rounded_path), rounded_path,
|
|
||||||
(vg_lite_float_t) rel_clip.x1, (vg_lite_float_t) rel_clip.y1,
|
|
||||||
((vg_lite_float_t) rel_clip.x2) + 1.0f, ((vg_lite_float_t) rel_clip.y2) + 1.0f);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int32_t rect_path[] = { /*VG rectangular path*/
|
|
||||||
VLC_OP_MOVE, rel_coords.x1, rel_coords.y1,
|
|
||||||
VLC_OP_LINE, rel_coords.x2 + 1, rel_coords.y1,
|
|
||||||
VLC_OP_LINE, rel_coords.x2 + 1, rel_coords.y2 + 1,
|
|
||||||
VLC_OP_LINE, rel_coords.x1, rel_coords.y2 + 1,
|
|
||||||
VLC_OP_LINE, rel_coords.x1, rel_coords.y1,
|
|
||||||
VLC_OP_END
|
|
||||||
};
|
|
||||||
err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_LOW, sizeof(rect_path), rect_path,
|
|
||||||
(vg_lite_float_t) rel_clip.x1, (vg_lite_float_t) rel_clip.y1,
|
|
||||||
((vg_lite_float_t) rel_clip.x2) + 1.0f, ((vg_lite_float_t) rel_clip.y2) + 1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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);
|
||||||
VG_LITE_ERR_RETURN_INV(err, "Init path failed.");
|
VG_LITE_ERR_RETURN_INV(err, "Init path failed.");
|
||||||
|
|
||||||
|
vg_lite_matrix_t matrix;
|
||||||
vg_lite_identity(&matrix);
|
vg_lite_identity(&matrix);
|
||||||
|
|
||||||
|
vg_lite_matrix_t * grad_matrix;
|
||||||
|
vg_lite_linear_gradient_t gradient;
|
||||||
|
|
||||||
/*** Init Color/Gradient ***/
|
/*** Init Color/Gradient ***/
|
||||||
if(dsc->bg_grad.dir != (lv_grad_dir_t)LV_GRAD_DIR_NONE) {
|
if(dsc->bg_grad.dir != (lv_grad_dir_t)LV_GRAD_DIR_NONE) {
|
||||||
uint32_t colors[2];
|
uint32_t colors[2];
|
||||||
@@ -154,18 +127,14 @@ lv_res_t lv_gpu_nxp_vglite_draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_
|
|||||||
lv_color32_t col32[2];
|
lv_color32_t col32[2];
|
||||||
|
|
||||||
/* Gradient setup */
|
/* Gradient setup */
|
||||||
uint8_t cnt = MAX(dsc->bg_grad.stops_count, 2);
|
uint8_t cnt = LV_MAX(dsc->bg_grad.stops_count, 2);
|
||||||
for(uint8_t i = 0; i < cnt; i++) {
|
for(uint8_t i = 0; i < cnt; i++) {
|
||||||
col32[i].full = lv_color_to32(dsc->bg_grad.stops[i].color); /*Convert color to RGBA8888*/
|
col32[i].full = lv_color_to32(dsc->bg_grad.stops[i].color); /*Convert color to RGBA8888*/
|
||||||
stops[i] = dsc->bg_grad.stops[i].frac;
|
stops[i] = dsc->bg_grad.stops[i].frac;
|
||||||
#if LV_COLOR_DEPTH==16
|
|
||||||
colors[i] = ((uint32_t)col32[i].ch.alpha << 24) | ((uint32_t)col32[i].ch.blue << 16) |
|
vg_lite_buffer_format_t color_format = LV_COLOR_DEPTH == 16 ? VG_LITE_ABGR8888 : VG_LITE_ARGB8888;
|
||||||
((uint32_t)col32[i].ch.green << 8) | (uint32_t)col32[i].ch.red;
|
if(lv_vglite_premult_and_swizzle(&colors[i], col32[i], dsc->bg_opa, color_format) != LV_RES_OK)
|
||||||
#else /*LV_COLOR_DEPTH==32*/
|
VG_LITE_RETURN_INV("Premultiplication and swizzle failed.");
|
||||||
/* watchout: red and blue color components are inverted versus vg_lite_color_t order */
|
|
||||||
colors[i] = ((uint32_t)col32[i].ch.alpha << 24) | ((uint32_t)col32[i].ch.red << 16) |
|
|
||||||
((uint32_t)col32[i].ch.green << 8) | (uint32_t)col32[i].ch.blue;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lv_memzero(&gradient, sizeof(vg_lite_linear_gradient_t));
|
lv_memzero(&gradient, sizeof(vg_lite_linear_gradient_t));
|
||||||
@@ -181,7 +150,7 @@ lv_res_t lv_gpu_nxp_vglite_draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_
|
|||||||
|
|
||||||
grad_matrix = vg_lite_get_grad_matrix(&gradient);
|
grad_matrix = vg_lite_get_grad_matrix(&gradient);
|
||||||
vg_lite_identity(grad_matrix);
|
vg_lite_identity(grad_matrix);
|
||||||
vg_lite_translate((float)rel_coords.x1, (float)rel_coords.y1, grad_matrix);
|
vg_lite_translate((float)coords->x1, (float)coords->y1, grad_matrix);
|
||||||
|
|
||||||
if(dsc->bg_grad.dir == (lv_grad_dir_t)LV_GRAD_DIR_VER) {
|
if(dsc->bg_grad.dir == (lv_grad_dir_t)LV_GRAD_DIR_VER) {
|
||||||
vg_lite_scale(1.0f, (float)height / 256.0f, grad_matrix);
|
vg_lite_scale(1.0f, (float)height / 256.0f, grad_matrix);
|
||||||
@@ -192,39 +161,22 @@ lv_res_t lv_gpu_nxp_vglite_draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lv_opa_t bg_opa = dsc->bg_opa;
|
|
||||||
lv_color32_t bg_col32 = {.full = lv_color_to32(dsc->bg_color)}; /*Convert color to RGBA8888*/
|
lv_color32_t bg_col32 = {.full = lv_color_to32(dsc->bg_color)}; /*Convert color to RGBA8888*/
|
||||||
if(bg_opa <= (lv_opa_t)LV_OPA_MAX) {
|
vg_lite_buffer_format_t color_format = LV_COLOR_DEPTH == 16 ? VG_LITE_BGRA8888 : VG_LITE_ABGR8888;
|
||||||
/* Only pre-multiply color if hardware pre-multiplication is not present */
|
if(lv_vglite_premult_and_swizzle(&vgcol, bg_col32, dsc->bg_opa, color_format) != LV_RES_OK)
|
||||||
if(!vg_lite_query_feature(gcFEATURE_BIT_VG_PE_PREMULTIPLY)) {
|
VG_LITE_RETURN_INV("Premultiplication and swizzle failed.");
|
||||||
bg_col32.ch.red = (uint8_t)(((uint16_t)bg_col32.ch.red * bg_opa) >> 8);
|
|
||||||
bg_col32.ch.green = (uint8_t)(((uint16_t)bg_col32.ch.green * bg_opa) >> 8);
|
|
||||||
bg_col32.ch.blue = (uint8_t)(((uint16_t)bg_col32.ch.blue * bg_opa) >> 8);
|
|
||||||
}
|
|
||||||
bg_col32.ch.alpha = bg_opa;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if LV_COLOR_DEPTH==16
|
|
||||||
vgcol = bg_col32.full;
|
|
||||||
#else /*LV_COLOR_DEPTH==32*/
|
|
||||||
vgcol = ((uint32_t)bg_col32.ch.alpha << 24) | ((uint32_t)bg_col32.ch.blue << 16) |
|
|
||||||
((uint32_t)bg_col32.ch.green << 8) | (uint32_t)bg_col32.ch.red;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*Clean & invalidate cache*/
|
|
||||||
lv_vglite_invalidate_cache();
|
|
||||||
|
|
||||||
/*** Draw rectangle ***/
|
/*** Draw rectangle ***/
|
||||||
if(dsc->bg_grad.dir == (lv_grad_dir_t)LV_GRAD_DIR_NONE) {
|
if(dsc->bg_grad.dir == (lv_grad_dir_t)LV_GRAD_DIR_NONE) {
|
||||||
err = vg_lite_draw(&vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol);
|
err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
err = vg_lite_draw_gradient(&vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, &gradient, VG_LITE_BLEND_SRC_OVER);
|
err = vg_lite_draw_gradient(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, &gradient, VG_LITE_BLEND_SRC_OVER);
|
||||||
}
|
}
|
||||||
VG_LITE_ERR_RETURN_INV(err, "Draw gradient failed.");
|
VG_LITE_ERR_RETURN_INV(err, "Draw gradient failed.");
|
||||||
|
|
||||||
err = vg_lite_finish();
|
if(lv_vglite_run() != LV_RES_OK)
|
||||||
VG_LITE_ERR_RETURN_INV(err, "Finish failed.");
|
VG_LITE_RETURN_INV("Run failed.");
|
||||||
|
|
||||||
err = vg_lite_clear_path(&path);
|
err = vg_lite_clear_path(&path);
|
||||||
VG_LITE_ERR_RETURN_INV(err, "Clear path failed.");
|
VG_LITE_ERR_RETURN_INV(err, "Clear path failed.");
|
||||||
@@ -237,6 +189,261 @@ lv_res_t lv_gpu_nxp_vglite_draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_
|
|||||||
return LV_RES_OK;
|
return LV_RES_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lv_res_t lv_gpu_nxp_vglite_draw_border_generic(const lv_area_t * coords, const lv_area_t * clip_area,
|
||||||
|
const lv_draw_rect_dsc_t * dsc, bool border)
|
||||||
|
{
|
||||||
|
vg_lite_error_t err = VG_LITE_SUCCESS;
|
||||||
|
vg_lite_color_t vgcol; /* vglite takes ABGR */
|
||||||
|
lv_coord_t radius = dsc->radius;
|
||||||
|
vg_lite_buffer_t * vgbuf = lv_vglite_get_dest_buf();
|
||||||
|
|
||||||
|
if(radius < 0)
|
||||||
|
return LV_RES_INV;
|
||||||
|
|
||||||
|
if(border) {
|
||||||
|
/* Draw border - only has radius if object has radius*/
|
||||||
|
lv_coord_t border_half = (lv_coord_t)floor(dsc->border_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;
|
||||||
|
|
||||||
|
/* Choose vglite blend mode based on given lvgl blend mode */
|
||||||
|
vg_lite_blend_t vglite_blend_mode = lv_vglite_get_blend_mode(dsc->blend_mode);
|
||||||
|
|
||||||
|
/*** Init path ***/
|
||||||
|
int32_t path_data[RECT_PATH_DATA_MAX_SIZE];
|
||||||
|
uint32_t path_data_size;
|
||||||
|
lv_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_LOW;
|
||||||
|
|
||||||
|
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);
|
||||||
|
VG_LITE_ERR_RETURN_INV(err, "Init path failed.");
|
||||||
|
|
||||||
|
vg_lite_matrix_t matrix;
|
||||||
|
vg_lite_identity(&matrix);
|
||||||
|
|
||||||
|
lv_opa_t opa;
|
||||||
|
lv_color32_t col32;
|
||||||
|
lv_coord_t line_width;
|
||||||
|
|
||||||
|
if(border) {
|
||||||
|
opa = dsc->border_opa;
|
||||||
|
col32.full = lv_color_to32(dsc->border_color); /*Convert color to RGBA8888*/
|
||||||
|
line_width = dsc->border_width;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
opa = dsc->outline_opa;
|
||||||
|
col32.full = lv_color_to32(dsc->outline_color); /*Convert color to RGBA8888*/
|
||||||
|
line_width = dsc->outline_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
vg_lite_buffer_format_t color_format = LV_COLOR_DEPTH == 16 ? VG_LITE_BGRA8888 : VG_LITE_ABGR8888;
|
||||||
|
if(lv_vglite_premult_and_swizzle(&vgcol, col32, opa, color_format) != LV_RES_OK)
|
||||||
|
VG_LITE_RETURN_INV("Premultiplication and swizzle failed.");
|
||||||
|
|
||||||
|
/*** Draw border ***/
|
||||||
|
err = vg_lite_set_draw_path_type(&path, VG_LITE_DRAW_STROKE_PATH);
|
||||||
|
VG_LITE_ERR_RETURN_INV(err, "Set draw path type failed.");
|
||||||
|
|
||||||
|
err = vg_lite_set_stroke(&path, cap_style, join_style, line_width, 8, NULL, 0, 0, vgcol);
|
||||||
|
VG_LITE_ERR_RETURN_INV(err, "Set stroke failed.");
|
||||||
|
|
||||||
|
err = vg_lite_update_stroke(&path);
|
||||||
|
VG_LITE_ERR_RETURN_INV(err, "Update stroke failed.");
|
||||||
|
|
||||||
|
err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, vglite_blend_mode, vgcol);
|
||||||
|
VG_LITE_ERR_RETURN_INV(err, "Draw border failed.");
|
||||||
|
|
||||||
|
if(lv_vglite_run() != LV_RES_OK)
|
||||||
|
VG_LITE_RETURN_INV("Run failed.");
|
||||||
|
|
||||||
|
err = vg_lite_clear_path(&path);
|
||||||
|
VG_LITE_ERR_RETURN_INV(err, "Clear path failed.");
|
||||||
|
|
||||||
|
return LV_RES_OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lv_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
|
* STATIC FUNCTIONS
|
||||||
**********************/
|
**********************/
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/**
|
/**
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright 2021, 2022 NXP
|
* Copyright 2021-2023 NXP
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -40,7 +40,7 @@ extern "C" {
|
|||||||
#include "../../../lv_conf_internal.h"
|
#include "../../../lv_conf_internal.h"
|
||||||
|
|
||||||
#if LV_USE_GPU_NXP_VG_LITE
|
#if LV_USE_GPU_NXP_VG_LITE
|
||||||
#include "lv_gpu_nxp_vglite.h"
|
#include "lv_vglite_utils.h"
|
||||||
#include "../../lv_draw_rect.h"
|
#include "../../lv_draw_rect.h"
|
||||||
|
|
||||||
/*********************
|
/*********************
|
||||||
@@ -56,13 +56,33 @@ extern "C" {
|
|||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw rectangle shape with effects (rounded corners, gradient)
|
* 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
|
||||||
|
*
|
||||||
|
* @retval LV_RES_OK Draw completed
|
||||||
|
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
|
||||||
*
|
*
|
||||||
* @param draw_ctx drawing context
|
|
||||||
* @param dsc description of the rectangle
|
|
||||||
* @param coords the area where rectangle is clipped
|
|
||||||
*/
|
*/
|
||||||
lv_res_t lv_gpu_nxp_vglite_draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
|
lv_res_t lv_gpu_nxp_vglite_draw_bg(const lv_area_t * coords, const lv_area_t * clip_area,
|
||||||
|
const lv_draw_rect_dsc_t * dsc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* @param[in] border True for border, False for outline
|
||||||
|
*
|
||||||
|
* @retval LV_RES_OK Draw completed
|
||||||
|
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
lv_res_t lv_gpu_nxp_vglite_draw_border_generic(const lv_area_t * coords, const lv_area_t * clip_area,
|
||||||
|
const lv_draw_rect_dsc_t * dsc, bool border);
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* MACROS
|
* MACROS
|
||||||
|
|||||||
@@ -1,153 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file lv_gpu_nxp_vglite.c
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright 2020-2022 NXP
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights to
|
|
||||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
||||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
|
||||||
* subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice (including the next paragraph)
|
|
||||||
* shall be included in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
||||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
||||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
|
||||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
|
||||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*********************
|
|
||||||
* INCLUDES
|
|
||||||
*********************/
|
|
||||||
|
|
||||||
#include "lv_gpu_nxp_vglite.h"
|
|
||||||
|
|
||||||
#if LV_USE_GPU_NXP_VG_LITE
|
|
||||||
#include "../../../core/lv_refr.h"
|
|
||||||
#if BLIT_DBG_AREAS
|
|
||||||
#include "lv_draw_vglite_blend.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*********************
|
|
||||||
* DEFINES
|
|
||||||
*********************/
|
|
||||||
|
|
||||||
#if LV_COLOR_DEPTH==16
|
|
||||||
#define VG_LITE_PX_FMT VG_LITE_RGB565
|
|
||||||
#elif LV_COLOR_DEPTH==32
|
|
||||||
#define VG_LITE_PX_FMT VG_LITE_BGRA8888
|
|
||||||
#else
|
|
||||||
#error Only 16bit and 32bit color depth are supported. Set LV_COLOR_DEPTH to 16 or 32.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**********************
|
|
||||||
* TYPEDEFS
|
|
||||||
**********************/
|
|
||||||
|
|
||||||
/**********************
|
|
||||||
* STATIC PROTOTYPES
|
|
||||||
**********************/
|
|
||||||
|
|
||||||
/**********************
|
|
||||||
* STATIC VARIABLES
|
|
||||||
**********************/
|
|
||||||
|
|
||||||
/**********************
|
|
||||||
* MACROS
|
|
||||||
**********************/
|
|
||||||
|
|
||||||
/**********************
|
|
||||||
* GLOBAL FUNCTIONS
|
|
||||||
**********************/
|
|
||||||
|
|
||||||
lv_res_t lv_vglite_init_buf(vg_lite_buffer_t * vgbuf, uint32_t width, uint32_t height, uint32_t stride,
|
|
||||||
const lv_color_t * ptr, bool source)
|
|
||||||
{
|
|
||||||
/*Test for memory alignment*/
|
|
||||||
if((((uintptr_t)ptr) % (uintptr_t)LV_ATTRIBUTE_MEM_ALIGN_SIZE) != (uintptr_t)0x0U)
|
|
||||||
VG_LITE_RETURN_INV("%s buffer (0x%x) not aligned to %d.", source ? "Src" : "Dest",
|
|
||||||
(size_t) ptr, LV_ATTRIBUTE_MEM_ALIGN_SIZE);
|
|
||||||
|
|
||||||
/*Test for stride alignment*/
|
|
||||||
if(source && (stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * sizeof(lv_color_t))) != 0x0U)
|
|
||||||
VG_LITE_RETURN_INV("Src buffer stride (%d bytes) not aligned to %d bytes.", stride,
|
|
||||||
LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * sizeof(lv_color_t));
|
|
||||||
|
|
||||||
vgbuf->format = VG_LITE_PX_FMT;
|
|
||||||
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_memzero(&vgbuf->yuv, sizeof(vgbuf->yuv));
|
|
||||||
|
|
||||||
vgbuf->memory = (void *)ptr;
|
|
||||||
vgbuf->address = (uint32_t)vgbuf->memory;
|
|
||||||
vgbuf->handle = NULL;
|
|
||||||
|
|
||||||
return LV_RES_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if BLIT_DBG_AREAS
|
|
||||||
void lv_vglite_dbg_draw_rectangle(lv_color_t * dest_buf, lv_coord_t dest_width, lv_coord_t dest_height,
|
|
||||||
lv_area_t * fill_area, lv_color_t color)
|
|
||||||
{
|
|
||||||
lv_area_t a;
|
|
||||||
|
|
||||||
/* top line */
|
|
||||||
a.x1 = fill_area->x1;
|
|
||||||
a.x2 = fill_area->x2;
|
|
||||||
a.y1 = fill_area->y1;
|
|
||||||
a.y2 = fill_area->y1;
|
|
||||||
lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER);
|
|
||||||
|
|
||||||
|
|
||||||
/* bottom line */
|
|
||||||
a.x1 = fill_area->x1;
|
|
||||||
a.x2 = fill_area->x2;
|
|
||||||
a.y1 = fill_area->y2;
|
|
||||||
a.y2 = fill_area->y2;
|
|
||||||
lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER);
|
|
||||||
|
|
||||||
/* left line */
|
|
||||||
a.x1 = fill_area->x1;
|
|
||||||
a.x2 = fill_area->x1;
|
|
||||||
a.y1 = fill_area->y1;
|
|
||||||
a.y2 = fill_area->y2;
|
|
||||||
lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER);
|
|
||||||
|
|
||||||
/* right line */
|
|
||||||
a.x1 = fill_area->x2;
|
|
||||||
a.x2 = fill_area->x2;
|
|
||||||
a.y1 = fill_area->y1;
|
|
||||||
a.y2 = fill_area->y2;
|
|
||||||
lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER);
|
|
||||||
}
|
|
||||||
#endif /* BLIT_DBG_AREAS */
|
|
||||||
|
|
||||||
void lv_vglite_invalidate_cache(void)
|
|
||||||
{
|
|
||||||
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
|
||||||
if(disp->driver->clean_dcache_cb)
|
|
||||||
disp->driver->clean_dcache_cb(disp->driver);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**********************
|
|
||||||
* STATIC FUNCTIONS
|
|
||||||
**********************/
|
|
||||||
|
|
||||||
#endif /*LV_USE_GPU_NXP_VG_LITE*/
|
|
||||||
143
src/draw/nxp/vglite/lv_vglite_buf.c
Normal file
143
src/draw/nxp/vglite/lv_vglite_buf.c
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_vglite_buf.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright 2023 NXP
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next paragraph)
|
||||||
|
* shall be included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||||
|
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||||
|
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "lv_vglite_buf.h"
|
||||||
|
|
||||||
|
#if LV_USE_GPU_NXP_VG_LITE
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#if LV_COLOR_DEPTH == 16
|
||||||
|
#define VG_LITE_PX_FMT VG_LITE_RGB565
|
||||||
|
#elif LV_COLOR_DEPTH == 32
|
||||||
|
#define VG_LITE_PX_FMT VG_LITE_BGRA8888
|
||||||
|
#else
|
||||||
|
#error Only 16bit and 32bit color depth are supported. Set LV_COLOR_DEPTH to 16 or 32.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
static inline void lv_vglite_set_dest_buf(const lv_color_t * buf, const lv_area_t * area, lv_coord_t stride);
|
||||||
|
static inline void lv_vglite_set_buf_ptr(vg_lite_buffer_t * vgbuf, const lv_color_t * buf);
|
||||||
|
static inline void lv_vglite_set_buf(vg_lite_buffer_t * vgbuf, const lv_color_t * buf,
|
||||||
|
const lv_area_t * area, lv_coord_t stride);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
static vg_lite_buffer_t dest_vgbuf;
|
||||||
|
static vg_lite_buffer_t src_vgbuf;
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
void lv_gpu_nxp_vglite_init_buf(const lv_color_t * buf, const lv_area_t * area, lv_coord_t stride)
|
||||||
|
{
|
||||||
|
lv_vglite_set_dest_buf(buf, area, stride);
|
||||||
|
}
|
||||||
|
|
||||||
|
vg_lite_buffer_t * lv_vglite_get_dest_buf(void)
|
||||||
|
{
|
||||||
|
return &dest_vgbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
vg_lite_buffer_t * lv_vglite_get_src_buf(void)
|
||||||
|
{
|
||||||
|
return &src_vgbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_vglite_set_dest_buf_ptr(const lv_color_t * buf)
|
||||||
|
{
|
||||||
|
lv_vglite_set_buf_ptr(&dest_vgbuf, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_vglite_set_src_buf_ptr(const lv_color_t * buf)
|
||||||
|
{
|
||||||
|
lv_vglite_set_buf_ptr(&src_vgbuf, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_vglite_set_src_buf(const lv_color_t * buf, const lv_area_t * area, lv_coord_t stride)
|
||||||
|
{
|
||||||
|
if(src_vgbuf.memory != (void *)buf)
|
||||||
|
lv_vglite_set_buf(&src_vgbuf, buf, area, stride);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
static inline void lv_vglite_set_dest_buf(const lv_color_t * buf, const lv_area_t * area, lv_coord_t stride)
|
||||||
|
{
|
||||||
|
lv_vglite_set_buf(&dest_vgbuf, buf, area, stride);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void lv_vglite_set_buf_ptr(vg_lite_buffer_t * vgbuf, const lv_color_t * buf)
|
||||||
|
{
|
||||||
|
vgbuf->memory = (void *)buf;
|
||||||
|
vgbuf->address = (uint32_t)vgbuf->memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void lv_vglite_set_buf(vg_lite_buffer_t * vgbuf, const lv_color_t * buf,
|
||||||
|
const lv_area_t * area, lv_coord_t stride)
|
||||||
|
{
|
||||||
|
vgbuf->format = VG_LITE_PX_FMT;
|
||||||
|
vgbuf->tiled = VG_LITE_LINEAR;
|
||||||
|
vgbuf->image_mode = VG_LITE_NORMAL_IMAGE_MODE;
|
||||||
|
vgbuf->transparency_mode = VG_LITE_IMAGE_OPAQUE;
|
||||||
|
|
||||||
|
vgbuf->width = (int32_t)lv_area_get_width(area);
|
||||||
|
vgbuf->height = (int32_t)lv_area_get_height(area);
|
||||||
|
vgbuf->stride = (int32_t)(stride) * sizeof(lv_color_t);
|
||||||
|
|
||||||
|
lv_memset(&vgbuf->yuv, 0, sizeof(vgbuf->yuv));
|
||||||
|
|
||||||
|
vgbuf->memory = (void *)buf;
|
||||||
|
vgbuf->address = (uint32_t)vgbuf->memory;
|
||||||
|
vgbuf->handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /*LV_USE_GPU_NXP_VG_LITE*/
|
||||||
113
src/draw/nxp/vglite/lv_vglite_buf.h
Normal file
113
src/draw/nxp/vglite/lv_vglite_buf.h
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_vglite_buf.h
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright 2023 NXP
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next paragraph)
|
||||||
|
* shall be included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||||
|
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||||
|
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LV_VGLITE_BUF_H
|
||||||
|
#define LV_VGLITE_BUF_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
#include "../../../lv_conf_internal.h"
|
||||||
|
|
||||||
|
#if LV_USE_GPU_NXP_VG_LITE
|
||||||
|
#include "vg_lite.h"
|
||||||
|
#include "../../sw/lv_draw_sw.h"
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
/**
|
||||||
|
* Init vglite destination buffer. It will be done once per frame.
|
||||||
|
*
|
||||||
|
* @param[in] buf Destination buffer address (does not require alignment for VG_LITE_LINEAR mode)
|
||||||
|
* @param[in] area Destination buffer area (for width and height)
|
||||||
|
* @param[in] stride Stride of destination buffer
|
||||||
|
*/
|
||||||
|
void lv_gpu_nxp_vglite_init_buf(const lv_color_t * buf, const lv_area_t * area, lv_coord_t stride);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get vglite destination buffer pointer.
|
||||||
|
*
|
||||||
|
* @retval The vglite destination buffer
|
||||||
|
*/
|
||||||
|
vg_lite_buffer_t * lv_vglite_get_dest_buf(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get vglite source buffer pointer.
|
||||||
|
*
|
||||||
|
* @retval The vglite source buffer
|
||||||
|
*/
|
||||||
|
vg_lite_buffer_t * lv_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 lv_vglite_set_dest_buf_ptr(const lv_color_t * buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set vglite source buffer address only.
|
||||||
|
*
|
||||||
|
* @param[in] buf Source buffer address
|
||||||
|
*/
|
||||||
|
void lv_vglite_set_src_buf_ptr(const lv_color_t * buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set vglite source buffer. It will be done only if buffer addreess is different.
|
||||||
|
*
|
||||||
|
* @param[in] buf Source buffer address
|
||||||
|
* @param[in] area Source buffer area (for width and height)
|
||||||
|
* @param[in] stride Stride of source buffer
|
||||||
|
*/
|
||||||
|
void lv_vglite_set_src_buf(const lv_color_t * buf, const lv_area_t * area, lv_coord_t stride);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
#endif /*LV_USE_GPU_NXP_VG_LITE*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /*extern "C"*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*LV_VGLITE_BUF_H*/
|
||||||
149
src/draw/nxp/vglite/lv_vglite_utils.c
Normal file
149
src/draw/nxp/vglite/lv_vglite_utils.c
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_vglite_utils.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright 2022, 2023 NXP
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next paragraph)
|
||||||
|
* shall be included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||||
|
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||||
|
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "lv_vglite_utils.h"
|
||||||
|
|
||||||
|
#if LV_USE_GPU_NXP_VG_LITE
|
||||||
|
#include "../../../core/lv_refr.h"
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean and invalidate cache.
|
||||||
|
*/
|
||||||
|
static inline void invalidate_cache(void);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
lv_res_t lv_vglite_run(void)
|
||||||
|
{
|
||||||
|
invalidate_cache();
|
||||||
|
|
||||||
|
VG_LITE_ERR_RETURN_INV(vg_lite_flush(), "Flush failed.");
|
||||||
|
|
||||||
|
return LV_RES_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_res_t lv_vglite_premult_and_swizzle(vg_lite_color_t * vg_col32, lv_color32_t lv_col32, lv_opa_t opa,
|
||||||
|
vg_lite_buffer_format_t vg_col_format)
|
||||||
|
{
|
||||||
|
|
||||||
|
lv_color32_t lv_col32_premul = lv_col32;
|
||||||
|
if(opa <= (lv_opa_t)LV_OPA_MAX) {
|
||||||
|
/* Only pre-multiply color if hardware pre-multiplication is not present */
|
||||||
|
if(!vg_lite_query_feature(gcFEATURE_BIT_VG_PE_PREMULTIPLY)) {
|
||||||
|
lv_col32_premul.ch.red = (uint8_t)(((uint16_t)lv_col32.ch.red * opa) >> 8);
|
||||||
|
lv_col32_premul.ch.green = (uint8_t)(((uint16_t)lv_col32.ch.green * opa) >> 8);
|
||||||
|
lv_col32_premul.ch.blue = (uint8_t)(((uint16_t)lv_col32.ch.blue * opa) >> 8);
|
||||||
|
}
|
||||||
|
lv_col32_premul.ch.alpha = opa;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(vg_col_format) {
|
||||||
|
case VG_LITE_BGRA8888:
|
||||||
|
*vg_col32 = lv_col32_premul.full;
|
||||||
|
break;
|
||||||
|
case VG_LITE_RGBA8888:
|
||||||
|
*vg_col32 = ((uint32_t)lv_col32_premul.ch.red << 24) | ((uint32_t)lv_col32_premul.ch.green << 16) |
|
||||||
|
((uint32_t)lv_col32_premul.ch.blue << 8) | (uint32_t)lv_col32_premul.ch.alpha;
|
||||||
|
break;
|
||||||
|
case VG_LITE_ABGR8888:
|
||||||
|
*vg_col32 = ((uint32_t)lv_col32_premul.ch.alpha << 24) | ((uint32_t)lv_col32_premul.ch.blue << 16) |
|
||||||
|
((uint32_t)lv_col32_premul.ch.green << 8) | (uint32_t)lv_col32_premul.ch.red;
|
||||||
|
break;
|
||||||
|
case VG_LITE_ARGB8888:
|
||||||
|
*vg_col32 = ((uint32_t)lv_col32_premul.ch.alpha << 24) | ((uint32_t)lv_col32_premul.ch.red << 16) |
|
||||||
|
((uint32_t)lv_col32_premul.ch.green << 8) | (uint32_t)lv_col32_premul.ch.blue;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return LV_RES_INV;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LV_RES_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
vg_lite_blend_t lv_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;
|
||||||
|
case LV_BLEND_MODE_REPLACE:
|
||||||
|
vg_blend_mode = VG_LITE_BLEND_NONE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
vg_blend_mode = VG_LITE_BLEND_SRC_OVER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return vg_blend_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
static inline void invalidate_cache(void)
|
||||||
|
{
|
||||||
|
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
||||||
|
if(disp->driver->clean_dcache_cb)
|
||||||
|
disp->driver->clean_dcache_cb(disp->driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /*LV_USE_GPU_NXP_VG_LITE*/
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
/**
|
/**
|
||||||
* @file lv_gpu_nxp_vglite.h
|
* @file lv_vglite_utils.h
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright 2020-2022 NXP
|
* Copyright 2022, 2023 NXP
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -27,8 +27,8 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LV_GPU_NXP_VGLITE_H
|
#ifndef LV_VGLITE_UTILS_H
|
||||||
#define LV_GPU_NXP_VGLITE_H
|
#define LV_VGLITE_UTILS_H
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -43,40 +43,21 @@ extern "C" {
|
|||||||
#include "vg_lite.h"
|
#include "vg_lite.h"
|
||||||
#include "../../sw/lv_draw_sw.h"
|
#include "../../sw/lv_draw_sw.h"
|
||||||
#include "../../../misc/lv_log.h"
|
#include "../../../misc/lv_log.h"
|
||||||
#include "fsl_debug_console.h"
|
|
||||||
|
|
||||||
/*********************
|
/*********************
|
||||||
* DEFINES
|
* DEFINES
|
||||||
*********************/
|
*********************/
|
||||||
|
|
||||||
/** Use this symbol as limit to disable feature (value has to be larger than supported resolution) */
|
|
||||||
#define LV_GPU_NXP_VG_LITE_FEATURE_DISABLED (1920*1080+1)
|
|
||||||
|
|
||||||
/** Stride in px required by VG-Lite HW. Don't change this. */
|
|
||||||
#define LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX 16U
|
|
||||||
|
|
||||||
#ifndef LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
#ifndef LV_GPU_NXP_VG_LITE_LOG_ERRORS
|
||||||
/** Enable logging of VG-Lite errors (\see LV_LOG_ERROR)*/
|
/** Enable logging of VG-Lite errors (\see LV_LOG_ERROR)*/
|
||||||
#define LV_GPU_NXP_VG_LITE_LOG_ERRORS 1
|
#define LV_GPU_NXP_VG_LITE_LOG_ERRORS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef LV_GPU_NXP_VG_LITE_LOG_TRACES
|
#ifndef LV_GPU_NXP_VG_LITE_LOG_TRACES
|
||||||
/** Enable logging of VG-Lite errors (\see LV_LOG_ERROR)*/
|
/** Enable logging of VG-Lite traces (\see LV_LOG_ERROR)*/
|
||||||
#define LV_GPU_NXP_VG_LITE_LOG_TRACES 0
|
#define LV_GPU_NXP_VG_LITE_LOG_TRACES 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Draw rectangles around BLIT tiles */
|
|
||||||
#define BLIT_DBG_AREAS 0
|
|
||||||
|
|
||||||
/* Print detailed info to SDK console (NOT to LVGL log system) */
|
|
||||||
#define BLIT_DBG_VERBOSE 0
|
|
||||||
|
|
||||||
/* Verbose debug print */
|
|
||||||
#if BLIT_DBG_VERBOSE
|
|
||||||
#define PRINT_BLT PRINTF
|
|
||||||
#else
|
|
||||||
#define PRINT_BLT(...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* The optimal Bezier control point offset for radial unit
|
/* The optimal Bezier control point offset for radial unit
|
||||||
* see: https://spencermortensen.com/articles/bezier-circle/
|
* see: https://spencermortensen.com/articles/bezier-circle/
|
||||||
@@ -95,36 +76,35 @@ extern "C" {
|
|||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fills vg_lite_buffer_t structure according given parameters.
|
* Premultiplies and swizzles given LVGL 32bit color to obtain vglite color.
|
||||||
*
|
*
|
||||||
* @param[in/out] vgbuf Buffer structure to be filled
|
* @param[in/out] vg_col32 The obtained vglite color
|
||||||
* @param[in] width Width of buffer in pixels
|
* @param[in] lv_col32 The initial LVGL 32bit color
|
||||||
* @param[in] height Height of buffer in pixels
|
* @param[in] opa The opacity to premultiply with
|
||||||
* @param[in] stride Stride of the buffer in bytes
|
* @param[in] vg_col_format The format of the resulting vglite color
|
||||||
* @param[in] ptr Pointer to the buffer (must be aligned according VG-Lite requirements)
|
|
||||||
* @param[in] source Boolean to check if this is a source buffer
|
|
||||||
*/
|
|
||||||
lv_res_t lv_vglite_init_buf(vg_lite_buffer_t * vgbuf, uint32_t width, uint32_t height, uint32_t stride,
|
|
||||||
const lv_color_t * ptr, bool source);
|
|
||||||
|
|
||||||
#if BLIT_DBG_AREAS
|
|
||||||
/**
|
|
||||||
* Draw a simple rectangle, 1 px line width.
|
|
||||||
*
|
*
|
||||||
* @param dest_buf Destination buffer
|
* @retval LV_RES_OK Operation completed
|
||||||
* @param dest_width Destination buffer width (must be aligned on 16px)
|
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
|
||||||
* @param dest_height Destination buffer height
|
|
||||||
* @param fill_area Rectangle coordinates
|
|
||||||
* @param color Rectangle color
|
|
||||||
*/
|
*/
|
||||||
void lv_vglite_dbg_draw_rectangle(lv_color_t * dest_buf, lv_coord_t dest_width, lv_coord_t dest_height,
|
lv_res_t lv_vglite_premult_and_swizzle(vg_lite_color_t * vg_col32, lv_color32_t lv_col32, lv_opa_t opa,
|
||||||
lv_area_t * fill_area, lv_color_t color);
|
vg_lite_buffer_format_t vg_col_format);
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clean & invalidate cache.
|
* Get vglite blend mode.
|
||||||
|
*
|
||||||
|
* @param[in] lv_blend_mode The LVGL blend mode
|
||||||
|
*
|
||||||
|
* @retval The vglite blend mode
|
||||||
*/
|
*/
|
||||||
void lv_vglite_invalidate_cache(void);
|
vg_lite_blend_t lv_vglite_get_blend_mode(lv_blend_mode_t lv_blend_mode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear cache and flush command to VG-Lite.
|
||||||
|
*
|
||||||
|
* @retval LV_RES_OK Run completed
|
||||||
|
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
|
||||||
|
*/
|
||||||
|
lv_res_t lv_vglite_run(void);
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* MACROS
|
* MACROS
|
||||||
@@ -142,7 +122,8 @@ void lv_vglite_invalidate_cache(void);
|
|||||||
#define VG_LITE_ERR_RETURN_INV(err, fmt, ...) \
|
#define VG_LITE_ERR_RETURN_INV(err, fmt, ...) \
|
||||||
do { \
|
do { \
|
||||||
if(err != VG_LITE_SUCCESS) { \
|
if(err != VG_LITE_SUCCESS) { \
|
||||||
LV_LOG_ERROR(fmt, ##__VA_ARGS__); \
|
LV_LOG_ERROR(fmt" (err = %d)", \
|
||||||
|
err, ##__VA_ARGS__); \
|
||||||
return LV_RES_INV; \
|
return LV_RES_INV; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
@@ -158,7 +139,7 @@ void lv_vglite_invalidate_cache(void);
|
|||||||
#if LV_GPU_NXP_VG_LITE_LOG_TRACES
|
#if LV_GPU_NXP_VG_LITE_LOG_TRACES
|
||||||
#define VG_LITE_LOG_TRACE(fmt, ...) \
|
#define VG_LITE_LOG_TRACE(fmt, ...) \
|
||||||
do { \
|
do { \
|
||||||
LV_LOG_ERROR(fmt, ##__VA_ARGS__); \
|
LV_LOG(fmt, ##__VA_ARGS__); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define VG_LITE_RETURN_INV(fmt, ...) \
|
#define VG_LITE_RETURN_INV(fmt, ...) \
|
||||||
@@ -182,4 +163,4 @@ void lv_vglite_invalidate_cache(void);
|
|||||||
} /*extern "C"*/
|
} /*extern "C"*/
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /*LV_GPU_NXP_VGLITE_H*/
|
#endif /*LV_VGLITE_UTILS_H*/
|
||||||
@@ -35,8 +35,12 @@
|
|||||||
#include "../draw/arm2d/lv_gpu_arm2d.h"
|
#include "../draw/arm2d/lv_gpu_arm2d.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LV_USE_GPU_NXP_PXP || LV_USE_GPU_NXP_VG_LITE
|
#if LV_USE_GPU_NXP_VG_LITE
|
||||||
#include "../draw/nxp/lv_gpu_nxp.h"
|
#include "../draw/nxp/vglite/lv_draw_vglite.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LV_USE_GPU_NXP_PXP
|
||||||
|
#include "../draw/nxp/pxp/lv_draw_pxp.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LV_USE_THEME_DEFAULT
|
#if LV_USE_THEME_DEFAULT
|
||||||
@@ -110,10 +114,14 @@ void lv_disp_drv_init(lv_disp_drv_t * driver)
|
|||||||
driver->draw_ctx_init = lv_draw_swm341_dma2d_ctx_init;
|
driver->draw_ctx_init = lv_draw_swm341_dma2d_ctx_init;
|
||||||
driver->draw_ctx_deinit = lv_draw_swm341_dma2d_ctx_deinit;
|
driver->draw_ctx_deinit = lv_draw_swm341_dma2d_ctx_deinit;
|
||||||
driver->draw_ctx_size = sizeof(lv_draw_swm341_dma2d_ctx_t);
|
driver->draw_ctx_size = sizeof(lv_draw_swm341_dma2d_ctx_t);
|
||||||
#elif LV_USE_GPU_NXP_PXP || LV_USE_GPU_NXP_VG_LITE
|
#elif LV_USE_GPU_NXP_VG_LITE
|
||||||
driver->draw_ctx_init = lv_draw_nxp_ctx_init;
|
driver->draw_ctx_init = lv_draw_vglite_ctx_init;
|
||||||
driver->draw_ctx_deinit = lv_draw_nxp_ctx_deinit;
|
driver->draw_ctx_deinit = lv_draw_vglite_ctx_deinit;
|
||||||
driver->draw_ctx_size = sizeof(lv_draw_nxp_ctx_t);
|
driver->draw_ctx_size = sizeof(lv_draw_vglite_ctx_t);
|
||||||
|
#elif LV_USE_GPU_NXP_PXP
|
||||||
|
driver->draw_ctx_init = lv_draw_pxp_ctx_init;
|
||||||
|
driver->draw_ctx_deinit = lv_draw_pxp_ctx_deinit;
|
||||||
|
driver->draw_ctx_size = sizeof(lv_draw_pxp_ctx_t);
|
||||||
#elif LV_USE_DRAW_SDL
|
#elif LV_USE_DRAW_SDL
|
||||||
driver->draw_ctx_init = lv_draw_sdl_init_ctx;
|
driver->draw_ctx_init = lv_draw_sdl_init_ctx;
|
||||||
driver->draw_ctx_deinit = lv_draw_sdl_deinit_ctx;
|
driver->draw_ctx_deinit = lv_draw_sdl_deinit_ctx;
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ lv_obj_t * lv_animimg_create(lv_obj_t * parent)
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lv_animimg_set_src(lv_obj_t * obj, lv_img_dsc_t * dsc[], uint8_t num)
|
void lv_animimg_set_src(lv_obj_t * obj, const void * dsc[], uint8_t num)
|
||||||
{
|
{
|
||||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||||
lv_animimg_t * animimg = (lv_animimg_t *)obj;
|
lv_animimg_t * animimg = (lv_animimg_t *)obj;
|
||||||
@@ -103,7 +103,7 @@ void lv_animimg_set_repeat_count(lv_obj_t * obj, uint16_t count)
|
|||||||
* Getter functions
|
* Getter functions
|
||||||
*====================*/
|
*====================*/
|
||||||
|
|
||||||
lv_img_dsc_t ** lv_animimg_get_src(lv_obj_t * obj)
|
const void ** lv_animimg_get_src(lv_obj_t * obj)
|
||||||
{
|
{
|
||||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||||
lv_animimg_t * animimg = (lv_animimg_t *)obj;
|
lv_animimg_t * animimg = (lv_animimg_t *)obj;
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ typedef struct {
|
|||||||
lv_img_t img;
|
lv_img_t img;
|
||||||
lv_anim_t anim;
|
lv_anim_t anim;
|
||||||
/*picture sequence */
|
/*picture sequence */
|
||||||
lv_img_dsc_t ** dsc;
|
const void ** dsc;
|
||||||
int8_t pic_count;
|
int8_t pic_count;
|
||||||
} lv_animimg_t;
|
} lv_animimg_t;
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ lv_obj_t * lv_animimg_create(lv_obj_t * parent);
|
|||||||
* @param dsc pointer to a series images
|
* @param dsc pointer to a series images
|
||||||
* @param num images' number
|
* @param num images' number
|
||||||
*/
|
*/
|
||||||
void lv_animimg_set_src(lv_obj_t * img, lv_img_dsc_t * dsc[], uint8_t num);
|
void lv_animimg_set_src(lv_obj_t * img, const void * dsc[], uint8_t num);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Startup the image animation.
|
* Startup the image animation.
|
||||||
@@ -99,7 +99,7 @@ void lv_animimg_set_repeat_count(lv_obj_t * img, uint16_t count);
|
|||||||
* @param img pointer to an animation image object
|
* @param img pointer to an animation image object
|
||||||
* @return a pointer that will point to a series images
|
* @return a pointer that will point to a series images
|
||||||
*/
|
*/
|
||||||
lv_img_dsc_t ** lv_animimg_get_src(lv_obj_t * img);
|
const void ** lv_animimg_get_src(lv_obj_t * img);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the image animation images source.
|
* Get the image animation images source.
|
||||||
|
|||||||
@@ -44,16 +44,16 @@ void test_animimg_successful_create(void)
|
|||||||
|
|
||||||
void test_animimg_set_src(void)
|
void test_animimg_set_src(void)
|
||||||
{
|
{
|
||||||
lv_animimg_set_src(animimg, (lv_img_dsc_t **) anim_imgs, 3);
|
lv_animimg_set_src(animimg, (const void **) anim_imgs, 3);
|
||||||
|
|
||||||
TEST_ASSERT_NOT_NULL(animimg);
|
TEST_ASSERT_NOT_NULL(animimg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_animimg_get_src(void)
|
void test_animimg_get_src(void)
|
||||||
{
|
{
|
||||||
lv_animimg_set_src(animimg, (lv_img_dsc_t **) anim_imgs, 3);
|
lv_animimg_set_src(animimg, (const void **) anim_imgs, 3);
|
||||||
|
|
||||||
lv_img_dsc_t ** actual_dsc = lv_animimg_get_src(animimg);
|
const void ** actual_dsc = lv_animimg_get_src(animimg);
|
||||||
|
|
||||||
TEST_ASSERT_NOT_NULL(actual_dsc);
|
TEST_ASSERT_NOT_NULL(actual_dsc);
|
||||||
TEST_ASSERT_EQUAL_PTR(actual_dsc, anim_imgs);
|
TEST_ASSERT_EQUAL_PTR(actual_dsc, anim_imgs);
|
||||||
@@ -64,7 +64,7 @@ void test_animimg_get_src_count(void)
|
|||||||
{
|
{
|
||||||
uint8_t expected_count = 3;
|
uint8_t expected_count = 3;
|
||||||
|
|
||||||
lv_animimg_set_src(animimg, (lv_img_dsc_t **) anim_imgs, expected_count);
|
lv_animimg_set_src(animimg, (const void **) anim_imgs, expected_count);
|
||||||
|
|
||||||
uint8_t actual_count = lv_animimg_get_src_count(animimg);
|
uint8_t actual_count = lv_animimg_get_src_count(animimg);
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ void test_animimg_start(void)
|
|||||||
{
|
{
|
||||||
// for lv_animimg_start() to actually work,
|
// for lv_animimg_start() to actually work,
|
||||||
// we need to properly setup the widget beforehand
|
// we need to properly setup the widget beforehand
|
||||||
lv_animimg_set_src(animimg, (lv_img_dsc_t **) anim_imgs, 3);
|
lv_animimg_set_src(animimg, (const void **) anim_imgs, 3);
|
||||||
lv_animimg_set_duration(animimg, 1000);
|
lv_animimg_set_duration(animimg, 1000);
|
||||||
lv_animimg_set_repeat_count(animimg, LV_ANIM_REPEAT_INFINITE);
|
lv_animimg_set_repeat_count(animimg, LV_ANIM_REPEAT_INFINITE);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user