From da36a87bb30170f8235fc9d6b464d92000681681 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Mon, 28 Jan 2019 16:53:42 +0900 Subject: [PATCH] evas vg: improve masking render logic. Previous masking image is generated on vg rendering time, though context is changed to main vg rendering to masking, This had a issue that ector context switching which is not allowed in software backend because of asynchronou method. Now, this improvment brings the masking rendering move to vg render pre step with synchronous rendering method, then use the masking surface in the main vg rendering. --- src/lib/evas/canvas/efl_canvas_vg_container.c | 49 ++++++++++++++++--- .../canvas/efl_canvas_vg_gradient_linear.c | 3 ++ .../canvas/efl_canvas_vg_gradient_radial.c | 3 ++ src/lib/evas/canvas/efl_canvas_vg_object.c | 48 +++--------------- src/lib/evas/canvas/efl_canvas_vg_shape.c | 13 +++-- src/lib/evas/canvas/evas_vg_private.h | 14 ++++-- 6 files changed, 77 insertions(+), 53 deletions(-) diff --git a/src/lib/evas/canvas/efl_canvas_vg_container.c b/src/lib/evas/canvas/efl_canvas_vg_container.c index f82f18a9f2..f22ff1a81c 100644 --- a/src/lib/evas/canvas/efl_canvas_vg_container.c +++ b/src/lib/evas/canvas/efl_canvas_vg_container.c @@ -22,9 +22,35 @@ _invalidate_cb(void *data EINA_UNUSED, const Efl_Event *event) efl_unref(child); } +static void +_draw_mask(Evas_Object_Protected_Data *obj, Efl_VG *node, + Ector_Surface *ector, void *engine, void *output, + void *context) +{ + if (!efl_gfx_entity_visible_get(node)) return; + + if (efl_isa(node, EFL_CANVAS_VG_CONTAINER_CLASS)) + { + Efl_Canvas_Vg_Container_Data *cd = + efl_data_scope_get(node, EFL_CANVAS_VG_CONTAINER_CLASS); + + //Draw Mask Image. + Efl_VG *child; + Eina_List *l; + EINA_LIST_FOREACH(cd->children, l, child) + _draw_mask(obj, child, ector, engine, output, context); + } + else + { + Efl_Canvas_Vg_Node_Data *nd = efl_data_scope_get(node, EFL_CANVAS_VG_NODE_CLASS); + ENFN->ector_renderer_draw(engine, output, context, nd->renderer, NULL, EINA_FALSE); + } +} + static Ector_Buffer * _prepare_mask(Evas_Object_Protected_Data *obj, //vector object Efl_Canvas_Vg_Node* mask_obj, + void *engine, void *output, void *context, Ector_Surface *surface, Eina_Matrix3 *ptransform, Ector_Buffer *mask, @@ -75,10 +101,17 @@ _prepare_mask(Evas_Object_Protected_Data *obj, //vector object if (!pd->mask.buffer) ERR("Mask Buffer is invalid"); - pd->mask.dirty = EINA_TRUE; + //3. Prepare Drawing shapes. + _evas_vg_render_pre(obj, mask_obj, + engine, output, context, + surface, + ptransform, mask, mask_op); - //3. Prepare Drawing shapes... - _evas_vg_render_pre(obj, mask_obj, surface, ptransform, mask, mask_op); + //4. Generating Mask Image. + ector_buffer_pixels_set(surface, pd->mask.pixels, mbound.w, mbound.h, 0, + EFL_GFX_COLORSPACE_ARGB8888, EINA_TRUE); + ector_surface_reference_point_set(surface, -mbound.x, -mbound.y); + _draw_mask(obj, mask_obj, surface, engine, output, context); return pd->mask.buffer; } @@ -87,6 +120,7 @@ static void _efl_canvas_vg_container_render_pre(Evas_Object_Protected_Data *vg_pd, Efl_VG *obj EINA_UNUSED, Efl_Canvas_Vg_Node_Data *nd, + void *engine, void *output, void *context, Ector_Surface *surface, Eina_Matrix3 *ptransform, Ector_Buffer *mask, @@ -108,8 +142,9 @@ _efl_canvas_vg_container_render_pre(Evas_Object_Protected_Data *vg_pd, //Container may have mask source. if (pd->mask_src) { - mask = _prepare_mask(vg_pd, pd->mask_src, surface, ptransform, mask, - mask_op); + mask = _prepare_mask(vg_pd, pd->mask_src, + engine, output, context, surface, + ptransform, mask, mask_op); mask_op = pd->mask.option; } @@ -133,7 +168,9 @@ _efl_canvas_vg_container_render_pre(Evas_Object_Protected_Data *vg_pd, if (flag & EFL_GFX_CHANGE_FLAG_MATRIX) child_nd->flags |= EFL_GFX_CHANGE_FLAG_MATRIX; - _evas_vg_render_pre(vg_pd, child, surface, ctransform, mask, mask_op); + _evas_vg_render_pre(vg_pd, child, + engine, output, context, surface, + ctransform, mask, mask_op); } } diff --git a/src/lib/evas/canvas/efl_canvas_vg_gradient_linear.c b/src/lib/evas/canvas/efl_canvas_vg_gradient_linear.c index ad3118f23e..0b1435202b 100644 --- a/src/lib/evas/canvas/efl_canvas_vg_gradient_linear.c +++ b/src/lib/evas/canvas/efl_canvas_vg_gradient_linear.c @@ -59,6 +59,9 @@ static void _efl_canvas_vg_gradient_linear_render_pre(Evas_Object_Protected_Data *vg_pd EINA_UNUSED, Efl_VG *obj, Efl_Canvas_Vg_Node_Data *nd, + void *engine EINA_UNUSED, + void *output EINA_UNUSED, + void *context EINA_UNUSED, Ector_Surface *surface, Eina_Matrix3 *ptransform, Ector_Buffer *mask, diff --git a/src/lib/evas/canvas/efl_canvas_vg_gradient_radial.c b/src/lib/evas/canvas/efl_canvas_vg_gradient_radial.c index 4146cddf04..691dc5dec8 100644 --- a/src/lib/evas/canvas/efl_canvas_vg_gradient_radial.c +++ b/src/lib/evas/canvas/efl_canvas_vg_gradient_radial.c @@ -75,6 +75,9 @@ static void _efl_canvas_vg_gradient_radial_render_pre(Evas_Object_Protected_Data *vg_pd EINA_UNUSED, Efl_VG *obj, Efl_Canvas_Vg_Node_Data *nd, + void *engine EINA_UNUSED, + void *output EINA_UNUSED, + void *context EINA_UNUSED, Ector_Surface *surface, Eina_Matrix3 *ptransform, Ector_Buffer *mask, diff --git a/src/lib/evas/canvas/efl_canvas_vg_object.c b/src/lib/evas/canvas/efl_canvas_vg_object.c index 4ebf00d875..7a8e8a1d45 100644 --- a/src/lib/evas/canvas/efl_canvas_vg_object.c +++ b/src/lib/evas/canvas/efl_canvas_vg_object.c @@ -368,43 +368,6 @@ _evas_vg_render(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd, Efl_Canvas_Vg_Container_Data *cd = efl_data_scope_get(node, EFL_CANVAS_VG_CONTAINER_CLASS); - //Update Mask Image - if (cd->mask_src) - { - Efl_Canvas_Vg_Container_Data *cd2 = - efl_data_scope_get(cd->mask_src, EFL_CANVAS_VG_CONTAINER_CLASS); - - if (cd2->mask.buffer && cd2->mask.dirty) - { - Ector_Surface *ector = evas_ector_get(obj->layer->evas); - if (!ector) return; - - ENFN->ector_end(engine, output, context, ector, EINA_FALSE); - - //Need a better approach. - ector_buffer_pixels_set(ector, cd2->mask.pixels, cd2->mask.bound.w, cd2->mask.bound.h, 0, - EFL_GFX_COLORSPACE_ARGB8888, EINA_TRUE); - ector_surface_reference_point_set(ector, -cd2->mask.bound.x, -cd2->mask.bound.y); - - //Draw Mask Image. - Efl_VG *child; - Eina_List *l; - EINA_LIST_FOREACH(cd2->children, l, child) - _evas_vg_render(obj, pd, engine, output, context, child, - clips, EINA_FALSE); - - cd2->mask.dirty = EINA_FALSE; -#if 0 - FILE *fp = fopen("./test.raw", "w+"); - fwrite(cd2->mask.pixels, cd2->mask.bound.w * cd2->mask.bound.h, sizeof(uint32_t), fp); - fclose(fp); - ERR("size = %d x %d", cd2->mask.bound.w, cd2->mask.bound.h); -#endif - //Restore previous ector context - ENFN->ector_begin(engine, output, context, ector, 0, 0, EINA_FALSE, do_async); - } - } - if (cd->mask.target) return; //Don't draw mask itself. Efl_VG *child; @@ -443,13 +406,17 @@ _render_to_buffer(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd buffer_created = EINA_TRUE; } - _evas_vg_render_pre(obj, root, ector, NULL, NULL, 0); - //initialize buffer context = evas_common_draw_context_new(); evas_common_draw_context_set_render_op(context, _EVAS_RENDER_COPY); evas_common_draw_context_set_color(context, 255, 255, 255, 255); + //ector begin - end for drawing mask images. + ENFN->ector_begin(engine, buffer, context, ector, 0, 0, EINA_FALSE, EINA_FALSE); + _evas_vg_render_pre(obj, root, engine, buffer, context, ector, NULL, NULL, 0); + ENFN->ector_end(engine, buffer, context, ector, EINA_FALSE); + + //Actual content drawing ENFN->ector_begin(engine, buffer, context, ector, 0, 0, EINA_TRUE, do_async); //draw on buffer @@ -641,9 +608,10 @@ _efl_canvas_vg_object_render_pre(Evas_Object *eo_obj, } // FIXME: handle damage only on changed renderer. + // FIXME: Move this render_pre to efl_canvas_vg_render() s = evas_ector_get(obj->layer->evas); if (pd->root && s) - _evas_vg_render_pre(obj, pd->root, s, NULL, NULL, 0); + _evas_vg_render_pre(obj, pd->root, NULL, NULL, NULL, s, NULL, NULL, 0); /* now figure what changed and add draw rects */ /* if it just became visible or invisible */ diff --git a/src/lib/evas/canvas/efl_canvas_vg_shape.c b/src/lib/evas/canvas/efl_canvas_vg_shape.c index dc671f918b..417641af80 100644 --- a/src/lib/evas/canvas/efl_canvas_vg_shape.c +++ b/src/lib/evas/canvas/efl_canvas_vg_shape.c @@ -75,6 +75,7 @@ static void _efl_canvas_vg_shape_render_pre(Evas_Object_Protected_Data *vg_pd, Efl_VG *obj, Efl_Canvas_Vg_Node_Data *nd, + void *engine, void *output, void *context, Ector_Surface *surface, Eina_Matrix3 *ptransform, Ector_Buffer *mask, @@ -90,9 +91,15 @@ _efl_canvas_vg_shape_render_pre(Evas_Object_Protected_Data *vg_pd, EFL_CANVAS_VG_COMPUTE_MATRIX(ctransform, ptransform, nd); - fill = _evas_vg_render_pre(vg_pd, pd->fill, surface, ctransform, mask, mask_op); - stroke_fill = _evas_vg_render_pre(vg_pd, pd->stroke.fill, surface, ctransform, mask, mask_op); - stroke_marker = _evas_vg_render_pre(vg_pd, pd->stroke.marker, surface, ctransform, mask, mask_op); + fill = _evas_vg_render_pre(vg_pd, pd->fill, + engine, output, context, + surface, ctransform, mask, mask_op); + stroke_fill = _evas_vg_render_pre(vg_pd, pd->stroke.fill, + engine, output, context, + surface, ctransform, mask, mask_op); + stroke_marker = _evas_vg_render_pre(vg_pd, pd->stroke.marker, + engine, output, context, + surface, ctransform, mask, mask_op); if (!nd->renderer) { diff --git a/src/lib/evas/canvas/evas_vg_private.h b/src/lib/evas/canvas/evas_vg_private.h index fa122fa587..904c42506c 100644 --- a/src/lib/evas/canvas/evas_vg_private.h +++ b/src/lib/evas/canvas/evas_vg_private.h @@ -64,7 +64,8 @@ struct _Efl_Canvas_Vg_Node_Data Efl_Canvas_Vg_Object_Data *vd; void (*render_pre)(Evas_Object_Protected_Data *vg_pd, Efl_VG *node, - Efl_Canvas_Vg_Node_Data *nd, Ector_Surface *surface, + Efl_Canvas_Vg_Node_Data *nd, + void *engine, void *output, void *contenxt, Ector_Surface *surface, Eina_Matrix3 *ptransform, Ector_Buffer *mask, int mask_op, void *data); void *data; @@ -84,7 +85,6 @@ typedef struct _Vg_Mask Eina_Rect bound; //Mask boundary Eina_List *target; //Mask target int option; //Mask option - Eina_Bool dirty : 1; //Need to update mask image. } Vg_Mask; struct _Efl_Canvas_Vg_Container_Data @@ -138,11 +138,17 @@ efl_canvas_vg_object_change(Efl_Canvas_Vg_Object_Data *vd) } static inline Efl_Canvas_Vg_Node_Data * -_evas_vg_render_pre(Evas_Object_Protected_Data *vg_pd, Efl_VG *child, Ector_Surface *surface, Eina_Matrix3 *transform, Ector_Buffer *mask, int mask_op) +_evas_vg_render_pre(Evas_Object_Protected_Data *vg_pd, Efl_VG *child, + void *engine, void *output, void *context, + Ector_Surface *surface, + Eina_Matrix3 *transform, + Ector_Buffer *mask, int mask_op) { if (!child) return NULL; Efl_Canvas_Vg_Node_Data *nd = efl_data_scope_get(child, EFL_CANVAS_VG_NODE_CLASS); - if (nd) nd->render_pre(vg_pd, child, nd, surface, transform, mask, mask_op, nd->data); + if (nd) nd->render_pre(vg_pd, child, nd, + engine, output, context, surface, + transform, mask, mask_op, nd->data); return nd; }