move around - flatter.
[profile/ivi/evas.git] / src / modules / engines / software_x11 / evas_engine.c
1 #include "evas_common.h"
2 #include "evas_private.h"
3 #include "evas_engine.h"
4 #include "Evas_Engine_Software_X11.h"
5
6 /* function tables - filled in later (func and parent func) */
7 static Evas_Func func, pfunc;
8
9 /* engine struct data */
10 typedef struct _Render_Engine Render_Engine;
11
12 struct _Render_Engine
13 {
14    Tilebuf          *tb;
15    Outbuf           *ob;
16    Tilebuf_Rect     *rects;
17    Evas_Object_List *cur_rect;
18    int               end : 1;
19 };
20
21 /* prototypes we will use here */
22 static void *_output_setup(int w, int h, int rot, Display *disp, Drawable draw, Visual *vis, Colormap cmap, int depth, int debug, int grayscale, int max_colors, Pixmap mask, int shape_dither, int destination_alpha);
23 static Visual *_best_visual_get(Display *disp, int screen);
24 static Colormap _best_colormap_get(Display *disp, int screen);
25 static int _best_depth_get(Display *disp, int screen);
26
27 static void *eng_info(Evas *e);
28 static void eng_info_free(Evas *e, void *info);
29 static void eng_setup(Evas *e, void *info);
30 static void eng_output_free(void *data);
31 static void eng_output_resize(void *data, int w, int h);
32 static void eng_output_tile_size_set(void *data, int w, int h);
33 static void eng_output_redraws_rect_add(void *data, int x, int y, int w, int h);
34 static void eng_output_redraws_rect_del(void *data, int x, int y, int w, int h);
35 static void eng_output_redraws_clear(void *data);
36 static void *eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, int *cx, int *cy, int *cw, int *ch);
37 static void eng_output_redraws_next_update_push(void *data, void *surface, int x, int y, int w, int h);
38 static void eng_output_flush(void *data);
39 static void eng_output_idle_flush(void *data);
40
41 /* internal engine routines */
42 static void *
43 _output_setup(int w, int h, int rot, Display *disp, Drawable draw, Visual *vis, Colormap cmap, int depth, int debug, int grayscale, int max_colors, Pixmap mask, int shape_dither, int destination_alpha)
44 {
45    Render_Engine *re;
46
47    re = calloc(1, sizeof(Render_Engine));
48    /* if we haven't initialized - init (automatic abort if already done) */
49    evas_common_cpu_init();
50
51    evas_common_blend_init();
52    evas_common_image_init();
53    evas_common_convert_init();
54    evas_common_scale_init();
55    evas_common_rectangle_init();
56    evas_common_gradient_init();
57    evas_common_polygon_init();
58    evas_common_line_init();
59    evas_common_font_init();
60    evas_common_draw_init();
61    evas_common_tilebuf_init();
62
63    evas_software_x11_x_init();
64    evas_software_x11_x_color_init();
65    evas_software_x11_outbuf_init();
66
67    re->ob = evas_software_x11_outbuf_setup_x(w, h, rot, OUTBUF_DEPTH_INHERIT,
68                                              disp, draw, vis, cmap, depth,
69                                              grayscale, max_colors, mask,
70                                              shape_dither, destination_alpha);
71    if (!re->ob)
72      {
73         free(re);
74         return NULL;
75      }
76    
77    /* for updates return 1 big buffer, but only use portions of it, also cache
78     it and keepit around until an idle_flush */
79    /* disable for now - i am hunting down why some expedite tests are slower,
80     * as well as shaped stuff is broken and probable non-32bpp is broken as
81     * convert funcs dont do the right thing
82     *
83    re->ob->onebuf = 1;
84     */
85    
86    evas_software_x11_outbuf_debug_set(re->ob, debug);
87    re->tb = evas_common_tilebuf_new(w, h);
88    if (!re->tb)
89      {
90         evas_software_x11_outbuf_free(re->ob);
91         free(re);
92         return NULL;
93      }
94    /* in preliminary tests 16x16 gave highest framerates */
95    evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
96    return re;
97 }
98
99 static Visual *
100 _best_visual_get(Display *disp, int screen)
101 {
102    if (!disp) return NULL;
103    return DefaultVisual(disp, screen);
104 }
105
106 static Colormap
107 _best_colormap_get(Display *disp, int screen)
108 {
109    if (!disp) return 0;
110    return DefaultColormap(disp, screen);
111 }
112
113 static int
114 _best_depth_get(Display *disp, int screen)
115 {
116    if (!disp) return 0;
117    return DefaultDepth(disp, screen);
118 }
119
120 /* engine api this module provides */
121 static void *
122 eng_info(Evas *e)
123 {
124    Evas_Engine_Info_Software_X11 *info;
125
126    info = calloc(1, sizeof(Evas_Engine_Info_Software_X11));
127    if (!info) return NULL;
128    info->magic.magic = rand();
129    info->info.debug = 0;
130    info->info.alloc_grayscale = 0;
131    info->info.alloc_colors_max = 216;
132    info->func.best_visual_get = _best_visual_get;
133    info->func.best_colormap_get = _best_colormap_get;
134    info->func.best_depth_get = _best_depth_get;
135    return info;
136    e = NULL;
137 }
138
139 static void
140 eng_info_free(Evas *e, void *info)
141 {
142    Evas_Engine_Info_Software_X11 *in;
143
144    in = (Evas_Engine_Info_Software_X11 *)info;
145    free(in);
146 }
147
148 static void
149 eng_setup(Evas *e, void *in)
150 {
151    Render_Engine *re;
152    Evas_Engine_Info_Software_X11 *info;
153
154    info = (Evas_Engine_Info_Software_X11 *)in;
155    if (!e->engine.data.output)
156      e->engine.data.output =
157      _output_setup(e->output.w,
158                    e->output.h,
159                    info->info.rotation,
160                    info->info.display,
161                    info->info.drawable,
162                    info->info.visual,
163                    info->info.colormap,
164                    info->info.depth,
165                    info->info.debug,
166                    info->info.alloc_grayscale,
167                    info->info.alloc_colors_max,
168                    info->info.mask,
169                    info->info.shape_dither,
170                    info->info.destination_alpha);
171    else
172      {
173         int ponebuf = 0;
174         
175         re = e->engine.data.output;
176         ponebuf = re->ob->onebuf;
177         evas_software_x11_outbuf_free(re->ob);
178         re->ob = evas_software_x11_outbuf_setup_x(e->output.w,
179                                                   e->output.h,
180                                                   info->info.rotation,
181                                                   OUTBUF_DEPTH_INHERIT,
182                                                   info->info.display,
183                                                   info->info.drawable,
184                                                   info->info.visual,
185                                                   info->info.colormap,
186                                                   info->info.depth,
187                                                   info->info.alloc_grayscale,
188                                                   info->info.alloc_colors_max,
189                                                   info->info.mask,
190                                                   info->info.shape_dither,
191                                                   info->info.destination_alpha);
192         evas_software_x11_outbuf_debug_set(re->ob, info->info.debug);
193         re->ob->onebuf = ponebuf;
194      }
195    if (!e->engine.data.output) return;
196    if (!e->engine.data.context)
197      e->engine.data.context =
198      e->engine.func->context_new(e->engine.data.output);
199
200    re = e->engine.data.output;
201    evas_software_x11_outbuf_drawable_set(re->ob, info->info.drawable);
202    evas_software_x11_outbuf_mask_set(re->ob, info->info.mask);
203    evas_software_x11_outbuf_rotation_set(re->ob, info->info.rotation);
204 }
205
206 static void
207 eng_output_free(void *data)
208 {
209    Render_Engine *re;
210
211    if (!data) return;
212
213    re = (Render_Engine *)data;
214    evas_software_x11_outbuf_free(re->ob);
215    evas_common_tilebuf_free(re->tb);
216    if (re->rects) evas_common_tilebuf_free_render_rects(re->rects);
217    free(re);
218
219    evas_common_font_shutdown();
220    evas_common_image_shutdown();
221 }
222
223 static void
224 eng_output_resize(void *data, int w, int h)
225 {
226    Render_Engine *re;
227
228    re = (Render_Engine *)data;
229    evas_software_x11_outbuf_reconfigure(re->ob, w, h,
230                                    evas_software_x11_outbuf_get_rot(re->ob),
231                                    OUTBUF_DEPTH_INHERIT);
232    evas_common_tilebuf_free(re->tb);
233    re->tb = evas_common_tilebuf_new(w, h);
234    if (re->tb)
235      evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
236 }
237
238 static void
239 eng_output_tile_size_set(void *data, int w, int h)
240 {
241    Render_Engine *re;
242
243    re = (Render_Engine *)data;
244    evas_common_tilebuf_set_tile_size(re->tb, w, h);
245 }
246
247 static void
248 eng_output_redraws_rect_add(void *data, int x, int y, int w, int h)
249 {
250    Render_Engine *re;
251
252    re = (Render_Engine *)data;
253    evas_common_tilebuf_add_redraw(re->tb, x, y, w, h);
254 }
255
256 static void
257 eng_output_redraws_rect_del(void *data, int x, int y, int w, int h)
258 {
259    Render_Engine *re;
260
261    re = (Render_Engine *)data;
262    evas_common_tilebuf_del_redraw(re->tb, x, y, w, h);
263 }
264
265 static void
266 eng_output_redraws_clear(void *data)
267 {
268    Render_Engine *re;
269
270    re = (Render_Engine *)data;
271    evas_common_tilebuf_clear(re->tb);
272 }
273
274 static void *
275 eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, int *cx, int *cy, int *cw, int *ch)
276 {
277    Render_Engine *re;
278    RGBA_Image *surface;
279    Tilebuf_Rect *rect;
280    int ux, uy, uw, uh;
281
282    re = (Render_Engine *)data;
283    if (re->end)
284      {
285         re->end = 0;
286         return NULL;
287      }
288    if (!re->rects)
289      {
290         re->rects = evas_common_tilebuf_get_render_rects(re->tb);
291         re->cur_rect = (Evas_Object_List *)re->rects;
292      }
293    if (!re->cur_rect) return NULL;
294    rect = (Tilebuf_Rect *)re->cur_rect;
295    ux = rect->x; uy = rect->y; uw = rect->w; uh = rect->h;
296    re->cur_rect = re->cur_rect->next;
297    if (!re->cur_rect)
298      {
299         evas_common_tilebuf_free_render_rects(re->rects);
300         re->rects = NULL;
301         re->end = 1;
302      }
303
304    surface = evas_software_x11_outbuf_new_region_for_update
305      (re->ob, ux, uy, uw, uh, cx, cy, cw, ch);
306    *x = ux; *y = uy; *w = uw; *h = uh;
307    return surface;
308 }
309
310 static void
311 eng_output_redraws_next_update_push(void *data, void *surface, int x, int y, int w, int h)
312 {
313    Render_Engine *re;
314
315    re = (Render_Engine *)data;
316    evas_common_pipe_begin(surface);
317    evas_common_pipe_flush(surface);
318    evas_software_x11_outbuf_push_updated_region(re->ob, surface, x, y, w, h);
319    evas_software_x11_outbuf_free_region_for_update(re->ob, surface);
320    evas_common_cpu_end_opt();
321 }
322
323 static void
324 eng_output_flush(void *data)
325 {
326    Render_Engine *re;
327
328    re = (Render_Engine *)data;
329    evas_software_x11_outbuf_flush(re->ob);
330 }
331
332 static void
333 eng_output_idle_flush(void *data)
334 {
335    Render_Engine *re;
336
337    re = (Render_Engine *)data;
338    evas_software_x11_outbuf_idle_flush(re->ob);
339 }
340
341
342 /* module advertising code */
343 EAPI int
344 module_open(Evas_Module *em)
345 {
346    if (!em) return 0;
347    /* get whatever engine module we inherit from */
348    if (!_evas_module_engine_inherit(&pfunc, "software_generic")) return 0;
349    /* store it for later use */
350    func = pfunc;
351    /* now to override methods */
352 #define ORD(f) EVAS_API_OVERRIDE(f, &func, eng_)
353    ORD(info);
354    ORD(info_free);
355    ORD(setup);
356    ORD(output_free);
357    ORD(output_resize);
358    ORD(output_tile_size_set);
359    ORD(output_redraws_rect_add);
360    ORD(output_redraws_rect_del);
361    ORD(output_redraws_clear);
362    ORD(output_redraws_next_update_get);
363    ORD(output_redraws_next_update_push);
364    ORD(output_flush);
365    ORD(output_idle_flush);
366    /* now advertise out own api */
367    em->functions = (void *)(&func);
368    return 1;
369 }
370
371 EAPI void
372 module_close(void)
373 {
374 }
375
376 EAPI Evas_Module_Api evas_modapi = 
377 {
378    EVAS_MODULE_API_VERSION, 
379      EVAS_MODULE_TYPE_ENGINE,
380      "software_x11",
381      "none"
382 };