feat(render): basic of tiled rendering (#6761)
This commit is contained in:
committed by
GitHub
parent
911c7e8e72
commit
0daebca18b
@@ -239,6 +239,43 @@ In full and direct modes, the buffer size should be large enough for the whole s
|
||||
As LVGL can not handle fractional width make sure to round the horizontal resolution to 8-
|
||||
(For example 90 to 96)
|
||||
|
||||
|
||||
Tiled Rendering
|
||||
---------------
|
||||
|
||||
When multiple CPU cores are available and a large area needs to be redrawn, LVGL must identify independent areas that can be rendered in parallel.
|
||||
|
||||
For example, if there are 4 CPU cores, one core can draw the screen's background while the other 3 must wait until it is finished. If there are 2 buttons on the screen, those 2 buttons can be rendered in parallel, but 2 cores will still remain idle.
|
||||
|
||||
Due to dependencies among different areas, CPU cores cannot always be fully utilized.
|
||||
|
||||
To address this, LVGL can divide large areas that need to be updated into smaller tiles. These tiles are independent, making it easier to find areas that can be rendered concurrently.
|
||||
|
||||
Specifically, if there are 4 tiles and 4 cores, there will always be an independent area for each core within one of the tiles.
|
||||
|
||||
The maximum number of tiles can be set using the function :cpp:func:`lv_display_set_tile_cnt(disp, cnt)`. The default value is :cpp:expr:`LV_DRAW_SW_DRAW_UNIT_CNT` (or 1 if software rendering is not enabled).
|
||||
|
||||
Small areas are not further divided into smaller tiles because the overhead of spinning up 4 cores would outweigh the benefits.
|
||||
|
||||
The ideal tile size is calculated as ``ideal_tile_size = draw_buf_size / tile_cnt``. For example, in :cpp:enumerator:`LV_DISPLAY_RENDER_MODE_DIRECT` mode on an 800x480 screen, the display buffer is 800x480 = 375k pixels. If there are 4 tiles, the ideal tile size is approximately 93k pixels. Based on this, core utilization is as follows:
|
||||
|
||||
- 30k pixels: 1 core
|
||||
- 90k pixels: 1 core
|
||||
- 95k pixels: 2 cores (above 93k pixels, 2 cores are used)
|
||||
- 150k pixels: 2 cores
|
||||
- 200k pixels: 3 cores (above 186k pixels, 3 cores are used)
|
||||
- 300k pixels: 4 cores (above 279k pixels, 4 cores are used)
|
||||
- 375k pixels: 4 cores
|
||||
|
||||
In :cpp:enumerator:`LV_DISPLAY_RENDER_MODE_DIRECT`, the screen-sized draw buffer is divided by the tile count to determine the ideal tile sizes. If smaller areas are refreshed, it may result in fewer cores being used.
|
||||
|
||||
In :cpp:enumerator:`LV_DISPLAY_RENDER_MODE_FULL`, the maximum number of tiles is always created as the entire screen is refreshed.
|
||||
|
||||
In :cpp:enumerator:`LV_DISPLAY_RENDER_MODE_PARTIAL`, the partial buffer is divided into tiles. For example, if the draw buffer is 1/10th the size of the screen and there are 2 tiles, then 1/20th + 1/20th of the screen area will be rendered at once.
|
||||
|
||||
Tiled rendering only affects the rendering process, and the ``flush_cb`` is called once for each invalidated area. Therefore, tiling is not visible from the flushing point of view.
|
||||
|
||||
|
||||
User data
|
||||
---------
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ static void lv_refr_join_area(void);
|
||||
static void refr_invalid_areas(void);
|
||||
static void refr_sync_areas(void);
|
||||
static void refr_area(const lv_area_t * area_p);
|
||||
static void refr_area_part(lv_layer_t * layer);
|
||||
static void refr_configured_layer(lv_layer_t * layer);
|
||||
static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj);
|
||||
static void refr_obj_and_children(lv_layer_t * layer, lv_obj_t * top_obj);
|
||||
static void refr_obj(lv_layer_t * layer, lv_obj_t * obj);
|
||||
@@ -581,11 +581,50 @@ static void refr_invalid_areas(void)
|
||||
|
||||
for(i = 0; i < (int32_t)disp_refr->inv_p; i++) {
|
||||
/*Refresh the unjoined areas*/
|
||||
if(disp_refr->inv_area_joined[i] == 0) {
|
||||
if(disp_refr->inv_area_joined[i]) continue;
|
||||
|
||||
if(i == last_i) disp_refr->last_area = 1;
|
||||
disp_refr->last_part = 0;
|
||||
|
||||
lv_area_t inv_a = disp_refr->inv_areas[i];
|
||||
if(disp_refr->render_mode == LV_DISPLAY_RENDER_MODE_PARTIAL) {
|
||||
/*Calculate the max row num*/
|
||||
int32_t w = lv_area_get_width(&inv_a);
|
||||
int32_t h = lv_area_get_height(&inv_a);
|
||||
|
||||
int32_t max_row = get_max_row(disp_refr, w, h);
|
||||
|
||||
int32_t row;
|
||||
int32_t row_last = 0;
|
||||
lv_area_t sub_area;
|
||||
sub_area.x1 = inv_a.x1;
|
||||
sub_area.x2 = inv_a.x2;
|
||||
for(row = inv_a.y1; row + max_row - 1 <= inv_a.y2; row += max_row) {
|
||||
/*Calc. the next y coordinates of draw_buf*/
|
||||
sub_area.y1 = row;
|
||||
sub_area.y2 = row + max_row - 1;
|
||||
if(sub_area.y2 > inv_a.y2) sub_area.y2 = inv_a.y2;
|
||||
row_last = sub_area.y2;
|
||||
if(inv_a.y2 == row_last) disp_refr->last_part = 1;
|
||||
refr_area(&sub_area);
|
||||
draw_buf_flush(disp_refr);
|
||||
}
|
||||
|
||||
/*If the last y coordinates are not handled yet ...*/
|
||||
if(inv_a.y2 != row_last) {
|
||||
/*Calc. the next y coordinates of draw_buf*/
|
||||
sub_area.y1 = row;
|
||||
sub_area.y2 = inv_a.y2;
|
||||
disp_refr->last_part = 1;
|
||||
refr_area(&sub_area);
|
||||
draw_buf_flush(disp_refr);
|
||||
}
|
||||
}
|
||||
else if(disp_refr->render_mode == LV_DISPLAY_RENDER_MODE_FULL ||
|
||||
disp_refr->render_mode == LV_DISPLAY_RENDER_MODE_DIRECT) {
|
||||
disp_refr->last_part = 1;
|
||||
refr_area(&disp_refr->inv_areas[i]);
|
||||
draw_buf_flush(disp_refr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -618,91 +657,106 @@ static void refr_area(const lv_area_t * area_p)
|
||||
LV_PROFILER_REFR_BEGIN;
|
||||
lv_layer_t * layer = disp_refr->layer_head;
|
||||
layer->draw_buf = disp_refr->buf_act;
|
||||
layer->_clip_area = *area_p;
|
||||
layer->phy_clip_area = *area_p;
|
||||
|
||||
#if LV_DRAW_TRANSFORM_USE_MATRIX
|
||||
lv_matrix_identity(&layer->matrix);
|
||||
#endif
|
||||
if(disp_refr->render_mode == LV_DISPLAY_RENDER_MODE_FULL) {
|
||||
/*In full mode the area is always the full screen, so the buffer area to it too*/
|
||||
layer->buf_area = *area_p;
|
||||
layer_reshape_draw_buf(layer, layer->draw_buf->header.stride);
|
||||
|
||||
/*With full refresh just redraw directly into the buffer*/
|
||||
/*In direct mode draw directly on the absolute coordinates of the buffer*/
|
||||
if(disp_refr->render_mode != LV_DISPLAY_RENDER_MODE_PARTIAL) {
|
||||
}
|
||||
else if(disp_refr->render_mode == LV_DISPLAY_RENDER_MODE_PARTIAL) {
|
||||
/*In partial mode render this area to the buffer*/
|
||||
layer->buf_area = *area_p;
|
||||
layer_reshape_draw_buf(layer, LV_STRIDE_AUTO);
|
||||
}
|
||||
else if(disp_refr->render_mode == LV_DISPLAY_RENDER_MODE_DIRECT) {
|
||||
/*In direct mode the the buffer area is always the whole screen*/
|
||||
layer->buf_area.x1 = 0;
|
||||
layer->buf_area.y1 = 0;
|
||||
layer->buf_area.x2 = lv_display_get_horizontal_resolution(disp_refr) - 1;
|
||||
layer->buf_area.y2 = lv_display_get_vertical_resolution(disp_refr) - 1;
|
||||
lv_area_t disp_area;
|
||||
lv_area_set(&disp_area, 0, 0, lv_display_get_horizontal_resolution(disp_refr) - 1,
|
||||
lv_display_get_vertical_resolution(disp_refr) - 1);
|
||||
layer_reshape_draw_buf(layer, layer->draw_buf->header.stride);
|
||||
}
|
||||
|
||||
if(disp_refr->render_mode == LV_DISPLAY_RENDER_MODE_FULL) {
|
||||
disp_refr->last_part = 1;
|
||||
layer_reshape_draw_buf(layer, layer->draw_buf->header.stride);
|
||||
layer->_clip_area = disp_area;
|
||||
layer->phy_clip_area = disp_area;
|
||||
refr_area_part(layer);
|
||||
}
|
||||
else if(disp_refr->render_mode == LV_DISPLAY_RENDER_MODE_DIRECT) {
|
||||
disp_refr->last_part = disp_refr->last_area;
|
||||
layer_reshape_draw_buf(layer, layer->draw_buf->header.stride);
|
||||
layer->_clip_area = *area_p;
|
||||
layer->phy_clip_area = *area_p;
|
||||
refr_area_part(layer);
|
||||
/*Try to divide the area to smaller tiles*/
|
||||
uint32_t tile_cnt = 1;
|
||||
int32_t tile_h = lv_area_get_height(area_p);
|
||||
if(LV_COLOR_FORMAT_IS_INDEXED(layer->color_format) == false) {
|
||||
/* Assume that the the buffer size (can be screen sized or smaller in case of partial mode)
|
||||
* and max tile size are the optimal scenario. From this calculate the ideal tile size
|
||||
* and set the tile count and tile height accordingly.
|
||||
*/
|
||||
uint32_t max_tile_cnt = disp_refr->tile_cnt;
|
||||
uint32_t total_buf_size = layer->draw_buf->data_size;
|
||||
uint32_t ideal_tile_size = total_buf_size / max_tile_cnt;
|
||||
uint32_t area_buf_size = lv_area_get_size(area_p) * lv_color_format_get_size(layer->color_format);
|
||||
|
||||
tile_cnt = (area_buf_size + (ideal_tile_size - 1)) / ideal_tile_size; /*Round up*/
|
||||
tile_h = lv_area_get_height(area_p) / tile_cnt;
|
||||
}
|
||||
|
||||
/* Don't draw to the layers buffer of the display but create smaller dummy layers which are using the
|
||||
* display's layer buffer. These will be the tiles. By using tiles it's more likely that there will
|
||||
* be independent areas for each draw unit. */
|
||||
lv_layer_t * tile_layers = lv_malloc(tile_cnt * sizeof(lv_layer_t));
|
||||
LV_ASSERT_MALLOC(tile_layers);
|
||||
if(tile_layers == NULL) {
|
||||
disp_refr->refreshed_area = *area_p;
|
||||
LV_PROFILER_REFR_END;
|
||||
return;
|
||||
}
|
||||
uint32_t i;
|
||||
for(i = 0; i < tile_cnt; i++) {
|
||||
lv_area_t tile_area;
|
||||
lv_area_set(&tile_area, area_p->x1, area_p->y1 + i * tile_h,
|
||||
area_p->x2, area_p->y1 + (i + 1) * tile_h - 1);
|
||||
|
||||
/*Normal refresh: draw the area in parts*/
|
||||
/*Calculate the max row num*/
|
||||
int32_t w = lv_area_get_width(area_p);
|
||||
int32_t h = lv_area_get_height(area_p);
|
||||
int32_t y2 = area_p->y2 >= lv_display_get_vertical_resolution(disp_refr) ?
|
||||
lv_display_get_vertical_resolution(disp_refr) - 1 : area_p->y2;
|
||||
|
||||
int32_t max_row = get_max_row(disp_refr, w, h);
|
||||
|
||||
int32_t row;
|
||||
int32_t row_last = 0;
|
||||
lv_area_t sub_area;
|
||||
for(row = area_p->y1; row + max_row - 1 <= y2; row += max_row) {
|
||||
/*Calc. the next y coordinates of draw_buf*/
|
||||
sub_area.x1 = area_p->x1;
|
||||
sub_area.x2 = area_p->x2;
|
||||
sub_area.y1 = row;
|
||||
sub_area.y2 = row + max_row - 1;
|
||||
layer->draw_buf = disp_refr->buf_act;
|
||||
layer->buf_area = sub_area;
|
||||
layer->_clip_area = sub_area;
|
||||
layer->phy_clip_area = sub_area;
|
||||
layer_reshape_draw_buf(layer, LV_STRIDE_AUTO);
|
||||
if(sub_area.y2 > y2) sub_area.y2 = y2;
|
||||
row_last = sub_area.y2;
|
||||
if(y2 == row_last) disp_refr->last_part = 1;
|
||||
refr_area_part(layer);
|
||||
if(i == tile_cnt - 1) {
|
||||
tile_area.y2 = area_p->y2;
|
||||
}
|
||||
|
||||
/*If the last y coordinates are not handled yet ...*/
|
||||
if(y2 != row_last) {
|
||||
/*Calc. the next y coordinates of draw_buf*/
|
||||
sub_area.x1 = area_p->x1;
|
||||
sub_area.x2 = area_p->x2;
|
||||
sub_area.y1 = row;
|
||||
sub_area.y2 = y2;
|
||||
layer->draw_buf = disp_refr->buf_act;
|
||||
layer->buf_area = sub_area;
|
||||
layer->_clip_area = sub_area;
|
||||
layer->phy_clip_area = sub_area;
|
||||
layer_reshape_draw_buf(layer, LV_STRIDE_AUTO);
|
||||
disp_refr->last_part = 1;
|
||||
refr_area_part(layer);
|
||||
lv_layer_t * tile_layer = &tile_layers[i];
|
||||
lv_draw_layer_init(tile_layer, NULL, layer->color_format, &tile_area);
|
||||
tile_layer->buf_area = layer->buf_area; /*the buffer is still large*/
|
||||
tile_layer->draw_buf = layer->draw_buf;
|
||||
refr_configured_layer(tile_layer);
|
||||
}
|
||||
|
||||
|
||||
/*Wait until all tiles are ready and destroy remove them*/
|
||||
for(i = 0; i < tile_cnt; i++) {
|
||||
lv_layer_t * tile_layer = &tile_layers[i];
|
||||
while(tile_layer->draw_task_head) {
|
||||
lv_draw_dispatch_wait_for_request();
|
||||
lv_draw_dispatch();
|
||||
}
|
||||
|
||||
lv_layer_t * layer_i = disp_refr->layer_head;
|
||||
while(layer_i) {
|
||||
if(layer_i->next == tile_layer) {
|
||||
layer_i->next = tile_layer->next;
|
||||
break;
|
||||
}
|
||||
layer_i = layer_i->next;
|
||||
}
|
||||
|
||||
if(disp_refr->layer_deinit) disp_refr->layer_deinit(disp_refr, tile_layer);
|
||||
}
|
||||
lv_free(tile_layers);
|
||||
|
||||
disp_refr->refreshed_area = *area_p;
|
||||
LV_PROFILER_REFR_END;
|
||||
}
|
||||
|
||||
static void refr_area_part(lv_layer_t * layer)
|
||||
static void refr_configured_layer(lv_layer_t * layer)
|
||||
{
|
||||
LV_PROFILER_REFR_BEGIN;
|
||||
disp_refr->refreshed_area = layer->_clip_area;
|
||||
|
||||
#if LV_DRAW_TRANSFORM_USE_MATRIX
|
||||
lv_matrix_identity(&layer->matrix);
|
||||
#endif
|
||||
|
||||
/* In single buffered mode wait here until the buffer is freed.
|
||||
* Else we would draw into the buffer while it's still being transferred to the display*/
|
||||
@@ -711,13 +765,7 @@ static void refr_area_part(lv_layer_t * layer)
|
||||
}
|
||||
/*If the screen is transparent initialize it when the flushing is ready*/
|
||||
if(lv_color_format_has_alpha(disp_refr->color_format)) {
|
||||
lv_area_t a = disp_refr->refreshed_area;
|
||||
if(disp_refr->render_mode == LV_DISPLAY_RENDER_MODE_PARTIAL) {
|
||||
/*The area always starts at 0;0*/
|
||||
lv_area_move(&a, -disp_refr->refreshed_area.x1, -disp_refr->refreshed_area.y1);
|
||||
}
|
||||
|
||||
lv_draw_buf_clear(layer->draw_buf, &a);
|
||||
lv_draw_buf_clear(layer->draw_buf, &layer->_clip_area);
|
||||
}
|
||||
|
||||
lv_obj_t * top_act_scr = NULL;
|
||||
@@ -759,7 +807,6 @@ static void refr_area_part(lv_layer_t * layer)
|
||||
refr_obj_and_children(layer, lv_display_get_layer_top(disp_refr));
|
||||
refr_obj_and_children(layer, lv_display_get_layer_sys(disp_refr));
|
||||
|
||||
draw_buf_flush(disp_refr);
|
||||
LV_PROFILER_REFR_END;
|
||||
}
|
||||
|
||||
|
||||
@@ -77,6 +77,13 @@ lv_display_t * lv_display_create(int32_t hor_res, int32_t ver_res)
|
||||
disp->dpi = LV_DPI_DEF;
|
||||
disp->color_format = LV_COLOR_FORMAT_NATIVE;
|
||||
|
||||
|
||||
#if defined(LV_DRAW_SW_DRAW_UNIT_CNT)
|
||||
disp->tile_cnt = LV_DRAW_SW_DRAW_UNIT_CNT;
|
||||
#else
|
||||
disp->tile_cnt = 1;
|
||||
#endif
|
||||
|
||||
disp->layer_head = lv_malloc_zeroed(sizeof(lv_layer_t));
|
||||
LV_ASSERT_MALLOC(disp->layer_head);
|
||||
if(disp->layer_head == NULL) return NULL;
|
||||
@@ -488,6 +495,24 @@ lv_color_format_t lv_display_get_color_format(lv_display_t * disp)
|
||||
return disp->color_format;
|
||||
}
|
||||
|
||||
void lv_display_set_tile_cnt(lv_display_t * disp, uint32_t tile_cnt)
|
||||
{
|
||||
LV_ASSERT_FORMAT_MSG(tile_cnt < 256, "tile_cnt must be smaller than 256 (%d was used)", tile_cnt);
|
||||
|
||||
if(disp == NULL) disp = lv_display_get_default();
|
||||
if(disp == NULL) return;
|
||||
|
||||
disp->tile_cnt = tile_cnt;
|
||||
}
|
||||
|
||||
uint32_t lv_display_get_tile_cnt(lv_display_t * disp)
|
||||
{
|
||||
if(disp == NULL) disp = lv_display_get_default();
|
||||
if(disp == NULL) return 0;
|
||||
|
||||
return disp->tile_cnt;
|
||||
}
|
||||
|
||||
void lv_display_set_antialiasing(lv_display_t * disp, bool en)
|
||||
{
|
||||
if(disp == NULL) disp = lv_display_get_default();
|
||||
|
||||
@@ -293,6 +293,20 @@ void lv_display_set_color_format(lv_display_t * disp, lv_color_format_t color_fo
|
||||
*/
|
||||
lv_color_format_t lv_display_get_color_format(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Set the number of tiles for parallel rendering.
|
||||
* @param disp pointer to a display
|
||||
* @param tile_cnt number of tiles (1 =< tile_cnt < 256)
|
||||
*/
|
||||
void lv_display_set_tile_cnt(lv_display_t * disp, uint32_t tile_cnt);
|
||||
|
||||
/**
|
||||
* Get the number of tiles used for parallel rendering
|
||||
* @param disp pointer to a display
|
||||
* @return number of tiles
|
||||
*/
|
||||
uint32_t lv_display_get_tile_cnt(lv_display_t * disp);
|
||||
|
||||
/**
|
||||
* Enable anti-aliasing for the render engine
|
||||
* @param disp pointer to a display
|
||||
|
||||
@@ -91,6 +91,8 @@ struct _lv_display_t {
|
||||
|
||||
lv_display_render_mode_t render_mode;
|
||||
uint32_t antialiasing : 1; /**< 1: anti-aliasing is enabled on this display.*/
|
||||
uint32_t tile_cnt : 8; /**< Divide the display buffer into these number of tiles */
|
||||
|
||||
|
||||
/** 1: The current screen rendering is in progress*/
|
||||
uint32_t rendering_in_progress : 1;
|
||||
|
||||
@@ -398,7 +398,6 @@ uint32_t lv_draw_get_dependent_count(lv_draw_task_t * t_check)
|
||||
lv_layer_t * lv_draw_layer_create(lv_layer_t * parent_layer, lv_color_format_t color_format, const lv_area_t * area)
|
||||
{
|
||||
LV_PROFILER_DRAW_BEGIN;
|
||||
lv_display_t * disp = lv_refr_get_disp_refreshing();
|
||||
lv_layer_t * new_layer = lv_malloc_zeroed(sizeof(lv_layer_t));
|
||||
LV_ASSERT_MALLOC(new_layer);
|
||||
if(new_layer == NULL) {
|
||||
@@ -406,29 +405,45 @@ lv_layer_t * lv_draw_layer_create(lv_layer_t * parent_layer, lv_color_format_t c
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new_layer->parent = parent_layer;
|
||||
new_layer->_clip_area = *area;
|
||||
new_layer->buf_area = *area;
|
||||
new_layer->phy_clip_area = *area;
|
||||
new_layer->color_format = color_format;
|
||||
|
||||
#if LV_DRAW_TRANSFORM_USE_MATRIX
|
||||
lv_matrix_identity(&new_layer->matrix);
|
||||
#endif
|
||||
|
||||
if(disp->layer_head) {
|
||||
lv_layer_t * tail = disp->layer_head;
|
||||
while(tail->next) tail = tail->next;
|
||||
tail->next = new_layer;
|
||||
}
|
||||
else {
|
||||
disp->layer_head = new_layer;
|
||||
}
|
||||
lv_draw_layer_init(new_layer, parent_layer, color_format, area);
|
||||
|
||||
LV_PROFILER_DRAW_END;
|
||||
return new_layer;
|
||||
}
|
||||
|
||||
void lv_draw_layer_init(lv_layer_t * layer, lv_layer_t * parent_layer, lv_color_format_t color_format,
|
||||
const lv_area_t * area)
|
||||
{
|
||||
LV_PROFILER_DRAW_BEGIN;
|
||||
LV_ASSERT_NULL(layer);
|
||||
lv_memzero(layer, sizeof(lv_layer_t));
|
||||
lv_display_t * disp = lv_refr_get_disp_refreshing();
|
||||
|
||||
layer->parent = parent_layer;
|
||||
layer->_clip_area = *area;
|
||||
layer->buf_area = *area;
|
||||
layer->phy_clip_area = *area;
|
||||
layer->color_format = color_format;
|
||||
|
||||
#if LV_DRAW_TRANSFORM_USE_MATRIX
|
||||
lv_matrix_identity(&layer->matrix);
|
||||
#endif
|
||||
|
||||
if(disp->layer_init) disp->layer_init(disp, layer);
|
||||
|
||||
if(disp->layer_head) {
|
||||
lv_layer_t * tail = disp->layer_head;
|
||||
while(tail->next) tail = tail->next;
|
||||
tail->next = layer;
|
||||
}
|
||||
else {
|
||||
disp->layer_head = layer;
|
||||
}
|
||||
|
||||
LV_PROFILER_DRAW_END;
|
||||
}
|
||||
|
||||
|
||||
void * lv_draw_layer_alloc_buf(lv_layer_t * layer)
|
||||
{
|
||||
/*If the buffer of the layer is already allocated return it*/
|
||||
|
||||
@@ -212,7 +212,7 @@ lv_draw_task_t * lv_draw_get_next_available_task(lv_layer_t * layer, lv_draw_tas
|
||||
uint32_t lv_draw_get_dependent_count(lv_draw_task_t * t_check);
|
||||
|
||||
/**
|
||||
* Create a new layer on a parent layer
|
||||
* Create (allocate) a new layer on a parent layer
|
||||
* @param parent_layer the parent layer to which the layer will be merged when it's rendered
|
||||
* @param color_format the color format of the layer
|
||||
* @param area the areas of the layer (absolute coordinates)
|
||||
@@ -220,6 +220,17 @@ uint32_t lv_draw_get_dependent_count(lv_draw_task_t * t_check);
|
||||
*/
|
||||
lv_layer_t * lv_draw_layer_create(lv_layer_t * parent_layer, lv_color_format_t color_format, const lv_area_t * area);
|
||||
|
||||
/**
|
||||
* Initialize a layer which is allocated by the user
|
||||
* @param layer pointer the layer to initialize (its lifetime needs to be managed by the user)
|
||||
* @param parent_layer the parent layer to which the layer will be merged when it's rendered
|
||||
* @param color_format the color format of the layer
|
||||
* @param area the areas of the layer (absolute coordinates)
|
||||
* @return the new target_layer or NULL on error
|
||||
*/
|
||||
void lv_draw_layer_init(lv_layer_t * layer, lv_layer_t * parent_layer, lv_color_format_t color_format,
|
||||
const lv_area_t * area);
|
||||
|
||||
/**
|
||||
* Try to allocate a buffer for the layer.
|
||||
* @param layer pointer to a layer
|
||||
|
||||
@@ -553,14 +553,18 @@ static void execute_drawing(lv_draw_sw_unit_t * u)
|
||||
draw_unit_tmp = draw_unit_tmp->next;
|
||||
idx++;
|
||||
}
|
||||
lv_draw_rect_dsc_t rect_dsc;
|
||||
lv_draw_rect_dsc_init(&rect_dsc);
|
||||
rect_dsc.bg_color = lv_palette_main(idx % LV_PALETTE_LAST);
|
||||
rect_dsc.border_color = rect_dsc.bg_color;
|
||||
rect_dsc.bg_opa = LV_OPA_10;
|
||||
rect_dsc.border_opa = LV_OPA_80;
|
||||
rect_dsc.border_width = 1;
|
||||
lv_draw_sw_fill((lv_draw_unit_t *)u, &rect_dsc, &draw_area);
|
||||
lv_draw_fill_dsc_t fill_dsc;
|
||||
lv_draw_fill_dsc_init(&fill_dsc);
|
||||
fill_dsc.color = lv_palette_main(idx % LV_PALETTE_LAST);
|
||||
fill_dsc.opa = LV_OPA_10;
|
||||
lv_draw_sw_fill((lv_draw_unit_t *)u, &fill_dsc, &draw_area);
|
||||
|
||||
lv_draw_border_dsc_t border_dsc;
|
||||
lv_draw_border_dsc_init(&border_dsc);
|
||||
border_dsc.color = lv_palette_main(idx % LV_PALETTE_LAST);
|
||||
border_dsc.opa = LV_OPA_60;
|
||||
border_dsc.width = 1;
|
||||
lv_draw_sw_border((lv_draw_unit_t *)u, &border_dsc, &draw_area);
|
||||
|
||||
lv_point_t txt_size;
|
||||
lv_text_get_size(&txt_size, "W", LV_FONT_DEFAULT, 0, 0, 100, LV_TEXT_FLAG_NONE);
|
||||
@@ -571,9 +575,9 @@ static void execute_drawing(lv_draw_sw_unit_t * u)
|
||||
txt_area.x2 = draw_area.x1 + txt_size.x - 1;
|
||||
txt_area.y2 = draw_area.y1 + txt_size.y - 1;
|
||||
|
||||
lv_draw_rect_dsc_init(&rect_dsc);
|
||||
rect_dsc.bg_color = lv_color_white();
|
||||
lv_draw_sw_fill((lv_draw_unit_t *)u, &rect_dsc, &txt_area);
|
||||
lv_draw_fill_dsc_init(&fill_dsc);
|
||||
fill_dsc.color = lv_color_white();
|
||||
lv_draw_sw_fill((lv_draw_unit_t *)u, &fill_dsc, &txt_area);
|
||||
|
||||
char buf[8];
|
||||
lv_snprintf(buf, sizeof(buf), "%d", idx);
|
||||
|
||||
@@ -127,7 +127,7 @@ void lv_draw_sw_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dr
|
||||
}
|
||||
|
||||
lv_draw_fill_dsc_t fill_dsc;
|
||||
lv_draw_rect_dsc_init(&fill_dsc);
|
||||
lv_draw_fill_dsc_init(&fill_dsc);
|
||||
fill_dsc.color = lv_palette_main(idx % LV_PALETTE_LAST);
|
||||
fill_dsc.opa = LV_OPA_10;
|
||||
lv_draw_sw_fill(draw_unit, &fill_dsc, &area_rot);
|
||||
@@ -135,8 +135,8 @@ void lv_draw_sw_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dr
|
||||
lv_draw_border_dsc_t border_dsc;
|
||||
lv_draw_border_dsc_init(&border_dsc);
|
||||
border_dsc.color = lv_palette_main(idx % LV_PALETTE_LAST);
|
||||
border_dsc.opa = LV_OPA_100;
|
||||
border_dsc.width = 2;
|
||||
border_dsc.opa = LV_OPA_60;
|
||||
border_dsc.width = 1;
|
||||
lv_draw_sw_border(draw_unit, &border_dsc, &area_rot);
|
||||
|
||||
lv_point_t txt_size;
|
||||
|
||||
@@ -132,7 +132,6 @@ lv_display_t * lv_sdl_window_create(int32_t hor_res, int32_t ver_res)
|
||||
lv_display_set_render_mode(disp, LV_DISPLAY_RENDER_MODE_DIRECT);
|
||||
#endif /*LV_USE_DRAW_SDL == 0*/
|
||||
lv_display_add_event_cb(disp, res_chg_event_cb, LV_EVENT_RESOLUTION_CHANGED, NULL);
|
||||
|
||||
/*Process the initial events*/
|
||||
sdl_event_handler(NULL);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user