2016-06-09 23:55:28 -07:00
|
|
|
#define EFL_CANVAS_FILTER_INTERNAL_PROTECTED
|
2015-06-23 01:25:44 -07:00
|
|
|
|
2015-06-17 00:26:30 -07:00
|
|
|
#include "evas_common_private.h"
|
|
|
|
#include "evas_private.h"
|
|
|
|
#include "../../lib/efl/interfaces/efl_gfx_filter.eo.h"
|
2016-06-09 23:55:28 -07:00
|
|
|
#include "efl_canvas_filter_internal.eo.h"
|
2015-06-17 00:26:30 -07:00
|
|
|
#include "evas_filter.h"
|
|
|
|
|
2016-06-09 23:55:28 -07:00
|
|
|
#define MY_CLASS EFL_CANVAS_FILTER_INTERNAL_MIXIN
|
2015-06-17 00:26:30 -07:00
|
|
|
|
|
|
|
#define ENFN obj->layer->evas->engine.func
|
|
|
|
#define ENDT obj->layer->evas->engine.data.output
|
|
|
|
|
2016-02-29 00:04:13 -08:00
|
|
|
#define FCOW_BEGIN(_pd) ({ Evas_Object_Filter_Data *_fcow = eina_cow_write(evas_object_filter_cow, (const Eina_Cow_Data**)&(_pd->data)); _state_check(_fcow); _fcow; })
|
2016-01-04 04:46:56 -08:00
|
|
|
#define FCOW_END(_fcow, _pd) eina_cow_done(evas_object_filter_cow, (const Eina_Cow_Data**)&(_pd->data), _fcow, EINA_TRUE)
|
2017-04-03 18:25:05 -07:00
|
|
|
#define FCOW_WRITE(pd, name, value) do { \
|
|
|
|
if (pd->data->name != (value)) { \
|
|
|
|
fcow = FCOW_BEGIN(pd); \
|
|
|
|
fcow->name = (value); \
|
|
|
|
FCOW_END(fcow, pd); \
|
|
|
|
}} while (0)
|
2016-01-04 04:46:56 -08:00
|
|
|
|
2015-06-17 00:26:30 -07:00
|
|
|
typedef struct _Evas_Filter_Data Evas_Filter_Data;
|
2016-01-06 23:54:42 -08:00
|
|
|
typedef struct _Evas_Filter_Post_Render_Data Evas_Filter_Post_Render_Data;
|
|
|
|
|
2017-03-23 00:22:43 -07:00
|
|
|
struct _Evas_Object_Filter_Data
|
|
|
|
{
|
|
|
|
Evas_Object_Protected_Data *obj;
|
|
|
|
Eina_Stringshare *name;
|
|
|
|
Eina_Stringshare *code;
|
|
|
|
Evas_Filter_Program *chain;
|
|
|
|
Evas_Filter_Context *context;
|
|
|
|
Eina_Hash *sources; // Evas_Filter_Proxy_Binding
|
|
|
|
Eina_Inlist *data; // Evas_Filter_Data_Binding
|
|
|
|
Eina_Rectangle prev_obscured, obscured;
|
2017-03-22 23:55:41 -07:00
|
|
|
Evas_Filter_Padding prev_padding, padding;
|
2017-03-23 00:22:43 -07:00
|
|
|
void *output;
|
|
|
|
struct {
|
|
|
|
struct {
|
|
|
|
Eina_Stringshare *name;
|
|
|
|
double value;
|
|
|
|
} cur;
|
|
|
|
struct {
|
|
|
|
Eina_Stringshare *name;
|
|
|
|
double value;
|
|
|
|
} next;
|
|
|
|
double pos;
|
|
|
|
} state;
|
2017-04-03 18:25:05 -07:00
|
|
|
int obscured_changes;
|
2017-03-23 00:22:43 -07:00
|
|
|
Eina_Bool changed : 1;
|
|
|
|
Eina_Bool invalid : 1; // Code parse failed
|
|
|
|
Eina_Bool async : 1;
|
|
|
|
Eina_Bool reuse : 1;
|
|
|
|
};
|
|
|
|
|
2015-06-17 00:26:30 -07:00
|
|
|
struct _Evas_Filter_Data
|
|
|
|
{
|
|
|
|
const Evas_Object_Filter_Data *data;
|
2016-01-06 23:54:42 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct _Evas_Filter_Post_Render_Data
|
|
|
|
{
|
2016-12-22 03:18:51 -08:00
|
|
|
Evas_Filter_Data *pd;
|
2016-01-06 23:54:42 -08:00
|
|
|
Evas_Filter_Context *ctx;
|
|
|
|
Eina_Bool success;
|
2015-06-17 00:26:30 -07:00
|
|
|
};
|
|
|
|
|
2017-04-05 03:19:36 -07:00
|
|
|
// FIXME: This should be enabled (with proper heuristics)
|
|
|
|
#define FILTER_CONTEXT_REUSE EINA_FALSE
|
|
|
|
|
|
|
|
static const Evas_Object_Filter_Data evas_filter_data_cow_default = {
|
|
|
|
.reuse = FILTER_CONTEXT_REUSE
|
|
|
|
};
|
2017-03-23 00:22:43 -07:00
|
|
|
Eina_Cow *evas_object_filter_cow = NULL;
|
|
|
|
|
|
|
|
void
|
|
|
|
evas_filter_mixin_init(void)
|
|
|
|
{
|
|
|
|
evas_object_filter_cow = eina_cow_add
|
|
|
|
("Evas Filter Data", sizeof(Evas_Object_Filter_Data), 8,
|
|
|
|
&evas_filter_data_cow_default, EINA_TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
evas_filter_mixin_shutdown(void)
|
|
|
|
{
|
|
|
|
eina_cow_del(evas_object_filter_cow);
|
|
|
|
evas_object_filter_cow = NULL;
|
|
|
|
}
|
|
|
|
|
2016-02-29 00:04:13 -08:00
|
|
|
static inline void
|
|
|
|
_state_check(Evas_Object_Filter_Data *fcow)
|
|
|
|
{
|
|
|
|
if (!fcow->state.cur.name)
|
|
|
|
fcow->state.cur.name = eina_stringshare_add("default");
|
|
|
|
if (!fcow->state.next.name)
|
|
|
|
fcow->state.next.name = eina_stringshare_add("default");
|
|
|
|
}
|
|
|
|
|
2015-06-17 00:26:30 -07:00
|
|
|
static void
|
2016-01-06 23:54:42 -08:00
|
|
|
_filter_end_sync(Evas_Filter_Context *ctx, Evas_Object_Protected_Data *obj,
|
|
|
|
Evas_Filter_Data *pd, Eina_Bool success)
|
2015-06-17 00:26:30 -07:00
|
|
|
{
|
2016-01-06 23:54:42 -08:00
|
|
|
void *previous = pd->data->output;
|
2017-03-22 00:55:26 -07:00
|
|
|
Eina_Bool destroy = !pd->data->reuse;
|
|
|
|
Evas_Object_Filter_Data *fcow;
|
2016-01-06 23:54:42 -08:00
|
|
|
Eo *eo_obj = obj->object;
|
2017-04-05 03:19:36 -07:00
|
|
|
void *output = NULL;
|
2015-06-17 00:26:30 -07:00
|
|
|
|
|
|
|
if (!success)
|
|
|
|
{
|
|
|
|
ERR("Filter failed at runtime!");
|
2016-03-01 10:06:28 -08:00
|
|
|
evas_filter_invalid_set(eo_obj, EINA_TRUE);
|
|
|
|
evas_filter_dirty(eo_obj);
|
2017-03-22 00:55:26 -07:00
|
|
|
destroy = EINA_TRUE;
|
2015-06-17 00:26:30 -07:00
|
|
|
}
|
2016-01-04 04:46:56 -08:00
|
|
|
else
|
|
|
|
{
|
2017-04-05 03:19:36 -07:00
|
|
|
output = evas_filter_buffer_backing_get(ctx, EVAS_FILTER_BUFFER_OUTPUT_ID, EINA_FALSE);
|
|
|
|
FCOW_WRITE(pd, output, output);
|
2016-01-04 04:46:56 -08:00
|
|
|
}
|
|
|
|
|
2017-04-12 20:08:31 -07:00
|
|
|
if (previous)
|
|
|
|
ENFN->image_free(ENDT, previous);
|
2017-03-22 00:55:26 -07:00
|
|
|
|
|
|
|
if (destroy)
|
|
|
|
{
|
|
|
|
evas_filter_context_destroy(ctx);
|
|
|
|
ctx = NULL;
|
|
|
|
}
|
|
|
|
|
2017-04-05 03:19:36 -07:00
|
|
|
FCOW_WRITE(pd, context, ctx);
|
2015-06-17 00:26:30 -07:00
|
|
|
}
|
|
|
|
|
2016-06-20 07:31:31 -07:00
|
|
|
static void
|
2016-12-22 03:18:51 -08:00
|
|
|
_filter_async_post_render_cb(void *data)
|
2016-01-06 23:54:42 -08:00
|
|
|
{
|
2016-12-22 03:18:51 -08:00
|
|
|
Evas_Filter_Post_Render_Data *task = data;
|
|
|
|
Evas_Filter_Data *pd = task->pd;
|
2016-01-06 23:54:42 -08:00
|
|
|
|
2017-04-12 20:08:31 -07:00
|
|
|
#ifdef FILTERS_DEBUG
|
2016-12-22 03:18:51 -08:00
|
|
|
EINA_SAFETY_ON_FALSE_RETURN(eina_main_loop_is());
|
|
|
|
#endif
|
2016-01-06 23:54:42 -08:00
|
|
|
|
2016-12-22 03:18:51 -08:00
|
|
|
_filter_end_sync(task->ctx, pd->data->obj, pd, task->success);
|
|
|
|
free(task);
|
2016-01-06 23:54:42 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_filter_cb(Evas_Filter_Context *ctx, void *data, Eina_Bool success)
|
|
|
|
{
|
|
|
|
Evas_Filter_Post_Render_Data *post_data;
|
2016-12-22 03:18:51 -08:00
|
|
|
Evas_Object_Protected_Data *obj;
|
2016-10-05 20:09:53 -07:00
|
|
|
Evas_Filter_Data *pd = data;
|
2016-01-06 23:54:42 -08:00
|
|
|
|
2016-12-22 03:18:51 -08:00
|
|
|
obj = pd->data->obj;
|
2017-04-12 20:08:31 -07:00
|
|
|
EVAS_OBJECT_DATA_VALID_CHECK(obj);
|
2016-12-22 03:18:51 -08:00
|
|
|
|
2016-01-06 23:54:42 -08:00
|
|
|
if (!pd->data->async)
|
|
|
|
{
|
2016-12-22 03:18:51 -08:00
|
|
|
_filter_end_sync(ctx, pd->data->obj, pd, success);
|
2016-01-06 23:54:42 -08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-04-12 20:08:31 -07:00
|
|
|
#ifdef FILTERS_DEBUG
|
|
|
|
EINA_SAFETY_ON_FALSE_RETURN(!eina_main_loop_is());
|
|
|
|
#endif
|
|
|
|
|
2016-01-06 23:54:42 -08:00
|
|
|
post_data = calloc(1, sizeof(*post_data));
|
|
|
|
post_data->success = success;
|
|
|
|
post_data->ctx = ctx;
|
2016-12-22 03:18:51 -08:00
|
|
|
post_data->pd = pd;
|
|
|
|
evas_post_render_job_add(obj->layer->evas, _filter_async_post_render_cb, post_data);
|
2016-01-06 23:54:42 -08:00
|
|
|
}
|
|
|
|
|
2017-01-05 00:56:04 -08:00
|
|
|
void
|
|
|
|
_evas_filter_source_hash_free_cb(void *data)
|
2015-06-17 00:26:30 -07:00
|
|
|
{
|
|
|
|
Evas_Filter_Proxy_Binding *pb = data;
|
|
|
|
Evas_Object_Protected_Data *proxy, *source;
|
|
|
|
Evas_Filter_Data *pd;
|
|
|
|
|
2016-08-15 06:44:41 -07:00
|
|
|
proxy = efl_data_scope_get(pb->eo_proxy, EFL_CANVAS_OBJECT_CLASS);
|
|
|
|
source = efl_data_scope_get(pb->eo_source, EFL_CANVAS_OBJECT_CLASS);
|
2015-06-17 00:26:30 -07:00
|
|
|
|
|
|
|
if (source)
|
|
|
|
{
|
|
|
|
EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, source->proxy,
|
|
|
|
Evas_Object_Proxy_Data, source_write)
|
|
|
|
source_write->proxies = eina_list_remove(source_write->proxies, pb->eo_proxy);
|
|
|
|
EINA_COW_WRITE_END(evas_object_proxy_cow, source->proxy, source_write)
|
|
|
|
}
|
|
|
|
|
2016-08-15 06:44:41 -07:00
|
|
|
pd = efl_data_scope_get(pb->eo_proxy, MY_CLASS);
|
2015-06-17 00:26:30 -07:00
|
|
|
|
|
|
|
if (pd && proxy)
|
|
|
|
{
|
|
|
|
if (!eina_hash_population(pd->data->sources))
|
|
|
|
{
|
|
|
|
EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, proxy->proxy,
|
|
|
|
Evas_Object_Proxy_Data, proxy_write)
|
|
|
|
proxy_write->is_proxy = EINA_FALSE;
|
|
|
|
EINA_COW_WRITE_END(evas_object_proxy_cow, source->proxy, proxy_write)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
eina_stringshare_del(pb->name);
|
|
|
|
free(pb);
|
|
|
|
}
|
|
|
|
|
2016-12-22 02:41:04 -08:00
|
|
|
static inline Eina_Bool
|
|
|
|
_evas_filter_state_set_internal(Evas_Filter_Program *pgm, Evas_Filter_Data *pd)
|
|
|
|
{
|
|
|
|
Efl_Canvas_Filter_State state = EFL_CANVAS_FILTER_STATE_DEFAULT;
|
|
|
|
|
2016-12-22 03:18:51 -08:00
|
|
|
evas_filter_state_prepare(pd->data->obj->object, &state, NULL);
|
2016-12-22 02:41:04 -08:00
|
|
|
state.cur.name = pd->data->state.cur.name;
|
|
|
|
state.cur.value = pd->data->state.cur.value;
|
|
|
|
state.next.name = pd->data->state.next.name;
|
|
|
|
state.next.value = pd->data->state.next.value;
|
|
|
|
state.pos = pd->data->state.pos;
|
|
|
|
|
|
|
|
return evas_filter_program_state_set(pgm, &state);
|
|
|
|
}
|
|
|
|
|
2017-03-14 22:49:50 -07:00
|
|
|
static inline Eina_Bool
|
|
|
|
_evas_filter_obscured_region_changed(Evas_Filter_Data *pd)
|
|
|
|
{
|
|
|
|
Eina_Rectangle inter;
|
|
|
|
|
|
|
|
inter = pd->data->prev_obscured;
|
|
|
|
if (eina_rectangle_is_empty(&pd->data->obscured) &&
|
|
|
|
eina_rectangle_is_empty(&inter))
|
|
|
|
return EINA_FALSE;
|
|
|
|
if (!eina_rectangle_intersection(&inter, &pd->data->obscured))
|
|
|
|
return EINA_TRUE;
|
|
|
|
if ((inter.w != pd->data->prev_obscured.w) ||
|
|
|
|
(inter.h != pd->data->prev_obscured.h))
|
|
|
|
return EINA_TRUE;
|
|
|
|
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
2015-06-17 00:26:30 -07:00
|
|
|
Eina_Bool
|
|
|
|
evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
|
|
|
|
void *output, void *context, void *surface,
|
|
|
|
int x, int y, Eina_Bool do_async, Eina_Bool alpha)
|
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Evas_Filter_Data *pd = efl_data_scope_get(eo_obj, MY_CLASS);
|
2017-04-12 20:08:31 -07:00
|
|
|
int X, Y, W, H;
|
|
|
|
Evas_Filter_Context *filter;
|
|
|
|
void *drawctx;
|
|
|
|
Eina_Bool ok;
|
|
|
|
void *previous = pd->data->output;
|
|
|
|
Evas_Object_Filter_Data *fcow;
|
|
|
|
Eina_Bool use_map = EINA_FALSE;
|
|
|
|
Evas_Filter_Padding pad;
|
2015-06-17 00:26:30 -07:00
|
|
|
|
2017-04-12 20:08:31 -07:00
|
|
|
if (pd->data->invalid || (!pd->data->chain && !pd->data->code))
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
W = obj->cur->geometry.w;
|
|
|
|
H = obj->cur->geometry.h;
|
|
|
|
X = obj->cur->geometry.x;
|
|
|
|
Y = obj->cur->geometry.y;
|
|
|
|
|
|
|
|
// Prepare color multiplier
|
|
|
|
ENFN->context_color_set(output, context,
|
|
|
|
obj->cur->cache.clip.r,
|
|
|
|
obj->cur->cache.clip.g,
|
|
|
|
obj->cur->cache.clip.b,
|
|
|
|
obj->cur->cache.clip.a);
|
|
|
|
if (obj->cur->clipper)
|
|
|
|
ENFN->context_multiplier_set(output, context,
|
|
|
|
obj->cur->clipper->cur->cache.clip.r,
|
|
|
|
obj->cur->clipper->cur->cache.clip.g,
|
|
|
|
obj->cur->clipper->cur->cache.clip.b,
|
|
|
|
obj->cur->clipper->cur->cache.clip.a);
|
|
|
|
else
|
|
|
|
ENFN->context_multiplier_unset(output, context);
|
|
|
|
|
|
|
|
if (obj->map->cur.usemap && obj->map->cur.map && (obj->map->cur.map->count >= 4))
|
2015-06-17 00:26:30 -07:00
|
|
|
{
|
2017-04-12 20:08:31 -07:00
|
|
|
int iw, ih;
|
2017-04-03 22:28:29 -07:00
|
|
|
|
2017-04-12 20:08:31 -07:00
|
|
|
use_map = EINA_TRUE;
|
|
|
|
ENFN->image_size_get(ENDT, previous, &iw, &ih);
|
|
|
|
evas_object_map_update(eo_obj, x, y, iw, ih, iw, ih);
|
|
|
|
}
|
2017-04-03 22:28:29 -07:00
|
|
|
|
2017-04-12 20:08:31 -07:00
|
|
|
if (!pd->data->chain)
|
|
|
|
{
|
|
|
|
Evas_Filter_Program *pgm;
|
|
|
|
Eina_Bool invalid;
|
|
|
|
|
|
|
|
pgm = evas_filter_program_new(pd->data->name, alpha);
|
|
|
|
evas_filter_program_source_set_all(pgm, pd->data->sources);
|
|
|
|
evas_filter_program_data_set_all(pgm, pd->data->data);
|
|
|
|
_evas_filter_state_set_internal(pgm, pd);
|
|
|
|
invalid = !evas_filter_program_parse(pgm, pd->data->code);
|
|
|
|
if (invalid)
|
2015-06-17 00:26:30 -07:00
|
|
|
{
|
2017-04-12 20:08:31 -07:00
|
|
|
ERR("Filter program parsing failed");
|
|
|
|
evas_filter_program_del(pgm);
|
|
|
|
pgm = NULL;
|
2015-06-17 00:26:30 -07:00
|
|
|
}
|
2017-04-12 20:08:31 -07:00
|
|
|
fcow = FCOW_BEGIN(pd);
|
|
|
|
if (!invalid) evas_filter_program_padding_get(pgm, NULL, &fcow->padding);
|
|
|
|
fcow->chain = pgm;
|
|
|
|
fcow->invalid = invalid;
|
|
|
|
FCOW_END(fcow, pd);
|
|
|
|
if (invalid) return EINA_FALSE;
|
|
|
|
}
|
|
|
|
else if (previous && !pd->data->changed)
|
|
|
|
{
|
|
|
|
Eina_Bool redraw = EINA_TRUE;
|
|
|
|
|
|
|
|
if (_evas_filter_state_set_internal(pd->data->chain, pd))
|
|
|
|
DBG("Filter redraw by state change!");
|
|
|
|
else if (obj->changed)
|
|
|
|
DBG("Filter redraw by object content change!");
|
|
|
|
else if (obj->snapshot_needs_redraw)
|
|
|
|
DBG("Filter redraw by snapshot change!");
|
|
|
|
else if (_evas_filter_obscured_region_changed(pd))
|
|
|
|
DBG("Filter redraw by obscure regions change!");
|
|
|
|
else redraw = EINA_FALSE;
|
|
|
|
|
|
|
|
// Scan proxies to find if any changed
|
|
|
|
if (!redraw && pd->data->sources)
|
2015-06-17 00:26:30 -07:00
|
|
|
{
|
2017-04-12 20:08:31 -07:00
|
|
|
Evas_Filter_Proxy_Binding *pb;
|
|
|
|
Evas_Object_Protected_Data *source;
|
|
|
|
Eina_Iterator *iter;
|
2015-06-17 00:26:30 -07:00
|
|
|
|
2017-04-12 20:08:31 -07:00
|
|
|
iter = eina_hash_iterator_data_new(pd->data->sources);
|
|
|
|
EINA_ITERATOR_FOREACH(iter, pb)
|
2015-06-17 00:26:30 -07:00
|
|
|
{
|
2017-04-12 20:08:31 -07:00
|
|
|
source = efl_data_scope_get(pb->eo_source, EFL_CANVAS_OBJECT_CLASS);
|
|
|
|
if (source->changed)
|
2017-04-03 22:28:29 -07:00
|
|
|
{
|
2017-04-12 20:08:31 -07:00
|
|
|
redraw = EINA_TRUE;
|
|
|
|
break;
|
2017-04-03 22:28:29 -07:00
|
|
|
}
|
2015-06-17 00:26:30 -07:00
|
|
|
}
|
2017-04-12 20:08:31 -07:00
|
|
|
eina_iterator_free(iter);
|
2016-12-22 02:41:04 -08:00
|
|
|
}
|
2015-06-17 00:26:30 -07:00
|
|
|
|
2017-04-12 20:08:31 -07:00
|
|
|
if (!redraw)
|
2015-06-17 00:26:30 -07:00
|
|
|
{
|
2017-04-12 20:08:31 -07:00
|
|
|
// Render this image only
|
|
|
|
if (use_map)
|
2015-07-27 22:17:53 -07:00
|
|
|
{
|
2017-04-12 20:08:31 -07:00
|
|
|
ENFN->image_map_draw(ENDT, context, surface, previous,
|
|
|
|
obj->map->spans, EINA_TRUE, 0, do_async);
|
2017-03-22 00:55:26 -07:00
|
|
|
}
|
2017-04-12 20:08:31 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
ENFN->image_draw(ENDT, context,
|
|
|
|
surface, previous,
|
|
|
|
0, 0, W, H, // src
|
|
|
|
X + x, Y + y, W, H, // dst
|
|
|
|
EINA_FALSE, // smooth
|
|
|
|
do_async);
|
|
|
|
}
|
|
|
|
return EINA_TRUE;
|
2017-03-22 00:55:26 -07:00
|
|
|
}
|
2017-04-12 20:08:31 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_evas_filter_state_set_internal(pd->data->chain, pd);
|
|
|
|
}
|
|
|
|
|
|
|
|
filter = pd->data->context;
|
|
|
|
if (filter)
|
|
|
|
{
|
|
|
|
int prev_w, prev_h;
|
|
|
|
Eina_Bool was_async;
|
2017-03-22 00:55:26 -07:00
|
|
|
|
2017-04-12 20:08:31 -07:00
|
|
|
was_async = evas_filter_context_async_get(filter);
|
|
|
|
evas_filter_context_size_get(filter, &prev_w, &prev_h);
|
|
|
|
if ((!pd->data->reuse) || (was_async != do_async) ||
|
|
|
|
(prev_w != W) || (prev_h != H))
|
2017-03-22 00:55:26 -07:00
|
|
|
{
|
2017-04-12 20:08:31 -07:00
|
|
|
evas_filter_context_destroy(filter);
|
|
|
|
FCOW_WRITE(pd, context, NULL);
|
|
|
|
filter = NULL;
|
2017-03-22 00:55:26 -07:00
|
|
|
}
|
2017-04-12 20:08:31 -07:00
|
|
|
}
|
2017-03-22 00:55:26 -07:00
|
|
|
|
2017-04-12 20:08:31 -07:00
|
|
|
if (filter)
|
|
|
|
{
|
|
|
|
ok = evas_filter_context_program_use(filter, pd->data->chain, EINA_TRUE, X, Y);
|
|
|
|
if (!ok)
|
2017-03-22 00:55:26 -07:00
|
|
|
{
|
2017-04-12 20:08:31 -07:00
|
|
|
evas_filter_context_destroy(filter);
|
|
|
|
FCOW_WRITE(pd, context, NULL);
|
|
|
|
filter = NULL;
|
|
|
|
}
|
|
|
|
}
|
2017-03-22 00:55:26 -07:00
|
|
|
|
2017-04-12 20:08:31 -07:00
|
|
|
if (!filter)
|
|
|
|
{
|
|
|
|
filter = evas_filter_context_new(obj->layer->evas, do_async, 0);
|
2017-03-22 00:55:26 -07:00
|
|
|
|
2017-04-12 20:08:31 -07:00
|
|
|
// Run script
|
|
|
|
ok = evas_filter_context_program_use(filter, pd->data->chain, EINA_FALSE, X, Y);
|
|
|
|
if (!filter || !ok)
|
|
|
|
{
|
|
|
|
ERR("Parsing failed?");
|
|
|
|
evas_filter_context_destroy(filter);
|
|
|
|
FCOW_WRITE(pd, invalid, EINA_TRUE);
|
|
|
|
return EINA_FALSE;
|
2015-06-17 00:26:30 -07:00
|
|
|
}
|
2017-04-12 20:08:31 -07:00
|
|
|
}
|
2015-06-17 00:26:30 -07:00
|
|
|
|
2017-04-12 20:08:31 -07:00
|
|
|
// Proxies
|
|
|
|
evas_filter_context_proxy_render_all(filter, eo_obj, EINA_FALSE);
|
2015-06-17 00:26:30 -07:00
|
|
|
|
2017-04-12 20:08:31 -07:00
|
|
|
// Draw Context
|
|
|
|
drawctx = ENFN->context_new(ENDT);
|
|
|
|
ENFN->context_color_set(ENDT, drawctx, 255, 255, 255, 255);
|
2015-06-17 00:26:30 -07:00
|
|
|
|
2017-04-12 20:08:31 -07:00
|
|
|
// Set obscured region
|
|
|
|
evas_filter_context_obscured_region_set(filter, pd->data->obscured);
|
2017-03-14 22:49:50 -07:00
|
|
|
|
2017-04-12 20:08:31 -07:00
|
|
|
// Allocate all buffers now
|
|
|
|
evas_filter_context_buffers_allocate_all(filter);
|
|
|
|
evas_filter_target_set(filter, context, surface, X + x, Y + y,
|
|
|
|
use_map ? obj->map->spans : NULL);
|
2015-06-17 00:26:30 -07:00
|
|
|
|
2017-04-12 20:08:31 -07:00
|
|
|
// Request rendering from the object itself (child class)
|
|
|
|
evas_filter_program_padding_get(pd->data->chain, &pad, NULL);
|
|
|
|
ok = evas_filter_input_render(eo_obj, filter, drawctx, NULL, pad.l, pad.r, pad.t, pad.b, 0, 0, do_async);
|
|
|
|
if (!ok) ERR("Filter input render failed.");
|
2015-06-17 00:26:30 -07:00
|
|
|
|
2017-04-12 20:08:31 -07:00
|
|
|
ENFN->context_free(ENDT, drawctx);
|
2015-06-17 00:26:30 -07:00
|
|
|
|
2017-04-12 20:08:31 -07:00
|
|
|
// Add post-run callback and run filter
|
|
|
|
evas_filter_context_post_run_callback_set(filter, _filter_cb, pd);
|
2015-07-27 22:17:53 -07:00
|
|
|
|
2017-04-12 20:08:31 -07:00
|
|
|
fcow = FCOW_BEGIN(pd);
|
|
|
|
fcow->context = filter;
|
|
|
|
fcow->changed = EINA_FALSE;
|
|
|
|
fcow->async = do_async;
|
|
|
|
fcow->prev_obscured = fcow->obscured;
|
|
|
|
fcow->prev_padding = fcow->padding;
|
|
|
|
fcow->padding = pad;
|
|
|
|
fcow->invalid = EINA_FALSE;
|
|
|
|
FCOW_END(fcow, pd);
|
|
|
|
|
|
|
|
// Run the filter now (maybe async)
|
|
|
|
ok = evas_filter_context_run(filter);
|
|
|
|
if (!ok)
|
|
|
|
{
|
|
|
|
ERR("Filter program failed to run!");
|
|
|
|
evas_filter_context_destroy(filter);
|
2015-07-27 22:17:53 -07:00
|
|
|
fcow = FCOW_BEGIN(pd);
|
2017-04-12 20:08:31 -07:00
|
|
|
fcow->context = NULL;
|
|
|
|
fcow->invalid = EINA_TRUE;
|
2015-07-27 22:17:53 -07:00
|
|
|
FCOW_END(fcow, pd);
|
2015-06-17 00:26:30 -07:00
|
|
|
}
|
2017-04-12 20:08:31 -07:00
|
|
|
|
|
|
|
return ok;
|
2015-06-17 00:26:30 -07:00
|
|
|
}
|
|
|
|
|
2016-01-12 22:19:07 -08:00
|
|
|
EOLIAN static void
|
2016-06-09 23:55:28 -07:00
|
|
|
_efl_canvas_filter_internal_efl_gfx_filter_filter_program_set(Eo *eo_obj, Evas_Filter_Data *pd,
|
|
|
|
const char *code, const char *name)
|
2015-06-17 00:26:30 -07:00
|
|
|
{
|
2016-10-13 09:47:38 -07:00
|
|
|
Evas_Object_Protected_Data *obj;
|
2015-06-17 00:26:30 -07:00
|
|
|
Evas_Filter_Program *pgm = NULL;
|
2015-07-27 22:17:53 -07:00
|
|
|
Evas_Object_Filter_Data *fcow;
|
2017-03-22 23:55:41 -07:00
|
|
|
Eina_Bool invalid = pd->data->invalid;
|
2015-06-18 05:45:21 -07:00
|
|
|
Eina_Bool alpha;
|
2015-06-17 00:26:30 -07:00
|
|
|
|
2016-12-22 03:18:51 -08:00
|
|
|
obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
|
2016-06-28 18:58:57 -07:00
|
|
|
if (eina_streq(pd->data->code, code) && eina_streq(pd->data->name, name))
|
|
|
|
return;
|
2015-06-17 00:26:30 -07:00
|
|
|
|
|
|
|
evas_object_async_block(obj);
|
2015-07-27 22:17:53 -07:00
|
|
|
fcow = FCOW_BEGIN(pd);
|
2016-06-09 23:55:28 -07:00
|
|
|
{
|
2016-12-22 03:18:51 -08:00
|
|
|
fcow->obj = obj;
|
|
|
|
|
2017-03-22 00:55:26 -07:00
|
|
|
if (fcow->context)
|
|
|
|
evas_filter_context_destroy(fcow->context);
|
|
|
|
|
2016-06-09 23:55:28 -07:00
|
|
|
// Parse filter program
|
|
|
|
evas_filter_program_del(fcow->chain);
|
|
|
|
eina_stringshare_replace(&fcow->name, name);
|
|
|
|
if (code)
|
|
|
|
{
|
|
|
|
alpha = evas_filter_input_alpha(eo_obj);
|
|
|
|
pgm = evas_filter_program_new(fcow->name, alpha);
|
|
|
|
evas_filter_program_source_set_all(pgm, fcow->sources);
|
|
|
|
evas_filter_program_data_set_all(pgm, fcow->data);
|
2016-12-22 02:41:04 -08:00
|
|
|
_evas_filter_state_set_internal(pgm, pd);
|
2017-03-22 23:55:41 -07:00
|
|
|
invalid = !evas_filter_program_parse(pgm, code);
|
|
|
|
if (invalid)
|
2016-06-09 23:55:28 -07:00
|
|
|
{
|
|
|
|
ERR("Parsing failed!");
|
|
|
|
evas_filter_program_del(pgm);
|
|
|
|
pgm = NULL;
|
|
|
|
}
|
2017-03-22 23:55:41 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
evas_filter_program_padding_get(pgm, NULL, &fcow->padding);
|
|
|
|
}
|
2016-06-09 23:55:28 -07:00
|
|
|
}
|
|
|
|
fcow->chain = pgm;
|
|
|
|
fcow->changed = EINA_TRUE;
|
2017-03-22 23:55:41 -07:00
|
|
|
fcow->invalid = invalid;
|
2016-06-09 23:55:28 -07:00
|
|
|
eina_stringshare_replace(&fcow->code, code);
|
|
|
|
}
|
2015-07-27 22:17:53 -07:00
|
|
|
FCOW_END(fcow, pd);
|
2015-06-17 00:26:30 -07:00
|
|
|
|
2016-03-01 10:06:28 -08:00
|
|
|
evas_filter_dirty(eo_obj);
|
2015-06-17 00:26:30 -07:00
|
|
|
}
|
|
|
|
|
2016-01-12 22:19:07 -08:00
|
|
|
EOLIAN static void
|
2016-06-09 23:55:28 -07:00
|
|
|
_efl_canvas_filter_internal_efl_gfx_filter_filter_program_get(Eo *eo_obj EINA_UNUSED, Evas_Filter_Data *pd, const char **code, const char **name)
|
2015-06-17 00:26:30 -07:00
|
|
|
{
|
2015-06-19 01:38:28 -07:00
|
|
|
if (code) *code = pd->data->code;
|
|
|
|
if (name) *name = pd->data->name;
|
2015-06-17 00:26:30 -07:00
|
|
|
}
|
|
|
|
|
2016-01-12 22:19:07 -08:00
|
|
|
EOLIAN static void
|
2016-06-09 23:55:28 -07:00
|
|
|
_efl_canvas_filter_internal_efl_gfx_filter_filter_source_set(Eo *eo_obj, Evas_Filter_Data *pd,
|
|
|
|
const char *name, Efl_Gfx *eo_source)
|
2015-06-17 00:26:30 -07:00
|
|
|
{
|
2016-12-22 03:18:51 -08:00
|
|
|
Evas_Object_Protected_Data *obj;
|
2015-06-17 00:26:30 -07:00
|
|
|
Evas_Filter_Proxy_Binding *pb, *pb_old = NULL;
|
|
|
|
Evas_Object_Protected_Data *source = NULL;
|
|
|
|
Evas_Object_Filter_Data *fcow = NULL;
|
2017-03-22 23:55:41 -07:00
|
|
|
Eina_Bool invalid = pd->data->invalid;
|
2015-06-17 00:26:30 -07:00
|
|
|
|
2016-12-22 03:18:51 -08:00
|
|
|
obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
|
2015-06-17 00:26:30 -07:00
|
|
|
if (eo_source)
|
2016-08-15 06:44:41 -07:00
|
|
|
source = efl_data_scope_get(eo_source, EFL_CANVAS_OBJECT_CLASS);
|
2015-06-17 00:26:30 -07:00
|
|
|
|
|
|
|
evas_object_async_block(obj);
|
|
|
|
if (!name)
|
|
|
|
{
|
|
|
|
if (!eo_source || !pd->data->sources) return;
|
|
|
|
if (eina_hash_del_by_data(pd->data->sources, eo_source))
|
|
|
|
goto update;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!source && !pd->data->sources)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (pd->data->sources)
|
|
|
|
{
|
|
|
|
pb_old = eina_hash_find(pd->data->sources, name);
|
|
|
|
if (pb_old && (pb_old->eo_source == eo_source)) return;
|
|
|
|
}
|
|
|
|
|
2015-07-27 22:17:53 -07:00
|
|
|
fcow = FCOW_BEGIN(pd);
|
2015-06-17 00:26:30 -07:00
|
|
|
if (!fcow->sources)
|
2017-01-05 00:56:04 -08:00
|
|
|
fcow->sources = eina_hash_string_small_new(_evas_filter_source_hash_free_cb);
|
2015-06-17 00:26:30 -07:00
|
|
|
else if (pb_old)
|
|
|
|
eina_hash_del(fcow->sources, name, pb_old);
|
|
|
|
|
|
|
|
if (!source)
|
|
|
|
{
|
|
|
|
pb_old = eina_hash_find(fcow->sources, name);
|
|
|
|
if (!pb_old)
|
|
|
|
{
|
2015-07-27 22:17:53 -07:00
|
|
|
FCOW_END(fcow, pd);
|
2015-06-17 00:26:30 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
eina_hash_del_by_key(fcow->sources, name);
|
|
|
|
goto update;
|
|
|
|
}
|
|
|
|
|
|
|
|
pb = calloc(1, sizeof(*pb));
|
|
|
|
pb->eo_proxy = eo_obj;
|
|
|
|
pb->eo_source = eo_source;
|
|
|
|
pb->name = eina_stringshare_add(name);
|
|
|
|
|
|
|
|
if (!eina_list_data_find(source->proxy->proxies, eo_obj))
|
|
|
|
{
|
|
|
|
EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, source->proxy, Evas_Object_Proxy_Data, source_write)
|
|
|
|
source_write->proxies = eina_list_append(source_write->proxies, eo_obj);
|
|
|
|
EINA_COW_WRITE_END(evas_object_proxy_cow, source->proxy, source_write)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!obj->proxy->is_proxy)
|
|
|
|
{
|
|
|
|
EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, obj->proxy, Evas_Object_Proxy_Data, proxy_write)
|
|
|
|
proxy_write->is_proxy = EINA_TRUE;
|
|
|
|
EINA_COW_WRITE_END(evas_object_proxy_cow, obj->proxy, proxy_write)
|
|
|
|
}
|
|
|
|
|
|
|
|
eina_hash_add(fcow->sources, pb->name, pb);
|
|
|
|
evas_filter_program_source_set_all(fcow->chain, fcow->sources);
|
2015-06-22 05:52:16 -07:00
|
|
|
evas_filter_program_data_set_all(fcow->chain, fcow->data);
|
2017-03-22 23:55:41 -07:00
|
|
|
invalid = !evas_filter_program_parse(fcow->chain, fcow->code);
|
|
|
|
if (!invalid) evas_filter_program_padding_get(fcow->chain, NULL, &fcow->padding);
|
2015-06-17 00:26:30 -07:00
|
|
|
|
|
|
|
// Update object
|
|
|
|
update:
|
|
|
|
if (fcow)
|
|
|
|
{
|
|
|
|
fcow->changed = EINA_TRUE;
|
2017-03-22 23:55:41 -07:00
|
|
|
fcow->invalid = invalid;
|
2015-07-27 22:17:53 -07:00
|
|
|
FCOW_END(fcow, pd);
|
2015-06-17 00:26:30 -07:00
|
|
|
}
|
|
|
|
|
2016-03-01 10:06:28 -08:00
|
|
|
evas_filter_dirty(eo_obj);
|
2015-06-17 00:26:30 -07:00
|
|
|
}
|
|
|
|
|
2016-05-10 04:25:44 -07:00
|
|
|
EOLIAN static Efl_Gfx *
|
2016-06-09 23:55:28 -07:00
|
|
|
_efl_canvas_filter_internal_efl_gfx_filter_filter_source_get(Eo *obj EINA_UNUSED, Evas_Filter_Data *pd,
|
|
|
|
const char * name)
|
2015-06-17 00:26:30 -07:00
|
|
|
{
|
2016-02-28 22:23:18 -08:00
|
|
|
Evas_Filter_Proxy_Binding *pb = eina_hash_find(pd->data->sources, name);
|
|
|
|
if (!pb) return NULL;
|
|
|
|
return pb->eo_source;
|
2015-06-17 00:26:30 -07:00
|
|
|
}
|
|
|
|
|
2016-01-12 22:19:07 -08:00
|
|
|
EOLIAN static void
|
2016-06-09 23:55:28 -07:00
|
|
|
_efl_canvas_filter_internal_efl_gfx_filter_filter_state_set(Eo *eo_obj, Evas_Filter_Data *pd,
|
|
|
|
const char *cur_state, double cur_val,
|
|
|
|
const char *next_state, double next_val,
|
|
|
|
double pos)
|
2015-06-17 00:26:30 -07:00
|
|
|
{
|
2016-12-22 03:18:51 -08:00
|
|
|
Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
|
2015-06-17 00:26:30 -07:00
|
|
|
|
|
|
|
evas_object_async_block(obj);
|
2016-12-20 07:25:01 -08:00
|
|
|
if ((cur_state != pd->data->state.cur.name) ||
|
2017-01-06 09:57:46 -08:00
|
|
|
(!EINA_DBL_EQ(cur_val, pd->data->state.cur.value)) ||
|
2016-12-20 07:25:01 -08:00
|
|
|
(next_state != pd->data->state.next.name) ||
|
2017-01-06 09:57:46 -08:00
|
|
|
(!EINA_DBL_EQ(next_val, pd->data->state.next.value)) ||
|
|
|
|
(!EINA_DBL_EQ(pos, pd->data->state.pos)))
|
2015-06-17 00:26:30 -07:00
|
|
|
{
|
2015-07-27 22:17:53 -07:00
|
|
|
Evas_Object_Filter_Data *fcow = FCOW_BEGIN(pd);
|
|
|
|
fcow->changed = 1;
|
2016-02-28 22:23:18 -08:00
|
|
|
eina_stringshare_replace(&fcow->state.cur.name, cur_state);
|
2015-07-27 22:17:53 -07:00
|
|
|
fcow->state.cur.value = cur_val;
|
2016-02-28 22:23:18 -08:00
|
|
|
eina_stringshare_replace(&fcow->state.next.name, next_state);
|
2015-07-27 22:17:53 -07:00
|
|
|
fcow->state.next.value = next_val;
|
|
|
|
fcow->state.pos = pos;
|
|
|
|
FCOW_END(fcow, pd);
|
|
|
|
|
|
|
|
if (pd->data->chain)
|
2015-06-17 00:26:30 -07:00
|
|
|
{
|
2016-12-22 02:41:04 -08:00
|
|
|
_evas_filter_state_set_internal(pd->data->chain, pd);
|
2015-06-17 00:26:30 -07:00
|
|
|
}
|
|
|
|
|
2016-03-01 10:06:28 -08:00
|
|
|
evas_filter_dirty(eo_obj);
|
2015-06-17 00:26:30 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-12 22:19:07 -08:00
|
|
|
EOLIAN static void
|
2016-06-09 23:55:28 -07:00
|
|
|
_efl_canvas_filter_internal_efl_gfx_filter_filter_state_get(Eo *obj EINA_UNUSED, Evas_Filter_Data *pd,
|
|
|
|
const char **cur_state, double *cur_val,
|
|
|
|
const char **next_state, double *next_val,
|
|
|
|
double *pos)
|
2016-02-28 22:23:18 -08:00
|
|
|
{
|
|
|
|
if (cur_state) *cur_state = pd->data->state.cur.name;
|
|
|
|
if (cur_val) *cur_val = pd->data->state.cur.value;
|
|
|
|
if (next_state) *next_state = pd->data->state.next.name;
|
|
|
|
if (next_val) *next_val = pd->data->state.next.value;
|
|
|
|
if (pos) *pos = pd->data->state.pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
2016-06-09 23:55:28 -07:00
|
|
|
_efl_canvas_filter_internal_efl_gfx_filter_filter_padding_get(Eo *eo_obj EINA_UNUSED, Evas_Filter_Data *pd,
|
|
|
|
int *l, int *r, int *t, int *b)
|
2015-06-17 00:26:30 -07:00
|
|
|
{
|
2017-03-14 22:49:50 -07:00
|
|
|
Evas_Filter_Padding pad = { 0, 0, 0, 0 };
|
|
|
|
|
|
|
|
if (pd->data->chain)
|
|
|
|
evas_filter_program_padding_get(pd->data->chain, &pad, NULL);
|
|
|
|
|
|
|
|
if (l) *l = pad.l;
|
|
|
|
if (r) *r = pad.r;
|
|
|
|
if (t) *t = pad.t;
|
|
|
|
if (b) *b = pad.b;
|
2015-06-17 00:26:30 -07:00
|
|
|
}
|
|
|
|
|
2016-01-12 22:19:07 -08:00
|
|
|
EOLIAN static void
|
2016-06-09 23:55:28 -07:00
|
|
|
_efl_canvas_filter_internal_filter_changed_set(Eo *eo_obj EINA_UNUSED, Evas_Filter_Data *pd, Eina_Bool val)
|
2015-06-17 00:26:30 -07:00
|
|
|
{
|
2017-03-23 00:22:43 -07:00
|
|
|
if ((&evas_filter_data_cow_default != pd->data) && (pd->data->changed != val))
|
2015-06-17 00:26:30 -07:00
|
|
|
{
|
2015-07-27 22:17:53 -07:00
|
|
|
Evas_Object_Filter_Data *fcow = FCOW_BEGIN(pd);
|
|
|
|
fcow->changed = val;
|
|
|
|
FCOW_END(fcow, pd);
|
2015-06-17 00:26:30 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-12 22:19:07 -08:00
|
|
|
EOLIAN static void
|
2016-06-09 23:55:28 -07:00
|
|
|
_efl_canvas_filter_internal_filter_invalid_set(Eo *eo_obj EINA_UNUSED, Evas_Filter_Data *pd, Eina_Bool val)
|
2015-06-17 00:26:30 -07:00
|
|
|
{
|
|
|
|
if (pd->data->invalid != val)
|
|
|
|
{
|
2015-07-27 22:17:53 -07:00
|
|
|
Evas_Object_Filter_Data *fcow = FCOW_BEGIN(pd);
|
|
|
|
fcow->invalid = val;
|
|
|
|
FCOW_END(fcow, pd);
|
2015-06-17 00:26:30 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-10 07:23:04 -07:00
|
|
|
EOLIAN static Efl_Object *
|
|
|
|
_efl_canvas_filter_internal_efl_object_constructor(Eo *eo_obj, Evas_Filter_Data *pd)
|
2015-06-17 00:26:30 -07:00
|
|
|
{
|
2016-02-26 01:24:47 -08:00
|
|
|
Eo *obj = NULL;
|
|
|
|
|
2016-08-15 06:44:41 -07:00
|
|
|
obj = efl_constructor(efl_super(eo_obj, MY_CLASS));
|
2015-06-17 00:26:30 -07:00
|
|
|
pd->data = eina_cow_alloc(evas_object_filter_cow);
|
2016-02-26 01:24:47 -08:00
|
|
|
|
|
|
|
return obj;
|
2015-06-17 00:26:30 -07:00
|
|
|
}
|
|
|
|
|
2016-01-12 22:19:07 -08:00
|
|
|
EOLIAN static void
|
2016-08-10 07:23:04 -07:00
|
|
|
_efl_canvas_filter_internal_efl_object_destructor(Eo *eo_obj, Evas_Filter_Data *pd)
|
2015-06-17 00:26:30 -07:00
|
|
|
{
|
2016-12-22 03:18:51 -08:00
|
|
|
Evas_Object_Protected_Data *obj;
|
2015-06-23 00:40:51 -07:00
|
|
|
Evas_Filter_Data_Binding *db;
|
2016-12-22 03:18:51 -08:00
|
|
|
Evas_Public_Data *e;
|
2015-06-23 00:40:51 -07:00
|
|
|
Eina_Inlist *il;
|
2015-06-17 00:26:30 -07:00
|
|
|
|
2017-03-23 00:22:43 -07:00
|
|
|
if (!pd->data || (&evas_filter_data_cow_default == pd->data))
|
2016-02-26 01:24:47 -08:00
|
|
|
goto finish;
|
2015-06-17 00:26:30 -07:00
|
|
|
|
2016-12-22 03:18:51 -08:00
|
|
|
obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
|
|
|
|
e = obj->layer->evas;
|
|
|
|
|
2017-03-22 00:55:26 -07:00
|
|
|
if (pd->data->context)
|
|
|
|
evas_filter_context_destroy(pd->data->context);
|
|
|
|
|
2015-06-17 00:26:30 -07:00
|
|
|
if (pd->data->output)
|
2015-10-07 02:08:56 -07:00
|
|
|
{
|
|
|
|
if (!pd->data->async)
|
|
|
|
ENFN->image_free(ENDT, pd->data->output);
|
|
|
|
else
|
2016-12-22 03:18:51 -08:00
|
|
|
evas_unref_queue_image_put(e, pd->data->output);
|
2015-10-07 02:08:56 -07:00
|
|
|
}
|
2015-06-17 00:26:30 -07:00
|
|
|
eina_hash_free(pd->data->sources);
|
2015-06-23 00:40:51 -07:00
|
|
|
EINA_INLIST_FOREACH_SAFE(pd->data->data, il, db)
|
|
|
|
{
|
|
|
|
eina_stringshare_del(db->name);
|
|
|
|
eina_stringshare_del(db->value);
|
|
|
|
free(db);
|
|
|
|
}
|
2015-06-17 00:26:30 -07:00
|
|
|
evas_filter_program_del(pd->data->chain);
|
|
|
|
eina_stringshare_del(pd->data->code);
|
2016-02-28 22:23:18 -08:00
|
|
|
eina_stringshare_del(pd->data->state.cur.name);
|
|
|
|
eina_stringshare_del(pd->data->state.next.name);
|
2016-02-26 01:24:47 -08:00
|
|
|
|
|
|
|
finish:
|
2015-06-17 00:26:30 -07:00
|
|
|
eina_cow_free(evas_object_filter_cow, (const Eina_Cow_Data **) &pd->data);
|
2016-02-26 01:24:47 -08:00
|
|
|
|
2016-08-15 06:44:41 -07:00
|
|
|
efl_destructor(efl_super(eo_obj, MY_CLASS));
|
2015-06-17 00:26:30 -07:00
|
|
|
}
|
|
|
|
|
2016-01-12 22:19:07 -08:00
|
|
|
EOLIAN static void
|
2016-06-09 23:55:28 -07:00
|
|
|
_efl_canvas_filter_internal_efl_gfx_filter_filter_data_set(Eo *eo_obj, Evas_Filter_Data *pd,
|
|
|
|
const char *name, const char *value,
|
|
|
|
Eina_Bool execute)
|
2015-06-22 05:52:16 -07:00
|
|
|
{
|
2015-06-23 00:40:51 -07:00
|
|
|
Evas_Filter_Data_Binding *db, *found = NULL;
|
2015-07-27 22:17:53 -07:00
|
|
|
Evas_Object_Filter_Data *fcow;
|
2017-03-22 23:55:41 -07:00
|
|
|
Eina_Bool invalid = pd->data->invalid;
|
2015-06-22 05:52:16 -07:00
|
|
|
|
2015-06-23 00:40:51 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN(pd->data);
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(name);
|
2015-06-22 05:52:16 -07:00
|
|
|
|
2015-06-23 00:40:51 -07:00
|
|
|
EINA_INLIST_FOREACH(pd->data->data, db)
|
2015-06-22 05:52:16 -07:00
|
|
|
{
|
2015-06-23 00:40:51 -07:00
|
|
|
if (!strcmp(name, db->name))
|
|
|
|
{
|
|
|
|
if (db->execute == execute)
|
|
|
|
{
|
|
|
|
if ((value == db->value) || (value && db->value && !strcmp(value, db->value)))
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
found = db;
|
|
|
|
break;
|
|
|
|
}
|
2015-06-22 05:52:16 -07:00
|
|
|
}
|
|
|
|
|
2015-07-27 22:17:53 -07:00
|
|
|
fcow = FCOW_BEGIN(pd);
|
2016-06-09 23:55:28 -07:00
|
|
|
{
|
|
|
|
if (found)
|
|
|
|
{
|
|
|
|
// Note: we are keeping references to NULL values here.
|
|
|
|
eina_stringshare_replace(&found->value, value);
|
|
|
|
found->execute = execute;
|
|
|
|
}
|
|
|
|
else if (value)
|
|
|
|
{
|
|
|
|
db = calloc(1, sizeof(Evas_Filter_Data_Binding));
|
|
|
|
db->name = eina_stringshare_add(name);
|
|
|
|
db->value = eina_stringshare_add(value);
|
|
|
|
db->execute = execute;
|
|
|
|
fcow->data = eina_inlist_append(fcow->data, EINA_INLIST_GET(db));
|
|
|
|
}
|
2017-03-20 04:16:19 -07:00
|
|
|
if (fcow->chain)
|
|
|
|
{
|
|
|
|
evas_filter_program_data_set_all(fcow->chain, fcow->data);
|
2017-03-22 23:55:41 -07:00
|
|
|
invalid = !evas_filter_program_parse(fcow->chain, fcow->code);
|
|
|
|
if (!invalid) evas_filter_program_padding_get(fcow->chain, NULL, &fcow->padding);
|
2017-03-20 04:16:19 -07:00
|
|
|
}
|
2017-03-22 23:55:41 -07:00
|
|
|
fcow->invalid = invalid;
|
2016-06-09 23:55:28 -07:00
|
|
|
fcow->changed = 1;
|
|
|
|
}
|
2015-07-27 22:17:53 -07:00
|
|
|
FCOW_END(fcow, pd);
|
2016-03-01 18:37:36 -08:00
|
|
|
|
2016-03-03 02:00:26 -08:00
|
|
|
evas_filter_dirty(eo_obj);
|
2015-06-22 05:52:16 -07:00
|
|
|
}
|
|
|
|
|
2016-02-28 22:23:18 -08:00
|
|
|
EOLIAN static void
|
2016-06-09 23:55:28 -07:00
|
|
|
_efl_canvas_filter_internal_efl_gfx_filter_filter_data_get(Eo *obj EINA_UNUSED, Evas_Filter_Data *pd,
|
|
|
|
const char *name, const char **value,
|
|
|
|
Eina_Bool *execute)
|
2016-02-28 22:23:18 -08:00
|
|
|
{
|
|
|
|
Evas_Filter_Data_Binding *db;
|
|
|
|
|
|
|
|
if (!value && !execute) return;
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(pd->data);
|
|
|
|
|
|
|
|
EINA_INLIST_FOREACH(pd->data->data, db)
|
|
|
|
{
|
|
|
|
if (!strcmp(name, db->name))
|
|
|
|
{
|
|
|
|
if (value) *value = db->value;
|
|
|
|
if (execute) *execute = db->execute;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (value) *value = NULL;
|
|
|
|
if (execute) *execute = EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
2016-01-12 22:19:07 -08:00
|
|
|
EOLIAN static void *
|
2016-06-09 23:55:28 -07:00
|
|
|
_efl_canvas_filter_internal_filter_output_buffer_get(Eo *obj EINA_UNUSED, Evas_Filter_Data *pd)
|
2015-10-07 19:19:50 -07:00
|
|
|
{
|
|
|
|
return pd->data->output;
|
|
|
|
}
|
|
|
|
|
2017-03-22 23:55:41 -07:00
|
|
|
Eina_Bool
|
2017-03-29 21:52:48 -07:00
|
|
|
_evas_filter_obscured_regions_set(Evas_Object_Protected_Data *obj, const Eina_Tiler *tiler)
|
2017-03-14 22:49:50 -07:00
|
|
|
{
|
|
|
|
Evas_Object_Filter_Data *fcow;
|
2017-04-03 18:25:05 -07:00
|
|
|
Eina_Rectangle prev, rect = {};
|
2017-03-29 21:52:48 -07:00
|
|
|
Eina_Rectangle *r;
|
2017-03-22 23:55:41 -07:00
|
|
|
Evas_Filter_Data *pd;
|
2017-03-29 21:52:48 -07:00
|
|
|
Eina_Iterator *it;
|
2017-04-03 18:25:05 -07:00
|
|
|
Eina_Bool was_empty, redraw = EINA_FALSE;
|
|
|
|
int obscured_changes = 0;
|
2017-03-29 21:52:48 -07:00
|
|
|
int area = 0;
|
|
|
|
|
|
|
|
// TODO: Can we handle more than one opaque region?
|
2017-03-14 22:49:50 -07:00
|
|
|
|
|
|
|
pd = efl_data_scope_get(obj->object, MY_CLASS);
|
2017-03-22 23:55:41 -07:00
|
|
|
if (!pd->data) return EINA_FALSE;
|
|
|
|
|
2017-03-29 21:52:48 -07:00
|
|
|
// Find largest opaque rect
|
|
|
|
it = eina_tiler_iterator_new(tiler);
|
|
|
|
EINA_ITERATOR_FOREACH(it, r)
|
|
|
|
{
|
|
|
|
int wh = r->w * r->h;
|
|
|
|
if (wh > area)
|
|
|
|
{
|
|
|
|
area = wh;
|
|
|
|
rect = *r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
eina_iterator_free(it);
|
2017-03-14 22:49:50 -07:00
|
|
|
|
2017-03-29 21:52:48 -07:00
|
|
|
prev = pd->data->prev_obscured;
|
2017-04-03 18:25:05 -07:00
|
|
|
if (!pd->data->changed && (!prev.w || !prev.h))
|
|
|
|
{
|
|
|
|
was_empty = EINA_TRUE;
|
|
|
|
obscured_changes = 0;
|
|
|
|
}
|
2017-03-29 21:52:48 -07:00
|
|
|
else if (memcmp(&rect, &prev, sizeof(rect)))
|
2017-03-14 22:49:50 -07:00
|
|
|
{
|
2017-03-29 21:52:48 -07:00
|
|
|
fcow = FCOW_BEGIN(pd);
|
|
|
|
fcow->obscured = rect;
|
2017-04-03 18:25:05 -07:00
|
|
|
obscured_changes = fcow->obscured_changes + 1;
|
|
|
|
if (obscured_changes > 2)
|
|
|
|
{
|
|
|
|
// Reset obscure as it changes too much
|
|
|
|
memset(&fcow->obscured, 0, sizeof(fcow->obscured));
|
|
|
|
obscured_changes = 0;
|
|
|
|
redraw = EINA_TRUE;
|
|
|
|
}
|
2017-03-29 21:52:48 -07:00
|
|
|
FCOW_END(fcow, pd);
|
2017-03-14 22:49:50 -07:00
|
|
|
}
|
2017-03-22 23:55:41 -07:00
|
|
|
|
2017-04-03 18:25:05 -07:00
|
|
|
FCOW_WRITE(pd, obscured_changes, obscured_changes);
|
|
|
|
if (redraw) return EINA_TRUE;
|
|
|
|
|
2017-03-22 23:55:41 -07:00
|
|
|
// Snapshot objects need to be redrawn if the padding has increased
|
|
|
|
if ((pd->data->prev_padding.l < pd->data->padding.l) ||
|
|
|
|
(pd->data->prev_padding.r < pd->data->padding.r) ||
|
|
|
|
(pd->data->prev_padding.t < pd->data->padding.t) ||
|
|
|
|
(pd->data->prev_padding.b < pd->data->padding.b))
|
|
|
|
return EINA_TRUE;
|
|
|
|
|
|
|
|
// Snapshot objects need to be redrawn if the obscured region has shrank
|
2017-04-03 18:25:05 -07:00
|
|
|
if (!was_empty && !_evas_eina_rectangle_inside(&pd->data->obscured, &prev))
|
2017-03-22 23:55:41 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
|
|
|
|
return EINA_FALSE;
|
2017-03-14 22:49:50 -07:00
|
|
|
}
|
|
|
|
|
2017-03-16 19:24:10 -07:00
|
|
|
void
|
|
|
|
_evas_filter_radius_get(Evas_Object_Protected_Data *obj, int *l, int *r, int *t, int *b)
|
|
|
|
{
|
|
|
|
Evas_Filter_Padding pad = {};
|
|
|
|
Evas_Filter_Data *pd;
|
|
|
|
|
|
|
|
pd = efl_data_scope_get(obj->object, MY_CLASS);
|
|
|
|
if (!pd->data || !pd->data->chain) goto end;
|
|
|
|
|
|
|
|
evas_filter_program_padding_get(pd->data->chain, NULL, &pad);
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (l) *l = pad.l;
|
|
|
|
if (r) *r = pad.r;
|
|
|
|
if (t) *t = pad.t;
|
|
|
|
if (b) *b = pad.b;
|
|
|
|
}
|
|
|
|
|
2016-06-09 23:55:28 -07:00
|
|
|
#include "canvas/efl_canvas_filter_internal.eo.c"
|