obj->layer->evas->engine.func->image_stride_get(obj->layer->evas->engine.data.output, o->engine_data, &stride);
else
stride = w * 4;
+
EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
{
state_write->has_alpha = obj->layer->evas->engine.func->image_alpha_get(obj->layer->evas->engine.data.output, o->engine_data);
if (pixels)
{
Evas_Coord idw, idh, idx, idy;
+ int l = 0, r = 0, t = 0, b = 0;
int ix, iy, iw, ih;
if ((obj->map->cur.map) && (obj->map->cur.map->count > 3) && (obj->map->cur.usemap))
Evas_Filter_Context *filter = NULL;
void * const surface_save = surface;
void * const context_save = context;
- const Eina_Bool do_async_save = do_async;
- int l = 0, r = 0, t = 0, b = 0;
+ Eina_Bool input_stolen = EINA_FALSE;
Eina_Bool clear = EINA_FALSE;
int W, H, offx, offy;
/* Evas Filters on Image Object. Yet another experimental piece of code.
* Replace current context, offset and surface by filter-made targets.
+ *
+ * Mechanism:
+ * 1. Create a new surface & context, matching the object geometry
+ * 2. Render all borders & tiles into that surface
+ * 3. Apply effect and draw this surface into the original target
+ *
+ * Notes:
+ * This becomes VERY SLOW when the image OBJECT size grows... even if
+ * the image itself is very small. But we can't really apply a proper blur
+ * over one tile and repeat since blurs should overlap.
+ *
+ * Behaviour depends on the 'filled' flag:
+ * - If filled, then scale down the image to accomodate the whole filter's padding.
+ * - Otherwise, draw image in place and clip the filter's effects (eg. blur will be clipped out).
*/
if (!o->cur->filter.invalid && o->cur->filter.code)
{
Eina_Bool ok;
evas_filter_program_padding_get(pgm, &l, &r, &t, &b);
- W = obj->cur->geometry.w + l + r;
- H = obj->cur->geometry.h + t + b;
+ W = obj->cur->geometry.w;
+ H = obj->cur->geometry.h;
if (!redraw && o->cur->filter.output)
{
if (obj->layer->evas->engine.func->gl_surface_read_pixels)
{
- evas_filter_context_proxy_render_all(filter, eo_obj, EINA_FALSE);
+ // GL case: Create new surface, draw to it (OpenGL) and call glReadPixels
surface = obj->layer->evas->engine.func->image_map_surface_new(output, W, H, EINA_TRUE);
+ input_stolen = EINA_FALSE;
+ }
+ else
+ {
+ // Software case: Directly draw into the filter's input buffer
+ surface = evas_filter_buffer_backing_steal(filter, EVAS_FILTER_BUFFER_INPUT_ID);
+ input_stolen = EINA_TRUE;
+ }
+
+ if (!surface)
+ {
+ surface = surface_save;
+ ok = EINA_FALSE;
}
state_write:
{
if (ok)
{
- offx = l;
- offy = t;
context = obj->layer->evas->engine.func->context_new(output);
clear = EINA_TRUE;
- do_async = EINA_FALSE;
state_write->filter.chain = pgm;
+ if (!o->filled)
+ {
+ offx = 0;
+ offy = 0;
+ }
+ else
+ {
+ offx = l;
+ offy = t;
+ }
}
else
{
}
}
EINA_COW_IMAGE_STATE_WRITE_END(o, state_write)
+
+ if (clear)
+ {
+ obj->layer->evas->engine.func->context_color_set(output, context, 0, 0, 0, 0);
+ obj->layer->evas->engine.func->context_render_op_set(output, context, EVAS_RENDER_COPY);
+ obj->layer->evas->engine.func->rectangle_draw(output, context, surface, 0, 0, W, H, EINA_FALSE);
+ obj->layer->evas->engine.func->context_color_set(output, context, 255, 255, 255, 255);
+ obj->layer->evas->engine.func->context_render_op_set(output, context, EVAS_RENDER_BLEND);
+ }
}
while ((int)idx < obj->cur->geometry.w)
else
iw = ((int)(idx + idw)) - ix;
- if (clear)
- {
- obj->layer->evas->engine.func->context_color_set(output, context, 0, 0, 0, 0);
- obj->layer->evas->engine.func->context_render_op_set(output, context, EVAS_RENDER_COPY);
- obj->layer->evas->engine.func->rectangle_draw(output, context, surface, 0, 0, W, H, EINA_FALSE);
- obj->layer->evas->engine.func->context_color_set(output, context, 255, 255, 255, 255);
- obj->layer->evas->engine.func->context_render_op_set(output, context, EVAS_RENDER_BLEND);
- }
+ // Filter stuff
+ if (o->filled)
+ iw -= l + r;
while ((int)idy < obj->cur->geometry.h)
{
}
else
ih = ((int)(idy + idh)) - iy;
+
+ // Filter stuff
+ if (o->filled)
+ ih -= t + b;
+
if ((o->cur->border.l == 0) &&
(o->cur->border.r == 0) &&
(o->cur->border.t == 0) &&
EINA_COW_IMAGE_STATE_WRITE_END(o, state_write)
}
- evas_filter_image_draw(filter, context, EVAS_FILTER_BUFFER_INPUT_ID, surface, do_async_save);
- obj->layer->evas->engine.func->context_free(output, context);
+ if (!input_stolen)
+ evas_filter_image_draw(filter, context, EVAS_FILTER_BUFFER_INPUT_ID, surface, do_async);
+ else
+ evas_filter_buffer_backing_release(filter, surface);
evas_filter_target_set(filter, context_save, surface_save, obj->cur->geometry.x + x, obj->cur->geometry.y + y);
evas_filter_context_autodestroy(filter);
evas_filter_run(filter);
- obj->layer->evas->engine.func->image_map_surface_free(output, surface);
+ if (!input_stolen)
+ obj->layer->evas->engine.func->image_map_surface_free(output, surface);
+ obj->layer->evas->engine.func->context_free(output, context);
}
}
}