fb = _buffer_empty_new(ctx, 0, 0, alpha_only, EINA_FALSE);
if (!fb) return -1;
- XDBG("Created context buffer %d %s", fb->id, alpha_only ? "alpha" : "rgba");
return fb->id;
}
fb = _filter_buffer_get(ctx, bufid);
if (!fb) return NULL;
- return evas_ector_buffer_drawable_image_get(fb->buffer, EINA_TRUE);
+ return evas_ector_buffer_drawable_image_get(fb->buffer);
}
Eina_Bool
cmd->input = input;
cmd->mask = mask;
cmd->output = output;
+ if (output) output->dirty = EINA_TRUE;
ctx->commands = eina_inlist_append(ctx->commands, EINA_INLIST_GET(cmd));
return cmd;
Evas_Filter_Buffer *
evas_filter_temporary_buffer_get(Evas_Filter_Context *ctx, int w, int h,
- Eina_Bool alpha_only)
+ Eina_Bool alpha_only, Eina_Bool clean)
{
- Evas_Filter_Buffer *buf = NULL;
+ Evas_Filter_Buffer *fb = NULL;
Eina_List *l;
- EINA_LIST_FOREACH(ctx->buffers, l, buf)
+ EINA_LIST_FOREACH(ctx->buffers, l, fb)
{
- if (buf->transient && !buf->locked && (buf->alpha_only == alpha_only))
+ if (fb->transient && !fb->locked && (fb->alpha_only == alpha_only)
+ && (!clean || !fb->dirty))
{
- if ((!w || (w == buf->w)) && (!h || (h == buf->h)))
+ if ((!w || (w == fb->w)) && (!h || (h == fb->h)))
{
- buf->locked = EINA_TRUE;
- return buf;
+ fb->locked = EINA_TRUE;
+ return fb;
}
}
}
return NULL;
}
- buf = _buffer_empty_new(ctx, w, h, alpha_only, EINA_TRUE);
- buf->locked = EINA_TRUE;
+ fb = _buffer_empty_new(ctx, w, h, alpha_only, EINA_TRUE);
+ fb->locked = EINA_TRUE;
+ XDBG("Created temporary buffer %d %s", fb->id, alpha_only ? "alpha" : "rgba");
- return buf;
+ return fb;
}
static void
XDBG("Add fill %d with color(%d,%d,%d,%d)", buf->id, R, G, B, A);
- buf->dirty = EINA_TRUE;
+ if (!R && !G && !B && !A)
+ buf->dirty = EINA_FALSE;
+
return cmd;
}
{
Evas_Filter_Buffer *in = NULL, *out = NULL, *tmp = NULL, *in_dy = NULL;
Evas_Filter_Buffer *out_dy = NULL, *out_dx = NULL;
- Evas_Filter_Buffer *copybuf = NULL, *blur_out = NULL;
- Eina_Bool copy_back = EINA_FALSE, blend = EINA_FALSE;
+ Evas_Filter_Buffer *copybuf = NULL, *blendbuf = NULL;
Evas_Filter_Command *cmd = NULL;
- int R, G, B, A; DATA32 color;
+ int R, G, B, A, render_op;
+ Eina_Bool override;
+ DATA32 color;
+
+ // Note (SW engine):
+ // The basic blur operation overrides the pixels in the target buffer,
+ // only supports one direction (X or Y) and no offset. As a consequence
+ // most cases require intermediate work buffers.
EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(drawctx, NULL);
out = _filter_buffer_get(ctx, outbuf);
EINA_SAFETY_ON_FALSE_GOTO(out, fail);
- if (!in->alpha_only && out->alpha_only)
- DBG("Different color formats, implicit conversion may be slow");
-
if (in == out) out->dirty = EINA_FALSE;
- blend = (out->dirty && !out->transient);
ENFN->context_color_get(ENDT, drawctx, &R, &G, &B, &A);
color = ARGB_JOIN(A, R, G, B);
if (!color)
{
DBG("Blur with transparent color. Nothing to do.");
- /* FIXME: return skip; */
+ return _command_new(ctx, EVAS_FILTER_MODE_SKIP, NULL, NULL, NULL);
}
+ render_op = ENFN->context_render_op_get(ENDT, drawctx);
+ override = (render_op == EVAS_RENDER_COPY);
+
switch (type)
{
case EVAS_FILTER_BLUR_GAUSSIAN:
break;
case EVAS_FILTER_BLUR_DEFAULT:
-
- /* In DEFAULT mode we cheat, depending on the size of the kernel:
- * For 1px to 2px, use true Gaussian blur.
- * For 3px to 6px, use two Box blurs.
- * For more than 6px, use three Box blurs.
- * This will give both nicer and MUCH faster results than Gaussian.
- *
- * NOTE: When implementing blur with GL shaders, other tricks will be
- * needed, of course!
- */
{
- const Eina_Bool alpha = in->alpha_only;
+ /* In DEFAULT mode we cheat, depending on the size of the kernel:
+ * For 1px to 2px, use true Gaussian blur.
+ * For 3px to 6px, use two Box blurs.
+ * For more than 6px, use three Box blurs.
+ * This will give both nicer and MUCH faster results than Gaussian.
+ *
+ * NOTE: This step should be avoided in GL.
+ */
+
int tmp_out = outbuf;
int tmp_in = inbuf;
int tmp_ox = ox;
int tmp_oy = oy;
+ // For 2D blur: create intermediate buffer
if (dx && dy)
{
- tmp = evas_filter_temporary_buffer_get(ctx, 0, 0, alpha);
+ tmp = evas_filter_temporary_buffer_get(ctx, 0, 0, in->alpha_only, 1);
if (!tmp) goto fail;
tmp_in = tmp_out = tmp->id;
tmp_ox = tmp_oy = 0;
}
+ // X box blur
if (dx)
{
if (dx <= 2)
type = EVAS_FILTER_BLUR_GAUSSIAN;
else
- type = EVAS_FILTER_BLUR_BOX;
+ type = EVAS_FILTER_BLUR_BOX;
- if (dy && (color != 0xFFFFFFFF))
- ENFN->context_color_set(ENDT, drawctx, 255, 255, 255, 255);
+ if (dy) ENFN->context_color_set(ENDT, drawctx, 255, 255, 255, 255);
cmd = evas_filter_command_blur_add(ctx, drawctx, inbuf, tmp_out,
type, dx, 0, tmp_ox, tmp_oy, 0);
if (!cmd) goto fail;
cmd->blur.auto_count = EINA_TRUE;
- if (dy && (color != 0xFFFFFFFF))
- ENFN->context_color_set(ENDT, drawctx, R, G, B, A);
+ if (dy) ENFN->context_color_set(ENDT, drawctx, R, G, B, A);
}
+ // Y box blur
if (dy)
{
if (dy <= 2)
else
type = EVAS_FILTER_BLUR_BOX;
+ if (dx && (inbuf == outbuf))
+ ENFN->context_render_op_set(ENDT, drawctx, EVAS_RENDER_COPY);
cmd = evas_filter_command_blur_add(ctx, drawctx, tmp_in, outbuf,
type, 0, dy, ox, oy, 0);
+ if (dx && (inbuf == outbuf))
+ ENFN->context_render_op_set(ENDT, drawctx, render_op);
if (!cmd) goto fail;
cmd->blur.auto_count = EINA_TRUE;
}
return cmd;
}
- break;
default:
CRI("Not implemented yet!");
goto fail;
}
- if ((blend || (in->alpha_only && !out->alpha_only)) ||
- (!blend && !in->alpha_only && !out->alpha_only && (color != 0xFFFFFFFF)) ||
- (!in->alpha_only && out->alpha_only))
- {
- XDBG("Adding extra blending step %d --> %d (%s --> %s)", in->id, out->id,
- in->alpha_only ? "Alpha" : "RGBA",
- out->alpha_only ? "Alpha" : "RGBA");
- Eina_Bool wasl = in->locked;
- in->locked = 1;
- blur_out = evas_filter_temporary_buffer_get(ctx, 0, 0, in->alpha_only);
- in->locked = wasl;
- if (!blur_out) goto fail;
- blend = EINA_TRUE;
- }
- else
- blur_out = out;
-
+ // For 2D blur: create intermediate buffer between X and Y passes
if (dx && dy)
{
- tmp = evas_filter_temporary_buffer_get(ctx, 0, 0, in->alpha_only);
- if (!tmp) goto fail;
-
- if (!blend && (ox || oy))
+ // If there's an offset: create intermediate buffer before offset blend
+ if (ox || oy)
{
- copybuf = evas_filter_temporary_buffer_get(ctx, 0, 0, in->alpha_only);
+ copybuf = evas_filter_temporary_buffer_get(ctx, 0, 0, in->alpha_only, 0);
if (!copybuf) goto fail;
- copy_back = EINA_TRUE;
}
- if (in == blur_out)
+ // Intermediate buffer between X and Y passes
+ tmp = evas_filter_temporary_buffer_get(ctx, 0, 0, in->alpha_only, 0);
+ if (!tmp) goto fail;
+
+ if (in == out)
{
// IN = OUT and 2-D blur. IN -blur-> TMP -blur-> IN.
out_dx = tmp;
// IN != OUT and 2-D blur. IN -blur-> TMP -blur-> OUT.
out_dx = tmp;
in_dy = tmp;
- out_dy = copybuf ? copybuf : blur_out;
+ out_dy = copybuf ? copybuf : out;
}
}
else if (dx)
{
- if ((in == blur_out) || ox || oy)
+ // X blur only
+ if (in == out)
{
// IN = OUT and 1-D blur. IN -blur-> TMP -copy-> IN.
- tmp = evas_filter_temporary_buffer_get(ctx, 0, 0, in->alpha_only);
+ tmp = evas_filter_temporary_buffer_get(ctx, 0, 0, in->alpha_only, 0);
if (!tmp) goto fail;
- copy_back = EINA_TRUE;
copybuf = tmp;
out_dx = tmp;
}
+ else if (ox || oy || (color != 0xFFFFFFFF))
+ {
+ // IN != OUT and 1-D blur. IN -blur-> TMP -blend-> OUT.
+ tmp = evas_filter_temporary_buffer_get(ctx, 0, 0, in->alpha_only, 0);
+ if (!tmp) goto fail;
+ blendbuf = tmp;
+ out_dx = tmp;
+ }
+ else if (out->dirty)
+ {
+ // IN != OUT and 1-D blur. IN -blur-> TMP -blend-> OUT.
+ tmp = evas_filter_temporary_buffer_get(ctx, 0, 0, in->alpha_only, 0);
+ if (!tmp) goto fail;
+ blendbuf = tmp;
+ out_dx = tmp;
+ }
else
{
// IN != OUT and 1-D blur. IN -blur-> OUT.
- out_dx = blur_out;
+ out_dx = out;
}
}
else
{
- if ((in == blur_out) || ox || oy)
+ // Y blur only
+ if (in == out)
{
// IN = OUT and 1-D blur. IN -blur-> TMP -copy-> IN.
- tmp = evas_filter_temporary_buffer_get(ctx, 0, 0, in->alpha_only);
+ tmp = evas_filter_temporary_buffer_get(ctx, 0, 0, in->alpha_only, 0);
if (!tmp) goto fail;
- copy_back = EINA_TRUE;
copybuf = tmp;
in_dy = in;
out_dy = tmp;
}
+ else if (ox || oy || (color != 0xFFFFFFFF))
+ {
+ // IN != OUT and 1-D blur. IN -blur-> TMP -blend-> IN.
+ tmp = evas_filter_temporary_buffer_get(ctx, 0, 0, in->alpha_only, 0);
+ if (!tmp) goto fail;
+ if (override)
+ copybuf = tmp;
+ else
+ blendbuf = tmp;
+ in_dy = in;
+ out_dy = tmp;
+ }
+ else if (out->dirty && !override)
+ {
+ // IN != OUT and 1-D blur. IN -blur-> TMP -blend-> OUT.
+ tmp = evas_filter_temporary_buffer_get(ctx, 0, 0, in->alpha_only, 0);
+ if (!tmp) goto fail;
+ blendbuf = tmp;
+ in_dy = in;
+ out_dy = tmp;
+ }
else
{
// IN != OUT and 1-D blur. IN -blur-> OUT.
in_dy = in;
- out_dy = blur_out;
+ out_dy = out;
}
}
cmd->blur.dx = dx;
cmd->blur.dy = 0;
cmd->blur.count = count;
- if (!dy && !blend)
- DRAW_COLOR_SET(R, G, B, A);
+ if (!dy) DRAW_COLOR_SET(R, G, B, A);
}
if (dy)
cmd->blur.dx = 0;
cmd->blur.dy = dy;
cmd->blur.count = count;
- if (!blend)
- DRAW_COLOR_SET(R, G, B, A);
+ DRAW_COLOR_SET(R, G, B, A);
}
- if (copy_back)
+ if (blendbuf)
+ {
+ Evas_Filter_Command *blendcmd;
+
+ XDBG("Add extra blend %d -> %d", blendbuf->id, out->id);
+ blendcmd = evas_filter_command_blend_add(ctx, drawctx,
+ blendbuf->id, out->id, ox, oy,
+ EVAS_FILTER_FILL_MODE_NONE);
+ if (!blendcmd) goto fail;
+ ox = oy = 0;
+ }
+ else if (copybuf)
{
Evas_Filter_Command *copycmd;
- int render_op;
- if (!cmd) goto fail;
- XDBG("Add copy %d -> %d", copybuf->id, blur_out->id);
+ XDBG("Add extra copy %d -> %d: offset: %d,%d", copybuf->id, out->id, ox, oy);
ENFN->context_color_set(ENDT, drawctx, 255, 255, 255, 255);
- render_op = ENFN->context_render_op_get(ENDT, drawctx);
ENFN->context_render_op_set(ENDT, drawctx, EVAS_RENDER_COPY);
- copycmd = evas_filter_command_blend_add(ctx, drawctx, copybuf->id, blur_out->id, ox, oy, EVAS_FILTER_FILL_MODE_NONE);
+ copycmd = evas_filter_command_blend_add(ctx, drawctx,
+ copybuf->id, out->id, ox, oy,
+ EVAS_FILTER_FILL_MODE_NONE);
ENFN->context_color_set(ENDT, drawctx, R, G, B, A);
ENFN->context_render_op_set(ENDT, drawctx, render_op);
if (!copycmd) goto fail;
ox = oy = 0;
}
- if (blend)
- {
- Evas_Filter_Command *blendcmd;
-
- XDBG("Add blend %d (%s) -> %d (%s)",
- blur_out->id, blur_out->alpha_only ? "Alpha" : "RGBA",
- out->id, out->alpha_only ? "Alpha" : "RGBA");
- blendcmd = evas_filter_command_blend_add(ctx, drawctx, blur_out->id, out->id, ox, oy, EVAS_FILTER_FILL_MODE_NONE);
- if (!blendcmd) goto fail;
- }
-
out->dirty = EINA_TRUE;
_filter_buffer_unlock_all(ctx);
return cmd;
{
Evas_Filter_Command *cmd;
Evas_Filter_Buffer *in, *out;
+ Eina_Bool copy;
int R, G, B, A;
EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL);
cmd = _command_new(ctx, EVAS_FILTER_MODE_BLEND, in, NULL, out);
if (!cmd) return NULL;
+ if (ENFN->context_render_op_get(ENDT, drawctx) == EVAS_RENDER_COPY)
+ copy = EINA_TRUE;
+ else
+ copy = EINA_FALSE;
+
ENFN->context_color_get(ENDT, drawctx, &R, &G, &B, &A);
DRAW_COLOR_SET(R, G, B, A);
DRAW_FILL_SET(fillmode);
cmd->draw.ox = ox;
cmd->draw.oy = oy;
- cmd->draw.rop = _evas_to_gfx_render_op(ENFN->context_render_op_get(ENDT, drawctx));
+ cmd->draw.rop = copy ? EFL_GFX_RENDER_OP_COPY : EFL_GFX_RENDER_OP_BLEND;
cmd->draw.clip_use =
ENFN->context_clip_get(ENDT, drawctx,
&cmd->draw.clip.x, &cmd->draw.clip.y,
&cmd->draw.clip.w, &cmd->draw.clip.h);
- XDBG("Add blend %d -> %d", in->id, out->id);
+ XDBG("Add %s %d -> %d: offset %d,%d, color: %d,%d,%d,%d",
+ copy ? "copy" : "blend", in->id, out->id, ox, oy, R, G, B, A);
if (cmd->draw.clip_use)
XDBG("Draw clip: %d,%d,%d,%d", cmd->draw.clip.x, cmd->draw.clip.y,
cmd->draw.clip.w, cmd->draw.clip.h);
in = _filter_buffer_get(ctx, inbuf);
EINA_SAFETY_ON_NULL_RETURN_VAL(in, NULL);
- if (inbuf != outbuf)
+ out = _filter_buffer_get(ctx, outbuf);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(out, NULL);
+
+ if ((inbuf != outbuf) && out->dirty)
{
- tmp = evas_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, 1);
EINA_SAFETY_ON_NULL_RETURN_VAL(tmp, NULL);
growbuf = tmp->id;
}
memset(curve + end, 255, 256 - end);
}
- out = _filter_buffer_get(ctx, growbuf);
- if (!out) return NULL;
- out->dirty = EINA_TRUE;
- if (growbuf != outbuf)
- {
- out = _filter_buffer_get(ctx, growbuf);
- if (!out) return NULL;
- out->dirty = EINA_TRUE;
- }
-
threshcmd = evas_filter_command_curve_add(ctx, draw_context, growbuf, growbuf,
curve, EVAS_FILTER_CHANNEL_ALPHA);
if (!threshcmd)
cmd->curve.data = copy;
cmd->curve.channel = channel;
- out->dirty = EINA_TRUE;
return cmd;
}
if (in == out)
{
- tmp = evas_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, 1);
if (!tmp) return NULL;
disp_out = tmp;
}
if (!fillcmd) goto fail;
}
- out->dirty = EINA_TRUE;
-
_filter_buffer_unlock_all(ctx);
return cmd;
cmd->draw.rop = render_op;
DRAW_COLOR_SET(R, G, B, A);
DRAW_FILL_SET(fillmode);
- out->dirty = EINA_TRUE;
return cmd;
}
cmd->bump.white = white;
cmd->bump.elevation = elevation;
cmd->bump.compensate = !!(flags & EVAS_FILTER_BUMP_COMPENSATE);
- out->dirty = EINA_TRUE;
return cmd;
}
else
cmd->draw.rop = EFL_GFX_RENDER_OP_BLEND;
- out->dirty = EINA_TRUE;
-
return cmd;
}
src = _filter_buffer_get(ctx, EVAS_FILTER_BUFFER_OUTPUT_ID);
EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE);
- image = evas_ector_buffer_drawable_image_get(src->buffer, EINA_FALSE);
+ image = evas_ector_buffer_drawable_image_get(src->buffer);
EINA_SAFETY_ON_NULL_GOTO(image, fail);
// FIXME: Use ector buffer RENDERER here
fb = _filter_buffer_get(ctx, bufid);
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE);
- surface = evas_ector_buffer_render_image_get(fb->buffer, EINA_FALSE);
+ surface = evas_ector_buffer_render_image_get(fb->buffer);
EINA_SAFETY_ON_NULL_RETURN_VAL(surface, EINA_FALSE);
// Copied from evas_font_draw_async_check
fb = _filter_buffer_get(ctx, bufid);
if (!fb) return EINA_FALSE;
- surface = evas_ector_buffer_render_image_get(fb->buffer, EINA_FALSE);
+ surface = evas_ector_buffer_render_image_get(fb->buffer);
EINA_SAFETY_ON_NULL_RETURN_VAL(surface, EINA_FALSE);
ENFN->image_size_get(ENDT, image, &dw, &dh);
#define FNAME(a) case EVAS_FILTER_MODE_ ## a: return "EVAS_FILTER_MODE_" #a
switch (mode)
{
+ FNAME(SKIP);
FNAME(BLEND);
FNAME(BLUR);
FNAME(CURVE);
{
Evas_Filter_Support support = EVAS_FILTER_SUPPORT_NONE;
+ if (cmd->mode == EVAS_FILTER_MODE_SKIP)
+ return EINA_TRUE;
+
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input, EINA_FALSE);
typedef struct _Ector_GL_Buffer_Map Ector_GL_Buffer_Map;
typedef struct _Evas_Ector_GL_Buffer_Data Evas_Ector_GL_Buffer_Data;
+static int _map_id = 0;
+
struct _Ector_GL_Buffer_Map
{
EINA_INLIST;
unsigned int base_size; // in bytes
unsigned int x, y, w, h;
void *image_data, *base_data;
+ int map_id;
size_t length;
Efl_Gfx_Colorspace cspace;
Evas_GL_Image *im;
{
Evas_Public_Data *evas;
Evas_GL_Image *glim;
- Eina_Bool alpha_only;
+ Eina_Bool alpha_only, was_render;
Ector_GL_Buffer_Map *maps;
};
#define fail(fmt, ...) do { ERR(fmt, ##__VA_ARGS__); goto on_fail; } while (0)
+#if 0
+static inline void
+_mapped_image_dump(Eo *buf, Evas_GL_Image *im, const char *fmt, int id)
+{
+ if (!im || !im->im) return;
+ evas_common_save_image_to_file(im->im, eina_slstr_printf("/tmp/dump/%s_%02d_buf_%p_im_%p.png", fmt, id, buf, im),
+ NULL, 100, 9, NULL);
+}
+
+#define MAP_DUMP(_im, _fmt) _mapped_image_dump(obj, _im, _fmt, map->map_id)
+#else
+#define MAP_DUMP(...)
+#endif
+
/* FIXME: Conversion routines don't belong here */
static inline void
_pixels_argb_to_gry8_convert(uint8_t *dst, const uint32_t *src, int len)
pd->glim = NULL;
}
-EOLIAN static void *
-_evas_ector_gl_buffer_evas_ector_buffer_drawable_image_get(Eo *obj EINA_UNUSED,
- Evas_Ector_GL_Buffer_Data *pd,
- Eina_Bool update)
+static inline void *
+_image_get(Evas_Ector_GL_Buffer_Data *pd, Eina_Bool render)
{
- Render_Engine_GL_Generic *re = pd->evas->engine.data.output;
- Evas_Engine_GL_Context *gc;
-
if (pd->maps != NULL)
fail("Image is currently mapped!");
evas_gl_common_image_ref(pd->glim);
- if (!update) return pd->glim;
-
- gc = re->window_gl_context_get(re->software.ob);
- evas_gl_common_image_update(gc, pd->glim);
-
+ if (render) pd->was_render = EINA_TRUE;
return pd->glim;
on_fail:
}
EOLIAN static void *
-_evas_ector_gl_buffer_evas_ector_buffer_render_image_get(Eo *obj EINA_UNUSED,
- Evas_Ector_GL_Buffer_Data *pd,
- Eina_Bool update)
+_evas_ector_gl_buffer_evas_ector_buffer_drawable_image_get(Eo *obj EINA_UNUSED,
+ Evas_Ector_GL_Buffer_Data *pd)
{
- Render_Engine_GL_Generic *re = pd->evas->engine.data.output;
- Evas_Engine_GL_Context *gc;
-
- if (pd->maps != NULL)
- fail("Image is currently mapped!");
-
- evas_gl_common_image_ref(pd->glim);
- if (!update) return pd->glim;
-
- gc = re->window_gl_context_get(re->software.ob);
- evas_gl_common_image_update(gc, pd->glim);
-
- return pd->glim;
+ return _image_get(pd, EINA_FALSE);
+}
-on_fail:
- return NULL;
+EOLIAN static void *
+_evas_ector_gl_buffer_evas_ector_buffer_render_image_get(Eo *obj EINA_UNUSED,
+ Evas_Ector_GL_Buffer_Data *pd)
+{
+ return _image_get(pd, EINA_TRUE);
}
EOLIAN static Eina_Bool
EINA_SAFETY_ON_NULL_RETURN_VAL(image, EINA_FALSE);
EINA_SAFETY_ON_FALSE_RETURN_VAL(pd->glim == image, EINA_FALSE);
+ if (pd->was_render)
+ {
+ Render_Engine_GL_Generic *re = pd->evas->engine.data.output;
+ Evas_Engine_GL_Context *gc;
+
+ gc = re->window_gl_context_get(re->software.ob);
+ pd->glim = evas_gl_common_image_surface_detach(gc, pd->glim);
+ }
evas_gl_common_image_free(pd->glim);
return EINA_TRUE;
pxs = 4;
}
+ map->map_id = ++_map_id;
map->base_size = len * pxs;
map->length = (W * h + w - W) * pxs;
if (stride) *stride = W * pxs;
if (length) *length = map->length;
- EINA_INLIST_PREPEND(pd->maps, map);;
+ MAP_DUMP(im, "in");
+
+ EINA_INLIST_PREPEND(pd->maps, map);
return map->ptr;
on_fail:
if (map->im)
{
+ MAP_DUMP(map->im, "out_w_free");
pd->glim = evas_gl_common_image_surface_update(gc, map->im);
evas_gl_common_image_free(old_glim);
}
else
{
+ MAP_DUMP(old_glim, "out_w_nofree");
pd->glim = evas_gl_common_image_surface_update(gc, old_glim);
}
}
else
{
if (map->im)
- ENFN->image_free(ENDT, map->im);
+ {
+ MAP_DUMP(map->im, "out_ro_free");
+ ENFN->image_free(ENDT, map->im);
+ }
else
- ENFN->image_data_put(ENDT, pd->glim, map->image_data);
+ {
+ MAP_DUMP(pd->glim, "out_ro_nofree");
+ ENFN->image_data_put(ENDT, pd->glim, map->image_data);
+ }
}
if (map->allocated)
free(map->base_data);
#include "gl_engine_filter.h"
+// Copied logic from SW engine
+static Eina_Bool
+_mapped_blend(Evas_Engine_GL_Context *gc,
+ Evas_GL_Image *image,
+ Evas_Filter_Fill_Mode fillmode,
+ int sx, int sy, int sw, int sh,
+ int dx, int dy, int dw, int dh)
+{
+ int right = 0, bottom = 0, left = 0, top = 0;
+ int row, col, rows, cols;
+ Eina_Bool ret = EINA_TRUE;
+
+ EINA_SAFETY_ON_FALSE_RETURN_VAL((sx == 0) && (sy == 0), EINA_FALSE);
+
+ if (fillmode == EVAS_FILTER_FILL_MODE_NONE)
+ {
+ DBG("blend: %d,%d,%d,%d --> %d,%d,%d,%d", sx, sy, sw, sh, dx, dy, sw, sh);
+ evas_gl_common_image_draw(gc, image, sx, sy, sw, sh, dx, dy, sw, sh, EINA_TRUE);
+ return EINA_TRUE;
+ }
+
+ if (fillmode & EVAS_FILTER_FILL_MODE_REPEAT_X)
+ {
+ if (dx > 0) left = dx % sw;
+ else if (dx < 0) left = sw + (dx % sw);
+ cols = (dw /*- left*/) / sw;
+ if (left > 0)
+ right = dw - (sw * (cols - 1)) - left;
+ else
+ right = dw - (sw * cols);
+ dx = 0;
+ }
+ else if (fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X)
+ {
+ cols = 0;
+ dx = 0;
+ }
+ else
+ {
+ // FIXME: Probably wrong if dx != 0
+ cols = 0;
+ dw -= dx;
+ }
+
+ if (fillmode & EVAS_FILTER_FILL_MODE_REPEAT_Y)
+ {
+ if (dy > 0) top = dy % sh;
+ else if (dy < 0) top = sh + (dy % sh);
+ rows = (dh /*- top*/) / sh;
+ if (top > 0)
+ bottom = dh - (sh * (rows - 1)) - top;
+ else
+ bottom = dh - (sh * rows);
+ dy = 0;
+ }
+ else if (fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y)
+ {
+ rows = 0;
+ dy = 0;
+ }
+ else
+ {
+ // FIXME: Probably wrong if dy != 0
+ rows = 0;
+ dh -= dy;
+ }
+
+ if (top > 0) row = -1;
+ else row = 0;
+ for (; row <= rows; row++)
+ {
+ int src_x, src_y, src_w, src_h;
+ int dst_x, dst_y, dst_w, dst_h;
+
+ if (row == -1 && top > 0)
+ {
+ // repeat only
+ src_h = top;
+ src_y = sh - top;
+ dst_y = dy;
+ dst_h = src_h;
+ }
+ else if (row == rows && bottom > 0)
+ {
+ // repeat only
+ src_h = bottom;
+ src_y = 0;
+ dst_y = top + dy + row * sh;
+ dst_h = src_h;
+ }
+ else
+ {
+ src_y = 0;
+ if (fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y)
+ {
+ src_h = sh;
+ dst_h = dh;
+ dst_y = 0;
+ }
+ else
+ {
+ dst_y = top + dy + row * sh;
+ src_h = MIN(dh - dst_y, sh);
+ dst_h = src_h;
+ }
+ }
+ if (src_h <= 0 || dst_h <= 0) break;
+
+ if (left > 0) col = -1;
+ else col = 0;
+ for (; col <= cols; col++)
+ {
+ if (col == -1 && left > 0)
+ {
+ // repeat only
+ src_w = left;
+ src_x = sw - left;
+ dst_x = dx;
+ dst_w = src_w;
+ }
+ else if (col == cols && right > 0)
+ {
+ // repeat only
+ src_w = right;
+ src_x = 0;
+ dst_x = left + dx + col * sw;
+ dst_w = src_w;
+ }
+ else
+ {
+ src_x = 0;
+ if (fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X)
+ {
+ src_w = sw;
+ dst_w = dw;
+ dst_x = 0;
+ }
+ else
+ {
+ dst_x = left + dx + col * sw;
+ src_w = MIN(dw - dst_x, sw);
+ dst_w = src_w;
+ }
+ }
+ if (src_w <= 0 || dst_w <= 0) break;
+
+ DBG("blend: [%d,%d] %d,%d,%dx%d --> %d,%d,%dx%d "
+ "(src %dx%d, dst %dx%d)",
+ col, row, src_x, src_y, src_w, src_h,
+ dst_x, dst_y, dst_w, dst_h, sw, sh, dw, dh);
+ evas_gl_common_image_draw(gc, image, src_x, src_y, src_w, src_h,
+ dst_x, dst_y, dst_w, dst_h, EINA_TRUE);
+ }
+ }
+ return ret;
+}
+
static Eina_Bool
_gl_filter_blend(Render_Engine_GL_Generic *re, Evas_Filter_Command *cmd)
{
re->window_use(re->software.ob);
gc = re->window_gl_context_get(re->software.ob);
- image = evas_ector_buffer_drawable_image_get(cmd->input->buffer, EINA_TRUE);
+ image = evas_ector_buffer_drawable_image_get(cmd->input->buffer);
EINA_SAFETY_ON_NULL_RETURN_VAL(image, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(image->tex, EINA_FALSE);
- surface = evas_ector_buffer_render_image_get(cmd->output->buffer, EINA_FALSE);
+ surface = evas_ector_buffer_render_image_get(cmd->output->buffer);
EINA_SAFETY_ON_NULL_RETURN_VAL(surface, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(surface->tex, EINA_FALSE);
EINA_SAFETY_ON_FALSE_RETURN_VAL(surface->tex->pt->fb != 0, EINA_FALSE);
evas_gl_common_context_target_surface_set(gc, surface);
- // TODO: mapped render iteration
-
dc_save = gc->dc;
gc->dc = evas_common_draw_context_new();
evas_common_draw_context_set_multiplier(gc->dc, cmd->draw.R, cmd->draw.G, cmd->draw.B, cmd->draw.A);
+ gc->dc->render_op = _gfx_to_evas_render_op(cmd->draw.rop);
- evas_gl_common_image_draw(gc, image, 0, 0, image->w, image->h,
- cmd->draw.ox, cmd->draw.oy, image->w, image->h,
- EINA_TRUE);
+ DBG("blend %d @%p -> %d @%p", cmd->input->id, cmd->input->buffer,
+ cmd->output->id, cmd->output->buffer);
+ _mapped_blend(gc, image, cmd->draw.fillmode, 0, 0, image->w, image->h,
+ cmd->draw.ox, cmd->draw.oy, cmd->output->w, cmd->output->h);
evas_common_draw_context_free(gc->dc);
gc->dc = dc_save;