diff options
author | Cedric BAIL <cedric@osg.samsung.com> | 2015-05-09 20:02:13 +0200 |
---|---|---|
committer | Jean-Philippe Andre <jp.andre@samsung.com> | 2015-07-01 20:57:57 +0900 |
commit | 80eb72c7c5ea7dc59cbbb1bdb45b6860c2ae7f67 (patch) | |
tree | 45fe1d307fe61c1e2fa17fd0ac06c1c3d3fb316e | |
parent | 53a9aa8b34b8e488a5d2de1efd244aecd1ec81ad (diff) | |
download | efl-80eb72c7c5ea7dc59cbbb1bdb45b6860c2ae7f67.tar.gz |
evas: implementation of snapshot feature.
This should theorically work, need some test. Design is easy to understand. Render
every part of a snapshot object by rendering the content below it, before rendering
the stack above it using that object content.
-rw-r--r-- | src/lib/evas/canvas/evas_main.c | 4 | ||||
-rw-r--r-- | src/lib/evas/canvas/evas_object_image.c | 41 | ||||
-rw-r--r-- | src/lib/evas/canvas/evas_object_main.c | 2 | ||||
-rw-r--r-- | src/lib/evas/canvas/evas_render.c | 81 | ||||
-rw-r--r-- | src/lib/evas/include/evas_inline.x | 3 | ||||
-rw-r--r-- | src/lib/evas/include/evas_private.h | 2 |
6 files changed, 118 insertions, 15 deletions
diff --git a/src/lib/evas/canvas/evas_main.c b/src/lib/evas/canvas/evas_main.c index e20f748941..5e7e6ee242 100644 --- a/src/lib/evas/canvas/evas_main.c +++ b/src/lib/evas/canvas/evas_main.c @@ -175,7 +175,7 @@ _evas_canvas_eo_base_constructor(Eo *eo_obj, Evas_Public_Data *e) #define EVAS_ARRAY_SET(E, Array) \ eina_array_step_set(&E->Array, sizeof (E->Array), \ - ((1024 * sizeof (void*)) - sizeof (E->Array)) / sizeof (void*)); + ((1024 * sizeof (void*)) - sizeof (E->Array)) / sizeof (void*)); EVAS_ARRAY_SET(e, delete_objects); EVAS_ARRAY_SET(e, active_objects); @@ -184,6 +184,7 @@ _evas_canvas_eo_base_constructor(Eo *eo_obj, Evas_Public_Data *e) EVAS_ARRAY_SET(e, pending_objects); EVAS_ARRAY_SET(e, obscuring_objects); EVAS_ARRAY_SET(e, temporary_objects); + EVAS_ARRAY_SET(e, snapshot_objects); EVAS_ARRAY_SET(e, clip_changes); EVAS_ARRAY_SET(e, scie_unref_queue); EVAS_ARRAY_SET(e, image_unref_queue); @@ -300,6 +301,7 @@ _evas_canvas_eo_base_destructor(Eo *eo_e, Evas_Public_Data *e) eina_array_flush(&e->pending_objects); eina_array_flush(&e->obscuring_objects); eina_array_flush(&e->temporary_objects); + eina_array_flush(&e->snapshot_objects); eina_array_flush(&e->clip_changes); eina_array_flush(&e->scie_unref_queue); eina_array_flush(&e->image_unref_queue); diff --git a/src/lib/evas/canvas/evas_object_image.c b/src/lib/evas/canvas/evas_object_image.c index 30797e8d0c..dcd7af921e 100644 --- a/src/lib/evas/canvas/evas_object_image.c +++ b/src/lib/evas/canvas/evas_object_image.c @@ -69,6 +69,8 @@ struct _Evas_Object_Image_Pixels Evas_Video_Surface video; unsigned int video_caps; + + int surface_w, surface_h; /* used by snapshot feature */ }; struct _Evas_Object_Image_State @@ -232,7 +234,7 @@ static const Evas_Object_Image_Load_Opts default_load_opts = { }; static const Evas_Object_Image_Pixels default_pixels = { - NULL, { NULL, NULL }, { 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, ~0x0 + NULL, { NULL, NULL }, { 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, ~0x0, 0, 0 }; static const Evas_Object_Image_State default_state = { @@ -3268,6 +3270,14 @@ _evas_image_render(Eo *eo_obj, Evas_Object_Protected_Data *obj, uvw = imagew; uvh = imageh; } + else if (obj->cur->snapshot) + { + pixels = o->engine_data; + imagew = o->pixels->surface_w; + imageh = o->pixels->surface_h; + uvw = imagew; + uvh = imageh; + } else if (!o->cur->source) { pixels = evas_process_dirty_pixels(eo_obj, obj, o, output, surface, o->engine_data); @@ -3289,6 +3299,7 @@ _evas_image_render(Eo *eo_obj, Evas_Object_Protected_Data *obj, ((Evas_Image_Data *)eo_data_scope_get(o->cur->source, MY_CLASS))->engine_data) { Evas_Image_Data *oi; + oi = eo_data_scope_get(o->cur->source, MY_CLASS); pixels = oi->engine_data; imagew = oi->cur->image.w; @@ -4725,6 +4736,34 @@ _evas_image_snapshot_get(Eo *eo, Evas_Image_Data *pd EINA_UNUSED) return obj->cur->snapshot; } +void * +_evas_object_image_surface_get(Evas_Object *eo, Evas_Object_Protected_Data *obj) +{ + Evas_Image_Data *pd = eo_data_scope_get(eo, EVAS_IMAGE_CLASS); + + if (pd->engine_data && + pd->pixels->surface_w == obj->cur->geometry.w && + pd->pixels->surface_h == obj->cur->geometry.h) + return pd->engine_data; + + if (pd->engine_data) + ENFN->image_map_surface_free(ENDT, pd->engine_data); + + // FIXME: alpha forced to 1 for now, need to figure out Evas alpha here + EINA_COW_PIXEL_WRITE_BEGIN(pd, pixi_write) + { + pd->engine_data = ENFN->image_map_surface_new(ENDT, + obj->cur->geometry.w, + obj->cur->geometry.h, + 1); + pixi_write->surface_w = obj->cur->geometry.w; + pixi_write->surface_h = obj->cur->geometry.h; + } + EINA_COW_PIXEL_WRITE_END(pd, pixi_write); + + return pd->engine_data; +} + EAPI void evas_object_image_file_set(Eo *obj, const char *file, const char *key) { diff --git a/src/lib/evas/canvas/evas_object_main.c b/src/lib/evas/canvas/evas_object_main.c index 8800a041b5..9d4c7fb622 100644 --- a/src/lib/evas/canvas/evas_object_main.c +++ b/src/lib/evas/canvas/evas_object_main.c @@ -30,7 +30,7 @@ static const Evas_Object_Protected_State default_state = { NULL, { 0, 0, 0, 0 }, { { 0, 0, 0, 0, 0, 0, 0, 0, EINA_FALSE, EINA_FALSE } }, { 255, 255, 255, 255 }, - 1.0, 0, EVAS_RENDER_BLEND, EINA_FALSE, EINA_FALSE, EINA_FALSE, EINA_FALSE, EINA_FALSE, EINA_FALSE + 1.0, 0, EVAS_RENDER_BLEND, EINA_FALSE, EINA_FALSE, EINA_FALSE, EINA_FALSE, EINA_FALSE, EINA_FALSE, EINA_FALSE }; static const Evas_Object_Filter_Data default_filter = { NULL, NULL, NULL, NULL, NULL, NULL, { { "default", 0.0 }, { "default", 0.0 }, 0.0 }, EINA_FALSE, EINA_FALSE diff --git a/src/lib/evas/canvas/evas_render.c b/src/lib/evas/canvas/evas_render.c index be9a839aad..eac6a80444 100644 --- a/src/lib/evas/canvas/evas_render.c +++ b/src/lib/evas/canvas/evas_render.c @@ -461,6 +461,7 @@ _evas_render_phase1_object_process(Evas_Public_Data *e, Evas_Object *eo_obj, Eina_Array *restack_objects, Eina_Array *delete_objects, Eina_Array *render_objects, + Eina_Array *snapshot_objects, int restack, int *redraw_all, Eina_Bool mapped_parent, @@ -503,6 +504,8 @@ _evas_render_phase1_object_process(Evas_Public_Data *e, Evas_Object *eo_obj, if ((!mapped_parent) && ((is_active) || (obj->delete_me != 0))) OBJ_ARRAY_PUSH(active_objects, obj); + if (is_active && obj->cur->snapshot) + OBJ_ARRAY_PUSH(snapshot_objects, obj); #ifdef REND_DBG if (!is_active) @@ -561,6 +564,7 @@ _evas_render_phase1_object_process(Evas_Public_Data *e, Evas_Object *eo_obj, restack_objects, delete_objects, render_objects, + snapshot_objects, obj->restack, redraw_all, EINA_TRUE, @@ -618,6 +622,7 @@ _evas_render_phase1_object_process(Evas_Public_Data *e, Evas_Object *eo_obj, restack_objects, delete_objects, render_objects, + snapshot_objects, obj->restack, redraw_all, mapped_parent, @@ -696,6 +701,7 @@ _evas_render_phase1_object_process(Evas_Public_Data *e, Evas_Object *eo_obj, restack_objects, delete_objects, render_objects, + snapshot_objects, restack, redraw_all, mapped_parent, @@ -763,6 +769,7 @@ _evas_render_phase1_process(Evas_Public_Data *e, Eina_Array *restack_objects, Eina_Array *delete_objects, Eina_Array *render_objects, + Eina_Array *snapshot_objects, int *redraw_all) { Evas_Layer *lay; @@ -777,7 +784,8 @@ _evas_render_phase1_process(Evas_Public_Data *e, { clean_them |= _evas_render_phase1_object_process (e, obj->object, active_objects, restack_objects, delete_objects, - render_objects, 0, redraw_all, EINA_FALSE, EINA_FALSE, 2); + render_objects, snapshot_objects, 0, redraw_all, + EINA_FALSE, EINA_FALSE, 2); } } RD(0, " ---]\n"); @@ -856,6 +864,7 @@ clean_stuff: OBJS_ARRAY_CLEAN(&e->render_objects); OBJS_ARRAY_CLEAN(&e->restack_objects); OBJS_ARRAY_CLEAN(&e->delete_objects); + OBJS_ARRAY_CLEAN(&e->snapshot_objects); e->invalidate = EINA_TRUE; return; } @@ -899,7 +908,7 @@ _evas_render_can_use_overlay(Evas_Public_Data *e, Evas_Object *eo_obj) Evas_Object *video_parent = NULL; Eina_Rectangle zone; Evas_Coord xc1, yc1, xc2, yc2; - unsigned int i; + int i; Eina_Bool nooverlay; Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS); Evas_Object_Protected_Data *tmp = NULL; @@ -2085,13 +2094,13 @@ _cb_always_call(Evas *eo_e, Evas_Callback_Type type, void *event_info) static Eina_Bool evas_render_updates_internal_loop(Evas *eo_e, Evas_Public_Data *e, void *surface, + Evas_Object_Protected_Data *top, int ux, int uy, int uw, int uh, int cx, int cy, int cw, int ch, int fx, int fy, Eina_Bool alpha, Eina_Bool make_updates, Eina_Bool do_async, - Evas_Render_Mode render_mode, unsigned int *offset) { Evas_Object *eo_obj; @@ -2171,6 +2180,8 @@ evas_render_updates_internal_loop(Evas *eo_e, Evas_Public_Data *e, obj = eina_array_data_get(&e->active_objects, i); eo_obj = obj->object; + if (obj == top) break; + /* if it's in our outpout rect and it doesn't clip anything */ RD(0, " OBJ: [%p", obj); if (obj->name) RD(0, " '%s'", obj->name); @@ -2239,6 +2250,9 @@ evas_render_updates_internal_loop(Evas *eo_e, Evas_Public_Data *e, obj2 = (Evas_Object_Protected_Data *)eina_array_data_get (&e->temporary_objects, j); + + if (obj2 == top) break; + _evas_render_cutout_add(e, obj2, off_x + fx, off_y + fy); } #endif @@ -2262,14 +2276,6 @@ evas_render_updates_internal_loop(Evas *eo_e, Evas_Public_Data *e, } eina_evlog("-render_objects", eo_e, 0.0, NULL); - - eina_evlog("+render_push", eo_e, 0.0, NULL); - e->engine.func->output_redraws_next_update_push(e->engine.data.output, - surface, - ux, uy, uw, uh, - render_mode); - eina_evlog("-render_push", eo_e, 0.0, NULL); - /* free obscuring objects list */ OBJS_ARRAY_CLEAN(&e->temporary_objects); RD(0, " ---]\n"); @@ -2354,6 +2360,7 @@ evas_render_updates_internal(Evas *eo_e, &e->restack_objects, &e->delete_objects, &e->render_objects, + &e->snapshot_objects, &redraw_all); eina_evlog("-render_phase1", eo_e, 0.0, NULL); } @@ -2529,6 +2536,7 @@ evas_render_updates_internal(Evas *eo_e, unsigned int offset = 0; int fx = e->framespace.x; int fy = e->framespace.y; + int j; Eina_Bool haveup = EINA_FALSE; eina_evlog("+render_surface", eo_e, 0.0, NULL); @@ -2540,13 +2548,59 @@ evas_render_updates_internal(Evas *eo_e, { haveup = EINA_TRUE; + /* phase 6.1 render every snapshot that needs to be updated + for this part of the screen */ + for (j = e->snapshot_objects.count - 1; j >= 0; j--) + { + Eina_Rectangle output, cr, ur; + + obj = (Evas_Object_Protected_Data *)eina_array_data_get(&e->snapshot_objects, j); + + EINA_RECTANGLE_SET(&output, + obj->cur->geometry.x, + obj->cur->geometry.y, + obj->cur->geometry.w, + obj->cur->geometry.h); + EINA_RECTANGLE_SET(&ur, ux, uy, uw, uh); + + if (eina_rectangle_intersection(&ur, &output)) + { + void *pseudo_canvas; + unsigned int restore_offset = offset; + + EINA_RECTANGLE_SET(&cr, + ur.x - output.x, ur.y - output.y, + ur.w, ur.h); + + pseudo_canvas = _evas_object_image_surface_get(obj->object, obj); + + clean_them |= evas_render_updates_internal_loop(eo_e, e, pseudo_canvas, + obj, + ur.x, ur.y, ur.w, ur.h, + cr.x, cr.y, cr.w, cr.h, + fx, fy, alpha, + make_updates, do_async, + &offset); + + offset = restore_offset; + } + } + + /* phase 6.2 render all the object on the target surface */ clean_them |= evas_render_updates_internal_loop(eo_e, e, surface, + NULL, ux, uy, uw, uh, cx, cy, cw, ch, fx, fy, alpha, make_updates, do_async, - render_mode, &offset); + + eina_evlog("+render_push", eo_e, 0.0, NULL); + e->engine.func->output_redraws_next_update_push(e->engine.data.output, + surface, + ux, uy, uw, uh, + render_mode); + eina_evlog("-render_push", eo_e, 0.0, NULL); } eina_evlog("+render_output_flush", eo_e, 0.0, NULL); @@ -2684,6 +2738,7 @@ evas_render_updates_internal(Evas *eo_e, OBJS_ARRAY_CLEAN(&e->render_objects); OBJS_ARRAY_CLEAN(&e->restack_objects); OBJS_ARRAY_CLEAN(&e->temporary_objects); + OBJS_ARRAY_CLEAN(&e->snapshot_objects); eina_array_foreach(&e->clip_changes, _evas_clip_changes_free, NULL); eina_array_clean(&e->clip_changes); /* we should flush here and have a mempool system for this @@ -3088,6 +3143,8 @@ evas_render_invalidate(Evas *eo_e) OBJS_ARRAY_FLUSH(&e->restack_objects); OBJS_ARRAY_FLUSH(&e->delete_objects); + OBJS_ARRAY_FLUSH(&e->snapshot_objects); + e->invalidate = EINA_TRUE; } diff --git a/src/lib/evas/include/evas_inline.x b/src/lib/evas/include/evas_inline.x index 83fa4b41c8..7cc311c8d4 100644 --- a/src/lib/evas/include/evas_inline.x +++ b/src/lib/evas/include/evas_inline.x @@ -74,6 +74,9 @@ evas_object_is_opaque(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj) if ((obj->cur->clipper && obj->cur->clipper->mask->is_mask) || (obj->clip.mask)) return 0; + /* Non masked snapshot are supposed to be opaque */ + if (obj->cur->snapshot) + return 1; if (obj->func->is_opaque) return obj->func->is_opaque(eo_obj, obj, obj->private_data); return 1; diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index 18380363dd..823cc8452d 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -1881,6 +1881,8 @@ void _evas_device_unref(Evas_Device *dev); Eina_Bool evas_vg_loader_svg(Evas_Object *vg, const Eina_File *f, const char *key EINA_UNUSED); +void *_evas_object_image_surface_get(Evas_Object *eo, Evas_Object_Protected_Data *obj); + extern Eina_Cow *evas_object_proxy_cow; extern Eina_Cow *evas_object_map_cow; extern Eina_Cow *evas_object_state_cow; |