e_input: Remove eeze dependency
[platform/upstream/enlightenment.git] / src / bin / e_comp_screen.c
1 #include "e_client_intern.h"
2 #include "e_utils_intern.h"
3 #include "e_scale_intern.h"
4 #include "e_comp_canvas_intern.h"
5 #include "e_comp_screen_intern.h"
6 #include "e_comp_wl_input_intern.h"
7 #include "e_comp_wl_intern.h"
8 #include "e_explicit_sync_intern.h"
9 #include "e_comp_wl_tizen_hwc_intern.h"
10 #include "e_comp_intern.h"
11 #include "e_input_intern.h"
12 #include "e_error_intern.h"
13 #include "e_pointer_intern.h"
14 #include "e_output_intern.h"
15 #include "e_hwc_intern.h"
16 #include "e_hwc_window_intern.h"
17 #include "e_hwc_windows_intern.h"
18 #include "e_egl_sync_intern.h"
19 #include "e_config_intern.h"
20 #include "e_dbus_conn_intern.h"
21 #include "e_main_intern.h"
22 #include "e_hwc_planes_intern.h"
23
24 #include <tizen-extension-server-protocol.h>
25 #include <device/board-internal.h>
26 #include <tbm_drm_helper.h>
27 #include <gbm.h>
28
29 #define PATH "/org/enlightenment/wm"
30 #define IFACE "org.enlightenment.wm.screen_rotation"
31
32 static Ecore_Event_Handler *dbus_init_done_handler;
33 static Eldbus_Connection *edbus_conn = NULL;
34 static Eldbus_Connection_Type edbus_conn_type = ELDBUS_CONNECTION_TYPE_SYSTEM;
35 static Eldbus_Service_Interface *e_comp_screen_iface;
36
37 static Eina_List *event_handlers = NULL;
38 static Eina_List *output_hooks = NULL;
39
40 EINTERN int E_EVENT_SCREEN_CHANGE = 0;
41
42 enum
43 {
44    E_COMP_SCREEN_SIGNAL_ROTATION_CHANGED = 0
45 };
46
47 typedef struct _E_Comp_Screen_Tzsr
48 {
49    struct wl_resource *resource; /* tizen_screen_rotation */
50    E_Client           *ec;
51    struct wl_listener ec_destroy;
52 } E_Comp_Screen_Tzsr;
53
54 static Eina_List *tzsr_list;
55 static E_Client_Hook *tzsr_client_hook_del;
56
57 static void _tz_screen_rotation_cb_ec_destroy(struct wl_listener *listener, void *data);
58
59 static E_Comp_Screen_Tzsr*
60 _tz_surface_rotation_find(E_Client *ec)
61 {
62    E_Comp_Screen_Tzsr *tzsr = NULL;
63    struct wl_listener *listener;
64
65    listener = e_client_destroy_listener_get(ec, _tz_screen_rotation_cb_ec_destroy);
66    if (listener)
67      return wl_container_of(listener, tzsr, ec_destroy);
68
69    return tzsr;
70 }
71
72 static void
73 _tz_surface_rotation_free(E_Comp_Screen_Tzsr *tzsr)
74 {
75    ELOGF("TRANSFORM", "|tzsr(%p) freed", tzsr->ec, tzsr);
76    tzsr_list = eina_list_remove(tzsr_list, tzsr);
77    wl_list_remove(&tzsr->ec_destroy.link);
78    free(tzsr);
79 }
80
81 static void
82 _tz_screen_rotation_cb_ec_destroy(struct wl_listener *listener, void *data)
83 {
84    E_Comp_Screen_Tzsr *tzsr;
85
86    tzsr = wl_container_of(listener, tzsr, ec_destroy);
87    _tz_surface_rotation_free(tzsr);
88 }
89
90 static void
91 _tz_screen_rotation_get_ignore_output_transform(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface)
92 {
93    E_Comp_Screen_Tzsr *tzsr;
94    E_Client *ec;
95    E_Hwc_Policy hwc_policy;
96    E_Output *output;
97    E_Zone *zone;
98    Eina_Bool ignore = EINA_TRUE;
99
100    ec = e_client_from_surface_resource(surface);
101    EINA_SAFETY_ON_NULL_RETURN(ec);
102
103    tzsr = _tz_surface_rotation_find(ec);
104    if (tzsr) return;
105
106    tzsr = E_NEW(E_Comp_Screen_Tzsr, 1);
107    if (!tzsr)
108      {
109         wl_client_post_no_memory(client);
110         return;
111      }
112
113    tzsr->resource = resource;
114    tzsr->ec = ec;
115
116    tzsr->ec_destroy.notify = _tz_screen_rotation_cb_ec_destroy;
117    e_client_destroy_listener_add(ec, &tzsr->ec_destroy);
118
119    tzsr_list = eina_list_append(tzsr_list, tzsr);
120
121    zone = e_comp_zone_find_by_ec(ec);
122    if (zone)
123      {
124         output = e_output_find(zone->output_id);
125         if (output)
126           {
127              hwc_policy = e_hwc_policy_get(output->hwc);
128              if (hwc_policy == E_HWC_POLICY_WINDOWS)
129                ignore = EINA_FALSE;
130           }
131      }
132
133    ELOGF("TRANSFORM", "|tzsr(%p) client_ignore(%d) ignore(%d)",
134          ec, tzsr, e_config->screen_rotation_client_ignore, ignore);
135
136    e_comp_screen_rotation_ignore_output_transform_send(ec, ignore);
137 }
138
139 static void
140 _tz_screen_rotation_iface_cb_destroy(struct wl_client *client, struct wl_resource *resource)
141 {
142    wl_resource_destroy(resource);
143 }
144
145 static const struct tizen_screen_rotation_interface _tz_screen_rotation_interface =
146 {
147    _tz_screen_rotation_get_ignore_output_transform,
148    _tz_screen_rotation_iface_cb_destroy,
149 };
150
151 static void _tz_screen_rotation_cb_destroy(struct wl_resource *resource)
152 {
153    E_Comp_Screen_Tzsr *tzsr;
154    Eina_List *l, *ll;
155
156    EINA_LIST_FOREACH_SAFE(tzsr_list, l, ll, tzsr)
157      {
158         if (tzsr->resource == resource)
159           _tz_surface_rotation_free(tzsr);
160      }
161 }
162
163 static void
164 _tz_screen_rotation_cb_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
165 {
166    struct wl_resource *res;
167
168    if (!(res = wl_resource_create(client, &tizen_screen_rotation_interface, version, id)))
169      {
170         ERR("Could not create tizen_screen_rotation resource: %m");
171         wl_client_post_no_memory(client);
172         return;
173      }
174
175    wl_resource_set_implementation(res, &_tz_screen_rotation_interface, NULL, _tz_screen_rotation_cb_destroy);
176 }
177
178 static Eldbus_Message *
179 _e_comp_screen_dbus_get_cb(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
180 {
181    Eldbus_Message *reply = eldbus_message_method_return_new(msg);
182    int rotation = 0;
183
184    if (e_comp && e_comp->e_comp_screen)
185      rotation = e_comp->e_comp_screen->rotation;
186
187    ELOGF("COMP_SCREEN","got screen-rotation 'get' request: %d", NULL, rotation);
188
189    eldbus_message_arguments_append(reply, "i", rotation);
190
191    return reply;
192 }
193
194 static const Eldbus_Method methods[] =
195 {
196    {"get", NULL, ELDBUS_ARGS({"i", "int32"}), _e_comp_screen_dbus_get_cb, 0},
197    {}
198 };
199
200 static const Eldbus_Signal signals[] = {
201    [E_COMP_SCREEN_SIGNAL_ROTATION_CHANGED] = {"changed", ELDBUS_ARGS({ "i", "rotation" }), 0},
202    {}
203 };
204
205 static const Eldbus_Service_Interface_Desc iface_desc = {
206      IFACE, methods, signals, NULL, NULL, NULL
207 };
208
209 static void
210 _e_comp_screen_dbus_init()
211 {
212    E_Comp_Screen *e_comp_screen = e_comp->e_comp_screen;
213
214    e_comp_screen_iface = eldbus_service_interface_register(edbus_conn,
215                                                            PATH,
216                                                            &iface_desc);
217    EINA_SAFETY_ON_NULL_GOTO(e_comp_screen_iface, err);
218
219    if (e_comp_screen->rotation)
220      {
221         eldbus_service_signal_emit(e_comp_screen_iface, E_COMP_SCREEN_SIGNAL_ROTATION_CHANGED, e_comp_screen->rotation);
222         ELOGF("TRANSFORM", "screen-rotation sends signal: %d", NULL, e_comp_screen->rotation);
223      }
224
225    return;
226
227 err:
228    if (edbus_conn)
229      {
230         e_dbus_conn_connection_unref(edbus_conn);
231         edbus_conn = NULL;
232      }
233
234    return;
235 }
236
237 static char *
238 _layer_cap_to_str(tdm_layer_capability caps, tdm_layer_capability cap)
239 {
240    if (caps & cap)
241      {
242         if (cap == TDM_LAYER_CAPABILITY_CURSOR) return "cursor ";
243         else if (cap == TDM_LAYER_CAPABILITY_PRIMARY) return "primary ";
244         else if (cap == TDM_LAYER_CAPABILITY_OVERLAY) return "overlay ";
245         else if (cap == TDM_LAYER_CAPABILITY_GRAPHIC) return "graphics ";
246         else if (cap == TDM_LAYER_CAPABILITY_VIDEO) return "video ";
247         else if (cap == TDM_LAYER_CAPABILITY_TRANSFORM) return "transform ";
248         else if (cap == TDM_LAYER_CAPABILITY_RESEVED_MEMORY) return "reserved_memory ";
249         else if (cap == TDM_LAYER_CAPABILITY_NO_CROP) return "no_crop ";
250         else return "unkown";
251      }
252    return "";
253 }
254
255 static Eina_Bool
256 _e_comp_screen_commit_idle_cb(void *data EINA_UNUSED)
257 {
258    Eina_List *l, *ll;
259    E_Comp_Screen *e_comp_screen = NULL;
260    E_Output *output = NULL;
261
262    if (!e_comp->e_comp_screen) goto end;
263
264    if (e_config->comp_canvas_norender.use)
265      evas_norender(e_comp->evas);
266
267    if (e_comp->canvas_render_delayed) goto end;
268
269    e_comp_screen = e_comp->e_comp_screen;
270
271    EINA_LIST_FOREACH_SAFE(e_comp_screen->outputs, l, ll, output)
272      {
273         if (!output) continue;
274         if (!output->config.enabled) continue;
275
276         if (!e_output_commit(output))
277              ERR("fail to commit e_comp_screen->outputs.");
278
279         if (!e_output_render(output))
280              ERR("fail to render e_comp_screen->outputs.");
281      }
282 end:
283    return ECORE_CALLBACK_RENEW;
284 }
285
286 static void
287 _e_comp_screen_input_rotation_set(int rotation)
288 {
289    if (rotation > 0)
290      {
291         const Eina_List *l;
292         E_Input_Device *dev;
293
294         EINA_LIST_FOREACH(e_input_devices_get(), l, dev)
295           {
296              e_input_device_touch_rotation_set(dev, rotation);
297              e_input_device_rotation_set(dev, rotation);
298
299              ELOGF("COMP_SCREEN","EE Input Device Rotate: %d", NULL, rotation);
300           }
301      }
302 }
303
304 static Eina_Bool
305 _e_comp_screen_cb_input_device_add(void *data, int type, void *event)
306 {
307    Ecore_Event_Device_Info *e;
308    E_Comp *comp = data;
309
310    if (!(e = event)) goto end;
311
312    if (e->clas == ECORE_DEVICE_CLASS_MOUSE)
313      {
314         if (comp->wl_comp_data->ptr.num_devices == 0)
315           {
316              e_pointer_object_set(comp->pointer, NULL, 0, 0);
317              e_comp_wl_input_pointer_enabled_set(EINA_TRUE);
318           }
319         comp->wl_comp_data->ptr.num_devices++;
320      }
321    else if (e->clas == ECORE_DEVICE_CLASS_KEYBOARD)
322      {
323         comp->wl_comp_data->kbd.num_devices++;
324         e_comp_wl_input_keyboard_enabled_set(EINA_TRUE);
325      }
326    else if (e->clas == ECORE_DEVICE_CLASS_TOUCH)
327      {
328         e_comp_wl_input_touch_enabled_set(EINA_TRUE);
329         _e_comp_screen_input_rotation_set(e_comp->e_comp_screen->rotation);
330         comp->wl_comp_data->touch.num_devices++;
331      }
332
333 end:
334    return ECORE_CALLBACK_PASS_ON;
335 }
336
337 static void
338 _e_comp_screen_pointer_renew(void)
339 {
340      if ((e_comp_wl->ptr.num_devices == 0) && e_comp_wl->ptr.ec && e_comp_wl->ptr.ec->pointer_enter_sent)
341      {
342         if (e_devicemgr->last_device_ptr)
343           {
344              Evas_Device *last_ptr = NULL, *dev;
345              Eina_List *list, *l;
346              const char *name;
347              const char *description;
348
349              list = (Eina_List *)evas_device_list(evas_object_evas_get(e_comp_wl->ptr.ec->frame), NULL);
350              EINA_LIST_FOREACH(list, l, dev)
351                {
352                   name = evas_device_name_get(dev);
353                   description = evas_device_description_get(dev);
354
355                   if (!name || !description) continue;
356                   if ((!strncmp(name, e_devicemgr->last_device_ptr->name, strlen(e_devicemgr->last_device_ptr->name))) &&
357                       (!strncmp(description, e_devicemgr->last_device_ptr->identifier, strlen(e_devicemgr->last_device_ptr->identifier))) &&
358                       (evas_device_class_get(dev) == (Evas_Device_Class)e_devicemgr->last_device_ptr->clas))
359                     {
360                        last_ptr = dev;
361                        break;
362                     }
363                }
364              if (last_ptr)
365                e_comp_wl_mouse_out_renew(e_comp_wl->ptr.ec, 0, wl_fixed_to_int(e_comp_wl->ptr.x), wl_fixed_to_int(e_comp_wl->ptr.y), NULL, NULL, NULL, ecore_time_get(), EVAS_EVENT_FLAG_NONE, last_ptr, NULL);
366           }
367      }
368 }
369
370 static Eina_Bool
371 _e_comp_screen_cb_input_device_del(void *data, int type, void *event)
372 {
373    Ecore_Event_Device_Info *e;
374    E_Comp *comp = data;
375
376    if (!(e = event)) goto end;
377
378    if (e->clas == ECORE_DEVICE_CLASS_MOUSE)
379      {
380         comp->wl_comp_data->ptr.num_devices--;
381         if (comp->wl_comp_data->ptr.num_devices == 0)
382           {
383              e_comp_wl_input_pointer_enabled_set(EINA_FALSE);
384              e_pointer_object_set(comp->pointer, NULL, 0, 0);
385              e_pointer_hide(e_comp->pointer);
386
387              _e_comp_screen_pointer_renew();
388           }
389      }
390    else if (e->clas == ECORE_DEVICE_CLASS_KEYBOARD)
391      {
392         comp->wl_comp_data->kbd.num_devices--;
393         if (comp->wl_comp_data->kbd.num_devices == 0)
394           {
395              e_comp_wl_input_keyboard_enabled_set(EINA_FALSE);
396           }
397      }
398    else if (e->clas == ECORE_DEVICE_CLASS_TOUCH)
399      {
400         comp->wl_comp_data->touch.num_devices--;
401         if (comp->wl_comp_data->touch.num_devices == 0)
402           {
403              e_comp_wl_input_touch_enabled_set(EINA_FALSE);
404           }
405      }
406
407 end:
408
409    return ECORE_CALLBACK_PASS_ON;
410 }
411
412 static Eina_Bool
413 _e_comp_screen_size_update(E_Comp_Screen *e_comp_screen)
414 {
415    E_Output *output;
416    int sum_w = 0, max_h = 0, output_w, output_h;
417    Eina_List *l;
418
419    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, EINA_FALSE);
420
421    /* we place external output to the right of primary output */
422    EINA_LIST_FOREACH(e_comp_screen->outputs, l, output)
423      {
424         if (!e_output_connected(output)) continue;
425
426         e_output_size_get(output, &output_w, &output_h);
427         sum_w += output_w;
428
429         if (max_h < output_h)
430           max_h = output_h;
431      }
432
433    e_comp_screen->w = sum_w;
434    e_comp_screen->h = max_h;
435
436    if (e_comp->ee)
437      {
438         /* rotation should be reset because tbm_surface_queue or gbm_surface of
439          * ecore_evas is created without rotation
440          * and rotation of ecore_evas is reset after it is resized
441          */
442         if (e_comp_screen->rotation)
443           ecore_evas_rotation_with_resize_set(e_comp->ee, 0);
444
445         ecore_evas_resize(e_comp->ee, e_comp_screen->w, e_comp_screen->h);
446
447         if (e_comp_screen->rotation)
448           ecore_evas_rotation_with_resize_set(e_comp->ee, e_comp_screen->rotation);
449      }
450
451    return EINA_TRUE;
452 }
453
454 static Eina_Bool
455 _e_comp_screen_cb_event(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED)
456 {
457    E_Comp_Screen *e_comp_screen;
458    tdm_error ret;
459
460    if (!(e_comp_screen = data)) return ECORE_CALLBACK_RENEW;
461
462    ret = tdm_display_handle_events(e_comp_screen->tdisplay);
463    if (ret != TDM_ERROR_NONE)
464      ERR("tdm_display_handle_events failed");
465
466    return ECORE_CALLBACK_RENEW;
467 }
468
469 static E_Comp_Screen *
470 _e_comp_screen_new(E_Comp *comp)
471 {
472    E_Comp_Screen *e_comp_screen = NULL;
473    tdm_error error = TDM_ERROR_NONE;
474    tdm_display_capability capabilities;
475    const tbm_format *pp_formats;
476    int count, i;
477    int fd;
478
479    e_comp_screen = E_NEW(E_Comp_Screen, 1);
480    if (!e_comp_screen) return NULL;
481
482    /* tdm display init */
483    e_main_ts_begin("\tTDM Display Init");
484    e_comp_screen->tdisplay = tdm_display_init(&error);
485    if (!e_comp_screen->tdisplay)
486      {
487         e_main_ts_end("\tTDM Display Init Failed");
488         ERR("fail to get tdm_display\n");
489         free(e_comp_screen);
490         return NULL;
491      }
492    e_main_ts_end("\tTDM Display Init Done");
493
494    e_comp_screen->gdevice_fd = -1;
495    e_comp_screen->fd = -1;
496    tdm_display_get_fd(e_comp_screen->tdisplay, &fd);
497    if (fd < 0)
498      {
499         ERR("fail to get tdm_display fd\n");
500         goto fail;
501      }
502
503    e_comp_screen->fd = dup(fd);
504
505    e_comp_screen->hdlr =
506      ecore_main_fd_handler_add(e_comp_screen->fd, ECORE_FD_READ,
507                                _e_comp_screen_cb_event, e_comp_screen, NULL, NULL);
508    /* tdm display init */
509    e_main_ts_begin("\tTBM Bufmgr Server Init");
510    e_comp_screen->bufmgr = tbm_bufmgr_server_init();
511    if (!e_comp_screen->bufmgr)
512      {
513         e_main_ts_end("\tTBM Bufmgr Server Init Failed");
514         ERR("tbm_bufmgr_init failed\n");
515         goto fail;
516      }
517    e_main_ts_end("\tTBM Bufmgr Server Init Done");
518
519    error = tdm_display_get_capabilities(e_comp_screen->tdisplay, &capabilities);
520    if (error != TDM_ERROR_NONE)
521      {
522         ERR("tdm get_capabilities failed");
523         goto fail;
524      }
525
526    /* check the pp_support */
527    if (capabilities & TDM_DISPLAY_CAPABILITY_PP)
528      {
529         error = tdm_display_get_pp_available_formats(e_comp_screen->tdisplay, &pp_formats, &count);
530         if (error != TDM_ERROR_NONE)
531           ERR("fail to get available pp formats");
532         else
533           {
534              e_comp_screen->pp_enabled = EINA_TRUE;
535              for (i = 0 ; i < count ; i++)
536                e_comp_screen->available_pp_formats = eina_list_append(e_comp_screen->available_pp_formats, &pp_formats[i]);
537           }
538      }
539
540    e_main_ts_begin("\ttdm-socket Init");
541    if (e_comp_socket_init("tdm-socket"))
542      PRCTL("[Winsys] change permission and create sym link for %s", "tdm-socket");
543    e_main_ts_end("\ttdm-socket Init Done");
544
545    return e_comp_screen;
546
547 fail:
548    if (e_comp_screen->bufmgr) tbm_bufmgr_deinit(e_comp_screen->bufmgr);
549    if (e_comp_screen->fd >= 0) close(e_comp_screen->fd);
550    if (e_comp_screen->hdlr) ecore_main_fd_handler_del(e_comp_screen->hdlr);
551    if (e_comp_screen->tdisplay) tdm_display_deinit(e_comp_screen->tdisplay);
552
553    free(e_comp_screen);
554    TRACE_DS_END();
555
556    return NULL;
557 }
558
559 static void
560 _e_comp_screen_del(E_Comp_Screen *e_comp_screen)
561 {
562    Eina_List *l = NULL, *ll = NULL;
563    tbm_format *formats;
564
565    if (!e_comp_screen) return;
566
567    if (e_comp_screen->pp_enabled)
568      {
569         EINA_LIST_FOREACH_SAFE(e_comp_screen->available_pp_formats, l, ll, formats)
570           {
571              if (!formats) continue;
572              e_comp_screen->available_pp_formats = eina_list_remove(e_comp_screen->available_pp_formats, l);
573           }
574      }
575
576    if (e_comp_screen->gdevice) gbm_device_destroy(e_comp_screen->gdevice);
577    if (e_comp_screen->gdevice_fd >= 0) close(e_comp_screen->gdevice_fd);
578    if (e_comp_screen->bufmgr) tbm_bufmgr_deinit(e_comp_screen->bufmgr);
579    if (e_comp_screen->fd >= 0) close(e_comp_screen->fd);
580    if (e_comp_screen->hdlr) ecore_main_fd_handler_del(e_comp_screen->hdlr);
581    if (e_comp_screen->tdisplay) tdm_display_deinit(e_comp_screen->tdisplay);
582
583    free(e_comp_screen);
584 }
585
586 static void
587 _e_comp_screen_output_mode_change_cb(tdm_output *toutput, unsigned int index, void *user_data)
588 {
589    E_Comp_Screen *e_comp_screen = user_data;
590    E_Output *output = NULL;
591    Eina_Bool find = EINA_FALSE;
592    int count, num;
593    E_Output_Mode *set_emode = NULL, *current_emode = NULL;
594    E_Output_Mode *emode = NULL;
595    Eina_List *modelist = NULL, *l, *ll;
596
597    EINA_SAFETY_ON_NULL_RETURN(e_comp_screen);
598
599    EINA_LIST_FOREACH_SAFE(e_comp_screen->outputs, l, ll, output)
600      {
601         if (output->toutput == toutput)
602           {
603              find = EINA_TRUE;
604              break;
605           }
606      }
607    EINA_SAFETY_ON_FALSE_RETURN(find == EINA_TRUE);
608
609    current_emode = e_output_current_mode_get(output);
610    EINA_SAFETY_ON_NULL_RETURN(current_emode);
611
612    modelist = e_output_mode_list_get(output);
613    if (modelist)
614      {
615         num = eina_list_count(modelist);
616         EINA_SAFETY_ON_FALSE_RETURN(index < num);
617
618         count = 0;
619         EINA_LIST_FOREACH(modelist, l, emode)
620           {
621              if (count == index)
622                {
623                   set_emode = emode;
624                   break;
625                }
626              count++;
627           }
628
629         if (set_emode)
630           {
631              EINA_SAFETY_ON_TRUE_RETURN(current_emode == set_emode);
632
633              ELOGF("COMP_SCREEN","request mode change(%d) (%dx%d, %lf) -> (%dx%d, %lf)\n",
634                    NULL, index, current_emode->w, current_emode->h, current_emode->refresh,
635                    set_emode->w, set_emode->h, set_emode->refresh);
636
637              e_output_external_mode_change(output, set_emode);
638           }
639      }
640 }
641
642 static void
643 _e_comp_screen_output_destroy_cb(tdm_output *toutput, void *user_data)
644 {
645    E_Comp_Screen *e_comp_screen = user_data;
646    E_Output *output = NULL;
647    Eina_List *l, *ll;
648
649    EINA_SAFETY_ON_NULL_RETURN(e_comp_screen);
650
651    tdm_output_remove_destroy_handler(toutput, _e_comp_screen_output_destroy_cb, e_comp_screen);
652
653    EINA_LIST_FOREACH_SAFE(e_comp_screen->outputs, l, ll, output)
654      {
655         if (output->toutput == toutput)
656           {
657              e_comp_screen->num_outputs--;
658              e_comp_screen->outputs = eina_list_remove_list(e_comp_screen->outputs, l);
659              e_output_del(output);
660           }
661      }
662 }
663
664 static void
665 _e_comp_screen_output_create_cb(tdm_display *dpy, tdm_output *toutput, void *user_data)
666 {
667    E_Comp_Screen *e_comp_screen = user_data;
668    E_Output *output = NULL;
669    tdm_error ret = TDM_ERROR_NONE;
670
671    EINA_SAFETY_ON_NULL_RETURN(e_comp_screen);
672
673    TRACE_DS_BEGIN(OUTPUT:NEW);
674    output = e_output_new(e_comp_screen, e_comp_screen->num_outputs);
675    EINA_SAFETY_ON_NULL_GOTO(output, fail);
676    if (output->toutput != toutput) goto fail;
677    TRACE_DS_END();
678
679    TRACE_DS_BEGIN(OUTPUT:UPDATE);
680    if (!e_output_update(output))
681      {
682         ERR("fail to e_output_update.");
683         e_output_del(output);
684         goto fail;
685      }
686    TRACE_DS_END();
687
688    /* todo : add tdm_output_add_mode_change_request_handler()*/
689    ret = tdm_output_add_mode_change_request_handler(toutput, _e_comp_screen_output_mode_change_cb, e_comp_screen);
690    if (ret != TDM_ERROR_NONE)
691      {
692         ERR("fail to add output mode change handler.");
693         e_output_del(output);
694         return;
695      }
696
697    ret = tdm_output_add_destroy_handler(toutput, _e_comp_screen_output_destroy_cb, e_comp_screen);
698    if (ret != TDM_ERROR_NONE)
699      {
700         ERR("fail to add output destroy handler.");
701         e_output_del(output);
702         return;
703      }
704
705    e_comp_screen->outputs = eina_list_append(e_comp_screen->outputs, output);
706    e_comp_screen->num_outputs++;
707
708    return;
709
710 fail:
711    TRACE_DS_END();
712 }
713
714 static void
715 _e_comp_screen_deinit_outputs(E_Comp_Screen *e_comp_screen)
716 {
717    E_Output *output;
718    Eina_List *l, *ll;
719
720    tdm_display_remove_output_create_handler(e_comp_screen->tdisplay, _e_comp_screen_output_create_cb, e_comp_screen);
721
722    e_hwc_ecore_evas_deinit();
723
724    // free up e_outputs
725    EINA_LIST_FOREACH_SAFE(e_comp_screen->outputs, l, ll, output)
726      {
727         e_comp_screen->outputs = eina_list_remove_list(e_comp_screen->outputs, l);
728         e_output_del(output);
729      }
730
731    e_explicit_sync_deinit();
732    e_egl_sync_deinit();
733    e_hwc_deinit();
734    e_hwc_windows_deinit();
735    e_hwc_planes_deinit();
736    e_output_shutdown();
737 }
738
739 static Eina_Bool
740 _e_comp_screen_fake_output_set(E_Comp_Screen *e_comp_screen)
741 {
742    E_Output *primary_output = NULL;
743
744    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, EINA_FALSE);
745
746    primary_output = e_comp_screen_primary_output_get(e_comp_screen);
747    EINA_SAFETY_ON_NULL_RETURN_VAL(primary_output, EINA_FALSE);
748
749    if (!e_output_hwc_setup(primary_output))
750      {
751         ERR("fail to e_output_hwc_setup.");
752         return EINA_FALSE;
753      }
754
755    if (!e_output_fake_config_set(primary_output, 2, 1))
756      {
757         e_error_message_show(_("Fail to set the fake output config!\n"));
758         e_hwc_ecore_evas_deinit();
759         return EINA_FALSE;
760      }
761
762    return EINA_TRUE;
763 }
764
765 static Eina_Bool
766 _e_comp_screen_init_outputs(E_Comp_Screen *e_comp_screen)
767 {
768    E_Output *output = NULL;
769    E_Output_Mode *mode = NULL;
770    tdm_display *tdisplay = e_comp_screen->tdisplay;
771    int num_outputs;
772    int i;
773    Eina_Bool scale_updated = EINA_FALSE;
774    Eina_Bool connection_check = EINA_FALSE;
775    tdm_error err = TDM_ERROR_NONE;
776    char bootmode[32];
777    int ret;
778
779    /* init e_output */
780    if (!e_output_init())
781      {
782         ERR("fail to e_output_init.");
783         return EINA_FALSE;
784      }
785
786    /* get the num of outputs */
787    err = tdm_display_get_output_count(tdisplay, &num_outputs);
788    if ((err != TDM_ERROR_NONE) ||
789        (num_outputs < 1))
790      {
791         ERR("fail to get tdm_display_get_output_count\n");
792         return EINA_FALSE;
793      }
794    e_comp_screen->num_outputs = num_outputs;
795
796    ELOGF("COMP_SCREEN","num_outputs = %i", NULL, e_comp_screen->num_outputs);
797
798    if (!e_hwc_init())
799      {
800         ERR("e_hwc_init failed");
801         goto fail;
802      }
803
804    if (!e_hwc_planes_init())
805      {
806         ERR("e_hwc_planes_init failed");
807         goto fail;
808      }
809
810    if (!e_hwc_windows_init())
811      {
812         ERR("e_hwc_windows_init failed");
813         goto fail;
814      }
815
816    for (i = 0; i < num_outputs; i++)
817      {
818         e_main_ts_begin("\tE_Output New");
819         output = e_output_new(e_comp_screen, i);
820         if (!output)
821           {
822              e_main_ts_end("\tE_Output New Failed");
823              goto fail;
824           }
825
826         e_main_ts_begin("\tE_Output Update");
827         if (!e_output_update(output))
828           {
829             e_main_ts_end("\tE_Output Update Failed");
830             ERR("fail to e_output_update.");
831             goto fail;
832           }
833         e_main_ts_end("\tE_Output Update Done");
834
835         e_comp_screen->outputs = eina_list_append(e_comp_screen->outputs, output);
836
837         if (!e_output_connected(output)) continue;
838
839         connection_check = EINA_TRUE;
840
841         /* setting with the best mode and enable the output */
842         e_main_ts_begin("\tE_Output Find Best Mode");
843         mode = e_output_best_mode_find(output);
844         if (!mode)
845           {
846              e_main_ts_end("\tE_Output Find Best Mode Failed");
847              ERR("fail to get best mode.");
848              goto fail;
849           }
850         e_main_ts_end("\tE_Output Find Best Mode Done");
851
852         e_main_ts_begin("\tE_Output Mode Apply");
853         if (!e_output_mode_apply(output, mode))
854           {
855              e_main_ts_end("\tE_Output Mode Apply Failed");
856              ERR("fail to e_output_mode_apply.");
857              goto fail;
858           }
859         e_main_ts_end("\tE_Output Mode Apply Done");
860
861         e_main_ts_begin("\tE_Output Set DPMS ON");
862         ret = device_board_get_boot_mode(bootmode, sizeof(bootmode));
863         if (!ret && !e_util_strcmp(bootmode, "silent"))
864           {
865              INF("silent reboot. do not set dpms");
866           }
867         else
868           {
869              if (!e_output_dpms_set(output, E_OUTPUT_DPMS_ON))
870                {
871                   e_main_ts_end("\tE_Output Set DPMS ON Failed");
872                   ERR("fail to e_output_dpms.");
873                   goto fail;
874                }
875           }
876
877         e_main_ts_end("\tE_Output Set DPMS ON Done");
878
879         e_main_ts_begin("\tE_Output Hwc Setup");
880         if (!e_output_hwc_setup(output))
881           {
882              e_main_ts_end("\tE_Output Hwc Setup Failed");
883              ERR("fail to e_output_hwc_setup.");
884              goto fail;
885           }
886         e_main_ts_end("\tE_Output Hwc Setup Done");
887
888         /* update e_scale with first available output size */
889         if ((e_config->scale.for_tdm) && (!scale_updated))
890           {
891              double target_inch;
892              int dpi;
893
894              target_inch = (round((sqrt(output->info.size.w * output->info.size.w + output->info.size.h * output->info.size.h) / 25.4) * 10) / 10);
895              dpi = (round((sqrt(mode->w * mode->w + mode->h * mode->h) / target_inch) * 10) / 10);
896
897              e_scale_manual_update(dpi);
898              scale_updated = EINA_TRUE;
899           }
900      }
901
902    //TODO: if there is no output connected, make the fake output which is connected.
903    if (!connection_check)
904      {
905         if (!_e_comp_screen_fake_output_set(e_comp_screen))
906           goto fail;
907      }
908
909    _e_comp_screen_size_update(e_comp_screen);
910
911    e_main_ts_begin("\tE_Hwc Ecore_Evas Init");
912    if (!e_hwc_ecore_evas_init())
913      {
914         e_main_ts_end("\ttE_Hwc Ecore_Evas Init Failed");
915         ERR("fail to e_hwc_ecore_evas_init");
916         goto fail;
917      }
918    e_main_ts_end("\tE_Hwc Ecore_Evas Init Done");
919
920    if (tdm_display_add_output_create_handler(tdisplay, _e_comp_screen_output_create_cb, e_comp_screen)) goto fail;
921
922    return EINA_TRUE;
923 fail:
924    _e_comp_screen_deinit_outputs(e_comp_screen);
925
926    return EINA_FALSE;
927 }
928
929 static void
930 _e_comp_screen_e_screen_free(E_Screen *scr)
931 {
932    free(scr->id);
933    free(scr);
934 }
935
936 static void
937 _e_comp_screen_e_screens_set(E_Comp_Screen *e_comp_screen, Eina_List *screens)
938 {
939    E_FREE_LIST(e_comp_screen->e_screens, _e_comp_screen_e_screen_free);
940    e_comp_screen->e_screens = screens;
941 }
942
943 static void
944 _e_comp_screen_engine_deinit(void)
945 {
946    if (!e_comp) return;
947    if (!e_comp->e_comp_screen) return;
948
949    _e_comp_screen_deinit_outputs(e_comp->e_comp_screen);
950    _e_comp_screen_del(e_comp->e_comp_screen);
951    e_comp->e_comp_screen = NULL;
952 }
953
954 static Eina_Bool
955 _e_comp_screen_engine_init(void)
956 {
957    E_Comp_Screen *e_comp_screen = NULL;
958    int screen_rotation;
959
960    /* check the screen rotation */
961    screen_rotation = (e_config->screen_rotation_pre + e_config->screen_rotation_setting) % 360;
962
963    ELOGF("COMP_SCREEN","screen_rotation_pre %d and screen_rotation_setting %d",
964          NULL, e_config->screen_rotation_pre, e_config->screen_rotation_setting);
965
966    /* e_comp_screen new */
967    e_main_ts_begin("\tE_Comp_Screen New");
968    e_comp_screen = _e_comp_screen_new(e_comp);
969    if (!e_comp_screen)
970      {
971         e_main_ts_end("\tE_Comp_Screen New Failed");
972         e_error_message_show(_("Enlightenment cannot create e_comp_screen!\n"));
973         return EINA_FALSE;
974      }
975    e_main_ts_end("\tE_Comp_Screen New Done");
976
977    e_comp->e_comp_screen = e_comp_screen;
978    e_comp_screen->rotation_pre = e_config->screen_rotation_pre;
979    e_comp_screen->rotation_setting = e_config->screen_rotation_setting;
980    e_comp_screen->rotation = screen_rotation;
981
982    e_main_ts_begin("\tE_Comp_Screen Outputs Init");
983    if (!_e_comp_screen_init_outputs(e_comp_screen))
984      {
985         e_main_ts_end("\tE_Comp_Screen Outputs Init Failed");
986         e_error_message_show(_("Enlightenment cannot initialize outputs!\n"));
987         _e_comp_screen_engine_deinit();
988         return EINA_FALSE;
989      }
990    e_main_ts_end("\tE_Comp_Screen Outputs Init Done");
991
992    if (!E_EVENT_SCREEN_CHANGE) E_EVENT_SCREEN_CHANGE = ecore_event_type_new();
993
994    ecore_event_add(E_EVENT_SCREEN_CHANGE, NULL, NULL, NULL);
995
996    e_comp_screen_e_screens_setup(e_comp_screen, -1, -1);
997
998    /* update the screen, outputs and planes at the idle enterer of the ecore_loop */
999    ecore_idle_enterer_add(_e_comp_screen_commit_idle_cb, e_comp);
1000
1001    return EINA_TRUE;
1002 }
1003
1004 static Eina_Bool
1005 _e_comp_screen_cb_dbus_init_done(void *data, int type, void *event)
1006 {
1007    E_DBus_Conn_Init_Done_Event *e = event;
1008
1009    if (e->status == E_DBUS_CONN_INIT_SUCCESS && e->conn_type == edbus_conn_type)
1010      {
1011         edbus_conn = e_dbus_conn_connection_ref(edbus_conn_type);
1012
1013         if (edbus_conn)
1014           _e_comp_screen_dbus_init();
1015      }
1016
1017    ecore_event_handler_del(dbus_init_done_handler);
1018    dbus_init_done_handler = NULL;
1019
1020    return ECORE_CALLBACK_PASS_ON;
1021 }
1022
1023 EINTERN void
1024 e_comp_screen_e_screens_setup(E_Comp_Screen *e_comp_screen, int rw, int rh)
1025 {
1026    E_Screen *screen;
1027    E_Output *output;
1028    Eina_List *e_screens = NULL;
1029    Eina_List *l;
1030    int i = 0, right_x = 0;
1031
1032    output = e_comp_screen_primary_output_get(e_comp_screen);
1033    /* No pirmary output means that there is no output at the system */
1034    if (!output) goto out;
1035
1036    EINA_LIST_FOREACH(e_comp_screen->outputs, l, output)
1037      {
1038         screen = E_NEW(E_Screen, 1);
1039         if (!screen) return;
1040
1041         screen->escreen = screen->screen = i;
1042
1043         if (output->config.rotation % 180)
1044           {
1045              screen->w = output->config.geom.h;
1046              screen->h = output->config.geom.w;
1047           }
1048         else
1049           {
1050              screen->w = output->config.geom.w;
1051              screen->h = output->config.geom.h;
1052           }
1053
1054         if (e_output_connected(output))
1055           {
1056              output->config.geom.x = right_x;
1057              right_x += output->config.geom.w;
1058           }
1059         else
1060           {
1061              output->config.geom.x = 0;
1062           }
1063
1064         screen->x = output->config.geom.x;
1065         screen->y = output->config.geom.y;
1066
1067         if (output->id) screen->id = strdup(output->id);
1068
1069         e_screens = eina_list_append(e_screens, screen);
1070         ELOGF("COMP_SCREEN","E INIT: SCREEN: [%i][%i], %ix%i+%i+%i",
1071               NULL, i, i, screen->w, screen->h, screen->x, screen->y);
1072         i++;
1073      }
1074
1075    ELOGF("COMP_SCREEN","e_comp_screen_e_screens_setup............... %i %p\n", NULL, i, e_comp_screen->e_screens);
1076
1077    ecore_event_add(E_EVENT_SCREEN_CHANGE, NULL, NULL, NULL);
1078
1079    _e_comp_screen_e_screens_set(e_comp_screen, e_screens);
1080
1081    return;
1082 out:
1083    screen = E_NEW(E_Screen, 1);
1084    if (!screen) return;
1085    screen->escreen = screen->screen = 0;
1086    screen->x = 0;
1087    screen->y = 0;
1088    if ((rw > 0) && (rh > 0))
1089      screen->w = rw, screen->h = rh;
1090    else
1091      {
1092         if (e_comp_screen->rotation % 180)
1093           ecore_evas_geometry_get(e_comp->ee, NULL, NULL, &screen->h, &screen->w);
1094         else
1095           ecore_evas_geometry_get(e_comp->ee, NULL, NULL, &screen->w, &screen->h);
1096      }
1097    e_screens = eina_list_append(e_screens, screen);
1098
1099    ELOGF("COMP_SCREEN","E INIT: SCREEN: No Physical Screen : [%i][%i], %ix%i+%i+%i",
1100          NULL, i, i, screen->w, screen->h, screen->x, screen->y);
1101
1102    _e_comp_screen_e_screens_set(e_comp_screen, e_screens);
1103 }
1104
1105 EINTERN const Eina_List *
1106 e_comp_screen_e_screens_get(E_Comp_Screen *e_comp_screen)
1107 {
1108    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, NULL);
1109
1110    return e_comp_screen->e_screens;
1111 }
1112
1113 static void
1114 _e_comp_screen_cb_output_connect_status_change(void *data, E_Output *output)
1115 {
1116    _e_comp_screen_size_update(e_comp->e_comp_screen);
1117 }
1118
1119 static void
1120 _e_comp_screen_cb_output_mode_change(void *data, E_Output *output)
1121 {
1122    _e_comp_screen_size_update(e_comp->e_comp_screen);
1123 }
1124
1125 EINTERN Eina_Bool
1126 e_comp_screen_init()
1127 {
1128    E_Comp *comp;
1129    int w, h, ptr_x = 0, ptr_y = 0;
1130
1131    if (!(comp = e_comp))
1132      EINA_SAFETY_ON_NULL_RETURN_VAL(comp, EINA_FALSE);
1133
1134    e_main_ts_begin("\tE_Comp_Screen_Engine Init");
1135    if (!_e_comp_screen_engine_init())
1136      {
1137         e_main_ts_end("\tE_Comp_Screen_Engine Init Failed");
1138         ERR("Could not initialize the ecore_evas engine.");
1139         goto failed_comp_screen;
1140      }
1141    e_main_ts_end("\tE_Comp_Screen_Engine Init Done");
1142
1143    e_main_ts_begin("\tE_Input Init");
1144    if (!e_input_init(e_comp->ee))
1145      {
1146         e_main_ts_end("\tE_Input Init Failed");
1147         ERR("Could not initialize the e_input.");
1148         goto failed_comp_screen;
1149      }
1150    e_main_ts_end("\tE_Input Init Done");
1151
1152    e_main_ts_begin("\tE_Comp_Wl Init");
1153    if (!e_comp_wl_init())
1154      {
1155         e_main_ts_begin("\tE_Comp_Wl Init Failed");
1156         goto failed_comp_screen;
1157      }
1158    e_main_ts_end("\tE_Comp_Wl Init Done");
1159
1160    /* get the current screen geometry */
1161    ecore_evas_geometry_get(e_comp->ee, NULL, NULL, &w, &h);
1162
1163    /* canvas */
1164    e_main_ts_begin("\tE_Comp_Canvas Init");
1165    if (!e_comp_canvas_init(w, h))
1166      {
1167         e_main_ts_end("\tE_Comp_Canvas Init Failed");
1168         e_error_message_show(_("Enlightenment cannot initialize outputs!\n"));
1169         goto failed_comp_screen;
1170      }
1171    e_main_ts_end("\tE_Comp_Canvas Init Done");
1172
1173    e_main_ts_begin("\tE_Egl_Sync Init");
1174    if (e_egl_sync_init())
1175      ELOGF("E_EGL_SYNC", "Enabled the E_Egl_Sync", NULL);
1176    e_main_ts_end("\tE_Egl_Sync Init Done");
1177
1178    e_main_ts_begin("\tE_Explicit_Sync Init");
1179    if (e_explicit_sync_init())
1180      ELOGF("EX-SYNC", "Enabled the E_Explicit_Sync", NULL);
1181    e_main_ts_end("\tE_Explicit_Sync Init Done");
1182
1183    /* pointer */
1184    e_input_device_pointer_xy_get(NULL, &ptr_x, &ptr_y);
1185    e_comp_wl->ptr.x = wl_fixed_from_int(ptr_x);
1186    e_comp_wl->ptr.y = wl_fixed_from_int(ptr_y);
1187
1188    evas_event_feed_mouse_in(e_comp->evas, 0, NULL);
1189
1190    e_main_ts_begin("\tE_Pointer New");
1191    if ((comp->pointer = e_pointer_canvas_new(comp->ee, EINA_TRUE)))
1192      {
1193         e_pointer_hide(comp->pointer);
1194      }
1195    e_main_ts_end("\tE_Pointer New Done");
1196
1197    /* FIXME: We need a way to trap for user changing the keymap inside of E
1198     *        without the event coming from X11 */
1199
1200    /* FIXME: We should make a decision here ...
1201     *
1202     * Fetch the keymap from drm, OR set this to what the E config is....
1203     */
1204
1205    /* FIXME: This is just for testing at the moment....
1206     * happens to jive with what drm does */
1207
1208    if (!e_input_thread_mode_get())
1209      {
1210         e_main_ts_begin("\tE_Comp_WL Keymap Init");
1211         e_comp_wl_input_keymap_init();
1212         e_main_ts_begin("\tE_Comp_WL Keymap Init Done");
1213      }
1214
1215    /* try to add tizen_video to wayland globals */
1216    if (!wl_global_create(e_comp_wl->wl.disp, &tizen_screen_rotation_interface, 1,
1217                          NULL, _tz_screen_rotation_cb_bind))
1218      {
1219         ERR("Could not add tizen_screen_rotation to wayland globals");
1220         goto failed_comp_screen;
1221      }
1222
1223    if (!e_comp_wl_tizen_hwc_init())
1224      {
1225         e_main_ts_end("\e_comp_wl_tizen_hwc_init Init Failed");
1226         e_error_message_show(_("Enlightenment cannot initialize tizen_hwc!\n"));
1227         goto failed_comp_screen;
1228      }
1229
1230    e_main_ts_begin("\tDBUS Init");
1231    dbus_init_done_handler = NULL;
1232    if (e_dbus_conn_init() > 0)
1233      {
1234         dbus_init_done_handler = ecore_event_handler_add(E_EVENT_DBUS_CONN_INIT_DONE, _e_comp_screen_cb_dbus_init_done, NULL);
1235         e_dbus_conn_dbus_init(edbus_conn_type);
1236      }
1237    e_main_ts_end("\tDBUS Init Done");
1238
1239    E_LIST_HANDLER_APPEND(event_handlers, ECORE_EVENT_DEVICE_ADD, _e_comp_screen_cb_input_device_add, comp);
1240    E_LIST_HANDLER_PREPEND(event_handlers, ECORE_EVENT_DEVICE_DEL, _e_comp_screen_cb_input_device_del, comp);
1241
1242    E_OUTPUT_HOOK_APPEND(output_hooks, E_OUTPUT_HOOK_CONNECT_STATUS_CHANGE, _e_comp_screen_cb_output_connect_status_change, comp);
1243    E_OUTPUT_HOOK_APPEND(output_hooks, E_OUTPUT_HOOK_MODE_CHANGE, _e_comp_screen_cb_output_mode_change, comp);
1244
1245    _e_comp_screen_input_rotation_set(e_comp->e_comp_screen->rotation);
1246
1247    return EINA_TRUE;
1248
1249 failed_comp_screen:
1250
1251    e_comp_wl_tizen_hwc_shutdown();
1252    e_input_shutdown();
1253    _e_comp_screen_engine_deinit();
1254
1255    return EINA_FALSE;
1256 }
1257
1258 EINTERN void
1259 e_comp_screen_shutdown()
1260 {
1261    if (!e_comp) return;
1262    if (!e_comp->e_comp_screen) return;
1263
1264    e_comp_wl_tizen_hwc_shutdown();
1265
1266    if (e_comp_screen_iface)
1267      {
1268         eldbus_service_interface_unregister(e_comp_screen_iface);
1269         e_comp_screen_iface = NULL;
1270      }
1271
1272    if (edbus_conn)
1273      {
1274         e_dbus_conn_connection_unref(edbus_conn);
1275         edbus_conn = NULL;
1276      }
1277
1278    e_dbus_conn_shutdown();
1279
1280    _e_comp_screen_deinit_outputs(e_comp->e_comp_screen);
1281
1282    E_FREE_LIST(output_hooks, e_output_hook_del);
1283
1284    e_client_hook_del(tzsr_client_hook_del);
1285    tzsr_client_hook_del = NULL;
1286
1287    E_FREE_LIST(event_handlers, ecore_event_handler_del);
1288
1289    /* delete e_comp_sreen */
1290    _e_comp_screen_del(e_comp->e_comp_screen);
1291    e_comp->e_comp_screen = NULL;
1292 }
1293
1294 static E_Output *
1295 _e_comp_screen_output_find_primary(E_Comp_Screen *e_comp_screen)
1296 {
1297    E_Output *output = NULL, *o;
1298    const Eina_List *l;
1299
1300    EINA_LIST_FOREACH(e_comp_screen->outputs, l, o)
1301      {
1302         unsigned int pipe = 0;
1303         tdm_error error;
1304
1305         error = tdm_output_get_pipe(o->toutput, &pipe);
1306         if (error != TDM_ERROR_NONE || pipe != 0)
1307           continue;
1308
1309         output = o;
1310         break;
1311      }
1312
1313    if (!output)
1314      {
1315         ERR("couldn't find the primary output");
1316         return NULL;
1317      }
1318
1319    return output;
1320 }
1321
1322 static Eina_Bool
1323 _e_comp_screen_rotation_set(E_Comp_Screen *e_comp_screen, int screen_rotation,
1324   void (*setter)(E_Comp_Screen *e_comp_screen, int data), int data)
1325 {
1326    E_Output *output = NULL;
1327    E_Input_Device *dev;
1328    const Eina_List *l;
1329    int w, h;
1330
1331    output = _e_comp_screen_output_find_primary(e_comp_screen);
1332    if (!output)
1333      return EINA_FALSE;
1334
1335    if (!e_output_rotate(output, screen_rotation))
1336      return EINA_FALSE;
1337
1338    e_comp_screen->rotation = screen_rotation;
1339    if (setter)
1340       setter(e_comp_screen, data);
1341
1342    ecore_evas_rotation_with_resize_set(e_comp->ee, e_comp_screen->rotation);
1343    ecore_evas_geometry_get(e_comp->ee, NULL, NULL, &w, &h);
1344
1345    /* rendering forcely to prepare HWC */
1346    e_comp_render_queue();
1347    e_comp_hwc_end(__FUNCTION__);
1348
1349    EINA_LIST_FOREACH(e_input_devices_get(), l, dev)
1350      {
1351          e_input_device_touch_rotation_set(dev, e_comp_screen->rotation);
1352          e_input_device_rotation_set(dev, e_comp_screen->rotation);
1353
1354          ELOGF("COMP_SCREEN","EE Input Device Rotate: %d", NULL, e_comp_screen->rotation);
1355      }
1356
1357    if (e_comp_screen_iface)
1358      {
1359         eldbus_service_signal_emit(e_comp_screen_iface, E_COMP_SCREEN_SIGNAL_ROTATION_CHANGED, e_comp_screen->rotation);
1360         ELOGF("COMP_SCREEN", "screen-rotation sends signal: %d", NULL, e_comp_screen->rotation);
1361      }
1362
1363    ELOGF("COMP_SCREEN","EE Rotated and Resized: %d, %dx%d", NULL, e_comp_screen->rotation, w, h);
1364
1365    return EINA_TRUE;
1366 }
1367
1368 static void
1369 _e_comp_screen_rotation_pre_setter(E_Comp_Screen *e_comp_screen, int rotation_pre)
1370 {
1371    e_comp_screen->rotation_pre = rotation_pre;
1372    ELOGF("COMP_SCREEN","EE RotationPre: %d", NULL, rotation_pre);
1373 }
1374
1375 EINTERN Eina_Bool
1376 e_comp_screen_rotation_pre_set(E_Comp_Screen *e_comp_screen, int rotation_pre)
1377 {
1378    int screen_rotation;
1379
1380    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, EINA_FALSE);
1381    EINA_SAFETY_ON_TRUE_RETURN_VAL(rotation_pre % 90, EINA_FALSE);
1382    EINA_SAFETY_ON_TRUE_RETURN_VAL(rotation_pre < 0, EINA_FALSE);
1383    EINA_SAFETY_ON_TRUE_RETURN_VAL(rotation_pre > 270, EINA_FALSE);
1384
1385    if (e_comp_screen->rotation_pre == rotation_pre) return EINA_TRUE;
1386
1387    screen_rotation = (rotation_pre + e_comp_screen->rotation_setting) % 360;
1388
1389    return _e_comp_screen_rotation_set(e_comp_screen, screen_rotation,
1390      _e_comp_screen_rotation_pre_setter, rotation_pre);
1391 }
1392
1393 static void
1394 _e_comp_screen_rotation_setting_setter(E_Comp_Screen *e_comp_screen, int rotation)
1395 {
1396    e_comp_screen->rotation_setting = rotation;
1397    ELOGF("COMP_SCREEN","EE RotationSetting: %d", NULL, rotation);
1398 }
1399
1400 E_API Eina_Bool
1401 e_comp_screen_rotation_setting_set(E_Comp_Screen *e_comp_screen, int rotation)
1402 {
1403    int screen_rotation;
1404
1405    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, EINA_FALSE);
1406    EINA_SAFETY_ON_TRUE_RETURN_VAL(rotation % 90, EINA_FALSE);
1407    EINA_SAFETY_ON_TRUE_RETURN_VAL(rotation < 0, EINA_FALSE);
1408    EINA_SAFETY_ON_TRUE_RETURN_VAL(rotation > 270, EINA_FALSE);
1409
1410    if (e_comp_screen->rotation_setting == rotation) return EINA_TRUE;
1411
1412    screen_rotation = (e_comp_screen->rotation_pre + rotation) % 360;
1413
1414    return _e_comp_screen_rotation_set(e_comp_screen, screen_rotation,
1415      _e_comp_screen_rotation_setting_setter, rotation);
1416 }
1417
1418 E_API void
1419 e_comp_screen_rotation_ignore_output_transform_send(E_Client *ec, Eina_Bool ignore)
1420 {
1421    E_Comp_Screen_Tzsr *tzsr = _tz_surface_rotation_find(ec);
1422    E_Comp_Wl_Client_Data *cdata;
1423
1424    if (!tzsr) return;
1425
1426    /* if client have to considers the output transform */
1427    if (!ignore)
1428      {
1429         /* exception */
1430         if (e_config->screen_rotation_client_ignore)
1431           {
1432              ELOGF("TRANSFORM", "|tzsr(%p) ignore_output_transform: client_ignore", ec, tzsr);
1433              return;
1434           }
1435
1436         if (e_policy_client_is_quickpanel(ec))
1437            {
1438               ELOGF("TRANSFORM", "|tzsr(%p) ignore_output_transform: quickpanel", ec, tzsr);
1439               return;
1440            }
1441      }
1442
1443    ELOGF("TRANSFORM", "|tzsr(%p) ignore_output_transform(%d)", ec, tzsr, ignore);
1444
1445    cdata = e_client_cdata_get(ec);
1446    tizen_screen_rotation_send_ignore_output_transform(tzsr->resource, cdata->surface, ignore);
1447 }
1448
1449 EINTERN Eina_Bool
1450 e_comp_screen_rotation_ignore_output_transform_watch(E_Client *ec)
1451 {
1452    return (_tz_surface_rotation_find(ec)) ? EINA_TRUE : EINA_FALSE;
1453 }
1454
1455 EINTERN E_Output *
1456 e_comp_screen_primary_output_get(E_Comp_Screen *e_comp_screen)
1457 {
1458    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, NULL);
1459
1460    E_Output *output = NULL, *o = NULL;
1461    Eina_List *l = NULL;
1462    int highest_priority = 0;
1463
1464    /* find the highest priority of the e_output */
1465    EINA_LIST_FOREACH(e_comp_screen->outputs, l, o)
1466      {
1467         if (highest_priority < o->config.priority)
1468           {
1469              highest_priority = o->config.priority;
1470              output = o;
1471           }
1472      }
1473
1474    return output;
1475 }
1476
1477 EINTERN Eina_Bool
1478 e_comp_screen_pp_support(void)
1479 {
1480    E_Comp_Screen *e_comp_screen = NULL;
1481    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, EINA_FALSE);
1482
1483    e_comp_screen = e_comp->e_comp_screen;
1484    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, EINA_FALSE);
1485    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen->tdisplay, EINA_FALSE);
1486
1487    return e_comp_screen->pp_enabled;
1488 }
1489
1490
1491 EINTERN Eina_List *
1492 e_comp_screen_pp_available_formats_get(void)
1493 {
1494   E_Comp_Screen *e_comp_screen = NULL;
1495   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, EINA_FALSE);
1496
1497   e_comp_screen = e_comp->e_comp_screen;
1498   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, EINA_FALSE);
1499   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen->tdisplay, EINA_FALSE);
1500
1501   if (!e_comp_screen->pp_enabled)
1502     {
1503        ERR("pp does not support.");
1504        return NULL;
1505     }
1506
1507    return e_comp_screen->available_pp_formats;
1508 }
1509
1510 EINTERN void
1511 e_comp_screen_hwc_info_debug(void)
1512 {
1513    EINA_SAFETY_ON_NULL_RETURN(e_comp);
1514    EINA_SAFETY_ON_NULL_RETURN(e_comp->e_comp_screen);
1515
1516    E_Comp_Screen *e_comp_screen = e_comp->e_comp_screen;
1517    E_Output *output = NULL;
1518    E_Plane *plane = NULL;
1519    Eina_List *l_o, *ll_o;
1520    Eina_List *l_l, *ll_l;
1521    tdm_output_conn_status conn_status;
1522    int output_idx = 0;
1523    tdm_layer_capability layer_capabilities;
1524    char layer_cap[4096] = {0, };
1525    int i;
1526    const tdm_prop *tprops;
1527    int count;
1528
1529    INF("HWC: HWC Information ==========================================================");
1530    EINA_LIST_FOREACH_SAFE(e_comp_screen->outputs, l_o, ll_o, output)
1531      {
1532         tdm_error err = TDM_ERROR_NONE;
1533
1534         if (!output) continue;
1535
1536         if (e_hwc_policy_get(output->hwc) == E_HWC_POLICY_PLANES)
1537           {
1538              err = tdm_output_get_conn_status(output->toutput, &conn_status);
1539              if (err != TDM_ERROR_NONE) continue;
1540              if (conn_status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) continue;
1541
1542              INF("HWC: HWC Output(%d):(x, y, w, h)=(%d, %d, %d, %d) Information.",
1543                  ++output_idx,
1544                  output->config.geom.x, output->config.geom.y, output->config.geom.w, output->config.geom.h);
1545              INF("HWC:  num_layers=%d", output->plane_count);
1546              EINA_LIST_FOREACH_SAFE(output->planes, l_l, ll_l, plane)
1547                {
1548                    if (!plane) continue;
1549                    /* FIXME: hwc extension doesn't provide thing like layer */
1550                    tdm_layer_get_capabilities(plane->tlayer, &layer_capabilities);
1551                    snprintf(layer_cap, sizeof(layer_cap), "%s%s%s%s%s%s%s%s",
1552                             _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_CURSOR),
1553                             _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_PRIMARY),
1554                             _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_OVERLAY),
1555                             _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_GRAPHIC),
1556                             _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_VIDEO),
1557                             _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_TRANSFORM),
1558                             _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_RESEVED_MEMORY),
1559                             _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_NO_CROP));
1560                    INF("HWC:  index=%d zpos=%d ec=%p %s",
1561                        plane->index, plane->zpos,
1562                        plane->ec?plane->ec:NULL,
1563                        layer_cap);
1564                }
1565           }
1566         else
1567           {
1568              /* TODO: construct debug info for outputs managed by the hwc-wins */
1569              INF("HWC: HWC Output(%d) managed by hwc-wins.", ++output_idx);
1570
1571              if (!e_hwc_windows_get_available_properties(output->hwc, &tprops, &count))
1572                {
1573                   ERR("e_hwc_windows_get_video_available_properties failed");
1574                   return;
1575                }
1576              INF(">>>>>>>> Available UI props : count = %d", count);
1577              for (i = 0; i < count; i++)
1578                INF("   [%d] %s, %u", i, tprops[i].name, tprops[i].id);
1579
1580              if (!e_hwc_windows_get_video_available_properties(output->hwc, &tprops, &count))
1581                {
1582                   ERR("e_hwc_windows_get_video_available_properties failed");
1583                   return;
1584                }
1585              INF(">>>>>>>> Available VIDEO props : count = %d", count);
1586              for (i = 0; i < count; i++)
1587                INF("   [%d] %s, %u", i, tprops[i].name, tprops[i].id);
1588           }
1589      }
1590    INF("HWC: =========================================================================");
1591 }
1592
1593 #define NUM_SW_FORMAT   (sizeof(sw_formats) / sizeof(sw_formats[0]))
1594
1595 static tbm_format sw_formats[] = {
1596      TBM_FORMAT_ARGB8888,
1597      TBM_FORMAT_XRGB8888,
1598      TBM_FORMAT_YUV420,
1599      TBM_FORMAT_YVU420,
1600 };
1601
1602 static tdm_layer *
1603 _e_comp_screen_video_tdm_layer_get(tdm_output *output)
1604 {
1605    int i, count = 0;
1606 #ifdef CHECKING_PRIMARY_ZPOS
1607    int primary_idx = 0, primary_zpos = 0;
1608    tdm_layer *primary_layer;
1609 #endif
1610
1611    EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
1612
1613    tdm_output_get_layer_count(output, &count);
1614    for (i = 0; i < count; i++)
1615      {
1616         tdm_layer *layer = tdm_output_get_layer(output, i, NULL);
1617         tdm_layer_capability capabilities = 0;
1618         EINA_SAFETY_ON_NULL_RETURN_VAL(layer, NULL);
1619
1620         tdm_layer_get_capabilities(layer, &capabilities);
1621         if (capabilities & TDM_LAYER_CAPABILITY_VIDEO)
1622           return layer;
1623      }
1624
1625 #ifdef CHECKING_PRIMARY_ZPOS
1626    tdm_output_get_primary_index(output, &primary_idx);
1627    primary_layer = tdm_output_get_layer(output, primary_idx, NULL);
1628    EINA_SAFETY_ON_NULL_RETURN_VAL(primary_layer, NULL);
1629    tdm_layer_get_zpos(primary_layer, &primary_zpos);
1630 #endif
1631
1632    for (i = 0; i < count; i++)
1633      {
1634         tdm_layer *layer = tdm_output_get_layer(output, i, NULL);
1635         tdm_layer_capability capabilities = 0;
1636         EINA_SAFETY_ON_NULL_RETURN_VAL(layer, NULL);
1637
1638         tdm_layer_get_capabilities(layer, &capabilities);
1639         if (capabilities & TDM_LAYER_CAPABILITY_OVERLAY)
1640           {
1641 #ifdef CHECKING_PRIMARY_ZPOS
1642              int zpos = 0;
1643              tdm_layer_get_zpos(layer, &zpos);
1644              if (zpos >= primary_zpos) continue;
1645 #endif
1646              return layer;
1647           }
1648      }
1649
1650    return NULL;
1651 }
1652
1653 static E_Output *
1654 _e_comp_screen_eoutput_get_by_toutput(tdm_output *output)
1655 {
1656    Eina_List *l;
1657    E_Output *eo;
1658
1659    EINA_LIST_FOREACH(e_comp->e_comp_screen->outputs, l, eo)
1660       if (eo->toutput == output)
1661         return eo;
1662
1663    return NULL;
1664 }
1665
1666 E_API Eina_Bool
1667 e_comp_screen_available_video_formats_get(const tbm_format **formats, int *count)
1668 {
1669    E_Output *output;
1670    tdm_output *toutput;
1671    tdm_layer *layer;
1672    tdm_error error;
1673
1674    *count = 0;
1675
1676    if (e_comp_screen_pp_support())
1677      {
1678         error = tdm_display_get_pp_available_formats(e_comp->e_comp_screen->tdisplay, formats, count);
1679         if (error == TDM_ERROR_NONE)
1680           return EINA_TRUE;
1681      }
1682
1683    /* get the first output */
1684    toutput = tdm_display_get_output(e_comp->e_comp_screen->tdisplay, 0, NULL);
1685    if (!toutput)
1686      return EINA_FALSE;
1687
1688    output = _e_comp_screen_eoutput_get_by_toutput(toutput);
1689    if (!output)
1690      return EINA_FALSE;
1691
1692    if (e_hwc_policy_get(output->hwc) != E_HWC_POLICY_WINDOWS)
1693      {
1694         /* get the first suitable layer */
1695         layer = _e_comp_screen_video_tdm_layer_get(toutput);
1696         if (layer)
1697           {
1698              tdm_layer_get_available_formats(layer, formats, count);
1699           }
1700         else
1701           {
1702              *formats = sw_formats;
1703              *count = NUM_SW_FORMAT;
1704           }
1705      }
1706    else
1707      {
1708         error = tdm_hwc_get_video_supported_formats(output->hwc->thwc, formats, count);
1709         if (error != TDM_ERROR_NONE)
1710           {
1711              *formats = sw_formats;
1712              *count = NUM_SW_FORMAT;
1713           }
1714      }
1715
1716    return EINA_TRUE;
1717 }
1718
1719 EINTERN void *
1720 e_comp_screen_gbm_device_get(E_Comp_Screen *e_comp_screen)
1721 {
1722    int fd;
1723
1724    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, NULL);
1725
1726    if (e_comp_screen->gdevice) return e_comp_screen->gdevice;
1727
1728    fd = tbm_drm_helper_get_master_fd();
1729    EINA_SAFETY_ON_FALSE_RETURN_VAL(fd >= 0, NULL);
1730
1731    e_comp_screen->gdevice = gbm_create_device(fd);
1732    if (!e_comp_screen->gdevice)
1733      {
1734         ERR("fail to create gbm device");
1735         close(fd);
1736         return NULL;
1737      }
1738
1739    e_comp_screen->gdevice_fd = fd;
1740
1741    return e_comp_screen->gdevice;
1742 }
1743
1744 EINTERN Eina_Bool
1745 e_comp_screen_size_get(E_Comp_Screen *e_comp_screen, int *w, int *h)
1746 {
1747    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, EINA_FALSE);
1748
1749    if (w) *w = e_comp_screen->w;
1750    if (h) *h = e_comp_screen->h;
1751
1752    return EINA_TRUE;
1753 }
1754 static char *
1755 _e_comp_screen_dpms_to_string(E_OUTPUT_DPMS dpms)
1756 {
1757    switch (dpms)
1758      {
1759         case E_OUTPUT_DPMS_ON:
1760           return "DPMS_ON";
1761           break;
1762         case E_OUTPUT_DPMS_STANDBY:
1763           return "DPMS_STANDBY";
1764           break;
1765         case E_OUTPUT_DPMS_SUSPEND:
1766           return "DPMS_SUSPEND";
1767           break;
1768         case E_OUTPUT_DPMS_OFF:
1769           return "DPMS_OFF";
1770           break;
1771         default:
1772           return "Unknown";
1773      }
1774 }
1775
1776 EINTERN void
1777 e_comp_screen_debug_info_get(Eldbus_Message_Iter *iter)
1778 {
1779    Eldbus_Message_Iter *line_array;
1780    E_Comp_Screen *e_comp_screen = NULL;
1781    E_Output *output = NULL;
1782    E_Hwc *hwc = NULL;
1783    Eina_List *l;
1784    char info_str[1024];
1785
1786    e_comp_screen = e_comp->e_comp_screen;
1787
1788    eldbus_message_iter_arguments_append(iter, "as", &line_array);
1789    if (!e_comp_screen)
1790      {
1791         eldbus_message_iter_basic_append(line_array,
1792                                          's',
1793                                          "e_comp_screen not initialized..");
1794         eldbus_message_iter_container_close(iter, line_array);
1795         return;
1796      }
1797
1798    eldbus_message_iter_basic_append(line_array, 's',
1799    "===========================================================================================");
1800    eldbus_message_iter_basic_append(line_array, 's',
1801    " idx      id           status       dpms     (   x  ,   y  ) ( w    x    h ) ");
1802    eldbus_message_iter_basic_append(line_array, 's',
1803    "===========================================================================================");
1804
1805    EINA_LIST_FOREACH(e_comp_screen->outputs, l, output)
1806      {
1807         if (!output) continue;
1808         hwc = output->hwc;
1809         if (!output->hwc) continue;
1810         if (e_hwc_policy_get(hwc) == E_HWC_POLICY_NONE) continue;
1811
1812         snprintf(info_str, sizeof(info_str), "%2d %12s %15s %10s   (%5d , %5d) (%5d x %5d)",
1813                  output->index, output->id,
1814                  output->info.connected ? "connected" : "disconnected",
1815                  _e_comp_screen_dpms_to_string(output->dpms),
1816                  output->config.geom.x, output->config.geom.y,
1817                  output->config.geom.w, output->config.geom.h);
1818
1819         eldbus_message_iter_basic_append(line_array, 's', info_str);
1820      }
1821
1822    eldbus_message_iter_basic_append(line_array, 's',
1823    "===========================================================================================");
1824
1825    eldbus_message_iter_container_close(iter, line_array);
1826 }
1827
1828 E_API Eina_List *
1829 e_comp_screen_outputs_get(E_Comp_Screen *e_comp_screen)
1830 {
1831    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, NULL);
1832
1833    return e_comp_screen->outputs;
1834 }