LV_EVENT.DRAW_PART_END is used in several examples to draw custom graphics to the display. I wanted to use lv_canvas but it does not support an alpha channel so it isn’t going to work for what I am doing. The issue I am having using LV_EVENT.DRAW_PART_END is that what is custom drawn is not coupled to the object the event callback was registered to. What I mean by that is I have to use absolute screen coordinates to render they are not relative to the object. The other thing is when the screen is scrolled what has been rendered does not scroll. it stays in a fixed location.

If this the correct behavior? It doesn’t seem like it should be because of registering the callback to a specific object. Other GUI frameworks I have used and also the direct Windows API has defined “DC’s” for doing different thing. Like a client DC and paint DC for rendering to the window that an event was registered to or a screen DC which renders to the screen and is not married to a window. memory DC for rendering to a BMP or other file like buffer. That kind of thing. Is there only a “screen DC” (ctx) available in LVGL?.. Maybe I am missing where a context is that is specific to an object.

True, all drawing happens in an absolute coordinate system. However, you can use e.g. lv_area_move(area, x_ofs, y_ofs); to easily make the coordinates relative.

What is a “DC”?

in the world of the Windows operating system a DC is a “Device Context”.

They are responsible for handling what you are writing the graphics to. So a ScreenDC writes to the screen, as in anywhere on the screen and it’s not bound by anything. a ClientDC also writes to the screen bit it is bound to the location of the object that was passed when creating the ClientDC. a MemoryDC writes to memory for buffering purposes. so a MemoryDC would be kind of like what lv_canvas is and the ScreenDC is more along the lines of what LVGL uses for a context is there a context that is limited by the bounds of the object the event has been triggered for? something that would move with an object if the object was moved? The coordinates would be relative to that object and not to the screen.

much like what LVGL does with the event this topic is about to inform the user of when rendering needs to occur Windows also sends an event as well. and in the callback for that event a PaintDC can be created and it is much like the ClientDC. It doesn’t need to have an object passed to it upon creation as a PaintDC can only be created during a paint event so it automatically gets married to an object.

There are a lot of similarities between how LVGL runs and what Windows does.

Thanks, I understand now. In LVGL it works a little bit differently. In short the renderers see a clip_area which prevents drawing outside of the parent widget’s area.

In the new v9 drawing architecture it will be a little bit more sophisticated:

  • We have layers (i.e. independent buffers): there is one main layer for the display and LVGL can create new layers during rendering if needed too (e.g. if a widget with all its children needs to be rotated the widget will be drawn to a layer first and that layer will be rotated as an image)
  • If something needs to be drawn a draw_task will be created. It clearly separates the widgets from drawing. A draw_task tells nothing more but draw something on a given layer. Once we have the draw_tasks buffered we can “easily” (quite complex actually) manage rendering them in parallel.
  • Each draw_task know its clip_area

So as draw_tasks are separated from widgets we need to use absolute coordinates.

Here you can find the related GitHub discussions here.

Yesterday, I’ve just updated Lv_EVENT_DRAW_PART in the feat/parallel.rendering branch. It’s not full featured yet, but it’s much simpler than what we had so far. There is a single LV_EVENT_DRAW_TASK_ADDED event which is called when a draw task is added so that you can modify it or add other draw_tasks too. Fortunately, lv_obj_draw_part_dsc_t is removed too. It was very complicated to use. Here is an example for it with the calendar widget.