forked from enlightenment/efl
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.
This commit is contained in:
parent
4d6f20d714
commit
fbe92aa67f
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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]]
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.");
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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],
|
||||
|
|
|
@ -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…
Reference in New Issue