From 7066c8fbbb082934bc1da8251571d23da7b4d979 Mon Sep 17 00:00:00 2001 From: dyktronix Date: Thu, 17 Jun 2021 13:43:19 +0200 Subject: [PATCH 01/17] feat(spinbox ) add function to set cursor to specific position (#2314) * Spinbox set cursor to specific position (funct.) * changed exp10 to lv_pow(10 * Update lv_spinbox.c resolved indentation * Update spinbox.md Added lv_spinbox_set_pos description Co-authored-by: Sebastian Dyker --- docs/widgets/extra/spinbox.md | 2 ++ src/extra/widgets/spinbox/lv_spinbox.c | 17 +++++++++++++++++ src/extra/widgets/spinbox/lv_spinbox.h | 6 ++++++ 3 files changed, 25 insertions(+) diff --git a/docs/widgets/extra/spinbox.md b/docs/widgets/extra/spinbox.md index 920c1be1c..717a53d5d 100644 --- a/docs/widgets/extra/spinbox.md +++ b/docs/widgets/extra/spinbox.md @@ -20,6 +20,8 @@ The parts of the Spinbox are identical to the [Text area](/widgets/core/textarea `lv_spinbox_set_step(spinbox, 100)` sets which digits to change on increment/decrement. Only multiples of ten can be set, and not for example 3. +`lv_spinbox_set_pos(spinbox, 1)` sets the cursor to a specific digit to change on increment/decrement. For example position '0' sets the cursor to the least significant digit. + ### Format `lv_spinbox_set_digit_format(spinbox, digit_count, separator_position)` sets the number format. `digit_count` is the number of digits excluding the decimal separator and the sign. diff --git a/src/extra/widgets/spinbox/lv_spinbox.c b/src/extra/widgets/spinbox/lv_spinbox.c index 66bfdd0e6..5d972d5a8 100644 --- a/src/extra/widgets/spinbox/lv_spinbox.c +++ b/src/extra/widgets/spinbox/lv_spinbox.c @@ -145,6 +145,23 @@ void lv_spinbox_set_range(lv_obj_t * obj, int32_t range_min, int32_t range_max) lv_spinbox_updatevalue(obj); } +/** + * Set cursor position to a specific digit for edition + * @param spinbox pointer to spinbox + * @param pos selected position in spinbox + */ +void lv_spinbox_set_pos(lv_obj_t * obj, uint8_t pos) +{ + + lv_spinbox_t * spinbox = (lv_spinbox_t *)obj; + int32_t step_limit; + step_limit = LV_MAX(spinbox->range_max, (spinbox->range_min < 0 ? (-spinbox->range_min) : spinbox->range_min)); + int32_t new_step = spinbox->step * lv_pow(10, pos); + if(pos <= 0) spinbox->step = 1; + else if(new_step <= step_limit) spinbox->step = new_step; + + lv_spinbox_updatevalue(obj); +} /*===================== * Getter functions *====================*/ diff --git a/src/extra/widgets/spinbox/lv_spinbox.h b/src/extra/widgets/spinbox/lv_spinbox.h index 92000a042..ce3bce27c 100644 --- a/src/extra/widgets/spinbox/lv_spinbox.h +++ b/src/extra/widgets/spinbox/lv_spinbox.h @@ -99,6 +99,12 @@ void lv_spinbox_set_step(lv_obj_t * obj, uint32_t step); */ void lv_spinbox_set_range(lv_obj_t * obj, int32_t range_min, int32_t range_max); +/** + * Set cursor position to a specific digit for edition + * @param spinbox pointer to spinbox + * @param pos selected position in spinbox + */ +void lv_spinbox_set_pos(lv_obj_t * obj, uint8_t pos); /*===================== * Getter functions *====================*/ From 7c1eb0064535f2d914b9dc885ebb2a2d0d73381d Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Fri, 18 Jun 2021 11:05:33 +0200 Subject: [PATCH 02/17] docs(license) update company name and year --- LICENCE.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENCE.txt b/LICENCE.txt index a6f7f803e..f877abb18 100644 --- a/LICENCE.txt +++ b/LICENCE.txt @@ -1,5 +1,5 @@ MIT licence -Copyright (c) 2020 LVGL LLC +Copyright (c) 2021 LVGL Kft 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: From 4b8c73a5770657ab55bbe825f7887e28c55a8a4a Mon Sep 17 00:00:00 2001 From: Themba Dube Date: Fri, 18 Jun 2021 12:25:49 -0400 Subject: [PATCH 03/17] feat(docs) improvements to examples * examples are now loaded only when they are visible on your screen * stylistic improvements * support for a description --- .gitignore | 1 + docs/_ext/lv_example.py | 35 +++- docs/_static/css/custom.css | 35 +++- docs/_templates/page.html | 27 +++ docs/example_list.py | 9 +- docs/examples.md | 364 --------------------------------- examples/widgets/arc/index.rst | 1 + 7 files changed, 92 insertions(+), 380 deletions(-) delete mode 100644 docs/examples.md diff --git a/.gitignore b/.gitignore index 0286e4ad6..7ea1e3412 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ scripts/cppcheck_res.txt scripts/built_in_font/lv_font_* docs/doxygen_html docs/xml +docs/examples.md docs/out_latex docs/_static/built_lv_examples docs/LVGL.pdf diff --git a/docs/_ext/lv_example.py b/docs/_ext/lv_example.py index 4679d76d8..08fcf9f52 100644 --- a/docs/_ext/lv_example.py +++ b/docs/_ext/lv_example.py @@ -16,7 +16,8 @@ class LvExample(Directive): required_arguments = 1 option_spec = { 'excluded_languages': excluded_list, - 'language': directives.unchanged + 'language': directives.unchanged, + 'description': directives.unchanged } def get_example_code_path(self, example_path, language): return os.path.abspath("../examples/" + example_path + "." + language) @@ -27,8 +28,10 @@ class LvExample(Directive): return 'C' else: return language - def embed_code(self, example_file, example_path, language): + def github_path(self, example_path, language): env = self.state.document.settings.env + return f"https://github.com/lvgl/lvgl/blob/{env.config.repo_commit_hash}/examples/{example_path}.{language}" + def embed_code(self, example_file, example_path, language, buttons={}): toggle = nodes.container('', literal_block=False, classes=['toggle']) header = nodes.container('', literal_block=False, classes=['header']) toggle.append(header) @@ -40,7 +43,10 @@ class LvExample(Directive): literal_list = nodes.literal_block(contents, contents) literal_list['language'] = language toggle.append(literal_list) - header.append(nodes.raw(text=f"

{self.human_language_name(language)} code     view on GitHub

", format='html')) + paragraph_node = nodes.raw(text=f"

{self.human_language_name(language)} code  

", format='html') + for text, url in buttons.items(): + paragraph_node.append(nodes.raw(text=f"{text}", format='html')) + header.append(paragraph_node) return toggle def run(self): example_path = self.arguments[0] @@ -50,20 +56,27 @@ class LvExample(Directive): env = self.state.document.settings.env - iframe_node = nodes.raw(text=f"", format='html') - micropython_node = nodes.raw(text=f"Click to try in the MicroPython simulator!", format='html') - + iframe_html = "" + c_path = self.get_example_code_path(example_path, 'c') py_path = self.get_example_code_path(example_path, 'py') - c_code = self.embed_code(c_path, example_path, 'c') - py_code = self.embed_code(py_path, example_path, 'py') + c_code = self.embed_code(c_path, example_path, 'c', buttons={ + ' GitHub': self.github_path(example_path, 'c') + }) + py_code = self.embed_code(py_path, example_path, 'py', buttons={ + ' GitHub': self.github_path(example_path, 'py'), + ' Simulator': f"https://sim.lvgl.io/v{env.config.version}/micropython/ports/javascript/index.html?script_startup=https://raw.githubusercontent.com/lvgl/lvgl/{env.config.repo_commit_hash}/examples/header.py&script=https://raw.githubusercontent.com/lvgl/lvgl/{env.config.repo_commit_hash}/examples/{example_path}.py" + }) if not 'c' in excluded_languages: if env.app.tags.has('html'): - node_list.append(iframe_node) - if not 'py' in excluded_languages: - node_list.append(micropython_node) + iframe_html = f"
" + + description_html = f"
{self.options.get('description', '')}
" + layout_node = nodes.raw(text=f"
{iframe_html}{description_html}
", format='html') + + node_list.append(layout_node) if not 'c' in excluded_languages: node_list.append(c_code) if not 'py' in excluded_languages: diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css index a5e2c2532..a6f9c406b 100644 --- a/docs/_static/css/custom.css +++ b/docs/_static/css/custom.css @@ -19,7 +19,7 @@ span.pre:first-child code.sig-name { - //margin-left:8px; + /*margin-left:8px;*/ } .toggle .header { @@ -64,11 +64,42 @@ code.sig-name transform: translate(0, -10px); } -.lv-example { +.lv-example, .lv-example > iframe { border: none; outline: none; padding: none; display: block; width: 320px; height: 240px; + flex: none; + position: relative; } +.lv-example > iframe { + position: absolute; + top: 0; + left: 0; +} + +.lv-example-container { + display: flex; +} +.lv-example-description { + flex: 1 1 auto; +} + +.lv-example-link-button { + display: inline-block; + padding: 4px 8px; + border-radius: 4px; + background-color: #2980b9; + color: white; + margin: 0 4px; +} +.lv-example-link-button:hover { + color: white; + filter: brightness(120%); +} + +.lv-example-link-button:visited { + color: white; +} \ No newline at end of file diff --git a/docs/_templates/page.html b/docs/_templates/page.html index 9ceaae358..f29c63d4d 100644 --- a/docs/_templates/page.html +++ b/docs/_templates/page.html @@ -51,5 +51,32 @@ document.addEventListener('DOMContentLoaded', (event) => { }); }) +document.addEventListener('DOMContentLoaded', (event) => { + function onIntersection(entries) { + entries.forEach(entry => { + let currentlyLoaded = entry.target.getAttribute("data-is-loaded") == "true"; + let shouldBeLoaded = entry.intersectionRatio > 0; + if(currentlyLoaded != shouldBeLoaded) { + entry.target.setAttribute("data-is-loaded", shouldBeLoaded); + if(shouldBeLoaded) { + let iframe = document.createElement("iframe"); + iframe.src = entry.target.getAttribute("data-real-src"); + entry.target.appendChild(iframe); + } else { + let iframe = entry.target.querySelector("iframe"); + iframe.parentNode.removeChild(iframe); + } + } + }); + } + const config = { + rootMargin: '50px 0px', + threshold: 0.01 + }; + let observer = new IntersectionObserver(onIntersection, config); + document.querySelectorAll(".lv-example").forEach(iframe => { + observer.observe(iframe); + }); +}); {% endblock %} diff --git a/docs/example_list.py b/docs/example_list.py index f4f9e325b..999d9d138 100755 --- a/docs/example_list.py +++ b/docs/example_list.py @@ -1,5 +1,7 @@ +#!/usr/bin/env python3 import os - + + def process_index_rst(path): # print(path) with open(path) as fp: @@ -73,10 +75,11 @@ layouts = { def print_item(path, lvl, d, fout): for k in d: v = d[k] - b = os.path.basename(k) if k.startswith(path + "/lv_example_"): fout.write("#"*lvl + " " + v + "\n") - fout.write('\n') + fout.write('```eval_rst\n') + fout.write(f".. lv_example:: {k}\n") + fout.write('```\n') fout.write("\n") def exec(): diff --git a/docs/examples.md b/docs/examples.md deleted file mode 100644 index 1a2c540e2..000000000 --- a/docs/examples.md +++ /dev/null @@ -1,364 +0,0 @@ -```eval_rst -.. include:: /header.rst -:github_url: |github_link_base|/examples.md -``` - -# Examples -## Get started -### A button with a label and react on click event - - -### Create styles from scratch for buttons - - -### Create a slider and write its value on a label - - -## Styles -### Size styles - - -### Background styles - - -### Border styles - - -### Outline styles - - -### Shadow styles - - -### Image styles - - -### Text styles - - -### Line styles - - -### Transition - - -### Using multiple styles - - -### Local styles - - -### Add styles to parts and states - - -### Extending the current theme - - -## Animations -### Start animation on an event - - -### Playback animation - - -## Events -### Button click event - - -### Handle multiple events - - -### Event bubbling - - -## Layouts -### Flex -#### A simple row and a column layout with flexbox - - -#### Arrange items in rows with wrap and even spacing - - -#### Demonstrate flex grow - - -#### Demonstrate flex grow. - - -#### Demonstrate column and row gap style properties - - -#### RTL base direction changes order of the items - - -### Grid -#### A simple grid - - -#### Demonstrate cell placement and span - - -#### Demonstrate grid's "free unit" - - -#### Demonstrate track placement - - -#### Demonstrate column and row gap - - -#### Demonstrate RTL direction on grid - - -## Scrolling -### Nested scrolling - - -### Snapping - - -### Floating button - - -### Styling the scrollbars - - -### Right to left scrolling - - -### Translate on scroll - - -## Widgets -### Base object -#### Base objects with custom styles - - -#### Make an object draggable - - -### Arc -#### Simple Arc - - -#### Loader with Arc - - -### Bar -#### Simple Bar - - -#### Styling a bar - - -#### Temperature meter - - -#### Stripe pattern and range value - - -#### Bar with RTL and RTL base direction - - -#### Custom drawr to show the current value - - -### Button -#### Simple Buttons - - -#### Styling buttons - - -#### Gummy button - - -### Button matrix -#### Simple Button matrix - - -#### Custom buttons - - -#### Pagination - - -### Calendar -#### Calendar with header - - -### Canvas -#### Drawing on the Canvas and rotate - - -#### Transparent Canvas with chroma keying - - -### Chart -#### Line Chart - - -#### Faded area line chart with custom division lines - - -#### Axis ticks and labels with scrolling - - -#### Show the value of the pressed points - - -#### Display 1000 data points with zooming and scrolling - - -#### Show cursor on the clicked point - - -#### Scatter chart - - -### Checkbox -#### Simple Checkboxes - - -### Colorwheel -#### Simple Colorwheel - - -### Dropdown -#### Simple Drop down list - - -#### Drop down in four directions - - -#### Menu - - -### Image -#### Image from variable and symbol - - -#### Image recoloring - - -#### Rotate and zoom - - -#### Image offset and styling - - -### Image button -#### Simple Image button - - -### Keyboard -#### Keyboard with text area - - -### Label -#### Line wrap, recoloring and scrolling - - -#### Text shadow - - -#### Show LTR, RTL and Chinese texts - - -### LED -#### LED with custom style - - -### Line -#### Simple Line - - -### List -#### Simple List - - -### Meter -#### Simple meter - - -#### A meter with multiple arcs - - -#### A clock from a meter - - -#### Pie chart - - -### Message box -#### Simple Message box - - -### Roller -#### Simple Roller - - -#### Styling the roller - - -#### add fade mask to roller - - -### Slider -#### Simple Slider - - -#### Slider with custom style - - -#### Slider with extended drawer - - -### Span -#### Span with custom styles - - -### Spinbox -#### Simple Spinbox - - -### Spinner -#### Simple spinner - - -### Switch -#### Simple Switch - - -### Table -#### Simple table - - -#### Lightweighted list from table - - -### Tabview -#### Simple Tabview - - -#### Tabs on the left, styling and no scrolling - - -### Textarea -#### Simple Text area - - -#### Text area with password field - - -#### Text auto-formatting - - -### Tabview -#### Tileview with content - - -### Window -#### Simple window - - diff --git a/examples/widgets/arc/index.rst b/examples/widgets/arc/index.rst index 7c529f990..c257384ef 100644 --- a/examples/widgets/arc/index.rst +++ b/examples/widgets/arc/index.rst @@ -4,6 +4,7 @@ Simple Arc .. lv_example:: widgets/arc/lv_example_arc_1 :language: c + :description: A simple example to demonstrate the use of an arc. Loader with Arc """""""""""""""" From b5f632ee7a265ce4f2472522b422b8cd5366aaa9 Mon Sep 17 00:00:00 2001 From: Themba Dube Date: Fri, 18 Jun 2021 12:38:08 -0400 Subject: [PATCH 04/17] fix(docs) add margin for example description --- docs/_static/css/custom.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css index a6f9c406b..9c3b822e3 100644 --- a/docs/_static/css/custom.css +++ b/docs/_static/css/custom.css @@ -85,6 +85,7 @@ code.sig-name } .lv-example-description { flex: 1 1 auto; + margin-left: 1rem; } .lv-example-link-button { @@ -102,4 +103,4 @@ code.sig-name .lv-example-link-button:visited { color: white; -} \ No newline at end of file +} From 145a0fad0857dad7f2066e7d22436827e0d3fd7d Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Fri, 18 Jun 2021 18:11:53 -0400 Subject: [PATCH 05/17] fix(docs) consider an example to be visible over a wider area --- docs/_templates/page.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_templates/page.html b/docs/_templates/page.html index f29c63d4d..42dcda4e7 100644 --- a/docs/_templates/page.html +++ b/docs/_templates/page.html @@ -70,7 +70,7 @@ document.addEventListener('DOMContentLoaded', (event) => { }); } const config = { - rootMargin: '50px 0px', + rootMargin: '600px 0px', threshold: 0.01 }; let observer = new IntersectionObserver(onIntersection, config); From fe6d8d7636ae283afda68e85b2d1f143d8d05462 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Sun, 20 Jun 2021 12:34:22 +0200 Subject: [PATCH 06/17] fix(color) overflow with 16 bit color depth --- src/misc/lv_color.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/misc/lv_color.c b/src/misc/lv_color.c index 8cfb18c1e..7ec8c7196 100644 --- a/src/misc/lv_color.c +++ b/src/misc/lv_color.c @@ -43,7 +43,7 @@ LV_ATTRIBUTE_FAST_MEM void lv_color_fill(lv_color_t * buf, lv_color_t color, uin px_num--; } - uint32_t c32 = color.full + (color.full << 16); + uint32_t c32 = (uint32_t)color.full + ((uint32_t)color.full << 16); uint32_t * buf32 = (uint32_t *)buf; while(px_num > 16) { From b203167c7583905e2cb4006e57a16432841a2353 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Sun, 20 Jun 2021 12:35:03 +0200 Subject: [PATCH 07/17] feat(obj) send LV_EVENT_DRAW_PART_BEGIN/END for MAIN and SCROLLBAR parts --- src/core/lv_obj.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/core/lv_obj.c b/src/core/lv_obj.c index ae8d08866..9dada7aef 100644 --- a/src/core/lv_obj.c +++ b/src/core/lv_obj.c @@ -472,8 +472,18 @@ static void lv_obj_draw(lv_event_t * e) coords.y1 -= h; coords.y2 += h; + + lv_obj_draw_part_dsc_t part_dsc; + lv_obj_draw_dsc_init(&part_dsc, clip_area); + part_dsc.rect_dsc = &draw_dsc; + part_dsc.draw_area = &coords; + part_dsc.part = LV_PART_MAIN; + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_dsc); + lv_draw_rect(&coords, clip_area, &draw_dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_dsc); + #if LV_DRAW_COMPLEX if(lv_obj_get_style_clip_corner(obj, LV_PART_MAIN)) { lv_draw_mask_radius_param_t * mp = lv_mem_buf_get(sizeof(lv_draw_mask_radius_param_t)); @@ -530,8 +540,23 @@ static void draw_scrollbar(lv_obj_t * obj, const lv_area_t * clip_area) lv_res_t sb_res = scrollbar_init_draw_dsc(obj, &draw_dsc); if(sb_res != LV_RES_OK) return; - if(lv_area_get_size(&hor_area) > 0) lv_draw_rect(&hor_area, clip_area, &draw_dsc); - if(lv_area_get_size(&ver_area) > 0) lv_draw_rect(&ver_area, clip_area, &draw_dsc); + lv_obj_draw_part_dsc_t part_dsc; + lv_obj_draw_dsc_init(&part_dsc, clip_area); + part_dsc.rect_dsc = &draw_dsc; + part_dsc.part = LV_PART_SCROLLBAR; + + if(lv_area_get_size(&hor_area) > 0) { + part_dsc.draw_area = &hor_area; + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_dsc); + lv_draw_rect(&hor_area, clip_area, &draw_dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_dsc); + } + if(lv_area_get_size(&ver_area) > 0) { + part_dsc.draw_area = &ver_area; + lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_dsc); + lv_draw_rect(&ver_area, clip_area, &draw_dsc); + lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_dsc); + } } /** From 8a2a4a11c81d029ff737980b883c62dfbb4b44c6 Mon Sep 17 00:00:00 2001 From: Jozef Bastek Date: Tue, 8 Dec 2020 10:38:19 +0100 Subject: [PATCH 08/17] fix(pxp): update for v8 includes updates from NXP MCU SDK 2.10 with adaptation for lvgl v8: Updated cache handling - range limited cache flushing changed to complete cache flush, which is faster and shold be safe - flushing done via callback system, so OS specific code is removed from LVGL Signed-off-by: Jozef Bastek gpu: pxp: Buffer sync with BLITs Added buffer synchronisation with BLITs instead of memcpy for PXP. In LVGL v8, buffer synchronisation acceleration is moved to littlevgl_support.c. Signed-off-by: Jozef Bastek gpu: pxp: updates for v8 cache callback type changed in display driver struct chroma key name changed Signed-off-by: Seb Fagard gpu: pxp: new log header file for v8 Signed-off-by: Seb Fagard core: init PXP accelerator Signed-off-by: Seb Fagard --- src/core/lv_obj.c | 12 ++++++++++ src/gpu/lv_gpu_nxp_pxp.c | 46 +++++++----------------------------- src/gpu/lv_gpu_nxp_pxp.h | 5 ++++ src/gpu/lv_gpu_nxp_pxp_osa.c | 1 + 4 files changed, 27 insertions(+), 37 deletions(-) diff --git a/src/core/lv_obj.c b/src/core/lv_obj.c index 296d733cc..b7c95b307 100644 --- a/src/core/lv_obj.c +++ b/src/core/lv_obj.c @@ -30,6 +30,11 @@ #include "../gpu/lv_gpu_stm32_dma2d.h" #endif +#if LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT + #include "../gpu/lv_gpu_nxp_pxp.h" + #include "../gpu/lv_gpu_nxp_pxp_osa.h" +#endif + /********************* * DEFINES *********************/ @@ -105,6 +110,13 @@ void lv_init(void) lv_gpu_stm32_dma2d_init(); #endif +#if LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT + if(lv_gpu_nxp_pxp_init(&pxp_default_cfg) != LV_RES_OK) { + LV_LOG_ERROR("PXP init error. STOP.\n"); + for(; ;) ; + } +#endif + _lv_obj_style_init(); _lv_ll_init(&LV_GC_ROOT(_lv_disp_ll), sizeof(lv_disp_t)); _lv_ll_init(&LV_GC_ROOT(_lv_indev_ll), sizeof(lv_indev_t)); diff --git a/src/gpu/lv_gpu_nxp_pxp.c b/src/gpu/lv_gpu_nxp_pxp.c index 97753e822..1b669d861 100644 --- a/src/gpu/lv_gpu_nxp_pxp.c +++ b/src/gpu/lv_gpu_nxp_pxp.c @@ -71,8 +71,6 @@ static void lv_gpu_nxp_pxp_run(void); static void lv_gpu_nxp_pxp_blit_recolor(lv_color_t * dest, lv_coord_t dest_width, const lv_color_t * src, lv_coord_t src_width, lv_coord_t copy_width, lv_coord_t copy_height, lv_opa_t opa, lv_color_t recolor, lv_opa_t recolorOpa); -static void lv_gpu_nxp_invalidate_cache(uint32_t address, uint32_t width, uint32_t height, uint32_t stride, - uint32_t pxSize); /********************** * STATIC VARIABLES @@ -160,8 +158,7 @@ void lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, lv_coord_t dest_width, const lv_ .width = fill_area->x2 - fill_area->x1 + 1, .height = fill_area->y2 - fill_area->y1 + 1, }; - lv_gpu_nxp_invalidate_cache(outputConfig.buffer0Addr, outputConfig.width, outputConfig.height, outputConfig.pitchBytes, - sizeof(lv_color_t)); + PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputConfig); if(opa > LV_OPA_MAX) { @@ -272,9 +269,6 @@ void lv_gpu_nxp_pxp_blit(lv_color_t * dest, lv_coord_t dest_width, const lv_colo PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, copy_width - 1U, copy_height - 1U); PXP_SetAlphaSurfaceBlendConfig(LV_GPU_NXP_PXP_ID, &asBlendConfig); - lv_gpu_nxp_invalidate_cache(asBufferConfig.bufferAddr, copy_width, copy_height, asBufferConfig.pitchBytes, - sizeof(lv_color_t)); - if(colorKeyEnabled) { PXP_SetAlphaSurfaceOverlayColorKey(LV_GPU_NXP_PXP_ID, colorKey, colorKey); } @@ -290,10 +284,7 @@ void lv_gpu_nxp_pxp_blit(lv_color_t * dest, lv_coord_t dest_width, const lv_colo outputBufferConfig.height = copy_height; PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig); - lv_gpu_nxp_invalidate_cache(outputBufferConfig.buffer0Addr, outputBufferConfig.width, outputBufferConfig.height, - outputBufferConfig.pitchBytes, sizeof(lv_color_t)); - - lv_gpu_nxp_pxp_run(); /*Start PXP task*/ + lv_gpu_nxp_pxp_run(); /* Start PXP task */ } /** @@ -349,6 +340,12 @@ void lv_gpu_nxp_pxp_disable_recolor(void) */ static void lv_gpu_nxp_pxp_run(void) { + lv_disp_t * disp = _lv_refr_get_disp_refreshing(); + + if(disp && disp->driver->clean_dcache_cb) { /* Clean & invalidate cache */ + disp->driver->clean_dcache_cb(disp->driver); + } + pxp_cfg.pxp_run(); } @@ -396,9 +393,6 @@ static void lv_gpu_nxp_pxp_blit_recolor(lv_color_t * dest, lv_coord_t dest_width PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig); PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, copy_width - 1U, copy_height - 1U); - lv_gpu_nxp_invalidate_cache(asBufferConfig.bufferAddr, copy_width, copy_height, asBufferConfig.pitchBytes, - sizeof(lv_color_t)); - /*Disable PS buffer, use as color generator*/ PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U); PXP_SetProcessSurfaceBackGroundColor(LV_GPU_NXP_PXP_ID, lv_color_to32(recolor)); @@ -413,9 +407,6 @@ static void lv_gpu_nxp_pxp_blit_recolor(lv_color_t * dest, lv_coord_t dest_width outputBufferConfig.height = copy_height; PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig); - lv_gpu_nxp_invalidate_cache(outputBufferConfig.buffer0Addr, outputBufferConfig.width, outputBufferConfig.height, - outputBufferConfig.pitchBytes, sizeof(lv_color_t)); - pxp_porter_duff_config_t pdConfig; /*Configure Porter-Duff blending - For RGB 565 only!*/ @@ -454,23 +445,4 @@ static void lv_gpu_nxp_pxp_blit_recolor(lv_color_t * dest, lv_coord_t dest_width } } -/** - * @brief Invalidate cache for rectangular area of memory - * - * @param[in] address starting address of area - * @param[in] width width of area in pixels - * @param[in] height height of area in pixels - * @param[in] stride stride in bytes - * @param[in] pxSize pixel size in bytes - */ -static void lv_gpu_nxp_invalidate_cache(uint32_t address, uint32_t width, uint32_t height, uint32_t stride, - uint32_t pxSize) -{ - int y; - - for(y = 0; y < height; y++) { - DCACHE_CleanInvalidateByRange(address, width * pxSize); - address += stride; - } -} -#endif /*LV_USE_GPU && LV_USE_GPU_NXP_PXP*/ +#endif /* LV_USE_GPU_NXP_PXP */ diff --git a/src/gpu/lv_gpu_nxp_pxp.h b/src/gpu/lv_gpu_nxp_pxp.h index 9d3957246..9aba7c27d 100644 --- a/src/gpu/lv_gpu_nxp_pxp.h +++ b/src/gpu/lv_gpu_nxp_pxp.h @@ -61,6 +61,11 @@ extern "C" { #define LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT 16 #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 32 +#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 64 diff --git a/src/gpu/lv_gpu_nxp_pxp_osa.c b/src/gpu/lv_gpu_nxp_pxp_osa.c index 8e56efbf5..5a16db864 100644 --- a/src/gpu/lv_gpu_nxp_pxp_osa.c +++ b/src/gpu/lv_gpu_nxp_pxp_osa.c @@ -32,6 +32,7 @@ *********************/ #include "../lv_conf_internal.h" +#include "../misc/lv_log.h" #if LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT From e3e3eeaf8c1593d384c6537244a301cdc1abd3d9 Mon Sep 17 00:00:00 2001 From: Jozef Bastek Date: Fri, 4 Dec 2020 10:02:22 +0100 Subject: [PATCH 09/17] fix(vglite): update for v8 includes updates coming from NXP MCU SDK 2.10 with adaptation for lvgl v8: Fixed BLIT offset computation Previous implementation didn't take into account a possibility of non-zero offset in source image, so output was wrong if offset was used. With this fix, CPU and VG-Lite output is the same even with offsets. Signed-off-by: Jozef Bastek gpu: vglite: Buffer sync with BLITs Added buffer synchronisation with BLITs instead of memcpy for VG-Lite. In LVGL v8, buffer synchronisation acceleration is moved to littlevgl_support.c. Signed-off-by: Jozef Bastek gpu: vglite: Fixed BLIT boundary Fixed artifact issue revealed by buffer sync with BLIT feature. Caused by wrong BLIT boundary. Signed-off-by: Jozef Bastek gpu: vglite: BLIT quality degradation workaround for RT595 Limitation in RT595 causes BLIT image quality degradation when coordinates are above 368 px. This patch implements workaround that will break the BLIT into multiple smaller BLITs, so the quality is not affected for higher resolutions. Signed-off-by: Jozef Bastek gpu: vglite: Fix address alignment and stride requirements Fixed multiple issues: - The VGLite alignment requirement checks for the pixel destination buffer are not applicable in our case of Linear (non-tiled) format. - Some VGLite stride requirement requirement should be expressed in bytes, not in pixels. - Fix the Y alignment function to ensure that line starts at an address that the respects the alignment requirement of VG-Lite. Such mistakes do not break application, but cause a fallback to non-accelerated Blit by CPU. See MGG-741. Signed-off-by: Seb Fagard gpu: vglite: fix some MISRA C 2012 violations fixed 56 violations: mainly implicit format casts and unchecked returned values. see JIRA MCUX-43327 Signed-off-by: Seb Fagard gpu: vglite: fix stride requirement in _init_vg_buf() fix unit: need to convert the alignment requirement into bytes when checking stride parameter. fix condition: stride requirement applies only on source buffers. Signed-off-by: Seb Fagard gpu: vglite: updates for v8 cache callback type changed in display driver struct Signed-off-by: Seb Fagard gpu: vglite: update parameter type for v8 display driver is now a pointer in structure. Signed-off-by: Seb Fagard --- src/draw/lv_draw_blend.c | 16 +- src/gpu/lv_gpu_nxp_vglite.c | 570 ++++++++++++++++++++++++++++++++---- src/gpu/lv_gpu_nxp_vglite.h | 12 +- 3 files changed, 533 insertions(+), 65 deletions(-) diff --git a/src/draw/lv_draw_blend.c b/src/draw/lv_draw_blend.c index 31ca6ba0d..46ba49891 100644 --- a/src/draw/lv_draw_blend.c +++ b/src/draw/lv_draw_blend.c @@ -701,8 +701,8 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(const lv_area_t * disp_area, lv_col blit.src_stride = lv_area_get_width(map_area) * sizeof(lv_color_t); blit.src_area.x1 = (draw_area->x1 - (map_area->x1 - disp_area->x1)); blit.src_area.y1 = (draw_area->y1 - (map_area->y1 - disp_area->y1)); - blit.src_area.x2 = blit.src_area.x1 + draw_area_w; - blit.src_area.y2 = blit.src_area.y1 + draw_area_h; + blit.src_area.x2 = blit.src_area.x1 + draw_area_w - 1; + blit.src_area.y2 = blit.src_area.y1 + draw_area_h - 1; blit.dst = disp_buf; blit.dst_width = lv_area_get_width(disp_area); @@ -710,8 +710,8 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(const lv_area_t * disp_area, lv_col blit.dst_stride = lv_area_get_width(disp_area) * sizeof(lv_color_t); blit.dst_area.x1 = draw_area->x1; blit.dst_area.y1 = draw_area->y1; - blit.dst_area.x2 = blit.dst_area.x1 + draw_area_w; - blit.dst_area.y2 = blit.dst_area.y1 + draw_area_h; + blit.dst_area.x2 = blit.dst_area.x1 + draw_area_w - 1; + blit.dst_area.y2 = blit.dst_area.y1 + draw_area_h - 1; blit.opa = opa; @@ -751,8 +751,8 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(const lv_area_t * disp_area, lv_col blit.src_stride = lv_area_get_width(map_area) * sizeof(lv_color_t); blit.src_area.x1 = (draw_area->x1 - (map_area->x1 - disp_area->x1)); blit.src_area.y1 = (draw_area->y1 - (map_area->y1 - disp_area->y1)); - blit.src_area.x2 = blit.src_area.x1 + draw_area_w; - blit.src_area.y2 = blit.src_area.y1 + draw_area_h; + blit.src_area.x2 = blit.src_area.x1 + draw_area_w - 1; + blit.src_area.y2 = blit.src_area.y1 + draw_area_h - 1; blit.dst = disp_buf; blit.dst_width = lv_area_get_width(disp_area); @@ -760,8 +760,8 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(const lv_area_t * disp_area, lv_col blit.dst_stride = lv_area_get_width(disp_area) * sizeof(lv_color_t); blit.dst_area.x1 = draw_area->x1; blit.dst_area.y1 = draw_area->y1; - blit.dst_area.x2 = blit.dst_area.x1 + draw_area_w; - blit.dst_area.y2 = blit.dst_area.y1 + draw_area_h; + blit.dst_area.x2 = blit.dst_area.x1 + draw_area_w - 1; + blit.dst_area.y2 = blit.dst_area.y1 + draw_area_h - 1; blit.opa = opa; diff --git a/src/gpu/lv_gpu_nxp_vglite.c b/src/gpu/lv_gpu_nxp_vglite.c index 94ab5ca9a..6021300e7 100644 --- a/src/gpu/lv_gpu_nxp_vglite.c +++ b/src/gpu/lv_gpu_nxp_vglite.c @@ -40,27 +40,78 @@ #include "../misc/lv_log.h" #include "fsl_cache.h" #include "vg_lite.h" +#include "fsl_debug_console.h" /********************* * DEFINES *********************/ -/********************** - * TYPEDEFS - **********************/ - #if LV_COLOR_DEPTH==16 #define VGLITE_PX_FMT VG_LITE_RGB565 #else #error Only 16bit color depth is supported. Set LV_COLOR_DEPTH to 16. #endif +/* Enable BLIT quality degradation workaround for RT595 */ +#define RT595_BLIT_WRKRND_ENABLED 1 + +/* If LV_HOR_RES_MAX/LV_VER_RES_MAX is higher than this value, workaround will be enabled */ +#define RT595_BLIT_WRKRND_THR 352 + +/* Print detailed info to SDK console (NOT to LVGL log system) */ +#define BLIT_DBG_VERBOSE 0 + +/* Draw rectangles around BLIT tiles */ +#define BLIT_DBG_AREAS 0 + +/* Redirect PRINT to SDK PRINTF */ +#define PRINT PRINTF + +/* Verbose debug print */ +#if BLIT_DBG_VERBOSE + #define PRINT_BLT PRINTF +#else + #define PRINT_BLT(...) +#endif + +/* Internal compound symbol */ +#if (defined(CPU_MIMXRT595SFFOB) || defined(CPU_MIMXRT595SFFOB_cm33) || \ + defined(CPU_MIMXRT595SFFOC) || defined(CPU_MIMXRT595SFFOC_cm33)) && \ + ((LV_HOR_RES_MAX > RT595_BLIT_WRKRND_THR) || (LV_VER_RES_MAX > RT595_BLIT_WRKRND_THR)) && \ + RT595_BLIT_WRKRND_ENABLED + #define _BLIT_SPLIT_ENABLED 1 +#else + #define _BLIT_SPLIT_ENABLED 0 +#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 + **********************/ + /********************** * STATIC PROTOTYPES **********************/ -static lv_res_t init_vg_buf(vg_lite_buffer_t * dst, uint32_t width, uint32_t height, uint32_t stride, - const lv_color_t * ptr); +static lv_res_t _init_vg_buf(vg_lite_buffer_t * dst, uint32_t width, uint32_t height, uint32_t stride, + const lv_color_t * ptr, bool source); + +static lv_res_t _lv_gpu_nxp_vglite_blit_single(lv_gpu_nxp_vglite_blit_info_t * blit); +#if _BLIT_SPLIT_ENABLED +static void _align_x(lv_area_t * area, lv_color_t ** buf); +static void _align_y(lv_area_t * area, lv_color_t ** buf, uint32_t stridePx); +static void _sw_blit(lv_gpu_nxp_vglite_blit_info_t * blit); +#if BLIT_DBG_AREAS +static void _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 +static lv_res_t _lv_gpu_nxp_vglite_check_blit(lv_gpu_nxp_vglite_blit_info_t * blit); +#endif /********************** * STATIC VARIABLES @@ -70,6 +121,14 @@ static lv_res_t init_vg_buf(vg_lite_buffer_t * dst, uint32_t width, uint32_t hei * MACROS **********************/ +#define CHECK(cond, txt) \ + do { \ + if (cond) { \ + PRINT("%s. STOP!\n", txt); \ + for ( ; ; ); \ + } \ + } while(0) + /********************** * GLOBAL FUNCTIONS **********************/ @@ -94,25 +153,37 @@ lv_res_t lv_gpu_nxp_vglite_fill(lv_color_t * dest_buf, lv_coord_t dest_width, lv lv_color32_t col32 = {.full = lv_color_to32(color)}; /*Convert color to RGBA8888*/ lv_disp_t * disp = _lv_refr_get_disp_refreshing(); - if(init_vg_buf(&rt, dest_width, dest_height, dest_width * sizeof(lv_color_t), dest_buf) != LV_RES_OK) { + if(_init_vg_buf(&rt, (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) { #if LV_GPU_NXP_VG_LITE_LOG_ERRORS LV_LOG_ERROR("init_vg_buf reported error. Fill failed."); #endif return LV_RES_INV; } - if(opa >= LV_OPA_MAX) { /*Opaque fill*/ + if(opa >= (lv_opa_t) LV_OPA_MAX) { /*Opaque fill*/ rect.x = fill_area->x1; rect.y = fill_area->y1; - rect.width = (fill_area->x2 - fill_area->x1) + 1; - rect.height = (fill_area->y2 - fill_area->y1) + 1; + rect.width = (int32_t) fill_area->x2 - (int32_t) fill_area->x1 + 1; + rect.height = (int32_t) fill_area->y2 - (int32_t) fill_area->y1 + 1; - if(disp && disp->driver->clean_dcache_cb) { /*Clean & invalidate cache*/ + if(disp != NULL && disp->driver->clean_dcache_cb != NULL) { /*Clean & invalidate cache*/ disp->driver->clean_dcache_cb(disp->driver); } - err |= vg_lite_clear(&rt, &rect, col32.full); - err |= vg_lite_finish(); + err = vg_lite_clear(&rt, &rect, col32.full); + if (err != VG_LITE_SUCCESS) { + #if LV_GPU_NXP_VG_LITE_LOG_ERRORS + LV_LOG_ERROR("vg_lite_clear reported error. Fill failed."); + #endif + return LV_RES_INV; + } + err = vg_lite_finish(); + if (err != VG_LITE_SUCCESS) { + #if LV_GPU_NXP_VG_LITE_LOG_ERRORS + LV_LOG_ERROR("vg_lite_finish reported error. Fill failed."); + #endif + return LV_RES_INV; + } } else { /*fill with transparency*/ @@ -127,8 +198,8 @@ lv_res_t lv_gpu_nxp_vglite_fill(lv_color_t * dest_buf, lv_coord_t dest_width, lv VLC_OP_END }; - err |= vg_lite_init_path(&path, VG_LITE_S16, VG_LITE_LOW, sizeof(path_data), path_data, - fill_area->x1, fill_area->y1, fill_area->x2 + 1, fill_area->y2 + 1); + err = vg_lite_init_path(&path, VG_LITE_S16, 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); if(err != VG_LITE_SUCCESS) { #if LV_GPU_NXP_VG_LITE_LOG_ERRORS LV_LOG_ERROR("vg_lite_init_path() failed."); @@ -136,12 +207,12 @@ lv_res_t lv_gpu_nxp_vglite_fill(lv_color_t * dest_buf, lv_coord_t dest_width, lv return LV_RES_INV; } - colMix.ch.red = ((uint16_t)col32.ch.red * opa) >> 8; /*Pre-multiply color*/ - colMix.ch.green = ((uint16_t)col32.ch.green * opa) >> 8; - colMix.ch.blue = ((uint16_t)col32.ch.blue * opa) >> 8; + colMix.ch.red = (uint8_t)(((uint16_t)col32.ch.red * opa) >> 8); /*Pre-multiply color*/ + colMix.ch.green = (uint8_t)(((uint16_t)col32.ch.green * opa) >> 8); + colMix.ch.blue = (uint8_t)(((uint16_t)col32.ch.blue * opa) >> 8); colMix.ch.alpha = opa; - if(disp && disp->driver->clean_dcache_cb) { /*Clean & invalidate cache*/ + if((disp != NULL) && (disp->driver->clean_dcache_cb != NULL)) { /*Clean & invalidate cache*/ disp->driver->clean_dcache_cb(disp->driver); } @@ -149,8 +220,8 @@ lv_res_t lv_gpu_nxp_vglite_fill(lv_color_t * dest_buf, lv_coord_t dest_width, lv vg_lite_identity(&matrix); /*Draw rectangle*/ - err |= vg_lite_draw(&rt, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, colMix.full); - if(err) { + err = vg_lite_draw(&rt, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, colMix.full); + if(err != VG_LITE_SUCCESS) { #if LV_GPU_NXP_VG_LITE_LOG_ERRORS LV_LOG_ERROR("vg_lite_draw() failed."); #endif @@ -158,8 +229,21 @@ lv_res_t lv_gpu_nxp_vglite_fill(lv_color_t * dest_buf, lv_coord_t dest_width, lv return LV_RES_INV; } - err |= vg_lite_finish(); - err |= vg_lite_clear_path(&path); + err = vg_lite_finish(); + if(err != VG_LITE_SUCCESS) { +#if LV_GPU_NXP_VG_LITE_LOG_ERRORS + LV_LOG_ERROR("vg_lite_finish() failed."); +#endif + return LV_RES_INV; + } + + err = vg_lite_clear_path(&path); + if(err != VG_LITE_SUCCESS) { +#if LV_GPU_NXP_VG_LITE_LOG_ERRORS + LV_LOG_ERROR("vg_lite_clear_path() failed."); +#endif + return LV_RES_INV; + } } if(err == VG_LITE_SUCCESS) { @@ -180,63 +264,255 @@ lv_res_t lv_gpu_nxp_vglite_fill(lv_color_t * dest_buf, lv_coord_t dest_width, lv * @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) +{ +#if _BLIT_SPLIT_ENABLED + + 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; + } + + 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 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); + }; + + /* 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); + + + uint32_t totalWidth = lv_area_get_width(&blit->src_area); + uint32_t totalHeight = lv_area_get_height(&blit->src_area); + + lv_gpu_nxp_vglite_blit_info_t tileBlit; + + /* 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; + + /* 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; + + PRINT_BLT("\n"); + PRINT_BLT("Align shift: src: %d, dst: %d\n", shiftSrcX, shiftDstX); + + tileBlit = *blit; + + for(int tileY = 0; tileY < totalTilesY; tileY++) { + + 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 */ + } + tileBlit.src = blit->src + tileY * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR * blit->src_stride / sizeof( + lv_color_t); /* stride in px! */ + + 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; + + tileBlit.dst = blit->dst + tileY * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR * blit->dst_stride / sizeof( + lv_color_t); /* stride in px! */ + + for(int tileX = 0; tileX < totalTilesX; tileX++) { + + if(tileX == 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. + * 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; + } + else { + /* subsequent tiles always starts from 0, but shifted*/ + tileBlit.src_area.x1 = 0 + shiftSrcX; + tileBlit.dst_area.x1 = 0 + shiftDstX; + /* 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; + } + + /* 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; + } + + 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; + } + + 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; + } + + rv = _lv_gpu_nxp_vglite_blit_single(&tileBlit); + +#if BLIT_DBG_AREAS + _draw_rectangle((lv_color_t *) tileBlit.dst, tileBlit.dst_width, tileBlit.dst_height, &tileBlit.dst_area, LV_COLOR_RED); + _draw_rectangle((lv_color_t *) tileBlit.src, tileBlit.src_width, tileBlit.src_height, &tileBlit.src_area, + LV_COLOR_GREEN); +#endif + + PRINT_BLT("Tile [%d, %d]: " + "([%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 !!!"); + + 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 */ + } + + } + PRINT_BLT(" \n"); + } + + return rv; /* should never fail */ + +#else /* non RT595 */ + /* Just pass down */ + return _lv_gpu_nxp_vglite_blit_single(blit); +#endif +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +/*** + * BLock Image Transfer - single direct BLIT. + * @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) { vg_lite_buffer_t src_vgbuf, dst_vgbuf; vg_lite_error_t err = VG_LITE_SUCCESS; uint32_t rect[4]; lv_disp_t * disp = _lv_refr_get_disp_refreshing(); - if(blit->opa < LV_OPA_MIN) { + 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*/ } - if(!blit) { - /*Wrong parameter*/ - return LV_RES_INV; - } - /*Wrap src/dst buffer into VG-Lite buffer*/ - if(init_vg_buf(&src_vgbuf, blit->src_width, blit->src_height, blit->src_stride, blit->src) != LV_RES_OK) { + if(_init_vg_buf(&src_vgbuf, (uint32_t) blit->src_width, (uint32_t) blit->src_height, (uint32_t) blit->src_stride, blit->src, true) != LV_RES_OK) { #if LV_GPU_NXP_VG_LITE_LOG_ERRORS LV_LOG_ERROR("init_vg_buf reported error. BLIT failed."); #endif return LV_RES_INV; } - if(init_vg_buf(&dst_vgbuf, blit->dst_width, blit->dst_height, blit->dst_stride, blit->dst) != LV_RES_OK) { + if(_init_vg_buf(&dst_vgbuf, (uint32_t) blit->dst_width, (uint32_t) blit->dst_height, (uint32_t) blit->dst_stride, blit->dst, false) != LV_RES_OK) { #if LV_GPU_NXP_VG_LITE_LOG_ERRORS LV_LOG_ERROR("init_vg_buf reported error. BLIT failed."); #endif return LV_RES_INV; } - rect[0] = 0; /*Crop*/ - rect[1] = 0; - rect[2] = blit->src_width; - rect[3] = blit->src_height; + 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(blit->dst_area.x1, blit->dst_area.y1, &matrix); + vg_lite_translate((vg_lite_float_t)blit->dst_area.x1, (vg_lite_float_t)blit->dst_area.y1, &matrix); - if(disp && disp->driver->clean_dcache_cb) { /*Clean & invalidate cache*/ + if((disp != NULL) && (disp->driver->clean_dcache_cb != NULL)) { /*Clean & invalidate cache*/ disp->driver->clean_dcache_cb(disp->driver); } uint32_t color; vg_lite_blend_t blend; - if(blit->opa >= LV_OPA_MAX) { + if(blit->opa >= (uint8_t) LV_OPA_MAX) { color = 0x0; blend = VG_LITE_BLEND_NONE; } else { - color = ((blit->opa) << 24) | ((blit->opa) << 16) | ((blit->opa) << 8) | (blit->opa); + uint32_t opa = (uint32_t) blit->opa; + color = (opa << 24) | (opa << 16) | (opa << 8) | opa; blend = VG_LITE_BLEND_SRC_OVER; src_vgbuf.image_mode = VG_LITE_MULTIPLY_IMAGE_MODE; } - err |= vg_lite_blit_rect(&dst_vgbuf, &src_vgbuf, rect, &matrix, blend, color, VG_LITE_FILTER_POINT); - err |= vg_lite_finish(); + err = vg_lite_blit_rect(&dst_vgbuf, &src_vgbuf, rect, &matrix, blend, color, VG_LITE_FILTER_POINT); + if(err != VG_LITE_SUCCESS) { +#if LV_GPU_NXP_VG_LITE_LOG_ERRORS + LV_LOG_ERROR("vg_lite_blit_rect() failed."); +#endif + return LV_RES_INV; + } + + err = vg_lite_finish(); + if(err != VG_LITE_SUCCESS) { +#if LV_GPU_NXP_VG_LITE_LOG_ERRORS + LV_LOG_ERROR("vg_lite_finish() failed."); +#endif + return LV_RES_INV; + } if(err == VG_LITE_SUCCESS) { return LV_RES_OK; @@ -249,10 +525,6 @@ lv_res_t lv_gpu_nxp_vglite_blit(lv_gpu_nxp_vglite_blit_info_t * blit) } } -/********************** - * STATIC FUNCTIONS - **********************/ - /*** * Fills vg_lite_buffer_t structure according given parameters. * @param[out] dst Buffer structure to be filled @@ -261,19 +533,19 @@ lv_res_t lv_gpu_nxp_vglite_blit(lv_gpu_nxp_vglite_blit_info_t * blit) * @param[in] stride Stride of the buffer in bytes * @param[in] ptr Pointer to the buffer (must be aligned according VG-Lite requirements) */ -static lv_res_t init_vg_buf(vg_lite_buffer_t * dst, uint32_t width, uint32_t height, uint32_t stride, - const lv_color_t * ptr) +static lv_res_t _init_vg_buf(vg_lite_buffer_t * dst, uint32_t width, uint32_t height, uint32_t stride, + const lv_color_t * ptr, bool source) { - if((((uintptr_t)ptr) % LV_ATTRIBUTE_MEM_ALIGN_SIZE) != 0x0) { /*Test for alignment*/ + if((((uintptr_t)ptr) % (uintptr_t)LV_ATTRIBUTE_MEM_ALIGN_SIZE) != 0x0U) { /*Test for alignment*/ #if LV_GPU_NXP_VG_LITE_LOG_ERRORS LV_LOG_ERROR("ptr (0x%X) not aligned to %d.", (size_t) ptr, LV_ATTRIBUTE_MEM_ALIGN_SIZE); #endif return LV_RES_INV; } - if((stride % LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX) != 0x0) { /*Test for stride alignment*/ + if(source && (stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * sizeof(lv_color_t))) != 0x0U) { /*Test for stride alignment*/ #if LV_GPU_NXP_VG_LITE_LOG_ERRORS - LV_LOG_ERROR("Buffer stride (%d px) not aligned to %d px.", stride, LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); + LV_LOG_ERROR("Buffer stride (%d px) not aligned to %d bytes.", stride, LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * sizeof(lv_color_t)); #endif return LV_RES_INV; } @@ -283,17 +555,205 @@ static lv_res_t init_vg_buf(vg_lite_buffer_t * dst, uint32_t width, uint32_t hei dst->image_mode = VG_LITE_NORMAL_IMAGE_MODE; dst->transparency_mode = VG_LITE_IMAGE_OPAQUE; - dst->width = width; - dst->height = height; - dst->stride = stride; + dst->width = (int32_t) width; + dst->height = (int32_t) height; + dst->stride = (int32_t) stride; - memset(&dst->yuv, 0, sizeof(dst->yuv)); + void *r_ptr = memset(&dst->yuv, 0, sizeof(dst->yuv)); + if (r_ptr == NULL) { + return LV_RES_INV; + } dst->memory = (void *)ptr; dst->address = (uint32_t) dst->memory; - dst->handle = 0x0; + dst->handle = NULL; return LV_RES_OK; } +#if _BLIT_SPLIT_ENABLED + +/** + * Software BLIT as a fall-back scenario + * @param[in] blit BLIT configuration + */ +static void _sw_blit(lv_gpu_nxp_vglite_blit_info_t * blit) +{ + 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); + + uint32_t srcStridePx = blit->src_stride / sizeof(lv_color_t); + uint32_t dstStridePx = blit->dst_stride / 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_MAX) { + /* simple copy */ + for(y = 0; y < h; y++) { + _lv_memcpy(dst, src, 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; + } + } +} + +/** + * Verify BLIT structure - widths, stride, pointer alignment + * @param[in] blit + * @return + */ +static lv_res_t _lv_gpu_nxp_vglite_check_blit(lv_gpu_nxp_vglite_blit_info_t * blit) +{ + + if(lv_area_get_width(&blit->src_area) < LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX) { /* Test for minimal width */ +#if LV_GPU_NXP_VG_LITE_LOG_ERRORS + LV_LOG_ERROR("source area width (%d) is smaller than required (%d).", lv_area_get_width(&blit->src_area), + LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); +#endif + return LV_RES_INV; + } + + if(lv_area_get_width(&blit->dst_area) < LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX) { /* Test for minimal width */ +#if LV_GPU_NXP_VG_LITE_LOG_ERRORS + LV_LOG_ERROR("destination area width (%d) is smaller than required (%d).", lv_area_get_width(&blit->dst_area), + LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); +#endif + return LV_RES_INV; + } + + if((((uintptr_t) blit->src) % LV_ATTRIBUTE_MEM_ALIGN_SIZE) != 0x0) { /* Test for pointer alignment */ +#if LV_GPU_NXP_VG_LITE_LOG_ERRORS + LV_LOG_ERROR("source buffer ptr (0x%X) not aligned to %d.", (size_t) blit->src, LV_ATTRIBUTE_MEM_ALIGN_SIZE); +#endif + return LV_RES_INV; + } + /* No alignment requirement for destination pixel buffer when using mode VG_LITE_LINEAR */ + + if((blit->src_stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * LV_COLOR_DEPTH / 8)) != 0x0) { /* Test for stride alignment */ +#if LV_GPU_NXP_VG_LITE_LOG_ERRORS + LV_LOG_ERROR("source buffer stride (%d px) not aligned to %d px.", blit->src_stride, LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); +#endif + return LV_RES_INV; + } + + if((blit->dst_stride % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * LV_COLOR_DEPTH / 8)) != 0x0) { /* Test for stride alignment */ +#if LV_GPU_NXP_VG_LITE_LOG_ERRORS + LV_LOG_ERROR("destination buffer stride (%d px) not aligned to %d px.", blit->dst_stride, LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); +#endif + return LV_RES_INV; + } + + 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))) { +#if LV_GPU_NXP_VG_LITE_LOG_ERRORS + LV_LOG_ERROR("source and destination buffer areas are not equal."); +#endif + return LV_RES_INV; + } + + return LV_RES_OK; +} + +/*** + * 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) +{ + + int alignedAreaStartPx = area->x1 - (area->x1 % (LV_ATTRIBUTE_MEM_ALIGN_SIZE * 8 / LV_COLOR_DEPTH) ); + CHECK(alignedAreaStartPx < 0, "Should never happen."); + + area->x1 -= alignedAreaStartPx; + area->x2 -= alignedAreaStartPx; + *buf += alignedAreaStartPx; +} + +/*** + * 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) +{ + int LineToAlignMem; + int alignedAreaStartPy; + /* find how many lines of pixels will respect memory alignment requirement */ + if(stridePx % LV_ATTRIBUTE_MEM_ALIGN_SIZE == 0) { + alignedAreaStartPy = area->y1; + } else { + LineToAlignMem = LV_ATTRIBUTE_MEM_ALIGN_SIZE / (sizeof(lv_color_t) * LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); + CHECK(LV_ATTRIBUTE_MEM_ALIGN_SIZE % (sizeof(lv_color_t) * LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX) != 0, "Complex case: need gcd function."); + alignedAreaStartPy = area->y1 - (area->y1 % LineToAlignMem); + CHECK(alignedAreaStartPy < 0, "Should never happen."); + } + + area->y1 -= alignedAreaStartPy; + area->y2 -= alignedAreaStartPy; + *buf += alignedAreaStartPy * stridePx; +} + +#if BLIT_DBG_AREAS +/*** + * Draws a simple rectangle, 1 px line width. + * @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 + */ +static void _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 */ + +#endif /* _BLIT_SPLIT_ENABLED */ + #endif /*LV_USE_GPU_NXP_VG_LITE*/ diff --git a/src/gpu/lv_gpu_nxp_vglite.h b/src/gpu/lv_gpu_nxp_vglite.h index 3f8b71734..31416598e 100644 --- a/src/gpu/lv_gpu_nxp_vglite.h +++ b/src/gpu/lv_gpu_nxp_vglite.h @@ -43,8 +43,11 @@ extern "C" { * DEFINES *********************/ -/** Stride in px required by VG-Lite HW. Don't change this.*/ -#define LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX 16 +/** 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_FILL_SIZE_LIMIT /** Minimum area (in pixels) to be filled by VG-Lite with 100% opacity*/ @@ -61,6 +64,11 @@ extern "C" { #define LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT 32 #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 32 +#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 32 From 00c3eb197cb85e480809d97eb722589d75d81d94 Mon Sep 17 00:00:00 2001 From: Seb Fagard Date: Tue, 16 Mar 2021 16:42:01 +0100 Subject: [PATCH 10/17] fix(pxp): update RTOS macro for SDK 2.10 replace FSL_RTOS_FREE_RTOS by SDK_OS_FREE_RTOS in order to be aligned with MCU SDK 2.10. See MCUX-41577. Signed-off-by: Seb Fagard --- Kconfig | 2 +- lv_conf_template.h | 2 +- src/gpu/lv_gpu_nxp_pxp_osa.c | 16 ++++++++-------- src/lv_conf_internal.h | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Kconfig b/Kconfig index f509d9654..f0e629532 100644 --- a/Kconfig +++ b/Kconfig @@ -166,7 +166,7 @@ menu "LVGL configuration" 1: Add default bare metal and FreeRTOS interrupt handling routines for PXP (lv_gpu_nxp_pxp_osa.c) and call lv_gpu_nxp_pxp_init() automatically during lv_init(). - Note that symbol FSL_RTOS_FREE_RTOS has to be defined in order + Note that symbol SDK_OS_FREE_RTOS has to be defined in order to use FreeRTOS OSA, otherwise bare-metal implementation is selected. 0: lv_gpu_nxp_pxp_init() has to be called manually before diff --git a/lv_conf_template.h b/lv_conf_template.h index 36a380cba..2e2f7e36a 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -122,7 +122,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ #define LV_USE_GPU_NXP_PXP 0 #if LV_USE_GPU_NXP_PXP /*1: Add default bare metal and FreeRTOS interrupt handling routines for PXP (lv_gpu_nxp_pxp_osa.c) - * and call lv_gpu_nxp_pxp_init() automatically during lv_init(). Note that symbol FSL_RTOS_FREE_RTOS + * and call lv_gpu_nxp_pxp_init() automatically during lv_init(). Note that symbol SDK_OS_FREE_RTOS * has to be defined in order to use FreeRTOS OSA, otherwise bare-metal implementation is selected. *0: lv_gpu_nxp_pxp_init() has to be called manually before lv_init() */ diff --git a/src/gpu/lv_gpu_nxp_pxp_osa.c b/src/gpu/lv_gpu_nxp_pxp_osa.c index 5a16db864..d247f2b74 100644 --- a/src/gpu/lv_gpu_nxp_pxp_osa.c +++ b/src/gpu/lv_gpu_nxp_pxp_osa.c @@ -39,7 +39,7 @@ #include "lv_gpu_nxp_pxp.h" #include "fsl_pxp.h" -#if defined(FSL_RTOS_FREE_RTOS) +#if defined(SDK_OS_FREE_RTOS) #include "FreeRTOS.h" #include "semphr.h" #endif @@ -63,7 +63,7 @@ static void _lv_gpu_nxp_pxp_run(void); * STATIC VARIABLES **********************/ -#if defined(FSL_RTOS_FREE_RTOS) +#if defined(SDK_OS_FREE_RTOS) static SemaphoreHandle_t s_pxpIdle; #else static volatile bool s_pxpIdle; @@ -82,13 +82,13 @@ static void _lv_gpu_nxp_pxp_run(void); */ void PXP_IRQHandler(void) { -#if defined(FSL_RTOS_FREE_RTOS) +#if defined(SDK_OS_FREE_RTOS) BaseType_t taskAwake = pdFALSE; #endif if(kPXP_CompleteFlag & PXP_GetStatusFlags(LV_GPU_NXP_PXP_ID)) { PXP_ClearStatusFlags(LV_GPU_NXP_PXP_ID, kPXP_CompleteFlag); -#if defined(FSL_RTOS_FREE_RTOS) +#if defined(SDK_OS_FREE_RTOS) xSemaphoreGiveFromISR(s_pxpIdle, &taskAwake); portYIELD_FROM_ISR(taskAwake); #else @@ -107,7 +107,7 @@ void PXP_IRQHandler(void) */ static lv_res_t _lv_gpu_nxp_pxp_interrupt_init(void) { -#if defined(FSL_RTOS_FREE_RTOS) +#if defined(SDK_OS_FREE_RTOS) s_pxpIdle = xSemaphoreCreateBinary(); if(s_pxpIdle == NULL) { return LV_RES_INV; @@ -129,7 +129,7 @@ static lv_res_t _lv_gpu_nxp_pxp_interrupt_init(void) static void _lv_gpu_nxp_pxp_interrupt_deinit(void) { NVIC_DisableIRQ(LV_GPU_NXP_PXP_IRQ_ID); -#if defined(FSL_RTOS_FREE_RTOS) +#if defined(SDK_OS_FREE_RTOS) vSemaphoreDelete(s_pxpIdle); #endif } @@ -139,14 +139,14 @@ static void _lv_gpu_nxp_pxp_interrupt_deinit(void) */ static void _lv_gpu_nxp_pxp_run(void) { -#if !defined(FSL_RTOS_FREE_RTOS) +#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); -#if defined(FSL_RTOS_FREE_RTOS) +#if defined(SDK_OS_FREE_RTOS) if(xSemaphoreTake(s_pxpIdle, portMAX_DELAY) != pdTRUE) { LV_LOG_ERROR("xSemaphoreTake error. Task halted."); for(; ;) ; diff --git a/src/lv_conf_internal.h b/src/lv_conf_internal.h index 8f8a58691..6abd8bdc6 100644 --- a/src/lv_conf_internal.h +++ b/src/lv_conf_internal.h @@ -307,7 +307,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ #endif #if LV_USE_GPU_NXP_PXP /*1: Add default bare metal and FreeRTOS interrupt handling routines for PXP (lv_gpu_nxp_pxp_osa.c) - * and call lv_gpu_nxp_pxp_init() automatically during lv_init(). Note that symbol FSL_RTOS_FREE_RTOS + * and call lv_gpu_nxp_pxp_init() automatically during lv_init(). Note that symbol SDK_OS_FREE_RTOS * has to be defined in order to use FreeRTOS OSA, otherwise bare-metal implementation is selected. *0: lv_gpu_nxp_pxp_init() has to be called manually before lv_init() */ From 1d0c53118e5be46f0d9364c8f44a914eb30f5c35 Mon Sep 17 00:00:00 2001 From: Duco Sebel <74970928+DCSBL@users.noreply.github.com> Date: Mon, 21 Jun 2021 14:46:34 +0200 Subject: [PATCH 11/17] docs(README) fix broken references (#2329) --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index e48e5e39c..12e4184cc 100644 --- a/README.md +++ b/README.md @@ -115,14 +115,14 @@ LVGL is also avaiable as: This list shows the recommended way of learning the library: 1. Check the [Online demos](https://lvgl.io/demos) to see LVGL in action (3 minutes) 2. Read the [Introduction](https://docs.lvgl.io/master/intro/index.html) page of the documentation (5 minutes) -3. Get familiar with the basics on the [Quick overview](https://docs.lvgl.io/master/html/get-started/quick-overview.html) page (15 minutes) -4. Set up a [Simulator](https://docs.lvgl.io/latest/master/get-started/pc-simulator.html) (10 minutes) +3. Get familiar with the basics on the [Quick overview](https://docs.lvgl.io/master/get-started/quick-overview.html) page (15 minutes) +4. Set up a [Simulator](https://docs.lvgl.io/master/get-started/pc-simulator.html) (10 minutes) 5. Try out some [Examples](https://github.com/lvgl/lvgl/tree/master/examples) -6. Port LVGL to a board. See the [Porting](https://docs.lvgl.io/master/porting/index.html) guide or check the ready to use [Projects](https://github.com/lvgl?q=lv_port_&type=&language=) +6. Port LVGL to a board. See the [Porting](https://docs.lvgl.io/master/porting/index.html) guide or check the ready to use [Projects](https://github.com/lvgl?q=lv_port_) 7. Read the [Overview](https://docs.lvgl.io/master/overview/index.html) page to get a better understanding of the library (2-3 hours) -8. Check the documentation of the [Widgets](https://docs.lvgl.io/master/html/widgets/index.html) to see their features and usage +8. Check the documentation of the [Widgets](https://docs.lvgl.io/master/widgets/index.html) to see their features and usage 9. If you have questions go to the [Forum](http://forum.lvgl.io/) -10. Read the [Contributing](https://docs.lvgl.io/master/contributing/index.html) guide to see how you can help to improve LVGL (15 minutes) +10. Read the [Contributing](https://docs.lvgl.io/master/CONTRIBUTING.html) guide to see how you can help to improve LVGL (15 minutes) ## Examples @@ -177,5 +177,5 @@ Feel free to contact us if you have any questions. ## Contributing LVGL is an open project and contribution is very welcome. There are many ways to contribute from simply speaking about your project, through writing examples, improving the documentation, fixing bugs to hosing your own project under the LVGL organization. -For a detailed description of contribution opportunities visit the [Contributing](https://docs.lvgl.io/master/CONTRIBUTING.htmll) section of the documentation. +For a detailed description of contribution opportunities visit the [Contributing](https://docs.lvgl.io/master/CONTRIBUTING.html) section of the documentation. From 52d1c2e5b53eda4270abc0caa0eb309b35c010c8 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Mon, 21 Jun 2021 10:27:40 -0400 Subject: [PATCH 12/17] fix(examples) adjust canvas example for MicroPython API change --- examples/widgets/canvas/lv_example_canvas_1.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/widgets/canvas/lv_example_canvas_1.py b/examples/widgets/canvas/lv_example_canvas_1.py index 3c3709f69..895a41e45 100644 --- a/examples/widgets/canvas/lv_example_canvas_1.py +++ b/examples/widgets/canvas/lv_example_canvas_1.py @@ -39,5 +39,5 @@ img.header.cf = lv.img.CF.TRUE_COLOR img.header.w = _CANVAS_WIDTH img.header.h = _CANVAS_HEIGHT -canvas.fill_bg(lv_palette_lighten(LV_PALETTE_GREY, 3), LV_OPA_COVER) +canvas.fill_bg(lv.palette_lighten(lv.PALETTE.GREY, 3), lv.OPA.COVER) canvas.transform(img, 30, LV_IMG_ZOOM_NONE, 0, 0, _CANVAS_WIDTH // 2, _CANVAS_HEIGHT // 2, True); From 713b39ecdb7e8e219cc295bad7d953ff2136f138 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 22 Jun 2021 10:05:47 +0200 Subject: [PATCH 13/17] fix(obj, switch) do not send LV_EVENT_VALUE_CHANGED twice fixes #2330 --- src/core/lv_obj.c | 8 ++++++-- src/widgets/lv_switch.c | 4 ---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/core/lv_obj.c b/src/core/lv_obj.c index 9dada7aef..31f1afd72 100644 --- a/src/core/lv_obj.c +++ b/src/core/lv_obj.c @@ -647,8 +647,12 @@ static void lv_obj_event(const lv_obj_class_t * class_p, lv_event_t * e) else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) { lv_obj_clear_state(obj, LV_STATE_CHECKED); } - lv_res_t res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return; + + /*With Enter LV_EVENT_RELEASED will send VALUE_CHANGE event*/ + if(c != LV_KEY_ENTER) { + lv_res_t res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return; + } } } else if(code == LV_EVENT_FOCUSED) { diff --git a/src/widgets/lv_switch.c b/src/widgets/lv_switch.c index 21b7608fd..0a4b55bcf 100644 --- a/src/widgets/lv_switch.c +++ b/src/widgets/lv_switch.c @@ -112,10 +112,6 @@ static void lv_switch_event(const lv_obj_class_t * class_p, lv_event_t * e) *s = LV_MAX(*s, lv_obj_calculate_ext_draw_size(obj, LV_PART_INDICATOR)); } else if(code == LV_EVENT_CLICKED) { - uint32_t v = lv_obj_get_state(obj) & LV_STATE_CHECKED ? 1 : 0; - res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, &v); - if(res != LV_RES_OK) return; - lv_obj_invalidate(obj); } else if(code == LV_EVENT_DRAW_MAIN) { From 97ba12f280f0fa5400ff18c5317b9736063d8391 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 22 Jun 2021 10:26:37 +0200 Subject: [PATCH 14/17] fix(flex) fix NULL pointer dereference fixes #2331 --- src/extra/layouts/flex/lv_flex.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/extra/layouts/flex/lv_flex.c b/src/extra/layouts/flex/lv_flex.c index d18ed7818..5d6411529 100644 --- a/src/extra/layouts/flex/lv_flex.c +++ b/src/extra/layouts/flex/lv_flex.c @@ -342,8 +342,10 @@ static int32_t find_track_end(lv_obj_t * cont, flex_t * f, int32_t item_start_id LV_ASSERT_MALLOC(new_dsc); if(new_dsc == NULL) return item_id; - lv_memcpy(new_dsc, t->grow_dsc, sizeof(grow_dsc_t) * (t->grow_item_cnt - 1)); - lv_mem_buf_release(t->grow_dsc); + if(t->grow_dsc) { + lv_memcpy(new_dsc, t->grow_dsc, sizeof(grow_dsc_t) * (t->grow_item_cnt - 1)); + lv_mem_buf_release(t->grow_dsc); + } new_dsc[t->grow_item_cnt - 1].item = item; new_dsc[t->grow_item_cnt - 1].min_size = f->row ? lv_obj_get_style_min_width(item, LV_PART_MAIN) : lv_obj_get_style_min_height(item, LV_PART_MAIN); new_dsc[t->grow_item_cnt - 1].max_size = f->row ? lv_obj_get_style_max_width(item, LV_PART_MAIN) : lv_obj_get_style_max_height(item, LV_PART_MAIN); From 5bd82b038b841c0f7c93bbdacdbd61d6b9585846 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 22 Jun 2021 11:08:33 +0200 Subject: [PATCH 15/17] fix(flex) fix layout update and invalidation issues --- src/extra/layouts/flex/lv_flex.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/extra/layouts/flex/lv_flex.c b/src/extra/layouts/flex/lv_flex.c index 5d6411529..c618d16f1 100644 --- a/src/extra/layouts/flex/lv_flex.c +++ b/src/extra/layouts/flex/lv_flex.c @@ -113,6 +113,7 @@ void lv_obj_set_flex_align(lv_obj_t * obj, lv_flex_align_t main_place, lv_flex_a void lv_obj_set_flex_grow(lv_obj_t * obj, uint8_t grow) { lv_obj_set_style_flex_grow(obj, grow, 0); + lv_obj_mark_layout_as_dirty(lv_obj_get_parent(obj)); } @@ -455,16 +456,16 @@ static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, i break; } } - lv_area_t old_coords; - lv_area_copy(&old_coords, &item->coords); - - area_set_main_size(&item->coords, s); if(f->row) item->w_layout = 1; else item->h_layout = 1; - if(area_get_main_size(&old_coords) != area_get_main_size(&item->coords)) { + if(s != area_get_main_size(&item->coords)) { lv_obj_invalidate(item); + + lv_area_t old_coords; + lv_area_copy(&old_coords, &item->coords); + area_set_main_size(&item->coords, s); lv_event_send(item, LV_EVENT_SIZE_CHANGED, &old_coords); lv_event_send(lv_obj_get_parent(item), LV_EVENT_CHILD_CHANGED, item); lv_obj_invalidate(item); From 973a4e08d51e5ff55eae4e95bcdf8a1416ca66aa Mon Sep 17 00:00:00 2001 From: guoweilkd <35251456+guoweilkd@users.noreply.github.com> Date: Tue, 22 Jun 2021 20:42:39 +0800 Subject: [PATCH 16/17] fix(txt) enhance the function of break_chars (#2327) Co-authored-by: guowei15 --- src/extra/widgets/span/lv_span.c | 25 ++++--------------------- src/misc/lv_txt.c | 28 +--------------------------- src/misc/lv_txt.h | 26 ++++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 48 deletions(-) diff --git a/src/extra/widgets/span/lv_span.c b/src/extra/widgets/span/lv_span.c index ad40baaa1..412cddce5 100644 --- a/src/extra/widgets/span/lv_span.c +++ b/src/extra/widgets/span/lv_span.c @@ -50,7 +50,6 @@ static lv_opa_t lv_span_get_style_text_blend_mode(lv_obj_t * par, lv_span_t * sp static int32_t lv_span_get_style_text_decor(lv_obj_t * par, lv_span_t * span); static inline void span_text_check(const char ** text); -static inline bool is_break_char(uint32_t letter); static void get_txt_coords(const lv_obj_t * span, lv_area_t * area); static void lv_draw_span(lv_obj_t * spans, const lv_area_t * coords, const lv_area_t * mask); static bool lv_txt_get_snippet(const char * txt, const lv_font_t * font, lv_coord_t letter_space, @@ -442,9 +441,9 @@ lv_coord_t lv_spangroup_get_expand_height(lv_obj_t * obj, lv_coord_t width) /* break word deal width */ if(isfill && next_ofs > 0 && snippet_cnt > 0) { uint32_t letter = (uint32_t)cur_txt[cur_txt_ofs + next_ofs - 1]; - if(!(letter == '\0' || letter == '\n' || letter == '\r' || is_break_char(letter))) { + if(!(letter == '\0' || letter == '\n' || letter == '\r' || _lv_txt_is_break_char(letter))) { letter = (uint32_t)cur_txt[cur_txt_ofs + next_ofs]; - if(!(letter == '\0' || letter == '\n' || letter == '\r' || is_break_char(letter))) { + if(!(letter == '\0' || letter == '\n' || letter == '\r' || _lv_txt_is_break_char(letter))) { break; } } @@ -694,22 +693,6 @@ static inline void span_text_check(const char ** text) } } -static inline bool is_break_char(uint32_t letter) -{ - uint8_t i; - bool ret = false; - - /*Compare the letter to TXT_BREAK_CHARS*/ - for(i = 0; LV_TXT_BREAK_CHARS[i] != '\0'; i++) { - if(letter == (uint32_t)LV_TXT_BREAK_CHARS[i]) { - ret = true; /*If match then it is break char*/ - break; - } - } - - return ret; -} - /** * draw span group * @param spans obj handle @@ -788,9 +771,9 @@ static void lv_draw_span(lv_obj_t * obj, const lv_area_t * coords, const lv_area /* break word deal width */ if(isfill && next_ofs > 0 && lv_get_snippet_cnt() > 0) { uint32_t letter = (uint32_t)cur_txt[cur_txt_ofs + next_ofs - 1]; - if(!(letter == '\0' || letter == '\n' || letter == '\r' || is_break_char(letter))) { + if(!(letter == '\0' || letter == '\n' || letter == '\r' || _lv_txt_is_break_char(letter))) { letter = (uint32_t)cur_txt[cur_txt_ofs + next_ofs]; - if(!(letter == '\0' || letter == '\n' || letter == '\r' || is_break_char(letter))) { + if(!(letter == '\0' || letter == '\n' || letter == '\r' || _lv_txt_is_break_char(letter))) { break; } } diff --git a/src/misc/lv_txt.c b/src/misc/lv_txt.c index fa2bf0be9..10dcd1a0c 100644 --- a/src/misc/lv_txt.c +++ b/src/misc/lv_txt.c @@ -26,7 +26,6 @@ /********************** * STATIC PROTOTYPES **********************/ -static inline bool is_break_char(uint32_t letter); #if LV_TXT_ENC == LV_TXT_ENC_UTF8 static uint8_t lv_txt_utf8_size(const char * str); @@ -224,7 +223,7 @@ static uint32_t lv_txt_get_next_word(const char * txt, const lv_font_t * font, } /*Check for new line chars and breakchars*/ - if(letter == '\n' || letter == '\r' || is_break_char(letter)) { + if(letter == '\n' || letter == '\r' || _lv_txt_is_break_char(letter)) { /*Update the output width on the first character if it fits. *Must do this here in case first letter is a break character.*/ if(i == 0 && break_index == NO_BREAK_FOUND && word_w_ptr != NULL) *word_w_ptr = cur_w; @@ -895,28 +894,3 @@ static uint32_t lv_txt_iso8859_1_get_length(const char * txt) #error "Invalid character encoding. See `LV_TXT_ENC` in `lv_conf.h`" #endif - -/********************** - * STATIC FUNCTIONS - **********************/ - -/** - * Test if char is break char or not (a text can broken here or not) - * @param letter a letter - * @return false: 'letter' is not break char - */ -static inline bool is_break_char(uint32_t letter) -{ - uint8_t i; - bool ret = false; - - /*Compare the letter to TXT_BREAK_CHARS*/ - for(i = 0; LV_TXT_BREAK_CHARS[i] != '\0'; i++) { - if(letter == (uint32_t)LV_TXT_BREAK_CHARS[i]) { - ret = true; /*If match then it is break char*/ - break; - } - } - - return ret; -} diff --git a/src/misc/lv_txt.h b/src/misc/lv_txt.h index e9a097e9a..0bfaf58be 100644 --- a/src/misc/lv_txt.h +++ b/src/misc/lv_txt.h @@ -154,6 +154,32 @@ char * _lv_txt_set_text_vfmt(const char * fmt, va_list ap); */ void _lv_txt_encoded_letter_next_2(const char * txt, uint32_t * letter, uint32_t * letter_next, uint32_t *ofs); +/** + * Test if char is break char or not (a text can broken here or not) + * @param letter a letter + * @return false: 'letter' is not break char + */ +static inline bool _lv_txt_is_break_char(uint32_t letter) +{ + uint8_t i; + bool ret = false; + + /* each chinese character can be break */ + if (letter >= 0x4E00 && letter <= 0x9FA5) { + return true; + } + + /*Compare the letter to TXT_BREAK_CHARS*/ + for(i = 0; LV_TXT_BREAK_CHARS[i] != '\0'; i++) { + if(letter == (uint32_t)LV_TXT_BREAK_CHARS[i]) { + ret = true; /*If match then it is break char*/ + break; + } + } + + return ret; +} + /*************************************************************** * GLOBAL FUNCTION POINTERS FOR CHARACTER ENCODING INTERFACE ***************************************************************/ From 2df12827dda3f217fa26d2c98445a9b3f1ff22ab Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 22 Jun 2021 20:39:47 +0200 Subject: [PATCH 17/17] fix(refr) reduce the nesting level in lv_refr_area --- src/core/lv_refr.c | 112 ++++++++++++++++++++++----------------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/src/core/lv_refr.c b/src/core/lv_refr.c index b56d9e980..e7f9c1389 100644 --- a/src/core/lv_refr.c +++ b/src/core/lv_refr.c @@ -408,75 +408,75 @@ static void lv_refr_area(const lv_area_t * area_p) draw_buf->area.y2 = lv_disp_get_ver_res(disp_refr) - 1; disp_refr->driver->draw_buf->last_part = 1; lv_refr_area_part(area_p); + return; } + /*Normal refresh: draw the area in parts*/ - else { - lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp_refr); - /*Calculate the max row num*/ - lv_coord_t w = lv_area_get_width(area_p); - lv_coord_t h = lv_area_get_height(area_p); - lv_coord_t y2 = - area_p->y2 >= lv_disp_get_ver_res(disp_refr) ? lv_disp_get_ver_res(disp_refr) - 1 : area_p->y2; + lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp_refr); + /*Calculate the max row num*/ + lv_coord_t w = lv_area_get_width(area_p); + lv_coord_t h = lv_area_get_height(area_p); + lv_coord_t y2 = area_p->y2 >= lv_disp_get_ver_res(disp_refr) ? + lv_disp_get_ver_res(disp_refr) - 1 : area_p->y2; - int32_t max_row = (uint32_t)draw_buf->size / w; + int32_t max_row = (uint32_t)draw_buf->size / w; - if(max_row > h) max_row = h; + if(max_row > h) max_row = h; - /*Round down the lines of draw_buf if rounding is added*/ - if(disp_refr->driver->rounder_cb) { - lv_area_t tmp; - tmp.x1 = 0; - tmp.x2 = 0; - tmp.y1 = 0; + /*Round down the lines of draw_buf if rounding is added*/ + if(disp_refr->driver->rounder_cb) { + lv_area_t tmp; + tmp.x1 = 0; + tmp.x2 = 0; + tmp.y1 = 0; - lv_coord_t h_tmp = max_row; - do { - tmp.y2 = h_tmp - 1; - disp_refr->driver->rounder_cb(disp_refr->driver, &tmp); + lv_coord_t h_tmp = max_row; + do { + tmp.y2 = h_tmp - 1; + disp_refr->driver->rounder_cb(disp_refr->driver, &tmp); - /*If this height fits into `max_row` then fine*/ - if(lv_area_get_height(&tmp) <= max_row) break; + /*If this height fits into `max_row` then fine*/ + if(lv_area_get_height(&tmp) <= max_row) break; - /*Decrement the height of the area until it fits into `max_row` after rounding*/ - h_tmp--; - } while(h_tmp > 0); + /*Decrement the height of the area until it fits into `max_row` after rounding*/ + h_tmp--; + } while(h_tmp > 0); - if(h_tmp <= 0) { - LV_LOG_WARN("Can't set draw_buf height using the round function. (Wrong round_cb or to " - "small draw_buf)"); - return; - } - else { - max_row = tmp.y2 + 1; - } + if(h_tmp <= 0) { + LV_LOG_WARN("Can't set draw_buf height using the round function. (Wrong round_cb or to " + "small draw_buf)"); + return; } - - /*Always use the full row*/ - lv_coord_t row; - lv_coord_t row_last = 0; - for(row = area_p->y1; row + max_row - 1 <= y2; row += max_row) { - /*Calc. the next y coordinates of draw_buf*/ - draw_buf->area.x1 = area_p->x1; - draw_buf->area.x2 = area_p->x2; - draw_buf->area.y1 = row; - draw_buf->area.y2 = row + max_row - 1; - if(draw_buf->area.y2 > y2) draw_buf->area.y2 = y2; - row_last = draw_buf->area.y2; - if(y2 == row_last) disp_refr->driver->draw_buf->last_part = 1; - lv_refr_area_part(area_p); + else { + max_row = tmp.y2 + 1; } + } - /*If the last y coordinates are not handled yet ...*/ - if(y2 != row_last) { - /*Calc. the next y coordinates of draw_buf*/ - draw_buf->area.x1 = area_p->x1; - draw_buf->area.x2 = area_p->x2; - draw_buf->area.y1 = row; - draw_buf->area.y2 = y2; + /*Always use the full row*/ + lv_coord_t row; + lv_coord_t row_last = 0; + for(row = area_p->y1; row + max_row - 1 <= y2; row += max_row) { + /*Calc. the next y coordinates of draw_buf*/ + draw_buf->area.x1 = area_p->x1; + draw_buf->area.x2 = area_p->x2; + draw_buf->area.y1 = row; + draw_buf->area.y2 = row + max_row - 1; + if(draw_buf->area.y2 > y2) draw_buf->area.y2 = y2; + row_last = draw_buf->area.y2; + if(y2 == row_last) disp_refr->driver->draw_buf->last_part = 1; + lv_refr_area_part(area_p); + } - disp_refr->driver->draw_buf->last_part = 1; - lv_refr_area_part(area_p); - } + /*If the last y coordinates are not handled yet ...*/ + if(y2 != row_last) { + /*Calc. the next y coordinates of draw_buf*/ + draw_buf->area.x1 = area_p->x1; + draw_buf->area.x2 = area_p->x2; + draw_buf->area.y1 = row; + draw_buf->area.y2 = y2; + + disp_refr->driver->draw_buf->last_part = 1; + lv_refr_area_part(area_p); } }