feat(nxp): release NXP PXP and VG-Lite for LVGL v9.0 (#5288)
Signed-off-by: Nicușor Cîțu <nicusor.citu@nxp.com> Signed-off-by: Ana Grad <ana.grad@nxp.com> Co-authored-by: Ana Grad <ana.grad@nxp.com>
This commit is contained in:
@@ -2,158 +2,191 @@
|
||||
NXP
|
||||
===
|
||||
|
||||
NXP has integrated LVGL into the MCUXpresso SDK packages for general
|
||||
purpose and crossover microcontrollers, allowing 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>`__
|
||||
today and get started with your next GUI application.
|
||||
NXP has integrated LVGL into the MCUXpresso SDK packages for several of our
|
||||
microcontrollers as an optional software component, allowing easy evaluation and
|
||||
migration into your product design. LVGL is a free and open-source embedded
|
||||
graphic library with features that enable you need to create embedded GUIs with
|
||||
intuitive graphical elements, beautiful visual effects and a low memory
|
||||
footprint. The complete graphic framework includes a variety of widgets for you
|
||||
to use in the creation of your GUI, and supports more advanced functions such as
|
||||
animations and anti-aliasing.
|
||||
|
||||
LVGL enables graphics in our free GUI Guider UI tool. It's available for use
|
||||
with NXP’s general purpose and crossover microcontrollers, providing developers
|
||||
with a tool for creating complete, high quality GUI applications with LVGL.
|
||||
|
||||
Creating new project with LVGL
|
||||
------------------------------
|
||||
|
||||
Downloading the MCU SDK example project is recommended as a starting
|
||||
point. It comes fully configured with LVGL (and with PXP/VGLite support
|
||||
if the modules are present), no additional integration work is required.
|
||||
|
||||
`Download an SDK for a supported board <https://www.nxp.com/design/software/embedded-software/littlevgl-open-source-graphics-library:LITTLEVGL-OPEN-SOURCE-GRAPHICS-LIBRARY?&tid=vanLITTLEVGL-OPEN-SOURCE-GRAPHICS-LIBRARY>`__
|
||||
today and get started with your next GUI application. It comes fully configured
|
||||
with LVGL (and with PXP/VGLite support if the modules are present), no
|
||||
additional integration work is required.
|
||||
|
||||
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 through an API named
|
||||
VGLite. Each accelerator has its own context that allows them to be used
|
||||
individually as well simultaneously (in LVGL multithreading mode).
|
||||
|
||||
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. Each
|
||||
accelerator has its own context that allows them to be used individually as well
|
||||
simultaneously (in LVGL multithreading mode).
|
||||
|
||||
PXP accelerator
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Several drawing features in LVGL can be offloaded to the PXP engine. The
|
||||
CPU is available for other operations while the PXP is running. RTOS is
|
||||
required to block the LVGL drawing thread and switch to another task or
|
||||
suspend the CPU for power savings.
|
||||
|
||||
Supported draw callbacks are available in "src/draw/nxp/pxp/lv_draw_pxp.c":
|
||||
|
||||
.. code:: 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:
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
All operations can be used in conjunction with optional transparency.
|
||||
|
||||
- RGB565 and ARGB8888 color formats
|
||||
- Area fill with color
|
||||
- BLIT (BLock Image Transfer)
|
||||
- Screen Rotation (90, 180, 270 degree)
|
||||
- Color keying
|
||||
- Recoloring (color tint)
|
||||
- Image Rotation (90, 180, 270 degree)
|
||||
- RTOS integration layer
|
||||
- Default FreeRTOS and bare metal code provided
|
||||
- Combination of recolor and/or rotation + color key/alpha
|
||||
blend/transparency is supported. That is achieved by PXP in two
|
||||
steps:
|
||||
|
||||
- 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:
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Rotation is not supported for images unaligned to blocks of 16x16
|
||||
pixels. 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.
|
||||
|
||||
|
||||
Basic configuration:
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Select NXP PXP engine in lv_conf.h: Set :c:macro:`LV_USE_GPU_NXP_PXP` to ``1``
|
||||
- Enable default implementation for interrupt handling, PXP start
|
||||
function and automatic initialization: Set
|
||||
:c:macro:`LV_USE_GPU_NXP_PXP_AUTO_INIT` to ``1``
|
||||
- Select NXP PXP engine in "lv_conf.h": Set :c:macro:`LV_USE_DRAW_PXP` to `1`.
|
||||
- Enable PXP asserts in "lv_conf.h": Set :c:macro: `LV_USE_PXP_ASSERT` to `1`.
|
||||
There are few PXP assertions that can stop the program execution in case the
|
||||
c:macro: `LV_ASSERT_HANDLER` is set to `while(1);` (Halt by default). Else,
|
||||
there will be logged just an error message via `LV_LOG_ERROR`.
|
||||
- If :c:macro:`SDK_OS_FREE_RTOS` symbol is defined, FreeRTOS implementation
|
||||
will be used, otherwise bare metal code will be included
|
||||
|
||||
will be used, otherwise bare metal code will be included.
|
||||
|
||||
Basic initialization:
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- If :c:macro:`LV_USE_GPU_NXP_PXP_AUTO_INIT` is enabled, no user code is
|
||||
required; PXP is initialized automatically in :cpp:func:`lv_init`
|
||||
- For manual PXP initialization, default configuration structure for
|
||||
callbacks can be used. Initialize PXP before calling :cpp:func:`lv_init`
|
||||
PXP draw initialization is done automatically in :cpp:func:`lv_init()` once the
|
||||
PXP is enabled, no user code is required:
|
||||
|
||||
.. code:: c
|
||||
|
||||
#if LV_USE_GPU_NXP_PXP
|
||||
#include "src/draw/nxp/pxp/lv_gpu_nxp_pxp.h"
|
||||
#endif
|
||||
...
|
||||
#if LV_USE_GPU_NXP_PXP
|
||||
PXP_COND_STOP(!lv_gpu_nxp_pxp_init(), "PXP init failed.");
|
||||
#endif
|
||||
#if LV_USE_DRAW_PXP
|
||||
lv_draw_pxp_init();
|
||||
#endif
|
||||
|
||||
During PXP initialization, a new draw unit `lv_draw_pxp_unit_t` will be created
|
||||
with the additional callbacks:
|
||||
|
||||
.. code:: c
|
||||
|
||||
lv_draw_pxp_unit_t * draw_pxp_unit = lv_draw_create_unit(sizeof(lv_draw_pxp_unit_t));
|
||||
draw_pxp_unit->base_unit.evaluate_cb = _pxp_evaluate;
|
||||
draw_pxp_unit->base_unit.dispatch_cb = _pxp_dispatch;
|
||||
draw_pxp_unit->base_unit.delete_cb = _pxp_delete;
|
||||
|
||||
and an addition thread `_pxp_render_thread_cb()` will be spawned in order to
|
||||
handle the supported draw tasks.
|
||||
|
||||
.. code:: c
|
||||
|
||||
#if LV_USE_OS
|
||||
lv_thread_init(&draw_pxp_unit->thread, LV_THREAD_PRIO_HIGH, _pxp_render_thread_cb, 2 * 1024, draw_pxp_unit);
|
||||
#endif
|
||||
|
||||
If `LV_USE_OS` is not defined, then no additional draw thread will be created
|
||||
and the PXP drawing task will get executed on the same LVGL main thread.
|
||||
|
||||
`_pxp_evaluate()` will get called after each task is being created and will
|
||||
analyze if the task is supported by PXP or not. If it is supported, then an
|
||||
preferred score and the draw unit id will be set to the task. An `score` equal
|
||||
to `100` is the default CPU score. Smaller score means that PXP is capable of
|
||||
drawing it faster.
|
||||
|
||||
`_pxp_dispatch()` is the PXP dispatcher callback, it will take a ready to draw
|
||||
task (having the `DRAW_UNIT_ID_PXP` set) and will pass the task to the PXP draw
|
||||
unit for processing.
|
||||
|
||||
`_pxp_delete()` will cleanup the PXP draw unit.
|
||||
|
||||
Features supported:
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Several drawing features in LVGL can be offloaded to the PXP engine. The CPU is
|
||||
available for other operations while the PXP is running. RTOS is required to
|
||||
block the LVGL drawing thread and switch to another task or suspend the CPU for
|
||||
power savings.
|
||||
|
||||
Supported draw tasks are available in "src/draw/nxp/pxp/lv_draw_pxp.c":
|
||||
|
||||
.. code:: c
|
||||
|
||||
switch(t->type) {
|
||||
case LV_DRAW_TASK_TYPE_FILL:
|
||||
lv_draw_pxp_fill(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_IMAGE:
|
||||
lv_draw_pxp_img(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_LAYER:
|
||||
lv_draw_pxp_layer(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Additional, the screen rotation can be handled by the PXP:
|
||||
|
||||
.. code::c
|
||||
|
||||
void lv_draw_pxp_rotate(const void * src_buf, void * dest_buf, int32_t src_width, int32_t src_height,
|
||||
int32_t src_stride, int32_t dest_stride, lv_display_rotation_t rotation,
|
||||
lv_color_format_t cf);
|
||||
|
||||
- Fill area with color (w/o radius, w/o gradient) + optional opacity.
|
||||
- Blit source image RGB565/ARGB888/XRGB8888 over destination.
|
||||
RGB565/RGB888/ARGB888/XRGB8888 + optional opacity.
|
||||
- Recolor source image RGB565.
|
||||
- Scale and rotate (90, 180, 270 degree) source image RGB565.
|
||||
- Blending layers (w/ same supported formats as blitting).
|
||||
- Rotate screen (90, 180, 270 degree).
|
||||
|
||||
Known limitations:
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- PXP can only rotate at 90x angles.
|
||||
- Rotation is not supported for images unaligned to blocks of 16x16 pixels. PXP
|
||||
is set to process 16x16 blocks to optimize the system for memory bandwidth and
|
||||
image processing time. The output engine essentially truncates any output
|
||||
pixels after the desired number of pixels has been written. When rotating a
|
||||
source image and the output is not divisible by the block size, the incorrect
|
||||
pixels could be truncated and the final output image can look shifted.
|
||||
- Recolor or transformation for images w/ opacity or alpha channel can't be
|
||||
obtained in a single PXP pipeline configuration. Two or multiple steps would
|
||||
be required.
|
||||
- Buffer address must be aligned to 64 bytes: set :c:macro:`LV_DRAW_BUF_ALIGN`
|
||||
to `64` in "lv_conf.h".
|
||||
No stride alignment is required: set :c:macro:`LV_DRAW_BUF_STRIDE_ALIGN` to
|
||||
`1` in "lv_conf.h".
|
||||
|
||||
Project setup:
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
- Add PXP related files to project:
|
||||
- Add PXP related source files (and corresponding headers if available) to
|
||||
project:
|
||||
|
||||
- src/draw/nxp/pxp/lv_draw_pxp.c[.h]: draw context callbacks
|
||||
- src/draw/nxp/pxp/lv_draw_pxp_blend.c[.h]: fill and blit (with optional transformation)
|
||||
- src/draw/nxp/pxp/lv_gpu_nxp_pxp.c[.h]: init, uninit, run/wait PXP device
|
||||
- src/draw/nxp/pxp/lv_gpu_nxp_pxp_osa.c[.h]: OS abstraction (FreeRTOS or bare metal)
|
||||
- "src/draw/nxp/pxp/lv_draw_buf_pxp.c": draw buffer callbacks
|
||||
- "src/draw/nxp/pxp/lv_draw_pxp_fill.c": fill area
|
||||
- "src/draw/nxp/pxp/lv_draw_pxp_img.c": blit image (w/ optional recolor or
|
||||
transformation)
|
||||
- "src/draw/nxp/pxp/lv_draw_pxp_layer.c": layer blending
|
||||
- "src/draw/nxp/pxp/lv_draw_pxp.c": draw unit initialization
|
||||
- "src/draw/nxp/pxp/lv_pxp_cfg.c": init, deinit, run/wait PXP device
|
||||
- "src/draw/nxp/pxp/lv_pxp_osa.c": OS abstraction (FreeRTOS or bare metal)
|
||||
- "src/draw/nxp/pxp/lv_pxp_utils.c": function helpers
|
||||
|
||||
- optional, required only if :c:macro:`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: PXP driver
|
||||
- fsl_cache.c: CPU cache handling functions
|
||||
|
||||
- fsl_pxp.c[.h]: PXP driver
|
||||
- fsl_cache.c[.h]: CPU cache handling functions
|
||||
|
||||
|
||||
Logging:
|
||||
^^^^^^^^
|
||||
|
||||
- By default, :c:macro:`LV_GPU_NXP_PXP_LOG_ERRORS` is enabled so that any PXP error will be seen on SDK debug console
|
||||
- By default, :c:macro:`LV_GPU_NXP_PXP_LOG_TRACES` is disabled. Enable it for tracing logs (like PXP limitations)
|
||||
|
||||
|
||||
Advanced configuration:
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
PXP default configuration:
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Implementation depends on multiple OS-specific functions. The struct
|
||||
:cpp:struct:`lv_nxp_pxp_cfg_t` with callback pointers is used as a parameter
|
||||
for the :cpp:func:`lv_gpu_nxp_pxp_init` function. Default implementation
|
||||
for FreeRTOS and bare metal is provided in lv_gpu_nxp_pxp_osa.c
|
||||
|
||||
- :cpp:func:`pxp_interrupt_init`: Initialize PXP interrupt (HW setup, OS setup)
|
||||
- :cpp:func:`pxp_interrupt_deinit`: Deinitialize PXP interrupt (HW setup, OS setup)
|
||||
- :cpp:func:`pxp_run`: Start PXP job. Use OS-specific mechanism to block drawing thread.
|
||||
PXP must finish drawing before leaving this function.
|
||||
|
||||
- Area threshold (size limit) is configurable and used to decide
|
||||
whether the area will be processed by PXP or not. Areas smaller than
|
||||
the defined value will be processed by CPU and those bigger than the
|
||||
threshold will be processed by PXP. The threshold is defined as a
|
||||
macro in lv_draw_pxp.c
|
||||
|
||||
- :c:macro:`LV_GPU_NXP_PXP_SIZE_LIMIT`: size threshold for fill/blit (with optional transformation)
|
||||
:cpp:struct:`pxp_cfg_t` with callback pointers is used as a parameter for the
|
||||
:cpp:func:`lv_pxp_init()` function. Default implementation for FreeRTOS and
|
||||
bare metal is provided in lv_pxp_osa.c.
|
||||
|
||||
- :cpp:func:`pxp_interrupt_init()`: Initialize PXP interrupt (HW setup,
|
||||
OS setup)
|
||||
- :cpp:func:`pxp_interrupt_deinit()`: Deinitialize PXP interrupt (HW setup,
|
||||
OS setup)
|
||||
- :cpp:func:`pxp_run()`: Start PXP job. Use OS-specific mechanism to block
|
||||
drawing thread.
|
||||
- :cpp:func:`pxp_wait()`: Wait for PXP completion.
|
||||
|
||||
VGLite accelerator
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
@@ -163,116 +196,203 @@ CPU is available for other operations while the VGLite is running. An
|
||||
RTOS is required to block the LVGL drawing thread and switch to another
|
||||
task or suspend the CPU for power savings.
|
||||
|
||||
Supported draw callbacks are available in "src/draw/nxp/vglite/lv_draw_vglite.c":
|
||||
|
||||
.. code:: 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-1:
|
||||
|
||||
|
||||
Features supported:
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
All operations can be used in conjunction with optional transparency.
|
||||
|
||||
- RGB565 and ARGB8888 color formats
|
||||
- Area fill with color
|
||||
- BLIT (BLock Image Transfer)
|
||||
- Image Rotation (any degree with decimal)
|
||||
- Image Scale
|
||||
- Draw rectangle background with optional radius or gradient
|
||||
- Blit rectangle background image
|
||||
- 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-1:
|
||||
|
||||
|
||||
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
|
||||
(:c:macro:`VG_LITE_LINEAR`).
|
||||
|
||||
.. _basic-configuration-1:
|
||||
|
||||
|
||||
Basic configuration:
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Select NXP VGLite engine in lv_conf.h: Set :c:macro:`LV_USE_GPU_NXP_VG_LITE` to 1
|
||||
- :c:macro:`SDK_OS_FREE_RTOS` symbol needs to be defined so that the FreeRTOS implementation will be used
|
||||
|
||||
.. _basic-initialization-1:
|
||||
- Select NXP VGLite engine in "lv_conf.h": Set :c:macro:`LV_USE_DRAW_VGLITE` to
|
||||
`1`. :c:macro:`SDK_OS_FREE_RTOS` symbol needs to be defined so that FreeRTOS
|
||||
driver osal implementation will be enabled.
|
||||
- Enable VGLite asserts in "lv_conf.h": Set :c:macro: `LV_USE_VGLITE_ASSERT` to
|
||||
`1`.
|
||||
VGLite assertions will verify the driver API status code and in any error, it
|
||||
can stop the program execution in case the c:macro: `LV_ASSERT_HANDLER` is set
|
||||
to `while(1);` (Halt by default). Else, there will be logged just an error
|
||||
message via `LV_LOG_ERROR`.
|
||||
|
||||
Basic initialization:
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Initialize VGLite before calling :cpp:func:`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 the
|
||||
frame width. If less than or equal to 0, then no tessellation buffer
|
||||
is created, in which case VGLite is initialized only for blitting.
|
||||
Initialize VGLite GPU before calling :cpp:func:`lv_init()` by specifying the
|
||||
width/height of tessellation window. The default values for tesselation width
|
||||
and height, and command buffer size are in the SDK file "vglite_support.h".
|
||||
|
||||
.. code:: c
|
||||
|
||||
#if LV_USE_GPU_NXP_VG_LITE
|
||||
#if LV_USE_GPU_NXP_VG_LITE
|
||||
#include "vg_lite.h"
|
||||
#endif
|
||||
#include "vglite_support.h"
|
||||
#endif
|
||||
...
|
||||
#if LV_USE_GPU_NXP_VG_LITE
|
||||
VG_LITE_COND_STOP(vg_lite_init(64, 64) != VG_LITE_SUCCESS, "VGLite init failed.");
|
||||
#endif
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
if(vg_lite_init(DEFAULT_VG_LITE_TW_WIDTH, DEFAULT_VG_LITE_TW_HEIGHT) != VG_LITE_SUCCESS)
|
||||
{
|
||||
PRINTF("VGLite init error. STOP.");
|
||||
vg_lite_close();
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
.. _project-setup-1:
|
||||
if (vg_lite_set_command_buffer_size(VG_LITE_COMMAND_BUFFER_SIZE) != VG_LITE_SUCCESS)
|
||||
{
|
||||
PRINTF("VGLite set command buffer. STOP.");
|
||||
vg_lite_close();
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
#endif
|
||||
|
||||
Project setup:
|
||||
^^^^^^^^^^^^^^
|
||||
VGLite draw initialization is done automatically in :cpp:func:`lv_init()` once
|
||||
the VGLite is enabled, no user code is required:
|
||||
|
||||
- Add VGLite related files to project:
|
||||
.. code:: c
|
||||
|
||||
- src/draw/nxp/vglite/lv_draw_vglite.c[.h]: draw context callbacks
|
||||
- src/draw/nxp/vglite/lv_draw_vglite_blend.c[.h]: fill and blit (with optional transformation)
|
||||
- src/draw/nxp/vglite/lv_draw_vglite_rect.c[.h]: draw rectangle
|
||||
- src/draw/nxp/vglite/lv_draw_vglite_arc.c[.h]: draw arc
|
||||
- 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
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
lv_draw_vglite_init();
|
||||
#endif
|
||||
|
||||
.. _logging-1:
|
||||
During VGLite initialization, a new draw unit `lv_draw_vglite_unit_t` will be
|
||||
created with the additional callbacks:
|
||||
|
||||
Logging:
|
||||
^^^^^^^^
|
||||
.. code:: c
|
||||
|
||||
- By default, :c:macro:`LV_GPU_NXP_VG_LITE_LOG_ERRORS` is enabled so that any VGLite error will be seen on SDK debug console
|
||||
- By default, :c:macro:`LV_GPU_NXP_VG_LITE_LOG_TRACES` is disabled. Enable it
|
||||
for tracing logs (like blit split workaround or VGLite fallback to CPU due to any error on the driver)
|
||||
lv_draw_vglite_unit_t * draw_vglite_unit = lv_draw_create_unit(sizeof(lv_draw_vglite_unit_t));
|
||||
draw_vglite_unit->base_unit.evaluate_cb = _vglite_evaluate;
|
||||
draw_vglite_unit->base_unit.dispatch_cb = _vglite_dispatch;
|
||||
draw_vglite_unit->base_unit.delete_cb = _vglite_delete;
|
||||
|
||||
.. _advanced-configuration-1:
|
||||
and an addition thread `_vglite_render_thread_cb()` will be spawned in order to
|
||||
handle the supported draw tasks.
|
||||
|
||||
.. code:: c
|
||||
|
||||
#if LV_USE_OS
|
||||
lv_thread_init(&draw_vglite_unit->thread, LV_THREAD_PRIO_HIGH, _vglite_render_thread_cb, 2 * 1024, draw_vglite_unit);
|
||||
#endif
|
||||
|
||||
If `LV_USE_OS` is not defined, then no additional draw thread will be created
|
||||
and the VGLite drawing task will get executed on the same LVGL main thread.
|
||||
|
||||
`_vglite_evaluate()` will get called after each task is being created and will
|
||||
analyze if the task is supported by VGLite or not. If it is supported, then an
|
||||
preferred score and the draw unit id will be set to the task. An `score` equal
|
||||
to `100` is the default CPU score. Smaller score means that VGLite is capable of
|
||||
drawing it faster.
|
||||
|
||||
`_vglite_dispatch()` is the VGLite dispatcher callback, it will take a ready to
|
||||
draw task (having the `DRAW_UNIT_ID_VGLITE` set) and will pass the task to the
|
||||
VGLite draw unit for processing.
|
||||
|
||||
`_vglite_delete()` will cleanup the VGLite draw unit.
|
||||
|
||||
Advanced configuration:
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Area threshold (size limit) is configurable and used to decide
|
||||
whether the area will be processed by VGLite or not. Areas smaller
|
||||
than the defined value will be processed by CPU and those bigger than
|
||||
the threshold will be processed by VGLite. The threshold is defined
|
||||
as a macro in lv_draw_vglite.c
|
||||
- Enable VGLite blit split in "lv_conf.h":
|
||||
Set :c:macro: `LV_USE_VGLITE_BLIT_SPLIT` to `1`.
|
||||
Enabling the blit split workaround will mitigate any quality degradation issue
|
||||
on screen's dimension > 352 pixels.
|
||||
|
||||
- :c:macro:`LV_GPU_NXP_VG_LITE_SIZE_LIMIT`: size threshold for fill/blit (with optional transformation)
|
||||
.. code:: c
|
||||
|
||||
#define VGLITE_BLIT_SPLIT_THR 352
|
||||
|
||||
- By default, the blit split threshold is set to 352. Blits with width or height
|
||||
higher than this value will be done in multiple steps. Value must be multiple
|
||||
of stride alignment in px. For most color formats, the alignment is 16px
|
||||
(except the index formats). Transformation will not be supported once with
|
||||
the blit split.
|
||||
|
||||
- Enable VGLite draw task synchronously in "lv_conf.h":
|
||||
Set :c:macro: `LV_USE_VGLITE_DRAW_ASYNC` to `1`.
|
||||
Multiple draw tasks can be queued and flushed them once to the GPU based on
|
||||
the GPU idle status. If GPU is busy, the task will be queued, and the VGLite
|
||||
dispatcher will ask for a new available task. If GPU is idle, the queue with
|
||||
any pending tasks will be flushed to the GPU. The completion status of draw
|
||||
task will be sent to the main LVGL thread asynchronously.
|
||||
|
||||
Features supported:
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Several drawing features in LVGL can be offloaded to the VGLite engine. The CPU
|
||||
is available for other operations while the GPU is running. RTOS is required to
|
||||
block the LVGL drawing thread and switch to another task or suspend the CPU for
|
||||
power savings.
|
||||
|
||||
Supported draw tasks are available in "src/draw/nxp/pxp/lv_draw_vglite.c":
|
||||
|
||||
.. code:: c
|
||||
|
||||
switch(t->type) {
|
||||
case LV_DRAW_TASK_TYPE_LABEL:
|
||||
lv_draw_vglite_label(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_FILL:
|
||||
lv_draw_vglite_fill(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_BORDER:
|
||||
lv_draw_vglite_border(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_IMAGE:
|
||||
lv_draw_vglite_img(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_ARC:
|
||||
lv_draw_vglite_arc(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_LINE:
|
||||
lv_draw_vglite_line(draw_unit, t->draw_dsc);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_LAYER:
|
||||
lv_draw_vglite_layer(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_TRIANGLE:
|
||||
lv_draw_vglite_triangle(draw_unit, t->draw_dsc);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
All the below opration can be done in addition with optional opacity.
|
||||
- Fill area with color (w/ radius or gradient).
|
||||
- Blit source image (any format from `_vglite_src_cf_supported()`) over
|
||||
destination (any format from `_vglite_dest_cf_supported()`).
|
||||
- Recolor source image.
|
||||
- Scale and rotate (any decimal degree) source image.
|
||||
- Blending layers (w/ same supported formats as blitting).
|
||||
- Draw letters (blit bitmap letters - raster font).
|
||||
- Draw full borders (LV_BORDER_SIDE_FULL).
|
||||
- Draw arcs (w/ rounded edges).
|
||||
- Draw lines (w/ dash or rounded edges).
|
||||
- Draw triangles with color (w/ gradient).
|
||||
|
||||
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 (:c:macro:`VG_LITE_LINEAR`).
|
||||
|
||||
Project setup:
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
- Add VGLite related source files (and corresponding headers if available) to
|
||||
project:
|
||||
|
||||
- "src/draw/nxp/vglite/lv_draw_buf_vglite.c": draw buffer callbacks
|
||||
- "src/draw/nxp/vglite/lv_draw_vglite_arc.c": draw arc
|
||||
- "src/draw/nxp/vglite/lv_draw_vglite_border.c": draw border
|
||||
- "src/draw/nxp/vglite/lv_draw_vglite_fill.c": fill area
|
||||
- "src/draw/nxp/vglite/lv_draw_vglite_img.c": blit image (w/ optional
|
||||
recolor or transformation)
|
||||
- "src/draw/nxp/vglite/lv_draw_vglite_label.c": draw label
|
||||
- "src/draw/nxp/vglite/lv_draw_vglite_layer.c": layer blending
|
||||
- "src/draw/nxp/vglite/lv_draw_vglite_line.c": draw line
|
||||
- "src/draw/nxp/vglite/lv_draw_vglite_triangle.c": draw triangle
|
||||
- "src/draw/nxp/vglite/lv_draw_vglite.c": draw unit initialization
|
||||
- "src/draw/nxp/vglite/lv_vglite_buf.c": init/get vglite buffer
|
||||
- "src/draw/nxp/vglite/lv_vglite_matrix.c": set vglite matrix
|
||||
- "src/draw/nxp/vglite/lv_vglite_path.c": create vglite path data
|
||||
- "src/draw/nxp/vglite/lv_vglite_utils.c": function helpers
|
||||
|
||||
@@ -67,6 +67,23 @@
|
||||
*(Not so important, you can adjust it to modify default sizes and spaces)*/
|
||||
#define LV_DPI_DEF 130 /*[px/inch]*/
|
||||
|
||||
/*=================
|
||||
* OPERATING SYSTEM
|
||||
*=================*/
|
||||
/*Select an operating system to use. Possible options:
|
||||
* - LV_OS_NONE
|
||||
* - LV_OS_PTHREAD
|
||||
* - LV_OS_FREERTOS
|
||||
* - LV_OS_CMSIS_RTOS2
|
||||
* - LV_OS_RTTHREAD
|
||||
* - LV_OS_WINDOWS
|
||||
* - LV_OS_CUSTOM */
|
||||
#define LV_USE_OS LV_OS_NONE
|
||||
|
||||
#if LV_USE_OS == LV_OS_CUSTOM
|
||||
#define LV_OS_CUSTOM_INCLUDE <stdint.h>
|
||||
#endif
|
||||
|
||||
/*========================
|
||||
* RENDERING CONFIGURATION
|
||||
*========================*/
|
||||
@@ -122,9 +139,27 @@
|
||||
/* Use NXP's VG-Lite GPU on iMX RTxxx platforms. */
|
||||
#define LV_USE_DRAW_VGLITE 0
|
||||
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
/* Enable blit quality degradation workaround recommended for screen's dimension > 352 pixels. */
|
||||
#define LV_USE_VGLITE_BLIT_SPLIT 0
|
||||
|
||||
#if LV_USE_OS
|
||||
/* Enable VGLite draw async. Queue multiple tasks and flash them once to the GPU. */
|
||||
#define LV_USE_VGLITE_DRAW_ASYNC 1
|
||||
#endif
|
||||
|
||||
/* Enable VGLite asserts. */
|
||||
#define LV_USE_VGLITE_ASSERT 0
|
||||
#endif
|
||||
|
||||
/* Use NXP's PXP on iMX RTxxx platforms. */
|
||||
#define LV_USE_DRAW_PXP 0
|
||||
|
||||
#if LV_USE_DRAW_PXP
|
||||
/* Enable PXP asserts. */
|
||||
#define LV_USE_PXP_ASSERT 0
|
||||
#endif
|
||||
|
||||
/* Use Renesas Dave2D on RA platforms. */
|
||||
#define LV_USE_DRAW_DAVE2D 0
|
||||
|
||||
@@ -143,23 +178,6 @@
|
||||
|
||||
#endif
|
||||
|
||||
/*=================
|
||||
* OPERATING SYSTEM
|
||||
*=================*/
|
||||
/*Select an operating system to use. Possible options:
|
||||
* - LV_OS_NONE
|
||||
* - LV_OS_PTHREAD
|
||||
* - LV_OS_FREERTOS
|
||||
* - LV_OS_CMSIS_RTOS2
|
||||
* - LV_OS_RTTHREAD
|
||||
* - LV_OS_WINDOWS
|
||||
* - LV_OS_CUSTOM */
|
||||
#define LV_USE_OS LV_OS_NONE
|
||||
|
||||
#if LV_USE_OS == LV_OS_CUSTOM
|
||||
#define LV_OS_CUSTOM_INCLUDE <stdint.h>
|
||||
#endif
|
||||
|
||||
/*=======================
|
||||
* FEATURE CONFIGURATION
|
||||
*=======================*/
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2023 NXP
|
||||
* Copyright 2023-2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
@@ -33,7 +33,7 @@
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void _invalidate_cache(lv_draw_buf_t * draw_buf, const char * area);
|
||||
static void _invalidate_cache(void * buf, uint32_t stride, lv_color_format_t cf, const lv_area_t * area);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
@@ -58,44 +58,49 @@ void lv_draw_buf_pxp_init_handlers(void)
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void _invalidate_cache(lv_draw_buf_t * draw_buf, const char * area)
|
||||
static void _invalidate_cache(void * buf, uint32_t stride, lv_color_format_t cf, const lv_area_t * area)
|
||||
{
|
||||
LV_UNUSED(draw_buf);
|
||||
LV_UNUSED(area);
|
||||
if(area->y1 == 0) {
|
||||
uint16_t size = stride * lv_area_get_height(area);
|
||||
|
||||
DEMO_CleanInvalidateCache();
|
||||
/* Invalidate full buffer. */
|
||||
DEMO_CleanInvalidateCacheByAddr((void *)buf, size);
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t * buf_u8 = buf;
|
||||
/* ARM require a 32 byte aligned address. */
|
||||
uint8_t align_bytes = 32;
|
||||
uint8_t bits_per_pixel = lv_color_format_get_bpp(cf);
|
||||
|
||||
uint16_t align_pixels = align_bytes * 8 / bits_per_pixel;
|
||||
uint16_t offset_x = 0;
|
||||
|
||||
if(area->x1 >= (int32_t)(area->x1 % align_pixels)) {
|
||||
uint16_t shift_x = area->x1 - (area->x1 % align_pixels);
|
||||
|
||||
offset_x = area->x1 - shift_x;
|
||||
buf_u8 += (shift_x * bits_per_pixel) / 8;
|
||||
}
|
||||
|
||||
if(area->y1) {
|
||||
uint16_t shift_y = area->y1;
|
||||
|
||||
buf_u8 += shift_y * stride;
|
||||
}
|
||||
|
||||
/* Area to clear can start from a different offset in buffer.
|
||||
* Invalidate the area line by line.
|
||||
*/
|
||||
uint16_t line_pixels = offset_x + lv_area_get_width(area);
|
||||
uint16_t line_size = (line_pixels * bits_per_pixel) / 8;
|
||||
uint16_t area_height = lv_area_get_height(area);
|
||||
|
||||
for(uint16_t y = 0; y < area_height; y++) {
|
||||
const void * line_addr = buf_u8 + y * stride;
|
||||
|
||||
DEMO_CleanInvalidateCacheByAddr((void *)line_addr, line_size);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* @todo
|
||||
* LVGL needs to use hardware acceleration for buf_copy and do not affect GPU rendering.
|
||||
*/
|
||||
|
||||
void _pxp_buf_copy(void * dest_buf, uint32_t dest_stride, const lv_area_t * dest_area,
|
||||
void * src_buf, uint32_t src_stride, const lv_area_t * src_area,
|
||||
lv_color_format_t cf)
|
||||
{
|
||||
lv_pxp_reset();
|
||||
|
||||
const pxp_pic_copy_config_t picCopyConfig = {
|
||||
.srcPicBaseAddr = (uint32_t)src_buf,
|
||||
.srcPitchBytes = src_stride,
|
||||
.srcOffsetX = src_area->x1,
|
||||
.srcOffsetY = src_area->y1,
|
||||
.destPicBaseAddr = (uint32_t)dest_buf,
|
||||
.destPitchBytes = dest_stride,
|
||||
.destOffsetX = dest_area->x1,
|
||||
.destOffsetY = dest_area->y1,
|
||||
.width = lv_area_get_width(src_area),
|
||||
.height = lv_area_get_height(src_area),
|
||||
.pixelFormat = pxp_get_as_px_format(cf)
|
||||
};
|
||||
|
||||
PXP_StartPictureCopy(PXP_ID, &picCopyConfig);
|
||||
|
||||
lv_pxp_run();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*LV_USE_DRAW_PXP*/
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2022, 2023 NXP
|
||||
* Copyright 2022-2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
@@ -17,7 +17,11 @@
|
||||
|
||||
#if LV_USE_DRAW_PXP
|
||||
#include "lv_pxp_cfg.h"
|
||||
#include "../../../display/lv_display_private.h"
|
||||
#include "lv_pxp_utils.h"
|
||||
|
||||
#if LV_USE_PARALLEL_DRAW_DEBUG
|
||||
#include "../../../core/lv_global.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@@ -33,6 +37,12 @@
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/*
|
||||
* Evaluate a task and set the score and preferred PXP unit.
|
||||
* Return 1 if task is preferred, 0 otherwise (task is not supported).
|
||||
*/
|
||||
static int32_t _pxp_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task);
|
||||
|
||||
/*
|
||||
* Dispatch a task to the PXP unit.
|
||||
* Return 1 if task was dispatched, 0 otherwise (task not supported).
|
||||
@@ -40,10 +50,9 @@
|
||||
static int32_t _pxp_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer);
|
||||
|
||||
/*
|
||||
* Evaluate a task and set the score and preferred PXP unit.
|
||||
* Return 1 if task is preferred, 0 otherwise (task is not supported).
|
||||
* Delete the PXP draw unit.
|
||||
*/
|
||||
static int32_t _pxp_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task);
|
||||
static int32_t _pxp_delete(lv_draw_unit_t * draw_unit);
|
||||
|
||||
#if LV_USE_OS
|
||||
static void _pxp_render_thread_cb(void * ptr);
|
||||
@@ -59,6 +68,10 @@ static void _pxp_execute_drawing(lv_draw_pxp_unit_t * u);
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
#if LV_USE_PARALLEL_DRAW_DEBUG
|
||||
#define _draw_info LV_GLOBAL_DEFAULT()->draw_info
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
@@ -72,13 +85,14 @@ void lv_draw_pxp_init(void)
|
||||
lv_draw_buf_pxp_init_handlers();
|
||||
|
||||
lv_draw_pxp_unit_t * draw_pxp_unit = lv_draw_create_unit(sizeof(lv_draw_pxp_unit_t));
|
||||
draw_pxp_unit->base_unit.dispatch_cb = _pxp_dispatch;
|
||||
draw_pxp_unit->base_unit.evaluate_cb = _pxp_evaluate;
|
||||
draw_pxp_unit->base_unit.dispatch_cb = _pxp_dispatch;
|
||||
draw_pxp_unit->base_unit.delete_cb = _pxp_delete;
|
||||
|
||||
lv_pxp_init();
|
||||
|
||||
#if LV_USE_OS
|
||||
lv_thread_init(&draw_pxp_unit->thread, LV_THREAD_PRIO_HIGH, _pxp_render_thread_cb, 8 * 1024, draw_pxp_unit);
|
||||
lv_thread_init(&draw_pxp_unit->thread, LV_THREAD_PRIO_HIGH, _pxp_render_thread_cb, 2 * 1024, draw_pxp_unit);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -87,14 +101,96 @@ void lv_draw_pxp_deinit(void)
|
||||
lv_pxp_deinit();
|
||||
}
|
||||
|
||||
void lv_draw_pxp_rotate(const void * src_buf, void * dest_buf, int32_t src_width, int32_t src_height,
|
||||
int32_t src_stride, int32_t dest_stride, lv_display_rotation_t rotation,
|
||||
lv_color_format_t cf)
|
||||
{
|
||||
lv_pxp_reset();
|
||||
|
||||
/* convert rotation angle */
|
||||
pxp_rotate_degree_t pxp_rotation;
|
||||
switch(rotation) {
|
||||
case LV_DISPLAY_ROTATION_0:
|
||||
pxp_rotation = kPXP_Rotate0;
|
||||
break;
|
||||
case LV_DISPLAY_ROTATION_90:
|
||||
pxp_rotation = kPXP_Rotate90;
|
||||
break;
|
||||
case LV_DISPLAY_ROTATION_180:
|
||||
pxp_rotation = kPXP_Rotate180;
|
||||
break;
|
||||
case LV_DISPLAY_ROTATION_270:
|
||||
pxp_rotation = kPXP_Rotate270;
|
||||
break;
|
||||
default:
|
||||
pxp_rotation = kPXP_Rotate0;
|
||||
break;
|
||||
}
|
||||
PXP_SetRotateConfig(PXP_ID, kPXP_RotateOutputBuffer, pxp_rotation, kPXP_FlipDisable);
|
||||
|
||||
/*Simple blit, no effect - Disable PS buffer*/
|
||||
PXP_SetProcessSurfacePosition(PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
|
||||
|
||||
/*AS buffer - source image*/
|
||||
pxp_as_buffer_config_t asBufferConfig = {
|
||||
.pixelFormat = pxp_get_as_px_format(cf),
|
||||
.bufferAddr = (uint32_t)src_buf,
|
||||
.pitchBytes = src_stride
|
||||
};
|
||||
PXP_SetAlphaSurfaceBufferConfig(PXP_ID, &asBufferConfig);
|
||||
PXP_SetAlphaSurfacePosition(PXP_ID, 0U, 0U, src_width - 1U, src_height - 1U);
|
||||
PXP_EnableAlphaSurfaceOverlayColorKey(PXP_ID, false);
|
||||
|
||||
/*Output buffer.*/
|
||||
pxp_output_buffer_config_t outputBufferConfig = {
|
||||
.pixelFormat = pxp_get_out_px_format(cf),
|
||||
.interlacedMode = kPXP_OutputProgressive,
|
||||
.buffer0Addr = (uint32_t)dest_buf,
|
||||
.buffer1Addr = (uint32_t)0U,
|
||||
.pitchBytes = dest_stride,
|
||||
.width = src_width,
|
||||
.height = src_height
|
||||
};
|
||||
PXP_SetOutputBufferConfig(PXP_ID, &outputBufferConfig);
|
||||
|
||||
lv_pxp_run();
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static inline bool _pxp_cf_supported(lv_color_format_t cf)
|
||||
static inline bool _pxp_src_cf_supported(lv_color_format_t cf)
|
||||
{
|
||||
bool is_cf_supported = (cf == LV_COLOR_FORMAT_RGB565 || cf == LV_COLOR_FORMAT_RGB888 ||
|
||||
cf == LV_COLOR_FORMAT_ARGB8888 || cf == LV_COLOR_FORMAT_XRGB8888);
|
||||
bool is_cf_supported = false;
|
||||
|
||||
switch(cf) {
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
case LV_COLOR_FORMAT_XRGB8888:
|
||||
is_cf_supported = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return is_cf_supported;
|
||||
}
|
||||
|
||||
static inline bool _pxp_dest_cf_supported(lv_color_format_t cf)
|
||||
{
|
||||
bool is_cf_supported = false;
|
||||
|
||||
switch(cf) {
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
case LV_COLOR_FORMAT_RGB888:
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
case LV_COLOR_FORMAT_XRGB8888:
|
||||
is_cf_supported = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return is_cf_supported;
|
||||
}
|
||||
@@ -103,8 +199,9 @@ static bool _pxp_draw_img_supported(const lv_draw_image_dsc_t * draw_dsc)
|
||||
{
|
||||
const lv_image_dsc_t * img_dsc = draw_dsc->src;
|
||||
|
||||
bool has_recolor = (draw_dsc->recolor_opa != LV_OPA_TRANSP);
|
||||
bool has_transform = (draw_dsc->rotation != 0 || draw_dsc->zoom != LV_SCALE_NONE);
|
||||
bool has_recolor = (draw_dsc->recolor_opa > LV_OPA_MIN);
|
||||
bool has_transform = (draw_dsc->rotation != 0 || draw_dsc->scale_x != LV_SCALE_NONE ||
|
||||
draw_dsc->scale_y != LV_SCALE_NONE);
|
||||
|
||||
/* Recolor and transformation are not supported at the same time. */
|
||||
if(has_recolor && has_transform)
|
||||
@@ -146,6 +243,11 @@ static int32_t _pxp_evaluate(lv_draw_unit_t * u, lv_draw_task_t * t)
|
||||
{
|
||||
LV_UNUSED(u);
|
||||
|
||||
const lv_draw_dsc_base_t * draw_dsc_base = (lv_draw_dsc_base_t *) t->draw_dsc;
|
||||
|
||||
if(!_pxp_dest_cf_supported(draw_dsc_base->layer->color_format))
|
||||
return 0;
|
||||
|
||||
switch(t->type) {
|
||||
case LV_DRAW_TASK_TYPE_FILL: {
|
||||
const lv_draw_fill_dsc_t * draw_dsc = (lv_draw_fill_dsc_t *) t->draw_dsc;
|
||||
@@ -161,29 +263,11 @@ static int32_t _pxp_evaluate(lv_draw_unit_t * u, lv_draw_task_t * t)
|
||||
return 1;
|
||||
}
|
||||
|
||||
case LV_DRAW_TASK_TYPE_BG_IMG: {
|
||||
const lv_draw_bg_image_dsc_t * draw_dsc = (lv_draw_bg_image_dsc_t *) t->draw_dsc;
|
||||
lv_image_src_t src_type = lv_image_src_get_type(draw_dsc->src);
|
||||
|
||||
if(src_type == LV_IMAGE_SRC_SYMBOL)
|
||||
return 0;
|
||||
|
||||
if(!_pxp_cf_supported(draw_dsc->img_header.cf))
|
||||
return 0;
|
||||
|
||||
if(t->preference_score > 70) {
|
||||
t->preference_score = 70;
|
||||
t->preferred_draw_unit_id = DRAW_UNIT_ID_PXP;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
case LV_DRAW_TASK_TYPE_LAYER: {
|
||||
const lv_draw_image_dsc_t * draw_dsc = (lv_draw_image_dsc_t *) t->draw_dsc;
|
||||
lv_layer_t * layer_to_draw = (lv_layer_t *)draw_dsc->src;
|
||||
lv_draw_buf_t * draw_buf = &layer_to_draw->draw_buf;
|
||||
|
||||
if(!_pxp_cf_supported(draw_buf->color_format))
|
||||
if(!_pxp_src_cf_supported(layer_to_draw->color_format))
|
||||
return 0;
|
||||
|
||||
if(!_pxp_draw_img_supported(draw_dsc))
|
||||
@@ -200,7 +284,8 @@ static int32_t _pxp_evaluate(lv_draw_unit_t * u, lv_draw_task_t * t)
|
||||
lv_draw_image_dsc_t * draw_dsc = (lv_draw_image_dsc_t *) t->draw_dsc;
|
||||
const lv_image_dsc_t * img_dsc = draw_dsc->src;
|
||||
|
||||
if(!_pxp_cf_supported(img_dsc->header.cf))
|
||||
if((!_pxp_src_cf_supported(img_dsc->header.cf)) ||
|
||||
(!pxp_buf_aligned(img_dsc->data, img_dsc->header.stride)))
|
||||
return 0;
|
||||
|
||||
if(!_pxp_draw_img_supported(draw_dsc))
|
||||
@@ -227,16 +312,11 @@ static int32_t _pxp_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
|
||||
if(draw_pxp_unit->task_act)
|
||||
return 0;
|
||||
|
||||
/* Return if target buffer format is not supported. */
|
||||
if(!_pxp_cf_supported(layer->draw_buf.color_format))
|
||||
return 0;
|
||||
|
||||
/* Try to get an ready to draw. */
|
||||
lv_draw_task_t * t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_PXP);
|
||||
|
||||
/* Return 0 is no selection, some tasks can be supported only by other units. */
|
||||
if(t == NULL || t->preferred_draw_unit_id != DRAW_UNIT_ID_PXP)
|
||||
return 0;
|
||||
return -1;
|
||||
|
||||
void * buf = lv_draw_layer_alloc_buf(layer);
|
||||
if(buf == NULL)
|
||||
@@ -249,7 +329,8 @@ static int32_t _pxp_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
|
||||
|
||||
#if LV_USE_OS
|
||||
/* Let the render thread work. */
|
||||
lv_thread_sync_signal(&draw_pxp_unit->sync);
|
||||
if(draw_pxp_unit->inited)
|
||||
lv_thread_sync_signal(&draw_pxp_unit->sync);
|
||||
#else
|
||||
_pxp_execute_drawing(draw_pxp_unit);
|
||||
|
||||
@@ -263,22 +344,46 @@ static int32_t _pxp_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int32_t _pxp_delete(lv_draw_unit_t * draw_unit)
|
||||
{
|
||||
#if LV_USE_OS
|
||||
lv_draw_pxp_unit_t * draw_pxp_unit = (lv_draw_pxp_unit_t *) draw_unit;
|
||||
|
||||
LV_LOG_INFO("Cancel PXP draw thread.");
|
||||
draw_pxp_unit->exit_status = true;
|
||||
|
||||
if(draw_pxp_unit->inited)
|
||||
lv_thread_sync_signal(&draw_pxp_unit->sync);
|
||||
|
||||
lv_result_t res = lv_thread_delete(&draw_pxp_unit->thread);
|
||||
|
||||
return res;
|
||||
#else
|
||||
LV_UNUSED(draw_unit);
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void _pxp_execute_drawing(lv_draw_pxp_unit_t * u)
|
||||
{
|
||||
lv_draw_task_t * t = u->task_act;
|
||||
lv_draw_unit_t * draw_unit = (lv_draw_unit_t *)u;
|
||||
|
||||
/* Invalidate cache */
|
||||
lv_layer_t * layer = draw_unit->target_layer;
|
||||
lv_draw_buf_invalidate_cache(&layer->draw_buf, (const char *)&t->area);
|
||||
|
||||
lv_area_t draw_area;
|
||||
if(!_lv_area_intersect(&draw_area, &t->area, draw_unit->clip_area))
|
||||
return; /*Fully clipped, nothing to do*/
|
||||
|
||||
/* Make area relative to the buffer */
|
||||
lv_area_move(&draw_area, -layer->buf_area.x1, -layer->buf_area.y1);
|
||||
/* Invalidate only the drawing area */
|
||||
lv_draw_buf_invalidate_cache(layer->buf, layer->buf_stride, layer->color_format, &draw_area);
|
||||
|
||||
switch(t->type) {
|
||||
case LV_DRAW_TASK_TYPE_FILL:
|
||||
lv_draw_pxp_fill(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_BG_IMG:
|
||||
lv_draw_pxp_bg_img(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_IMAGE:
|
||||
lv_draw_pxp_img(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
@@ -288,6 +393,51 @@ static void _pxp_execute_drawing(lv_draw_pxp_unit_t * u)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if LV_USE_PARALLEL_DRAW_DEBUG
|
||||
/*Layers manage it for themselves*/
|
||||
if(t->type != LV_DRAW_TASK_TYPE_LAYER) {
|
||||
lv_area_t draw_area;
|
||||
if(!_lv_area_intersect(&draw_area, &t->area, u->base_unit.clip_area))
|
||||
return;
|
||||
|
||||
int32_t idx = 0;
|
||||
lv_draw_unit_t * draw_unit_tmp = _draw_info.unit_head;
|
||||
while(draw_unit_tmp != (lv_draw_unit_t *)u) {
|
||||
draw_unit_tmp = draw_unit_tmp->next;
|
||||
idx++;
|
||||
}
|
||||
lv_draw_rect_dsc_t rect_dsc;
|
||||
lv_draw_rect_dsc_init(&rect_dsc);
|
||||
rect_dsc.bg_color = lv_palette_main(idx % _LV_PALETTE_LAST);
|
||||
rect_dsc.border_color = rect_dsc.bg_color;
|
||||
rect_dsc.bg_opa = LV_OPA_10;
|
||||
rect_dsc.border_opa = LV_OPA_80;
|
||||
rect_dsc.border_width = 1;
|
||||
lv_draw_sw_fill((lv_draw_unit_t *)u, &rect_dsc, &draw_area);
|
||||
|
||||
lv_point_t txt_size;
|
||||
lv_text_get_size(&txt_size, "W", LV_FONT_DEFAULT, 0, 0, 100, LV_TEXT_FLAG_NONE);
|
||||
|
||||
lv_area_t txt_area;
|
||||
txt_area.x1 = draw_area.x1;
|
||||
txt_area.y1 = draw_area.y1;
|
||||
txt_area.x2 = draw_area.x1 + txt_size.x - 1;
|
||||
txt_area.y2 = draw_area.y1 + txt_size.y - 1;
|
||||
|
||||
lv_draw_rect_dsc_init(&rect_dsc);
|
||||
rect_dsc.bg_color = lv_color_white();
|
||||
lv_draw_sw_fill((lv_draw_unit_t *)u, &rect_dsc, &txt_area);
|
||||
|
||||
char buf[8];
|
||||
lv_snprintf(buf, sizeof(buf), "%d", idx);
|
||||
lv_draw_label_dsc_t label_dsc;
|
||||
lv_draw_label_dsc_init(&label_dsc);
|
||||
label_dsc.color = lv_color_black();
|
||||
label_dsc.text = buf;
|
||||
lv_draw_sw_label((lv_draw_unit_t *)u, &label_dsc, &txt_area);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if LV_USE_OS
|
||||
@@ -296,25 +446,37 @@ static void _pxp_render_thread_cb(void * ptr)
|
||||
lv_draw_pxp_unit_t * u = ptr;
|
||||
|
||||
lv_thread_sync_init(&u->sync);
|
||||
u->inited = true;
|
||||
|
||||
while(1) {
|
||||
/*
|
||||
* Wait for sync if no task received or _draw_task_buf is empty.
|
||||
* The thread will have to run as much as there are pending tasks.
|
||||
*/
|
||||
/* Wait for sync if there is no task set. */
|
||||
while(u->task_act == NULL) {
|
||||
if(u->exit_status)
|
||||
break;
|
||||
|
||||
lv_thread_sync_wait(&u->sync);
|
||||
}
|
||||
|
||||
if(u->exit_status) {
|
||||
LV_LOG_INFO("Ready to exit PXP draw thread.");
|
||||
break;
|
||||
}
|
||||
|
||||
_pxp_execute_drawing(u);
|
||||
|
||||
/* Cleanup. */
|
||||
/* Signal the ready state to dispatcher. */
|
||||
u->task_act->state = LV_DRAW_TASK_STATE_READY;
|
||||
|
||||
/* Cleanup. */
|
||||
u->task_act = NULL;
|
||||
|
||||
/* The draw unit is free now. Request a new dispatching as it can get a new task. */
|
||||
lv_draw_dispatch_request();
|
||||
}
|
||||
|
||||
u->inited = false;
|
||||
lv_thread_sync_delete(&u->sync);
|
||||
LV_LOG_INFO("Exit PXP draw thread.");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2022, 2023 NXP
|
||||
* Copyright 2022-2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
@@ -33,16 +33,7 @@ extern "C" {
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef lv_layer_t lv_pxp_layer_t;
|
||||
|
||||
typedef struct {
|
||||
lv_draw_unit_t base_unit;
|
||||
lv_draw_task_t * task_act;
|
||||
#if LV_USE_OS
|
||||
lv_thread_sync_t sync;
|
||||
lv_thread_t thread;
|
||||
#endif
|
||||
} lv_draw_pxp_unit_t;
|
||||
typedef lv_draw_sw_unit_t lv_draw_pxp_unit_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
@@ -54,8 +45,9 @@ void lv_draw_pxp_init(void);
|
||||
|
||||
void lv_draw_pxp_deinit(void);
|
||||
|
||||
void lv_draw_pxp_bg_img(lv_draw_unit_t * draw_unit, const lv_draw_bg_image_dsc_t * dsc,
|
||||
const lv_area_t * coords);
|
||||
void lv_draw_pxp_rotate(const void * src_buf, void * dest_buf, int32_t src_width, int32_t src_height,
|
||||
int32_t src_stride, int32_t dest_stride, lv_display_rotation_t rotation,
|
||||
lv_color_format_t cf);
|
||||
|
||||
void lv_draw_pxp_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc,
|
||||
const lv_area_t * coords);
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
/**
|
||||
* @file lv_draw_pxp_bg_img.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_pxp.h"
|
||||
|
||||
#if LV_USE_DRAW_PXP
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_pxp_bg_img(lv_draw_unit_t * draw_unit, const lv_draw_bg_image_dsc_t * dsc,
|
||||
const lv_area_t * coords)
|
||||
{
|
||||
if(dsc->src == NULL) return;
|
||||
if(dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
lv_area_t clip_area;
|
||||
if(!_lv_area_intersect(&clip_area, coords, draw_unit->clip_area)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const lv_area_t * clip_area_ori = draw_unit->clip_area;
|
||||
draw_unit->clip_area = &clip_area;
|
||||
|
||||
lv_draw_image_dsc_t img_dsc;
|
||||
lv_draw_image_dsc_init(&img_dsc);
|
||||
img_dsc.recolor = dsc->recolor;
|
||||
img_dsc.recolor_opa = dsc->recolor_opa;
|
||||
img_dsc.opa = dsc->opa;
|
||||
img_dsc.src = dsc->src;
|
||||
|
||||
/*Center align*/
|
||||
if(dsc->tiled == false) {
|
||||
lv_area_t area;
|
||||
area.x1 = coords->x1 + lv_area_get_width(coords) / 2 - dsc->img_header.w / 2;
|
||||
area.y1 = coords->y1 + lv_area_get_height(coords) / 2 - dsc->img_header.h / 2;
|
||||
area.x2 = area.x1 + dsc->img_header.w - 1;
|
||||
area.y2 = area.y1 + dsc->img_header.h - 1;
|
||||
|
||||
lv_draw_pxp_img(draw_unit, &img_dsc, &area);
|
||||
}
|
||||
else {
|
||||
lv_area_t area;
|
||||
area.y1 = coords->y1;
|
||||
area.y2 = area.y1 + dsc->img_header.h - 1;
|
||||
|
||||
for(; area.y1 <= coords->y2; area.y1 += dsc->img_header.h, area.y2 += dsc->img_header.h) {
|
||||
|
||||
area.x1 = coords->x1;
|
||||
area.x2 = area.x1 + dsc->img_header.w - 1;
|
||||
for(; area.x1 <= coords->x2; area.x1 += dsc->img_header.w, area.x2 += dsc->img_header.w) {
|
||||
lv_draw_pxp_img(draw_unit, &img_dsc, &area);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
draw_unit->clip_area = clip_area_ori;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_PXP*/
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2020-2023 NXP
|
||||
* Copyright 2020-2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
@@ -56,21 +56,17 @@ void lv_draw_pxp_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc
|
||||
|
||||
lv_area_t rel_coords;
|
||||
lv_area_copy(&rel_coords, coords);
|
||||
lv_area_move(&rel_coords, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
|
||||
lv_area_move(&rel_coords, -layer->buf_area.x1, -layer->buf_area.y1);
|
||||
|
||||
lv_area_t rel_clip_area;
|
||||
lv_area_copy(&rel_clip_area, draw_unit->clip_area);
|
||||
lv_area_move(&rel_clip_area, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
|
||||
lv_area_move(&rel_clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
|
||||
|
||||
lv_area_t blend_area;
|
||||
if(!_lv_area_intersect(&blend_area, &rel_coords, &rel_clip_area))
|
||||
return; /*Fully clipped, nothing to do*/
|
||||
|
||||
uint8_t * dest_buf = layer->draw_buf.buf;
|
||||
int32_t dest_stride = lv_draw_buf_get_stride(&layer->draw_buf);
|
||||
lv_color_format_t dest_cf = layer->draw_buf.color_format;
|
||||
|
||||
_pxp_fill(dest_buf, &blend_area, dest_stride, dest_cf, dsc);
|
||||
_pxp_fill(layer->buf, &blend_area, layer->buf_stride, layer->color_format, dsc);
|
||||
}
|
||||
|
||||
/**********************
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2020-2023 NXP
|
||||
* Copyright 2020-2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
@@ -71,14 +71,14 @@ void lv_draw_pxp_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dsc
|
||||
|
||||
lv_area_t rel_coords;
|
||||
lv_area_copy(&rel_coords, coords);
|
||||
lv_area_move(&rel_coords, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
|
||||
lv_area_move(&rel_coords, -layer->buf_area.x1, -layer->buf_area.y1);
|
||||
|
||||
lv_area_t rel_clip_area;
|
||||
lv_area_copy(&rel_clip_area, draw_unit->clip_area);
|
||||
lv_area_move(&rel_clip_area, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
|
||||
lv_area_move(&rel_clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
|
||||
|
||||
lv_area_t blend_area;
|
||||
bool has_transform = dsc->rotation != 0 || dsc->zoom != LV_SCALE_NONE;
|
||||
bool has_transform = (dsc->rotation != 0 || dsc->scale_x != LV_SCALE_NONE || dsc->scale_y != LV_SCALE_NONE);
|
||||
if(has_transform)
|
||||
lv_area_copy(&blend_area, &rel_coords);
|
||||
else if(!_lv_area_intersect(&blend_area, &rel_coords, &rel_clip_area))
|
||||
@@ -87,17 +87,17 @@ void lv_draw_pxp_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dsc
|
||||
const uint8_t * src_buf = img_dsc->data;
|
||||
|
||||
lv_area_t src_area;
|
||||
src_area.x1 = blend_area.x1 - (coords->x1 - layer->draw_buf_ofs.x);
|
||||
src_area.y1 = blend_area.y1 - (coords->y1 - layer->draw_buf_ofs.y);
|
||||
src_area.x1 = blend_area.x1 - (coords->x1 - layer->buf_area.x1);
|
||||
src_area.y1 = blend_area.y1 - (coords->y1 - layer->buf_area.y1);
|
||||
src_area.x2 = src_area.x1 + lv_area_get_width(coords) - 1;
|
||||
src_area.y2 = src_area.y1 + lv_area_get_height(coords) - 1;
|
||||
int32_t src_stride = img_dsc->header.stride;
|
||||
lv_color_format_t src_cf = img_dsc->header.cf;
|
||||
|
||||
uint8_t * dest_buf = layer->draw_buf.buf;
|
||||
int32_t dest_stride = lv_draw_buf_get_stride(&layer->draw_buf);
|
||||
lv_color_format_t dest_cf = layer->draw_buf.color_format;
|
||||
bool has_recolor = (dsc->recolor_opa != LV_OPA_TRANSP);
|
||||
uint8_t * dest_buf = layer->buf;
|
||||
int32_t dest_stride = layer->buf_stride;
|
||||
lv_color_format_t dest_cf = layer->color_format;
|
||||
bool has_recolor = (dsc->recolor_opa > LV_OPA_MIN);
|
||||
|
||||
if(has_recolor && !has_transform)
|
||||
_pxp_blit_recolor(dest_buf, &blend_area, dest_stride, dest_cf,
|
||||
@@ -194,10 +194,11 @@ static void _pxp_blit_transform(uint8_t * dest_buf, const lv_area_t * dest_area,
|
||||
int32_t piv_offset_x = 0;
|
||||
int32_t piv_offset_y = 0;
|
||||
|
||||
int32_t trim_size = 0;
|
||||
int32_t trim_x = 0;
|
||||
int32_t trim_y = 0;
|
||||
|
||||
bool has_rotation = (dsc->rotation != 0);
|
||||
bool has_scale = (dsc->zoom != LV_SCALE_NONE);
|
||||
bool has_scale = (dsc->scale_x != LV_SCALE_NONE || dsc->scale_y != LV_SCALE_NONE);
|
||||
uint8_t src_px_size = lv_color_format_get_size(src_cf);
|
||||
uint8_t dest_px_size = lv_color_format_get_size(dest_cf);
|
||||
|
||||
@@ -237,21 +238,21 @@ static void _pxp_blit_transform(uint8_t * dest_buf, const lv_area_t * dest_area,
|
||||
}
|
||||
|
||||
if(has_scale) {
|
||||
float scale_factor_fp = (float)dsc->zoom / LV_SCALE_NONE;
|
||||
int32_t scale_factor_int = (int32_t)scale_factor_fp;
|
||||
float fp_scale_x = (float)dsc->scale_x / LV_SCALE_NONE;
|
||||
float fp_scale_y = (float)dsc->scale_y / LV_SCALE_NONE;
|
||||
int32_t int_scale_x = (int32_t)fp_scale_x;
|
||||
int32_t int_scale_y = (int32_t)fp_scale_y;
|
||||
|
||||
/*Any scale_factor in (k, k + 1] will result in a trim equal to k*/
|
||||
if(scale_factor_fp == scale_factor_int)
|
||||
trim_size = scale_factor_int - 1;
|
||||
else
|
||||
trim_size = scale_factor_int;
|
||||
trim_x = (fp_scale_x == int_scale_x) ? int_scale_x - 1 : int_scale_x;
|
||||
trim_y = (fp_scale_y == int_scale_y) ? int_scale_y - 1 : int_scale_y;
|
||||
|
||||
dest_w = src_w * scale_factor_fp + trim_size;
|
||||
dest_h = src_h * scale_factor_fp + trim_size;
|
||||
dest_w = src_w * fp_scale_x + trim_x;
|
||||
dest_h = src_h * fp_scale_y + trim_y;
|
||||
|
||||
/*Final pivot offset = scale_factor * rotation_pivot_offset + scaling_pivot_offset*/
|
||||
piv_offset_x = floor(scale_factor_fp * piv_offset_x) - floor((scale_factor_fp - 1) * pivot.x);
|
||||
piv_offset_y = floor(scale_factor_fp * piv_offset_y) - floor((scale_factor_fp - 1) * pivot.y);
|
||||
piv_offset_x = floor(fp_scale_x * piv_offset_x) - floor((fp_scale_x - 1) * pivot.x);
|
||||
piv_offset_y = floor(fp_scale_y * piv_offset_y) - floor((fp_scale_y - 1) * pivot.y);
|
||||
}
|
||||
|
||||
/*PS buffer - source image*/
|
||||
@@ -264,7 +265,7 @@ static void _pxp_blit_transform(uint8_t * dest_buf, const lv_area_t * dest_area,
|
||||
.pitchBytes = src_stride
|
||||
};
|
||||
PXP_SetProcessSurfaceBufferConfig(PXP_ID, &psBufferConfig);
|
||||
PXP_SetProcessSurfacePosition(PXP_ID, 0U, 0U, dest_w - trim_size - 1U, dest_h - trim_size - 1U);
|
||||
PXP_SetProcessSurfacePosition(PXP_ID, 0U, 0U, dest_w - trim_x - 1U, dest_h - trim_y - 1U);
|
||||
|
||||
if(has_scale)
|
||||
PXP_SetProcessSurfaceScaler(PXP_ID, src_w, src_h, dest_w, dest_h);
|
||||
@@ -279,8 +280,8 @@ static void _pxp_blit_transform(uint8_t * dest_buf, const lv_area_t * dest_area,
|
||||
.buffer0Addr = (uint32_t)(dest_buf + dest_stride * (dest_area->y1 + piv_offset_y) + dest_px_size * (dest_area->x1 + piv_offset_x)),
|
||||
.buffer1Addr = (uint32_t)0U,
|
||||
.pitchBytes = dest_stride,
|
||||
.width = dest_w - trim_size,
|
||||
.height = dest_h - trim_size
|
||||
.width = dest_w - trim_x,
|
||||
.height = dest_h - trim_y
|
||||
};
|
||||
PXP_SetOutputBufferConfig(PXP_ID, &outputBufferConfig);
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2023 NXP
|
||||
* Copyright 2023-2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
@@ -18,6 +18,9 @@
|
||||
#if LV_USE_DRAW_PXP
|
||||
|
||||
#include "../../../stdlib/lv_string.h"
|
||||
#if LV_USE_PARALLEL_DRAW_DEBUG
|
||||
#include "../../../core/lv_global.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@@ -35,6 +38,10 @@
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
#if LV_USE_PARALLEL_DRAW_DEBUG
|
||||
#define _draw_info LV_GLOBAL_DEFAULT()->draw_info
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
@@ -50,20 +57,109 @@ void lv_draw_pxp_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * d
|
||||
|
||||
/*It can happen that nothing was draw on a layer and therefore its buffer is not allocated.
|
||||
*In this case just return. */
|
||||
if(layer_to_draw->draw_buf.buf == NULL)
|
||||
if(layer_to_draw->buf == NULL)
|
||||
return;
|
||||
|
||||
lv_image_dsc_t img_dsc = { 0 };
|
||||
img_dsc.header.w = layer_to_draw->draw_buf.width;
|
||||
img_dsc.header.h = layer_to_draw->draw_buf.height;
|
||||
img_dsc.header.cf = layer_to_draw->draw_buf.color_format;
|
||||
img_dsc.data = lv_draw_buf_get_buf(&layer_to_draw->draw_buf);
|
||||
uint32_t width = lv_area_get_width(&layer_to_draw->buf_area);
|
||||
uint32_t height = lv_area_get_height(&layer_to_draw->buf_area);
|
||||
const lv_area_t area = {
|
||||
.x1 = 0,
|
||||
.y1 = 0,
|
||||
.x2 = width - 1,
|
||||
.y2 = height - 1
|
||||
};
|
||||
lv_draw_buf_invalidate_cache(layer_to_draw->buf, layer_to_draw->buf_stride, layer_to_draw->color_format, &area);
|
||||
|
||||
lv_image_dsc_t img_dsc = {0};
|
||||
img_dsc.header.w = width;
|
||||
img_dsc.header.h = height;
|
||||
img_dsc.header.cf = layer_to_draw->color_format;
|
||||
img_dsc.header.stride = layer_to_draw->buf_stride;
|
||||
img_dsc.data = layer_to_draw->buf;
|
||||
|
||||
lv_draw_image_dsc_t new_draw_dsc;
|
||||
lv_memcpy(&new_draw_dsc, draw_dsc, sizeof(lv_draw_image_dsc_t));
|
||||
new_draw_dsc.src = &img_dsc;
|
||||
|
||||
lv_draw_pxp_img(draw_unit, &new_draw_dsc, coords);
|
||||
|
||||
#if LV_USE_LAYER_DEBUG || LV_USE_PARALLEL_DRAW_DEBUG
|
||||
lv_area_t area_rot;
|
||||
lv_area_copy(&area_rot, coords);
|
||||
if(draw_dsc->rotation || draw_dsc->scale_x != LV_SCALE_NONE || draw_dsc->scale_y != LV_SCALE_NONE) {
|
||||
int32_t w = lv_area_get_width(coords);
|
||||
int32_t h = lv_area_get_height(coords);
|
||||
|
||||
_lv_image_buf_get_transformed_area(&area_rot, w, h, draw_dsc->rotation, draw_dsc->scale_x, draw_dsc->scale_y,
|
||||
&draw_dsc->pivot);
|
||||
|
||||
area_rot.x1 += coords->x1;
|
||||
area_rot.y1 += coords->y1;
|
||||
area_rot.x2 += coords->x1;
|
||||
area_rot.y2 += coords->y1;
|
||||
}
|
||||
lv_area_t draw_area;
|
||||
if(!_lv_area_intersect(&draw_area, &area_rot, draw_unit->clip_area)) return;
|
||||
#endif
|
||||
|
||||
#if LV_USE_LAYER_DEBUG
|
||||
lv_draw_fill_dsc_t fill_dsc;
|
||||
lv_draw_fill_dsc_init(&fill_dsc);
|
||||
fill_dsc.color = lv_color_hex(layer_to_draw->color_format == LV_COLOR_FORMAT_ARGB8888 ? 0xff0000 : 0x00ff00);
|
||||
fill_dsc.opa = LV_OPA_20;
|
||||
lv_draw_sw_fill(draw_unit, &fill_dsc, &area_rot);
|
||||
|
||||
lv_draw_border_dsc_t border_dsc;
|
||||
lv_draw_border_dsc_init(&border_dsc);
|
||||
border_dsc.color = fill_dsc.color;
|
||||
border_dsc.opa = LV_OPA_60;
|
||||
border_dsc.width = 2;
|
||||
lv_draw_sw_border(draw_unit, &border_dsc, &area_rot);
|
||||
|
||||
#endif
|
||||
|
||||
#if LV_USE_PARALLEL_DRAW_DEBUG
|
||||
uint32_t idx = 0;
|
||||
lv_draw_unit_t * draw_unit_tmp = _draw_info.unit_head;
|
||||
while(draw_unit_tmp != draw_unit) {
|
||||
draw_unit_tmp = draw_unit_tmp->next;
|
||||
idx++;
|
||||
}
|
||||
|
||||
lv_draw_fill_dsc_t fill_dsc;
|
||||
lv_draw_rect_dsc_init(&fill_dsc);
|
||||
fill_dsc.color = lv_palette_main(idx % _LV_PALETTE_LAST);
|
||||
fill_dsc.opa = LV_OPA_10;
|
||||
lv_draw_sw_fill(draw_unit, &fill_dsc, &area_rot);
|
||||
|
||||
lv_draw_border_dsc_t border_dsc;
|
||||
lv_draw_border_dsc_init(&border_dsc);
|
||||
border_dsc.color = lv_palette_main(idx % _LV_PALETTE_LAST);
|
||||
border_dsc.opa = LV_OPA_100;
|
||||
border_dsc.width = 2;
|
||||
lv_draw_sw_border(draw_unit, &border_dsc, &area_rot);
|
||||
|
||||
lv_point_t txt_size;
|
||||
lv_text_get_size(&txt_size, "W", LV_FONT_DEFAULT, 0, 0, 100, LV_TEXT_FLAG_NONE);
|
||||
|
||||
lv_area_t txt_area;
|
||||
txt_area.x1 = draw_area.x1;
|
||||
txt_area.x2 = draw_area.x1 + txt_size.x - 1;
|
||||
txt_area.y2 = draw_area.y2;
|
||||
txt_area.y1 = draw_area.y2 - txt_size.y + 1;
|
||||
|
||||
lv_draw_fill_dsc_init(&fill_dsc);
|
||||
fill_dsc.color = lv_color_black();
|
||||
lv_draw_sw_fill(draw_unit, &fill_dsc, &txt_area);
|
||||
|
||||
char buf[8];
|
||||
lv_snprintf(buf, sizeof(buf), "%d", idx);
|
||||
lv_draw_label_dsc_t label_dsc;
|
||||
lv_draw_label_dsc_init(&label_dsc);
|
||||
label_dsc.color = lv_color_white();
|
||||
label_dsc.text = buf;
|
||||
lv_draw_sw_label(draw_unit, &label_dsc, &txt_area);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_PXP*/
|
||||
|
||||
@@ -48,10 +48,6 @@ void lv_pxp_init(void)
|
||||
{
|
||||
_pxp_cfg = pxp_get_default_cfg();
|
||||
|
||||
if(!_pxp_cfg || !_pxp_cfg->pxp_interrupt_deinit || !_pxp_cfg->pxp_interrupt_init ||
|
||||
!_pxp_cfg->pxp_run || !_pxp_cfg->pxp_wait)
|
||||
LV_LOG_ERROR("PXP configuration error.");
|
||||
|
||||
PXP_Init(PXP_ID);
|
||||
|
||||
PXP_EnableCsc1(PXP_ID, false); /*Disable CSC1, it is enabled by default.*/
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2020, 2022, 2023 NXP
|
||||
* Copyright 2020, 2022-2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "lv_pxp_osa.h"
|
||||
|
||||
#if LV_USE_DRAW_PXP
|
||||
#include "lv_pxp_utils.h"
|
||||
#include "../../../misc/lv_log.h"
|
||||
#include "fsl_pxp.h"
|
||||
|
||||
@@ -115,10 +116,7 @@ static void _pxp_interrupt_init(void)
|
||||
{
|
||||
#if defined(SDK_OS_FREE_RTOS)
|
||||
xPXPIdleSemaphore = xSemaphoreCreateBinary();
|
||||
if(xPXPIdleSemaphore == NULL) {
|
||||
LV_LOG_ERROR("xSemaphoreCreateBinary failed!");
|
||||
return;
|
||||
}
|
||||
PXP_ASSERT_MSG(xPXPIdleSemaphore, "xSemaphoreCreateBinary failed!");
|
||||
|
||||
NVIC_SetPriority(PXP_IRQ_ID, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1);
|
||||
#endif
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2020, 2022, 2023 NXP
|
||||
* Copyright 2020, 2022-2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2023 NXP
|
||||
* Copyright 2023-2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
@@ -42,15 +42,9 @@ pxp_output_pixel_format_t pxp_get_out_px_format(lv_color_format_t cf)
|
||||
pxp_output_pixel_format_t out_px_format = kPXP_OutputPixelFormatRGB565;
|
||||
|
||||
switch(cf) {
|
||||
/*2 byte (+alpha) formats*/
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
out_px_format = kPXP_OutputPixelFormatRGB565;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_RGB565A8:
|
||||
LV_ASSERT_MSG(false, "Unsupported color format.");
|
||||
break;
|
||||
|
||||
/*3 byte (+alpha) formats*/
|
||||
case LV_COLOR_FORMAT_RGB888:
|
||||
out_px_format = kPXP_OutputPixelFormatRGB888P;
|
||||
break;
|
||||
@@ -62,7 +56,7 @@ pxp_output_pixel_format_t pxp_get_out_px_format(lv_color_format_t cf)
|
||||
break;
|
||||
|
||||
default:
|
||||
LV_ASSERT_MSG(false, "Unsupported color format.");
|
||||
PXP_ASSERT_MSG(false, "Unsupported color format.");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -74,17 +68,11 @@ pxp_as_pixel_format_t pxp_get_as_px_format(lv_color_format_t cf)
|
||||
pxp_as_pixel_format_t as_px_format = kPXP_AsPixelFormatRGB565;
|
||||
|
||||
switch(cf) {
|
||||
/*2 byte (+alpha) formats*/
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
as_px_format = kPXP_AsPixelFormatRGB565;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_RGB565A8:
|
||||
LV_ASSERT_MSG(false, "Unsupported color format.");
|
||||
break;
|
||||
|
||||
/*3 byte (+alpha) formats*/
|
||||
case LV_COLOR_FORMAT_RGB888:
|
||||
LV_ASSERT_MSG(false, "Unsupported color format.");
|
||||
PXP_ASSERT_MSG(false, "Unsupported color format.");
|
||||
break;
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
as_px_format = kPXP_AsPixelFormatARGB8888;
|
||||
@@ -94,7 +82,7 @@ pxp_as_pixel_format_t pxp_get_as_px_format(lv_color_format_t cf)
|
||||
break;
|
||||
|
||||
default:
|
||||
LV_ASSERT_MSG(false, "Unsupported color format.");
|
||||
PXP_ASSERT_MSG(false, "Unsupported color format.");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -106,24 +94,18 @@ pxp_ps_pixel_format_t pxp_get_ps_px_format(lv_color_format_t cf)
|
||||
pxp_ps_pixel_format_t ps_px_format = kPXP_PsPixelFormatRGB565;
|
||||
|
||||
switch(cf) {
|
||||
/*2 byte (+alpha) formats*/
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
ps_px_format = kPXP_PsPixelFormatRGB565;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_RGB565A8:
|
||||
LV_ASSERT_MSG(false, "Unsupported color format.");
|
||||
break;
|
||||
|
||||
/*3 byte (+alpha) formats*/
|
||||
case LV_COLOR_FORMAT_RGB888:
|
||||
LV_ASSERT_MSG(false, "Unsupported color format.");
|
||||
PXP_ASSERT_MSG(false, "Unsupported color format.");
|
||||
break;
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
#if (!(defined(FSL_FEATURE_PXP_HAS_NO_EXTEND_PIXEL_FORMAT) && FSL_FEATURE_PXP_HAS_NO_EXTEND_PIXEL_FORMAT)) && \
|
||||
(!(defined(FSL_FEATURE_PXP_V3) && FSL_FEATURE_PXP_V3))
|
||||
ps_px_format = kPXP_PsPixelFormatARGB8888;
|
||||
#else
|
||||
LV_ASSERT_MSG(false, "Unsupported color format.");
|
||||
PXP_ASSERT_MSG(false, "Unsupported color format.");
|
||||
#endif
|
||||
break;
|
||||
case LV_COLOR_FORMAT_XRGB8888:
|
||||
@@ -136,13 +118,26 @@ pxp_ps_pixel_format_t pxp_get_ps_px_format(lv_color_format_t cf)
|
||||
break;
|
||||
|
||||
default:
|
||||
LV_ASSERT_MSG(false, "Unsupported color format.");
|
||||
PXP_ASSERT_MSG(false, "Unsupported color format.");
|
||||
break;
|
||||
}
|
||||
|
||||
return ps_px_format;
|
||||
}
|
||||
|
||||
bool pxp_buf_aligned(const void * buf, uint32_t stride)
|
||||
{
|
||||
/* Test for pointer alignment */
|
||||
if((uintptr_t)buf % 64)
|
||||
return false;
|
||||
|
||||
/* Test for invalid stride (no stride alignment required) */
|
||||
if(stride == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2023 NXP
|
||||
* Copyright 2023-2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
@@ -29,6 +29,14 @@ extern "C" {
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#if LV_USE_PXP_ASSERT
|
||||
#define PXP_ASSERT(expr) LV_ASSERT(expr)
|
||||
#define PXP_ASSERT_MSG(expr, msg) LV_ASSERT_MSG(expr, msg)
|
||||
#else
|
||||
#define PXP_ASSERT(expr)
|
||||
#define PXP_ASSERT_MSG(expr, msg) LV_LOG_ERROR(msg)
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
@@ -47,6 +55,8 @@ pxp_as_pixel_format_t pxp_get_as_px_format(lv_color_format_t cf);
|
||||
|
||||
pxp_ps_pixel_format_t pxp_get_ps_px_format(lv_color_format_t cf);
|
||||
|
||||
bool pxp_buf_aligned(const void * buf, uint32_t stride);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2023 NXP
|
||||
* Copyright 2023-2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
#include "lv_vglite_buf.h"
|
||||
#include "lv_vglite_matrix.h"
|
||||
#include "lv_vglite_utils.h"
|
||||
|
||||
#include "lvgl_support.h"
|
||||
@@ -36,14 +35,12 @@
|
||||
|
||||
static void * _buf_malloc(size_t size_bytes, lv_color_format_t cf);
|
||||
|
||||
static void * _align_buf(void * buf, lv_color_format_t cf);
|
||||
static void * _buf_align(void * buf, lv_color_format_t cf);
|
||||
|
||||
static void _invalidate_cache(lv_draw_buf_t * draw_buf, const char * area);
|
||||
static void _invalidate_cache(void * buf, uint32_t stride, lv_color_format_t cf, const lv_area_t * area);
|
||||
|
||||
static uint32_t _width_to_stride(uint32_t w, lv_color_format_t cf);
|
||||
|
||||
static void * _go_to_xy(lv_draw_buf_t * draw_buf, int32_t x, int32_t y);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
@@ -61,7 +58,7 @@ void lv_draw_buf_vglite_init_handlers(void)
|
||||
lv_draw_buf_handlers_t * handlers = lv_draw_buf_get_handlers();
|
||||
|
||||
handlers->buf_malloc_cb = _buf_malloc;
|
||||
handlers->align_pointer_cb = _align_buf;
|
||||
handlers->align_pointer_cb = _buf_align;
|
||||
handlers->invalidate_cache_cb = _invalidate_cache;
|
||||
handlers->width_to_stride_cb = _width_to_stride;
|
||||
}
|
||||
@@ -80,7 +77,7 @@ static void * _buf_malloc(size_t size_bytes, lv_color_format_t cf)
|
||||
return lv_malloc(size_bytes);
|
||||
}
|
||||
|
||||
static void * _align_buf(void * buf, lv_color_format_t cf)
|
||||
static void * _buf_align(void * buf, lv_color_format_t cf)
|
||||
{
|
||||
uint8_t align_bytes = vglite_get_alignment(cf);
|
||||
|
||||
@@ -93,17 +90,54 @@ static void * _align_buf(void * buf, lv_color_format_t cf)
|
||||
return buf_u8;
|
||||
}
|
||||
|
||||
static void _invalidate_cache(lv_draw_buf_t * draw_buf, const char * area)
|
||||
static void _invalidate_cache(void * buf, uint32_t stride, lv_color_format_t cf, const lv_area_t * area)
|
||||
{
|
||||
LV_UNUSED(draw_buf);
|
||||
LV_UNUSED(area);
|
||||
if(area->y1 == 0) {
|
||||
uint16_t size = stride * lv_area_get_height(area);
|
||||
|
||||
DEMO_CleanInvalidateCache();
|
||||
/* Invalidate full buffer. */
|
||||
DEMO_CleanInvalidateCacheByAddr((void *)buf, size);
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t * buf_u8 = buf;
|
||||
/* ARM require a 32 byte aligned address. */
|
||||
uint8_t align_bytes = 32;
|
||||
uint8_t bits_per_pixel = lv_color_format_get_bpp(cf);
|
||||
|
||||
uint16_t align_pixels = align_bytes * 8 / bits_per_pixel;
|
||||
uint16_t offset_x = 0;
|
||||
|
||||
if(area->x1 >= (int32_t)(area->x1 % align_pixels)) {
|
||||
uint16_t shift_x = area->x1 - (area->x1 % align_pixels);
|
||||
|
||||
offset_x = area->x1 - shift_x;
|
||||
buf_u8 += (shift_x * bits_per_pixel) / 8;
|
||||
}
|
||||
|
||||
if(area->y1) {
|
||||
uint16_t shift_y = area->y1;
|
||||
|
||||
buf_u8 += shift_y * stride;
|
||||
}
|
||||
|
||||
/* Area to clear can start from a different offset in buffer.
|
||||
* Invalidate the area line by line.
|
||||
*/
|
||||
uint16_t line_pixels = offset_x + lv_area_get_width(area);
|
||||
uint16_t line_size = (line_pixels * bits_per_pixel) / 8;
|
||||
uint16_t area_height = lv_area_get_height(area);
|
||||
|
||||
for(uint16_t y = 0; y < area_height; y++) {
|
||||
const void * line_addr = buf_u8 + y * stride;
|
||||
|
||||
DEMO_CleanInvalidateCacheByAddr((void *)line_addr, line_size);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t _width_to_stride(uint32_t w, lv_color_format_t cf)
|
||||
{
|
||||
uint8_t bits_per_pixel = vglite_get_px_size(cf);
|
||||
uint8_t bits_per_pixel = lv_color_format_get_bpp(cf);
|
||||
uint32_t width_bits = (w * bits_per_pixel + 7) & ~7;
|
||||
uint32_t width_bytes = width_bits / 8;
|
||||
uint8_t align_bytes = vglite_get_alignment(cf);
|
||||
@@ -111,70 +145,4 @@ static uint32_t _width_to_stride(uint32_t w, lv_color_format_t cf)
|
||||
return (width_bytes + align_bytes - 1) & ~(align_bytes - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo
|
||||
* LVGL needs to use hardware acceleration for buf_copy and do not affect GPU rendering.
|
||||
*/
|
||||
#if 0
|
||||
|
||||
static void _vglite_buf_clear(lv_draw_buf_t * draw_buf, const lv_area_t * area)
|
||||
{
|
||||
uint32_t stride = lv_draw_buf_get_stride(draw_buf);
|
||||
|
||||
/* Set vgbuf structure. */
|
||||
vg_lite_buffer_t vgbuf;
|
||||
vglite_set_buf(&vgbuf, draw_buf->buf, draw_buf->width, draw_buf->height, stride, draw_buf->color_format);
|
||||
|
||||
vg_lite_color_t vgcol = 0;
|
||||
|
||||
vg_lite_rectangle_t rect = {
|
||||
.x = area->x1,
|
||||
.y = area->y1,
|
||||
.width = lv_area_get_width(area),
|
||||
.height = lv_area_get_height(area)
|
||||
};
|
||||
|
||||
vg_lite_error_t err = vg_lite_clear(&vgbuf, &rect, vgcol);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Clear failed.");
|
||||
|
||||
vglite_run();
|
||||
}
|
||||
|
||||
static void _vglite_buf_copy(void * dest_buf, uint32_t dest_stride, const lv_area_t * dest_area,
|
||||
void * src_buf, uint32_t src_stride, const lv_area_t * src_area,
|
||||
lv_color_format_t cf)
|
||||
{
|
||||
/* Set src_vgbuf structure. */
|
||||
vg_lite_buffer_t src_vgbuf;
|
||||
vglite_set_buf(&src_vgbuf, src_buf, lv_area_get_width(src_area), lv_area_get_height(src_area), src_stride, cf);
|
||||
|
||||
/* Set dest_vgbuf structure. */
|
||||
vg_lite_buffer_t dest_vgbuf;
|
||||
vglite_set_buf(&dest_vgbuf, dest_buf, lv_area_get_width(dest_area), lv_area_get_height(dest_area), dest_stride, cf);
|
||||
|
||||
uint32_t rect[] = {
|
||||
(uint32_t)src_area->x1, /* start x */
|
||||
(uint32_t)src_area->y1, /* start y */
|
||||
(uint32_t)lv_area_get_width(src_area), /* width */
|
||||
(uint32_t)lv_area_get_height(src_area) /* height */
|
||||
};
|
||||
|
||||
/* Set scissor. */
|
||||
vglite_set_scissor(dest_area);
|
||||
|
||||
/* Set vgmatrix. */
|
||||
vglite_set_translation_matrix(dest_area);
|
||||
vg_lite_matrix_t * vgmatrix = vglite_get_matrix();
|
||||
|
||||
vg_lite_error_t err = vg_lite_blit_rect(&dest_vgbuf, &src_vgbuf, rect, vgmatrix,
|
||||
VG_LITE_BLEND_NONE, 0xFFFFFFFFU, VG_LITE_FILTER_POINT);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Blit rectangle failed.");
|
||||
|
||||
vglite_run();
|
||||
|
||||
/* Disable scissor. */
|
||||
vglite_disable_scissor();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*LV_USE_DRAW_VGLITE*/
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2023 NXP
|
||||
* Copyright 2023-2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
@@ -19,7 +19,9 @@
|
||||
#include "lv_vglite_buf.h"
|
||||
#include "lv_vglite_utils.h"
|
||||
|
||||
#include "../../../display/lv_display_private.h"
|
||||
#if LV_USE_PARALLEL_DRAW_DEBUG
|
||||
#include "../../../core/lv_global.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@@ -27,7 +29,7 @@
|
||||
|
||||
#define DRAW_UNIT_ID_VGLITE 2
|
||||
|
||||
#if LV_USE_OS
|
||||
#if LV_USE_VGLITE_DRAW_ASYNC
|
||||
#define VGLITE_TASK_BUF_SIZE 10
|
||||
#endif
|
||||
|
||||
@@ -35,7 +37,7 @@
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
#if LV_USE_OS
|
||||
#if LV_USE_VGLITE_DRAW_ASYNC
|
||||
/**
|
||||
* Structure of pending vglite draw task
|
||||
*/
|
||||
@@ -50,16 +52,21 @@ typedef struct _vglite_draw_task_t {
|
||||
**********************/
|
||||
|
||||
/*
|
||||
* Dispatch a task to the VGLite unit.
|
||||
* Evaluate a task and set the score and preferred VGLite draw unit.
|
||||
* Return 1 if task is preferred, 0 otherwise (task is not supported).
|
||||
*/
|
||||
static int32_t _vglite_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task);
|
||||
|
||||
/*
|
||||
* Dispatch (assign) a task to VGLite draw unit (itself).
|
||||
* Return 1 if task was dispatched, 0 otherwise (task not supported).
|
||||
*/
|
||||
static int32_t _vglite_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer);
|
||||
|
||||
/*
|
||||
* Evaluate a task and set the score and preferred VGLite unit.
|
||||
* Return 1 if task is preferred, 0 otherwise (task is not supported).
|
||||
* Delete the VGLite draw unit.
|
||||
*/
|
||||
static int32_t _vglite_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task);
|
||||
static int32_t _vglite_delete(lv_draw_unit_t * draw_unit);
|
||||
|
||||
#if LV_USE_OS
|
||||
static void _vglite_render_thread_cb(void * ptr);
|
||||
@@ -71,7 +78,11 @@ static void _vglite_execute_drawing(lv_draw_vglite_unit_t * u);
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
#if LV_USE_OS
|
||||
#if LV_USE_PARALLEL_DRAW_DEBUG
|
||||
#define _draw_info LV_GLOBAL_DEFAULT()->draw_info
|
||||
#endif
|
||||
|
||||
#if LV_USE_VGLITE_DRAW_ASYNC
|
||||
/*
|
||||
* Circular buffer to hold the queued and the flushed tasks.
|
||||
* Two indexes, _head and _tail, are used to signal the beginning
|
||||
@@ -95,11 +106,12 @@ void lv_draw_vglite_init(void)
|
||||
lv_draw_buf_vglite_init_handlers();
|
||||
|
||||
lv_draw_vglite_unit_t * draw_vglite_unit = lv_draw_create_unit(sizeof(lv_draw_vglite_unit_t));
|
||||
draw_vglite_unit->base_unit.dispatch_cb = _vglite_dispatch;
|
||||
draw_vglite_unit->base_unit.evaluate_cb = _vglite_evaluate;
|
||||
draw_vglite_unit->base_unit.dispatch_cb = _vglite_dispatch;
|
||||
draw_vglite_unit->base_unit.delete_cb = _vglite_delete;
|
||||
|
||||
#if LV_USE_OS
|
||||
lv_thread_init(&draw_vglite_unit->thread, LV_THREAD_PRIO_HIGH, _vglite_render_thread_cb, 8 * 1024, draw_vglite_unit);
|
||||
lv_thread_init(&draw_vglite_unit->thread, LV_THREAD_PRIO_HIGH, _vglite_render_thread_cb, 2 * 1024, draw_vglite_unit);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -111,19 +123,70 @@ void lv_draw_vglite_deinit(void)
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static inline bool _vglite_cf_supported(lv_color_format_t cf)
|
||||
static inline bool _vglite_src_cf_supported(lv_color_format_t cf)
|
||||
{
|
||||
/*Add here the platform specific code for supported formats.*/
|
||||
bool is_cf_supported = false;
|
||||
|
||||
bool is_cf_unsupported = (cf == LV_COLOR_FORMAT_RGB565A8 || cf == LV_COLOR_FORMAT_RGB888);
|
||||
switch(cf) {
|
||||
#if CHIPID == 0x255 || CHIPID == 0x555
|
||||
case LV_COLOR_FORMAT_I1:
|
||||
case LV_COLOR_FORMAT_I2:
|
||||
case LV_COLOR_FORMAT_I4:
|
||||
case LV_COLOR_FORMAT_I8:
|
||||
#endif
|
||||
case LV_COLOR_FORMAT_A4:
|
||||
case LV_COLOR_FORMAT_A8:
|
||||
case LV_COLOR_FORMAT_L8:
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
#if CHIPID == 0x555
|
||||
case LV_COLOR_FORMAT_RGB565A8:
|
||||
case LV_COLOR_FORMAT_RGB888:
|
||||
#endif
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
case LV_COLOR_FORMAT_XRGB8888:
|
||||
is_cf_supported = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (!is_cf_unsupported);
|
||||
return is_cf_supported;
|
||||
}
|
||||
|
||||
static inline bool _vglite_dest_cf_supported(lv_color_format_t cf)
|
||||
{
|
||||
bool is_cf_supported = false;
|
||||
|
||||
switch(cf) {
|
||||
case LV_COLOR_FORMAT_A8:
|
||||
#if CHIPID == 0x255 || CHIPID == 0x555
|
||||
case LV_COLOR_FORMAT_L8:
|
||||
#endif
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
#if CHIPTID == 0x555
|
||||
case LV_COLOR_FORMAT_RGB565A8:
|
||||
case LV_COLOR_FORMAT_RGB888:
|
||||
#endif
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
case LV_COLOR_FORMAT_XRGB8888:
|
||||
is_cf_supported = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return is_cf_supported;
|
||||
}
|
||||
|
||||
static int32_t _vglite_evaluate(lv_draw_unit_t * u, lv_draw_task_t * t)
|
||||
{
|
||||
LV_UNUSED(u);
|
||||
|
||||
const lv_draw_dsc_base_t * draw_dsc_base = (lv_draw_dsc_base_t *) t->draw_dsc;
|
||||
|
||||
if(!_vglite_dest_cf_supported(draw_dsc_base->layer->color_format))
|
||||
return 0;
|
||||
|
||||
switch(t->type) {
|
||||
case LV_DRAW_TASK_TYPE_FILL:
|
||||
if(t->preference_score > 80) {
|
||||
@@ -134,6 +197,7 @@ static int32_t _vglite_evaluate(lv_draw_unit_t * u, lv_draw_task_t * t)
|
||||
|
||||
case LV_DRAW_TASK_TYPE_LINE:
|
||||
case LV_DRAW_TASK_TYPE_ARC:
|
||||
case LV_DRAW_TASK_TYPE_TRIANGLE:
|
||||
if(t->preference_score > 90) {
|
||||
t->preference_score = 90;
|
||||
t->preferred_draw_unit_id = DRAW_UNIT_ID_VGLITE;
|
||||
@@ -160,37 +224,11 @@ static int32_t _vglite_evaluate(lv_draw_unit_t * u, lv_draw_task_t * t)
|
||||
return 1;
|
||||
}
|
||||
|
||||
case LV_DRAW_TASK_TYPE_BG_IMG: {
|
||||
const lv_draw_bg_image_dsc_t * draw_dsc = (lv_draw_bg_image_dsc_t *) t->draw_dsc;
|
||||
lv_image_src_t src_type = lv_image_src_get_type(draw_dsc->src);
|
||||
|
||||
if(src_type != LV_IMAGE_SRC_SYMBOL) {
|
||||
bool has_recolor = (draw_dsc->recolor_opa != LV_OPA_TRANSP);
|
||||
|
||||
if(has_recolor
|
||||
|| (!_vglite_cf_supported(draw_dsc->img_header.cf))
|
||||
|| (!vglite_buf_aligned(draw_dsc->src, draw_dsc->img_header.stride, draw_dsc->img_header.cf))
|
||||
)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(t->preference_score > 80) {
|
||||
t->preference_score = 80;
|
||||
t->preferred_draw_unit_id = DRAW_UNIT_ID_VGLITE;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
case LV_DRAW_TASK_TYPE_LAYER: {
|
||||
const lv_draw_image_dsc_t * draw_dsc = (lv_draw_image_dsc_t *) t->draw_dsc;
|
||||
lv_layer_t * layer_to_draw = (lv_layer_t *)draw_dsc->src;
|
||||
lv_draw_buf_t * draw_buf = &layer_to_draw->draw_buf;
|
||||
|
||||
bool has_recolor = (draw_dsc->recolor_opa != LV_OPA_TRANSP);
|
||||
|
||||
if(has_recolor
|
||||
|| (!_vglite_cf_supported(draw_buf->color_format))
|
||||
)
|
||||
if(!_vglite_src_cf_supported(layer_to_draw->color_format))
|
||||
return 0;
|
||||
|
||||
if(t->preference_score > 80) {
|
||||
@@ -204,16 +242,15 @@ static int32_t _vglite_evaluate(lv_draw_unit_t * u, lv_draw_task_t * t)
|
||||
lv_draw_image_dsc_t * draw_dsc = (lv_draw_image_dsc_t *) t->draw_dsc;
|
||||
const lv_image_dsc_t * img_dsc = draw_dsc->src;
|
||||
|
||||
bool has_recolor = (draw_dsc->recolor_opa != LV_OPA_TRANSP);
|
||||
#if VGLITE_BLIT_SPLIT_ENABLED
|
||||
bool has_transform = (draw_dsc->angle != 0 || draw_dsc->zoom != LV_ZOOM_NONE);
|
||||
#if LV_USE_VGLITE_BLIT_SPLIT
|
||||
bool has_transform = (draw_dsc->rotation != 0 || draw_dsc->scale_x != LV_SCALE_NONE ||
|
||||
draw_dsc->scale_y != LV_SCALE_NONE);
|
||||
#endif
|
||||
|
||||
if(has_recolor
|
||||
#if VGLITE_BLIT_SPLIT_ENABLED
|
||||
if((!_vglite_src_cf_supported(img_dsc->header.cf))
|
||||
#if LV_USE_VGLITE_BLIT_SPLIT
|
||||
|| has_transform
|
||||
#endif
|
||||
|| (!_vglite_cf_supported(img_dsc->header.cf))
|
||||
|| (!vglite_buf_aligned(img_dsc->data, img_dsc->header.stride, img_dsc->header.cf))
|
||||
)
|
||||
return 0;
|
||||
@@ -239,19 +276,11 @@ static int32_t _vglite_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
|
||||
if(draw_vglite_unit->task_act)
|
||||
return 0;
|
||||
|
||||
/* Return if target buffer format is not supported.
|
||||
*
|
||||
* FIXME: Source format and destination format support is different!
|
||||
*/
|
||||
if(!_vglite_cf_supported(layer->draw_buf.color_format))
|
||||
return 0;
|
||||
|
||||
/* Try to get an ready to draw. */
|
||||
lv_draw_task_t * t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_VGLITE);
|
||||
|
||||
/* Return 0 is no selection, some tasks can be supported by other units. */
|
||||
if(t == NULL || t->preferred_draw_unit_id != DRAW_UNIT_ID_VGLITE)
|
||||
return 0;
|
||||
return -1;
|
||||
|
||||
void * buf = lv_draw_layer_alloc_buf(layer);
|
||||
if(buf == NULL)
|
||||
@@ -264,7 +293,8 @@ static int32_t _vglite_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
|
||||
|
||||
#if LV_USE_OS
|
||||
/* Let the render thread work. */
|
||||
lv_thread_sync_signal(&draw_vglite_unit->sync);
|
||||
if(draw_vglite_unit->inited)
|
||||
lv_thread_sync_signal(&draw_vglite_unit->sync);
|
||||
#else
|
||||
_vglite_execute_drawing(draw_vglite_unit);
|
||||
|
||||
@@ -278,17 +308,55 @@ static int32_t _vglite_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int32_t _vglite_delete(lv_draw_unit_t * draw_unit)
|
||||
{
|
||||
#if LV_USE_OS
|
||||
lv_draw_vglite_unit_t * draw_vglite_unit = (lv_draw_vglite_unit_t *) draw_unit;
|
||||
|
||||
LV_LOG_INFO("Cancel VGLite draw thread.");
|
||||
draw_vglite_unit->exit_status = true;
|
||||
|
||||
if(draw_vglite_unit->inited)
|
||||
lv_thread_sync_signal(&draw_vglite_unit->sync);
|
||||
|
||||
lv_result_t res = lv_thread_delete(&draw_vglite_unit->thread);
|
||||
|
||||
return res;
|
||||
#else
|
||||
LV_UNUSED(draw_unit);
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void _vglite_execute_drawing(lv_draw_vglite_unit_t * u)
|
||||
{
|
||||
lv_draw_task_t * t = u->task_act;
|
||||
lv_draw_unit_t * draw_unit = (lv_draw_unit_t *)u;
|
||||
lv_layer_t * layer = draw_unit->target_layer;
|
||||
|
||||
/* Set target buffer */
|
||||
lv_layer_t * layer = draw_unit->target_layer;
|
||||
vglite_set_dest_buf(&layer->draw_buf);
|
||||
uint32_t buf_width = lv_area_get_width(&layer->buf_area);
|
||||
uint32_t buf_height = lv_area_get_height(&layer->buf_area);
|
||||
|
||||
/* Invalidate cache */
|
||||
lv_draw_buf_invalidate_cache(&layer->draw_buf, (const char *)&t->area);
|
||||
vglite_set_dest_buf(layer->buf, buf_width, buf_height, layer->buf_stride, layer->color_format);
|
||||
|
||||
lv_area_t clip_area;
|
||||
lv_area_copy(&clip_area, draw_unit->clip_area);
|
||||
lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
|
||||
|
||||
lv_area_t draw_area;
|
||||
lv_area_copy(&draw_area, &t->area);
|
||||
lv_area_move(&draw_area, -layer->buf_area.x1, -layer->buf_area.y1);
|
||||
|
||||
if(!_lv_area_intersect(&draw_area, &draw_area, &clip_area))
|
||||
return; /*Fully clipped, nothing to do*/
|
||||
|
||||
/* Invalidate the drawing area */
|
||||
lv_draw_buf_invalidate_cache(layer->buf, layer->buf_stride, layer->color_format, &draw_area);
|
||||
|
||||
/* Set scissor area */
|
||||
vglite_set_scissor(&clip_area);
|
||||
|
||||
switch(t->type) {
|
||||
case LV_DRAW_TASK_TYPE_LABEL:
|
||||
@@ -300,9 +368,6 @@ static void _vglite_execute_drawing(lv_draw_vglite_unit_t * u)
|
||||
case LV_DRAW_TASK_TYPE_BORDER:
|
||||
lv_draw_vglite_border(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_BG_IMG:
|
||||
lv_draw_vglite_bg_img(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_IMAGE:
|
||||
lv_draw_vglite_img(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
@@ -315,20 +380,25 @@ static void _vglite_execute_drawing(lv_draw_vglite_unit_t * u)
|
||||
case LV_DRAW_TASK_TYPE_LAYER:
|
||||
lv_draw_vglite_layer(draw_unit, t->draw_dsc, &t->area);
|
||||
break;
|
||||
case LV_DRAW_TASK_TYPE_TRIANGLE:
|
||||
lv_draw_vglite_triangle(draw_unit, t->draw_dsc);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Disable scissor */
|
||||
vglite_set_scissor(&layer->buf_area);
|
||||
|
||||
#if LV_USE_PARALLEL_DRAW_DEBUG
|
||||
/* Layers manage it for themselves. */
|
||||
/*Layers manage it for themselves*/
|
||||
if(t->type != LV_DRAW_TASK_TYPE_LAYER) {
|
||||
lv_area_t draw_area;
|
||||
if(!_lv_area_intersect(&draw_area, &t->area, u->base_unit.clip_area))
|
||||
return;
|
||||
|
||||
int32_t idx = 0;
|
||||
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
||||
lv_draw_unit_t * draw_unit_tmp = disp->draw_unit_head;
|
||||
lv_draw_unit_t * draw_unit_tmp = _draw_info.unit_head;
|
||||
while(draw_unit_tmp != (lv_draw_unit_t *)u) {
|
||||
draw_unit_tmp = draw_unit_tmp->next;
|
||||
idx++;
|
||||
@@ -340,10 +410,10 @@ static void _vglite_execute_drawing(lv_draw_vglite_unit_t * u)
|
||||
rect_dsc.bg_opa = LV_OPA_10;
|
||||
rect_dsc.border_opa = LV_OPA_80;
|
||||
rect_dsc.border_width = 1;
|
||||
lv_draw_vglite_rect((lv_draw_unit_t *)u, &rect_dsc, &draw_area);
|
||||
lv_draw_sw_fill((lv_draw_unit_t *)u, &rect_dsc, &draw_area);
|
||||
|
||||
lv_point_t txt_size;
|
||||
lv_txt_get_size(&txt_size, "W", LV_FONT_DEFAULT, 0, 0, 100, LV_TEXT_FLAG_NONE);
|
||||
lv_text_get_size(&txt_size, "W", LV_FONT_DEFAULT, 0, 0, 100, LV_TEXT_FLAG_NONE);
|
||||
|
||||
lv_area_t txt_area;
|
||||
txt_area.x1 = draw_area.x1;
|
||||
@@ -353,7 +423,7 @@ static void _vglite_execute_drawing(lv_draw_vglite_unit_t * u)
|
||||
|
||||
lv_draw_rect_dsc_init(&rect_dsc);
|
||||
rect_dsc.bg_color = lv_color_white();
|
||||
lv_draw_vglite_rect((lv_draw_unit_t *)u, &rect_dsc, &txt_area);
|
||||
lv_draw_sw_fill((lv_draw_unit_t *)u, &rect_dsc, &txt_area);
|
||||
|
||||
char buf[8];
|
||||
lv_snprintf(buf, sizeof(buf), "%d", idx);
|
||||
@@ -361,12 +431,12 @@ static void _vglite_execute_drawing(lv_draw_vglite_unit_t * u)
|
||||
lv_draw_label_dsc_init(&label_dsc);
|
||||
label_dsc.color = lv_color_black();
|
||||
label_dsc.text = buf;
|
||||
lv_draw_vglite_label((lv_draw_unit_t *)u, &label_dsc, &txt_area);
|
||||
lv_draw_sw_label((lv_draw_unit_t *)u, &label_dsc, &txt_area);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if LV_USE_OS
|
||||
#if LV_USE_VGLITE_DRAW_ASYNC
|
||||
static inline void _vglite_queue_task(lv_draw_task_t * task_act)
|
||||
{
|
||||
_draw_task_buf[_tail].task = task_act;
|
||||
@@ -397,29 +467,47 @@ static inline void _vglite_signal_task_ready(lv_draw_task_t * task_act)
|
||||
}
|
||||
|
||||
if(task_act)
|
||||
LV_ASSERT_MSG(_tail != _head, "VGLite task buffer full.");
|
||||
VGLITE_ASSERT_MSG(_tail != _head, "VGLite task buffer full.");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LV_USE_OS
|
||||
static void _vglite_render_thread_cb(void * ptr)
|
||||
{
|
||||
lv_draw_vglite_unit_t * u = ptr;
|
||||
|
||||
lv_thread_sync_init(&u->sync);
|
||||
u->inited = true;
|
||||
|
||||
while(1) {
|
||||
/*
|
||||
* Wait for sync if no task received or _draw_task_buf is empty.
|
||||
* The thread will have to run as much as there are pending tasks.
|
||||
*/
|
||||
while(u->task_act == NULL && _head == _tail) {
|
||||
/* Wait for sync if there is no task set. */
|
||||
while(u->task_act == NULL
|
||||
#if LV_USE_VGLITE_DRAW_ASYNC
|
||||
/*
|
||||
* Wait for sync if _draw_task_buf is empty.
|
||||
* The thread will have to run as much as there are pending tasks.
|
||||
*/
|
||||
&& _head == _tail
|
||||
#endif
|
||||
) {
|
||||
if(u->exit_status)
|
||||
break;
|
||||
|
||||
lv_thread_sync_wait(&u->sync);
|
||||
}
|
||||
|
||||
if(u->task_act) {
|
||||
_vglite_queue_task((void *)u->task_act);
|
||||
if(u->exit_status) {
|
||||
LV_LOG_INFO("Ready to exit VGLite draw thread.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(u->task_act) {
|
||||
#if LV_USE_VGLITE_DRAW_ASYNC
|
||||
_vglite_queue_task((void *)u->task_act);
|
||||
#endif
|
||||
_vglite_execute_drawing(u);
|
||||
}
|
||||
#if LV_USE_VGLITE_DRAW_ASYNC
|
||||
else {
|
||||
/*
|
||||
* Update the flush status for last pending tasks.
|
||||
@@ -427,15 +515,23 @@ static void _vglite_render_thread_cb(void * ptr)
|
||||
*/
|
||||
vglite_run();
|
||||
}
|
||||
|
||||
#endif
|
||||
#if LV_USE_VGLITE_DRAW_ASYNC
|
||||
_vglite_signal_task_ready((void *)u->task_act);
|
||||
|
||||
#else
|
||||
/* Signal the ready state to dispatcher. */
|
||||
u->task_act->state = LV_DRAW_TASK_STATE_READY;
|
||||
#endif
|
||||
/* Cleanup. */
|
||||
u->task_act = NULL;
|
||||
|
||||
/* The draw unit is free now. Request a new dispatching as it can get a new task. */
|
||||
lv_draw_dispatch_request();
|
||||
}
|
||||
|
||||
u->inited = false;
|
||||
lv_thread_sync_delete(&u->sync);
|
||||
LV_LOG_INFO("Exit VGLite draw thread.");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2023 NXP
|
||||
* Copyright 2023-2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
@@ -29,33 +29,11 @@ extern "C" {
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**
|
||||
* Enable BLIT quality degradation workaround for RT595,
|
||||
* recommended for screen's dimension > 352 pixels.
|
||||
*/
|
||||
#define RT595_BLIT_WRKRND_ENABLED 1
|
||||
|
||||
/* Internal compound symbol */
|
||||
#if (defined(CPU_MIMXRT595SFFOB) || defined(CPU_MIMXRT595SFFOB_cm33) || \
|
||||
defined(CPU_MIMXRT595SFFOC) || defined(CPU_MIMXRT595SFFOC_cm33)) && \
|
||||
RT595_BLIT_WRKRND_ENABLED
|
||||
#define VGLITE_BLIT_SPLIT_ENABLED 1
|
||||
#else
|
||||
#define VGLITE_BLIT_SPLIT_ENABLED 0
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
lv_draw_unit_t base_unit;
|
||||
lv_draw_task_t * task_act;
|
||||
#if LV_USE_OS
|
||||
lv_thread_sync_t sync;
|
||||
lv_thread_t thread;
|
||||
#endif
|
||||
} lv_draw_vglite_unit_t;
|
||||
typedef lv_draw_sw_unit_t lv_draw_vglite_unit_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
@@ -70,9 +48,6 @@ void lv_draw_vglite_deinit(void);
|
||||
void lv_draw_vglite_arc(lv_draw_unit_t * draw_unit, const lv_draw_arc_dsc_t * dsc,
|
||||
const lv_area_t * coords);
|
||||
|
||||
void lv_draw_vglite_bg_img(lv_draw_unit_t * draw_unit, const lv_draw_bg_image_dsc_t * dsc,
|
||||
const lv_area_t * coords);
|
||||
|
||||
void lv_draw_vglite_border(lv_draw_unit_t * draw_unit, const lv_draw_border_dsc_t * dsc,
|
||||
const lv_area_t * coords);
|
||||
|
||||
@@ -90,6 +65,8 @@ void lv_draw_vglite_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t
|
||||
|
||||
void lv_draw_vglite_line(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc);
|
||||
|
||||
void lv_draw_vglite_triangle(lv_draw_unit_t * draw_unit, const lv_draw_triangle_dsc_t * dsc);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2021-2023 NXP
|
||||
* Copyright 2021-2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
@@ -77,7 +77,7 @@ typedef struct _cubic_cont_pt {
|
||||
* Draw arc shape with effects
|
||||
*
|
||||
* @param[in] center Arc center with relative coordinates
|
||||
* @param[in] clip_area Clipping area with relative coordinates to dest buff
|
||||
* @param[in] clip_area Clip area with relative coordinates to dest buff
|
||||
* @param[in] dsc Arc description structure (width, rounded ending, opacity)
|
||||
*
|
||||
*/
|
||||
@@ -109,13 +109,13 @@ void lv_draw_vglite_arc(lv_draw_unit_t * draw_unit, const lv_draw_arc_dsc_t * ds
|
||||
return;
|
||||
|
||||
lv_layer_t * layer = draw_unit->target_layer;
|
||||
lv_point_t rel_center = {dsc->center.x - layer->draw_buf_ofs.x, dsc->center.y - layer->draw_buf_ofs.y};
|
||||
lv_point_t center = {dsc->center.x - layer->buf_area.x1, dsc->center.y - layer->buf_area.y1};
|
||||
|
||||
lv_area_t rel_clip_area;
|
||||
lv_area_copy(&rel_clip_area, draw_unit->clip_area);
|
||||
lv_area_move(&rel_clip_area, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
|
||||
lv_area_t clip_area;
|
||||
lv_area_copy(&clip_area, draw_unit->clip_area);
|
||||
lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
|
||||
|
||||
_vglite_draw_arc(&rel_center, &rel_clip_area, dsc);
|
||||
_vglite_draw_arc(¢er, &clip_area, dsc);
|
||||
}
|
||||
|
||||
/**********************
|
||||
@@ -207,7 +207,7 @@ static void _set_full_arc(vg_arc * fullarc)
|
||||
fullarc->p3y = 0;
|
||||
break;
|
||||
default:
|
||||
LV_ASSERT_MSG(false, "Invalid arc quarter.");
|
||||
VGLITE_ASSERT_MSG(false, "Invalid arc quarter.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -562,10 +562,14 @@ static void _add_arc_path(int32_t * arc_path, int * pidx, int32_t radius,
|
||||
static void _vglite_draw_arc(const lv_point_t * center, const lv_area_t * clip_area,
|
||||
const lv_draw_arc_dsc_t * dsc)
|
||||
{
|
||||
vg_lite_error_t err = VG_LITE_SUCCESS;
|
||||
vg_lite_path_t path;
|
||||
uint16_t start_angle = dsc->start_angle;
|
||||
uint16_t end_angle = dsc->end_angle;
|
||||
|
||||
/* be sure end_angle > start_angle */
|
||||
if(end_angle < start_angle)
|
||||
end_angle += 360;
|
||||
|
||||
bool donut = ((end_angle - start_angle) % 360 == 0) ? true : false;
|
||||
vg_lite_buffer_t * vgbuf = vglite_get_dest_buf();
|
||||
|
||||
@@ -662,10 +666,9 @@ static void _vglite_draw_arc(const lv_point_t * center, const lv_area_t * clip_a
|
||||
|
||||
arc_path[pidx++] = VLC_OP_END;
|
||||
|
||||
err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, (uint32_t)pidx * sizeof(int32_t), arc_path,
|
||||
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
|
||||
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Init path failed.");
|
||||
VGLITE_CHECK_ERROR(vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, (uint32_t)pidx * sizeof(int32_t), arc_path,
|
||||
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
|
||||
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f));
|
||||
|
||||
lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->opa);
|
||||
vg_lite_color_t vgcol = vglite_get_color(col32, false);
|
||||
@@ -673,18 +676,12 @@ static void _vglite_draw_arc(const lv_point_t * center, const lv_area_t * clip_a
|
||||
vg_lite_matrix_t matrix;
|
||||
vg_lite_identity(&matrix);
|
||||
|
||||
vglite_set_scissor(clip_area);
|
||||
|
||||
/*** Draw arc ***/
|
||||
err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Draw arc failed.");
|
||||
VGLITE_CHECK_ERROR(vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol));
|
||||
|
||||
vglite_run();
|
||||
|
||||
vglite_disable_scissor();
|
||||
|
||||
err = vg_lite_clear_path(&path);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Clear path failed.");
|
||||
VGLITE_CHECK_ERROR(vg_lite_clear_path(&path));
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_VGLITE*/
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
/**
|
||||
* @file lv_draw_vglite_bg_img.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2022, 2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_vglite.h"
|
||||
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_vglite_bg_img(lv_draw_unit_t * draw_unit, const lv_draw_bg_image_dsc_t * dsc,
|
||||
const lv_area_t * coords)
|
||||
{
|
||||
if(dsc->src == NULL) return;
|
||||
if(dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
lv_area_t clip_area;
|
||||
if(!_lv_area_intersect(&clip_area, coords, draw_unit->clip_area)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const lv_area_t * clip_area_ori = draw_unit->clip_area;
|
||||
draw_unit->clip_area = &clip_area;
|
||||
|
||||
lv_image_src_t src_type = lv_image_src_get_type(dsc->src);
|
||||
if(src_type == LV_IMAGE_SRC_SYMBOL) {
|
||||
lv_point_t size;
|
||||
lv_text_get_size(&size, dsc->src, dsc->font, 0, 0, LV_COORD_MAX, LV_TEXT_FLAG_NONE);
|
||||
lv_area_t a;
|
||||
a.x1 = coords->x1 + lv_area_get_width(coords) / 2 - size.x / 2;
|
||||
a.x2 = a.x1 + size.x - 1;
|
||||
a.y1 = coords->y1 + lv_area_get_height(coords) / 2 - size.y / 2;
|
||||
a.y2 = a.y1 + size.y - 1;
|
||||
|
||||
lv_draw_label_dsc_t label_draw_dsc;
|
||||
lv_draw_label_dsc_init(&label_draw_dsc);
|
||||
label_draw_dsc.font = dsc->font;
|
||||
label_draw_dsc.color = dsc->recolor;
|
||||
label_draw_dsc.opa = dsc->opa;
|
||||
label_draw_dsc.text = dsc->src;
|
||||
lv_draw_vglite_label(draw_unit, &label_draw_dsc, &a);
|
||||
}
|
||||
else {
|
||||
lv_draw_image_dsc_t img_dsc;
|
||||
lv_draw_image_dsc_init(&img_dsc);
|
||||
img_dsc.recolor = dsc->recolor;
|
||||
img_dsc.recolor_opa = dsc->recolor_opa;
|
||||
img_dsc.opa = dsc->opa;
|
||||
img_dsc.src = dsc->src;
|
||||
|
||||
/*Center align*/
|
||||
if(dsc->tiled == false) {
|
||||
lv_area_t area;
|
||||
area.x1 = coords->x1 + lv_area_get_width(coords) / 2 - dsc->img_header.w / 2;
|
||||
area.y1 = coords->y1 + lv_area_get_height(coords) / 2 - dsc->img_header.h / 2;
|
||||
area.x2 = area.x1 + dsc->img_header.w - 1;
|
||||
area.y2 = area.y1 + dsc->img_header.h - 1;
|
||||
|
||||
lv_draw_vglite_img(draw_unit, &img_dsc, &area);
|
||||
}
|
||||
else {
|
||||
lv_area_t area;
|
||||
area.y1 = coords->y1;
|
||||
area.y2 = area.y1 + dsc->img_header.h - 1;
|
||||
|
||||
for(; area.y1 <= coords->y2; area.y1 += dsc->img_header.h, area.y2 += dsc->img_header.h) {
|
||||
|
||||
area.x1 = coords->x1;
|
||||
area.x2 = area.x1 + dsc->img_header.w - 1;
|
||||
for(; area.x1 <= coords->x2; area.x1 += dsc->img_header.w, area.x2 += dsc->img_header.w) {
|
||||
lv_draw_vglite_img(draw_unit, &img_dsc, &area);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
draw_unit->clip_area = clip_area_ori;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_VGLITE*/
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2022, 2023 NXP
|
||||
* Copyright 2022-2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
@@ -42,7 +42,7 @@
|
||||
* Draw rectangle border/outline shape with effects (rounded corners, opacity)
|
||||
*
|
||||
* @param[in] coords Coordinates of the rectangle border/outline (relative to dest buff)
|
||||
* @param[in] clip_area Clipping area with relative coordinates to dest buff
|
||||
* @param[in] clip_area Clip area with relative coordinates to dest buff
|
||||
* @param[in] dsc Description of the rectangle border/outline
|
||||
*
|
||||
*/
|
||||
@@ -72,33 +72,26 @@ void lv_draw_vglite_border(lv_draw_unit_t * draw_unit, const lv_draw_border_dsc_
|
||||
return;
|
||||
|
||||
lv_layer_t * layer = draw_unit->target_layer;
|
||||
lv_area_t rel_coords;
|
||||
lv_area_t inward_coords;
|
||||
int32_t width = dsc->width;
|
||||
|
||||
/* Move border inwards to align with software rendered border */
|
||||
rel_coords.x1 = coords->x1 + ceil(width / 2.0f);
|
||||
rel_coords.x2 = coords->x2 - floor(width / 2.0f);
|
||||
rel_coords.y1 = coords->y1 + ceil(width / 2.0f);
|
||||
rel_coords.y2 = coords->y2 - floor(width / 2.0f);
|
||||
inward_coords.x1 = coords->x1 + ceil(width / 2.0f);
|
||||
inward_coords.x2 = coords->x2 - floor(width / 2.0f);
|
||||
inward_coords.y1 = coords->y1 + ceil(width / 2.0f);
|
||||
inward_coords.y2 = coords->y2 - floor(width / 2.0f);
|
||||
|
||||
/* Move outline outwards to align with software rendered outline */
|
||||
//int32_t outline_pad = dsc->outline_pad - 1;
|
||||
//rel_coords.x1 = coords->x1 - outline_pad - floor(dsc->outline_width / 2.0f);
|
||||
//rel_coords.x2 = coords->x2 + outline_pad + ceil(dsc->outline_width / 2.0f);
|
||||
//rel_coords.y1 = coords->y1 - outline_pad - floor(dsc->outline_width / 2.0f);
|
||||
//rel_coords.y2 = coords->y2 + outline_pad + ceil(dsc->outline_width / 2.0f);
|
||||
lv_area_move(&inward_coords, -layer->buf_area.x1, -layer->buf_area.y1);
|
||||
|
||||
lv_area_move(&rel_coords, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
|
||||
|
||||
lv_area_t rel_clip_area;
|
||||
lv_area_copy(&rel_clip_area, draw_unit->clip_area);
|
||||
lv_area_move(&rel_clip_area, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
|
||||
lv_area_t clip_area;
|
||||
lv_area_copy(&clip_area, draw_unit->clip_area);
|
||||
lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
|
||||
|
||||
lv_area_t clipped_coords;
|
||||
if(!_lv_area_intersect(&clipped_coords, &rel_coords, &rel_clip_area))
|
||||
if(!_lv_area_intersect(&clipped_coords, &inward_coords, &clip_area))
|
||||
return; /*Fully clipped, nothing to do*/
|
||||
|
||||
_vglite_draw_border(&rel_coords, &rel_clip_area, dsc);
|
||||
_vglite_draw_border(&inward_coords, &clip_area, dsc);
|
||||
}
|
||||
|
||||
/**********************
|
||||
@@ -108,7 +101,6 @@ void lv_draw_vglite_border(lv_draw_unit_t * draw_unit, const lv_draw_border_dsc_
|
||||
static void _vglite_draw_border(const lv_area_t * coords, const lv_area_t * clip_area,
|
||||
const lv_draw_border_dsc_t * dsc)
|
||||
{
|
||||
vg_lite_error_t err = VG_LITE_SUCCESS;
|
||||
int32_t radius = dsc->radius;
|
||||
vg_lite_buffer_t * vgbuf = vglite_get_dest_buf();
|
||||
|
||||
@@ -119,13 +111,6 @@ static void _vglite_draw_border(const lv_area_t * coords, const lv_area_t * clip
|
||||
if(radius > border_half)
|
||||
radius = radius - border_half;
|
||||
|
||||
//else {
|
||||
// /* Draw outline - always has radius, leave the same radius in the circle case */
|
||||
// int32_t outline_half = (int32_t)ceil(dsc->outline_width / 2.0f);
|
||||
// if(radius < (int32_t)LV_RADIUS_CIRCLE - outline_half)
|
||||
// radius = radius + outline_half;
|
||||
//}
|
||||
|
||||
vg_lite_cap_style_t cap_style = (radius) ? VG_LITE_CAP_ROUND : VG_LITE_CAP_BUTT;
|
||||
vg_lite_join_style_t join_style = (radius) ? VG_LITE_JOIN_ROUND : VG_LITE_JOIN_MITER;
|
||||
|
||||
@@ -136,10 +121,9 @@ static void _vglite_draw_border(const lv_area_t * coords, const lv_area_t * clip
|
||||
vg_lite_quality_t path_quality = radius > 0 ? VG_LITE_HIGH : VG_LITE_MEDIUM;
|
||||
|
||||
vg_lite_path_t path;
|
||||
err = vg_lite_init_path(&path, VG_LITE_S32, path_quality, path_data_size, path_data,
|
||||
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
|
||||
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Init path failed.");
|
||||
VGLITE_CHECK_ERROR(vg_lite_init_path(&path, VG_LITE_S32, path_quality, path_data_size, path_data,
|
||||
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
|
||||
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f));
|
||||
|
||||
lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->opa);
|
||||
vg_lite_color_t vgcol = vglite_get_color(col32, false);
|
||||
@@ -150,26 +134,17 @@ static void _vglite_draw_border(const lv_area_t * coords, const lv_area_t * clip
|
||||
int32_t line_width = dsc->width;
|
||||
|
||||
/*** Draw border ***/
|
||||
err = vg_lite_set_draw_path_type(&path, VG_LITE_DRAW_STROKE_PATH);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Set draw path type failed.");
|
||||
VGLITE_CHECK_ERROR(vg_lite_set_draw_path_type(&path, VG_LITE_DRAW_STROKE_PATH));
|
||||
|
||||
err = vg_lite_set_stroke(&path, cap_style, join_style, line_width, 8, NULL, 0, 0, vgcol);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Set stroke failed.");
|
||||
VGLITE_CHECK_ERROR(vg_lite_set_stroke(&path, cap_style, join_style, line_width, 8, NULL, 0, 0, vgcol));
|
||||
|
||||
err = vg_lite_update_stroke(&path);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Update stroke failed.");
|
||||
VGLITE_CHECK_ERROR(vg_lite_update_stroke(&path));
|
||||
|
||||
vglite_set_scissor(clip_area);
|
||||
|
||||
err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Draw border failed.");
|
||||
VGLITE_CHECK_ERROR(vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol));
|
||||
|
||||
vglite_run();
|
||||
|
||||
vglite_disable_scissor();
|
||||
|
||||
err = vg_lite_clear_path(&path);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Clear path failed.");
|
||||
VGLITE_CHECK_ERROR(vg_lite_clear_path(&path));
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_VGLITE*/
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2020-2023 NXP
|
||||
* Copyright 2020-2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
@@ -47,7 +47,7 @@ static void _vglite_fill(const lv_area_t * dest_area, const lv_draw_fill_dsc_t *
|
||||
* Draw rectangle background with effects (rounded corners, gradient)
|
||||
*
|
||||
* @param[in] coords Coordinates of the rectangle background (relative to dest buff)
|
||||
* @param[in] clip_area Clipping area with relative coordinates to dest buff
|
||||
* @param[in] clip_area Clip area with relative coordinates to dest buff
|
||||
* @param[in] dsc Description of the rectangle background
|
||||
*
|
||||
*/
|
||||
@@ -73,24 +73,16 @@ void lv_draw_vglite_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t *
|
||||
return;
|
||||
|
||||
lv_layer_t * layer = draw_unit->target_layer;
|
||||
lv_area_t rel_coords;
|
||||
lv_area_copy(&rel_coords, coords);
|
||||
lv_area_t relative_coords;
|
||||
lv_area_copy(&relative_coords, coords);
|
||||
lv_area_move(&relative_coords, -layer->buf_area.x1, -layer->buf_area.y1);
|
||||
|
||||
/*If the border fully covers make the bg area 1px smaller to avoid artifacts on the corners*/
|
||||
//if(dsc->border_width > 1 && dsc->border_opa >= (lv_opa_t)LV_OPA_MAX && dsc->radius != 0) {
|
||||
// rel_coords.x1 += (dsc->border_side & LV_BORDER_SIDE_LEFT) ? 1 : 0;
|
||||
// rel_coords.y1 += (dsc->border_side & LV_BORDER_SIDE_TOP) ? 1 : 0;
|
||||
// rel_coords.x2 -= (dsc->border_side & LV_BORDER_SIDE_RIGHT) ? 1 : 0;
|
||||
// rel_coords.y2 -= (dsc->border_side & LV_BORDER_SIDE_BOTTOM) ? 1 : 0;
|
||||
//}
|
||||
lv_area_move(&rel_coords, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
|
||||
|
||||
lv_area_t rel_clip_area;
|
||||
lv_area_copy(&rel_clip_area, draw_unit->clip_area);
|
||||
lv_area_move(&rel_clip_area, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
|
||||
lv_area_t clip_area;
|
||||
lv_area_copy(&clip_area, draw_unit->clip_area);
|
||||
lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
|
||||
|
||||
lv_area_t clipped_coords;
|
||||
if(!_lv_area_intersect(&clipped_coords, &rel_coords, &rel_clip_area))
|
||||
if(!_lv_area_intersect(&clipped_coords, &relative_coords, &clip_area))
|
||||
return; /*Fully clipped, nothing to do*/
|
||||
|
||||
/*
|
||||
@@ -99,7 +91,7 @@ void lv_draw_vglite_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t *
|
||||
if((dsc->radius == 0) && (dsc->grad.dir == (lv_grad_dir_t)LV_GRAD_DIR_NONE))
|
||||
_vglite_fill(&clipped_coords, dsc);
|
||||
else
|
||||
_vglite_draw_rect(&rel_coords, &rel_clip_area, dsc);
|
||||
_vglite_draw_rect(&relative_coords, &clip_area, dsc);
|
||||
}
|
||||
|
||||
/**********************
|
||||
@@ -108,7 +100,6 @@ void lv_draw_vglite_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t *
|
||||
|
||||
static void _vglite_fill(const lv_area_t * dest_area, const lv_draw_fill_dsc_t * dsc)
|
||||
{
|
||||
vg_lite_error_t err = VG_LITE_SUCCESS;
|
||||
vg_lite_buffer_t * vgbuf = vglite_get_dest_buf();
|
||||
|
||||
lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->opa);
|
||||
@@ -122,8 +113,7 @@ static void _vglite_fill(const lv_area_t * dest_area, const lv_draw_fill_dsc_t *
|
||||
.height = lv_area_get_height(dest_area)
|
||||
};
|
||||
|
||||
err = vg_lite_clear(vgbuf, &rect, vgcol);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Clear failed.");
|
||||
VGLITE_CHECK_ERROR(vg_lite_clear(vgbuf, &rect, vgcol));
|
||||
|
||||
vglite_run();
|
||||
}
|
||||
@@ -139,32 +129,29 @@ static void _vglite_fill(const lv_area_t * dest_area, const lv_draw_fill_dsc_t *
|
||||
VLC_OP_END
|
||||
};
|
||||
|
||||
err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_MEDIUM, sizeof(path_data), path_data,
|
||||
(vg_lite_float_t) dest_area->x1, (vg_lite_float_t) dest_area->y1,
|
||||
((vg_lite_float_t) dest_area->x2) + 1.0f, ((vg_lite_float_t) dest_area->y2) + 1.0f);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Init path failed.");
|
||||
VGLITE_CHECK_ERROR(vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_MEDIUM, sizeof(path_data), path_data,
|
||||
(vg_lite_float_t) dest_area->x1, (vg_lite_float_t) dest_area->y1,
|
||||
((vg_lite_float_t) dest_area->x2) + 1.0f, ((vg_lite_float_t) dest_area->y2) + 1.0f));
|
||||
|
||||
vg_lite_matrix_t matrix;
|
||||
vg_lite_identity(&matrix);
|
||||
|
||||
/*Draw rectangle*/
|
||||
err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Draw rectangle failed.");
|
||||
VGLITE_CHECK_ERROR(vg_lite_draw(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol));
|
||||
|
||||
vglite_run();
|
||||
|
||||
err = vg_lite_clear_path(&path);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Clear path failed.");
|
||||
VGLITE_CHECK_ERROR(vg_lite_clear_path(&path));
|
||||
}
|
||||
}
|
||||
|
||||
static void _vglite_draw_rect(const lv_area_t * coords, const lv_area_t * clip_area,
|
||||
const lv_draw_fill_dsc_t * dsc)
|
||||
{
|
||||
vg_lite_error_t err = VG_LITE_SUCCESS;
|
||||
int32_t width = lv_area_get_width(coords);
|
||||
int32_t height = lv_area_get_height(coords);
|
||||
int32_t radius = dsc->radius;
|
||||
lv_opa_t opa = dsc->opa;
|
||||
vg_lite_buffer_t * vgbuf = vglite_get_dest_buf();
|
||||
|
||||
if(dsc->radius < 0)
|
||||
@@ -177,20 +164,17 @@ static void _vglite_draw_rect(const lv_area_t * coords, const lv_area_t * clip_a
|
||||
vg_lite_quality_t path_quality = dsc->radius > 0 ? VG_LITE_HIGH : VG_LITE_MEDIUM;
|
||||
|
||||
vg_lite_path_t path;
|
||||
err = vg_lite_init_path(&path, VG_LITE_S32, path_quality, path_data_size, path_data,
|
||||
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
|
||||
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Init path failed.");
|
||||
VGLITE_CHECK_ERROR(vg_lite_init_path(&path, VG_LITE_S32, path_quality, path_data_size, path_data,
|
||||
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
|
||||
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f));
|
||||
|
||||
vg_lite_matrix_t matrix;
|
||||
vg_lite_identity(&matrix);
|
||||
|
||||
/*** Init Color ***/
|
||||
lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->opa);
|
||||
lv_color32_t col32 = lv_color_to_32(dsc->color, opa);
|
||||
vg_lite_color_t vgcol = vglite_get_color(col32, false);
|
||||
|
||||
vglite_set_scissor(clip_area);
|
||||
|
||||
vg_lite_linear_gradient_t gradient;
|
||||
bool has_gradient = (dsc->grad.dir != (lv_grad_dir_t)LV_GRAD_DIR_NONE);
|
||||
|
||||
@@ -198,29 +182,30 @@ static void _vglite_draw_rect(const lv_area_t * coords, const lv_area_t * clip_a
|
||||
if(has_gradient) {
|
||||
vg_lite_matrix_t * grad_matrix;
|
||||
|
||||
uint32_t colors[2];
|
||||
uint32_t stops[2];
|
||||
lv_color32_t col32[2];
|
||||
vg_lite_uint32_t colors[LV_GRADIENT_MAX_STOPS];
|
||||
vg_lite_uint32_t stops[LV_GRADIENT_MAX_STOPS];
|
||||
lv_color32_t col32[LV_GRADIENT_MAX_STOPS];
|
||||
|
||||
/* Gradient setup */
|
||||
uint8_t cnt = LV_MAX(dsc->grad.stops_count, 2);
|
||||
vg_lite_uint32_t cnt = LV_MAX(dsc->grad.stops_count, LV_GRADIENT_MAX_STOPS);
|
||||
lv_opa_t opa;
|
||||
|
||||
for(uint8_t i = 0; i < cnt; i++) {
|
||||
stops[i] = dsc->grad.stops[i].frac;
|
||||
|
||||
col32[i] = lv_color_to_32(dsc->grad.stops[i].color, dsc->opa);
|
||||
opa = LV_OPA_MIX2(dsc->grad.stops[i].opa, dsc->opa);
|
||||
|
||||
col32[i] = lv_color_to_32(dsc->grad.stops[i].color, opa);
|
||||
colors[i] = vglite_get_color(col32[i], true);
|
||||
}
|
||||
|
||||
lv_memzero(&gradient, sizeof(vg_lite_linear_gradient_t));
|
||||
|
||||
err = vg_lite_init_grad(&gradient);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Init gradient failed");
|
||||
VGLITE_CHECK_ERROR(vg_lite_init_grad(&gradient));
|
||||
|
||||
err = vg_lite_set_grad(&gradient, cnt, colors, stops);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Set gradient failed.");
|
||||
VGLITE_CHECK_ERROR(vg_lite_set_grad(&gradient, cnt, colors, stops));
|
||||
|
||||
err = vg_lite_update_grad(&gradient);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Update gradient failed.");
|
||||
VGLITE_CHECK_ERROR(vg_lite_update_grad(&gradient));
|
||||
|
||||
grad_matrix = vg_lite_get_grad_matrix(&gradient);
|
||||
vg_lite_identity(grad_matrix);
|
||||
@@ -234,25 +219,19 @@ static void _vglite_draw_rect(const lv_area_t * coords, const lv_area_t * clip_a
|
||||
vg_lite_scale((float)width / 256.0f, 1.0f, grad_matrix);
|
||||
}
|
||||
|
||||
err = vg_lite_draw_gradient(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, &gradient, VG_LITE_BLEND_SRC_OVER);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Draw gradient failed.");
|
||||
VGLITE_CHECK_ERROR(vg_lite_draw_gradient(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, &gradient,
|
||||
VG_LITE_BLEND_SRC_OVER));
|
||||
}
|
||||
else {
|
||||
err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Draw rectangle failed.");
|
||||
VGLITE_CHECK_ERROR(vg_lite_draw(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol));
|
||||
}
|
||||
|
||||
vglite_run();
|
||||
|
||||
vglite_disable_scissor();
|
||||
VGLITE_CHECK_ERROR(vg_lite_clear_path(&path));
|
||||
|
||||
err = vg_lite_clear_path(&path);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Clear path failed.");
|
||||
|
||||
if(has_gradient) {
|
||||
err = vg_lite_clear_grad(&gradient);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Clear gradient failed.");
|
||||
}
|
||||
if(has_gradient)
|
||||
VGLITE_CHECK_ERROR(vg_lite_clear_grad(&gradient));
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_VGLITE*/
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2020-2023 NXP
|
||||
* Copyright 2020-2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
@@ -26,7 +26,7 @@
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#if VGLITE_BLIT_SPLIT_ENABLED
|
||||
#if LV_USE_VGLITE_BLIT_SPLIT
|
||||
/**
|
||||
* BLIT split threshold - BLITs with width or height higher than this value will
|
||||
* be done in multiple steps. Value must be multiple of stride alignment in px.
|
||||
@@ -47,7 +47,7 @@
|
||||
do { \
|
||||
} while (0)
|
||||
#endif
|
||||
#endif
|
||||
#endif /*LV_USE_VGLITE_BLIT_SPLIT*/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
@@ -63,12 +63,13 @@
|
||||
*
|
||||
* @param[in] dest_area Destination area with relative coordinates to dest buffer
|
||||
* @param[in] src_area Source area with relative coordinates to src buffer
|
||||
* @param[in] opa Opacity
|
||||
* @param[in] dsc Image descriptor
|
||||
*
|
||||
*/
|
||||
static void _vglite_blit_single(const lv_area_t * dest_area, const lv_area_t * src_area, lv_opa_t opa);
|
||||
static void _vglite_blit_single(const lv_area_t * dest_area, const lv_area_t * src_area,
|
||||
const lv_draw_image_dsc_t * dsc);
|
||||
|
||||
#if VGLITE_BLIT_SPLIT_ENABLED
|
||||
#if LV_USE_VGLITE_BLIT_SPLIT
|
||||
/**
|
||||
* Move buffer pointer as close as possible to area, but with respect to alignment requirements.
|
||||
*
|
||||
@@ -91,26 +92,25 @@ static void _move_buf_close_to_area(void ** buf, lv_area_t * area, uint32_t stri
|
||||
* @param[in] src_area Source area with relative coordinates to src buffer
|
||||
* @param[in] src_stride Stride of source buffer in bytes
|
||||
* @param[in] src_cf Color format of source buffer
|
||||
* @param[in] opa Opacity
|
||||
* @param[in] dsc Image descriptor
|
||||
*
|
||||
*/
|
||||
static void _vglite_blit_split(void * dest_buf, lv_area_t * dest_area, uint32_t dest_stride, lv_color_format_t dest_cf,
|
||||
const void * src_buf, lv_area_t * src_area, uint32_t src_stride, lv_color_format_t src_cf,
|
||||
lv_opa_t opa);
|
||||
const lv_draw_image_dsc_t * dsc);
|
||||
#else
|
||||
/**
|
||||
* BLock Image Transfer - copy rectangular image from src_buf to dst_buf with transformation.
|
||||
* By default, image is copied directly, with optional opacity.
|
||||
*
|
||||
* @param[in] dest_area Area with relative coordinates to dest buffer
|
||||
* @param[in] clip_area Clip area with relative coordinates to dest buffer
|
||||
* @param[in] src_area Source area with relative coordinates to src buffer
|
||||
* @param[in] dsc Image descriptor
|
||||
*
|
||||
*/
|
||||
static void _vglite_blit_transform(const lv_area_t * dest_area, const lv_area_t * clip_area,
|
||||
const lv_area_t * src_area, const lv_draw_image_dsc_t * dsc);
|
||||
#endif /*VGLITE_BLIT_SPLIT_ENABLED*/
|
||||
static void _vglite_blit_transform(const lv_area_t * dest_area, const lv_area_t * src_area,
|
||||
const lv_draw_image_dsc_t * dsc);
|
||||
#endif /*LV_USE_VGLITE_BLIT_SPLIT*/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
@@ -133,28 +133,28 @@ void lv_draw_vglite_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t *
|
||||
lv_layer_t * layer = draw_unit->target_layer;
|
||||
const lv_image_dsc_t * img_dsc = dsc->src;
|
||||
|
||||
lv_area_t rel_coords;
|
||||
lv_area_copy(&rel_coords, coords);
|
||||
lv_area_move(&rel_coords, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
|
||||
lv_area_t relative_coords;
|
||||
lv_area_copy(&relative_coords, coords);
|
||||
lv_area_move(&relative_coords, -layer->buf_area.x1, -layer->buf_area.y1);
|
||||
|
||||
lv_area_t rel_clip_area;
|
||||
lv_area_copy(&rel_clip_area, draw_unit->clip_area);
|
||||
lv_area_move(&rel_clip_area, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
|
||||
lv_area_t clip_area;
|
||||
lv_area_copy(&clip_area, draw_unit->clip_area);
|
||||
lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
|
||||
|
||||
lv_area_t blend_area;
|
||||
bool has_transform = dsc->rotation != 0 || dsc->zoom != LV_SCALE_NONE;
|
||||
bool has_transform = (dsc->rotation != 0 || dsc->scale_x != LV_SCALE_NONE || dsc->scale_y != LV_SCALE_NONE);
|
||||
if(has_transform)
|
||||
lv_area_copy(&blend_area, &rel_coords);
|
||||
else if(!_lv_area_intersect(&blend_area, &rel_coords, &rel_clip_area))
|
||||
lv_area_copy(&blend_area, &relative_coords);
|
||||
else if(!_lv_area_intersect(&blend_area, &relative_coords, &clip_area))
|
||||
return; /*Fully clipped, nothing to do*/
|
||||
|
||||
const void * src_buf = img_dsc->data;
|
||||
|
||||
lv_area_t src_area;
|
||||
src_area.x1 = blend_area.x1 - (coords->x1 - layer->draw_buf_ofs.x);
|
||||
src_area.y1 = blend_area.y1 - (coords->y1 - layer->draw_buf_ofs.y);
|
||||
src_area.x2 = src_area.x1 + lv_area_get_width(coords) - 1;
|
||||
src_area.y2 = src_area.y1 + lv_area_get_height(coords) - 1;
|
||||
src_area.x1 = blend_area.x1 - (coords->x1 - layer->buf_area.x1);
|
||||
src_area.y1 = blend_area.y1 - (coords->y1 - layer->buf_area.y1);
|
||||
src_area.x2 = img_dsc->header.w - 1;
|
||||
src_area.y2 = img_dsc->header.h - 1;
|
||||
|
||||
lv_color_format_t src_cf = img_dsc->header.cf;
|
||||
uint32_t src_stride = img_dsc->header.stride;
|
||||
@@ -162,86 +162,82 @@ void lv_draw_vglite_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t *
|
||||
/* Set src_vgbuf structure. */
|
||||
vglite_set_src_buf(src_buf, lv_area_get_width(&src_area), lv_area_get_height(&src_area), src_stride, src_cf);
|
||||
|
||||
#if VGLITE_BLIT_SPLIT_ENABLED
|
||||
void * dest_buf = lv_draw_buf_get_buf(&layer->draw_buf);
|
||||
uint32_t dest_stride = lv_draw_buf_get_stride(&layer->draw_buf);
|
||||
lv_color_format_t dest_cf = layer->draw_buf.color_format;
|
||||
#if LV_USE_VGLITE_BLIT_SPLIT
|
||||
void * dest_buf = layer->buf;
|
||||
uint32_t dest_stride = layer->buf_stride;
|
||||
lv_color_format_t dest_cf = layer->color_format;
|
||||
|
||||
if(!has_transform)
|
||||
_vglite_blit_split(dest_buf, &blend_area, dest_stride, dest_cf,
|
||||
src_buf, &src_area, src_stride, src_cf, dsc->opa);
|
||||
src_buf, &src_area, src_stride, src_cf, dsc);
|
||||
#else
|
||||
if(has_transform)
|
||||
_vglite_blit_transform(&blend_area, &rel_clip_area, &src_area, dsc);
|
||||
_vglite_blit_transform(&blend_area, &src_area, dsc);
|
||||
else
|
||||
_vglite_blit_single(&blend_area, &src_area, dsc->opa);
|
||||
#endif
|
||||
_vglite_blit_single(&blend_area, &src_area, dsc);
|
||||
#endif /*LV_USE_VGLITE_BLIT_SPLIT*/
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
static void _vglite_blit(const lv_area_t * src_area, lv_opa_t opa)
|
||||
static void _vglite_blit(const lv_area_t * src_area, const lv_draw_image_dsc_t * dsc)
|
||||
{
|
||||
vg_lite_error_t err = VG_LITE_SUCCESS;
|
||||
vg_lite_buffer_t * dst_vgbuf = vglite_get_dest_buf();
|
||||
vg_lite_buffer_t * src_vgbuf = vglite_get_src_buf();
|
||||
|
||||
uint32_t rect[] = {
|
||||
(uint32_t)src_area->x1, /* start x */
|
||||
(uint32_t)src_area->y1, /* start y */
|
||||
(uint32_t)lv_area_get_width(src_area), /* width */
|
||||
(uint32_t)lv_area_get_height(src_area) /* height */
|
||||
vg_lite_rectangle_t rect = {
|
||||
.x = (vg_lite_int32_t)src_area->x1,
|
||||
.y = (vg_lite_int32_t)src_area->y1,
|
||||
.width = (vg_lite_int32_t)lv_area_get_width(src_area),
|
||||
.height = (vg_lite_int32_t)lv_area_get_height(src_area)
|
||||
};
|
||||
|
||||
uint32_t color;
|
||||
vg_lite_blend_t blend;
|
||||
if(opa >= (lv_opa_t)LV_OPA_MAX) {
|
||||
color = 0xFFFFFFFFU;
|
||||
blend = VG_LITE_BLEND_SRC_OVER;
|
||||
src_vgbuf->transparency_mode = VG_LITE_IMAGE_TRANSPARENT;
|
||||
src_vgbuf->image_mode = VG_LITE_MULTIPLY_IMAGE_MODE;
|
||||
src_vgbuf->transparency_mode = VG_LITE_IMAGE_TRANSPARENT;
|
||||
|
||||
lv_color_t color;
|
||||
lv_opa_t opa;
|
||||
|
||||
bool has_recolor = (dsc->recolor_opa > LV_OPA_MIN);
|
||||
if(has_recolor) {
|
||||
color = dsc->recolor;
|
||||
opa = LV_OPA_MIX2(dsc->recolor_opa, dsc->opa);
|
||||
}
|
||||
else {
|
||||
if(vg_lite_query_feature(gcFEATURE_BIT_VG_PE_PREMULTIPLY)) {
|
||||
color = (opa << 24) | 0x00FFFFFFU;
|
||||
}
|
||||
else {
|
||||
color = (opa << 24) | (opa << 16) | (opa << 8) | opa;
|
||||
}
|
||||
blend = VG_LITE_BLEND_SRC_OVER;
|
||||
src_vgbuf->image_mode = VG_LITE_MULTIPLY_IMAGE_MODE;
|
||||
src_vgbuf->transparency_mode = VG_LITE_IMAGE_TRANSPARENT;
|
||||
color.red = 0xFF;
|
||||
color.green = 0xFF;
|
||||
color.blue = 0xFF;
|
||||
opa = dsc->opa;
|
||||
}
|
||||
|
||||
vg_lite_matrix_t * vgmatrix = vglite_get_matrix();
|
||||
lv_color32_t col32 = lv_color_to_32(color, opa);
|
||||
vg_lite_color_t vgcol = vglite_get_color(col32, false);
|
||||
|
||||
err = vg_lite_blit_rect(dst_vgbuf, src_vgbuf, rect, vgmatrix, blend, color, VG_LITE_FILTER_POINT);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Blit rectangle failed.");
|
||||
vg_lite_matrix_t * vgmatrix = vglite_get_matrix();
|
||||
vg_lite_blend_t vgblend = vglite_get_blend_mode(dsc->blend_mode);
|
||||
|
||||
VGLITE_CHECK_ERROR(vg_lite_blit_rect(dst_vgbuf, src_vgbuf, &rect, vgmatrix, vgblend, vgcol, VG_LITE_FILTER_POINT));
|
||||
|
||||
vglite_run();
|
||||
}
|
||||
|
||||
static void _vglite_blit_single(const lv_area_t * dest_area, const lv_area_t * src_area, lv_opa_t opa)
|
||||
static void _vglite_blit_single(const lv_area_t * dest_area, const lv_area_t * src_area,
|
||||
const lv_draw_image_dsc_t * dsc)
|
||||
{
|
||||
/* Set scissor. */
|
||||
vglite_set_scissor(dest_area);
|
||||
|
||||
/* Set vgmatrix. */
|
||||
vglite_set_translation_matrix(dest_area);
|
||||
|
||||
/* Start blit. */
|
||||
_vglite_blit(src_area, opa);
|
||||
|
||||
/* Disable scissor. */
|
||||
vglite_disable_scissor();
|
||||
_vglite_blit(src_area, dsc);
|
||||
}
|
||||
|
||||
#if VGLITE_BLIT_SPLIT_ENABLED
|
||||
#if LV_USE_VGLITE_BLIT_SPLIT
|
||||
static void _move_buf_close_to_area(void ** buf, lv_area_t * area, uint32_t stride, lv_color_format_t cf)
|
||||
{
|
||||
uint8_t ** buf_u8 = (uint8_t **)buf;
|
||||
uint8_t align_bytes = vglite_get_alignment(cf);
|
||||
uint8_t bits_per_pixel = vglite_get_px_size(cf);
|
||||
uint8_t bits_per_pixel = lv_color_format_get_bpp(cf);
|
||||
|
||||
uint16_t align_pixels = align_bytes * 8 / bits_per_pixel;
|
||||
|
||||
@@ -264,7 +260,7 @@ static void _move_buf_close_to_area(void ** buf, lv_area_t * area, uint32_t stri
|
||||
|
||||
static void _vglite_blit_split(void * dest_buf, lv_area_t * dest_area, uint32_t dest_stride, lv_color_format_t dest_cf,
|
||||
const void * src_buf, lv_area_t * src_area, uint32_t src_stride, lv_color_format_t src_cf,
|
||||
lv_opa_t opa)
|
||||
const lv_draw_image_dsc_t * dsc)
|
||||
{
|
||||
VGLITE_TRACE("Blit "
|
||||
"Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | "
|
||||
@@ -288,7 +284,7 @@ static void _vglite_blit_split(void * dest_buf, lv_area_t * dest_area, uint32_t
|
||||
vglite_set_dest_buf_ptr(dest_buf);
|
||||
vglite_set_src_buf_ptr(src_buf);
|
||||
|
||||
_vglite_blit_single(dest_area, src_area, opa);
|
||||
_vglite_blit_single(dest_area, src_area, dsc);
|
||||
|
||||
VGLITE_TRACE("Single "
|
||||
"Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | "
|
||||
@@ -355,8 +351,8 @@ static void _vglite_blit_split(void * dest_buf, lv_area_t * dest_area, uint32_t
|
||||
tile_dest_area.x1 = shift_dest_x;
|
||||
if(x > 0) {
|
||||
/* Advance start pointer for every tile, except the first raw (x = 0) */
|
||||
tile_src_buf += VGLITE_BLIT_SPLIT_THR * vglite_get_px_size(src_cf) / 8;
|
||||
tile_dest_buf += VGLITE_BLIT_SPLIT_THR * vglite_get_px_size(dest_cf) / 8;
|
||||
tile_src_buf += VGLITE_BLIT_SPLIT_THR * lv_color_format_get_bpp(src_cf) / 8;
|
||||
tile_dest_buf += VGLITE_BLIT_SPLIT_THR * lv_color_format_get_bpp(dest_cf) / 8;
|
||||
}
|
||||
|
||||
/* Calculate x2 coordinates */
|
||||
@@ -375,7 +371,7 @@ static void _vglite_blit_split(void * dest_buf, lv_area_t * dest_area, uint32_t
|
||||
vglite_set_dest_buf_ptr(tile_dest_buf);
|
||||
vglite_set_src_buf_ptr(tile_src_buf);
|
||||
|
||||
_vglite_blit_single(&tile_dest_area, &tile_src_area, opa);
|
||||
_vglite_blit_single(&tile_dest_area, &tile_src_area, dsc);
|
||||
|
||||
VGLITE_TRACE("Tile [%d, %d] "
|
||||
"Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | "
|
||||
@@ -391,21 +387,15 @@ static void _vglite_blit_split(void * dest_buf, lv_area_t * dest_area, uint32_t
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void _vglite_blit_transform(const lv_area_t * dest_area, const lv_area_t * clip_area,
|
||||
const lv_area_t * src_area, const lv_draw_image_dsc_t * dsc)
|
||||
static void _vglite_blit_transform(const lv_area_t * dest_area, const lv_area_t * src_area,
|
||||
const lv_draw_image_dsc_t * dsc)
|
||||
{
|
||||
/* Set scissor. */
|
||||
vglite_set_scissor(clip_area);
|
||||
|
||||
/* Set vgmatrix. */
|
||||
vglite_set_transformation_matrix(dest_area, dsc);
|
||||
|
||||
/* Start blit. */
|
||||
_vglite_blit(src_area, dsc->opa);
|
||||
|
||||
/* Disable scissor. */
|
||||
vglite_disable_scissor();
|
||||
_vglite_blit(src_area, dsc);
|
||||
}
|
||||
#endif /*VGLITE_BLIT_SPLIT_ENABLED*/
|
||||
#endif /*LV_USE_VGLITE_BLIT_SPLIT*/
|
||||
|
||||
#endif /*LV_USE_DRAW_VGLITE*/
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2023 NXP
|
||||
* Copyright 2023-2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
@@ -40,17 +40,12 @@ static void _draw_vglite_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t
|
||||
/**
|
||||
* Draw letter (character bitmap blend) with optional color and opacity
|
||||
*
|
||||
* @param[in] dest_area Area with relative coordinates of destination buffer
|
||||
* @param[in] mask_buf Mask buffer
|
||||
* @param[in] mask_area Mask area with relative coordinates of source buffer
|
||||
* @param[in] mask_stride Stride of mask buffer in bytes
|
||||
* @param[in] color Color
|
||||
* @param[in] opa Opacity
|
||||
*
|
||||
*/
|
||||
static void _vglite_draw_letter(const lv_area_t * dest_area,
|
||||
const void * mask_buf, const lv_area_t * mask_area, uint32_t mask_stride,
|
||||
lv_color_t color, lv_opa_t opa);
|
||||
static void _vglite_draw_letter(const lv_area_t * mask_area, lv_color_t color, lv_opa_t opa);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
@@ -105,24 +100,20 @@ static void _draw_vglite_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t
|
||||
lv_area_t blend_area;
|
||||
if(!_lv_area_intersect(&blend_area, glyph_draw_dsc->letter_coords, draw_unit->clip_area))
|
||||
return;
|
||||
lv_area_move(&blend_area, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
|
||||
lv_area_move(&blend_area, -layer->buf_area.x1, -layer->buf_area.y1);
|
||||
|
||||
const lv_draw_buf_t * draw_buf = glyph_draw_dsc->glyph_data;
|
||||
const uint8_t * mask_buf = draw_buf->data;
|
||||
lv_area_t mask_area;
|
||||
lv_area_copy(&mask_area, glyph_draw_dsc->letter_coords);
|
||||
lv_area_move(&mask_area, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
|
||||
const void * mask_buf = draw_buf->data;
|
||||
|
||||
/**
|
||||
* @todo check if we can use draw_buf->header.stride directly.
|
||||
*/
|
||||
uint32_t mask_stride = lv_draw_buf_width_to_stride(
|
||||
lv_area_get_width(glyph_draw_dsc->letter_coords),
|
||||
LV_COLOR_FORMAT_A8);
|
||||
if(mask_buf) {
|
||||
mask_buf += mask_stride * (blend_area.y1 - glyph_draw_dsc->letter_coords->y1) +
|
||||
(blend_area.x1 - glyph_draw_dsc->letter_coords->x1);
|
||||
}
|
||||
uint32_t mask_width = lv_area_get_width(glyph_draw_dsc->letter_coords);
|
||||
uint32_t mask_height = lv_area_get_height(glyph_draw_dsc->letter_coords);
|
||||
uint32_t mask_stride = draw_buf->header.stride;
|
||||
|
||||
lv_area_t mask_area;
|
||||
mask_area.x1 = blend_area.x1 - (glyph_draw_dsc->letter_coords->x1 - layer->buf_area.x1);
|
||||
mask_area.y1 = blend_area.y1 - (glyph_draw_dsc->letter_coords->y1 - layer->buf_area.y1);
|
||||
mask_area.x2 = mask_width - 1;
|
||||
mask_area.y2 = mask_height - 1;
|
||||
|
||||
if(!vglite_buf_aligned(mask_buf, mask_stride, LV_COLOR_FORMAT_A8)) {
|
||||
/* Draw a placeholder rectangle*/
|
||||
@@ -134,9 +125,15 @@ static void _draw_vglite_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t
|
||||
lv_draw_vglite_border(draw_unit, &border_draw_dsc, glyph_draw_dsc->bg_coords);
|
||||
}
|
||||
else {
|
||||
/* Set src_vgbuf structure. */
|
||||
vglite_set_src_buf(mask_buf, mask_width, mask_height, mask_stride, LV_COLOR_FORMAT_A8);
|
||||
|
||||
_vglite_draw_letter(&blend_area, mask_buf, &mask_area, mask_stride,
|
||||
glyph_draw_dsc->color, glyph_draw_dsc->opa);
|
||||
/* Set vgmatrix. */
|
||||
vglite_set_translation_matrix(&blend_area);
|
||||
|
||||
lv_draw_buf_invalidate_cache((void *)mask_buf, mask_stride, LV_COLOR_FORMAT_A8, &mask_area);
|
||||
|
||||
_vglite_draw_letter(&mask_area, glyph_draw_dsc->color, glyph_draw_dsc->opa);
|
||||
}
|
||||
}
|
||||
else if(glyph_draw_dsc->format == LV_DRAW_LETTER_BITMAP_FORMAT_IMAGE) {
|
||||
@@ -157,46 +154,29 @@ static void _draw_vglite_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t
|
||||
}
|
||||
}
|
||||
|
||||
static void _vglite_draw_letter(const lv_area_t * dest_area,
|
||||
const void * mask_buf, const lv_area_t * mask_area, uint32_t mask_stride,
|
||||
lv_color_t color, lv_opa_t opa)
|
||||
static void _vglite_draw_letter(const lv_area_t * mask_area, lv_color_t color, lv_opa_t opa)
|
||||
{
|
||||
vg_lite_error_t err = VG_LITE_SUCCESS;
|
||||
vg_lite_buffer_t * dst_vgbuf = vglite_get_dest_buf();
|
||||
vg_lite_buffer_t * mask_vgbuf = vglite_get_src_buf();
|
||||
|
||||
vg_lite_buffer_t mask_vgbuf;
|
||||
mask_vgbuf.format = VG_LITE_A8;
|
||||
mask_vgbuf.tiled = VG_LITE_LINEAR;
|
||||
mask_vgbuf.image_mode = VG_LITE_MULTIPLY_IMAGE_MODE;
|
||||
mask_vgbuf.transparency_mode = VG_LITE_IMAGE_TRANSPARENT;
|
||||
mask_vgbuf.width = (int32_t)lv_area_get_width(mask_area);
|
||||
mask_vgbuf.height = (int32_t)lv_area_get_height(mask_area);
|
||||
mask_vgbuf.stride = (int32_t)mask_stride;
|
||||
mask_vgbuf->image_mode = VG_LITE_MULTIPLY_IMAGE_MODE;
|
||||
mask_vgbuf->transparency_mode = VG_LITE_IMAGE_TRANSPARENT;
|
||||
|
||||
lv_memzero(&mask_vgbuf.yuv, sizeof(mask_vgbuf.yuv));
|
||||
|
||||
mask_vgbuf.memory = (void *)mask_buf;
|
||||
mask_vgbuf.address = (uint32_t)mask_vgbuf.memory;
|
||||
mask_vgbuf.handle = NULL;
|
||||
|
||||
uint32_t rect[] = {
|
||||
(uint32_t)0, /* start x */
|
||||
(uint32_t)0, /* start y */
|
||||
(uint32_t)lv_area_get_width(mask_area), /* width */
|
||||
(uint32_t)lv_area_get_height(mask_area) /* height */
|
||||
vg_lite_rectangle_t rect = {
|
||||
.x = (vg_lite_int32_t)mask_area->x1,
|
||||
.y = (vg_lite_int32_t)mask_area->y1,
|
||||
.width = (vg_lite_int32_t)lv_area_get_width(mask_area),
|
||||
.height = (vg_lite_int32_t)lv_area_get_height(mask_area)
|
||||
};
|
||||
|
||||
lv_color32_t col32 = lv_color_to_32(color, opa);
|
||||
vg_lite_color_t vgcol = vglite_get_color(col32, false);
|
||||
|
||||
/* Set vgmatrix. */
|
||||
vglite_set_translation_matrix(dest_area);
|
||||
vg_lite_matrix_t * vgmatrix = vglite_get_matrix();
|
||||
|
||||
/*Blit with font color as paint color*/
|
||||
err = vg_lite_blit_rect(dst_vgbuf, &mask_vgbuf, rect, vgmatrix, VG_LITE_BLEND_SRC_OVER, vgcol,
|
||||
VG_LITE_FILTER_POINT);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Draw letter failed.");
|
||||
VGLITE_CHECK_ERROR(vg_lite_blit_rect(dst_vgbuf, mask_vgbuf, &rect, vgmatrix, VG_LITE_BLEND_SRC_OVER, vgcol,
|
||||
VG_LITE_FILTER_POINT));
|
||||
|
||||
vglite_run();
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2023 NXP
|
||||
* Copyright 2023-2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
@@ -18,6 +18,9 @@
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
|
||||
#include "../../../stdlib/lv_string.h"
|
||||
#if LV_USE_PARALLEL_DRAW_DEBUG
|
||||
#include "../../../core/lv_global.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@@ -35,6 +38,10 @@
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
#if LV_USE_PARALLEL_DRAW_DEBUG
|
||||
#define _draw_info LV_GLOBAL_DEFAULT()->draw_info
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
@@ -50,20 +57,112 @@ void lv_draw_vglite_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t
|
||||
|
||||
/*It can happen that nothing was draw on a layer and therefore its buffer is not allocated.
|
||||
*In this case just return. */
|
||||
if(layer_to_draw->draw_buf.buf == NULL)
|
||||
if(layer_to_draw->buf == NULL)
|
||||
return;
|
||||
|
||||
lv_image_dsc_t img_dsc = { 0 };
|
||||
img_dsc.header.w = layer_to_draw->draw_buf.width;
|
||||
img_dsc.header.h = layer_to_draw->draw_buf.height;
|
||||
img_dsc.header.cf = layer_to_draw->draw_buf.color_format;
|
||||
img_dsc.data = lv_draw_buf_get_buf(&layer_to_draw->draw_buf);
|
||||
uint32_t width = lv_area_get_width(&layer_to_draw->buf_area);
|
||||
uint32_t height = lv_area_get_height(&layer_to_draw->buf_area);
|
||||
const lv_area_t area = {
|
||||
.x1 = 0,
|
||||
.y1 = 0,
|
||||
.x2 = width - 1,
|
||||
.y2 = height - 1
|
||||
};
|
||||
lv_draw_buf_invalidate_cache(layer_to_draw->buf, layer_to_draw->buf_stride, layer_to_draw->color_format, &area);
|
||||
|
||||
lv_image_dsc_t img_dsc = {0};
|
||||
img_dsc.header.w = width;
|
||||
img_dsc.header.h = height;
|
||||
img_dsc.header.cf = layer_to_draw->color_format;
|
||||
img_dsc.header.stride = layer_to_draw->buf_stride;
|
||||
img_dsc.data = layer_to_draw->buf;
|
||||
|
||||
lv_draw_image_dsc_t new_draw_dsc;
|
||||
lv_memcpy(&new_draw_dsc, draw_dsc, sizeof(lv_draw_image_dsc_t));
|
||||
new_draw_dsc.src = &img_dsc;
|
||||
|
||||
lv_draw_vglite_img(draw_unit, &new_draw_dsc, coords);
|
||||
|
||||
#if LV_USE_LAYER_DEBUG || LV_USE_PARALLEL_DRAW_DEBUG
|
||||
lv_area_t area_rot;
|
||||
lv_area_copy(&area_rot, coords);
|
||||
bool has_transform = (draw_dsc->rotation != 0 || draw_dsc->scale_x != LV_SCALE_NONE ||
|
||||
draw_dsc->scale_y != LV_SCALE_NONE);
|
||||
|
||||
if(has_transform) {
|
||||
int32_t w = lv_area_get_width(coords);
|
||||
int32_t h = lv_area_get_height(coords);
|
||||
|
||||
_lv_image_buf_get_transformed_area(&area_rot, w, h, draw_dsc->rotation, draw_dsc->scale_x, draw_dsc->scale_y,
|
||||
&draw_dsc->pivot);
|
||||
|
||||
area_rot.x1 += coords->x1;
|
||||
area_rot.y1 += coords->y1;
|
||||
area_rot.x2 += coords->x1;
|
||||
area_rot.y2 += coords->y1;
|
||||
}
|
||||
lv_area_t draw_area;
|
||||
if(!_lv_area_intersect(&draw_area, &area_rot, draw_unit->clip_area)) return;
|
||||
#endif
|
||||
|
||||
#if LV_USE_LAYER_DEBUG
|
||||
lv_draw_fill_dsc_t fill_dsc;
|
||||
lv_draw_fill_dsc_init(&fill_dsc);
|
||||
fill_dsc.color = lv_color_hex(layer_to_draw->color_format == LV_COLOR_FORMAT_ARGB8888 ? 0xff0000 : 0x00ff00);
|
||||
fill_dsc.opa = LV_OPA_20;
|
||||
lv_draw_sw_fill(draw_unit, &fill_dsc, &area_rot);
|
||||
|
||||
lv_draw_border_dsc_t border_dsc;
|
||||
lv_draw_border_dsc_init(&border_dsc);
|
||||
border_dsc.color = fill_dsc.color;
|
||||
border_dsc.opa = LV_OPA_60;
|
||||
border_dsc.width = 2;
|
||||
lv_draw_sw_border(draw_unit, &border_dsc, &area_rot);
|
||||
|
||||
#endif
|
||||
|
||||
#if LV_USE_PARALLEL_DRAW_DEBUG
|
||||
uint32_t idx = 0;
|
||||
lv_draw_unit_t * draw_unit_tmp = _draw_info.unit_head;
|
||||
while(draw_unit_tmp != draw_unit) {
|
||||
draw_unit_tmp = draw_unit_tmp->next;
|
||||
idx++;
|
||||
}
|
||||
|
||||
lv_draw_fill_dsc_t fill_dsc;
|
||||
lv_draw_rect_dsc_init(&fill_dsc);
|
||||
fill_dsc.color = lv_palette_main(idx % _LV_PALETTE_LAST);
|
||||
fill_dsc.opa = LV_OPA_10;
|
||||
lv_draw_sw_fill(draw_unit, &fill_dsc, &area_rot);
|
||||
|
||||
lv_draw_border_dsc_t border_dsc;
|
||||
lv_draw_border_dsc_init(&border_dsc);
|
||||
border_dsc.color = lv_palette_main(idx % _LV_PALETTE_LAST);
|
||||
border_dsc.opa = LV_OPA_100;
|
||||
border_dsc.width = 2;
|
||||
lv_draw_sw_border(draw_unit, &border_dsc, &area_rot);
|
||||
|
||||
lv_point_t txt_size;
|
||||
lv_text_get_size(&txt_size, "W", LV_FONT_DEFAULT, 0, 0, 100, LV_TEXT_FLAG_NONE);
|
||||
|
||||
lv_area_t txt_area;
|
||||
txt_area.x1 = draw_area.x1;
|
||||
txt_area.x2 = draw_area.x1 + txt_size.x - 1;
|
||||
txt_area.y2 = draw_area.y2;
|
||||
txt_area.y1 = draw_area.y2 - txt_size.y + 1;
|
||||
|
||||
lv_draw_fill_dsc_init(&fill_dsc);
|
||||
fill_dsc.color = lv_color_black();
|
||||
lv_draw_sw_fill(draw_unit, &fill_dsc, &txt_area);
|
||||
|
||||
char buf[8];
|
||||
lv_snprintf(buf, sizeof(buf), "%d", idx);
|
||||
lv_draw_label_dsc_t label_dsc;
|
||||
lv_draw_label_dsc_init(&label_dsc);
|
||||
label_dsc.color = lv_color_white();
|
||||
label_dsc.text = buf;
|
||||
lv_draw_sw_label(draw_unit, &label_dsc, &txt_area);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_VGLITE*/
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2022, 2023 NXP
|
||||
* Copyright 2022-2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
@@ -36,7 +36,7 @@
|
||||
*
|
||||
* @param[in] point1 Starting point with relative coordinates
|
||||
* @param[in] point2 Ending point with relative coordinates
|
||||
* @param[in] clip_area Clipping area with relative coordinates to dest buff
|
||||
* @param[in] clip_area Clip area with relative coordinates to dest buff
|
||||
* @param[in] dsc Line description structure (width, rounded ending, opacity, ...)
|
||||
*
|
||||
*/
|
||||
@@ -65,21 +65,21 @@ void lv_draw_vglite_line(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t *
|
||||
return;
|
||||
|
||||
lv_layer_t * layer = draw_unit->target_layer;
|
||||
lv_area_t rel_clip_area;
|
||||
rel_clip_area.x1 = LV_MIN(dsc->p1.x, dsc->p2.x) - dsc->width / 2;
|
||||
rel_clip_area.x2 = LV_MAX(dsc->p1.x, dsc->p2.x) + dsc->width / 2;
|
||||
rel_clip_area.y1 = LV_MIN(dsc->p1.y, dsc->p2.y) - dsc->width / 2;
|
||||
rel_clip_area.y2 = LV_MAX(dsc->p1.y, dsc->p2.y) + dsc->width / 2;
|
||||
lv_area_t clip_area;
|
||||
clip_area.x1 = LV_MIN(dsc->p1.x, dsc->p2.x) - dsc->width / 2;
|
||||
clip_area.x2 = LV_MAX(dsc->p1.x, dsc->p2.x) + dsc->width / 2;
|
||||
clip_area.y1 = LV_MIN(dsc->p1.y, dsc->p2.y) - dsc->width / 2;
|
||||
clip_area.y2 = LV_MAX(dsc->p1.y, dsc->p2.y) + dsc->width / 2;
|
||||
|
||||
if(!_lv_area_intersect(&rel_clip_area, &rel_clip_area, draw_unit->clip_area))
|
||||
if(!_lv_area_intersect(&clip_area, &clip_area, draw_unit->clip_area))
|
||||
return; /*Fully clipped, nothing to do*/
|
||||
|
||||
lv_area_move(&rel_clip_area, -layer->draw_buf_ofs.x, -layer->draw_buf_ofs.y);
|
||||
lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
|
||||
|
||||
lv_point_t rel_point1 = {dsc->p1.x - layer->draw_buf_ofs.x, dsc->p1.y - layer->draw_buf_ofs.y};
|
||||
lv_point_t rel_point2 = {dsc->p2.x - layer->draw_buf_ofs.x, dsc->p2.y - layer->draw_buf_ofs.y};
|
||||
lv_point_t point1 = {dsc->p1.x - layer->buf_area.x1, dsc->p1.y - layer->buf_area.y1};
|
||||
lv_point_t point2 = {dsc->p2.x - layer->buf_area.x1, dsc->p2.y - layer->buf_area.y1};
|
||||
|
||||
_vglite_draw_line(&rel_point1, &rel_point2, &rel_clip_area, dsc);
|
||||
_vglite_draw_line(&point1, &point2, &clip_area, dsc);
|
||||
}
|
||||
|
||||
/**********************
|
||||
@@ -89,7 +89,6 @@ void lv_draw_vglite_line(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t *
|
||||
static void _vglite_draw_line(const lv_point_t * point1, const lv_point_t * point2,
|
||||
const lv_area_t * clip_area, const lv_draw_line_dsc_t * dsc)
|
||||
{
|
||||
vg_lite_error_t err = VG_LITE_SUCCESS;
|
||||
vg_lite_path_t path;
|
||||
vg_lite_buffer_t * vgbuf = vglite_get_dest_buf();
|
||||
vg_lite_cap_style_t cap_style = (dsc->round_start || dsc->round_end) ? VG_LITE_CAP_ROUND : VG_LITE_CAP_BUTT;
|
||||
@@ -107,8 +106,7 @@ static void _vglite_draw_line(const lv_point_t * point1, const lv_point_t * poin
|
||||
stroke_dash_phase = (vg_lite_float_t)dsc->dash_width / 2;
|
||||
}
|
||||
|
||||
/* Choose vglite blend mode based on given lvgl blend mode */
|
||||
vg_lite_blend_t vglite_blend_mode = vglite_get_blend_mode(dsc->blend_mode);
|
||||
vg_lite_blend_t vgblend = vglite_get_blend_mode(dsc->blend_mode);
|
||||
|
||||
/*** Init path ***/
|
||||
int32_t width = dsc->width;
|
||||
@@ -119,10 +117,9 @@ static void _vglite_draw_line(const lv_point_t * point1, const lv_point_t * poin
|
||||
VLC_OP_END
|
||||
};
|
||||
|
||||
err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, sizeof(line_path), line_path,
|
||||
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
|
||||
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Init path failed.");
|
||||
VGLITE_CHECK_ERROR(vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, sizeof(line_path), line_path,
|
||||
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
|
||||
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f));
|
||||
|
||||
lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->opa);
|
||||
vg_lite_color_t vgcol = vglite_get_color(col32, false);
|
||||
@@ -131,27 +128,18 @@ static void _vglite_draw_line(const lv_point_t * point1, const lv_point_t * poin
|
||||
vg_lite_identity(&matrix);
|
||||
|
||||
/*** Draw line ***/
|
||||
err = vg_lite_set_draw_path_type(&path, VG_LITE_DRAW_STROKE_PATH);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Set draw path type failed.");
|
||||
VGLITE_CHECK_ERROR(vg_lite_set_draw_path_type(&path, VG_LITE_DRAW_STROKE_PATH));
|
||||
|
||||
err = vg_lite_set_stroke(&path, cap_style, join_style, width, 8, stroke_dash_pattern, stroke_dash_count,
|
||||
stroke_dash_phase, vgcol);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Set stroke failed.");
|
||||
VGLITE_CHECK_ERROR(vg_lite_set_stroke(&path, cap_style, join_style, width, 8, stroke_dash_pattern, stroke_dash_count,
|
||||
stroke_dash_phase, vgcol));
|
||||
|
||||
err = vg_lite_update_stroke(&path);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Update stroke failed.");
|
||||
VGLITE_CHECK_ERROR(vg_lite_update_stroke(&path));
|
||||
|
||||
vglite_set_scissor(clip_area);
|
||||
|
||||
err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, vglite_blend_mode, vgcol);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Draw line failed.");
|
||||
VGLITE_CHECK_ERROR(vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, vgblend, vgcol));
|
||||
|
||||
vglite_run();
|
||||
|
||||
vglite_disable_scissor();
|
||||
|
||||
err = vg_lite_clear_path(&path);
|
||||
LV_ASSERT_MSG(err == VG_LITE_SUCCESS, "Clear path failed.");
|
||||
VGLITE_CHECK_ERROR(vg_lite_clear_path(&path));
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_VGLITE*/
|
||||
|
||||
179
src/draw/nxp/vglite/lv_draw_vglite_triangle.c
Normal file
179
src/draw/nxp/vglite/lv_draw_vglite_triangle.c
Normal file
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
* @file lv_draw_vglite_triangle.c
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2023-2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_draw_vglite.h"
|
||||
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
#include "lv_vglite_buf.h"
|
||||
#include "lv_vglite_path.h"
|
||||
#include "lv_vglite_utils.h"
|
||||
|
||||
#include "../../../stdlib/lv_string.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Draw triangle shape with effects (opacity, gradient)
|
||||
*
|
||||
* @param[in] coords Coordinates of the triangle (relative to dest buff)
|
||||
* @param[in] clip_area Clipping area with relative coordinates to dest buff
|
||||
* @param[in] dsc Description of the triangle
|
||||
*
|
||||
*/
|
||||
static void _vglite_draw_triangle(const lv_area_t * coords, const lv_area_t * clip_area,
|
||||
const lv_draw_triangle_dsc_t * dsc);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_vglite_triangle(lv_draw_unit_t * draw_unit, const lv_draw_triangle_dsc_t * dsc)
|
||||
{
|
||||
if(dsc->bg_opa <= (lv_opa_t)LV_OPA_MIN)
|
||||
return;
|
||||
|
||||
lv_layer_t * layer = draw_unit->target_layer;
|
||||
lv_area_t clip_area;
|
||||
lv_area_copy(&clip_area, draw_unit->clip_area);
|
||||
lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
|
||||
|
||||
lv_area_t coords;
|
||||
coords.x1 = (int32_t)LV_MIN3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x);
|
||||
coords.y1 = (int32_t)LV_MIN3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y);
|
||||
coords.x2 = (int32_t)LV_MAX3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x);
|
||||
coords.y2 = (int32_t)LV_MAX3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y);
|
||||
|
||||
lv_area_move(&coords, -layer->buf_area.x1, -layer->buf_area.y1);
|
||||
|
||||
lv_area_t clipped_coords;
|
||||
if(!_lv_area_intersect(&clipped_coords, &coords, &clip_area))
|
||||
return; /* Fully clipped, nothing to do */
|
||||
|
||||
_vglite_draw_triangle(&coords, &clip_area, dsc);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void _vglite_draw_triangle(const lv_area_t * coords, const lv_area_t * clip_area,
|
||||
const lv_draw_triangle_dsc_t * dsc)
|
||||
{
|
||||
vg_lite_buffer_t * vgbuf = vglite_get_dest_buf();
|
||||
|
||||
lv_area_t tri_area;
|
||||
tri_area.x1 = (int32_t)LV_MIN3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x);
|
||||
tri_area.y1 = (int32_t)LV_MIN3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y);
|
||||
tri_area.x2 = (int32_t)LV_MAX3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x);
|
||||
tri_area.y2 = (int32_t)LV_MAX3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y);
|
||||
|
||||
uint32_t width = tri_area.x2 - tri_area.x1;
|
||||
uint32_t height = tri_area.y2 - tri_area.y1;
|
||||
|
||||
/* Init path */
|
||||
int32_t triangle_path[] = { /*VG line path*/
|
||||
VLC_OP_MOVE, dsc->p[0].x, dsc->p[0].y,
|
||||
VLC_OP_LINE, dsc->p[1].x, dsc->p[1].y,
|
||||
VLC_OP_LINE, dsc->p[2].x, dsc->p[2].y,
|
||||
VLC_OP_LINE, dsc->p[0].x, dsc->p[0].y,
|
||||
VLC_OP_END
|
||||
};
|
||||
|
||||
vg_lite_path_t path;
|
||||
VGLITE_CHECK_ERROR(vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, sizeof(triangle_path), triangle_path,
|
||||
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
|
||||
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f));
|
||||
|
||||
vg_lite_matrix_t matrix;
|
||||
vg_lite_identity(&matrix);
|
||||
|
||||
/* Init Color */
|
||||
lv_color32_t col32 = lv_color_to_32(dsc->bg_color, dsc->bg_opa);
|
||||
vg_lite_color_t vgcol = vglite_get_color(col32, false);
|
||||
|
||||
vg_lite_linear_gradient_t gradient;
|
||||
bool has_gradient = (dsc->bg_grad.dir != (lv_grad_dir_t)LV_GRAD_DIR_NONE);
|
||||
|
||||
/* Init Gradient*/
|
||||
if(has_gradient) {
|
||||
vg_lite_matrix_t * grad_matrix;
|
||||
|
||||
vg_lite_uint32_t colors[LV_GRADIENT_MAX_STOPS];
|
||||
vg_lite_uint32_t stops[LV_GRADIENT_MAX_STOPS];
|
||||
lv_color32_t col32[LV_GRADIENT_MAX_STOPS];
|
||||
|
||||
/* Gradient Setup */
|
||||
vg_lite_uint32_t cnt = LV_MAX(dsc->bg_grad.stops_count, LV_GRADIENT_MAX_STOPS);
|
||||
for(uint8_t i = 0; i < cnt; i++) {
|
||||
stops[i] = dsc->bg_grad.stops[i].frac;
|
||||
|
||||
col32[i] = lv_color_to_32(dsc->bg_grad.stops[i].color, dsc->bg_grad.stops[i].opa);
|
||||
colors[i] = vglite_get_color(col32[i], true);
|
||||
}
|
||||
|
||||
lv_memzero(&gradient, sizeof(vg_lite_linear_gradient_t));
|
||||
|
||||
VGLITE_CHECK_ERROR(vg_lite_init_grad(&gradient));
|
||||
|
||||
VGLITE_CHECK_ERROR(vg_lite_set_grad(&gradient, cnt, colors, stops));
|
||||
|
||||
VGLITE_CHECK_ERROR(vg_lite_update_grad(&gradient));
|
||||
|
||||
grad_matrix = vg_lite_get_grad_matrix(&gradient);
|
||||
vg_lite_identity(grad_matrix);
|
||||
vg_lite_translate((float)coords->x1, (float)coords->y1, grad_matrix);
|
||||
|
||||
if(dsc->bg_grad.dir == (lv_grad_dir_t)LV_GRAD_DIR_VER) {
|
||||
vg_lite_scale(1.0f, (float)height / 256.0f, grad_matrix);
|
||||
vg_lite_rotate(90.0f, grad_matrix);
|
||||
}
|
||||
else { /*LV_GRAD_DIR_HOR*/
|
||||
vg_lite_scale((float)width / 256.0f, 1.0f, grad_matrix);
|
||||
}
|
||||
|
||||
VGLITE_CHECK_ERROR(vg_lite_draw_gradient(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, &gradient,
|
||||
VG_LITE_BLEND_SRC_OVER));
|
||||
}
|
||||
else {
|
||||
VGLITE_CHECK_ERROR(vg_lite_draw(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol));
|
||||
}
|
||||
|
||||
vglite_run();
|
||||
|
||||
VGLITE_CHECK_ERROR(vg_lite_clear_path(&path));
|
||||
|
||||
if(has_gradient)
|
||||
VGLITE_CHECK_ERROR(vg_lite_clear_grad(&gradient));
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_VGLITE*/
|
||||
@@ -69,20 +69,20 @@ void vglite_set_src_buf_ptr(const void * buf)
|
||||
_set_vgbuf_ptr(&_src_vgbuf, (void *)buf);
|
||||
}
|
||||
|
||||
void vglite_set_dest_buf(const lv_draw_buf_t * draw_buf)
|
||||
void vglite_set_dest_buf(const void * buf, uint32_t width, uint32_t height, uint32_t stride,
|
||||
lv_color_format_t cf)
|
||||
{
|
||||
vglite_set_buf(&_dest_vgbuf, draw_buf->buf, draw_buf->width, draw_buf->height,
|
||||
lv_draw_buf_get_stride(draw_buf), draw_buf->color_format);
|
||||
vglite_set_buf(&_dest_vgbuf, (void *)buf, width, height, stride, cf);
|
||||
}
|
||||
|
||||
void vglite_set_src_buf(const void * buf, int32_t width, int32_t height, uint32_t stride,
|
||||
void vglite_set_src_buf(const void * buf, uint32_t width, uint32_t height, uint32_t stride,
|
||||
lv_color_format_t cf)
|
||||
{
|
||||
vglite_set_buf(&_src_vgbuf, (void *)buf, width, height, stride, cf);
|
||||
}
|
||||
|
||||
void vglite_set_buf(vg_lite_buffer_t * vgbuf, void * buf,
|
||||
int32_t width, int32_t height, uint32_t stride,
|
||||
uint32_t width, uint32_t height, uint32_t stride,
|
||||
lv_color_format_t cf)
|
||||
{
|
||||
vg_lite_buffer_format_t vgformat = vglite_get_buf_format(cf);
|
||||
|
||||
@@ -71,12 +71,17 @@ void vglite_set_dest_buf_ptr(void * buf);
|
||||
void vglite_set_src_buf_ptr(const void * buf);
|
||||
|
||||
/**
|
||||
* Set vglite target (destination) buffer.
|
||||
* Set vglite destination buffer.
|
||||
*
|
||||
* @param[in] draw_buf Destination draw buffer descriptor
|
||||
* @param[in] buf Destination buffer address
|
||||
* @param[in] width Destination buffer width
|
||||
* @param[in] height Destination buffer height
|
||||
* @param[in] stride Destination buffer stride in bytes
|
||||
* @param[in] cf Destination buffer color format
|
||||
*
|
||||
*/
|
||||
void vglite_set_dest_buf(const lv_draw_buf_t * draw_buf);
|
||||
void vglite_set_dest_buf(const void * buf, uint32_t width, uint32_t height, uint32_t stride,
|
||||
lv_color_format_t cf);
|
||||
|
||||
/**
|
||||
* Set vglite source buffer.
|
||||
@@ -88,7 +93,7 @@ void vglite_set_dest_buf(const lv_draw_buf_t * draw_buf);
|
||||
* @param[in] cf Source buffer color format
|
||||
*
|
||||
*/
|
||||
void vglite_set_src_buf(const void * buf, int32_t width, int32_t height, uint32_t stride,
|
||||
void vglite_set_src_buf(const void * buf, uint32_t width, uint32_t height, uint32_t stride,
|
||||
lv_color_format_t cf);
|
||||
|
||||
/**
|
||||
@@ -103,7 +108,7 @@ void vglite_set_src_buf(const void * buf, int32_t width, int32_t height, uint32_
|
||||
*
|
||||
*/
|
||||
void vglite_set_buf(vg_lite_buffer_t * vgbuf, void * buf,
|
||||
int32_t width, int32_t height, uint32_t stride,
|
||||
uint32_t width, uint32_t height, uint32_t stride,
|
||||
lv_color_format_t cf);
|
||||
|
||||
/**********************
|
||||
|
||||
@@ -58,15 +58,16 @@ void vglite_set_transformation_matrix(const lv_area_t * dest_area, const lv_draw
|
||||
{
|
||||
vglite_set_translation_matrix(dest_area);
|
||||
|
||||
bool has_scale = (dsc->zoom != LV_SCALE_NONE);
|
||||
bool has_scale = (dsc->scale_x != LV_SCALE_NONE || dsc->scale_y != LV_SCALE_NONE);
|
||||
bool has_rotation = (dsc->rotation != 0);
|
||||
|
||||
vg_lite_translate(dsc->pivot.x, dsc->pivot.y, &_vgmatrix);
|
||||
if(has_rotation)
|
||||
vg_lite_rotate(dsc->rotation / 10.0f, &_vgmatrix); /* angle is 1/10 degree */
|
||||
if(has_scale) {
|
||||
vg_lite_float_t scale = 1.0f * dsc->zoom / LV_SCALE_NONE;
|
||||
vg_lite_scale(scale, scale, &_vgmatrix);
|
||||
vg_lite_float_t scale_x = 1.0f * dsc->scale_x / LV_SCALE_NONE;
|
||||
vg_lite_float_t scale_y = 1.0f * dsc->scale_y / LV_SCALE_NONE;
|
||||
vg_lite_scale(scale_x, scale_y, &_vgmatrix);
|
||||
}
|
||||
vg_lite_translate(0.0f - dsc->pivot.x, 0.0f - dsc->pivot.y, &_vgmatrix);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2022, 2023 NXP
|
||||
* Copyright 2022-2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
@@ -20,10 +20,6 @@
|
||||
|
||||
#include "../../../core/lv_refr.h"
|
||||
|
||||
#if LV_USE_OS
|
||||
#include "vg_lite_gpu.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
@@ -40,7 +36,7 @@
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
#if LV_USE_OS
|
||||
#if LV_USE_VGLITE_DRAW_ASYNC
|
||||
static volatile bool _cmd_buf_flushed = false;
|
||||
#endif
|
||||
|
||||
@@ -52,7 +48,29 @@
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#if LV_USE_OS
|
||||
const char * vglite_error_to_string(vg_lite_error_t error)
|
||||
{
|
||||
switch(error) {
|
||||
ENUM_TO_STRING(VG_LITE_SUCCESS);
|
||||
ENUM_TO_STRING(VG_LITE_INVALID_ARGUMENT);
|
||||
ENUM_TO_STRING(VG_LITE_OUT_OF_MEMORY);
|
||||
ENUM_TO_STRING(VG_LITE_NO_CONTEXT);
|
||||
ENUM_TO_STRING(VG_LITE_TIMEOUT);
|
||||
ENUM_TO_STRING(VG_LITE_OUT_OF_RESOURCES);
|
||||
ENUM_TO_STRING(VG_LITE_GENERIC_IO);
|
||||
ENUM_TO_STRING(VG_LITE_NOT_SUPPORT);
|
||||
ENUM_TO_STRING(VG_LITE_ALREADY_EXISTS);
|
||||
ENUM_TO_STRING(VG_LITE_NOT_ALIGNED);
|
||||
ENUM_TO_STRING(VG_LITE_FLEXA_TIME_OUT);
|
||||
ENUM_TO_STRING(VG_LITE_FLEXA_HANDSHAKE_FAIL);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return "VG_LITE_UKNOWN_ERROR";
|
||||
}
|
||||
|
||||
#if LV_USE_VGLITE_DRAW_ASYNC
|
||||
bool vglite_cmd_buf_is_flushed(void)
|
||||
{
|
||||
return _cmd_buf_flushed;
|
||||
@@ -61,10 +79,12 @@ bool vglite_cmd_buf_is_flushed(void)
|
||||
|
||||
void vglite_run(void)
|
||||
{
|
||||
#if LV_USE_OS
|
||||
vg_lite_gpu_state_t gpu_state = vg_lite_get_gpu_state();
|
||||
#if LV_USE_VGLITE_DRAW_ASYNC
|
||||
vg_lite_uint32_t gpu_idle = 0;
|
||||
|
||||
if(gpu_state == VG_LITE_GPU_BUSY) {
|
||||
VGLITE_CHECK_ERROR(vg_lite_get_parameter(VG_LITE_GPU_IDLE_STATE, 1, (vg_lite_pointer)&gpu_idle));
|
||||
|
||||
if(!gpu_idle) {
|
||||
_cmd_buf_flushed = false;
|
||||
|
||||
return;
|
||||
@@ -72,15 +92,15 @@ void vglite_run(void)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* For multithreading version (with OS), we simply flush the command buffer
|
||||
* and the vglite draw thread will signal the dispatcher for completed tasks.
|
||||
* Without OS, we process the tasks and signal them as complete one by one.
|
||||
* If LV_USE_VGLITE_DRAW_ASYNC is enabled, simply flush the command buffer and the
|
||||
* vglite draw thread will signal asynchronous the dispatcher for completed tasks.
|
||||
* Without draw async, process the tasks and signal them as complete one by one.
|
||||
*/
|
||||
#if LV_USE_OS
|
||||
LV_ASSERT_MSG(vg_lite_flush() == VG_LITE_SUCCESS, "Flush failed.");
|
||||
#if LV_USE_VGLITE_DRAW_ASYNC
|
||||
VGLITE_CHECK_ERROR(vg_lite_flush());
|
||||
_cmd_buf_flushed = true;
|
||||
#else
|
||||
LV_ASSERT_MSG(vg_lite_finish() == VG_LITE_SUCCESS, "Finish failed.");
|
||||
VGLITE_CHECK_ERROR(vg_lite_finish());
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -88,12 +108,10 @@ vg_lite_color_t vglite_get_color(lv_color32_t lv_col32, bool gradient)
|
||||
{
|
||||
vg_lite_color_t vg_col32;
|
||||
|
||||
/* Only pre-multiply color if hardware pre-multiplication is not present */
|
||||
if(!vg_lite_query_feature(gcFEATURE_BIT_VG_PE_PREMULTIPLY)) {
|
||||
lv_col32.red = (uint8_t)((lv_col32.red * lv_col32.alpha) >> 8);
|
||||
lv_col32.green = (uint8_t)((lv_col32.green * lv_col32.alpha) >> 8);
|
||||
lv_col32.blue = (uint8_t)((lv_col32.blue * lv_col32.alpha) >> 8);
|
||||
}
|
||||
/* Pre-multiply alpha */
|
||||
lv_col32.red = LV_UDIV255(lv_col32.red * lv_col32.alpha);
|
||||
lv_col32.green = LV_UDIV255(lv_col32.green * lv_col32.alpha);
|
||||
lv_col32.blue = LV_UDIV255(lv_col32.blue * lv_col32.alpha);
|
||||
|
||||
if(!gradient)
|
||||
/* The color is in ABGR8888 format with red channel in the lower 8 bits. */
|
||||
@@ -109,21 +127,45 @@ vg_lite_color_t vglite_get_color(lv_color32_t lv_col32, bool gradient)
|
||||
|
||||
vg_lite_blend_t vglite_get_blend_mode(lv_blend_mode_t lv_blend_mode)
|
||||
{
|
||||
vg_lite_blend_t vg_blend_mode;
|
||||
vg_lite_blend_t vg_blend_mode = VG_LITE_BLEND_NONE;
|
||||
|
||||
switch(lv_blend_mode) {
|
||||
case LV_BLEND_MODE_ADDITIVE:
|
||||
vg_blend_mode = VG_LITE_BLEND_ADDITIVE;
|
||||
break;
|
||||
case LV_BLEND_MODE_SUBTRACTIVE:
|
||||
vg_blend_mode = VG_LITE_BLEND_SUBTRACT;
|
||||
break;
|
||||
case LV_BLEND_MODE_MULTIPLY:
|
||||
vg_blend_mode = VG_LITE_BLEND_MULTIPLY;
|
||||
break;
|
||||
default:
|
||||
vg_blend_mode = VG_LITE_BLEND_SRC_OVER;
|
||||
break;
|
||||
if(vg_lite_query_feature(gcFEATURE_BIT_VG_LVGL_SUPPORT)) {
|
||||
switch(lv_blend_mode) {
|
||||
case LV_BLEND_MODE_NORMAL:
|
||||
vg_blend_mode = VG_LITE_BLEND_NORMAL_LVGL;
|
||||
break;
|
||||
case LV_BLEND_MODE_ADDITIVE:
|
||||
vg_blend_mode = VG_LITE_BLEND_ADDITIVE_LVGL;
|
||||
break;
|
||||
case LV_BLEND_MODE_SUBTRACTIVE:
|
||||
vg_blend_mode = VG_LITE_BLEND_SUBTRACT_LVGL;
|
||||
break;
|
||||
case LV_BLEND_MODE_MULTIPLY:
|
||||
vg_blend_mode = VG_LITE_BLEND_MULTIPLY_LVGL;
|
||||
break;
|
||||
default:
|
||||
VGLITE_ASSERT_MSG(false, "Unsupported blend mode.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch(lv_blend_mode) {
|
||||
case LV_BLEND_MODE_NORMAL:
|
||||
vg_blend_mode = VG_LITE_BLEND_SRC_OVER;
|
||||
break;
|
||||
case LV_BLEND_MODE_ADDITIVE:
|
||||
vg_blend_mode = VG_LITE_BLEND_ADDITIVE;
|
||||
break;
|
||||
case LV_BLEND_MODE_SUBTRACTIVE:
|
||||
vg_blend_mode = VG_LITE_BLEND_SUBTRACT;
|
||||
break;
|
||||
case LV_BLEND_MODE_MULTIPLY:
|
||||
vg_blend_mode = VG_LITE_BLEND_MULTIPLY;
|
||||
break;
|
||||
default:
|
||||
VGLITE_ASSERT_MSG(false, "Unsupported blend mode.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return vg_blend_mode;
|
||||
@@ -134,7 +176,6 @@ vg_lite_buffer_format_t vglite_get_buf_format(lv_color_format_t cf)
|
||||
vg_lite_buffer_format_t vg_buffer_format = VG_LITE_BGR565;
|
||||
|
||||
switch(cf) {
|
||||
/*<=1 byte (+alpha) formats*/
|
||||
case LV_COLOR_FORMAT_L8:
|
||||
vg_buffer_format = VG_LITE_L8;
|
||||
break;
|
||||
@@ -153,18 +194,14 @@ vg_lite_buffer_format_t vglite_get_buf_format(lv_color_format_t cf)
|
||||
case LV_COLOR_FORMAT_I8:
|
||||
vg_buffer_format = VG_LITE_INDEX_8;
|
||||
break;
|
||||
|
||||
/*2 byte (+alpha) formats*/
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
vg_buffer_format = VG_LITE_BGR565;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_RGB565A8:
|
||||
LV_ASSERT_MSG(false, "Unsupported color format.");
|
||||
vg_buffer_format = VG_LITE_ABGR8565;
|
||||
break;
|
||||
|
||||
/*3 byte (+alpha) formats*/
|
||||
case LV_COLOR_FORMAT_RGB888:
|
||||
LV_ASSERT_MSG(false, "Unsupported color format.");
|
||||
vg_buffer_format = VG_LITE_BGR888;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
vg_buffer_format = VG_LITE_BGRA8888;
|
||||
@@ -174,52 +211,13 @@ vg_lite_buffer_format_t vglite_get_buf_format(lv_color_format_t cf)
|
||||
break;
|
||||
|
||||
default:
|
||||
LV_ASSERT_MSG(false, "Unsupported color format.");
|
||||
VGLITE_ASSERT_MSG(false, "Unsupported color format.");
|
||||
break;
|
||||
}
|
||||
|
||||
return vg_buffer_format;
|
||||
}
|
||||
|
||||
uint8_t vglite_get_px_size(lv_color_format_t cf)
|
||||
{
|
||||
uint8_t bits_per_pixel = LV_COLOR_DEPTH;
|
||||
|
||||
switch(cf) {
|
||||
case LV_COLOR_FORMAT_I1:
|
||||
bits_per_pixel = 1;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_I2:
|
||||
bits_per_pixel = 2;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_I4:
|
||||
bits_per_pixel = 4;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_I8:
|
||||
case LV_COLOR_FORMAT_A8:
|
||||
case LV_COLOR_FORMAT_L8:
|
||||
bits_per_pixel = 8;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
bits_per_pixel = 16;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_RGB565A8:
|
||||
case LV_COLOR_FORMAT_RGB888:
|
||||
bits_per_pixel = 24;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
case LV_COLOR_FORMAT_XRGB8888:
|
||||
bits_per_pixel = 32;
|
||||
break;
|
||||
|
||||
default:
|
||||
LV_ASSERT_MSG(false, "Unsupported buffer format.");
|
||||
break;
|
||||
}
|
||||
|
||||
return bits_per_pixel;
|
||||
}
|
||||
|
||||
uint8_t vglite_get_alignment(lv_color_format_t cf)
|
||||
{
|
||||
uint8_t align_bytes = LV_COLOR_DEPTH / 8 * 16; /*16 pixels*/
|
||||
@@ -228,12 +226,20 @@ uint8_t vglite_get_alignment(lv_color_format_t cf)
|
||||
case LV_COLOR_FORMAT_I1:
|
||||
case LV_COLOR_FORMAT_I2:
|
||||
case LV_COLOR_FORMAT_I4:
|
||||
align_bytes = 8;
|
||||
/*
|
||||
* VGLite alignment require 8 bytes.
|
||||
* But ARM clean and invalidate cache needs 32 bytes address alignment.
|
||||
*/
|
||||
align_bytes = 32;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_I8:
|
||||
case LV_COLOR_FORMAT_A8:
|
||||
case LV_COLOR_FORMAT_L8:
|
||||
align_bytes = 16;
|
||||
/*
|
||||
* VGLite alignment require 16 bytes.
|
||||
* But ARM clean and invalidate cache needs 32 bytes address alignment.
|
||||
*/
|
||||
align_bytes = 32;
|
||||
break;
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
align_bytes = 32;
|
||||
@@ -248,7 +254,7 @@ uint8_t vglite_get_alignment(lv_color_format_t cf)
|
||||
break;
|
||||
|
||||
default:
|
||||
LV_ASSERT_MSG(false, "Unsupported buffer format.");
|
||||
VGLITE_ASSERT_MSG(false, "Unsupported buffer format.");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -262,18 +268,12 @@ bool vglite_buf_aligned(const void * buf, uint32_t stride, lv_color_format_t cf)
|
||||
/* No alignment requirement for destination buffer when using mode VG_LITE_LINEAR */
|
||||
|
||||
/* Test for pointer alignment */
|
||||
if((uintptr_t)buf % align_bytes) {
|
||||
LV_LOG_ERROR("Buffer address (0x%x) not aligned to %d bytes.",
|
||||
(size_t)buf, align_bytes);
|
||||
if((uintptr_t)buf % align_bytes)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Test for stride alignment */
|
||||
if(stride % align_bytes) {
|
||||
LV_LOG_ERROR("Buffer stride (%d bytes) not aligned to %d bytes.",
|
||||
stride, align_bytes);
|
||||
if(stride == 0 || stride % align_bytes)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2022, 2023 NXP
|
||||
* Copyright 2022-2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
@@ -25,11 +25,34 @@ extern "C" {
|
||||
#include "../../sw/lv_draw_sw.h"
|
||||
|
||||
#include "vg_lite.h"
|
||||
#include "vg_lite_options.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define ENUM_TO_STRING(e) \
|
||||
case (e): \
|
||||
return #e
|
||||
|
||||
#if LV_USE_VGLITE_ASSERT
|
||||
#define VGLITE_ASSERT(expr) LV_ASSERT(expr)
|
||||
#define VGLITE_ASSERT_MSG(expr, msg) LV_ASSERT_MSG(expr, msg)
|
||||
#else
|
||||
#define VGLITE_ASSERT(expr)
|
||||
#define VGLITE_ASSERT_MSG(expr, msg) LV_LOG_ERROR(msg)
|
||||
#endif
|
||||
|
||||
#define VGLITE_CHECK_ERROR(function) \
|
||||
do { \
|
||||
vg_lite_error_t error = function; \
|
||||
if(error != VG_LITE_SUCCESS) { \
|
||||
LV_LOG_ERROR("Execute '" #function "' error(%d): %s", \
|
||||
(int)error, vglite_error_to_string(error)); \
|
||||
VGLITE_ASSERT(false); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
@@ -39,24 +62,20 @@ extern "C" {
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Enable scissor and set the clipping box.
|
||||
* Set the clipping box.
|
||||
*
|
||||
* @param[in] clip_area Clip area with relative coordinates of destination buffer
|
||||
*
|
||||
*/
|
||||
static inline void vglite_set_scissor(const lv_area_t * clip_area);
|
||||
|
||||
/**
|
||||
* Disable scissor.
|
||||
*
|
||||
*/
|
||||
static inline void vglite_disable_scissor(void);
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
#if LV_USE_OS
|
||||
const char * vglite_error_to_string(vg_lite_error_t error);
|
||||
|
||||
#if LV_USE_VGLITE_DRAW_ASYNC
|
||||
/**
|
||||
* Get VG-Lite command buffer flushed status.
|
||||
*
|
||||
@@ -65,7 +84,7 @@ bool vglite_cmd_buf_is_flushed(void);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Clear cache and flush command to VG-Lite.
|
||||
* Flush command to VG-Lite.
|
||||
*
|
||||
*/
|
||||
void vglite_run(void);
|
||||
@@ -102,16 +121,6 @@ vg_lite_blend_t vglite_get_blend_mode(lv_blend_mode_t lv_blend_mode);
|
||||
*/
|
||||
vg_lite_buffer_format_t vglite_get_buf_format(lv_color_format_t cf);
|
||||
|
||||
/**
|
||||
* Get vglite buffer pixel size.
|
||||
*
|
||||
* @param[in] cf Color format
|
||||
*
|
||||
* @retval Bits per pixel
|
||||
*
|
||||
*/
|
||||
uint8_t vglite_get_px_size(lv_color_format_t cf);
|
||||
|
||||
/**
|
||||
* Get vglite buffer alignment.
|
||||
*
|
||||
@@ -144,15 +153,7 @@ bool vglite_buf_aligned(const void * buf, uint32_t stride, lv_color_format_t cf)
|
||||
|
||||
static inline void vglite_set_scissor(const lv_area_t * clip_area)
|
||||
{
|
||||
vg_lite_enable_scissor();
|
||||
vg_lite_set_scissor((int32_t)clip_area->x1, (int32_t)clip_area->y1,
|
||||
(int32_t)lv_area_get_width(clip_area),
|
||||
(int32_t)lv_area_get_height(clip_area));
|
||||
}
|
||||
|
||||
static inline void vglite_disable_scissor(void)
|
||||
{
|
||||
vg_lite_disable_scissor();
|
||||
vg_lite_set_scissor(clip_area->x1, clip_area->y1, clip_area->x2 + 1, clip_area->y2 + 1);
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_VGLITE*/
|
||||
|
||||
@@ -189,6 +189,35 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*=================
|
||||
* OPERATING SYSTEM
|
||||
*=================*/
|
||||
/*Select an operating system to use. Possible options:
|
||||
* - LV_OS_NONE
|
||||
* - LV_OS_PTHREAD
|
||||
* - LV_OS_FREERTOS
|
||||
* - LV_OS_CMSIS_RTOS2
|
||||
* - LV_OS_RTTHREAD
|
||||
* - LV_OS_WINDOWS
|
||||
* - LV_OS_CUSTOM */
|
||||
#ifndef LV_USE_OS
|
||||
#ifdef CONFIG_LV_USE_OS
|
||||
#define LV_USE_OS CONFIG_LV_USE_OS
|
||||
#else
|
||||
#define LV_USE_OS LV_OS_NONE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if LV_USE_OS == LV_OS_CUSTOM
|
||||
#ifndef LV_OS_CUSTOM_INCLUDE
|
||||
#ifdef CONFIG_LV_OS_CUSTOM_INCLUDE
|
||||
#define LV_OS_CUSTOM_INCLUDE CONFIG_LV_OS_CUSTOM_INCLUDE
|
||||
#else
|
||||
#define LV_OS_CUSTOM_INCLUDE <stdint.h>
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*========================
|
||||
* RENDERING CONFIGURATION
|
||||
*========================*/
|
||||
@@ -332,6 +361,41 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
/* Enable blit quality degradation workaround recommended for screen's dimension > 352 pixels. */
|
||||
#ifndef LV_USE_VGLITE_BLIT_SPLIT
|
||||
#ifdef CONFIG_LV_USE_VGLITE_BLIT_SPLIT
|
||||
#define LV_USE_VGLITE_BLIT_SPLIT CONFIG_LV_USE_VGLITE_BLIT_SPLIT
|
||||
#else
|
||||
#define LV_USE_VGLITE_BLIT_SPLIT 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if LV_USE_OS
|
||||
/* Enable VGLite draw async. Queue multiple tasks and flash them once to the GPU. */
|
||||
#ifndef LV_USE_VGLITE_DRAW_ASYNC
|
||||
#ifdef _LV_KCONFIG_PRESENT
|
||||
#ifdef CONFIG_LV_USE_VGLITE_DRAW_ASYNC
|
||||
#define LV_USE_VGLITE_DRAW_ASYNC CONFIG_LV_USE_VGLITE_DRAW_ASYNC
|
||||
#else
|
||||
#define LV_USE_VGLITE_DRAW_ASYNC 0
|
||||
#endif
|
||||
#else
|
||||
#define LV_USE_VGLITE_DRAW_ASYNC 1
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Enable VGLite asserts. */
|
||||
#ifndef LV_USE_VGLITE_ASSERT
|
||||
#ifdef CONFIG_LV_USE_VGLITE_ASSERT
|
||||
#define LV_USE_VGLITE_ASSERT CONFIG_LV_USE_VGLITE_ASSERT
|
||||
#else
|
||||
#define LV_USE_VGLITE_ASSERT 0
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Use NXP's PXP on iMX RTxxx platforms. */
|
||||
#ifndef LV_USE_DRAW_PXP
|
||||
#ifdef CONFIG_LV_USE_DRAW_PXP
|
||||
@@ -341,6 +405,17 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if LV_USE_DRAW_PXP
|
||||
/* Enable PXP asserts. */
|
||||
#ifndef LV_USE_PXP_ASSERT
|
||||
#ifdef CONFIG_LV_USE_PXP_ASSERT
|
||||
#define LV_USE_PXP_ASSERT CONFIG_LV_USE_PXP_ASSERT
|
||||
#else
|
||||
#define LV_USE_PXP_ASSERT 0
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Use Renesas Dave2D on RA platforms. */
|
||||
#ifndef LV_USE_DRAW_DAVE2D
|
||||
#ifdef CONFIG_LV_USE_DRAW_DAVE2D
|
||||
@@ -389,35 +464,6 @@
|
||||
|
||||
#endif
|
||||
|
||||
/*=================
|
||||
* OPERATING SYSTEM
|
||||
*=================*/
|
||||
/*Select an operating system to use. Possible options:
|
||||
* - LV_OS_NONE
|
||||
* - LV_OS_PTHREAD
|
||||
* - LV_OS_FREERTOS
|
||||
* - LV_OS_CMSIS_RTOS2
|
||||
* - LV_OS_RTTHREAD
|
||||
* - LV_OS_WINDOWS
|
||||
* - LV_OS_CUSTOM */
|
||||
#ifndef LV_USE_OS
|
||||
#ifdef CONFIG_LV_USE_OS
|
||||
#define LV_USE_OS CONFIG_LV_USE_OS
|
||||
#else
|
||||
#define LV_USE_OS LV_OS_NONE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if LV_USE_OS == LV_OS_CUSTOM
|
||||
#ifndef LV_OS_CUSTOM_INCLUDE
|
||||
#ifdef CONFIG_LV_OS_CUSTOM_INCLUDE
|
||||
#define LV_OS_CUSTOM_INCLUDE CONFIG_LV_OS_CUSTOM_INCLUDE
|
||||
#else
|
||||
#define LV_OS_CUSTOM_INCLUDE <stdint.h>
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*=======================
|
||||
* FEATURE CONFIGURATION
|
||||
*=======================*/
|
||||
|
||||
@@ -70,6 +70,10 @@ static void lv_mem_walker(void * ptr, size_t size, int used, void * user);
|
||||
|
||||
void lv_mem_init(void)
|
||||
{
|
||||
#if LV_USE_OS
|
||||
lv_mutex_init(&state.mutex);
|
||||
#endif
|
||||
|
||||
#if LV_MEM_ADR == 0
|
||||
#ifdef LV_MEM_POOL_ALLOC
|
||||
state.tlsf = lv_tlsf_create_with_pool((void *)LV_MEM_POOL_ALLOC(LV_MEM_SIZE), LV_MEM_SIZE);
|
||||
@@ -82,10 +86,6 @@ void lv_mem_init(void)
|
||||
state.tlsf = lv_tlsf_create_with_pool((void *)LV_MEM_ADR, LV_MEM_SIZE);
|
||||
#endif
|
||||
|
||||
#if LV_USE_OS
|
||||
lv_mutex_init(&state.mutex);
|
||||
#endif
|
||||
|
||||
_lv_ll_init(&state.pool_ll, sizeof(lv_pool_t));
|
||||
|
||||
/*Record the first pool*/
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#if LV_BUILD_TEST || 1
|
||||
#if LV_BUILD_TEST
|
||||
#include "../lvgl.h"
|
||||
|
||||
#include "unity/unity.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#if LV_BUILD_TEST || 1
|
||||
#if LV_BUILD_TEST
|
||||
#include "../lvgl.h"
|
||||
|
||||
#include "unity/unity.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#if LV_BUILD_TEST || 1
|
||||
#if LV_BUILD_TEST
|
||||
#include "../lvgl.h"
|
||||
|
||||
#include "unity/unity.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#if LV_BUILD_TEST || 1
|
||||
#if LV_BUILD_TEST
|
||||
#include "../lvgl.h"
|
||||
|
||||
#include "unity/unity.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#if LV_BUILD_TEST || 1
|
||||
#if LV_BUILD_TEST
|
||||
#include "../lvgl.h"
|
||||
|
||||
#include "unity/unity.h"
|
||||
|
||||
Reference in New Issue
Block a user