1 #ifndef EVAS_FILTER_PRIVATE_H
2 #define EVAS_FILTER_PRIVATE_H
3 
4 #include "evas_filter.h"
5 #include "evas_private.h"
6 
7 /* logging variables */
8 extern int _evas_filter_log_dom;
9 #define EVAS_FILTER_LOG_COLOR EINA_COLOR_LIGHTBLUE
10 
11 #ifdef ERR
12 # undef ERR
13 #endif
14 #define ERR(...) EINA_LOG_DOM_ERR(_evas_filter_log_dom, __VA_ARGS__)
15 #ifdef INF
16 # undef INF
17 #endif
18 #define INF(...) EINA_LOG_DOM_INFO(_evas_filter_log_dom, __VA_ARGS__)
19 #ifdef WRN
20 # undef WRN
21 #endif
22 #define WRN(...) EINA_LOG_DOM_WARN(_evas_filter_log_dom, __VA_ARGS__)
23 #ifdef CRI
24 # undef CRI
25 #endif
26 #define CRI(...) EINA_LOG_DOM_CRIT(_evas_filter_log_dom, __VA_ARGS__)
27 #ifdef DBG
28 # undef DBG
29 #endif
30 #define DBG(...) EINA_LOG_DOM_DBG(_evas_filter_log_dom, __VA_ARGS__)
31 
32 #ifdef FILTERS_DEBUG
33 # define XDBG(...) DBG(__VA_ARGS__)
34 #else
35 # define XDBG(...) do {} while (0)
36 #endif
37 
38 // This is a potential optimization.
39 #define DIV_USING_BITSHIFT 1
40 
41 #ifdef LITTLE_ENDIAN
42 #define ALPHA 3
43 #define RGB0 0
44 #define RGB3 3
45 #define RED 2
46 #define GREEN 1
47 #define BLUE 0
48 #else
49 #define ALPHA 0
50 #define RGB0 1
51 #define RGB3 4
52 #define RED 0
53 #define GREEN 1
54 #define BLUE 2
55 #endif
56 
57 // RGBA = (((a) << 24) + ((r) << 16) + ((g) << 8) + (b))
58 #define ALPHA_OF(a) ((a) >> 24)
59 #define RED_OF(a)   (((a) >> 16) & 0xff)
60 #define GREEN_OF(a) (((a) >> 8) & 0xff)
61 #define BLUE_OF(a)  ((a) & 0xff)
62 
63 // Enable debug if you're working on optimizations
64 #define DEBUG_TIME 1
65 
66 // Windows build will break if CLOCK_MONOTONIC is used
67 #if !defined(_POSIX_MONOTONIC_CLOCK) || (_POSIX_MONOTONIC_CLOCK < 0)
68 # undef DEBUG_TIME
69 # define DEBUG_TIME 0
70 #endif
71 
72 // The 'restrict' keyword is part of C99
73 #if __STDC_VERSION__ < 199901L
74 # define restrict
75 #endif
76 
77 // Helpers
78 #undef ENFN
79 #undef ENC
80 #define ENFN ctx->evas->engine.func
81 #define ENC _evas_engine_context(ctx->evas)
82 
83 #define CMD_ENC _evas_engine_context(cmd->ctx->evas)
84 #define FB_ENC _evas_engine_context(fb->ctx->evas)
85 
86 #define BUFFERS_LOCK() do { if (cmd->input) cmd->input->locked = 1; if (cmd->output) cmd->output->locked = 1; if (cmd->mask) cmd->mask->locked = 1; } while (0)
87 #define BUFFERS_UNLOCK() do { if (cmd->input) cmd->input->locked = 0; if (cmd->output) cmd->output->locked = 0; if (cmd->mask) cmd->mask->locked = 0; } while (0)
88 
89 #if DEBUG_TIME
90 # define DEBUG_TIME_BEGIN() \
91    struct timespec ts1, ts2; \
92    clock_gettime(CLOCK_MONOTONIC, &ts1);
93 # define DEBUG_TIME_END() \
94    clock_gettime(CLOCK_MONOTONIC, &ts2); \
95    long long int t = 1000000LL * (ts2.tv_sec - ts1.tv_sec) \
96    + (ts2.tv_nsec - ts1.tv_nsec) / 1000LL; (void) t; \
97    XDBG("TIME SPENT: %lldus", t);
98 #else
99 # define DEBUG_TIME_BEGIN() do {} while(0)
100 # define DEBUG_TIME_END() do {} while(0)
101 #endif
102 
103 #if DIV_USING_BITSHIFT
104 # define DEFINE_DIVIDER(div) const int pow2 = evas_filter_smallest_pow2_larger_than((div) << 10); const int numerator = (1 << pow2) / (div);
105 # define DIVIDE(val) (((val) * numerator) >> pow2)
106 #else
107 # define DEFINE_DIVIDER(div) const int divider = (div);
108 # define DIVIDE(val) ((val) / divider)
109 #endif
110 
111 typedef enum _Evas_Filter_Interpolation_Mode Evas_Filter_Interpolation_Mode;
112 
113 typedef Evas_Filter_Buffer * (*evas_filter_buffer_scaled_get_func)(Evas_Filter_Context *ctx, Evas_Filter_Buffer *src, unsigned w, unsigned h);
114 
115 
116 struct _Evas_Filter_Context
117 {
118    Evas_Public_Data *evas;
119    Eina_Inlist *commands;
120    Eina_List *buffers; // Evas_Filter_Buffer *
121    int last_buffer_id;
122    int last_command_id;
123    void *user_data; // used by textblock
124 
125    // ugly hack (dlsym fail)
126    evas_filter_buffer_scaled_get_func buffer_scaled_get;
127 
128    // Variables changing at each run
129    int x, y; // Position of the object (for GL downscaling of snapshots)
130    int w, h; // Dimensions of the input/output buffers
131 
132    struct {
133       // Padding in the current input/output buffers
134       Evas_Filter_Padding calculated, final;
135    } pad;
136 
137    struct {
138       // Useless region: obscured by other objects
139       Eina_Rectangle real, effective;
140    } obscured;
141 
142    struct
143    {
144       /** Post-processing callback. The context can be safely destroyed here. */
145       Evas_Filter_Cb cb;
146       void *data;
147    } post_run;
148 
149    struct
150    {
151       void *surface;
152       int x, y;
153       int cx, cy, cw, ch; // clip
154       int r, g, b, a; // clip color
155       void *mask; // mask
156       int mask_x, mask_y; // mask offset
157       Evas_Render_Op rop;
158       RGBA_Map *map;
159       Eina_Bool clip_use : 1;
160       Eina_Bool color_use : 1;
161    } target;
162 
163    short        run_count;
164    short        refcount;
165 
166    Eina_Bool running : 1;
167    Eina_Bool async : 1;
168    Eina_Bool has_proxies : 1;
169    Eina_Bool gl : 1;
170 
171 };
172 
173 struct _Evas_Filter_Command
174 {
175    EINA_INLIST;
176 
177    int id;
178    Evas_Filter_Mode mode;
179    Evas_Filter_Context *ctx;
180 
181    Evas_Filter_Buffer *input;
182    Evas_Filter_Buffer *mask;
183    Evas_Filter_Buffer *output;
184 
185    union
186    {
187       struct
188       {
189          float dx, dy;
190          int count;
191          Evas_Filter_Blur_Type type;
192          Eina_Bool auto_count : 1; // If true, BOX blur will be smooth using
193       } blur;
194 
195       struct
196       {
197          DATA8 *data; // Pointer to 256 char array
198          Evas_Filter_Channel channel;
199       } curve;
200 
201       struct
202       {
203          // mask contains the map data
204          Evas_Filter_Displacement_Flags flags;
205          int intensity; // Max displacement in pixels
206       } displacement;
207 
208       struct
209       {
210          float xyangle; // in degrees: 0-360 (modulo)
211          float zangle;  // degrees: 0-90 (defaults to 0)
212          float specular_factor; // range TBD: 0-...
213          float elevation;
214          DATA32 dark;
215          DATA32 color;
216          DATA32 white;
217          Eina_Bool compensate : 1; // Compensate for darkening
218          //Eina_Bool specular : 1; // Use specular light as well (needs specular_factor > 0)
219       } bump;
220 
221       struct
222       {
223          Evas_Filter_Transform_Flags flags;
224       } transform;
225    };
226 
227    struct {
228       Efl_Gfx_Render_Op rop;
229       int R, G, B, A;
230       int ox, oy;
231       union {
232          struct {
233             int x, y, w, h;
234          };
235          struct {
236             int l, r, t, b;
237          };
238       } clip;
239       struct {
240          int factor_x, factor_y;
241          int pad_x, pad_y;
242          Eina_Bool down;
243       } scale;
244       Evas_Filter_Fill_Mode fillmode;
245       Eina_Bool alphaonly : 1;
246       Eina_Bool clip_use : 1;
247       Eina_Bool clip_mode_lrtb : 1;
248       Eina_Bool need_temp_buffer : 1;
249       Eina_Bool output_was_dirty : 1;
250    } draw;
251 };
252 
253 struct _Evas_Filter_Buffer
254 {
255    EINA_REFCOUNT;
256 
257    int id;
258    Evas_Filter_Context *ctx;
259 
260    Evas_Object *source;
261    Eina_Stringshare *source_name;
262    Ector_Buffer *buffer;
263    int w, h;
264 
265    Eina_Bool used : 1;        // This buffer is in use (useful for reuse of context)
266    Eina_Bool alpha_only : 1;  // 1 channel (A) instead of 4 (RGBA)
267    Eina_Bool transient : 1;   // temporary buffer (automatic allocation)
268    Eina_Bool locked : 1;      // internal flag
269    Eina_Bool dirty : 1;       // Marked as dirty as soon as a command writes to it
270    Eina_Bool is_render : 1;   // Is render target of a filter using engine functions (ie. needs FBO in GL)
271    Eina_Bool cleanup : 1;     // Needs cleaning up if not allocated
272 };
273 
274 enum _Evas_Filter_Interpolation_Mode
275 {
276    EVAS_FILTER_INTERPOLATION_MODE_NONE,
277    EVAS_FILTER_INTERPOLATION_MODE_LINEAR
278 };
279 
280 enum _Evas_Filter_Support
281 {
282    EVAS_FILTER_SUPPORT_NONE = 0,
283    EVAS_FILTER_SUPPORT_CPU,
284    EVAS_FILTER_SUPPORT_GL
285 };
286 
287 void                     evas_filter_mixin_init(void);
288 void                     evas_filter_mixin_shutdown(void);
289 
290 void                     evas_filter_context_clear(Evas_Filter_Context *ctx, Eina_Bool keep_buffers);
291 void                     evas_filter_context_source_set(Evas_Filter_Context *ctx, Evas_Object *eo_proxy, Evas_Object *eo_source, int bufid, Eina_Stringshare *name);
292 
293 /* Utility functions */
294 void _clip_to_target(int *sx, int *sy, int sw, int sh, int ox, int oy, int dw, int dh, int *dx, int *dy, int *rows, int *cols);
295 Eina_Bool evas_filter_buffer_alloc(Evas_Filter_Buffer *fb, int w, int h);
296 Evas_Filter_Buffer *_filter_buffer_get(Evas_Filter_Context *ctx, int bufid);
297 Evas_Filter_Buffer *evas_filter_temporary_buffer_get(Evas_Filter_Context *ctx, int w, int h, Eina_Bool alpha_only, Eina_Bool clean);
298 Evas_Filter_Buffer *evas_filter_buffer_scaled_get(Evas_Filter_Context *ctx, Evas_Filter_Buffer *src, unsigned w, unsigned h);
299 Eina_Bool           evas_filter_interpolate(DATA8* output /* 256 values */, int *points /* 256 values */, Evas_Filter_Interpolation_Mode mode);
300 int evas_filter_smallest_pow2_larger_than(int val);
301 
302 void _evas_filter_context_program_reuse(void *engine, void *output, Evas_Filter_Context *ctx);
303 void evas_filter_parser_shutdown(void);
304 
305 #define E_READ  ECTOR_BUFFER_ACCESS_FLAG_READ
306 #define E_WRITE ECTOR_BUFFER_ACCESS_FLAG_WRITE
307 #define E_ALPHA EFL_GFX_COLORSPACE_GRY8
308 #define E_ARGB  EFL_GFX_COLORSPACE_ARGB8888
309 
310 static inline void *
_buffer_map_all(Ector_Buffer * buf,unsigned int * len,Ector_Buffer_Access_Flag mode,Efl_Gfx_Colorspace cspace,unsigned int * stride)311 _buffer_map_all(Ector_Buffer *buf, unsigned int *len, Ector_Buffer_Access_Flag mode, Efl_Gfx_Colorspace cspace, unsigned int *stride)
312 {
313    void *ret = NULL;
314    int w, h;
315    if (!buf) return NULL;
316    ector_buffer_size_get(buf, &w, &h);
317    ret = ector_buffer_map(buf, len, mode, 0, 0, w, h, cspace, stride);
318    return ret;
319 }
320 
321 #endif // EVAS_FILTER_PRIVATE_H
322