From fbe92aa67f18f8c0401cdc6d4440ed512c43b131 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Fri, 7 Dec 2018 19:38:48 +0900 Subject: [PATCH] evas ector: add software implmentation for masking feature. This implementation uses Ector_Buffer to generate mask image from vg container, and pass it to Ector engine. Ector renderer could blend this image as a mask. Yet only vg container works as a mask, we could extend shape to support masking later. Still vector gl drawing is not completed, We use software ector buffer to draw on it. This is on progessing. --- src/lib/ector/ector_private.h | 2 - src/lib/ector/ector_renderer.c | 34 +--- src/lib/ector/ector_renderer.eo | 21 ++- .../software/ector_renderer_software_shape.c | 36 +++- .../software/ector_renderer_software_shape.eo | 1 + .../ector/software/ector_software_buffer.c | 4 +- .../ector/software/ector_software_private.h | 11 +- .../software/ector_software_rasterizer.c | 122 +++++++++++-- src/lib/evas/canvas/efl_canvas_vg_container.c | 163 ++++++++++++++++-- .../evas/canvas/efl_canvas_vg_container.eo | 5 +- .../canvas/efl_canvas_vg_gradient_linear.c | 23 +-- .../canvas/efl_canvas_vg_gradient_radial.c | 21 ++- src/lib/evas/canvas/efl_canvas_vg_node.c | 41 +---- src/lib/evas/canvas/efl_canvas_vg_node.eo | 7 +- src/lib/evas/canvas/efl_canvas_vg_object.c | 102 ++++++----- src/lib/evas/canvas/efl_canvas_vg_shape.c | 32 ++-- src/lib/evas/canvas/evas_vg_private.h | 30 +++- src/lib/evas/include/evas_private.h | 6 +- .../evas/engines/gl_generic/evas_engine.c | 82 +++++++-- .../evas/engines/gl_generic/meson.build | 2 + .../engines/software_generic/evas_engine.c | 26 +-- 21 files changed, 541 insertions(+), 230 deletions(-) diff --git a/src/lib/ector/ector_private.h b/src/lib/ector/ector_private.h index 1f483664e8..8604768e16 100644 --- a/src/lib/ector/ector_private.h +++ b/src/lib/ector/ector_private.h @@ -63,8 +63,6 @@ struct _Ector_Renderer_Data int r, g, b, a; } color; - Ector_Renderer *mask; - Eina_Bool visibility : 1; Eina_Bool finalized : 1; }; diff --git a/src/lib/ector/ector_renderer.c b/src/lib/ector/ector_renderer.c index 1c2026e4da..186e3233ab 100644 --- a/src/lib/ector/ector_renderer.c +++ b/src/lib/ector/ector_renderer.c @@ -127,31 +127,6 @@ _ector_renderer_color_get(const Eo *obj EINA_UNUSED, if (a) *a = pd->color.a; } -static void -_ector_renderer_mask_set(Eo *obj EINA_UNUSED, - Ector_Renderer_Data *pd, - Ector_Renderer *mask) -{ - efl_replace(&pd->mask, mask); -} - -static Ector_Renderer * -_ector_renderer_mask_get(const Eo *obj EINA_UNUSED, - Ector_Renderer_Data *pd) -{ - return pd->mask; -} - -static Eina_Bool -_ector_renderer_prepare(Eo *obj EINA_UNUSED, - Ector_Renderer_Data *pd) -{ - if (pd->mask) - ector_renderer_prepare(pd->mask); - - return EINA_TRUE; -} - static unsigned int _ector_renderer_crc_get(const Eo *obj EINA_UNUSED, Ector_Renderer_Data *pd) @@ -162,9 +137,16 @@ _ector_renderer_crc_get(const Eo *obj EINA_UNUSED, crc = eina_crc((void*) &pd->origin, sizeof(pd->origin), crc, EINA_FALSE); if (pd->m) crc = eina_crc((void*) pd->m, sizeof(Eina_Matrix3), crc, EINA_FALSE); - if (pd->mask) crc = _renderer_crc_get(pd->mask, crc); return crc; } +static void +_ector_renderer_mask_set(Eo *obj EINA_UNUSED, + Ector_Renderer_Data *pd EINA_UNUSED, + Ector_Buffer *mask EINA_UNUSED, + int op EINA_UNUSED) +{ +} + #include "ector_renderer.eo.c" diff --git a/src/lib/ector/ector_renderer.eo b/src/lib/ector/ector_renderer.eo index de669c0cc7..844ec1adaa 100644 --- a/src/lib/ector/ector_renderer.eo +++ b/src/lib/ector/ector_renderer.eo @@ -72,22 +72,21 @@ abstract Ector.Renderer (Efl.Object) a: int; [[The alpha component of the given color.]] } } - @property mask { - [[Rendering mask]] - set { - } - get { - } - values { - mask: Ector.Renderer; [[Rendering mask]] - } - } @property crc { [[Cyclic redundancy check]] get { return: uint; [[CRC value]] } } + @property mask { + [[Set Mask Image to this Renderer]] + set { + } + values { + mask: Ector.Buffer; [[Mask Image Buffer]] + op: int; [[Masking option]] + } + } draw @pure_virtual { [[Actual draw operation]] return: bool; [[$true on success, $false otherwise]] @@ -97,7 +96,7 @@ abstract Ector.Renderer (Efl.Object) @in mul_col: uint; [[Premultiplied color]] } } - prepare { + prepare @pure_virtual { [[Prepare for rendering]] return: bool; [[$true on success, $false otherwise]] } diff --git a/src/lib/ector/software/ector_renderer_software_shape.c b/src/lib/ector/software/ector_renderer_software_shape.c index 6749d5fcb9..396e47283e 100644 --- a/src/lib/ector/software/ector_renderer_software_shape.c +++ b/src/lib/ector/software/ector_renderer_software_shape.c @@ -38,6 +38,9 @@ struct _Ector_Renderer_Software_Shape_Data Shape_Rle_Data *shape_data; Shape_Rle_Data *outline_data; + Ector_Buffer *mask; + int mask_op; + Ector_Software_Shape_Task *task; Eina_Bool done; @@ -223,7 +226,7 @@ static void _outline_transform(Outline *outline, Eina_Matrix3 *m) static Eina_Bool _generate_outline(const Efl_Gfx_Path_Command *cmds, const double *pts, Outline * outline) { - Eina_Bool close_path = EINA_FALSE; + Eina_Bool close_path = EINA_FALSE; for (; *cmds != EFL_GFX_PATH_COMMAND_TYPE_END; cmds++) { switch (*cmds) @@ -661,16 +664,18 @@ _ector_renderer_software_shape_ector_renderer_draw(Eo *obj, x = pd->surface->x + (int)pd->base->origin.x; y = pd->surface->y + (int)pd->base->origin.y; - // fill the span_data structure ector_software_rasterizer_clip_rect_set(pd->surface->rasterizer, clips); ector_software_rasterizer_transform_set(pd->surface->rasterizer, pd->base->m); + // fill the span_data structure if (pd->shape->fill) { ector_renderer_software_op_fill(pd->shape->fill); ector_software_rasterizer_draw_rle_data(pd->surface->rasterizer, x, y, mul_col, op, - pd->shape_data); + pd->shape_data, + pd->mask, + pd->mask_op); } else { @@ -683,16 +688,22 @@ _ector_renderer_software_shape_ector_renderer_draw(Eo *obj, pd->base->color.a); ector_software_rasterizer_draw_rle_data(pd->surface->rasterizer, x, y, mul_col, op, - pd->shape_data); + pd->shape_data, + pd->mask, + pd->mask_op); } } + if (!pd->outline_data) return EINA_TRUE; + if (pd->shape->stroke.fill) { ector_renderer_software_op_fill(pd->shape->stroke.fill); ector_software_rasterizer_draw_rle_data(pd->surface->rasterizer, x, y, mul_col, op, - pd->outline_data); + pd->outline_data, + pd->mask, + pd->mask_op); } else { @@ -705,7 +716,9 @@ _ector_renderer_software_shape_ector_renderer_draw(Eo *obj, pd->public_shape->stroke.color.a); ector_software_rasterizer_draw_rle_data(pd->surface->rasterizer, x, y, mul_col, op, - pd->outline_data); + pd->outline_data, + pd->mask, + pd->mask_op); } } @@ -831,4 +844,15 @@ _ector_renderer_software_shape_ector_renderer_crc_get(const Eo *obj, return crc; } +static void +_ector_renderer_software_shape_ector_renderer_mask_set(Eo *obj EINA_UNUSED, + Ector_Renderer_Software_Shape_Data *pd, + Ector_Buffer *mask, + int op) +{ + //Use ref/unref. + pd->mask = mask; + pd->mask_op = op; +} + #include "ector_renderer_software_shape.eo.c" diff --git a/src/lib/ector/software/ector_renderer_software_shape.eo b/src/lib/ector/software/ector_renderer_software_shape.eo index 97b15ca153..abe8344f3f 100644 --- a/src/lib/ector/software/ector_renderer_software_shape.eo +++ b/src/lib/ector/software/ector_renderer_software_shape.eo @@ -6,6 +6,7 @@ class Ector.Renderer.Software.Shape (Ector.Renderer.Software, Ector.Renderer.Sha Ector.Renderer.prepare; Ector.Renderer.draw; Ector.Renderer.Software.op_fill; + Ector.Renderer.mask { set; } Ector.Renderer.crc { get; } Efl.Gfx.Path.path { set; } Efl.Object.constructor; diff --git a/src/lib/ector/software/ector_software_buffer.c b/src/lib/ector/software/ector_software_buffer.c index e8981281f5..e7d288e1e1 100644 --- a/src/lib/ector/software/ector_software_buffer.c +++ b/src/lib/ector/software/ector_software_buffer.c @@ -76,8 +76,8 @@ _ector_software_buffer_base_ector_buffer_pixels_set(Eo *obj, Ector_Software_Buff { unsigned pxs; - if (pd->generic->immutable) - fail("This buffer is immutable."); + //if (pd->generic->immutable) +// fail("This buffer is immutable."); if (pd->internal.maps) fail("Can not call pixels_set when the buffer is mapped."); diff --git a/src/lib/ector/software/ector_software_private.h b/src/lib/ector/software/ector_software_private.h index dad1f9948c..34ea0038b7 100644 --- a/src/lib/ector/software/ector_software_private.h +++ b/src/lib/ector/software/ector_software_private.h @@ -82,9 +82,11 @@ typedef struct _Span_Data int offx, offy; Clip_Data clip; + Ector_Software_Buffer_Base_Data *mask; + int mask_op; Eina_Matrix3 inv; Span_Data_Type type; - Eina_Bool fast_matrix ; + Eina_Bool fast_matrix; uint32_t mul_col; Efl_Gfx_Render_Op op; union { @@ -129,7 +131,12 @@ void ector_software_rasterizer_clip_shape_set(Software_Rasterizer *rasterizer, S Shape_Rle_Data * ector_software_rasterizer_generate_rle_data(Ector_Software_Thread *thread, Software_Rasterizer *rasterizer, SW_FT_Outline *outline); Shape_Rle_Data * ector_software_rasterizer_generate_stroke_rle_data(Ector_Software_Thread *thread, Software_Rasterizer *rasterizer, SW_FT_Outline *outline, Eina_Bool closePath); -void ector_software_rasterizer_draw_rle_data(Software_Rasterizer *rasterizer, int x, int y, uint32_t mul_col, Efl_Gfx_Render_Op op, Shape_Rle_Data* rle); +void ector_software_rasterizer_draw_rle_data(Software_Rasterizer *rasterizer, + int x, int y, uint32_t mul_col, + Efl_Gfx_Render_Op op, + Shape_Rle_Data* rle, + Ector_Buffer *mask, + int mask_op); void ector_software_rasterizer_destroy_rle_data(Shape_Rle_Data *rle); diff --git a/src/lib/ector/software/ector_software_rasterizer.c b/src/lib/ector/software/ector_software_rasterizer.c index 25169be790..7a03bb69f2 100644 --- a/src/lib/ector/software/ector_software_rasterizer.c +++ b/src/lib/ector/software/ector_software_rasterizer.c @@ -14,22 +14,100 @@ static void _blend_color_argb(int count, const SW_FT_Span *spans, void *user_data) { - RGBA_Comp_Func_Solid comp_func; - Span_Data *data = (Span_Data *)(user_data); + Span_Data *sd = user_data; uint32_t color, *buffer, *target; - const int pix_stride = data->raster_buffer->stride / 4; + const int pix_stride = sd->raster_buffer->stride / 4; // multiply the color with mul_col if any - color = DRAW_MUL4_SYM(data->color, data->mul_col); - comp_func = efl_draw_func_solid_span_get(data->op, color); + color = DRAW_MUL4_SYM(sd->color, sd->mul_col); + RGBA_Comp_Func_Solid comp_func = efl_draw_func_solid_span_get(sd->op, color); // move to the offset location - buffer = data->raster_buffer->pixels.u32 + ((pix_stride * data->offy) + data->offx); + buffer = sd->raster_buffer->pixels.u32 + ((pix_stride * sd->offy) + sd->offx); + + while (count--) + { + target = buffer + ((pix_stride * spans->y) + spans->x); + comp_func(target, spans->len, color, spans->coverage); + ++spans; + } +} + +static void +_blend_color_argb_with_maskA(int count, const SW_FT_Span *spans, void *user_data) +{ + Span_Data *sd = user_data; + const int pix_stride = sd->raster_buffer->stride / 4; + Ector_Software_Buffer_Base_Data *mask = sd->mask; + + // multiply the color with mul_col if any + uint32_t color = DRAW_MUL4_SYM(sd->color, sd->mul_col); + RGBA_Comp_Func_Solid comp_func = efl_draw_func_solid_span_get(sd->op, color); + + // move to the offset location + uint32_t *buffer = + sd->raster_buffer->pixels.u32 + ((pix_stride * sd->offy) + sd->offx); + uint32_t *mbuffer = mask->pixels.u32; while (count--) { - target = buffer + ((pix_stride * spans->y) + spans->x); - comp_func(target, spans->len, color, spans->coverage); + uint32_t *target = buffer + ((pix_stride * spans->y) + spans->x); + uint32_t *mtarget = + mbuffer + ((mask->generic->w * spans->y) + spans->x); + uint32_t *temp = alloca(sizeof(uint32_t) * spans->len); + memset(temp, 0x00, sizeof(uint32_t) * spans->len); + comp_func(temp, spans->len, color, spans->coverage); + + //masking + for (int i = 0; i < spans->len; i++) + { + *temp = draw_mul_256(((*mtarget)>>24), *temp); + int alpha = 255 - ((*temp) >> 24); + *target = *temp + draw_mul_256(alpha, *target); + ++temp; + ++mtarget; + ++target; + } + ++spans; + } +} + +static void +_blend_color_argb_with_maskInvA(int count, const SW_FT_Span *spans, void *user_data) +{ + Span_Data *sd = user_data; + const int pix_stride = sd->raster_buffer->stride / 4; + Ector_Software_Buffer_Base_Data *mask = sd->mask; + + // multiply the color with mul_col if any + uint32_t color = DRAW_MUL4_SYM(sd->color, sd->mul_col); + RGBA_Comp_Func_Solid comp_func = efl_draw_func_solid_span_get(sd->op, color); + + // move to the offset location + uint32_t *buffer = + sd->raster_buffer->pixels.u32 + ((pix_stride * sd->offy) + sd->offx); + uint32_t *mbuffer = mask->pixels.u32; + + while (count--) + { + uint32_t *target = buffer + ((pix_stride * spans->y) + spans->x); + uint32_t *mtarget = + mbuffer + ((mask->generic->w * spans->y) + spans->x); + uint32_t *temp = alloca(sizeof(uint32_t) * spans->len); + memset(temp, 0x00, sizeof(uint32_t) * spans->len); + comp_func(temp, spans->len, color, spans->coverage); + + //masking + for (int i = 0; i < spans->len; i++) + { + if (*mtarget) + *temp = draw_mul_256((255 - ((*mtarget)>>24)), *temp); + int alpha = 255 - ((*temp) >> 24); + *target = *temp + draw_mul_256(alpha, *target); + ++temp; + ++mtarget; + ++target; + } ++spans; } } @@ -267,13 +345,24 @@ _span_fill_clipPath(int span_count, const SW_FT_Span *spans, void *user_data) static void _adjust_span_fill_methods(Span_Data *spdata) { + //Blending Function switch(spdata->type) { case None: - spdata->unclipped_blend = 0; + spdata->unclipped_blend = NULL; break; case Solid: - spdata->unclipped_blend = &_blend_color_argb; + { + if (spdata->mask) + { + if (spdata->mask_op == 2) + spdata->unclipped_blend = &_blend_color_argb_with_maskInvA; + else + spdata->unclipped_blend = &_blend_color_argb_with_maskA; + } + else + spdata->unclipped_blend = &_blend_color_argb; + } break; case LinearGradient: case RadialGradient: @@ -539,17 +628,22 @@ ector_software_rasterizer_radial_gradient_set(Software_Rasterizer *rasterizer, rasterizer->fill_data.type = RadialGradient; } -void ector_software_rasterizer_draw_rle_data(Software_Rasterizer *rasterizer, - int x, int y, uint32_t mul_col, - Efl_Gfx_Render_Op op, Shape_Rle_Data* rle) +void +ector_software_rasterizer_draw_rle_data(Software_Rasterizer *rasterizer, + int x, int y, uint32_t mul_col, + Efl_Gfx_Render_Op op, Shape_Rle_Data* rle, + Ector_Buffer *mask, + int mask_op) { - // check for NULL rle data if (!rle) return; rasterizer->fill_data.offx = x; rasterizer->fill_data.offy = y; rasterizer->fill_data.mul_col = mul_col; rasterizer->fill_data.op = op; + rasterizer->fill_data.mask = + mask ? efl_data_scope_get(mask, ECTOR_SOFTWARE_BUFFER_BASE_MIXIN) : NULL; + rasterizer->fill_data.mask_op = mask_op; _setup_span_fill_matrix(rasterizer); _adjust_span_fill_methods(&rasterizer->fill_data); diff --git a/src/lib/evas/canvas/efl_canvas_vg_container.c b/src/lib/evas/canvas/efl_canvas_vg_container.c index ccb8bfbf76..addbf0cbc9 100644 --- a/src/lib/evas/canvas/efl_canvas_vg_container.c +++ b/src/lib/evas/canvas/efl_canvas_vg_container.c @@ -22,17 +22,75 @@ _invalidate_cb(void *data EINA_UNUSED, const Efl_Event *event) efl_unref(child); } +static Ector_Buffer * +_prepare_mask(Evas_Object_Protected_Data *obj, //vector object + Efl_Canvas_Vg_Node* mask_obj, + Ector_Surface *surface, + Eina_Matrix3 *ptransform, + Ector_Buffer *mask, + int mask_op) +{ + Efl_Canvas_Vg_Container_Data *pd = efl_data_scope_get(mask_obj, MY_CLASS); + Efl_Canvas_Vg_Node_Data *nd = + efl_data_scope_get(mask_obj, EFL_CANVAS_VG_NODE_CLASS); + if (nd->flags == EFL_GFX_CHANGE_FLAG_NONE) return pd->mask.buffer; + + //1. Mask Size + Eina_Rect mbound; + mbound.x = 0; + mbound.y = 0; + mbound.w = obj->cur->geometry.w; + mbound.h = obj->cur->geometry.h; + +// efl_gfx_path_bounds_get(mask, &mbound); + + //2. Reusable ector buffer? + if (!pd->mask.buffer || (pd->mask.bound.w != mbound.w) || + (pd->mask.bound.h != mbound.h)) + { + if (pd->mask.pixels) free(pd->mask.pixels); + if (pd->mask.buffer) efl_unref(pd->mask.buffer); + pd->mask.pixels = calloc(sizeof(uint32_t), mbound.w * mbound.h); + pd->mask.buffer = ENFN->ector_buffer_new(ENC, obj->layer->evas->evas, + mbound.w, mbound.h, + EFL_GFX_COLORSPACE_ARGB8888, + ECTOR_BUFFER_FLAG_DRAWABLE | + ECTOR_BUFFER_FLAG_CPU_READABLE | + ECTOR_BUFFER_FLAG_CPU_WRITABLE); + ector_buffer_pixels_set(pd->mask.buffer, pd->mask.pixels, + mbound.w, mbound.h, 0, + EFL_GFX_COLORSPACE_ARGB8888, EINA_TRUE); + pd->mask.bound.w = mbound.w; + pd->mask.bound.h = mbound.h; + pd->mask.vg_pd = obj; + } + + pd->mask.bound.x = mbound.x; + pd->mask.bound.y = mbound.y; + + 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, surface, ptransform, mask, mask_op); + + return pd->mask.buffer; +} + static void -_efl_canvas_vg_container_render_pre(Eo *obj EINA_UNUSED, - Eina_Matrix3 *parent, - Ector_Surface *s, - void *data, - Efl_Canvas_Vg_Node_Data *nd) +_efl_canvas_vg_container_render_pre(Evas_Object_Protected_Data *vg_pd, + Efl_VG *obj EINA_UNUSED, + Efl_Canvas_Vg_Node_Data *nd, + Ector_Surface *surface, + Eina_Matrix3 *ptransform, + Ector_Buffer *mask, + int mask_op, + void *data) { Efl_Canvas_Vg_Container_Data *pd = data; Eina_List *l; - Eo *child; - Efl_Canvas_Vg_Node_Data *child_nd; + Efl_VG *child; Efl_Gfx_Change_Flag flag; if (nd->flags == EFL_GFX_CHANGE_FLAG_NONE) return; @@ -40,20 +98,37 @@ _efl_canvas_vg_container_render_pre(Eo *obj EINA_UNUSED, flag = nd->flags; nd->flags = EFL_GFX_CHANGE_FLAG_NONE; - EFL_CANVAS_VG_COMPUTE_MATRIX(current, parent, nd); + EFL_CANVAS_VG_COMPUTE_MATRIX(ctransform, ptransform, nd); + + //Container may have mask source. + if (pd->mask_src) + { + mask = _prepare_mask(vg_pd, pd->mask_src, surface, ptransform, mask, + mask_op); + mask_op = pd->mask.option; + } EINA_LIST_FOREACH(pd->children, l, child) { + //Don't need to update mask nodes. + if (efl_isa(child, MY_CLASS)) + { + Efl_Canvas_Vg_Container_Data *child_cd = + efl_data_scope_get(child, MY_CLASS); + if (child_cd->mask.target) continue; + } + //Skip Gradients. they will be updated by Shape. if (efl_isa(child, EFL_CANVAS_VG_GRADIENT_CLASS)) continue; + Efl_Canvas_Vg_Node_Data *child_nd = + efl_data_scope_get(child, EFL_CANVAS_VG_NODE_CLASS); + if (flag & EFL_GFX_CHANGE_FLAG_MATRIX) - { - child_nd = efl_data_scope_get(child, EFL_CANVAS_VG_NODE_CLASS); - child_nd->flags |= EFL_GFX_CHANGE_FLAG_MATRIX; - } - _evas_vg_render_pre(child, s, current); + child_nd->flags |= EFL_GFX_CHANGE_FLAG_MATRIX; + + _evas_vg_render_pre(vg_pd, child, surface, ctransform, mask, mask_op); } } @@ -77,16 +152,23 @@ _efl_canvas_vg_container_efl_object_constructor(Eo *obj, static void _efl_canvas_vg_container_efl_object_destructor(Eo *obj, - Efl_Canvas_Vg_Container_Data *pd EINA_UNUSED) + Efl_Canvas_Vg_Container_Data *pd) { - efl_destructor(efl_super(obj, MY_CLASS)); + //Destroy mask surface + if (pd->mask.buffer) efl_unref(pd->mask.buffer); + if (pd->mask.pixels) free(pd->mask.pixels); + + efl_unref(pd->mask_src); + eina_list_free(pd->mask.target); eina_hash_free(pd->names); + + efl_destructor(efl_super(obj, MY_CLASS)); } static void _efl_canvas_vg_container_efl_gfx_path_bounds_get(const Eo *obj EINA_UNUSED, - Efl_Canvas_Vg_Container_Data *pd, - Eina_Rect *r) + Efl_Canvas_Vg_Container_Data *pd, + Eina_Rect *r) { Eina_Rect s; Eina_Bool first = EINA_TRUE; @@ -162,12 +244,51 @@ _efl_canvas_vg_container_efl_gfx_path_interpolate(Eo *obj, Efl_Canvas_Vg_Contain if (!r) break; } + //Interpolates Mask + Efl_Canvas_Vg_Container_Data *fromd = efl_data_scope_get(from, MY_CLASS); + Efl_Canvas_Vg_Container_Data *tod = efl_data_scope_get(to, MY_CLASS); + + if (fromd->mask_src && tod->mask_src && pd->mask_src) + { + if (!efl_gfx_path_interpolate(pd->mask_src, + fromd->mask_src, tod->mask_src, pos_map)) + return EINA_FALSE; + } + eina_iterator_free(from_it); eina_iterator_free(to_it); return r; } +static void +_efl_canvas_vg_container_efl_canvas_vg_node_mask_set(Eo *obj, + Efl_Canvas_Vg_Container_Data *pd, + Efl_Canvas_Vg_Node *mask, + int op) +{ + if (pd->mask_src == mask) return; + + EINA_SAFETY_ON_FALSE_RETURN(efl_isa(mask, MY_CLASS)); + + if (pd->mask_src) + { + Efl_Canvas_Vg_Container_Data *pd2 = + efl_data_scope_get(pd->mask_src, MY_CLASS); + pd2->mask.target = eina_list_remove(pd2->mask.target, obj); + } + + if (mask) + { + Efl_Canvas_Vg_Container_Data *pd2 = efl_data_scope_get(mask, MY_CLASS); + pd2->mask.target = eina_list_append(pd2->mask.target, obj); + } + + pd->mask.option = op; + efl_replace(&pd->mask_src, mask); + _efl_canvas_vg_node_changed(obj); +} + EOLIAN static Efl_VG * _efl_canvas_vg_container_efl_duplicate_duplicate(const Eo *obj, Efl_Canvas_Vg_Container_Data *pd) @@ -180,6 +301,14 @@ _efl_canvas_vg_container_efl_duplicate_duplicate(const Eo *obj, efl_event_callback_add(container, EFL_EVENT_INVALIDATE, _invalidate_cb, NULL); efl_parent_set(container, efl_parent_get(obj)); + //Copy Mask + if (pd->mask_src) + { + Eo * mask_src = efl_duplicate(pd->mask_src); + efl_parent_set(mask_src, container); + efl_canvas_vg_node_mask_set(container, mask_src, pd->mask.option); + } + //Copy Children EINA_LIST_FOREACH(pd->children, l, child) { diff --git a/src/lib/evas/canvas/efl_canvas_vg_container.eo b/src/lib/evas/canvas/efl_canvas_vg_container.eo index f89d584d86..4060441d44 100644 --- a/src/lib/evas/canvas/efl_canvas_vg_container.eo +++ b/src/lib/evas/canvas/efl_canvas_vg_container.eo @@ -4,14 +4,14 @@ class Efl.Canvas.Vg.Container (Efl.Canvas.Vg.Node) legacy_prefix: evas_vg_container; methods { child_get { - [[Get child of container]] + [[Get child of container]] params { @in name: string; [[Child node name]] } return: Efl.Canvas.Vg.Node; [[Child object]] } children_get { - [[Get all children of container]] + [[Get all children of container]] return: iterator @owned @warn_unused; [[Iterator to children]] } } @@ -21,5 +21,6 @@ class Efl.Canvas.Vg.Container (Efl.Canvas.Vg.Node) Efl.Gfx.Path.bounds_get; Efl.Gfx.Path.interpolate; Efl.Duplicate.duplicate; + Efl.Canvas.Vg.Node.mask { set; } } } 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 391f9c81b5..fa35d29153 100644 --- a/src/lib/evas/canvas/efl_canvas_vg_gradient_linear.c +++ b/src/lib/evas/canvas/efl_canvas_vg_gradient_linear.c @@ -56,30 +56,33 @@ _efl_canvas_vg_gradient_linear_efl_gfx_gradient_linear_end_get(const Eo *obj EIN } static void -_efl_canvas_vg_gradient_linear_render_pre(Eo *obj, - Eina_Matrix3 *parent, - Ector_Surface *s, - void *data, - Efl_Canvas_Vg_Node_Data *nd) +_efl_canvas_vg_gradient_linear_render_pre(Evas_Object_Protected_Data *vg_pd EINA_UNUSED, + Efl_VG *obj, + Efl_Canvas_Vg_Node_Data *nd, + Ector_Surface *surface, + Eina_Matrix3 *ptransform, + Ector_Buffer *mask, + int mask_op, + void *data) { Efl_Canvas_Vg_Gradient_Linear_Data *pd = data; Efl_Canvas_Vg_Gradient_Data *gd; - if (nd->flags == EFL_GFX_CHANGE_FLAG_NONE) return ; + if (nd->flags == EFL_GFX_CHANGE_FLAG_NONE) return; nd->flags = EFL_GFX_CHANGE_FLAG_NONE; gd = efl_data_scope_get(obj, EFL_CANVAS_VG_GRADIENT_CLASS); - EFL_CANVAS_VG_COMPUTE_MATRIX(current, parent, nd); + EFL_CANVAS_VG_COMPUTE_MATRIX(ctransform, ptransform, nd); if (!nd->renderer) { efl_domain_current_push(EFL_ID_DOMAIN_SHARED); - nd->renderer = ector_surface_renderer_factory_new(s, ECTOR_RENDERER_GRADIENT_LINEAR_MIXIN); + nd->renderer = ector_surface_renderer_factory_new(surface, ECTOR_RENDERER_GRADIENT_LINEAR_MIXIN); efl_domain_current_pop(); } - ector_renderer_transformation_set(nd->renderer, current); + ector_renderer_transformation_set(nd->renderer, ctransform); ector_renderer_origin_set(nd->renderer, nd->x, nd->y); ector_renderer_color_set(nd->renderer, nd->r, nd->g, nd->b, nd->a); ector_renderer_visibility_set(nd->renderer, nd->visibility); @@ -87,8 +90,8 @@ _efl_canvas_vg_gradient_linear_render_pre(Eo *obj, efl_gfx_gradient_spread_set(nd->renderer, gd->spread); efl_gfx_gradient_linear_start_set(nd->renderer, pd->start.x, pd->start.y); efl_gfx_gradient_linear_end_set(nd->renderer, pd->end.x, pd->end.y); - ector_renderer_prepare(nd->renderer); + ector_renderer_mask_set(nd->renderer, mask, mask_op); } static Eo * 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 6a72b7e4da..9ff537e2ed 100644 --- a/src/lib/evas/canvas/efl_canvas_vg_gradient_radial.c +++ b/src/lib/evas/canvas/efl_canvas_vg_gradient_radial.c @@ -72,11 +72,14 @@ _efl_canvas_vg_gradient_radial_efl_gfx_gradient_radial_focal_get(const Eo *obj E } static void -_efl_canvas_vg_gradient_radial_render_pre(Eo *obj, - Eina_Matrix3 *parent, - Ector_Surface *s, - void *data, - Efl_Canvas_Vg_Node_Data *nd) +_efl_canvas_vg_gradient_radial_render_pre(Evas_Object_Protected_Data *vg_pd EINA_UNUSED, + Efl_VG *obj, + Efl_Canvas_Vg_Node_Data *nd, + Ector_Surface *surface, + Eina_Matrix3 *ptransform, + Ector_Buffer *mask, + int mask_op, + void *data) { Efl_Canvas_Vg_Gradient_Radial_Data *pd = data; Efl_Canvas_Vg_Gradient_Data *gd; @@ -86,16 +89,16 @@ _efl_canvas_vg_gradient_radial_render_pre(Eo *obj, nd->flags = EFL_GFX_CHANGE_FLAG_NONE; gd = efl_data_scope_get(obj, EFL_CANVAS_VG_GRADIENT_CLASS); - EFL_CANVAS_VG_COMPUTE_MATRIX(current, parent, nd); + EFL_CANVAS_VG_COMPUTE_MATRIX(ctransform, ptransform, nd); if (!nd->renderer) { efl_domain_current_push(EFL_ID_DOMAIN_SHARED); - nd->renderer = ector_surface_renderer_factory_new(s, ECTOR_RENDERER_GRADIENT_RADIAL_MIXIN); + nd->renderer = ector_surface_renderer_factory_new(surface, ECTOR_RENDERER_GRADIENT_RADIAL_MIXIN); efl_domain_current_pop(); } - ector_renderer_transformation_set(nd->renderer, current); + ector_renderer_transformation_set(nd->renderer, ctransform); ector_renderer_origin_set(nd->renderer, nd->x, nd->y); ector_renderer_color_set(nd->renderer, nd->r, nd->g, nd->b, nd->a); ector_renderer_visibility_set(nd->renderer, nd->visibility); @@ -104,8 +107,8 @@ _efl_canvas_vg_gradient_radial_render_pre(Eo *obj, efl_gfx_gradient_radial_center_set(nd->renderer, pd->center.x, pd->center.y); efl_gfx_gradient_radial_focal_set(nd->renderer, pd->focal.x, pd->focal.y); efl_gfx_gradient_radial_radius_set(nd->renderer, pd->radius); - ector_renderer_prepare(nd->renderer); + ector_renderer_mask_set(nd->renderer, mask, mask_op); } static Eo * diff --git a/src/lib/evas/canvas/efl_canvas_vg_node.c b/src/lib/evas/canvas/efl_canvas_vg_node.c index e7ef736528..dc2c4a3a09 100644 --- a/src/lib/evas/canvas/efl_canvas_vg_node.c +++ b/src/lib/evas/canvas/efl_canvas_vg_node.c @@ -65,6 +65,14 @@ _efl_canvas_vg_node_transformation_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Vg_ return pd->m; } +static void +_efl_canvas_vg_node_mask_set(Eo *obj EINA_UNUSED, + Efl_Canvas_Vg_Node_Data *pd EINA_UNUSED, + Efl_Canvas_Vg_Node *mask EINA_UNUSED, + int op EINA_UNUSED) +{ +} + static void _efl_canvas_vg_node_origin_set(Eo *obj, Efl_Canvas_Vg_Node_Data *pd, @@ -166,25 +174,6 @@ _efl_canvas_vg_node_efl_gfx_color_color_get(const Eo *obj EINA_UNUSED, if (a) *a = pd->a; } -static void -_efl_canvas_vg_node_mask_set(Eo *obj EINA_UNUSED, - Efl_Canvas_Vg_Node_Data *pd, - Efl_VG *r) -{ - Efl_VG *tmp = pd->mask; - - pd->mask = efl_ref(r); - efl_unref(tmp); - - _efl_canvas_vg_node_changed(obj); -} - -static Efl_VG* -_efl_canvas_vg_node_mask_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Vg_Node_Data *pd) -{ - return pd->mask; -} - static Eina_Size2D _efl_canvas_vg_node_efl_gfx_entity_size_get(const Eo *obj, Efl_Canvas_Vg_Node_Data *pd EINA_UNUSED) { @@ -711,14 +700,6 @@ _efl_canvas_vg_node_efl_gfx_path_interpolate(Eo *obj, Efl_Canvas_Vg_Node_Data *p pd->visibility = pos_map >= 0.5 ? tod->visibility : fromd->visibility; - //Interpolates Mask - if (fromd->mask && tod->mask && pd->mask) - { - if (!efl_gfx_path_interpolate(pd->mask, - fromd->mask, tod->mask, pos_map)) - return EINA_FALSE; - } - _efl_canvas_vg_node_changed(obj); return EINA_TRUE; @@ -750,12 +731,6 @@ _efl_canvas_vg_node_efl_duplicate_duplicate(const Eo *obj, Efl_Canvas_Vg_Node_Da if (nd->m) memcpy(nd->m, pd->m, sizeof(Eina_Matrix3)); } - if (pd->mask) - { - nd->mask = efl_duplicate(pd->mask); - efl_parent_set(nd->mask, node); - } - nd->x = pd->x; nd->y = pd->y; nd->r = pd->r; diff --git a/src/lib/evas/canvas/efl_canvas_vg_node.eo b/src/lib/evas/canvas/efl_canvas_vg_node.eo index 6b720c2c53..361fe741d7 100644 --- a/src/lib/evas/canvas/efl_canvas_vg_node.eo +++ b/src/lib/evas/canvas/efl_canvas_vg_node.eo @@ -42,13 +42,12 @@ abstract Efl.Canvas.Vg.Node (Efl.Object, Efl.Gfx.Entity, Efl.Gfx.Color, Efl.Gfx. } } @property mask { - [[Vector graphics object mask]] + [[Set Mask Node to this renderer]] set { } - get { - } values { - m: Efl.Canvas.Vg.Node; [[Object mask]] + mask: Efl.Canvas.Vg.Node; [[Mask object]] + op: int; [[Masking Option. Reserved]] } } } diff --git a/src/lib/evas/canvas/efl_canvas_vg_object.c b/src/lib/evas/canvas/efl_canvas_vg_object.c index a227c6bd9f..ac45c6d791 100644 --- a/src/lib/evas/canvas/efl_canvas_vg_object.c +++ b/src/lib/evas/canvas/efl_canvas_vg_object.c @@ -371,37 +371,71 @@ _efl_canvas_vg_object_efl_object_finalize(Eo *obj, Efl_Canvas_Vg_Object_Data *pd static void _evas_vg_render(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd, - void *engine, void *output, void *context, void *surface, Efl_VG *n, + void *engine, void *output, void *context, Efl_VG *node, Eina_Array *clips, Eina_Bool do_async) { - if (efl_isa(n, EFL_CANVAS_VG_CONTAINER_CLASS)) + if (efl_isa(node, EFL_CANVAS_VG_CONTAINER_CLASS)) { - Efl_Canvas_Vg_Container_Data *vc; + 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; Eina_List *l; - vc = efl_data_scope_get(n, EFL_CANVAS_VG_CONTAINER_CLASS); - - EINA_LIST_FOREACH(vc->children, l, child) - _evas_vg_render(obj, pd, - engine, output, context, surface, child, - clips, do_async); + EINA_LIST_FOREACH(cd->children, l, child) + _evas_vg_render(obj, pd, engine, output, context, child, clips, do_async); } else { - Efl_Canvas_Vg_Node_Data *nd; - nd = efl_data_scope_get(n, EFL_CANVAS_VG_NODE_CLASS); - obj->layer->evas->engine.func->ector_renderer_draw(engine, output, context, surface, nd->renderer, clips, do_async); - if (do_async) - eina_array_push(&pd->cleanup, efl_ref(nd->renderer)); + 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, clips, do_async); + if (do_async) eina_array_push(&pd->cleanup, efl_ref(nd->renderer)); } } //renders a vg_tree to an offscreen buffer and push it to the cache. static void * _render_to_buffer(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd, - void *engine, void *surface, - Efl_VG *root, int w, int h, void *key, + void *engine, Efl_VG *root, int w, int h, void *key, void *buffer, Eina_Bool do_async) { Ector_Surface *ector; @@ -420,29 +454,24 @@ _render_to_buffer(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd buffer_created = EINA_TRUE; } - _evas_vg_render_pre(root, ector, NULL); + _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); - obj->layer->evas->engine.func->ector_begin(engine, buffer, - context, surface, - ector, - 0, 0, - do_async); + + ENFN->ector_begin(engine, buffer, context, ector, 0, 0, EINA_TRUE, do_async); + //draw on buffer _evas_vg_render(obj, pd, engine, buffer, - context, surface, - root, NULL, + context, root, + NULL, do_async); - obj->layer->evas->engine.func->image_dirty_region(engine, buffer, 0, 0, w, h); - obj->layer->evas->engine.func->ector_end(engine, buffer, - context, surface, - ector,do_async); - + ENFN->image_dirty_region(engine, buffer, 0, 0, w, h); + ENFN->ector_end(engine, buffer, context, ector, do_async); evas_common_draw_context_free(context); if (buffer_created) @@ -498,7 +527,7 @@ _cache_vg_entry_render(Evas_Object_Protected_Data *obj, void *buffer = ENFN->ector_surface_cache_get(engine, root); if (!buffer) - buffer = _render_to_buffer(obj, pd, engine, surface, root, w, h, root, NULL, + buffer = _render_to_buffer(obj, pd, engine, root, w, h, root, NULL, do_async); else //cache reference was increased when we get the cache. @@ -534,20 +563,15 @@ _user_vg_entry_render(Evas_Object_Protected_Data *obj, if (!buffer) { // render to the buffer - buffer = _render_to_buffer(obj, pd, - engine, surface, - user_entry->root, - w, h, - user_entry, - buffer, + buffer = _render_to_buffer(obj, pd, engine, user_entry->root, + w, h, user_entry, buffer, do_async); } else { // render to the buffer if (pd->changed) - buffer = _render_to_buffer(obj, pd, - engine, surface, + buffer = _render_to_buffer(obj, pd, engine, user_entry->root, w, h, user_entry, @@ -630,7 +654,7 @@ _efl_canvas_vg_object_render_pre(Evas_Object *eo_obj, // FIXME: handle damage only on changed renderer. s = evas_ector_get(obj->layer->evas); if (pd->root && s) - _evas_vg_render_pre(pd->root, s, NULL); + _evas_vg_render_pre(obj, pd->root, 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 d55009afcb..106efeccfb 100644 --- a/src/lib/evas/canvas/efl_canvas_vg_shape.c +++ b/src/lib/evas/canvas/efl_canvas_vg_shape.c @@ -78,43 +78,45 @@ _efl_canvas_vg_shape_stroke_marker_get(const Eo *obj EINA_UNUSED, } static void -_efl_canvas_vg_shape_render_pre(Eo *obj EINA_UNUSED, - Eina_Matrix3 *parent, - Ector_Surface *s, - void *data, - Efl_Canvas_Vg_Node_Data *nd) +_efl_canvas_vg_shape_render_pre(Evas_Object_Protected_Data *vg_pd, + Efl_VG *obj, + Efl_Canvas_Vg_Node_Data *nd, + Ector_Surface *surface, + Eina_Matrix3 *ptransform, + Ector_Buffer *mask, + int mask_op, + void *data) { Efl_Canvas_Vg_Shape_Data *pd = data; - Efl_Canvas_Vg_Node_Data *fill, *stroke_fill, *stroke_marker, *mask; + Efl_Canvas_Vg_Node_Data *fill, *stroke_fill, *stroke_marker; if (nd->flags == EFL_GFX_CHANGE_FLAG_NONE) return; nd->flags = EFL_GFX_CHANGE_FLAG_NONE; - EFL_CANVAS_VG_COMPUTE_MATRIX(current, parent, nd); + EFL_CANVAS_VG_COMPUTE_MATRIX(ctransform, ptransform, nd); - fill = _evas_vg_render_pre(pd->fill, s, current); - stroke_fill = _evas_vg_render_pre(pd->stroke.fill, s, current); - stroke_marker = _evas_vg_render_pre(pd->stroke.marker, s, current); - mask = _evas_vg_render_pre(nd->mask, s, current); + 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); if (!nd->renderer) { efl_domain_current_push(EFL_ID_DOMAIN_SHARED); - nd->renderer = ector_surface_renderer_factory_new(s, ECTOR_RENDERER_SHAPE_MIXIN); + nd->renderer = ector_surface_renderer_factory_new(surface, ECTOR_RENDERER_SHAPE_MIXIN); efl_domain_current_pop(); } - - ector_renderer_transformation_set(nd->renderer, current); + ector_renderer_transformation_set(nd->renderer, ctransform); ector_renderer_origin_set(nd->renderer, nd->x, nd->y); ector_renderer_color_set(nd->renderer, nd->r, nd->g, nd->b, nd->a); ector_renderer_visibility_set(nd->renderer, nd->visibility); - ector_renderer_mask_set(nd->renderer, mask ? mask->renderer : NULL); ector_renderer_shape_fill_set(nd->renderer, fill ? fill->renderer : NULL); ector_renderer_shape_stroke_fill_set(nd->renderer, stroke_fill ? stroke_fill->renderer : NULL); ector_renderer_shape_stroke_marker_set(nd->renderer, stroke_marker ? stroke_marker->renderer : NULL); efl_gfx_path_copy_from(nd->renderer, obj); ector_renderer_prepare(nd->renderer); + ector_renderer_mask_set(nd->renderer, mask, mask_op); + } static Eo * diff --git a/src/lib/evas/canvas/evas_vg_private.h b/src/lib/evas/canvas/evas_vg_private.h index a4d11d06cb..10b8b49b25 100644 --- a/src/lib/evas/canvas/evas_vg_private.h +++ b/src/lib/evas/canvas/evas_vg_private.h @@ -57,12 +57,13 @@ struct _Efl_Canvas_Vg_Node_Data Eina_Matrix3 *m; Efl_Canvas_Vg_Interpolation *intp; - Efl_Canvas_Vg_Node *mask; Ector_Renderer *renderer; Efl_VG *vg_obj; //...Not necessary!! - void (*render_pre)(Eo *obj, Eina_Matrix3 *parent, Ector_Surface *s, void *data, Efl_Canvas_Vg_Node_Data *nd); + void (*render_pre)(Evas_Object_Protected_Data *vg_pd, Efl_VG *node, + Efl_Canvas_Vg_Node_Data *nd, Ector_Surface *surface, + Eina_Matrix3 *ptransform, Ector_Buffer *mask, int mask_op, void *data); void *data; double x, y; @@ -74,11 +75,25 @@ struct _Efl_Canvas_Vg_Node_Data Eina_Bool parenting : 1; }; +typedef struct _Vg_Mask +{ + Evas_Object_Protected_Data *vg_pd; //Vector Object (for accessing backend engine) + Ector_Buffer *buffer; //Mask Ector Buffer + void *pixels; //Mask pixel buffer (actual data) + 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 { Eina_List *children; - Eina_Hash *names; + + //Masking feature. + Efl_Canvas_Vg_Node *mask_src; //Mask Source + Vg_Mask mask; //Mask source data }; struct _Efl_Canvas_Vg_Gradient_Data @@ -112,13 +127,12 @@ Eina_Bool evas_cache_vg_entry_file_save(Vg_Cache_Entry *vg_ent void efl_canvas_vg_node_root_set(Efl_VG *node, Efl_VG *vg_obj); static inline Efl_Canvas_Vg_Node_Data * -_evas_vg_render_pre(Efl_VG *child, Ector_Surface *s, Eina_Matrix3 *m) +_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) { if (!child) return NULL; - - Efl_Canvas_Vg_Node_Data *child_nd = efl_data_scope_get(child, EFL_CANVAS_VG_NODE_CLASS); - if (child_nd) child_nd->render_pre(child, m, s, child_nd->data, child_nd); - return child_nd; + 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); + return nd; } static inline void diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index 34dffee36b..3d5020fdd6 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -1482,9 +1482,9 @@ struct _Evas_Func void (*ector_destroy) (void *engine, Ector_Surface *surface); Ector_Buffer *(*ector_buffer_wrap) (void *engine, Evas *e, void *engine_image); Ector_Buffer *(*ector_buffer_new) (void *engine, Evas *e, int width, int height, Efl_Gfx_Colorspace cspace, Ector_Buffer_Flag flags); - void (*ector_begin) (void *engine, void *output, void *context, void *surface, Ector_Surface *ector, int x, int y, Eina_Bool do_async); - void (*ector_renderer_draw) (void *engine, void *output, void *context, void *surface, Ector_Renderer *r, Eina_Array *clips, Eina_Bool do_async); - void (*ector_end) (void *engine, void *output, void *context, void *surface, Ector_Surface *ector, Eina_Bool do_async); + void (*ector_begin) (void *engine, void *output, void *context, Ector_Surface *ector, int x, int y, Eina_Bool clear, Eina_Bool do_async); + void (*ector_renderer_draw) (void *engine, void *output, void *context, Ector_Renderer *r, Eina_Array *clips, Eina_Bool do_async); + void (*ector_end) (void *engine, void *output, void *context, Ector_Surface *ector, Eina_Bool do_async); void *(*ector_surface_create) (void *engine, int w, int h, int *error); void (*ector_surface_destroy) (void *engine, void *surface); diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c b/src/modules/evas/engines/gl_generic/evas_engine.c index 5d0771a058..96b0e41a94 100644 --- a/src/modules/evas/engines/gl_generic/evas_engine.c +++ b/src/modules/evas/engines/gl_generic/evas_engine.c @@ -2509,25 +2509,72 @@ eng_ector_buffer_wrap(void *engine EINA_UNUSED, Evas *evas, void *engine_image) evas_ector_buffer_engine_image_set(efl_added, evas, im)); } +//FIXME: Currently Ector GL doens't work properly. Use software instead. +#include "../software_generic/evas_ector_software.h" + static Ector_Buffer * eng_ector_buffer_new(void *engine, Evas *evas, int w, int h, Efl_Gfx_Colorspace cspace, Ector_Buffer_Flag flags) { - return efl_add(EVAS_ECTOR_GL_BUFFER_CLASS, evas, - evas_ector_gl_buffer_prepare(efl_added, engine, w, h, cspace, flags)); + /* FIXME: This condition is tricky, this buffer could be used for masking + * buffer by vector, Require to use software drawing. + */ + if (flags != (ECTOR_BUFFER_FLAG_DRAWABLE | ECTOR_BUFFER_FLAG_CPU_READABLE | ECTOR_BUFFER_FLAG_CPU_WRITABLE)) + { + return efl_add(EVAS_ECTOR_GL_BUFFER_CLASS, evas, + evas_ector_gl_buffer_prepare(efl_added, engine, w, h, cspace, flags)); + } + else + { + Ector_Buffer *buf; + Image_Entry *ie; + void *pixels; + int pxs; + + if (cspace == EFL_GFX_COLORSPACE_ARGB8888) + pxs = 4; + else if (cspace == EFL_GFX_COLORSPACE_GRY8) + pxs = 1; + else + { + ERR("Unsupported colorspace: %d", (int) cspace); + return NULL; + } + + // alloc buffer + ie = evas_cache_image_copied_data(evas_common_image_cache_get(), w, h, + NULL, EINA_TRUE, cspace); + if (!ie) return NULL; + pixels = ((RGBA_Image *) ie)->image.data; + memset(pixels, 0, w * h * pxs); + + if (!efl_domain_current_push(EFL_ID_DOMAIN_SHARED)) + { + evas_cache_image_drop(ie); + return NULL; + } + + buf = efl_add_ref(EVAS_ECTOR_SOFTWARE_BUFFER_CLASS, NULL, + evas_ector_buffer_engine_image_set(efl_added, engine, ie)); + efl_domain_current_pop(); + + evas_cache_image_drop(ie); + + return buf; + } } static void -eng_ector_renderer_draw(void *engine EINA_UNUSED, void *output, - void *context EINA_UNUSED, void *surface EINA_UNUSED, - Ector_Renderer *renderer, Eina_Array *clips EINA_UNUSED, Eina_Bool do_async EINA_UNUSED) +eng_ector_renderer_draw(void *engine EINA_UNUSED, void *surface, + void *context EINA_UNUSED, Ector_Renderer *renderer, + Eina_Array *clips EINA_UNUSED, Eina_Bool do_async EINA_UNUSED) { - if (use_cairo|| !use_gl) + if (use_cairo || !use_gl) { int w, h; Eina_Rectangle *r; Eina_Array *c = eina_array_new(4); - Evas_GL_Image *glimg = output; + Evas_GL_Image *glimg = surface; eng_image_size_get(engine, glimg, &w, &h); eina_array_push(c, eina_rectangle_new(0, 0, w, h)); @@ -2603,21 +2650,22 @@ eng_ector_surface_cache_drop(void *engine, void *key) } static void -eng_ector_begin(void *engine, void *output, - void *context EINA_UNUSED, void *surface EINA_UNUSED, - Ector_Surface *ector, int x, int y, Eina_Bool do_async EINA_UNUSED) +eng_ector_begin(void *engine, void *surface, + void *context EINA_UNUSED, Ector_Surface *ector, + int x, int y, Eina_Bool clear, Eina_Bool do_async EINA_UNUSED) { if (use_cairo|| !use_gl) { int w, h, stride; - Evas_GL_Image *glim = output; + Evas_GL_Image *glim = surface; DATA32 *pixels; int load_err; glim = eng_image_data_get(engine, glim, EINA_TRUE, &pixels, &load_err,NULL); eng_image_stride_get(engine, glim, &stride); eng_image_size_get(engine, glim, &w, &h); - memset(pixels, 0, stride * h); + + if (clear) memset(pixels, 0, stride * h); // it just uses the software backend to draw for now ector_buffer_pixels_set(ector, pixels, w, h, stride, EFL_GFX_COLORSPACE_ARGB8888, EINA_TRUE); @@ -2630,13 +2678,15 @@ eng_ector_begin(void *engine, void *output, } static void -eng_ector_end(void *engine, void *output, - void *context EINA_UNUSED, void *surface EINA_UNUSED, - Ector_Surface *ector, Eina_Bool do_async EINA_UNUSED) +eng_ector_end(void *engine, + void *surface, + void *context EINA_UNUSED, + Ector_Surface *ector, + Eina_Bool do_async EINA_UNUSED) { if (use_cairo || !use_gl) { - Evas_GL_Image *glim = output; + Evas_GL_Image *glim = surface; DATA32 *pixels; int load_err; diff --git a/src/modules/evas/engines/gl_generic/meson.build b/src/modules/evas/engines/gl_generic/meson.build index cbc467b7ab..8926f24127 100644 --- a/src/modules/evas/engines/gl_generic/meson.build +++ b/src/modules/evas/engines/gl_generic/meson.build @@ -34,6 +34,8 @@ endforeach engine_deps = [gl_common] +engine_include_dir = include_directories(join_paths('..','software_generic')) + if get_option('evas-modules') == 'shared' and not evas_force_static.contains(engine) shared_module(mod_full_name, engine_src, include_directories : config_dir + [engine_include_dir], diff --git a/src/modules/evas/engines/software_generic/evas_engine.c b/src/modules/evas/engines/software_generic/evas_engine.c index 51d24c2ca1..7007f3a2fd 100644 --- a/src/modules/evas/engines/software_generic/evas_engine.c +++ b/src/modules/evas/engines/software_generic/evas_engine.c @@ -411,6 +411,7 @@ struct _Evas_Thread_Command_Ector_Surface Ector_Surface *ector; void *pixels; int x, y; + Eina_Bool clear; }; // declare here as it is re-used @@ -4237,7 +4238,7 @@ eng_ector_buffer_wrap(void *data, Evas *e EINA_UNUSED, void *engine_image) } static Ector_Buffer * -eng_ector_buffer_new(void *data EINA_UNUSED, Evas *evas, int width, int height, +eng_ector_buffer_new(void *data, Evas *evas, int width, int height, Efl_Gfx_Colorspace cspace, Ector_Buffer_Flag flags EINA_UNUSED) { Ector_Buffer *buf; @@ -4293,8 +4294,8 @@ _draw_thread_ector_draw(void *data) static void eng_ector_renderer_draw(void *engine EINA_UNUSED, void *surface, - void *context, void *remove EINA_UNUSED, - Ector_Renderer *renderer, Eina_Array *clips, Eina_Bool do_async) + void *context, Ector_Renderer *renderer, + Eina_Array *clips, Eina_Bool do_async) { RGBA_Image *dst = surface; RGBA_Draw_Context *dc = context; @@ -4400,7 +4401,7 @@ _draw_thread_ector_surface_set(void *data) x = ector_surface->x; y = ector_surface->y; // clear the surface before giving to ector - memset(pixels, 0, (w * h * 4)); + if (ector_surface->clear) memset(pixels, 0, (w * h * 4)); } ector_buffer_pixels_set(ector_surface->ector, pixels, w, h, 0, EFL_GFX_COLORSPACE_ARGB8888, EINA_TRUE); @@ -4411,20 +4412,21 @@ _draw_thread_ector_surface_set(void *data) static void eng_ector_begin(void *engine EINA_UNUSED, void *surface, - void *context EINA_UNUSED, void *remove EINA_UNUSED, - Ector_Surface *ector, int x, int y, Eina_Bool do_async) + void *context EINA_UNUSED, Ector_Surface *ector, + int x, int y, Eina_Bool clear, Eina_Bool do_async) { if (do_async) { Evas_Thread_Command_Ector_Surface *nes; nes = eina_mempool_malloc(_mp_command_ector_surface, sizeof (Evas_Thread_Command_Ector_Surface)); - if (!nes) return ; + if (!nes) return; nes->ector = ector; nes->pixels = surface; nes->x = x; nes->y = y; + nes->clear = clear; QCMD(_draw_thread_ector_surface_set, nes); } @@ -4439,7 +4441,7 @@ eng_ector_begin(void *engine EINA_UNUSED, void *surface, w = sf->cache_entry.w; h = sf->cache_entry.h; // clear the surface before giving to ector - memset(pixels, 0, (w * h * 4)); + if (clear) memset(pixels, 0, (w * h * 4)); ector_buffer_pixels_set(ector, pixels, w, h, 0, EFL_GFX_COLORSPACE_ARGB8888, EINA_TRUE); ector_surface_reference_point_set(ector, x, y); @@ -4447,9 +4449,11 @@ eng_ector_begin(void *engine EINA_UNUSED, void *surface, } static void -eng_ector_end(void *engine EINA_UNUSED, void *surface EINA_UNUSED, - void *context EINA_UNUSED, void *remove EINA_UNUSED, - Ector_Surface *ector, Eina_Bool do_async) +eng_ector_end(void *engine EINA_UNUSED, + void *surface EINA_UNUSED, + void *context EINA_UNUSED, + Ector_Surface *ector, + Eina_Bool do_async) { if (do_async) {