Evas filters: Implement mix3 func for rgba masking
This operation was faked by running a mul and a blend ops. Now they are combined into one. A GL shader should also be able to do this in a single pass.
This commit is contained in:
parent
ecc7da9cba
commit
8f4018b690
|
@ -261,7 +261,8 @@ lib/evas/canvas/evas_vg_shape.c
|
||||||
|
|
||||||
# Static draw lib
|
# Static draw lib
|
||||||
lib_evas_libevas_la_SOURCES += \
|
lib_evas_libevas_la_SOURCES += \
|
||||||
static_libs/draw/draw_alpha_main.c
|
static_libs/draw/draw_alpha_main.c \
|
||||||
|
static_libs/draw/draw_main.c
|
||||||
|
|
||||||
# Engine
|
# Engine
|
||||||
lib_evas_libevas_la_SOURCES += \
|
lib_evas_libevas_la_SOURCES += \
|
||||||
|
|
|
@ -349,71 +349,81 @@ _mask_cpu_alpha_alpha_rgba(Evas_Filter_Command *cmd)
|
||||||
static Eina_Bool
|
static Eina_Bool
|
||||||
_mask_cpu_rgba_rgba_rgba(Evas_Filter_Command *cmd)
|
_mask_cpu_rgba_rgba_rgba(Evas_Filter_Command *cmd)
|
||||||
{
|
{
|
||||||
//Evas_Filter_Command fake_cmd;
|
Draw_Func_ARGB_Mix3 func;
|
||||||
Evas_Filter_Fill_Mode fillmode;
|
RGBA_Image *in, *out, *mask;
|
||||||
//Evas_Filter_Apply_Func blend;
|
DATA32 *dst, *msk, *src;
|
||||||
Evas_Filter_Buffer *fb;
|
int w, h, mw, mh, y, my, r;
|
||||||
Eina_Bool ret = EINA_FALSE;
|
int stepsize, stepcount, step;
|
||||||
int w, h;
|
DATA32 color;
|
||||||
|
|
||||||
fake_cmd = *cmd;
|
/* Mechanism:
|
||||||
w = cmd->input->w;
|
* 1. Stretch mask as requested in fillmode
|
||||||
h = cmd->input->h;
|
* 2. Mix 3 colors
|
||||||
|
|
||||||
// FIXME: do a single pass
|
|
||||||
/* Blend 2 rgba images into rgba destination.
|
|
||||||
* Mechanism:
|
|
||||||
* 1. Copy input to temp (COPY)
|
|
||||||
* 2. Blend mask to temp (MUL)
|
|
||||||
* 3. Blend temp to output (render_op)
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Copy
|
in = (RGBA_Image *) cmd->input->backing;
|
||||||
BUFFERS_LOCK();
|
out = (RGBA_Image *) cmd->output->backing;
|
||||||
fb = evas_filter_buffer_scaled_get(cmd->ctx, cmd->input, w, h);
|
mask = (RGBA_Image *) cmd->mask->backing;
|
||||||
BUFFERS_UNLOCK();
|
|
||||||
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE);
|
|
||||||
fb->locked = EINA_TRUE;
|
|
||||||
|
|
||||||
// Repeat mask if unspecified - NONE is not possible
|
w = cmd->input->w;
|
||||||
fillmode = cmd->draw.fillmode;
|
h = cmd->input->h;
|
||||||
if ((fillmode & (EVAS_FILTER_FILL_MODE_REPEAT_X | EVAS_FILTER_FILL_MODE_STRETCH_X)) == 0)
|
mw = cmd->mask->w;
|
||||||
|
mh = cmd->mask->h;
|
||||||
|
src = in->image.data;
|
||||||
|
dst = out->image.data;
|
||||||
|
|
||||||
|
// Stretch if necessary.
|
||||||
|
if ((mw != w || mh != h) && (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_XY))
|
||||||
{
|
{
|
||||||
DBG("X fillmode not specified: defaults to repeat");
|
Evas_Filter_Buffer *fb;
|
||||||
fillmode |= EVAS_FILTER_FILL_MODE_REPEAT_X;
|
|
||||||
}
|
if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X)
|
||||||
if ((fillmode & (EVAS_FILTER_FILL_MODE_REPEAT_Y | EVAS_FILTER_FILL_MODE_STRETCH_Y)) == 0)
|
mw = w;
|
||||||
{
|
if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y)
|
||||||
DBG("Y fillmode not specified: defaults to repeat");
|
mh = h;
|
||||||
fillmode |= EVAS_FILTER_FILL_MODE_REPEAT_Y;
|
|
||||||
|
BUFFERS_LOCK();
|
||||||
|
fb = evas_filter_buffer_scaled_get(cmd->ctx, cmd->mask, mw, mh);
|
||||||
|
BUFFERS_UNLOCK();
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE);
|
||||||
|
fb->locked = EINA_FALSE;
|
||||||
|
mask = fb->backing;
|
||||||
}
|
}
|
||||||
|
|
||||||
#warning FIXME: filter full RGBA masking is now broken
|
color = ARGB_JOIN(cmd->draw.A, cmd->draw.R, cmd->draw.G, cmd->draw.B);
|
||||||
goto finish;
|
msk = mask->image.data;
|
||||||
|
|
||||||
#if 0
|
EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE);
|
||||||
// Mask --> Temp
|
EINA_SAFETY_ON_NULL_RETURN_VAL(dst, EINA_FALSE);
|
||||||
fake_cmd.input = cmd->mask;
|
EINA_SAFETY_ON_NULL_RETURN_VAL(msk, EINA_FALSE);
|
||||||
fake_cmd.mask = NULL;
|
EINA_SAFETY_ON_FALSE_RETURN_VAL((w > 0) && (mw > 0), EINA_FALSE);
|
||||||
fake_cmd.output = fb;
|
|
||||||
fake_cmd.draw.rop = EVAS_RENDER_MUL; // FIXME
|
|
||||||
fake_cmd.draw.fillmode = fillmode;
|
|
||||||
blend = evas_filter_blend_cpu_func_get(&fake_cmd);
|
|
||||||
EINA_SAFETY_ON_NULL_RETURN_VAL(blend, EINA_FALSE);
|
|
||||||
ret = blend(&fake_cmd);
|
|
||||||
if (!ret) goto finish;
|
|
||||||
|
|
||||||
// Temp --> Output
|
stepsize = MIN(mw, w);
|
||||||
fake_cmd.draw.rop = EFL_GFX_RENDER_OP_BLEND;
|
stepcount = w / stepsize;
|
||||||
fake_cmd.input = fb;
|
|
||||||
fake_cmd.output = cmd->output;
|
|
||||||
fake_cmd.draw.fillmode = EVAS_FILTER_FILL_MODE_NONE;
|
|
||||||
blend = evas_filter_blend_cpu_func_get(&fake_cmd);
|
|
||||||
EINA_SAFETY_ON_NULL_RETURN_VAL(blend, EINA_FALSE);
|
|
||||||
ret = blend(&fake_cmd);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
finish:
|
func = efl_draw_func_argb_mix3_get(cmd->draw.rop, color);
|
||||||
fb->locked = EINA_FALSE;
|
|
||||||
return ret;
|
// Apply mask using Gfx functions
|
||||||
|
for (y = 0, my = 0; y < h; y++, my++, msk += mw)
|
||||||
|
{
|
||||||
|
if (my >= mh)
|
||||||
|
{
|
||||||
|
my = 0;
|
||||||
|
msk = mask->image.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (step = 0; step < stepcount; step++, dst += stepsize, src += stepsize)
|
||||||
|
func(dst, src, msk, stepsize, color);
|
||||||
|
|
||||||
|
r = w - (stepsize * stepcount);
|
||||||
|
if (r > 0)
|
||||||
|
{
|
||||||
|
func(dst, src, msk, r, color);
|
||||||
|
dst += r;
|
||||||
|
src += r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
typedef void (*RGBA_Comp_Func) (uint32_t *dest, const uint32_t *src, int length, uint32_t mul_col, uint32_t const_alpha);
|
typedef void (*RGBA_Comp_Func) (uint32_t *dest, const uint32_t *src, int length, uint32_t mul_col, uint32_t const_alpha);
|
||||||
typedef void (*RGBA_Comp_Func_Solid) (uint32_t *dest, int length, uint32_t color, uint32_t const_alpha);
|
typedef void (*RGBA_Comp_Func_Solid) (uint32_t *dest, int length, uint32_t color, uint32_t const_alpha);
|
||||||
typedef void (*RGBA_Comp_Func_Mask) (uint32_t *dest, uint8_t *mask, int length, uint32_t color);
|
typedef void (*RGBA_Comp_Func_Mask) (uint32_t *dest, uint8_t *mask, int length, uint32_t color);
|
||||||
|
typedef void (*Draw_Func_ARGB_Mix3) (uint32_t *dest, uint32_t *src, uint32_t *mul, int len, uint32_t color);
|
||||||
typedef void (*Alpha_Gfx_Func) (uint8_t *src, uint8_t *dst, int len);
|
typedef void (*Alpha_Gfx_Func) (uint8_t *src, uint8_t *dst, int len);
|
||||||
|
|
||||||
int efl_draw_init(void);
|
int efl_draw_init(void);
|
||||||
|
@ -18,6 +19,7 @@ int efl_draw_init(void);
|
||||||
RGBA_Comp_Func efl_draw_func_span_get (Efl_Gfx_Render_Op op, uint32_t color, Eina_Bool src_alpha);
|
RGBA_Comp_Func efl_draw_func_span_get (Efl_Gfx_Render_Op op, uint32_t color, Eina_Bool src_alpha);
|
||||||
RGBA_Comp_Func_Solid efl_draw_func_solid_span_get (Efl_Gfx_Render_Op op, uint32_t color);
|
RGBA_Comp_Func_Solid efl_draw_func_solid_span_get (Efl_Gfx_Render_Op op, uint32_t color);
|
||||||
RGBA_Comp_Func_Mask efl_draw_func_mask_span_get (Efl_Gfx_Render_Op op, uint32_t color);
|
RGBA_Comp_Func_Mask efl_draw_func_mask_span_get (Efl_Gfx_Render_Op op, uint32_t color);
|
||||||
|
Draw_Func_ARGB_Mix3 efl_draw_func_argb_mix3_get (Efl_Gfx_Render_Op op, uint32_t color);
|
||||||
Alpha_Gfx_Func efl_draw_alpha_func_get (Efl_Gfx_Render_Op op, Eina_Bool has_mask);
|
Alpha_Gfx_Func efl_draw_alpha_func_get (Efl_Gfx_Render_Op op, Eina_Bool has_mask);
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,6 +56,7 @@ Alpha_Gfx_Func efl_draw_alpha_func_get (Efl_Gfx_Render_Op op, Eina_
|
||||||
#define DRAW_ARGB_JOIN(a,r,g,b) \
|
#define DRAW_ARGB_JOIN(a,r,g,b) \
|
||||||
(((a) << 24) + ((r) << 16) + ((g) << 8) + (b))
|
(((a) << 24) + ((r) << 16) + ((g) << 8) + (b))
|
||||||
|
|
||||||
|
/* argb multiply */
|
||||||
#define DRAW_MUL4_SYM(x, y) \
|
#define DRAW_MUL4_SYM(x, y) \
|
||||||
( ((((((x) >> 16) & 0xff00) * (((y) >> 16) & 0xff00)) + 0xff0000) & 0xff000000) + \
|
( ((((((x) >> 16) & 0xff00) * (((y) >> 16) & 0xff00)) + 0xff0000) & 0xff000000) + \
|
||||||
((((((x) >> 8) & 0xff00) * (((y) >> 16) & 0xff)) + 0xff00) & 0xff0000) + \
|
((((((x) >> 8) & 0xff00) * (((y) >> 16) & 0xff)) + 0xff00) & 0xff0000) + \
|
||||||
|
|
|
@ -138,12 +138,15 @@ _comp_func_mask_blend(uint32_t *dest, uint8_t *mask, int length, uint32_t color)
|
||||||
|
|
||||||
for (k = 0; k < length; k++, dest++, mask++)
|
for (k = 0; k < length; k++, dest++, mask++)
|
||||||
{
|
{
|
||||||
uint32_t c = draw_mul_256(*mask, color);
|
uint32_t c = draw_mul_256((*mask + 1), color);
|
||||||
int a = 256 - (c >> 24);
|
int a = 256 - (c >> 24);
|
||||||
*dest = c + draw_mul_256(a, *dest);
|
*dest = c + draw_mul_256(a, *dest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* s = m * color
|
||||||
|
* d = s * sa
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
_comp_func_mask_copy(uint32_t *dest, uint8_t *mask, int length, uint32_t color)
|
_comp_func_mask_copy(uint32_t *dest, uint8_t *mask, int length, uint32_t color)
|
||||||
{
|
{
|
||||||
|
@ -151,8 +154,65 @@ _comp_func_mask_copy(uint32_t *dest, uint8_t *mask, int length, uint32_t color)
|
||||||
|
|
||||||
for (k = 0; k < length; k++, dest++, mask++)
|
for (k = 0; k < length; k++, dest++, mask++)
|
||||||
{
|
{
|
||||||
int a = (*mask & 0x80) ? *mask + 1 : *mask;
|
*dest = draw_mul_256(*mask + 1, color);
|
||||||
*dest = draw_mul_256(a, color);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* w = s * m * c
|
||||||
|
* d = d * (1-wa) + w * wa
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
_comp_func_mix3_blend(uint32_t *dest, uint32_t *src, uint32_t *mul, int len, uint32_t color)
|
||||||
|
{
|
||||||
|
int k, a;
|
||||||
|
|
||||||
|
for (k = 0; k < len; k++, dest++, src++, mul++)
|
||||||
|
{
|
||||||
|
uint32_t c = DRAW_MUL4_SYM(*mul, color);
|
||||||
|
c = DRAW_MUL4_SYM(c, *src);
|
||||||
|
a = 256 - (c >> 24);
|
||||||
|
*dest = c + draw_mul_256(a, *dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* d = s * m * c */
|
||||||
|
static void
|
||||||
|
_comp_func_mix3_copy(uint32_t *dest, uint32_t *src, uint32_t *mul, int len, uint32_t color)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
|
||||||
|
for (k = 0; k < len; k++, dest++, src++, mul++)
|
||||||
|
{
|
||||||
|
uint32_t c = DRAW_MUL4_SYM(*mul, color);
|
||||||
|
*dest = DRAW_MUL4_SYM(c, *src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* w = s * m
|
||||||
|
* d = d * (1-wa) + w * wa
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
_comp_func_mix3_blend_nomul(uint32_t *dest, uint32_t *src, uint32_t *mul, int len, uint32_t color EINA_UNUSED)
|
||||||
|
{
|
||||||
|
int k, a;
|
||||||
|
|
||||||
|
for (k = 0; k < len; k++, dest++, src++, mul++)
|
||||||
|
{
|
||||||
|
uint32_t c = DRAW_MUL4_SYM(*mul, *src);
|
||||||
|
a = 256 - (c >> 24);
|
||||||
|
*dest = c + draw_mul_256(a, *dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* d = s * m */
|
||||||
|
static void
|
||||||
|
_comp_func_mix3_copy_nomul(uint32_t *dest, uint32_t *src, uint32_t *mul, int len, uint32_t color EINA_UNUSED)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
|
||||||
|
for (k = 0; k < len; k++, dest++, src++, mul++)
|
||||||
|
{
|
||||||
|
*dest = DRAW_MUL4_SYM(*mul, *src);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,12 +231,28 @@ RGBA_Comp_Func func_for_mode[EFL_GFX_RENDER_OP_LAST] = {
|
||||||
_comp_func_source
|
_comp_func_source
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Draw_Func_ARGB_Mix3 func_for_mode_argb_mix3[EFL_GFX_RENDER_OP_LAST * 2] = {
|
||||||
|
_comp_func_mix3_blend,
|
||||||
|
_comp_func_mix3_copy,
|
||||||
|
_comp_func_mix3_blend_nomul,
|
||||||
|
_comp_func_mix3_copy_nomul
|
||||||
|
};
|
||||||
|
|
||||||
RGBA_Comp_Func_Mask
|
RGBA_Comp_Func_Mask
|
||||||
efl_draw_func_mask_span_get(Efl_Gfx_Render_Op op, uint32_t color EINA_UNUSED)
|
efl_draw_func_mask_span_get(Efl_Gfx_Render_Op op, uint32_t color EINA_UNUSED)
|
||||||
{
|
{
|
||||||
return func_for_mode_mask[op];
|
return func_for_mode_mask[op];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Draw_Func_ARGB_Mix3
|
||||||
|
efl_draw_func_argb_mix3_get(Efl_Gfx_Render_Op op, uint32_t color)
|
||||||
|
{
|
||||||
|
if (color == 0xffffffff)
|
||||||
|
return func_for_mode_argb_mix3[op + 2];
|
||||||
|
else
|
||||||
|
return func_for_mode_argb_mix3[op];
|
||||||
|
}
|
||||||
|
|
||||||
RGBA_Comp_Func_Solid
|
RGBA_Comp_Func_Solid
|
||||||
efl_draw_func_solid_span_get(Efl_Gfx_Render_Op op, uint32_t color)
|
efl_draw_func_solid_span_get(Efl_Gfx_Render_Op op, uint32_t color)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue