From: Jean-Philippe Andre Date: Tue, 10 Jan 2017 02:44:25 +0000 (+0900) Subject: evas: Drop unused buffer from textblock filters X-Git-Tag: upstream/1.20.0~2421 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3a98d0ea88cdc30c45a6b294cec3fca0aa1fcbb3;p=platform%2Fupstream%2Fefl.git evas: Drop unused buffer from textblock filters This is a first step before implementing some form of caching of those output buffers. At the moment, it very aggressively deletes any buffer that falls outside the clip of the textblock object. Note that this is better in terms of memory usage but way worse in terms of render performance (eg. scrolling). If a textblock is a proxy source then we keep all the buffers (the entire object is to be rendered). + fix a crash --- diff --git a/src/lib/evas/canvas/evas_object_textblock.c b/src/lib/evas/canvas/evas_object_textblock.c index 0d0e25b..fb80dae 100644 --- a/src/lib/evas/canvas/evas_object_textblock.c +++ b/src/lib/evas/canvas/evas_object_textblock.c @@ -140,6 +140,10 @@ static const char o_type[] = "textblock"; } \ while(0) +// testing out some macros to maybe add to eina +#define EINA_INLIST_REMOVE(l,i) do { l = (__typeof__(l)) eina_inlist_remove(EINA_INLIST_GET(l), EINA_INLIST_GET(i)); } while (0) +#define EINA_INLIST_APPEND(l,i) do { l = (__typeof__(l)) eina_inlist_append(EINA_INLIST_GET(l), EINA_INLIST_GET(i)); } while (0) + /* private struct for textblock object internal data */ /** * @internal @@ -459,6 +463,8 @@ struct _Evas_Object_Textblock_Format_Item struct _Text_Item_Filter { + EINA_INLIST; /**< list on the tb object */ + Efl_Canvas_Text_Data *textblock; Evas_Object_Textblock_Text_Item *ti; /**< associated text item. if null, it was deleted */ Evas_Filter_Context *ctx; /**< running context for the filter */ Evas_Public_Data *evas; /**< evas instance */ @@ -609,6 +615,7 @@ struct _Evas_Object_Textblock Efl_Canvas_Text_Filter_Program *programs; Evas_Filter_Data_Binding *data_bindings; Eina_Hash *sources; + Text_Item_Filter *text_items; // inlist } gfx_filter; Eina_Bool redraw : 1; Eina_Bool changed : 1; @@ -989,6 +996,8 @@ _item_free(const Evas_Object *eo_obj, Evas_Object_Textblock_Line *ln, Evas_Objec evas_common_text_props_content_unref(&ti->text_props); if (EINA_UNLIKELY(ti->gfx_filter != NULL)) { + Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS); + if (ti->gfx_filter->output) { Evas *eo_evas = evas_object_evas_get(eo_obj); @@ -998,6 +1007,7 @@ _item_free(const Evas_Object *eo_obj, Evas_Object_Textblock_Line *ln, Evas_Objec _image_safe_unref(evas, ti->gfx_filter->output, async); ti->gfx_filter->output = NULL; } + EINA_INLIST_REMOVE(o->gfx_filter.text_items, ti->gfx_filter); if (!ti->gfx_filter->ctx) free(ti->gfx_filter); else @@ -2761,6 +2771,15 @@ _format_dup(Evas_Object *eo_obj, const Evas_Object_Textblock_Format *fmt) /* FIXME: just ref the font here... */ fmt2->font.font = evas_font_load(obj->layer->evas->evas, fmt2->font.fdesc, fmt2->font.source, (int)(((double) fmt2->font.size) * obj->cur->scale)); + + if (fmt->gfx_filter) + { + fmt2->gfx_filter = malloc(sizeof(*fmt2->gfx_filter)); + memcpy(fmt2->gfx_filter, fmt->gfx_filter, sizeof(*fmt->gfx_filter)); + fmt2->gfx_filter->name = eina_stringshare_ref(fmt->gfx_filter->name); + fmt2->gfx_filter->dc = ENFN->context_dup(ENDT, fmt->gfx_filter->dc); + } + return fmt2; } @@ -12886,9 +12905,6 @@ _efl_canvas_text_efl_object_destructor(Eo *eo_obj, Efl_Canvas_Text_Data *o EINA_ efl_destructor(efl_super(eo_obj, MY_CLASS)); } -// testing this macro... -#define EINA_INLIST_REMOVE(l,i) do { l = (__typeof__(l)) eina_inlist_remove(EINA_INLIST_GET(l), EINA_INLIST_GET(i)); } while (0) - static void evas_object_textblock_free(Evas_Object *eo_obj) { @@ -12978,7 +12994,6 @@ _filter_sync_end(Evas_Filter_Context *ctx, Eina_Bool success) if (filter->ti->parent.format->gfx_filter) filter->ti->parent.format->gfx_filter->invalid = !success; // else just avoid sigsegv - filter->ti = NULL; filter->ctx = NULL; } else @@ -13015,6 +13030,66 @@ _filter_cb(Evas_Filter_Context *ctx, void *data, Eina_Bool success) evas_post_render_job_add(evas, _filter_post_render_cb, post_data); } +static Eina_Rectangle +_filter_relative_bounding_box_get(const Text_Item_Filter *tif) +{ + int x_offset, y_offset, l, r, t, b; + Eina_Rectangle rect; + + x_offset = tif->ti->parent.ln->x + tif->ti->parent.x; + y_offset = tif->ti->parent.ln->par->y + tif->ti->parent.ln->y; + l = tif->ti->parent.format->gfx_filter->pad.l; + r = tif->ti->parent.format->gfx_filter->pad.r; + t = tif->ti->parent.format->gfx_filter->pad.t; + b = tif->ti->parent.format->gfx_filter->pad.b; + + rect.x = x_offset - l; + rect.y = y_offset - t; + rect.w = tif->ti->parent.w; + rect.h = tif->ti->parent.h + t + b; + return rect; +} + +static void +_filter_output_cache_prune(Evas_Object_Protected_Data *obj, Efl_Canvas_Text_Data *o) +{ + Text_Item_Filter *tif; + Eina_Inlist *il; + Eina_Rectangle obj_rect; + + // proxy surfaces contain the entire object, nothing to prune + if (obj->proxy->proxies) + return; + + obj_rect.x = obj->cur->cache.clip.x; + obj_rect.y = obj->cur->cache.clip.y; + obj_rect.w = obj->cur->cache.clip.w; + obj_rect.h = obj->cur->cache.clip.h; + + EINA_INLIST_FOREACH_SAFE(o->gfx_filter.text_items, il, tif) + { + Eina_Rectangle it_rect; + + if (!tif->ti) + { + if (tif->ctx) continue; + } + else + { + if (!tif->ti->parent.ln || !tif->ti->parent.ln->par) continue; + + it_rect = _filter_relative_bounding_box_get(tif); + it_rect.x += obj->cur->geometry.x; + it_rect.y += obj->cur->geometry.y; + if (eina_rectangles_intersect(&obj_rect, &it_rect)) continue; + } + + _image_safe_unref(obj->layer->evas, tif->output, tif->do_async); + tif->output = NULL; + + } +} + static void evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj, @@ -13176,9 +13251,9 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED, #define DRAW_TEXT(ox, oy) do { \ if (ti->parent.format->font.font) \ { \ - if (EINA_LIKELY(!_filter_context_get(ti))) \ + if (EINA_LIKELY(!ti->gfx_filter || (!ti->gfx_filter->ctx && !ti->gfx_filter->output))) \ DRAW_TEXT_NOFILTER(ox, oy); \ - else if (!_filter_output_get(ti)) \ + else if (ti->gfx_filter->ctx != NULL) \ DRAW_TEXT_FILTER(ti->parent.format->gfx_filter, ox, oy); \ } } while(0) @@ -13350,6 +13425,7 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED, ti->gfx_filter = calloc(1, sizeof(*ti->gfx_filter)); ti->gfx_filter->evas = obj->layer->evas; ti->gfx_filter->ti = ti; + EINA_INLIST_APPEND(o->gfx_filter.text_items, ti->gfx_filter); } ctx = evas_filter_context_new(obj->layer->evas, do_async, ti->gfx_filter); evas_filter_state_prepare(eo_obj, &state, ti); @@ -13665,8 +13741,8 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED, X = obj->cur->geometry.x + ln->x + ti->parent.x + x - filter->pad.l; Y = obj->cur->geometry.y + ln->par->y + ln->y + y - filter->pad.t; + ca = cr = cb = cg = 255; ENFN->context_color_set(ENDT, context, 255, 255, 255, 255); - ENFN->context_multiplier_unset(ENDT, context); ENFN->image_size_get(ENDT, buffer, &W, &H); ENFN->image_draw(ENDT, context, surface, buffer, 0, 0, W, H, X, Y, W, H, 0, do_async); @@ -14089,7 +14165,7 @@ done: static void evas_object_textblock_render_post(Evas_Object *eo_obj, - Evas_Object_Protected_Data *obj EINA_UNUSED, + Evas_Object_Protected_Data *obj, void *type_private_data EINA_UNUSED) { /* Efl_Canvas_Text_Data *o; */ @@ -14103,6 +14179,7 @@ evas_object_textblock_render_post(Evas_Object *eo_obj, /* move cur to prev safely for object data */ evas_object_cur_prev(eo_obj); /* o->prev = o->cur; */ + _filter_output_cache_prune(obj, type_private_data); } static unsigned int evas_object_textblock_id_get(Evas_Object *eo_obj)