tizen 2.4 release
[framework/uifw/e17-mod-tizen-comp.git] / src / e_mod_comp_canvas.c
1 #include "e_mod_comp_shared_types.h"
2 #include "e_mod_comp_debug.h"
3 #include "e_mod_comp.h"
4
5 /* static global variables */
6 static int _canvas_num = 0;
7
8 /* local subsystem functions */
9 static void      _fps_update(E_Comp_Canvas *canvas);
10 static void      _pre_swap(void *data, Evas *e, void *event_info);
11 static void      _post_swap(void *data, Evas *e, void *event_info);
12 static Eina_Bool _nocomp_prepare_timeout(void *data);
13 #if USE_NOCOMP_DISPOSE
14 static Eina_Bool _nocomp_end_timeout(void *data);
15 #endif
16
17 /* externally accessible functions */
18 EAPI void
19 e_mod_comp_layer_eval(E_Comp_Layer *ly)
20 {
21    e_layout_freeze(ly->layout);
22
23    if (!ly->bg)
24      {
25         ly->bg = evas_object_rectangle_add(ly->canvas->evas);
26         /* TODO: make it configurable */
27         if (!strncmp(ly->name, "move", strlen("move")))
28           evas_object_color_set(ly->bg, 0, 0, 0, 0);
29         else if (!strncmp(ly->name, "ly-ctrl", strlen("ly-ctrl")))
30 #if 0
31           evas_object_color_set(ly->bg, 0, 255, 0, 80);
32 #else
33           evas_object_color_set(ly->bg, 0, 0, 0, 0);
34 #endif
35         else
36           evas_object_color_set(ly->bg, 0, 0, 0, 255);
37         evas_object_show(ly->bg);
38         e_layout_pack(ly->layout, ly->bg);
39      }
40    e_layout_child_move(ly->bg, ly->x, ly->y);
41    e_layout_child_resize(ly->bg, ly->w, ly->h);
42    e_layout_child_lower(ly->bg);
43
44    evas_object_move(ly->layout, ly->x, ly->y);
45    evas_object_resize(ly->layout, ly->w, ly->h);
46    e_layout_virtual_size_set(ly->layout, ly->w, ly->h);
47
48    e_layout_thaw(ly->layout);
49 }
50
51 EAPI void
52 e_mod_comp_layer_populate(E_Comp_Layer *ly,
53                           Evas_Object  *o)
54 {
55    e_layout_pack(ly->layout, o);
56 }
57
58 EAPI void
59 e_mod_comp_layer_populate_above_normal(E_Comp_Layer *ly,
60                                        Evas_Object  *o)
61 {
62    E_Comp_Win *cw;
63    Eina_List *l;
64    E_Comp_Object *co;
65
66    if (!((ly) &&
67          (ly->canvas) &&
68          (ly->canvas->zone) &&
69          (ly->canvas->zone->container)))
70      {
71         return;
72      }
73
74    /* try to look for the boundary of the normal layer in the E_Container */
75    Ecore_X_Window win = ly->canvas->zone->container->layers[3].win;
76    if (!win) return;
77
78    E_Comp *c = e_mod_comp_util_get();
79    Eina_Bool found = EINA_FALSE;
80    EINA_INLIST_REVERSE_FOREACH(c->wins, cw)
81      {
82         if (cw->win == win)
83           {
84              found = EINA_TRUE;
85              break;
86           }
87      }
88
89    if (found)
90      {
91         EINA_LIST_FOREACH(cw->objs, l, co)
92           {
93              e_layout_child_raise_above(o, co->shadow);
94           }
95      }
96    else
97      e_layout_child_raise(o);
98 }
99
100 EAPI void
101 e_mod_comp_layer_raise_above(E_Comp_Canvas  *canvas,
102                              Evas_Object    *o,
103                              E_Border       *bd)
104 {
105    E_Comp_Win *cw;
106    Eina_List *l;
107    E_Comp_Object *co;
108
109    if (!((canvas) &&
110          (canvas->zone) &&
111          (canvas->zone->container)))
112      {
113         return;
114      }
115
116    E_Comp *c = e_mod_comp_util_get();
117    Eina_Bool found = EINA_FALSE;
118    EINA_INLIST_REVERSE_FOREACH(c->wins, cw)
119      {
120         if ((cw->bd) && (cw->bd == bd))
121           {
122              found = EINA_TRUE;
123              break;
124           }
125      }
126
127    if (found)
128      {
129         EINA_LIST_FOREACH(cw->objs, l, co)
130           {
131              e_layout_child_raise_above(o, co->shadow);
132           }
133      }
134 }
135
136 EAPI void
137 e_mod_comp_layer_lower_below(E_Comp_Canvas  *canvas,
138                              Evas_Object    *o,
139                              E_Border       *bd)
140 {
141    E_Comp_Win *cw;
142    Eina_List *l;
143    E_Comp_Object *co;
144
145    if (!((canvas) &&
146          (canvas->zone) &&
147          (canvas->zone->container)))
148      {
149         return;
150      }
151
152    E_Comp *c = e_mod_comp_util_get();
153    Eina_Bool found = EINA_FALSE;
154    EINA_INLIST_REVERSE_FOREACH(c->wins, cw)
155      {
156         if ((cw->bd) && (cw->bd == bd))
157           {
158              found = EINA_TRUE;
159              break;
160           }
161      }
162
163    if (found)
164      {
165         EINA_LIST_FOREACH(cw->objs, l, co)
166           {
167              e_layout_child_lower_below(o, co->shadow);
168           }
169      }
170 }
171
172 /* adjust the stack position of the background object to the bottom of layer */
173 EAPI void
174 e_mod_comp_layer_bg_adjust(E_Comp_Layer *ly)
175 {
176    e_layout_freeze(ly->layout);
177
178    if (!ly->bg)
179      {
180         ly->bg = evas_object_rectangle_add(ly->canvas->evas);
181         evas_object_color_set(ly->bg, 0, 0, 0, 255);
182         evas_object_show(ly->bg);
183         e_layout_pack(ly->layout, ly->bg);
184      }
185
186    e_layout_child_lower(ly->bg);
187
188    e_layout_thaw(ly->layout);
189 }
190
191 EAPI void
192 e_mod_comp_layer_effect_set(E_Comp_Layer *ly,
193                             Eina_Bool     set)
194 {
195    if (strcmp(ly->name, "effect"))
196      return;
197
198    if (set)
199      {
200         ly->count++;
201         ly->canvas->animation.run = 1;
202         ly->canvas->animation.num++;
203
204         if (!evas_object_visible_get(ly->layout))
205           {
206              e_mod_comp_composite_mode_set(ly->canvas->zone, EINA_TRUE);
207              evas_object_show(ly->layout);
208           }
209      }
210    else
211      {
212         /* decrease effect count and hide effect layer if it is 0 */
213         ly->count--;
214         ly->canvas->animation.num--;
215
216         if (ly->count <= 0)
217           {
218              E_FREE_LIST(ly->objs, ly->canvas->comp->effect_funcs.object_free);
219              evas_object_hide(ly->layout);
220
221              ly->canvas->animation.run = 0;
222              ly->canvas->animation.num = 0;
223              ly->count = 0;
224
225              e_mod_comp_composite_mode_set(ly->canvas->zone, EINA_FALSE);
226           }
227      }
228 }
229
230 EAPI Eina_Bool
231 e_mod_comp_layer_effect_get(E_Comp_Layer *ly)
232 {
233    E_CHECK_RETURN(ly, EINA_FALSE);
234
235    if (strcmp(ly->name, "effect"))
236      return EINA_FALSE;
237
238    return ly->canvas->animation.run;
239 }
240
241 EAPI E_Comp_Effect_Object *
242 e_mod_comp_layer_effect_obj_get(E_Comp_Layer   *ly,
243                                 Ecore_X_Window win)
244 {
245    E_Comp_Effect_Object *obj = NULL;
246    Eina_List *l;
247    E_CHECK_RETURN(ly, NULL);
248
249    if (strcmp(ly->name, "effect"))
250      return NULL;
251
252    EINA_LIST_FOREACH(ly->objs, l, obj)
253      {
254         if (!obj) continue;
255         if (obj->win == win)
256           {
257              return obj;
258           }
259      }
260
261    return NULL;
262 }
263
264 static void
265 _ly_intercept_show(void        *data,
266                    Evas_Object *obj)
267 {
268    E_Comp_Layer *ly = (E_Comp_Layer *)data;
269
270    ELBF(ELBT_COMP, 0, 0,
271         "%15.15s|name:%s layout:%p obj:%p",
272         "LY_PRE_SHOW", ly->name, ly->layout, obj);
273
274    /* TODO: an incontrollable effect layer show problem can occasionally occur. */
275    if (!strcmp(ly->name, "effect"))
276      {
277         if (!ly->canvas->animation.run)
278           {
279              ELBF(ELBT_COMP, 0, 0,
280                   "%15.15s|name:%s layout:%p obj:%p SKIP SHOW run:%d",
281                   "LY_PRE_SHOW", ly->name, ly->layout, obj,
282                   ly->canvas->animation.run);
283
284              return;
285           }
286      }
287
288    evas_object_show(obj);
289 }
290
291 static void
292 _ly_intercept_hide(void        *data,
293                    Evas_Object *obj)
294 {
295    E_Comp_Layer *ly = (E_Comp_Layer *)data;
296
297    ELBF(ELBT_COMP, 0, 0,
298         "%15.15s|name:%s layout:%p obj:%p",
299         "LY_PRE_HIDE", ly->name, ly->layout, obj);
300
301    evas_object_hide(obj);
302 }
303
304 /* externally accessible functions */
305 EAPI E_Comp_Canvas *
306 e_mod_comp_canvas_add(E_Comp *c,
307                       E_Zone *zone)
308 {
309    E_Comp_Canvas *canvas;
310    E_Comp_Layer *ly;
311    int x, y, w, h;
312    E_CHECK_RETURN(c, 0);
313
314    canvas = E_NEW(E_Comp_Canvas, 1);
315    E_CHECK_RETURN(canvas, 0);
316
317    if (zone)
318      {
319         x = zone->x;
320         y = zone->y;
321         w = zone->w;
322         h = zone->h;
323      }
324    else
325      {
326         x = 0;
327         y = 0;
328         w = c->man->w;
329         h = c->man->h;
330      }
331
332    if (_comp_mod->conf->engine == ENGINE_GL)
333      {
334         int opt[20];
335         int opt_i = 0;
336
337         if (_comp_mod->conf->indirect)
338           {
339              opt[opt_i] = ECORE_EVAS_GL_X11_OPT_INDIRECT;
340              opt_i++;
341              opt[opt_i] = 1;
342              opt_i++;
343           }
344         if (_comp_mod->conf->vsync)
345           {
346              opt[opt_i] = ECORE_EVAS_GL_X11_OPT_VSYNC;
347              opt_i++;
348              opt[opt_i] = 1;
349              opt_i++;
350           }
351         if (opt_i > 0)
352           {
353              opt[opt_i] = ECORE_EVAS_GL_X11_OPT_NONE;
354              canvas->ee = ecore_evas_gl_x11_options_new(NULL, c->win, x, y, w, h, opt);
355           }
356         if (!canvas->ee)
357           canvas->ee = ecore_evas_gl_x11_new(NULL, c->win, x, y, w, h);
358         
359         if (canvas->ee)
360              c->gl = 1;
361
362      }
363    if (!canvas->ee)
364      {
365         if (_comp_mod->conf->engine == ENGINE_GL)
366           {
367              e_util_dialog_internal
368                (_("Compositor Warning"),
369                _("Your screen does not support OpenGL.<br>"
370                  "Falling back to software engine."));
371           }
372
373         canvas->ee = ecore_evas_software_x11_new(NULL, c->win, x, y, w, h);
374      }
375    if (!canvas->ee)
376      {
377         e_util_dialog_internal
378            (_("Compositor Error"),
379             _("Failed to initialize Ecore Evas."));
380         goto error_cleanup;
381      }
382
383    canvas->x = x;
384    canvas->y = y;
385    canvas->w = w;
386    canvas->h = h;
387
388    canvas->comp = c;
389    canvas->num = _canvas_num++;
390
391    ecore_evas_comp_sync_set(canvas->ee, 0);
392    canvas->evas = ecore_evas_get(canvas->ee);
393
394    evas_event_callback_add(canvas->evas, EVAS_CALLBACK_RENDER_FLUSH_PRE,
395                            _pre_swap, c); 
396    evas_event_callback_add(canvas->evas,  EVAS_CALLBACK_RENDER_FLUSH_POST,
397                            _post_swap, c);
398
399    canvas->bg_img = evas_object_rectangle_add(canvas->evas);
400    if (_comp_mod->conf->use_hwc)
401       {
402         ecore_evas_alpha_set(canvas->ee, EINA_TRUE);
403         evas_object_color_set(canvas->bg_img, 0, 0, 0, 0);
404       }
405     else
406        evas_object_color_set(canvas->bg_img, 0, 0, 0, 255);
407
408    evas_object_stack_below(canvas->bg_img, evas_object_bottom_get(canvas->evas));
409    evas_object_move(canvas->bg_img, 0, 0);
410    evas_object_resize(canvas->bg_img, w, h);
411    evas_object_show(canvas->bg_img);
412
413    ecore_evas_show(canvas->ee);
414
415    canvas->ee_win = ecore_evas_window_get(canvas->ee);
416    canvas->zone = zone;
417
418    canvas->stereoscopic_mode = E_COMP_STEREO_MONO;
419
420    /* TODO: make a configurable list */
421    int i;
422    const char *names[] = {"comp", "effect", "move", "ly-ctrl"};
423    for (i = 0; i < 4; i++)
424      {
425         ly = E_NEW(E_Comp_Layer, 1);
426         E_CHECK_GOTO(ly, error_cleanup);
427         ly->name = strdup(names[i]);
428         if (!ly->name)
429           {
430              E_FREE(ly);
431              goto error_cleanup;
432           }
433
434         ly->layout = e_layout_add(canvas->evas);
435         if (!ly->layout)
436           {
437              free(ly->name);
438              E_FREE(ly);
439              goto error_cleanup;
440           }
441
442         evas_object_color_set(ly->layout, 255, 255, 255, 255);
443
444         ly->x = 0;
445         ly->y = 0;
446         ly->w = w;
447         ly->h = h;
448         ly->canvas = canvas;
449         ly->need_init = EINA_TRUE;
450
451         e_mod_comp_layer_eval(ly);
452
453         if (!strcmp(names[i], "comp"))
454           evas_object_show(ly->layout);
455
456         evas_object_intercept_show_callback_add(ly->layout, _ly_intercept_show, ly);
457         evas_object_intercept_hide_callback_add(ly->layout, _ly_intercept_hide, ly);
458
459         canvas->layers = eina_list_append(canvas->layers, ly);
460
461         ELBF(ELBT_COMP, 0, i, "E_Comp_Layer:%s", names[i]);
462      }
463
464    // comp can create only one ecore_evas for H/W overlay window
465    // this limit will be removed later
466    if ((_comp_mod->conf->use_hw_ov) &&
467        ((!zone) || (zone->num == 0)) &&
468        (!c->use_hw_ov))
469      {
470         canvas->ov = e_mod_comp_hw_ov_win_new(c->win, x, y, w, h);
471         if (canvas->ov)
472           {
473              c->use_hw_ov = EINA_TRUE;
474              e_mod_comp_hw_ov_win_root_set(canvas->ov, c->man->root);
475           }
476      }
477
478    canvas->zr = c->effect_funcs.zone_rotation_new(canvas);
479    E_CHECK_GOTO(canvas->zr, error_cleanup);
480
481    if (_comp_mod->conf->use_hwc)
482      {
483         if (c->hwcomp_funcs.hwcomp_new)
484            canvas->hwcomp = c->hwcomp_funcs.hwcomp_new(canvas);
485         else
486            canvas->hwcomp = NULL;
487
488         if (!canvas->hwcomp)
489           {
490              e_util_dialog_internal
491                (_("Compositor Error"),
492                _("Your screen does not support the HWC<br>"
493                  "This is needed for it to function."));
494              E_FREE(canvas);
495              return NULL;
496           }
497
498         _comp_mod->conf->nocomp_fs = 0;
499      }
500
501    c->canvases = eina_list_append(c->canvases, canvas);
502
503    return canvas;
504
505 error_cleanup:
506    if (canvas->zr)
507      c->effect_funcs.zone_rotation_free(canvas->zr);
508
509    EINA_LIST_FREE(canvas->layers, ly)
510      {
511         free(ly->name);
512         evas_object_del(ly->layout);
513         E_FREE(ly);
514      }
515    if (canvas->ee)
516      ecore_evas_free(canvas->ee);
517
518    memset(canvas, 0, sizeof(E_Comp_Canvas));
519    E_FREE(canvas);
520
521    return NULL;
522 }
523
524 EAPI void
525 e_mod_comp_canvas_del(E_Comp_Canvas *canvas)
526 {
527    E_Comp_Layer *ly;
528    E_Comp *c = e_mod_comp_util_get();
529
530    if (_comp_mod->conf->use_hwc)
531      {
532         if (c->hwcomp_funcs.hwcomp_free)
533            c->hwcomp_funcs.hwcomp_free(canvas->hwcomp);
534         canvas->hwcomp = NULL;
535      }
536
537    if (canvas->fps.fg)
538      {
539         evas_object_del(canvas->fps.fg);
540         canvas->fps.fg = NULL;
541      }
542    if (canvas->fps.bg)
543      {
544         evas_object_del(canvas->fps.bg);
545         canvas->fps.bg = NULL;
546      }
547    if (canvas->bg_img)
548      {
549         evas_object_del(canvas->bg_img);
550         canvas->bg_img = NULL;
551      }
552    if (canvas->zr)
553      {
554         canvas->comp->effect_funcs.zone_rotation_free(canvas->zr);
555         canvas->zr = NULL;
556      }
557    if (canvas->ov)
558      {
559         e_mod_comp_hw_ov_win_free(canvas->ov);
560         canvas->ov = NULL;
561         canvas->comp->use_hw_ov = EINA_FALSE;
562      }
563    if ((c) && (c->gl))
564       ecore_evas_gl_x11_pre_post_swap_callback_set(canvas->ee, NULL, NULL, NULL);
565    ecore_evas_manual_render(canvas->ee);
566
567    EINA_LIST_FREE(canvas->layers, ly)
568      {
569         free(ly->name);
570         evas_object_del(ly->layout);
571         E_FREE(ly);
572      }
573
574    ecore_evas_free(canvas->ee);
575    memset(canvas, 0, sizeof(E_Comp_Canvas));
576    E_FREE(canvas);
577 }
578
579 EAPI E_Comp_Layer *
580 e_mod_comp_canvas_layer_get(E_Comp_Canvas *canvas,
581                             const char    *name)
582 {
583    E_Comp_Layer *ly;
584    Eina_List *l;
585
586    E_CHECK_RETURN(canvas, NULL);
587    E_CHECK_RETURN(name, NULL);
588
589    EINA_LIST_FOREACH(canvas->layers, l, ly)
590      {
591         if (!strcmp(ly->name, name))
592           return ly;
593      }
594
595    return NULL;
596 }
597
598 EAPI E_Comp_Win *
599 e_mod_comp_canvas_fullscreen_check(E_Comp_Canvas *canvas)
600 {
601    E_Comp *c = canvas->comp;
602    E_Comp_Win *cw = NULL;
603
604    if (c->fake_image_launch)
605      {
606         Eina_Bool res = c->effect_funcs.image_launch_running_check(c->eff_img);
607         E_CHECK_RETURN(!res, NULL);
608      }
609
610    E_CHECK_RETURN(c->wins, NULL);
611    E_CHECK_RETURN(_comp_mod->conf->nocomp_fs, NULL);
612
613    EINA_INLIST_REVERSE_FOREACH(c->wins, cw)
614      {
615         if ((!cw->visible)   ||
616             (cw->input_only) ||
617             (cw->invalid))
618           {
619              continue;
620           }
621         if (!E_INTERSECTS(canvas->x, canvas->y, canvas->w, canvas->h,
622                           cw->x, cw->y, cw->w, cw->h))
623           {
624              continue;
625           }
626 #ifdef _F_USE_BORDER_TRANSFORM_
627         if ((cw) && (cw->bd) && (e_border_transform_enable_get(cw->bd)))
628           {
629              return NULL;
630           }
631         else
632 #endif /* end of _F_USE_BORDER_TRANSFORM_ */
633           {
634              if (REGION_EQUAL_TO_CANVAS(cw, canvas) &&
635                  (!cw->argb) &&
636                  (!cw->shaped) &&
637                  (cw->dmg_updates >= 1) &&
638                  (!cw->show_ready) &&
639                  (cw->show_done) &&
640                  (cw->use_dri2))
641                {
642                   if (cw->always_selective_mode)
643                     {
644                        ELBF(ELBT_COMP, 0, 0, "ALWAYS_SELECTIVE_MODE [%x]", e_mod_comp_util_client_xid_get(cw));
645                        return NULL;
646                     }
647                   return cw;
648                }
649              else
650                 return NULL;
651           }
652      }
653    return NULL;
654 }
655
656 EAPI void
657 e_mod_comp_canvas_nocomp_prepare(E_Comp_Canvas *canvas,
658                                  E_Comp_Win    *cw)
659 {
660    E_CHECK(canvas);
661    E_CHECK(cw);
662    E_CHECK(canvas->nocomp.mode == E_NOCOMP_MODE_NONE);
663
664    canvas->nocomp.mode = E_NOCOMP_MODE_PREPARE;
665    canvas->nocomp.prepare.cw = cw;
666    canvas->nocomp.prepare.timer = ecore_timer_add(_comp_mod->conf->nocomp_begin_timeout,
667                                                   _nocomp_prepare_timeout,
668                                                   canvas);
669 }
670
671 EAPI Eina_Bool
672 e_mod_comp_canvas_nocomp_begin(E_Comp_Canvas *canvas)
673 {
674    E_Comp *c = NULL;
675    E_Comp_Win *cw = NULL;
676
677    E_CHECK_RETURN(canvas, EINA_FALSE);
678    c = canvas->comp;
679    E_CHECK_RETURN(c, EINA_FALSE);
680    cw = canvas->nocomp.prepare.cw;
681    E_CHECK_RETURN(cw, EINA_FALSE);
682
683    ELBF(ELBT_COMP, 0,
684         e_mod_comp_util_client_xid_get(cw),
685         "NOCOMP_BEGIN canvas:%d dmg:%d",
686         canvas->num, cw->dmg_updates);
687
688    e_mod_comp_hw_ov_win_msg_show
689      (E_COMP_LOG_TYPE_NOCOMP,
690      ">> %d NOCOMP 0x%x dmg:%d",
691      canvas->num,
692      e_mod_comp_util_client_xid_get(cw),
693      cw->dmg_updates);
694
695    ecore_x_grab();
696
697    if (cw->redirected)
698      {
699         ecore_x_composite_unredirect_window(cw->win, ECORE_X_COMPOSITE_UPDATE_MANUAL);
700         cw->redirected = 0;
701      }
702
703    if (cw->damage)
704      {
705         Ecore_X_Region parts;
706         e_mod_comp_win_del_damage(cw, cw->damage);
707         parts = ecore_x_region_new(NULL, 0);
708         ecore_x_damage_subtract(cw->damage, 0, parts);
709         ecore_x_region_free(parts);
710         ecore_x_damage_free(cw->damage);
711         cw->damage = 0;
712      }
713
714    e_mod_comp_win_comp_objs_img_deinit(cw);
715    if (cw->pixmap)
716      {
717         ecore_x_pixmap_free(cw->pixmap);
718         cw->pixmap = 0;
719         ecore_x_e_comp_pixmap_set(cw->win, cw->pixmap);
720      }
721
722    ecore_x_window_shape_rectangle_subtract(c->win,
723                                            canvas->x,
724                                            canvas->y,
725                                            canvas->w,
726                                            canvas->h);
727    ecore_x_sync();
728    ecore_x_ungrab();
729
730    ecore_evas_manual_render_set(canvas->ee, 1);
731    c->nocomp = 1;
732    //c->render_overflow = OVER_FLOW;
733    canvas->nocomp.mode = E_NOCOMP_MODE_RUN;
734    canvas->nocomp.cw = cw;
735    canvas->nocomp.prepare.cw = NULL;
736
737    if (canvas->nocomp.prepare.timer)
738      {
739         ecore_timer_del(canvas->nocomp.prepare.timer);
740         canvas->nocomp.prepare.timer = NULL;
741      }
742
743    if (cw->update_timeout)
744      {
745         ecore_timer_del(cw->update_timeout);
746         cw->update_timeout = NULL;
747      }
748
749    cw->nocomp = 1;
750    cw->pw = 0;
751    cw->ph = 0;
752    cw->needpix = 1;
753
754    e_mod_comp_win_shape_input_invalid_set(c, 1);
755    e_mod_comp_win_render_queue(cw);
756
757    return EINA_TRUE;
758 }
759
760 EAPI Eina_Bool
761 e_mod_comp_canvas_nocomp_end(E_Comp_Canvas *canvas)
762 {
763    E_Comp *c = NULL;
764    E_Comp_Win *cw = NULL;
765
766    E_CHECK_RETURN(_comp_mod->conf->nocomp_fs, EINA_FALSE);
767
768    c = canvas->comp;
769    E_CHECK_RETURN(c, EINA_FALSE);
770
771    cw = canvas->nocomp.cw;
772    E_CHECK_RETURN(cw, EINA_FALSE);
773
774    ELBF(ELBT_COMP, 0,
775         e_mod_comp_util_client_xid_get(cw),
776         "NOCOMP_END canvas:%d dmg:%d",
777         canvas->num, cw->dmg_updates);
778
779    e_mod_comp_hw_ov_win_msg_show
780      (E_COMP_LOG_TYPE_NOCOMP,
781      ">> %d COMP 0x%x",
782      canvas->num,
783      e_mod_comp_util_client_xid_get(cw));
784
785    ecore_x_grab();
786    if (!cw->damage)
787      {
788         cw->damage = ecore_x_damage_new
789           (cw->win, ECORE_X_DAMAGE_REPORT_DELTA_RECTANGLES);
790         e_mod_comp_win_add_damage(cw, cw->damage);
791      }
792
793    ecore_x_window_shape_rectangle_add(c->win,
794                                       canvas->x,
795                                       canvas->y,
796                                       canvas->w,
797                                       canvas->h);
798    if (!cw->redirected)
799      {
800         ecore_x_composite_redirect_window(cw->win,
801                                           ECORE_X_COMPOSITE_UPDATE_MANUAL);
802         cw->redirected = 1;
803      }
804    ecore_x_sync();
805    ecore_x_ungrab();
806
807 #if USE_NOCOMP_DISPOSE
808    canvas->nocomp.mode = E_NOCOMP_MODE_END;
809    canvas->nocomp.end.cw = cw;
810    canvas->nocomp.cw = NULL;
811    canvas->nocomp.end.dmg_updates = cw->dmg_updates + 2;
812
813
814    if (canvas->nocomp.end.timer)
815      {
816         ecore_timer_del(canvas->nocomp.end.timer);
817         canvas->nocomp.end.timer = NULL;
818      }
819    canvas->nocomp.end.timer = ecore_timer_add(2.0f,
820                                               _nocomp_end_timeout,
821                                               canvas);
822 #else
823    e_mod_comp_canvas_nocomp_dispose(canvas);
824 #endif
825    return EINA_TRUE;
826 }
827
828 EAPI Eina_Bool
829 e_mod_comp_canvas_nocomp_dispose(E_Comp_Canvas *canvas)
830 {
831    E_Comp *c = NULL;
832    E_Comp_Win *cw = NULL;
833    Ecore_X_Pixmap pm;
834    E_Update_Rect *r;
835    int i;
836
837    E_CHECK_RETURN(_comp_mod->conf->nocomp_fs, EINA_FALSE);
838 #if USE_NOCOMP_DISPOSE
839    E_CHECK_RETURN((canvas->nocomp.mode == E_NOCOMP_MODE_END), EINA_FALSE);
840 #endif
841
842    c = canvas->comp;
843    E_CHECK_RETURN(c, EINA_FALSE);
844
845 #if USE_NOCOMP_DISPOSE
846    cw = canvas->nocomp.end.cw;
847 #else
848    cw = canvas->nocomp.cw;
849    canvas->nocomp.cw = NULL;
850 #endif
851    E_CHECK_RETURN(cw, EINA_FALSE);
852    E_CHECK_GOTO(cw->win, finish);
853
854    ELBF(ELBT_COMP, 0,
855         e_mod_comp_util_client_xid_get(cw),
856         "NOCOMP_DISPOSE canvas:%d dmg:%d",
857         canvas->num, cw->dmg_updates);
858
859    if (canvas->nocomp.end.timer)
860      {
861         ecore_timer_del(canvas->nocomp.end.timer);
862         canvas->nocomp.end.timer = NULL;
863      }
864
865    pm = ecore_x_composite_name_window_pixmap_get(cw->win);
866    if (pm)
867      {
868         Ecore_X_Pixmap oldpm;
869         cw->needpix = 0;
870         e_mod_comp_win_comp_objs_needxim_set(cw, 1);
871         oldpm = cw->pixmap;
872         cw->pixmap = pm;
873         if (cw->pixmap)
874           {
875              ecore_x_pixmap_geometry_get(cw->pixmap, NULL, NULL, &(cw->pw), &(cw->ph));
876              if (!((cw->pw == cw->w) && (cw->ph == cw->h)))
877                {
878                   ELBF(ELBT_COMP, 0,
879                        e_mod_comp_util_client_xid_get(cw),
880                        "NOCOMP_DISPOSE Size was not same. cw(w=%d, h=%d), pw(w=%d, h=%d)",
881                        cw->w, cw->h, cw->pw, cw->ph);
882                   cw->needpix = 1;
883 #if USE_NOCOMP_DISPOSE
884                   cw->pw = cw->w;
885                   cw->ph = cw->h;
886                   cw->pixmap = oldpm;
887                   ecore_x_pixmap_free(pm);
888 #endif
889                }
890              if ((cw->pw > 0) && (cw->ph > 0))
891                {
892                   e_mod_comp_win_comp_objs_img_resize(cw, cw->pw, cw->ph);
893                   e_mod_comp_win_comp_objs_resize(cw, cw->pw, cw->ph);
894                }
895           }
896         else
897           {
898              cw->pw = 0;
899              cw->ph = 0;
900           }
901         if ((cw->pw <= 0) || (cw->ph <= 0))
902           {
903              e_mod_comp_win_comp_objs_img_deinit(cw);
904              if (cw->pixmap)
905                {
906                   ecore_x_pixmap_free(cw->pixmap);
907                   cw->pixmap = 0;
908                }
909              cw->pw = 0;
910              cw->ph = 0;
911           }
912         ecore_x_e_comp_pixmap_set(cw->win, cw->pixmap);
913         e_mod_comp_win_comp_objs_native_set(cw, 0);
914         e_mod_comp_update_resize(cw->up, cw->pw, cw->ph);
915         e_mod_comp_update_add(cw->up, 0, 0, cw->pw, cw->ph);
916         if (oldpm) ecore_x_pixmap_free(oldpm);
917      }
918    if (((cw->c->gl  && _comp_mod->conf->texture_from_pixmap) || _comp_mod->conf->use_efl_native_surface)
919        && (!cw->shaped)
920        && (!cw->rects))
921      {
922         e_mod_comp_win_comp_objs_img_size_set(cw, cw->pw, cw->ph);
923         e_mod_comp_win_comp_objs_img_init(cw);
924         r = e_mod_comp_update_rects_get(cw->up);
925         if (r)
926           {
927              for (i = 0; r[i].w > 0; i++)
928                {
929                   int x, y, w, h;
930                   x = r[i].x; y = r[i].y;
931                   w = r[i].w; h = r[i].h;
932                   e_mod_comp_win_comp_objs_img_data_update_add(cw, x, y, w, h);
933                }
934              e_mod_comp_update_clear(cw->up);
935              free(r);
936           }
937      }
938
939    cw->nocomp = 0;
940    e_mod_comp_win_render_queue(cw);
941
942 finish:
943    ecore_evas_manual_render_set(canvas->ee, 0);
944    canvas->nocomp.end.cw = NULL;
945    canvas->nocomp.end.dmg_updates = 0;
946    canvas->nocomp.mode = E_NOCOMP_MODE_NONE;
947    c->nocomp = 0;
948
949    return EINA_TRUE;
950 }
951
952 EINTERN void
953 e_mod_comp_canvas_stereo_layout_set(E_Comp_Canvas *canvas)
954 {
955    unsigned int stereo_mode = 0;
956    E_Comp_Layer *ly = NULL;
957
958    stereo_mode = canvas->stereoscopic_mode;
959
960    ly = e_mod_comp_canvas_layer_get(canvas, "comp");
961
962    if (!ly) return;
963
964    e_layout_freeze(ly->layout);
965    if (stereo_mode == E_COMP_STEREO_HORIZONTAL)
966      {
967        e_layout_virtual_size_set(ly->layout, ly->w, (ly->h)*2);
968      }
969    else if (stereo_mode == E_COMP_STEREO_VERTICAL)
970      {
971        e_layout_virtual_size_set(ly->layout, (ly->w)*2, ly->h);
972      }
973    else if ((stereo_mode == E_COMP_STEREO_INTERLACED) || 
974             (stereo_mode == E_COMP_STEREO_MONO))
975      {
976        e_layout_virtual_size_set(ly->layout, ly->w, ly->h);
977      }
978
979    e_layout_thaw(ly->layout);
980 }
981
982 /* local subsystem functions */
983 static void
984 _fps_update(E_Comp_Canvas *canvas)
985 {
986    char buf[128];
987    double fps = 0.0, t, dt;
988    int i;
989    Evas_Coord x = 0, y = 0, w = 0, h = 0;
990    E_Zone *z;
991
992    if (!_comp_mod->conf->fps_show) return;
993
994    t = ecore_time_get();
995
996    if (_comp_mod->conf->fps_average_range < 1)
997      _comp_mod->conf->fps_average_range = 30;
998    else if (_comp_mod->conf->fps_average_range > 120)
999      _comp_mod->conf->fps_average_range = 120;
1000
1001    dt = t - canvas->fps.frametimes[_comp_mod->conf->fps_average_range - 1];
1002
1003    if (dt > 0.0) fps = (double)_comp_mod->conf->fps_average_range / dt;
1004    else fps = 0.0;
1005
1006    if (fps > 0.0) snprintf(buf, sizeof(buf), "FPS: %1.1f", fps);
1007    else snprintf(buf, sizeof(buf), "FPS: N/A");
1008
1009    for (i = 121; i >= 1; i--) canvas->fps.frametimes[i] = canvas->fps.frametimes[i - 1];
1010    canvas->fps.frametimes[0] = t;
1011    canvas->fps.frameskip++;
1012
1013    if (canvas->fps.frameskip >= _comp_mod->conf->fps_average_range)
1014      {
1015         canvas->fps.frameskip = 0;
1016         evas_object_text_text_set(canvas->fps.fg, buf);
1017      }
1018
1019    evas_object_geometry_get(canvas->fps.fg, NULL, NULL, &w, &h);
1020
1021    w += 8;
1022    h += 8;
1023
1024    z = canvas->zone;
1025    if (z)
1026      {
1027         switch (_comp_mod->conf->fps_corner)
1028           {
1029            case 3: // bottom-right
1030               x = z->w - w;
1031               y = z->h - h;
1032               break;
1033            case 2: // bottom-left
1034               x = 0;
1035               y = z->y + z->h - h;
1036               break;
1037            case 1: // top-right
1038               x = z->w - w;
1039               y = z->y;
1040               break;
1041            default: // 0 // top-left
1042               x = 0;
1043               y = z->y;
1044               break;
1045           }
1046      }
1047    evas_object_move(canvas->fps.bg, x, y);
1048    evas_object_resize(canvas->fps.bg, w, h);
1049    evas_object_move(canvas->fps.fg, x + 4, y + 4);
1050 }
1051
1052 static void
1053 _pre_swap(void *data, Evas *e, void *event_info)
1054 {
1055    E_Comp *c = (E_Comp *)data;
1056    Eina_List *l;
1057    E_Comp_Canvas *canvas;
1058    E_CHECK(c);
1059
1060    e_mod_comp_x_grab_set(c, EINA_FALSE);
1061
1062    EINA_LIST_FOREACH(c->canvases, l, canvas)
1063      {
1064         if (!canvas) continue;
1065         if (canvas->evas != e) continue;
1066
1067         ELB(ELBT_COMP_RENDER, "----------------SWAP----------------", canvas->num);
1068
1069
1070         if ((_comp_mod->conf->use_hwc) && (c->hwcomp_funcs.fullcomp_pending_release))
1071           {
1072              c->hwcomp_funcs.fullcomp_pending_release(canvas->hwcomp);
1073           }
1074
1075         if (_comp_mod->conf->fps_show)
1076           {
1077              if (!canvas->fps.bg)
1078                {
1079                   canvas->fps.bg = evas_object_rectangle_add(canvas->evas);
1080                   evas_object_color_set(canvas->fps.bg, 0, 0, 0, 128);
1081                   evas_object_layer_set(canvas->fps.bg, EVAS_LAYER_MAX);
1082                   evas_object_show(canvas->fps.bg);
1083                }
1084              if (!canvas->fps.fg)
1085                {
1086                   canvas->fps.fg = evas_object_text_add(canvas->evas);
1087                   evas_object_text_font_set(canvas->fps.fg, "Sans", 30);
1088                   evas_object_text_text_set(canvas->fps.fg, "FPS: 0.0");
1089                   evas_object_color_set(canvas->fps.fg, 255, 255, 255, 255);
1090                   evas_object_layer_set(canvas->fps.fg, EVAS_LAYER_MAX);
1091                   evas_object_show(canvas->fps.fg);
1092                }
1093              _fps_update(canvas);
1094           }
1095         else
1096           {
1097              if (canvas->fps.fg)
1098                {
1099                   evas_object_del(canvas->fps.fg);
1100                   canvas->fps.fg = NULL;
1101                }
1102              if (canvas->fps.bg)
1103                {
1104                   evas_object_del(canvas->fps.bg);
1105                   canvas->fps.bg = NULL;
1106                }
1107           }
1108      }
1109 }
1110
1111 static void
1112 _post_swap(void *data, Evas *e, void *event_info)
1113 {
1114    E_Comp *c = (E_Comp *)data;
1115    E_CHECK(c);
1116    E_CHECK(_comp_mod->conf->nocomp_fs);
1117
1118    Eina_List *l = NULL;
1119    E_Comp_Canvas *canvas = NULL;
1120    E_Comp_Win *cw = NULL;
1121    EINA_LIST_FOREACH(c->canvases, l, canvas)
1122      {
1123         if (canvas->evas != e) continue;
1124         if (canvas->nocomp.mode != E_NOCOMP_MODE_NONE) continue;
1125         if (canvas->nocomp.force_composite) continue;
1126         if (canvas->animation.run) continue;
1127
1128         cw = e_mod_comp_canvas_fullscreen_check(canvas);
1129         if (!cw) continue;
1130
1131         e_mod_comp_canvas_nocomp_prepare(canvas, cw);
1132      }
1133 }
1134
1135 static Eina_Bool
1136 _nocomp_prepare_timeout(void *data)
1137 {
1138    E_Comp_Canvas *canvas = (E_Comp_Canvas *)data;
1139    E_Comp_Win *cw;
1140    E_CHECK_RETURN(canvas, ECORE_CALLBACK_CANCEL);
1141
1142    if (canvas->nocomp.prepare.timer)
1143      {
1144         ecore_timer_del(canvas->nocomp.prepare.timer);
1145         canvas->nocomp.prepare.timer = NULL;
1146      }
1147
1148    if ((canvas->nocomp.force_composite)||
1149        (canvas->animation.run))
1150      {
1151         canvas->nocomp.prepare.cw = NULL;
1152         canvas->nocomp.mode = E_NOCOMP_MODE_NONE;
1153         return ECORE_CALLBACK_CANCEL;
1154      }
1155
1156    cw = e_mod_comp_canvas_fullscreen_check(canvas);
1157    if (!cw)
1158      {
1159         canvas->nocomp.prepare.cw = NULL;
1160         canvas->nocomp.mode = E_NOCOMP_MODE_NONE;
1161         return ECORE_CALLBACK_CANCEL;
1162      }
1163    else if (cw != canvas->nocomp.prepare.cw)
1164      {
1165         canvas->nocomp.prepare.cw = cw;
1166         canvas->nocomp.prepare.timer = ecore_timer_add(_comp_mod->conf->nocomp_begin_timeout,
1167                                                        _nocomp_prepare_timeout,
1168                                                        canvas);
1169         return ECORE_CALLBACK_CANCEL;
1170      }
1171
1172    e_mod_comp_canvas_nocomp_begin(canvas);
1173
1174    return ECORE_CALLBACK_CANCEL;
1175 }
1176
1177 #if USE_NOCOMP_DISPOSE
1178 static Eina_Bool
1179 _nocomp_end_timeout(void *data)
1180 {
1181    E_Comp_Canvas *canvas = (E_Comp_Canvas *)data;
1182    if (canvas->nocomp.end.timer)
1183      {
1184         ecore_timer_del(canvas->nocomp.end.timer);
1185         canvas->nocomp.end.timer = NULL;
1186      }
1187    e_mod_comp_canvas_nocomp_dispose(canvas);
1188    return ECORE_CALLBACK_CANCEL;
1189 }
1190 #endif