Discussion:
[EGIT] [core/efl] master 01/01: evas ector: add software implmentation for masking feature.
Hermet Park
2018-12-07 10:50:15 UTC
Permalink
hermet pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=fbe92aa67f18f8c0401cdc6d4440ed512c43b131

commit fbe92aa67f18f8c0401cdc6d4440ed512c43b131
Author: Hermet Park <***@gmail.com>
Date: Fri Dec 7 19:38:48 2018 +0900

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 ++-
.../ector/software/ector_renderer_software_shape.c | 36 ++++-
.../software/ector_renderer_software_shape.eo | 1 +
src/lib/ector/software/ector_software_buffer.c | 4 +-
src/lib/ector/software/ector_software_private.h | 11 +-
src/lib/ector/software/ector_software_rasterizer.c | 122 +++++++++++++--
src/lib/evas/canvas/efl_canvas_vg_container.c | 163 ++++++++++++++++++---
src/lib/evas/canvas/efl_canvas_vg_container.eo | 5 +-
.../evas/canvas/efl_canvas_vg_gradient_linear.c | 23 +--
.../evas/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 +-
src/modules/evas/engines/gl_generic/evas_engine.c | 82 +++++++++--
src/modules/evas/engines/gl_generic/meson.build | 2 +
.../evas/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<Efl.Canvas.Vg.Node> @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)
{

--

Loading...