summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJean-Philippe Andre <jp.andre@samsung.com>2015-06-18 21:45:21 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2015-06-25 14:36:09 +0900
commit29402b2ce965c83cdcbfa29ac08b918ab01d95d2 (patch)
tree1ab6e4c9fc9d0e30985ee8f524edfef02235335a /src
parent351090f95de447c0d820bb02eb40889ab78b0736 (diff)
Evas filters: Complete support for image filtering
Reusing the new EO mixin, complete the support for image filtering. This now adds support for edje state inside the image filter.
Diffstat (limited to 'src')
-rw-r--r--src/lib/evas/canvas/evas_filter.eo6
-rw-r--r--src/lib/evas/canvas/evas_filter_mixin.c18
-rw-r--r--src/lib/evas/canvas/evas_image.eo65
-rw-r--r--src/lib/evas/canvas/evas_object_image.c559
-rw-r--r--src/lib/evas/canvas/evas_object_text.c31
-rw-r--r--src/lib/evas/canvas/evas_text.eo3
6 files changed, 166 insertions, 516 deletions
diff --git a/src/lib/evas/canvas/evas_filter.eo b/src/lib/evas/canvas/evas_filter.eo
index 7f6bdcb..2750e10 100644
--- a/src/lib/evas/canvas/evas_filter.eo
+++ b/src/lib/evas/canvas/evas_filter.eo
@@ -32,10 +32,15 @@ mixin Evas.Filter (Efl.Gfx.Filter)
32 This should be called at the beginning of a parent's class destructor. 32 This should be called at the beginning of a parent's class destructor.
33 ]] 33 ]]
34 } 34 }
35 input_alpha {
36 [[Called by Evas.Filter to determine whether the input is alpha or rgba.]]
37 return: bool;
38 }
35 input_render { 39 input_render {
36 [[Called by Evas.Filter when the parent class must render the input. 40 [[Called by Evas.Filter when the parent class must render the input.
37 ; 41 ;
38 ]] 42 ]]
43 return: bool; [[Indicates success from the object render function.]]
39 params { 44 params {
40 filter: void*; [[Evas_Filter_Context]] 45 filter: void*; [[Evas_Filter_Context]]
41 drawctx: void*; 46 drawctx: void*;
@@ -60,6 +65,7 @@ mixin Evas.Filter (Efl.Gfx.Filter)
60 Efl.Gfx.Filter.padding.get; 65 Efl.Gfx.Filter.padding.get;
61 Efl.Gfx.Filter.source_set; 66 Efl.Gfx.Filter.source_set;
62 Efl.Gfx.Filter.source_get; 67 Efl.Gfx.Filter.source_get;
68 @virtual .input_alpha;
63 @virtual .input_render; 69 @virtual .input_render;
64 @virtual .dirty; 70 @virtual .dirty;
65 } 71 }
diff --git a/src/lib/evas/canvas/evas_filter_mixin.c b/src/lib/evas/canvas/evas_filter_mixin.c
index 20aa8cc..243b359 100644
--- a/src/lib/evas/canvas/evas_filter_mixin.c
+++ b/src/lib/evas/canvas/evas_filter_mixin.c
@@ -222,21 +222,9 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
222 if (fcow->output != previous) 222 if (fcow->output != previous)
223 evas_filter_buffer_backing_release(filter, previous); 223 evas_filter_buffer_backing_release(filter, previous);
224 224
225 // Request rendering from the object itself (child class)
225 evas_filter_program_padding_get(fcow->chain, &l, &r, &t, &b); 226 evas_filter_program_padding_get(fcow->chain, &l, &r, &t, &b);
226 eo_do(eo_obj, evas_filter_input_render(filter, drawctx, l, r, t, b, do_async)); 227 eo_do(eo_obj, evas_filter_input_render(filter, drawctx, l, r, t, b, do_async));
227#warning TODO: draw text into input buffer
228#if 0
229 // Render text to input buffer
230 EINA_INLIST_FOREACH(EINA_INLIST_GET(pd->items), it)
231 if ((pd->font) && (it->text_props.len > 0))
232 {
233 evas_filter_font_draw(filter, drawctx, EVAS_FILTER_BUFFER_INPUT_ID, pd->font,
234 sl + it->x,
235 st + (int) pd->max_ascent,
236 &it->text_props,
237 do_async);
238 }
239#endif
240 228
241 ENFN->context_free(ENDT, drawctx); 229 ENFN->context_free(ENDT, drawctx);
242 230
@@ -268,6 +256,7 @@ _evas_filter_efl_gfx_filter_program_set(Eo *eo_obj, Evas_Filter_Data *pd,
268{ 256{
269 Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS); 257 Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
270 Evas_Filter_Program *pgm = NULL; 258 Evas_Filter_Program *pgm = NULL;
259 Eina_Bool alpha;
271 260
272 if (!pd) return; 261 if (!pd) return;
273 if (pd->data->code == code) return; 262 if (pd->data->code == code) return;
@@ -280,7 +269,8 @@ _evas_filter_efl_gfx_filter_program_set(Eo *eo_obj, Evas_Filter_Data *pd,
280 evas_filter_program_del(fcow->chain); 269 evas_filter_program_del(fcow->chain);
281 if (code) 270 if (code)
282 { 271 {
283 pgm = evas_filter_program_new("Evas_Text", EINA_TRUE); 272 alpha = eo_do_ret(eo_obj, alpha, evas_filter_input_alpha());
273 pgm = evas_filter_program_new("Evas.Filter", alpha);
284 evas_filter_program_source_set_all(pgm, fcow->sources); 274 evas_filter_program_source_set_all(pgm, fcow->sources);
285 evas_filter_program_state_set(pgm, eo_obj, obj, 275 evas_filter_program_state_set(pgm, eo_obj, obj,
286 fcow->state.cur.name, fcow->state.cur.value, 276 fcow->state.cur.name, fcow->state.cur.value,
diff --git a/src/lib/evas/canvas/evas_image.eo b/src/lib/evas/canvas/evas_image.eo
index 38231e3..9d387b5 100644
--- a/src/lib/evas/canvas/evas_image.eo
+++ b/src/lib/evas/canvas/evas_image.eo
@@ -1,4 +1,4 @@
1class Evas.Image (Evas.Object, Efl.File, Efl.Image, Efl.Gfx.Fill, Efl.Gfx.View) 1class Evas.Image (Evas.Object, Efl.File, Efl.Image, Efl.Gfx.Fill, Efl.Gfx.View, Evas.Filter)
2{ 2{
3 legacy_prefix: evas_object_image; 3 legacy_prefix: evas_object_image;
4 eo_prefix: evas_obj_image; 4 eo_prefix: evas_obj_image;
@@ -756,61 +756,6 @@ class Evas.Image (Evas.Object, Efl.File, Efl.Image, Efl.Gfx.Fill, Efl.Gfx.View)
756 scene: Evas.Canvas3D.Scene *; /*@ 3D scene on an image object. */ 756 scene: Evas.Canvas3D.Scene *; /*@ 3D scene on an image object. */
757 } 757 }
758 } 758 }
759 @property filter_program {
760 set {
761 /*@ Set an Evas filter program on this Text Object.
762
763 If the program fails to compile (syntax error, invalid
764 buffer name, etc...), the standard text effects will be
765 applied instead (SHADOW, etc...). switch back to the
766 standard text effects.
767
768 @since 1.9
769 @note EXPERIMENTAL FEATURE. This is an unstable API,
770 please use only for testing purposes.
771 @see @ref evasfiltersref "Evas filters reference"
772 */
773 legacy: null;
774 }
775 values {
776 program: const(char)*; /*@ The program code, as defined
777 by the @ref evasfiltersref "Evas filters script language".
778 Pass NULL to remove the former program and switch back
779 to the standard text effect
780
781 @since 1.9
782 @note EXPERIMENTAL FEATURE. This is an unstable API,
783 please use only for testing purposes.
784 @see @ref evasfiltersref "Evas filters reference"
785 */
786 }
787 }
788 @property filter_source {
789 set {
790 /*@ Bind an object to use as a mask or texture with Evas Filters.
791
792 This will create automatically a new RGBA buffer containing
793 the source object's pixels (as it is rendered). */
794 legacy: null;
795 }
796 values {
797 name: const(char)*; /*@ Object name as used in the program code */
798 eobj: Eo*; /*@ Eo object to use through proxy rendering */
799 }
800 }
801 @property filter_padding {
802 get {
803 /*@ Get the value of the extra padding set when a filter is used. */
804 return: bool; /*@ Returns false if the filter is invalid and padding is 0 */
805 legacy: null;
806 }
807 values {
808 l: int; /*@ Left padding in pixels */
809 r: int; /*@ Right padding in pixels */
810 t: int; /*@ Top padding in pixels */
811 b: int; /*@ Bottom padding in pixels */
812 }
813 }
814 @property orient { 759 @property orient {
815 set { 760 set {
816 /*@ 761 /*@
@@ -992,5 +937,13 @@ class Evas.Image (Evas.Object, Efl.File, Efl.Image, Efl.Gfx.Fill, Efl.Gfx.View)
992 Efl.Gfx.Fill.fill.get; 937 Efl.Gfx.Fill.fill.get;
993 Efl.Gfx.View.size.set; 938 Efl.Gfx.View.size.set;
994 Efl.Gfx.View.size.get; 939 Efl.Gfx.View.size.get;
940 Efl.Gfx.Filter.program.set;
941 Efl.Gfx.Filter.program.get;
942 Efl.Gfx.Filter.source_set;
943 Efl.Gfx.Filter.source_get;
944 Efl.Gfx.Filter.state.set;
945 Evas.Filter.input_alpha;
946 Evas.Filter.input_render;
947 Evas.Filter.dirty;
995 } 948 }
996} 949}
diff --git a/src/lib/evas/canvas/evas_object_image.c b/src/lib/evas/canvas/evas_object_image.c
index bbf5c80..7532c4a 100644
--- a/src/lib/evas/canvas/evas_object_image.c
+++ b/src/lib/evas/canvas/evas_object_image.c
@@ -14,6 +14,9 @@
14#include "../common/evas_convert_color.h" 14#include "../common/evas_convert_color.h"
15#include "../common/evas_convert_colorspace.h" 15#include "../common/evas_convert_colorspace.h"
16#include "../common/evas_convert_yuv.h" 16#include "../common/evas_convert_yuv.h"
17
18#include "../efl/interfaces/efl_gfx_filter.eo.h"
19#include "evas_filter.eo.h"
17#include "evas_filter.h" 20#include "evas_filter.h"
18 21
19#define MY_CLASS EVAS_IMAGE_CLASS 22#define MY_CLASS EVAS_IMAGE_CLASS
@@ -78,8 +81,6 @@ struct _Evas_Object_Image_State
78 unsigned char fill; 81 unsigned char fill;
79 } border; 82 } border;
80 83
81 const Evas_Object_Filter_Data *filter;
82
83 Evas_Object *source; 84 Evas_Object *source;
84 Evas_Map *defmap; 85 Evas_Map *defmap;
85 Evas_Canvas3D_Scene *scene; 86 Evas_Canvas3D_Scene *scene;
@@ -131,6 +132,7 @@ struct _Evas_Object_Image
131 Eina_Bool proxy_src_clip : 1; 132 Eina_Bool proxy_src_clip : 1;
132 Eina_Bool written : 1; 133 Eina_Bool written : 1;
133 Eina_Bool direct_render : 1; 134 Eina_Bool direct_render : 1;
135 Eina_Bool has_filter : 1;
134 struct 136 struct
135 { 137 {
136 Eina_Bool video_move : 1; 138 Eina_Bool video_move : 1;
@@ -151,6 +153,9 @@ static void evas_object_image_render(Evas_Object *eo_obj, Evas_Object_Protected_
151 void *type_private_data, 153 void *type_private_data,
152 void *output, void *context, void *surface, 154 void *output, void *context, void *surface,
153 int x, int y, Eina_Bool do_async); 155 int x, int y, Eina_Bool do_async);
156static void _evas_image_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
157 void *output, void *context, void *surface,
158 int x, int y, Eina_Bool do_async);
154static void evas_object_image_free(Evas_Object *eo_obj, 159static void evas_object_image_free(Evas_Object *eo_obj,
155 Evas_Object_Protected_Data *obj); 160 Evas_Object_Protected_Data *obj);
156static void evas_object_image_render_pre(Evas_Object *eo_obj, 161static void evas_object_image_render_pre(Evas_Object *eo_obj,
@@ -231,7 +236,6 @@ static const Evas_Object_Image_State default_state = {
231 { 0, 0, 0, 0 }, // fill 236 { 0, 0, 0, 0 }, // fill
232 { 0, 0, 0 }, // image 237 { 0, 0, 0 }, // image
233 { 1.0, 0, 0, 0, 0, 1 }, // border 238 { 1.0, 0, 0, 0, 0, 1 }, // border
234 NULL, // filter
235 NULL, NULL, NULL, //source, defmap, scene 239 NULL, NULL, NULL, //source, defmap, scene
236 { NULL }, //u 240 { NULL }, //u
237 NULL, //key 241 NULL, //key
@@ -267,12 +271,6 @@ Eina_Cow *evas_object_image_state_cow = NULL;
267# define EINA_COW_IMAGE_STATE_WRITE_END(Obj, Write) \ 271# define EINA_COW_IMAGE_STATE_WRITE_END(Obj, Write) \
268 EINA_COW_WRITE_END(evas_object_image_state_cow, Obj->cur, Write) 272 EINA_COW_WRITE_END(evas_object_image_state_cow, Obj->cur, Write)
269 273
270# define EINA_COW_IMAGE_FILTER_WRITE_BEGIN(State, Write) \
271 EINA_COW_WRITE_BEGIN(evas_object_filter_cow, State->filter, Evas_Object_Filter_Data, Write)
272
273# define EINA_COW_IMAGE_FILTER_WRITE_END(State, Write) \
274 EINA_COW_WRITE_END(evas_object_filter_cow, State->filter, Write)
275
276# define EVAS_OBJECT_WRITE_IMAGE_FREE_FILE_AND_KEY(Obj) \ 274# define EVAS_OBJECT_WRITE_IMAGE_FREE_FILE_AND_KEY(Obj) \
277 if ((!Obj->cur->mmaped_source && Obj->cur->u.file) || Obj->cur->key) \ 275 if ((!Obj->cur->mmaped_source && Obj->cur->u.file) || Obj->cur->key) \
278 { \ 276 { \
@@ -362,16 +360,15 @@ _evas_image_eo_base_constructor(Eo *eo_obj, Evas_Image_Data *o)
362 o->proxy_src_clip = EINA_TRUE; 360 o->proxy_src_clip = EINA_TRUE;
363 361
364 cspace = ENFN->image_colorspace_get(ENDT, o->engine_data); 362 cspace = ENFN->image_colorspace_get(ENDT, o->engine_data);
365 363 if (cspace != o->cur->cspace)
366 if (!o->cur->filter || (cspace != o->cur->cspace))
367 { 364 {
368 EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write) 365 EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
369 state_write->cspace = cspace; 366 state_write->cspace = cspace;
370 if (!state_write->filter)
371 state_write->filter = eina_cow_alloc(evas_object_filter_cow);
372 EINA_COW_IMAGE_STATE_WRITE_END(o, state_write); 367 EINA_COW_IMAGE_STATE_WRITE_END(o, state_write);
373 } 368 }
374 369
370 eo_do(eo_obj, evas_filter_constructor());
371
375 return eo_obj; 372 return eo_obj;
376} 373}
377 374
@@ -2874,6 +2871,8 @@ evas_object_image_free(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj)
2874 } 2871 }
2875 EINA_COW_PIXEL_WRITE_END(o, pixi_write); 2872 EINA_COW_PIXEL_WRITE_END(o, pixi_write);
2876 } 2873 }
2874
2875 eo_do(eo_obj, evas_filter_destructor());
2877} 2876}
2878 2877
2879static void 2878static void
@@ -3050,35 +3049,74 @@ evas_process_dirty_pixels(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj,
3050 return pixels; 3049 return pixels;
3051} 3050}
3052 3051
3053static void 3052EOLIAN void
3054_filter_cb(Evas_Filter_Context *ctx, void *data, Eina_Bool success) 3053_evas_image_evas_filter_dirty(Eo *eo_obj EINA_UNUSED, Evas_Image_Data *o)
3054{
3055 o->changed = 1;
3056}
3057
3058EOLIAN Eina_Bool
3059_evas_image_evas_filter_input_alpha(Eo *eo_obj EINA_UNUSED, Evas_Image_Data *o EINA_UNUSED)
3055{ 3060{
3056 Eo *eo_obj = data; 3061 return EINA_FALSE;
3062}
3063
3064EOLIAN Eina_Bool
3065_evas_image_evas_filter_input_render(Eo *eo_obj, Evas_Image_Data *o,
3066 void *_filter, void *context,
3067 int l, int r EINA_UNUSED, int t, int b EINA_UNUSED,
3068 Eina_Bool do_async)
3069{
3070 Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
3071 Evas_Filter_Context *filter = _filter;
3072 void *surface, *output;
3073 Eina_Bool input_stolen;
3074 int W, H;
3075
3076 W = obj->cur->geometry.w;
3077 H = obj->cur->geometry.h;
3078 output = ENDT;
3057 3079
3058 // Destroy context as we won't reuse it. 3080 if (ENFN->gl_surface_read_pixels)
3059 evas_filter_context_destroy(ctx); 3081 {
3082 surface = ENFN->image_map_surface_new(output, W, H, EINA_TRUE);
3083 input_stolen = EINA_FALSE;
3084 }
3085 else
3086 {
3087 surface = evas_filter_buffer_backing_steal(filter, EVAS_FILTER_BUFFER_INPUT_ID);
3088 input_stolen = EINA_TRUE;
3089 }
3090 if (!o->filled)
3091 {
3092 l = 0;
3093 t = 0;
3094 }
3060 3095
3061 // Redraw image normally 3096 if (!surface)
3062 if (!success)
3063 { 3097 {
3064 Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS); 3098 ERR("Failed to allocate surface for filter input!");
3065 Evas_Image_Data *o = (Evas_Image_Data *) obj->private_data; 3099 return EINA_FALSE;
3100 }
3066 3101
3067 ERR("Filter failed at runtime!"); 3102 ENFN->context_color_set(output, context, 0, 0, 0, 0);
3068 EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write) 3103 ENFN->context_render_op_set(output, context, EVAS_RENDER_COPY);
3069 EINA_COW_IMAGE_FILTER_WRITE_BEGIN(state_write, fcow) 3104 ENFN->rectangle_draw(output, context, surface, 0, 0, W, H, EINA_FALSE);
3070 fcow->invalid = EINA_TRUE; 3105 ENFN->context_color_set(output, context, 255, 255, 255, 255);
3071 EINA_COW_IMAGE_FILTER_WRITE_END(state_write, fcow) 3106 ENFN->context_render_op_set(output, context, EVAS_RENDER_BLEND);
3072 EINA_COW_IMAGE_STATE_WRITE_END(o, state_write)
3073 3107
3074 // Update object 3108 _evas_image_render(eo_obj, obj, output, context, surface,
3075 obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS); 3109 l - obj->cur->geometry.x, t - obj->cur->geometry.y, do_async);
3076 o->changed = EINA_TRUE; 3110
3077 evas_object_change(eo_obj, obj); 3111 if (!input_stolen)
3078 evas_object_clip_dirty(eo_obj, obj); 3112 {
3079 evas_object_coords_recalc(eo_obj, obj); 3113 evas_filter_image_draw(filter, context, EVAS_FILTER_BUFFER_INPUT_ID, surface, do_async);
3080 evas_object_inform_call_resize(eo_obj); 3114 ENFN->image_map_surface_free(output, surface);
3081 } 3115 }
3116 else
3117 evas_filter_buffer_backing_release(filter, surface);
3118
3119 return EINA_TRUE;
3082} 3120}
3083 3121
3084static void 3122static void
@@ -3086,8 +3124,6 @@ evas_object_image_render(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, v
3086 void *output, void *context, void *surface, int x, int y, Eina_Bool do_async) 3124 void *output, void *context, void *surface, int x, int y, Eina_Bool do_async)
3087{ 3125{
3088 Evas_Image_Data *o = type_private_data; 3126 Evas_Image_Data *o = type_private_data;
3089 int imagew, imageh, uvw, uvh;
3090 void *pixels;
3091 3127
3092 if ((o->cur->fill.w < 1) || (o->cur->fill.h < 1)) 3128 if ((o->cur->fill.w < 1) || (o->cur->fill.h < 1))
3093 return; /* no error message, already printed in pre_render */ 3129 return; /* no error message, already printed in pre_render */
@@ -3145,6 +3181,24 @@ evas_object_image_render(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, v
3145 if (ENFN->gl_image_direct_set) 3181 if (ENFN->gl_image_direct_set)
3146 ENFN->gl_image_direct_set(output, o->engine_data, EINA_FALSE); 3182 ENFN->gl_image_direct_set(output, o->engine_data, EINA_FALSE);
3147 3183
3184 /* Render filter */
3185 if (o->has_filter)
3186 {
3187 if (evas_filter_object_render(eo_obj, obj, output, context, surface, x, y, do_async, EINA_FALSE))
3188 return;
3189 }
3190
3191 _evas_image_render(eo_obj, obj, output, context, surface, x, y, do_async);
3192}
3193
3194static void
3195_evas_image_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
3196 void *output, void *context, void *surface, int x, int y, Eina_Bool do_async)
3197{
3198 Evas_Image_Data *o = obj->private_data;
3199 int imagew, imageh, uvw, uvh;
3200 void *pixels;
3201
3148 Evas_Object_Protected_Data *source = 3202 Evas_Object_Protected_Data *source =
3149 (o->cur->source ? 3203 (o->cur->source ?
3150 eo_data_scope_get(o->cur->source, EVAS_OBJECT_CLASS): 3204 eo_data_scope_get(o->cur->source, EVAS_OBJECT_CLASS):
@@ -3216,14 +3270,8 @@ evas_object_image_render(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, v
3216 } 3270 }
3217 else 3271 else
3218 { 3272 {
3219 Evas_Filter_Context *filter = NULL; 3273 int offx, offy;
3220 void * const surface_save = surface; 3274
3221 void * const context_save = context;
3222 Eina_Bool input_stolen = EINA_FALSE;
3223 Eina_Bool clear = EINA_FALSE;
3224 int W, H, offx, offy;
3225
3226start_draw:
3227 ENFN->image_scale_hint_set(output, pixels, o->scale_hint); 3275 ENFN->image_scale_hint_set(output, pixels, o->scale_hint);
3228 /* This is technically a bug here: If the value is recreated 3276 /* This is technically a bug here: If the value is recreated
3229 * (which is returned)it may be a new object, however exactly 0 3277 * (which is returned)it may be a new object, however exactly 0
@@ -3241,153 +3289,6 @@ start_draw:
3241 offx = obj->cur->geometry.x + x; 3289 offx = obj->cur->geometry.x + x;
3242 offy = obj->cur->geometry.y + y; 3290 offy = obj->cur->geometry.y + y;
3243 3291
3244 /* Evas Filters on Image Object. Yet another experimental piece of code.
3245 * Replace current context, offset and surface by filter-made targets.
3246 *
3247 * Mechanism:
3248 * 1. Create a new surface & context, matching the object geometry
3249 * 2. Render all borders & tiles into that surface
3250 * 3. Apply effect and draw this surface into the original target
3251 *
3252 * Notes:
3253 * This becomes VERY SLOW when the image OBJECT size grows... even if
3254 * the image itself is very small. But we can't really apply a proper blur
3255 * over one tile and repeat since blurs should overlap.
3256 *
3257 * Behaviour depends on the 'filled' flag:
3258 * - If filled, then scale down the image to accomodate the whole filter's padding.
3259 * - Otherwise, draw image in place and clip the filter's effects (eg. blur will be clipped out).
3260 */
3261 if (!o->cur->filter->invalid && o->cur->filter->code)
3262 {
3263 Evas_Filter_Program *pgm = o->cur->filter->chain;
3264 Eina_Bool redraw = (o->changed || o->cur->filter->changed);
3265 Eina_Bool ok;
3266
3267 evas_filter_program_padding_get(pgm, &l, &r, &t, &b);
3268 W = obj->cur->geometry.w;
3269 H = obj->cur->geometry.h;
3270
3271#warning implement state_set from edje
3272 if (pgm && evas_filter_program_state_set(pgm, eo_obj, obj, NULL, 0.0, NULL, 0.0, 0.0))
3273 redraw = EINA_TRUE;
3274
3275 if (!redraw && o->cur->filter->output)
3276 {
3277 if (eina_hash_population(o->cur->filter->sources) > 0)
3278 {
3279 Evas_Filter_Proxy_Binding *pb;
3280 Evas_Object_Protected_Data *prxsource;
3281 Eina_Iterator *iter;
3282
3283 iter = eina_hash_iterator_data_new(o->cur->filter->sources);
3284 EINA_ITERATOR_FOREACH(iter, pb)
3285 {
3286 prxsource = eo_data_scope_get(pb->eo_source, EVAS_OBJECT_CLASS);
3287 if (prxsource->changed)
3288 {
3289 redraw = EINA_TRUE;
3290 break;
3291 }
3292 }
3293 eina_iterator_free(iter);
3294 }
3295
3296 if (!redraw)
3297 {
3298 // Render this image only
3299 ENFN->image_draw(output, context,
3300 surface, o->cur->filter->output,
3301 0, 0, W, H,
3302 offx, offy, W, H,
3303 EINA_TRUE,
3304 do_async);
3305 return;
3306 }
3307 }
3308
3309 if (!pgm)
3310 {
3311 pgm = evas_filter_program_new("Image", EINA_FALSE);
3312 evas_filter_program_source_set_all(pgm, o->cur->filter->sources);
3313 evas_filter_program_state_set(pgm, eo_obj, obj, NULL, 0.0, NULL, 0.0, 0.0);
3314 ok = evas_filter_program_parse(pgm, o->cur->filter->code);
3315 if (!ok) goto state_write;
3316 }
3317
3318 filter = evas_filter_context_new(obj->layer->evas, do_async);
3319 ok = evas_filter_context_program_use(filter, pgm);
3320 if (!ok) goto state_write;
3321
3322 evas_filter_context_proxy_render_all(filter, eo_obj, EINA_FALSE);
3323 ok = evas_filter_context_buffers_allocate_all(filter);
3324 if (!ok) goto state_write;
3325
3326 if (ENFN->gl_surface_read_pixels)
3327 {
3328 // GL case: Create new surface, draw to it (OpenGL) and call glReadPixels
3329 surface = ENFN->image_map_surface_new(output, W, H, EINA_TRUE);
3330 input_stolen = EINA_FALSE;
3331 }
3332 else
3333 {
3334 // Software case: Directly draw into the filter's input buffer
3335 surface = evas_filter_buffer_backing_steal(filter, EVAS_FILTER_BUFFER_INPUT_ID);
3336 input_stolen = EINA_TRUE;
3337 }
3338
3339 if (!surface)
3340 {
3341 surface = surface_save;
3342 ok = EINA_FALSE;
3343 }
3344
3345state_write:
3346 EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
3347 {
3348 if (ok)
3349 {
3350 context = ENFN->context_new(output);
3351 clear = EINA_TRUE;
3352 EINA_COW_IMAGE_FILTER_WRITE_BEGIN(state_write, fcow)
3353 fcow->chain = pgm;
3354 EINA_COW_IMAGE_FILTER_WRITE_END(state_write, fcow)
3355 if (!o->filled)
3356 {
3357 offx = 0;
3358 offy = 0;
3359 }
3360 else
3361 {
3362 offx = l;
3363 offy = t;
3364 }
3365 }
3366 else
3367 {
3368 ERR("Failed to apply this filter");
3369 evas_filter_context_destroy(filter);
3370 evas_filter_program_del(pgm);
3371 EINA_COW_IMAGE_FILTER_WRITE_BEGIN(state_write, fcow)
3372 fcow->invalid = EINA_TRUE;
3373 fcow->chain = NULL;
3374 EINA_COW_IMAGE_FILTER_WRITE_END(state_write, fcow)
3375 l = r = t = b = 0;
3376 filter = NULL;
3377 }
3378 }
3379 EINA_COW_IMAGE_STATE_WRITE_END(o, state_write)
3380
3381 if (clear)
3382 {
3383 ENFN->context_color_set(output, context, 0, 0, 0, 0);
3384 ENFN->context_render_op_set(output, context, EVAS_RENDER_COPY);
3385 ENFN->rectangle_draw(output, context, surface, 0, 0, W, H, EINA_FALSE);
3386 ENFN->context_color_set(output, context, 255, 255, 255, 255);
3387 ENFN->context_render_op_set(output, context, EVAS_RENDER_BLEND);
3388 }
3389 }
3390
3391 while ((int)idx < obj->cur->geometry.w) 3292 while ((int)idx < obj->cur->geometry.w)
3392 { 3293 {
3393 Evas_Coord ydy; 3294 Evas_Coord ydy;
@@ -3612,58 +3513,6 @@ state_write:
3612 idy = ydy; 3513 idy = ydy;
3613 if (dobreak_w) break; 3514 if (dobreak_w) break;
3614 } 3515 }
3615
3616 /* Evas filters wrap-up */
3617 if (filter)
3618 {
3619 Eina_Bool ok = EINA_FALSE;
3620
3621 EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
3622 EINA_COW_IMAGE_FILTER_WRITE_BEGIN(state_write, fcow)
3623 {
3624
3625 void *outbuf = evas_filter_buffer_backing_steal(filter, EVAS_FILTER_BUFFER_OUTPUT_ID);
3626 if (outbuf != fcow->output)
3627 {
3628 evas_filter_buffer_backing_release(filter, fcow->output);
3629 fcow->output = outbuf;
3630 }
3631
3632 if (!input_stolen)
3633 evas_filter_image_draw(filter, context, EVAS_FILTER_BUFFER_INPUT_ID, surface, do_async);
3634 else
3635 evas_filter_buffer_backing_release(filter, surface);
3636
3637 evas_filter_target_set(filter, context_save, surface_save, obj->cur->geometry.x + x, obj->cur->geometry.y + y);
3638 evas_filter_context_post_run_callback_set(filter, _filter_cb, eo_obj);
3639 ok = evas_filter_run(filter);
3640
3641 if (!input_stolen)
3642 ENFN->image_map_surface_free(output, surface);
3643 ENFN->context_free(output, context);
3644
3645 if (!ok)
3646 {
3647 ERR("Rendering failed");
3648 fcow->invalid = EINA_TRUE;
3649 l = r = t = b = 0;
3650 context = context_save;
3651 surface = surface_save;
3652 input_stolen = EINA_FALSE;
3653 clear = EINA_FALSE;
3654 filter = NULL;
3655 }
3656 else
3657 {
3658 fcow->changed = EINA_FALSE;
3659 }
3660 }
3661 EINA_COW_IMAGE_FILTER_WRITE_END(state_write, fcow)
3662 EINA_COW_IMAGE_STATE_WRITE_END(o, state_write)
3663
3664 if (!ok)
3665 goto start_draw;
3666 }
3667 } 3516 }
3668 } 3517 }
3669} 3518}
@@ -3823,11 +3672,6 @@ evas_object_image_render_pre(Evas_Object *eo_obj,
3823 evas_object_render_pre_prev_cur_add(&e->clip_changes, eo_obj, obj); 3672 evas_object_render_pre_prev_cur_add(&e->clip_changes, eo_obj, obj);
3824 if (!o->pixels->pixel_updates) goto done; 3673 if (!o->pixels->pixel_updates) goto done;
3825 } 3674 }
3826 if (o->cur->filter->changed)
3827 {
3828 evas_object_render_pre_prev_cur_add(&e->clip_changes, eo_obj, obj);
3829 if (!o->pixels->pixel_updates) goto done;
3830 }
3831 if (o->changed) 3675 if (o->changed)
3832 { 3676 {
3833 if ((o->cur->fill.x != o->prev->fill.x) || 3677 if ((o->cur->fill.x != o->prev->fill.x) ||
@@ -4819,189 +4663,6 @@ _evas_object_image_video_overlay_do(Evas_Object *eo_obj)
4819 o->delayed.video_hide = EINA_FALSE; 4663 o->delayed.video_hide = EINA_FALSE;
4820} 4664}
4821 4665
4822/* Evas Filters functions. Similar to Evas_Text. */
4823
4824EOLIAN static void
4825_evas_image_filter_program_set(Eo *eo_obj, Evas_Image_Data *o, const char *arg)
4826{
4827 Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
4828 Evas_Filter_Program *pgm = NULL;
4829
4830 if (!o) return;
4831 if (o->cur->filter->code == arg) return;
4832 if (o->cur->filter->code && arg && !strcmp(arg, o->cur->filter->code)) return;
4833
4834 evas_object_async_block(obj);
4835 EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
4836 EINA_COW_IMAGE_FILTER_WRITE_BEGIN(state_write, fcow)
4837 {
4838 // Parse filter program
4839 evas_filter_program_del(fcow->chain);
4840 if (arg)
4841 {
4842 pgm = evas_filter_program_new("Evas_Text: Filter Program", EINA_FALSE);
4843 evas_filter_program_source_set_all(pgm, fcow->sources);
4844 evas_filter_program_state_set(pgm, eo_obj, obj, NULL, 0.0, NULL, 0.0, 0.0);
4845 if (!evas_filter_program_parse(pgm, arg))
4846 {
4847 ERR("Parsing failed!");
4848 evas_filter_program_del(pgm);
4849 pgm = NULL;
4850 }
4851 }
4852
4853 fcow->chain = pgm;
4854 fcow->changed = EINA_TRUE;
4855 fcow->invalid = (pgm == NULL);
4856 eina_stringshare_replace(&fcow->code, arg);
4857 }
4858 EINA_COW_IMAGE_FILTER_WRITE_END(state_write, fcow)
4859 EINA_COW_IMAGE_STATE_WRITE_END(o, state_write);
4860
4861 // Update object
4862 o->changed = EINA_TRUE;
4863 evas_object_change(eo_obj, obj);
4864}
4865
4866static void
4867_filter_source_hash_free_cb(void *data)
4868{
4869 Evas_Filter_Proxy_Binding *pb = data;
4870 Evas_Object_Protected_Data *proxy, *source;
4871 Evas_Image_Data *o;
4872
4873 proxy = eo_data_scope_get(pb->eo_proxy, EVAS_OBJECT_CLASS);
4874 source = eo_data_scope_get(pb->eo_source, EVAS_OBJECT_CLASS);
4875
4876 if (source)
4877 {
4878 EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, source->proxy,
4879 Evas_Object_Proxy_Data, source_write)
4880 source_write->proxies = eina_list_remove(source_write->proxies, pb->eo_proxy);
4881 EINA_COW_WRITE_END(evas_object_proxy_cow, source->proxy, source_write)
4882 }
4883
4884 o = eo_data_scope_get(pb->eo_proxy, MY_CLASS);
4885
4886 if (o && proxy)
4887 {
4888 if (!eina_hash_population(o->cur->filter->sources))
4889 {
4890 EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, proxy->proxy,
4891 Evas_Object_Proxy_Data, proxy_write)
4892 proxy_write->is_proxy = EINA_FALSE;
4893 EINA_COW_WRITE_END(evas_object_proxy_cow, source->proxy, proxy_write)
4894 }
4895 }
4896
4897 eina_stringshare_del(pb->name);
4898 free(pb);
4899}
4900
4901EOLIAN static void
4902_evas_image_filter_source_set(Eo *eo_obj, Evas_Image_Data *o, const char *name,
4903 Evas_Object *eo_source)
4904{
4905
4906 Evas_Object_Protected_Data *obj;
4907 Evas_Filter_Program *pgm = o->cur->filter->chain;
4908 Evas_Filter_Proxy_Binding *pb, *pb_old = NULL;
4909 Evas_Object_Protected_Data *source = NULL;
4910 Eina_Hash *sources = o->cur->filter->sources;
4911
4912 obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
4913 evas_object_async_block(obj);
4914 if (eo_source) source = eo_data_scope_get(eo_source, EVAS_OBJECT_CLASS);
4915
4916 if (!name)
4917 {
4918 if (!eo_source || !o->cur->filter->sources) return;
4919 if (eina_hash_del_by_data(o->cur->filter->sources, eo_source))
4920 goto update;
4921 return;
4922 }
4923
4924 if (!sources)
4925 {
4926 if (!source) return;
4927 sources = eina_hash_string_small_new
4928 (EINA_FREE_CB(_filter_source_hash_free_cb));
4929 }
4930 else
4931 {
4932 pb_old = eina_hash_find(sources, name);
4933 if (pb_old)
4934 {
4935 if (pb_old->eo_source == eo_source) goto update;
4936 eina_hash_del(sources, name, pb_old);
4937 }
4938 }
4939
4940 if (!source)
4941 {
4942 pb_old = eina_hash_find(sources, name);
4943 if (!pb_old) return;
4944 eina_hash_del_by_key(sources, name);
4945 goto update;
4946 }
4947
4948 pb = calloc(1, sizeof(*pb));
4949 pb->eo_proxy = eo_obj;
4950 pb->eo_source = eo_source;
4951 pb->name = eina_stringshare_add(name);
4952
4953 EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, source->proxy,
4954 Evas_Object_Proxy_Data, source_write)
4955 if (!eina_list_data_find(source_write->proxies, eo_obj))
4956 source_write->proxies = eina_list_append(source_write->proxies, eo_obj);
4957 EINA_COW_WRITE_END(evas_object_proxy_cow, source->proxy, source_write)
4958
4959 EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, obj->proxy,
4960 Evas_Object_Proxy_Data, proxy_write)
4961 proxy_write->is_proxy = EINA_TRUE;
4962 EINA_COW_WRITE_END(evas_object_proxy_cow, obj->proxy, proxy_write)
4963
4964 eina_hash_add(sources, pb->name, pb);
4965 evas_filter_program_source_set_all(pgm, sources);
4966
4967update:
4968 EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
4969 EINA_COW_IMAGE_FILTER_WRITE_BEGIN(state_write, fcow)
4970 fcow->changed = EINA_TRUE;
4971 fcow->invalid = EINA_FALSE;
4972 fcow->sources = sources;
4973 EINA_COW_IMAGE_FILTER_WRITE_END(state_write, fcow)
4974 EINA_COW_IMAGE_STATE_WRITE_END(o, state_write);
4975
4976 // Update object
4977 o->changed = 1;
4978 evas_object_change(eo_obj, obj);
4979 evas_object_clip_dirty(eo_obj, obj);
4980 evas_object_coords_recalc(eo_obj, obj);
4981 evas_object_inform_call_resize(eo_obj);
4982}
4983
4984EOLIAN Eina_Bool
4985_evas_image_filter_padding_get(Eo *obj EINA_UNUSED, Evas_Image_Data *o,
4986 int *l, int *r, int *t, int *b)
4987{
4988 Evas_Filter_Program *pgm = o->cur->filter->chain;
4989 int pl = 0, pr = 0, pt = 0, pb = 0;
4990 Eina_Bool used = EINA_FALSE;
4991
4992 if (pgm)
4993 {
4994 used = !o->cur->filter->invalid;
4995 evas_filter_program_padding_get(pgm, &pl, &pr, &pt, &pb);
4996 }
4997
4998 if (l) *l = pl;
4999 if (r) *r = pr;
5000 if (t) *t = pt;
5001 if (b) *b = pb;
5002 return used;
5003}
5004
5005/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/ 4666/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/
5006 4667
5007EAPI void 4668EAPI void
@@ -5067,4 +4728,38 @@ evas_object_image_smooth_scale_get(const Eo *obj)
5067 return eo_do_ret((Eo *) obj, ret, efl_image_smooth_scale_get()); 4728 return eo_do_ret((Eo *) obj, ret, efl_image_smooth_scale_get());
5068} 4729}
5069 4730
4731EOLIAN void
4732_evas_image_efl_gfx_filter_program_set(Eo *obj, Evas_Image_Data *pd EINA_UNUSED, const char *code)
4733{
4734 pd->has_filter = (code != NULL);
4735 eo_do_super(obj, MY_CLASS, efl_gfx_filter_program_set(code));
4736}
4737
4738EOLIAN const char *
4739_evas_image_efl_gfx_filter_program_get(Eo *obj, Evas_Image_Data *pd EINA_UNUSED)
4740{
4741 const char *code;
4742 return eo_do_super_ret(obj, MY_CLASS, code, efl_gfx_filter_program_get());
4743}
4744
4745EOLIAN void
4746_evas_image_efl_gfx_filter_source_set(Eo *obj, Evas_Image_Data *pd EINA_UNUSED, const char *name, Efl_Gfx_Base *source)
4747{
4748 eo_do_super(obj, MY_CLASS, efl_gfx_filter_source_set(name, source));
4749}
4750
4751EOLIAN void
4752_evas_image_efl_gfx_filter_source_get(Eo *obj, Evas_Image_Data *pd EINA_UNUSED, const char *name, Efl_Gfx_Base **source)
4753{
4754 eo_do_super(obj, MY_CLASS, efl_gfx_filter_source_get(name, source));
4755}
4756
4757EOLIAN void
4758_evas_image_efl_gfx_filter_state_set(Eo *obj, Evas_Image_Data *pd EINA_UNUSED,
4759 const char *cur_state, double cur_val,
4760 const char *next_state, double next_val, double pos)
4761{
4762 eo_do_super(obj, MY_CLASS, efl_gfx_filter_state_set(cur_state, cur_val, next_state, next_val, pos));
4763}
4764
5070#include "canvas/evas_image.eo.c" 4765#include "canvas/evas_image.eo.c"
diff --git a/src/lib/evas/canvas/evas_object_text.c b/src/lib/evas/canvas/evas_object_text.c
index 6535046..899b625 100644
--- a/src/lib/evas/canvas/evas_object_text.c
+++ b/src/lib/evas/canvas/evas_object_text.c
@@ -1589,24 +1589,34 @@ _evas_text_evas_filter_dirty(Eo *eo_obj, Evas_Text_Data *o)
1589 _evas_object_text_recalc(eo_obj, o->cur.text); 1589 _evas_object_text_recalc(eo_obj, o->cur.text);
1590} 1590}
1591 1591
1592EOLIAN void 1592EOLIAN Eina_Bool
1593_evas_text_evas_filter_input_alpha(Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o EINA_UNUSED)
1594{
1595 return EINA_TRUE;
1596}
1597
1598EOLIAN Eina_Bool
1593_evas_text_evas_filter_input_render(Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o, 1599_evas_text_evas_filter_input_render(Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o,
1594 void *_filter, void *drawctx, 1600 void *_filter, void *drawctx,
1595 int l, int r, int t, int b, Eina_Bool do_async) 1601 int l, int r EINA_UNUSED, int t, int b EINA_UNUSED,
1602 Eina_Bool do_async)
1596{ 1603{
1597 Evas_Filter_Context *filter = _filter; 1604 Evas_Filter_Context *filter = _filter;
1598 Evas_Object_Text_Item *it; 1605 Evas_Object_Text_Item *it;
1599 (void) r; (void) b;
1600 1606
1601 EINA_INLIST_FOREACH(EINA_INLIST_GET(o->items), it) 1607 EINA_INLIST_FOREACH(EINA_INLIST_GET(o->items), it)
1602 if ((o->font) && (it->text_props.len > 0)) 1608 if ((o->font) && (it->text_props.len > 0))
1603 { 1609 {
1604 evas_filter_font_draw(filter, drawctx, EVAS_FILTER_BUFFER_INPUT_ID, o->font, 1610 if (!evas_filter_font_draw(filter, drawctx,
1605 l + it->x, 1611 EVAS_FILTER_BUFFER_INPUT_ID, o->font,
1606 t + (int) o->max_ascent, 1612 l + it->x,
1607 &it->text_props, 1613 t + (int) o->max_ascent,
1608 do_async); 1614 &it->text_props,
1615 do_async))
1616 return EINA_FALSE;
1609 } 1617 }
1618
1619 return EINA_TRUE;
1610} 1620}
1611 1621
1612static void 1622static void
@@ -2216,9 +2226,6 @@ evas_object_text_text_get(const Eo *obj)
2216 return eo_do_ret((Eo *) obj, ret, efl_text_get()); 2226 return eo_do_ret((Eo *) obj, ret, efl_text_get());
2217} 2227}
2218 2228
2219
2220/* urgh. why are those needed? */
2221
2222EOLIAN void 2229EOLIAN void
2223_evas_text_efl_gfx_filter_program_set(Eo *obj, Evas_Text_Data *pd EINA_UNUSED, const char *code) 2230_evas_text_efl_gfx_filter_program_set(Eo *obj, Evas_Text_Data *pd EINA_UNUSED, const char *code)
2224{ 2231{
@@ -2253,6 +2260,4 @@ _evas_text_efl_gfx_filter_state_set(Eo *obj, Evas_Text_Data *pd EINA_UNUSED,
2253 eo_do_super(obj, MY_CLASS, efl_gfx_filter_state_set(cur_state, cur_val, next_state, next_val, pos)); 2260 eo_do_super(obj, MY_CLASS, efl_gfx_filter_state_set(cur_state, cur_val, next_state, next_val, pos));
2254} 2261}
2255 2262
2256
2257
2258#include "canvas/evas_text.eo.c" 2263#include "canvas/evas_text.eo.c"
diff --git a/src/lib/evas/canvas/evas_text.eo b/src/lib/evas/canvas/evas_text.eo
index 5991c0a..c21b2c4 100644
--- a/src/lib/evas/canvas/evas_text.eo
+++ b/src/lib/evas/canvas/evas_text.eo
@@ -331,7 +331,8 @@ class Evas.Text (Evas.Object, Efl.Text, Efl.Text_Properties, Evas.Filter)
331 Efl.Gfx.Filter.source_set; 331 Efl.Gfx.Filter.source_set;
332 Efl.Gfx.Filter.source_get; 332 Efl.Gfx.Filter.source_get;
333 Efl.Gfx.Filter.state.set; 333 Efl.Gfx.Filter.state.set;
334 Evas.Filter.dirty; 334 Evas.Filter.input_alpha;
335 Evas.Filter.input_render; 335 Evas.Filter.input_render;
336 Evas.Filter.dirty;
336 } 337 }
337} 338}