#define FCOW_END(_fcow, _pd) eina_cow_done(evas_object_filter_cow, (const Eina_Cow_Data**)&(_pd->data), _fcow, EINA_TRUE)
typedef struct _Evas_Filter_Data Evas_Filter_Data;
+typedef struct _Evas_Filter_Post_Render_Data Evas_Filter_Post_Render_Data;
+
struct _Evas_Filter_Data
{
const Evas_Object_Filter_Data *data;
+ Eina_Bool has_cb;
+ SLK(lck);
+ Eina_List *post_data;
+};
+
+struct _Evas_Filter_Post_Render_Data
+{
+ Evas_Filter_Context *ctx;
+ Eina_Bool success;
};
static void
-_filter_cb(Evas_Filter_Context *ctx, void *data, Eina_Bool success)
+_filter_end_sync(Evas_Filter_Context *ctx, Evas_Object_Protected_Data *obj,
+ Evas_Filter_Data *pd, Eina_Bool success)
{
- Eo *eo_obj = data;
- Evas_Filter_Data *pd = eo_data_scope_get(eo_obj, MY_CLASS);
+ void *previous = pd->data->output;
+ Eo *eo_obj = obj->object;
- // FIXME: This needs to run in the main loop
+#ifdef DEBUG
+ EINA_SAFETY_ON_FALSE_RETURN(eina_main_loop_is());
+#endif
- // Redraw text with normal styles in case of failure
if (!success)
{
- Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
-
ERR("Filter failed at runtime!");
eo_do(eo_obj,
evas_filter_invalid_set(EINA_TRUE);
}
// Destroy context as we won't reuse it.
+ evas_filter_buffer_backing_release(ctx, previous);
evas_filter_context_destroy(ctx);
}
+static Eina_Bool
+_render_post_cb(void *data, Eo *evas EINA_UNUSED,
+ const Eo_Event_Description2 *desc EINA_UNUSED,
+ void *event_info EINA_UNUSED)
+{
+ Eo *eo_obj = data;
+ Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
+ Evas_Filter_Data *pd = eo_data_scope_get(eo_obj, MY_CLASS);
+ Eina_List *post_data;
+ Evas_Filter_Post_Render_Data *task;
+
+ SLKL(pd->lck);
+ post_data = pd->post_data;
+ pd->post_data = NULL;
+ SLKU(pd->lck);
+
+ EINA_LIST_FREE(post_data, task)
+ {
+ _filter_end_sync(task->ctx, obj, pd, task->success);
+ free(task);
+ }
+
+ return EO_CALLBACK_CONTINUE;
+}
+
+static void
+_filter_cb(Evas_Filter_Context *ctx, void *data, Eina_Bool success)
+{
+ Eo *eo_obj = data;
+ Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
+ Evas_Filter_Data *pd = eo_data_scope_get(eo_obj, MY_CLASS);
+ Evas_Filter_Post_Render_Data *post_data;
+
+ if (!pd->data->async)
+ {
+ _filter_end_sync(ctx, obj, pd, success);
+ return;
+ }
+
+ post_data = calloc(1, sizeof(*post_data));
+ post_data->success = success;
+ post_data->ctx = ctx;
+ SLKL(pd->lck);
+ pd->post_data = eina_list_append(pd->post_data, post_data);
+ SLKU(pd->lck);
+}
+
static void
_filter_source_hash_free_cb(void *data)
{
{
Evas_Filter_Data *pd = eo_data_scope_get(eo_obj, MY_CLASS);
- // FIXME: Forcing sync render for all engines! (cb needs the main loop)
- if (do_async) WRN("Disarding async render flag!");
- do_async = EINA_FALSE;
-
if (!pd->data->invalid && (pd->data->chain || pd->data->code))
{
int X, Y, W, H, l = 0, r = 0, t = 0, b = 0;
if (!redraw)
{
+ if (pd->has_cb)
+ {
+ // Post render callback is not required anymore
+ Evas *e = obj->layer->evas->evas;
+ eo_do(e, eo_event_callback_del(EVAS_CANVAS_EVENT_RENDER_POST,
+ _render_post_cb, eo_obj));
+ pd->has_cb = EINA_FALSE;
+ }
+
// Render this image only
ENFN->image_draw(ENDT, context,
surface, previous,
evas_filter_context_buffers_allocate_all(filter);
evas_filter_target_set(filter, context, surface, X + x, Y + y);
- // Release previous output
- evas_filter_buffer_backing_release(filter, previous);
-
// Request rendering from the object itself (child class)
evas_filter_program_padding_get(pd->data->chain, &l, &r, &t, &b);
eo_do(eo_obj, ok = evas_filter_input_render(filter, drawctx, l, r, t, b, do_async));
ENFN->context_free(ENDT, drawctx);
// Add post-run callback and run filter
+ if (do_async && !pd->has_cb)
+ {
+ Evas *e = obj->layer->evas->evas;
+ eo_do(e, eo_event_callback_add(EVAS_CANVAS_EVENT_RENDER_POST,
+ _render_post_cb, eo_obj));
+ pd->has_cb = EINA_TRUE;
+ }
evas_filter_context_post_run_callback_set(filter, _filter_cb, eo_obj);
ok = evas_filter_run(filter);
fcow = FCOW_BEGIN(pd);
- fcow->output = NULL;
fcow->changed = EINA_FALSE;
fcow->async = do_async;
if (!ok) fcow->invalid = EINA_TRUE;
_evas_filter_constructor(Eo *eo_obj EINA_UNUSED, Evas_Filter_Data *pd)
{
pd->data = eina_cow_alloc(evas_object_filter_cow);
+ SLKI(pd->lck);
}
EOLIAN void
evas_filter_program_del(pd->data->chain);
eina_stringshare_del(pd->data->code);
eina_cow_free(evas_object_filter_cow, (const Eina_Cow_Data **) &pd->data);
+ if (pd->has_cb)
+ {
+ Evas *e = obj->layer->evas->evas;
+ eo_do(e, eo_event_callback_del(EVAS_CANVAS_EVENT_RENDER_POST,
+ _render_post_cb, eo_obj));
+ }
+ SLKD(pd->lck);
}
EOLIAN void
ctx->evas = evas;
ctx->async = async;
- /* Note:
- * For now, we need to detect whether the engine is full SW or GL.
- * In case of GL, we will have two buffers in parallel:
- * RGBA_Image backing and a GL texture (glimage). We can't just leave it
- * to the engine to handle the image data since it will try to discard the
- * original buffer as early as possible to save memory, but we still need
- * it for filtering.
- * In the future, Evas_Engine functions need to be added to abstract this
- * better and implement filters direcly with shaders.
- */
- ctx->gl_engine = (evas->engine.func->gl_surface_read_pixels != NULL);
return ctx;
}
if (!stolen_buffer) return EINA_FALSE;
EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, EINA_FALSE);
- if (ctx->async)
- evas_unref_queue_image_put(ctx->evas, stolen_buffer);
- else
- {
- ctx->post_run.buffers_to_free =
- eina_list_append(ctx->post_run.buffers_to_free, stolen_buffer);
- }
+#ifdef DEBUG
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_main_loop_is(), EINA_FALSE);
+#endif
+ ENFN->image_free(ENDT, stolen_buffer);
return EINA_TRUE;
}
ctx->evas->engine.func->image_free(ctx->evas->engine.data.output, ctx->target.mask);
ctx->target.mask = mask;
-#if 0
- if (ctx->gl_engine)
- {
- // Since GL has sync rendering, draw_context is safe to keep around
- Evas_Filter_Buffer *fb;
-
- ctx->target.context = draw_context;
-
- fb = _filter_buffer_get(ctx, EVAS_FILTER_BUFFER_OUTPUT_ID);
- EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE);
- if (!fb->backing)
- return EINA_FALSE;
-
- fb->glimage = ENFN->image_new_from_data
- (ENDT, fb->w, fb->h, fb->backing->image.data, EINA_TRUE,
- fb->backing->cache_entry.space);
-
- XDBG("Set target as #%d (%p) and output #%d (%p, gl %p)",
- ctx->target.bufid, surface, fb->id, fb->backing, fb->glimage);
- }
-#endif
-
return EINA_TRUE;
}
EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(dst, EINA_FALSE);
-#if 0
- if (ctx->gl_engine)
- {
- drawctx = ctx->target.context;
- surface = dst->glimage;
- if (src->glimage)
- {
- XDBG("Using glimage from output buffer.");
- if (src->backing)
- ENFN->image_data_put(ENDT, src->glimage, src->backing->image.data);
- }
- else
- {
- RGBA_Image *im = src->backing;
-
- XDBG("Creating glimage from output buffer.");
- src->glimage = ENFN->image_new_from_data(ENDT, src->w, src->h,
- im->image.data, EINA_TRUE,
- EVAS_COLORSPACE_ARGB8888);
- }
- image = src->glimage;
- }
- else
-#endif
- {
- drawctx = ENFN->context_new(ENDT);
- image = _evas_image_get(src->buffer);
- surface = _evas_image_get(dst->buffer);
- }
+ drawctx = ENFN->context_new(ENDT);
+ image = _evas_image_get(src->buffer);
+ surface = _evas_image_get(dst->buffer);
EINA_SAFETY_ON_NULL_RETURN_VAL(image, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(surface, EINA_FALSE);
ctx->target.x, ctx->target.y, src->w, src->h,
EINA_TRUE, EINA_FALSE);
- if (ctx->target.mask)
- ENFN->context_clip_image_unset(ENDT, drawctx);
-
- if (!ctx->gl_engine)
- ENFN->context_free(ENDT, drawctx);
- else if (use_clip)
- ENFN->context_clip_set(ENDT, drawctx, cx, cy, cw, ch);
- else
- ENFN->context_clip_unset(ENDT, drawctx);
-
+ ENFN->context_free(ENDT, drawctx);
return EINA_TRUE;
}
ctx->running = EINA_FALSE;
DEBUG_TIME_END();
- EINA_LIST_FREE(ctx->post_run.buffers_to_free, buffer)
- ENFN->image_free(ENDT, buffer);
-
return ok;
}
if (!ctx->commands)
return EINA_TRUE;
- if (ctx->gl_engine && !warned)
+ if (ENFN->gl_surface_read_pixels && !warned)
{
- DBG("OpenGL support through SW functions, expect low performance!");
+ WRN("OpenGL support through SW functions, expect low performance!");
warned = 1;
}