1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-28 07:03:00 +08:00

fix(sdl): destroy texture after use if not stored in cache (#4173)

This commit is contained in:
Mariotaku 2023-05-09 00:02:49 +09:00 committed by GitHub
parent 45b13c378f
commit ee95e7dc25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 232 additions and 51 deletions

View File

@ -104,7 +104,9 @@ void lv_draw_sdl_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * ds
}
lv_coord_t w = lv_area_get_width(&draw_area), h = lv_area_get_height(&draw_area);
SDL_Texture * texture = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM1, w, h);
bool texture_cached = false;
SDL_Texture * texture = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM1, w, h,
&texture_cached);
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
dump_masks(texture, &draw_area, mask_ids, mask_ids_count, cap_ids[0] != LV_MASK_ID_INV ? cap_ids : NULL);
@ -135,6 +137,11 @@ void lv_draw_sdl_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * ds
SDL_SetTextureColorMod(texture, color.r, color.g, color.b);
SDL_SetTextureAlphaMod(texture, dsc->opa);
SDL_RenderCopy(ctx->renderer, texture, &srcrect, &dstrect);
if(!texture_cached) {
LV_LOG_WARN("Texture is not cached, this will impact performance.");
SDL_DestroyTexture(texture);
}
}
/**********************

View File

@ -86,7 +86,8 @@ bool lv_draw_sdl_composite_begin(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coor
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);
internals->composition = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET0, w, h,
&internals->composition_cached);
/* 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 */
@ -174,19 +175,23 @@ void lv_draw_sdl_composite_end(lv_draw_sdl_ctx_t * ctx, const lv_area_t * apply_
break;
}
SDL_RenderCopy(ctx->renderer, internals->composition, &src_rect, &dst_rect);
if(!internals->composition_cached) {
LV_LOG_WARN("Texture is not cached, this will impact performance.");
SDL_DestroyTexture(internals->composition);
}
}
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,
lv_coord_t w, lv_coord_t h)
lv_coord_t w, lv_coord_t h, bool * texture_in_cache)
{
lv_point_t * tex_size = NULL;
composite_key_t mask_key = mask_key_create(id);
SDL_Texture * result = lv_draw_sdl_texture_cache_get_with_userdata(ctx, &mask_key, sizeof(composite_key_t), NULL,
(void **) &tex_size);
if(!result || tex_size->x < w || tex_size->y < h) {
if(result == NULL || 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_TRANSFORM0) {
@ -198,8 +203,19 @@ SDL_Texture * lv_draw_sdl_composite_texture_obtain(lv_draw_sdl_ctx_t * ctx, lv_d
result = SDL_CreateTexture(ctx->renderer, LV_DRAW_SDL_TEXTURE_FORMAT, access, size, size);
tex_size = lv_mem_alloc(sizeof(lv_point_t));
tex_size->x = tex_size->y = size;
lv_draw_sdl_texture_cache_put_advanced(ctx, &mask_key, sizeof(composite_key_t), result, tex_size, lv_mem_free, 0);
bool in_cache = lv_draw_sdl_texture_cache_put_advanced(ctx, &mask_key, sizeof(composite_key_t), result,
tex_size, lv_mem_free, 0);
if(!in_cache) {
lv_mem_free(tex_size);
}
if(texture_in_cache != NULL) {
*texture_in_cache = in_cache;
}
}
else if(texture_in_cache != NULL) {
*texture_in_cache = true;
}
return result;
}

View File

@ -45,6 +45,7 @@ typedef enum lv_draw_sdl_composite_texture_id_t {
/**
* Begin drawing with mask. Render target will be switched to a temporary texture,
* and drawing coordinates may get clipped or translated
* @param ctx Drawing context
* @param coords_in Original coordinates
* @param clip_in Original clip area
* @param extension Useful for shadows or outlines, can be NULL
@ -59,8 +60,18 @@ bool lv_draw_sdl_composite_begin(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coor
void lv_draw_sdl_composite_end(lv_draw_sdl_ctx_t * ctx, const lv_area_t * apply_area, lv_blend_mode_t blend_mode);
/**
*
* @param ctx Drawing context
* @param id Texture ID
* @param w Maximum width needed
* @param h Maximum height needed
* @param texture_in_cache output to query if the texture is in cache. If it's not in cache, you'll need to destroy it
* by yourself
* @return Obtained texture
*/
SDL_Texture * lv_draw_sdl_composite_texture_obtain(lv_draw_sdl_ctx_t * ctx, lv_draw_sdl_composite_texture_id_t id,
lv_coord_t w, lv_coord_t h);
lv_coord_t w, lv_coord_t h, bool * texture_in_cache);
/**********************
* MACROS

View File

@ -72,7 +72,8 @@ static void draw_img_rounded(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture, con
lv_coord_t radius);
static SDL_Texture * img_rounded_frag_obtain(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture,
const lv_draw_sdl_img_header_t * header, int w, int h, lv_coord_t radius);
const lv_draw_sdl_img_header_t * header, int w, int h, lv_coord_t radius,
bool * in_cache);
static lv_draw_img_rounded_key_t rounded_key_create(const SDL_Texture * texture, lv_coord_t w, lv_coord_t h,
lv_coord_t radius);
@ -106,11 +107,16 @@ lv_res_t lv_draw_sdl_img_core(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t
lv_draw_sdl_img_header_t * header = NULL;
SDL_Texture * texture = lv_draw_sdl_texture_cache_get_with_userdata(ctx, key, key_size, &texture_found,
(void **) &header);
bool texture_in_cache = false;
if(!texture_found) {
lv_draw_sdl_img_load_texture(ctx, key, key_size, src, draw_dsc->frame_id, &texture, &header);
lv_draw_sdl_img_load_texture(ctx, key, key_size, src, draw_dsc->frame_id, &texture, &header,
&texture_in_cache);
}
else {
texture_in_cache = true;
}
SDL_free(key);
if(!texture) {
if(!texture || !header) {
return LV_RES_INV;
}
@ -148,6 +154,14 @@ lv_res_t lv_draw_sdl_img_core(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t
lv_draw_sdl_composite_end(ctx, &apply_area, draw_dsc->blend_mode);
if(!texture_in_cache) {
LV_LOG_WARN("Texture is not cached, this will impact performance.");
if(!header->managed) {
SDL_DestroyTexture(texture);
}
lv_mem_free(header);
}
return LV_RES_OK;
}
@ -185,7 +199,7 @@ static void calc_draw_part(SDL_Texture * texture, const lv_draw_sdl_img_header_t
bool lv_draw_sdl_img_load_texture(lv_draw_sdl_ctx_t * ctx, lv_draw_sdl_cache_key_head_img_t * key, size_t key_size,
const void * src, int32_t frame_id, SDL_Texture ** texture,
lv_draw_sdl_img_header_t ** header)
lv_draw_sdl_img_header_t ** header, bool * texture_in_cache)
{
_lv_img_cache_entry_t * cdsc = _lv_img_cache_open(src, lv_color_white(), frame_id);
lv_draw_sdl_cache_flag_t tex_flags = 0;
@ -210,16 +224,18 @@ bool lv_draw_sdl_img_load_texture(lv_draw_sdl_ctx_t * ctx, lv_draw_sdl_cache_key
#endif
}
if(texture && cdsc) {
*header = SDL_malloc(sizeof(lv_draw_sdl_img_header_t));
*header = lv_mem_alloc(sizeof(lv_draw_sdl_img_header_t));
SDL_memcpy(&(*header)->base, &cdsc->dec_dsc.header, sizeof(lv_img_header_t));
(*header)->rect = rect;
lv_draw_sdl_texture_cache_put_advanced(ctx, key, key_size, *texture, *header, SDL_free, tex_flags);
(*header)->managed = (tex_flags & LV_DRAW_SDL_CACHE_FLAG_MANAGED) != 0;
*texture_in_cache = lv_draw_sdl_texture_cache_put_advanced(ctx, key, key_size, *texture, *header, SDL_free,
tex_flags);
return true;
}
else {
lv_draw_sdl_texture_cache_put(ctx, key, key_size, NULL);
*texture_in_cache = lv_draw_sdl_texture_cache_put(ctx, key, key_size, NULL);
return false;
}
return true;
}
/**********************
@ -320,7 +336,8 @@ static void draw_img_rounded(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture, con
{
const int w = lv_area_get_width(coords), h = lv_area_get_height(coords);
lv_coord_t real_radius = LV_MIN3(radius, w, h);
SDL_Texture * frag = img_rounded_frag_obtain(ctx, texture, header, w, h, real_radius);
bool frag_in_cache = false;
SDL_Texture * frag = img_rounded_frag_obtain(ctx, texture, header, w, h, real_radius, &frag_in_cache);
apply_recolor_opa(frag, draw_dsc);
lv_draw_sdl_rect_bg_frag_draw_corners(ctx, frag, real_radius, coords, clip, true);
@ -360,6 +377,11 @@ static void draw_img_rounded(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture, con
SDL_RenderCopy(ctx->renderer, texture, &src_rect, &dst_rect);
}
SDL_RenderSetClipRect(ctx->renderer, NULL);
if(!frag_in_cache) {
LV_LOG_WARN("Texture is not cached, this will impact performance.");
SDL_DestroyTexture(frag);
}
}
static void apply_recolor_opa(SDL_Texture * texture, const lv_draw_img_dsc_t * draw_dsc)
@ -377,15 +399,18 @@ static void apply_recolor_opa(SDL_Texture * texture, const lv_draw_img_dsc_t * d
}
static SDL_Texture * img_rounded_frag_obtain(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture,
const lv_draw_sdl_img_header_t * header, int w, int h, lv_coord_t radius)
const lv_draw_sdl_img_header_t * header, int w, int h, lv_coord_t radius,
bool * in_cache)
{
lv_draw_img_rounded_key_t key = rounded_key_create(texture, w, h, radius);
SDL_Texture * mask_frag = lv_draw_sdl_rect_bg_frag_obtain(ctx, radius);
bool mask_frag_in_cache = false;
SDL_Texture * mask_frag = lv_draw_sdl_rect_bg_frag_obtain(ctx, radius, &mask_frag_in_cache);
SDL_Texture * img_frag = lv_draw_sdl_texture_cache_get(ctx, &key, sizeof(key), NULL);
if(img_frag == NULL) {
const lv_coord_t full_frag_size = radius * 2 + 3;
img_frag = SDL_CreateTexture(ctx->renderer, LV_DRAW_SDL_TEXTURE_FORMAT, SDL_TEXTUREACCESS_TARGET,
full_frag_size, full_frag_size);
SDL_assert(img_frag);
SDL_SetTextureBlendMode(img_frag, SDL_BLENDMODE_BLEND);
SDL_Texture * old_target = SDL_GetRenderTarget(ctx->renderer);
SDL_SetRenderTarget(ctx->renderer, img_frag);
@ -395,7 +420,7 @@ static SDL_Texture * img_rounded_frag_obtain(lv_draw_sdl_ctx_t * ctx, SDL_Textur
SDL_RenderFillRect(ctx->renderer, NULL);
SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_BLEND);
lv_area_t coords = {0, 0, w - 1, h - 1}, clip;
lv_area_t coords = {0, 0, w - 1, h - 1};
lv_area_t frag_coords = {0, 0, full_frag_size - 1, full_frag_size - 1};
lv_draw_sdl_rect_bg_frag_draw_corners(ctx, mask_frag, radius, &frag_coords, NULL, false);
@ -446,7 +471,14 @@ static SDL_Texture * img_rounded_frag_obtain(lv_draw_sdl_ctx_t * ctx, SDL_Textur
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
SDL_SetRenderTarget(ctx->renderer, old_target);
lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), img_frag);
*in_cache = lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), img_frag);
}
else {
*in_cache = true;
}
if(!mask_frag_in_cache) {
LV_LOG_WARN("Texture is not cached, this will impact performance.");
SDL_DestroyTexture(mask_frag);
}
return img_frag;
}

View File

@ -35,6 +35,7 @@ extern "C" {
typedef struct lv_draw_sdl_img_header_t {
lv_img_header_t base;
SDL_Rect rect;
bool managed;
} lv_draw_sdl_img_header_t;
/**********************
@ -56,9 +57,22 @@ typedef struct lv_draw_sdl_img_header_t {
/*=====================
* Other functions
*====================*/
/**
*
* @param ctx Drawing context
* @param key Texture cache key
* @param key_size Size of texture cache key
* @param src Image source pointer
* @param frame_id Frame ID for animated image
* @param texture Texture for render
* @param header Header also holds sdl image info
* @param texture_in_cache Whether the texture has been put in the cache. Please note for managed texture,
* this will be false too. So you'll need to check header.managed too.
* @return Whether the image has been loaded successfully
*/
bool lv_draw_sdl_img_load_texture(lv_draw_sdl_ctx_t * ctx, lv_draw_sdl_cache_key_head_img_t * key, size_t key_size,
const void * src, int32_t frame_id, SDL_Texture ** texture,
lv_draw_sdl_img_header_t ** header);
lv_draw_sdl_img_header_t ** header, bool * texture_in_cache);
/**********************
* MACROS
**********************/

View File

@ -54,7 +54,7 @@ static lv_font_glyph_key_t font_key_glyph_create(const lv_font_t * font_p, uint3
* GLOBAL FUNCTIONS
**********************/
void lv_draw_sdl_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p,
void lv_draw_sdl_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p,
uint32_t letter)
{
const lv_area_t * clip_area = draw_ctx->clip_area;
@ -117,6 +117,7 @@ void lv_draw_sdl_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t
lv_font_glyph_key_t glyph_key = font_key_glyph_create(font_p, letter);
bool glyph_found = false;
SDL_Texture * texture = lv_draw_sdl_texture_cache_get(ctx, &glyph_key, sizeof(glyph_key), &glyph_found);
bool in_cache = false;
if(!glyph_found) {
if(g.resolved_font) {
font_p = g.resolved_font;
@ -128,7 +129,10 @@ void lv_draw_sdl_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t
texture = SDL_CreateTextureFromSurface(renderer, mask);
SDL_FreeSurface(mask);
lv_mem_free(buf);
lv_draw_sdl_texture_cache_put(ctx, &glyph_key, sizeof(glyph_key), texture);
in_cache = lv_draw_sdl_texture_cache_put(ctx, &glyph_key, sizeof(glyph_key), texture);
}
else {
in_cache = true;
}
if(!texture) {
return;
@ -142,6 +146,10 @@ void lv_draw_sdl_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t
/*If the letter is completely out of mask don't draw it*/
if(!_lv_area_intersect(&draw_area, &t_letter, &t_clip)) {
if(!in_cache) {
LV_LOG_WARN("Texture is not cached, this will impact performance.");
SDL_DestroyTexture(texture);
}
return;
}
SDL_Rect srcrect, dstrect;
@ -156,6 +164,11 @@ void lv_draw_sdl_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t
SDL_RenderCopy(renderer, texture, &srcrect, &dstrect);
lv_draw_sdl_composite_end(ctx, &apply_area, dsc->blend_mode);
if(!in_cache) {
LV_LOG_WARN("Texture is not cached, this will impact performance.");
SDL_DestroyTexture(texture);
}
}
/**********************

View File

@ -58,7 +58,8 @@ lv_draw_layer_ctx_t * lv_draw_sdl_layer_init(lv_draw_ctx_t * draw_ctx, lv_draw_l
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 = lv_draw_sdl_composite_texture_obtain(ctx, texture_id, target_w, target_h,
&transform_ctx->target_in_cache);
transform_ctx->target_rect.x = 0;
transform_ctx->target_rect.y = 0;
transform_ctx->target_rect.w = target_w;
@ -117,6 +118,11 @@ void lv_draw_sdl_layer_blend(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * lay
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;
lv_draw_sdl_layer_ctx_t * transform_ctx = (lv_draw_sdl_layer_ctx_t *) layer_ctx;
if(!transform_ctx->target_in_cache && transform_ctx->target != NULL) {
LV_LOG_WARN("Texture is not cached, this will impact performance.");
SDL_DestroyTexture(transform_ctx->target);
}
ctx->internals->transform_count -= 1;
}

View File

@ -28,6 +28,7 @@ typedef struct _lv_draw_sdl_layer_ctx_t {
SDL_Texture * orig_target;
SDL_Texture * target;
SDL_Rect target_rect;
bool target_in_cache;
lv_draw_layer_flags_t flags;
} lv_draw_sdl_layer_ctx_t;
/**********************

View File

@ -53,7 +53,7 @@ static SDL_Texture * line_texture_create(lv_draw_sdl_ctx_t * sdl_ctx, const lv_d
* GLOBAL FUNCTIONS
**********************/
void lv_draw_sdl_draw_line(lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, const lv_point_t * point1,
const lv_point_t * point2)
const lv_point_t * point2, bool * in_cache)
{
lv_draw_sdl_ctx_t * sdl_ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
SDL_Renderer * renderer = sdl_ctx->renderer;
@ -68,7 +68,7 @@ void lv_draw_sdl_draw_line(lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t *
SDL_Texture * texture = lv_draw_sdl_texture_cache_get(sdl_ctx, &key, sizeof(key), NULL);
if(!texture) {
texture = line_texture_create(sdl_ctx, dsc, (lv_coord_t) length);
lv_draw_sdl_texture_cache_put(sdl_ctx, &key, sizeof(key), texture);
*in_cache = lv_draw_sdl_texture_cache_put(sdl_ctx, &key, sizeof(key), texture);
}
lv_area_t coords = {x1, y1, x2, y2};

View File

@ -77,7 +77,9 @@ void lv_draw_sdl_polygon(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dr
int16_t mask_id = lv_draw_mask_add(&polygon_param, NULL);
lv_coord_t w = lv_area_get_width(&draw_area), h = lv_area_get_height(&draw_area);
SDL_Texture * texture = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM1, w, h);
bool texture_in_cache = false;
SDL_Texture * texture = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM1, w, h,
&texture_in_cache);
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
dump_masks(texture, &draw_area);
@ -91,6 +93,10 @@ void lv_draw_sdl_polygon(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dr
SDL_SetTextureColorMod(texture, color.r, color.g, color.b);
SDL_SetTextureAlphaMod(texture, draw_dsc->bg_opa);
SDL_RenderCopy(ctx->renderer, texture, &srcrect, &dstrect);
if(!texture_in_cache) {
LV_LOG_WARN("Texture is not cached, this will impact performance.");
SDL_DestroyTexture(texture);
}
}
/**********************

View File

@ -35,6 +35,7 @@ typedef struct lv_draw_sdl_context_internals_t {
lv_lru_t * texture_cache;
SDL_Texture * mask;
SDL_Texture * composition;
bool composition_cached;
SDL_Texture * target_backup;
uint8_t transform_count;
} lv_draw_sdl_context_internals_t;

View File

@ -175,7 +175,7 @@ void lv_draw_sdl_draw_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t *
lv_draw_sdl_composite_end(ctx, &apply_area, dsc->blend_mode);
}
SDL_Texture * lv_draw_sdl_rect_bg_frag_obtain(lv_draw_sdl_ctx_t * ctx, lv_coord_t radius)
SDL_Texture * lv_draw_sdl_rect_bg_frag_obtain(lv_draw_sdl_ctx_t * ctx, lv_coord_t radius, bool * in_cache)
{
lv_draw_rect_bg_key_t key = rect_bg_key_create(radius, radius);
SDL_Texture * texture = lv_draw_sdl_texture_cache_get(ctx, &key, sizeof(key), NULL);
@ -188,13 +188,16 @@ SDL_Texture * lv_draw_sdl_rect_bg_frag_obtain(lv_draw_sdl_ctx_t * ctx, lv_coord_
texture = lv_draw_sdl_mask_dump_texture(ctx->renderer, &coords_frag, &mask_id, 1);
SDL_assert(texture != NULL);
lv_draw_mask_remove_id(mask_id);
lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), texture);
*in_cache = lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), texture);
}
else {
*in_cache = true;
}
return texture;
}
SDL_Texture * lv_draw_sdl_rect_grad_frag_obtain(lv_draw_sdl_ctx_t * ctx, const lv_grad_dsc_t * grad, lv_coord_t w,
lv_coord_t h, lv_coord_t radius)
lv_coord_t h, lv_coord_t radius, bool * in_cache)
{
lv_draw_rect_grad_frag_key_t key = rect_grad_frag_key_create(grad, w, h, radius);
SDL_Texture * texture = lv_draw_sdl_texture_cache_get(ctx, &key, sizeof(key), NULL);
@ -240,12 +243,15 @@ SDL_Texture * lv_draw_sdl_rect_grad_frag_obtain(lv_draw_sdl_ctx_t * ctx, const l
draw_bg_grad_simple(ctx, &blend_coords, &draw_area, grad, true);
SDL_SetRenderTarget(ctx->renderer, target_backup);
lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), texture);
*in_cache = lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), texture);
}
else {
*in_cache = true;
}
return texture;
}
SDL_Texture * lv_draw_sdl_rect_grad_strip_obtain(lv_draw_sdl_ctx_t * ctx, const lv_grad_dsc_t * grad)
SDL_Texture * lv_draw_sdl_rect_grad_strip_obtain(lv_draw_sdl_ctx_t * ctx, const lv_grad_dsc_t * grad, bool * in_cache)
{
lv_draw_rect_grad_strip_key_t key = rect_grad_strip_key_create(grad);
SDL_Texture * texture = lv_draw_sdl_texture_cache_get(ctx, &key, sizeof(key), NULL);
@ -265,7 +271,10 @@ SDL_Texture * lv_draw_sdl_rect_grad_strip_obtain(lv_draw_sdl_ctx_t * ctx, const
texture = SDL_CreateTextureFromSurface(ctx->renderer, surface);
SDL_assert(texture != NULL);
SDL_FreeSurface(surface);
lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), texture);
*in_cache = lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), texture);
}
else {
*in_cache = true;
}
return texture;
}
@ -388,7 +397,8 @@ static void draw_bg_color(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, con
/*A small texture with a quarter of the rect is enough*/
lv_coord_t bg_w = lv_area_get_width(coords), bg_h = lv_area_get_height(coords);
lv_coord_t real_radius = LV_MIN3(bg_w / 2, bg_h / 2, radius);
SDL_Texture * texture = lv_draw_sdl_rect_bg_frag_obtain(ctx, real_radius);
bool texture_in_cache = false;
SDL_Texture * texture = lv_draw_sdl_rect_bg_frag_obtain(ctx, real_radius, &texture_in_cache);
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
SDL_SetTextureAlphaMod(texture, dsc->bg_opa);
@ -396,6 +406,11 @@ static void draw_bg_color(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, con
lv_draw_sdl_rect_bg_frag_draw_corners(ctx, texture, real_radius, coords, draw_area, false);
frag_render_borders(ctx->renderer, texture, real_radius, coords, draw_area, false);
frag_render_center(ctx->renderer, texture, real_radius, coords, draw_area, false);
if(!texture_in_cache) {
LV_LOG_WARN("Texture is not cached, this will impact performance.");
SDL_DestroyTexture(texture);
}
}
static void draw_bg_grad_simple(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area,
@ -427,7 +442,8 @@ static void draw_bg_grad_simple(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coord
}
}
SDL_Texture * grad_texture = lv_draw_sdl_rect_grad_strip_obtain(ctx, grad);
bool grad_texture_in_cache = false;
SDL_Texture * grad_texture = lv_draw_sdl_rect_grad_strip_obtain(ctx, grad, &grad_texture_in_cache);
if(blend_mod) {
SDL_SetTextureBlendMode(grad_texture, SDL_BLENDMODE_MOD);
}
@ -436,6 +452,11 @@ static void draw_bg_grad_simple(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coord
}
SDL_RenderCopy(ctx->renderer, grad_texture, &srcrect, &dstrect);
if(!grad_texture_in_cache) {
LV_LOG_WARN("Texture is not cached, this will impact performance.");
SDL_DestroyTexture(grad_texture);
}
}
static void draw_bg_grad_radius(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area,
@ -445,7 +466,9 @@ static void draw_bg_grad_radius(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coord
/*A small texture with a quarter of the rect is enough*/
lv_coord_t bg_w = lv_area_get_width(coords), bg_h = lv_area_get_height(coords);
lv_coord_t real_radius = LV_MIN3(bg_w / 2, bg_h / 2, radius);
SDL_Texture * grad_texture = lv_draw_sdl_rect_grad_frag_obtain(ctx, &dsc->bg_grad, bg_w, bg_h, radius);
bool grad_texture_in_cache = false;
SDL_Texture * grad_texture = lv_draw_sdl_rect_grad_frag_obtain(ctx, &dsc->bg_grad, bg_w, bg_h, radius,
&grad_texture_in_cache);
SDL_SetTextureBlendMode(grad_texture, SDL_BLENDMODE_BLEND);
lv_draw_sdl_rect_bg_frag_draw_corners(ctx, grad_texture, real_radius, coords, draw_area, true);
@ -497,6 +520,11 @@ static void draw_bg_grad_radius(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coord
_lv_area_intersect(&part_area, &part_coords, draw_area);
draw_bg_grad_simple(ctx, coords, &part_area, &dsc->bg_grad, false);
}
if(!grad_texture_in_cache) {
LV_LOG_WARN("Texture is not cached, this will impact performance.");
SDL_DestroyTexture(grad_texture);
}
}
static void draw_bg_img(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area,
@ -632,6 +660,7 @@ static void draw_shadow(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const
lv_draw_rect_shadow_key_t key = rect_shadow_key_create(radius, frag_size, sw);
SDL_Texture * texture = lv_draw_sdl_texture_cache_get(ctx, &key, sizeof(key), NULL);
bool texture_in_cache = false;
if(texture == NULL) {
lv_area_t mask_area = {blur_growth, blur_growth}, mask_area_blurred = {0, 0};
lv_area_set_width(&mask_area, frag_size * 2);
@ -650,7 +679,10 @@ static void draw_shadow(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const
lv_mem_buf_release(mask_buf);
lv_draw_mask_remove_id(mask_id);
SDL_assert(texture);
lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), texture);
texture_in_cache = lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), texture);
}
else {
texture_in_cache = true;
}
SDL_Color shadow_color;
@ -662,6 +694,11 @@ static void draw_shadow(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const
lv_draw_sdl_rect_bg_frag_draw_corners(ctx, texture, blur_frag_size, &shadow_area, clip, false);
frag_render_borders(ctx->renderer, texture, blur_frag_size, &shadow_area, clip, false);
frag_render_center(ctx->renderer, texture, blur_frag_size, &shadow_area, clip, false);
if(!texture_in_cache) {
LV_LOG_WARN("Texture is not cached, this will impact performance.");
SDL_DestroyTexture(texture);
}
}
@ -743,6 +780,7 @@ static void draw_border_generic(lv_draw_sdl_ctx_t * ctx, const lv_area_t * outer
lv_coord_t max_side = LV_MAX4(key.offsets.x1, key.offsets.y1, -key.offsets.x2, -key.offsets.y2);
lv_coord_t frag_size = LV_MAX(radius, max_side);
SDL_Texture * texture = lv_draw_sdl_texture_cache_get(ctx, &key, sizeof(key), NULL);
bool texture_in_cache;
if(texture == NULL) {
/* Create a mask texture with size of (frag_size * 2 + FRAG_SPACING) */
const lv_area_t frag_area = {0, 0, frag_size * 2 + FRAG_SPACING - 1, frag_size * 2 + FRAG_SPACING - 1};
@ -769,7 +807,10 @@ static void draw_border_generic(lv_draw_sdl_ctx_t * ctx, const lv_area_t * outer
lv_draw_mask_remove_id(mask_ids[1]);
lv_draw_mask_remove_id(mask_ids[0]);
SDL_assert(texture);
lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), texture);
texture_in_cache = lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), texture);
}
else {
texture_in_cache = true;
}
SDL_Rect outer_rect;
@ -783,6 +824,11 @@ static void draw_border_generic(lv_draw_sdl_ctx_t * ctx, const lv_area_t * outer
lv_draw_sdl_rect_bg_frag_draw_corners(ctx, texture, frag_size, outer_area, clip, true);
frag_render_borders(renderer, texture, frag_size, outer_area, clip, true);
if(!texture_in_cache) {
LV_LOG_WARN("Texture is not cached, this will impact performance.");
SDL_DestroyTexture(texture);
}
}
static void frag_render_borders(SDL_Renderer * renderer, SDL_Texture * frag, lv_coord_t frag_size,

View File

@ -57,12 +57,36 @@ typedef struct lv_draw_sdl_rect_header_t {
* Other functions
*====================*/
SDL_Texture * lv_draw_sdl_rect_bg_frag_obtain(lv_draw_sdl_ctx_t * ctx, lv_coord_t radius);
/**
*
* @param ctx Drawing context
* @param radius Corner radius of the rectangle
* @param in_cache Whether the texture has been put in the cache
* @return Background fragment texture
*/
SDL_Texture * lv_draw_sdl_rect_bg_frag_obtain(lv_draw_sdl_ctx_t * ctx, lv_coord_t radius, bool * in_cache);
/**
*
* @param ctx Drawing context
* @param grad Gradient info
* @param w Width of the rectangle
* @param h Height of the rectangle
* @param radius Corner radius of the rectangle
* @param in_cache Whether the texture has been put in the cache
* @return Gradient fragment texture
*/
SDL_Texture * lv_draw_sdl_rect_grad_frag_obtain(lv_draw_sdl_ctx_t * ctx, const lv_grad_dsc_t * grad, lv_coord_t w,
lv_coord_t h, lv_coord_t radius);
lv_coord_t h, lv_coord_t radius, bool * in_cache);
SDL_Texture * lv_draw_sdl_rect_grad_strip_obtain(lv_draw_sdl_ctx_t * ctx, const lv_grad_dsc_t * grad);
/**
*
* @param ctx Drawing context
* @param grad Gradient info
* @param in_cache Whether the texture has been put in the cache
* @return Gradient strip texture
*/
SDL_Texture * lv_draw_sdl_rect_grad_strip_obtain(lv_draw_sdl_ctx_t * ctx, const lv_grad_dsc_t * grad, bool * in_cache);
void lv_draw_sdl_rect_bg_frag_draw_corners(lv_draw_sdl_ctx_t * ctx, SDL_Texture * frag, lv_coord_t frag_size,
const lv_area_t * coords, const lv_area_t * clip, bool full);

View File

@ -81,12 +81,12 @@ SDL_Texture * lv_draw_sdl_texture_cache_get_with_userdata(lv_draw_sdl_ctx_t * ct
return value->texture;
}
void lv_draw_sdl_texture_cache_put(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, SDL_Texture * texture)
bool lv_draw_sdl_texture_cache_put(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, SDL_Texture * texture)
{
lv_draw_sdl_texture_cache_put_advanced(ctx, key, key_length, texture, NULL, NULL, 0);
return lv_draw_sdl_texture_cache_put_advanced(ctx, key, key_length, texture, NULL, NULL, 0);
}
void lv_draw_sdl_texture_cache_put_advanced(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length,
bool lv_draw_sdl_texture_cache_put_advanced(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length,
SDL_Texture * texture, void * userdata, void userdata_free(void *),
lv_draw_sdl_cache_flag_t flags)
{
@ -97,22 +97,20 @@ void lv_draw_sdl_texture_cache_put_advanced(lv_draw_sdl_ctx_t * ctx, const void
value->userdata_free = userdata_free;
value->flags = flags;
if(!texture) {
lv_lru_set(lru, key, key_length, value, 1);
return;
return lv_lru_set(lru, key, key_length, value, 1) == LV_LRU_OK;
}
if(flags & LV_DRAW_SDL_CACHE_FLAG_MANAGED) {
/* Managed texture doesn't count into cache size */
LV_LOG_INFO("cache texture %p", texture);
lv_lru_set(lru, key, key_length, value, 1);
return;
return lv_lru_set(lru, key, key_length, value, 1) == LV_LRU_OK;
}
Uint32 format;
int access, width, height;
if(SDL_QueryTexture(texture, &format, &access, &width, &height) != 0) {
return;
return false;
}
LV_LOG_INFO("cache texture %p, %d*%d@%dbpp", texture, width, height, SDL_BITSPERPIXEL(format));
lv_lru_set(lru, key, key_length, value, width * height * SDL_BITSPERPIXEL(format) / 8);
return lv_lru_set(lru, key, key_length, value, width * height * SDL_BITSPERPIXEL(format) / 8) == LV_LRU_OK;
}
lv_draw_sdl_cache_key_head_img_t * lv_draw_sdl_texture_img_key_create(const void * src, int32_t frame_id, size_t * size)

View File

@ -82,9 +82,15 @@ SDL_Texture * lv_draw_sdl_texture_cache_get(lv_draw_sdl_ctx_t * ctx, const void
SDL_Texture * lv_draw_sdl_texture_cache_get_with_userdata(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length,
bool * found, void ** userdata);
void lv_draw_sdl_texture_cache_put(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, SDL_Texture * texture);
/**
* @return Whether the texture has been put in the cache
*/
bool lv_draw_sdl_texture_cache_put(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, SDL_Texture * texture);
void lv_draw_sdl_texture_cache_put_advanced(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length,
/**
* @return Whether the texture has been put in the cache
*/
bool lv_draw_sdl_texture_cache_put_advanced(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length,
SDL_Texture * texture, void * userdata, void userdata_free(void *),
lv_draw_sdl_cache_flag_t flags);