diff --git a/src/core/lv_refr.c b/src/core/lv_refr.c index 805814511..ca78f4445 100644 --- a/src/core/lv_refr.c +++ b/src/core/lv_refr.c @@ -578,6 +578,21 @@ static void refr_invalid_areas(void) LV_PROFILER_END; } +/** + * Reshape the draw buffer if required + * @param layer pointer to a layer which will be drawn + */ +static void layer_reshape_draw_buf(lv_layer_t * layer) +{ + LV_ASSERT(lv_draw_buf_reshape( + layer->draw_buf, + layer->color_format, + lv_area_get_width(&layer->buf_area), + lv_area_get_height(&layer->buf_area), + 0) + != NULL); +} + /** * Refresh an area if there is Virtual Display Buffer * @param area_p pointer to an area to refresh @@ -586,7 +601,7 @@ static void refr_area(const lv_area_t * area_p) { LV_PROFILER_BEGIN; lv_layer_t * layer = disp_refr->layer_head; - layer->buf = disp_refr->buf_act->data; + layer->draw_buf = disp_refr->buf_act; /*With full refresh just redraw directly into the buffer*/ /*In direct mode draw directly on the absolute coordinates of the buffer*/ @@ -595,7 +610,7 @@ static void refr_area(const lv_area_t * area_p) 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; - layer->buf_stride = lv_draw_buf_width_to_stride(lv_area_get_width(&layer->buf_area), layer->color_format); + layer_reshape_draw_buf(layer); 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); @@ -632,10 +647,10 @@ static void refr_area(const lv_area_t * area_p) sub_area.x2 = area_p->x2; sub_area.y1 = row; sub_area.y2 = row + max_row - 1; - layer->buf = disp_refr->buf_act->data; + layer->draw_buf = disp_refr->buf_act; layer->buf_area = sub_area; - layer->buf_stride = lv_draw_buf_width_to_stride(lv_area_get_width(&layer->buf_area), layer->color_format); layer->_clip_area = sub_area; + layer_reshape_draw_buf(layer); if(sub_area.y2 > y2) sub_area.y2 = y2; row_last = sub_area.y2; if(y2 == row_last) disp_refr->last_part = 1; @@ -649,9 +664,10 @@ static void refr_area(const lv_area_t * area_p) sub_area.x2 = area_p->x2; sub_area.y1 = row; sub_area.y2 = y2; - layer->buf = disp_refr->buf_act->data; + layer->draw_buf = disp_refr->buf_act; layer->buf_area = sub_area; layer->_clip_area = sub_area; + layer_reshape_draw_buf(layer); disp_refr->last_part = 1; refr_area_part(layer); } @@ -672,7 +688,7 @@ static void refr_area_part(lv_layer_t * layer) if(lv_color_format_has_alpha(disp_refr->color_format)) { uint32_t w = lv_area_get_width(&layer->buf_area); uint32_t h = lv_area_get_height(&layer->buf_area); - lv_draw_buf_clear(layer->buf, w, h, layer->color_format, &disp_refr->refreshed_area); + lv_draw_buf_clear(layer->draw_buf->data, w, h, layer->draw_buf->header.cf, &disp_refr->refreshed_area); } lv_obj_t * top_act_scr = NULL; @@ -1010,7 +1026,7 @@ static void draw_buf_flush(lv_display_t * disp) bool flushing_last = disp->flushing_last; if(disp->flush_cb) { - call_flush_cb(disp, &disp->refreshed_area, layer->buf); + call_flush_cb(disp, &disp->refreshed_area, layer->draw_buf->data); } /*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)) { diff --git a/src/display/lv_display.c b/src/display/lv_display.c index 0f7478569..8a8053411 100644 --- a/src/display/lv_display.c +++ b/src/display/lv_display.c @@ -81,7 +81,6 @@ lv_display_t * lv_display_create(int32_t hor_res, int32_t ver_res) disp->layer_head->buf_area.y1 = 0; disp->layer_head->buf_area.x2 = hor_res - 1; disp->layer_head->buf_area.y2 = ver_res - 1; - disp->layer_head->buf_stride = lv_draw_buf_width_to_stride(hor_res, LV_COLOR_FORMAT_NATIVE); disp->layer_head->color_format = disp->color_format; disp->inv_en_cnt = 1; diff --git a/src/draw/lv_draw.c b/src/draw/lv_draw.c index cb2ff3e11..e5e6573c5 100644 --- a/src/draw/lv_draw.c +++ b/src/draw/lv_draw.c @@ -187,14 +187,15 @@ bool lv_draw_dispatch_layer(lv_display_t * disp, lv_layer_t * layer) lv_draw_image_dsc_t * draw_image_dsc = t->draw_dsc; lv_layer_t * layer_drawn = (lv_layer_t *)draw_image_dsc->src; - if(layer_drawn->buf) { + if(layer_drawn->draw_buf) { int32_t h = lv_area_get_height(&layer_drawn->buf_area); int32_t w = lv_area_get_width(&layer_drawn->buf_area); uint32_t layer_size_byte = h * lv_draw_buf_width_to_stride(w, layer_drawn->color_format); _draw_info.used_memory_for_layers_kb -= get_layer_size_kb(layer_size_byte); LV_LOG_INFO("Layer memory used: %" LV_PRIu32 " kB\n", _draw_info.used_memory_for_layers_kb); - lv_draw_buf_free(layer_drawn->buf_unaligned); + lv_draw_buf_destroy(layer_drawn->draw_buf); + layer_drawn->draw_buf = NULL; } /*Remove the layer from the display's*/ @@ -345,7 +346,6 @@ lv_layer_t * lv_draw_layer_create(lv_layer_t * parent_layer, lv_color_format_t c new_layer->parent = parent_layer; new_layer->_clip_area = *area; new_layer->buf_area = *area; - new_layer->buf_stride = lv_draw_buf_width_to_stride(lv_area_get_width(area), color_format); new_layer->color_format = color_format; if(disp->layer_head) { @@ -362,51 +362,37 @@ lv_layer_t * lv_draw_layer_create(lv_layer_t * parent_layer, lv_color_format_t c void * lv_draw_layer_alloc_buf(lv_layer_t * layer) { - int32_t w = lv_area_get_width(&layer->buf_area); - uint32_t stride = lv_draw_buf_width_to_stride(w, layer->color_format); - - /*If the buffer of the layer is not allocated yet, allocate it now*/ - if(layer->buf == NULL) { - int32_t h = lv_area_get_height(&layer->buf_area); - uint32_t layer_size_byte = h * stride; - layer->buf_unaligned = lv_draw_buf_malloc(layer_size_byte, layer->color_format); - - if(layer->buf_unaligned == NULL) { - LV_LOG_WARN("Allocating %"LV_PRIu32" bytes of layer buffer failed. Try later", layer_size_byte); - return NULL; - } - - layer->buf = lv_draw_buf_align(layer->buf_unaligned, layer->color_format); - - _draw_info.used_memory_for_layers_kb += get_layer_size_kb(layer_size_byte); - LV_LOG_INFO("Layer memory used: %" LV_PRIu32 " kB\n", _draw_info.used_memory_for_layers_kb); - - if(lv_color_format_has_alpha(layer->color_format)) { - lv_area_t a; - a.x1 = 0; - a.y1 = 0; - a.x2 = w - 1; - a.y2 = h - 1; - lv_draw_buf_clear(layer->buf, w, h, layer->color_format, &a); - } + /*If the buffer of the layer is already allocated return it*/ + if(layer->draw_buf != NULL) { + return layer->draw_buf->data; } - /*Set the stride also for static allocated buffers as well as for new dynamically allocated*/ - if(layer->buf_stride == 0) layer->buf_stride = stride; + /*If the buffer of the layer is not allocated yet, allocate it now*/ + int32_t w = lv_area_get_width(&layer->buf_area); + int32_t h = lv_area_get_height(&layer->buf_area); - /*Make sure the buffer address is aligned in case of already allocated buffers*/ - return lv_draw_buf_align(layer->buf, layer->color_format); + layer->draw_buf = lv_draw_buf_create(w, h, layer->color_format, 0); + + if(layer->draw_buf == NULL) { + LV_LOG_WARN("Allocating layer buffer failed. Try later"); + return NULL; + } + + if(lv_color_format_has_alpha(layer->color_format)) { + lv_area_t a; + a.x1 = 0; + a.y1 = 0; + a.x2 = w - 1; + a.y2 = h - 1; + lv_draw_buf_clear(layer->draw_buf->data, w, h, layer->color_format, &a); + } + + return layer->draw_buf->data; } void * lv_draw_layer_go_to_xy(lv_layer_t * layer, int32_t x, int32_t y) { - lv_draw_buf_t tmp; - tmp.data = layer->buf; - tmp.header.stride = layer->buf_stride; - tmp.header.cf = layer->color_format; - tmp.header.w = lv_area_get_width(&layer->buf_area); - tmp.header.h = lv_area_get_height(&layer->buf_area); - return lv_draw_buf_goto_xy(&tmp, x, y); + return lv_draw_buf_goto_xy(layer->draw_buf, x, y); } /********************** diff --git a/src/draw/lv_draw.h b/src/draw/lv_draw.h index 675cf0186..0672bc55d 100644 --- a/src/draw/lv_draw.h +++ b/src/draw/lv_draw.h @@ -146,13 +146,8 @@ struct _lv_draw_unit_t { struct _lv_layer_t { - /** The unaligned buffer where drawing will happen*/ - void * buf_unaligned; - - /** The aligned buffer, result of lv_draw_buf_align(layer->buf_unaligned)*/ - void * buf; - - uint32_t buf_stride; + /** Target draw buffer of the layer*/ + lv_draw_buf_t * draw_buf; /** The absolute coordinates of the buffer */ lv_area_t buf_area; diff --git a/src/draw/lv_draw_buf.c b/src/draw/lv_draw_buf.c index 8bcb4bf68..b0be35072 100644 --- a/src/draw/lv_draw_buf.c +++ b/src/draw/lv_draw_buf.c @@ -416,10 +416,5 @@ static uint32_t _calculate_draw_buf_size(uint32_t w, uint32_t h, lv_color_format size += LV_COLOR_INDEXED_PALETTE_SIZE(cf) * 4; } - /*RLE decompression operates on pixel unit, thus add padding to make sure memory is enough*/ - uint8_t bpp = lv_color_format_get_bpp(cf); - bpp = (bpp + 7) >> 3; - size += bpp; - return size; } diff --git a/src/draw/sw/lv_draw_sw_img.c b/src/draw/sw/lv_draw_sw_img.c index 06c8b46f0..0867d2623 100644 --- a/src/draw/sw/lv_draw_sw_img.c +++ b/src/draw/sw/lv_draw_sw_img.c @@ -73,22 +73,11 @@ void lv_draw_sw_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dr /*It can happen that nothing was draw on a layer and therefore its buffer is not allocated. *In this case just return. */ - if(layer_to_draw->buf == NULL) return; - - lv_image_dsc_t img_dsc = { 0 }; - img_dsc.header.w = lv_area_get_width(&layer_to_draw->buf_area); - img_dsc.header.h = lv_area_get_height(&layer_to_draw->buf_area); - img_dsc.header.cf = layer_to_draw->color_format; - img_dsc.header.stride = layer_to_draw->buf_stride; - img_dsc.data = layer_to_draw->buf; - - lv_draw_image_dsc_t new_draw_dsc; - lv_memcpy(&new_draw_dsc, draw_dsc, sizeof(lv_draw_image_dsc_t)); - new_draw_dsc.src = &img_dsc; + if(layer_to_draw->draw_buf == NULL) return; + lv_draw_image_dsc_t new_draw_dsc = *draw_dsc; + new_draw_dsc.src = layer_to_draw->draw_buf; lv_draw_sw_image(draw_unit, &new_draw_dsc, coords); - lv_image_cache_drop(&img_dsc); - #if LV_USE_LAYER_DEBUG || LV_USE_PARALLEL_DRAW_DEBUG lv_area_t area_rot; lv_area_copy(&area_rot, coords); diff --git a/src/draw/sw/lv_draw_sw_mask_rect.c b/src/draw/sw/lv_draw_sw_mask_rect.c index 960718608..acd629413 100644 --- a/src/draw/sw/lv_draw_sw_mask_rect.c +++ b/src/draw/sw/lv_draw_sw_mask_rect.c @@ -56,27 +56,29 @@ void lv_draw_sw_mask_rect(lv_draw_unit_t * draw_unit, const lv_draw_mask_rect_ds int32_t buf_h = lv_area_get_height(&target_layer->buf_area); lv_area_t clear_area; + void * buf = target_layer->draw_buf->data; + /*Clear the top part*/ lv_area_set(&clear_area, draw_unit->clip_area->x1, draw_unit->clip_area->y1, draw_unit->clip_area->x2, dsc->area.y1 - 1); lv_area_move(&clear_area, -target_layer->buf_area.x1, -target_layer->buf_area.y1); - lv_draw_buf_clear(target_layer->buf, buf_w, buf_h, target_layer->color_format, &clear_area); + lv_draw_buf_clear(buf, buf_w, buf_h, target_layer->color_format, &clear_area); /*Clear the bottom part*/ lv_area_set(&clear_area, draw_unit->clip_area->x1, dsc->area.y2 + 1, draw_unit->clip_area->x2, draw_unit->clip_area->y2); lv_area_move(&clear_area, -target_layer->buf_area.x1, -target_layer->buf_area.y1); - lv_draw_buf_clear(target_layer->buf, buf_w, buf_h, target_layer->color_format, &clear_area); + lv_draw_buf_clear(buf, buf_w, buf_h, target_layer->color_format, &clear_area); /*Clear the left part*/ lv_area_set(&clear_area, draw_unit->clip_area->x1, dsc->area.y1, dsc->area.x1 - 1, dsc->area.y2); lv_area_move(&clear_area, -target_layer->buf_area.x1, -target_layer->buf_area.y1); - lv_draw_buf_clear(target_layer->buf, buf_w, buf_h, target_layer->color_format, &clear_area); + lv_draw_buf_clear(buf, buf_w, buf_h, target_layer->color_format, &clear_area); /*Clear the right part*/ lv_area_set(&clear_area, dsc->area.x2 + 1, dsc->area.y1, draw_unit->clip_area->x2, dsc->area.y2); lv_area_move(&clear_area, -target_layer->buf_area.x1, -target_layer->buf_area.y1); - lv_draw_buf_clear(target_layer->buf, buf_w, buf_h, target_layer->color_format, &clear_area); + lv_draw_buf_clear(buf, buf_w, buf_h, target_layer->color_format, &clear_area); lv_draw_sw_mask_radius_param_t param; lv_draw_sw_mask_radius_init(¶m, &dsc->area, dsc->radius, false); diff --git a/src/draw/sw/lv_draw_sw_vector.c b/src/draw/sw/lv_draw_sw_vector.c index 2cd14a8db..a32530d1b 100644 --- a/src/draw/sw/lv_draw_sw_vector.c +++ b/src/draw/sw/lv_draw_sw_vector.c @@ -427,22 +427,24 @@ void lv_draw_sw_vector(lv_draw_unit_t * draw_unit, const lv_draw_vector_task_dsc return; lv_layer_t * layer = dsc->base.layer; - if(layer->buf == NULL) + lv_draw_buf_t * draw_buf = layer->draw_buf; + if(draw_buf == NULL) return; - if(layer->color_format != LV_COLOR_FORMAT_ARGB8888 && \ - layer->color_format != LV_COLOR_FORMAT_XRGB8888) { - LV_LOG_ERROR("unsupported layer color: %d", layer->color_format); + lv_color_format_t cf = draw_buf->header.cf; + + if(cf != LV_COLOR_FORMAT_ARGB8888 && \ + cf != LV_COLOR_FORMAT_XRGB8888) { + LV_LOG_ERROR("unsupported layer color: %d", cf); return; } - void * buf = layer->buf; + void * buf = draw_buf->data; int32_t width = lv_area_get_width(&layer->buf_area); int32_t height = lv_area_get_height(&layer->buf_area); - uint32_t stride = layer->buf_stride; - stride /= 4; + uint32_t stride = draw_buf->header.stride; Tvg_Canvas * canvas = tvg_swcanvas_create(); - tvg_swcanvas_set_target(canvas, buf, stride, width, height, TVG_COLORSPACE_ARGB8888); + tvg_swcanvas_set_target(canvas, buf, stride / 4, width, height, TVG_COLORSPACE_ARGB8888); lv_ll_t * task_list = dsc->task_list; _lv_vector_for_each_destroy_tasks(task_list, _task_draw_cb, canvas); diff --git a/src/draw/vg_lite/lv_draw_vg_lite.c b/src/draw/vg_lite/lv_draw_vg_lite.c index 0d1be3af2..256b8137a 100644 --- a/src/draw/vg_lite/lv_draw_vg_lite.c +++ b/src/draw/vg_lite/lv_draw_vg_lite.c @@ -89,15 +89,7 @@ static void draw_execute(lv_draw_vg_lite_unit_t * u) lv_layer_t * layer = u->base_unit.target_layer; - lv_draw_buf_t draw_buf = { 0 }; - uint32_t w, h, stride; - w = lv_area_get_width(&layer->buf_area); - h = lv_area_get_height(&layer->buf_area); - stride = lv_draw_buf_width_to_stride(w, layer->color_format); - - lv_image_header_init(&draw_buf.header, w, h, layer->color_format, stride, 0); - draw_buf.data = layer->buf; - lv_vg_lite_buffer_from_draw_buf(&u->target_buffer, &draw_buf); + lv_vg_lite_buffer_from_draw_buf(&u->target_buffer, layer->draw_buf); vg_lite_identity(&u->global_matrix); vg_lite_translate(-layer->buf_area.x1, -layer->buf_area.y1, &u->global_matrix); @@ -160,11 +152,6 @@ static int32_t draw_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer) return 0; } - /* Return if target buffer format is not supported. */ - if(!lv_vg_lite_is_dest_cf_supported(layer->color_format)) { - return -1; - } - /* Try to get an ready to draw. */ lv_draw_task_t * t = lv_draw_get_next_available_task(layer, NULL, VG_LITE_DRAW_UNIT_ID); @@ -178,6 +165,11 @@ static int32_t draw_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer) return -1; } + /* Return if target buffer format is not supported. */ + if(!lv_vg_lite_is_dest_cf_supported(layer->draw_buf->header.cf)) { + return -1; + } + t->state = LV_DRAW_TASK_STATE_IN_PROGRESS; draw_vg_lite_unit->base_unit.target_layer = layer; draw_vg_lite_unit->base_unit.clip_area = &t->clip_area; diff --git a/src/draw/vg_lite/lv_draw_vg_lite_layer.c b/src/draw/vg_lite/lv_draw_vg_lite_layer.c index 0d5836853..c3756fb9f 100644 --- a/src/draw/vg_lite/lv_draw_vg_lite_layer.c +++ b/src/draw/vg_lite/lv_draw_vg_lite_layer.c @@ -45,24 +45,18 @@ void lv_draw_vg_lite_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t /*It can happen that nothing was draw on a layer and therefore its buffer is not allocated. *In this case just return. */ - if(layer->buf == NULL) + if(layer->draw_buf == NULL) return; - lv_image_dsc_t img_dsc; - lv_memzero(&img_dsc, sizeof(lv_image_dsc_t)); - img_dsc.header.w = lv_area_get_width(&layer->buf_area); - img_dsc.header.h = lv_area_get_height(&layer->buf_area); - img_dsc.header.cf = layer->color_format; - img_dsc.data = layer->buf; - - /* The GPU output is premultiplied RGB */ - img_dsc.header.flags = LV_IMAGE_FLAGS_PREMULTIPLIED; + /* The GPU output should already be premultiplied RGB */ + if((layer->draw_buf->header.flags & LV_IMAGE_FLAGS_PREMULTIPLIED) == 0) { + LV_LOG_WARN("GPU output is not premultiplied RGB."); + layer->draw_buf->header.flags |= LV_IMAGE_FLAGS_PREMULTIPLIED; + } lv_draw_image_dsc_t new_draw_dsc = *draw_dsc; - new_draw_dsc.src = &img_dsc; - + new_draw_dsc.src = layer->draw_buf; lv_draw_vg_lite_img(draw_unit, &new_draw_dsc, coords); - lv_image_cache_drop(&img_dsc); } /********************** diff --git a/src/draw/vg_lite/lv_draw_vg_lite_vector.c b/src/draw/vg_lite/lv_draw_vg_lite_vector.c index c07b57051..19d34b812 100644 --- a/src/draw/vg_lite/lv_draw_vg_lite_vector.c +++ b/src/draw/vg_lite/lv_draw_vg_lite_vector.c @@ -52,7 +52,7 @@ void lv_draw_vg_lite_vector(lv_draw_unit_t * draw_unit, const lv_draw_vector_tas return; lv_layer_t * layer = dsc->base.layer; - if(layer->buf == NULL) + if(layer->draw_buf == NULL) return; _lv_vector_for_each_destroy_tasks(dsc->task_list, task_draw_cb, draw_unit); diff --git a/src/libs/bin_decoder/lv_bin_decoder.c b/src/libs/bin_decoder/lv_bin_decoder.c index 9703e4da7..f1c087a56 100644 --- a/src/libs/bin_decoder/lv_bin_decoder.c +++ b/src/libs/bin_decoder/lv_bin_decoder.c @@ -1039,6 +1039,13 @@ static lv_result_t decompress_image(lv_image_decoder_dsc_t * dsc, const lv_image uint32_t out_len = compressed->decompressed_size; uint32_t input_len = compressed->compressed_size; LV_UNUSED(input_len); + + /** + * @todo + * FIXME, RLE compressed image needs extra memory because decompression operates on + * pixel unit not byte unit. Should optimize RLE decompress to not write to extra memory. + */ + dsc->header.h += 1; lv_draw_buf_t * decompressed = lv_draw_buf_create(dsc->header.w, dsc->header.h, dsc->header.cf, dsc->header.stride); if(decompressed == NULL) { @@ -1046,6 +1053,7 @@ static lv_result_t decompress_image(lv_image_decoder_dsc_t * dsc, const lv_image return LV_RESULT_INVALID; } + dsc->header.h -= 1; /*Change it back*/ if(decompressed->data_size < out_len) { LV_LOG_WARN("decompressed size mismatch: %" LV_PRIu32 ", %" LV_PRIu32, decompressed->data_size, out_len); lv_draw_buf_destroy(decompressed); diff --git a/src/others/snapshot/lv_snapshot.c b/src/others/snapshot/lv_snapshot.c index 9aadd889a..0238448e8 100644 --- a/src/others/snapshot/lv_snapshot.c +++ b/src/others/snapshot/lv_snapshot.c @@ -111,7 +111,10 @@ lv_result_t lv_snapshot_take_to_buf(lv_obj_t * obj, lv_color_format_t cf, lv_ima lv_layer_t layer; lv_memzero(&layer, sizeof(layer)); - layer.buf = buf; + lv_draw_buf_t draw_buf; + lv_draw_buf_from_image(&draw_buf, dsc); + + layer.draw_buf = &draw_buf; layer.buf_area.x1 = snapshot_area.x1; layer.buf_area.y1 = snapshot_area.y1; layer.buf_area.x2 = snapshot_area.x1 + w - 1; diff --git a/src/widgets/canvas/lv_canvas.c b/src/widgets/canvas/lv_canvas.c index cdc335c62..5c0c14d33 100644 --- a/src/widgets/canvas/lv_canvas.c +++ b/src/widgets/canvas/lv_canvas.c @@ -346,11 +346,10 @@ void lv_canvas_init_layer(lv_obj_t * obj, lv_layer_t * layer) lv_area_t canvas_area = {0, 0, header->w - 1, header->h - 1}; lv_memzero(layer, sizeof(*layer)); - layer->buf = canvas->draw_buf->data; + layer->draw_buf = canvas->draw_buf; layer->color_format = header->cf; layer->buf_area = canvas_area; layer->_clip_area = canvas_area; - layer->buf_stride = header->stride; } void lv_canvas_finish_layer(lv_obj_t * canvas, lv_layer_t * layer)