mirror of
https://github.com/lvgl/lvgl.git
synced 2024-11-23 09:43:41 +08:00
fix(sdl): add transformation support for the SDL backend (#3403)
* sdl transform wip * sdl transform wip * working transform (scale, rotate) * fixed transform with masks * fixing includes * removed lv_obj_t references in draw backend * update the API to work with SW layers too * update lv_conf_internal.h * makefile fixes * updated sdl transform implementation Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com>
This commit is contained in:
parent
ca9aff6119
commit
f575935180
@ -125,8 +125,6 @@
|
||||
* and blend it as an image with the given opacity.
|
||||
* Note that `bg_opa`, `text_opa` etc don't require buffering into layer)
|
||||
* The widget can be buffered in smaller chunks to avoid using large buffers.
|
||||
* `draw_area` (`lv_area_t` meaning the area to draw and `px_size` (size of a pixel in bytes)
|
||||
* can be used the set the buffer size adaptively.
|
||||
*
|
||||
* - LV_LAYER_SIMPLE_BUF_SIZE: [bytes] the optimal target buffer size. LVGL will try to allocate it
|
||||
* - LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE: [bytes] used if `LV_LAYER_SIMPLE_BUF_SIZE` couldn't be allocated.
|
||||
@ -136,7 +134,7 @@
|
||||
* and can't be drawn in chunks. So these settings affects only widgets with opacity.
|
||||
*/
|
||||
#define LV_LAYER_SIMPLE_BUF_SIZE (24 * 1024)
|
||||
#define LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE LV_MAX(lv_area_get_width(&draw_area) * px_size, 2048)
|
||||
#define LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE (3 * 1024)
|
||||
|
||||
/*Default image cache size. Image caching keeps the images opened.
|
||||
*If only the built-in image formats are used there is no real advantage of caching. (I.e. if no new image decoder is added)
|
||||
|
@ -812,204 +812,159 @@ static void refr_obj_and_children(lv_draw_ctx_t * draw_ctx, lv_obj_t * top_obj)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static lv_res_t layer_get_area(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj, lv_layer_type_t layer_type,
|
||||
lv_area_t * layer_area_out)
|
||||
{
|
||||
lv_coord_t ext_draw_size = _lv_obj_get_ext_draw_size(obj);
|
||||
lv_area_t obj_coords_ext;
|
||||
lv_obj_get_coords(obj, &obj_coords_ext);
|
||||
lv_area_increase(&obj_coords_ext, ext_draw_size, ext_draw_size);
|
||||
|
||||
if(layer_type == LV_LAYER_TYPE_TRANSFORM) {
|
||||
/*Get the transformed area and clip it to the current clip area.
|
||||
*This area needs to be updated on the screen.*/
|
||||
lv_area_t clip_coords_for_obj;
|
||||
lv_area_t tranf_coords = obj_coords_ext;
|
||||
lv_obj_get_transformed_area(obj, &tranf_coords, false, false);
|
||||
if(!_lv_area_intersect(&clip_coords_for_obj, draw_ctx->clip_area, &tranf_coords)) {
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
/*Transform back (inverse) the transformed area.
|
||||
*It will tell which area of the non-transformed widget needs to be redrawn
|
||||
*in order to cover transformed area after transformation.*/
|
||||
lv_area_t inverse_clip_coords_for_obj = clip_coords_for_obj;
|
||||
lv_obj_get_transformed_area(obj, &inverse_clip_coords_for_obj, false, true);
|
||||
if(!_lv_area_intersect(&inverse_clip_coords_for_obj, &inverse_clip_coords_for_obj, &obj_coords_ext)) {
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
*layer_area_out = inverse_clip_coords_for_obj;
|
||||
}
|
||||
else if(layer_type == LV_LAYER_TYPE_SIMPLE) {
|
||||
lv_area_t clip_coords_for_obj;
|
||||
if(!_lv_area_intersect(&clip_coords_for_obj, draw_ctx->clip_area, &obj_coords_ext)) {
|
||||
return LV_RES_INV;
|
||||
}
|
||||
*layer_area_out = clip_coords_for_obj;
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Unhandled intermediate layer type");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
static void layer_alpha_test(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx,
|
||||
lv_draw_layer_flags_t flags)
|
||||
{
|
||||
bool has_alpha;
|
||||
/*If globally the layer has alpha maybe this smaller section has not (e.g. not on a rounded corner)
|
||||
*If turns out that this section has no alpha renderer can choose faster algorithms*/
|
||||
if(flags & LV_DRAW_LAYER_FLAG_HAS_ALPHA) {
|
||||
/*Test for alpha by assuming there is no alpha. If it fails, fall back to rendering with alpha*/
|
||||
has_alpha = true;
|
||||
if(_lv_area_is_in(&layer_ctx->area_act, &obj->coords, 0)) {
|
||||
lv_cover_check_info_t info;
|
||||
info.res = LV_COVER_RES_COVER;
|
||||
info.area = &layer_ctx->area_act;
|
||||
lv_event_send(obj, LV_EVENT_COVER_CHECK, &info);
|
||||
if(info.res == LV_COVER_RES_COVER) has_alpha = false;
|
||||
}
|
||||
|
||||
if(has_alpha) {
|
||||
layer_ctx->area_act.y2 = layer_ctx->area_act.y1 + layer_ctx->max_row_with_alpha - 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
has_alpha = false;
|
||||
}
|
||||
|
||||
if(layer_ctx->area_act.y2 > layer_ctx->area_full.y2) layer_ctx->area_act.y2 = layer_ctx->area_full.y2;
|
||||
lv_draw_layer_adjust(draw_ctx, layer_ctx, has_alpha ? LV_DRAW_LAYER_FLAG_HAS_ALPHA : LV_DRAW_LAYER_FLAG_NONE);
|
||||
}
|
||||
|
||||
|
||||
void refr_obj(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj)
|
||||
{
|
||||
/*Do not refresh hidden objects*/
|
||||
if(lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) return;
|
||||
lv_layer_type_t inlayer = _lv_obj_get_layer_type(obj);
|
||||
if(inlayer == LV_LAYER_TYPE_NONE) {
|
||||
lv_layer_type_t layer_type = _lv_obj_get_layer_type(obj);
|
||||
if(layer_type == LV_LAYER_TYPE_NONE) {
|
||||
lv_obj_redraw(draw_ctx, obj);
|
||||
}
|
||||
else {
|
||||
lv_opa_t opa = lv_obj_get_style_opa(obj, 0);
|
||||
if(opa < LV_OPA_MIN) return;
|
||||
|
||||
lv_area_t draw_area;
|
||||
const lv_area_t * clip_area_ori = draw_ctx->clip_area;
|
||||
lv_coord_t ext_draw_size = _lv_obj_get_ext_draw_size(obj);
|
||||
lv_area_t obj_coords_ext;
|
||||
lv_obj_get_coords(obj, &obj_coords_ext);
|
||||
lv_area_increase(&obj_coords_ext, ext_draw_size, ext_draw_size);
|
||||
uint32_t buf_size_sub;
|
||||
lv_area_t layer_area_full;
|
||||
lv_res_t res = layer_get_area(draw_ctx, obj, layer_type, &layer_area_full);
|
||||
if(res != LV_RES_OK) return;
|
||||
|
||||
if(inlayer == LV_LAYER_TYPE_TRANSFORM) {
|
||||
lv_area_t clip_coords_for_obj;
|
||||
lv_area_t tranf_coords = obj_coords_ext;
|
||||
lv_obj_get_transformed_area(obj, &tranf_coords, false, false);
|
||||
if(!_lv_area_intersect(&clip_coords_for_obj, clip_area_ori, &tranf_coords)) {
|
||||
return;
|
||||
}
|
||||
lv_draw_layer_flags_t flags = LV_DRAW_LAYER_FLAG_HAS_ALPHA;
|
||||
|
||||
lv_area_t inverse_clip_coords_for_obj = clip_coords_for_obj;
|
||||
lv_obj_get_transformed_area(obj, &inverse_clip_coords_for_obj, false, true);
|
||||
if(!_lv_area_intersect(&inverse_clip_coords_for_obj, &inverse_clip_coords_for_obj, &obj_coords_ext)) {
|
||||
return;
|
||||
}
|
||||
|
||||
draw_area = inverse_clip_coords_for_obj;
|
||||
}
|
||||
else if(inlayer == LV_LAYER_TYPE_SIMPLE) {
|
||||
lv_area_t clip_coords_for_obj;
|
||||
if(!_lv_area_intersect(&clip_coords_for_obj, clip_area_ori, &obj_coords_ext)) {
|
||||
return;
|
||||
}
|
||||
draw_area = clip_coords_for_obj;
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Unhandled intermediate layer type");
|
||||
return;
|
||||
}
|
||||
|
||||
bool full_cover = false;
|
||||
if(_lv_area_is_in(&draw_area, &obj->coords, 0)) {
|
||||
if(_lv_area_is_in(&layer_area_full, &obj->coords, 0)) {
|
||||
lv_cover_check_info_t info;
|
||||
info.res = LV_COVER_RES_COVER;
|
||||
info.area = &draw_area;
|
||||
info.area = &layer_area_full;
|
||||
lv_event_send(obj, LV_EVENT_COVER_CHECK, &info);
|
||||
if(info.res == LV_COVER_RES_COVER) full_cover = true;
|
||||
if(info.res == LV_COVER_RES_COVER) flags &= ~LV_DRAW_LAYER_FLAG_HAS_ALPHA;
|
||||
}
|
||||
|
||||
if(LV_COLOR_SCREEN_TRANSP == 0 && !full_cover) {
|
||||
LV_LOG_WARN("Rendering this widget needs LV_COLOR_SCREEN_TRANSP 1");
|
||||
if(layer_type == LV_LAYER_TYPE_SIMPLE) flags |= LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE;
|
||||
|
||||
lv_draw_layer_ctx_t * layer_ctx = lv_draw_layer_create(draw_ctx, &layer_area_full, flags);
|
||||
if(layer_ctx == NULL) {
|
||||
LV_LOG_WARN("Couldn't create a new layer context");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t px_size = full_cover ? sizeof(lv_color_t) : LV_IMG_PX_SIZE_ALPHA_BYTE;
|
||||
|
||||
if(inlayer == LV_LAYER_TYPE_SIMPLE) {
|
||||
buf_size_sub = LV_LAYER_SIMPLE_BUF_SIZE;
|
||||
}
|
||||
else {
|
||||
buf_size_sub = lv_area_get_size(&draw_area) * px_size;
|
||||
}
|
||||
|
||||
uint32_t buf_size_full = lv_area_get_size(&draw_area) * px_size;
|
||||
if(buf_size_sub > buf_size_full) buf_size_sub = buf_size_full;
|
||||
|
||||
uint8_t * layer_buf = lv_mem_alloc(buf_size_sub);
|
||||
/*Try again with a smaller buf size*/
|
||||
if(inlayer == LV_LAYER_TYPE_SIMPLE) {
|
||||
if(layer_buf == NULL) {
|
||||
LV_LOG_WARN("Cannot allocate %"LV_PRIu32" bytes for layer buffer. Allocating %"LV_PRIu32" bytes instead. (Reduced performance)",
|
||||
(uint32_t)buf_size_sub * px_size, (uint32_t)LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE * px_size);
|
||||
buf_size_sub = LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE;
|
||||
if(buf_size_sub > buf_size_full) buf_size_sub = buf_size_full;
|
||||
layer_buf = lv_mem_alloc(buf_size_sub);
|
||||
}
|
||||
}
|
||||
if(layer_buf == NULL) {
|
||||
LV_LOG_ERROR("Out of memory: couldn't allocate %"LV_PRIu32" bytes for layer buffer.", (uint32_t)buf_size_sub * px_size);
|
||||
LV_ASSERT_MALLOC(layer_buf);
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t row_cnt = 0;
|
||||
lv_draw_ctx_t * new_draw_ctx = lv_mem_alloc(disp_refr->driver->draw_ctx_size);
|
||||
LV_ASSERT_MALLOC(new_draw_ctx);
|
||||
if(new_draw_ctx == NULL) {
|
||||
LV_LOG_ERROR("Out of memory: couldn't allocate new draw context.");
|
||||
lv_mem_free(layer_buf);
|
||||
return;
|
||||
}
|
||||
|
||||
lv_area_t draw_area_sub = draw_area;
|
||||
|
||||
/*Set-up a new draw_ctx*/
|
||||
bool old_scr_transp = disp_refr->driver->screen_transp;
|
||||
disp_refr->driver->draw_ctx_init(disp_refr->driver, new_draw_ctx);
|
||||
new_draw_ctx->clip_area = &draw_area_sub;
|
||||
new_draw_ctx->buf_area = &draw_area_sub;
|
||||
new_draw_ctx->buf = (void *)layer_buf;
|
||||
lv_point_t pivot = {
|
||||
.x = lv_obj_get_style_transform_pivot_x(obj, 0),
|
||||
.y = lv_obj_get_style_transform_pivot_y(obj, 0)
|
||||
};
|
||||
|
||||
lv_draw_img_dsc_t draw_dsc;
|
||||
lv_draw_img_dsc_init(&draw_dsc);
|
||||
draw_dsc.opa = opa;
|
||||
draw_dsc.angle = lv_obj_get_style_transform_angle(obj, 0);
|
||||
if(draw_dsc.angle > 3600) draw_dsc.angle -= 3600;
|
||||
if(draw_dsc.angle < 0) draw_dsc.angle += 3600;
|
||||
else if(draw_dsc.angle < 0) draw_dsc.angle += 3600;
|
||||
|
||||
draw_dsc.zoom = lv_obj_get_style_transform_zoom(obj, 0);
|
||||
draw_dsc.blend_mode = lv_obj_get_style_blend_mode(obj, 0);
|
||||
draw_dsc.antialias = disp_refr->driver->antialiasing;
|
||||
|
||||
lv_point_t pivot;
|
||||
pivot.x = lv_obj_get_style_transform_pivot_x(obj, 0);
|
||||
pivot.y = lv_obj_get_style_transform_pivot_y(obj, 0);
|
||||
|
||||
lv_img_dsc_t img;
|
||||
img.data = layer_buf;
|
||||
img.header.always_zero = 0;
|
||||
img.header.w = lv_area_get_width(&draw_area);
|
||||
|
||||
/*If the whole area is covers calculate the row count only once*/
|
||||
if(full_cover) {
|
||||
row_cnt = buf_size_sub / (sizeof(lv_color_t) * lv_area_get_width(&draw_area));
|
||||
draw_area_sub.y2 = draw_area_sub.y1 + row_cnt - 1;
|
||||
if(draw_area_sub.y2 > draw_area.y2) draw_area_sub.y2 = draw_area.y2;
|
||||
if(flags & LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE) {
|
||||
layer_ctx->area_act = layer_ctx->area_full;
|
||||
layer_ctx->area_act.y2 = layer_ctx->area_act.y1 + layer_ctx->max_row_with_no_alpha - 1;
|
||||
if(layer_ctx->area_act.y2 > layer_ctx->area_full.y2) layer_ctx->area_act.y2 = layer_ctx->area_full.y2;
|
||||
}
|
||||
|
||||
while(draw_area_sub.y1 <= draw_area.y2) {
|
||||
/* If the widget covers the area of as many rows as an RGB buffer provides,
|
||||
* draw it as RGB instead of ARGB because it's much faster
|
||||
* `full_cover_global == true` indicates that the widget covers the whole draw_area anyway*/
|
||||
if(!full_cover) {
|
||||
row_cnt = buf_size_sub / (sizeof(lv_color_t) * lv_area_get_width(&draw_area));
|
||||
while(layer_ctx->area_act.y1 <= layer_area_full.y2) {
|
||||
if(flags & LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE) {
|
||||
layer_alpha_test(obj, draw_ctx, layer_ctx, flags);
|
||||
}
|
||||
|
||||
draw_area_sub.y2 = draw_area_sub.y1 + row_cnt - 1;
|
||||
if(draw_area_sub.y2 > draw_area.y2) draw_area_sub.y2 = draw_area.y2;
|
||||
lv_obj_redraw(draw_ctx, obj);
|
||||
|
||||
bool full_cover_sub = false;
|
||||
if(_lv_area_is_in(&draw_area_sub, &obj->coords, 0)) {
|
||||
lv_cover_check_info_t info;
|
||||
info.res = LV_COVER_RES_COVER;
|
||||
info.area = &draw_area_sub;
|
||||
lv_event_send(obj, LV_EVENT_COVER_CHECK, &info);
|
||||
if(info.res == LV_COVER_RES_COVER) full_cover_sub = true;
|
||||
}
|
||||
draw_dsc.pivot.x = obj->coords.x1 + pivot.x - draw_ctx->buf_area->x1;
|
||||
draw_dsc.pivot.y = obj->coords.y1 + pivot.y - draw_ctx->buf_area->y1;
|
||||
|
||||
/* In the area is not covered by the widget recalculate the row count using ARGB pixel size
|
||||
* It can happen that this smaller area is already covered by the widget but ignore this case
|
||||
* in favor of fewer LV_EVENT_COVER_CHECK calls */
|
||||
if(!full_cover_sub) {
|
||||
row_cnt = buf_size_sub / (LV_IMG_PX_SIZE_ALPHA_BYTE * lv_area_get_width(&draw_area));
|
||||
draw_area_sub.y2 = draw_area_sub.y1 + row_cnt - 1;
|
||||
if(draw_area_sub.y2 > draw_area.y2) draw_area_sub.y2 = draw_area.y2;
|
||||
disp_refr->driver->screen_transp = 1;
|
||||
img.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA;
|
||||
}
|
||||
else {
|
||||
disp_refr->driver->screen_transp = 0;
|
||||
img.header.cf = LV_IMG_CF_TRUE_COLOR;
|
||||
}
|
||||
/*With LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE it should also go the next chunk*/
|
||||
lv_draw_layer_blend(draw_ctx, layer_ctx, &draw_dsc);
|
||||
|
||||
draw_dsc.pivot.x = obj->coords.x1 + pivot.x - draw_area_sub.x1;
|
||||
draw_dsc.pivot.y = obj->coords.y1 + pivot.y - draw_area_sub.y1;
|
||||
if((flags & LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE) == 0) break;
|
||||
|
||||
if(!full_cover_sub) lv_memset_00(layer_buf, buf_size_sub);
|
||||
lv_obj_redraw(new_draw_ctx, obj);
|
||||
|
||||
lv_img_cache_invalidate_src(&img);
|
||||
|
||||
img.header.h = lv_area_get_height(&draw_area_sub);
|
||||
|
||||
disp_refr->driver->screen_transp = old_scr_transp;
|
||||
lv_draw_img(draw_ctx, &draw_dsc, &draw_area_sub, &img);
|
||||
|
||||
draw_area_sub.y1 = draw_area_sub.y2 + 1;
|
||||
if(draw_area_sub.y2 > draw_area.y2) draw_area_sub.y2 = draw_area.y2;
|
||||
lv_area_move(&layer_ctx->area_act, 0, layer_ctx->max_row_with_no_alpha);
|
||||
}
|
||||
|
||||
disp_refr->driver->draw_ctx_deinit(disp_refr->driver, new_draw_ctx);
|
||||
lv_mem_free(layer_buf);
|
||||
lv_mem_free(new_draw_ctx);
|
||||
disp_refr->driver->screen_transp = old_scr_transp;
|
||||
lv_draw_layer_destroy(draw_ctx, layer_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static uint32_t get_max_row(lv_disp_t * disp, lv_coord_t area_w, lv_coord_t area_h)
|
||||
{
|
||||
int32_t max_row = (uint32_t)disp->driver->draw_buf->size / area_w;
|
||||
|
@ -42,6 +42,11 @@ void lv_draw_init(void)
|
||||
/*Nothing to init now*/
|
||||
}
|
||||
|
||||
void lv_draw_wait_for_finish(lv_draw_ctx_t * draw_ctx)
|
||||
{
|
||||
if(draw_ctx->wait_for_finish) draw_ctx->wait_for_finish(draw_ctx);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
@ -28,6 +28,7 @@ extern "C" {
|
||||
#include "lv_draw_arc.h"
|
||||
#include "lv_draw_mask.h"
|
||||
#include "lv_draw_transform.h"
|
||||
#include "lv_draw_layer.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@ -41,6 +42,19 @@ typedef struct {
|
||||
void * user_data;
|
||||
} lv_draw_mask_t;
|
||||
|
||||
typedef struct _lv_draw_layer_ctx_t {
|
||||
lv_area_t area_full;
|
||||
lv_area_t area_act;
|
||||
lv_coord_t max_row_with_alpha;
|
||||
lv_coord_t max_row_with_no_alpha;
|
||||
void * buf;
|
||||
struct {
|
||||
const lv_area_t * clip_area;
|
||||
lv_area_t * buf_area;
|
||||
void * buf;
|
||||
bool screen_transp;
|
||||
} original;
|
||||
} lv_draw_layer_ctx_t;
|
||||
|
||||
typedef struct _lv_draw_ctx_t {
|
||||
/**
|
||||
@ -126,6 +140,50 @@ typedef struct _lv_draw_ctx_t {
|
||||
void (*buffer_copy)(struct _lv_draw_ctx_t * draw_ctx, void * dest_buf, lv_coord_t dest_stride,
|
||||
const lv_area_t * dest_area,
|
||||
void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area);
|
||||
|
||||
/**
|
||||
* Initialize a new layer context.
|
||||
* The original buffer and area data are already saved from `draw_ctx` to `layer_ctx`
|
||||
* @param draw_ctx pointer to the current draw context
|
||||
* @param layer_area the coordinates of the layer
|
||||
* @param flags OR-ed flags from @lv_draw_layer_flags_t
|
||||
* @return pointer to the layer context, or NULL on error
|
||||
*/
|
||||
struct _lv_draw_layer_ctx_t * (*layer_init)(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx,
|
||||
lv_draw_layer_flags_t flags);
|
||||
|
||||
/**
|
||||
* Adjust the layer_ctx and/or draw_ctx based on the `layer_ctx->area_act`.
|
||||
* It's called only if flags has `LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE`
|
||||
* @param draw_ctx pointer to the current draw context
|
||||
* @param layer_ctx pointer to a layer context
|
||||
* @param flags OR-ed flags from @lv_draw_layer_flags_t
|
||||
*/
|
||||
void (*layer_adjust)(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx,
|
||||
lv_draw_layer_flags_t flags);
|
||||
|
||||
/**
|
||||
* Blend a rendered layer to `layer_ctx->area_act`
|
||||
* @param draw_ctx pointer to the current draw context
|
||||
* @param layer_ctx pointer to a layer context
|
||||
* @param draw_dsc pointer to an image draw descriptor
|
||||
*/
|
||||
void (*layer_blend)(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx,
|
||||
const lv_draw_img_dsc_t * draw_dsc);
|
||||
|
||||
/**
|
||||
* Destroy a layer context. The original buffer and area data of the `draw_ctx` will be restored
|
||||
* and the `layer_ctx` itself will be freed automatically.
|
||||
* @param draw_ctx pointer to the current draw context
|
||||
* @param layer_ctx pointer to a layer context
|
||||
*/
|
||||
void (*layer_destroy)(struct _lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx);
|
||||
|
||||
/**
|
||||
* Size of a layer context in bytes.
|
||||
*/
|
||||
size_t layer_instance_size;
|
||||
|
||||
#if LV_USE_USER_DATA
|
||||
void * user_data;
|
||||
#endif
|
||||
@ -138,6 +196,9 @@ typedef struct _lv_draw_ctx_t {
|
||||
|
||||
void lv_draw_init(void);
|
||||
|
||||
|
||||
void lv_draw_wait_for_finish(lv_draw_ctx_t * draw_ctx);
|
||||
|
||||
/**********************
|
||||
* GLOBAL VARIABLES
|
||||
**********************/
|
||||
|
@ -6,6 +6,7 @@ CSRCS += lv_draw_line.c
|
||||
CSRCS += lv_draw_mask.c
|
||||
CSRCS += lv_draw_rect.c
|
||||
CSRCS += lv_draw_transform.c
|
||||
CSRCS += lv_draw_layer.c
|
||||
CSRCS += lv_draw_triangle.c
|
||||
CSRCS += lv_img_buf.c
|
||||
CSRCS += lv_img_cache.c
|
||||
|
89
src/draw/lv_draw_layer.c
Normal file
89
src/draw/lv_draw_layer.c
Normal file
@ -0,0 +1,89 @@
|
||||
/**
|
||||
* @file lv_draw_layer.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw.h"
|
||||
#include "lv_draw_arc.h"
|
||||
#include "../core/lv_refr.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_draw_layer_ctx_t * lv_draw_layer_create(lv_draw_ctx_t * draw_ctx, const lv_area_t * layer_area,
|
||||
lv_draw_layer_flags_t flags)
|
||||
{
|
||||
if(draw_ctx->layer_init == NULL) return NULL;
|
||||
|
||||
lv_draw_layer_ctx_t * layer_ctx = lv_mem_alloc(draw_ctx->layer_instance_size);
|
||||
LV_ASSERT_MALLOC(layer_ctx);
|
||||
if(layer_ctx == NULL) {
|
||||
LV_LOG_WARN("Couldn't allocate a new layer context");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_memset_00(layer_ctx, draw_ctx->layer_instance_size);
|
||||
|
||||
lv_disp_t * disp_refr = _lv_refr_get_disp_refreshing();
|
||||
layer_ctx->original.buf = draw_ctx->buf;
|
||||
layer_ctx->original.buf_area = draw_ctx->buf_area;
|
||||
layer_ctx->original.clip_area = draw_ctx->clip_area;
|
||||
layer_ctx->original.screen_transp = disp_refr->driver->screen_transp;
|
||||
layer_ctx->area_full = *layer_area;
|
||||
|
||||
return draw_ctx->layer_init(draw_ctx, layer_ctx, flags);
|
||||
}
|
||||
|
||||
void lv_draw_layer_adjust(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx,
|
||||
lv_draw_layer_flags_t flags)
|
||||
{
|
||||
if(draw_ctx->layer_adjust) draw_ctx->layer_adjust(draw_ctx, layer_ctx, flags);
|
||||
}
|
||||
|
||||
void lv_draw_layer_blend(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx,
|
||||
lv_draw_img_dsc_t * draw_dsc)
|
||||
{
|
||||
if(draw_ctx->layer_blend) draw_ctx->layer_blend(draw_ctx, layer_ctx, draw_dsc);
|
||||
}
|
||||
|
||||
void lv_draw_layer_destroy(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx)
|
||||
{
|
||||
|
||||
lv_draw_wait_for_finish(draw_ctx);
|
||||
draw_ctx->buf = layer_ctx->original.buf;
|
||||
draw_ctx->buf_area = layer_ctx->original.buf_area;
|
||||
draw_ctx->clip_area = layer_ctx->original.clip_area;
|
||||
lv_disp_t * disp_refr = _lv_refr_get_disp_refreshing();
|
||||
disp_refr->driver->screen_transp = layer_ctx->original.screen_transp;
|
||||
|
||||
if(draw_ctx->layer_destroy) draw_ctx->layer_destroy(draw_ctx, layer_ctx);
|
||||
lv_mem_free(layer_ctx);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
83
src/draw/lv_draw_layer.h
Normal file
83
src/draw/lv_draw_layer.h
Normal file
@ -0,0 +1,83 @@
|
||||
/**
|
||||
* @file lv_draw_layer.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_LAYER_H
|
||||
#define LV_DRAW_LAYER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
struct _lv_draw_ctx_t;
|
||||
struct _lv_draw_layer_ctx_t;
|
||||
|
||||
typedef enum {
|
||||
LV_DRAW_LAYER_FLAG_NONE,
|
||||
LV_DRAW_LAYER_FLAG_HAS_ALPHA,
|
||||
LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE,
|
||||
} lv_draw_layer_flags_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a new layer context. It is used to start and independent rendering session
|
||||
* with the current draw_ctx
|
||||
* @param draw_ctx pointer to the current draw context
|
||||
* @param layer_area the coordinates of the layer
|
||||
* @param flags OR-ed flags from @lv_draw_layer_flags_t
|
||||
* @return pointer to the layer context, or NULL on error
|
||||
*/
|
||||
struct _lv_draw_layer_ctx_t * lv_draw_layer_create(struct _lv_draw_ctx_t * draw_ctx, const lv_area_t * layer_area,
|
||||
lv_draw_layer_flags_t flags);
|
||||
|
||||
/**
|
||||
* Adjust the layer_ctx and/or draw_ctx based on the `layer_ctx->area_act`.
|
||||
* It's called only if flags has `LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE`
|
||||
* @param draw_ctx pointer to the current draw context
|
||||
* @param layer_ctx pointer to a layer context
|
||||
* @param flags OR-ed flags from @lv_draw_layer_flags_t
|
||||
*/
|
||||
void lv_draw_layer_adjust(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx,
|
||||
lv_draw_layer_flags_t flags);
|
||||
|
||||
/**
|
||||
* Blend a rendered layer to `layer_ctx->area_act`
|
||||
* @param draw_ctx pointer to the current draw context
|
||||
* @param layer_ctx pointer to a layer context
|
||||
* @param draw_dsc pointer to an image draw descriptor
|
||||
*/
|
||||
void lv_draw_layer_blend(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx,
|
||||
lv_draw_img_dsc_t * draw_dsc);
|
||||
|
||||
/**
|
||||
* Destroy a layer context.
|
||||
* @param draw_ctx pointer to the current draw context
|
||||
* @param layer_ctx pointer to a layer context
|
||||
*/
|
||||
void lv_draw_layer_destroy(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_LAYER_H*/
|
@ -15,6 +15,7 @@
|
||||
#include "lv_draw_sdl.h"
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
#include "lv_draw_sdl_layer.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@ -69,6 +70,10 @@ void lv_draw_sdl_init_ctx(lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx)
|
||||
draw_ctx->draw_arc = lv_draw_sdl_draw_arc;
|
||||
draw_ctx->draw_polygon = lv_draw_sdl_polygon;
|
||||
draw_ctx->draw_bg = lv_draw_sdl_draw_bg;
|
||||
draw_ctx->layer_init = lv_draw_sdl_layer_init;
|
||||
draw_ctx->layer_blend = lv_draw_sdl_layer_blend;
|
||||
draw_ctx->layer_destroy = lv_draw_sdl_layer_destroy;
|
||||
draw_ctx->layer_instance_size = sizeof(lv_draw_sdl_layer_ctx_t);
|
||||
lv_draw_sdl_ctx_t * draw_ctx_sdl = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
draw_ctx_sdl->renderer = ((lv_draw_sdl_drv_param_t *) disp_drv->user_data)->renderer;
|
||||
draw_ctx_sdl->internals = lv_mem_alloc(sizeof(lv_draw_sdl_context_internals_t));
|
||||
|
@ -11,6 +11,7 @@ CSRCS += lv_draw_sdl_rect.c
|
||||
CSRCS += lv_draw_sdl_stack_blur.c
|
||||
CSRCS += lv_draw_sdl_texture_cache.c
|
||||
CSRCS += lv_draw_sdl_utils.c
|
||||
CSRCS += lv_draw_sdl_layer.c
|
||||
|
||||
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sdl
|
||||
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sdl
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include "../../misc/lv_gc.h"
|
||||
#include "../../core/lv_refr.h"
|
||||
#include "lv_draw_sdl_composite.h"
|
||||
#include "lv_draw_sdl_mask.h"
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_priv.h"
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
@ -84,15 +83,16 @@ bool lv_draw_sdl_composite_begin(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coor
|
||||
const bool draw_blend = blend_mode != LV_BLEND_MODE_NORMAL;
|
||||
if(draw_mask || draw_blend) {
|
||||
lv_draw_sdl_context_internals_t * internals = ctx->internals;
|
||||
LV_ASSERT(internals->mask == NULL && internals->composition == NULL);
|
||||
LV_ASSERT(internals->mask == NULL && internals->composition == NULL && internals->target_backup == NULL);
|
||||
|
||||
lv_coord_t w = lv_area_get_width(apply_area), h = lv_area_get_height(apply_area);
|
||||
internals->composition = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET0, w, h);
|
||||
/* Don't need to worry about overflow */
|
||||
/* Don't need to worry about integral overflow */
|
||||
lv_coord_t ofs_x = (lv_coord_t) - apply_area->x1, ofs_y = (lv_coord_t) - apply_area->y1;
|
||||
/* Offset draw area to start with (0,0) of coords */
|
||||
lv_area_move(coords_out, ofs_x, ofs_y);
|
||||
lv_area_move(clip_out, ofs_x, ofs_y);
|
||||
internals->target_backup = SDL_GetRenderTarget(ctx->renderer);
|
||||
SDL_SetRenderTarget(ctx->renderer, internals->composition);
|
||||
SDL_SetRenderDrawColor(ctx->renderer, 255, 255, 255, 0);
|
||||
SDL_RenderClear(ctx->renderer);
|
||||
@ -140,7 +140,7 @@ void lv_draw_sdl_composite_end(lv_draw_sdl_ctx_t * ctx, const lv_area_t * apply_
|
||||
SDL_Rect dst_rect;
|
||||
lv_area_to_sdl_rect(apply_area, &dst_rect);
|
||||
|
||||
SDL_SetRenderTarget(ctx->renderer, ctx->base_draw.buf);
|
||||
SDL_SetRenderTarget(ctx->renderer, internals->target_backup);
|
||||
switch(blend_mode) {
|
||||
case LV_BLEND_MODE_NORMAL:
|
||||
SDL_SetTextureBlendMode(internals->composition, SDL_BLENDMODE_BLEND);
|
||||
@ -173,7 +173,7 @@ void lv_draw_sdl_composite_end(lv_draw_sdl_ctx_t * ctx, const lv_area_t * apply_
|
||||
SDL_RenderCopy(ctx->renderer, internals->composition, &src_rect, &dst_rect);
|
||||
}
|
||||
|
||||
internals->mask = internals->composition = NULL;
|
||||
internals->mask = internals->composition = internals->target_backup = NULL;
|
||||
}
|
||||
|
||||
SDL_Texture * lv_draw_sdl_composite_texture_obtain(lv_draw_sdl_ctx_t * ctx, lv_draw_sdl_composite_texture_id_t id,
|
||||
@ -186,7 +186,10 @@ SDL_Texture * lv_draw_sdl_composite_texture_obtain(lv_draw_sdl_ctx_t * ctx, lv_d
|
||||
if(!result || tex_size->x < w || tex_size->y < h) {
|
||||
lv_coord_t size = next_pow_of_2(LV_MAX(w, h));
|
||||
int access = SDL_TEXTUREACCESS_STREAMING;
|
||||
if(id >= LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET0) {
|
||||
if(id >= LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TRANSFORM0) {
|
||||
access = SDL_TEXTUREACCESS_TARGET;
|
||||
}
|
||||
else if(id >= LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET0) {
|
||||
access = SDL_TEXTUREACCESS_TARGET;
|
||||
}
|
||||
result = SDL_CreateTexture(ctx->renderer, LV_DRAW_SDL_TEXTURE_FORMAT, access, size, size);
|
||||
|
@ -35,6 +35,7 @@ typedef enum lv_draw_sdl_composite_texture_id_t {
|
||||
LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM1,
|
||||
LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET0,
|
||||
LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET1,
|
||||
LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TRANSFORM0,
|
||||
} lv_draw_sdl_composite_texture_id_t;
|
||||
|
||||
/**********************
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
#include "lv_draw_sdl_composite.h"
|
||||
#include "lv_draw_sdl_rect.h"
|
||||
#include "lv_draw_sdl_layer.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@ -123,11 +124,15 @@ lv_res_t lv_draw_sdl_img_core(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t
|
||||
/* Coords will be translated so coords will start at (0,0) */
|
||||
lv_area_t t_coords = zoomed_cords, t_clip = *clip, apply_area;
|
||||
|
||||
bool has_composite = false;
|
||||
|
||||
if(!check_mask_simple_radius(&t_coords, &radius)) {
|
||||
lv_draw_sdl_composite_begin(ctx, &zoomed_cords, clip, NULL, draw_dsc->blend_mode,
|
||||
&t_coords, &t_clip, &apply_area);
|
||||
has_composite = lv_draw_sdl_composite_begin(ctx, &zoomed_cords, clip, NULL, draw_dsc->blend_mode,
|
||||
&t_coords, &t_clip, &apply_area);
|
||||
}
|
||||
|
||||
lv_draw_sdl_transform_areas_offset(ctx, has_composite, &apply_area, &t_coords, &t_clip);
|
||||
|
||||
SDL_Rect clip_rect, coords_rect;
|
||||
lv_area_to_sdl_rect(&t_clip, &clip_rect);
|
||||
lv_area_to_sdl_rect(&t_coords, &coords_rect);
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_texture_cache.h"
|
||||
#include "lv_draw_sdl_composite.h"
|
||||
#include "lv_draw_sdl_layer.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@ -134,8 +135,10 @@ void lv_draw_sdl_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t
|
||||
}
|
||||
|
||||
lv_area_t t_letter = letter_area, t_clip = *clip_area, apply_area;
|
||||
bool has_mask = lv_draw_sdl_composite_begin(ctx, &letter_area, clip_area, NULL, dsc->blend_mode, &t_letter, &t_clip,
|
||||
&apply_area);
|
||||
bool has_composite = lv_draw_sdl_composite_begin(ctx, &letter_area, clip_area, NULL, dsc->blend_mode, &t_letter,
|
||||
&t_clip, &apply_area);
|
||||
|
||||
lv_draw_sdl_transform_areas_offset(ctx, has_composite, &apply_area, &t_letter, &t_clip);
|
||||
|
||||
/*If the letter is completely out of mask don't draw it*/
|
||||
if(!_lv_area_intersect(&draw_area, &t_letter, &t_clip)) {
|
||||
|
132
src/draw/sdl/lv_draw_sdl_layer.c
Normal file
132
src/draw/sdl/lv_draw_sdl_layer.c
Normal file
@ -0,0 +1,132 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_refr.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
|
||||
#include "../../core/lv_refr.h"
|
||||
|
||||
#include "lv_draw_sdl.h"
|
||||
#include "lv_draw_sdl_priv.h"
|
||||
#include "lv_draw_sdl_composite.h"
|
||||
#include "lv_draw_sdl_utils.h"
|
||||
#include "lv_draw_sdl_layer.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_draw_layer_ctx_t * lv_draw_sdl_layer_init(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx,
|
||||
lv_draw_layer_flags_t flags)
|
||||
{
|
||||
lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
SDL_Renderer * renderer = ctx->renderer;
|
||||
|
||||
lv_draw_sdl_layer_ctx_t * transform_ctx = (lv_draw_sdl_layer_ctx_t *) layer_ctx;
|
||||
|
||||
transform_ctx->flags = flags;
|
||||
transform_ctx->orig_target = SDL_GetRenderTarget(renderer);
|
||||
|
||||
lv_coord_t target_w = lv_area_get_width(&layer_ctx->area_full);
|
||||
lv_coord_t target_h = lv_area_get_height(&layer_ctx->area_full);
|
||||
|
||||
enum lv_draw_sdl_composite_texture_id_t texture_id = LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TRANSFORM0 +
|
||||
ctx->internals->transform_count;
|
||||
transform_ctx->target = lv_draw_sdl_composite_texture_obtain(ctx, texture_id, target_w, target_h);
|
||||
transform_ctx->target_rect.x = 0;
|
||||
transform_ctx->target_rect.y = 0;
|
||||
transform_ctx->target_rect.w = target_w;
|
||||
transform_ctx->target_rect.h = target_h;
|
||||
|
||||
SDL_SetTextureBlendMode(transform_ctx->target, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetRenderTarget(renderer, transform_ctx->target);
|
||||
SDL_RenderClear(renderer);
|
||||
|
||||
/* Set proper drawing context for transform layer */
|
||||
ctx->internals->transform_count += 1;
|
||||
draw_ctx->buf_area = &layer_ctx->area_full;
|
||||
draw_ctx->clip_area = &layer_ctx->area_full;
|
||||
|
||||
return layer_ctx;
|
||||
}
|
||||
|
||||
void lv_draw_sdl_layer_blend(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx,
|
||||
const lv_draw_img_dsc_t * draw_dsc)
|
||||
{
|
||||
lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
lv_draw_sdl_layer_ctx_t * transform_ctx = (lv_draw_sdl_layer_ctx_t *) layer_ctx;
|
||||
|
||||
SDL_Renderer * renderer = ctx->renderer;
|
||||
|
||||
SDL_Rect trans_rect;
|
||||
|
||||
if(transform_ctx->flags & LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE) {
|
||||
lv_area_zoom_to_sdl_rect(&layer_ctx->area_act, &trans_rect, draw_dsc->zoom, &draw_dsc->pivot);
|
||||
}
|
||||
else {
|
||||
lv_area_zoom_to_sdl_rect(&layer_ctx->area_full, &trans_rect, draw_dsc->zoom, &draw_dsc->pivot);
|
||||
}
|
||||
|
||||
SDL_SetRenderTarget(renderer, transform_ctx->orig_target);
|
||||
|
||||
/*Render off-screen texture, transformed*/
|
||||
SDL_Rect clip_rect;
|
||||
lv_area_to_sdl_rect(layer_ctx->original.clip_area, &clip_rect);
|
||||
SDL_Point center = {.x = draw_dsc->pivot.x, .y = draw_dsc->pivot.y};
|
||||
SDL_RenderSetClipRect(renderer, &clip_rect);
|
||||
SDL_RenderCopyEx(renderer, transform_ctx->target, &transform_ctx->target_rect, &trans_rect,
|
||||
draw_dsc->angle, ¢er, SDL_FLIP_NONE);
|
||||
SDL_RenderSetClipRect(renderer, NULL);
|
||||
}
|
||||
|
||||
void lv_draw_sdl_layer_destroy(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx)
|
||||
{
|
||||
lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
|
||||
ctx->internals->transform_count -= 1;
|
||||
}
|
||||
|
||||
void lv_draw_sdl_transform_areas_offset(lv_draw_sdl_ctx_t * ctx, bool has_composite, lv_area_t * apply_area,
|
||||
lv_area_t * coords, lv_area_t * clip)
|
||||
{
|
||||
if(ctx->internals->transform_count == 0) {
|
||||
return;
|
||||
}
|
||||
lv_area_t * area = ctx->base_draw.buf_area;
|
||||
lv_area_move(coords, -area->x1, -area->y1);
|
||||
lv_area_move(clip, -area->x1, -area->y1);
|
||||
if(has_composite) {
|
||||
lv_area_move(apply_area, -area->x1, -area->y1);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_GPU_SDL*/
|
55
src/draw/sdl/lv_draw_sdl_layer.h
Normal file
55
src/draw/sdl/lv_draw_sdl_layer.h
Normal file
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* @file lv_draw_sdl_refr.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_TEMPL_H
|
||||
#define LV_TEMPL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_sdl.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct _lv_draw_sdl_layer_ctx_t {
|
||||
lv_draw_layer_ctx_t base;
|
||||
|
||||
SDL_Texture * orig_target;
|
||||
SDL_Texture * target;
|
||||
SDL_Rect target_rect;
|
||||
lv_draw_layer_flags_t flags;
|
||||
} lv_draw_sdl_layer_ctx_t;
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
lv_draw_layer_ctx_t * lv_draw_sdl_layer_init(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx,
|
||||
lv_draw_layer_flags_t flags);
|
||||
|
||||
void lv_draw_sdl_layer_blend(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * transform_ctx,
|
||||
const lv_draw_img_dsc_t * draw_dsc);
|
||||
|
||||
void lv_draw_sdl_layer_destroy(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx);
|
||||
|
||||
void lv_draw_sdl_transform_areas_offset(lv_draw_sdl_ctx_t * ctx, bool has_composite, lv_area_t * apply_area,
|
||||
lv_area_t * coords, lv_area_t * clip);
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_TEMPL_H*/
|
@ -35,6 +35,8 @@ typedef struct lv_draw_sdl_context_internals_t {
|
||||
lv_lru_t * texture_cache;
|
||||
SDL_Texture * mask;
|
||||
SDL_Texture * composition;
|
||||
SDL_Texture * target_backup;
|
||||
uint8_t transform_count;
|
||||
} lv_draw_sdl_context_internals_t;
|
||||
|
||||
/**********************
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "lv_draw_sdl_composite.h"
|
||||
#include "lv_draw_sdl_mask.h"
|
||||
#include "lv_draw_sdl_stack_blur.h"
|
||||
#include "lv_draw_sdl_img.h"
|
||||
#include "lv_draw_sdl_layer.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@ -124,7 +124,11 @@ void lv_draw_sdl_draw_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t *
|
||||
}
|
||||
/* Coords will be translated so coords will start at (0,0) */
|
||||
lv_area_t t_coords = *coords, t_clip = *clip, apply_area, t_area;
|
||||
lv_draw_sdl_composite_begin(ctx, coords, clip, &extension, dsc->blend_mode, &t_coords, &t_clip, &apply_area);
|
||||
bool has_composite = lv_draw_sdl_composite_begin(ctx, coords, clip, &extension, dsc->blend_mode, &t_coords, &t_clip,
|
||||
&apply_area);
|
||||
|
||||
lv_draw_sdl_transform_areas_offset(ctx, has_composite, &apply_area, &t_coords, &t_clip);
|
||||
|
||||
bool has_content = _lv_area_intersect(&t_area, &t_coords, &t_clip);
|
||||
|
||||
SDL_Rect clip_rect;
|
||||
|
@ -56,7 +56,12 @@ void lv_draw_sw_init_ctx(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
|
||||
#endif
|
||||
draw_sw_ctx->base_draw.wait_for_finish = lv_draw_sw_wait_for_finish;
|
||||
draw_sw_ctx->base_draw.buffer_copy = lv_draw_sw_buffer_copy;
|
||||
draw_sw_ctx->base_draw.layer_init = lv_draw_sw_layer_create;
|
||||
draw_sw_ctx->base_draw.layer_adjust = lv_draw_sw_layer_adjust;
|
||||
draw_sw_ctx->base_draw.layer_blend = lv_draw_sw_layer_blend;
|
||||
draw_sw_ctx->base_draw.layer_destroy = lv_draw_sw_layer_destroy;
|
||||
draw_sw_ctx->blend = lv_draw_sw_blend_basic;
|
||||
draw_ctx->layer_instance_size = sizeof(lv_draw_sw_layer_ctx_t);
|
||||
}
|
||||
|
||||
void lv_draw_sw_deinit_ctx(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
|
||||
@ -96,7 +101,6 @@ void lv_draw_sw_buffer_copy(lv_draw_ctx_t * draw_ctx,
|
||||
dest_bufc += dest_stride;
|
||||
src_bufc += src_stride;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**********************
|
||||
|
@ -36,6 +36,13 @@ typedef struct {
|
||||
void (*blend)(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc);
|
||||
} lv_draw_sw_ctx_t;
|
||||
|
||||
typedef struct {
|
||||
lv_draw_layer_ctx_t base_draw;
|
||||
|
||||
uint32_t buf_size_bytes: 31;
|
||||
uint32_t has_alpha : 1;
|
||||
} lv_draw_sw_layer_ctx_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
@ -67,11 +74,21 @@ void lv_draw_sw_buffer_copy(lv_draw_ctx_t * draw_ctx,
|
||||
void * dest_buf, lv_coord_t dest_stride, const lv_area_t * dest_area,
|
||||
void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area);
|
||||
|
||||
|
||||
void lv_draw_sw_transform(lv_draw_ctx_t * draw_ctx, const lv_area_t * dest_area, const void * src_buf,
|
||||
lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride,
|
||||
const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t cf, lv_color_t * cbuf, lv_opa_t * abuf);
|
||||
|
||||
struct _lv_draw_layer_ctx_t * lv_draw_sw_layer_create(struct _lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx,
|
||||
lv_draw_layer_flags_t flags);
|
||||
|
||||
void lv_draw_sw_layer_adjust(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx,
|
||||
lv_draw_layer_flags_t flags);
|
||||
|
||||
void lv_draw_sw_layer_blend(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx,
|
||||
const lv_draw_img_dsc_t * draw_dsc);
|
||||
|
||||
void lv_draw_sw_layer_destroy(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx);
|
||||
|
||||
/***********************
|
||||
* GLOBAL VARIABLES
|
||||
***********************/
|
||||
|
@ -9,6 +9,7 @@ CSRCS += lv_draw_sw_line.c
|
||||
CSRCS += lv_draw_sw_polygon.c
|
||||
CSRCS += lv_draw_sw_rect.c
|
||||
CSRCS += lv_draw_sw_transform.c
|
||||
CSRCS += lv_draw_sw_layer.c
|
||||
|
||||
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sw
|
||||
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sw
|
||||
|
152
src/draw/sw/lv_draw_sw_layer.c
Normal file
152
src/draw/sw/lv_draw_sw_layer.c
Normal file
@ -0,0 +1,152 @@
|
||||
/**
|
||||
* @file lv_draw_sw_layer.h
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_sw.h"
|
||||
#include "../../hal/lv_hal_disp.h"
|
||||
#include "../../misc/lv_area.h"
|
||||
#include "../../core/lv_refr.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
|
||||
struct _lv_draw_layer_ctx_t * lv_draw_sw_layer_create(struct _lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx,
|
||||
lv_draw_layer_flags_t flags)
|
||||
{
|
||||
if(LV_COLOR_SCREEN_TRANSP == 0 && (flags & LV_DRAW_LAYER_FLAG_HAS_ALPHA)) {
|
||||
LV_LOG_WARN("Rendering this widget needs LV_COLOR_SCREEN_TRANSP 1");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_draw_sw_layer_ctx_t * layer_sw_ctx = (lv_draw_sw_layer_ctx_t *) layer_ctx;
|
||||
uint32_t px_size = flags & LV_DRAW_LAYER_FLAG_HAS_ALPHA ? LV_IMG_PX_SIZE_ALPHA_BYTE : sizeof(lv_color_t);
|
||||
if(flags & LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE) {
|
||||
layer_sw_ctx->buf_size_bytes = LV_LAYER_SIMPLE_BUF_SIZE;
|
||||
uint32_t full_size = lv_area_get_size(&layer_sw_ctx->base_draw.area_full) * px_size;
|
||||
if(layer_sw_ctx->buf_size_bytes > full_size) layer_sw_ctx->buf_size_bytes = full_size;
|
||||
layer_sw_ctx->base_draw.buf = lv_mem_alloc(layer_sw_ctx->buf_size_bytes);
|
||||
if(layer_sw_ctx->base_draw.buf == NULL) {
|
||||
LV_LOG_WARN("Cannot allocate %"LV_PRIu32" bytes for layer buffer. Allocating %"LV_PRIu32" bytes instead. (Reduced performance)",
|
||||
(uint32_t)layer_sw_ctx->buf_size_bytes, (uint32_t)LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE * px_size);
|
||||
layer_sw_ctx->buf_size_bytes = LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE;
|
||||
layer_sw_ctx->base_draw.buf = lv_mem_alloc(layer_sw_ctx->buf_size_bytes);
|
||||
if(layer_sw_ctx->base_draw.buf == NULL) {
|
||||
lv_mem_free(layer_ctx);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
layer_sw_ctx->base_draw.area_act = layer_sw_ctx->base_draw.area_full;
|
||||
layer_sw_ctx->base_draw.area_act.y2 = layer_sw_ctx->base_draw.area_full.y1;
|
||||
lv_coord_t w = lv_area_get_width(&layer_sw_ctx->base_draw.area_act);
|
||||
layer_sw_ctx->base_draw.max_row_with_alpha = layer_sw_ctx->buf_size_bytes / w / LV_IMG_PX_SIZE_ALPHA_BYTE;
|
||||
layer_sw_ctx->base_draw.max_row_with_no_alpha = layer_sw_ctx->buf_size_bytes / w / sizeof(lv_color_t);
|
||||
}
|
||||
else {
|
||||
layer_sw_ctx->base_draw.area_act = layer_sw_ctx->base_draw.area_full;
|
||||
layer_sw_ctx->buf_size_bytes = lv_area_get_size(&layer_sw_ctx->base_draw.area_full) * px_size;
|
||||
layer_sw_ctx->base_draw.buf = lv_mem_alloc(layer_sw_ctx->buf_size_bytes);
|
||||
lv_memset_00(layer_sw_ctx->base_draw.buf, layer_sw_ctx->buf_size_bytes);
|
||||
layer_sw_ctx->has_alpha = flags & LV_DRAW_LAYER_FLAG_HAS_ALPHA ? 1 : 0;
|
||||
if(layer_sw_ctx->base_draw.buf == NULL) {
|
||||
lv_mem_free(layer_ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
draw_ctx->buf = layer_sw_ctx->base_draw.buf;
|
||||
draw_ctx->buf_area = &layer_sw_ctx->base_draw.area_act;
|
||||
draw_ctx->clip_area = &layer_sw_ctx->base_draw.area_act;
|
||||
|
||||
lv_disp_t * disp_refr = _lv_refr_get_disp_refreshing();
|
||||
disp_refr->driver->screen_transp = flags & LV_DRAW_LAYER_FLAG_HAS_ALPHA ? 1 : 0;
|
||||
}
|
||||
|
||||
return layer_ctx;
|
||||
}
|
||||
|
||||
void lv_draw_sw_layer_adjust(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx,
|
||||
lv_draw_layer_flags_t flags)
|
||||
{
|
||||
|
||||
lv_draw_sw_layer_ctx_t * layer_sw_ctx = (lv_draw_sw_layer_ctx_t *) layer_ctx;
|
||||
lv_disp_t * disp_refr = _lv_refr_get_disp_refreshing();
|
||||
if(flags & LV_DRAW_LAYER_FLAG_HAS_ALPHA) {
|
||||
lv_memset_00(layer_ctx->buf, layer_sw_ctx->buf_size_bytes);
|
||||
layer_sw_ctx->has_alpha = 1;
|
||||
disp_refr->driver->screen_transp = 1;
|
||||
}
|
||||
else {
|
||||
layer_sw_ctx->has_alpha = 0;
|
||||
disp_refr->driver->screen_transp = 0;
|
||||
}
|
||||
|
||||
draw_ctx->buf = layer_ctx->buf;
|
||||
draw_ctx->buf_area = &layer_ctx->area_act;
|
||||
draw_ctx->clip_area = &layer_ctx->area_act;
|
||||
}
|
||||
|
||||
void lv_draw_sw_layer_blend(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx,
|
||||
const lv_draw_img_dsc_t * draw_dsc)
|
||||
{
|
||||
lv_draw_sw_layer_ctx_t * layer_sw_ctx = (lv_draw_sw_layer_ctx_t *) layer_ctx;
|
||||
|
||||
lv_img_dsc_t img;
|
||||
img.data = draw_ctx->buf;
|
||||
img.header.always_zero = 0;
|
||||
img.header.w = lv_area_get_width(draw_ctx->buf_area);
|
||||
img.header.h = lv_area_get_height(draw_ctx->buf_area);
|
||||
img.header.cf = layer_sw_ctx->has_alpha ? LV_IMG_CF_TRUE_COLOR_ALPHA : LV_IMG_CF_TRUE_COLOR;
|
||||
lv_img_cache_invalidate_src(&img);
|
||||
|
||||
/*Restore the original draw_ctx*/
|
||||
draw_ctx->buf = layer_ctx->original.buf;
|
||||
draw_ctx->buf_area = layer_ctx->original.buf_area;
|
||||
draw_ctx->clip_area = layer_ctx->original.clip_area;
|
||||
lv_disp_t * disp_refr = _lv_refr_get_disp_refreshing();
|
||||
disp_refr->driver->screen_transp = layer_ctx->original.screen_transp;
|
||||
|
||||
/*Blend the layer*/
|
||||
lv_draw_img(draw_ctx, draw_dsc, &layer_ctx->area_act, &img);
|
||||
lv_draw_wait_for_finish(draw_ctx);
|
||||
}
|
||||
|
||||
void lv_draw_sw_layer_destroy(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx)
|
||||
{
|
||||
LV_UNUSED(draw_ctx);
|
||||
|
||||
lv_mem_free(layer_ctx->buf);
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
@ -317,8 +317,6 @@
|
||||
* and blend it as an image with the given opacity.
|
||||
* Note that `bg_opa`, `text_opa` etc don't require buffering into layer)
|
||||
* The widget can be buffered in smaller chunks to avoid using large buffers.
|
||||
* `draw_area` (`lv_area_t` meaning the area to draw and `px_size` (size of a pixel in bytes)
|
||||
* can be used the set the buffer size adaptively.
|
||||
*
|
||||
* - LV_LAYER_SIMPLE_BUF_SIZE: [bytes] the optimal target buffer size. LVGL will try to allocate it
|
||||
* - LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE: [bytes] used if `LV_LAYER_SIMPLE_BUF_SIZE` couldn't be allocated.
|
||||
@ -338,7 +336,7 @@
|
||||
#ifdef CONFIG_LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE
|
||||
#define LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE CONFIG_LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE
|
||||
#else
|
||||
#define LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE LV_MAX(lv_area_get_width(&draw_area) * px_size, 2048)
|
||||
#define LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE (3 * 1024)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user