diff options
author | Cedric BAIL <cedric@osg.samsung.com> | 2015-05-09 20:02:13 +0200 |
---|---|---|
committer | Cedric BAIL <cedric@osg.samsung.com> | 2015-08-05 15:12:33 +0200 |
commit | 033658d1caf0624fac71d482be5c8f14622b09b7 (patch) | |
tree | 3df916048def3d0b82ce07890daec126e54ec884 | |
parent | 8b31b7c33a8f7e35e95e9e8b01eb0fc826787fa9 (diff) | |
download | efl-033658d1caf0624fac71d482be5c8f14622b09b7.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 32191fdabf..2f8561f219 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 @@ -233,7 +235,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 = { @@ -3301,6 +3303,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); @@ -3322,6 +3332,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; @@ -4758,6 +4769,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_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 3de8510d12..91d6761b41 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 c308cb0b8f..f178ff56f9 100644 --- a/src/lib/evas/canvas/evas_render.c +++ b/src/lib/evas/canvas/evas_render.c @@ -496,6 +496,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, @@ -538,6 +539,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) @@ -596,6 +599,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, @@ -653,6 +657,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, @@ -731,6 +736,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, @@ -798,6 +804,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; @@ -812,7 +819,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"); @@ -891,6 +899,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; } @@ -934,7 +943,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; @@ -2124,13 +2133,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; @@ -2210,6 +2219,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); IFRD(0, " '%s'", obj->name); @@ -2279,6 +2290,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 @@ -2302,14 +2316,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"); @@ -2394,6 +2400,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); } @@ -2569,6 +2576,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; if (do_async) _evas_render_busy_begin(); @@ -2581,13 +2589,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); @@ -2725,6 +2779,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 @@ -3131,6 +3186,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 4614737911..29cc7d9744 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 fe838d0f14..f4e019ee7a 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -1880,6 +1880,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; |