Repository: lvgl/lvgl (C)

Issue:
lvgl 9.1 canvas image not updated on the screen, unless canvas invalidated
### LVGL version

v9.1.0

### What happened?

I cannot update the lines on canvas "in live" unless the canvas or the main object are invalidated.
The lines are drawn on the buffer, but the buffer is not updated to the screen.

### How to reproduce?

I pretty much follow example of canvas, trying to draw lines on the canvas.
I create a canvas as part of my own lv_obj. 
Then I create a static draw buffer and set it.
To draw some lines I init a layer, draw the lines, and then finish the layer.

```
LV_DRAW_BUF_DEFINE(canvas_buf, 480, 480, LV_COLOR_FORMAT_ARGB8888);

my_obj->canvas = lv_canvas_create((lv_obj_t*)my_obj);
lv_canvas_set_draw_buf(my_obj->canvas, &canvas_buf);

lv_obj_align(my_obj->canvas, LV_ALIGN_CENTER, 0, 0);
lv_canvas_fill_bg(my_obj->canvas, lv_color_black(), LV_OPA_COVER);

lv_canvas_init_layer(my_obj->canvas, &layer);

// create and init line_dsc
for (uint32_t tick = 0; tick < 100; tick++) {
    lv_draw_line(&layer, &line_dsc);
}

lv_canvas_finish_layer(my_obj->canvas, &layer);
```

Unless I do not `lv_obj_invalidate(canvas)` the lines are not shown.
I can also see the lines after I change screen with `lv_screen_load(other_obj)` to another object and then get back `lv_screen_load(my_obj)`.


Discussion: Yup @oleg-amp, I am seeing it too. Thanks!

The other `lv_canvas_*` functions all call `lv_obj_invalidate` on the whole canvas, even `lv_canvas_set_px`. It looks like it was just forgotten in `lv_canvas_finish_layer` and missed because the tests never cover the case where the canvas isn't already invalid when `lv_canvas_finish_layer` is called. Edit: also possibly missed because many users would `fill_bg` before doing their canvas layers, which would invalidate the canvas.

@kisvegabor is this a worthy fix? Also, is this an opportunity to write a new kind of test?

```diff
diff --git a/src/widgets/canvas/lv_canvas.c b/src/widgets/canvas/lv_canvas.c
index 4ce2017af..9fb7c23b6 100644
--- a/src/widgets/canvas/lv_canvas.c
+++ b/src/widgets/canvas/lv_canvas.c
@@ -336,6 +336,7 @@ void lv_canvas_finish_layer(lv_obj_t * canvas, lv_layer_t * layer)
     while(layer->draw_task_head) {
         lv_draw_dispatch_wait_for_request();
         lv_draw_dispatch_layer(lv_obj_get_display(canvas), layer);
+        lv_obj_invalidate(canvas);
     }
 }
 
```
> is this a worthy fix? Also, is this an opportunity to write a new kind of test?

Absolutely! It's clearly a bug. However it's hard to test as the screenshot compare function [starts with a screen invalidation](https://github.com/lvgl/lvgl/blob/master/tests/unity/unity_support.c#L75). What you can do is:
1. Create a canvas
3. Call `lv_refr_now(NULL)` to refresh when needs to be refreshed. 
2. Add an event for `LV_EVENT_DRAW_MAIN` and increment a counter when it's called.
4. Update canvas
5. Call `lv_refr_now(NULL)` again
6. Check if the counter was incremented.

This way we can save several no so interesting reference images too.



Fix (patch):
diff --git a/src/widgets/canvas/lv_canvas.c b/src/widgets/canvas/lv_canvas.c
index 4ce2017afa7b..0391bd209b60 100644
--- a/src/widgets/canvas/lv_canvas.c
+++ b/src/widgets/canvas/lv_canvas.c
@@ -333,10 +333,12 @@ void lv_canvas_init_layer(lv_obj_t * obj, lv_layer_t * layer)
 
 void lv_canvas_finish_layer(lv_obj_t * canvas, lv_layer_t * layer)
 {
+    if(layer->draw_task_head == NULL) return;
     while(layer->draw_task_head) {
         lv_draw_dispatch_wait_for_request();
         lv_draw_dispatch_layer(lv_obj_get_display(canvas), layer);
     }
+    lv_obj_invalidate(canvas);
 }
 
 /**********************