feat(cache): add empty_cb, add cache manager replace function, fix builtin cache init and tracing, update image overview documentation (#4604)

This commit is contained in:
PGNetHun
2023-09-26 13:57:18 +02:00
committed by GitHub
parent c4cab173c9
commit d57000349c
4 changed files with 120 additions and 56 deletions

View File

@@ -17,7 +17,7 @@ Variables
---------
Images stored internally in a variable are composed mainly of an
:cpp:struct:`lv_img_dsc_t` structure with the following fields:
:cpp:struct:`lv_image_dsc_t` structure with the following fields:
- **header**:
@@ -136,16 +136,16 @@ variable to display it using LVGL. For example:
uint8_t my_img_data[] = {0x00, 0x01, 0x02, ...};
static lv_img_dsc_t my_img_dsc = {
static lv_image_dsc_t my_img_dsc = {
.header.always_zero = 0,
.header.w = 80,
.header.h = 60,
.data_size = 80 * 60 * LV_COLOR_DEPTH / 8,
.header.cf = LV_IMG_CF_TRUE_COLOR, /*Set the color format*/
.header.cf = LV_COLOR_FORMAT_NATIVE, /*Set the color format*/
.data = my_img_data,
};
If the color format is :cpp:enumerator:`LV_COLOR_FORMAT_NATIVE_ALPHA` you can set
If the color format is :cpp:enumerator:`LV_COLOR_FORMAT_NATIVE_WITH_ALPHA` you can set
``data_size`` like ``80 * 60 *`` :cpp:enumerator:`LV_IMG_PX_SIZE_ALPHA_BYTE`.
Another (possibly simpler) option to create and display an image at
@@ -159,13 +159,13 @@ The simplest way to use an image in LVGL is to display it with an
.. code:: c
lv_obj_t * icon = lv_img_create(lv_scr_act(), NULL);
lv_obj_t * icon = lv_image_create(lv_scr_act(), NULL);
/*From variable*/
lv_img_set_src(icon, &my_icon_dsc);
lv_image_set_src(icon, &my_icon_dsc);
/*From file*/
lv_img_set_src(icon, "S:my_icon.bin");
lv_image_set_src(icon, "S:my_icon.bin");
If the image was converted with the online converter, you should use
:cpp:expr:`LV_IMG_DECLARE(my_icon_dsc)` to declare the image in the file where
@@ -242,10 +242,10 @@ open/close the PNG files. It should look like this:
.. code:: c
/*Create a new decoder and register functions */
lv_img_decoder_t * dec = lv_img_decoder_create();
lv_img_decoder_set_info_cb(dec, decoder_info);
lv_img_decoder_set_open_cb(dec, decoder_open);
lv_img_decoder_set_close_cb(dec, decoder_close);
lv_image_decoder_t * dec = lv_image_decoder_create();
lv_image_decoder_set_info_cb(dec, decoder_info);
lv_image_decoder_set_open_cb(dec, decoder_open);
lv_image_decoder_set_close_cb(dec, decoder_close);
/**
@@ -255,7 +255,7 @@ open/close the PNG files. It should look like this:
* @param header store the info here
* @return LV_RES_OK: no error; LV_RES_INV: can't get the info
*/
static lv_res_t decoder_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header)
static lv_res_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header)
{
/*Check whether the type `src` is known by the decoder*/
if(is_png(src) == false) return LV_RES_INV;
@@ -263,7 +263,7 @@ open/close the PNG files. It should look like this:
/* Read the PNG header and find `width` and `height` */
...
header->cf = LV_IMG_CF_RAW_ALPHA;
header->cf = LV_COLOR_FORMAT_RAW_ALPHA;
header->w = width;
header->h = height;
}
@@ -274,7 +274,7 @@ open/close the PNG files. It should look like this:
* @param dsc pointer to a descriptor which describes this decoding session
* @return LV_RES_OK: no error; LV_RES_INV: can't get the info
*/
static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc)
static lv_res_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc)
{
/*Check whether the type `src` is known by the decoder*/
@@ -284,10 +284,10 @@ open/close the PNG files. It should look like this:
dsc->img_data = my_png_decoder(src);
/*Change the color format if required. For PNG usually 'Raw' is fine*/
dsc->header.cf = LV_IMG_CF_...
dsc->header.cf = LV_COLOR_FORMAT_...
/*Call a built in decoder function if required. It's not required if`my_png_decoder` opened the image in true color format.*/
lv_res_t res = lv_img_decoder_built_in_open(decoder, dsc);
lv_res_t res = lv_image_decoder_built_in_open(decoder, dsc);
return res;
}
@@ -303,7 +303,7 @@ open/close the PNG files. It should look like this:
* @param buf a buffer to store the decoded pixels
* @return LV_RES_OK: ok; LV_RES_INV: failed
*/
lv_res_t decoder_built_in_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc, lv_coord_t x,
lv_res_t decoder_built_in_read_line(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, lv_coord_t x,
lv_coord_t y, lv_coord_t len, uint8_t * buf)
{
/*With PNG it's usually not required*/
@@ -317,12 +317,12 @@ open/close the PNG files. It should look like this:
* @param decoder pointer to the decoder where this function belongs
* @param dsc pointer to a descriptor which describes this decoding session
*/
static void decoder_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc)
static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc)
{
/*Free all allocated data*/
/*Call the built-in close function if the built-in open/read_line was used*/
lv_img_decoder_built_in_close(decoder, dsc);
lv_image_decoder_built_in_close(decoder, dsc);
}
@@ -348,8 +348,8 @@ Manually use an image decoder
LVGL will use registered image decoders automatically if you try and
draw a raw image (i.e. using the ``lv_img`` object) but you can use them
manually too. Create an :cpp:type:`lv_img_decoder_dsc_t` variable to describe
the decoding session and call :cpp:func:`lv_img_decoder_open`.
manually too. Create an :cpp:type:`lv_image_decoder_dsc_t` variable to describe
the decoding session and call :cpp:func:`lv_image_decoder_open`.
The ``color`` parameter is used only with ``LV_IMG_CF_ALPHA_1/2/4/8BIT``
images to tell color of the image. ``frame_id`` can be used if the image
@@ -359,12 +359,12 @@ to open is an animation.
lv_res_t res;
lv_img_decoder_dsc_t dsc;
res = lv_img_decoder_open(&dsc, &my_img_dsc, color, frame_id);
lv_image_decoder_dsc_t dsc;
res = lv_image_decoder_open(&dsc, &my_img_dsc, color, frame_id);
if(res == LV_RES_OK) {
/*Do something with `dsc->img_data`*/
lv_img_decoder_close(&dsc);
lv_image_decoder_close(&dsc);
}
.. _image-caching:
@@ -390,12 +390,13 @@ a relatively fast storage medium.
Cache size
----------
The number of cache entries can be defined with
:c:macro:`LV_IMG_CACHE_DEF_SIZE` in *lv_conf.h*. The default value is 1 so only
the most recently used image will be left open.
The size of cache (in bytes) can be defined with
:c:macro:`LV_CACHE_DEF_SIZE` in *lv_conf.h*. The default value is 0, so
no image is cached.
The size of the cache can be changed at run-time with
:cpp:expr:`lv_img_cache_set_size(entry_num)`.
The size of cache can be changed at run-time with
:cpp:expr:`lv_cache_set_max_size(size_t size)`,
and get with :cpp:expr:`lv_cache_get_max_size()`.
Value of images
---------------
@@ -435,55 +436,74 @@ to cache even the largest images at the same time.
Clean the cache
---------------
Let's say you have loaded a PNG image into a :cpp:struct:`lv_img_dsc_t` ``my_png``
variable and use it in an ``lv_img`` object. If the image is already
Let's say you have loaded a PNG image into a :cpp:struct:`lv_image_dsc_t` ``my_png``
variable and use it in an ``lv_image`` object. If the image is already
cached and you then change the underlying PNG file, you need to notify
LVGL to cache the image again. Otherwise, there is no easy way of
detecting that the underlying file changed and LVGL will still draw the
old image from cache.
To do this, use :cpp:expr:`lv_img_cache_invalidate_src(&my_png)`. If ``NULL`` is
passed as a parameter, the whole cache will be cleaned.
To do this, use :cpp:expr:`lv_cache_invalidate(lv_cache_find(&my_png, LV_CACHE_SRC_TYPE_PTR, 0, 0));`.
Custom cache algorithm
----------------------
If you want to implement your own cache algorithm, you can refer to the
following code to replace the LVGL built-in image cache manager:
following code to replace the LVGL built-in cache manager:
.. code:: c
static _lv_img_cache_entry_t * my_img_cache_open(const void * src, lv_color_t color, int32_t frame_id)
static lv_cache_entry_t * my_cache_add_cb(size_t size)
{
...
}
static void my_img_cache_set_size(uint16_t new_entry_cnt)
static lv_cache_entry_t * my_cache_find_cb(const void * src, lv_cache_src_type_t src_type, uint32_t param1, uint32_t param2)
{
...
}
static void my_img_cache_invalidate_src(const void * src)
static void my_cache_invalidate_cb(lv_cache_entry_t * entry)
{
...
}
void my_img_cache_init(void)
static const void * my_cache_get_data_cb(lv_cache_entry_t * entry)
{
/* Before replacing the image cache manager,
* you should ensure that all caches are cleared to prevent memory leaks.
*/
lv_img_cache_invalidate_src(NULL);
...
}
/*Initialize image cache manager.*/
lv_img_cache_manager_t manager;
lv_img_cache_manager_init(&manager);
manager.open_cb = my_img_cache_open;
manager.set_size_cb = my_img_cache_set_size;
manager.invalidate_src_cb = my_img_cache_invalidate_src;
static void my_cache_release_cb(lv_cache_entry_t * entry)
{
...
}
/*Apply image cache manager to LVGL.*/
lv_img_cache_manager_apply(&manager);
static void my_cache_set_max_size_cb(size_t new_size)
{
...
}
static void my_cache_empty_cb(void)
{
...
}
void my_cache_init(void)
{
/*Initialize new cache manager.*/
lv_cache_manager_t my_manager;
my_manager.add_cb = my_cache_add_cb;
my_manager.find_cb = my_cache_find_cb;
my_manager.invalidate_cb = my_cache_invalidate_cb;
my_manager.get_data_cb = my_cache_get_data_cb;
my_manager.release_cb = my_cache_release_cb;
my_manager.set_max_size_cb = my_cache_set_max_size_cb;
my_manager.empty_cb = my_cache_empty_cb;
/*Replace existing cache manager with the new one.*/
lv_cache_lock();
lv_cache_replace_manager(&my_manager);
lv_cache_unlock();
}
API