mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-21 06:53:01 +08:00
191 lines
10 KiB
Markdown
191 lines
10 KiB
Markdown
|
```eval_rst
|
||
|
.. include:: /header.rst
|
||
|
:github_url: |github_link_base|/overview/display.md
|
||
|
```
|
||
|
# Displays
|
||
|
|
||
|
``` important:: The basic concept of *display* in LVGL is explained in the [Porting](/porting/display) section. So before reading further, please read the [Porting](/porting/display) section first.
|
||
|
```
|
||
|
|
||
|
## Multiple display support
|
||
|
|
||
|
In LVGL, you can have multiple displays, each with their own driver and objects. The only limitation is that every display needs to be have same color depth (as defined in `LV_COLOR_DEPTH`).
|
||
|
If the displays are different in this regard the rendered image can be converted to the correct format in the drivers `flush_cb`.
|
||
|
|
||
|
Creating more displays is easy: just initialize more display buffers and register another driver for every display.
|
||
|
When you create the UI, use `lv_disp_set_default(disp)` to tell the library on which display to create objects.
|
||
|
|
||
|
Why would you want multi-display support? Here are some examples:
|
||
|
- Have a "normal" TFT display with local UI and create "virtual" screens on VNC on demand. (You need to add your VNC driver).
|
||
|
- Have a large TFT display and a small monochrome display.
|
||
|
- Have some smaller and simple displays in a large instrument or technology.
|
||
|
- Have two large TFT displays: one for a customer and one for the shop assistant.
|
||
|
|
||
|
### Using only one display
|
||
|
Using more displays can be useful, but in most cases, it's not required. Therefore, the whole concept of multi-display is completely hidden if you register only one display.
|
||
|
By default, the lastly created (the only one) display is used as default.
|
||
|
|
||
|
`lv_scr_act()`, `lv_scr_load(scr)`, `lv_layer_top()`, `lv_layer_sys()`, `LV_HOR_RES` and `LV_VER_RES` are always applied on the lastly created (default) screen.
|
||
|
If you pass `NULL` as `disp` parameter to display related function, usually the default display will be used.
|
||
|
E.g. `lv_disp_trig_activity(NULL)` will trigger a user activity on the default screen. (See below in [Inactivity](#Inactivity)).
|
||
|
|
||
|
### Mirror display
|
||
|
|
||
|
To mirror the image of the display to another display, you don't need to use the multi-display support. Just transfer the buffer received in `drv.flush_cb` to another display too.
|
||
|
|
||
|
### Split image
|
||
|
You can create a larger display from smaller ones. You can create it as below:
|
||
|
1. Set the resolution of the displays to the large display's resolution.
|
||
|
2. In `drv.flush_cb`, truncate and modify the `area` parameter for each display.
|
||
|
3. Send the buffer's content to each display with the truncated area.
|
||
|
|
||
|
## Screens
|
||
|
|
||
|
Every display has each set of [Screens](overview/object#screen-the-most-basic-parent) and the object on the screens.
|
||
|
|
||
|
Be sure not to confuse displays and screens:
|
||
|
|
||
|
* **Displays** are the physical hardware drawing the pixels.
|
||
|
* **Screens** are the high-level root objects associated with a particular display. One display can have multiple screens associated with it, but not vice versa.
|
||
|
|
||
|
Screens can be considered the highest level containers which have no parent.
|
||
|
The screen's size is always equal to its display and size their position is (0;0). Therefore, the screens coordinates can't be changed, i.e. `lv_obj_set_pos()`, `lv_obj_set_size()` or similar functions can't be used on screens.
|
||
|
|
||
|
A screen can be created from any object type but, the two most typical types are the [Base object](/widgets/obj) and the [Image](/widgets/img) (to create a wallpaper).
|
||
|
|
||
|
To create a screen, use `lv_obj_t * scr = lv_<type>_create(NULL, copy)`. `copy` can be an other screen to copy it.
|
||
|
|
||
|
To load a screen, use `lv_scr_load(scr)`. To get the active screen, use `lv_scr_act()`. These functions works on the default display. If you want to to specify which display to work on, use `lv_disp_get_scr_act(disp)` and `lv_disp_load_scr(disp, scr)`. Screen can be loaded with animations too. Read more [here](object.html#load-screens).
|
||
|
|
||
|
Screens can be deleted with `lv_obj_del(scr)`, but ensure that you do not delete the currently loaded screen.
|
||
|
|
||
|
### Transparent screens
|
||
|
|
||
|
Usually, the opacity of the screen is `LV_OPA_COVER` to provide a solid background for its children. If it's not the case (opacity < 100%) the display's background color or image will be visible.
|
||
|
See the [Display background](#display-background) section for more details. If the display's background opacity is also not `LV_OPA_COVER` LVGL has no solid background to draw.
|
||
|
|
||
|
This configuration (transparent screen ans display) could be used to create for example OSD menus where a video is played to lower layer, and menu is created on an upper layer.
|
||
|
|
||
|
To handle transparent displays special (slower) color mixing algorithms needs to be used by LVGL so this feature needs to enabled with `LV_COLOR_SCREEN_TRANSP` n `lv_conf.h`.
|
||
|
As this mode operates on the Alpha channel of the pixels `LV_COLOR_DEPTH = 32` is also required. The Alpha channel of 32-bit colors will be 0 where there are no objects and will be 255 where there are solid objects.
|
||
|
|
||
|
In summary, to enable transparent screen and displays to create OSD menu-like UIs:
|
||
|
- Enable `LV_COLOR_SCREEN_TRANSP` in `lv_conf.h`
|
||
|
- Be sure to use `LV_COLOR_DEPTH 32`
|
||
|
- Set the screens opacity to `LV_OPA_TRANSP` e.g. with `lv_obj_set_style_local_bg_opa(lv_scr_act(), LV_OBJMASK_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP)`
|
||
|
- Set the display opacity to `LV_OPA_TRANSP` with `lv_disp_set_bg_opa(NULL, LV_OPA_TRANSP);`
|
||
|
|
||
|
## Features of displays
|
||
|
|
||
|
### Inactivity
|
||
|
|
||
|
The user's inactivity is measured on each display. Every use of an [Input device](/overview/indev) (if [associated with the display](/porting/indev#other-features)) counts as an activity.
|
||
|
To get time elapsed since the last activity, use `lv_disp_get_inactive_time(disp)`. If `NULL` is passed, the overall smallest inactivity time will be returned from all displays (**not the default display**).
|
||
|
|
||
|
You can manually trigger an activity using `lv_disp_trig_activity(disp)`. If `disp` is `NULL`, the default screen will be used (**and not all displays**).
|
||
|
|
||
|
### Background
|
||
|
Every display has background color, a background image and background opacity properties. They become visible when the current screen is transparent or not positioned to cover the whole display.
|
||
|
|
||
|
Background color is a simple color to fill the display. It can be adjusted with `lv_disp_set_bg_color(disp, color)`;
|
||
|
|
||
|
Background image is path to file or pointer to an `lv_img_dsc_t` variable (converted image) to be used as wallpaper. It can be set with `lv_disp_set_bg_color(disp, &my_img)`;
|
||
|
If the background image is set (not `NULL`) the background won't filled with `bg_color`.
|
||
|
|
||
|
The opacity of the background color or image can be adjusted with `lv_disp_set_bg_opa(disp, opa)`.
|
||
|
|
||
|
The `disp` parameter of these functions can be `NULL` to refer it to the default display.
|
||
|
|
||
|
|
||
|
## Colors
|
||
|
|
||
|
The color module handles all color-related functions like changing color depth, creating colors from hex code, converting between color depths, mixing colors, etc.
|
||
|
|
||
|
The following variable types are defined by the color module:
|
||
|
|
||
|
- **lv_color1_t** Store monochrome color. For compatibility, it also has R, G, B fields but they are always the same value (1 byte)
|
||
|
- **lv_color8_t** A structure to store R (3 bit),G (3 bit),B (2 bit) components for 8-bit colors (1 byte)
|
||
|
- **lv_color16_t** A structure to store R (5 bit),G (6 bit),B (5 bit) components for 16-bit colors (2 byte)
|
||
|
- **lv_color32_t** A structure to store R (8 bit),G (8 bit), B (8 bit) components for 24-bit colors (4 byte)
|
||
|
- **lv_color_t** Equal to `lv_color1/8/16/24_t` according to color depth settings
|
||
|
- **lv_color_int_t** `uint8_t`, `uint16_t` or `uint32_t` according to color depth setting. Used to build color arrays from plain numbers.
|
||
|
- **lv_opa_t** A simple `uint8_`t type to describe opacity.
|
||
|
|
||
|
The `lv_color_t`, `lv_color1_t`, `lv_color8_t`, `lv_color16_t` and `lv_color32_t` types have got four fields:
|
||
|
|
||
|
- **ch.red** red channel
|
||
|
- **ch.green** green channel
|
||
|
- **ch.blue** blue channel
|
||
|
- **full** red + green + blue as one number
|
||
|
|
||
|
You can set the current color depth in *lv_conf.h*, by setting the `LV_COLOR_DEPTH` define to 1 (monochrome), 8, 16 or 32.
|
||
|
|
||
|
### Convert color
|
||
|
You can convert a color from the current color depth to another. The converter functions return with a number, so you have to use the `full` field:
|
||
|
|
||
|
```c
|
||
|
lv_color_t c;
|
||
|
c.red = 0x38;
|
||
|
c.green = 0x70;
|
||
|
c.blue = 0xCC;
|
||
|
|
||
|
lv_color1_t c1;
|
||
|
c1.full = lv_color_to1(c); /*Return 1 for light colors, 0 for dark colors*/
|
||
|
|
||
|
lv_color8_t c8;
|
||
|
c8.full = lv_color_to8(c); /*Give a 8 bit number with the converted color*/
|
||
|
|
||
|
lv_color16_t c16;
|
||
|
c16.full = lv_color_to16(c); /*Give a 16 bit number with the converted color*/
|
||
|
|
||
|
lv_color32_t c24;
|
||
|
c32.full = lv_color_to32(c); /*Give a 32 bit number with the converted color*/
|
||
|
```
|
||
|
|
||
|
### Swap 16 colors
|
||
|
You may set `LV_COLOR_16_SWAP` in *lv_conf.h* to swap the bytes of *RGB565* colors. It's useful if you send the 16-bit colors via a byte-oriented interface like SPI.
|
||
|
|
||
|
As 16-bit numbers are stored in Little Endian format (lower byte on the lower address), the interface will send the lower byte first. However, displays usually need the higher byte first. A mismatch in the byte order will result in highly distorted colors.
|
||
|
|
||
|
### Create and mix colors
|
||
|
You can create colors with the current color depth using the LV_COLOR_MAKE macro. It takes 3 arguments (red, green, blue) as 8-bit numbers.
|
||
|
For example to create light red color: `my_color = COLOR_MAKE(0xFF,0x80,0x80)`.
|
||
|
|
||
|
Colors can be created from HEX codes too: `my_color = lv_color_hex(0x288ACF)` or `my_color = lv_folro_hex3(0x28C)`.
|
||
|
|
||
|
Mixing two colors is possible with `mixed_color = lv_color_mix(color1, color2, ratio)`. Ration can be 0..255. 0 results fully color2, 255 result fully color1.
|
||
|
|
||
|
Colors can be created with from HSV space too using `lv_color_hsv_to_rgb(hue, saturation, value)` . `hue` should be in 0..360 range, `saturation` and `value` in 0..100 range.
|
||
|
|
||
|
### Opacity
|
||
|
To describe opacity the `lv_opa_t` type is created as a wrapper to `uint8_t`. Some defines are also introduced:
|
||
|
|
||
|
- **LV_OPA_TRANSP** Value: 0, means the opacity makes the color completely transparent
|
||
|
- **LV_OPA_10** Value: 25, means the color covers only a little
|
||
|
- **LV_OPA_20 ... OPA_80** come logically
|
||
|
- **LV_OPA_90** Value: 229, means the color near completely covers
|
||
|
- **LV_OPA_COVER** Value: 255, means the color completely covers
|
||
|
|
||
|
You can also use the `LV_OPA_*` defines in `lv_color_mix()` as a *ratio*.
|
||
|
|
||
|
## API
|
||
|
|
||
|
|
||
|
### Display
|
||
|
|
||
|
```eval_rst
|
||
|
|
||
|
.. doxygenfile:: lv_disp.h
|
||
|
:project: lvgl
|
||
|
|
||
|
```
|
||
|
|
||
|
### Colors
|
||
|
|
||
|
```eval_rst
|
||
|
|
||
|
.. doxygenfile:: lv_color.h
|
||
|
:project: lvgl
|
||
|
|
||
|
```
|