docs(porting): review and update to v9
This commit is contained in:
@@ -5,7 +5,7 @@ Display interface
|
|||||||
=================
|
=================
|
||||||
|
|
||||||
To create a display for LVGL call
|
To create a display for LVGL call
|
||||||
:cpp:expr:`lv_disp_t * disp = lv_disp_create(hor_res, ver_res)`. You can create
|
:cpp:expr:`lv_display_t * display = lv_display_create(hor_res, ver_res)`. You can create
|
||||||
a multiple displays and a different driver for each (see below),
|
a multiple displays and a different driver for each (see below),
|
||||||
|
|
||||||
Basic setup
|
Basic setup
|
||||||
@@ -22,38 +22,39 @@ An example ``flush_cb`` looks like this:
|
|||||||
|
|
||||||
.. code:: c
|
.. code:: c
|
||||||
|
|
||||||
void my_flush_cb(lv_disp_t * disp, const lv_area_t * area, lv_color_t * buf)
|
void my_flush_cb(lv_display_t * display, const lv_area_t * area, void * px_map)
|
||||||
{
|
{
|
||||||
/*The most simple case (but also the slowest) to put all pixels to the screen one-by-one
|
/*The most simple case (but also the slowest) to put all pixels to the screen one-by-one
|
||||||
*`put_px` is just an example, it needs to be implemented by you.*/
|
*`put_px` is just an example, it needs to be implemented by you.*/
|
||||||
|
uint16_t * buf16 = (uint16_t)px_map; /*Let's say it's a 16 bit (RGB565) display*/
|
||||||
int32_t x, y;
|
int32_t x, y;
|
||||||
for(y = area->y1; y <= area->y2; y++) {
|
for(y = area->y1; y <= area->y2; y++) {
|
||||||
for(x = area->x1; x <= area->x2; x++) {
|
for(x = area->x1; x <= area->x2; x++) {
|
||||||
put_px(x, y, *buf);
|
put_px(x, y, *buf16);
|
||||||
buf++;
|
buf16++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* IMPORTANT!!!
|
/* IMPORTANT!!!
|
||||||
* Inform LVGL that you are ready with the flushing and buf is not used anymore*/
|
* Inform LVGL that you are ready with the flushing and buf is not used anymore*/
|
||||||
lv_disp_flush_ready(disp);
|
lv_display_flush_ready(disp);
|
||||||
}
|
}
|
||||||
|
|
||||||
Use :cpp:expr:`lv_disp_set_flush_cb(disp, my_flush_cb)` to set a new ``flush_cb``.
|
Use :cpp:expr:`lv_display_set_flush_cb(disp, my_flush_cb)` to set a new ``flush_cb``.
|
||||||
|
|
||||||
:cpp:expr:`lv_disp_flush_ready(disp)` needs to be called when flushing is ready
|
:cpp:expr:`lv_display_flush_ready(disp)` needs to be called when flushing is ready
|
||||||
to inform LVGL the buffer is not used anymore by the driver and it can
|
to inform LVGL the buffer is not used anymore by the driver and it can
|
||||||
render new content into it.
|
render new content into it.
|
||||||
|
|
||||||
LVGL might render the screen in multiple chunks and therefore call
|
LVGL might render the screen in multiple chunks and therefore call
|
||||||
``flush_cb`` multiple times. To see if the current one is the last chunk
|
``flush_cb`` multiple times. To see if the current one is the last chunk
|
||||||
of rendering use :cpp:expr:`lv_disp_flush_is_last(disp)`.
|
of rendering use :cpp:expr:`lv_display_flush_is_last(display)`.
|
||||||
|
|
||||||
Draw buffers
|
Draw buffers
|
||||||
------------
|
------------
|
||||||
|
|
||||||
The draw buffers can be set with
|
The draw buffers can be set with
|
||||||
:cpp:expr:`lv_disp_set_draw_buffers(disp, buf1, buf2, buf_size_px, render_mode)`
|
:cpp:expr:`lv_display_set_draw_buffers(display, buf1, buf2, buf_size_px, render_mode)`
|
||||||
|
|
||||||
- ``buf1`` a buffer where LVGL can render
|
- ``buf1`` a buffer where LVGL can render
|
||||||
- ``buf2`` a second optional buffer (see more details below)
|
- ``buf2`` a second optional buffer (see more details below)
|
||||||
@@ -64,26 +65,27 @@ The draw buffers can be set with
|
|||||||
screen is smaller parts. This way the buffers can be smaller then
|
screen is smaller parts. This way the buffers can be smaller then
|
||||||
the display to save RAM. At least 1/10 screen size buffer(s) are
|
the display to save RAM. At least 1/10 screen size buffer(s) are
|
||||||
recommended. In ``flush_cb`` the rendered images needs to be
|
recommended. In ``flush_cb`` the rendered images needs to be
|
||||||
copied to the given area of the display.
|
copied to the given area of the display. In this mode if a button is pressed
|
||||||
|
only the button's area will be redrawn.
|
||||||
- :cpp:enumerator:`LV_DISP_RENDER_MODE_DIRECT` The buffer(s) has to be screen
|
- :cpp:enumerator:`LV_DISP_RENDER_MODE_DIRECT` The buffer(s) has to be screen
|
||||||
sized and LVGL will render into the correct location of the
|
sized and LVGL will render into the correct location of the
|
||||||
buffer. This way the buffer always contain the whole image. If two
|
buffer. This way the buffer always contain the whole image. If two
|
||||||
buffer are used the rendered ares are automatically copied to the
|
buffer are used the rendered ares are automatically copied to the
|
||||||
other buffer after flushing. Due to this in ``flush_cb`` typically
|
other buffer after flushing. Due to this in ``flush_cb`` typically
|
||||||
only a frame buffer address needs to be changed and always the
|
only a frame buffer address needs to be changed. If a button is pressed
|
||||||
changed areas will be redrawn.
|
only the button's area will be redrawn.
|
||||||
- :cpp:enumerator:`LV_DISP_RENDER_MODE_FULL` The buffer can smaller or screen
|
- :cpp:enumerator:`LV_DISP_RENDER_MODE_FULL` The buffer(s) has to be screen
|
||||||
sized but LVGL will always redraw the whole screen even is only 1
|
sized and LVGL will always redraw the whole screen even if only 1
|
||||||
pixel has been changed. If two screen sized draw buffers are
|
pixel has been changed. If two screen sized draw buffers are
|
||||||
provided, LVGL's display handling works like "traditional" double
|
provided, LVGL's display handling works like "traditional" double
|
||||||
buffering. This means the ``flush_cb`` callback only has to update
|
buffering. This means the ``flush_cb`` callback only has to update
|
||||||
the address of the framebuffer (``color_p`` parameter).
|
the address of the frame buffer to the ``px_map`` parameter.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
.. code:: c
|
.. code:: c
|
||||||
|
|
||||||
static lv_color_t buf[LCD_HOR_RES * LCD_VER_RES / 10];
|
static uint16_t buf[LCD_HOR_RES * LCD_VER_RES / 10];
|
||||||
lv_disp_set_draw_buffers(disp, buf, NULL, sizeof(buf), LV_DISP_RENDER_MODE_PARTIAL);
|
lv_disp_set_draw_buffers(disp, buf, NULL, sizeof(buf), LV_DISP_RENDER_MODE_PARTIAL);
|
||||||
|
|
||||||
One buffer
|
One buffer
|
||||||
@@ -91,8 +93,9 @@ One buffer
|
|||||||
|
|
||||||
If only one buffer is used LVGL draws the content of the screen into
|
If only one buffer is used LVGL draws the content of the screen into
|
||||||
that draw buffer and sends it to the display via the ``flush_cb``. LVGL
|
that draw buffer and sends it to the display via the ``flush_cb``. LVGL
|
||||||
then needs to wait until the content of the buffer is sent to the
|
then needs to wait until :cpp:expr:`lv_display_flush_ready` is called
|
||||||
display before drawing something new into it.
|
(that is the content of the buffer is sent to the
|
||||||
|
display) before drawing something new into it.
|
||||||
|
|
||||||
Two buffers
|
Two buffers
|
||||||
^^^^^^^^^^^
|
^^^^^^^^^^^
|
||||||
@@ -110,111 +113,69 @@ Resolution
|
|||||||
----------
|
----------
|
||||||
|
|
||||||
To set the resolution of the display after creation use
|
To set the resolution of the display after creation use
|
||||||
:cpp:expr:`lv_disp_set_res(disp, hor_res, ver_res)`
|
:cpp:expr:`lv_display_set_resolution(display, hor_res, ver_res)`
|
||||||
|
|
||||||
It's not mandatory to use the whole display for LVGL, however in some
|
It's not mandatory to use the whole display for LVGL, however in some
|
||||||
cases the physical resolution is important. For example the touchpad
|
cases the physical resolution is important. For example the touchpad
|
||||||
still sees the whole resolution and the values needs to be converted to
|
still sees the whole resolution and the values needs to be converted to
|
||||||
the active LVGL display area. So the physical resolution and the offset
|
the active LVGL display area. So the physical resolution and the offset
|
||||||
of the active area can be set with
|
of the active area can be set with
|
||||||
:cpp:expr:`lv_disp_set_physical_res(disp, hor_res, ver_res)` and
|
:cpp:expr:`lv_display_set_physical_resolution(disp, hor_res, ver_res)` and
|
||||||
:cpp:expr:`lv_disp_set_offset(disp, x, y)`
|
:cpp:expr:`lv_display_set_offset(disp, x, y)`
|
||||||
|
|
||||||
|
Flush wait callback
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
By using :cpp:expr:`lv_display_flush_ready` LVGL will spin in a loop
|
||||||
|
while waiting for flushing.
|
||||||
|
|
||||||
|
However with the help of :cpp:expr:`lv_display_set_flush_wait_cb` a custom
|
||||||
|
wait callback be set for flushing. This callback can use a semaphore, mutex,
|
||||||
|
or anything else to optimize while the waiting for flush.
|
||||||
|
|
||||||
|
If ``flush_wait_cb`` is not set, LVGL assume that `lv_display_flush_ready`
|
||||||
|
is used.
|
||||||
|
|
||||||
Rotation
|
Rotation
|
||||||
--------
|
--------
|
||||||
|
|
||||||
LVGL supports rotation of the display in 90 degree increments. You can
|
LVGL supports rotation of the display in 90 degree increments. You can
|
||||||
select whether you'd like software rotation or hardware rotation.
|
select whether you would like software rotation or hardware rotation.
|
||||||
|
|
||||||
The orientation of the display can be changed with
|
The orientation of the display can be changed with
|
||||||
``lv_disp_set_rotation(disp, LV_DISP_ROTATION_0/90/180/270, true/false)``.
|
``lv_disp_set_rotation(disp, LV_DISPLAY_ROTATION_0/90/180/270)``.
|
||||||
LVGL will swap the horizontal and vertical resolutions internally
|
LVGL will swap the horizontal and vertical resolutions internally
|
||||||
according to the set degree. If the last parameter is ``true`` LVGL will
|
according to the set degree. When changing the rotation
|
||||||
rotate the rendered image. If it's ``false`` the display driver should
|
:cpp:expr:`LV_EVENT_SIZE_CHANGED` is sent to the display to allow
|
||||||
rotate the rendered image.
|
reconfiguring the hardware. In lack of hardware display rotation support
|
||||||
|
:cpp:expr:`lv_draw_sw_rotate` can be used to rotate the buffer in the
|
||||||
|
``flush_cb``.
|
||||||
|
|
||||||
Color format
|
Color format
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Set the color format of the display. The default is
|
The default color format of the display is set according to :c:macro:`LV_COLOR_DEPTH`
|
||||||
:cpp:enumerator:`LV_COLOR_FORMAT_NATIVE` which means LVGL render with the follow
|
(see ``lv_conf.h``)
|
||||||
formats depending on :c:macro:`LV_COLOR_DEPTH`:
|
|
||||||
|
|
||||||
- :c:macro:`LV_COLOR_DEPTH` ``32``: XRGB8888 (4 bytes/pixel)
|
- :c:macro:`LV_COLOR_DEPTH` ``32``: XRGB8888 (4 bytes/pixel)
|
||||||
- :c:macro:`LV_COLOR_DEPTH` ``24``: RGB888 (3 bytes/pixel)
|
- :c:macro:`LV_COLOR_DEPTH` ``24``: RGB888 (3 bytes/pixel)
|
||||||
- :c:macro:`LV_COLOR_DEPTH` ``16``: RGB565 (2 bytes/pixel)
|
- :c:macro:`LV_COLOR_DEPTH` ``16``: RGB565 (2 bytes/pixel)
|
||||||
- :c:macro:`LV_COLOR_DEPTH` ``8``: L8 (1 bytes/pixel)
|
- :c:macro:`LV_COLOR_DEPTH` ``8``: L8 (1 bytes/pixel) Not supported yet
|
||||||
|
|
||||||
The ``color_format`` can be changed with
|
The ``color_format`` can be changed with
|
||||||
:cpp:expr:`lv_disp_set_color_depth(disp, LV_COLOR_FORMAT_...)` to the following
|
:cpp:expr:`lv_display_set_color_depth(display, LV_COLOR_FORMAT_...)`.
|
||||||
values:
|
Besides the default value :c:macro:`LV_COLOR_FORMAT_ARGB8888` can be
|
||||||
|
used as a well.
|
||||||
|
|
||||||
- :cpp:enumerator:`LV_COLOR_FORMAT_NATIVE_ALPHA`: Append an alpha byte to the native format resulting
|
It's very important that draw buffer(s) should be large enough for any
|
||||||
in A8L8, ARGB8565, ARGB8888 formats.
|
selected color format.
|
||||||
- :cpp:enumerator:`LV_COLOR_FORMAT_NATIVE_REVERSE`: Reverse the byte order of the native format. Useful if the
|
|
||||||
rendered image is sent to the display via SPI and
|
|
||||||
the display needs the bytes in the opposite order.
|
|
||||||
- :cpp:enumerator:`LV_COLOR_FORMAT_L8`: Lightness only on 8 bit
|
|
||||||
- :cpp:enumerator:`LV_COLOR_FORMAT_A8`: Alpha only on 8 bit
|
|
||||||
- :cpp:enumerator:`LV_COLOR_FORMAT_I8`: Indexed (palette) 8 bit
|
|
||||||
- :cpp:enumerator:`LV_COLOR_FORMAT_A8L8`: Lightness on 8 bit with 8 bit alpha
|
|
||||||
- :cpp:enumerator:`LV_COLOR_FORMAT_ARGB2222`: ARGB with 2 bit for each channel
|
|
||||||
- :cpp:enumerator:`LV_COLOR_FORMAT_RGB565`: 16 bit RGB565 format without alpha channel
|
|
||||||
- :cpp:enumerator:`LV_COLOR_FORMAT_ARGB8565`: 16 bit RGB565 format and 8 bit alpha channel
|
|
||||||
- :cpp:enumerator:`LV_COLOR_FORMAT_ARGB1555`: 5 bit for each color channel and 1 bit for alpha
|
|
||||||
- :cpp:enumerator:`LV_COLOR_FORMAT_ARGB4444`: 4 bit for each channel
|
|
||||||
- :cpp:enumerator:`LV_COLOR_FORMAT_RGB888`: 8 bit for each color channel with out alpha channel
|
|
||||||
- :cpp:enumerator:`LV_COLOR_FORMAT_ARGB8888`: 8 bit for each channel
|
|
||||||
- :cpp:enumerator:`LV_COLOR_FORMAT_XRGB8888`: 8 bit for each color channel and 8 bit placeholder for the alpha channel
|
|
||||||
|
|
||||||
If the color format is set to non-native ``draw_ctx->buffer_convert``
|
|
||||||
function will be called before calling ``flush_cb`` to convert the
|
|
||||||
native color format to the desired, therefore rendering in non-native
|
|
||||||
formats has a negative effect on performance. Learn more about
|
|
||||||
``draw_ctx`` `here </porting/gpu>`__.
|
|
||||||
|
|
||||||
It's very important that draw buffer(s) should be large enough for both
|
|
||||||
the native format and the target color format. For example if
|
|
||||||
``LV_COLOR_DEPTH == 16`` and :cpp:enumerator:`LV_COLOR_FORMAT_XRGB8888` is selected
|
|
||||||
LVGL will choose the larger to figure out how many pixel can be
|
|
||||||
rendered at once. Therefore with :cpp:enumerator:`LV_DISP_RENDER_MODE_FULL` and the
|
|
||||||
larger pixel size needs to be chosen.
|
|
||||||
|
|
||||||
:cpp:enumerator:`LV_DISP_RENDER_MODE_DIRECT` supports only the
|
|
||||||
:cpp:enumerator:`LV_COLOR_FORMAT_NATIVE` format.
|
|
||||||
|
|
||||||
Antialiasing
|
|
||||||
------------
|
|
||||||
|
|
||||||
:cpp:expr:`lv_disp_set_antialiasing(disp, true/false)` enables/disables the
|
|
||||||
antialiasing (edge smoothing) on the given display.
|
|
||||||
|
|
||||||
User data
|
User data
|
||||||
---------
|
---------
|
||||||
|
|
||||||
With :cpp:expr:`lv_disp_set_user_data(disp, p)` a pointer to a custom data can
|
With :cpp:expr:`lv_display_set_user_data(disp, p)` a pointer to a custom data can
|
||||||
be stored in display object.
|
be stored in display object.
|
||||||
|
|
||||||
Events
|
|
||||||
******
|
|
||||||
|
|
||||||
:cpp:expr:`lv_disp_add_event_cb(disp, event_cb, LV_DISP_EVENT_..., user_data)` adds
|
|
||||||
an event handler to a display. The following events are sent:
|
|
||||||
|
|
||||||
- :cpp:enumerator:`LV_DISP_EVENT_INVALIDATE_AREA` An area is invalidated (marked for redraw).
|
|
||||||
:cpp:expr:`lv_event_get_param(e)` returns a pointer to an :cpp:struct:`lv_area_t`
|
|
||||||
variable with the coordinates of the area to be invalidated. The area can
|
|
||||||
be freely modified is needed to adopt it the special requirement of the
|
|
||||||
display. Usually needed with monochrome displays to invalidate Nx8
|
|
||||||
lines at once.
|
|
||||||
- :cpp:enumerator:`LV_DISP_EVENT_RENDER_START`: Called when rendering starts.
|
|
||||||
- :cpp:enumerator:`LV_DISP_EVENT_RENDER_READY`: Called when rendering is ready
|
|
||||||
- :cpp:enumerator:`LV_DISP_EVENT_RESOLUTION_CHANGED`: Called when the resolution changes due
|
|
||||||
to :cpp:func:`lv_disp_set_resolution` or :cpp:func:`lv_disp_set_rotation`.
|
|
||||||
|
|
||||||
Other options
|
|
||||||
*************
|
|
||||||
|
|
||||||
Decoupling the display refresh timer
|
Decoupling the display refresh timer
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
|
||||||
@@ -246,6 +207,30 @@ select the display to refresh before :cpp:expr:`_lv_disp_refr_timer(NULL)`.
|
|||||||
If the performance monitor is enabled, the value of :c:macro:`LV_DEF_REFR_PERIOD` needs to be set to be
|
If the performance monitor is enabled, the value of :c:macro:`LV_DEF_REFR_PERIOD` needs to be set to be
|
||||||
consistent with the refresh period of the display to ensure that the statistical results are correct.
|
consistent with the refresh period of the display to ensure that the statistical results are correct.
|
||||||
|
|
||||||
|
|
||||||
|
Events
|
||||||
|
******
|
||||||
|
|
||||||
|
:cpp:expr:`lv_display_add_event_cb(disp, event_cb, LV_EVENT_..., user_data)` adds
|
||||||
|
an event handler to a display. The following events are sent:
|
||||||
|
|
||||||
|
- :cpp:enumerator:`LV_EVENT_INVALIDATE_AREA` An area is invalidated (marked for redraw).
|
||||||
|
:cpp:expr:`lv_event_get_param(e)` returns a pointer to an :cpp:struct:`lv_area_t`
|
||||||
|
variable with the coordinates of the area to be invalidated. The area can
|
||||||
|
be freely modified if needed to adopt it the special requirement of the
|
||||||
|
display. Usually needed with monochrome displays to invalidate ``N x 8``
|
||||||
|
rows or columns at once.
|
||||||
|
- :cpp:enumerator:`LV_EVENT_REFR_REQUEST`: Sent when something happened that requires redraw.
|
||||||
|
- :cpp:enumerator:`LV_EVENT_REFR_START`: Sent when a refreshing cycle starts. Sent even if there is nothing to redraw.
|
||||||
|
- :cpp:enumerator:`LV_EVENT_REFR_READY`: Sent when refreshing is ready (after rendering and calling the ``flush_cb``). Sent even if no redraw happened.
|
||||||
|
- :cpp:enumerator:`LV_EVENT_RENDER_START`: Sent when rendering starts.
|
||||||
|
- :cpp:enumerator:`LV_EVENT_RENDER_READY`: Sent when rendering is ready (before calling the ``flush_cb``)
|
||||||
|
- :cpp:enumerator:`LV_EVENT_FLUSH_START`: Sent before the ``flush_cb`` is called.
|
||||||
|
- :cpp:enumerator:`LV_EVENT_FLUSH_READY`: Sent when the ``flush_cb`` returned.
|
||||||
|
- :cpp:enumerator:`LV_EVENT_RESOLUTION_CHANGED`: Sent when the resolution changes due
|
||||||
|
to :cpp:func:`lv_display_set_resolution` or :cpp:func:`lv_display_set_rotation`.
|
||||||
|
|
||||||
|
|
||||||
Further reading
|
Further reading
|
||||||
***************
|
***************
|
||||||
|
|
||||||
|
|||||||
@@ -1,252 +1,75 @@
|
|||||||
==============
|
==========
|
||||||
Add custom GPU
|
Custom GPU
|
||||||
==============
|
==========
|
||||||
|
|
||||||
LVGL has a flexible and extendable draw pipeline. You can hook it to do
|
LVGL has a flexible and extendable draw pipeline. You can hook it to do
|
||||||
some rendering with a GPU or even completely replace the built-in
|
some rendering with a GPU or even completely replace the built-in
|
||||||
software renderer.
|
software renderer.
|
||||||
|
|
||||||
Draw context
|
|
||||||
************
|
|
||||||
|
|
||||||
The core structure of drawing is :cpp:type:`lv_draw_ctx_t`. It contains a
|
Overview
|
||||||
pointer to a buffer where drawing should happen and a couple of
|
********
|
||||||
callbacks to draw rectangles, texts, and other primitives.
|
|
||||||
|
|
||||||
Fields
|
Draw task
|
||||||
------
|
---------
|
||||||
|
|
||||||
:cpp:type:`lv_draw_ctx_t` has the following fields:
|
|
||||||
|
|
||||||
- ``void * buf`` Pointer to a buffer to draw into
|
|
||||||
- ``lv_area_t * buf_area`` The position and size of ``buf`` (absolute coordinates)
|
|
||||||
- ``const lv_area_t * clip_area`` The current clip area with absolute coordinates, always the same or smaller than ``buf_area``. All drawings should be clipped to this area.
|
|
||||||
- ``void (*draw_rect)()`` Draw a rectangle with shadow, gradient, border, etc.
|
|
||||||
- ``void (*draw_arc)()`` Draw an arc
|
|
||||||
- ``void (*draw_img_decoded)()`` Draw an (A)RGB image that is already decoded by LVGL.
|
|
||||||
- ``lv_res_t (*draw_img)()`` Draw an image before decoding it (it bypasses LVGL's internal image decoders)
|
|
||||||
- ``void (*draw_letter)()`` Draw a letter
|
|
||||||
- ``void (*draw_line)()`` Draw a line - ``void (*draw_polygon)()`` Draw a polygon
|
|
||||||
- ``void (*draw_bg)()`` Replace the buffer with a rect without decoration like radius or borders.
|
|
||||||
- ``void (*wait_for_finish)()`` Wait until all background operation are finished. (E.g. GPU operations)
|
|
||||||
- ``void * user_data`` Custom user data for arbitrary purpose
|
|
||||||
|
|
||||||
(For the sake of simplicity the parameters of the callbacks are not shown here.)
|
|
||||||
|
|
||||||
All ``draw_*`` callbacks receive a pointer to the current ``draw_ctx``
|
|
||||||
as their first parameter. Among the other parameters there is a
|
|
||||||
descriptor that tells what to draw, e.g. for ``draw_rect`` it's called
|
|
||||||
:cpp:struct:`lv_draw_rect_dsc_t`,
|
|
||||||
for :cpp:func:`lv_draw_line` it's called :cpp:struct:`lv_draw_line_dsc_t`,
|
|
||||||
etc.
|
|
||||||
|
|
||||||
To correctly render according to a ``draw_dsc`` you need to be familiar
|
|
||||||
with the `Boxing model </overview/coords.html#boxing-model>`__
|
|
||||||
of LVGL and the meanings of the fields. The name and meaning of the
|
|
||||||
fields are identical to name and meaning of the `Style properties </overview/style-props.html>`__.
|
|
||||||
|
|
||||||
Initialization
|
|
||||||
--------------
|
|
||||||
|
|
||||||
The :cpp:type:`lv_disp_t` has 4 fields related to the draw context:
|
|
||||||
|
|
||||||
- ``lv_draw_ctx_t * draw_ctx`` Pointer to the ``draw_ctx`` of this display
|
|
||||||
- ``void (*draw_ctx_init)(struct _lv_disp_t * disp_drv, lv_draw_ctx_t * draw_ctx)`` Callback to initialize a ``draw_ctx``
|
|
||||||
- ``void (*draw_ctx_deinit)(struct _lv_disp_t * disp_drv, lv_draw_ctx_t * draw_ctx)`` Callback to de-initialize a ``draw_ctx``
|
|
||||||
- ``size_t draw_ctx_size`` Size of the draw context structure. E.g. :cpp:expr:`sizeof(lv_draw_sw_ctx_t)`
|
|
||||||
|
|
||||||
When you ignore these fields, LVGL will set default values for callbacks
|
|
||||||
and size in :cpp:func:`lv_disp_drv_init` based on the configuration in
|
|
||||||
``lv_conf.h``. :cpp:func:`lv_disp_drv_register` will allocate a ``draw_ctx``
|
|
||||||
based on ``draw_ctx_size`` and call :cpp:func:`draw_ctx_init` on it.
|
|
||||||
|
|
||||||
However, you can overwrite the callbacks and the size values before
|
|
||||||
calling :cpp:func:`lv_disp_drv_register`. It makes it possible to use your own
|
|
||||||
``draw_ctx`` with your own callbacks.
|
|
||||||
|
|
||||||
Software renderer
|
|
||||||
*****************
|
|
||||||
|
|
||||||
LVGL's built in software renderer extends the basic :cpp:type:`lv_draw_ctx_t`
|
|
||||||
structure and sets the draw callbacks. It looks like this:
|
|
||||||
|
|
||||||
.. code:: c
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
/** Include the basic draw_ctx type*/
|
|
||||||
lv_draw_ctx_t base_draw;
|
|
||||||
|
|
||||||
/** Blend a color or image to an area*/
|
|
||||||
void (*blend)(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc);
|
|
||||||
} lv_draw_sw_ctx_t;
|
|
||||||
|
|
||||||
Set the draw callbacks in :cpp:func:`draw_ctx_init` like:
|
|
||||||
|
|
||||||
.. code:: c
|
|
||||||
|
|
||||||
draw_sw_ctx->base_draw.draw_rect = lv_draw_sw_rect;
|
|
||||||
draw_sw_ctx->base_draw.draw_letter = lv_draw_sw_letter;
|
|
||||||
...
|
|
||||||
|
|
||||||
Blend callback
|
|
||||||
--------------
|
|
||||||
|
|
||||||
As you saw above the software renderer adds the ``blend`` callback
|
|
||||||
field. It's a special callback related to how the software renderer
|
|
||||||
works. All draw operations end up in the ``blend`` callback which can
|
|
||||||
either fill an area or copy an image to an area by considering an optional mask.
|
|
||||||
|
|
||||||
The :cpp:struct:`lv_draw_sw_blend_dsc_t` parameter describes what and how to
|
|
||||||
blend. It has the following fields:
|
|
||||||
|
|
||||||
- ``const lv_area_t * blend_area`` The area with absolute coordinates to draw
|
|
||||||
on ``draw_ctx->buf``. If ``src_buf`` is set, it's the coordinates of the image to blend.
|
|
||||||
- ``const lv_color_t * src_buf`` Pointer to an image to blend. If set,
|
|
||||||
``color`` is ignored. If not set fill ``blend_area`` with ``color``
|
|
||||||
- ``lv_color_t color`` Fill color. Used only if ``src_buf == NULL``
|
|
||||||
- ``lv_opa_t * mask_buf`` NULL if ignored, or an alpha mask to apply on ``blend_area``
|
|
||||||
- ``lv_draw_mask_res_t mask_res`` The result of the previous mask operation. (``LV_DRAW_MASK_RES_...``)
|
|
||||||
- ``const lv_area_t * mask_area`` The area of ``mask_buf`` with absolute coordinates
|
|
||||||
- ``lv_opa_t opa`` The overall opacity
|
|
||||||
- ``lv_blend_mode_t blend_mode`` E.g. :cpp:enumerator:`LV_BLEND_MODE_ADDITIVE`
|
|
||||||
|
|
||||||
Extend the software renderer
|
|
||||||
****************************
|
|
||||||
|
|
||||||
New blend callback
|
|
||||||
------------------
|
|
||||||
|
|
||||||
Let's take a practical example: you would like to use your MCUs GPU for
|
|
||||||
color fill operations only.
|
|
||||||
|
|
||||||
As all draw callbacks call ``blend`` callback to fill an area in the end
|
|
||||||
only the ``blend`` callback needs to be overwritten.
|
|
||||||
|
|
||||||
First extend :cpp:struct:`lv_draw_sw_ctx_t`:
|
|
||||||
|
|
||||||
.. code:: c
|
|
||||||
|
|
||||||
|
|
||||||
/*We don't add new fields, so just for clarity add new type*/
|
When :cpp:expr`lv_draw_rect`, :cpp:expr`lv_draw_label` or similar functions are called
|
||||||
typedef lv_draw_sw_ctx_t my_draw_ctx_t;
|
LVGL creates a so called draw task.
|
||||||
|
|
||||||
void my_draw_ctx_init(lv_disp_t * drv, lv_draw_ctx_t * draw_ctx)
|
Draw unit
|
||||||
{
|
---------
|
||||||
/*Initialize the parent type first */
|
|
||||||
lv_draw_sw_init_ctx(drv, draw_ctx);
|
|
||||||
|
|
||||||
/*Change some callbacks*/
|
The draw tasks are collected in a list and periodically dispatched to draw units. A
|
||||||
my_draw_ctx_t * my_draw_ctx = (my_draw_ctx_t *)draw_ctx;
|
draw unit can a CPU core, a GPU, just a new rendering library for certain or all draw tasks,
|
||||||
|
or basically anything that can draw somehow.
|
||||||
|
|
||||||
my_draw_ctx->blend = my_draw_blend;
|
Draw task evaluation
|
||||||
my_draw_ctx->base_draw.wait_for_finish = my_gpu_wait;
|
|
||||||
}
|
|
||||||
|
|
||||||
After calling :cpp:expr:`lv_disp_draw_init(&drv)` you can assign the new
|
|
||||||
:cpp:func:`draw_ctx_init` callback and set ``draw_ctx_size`` to overwrite the
|
|
||||||
defaults:
|
|
||||||
|
|
||||||
.. code:: c
|
|
||||||
|
|
||||||
static lv_disp_t drv;
|
|
||||||
lv_disp_draw_init(&drv);
|
|
||||||
drv->hor_res = my_hor_res;
|
|
||||||
drv->ver_res = my_ver_res;
|
|
||||||
drv->flush_cb = my_flush_cb;
|
|
||||||
|
|
||||||
/*New draw ctx settings*/
|
|
||||||
drv->draw_ctx_init = my_draw_ctx_init;
|
|
||||||
drv->draw_ctx_size = sizeof(my_draw_ctx_t);
|
|
||||||
|
|
||||||
lv_disp_drv_register(&drv);
|
|
||||||
|
|
||||||
This way when LVGL calls ``blend`` it will call ``my_draw_blend`` and we
|
|
||||||
can do custom GPU operations. Here is a complete example:
|
|
||||||
|
|
||||||
.. code:: c
|
|
||||||
|
|
||||||
void my_draw_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc)
|
|
||||||
{
|
|
||||||
/*Let's get the blend area which is the intersection of the area to fill and the clip area.*/
|
|
||||||
lv_area_t blend_area;
|
|
||||||
if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area)) return; /*Fully clipped, nothing to do*/
|
|
||||||
|
|
||||||
/*Fill only non masked, fully opaque, normal blended and not too small areas*/
|
|
||||||
if(dsc->src_buf == NULL && dsc->mask == NULL && dsc->opa >= LV_OPA_MAX &&
|
|
||||||
dsc->blend_mode == LV_BLEND_MODE_NORMAL && lv_area_get_size(&blend_area) > 100) {
|
|
||||||
|
|
||||||
/*Got the first pixel on the buffer*/
|
|
||||||
int32_t dest_stride = lv_area_get_width(draw_ctx->buf_area); /*Width of the destination buffer*/
|
|
||||||
lv_color_t * dest_buf = draw_ctx->buf;
|
|
||||||
dest_buf += dest_stride * (blend_area.y1 - draw_ctx->buf_area->y1) + (blend_area.x1 - draw_ctx->buf_area->x1);
|
|
||||||
|
|
||||||
/*Make the blend area relative to the buffer*/
|
|
||||||
lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
|
|
||||||
|
|
||||||
/*Call your custom gou fill function to fill blend_area, on dest_buf with dsc->color*/
|
|
||||||
my_gpu_fill(dest_buf, dest_stride, &blend_area, dsc->color);
|
|
||||||
}
|
|
||||||
/*Fallback: the GPU doesn't support these settings. Call the SW renderer.*/
|
|
||||||
else {
|
|
||||||
lv_draw_sw_blend_basic(draw_ctx, dsc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
The implementation of wait callback is much simpler:
|
|
||||||
|
|
||||||
.. code:: c
|
|
||||||
|
|
||||||
void my_gpu_wait(lv_draw_ctx_t * draw_ctx)
|
|
||||||
{
|
|
||||||
while(my_gpu_is_working());
|
|
||||||
|
|
||||||
/*Call SW renderer's wait callback too*/
|
|
||||||
lv_draw_sw_wait_for_finish(draw_ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
New rectangle drawer
|
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
If your MCU has a more powerful GPU that can draw e.g. rounded
|
Different draw units might render slight different output for example for an image transformation or
|
||||||
rectangles you can replace the original software drawer too. A custom
|
a gradient. If such a draw task were assigned to a different draw units, the screen might jitter a
|
||||||
``draw_rect`` callback might look like this:
|
little bit. To resolve it each draw unit has an ``evaluate_cb`` which is called when a draw task is created.
|
||||||
|
Based on the type and parameters of the draw task each draw unit can decide if it want to assign the
|
||||||
|
draw task to itself. This way a certain type of draw task (e.g. rounded rectangle with horizontal
|
||||||
|
gradient) will be always assigned to the same draw unit. It avoid the above mentioned issue of
|
||||||
|
slight difference between draw units.
|
||||||
|
|
||||||
.. code:: c
|
|
||||||
|
|
||||||
void my_draw_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords)
|
Dispatching
|
||||||
{
|
-----------
|
||||||
if(lv_draw_mask_is_any(coords) == false && dsc->grad == NULL && dsc->bg_img_src == NULL &&
|
|
||||||
dsc->shadow_width == 0 && dsc->blend_mode = LV_BLEND_MODE_NORMAL)
|
|
||||||
{
|
|
||||||
/*Draw the background*/
|
|
||||||
my_bg_drawer(draw_ctx, coords, dsc->bg_color, dsc->radius);
|
|
||||||
|
|
||||||
/*Draw the border if any*/
|
While collecting draw tasks LVGL frequently tries to dispatch the collected draw tasks to the draw units.
|
||||||
if(dsc->border_width) {
|
This handles via the ``dispatch_cb`` of the draw units.
|
||||||
my_border_drawer(draw_ctx, coords, dsc->border_width, dsc->border_color, dsc->border_opa)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Draw the outline if any*/
|
If a draw unit is busy with an other draw task, it just returns. However, it is available it can take a draw task.
|
||||||
if(dsc->outline_width) {
|
|
||||||
my_outline_drawer(draw_ctx, coords, dsc->outline_width, dsc->outline_color, dsc->outline_opa, dsc->outline_pad)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*Fallback*/
|
|
||||||
else {
|
|
||||||
lv_draw_sw_rect(draw_ctx, dsc, coords);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
``my_draw_rect`` can fully bypass the use of ``blend`` callback if
|
:cpp:expr:`lv_draw_get_next_available_task(layer, previous_task, draw_unit_id)` is a useful helper function which
|
||||||
needed.
|
returns an available draw task. "Available draw task" means that, all the draw tasks which should be drawn under a draw task
|
||||||
|
are ready and it is assigned to the given draw unit.
|
||||||
|
|
||||||
Fully custom draw engine
|
|
||||||
************************
|
|
||||||
|
|
||||||
For example if your MCU/MPU supports a powerful vector graphics engine
|
Layers
|
||||||
you might use only that instead of LVGL's SW renderer. In this case, you
|
------
|
||||||
need to base the renderer on the basic :cpp:type:`lv_draw_ctx_t` (instead of
|
|
||||||
:cpp:struct:`lv_draw_sw_ctx_t`) and extend/initialize it as you wish.
|
A layer is a buffer with a given area on which rendering happens. Each display has a "main" layer, but
|
||||||
|
during rendering additional layers might be created internally to handle for example arbitrary widget transformations.
|
||||||
|
|
||||||
|
|
||||||
|
Hierarchy of modules
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
All these together looks like this
|
||||||
|
- list of draw units
|
||||||
|
- display(s)
|
||||||
|
- layer(s): Each display has its own list of layers
|
||||||
|
- draw tasks: Each layer has its own list of draw tasks
|
||||||
|
|
||||||
|
References
|
||||||
|
**********
|
||||||
|
|
||||||
|
As a reference take a look at `lv_draw_sw.c <https://github.com/lvgl/lvgl/blob/master/src/draw/sw/lv_draw_sw.c>`__
|
||||||
|
|
||||||
API
|
API
|
||||||
***
|
***
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ Add lvgl to your project
|
|||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
The graphics library itself is the ``lvgl`` directory. It contains a
|
The graphics library itself is the ``lvgl`` directory. It contains a
|
||||||
couple of folders but to use ``lvgl`` you only need ``.c`` and ``.h``
|
couple of folders but to use ``lvgl`` you only need the ``.c`` and ``.h``
|
||||||
files from the ``src`` folder.
|
files in the ``src`` folder.
|
||||||
|
|
||||||
Automatically add files
|
Automatically add files
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
@@ -39,12 +39,12 @@ main Makefile:
|
|||||||
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/lvgl.mk
|
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/lvgl.mk
|
||||||
|
|
||||||
For integration with CMake take a look this section of the
|
For integration with CMake take a look this section of the
|
||||||
`Documentation </get-started/platforms/cmake>`__.
|
`Documentation </integration/build/cmake>`__.
|
||||||
|
|
||||||
Other platforms and tools
|
Other platforms and tools
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
The `Get started </get-started/index>`__ section contains many platform
|
The `Get started </integartion/index>`__ section contains many platform
|
||||||
specific descriptions e.g. for ESP32, Arduino, NXP, RT-Thread, NuttX,
|
specific descriptions e.g. for ESP32, Arduino, NXP, RT-Thread, NuttX,
|
||||||
etc.
|
etc.
|
||||||
|
|
||||||
@@ -61,8 +61,8 @@ Configuration file
|
|||||||
------------------
|
------------------
|
||||||
|
|
||||||
There is a configuration header file for LVGL called **lv_conf.h**. You
|
There is a configuration header file for LVGL called **lv_conf.h**. You
|
||||||
modify this header to set the library's basic behavior, disable unused
|
can modify this header to set the library's basic behavior, disable unused
|
||||||
modules and features, adjust the size of memory buffers in compile-time,
|
modules and features, adjust the size of buffers in compile-time,
|
||||||
etc.
|
etc.
|
||||||
|
|
||||||
To get ``lv_conf.h`` **copy lvgl/lv_conf_template.h** next to the
|
To get ``lv_conf.h`` **copy lvgl/lv_conf_template.h** next to the
|
||||||
@@ -94,12 +94,12 @@ be set via the :c:macro:`LV_CONF_PATH` define. For example
|
|||||||
|
|
||||||
If :c:macro:`LV_CONF_SKIP` is defined, LVGL will not try to include
|
If :c:macro:`LV_CONF_SKIP` is defined, LVGL will not try to include
|
||||||
``lv_conf.h``. Instead you can pass the config defines using build
|
``lv_conf.h``. Instead you can pass the config defines using build
|
||||||
options. For example ``"-DLV_COLOR_DEPTH=32 -DLV_USE_BTN=1"``. The unset
|
options. For example ``"-DLV_COLOR_DEPTH=32 -DLV_USE_BUTTON=1"``. The unset
|
||||||
options will get a default value which is the same as the ones in
|
options will get a default value which is the same as the content of
|
||||||
``lv_conf_template.h``.
|
``lv_conf_template.h``.
|
||||||
|
|
||||||
LVGL also can be used via ``Kconfig`` and ``menuconfig``. You can use
|
LVGL also can be used via ``Kconfig`` and ``menuconfig``. You can use
|
||||||
``lv_conf.h`` together with Kconfig, but keep in mind that the value
|
``lv_conf.h`` together with Kconfig too, but keep in mind that the value
|
||||||
from ``lv_conf.h`` or build settings (``-D...``) overwrite the values
|
from ``lv_conf.h`` or build settings (``-D...``) overwrite the values
|
||||||
set in Kconfig. To ignore the configs from ``lv_conf.h`` simply remove
|
set in Kconfig. To ignore the configs from ``lv_conf.h`` simply remove
|
||||||
its content, or define :c:macro:`LV_CONF_SKIP`.
|
its content, or define :c:macro:`LV_CONF_SKIP`.
|
||||||
@@ -107,6 +107,8 @@ its content, or define :c:macro:`LV_CONF_SKIP`.
|
|||||||
To enable multi-instance feature, set :c:macro:`LV_GLOBAL_CUSTOM` in
|
To enable multi-instance feature, set :c:macro:`LV_GLOBAL_CUSTOM` in
|
||||||
``lv_conf.h`` and provide a custom function to
|
``lv_conf.h`` and provide a custom function to
|
||||||
:cpp:func:`lv_global_default` using ``__thread`` or ``pthread_key_t``.
|
:cpp:func:`lv_global_default` using ``__thread`` or ``pthread_key_t``.
|
||||||
|
It will allow running multiple LVGL instances by storing the global variables
|
||||||
|
in TLS (Thread Local Storage).
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
@@ -125,7 +127,7 @@ Initialization
|
|||||||
To use the graphics library you have to initialize it and setup required
|
To use the graphics library you have to initialize it and setup required
|
||||||
components. The order of the initialization is:
|
components. The order of the initialization is:
|
||||||
|
|
||||||
1. Call :cpp:func:`lv_init`.
|
1. Call :cpp:func:`lv_init()`.
|
||||||
2. Initialize your drivers.
|
2. Initialize your drivers.
|
||||||
3. Register the display and input devices drivers in LVGL. Learn more
|
3. Register the display and input devices drivers in LVGL. Learn more
|
||||||
about `Display </porting/display>`__ and `Input
|
about `Display </porting/display>`__ and `Input
|
||||||
|
|||||||
@@ -420,7 +420,7 @@ refr_finish:
|
|||||||
_lv_draw_sw_mask_cleanup();
|
_lv_draw_sw_mask_cleanup();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
lv_display_send_event(disp_refr, LV_EVENT_REFR_FINISH, NULL);
|
lv_display_send_event(disp_refr, LV_EVENT_REFR_READY, NULL);
|
||||||
|
|
||||||
LV_TRACE_REFR("finished");
|
LV_TRACE_REFR("finished");
|
||||||
LV_PROFILER_END;
|
LV_PROFILER_END;
|
||||||
@@ -1006,14 +1006,7 @@ static void draw_buf_flush(lv_display_t * disp)
|
|||||||
bool flushing_last = disp->flushing_last;
|
bool flushing_last = disp->flushing_last;
|
||||||
|
|
||||||
if(disp->flush_cb) {
|
if(disp->flush_cb) {
|
||||||
/*Rotate the buffer to the display's native orientation if necessary*/
|
call_flush_cb(disp, &disp->refreshed_area, layer->buf);
|
||||||
if(disp->rotation != LV_DISPLAY_ROTATION_0 && disp->sw_rotate) {
|
|
||||||
LV_LOG_WARN("SW rotation is not supported now");
|
|
||||||
call_flush_cb(disp, &disp->refreshed_area, layer->buf);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
call_flush_cb(disp, &disp->refreshed_area, layer->buf);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/*If there are 2 buffers swap them. With direct mode swap only on the last area*/
|
/*If there are 2 buffers swap them. With direct mode swap only on the last area*/
|
||||||
if(lv_display_is_double_buffered(disp) && (disp->render_mode != LV_DISPLAY_RENDER_MODE_DIRECT || flushing_last)) {
|
if(lv_display_is_double_buffered(disp) && (disp->render_mode != LV_DISPLAY_RENDER_MODE_DIRECT || flushing_last)) {
|
||||||
|
|||||||
@@ -720,13 +720,12 @@ lv_result_t lv_display_send_event(lv_display_t * disp, lv_event_code_t code, voi
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lv_display_set_rotation(lv_display_t * disp, lv_display_rotation_t rotation, bool sw_rotate)
|
void lv_display_set_rotation(lv_display_t * disp, lv_display_rotation_t rotation)
|
||||||
{
|
{
|
||||||
if(disp == NULL) disp = lv_display_get_default();
|
if(disp == NULL) disp = lv_display_get_default();
|
||||||
if(disp == NULL) return;
|
if(disp == NULL) return;
|
||||||
|
|
||||||
disp->rotation = rotation;
|
disp->rotation = rotation;
|
||||||
disp->sw_rotate = sw_rotate;
|
|
||||||
update_resolution(disp);
|
update_resolution(disp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -159,10 +159,8 @@ void lv_display_set_offset(lv_display_t * disp, int32_t x, int32_t y);
|
|||||||
* Set the rotation of this display. LVGL will swap the horizontal and vertical resolutions internally.
|
* Set the rotation of this display. LVGL will swap the horizontal and vertical resolutions internally.
|
||||||
* @param disp pointer to a display (NULL to use the default display)
|
* @param disp pointer to a display (NULL to use the default display)
|
||||||
* @param rotation `LV_DISPLAY_ROTATION_0/90/180/270`
|
* @param rotation `LV_DISPLAY_ROTATION_0/90/180/270`
|
||||||
* @param sw_rotate true: make LVGL rotate the rendered image;
|
|
||||||
* false: the display driver should rotate the rendered image
|
|
||||||
*/
|
*/
|
||||||
void lv_display_set_rotation(lv_display_t * disp, lv_display_rotation_t rotation, bool sw_rotate);
|
void lv_display_set_rotation(lv_display_t * disp, lv_display_rotation_t rotation);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the DPI (dot per inch) of the display.
|
* Set the DPI (dot per inch) of the display.
|
||||||
|
|||||||
@@ -97,12 +97,12 @@ typedef enum {
|
|||||||
|
|
||||||
/** Events of optional LVGL components*/
|
/** Events of optional LVGL components*/
|
||||||
LV_EVENT_INVALIDATE_AREA,
|
LV_EVENT_INVALIDATE_AREA,
|
||||||
LV_EVENT_RENDER_START,
|
|
||||||
LV_EVENT_RENDER_READY,
|
|
||||||
LV_EVENT_RESOLUTION_CHANGED,
|
LV_EVENT_RESOLUTION_CHANGED,
|
||||||
LV_EVENT_REFR_REQUEST,
|
LV_EVENT_REFR_REQUEST,
|
||||||
LV_EVENT_REFR_START,
|
LV_EVENT_REFR_START,
|
||||||
LV_EVENT_REFR_FINISH,
|
LV_EVENT_REFR_READY,
|
||||||
|
LV_EVENT_RENDER_START,
|
||||||
|
LV_EVENT_RENDER_READY,
|
||||||
LV_EVENT_FLUSH_START,
|
LV_EVENT_FLUSH_START,
|
||||||
LV_EVENT_FLUSH_FINISH,
|
LV_EVENT_FLUSH_FINISH,
|
||||||
|
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ static void perf_monitor_disp_event_cb(lv_event_t * e)
|
|||||||
info->measured.refr_interval_sum += lv_tick_elaps(info->measured.refr_start);
|
info->measured.refr_interval_sum += lv_tick_elaps(info->measured.refr_start);
|
||||||
info->measured.refr_start = lv_tick_get();
|
info->measured.refr_start = lv_tick_get();
|
||||||
break;
|
break;
|
||||||
case LV_EVENT_REFR_FINISH:
|
case LV_EVENT_REFR_READY:
|
||||||
info->measured.refr_elaps_sum += lv_tick_elaps(info->measured.refr_start);
|
info->measured.refr_elaps_sum += lv_tick_elaps(info->measured.refr_start);
|
||||||
info->measured.refr_cnt++;
|
info->measured.refr_cnt++;
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user