From 0645af32a2e5ff7fc605450f7993212a6ffae292 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 11 Jan 2022 11:35:01 +0100 Subject: [PATCH] doc(gpu): add a page for external GPU support and draw_ctx related to: #2988 --- docs/porting/gpu.md | 205 ++++++++++++++++++++++ docs/porting/index.md | 1 + src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.c | 2 +- src/draw/sw/lv_draw_sw_blend.c | 6 +- src/draw/sw/lv_draw_sw_blend.h | 2 +- src/draw/sw/lv_draw_sw_img.c | 4 +- src/draw/sw/lv_draw_sw_letter.c | 4 +- src/draw/sw/lv_draw_sw_line.c | 6 +- src/draw/sw/lv_draw_sw_rect.c | 66 +++---- 9 files changed, 251 insertions(+), 45 deletions(-) create mode 100644 docs/porting/gpu.md diff --git a/docs/porting/gpu.md b/docs/porting/gpu.md new file mode 100644 index 000000000..b4a9dbd30 --- /dev/null +++ b/docs/porting/gpu.md @@ -0,0 +1,205 @@ +```eval_rst +.. include:: /header.rst +:github_url: |github_link_base|/porting/gpu.md +``` +# Add custom GPU + +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), +for `lv_draw_line` it's called [lv_draw_line_dsc_t](https://github.com/lvgl/lvgl/blob/master/src/draw/lv_draw_line.h). + + +### Initialization + +The `lv_disp_drv_t` has 4 fields related to the draw context: +- `lv_draw_ctx_t * draw_ctx` Pointer to the `draw_ctx` of this display +- `void (*draw_ctx_init)(struct _lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx)` Callback to initialize a `draw_ctx` +- `void (*draw_ctx_deinit)(struct _lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx)` Callback to de-initialize a `draw_ctx` +- `size_t draw_ctx_size` Size of the draw context structure. E.g. `sizeof(lv_draw_sw_ctx_t)` + +If you ignore these fields LVGL will set default values for callbacks and size in `lv_disp_drv_init()` based on the configuration in `lv_conf.h`. +`lv_disp_drv_register()` will allocate a `draw_ctx` based on `draw_ctx_size` and call `draw_ctx_init()` on it. + +However, you can overwrite the callbacks and the size values before calling `lv_disp_drv_register()`. +It makes possible to use your own `draw_ctx` with your own callbacks. + + +## Software renderer +LVGL's built in software renderer extends the basic `lv_draw_ctx_t` structure and sets the draw callbacks. It looks like this: +```c +typedef struct { +    /** Include the basic draw_ctx type*/ +    lv_draw_ctx_t base_draw; + +    /** Blend a color or image to an area*/ +    void (*blend)(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc); +} lv_draw_sw_ctx_t; +``` + +Set the draw callbacks in `draw_ctx_init()` like: +```c +draw_sw_ctx->base_draw.draw_rect = lv_draw_sw_rect; +draw_sw_ctx->base_draw.draw_letter = lv_draw_sw_letter; +... +``` + +### Blend callback +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 an area 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 +- `lv_opa_t opa`  The overall opacity +- `lv_blend_mode_t blend_mode`  E.g. `LV_BLEND_MODE_ADDITIVE` + + +## Extend the software renderer + +### New blend callback + +Let's take a practical example: you would like to use your MCUs GPU for color fill operations only. + +As all draw callbacks call `blend` callback to fill an area in the end only the `blend` callback needs to be overwritten. + +First extend `lv_draw_sw_ctx_t`: +```c + +/*We don't add new fields, so just for clarity add new type*/ +typedef lv_draw_sw_ctx_t my_draw_ctx_t; + +void my_draw_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) +{ +    /*Initialize the parent type first */ +    lv_draw_sw_init_ctx(drv, draw_ctx); + +    /*Change some callbacks*/ +    my_draw_ctx_t * my_draw_ctx = (my_draw_ctx_t *)draw_ctx; + +    my_draw_ctx->blend = my_draw_blend; +    my_draw_ctx->base_draw.wait_for_finish = my_gpu_wait; +} +``` + +After calling `lv_disp_draw_init(&drv)` you can assign the new `draw_ctx_init` callback and set `draw_ctx_size` to overwrite the defaults: +```c +static lv_disp_drv_t drv; +lv_disp_draw_init(&drv); +drv->hor_res = my_hor_res; +drv->ver_res = my_ver_res; +drv->flush_cb = my_flush_cb; + +/*New draw ctx settings*/ +drv->draw_ctx_init = my_draw_ctx_init; +drv->draw_ctx_size = sizeof(my_draw_ctx_t); + +lv_disp_drv_register(&drv); +``` + +This way when LVGL calls `blend` it will call `my_draw_blend` and we can do custom GPU operations. Here is a complete example: +```c +void my_draw_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc) +{ +    /*Let's get the blend area which is the intersection of the area to fill and the clip area.*/ +    lv_area_t blend_area; +    if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area)) return;  /*Fully clipped, nothing to do*/ + +    /*Fill only non masked, fully opaque, normal blended and not too small areas*/ +    if(dsc->src_buf == NULL && dsc->mask == NULL && dsc->opa >= LV_OPA_MAX && +       dsc->blend_mode == LV_BLEND_MODE_NORMAL && lv_area_get_size(&blend_area) > 100) { + +        /*Got the first pixel on the buffer*/ +        lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area); /*Width of the destination buffer*/ +        lv_color_t * dest_buf = draw_ctx->buf; +        dest_buf += dest_stride * (blend_area.y1 - draw_ctx->buf_area->y1) + (blend_area.x1 - draw_ctx->buf_area->x1); + +        /*Make the blend area relative to the buffer*/       +        lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); +        +        /*Call your custom gou fill function to fill blend_area, on dest_buf with dsc->color*/   +        my_gpu_fill(dest_buf, dest_stride, &blend_area, dsc->color); +    } +    /*Fallback: the GPU doesn't support these settings. Call the SW renderer.*/ +    else { +      lv_draw_sw_blend_basic(draw_ctx, dsc); +    } +} +``` + +The implementation of wait callback is much simpler: +```c +void my_gpu_wait(lv_draw_ctx_t * draw_ctx) +{ +    while(my_gpu_is_working()); +    +    /*Call SW renderer's wait callback too*/ +    lv_draw_sw_wait_for_finish(draw_ctx); +} +``` + +### New rectangle drawer +If your MCU has a more powerful GPU that can draw e.g. rounded rectangles you can replace the original software drawer too. +A custom `draw_rect` callback might look like this: +```c +void my_draw_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords) +{ +  if(lv_draw_mask_is_any(coords) == false && dsc->grad == NULL && dsc->bg_img_src == NULL && +     dsc->shadow_width == 0 && dsc->blend_mode = LV_BLEND_MODE_NORMAL) +  { +    /*Draw the background*/ +    my_bg_drawer(draw_ctx, coords, dsc->bg_color, dsc->radius); +    +    /*Draw the border if any*/ +    if(dsc->border_width) { +      my_border_drawer(draw_ctx, coords, dsc->border_width, dsc->border_color, dsc->border_opa) +    } +    +    /*Draw the outline if any*/ +    if(dsc->outline_width) { +      my_outline_drawer(draw_ctx, coords, dsc->outline_width, dsc->outline_color, dsc->outline_opa, dsc->outline_pad) +    } +  } +  /*Fallback*/ +  else { +    lv_draw_sw_rect(draw_ctx, dsc, coords); +  } +} +``` + +`my_draw_rect` can fully bypass the use of `blend` callback if needed. + +## Fully custom draw engine + +For example if your MCU/MPU supports a powerful vector graphics engine you might use only that instead of LVGL's SW renderer. +In this case, you need to base the renderer on the basic `lv_draw_ctx_t` (instead of `lv_draw_sw_ctx_t`) and extend/initialize it as you wish. + diff --git a/docs/porting/index.md b/docs/porting/index.md index 874430742..70f926ecf 100644 --- a/docs/porting/index.md +++ b/docs/porting/index.md @@ -18,6 +18,7 @@ sleep os log + gpu ``` diff --git a/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.c b/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.c index 0f4ea890e..20344a567 100644 --- a/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.c +++ b/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.c @@ -120,7 +120,7 @@ void lv_draw_stm32_dma2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_ bool done = false; - if(dsc->mask == NULL && dsc->blend_mode == LV_BLEND_MODE_NORMAL && lv_area_get_size(&blend_area) > 100) { + if(dsc->mask_buf == NULL && dsc->blend_mode == LV_BLEND_MODE_NORMAL && lv_area_get_size(&blend_area) > 100) { lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area); lv_color_t * dest_buf = draw_ctx->buf; diff --git a/src/draw/sw/lv_draw_sw_blend.c b/src/draw/sw/lv_draw_sw_blend.c index 5c56eb6a0..d8cbc0735 100644 --- a/src/draw/sw/lv_draw_sw_blend.c +++ b/src/draw/sw/lv_draw_sw_blend.c @@ -108,10 +108,10 @@ void lv_draw_sw_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * d LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_blend_basic(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc) { const lv_opa_t * mask; - if(dsc->mask == NULL) mask = NULL; - if(dsc->mask && dsc->mask_res == LV_DRAW_MASK_RES_TRANSP) return; + if(dsc->mask_buf == NULL) mask = NULL; + if(dsc->mask_buf && dsc->mask_res == LV_DRAW_MASK_RES_TRANSP) return; else if(dsc->mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask = NULL; - else mask = dsc->mask; + else mask = dsc->mask_buf; lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area); diff --git a/src/draw/sw/lv_draw_sw_blend.h b/src/draw/sw/lv_draw_sw_blend.h index 293b50bcd..a1fde7de3 100644 --- a/src/draw/sw/lv_draw_sw_blend.h +++ b/src/draw/sw/lv_draw_sw_blend.h @@ -31,7 +31,7 @@ typedef struct { * will be clipped to draw_`ctx->clip_area` */ const lv_color_t * src_buf; /**< Pointer to an image to blend. If set `fill_color is ignored`*/ lv_color_t color; /**< Fill color*/ - lv_opa_t * mask; /**< NULL if ignored, or an alpha mask to apply on `blend_area`*/ + 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 */ const lv_area_t * mask_area; /**< The area of `mask_buf` with absolute coordinates*/ lv_opa_t opa; /**< The overall opacity*/ diff --git a/src/draw/sw/lv_draw_sw_img.c b/src/draw/sw/lv_draw_sw_img.c index 40531a2d2..e7129db98 100644 --- a/src/draw/sw/lv_draw_sw_img.c +++ b/src/draw/sw/lv_draw_sw_img.c @@ -91,7 +91,7 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_img_decoded(struct _lv_draw_ctx_t * draw_c uint32_t mask_buf_size = lv_area_get_size(&draw_area) > (uint32_t) hor_res ? hor_res : lv_area_get_size(&draw_area); lv_color_t * src_buf_rgb = lv_mem_buf_get(mask_buf_size * sizeof(lv_color_t)); lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size); - blend_dsc.mask = mask_buf; + blend_dsc.mask_buf = mask_buf; blend_dsc.mask_area = &blend_area; blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; blend_dsc.src_buf = src_buf_rgb; @@ -150,7 +150,7 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_img_decoded(struct _lv_draw_ctx_t * draw_c uint32_t mask_buf_size = lv_area_get_size(&draw_area) > hor_res ? hor_res : lv_area_get_size(&draw_area); lv_color_t * src_buf_rgb = lv_mem_buf_get(mask_buf_size * sizeof(lv_color_t)); lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size); - blend_dsc.mask = mask_buf; + blend_dsc.mask_buf = mask_buf; blend_dsc.mask_area = &blend_area; blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; blend_dsc.src_buf = src_buf_rgb; diff --git a/src/draw/sw/lv_draw_sw_letter.c b/src/draw/sw/lv_draw_sw_letter.c index ac9279c77..a098187a9 100644 --- a/src/draw/sw/lv_draw_sw_letter.c +++ b/src/draw/sw/lv_draw_sw_letter.c @@ -226,7 +226,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_letter_normal(lv_draw_ctx_t * draw_ctx, c lv_coord_t hor_res = lv_disp_get_hor_res(_lv_refr_get_disp_refreshing()); uint32_t mask_buf_size = box_w * box_h > hor_res ? hor_res : box_w * box_h; lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size); - blend_dsc.mask = mask_buf; + blend_dsc.mask_buf = mask_buf; int32_t mask_p = 0; lv_area_t fill_area; @@ -412,7 +412,7 @@ static void draw_letter_subpx(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_ blend_dsc.blend_area = &map_area; blend_dsc.mask_area = &map_area; blend_dsc.src_buf = color_buf; - blend_dsc.mask = mask_buf; + blend_dsc.mask_buf = mask_buf; blend_dsc.opa = opa; blend_dsc.blend_mode = dsc->blend_mode; diff --git a/src/draw/sw/lv_draw_sw_line.c b/src/draw/sw/lv_draw_sw_line.c index c4fe5fe4d..73833c164 100644 --- a/src/draw/sw/lv_draw_sw_line.c +++ b/src/draw/sw/lv_draw_sw_line.c @@ -156,7 +156,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_line_hor(struct _lv_draw_ctx_t * draw_ctx } lv_opa_t * mask_buf = lv_mem_buf_get(blend_area_w); - blend_dsc.mask = mask_buf; + blend_dsc.mask_buf = mask_buf; blend_dsc.mask_area = &blend_area; int32_t h; for(h = blend_area.y1; h <= y2; h++) { @@ -237,7 +237,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_line_ver(struct _lv_draw_ctx_t * draw_ctx blend_area.y2 = blend_area.y1; lv_opa_t * mask_buf = lv_mem_buf_get(draw_area_w); - blend_dsc.mask = mask_buf; + blend_dsc.mask_buf = mask_buf; blend_dsc.mask_area = &blend_area; lv_coord_t dash_start = 0; @@ -390,7 +390,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_line_skew(struct _lv_draw_ctx_t * draw_ct blend_dsc.blend_area = &blend_area; blend_dsc.color = dsc->color; blend_dsc.opa = dsc->opa; - blend_dsc.mask = mask_buf; + blend_dsc.mask_buf = mask_buf; blend_dsc.mask_area = &blend_area; /*Fill the first row with 'color'*/ diff --git a/src/draw/sw/lv_draw_sw_rect.c b/src/draw/sw/lv_draw_sw_rect.c index 64d871d7f..66b7ed773 100644 --- a/src/draw/sw/lv_draw_sw_rect.c +++ b/src/draw/sw/lv_draw_sw_rect.c @@ -156,7 +156,7 @@ static void draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, co lv_memset_00(&blend_dsc, sizeof(lv_draw_sw_blend_dsc_t)); blend_dsc.blend_mode = dsc->blend_mode; blend_dsc.color = dsc->bg_color; - blend_dsc.mask = mask_buf; + blend_dsc.mask_buf = mask_buf; blend_dsc.opa = LV_OPA_COVER; blend_dsc.blend_area = &blend_area; blend_dsc.mask_area = &blend_area; @@ -238,7 +238,7 @@ static void draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, co blend_area.y1 = bg_coords.y1 + rout; blend_area.y2 = bg_coords.y2 - rout; blend_dsc.opa = opa; - blend_dsc.mask = NULL; + blend_dsc.mask_buf = NULL; lv_draw_sw_blend(draw_ctx, &blend_dsc); } /*With gradient and/or mask draw line by line*/ @@ -484,7 +484,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_shadow(lv_draw_ctx_t * draw_ctx, const lv lv_memset_00(&blend_dsc, sizeof(blend_dsc)); blend_dsc.blend_area = &blend_area; blend_dsc.mask_area = &blend_area; - blend_dsc.mask = mask_buf; + blend_dsc.mask_buf = mask_buf; blend_dsc.color = dsc->shadow_color; blend_dsc.opa = dsc->shadow_opa; blend_dsc.blend_mode = dsc->blend_mode; @@ -514,7 +514,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_shadow(lv_draw_ctx_t * draw_ctx, const lv if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; else simple_sub = simple; if(w > 0) { - blend_dsc.mask = mask_buf; + blend_dsc.mask_buf = mask_buf; blend_area.x1 = clip_area_sub.x1; blend_area.x2 = clip_area_sub.x2; blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; /*In simple mode it won't be overwritten*/ @@ -528,7 +528,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_shadow(lv_draw_ctx_t * draw_ctx, const lv if(blend_dsc.mask_res == LV_DRAW_MASK_RES_FULL_COVER) blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; } else { - blend_dsc.mask = sh_buf_tmp; + blend_dsc.mask_buf = sh_buf_tmp; } lv_draw_sw_blend(draw_ctx, &blend_dsc); sh_buf_tmp += corner_size; @@ -557,7 +557,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_shadow(lv_draw_ctx_t * draw_ctx, const lv else simple_sub = simple; if(w > 0) { - blend_dsc.mask = mask_buf; + blend_dsc.mask_buf = mask_buf; blend_area.x1 = clip_area_sub.x1; blend_area.x2 = clip_area_sub.x2; blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; /*In simple mode it won't be overwritten*/ @@ -571,7 +571,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_shadow(lv_draw_ctx_t * draw_ctx, const lv if(blend_dsc.mask_res == LV_DRAW_MASK_RES_FULL_COVER) blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; } else { - blend_dsc.mask = sh_buf_tmp; + blend_dsc.mask_buf = sh_buf_tmp; } lv_draw_sw_blend(draw_ctx, &blend_dsc); sh_buf_tmp += corner_size; @@ -598,10 +598,10 @@ LV_ATTRIBUTE_FAST_MEM static void draw_shadow(lv_draw_ctx_t * draw_ctx, const lv if(w > 0) { if(!simple_sub) { - blend_dsc.mask = mask_buf; + blend_dsc.mask_buf = mask_buf; } else { - blend_dsc.mask = NULL; + blend_dsc.mask_buf = NULL; } blend_area.x1 = clip_area_sub.x1; blend_area.x2 = clip_area_sub.x2; @@ -645,10 +645,10 @@ LV_ATTRIBUTE_FAST_MEM static void draw_shadow(lv_draw_ctx_t * draw_ctx, const lv else simple_sub = simple; if(!simple_sub) { - blend_dsc.mask = mask_buf; + blend_dsc.mask_buf = mask_buf; } else { - blend_dsc.mask = NULL; + blend_dsc.mask_buf = NULL; } blend_area.x1 = clip_area_sub.x1; blend_area.x2 = clip_area_sub.x2; @@ -699,7 +699,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_shadow(lv_draw_ctx_t * draw_ctx, const lv /*Do not mask if out of the bg*/ if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; else simple_sub = simple; - blend_dsc.mask = simple_sub ? sh_buf_tmp : mask_buf; + blend_dsc.mask_buf = simple_sub ? sh_buf_tmp : mask_buf; if(w > 0) { blend_area.x1 = clip_area_sub.x1; @@ -756,7 +756,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_shadow(lv_draw_ctx_t * draw_ctx, const lv /*Do not mask if out of the bg*/ if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; else simple_sub = simple; - blend_dsc.mask = simple_sub ? sh_buf_tmp : mask_buf; + blend_dsc.mask_buf = simple_sub ? sh_buf_tmp : mask_buf; if(w > 0) { blend_area.x1 = clip_area_sub.x1; blend_area.x2 = clip_area_sub.x2; @@ -795,7 +795,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_shadow(lv_draw_ctx_t * draw_ctx, const lv /*Do not mask if out of the bg*/ if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; else simple_sub = simple; - blend_dsc.mask = mask_buf; + blend_dsc.mask_buf = mask_buf; if(w > 0) { blend_area.x1 = clip_area_sub.x1; @@ -811,7 +811,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_shadow(lv_draw_ctx_t * draw_ctx, const lv if(blend_dsc.mask_res == LV_DRAW_MASK_RES_FULL_COVER) blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; } else { - blend_dsc.mask = sh_buf_tmp; + blend_dsc.mask_buf = sh_buf_tmp; } lv_draw_sw_blend(draw_ctx, &blend_dsc); @@ -840,7 +840,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_shadow(lv_draw_ctx_t * draw_ctx, const lv /*Do not mask if out of the bg*/ if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; else simple_sub = simple; - blend_dsc.mask = mask_buf; + blend_dsc.mask_buf = mask_buf; if(w > 0) { blend_area.x1 = clip_area_sub.x1; blend_area.x2 = clip_area_sub.x2; @@ -855,7 +855,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_shadow(lv_draw_ctx_t * draw_ctx, const lv if(blend_dsc.mask_res == LV_DRAW_MASK_RES_FULL_COVER) blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; } else { - blend_dsc.mask = sh_buf_tmp; + blend_dsc.mask_buf = sh_buf_tmp; } lv_draw_sw_blend(draw_ctx, &blend_dsc); sh_buf_tmp += corner_size; @@ -868,7 +868,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_shadow(lv_draw_ctx_t * draw_ctx, const lv blend_area.x2 = shadow_area.x2 - corner_size; blend_area.y1 = shadow_area.y1 + corner_size; blend_area.y2 = shadow_area.y2 - corner_size; - blend_dsc.mask = mask_buf; + blend_dsc.mask_buf = mask_buf; if(_lv_area_intersect(&clip_area_sub, &blend_area, draw_ctx->clip_area) && !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { @@ -1126,7 +1126,7 @@ void draw_border_generic(lv_draw_ctx_t * draw_ctx, const lv_area_t * outer_area, lv_draw_sw_blend_dsc_t blend_dsc; lv_memset_00(&blend_dsc, sizeof(blend_dsc)); - blend_dsc.mask = lv_mem_buf_get(draw_area_w);; + blend_dsc.mask_buf = lv_mem_buf_get(draw_area_w);; /*Create mask for the outer area*/ @@ -1172,8 +1172,8 @@ void draw_border_generic(lv_draw_ctx_t * draw_ctx, const lv_area_t * outer_area, blend_area.y1 = h; blend_area.y2 = h; - lv_memset_ff(blend_dsc.mask, draw_area_w); - blend_dsc.mask_res = lv_draw_mask_apply(blend_dsc.mask, draw_area.x1, h, draw_area_w); + lv_memset_ff(blend_dsc.mask_buf, draw_area_w); + blend_dsc.mask_res = lv_draw_mask_apply(blend_dsc.mask_buf, draw_area.x1, h, draw_area_w); lv_draw_sw_blend(draw_ctx, &blend_dsc); } @@ -1183,7 +1183,7 @@ void draw_border_generic(lv_draw_ctx_t * draw_ctx, const lv_area_t * outer_area, lv_draw_mask_free_param(&mask_rout_param); lv_draw_mask_remove_id(mask_rout_id); } - lv_mem_buf_release(blend_dsc.mask); + lv_mem_buf_release(blend_dsc.mask_buf); return; } @@ -1245,8 +1245,8 @@ void draw_border_generic(lv_draw_ctx_t * draw_ctx, const lv_area_t * outer_area, lv_coord_t bottom_y = outer_area->y2 - h; if(top_y < draw_area.y1 && bottom_y > draw_area.y2) continue; /*This line is clipped now*/ - lv_memset_ff(blend_dsc.mask, draw_area_w); - blend_dsc.mask_res = lv_draw_mask_apply(blend_dsc.mask, blend_area.x1, top_y, draw_area_w); + lv_memset_ff(blend_dsc.mask_buf, draw_area_w); + blend_dsc.mask_res = lv_draw_mask_apply(blend_dsc.mask_buf, blend_area.x1, top_y, draw_area_w); if(top_y >= draw_area.y1) { blend_area.y1 = top_y; @@ -1272,8 +1272,8 @@ void draw_border_generic(lv_draw_ctx_t * draw_ctx, const lv_area_t * outer_area, blend_area.y1 = h; blend_area.y2 = h; - lv_memset_ff(blend_dsc.mask, blend_w); - blend_dsc.mask_res = lv_draw_mask_apply(blend_dsc.mask, blend_area.x1, h, blend_w); + lv_memset_ff(blend_dsc.mask_buf, blend_w); + blend_dsc.mask_res = lv_draw_mask_apply(blend_dsc.mask_buf, blend_area.x1, h, blend_w); lv_draw_sw_blend(draw_ctx, &blend_dsc); } } @@ -1283,8 +1283,8 @@ void draw_border_generic(lv_draw_ctx_t * draw_ctx, const lv_area_t * outer_area, blend_area.y1 = h; blend_area.y2 = h; - lv_memset_ff(blend_dsc.mask, blend_w); - blend_dsc.mask_res = lv_draw_mask_apply(blend_dsc.mask, blend_area.x1, h, blend_w); + lv_memset_ff(blend_dsc.mask_buf, blend_w); + blend_dsc.mask_res = lv_draw_mask_apply(blend_dsc.mask_buf, blend_area.x1, h, blend_w); lv_draw_sw_blend(draw_ctx, &blend_dsc); } } @@ -1301,8 +1301,8 @@ void draw_border_generic(lv_draw_ctx_t * draw_ctx, const lv_area_t * outer_area, blend_area.y1 = h; blend_area.y2 = h; - lv_memset_ff(blend_dsc.mask, blend_w); - blend_dsc.mask_res = lv_draw_mask_apply(blend_dsc.mask, blend_area.x1, h, blend_w); + lv_memset_ff(blend_dsc.mask_buf, blend_w); + blend_dsc.mask_res = lv_draw_mask_apply(blend_dsc.mask_buf, blend_area.x1, h, blend_w); lv_draw_sw_blend(draw_ctx, &blend_dsc); } } @@ -1312,8 +1312,8 @@ void draw_border_generic(lv_draw_ctx_t * draw_ctx, const lv_area_t * outer_area, blend_area.y1 = h; blend_area.y2 = h; - lv_memset_ff(blend_dsc.mask, blend_w); - blend_dsc.mask_res = lv_draw_mask_apply(blend_dsc.mask, blend_area.x1, h, blend_w); + lv_memset_ff(blend_dsc.mask_buf, blend_w); + blend_dsc.mask_res = lv_draw_mask_apply(blend_dsc.mask_buf, blend_area.x1, h, blend_w); lv_draw_sw_blend(draw_ctx, &blend_dsc); } } @@ -1324,7 +1324,7 @@ void draw_border_generic(lv_draw_ctx_t * draw_ctx, const lv_area_t * outer_area, lv_draw_mask_remove_id(mask_rin_id); lv_draw_mask_free_param(&mask_rout_param); lv_draw_mask_remove_id(mask_rout_id); - lv_mem_buf_release(blend_dsc.mask); + lv_mem_buf_release(blend_dsc.mask_buf); #else /*LV_DRAW_COMPLEX*/ LV_UNUSED(blend_mode);