From ee95e7dc254f5ac249eb379fcce6a5cef4d0dc18 Mon Sep 17 00:00:00 2001 From: Mariotaku Date: Tue, 9 May 2023 00:02:49 +0900 Subject: [PATCH] fix(sdl): destroy texture after use if not stored in cache (#4173) --- src/draw/sdl/lv_draw_sdl_arc.c | 9 +++- src/draw/sdl/lv_draw_sdl_composite.c | 24 +++++++-- src/draw/sdl/lv_draw_sdl_composite.h | 13 ++++- src/draw/sdl/lv_draw_sdl_img.c | 58 +++++++++++++++----- src/draw/sdl/lv_draw_sdl_img.h | 16 +++++- src/draw/sdl/lv_draw_sdl_label.c | 17 +++++- src/draw/sdl/lv_draw_sdl_layer.c | 8 ++- src/draw/sdl/lv_draw_sdl_layer.h | 1 + src/draw/sdl/lv_draw_sdl_line.c | 4 +- src/draw/sdl/lv_draw_sdl_polygon.c | 8 ++- src/draw/sdl/lv_draw_sdl_priv.h | 1 + src/draw/sdl/lv_draw_sdl_rect.c | 68 ++++++++++++++++++++---- src/draw/sdl/lv_draw_sdl_rect.h | 30 +++++++++-- src/draw/sdl/lv_draw_sdl_texture_cache.c | 16 +++--- src/draw/sdl/lv_draw_sdl_texture_cache.h | 10 +++- 15 files changed, 232 insertions(+), 51 deletions(-) diff --git a/src/draw/sdl/lv_draw_sdl_arc.c b/src/draw/sdl/lv_draw_sdl_arc.c index 5786eaeb9..f43fef641 100644 --- a/src/draw/sdl/lv_draw_sdl_arc.c +++ b/src/draw/sdl/lv_draw_sdl_arc.c @@ -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); + } } /********************** diff --git a/src/draw/sdl/lv_draw_sdl_composite.c b/src/draw/sdl/lv_draw_sdl_composite.c index 4d0603d70..e155570d8 100644 --- a/src/draw/sdl/lv_draw_sdl_composite.c +++ b/src/draw/sdl/lv_draw_sdl_composite.c @@ -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; } diff --git a/src/draw/sdl/lv_draw_sdl_composite.h b/src/draw/sdl/lv_draw_sdl_composite.h index 72a2daef7..57191bbce 100644 --- a/src/draw/sdl/lv_draw_sdl_composite.h +++ b/src/draw/sdl/lv_draw_sdl_composite.h @@ -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 diff --git a/src/draw/sdl/lv_draw_sdl_img.c b/src/draw/sdl/lv_draw_sdl_img.c index 3c955d840..4dddc8c60 100644 --- a/src/draw/sdl/lv_draw_sdl_img.c +++ b/src/draw/sdl/lv_draw_sdl_img.c @@ -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; } diff --git a/src/draw/sdl/lv_draw_sdl_img.h b/src/draw/sdl/lv_draw_sdl_img.h index 0e2702772..6233913d8 100644 --- a/src/draw/sdl/lv_draw_sdl_img.h +++ b/src/draw/sdl/lv_draw_sdl_img.h @@ -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 **********************/ diff --git a/src/draw/sdl/lv_draw_sdl_label.c b/src/draw/sdl/lv_draw_sdl_label.c index b8c79ae4a..d043c510b 100644 --- a/src/draw/sdl/lv_draw_sdl_label.c +++ b/src/draw/sdl/lv_draw_sdl_label.c @@ -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); + } } /********************** diff --git a/src/draw/sdl/lv_draw_sdl_layer.c b/src/draw/sdl/lv_draw_sdl_layer.c index ae5c327ac..d517636d9 100644 --- a/src/draw/sdl/lv_draw_sdl_layer.c +++ b/src/draw/sdl/lv_draw_sdl_layer.c @@ -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; } diff --git a/src/draw/sdl/lv_draw_sdl_layer.h b/src/draw/sdl/lv_draw_sdl_layer.h index b60303c47..f6aa66867 100644 --- a/src/draw/sdl/lv_draw_sdl_layer.h +++ b/src/draw/sdl/lv_draw_sdl_layer.h @@ -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; /********************** diff --git a/src/draw/sdl/lv_draw_sdl_line.c b/src/draw/sdl/lv_draw_sdl_line.c index 3a15d6d33..204e1a3d8 100644 --- a/src/draw/sdl/lv_draw_sdl_line.c +++ b/src/draw/sdl/lv_draw_sdl_line.c @@ -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}; diff --git a/src/draw/sdl/lv_draw_sdl_polygon.c b/src/draw/sdl/lv_draw_sdl_polygon.c index c5df50cb9..68305c7c8 100644 --- a/src/draw/sdl/lv_draw_sdl_polygon.c +++ b/src/draw/sdl/lv_draw_sdl_polygon.c @@ -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); + } } /********************** diff --git a/src/draw/sdl/lv_draw_sdl_priv.h b/src/draw/sdl/lv_draw_sdl_priv.h index 24a876218..ffc191b0a 100644 --- a/src/draw/sdl/lv_draw_sdl_priv.h +++ b/src/draw/sdl/lv_draw_sdl_priv.h @@ -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; diff --git a/src/draw/sdl/lv_draw_sdl_rect.c b/src/draw/sdl/lv_draw_sdl_rect.c index 6418a0af6..149dcbf67 100644 --- a/src/draw/sdl/lv_draw_sdl_rect.c +++ b/src/draw/sdl/lv_draw_sdl_rect.c @@ -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, diff --git a/src/draw/sdl/lv_draw_sdl_rect.h b/src/draw/sdl/lv_draw_sdl_rect.h index 3472af31b..c3262d5f1 100644 --- a/src/draw/sdl/lv_draw_sdl_rect.h +++ b/src/draw/sdl/lv_draw_sdl_rect.h @@ -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); diff --git a/src/draw/sdl/lv_draw_sdl_texture_cache.c b/src/draw/sdl/lv_draw_sdl_texture_cache.c index 6845addf5..406741783 100644 --- a/src/draw/sdl/lv_draw_sdl_texture_cache.c +++ b/src/draw/sdl/lv_draw_sdl_texture_cache.c @@ -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) diff --git a/src/draw/sdl/lv_draw_sdl_texture_cache.h b/src/draw/sdl/lv_draw_sdl_texture_cache.h index 1bbf17cd8..3a799f58b 100644 --- a/src/draw/sdl/lv_draw_sdl_texture_cache.h +++ b/src/draw/sdl/lv_draw_sdl_texture_cache.h @@ -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);