summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCedric BAIL <cedric@osg.samsung.com>2017-08-25 10:55:15 -0700
committerCedric BAIL <cedric@osg.samsung.com>2017-08-25 10:55:15 -0700
commit8286a56279242bb0418ace7d37b225621b5e5c40 (patch)
treea827fc7834b635edb94f8343347449d315ead31a
parent4b1505c294250e93a22b9055573dfb77fe52f133 (diff)
downloadefl-8286a56279242bb0418ace7d37b225621b5e5c40.tar.gz
evas: enable rendering of multiple output.
-rw-r--r--src/lib/evas/canvas/evas_render.c382
1 files changed, 196 insertions, 186 deletions
diff --git a/src/lib/evas/canvas/evas_render.c b/src/lib/evas/canvas/evas_render.c
index 1d42b8c5e8..16895ad3cb 100644
--- a/src/lib/evas/canvas/evas_render.c
+++ b/src/lib/evas/canvas/evas_render.c
@@ -3088,11 +3088,17 @@ evas_render_updates_internal_loop(Evas *eo_e, Evas_Public_Data *evas,
return clean_them;
}
-static Efl_Canvas_Output *
-_evas_overlay_output_find(Evas_Public_Data *e, Evas_Object_Protected_Data *obj)
+typedef enum _Evas_3State
+{
+ EVAS_3STATE_OUTSIDE,
+ EVAS_3STATE_INSIDE,
+ EVAS_3STATE_OVER
+} Evas_3State;
+
+static Evas_3State
+_evas_overlay_output_find(Efl_Canvas_Output *output,
+ Evas_Object_Protected_Data *obj)
{
- Efl_Canvas_Output *output;
- Eina_List *lo;
const Eina_Rectangle geometry = {
obj->cur->geometry.x,
obj->cur->geometry.y,
@@ -3102,23 +3108,14 @@ _evas_overlay_output_find(Evas_Public_Data *e, Evas_Object_Protected_Data *obj)
Eina_Rectangle copy = geometry;
/* A video object can only be in one output at a time, check that first */
- EINA_LIST_FOREACH(e->outputs, lo, output)
- {
- if (!eina_rectangle_intersection(&copy, &output->geometry))
- {
- copy = geometry;
- continue ;
- }
- if (memcmp(&copy, &geometry, sizeof (Eina_Rectangle)) != 0)
- {
- /* This means that it does intersect this output and another */
- return NULL;
- }
+ if (!eina_rectangle_intersection(&copy, &output->geometry))
+ return EVAS_3STATE_OUTSIDE;
- return output;
- }
+ if (memcmp(&copy, &geometry, sizeof (Eina_Rectangle)) != 0)
+ /* This means that it does intersect this output and another */
+ return EVAS_3STATE_OVER;
- return NULL;
+ return EVAS_3STATE_INSIDE;
}
static Eina_Bool
@@ -3132,7 +3129,7 @@ evas_render_updates_internal(Evas *eo_e,
Evas_Object_Protected_Data *obj;
Evas_Public_Data *evas, *e;
Efl_Canvas_Output *out;
- Eina_List *ll;
+ Eina_List *ll, *l;
Eina_Bool clean_them = EINA_FALSE;
Eina_Bool rendering = EINA_FALSE;
Eina_Bool alpha;
@@ -3144,6 +3141,7 @@ evas_render_updates_internal(Evas *eo_e,
Evas_Render_Mode render_mode = !do_async ?
EVAS_RENDER_MODE_SYNC :
EVAS_RENDER_MODE_ASYNC_INIT;
+ Eina_Bool haveup = EINA_FALSE;
MAGIC_CHECK(eo_e, Evas, MAGIC_EVAS);
return EINA_FALSE;
@@ -3317,195 +3315,206 @@ evas_render_updates_internal(Evas *eo_e,
}
eina_evlog("-render_phase5", eo_e, 0.0, NULL);
- /* phase 6. Initialize output */
- out = eina_list_data_get(e->outputs);
- if (out->changed)
+ EINA_LIST_FOREACH(e->outputs, l, out)
{
- ENFN->output_resize(ENC, out->output,
- out->geometry.w, out->geometry.h);
- ENFN->output_redraws_rect_add(ENC,
- out->geometry.x, out->geometry.y,
- out->geometry.w, out->geometry.h);
- out->changed = EINA_FALSE;
- }
+ /* phase 6. Initialize output */
+ if (out->changed)
+ {
+ ENFN->output_resize(ENC, out->output,
+ out->geometry.w, out->geometry.h);
+ ENFN->output_redraws_rect_add(ENC,
+ out->geometry.x, out->geometry.y,
+ out->geometry.w, out->geometry.h);
+ out->changed = EINA_FALSE;
+ }
- /* Define the output for Evas_GL operation */
- if (ENFN->gl_output_set)
- ENFN->gl_output_set(ENC, out->output);
+ /* Define the output for Evas_GL operation */
+ if (ENFN->gl_output_set)
+ ENFN->gl_output_set(ENC, out->output);
- /* phase 7. check if video surface should be inlined or stay in their hardware plane */
- eina_evlog("+render_phase7", eo_e, 0.0, NULL);
- alpha = ENFN->canvas_alpha_get(out->output);
+ /* phase 7. check if video surface should be inlined or stay in their hardware plane */
+ eina_evlog("+render_phase7", eo_e, 0.0, NULL);
+ alpha = ENFN->canvas_alpha_get(out->output);
- EINA_LIST_FOREACH(e->video_objects, ll, eo_obj)
- {
- Efl_Canvas_Output *output;
- Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
+ EINA_LIST_FOREACH(e->video_objects, ll, eo_obj)
+ {
+ Evas_Object_Protected_Data *obj;
+ Evas_3State state;
- output = _evas_overlay_output_find(e, obj);
+ obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
+ state = _evas_overlay_output_find(out, obj);
+ if (state == EVAS_3STATE_OUTSIDE) continue;
- /* we need the surface to be transparent to display the underlying overlay */
- if (output && alpha && _evas_render_can_use_overlay(e, eo_obj, output))
- _evas_object_image_video_overlay_show(eo_obj);
- else
- _evas_object_image_video_overlay_hide(eo_obj);
- }
+ /* we need the surface to be transparent to display the underlying overlay */
+ if (state == EVAS_3STATE_INSIDE &&
+ alpha &&
+ _evas_render_can_use_overlay(e, eo_obj, out))
+ _evas_object_image_video_overlay_show(eo_obj);
+ else
+ _evas_object_image_video_overlay_hide(eo_obj);
+ }
- /* check if individual image objects can be dropped into hardware planes */
- if (ENFN->image_plane_assign)
- EINA_INARRAY_FOREACH(&evas->active_objects, ao)
- {
- Evas_Object_Protected_Data *obj2;
- Evas_Object *eo_obj2;
- Efl_Canvas_Output *output;
- Eina_List *lo;
+ /* check if individual image objects can be dropped into hardware planes */
+ if (ENFN->image_plane_assign)
+ EINA_INARRAY_FOREACH(&evas->active_objects, ao)
+ {
+ Evas_Object_Protected_Data *obj2;
+ Evas_Object *eo_obj2;
+ Efl_Canvas_Output *output;
+ Evas_3State state;
+ Eina_List *lo;
- obj2 = ao->obj;
- eo_obj2 = obj2->object;
+ obj2 = ao->obj;
+ eo_obj2 = obj2->object;
- if (!efl_isa(eo_obj2, EFL_CANVAS_IMAGE_INTERNAL_CLASS)) continue;
+ if (!efl_isa(eo_obj2, EFL_CANVAS_IMAGE_INTERNAL_CLASS)) continue;
- if (evas_object_image_video_surface_get(eo_obj2)) continue;
+ if (evas_object_image_video_surface_get(eo_obj2)) continue;
- /* Find the output the object was in */
- EINA_LIST_FOREACH(e->outputs, lo, output)
- {
- if (!eina_list_data_find(output->planes, obj2)) continue ;
- _evas_object_image_plane_release(eo_obj2, obj2, output);
- break;
- }
+ /* Find the output the object was in */
+ EINA_LIST_FOREACH(e->outputs, lo, output)
+ {
+ if (!eina_list_data_find(output->planes, obj2)) continue ;
+ _evas_object_image_plane_release(eo_obj2, obj2, output);
+ break;
+ }
- /* A video object can only be in one output at a time, check that first */
- output = _evas_overlay_output_find(e, obj2);
- if (!output) continue ;
+ /* A video object can only be in one output at a time, check that first */
+ state = _evas_overlay_output_find(out, obj2);
+ if (state == EVAS_3STATE_OUTSIDE) continue ;
- if (!_evas_render_can_use_overlay(e, eo_obj2, output))
- {
- /* This may free up things temporarily allocated by
- * _can_use_overlay() testing in the engine */
- _evas_object_image_plane_release(eo_obj2, obj2, output);
+ if (!_evas_render_can_use_overlay(e, eo_obj2, out))
+ {
+ /* This may free up things temporarily allocated by
+ * _can_use_overlay() testing in the engine */
+ _evas_object_image_plane_release(eo_obj2, obj2, out);
+ }
}
- }
- eina_evlog("-render_phase7", eo_e, 0.0, NULL);
+ eina_evlog("-render_phase7", eo_e, 0.0, NULL);
- /* phase 8. go thru each update rect and render objects in it*/
- eina_evlog("+render_phase8", eo_e, 0.0, NULL);
- if (do_draw)
- {
- Render_Updates *ru;
- void *surface;
- int ux, uy, uw, uh;
- int cx, cy, cw, ch;
- 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();
- eina_evlog("+render_surface", eo_e, 0.0, NULL);
- // FIXME: handle multiple output
- while ((surface =
- ENFN->output_redraws_next_update_get
- (ENC, out->output,
- &ux, &uy, &uw, &uh,
- &cx, &cy, &cw, &ch)))
+ /* phase 8. go thru each update rect and render objects in it*/
+ eina_evlog("+render_phase8", eo_e, 0.0, NULL);
+ if (do_draw)
{
- void *ctx;
+ Render_Updates *ru;
+ void *surface;
+ int ux, uy, uw, uh;
+ int cx, cy, cw, ch;
+ unsigned int offset = 0;
+ int fx = e->framespace.x;
+ int fy = e->framespace.y;
+ int j;
+
+ if (do_async) _evas_render_busy_begin();
+ eina_evlog("+render_surface", eo_e, 0.0, NULL);
+ while ((surface =
+ ENFN->output_redraws_next_update_get
+ (ENC, out->output,
+ &ux, &uy, &uw, &uh,
+ &cx, &cy, &cw, &ch)))
+ {
+ void *ctx;
- haveup = EINA_TRUE;
+ haveup = EINA_TRUE;
- /* phase 7.1 render every snapshot that needs to be updated
- for this part of the screen */
- eina_evlog("+render_snapshots", eo_e, 0.0, NULL);
- for (j = e->snapshot_objects.count - 1; j >= 0; j--)
- {
- Evas_Object_Protected_Data *snap;
- Eina_Rectangle output, cr, ur;
-
- snap = eina_array_data_get(&e->snapshot_objects, j);
-
- EINA_RECTANGLE_SET(&output,
- snap->cur->geometry.x,
- snap->cur->geometry.y,
- snap->cur->geometry.w,
- snap->cur->geometry.h);
- EINA_RECTANGLE_SET(&ur, ux, uy, uw, uh);
-
- // FIXME: We should render snapshots only once per frame,
- // not once per update region!
- if (snap->snapshot_needs_redraw &&
- eina_rectangle_intersection(&ur, &output))
+ /* phase 7.1 render every snapshot that needs to be updated
+ for this part of the screen */
+ eina_evlog("+render_snapshots", eo_e, 0.0, NULL);
+ for (j = e->snapshot_objects.count - 1; j >= 0; j--)
{
- Cutout_Margin cm = {};
- unsigned int restore_offset = offset;
- Eina_Bool skip_cutouts = EINA_FALSE;
- void *pseudo_canvas;
-
- EINA_RECTANGLE_SET(&cr,
- ur.x - output.x, ur.y - output.y,
- ur.w, ur.h);
-
- pseudo_canvas = _evas_object_image_surface_get(snap, EINA_TRUE);
-
- // Get required margin for filters (eg. blur radius)
- _evas_filter_radius_get(snap, &cm.l, &cm.r, &cm.t, &cm.b);
-
- if (snap->map->cur.usemap || snap->proxy->proxies ||
- snap->snapshot_no_obscure ||
- ((cm.l + cm.r) >= output.w) ||
- ((cm.t + cm.b) >= output.h))
- skip_cutouts = EINA_TRUE;
-
- RD(0, " SNAPSHOT %s [sfc:%p ur:%d,%d %dx%d]\n", RDNAME(snap), pseudo_canvas, ur.x, ur.y, ur.w, ur.h);
- ctx = ENFN->context_new(ENC);
- clean_them |= evas_render_updates_internal_loop(eo_e, e, out->output, pseudo_canvas, ctx,
- snap,
- ur.x, ur.y, ur.w, ur.h,
- cr.x, cr.y, cr.w, cr.h,
- fx, fy, skip_cutouts, &cm,
- alpha, do_async,
- &offset, 1);
- ENFN->context_free(ENC, ctx);
-
- offset = restore_offset;
+ Evas_Object_Protected_Data *snap;
+ Eina_Rectangle output, cr, ur;
+
+ snap = eina_array_data_get(&e->snapshot_objects, j);
+
+ EINA_RECTANGLE_SET(&output,
+ snap->cur->geometry.x,
+ snap->cur->geometry.y,
+ snap->cur->geometry.w,
+ snap->cur->geometry.h);
+ EINA_RECTANGLE_SET(&ur, ux, uy, uw, uh);
+
+ // FIXME: We should render snapshots only once per frame,
+ // not once per update region per output !
+ if (snap->snapshot_needs_redraw &&
+ eina_rectangle_intersection(&ur, &output))
+ {
+ Cutout_Margin cm = {};
+ unsigned int restore_offset = offset;
+ Eina_Bool skip_cutouts = EINA_FALSE;
+ void *pseudo_canvas;
+
+ EINA_RECTANGLE_SET(&cr,
+ ur.x - output.x, ur.y - output.y,
+ ur.w, ur.h);
+
+ pseudo_canvas = _evas_object_image_surface_get(snap, EINA_TRUE);
+
+ // Get required margin for filters (eg. blur radius)
+ _evas_filter_radius_get(snap, &cm.l, &cm.r, &cm.t, &cm.b);
+
+ if (snap->map->cur.usemap || snap->proxy->proxies ||
+ snap->snapshot_no_obscure ||
+ ((cm.l + cm.r) >= output.w) ||
+ ((cm.t + cm.b) >= output.h))
+ skip_cutouts = EINA_TRUE;
+
+ RD(0, " SNAPSHOT %s [sfc:%p ur:%d,%d %dx%d]\n", RDNAME(snap), pseudo_canvas, ur.x, ur.y, ur.w, ur.h);
+ ctx = ENFN->context_new(ENC);
+ clean_them |= evas_render_updates_internal_loop(eo_e, e, out->output, pseudo_canvas, ctx,
+ snap,
+ ur.x, ur.y, ur.w, ur.h,
+ cr.x, cr.y, cr.w, cr.h,
+ fx, fy, skip_cutouts, &cm,
+ alpha, do_async,
+ &offset, 1);
+ ENFN->context_free(ENC, ctx);
+
+ offset = restore_offset;
+ }
}
- }
- eina_evlog("-render_snapshots", eo_e, 0.0, NULL);
+ eina_evlog("-render_snapshots", eo_e, 0.0, NULL);
- eina_evlog("+render_update", eo_e, 0.0, NULL);
- /* phase 7.2 render all the object on the target surface */
- if ((do_async) || (make_updates))
- {
- ru = malloc(sizeof(*ru));
- ru->surface = surface;
- //XXX: need a way of reffing output surfaces
- NEW_RECT(ru->area, ux, uy, uw, uh);
- eina_spinlock_take(&(e->render.lock));
- out->updates = eina_list_append(out->updates, ru);
- eina_spinlock_release(&(e->render.lock));
- }
+ eina_evlog("+render_update", eo_e, 0.0, NULL);
+ /* phase 7.2 render all the object on the target surface */
+ if ((do_async) || (make_updates))
+ {
+ ru = malloc(sizeof(*ru));
+ ru->surface = surface;
+ //XXX: need a way of reffing output surfaces
+ NEW_RECT(ru->area, ux, uy, uw, uh);
+ eina_spinlock_take(&(e->render.lock));
+ out->updates = eina_list_append(out->updates, ru);
+ eina_spinlock_release(&(e->render.lock));
+ }
- ctx = ENFN->context_new(ENC);
- clean_them |= evas_render_updates_internal_loop(eo_e, e, out->output, surface,
- ctx, NULL,
- ux, uy, uw, uh,
- cx, cy, cw, ch,
- fx, fy,
- EINA_FALSE, NULL,
- alpha, do_async,
- &offset, 0);
- ENFN->context_free(ENC, ctx);
+ ctx = ENFN->context_new(ENC);
+ clean_them |= evas_render_updates_internal_loop(eo_e, e, out->output, surface,
+ ctx, NULL,
+ ux, uy, uw, uh,
+ cx, cy, cw, ch,
+ fx, fy,
+ EINA_FALSE, NULL,
+ alpha, do_async,
+ &offset, 0);
+ ENFN->context_free(ENC, ctx);
- eina_evlog("-render_update", eo_e, 0.0, NULL);
- if (!do_async)
- {
- eina_evlog("+render_push", eo_e, 0.0, NULL);
- ENFN->output_redraws_next_update_push(ENC, out->output, surface, ux, uy, uw, uh, render_mode);
- eina_evlog("-render_push", eo_e, 0.0, NULL);
+ eina_evlog("-render_update", eo_e, 0.0, NULL);
+ if (!do_async)
+ {
+ eina_evlog("+render_push", eo_e, 0.0, NULL);
+ ENFN->output_redraws_next_update_push(ENC, out->output, surface, ux, uy, uw, uh, render_mode);
+ eina_evlog("-render_push", eo_e, 0.0, NULL);
+ }
}
+
+ eina_evlog("-render_surface", eo_e, 0.0, NULL);
}
+ }
+ /* First process all output, then flush */
+ if (do_draw)
+ {
if (haveup)
{
if (do_async)
@@ -3526,13 +3535,13 @@ evas_render_updates_internal(Evas *eo_e,
_evas_object_image_video_overlay_do(eo_obj);
}
_cb_always_call(eo_e, EVAS_CALLBACK_RENDER_FLUSH_PRE, NULL);
- ENFN->output_flush(ENC, out->output, EVAS_RENDER_MODE_SYNC);
+ EINA_LIST_FOREACH(e->outputs, l, out)
+ ENFN->output_flush(ENC, out->output, EVAS_RENDER_MODE_SYNC);
_cb_always_call(eo_e, EVAS_CALLBACK_RENDER_FLUSH_POST, NULL);
eina_evlog("-render_output_flush", eo_e, 0.0, NULL);
}
}
rendering = haveup;
- eina_evlog("-render_surface", eo_e, 0.0, NULL);
}
eina_evlog("-render_phase8", eo_e, 0.0, NULL);
@@ -3540,7 +3549,8 @@ evas_render_updates_internal(Evas *eo_e,
if (!do_async && rendering)
{
/* clear redraws */
- ENFN->output_redraws_clear(ENC, out->output);
+ EINA_LIST_FOREACH(e->outputs, l, out)
+ ENFN->output_redraws_clear(ENC, out->output);
}
eina_evlog("-render_clear", eo_e, 0.0, NULL);