# Static draw lib
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
lib_evas_libevas_la_SOURCES += \
static Eina_Bool
_mask_cpu_rgba_rgba_rgba(Evas_Filter_Command *cmd)
{
- //Evas_Filter_Command fake_cmd;
- Evas_Filter_Fill_Mode fillmode;
- //Evas_Filter_Apply_Func blend;
- Evas_Filter_Buffer *fb;
- Eina_Bool ret = EINA_FALSE;
- int w, h;
+ Draw_Func_ARGB_Mix3 func;
+ RGBA_Image *in, *out, *mask;
+ DATA32 *dst, *msk, *src;
+ int w, h, mw, mh, y, my, r;
+ int stepsize, stepcount, step;
+ DATA32 color;
+
+ /* Mechanism:
+ * 1. Stretch mask as requested in fillmode
+ * 2. Mix 3 colors
+ */
+
+ in = (RGBA_Image *) cmd->input->backing;
+ out = (RGBA_Image *) cmd->output->backing;
+ mask = (RGBA_Image *) cmd->mask->backing;
- fake_cmd = *cmd;
w = cmd->input->w;
h = cmd->input->h;
+ mw = cmd->mask->w;
+ mh = cmd->mask->h;
+ src = in->image.data;
+ dst = out->image.data;
- // 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)
- */
+ // Stretch if necessary.
+ if ((mw != w || mh != h) && (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_XY))
+ {
+ Evas_Filter_Buffer *fb;
+
+ if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X)
+ mw = w;
+ if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y)
+ mh = h;
- // Copy
- BUFFERS_LOCK();
- fb = evas_filter_buffer_scaled_get(cmd->ctx, cmd->input, w, h);
- BUFFERS_UNLOCK();
- EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE);
- fb->locked = EINA_TRUE;
+ BUFFERS_LOCK();
+ fb = evas_filter_buffer_scaled_get(cmd->ctx, cmd->mask, mw, mh);
+ BUFFERS_UNLOCK();
- // Repeat mask if unspecified - NONE is not possible
- fillmode = cmd->draw.fillmode;
- if ((fillmode & (EVAS_FILTER_FILL_MODE_REPEAT_X | EVAS_FILTER_FILL_MODE_STRETCH_X)) == 0)
- {
- DBG("X fillmode not specified: defaults to repeat");
- fillmode |= EVAS_FILTER_FILL_MODE_REPEAT_X;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE);
+ fb->locked = EINA_FALSE;
+ mask = fb->backing;
}
- if ((fillmode & (EVAS_FILTER_FILL_MODE_REPEAT_Y | EVAS_FILTER_FILL_MODE_STRETCH_Y)) == 0)
+
+ color = ARGB_JOIN(cmd->draw.A, cmd->draw.R, cmd->draw.G, cmd->draw.B);
+ msk = mask->image.data;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(dst, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(msk, EINA_FALSE);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL((w > 0) && (mw > 0), EINA_FALSE);
+
+ stepsize = MIN(mw, w);
+ stepcount = w / stepsize;
+
+ func = efl_draw_func_argb_mix3_get(cmd->draw.rop, color);
+
+ // Apply mask using Gfx functions
+ for (y = 0, my = 0; y < h; y++, my++, msk += mw)
{
- DBG("Y fillmode not specified: defaults to repeat");
- fillmode |= EVAS_FILTER_FILL_MODE_REPEAT_Y;
+ 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;
+ }
}
-#warning FIXME: filter full RGBA masking is now broken
- goto finish;
-
-#if 0
- // Mask --> Temp
- fake_cmd.input = cmd->mask;
- fake_cmd.mask = NULL;
- 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
- fake_cmd.draw.rop = EFL_GFX_RENDER_OP_BLEND;
- 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:
- fb->locked = EINA_FALSE;
- return ret;
+ return EINA_TRUE;
}
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_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);
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_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);
+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);
#define DRAW_ARGB_JOIN(a,r,g,b) \
(((a) << 24) + ((r) << 16) + ((g) << 8) + (b))
+/* argb multiply */
#define DRAW_MUL4_SYM(x, y) \
( ((((((x) >> 16) & 0xff00) * (((y) >> 16) & 0xff00)) + 0xff0000) & 0xff000000) + \
((((((x) >> 8) & 0xff00) * (((y) >> 16) & 0xff)) + 0xff00) & 0xff0000) + \
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);
*dest = c + draw_mul_256(a, *dest);
}
}
+/* s = m * color
+ * d = s * sa
+ */
static void
_comp_func_mask_copy(uint32_t *dest, uint8_t *mask, int length, uint32_t color)
{
for (k = 0; k < length; k++, dest++, mask++)
{
- int a = (*mask & 0x80) ? *mask + 1 : *mask;
- *dest = draw_mul_256(a, color);
+ *dest = draw_mul_256(*mask + 1, 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);
}
}
_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
efl_draw_func_mask_span_get(Efl_Gfx_Render_Op op, uint32_t color EINA_UNUSED)
{
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
efl_draw_func_solid_span_get(Efl_Gfx_Render_Op op, uint32_t color)
{