diff --git a/demos/lv_demos.h b/demos/lv_demos.h index 9d45e6324c88..63f34dfc72fd 100644 --- a/demos/lv_demos.h +++ b/demos/lv_demos.h @@ -51,6 +51,10 @@ extern "C" { #include "multilang/lv_demo_multilang.h" #endif +#if LV_USE_DEMO_RENDER +#include "render/lv_demo_render.h" +#endif + /********************* * DEFINES *********************/ diff --git a/demos/render/README.md b/demos/render/README.md new file mode 100644 index 000000000000..6518490edee1 --- /dev/null +++ b/demos/render/README.md @@ -0,0 +1,48 @@ +# Benchmark demo + + +![LVGL benchmark running](screenshot1.png) + +## Overview + +The benchmark demo tests the performance in various cases. +For example rectangle, border, shadow, text, image blending, image transformation, blending modes, etc. +All tests are repeated with 50% opacity. + +The size and position of the objects during testing are set with a pseudo random number to make the benchmark repeatable. + +On to top of the screen the title of the current test step, and the result of the previous step is displayed. + +## Run the benchmark +- In `lv_conf.h` or equivalent places set `LV_USE_DEMO_BENCHMARK 1` +- After `lv_init()` and initializing the drivers and call `lv_demo_benchmark(mode)` +- If you only want to run a specific scene for any purpose (e.g. debug, performance optimization etc.), you can call `lv_demo_benchmark_run_scene(mode, scene_idx)` instead of `lv_demo_benchmark()`and pass the scene number. +- If you enabled trace output by setting macro `LV_USE_LOG` to `1` and trace level `LV_LOG_LEVEL` to `LV_LOG_LEVEL_USER` or higher, benchmark results are printed out in `csv` format. + + +## Modes +The `mode` should be passed to `lv_demo_benchmark(mode)` or `lv_demo_benchmark_run_scene(mode, scene_idx)`. + +- `LV_DEMO_BENCHMARK_MODE_RENDER_AND_DRIVER` Render the scenes and show them on the display. Measure rendering time but it might contain extra time when LVGL waits for the driver. Run each scenes for a few seconds so the performance can be seen by eye too. As only the rendering time is measured and converted to FPS, really high values (e.g. 1000 FPS) are possible. +- `LV_DEMO_BENCHMARK_MODE_REAL` Similar to `RENDER_AND_DRIVER` but instead of measuring the rendering time only measure the real FPS of the system. E.g. even if a scene was rendered in 1 ms, but the screen is redrawn only in every 100 ms, the result will be 10 FPS. +- `LV_DEMO_BENCHMARK_MODE_RENDER_ONLY` Temporarily display the `flush_cb` so the pure rendering time will be measured. The display is not updated during the benchmark, only at the end when the summary table is shown. Renders a given number of frames from each scene and calculate the FPS from them. + + +## Result summary +In the end, a table is created to display measured FPS values. + +On top of the summary screen, the "Weighted FPS" value is shown. +In this, the result of the more common cases are taken into account with a higher weight. + +"Opa. speed" shows the speed of the measurements with opacity compared to full opacity. +E.g. "Opa. speed = 90%" means that rendering with opacity is 10% slower. + +In the first section of the table, "Slow but common cases", those cases are displayed which are considered common but were slower than 20 FPS. + +Below this in the "All cases section" all the results are shown. The < 10 FPS results are shown with red, the >= 10 but < 20 FPS values are displayed with orange. + +![LVGL benchmark result summary](screenshot2.png) + + + +**NOTE**: Compared to the past, the use of rotation and zoom(scaling) in GUI applications has become increasingly common. Therefore, starting from LVGL9, we have assigned a higher priority to zoom(scaling) and rotation operations. diff --git a/demos/render/lv_demo_render.c b/demos/render/lv_demo_render.c new file mode 100644 index 000000000000..6fcf0ab67230 --- /dev/null +++ b/demos/render/lv_demo_render.c @@ -0,0 +1,280 @@ +/** + * @file lv_demo_render.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_demo_render.h" + +#if LV_USE_DEMO_RENDER +#include "../../src/display/lv_display_private.h" +#include "../../src/core/lv_global.h" + +/********************* + * DEFINES + *********************/ + +#define COL_CNT 8 +#define ROW_CNT 8 +#define DEF_WIDTH 55 +#define DEF_HEIGHT 30 + +/********************** + * TYPEDEFS + **********************/ + +#define SCENE_TIME_DEF 2000 + +typedef struct { + const char * name; + void (*create_cb)(lv_obj_t * parent); +} scene_dsc_t; + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void add_to_cell(lv_obj_t * obj, lv_coord_t col, lv_coord_t row); + + +static lv_obj_t * fill_obj_create(lv_obj_t * parent, lv_coord_t col, lv_coord_t row) +{ + lv_color_t colors[] = {lv_color_hex3(0x000), + lv_color_hex3(0xfff), + lv_color_hex3(0xf00), + lv_color_hex3(0x0f0), + lv_color_hex3(0x00f), + lv_color_hex3(0xff0), + lv_color_hex3(0x0ff), + lv_color_hex3(0xf0f), + }; + + lv_obj_t * obj = lv_obj_create(parent); + lv_obj_remove_style_all(obj); + lv_obj_set_style_bg_opa(obj, LV_OPA_COVER, 0); + lv_obj_set_style_bg_color(obj, colors[col], 0); + lv_obj_set_size(obj, DEF_WIDTH, DEF_HEIGHT); + add_to_cell(obj, col, row); + + return obj; + +} + +static void fill_cb(lv_obj_t * parent) +{ + + uint32_t i; + for(i = 0; i < COL_CNT; i++) { + fill_obj_create(parent, i, 0); + } + + for(i = 0; i < COL_CNT; i++) { + lv_obj_t * obj = fill_obj_create(parent, i, 1); + lv_obj_set_style_radius(obj, 10, 0); + } + + for(i = 0; i < COL_CNT; i++) { + lv_obj_t * obj = fill_obj_create(parent, i, 2); + lv_obj_set_style_radius(obj, 100, 0); + } + + for(i = 0; i < COL_CNT; i++) { + lv_obj_t * obj = fill_obj_create(parent, i, 3); + lv_obj_set_style_radius(obj, 10, 0); + lv_obj_set_style_bg_grad_dir(obj, LV_GRAD_DIR_HOR, 0); + lv_obj_set_style_bg_grad_color(obj, lv_color_hex3(0x888), 0); + lv_obj_set_style_bg_grad_stop(obj, 200, 0); + } + + for(i = 0; i < COL_CNT; i++) { + lv_obj_t * obj = fill_obj_create(parent, i, 4); + lv_obj_set_style_radius(obj, 10, 0); + lv_obj_set_style_bg_grad_dir(obj, LV_GRAD_DIR_VER, 0); + lv_obj_set_style_bg_grad_color(obj, lv_color_hex3(0x888), 0); + lv_obj_set_style_bg_grad_stop(obj, 200, 0); + } + + for(i = 0; i < COL_CNT; i++) { + + lv_obj_t * obj = fill_obj_create(parent, i, 5); + lv_obj_set_style_radius(obj, 10, 0); + lv_obj_set_style_bg_grad_dir(obj, LV_GRAD_DIR_HOR, 0); + lv_obj_set_style_bg_grad_color(obj, lv_color_hex3(0x888), 0); + lv_obj_set_style_bg_grad_opa(obj, LV_OPA_TRANSP, 0); + lv_obj_set_style_bg_grad_stop(obj, 200, 0); + } + + for(i = 0; i < COL_CNT; i++) { + lv_obj_t * obj = fill_obj_create(parent, i, 6); + lv_obj_set_style_radius(obj, 10, 0); + lv_obj_set_style_bg_grad_dir(obj, LV_GRAD_DIR_VER, 0); + lv_obj_set_style_bg_grad_color(obj, lv_color_hex3(0x888), 0); + lv_obj_set_style_bg_grad_opa(obj, LV_OPA_TRANSP, 0); + lv_obj_set_style_bg_grad_stop(obj, 200, 0); + } +} + +static lv_obj_t * border_obj_create(lv_obj_t * parent, lv_coord_t col, lv_coord_t row) +{ + + lv_obj_t * obj = lv_obj_create(parent); + lv_obj_remove_style_all(obj); + lv_obj_set_style_border_color(obj, lv_color_hex3(0x000), 0); + lv_obj_set_style_border_width(obj, 3, 0); + lv_obj_set_size(obj, DEF_WIDTH, DEF_HEIGHT); + add_to_cell(obj, col, row); + + return obj; + +} + +static void border_cb(lv_obj_t * parent) +{ + lv_border_side_t sides[] = { + LV_BORDER_SIDE_NONE, + LV_BORDER_SIDE_FULL, + LV_BORDER_SIDE_LEFT, + LV_BORDER_SIDE_RIGHT, + LV_BORDER_SIDE_TOP, + LV_BORDER_SIDE_BOTTOM, + LV_BORDER_SIDE_TOP | LV_BORDER_SIDE_RIGHT, + LV_BORDER_SIDE_RIGHT | LV_BORDER_SIDE_BOTTOM, + LV_BORDER_SIDE_LEFT| LV_BORDER_SIDE_BOTTOM, + LV_BORDER_SIDE_LEFT | LV_BORDER_SIDE_TOP, + LV_BORDER_SIDE_LEFT | LV_BORDER_SIDE_RIGHT, + LV_BORDER_SIDE_TOP | LV_BORDER_SIDE_BOTTOM, + LV_BORDER_SIDE_LEFT | LV_BORDER_SIDE_RIGHT | LV_BORDER_SIDE_BOTTOM, + LV_BORDER_SIDE_LEFT | LV_BORDER_SIDE_BOTTOM | LV_BORDER_SIDE_TOP, + LV_BORDER_SIDE_LEFT | LV_BORDER_SIDE_RIGHT | LV_BORDER_SIDE_TOP, + LV_BORDER_SIDE_BOTTOM | LV_BORDER_SIDE_RIGHT | LV_BORDER_SIDE_TOP, + }; + + uint32_t i; + for(i = 0; i < COL_CNT; i++) { + lv_obj_t * obj = border_obj_create(parent, i, 0); + lv_obj_set_style_radius(obj, 0, 0); + lv_obj_set_style_border_side(obj, sides[i], 0); + lv_obj_set_style_border_color(obj, lv_color_hex3(0xf00), 0); + } + + for(i = 0; i < COL_CNT; i++) { + lv_obj_t * obj = border_obj_create(parent, i, 1); + lv_obj_set_style_radius(obj, 0, 0); + lv_obj_set_style_border_side(obj, sides[i + 8], 0); + lv_obj_set_style_border_color(obj, lv_color_hex3(0xf00), 0); + } + + for(i = 0; i < COL_CNT; i++) { + lv_obj_t * obj = border_obj_create(parent, i, 2); + lv_obj_set_style_radius(obj, 10, 0); + lv_obj_set_style_border_side(obj, sides[i], 0); + lv_obj_set_style_border_color(obj, lv_color_hex3(0x0f0), 0); + } + + for(i = 0; i < COL_CNT; i++) { + lv_obj_t * obj = border_obj_create(parent, i, 3); + lv_obj_set_style_radius(obj, 10, 0); + lv_obj_set_style_border_side(obj, sides[i + 8], 0); + lv_obj_set_style_border_color(obj, lv_color_hex3(0x0f0), 0); + } + + for(i = 0; i < COL_CNT; i++) { + lv_obj_t * obj = border_obj_create(parent, i, 4); + lv_obj_set_style_radius(obj, 100, 0); + lv_obj_set_style_border_side(obj, sides[i], 0); + lv_obj_set_style_border_color(obj, lv_color_hex3(0x00f), 0); + } + + for(i = 0; i < COL_CNT; i++) { + lv_obj_t * obj = border_obj_create(parent, i, 5); + lv_obj_set_style_radius(obj, 100, 0); + lv_obj_set_style_border_side(obj, sides[i + 8], 0); + lv_obj_set_style_border_color(obj, lv_color_hex3(0x00f), 0); + } + + for(i = 0; i < COL_CNT; i++) { + lv_obj_t * obj = border_obj_create(parent, i, 6); + lv_obj_set_style_radius(obj, 100, 0); + lv_obj_set_style_border_side(obj, sides[i], 0); + lv_obj_set_style_border_color(obj, lv_color_hex3(0x888), 0); + lv_obj_set_style_border_width(obj, 10, 0); + } + + for(i = 0; i < COL_CNT; i++) { + lv_obj_t * obj = border_obj_create(parent, i, 7); + lv_obj_set_style_radius(obj, 100, 0); + lv_obj_set_style_border_side(obj, sides[i + 8], 0); + lv_obj_set_style_border_color(obj, lv_color_hex3(0x888), 0); + lv_obj_set_style_border_width(obj, 10, 0); + } +} + +/********************** + * STATIC VARIABLES + **********************/ +//fill (radius + gradient too) +//border (each sides + radius) +//outline (radius) +//box shadow (offset, size, spread) +//text (normal text + underline/strike through, placeholder) +//triangle (just some rectangles) +//image (various formats + transformation) +//line (various angles + line caps) +//arc (some arcs + caps) +//vector (later) +//layer (blend mode, transformation) +//mask bitmap (not implemented SW render yet) +//mask rectangle + +static scene_dsc_t scenes[] = { + {.name = "Fill ", .create_cb = fill_cb}, + {.name = "Border", .create_cb = border_cb}, + + {.name = "", .create_cb = NULL} +}; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_demo_render(uint32_t idx) +{ + + lv_obj_t * scr = lv_screen_active(); + lv_obj_clean(scr); + lv_obj_remove_style_all(scr); + lv_obj_set_style_bg_opa(scr, LV_OPA_COVER, 0); + lv_obj_set_style_text_color(scr, lv_color_black(), 0); + lv_obj_set_style_bg_color(scr, lv_color_white(), 0); + + lv_obj_t * main_parent = lv_obj_create(scr); + lv_obj_remove_style_all(main_parent); + lv_obj_set_style_bg_opa(main_parent, LV_OPA_COVER, 0); + lv_obj_set_style_bg_color(main_parent, lv_color_hex3(0xaaf), 0); + lv_obj_set_size(main_parent, 480, 272); + + static const lv_coord_t grid_cols[] = {60, 60, 60, 60, 60, 60, 60, 60, LV_GRID_TEMPLATE_LAST}; + static const lv_coord_t grid_rows[] = {34, 34, 34, 34, 34, 34, 34, 34, LV_GRID_TEMPLATE_LAST}; + lv_obj_set_grid_dsc_array(main_parent, grid_cols, grid_rows); + + + if(scenes[idx].create_cb) scenes[idx].create_cb(main_parent); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void add_to_cell(lv_obj_t * obj, lv_coord_t col, lv_coord_t row) +{ + lv_obj_set_grid_cell(obj, LV_GRID_ALIGN_CENTER, col, 1, LV_GRID_ALIGN_CENTER, row, 1); +} + + +#endif diff --git a/demos/render/lv_demo_render.h b/demos/render/lv_demo_render.h new file mode 100644 index 000000000000..7e63ed68c637 --- /dev/null +++ b/demos/render/lv_demo_render.h @@ -0,0 +1,48 @@ +/** + * @file lv_demo_render.h + * + */ + +#ifndef LV_DEMO_RENDER_H +#define LV_DEMO_RENDER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_demos.h" + +#if LV_USE_DEMO_RENDER + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Run the render verification for a scenario + * @param idx index of the scenario to run + */ +void lv_demo_render(uint32_t idx); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_DEMO_RENDER*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_DEMO_RENDER_H*/ diff --git a/demos/render/screenshot1.png b/demos/render/screenshot1.png new file mode 100644 index 000000000000..845f2be62a21 Binary files /dev/null and b/demos/render/screenshot1.png differ diff --git a/demos/render/screenshot2.png b/demos/render/screenshot2.png new file mode 100644 index 000000000000..0a0023b60f64 Binary files /dev/null and b/demos/render/screenshot2.png differ diff --git a/docs/overview/style-props.md b/docs/overview/style-props.md index 07eb68022138..15ce2b4427b6 100644 --- a/docs/overview/style-props.md +++ b/docs/overview/style-props.md @@ -226,7 +226,7 @@ Sets the padding between the columns. Used by the layouts. Properties to describe spacing around an object. Very similar to the margin properties in HTML. ### margin_top -Sets the margin on the top. The object will keep this space from its siblings in layouts. +Sets the margin on the top. The object will keep this space from its siblings in layouts. -### bg_grad -Set the gradient definition. The pointed instance must exist while the object is alive. NULL to disable. It wraps `BG_GRAD_COLOR`, `BG_GRAD_DIR`, `BG_MAIN_STOP` and `BG_GRAD_STOP` into one descriptor and allows creating gradients with more colors too. +### bg_main_opa +Set the opacity of the first gradient color + +### bg_grad_opa +Set the opacity of the second gradient color + -### bg_dither_mode -Set the dithering mode of the gradient of the background. The possible values are `LV_DITHER_NONE/ORDERED/ERR_DIFF`. +### bg_grad +Set the gradient definition. The pointed instance must exist while the object is alive. NULL to disable. It wraps `BG_GRAD_COLOR`, `BG_GRAD_DIR`, `BG_MAIN_STOP` and `BG_GRAD_STOP` into one descriptor and allows creating gradients with more colors too. If it's set other gradient related properties will be ignored'