svn update: 48958 (latest:48959)
[framework/uifw/ecore.git] / src / lib / ecore_evas / ecore_evas_sdl.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4
5 #ifdef HAVE_CONFIG_H
6 # include <config.h>
7 #endif
8
9 #include <Ecore.h>
10 #include <Ecore_Input.h>
11 #include <Ecore_Input_Evas.h>
12 #if defined(BUILD_ECORE_EVAS_SOFTWARE_SDL) || defined(BUILD_ECORE_EVAS_OPENGL_SDL)
13 # include <Ecore_Sdl.h>
14 # ifdef BUILD_ECORE_EVAS_SOFTWARE_SDL
15 #  include <Evas_Engine_SDL.h>
16 # endif
17 # ifdef BUILD_ECORE_EVAS_OPENGL_SDL
18 #  include <Evas_Engine_GL_SDL.h>
19 # endif
20 #endif
21
22 #include "ecore_evas_private.h"
23 #include "Ecore_Evas.h"
24
25 // fixme: 1 sdl window only at a time? seems wrong
26
27 #if defined(BUILD_ECORE_EVAS_SOFTWARE_SDL) || defined(BUILD_ECORE_EVAS_OPENGL_SDL)
28
29 /* static char *ecore_evas_default_display = "0"; */
30 /* static Ecore_List *ecore_evas_input_devices = NULL; */
31
32 static int                      _ecore_evas_init_count = 0;
33
34 static Ecore_Evas               *sdl_ee = NULL;
35 static Ecore_Event_Handler      *ecore_evas_event_handlers[4] = {
36    NULL, NULL, NULL, NULL
37 };
38
39 static const char               *ecore_evas_sdl_default = "EFL SDL";
40 static int                      _ecore_evas_fps_debug = 0;
41 static Ecore_Poller             *ecore_evas_event;
42 static Ecore_Evas               *ecore_evases = NULL;
43
44 static Ecore_Evas *
45 _ecore_evas_sdl_match(void)
46 {
47    return sdl_ee;
48 }
49
50 static int
51 _ecore_evas_sdl_event_got_focus(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
52 {
53    Ecore_Evas                   *ee;
54
55    ee = _ecore_evas_sdl_match();
56
57    if (!ee) return 1;
58    /* pass on event */
59    ee->prop.focused = 1;
60
61    return 0;
62 }
63
64 static int
65 _ecore_evas_sdl_event_lost_focus(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
66 {
67    Ecore_Evas                   *ee;
68
69    ee = _ecore_evas_sdl_match();
70
71    if (!ee) return 1;
72    /* pass on event */
73    ee->prop.focused = 0;
74
75    return 0;
76 }
77
78 static int
79 _ecore_evas_sdl_event_video_resize(void *data __UNUSED__, int type __UNUSED__, void *event)
80 {
81    Ecore_Sdl_Event_Video_Resize *e;
82    Ecore_Evas                   *ee;
83
84    e = event;
85    ee = _ecore_evas_sdl_match();
86
87    if (!ee) return 1; /* pass on event */
88    evas_output_size_set(ee->evas, e->w, e->h);
89
90    return 0;
91 }
92
93 static int
94 _ecore_evas_sdl_event_video_expose(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
95 {
96    Ecore_Evas                   *ee;
97    int                          w;
98    int                          h;
99
100    ee = _ecore_evas_sdl_match();
101
102    if (!ee) return 1;
103    evas_output_size_get(ee->evas, &w, &h);
104    evas_damage_rectangle_add(ee->evas, 0, 0, w, h);
105
106    return 0;
107 }
108
109 static int
110 _ecore_evas_render(Ecore_Evas *ee)
111 {
112    Eina_List *updates;
113
114    updates = evas_render_updates(ee->evas);
115    if (updates)
116      {
117         evas_render_updates_free(updates);
118         _ecore_evas_idle_timeout_update(ee);
119      }
120    return updates ? 1 : 0;
121 }
122
123 static int
124 _ecore_evas_sdl_render(Ecore_Evas *ee)
125 {
126    int rend = 0;
127
128 #ifdef BUILD_ECORE_EVAS_SOFTWARE_BUFFER
129    Eina_List *ll;
130    Ecore_Evas *ee2;
131
132    EINA_LIST_FOREACH(ee->sub_ecore_evas, ll, ee2)
133      {
134         if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2);
135         rend |= _ecore_evas_buffer_render(ee2);
136         if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2);
137      }
138 #endif
139
140    if (ee->func.fn_pre_render) ee->func.fn_pre_render(ee);
141
142    if (ee->prop.avoid_damage) rend = _ecore_evas_render(ee);
143    else if ((ee->visible) ||
144             ((ee->should_be_visible) && (ee->prop.fullscreen)) ||
145             ((ee->should_be_visible) && (ee->prop.override)))
146      rend |= _ecore_evas_render(ee);
147    else
148      evas_norender(ee->evas);
149
150    if (ee->func.fn_post_render) ee->func.fn_post_render(ee);
151    return rend;
152 }
153
154 static int
155 _ecore_evas_sdl_event(void *data __UNUSED__)
156 {
157    ecore_sdl_feed_events();
158    return 1;
159 }
160
161 static int
162 _ecore_evas_sdl_init(int w __UNUSED__, int h __UNUSED__)
163 {
164    _ecore_evas_init_count++;
165    if (_ecore_evas_init_count > 1) return _ecore_evas_init_count;
166
167 #ifndef _WIN32
168    if (getenv("ECORE_EVAS_FPS_DEBUG")) _ecore_evas_fps_debug = 1;
169 #endif /* _WIN32 */
170    // this is pretty bad: poller? and set poll time? pol time is meant to be 
171    // adjustable for things like polling battery state, or amoutn of spare
172    // memory etc.
173    // 
174    ecore_evas_event = ecore_poller_add(ECORE_POLLER_CORE, 1, _ecore_evas_sdl_event, NULL);
175    ecore_poller_poll_interval_set(ECORE_POLLER_CORE, 0.006);
176 #ifndef _WIN32
177    if (_ecore_evas_fps_debug) _ecore_evas_fps_debug_init();
178 #endif /* _WIN32 */
179
180    ecore_event_evas_init();
181
182    ecore_evas_event_handlers[0] = ecore_event_handler_add(ECORE_SDL_EVENT_GOT_FOCUS, _ecore_evas_sdl_event_got_focus, NULL);
183    ecore_evas_event_handlers[1] = ecore_event_handler_add(ECORE_SDL_EVENT_LOST_FOCUS, _ecore_evas_sdl_event_lost_focus, NULL);
184    ecore_evas_event_handlers[2] = ecore_event_handler_add(ECORE_SDL_EVENT_RESIZE, _ecore_evas_sdl_event_video_resize, NULL);
185    ecore_evas_event_handlers[3] = ecore_event_handler_add(ECORE_SDL_EVENT_EXPOSE, _ecore_evas_sdl_event_video_expose, NULL);
186
187    return _ecore_evas_init_count;
188 }
189
190 static int
191 _ecore_evas_sdl_shutdown(void)
192 {
193    _ecore_evas_init_count--;
194    if (_ecore_evas_init_count == 0)
195      {
196         int i;
197
198         for (i = 0; i < sizeof (ecore_evas_event_handlers) / sizeof (Ecore_Event_Handler*); i++)
199           ecore_event_handler_del(ecore_evas_event_handlers[i]);
200         ecore_event_evas_shutdown();
201         ecore_poller_del(ecore_evas_event);
202         ecore_evas_event = NULL;
203 #ifndef _WIN32
204         if (_ecore_evas_fps_debug) _ecore_evas_fps_debug_shutdown();
205 #endif /* _WIN32 */
206      }
207    if (_ecore_evas_init_count < 0) _ecore_evas_init_count = 0;
208    return _ecore_evas_init_count;
209 }
210
211 static void
212 _ecore_evas_sdl_free(Ecore_Evas *ee)
213 {
214    if (sdl_ee == ee) sdl_ee = NULL;
215    
216    ecore_event_window_unregister(0);
217    _ecore_evas_sdl_shutdown();
218    ecore_sdl_shutdown();
219 }
220
221 static void
222 _ecore_evas_resize(Ecore_Evas *ee, int w, int h)
223 {
224    if ((w == ee->w) && (h == ee->h)) return;
225    ee->w = w;
226    ee->h = h;
227
228    evas_output_size_set(ee->evas, ee->w, ee->h);
229    evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
230    evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
231
232    if (ee->func.fn_resize) ee->func.fn_resize(ee);
233 }
234
235 static void
236 _ecore_evas_move_resize(Ecore_Evas *ee, int x __UNUSED__, int y __UNUSED__, int w, int h)
237 {
238    if ((w == ee->w) && (h == ee->h)) return;
239    ee->w = w;
240    ee->h = h;
241
242    evas_output_size_set(ee->evas, ee->w, ee->h);
243    evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
244    evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
245
246    if (ee->func.fn_resize) ee->func.fn_resize(ee);
247 }
248
249 static void
250 _ecore_evas_object_cursor_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
251 {
252    Ecore_Evas *ee;
253
254    ee = data;
255    if (ee)
256      ee->prop.cursor.object = NULL;
257 }
258
259 static void
260 _ecore_evas_object_cursor_set(Ecore_Evas *ee, Evas_Object *obj, int layer, int hot_x, int hot_y)
261 {
262    int x, y;
263
264    if (ee->prop.cursor.object) evas_object_del(ee->prop.cursor.object);
265
266    if (obj == NULL)
267      {
268         ee->prop.cursor.object = NULL;
269         ee->prop.cursor.layer = 0;
270         ee->prop.cursor.hot.x = 0;
271         ee->prop.cursor.hot.y = 0;
272         return;
273      }
274
275    ee->prop.cursor.object = obj;
276    ee->prop.cursor.layer = layer;
277    ee->prop.cursor.hot.x = hot_x;
278    ee->prop.cursor.hot.y = hot_y;
279    evas_pointer_output_xy_get(ee->evas, &x, &y);
280    evas_object_layer_set(ee->prop.cursor.object, ee->prop.cursor.layer);
281    evas_object_move(ee->prop.cursor.object,
282                     x - ee->prop.cursor.hot.x,
283                     y - ee->prop.cursor.hot.y);
284    evas_object_pass_events_set(ee->prop.cursor.object, 1);
285    if (evas_pointer_inside_get(ee->evas))
286      evas_object_show(ee->prop.cursor.object);
287
288    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _ecore_evas_object_cursor_del, ee);
289 }
290
291 static Ecore_Evas_Engine_Func _ecore_sdl_engine_func =
292 {
293    _ecore_evas_sdl_free,
294    NULL,
295    NULL,
296    NULL,
297    NULL,
298    NULL,
299    NULL,
300    NULL,
301    NULL,
302    NULL,
303    NULL,
304    NULL,
305    NULL,
306    NULL,
307    NULL,
308    NULL,
309    NULL,
310    _ecore_evas_resize,
311    _ecore_evas_move_resize,
312    NULL,
313    NULL,
314    NULL,
315    NULL,
316    NULL,
317    NULL,
318    NULL,
319    NULL,
320    NULL,
321    NULL,
322    NULL,
323    NULL,
324    NULL,
325    _ecore_evas_object_cursor_set,
326    NULL,
327    NULL,
328    NULL,
329    NULL,
330    NULL,
331    NULL,
332    NULL,
333    NULL,
334    NULL,
335    NULL,
336    NULL,
337    NULL,
338    NULL, //transparent
339      
340      NULL // render
341 };
342
343 static Ecore_Evas*
344 _ecore_evas_internal_sdl_new(int rmethod, const char* name, int w, int h, int fullscreen, int hwsurface, int noframe, int alpha)
345 {
346    void                 *einfo;
347    Ecore_Evas           *ee;
348
349    if (!name)
350      name = ecore_evas_sdl_default;
351
352    if (ecore_evases) return NULL;
353
354    ee = calloc(1, sizeof(Ecore_Evas));
355    if (!ee) return NULL;
356
357    ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
358
359    ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_sdl_engine_func;
360
361    ee->driver = "sdl";
362    if (name) ee->name = strdup(name);
363
364    if (w < 1) w = 1;
365    if (h < 1) h = 1;
366    ee->visible = 1;
367    ee->w = w;
368    ee->h = h;
369
370    ee->prop.max.w = 0;
371    ee->prop.max.h = 0;
372    ee->prop.layer = 0;
373    ee->prop.focused = 1;
374    ee->prop.borderless = 1;
375    ee->prop.override = 1;
376    ee->prop.maximized = 1;
377    ee->prop.fullscreen = fullscreen;
378    ee->prop.withdrawn = 0;
379    ee->prop.sticky = 0;
380    ee->prop.window = 0;
381
382    /* init evas here */
383    ee->evas = evas_new();
384    evas_data_attach_set(ee->evas, ee);
385    evas_output_method_set(ee->evas, rmethod);
386
387    evas_output_size_set(ee->evas, w, h);
388    evas_output_viewport_set(ee->evas, 0, 0, w, h);
389
390    if (rmethod == evas_render_method_lookup("software_sdl"))
391      {
392 #ifdef BUILD_ECORE_EVAS_SOFTWARE_SDL
393         einfo = evas_engine_info_get(ee->evas);
394         if (einfo)
395           {
396              ((Evas_Engine_Info_SDL *)einfo)->info.rotation = 0;
397              ((Evas_Engine_Info_SDL *)einfo)->info.fullscreen = fullscreen;
398              ((Evas_Engine_Info_SDL *)einfo)->info.hwsurface = hwsurface;
399              ((Evas_Engine_Info_SDL *)einfo)->info.noframe = noframe;
400              ((Evas_Engine_Info_SDL *)einfo)->info.alpha = alpha;
401              evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
402           }
403 #endif
404      }
405    else if (rmethod == evas_render_method_lookup("gl_sdl"))
406      {
407 #ifdef BUILD_ECORE_EVAS_OPENGL_SDL
408         einfo = evas_engine_info_get(ee->evas);
409         if (einfo)
410           {
411              ((Evas_Engine_Info_GL_SDL *)einfo)->flags.fullscreen = fullscreen;
412              ((Evas_Engine_Info_GL_SDL *)einfo)->flags.noframe = noframe;
413              evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
414           }
415 #endif
416      }
417
418    if (!ecore_sdl_init(name))
419      {
420         evas_free(ee->evas);
421         if (ee->name) free(ee->name);
422         free(ee);
423         return NULL;
424      }
425
426    _ecore_evas_sdl_init(w, h);
427
428    ecore_event_window_register(0, ee, ee->evas, (Ecore_Event_Mouse_Move_Cb) _ecore_evas_mouse_move_process);
429
430    SDL_ShowCursor(SDL_DISABLE);
431
432    ee->engine.func->fn_render = _ecore_evas_sdl_render;
433    _ecore_evas_register(ee);
434    
435    sdl_ee = ee;
436    
437    evas_event_feed_mouse_in(ee->evas, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff), NULL);
438    evas_focus_in(ee->evas);
439
440    return ee;
441 }
442 #endif
443
444 #ifdef BUILD_ECORE_EVAS_SOFTWARE_SDL
445 EAPI Ecore_Evas*
446 ecore_evas_sdl_new(const char* name, int w, int h, int fullscreen, int hwsurface, int noframe, int alpha)
447 {
448    Ecore_Evas          *ee;
449    int                  rmethod;
450
451    rmethod = evas_render_method_lookup("software_sdl");
452    if (!rmethod) return NULL;
453
454    ee = _ecore_evas_internal_sdl_new(rmethod, name, w, h, fullscreen, hwsurface, noframe, alpha);
455    ee->driver = "sdl";
456    return ee;
457 }
458 #else
459 EAPI Ecore_Evas*
460 ecore_evas_sdl_new(const char* name __UNUSED__, int w __UNUSED__, int h __UNUSED__, int fullscreen __UNUSED__, int hwsurface __UNUSED__, int noframe __UNUSED__, int alpha __UNUSED__)
461 {
462    ERR("OUTCH !");
463    return NULL;
464 }
465 #endif
466
467 #ifdef BUILD_ECORE_EVAS_SOFTWARE_SDL
468 EAPI Ecore_Evas*
469 ecore_evas_sdl16_new(const char* name, int w, int h, int fullscreen, int hwsurface, int noframe, int alpha)
470 {
471    Ecore_Evas          *ee;
472    int                  rmethod;
473
474    rmethod = evas_render_method_lookup("software_16_sdl");
475    if (!rmethod) return NULL;
476
477    ee = _ecore_evas_internal_sdl_new(rmethod, name, w, h, fullscreen, hwsurface, noframe, alpha);
478    ee->driver = "software_16_sdl";
479    return ee;
480 }
481 #else
482 EAPI Ecore_Evas*
483 ecore_evas_sdl16_new(const char* name __UNUSED__, int w __UNUSED__, int h __UNUSED__, int fullscreen __UNUSED__, int hwsurface __UNUSED__, int noframe __UNUSED__, int alpha __UNUSED__)
484 {
485    ERR("OUTCH !");
486    return NULL;
487 }
488 #endif
489
490 #ifdef BUILD_ECORE_EVAS_OPENGL_SDL
491 EAPI Ecore_Evas*
492 ecore_evas_gl_sdl_new(const char* name, int w, int h, int fullscreen, int noframe)
493 {
494    Ecore_Evas          *ee;
495    int                  rmethod;
496
497    rmethod = evas_render_method_lookup("gl_sdl");
498    if (!rmethod) return NULL;
499
500    ee = _ecore_evas_internal_sdl_new(rmethod, name, w, h, fullscreen, 0, noframe, 0);
501    ee->driver = "gl_sdl";
502    return ee;
503 }
504 #else
505 EAPI Ecore_Evas*
506 ecore_evas_gl_sdl_new(const char* name __UNUSED__, int w __UNUSED__, int h __UNUSED__, int fullscreen __UNUSED__, int noframe __UNUSED__)
507 {
508    ERR("OUTCH !");
509    return NULL;
510 }
511 #endif
512