Questions about drawing and masking

Hello everyone, I am a student from Germany and currently working on a project with LVGL. A part of my work also includes explaining the mechanisms behind the library and I’m kind of stuck with the drawing and masking mechanics.

I already read the sections in the documentation regarding this topic and understood it that way:

-The base for every drawing is a filled rectangle. Color, Size etc. according to the draw descriptor.

-That rectangle is loaded into a draw buffer; now that buffer should look sth like this(for a purple rect):

(255,0,255) (255,0,255) (255,0,255) …
(255,0,255) (255,0,255) (255,0,255) …
(255,0,255) (255,0,255) …
… …

-Next on, we need to create masks (if we want to draw something more complex than an image or a rect) and load them into the mask buffer (which has the same size as the draw buffer ?) The mask buffer looks like this:

255 255 255…
255 255 255…
255 255 …
… …

Now if I interpreted correctly the mask types e.g. LV_DRAW_MASK_TYPE_LINE are basically algorithms that change the 255 to a 0 in the right spots.
In the documentation this line confuses me:

Apply all the created mask(s) for one or a few lines.

What do you mean by line ? I thought the mask buffer contains all masks for the whole rectangle, and not for one or a few lines.
Also the values in the mask buffer between 0 and 255, do they indicate the opacity ?

Alright, my style of explaining and asking questions at the same may be a little confusing and I’m sorry for that. I hope someone could give me some more hints on my questions and correct me on the statements I made. Thank you!!

Edit (new Questions):

Is it correct, that fonts are already saved masks?
How big is the draw buffer? Is it as big as the area on the screen, that needs to be changed or is it as big as the display?

@kisvegabor I think you will do a better job of answering most of these. :wink:

1 Like

Hi,

If you look at lv_draw_blend.c you find 2 top-level functions _lv_blend_fill and _lv_blend_map. They are quite similar. The only diffrence is that “map” draws an image but “fill” fills an area with a color.

If an area just needs to be filled with a color there is no “rectangle is loaded into a draw buffer” (as you said). LVGL just fills the display buffers (where the screen’s content is rendered) with the given color. If the opacity is not 100% instead of simply filling LVGL mixes the current color of the display buffer and the fill color according to blend mode and opacity level.

And here comes the trick: what there is a mask too? Lets we are drawing a 200x200 px red circle. LVGL needs to fill the 200x200 px area with red but needs to consider a mask. Allocating a 200x200 mask would be too much memory (40kB) therefore LVGL draws the circle in smaller chunks. Most of the drawing routines use a “horizontal resolution” max mask size. If the horizontal resolution is 800 px, 4 lines of the 200x200 px circle can fit into the mask. The rendring goes like this:

  1. Allocate a mask of 800 bytes
  2. Add a circle mask (other masks can be added by other routines earlier)
  3. Start from y = 0 of the circle
  4. Tell the “masking engine” to apply all the added mask on the y...y+4 lines
  5. Call _lv_belnd_fill with the calculated mask, the y..y+4 area, and the red color
  6. y+=4 and start from 4) while y < 200

The same goes for _lv_blend_map but instead of a fill color, an image is copied to the display buffer.

In reality, it’s more complicated because not only the circle’s maks is split into chunks, but usually, the whole display rendering also happens in chunks because on most of the systems the display buffer (where LVGL renders) is smaller than a whole screen.

Besides partial updates can happen too. E.g. redraw only the (20;40) (40;60) area of a 200x200 circle. In this case only a 20 px wide area is redrawn and the 800 px can cover max 40 lines. The mask calculations are instructed to calculate masks from x=20 to x=40.

Yes! Fonts are drawn with _lv_blend_fill considering the glyph’s “image” as a mask.

Another example: lines are also drawn by _lv_blend_fill using 4 lines mask on the top, bottom, left, and right side of the line.

Or ARGB images are drawn with _lv_blend_map where the map is the RGB part and the Alpha part is loaded into a mask.

As I’ve mentioned above, there is no draw buffer as you have described. (We usually the “draw buffer” or “display buffer” expression for the buffer where LVGL draws the final content of the screen and not a temporal buffer where the fill color is loaded)

I hope I could help. Let me know if you have further questions.

2 Likes

Hello, thanks a lot for your effort! That means that the max mask size is fixed (and probably dependent of the size of the framebuffer)? Anyway, your explanation solved all my questions perfectly and you helped me a lot, thank you for that.

Yes. More precisely on the horizontal resolution.

You’re welcome. :slight_smile:

1 Like