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.
This commit is contained in:
Hermet Park 2019-01-28 16:53:42 +09:00
parent c03f272bec
commit da36a87bb3
6 changed files with 77 additions and 53 deletions

View File

@ -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);
}
}

View File

@ -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,

View File

@ -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,

View File

@ -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 */

View File

@ -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)
{

View File

@ -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;
}