forked from enlightenment/efl
Evas filters: Implement mask stretch in RGBA blend
Brutal method for now: allocate YET ANOTHER buffer, render scaled image to it (smooth scaling, oh yeah), use this as a new mask. For now, supports: Alpha Input, RGBA mask, RGBA output, X,Y,XY stretching
This commit is contained in:
parent
9623e1f238
commit
40bb984b42
|
@ -508,8 +508,8 @@ _command_get(Evas_Filter_Context *ctx, int cmdid)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Evas_Filter_Buffer *
|
Evas_Filter_Buffer *
|
||||||
_filter_temporary_buffer_get(Evas_Filter_Context *ctx, int w, int h,
|
evas_filter_temporary_buffer_get(Evas_Filter_Context *ctx, int w, int h,
|
||||||
Eina_Bool alpha_only)
|
Eina_Bool alpha_only)
|
||||||
{
|
{
|
||||||
Evas_Filter_Buffer *buf = NULL;
|
Evas_Filter_Buffer *buf = NULL;
|
||||||
|
@ -630,7 +630,7 @@ evas_filter_command_blur_add(Evas_Filter_Context *ctx, void *drawctx,
|
||||||
else if (in->alpha_only && !out->alpha_only)
|
else if (in->alpha_only && !out->alpha_only)
|
||||||
{
|
{
|
||||||
INF("Adding extra blending step (Alpha --> RGBA)");
|
INF("Adding extra blending step (Alpha --> RGBA)");
|
||||||
blur_out = _filter_temporary_buffer_get(ctx, 0, 0, EINA_TRUE);
|
blur_out = evas_filter_temporary_buffer_get(ctx, 0, 0, EINA_TRUE);
|
||||||
if (!blur_out) goto fail;
|
if (!blur_out) goto fail;
|
||||||
convert = EINA_TRUE;
|
convert = EINA_TRUE;
|
||||||
}
|
}
|
||||||
|
@ -639,12 +639,12 @@ evas_filter_command_blur_add(Evas_Filter_Context *ctx, void *drawctx,
|
||||||
|
|
||||||
if (dx && dy)
|
if (dx && dy)
|
||||||
{
|
{
|
||||||
tmp = _filter_temporary_buffer_get(ctx, 0, 0, in->alpha_only);
|
tmp = evas_filter_temporary_buffer_get(ctx, 0, 0, in->alpha_only);
|
||||||
if (!tmp) goto fail;
|
if (!tmp) goto fail;
|
||||||
|
|
||||||
if (!convert && (ox || oy))
|
if (!convert && (ox || oy))
|
||||||
{
|
{
|
||||||
copybuf = _filter_temporary_buffer_get(ctx, 0, 0, in->alpha_only);
|
copybuf = evas_filter_temporary_buffer_get(ctx, 0, 0, in->alpha_only);
|
||||||
copy_back = EINA_TRUE;
|
copy_back = EINA_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -668,7 +668,7 @@ evas_filter_command_blur_add(Evas_Filter_Context *ctx, void *drawctx,
|
||||||
if ((in == blur_out) || ox || oy)
|
if ((in == blur_out) || ox || oy)
|
||||||
{
|
{
|
||||||
// IN = OUT and 1-D blur. IN -blur-> TMP -copy-> IN.
|
// IN = OUT and 1-D blur. IN -blur-> TMP -copy-> IN.
|
||||||
tmp = _filter_temporary_buffer_get(ctx, 0, 0, in->alpha_only);
|
tmp = evas_filter_temporary_buffer_get(ctx, 0, 0, in->alpha_only);
|
||||||
if (!tmp) goto fail;
|
if (!tmp) goto fail;
|
||||||
copy_back = EINA_TRUE;
|
copy_back = EINA_TRUE;
|
||||||
copybuf = tmp;
|
copybuf = tmp;
|
||||||
|
@ -685,7 +685,7 @@ evas_filter_command_blur_add(Evas_Filter_Context *ctx, void *drawctx,
|
||||||
if ((in == blur_out) || ox || oy)
|
if ((in == blur_out) || ox || oy)
|
||||||
{
|
{
|
||||||
// IN = OUT and 1-D blur. IN -blur-> TMP -copy-> IN.
|
// IN = OUT and 1-D blur. IN -blur-> TMP -copy-> IN.
|
||||||
tmp = _filter_temporary_buffer_get(ctx, 0, 0, in->alpha_only);
|
tmp = evas_filter_temporary_buffer_get(ctx, 0, 0, in->alpha_only);
|
||||||
if (!tmp) goto fail;
|
if (!tmp) goto fail;
|
||||||
copy_back = EINA_TRUE;
|
copy_back = EINA_TRUE;
|
||||||
copybuf = tmp;
|
copybuf = tmp;
|
||||||
|
@ -920,7 +920,7 @@ evas_filter_command_displacement_map_add(Evas_Filter_Context *ctx,
|
||||||
|
|
||||||
if (in == out)
|
if (in == out)
|
||||||
{
|
{
|
||||||
tmp = _filter_temporary_buffer_get(ctx, in->w, in->h, in->alpha_only);
|
tmp = evas_filter_temporary_buffer_get(ctx, in->w, in->h, in->alpha_only);
|
||||||
if (!tmp) return -1;
|
if (!tmp) return -1;
|
||||||
disp_out = tmp;
|
disp_out = tmp;
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,17 +138,19 @@ static Eina_Bool
|
||||||
_mask_cpu_alpha_rgba_rgba(Evas_Filter_Command *cmd)
|
_mask_cpu_alpha_rgba_rgba(Evas_Filter_Command *cmd)
|
||||||
{
|
{
|
||||||
RGBA_Gfx_Func func1, func2;
|
RGBA_Gfx_Func func1, func2;
|
||||||
RGBA_Image *in, *out, *mask;
|
Evas_Filter_Buffer *tmpbuf = NULL;
|
||||||
|
RGBA_Image *in, *out, *mask, *mask_stretched = NULL;
|
||||||
DATA8 *src;
|
DATA8 *src;
|
||||||
DATA32 *dst, *msk, *span;
|
DATA32 *dst, *msk, *span;
|
||||||
int op = cmd->draw.render_op;
|
int op = cmd->draw.render_op;
|
||||||
int w, h, mw, mh, x, y, my;
|
int w, h, mw, mh, x, y, my, mws, mhs;
|
||||||
int stepsize, stepcount, step;
|
int stepsize, stepcount, step;
|
||||||
DATA32 color2;
|
DATA32 color2;
|
||||||
|
|
||||||
/* Mechanism:
|
/* Mechanism:
|
||||||
* 1. Render mask to span using input as mask
|
* 1. Stretch mask as requested in fillmode
|
||||||
* 2. Render span into destination
|
* 2. Render mask to span using input as mask
|
||||||
|
* 3. Render span into destination
|
||||||
*
|
*
|
||||||
* FIXME: Could probably be optimized into a single op :)
|
* FIXME: Could probably be optimized into a single op :)
|
||||||
*/
|
*/
|
||||||
|
@ -165,6 +167,64 @@ _mask_cpu_alpha_rgba_rgba(Evas_Filter_Command *cmd)
|
||||||
dst = out->image.data;
|
dst = out->image.data;
|
||||||
msk = mask->image.data;
|
msk = mask->image.data;
|
||||||
|
|
||||||
|
// Stretch if necessary. TODO: Move this to common func. Support alpha too.
|
||||||
|
if (mw != w || mh != h)
|
||||||
|
{
|
||||||
|
Eina_Bool stretch = EINA_FALSE;
|
||||||
|
mws = mw;
|
||||||
|
mhs = mh;
|
||||||
|
|
||||||
|
if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X)
|
||||||
|
{
|
||||||
|
mws = w;
|
||||||
|
stretch = EINA_TRUE;
|
||||||
|
}
|
||||||
|
if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y)
|
||||||
|
{
|
||||||
|
mhs = h;
|
||||||
|
stretch = EINA_TRUE;
|
||||||
|
}
|
||||||
|
if (stretch)
|
||||||
|
{
|
||||||
|
void *drawctx;
|
||||||
|
|
||||||
|
// Alloc
|
||||||
|
cmd->input->locked = EINA_TRUE;
|
||||||
|
cmd->mask->locked = EINA_TRUE;
|
||||||
|
cmd->output->locked = EINA_TRUE;
|
||||||
|
|
||||||
|
tmpbuf = evas_filter_temporary_buffer_get(cmd->ctx, mws, mhs, cmd->mask->alpha_only);
|
||||||
|
if (evas_filter_buffer_alloc(tmpbuf, mws, mhs))
|
||||||
|
mask_stretched = evas_filter_buffer_backing_get(cmd->ctx, tmpbuf->id);
|
||||||
|
|
||||||
|
cmd->input->locked = EINA_FALSE;
|
||||||
|
cmd->mask->locked = EINA_FALSE;
|
||||||
|
cmd->output->locked = EINA_FALSE;
|
||||||
|
|
||||||
|
if (!mask_stretched)
|
||||||
|
{
|
||||||
|
ERR("Buffer allocation failed for size %dx%d", mws, mhs);
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scale
|
||||||
|
drawctx = cmd->ENFN->context_new(cmd->ENDT);
|
||||||
|
cmd->ENFN->context_color_set(cmd->ENDT, drawctx, 255, 255, 255, 255);
|
||||||
|
cmd->ENFN->context_render_op_set(cmd->ENDT, drawctx, EVAS_RENDER_COPY);
|
||||||
|
cmd->ENFN->image_draw(cmd->ENDT, drawctx, mask_stretched, mask,
|
||||||
|
0, 0, mw, mh, // src
|
||||||
|
0, 0, mws, mhs, // dst
|
||||||
|
EINA_TRUE, // smooth
|
||||||
|
EINA_FALSE); // Not async
|
||||||
|
cmd->ENFN->context_free(cmd->ENDT, drawctx);
|
||||||
|
|
||||||
|
mask = mask_stretched;
|
||||||
|
msk = mask->image.data;
|
||||||
|
mw = mws;
|
||||||
|
mh = mhs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
color2 = ARGB_JOIN(cmd->draw.A, cmd->draw.R, cmd->draw.G, cmd->draw.B);
|
color2 = ARGB_JOIN(cmd->draw.A, cmd->draw.R, cmd->draw.G, cmd->draw.B);
|
||||||
|
|
||||||
EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE);
|
EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE);
|
||||||
|
@ -206,6 +266,7 @@ _mask_cpu_alpha_rgba_rgba(Evas_Filter_Command *cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
free(span);
|
free(span);
|
||||||
|
if (tmpbuf) tmpbuf->locked = EINA_FALSE; // Don't free right away
|
||||||
return EINA_TRUE;
|
return EINA_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -139,5 +139,6 @@ Evas_Filter_Apply_Func evas_filter_mask_cpu_func_get(Evas_Filter_Command *cmd)
|
||||||
void _clip_to_target(int *sx, int *sy, int sw, int sh, int ox, int oy, int dw, int dh, int *dx, int *dy, int *rows, int *cols);
|
void _clip_to_target(int *sx, int *sy, int sw, int sh, int ox, int oy, int dw, int dh, int *dx, int *dy, int *rows, int *cols);
|
||||||
Eina_Bool evas_filter_buffer_alloc(Evas_Filter_Buffer *fb, int w, int h);
|
Eina_Bool evas_filter_buffer_alloc(Evas_Filter_Buffer *fb, int w, int h);
|
||||||
Evas_Filter_Buffer *_filter_buffer_get(Evas_Filter_Context *ctx, int bufid);
|
Evas_Filter_Buffer *_filter_buffer_get(Evas_Filter_Context *ctx, int bufid);
|
||||||
|
Evas_Filter_Buffer *evas_filter_temporary_buffer_get(Evas_Filter_Context *ctx, int w, int h, Eina_Bool alpha_only);
|
||||||
|
|
||||||
#endif // EVAS_FILTER_PRIVATE_H
|
#endif // EVAS_FILTER_PRIVATE_H
|
||||||
|
|
Loading…
Reference in New Issue