forked from enlightenment/efl
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:
parent
c03f272bec
commit
da36a87bb3
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue