From 1c9865a8ae8bed79fd58e14a282a7eb98ce19baf Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Tue, 21 Jan 2014 16:49:43 +0900 Subject: [PATCH] Evas filters: Implement repeat and stretch for rgba to alpha Use the mapped rendering to implement repeat and stretch with rgba to alpha buffers blending. If stretch is required, it will add one more (expensive) scaling step. --- src/lib/evas/filters/evas_filter_blend.c | 111 ++++++++++++++++++----- 1 file changed, 87 insertions(+), 24 deletions(-) diff --git a/src/lib/evas/filters/evas_filter_blend.c b/src/lib/evas/filters/evas_filter_blend.c index 141d0af50e..b022f603c0 100644 --- a/src/lib/evas/filters/evas_filter_blend.c +++ b/src/lib/evas/filters/evas_filter_blend.c @@ -32,6 +32,21 @@ _filter_blend_cpu_alpha(Evas_Filter_Command *cmd) DATA8 *maskdata, *dstdata; int sw, sh, dw, dh, ox, oy, sx = 0, sy = 0, dx = 0, dy = 0, rows, cols, y; + /* + * NOTE: Alpha to alpha blending does not support stretching operations + * yet, because we don't have any scaling functions for alpha buffers. + * Also, I'm not going to implement it by converting to RGBA either. + */ + if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_XY) + { + CRI("Alpha to alpha blending does not support stretch"); + return EINA_FALSE; + } + + // TODO: Call _mapped_blend_cpu to implement repeat fill mode. + if (cmd->draw.fillmode != EVAS_FILTER_FILL_MODE_NONE) + ERR("Fill modes are not implemented for Alpha --> RGBA"); + func = evas_common_alpha_func_get(cmd->draw.render_op); if (!func) return EINA_FALSE; @@ -306,6 +321,10 @@ _filter_blend_cpu_mask_rgba(Evas_Filter_Command *cmd) if (!evas_filter_buffer_alloc(cmd->output, cmd->output->w, cmd->output->h)) return EINA_FALSE; + // TODO: Call _mapped_blend_cpu to implement repeat fill mode. + if (cmd->draw.fillmode != EVAS_FILTER_FILL_MODE_NONE) + ERR("Fill modes are not implemented for Alpha --> RGBA"); + in = cmd->input->backing; out = cmd->output->backing; sw = in->cache_entry.w; @@ -348,50 +367,94 @@ _filter_blend_cpu_mask_rgba(Evas_Filter_Command *cmd) return EINA_TRUE; } +static Eina_Bool +_image_draw_cpu_rgba2alpha(void *data EINA_UNUSED, void *context EINA_UNUSED, + void *surface, void *image, + int src_x, int src_y, int src_w, int src_h, + int dst_x, int dst_y, int dst_w, int dst_h, + int smooth EINA_UNUSED, + Eina_Bool do_async EINA_UNUSED) +{ + RGBA_Image *src = image; + RGBA_Image *dst = surface; + DATA32* srcdata = src->image.data; + DATA8* dstdata = dst->mask.data; + int x, y, sw, dw; + DEFINE_DIVIDER(3); + + EINA_SAFETY_ON_FALSE_RETURN_VAL((src_w == dst_w) && (src_h == dst_h), EINA_FALSE); + + sw = src->cache_entry.w; + dw = dst->cache_entry.w; + + srcdata += src_y * sw; + dstdata += dst_y * dw; + for (y = src_h; y; y--) + { + DATA32 *s = srcdata + src_x; + DATA8 *d = dstdata + dst_x; + for (x = src_w; x; x--, d++, s++) + { + // TODO: Add weights like in YUV <--> RGB? + *d = DIVIDE(R_VAL(s) + G_VAL(s) + B_VAL(s)); + } + srcdata += sw; + dstdata += dw; + } + + return EINA_TRUE; +} + static Eina_Bool _filter_blend_cpu_rgba2alpha(Evas_Filter_Command *cmd) { RGBA_Image *in, *out; - DATA8 *dstdata; - DATA32 *srcdata; - int sw, sh, dw, dh, ox, oy, sx = 0, sy = 0, dx = 0, dy = 0, rows, cols, y, x; - DEFINE_DIVIDER(3); + int sw, sh, dx, dy, dw, dh, sx, sy; if (!evas_filter_buffer_alloc(cmd->output, cmd->output->w, cmd->output->h)) return EINA_FALSE; in = cmd->input->backing; out = cmd->output->backing; + EINA_SAFETY_ON_NULL_RETURN_VAL(in, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(out, EINA_FALSE); + + sx = 0; + sy = 0; sw = in->cache_entry.w; sh = in->cache_entry.h; + dw = out->cache_entry.w; dh = out->cache_entry.h; - ox = cmd->draw.ox; - oy = cmd->draw.oy; - srcdata = in->image.data; - dstdata = out->mask.data; + dx = cmd->draw.ox; + dy = cmd->draw.oy; - _clip_to_target(&sx, &sy, sw, sh, ox, oy, dw, dh, &dx, &dy, &rows, &cols); - // FIXME/TODO: Clip to context clip - - if (cols <= 0 || rows <= 0) + if ((dw <= 0) || (dh <= 0) || (sw <= 0) || (sh <= 0)) return EINA_TRUE; - srcdata += sy * sw; - dstdata += dy * dw; - for (y = rows; y; y--) + // Stretch if necessary. + if ((sw != dw || sh != dh) && (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_XY)) { - DATA32 *s = srcdata + sx; - DATA8 *d = dstdata + dx; - for (x = cols; x; x--, d++, s++) - { - // TODO: Add weights? - *d = DIVIDE(R_VAL(s) + G_VAL(s) + B_VAL(s)); - } - srcdata += sw; - dstdata += dw; + Evas_Filter_Buffer *fb; + + if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X) + sw = dw; + if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y) + sh = dh; + + BUFFERS_LOCK(); + fb = evas_filter_buffer_scaled_get(cmd->ctx, cmd->input, sw, sh); + BUFFERS_UNLOCK(); + + EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE); + fb->locked = EINA_FALSE; + in = fb->backing; } + _mapped_blend_cpu(cmd->ENDT, NULL, in, out, cmd->draw.fillmode, + sx, sy, sw, sh, dx, dy, dw, dh, + _image_draw_cpu_rgba2alpha); + return EINA_TRUE; }