LVGL has a flexible and extendable draw pipeline. You can hook it to do some rendering with a GPU or even completely replace the built-in software renderer.
## Draw context
The core structure of drawing is `lv_draw_ctx_t`.
It contains a pointer to a buffer where drawing should happen and a couple of callbacks to draw rectangles, texts, and other primitives.
### Fields
`lv_draw_ctx_t` has the following fields:
-`void * buf` Pointer to a buffer to draw into
-`lv_area_t * buf_area` The the position and size of `buf` (absolute coordinates)
-`const lv_area_t * clip_area` The current clip area with absolute coordinates, always the same or smaller than `buf_area`. All drawings should be clipped to this area.
-`void (*draw_rect)()` Draw a rectangle with shadow, gradient, border, etc.
-`void (*draw_arc)()` Draw and arc
-`void (*draw_img_decoded)()` Draw an (A)RGB image that is already decoded by LVGL.
-`lv_res_t (*draw_img)()` Draw an image before decoding it (it bypasses LVGL's internal image decoders)
-`void (*draw_letter)()` Draw a letter
-`void (*draw_line)()` Draw a line
-`void (*draw_polygon)()` Draw polygon
-`void (*draw_bg)()` Replace the buffer with a rect without decoration like radius or borders.
-`void (*wait_for_finish)()` Wait until all background operation are finished. (E.g. GPU operations)
-`void * user_data` Custom user data for arbitrary purpose
(For the sake of simplicity the parameters of the callbacks are not shown here.)
All `draw_*` callbacks receive a pointer to the current `draw_ctx` as their first parameter. Among the other parameters there is a descriptor too that tells what to draw.
E.g. for `draw_rect` it's called [lv_draw_rect_dsc_t](https://github.com/lvgl/lvgl/blob/master/src/draw/lv_draw_rect.h),
To correctly render according to a `draw_dsc` you need to be familiar with the [Boxing model](https://docs.lvgl.io/master/overview/coords.html#boxing-model) of LVGL and the meanings of the fields. The name and meaning of the fields are identical to name and meaning of the [Style properties](https://docs.lvgl.io/master/overview/style-props.html).
As you saw above the software renderer adds the `blend` callback field. It's a special callback related to how the software renderer works.
All draw operations end up in the `blend` callback which can either fill anarea or copy an image to an area by considering an optional mask.
The `lv_draw_sw_blend_dsc_t` parameter describes what and how to blend. It has the following fields:
-`const lv_area_t * blend_area` The area with absolute coordinates to draw on `draw_ctx->buf`. If `src_buf` is set, it's the coordinates of the image to blend.
-`const lv_color_t * src_buf` Pointer to an image to blend. If set, `color` is ignored. If not set fill `blend_area` with `color`
-`lv_color_t color` Fill color. Used only if `src_buf == NULL`
-`lv_opa_t * mask_buf` NULL if ignored, or an alpha mask to apply on `blend_area`
-`lv_draw_mask_res_t mask_res` The result of the previous mask operation. (`LV_DRAW_MASK_RES_...`)
-`const lv_area_t * mask_area` The area of `mask_buf` with absolute coordinates