From 945f5078abd925ec137c7ccdf016e7200d684241 Mon Sep 17 00:00:00 2001 From: Subhransu Mohanty Date: Fri, 5 Aug 2016 13:45:11 +0900 Subject: [PATCH] svg: backported from opensource Change-Id: Ice88f75c1461f3febb6eb1f67be27cf02f6db49d --- src/bin/edje/edje_cc_handlers.c | 11 ++- src/bin/edje/edje_svg_loader.c | 12 +++- src/lib/edje/edje_calc.c | 12 +--- src/lib/edje/edje_edit.c | 2 + src/lib/edje/edje_load.c | 5 +- src/lib/efl/interfaces/efl_gfx_shape.c | 26 +++---- src/lib/evas/canvas/evas_object_vg.c | 25 +++++-- src/lib/evas/include/evas_private.h | 16 +++-- src/lib/evas/vg/evas_vg_cache.c | 16 ++--- src/lib/evas/vg/evas_vg_common.h | 1 + src/lib/evas/vg/evas_vg_eet_handler.c | 82 +++++++++++++++------- src/modules/evas/engines/gl_generic/evas_engine.c | 65 +++++++++++------ .../evas/engines/software_generic/evas_engine.c | 72 +++++++++++++------ 13 files changed, 231 insertions(+), 114 deletions(-) diff --git a/src/bin/edje/edje_cc_handlers.c b/src/bin/edje/edje_cc_handlers.c index e5cb7eb..ade4c08 100644 --- a/src/bin/edje/edje_cc_handlers.c +++ b/src/bin/edje/edje_cc_handlers.c @@ -1970,6 +1970,10 @@ _handle_vector_image(void) break; } } + + if (ed->vg.id < 0) + error_and_abort(NULL, "Failed to find the vector resource :%s", name); + free(name); } @@ -2035,7 +2039,7 @@ st_images_vector(void) vector = edje_file->image_dir->vectors + edje_file->image_dir->vectors_count - 1; vector->entry = tmp; - vector->id = edje_file->image_dir->vectors_count; + vector->id = edje_file->image_dir->vectors_count - 1; } /** @@ -7433,7 +7437,10 @@ st_collections_group_parts_part_description_inherit(void) } case EDJE_PART_TYPE_VECTOR: { - // TODO + Edje_Part_Description_Vector *ied = (Edje_Part_Description_Vector *) ed; + Edje_Part_Description_Vector *iparent = (Edje_Part_Description_Vector *) parent; + ied->vg.set = iparent->vg.set; + ied->vg.id = iparent->vg.id; break; } } diff --git a/src/bin/edje/edje_svg_loader.c b/src/bin/edje/edje_svg_loader.c index a6377f6..3e24e2a 100644 --- a/src/bin/edje/edje_svg_loader.c +++ b/src/bin/edje/edje_svg_loader.c @@ -1135,7 +1135,13 @@ static Eina_Bool _attr_parse_polygon_node(void *data, const char *key, const char *value) { Svg_Node *node = data; - Svg_Polygon_Node *polygon = &(node->node.polygon); + Svg_Polygon_Node *polygon = NULL; + + if (node->type == SVG_NODE_POLYGON) + polygon = &(node->node.polygon); + else + polygon = &(node->node.polyline); + if (!strcmp(key, "points")) { @@ -1369,6 +1375,10 @@ _copy_attribute(Svg_Node *to, Svg_Node *from) to->node.polygon.points_count = from->node.polygon.points_count; to->node.polygon.points = calloc(to->node.polygon.points_count, sizeof(double)); break; + case SVG_NODE_POLYLINE: + to->node.polyline.points_count = from->node.polyline.points_count; + to->node.polyline.points = calloc(to->node.polyline.points_count, sizeof(double)); + break; default: break; } diff --git a/src/lib/edje/edje_calc.c b/src/lib/edje/edje_calc.c index 9737002..3f60e49 100644 --- a/src/lib/edje/edje_calc.c +++ b/src/lib/edje/edje_calc.c @@ -3214,7 +3214,7 @@ _edje_image_recalc_apply(Edje *ed, Edje_Real_Part *ep, Edje_Calc_Params *p3, Edj static void _edje_svg_recalc_apply(Edje *ed, Edje_Real_Part *ep, Edje_Calc_Params *p3 EINA_UNUSED, Edje_Part_Description_Vector *chosen_desc, FLOAT_T pos) { - int new_svg = 0; + int new_svg = -1; //invalid svg int w, h; evas_object_geometry_get(ep->object, NULL, NULL, &w, &h); @@ -3224,15 +3224,9 @@ _edje_svg_recalc_apply(Edje *ed, Edje_Real_Part *ep, Edje_Calc_Params *p3 EINA_U { Edje_Part_Description_Vector *next_state = (Edje_Part_Description_Vector *)ep->param2->description; if (chosen_desc->vg.id != next_state->vg.id) - { - new_svg = next_state->vg.id; - } + new_svg = next_state->vg.id; else - { - new_svg = 0; - pos = 0; - } - + pos = 0; } evas_object_vg_path_set(ep->object, ed->file->path, chosen_desc->vg.id, new_svg, pos); } diff --git a/src/lib/edje/edje_edit.c b/src/lib/edje/edje_edit.c index a5e9e60..475e9f0 100644 --- a/src/lib/edje/edje_edit.c +++ b/src/lib/edje/edje_edit.c @@ -3128,6 +3128,8 @@ _edje_edit_real_part_add(Evas_Object *obj, const char *name, Edje_Part_Type type { rp->type = EDJE_PART_TYPE_VECTOR; rp->typedata.vector = calloc(1, sizeof(Edje_Real_Part_Vector)); + if (rp->typedata.vector) + rp->typedata.vector->cur.svg_id = -1; rp->object = evas_object_vg_add(ed->base->evas); } else if (ep->type == EDJE_PART_TYPE_IMAGE || ep->type == EDJE_PART_TYPE_PROXY) diff --git a/src/lib/edje/edje_load.c b/src/lib/edje/edje_load.c index 9ada9c0..d62979b 100644 --- a/src/lib/edje/edje_load.c +++ b/src/lib/edje/edje_load.c @@ -673,7 +673,10 @@ _edje_object_file_set_internal(Evas_Object *obj, const Eina_File *file, const ch case EDJE_PART_TYPE_VECTOR: rp->type = EDJE_PART_TYPE_VECTOR; rp->typedata.vector = calloc(1, sizeof(Edje_Real_Part_Vector)); - if (!rp->typedata.vector) memerr = EINA_TRUE; + if (!rp->typedata.vector) + memerr = EINA_TRUE; + else + rp->typedata.vector->cur.svg_id = -1; break; case EDJE_PART_TYPE_GROUP: diff --git a/src/lib/efl/interfaces/efl_gfx_shape.c b/src/lib/efl/interfaces/efl_gfx_shape.c index f7c306f..7ffcda5 100644 --- a/src/lib/efl/interfaces/efl_gfx_shape.c +++ b/src/lib/efl/interfaces/efl_gfx_shape.c @@ -275,13 +275,13 @@ _efl_gfx_shape_equal_commands_internal(Efl_Gfx_Shape_Data *a, static inline double interpolate(double from, double to, double pos_map) { - return (from * pos_map) + (to * (1.0 - pos_map)); + return (from * (1.0 - pos_map)) + (to * pos_map); } static inline int interpolatei(int from, int to, double pos_map) { - return (from * pos_map) + (to * (1.0 - pos_map)); + return (from * (1.0 - pos_map)) + (to * pos_map); } typedef struct _Efl_Gfx_Property Efl_Gfx_Property; @@ -403,17 +403,17 @@ _efl_gfx_shape_interpolate(Eo *obj, Efl_Gfx_Shape_Data *pd, eo_do(obj, - efl_gfx_shape_stroke_scale_set(interpolate(property_to.scale, property_from.scale, pos_map)), - efl_gfx_shape_stroke_color_set(interpolatei(property_to.r, property_from.r, pos_map), - interpolatei(property_to.g, property_from.g, pos_map), - interpolatei(property_to.b, property_from.b, pos_map), - interpolatei(property_to.a, property_from.a, pos_map)), - efl_gfx_color_set(interpolatei(property_to.fr, property_from.fr, pos_map), - interpolatei(property_to.fg, property_from.fg, pos_map), - interpolatei(property_to.fb, property_from.fb, pos_map), - interpolatei(property_to.fa, property_from.fa, pos_map)), - efl_gfx_shape_stroke_width_set(interpolate(property_to.w, property_from.w, pos_map)), - efl_gfx_shape_stroke_location_set(interpolate(property_to.centered, property_from.centered, pos_map)), + efl_gfx_shape_stroke_scale_set(interpolate(property_from.scale, property_to.scale, pos_map)), + efl_gfx_shape_stroke_color_set(interpolatei(property_from.r, property_to.r, pos_map), + interpolatei(property_from.g, property_to.g, pos_map), + interpolatei(property_from.b, property_to.b, pos_map), + interpolatei(property_from.a, property_to.a, pos_map)), + efl_gfx_color_set(interpolatei(property_from.fr, property_to.fr, pos_map), + interpolatei(property_from.fg, property_to.fg, pos_map), + interpolatei(property_from.fb, property_to.fb, pos_map), + interpolatei(property_from.fa, property_to.fa, pos_map)), + efl_gfx_shape_stroke_width_set(interpolate(property_from.w, property_to.w, pos_map)), + efl_gfx_shape_stroke_location_set(interpolate(property_from.centered, property_to.centered, pos_map)), efl_gfx_shape_stroke_dash_set(dash, property_to.dash_length), efl_gfx_shape_stroke_cap_set(pos_map < 0.5 ? property_from.c : property_to.c), efl_gfx_shape_stroke_join_set(pos_map < 0.5 ? property_from.j : property_to.j), diff --git a/src/lib/evas/canvas/evas_object_vg.c b/src/lib/evas/canvas/evas_object_vg.c index 84de3c0..9c1d912 100644 --- a/src/lib/evas/canvas/evas_object_vg.c +++ b/src/lib/evas/canvas/evas_object_vg.c @@ -229,6 +229,7 @@ _svg_data_render(Evas_Object_Protected_Data *obj, void *buffer; Ector_Surface *ector; RGBA_Draw_Context *ct; + Eina_Bool async_unref; // if the size changed in between path set and the draw call; if (!(svg->w == obj->cur->geometry.w && @@ -240,21 +241,23 @@ _svg_data_render(Evas_Object_Protected_Data *obj, vd->svg = svg; } // if the buffer is not created yet - buffer = obj->layer->evas->engine.func->ector_surface_cache_get(output, svg->key); + root = evas_cache_svg_vg_tree_get(svg); + if (!root) return; + buffer = obj->layer->evas->engine.func->ector_surface_cache_get(output, root); if (!buffer) { - root = evas_cache_svg_vg_tree_get(svg); - if (!root) return; // manual render the vg tree ector = evas_ector_get(obj->layer->evas); if (!ector) return; + //1. render pre _evas_vg_render_pre(root, ector, NULL); // 2. create surface buffer = obj->layer->evas->engine.func->ector_surface_create(output, NULL, svg->w, - svg->h); + svg->h, + EINA_TRUE); //3. draw into the buffer ct = evas_common_draw_context_new(); evas_common_draw_context_set_render_op(ct, _EVAS_RENDER_COPY); @@ -267,17 +270,24 @@ _svg_data_render(Evas_Object_Protected_Data *obj, output, ct, buffer, root, NULL, do_async); + obj->layer->evas->engine.func->image_dirty_region(output, buffer, 0, 0, 0, 0); obj->layer->evas->engine.func->ector_end(output, ct, ector, buffer, do_async); - obj->layer->evas->engine.func->ector_surface_cache_set(output, svg->key, buffer); + obj->layer->evas->engine.func->ector_surface_cache_set(output, root, buffer); evas_common_draw_context_free(ct); } // draw the buffer as image to canvas - obj->layer->evas->engine.func->image_draw(output, context, surface, + + async_unref = obj->layer->evas->engine.func->image_draw(output, context, surface, buffer, 0, 0, obj->cur->geometry.w, obj->cur->geometry.h, obj->cur->geometry.x + x, obj->cur->geometry.y + y, obj->cur->geometry.w, obj->cur->geometry.h, EINA_TRUE, do_async); + if (do_async && async_unref) + { + evas_cache_image_ref((Image_Entry *)buffer); + evas_unref_queue_image_put(obj->layer->evas, buffer); + } } static void @@ -327,7 +337,8 @@ evas_object_vg_render(Evas_Object *eo_obj EINA_UNUSED, vd->backing_store = obj->layer->evas->engine.func->ector_surface_create(output, vd->backing_store, obj->cur->geometry.w, - obj->cur->geometry.h); + obj->cur->geometry.h, + EINA_FALSE); if (!vd->backing_store) { obj->layer->evas->engine.func->ector_begin(output, context, ector, surface, diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index 97597f2..c05cd4a 100755 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -529,10 +529,18 @@ typedef enum _Evas_Font_Spacing Evas_Font_Spacing; // ector cache typedef struct _Ector_Surface_Cache Ector_Surface_Cache; +typedef struct _Ector_Surface_Data Ector_Surface_Data; + +struct _Ector_Surface_Data +{ + void *key; + void *surface; +}; struct _Ector_Surface_Cache { - Eina_Hash *suface_hash; + Eina_Hash *surface_hash; + Eina_List *lru_list; void *output; }; @@ -1471,9 +1479,9 @@ struct _Evas_Func void (*ector_begin) (void *data, void *context, Ector_Surface *ector, void *surface, int x, int y, Eina_Bool do_async); void (*ector_renderer_draw) (void *data, void *context, void *surface, Ector_Renderer *r, Eina_Array *clips, Eina_Bool do_async); void (*ector_end) (void *data, void *context, Ector_Surface *ector, void *surface, Eina_Bool do_async); - void *(*ector_surface_create) (void *data, void *surface, int w, int h); - void (*ector_surface_cache_set) (void *data, const char *key, void *surface); - void *(*ector_surface_cache_get) (void *data, const char *key); + void *(*ector_surface_create) (void *data, void *surface, int w, int h, Eina_Bool force); + void (*ector_surface_cache_set) (void *data, void *key, void *surface); + void *(*ector_surface_cache_get) (void *data, void *key); }; struct _Evas_Image_Save_Func diff --git a/src/lib/evas/vg/evas_vg_cache.c b/src/lib/evas/vg/evas_vg_cache.c index e84a738..7932744 100644 --- a/src/lib/evas/vg/evas_vg_cache.c +++ b/src/lib/evas/vg/evas_vg_cache.c @@ -1,5 +1,5 @@ -#include "evas_vg_cache.h" #include "evas_vg_common.h" +#include "evas_vg_cache.h" static Evas_Cache_Svg* svg_cache = NULL; @@ -74,20 +74,16 @@ _evas_cache_svg_vg_tree_update(Svg_Entry *entry) Vg_Data *src_vg = NULL, *dst_vg = NULL; if(!entry) return; - if (!entry->src_vg) + if (entry->src_vg < 0) { entry->root = NULL; return; } - if (!entry->dest_vg) - { - src_vg = _evas_cache_vg_data_find(entry->file, entry->src_vg); - } - else - { - dst_vg = _evas_cache_vg_data_find(entry->file, entry->dest_vg); - } + src_vg = _evas_cache_vg_data_find(entry->file, entry->src_vg); + if (entry->dest_vg >= 0) + dst_vg = _evas_cache_vg_data_find(entry->file, entry->dest_vg); + entry->root = _evas_vg_dup_vg_tree(src_vg, dst_vg, entry->key_frame, entry->w, entry->h); eina_stringshare_del(entry->file); entry->file = NULL; diff --git a/src/lib/evas/vg/evas_vg_common.h b/src/lib/evas/vg/evas_vg_common.h index 8052e4f..b6f8c7a 100644 --- a/src/lib/evas/vg/evas_vg_common.h +++ b/src/lib/evas/vg/evas_vg_common.h @@ -278,6 +278,7 @@ struct _Svg_Node Svg_Circle_Node circle; Svg_Ellipse_Node ellipse; Svg_Polygon_Node polygon; + Svg_Polygon_Node polyline; Svg_Rect_Node rect; Svg_Path_Node path; }node; diff --git a/src/lib/evas/vg/evas_vg_eet_handler.c b/src/lib/evas/vg/evas_vg_eet_handler.c index df9ec5f..6216a78 100644 --- a/src/lib/evas/vg/evas_vg_eet_handler.c +++ b/src/lib/evas/vg/evas_vg_eet_handler.c @@ -274,6 +274,7 @@ _eet_for_polygon_node(void) EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eetc, Svg_Polygon_Node); eet = eet_data_descriptor_stream_new(&eetc); + EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Polygon_Node, "points_count", points_count, EET_T_INT); EET_DATA_DESCRIPTOR_ADD_BASIC_VAR_ARRAY(eet, Svg_Polygon_Node, "points", points, EET_T_DOUBLE); return eet; } @@ -302,7 +303,7 @@ struct { SVG_NODE_CIRCLE, "circle" }, { SVG_NODE_ELLIPSE, "ellipse" }, { SVG_NODE_POLYGON, "polygon" }, - { SVG_NODE_POLYLINE, "polygon" }, + { SVG_NODE_POLYLINE, "polyline" }, { SVG_NODE_RECT, "rect" }, { SVG_NODE_PATH, "path" }, { SVG_NODE_UNKNOWN, NULL } @@ -387,6 +388,7 @@ _evas_vg_svg_node_eet(void) EET_DATA_DESCRIPTOR_ADD_MAPPING(eet_union, "rect", _edje_edd_edje_rect_node); EET_DATA_DESCRIPTOR_ADD_MAPPING(eet_union, "path", _edje_edd_edje_path_node); EET_DATA_DESCRIPTOR_ADD_MAPPING(eet_union, "polygon", _edje_edd_edje_polygon_node); + EET_DATA_DESCRIPTOR_ADD_MAPPING(eet_union, "polyline", _edje_edd_edje_polygon_node); EET_DATA_DESCRIPTOR_ADD_UNION(_edje_edd_edje_vg_node, Svg_Node, "node", node, type, eet_union); @@ -513,7 +515,9 @@ _apply_vg_property(Svg_Node *node, Efl_VG *vg) } // apply the stroke style property - evas_vg_shape_stroke_width_set(vg, style->stroke.width); + //@TODO HACK, fix the below api to take the stroke width as pixels + // rightnow it draws double the pixel (inside and outside the outline) + evas_vg_shape_stroke_width_set(vg, style->stroke.width/2.0); evas_vg_shape_stroke_cap_set(vg, style->stroke.cap); evas_vg_shape_stroke_join_set(vg, style->stroke.join); evas_vg_shape_stroke_scale_set(vg, style->stroke.scale); @@ -590,6 +594,7 @@ _create_vg_node(Svg_Node *node, Efl_VG *parent) _add_polyline(vg, node->node.polygon.points, node->node.polygon.points_count, EINA_TRUE); break; case SVG_NODE_POLYLINE: + vg = evas_vg_shape_add(parent); _add_polyline(vg, node->node.polygon.points, node->node.polygon.points_count, EINA_FALSE); break; case SVG_NODE_ELLIPSE: @@ -614,6 +619,25 @@ _create_vg_node(Svg_Node *node, Efl_VG *parent) _apply_vg_property(node, vg); } +static void +_apply_stroke_scale(Efl_VG *node, double scale) +{ + Efl_VG *child; + Eina_Iterator *itr; + + if (eo_isa(node, EFL_VG_CONTAINER_CLASS)) + { + eo_do(node, itr = efl_vg_container_children_get()); + EINA_ITERATOR_FOREACH(itr, child) + _apply_stroke_scale(child, scale); + eina_iterator_free(itr); + } + else + { + evas_vg_shape_stroke_scale_set(node, scale); + } +} + Vg_Data * _evas_vg_load_vg_data(Eina_Stringshare *path, int svg_id) { @@ -660,12 +684,31 @@ _evas_vg_load_vg_data(Eina_Stringshare *path, int svg_id) return vector; } +static void +_apply_transformation(Efl_VG *root, double w, double h, Vg_Data *vg_data) +{ + double sx, sy, scale; + Eina_Matrix3 m; + + sx = w/vg_data->w; + sy = h/vg_data->h; + scale = sx < sy ? sx: sy; + eina_matrix3_identity(&m); + // allign hcenter and vcenter + //@TODO take care of the preserveaspectratio attribute + eina_matrix3_translate(&m, (w - vg_data->w * scale)/2.0, (h - vg_data->h * scale)/2.0); + eina_matrix3_scale(&m, scale, scale); + eina_matrix3_translate(&m, -vg_data->x, -vg_data->y); + evas_vg_node_transformation_set(root, &m); + _apply_stroke_scale(root, scale); +} + Efl_VG * _evas_vg_dup_vg_tree(Vg_Data *src, Vg_Data *dest, float pos, double w, double h) { - double sx, sy; + Efl_VG *root; - Eina_Matrix3 matrix; + Eina_Matrix3 m; if (!src) return NULL; if (w==0 || h ==0 ) return NULL; @@ -673,12 +716,7 @@ _evas_vg_dup_vg_tree(Vg_Data *src, Vg_Data *dest, float pos, double w, double h) { root = evas_vg_container_add(NULL); evas_vg_node_dup(root, src->vg); - sx = w/src->w; - sy = h/src->h; - eina_matrix3_identity(&matrix); - eina_matrix3_scale(&matrix, sx, sy); - eina_matrix3_translate(&matrix, -src->x, -src->y); - evas_vg_node_transformation_set(root, &matrix); + _apply_transformation(root, w, h, src); } else { @@ -686,20 +724,10 @@ _evas_vg_dup_vg_tree(Vg_Data *src, Vg_Data *dest, float pos, double w, double h) evas_vg_node_dup(root, src->vg); // for start vector - sx = w/src->w; - sy = h/src->h; - eina_matrix3_identity(&matrix); - eina_matrix3_scale(&matrix, sx, sy); - eina_matrix3_translate(&matrix, -src->x, -src->y); - evas_vg_node_transformation_set(src->vg, &matrix); + _apply_transformation(src->vg, w, h, src); // for end vector - sx = w/dest->w; - sy = h/dest->h; - eina_matrix3_identity(&matrix); - eina_matrix3_scale(&matrix, sx, sy); - eina_matrix3_translate(&matrix, -dest->x, -dest->y); - evas_vg_node_transformation_set(dest->vg, &matrix); + _apply_transformation(dest->vg, w, h, dest); // do the interpolation if (!evas_vg_node_interpolate(root, src->vg, dest->vg, pos)) @@ -710,9 +738,9 @@ _evas_vg_dup_vg_tree(Vg_Data *src, Vg_Data *dest, float pos, double w, double h) // instead of duplicating the tree and applying the transformation // i just updated the transformation matrix and reset it back to null. // assumption is that the root vg will never have a transformation - eina_matrix3_identity(&matrix); - evas_vg_node_transformation_set(src->vg, &matrix); - evas_vg_node_transformation_set(dest->vg, &matrix); + eina_matrix3_identity(&m); + evas_vg_node_transformation_set(src->vg, &m); + evas_vg_node_transformation_set(dest->vg, &m); } return root; } @@ -770,9 +798,11 @@ _evas_vg_svg_node_free(Svg_Node *node) eina_stringshare_del(node->node.path.path); break; case SVG_NODE_POLYGON: - case SVG_NODE_POLYLINE: free(node->node.polygon.points); break; + case SVG_NODE_POLYLINE: + free(node->node.polyline.points); + break; case SVG_NODE_DOC: _evas_vg_svg_node_free(node->node.doc.defs); break; diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c b/src/modules/evas/engines/gl_generic/evas_engine.c index 0ae044c..b240e26 100644 --- a/src/modules/evas/engines/gl_generic/evas_engine.c +++ b/src/modules/evas/engines/gl_generic/evas_engine.c @@ -2471,7 +2471,7 @@ eng_ector_renderer_draw(void *data, void *context, void *surface, Ector_Renderer } static void * -eng_ector_surface_create(void *data, void *surface, int width, int height) +eng_ector_surface_create(void *data, void *surface, int width, int height, Eina_Bool force EINA_UNUSED) { Evas_GL_Image *glim; @@ -2552,48 +2552,73 @@ eng_ector_end(void *data EINA_UNUSED, void *context EINA_UNUSED, Ector_Surface * } } -static Ector_Surface_Cache *gl_cache = NULL; - -static void -_ector_surface_cache_free_cb(void *data) -{ - eng_image_free(gl_cache->output, data); -} +static Ector_Surface_Cache *surface_cache = NULL; static void _ector_surface_cache_init(void *output) { - if (!gl_cache) + if (!surface_cache) { - gl_cache = calloc(1, sizeof(Ector_Surface_Cache)); - gl_cache->output = output; - gl_cache->suface_hash = eina_hash_string_superfast_new(_ector_surface_cache_free_cb); + surface_cache = calloc(1, sizeof(Ector_Surface_Cache)); + surface_cache->output = output; + surface_cache->surface_hash = eina_hash_int32_new(NULL); } } // static void // _ector_surface_cache_dump(void) // { -// if (gl_cache) +// Ector_Surface_Data *data; + +// if (surface_cache) // { -// eina_hash_free(gl_cache->suface_hash); -// free(gl_cache); -// gl_cache = NULL; +// eina_hash_free(surface_cache->surface_hash); +// EINA_LIST_FREE(surface_cache->lru_list, data) +// { +// eng_image_free(surface_cache->output, data->surface); +// free(data); +// } +// free(surface_cache); +// surface_cache = NULL; // } // } static void -eng_ector_surface_cache_set(void *data, const char *key, void *surface) +eng_ector_surface_cache_set(void *data, void *key, void *surface) { + Ector_Surface_Data *surface_data = NULL; + int count; _ector_surface_cache_init(data); - eina_hash_add(gl_cache->suface_hash, key, surface); + surface_data = calloc(1, sizeof(surface_data)); + surface_data->key = key; + surface_data->surface = surface; + eina_hash_add(surface_cache->surface_hash, &key, surface_data); + surface_cache->lru_list = eina_list_prepend(surface_cache->lru_list, surface_data); + count = eina_list_count(surface_cache->lru_list); + if (count > 50) + { + surface_data = eina_list_data_get(eina_list_last(surface_cache->lru_list)); + eina_hash_del(surface_cache->surface_hash, &surface_data->key, surface_data); + surface_cache->lru_list = eina_list_remove_list(surface_cache->lru_list, eina_list_last(surface_cache->lru_list)); + eng_image_free(surface_cache->output, surface_data->surface); + free(surface_data); + } } static void * -eng_ector_surface_cache_get(void *data, const char *key) +eng_ector_surface_cache_get(void *data, void *key) { + Ector_Surface_Data *surface_data = NULL; + _ector_surface_cache_init(data); - return eina_hash_find(gl_cache->suface_hash, key); + surface_data = eina_hash_find(surface_cache->surface_hash, &key); + if (surface_data) + { + surface_cache->lru_list = eina_list_remove(surface_cache->lru_list, surface_data); + surface_cache->lru_list = eina_list_prepend(surface_cache->lru_list, surface_data); + return surface_data->surface; + } + return NULL; } diff --git a/src/modules/evas/engines/software_generic/evas_engine.c b/src/modules/evas/engines/software_generic/evas_engine.c index 9b65d80..c244bec 100644 --- a/src/modules/evas/engines/software_generic/evas_engine.c +++ b/src/modules/evas/engines/software_generic/evas_engine.c @@ -3890,13 +3890,19 @@ _draw_thread_ector_surface_set(void *data) } static void * -eng_ector_surface_create(void *data EINA_UNUSED, void *surface EINA_UNUSED, int width EINA_UNUSED, int height EINA_UNUSED) +eng_ector_surface_create(void *data, void *surface, int width, int height, Eina_Bool force) { RGBA_Image *im; + void *pixels = NULL; + + if (!force) return NULL; if (!surface) { surface = eng_image_new_from_copied_data(data, width, height, NULL, EINA_TRUE, EVAS_COLORSPACE_ARGB8888); + im = surface; + pixels = evas_cache_image_pixels(&im->cache_entry); + memset(pixels, 0, (width * height * 4)); } else { @@ -3912,49 +3918,73 @@ eng_ector_surface_create(void *data EINA_UNUSED, void *surface EINA_UNUSED, int return surface; } -static Ector_Surface_Cache *sw_cache = NULL; - -static void -_ector_surface_cache_free_cb(void *data) -{ - eng_image_free(sw_cache->output, data); -} +static Ector_Surface_Cache *surface_cache = NULL; static void _ector_surface_cache_init(void *output) { - if (!sw_cache) + if (!surface_cache) { - printf("engine cache init\n"); - sw_cache = calloc(1, sizeof(Ector_Surface_Cache)); - sw_cache->output = output; - sw_cache->suface_hash = eina_hash_string_superfast_new(_ector_surface_cache_free_cb); + surface_cache = calloc(1, sizeof(Ector_Surface_Cache)); + surface_cache->output = output; + surface_cache->surface_hash = eina_hash_int32_new(NULL); } } static void _ector_surface_cache_dump(void) { - if (sw_cache) + Ector_Surface_Data *data; + + if (surface_cache) { - eina_hash_free(sw_cache->suface_hash); - free(sw_cache); - sw_cache = NULL; + eina_hash_free(surface_cache->surface_hash); + EINA_LIST_FREE(surface_cache->lru_list, data) + { + eng_image_free(surface_cache->output, data->surface); + free(data); + } + free(surface_cache); + surface_cache = NULL; } } static void -eng_ector_surface_cache_set(void *data, const char *key, void *surface) +eng_ector_surface_cache_set(void *data, void *key, void *surface) { + Ector_Surface_Data *surface_data = NULL; + int count; _ector_surface_cache_init(data); - eina_hash_add(sw_cache->suface_hash, key, surface); + surface_data = calloc(1, sizeof(surface_data)); + surface_data->key = key; + surface_data->surface = surface; + eina_hash_add(surface_cache->surface_hash, &key, surface_data); + surface_cache->lru_list = eina_list_prepend(surface_cache->lru_list, surface_data); + count = eina_list_count(surface_cache->lru_list); + if (count > 50) + { + surface_data = eina_list_data_get(eina_list_last(surface_cache->lru_list)); + eina_hash_del(surface_cache->surface_hash, &surface_data->key, surface_data); + surface_cache->lru_list = eina_list_remove_list(surface_cache->lru_list, eina_list_last(surface_cache->lru_list)); + eng_image_free(surface_cache->output, surface_data->surface); + free(surface_data); + } } static void * -eng_ector_surface_cache_get(void *data, const char *key) +eng_ector_surface_cache_get(void *data, void *key) { + Ector_Surface_Data *surface_data = NULL; + _ector_surface_cache_init(data); - return eina_hash_find(sw_cache->suface_hash, key); + surface_data = eina_hash_find(surface_cache->surface_hash, &key); + if (surface_data) + { + surface_cache->lru_list = eina_list_remove(surface_cache->lru_list, surface_data); + surface_cache->lru_list = eina_list_prepend(surface_cache->lru_list, surface_data); + return surface_data->surface; + } + return NULL; } -- 2.7.4