0641fe8c2a74b8a5edab64dc313132b14e79dac8
[platform/upstream/enlightenment.git] / src / bin / e_comp_screen.c
1 #include "e.h"
2 #include <Ecore_Drm.h>
3
4 static Eina_List *event_handlers = NULL;
5 static Eina_Bool session_state = EINA_FALSE;
6
7 static Eina_Bool dont_set_ecore_drm_keymap = EINA_FALSE;
8 static Eina_Bool dont_use_xkb_cache = EINA_FALSE;
9
10 E_API int              E_EVENT_SCREEN_CHANGE = 0;
11
12 typedef struct _E_Comp_Screen_Tzsr
13 {
14    struct wl_resource *resource; /* tizen_screen_rotation */
15    E_Client           *ec;
16 } E_Comp_Screen_Tzsr;
17
18 static Eina_List *tzsr_list;
19 static E_Client_Hook *tzsr_client_hook_del;
20
21 static E_Comp_Screen_Tzsr*
22 _tz_surface_rotation_find(E_Client *ec)
23 {
24    E_Comp_Screen_Tzsr *tzsr;
25    Eina_List *l;
26
27    EINA_LIST_FOREACH(tzsr_list, l, tzsr)
28      {
29         if (tzsr->ec == ec)
30           return tzsr;
31      }
32
33    return NULL;
34 }
35
36 static void
37 _tz_surface_rotation_free(E_Comp_Screen_Tzsr *tzsr)
38 {
39    ELOGF("COMP", "|tzsr(%p)", NULL, tzsr->ec, tzsr);
40    tzsr_list = eina_list_remove(tzsr_list, tzsr);
41    free(tzsr);
42 }
43
44 static void
45 _tz_screen_rotation_cb_client_del(void *data, E_Client *ec)
46 {
47    E_Comp_Screen_Tzsr *tzsr = _tz_surface_rotation_find(ec);
48    if (!tzsr) return;
49    _tz_surface_rotation_free(tzsr);
50 }
51
52 static void
53 _tz_screen_rotation_get_ignore_output_transform(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface)
54 {
55    E_Comp_Screen_Tzsr *tzsr;
56    E_Client *ec;
57
58    ec = wl_resource_get_user_data(surface);
59    EINA_SAFETY_ON_NULL_RETURN(ec);
60
61    tzsr = _tz_surface_rotation_find(ec);
62    if (tzsr) return;
63
64    tzsr = E_NEW(E_Comp_Screen_Tzsr, 1);
65    if (!tzsr)
66      {
67         wl_client_post_no_memory(client);
68         return;
69      }
70
71    tzsr->resource = resource;
72    tzsr->ec = ec;
73
74    ELOGF("COMP", "|tzsr(%p)", NULL, ec, tzsr);
75
76    tzsr_list = eina_list_append(tzsr_list, tzsr);
77 }
78
79 static const struct tizen_screen_rotation_interface _tz_screen_rotation_interface =
80 {
81    _tz_screen_rotation_get_ignore_output_transform,
82 };
83
84 static void
85 _tz_screen_rotation_cb_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
86 {
87    struct wl_resource *res;
88
89    if (!(res = wl_resource_create(client, &tizen_screen_rotation_interface, version, id)))
90      {
91         ERR("Could not create tizen_screen_rotation resource: %m");
92         wl_client_post_no_memory(client);
93         return;
94      }
95
96    wl_resource_set_implementation(res, &_tz_screen_rotation_interface, NULL, NULL);
97 }
98
99 static char *
100 _layer_cap_to_str(tdm_layer_capability caps, tdm_layer_capability cap)
101 {
102    if (caps & cap)
103      {
104         if (cap == TDM_LAYER_CAPABILITY_CURSOR) return "cursor ";
105         else if (cap == TDM_LAYER_CAPABILITY_PRIMARY) return "primary ";
106         else if (cap == TDM_LAYER_CAPABILITY_OVERLAY) return "overlay ";
107         else if (cap == TDM_LAYER_CAPABILITY_GRAPHIC) return "graphics ";
108         else if (cap == TDM_LAYER_CAPABILITY_VIDEO) return "video ";
109         else if (cap == TDM_LAYER_CAPABILITY_TRANSFORM) return "transform ";
110         else if (cap == TDM_LAYER_CAPABILITY_RESEVED_MEMORY) return "reserved_memory ";
111         else if (cap == TDM_LAYER_CAPABILITY_NO_CROP) return "no_crop ";
112         else return "unkown";
113      }
114    return "";
115 }
116
117 static Eina_Bool
118 _e_comp_screen_cb_activate(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
119 {
120    Ecore_Drm_Event_Activate *e;
121
122    if (!(e = event)) goto end;
123
124    if (e->active)
125      {
126         E_Client *ec;
127
128         if (session_state) goto end;
129         session_state = EINA_TRUE;
130
131         ecore_evas_show(e_comp->ee);
132         E_CLIENT_FOREACH(ec)
133           {
134              if (ec->visible && (!ec->input_only))
135                e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
136           }
137         e_comp_render_queue();
138         e_comp_shape_queue_block(0);
139         ecore_event_add(E_EVENT_COMPOSITOR_ENABLE, NULL, NULL, NULL);
140      }
141    else
142      {
143         session_state = EINA_FALSE;
144         ecore_evas_hide(e_comp->ee);
145         edje_file_cache_flush();
146         edje_collection_cache_flush();
147         evas_image_cache_flush(e_comp->evas);
148         evas_font_cache_flush(e_comp->evas);
149         evas_render_dump(e_comp->evas);
150
151         e_comp_render_queue();
152         e_comp_shape_queue_block(1);
153         ecore_event_add(E_EVENT_COMPOSITOR_DISABLE, NULL, NULL, NULL);
154      }
155
156 end:
157    return ECORE_CALLBACK_PASS_ON;
158 }
159
160 #if 0
161 static Eina_Bool
162 _e_comp_screen_cb_output_drm(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
163 {
164    const Eina_List *l;
165    E_Output *output;
166    Ecore_Drm_Event_Output *e;
167    E_Comp_Screen *e_comp_screen = NULL;
168
169    if (!(e = event)) goto end;
170    if (!e_comp) goto end;
171    if (!e_comp->e_comp_screen) goto end;
172
173    e_comp_screen = e_comp->e_comp_screen;
174
175    DBG("WL_DRM OUTPUT CHANGE");
176
177    EINA_LIST_FOREACH(e_comp_screen->outputs, l, output)
178      {
179         if ((!strcmp(output->info.name, e->name)) &&
180             (!strcmp(output->info.screen, e->model)))
181           {
182              if (e->plug)
183                {
184                   if (!e_comp_wl_output_init(output->id, e->make, e->model,
185                                              e->x, e->y, e->w, e->h,
186                                              e->phys_width, e->phys_height,
187                                              e->refresh, e->subpixel_order,
188                                              e->transform))
189                     {
190                        ERR("Could not setup new output: %s", output->id);
191                     }
192                }
193              else
194                e_comp_wl_output_remove(output->id);
195
196              break;
197           }
198      }
199
200    /* previous calculation of e_scale gave unsuitable value because
201     * there were no sufficient information to calculate dpi.
202     * so it's considerable to re-calculate e_scale with output geometry.
203     */
204    double target_inch;
205    int dpi;
206
207    target_inch = (round((sqrt(e->phys_width * e->phys_width + e->phys_height * e->phys_height) / 25.4) * 10) / 10);
208    dpi = (round((sqrt(e->w * e->w + e->h * e->h) / target_inch) * 10) / 10);
209
210    e_scale_manual_update(dpi);
211
212 end:
213    return ECORE_CALLBACK_PASS_ON;
214 }
215 #endif
216
217 static Eina_Bool
218 _e_comp_screen_commit_idle_cb(void *data EINA_UNUSED)
219 {
220    Eina_List *l, *ll;
221    E_Comp_Screen *e_comp_screen = NULL;
222    E_Output *output = NULL;
223
224    if (!e_comp->e_comp_screen) goto end;
225
226    e_comp_screen = e_comp->e_comp_screen;
227
228    EINA_LIST_FOREACH_SAFE(e_comp_screen->outputs, l, ll, output)
229      {
230         if (!output) continue;
231         if (!output->config.enabled) continue;
232
233         if (!e_output_commit(output))
234              ERR("fail to commit e_comp_screen->outputs.");
235
236         if (!e_output_render(output))
237              ERR("fail to render e_comp_screen->outputs.");
238
239      }
240
241 end:
242    return ECORE_CALLBACK_RENEW;
243 }
244
245 static Eina_Bool
246 _e_comp_screen_cb_input_device_add(void *data, int type, void *event)
247 {
248    Ecore_Drm_Event_Input_Device_Add *e;
249    E_Comp *comp = data;
250
251    if (!(e = event)) goto end;
252
253    if (e->caps & EVDEV_SEAT_POINTER)
254      {
255         if (comp->wl_comp_data->ptr.num_devices == 0)
256           {
257              e_pointer_object_set(comp->pointer, NULL, 0, 0);
258              e_comp_wl_input_pointer_enabled_set(EINA_TRUE);
259           }
260         comp->wl_comp_data->ptr.num_devices++;
261      }
262    if (e->caps & EVDEV_SEAT_KEYBOARD)
263      {
264         comp->wl_comp_data->kbd.num_devices++;
265         e_comp_wl_input_keyboard_enabled_set(EINA_TRUE);
266      }
267    if (e->caps & EVDEV_SEAT_TOUCH)
268      {
269         e_comp_wl_input_touch_enabled_set(EINA_TRUE);
270         comp->wl_comp_data->touch.num_devices++;
271      }
272
273 end:
274    return ECORE_CALLBACK_PASS_ON;
275 }
276
277 static Eina_Bool
278 _e_comp_screen_cb_input_device_del(void *data, int type, void *event)
279 {
280    Ecore_Drm_Event_Input_Device_Del *e;
281    E_Comp *comp = data;
282
283    if (!(e = event)) goto end;
284
285    if (e->caps & EVDEV_SEAT_POINTER)
286      {
287         comp->wl_comp_data->ptr.num_devices--;
288         if (comp->wl_comp_data->ptr.num_devices == 0)
289           {
290              e_comp_wl_input_pointer_enabled_set(EINA_FALSE);
291              e_pointer_object_set(comp->pointer, NULL, 0, 0);
292              e_pointer_hide(e_comp->pointer);
293           }
294      }
295
296 end:
297
298    return ECORE_CALLBACK_PASS_ON;
299 }
300
301 static void
302 _e_comp_screen_cb_ee_resize(Ecore_Evas *ee EINA_UNUSED)
303 {
304    e_comp_canvas_update();
305 }
306
307 static E_Comp_Screen *
308 _e_comp_screen_new(E_Comp *comp)
309 {
310    E_Comp_Screen *e_comp_screen = NULL;
311    tdm_error error = TDM_ERROR_NONE;
312
313    e_comp_screen = E_NEW(E_Comp_Screen, 1);
314    if (!e_comp_screen) return NULL;
315
316    /* tdm display init */
317    e_comp_screen->tdisplay = tdm_display_init(&error);
318    if (!e_comp_screen->tdisplay)
319      {
320         ERR("fail to get tdm_display\n");
321         free(e_comp_screen);
322         return NULL;
323      }
324
325    if (e_comp_socket_init("tdm-socket"))
326      PRCTL("[Winsys] change permission and create sym link for %s", "tdm-socket");
327
328    return e_comp_screen;
329 }
330
331 static void
332 _e_comp_screen_del(E_Comp_Screen *e_comp_screen)
333 {
334    if (!e_comp_screen) return;
335
336    if (e_comp_screen->tdisplay) tdm_display_deinit(e_comp_screen->tdisplay);
337
338    free(e_comp_screen);
339 }
340
341 static void
342 _e_comp_screen_deinit_outputs(E_Comp_Screen *e_comp_screen)
343 {
344    E_Output *output;
345
346    // free up e_outputs
347    EINA_LIST_FREE(e_comp_screen->outputs, output)
348      {
349         e_output_del(output);
350      }
351
352    e_output_shutdown();
353 }
354
355 static Eina_Bool
356 _e_comp_screen_init_outputs(E_Comp_Screen *e_comp_screen)
357 {
358    E_Output *output = NULL;
359    E_Output_Mode *mode = NULL;
360    tdm_display *tdisplay = e_comp_screen->tdisplay;
361    int num_outputs;
362    int i;
363    Eina_Bool scale_updated = EINA_FALSE;
364
365    /* init e_output */
366    if (!e_output_init())
367      {
368         ERR("fail to e_output_init.");
369         return EINA_FALSE;
370      }
371
372    /* get the num of outputs */
373    tdm_display_get_output_count(tdisplay, &num_outputs);
374    if (num_outputs < 1)
375      {
376         ERR("fail to get tdm_display_get_output_count\n");
377         return EINA_FALSE;
378      }
379    e_comp_screen->num_outputs = num_outputs;
380
381    INF("E_COMP_SCREEN: num_outputs = %i", e_comp_screen->num_outputs);
382
383    for (i = 0; i < num_outputs; i++)
384      {
385         output = e_output_new(e_comp_screen, i);
386         if (!output) goto fail;
387
388         if (!e_output_update(output))
389           {
390             ERR("fail to e_output_update.");
391             goto fail;
392           }
393
394         e_comp_screen->outputs = eina_list_append(e_comp_screen->outputs, output);
395
396         if (!e_output_connected(output)) continue;
397
398         /* setting with the best mode and enable the output */
399         mode = e_output_best_mode_find(output);
400         if (!mode)
401           {
402              ERR("fail to get best mode.");
403              goto fail;
404           }
405
406         if (!e_output_mode_apply(output, mode))
407           {
408              ERR("fail to e_output_mode_apply.");
409              goto fail;
410           }
411         if (!e_output_dpms_set(output, E_OUTPUT_DPMS_ON))
412           {
413              ERR("fail to e_output_dpms.");
414              goto fail;
415           }
416
417         /* update e_scale with first available output size */
418         if ((e_config->scale.for_tdm) && (!scale_updated))
419           {
420              double target_inch;
421              int dpi;
422
423              target_inch = (round((sqrt(output->info.size.w * output->info.size.w + output->info.size.h * output->info.size.h) / 25.4) * 10) / 10);
424              dpi = (round((sqrt(mode->w * mode->w + mode->h * mode->h) / target_inch) * 10) / 10);
425
426              e_scale_manual_update(dpi);
427              scale_updated = EINA_TRUE;
428           }
429      }
430
431    //TODO: if there is no output connected, make the fake output which is connected.
432
433
434    return EINA_TRUE;
435 fail:
436    _e_comp_screen_deinit_outputs(e_comp_screen);
437
438    return EINA_FALSE;
439 }
440
441 static Eina_Bool
442 _drm_read_pixels(E_Comp_Wl_Output *output, void *pixels)
443 {
444    Ecore_Drm_Device *dev;
445    Ecore_Drm_Fb *fb = NULL;
446    const Eina_List *drm_devs, *l;
447    int i = 0, bstride;
448    unsigned char *s, *d = pixels;
449
450    drm_devs = ecore_drm_devices_get();
451    EINA_LIST_FOREACH(drm_devs, l, dev)
452      {
453         fb = dev->next;
454         if (!fb) fb = dev->current;
455         if (fb) break;
456      }
457
458    if (!fb) return EINA_FALSE;
459
460    bstride = output->w * sizeof(int);
461
462    for (i = output->y; i < output->y + output->h; i++)
463      {
464         s = fb->mmap;
465         s += (fb->stride * i) + (output->x * sizeof(int));
466         memcpy(d, s, (output->w * sizeof(int)));
467         d += bstride;
468      }
469
470    return EINA_TRUE;
471 }
472
473 E_API void
474 _e_comp_screen_keymap_set(struct xkb_context **ctx, struct xkb_keymap **map)
475 {
476    char *keymap_path = NULL;
477    struct xkb_context *context;
478    struct xkb_keymap *keymap;
479    struct xkb_rule_names names = {0,};
480    const char* default_rules, *default_model, *default_layout, *default_variant, *default_options;
481
482    TRACE_INPUT_BEGIN(_e_comp_screen_keymap_set);
483
484    context = xkb_context_new(0);
485    EINA_SAFETY_ON_NULL_RETURN(context);
486
487    /* assemble xkb_rule_names so we can fetch keymap */
488    memset(&names, 0, sizeof(names));
489
490    default_rules = e_comp_wl_input_keymap_default_rules_get();
491    default_model = e_comp_wl_input_keymap_default_model_get();
492    default_layout = e_comp_wl_input_keymap_default_layout_get();
493    default_variant = e_comp_wl_input_keymap_default_variant_get();
494    default_options = e_comp_wl_input_keymap_default_options_get();
495
496    names.rules = strdup(default_rules);
497    names.model = strdup(default_model);
498    names.layout = strdup(default_layout);
499    if (default_variant) names.variant = strdup(default_variant);
500    if (default_options) names.options = strdup(default_options);
501
502    keymap = e_comp_wl_input_keymap_compile(context, names, &keymap_path);
503    eina_stringshare_del(keymap_path);
504    EINA_SAFETY_ON_NULL_GOTO(keymap, cleanup);
505
506    *ctx = context;
507    *map = keymap;
508
509    if (dont_set_ecore_drm_keymap == EINA_FALSE)
510      {
511         ecore_drm_device_keyboard_cached_context_set(*ctx);
512         ecore_drm_device_keyboard_cached_keymap_set(*map);
513      }
514
515 cleanup:
516    free((char *)names.rules);
517    free((char *)names.model);
518    free((char *)names.layout);
519    if (names.variant) free((char *)names.variant);
520    if (names.options) free((char *)names.options);
521
522    TRACE_INPUT_END();
523 }
524
525 static int
526 _e_comp_screen_e_screen_sort_cb(const void *data1, const void *data2)
527 {
528    const E_Output *s1 = data1, *s2 = data2;
529    int dif;
530
531    dif = -(s1->config.priority - s2->config.priority);
532    if (dif == 0)
533      {
534         dif = s1->config.geom.x - s2->config.geom.x;
535         if (dif == 0)
536           dif = s1->config.geom.y - s2->config.geom.y;
537      }
538    return dif;
539 }
540
541 static void
542 _e_comp_screen_e_screen_free(E_Screen *scr)
543 {
544    free(scr->id);
545    free(scr);
546 }
547
548 static void
549 _e_comp_screen_e_screens_set(E_Comp_Screen *e_comp_screen, Eina_List *screens)
550 {
551    E_FREE_LIST(e_comp_screen->e_screens, _e_comp_screen_e_screen_free);
552    e_comp_screen->e_screens = screens;
553 }
554
555 static void
556 _e_comp_screen_engine_deinit(void)
557 {
558    if (!e_comp) return;
559    if (!e_comp->e_comp_screen) return;
560
561    _e_comp_screen_deinit_outputs(e_comp->e_comp_screen);
562    _e_comp_screen_del(e_comp->e_comp_screen);
563    e_comp->e_comp_screen = NULL;
564 }
565
566 static Eina_Bool
567 _e_comp_screen_engine_init(void)
568 {
569    E_Comp_Screen *e_comp_screen = NULL;
570    int w = 0, h = 0, scr_w = 1, scr_h = 1;
571    int screen_rotation;
572    char buf[1024];
573    E_Output *output = NULL;
574
575    INF("ecore evase engine init with TDM. HWC.");
576
577    /* check the screen rotation */
578    screen_rotation = (e_config->screen_rotation_pre + e_config->screen_rotation_setting) % 360;
579
580    INF("E_COMP_SCREEN: screen_rotation_pre %d and screen_rotation_setting %d",
581        e_config->screen_rotation_pre, e_config->screen_rotation_setting);
582
583    /* set env for use tbm_surface_queue*/
584    setenv("USE_EVAS_SOFTWARE_TBM_ENGINE", "1", 1);
585
586    /* set gl available if we have ecore_evas support */
587    if (ecore_evas_engine_type_supported_get(ECORE_EVAS_ENGINE_OPENGL_DRM))
588      e_comp_gl_set(EINA_TRUE);
589
590    /* e_comp_screen new */
591    e_comp_screen = _e_comp_screen_new(e_comp);
592    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, EINA_FALSE);
593
594    e_comp->e_comp_screen = e_comp_screen;
595    e_comp_screen->rotation = screen_rotation;
596
597    e_main_ts("\tE_Outputs Init");
598    if (!_e_comp_screen_init_outputs(e_comp_screen))
599      {
600         e_error_message_show(_("Enlightenment cannot initialize outputs!\n"));
601         _e_comp_screen_engine_deinit();
602         return EINA_FALSE;
603      }
604    e_main_ts("\tE_Outputs Init Done");
605
606    /* get the primary output */
607    output = e_comp_screen_primary_output_get(e_comp_screen);
608    if (!output)
609      {
610         e_error_message_show(_("Fail to get the primary output!\n"));
611         _e_comp_screen_engine_deinit();
612         return EINA_FALSE;
613      }
614
615    /* get the size of the primary output */
616    e_output_size_get(output, &scr_w, &scr_h);
617
618    INF("GL available:%d config engine:%d screen size:%dx%d",
619        e_comp_gl_get(), e_comp_config_get()->engine, scr_w, scr_h);
620
621    if ((e_comp_gl_get()) &&
622        (e_comp_config_get()->engine == E_COMP_ENGINE_GL))
623      {
624         e_main_ts("\tEE_GL_DRM New");
625         e_comp->ee = ecore_evas_gl_drm_new(NULL, 0, 0, 0, scr_w, scr_h);
626         snprintf(buf, sizeof(buf), "\tEE_GL_DRM New Done %p %dx%d", e_comp->ee, scr_w, scr_h);
627         e_main_ts(buf);
628
629         if (!e_comp->ee)
630           e_comp_gl_set(EINA_FALSE);
631         else
632           {
633              Evas_GL *evasgl = NULL;
634              Evas_GL_API *glapi = NULL;
635
636              e_main_ts("\tEvas_GL New");
637              evasgl = evas_gl_new(ecore_evas_get(e_comp->ee));
638              if (evasgl)
639                {
640                   glapi = evas_gl_api_get(evasgl);
641                   if (!((glapi) && (glapi->evasglBindWaylandDisplay)))
642                     {
643                        e_comp_gl_set(EINA_FALSE);
644                        ecore_evas_free(e_comp->ee);
645                        e_comp->ee = NULL;
646                        e_main_ts("\tEvas_GL New Failed 1");
647                     }
648                   else
649                     {
650                        e_main_ts("\tEvas_GL New Done");
651                     }
652                }
653              else
654                {
655                   e_comp_gl_set(EINA_FALSE);
656                   ecore_evas_free(e_comp->ee);
657                   e_comp->ee = NULL;
658                   e_main_ts("\tEvas_GL New Failed 2");
659                }
660              evas_gl_free(evasgl);
661           }
662      }
663
664    /* fallback to framebuffer drm (non-accel) */
665    if (!e_comp->ee)
666      {
667         e_main_ts("\tEE_DRM New");
668         e_comp->ee = ecore_evas_drm_new(NULL, 0, 0, 0, scr_w, scr_h);
669         snprintf(buf, sizeof(buf), "\tEE_DRM New Done %p %dx%d", e_comp->ee, scr_w, scr_h);
670         e_main_ts(buf);
671      }
672
673    if (!e_comp->ee)
674      {
675         e_error_message_show(_("Enlightenment cannot initialize outputs!\n"));
676         _e_comp_screen_engine_deinit();
677         return EINA_FALSE;
678      }
679
680    ecore_evas_data_set(e_comp->ee, "comp", e_comp);
681
682    ecore_evas_callback_resize_set(e_comp->ee, _e_comp_screen_cb_ee_resize);
683
684    if (screen_rotation)
685      {
686         /* SHOULD called with resize option after ecore_evas_resize */
687         ecore_evas_rotation_with_resize_set(e_comp->ee, screen_rotation);
688         ecore_evas_geometry_get(e_comp->ee, NULL, NULL, &w, &h);
689
690         snprintf(buf, sizeof(buf), "\tEE Rotate and Resize %d, %dx%d", screen_rotation, w, h);
691         e_main_ts(buf);
692      }
693
694    if (!E_EVENT_SCREEN_CHANGE) E_EVENT_SCREEN_CHANGE = ecore_event_type_new();
695
696    ecore_event_add(E_EVENT_SCREEN_CHANGE, NULL, NULL, NULL);
697
698    e_comp_screen_e_screens_setup(e_comp_screen, -1, -1);
699
700    /* TODO: need the output changed handler with TDM */
701    //E_LIST_HANDLER_APPEND(event_handlers, ECORE_DRM_EVENT_OUTPUT,        _e_comp_screen_cb_output_drm,       comp);
702
703    /* update the screen, outputs and planes at the idle enterer of the ecore_loop */
704    ecore_idle_enterer_add(_e_comp_screen_commit_idle_cb, e_comp);
705
706    return EINA_TRUE;
707 }
708
709 EINTERN void
710 e_comp_screen_e_screens_setup(E_Comp_Screen *e_comp_screen, int rw, int rh)
711 {
712    int i;
713    E_Screen *screen;
714    Eina_List *outputs = NULL, *outputs_rem;
715    Eina_List *e_screens = NULL;
716    Eina_List *l, *ll;
717    E_Output *output, *s2, *s_chosen;
718    Eina_Bool removed;
719
720    if (!e_comp_screen->outputs) goto out;
721    // put screens in tmp list
722    EINA_LIST_FOREACH(e_comp_screen->outputs, l, output)
723      {
724         if ((output->config.enabled) &&
725             (output->config.geom.w > 0) &&
726             (output->config.geom.h > 0))
727           {
728              outputs = eina_list_append(outputs, output);
729           }
730      }
731    // remove overlapping screens - if a set of screens overlap, keep the
732    // smallest/lowest res
733    do
734      {
735         removed = EINA_FALSE;
736
737         EINA_LIST_FOREACH(outputs, l, output)
738           {
739              outputs_rem = NULL;
740
741              EINA_LIST_FOREACH(l->next, ll, s2)
742                {
743                   if (E_INTERSECTS(output->config.geom.x, output->config.geom.y,
744                                    output->config.geom.w, output->config.geom.h,
745                                    s2->config.geom.x, s2->config.geom.y,
746                                    s2->config.geom.w, s2->config.geom.h))
747                     {
748                        if (!outputs_rem)
749                          outputs_rem = eina_list_append(outputs_rem, output);
750                        outputs_rem = eina_list_append(outputs_rem, s2);
751                     }
752                }
753              // we have intersecting screens - choose the lowest res one
754              if (outputs_rem)
755                {
756                   removed = EINA_TRUE;
757                   // find the smallest screen (chosen one)
758                   s_chosen = NULL;
759                   EINA_LIST_FOREACH(outputs_rem, ll, s2)
760                     {
761                        if (!s_chosen) s_chosen = s2;
762                        else
763                          {
764                             if ((s_chosen->config.geom.w *
765                                  s_chosen->config.geom.h) >
766                                 (s2->config.geom.w *
767                                  s2->config.geom.h))
768                               s_chosen = s2;
769                          }
770                     }
771                   // remove all from screens but the chosen one
772                   EINA_LIST_FREE(outputs_rem, s2)
773                     {
774                        if (s2 != s_chosen)
775                          outputs = eina_list_remove_list(outputs, l);
776                     }
777                   // break our list walk and try again
778                   break;
779                }
780           }
781      }
782    while (removed);
783    // sort screens by priority etc.
784    outputs = eina_list_sort(outputs, 0, _e_comp_screen_e_screen_sort_cb);
785    i = 0;
786    EINA_LIST_FOREACH(outputs, l, output)
787      {
788         screen = E_NEW(E_Screen, 1);
789         screen->escreen = screen->screen = i;
790         screen->x = output->config.geom.x;
791         screen->y = output->config.geom.y;
792
793         if (output->config.rotation % 180)
794           {
795              screen->w = output->config.geom.h;
796              screen->h = output->config.geom.w;
797           }
798         else
799           {
800              screen->w = output->config.geom.w;
801              screen->h = output->config.geom.h;
802           }
803
804         if (output->id) screen->id = strdup(output->id);
805
806         e_screens = eina_list_append(e_screens, screen);
807         INF("E INIT: SCREEN: [%i][%i], %ix%i+%i+%i",
808             i, i, screen->w, screen->h, screen->x, screen->y);
809         i++;
810      }
811    eina_list_free(outputs);
812    // if we have NO screens at all (above - i will be 0) AND we have no
813    // existing screens set up in xinerama - then just say root window size
814    // is the entire screen. this should handle the case where you unplug ALL
815    // screens from an existing setup (unplug external monitors and/or close
816    // laptop lid), in which case as long as at least one screen is configured
817    // in xinerama, it will be left-as is until next time we re-eval screen
818    // setup and have at least one screen
819    printf("e_comp_screen_e_screens_setup............... %i %p\n", i, e_comp_screen->e_screens);
820    if ((i == 0) && (!e_comp_screen->e_screens))
821      {
822 out:
823         screen = E_NEW(E_Screen, 1);
824         screen->escreen = screen->screen = 0;
825         screen->x = 0;
826         screen->y = 0;
827         if ((rw > 0) && (rh > 0))
828           screen->w = rw, screen->h = rh;
829         else
830           {
831              if (e_comp_screen->rotation % 180)
832                ecore_evas_screen_geometry_get(e_comp->ee, NULL, NULL, &screen->h, &screen->w);
833              else
834                ecore_evas_screen_geometry_get(e_comp->ee, NULL, NULL, &screen->w, &screen->h);
835           }
836         e_screens = eina_list_append(e_screens, screen);
837      }
838    _e_comp_screen_e_screens_set(e_comp_screen, e_screens);
839 }
840
841 EINTERN const Eina_List *
842 e_comp_screen_e_screens_get(E_Comp_Screen *e_comp_screen)
843 {
844    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, NULL);
845
846    return e_comp_screen->e_screens;
847 }
848
849 E_API Eina_Bool
850 e_comp_screen_init()
851 {
852    E_Comp *comp;
853    int w, h;
854    struct xkb_context *ctx = NULL;
855    struct xkb_keymap *map = NULL;
856
857    TRACE_DS_BEGIN(E_COMP_SCREEN:INIT);
858    if (!(comp = e_comp))
859      {
860         TRACE_DS_END();
861         EINA_SAFETY_ON_NULL_RETURN_VAL(comp, EINA_FALSE);
862      }
863
864    if (!_e_comp_screen_engine_init())
865      {
866         ERR("Could not initialize the ecore_evas engine.");
867         goto failed_comp_screen;
868      }
869
870    e_main_ts("\tE_Comp_Wl Init");
871    if (!e_comp_wl_init())
872      {
873         goto failed_comp_screen;
874      }
875    e_main_ts("\tE_Comp_Wl Init Done");
876
877    /* get the current screen geometry */
878    ecore_evas_screen_geometry_get(e_comp->ee, NULL, NULL, &w, &h);
879
880    /* canvas */
881    e_main_ts("\tE_Comp_Canvas Init");
882    if (!e_comp_canvas_init(w, h))
883      {
884         e_error_message_show(_("Enlightenment cannot initialize outputs!\n"));
885         goto failed_comp_screen;
886      }
887    e_main_ts("\tE_Comp_Canvas Init Done");
888
889    e_comp_wl->screenshooter.read_pixels = _drm_read_pixels;
890
891    /* pointer */
892    ecore_evas_pointer_xy_get(e_comp->ee,
893                              &e_comp_wl->ptr.x,
894                              &e_comp_wl->ptr.y);
895
896    evas_event_feed_mouse_in(e_comp->evas, 0, NULL);
897
898    e_main_ts("\tE_Pointer New");
899    if ((comp->pointer = e_pointer_canvas_new(comp->ee, EINA_TRUE)))
900      {
901         e_pointer_hide(comp->pointer);
902
903         if (comp->e_comp_screen->rotation)
904           {
905              const Eina_List *l;
906              Ecore_Drm_Device *dev;
907              EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
908                ecore_drm_device_pointer_rotation_set(dev, comp->e_comp_screen->rotation);
909           }
910      }
911    e_main_ts("\tE_Pointer New Done");
912
913    /* keymap */
914    dont_set_ecore_drm_keymap = getenv("NO_ECORE_DRM_KEYMAP_CACHE") ? EINA_TRUE : EINA_FALSE;
915    dont_use_xkb_cache = getenv("NO_KEYMAP_CACHE") ? EINA_TRUE : EINA_FALSE;
916
917    if (e_config->xkb.use_cache && !dont_use_xkb_cache)
918      {
919         e_main_ts("\tDRM Keymap Init");
920         _e_comp_screen_keymap_set(&ctx, &map);
921         e_main_ts("\tDRM Keymap Init Done");
922      }
923
924    /* FIXME: We need a way to trap for user changing the keymap inside of E
925     *        without the event coming from X11 */
926
927    /* FIXME: We should make a decision here ...
928     *
929     * Fetch the keymap from drm, OR set this to what the E config is....
930     */
931
932    /* FIXME: This is just for testing at the moment....
933     * happens to jive with what drm does */
934    e_main_ts("\tE_Comp_WL Keymap Init");
935    e_comp_wl_input_keymap_set(e_comp_wl_input_keymap_default_rules_get(),
936                               e_comp_wl_input_keymap_default_model_get(),
937                               e_comp_wl_input_keymap_default_layout_get(),
938                               e_comp_wl_input_keymap_default_variant_get(),
939                               e_comp_wl_input_keymap_default_options_get(),
940                               ctx, map);
941    e_main_ts("\tE_Comp_WL Keymap Init Done");
942
943    /* try to add tizen_video to wayland globals */
944    if (!wl_global_create(e_comp_wl->wl.disp, &tizen_screen_rotation_interface, 1,
945                          NULL, _tz_screen_rotation_cb_bind))
946      {
947         ERR("Could not add tizen_screen_rotation to wayland globals");
948         goto failed_comp_screen;
949      }
950
951    /* this setup function is called after e_comp_canvas_init */
952    if (!e_comp_screen_setup(e_comp->e_comp_screen))
953      {
954         ERR("fail to e_comp_screen_setup");
955         return EINA_FALSE;
956      }
957
958    tzsr_client_hook_del = e_client_hook_add(E_CLIENT_HOOK_DEL, _tz_screen_rotation_cb_client_del, NULL);
959
960    E_LIST_HANDLER_APPEND(event_handlers, ECORE_DRM_EVENT_ACTIVATE,         _e_comp_screen_cb_activate,         comp);
961    E_LIST_HANDLER_APPEND(event_handlers, ECORE_DRM_EVENT_INPUT_DEVICE_ADD, _e_comp_screen_cb_input_device_add, comp);
962    E_LIST_HANDLER_APPEND(event_handlers, ECORE_DRM_EVENT_INPUT_DEVICE_DEL, _e_comp_screen_cb_input_device_del, comp);
963
964    TRACE_DS_END();
965
966    return EINA_TRUE;
967
968 failed_comp_screen:
969
970    _e_comp_screen_engine_deinit();
971
972    TRACE_DS_END();
973
974    return EINA_FALSE;
975 }
976
977 E_API void
978 e_comp_screen_shutdown()
979 {
980    if (!e_comp) return;
981    if (!e_comp->e_comp_screen) return;
982
983    /* shutdown ecore_drm */
984    /* ecore_drm_shutdown(); */
985
986    _e_comp_screen_deinit_outputs(e_comp->e_comp_screen);
987
988    e_client_hook_del(tzsr_client_hook_del);
989    tzsr_client_hook_del = NULL;
990
991    dont_set_ecore_drm_keymap = EINA_FALSE;
992    dont_use_xkb_cache = EINA_FALSE;
993    E_FREE_LIST(event_handlers, ecore_event_handler_del);
994
995    /* delete e_comp_sreen */
996    _e_comp_screen_del(e_comp->e_comp_screen);
997    e_comp->e_comp_screen = NULL;
998 }
999
1000 EINTERN Eina_Bool
1001 e_comp_screen_setup(E_Comp_Screen *e_comp_screen)
1002 {
1003    Eina_List *l, *ll;
1004    E_Output *output = NULL;
1005
1006    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, EINA_FALSE);
1007
1008    EINA_LIST_FOREACH_SAFE(e_comp_screen->outputs, l, ll, output)
1009      {
1010         if (!output) continue;
1011         if (!output->config.enabled) continue;
1012
1013         if (!e_output_setup(output))
1014           {
1015              ERR("fail to e_ouptut_hwc_setup.");
1016              continue;
1017           }
1018      }
1019
1020    return EINA_TRUE;
1021 }
1022
1023 E_API Eina_Bool
1024 e_comp_screen_rotation_setting_set(E_Comp_Screen *e_comp_screen, int rotation)
1025 {
1026    E_Output *output = NULL, *o;
1027    Eina_List *l;
1028    const Eina_List *ll;
1029    int w, h;
1030    int screen_rotation;
1031    Ecore_Drm_Device *dev;
1032
1033    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, EINA_FALSE);
1034    EINA_SAFETY_ON_TRUE_RETURN_VAL(rotation % 90, EINA_FALSE);
1035    EINA_SAFETY_ON_TRUE_RETURN_VAL(rotation < 0, EINA_FALSE);
1036    EINA_SAFETY_ON_TRUE_RETURN_VAL(rotation > 270, EINA_FALSE);
1037
1038    if (e_config->screen_rotation_setting == rotation) return EINA_TRUE;
1039
1040    EINA_LIST_FOREACH(e_comp_screen->outputs, l, o)
1041      {
1042         unsigned int pipe = 0;
1043         tdm_error error;
1044
1045         error = tdm_output_get_pipe(o->toutput, &pipe);
1046         if (error != TDM_ERROR_NONE || pipe != 0)
1047           continue;
1048
1049         output = o;
1050         break;
1051      }
1052
1053    if (!output)
1054      {
1055         ERR("couldn't find the primary output");
1056         return EINA_FALSE;
1057      }
1058
1059    screen_rotation = (e_config->screen_rotation_pre + rotation) % 360;
1060
1061    if (!e_output_rotate(output, screen_rotation))
1062      return EINA_FALSE;
1063
1064    /* TODO: need to save e_config->screen_rotation_setting to e_config data file */
1065    e_config->screen_rotation_setting = rotation;
1066    e_comp_screen->rotation = screen_rotation;
1067
1068    ecore_evas_rotation_with_resize_set(e_comp->ee, e_comp_screen->rotation);
1069    ecore_evas_geometry_get(e_comp->ee, NULL, NULL, &w, &h);
1070
1071    EINA_LIST_FOREACH(ecore_drm_devices_get(), ll, dev)
1072      ecore_drm_device_pointer_rotation_set(dev, e_comp_screen->rotation);
1073
1074    INF("EE Rotated and Resized: %d, %dx%d", e_comp_screen->rotation, w, h);
1075
1076    return EINA_TRUE;
1077 }
1078
1079 EINTERN void
1080 e_comp_screen_rotation_ignore_output_transform_send(E_Client *ec, Eina_Bool ignore)
1081 {
1082    E_Comp_Screen_Tzsr *tzsr = _tz_surface_rotation_find(ec);
1083
1084    if (!tzsr) return;
1085
1086    ELOGF("COMP", "|tzsr(%p) ignore(%d)", NULL, ec, tzsr, ignore);
1087
1088    tizen_screen_rotation_send_ignore_output_transform(tzsr->resource, ec->comp_data->surface, ignore);
1089 }
1090
1091 EINTERN E_Output *
1092 e_comp_screen_primary_output_get(E_Comp_Screen *e_comp_screen)
1093 {
1094    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, NULL);
1095
1096    E_Output *output = NULL, *o = NULL;
1097    Eina_List *l = NULL;
1098    int highest_priority = 0;
1099
1100    /* find the highest priority of the e_output */
1101    EINA_LIST_FOREACH(e_comp_screen->outputs, l, o)
1102      {
1103         if (highest_priority < o->config.priority)
1104           {
1105              highest_priority = o->config.priority;
1106              output = o;
1107           }
1108      }
1109
1110    return output;
1111 }
1112
1113 EINTERN void
1114 e_comp_screen_hwc_info_debug(void)
1115 {
1116    EINA_SAFETY_ON_NULL_RETURN(e_comp);
1117    EINA_SAFETY_ON_NULL_RETURN(e_comp->e_comp_screen);
1118
1119    E_Comp_Screen *e_comp_screen = e_comp->e_comp_screen;
1120    E_Output *output = NULL;
1121    E_Plane *plane = NULL;
1122    Eina_List *l_o, *ll_o;
1123    Eina_List *l_l, *ll_l;
1124    tdm_output_conn_status conn_status;
1125    int output_idx = 0;
1126    tdm_layer_capability layer_capabilities;
1127    char layer_cap[4096] = {0, };
1128
1129    INF("HWC: HWC Information ==========================================================");
1130    EINA_LIST_FOREACH_SAFE(e_comp_screen->outputs, l_o, ll_o, output)
1131      {
1132         if (!output) continue;
1133         tdm_output_get_conn_status(output->toutput, &conn_status);
1134         if (conn_status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) continue;
1135
1136         INF("HWC: HWC Output(%d):(x, y, w, h)=(%d, %d, %d, %d) Information.",
1137             ++output_idx,
1138             output->config.geom.x, output->config.geom.y, output->config.geom.w, output->config.geom.h);
1139         INF("HWC:  num_layers=%d", output->plane_count);
1140         EINA_LIST_FOREACH_SAFE(output->planes, l_l, ll_l, plane)
1141           {
1142               if (!plane) continue;
1143               tdm_layer_get_capabilities(plane->tlayer, &layer_capabilities);
1144               snprintf(layer_cap, sizeof(layer_cap), "%s%s%s%s%s%s%s%s",
1145                        _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_CURSOR),
1146                        _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_PRIMARY),
1147                        _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_OVERLAY),
1148                        _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_GRAPHIC),
1149                        _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_VIDEO),
1150                        _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_TRANSFORM),
1151                        _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_RESEVED_MEMORY),
1152                        _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_NO_CROP));
1153               INF("HWC:  index=%d zpos=%d ec=%p %s",
1154                   plane->index, plane->zpos,
1155                   plane->ec?plane->ec:NULL,
1156                   layer_cap);
1157           }
1158      }
1159    INF("HWC: =========================================================================");
1160 }