Compare commits

...

129 Commits

Author SHA1 Message Date
Gabor Kiss-Vamosi
e6d7be00bf docs: update changelog 2023-07-05 13:42:21 +02:00
Gabriel Wang
15433d69b9 chore(cmsis-pack): update cmsis-pack for v8.3.8 (#4340) 2023-07-05 13:39:10 +02:00
Gabor Kiss-Vamosi
9491c3ff6d example(tabview): fix tabview disable scrollig example
there is no animatin after selecting a tab by clicking anymore
2023-06-30 22:50:52 +02:00
Gabor Kiss-Vamosi
3de61c76af fix(tabview): remove the animation if the tab is selected by clicking the button on the header 2023-06-26 10:33:21 +02:00
kolliemo
09cc0de573 docs: mention incompatibility between software rotation and direct_mode or full_refresh (#4308) 2023-06-23 22:39:10 +02:00
Gabor Kiss-Vamosi
227ac02341 docs(faq): don't say 24 bit is support as LVGL can't render in RGB888 directly 2023-06-23 09:52:25 +02:00
Gabor Kiss-Vamosi
8b83fe7ea5 feat(rt-thread): make the rt-thread env recursively glob the UI files 2023-06-20 07:53:34 +02:00
Gabor Kiss-Vamosi
edd5ad28ad fix(btnmatrix): fix array out of bounds addressing with groups and no buttons 2023-06-19 10:28:23 +02:00
pete-pjb
07bce7466d fix:(BtnMatrix) Backport https://github.com/lvgl/lvgl/pull/4185
Stop disabled/hidden button matrix keys from getting stuck in a loop
2023-06-16 17:51:49 +01:00
pete-pjb
1713cd3fd8 Revert "fix:(BtnMatrix) Backport https://github.com/lvgl/lvgl/pull/4185"
This reverts commit cb602ea778.
2023-06-16 17:42:08 +01:00
pete-pjb
cb602ea778 fix:(BtnMatrix) Backport https://github.com/lvgl/lvgl/pull/4185
Stop Button Matrix getting stuck in loop if buttons disable/hidden
2023-06-16 17:31:34 +01:00
Rbb666
caf29ef0c5 add(docs): add renesas-ra6m3 get-started document (#4278) 2023-06-12 12:21:46 +02:00
jacquesdmernok
a3199514ab fix(stm32): static function prototypes moved from .h to .c (#4276) 2023-06-12 12:12:12 +02:00
Rbb666
78cbdfc151 add(gpu): add renesas-ra6m3 gpu adaptation (#4270) 2023-06-08 10:42:34 +02:00
Gabor Kiss-Vamosi
75e6ef4e1d fix(btnmatrix): fix using > 7 as button width 2023-05-31 22:49:41 +02:00
Lorenzo Arena
2376c57860 fix(png): fix decode image size and some warnings (#4248) 2023-05-29 10:43:49 +02:00
Gabor Kiss-Vamosi
e3659c46b1 fix(arduino): fix messed up variable types 2023-05-24 11:09:51 +02:00
Lorenzo Arena
df96b57f4e fix(bidi): add more Hebrew checks to RTL characters set (#4171) (#4239) 2023-05-24 10:00:07 +02:00
Gabor Kiss-Vamosi
67b3011f83 fix(chart): fix division by zero if there are no ticks 2023-05-19 10:25:17 +02:00
nicusorcitu
d87737612a perf(pxp, vglite): improve performance and add more features (#4222)
Signed-off-by: Nicușor Cîțu <nicusor.citu@nxp.com>
Signed-off-by: Stefan Babatie <stefan.babatie@nxp.com>
Signed-off-by: Jason Yu <zejiang.yu@nxp.com>
Co-authored-by: Stefan Babatie <stefan.babatie@nxp.com>
Co-authored-by: Jason Yu <zejiang.yu@nxp.com>
2023-05-18 22:43:19 +02:00
Gabor Kiss-Vamosi
6a89bd2d74 fix(msgbox): fix typo 2023-05-18 13:01:17 +02:00
Gabor Kiss-Vamosi
6843c191b7 fix(msgbox): add missing lv_obj_class_init_obj
fixes #4226
2023-05-18 11:53:58 +02:00
Gabor Kiss-Vamosi
1caafc55dd fix(disp): fix memory leak lv_scr_load_anim with auto_del and time=0
fixes: #4212
2023-05-18 11:14:16 +02:00
Gabor Kiss-Vamosi
5ba90a5c41 fix(flex): register LV_STYLE_FLEX_GROW
fixes #4214
2023-05-10 08:25:04 +02:00
jadergn
630da9c6ca fix(img): fix getting the image type on big endian systems (#4215) 2023-05-09 20:27:54 +02:00
Mariotaku
ee95e7dc25 fix(sdl): destroy texture after use if not stored in cache (#4173) 2023-05-08 17:02:49 +02:00
Gabor Kiss-Vamosi
45b13c378f fix(draw): typo with LV_COLOR_DEPTH 8 2023-05-03 10:34:18 +02:00
Gabriel Wang
2b56e04205 chore(cmsis-pack): update cmsis-pack for v8.3.7 (#4203) 2023-05-03 10:11:24 +02:00
Gabor Kiss-Vamosi
177900b033 docs(changelog): update changelog for v8.3.7 2023-05-03 10:07:40 +02:00
Oleg Belousov
203e7fc97d fix (spinbox): doubling characters entered from the keyboard (#4190) 2023-05-01 11:11:56 +02:00
Gabriel Wang
7345e62355 fix(arm-2d): fix transform-chrome-keying issue (#4178) 2023-04-28 11:26:53 +02:00
Gabor Kiss-Vamosi
48d7878bac fix(style): fix trasition on bg_grad color
fixes: #4174
2023-04-28 10:37:32 +02:00
Gabor Kiss-Vamosi
a0795b49e8 fix(indev): fix integer overflow in recursive zoom calculation 2023-04-24 20:10:33 +02:00
Gabor Kiss-Vamosi
a150b15e45 feat(btnmatrix): review ctrl map and allow width values to be max 15 2023-04-24 10:54:47 +02:00
Posejdos
a95714ba7c fix(menu): prevent setting the current page again (#4136) 2023-04-18 10:50:22 +02:00
Tomas Rezucha
8536152d81 fix(esp): fix ESP-IDF pedantic builds (backport v8.3) (#4135) 2023-04-17 13:03:58 +02:00
moinmoin-sh
6314441839 fix: color mixing with LV_COLOR_SWAP == 1 (#4101) 2023-04-03 15:10:03 +02:00
Gabor Kiss-Vamosi
88c51b22ad docs: udpate changelog 2023-04-03 10:29:45 +02:00
Gabriel Wang
6b0092c0d9 chore(cmsis-pack): update cmsis-pack for v8.3.6 (#4108) 2023-04-03 10:27:16 +02:00
Gabor Kiss-Vamosi
aa313806d0 fix(bar): delete running animations when a new value is set without animation
fixes #4094
2023-04-03 10:25:04 +02:00
Gabor Kiss-Vamosi
5e0e1c8c4e chore: code formatting 2023-03-28 13:56:17 +02:00
Gabor Kiss-Vamosi
d0e19eb2d3 fix(arc): fix knob area invalidation 2023-03-28 13:53:59 +02:00
Neo Xu
fd20fabfda fix(group): fix default_group becomes wild pointer when deleted (#4076) 2023-03-20 15:27:22 +01:00
Gabor Kiss-Vamosi
399069b4a2 Update build_html_examples.sh 2023-03-17 17:08:33 +01:00
Gabor Kiss-Vamosi
501230e0fc docs: use a fixed commit of lv_web_emscripten
fixes #4071
2023-03-17 17:00:52 +01:00
Neo Xu
adcf166382 fix(fs_posix): allow creating new file and set permission. (#3976)
Signed-off-by: Neo Xu <neo.xu1990@gmail.com>
2023-03-17 09:40:23 +01:00
Gabor Kiss-Vamosi
2f294aa76c docs(arduino): add note to not use lv_examles library 2023-03-14 07:40:48 +01:00
Gabor Kiss-Vamosi
9a870b34a9 format code 2023-03-08 11:12:11 +01:00
Gabor Kiss-Vamosi
0b7777f27a fix(slider): consider animations on pressing 2023-03-08 11:09:38 +01:00
Neo Xu
e8d8f399e0 fix(img): support negative angles (#3846)
Signed-off-by: Xu Xingliang <xuxingliang@xiaomi.com>
2023-02-27 17:16:08 +01:00
yuqingli05
0df09db23e fix(gif): synchronize with master (#4003) 2023-02-20 21:05:48 +01:00
Morgan Diepart
e2386fd46d fix(gpu): fix STM GPU drivers for some variants (#4004) 2023-02-20 14:26:11 +01:00
fvanroie
2944277f07 fix(img): possible divide by 0 exception (lvgl#3988) (#3990)
Co-authored-by: fvanroie <cpt_jack@msn.com>
2023-02-15 20:57:19 +01:00
Gabor Kiss-Vamosi
6af01798d8 feat(msg): add lv_msg_unsubcribe_obj 2023-02-14 13:36:12 +01:00
Gabor Kiss-Vamosi
77670fb1a5 chore: update the version numbers to v8.3.5-dev 2023-02-07 08:16:26 +01:00
Gabor Kiss-Vamosi
f29514aa5c docs: update changelog 2023-02-07 08:12:45 +01:00
Gabriel Wang
e7e8cf846d feat(cmsis-pack): update cmsis-pack for v8.3.5 (#3972) 2023-02-07 08:10:13 +01:00
Junbo Zheng
8b1270347f fix(monkey): remove executable permissions from source files (#3971)
Signed-off-by: Junbo Zheng <zhengjunbo1@xiaomi.com>
2023-02-07 07:34:38 +01:00
Amir Gonnen
e6cd7063b6 fix(ci): set Ubuntu version for MicroPython test (#3865) 2023-02-01 13:39:40 +01:00
Gabor Kiss-Vamosi
34c545ef19 docs(indev): fix the name of long_press_repeat_time (was long_press_rep_time)
fixes #3954
2023-02-01 10:42:03 +01:00
nicusorcitu
361ee79611 feat(gpu): improve NXP's PXP and VGLite accelerators (#3952)
Signed-off-by: Nicușor Cîțu <nicusor.citu@nxp.com>
Signed-off-by: Stefan Babatie <stefan.babatie@nxp.com>
Signed-off-by: Wenbin Yuan <wenbin.yuan@nxp.com>
Co-authored-by: Stefan Babatie <stefan.babatie@nxp.com>
Co-authored-by: Wenbin Yuan <wenbin.yuan@nxp.com>
2023-02-01 10:35:24 +01:00
Gabor Kiss-Vamosi
39f424767f fix(roller): consider the recolor setting of the label
fixes #3950
2023-01-28 23:57:08 +01:00
Tomasz Jastrzębski
1853cc5143 perf(dam2d): rework stm32 dma2d (#3904) 2023-01-23 08:37:34 +01:00
Gabor Kiss-Vamosi
9faca8a8d4 Update layer.md 2023-01-13 09:27:22 +01:00
Mr.9You
8ea6f03fc3 fix(Kconfig): Fix wrong type of LV_FS_STDIO_CACHE_SIZE (v8.3) (#3906) 2023-01-05 21:19:33 +01:00
Forairaaaaa
c6c1b0b3d3 chore: add an option to "LV_TICK_CUSTOM" (#3879) 2023-01-03 08:12:19 +01:00
Mr.9You
e529230f4b ci(esp): fix push to the component registry on tag 2023-01-02 20:16:37 +01:00
Gabriel Wang
dbb15bb3ea feat(cmsis-pack): update for v8.3.4 (#3896) 2023-01-01 13:30:29 +01:00
Gabor Kiss-Vamosi
47c8f8f982 bump version numbers to v8.3.5-dev 2022-12-15 13:39:56 +01:00
Gabor Kiss-Vamosi
2c0162b457 release v8.3.4 2022-12-15 13:38:36 +01:00
Man, Jianting (Meco)
dec580b9f1 fix(rt-thread): sync rt-thread v5.0.0 rt_align (#3864) 2022-12-13 11:47:17 +01:00
Gabor Kiss-Vamosi
ad56dfaf70 fix(gridnav): fix stucking in pressed state with encoder
fixes #3854
2022-12-13 09:59:20 +01:00
Gabor Kiss-Vamosi
c8e584f879 fix(style): add the missing support for pct pivot in tranasform style properties 2022-12-11 00:16:57 +01:00
Mariotaku
d2d886aae5 fix(draw): SDL2 gradient support #3848 (#3856) 2022-12-08 10:36:03 +01:00
Gabor Kiss-Vamosi
1e3ca25fed fix(example): fix warnings
related to #3759
2022-12-06 08:08:20 +01:00
Gabor Kiss-Vamosi
84cf05d8b2 fix(indev): fix scrolling on transformed obejcts
related to #3819
2022-12-05 09:46:21 +01:00
Gabor Kiss-Vamosi
2c17b28ac4 fix(darw): add back the disappeared antialising=0 support
fixes #3838
2022-12-03 17:49:48 +01:00
Gabor Kiss-Vamosi
1ed026ca73 fix(benchmark): fix warnings
related to #3759
2022-12-02 14:34:30 +01:00
Gabor Kiss-Vamosi
ae3825871e demo(benchmark): fix lv_label_set_text_fmt format strings 2022-11-28 21:34:30 +01:00
Man, Jianting (Meco)
ae300acb2f [v8.3.x][rt-thread][squareline] fix compiler cannot find the lvgl/lvg… (#3834) 2022-11-28 19:38:29 +01:00
Gabor Kiss-Vamosi
41fa416134 fix(msg): fix typos in API by adding wrappers
fixes #3822
2022-11-24 11:08:53 +01:00
Gabor Kiss-Vamosi
68f6190f8e chore: format code 2022-11-23 12:49:05 +01:00
Gabor Kiss-Vamosi
1173dcba96 demo(benchmark): fix warning 2022-11-23 12:45:25 +01:00
Gabor Kiss-Vamosi
716e5e2c8b fix(meter): fix setting part_draw_dsc.id in needle img drawing 2022-11-20 12:37:13 +01:00
Gabor Kiss-Vamosi
bb2c2ac34a fix(chart): fix very dense bar charts 2022-11-20 12:37:13 +01:00
Gabor Kiss-Vamosi
c4c400716e fix(flex): be sure obj->w_layout and h_layout can't be set at the same time
realted to https://forum.lvgl.io/t/flex-grow-in-rotate/10220/4
2022-11-17 21:28:30 +01:00
_VIFEXTech
6825d4bd1d chore(table): remove extra spaces (#3805)
Co-authored-by: pengyiqiang <pengyiqiang@xiaomi.com>
2022-11-16 14:21:42 +01:00
Gabor Kiss-Vamosi
39d03a80f4 feat(table): scroll to the selected cell with key navigation
Fixes https://forum.lvgl.io/t/grid-navigation-with-automatic-scrolling-for-table/10285
2022-11-16 11:32:11 +01:00
Ramesh
340a1cb60b fix(esp.cmake): add demos and examples (#3784) 2022-11-05 18:55:30 +01:00
Gabor Kiss-Vamosi
e06f03db72 fix(draw): fix transformation accuracy
fixes #3777
2022-11-02 17:26:12 +01:00
Gabor Kiss-Vamosi
bd11ad8542 fix(draw): handle LV_COLOR_DEPTH == 1 too in lv_draw_sw_transform
fixes: #3772
2022-11-01 18:25:09 +01:00
Gabor Kiss-Vamosi
e050f5ca15 fix(draw): fix text color with sub pixel rendering and BGR order
fixes: #3764
2022-10-26 10:14:02 +02:00
Gabor Kiss-Vamosi
903e94b716 fix(style): remove the reduntant define of LV_GRADIENT_MAX_STOPS
fixes #3752
2022-10-24 16:03:34 +02:00
Gabor Kiss-Vamosi
0732400e7b Revert "feat(keyboard): ported arabic keyboard from release 7.10.0 (#3728)"
This reverts commit 483b2a4322.
2022-10-09 19:27:34 +02:00
gianlucacornacchia
483b2a4322 feat(keyboard): ported arabic keyboard from release 7.10.0 (#3728) 2022-10-09 18:42:10 +02:00
Gabor Kiss-Vamosi
5545ffc925 release v8.3.3 2022-10-06 10:00:12 +02:00
Gabor Kiss-Vamosi
c8bee40410 fix: version number in lvgl.h 2022-09-30 11:26:19 +02:00
Gabor Kiss-Vamosi
755d363ecc release v8.3.2 2022-09-27 08:04:09 +02:00
Gabor Kiss-Vamosi
dfd14fa778 fix(slider): find the nearest value on click instead of floor
fixes: #3690
2022-09-19 09:55:49 +02:00
Mariotaku
1ab9aa5312 fix(fragment): fixed child fragment event dispatch (#3683) 2022-09-12 16:19:54 +02:00
Mariotaku
4d69cd865c fix(sdl): clear streaming/target texture with FillRect (#3682) 2022-09-12 16:18:47 +02:00
Tyler
832bef4346 fix(sdl): transformation with alpha (#3576) (#3678)
Co-authored-by: Mariotaku <mariotaku.lee@gmail.com>
2022-09-10 13:51:42 +02:00
Gabor Kiss-Vamosi
d5b2a9b256 fix(draw): fix border drawing with thick borders
fixes #3648
2022-09-02 13:32:18 +02:00
Gabor Kiss-Vamosi
7640950216 chore: fix warnings 2022-08-31 22:32:56 +02:00
Gabor Kiss-Vamosi
8b605cc482 fix(refr): fix true double double buffering logic with transparent screens
fixes #3623
2022-08-31 21:15:53 +02:00
Gabor Kiss-Vamosi
ece3495004 fix(draw): allow drawing outline with LV_DRAW_COMPLEX == 0 too 2022-08-31 21:15:53 +02:00
_VIFEXTech
f6655c2aaf fix(draw_sw): fix image cache to access the freed stack space (#3584)
Co-authored-by: pengyiqiang <pengyiqiang@xiaomi.com>
2022-08-23 15:30:05 +02:00
Pieter De Gendt
cba2aa95c8 fix(style): use compile time prop_cnt for const styles (#3609)
No need to end with an empty/invalid property in the const list.
This change allows to save space, and doesn't break existing lists.
2022-08-23 12:19:48 +02:00
Man, Jianting (Meco)
660464c973 chore(rt-thread) backport fixes from v9 (#3604)
https://github.com/lvgl/lvgl/pull/3566
https://github.com/lvgl/lvgl/pull/3467
2022-08-21 20:42:32 -04:00
Gabor Kiss-Vamosi
5156ee058d fix(group): be sure obj is removed from its current group in lv_group_add_obj
fixes #3593
2022-08-19 12:03:06 +02:00
Gabor Kiss-Vamosi
a0515ba30d fix(style): add missing invalidation in lv_obj_remove_local_style_prop
fixes #3581
2022-08-17 12:51:45 +02:00
Chris Morgan
1a46030918 docs(draw) remove reference to old lv_fs_add_drv function (#3564) 2022-08-11 09:24:49 -04:00
Chris Morgan
f58dcd94fc docs(disp): LV_COLOR_SCREEN_TRANSP remove dependency on LV_COLOR_DEPTH_32 as transparency is supported across all color depths (#3556)
* Kconfig - LV_COLOR_SCREEN_TRANSP remove dependency on LV_COLOR_DEPTH_32 as transparency is supported across all color depths

* display.md - LV_COLOR_SCREEN_TRANSP remove mention of 32bpp requirement that is no longer necessary
2022-08-10 14:00:14 +02:00
Gabor Kiss-Vamosi
d59bba12db fix(colorwheel): fix updating color when using lv_colorwheel_set_hsv
fixes https://forum.lvgl.io/t/about-colorwheel-updates-bug/9522
2022-08-07 23:08:19 +02:00
Gabor Kiss-Vamosi
5022476edc remove accidentally added code 2022-08-07 23:07:10 +02:00
Gabor Kiss-Vamosi
b884abae26 fix(canvas): fix clipéping on transformation
fixes: #3545
2022-08-07 21:34:17 +02:00
卢华东
aa45d59852 fix(demo): can not found lvgl.h file (#3477) 2022-07-28 00:08:02 +02:00
Amir Gonnen
55e95ed351 fix(ci) checkout lv_micropython release/v8 branch (#3524) 2022-07-26 17:53:17 -04:00
Gabor Kiss-Vamosi
be485d7605 ci: protect test.c with #if LV_BUILD_TEST 2022-07-25 21:33:31 +02:00
Gabor Kiss-Vamosi
9024b72b48 update the changelog 2022-07-25 12:46:26 +02:00
Gabor Kiss-Vamosi
9b998aa47d Bump version numbers to v8.3.1 2022-07-25 12:44:28 +02:00
Gabor Kiss-Vamosi
71913d300d example(freetype): Update the Micropython example to use the Lato font 2022-07-25 12:43:17 +02:00
Adam Martini
284834e799 fix(led): add bg_color draw descriptors back to led draw event to support LV_DRAW_COMPLEX 0 (#3515)
Co-authored-by: Hopper Automation <automation_hopper@hopper.com>
2022-07-23 20:40:56 +02:00
Gabor Kiss-Vamosi
8544cc3806 example(freetype): replace the arial font with lato to avoid licensing issues
fixes https://github.com/zephyrproject-rtos/zephyr/issues/48111
2022-07-23 20:32:56 +02:00
s-hadinger
62662f68e9 docs(tasmota): support LVGL 8.3.0 (#3511) 2022-07-20 14:04:42 +02:00
Gabor Kiss-Vamosi
a283273bd2 fix(arc): fix arc knob invalidation in SYMMETRICAL mode
fixes #3465
2022-07-14 17:23:13 +02:00
Gabor Kiss-Vamosi
9750c97aff fix(refr): fix lv_refr_get_top_obj
related to https://forum.lvgl.io/t/how-to-speed-up-the-v8-version/9091/21
2022-07-14 17:22:54 +02:00
Gabor Kiss-Vamosi
2967172bee fix(slider): fix knob drawing in symmetrical mode 2022-07-14 17:22:46 +02:00
Badokas
9e1b6166b0 docs(readme): fix LVGL version typo (8.3.0) (#3462) 2022-07-07 21:07:17 +02:00
151 changed files with 6911 additions and 2432 deletions

View File

@@ -8,7 +8,7 @@ jobs:
build:
if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }}
name: Build ${{ matrix.port }} port
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
continue-on-error: true
strategy:
matrix:
@@ -23,7 +23,7 @@ jobs:
- name: Clone lv_micropython
run: |
git clone https://github.com/lvgl/lv_micropython.git .
git checkout master
git checkout release/v8
- name: Initialize lv_bindings submodule
run: git submodule update --init --recursive lib/lv_bindings
- name: Update ${{ matrix.port }} port submodules

View File

@@ -1,23 +1,23 @@
name: Push LVGL release to Espressif Component Service
# If the commit is tagged, it will be uploaded. Other scenario silently fail.
on:
push:
branches:
- master
jobs:
upload_components:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
with:
submodules: "recursive"
- name: Upload component to component registry
uses: espressif/github-actions/upload_components@master
with:
name: "lvgl"
version: "git"
namespace: "lvgl"
api_token: ${{ secrets.ESP_IDF_COMPONENT_API_TOKEN }}
name: Push LVGL release to Espressif Component Service
# If the commit is tagged, it will be uploaded. Other scenario silently fail.
on:
push:
tags:
- v*
jobs:
upload_components:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
submodules: "recursive"
- name: Upload component to component registry
uses: espressif/upload-components-ci-action@v1
with:
name: "lvgl"
version: ${{ github.ref_name }}
namespace: "lvgl"
api_token: ${{ secrets.ESP_IDF_COMPONENT_API_TOKEN }}

17
Kconfig
View File

@@ -42,11 +42,9 @@ menu "LVGL configuration"
config LV_COLOR_SCREEN_TRANSP
bool "Enable more complex drawing routines to manage screens transparency."
depends on LV_COLOR_DEPTH_32
help
Can be used if the UI is above another layer, e.g. an OSD menu or video player.
Requires `LV_COLOR_DEPTH = 32` colors and the screen's `bg_opa` should be set to
non LV_OPA_COVER value
The screen's `bg_opa` should be set to non LV_OPA_COVER value
config LV_COLOR_MIX_ROUND_OFS
int "Adjust color mix functions rounding"
@@ -230,6 +228,16 @@ menu "LVGL configuration"
Must be defined to include path of CMSIS header of target processor
e.g. "stm32f769xx.h" or "stm32f429xx.h"
config LV_USE_GPU_RA6M3_G2D
bool "Enable RA6M3 G2D GPU."
config LV_GPU_RA6M3_G2D_INCLUDE
string "include path of target processor"
depends on LV_USE_GPU_RA6M3_G2D
default "hal_data.h"
help
Must be defined to include path of target processor
e.g. "hal_data.h"
config LV_USE_GPU_SWM341_DMA2D
bool "Enable SWM341 DMA2D GPU."
config LV_GPU_SWM341_DMA2D_INCLUDE
@@ -913,7 +921,8 @@ menu "LVGL configuration"
string "Set the working directory"
depends on LV_USE_FS_STDIO
config LV_FS_STDIO_CACHE_SIZE
string ">0 to cache this number of bytes in lv_fs_read()"
int ">0 to cache this number of bytes in lv_fs_read()"
default 0
depends on LV_USE_FS_STDIO
config LV_USE_FS_POSIX

View File

@@ -1,9 +1,4 @@
#if defined(LV_LVGL_H_INCLUDE_SIMPLE)
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
#include "../../../lvgl.h"
#ifndef LV_ATTRIBUTE_MEM_ALIGN
#define LV_ATTRIBUTE_MEM_ALIGN

View File

@@ -725,7 +725,8 @@ void lv_demo_benchmark_run_scene(int_fast16_t scene_no)
scene_act = scene_no >> 1;
if(scenes[scene_act].create_cb) {
lv_label_set_text_fmt(title, "%"LV_PRId32"/%d: %s%s", scene_act * 2 + (opa_mode ? 1 : 0), (int)(dimof(scenes) * 2) - 2,
lv_label_set_text_fmt(title, "%"LV_PRId32"/%"LV_PRId32": %s%s", scene_act * 2 + (opa_mode ? 1 : 0),
(int32_t)(dimof(scenes) * 2) - 2,
scenes[scene_act].name, opa_mode ? " + opa" : "");
lv_label_set_text(subtitle, "");
@@ -995,8 +996,8 @@ static void scene_next_task_cb(lv_timer_t * timer)
}
if(scenes[scene_act].create_cb) {
lv_label_set_text_fmt(title, "%"LV_PRId32"/%d: %s%s", scene_act * 2 + (opa_mode ? 1 : 0),
(int)(dimof(scenes) * 2) - 2, scenes[scene_act].name, opa_mode ? " + opa" : "");
lv_label_set_text_fmt(title, "%"LV_PRId32"/%"LV_PRId32": %s%s", scene_act * 2 + (opa_mode ? 1 : 0),
(int32_t)(dimof(scenes) * 2) - 2, scenes[scene_act].name, opa_mode ? " + opa" : "");
if(opa_mode) {
lv_label_set_text_fmt(subtitle, "Result of \"%s\": %"LV_PRId32" FPS", scenes[scene_act].name,
scenes[scene_act].fps_normal);

View File

@@ -1,7 +1,239 @@
# Changelog
## [v8.3.8](https://github.com/lvgl/lvgl/compare/v8.3.8...v8.3.7) 5 July 2023
## [v8.2.0](https://github.com/lvgl/lvgl/compare/v8.2.0...v8.2.0) 6 July 2022
### New Features
- feat(rt-thread): make the rt-thread env recursively glob the UI files [`8b83fe7`](https://github.com/lvgl/lvgl/commit/8b83fe7ea53a597cdbae8204d0aa9be8ad3d2b89)
### Performance
- perf(pxp, vglite): improve performance and add more features [`4222`](https://github.com/lvgl/lvgl/pull/4222)
### Fixes
- fix(stm32): static function prototypes moved from .h to .c [`4276`](https://github.com/lvgl/lvgl/pull/4276)
- fix(png): fix decode image size and some warnings [`4248`](https://github.com/lvgl/lvgl/pull/4248)
- fix(bidi): add more Hebrew checks to RTL characters set (#4171) [`4239`](https://github.com/lvgl/lvgl/pull/4239)
- fix(img): fix getting the image type on big endian systems [`4215`](https://github.com/lvgl/lvgl/pull/4215)
- fix(sdl): destroy texture after use if not stored in cache [`4173`](https://github.com/lvgl/lvgl/pull/4173)
- fix:(BtnMatrix) Backport https://github.com/lvgl/lvgl/pull/4185 [`cb602ea`](https://github.com/lvgl/lvgl/commit/cb602ea7785de21a187ef5ee5f7de4e3aa3f7e0e)
- fix(arduino): fix messed up variable types [`e3659c4`](https://github.com/lvgl/lvgl/commit/e3659c46b128b2b715b196c3ccfb94b3de4c89f8)
- fix:(BtnMatrix) Backport https://github.com/lvgl/lvgl/pull/4185 [`07bce74`](https://github.com/lvgl/lvgl/commit/07bce7466d471a15ba241a9db3239f7a116b0b46)
- fix(chart): fix division by zero if there are no ticks [`67b3011`](https://github.com/lvgl/lvgl/commit/67b3011f835b08c77ff60ae2d1e6592a710ca2b1)
- fix(msgbox): fix typo [`6a89bd2`](https://github.com/lvgl/lvgl/commit/6a89bd2d7409ac4d49ad32da73ba50a84f7c8990)
- fix(tabview): remove the animation if the tab is selected by clicking the button on the header [`3de61c7`](https://github.com/lvgl/lvgl/commit/3de61c76af0aed1665e9d61e47b4dd50b9e8bdf1)
- fix(btnmatrix): fix array out of bounds addressing with groups and no buttons [`edd5ad2`](https://github.com/lvgl/lvgl/commit/edd5ad28ad74d1025db0b442cfa390d8c01ae006)
- fix(btnmatrix): fix using &gt; 7 as button width [`75e6ef4`](https://github.com/lvgl/lvgl/commit/75e6ef4e1d66a85d68160b97ef931b0717e77212)
- fix(draw): typo with LV_COLOR_DEPTH 8 [`45b13c3`](https://github.com/lvgl/lvgl/commit/45b13c378f6fc1728ddf1547c25daa61d62c9f76)
- fix(disp): fix memory leak lv_scr_load_anim with auto_del and time=0 [`1caafc5`](https://github.com/lvgl/lvgl/commit/1caafc55dde46e1b7e3d17d8c5349fbf7cccba9f)
- fix(msgbox): add missing lv_obj_class_init_obj [`6843c19`](https://github.com/lvgl/lvgl/commit/6843c191b792f66829477827279adbbc763541c1)
- fix(flex): register LV_STYLE_FLEX_GROW [`5ba90a5`](https://github.com/lvgl/lvgl/commit/5ba90a5c41f584a8eb3a4fc8e2f466729652ddb3)
### Examples
- example(tabview): fix tabview disable scrollig example [`9491c3f`](https://github.com/lvgl/lvgl/commit/9491c3ff6d2f8e56b13d8fb493d4b3ee98ef1a4b)
### Docs
- docs: mention incompatibility between software rotation and `direct_mode` or `full_refresh` [`4308`](https://github.com/lvgl/lvgl/pull/4308)
- docs(faq): don't say 24 bit is support as LVGL can't render in RGB888 directly [`227ac02`](https://github.com/lvgl/lvgl/commit/227ac023419eeb253892b1c36113059f12b1f9f2)
### CI and tests
### Others
- chore(cmsis-pack): update cmsis-pack for v8.3.8 [`4340`](https://github.com/lvgl/lvgl/pull/4340)
- add(docs): add renesas-ra6m3 get-started document [`4278`](https://github.com/lvgl/lvgl/pull/4278)
- add(gpu): add renesas-ra6m3 gpu adaptation [`4270`](https://github.com/lvgl/lvgl/pull/4270)
- Revert "fix:(BtnMatrix) Backport https://github.com/lvgl/lvgl/pull/4185" [`1713cd3`](https://github.com/lvgl/lvgl/commit/1713cd3fd8f93aa575fbcf0e34b8626b6ee69ded)
## [v8.3.7](https://github.com/lvgl/lvgl/compare/v8.3.7...v8.3.6) 3 May 2023
### New Features
- feat(btnmatrix): review ctrl map and allow width values to be max 15 [`a150b15`](https://github.com/lvgl/lvgl/commit/a150b15e45a922eb5497fe5a31a480e1cd689246)
### Fixes
- fix (spinbox): doubling characters entered from the keyboard [`4190`](https://github.com/lvgl/lvgl/pull/4190)
- fix(arm-2d): fix transform-chrome-keying issue [`4178`](https://github.com/lvgl/lvgl/pull/4178)
- fix(menu): prevent setting the current page again [`4136`](https://github.com/lvgl/lvgl/pull/4136)
- fix(esp): fix ESP-IDF pedantic builds (backport v8.3) [`4135`](https://github.com/lvgl/lvgl/pull/4135)
- fix: color mixing with LV_COLOR_SWAP == 1 [`4101`](https://github.com/lvgl/lvgl/pull/4101)
- fix(indev): fix integer overflow in recursive zoom calculation [`a0795b4`](https://github.com/lvgl/lvgl/commit/a0795b49e82102ad68a27c86c36c37fffbe66d3c)
- fix(style): fix trasition on bg_grad color [`48d7878`](https://github.com/lvgl/lvgl/commit/48d7878bac3f607322957ed6f710d6615d5e72e0)
## [v8.3.6](https://github.com/lvgl/lvgl/compare/v8.3.6...v8.3.5) 3 April 2023
### New Features
- feat(msg): add lv_msg_unsubcribe_obj [`6af0179`](https://github.com/lvgl/lvgl/commit/6af01798d82f90f0c2ba6a9da39c4f10fb427df7)
### Performance
### Fixes
- fix(group): fix default_group becomes wild pointer when deleted [`4076`](https://github.com/lvgl/lvgl/pull/4076)
- fix(fs_posix): allow creating new file and set permission. [`3976`](https://github.com/lvgl/lvgl/pull/3976)
- fix(img): support negative angles [`3846`](https://github.com/lvgl/lvgl/pull/3846)
- fix(gif): synchronize with master [`4003`](https://github.com/lvgl/lvgl/pull/4003)
- fix(gpu): fix STM GPU drivers for some variants [`4004`](https://github.com/lvgl/lvgl/pull/4004)
- fix(img): possible divide by 0 exception (lvgl#3988) [`3990`](https://github.com/lvgl/lvgl/pull/3990)
- fix(arc): fix knob area invalidation [`d0e19eb`](https://github.com/lvgl/lvgl/commit/d0e19eb2d38ba8a500399b0496d7a8363be4003e)
- fix(slider): consider animations on pressing [`0b7777f`](https://github.com/lvgl/lvgl/commit/0b7777f27a7932efe3d594be426e1beb59d80ae3)
- fix(bar): delete running animations when a new value is set without animation [`aa31380`](https://github.com/lvgl/lvgl/commit/aa313806d0ebde475fc2bc360a15172cc1b658a7)
- docs: use a fixed commit of lv_web_emscripten [`501230e`](https://github.com/lvgl/lvgl/commit/501230e0fc95936199b3187d350873c3bb4a94e4)
### Examples
### Docs
- docs(arduino): add note to not use lv_examles library [`2f294aa`](https://github.com/lvgl/lvgl/commit/2f294aa76c8fece98a4fa72304bc6f267ed2a228)
- docs: use a fixed commit of lv_web_emscripten [`501230e`](https://github.com/lvgl/lvgl/commit/501230e0fc95936199b3187d350873c3bb4a94e4)
### CI and tests
### Others
- chore(cmsis-pack): update cmsis-pack for v8.3.6 [`4108`](https://github.com/lvgl/lvgl/pull/4108)
- chore: update the version numbers to v8.3.5-dev [`77670fb`](https://github.com/lvgl/lvgl/commit/77670fb1a55e0f2012ff7a057e535830e7253e22)
- Update build_html_examples.sh [`399069b`](https://github.com/lvgl/lvgl/commit/399069b4a2423c11823581668fe71ce9a7c88e7d)
## [v8.3.5](https://github.com/lvgl/lvgl/compare/v8.3.4...v8.3.5) 7 February 2023
### Performance
- perf(gpu): improve NXP's PXP and VGLite accelerators [`3952`](https://github.com/lvgl/lvgl/pull/3952)
- perf(dam2d): rework stm32 dma2d [`3904`](https://github.com/lvgl/lvgl/pull/3904)
### Fixes
- fix(monkey): remove executable permissions from source files [`3971`](https://github.com/lvgl/lvgl/pull/3971)
- fix(ci): set Ubuntu version for MicroPython test [`3865`](https://github.com/lvgl/lvgl/pull/3865)
- fix(Kconfig): fix wrong type of LV_FS_STDIO_CACHE_SIZE (v8.3) [`3906`](https://github.com/lvgl/lvgl/pull/3906)
- docs(indev): fix the name of long_press_repeat_time (was long_press_rep_time) [`34c545e`](https://github.com/lvgl/lvgl/commit/34c545ef19dc97c8952a412e533a4cd3924b9fbc)
- fix(roller): consider the recolor setting of the label [`39f4247`](https://github.com/lvgl/lvgl/commit/39f424767fa57376c4cb08cf22951fd56d854fd6)
### Examples
### Docs
- docs(indev): fix the name of long_press_repeat_time (was long_press_rep_time) [`34c545e`](https://github.com/lvgl/lvgl/commit/34c545ef19dc97c8952a412e533a4cd3924b9fbc)
### CI and tests
- ci(esp): fix push to the component registry on tag [`e529230`](https://github.com/lvgl/lvgl/commit/e529230f4bb97b4506c430aac96d5ddaef685dc4)
### Others
- chore(cmsis-pack): update cmsis-pack for v8.3.5 [`3972`](https://github.com/lvgl/lvgl/pull/3972)
- chore: add an option to "LV_TICK_CUSTOM" [`3879`](https://github.com/lvgl/lvgl/pull/3879)
- bump version numbers to v8.3.5-dev [`47c8f8f`](https://github.com/lvgl/lvgl/commit/47c8f8f9822f4c0c0ffbe2f12b380bddefcec475)
- Update layer.md [`9faca8a`](https://github.com/lvgl/lvgl/commit/9faca8a8d4125e21dedbf6e46aa1586a6b57e5b8)
## [v8.3.4](https://github.com/lvgl/lvgl/compare/v8.3.4...v8.3.3) 15 December 2022
### New Features
- feat(keyboard): ported arabic keyboard from release 7.10.0 [`3728`](https://github.com/lvgl/lvgl/pull/3728)
- feat(table): scroll to the selected cell with key navigation [`39d03a8`](https://github.com/lvgl/lvgl/commit/39d03a80f45847a1977cfe9cc6a509b1613d0aca)
### Fixes
- fix(rt-thread): sync rt-thread v5.0.0 rt_align [`3864`](https://github.com/lvgl/lvgl/pull/3864)
- fix(draw): SDL2 gradient support #3848 [`3856`](https://github.com/lvgl/lvgl/pull/3856)
- fix(esp.cmake): add demos and examples [`3784`](https://github.com/lvgl/lvgl/pull/3784)
- fix(indev): fix scrolling on transformed obejcts [`84cf05d`](https://github.com/lvgl/lvgl/commit/84cf05d8b23b31e000db757a278545e58fcbcbe8)
- fix(style): add the missing support for pct pivot in tranasform style properties [`c8e584f`](https://github.com/lvgl/lvgl/commit/c8e584f879a1e1427e7a8f5ff496af39f17df41d)
- fix(flex): be sure obj-&gt;w_layout and h_layout can't be set at the same time [`c4c4007`](https://github.com/lvgl/lvgl/commit/c4c400716e80a279e7b3d43b8992915fe94441eb)
- fix(chart): fix very dense bar charts [`bb2c2ac`](https://github.com/lvgl/lvgl/commit/bb2c2ac34ac943978513c7ed51885078979b1c10)
- fix(draw): handle LV_COLOR_DEPTH == 1 too in lv_draw_sw_transform [`bd11ad8`](https://github.com/lvgl/lvgl/commit/bd11ad8542eac9ff51420e5afb80f7e6fcf36a5c)
- fix(example): fix warnings [`1e3ca25`](https://github.com/lvgl/lvgl/commit/1e3ca25fed13bbf85c32a60d4b7041cf8bd525ab)
- fix(benchmark): fix warnings [`1ed026c`](https://github.com/lvgl/lvgl/commit/1ed026ca7307957568fe419f1ff39a15b2535b3e)
- fix(draw): fix text color with sub pixel rendering and BGR order [`e050f5c`](https://github.com/lvgl/lvgl/commit/e050f5ca156f79d752894f38f0a437c946205cb4)
- fix(meter): fix setting part_draw_dsc.id in needle img drawing [`716e5e2`](https://github.com/lvgl/lvgl/commit/716e5e2c8bd2a22e7d56e8d7ca33054a11a1f4ed)
- fix(gridnav): fix stucking in pressed state with encoder [`ad56dfa`](https://github.com/lvgl/lvgl/commit/ad56dfaf7046a9bb8c05e877a8c8852cd14a59af)
- fix(darw): add back the disappeared antialising=0 support [`2c17b28`](https://github.com/lvgl/lvgl/commit/2c17b28ac476c95a4153ab6cabb77b1c7208bb74)
- fix(msg): fix typos in API by adding wrappers [`41fa416`](https://github.com/lvgl/lvgl/commit/41fa41613455260ccdeb87ecb890ce026ff0a435)
- fix(draw): fix transformation accuracy [`e06f03d`](https://github.com/lvgl/lvgl/commit/e06f03db72f98439078118518158f52439dd7bf8)
- fix(style): remove the reduntant define of LV_GRADIENT_MAX_STOPS [`903e94b`](https://github.com/lvgl/lvgl/commit/903e94b716ca1b32cdb51de11df679953699e53b)
- demo(benchmark): fix lv_label_set_text_fmt format strings [`ae38258`](https://github.com/lvgl/lvgl/commit/ae3825871e31cd42cad2f310bdfc605150670511)
- demo(benchmark): fix warning [`1173dcb`](https://github.com/lvgl/lvgl/commit/1173dcba96621e20c9a7240c8572bd6573bce6a0)
## [v8.3.3](https://github.com/lvgl/lvgl/compare/v8.3.2...v8.3.3) 06 October 2022
v8.3.3 is the same as v8.3.2. It was released only because the version number was set incorrectly in lvgl.h.
## [v8.3.2](https://github.com/lvgl/lvgl/compare/v8.3.1...v8.3.2) 27 September 2022
### Fixes
- fix(fragment): fixed child fragment event dispatch [`3683`](https://github.com/lvgl/lvgl/pull/3683)
- fix(sdl): clear streaming/target texture with FillRect [`3682`](https://github.com/lvgl/lvgl/pull/3682)
- fix(sdl): transformation with alpha (#3576) [`3678`](https://github.com/lvgl/lvgl/pull/3678)
- fix(draw_sw): fix image cache to access the freed stack space [`3584`](https://github.com/lvgl/lvgl/pull/3584)
- fix(style): use compile time prop_cnt for const styles [`3609`](https://github.com/lvgl/lvgl/pull/3609)
- fix(demo): can not found lvgl.h file [`3477`](https://github.com/lvgl/lvgl/pull/3477)
- fix(ci) checkout lv_micropython release/v8 branch [`3524`](https://github.com/lvgl/lvgl/pull/3524)
- fix(canvas): fix clipéping on transformation [`b884aba`](https://github.com/lvgl/lvgl/commit/b884abae26f3824b27783a85d18ed51e550347c1)
- fix(draw): allow drawing outline with LV_DRAW_COMPLEX == 0 too [`ece3495`](https://github.com/lvgl/lvgl/commit/ece34950040e218fc73605a4e88f1060c2a274f8)
- fix(colorwheel): fix updating color when using lv_colorwheel_set_hsv [`d59bba1`](https://github.com/lvgl/lvgl/commit/d59bba12db115afb4b6aa53eed2625221dfff2fd)
- fix(slider): find the nearest value on click instead of floor [`dfd14fa`](https://github.com/lvgl/lvgl/commit/dfd14fa778aef25d0db61748a58aa9989ce5e2c8)
- fix(draw): fix border drawing with thick borders [`d5b2a9b`](https://github.com/lvgl/lvgl/commit/d5b2a9b2562cbfa327bf0ec03c11d28576037a14)
- fix(refr): fix true double double buffering logic with transparent screens [`8b605cc`](https://github.com/lvgl/lvgl/commit/8b605cc48224d0497cdd936fa77229e0c3d606d2)
- fix(group): be sure obj is removed from its current group in lv_group_add_obj [`5156ee0`](https://github.com/lvgl/lvgl/commit/5156ee058d5de674a00ffd84d15d460de7f0e53b)
- fix(style): add missing invalidation in lv_obj_remove_local_style_prop [`a0515ba`](https://github.com/lvgl/lvgl/commit/a0515ba30dd74b8b22a6709d334eb03782ee1a4d)
### Docs
- docs(draw) remove reference to old lv_fs_add_drv function [`3564`](https://github.com/lvgl/lvgl/pull/3564)
- docs(disp): LV_COLOR_SCREEN_TRANSP remove dependency on LV_COLOR_DEPTH_32 as transparency is supported across all color depths [`3556`](https://github.com/lvgl/lvgl/pull/3556)
### CI and tests
- ci: protect test.c with #if LV_BUILD_TEST [`be485d7`](https://github.com/lvgl/lvgl/commit/be485d7605136d2a5d6a633c7cb5b7c525cae7ee)
### Others
- chore(rt-thread) backport fixes from v9 [`3604`](https://github.com/lvgl/lvgl/pull/3604)
- chore: fix warnings [`7640950`](https://github.com/lvgl/lvgl/commit/76409502163ffe67cfbab9c7f24f2226cc8a5941)
- remove accidentally added code [`5022476`](https://github.com/lvgl/lvgl/commit/5022476edc8676f2a6ef7b919d3578159edeef7c)
## [v8.3.1](https://github.com/lvgl/lvgl/compare/v8.3.0...v8.3.1) 25 July 2022
### Fixes
- fix(led): add bg_color draw descriptors back to led draw event to support LV_DRAW_COMPLEX 0 [`3515`](https://github.com/lvgl/lvgl/pull/3515)
- fix(slider): fix knob drawing in symmetrical mode [`2967172`](https://github.com/lvgl/lvgl/commit/2967172bee806e77da6ee2307c79e867af3f76bc)
- fix(refr): fix lv_refr_get_top_obj [`9750c97`](https://github.com/lvgl/lvgl/commit/9750c97aff4dc3de80559b150852b829f006d6bf)
- fix(arc): fix arc knob invalidation in SYMMETRICAL mode [`a283273`](https://github.com/lvgl/lvgl/commit/a283273bd27599dae6b044a941b6591ad45e059b)
### Examples
- example(freetype): Update the Micropython example to use the Lato font [`71913d3`](https://github.com/lvgl/lvgl/commit/71913d300dde25d1b87d1b44fa1fa47854defd59)
- example(freetype): replace the arial font with lato to avoid licensing issues [`8544cc3`](https://github.com/lvgl/lvgl/commit/8544cc38062d9c817013bbe6aedbb47112e580ad)
### Docs
- docs(readme): fix LVGL version typo (8.3.0) [`3462`](https://github.com/lvgl/lvgl/pull/3462)
- docs(tasmota): support LVGL 8.3.0 (#3511) [`62662f6`](https://github.com/lvgl/lvgl/commit/62662f68e9cf90adcb96d42030eca5fa135b96a5)
## [v8.3.0](https://github.com/lvgl/lvgl/compare/v8.2.0...v8.3.0) 6 July 2022
### Overview

View File

@@ -52,9 +52,14 @@ In the INO file you can see how to register a display and a touchpad for LVGL an
Note that, there is no dedicated INO file for every example. Instead, you can load an example by calling an `lv_example_...` function. For example `lv_example_btn_1()`.
**IMPORTANT**
**IMPORTANT NOTE 1**
Due to some the limitations of Arduino's build system you need to copy `lvgl/examples` to `lvgl/src/examples`. Similarly for the demos `lvgl/demos` to `lvgl/src/demos`.
**IMPORTANT NOTE 2**
Note that the `lv_examples` library is for LVGL v7 and you shouldn't install it for this version (since LVGL v8)
as the examples and demos are now part of the main LVGL library.
## Debugging and logging
LVGL can display debug information in case of trouble.

View File

@@ -9,6 +9,7 @@
nxp
stm32
espressif
renesas
arduino
tasmota-berry
cmake

View File

@@ -1,6 +1,6 @@
# NXP
NXP has integrated LVGL into the MCUXpresso SDK packages for several of their general purpose and crossover
microcontrollers, allowing easy evaluation and migration into your product design.
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.
@@ -10,42 +10,40 @@ with PXP/VGLite support if the modules are present), no additional integration w
## 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. There is a single NXP draw context that covers both GPUs allowing to have enabled either
one or even both at the same time. While enableing both 2D accelerators, the VGLite can be used to accelerate widget
drawing while the PXP accelerated blit and fill operations.
Supported draw callbacks are available in "src/draw/nxp/lv_gpu_nxp.c":
```c
nxp_draw_ctx->base_draw.draw_arc = lv_draw_nxp_arc;
nxp_draw_ctx->base_draw.draw_rect = lv_draw_nxp_rect;
nxp_draw_ctx->base_draw.draw_img_decoded = lv_draw_nxp_img_decoded;
nxp_draw_ctx->blend = lv_draw_nxp_blend;
```
If enabled both GPUs, the PXP is the preffered one to be used for drawing operation. A fallback mechanism is
implemented so that if the feature is not supported by PXP (or if PXP fails), the VGLite will take over to handle the
task. At the end, the CPU will assure that every widget drawing is fully covered (if not already done by GPU).
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 VGLite (if supported) and CPU are available for
other operations while the PXP is running. An RTOS is required to block the LVGL drawing thread and switch to another
task or suspend the CPU for power savings.
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":
```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;
pxp_draw_ctx->base_draw.buffer_copy = lv_draw_pxp_buffer_copy;
```
#### Features supported:
All operations can be used in conjunction with optional transparency.
- RGB565 and ARGB8888 color formats
- Area fill + optional transparency
- BLIT (BLock Image Transfer) + optional transparency
- Color keying + optional transparency
- Recoloring (color tint) + optional transparency
- Image Rotation (90, 180, 270 degree) + optional transparency
- Recoloring (color tint) + Image Rotation (90, 180, 270 degree) + optional transparency
- 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)
- Buffer copy
- RTOS integration layer
- Default FreeRTOS and bare metal code provided
- Combination of recolor and/or rotation + color key/alpha blend/transparency is supported but PXP needs two steps.
First step is to recolor/rotate the image to a temporarly buffer (please check LV_MEM_SIZE value for allocation limit)
and another step is required to handle color keying, alpha chanel or to apply transparency.
- 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.
@@ -78,51 +76,71 @@ and the final output image can look shifted.
#### Project setup:
- Add PXP related files to project:
- src/draw/nxp/pxp/lv_gpu_nxp_pxp.c, src/draw/nxp/pxp/lv_gpu_nxp_pxp.h: init, uninit, run/wait PXP device, log/trace
- src/draw/nxp/pxp/lv_draw_pxp_blend.c, src/draw/nxp/pxp/lv_draw_pxp_blend.h: fill and blit (w/o transformation)
- src/draw/nxp/pxp/lv_gpu_nxp_osa.c, src/draw/nxp/pxp/lv_gpu_osa.h: default implementation of OS-specific functions
(bare metal and FreeRTOS only)
- 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)
- optional, required only if `LV_USE_GPU_NXP_PXP_AUTO_INIT` is set to 1
- PXP related code depends on two drivers provided by MCU SDK. These drivers need to be added to project:
- fsl_pxp.c, fsl_pxp.h: PXP driver
- fsl_cache.c, fsl_cache.h: CPU cache handling functions
- fsl_pxp.c[.h]: PXP driver
- fsl_cache.c[.h]: CPU cache handling functions
#### Logging:
- By default, LV_GPU_NXP_PXP_LOG_ERRORS is enabled so that any PXP error will be seen on LVGL output
- For tracing logs about the PXP limitations or size thresholds, the user can enable LV_GPU_NXP_PXP_LOG_TRACES
- By default, `LV_GPU_NXP_PXP_LOG_ERRORS` is enabled so that any PXP error will be seen on SDK debug console
- By default, `LV_GPU_NXP_PXP_LOG_TRACES` is disabled. Enable it for tracing logs (like PXP limitations)
#### Advanced configuration:
- Implementation depends on multiple OS-specific functions. The struct `lv_nxp_pxp_cfg_t` with callback pointers is
used as a parameter for the `lv_gpu_nxp_pxp_init()` function. Default implementation for FreeRTOS and baremetal is
provided in lv_gpu_nxp_osa.c
used as a parameter for the `lv_gpu_nxp_pxp_init()` function. Default implementation for FreeRTOS and bare metal is
provided in lv_gpu_nxp_pxp_osa.c
- `pxp_interrupt_init()`: Initialize PXP interrupt (HW setup, OS setup)
- `pxp_interrupt_deinit()`: Deinitialize PXP interrupt (HW setup, OS setup)
- `pxp_run()`: Start PXP job. Use OS-specific mechanism to block drawing thread. PXP must finish drawing before
leaving this function.
- There are configurable area thresholds which are used to decide whether the area will be processed by CPU or by PXP.
Areas smaller than a defined value will be processed by CPU and those bigger than the threshold will be processed by
PXP. These thresholds may be defined as preprocessor variables. Default values are defined in lv_draw_pxp_blend.h
- `LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT`: size threshold for image BLIT, BLIT with color keying, BLIT with recolor and
BLIT with rotation (OPA >= LV_OPA_MAX)
- `LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT`: size threshold for image BLIT, BLIT with color keying, BLIT with recolor
and BLIT with rotation and transparency (OPA < LV_OPA_MAX)
- `LV_GPU_NXP_PXP_FILL_SIZE_LIMIT`: size threshold for fill operation (OPA >= LV_OPA_MAX)
- `LV_GPU_NXP_PXP_FILL_OPA_SIZE_LIMIT`: size threshold for fill operation with transparency (OPA < LV_OPA_MAX)
- 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
- `LV_GPU_NXP_PXP_SIZE_LIMIT`: size threshold for fill/blit (with optional transformation)
### VGLite accelerator
Extra drawing features in LVGL can be handled by the VGLite engine. The PXP (if supported) and CPU are 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.
Extra drawing features in LVGL can be handled by the VGLite engine. The 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":
```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;
vglite_draw_ctx->base_draw.buffer_copy = lv_draw_vglite_buffer_copy;
```
#### Features supported:
All operations can be used in conjunction with optional transparency.
- RGB565 and ARGB8888 color formats
- Area fill + optional transparency
- BLIT (BLock Image Transfer) + optional transparency
- Image Rotation (any degree with decimal) + optional transparency
- Image Scale + optional transparency
- Draw background rectangle with radius or gradient
- Draw arc
- RTOS integration layer
- 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
- Buffer copy
#### Known limitations:
- Source image alignment:
The byte alignment requirement for a pixel depends on the specific pixel format. Both buffer address and buffer stride
must be aligned. As general rule, the alignment is set to 16 pixels. This makes the buffer address alignment to be
32 bytes for RGB565 and 64 bytes for ARGB8888.
- For pixel engine (PE) destination, the alignment should be 64 bytes for all tiled (4x4) buffer layouts.
The pixel engine has no additional alignment requirement for linear buffer layouts (`VG_LITE_LINEAR`).
#### Basic configuration:
- Select NXP VGLite engine in lv_conf.h: Set `LV_USE_GPU_NXP_VG_LITE` to 1
@@ -130,8 +148,8 @@ task or suspend the CPU for power savings.
#### Basic initialization:
- Initialize VGLite before calling `lv_init()` by specifying the width/height of tessellation window. Value should be
a multiple of 16; minimum value is 16 pixels, maximum cannot be greater than frame width. If less than or equal to 0,
then no tessellation buffer is created, in which case the function is used for a blit init.
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.
```c
#if LV_USE_GPU_NXP_VG_LITE
#include "vg_lite.h"
@@ -144,25 +162,21 @@ task or suspend the CPU for power savings.
#### Project setup:
- Add VGLite related files to project:
- src/draw/nxp/vglite/lv_gpu_nxp_vglite.c, src/draw/nxp/vglite/lv_gpu_nxp_vglite.h: buffer init, log/trace
- src/draw/nxp/vglite/lv_draw_vglite_blend.c, src/draw/nxp/vglite/lv_draw_vglite_blend.h: fill and blit
(w/o transformation)
- src/draw/nxp/vglite/lv_draw_vglite_rect.c, src/draw/nxp/vglite/lv_draw_vglite_rect.h: rectangle draw
- src/draw/nxp/vglite/lv_draw_vglite_arc.c, src/draw/nxp/vglite/lv_draw_vglite_arc.h: arc draw
- 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
#### Logging:
- By default, LV_GPU_NXP_VG_LITE_LOG_ERRORS is enabled so that any VGLite error will be seen on LVGL output
- For tracing logs about the VGLite limitations, size thresholds or stride alignment, the user can enable
LV_GPU_NXP_VG_LITE_LOG_TRACES
- By default, `LV_GPU_NXP_VG_LITE_LOG_ERRORS` is enabled so that any VGLite error will be seen on SDK debug console
- By default, `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)
#### Advanced configuration:
- There are configurable area thresholds which are used to decide whether the area will be processed by CPU or by
VGLite. Areas smaller than a defined value will be processed by CPU and those bigger than the threshold will be
processed by VGLite. These thresholds may be defined as preprocessor variables. Default values are defined in
lv_draw_vglite_blend.h
- `LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT`: size threshold for image BLIT, BLIT with scale and BLIT with rotation
(OPA >= LV_OPA_MAX)
- `LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT`: size threshold for image BLIT, BLIT with scale and BLIT with rotation
and transparency (OPA < LV_OPA_MAX)
- `LV_GPU_NXP_VG_LITE_FILL_SIZE_LIMIT`: size threshold for fill operation (OPA >= LV_OPA_MAX)
- `LV_GPU_NXP_VG_LITE_FILL_OPA_SIZE_LIMIT`: size threshold for fill operation with transparency (OPA < LV_OPA_MAX)
- 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
- `LV_GPU_NXP_VG_LITE_SIZE_LIMIT`: size threshold for fill/blit (with optional transformation)

View File

@@ -0,0 +1,129 @@
# Renesas
The [HMI-Board](https://bit.ly/3I9nfUo) development board SDK now comes with LVGL integration for quick evaluation. Simply download the [SDK](https://github.com/RT-Thread-Studio/sdk-bsp-ra6m3-hmi-board/tree/main/projects/hmi-board-lvgl) for the supported motherboard and youll be on your way to creating your next GUI application in no time. For more information, check out the [Software design description](https://github.com/RT-Thread-Studio/sdk-bsp-ra6m3-hmi-board/blob/main/projects/hmi-board-lvgl/README.md).
## Creating new project with LVGL
It is recommended to start your project by downloading the HMI-Board SDK example project. It comes fully equipped with LVGL and dave-2d support (if the modules are present), so you wont need to do any additional integration work.
## HW acceleration for Renesas RA6M3 platforms
For RA6M3 platforms, hardware acceleration can be achieved using the dave-2d GPU, depending on the platform used. Each accelerator has its own context, allowing them to be used individually or simultaneously in LVGLs multithreading mode.
### Dave-2d accelerator
LVGL can offload several drawing features to the dave-2d engine, freeing up the CPU for other operations while dave-2d runs. 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 can be found in “src/draw/renesas/lv_gpu_d2_ra6m3.c”.
LVGL can offload several drawing features to the dave-2d engine, freeing up the CPU for other operations while dave-2d runs. 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 can be found in “src/draw/renesas/lv_gpu_d2_ra6m3.c”.
```c
ra_2d_draw_ctx->blend = lv_draw_ra6m3_2d_blend;
ra_2d_draw_ctx->base_draw.draw_img_decoded = lv_port_gpu_img_decoded;
ra_2d_draw_ctx->base_draw.wait_for_finish = lv_port_gpu_wait;
ra_2d_draw_ctx->base_draw.draw_letter = lv_draw_gpu_letter;
```
### 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)
- Color conversion
- Rotate and scale
- Alpha blending
- Bilinear filtering
- RTOS integration layer
- Default RT-Thread code provided
- Subpixel exact placement
### Basic configuration:
- Select Renesas dave-2d engine in lv_conf.h: Set `LV_USE_GPU_RA6M3_G2D` to 1
- Set referenced header file in lv_conf.h: `#define LV_GPU_RA6M3_G2D_INCLUDE "hal_data.h"`
### RT-Thread Example:
```c
#define COLOR_BUFFER (LV_HOR_RES_MAX * LV_VER_RES_MAX)
static lv_disp_drv_t disp_drv;
/*A static or global variable to store the buffers*/
static lv_color_t buf_1[COLOR_BUFFER];
```
- After initializing your peripherals (such as SPI, GPIOs, and LCD) in the `lv_port_disp_init()` function, you can initialize LVGL using [`lv_init()`.](https://docs.lvgl.io/master/API/core/lv_obj.html#_CPPv47lv_initv) Next, register the frame buffers using `lv_disp_draw_buf_init()` and create a new display driver using `lv_disp_drv_init()`.
```c
/*Initialize `disp_buf` with the buffer(s). With only one buffer use NULL instead buf_2 */
lv_disp_draw_buf_init(&disp_buf, buf_1, RT_NULL, COLOR_BUFFER);
lv_disp_drv_init(&disp_drv); /*Basic initialization*/
/*Set the resolution of the display*/
disp_drv.hor_res = LV_HOR_RES_MAX;
disp_drv.ver_res = LV_VER_RES_MAX;
/*Set a display buffer*/
disp_drv.draw_buf = &disp_buf;
/*Used to copy the buffer's content to the display*/
disp_drv.flush_cb = disp_flush;
/* Initialize GPU module */
lv_port_gpu_hw_init();
/*Finally register the driver*/
lv_disp_drv_register(&disp_drv);
```
* To run LVGL, youll need to create a thread. You can find examples of how to do this using RT-Thread in the `env_support/rt-thread/lv_rt_thread_port.c` file.
```c
static void lvgl_thread_entry(void *parameter)
{
#if LV_USE_LOG
lv_log_register_print_cb(lv_rt_log);
#endif /* LV_USE_LOG */
lv_init();
lv_port_disp_init();
lv_port_indev_init();
lv_user_gui_init();
/* handle the tasks of LVGL */
while(1)
{
lv_task_handler();
rt_thread_mdelay(LV_DISP_DEF_REFR_PERIOD);
}
}
static int lvgl_thread_init(void)
{
rt_err_t err;
/* create lvgl thread */
err = rt_thread_init(&lvgl_thread, "LVGL", lvgl_thread_entry, RT_NULL,
&lvgl_thread_stack[0], sizeof(lvgl_thread_stack), PKG_LVGL_THREAD_PRIO, 10);
if(err != RT_EOK)
{
LOG_E("Failed to create LVGL thread");
return -1;
}
rt_thread_startup(&lvgl_thread);
return 0;
}
INIT_ENV_EXPORT(lvgl_thread_init);
```
- The last step is to create a function to output the frame buffer to your LCD. The specifics of this function will depend on the features of your MCU. Heres an example for a typical MCU interface: `my_flush_cb`.
```c
static void my_flush_cb(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p)
{
#ifdef PKG_USING_ILI9341
lcd_fill_array_spi(area->x1, area->y1, area->x2, area->y2, color_p);
#elif LV_USE_GPU_RA6M3_G2D
lv_port_gpu_blit(area->x1, area->y1, color_p, area);
#else
......
#endif
lv_disp_flush_ready(disp_drv);
}
```

View File

@@ -31,7 +31,7 @@ In 2021, Tasmota added full support of LVGL for ESP32 based devices. It also int
A comprehensive mapping of LVGL in Berry language is now available, similar to the mapping of Micropython. It allows to use +98% of all LVGL features. It is also possible to write custom widgets in Berry.
Versions supported: LVGL v8.0.2, LodePNG v20201017, Freetype 2.10.4
Versions supported: LVGL v8.3.0, LodePNG v20201017, Freetype 2.10.4
### Tasmota + Berry + LVGL could be used for:

View File

@@ -132,7 +132,7 @@ LVGL needs just one simple driver function to copy an array of pixels into a giv
If you can do this with your display then you can use it with LVGL.
Some examples of the supported display types:
- TFTs with 16 or 24 bit color depth
- TFTs with 16 or 32 bit color depth
- Monitors with an HDMI port
- Small monochrome displays
- Gray-scale displays

View File

@@ -63,11 +63,10 @@ See the [Display background](#display-background) section for more details. If t
This configuration (transparent screen and display) could be used to create for example OSD menus where a video is played on a lower layer, and a menu is overlayed on an upper layer.
To handle transparent displays, special (slower) color mixing algorithms need to be used by LVGL so this feature needs to enabled with `LV_COLOR_SCREEN_TRANSP` in `lv_conf.h`.
As this mode operates on the Alpha channel of the pixels `LV_COLOR_DEPTH = 32` is also required. The Alpha channel of 32-bit colors will be 0 where there are no objects and 255 where there are solid objects.
The Alpha channel of 32-bit colors will be 0 where there are no objects and 255 where there are solid objects.
In summary, to enable transparent screens and displays for OSD menu-like UIs:
- Enable `LV_COLOR_SCREEN_TRANSP` in `lv_conf.h`
- Be sure to use `LV_COLOR_DEPTH 32`
- Set the screen's opacity to `LV_OPA_TRANSP` e.g. with `lv_obj_set_style_local_bg_opa(lv_scr_act(), LV_OBJMASK_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP)`
- Set the display opacity to `LV_OPA_TRANSP` with `lv_disp_set_bg_opa(NULL, LV_OPA_TRANSP);`

View File

@@ -34,11 +34,11 @@ lv_label_set_text(label2, "Button 2"); /*Set the text of the label*/
lv_obj_del(label2);
```
## Bring to the foreground
## Change order
There are four explicit ways to bring an object to the foreground:
- Use `lv_obj_move_foreground(obj)` to bring an object to the foreground. Similarly, use `lv_obj_move_background(obj)` to move it to the background.
- Use `lv_obj_move_up(obj)` to move an object one position up in the hierarchy, Similarly, use `lv_obj_move_down(obj)` to move an object one position down in the hierarchy.
- Use `lv_obj_move_to_index(obj, idx)` to move an object to a given index in the order of children. (0: backgroud, child_num - 1: foreground, <0: count from the top, to move forward (up): `lv_obj_move_to_index(obj, lv_obj_get_index(obj) - 1)`)
- Use `lv_obj_swap(obj1, obj2)` to swap the relative layer position of two objects.
- When `lv_obj_set_parent(obj, new_parent)` is used, `obj` will be on the foreground of the `new_parent`.

View File

@@ -1,4 +1,32 @@
# ARM-2D GPU
# Arm-2D GPU
TODO
Arm-2D is not a GPU but **an abstraction layer for 2D GPUs dedicated to Microcontrollers**. It supports all Cortex-M processors ranging from Cortex-M0 to the latest Cortex-M85.
Arm-2D is an open-source project on Github. For more, please refer to: https://github.com/ARM-software/Arm-2D.
## How to Use
In general, you can set the macro `LV_USE_GPU_ARM2D` to `1`in `lv_conf.h` to enable Arm-2D acceleration for LVGL.
If you are using **[CMSIS-Pack](https://github.com/lvgl/lvgl/tree/master/env_support/cmsis-pack)** to deploy the LVGL. You don't have to define the macro `LV_USE_GPU_ARM2D` manually, instead, please select the component `GPU Arm-2D` in the **RTE** dialog. This step will define the macro for us.
## Design Considerations
As mentioned before, Arm-2D is an abstraction layer for 2D GPU; hence if there is no accelerator or dedicated instruction set (such as Helium or ACI) available for Arm-2D, it provides negligible performance boost for LVGL (sometimes worse) for regular Cortex-M processors.
**We highly recommend you enable Arm-2D acceleration for LVGL** when:
- The target processors are **Cortex-M55** and/or **Cortex-M85**
- The target processors support **[Helium](https://developer.arm.com/documentation/102102/0103/?lang=en)**.
- The device vendor provides an arm-2d compliant driver for their propriotory 2D accelerators and/or customized instruction set.
- The target device contains [DMA-350](https://community.arm.com/arm-community-blogs/b/internet-of-things-blog/posts/arm-corelink-dma-350-next-generation-direct-memory-access-for-endpoint-ai)
## Examples
- [A Cortex-M55 (supports Helium) based MDK Project, PC emulation is available.](https://github.com/lvgl/lv_port_an547_cm55_sim)

View File

@@ -204,6 +204,8 @@ The default rotation of your display when it is initialized can be set using the
Display rotation can also be changed at runtime using the `lv_disp_set_rotation(disp, rot)` API.
Note that when using software rotation, you cannot use neither `direct_mode` nor `full_refresh` in the driver. When using either of these, you will have to rotate the pixels yourself e.g. in the `flush_cb`.
Support for software rotation is a new feature, so there may be some glitches/bugs depending on your configuration. If you encounter a problem please open an issue on [GitHub](https://github.com/lvgl/lvgl/issues).
### Decoupling the display refresh timer

View File

@@ -114,7 +114,7 @@ You need to have 3 buttons available:
- `LV_KEY_RIGHT` will simulate turning encoder right
- other keys will be passed to the focused widget
If you hold the keys it will simulate an encoder advance with period specified in `indev_drv.long_press_rep_time`.
If you hold the keys it will simulate an encoder advance with period specified in `indev_drv.long_press_repeat_time`.
```c
indev_drv.type = LV_INDEV_TYPE_ENCODER;
@@ -172,7 +172,7 @@ The default value of the following parameters can be changed in `lv_indev_drv_t`
- `scroll_limit` Number of pixels to slide before actually scrolling the object.
- `scroll_throw` Scroll throw (momentum) slow-down in [%]. Greater value means faster slow-down.
- `long_press_time` Press time to send `LV_EVENT_LONG_PRESSED` (in milliseconds)
- `long_press_rep_time` Interval of sending `LV_EVENT_LONG_PRESSED_REPEAT` (in milliseconds)
- `long_press_repeat_time` Interval of sending `LV_EVENT_LONG_PRESSED_REPEAT` (in milliseconds)
- `read_timer` pointer to the `lv_timer` which reads the input device. Its parameters can be changed by `lv_timer_...()` functions. `LV_INDEV_DEF_READ_PERIOD` in `lv_conf.h` sets the default read period.
### Feedback

View File

@@ -25,7 +25,7 @@ So in the example the first row will have 2 buttons each with 50% width and a se
The buttons' width can be set relative to the other button in the same row with `lv_btnmatrix_set_btn_width(btnm, btn_id, width)`
E.g. in a line with two buttons: *btnA, width = 1* and *btnB, width = 2*, *btnA* will have 33 % width and *btnB* will have 66 % width.
It's similar to how the [`flex-grow`](https://developer.mozilla.org/en-US/docs/Web/CSS/flex-grow) property works in CSS.
The width must be in the \[1..7\] range and the default width is 1.
The width must be in the \[1..15\] range and the default width is 1.
In addition to the width, each button can be customized with the following parameters:
- `LV_BTNMATRIX_CTRL_HIDDEN` Makes a button hidden (hidden buttons still take up space in the layout, they are just not visible or clickable)

View File

@@ -12,22 +12,43 @@ if(LV_MICROPYTHON)
${LVGL_ROOT_DIR}/../
REQUIRES
main)
target_compile_definitions(${COMPONENT_LIB}
INTERFACE "-DLV_CONF_INCLUDE_SIMPLE")
if(CONFIG_LV_ATTRIBUTE_FAST_MEM_USE_IRAM)
target_compile_definitions(${COMPONENT_LIB}
INTERFACE "-DLV_ATTRIBUTE_FAST_MEM=IRAM_ATTR")
endif()
else()
idf_component_register(SRCS ${SOURCES} INCLUDE_DIRS ${LVGL_ROOT_DIR}
${LVGL_ROOT_DIR}/src ${LVGL_ROOT_DIR}/../)
target_compile_definitions(${COMPONENT_LIB} PUBLIC "-DLV_CONF_INCLUDE_SIMPLE")
if(CONFIG_LV_ATTRIBUTE_FAST_MEM_USE_IRAM)
target_compile_definitions(${COMPONENT_LIB}
PUBLIC "-DLV_ATTRIBUTE_FAST_MEM=IRAM_ATTR")
if(CONFIG_LV_BUILD_EXAMPLES)
file(GLOB_RECURSE EXAMPLE_SOURCES ${LVGL_ROOT_DIR}/examples/*.c)
set_source_files_properties(${EXAMPLE_SOURCES} COMPILE_FLAGS "-Wno-unused-variable -Wno-format")
endif()
if(CONFIG_LV_USE_DEMO_WIDGETS)
file(GLOB_RECURSE DEMO_WIDGETS_SOURCES ${LVGL_ROOT_DIR}/demos/widgets/*.c)
list(APPEND DEMO_SOURCES ${DEMO_WIDGETS_SOURCES})
endif()
if(CONFIG_LV_USE_DEMO_KEYPAD_AND_ENCODER)
file(GLOB_RECURSE DEMO_KEYPAD_AND_ENCODER_SOURCES ${LVGL_ROOT_DIR}/demos/keypad_encoder/*.c)
list(APPEND DEMO_SOURCES ${DEMO_KEYPAD_AND_ENCODER_SOURCES})
endif()
if(CONFIG_LV_USE_DEMO_BENCHMARK)
file(GLOB_RECURSE DEMO_BENCHMARK_SOURCES ${LVGL_ROOT_DIR}/demos/benchmark/*.c)
list(APPEND DEMO_SOURCES ${DEMO_BENCHMARK_SOURCES})
endif()
if(CONFIG_LV_USE_DEMO_STRESS)
file(GLOB_RECURSE DEMO_STRESS_SOURCES ${LVGL_ROOT_DIR}/demos/stress/*.c)
list(APPEND DEMO_SOURCES ${DEMO_STRESS_SOURCES})
endif()
if(CONFIG_LV_USE_DEMO_MUSIC)
file(GLOB_RECURSE DEMO_MUSIC_SOURCES ${LVGL_ROOT_DIR}/demos/music/*.c)
list(APPEND DEMO_SOURCES ${DEMO_MUSIC_SOURCES})
set_source_files_properties(${DEMO_MUSIC_SOURCES} COMPILE_FLAGS "-Wno-format")
endif()
idf_component_register(SRCS ${SOURCES} ${EXAMPLE_SOURCES} ${DEMO_SOURCES}
INCLUDE_DIRS ${LVGL_ROOT_DIR} ${LVGL_ROOT_DIR}/src ${LVGL_ROOT_DIR}/../
${LVGL_ROOT_DIR}/examples ${LVGL_ROOT_DIR}/demos
REQUIRES esp_timer)
endif()
target_compile_definitions(${COMPONENT_LIB} PUBLIC "-DLV_CONF_INCLUDE_SIMPLE")
if(CONFIG_LV_ATTRIBUTE_FAST_MEM_USE_IRAM)
target_compile_definitions(${COMPONENT_LIB}
PUBLIC "-DLV_ATTRIBUTE_FAST_MEM=IRAM_ATTR")
endif()

View File

@@ -20,7 +20,7 @@
-->
<package schemaVersion="1.4" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:noNamespaceSchemaLocation="PACK.xsd">
<package schemaVersion="1.4" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:noNamespaceSchemaLocation="https://raw.githubusercontent.com/Open-CMSIS-Pack/Open-CMSIS-Pack-Spec/v1.7.7/schema/PACK.xsd">
<vendor>LVGL</vendor>
<name>lvgl</name>
<description>LVGL (Light and Versatile Graphics Library) is a free and open-source graphics library providing everything you need to create an embedded GUI with easy-to-use graphical elements, beautiful visual effects and a low memory footprint.</description>
@@ -36,12 +36,31 @@
<repository type="git">https://github.com/lvgl/lvgl.git</repository>
<releases>
<release date="2022-07-06" version="1.0.6" url="https://raw.githubusercontent.com/lvgl/lvgl/master/env_support/cmsis-pack/LVGL.lvgl.1.0.6.pack">
- LVGL 8.3.0 release
- Apply patch for memory leaking issue
- Apply patch to speed up non normal blend mode
- Add 9-key input mode to pinyin
- Other minor changes
<release date="2023-07-04" version="8.3.8" url="https://raw.githubusercontent.com/lvgl/lvgl/master/env_support/cmsis-pack/LVGL.lvgl.8.3.8.pack">
- LVGL 8.3.8
- Add renesas-ra6m3 gpu adaptation
- Improve performance and add more features for PXP and VGLite
- Minor updates
</release>
<release date="2023-04-28" version="8.3.7" url="https://github.com/lvgl/lvgl/raw/2b56e04205481daa6575bd5f7ab5df59d11676eb/env_support/cmsis-pack/LVGL.lvgl.8.3.7.pack">
- LVGL 8.3.7
- Minor updates
</release>
<release date="2023-04-02" version="8.3.6" url="https://github.com/lvgl/lvgl/raw/6b0092c0d91b2c7bfded48e04cc7b486ed3a72bd/env_support/cmsis-pack/LVGL.lvgl.8.3.6.pack">
- LVGL 8.3.6 release
- Various fixes, See CHANGELOG.md
</release>
<release date="2023-02-06" version="8.3.5" url="https://github.com/lvgl/lvgl/raw/e7e8cf846dce96f7542e27b5c9655bab680c31a1/env_support/cmsis-pack/LVGL.lvgl.8.3.5.pack">
- LVGL 8.3.5 release
- Use LVGL version as the cmsis-pack version
- Fix GPU support for NXP PXP and NXP VGLite
- Rework stm32 DMA2D support
- Various fixes
</release>
<release date="2022-12-31" version="1.0.6-p1" url="https://github.com/lvgl/lvgl/raw/dbb15bb3ea0365373bc1ba8b182556f937e61e7d/env_support/cmsis-pack/LVGL.lvgl.1.0.6-p1.pack">
- LVGL 8.3.4 release
- Update GPU Arm-2D support
- Various fixes
</release>
<release date="2022-06-29" version="1.0.5" url="https://github.com/GorgonMeducer/lvgl/raw/922108dbbe6d1c0be1069c342ca8693afee8c169/env_support/cmsis-pack/LVGL.lvgl.1.0.5.pack">
- LVGL 8.3.0-dev
@@ -159,6 +178,90 @@
<require Cclass="Acceleration" Cgroup="Arm-2D"/>
</condition>
<condition id="LVGL-GPU-Arm-2D">
<description>Enable LVGL Arm-2D GPU Support</description>
<require Cclass="LVGL" Cgroup="lvgl" Csub="Essential"/>
<!--<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU Arm-2D"/>-->
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU STM32-DMA2D"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU SWM341-DMA2D"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU NXP-PXP"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU NXP-VGLite"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU GD32-IPA"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="LVGL-GPU-RA6M3-G2D"/>
</condition>
<condition id="LVGL-GPU-STM32-DMA2D">
<description>Enable LVGL Arm-2D GPU Support</description>
<require Cclass="LVGL" Cgroup="lvgl" Csub="Essential"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU Arm-2D"/>
<!--<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU STM32-DMA2D"/>-->
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU SWM341-DMA2D"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU NXP-PXP"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU NXP-VGLite"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU GD32-IPA"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="LVGL-GPU-RA6M3-G2D"/>
</condition>
<condition id="LVGL-GPU-SWM341-DMA2D">
<description>Enable LVGL Arm-2D GPU Support</description>
<require Cclass="LVGL" Cgroup="lvgl" Csub="Essential"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU Arm-2D"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU STM32-DMA2D"/>
<!--<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU SWM341-DMA2D"/>-->
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU NXP-PXP"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU NXP-VGLite"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU GD32-IPA"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="LVGL-GPU-RA6M3-G2D"/>
</condition>
<condition id="LVGL-GPU-NXP-PXP">
<description>Enable LVGL Arm-2D GPU Support</description>
<require Cclass="LVGL" Cgroup="lvgl" Csub="Essential"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU Arm-2D"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU STM32-DMA2D"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU SWM341-DMA2D"/>
<!--<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU NXP-PXP"/>-->
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU NXP-VGLite"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU GD32-IPA"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="LVGL-GPU-RA6M3-G2D"/>
</condition>
<condition id="LVGL-GPU-NXP-VGLite">
<description>Enable LVGL Arm-2D GPU Support</description>
<require Cclass="LVGL" Cgroup="lvgl" Csub="Essential"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU Arm-2D"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU STM32-DMA2D"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU SWM341-DMA2D"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU NXP-PXP"/>
<!--<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU NXP-VGLite"/>-->
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU GD32-IPA"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="LVGL-GPU-RA6M3-G2D"/>
</condition>
<condition id="LVGL-GPU-GD32-IPA">
<description>Enable LVGL Arm-2D GPU Support</description>
<require Cclass="LVGL" Cgroup="lvgl" Csub="Essential"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU Arm-2D"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU STM32-DMA2D"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU SWM341-DMA2D"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU NXP-PXP"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU NXP-VGLite"/>
<!--<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU GD32-IPA"/>-->
<deny Cclass="LVGL" Cgroup="lvgl" Csub="LVGL-GPU-RA6M3-G2D"/>
</condition>
<condition id="LVGL-GPU-RA6M3-G2D">
<description>Enable LVGL Arm-2D GPU Support</description>
<require Cclass="LVGL" Cgroup="lvgl" Csub="Essential"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU Arm-2D"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU STM32-DMA2D"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU SWM341-DMA2D"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU NXP-PXP"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU NXP-VGLite"/>
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU GD32-IPA"/>
<!--<deny Cclass="LVGL" Cgroup="lvgl" Csub="LVGL-GPU-RA6M3-G2D"/>-->
</condition>
</conditions>
<!-- apis section (optional - for Application Programming Interface descriptions) -->
<!--
@@ -191,7 +294,7 @@
-->
<components>
<bundle Cbundle="LVGL" Cclass="LVGL" Cversion="8.3.0">
<bundle Cbundle="LVGL" Cclass="LVGL" Cversion="8.3.8">
<description>LVGL (Light and Versatile Graphics Library) is a free and open-source graphics library providing everything you need to create an embedded GUI with easy-to-use graphical elements, beautiful visual effects and a low memory footprint.</description>
<doc></doc>
<component Cgroup="lvgl" Csub="Essential" >
@@ -324,10 +427,18 @@
<file category="sourceC" name="src/widgets/lv_textarea.c" />
<!-- general -->
<file category="preIncludeGlobal" name="lv_conf_cmsis.h" attr="config" version="1.0.2" />
<file category="preIncludeGlobal" name="lv_conf_cmsis.h" attr="config" version="1.0.3" />
<file category="sourceC" name="lv_cmsis_pack.c" attr="config" version="1.0.0" />
<file category="header" name="lvgl.h" />
<file category="doc" name="README.md"/>
<!-- code template -->
<file category="header" name="examples/porting/lv_port_disp_template.h" attr="template" select="Display port template" version="2.0.0"/>
<file category="sourceC" name="examples/porting/lv_port_disp_template.c" attr="template" select="Display port template" version="2.0.0"/>
<file category="header" name="examples/porting/lv_port_indev_template.h" attr="template" select="Input devices port template" version="2.0.0"/>
<file category="sourceC" name="examples/porting/lv_port_indev_template.c" attr="template" select="Input devices port template" version="2.0.0"/>
<file category="header" name="examples/porting/lv_port_fs_template.h" attr="template" select="File system port template" version="2.0.0"/>
<file category="sourceC" name="examples/porting/lv_port_fs_template.c" attr="template" select="File system port template" version="2.0.0"/>
</files>
@@ -360,7 +471,7 @@
</files>
</component>
<component Cgroup="lvgl" Csub="GPU Arm-2D" condition="LVGL-Essential" Cversion="1.0.3">
<component Cgroup="lvgl" Csub="GPU Arm-2D" condition="LVGL-GPU-Arm-2D" Cversion="1.2.2">
<description>A 2D image processing library from Arm (i.e. Arm-2D) for All Cortex-M processors including Cortex-M0</description>
<files>
<file category="sourceC" name="src/draw/arm2d/lv_gpu_arm2d.c" condition="Arm-2D"/>
@@ -375,7 +486,7 @@
</component>
<component Cgroup="lvgl" Csub="GPU STM32-DMA2D" condition="LVGL-Essential">
<component Cgroup="lvgl" Csub="GPU STM32-DMA2D" condition="LVGL-GPU-STM32-DMA2D">
<description>An hardware acceleration from STM32-DMA2D</description>
<files>
<file category="sourceC" name="src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.c" />
@@ -389,7 +500,7 @@
</component>
<component Cgroup="lvgl" Csub="GPU SWM341-DMA2D" condition="LVGL-Essential">
<component Cgroup="lvgl" Csub="GPU SWM341-DMA2D" condition="LVGL-GPU-SWM341-DMA2D">
<description>An hardware acceleration from SWM341-DMA2D</description>
<files>
<file category="sourceC" name="src/draw/swm341_dma2d/lv_gpu_swm341_dma2d.c" />
@@ -403,13 +514,13 @@
</component>
<component Cgroup="lvgl" Csub="GPU NXP-PXP" condition="LVGL-Essential">
<component Cgroup="lvgl" Csub="GPU NXP-PXP" condition="LVGL-GPU-NXP-PXP">
<description>An hardware acceleration from NXP-PXP</description>
<files>
<file category="sourceC" name="src/draw/nxp/lv_gpu_nxp.c" />
<file category="sourceC" name="src/draw/nxp/pxp/lv_draw_pxp_blend.c" />
<file category="sourceC" name="src/draw/nxp/pxp/lv_gpu_nxp_pxp.c" />
<file category="sourceC" name="src/draw/nxp/pxp/lv_gpu_nxp_pxp_osa.c" />
<file category="sourceC" name="src/draw/nxp/pxp/lv_draw_pxp.c" />
<file category="sourceC" name="src/draw/nxp/pxp/lv_draw_pxp_blend.c" />
<file category="sourceC" name="src/draw/nxp/pxp/lv_gpu_nxp_pxp.c" />
<file category="sourceC" name="src/draw/nxp/pxp/lv_gpu_nxp_pxp_osa.c" />
</files>
<RTE_Components_h>
@@ -420,14 +531,16 @@
</component>
<component Cgroup="lvgl" Csub="GPU NXP-VGLite" condition="LVGL-Essential">
<component Cgroup="lvgl" Csub="GPU NXP-VGLite" condition="LVGL-GPU-NXP-VGLite">
<description>An hardware acceleration from NXP-VGLite</description>
<files>
<file category="sourceC" name="src/draw/nxp/lv_gpu_nxp.c" />
<file category="sourceC" name="src/draw/nxp/vglite/lv_draw_vglite_arc.c" />
<file category="sourceC" name="src/draw/nxp/vglite/lv_draw_vglite_blend.c" />
<file category="sourceC" name="src/draw/nxp/vglite/lv_draw_vglite_rect.c" />
<file category="sourceC" name="src/draw/nxp/vglite/lv_gpu_nxp_vglite.c" />
<file category="sourceC" name="src/draw/nxp/vglite/lv_draw_vglite.c" />
<file category="sourceC" name="src/draw/nxp/vglite/lv_draw_vglite_arc.c" />
<file category="sourceC" name="src/draw/nxp/vglite/lv_draw_vglite_blend.c" />
<file category="sourceC" name="src/draw/nxp/vglite/lv_draw_vglite_line.c" />
<file category="sourceC" name="src/draw/nxp/vglite/lv_draw_vglite_rect.c" />
<file category="sourceC" name="src/draw/nxp/vglite/lv_vglite_buf.c" />
<file category="sourceC" name="src/draw/nxp/vglite/lv_vglite_utils.c" />
</files>
<RTE_Components_h>
@@ -438,6 +551,22 @@
</component>
<component Cgroup="lvgl" Csub="GPU RA6M3-G2D" condition="LVGL-GPU-RA6M3-G2D">
<description>An hardware acceleration from Renesas RA6M3-G2D</description>
<files>
<file category="sourceC" name="src/draw/renesas/lv_gpu_d2_draw_label.c" />
<file category="sourceC" name="src/draw/renesas/lv_gpu_d2_ra6m3.c" />
</files>
<RTE_Components_h>
/*! \brief enable RA6M3-G2D */
#define LV_USE_GPU_RA6M3_G2D 1
</RTE_Components_h>
</component>
<component Cgroup="lvgl" Csub="Extra Themes" condition="LVGL-Essential">
<description>Extra Themes, Widgets and Layouts</description>
<files>

View File

@@ -2,8 +2,8 @@
<index schemaVersion="1.0.0" xs:noNamespaceSchemaLocation="PackIndex.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance">
<vendor>LVGL</vendor>
<url>https://raw.githubusercontent.com/lvgl/lvgl/master/env_support/cmsis-pack/</url>
<timestamp>2022-07-06T00:09:27</timestamp>
<timestamp>2023-07-04</timestamp>
<pindex>
<pdsc url="https://raw.githubusercontent.com/lvgl/lvgl/master/env_support/cmsis-pack/" vendor="LVGL" name="lvgl" version="1.0.6"/>
<pdsc url="https://raw.githubusercontent.com/lvgl/lvgl/release/v8.3/env_support/cmsis-pack/" vendor="LVGL" name="lvgl" version="8.3.8"/>
</pindex>
</index>

View File

@@ -21,8 +21,8 @@ if [ `uname -s` = "Linux" ]
CMSIS_PACK_PATH="/home/$USER/.arm/Packs/ARM/CMSIS/5.7.0/"
PATH_TO_ADD="$CMSIS_PACK_PATH/CMSIS/Utilities/Linux64/"
else
CMSIS_PACK_PATH="/C/Users/gabriel/AppData/Local/Arm/Packs/ARM/CMSIS/5.7.0"
PATH_TO_ADD="/C/Program Files (x86)/7-Zip/:$CMSIS_PACK_PATH/CMSIS/Utilities/Win32/:/C/xmllint/"
CMSIS_PACK_PATH="/C/Users/$USER/AppData/Local/Arm/Packs/ARM/CMSIS/5.7.0"
PATH_TO_ADD="/C/Program Files (x86)/7-Zip/:/C/Program Files/7-Zip/:$CMSIS_PACK_PATH/CMSIS/Utilities/Win32/:/C/xmllint/"
fi
[[ ":$PATH:" != *":$PATH_TO_ADD}:"* ]] && PATH="${PATH}:${PATH_TO_ADD}"
echo $PATH_TO_ADD appended to PATH

View File

@@ -1,6 +1,6 @@
/**
* @file lv_conf.h
* Configuration file for v8.3.0
* Configuration file for v8.3.8
*/
/* clang-format off */
@@ -82,19 +82,17 @@
#define LV_TICK_CUSTOM 1
#if LV_TICK_CUSTOM
extern uint32_t SystemCoreClock;
#define LV_TICK_CUSTOM_INCLUDE "perf_counter.h"
#if __PER_COUNTER_VER__ < 10902ul
#define LV_TICK_CUSTOM_SYS_TIME_EXPR ((uint32_t)get_system_ticks() / (SystemCoreClock / 1000ul))
#else
#define LV_TICK_CUSTOM_SYS_TIME_EXPR get_system_ms()
#endif
#define LV_TICK_CUSTOM_INCLUDE "perf_counter.h"
#define LV_TICK_CUSTOM_SYS_TIME_EXPR get_system_ms()
#endif /*LV_TICK_CUSTOM*/
#else
#define LV_TICK_CUSTOM 0
#if LV_TICK_CUSTOM
#define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/
#define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/
/*If using lvgl as ESP32 component*/
// #define LV_TICK_CUSTOM_INCLUDE "esp_timer.h"
// #define LV_TICK_CUSTOM_SYS_TIME_EXPR ((esp_timer_get_time() / 1000LL))
#endif /*LV_TICK_CUSTOM*/
#endif /*__PERF_COUNTER__*/
@@ -183,7 +181,7 @@
/*Use STM32's DMA2D (aka Chrom Art) GPU*/
#if LV_USE_GPU_STM32_DMA2D
/*Must be defined to include path of CMSIS header of target processor
e.g. "stm32f769xx.h" or "stm32f429xx.h"*/
e.g. "stm32f7xx.h" or "stm32f4xx.h"*/
#define LV_GPU_DMA2D_CMSIS_INCLUDE
#endif
@@ -202,6 +200,12 @@
#define LV_USE_GPU_NXP_PXP_AUTO_INIT 0
#endif
#if LV_USE_GPU_RA6M3_G2D
/*include path of target processor
e.g. "hal_data.h"*/
#define LV_GPU_RA6M3_G2D_INCLUDE "hal_data.h"
#endif
/*Use SDL renderer API*/
#define LV_USE_GPU_SDL 0
#if LV_USE_GPU_SDL
@@ -227,11 +231,11 @@
*LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail
*LV_LOG_LEVEL_USER Only logs added by the user
*LV_LOG_LEVEL_NONE Do not log anything*/
#define LV_LOG_LEVEL LV_LOG_LEVEL_WARN
#define LV_LOG_LEVEL LV_LOG_LEVEL_USER
/*1: Print the log with 'printf';
*0: User need to register a callback with `lv_log_register_print_cb()`*/
#define LV_LOG_PRINTF 0
#define LV_LOG_PRINTF 1
/*Enable/disable LV_LOG_TRACE in modules that produces a huge number of logs*/
#define LV_LOG_TRACE_MEM 1
@@ -350,9 +354,9 @@
*https://fonts.google.com/specimen/Montserrat*/
#define LV_FONT_MONTSERRAT_8 0
#define LV_FONT_MONTSERRAT_10 0
#define LV_FONT_MONTSERRAT_12 0
#define LV_FONT_MONTSERRAT_12 1
#define LV_FONT_MONTSERRAT_14 1
#define LV_FONT_MONTSERRAT_16 0
#define LV_FONT_MONTSERRAT_16 1
#define LV_FONT_MONTSERRAT_18 0
#define LV_FONT_MONTSERRAT_20 0
#define LV_FONT_MONTSERRAT_22 0

View File

@@ -71,7 +71,11 @@
# define LV_BIG_ENDIAN_SYSTEM 0
#endif
#define LV_ATTRIBUTE_MEM_ALIGN ALIGN(4)
#ifdef rt_align /* >= RT-Thread v5.0.0 */
# define LV_ATTRIBUTE_MEM_ALIGN rt_align(RT_ALIGN_SIZE)
#else
# define LV_ATTRIBUTE_MEM_ALIGN ALIGN(RT_ALIGN_SIZE)
#endif
/*==================
* EXAMPLES

View File

@@ -31,6 +31,12 @@ extern void lv_port_indev_init(void);
extern void lv_user_gui_init(void);
static struct rt_thread lvgl_thread;
#ifdef rt_align
rt_align(RT_ALIGN_SIZE)
#else
ALIGN(RT_ALIGN_SIZE)
#endif
static rt_uint8_t lvgl_thread_stack[PKG_LVGL_THREAD_STACK_SIZE];
#if LV_USE_LOG

View File

@@ -0,0 +1,4 @@
This folder is for LVGL SquareLine Studio
SquareLine Studio can automatically put the generated C files into `ui` folder, so that rt-thread will automatically detect them; or, as a user, you can move the generated C files into `ui` folder manually.

View File

@@ -0,0 +1,25 @@
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
inc = [cwd]
# check if .h or .hpp files exsit
def check_h_hpp_exsit(path):
file_dirs = os.listdir(path)
for file_dir in file_dirs:
if os.path.splitext(file_dir)[1] in ['.h', '.hpp']:
return True
return False
sls_src_cwd = cwd
for root, dirs, files in os.walk(sls_src_cwd):
for dir in dirs:
current_path = os.path.join(root, dir)
src = src + Glob(os.path.join(current_path,'*.c')) # add all .c files
if check_h_hpp_exsit(current_path): # add .h and .hpp path
inc = inc + [current_path]
group = DefineGroup('LVGL-SquareLine', src, depend = ['PKG_USING_LVGL_SQUARELINE'], CPPPATH = inc)
Return('group')

View File

@@ -0,0 +1,19 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: MIT
*
* Change Logs:
* Date Author Notes
* 2022-05-13 Meco Man First version
*/
#ifdef __RTTHREAD__
void lv_user_gui_init(void)
{
extern void ui_init(void);
ui_init();
}
#endif /* __RTTHREAD__ */

View File

@@ -0,0 +1,15 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: MIT
*
* Change Logs:
* Date Author Notes
* 2022-11-20 Meco Man The first version
*/
#ifdef __RTTHREAD__
#include "../../../../../lvgl.h" /* back to the root folder's lvgl.h */
#endif /* __RTTHREAD__ */

View File

@@ -1,5 +1,5 @@
#include "../lv_examples.h"
#if LV_BUILD_EXAMPLES && LV_USE_SLIDER && LV_USE_CHART && LV_USE_BTN
#if LV_BUILD_EXAMPLES && LV_USE_SLIDER && LV_USE_CHART && LV_USE_BTN && LV_USE_GRID
/**
* the example show the use of cubic-bezier3 in animation.

View File

@@ -1,19 +1,20 @@
/*Using LVGL with Arduino requires some extra steps:
*Be sure to read the docs here: https://docs.lvgl.io/master/get-started/platforms/arduino.html */
#include <lvgl.h>
#include <TFT_eSPI.h>
/*If you want to use the LVGL examples,
make sure to install the lv_examples Arduino library
and uncomment the following line.
#include <lv_examples.h>
*/
#include <lv_demo.h>
/*To use the built-in examples and demos of LVGL uncomment the includes below respectively.
*You also need to copy `lvgl/examples` to `lvgl/src/examples`. Similarly for the demos `lvgl/demos` to `lvgl/src/demos`.
Note that the `lv_examples` library is for LVGL v7 and you shouldn't install it for this version (since LVGL v8)
as the examples and demos are now part of the main LVGL library. */
/*Change to your screen resolution*/
static const uint16_t screenWidth = 480;
static const uint16_t screenHeight = 320;
static lv_disp_draw_buf_t draw_buf;
static lv_color_t buf[ screenWidth * 10 ];
static lv_color_t buf[ screenWidth * screenHeight / 10 ];
TFT_eSPI tft = TFT_eSPI(screenWidth, screenHeight); /* TFT instance */
@@ -27,7 +28,7 @@ void my_print(const char * buf)
#endif
/* Display flushing */
void my_disp_flush( lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p )
void my_disp_flush( lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p )
{
uint32_t w = ( area->x2 - area->x1 + 1 );
uint32_t h = ( area->y2 - area->y1 + 1 );
@@ -37,11 +38,11 @@ void my_disp_flush( lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *colo
tft.pushColors( ( uint16_t * )&color_p->full, w * h, true );
tft.endWrite();
lv_disp_flush_ready( disp );
lv_disp_flush_ready( disp_drv );
}
/*Read the touchpad*/
void my_touchpad_read( lv_indev_drv_t * indev_driver, lv_indev_data_t * data )
void my_touchpad_read( lv_indev_drv_t * indev_drv, lv_indev_data_t * data )
{
uint16_t touchX, touchY;
@@ -92,7 +93,7 @@ void setup()
uint16_t calData[5] = { 275, 3620, 264, 3532, 1 };
tft.setTouch( calData );
lv_disp_draw_buf_init( &draw_buf, buf, NULL, screenWidth * 10 );
lv_disp_draw_buf_init( &draw_buf, buf, NULL, screenWidth * screenHeight / 10 );
/*Initialize the display*/
static lv_disp_drv_t disp_drv;
@@ -110,26 +111,25 @@ void setup()
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = my_touchpad_read;
lv_indev_drv_register( &indev_drv );
#if 0
/* Create simple label */
lv_obj_t *label = lv_label_create( lv_scr_act() );
lv_label_set_text( label, LVGL_Arduino.c_str() );
lv_label_set_text( label, "Hello Ardino and LVGL!");
lv_obj_align( label, LV_ALIGN_CENTER, 0, 0 );
#else
/* Try an example from the lv_examples Arduino library
make sure to include it as written above.
lv_example_btn_1();
*/
// uncomment one of these demos
lv_demo_widgets(); // OK
// lv_demo_benchmark(); // OK
// lv_demo_keypad_encoder(); // works, but I haven't an encoder
// lv_demo_music(); // NOK
/* Try an example. See all the examples
* online: https://docs.lvgl.io/master/examples.html
* source codes: https://github.com/lvgl/lvgl/tree/e7f88efa5853128bf871dde335c0ca8da9eb7731/examples */
//lv_example_btn_1();
/*Or try out a demo. Don't forget to enable the demos in lv_conf.h. E.g. LV_USE_DEMOS_WIDGETS*/
//lv_demo_widgets();
// lv_demo_benchmark();
// lv_demo_keypad_encoder();
// lv_demo_music();
// lv_demo_printer();
// lv_demo_stress(); // seems to be OK
#endif
// lv_demo_stress();
Serial.println( "Setup done" );
}

View File

@@ -28,7 +28,7 @@ void lv_example_flex_1(void)
lv_obj_set_size(obj, 100, LV_PCT(100));
label = lv_label_create(obj);
lv_label_set_text_fmt(label, "Item: %u", i);
lv_label_set_text_fmt(label, "Item: %"LV_PRIu32, i);
lv_obj_center(label);
/*Add items to the column*/

Binary file not shown.

Binary file not shown.

View File

@@ -10,7 +10,7 @@ void lv_example_freetype_1(void)
/*Create a font*/
static lv_ft_info_t info;
/*FreeType uses C standard file system, so no driver letter is required.*/
info.name = "./lvgl/examples/libs/freetype/arial.ttf";
info.name = "./lvgl/examples/libs/freetype/Lato-Regular.ttf";
info.weight = 24;
info.style = FT_FONT_STYLE_NORMAL;
info.mem = NULL;

View File

@@ -4,7 +4,7 @@ import display_driver
import fs_driver
info = lv.ft_info_t()
info.name ="./arial.ttf"
info.name ="./Lato-Regular.ttf"
info.weight = 24
info.style = lv.FT_FONT_STYLE.NORMAL
info.font_init()

View File

@@ -14,7 +14,7 @@ void lv_example_animimg_1(void)
{
lv_obj_t * animimg0 = lv_animimg_create(lv_scr_act());
lv_obj_center(animimg0);
lv_animimg_set_src(animimg0, (lv_img_dsc_t **) anim_imgs, 3);
lv_animimg_set_src(animimg0, (const void **) anim_imgs, 3);
lv_animimg_set_duration(animimg0, 1000);
lv_animimg_set_repeat_count(animimg0, LV_ANIM_REPEAT_INFINITE);
lv_animimg_start(animimg0);

View File

@@ -18,11 +18,11 @@ static void float_btn_event_cb(lv_event_t * e)
cont = lv_menu_cont_create(sub_page);
label = lv_label_create(cont);
lv_label_set_text_fmt(label, "Hello, I am hiding inside %i", btn_cnt);
lv_label_set_text_fmt(label, "Hello, I am hiding inside %"LV_PRIu32, btn_cnt);
cont = lv_menu_cont_create(main_page);
label = lv_label_create(cont);
lv_label_set_text_fmt(label, "Item %i", btn_cnt);
lv_label_set_text_fmt(label, "Item %"LV_PRIu32, btn_cnt);
lv_menu_set_load_page_event(menu, cont, sub_page);
lv_obj_scroll_to_view_recursive(cont, LV_ANIM_ON);

View File

@@ -1,21 +1,11 @@
#include "../../lv_examples.h"
#if LV_USE_TABVIEW && LV_BUILD_EXAMPLES
static void scroll_begin_event(lv_event_t * e)
{
/*Disable the scroll animations. Triggered when a tab button is clicked */
if(lv_event_get_code(e) == LV_EVENT_SCROLL_BEGIN) {
lv_anim_t * a = lv_event_get_param(e);
if(a) a->time = 0;
}
}
void lv_example_tabview_2(void)
{
/*Create a Tab view object*/
lv_obj_t * tabview;
tabview = lv_tabview_create(lv_scr_act(), LV_DIR_LEFT, 80);
lv_obj_add_event_cb(lv_tabview_get_content(tabview), scroll_begin_event, LV_EVENT_SCROLL_BEGIN, NULL);
lv_obj_set_style_bg_color(tabview, lv_palette_lighten(LV_PALETTE_RED, 2), 0);

View File

@@ -1,15 +1,6 @@
def scroll_begin_event(e):
#Disable the scroll animations. Triggered when a tab button is clicked */
if e.get_code() == lv.EVENT.SCROLL_BEGIN:
a = lv.anim_t.__cast__(e.get_param())
if a:
a.time = 0
# Create a Tab view object
tabview = lv.tabview(lv.scr_act(), lv.DIR.LEFT, 80)
tabview.get_content().add_event_cb(scroll_begin_event, lv.EVENT.SCROLL_BEGIN, None)
tabview.set_style_bg_color(lv.palette_lighten(lv.PALETTE.RED, 2), 0)
tab_btns = tabview.get_tab_btns()

View File

@@ -1,2 +1,5 @@
description: LVGL - Light and Versatile Graphics Library
url: https://github.com/lvgl/lvgl
description: LVGL - Light and Versatile Graphics Library
url: https://lvgl.io/
repository: https://github.com/lvgl/lvgl.git
documentation: https://docs.lvgl.io/
issues: https://github.com/lvgl/lvgl/issues

View File

@@ -1,6 +1,6 @@
{
"name": "lvgl",
"version": "8.3.0",
"version": "8.3.8",
"keywords": "graphics, gui, embedded, tft, lvgl",
"description": "Graphics library to create embedded GUI with easy-to-use graphical elements, beautiful visual effects and low memory footprint. It offers anti-aliasing, opacity, and animations using only one frame buffer.",
"repository": {

View File

@@ -1,5 +1,5 @@
name=lvgl
version=8.3.0
version=8.3.8
author=kisvegabor
maintainer=kisvegabor,embeddedt,pete-pjb
sentence=Full-featured Graphics Library for Embedded Systems

View File

@@ -1,6 +1,6 @@
/**
* @file lv_conf.h
* Configuration file for v8.3.0
* Configuration file for v8.3.8
*/
/*
@@ -89,6 +89,9 @@
#if LV_TICK_CUSTOM
#define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/
#define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/
/*If using lvgl as ESP32 component*/
// #define LV_TICK_CUSTOM_INCLUDE "esp_timer.h"
// #define LV_TICK_CUSTOM_SYS_TIME_EXPR ((esp_timer_get_time() / 1000LL))
#endif /*LV_TICK_CUSTOM*/
/*Default Dot Per Inch. Used to initialize default sizes such as widgets sized, style paddings.
@@ -180,10 +183,18 @@
#define LV_USE_GPU_STM32_DMA2D 0
#if LV_USE_GPU_STM32_DMA2D
/*Must be defined to include path of CMSIS header of target processor
e.g. "stm32f769xx.h" or "stm32f429xx.h"*/
e.g. "stm32f7xx.h" or "stm32f4xx.h"*/
#define LV_GPU_DMA2D_CMSIS_INCLUDE
#endif
/*Enable RA6M3 G2D GPU*/
#define LV_USE_GPU_RA6M3_G2D 0
#if LV_USE_GPU_RA6M3_G2D
/*include path of target processor
e.g. "hal_data.h"*/
#define LV_GPU_RA6M3_G2D_INCLUDE "hal_data.h"
#endif
/*Use SWM341's DMA2D GPU*/
#define LV_USE_GPU_SWM341_DMA2D 0
#if LV_USE_GPU_SWM341_DMA2D

2
lvgl.h
View File

@@ -15,7 +15,7 @@ extern "C" {
***************************/
#define LVGL_VERSION_MAJOR 8
#define LVGL_VERSION_MINOR 3
#define LVGL_VERSION_PATCH 0
#define LVGL_VERSION_PATCH 8
#define LVGL_VERSION_INFO ""
/*********************

View File

@@ -6,6 +6,7 @@ rm -rf emscripten_builder
git clone https://github.com/lvgl/lv_sim_emscripten.git emscripten_builder
scripts/genexamplelist.sh > emscripten_builder/examplelist.c
cd emscripten_builder
git checkout 45e0bc5c8d3e55cfbcaf8214361d2335b8b9a7b4
git submodule update --init -- lvgl
cd lvgl
git checkout $CURRENT_REF

View File

@@ -262,6 +262,7 @@ void lv_scr_load_anim(lv_obj_t * new_scr, lv_scr_load_anim_t anim_type, uint32_t
/*Shortcut for immediate load*/
if(time == 0 && delay == 0) {
scr_load_internal(new_scr);
if(auto_del) lv_obj_del(act_scr);
return;
}

View File

@@ -92,6 +92,7 @@ void lv_group_del(lv_group_t * group)
indev = lv_indev_get_next(indev);
}
if(default_group == group) default_group = NULL;
_lv_ll_clear(&(group->obj_ll));
_lv_ll_remove(&LV_GC_ROOT(_lv_group_ll), group);
lv_mem_free(group);
@@ -113,6 +114,9 @@ void lv_group_add_obj(lv_group_t * group, lv_obj_t * obj)
LV_LOG_TRACE("begin");
/*Be sure the object is removed from its current group*/
lv_group_remove_obj(obj);
/*Do not add the object twice*/
lv_obj_t ** obj_i;
_LV_LL_READ(&group->obj_ll, obj_i) {

View File

@@ -852,8 +852,6 @@ static void indev_proc_press(_lv_indev_proc_t * proc)
if(indev_reset_check(proc)) return;
}
lv_obj_transform_point(indev_obj_act, &proc->types.pointer.act_point, true, true);
/*If a new object was found reset some variables and send a pressed event handler*/
if(indev_obj_act != proc->types.pointer.act_obj) {
proc->types.pointer.last_point.x = proc->types.pointer.act_point.x;
@@ -987,6 +985,27 @@ static void indev_proc_release(_lv_indev_proc_t * proc)
proc->pr_timestamp = 0;
proc->longpr_rep_timestamp = 0;
/*Get the transformed vector with this object*/
if(scroll_obj) {
int16_t angle = 0;
int16_t zoom = 256;
lv_point_t pivot = { 0, 0 };
lv_obj_t * parent = scroll_obj;
while(parent) {
angle += lv_obj_get_style_transform_angle(parent, 0);
zoom *= (lv_obj_get_style_transform_zoom(parent, 0) / 256);
parent = lv_obj_get_parent(parent);
}
if(angle != 0 || zoom != LV_IMG_ZOOM_NONE) {
angle = -angle;
zoom = (256 * 256) / zoom;
lv_point_transform(&proc->types.pointer.scroll_throw_vect, angle, zoom, &pivot);
lv_point_transform(&proc->types.pointer.scroll_throw_vect_ori, angle, zoom, &pivot);
}
}
}
/*The reset can be set in the Call the ancestor's event handler function.

View File

@@ -45,12 +45,13 @@ static lv_coord_t elastic_diff(lv_obj_t * scroll_obj, lv_coord_t diff, lv_coord_
void _lv_indev_scroll_handler(_lv_indev_proc_t * proc)
{
if(proc->types.pointer.vect.x == 0 && proc->types.pointer.vect.y == 0) {
return;
}
lv_obj_t * scroll_obj = proc->types.pointer.scroll_obj;
/*If there is no scroll object yet try to find one*/
if(scroll_obj == NULL) {
proc->types.pointer.scroll_sum.x += proc->types.pointer.vect.x;
proc->types.pointer.scroll_sum.y += proc->types.pointer.vect.y;
scroll_obj = find_scroll_obj(proc);
if(scroll_obj == NULL) return;
@@ -61,35 +62,50 @@ void _lv_indev_scroll_handler(_lv_indev_proc_t * proc)
}
/*Set new position or scroll if the vector is not zero*/
if(proc->types.pointer.vect.x != 0 || proc->types.pointer.vect.y != 0) {
lv_coord_t diff_x = 0;
lv_coord_t diff_y = 0;
if(proc->types.pointer.scroll_dir == LV_DIR_HOR) {
lv_coord_t sr = lv_obj_get_scroll_right(scroll_obj);
lv_coord_t sl = lv_obj_get_scroll_left(scroll_obj);
diff_x = elastic_diff(scroll_obj, proc->types.pointer.vect.x, sl, sr, LV_DIR_HOR);
}
else {
lv_coord_t st = lv_obj_get_scroll_top(scroll_obj);
lv_coord_t sb = lv_obj_get_scroll_bottom(scroll_obj);
diff_y = elastic_diff(scroll_obj, proc->types.pointer.vect.y, st, sb, LV_DIR_VER);
}
lv_dir_t scroll_dir = lv_obj_get_scroll_dir(scroll_obj);
if((scroll_dir & LV_DIR_LEFT) == 0 && diff_x > 0) diff_x = 0;
if((scroll_dir & LV_DIR_RIGHT) == 0 && diff_x < 0) diff_x = 0;
if((scroll_dir & LV_DIR_TOP) == 0 && diff_y > 0) diff_y = 0;
if((scroll_dir & LV_DIR_BOTTOM) == 0 && diff_y < 0) diff_y = 0;
/*Respect the scroll limit area*/
scroll_limit_diff(proc, &diff_x, &diff_y);
_lv_obj_scroll_by_raw(scroll_obj, diff_x, diff_y);
if(proc->reset_query) return;
proc->types.pointer.scroll_sum.x += diff_x;
proc->types.pointer.scroll_sum.y += diff_y;
int16_t angle = 0;
int16_t zoom = 256;
lv_obj_t * parent = scroll_obj;
while(parent) {
angle += lv_obj_get_style_transform_angle(parent, 0);
zoom *= (lv_obj_get_style_transform_zoom(parent, 0) / 256);
parent = lv_obj_get_parent(parent);
}
if(angle != 0 || zoom != LV_IMG_ZOOM_NONE) {
angle = -angle;
zoom = (256 * 256) / zoom;
lv_point_t pivot = { 0, 0 };
lv_point_transform(&proc->types.pointer.vect, angle, zoom, &pivot);
}
lv_coord_t diff_x = 0;
lv_coord_t diff_y = 0;
if(proc->types.pointer.scroll_dir == LV_DIR_HOR) {
lv_coord_t sr = lv_obj_get_scroll_right(scroll_obj);
lv_coord_t sl = lv_obj_get_scroll_left(scroll_obj);
diff_x = elastic_diff(scroll_obj, proc->types.pointer.vect.x, sl, sr, LV_DIR_HOR);
}
else {
lv_coord_t st = lv_obj_get_scroll_top(scroll_obj);
lv_coord_t sb = lv_obj_get_scroll_bottom(scroll_obj);
diff_y = elastic_diff(scroll_obj, proc->types.pointer.vect.y, st, sb, LV_DIR_VER);
}
lv_dir_t scroll_dir = lv_obj_get_scroll_dir(scroll_obj);
if((scroll_dir & LV_DIR_LEFT) == 0 && diff_x > 0) diff_x = 0;
if((scroll_dir & LV_DIR_RIGHT) == 0 && diff_x < 0) diff_x = 0;
if((scroll_dir & LV_DIR_TOP) == 0 && diff_y > 0) diff_y = 0;
if((scroll_dir & LV_DIR_BOTTOM) == 0 && diff_y < 0) diff_y = 0;
/*Respect the scroll limit area*/
scroll_limit_diff(proc, &diff_x, &diff_y);
_lv_obj_scroll_by_raw(scroll_obj, diff_x, diff_y);
if(proc->reset_query) return;
proc->types.pointer.scroll_sum.x += diff_x;
proc->types.pointer.scroll_sum.y += diff_y;
}
@@ -99,7 +115,6 @@ void _lv_indev_scroll_throw_handler(_lv_indev_proc_t * proc)
if(scroll_obj == NULL) return;
if(proc->types.pointer.scroll_dir == LV_DIR_NONE) return;
lv_indev_t * indev_act = lv_indev_get_act();
lv_coord_t scroll_throw = indev_act->driver->scroll_throw;
@@ -259,14 +274,37 @@ static lv_obj_t * find_scroll_obj(_lv_indev_proc_t * proc)
/*Decide if it's a horizontal or vertical scroll*/
bool hor_en = false;
bool ver_en = false;
if(LV_ABS(proc->types.pointer.scroll_sum.x) > LV_ABS(proc->types.pointer.scroll_sum.y)) {
hor_en = true;
}
else {
ver_en = true;
}
proc->types.pointer.scroll_sum.x += proc->types.pointer.vect.x;
proc->types.pointer.scroll_sum.y += proc->types.pointer.vect.y;
while(obj_act) {
/*Get the transformed scroll_sum with this object*/
int16_t angle = 0;
int32_t zoom = 256;
lv_point_t pivot = { 0, 0 };
lv_obj_t * parent = obj_act;
while(parent) {
angle += lv_obj_get_style_transform_angle(parent, 0);
int32_t zoom_act = lv_obj_get_style_transform_zoom(parent, 0);
zoom = (zoom * zoom_act) >> 8;
parent = lv_obj_get_parent(parent);
}
lv_point_t obj_scroll_sum = proc->types.pointer.scroll_sum;
if(angle != 0 || zoom != LV_IMG_ZOOM_NONE) {
angle = -angle;
zoom = (256 * 256) / zoom;
lv_point_transform(&obj_scroll_sum, angle, zoom, &pivot);
}
if(LV_ABS(obj_scroll_sum.x) > LV_ABS(obj_scroll_sum.y)) {
hor_en = true;
}
else {
ver_en = true;
}
if(lv_obj_has_flag(obj_act, LV_OBJ_FLAG_SCROLLABLE) == false) {
/*If this object don't want to chain the scroll to the parent stop searching*/
if(lv_obj_has_flag(obj_act, LV_OBJ_FLAG_SCROLL_CHAIN_HOR) == false && hor_en) break;
@@ -300,15 +338,15 @@ static lv_obj_t * find_scroll_obj(_lv_indev_proc_t * proc)
*is propagated to this object it can show at least elastic scroll effect.
*But if not hor/ver scrollable do not scroll it at all (so it's not a good candidate)*/
if((st > 0 || sb > 0) &&
((up_en && proc->types.pointer.scroll_sum.y >= scroll_limit) ||
(down_en && proc->types.pointer.scroll_sum.y <= - scroll_limit))) {
((up_en && obj_scroll_sum.y >= scroll_limit) ||
(down_en && obj_scroll_sum.y <= - scroll_limit))) {
obj_candidate = obj_act;
dir_candidate = LV_DIR_VER;
}
if((sl > 0 || sr > 0) &&
((left_en && proc->types.pointer.scroll_sum.x >= scroll_limit) ||
(right_en && proc->types.pointer.scroll_sum.x <= - scroll_limit))) {
((left_en && obj_scroll_sum.x >= scroll_limit) ||
(right_en && obj_scroll_sum.x <= - scroll_limit))) {
obj_candidate = obj_act;
dir_candidate = LV_DIR_HOR;
}
@@ -318,11 +356,11 @@ static lv_obj_t * find_scroll_obj(_lv_indev_proc_t * proc)
if(sl <= 0) left_en = false;
if(sr <= 0) right_en = false;
/*If the object really can be scrolled into the current direction the use it.*/
if((left_en && proc->types.pointer.scroll_sum.x >= scroll_limit) ||
(right_en && proc->types.pointer.scroll_sum.x <= - scroll_limit) ||
(up_en && proc->types.pointer.scroll_sum.y >= scroll_limit) ||
(down_en && proc->types.pointer.scroll_sum.y <= - scroll_limit)) {
/*If the object really can be scrolled into the current direction then use it.*/
if((left_en && obj_scroll_sum.x >= scroll_limit) ||
(right_en && obj_scroll_sum.x <= - scroll_limit) ||
(up_en && obj_scroll_sum.y >= scroll_limit) ||
(down_en && obj_scroll_sum.y <= - scroll_limit)) {
proc->types.pointer.scroll_dir = hor_en ? LV_DIR_HOR : LV_DIR_VER;
break;
}

View File

@@ -30,6 +30,10 @@
#include "../draw/stm32_dma2d/lv_gpu_stm32_dma2d.h"
#endif
#if LV_USE_GPU_RA6M3_G2D
#include "../draw/renesas/lv_gpu_d2_ra6m3.h"
#endif
#if LV_USE_GPU_SWM341_DMA2D
#include "../draw/swm341_dma2d/lv_gpu_swm341_dma2d.h"
#endif
@@ -119,6 +123,11 @@ void lv_init(void)
lv_draw_stm32_dma2d_init();
#endif
#if LV_USE_GPU_RA6M3_G2D
/*Initialize G2D GPU*/
lv_draw_ra6m3_g2d_init();
#endif
#if LV_USE_GPU_SWM341_DMA2D
/*Initialize DMA2D GPU*/
lv_draw_swm341_dma2d_init();

View File

@@ -1160,9 +1160,21 @@ static void transform_point(const lv_obj_t * obj, lv_point_t * p, bool inv)
if(angle == 0 && zoom == LV_IMG_ZOOM_NONE) return;
lv_point_t pivot;
pivot.x = obj->coords.x1 + lv_obj_get_style_transform_pivot_x(obj, 0);
pivot.y = obj->coords.y1 + lv_obj_get_style_transform_pivot_y(obj, 0);
lv_point_t pivot = {
.x = lv_obj_get_style_transform_pivot_x(obj, 0),
.y = lv_obj_get_style_transform_pivot_y(obj, 0)
};
if(LV_COORD_IS_PCT(pivot.x)) {
pivot.x = (LV_COORD_GET_PCT(pivot.x) * lv_area_get_width(&obj->coords)) / 100;
}
if(LV_COORD_IS_PCT(pivot.y)) {
pivot.y = (LV_COORD_GET_PCT(pivot.y) * lv_area_get_height(&obj->coords)) / 100;
}
pivot.x = obj->coords.x1 + pivot.x;
pivot.y = obj->coords.y1 + pivot.y;
if(inv) {
angle = -angle;
zoom = (256 * 256) / zoom;

View File

@@ -314,7 +314,12 @@ bool lv_obj_remove_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_sty
/*The style is not found*/
if(i == obj->style_cnt) return false;
return lv_style_remove_prop(obj->styles[i].style, prop);
lv_res_t res = lv_style_remove_prop(obj->styles[i].style, prop);
if(res == LV_RES_OK) {
lv_obj_refresh_style(obj, selector, prop);
}
return res;
}
void _lv_obj_style_create_transition(lv_obj_t * obj, lv_part_t part, lv_state_t prev_state, lv_state_t new_state,
@@ -744,6 +749,7 @@ static void trans_anim_cb(void * _tr, int32_t v)
else value_final.ptr = tr->end_value.ptr;
break;
case LV_STYLE_BG_COLOR:
case LV_STYLE_BG_GRAD_COLOR:
case LV_STYLE_BORDER_COLOR:
case LV_STYLE_TEXT_COLOR:
case LV_STYLE_SHADOW_COLOR:

View File

@@ -323,15 +323,8 @@ void _lv_disp_refr_timer(lv_timer_t * tmr)
refr_invalid_areas();
/*If refresh happened ...*/
if(disp_refr->inv_p != 0) {
if(disp_refr->driver->full_refresh) {
lv_area_t disp_area;
lv_area_set(&disp_area, 0, 0, lv_disp_get_hor_res(disp_refr) - 1, lv_disp_get_ver_res(disp_refr) - 1);
disp_refr->driver->draw_ctx->buf_area = &disp_area;
draw_buf_flush(disp_refr);
}
/*Clean up*/
lv_memset_00(disp_refr->inv_areas, sizeof(disp_refr->inv_areas));
@@ -620,9 +613,15 @@ static void refr_area_part(lv_draw_ctx_t * draw_ctx)
{
lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp_refr);
if(draw_ctx->init_buf)
draw_ctx->init_buf(draw_ctx);
/* Below the `area_p` area will be redrawn into the draw buffer.
* In single buffered mode wait here until the buffer is freed.*/
if(draw_buf->buf1 && !draw_buf->buf2) {
* In single buffered mode wait here until the buffer is freed.
* In full double buffered mode wait here while the buffers are swapped and a buffer becomes available*/
bool full_sized = draw_buf->size == (uint32_t)disp_refr->driver->hor_res * disp_refr->driver->ver_res;
if((draw_buf->buf1 && !draw_buf->buf2) ||
(draw_buf->buf1 && draw_buf->buf2 && full_sized)) {
while(draw_buf->flushing) {
if(disp_refr->driver->wait_cb) disp_refr->driver->wait_cb(disp_refr->driver);
}
@@ -710,11 +709,7 @@ static void refr_area_part(lv_draw_ctx_t * draw_ctx)
refr_obj_and_children(draw_ctx, lv_disp_get_layer_top(disp_refr));
refr_obj_and_children(draw_ctx, lv_disp_get_layer_sys(disp_refr));
/*In true double buffered mode flush only once when all areas were rendered.
*In normal mode flush after every area*/
if(disp_refr->driver->full_refresh == false) {
draw_buf_flush(disp_refr);
}
draw_buf_flush(disp_refr);
}
/**
@@ -738,9 +733,9 @@ static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj)
lv_event_send(obj, LV_EVENT_COVER_CHECK, &info);
if(info.res == LV_COVER_RES_MASKED) return NULL;
uint32_t i;
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
for(i = 0; i < child_cnt; i++) {
int32_t i;
int32_t child_cnt = lv_obj_get_child_cnt(obj);
for(i = child_cnt - 1; i >= 0; i--) {
lv_obj_t * child = obj->spec_attr->children[i];
found_p = lv_refr_get_top_obj(area_p, child);
@@ -922,6 +917,13 @@ void refr_obj(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj)
.y = lv_obj_get_style_transform_pivot_y(obj, 0)
};
if(LV_COORD_IS_PCT(pivot.x)) {
pivot.x = (LV_COORD_GET_PCT(pivot.x) * lv_area_get_width(&obj->coords)) / 100;
}
if(LV_COORD_IS_PCT(pivot.y)) {
pivot.y = (LV_COORD_GET_PCT(pivot.y) * lv_area_get_height(&obj->coords)) / 100;
}
lv_draw_img_dsc_t draw_dsc;
lv_draw_img_dsc_init(&draw_dsc);
draw_dsc.opa = opa;
@@ -1189,24 +1191,13 @@ static void draw_buf_flush(lv_disp_t * disp)
lv_draw_ctx_t * draw_ctx = disp->driver->draw_ctx;
if(draw_ctx->wait_for_finish) draw_ctx->wait_for_finish(draw_ctx);
/* In double buffered mode wait until the other buffer is freed
/* In partial double buffered mode wait until the other buffer is freed
* and driver is ready to receive the new buffer */
if(draw_buf->buf1 && draw_buf->buf2) {
bool full_sized = draw_buf->size == (uint32_t)disp_refr->driver->hor_res * disp_refr->driver->ver_res;
if(draw_buf->buf1 && draw_buf->buf2 && !full_sized) {
while(draw_buf->flushing) {
if(disp_refr->driver->wait_cb) disp_refr->driver->wait_cb(disp_refr->driver);
}
/*If the screen is transparent initialize it when the flushing is ready*/
#if LV_COLOR_SCREEN_TRANSP
if(disp_refr->driver->screen_transp) {
if(disp_refr->driver->clear_cb) {
disp_refr->driver->clear_cb(disp_refr->driver, disp_refr->driver->draw_buf->buf_act, disp_refr->driver->draw_buf->size);
}
else {
lv_memset_00(disp_refr->driver->draw_buf->buf_act, disp_refr->driver->draw_buf->size * LV_IMG_PX_SIZE_ALPHA_BYTE);
}
}
#endif
}
draw_buf->flushing = 1;
@@ -1225,6 +1216,7 @@ static void draw_buf_flush(lv_disp_t * disp)
call_flush_cb(disp->driver, draw_ctx->buf_area, draw_ctx->buf);
}
}
/*If there are 2 buffers swap them. With direct mode swap only on the last area*/
if(draw_buf->buf1 && draw_buf->buf2 && (!disp->driver->direct_mode || flushing_last)) {
if(draw_buf->buf_act == draw_buf->buf1)

View File

@@ -3,6 +3,24 @@
*
*/
/*
* Copyright (C) 2010-2023 Arm Limited or its affiliates. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*********************
* INCLUDES
*********************/
@@ -39,6 +57,7 @@
#include "../../core/lv_refr.h"
#if LV_USE_GPU_ARM2D
#define __ARM_2D_IMPL__
#include "arm_2d.h"
#include "__arm_2d_impl.h"
@@ -89,10 +108,14 @@
#define __arm_2d_impl_cl_key_copy __arm_2d_impl_rgb16_cl_key_copy
#define __arm_2d_impl_alpha_blending_colour_keying \
__arm_2d_impl_rgb565_alpha_blending_colour_keying
#define arm_2d_tile_transform_with_src_mask_and_opacity \
arm_2d_rgb565_tile_transform_with_src_mask_and_opacity
#define arm_2d_tile_transform_with_opacity \
arm_2d_rgb565_tile_transform_with_opacity
#define arm_2d_tile_transform_with_src_mask_and_opacity_prepare \
arm_2dp_rgb565_tile_transform_with_src_mask_and_opacity_prepare
#define arm_2d_tile_transform_with_opacity_prepare \
arm_2dp_rgb565_tile_transform_with_opacity_prepare
#define arm_2d_tile_transform_only_with_opacity_prepare \
arm_2dp_rgb565_tile_transform_only_with_opacity_prepare
#define arm_2d_tile_transform_prepare \
arm_2dp_rgb565_tile_transform_prepare
#define __ARM_2D_PIXEL_BLENDING_OPA __ARM_2D_PIXEL_BLENDING_OPA_RGB565
@@ -124,10 +147,14 @@
#define __arm_2d_impl_cl_key_copy __arm_2d_impl_rgb32_cl_key_copy
#define __arm_2d_impl_alpha_blending_colour_keying \
__arm_2d_impl_cccn888_alpha_blending_colour_keying
#define arm_2d_tile_transform_with_src_mask_and_opacity \
arm_2d_cccn888_tile_transform_with_src_mask_and_opacity
#define arm_2d_tile_transform_with_opacity \
arm_2d_cccn888_tile_transform_with_opacity
#define arm_2d_tile_transform_with_src_mask_and_opacity_prepare \
arm_2dp_cccn888_tile_transform_with_src_mask_and_opacity_prepare
#define arm_2d_tile_transform_with_opacity_prepare \
arm_2dp_cccn888_tile_transform_with_opacity_prepare
#define arm_2d_tile_transform_only_with_opacity_prepare \
arm_2dp_cccn888_tile_transform_only_with_opacity_prepare
#define arm_2d_tile_transform_prepare \
arm_2dp_cccn888_tile_transform_prepare
#define __ARM_2D_PIXEL_BLENDING_OPA __ARM_2D_PIXEL_BLENDING_OPA_CCCN888
@@ -298,11 +325,88 @@
/* replace src_buf for the following operation */ \
src_buf = (const uint8_t *)rgb_tmp_buf; \
} \
__VA_ARGS__ \
do { \
__VA_ARGS__ \
} while(0); \
if (NULL != rgb_tmp_buf) { \
lv_mem_buf_release(rgb_tmp_buf); \
} \
} while(0);
} while(0); \
src_buf = src_buf_org;
#define __RECOLOUR_BEGIN() \
do { \
lv_color_t *rgb_tmp_buf = NULL; \
if(draw_dsc->recolor_opa > LV_OPA_MIN) { \
rgb_tmp_buf \
= lv_mem_buf_get(src_w * src_h * sizeof(lv_color_t)); \
if (NULL == rgb_tmp_buf) { \
LV_LOG_WARN( \
"Failed to allocate memory for accelerating recolour, " \
"use normal route instead."); \
break; \
} \
lv_memcpy(rgb_tmp_buf, src_buf, src_w * src_h * sizeof(lv_color_t));\
arm_2d_size_t copy_size = { \
.iWidth = src_w, \
.iHeight = src_h, \
}; \
/* apply re-colour */ \
__arm_2d_impl_colour_filling_with_opacity( \
(color_int *)rgb_tmp_buf, \
src_w, \
&copy_size, \
(color_int)draw_dsc->recolor.full, \
draw_dsc->recolor_opa); \
\
/* replace src_buf for the following operation */ \
src_buf = (const uint8_t *)rgb_tmp_buf; \
} \
do {
#define __RECOLOUR_END() \
} while(0); \
if (NULL != rgb_tmp_buf) { \
lv_mem_buf_release(rgb_tmp_buf); \
} \
} while(0); \
src_buf = src_buf_org;
#define __ARM_2D_PREPARE_TRANS_AND_TARGET_REGION(__TRANS_PREPARE, ...) \
do { \
__TRANS_PREPARE( \
NULL, \
__VA_ARGS__); \
\
target_region = (arm_2d_region_t) { \
.tLocation = { \
.iX = coords->x1 - draw_ctx->clip_area->x1, \
.iY = coords->y1 - draw_ctx->clip_area->y1, \
}, \
.tSize = { \
.iWidth = lv_area_get_width(coords), \
.iHeight = lv_area_get_height(coords), \
}, \
}; \
\
arm_2d_size_t tTransSize \
= ARM_2D_CTRL.DefaultOP \
.tTransform.Source.ptTile->tRegion.tSize; \
\
if (target_region.tSize.iWidth < tTransSize.iWidth) { \
int16_t iDelta = tTransSize.iWidth - target_region.tSize.iWidth;\
target_region.tLocation.iX -= iDelta / 2; \
target_region.tSize.iWidth = tTransSize.iWidth; \
} \
\
if (target_region.tSize.iHeight < tTransSize.iHeight) { \
int16_t iDelta \
= tTransSize.iHeight - target_region.tSize.iHeight; \
target_region.tLocation.iY -= iDelta / 2; \
target_region.tSize.iHeight = tTransSize.iHeight; \
} \
} while(0)
/* *INDENT-ON* */
/**********************
@@ -601,18 +705,26 @@ static void lv_draw_arm2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend
lv_area_t blend_area;
if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area)) return;
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
//lv_disp_t * disp = _lv_refr_get_disp_refreshing();
bool is_accelerated = false;
do {
if(NULL != disp->driver->set_px_cb) {
break;
/* target buffer */
lv_color_t * dest_buf = draw_ctx->buf;
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
if(disp->driver->screen_transp == 0) {
dest_buf += dest_stride * (blend_area.y1 - draw_ctx->buf_area->y1) + (blend_area.x1 - draw_ctx->buf_area->x1);
}
else {
/*With LV_COLOR_DEPTH 16 it means ARGB8565 (3 bytes format)*/
uint8_t * dest_buf8 = (uint8_t *) dest_buf;
dest_buf8 += dest_stride * (blend_area.y1 - draw_ctx->buf_area->y1) * LV_IMG_PX_SIZE_ALPHA_BYTE;
dest_buf8 += (blend_area.x1 - draw_ctx->buf_area->x1) * LV_IMG_PX_SIZE_ALPHA_BYTE;
dest_buf = (lv_color_t *)dest_buf8;
}
lv_color_t * dest_buf = draw_ctx->buf;
dest_buf += dest_stride * (blend_area.y1 - draw_ctx->buf_area->y1)
+ (blend_area.x1 - draw_ctx->buf_area->x1);
/* source buffer */
const lv_color_t * src_buf = dsc->src_buf;
lv_coord_t src_stride;
if(src_buf) {
@@ -634,7 +746,9 @@ static void lv_draw_arm2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend
lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
if(disp->driver->screen_transp) {
break;
}
if(dsc->src_buf == NULL) {
if(dsc->blend_mode == LV_BLEND_MODE_NORMAL) {
is_accelerated = arm_2d_fill_normal(dest_buf,
@@ -645,14 +759,8 @@ static void lv_draw_arm2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend
mask,
mask_stride);
}
#if LV_DRAW_COMPLEX
else {
break;
}
#endif
}
else {
if(dsc->blend_mode == LV_BLEND_MODE_NORMAL) {
is_accelerated = arm_2d_copy_normal(dest_buf,
&blend_area,
@@ -663,11 +771,6 @@ static void lv_draw_arm2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend
mask,
mask_stride);
}
#if LV_DRAW_COMPLEX
else {
break;
}
#endif
}
} while(0);
@@ -698,15 +801,11 @@ static bool arm_2d_fill_normal(lv_color_t * dest_buf,
}
/*Has opacity*/
else {
#if LV_COLOR_SCREEN_TRANSP
return false;
#else
__arm_2d_impl_colour_filling_with_opacity((color_int *)dest_buf,
dest_stride,
&target_size,
color.full,
opa);
#endif
}
}
/*Masked*/
@@ -722,9 +821,6 @@ static bool arm_2d_fill_normal(lv_color_t * dest_buf,
}
/*With opacity*/
else {
#if LV_COLOR_SCREEN_TRANSP
return false;
#else
__arm_2d_impl_colour_filling_mask_opacity((color_int *)dest_buf,
dest_stride,
(uint8_t *)mask,
@@ -732,7 +828,6 @@ static bool arm_2d_fill_normal(lv_color_t * dest_buf,
&target_size,
color.full,
opa);
#endif
}
}
@@ -759,10 +854,6 @@ static bool arm_2d_copy_normal(lv_color_t * dest_buf,
.iHeight = lv_area_get_height(dest_area),
};
#if LV_COLOR_SCREEN_TRANSP
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
#endif
/*Simple fill (maybe with opacity), no masking*/
if(mask == NULL) {
if(opa >= LV_OPA_MAX) {
@@ -773,25 +864,18 @@ static bool arm_2d_copy_normal(lv_color_t * dest_buf,
&copy_size);
}
else {
#if LV_COLOR_SCREEN_TRANSP
return false;
#else
__arm_2d_impl_alpha_blending((color_int *)src_buf,
src_stride,
(color_int *)dest_buf,
dest_stride,
&copy_size,
opa);
#endif
}
}
/*Masked*/
else {
/*Only the mask matters*/
if(opa > LV_OPA_MAX) {
#if LV_COLOR_SCREEN_TRANSP
return false;
#else
__arm_2d_impl_src_msk_copy((color_int *)src_buf,
src_stride,
(uint8_t *)mask,
@@ -800,13 +884,9 @@ static bool arm_2d_copy_normal(lv_color_t * dest_buf,
(color_int *)dest_buf,
dest_stride,
&copy_size);
#endif
}
/*Handle opa and mask values too*/
else {
#if LV_COLOR_SCREEN_TRANSP
return false;
#else
__arm_2d_impl_gray8_alpha_blending((uint8_t *)mask,
mask_stride,
(uint8_t *)mask,
@@ -822,7 +902,6 @@ static bool arm_2d_copy_normal(lv_color_t * dest_buf,
(color_int *)dest_buf,
dest_stride,
&copy_size);
#endif
}
}
@@ -839,6 +918,7 @@ static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx,
/*Use the clip area as draw area*/
lv_area_t draw_area;
lv_area_copy(&draw_area, draw_ctx->clip_area);
const uint8_t * src_buf_org = src_buf;
bool mask_any = lv_draw_mask_is_any(&draw_area);
bool transform = draw_dsc->angle != 0 || draw_dsc->zoom != LV_IMG_ZOOM_NONE ? true : false;
@@ -851,6 +931,13 @@ static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx,
blend_dsc.blend_mode = draw_dsc->blend_mode;
blend_dsc.blend_area = &blend_area;
if(lv_img_cf_is_chroma_keyed(cf)) cf = LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED;
else if(cf == LV_IMG_CF_ALPHA_8BIT) {}
else if(cf == LV_IMG_CF_RGB565A8) {}
else if(lv_img_cf_has_alpha(cf)) cf = LV_IMG_CF_TRUE_COLOR_ALPHA;
else cf = LV_IMG_CF_TRUE_COLOR;
/*The simplest case just copy the pixels into the draw_buf*/
if(!mask_any && !transform && cf == LV_IMG_CF_TRUE_COLOR && draw_dsc->recolor_opa == LV_OPA_TRANSP) {
blend_dsc.src_buf = (const lv_color_t *)src_buf;
@@ -859,6 +946,9 @@ static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx,
lv_draw_sw_blend(draw_ctx, &blend_dsc);
}
else if(!mask_any && !transform && cf == LV_IMG_CF_ALPHA_8BIT) {
lv_area_t clipped_coords;
if(!_lv_area_intersect(&clipped_coords, coords, draw_ctx->clip_area)) return;
blend_dsc.mask_buf = (lv_opa_t *)src_buf;
blend_dsc.mask_area = coords;
blend_dsc.src_buf = NULL;
@@ -869,7 +959,8 @@ static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx,
lv_draw_sw_blend(draw_ctx, &blend_dsc);
}
#if LV_COLOR_DEPTH == 16
else if(!mask_any && !transform && cf == LV_IMG_CF_RGB565A8 && draw_dsc->recolor_opa == LV_OPA_TRANSP) {
else if(!mask_any && !transform && cf == LV_IMG_CF_RGB565A8 && draw_dsc->recolor_opa == LV_OPA_TRANSP &&
blend_dsc.opa >= LV_OPA_MAX) {
lv_coord_t src_w = lv_area_get_width(coords);
lv_coord_t src_h = lv_area_get_height(coords);
blend_dsc.src_buf = (const lv_color_t *)src_buf;
@@ -922,6 +1013,23 @@ static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx,
LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER;
blend_dsc.mask_res = mask_res_def;
if(cf == LV_IMG_CF_ALPHA_8BIT) {
/* original code:
lv_color_fill(rgb_buf, draw_dsc->recolor, buf_size);
*/
arm_2d_size_t copy_size = {
.iWidth = buf_w,
.iHeight = buf_h,
};
/* apply re-colour */
__arm_2d_impl_colour_filling(
(color_int *)rgb_buf,
buf_w,
&copy_size,
(color_int)draw_dsc->recolor.full);
}
bool is_accelerated = false;
if(!transform) {
@@ -968,7 +1076,7 @@ static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx,
}
else if((LV_COLOR_DEPTH == 32)
&& !mask_any
&& (cf == LV_IMG_CF_TRUE_COLOR_ALPHA)) {
&& (LV_IMG_CF_TRUE_COLOR_ALPHA == cf)) {
/* accelerate copy-with-source-masks-and-opacity */
/* *INDENT-OFF* */
@@ -1025,6 +1133,63 @@ static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx,
)
/* *INDENT-ON* */
}
else if(!mask_any
&& (LV_IMG_CF_RGB565A8 == cf)) {
/* accelerate copy-with-source-masks-and-opacity */
uint8_t * mask_after_rgb = src_buf + sizeof(lv_color_t) * src_w * src_h;
/* *INDENT-OFF* */
__RECOLOUR_WRAPPER(
__PREPARE_LL_ACCELERATION__();
uint8_t * mask_temp_buf = NULL;
if(blend_dsc.opa < LV_OPA_MAX) {
mask_temp_buf = lv_mem_buf_get(copy_size.iHeight * copy_size.iWidth);
if(NULL == mask_temp_buf) {
LV_LOG_WARN(
"Failed to allocate memory for alpha mask,"
" use normal route instead.");
break;
}
lv_memset_00(mask_temp_buf, copy_size.iHeight * copy_size.iWidth);
__arm_2d_impl_gray8_colour_filling_mask_opacity(
mask_temp_buf,
src_stride,
mask_after_rgb,
src_stride,
&copy_size,
0xFF,
blend_dsc.opa);
__arm_2d_impl_src_msk_copy(
(color_int *)src_buf_tmp,
src_stride,
mask_temp_buf,
src_stride,
&copy_size,
(color_int *)dest_buf,
dest_stride,
&copy_size);
lv_mem_buf_release(mask_temp_buf);
}
else {
__arm_2d_impl_src_msk_copy(
(color_int *)src_buf_tmp,
src_stride,
mask_after_rgb,
src_stride,
&copy_size,
(color_int *)dest_buf,
dest_stride,
&copy_size);
}
is_accelerated = true;
)
/* *INDENT-ON* */
}
else if(!mask_any && (cf == LV_IMG_CF_TRUE_COLOR)) {
/* accelerate copy-with-source-masks-and-opacity */
@@ -1063,6 +1228,7 @@ static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx,
&& (draw_dsc->recolor_opa == LV_OPA_TRANSP)
&& (((LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED == cf)
|| (LV_IMG_CF_TRUE_COLOR == cf))
|| (LV_IMG_CF_RGB565A8 == cf)
#if defined(__ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__) && __ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__
|| ((LV_IMG_CF_TRUE_COLOR_ALPHA == cf)
&& (LV_COLOR_DEPTH == 32))
@@ -1070,6 +1236,7 @@ static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx,
)
) {
uint8_t * mask_after_rgb = src_buf + sizeof(lv_color_t) * src_w * src_h;
/* *INDENT-OFF* */
__RECOLOUR_WRAPPER(
/* accelerate transform without re-color */
@@ -1108,17 +1275,6 @@ static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx,
&target_tile,
false);
target_region = (arm_2d_region_t) {
.tLocation = {
.iX = coords->x1 - draw_ctx->clip_area->x1,
.iY = coords->y1 - draw_ctx->clip_area->y1,
},
.tSize = {
.iWidth = lv_area_get_width(coords),
.iHeight = lv_area_get_height(coords),
},
};
static arm_2d_tile_t source_tile;
source_tile = (arm_2d_tile_t) {
@@ -1132,46 +1288,99 @@ static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx,
.pchBuffer = (uint8_t *)src_buf,
};
static arm_2d_tile_t mask_tile;
mask_tile = source_tile;
mask_tile.tInfo.bHasEnforcedColour = true;
mask_tile.tInfo.tColourInfo.chScheme = ARM_2D_CHANNEL_8in32;
mask_tile.pchBuffer += 3;
static arm_2d_location_t source_center, target_center;
source_center.iX = draw_dsc->pivot.x;
source_center.iY = draw_dsc->pivot.y;
if(LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED == cf) {
if((LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED == cf) ||
(LV_IMG_CF_TRUE_COLOR == cf)) {
arm_2d_tile_transform_with_opacity(
__ARM_2D_PREPARE_TRANS_AND_TARGET_REGION(
arm_2d_tile_transform_with_opacity_prepare,
&source_tile,
&target_tile,
&target_region,
source_center,
ARM_2D_ANGLE((draw_dsc->angle / 10.0f)),
draw_dsc->zoom / 256.0f,
(color_int)LV_COLOR_CHROMA_KEY.full,
blend_dsc.opa);
is_accelerated = true;
}
#if defined(__ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__) \
&& __ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__
else if((LV_IMG_CF_TRUE_COLOR_ALPHA == cf) &&
(LV_COLOR_DEPTH == 32)) {
arm_2d_tile_transform_with_src_mask_and_opacity(
&source_tile,
&mask_tile,
arm_2d_tile_transform(
&target_tile,
&target_region,
NULL
);
is_accelerated = true;
}
#if ARM_2D_VERISON >= 10103
else if (LV_IMG_CF_TRUE_COLOR == cf) {
__ARM_2D_PREPARE_TRANS_AND_TARGET_REGION(
arm_2d_tile_transform_only_with_opacity_prepare,
&source_tile,
source_center,
ARM_2D_ANGLE((draw_dsc->angle / 10.0f)),
draw_dsc->zoom / 256.0f,
blend_dsc.opa);
arm_2d_tile_transform(
&target_tile,
&target_region,
NULL
);
is_accelerated = true;
}
#endif
else if (LV_IMG_CF_RGB565A8 == cf) {
static arm_2d_tile_t mask_tile;
mask_tile = source_tile;
mask_tile.tInfo.bHasEnforcedColour = true;
mask_tile.tInfo.tColourInfo.chScheme = ARM_2D_COLOUR_GRAY8;
mask_tile.pchBuffer = mask_after_rgb;
__ARM_2D_PREPARE_TRANS_AND_TARGET_REGION(
arm_2d_tile_transform_with_src_mask_and_opacity_prepare,
&source_tile,
&mask_tile,
source_center,
ARM_2D_ANGLE((draw_dsc->angle / 10.0f)),
draw_dsc->zoom / 256.0f,
blend_dsc.opa
);
arm_2d_tile_transform(
&target_tile,
&target_region,
NULL
);
is_accelerated = true;
}
#if defined(__ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__) \
&& __ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__
else if((LV_IMG_CF_TRUE_COLOR_ALPHA == cf) &&
(LV_COLOR_DEPTH == 32)) {
static arm_2d_tile_t mask_tile;
mask_tile = source_tile;
mask_tile.tInfo.bHasEnforcedColour = true;
mask_tile.tInfo.tColourInfo.chScheme = ARM_2D_CHANNEL_8in32;
mask_tile.pchBuffer += 3;
__ARM_2D_PREPARE_TRANS_AND_TARGET_REGION(
arm_2d_tile_transform_with_src_mask_and_opacity_prepare,
&source_tile,
&mask_tile,
source_center,
ARM_2D_ANGLE((draw_dsc->angle / 10.0f)),
draw_dsc->zoom / 256.0f,
blend_dsc.opa
);
arm_2d_tile_transform(
&target_tile,
&target_region,
NULL
);
is_accelerated = true;
}
#endif
@@ -1208,7 +1417,7 @@ static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx,
(color_int)draw_dsc->recolor.full,
draw_dsc->recolor_opa);
}
#if LV_DRAW_COMPLEX
#if LV_USE_DRAW_MASKS
/*Apply the masks if any*/
if(mask_any) {
lv_coord_t y;
@@ -1275,7 +1484,7 @@ static void convert_cb(const lv_area_t * dest_area, const void * src_buf, lv_coo
if(cf == LV_IMG_CF_TRUE_COLOR || cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) {
uint32_t px_cnt = lv_area_get_size(dest_area);
lv_memset_ff(abuf, px_cnt);
lv_memset(abuf, 0xff, px_cnt);
src_tmp8 += (src_stride * dest_area->y1 * sizeof(lv_color_t)) + dest_area->x1 * sizeof(lv_color_t);
uint32_t dest_w = lv_area_get_width(dest_area);

View File

@@ -72,6 +72,7 @@ typedef struct _lv_draw_ctx_t {
*/
const lv_area_t * clip_area;
void (*init_buf)(struct _lv_draw_ctx_t * draw_ctx);
void (*draw_rect)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);

View File

@@ -69,18 +69,19 @@ void lv_draw_img(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, const
if(dsc->opa <= LV_OPA_MIN) return;
lv_res_t res;
lv_res_t res = LV_RES_INV;
if(draw_ctx->draw_img) {
res = draw_ctx->draw_img(draw_ctx, dsc, coords, src);
}
else {
if(res != LV_RES_OK) {
res = decode_and_draw(draw_ctx, dsc, coords, src);
}
if(res == LV_RES_INV) {
if(res != LV_RES_OK) {
LV_LOG_WARN("Image draw error");
show_error(draw_ctx, coords, "No\ndata");
return;
}
}
@@ -197,11 +198,19 @@ lv_img_src_t lv_img_src_get_type(const void * src)
if(src == NULL) return img_src_type;
const uint8_t * u8_p = src;
/*The first byte shows the type of the image source*/
/*The first or fourth byte depending on platform endianess shows the type of the image source*/
#if LV_BIG_ENDIAN_SYSTEM
if(u8_p[3] >= 0x20 && u8_p[3] <= 0x7F) {
#else
if(u8_p[0] >= 0x20 && u8_p[0] <= 0x7F) {
#endif
img_src_type = LV_IMG_SRC_FILE; /*If it's an ASCII character then it's file name*/
}
#if LV_BIG_ENDIAN_SYSTEM
else if(u8_p[3] >= 0x80) {
#else
else if(u8_p[0] >= 0x80) {
#endif
img_src_type = LV_IMG_SRC_SYMBOL; /*Symbols begins after 0x7F*/
}
else {

View File

@@ -144,7 +144,7 @@ void _lv_img_decoder_init(void);
* Get information about an image.
* Try the created image decoder one by one. Once one is able to get info that info will be used.
* @param src the image source. Can be
* 1) File name: E.g. "S:folder/img1.png" (The drivers needs to registered via `lv_fs_add_drv()`)
* 1) File name: E.g. "S:folder/img1.png" (The drivers needs to registered via `lv_fs_drv_register()`)
* 2) Variable: Pointer to an `lv_img_dsc_t` variable
* 3) Symbol: E.g. `LV_SYMBOL_OK`
* @param header the image info will be stored here
@@ -157,7 +157,7 @@ lv_res_t lv_img_decoder_get_info(const void * src, lv_img_header_t * header);
* Try the created image decoders one by one. Once one is able to open the image that decoder is saved in `dsc`
* @param dsc describes a decoding session. Simply a pointer to an `lv_img_decoder_dsc_t` variable.
* @param src the image source. Can be
* 1) File name: E.g. "S:folder/img1.png" (The drivers needs to registered via `lv_fs_add_drv()`)
* 1) File name: E.g. "S:folder/img1.png" (The drivers needs to registered via `lv_fs_drv_register())`)
* 2) Variable: Pointer to an `lv_img_dsc_t` variable
* 3) Symbol: E.g. `LV_SYMBOL_OK`
* @param color The color of the image with `LV_IMG_CF_ALPHA_...`

View File

@@ -1,5 +1,3 @@
CSRCS += lv_gpu_nxp.c
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp

View File

@@ -1,418 +0,0 @@
/**
* @file lv_gpu_nxp.c
*
*/
/**
* MIT License
*
* Copyright 2022 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next paragraph)
* shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_gpu_nxp.h"
#if LV_USE_GPU_NXP_PXP || LV_USE_GPU_NXP_VG_LITE
/*
* allow to use both PXP and VGLITE
* both 2D accelerators can be used at the same time:
* thus VGLITE can be used to accelerate widget drawing
* while PXP accelerates Blit & Fill operations.
*/
#if LV_USE_GPU_NXP_PXP
#include "pxp/lv_draw_pxp_blend.h"
#endif
#if LV_USE_GPU_NXP_VG_LITE
#include "vglite/lv_draw_vglite_blend.h"
#include "vglite/lv_draw_vglite_rect.h"
#include "vglite/lv_draw_vglite_arc.h"
#endif
#if LV_COLOR_DEPTH != 32
#include "../../core/lv_refr.h"
#endif
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void lv_draw_nxp_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc,
const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t cf);
static void lv_draw_nxp_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc);
static void lv_draw_nxp_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
static lv_res_t draw_nxp_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
static void lv_draw_nxp_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center,
uint16_t radius, uint16_t start_angle, uint16_t end_angle);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_nxp_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
{
lv_draw_sw_init_ctx(drv, draw_ctx);
lv_draw_nxp_ctx_t * nxp_draw_ctx = (lv_draw_sw_ctx_t *)draw_ctx;
nxp_draw_ctx->base_draw.draw_arc = lv_draw_nxp_arc;
nxp_draw_ctx->base_draw.draw_rect = lv_draw_nxp_rect;
nxp_draw_ctx->base_draw.draw_img_decoded = lv_draw_nxp_img_decoded;
nxp_draw_ctx->blend = lv_draw_nxp_blend;
//nxp_draw_ctx->base_draw.wait_for_finish = lv_draw_nxp_wait_cb;
}
void lv_draw_nxp_ctx_deinit(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
{
lv_draw_sw_deinit_ctx(drv, draw_ctx);
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* During rendering, LVGL might initializes new draw_ctxs and start drawing into
* a separate buffer (called layer). If the content to be rendered has "holes",
* e.g. rounded corner, LVGL temporarily sets the disp_drv.screen_transp flag.
* It means the renderers should draw into an ARGB buffer.
* With 32 bit color depth it's not a big problem but with 16 bit color depth
* the target pixel format is ARGB8565 which is not supported by the GPU.
* In this case, the NXP callbacks should fallback to SW rendering.
*/
static inline bool need_argb8565_support()
{
#if LV_COLOR_DEPTH != 32
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
if(disp->driver->screen_transp == 1)
return true;
#endif
return false;
}
static void lv_draw_nxp_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc)
{
lv_area_t blend_area;
/*Let's get the blend area which is the intersection of the area to fill and the clip area.*/
if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area))
return; /*Fully clipped, nothing to do*/
/*Make the blend area relative to the buffer*/
lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
bool done = false;
/*Fill/Blend only non masked, normal blended*/
if(dsc->mask_buf == NULL && dsc->blend_mode == LV_BLEND_MODE_NORMAL && !need_argb8565_support()) {
lv_color_t * dest_buf = draw_ctx->buf;
lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area);
#if LV_USE_GPU_NXP_VG_LITE
lv_coord_t dest_width = lv_area_get_width(draw_ctx->buf_area);
lv_coord_t dest_height = lv_area_get_height(draw_ctx->buf_area);
#endif
const lv_color_t * src_buf = dsc->src_buf;
if(src_buf == NULL) {
#if LV_USE_GPU_NXP_PXP
done = (lv_gpu_nxp_pxp_fill(dest_buf, dest_stride, &blend_area,
dsc->color, dsc->opa) == LV_RES_OK);
if(!done)
PXP_LOG_TRACE("PXP fill failed. Fallback.");
#endif
#if LV_USE_GPU_NXP_VG_LITE
if(!done) {
done = (lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &blend_area,
dsc->color, dsc->opa) == LV_RES_OK);
if(!done)
VG_LITE_LOG_TRACE("VG-Lite fill failed. Fallback.");
}
#endif
}
else {
#if LV_USE_GPU_NXP_PXP
done = (lv_gpu_nxp_pxp_blit(dest_buf, &blend_area, dest_stride, src_buf, dsc->blend_area,
dsc->opa, LV_DISP_ROT_NONE) == LV_RES_OK);
if(!done)
PXP_LOG_TRACE("PXP blit failed. Fallback.");
#endif
#if LV_USE_GPU_NXP_VG_LITE
if(!done) {
lv_gpu_nxp_vglite_blit_info_t blit;
lv_coord_t src_stride = lv_area_get_width(dsc->blend_area);
blit.src = src_buf;
blit.src_width = lv_area_get_width(dsc->blend_area);
blit.src_height = lv_area_get_height(dsc->blend_area);
blit.src_stride = src_stride * (int32_t)sizeof(lv_color_t);
blit.src_area.x1 = (blend_area.x1 - (dsc->blend_area->x1 - draw_ctx->buf_area->x1));
blit.src_area.y1 = (blend_area.y1 - (dsc->blend_area->y1 - draw_ctx->buf_area->y1));
blit.src_area.x2 = blit.src_area.x1 + blit.src_width - 1;
blit.src_area.y2 = blit.src_area.y1 + blit.src_height - 1;
blit.dst = dest_buf;
blit.dst_width = dest_width;
blit.dst_height = dest_height;
blit.dst_stride = dest_stride * (int32_t)sizeof(lv_color_t);
blit.dst_area.x1 = blend_area.x1;
blit.dst_area.y1 = blend_area.y1;
blit.dst_area.x2 = blend_area.x2;
blit.dst_area.y2 = blend_area.y2;
blit.opa = dsc->opa;
blit.zoom = LV_IMG_ZOOM_NONE;
blit.angle = 0;
done = (lv_gpu_nxp_vglite_blit(&blit) == LV_RES_OK);
if(!done)
VG_LITE_LOG_TRACE("VG-Lite blit failed. Fallback.");
}
#endif
}
}
if(!done)
lv_draw_sw_blend_basic(draw_ctx, dsc);
}
static void lv_draw_nxp_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc,
const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t cf)
{
/*Use the clip area as draw area*/
lv_area_t draw_area;
lv_area_copy(&draw_area, draw_ctx->clip_area);
bool mask_any = lv_draw_mask_is_any(&draw_area);
#if LV_USE_GPU_NXP_VG_LITE
bool recolor = (dsc->recolor_opa != LV_OPA_TRANSP);
#endif
#if LV_USE_GPU_NXP_PXP
bool scale = (dsc->zoom != LV_IMG_ZOOM_NONE);
#endif
bool done = false;
lv_area_t blend_area;
/*Let's get the blend area which is the intersection of the area to fill and the clip area.*/
if(!_lv_area_intersect(&blend_area, coords, draw_ctx->clip_area))
return; /*Fully clipped, nothing to do*/
/*Make the blend area relative to the buffer*/
lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
const lv_color_t * src_buf = (const lv_color_t *)map_p;
if(!src_buf) {
lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf);
return;
}
lv_color_t * dest_buf = draw_ctx->buf;
lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area);
#if LV_USE_GPU_NXP_PXP
if(!mask_any && !scale && !need_argb8565_support()
#if LV_COLOR_DEPTH!=32
&& !lv_img_cf_has_alpha(cf)
#endif
) {
done = (lv_gpu_nxp_pxp_blit_transform(dest_buf, &blend_area, dest_stride, src_buf, coords,
dsc, cf) == LV_RES_OK);
if(!done)
PXP_LOG_TRACE("PXP blit transform failed. Fallback.");
}
#endif
#if LV_USE_GPU_NXP_VG_LITE
if(!done && !mask_any && !need_argb8565_support() &&
!lv_img_cf_is_chroma_keyed(cf) && !recolor
#if LV_COLOR_DEPTH!=32
&& !lv_img_cf_has_alpha(cf)
#endif
) {
lv_gpu_nxp_vglite_blit_info_t blit;
lv_coord_t src_stride = lv_area_get_width(coords);
blit.src = src_buf;
blit.src_width = lv_area_get_width(coords);
blit.src_height = lv_area_get_height(coords);
blit.src_stride = src_stride * (int32_t)sizeof(lv_color_t);
blit.src_area.x1 = (blend_area.x1 - (coords->x1 - draw_ctx->buf_area->x1));
blit.src_area.y1 = (blend_area.y1 - (coords->y1 - draw_ctx->buf_area->y1));
blit.src_area.x2 = blit.src_area.x1 + blit.src_width - 1;
blit.src_area.y2 = blit.src_area.y1 + blit.src_height - 1;
blit.dst = dest_buf;
blit.dst_width = lv_area_get_width(draw_ctx->buf_area);
blit.dst_height = lv_area_get_height(draw_ctx->buf_area);
blit.dst_stride = dest_stride * (int32_t)sizeof(lv_color_t);
blit.dst_area.x1 = blend_area.x1;
blit.dst_area.y1 = blend_area.y1;
blit.dst_area.x2 = blend_area.x2;
blit.dst_area.y2 = blend_area.y2;
blit.opa = dsc->opa;
blit.angle = dsc->angle;
blit.pivot = dsc->pivot;
blit.zoom = dsc->zoom;
done = (lv_gpu_nxp_vglite_blit_transform(&blit) == LV_RES_OK);
if(!done)
VG_LITE_LOG_TRACE("VG-Lite blit transform failed. Fallback.");
}
#endif
if(!done)
lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf);
}
static void lv_draw_nxp_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords)
{
bool done = false;
lv_draw_rect_dsc_t nxp_dsc;
lv_memcpy(&nxp_dsc, dsc, sizeof(nxp_dsc));
#if LV_DRAW_COMPLEX
/* Draw only the shadow */
nxp_dsc.bg_opa = 0;
nxp_dsc.bg_img_opa = 0;
nxp_dsc.border_opa = 0;
nxp_dsc.outline_opa = 0;
lv_draw_sw_rect(draw_ctx, &nxp_dsc, coords);
/* Draw the background */
nxp_dsc.shadow_opa = 0;
nxp_dsc.bg_opa = dsc->bg_opa;
done = (draw_nxp_bg(draw_ctx, &nxp_dsc, coords) == LV_RES_OK);
#endif /*LV_DRAW_COMPLEX*/
/* Draw the remaining parts */
nxp_dsc.shadow_opa = 0;
if(done)
nxp_dsc.bg_opa = 0;
nxp_dsc.bg_img_opa = dsc->bg_img_opa;
nxp_dsc.border_opa = dsc->border_opa;
nxp_dsc.outline_opa = dsc->outline_opa;
lv_draw_sw_rect(draw_ctx, &nxp_dsc, coords);
}
static lv_res_t draw_nxp_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords)
{
if(dsc->bg_opa <= LV_OPA_MIN)
return LV_RES_INV;
lv_area_t bg_coords;
lv_area_copy(&bg_coords, coords);
/*If the border fully covers make the bg area 1px smaller to avoid artifacts on the corners*/
if(dsc->border_width > 1 && dsc->border_opa >= (lv_opa_t)LV_OPA_MAX && dsc->radius != 0) {
bg_coords.x1 += (dsc->border_side & LV_BORDER_SIDE_LEFT) ? 1 : 0;
bg_coords.y1 += (dsc->border_side & LV_BORDER_SIDE_TOP) ? 1 : 0;
bg_coords.x2 -= (dsc->border_side & LV_BORDER_SIDE_RIGHT) ? 1 : 0;
bg_coords.y2 -= (dsc->border_side & LV_BORDER_SIDE_BOTTOM) ? 1 : 0;
}
lv_area_t clipped_coords;
if(!_lv_area_intersect(&clipped_coords, &bg_coords, draw_ctx->clip_area))
return LV_RES_INV;
lv_grad_dir_t grad_dir = dsc->bg_grad.dir;
lv_color_t bg_color = grad_dir == LV_GRAD_DIR_NONE ? dsc->bg_color : dsc->bg_grad.stops[0].color;
if(bg_color.full == dsc->bg_grad.stops[1].color.full) grad_dir = LV_GRAD_DIR_NONE;
bool mask_any = lv_draw_mask_is_any(&bg_coords);
/*
* Most simple case: just a plain rectangle (no mask, no radius, no gradient)
* shall fallback to lv_draw_sw_blend().
*
* Complex case: gradient or radius but no mask.
*/
if(!mask_any && ((dsc->radius != 0) || (grad_dir != LV_GRAD_DIR_NONE)) && !need_argb8565_support()) {
#if LV_USE_GPU_NXP_VG_LITE
lv_res_t res = lv_gpu_nxp_vglite_draw_bg(draw_ctx, dsc, &bg_coords);
if(res != LV_RES_OK)
VG_LITE_LOG_TRACE("VG-Lite draw bg failed. Fallback.");
return res;
#endif
}
return LV_RES_INV;
}
static void lv_draw_nxp_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center,
uint16_t radius, uint16_t start_angle, uint16_t end_angle)
{
bool done = false;
#if LV_DRAW_COMPLEX
if(dsc->opa <= LV_OPA_MIN)
return;
if(dsc->width == 0)
return;
if(start_angle == end_angle)
return;
#if LV_USE_GPU_NXP_VG_LITE
if(!need_argb8565_support()) {
done = (lv_gpu_nxp_vglite_draw_arc(draw_ctx, dsc, center, (int32_t)radius,
(int32_t)start_angle, (int32_t)end_angle) == LV_RES_OK);
if(!done)
VG_LITE_LOG_TRACE("VG-Lite draw arc failed. Fallback.");
}
#endif
#endif/*LV_DRAW_COMPLEX*/
if(!done)
lv_draw_sw_arc(draw_ctx, dsc, center, radius, start_angle, end_angle);
}
#endif /*LV_USE_GPU_NXP_PXP || LV_USE_GPU_NXP_VG_LITE*/

View File

@@ -1,3 +1,4 @@
CSRCS += lv_draw_pxp.c
CSRCS += lv_draw_pxp_blend.c
CSRCS += lv_gpu_nxp_pxp_osa.c
CSRCS += lv_gpu_nxp_pxp.c

View File

@@ -0,0 +1,275 @@
/**
* @file lv_draw_pxp.c
*
*/
/**
* MIT License
*
* Copyright 2022, 2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next paragraph)
* shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_pxp.h"
#if LV_USE_GPU_NXP_PXP
#include "lv_draw_pxp_blend.h"
#if LV_COLOR_DEPTH != 32
#include "../../../core/lv_refr.h"
#endif
/*********************
* DEFINES
*********************/
/* Minimum area (in pixels) for PXP blit/fill processing. */
#ifndef LV_GPU_NXP_PXP_SIZE_LIMIT
#define LV_GPU_NXP_PXP_SIZE_LIMIT 5000
#endif
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void lv_draw_pxp_wait_for_finish(lv_draw_ctx_t * draw_ctx);
static void lv_draw_pxp_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc);
static void lv_draw_pxp_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc,
const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t cf);
static void lv_draw_pxp_buffer_copy(lv_draw_ctx_t * draw_ctx,
void * dest_buf, lv_coord_t dest_stride, const lv_area_t * dest_area,
void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_pxp_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
{
lv_draw_sw_init_ctx(drv, draw_ctx);
lv_draw_pxp_ctx_t * pxp_draw_ctx = (lv_draw_sw_ctx_t *)draw_ctx;
pxp_draw_ctx->base_draw.draw_img_decoded = lv_draw_pxp_img_decoded;
pxp_draw_ctx->blend = lv_draw_pxp_blend;
pxp_draw_ctx->base_draw.wait_for_finish = lv_draw_pxp_wait_for_finish;
pxp_draw_ctx->base_draw.buffer_copy = lv_draw_pxp_buffer_copy;
}
void lv_draw_pxp_ctx_deinit(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
{
lv_draw_sw_deinit_ctx(drv, draw_ctx);
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* During rendering, LVGL might initializes new draw_ctxs and start drawing into
* a separate buffer (called layer). If the content to be rendered has "holes",
* e.g. rounded corner, LVGL temporarily sets the disp_drv.screen_transp flag.
* It means the renderers should draw into an ARGB buffer.
* With 32 bit color depth it's not a big problem but with 16 bit color depth
* the target pixel format is ARGB8565 which is not supported by the GPU.
* In this case, the PXP callbacks should fallback to SW rendering.
*/
static inline bool need_argb8565_support()
{
#if LV_COLOR_DEPTH != 32
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
if(disp->driver->screen_transp == 1)
return true;
#endif
return false;
}
static void lv_draw_pxp_wait_for_finish(lv_draw_ctx_t * draw_ctx)
{
lv_gpu_nxp_pxp_wait();
lv_draw_sw_wait_for_finish(draw_ctx);
}
static void lv_draw_pxp_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc)
{
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
return;
if(need_argb8565_support()) {
lv_draw_sw_blend_basic(draw_ctx, dsc);
return;
}
lv_area_t blend_area;
/*Let's get the blend area which is the intersection of the area to draw and the clip area*/
if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area))
return; /*Fully clipped, nothing to do*/
/*Make the blend area relative to the buffer*/
lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
if(dsc->mask_buf != NULL || dsc->blend_mode != LV_BLEND_MODE_NORMAL ||
lv_area_get_size(&blend_area) < LV_GPU_NXP_PXP_SIZE_LIMIT) {
lv_draw_sw_blend_basic(draw_ctx, dsc);
return;
}
/*Fill/Blend only non masked, normal blended*/
lv_color_t * dest_buf = draw_ctx->buf;
lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area);
const lv_color_t * src_buf = dsc->src_buf;
if(src_buf == NULL) {
lv_gpu_nxp_pxp_fill(dest_buf, &blend_area, dest_stride, dsc->color, dsc->opa);
}
else {
lv_area_t src_area;
src_area.x1 = blend_area.x1 - (dsc->blend_area->x1 - draw_ctx->buf_area->x1);
src_area.y1 = blend_area.y1 - (dsc->blend_area->y1 - draw_ctx->buf_area->y1);
src_area.x2 = src_area.x1 + lv_area_get_width(dsc->blend_area) - 1;
src_area.y2 = src_area.y1 + lv_area_get_height(dsc->blend_area) - 1;
lv_coord_t src_stride = lv_area_get_width(dsc->blend_area);
lv_gpu_nxp_pxp_blit(dest_buf, &blend_area, dest_stride, src_buf, &src_area, src_stride,
dsc->opa, LV_DISP_ROT_NONE);
}
}
static void lv_draw_pxp_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc,
const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t cf)
{
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
return;
if(need_argb8565_support()) {
lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf);
return;
}
const lv_color_t * src_buf = (const lv_color_t *)map_p;
if(!src_buf) {
lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf);
return;
}
lv_area_t rel_coords;
lv_area_copy(&rel_coords, coords);
lv_area_move(&rel_coords, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
lv_area_t rel_clip_area;
lv_area_copy(&rel_clip_area, draw_ctx->clip_area);
lv_area_move(&rel_clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
bool has_scale = (dsc->zoom != LV_IMG_ZOOM_NONE);
bool has_rotation = (dsc->angle != 0);
bool unsup_rotation = false;
lv_area_t blend_area;
if(has_rotation)
lv_area_copy(&blend_area, &rel_coords);
else if(!_lv_area_intersect(&blend_area, &rel_coords, &rel_clip_area))
return; /*Fully clipped, nothing to do*/
bool has_mask = lv_draw_mask_is_any(&blend_area);
lv_coord_t src_width = lv_area_get_width(coords);
lv_coord_t src_height = lv_area_get_height(coords);
if(has_rotation) {
/*
* PXP can only rotate at 90x angles.
*/
if(dsc->angle % 900) {
PXP_LOG_TRACE("Rotation angle %d is not supported. PXP can rotate only 90x angle.", dsc->angle);
unsup_rotation = true;
}
/*
* PXP is set to process 16x16 blocks to optimize the system for memory
* bandwidth and image processing time.
* The output engine essentially truncates any output pixels after the
* desired number of pixels has been written.
* When rotating a source image and the output is not divisible by the block
* size, the incorrect pixels could be truncated and the final output image
* can look shifted.
*/
if(src_width % 16 || src_height % 16) {
PXP_LOG_TRACE("Rotation is not supported for image w/o alignment to block size 16x16.");
unsup_rotation = true;
}
}
if(has_mask || has_scale || unsup_rotation || lv_area_get_size(&blend_area) < LV_GPU_NXP_PXP_SIZE_LIMIT
#if LV_COLOR_DEPTH != 32
|| lv_img_cf_has_alpha(cf)
#endif
) {
lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf);
return;
}
lv_color_t * dest_buf = draw_ctx->buf;
lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area);
lv_area_t src_area;
src_area.x1 = blend_area.x1 - (coords->x1 - draw_ctx->buf_area->x1);
src_area.y1 = blend_area.y1 - (coords->y1 - draw_ctx->buf_area->y1);
src_area.x2 = src_area.x1 + src_width - 1;
src_area.y2 = src_area.y1 + src_height - 1;
lv_coord_t src_stride = lv_area_get_width(coords);
lv_gpu_nxp_pxp_blit_transform(dest_buf, &blend_area, dest_stride, src_buf, &src_area, src_stride,
dsc, cf);
}
static void lv_draw_pxp_buffer_copy(lv_draw_ctx_t * draw_ctx,
void * dest_buf, lv_coord_t dest_stride, const lv_area_t * dest_area,
void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area)
{
LV_UNUSED(draw_ctx);
if(lv_area_get_size(dest_area) < LV_GPU_NXP_PXP_SIZE_LIMIT) {
lv_draw_sw_buffer_copy(draw_ctx, dest_buf, dest_stride, dest_area, src_buf, src_stride, src_area);
return;
}
lv_gpu_nxp_pxp_buffer_copy(dest_buf, dest_area, dest_stride, src_buf, src_area, src_stride);
}
#endif /*LV_USE_GPU_NXP_PXP*/

View File

@@ -1,12 +1,12 @@
/**
* @file lv_gpu_nxp.h
* @file lv_draw_pxp.h
*
*/
/**
* MIT License
*
* Copyright 2022 NXP
* Copyright 2022, 2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -27,8 +27,8 @@
*
*/
#ifndef LV_GPU_NXP_H
#define LV_GPU_NXP_H
#ifndef LV_DRAW_PXP_H
#define LV_DRAW_PXP_H
#ifdef __cplusplus
extern "C" {
@@ -38,9 +38,10 @@ extern "C" {
* INCLUDES
*********************/
#include "../../lv_conf_internal.h"
#if LV_USE_GPU_NXP_PXP || LV_USE_GPU_NXP_VG_LITE
#include "../sw/lv_draw_sw.h"
#include "../../../lv_conf_internal.h"
#if LV_USE_GPU_NXP_PXP
#include "../../sw/lv_draw_sw.h"
/*********************
* DEFINES
@@ -49,23 +50,23 @@ extern "C" {
/**********************
* TYPEDEFS
**********************/
typedef lv_draw_sw_ctx_t lv_draw_nxp_ctx_t;
typedef lv_draw_sw_ctx_t lv_draw_pxp_ctx_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_draw_nxp_ctx_init(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
void lv_draw_pxp_ctx_init(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
void lv_draw_nxp_ctx_deinit(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
void lv_draw_pxp_ctx_deinit(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
/**********************
* MACROS
**********************/
#endif /*LV_USE_GPU_NXP_PXP || LV_USE_GPU_NXP_VG_LITE*/
#endif /*LV_USE_GPU_NXP_PXP*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_GPU_NXP_H*/
#endif /*LV_DRAW_PXP_H*/

View File

@@ -6,7 +6,7 @@
/**
* MIT License
*
* Copyright 2020-2022 NXP
* Copyright 2020-2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -34,6 +34,7 @@
#include "lv_draw_pxp_blend.h"
#if LV_USE_GPU_NXP_PXP
#include "lvgl_support.h"
/*********************
* DEFINES
@@ -43,25 +44,25 @@
#error Color swap not implemented. Disable LV_COLOR_16_SWAP feature.
#endif
#if LV_COLOR_DEPTH==16
#if LV_COLOR_DEPTH == 16
#define PXP_OUT_PIXEL_FORMAT kPXP_OutputPixelFormatRGB565
#define PXP_AS_PIXEL_FORMAT kPXP_AsPixelFormatRGB565
#define PXP_PS_PIXEL_FORMAT kPXP_PsPixelFormatRGB565
#elif LV_COLOR_DEPTH==32
#define PXP_TEMP_BUF_SIZE LCD_WIDTH * LCD_HEIGHT * 2U
#elif LV_COLOR_DEPTH == 32
#define PXP_OUT_PIXEL_FORMAT kPXP_OutputPixelFormatARGB8888
#define PXP_AS_PIXEL_FORMAT kPXP_AsPixelFormatARGB8888
#define PXP_PS_PIXEL_FORMAT kPXP_PsPixelFormatRGB888
#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))
#define PXP_PS_PIXEL_FORMAT kPXP_PsPixelFormatARGB8888
#else
#define PXP_PS_PIXEL_FORMAT kPXP_PsPixelFormatRGB888
#endif
#define PXP_TEMP_BUF_SIZE LCD_WIDTH * LCD_HEIGHT * 4U
#elif
#error Only 16bit and 32bit color depth are supported. Set LV_COLOR_DEPTH to 16 or 32.
#endif
#if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) \
|| defined (_WIN64) || defined (__LP64__) || defined (__LLP64__)
#define ALIGN_SIZE 8
#else
#define ALIGN_SIZE 4
#endif
/**********************
* TYPEDEFS
**********************/
@@ -70,63 +71,60 @@
* STATIC PROTOTYPES
**********************/
static LV_ATTRIBUTE_MEM_ALIGN uint8_t temp_buf[PXP_TEMP_BUF_SIZE];
/**
* BLock Image Transfer - copy rectangular image from src buffer to dst buffer
* with combination of transformation (rotation, scale, recolor) and opacity, alpha channel
* or color keying. This requires two steps. First step is used for transformation into
* a temporary buffer and the second one will handle the color format or opacity.
*
* @param[in/out] dest_buf destination buffer
* @param[in] dest_area area to be copied from src_buf to dst_buf
* @param[in] dest_stride width (stride) of destination buffer in pixels
* @param[in] src_buf source buffer
* @param[in] src_area source area with absolute coordinates to draw on destination buffer
* @param[in] dsc image descriptor
* @param[in] cf color format
* @retval LV_RES_OK Fill completed
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS)
* @param[in/out] dest_buf Destination buffer
* @param[in] dest_area Area with relative coordinates of destination buffer
* @param[in] dest_stride Stride of destination buffer in pixels
* @param[in] src_buf Source buffer
* @param[in] src_area Area with relative coordinates of source buffer
* @param[in] src_stride Stride of source buffer in pixels
* @param[in] dsc Image descriptor
* @param[in] cf Color format
*/
static lv_res_t lv_gpu_nxp_pxp_blit_opa(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area,
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf);
static void lv_pxp_blit_opa(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf);
/**
* BLock Image Transfer - copy rectangular image from src buffer to dst buffer
* with transformation and full opacity.
*
* @param[in/out] dest_buf destination buffer
* @param[in] dest_area area to be copied from src_buf to dst_buf
* @param[in] dest_stride width (stride) of destination buffer in pixels
* @param[in] src_buf source buffer
* @param[in] src_area source area with absolute coordinates to draw on destination buffer
* @param[in] dsc image descriptor
* @param[in] cf color format
* @retval LV_RES_OK Fill completed
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS)
* @param[in/out] dest_buf Destination buffer
* @param[in] dest_area Area with relative coordinates of destination buffer
* @param[in] dest_stride Stride of destination buffer in pixels
* @param[in] src_buf Source buffer
* @param[in] src_area Area with relative coordinates of source buffer
* @param[in] src_stride Stride of source buffer in pixels
* @param[in] dsc Image descriptor
* @param[in] cf Color format
*/
static lv_res_t lv_gpu_nxp_pxp_blit_cover(lv_color_t * dest_buf, const lv_area_t * dest_area,
lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area,
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf);
static void lv_pxp_blit_cover(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf);
/**
* BLock Image Transfer - copy rectangular image from src buffer to dst buffer
* without transformation but handling color format or opacity.
*
* @param[in/out] dest_buf destination buffer
* @param[in] dest_area area to be copied from src_buf to dst_buf
* @param[in] dest_stride width (stride) of destination buffer in pixels
* @param[in] src_buf source buffer
* @param[in] src_area source area with absolute coordinates to draw on destination buffer
* @param[in] dsc image descriptor
* @param[in] cf color format
* @retval LV_RES_OK Fill completed
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS)
* @param[in/out] dest_buf Destination buffer
* @param[in] dest_area Area with relative coordinates of destination buffer
* @param[in] dest_stride Stride of destination buffer in pixels
* @param[in] src_buf Source buffer
* @param[in] src_area Area with relative coordinates of source buffer
* @param[in] src_stride Stride of source buffer in pixels
* @param[in] dsc Image descriptor
* @param[in] cf Color format
*/
static lv_res_t lv_gpu_nxp_pxp_blit_cf(lv_color_t * dest_buf, const lv_area_t * dest_area,
lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area,
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf);
static void lv_pxp_blit_cf(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf);
/**********************
* STATIC VARIABLES
@@ -136,45 +134,27 @@ static lv_res_t lv_gpu_nxp_pxp_blit_cf(lv_color_t * dest_buf, const lv_area_t *
* MACROS
**********************/
#define ROUND_UP(x, align) ((x + (align - 1)) & ~(align - 1))
/**********************
* GLOBAL FUNCTIONS
**********************/
lv_res_t lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, lv_coord_t dest_stride, const lv_area_t * fill_area,
lv_color_t color, lv_opa_t opa)
void lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
lv_color_t color, lv_opa_t opa)
{
uint32_t area_size = lv_area_get_size(fill_area);
lv_coord_t area_w = lv_area_get_width(fill_area);
lv_coord_t area_h = lv_area_get_height(fill_area);
lv_coord_t dest_w = lv_area_get_width(dest_area);
lv_coord_t dest_h = lv_area_get_height(dest_area);
if(opa >= (lv_opa_t)LV_OPA_MAX) {
if(area_size < LV_GPU_NXP_PXP_FILL_SIZE_LIMIT) {
PXP_LOG_TRACE("Area size %d smaller than limit %d.", area_size, LV_GPU_NXP_PXP_FILL_SIZE_LIMIT);
return LV_RES_INV;
}
}
else {
if(area_size < LV_GPU_NXP_PXP_FILL_OPA_SIZE_LIMIT) {
PXP_LOG_TRACE("Area size %d smaller than limit %d.", area_size, LV_GPU_NXP_PXP_FILL_OPA_SIZE_LIMIT);
return LV_RES_INV;
}
}
PXP_Init(LV_GPU_NXP_PXP_ID);
PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false); /*Disable CSC1, it is enabled by default.*/
PXP_SetProcessBlockSize(LV_GPU_NXP_PXP_ID, kPXP_BlockSize16); /*Block size 16x16 for higher performance*/
lv_gpu_nxp_pxp_reset();
/*OUT buffer configure*/
pxp_output_buffer_config_t outputConfig = {
.pixelFormat = PXP_OUT_PIXEL_FORMAT,
.interlacedMode = kPXP_OutputProgressive,
.buffer0Addr = (uint32_t)(dest_buf + dest_stride * fill_area->y1 + fill_area->x1),
.buffer0Addr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_area->x1),
.buffer1Addr = (uint32_t)NULL,
.pitchBytes = dest_stride * sizeof(lv_color_t),
.width = area_w,
.height = area_h
.width = dest_w,
.height = dest_h
};
PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputConfig);
@@ -193,7 +173,7 @@ lv_res_t lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, lv_coord_t dest_stride, cons
};
PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig);
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, area_w, area_h);
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U);
}
/*Disable PS, use as color generator*/
@@ -223,34 +203,19 @@ lv_res_t lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, lv_coord_t dest_stride, cons
PXP_SetPorterDuffConfig(LV_GPU_NXP_PXP_ID, &pdConfig);
lv_gpu_nxp_pxp_run(); /*Start PXP task*/
return LV_RES_OK;
lv_gpu_nxp_pxp_run();
}
lv_res_t lv_gpu_nxp_pxp_blit(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_opa_t opa, lv_disp_rot_t angle)
void lv_gpu_nxp_pxp_blit(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
lv_opa_t opa, lv_disp_rot_t angle)
{
uint32_t dest_size = lv_area_get_size(dest_area);
lv_coord_t dest_w = lv_area_get_width(dest_area);
lv_coord_t dest_h = lv_area_get_height(dest_area);
lv_coord_t src_w = lv_area_get_width(src_area);
lv_coord_t src_h = lv_area_get_height(src_area);
if(opa >= (lv_opa_t)LV_OPA_MAX) {
if(dest_size < LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT) {
PXP_LOG_TRACE("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT);
return LV_RES_INV;
}
}
else {
if(dest_size < LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT) {
PXP_LOG_TRACE("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT);
return LV_RES_INV;
}
}
PXP_Init(LV_GPU_NXP_PXP_ID);
PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false); /*Disable CSC1, it is enabled by default.*/
PXP_SetProcessBlockSize(LV_GPU_NXP_PXP_ID, kPXP_BlockSize16); /*block size 16x16 for higher performance*/
lv_gpu_nxp_pxp_reset();
/* convert rotation angle */
pxp_rotate_degree_t pxp_rot;
@@ -297,19 +262,17 @@ lv_res_t lv_gpu_nxp_pxp_blit(lv_color_t * dest_buf, const lv_area_t * dest_area,
asBlendConfig.alphaMode = kPXP_AlphaOverride;
PXP_SetProcessSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &psBufferConfig);
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1, dest_h - 1);
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U);
}
lv_coord_t src_stride = lv_area_get_width(src_area);
/*AS buffer - source image*/
pxp_as_buffer_config_t asBufferConfig = {
.pixelFormat = PXP_AS_PIXEL_FORMAT,
.bufferAddr = (uint32_t)src_buf,
.bufferAddr = (uint32_t)(src_buf + src_stride * src_area->y1 + src_area->x1),
.pitchBytes = src_stride * sizeof(lv_color_t)
};
PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig);
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U);
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, src_w - 1U, src_h - 1U);
PXP_SetAlphaSurfaceBlendConfig(LV_GPU_NXP_PXP_ID, &asBlendConfig);
PXP_EnableAlphaSurfaceOverlayColorKey(LV_GPU_NXP_PXP_ID, false);
@@ -325,162 +288,147 @@ lv_res_t lv_gpu_nxp_pxp_blit(lv_color_t * dest_buf, const lv_area_t * dest_area,
};
PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig);
lv_gpu_nxp_pxp_run(); /* Start PXP task */
return LV_RES_OK;
lv_gpu_nxp_pxp_run();
}
lv_res_t lv_gpu_nxp_pxp_blit_transform(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area,
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf)
void lv_gpu_nxp_pxp_blit_transform(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf)
{
uint32_t dest_size = lv_area_get_size(dest_area);
bool has_recolor = (dsc->recolor_opa != LV_OPA_TRANSP);
bool has_rotation = (dsc->angle != 0);
if(dsc->opa >= (lv_opa_t)LV_OPA_MAX) {
if(dest_size < LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT) {
PXP_LOG_TRACE("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT);
return LV_RES_INV;
if(has_recolor || has_rotation) {
if(dsc->opa >= (lv_opa_t)LV_OPA_MAX && !lv_img_cf_has_alpha(cf) && !lv_img_cf_is_chroma_keyed(cf)) {
lv_pxp_blit_cover(dest_buf, dest_area, dest_stride, src_buf, src_area, src_stride, dsc, cf);
return;
}
}
else {
if(dest_size < LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT) {
PXP_LOG_TRACE("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT);
return LV_RES_INV;
}
}
bool recolor = (dsc->recolor_opa != LV_OPA_TRANSP);
bool rotation = (dsc->angle != 0);
if(rotation) {
if(dsc->angle != 0 && dsc->angle != 900 && dsc->angle != 1800 && dsc->angle != 2700) {
PXP_LOG_TRACE("Rotation angle %d is not supported. PXP can rotate only 90x angle.", dsc->angle);
return LV_RES_INV;
}
}
if(recolor || rotation) {
if(dsc->opa >= (lv_opa_t)LV_OPA_MAX && !lv_img_cf_has_alpha(cf) && !lv_img_cf_is_chroma_keyed(cf))
return lv_gpu_nxp_pxp_blit_cover(dest_buf, dest_area, dest_stride, src_buf, src_area, dsc, cf);
else
else {
/*Recolor and/or rotation with alpha or opacity is done in two steps.*/
return lv_gpu_nxp_pxp_blit_opa(dest_buf, dest_area, dest_stride, src_buf, src_area, dsc, cf);
lv_pxp_blit_opa(dest_buf, dest_area, dest_stride, src_buf, src_area, src_stride, dsc, cf);
return;
}
}
return lv_gpu_nxp_pxp_blit_cf(dest_buf, dest_area, dest_stride, src_buf, src_area, dsc, cf);
lv_pxp_blit_cf(dest_buf, dest_area, dest_stride, src_buf, src_area, src_stride, dsc, cf);
}
void lv_gpu_nxp_pxp_buffer_copy(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride)
{
lv_coord_t src_width = lv_area_get_width(src_area);
lv_coord_t src_height = lv_area_get_height(src_area);
lv_gpu_nxp_pxp_reset();
const pxp_pic_copy_config_t picCopyConfig = {
.srcPicBaseAddr = (uint32_t)src_buf,
.srcPitchBytes = src_stride * sizeof(lv_color_t),
.srcOffsetX = src_area->x1,
.srcOffsetY = src_area->y1,
.destPicBaseAddr = (uint32_t)dest_buf,
.destPitchBytes = dest_stride * sizeof(lv_color_t),
.destOffsetX = dest_area->x1,
.destOffsetY = dest_area->y1,
.width = src_width,
.height = src_height,
.pixelFormat = PXP_AS_PIXEL_FORMAT
};
PXP_StartPictureCopy(LV_GPU_NXP_PXP_ID, &picCopyConfig);
lv_gpu_nxp_pxp_wait();
}
/**********************
* STATIC FUNCTIONS
**********************/
static lv_res_t lv_gpu_nxp_pxp_blit_opa(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area,
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf)
static void lv_pxp_blit_opa(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf)
{
lv_coord_t dest_w = lv_area_get_width(dest_area);
lv_coord_t dest_h = lv_area_get_height(dest_area);
lv_res_t res;
uint32_t size = dest_w * dest_h * sizeof(lv_color_t);
if(ROUND_UP(size, ALIGN_SIZE) >= LV_MEM_SIZE)
PXP_RETURN_INV("Insufficient memory for temporary buffer. Please increase LV_MEM_SIZE.");
lv_color_t * tmp_buf = (lv_color_t *)lv_mem_buf_get(size);
if(!tmp_buf)
PXP_RETURN_INV("Allocating temporary buffer failed.");
const lv_area_t tmp_area = {
.x1 = 0,
.y1 = 0,
.x2 = dest_w - 1,
.y2 = dest_h - 1
};
lv_area_t temp_area;
lv_area_copy(&temp_area, dest_area);
lv_coord_t temp_stride = dest_stride;
lv_coord_t temp_w = lv_area_get_width(&temp_area);
lv_coord_t temp_h = lv_area_get_height(&temp_area);
/*Step 1: Transform with full opacity to temporary buffer*/
res = lv_gpu_nxp_pxp_blit_cover(tmp_buf, &tmp_area, dest_w, src_buf, src_area, dsc, cf);
if(res != LV_RES_OK) {
PXP_LOG_TRACE("Blit cover with full opacity failed.");
lv_mem_buf_release(tmp_buf);
lv_pxp_blit_cover((lv_color_t *)temp_buf, &temp_area, temp_stride, src_buf, src_area, src_stride, dsc, cf);
return res;
/*Switch width and height if angle requires it*/
if(dsc->angle == 900 || dsc->angle == 2700) {
temp_area.x2 = temp_area.x1 + temp_h - 1;
temp_area.y2 = temp_area.y1 + temp_w - 1;
}
/*Step 2: Blit temporary results with required opacity to output*/
res = lv_gpu_nxp_pxp_blit_cf(dest_buf, dest_area, dest_stride, tmp_buf, &tmp_area, dsc, cf);
/*Clean-up memory*/
lv_mem_buf_release(tmp_buf);
return res;
/*Step 2: Blit temporary result with required opacity to output*/
lv_pxp_blit_cf(dest_buf, &temp_area, dest_stride, (lv_color_t *)temp_buf, &temp_area, temp_stride, dsc, cf);
}
static lv_res_t lv_gpu_nxp_pxp_blit_cover(lv_color_t * dest_buf, const lv_area_t * dest_area,
lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area,
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf)
static void lv_pxp_blit_cover(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf)
{
lv_coord_t dest_w = lv_area_get_width(dest_area);
lv_coord_t dest_h = lv_area_get_height(dest_area);
lv_coord_t src_w = lv_area_get_width(src_area);
lv_coord_t src_h = lv_area_get_height(src_area);
bool recolor = (dsc->recolor_opa != LV_OPA_TRANSP);
bool rotation = (dsc->angle != 0);
bool has_recolor = (dsc->recolor_opa != LV_OPA_TRANSP);
bool has_rotation = (dsc->angle != 0);
PXP_Init(LV_GPU_NXP_PXP_ID);
PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false); /*Disable CSC1, it is enabled by default.*/
PXP_SetProcessBlockSize(LV_GPU_NXP_PXP_ID, kPXP_BlockSize16); /*block size 16x16 for higher performance*/
lv_point_t pivot = dsc->pivot;
lv_coord_t piv_offset_x;
lv_coord_t piv_offset_y;
if(rotation) {
/*
* PXP is set to process 16x16 blocks to optimize the system for memory
* bandwidth and image processing time.
* The output engine essentially truncates any output pixels after the
* desired number of pixels has been written.
* When rotating a source image and the output is not divisible by the block
* size, the incorrect pixels could be truncated and the final output image
* can look shifted.
*/
if(lv_area_get_width(src_area) % 16 || lv_area_get_height(src_area) % 16) {
PXP_LOG_TRACE("Rotation is not supported for image w/o alignment to block size 16x16.");
return LV_RES_INV;
}
lv_gpu_nxp_pxp_reset();
/*Convert rotation angle*/
pxp_rotate_degree_t pxp_rot;
if(has_rotation) {
/*Convert rotation angle and calculate offsets caused by pivot*/
pxp_rotate_degree_t pxp_angle;
switch(dsc->angle) {
case 0:
pxp_rot = kPXP_Rotate0;
pxp_angle = kPXP_Rotate0;
piv_offset_x = 0;
piv_offset_y = 0;
break;
case 900:
pxp_rot = kPXP_Rotate90;
piv_offset_x = pivot.x + pivot.y - dest_h;
piv_offset_y = pivot.y - pivot.x;
pxp_angle = kPXP_Rotate90;
break;
case 1800:
pxp_rot = kPXP_Rotate180;
piv_offset_x = 2 * pivot.x - dest_w;
piv_offset_y = 2 * pivot.y - dest_h;
pxp_angle = kPXP_Rotate180;
break;
case 2700:
pxp_rot = kPXP_Rotate270;
piv_offset_x = pivot.x - pivot.y;
piv_offset_y = pivot.x + pivot.y - dest_w;
pxp_angle = kPXP_Rotate270;
break;
default:
PXP_LOG_TRACE("Rotation angle %d is not supported. PXP can rotate only 90x angle.", dsc->angle);
return LV_RES_INV;
piv_offset_x = 0;
piv_offset_y = 0;
pxp_angle = kPXP_Rotate0;
}
PXP_SetRotateConfig(LV_GPU_NXP_PXP_ID, kPXP_RotateOutputBuffer, pxp_rot, kPXP_FlipDisable);
PXP_SetRotateConfig(LV_GPU_NXP_PXP_ID, kPXP_RotateOutputBuffer, pxp_angle, kPXP_FlipDisable);
lv_area_move(dest_area, piv_offset_x, piv_offset_y);
}
lv_coord_t src_stride = lv_area_get_width(src_area);
/*AS buffer - source image*/
pxp_as_buffer_config_t asBufferConfig = {
.pixelFormat = PXP_AS_PIXEL_FORMAT,
.bufferAddr = (uint32_t)src_buf,
.bufferAddr = (uint32_t)(src_buf + src_stride * src_area->y1 + src_area->x1),
.pitchBytes = src_stride * sizeof(lv_color_t)
};
PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig);
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U);
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, src_w - 1U, src_h - 1U);
/*Disable PS buffer*/
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
if(recolor)
if(has_recolor)
/*Use as color generator*/
PXP_SetProcessSurfaceBackGroundColor(LV_GPU_NXP_PXP_ID, lv_color_to32(dsc->recolor));
@@ -496,7 +444,7 @@ static lv_res_t lv_gpu_nxp_pxp_blit_cover(lv_color_t * dest_buf, const lv_area_t
};
PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig);
if(recolor || lv_img_cf_has_alpha(cf)) {
if(has_recolor || lv_img_cf_has_alpha(cf)) {
/**
* Configure Porter-Duff blending.
*
@@ -512,7 +460,7 @@ static lv_res_t lv_gpu_nxp_pxp_blit_cover(lv_color_t * dest_buf, const lv_area_t
.srcGlobalAlphaMode = lv_img_cf_has_alpha(cf) ? kPXP_PorterDuffLocalAlpha : kPXP_PorterDuffGlobalAlpha,
.dstFactorMode = kPXP_PorterDuffFactorStraight,
.srcFactorMode = kPXP_PorterDuffFactorInversed,
.dstGlobalAlpha = recolor ? dsc->recolor_opa : 0x00,
.dstGlobalAlpha = has_recolor ? dsc->recolor_opa : 0x00,
.srcGlobalAlpha = 0xff,
.dstAlphaMode = kPXP_PorterDuffAlphaStraight, /*don't care*/
.srcAlphaMode = kPXP_PorterDuffAlphaStraight
@@ -520,22 +468,19 @@ static lv_res_t lv_gpu_nxp_pxp_blit_cover(lv_color_t * dest_buf, const lv_area_t
PXP_SetPorterDuffConfig(LV_GPU_NXP_PXP_ID, &pdConfig);
}
lv_gpu_nxp_pxp_run(); /*Start PXP task*/
return LV_RES_OK;
lv_gpu_nxp_pxp_run();
}
static lv_res_t lv_gpu_nxp_pxp_blit_cf(lv_color_t * dest_buf, const lv_area_t * dest_area,
lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area,
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf)
static void lv_pxp_blit_cf(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf)
{
lv_coord_t dest_w = lv_area_get_width(dest_area);
lv_coord_t dest_h = lv_area_get_height(dest_area);
lv_coord_t src_w = lv_area_get_width(src_area);
lv_coord_t src_h = lv_area_get_height(src_area);
PXP_Init(LV_GPU_NXP_PXP_ID);
PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false); /*Disable CSC1, it is enabled by default.*/
PXP_SetProcessBlockSize(LV_GPU_NXP_PXP_ID, kPXP_BlockSize16); /*block size 16x16 for higher performance*/
lv_gpu_nxp_pxp_reset();
pxp_as_blend_config_t asBlendConfig = {
.alpha = dsc->opa,
@@ -566,28 +511,26 @@ static lv_res_t lv_gpu_nxp_pxp_blit_cf(lv_color_t * dest_buf, const lv_area_t *
asBlendConfig.alphaMode = lv_img_cf_has_alpha(cf) ? kPXP_AlphaMultiply : kPXP_AlphaOverride;
}
PXP_SetProcessSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &psBufferConfig);
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1, dest_h - 1);
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U);
}
lv_coord_t src_stride = lv_area_get_width(src_area);
/*AS buffer - source image*/
pxp_as_buffer_config_t asBufferConfig = {
.pixelFormat = PXP_AS_PIXEL_FORMAT,
.bufferAddr = (uint32_t)src_buf,
.bufferAddr = (uint32_t)(src_buf + src_stride * src_area->y1 + src_area->x1),
.pitchBytes = src_stride * sizeof(lv_color_t)
};
PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig);
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U);
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, src_w - 1U, src_h - 1U);
PXP_SetAlphaSurfaceBlendConfig(LV_GPU_NXP_PXP_ID, &asBlendConfig);
if(lv_img_cf_is_chroma_keyed(cf)) {
lv_color_t colorKeyLow = LV_COLOR_CHROMA_KEY;
lv_color_t colorKeyHigh = LV_COLOR_CHROMA_KEY;
bool recolor = (dsc->recolor_opa != LV_OPA_TRANSP);
bool has_recolor = (dsc->recolor_opa != LV_OPA_TRANSP);
if(recolor) {
if(has_recolor) {
/* New color key after recoloring */
lv_color_t colorKey = lv_color_mix(dsc->recolor, LV_COLOR_CHROMA_KEY, dsc->recolor_opa);
@@ -595,11 +538,11 @@ static lv_res_t lv_gpu_nxp_pxp_blit_cf(lv_color_t * dest_buf, const lv_area_t *
LV_COLOR_SET_G(colorKeyLow, colorKey.ch.green != 0 ? colorKey.ch.green - 1 : 0);
LV_COLOR_SET_B(colorKeyLow, colorKey.ch.blue != 0 ? colorKey.ch.blue - 1 : 0);
#if LV_COLOR_DEPTH==16
#if LV_COLOR_DEPTH == 16
LV_COLOR_SET_R(colorKeyHigh, colorKey.ch.red != 0x1f ? colorKey.ch.red + 1 : 0x1f);
LV_COLOR_SET_G(colorKeyHigh, colorKey.ch.green != 0x3f ? colorKey.ch.green + 1 : 0x3f);
LV_COLOR_SET_B(colorKeyHigh, colorKey.ch.blue != 0x1f ? colorKey.ch.blue + 1 : 0x1f);
#else /*LV_COLOR_DEPTH==32*/
#else /*LV_COLOR_DEPTH == 32*/
LV_COLOR_SET_R(colorKeyHigh, colorKey.ch.red != 0xff ? colorKey.ch.red + 1 : 0xff);
LV_COLOR_SET_G(colorKeyHigh, colorKey.ch.green != 0xff ? colorKey.ch.green + 1 : 0xff);
LV_COLOR_SET_B(colorKeyHigh, colorKey.ch.blue != 0xff ? colorKey.ch.blue + 1 : 0xff);
@@ -624,9 +567,7 @@ static lv_res_t lv_gpu_nxp_pxp_blit_cf(lv_color_t * dest_buf, const lv_area_t *
};
PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig);
lv_gpu_nxp_pxp_run(); /* Start PXP task */
return LV_RES_OK;
lv_gpu_nxp_pxp_run();
}
#endif /*LV_USE_GPU_NXP_PXP*/

View File

@@ -6,7 +6,7 @@
/**
* MIT License
*
* Copyright 2020-2022 NXP
* Copyright 2020-2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -48,31 +48,6 @@ extern "C" {
* DEFINES
*********************/
#ifndef LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT
/** Minimum area (in pixels) for image copy with 100% opacity to be handled by PXP*/
#define LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT 5000
#endif
#ifndef LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT
/** Minimum area (in pixels) for image copy with transparency to be handled by PXP*/
#define LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT 5000
#endif
#ifndef LV_GPU_NXP_PXP_BUFF_SYNC_BLIT_SIZE_LIMIT
/** Minimum invalidated area (in pixels) to be synchronized by PXP during buffer sync */
#define LV_GPU_NXP_PXP_BUFF_SYNC_BLIT_SIZE_LIMIT 5000
#endif
#ifndef LV_GPU_NXP_PXP_FILL_SIZE_LIMIT
/** Minimum area (in pixels) to be filled by PXP with 100% opacity*/
#define LV_GPU_NXP_PXP_FILL_SIZE_LIMIT 5000
#endif
#ifndef LV_GPU_NXP_PXP_FILL_OPA_SIZE_LIMIT
/** Minimum area (in pixels) to be filled by PXP with transparency*/
#define LV_GPU_NXP_PXP_FILL_OPA_SIZE_LIMIT 5000
#endif
/**********************
* TYPEDEFS
**********************/
@@ -84,51 +59,63 @@ extern "C" {
/**
* Fill area, with optional opacity.
*
* @param[in/out] dest_buf destination buffer
* @param[in] dest_stride width (stride) of destination buffer in pixels
* @param[in] fill_area area to fill
* @param[in] color color
* @param[in] opa transparency of the color
* @retval LV_RES_OK Fill completed
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS)
* @param[in/out] dest_buf Destination buffer
* @param[in] dest_area Area with relative coordinates of destination buffer
* @param[in] dest_stride Stride of destination buffer in pixels
* @param[in] color Color
* @param[in] opa Opacity
*/
lv_res_t lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, lv_coord_t dest_stride, const lv_area_t * fill_area,
lv_color_t color, lv_opa_t opa);
void lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
lv_color_t color, lv_opa_t opa);
/**
* BLock Image Transfer - copy rectangular image from src_buf to dst_buf with effects.
* By default, image is copied directly, with optional opacity. This function can also
* rotate the display output buffer to a specified angle (90x step).
*
* @param[in/out] dest_buf destination buffer
* @param[in] dest_area destination area
* @param[in] dest_stride width (stride) of destination buffer in pixels
* @param[in] src_buf source buffer
* @param[in] src_area source area with absolute coordinates to draw on destination buffer
* @param[in] opa opacity of the result
* @param[in] angle display rotation angle (90x)
* @retval LV_RES_OK Fill completed
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS)
* @param[in/out] dest_buf Destination buffer
* @param[in] dest_area Area with relative coordinates of destination buffer
* @param[in] dest_stride Stride of destination buffer in pixels
* @param[in] src_buf Source buffer
* @param[in] src_area Source area with relative coordinates of source buffer
* @param[in] src_stride Stride of source buffer in pixels
* @param[in] opa Opacity
* @param[in] angle Display rotation angle (90x)
*/
lv_res_t lv_gpu_nxp_pxp_blit(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_opa_t opa, lv_disp_rot_t angle);
void lv_gpu_nxp_pxp_blit(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
lv_opa_t opa, lv_disp_rot_t angle);
/**
* BLock Image Transfer - copy rectangular image from src_buf to dst_buf with transformation.
*
*
* @param[in/out] dest_buf destination buffer
* @param[in] dest_area destination area
* @param[in] dest_stride width (stride) of destination buffer in pixels
* @param[in] src_buf source buffer
* @param[in] src_area source area with absolute coordinates to draw on destination buffer
* @param[in] dsc image descriptor
* @param[in] cf color format
* @retval LV_RES_OK Fill completed
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS)
* @param[in/out] dest_buf Destination buffer
* @param[in] dest_area Area with relative coordinates of destination buffer
* @param[in] dest_stride Stride of destination buffer in pixels
* @param[in] src_buf Source buffer
* @param[in] src_area Area with relative coordinates of source buffer
* @param[in] src_stride Stride of source buffer in pixels
* @param[in] dsc Image descriptor
* @param[in] cf Color format
*/
lv_res_t lv_gpu_nxp_pxp_blit_transform(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf);
void lv_gpu_nxp_pxp_blit_transform(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf);
/**
* BLock Image Transfer - copy rectangular image from src_buf to dst_buf, no transformation or blending.
*
*
* @param[in/out] dest_buf Destination buffer
* @param[in] dest_area Area with relative coordinates of destination buffer
* @param[in] dest_stride Stride of destination buffer in pixels
* @param[in] src_buf Source buffer
* @param[in] src_area Area with relative coordinates of source buffer
* @param[in] src_stride Stride of source buffer in pixels
*/
void lv_gpu_nxp_pxp_buffer_copy(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride);
/**********************
* MACROS

View File

@@ -6,7 +6,7 @@
/**
* MIT License
*
* Copyright 2020-2022 NXP
* Copyright 2020-2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -50,9 +50,9 @@
**********************/
/**
* Clean & invalidate cache.
* Clean and invalidate cache.
*/
static void invalidate_cache(void);
static inline void invalidate_cache(void);
/**********************
* STATIC VARIABLES
@@ -70,16 +70,23 @@ static lv_nxp_pxp_cfg_t * pxp_cfg;
lv_res_t lv_gpu_nxp_pxp_init(void)
{
#if LV_USE_GPU_NXP_PXP_AUTO_INIT
pxp_cfg = lv_gpu_nxp_pxp_get_cfg();
#endif
if(!pxp_cfg || !pxp_cfg->pxp_interrupt_deinit || !pxp_cfg->pxp_interrupt_init || !pxp_cfg->pxp_run)
if(!pxp_cfg || !pxp_cfg->pxp_interrupt_deinit || !pxp_cfg->pxp_interrupt_init ||
!pxp_cfg->pxp_run || !pxp_cfg->pxp_wait)
PXP_RETURN_INV("PXP configuration error.");
PXP_Init(LV_GPU_NXP_PXP_ID);
PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false); /*Disable CSC1, it is enabled by default.*/
PXP_SetProcessBlockSize(LV_GPU_NXP_PXP_ID, kPXP_BlockSize16); /*Block size 16x16 for higher performance*/
PXP_EnableInterrupts(LV_GPU_NXP_PXP_ID, kPXP_CompleteInterruptEnable);
if(pxp_cfg->pxp_interrupt_init() != LV_RES_OK) {
PXP_DisableInterrupts(LV_GPU_NXP_PXP_ID, kPXP_CompleteInterruptEnable);
PXP_Deinit(LV_GPU_NXP_PXP_ID);
PXP_RETURN_INV("PXP interrupt init failed.");
}
@@ -90,23 +97,38 @@ lv_res_t lv_gpu_nxp_pxp_init(void)
void lv_gpu_nxp_pxp_deinit(void)
{
pxp_cfg->pxp_interrupt_deinit();
PXP_DisableInterrupts(PXP, kPXP_CompleteInterruptEnable);
PXP_DisableInterrupts(LV_GPU_NXP_PXP_ID, kPXP_CompleteInterruptEnable);
PXP_Deinit(LV_GPU_NXP_PXP_ID);
}
void lv_gpu_nxp_pxp_reset(void)
{
/* Wait for previous command to complete before resetting the registers. */
lv_gpu_nxp_pxp_wait();
PXP_ResetControl(LV_GPU_NXP_PXP_ID);
PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false); /*Disable CSC1, it is enabled by default.*/
PXP_SetProcessBlockSize(LV_GPU_NXP_PXP_ID, kPXP_BlockSize16); /*Block size 16x16 for higher performance*/
}
void lv_gpu_nxp_pxp_run(void)
{
/*Clean & invalidate cache*/
invalidate_cache();
pxp_cfg->pxp_run();
}
void lv_gpu_nxp_pxp_wait(void)
{
pxp_cfg->pxp_wait();
}
/**********************
* STATIC FUNCTIONS
**********************/
static void invalidate_cache(void)
static inline void invalidate_cache(void)
{
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
if(disp->driver->clean_dcache_cb)

View File

@@ -6,7 +6,7 @@
/**
* MIT License
*
* Copyright 2020-2022 NXP
* Copyright 2020-2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -81,8 +81,11 @@ typedef struct {
/** Callback for PXP interrupt de-initialization*/
void (*pxp_interrupt_deinit)(void);
/** Callback that should start PXP and wait for operation complete*/
/** Callback for PXP start*/
void (*pxp_run)(void);
/** Callback for waiting of PXP completion*/
void (*pxp_wait)(void);
} lv_nxp_pxp_cfg_t;
/**********************
@@ -104,10 +107,20 @@ lv_res_t lv_gpu_nxp_pxp_init(void);
void lv_gpu_nxp_pxp_deinit(void);
/**
* Start PXP job and wait for completion.
* Reset PXP device.
*/
void lv_gpu_nxp_pxp_reset(void);
/**
* Clear cache and start PXP.
*/
void lv_gpu_nxp_pxp_run(void);
/**
* Wait for PXP completion.
*/
void lv_gpu_nxp_pxp_wait(void);
/**********************
* MACROS
**********************/
@@ -136,7 +149,7 @@ void lv_gpu_nxp_pxp_run(void);
#if LV_GPU_NXP_PXP_LOG_TRACES
#define PXP_LOG_TRACE(fmt, ...) \
do { \
LV_LOG_ERROR(fmt, ##__VA_ARGS__); \
LV_LOG(fmt, ##__VA_ARGS__); \
} while (0)
#else
#define PXP_LOG_TRACE(fmt, ...) \

View File

@@ -6,7 +6,7 @@
/**
* MIT License
*
* Copyright 2020, 2022 NXP
* Copyright 2020, 2022, 2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -65,24 +65,29 @@ static lv_res_t _lv_gpu_nxp_pxp_interrupt_init(void);
static void _lv_gpu_nxp_pxp_interrupt_deinit(void);
/**
* Start the PXP job and wait for task completion.
* Start the PXP job.
*/
static void _lv_gpu_nxp_pxp_run(void);
/**
* Wait for PXP completion.
*/
static void _lv_gpu_nxp_pxp_wait(void);
/**********************
* STATIC VARIABLES
**********************/
#if defined(SDK_OS_FREE_RTOS)
static SemaphoreHandle_t s_pxpIdle;
#else
static volatile bool s_pxpIdle;
static SemaphoreHandle_t s_pxpIdleSem;
#endif
static volatile bool s_pxpIdle;
static lv_nxp_pxp_cfg_t pxp_default_cfg = {
.pxp_interrupt_init = _lv_gpu_nxp_pxp_interrupt_init,
.pxp_interrupt_deinit = _lv_gpu_nxp_pxp_interrupt_deinit,
.pxp_run = _lv_gpu_nxp_pxp_run
.pxp_run = _lv_gpu_nxp_pxp_run,
.pxp_wait = _lv_gpu_nxp_pxp_wait,
};
/**********************
@@ -102,7 +107,7 @@ void PXP_IRQHandler(void)
if(kPXP_CompleteFlag & PXP_GetStatusFlags(LV_GPU_NXP_PXP_ID)) {
PXP_ClearStatusFlags(LV_GPU_NXP_PXP_ID, kPXP_CompleteFlag);
#if defined(SDK_OS_FREE_RTOS)
xSemaphoreGiveFromISR(s_pxpIdle, &taskAwake);
xSemaphoreGiveFromISR(s_pxpIdleSem, &taskAwake);
portYIELD_FROM_ISR(taskAwake);
#else
s_pxpIdle = true;
@@ -122,14 +127,13 @@ lv_nxp_pxp_cfg_t * lv_gpu_nxp_pxp_get_cfg(void)
static lv_res_t _lv_gpu_nxp_pxp_interrupt_init(void)
{
#if defined(SDK_OS_FREE_RTOS)
s_pxpIdle = xSemaphoreCreateBinary();
if(s_pxpIdle == NULL)
s_pxpIdleSem = xSemaphoreCreateBinary();
if(s_pxpIdleSem == NULL)
return LV_RES_INV;
NVIC_SetPriority(LV_GPU_NXP_PXP_IRQ_ID, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1);
#else
s_pxpIdle = true;
#endif
s_pxpIdle = true;
NVIC_EnableIRQ(LV_GPU_NXP_PXP_IRQ_ID);
@@ -140,21 +144,33 @@ static void _lv_gpu_nxp_pxp_interrupt_deinit(void)
{
NVIC_DisableIRQ(LV_GPU_NXP_PXP_IRQ_ID);
#if defined(SDK_OS_FREE_RTOS)
vSemaphoreDelete(s_pxpIdle);
vSemaphoreDelete(s_pxpIdleSem);
#endif
}
/**
* Function to start PXP job.
*/
static void _lv_gpu_nxp_pxp_run(void)
{
#if !defined(SDK_OS_FREE_RTOS)
s_pxpIdle = false;
#endif
PXP_EnableInterrupts(LV_GPU_NXP_PXP_ID, kPXP_CompleteInterruptEnable);
PXP_Start(LV_GPU_NXP_PXP_ID);
}
/**
* Function to wait for PXP completion.
*/
static void _lv_gpu_nxp_pxp_wait(void)
{
#if defined(SDK_OS_FREE_RTOS)
PXP_COND_STOP(!xSemaphoreTake(s_pxpIdle, portMAX_DELAY), "xSemaphoreTake failed.");
/* Return if PXP was never started, otherwise the semaphore will lock forever. */
if(s_pxpIdle == true)
return;
if(xSemaphoreTake(s_pxpIdleSem, portMAX_DELAY) == pdTRUE)
s_pxpIdle = true;
#else
while(s_pxpIdle == false) {
}

View File

@@ -1,7 +1,10 @@
CSRCS += lv_draw_vglite.c
CSRCS += lv_draw_vglite_arc.c
CSRCS += lv_draw_vglite_blend.c
CSRCS += lv_draw_vglite_line.c
CSRCS += lv_draw_vglite_rect.c
CSRCS += lv_gpu_nxp_vglite.c
CSRCS += lv_vglite_buf.c
CSRCS += lv_vglite_utils.c
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/vglite
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/vglite

View File

@@ -0,0 +1,557 @@
/**
* @file lv_draw_vglite.c
*
*/
/**
* MIT License
*
* Copyright 2022, 2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next paragraph)
* shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_vglite.h"
#if LV_USE_GPU_NXP_VG_LITE
#include <math.h>
#include "lv_draw_vglite_blend.h"
#include "lv_draw_vglite_line.h"
#include "lv_draw_vglite_rect.h"
#include "lv_draw_vglite_arc.h"
#include "lv_vglite_buf.h"
#if LV_COLOR_DEPTH != 32
#include "../../../core/lv_refr.h"
#endif
/*********************
* DEFINES
*********************/
/* Minimum area (in pixels) for VG-Lite blit/fill processing. */
#ifndef LV_GPU_NXP_VG_LITE_SIZE_LIMIT
#define LV_GPU_NXP_VG_LITE_SIZE_LIMIT 5000
#endif
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void lv_draw_vglite_init_buf(lv_draw_ctx_t * draw_ctx);
static void lv_draw_vglite_wait_for_finish(lv_draw_ctx_t * draw_ctx);
static void lv_draw_vglite_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc,
const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t cf);
static void lv_draw_vglite_buffer_copy(lv_draw_ctx_t * draw_ctx,
void * dest_buf, lv_coord_t dest_stride, const lv_area_t * dest_area,
void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area);
static void lv_draw_vglite_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc);
static void lv_draw_vglite_line(lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, const lv_point_t * point1,
const lv_point_t * point2);
static void lv_draw_vglite_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
static lv_res_t lv_draw_vglite_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
static lv_res_t lv_draw_vglite_border(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc,
const lv_area_t * coords);
static lv_res_t lv_draw_vglite_outline(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc,
const lv_area_t * coords);
static void lv_draw_vglite_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center,
uint16_t radius, uint16_t start_angle, uint16_t end_angle);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_vglite_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
{
lv_draw_sw_init_ctx(drv, draw_ctx);
lv_draw_vglite_ctx_t * vglite_draw_ctx = (lv_draw_sw_ctx_t *)draw_ctx;
vglite_draw_ctx->base_draw.init_buf = lv_draw_vglite_init_buf;
vglite_draw_ctx->base_draw.draw_line = lv_draw_vglite_line;
vglite_draw_ctx->base_draw.draw_arc = lv_draw_vglite_arc;
vglite_draw_ctx->base_draw.draw_rect = lv_draw_vglite_rect;
vglite_draw_ctx->base_draw.draw_img_decoded = lv_draw_vglite_img_decoded;
vglite_draw_ctx->blend = lv_draw_vglite_blend;
vglite_draw_ctx->base_draw.wait_for_finish = lv_draw_vglite_wait_for_finish;
vglite_draw_ctx->base_draw.buffer_copy = lv_draw_vglite_buffer_copy;
}
void lv_draw_vglite_ctx_deinit(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
{
lv_draw_sw_deinit_ctx(drv, draw_ctx);
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* During rendering, LVGL might initializes new draw_ctxs and start drawing into
* a separate buffer (called layer). If the content to be rendered has "holes",
* e.g. rounded corner, LVGL temporarily sets the disp_drv.screen_transp flag.
* It means the renderers should draw into an ARGB buffer.
* With 32 bit color depth it's not a big problem but with 16 bit color depth
* the target pixel format is ARGB8565 which is not supported by the GPU.
* In this case, the VG-Lite callbacks should fallback to SW rendering.
*/
static inline bool need_argb8565_support()
{
#if LV_COLOR_DEPTH != 32
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
if(disp->driver->screen_transp == 1)
return true;
#endif
return false;
}
static void lv_draw_vglite_init_buf(lv_draw_ctx_t * draw_ctx)
{
lv_gpu_nxp_vglite_init_buf(draw_ctx->buf, draw_ctx->buf_area, lv_area_get_width(draw_ctx->buf_area));
}
static void lv_draw_vglite_wait_for_finish(lv_draw_ctx_t * draw_ctx)
{
vg_lite_finish();
lv_draw_sw_wait_for_finish(draw_ctx);
}
static void lv_draw_vglite_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc)
{
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
return;
if(need_argb8565_support()) {
lv_draw_sw_blend_basic(draw_ctx, dsc);
return;
}
lv_area_t blend_area;
if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area))
return; /*Fully clipped, nothing to do*/
lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
bool done = false;
/*Fill/Blend only non masked, normal blended*/
if(dsc->mask_buf == NULL && dsc->blend_mode == LV_BLEND_MODE_NORMAL &&
lv_area_get_size(&blend_area) >= LV_GPU_NXP_VG_LITE_SIZE_LIMIT) {
const lv_color_t * src_buf = dsc->src_buf;
if(src_buf == NULL) {
done = (lv_gpu_nxp_vglite_fill(&blend_area, dsc->color, dsc->opa) == LV_RES_OK);
if(!done)
VG_LITE_LOG_TRACE("VG-Lite fill failed. Fallback.");
}
else {
lv_area_t src_area;
src_area.x1 = blend_area.x1 - (dsc->blend_area->x1 - draw_ctx->buf_area->x1);
src_area.y1 = blend_area.y1 - (dsc->blend_area->y1 - draw_ctx->buf_area->y1);
src_area.x2 = src_area.x1 + lv_area_get_width(dsc->blend_area) - 1;
src_area.y2 = src_area.y1 + lv_area_get_height(dsc->blend_area) - 1;
lv_coord_t src_stride = lv_area_get_width(dsc->blend_area);
#if VG_LITE_BLIT_SPLIT_ENABLED
lv_color_t * dest_buf = draw_ctx->buf;
lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area);
done = (lv_gpu_nxp_vglite_blit_split(dest_buf, &blend_area, dest_stride,
src_buf, &src_area, src_stride, dsc->opa) == LV_RES_OK);
#else
done = (lv_gpu_nxp_vglite_blit(&blend_area, src_buf, &src_area, src_stride, dsc->opa) == LV_RES_OK);
#endif
if(!done)
VG_LITE_LOG_TRACE("VG-Lite blit failed. Fallback.");
}
}
if(!done)
lv_draw_sw_blend_basic(draw_ctx, dsc);
}
static void lv_draw_vglite_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc,
const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t cf)
{
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
return;
if(need_argb8565_support()) {
lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf);
return;
}
const lv_color_t * src_buf = (const lv_color_t *)map_p;
if(!src_buf) {
lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf);
return;
}
lv_area_t rel_coords;
lv_area_copy(&rel_coords, coords);
lv_area_move(&rel_coords, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
lv_area_t rel_clip_area;
lv_area_copy(&rel_clip_area, draw_ctx->clip_area);
lv_area_move(&rel_clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
lv_area_t blend_area;
bool has_transform = dsc->angle != 0 || dsc->zoom != LV_IMG_ZOOM_NONE;
if(has_transform)
lv_area_copy(&blend_area, &rel_coords);
else if(!_lv_area_intersect(&blend_area, &rel_coords, &rel_clip_area))
return; /*Fully clipped, nothing to do*/
bool has_mask = lv_draw_mask_is_any(&blend_area);
bool has_recolor = (dsc->recolor_opa != LV_OPA_TRANSP);
bool done = false;
if(!has_mask && !has_recolor && !lv_img_cf_is_chroma_keyed(cf) &&
lv_area_get_size(&blend_area) >= LV_GPU_NXP_VG_LITE_SIZE_LIMIT
#if LV_COLOR_DEPTH != 32
&& !lv_img_cf_has_alpha(cf)
#endif
) {
lv_area_t src_area;
src_area.x1 = blend_area.x1 - (coords->x1 - draw_ctx->buf_area->x1);
src_area.y1 = blend_area.y1 - (coords->y1 - draw_ctx->buf_area->y1);
src_area.x2 = src_area.x1 + lv_area_get_width(coords) - 1;
src_area.y2 = src_area.y1 + lv_area_get_height(coords) - 1;
lv_coord_t src_stride = lv_area_get_width(coords);
#if VG_LITE_BLIT_SPLIT_ENABLED
lv_color_t * dest_buf = draw_ctx->buf;
lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area);
if(has_transform)
/* VG-Lite blit split with transformation is not supported! */
done = false;
else
done = (lv_gpu_nxp_vglite_blit_split(dest_buf, &blend_area, dest_stride,
src_buf, &src_area, src_stride, dsc->opa) == LV_RES_OK);
#else
if(has_transform)
done = (lv_gpu_nxp_vglite_blit_transform(&blend_area, &rel_clip_area,
src_buf, &src_area, src_stride, dsc) == LV_RES_OK);
else
done = (lv_gpu_nxp_vglite_blit(&blend_area, src_buf, &src_area, src_stride, dsc->opa) == LV_RES_OK);
#endif
if(!done)
VG_LITE_LOG_TRACE("VG-Lite blit %sfailed. Fallback.", has_transform ? "transform " : "");
}
if(!done)
lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf);
}
static void lv_draw_vglite_buffer_copy(lv_draw_ctx_t * draw_ctx,
void * dest_buf, lv_coord_t dest_stride, const lv_area_t * dest_area,
void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area)
{
bool done = false;
if(lv_area_get_size(dest_area) >= LV_GPU_NXP_VG_LITE_SIZE_LIMIT) {
done = lv_gpu_nxp_vglite_buffer_copy(dest_buf, dest_area, dest_stride, src_buf, src_area, src_stride);
if(!done)
VG_LITE_LOG_TRACE("VG-Lite buffer copy failed. Fallback.");
}
if(!done)
lv_draw_sw_buffer_copy(draw_ctx, dest_buf, dest_stride, dest_area, src_buf, src_stride, src_area);
}
static void lv_draw_vglite_line(lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, const lv_point_t * point1,
const lv_point_t * point2)
{
if(dsc->width == 0)
return;
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
return;
if(point1->x == point2->x && point1->y == point2->y)
return;
if(need_argb8565_support()) {
lv_draw_sw_line(draw_ctx, dsc, point1, point2);
return;
}
lv_area_t rel_clip_area;
rel_clip_area.x1 = LV_MIN(point1->x, point2->x) - dsc->width / 2;
rel_clip_area.x2 = LV_MAX(point1->x, point2->x) + dsc->width / 2;
rel_clip_area.y1 = LV_MIN(point1->y, point2->y) - dsc->width / 2;
rel_clip_area.y2 = LV_MAX(point1->y, point2->y) + dsc->width / 2;
lv_area_t clipped_coords;
if(!_lv_area_intersect(&clipped_coords, &rel_clip_area, draw_ctx->clip_area))
return; /*Fully clipped, nothing to do*/
lv_area_move(&rel_clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
lv_point_t rel_point1 = { point1->x - draw_ctx->buf_area->x1, point1->y - draw_ctx->buf_area->y1 };
lv_point_t rel_point2 = { point2->x - draw_ctx->buf_area->x1, point2->y - draw_ctx->buf_area->y1 };
bool done = false;
bool has_mask = lv_draw_mask_is_any(&rel_clip_area);
if(!has_mask) {
done = (lv_gpu_nxp_vglite_draw_line(&rel_point1, &rel_point2, &rel_clip_area, dsc) == LV_RES_OK);
if(!done)
VG_LITE_LOG_TRACE("VG-Lite draw line failed. Fallback.");
}
if(!done)
lv_draw_sw_line(draw_ctx, dsc, point1, point2);
}
static void lv_draw_vglite_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords)
{
if(need_argb8565_support()) {
lv_draw_sw_rect(draw_ctx, dsc, coords);
return;
}
lv_draw_rect_dsc_t vglite_dsc;
lv_memcpy(&vglite_dsc, dsc, sizeof(vglite_dsc));
vglite_dsc.bg_opa = 0;
vglite_dsc.bg_img_opa = 0;
vglite_dsc.border_opa = 0;
vglite_dsc.outline_opa = 0;
#if LV_DRAW_COMPLEX
/* Draw the shadow with CPU */
lv_draw_sw_rect(draw_ctx, &vglite_dsc, coords);
vglite_dsc.shadow_opa = 0;
#endif /*LV_DRAW_COMPLEX*/
/* Draw the background */
vglite_dsc.bg_opa = dsc->bg_opa;
if(lv_draw_vglite_bg(draw_ctx, &vglite_dsc, coords) != LV_RES_OK)
lv_draw_sw_rect(draw_ctx, &vglite_dsc, coords);
vglite_dsc.bg_opa = 0;
/* Draw the background image
* It will be done once draw_ctx->draw_img_decoded()
* callback gets called from lv_draw_sw_rect().
*/
vglite_dsc.bg_img_opa = dsc->bg_img_opa;
lv_draw_sw_rect(draw_ctx, &vglite_dsc, coords);
vglite_dsc.bg_img_opa = 0;
/* Draw the border */
vglite_dsc.border_opa = dsc->border_opa;
if(lv_draw_vglite_border(draw_ctx, &vglite_dsc, coords) != LV_RES_OK)
lv_draw_sw_rect(draw_ctx, &vglite_dsc, coords);
vglite_dsc.border_opa = 0;
/* Draw the outline */
vglite_dsc.outline_opa = dsc->outline_opa;
if(lv_draw_vglite_outline(draw_ctx, &vglite_dsc, coords) != LV_RES_OK)
lv_draw_sw_rect(draw_ctx, &vglite_dsc, coords);
}
static lv_res_t lv_draw_vglite_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords)
{
if(dsc->bg_opa <= (lv_opa_t)LV_OPA_MIN)
return LV_RES_INV;
lv_area_t rel_coords;
lv_area_copy(&rel_coords, coords);
/*If the border fully covers make the bg area 1px smaller to avoid artifacts on the corners*/
if(dsc->border_width > 1 && dsc->border_opa >= (lv_opa_t)LV_OPA_MAX && dsc->radius != 0) {
rel_coords.x1 += (dsc->border_side & LV_BORDER_SIDE_LEFT) ? 1 : 0;
rel_coords.y1 += (dsc->border_side & LV_BORDER_SIDE_TOP) ? 1 : 0;
rel_coords.x2 -= (dsc->border_side & LV_BORDER_SIDE_RIGHT) ? 1 : 0;
rel_coords.y2 -= (dsc->border_side & LV_BORDER_SIDE_BOTTOM) ? 1 : 0;
}
lv_area_move(&rel_coords, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
lv_area_t rel_clip_area;
lv_area_copy(&rel_clip_area, draw_ctx->clip_area);
lv_area_move(&rel_clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
lv_area_t clipped_coords;
if(!_lv_area_intersect(&clipped_coords, &rel_coords, &rel_clip_area))
return LV_RES_OK; /*Fully clipped, nothing to do*/
bool has_mask = lv_draw_mask_is_any(&rel_coords);
lv_grad_dir_t grad_dir = dsc->bg_grad.dir;
lv_color_t bg_color = (grad_dir == (lv_grad_dir_t)LV_GRAD_DIR_NONE) ?
dsc->bg_color : dsc->bg_grad.stops[0].color;
if(bg_color.full == dsc->bg_grad.stops[1].color.full)
grad_dir = LV_GRAD_DIR_NONE;
/*
* Most simple case: just a plain rectangle (no mask, no radius, no gradient)
* shall be handled by draw_ctx->blend().
*
* Complex case: gradient or radius but no mask.
*/
if(!has_mask && ((dsc->radius != 0) || (grad_dir != (lv_grad_dir_t)LV_GRAD_DIR_NONE))) {
lv_res_t res = lv_gpu_nxp_vglite_draw_bg(&rel_coords, &rel_clip_area, dsc);
if(res != LV_RES_OK)
VG_LITE_LOG_TRACE("VG-Lite draw bg failed. Fallback.");
return res;
}
return LV_RES_INV;
}
static lv_res_t lv_draw_vglite_border(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc,
const lv_area_t * coords)
{
if(dsc->border_opa <= (lv_opa_t)LV_OPA_MIN)
return LV_RES_INV;
if(dsc->border_width == 0)
return LV_RES_INV;
if(dsc->border_post)
return LV_RES_INV;
if(dsc->border_side != (lv_border_side_t)LV_BORDER_SIDE_FULL)
return LV_RES_INV;
lv_area_t rel_coords;
lv_coord_t border_width = dsc->border_width;
/* Move border inwards to align with software rendered border */
rel_coords.x1 = coords->x1 + ceil(border_width / 2.0f);
rel_coords.x2 = coords->x2 - floor(border_width / 2.0f);
rel_coords.y1 = coords->y1 + ceil(border_width / 2.0f);
rel_coords.y2 = coords->y2 - floor(border_width / 2.0f);
lv_area_move(&rel_coords, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
lv_area_t rel_clip_area;
lv_area_copy(&rel_clip_area, draw_ctx->clip_area);
lv_area_move(&rel_clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
lv_area_t clipped_coords;
if(!_lv_area_intersect(&clipped_coords, &rel_coords, &rel_clip_area))
return LV_RES_OK; /*Fully clipped, nothing to do*/
lv_res_t res = lv_gpu_nxp_vglite_draw_border_generic(&rel_coords, &rel_clip_area, dsc, true);
if(res != LV_RES_OK)
VG_LITE_LOG_TRACE("VG-Lite draw border failed. Fallback.");
return res;
}
static lv_res_t lv_draw_vglite_outline(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc,
const lv_area_t * coords)
{
if(dsc->outline_opa <= (lv_opa_t)LV_OPA_MIN)
return LV_RES_INV;
if(dsc->outline_width == 0)
return LV_RES_INV;
/* Move outline outwards to align with software rendered outline */
lv_coord_t outline_pad = dsc->outline_pad - 1;
lv_area_t rel_coords;
rel_coords.x1 = coords->x1 - outline_pad - floor(dsc->outline_width / 2.0f);
rel_coords.x2 = coords->x2 + outline_pad + ceil(dsc->outline_width / 2.0f);
rel_coords.y1 = coords->y1 - outline_pad - floor(dsc->outline_width / 2.0f);
rel_coords.y2 = coords->y2 + outline_pad + ceil(dsc->outline_width / 2.0f);
lv_area_move(&rel_coords, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
lv_area_t rel_clip_area;
lv_area_copy(&rel_clip_area, draw_ctx->clip_area);
lv_area_move(&rel_clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
lv_area_t clipped_coords;
if(!_lv_area_intersect(&clipped_coords, &rel_coords, &rel_clip_area))
return LV_RES_OK; /*Fully clipped, nothing to do*/
lv_res_t res = lv_gpu_nxp_vglite_draw_border_generic(&rel_coords, &rel_clip_area, dsc, false);
if(res != LV_RES_OK)
VG_LITE_LOG_TRACE("VG-Lite draw outline failed. Fallback.");
return res;
}
static void lv_draw_vglite_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center,
uint16_t radius, uint16_t start_angle, uint16_t end_angle)
{
bool done = false;
#if LV_DRAW_COMPLEX
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
return;
if(dsc->width == 0)
return;
if(start_angle == end_angle)
return;
if(need_argb8565_support()) {
lv_draw_sw_arc(draw_ctx, dsc, center, radius, start_angle, end_angle);
return;
}
lv_point_t rel_center = {center->x - draw_ctx->buf_area->x1, center->y - draw_ctx->buf_area->y1};
lv_area_t rel_clip_area;
lv_area_copy(&rel_clip_area, draw_ctx->clip_area);
lv_area_move(&rel_clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
bool has_mask = lv_draw_mask_is_any(&rel_clip_area);
if(!has_mask) {
done = (lv_gpu_nxp_vglite_draw_arc(&rel_center, (int32_t)radius, (int32_t)start_angle, (int32_t)end_angle,
&rel_clip_area, dsc) == LV_RES_OK);
if(!done)
VG_LITE_LOG_TRACE("VG-Lite draw arc failed. Fallback.");
}
#endif/*LV_DRAW_COMPLEX*/
if(!done)
lv_draw_sw_arc(draw_ctx, dsc, center, radius, start_angle, end_angle);
}
#endif /*LV_USE_GPU_NXP_VG_LITE*/

View File

@@ -0,0 +1,72 @@
/**
* @file lv_draw_vglite.h
*
*/
/**
* MIT License
*
* Copyright 2022, 2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next paragraph)
* shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef LV_DRAW_VGLITE_H
#define LV_DRAW_VGLITE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_GPU_NXP_VG_LITE
#include "../../sw/lv_draw_sw.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef lv_draw_sw_ctx_t lv_draw_vglite_ctx_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_draw_vglite_ctx_init(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
void lv_draw_vglite_ctx_deinit(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
/**********************
* MACROS
**********************/
#endif /*LV_USE_GPU_NXP_VG_LITE*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_VGLITE_H*/

View File

@@ -6,7 +6,7 @@
/**
* MIT License
*
* Copyright 2021, 2022 NXP
* Copyright 2021-2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -34,7 +34,8 @@
#include "lv_draw_vglite_arc.h"
#if LV_USE_GPU_NXP_VG_LITE
#include "math.h"
#include "lv_vglite_buf.h"
#include <math.h>
/*********************
* DEFINES
@@ -88,7 +89,7 @@ typedef struct _cubic_cont_pt {
static void rotate_point(int32_t angle, int32_t * x, int32_t * y);
static void add_arc_path(int32_t * arc_path, int * pidx, int32_t radius,
int32_t start_angle, int32_t end_angle, lv_point_t center, bool cw);
int32_t start_angle, int32_t end_angle, const lv_point_t * center, bool cw);
/**********************
* STATIC VARIABLES
@@ -102,31 +103,20 @@ static void add_arc_path(int32_t * arc_path, int * pidx, int32_t radius,
* GLOBAL FUNCTIONS
**********************/
lv_res_t lv_gpu_nxp_vglite_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center,
int32_t radius, int32_t start_angle, int32_t end_angle)
lv_res_t lv_gpu_nxp_vglite_draw_arc(const lv_point_t * center, int32_t radius, int32_t start_angle, int32_t end_angle,
const lv_area_t * clip_area, const lv_draw_arc_dsc_t * dsc)
{
vg_lite_buffer_t vgbuf;
vg_lite_error_t err = VG_LITE_SUCCESS;
lv_color32_t col32 = {.full = lv_color_to32(dsc->color)}; /*Convert color to RGBA8888*/
lv_coord_t dest_width = lv_area_get_width(draw_ctx->buf_area);
lv_coord_t dest_height = lv_area_get_height(draw_ctx->buf_area);
vg_lite_path_t path;
vg_lite_color_t vgcol; /* vglite takes ABGR */
vg_lite_matrix_t matrix;
lv_opa_t opa = dsc->opa;
bool donut = ((end_angle - start_angle) % 360 == 0) ? true : false;
lv_point_t clip_center = {center->x - draw_ctx->buf_area->x1, center->y - draw_ctx->buf_area->y1};
vg_lite_buffer_t * vgbuf = lv_vglite_get_dest_buf();
/* path: max size = 16 cubic bezier (7 words each) */
int32_t arc_path[16 * 7];
lv_memset_00(arc_path, sizeof(arc_path));
/*** Init destination buffer ***/
if(lv_vglite_init_buf(&vgbuf, (uint32_t)dest_width, (uint32_t)dest_height, (uint32_t)dest_width * sizeof(lv_color_t),
(const lv_color_t *)draw_ctx->buf, false) != LV_RES_OK)
VG_LITE_RETURN_INV("Init buffer failed.");
/*** Init path ***/
lv_coord_t width = dsc->width; /* inner arc radius = outer arc radius - width */
if(width > (lv_coord_t)radius)
@@ -140,11 +130,11 @@ lv_res_t lv_gpu_nxp_vglite_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_
cp_y = 0;
rotate_point(start_angle, &cp_x, &cp_y);
arc_path[pidx++] = VLC_OP_MOVE;
arc_path[pidx++] = clip_center.x + cp_x;
arc_path[pidx++] = clip_center.y + cp_y;
arc_path[pidx++] = center->x + cp_x;
arc_path[pidx++] = center->y + cp_y;
/* draw 1-5 outer quarters */
add_arc_path(arc_path, &pidx, radius, start_angle, end_angle, clip_center, true);
add_arc_path(arc_path, &pidx, radius, start_angle, end_angle, center, true);
if(donut) {
/* close outer circle */
@@ -152,24 +142,24 @@ lv_res_t lv_gpu_nxp_vglite_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_
cp_y = 0;
rotate_point(start_angle, &cp_x, &cp_y);
arc_path[pidx++] = VLC_OP_LINE;
arc_path[pidx++] = clip_center.x + cp_x;
arc_path[pidx++] = clip_center.y + cp_y;
arc_path[pidx++] = center->x + cp_x;
arc_path[pidx++] = center->y + cp_y;
/* start inner circle */
cp_x = radius - width;
cp_y = 0;
rotate_point(start_angle, &cp_x, &cp_y);
arc_path[pidx++] = VLC_OP_MOVE;
arc_path[pidx++] = clip_center.x + cp_x;
arc_path[pidx++] = clip_center.y + cp_y;
arc_path[pidx++] = center->x + cp_x;
arc_path[pidx++] = center->y + cp_y;
}
else if(dsc->rounded != 0U) { /* 1st rounded arc ending */
cp_x = radius - width / 2;
cp_y = 0;
rotate_point(end_angle, &cp_x, &cp_y);
lv_point_t round_center = {clip_center.x + cp_x, clip_center.y + cp_y};
lv_point_t round_center = {center->x + cp_x, center->y + cp_y};
add_arc_path(arc_path, &pidx, width / 2, end_angle, (end_angle + 180),
round_center, true);
&round_center, true);
}
else { /* 1st flat ending */
@@ -177,12 +167,12 @@ lv_res_t lv_gpu_nxp_vglite_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_
cp_y = 0;
rotate_point(end_angle, &cp_x, &cp_y);
arc_path[pidx++] = VLC_OP_LINE;
arc_path[pidx++] = clip_center.x + cp_x;
arc_path[pidx++] = clip_center.y + cp_y;
arc_path[pidx++] = center->x + cp_x;
arc_path[pidx++] = center->y + cp_y;
}
/* draw 1-5 inner quarters */
add_arc_path(arc_path, &pidx, radius - width, start_angle, end_angle, clip_center, false);
add_arc_path(arc_path, &pidx, radius - width, start_angle, end_angle, center, false);
/* last control point of curve */
if(donut) { /* close the loop */
@@ -190,17 +180,17 @@ lv_res_t lv_gpu_nxp_vglite_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_
cp_y = 0;
rotate_point(start_angle, &cp_x, &cp_y);
arc_path[pidx++] = VLC_OP_LINE;
arc_path[pidx++] = clip_center.x + cp_x;
arc_path[pidx++] = clip_center.y + cp_y;
arc_path[pidx++] = center->x + cp_x;
arc_path[pidx++] = center->y + cp_y;
}
else if(dsc->rounded != 0U) { /* 2nd rounded arc ending */
cp_x = radius - width / 2;
cp_y = 0;
rotate_point(start_angle, &cp_x, &cp_y);
lv_point_t round_center = {clip_center.x + cp_x, clip_center.y + cp_y};
lv_point_t round_center = {center->x + cp_x, center->y + cp_y};
add_arc_path(arc_path, &pidx, width / 2, (start_angle + 180), (start_angle + 360),
round_center, true);
&round_center, true);
}
else { /* 2nd flat ending */
@@ -208,46 +198,34 @@ lv_res_t lv_gpu_nxp_vglite_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_
cp_y = 0;
rotate_point(start_angle, &cp_x, &cp_y);
arc_path[pidx++] = VLC_OP_LINE;
arc_path[pidx++] = clip_center.x + cp_x;
arc_path[pidx++] = clip_center.y + cp_y;
arc_path[pidx++] = center->x + cp_x;
arc_path[pidx++] = center->y + cp_y;
}
arc_path[pidx++] = VLC_OP_END;
err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, (uint32_t)pidx * sizeof(int32_t), arc_path,
(vg_lite_float_t) draw_ctx->clip_area->x1, (vg_lite_float_t) draw_ctx->clip_area->y1,
((vg_lite_float_t) draw_ctx->clip_area->x2) + 1.0f, ((vg_lite_float_t) draw_ctx->clip_area->y2) + 1.0f);
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f);
VG_LITE_ERR_RETURN_INV(err, "Init path failed.");
/* set rotation angle */
vg_lite_buffer_format_t color_format = LV_COLOR_DEPTH == 16 ? VG_LITE_BGRA8888 : VG_LITE_ABGR8888;
if(lv_vglite_premult_and_swizzle(&vgcol, col32, dsc->opa, color_format) != LV_RES_OK)
VG_LITE_RETURN_INV("Premultiplication and swizzle failed.");
vg_lite_matrix_t matrix;
vg_lite_identity(&matrix);
if(opa <= (lv_opa_t)LV_OPA_MAX) {
/* Only pre-multiply color if hardware pre-multiplication is not present */
if(!vg_lite_query_feature(gcFEATURE_BIT_VG_PE_PREMULTIPLY)) {
col32.ch.red = (uint8_t)(((uint16_t)col32.ch.red * opa) >> 8);
col32.ch.green = (uint8_t)(((uint16_t)col32.ch.green * opa) >> 8);
col32.ch.blue = (uint8_t)(((uint16_t)col32.ch.blue * opa) >> 8);
}
col32.ch.alpha = opa;
}
#if LV_COLOR_DEPTH==16
vgcol = col32.full;
#else /*LV_COLOR_DEPTH==32*/
vgcol = ((uint32_t)col32.ch.alpha << 24) | ((uint32_t)col32.ch.blue << 16) | ((uint32_t)col32.ch.green << 8) |
(uint32_t)col32.ch.red;
#endif
/*Clean & invalidate cache*/
lv_vglite_invalidate_cache();
lv_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);
err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol);
VG_LITE_ERR_RETURN_INV(err, "Draw arc failed.");
err = vg_lite_finish();
VG_LITE_ERR_RETURN_INV(err, "Finish failed.");
if(lv_vglite_run() != LV_RES_OK)
VG_LITE_RETURN_INV("Run failed.");
lv_vglite_disable_scissor();
err = vg_lite_clear_path(&path);
VG_LITE_ERR_RETURN_INV(err, "Clear path failed.");
@@ -564,50 +542,50 @@ static void get_arc_control_points(vg_arc * arc, bool start)
* center: (in) the center of the circle in draw coordinates
* cw: (in) true if arc is clockwise
*/
static void add_split_arc_path(int32_t * arc_path, int * pidx, vg_arc * q_arc, lv_point_t center, bool cw)
static void add_split_arc_path(int32_t * arc_path, int * pidx, vg_arc * q_arc, const lv_point_t * center, bool cw)
{
/* assumes first control point already in array arc_path[] */
int idx = *pidx;
if(cw) {
#if BEZIER_DBG_CONTROL_POINTS
arc_path[idx++] = VLC_OP_LINE;
arc_path[idx++] = q_arc->p1x + center.x;
arc_path[idx++] = q_arc->p1y + center.y;
arc_path[idx++] = q_arc->p1x + center->x;
arc_path[idx++] = q_arc->p1y + center->y;
arc_path[idx++] = VLC_OP_LINE;
arc_path[idx++] = q_arc->p2x + center.x;
arc_path[idx++] = q_arc->p2y + center.y;
arc_path[idx++] = q_arc->p2x + center->x;
arc_path[idx++] = q_arc->p2y + center->y;
arc_path[idx++] = VLC_OP_LINE;
arc_path[idx++] = q_arc->p3x + center.x;
arc_path[idx++] = q_arc->p3y + center.y;
arc_path[idx++] = q_arc->p3x + center->x;
arc_path[idx++] = q_arc->p3y + center->y;
#else
arc_path[idx++] = VLC_OP_CUBIC;
arc_path[idx++] = q_arc->p1x + center.x;
arc_path[idx++] = q_arc->p1y + center.y;
arc_path[idx++] = q_arc->p2x + center.x;
arc_path[idx++] = q_arc->p2y + center.y;
arc_path[idx++] = q_arc->p3x + center.x;
arc_path[idx++] = q_arc->p3y + center.y;
arc_path[idx++] = q_arc->p1x + center->x;
arc_path[idx++] = q_arc->p1y + center->y;
arc_path[idx++] = q_arc->p2x + center->x;
arc_path[idx++] = q_arc->p2y + center->y;
arc_path[idx++] = q_arc->p3x + center->x;
arc_path[idx++] = q_arc->p3y + center->y;
#endif
}
else { /* reverse points order when counter-clockwise */
#if BEZIER_DBG_CONTROL_POINTS
arc_path[idx++] = VLC_OP_LINE;
arc_path[idx++] = q_arc->p2x + center.x;
arc_path[idx++] = q_arc->p2y + center.y;
arc_path[idx++] = q_arc->p2x + center->x;
arc_path[idx++] = q_arc->p2y + center->y;
arc_path[idx++] = VLC_OP_LINE;
arc_path[idx++] = q_arc->p1x + center.x;
arc_path[idx++] = q_arc->p1y + center.y;
arc_path[idx++] = q_arc->p1x + center->x;
arc_path[idx++] = q_arc->p1y + center->y;
arc_path[idx++] = VLC_OP_LINE;
arc_path[idx++] = q_arc->p0x + center.x;
arc_path[idx++] = q_arc->p0y + center.y;
arc_path[idx++] = q_arc->p0x + center->x;
arc_path[idx++] = q_arc->p0y + center->y;
#else
arc_path[idx++] = VLC_OP_CUBIC;
arc_path[idx++] = q_arc->p2x + center.x;
arc_path[idx++] = q_arc->p2y + center.y;
arc_path[idx++] = q_arc->p1x + center.x;
arc_path[idx++] = q_arc->p1y + center.y;
arc_path[idx++] = q_arc->p0x + center.x;
arc_path[idx++] = q_arc->p0y + center.y;
arc_path[idx++] = q_arc->p2x + center->x;
arc_path[idx++] = q_arc->p2y + center->y;
arc_path[idx++] = q_arc->p1x + center->x;
arc_path[idx++] = q_arc->p1y + center->y;
arc_path[idx++] = q_arc->p0x + center->x;
arc_path[idx++] = q_arc->p0y + center->y;
#endif
}
/* update index i n path array*/
@@ -615,7 +593,7 @@ static void add_split_arc_path(int32_t * arc_path, int * pidx, vg_arc * q_arc, l
}
static void add_arc_path(int32_t * arc_path, int * pidx, int32_t radius,
int32_t start_angle, int32_t end_angle, lv_point_t center, bool cw)
int32_t start_angle, int32_t end_angle, const lv_point_t * center, bool cw)
{
/* set number of arcs to draw */
vg_arc q_arc;

View File

@@ -6,7 +6,7 @@
/**
* MIT License
*
* Copyright 2021, 2022 NXP
* Copyright 2021-2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -40,7 +40,7 @@ extern "C" {
#include "../../../lv_conf_internal.h"
#if LV_USE_GPU_NXP_VG_LITE
#include "lv_gpu_nxp_vglite.h"
#include "lv_vglite_utils.h"
/*********************
* DEFINES
@@ -54,17 +54,21 @@ extern "C" {
* GLOBAL PROTOTYPES
**********************/
/***
/**
* Draw arc shape with effects
* @param draw_ctx drawing context
* @param dsc the arc description structure (width, rounded ending, opacity)
* @param center the coordinates of the arc center
* @param radius the radius of external arc
* @param start_angle the starting angle in degrees
* @param end_angle the ending angle in degrees
*
* @param[in] center Arc center with relative coordinates
* @param[in] radius Radius of external arc
* @param[in] start_angle Starting angle in degrees
* @param[in] end_angle Ending angle in degrees
* @param[in] clip_area Clipping area with relative coordinates to dest buff
* @param[in] dsc Arc description structure (width, rounded ending, opacity)
*
* @retval LV_RES_OK Draw completed
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
*/
lv_res_t lv_gpu_nxp_vglite_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center,
int32_t radius, int32_t start_angle, int32_t end_angle);
lv_res_t lv_gpu_nxp_vglite_draw_arc(const lv_point_t * center, int32_t radius, int32_t start_angle, int32_t end_angle,
const lv_area_t * clip_area, const lv_draw_arc_dsc_t * dsc);
/**********************
* MACROS

View File

@@ -6,7 +6,7 @@
/**
* MIT License
*
* Copyright 2020-2022 NXP
* Copyright 2020-2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -34,30 +34,24 @@
#include "lv_draw_vglite_blend.h"
#if LV_USE_GPU_NXP_VG_LITE
#include "lv_vglite_buf.h"
#include "lv_vglite_utils.h"
/*********************
* DEFINES
*********************/
/* Enable BLIT quality degradation workaround for RT595, recommended for screen's dimension > 352 pixels */
#define RT595_BLIT_WRKRND_ENABLED 1
/** Stride in px required by VG-Lite HW*/
#define LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX 16U
/* Internal compound symbol */
#if (defined(CPU_MIMXRT595SFFOB) || defined(CPU_MIMXRT595SFFOB_cm33) || \
defined(CPU_MIMXRT595SFFOC) || defined(CPU_MIMXRT595SFFOC_cm33)) && \
RT595_BLIT_WRKRND_ENABLED
#define VG_LITE_BLIT_SPLIT_ENABLED 1
#else
#define VG_LITE_BLIT_SPLIT_ENABLED 0
#if VG_LITE_BLIT_SPLIT_ENABLED
/**
* BLIT split threshold - BLITs with width or height higher than this value will be done
* in multiple steps. Value must be 16-aligned. Don't change.
*/
#define LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR 352
#endif
/**
* BLIT split threshold - BLITs with width or height higher than this value will be done
* in multiple steps. Value must be 16-aligned. Don't change.
*/
#define LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR 352
/**********************
* TYPEDEFS
**********************/
@@ -67,63 +61,85 @@
**********************/
/**
* BLock Image Transfer - single direct BLIT.
* Blit image, with optional opacity.
*
* @param[in] src_area Source area with relative coordinates of source buffer
* @param[in] opa Opacity
*
* @param[in] blit Description of the transfer
* @retval LV_RES_OK Transfer complete
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
*/
static lv_res_t _lv_gpu_nxp_vglite_blit_single(lv_gpu_nxp_vglite_blit_info_t * blit);
static lv_res_t lv_vglite_blit(const lv_area_t * src_area, lv_opa_t opa);
/**
* Check source memory and stride alignment.
*
* @param[in] src_buf Source buffer
* @param[in] src_stride Stride of source buffer in pixels
*
* @retval LV_RES_OK Alignment OK
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
*/
static lv_res_t check_src_alignment(const lv_color_t * src_buf, lv_coord_t src_stride);
/**
* Creates matrix that translates to origin of given destination area.
*
* @param[in] dest_area Area with relative coordinates of destination buffer
*/
static inline void lv_vglite_set_translation_matrix(const lv_area_t * dest_area);
/**
* Creates matrix that translates to origin of given destination area with transformation (scale or rotate).
*
* @param[in] dest_area Area with relative coordinates of destination buffer
* @param[in] dsc Image descriptor
*/
static inline void lv_vglite_set_transformation_matrix(const lv_area_t * dest_area, const lv_draw_img_dsc_t * dsc);
#if VG_LITE_BLIT_SPLIT_ENABLED
/**
* Move buffer pointer as close as possible to area, but with respect to alignment requirements. X-axis only.
*
* @param[in/out] area Area to be updated
* @param[in/out] buf Pointer to be updated
*/
static void align_x(lv_area_t * area, lv_color_t ** buf);
/**
* Move buffer pointer as close as possible to area, but with respect to alignment requirements. X-axis only.
*
* @param[in,out] area Area to be updated
* @param[in,out] buf Pointer to be updated
*/
static void _align_x(lv_area_t * area, lv_color_t ** buf);
/**
* Move buffer pointer to the area start and update variables, Y-axis only.
*
* @param[in/out] area Area to be updated
* @param[in/out] buf Pointer to be updated
* @param[in] stride Buffer stride in pixels
*/
static void align_y(lv_area_t * area, lv_color_t ** buf, lv_coord_t stride);
/**
* Move buffer pointer to the area start and update variables, Y-axis only.
*
* @param[in,out] area Area to be updated
* @param[in,out] buf Pointer to be updated
* @param[in] stridePx Buffer stride in pixels
*/
static void _align_y(lv_area_t * area, lv_color_t ** buf, uint32_t stridePx);
/**
* Software BLIT as a fall-back scenario.
*
* @param[in] blit BLIT configuration
*/
static void _sw_blit(lv_gpu_nxp_vglite_blit_info_t * blit);
/**
* Verify BLIT structure - widths, stride, pointer alignment
*
* @param[in] blit BLIT configuration
* @retval LV_RES_OK
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
*/
static lv_res_t _lv_gpu_nxp_vglite_check_blit(lv_gpu_nxp_vglite_blit_info_t * blit);
/**
* BLock Image Transfer - split BLIT.
*
* @param[in] blit BLIT configuration
* @retval LV_RES_OK Transfer complete
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
*/
static lv_res_t _lv_gpu_nxp_vglite_blit_split(lv_gpu_nxp_vglite_blit_info_t * blit);
#endif
/**
* Blit image split in tiles, with optional opacity.
*
* @param[in/out] dest_buf Destination buffer
* @param[in] dest_area Area with relative coordinates of destination buffer
* @param[in] dest_stride Stride of destination buffer in pixels
* @param[in] src_buf Source buffer
* @param[in] src_area Source area with relative coordinates of source buffer
* @param[in] src_stride Stride of source buffer in pixels
* @param[in] opa Opacity
*
* @retval LV_RES_OK Transfer complete
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
*/
static lv_res_t lv_vglite_blit_split(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, lv_area_t * src_area, lv_coord_t src_stride,
lv_opa_t opa);
#endif /*VG_LITE_BLIT_SPLIT_ENABLED*/
/**********************
* STATIC VARIABLES
**********************/
static vg_lite_matrix_t vgmatrix;
/**********************
* MACROS
**********************/
@@ -132,98 +148,57 @@ static lv_res_t _lv_gpu_nxp_vglite_blit_single(lv_gpu_nxp_vglite_blit_info_t * b
* GLOBAL FUNCTIONS
**********************/
lv_res_t lv_gpu_nxp_vglite_fill(lv_color_t * dest_buf, lv_coord_t dest_width, lv_coord_t dest_height,
const lv_area_t * fill_area, lv_color_t color, lv_opa_t opa)
lv_res_t lv_gpu_nxp_vglite_fill(const lv_area_t * dest_area, lv_color_t color, lv_opa_t opa)
{
uint32_t area_size = lv_area_get_size(fill_area);
lv_coord_t area_w = lv_area_get_width(fill_area);
lv_coord_t area_h = lv_area_get_height(fill_area);
if(opa >= (lv_opa_t)LV_OPA_MAX) {
if(area_size < LV_GPU_NXP_VG_LITE_FILL_SIZE_LIMIT)
VG_LITE_RETURN_INV("Area size %d smaller than limit %d.", area_size, LV_GPU_NXP_VG_LITE_FILL_SIZE_LIMIT);
}
else {
if(area_size < LV_GPU_NXP_VG_LITE_FILL_OPA_SIZE_LIMIT)
VG_LITE_RETURN_INV("Area size %d smaller than limit %d.", area_size, LV_GPU_NXP_VG_LITE_FILL_OPA_SIZE_LIMIT);
}
vg_lite_buffer_t vgbuf;
vg_lite_rectangle_t rect;
vg_lite_error_t err = VG_LITE_SUCCESS;
lv_color32_t col32 = {.full = lv_color_to32(color)}; /*Convert color to RGBA8888*/
vg_lite_color_t vgcol; /* vglite takes ABGR */
vg_lite_buffer_t * vgbuf = lv_vglite_get_dest_buf();
if(lv_vglite_init_buf(&vgbuf, (uint32_t)dest_width, (uint32_t)dest_height, (uint32_t)dest_width * sizeof(lv_color_t),
(const lv_color_t *)dest_buf, false) != LV_RES_OK)
VG_LITE_RETURN_INV("Init buffer failed.");
vg_lite_buffer_format_t color_format = LV_COLOR_DEPTH == 16 ? VG_LITE_BGRA8888 : VG_LITE_ABGR8888;
if(lv_vglite_premult_and_swizzle(&vgcol, col32, opa, color_format) != LV_RES_OK)
VG_LITE_RETURN_INV("Premultiplication and swizzle failed.");
if(opa >= (lv_opa_t)LV_OPA_MAX) { /*Opaque fill*/
rect.x = fill_area->x1;
rect.y = fill_area->y1;
rect.width = area_w;
rect.height = area_h;
vg_lite_rectangle_t rect = {
.x = dest_area->x1,
.y = dest_area->y1,
.width = lv_area_get_width(dest_area),
.height = lv_area_get_height(dest_area)
};
/*Clean & invalidate cache*/
lv_vglite_invalidate_cache();
#if LV_COLOR_DEPTH==16
vgcol = col32.full;
#else /*LV_COLOR_DEPTH==32*/
vgcol = ((uint32_t)col32.ch.alpha << 24) | ((uint32_t)col32.ch.blue << 16) | ((uint32_t)col32.ch.green << 8) |
(uint32_t)col32.ch.red;
#endif
err = vg_lite_clear(&vgbuf, &rect, vgcol);
err = vg_lite_clear(vgbuf, &rect, vgcol);
VG_LITE_ERR_RETURN_INV(err, "Clear failed.");
err = vg_lite_finish();
VG_LITE_ERR_RETURN_INV(err, "Finish failed.");
if(lv_vglite_run() != LV_RES_OK)
VG_LITE_RETURN_INV("Run failed.");
}
else { /*fill with transparency*/
vg_lite_path_t path;
int32_t path_data[] = { /*VG rectangular path*/
VLC_OP_MOVE, fill_area->x1, fill_area->y1,
VLC_OP_LINE, fill_area->x2 + 1, fill_area->y1,
VLC_OP_LINE, fill_area->x2 + 1, fill_area->y2 + 1,
VLC_OP_LINE, fill_area->x1, fill_area->y2 + 1,
VLC_OP_LINE, fill_area->x1, fill_area->y1,
VLC_OP_MOVE, dest_area->x1, dest_area->y1,
VLC_OP_LINE, dest_area->x2 + 1, dest_area->y1,
VLC_OP_LINE, dest_area->x2 + 1, dest_area->y2 + 1,
VLC_OP_LINE, dest_area->x1, dest_area->y2 + 1,
VLC_OP_LINE, dest_area->x1, dest_area->y1,
VLC_OP_END
};
err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_LOW, sizeof(path_data), path_data,
(vg_lite_float_t) fill_area->x1, (vg_lite_float_t) fill_area->y1,
((vg_lite_float_t) fill_area->x2) + 1.0f, ((vg_lite_float_t) fill_area->y2) + 1.0f);
(vg_lite_float_t) dest_area->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_ERR_RETURN_INV(err, "Init path failed.");
/* Only pre-multiply color if hardware pre-multiplication is not present */
if(!vg_lite_query_feature(gcFEATURE_BIT_VG_PE_PREMULTIPLY)) {
col32.ch.red = (uint8_t)(((uint16_t)col32.ch.red * opa) >> 8);
col32.ch.green = (uint8_t)(((uint16_t)col32.ch.green * opa) >> 8);
col32.ch.blue = (uint8_t)(((uint16_t)col32.ch.blue * opa) >> 8);
}
col32.ch.alpha = opa;
#if LV_COLOR_DEPTH==16
vgcol = col32.full;
#else /*LV_COLOR_DEPTH==32*/
vgcol = ((uint32_t)col32.ch.alpha << 24) | ((uint32_t)col32.ch.blue << 16) | ((uint32_t)col32.ch.green << 8) |
(uint32_t)col32.ch.red;
#endif
/*Clean & invalidate cache*/
lv_vglite_invalidate_cache();
vg_lite_matrix_t matrix;
vg_lite_identity(&matrix);
/*Draw rectangle*/
err = vg_lite_draw(&vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol);
err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol);
VG_LITE_ERR_RETURN_INV(err, "Draw rectangle failed.");
err = vg_lite_finish();
VG_LITE_ERR_RETURN_INV(err, "Finish failed.");
if(lv_vglite_run() != LV_RES_OK)
VG_LITE_RETURN_INV("Run failed.");
err = vg_lite_clear_path(&path);
VG_LITE_ERR_RETURN_INV(err, "Clear path failed.");
@@ -232,41 +207,128 @@ lv_res_t lv_gpu_nxp_vglite_fill(lv_color_t * dest_buf, lv_coord_t dest_width, lv
return LV_RES_OK;
}
lv_res_t lv_gpu_nxp_vglite_blit(lv_gpu_nxp_vglite_blit_info_t * blit)
{
uint32_t dest_size = lv_area_get_size(&blit->dst_area);
if(blit->opa >= (lv_opa_t)LV_OPA_MAX) {
if(dest_size < LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT)
VG_LITE_RETURN_INV("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT);
}
else {
if(dest_size < LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT)
VG_LITE_RETURN_INV("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT);
}
#if VG_LITE_BLIT_SPLIT_ENABLED
return _lv_gpu_nxp_vglite_blit_split(blit);
#endif /* non RT595 */
lv_res_t lv_gpu_nxp_vglite_blit_split(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, lv_area_t * src_area, lv_coord_t src_stride,
lv_opa_t opa)
{
/* Set src_vgbuf structure. */
lv_vglite_set_src_buf(src_buf, src_area, src_stride);
/* Just pass down */
return _lv_gpu_nxp_vglite_blit_single(blit);
lv_color_t * orig_dest_buf = dest_buf;
lv_res_t rv = lv_vglite_blit_split(dest_buf, dest_area, dest_stride, src_buf, src_area, src_stride, opa);
/* Restore the original dest_vgbuf memory address. */
lv_vglite_set_dest_buf_ptr(orig_dest_buf);
return rv;
}
#else
lv_res_t lv_gpu_nxp_vglite_blit(const lv_area_t * dest_area,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
lv_opa_t opa)
{
if(check_src_alignment(src_buf, src_stride) != LV_RES_OK)
VG_LITE_RETURN_INV("Check src alignment failed.");
/* Set src_vgbuf structure. */
lv_vglite_set_src_buf(src_buf, src_area, src_stride);
/* Set scissor. */
lv_vglite_set_scissor(dest_area);
/* Set vgmatrix. */
lv_vglite_set_translation_matrix(dest_area);
/* Start blit. */
lv_res_t rv = lv_vglite_blit(src_area, opa);
/* Disable scissor. */
lv_vglite_disable_scissor();
return rv;
}
lv_res_t lv_gpu_nxp_vglite_blit_transform(lv_gpu_nxp_vglite_blit_info_t * blit)
lv_res_t lv_gpu_nxp_vglite_blit_transform(const lv_area_t * dest_area, const lv_area_t * clip_area,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
const lv_draw_img_dsc_t * dsc)
{
uint32_t dest_size = lv_area_get_size(&blit->dst_area);
lv_res_t rv = LV_RES_INV;
if(blit->opa >= (lv_opa_t)LV_OPA_MAX) {
if(dest_size < LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT)
VG_LITE_RETURN_INV("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT);
}
else {
if(dest_size < LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT)
VG_LITE_RETURN_INV("Area size %d smaller than limit %d.", dest_size, LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT);
if(check_src_alignment(src_buf, src_stride) != LV_RES_OK)
VG_LITE_RETURN_INV("Check src alignment failed.");
/* Set src_vgbuf structure. */
lv_vglite_set_src_buf(src_buf, src_area, src_stride);
/* Set scissor */
lv_vglite_set_scissor(clip_area);
/* Set vgmatrix. */
lv_vglite_set_transformation_matrix(dest_area, dsc);
/* Start blit. */
rv = lv_vglite_blit(src_area, dsc->opa);
/* Disable scissor. */
lv_vglite_disable_scissor();
return rv;
}
#endif /*VG_LITE_BLIT_SPLIT_ENABLED*/
lv_res_t lv_gpu_nxp_vglite_buffer_copy(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride)
{
vg_lite_error_t err = VG_LITE_SUCCESS;
if(check_src_alignment(src_buf, src_stride) != LV_RES_OK)
VG_LITE_RETURN_INV("Check src alignment failed.");
vg_lite_buffer_t src_vgbuf;
/* Set src_vgbuf structure. */
lv_vglite_set_buf(&src_vgbuf, src_buf, src_area, src_stride);
vg_lite_buffer_t dest_vgbuf;
/* Set dest_vgbuf structure. */
lv_vglite_set_buf(&dest_vgbuf, dest_buf, dest_area, dest_stride);
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. */
lv_vglite_set_scissor(dest_area);
/* Set vgmatrix. */
lv_vglite_set_translation_matrix(dest_area);
err = vg_lite_blit_rect(&dest_vgbuf, &src_vgbuf, rect, &vgmatrix,
VG_LITE_BLEND_NONE, 0xFFFFFFFFU, VG_LITE_FILTER_POINT);
if(err != VG_LITE_SUCCESS) {
LV_LOG_ERROR("Blit rectangle failed.");
/* Disable scissor. */
lv_vglite_disable_scissor();
return LV_RES_INV;
}
return _lv_gpu_nxp_vglite_blit_single(blit);
if(lv_vglite_run() != LV_RES_OK) {
LV_LOG_ERROR("Run failed.");
/* Disable scissor. */
lv_vglite_disable_scissor();
return LV_RES_INV;
}
/* Disable scissor. */
lv_vglite_disable_scissor();
return LV_RES_OK;
}
/**********************
@@ -274,223 +336,210 @@ lv_res_t lv_gpu_nxp_vglite_blit_transform(lv_gpu_nxp_vglite_blit_info_t * blit)
**********************/
#if VG_LITE_BLIT_SPLIT_ENABLED
static lv_res_t _lv_gpu_nxp_vglite_blit_split(lv_gpu_nxp_vglite_blit_info_t * blit)
static lv_res_t lv_vglite_blit_split(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, lv_area_t * src_area, lv_coord_t src_stride,
lv_opa_t opa)
{
lv_res_t rv = LV_RES_INV;
if(_lv_gpu_nxp_vglite_check_blit(blit) != LV_RES_OK) {
PRINT_BLT("Blit check failed\n");
return LV_RES_INV;
}
VG_LITE_LOG_TRACE("Blit "
"Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | "
"Size: ([%dx%d] -> [%dx%d]) | "
"Addr: (0x%x -> 0x%x)",
src_area->x1, src_area->y1, src_area->x2, src_area->y2,
dest_area->x1, dest_area->y1, dest_area->x2, dest_area->y2,
lv_area_get_width(src_area), lv_area_get_height(src_area),
lv_area_get_width(dest_area), lv_area_get_height(dest_area),
(uintptr_t)src_buf, (uintptr_t)dest_buf);
PRINT_BLT("BLIT from: "
"Area: %03d,%03d - %03d,%03d "
"Addr: %d\n\n",
blit->src_area.x1, blit->src_area.y1,
blit->src_area.x2, blit->src_area.y2,
(uintptr_t) blit->src);
PRINT_BLT("BLIT to: "
"Area: %03d,%03d - %03d,%03d "
"Addr: %d\n\n",
blit->dst_area.x1, blit->dst_area.y1,
blit->dst_area.x2, blit->dst_area.y2,
(uintptr_t) blit->src);
/* Stage 1: Move starting pointers as close as possible to [x1, y1], so coordinates are as small as possible. */
_align_x(&blit->src_area, (lv_color_t **)&blit->src);
_align_y(&blit->src_area, (lv_color_t **)&blit->src, blit->src_stride / sizeof(lv_color_t));
_align_x(&blit->dst_area, (lv_color_t **)&blit->dst);
_align_y(&blit->dst_area, (lv_color_t **)&blit->dst, blit->dst_stride / sizeof(lv_color_t));
/* Stage 1: Move starting pointers as close as possible to [x1, y1], so coordinates are as small as possible. */
align_x(src_area, (lv_color_t **)&src_buf);
align_y(src_area, (lv_color_t **)&src_buf, src_stride);
align_x(dest_area, (lv_color_t **)&dest_buf);
align_y(dest_area, (lv_color_t **)&dest_buf, dest_stride);
/* Stage 2: If we're in limit, do a single BLIT */
if((blit->src_area.x2 < LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) &&
(blit->src_area.y2 < LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR)) {
PRINT_BLT("Simple blit!\n");
return _lv_gpu_nxp_vglite_blit_single(blit);
if((src_area->x2 < LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) &&
(src_area->y2 < LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR)) {
if(check_src_alignment(src_buf, src_stride) != LV_RES_OK)
VG_LITE_RETURN_INV("Check src alignment failed.");
/* Set new dest_vgbuf and src_vgbuf memory addresses. */
lv_vglite_set_dest_buf_ptr(dest_buf);
lv_vglite_set_src_buf_ptr(src_buf);
/* Set scissor */
lv_vglite_set_scissor(dest_area);
/* Set vgmatrix. */
lv_vglite_set_translation_matrix(dest_area);
/* Start blit. */
rv = lv_vglite_blit(src_area, opa);
/* Disable scissor. */
lv_vglite_disable_scissor();
VG_LITE_LOG_TRACE("Single "
"Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | "
"Size: ([%dx%d] -> [%dx%d]) | "
"Addr: (0x%x -> 0x%x) %s",
src_area->x1, src_area->y1, src_area->x2, src_area->y2,
dest_area->x1, dest_area->y1, dest_area->x2, dest_area->y2,
lv_area_get_width(src_area), lv_area_get_height(src_area),
lv_area_get_width(dest_area), lv_area_get_height(dest_area),
(uintptr_t)src_buf, (uintptr_t)dest_buf,
rv == LV_RES_OK ? "OK!" : "FAILED!");
return rv;
};
/* Stage 3: Split the BLIT into multiple tiles */
PRINT_BLT("Split blit!\n");
PRINT_BLT("Blit "
"([%03d,%03d], [%03d,%03d]) -> "
"([%03d,%03d], [%03d,%03d]) | "
"([%03dx%03d] -> [%03dx%03d]) | "
"A:(%d -> %d)\n",
blit->src_area.x1, blit->src_area.y1, blit->src_area.x2, blit->src_area.y2,
blit->dst_area.x1, blit->dst_area.y1, blit->dst_area.x2, blit->dst_area.y2,
lv_area_get_width(&blit->src_area), lv_area_get_height(&blit->src_area),
lv_area_get_width(&blit->dst_area), lv_area_get_height(&blit->dst_area),
(uintptr_t) blit->src, (uintptr_t) blit->dst);
VG_LITE_LOG_TRACE("Split "
"Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | "
"Size: ([%dx%d] -> [%dx%d]) | "
"Addr: (0x%x -> 0x%x)",
src_area->x1, src_area->y1, src_area->x2, src_area->y2,
dest_area->x1, dest_area->y1, dest_area->x2, dest_area->y2,
lv_area_get_width(src_area), lv_area_get_height(src_area),
lv_area_get_width(dest_area), lv_area_get_height(dest_area),
(uintptr_t)src_buf, (uintptr_t)dest_buf);
lv_coord_t totalWidth = lv_area_get_width(&blit->src_area);
lv_coord_t totalHeight = lv_area_get_height(&blit->src_area);
lv_gpu_nxp_vglite_blit_info_t tileBlit;
lv_coord_t width = lv_area_get_width(src_area);
lv_coord_t height = lv_area_get_height(src_area);
/* Number of tiles needed */
int totalTilesX = (blit->src_area.x1 + totalWidth + LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1) /
LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR;
int totalTilesY = (blit->src_area.y1 + totalHeight + LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1) /
LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR;
int total_tiles_x = (src_area->x1 + width + LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1) /
LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR;
int total_tiles_y = (src_area->y1 + height + LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1) /
LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR;
/* src and dst buffer shift against each other. Src buffer real data [0,0] may start actually at [3,0] in buffer, as
* the buffer pointer has to be aligned, while dst buffer real data [0,0] may start at [1,0] in buffer. alignment may be
* different */
int shiftSrcX = (blit->src_area.x1 > blit->dst_area.x1) ? (blit->src_area.x1 - blit->dst_area.x1) : 0;
int shiftDstX = (blit->src_area.x1 < blit->dst_area.x1) ? (blit->dst_area.x1 - blit->src_area.x1) : 0;
int shift_src_x = (src_area->x1 > dest_area->x1) ? (src_area->x1 - dest_area->x1) : 0;
int shift_dest_x = (src_area->x1 < dest_area->x1) ? (dest_area->x1 - src_area->x1) : 0;
PRINT_BLT("\n");
PRINT_BLT("Align shift: src: %d, dst: %d\n", shiftSrcX, shiftDstX);
VG_LITE_LOG_TRACE("X shift: src: %d, dst: %d", shift_src_x, shift_dest_x);
tileBlit = *blit;
lv_color_t * tile_dest_buf;
lv_area_t tile_dest_area;
const lv_color_t * tile_src_buf;
lv_area_t tile_src_area;
for(int tileY = 0; tileY < totalTilesY; tileY++) {
for(int y = 0; y < total_tiles_y; y++) {
tileBlit.src_area.y1 = 0; /* no vertical alignment, always start from 0 */
tileBlit.src_area.y2 = totalHeight - tileY * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
if(tileBlit.src_area.y2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) {
tileBlit.src_area.y2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; /* Should never happen */
tile_src_area.y1 = 0; /* no vertical alignment, always start from 0 */
tile_src_area.y2 = height - y * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
if(tile_src_area.y2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) {
tile_src_area.y2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; /* Should never happen */
}
tileBlit.src = blit->src + tileY * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR * blit->src_stride / sizeof(
lv_color_t); /* stride in px! */
tile_src_buf = src_buf + y * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR * src_stride;
tileBlit.dst_area.y1 = tileBlit.src_area.y1; /* y has no alignment, always in sync with src */
tileBlit.dst_area.y2 = tileBlit.src_area.y2;
tile_dest_area.y1 = tile_src_area.y1; /* y has no alignment, always in sync with src */
tile_dest_area.y2 = tile_src_area.y2;
tileBlit.dst = blit->dst + tileY * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR * blit->dst_stride / sizeof(
lv_color_t); /* stride in px! */
tile_dest_buf = dest_buf + y * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR * dest_stride;
for(int tileX = 0; tileX < totalTilesX; tileX++) {
for(int x = 0; x < total_tiles_x; x++) {
if(tileX == 0) {
if(x == 0) {
/* 1st tile is special - there may be a gap between buffer start pointer
* and area.x1 value, as the pointer has to be aligned.
* tileBlit.src pointer - keep init value from Y-loop.
* tile_src_buf pointer - keep init value from Y-loop.
* Also, 1st tile start is not shifted! shift is applied from 2nd tile */
tileBlit.src_area.x1 = blit->src_area.x1;
tileBlit.dst_area.x1 = blit->dst_area.x1;
tile_src_area.x1 = src_area->x1;
tile_dest_area.x1 = dest_area->x1;
}
else {
/* subsequent tiles always starts from 0, but shifted*/
tileBlit.src_area.x1 = 0 + shiftSrcX;
tileBlit.dst_area.x1 = 0 + shiftDstX;
tile_src_area.x1 = 0 + shift_src_x;
tile_dest_area.x1 = 0 + shift_dest_x;
/* and advance start pointer + 1 tile size */
tileBlit.src += LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR;
tileBlit.dst += LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR;
tile_src_buf += LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR;
tile_dest_buf += LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR;
}
/* Clip tile end coordinates */
tileBlit.src_area.x2 = totalWidth + blit->src_area.x1 - tileX * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
if(tileBlit.src_area.x2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) {
tileBlit.src_area.x2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
tile_src_area.x2 = width + src_area->x1 - x * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
if(tile_src_area.x2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) {
tile_src_area.x2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
}
tileBlit.dst_area.x2 = totalWidth + blit->dst_area.x1 - tileX * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
if(tileBlit.dst_area.x2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) {
tileBlit.dst_area.x2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
tile_dest_area.x2 = width + dest_area->x1 - x * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
if(tile_dest_area.x2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) {
tile_dest_area.x2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1;
}
if(tileX < (totalTilesX - 1)) {
/* And adjust end coords if shifted, but not for last tile! */
tileBlit.src_area.x2 += shiftSrcX;
tileBlit.dst_area.x2 += shiftDstX;
if(x < (total_tiles_x - 1)) {
/* And adjust end coords if shifted, but not for last tile! */
tile_src_area.x2 += shift_src_x;
tile_dest_area.x2 += shift_dest_x;
}
rv = _lv_gpu_nxp_vglite_blit_single(&tileBlit);
if(check_src_alignment(tile_src_buf, src_stride) != LV_RES_OK)
VG_LITE_RETURN_INV("Check src alignment failed.");
#if BLIT_DBG_AREAS
lv_vglite_dbg_draw_rectangle((lv_color_t *) tileBlit.dst, tileBlit.dst_width, tileBlit.dst_height, &tileBlit.dst_area,
LV_COLOR_RED);
lv_vglite_dbg_draw_rectangle((lv_color_t *) tileBlit.src, tileBlit.src_width, tileBlit.src_height, &tileBlit.src_area,
LV_COLOR_GREEN);
#endif
/* Set new dest_vgbuf and src_vgbuf memory addresses. */
lv_vglite_set_dest_buf_ptr(tile_dest_buf);
lv_vglite_set_src_buf_ptr(tile_src_buf);
PRINT_BLT("Tile [%d, %d]: "
"([%d,%d], [%d,%d]) -> "
"([%d,%d], [%d,%d]) | "
"([%dx%d] -> [%dx%d]) | "
"A:(0x%8X -> 0x%8X) %s\n",
tileX, tileY,
tileBlit.src_area.x1, tileBlit.src_area.y1, tileBlit.src_area.x2, tileBlit.src_area.y2,
tileBlit.dst_area.x1, tileBlit.dst_area.y1, tileBlit.dst_area.x2, tileBlit.dst_area.y2,
lv_area_get_width(&tileBlit.src_area), lv_area_get_height(&tileBlit.src_area),
lv_area_get_width(&tileBlit.dst_area), lv_area_get_height(&tileBlit.dst_area),
(uintptr_t) tileBlit.src, (uintptr_t) tileBlit.dst,
rv == LV_RES_OK ? "OK!" : "!!! FAILED !!!");
/* Set scissor */
lv_vglite_set_scissor(&tile_dest_area);
if(rv != LV_RES_OK) { /* if anything goes wrong... */
#if LV_GPU_NXP_VG_LITE_LOG_ERRORS
LV_LOG_ERROR("Split blit failed. Trying SW blit instead.");
#endif
_sw_blit(&tileBlit);
rv = LV_RES_OK; /* Don't report error, as SW BLIT was performed */
/* Set vgmatrix. */
lv_vglite_set_translation_matrix(&tile_dest_area);
/* Start blit. */
rv = lv_vglite_blit(&tile_src_area, opa);
/* Disable scissor. */
lv_vglite_disable_scissor();
VG_LITE_LOG_TRACE("Tile [%d, %d] "
"Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | "
"Size: ([%dx%d] -> [%dx%d]) | "
"Addr: (0x%x -> 0x%x) %s",
x, y,
tile_src_area.x1, tile_src_area.y1, tile_src_area.x2, tile_src_area.y2,
tile_dest_area.x1, tile_dest_area.y1, tile_dest_area.x2, tile_dest_area.y2,
lv_area_get_width(&tile_src_area), lv_area_get_height(&tile_src_area),
lv_area_get_width(&tile_dest_area), lv_area_get_height(&tile_dest_area),
(uintptr_t)tile_src_buf, (uintptr_t)tile_dest_buf,
rv == LV_RES_OK ? "OK!" : "FAILED!");
if(rv != LV_RES_OK) {
return rv;
}
}
PRINT_BLT(" \n");
}
return rv; /* should never fail */
return rv;
}
#endif /* VG_LITE_BLIT_SPLIT_ENABLED */
#endif /*VG_LITE_BLIT_SPLIT_ENABLED*/
static lv_res_t _lv_gpu_nxp_vglite_blit_single(lv_gpu_nxp_vglite_blit_info_t * blit)
static lv_res_t lv_vglite_blit(const lv_area_t * src_area, lv_opa_t opa)
{
vg_lite_buffer_t src_vgbuf, dst_vgbuf;
vg_lite_error_t err = VG_LITE_SUCCESS;
uint32_t rect[4];
vg_lite_float_t scale = 1.0;
vg_lite_buffer_t * dst_vgbuf = lv_vglite_get_dest_buf();
vg_lite_buffer_t * src_vgbuf = lv_vglite_get_src_buf();
if(blit == NULL) {
/*Wrong parameter*/
return LV_RES_INV;
}
if(blit->opa < (lv_opa_t) LV_OPA_MIN) {
return LV_RES_OK; /*Nothing to BLIT*/
}
/*Wrap src/dst buffer into VG-Lite buffer*/
if(lv_vglite_init_buf(&src_vgbuf, (uint32_t)blit->src_width, (uint32_t)blit->src_height, (uint32_t)blit->src_stride,
blit->src, true) != LV_RES_OK)
VG_LITE_RETURN_INV("Init buffer failed.");
if(lv_vglite_init_buf(&dst_vgbuf, (uint32_t)blit->dst_width, (uint32_t)blit->dst_height, (uint32_t)blit->dst_stride,
blit->dst, false) != LV_RES_OK)
VG_LITE_RETURN_INV("Init buffer failed.");
rect[0] = (uint32_t)blit->src_area.x1; /* start x */
rect[1] = (uint32_t)blit->src_area.y1; /* start y */
rect[2] = (uint32_t)blit->src_area.x2 - (uint32_t)blit->src_area.x1 + 1U; /* width */
rect[3] = (uint32_t)blit->src_area.y2 - (uint32_t)blit->src_area.y1 + 1U; /* height */
vg_lite_matrix_t matrix;
vg_lite_identity(&matrix);
vg_lite_translate((vg_lite_float_t)blit->dst_area.x1, (vg_lite_float_t)blit->dst_area.y1, &matrix);
if((blit->angle != 0) || (blit->zoom != LV_IMG_ZOOM_NONE)) {
vg_lite_translate(blit->pivot.x, blit->pivot.y, &matrix);
vg_lite_rotate(blit->angle / 10.0f, &matrix); /* angle is 1/10 degree */
scale = 1.0f * blit->zoom / LV_IMG_ZOOM_NONE;
vg_lite_scale(scale, scale, &matrix);
vg_lite_translate(0.0f - blit->pivot.x, 0.0f - blit->pivot.y, &matrix);
}
/*Clean & invalidate cache*/
lv_vglite_invalidate_cache();
uint32_t rect[] = {
(uint32_t)src_area->x1, /* start x */
(uint32_t)src_area->y1, /* start y */
(uint32_t)lv_area_get_width(src_area), /* width */
(uint32_t)lv_area_get_height(src_area) /* height */
};
uint32_t color;
vg_lite_blend_t blend;
if(blit->opa >= (lv_opa_t)LV_OPA_MAX) {
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->transparency_mode = VG_LITE_IMAGE_TRANSPARENT;
}
else {
uint32_t opa = (uint32_t)blit->opa;
if(vg_lite_query_feature(gcFEATURE_BIT_VG_PE_PREMULTIPLY)) {
color = (opa << 24) | 0x00FFFFFFU;
}
@@ -498,94 +547,62 @@ static lv_res_t _lv_gpu_nxp_vglite_blit_single(lv_gpu_nxp_vglite_blit_info_t * b
color = (opa << 24) | (opa << 16) | (opa << 8) | opa;
}
blend = VG_LITE_BLEND_SRC_OVER;
src_vgbuf.image_mode = VG_LITE_MULTIPLY_IMAGE_MODE;
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;
}
err = vg_lite_blit_rect(&dst_vgbuf, &src_vgbuf, rect, &matrix, blend, color, VG_LITE_FILTER_POINT);
err = vg_lite_blit_rect(dst_vgbuf, src_vgbuf, rect, &vgmatrix, blend, color, VG_LITE_FILTER_POINT);
VG_LITE_ERR_RETURN_INV(err, "Blit rectangle failed.");
err = vg_lite_finish();
VG_LITE_ERR_RETURN_INV(err, "Finish failed.");
if(lv_vglite_run() != LV_RES_OK)
VG_LITE_RETURN_INV("Run failed.");
return LV_RES_OK;
}
static lv_res_t check_src_alignment(const lv_color_t * src_buf, lv_coord_t src_stride)
{
/* No alignment requirement for destination pixel buffer when using mode VG_LITE_LINEAR */
/* Test for pointer alignment */
if((((uintptr_t)src_buf) % (uintptr_t)LV_ATTRIBUTE_MEM_ALIGN_SIZE) != (uintptr_t)0x0U)
VG_LITE_RETURN_INV("Src buffer ptr (0x%x) not aligned to 0x%x bytes.",
(size_t)src_buf, LV_ATTRIBUTE_MEM_ALIGN_SIZE);
/* Test for stride alignment */
if((src_stride % (lv_coord_t)LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX) != 0x0U)
VG_LITE_RETURN_INV("Src buffer stride (%d px) not aligned to %d px.",
src_stride, LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX);
return LV_RES_OK;
}
static inline void lv_vglite_set_translation_matrix(const lv_area_t * dest_area)
{
vg_lite_identity(&vgmatrix);
vg_lite_translate((vg_lite_float_t)dest_area->x1, (vg_lite_float_t)dest_area->y1, &vgmatrix);
}
static inline void lv_vglite_set_transformation_matrix(const lv_area_t * dest_area, const lv_draw_img_dsc_t * dsc)
{
lv_vglite_set_translation_matrix(dest_area);
bool has_scale = (dsc->zoom != LV_IMG_ZOOM_NONE);
bool has_rotation = (dsc->angle != 0);
vg_lite_translate(dsc->pivot.x, dsc->pivot.y, &vgmatrix);
if(has_rotation)
vg_lite_rotate(dsc->angle / 10.0f, &vgmatrix); /* angle is 1/10 degree */
if(has_scale) {
vg_lite_float_t scale = 1.0f * dsc->zoom / LV_IMG_ZOOM_NONE;
vg_lite_scale(scale, scale, &vgmatrix);
}
vg_lite_translate(0.0f - dsc->pivot.x, 0.0f - dsc->pivot.y, &vgmatrix);
}
#if VG_LITE_BLIT_SPLIT_ENABLED
static void _sw_blit(lv_gpu_nxp_vglite_blit_info_t * blit)
static void align_x(lv_area_t * area, lv_color_t ** buf)
{
int x, y;
lv_coord_t w = lv_area_get_width(&blit->src_area);
lv_coord_t h = lv_area_get_height(&blit->src_area);
int32_t srcStridePx = blit->src_stride / (int32_t)sizeof(lv_color_t);
int32_t dstStridePx = blit->dst_stride / (int32_t)sizeof(lv_color_t);
lv_color_t * src = (lv_color_t *)blit->src + blit->src_area.y1 * srcStridePx + blit->src_area.x1;
lv_color_t * dst = (lv_color_t *)blit->dst + blit->dst_area.y1 * dstStridePx + blit->dst_area.x1;
if(blit->opa >= (lv_opa_t)LV_OPA_MAX) {
/* simple copy */
for(y = 0; y < h; y++) {
lv_memcpy(dst, src, (uint32_t)w * sizeof(lv_color_t));
src += srcStridePx;
dst += dstStridePx;
}
}
else if(blit->opa >= LV_OPA_MIN) {
/* alpha blending */
for(y = 0; y < h; y++) {
for(x = 0; x < w; x++) {
dst[x] = lv_color_mix(src[x], dst[x], blit->opa);
}
src += srcStridePx;
dst += dstStridePx;
}
}
}
static lv_res_t _lv_gpu_nxp_vglite_check_blit(lv_gpu_nxp_vglite_blit_info_t * blit)
{
/* Test for minimal width */
if(lv_area_get_width(&blit->src_area) < (lv_coord_t)LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX)
VG_LITE_RETURN_INV("Src area width (%d) is smaller than required (%d).", lv_area_get_width(&blit->src_area),
LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX);
/* Test for minimal width */
if(lv_area_get_width(&blit->dst_area) < (lv_coord_t)LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX)
VG_LITE_RETURN_INV("Dest area width (%d) is smaller than required (%d).", lv_area_get_width(&blit->dst_area),
LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX);
/* Test for pointer alignment */
if((((uintptr_t) blit->src) % LV_ATTRIBUTE_MEM_ALIGN_SIZE) != 0x0)
VG_LITE_RETURN_INV("Src buffer ptr (0x%X) not aligned to %d.", (size_t) blit->src, LV_ATTRIBUTE_MEM_ALIGN_SIZE);
/* No alignment requirement for destination pixel buffer when using mode VG_LITE_LINEAR */
/* Test for stride alignment */
if((blit->src_stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * LV_COLOR_DEPTH / 8)) != 0x0)
VG_LITE_RETURN_INV("Src buffer stride (%d px) not aligned to %d px.", blit->src_stride,
LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX);
/* Test for stride alignment */
if((blit->dst_stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * LV_COLOR_DEPTH / 8)) != 0x0)
VG_LITE_RETURN_INV("Dest buffer stride (%d px) not aligned to %d px.", blit->dst_stride,
LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX);
if((lv_area_get_width(&blit->src_area) != lv_area_get_width(&blit->dst_area)) ||
(lv_area_get_height(&blit->src_area) != lv_area_get_height(&blit->dst_area)))
VG_LITE_RETURN_INV("Src and dest buffer areas are not equal.");
return LV_RES_OK;
}
static void _align_x(lv_area_t * area, lv_color_t ** buf)
{
int alignedAreaStartPx = area->x1 - (area->x1 % (LV_ATTRIBUTE_MEM_ALIGN_SIZE * 8 / LV_COLOR_DEPTH));
int alignedAreaStartPx = area->x1 - (area->x1 % (LV_ATTRIBUTE_MEM_ALIGN_SIZE / sizeof(lv_color_t)));
VG_LITE_COND_STOP(alignedAreaStartPx < 0, "Negative X alignment.");
area->x1 -= alignedAreaStartPx;
@@ -593,17 +610,17 @@ static void _align_x(lv_area_t * area, lv_color_t ** buf)
*buf += alignedAreaStartPx;
}
static void _align_y(lv_area_t * area, lv_color_t ** buf, uint32_t stridePx)
static void align_y(lv_area_t * area, lv_color_t ** buf, lv_coord_t stride)
{
int LineToAlignMem;
int alignedAreaStartPy;
/* find how many lines of pixels will respect memory alignment requirement */
if(stridePx % (uint32_t)LV_ATTRIBUTE_MEM_ALIGN_SIZE == 0U) {
if((stride % (lv_coord_t)LV_ATTRIBUTE_MEM_ALIGN_SIZE) == 0x0U) {
alignedAreaStartPy = area->y1;
}
else {
LineToAlignMem = LV_ATTRIBUTE_MEM_ALIGN_SIZE / (sizeof(lv_color_t) * LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX);
VG_LITE_COND_STOP(LV_ATTRIBUTE_MEM_ALIGN_SIZE % (sizeof(lv_color_t) * LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX),
LineToAlignMem = LV_ATTRIBUTE_MEM_ALIGN_SIZE / (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * sizeof(lv_color_t));
VG_LITE_COND_STOP(LV_ATTRIBUTE_MEM_ALIGN_SIZE % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * sizeof(lv_color_t)),
"Complex case: need gcd function.");
alignedAreaStartPy = area->y1 - (area->y1 % LineToAlignMem);
VG_LITE_COND_STOP(alignedAreaStartPy < 0, "Negative Y alignment.");
@@ -611,7 +628,7 @@ static void _align_y(lv_area_t * area, lv_color_t ** buf, uint32_t stridePx)
area->y1 -= alignedAreaStartPy;
area->y2 -= alignedAreaStartPy;
*buf += (uint32_t)alignedAreaStartPy * stridePx;
*buf += (uint32_t)(alignedAreaStartPy * stride);
}
#endif /*VG_LITE_BLIT_SPLIT_ENABLED*/

View File

@@ -6,7 +6,7 @@
/**
* MIT License
*
* Copyright 2020-2022 NXP
* Copyright 2020-2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -41,64 +41,31 @@ extern "C" {
#include "../../../lv_conf_internal.h"
#if LV_USE_GPU_NXP_VG_LITE
#include "lv_gpu_nxp_vglite.h"
#include "lv_vglite_utils.h"
/*********************
* DEFINES
*********************/
#ifndef LV_GPU_NXP_VG_LITE_FILL_SIZE_LIMIT
/** Minimum area (in pixels) to be filled by VG-Lite with 100% opacity*/
#define LV_GPU_NXP_VG_LITE_FILL_SIZE_LIMIT 5000
#endif
/**
* Enable BLIT quality degradation workaround for RT595,
* recommended for screen's dimension > 352 pixels.
*/
#define RT595_BLIT_WRKRND_ENABLED 1
#ifndef LV_GPU_NXP_VG_LITE_FILL_OPA_SIZE_LIMIT
/** Minimum area (in pixels) to be filled by VG-Lite with transparency*/
#define LV_GPU_NXP_VG_LITE_FILL_OPA_SIZE_LIMIT 5000
#endif
#ifndef LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT
/** Minimum area (in pixels) for image copy with 100% opacity to be handled by VG-Lite*/
#define LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT 5000
#endif
#ifndef LV_GPU_NXP_VG_LITE_BUFF_SYNC_BLIT_SIZE_LIMIT
/** Minimum invalidated area (in pixels) to be synchronized by VG-Lite during buffer sync */
#define LV_GPU_NXP_VG_LITE_BUFF_SYNC_BLIT_SIZE_LIMIT 5000
#endif
#ifndef LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT
/** Minimum area (in pixels) for image copy with transparency to be handled by VG-Lite*/
#define LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT 5000
/* Internal compound symbol */
#if (defined(CPU_MIMXRT595SFFOB) || defined(CPU_MIMXRT595SFFOB_cm33) || \
defined(CPU_MIMXRT595SFFOC) || defined(CPU_MIMXRT595SFFOC_cm33)) && \
RT595_BLIT_WRKRND_ENABLED
#define VG_LITE_BLIT_SPLIT_ENABLED 1
#else
#define VG_LITE_BLIT_SPLIT_ENABLED 0
#endif
/**********************
* TYPEDEFS
**********************/
/**
* BLock Image Transfer descriptor structure
*/
typedef struct {
const lv_color_t * src; /**< Source buffer pointer (must be aligned on 32 bytes)*/
lv_area_t src_area; /**< Area to be copied from source*/
lv_coord_t src_width; /**< Source buffer width*/
lv_coord_t src_height; /**< Source buffer height*/
int32_t src_stride; /**< Source buffer stride in bytes (must be aligned on 16 px)*/
const lv_color_t * dst; /**< Destination buffer pointer (must be aligned on 32 bytes)*/
lv_area_t dst_area; /**< Target area in destination buffer (must be the same as src_area)*/
lv_coord_t dst_width; /**< Destination buffer width*/
lv_coord_t dst_height; /**< Destination buffer height*/
int32_t dst_stride; /**< Destination buffer stride in bytes (must be aligned on 16 px)*/
lv_opa_t opa; /**< Opacity - alpha mix (0 = source not copied, 255 = 100% opaque)*/
uint32_t angle; /**< Rotation angle (1/10 of degree)*/
uint32_t zoom; /**< 256 = no zoom (1:1 scale ratio)*/
lv_point_t pivot; /**< The coordinates of rotation pivot in source image buffer*/
} lv_gpu_nxp_vglite_blit_info_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
@@ -106,35 +73,87 @@ typedef struct {
/**
* Fill area, with optional opacity.
*
* @param[in/out] dest_buf Destination buffer pointer (must be aligned on 32 bytes)
* @param[in] dest_width Destination buffer width in pixels (must be aligned on 16 px)
* @param[in] dest_height Destination buffer height in pixels
* @param[in] fill_area Area to be filled
* @param[in] color Fill color
* @param[in] dest_area Area with relative coordinates of destination buffer
* @param[in] color Color
* @param[in] opa Opacity (255 = full, 128 = 50% background/50% color, 0 = no fill)
*
* @retval LV_RES_OK Fill completed
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
*/
lv_res_t lv_gpu_nxp_vglite_fill(lv_color_t * dest_buf, lv_coord_t dest_width, lv_coord_t dest_height,
const lv_area_t * fill_area, lv_color_t color, lv_opa_t opa);
lv_res_t lv_gpu_nxp_vglite_fill(const lv_area_t * dest_area, lv_color_t color, lv_opa_t opa);
#if VG_LITE_BLIT_SPLIT_ENABLED
/**
* BLock Image Transfer.
* BLock Image Transfer - copy rectangular image from src_buf to dst_buf with effects.
* By default, image is copied directly, with optional opacity.
*
* @param[in/out] dest_buf Destination buffer
* @param[in] dest_area Area with relative coordinates of destination buffer
* @param[in] dest_stride Stride of destination buffer in pixels
* @param[in] src_buf Source buffer
* @param[in] src_area Source area with relative coordinates of source buffer
* @param[in] src_stride Stride of source buffer in pixels
* @param[in] opa Opacity
*
* @param[in] blit Description of the transfer
* @retval LV_RES_OK Transfer complete
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
*/
lv_res_t lv_gpu_nxp_vglite_blit(lv_gpu_nxp_vglite_blit_info_t * blit);
lv_res_t lv_gpu_nxp_vglite_blit_split(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, lv_area_t * src_area, lv_coord_t src_stride,
lv_opa_t opa);
#else
/**
* BLock Image Transfer with transformation.
* BLock Image Transfer - copy rectangular image from src_buf to dst_buf with effects.
* By default, image is copied directly, with optional opacity.
*
* @param[in] dest_stride Stride of destination buffer in pixels
* @param[in] src_buf Source buffer
* @param[in] src_area Source area with relative coordinates of source buffer
* @param[in] src_stride Stride of source buffer in pixels
* @param[in] opa Opacity
*
* @param[in] blit Description of the transfer
* @retval LV_RES_OK Transfer complete
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
*/
lv_res_t lv_gpu_nxp_vglite_blit_transform(lv_gpu_nxp_vglite_blit_info_t * blit);
lv_res_t lv_gpu_nxp_vglite_blit(const lv_area_t * dest_area,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
lv_opa_t opa);
/**
* 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 of destination buffer
* @param[in] clip_area Clip area with relative coordinates of destination buffer
* @param[in] src_buf Source buffer
* @param[in] src_area Source area with relative coordinates of source buffer
* @param[in] src_stride Stride of source buffer in pixels
* @param[in] dsc Image descriptor
*
* @retval LV_RES_OK Transfer complete
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
*/
lv_res_t lv_gpu_nxp_vglite_blit_transform(const lv_area_t * dest_area, const lv_area_t * clip_area,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
const lv_draw_img_dsc_t * dsc);
#endif /*VG_LITE_BLIT_SPLIT_ENABLED*/
/**
* BLock Image Transfer - simple copy of rectangular image from source to destination.
*
* @param[in] dest_buf Destination buffer
* @param[in] dest_area Area with relative coordinates of destination buffer
* @param[in] dest_stride Stride of destination buffer in pixels
* @param[in] src_buf Source buffer
* @param[in] src_area Source area with relative coordinates of source buffer
* @param[in] src_stride Stride of source buffer in pixels
*
* @retval LV_RES_OK Transfer complete
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
*/
lv_res_t lv_gpu_nxp_vglite_buffer_copy(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride);
/**********************
* MACROS

View File

@@ -0,0 +1,142 @@
/**
* @file lv_draw_vglite_line.c
*
*/
/**
* MIT License
*
* Copyright 2022, 2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next paragraph)
* shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_vglite_line.h"
#if LV_USE_GPU_NXP_VG_LITE
#include "lv_vglite_buf.h"
#include <math.h>
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
lv_res_t lv_gpu_nxp_vglite_draw_line(const lv_point_t * point1, const lv_point_t * point2,
const lv_area_t * clip_area, const lv_draw_line_dsc_t * dsc)
{
vg_lite_error_t err = VG_LITE_SUCCESS;
vg_lite_path_t path;
vg_lite_color_t vgcol; /* vglite takes ABGR */
vg_lite_buffer_t * vgbuf = lv_vglite_get_dest_buf();
vg_lite_cap_style_t cap_style = (dsc->round_start || dsc->round_end) ? VG_LITE_CAP_ROUND : VG_LITE_CAP_BUTT;
vg_lite_join_style_t join_style = (dsc->round_start || dsc->round_end) ? VG_LITE_JOIN_ROUND : VG_LITE_JOIN_MITER;
bool is_dashed = (dsc->dash_width && dsc->dash_gap);
vg_lite_float_t stroke_dash_pattern[2] = {0, 0};
uint32_t stroke_dash_count = 0;
vg_lite_float_t stroke_dash_phase = 0;
if(is_dashed) {
stroke_dash_pattern[0] = (vg_lite_float_t)dsc->dash_width;
stroke_dash_pattern[1] = (vg_lite_float_t)dsc->dash_gap;
stroke_dash_count = sizeof(stroke_dash_pattern) / sizeof(vg_lite_float_t);
stroke_dash_phase = (vg_lite_float_t)dsc->dash_width / 2;
}
/* Choose vglite blend mode based on given lvgl blend mode */
vg_lite_blend_t vglite_blend_mode = lv_vglite_get_blend_mode(dsc->blend_mode);
/*** Init path ***/
lv_coord_t width = dsc->width;
int32_t line_path[] = { /*VG line path*/
VLC_OP_MOVE, point1->x, point1->y,
VLC_OP_LINE, point2->x, point2->y,
VLC_OP_END
};
err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, sizeof(line_path), line_path,
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f);
VG_LITE_ERR_RETURN_INV(err, "Init path failed.");
vg_lite_matrix_t matrix;
vg_lite_identity(&matrix);
lv_color32_t col32 = { .full = lv_color_to32(dsc->color) }; /*Convert color to RGBA8888*/
vg_lite_buffer_format_t color_format = LV_COLOR_DEPTH == 16 ? VG_LITE_BGRA8888 : VG_LITE_ABGR8888;
if(lv_vglite_premult_and_swizzle(&vgcol, col32, dsc->opa, color_format) != LV_RES_OK)
VG_LITE_RETURN_INV("Premultiplication and swizzle failed.");
/*** Draw line ***/
err = vg_lite_set_draw_path_type(&path, VG_LITE_DRAW_STROKE_PATH);
VG_LITE_ERR_RETURN_INV(err, "Set draw path type failed.");
err = vg_lite_set_stroke(&path, cap_style, join_style, width, 8, stroke_dash_pattern, stroke_dash_count,
stroke_dash_phase, vgcol);
VG_LITE_ERR_RETURN_INV(err, "Set stroke failed.");
err = vg_lite_update_stroke(&path);
VG_LITE_ERR_RETURN_INV(err, "Update stroke failed.");
lv_vglite_set_scissor(clip_area);
err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, vglite_blend_mode, vgcol);
VG_LITE_ERR_RETURN_INV(err, "Draw line failed.");
if(lv_vglite_run() != LV_RES_OK)
VG_LITE_RETURN_INV("Run failed.");
lv_vglite_disable_scissor();
err = vg_lite_clear_path(&path);
VG_LITE_ERR_RETURN_INV(err, "Clear path failed.");
return LV_RES_OK;
}
/**********************
* STATIC FUNCTIONS
**********************/
#endif /*LV_USE_GPU_NXP_VG_LITE*/

View File

@@ -0,0 +1,83 @@
/**
* @file lv_draw_vglite_line.h
*
*/
/**
* MIT License
*
* Copyright 2022, 2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next paragraph)
* shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef LV_DRAW_VGLITE_LINE_H
#define LV_DRAW_VGLITE_LINE_H
#ifdef __cplusplus
extern "C"
{
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_GPU_NXP_VG_LITE
#include "lv_vglite_utils.h"
#include "../../lv_draw_line.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Draw line shape with effects
*
* @param[in] point1 Starting point with relative coordinates
* @param[in] point2 Ending point with relative coordinates
* @param[in] clip_area Clipping area with relative coordinates to dest buff
* @param[in] dsc Line description structure (width, rounded ending, opacity, ...)
*
* @retval LV_RES_OK Draw completed
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
*/
lv_res_t lv_gpu_nxp_vglite_draw_line(const lv_point_t * point1, const lv_point_t * point2,
const lv_area_t * clip_area, const lv_draw_line_dsc_t * dsc);
/**********************
* MACROS
**********************/
#endif /*LV_USE_GPU_NXP_VG_LITE*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_VGLITE_RECT_H*/

View File

@@ -6,7 +6,7 @@
/**
* MIT License
*
* Copyright 2021, 2022 NXP
* Copyright 2021-2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -34,10 +34,28 @@
#include "lv_draw_vglite_rect.h"
#if LV_USE_GPU_NXP_VG_LITE
#include "lv_vglite_buf.h"
#include <math.h>
/*********************
* DEFINES
*********************/
/*********************
* DEFINES
*********************/
/* Path data sizes for different elements */
#define CUBIC_PATH_DATA_SIZE 7 /* 1 opcode, 6 arguments */
#define LINE_PATH_DATA_SIZE 3 /* 1 opcode, 2 arguments */
#define MOVE_PATH_DATA_SIZE 3 /* 1 opcode, 2 arguments */
#define END_PATH_DATA_SIZE 1 /* 1 opcode, 0 arguments */
/* Maximum possible rectangle path size
* is in the rounded rectangle case:
* - 1 move for the path start
* - 4 cubics for the corners
* - 4 lines for the sides
* - 1 end for the path end */
#define RECT_PATH_DATA_MAX_SIZE 1 * MOVE_PATH_DATA_SIZE + 4 * CUBIC_PATH_DATA_SIZE + 4 * LINE_PATH_DATA_SIZE + 1 * END_PATH_DATA_SIZE
/**********************
* TYPEDEFS
@@ -47,6 +65,18 @@
* STATIC PROTOTYPES
**********************/
/**
* Generates path data for rectangle drawing.
*
* @param[in/out] path The path data to initialize
* @param[in/out] path_size The resulting size of the created path data
* @param[in] dsc The style descriptor for the rectangle to be drawn
* @param[in] coords The coordinates of the rectangle to be drawn
*/
static void lv_vglite_create_rect_path_data(int32_t * path_data, uint32_t * path_data_size,
lv_coord_t radius,
const lv_area_t * coords);
/**********************
* STATIC VARIABLES
**********************/
@@ -59,94 +89,37 @@
* GLOBAL FUNCTIONS
**********************/
lv_res_t lv_gpu_nxp_vglite_draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords)
lv_res_t lv_gpu_nxp_vglite_draw_bg(const lv_area_t * coords, const lv_area_t * clip_area,
const lv_draw_rect_dsc_t * dsc)
{
vg_lite_buffer_t vgbuf;
vg_lite_error_t err = VG_LITE_SUCCESS;
lv_coord_t dest_width = lv_area_get_width(draw_ctx->buf_area);
lv_coord_t dest_height = lv_area_get_height(draw_ctx->buf_area);
vg_lite_path_t path;
vg_lite_color_t vgcol; /* vglite takes ABGR */
vg_lite_matrix_t matrix;
lv_coord_t width = lv_area_get_width(coords);
lv_coord_t height = lv_area_get_height(coords);
vg_lite_linear_gradient_t gradient;
vg_lite_matrix_t * grad_matrix;
vg_lite_color_t vgcol;
lv_coord_t radius = dsc->radius;
vg_lite_buffer_t * vgbuf = lv_vglite_get_dest_buf();
if(dsc->radius < 0)
return LV_RES_INV;
/* Make areas relative to draw buffer */
lv_area_t rel_coords;
lv_area_copy(&rel_coords, coords);
lv_area_move(&rel_coords, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
lv_area_t rel_clip;
lv_area_copy(&rel_clip, draw_ctx->clip_area);
lv_area_move(&rel_clip, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
/*** Init destination buffer ***/
if(lv_vglite_init_buf(&vgbuf, (uint32_t)dest_width, (uint32_t)dest_height, (uint32_t)dest_width * sizeof(lv_color_t),
(const lv_color_t *)draw_ctx->buf, false) != LV_RES_OK)
VG_LITE_RETURN_INV("Init buffer failed.");
/*** Init path ***/
int32_t rad = dsc->radius;
if(dsc->radius == LV_RADIUS_CIRCLE) {
rad = (width > height) ? height / 2 : width / 2;
}
if((dsc->radius == LV_RADIUS_CIRCLE) && (width == height)) {
float tang = ((float)rad * BEZIER_OPTIM_CIRCLE);
int32_t cpoff = (int32_t)tang;
int32_t circle_path[] = { /*VG circle path*/
VLC_OP_MOVE, rel_coords.x1 + rad, rel_coords.y1,
VLC_OP_CUBIC_REL, cpoff, 0, rad, rad - cpoff, rad, rad, /* top-right */
VLC_OP_CUBIC_REL, 0, cpoff, cpoff - rad, rad, 0 - rad, rad, /* bottom-right */
VLC_OP_CUBIC_REL, 0 - cpoff, 0, 0 - rad, cpoff - rad, 0 - rad, 0 - rad, /* bottom-left */
VLC_OP_CUBIC_REL, 0, 0 - cpoff, rad - cpoff, 0 - rad, rad, 0 - rad, /* top-left */
VLC_OP_END
};
err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, sizeof(circle_path), circle_path,
(vg_lite_float_t) rel_clip.x1, (vg_lite_float_t) rel_clip.y1,
((vg_lite_float_t) rel_clip.x2) + 1.0f, ((vg_lite_float_t) rel_clip.y2) + 1.0f);
}
else if(dsc->radius > 0) {
float tang = ((float)rad * BEZIER_OPTIM_CIRCLE);
int32_t cpoff = (int32_t)tang;
int32_t rounded_path[] = { /*VG rounded rectangular path*/
VLC_OP_MOVE, rel_coords.x1 + rad, rel_coords.y1,
VLC_OP_LINE, rel_coords.x2 - rad + 1, rel_coords.y1, /* top */
VLC_OP_CUBIC_REL, cpoff, 0, rad, rad - cpoff, rad, rad, /* top-right */
VLC_OP_LINE, rel_coords.x2 + 1, rel_coords.y2 - rad + 1, /* right */
VLC_OP_CUBIC_REL, 0, cpoff, cpoff - rad, rad, 0 - rad, rad, /* bottom-right */
VLC_OP_LINE, rel_coords.x1 + rad, rel_coords.y2 + 1, /* bottom */
VLC_OP_CUBIC_REL, 0 - cpoff, 0, 0 - rad, cpoff - rad, 0 - rad, 0 - rad, /* bottom-left */
VLC_OP_LINE, rel_coords.x1, rel_coords.y1 + rad, /* left */
VLC_OP_CUBIC_REL, 0, 0 - cpoff, rad - cpoff, 0 - rad, rad, 0 - rad, /* top-left */
VLC_OP_END
};
err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, sizeof(rounded_path), rounded_path,
(vg_lite_float_t) rel_clip.x1, (vg_lite_float_t) rel_clip.y1,
((vg_lite_float_t) rel_clip.x2) + 1.0f, ((vg_lite_float_t) rel_clip.y2) + 1.0f);
}
else {
int32_t rect_path[] = { /*VG rectangular path*/
VLC_OP_MOVE, rel_coords.x1, rel_coords.y1,
VLC_OP_LINE, rel_coords.x2 + 1, rel_coords.y1,
VLC_OP_LINE, rel_coords.x2 + 1, rel_coords.y2 + 1,
VLC_OP_LINE, rel_coords.x1, rel_coords.y2 + 1,
VLC_OP_LINE, rel_coords.x1, rel_coords.y1,
VLC_OP_END
};
err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_LOW, sizeof(rect_path), rect_path,
(vg_lite_float_t) rel_clip.x1, (vg_lite_float_t) rel_clip.y1,
((vg_lite_float_t) rel_clip.x2) + 1.0f, ((vg_lite_float_t) rel_clip.y2) + 1.0f);
}
int32_t path_data[RECT_PATH_DATA_MAX_SIZE];
uint32_t path_data_size;
lv_vglite_create_rect_path_data(path_data, &path_data_size, radius, coords);
vg_lite_quality_t path_quality = dsc->radius > 0 ? VG_LITE_HIGH : VG_LITE_LOW;
vg_lite_path_t path;
err = vg_lite_init_path(&path, VG_LITE_S32, path_quality, path_data_size, path_data,
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f);
VG_LITE_ERR_RETURN_INV(err, "Init path failed.");
vg_lite_matrix_t matrix;
vg_lite_identity(&matrix);
vg_lite_matrix_t * grad_matrix;
vg_lite_linear_gradient_t gradient;
/*** Init Color/Gradient ***/
if(dsc->bg_grad.dir != (lv_grad_dir_t)LV_GRAD_DIR_NONE) {
uint32_t colors[2];
@@ -154,18 +127,14 @@ lv_res_t lv_gpu_nxp_vglite_draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_
lv_color32_t col32[2];
/* Gradient setup */
uint8_t cnt = MAX(dsc->bg_grad.stops_count, 2);
uint8_t cnt = LV_MAX(dsc->bg_grad.stops_count, 2);
for(uint8_t i = 0; i < cnt; i++) {
col32[i].full = lv_color_to32(dsc->bg_grad.stops[i].color); /*Convert color to RGBA8888*/
stops[i] = dsc->bg_grad.stops[i].frac;
#if LV_COLOR_DEPTH==16
colors[i] = ((uint32_t)col32[i].ch.alpha << 24) | ((uint32_t)col32[i].ch.blue << 16) |
((uint32_t)col32[i].ch.green << 8) | (uint32_t)col32[i].ch.red;
#else /*LV_COLOR_DEPTH==32*/
/* watchout: red and blue color components are inverted versus vg_lite_color_t order */
colors[i] = ((uint32_t)col32[i].ch.alpha << 24) | ((uint32_t)col32[i].ch.red << 16) |
((uint32_t)col32[i].ch.green << 8) | (uint32_t)col32[i].ch.blue;
#endif
vg_lite_buffer_format_t color_format = LV_COLOR_DEPTH == 16 ? VG_LITE_ABGR8888 : VG_LITE_ARGB8888;
if(lv_vglite_premult_and_swizzle(&colors[i], col32[i], dsc->bg_opa, color_format) != LV_RES_OK)
VG_LITE_RETURN_INV("Premultiplication and swizzle failed.");
}
lv_memset_00(&gradient, sizeof(vg_lite_linear_gradient_t));
@@ -181,7 +150,7 @@ lv_res_t lv_gpu_nxp_vglite_draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_
grad_matrix = vg_lite_get_grad_matrix(&gradient);
vg_lite_identity(grad_matrix);
vg_lite_translate((float)rel_coords.x1, (float)rel_coords.y1, grad_matrix);
vg_lite_translate((float)coords->x1, (float)coords->y1, grad_matrix);
if(dsc->bg_grad.dir == (lv_grad_dir_t)LV_GRAD_DIR_VER) {
vg_lite_scale(1.0f, (float)height / 256.0f, grad_matrix);
@@ -192,39 +161,26 @@ lv_res_t lv_gpu_nxp_vglite_draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_
}
}
lv_opa_t bg_opa = dsc->bg_opa;
lv_color32_t bg_col32 = {.full = lv_color_to32(dsc->bg_color)}; /*Convert color to RGBA8888*/
if(bg_opa <= (lv_opa_t)LV_OPA_MAX) {
/* Only pre-multiply color if hardware pre-multiplication is not present */
if(!vg_lite_query_feature(gcFEATURE_BIT_VG_PE_PREMULTIPLY)) {
bg_col32.ch.red = (uint8_t)(((uint16_t)bg_col32.ch.red * bg_opa) >> 8);
bg_col32.ch.green = (uint8_t)(((uint16_t)bg_col32.ch.green * bg_opa) >> 8);
bg_col32.ch.blue = (uint8_t)(((uint16_t)bg_col32.ch.blue * bg_opa) >> 8);
}
bg_col32.ch.alpha = bg_opa;
}
vg_lite_buffer_format_t color_format = LV_COLOR_DEPTH == 16 ? VG_LITE_BGRA8888 : VG_LITE_ABGR8888;
if(lv_vglite_premult_and_swizzle(&vgcol, bg_col32, dsc->bg_opa, color_format) != LV_RES_OK)
VG_LITE_RETURN_INV("Premultiplication and swizzle failed.");
#if LV_COLOR_DEPTH==16
vgcol = bg_col32.full;
#else /*LV_COLOR_DEPTH==32*/
vgcol = ((uint32_t)bg_col32.ch.alpha << 24) | ((uint32_t)bg_col32.ch.blue << 16) |
((uint32_t)bg_col32.ch.green << 8) | (uint32_t)bg_col32.ch.red;
#endif
/*Clean & invalidate cache*/
lv_vglite_invalidate_cache();
lv_vglite_set_scissor(clip_area);
/*** Draw rectangle ***/
if(dsc->bg_grad.dir == (lv_grad_dir_t)LV_GRAD_DIR_NONE) {
err = vg_lite_draw(&vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol);
err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol);
}
else {
err = vg_lite_draw_gradient(&vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, &gradient, VG_LITE_BLEND_SRC_OVER);
err = vg_lite_draw_gradient(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, &gradient, VG_LITE_BLEND_SRC_OVER);
}
VG_LITE_ERR_RETURN_INV(err, "Draw gradient failed.");
err = vg_lite_finish();
VG_LITE_ERR_RETURN_INV(err, "Finish failed.");
if(lv_vglite_run() != LV_RES_OK)
VG_LITE_RETURN_INV("Run failed.");
lv_vglite_disable_scissor();
err = vg_lite_clear_path(&path);
VG_LITE_ERR_RETURN_INV(err, "Clear path failed.");
@@ -237,8 +193,267 @@ lv_res_t lv_gpu_nxp_vglite_draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_
return LV_RES_OK;
}
lv_res_t lv_gpu_nxp_vglite_draw_border_generic(const lv_area_t * coords, const lv_area_t * clip_area,
const lv_draw_rect_dsc_t * dsc, bool border)
{
vg_lite_error_t err = VG_LITE_SUCCESS;
vg_lite_color_t vgcol; /* vglite takes ABGR */
lv_coord_t radius = dsc->radius;
vg_lite_buffer_t * vgbuf = lv_vglite_get_dest_buf();
if(radius < 0)
return LV_RES_INV;
if(border) {
/* Draw border - only has radius if object has radius*/
lv_coord_t border_half = (lv_coord_t)floor(dsc->border_width / 2.0f);
if(radius > border_half)
radius = radius - border_half;
}
else {
/* Draw outline - always has radius, leave the same radius in the circle case */
lv_coord_t outline_half = (lv_coord_t)ceil(dsc->outline_width / 2.0f);
if(radius < (lv_coord_t)LV_RADIUS_CIRCLE - outline_half)
radius = radius + outline_half;
}
vg_lite_cap_style_t cap_style = (radius) ? VG_LITE_CAP_ROUND : VG_LITE_CAP_BUTT;
vg_lite_join_style_t join_style = (radius) ? VG_LITE_JOIN_ROUND : VG_LITE_JOIN_MITER;
/* Choose vglite blend mode based on given lvgl blend mode */
vg_lite_blend_t vglite_blend_mode = lv_vglite_get_blend_mode(dsc->blend_mode);
/*** Init path ***/
int32_t path_data[RECT_PATH_DATA_MAX_SIZE];
uint32_t path_data_size;
lv_vglite_create_rect_path_data(path_data, &path_data_size, radius, coords);
vg_lite_quality_t path_quality = dsc->radius > 0 ? VG_LITE_HIGH : VG_LITE_LOW;
vg_lite_path_t path;
err = vg_lite_init_path(&path, VG_LITE_S32, path_quality, path_data_size, path_data,
(vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1,
((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f);
VG_LITE_ERR_RETURN_INV(err, "Init path failed.");
vg_lite_matrix_t matrix;
vg_lite_identity(&matrix);
lv_opa_t opa;
lv_color32_t col32;
lv_coord_t line_width;
if(border) {
opa = dsc->border_opa;
col32.full = lv_color_to32(dsc->border_color); /*Convert color to RGBA8888*/
line_width = dsc->border_width;
}
else {
opa = dsc->outline_opa;
col32.full = lv_color_to32(dsc->outline_color); /*Convert color to RGBA8888*/
line_width = dsc->outline_width;
}
vg_lite_buffer_format_t color_format = LV_COLOR_DEPTH == 16 ? VG_LITE_BGRA8888 : VG_LITE_ABGR8888;
if(lv_vglite_premult_and_swizzle(&vgcol, col32, opa, color_format) != LV_RES_OK)
VG_LITE_RETURN_INV("Premultiplication and swizzle failed.");
/*** Draw border ***/
err = vg_lite_set_draw_path_type(&path, VG_LITE_DRAW_STROKE_PATH);
VG_LITE_ERR_RETURN_INV(err, "Set draw path type failed.");
err = vg_lite_set_stroke(&path, cap_style, join_style, line_width, 8, NULL, 0, 0, vgcol);
VG_LITE_ERR_RETURN_INV(err, "Set stroke failed.");
err = vg_lite_update_stroke(&path);
VG_LITE_ERR_RETURN_INV(err, "Update stroke failed.");
lv_vglite_set_scissor(clip_area);
err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, vglite_blend_mode, vgcol);
VG_LITE_ERR_RETURN_INV(err, "Draw border failed.");
if(lv_vglite_run() != LV_RES_OK)
VG_LITE_RETURN_INV("Run failed.");
lv_vglite_disable_scissor();
err = vg_lite_clear_path(&path);
VG_LITE_ERR_RETURN_INV(err, "Clear path failed.");
return LV_RES_OK;
}
/**********************
* STATIC FUNCTIONS
**********************/
static void lv_vglite_create_rect_path_data(int32_t * path_data, uint32_t * path_data_size,
lv_coord_t radius,
const lv_area_t * coords)
{
lv_coord_t rect_width = lv_area_get_width(coords);
lv_coord_t rect_height = lv_area_get_height(coords);
/* Get the final radius. Can't be larger than the half of the shortest side */
int32_t shortest_side = LV_MIN(rect_width, rect_height);
int32_t final_radius = LV_MIN(radius, shortest_side / 2);
/* Path data element index */
uint8_t pidx = 0;
if((radius == (lv_coord_t)LV_RADIUS_CIRCLE) && (rect_width == rect_height)) {
/* Get the control point offset for rounded cases */
int32_t cpoff = (int32_t)((float)final_radius * BEZIER_OPTIM_CIRCLE);
/* Circle case */
/* Starting point */
path_data[pidx++] = VLC_OP_MOVE;
path_data[pidx++] = coords->x1 + final_radius;
path_data[pidx++] = coords->y1;
/* Top-right arc */
path_data[pidx++] = VLC_OP_CUBIC_REL;
path_data[pidx++] = cpoff;
path_data[pidx++] = 0;
path_data[pidx++] = final_radius;
path_data[pidx++] = final_radius - cpoff;
path_data[pidx++] = final_radius;
path_data[pidx++] = final_radius;
/* Bottom-right arc*/
path_data[pidx++] = VLC_OP_CUBIC_REL;
path_data[pidx++] = 0;
path_data[pidx++] = cpoff;
path_data[pidx++] = cpoff - final_radius;
path_data[pidx++] = final_radius;
path_data[pidx++] = 0 - final_radius;
path_data[pidx++] = final_radius;
/* Bottom-left arc */
path_data[pidx++] = VLC_OP_CUBIC_REL;
path_data[pidx++] = 0 - cpoff;
path_data[pidx++] = 0;
path_data[pidx++] = 0 - final_radius;
path_data[pidx++] = cpoff - final_radius;
path_data[pidx++] = 0 - final_radius;
path_data[pidx++] = 0 - final_radius;
/* Top-left arc*/
path_data[pidx++] = VLC_OP_CUBIC_REL;
path_data[pidx++] = 0;
path_data[pidx++] = 0 - cpoff;
path_data[pidx++] = final_radius - cpoff;
path_data[pidx++] = 0 - final_radius;
path_data[pidx++] = final_radius;
path_data[pidx++] = 0 - final_radius;
/* Ending point */
path_data[pidx++] = VLC_OP_END;
}
else if(radius > 0) {
/* Get the control point offset for rounded cases */
int32_t cpoff = (int32_t)((float)final_radius * BEZIER_OPTIM_CIRCLE);
/* Rounded rectangle case */
/* Starting point */
path_data[pidx++] = VLC_OP_MOVE;
path_data[pidx++] = coords->x1 + final_radius;
path_data[pidx++] = coords->y1;
/* Top side */
path_data[pidx++] = VLC_OP_LINE;
path_data[pidx++] = coords->x2 - final_radius + 1; // Extended for VGLite
path_data[pidx++] = coords->y1;
/* Top-right corner */
path_data[pidx++] = VLC_OP_CUBIC_REL;
path_data[pidx++] = cpoff;
path_data[pidx++] = 0;
path_data[pidx++] = final_radius;
path_data[pidx++] = final_radius - cpoff;
path_data[pidx++] = final_radius;
path_data[pidx++] = final_radius;
/* Right side */
path_data[pidx++] = VLC_OP_LINE;
path_data[pidx++] = coords->x2 + 1; // Extended for VGLite
path_data[pidx++] = coords->y2 - final_radius + 1; // Extended for VGLite
/* Bottom-right corner*/
path_data[pidx++] = VLC_OP_CUBIC_REL;
path_data[pidx++] = 0;
path_data[pidx++] = cpoff;
path_data[pidx++] = cpoff - final_radius;
path_data[pidx++] = final_radius;
path_data[pidx++] = 0 - final_radius;
path_data[pidx++] = final_radius;
/* Bottom side */
path_data[pidx++] = VLC_OP_LINE;
path_data[pidx++] = coords->x1 + final_radius;
path_data[pidx++] = coords->y2 + 1; // Extended for VGLite
/* Bottom-left corner */
path_data[pidx++] = VLC_OP_CUBIC_REL;
path_data[pidx++] = 0 - cpoff;
path_data[pidx++] = 0;
path_data[pidx++] = 0 - final_radius;
path_data[pidx++] = cpoff - final_radius;
path_data[pidx++] = 0 - final_radius;
path_data[pidx++] = 0 - final_radius;
/* Left side*/
path_data[pidx++] = VLC_OP_LINE;
path_data[pidx++] = coords->x1;
path_data[pidx++] = coords->y1 + final_radius;
/* Top-left corner */
path_data[pidx++] = VLC_OP_CUBIC_REL;
path_data[pidx++] = 0;
path_data[pidx++] = 0 - cpoff;
path_data[pidx++] = final_radius - cpoff;
path_data[pidx++] = 0 - final_radius;
path_data[pidx++] = final_radius;
path_data[pidx++] = 0 - final_radius;
/* Ending point */
path_data[pidx++] = VLC_OP_END;
}
else {
/* Non-rounded rectangle case */
/* Starting point */
path_data[pidx++] = VLC_OP_MOVE;
path_data[pidx++] = coords->x1;
path_data[pidx++] = coords->y1;
/* Top side */
path_data[pidx++] = VLC_OP_LINE;
path_data[pidx++] = coords->x2 + 1; // Extended for VGLite
path_data[pidx++] = coords->y1;
/* Right side */
path_data[pidx++] = VLC_OP_LINE;
path_data[pidx++] = coords->x2 + 1; // Extended for VGLite
path_data[pidx++] = coords->y2 + 1; // Extended for VGLite
/* Bottom side */
path_data[pidx++] = VLC_OP_LINE;
path_data[pidx++] = coords->x1;
path_data[pidx++] = coords->y2 + 1; // Extended for VGLite
/* Left side*/
path_data[pidx++] = VLC_OP_LINE;
path_data[pidx++] = coords->x1;
path_data[pidx++] = coords->y1;
/* Ending point */
path_data[pidx++] = VLC_OP_END;
}
/* Resulting path size */
*path_data_size = pidx * sizeof(int32_t);
}
#endif /*LV_USE_GPU_NXP_VG_LITE*/

View File

@@ -6,7 +6,7 @@
/**
* MIT License
*
* Copyright 2021, 2022 NXP
* Copyright 2021-2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -40,7 +40,7 @@ extern "C" {
#include "../../../lv_conf_internal.h"
#if LV_USE_GPU_NXP_VG_LITE
#include "lv_gpu_nxp_vglite.h"
#include "lv_vglite_utils.h"
#include "../../lv_draw_rect.h"
/*********************
@@ -56,13 +56,33 @@ extern "C" {
**********************/
/**
* Draw rectangle shape with effects (rounded corners, gradient)
* Draw rectangle background with effects (rounded corners, gradient)
*
* @param[in] coords Coordinates of the rectangle background (relative to dest buff)
* @param[in] clip_area Clipping area with relative coordinates to dest buff
* @param[in] dsc Description of the rectangle background
*
* @retval LV_RES_OK Draw completed
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
*
* @param draw_ctx drawing context
* @param dsc description of the rectangle
* @param coords the area where rectangle is clipped
*/
lv_res_t lv_gpu_nxp_vglite_draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords);
lv_res_t lv_gpu_nxp_vglite_draw_bg(const lv_area_t * coords, const lv_area_t * clip_area,
const lv_draw_rect_dsc_t * dsc);
/**
* Draw rectangle border/outline shape with effects (rounded corners, opacity)
*
* @param[in] coords Coordinates of the rectangle border/outline (relative to dest buff)
* @param[in] clip_area Clipping area with relative coordinates to dest buff
* @param[in] dsc Description of the rectangle border/outline
* @param[in] border True for border, False for outline
*
* @retval LV_RES_OK Draw completed
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
*
*/
lv_res_t lv_gpu_nxp_vglite_draw_border_generic(const lv_area_t * coords, const lv_area_t * clip_area,
const lv_draw_rect_dsc_t * dsc, bool border);
/**********************
* MACROS

View File

@@ -1,153 +0,0 @@
/**
* @file lv_gpu_nxp_vglite.c
*
*/
/**
* MIT License
*
* Copyright 2020-2022 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next paragraph)
* shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_gpu_nxp_vglite.h"
#if LV_USE_GPU_NXP_VG_LITE
#include "../../../core/lv_refr.h"
#if BLIT_DBG_AREAS
#include "lv_draw_vglite_blend.h"
#endif
/*********************
* DEFINES
*********************/
#if LV_COLOR_DEPTH==16
#define VG_LITE_PX_FMT VG_LITE_RGB565
#elif LV_COLOR_DEPTH==32
#define VG_LITE_PX_FMT VG_LITE_BGRA8888
#else
#error Only 16bit and 32bit color depth are supported. Set LV_COLOR_DEPTH to 16 or 32.
#endif
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
lv_res_t lv_vglite_init_buf(vg_lite_buffer_t * vgbuf, uint32_t width, uint32_t height, uint32_t stride,
const lv_color_t * ptr, bool source)
{
/*Test for memory alignment*/
if((((uintptr_t)ptr) % (uintptr_t)LV_ATTRIBUTE_MEM_ALIGN_SIZE) != (uintptr_t)0x0U)
VG_LITE_RETURN_INV("%s buffer (0x%x) not aligned to %d.", source ? "Src" : "Dest",
(size_t) ptr, LV_ATTRIBUTE_MEM_ALIGN_SIZE);
/*Test for stride alignment*/
if(source && (stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * sizeof(lv_color_t))) != 0x0U)
VG_LITE_RETURN_INV("Src buffer stride (%d bytes) not aligned to %d bytes.", stride,
LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * sizeof(lv_color_t));
vgbuf->format = VG_LITE_PX_FMT;
vgbuf->tiled = VG_LITE_LINEAR;
vgbuf->image_mode = VG_LITE_NORMAL_IMAGE_MODE;
vgbuf->transparency_mode = VG_LITE_IMAGE_OPAQUE;
vgbuf->width = (int32_t)width;
vgbuf->height = (int32_t)height;
vgbuf->stride = (int32_t)stride;
lv_memset_00(&vgbuf->yuv, sizeof(vgbuf->yuv));
vgbuf->memory = (void *)ptr;
vgbuf->address = (uint32_t)vgbuf->memory;
vgbuf->handle = NULL;
return LV_RES_OK;
}
#if BLIT_DBG_AREAS
void lv_vglite_dbg_draw_rectangle(lv_color_t * dest_buf, lv_coord_t dest_width, lv_coord_t dest_height,
lv_area_t * fill_area, lv_color_t color)
{
lv_area_t a;
/* top line */
a.x1 = fill_area->x1;
a.x2 = fill_area->x2;
a.y1 = fill_area->y1;
a.y2 = fill_area->y1;
lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER);
/* bottom line */
a.x1 = fill_area->x1;
a.x2 = fill_area->x2;
a.y1 = fill_area->y2;
a.y2 = fill_area->y2;
lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER);
/* left line */
a.x1 = fill_area->x1;
a.x2 = fill_area->x1;
a.y1 = fill_area->y1;
a.y2 = fill_area->y2;
lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER);
/* right line */
a.x1 = fill_area->x2;
a.x2 = fill_area->x2;
a.y1 = fill_area->y1;
a.y2 = fill_area->y2;
lv_gpu_nxp_vglite_fill(dest_buf, dest_width, dest_height, &a, color, LV_OPA_COVER);
}
#endif /* BLIT_DBG_AREAS */
void lv_vglite_invalidate_cache(void)
{
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
if(disp->driver->clean_dcache_cb)
disp->driver->clean_dcache_cb(disp->driver);
}
/**********************
* STATIC FUNCTIONS
**********************/
#endif /*LV_USE_GPU_NXP_VG_LITE*/

View File

@@ -0,0 +1,141 @@
/**
* @file lv_vglite_buf.c
*
*/
/**
* MIT License
*
* Copyright 2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next paragraph)
* shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_vglite_buf.h"
#if LV_USE_GPU_NXP_VG_LITE
/*********************
* DEFINES
*********************/
#if LV_COLOR_DEPTH == 16
#define VG_LITE_PX_FMT VG_LITE_RGB565
#elif LV_COLOR_DEPTH == 32
#define VG_LITE_PX_FMT VG_LITE_BGRA8888
#else
#error Only 16bit and 32bit color depth are supported. Set LV_COLOR_DEPTH to 16 or 32.
#endif
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static inline void lv_vglite_set_dest_buf(const lv_color_t * buf, const lv_area_t * area, lv_coord_t stride);
static inline void lv_vglite_set_buf_ptr(vg_lite_buffer_t * vgbuf, const lv_color_t * buf);
/**********************
* STATIC VARIABLES
**********************/
static vg_lite_buffer_t dest_vgbuf;
static vg_lite_buffer_t src_vgbuf;
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_gpu_nxp_vglite_init_buf(const lv_color_t * buf, const lv_area_t * area, lv_coord_t stride)
{
lv_vglite_set_dest_buf(buf, area, stride);
}
vg_lite_buffer_t * lv_vglite_get_dest_buf(void)
{
return &dest_vgbuf;
}
vg_lite_buffer_t * lv_vglite_get_src_buf(void)
{
return &src_vgbuf;
}
void lv_vglite_set_dest_buf_ptr(const lv_color_t * buf)
{
lv_vglite_set_buf_ptr(&dest_vgbuf, buf);
}
void lv_vglite_set_src_buf_ptr(const lv_color_t * buf)
{
lv_vglite_set_buf_ptr(&src_vgbuf, buf);
}
void lv_vglite_set_src_buf(const lv_color_t * buf, const lv_area_t * area, lv_coord_t stride)
{
if(src_vgbuf.memory != (void *)buf)
lv_vglite_set_buf(&src_vgbuf, buf, area, stride);
}
void lv_vglite_set_buf(vg_lite_buffer_t * vgbuf, const lv_color_t * buf,
const lv_area_t * area, lv_coord_t stride)
{
vgbuf->format = VG_LITE_PX_FMT;
vgbuf->tiled = VG_LITE_LINEAR;
vgbuf->image_mode = VG_LITE_NORMAL_IMAGE_MODE;
vgbuf->transparency_mode = VG_LITE_IMAGE_OPAQUE;
vgbuf->width = (int32_t)lv_area_get_width(area);
vgbuf->height = (int32_t)lv_area_get_height(area);
vgbuf->stride = (int32_t)(stride) * sizeof(lv_color_t);
lv_memset_00(&vgbuf->yuv, sizeof(vgbuf->yuv));
vgbuf->memory = (void *)buf;
vgbuf->address = (uint32_t)vgbuf->memory;
vgbuf->handle = NULL;
}
/**********************
* STATIC FUNCTIONS
**********************/
static inline void lv_vglite_set_dest_buf(const lv_color_t * buf, const lv_area_t * area, lv_coord_t stride)
{
lv_vglite_set_buf(&dest_vgbuf, buf, area, stride);
}
static inline void lv_vglite_set_buf_ptr(vg_lite_buffer_t * vgbuf, const lv_color_t * buf)
{
vgbuf->memory = (void *)buf;
vgbuf->address = (uint32_t)vgbuf->memory;
}
#endif /*LV_USE_GPU_NXP_VG_LITE*/

View File

@@ -0,0 +1,124 @@
/**
* @file lv_vglite_buf.h
*
*/
/**
* MIT License
*
* Copyright 2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next paragraph)
* shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef LV_VGLITE_BUF_H
#define LV_VGLITE_BUF_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_GPU_NXP_VG_LITE
#include "vg_lite.h"
#include "../../sw/lv_draw_sw.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Init vglite destination buffer. It will be done once per frame.
*
* @param[in] buf Destination buffer address (does not require alignment for VG_LITE_LINEAR mode)
* @param[in] area Destination buffer area (for width and height)
* @param[in] stride Stride of destination buffer
*/
void lv_gpu_nxp_vglite_init_buf(const lv_color_t * buf, const lv_area_t * area, lv_coord_t stride);
/**
* Get vglite destination buffer pointer.
*
* @retval The vglite destination buffer
*/
vg_lite_buffer_t * lv_vglite_get_dest_buf(void);
/**
* Get vglite source buffer pointer.
*
* @retval The vglite source buffer
*/
vg_lite_buffer_t * lv_vglite_get_src_buf(void);
/**
* Set vglite destination buffer address only.
*
* @param[in] buf Destination buffer address (does not require alignment for VG_LITE_LINEAR mode)
*/
void lv_vglite_set_dest_buf_ptr(const lv_color_t * buf);
/**
* Set vglite source buffer address only.
*
* @param[in] buf Source buffer address
*/
void lv_vglite_set_src_buf_ptr(const lv_color_t * buf);
/**
* Set vglite source buffer. It will be done only if buffer addreess is different.
*
* @param[in] buf Source buffer address
* @param[in] area Source buffer area (for width and height)
* @param[in] stride Stride of source buffer
*/
void lv_vglite_set_src_buf(const lv_color_t * buf, const lv_area_t * area, lv_coord_t stride);
/**
* Set vglite buffer.
*
* @param[in] vgbuf Address of the VGLite buffer object
* @param[in] buf Address of the memory for the VGLite buffer
* @param[in] area buffer area (for width and height)
* @param[in] stride buffer stride
*/
void lv_vglite_set_buf(vg_lite_buffer_t * vgbuf, const lv_color_t * buf,
const lv_area_t * area, lv_coord_t stride);
/**********************
* MACROS
**********************/
#endif /*LV_USE_GPU_NXP_VG_LITE*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_VGLITE_BUF_H*/

View File

@@ -0,0 +1,149 @@
/**
* @file lv_vglite_utils.c
*
*/
/**
* MIT License
*
* Copyright 2022, 2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next paragraph)
* shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_vglite_utils.h"
#if LV_USE_GPU_NXP_VG_LITE
#include "../../../core/lv_refr.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**
* Clean and invalidate cache.
*/
static inline void invalidate_cache(void);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
lv_res_t lv_vglite_run(void)
{
invalidate_cache();
VG_LITE_ERR_RETURN_INV(vg_lite_flush(), "Flush failed.");
return LV_RES_OK;
}
lv_res_t lv_vglite_premult_and_swizzle(vg_lite_color_t * vg_col32, lv_color32_t lv_col32, lv_opa_t opa,
vg_lite_buffer_format_t vg_col_format)
{
lv_color32_t lv_col32_premul = lv_col32;
if(opa <= (lv_opa_t)LV_OPA_MAX) {
/* Only pre-multiply color if hardware pre-multiplication is not present */
if(!vg_lite_query_feature(gcFEATURE_BIT_VG_PE_PREMULTIPLY)) {
lv_col32_premul.ch.red = (uint8_t)(((uint16_t)lv_col32.ch.red * opa) >> 8);
lv_col32_premul.ch.green = (uint8_t)(((uint16_t)lv_col32.ch.green * opa) >> 8);
lv_col32_premul.ch.blue = (uint8_t)(((uint16_t)lv_col32.ch.blue * opa) >> 8);
}
lv_col32_premul.ch.alpha = opa;
}
switch(vg_col_format) {
case VG_LITE_BGRA8888:
*vg_col32 = lv_col32_premul.full;
break;
case VG_LITE_RGBA8888:
*vg_col32 = ((uint32_t)lv_col32_premul.ch.red << 24) | ((uint32_t)lv_col32_premul.ch.green << 16) |
((uint32_t)lv_col32_premul.ch.blue << 8) | (uint32_t)lv_col32_premul.ch.alpha;
break;
case VG_LITE_ABGR8888:
*vg_col32 = ((uint32_t)lv_col32_premul.ch.alpha << 24) | ((uint32_t)lv_col32_premul.ch.blue << 16) |
((uint32_t)lv_col32_premul.ch.green << 8) | (uint32_t)lv_col32_premul.ch.red;
break;
case VG_LITE_ARGB8888:
*vg_col32 = ((uint32_t)lv_col32_premul.ch.alpha << 24) | ((uint32_t)lv_col32_premul.ch.red << 16) |
((uint32_t)lv_col32_premul.ch.green << 8) | (uint32_t)lv_col32_premul.ch.blue;
break;
default:
return LV_RES_INV;
}
return LV_RES_OK;
}
vg_lite_blend_t lv_vglite_get_blend_mode(lv_blend_mode_t lv_blend_mode)
{
vg_lite_blend_t vg_blend_mode;
switch(lv_blend_mode) {
case LV_BLEND_MODE_ADDITIVE:
vg_blend_mode = VG_LITE_BLEND_ADDITIVE;
break;
case LV_BLEND_MODE_SUBTRACTIVE:
vg_blend_mode = VG_LITE_BLEND_SUBTRACT;
break;
case LV_BLEND_MODE_MULTIPLY:
vg_blend_mode = VG_LITE_BLEND_MULTIPLY;
break;
case LV_BLEND_MODE_REPLACE:
vg_blend_mode = VG_LITE_BLEND_NONE;
break;
default:
vg_blend_mode = VG_LITE_BLEND_SRC_OVER;
break;
}
return vg_blend_mode;
}
/**********************
* STATIC FUNCTIONS
**********************/
static inline void invalidate_cache(void)
{
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
if(disp->driver->clean_dcache_cb)
disp->driver->clean_dcache_cb(disp->driver);
}
#endif /*LV_USE_GPU_NXP_VG_LITE*/

View File

@@ -1,12 +1,12 @@
/**
* @file lv_gpu_nxp_vglite.h
* @file lv_vglite_utils.h
*
*/
/**
* MIT License
*
* Copyright 2020-2022 NXP
* Copyright 2022, 2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -27,8 +27,8 @@
*
*/
#ifndef LV_GPU_NXP_VGLITE_H
#define LV_GPU_NXP_VGLITE_H
#ifndef LV_VGLITE_UTILS_H
#define LV_VGLITE_UTILS_H
#ifdef __cplusplus
extern "C" {
@@ -43,40 +43,21 @@ extern "C" {
#include "vg_lite.h"
#include "../../sw/lv_draw_sw.h"
#include "../../../misc/lv_log.h"
#include "fsl_debug_console.h"
/*********************
* DEFINES
*********************/
/** Use this symbol as limit to disable feature (value has to be larger than supported resolution) */
#define LV_GPU_NXP_VG_LITE_FEATURE_DISABLED (1920*1080+1)
/** Stride in px required by VG-Lite HW. Don't change this. */
#define LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX 16U
#ifndef LV_GPU_NXP_VG_LITE_LOG_ERRORS
/** Enable logging of VG-Lite errors (\see LV_LOG_ERROR)*/
#define LV_GPU_NXP_VG_LITE_LOG_ERRORS 1
#endif
#ifndef LV_GPU_NXP_VG_LITE_LOG_TRACES
/** Enable logging of VG-Lite errors (\see LV_LOG_ERROR)*/
/** Enable logging of VG-Lite traces (\see LV_LOG_ERROR)*/
#define LV_GPU_NXP_VG_LITE_LOG_TRACES 0
#endif
/* Draw rectangles around BLIT tiles */
#define BLIT_DBG_AREAS 0
/* Print detailed info to SDK console (NOT to LVGL log system) */
#define BLIT_DBG_VERBOSE 0
/* Verbose debug print */
#if BLIT_DBG_VERBOSE
#define PRINT_BLT PRINTF
#else
#define PRINT_BLT(...)
#endif
/* The optimal Bezier control point offset for radial unit
* see: https://spencermortensen.com/articles/bezier-circle/
@@ -90,41 +71,57 @@ extern "C" {
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**
* Enable scissor and set the clipping box.
*
* @param[in] clip_area Clip area with relative coordinates of destination buffer
*/
static inline void lv_vglite_set_scissor(const lv_area_t * clip_area);
/**
* Disable scissor.
*/
static inline void lv_vglite_disable_scissor(void);
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Fills vg_lite_buffer_t structure according given parameters.
* Premultiplies and swizzles given LVGL 32bit color to obtain vglite color.
*
* @param[in/out] vgbuf Buffer structure to be filled
* @param[in] width Width of buffer in pixels
* @param[in] height Height of buffer in pixels
* @param[in] stride Stride of the buffer in bytes
* @param[in] ptr Pointer to the buffer (must be aligned according VG-Lite requirements)
* @param[in] source Boolean to check if this is a source buffer
*/
lv_res_t lv_vglite_init_buf(vg_lite_buffer_t * vgbuf, uint32_t width, uint32_t height, uint32_t stride,
const lv_color_t * ptr, bool source);
#if BLIT_DBG_AREAS
/**
* Draw a simple rectangle, 1 px line width.
* @param[in/out] vg_col32 The obtained vglite color
* @param[in] lv_col32 The initial LVGL 32bit color
* @param[in] opa The opacity to premultiply with
* @param[in] vg_col_format The format of the resulting vglite color
*
* @param dest_buf Destination buffer
* @param dest_width Destination buffer width (must be aligned on 16px)
* @param dest_height Destination buffer height
* @param fill_area Rectangle coordinates
* @param color Rectangle color
* @retval LV_RES_OK Operation completed
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
*/
void lv_vglite_dbg_draw_rectangle(lv_color_t * dest_buf, lv_coord_t dest_width, lv_coord_t dest_height,
lv_area_t * fill_area, lv_color_t color);
#endif
lv_res_t lv_vglite_premult_and_swizzle(vg_lite_color_t * vg_col32, lv_color32_t lv_col32, lv_opa_t opa,
vg_lite_buffer_format_t vg_col_format);
/**
* Clean & invalidate cache.
* Get vglite blend mode.
*
* @param[in] lv_blend_mode The LVGL blend mode
*
* @retval The vglite blend mode
*/
void lv_vglite_invalidate_cache(void);
vg_lite_blend_t lv_vglite_get_blend_mode(lv_blend_mode_t lv_blend_mode);
/**
* Clear cache and flush command to VG-Lite.
*
* @retval LV_RES_OK Run completed
* @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS)
*/
lv_res_t lv_vglite_run(void);
/**********************
* MACROS
@@ -142,7 +139,8 @@ void lv_vglite_invalidate_cache(void);
#define VG_LITE_ERR_RETURN_INV(err, fmt, ...) \
do { \
if(err != VG_LITE_SUCCESS) { \
LV_LOG_ERROR(fmt, ##__VA_ARGS__); \
LV_LOG_ERROR(fmt" (err = %d)", \
err, ##__VA_ARGS__); \
return LV_RES_INV; \
} \
} while (0)
@@ -158,7 +156,7 @@ void lv_vglite_invalidate_cache(void);
#if LV_GPU_NXP_VG_LITE_LOG_TRACES
#define VG_LITE_LOG_TRACE(fmt, ...) \
do { \
LV_LOG_ERROR(fmt, ##__VA_ARGS__); \
LV_LOG(fmt, ##__VA_ARGS__); \
} while (0)
#define VG_LITE_RETURN_INV(fmt, ...) \
@@ -176,10 +174,27 @@ void lv_vglite_invalidate_cache(void);
}while(0)
#endif /*LV_GPU_NXP_VG_LITE_LOG_TRACES*/
/**********************
* STATIC FUNCTIONS
**********************/
static inline void lv_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 lv_vglite_disable_scissor(void)
{
vg_lite_disable_scissor();
}
#endif /*LV_USE_GPU_NXP_VG_LITE*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_GPU_NXP_VGLITE_H*/
#endif /*LV_VGLITE_UTILS_H*/

View File

@@ -0,0 +1,7 @@
CSRCS += lv_gpu_d2_ra6m3.c
CSRCS += lv_gpu_d2_draw_label.c
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/renesas
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/renesas
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/renesas"

View File

@@ -0,0 +1,292 @@
/**
* @file lv_gpu_d2_draw_label.c
*
* @description HAL layer for display driver
*
*/
/*********************
* INCLUDES
*********************/
#include "../../draw/lv_draw_label.h"
#include "../../misc/lv_assert.h"
#include "../../core/lv_refr.h"
#include "lv_gpu_d2_ra6m3.h"
#if LV_USE_GPU_RA6M3_G2D
#include LV_GPU_RA6M3_G2D_INCLUDE
/**********************
* STATIC VARIABLES
**********************/
/**********************
* GLOBAL VARIABLES
**********************/
extern const uint8_t _lv_bpp1_opa_table[2];
extern const uint8_t _lv_bpp2_opa_table[4];
extern const uint8_t _lv_bpp4_opa_table[16];
extern const uint8_t _lv_bpp8_opa_table[256];
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**********************
* STATIC FUNCTIONS
**********************/
LV_ATTRIBUTE_FAST_MEM static void draw_letter_normal(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc,
const lv_point_t * pos, lv_font_glyph_dsc_t * g, const uint8_t * map_p)
{
const uint8_t * bpp_opa_table_p;
uint32_t bitmask_init;
uint32_t bitmask;
uint32_t bpp = g->bpp;
lv_opa_t opa = dsc->opa;
uint32_t shades;
if(bpp == 3) bpp = 4;
#if LV_USE_IMGFONT
if(bpp == LV_IMGFONT_BPP) { //is imgfont
lv_area_t fill_area;
fill_area.x1 = pos->x;
fill_area.y1 = pos->y;
fill_area.x2 = pos->x + g->box_w - 1;
fill_area.y2 = pos->y + g->box_h - 1;
lv_draw_img_dsc_t img_dsc;
lv_draw_img_dsc_init(&img_dsc);
img_dsc.angle = 0;
img_dsc.zoom = LV_IMG_ZOOM_NONE;
img_dsc.opa = dsc->opa;
img_dsc.blend_mode = dsc->blend_mode;
lv_draw_img(draw_ctx, &img_dsc, &fill_area, map_p);
return;
}
#endif
switch(bpp) {
case 1:
bpp_opa_table_p = _lv_bpp1_opa_table;
bitmask_init = 0x80;
shades = 2;
break;
case 2:
bpp_opa_table_p = _lv_bpp2_opa_table;
bitmask_init = 0xC0;
shades = 4;
break;
case 4:
bpp_opa_table_p = _lv_bpp4_opa_table;
bitmask_init = 0xF0;
shades = 16;
break;
case 8:
bpp_opa_table_p = _lv_bpp8_opa_table;
bitmask_init = 0xFF;
shades = 256;
break; /*No opa table, pixel value will be used directly*/
default:
LV_LOG_WARN("lv_draw_letter: invalid bpp");
return; /*Invalid bpp. Can't render the letter*/
}
static lv_opa_t opa_table[256];
static lv_opa_t prev_opa = LV_OPA_TRANSP;
static uint32_t prev_bpp = 0;
if(opa < LV_OPA_MAX) {
if(prev_opa != opa || prev_bpp != bpp) {
uint32_t i;
for(i = 0; i < shades; i++) {
opa_table[i] = bpp_opa_table_p[i] == LV_OPA_COVER ? opa : ((bpp_opa_table_p[i] * opa) >> 8);
}
}
bpp_opa_table_p = opa_table;
prev_opa = opa;
prev_bpp = bpp;
}
int32_t col, row;
int32_t box_w = g->box_w;
int32_t box_h = g->box_h;
int32_t width_bit = box_w * bpp; /*Letter width in bits*/
/*Calculate the col/row start/end on the map*/
int32_t col_start = pos->x >= draw_ctx->clip_area->x1 ? 0 : draw_ctx->clip_area->x1 - pos->x;
int32_t col_end = pos->x + box_w <= draw_ctx->clip_area->x2 ? box_w : draw_ctx->clip_area->x2 - pos->x + 1;
int32_t row_start = pos->y >= draw_ctx->clip_area->y1 ? 0 : draw_ctx->clip_area->y1 - pos->y;
int32_t row_end = pos->y + box_h <= draw_ctx->clip_area->y2 ? box_h : draw_ctx->clip_area->y2 - pos->y + 1;
/*Move on the map too*/
uint32_t bit_ofs = (row_start * width_bit) + (col_start * bpp);
map_p += bit_ofs >> 3;
uint8_t letter_px;
uint32_t col_bit;
col_bit = bit_ofs & 0x7; /*"& 0x7" equals to "% 8" just faster*/
lv_draw_sw_blend_dsc_t blend_dsc;
lv_memset_00(&blend_dsc, sizeof(blend_dsc));
blend_dsc.color = dsc->color;
blend_dsc.opa = LV_OPA_COVER;
blend_dsc.blend_mode = dsc->blend_mode;
lv_coord_t hor_res = lv_disp_get_hor_res(_lv_refr_get_disp_refreshing());
uint32_t mask_buf_size = box_w * box_h > hor_res ? hor_res : box_w * box_h;
lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size);
blend_dsc.mask_buf = mask_buf;
int32_t mask_p = 0;
lv_area_t fill_area;
fill_area.x1 = col_start + pos->x;
fill_area.x2 = col_end + pos->x - 1;
fill_area.y1 = row_start + pos->y;
fill_area.y2 = fill_area.y1;
#if LV_DRAW_COMPLEX
lv_coord_t fill_w = lv_area_get_width(&fill_area);
lv_area_t mask_area;
lv_area_copy(&mask_area, &fill_area);
mask_area.y2 = mask_area.y1 + row_end;
bool mask_any = lv_draw_mask_is_any(&mask_area);
#endif
blend_dsc.blend_area = &fill_area;
blend_dsc.mask_area = &fill_area;
uint32_t col_bit_max = 8 - bpp;
uint32_t col_bit_row_ofs = (box_w + col_start - col_end) * bpp;
for(row = row_start ; row < row_end; row++) {
#if LV_DRAW_COMPLEX
int32_t mask_p_start = mask_p;
#endif
bitmask = bitmask_init >> col_bit;
for(col = col_start; col < col_end; col++) {
/*Load the pixel's opacity into the mask*/
letter_px = (*map_p & bitmask) >> (col_bit_max - col_bit);
if(letter_px) {
mask_buf[mask_p] = bpp_opa_table_p[letter_px];
}
else {
mask_buf[mask_p] = 0;
}
/*Go to the next column*/
if(col_bit < col_bit_max) {
col_bit += bpp;
bitmask = bitmask >> bpp;
}
else {
col_bit = 0;
bitmask = bitmask_init;
map_p++;
}
/*Next mask byte*/
mask_p++;
}
#if LV_DRAW_COMPLEX
/*Apply masks if any*/
if(mask_any) {
blend_dsc.mask_res = lv_draw_mask_apply(mask_buf + mask_p_start, fill_area.x1, fill_area.y2,
fill_w);
if(blend_dsc.mask_res == LV_DRAW_MASK_RES_TRANSP) {
lv_memset_00(mask_buf + mask_p_start, fill_w);
}
}
#endif
if((uint32_t) mask_p + (col_end - col_start) < mask_buf_size) {
fill_area.y2 ++;
}
else {
blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED;
lv_draw_ra6m3_2d_blend(draw_ctx, &blend_dsc);
fill_area.y1 = fill_area.y2 + 1;
fill_area.y2 = fill_area.y1;
mask_p = 0;
}
col_bit += col_bit_row_ofs;
map_p += (col_bit >> 3);
col_bit = col_bit & 0x7;
}
/*Flush the last part*/
if(fill_area.y1 != fill_area.y2) {
fill_area.y2--;
blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED;
lv_draw_ra6m3_2d_blend(draw_ctx, &blend_dsc);
mask_p = 0;
}
lv_mem_buf_release(mask_buf);
}
void lv_draw_gpu_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p,
uint32_t letter)
{
const lv_font_t * font_p = dsc->font;
lv_opa_t opa = dsc->opa;
if(opa < LV_OPA_MIN) return;
if(opa > LV_OPA_MAX) opa = LV_OPA_COVER;
if(font_p == NULL) {
LV_LOG_WARN("lv_draw_letter: font is NULL");
return;
}
lv_font_glyph_dsc_t g;
bool g_ret = lv_font_get_glyph_dsc(font_p, &g, letter, '\0');
if(g_ret == false) {
/*Add warning if the dsc is not found
*but do not print warning for non printable ASCII chars (e.g. '\n')*/
if(letter >= 0x20 &&
letter != 0xf8ff && /*LV_SYMBOL_DUMMY*/
letter != 0x200c) { /*ZERO WIDTH NON-JOINER*/
LV_LOG_WARN("lv_draw_letter: glyph dsc. not found for U+%X", letter);
}
return;
}
/*Don't draw anything if the character is empty. E.g. space*/
if((g.box_h == 0) || (g.box_w == 0)) return;
lv_point_t gpos;
gpos.x = pos_p->x + g.ofs_x;
gpos.y = pos_p->y + (dsc->font->line_height - dsc->font->base_line) - g.box_h - g.ofs_y;
/*If the letter is completely out of mask don't draw it*/
if(gpos.x + g.box_w < draw_ctx->clip_area->x1 ||
gpos.x > draw_ctx->clip_area->x2 ||
gpos.y + g.box_h < draw_ctx->clip_area->y1 ||
gpos.y > draw_ctx->clip_area->y2) {
return;
}
const uint8_t * map_p = lv_font_get_glyph_bitmap(font_p, letter);
if(map_p == NULL) {
LV_LOG_WARN("lv_draw_letter: character's bitmap not found");
return;
}
if(font_p->subpx) {
#if LV_DRAW_COMPLEX && LV_USE_FONT_SUBPX
draw_letter_subpx(pos_x, pos_y, &g, clip_area, map_p, color, opa, blend_mode);
#else
LV_LOG_WARN("Can't draw sub-pixel rendered letter because LV_USE_FONT_SUBPX == 0 in lv_conf.h");
#endif
}
else {
draw_letter_normal(draw_ctx, dsc, &gpos, &g, map_p);
}
}
#endif

View File

@@ -0,0 +1,742 @@
/**
* @file lv_gpu_d2_ra6m3.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_gpu_d2_ra6m3.h"
#include "../../core/lv_refr.h"
#include <math.h>
#if LV_USE_GPU_RA6M3_G2D
#include LV_GPU_RA6M3_G2D_INCLUDE
/*********************
* DEFINES
*********************/
#define LOG_ERRORS
#ifdef LOG_ERRORS
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define ERROR_LIST_SIZE (4)
#define D2_EXEC(a) lv_port_gpu_log_error(a, __func__, __LINE__)
#else
/* here is error logging not enabled */
#define D2_EXEC(a) a;
#endif
/**********************
* TYPEDEFS
**********************/
typedef struct {
d2_s32 error;
const char * func;
int line;
} log_error_entry;
/**********************
* STATIC PROTOTYPES
**********************/
#ifdef LOG_ERRORS
static void lv_port_gpu_log_error(d2_s32 status, const char * func, int line);
#endif
static void invalidate_cache(void);
void lv_draw_gpu_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p,
uint32_t letter);
/**********************
* STATIC VARIABLES
**********************/
#ifdef LOG_ERRORS
static log_error_entry log_error_list[ERROR_LIST_SIZE];
static int error_list_index;
static int error_count;
#endif
static d2_device * _d2_handle;
static d2_renderbuffer * renderbuffer;
static d2_s32 src_cf_val, dst_cf_val;
static lv_draw_img_dsc_t img_dsc;
static bool color_key_enabled, alpha_enabled, blend_enabled, colorize_enabled;
/**********************
* STATIC FUNCTIONS
**********************/
static d2_s32 lv_port_gpu_cf_lv_to_d2(lv_img_cf_t cf)
{
d2_s32 d2_cf;
#if (DLG_LVGL_CF == 1)
switch(cf & ~(1 << 5)) {
#else
switch(cf) {
#endif /* (DLG_LVGL_CF == 1) */
case LV_IMG_CF_TRUE_COLOR:
d2_cf = d2_mode_rgb565;
break;
case LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED:
d2_cf = d2_mode_rgb565;
break;
case LV_IMG_CF_ALPHA_1BIT:
d2_cf = d2_mode_alpha1;
break;
case LV_IMG_CF_ALPHA_2BIT:
d2_cf = d2_mode_alpha2;
break;
case LV_IMG_CF_ALPHA_4BIT:
d2_cf = d2_mode_alpha4;
break;
case LV_IMG_CF_ALPHA_8BIT:
d2_cf = d2_mode_alpha8;
break;
case LV_IMG_CF_INDEXED_1BIT:
d2_cf = d2_mode_i1 | d2_mode_clut;
break;
case LV_IMG_CF_INDEXED_2BIT:
d2_cf = d2_mode_i2 | d2_mode_clut;
break;
case LV_IMG_CF_INDEXED_4BIT:
d2_cf = d2_mode_i4 | d2_mode_clut;
break;
case LV_IMG_CF_INDEXED_8BIT:
d2_cf = d2_mode_i8 | d2_mode_clut;
break;
#if (DLG_LVGL_CF == 1)
case LV_IMG_CF_RGB565:
d2_cf = d2_mode_rgb565;
break;
case LV_IMG_CF_RGB888:
d2_cf = d2_mode_rgb888;
break;
case LV_IMG_CF_RGBA8888:
d2_cf = d2_mode_rgba8888;
break;
#endif /* DLG_LVGL_CF */
default:
return -1;
}
#if (DLG_LVGL_CF == 1)
return d2_cf | (cf & (1 << 5) ? d2_mode_rle : 0);
#else
return d2_cf;
#endif /* (DLG_LVGL_CF == 1) */
}
static bool lv_port_gpu_cf_fb_valid(d2_s32 cf)
{
if((cf & (d2_mode_rle | d2_mode_clut)) || cf < 0) {
return false;
}
switch(cf) {
case d2_mode_alpha8:
case d2_mode_rgb565:
case d2_mode_argb8888:
case d2_mode_argb4444:
case d2_mode_rgba8888:
case d2_mode_rgba4444:
return true;
default:
return false;
}
}
static bool lv_port_gpu_cf_has_alpha(d2_s32 cf)
{
switch(cf & ~(d2_mode_clut | d2_mode_rle)) {
case d2_mode_argb8888:
case d2_mode_rgba8888:
case d2_mode_argb4444:
case d2_mode_rgba4444:
case d2_mode_argb1555:
case d2_mode_rgba5551:
case d2_mode_ai44:
case d2_mode_i8:
case d2_mode_i4:
case d2_mode_i2:
case d2_mode_i1:
case d2_mode_alpha8:
case d2_mode_alpha4:
case d2_mode_alpha2:
case d2_mode_alpha1:
return true;
default:
return false;
}
}
static bool lv_port_gpu_cf_is_alpha(d2_s32 cf)
{
switch(cf & ~d2_mode_rle) {
case d2_mode_alpha8:
case d2_mode_alpha4:
case d2_mode_alpha2:
case d2_mode_alpha1:
return true;
default:
return false;
}
}
static d2_color lv_port_gpu_color_lv_to_d2(lv_color_t color)
{
uint8_t alpha, red, green, blue;
alpha = 0xFF;
red = color.ch.red << 3 | color.ch.red >> 2;
green = color.ch.green << 2 | color.ch.green >> 4;
blue = color.ch.blue << 3 | color.ch.blue >> 2;
return (alpha) << 24UL
| (red) << 16UL
| (green) << 8UL
| (blue) << 0UL;
}
static void lv_port_gpu_get_recolor_consts(d2_color * cl, d2_color * ch)
{
d2_color c = lv_port_gpu_color_lv_to_d2(img_dsc.recolor);
d2_alpha r, g, b, opa = img_dsc.recolor_opa > LV_OPA_MAX ? LV_OPA_COVER : img_dsc.recolor_opa;
r = ((uint32_t)((uint8_t)(c >> 16UL)) * opa) / 255;
g = ((uint32_t)((uint8_t)(c >> 8UL)) * opa) / 255;
b = ((uint32_t)((uint8_t)(c >> 0UL)) * opa) / 255;
*cl = r << 16UL | g << 8UL | b << 0UL;
r += 255 - opa;
g += 255 - opa;
b += 255 - opa;
*ch = r << 16UL | g << 8UL | b << 0UL;
}
static int lv_port_gpu_handle_indexed_color(const lv_color_t ** src, const d2_color ** clut, d2_s32 cf)
{
int clut_len = 0;
if(cf & d2_mode_clut) {
/* Calculate CLUT length in entries */
switch(cf & ~(d2_mode_clut | d2_mode_rle)) {
case d2_mode_i1:
clut_len = 2;
break;
case d2_mode_i2:
clut_len = 4;
break;
case d2_mode_i4:
clut_len = 16;
break;
case d2_mode_i8:
clut_len = 256;
break;
case d2_mode_ai44:
clut_len = 16;
break;
default:
return 0;
}
*clut = (const d2_color *)*src;
*src = (const lv_color_t *)((const uint32_t *)*src + clut_len);
}
return clut_len;
}
static int lv_port_gpu_cf_bpp(d2_s32 cf)
{
switch(cf & ~(d2_mode_clut | d2_mode_rle)) {
case d2_mode_argb8888:
return 32;
case d2_mode_rgba8888:
return 32;
case d2_mode_rgb888:
return 32;
case d2_mode_argb4444:
return 16;
case d2_mode_rgba4444:
return 16;
case d2_mode_argb1555:
return 16;
case d2_mode_rgba5551:
return 16;
case d2_mode_rgb565:
return 16;
case d2_mode_ai44:
return 8;
case d2_mode_i8:
return 8;
case d2_mode_i4:
return 4;
case d2_mode_i2:
return 2;
case d2_mode_i1:
return 1;
case d2_mode_alpha8:
return 8;
case d2_mode_alpha4:
return 4;
case d2_mode_alpha2:
return 2;
case d2_mode_alpha1:
return 1;
default:
return 0;
}
}
static d2_s32 lv_port_gpu_cf_get_default(void)
{
return d2_mode_rgb565;
}
static void lv_port_gpu_config_blit_clear(void)
{
alpha_enabled = false;
color_key_enabled = false;
blend_enabled = true;
colorize_enabled = false;
lv_draw_img_dsc_init(&img_dsc);
src_cf_val = lv_port_gpu_cf_get_default();
dst_cf_val = lv_port_gpu_cf_get_default();
}
void lv_port_gpu_init(void)
{
lv_port_gpu_config_blit_clear();
}
static void lv_port_gpu_rotate_point(int * x, int * y, float cos_angle, float sin_angle, int pivot_x, int pivot_y)
{
float fx, fy;
*x -= pivot_x;
*y -= pivot_y;
fx = ((float) * x) / 16.0f;
fy = ((float) * y) / 16.0f;
*x = (int)(((fx * cos_angle) - (fy * sin_angle)) * 16.0f);
*y = (int)(((fx * sin_angle) + (fy * cos_angle)) * 16.0f);
*x += pivot_x;
*y += pivot_y;
}
void lv_draw_ra6m3_g2d_init(void)
{
if(_d2_handle != NULL) {
return;
}
_d2_handle = d2_opendevice(0);
if(_d2_handle == NULL)
return;
/* set blocksize for default displaylist */
if(d2_setdlistblocksize(_d2_handle, 25) != D2_OK) {
LV_LOG_ERROR("Could NOT d2_setdlistblocksize\n");
d2_closedevice(_d2_handle);
return;
}
/* bind the hardware */
if(d2_inithw(_d2_handle, 0) != D2_OK) {
LV_LOG_ERROR("Could NOT d2_inithw\n");
d2_closedevice(_d2_handle);
return;
}
renderbuffer = d2_newrenderbuffer(_d2_handle, 20, 20);
if(!renderbuffer) {
LV_LOG_ERROR("NO renderbuffer\n");
d2_closedevice(_d2_handle);
return;
}
}
static void lv_port_gpu_hw_deinit(void)
{
if(_d2_handle == NULL)
return;
D2_EXEC(d2_freerenderbuffer(_d2_handle, renderbuffer));
D2_EXEC(d2_closedevice(_d2_handle));
renderbuffer = NULL;
_d2_handle = NULL;
}
void lv_port_gpu_flush(void)
{
lv_port_gpu_hw_deinit();
}
static void lv_port_gpu_start_render(void)
{
D2_EXEC(d2_selectrenderbuffer(_d2_handle, renderbuffer));
}
static void lv_port_gpu_complete_render(void)
{
D2_EXEC(d2_flushframe(_d2_handle));
}
void lv_port_gpu_wait(lv_draw_ctx_t * draw_ctx)
{
lv_port_gpu_complete_render();
lv_draw_sw_wait_for_finish(draw_ctx);
}
static void lv_port_gpu_execute_render(void)
{
if(_d2_handle) {
D2_EXEC(d2_executerenderbuffer(_d2_handle, renderbuffer, 0));
}
}
void lv_port_gpu_blit(int32_t x, int32_t y, lv_color_t * dst, const lv_area_t * fill_area)
{
uint32_t ModeSrc;
ModeSrc = d2_mode_rgb565;
lv_coord_t dst_width, dst_hight;
dst_width = lv_area_get_width(fill_area);
dst_hight = lv_area_get_height(fill_area);
d2_selectrenderbuffer(_d2_handle, renderbuffer);
// Generate render operations
d2_framebuffer(_d2_handle, (uint16_t *)&fb_background[0], LV_HOR_RES_MAX, LV_HOR_RES_MAX,
MAX(fill_area->y2 + 1, 2), lv_port_gpu_cf_get_default());
d2_cliprect(_d2_handle, 0, 0, LV_HOR_RES_MAX - 1, fill_area->y2);
d2_setblitsrc(_d2_handle, (void *) dst, dst_width, dst_width, dst_hight, ModeSrc);
d2_blitcopy(_d2_handle, dst_width, dst_hight, 0, 0, D2_FIX4(dst_width), D2_FIX4(dst_hight),
D2_FIX4(fill_area->x1), D2_FIX4(fill_area->y1), 0);
// Execute render operations
d2_executerenderbuffer(_d2_handle, renderbuffer, 0);
}
void lv_port_gpu_fill(lv_color_t * dest_buf, const lv_area_t * fill_area, lv_coord_t dst_width,
lv_color_t color, lv_opa_t opa)
{
invalidate_cache();
lv_port_gpu_start_render();
D2_EXEC(d2_framebuffer(_d2_handle, d1_maptovidmem(_d2_handle, dest_buf), MAX(dst_width, 2), MAX(dst_width, 2),
MAX(fill_area->y2 + 1, 2), lv_port_gpu_cf_get_default()));
D2_EXEC(d2_cliprect(_d2_handle, 0, 0, dst_width - 1, fill_area->y2));
D2_EXEC(d2_setalpha(_d2_handle, opa > LV_OPA_MAX ? 0xFF : opa));
D2_EXEC(d2_setcolor(_d2_handle, 0, lv_port_gpu_color_lv_to_d2(color)));
D2_EXEC(d2_renderbox(_d2_handle, D2_FIX4(fill_area->x1), D2_FIX4(fill_area->y1),
D2_FIX4(lv_area_get_width(fill_area)), D2_FIX4(lv_area_get_height(fill_area))));
lv_port_gpu_execute_render();
}
bool lv_port_gpu_config_blit(const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t dst_cf,
lv_img_cf_t src_cf, bool alpha_en, bool color_key_en, bool blend_en, bool colorize_en)
{
d2_s32 d2_src_cf, d2_dst_cf;
if(blend_en && draw_dsc->blend_mode != LV_BLEND_MODE_NORMAL
&& draw_dsc->blend_mode != LV_BLEND_MODE_ADDITIVE) {
return false;
}
d2_src_cf = lv_port_gpu_cf_lv_to_d2(src_cf);
d2_dst_cf = lv_port_gpu_cf_lv_to_d2(dst_cf);
if(d2_src_cf < 0 || !lv_port_gpu_cf_fb_valid(d2_dst_cf)) {
return false;
}
src_cf_val = d2_src_cf;
dst_cf_val = d2_dst_cf;
img_dsc = *draw_dsc;
/* Disable alpha if alpha channel does not exist */
alpha_enabled = lv_port_gpu_cf_has_alpha(src_cf_val) ? alpha_en : 0;
color_key_enabled = color_key_en;
blend_enabled = blend_en;
colorize_enabled = colorize_en | lv_port_gpu_cf_is_alpha(src_cf_val);
return true;
}
static void lv_port_gpu_blit_internal(const lv_area_t * dest_area, const lv_color_t * src_buf,
const lv_area_t * src_area, d2_u32 flags)
{
const lv_area_t * img_area = src_area;
lv_area_t img_area_scaled;
lv_coord_t w, h, img_w, img_h;
d2_s32 pitch;
int bpp = lv_port_gpu_cf_bpp(src_cf_val);
D2_EXEC(d2_cliprect(_d2_handle, dest_area->x1, dest_area->y1, dest_area->x2, dest_area->y2));
pitch = w = lv_area_get_width(src_area);
h = lv_area_get_height(src_area);
if(img_dsc.zoom != LV_IMG_ZOOM_NONE) {
img_area_scaled.x1 = src_area->x1 + ((((int32_t)0 - img_dsc.pivot.x) * img_dsc.zoom) >> 8) + img_dsc.pivot.x;
img_area_scaled.x2 = src_area->x1 + ((((int32_t)w - img_dsc.pivot.x) * img_dsc.zoom) >> 8) + img_dsc.pivot.x;
img_area_scaled.y1 = src_area->y1 + ((((int32_t)0 - img_dsc.pivot.y) * img_dsc.zoom) >> 8) + img_dsc.pivot.y;
img_area_scaled.y2 = src_area->y1 + ((((int32_t)h - img_dsc.pivot.y) * img_dsc.zoom) >> 8) + img_dsc.pivot.y;
img_area = &img_area_scaled;
}
img_w = lv_area_get_width(img_area);
img_h = lv_area_get_height(img_area);
if(0 < bpp && bpp < 8) {
pitch = (w + (8 - bpp)) & (~(8 - bpp));
}
if(img_dsc.angle == 0) {
D2_EXEC(d2_setblitsrc(_d2_handle, (void *) src_buf, pitch, w, h, src_cf_val));
D2_EXEC(d2_blitcopy(_d2_handle, w, h, 0, 0,
D2_FIX4(img_w), D2_FIX4(img_h), D2_FIX4(img_area->x1), D2_FIX4(img_area->y1), flags));
}
else {
int x, y, x1, y1, x2, y2, x3, y3, x4, y4, dxu, dxv, dyu, dyv, xx, xy, yx, yy;
int pivot_scaled_x, pivot_scaled_y;
int tex_offset = (flags & d2_bf_filter) ? -32767 : 0;
d2_u8 amode, cmode = d2_to_copy;
float angle = ((float)img_dsc.angle / 10) * M_PI / 180;
float cos_angle = cosf(angle);
float sin_angle = sinf(angle);
d2_u8 fillmode_backup;
/* setup texture params */
fillmode_backup = d2_getfillmode(_d2_handle);
D2_EXEC(d2_setfillmode(_d2_handle, d2_fm_texture));
D2_EXEC(d2_settexture(_d2_handle, (void *) src_buf, pitch, w, h, src_cf_val));
D2_EXEC(d2_settexturemode(_d2_handle, flags & (d2_bf_filter | d2_bf_wrap)));
amode = flags & d2_bf_usealpha ? d2_to_copy : d2_to_one;
cmode = flags & d2_bf_colorize2 ? d2_to_blend : d2_to_copy;
D2_EXEC(d2_settextureoperation(_d2_handle, amode, cmode, cmode, cmode));
if(flags & d2_bf_colorize2) {
d2_color cl = d2_getcolor(_d2_handle, 0), ch = d2_getcolor(_d2_handle, 1);
D2_EXEC(d2_settexopparam(_d2_handle, d2_cc_red, (uint8_t)(cl >> 16UL),
(uint8_t)(ch >> 16UL)));
D2_EXEC(d2_settexopparam(_d2_handle, d2_cc_green, (uint8_t)(cl >> 8UL),
(uint8_t)(ch >> 8UL)));
D2_EXEC(d2_settexopparam(_d2_handle, d2_cc_blue, (uint8_t)(cl >> 0UL),
(uint8_t)(ch >> 0UL)));
}
x = D2_FIX4(img_area->x1);
y = D2_FIX4(img_area->y1);
/* define quad points */
x1 = D2_FIX4(0);
y1 = D2_FIX4(0);
x2 = D2_FIX4(img_w);
y2 = D2_FIX4(0);
x3 = D2_FIX4(img_w);
y3 = D2_FIX4(img_h);
x4 = D2_FIX4(0);
y4 = D2_FIX4(img_h);
/* rotate points for quad */
pivot_scaled_x = (img_dsc.pivot.x * img_dsc.zoom) >> 4;
pivot_scaled_y = (img_dsc.pivot.y * img_dsc.zoom) >> 4;
lv_port_gpu_rotate_point(&x1, &y1, cos_angle, sin_angle, pivot_scaled_x, pivot_scaled_y);
lv_port_gpu_rotate_point(&x2, &y2, cos_angle, sin_angle, pivot_scaled_x, pivot_scaled_y);
lv_port_gpu_rotate_point(&x3, &y3, cos_angle, sin_angle, pivot_scaled_x, pivot_scaled_y);
lv_port_gpu_rotate_point(&x4, &y4, cos_angle, sin_angle, pivot_scaled_x, pivot_scaled_y);
/* compute texture increments */
xx = (int)(cos_angle * 65536.0f);
xy = (int)(sin_angle * 65536.0f);
yx = (int)(-sin_angle * 65536.0f);
yy = (int)(cos_angle * 65536.0f);
dxu = ((D2_FIX16(w) / D2_FIX4(img_w)) * xx) >> 12;
dxv = ((D2_FIX16(w) / D2_FIX4(img_w)) * xy) >> 12;
dyu = ((D2_FIX16(h) / D2_FIX4(img_h)) * yx) >> 12;
dyv = ((D2_FIX16(h) / D2_FIX4(img_h)) * yy) >> 12;
/* map texture exactly to rotated quad, so texel center is always (0/0) top-left */
D2_EXEC(d2_settexelcenter(_d2_handle, 0, 0));
D2_EXEC(d2_settexturemapping(_d2_handle, (d2_point)(x + x1), (d2_point)(y + y1),
tex_offset, tex_offset, dxu, dxv, dyu, dyv));
int minx = MAX(dest_area->x1, D2_INT4(x + MIN(x1, MIN(x2, MIN(x3, x4)))));
int maxx = MIN(dest_area->x2, D2_INT4(x + MAX(x1, MAX(x2, MAX(x3, x4)))));
int slice = (flags & d2_bf_filter) ? 6 : 8;
/* Perform render operation in slices to acheive better performance */
for(int posx = minx; posx < maxx; posx += slice) {
D2_EXEC(d2_cliprect(_d2_handle, posx, dest_area->y1, MIN(posx + slice - 1, maxx), dest_area->y2));
D2_EXEC(d2_renderquad(_d2_handle, (d2_point)(x + x1), (d2_point)(y + y1),
(d2_point)(x + x2), (d2_point)(y + y2),
(d2_point)(x + x3), (d2_point)(y + y3),
(d2_point)(x + x4), (d2_point)(y + y4), 0));
}
D2_EXEC(d2_setfillmode(_d2_handle, fillmode_backup));
}
}
void lv_port_ra_gpu_blit(lv_color_t * dst, const lv_area_t * dst_area, lv_coord_t dest_stride,
const lv_color_t * src, const lv_area_t * src_area, lv_opa_t opa)
{
d2_u32 flags = 0;
const d2_color * clut = NULL;
int clut_len = 0;
invalidate_cache();
clut_len = lv_port_gpu_handle_indexed_color(&src, &clut, src_cf_val);
lv_port_gpu_start_render();
D2_EXEC(d2_framebuffer(_d2_handle, d1_maptovidmem(_d2_handle, dst), MAX(dest_stride, 2),
MAX(dst_area->x2 + 1, 2), MAX(dst_area->y2 + 1, 2), dst_cf_val));
flags |= alpha_enabled ? d2_bf_usealpha : 0;
D2_EXEC(d2_setalpha(_d2_handle, opa > LV_OPA_MAX ? LV_OPA_COVER : opa));
if(clut) {
D2_EXEC(d2_writetexclut_direct(_d2_handle, clut, 0, clut_len));
}
flags |= color_key_enabled ? d2_bf_usealpha : 0;
flags |= (colorize_enabled || img_dsc.recolor_opa != LV_OPA_TRANSP) ? d2_bf_colorize2 : 0;
if(colorize_enabled) {
D2_EXEC(d2_setcolor(_d2_handle, 0, lv_port_gpu_color_lv_to_d2(img_dsc.recolor)));
D2_EXEC(d2_setcolor(_d2_handle, 1, lv_port_gpu_color_lv_to_d2(img_dsc.recolor)));
}
else if(img_dsc.recolor_opa != LV_OPA_TRANSP) {
d2_color cl = 0, ch = 0;
lv_port_gpu_get_recolor_consts(&cl, &ch);
D2_EXEC(d2_setcolor(_d2_handle, 0, cl));
D2_EXEC(d2_setcolor(_d2_handle, 1, ch));
}
flags |= ((img_dsc.angle || img_dsc.zoom != LV_IMG_ZOOM_NONE) && img_dsc.antialias) ? d2_bf_filter : 0;
if(blend_enabled) {
D2_EXEC(d2_setblendmode(_d2_handle, d2_bm_alpha,
img_dsc.blend_mode != LV_BLEND_MODE_NORMAL ? d2_bm_one : d2_bm_one_minus_alpha));
D2_EXEC(d2_setalphablendmode(_d2_handle, d2_bm_one, d2_bm_one_minus_alpha));
}
else {
D2_EXEC(d2_setblendmode(_d2_handle, d2_bm_one, d2_bm_zero));
D2_EXEC(d2_setalphablendmode(_d2_handle, d2_bm_one, d2_bm_zero));
}
lv_port_gpu_blit_internal(dst_area, src, src_area, flags);
lv_port_gpu_execute_render();
}
void lv_draw_ra6m3_2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc)
{
lv_area_t blend_area;
if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area)) return;
bool done = false;
if(dsc->mask_buf == NULL && dsc->blend_mode == LV_BLEND_MODE_NORMAL && lv_area_get_size(&blend_area) > 100) {
lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area);
lv_color_t * dest_buf = draw_ctx->buf;
const lv_color_t * src_buf = dsc->src_buf;
if(src_buf) {
lv_draw_sw_blend_basic(draw_ctx, dsc);
lv_area_t src_area;
src_area.x1 = blend_area.x1 - (dsc->blend_area->x1 - draw_ctx->buf_area->x1);
src_area.y1 = blend_area.y1 - (dsc->blend_area->y1 - draw_ctx->buf_area->y1);
src_area.x2 = src_area.x1 + lv_area_get_width(dsc->blend_area) - 1;
src_area.y2 = src_area.y1 + lv_area_get_height(dsc->blend_area) - 1;
lv_port_ra_gpu_blit(dest_buf, &blend_area, dest_stride, src_buf, &src_area, dsc->opa);
done = true;
}
else if(dsc->opa >= LV_OPA_MAX) {
lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
lv_port_gpu_fill(dest_buf, &blend_area, dest_stride, dsc->color, dsc->opa);
done = true;
}
}
if(!done) lv_draw_sw_blend_basic(draw_ctx, dsc);
}
static void lv_port_gpu_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc,
const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t color_format)
{
/*TODO basic ARGB8888 image can be handles here*/
lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, color_format);
}
void lv_draw_ra6m3_2d_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
{
lv_draw_sw_init_ctx(drv, draw_ctx);
lv_draw_ra6m3_dma2d_ctx_t * ra_2d_draw_ctx = (lv_draw_sw_ctx_t *)draw_ctx;
ra_2d_draw_ctx->blend = lv_draw_ra6m3_2d_blend;
ra_2d_draw_ctx->base_draw.draw_img_decoded = lv_port_gpu_img_decoded;
ra_2d_draw_ctx->base_draw.wait_for_finish = lv_port_gpu_wait;
ra_2d_draw_ctx->base_draw.draw_letter = lv_draw_gpu_letter;
//ra_2d_draw_ctx->base_draw.buffer_copy = lv_draw_ra6m3_2d_buffer_copy;
}
void lv_draw_stm32_dma2d_ctx_deinit(lv_disp_t * disp, lv_draw_ctx_t * draw_ctx)
{
LV_UNUSED(disp);
LV_UNUSED(draw_ctx);
}
static void invalidate_cache(void)
{
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
if(disp->driver->clean_dcache_cb) disp->driver->clean_dcache_cb(disp->driver);
}
#ifdef LOG_ERRORS
static void lv_port_gpu_log_error(d2_s32 status, const char * func, int line)
{
if(status) {
log_error_list[error_list_index].error = status;
log_error_list[error_list_index].func = func;
log_error_list[error_list_index].line = line;
LV_LOG_ERROR("%s\r\n", d2_geterrorstring(_d2_handle));
LV_LOG_ERROR("%d:\t%d - %s : %d\r\n", error_count,
log_error_list[error_list_index].error,
log_error_list[error_list_index].func,
log_error_list[error_list_index].line);
error_count++;
error_list_index++;
if(error_list_index >= ERROR_LIST_SIZE) {
error_list_index = 0;
}
}
}
#endif
#endif /* LV_USE_GPU_RA6M3_G2D */

View File

@@ -0,0 +1,56 @@
/**
* @file lv_gpu_d2_ra6m3.h
*
*/
#ifndef LV_GPU_D2_RA6M3_H
#define LV_GPU_D2_RA6M3_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../misc/lv_color.h"
#if LV_USE_GPU_RA6M3_G2D
#include "../../core/lv_disp.h"
#include "../sw/lv_draw_sw.h"
/**********************
* DEFINE
**********************/
#define MIN(A, B) ((A) < (B) ? (A) : (B))
#define MAX(A, B) ((A) > (B) ? (A) : (B))
#define M_PI 3.1415926
/**********************
* TYPEDEFS
**********************/
typedef lv_draw_sw_ctx_t lv_draw_ra6m3_dma2d_ctx_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_draw_ra6m3_g2d_init(void);
void lv_port_gpu_init(void);
void lv_port_gpu_flush(void);
void lv_port_gpu_blit(int32_t x, int32_t y, lv_color_t * dst, const lv_area_t * fill_area);
void lv_draw_ra6m3_2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc);
void lv_draw_ra6m3_2d_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx);
void lv_draw_ra6m3_2d_ctx_deinit(lv_disp_drv_t * disp, lv_draw_ctx_t * draw_ctx);
#endif /*LV_USE_GPU_GD32_IPA*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif

View File

@@ -104,7 +104,9 @@ void lv_draw_sdl_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * ds
}
lv_coord_t w = lv_area_get_width(&draw_area), h = lv_area_get_height(&draw_area);
SDL_Texture * texture = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM1, w, h);
bool texture_cached = false;
SDL_Texture * texture = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM1, w, h,
&texture_cached);
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
dump_masks(texture, &draw_area, mask_ids, mask_ids_count, cap_ids[0] != LV_MASK_ID_INV ? cap_ids : NULL);
@@ -135,6 +137,11 @@ void lv_draw_sdl_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * ds
SDL_SetTextureColorMod(texture, color.r, color.g, color.b);
SDL_SetTextureAlphaMod(texture, dsc->opa);
SDL_RenderCopy(ctx->renderer, texture, &srcrect, &dstrect);
if(!texture_cached) {
LV_LOG_WARN("Texture is not cached, this will impact performance.");
SDL_DestroyTexture(texture);
}
}
/**********************

View File

@@ -86,7 +86,8 @@ bool lv_draw_sdl_composite_begin(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coor
LV_ASSERT(internals->mask == NULL && internals->composition == NULL && internals->target_backup == NULL);
lv_coord_t w = lv_area_get_width(apply_area), h = lv_area_get_height(apply_area);
internals->composition = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET0, w, h);
internals->composition = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET0, w, h,
&internals->composition_cached);
/* Don't need to worry about integral overflow */
lv_coord_t ofs_x = (lv_coord_t) - apply_area->x1, ofs_y = (lv_coord_t) - apply_area->y1;
/* Offset draw area to start with (0,0) of coords */
@@ -95,7 +96,10 @@ bool lv_draw_sdl_composite_begin(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coor
internals->target_backup = SDL_GetRenderTarget(ctx->renderer);
SDL_SetRenderTarget(ctx->renderer, internals->composition);
SDL_SetRenderDrawColor(ctx->renderer, 255, 255, 255, 0);
SDL_RenderClear(ctx->renderer);
/* SDL_RenderClear is not working properly, so we overwrite the target with solid color */
SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_NONE);
SDL_RenderFillRect(ctx->renderer, NULL);
SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_BLEND);
#if LV_GPU_SDL_CUSTOM_BLEND_MODE
internals->mask = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM0, w, h);
dump_masks(internals->mask, apply_area);
@@ -171,19 +175,23 @@ void lv_draw_sdl_composite_end(lv_draw_sdl_ctx_t * ctx, const lv_area_t * apply_
break;
}
SDL_RenderCopy(ctx->renderer, internals->composition, &src_rect, &dst_rect);
if(!internals->composition_cached) {
LV_LOG_WARN("Texture is not cached, this will impact performance.");
SDL_DestroyTexture(internals->composition);
}
}
internals->mask = internals->composition = internals->target_backup = NULL;
}
SDL_Texture * lv_draw_sdl_composite_texture_obtain(lv_draw_sdl_ctx_t * ctx, lv_draw_sdl_composite_texture_id_t id,
lv_coord_t w, lv_coord_t h)
lv_coord_t w, lv_coord_t h, bool * texture_in_cache)
{
lv_point_t * tex_size = NULL;
composite_key_t mask_key = mask_key_create(id);
SDL_Texture * result = lv_draw_sdl_texture_cache_get_with_userdata(ctx, &mask_key, sizeof(composite_key_t), NULL,
(void **) &tex_size);
if(!result || tex_size->x < w || tex_size->y < h) {
if(result == NULL || tex_size->x < w || tex_size->y < h) {
lv_coord_t size = next_pow_of_2(LV_MAX(w, h));
int access = SDL_TEXTUREACCESS_STREAMING;
if(id >= LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TRANSFORM0) {
@@ -195,8 +203,19 @@ SDL_Texture * lv_draw_sdl_composite_texture_obtain(lv_draw_sdl_ctx_t * ctx, lv_d
result = SDL_CreateTexture(ctx->renderer, LV_DRAW_SDL_TEXTURE_FORMAT, access, size, size);
tex_size = lv_mem_alloc(sizeof(lv_point_t));
tex_size->x = tex_size->y = size;
lv_draw_sdl_texture_cache_put_advanced(ctx, &mask_key, sizeof(composite_key_t), result, tex_size, lv_mem_free, 0);
bool in_cache = lv_draw_sdl_texture_cache_put_advanced(ctx, &mask_key, sizeof(composite_key_t), result,
tex_size, lv_mem_free, 0);
if(!in_cache) {
lv_mem_free(tex_size);
}
if(texture_in_cache != NULL) {
*texture_in_cache = in_cache;
}
}
else if(texture_in_cache != NULL) {
*texture_in_cache = true;
}
return result;
}

View File

@@ -45,6 +45,7 @@ typedef enum lv_draw_sdl_composite_texture_id_t {
/**
* Begin drawing with mask. Render target will be switched to a temporary texture,
* and drawing coordinates may get clipped or translated
* @param ctx Drawing context
* @param coords_in Original coordinates
* @param clip_in Original clip area
* @param extension Useful for shadows or outlines, can be NULL
@@ -59,8 +60,18 @@ bool lv_draw_sdl_composite_begin(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coor
void lv_draw_sdl_composite_end(lv_draw_sdl_ctx_t * ctx, const lv_area_t * apply_area, lv_blend_mode_t blend_mode);
/**
*
* @param ctx Drawing context
* @param id Texture ID
* @param w Maximum width needed
* @param h Maximum height needed
* @param texture_in_cache output to query if the texture is in cache. If it's not in cache, you'll need to destroy it
* by yourself
* @return Obtained texture
*/
SDL_Texture * lv_draw_sdl_composite_texture_obtain(lv_draw_sdl_ctx_t * ctx, lv_draw_sdl_composite_texture_id_t id,
lv_coord_t w, lv_coord_t h);
lv_coord_t w, lv_coord_t h, bool * texture_in_cache);
/**********************
* MACROS

View File

@@ -72,7 +72,8 @@ static void draw_img_rounded(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture, con
lv_coord_t radius);
static SDL_Texture * img_rounded_frag_obtain(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture,
const lv_draw_sdl_img_header_t * header, int w, int h, lv_coord_t radius);
const lv_draw_sdl_img_header_t * header, int w, int h, lv_coord_t radius,
bool * in_cache);
static lv_draw_img_rounded_key_t rounded_key_create(const SDL_Texture * texture, lv_coord_t w, lv_coord_t h,
lv_coord_t radius);
@@ -106,11 +107,16 @@ lv_res_t lv_draw_sdl_img_core(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t
lv_draw_sdl_img_header_t * header = NULL;
SDL_Texture * texture = lv_draw_sdl_texture_cache_get_with_userdata(ctx, key, key_size, &texture_found,
(void **) &header);
bool texture_in_cache = false;
if(!texture_found) {
lv_draw_sdl_img_load_texture(ctx, key, key_size, src, draw_dsc->frame_id, &texture, &header);
lv_draw_sdl_img_load_texture(ctx, key, key_size, src, draw_dsc->frame_id, &texture, &header,
&texture_in_cache);
}
else {
texture_in_cache = true;
}
SDL_free(key);
if(!texture) {
if(!texture || !header) {
return LV_RES_INV;
}
@@ -148,6 +154,14 @@ lv_res_t lv_draw_sdl_img_core(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t
lv_draw_sdl_composite_end(ctx, &apply_area, draw_dsc->blend_mode);
if(!texture_in_cache) {
LV_LOG_WARN("Texture is not cached, this will impact performance.");
if(!header->managed) {
SDL_DestroyTexture(texture);
}
lv_mem_free(header);
}
return LV_RES_OK;
}
@@ -185,7 +199,7 @@ static void calc_draw_part(SDL_Texture * texture, const lv_draw_sdl_img_header_t
bool lv_draw_sdl_img_load_texture(lv_draw_sdl_ctx_t * ctx, lv_draw_sdl_cache_key_head_img_t * key, size_t key_size,
const void * src, int32_t frame_id, SDL_Texture ** texture,
lv_draw_sdl_img_header_t ** header)
lv_draw_sdl_img_header_t ** header, bool * texture_in_cache)
{
_lv_img_cache_entry_t * cdsc = _lv_img_cache_open(src, lv_color_white(), frame_id);
lv_draw_sdl_cache_flag_t tex_flags = 0;
@@ -210,16 +224,18 @@ bool lv_draw_sdl_img_load_texture(lv_draw_sdl_ctx_t * ctx, lv_draw_sdl_cache_key
#endif
}
if(texture && cdsc) {
*header = SDL_malloc(sizeof(lv_draw_sdl_img_header_t));
*header = lv_mem_alloc(sizeof(lv_draw_sdl_img_header_t));
SDL_memcpy(&(*header)->base, &cdsc->dec_dsc.header, sizeof(lv_img_header_t));
(*header)->rect = rect;
lv_draw_sdl_texture_cache_put_advanced(ctx, key, key_size, *texture, *header, SDL_free, tex_flags);
(*header)->managed = (tex_flags & LV_DRAW_SDL_CACHE_FLAG_MANAGED) != 0;
*texture_in_cache = lv_draw_sdl_texture_cache_put_advanced(ctx, key, key_size, *texture, *header, SDL_free,
tex_flags);
return true;
}
else {
lv_draw_sdl_texture_cache_put(ctx, key, key_size, NULL);
*texture_in_cache = lv_draw_sdl_texture_cache_put(ctx, key, key_size, NULL);
return false;
}
return true;
}
/**********************
@@ -320,7 +336,8 @@ static void draw_img_rounded(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture, con
{
const int w = lv_area_get_width(coords), h = lv_area_get_height(coords);
lv_coord_t real_radius = LV_MIN3(radius, w, h);
SDL_Texture * frag = img_rounded_frag_obtain(ctx, texture, header, w, h, real_radius);
bool frag_in_cache = false;
SDL_Texture * frag = img_rounded_frag_obtain(ctx, texture, header, w, h, real_radius, &frag_in_cache);
apply_recolor_opa(frag, draw_dsc);
lv_draw_sdl_rect_bg_frag_draw_corners(ctx, frag, real_radius, coords, clip, true);
@@ -360,6 +377,11 @@ static void draw_img_rounded(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture, con
SDL_RenderCopy(ctx->renderer, texture, &src_rect, &dst_rect);
}
SDL_RenderSetClipRect(ctx->renderer, NULL);
if(!frag_in_cache) {
LV_LOG_WARN("Texture is not cached, this will impact performance.");
SDL_DestroyTexture(frag);
}
}
static void apply_recolor_opa(SDL_Texture * texture, const lv_draw_img_dsc_t * draw_dsc)
@@ -377,22 +399,28 @@ static void apply_recolor_opa(SDL_Texture * texture, const lv_draw_img_dsc_t * d
}
static SDL_Texture * img_rounded_frag_obtain(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture,
const lv_draw_sdl_img_header_t * header, int w, int h, lv_coord_t radius)
const lv_draw_sdl_img_header_t * header, int w, int h, lv_coord_t radius,
bool * in_cache)
{
lv_draw_img_rounded_key_t key = rounded_key_create(texture, w, h, radius);
SDL_Texture * mask_frag = lv_draw_sdl_rect_bg_frag_obtain(ctx, radius);
bool mask_frag_in_cache = false;
SDL_Texture * mask_frag = lv_draw_sdl_rect_bg_frag_obtain(ctx, radius, &mask_frag_in_cache);
SDL_Texture * img_frag = lv_draw_sdl_texture_cache_get(ctx, &key, sizeof(key), NULL);
if(img_frag == NULL) {
const lv_coord_t full_frag_size = radius * 2 + 3;
img_frag = SDL_CreateTexture(ctx->renderer, LV_DRAW_SDL_TEXTURE_FORMAT, SDL_TEXTUREACCESS_TARGET,
full_frag_size, full_frag_size);
SDL_assert(img_frag);
SDL_SetTextureBlendMode(img_frag, SDL_BLENDMODE_BLEND);
SDL_Texture * old_target = SDL_GetRenderTarget(ctx->renderer);
SDL_SetRenderTarget(ctx->renderer, img_frag);
SDL_SetRenderDrawColor(ctx->renderer, 0, 0, 0, 0);
SDL_RenderClear(ctx->renderer);
/* SDL_RenderClear is not working properly, so we overwrite the target with solid color */
SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_NONE);
SDL_RenderFillRect(ctx->renderer, NULL);
SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_BLEND);
lv_area_t coords = {0, 0, w - 1, h - 1}, clip;
lv_area_t coords = {0, 0, w - 1, h - 1};
lv_area_t frag_coords = {0, 0, full_frag_size - 1, full_frag_size - 1};
lv_draw_sdl_rect_bg_frag_draw_corners(ctx, mask_frag, radius, &frag_coords, NULL, false);
@@ -443,7 +471,14 @@ static SDL_Texture * img_rounded_frag_obtain(lv_draw_sdl_ctx_t * ctx, SDL_Textur
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
SDL_SetRenderTarget(ctx->renderer, old_target);
lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), img_frag);
*in_cache = lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), img_frag);
}
else {
*in_cache = true;
}
if(!mask_frag_in_cache) {
LV_LOG_WARN("Texture is not cached, this will impact performance.");
SDL_DestroyTexture(mask_frag);
}
return img_frag;
}

View File

@@ -35,6 +35,7 @@ extern "C" {
typedef struct lv_draw_sdl_img_header_t {
lv_img_header_t base;
SDL_Rect rect;
bool managed;
} lv_draw_sdl_img_header_t;
/**********************
@@ -56,9 +57,22 @@ typedef struct lv_draw_sdl_img_header_t {
/*=====================
* Other functions
*====================*/
/**
*
* @param ctx Drawing context
* @param key Texture cache key
* @param key_size Size of texture cache key
* @param src Image source pointer
* @param frame_id Frame ID for animated image
* @param texture Texture for render
* @param header Header also holds sdl image info
* @param texture_in_cache Whether the texture has been put in the cache. Please note for managed texture,
* this will be false too. So you'll need to check header.managed too.
* @return Whether the image has been loaded successfully
*/
bool lv_draw_sdl_img_load_texture(lv_draw_sdl_ctx_t * ctx, lv_draw_sdl_cache_key_head_img_t * key, size_t key_size,
const void * src, int32_t frame_id, SDL_Texture ** texture,
lv_draw_sdl_img_header_t ** header);
lv_draw_sdl_img_header_t ** header, bool * texture_in_cache);
/**********************
* MACROS
**********************/

View File

@@ -54,7 +54,7 @@ static lv_font_glyph_key_t font_key_glyph_create(const lv_font_t * font_p, uint3
* GLOBAL FUNCTIONS
**********************/
void lv_draw_sdl_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p,
void lv_draw_sdl_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p,
uint32_t letter)
{
const lv_area_t * clip_area = draw_ctx->clip_area;
@@ -117,6 +117,7 @@ void lv_draw_sdl_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t
lv_font_glyph_key_t glyph_key = font_key_glyph_create(font_p, letter);
bool glyph_found = false;
SDL_Texture * texture = lv_draw_sdl_texture_cache_get(ctx, &glyph_key, sizeof(glyph_key), &glyph_found);
bool in_cache = false;
if(!glyph_found) {
if(g.resolved_font) {
font_p = g.resolved_font;
@@ -128,7 +129,10 @@ void lv_draw_sdl_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t
texture = SDL_CreateTextureFromSurface(renderer, mask);
SDL_FreeSurface(mask);
lv_mem_free(buf);
lv_draw_sdl_texture_cache_put(ctx, &glyph_key, sizeof(glyph_key), texture);
in_cache = lv_draw_sdl_texture_cache_put(ctx, &glyph_key, sizeof(glyph_key), texture);
}
else {
in_cache = true;
}
if(!texture) {
return;
@@ -142,6 +146,10 @@ void lv_draw_sdl_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t
/*If the letter is completely out of mask don't draw it*/
if(!_lv_area_intersect(&draw_area, &t_letter, &t_clip)) {
if(!in_cache) {
LV_LOG_WARN("Texture is not cached, this will impact performance.");
SDL_DestroyTexture(texture);
}
return;
}
SDL_Rect srcrect, dstrect;
@@ -156,6 +164,11 @@ void lv_draw_sdl_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t
SDL_RenderCopy(renderer, texture, &srcrect, &dstrect);
lv_draw_sdl_composite_end(ctx, &apply_area, dsc->blend_mode);
if(!in_cache) {
LV_LOG_WARN("Texture is not cached, this will impact performance.");
SDL_DestroyTexture(texture);
}
}
/**********************

View File

@@ -58,15 +58,24 @@ lv_draw_layer_ctx_t * lv_draw_sdl_layer_init(lv_draw_ctx_t * draw_ctx, lv_draw_l
enum lv_draw_sdl_composite_texture_id_t texture_id = LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TRANSFORM0 +
ctx->internals->transform_count;
transform_ctx->target = lv_draw_sdl_composite_texture_obtain(ctx, texture_id, target_w, target_h);
transform_ctx->target = lv_draw_sdl_composite_texture_obtain(ctx, texture_id, target_w, target_h,
&transform_ctx->target_in_cache);
transform_ctx->target_rect.x = 0;
transform_ctx->target_rect.y = 0;
transform_ctx->target_rect.w = target_w;
transform_ctx->target_rect.h = target_h;
layer_ctx->max_row_with_alpha = target_h;
layer_ctx->max_row_with_no_alpha = target_h;
SDL_SetTextureBlendMode(transform_ctx->target, SDL_BLENDMODE_BLEND);
SDL_SetRenderTarget(renderer, transform_ctx->target);
SDL_RenderClear(renderer);
/* SDL_RenderClear is not working properly, so we overwrite the target with solid color */
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
SDL_RenderFillRect(renderer, NULL);
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
/* Set proper drawing context for transform layer */
ctx->internals->transform_count += 1;
@@ -100,6 +109,7 @@ void lv_draw_sdl_layer_blend(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * lay
lv_area_to_sdl_rect(layer_ctx->original.clip_area, &clip_rect);
SDL_Point center = {.x = draw_dsc->pivot.x, .y = draw_dsc->pivot.y};
SDL_RenderSetClipRect(renderer, &clip_rect);
SDL_SetTextureAlphaMod(transform_ctx->target, draw_dsc->opa);
SDL_RenderCopyEx(renderer, transform_ctx->target, &transform_ctx->target_rect, &trans_rect,
draw_dsc->angle, &center, SDL_FLIP_NONE);
SDL_RenderSetClipRect(renderer, NULL);
@@ -108,6 +118,11 @@ void lv_draw_sdl_layer_blend(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * lay
void lv_draw_sdl_layer_destroy(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx)
{
lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
lv_draw_sdl_layer_ctx_t * transform_ctx = (lv_draw_sdl_layer_ctx_t *) layer_ctx;
if(!transform_ctx->target_in_cache && transform_ctx->target != NULL) {
LV_LOG_WARN("Texture is not cached, this will impact performance.");
SDL_DestroyTexture(transform_ctx->target);
}
ctx->internals->transform_count -= 1;
}

View File

@@ -28,6 +28,7 @@ typedef struct _lv_draw_sdl_layer_ctx_t {
SDL_Texture * orig_target;
SDL_Texture * target;
SDL_Rect target_rect;
bool target_in_cache;
lv_draw_layer_flags_t flags;
} lv_draw_sdl_layer_ctx_t;
/**********************

View File

@@ -53,7 +53,7 @@ static SDL_Texture * line_texture_create(lv_draw_sdl_ctx_t * sdl_ctx, const lv_d
* GLOBAL FUNCTIONS
**********************/
void lv_draw_sdl_draw_line(lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, const lv_point_t * point1,
const lv_point_t * point2)
const lv_point_t * point2, bool * in_cache)
{
lv_draw_sdl_ctx_t * sdl_ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
SDL_Renderer * renderer = sdl_ctx->renderer;
@@ -68,7 +68,7 @@ void lv_draw_sdl_draw_line(lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t *
SDL_Texture * texture = lv_draw_sdl_texture_cache_get(sdl_ctx, &key, sizeof(key), NULL);
if(!texture) {
texture = line_texture_create(sdl_ctx, dsc, (lv_coord_t) length);
lv_draw_sdl_texture_cache_put(sdl_ctx, &key, sizeof(key), texture);
*in_cache = lv_draw_sdl_texture_cache_put(sdl_ctx, &key, sizeof(key), texture);
}
lv_area_t coords = {x1, y1, x2, y2};
@@ -126,7 +126,10 @@ static SDL_Texture * line_texture_create(lv_draw_sdl_ctx_t * sdl_ctx, const lv_d
SDL_SetRenderTarget(sdl_ctx->renderer, texture);
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
SDL_SetRenderDrawColor(sdl_ctx->renderer, 0xFF, 0xFF, 0xFF, 0x0);
SDL_RenderClear(sdl_ctx->renderer);
/* SDL_RenderClear is not working properly, so we overwrite the target with solid color */
SDL_SetRenderDrawBlendMode(sdl_ctx->renderer, SDL_BLENDMODE_NONE);
SDL_RenderFillRect(sdl_ctx->renderer, NULL);
SDL_SetRenderDrawBlendMode(sdl_ctx->renderer, SDL_BLENDMODE_BLEND);
SDL_SetRenderDrawColor(sdl_ctx->renderer, 0xFF, 0xFF, 0xFF, 0xFF);
SDL_Rect line_rect = {1 + dsc->width / 2, 1, length, dsc->width};
SDL_RenderFillRect(sdl_ctx->renderer, &line_rect);

View File

@@ -77,7 +77,9 @@ void lv_draw_sdl_polygon(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dr
int16_t mask_id = lv_draw_mask_add(&polygon_param, NULL);
lv_coord_t w = lv_area_get_width(&draw_area), h = lv_area_get_height(&draw_area);
SDL_Texture * texture = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM1, w, h);
bool texture_in_cache = false;
SDL_Texture * texture = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM1, w, h,
&texture_in_cache);
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
dump_masks(texture, &draw_area);
@@ -91,6 +93,10 @@ void lv_draw_sdl_polygon(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dr
SDL_SetTextureColorMod(texture, color.r, color.g, color.b);
SDL_SetTextureAlphaMod(texture, draw_dsc->bg_opa);
SDL_RenderCopy(ctx->renderer, texture, &srcrect, &dstrect);
if(!texture_in_cache) {
LV_LOG_WARN("Texture is not cached, this will impact performance.");
SDL_DestroyTexture(texture);
}
}
/**********************

View File

@@ -35,6 +35,7 @@ typedef struct lv_draw_sdl_context_internals_t {
lv_lru_t * texture_cache;
SDL_Texture * mask;
SDL_Texture * composition;
bool composition_cached;
SDL_Texture * target_backup;
uint8_t transform_count;
} lv_draw_sdl_context_internals_t;

Some files were not shown because too many files have changed in this diff Show More