e_comp_drm: add e_comp_drm on behalf of wl_drm module 91/68091/3
authorJuyeon Lee <juyeonne.lee@samsung.com>
Mon, 2 May 2016 05:43:48 +0000 (14:43 +0900)
committerGwanglim Lee <gl77.lee@samsung.com>
Mon, 2 May 2016 11:06:12 +0000 (04:06 -0700)
Change-Id: I46ef7d7700ebe720caa2f6c19c4412c59e536f1b

15 files changed:
configure.ac
src/bin/Makefile.mk
src/bin/e_comp.c
src/bin/e_comp.h
src/bin/e_comp_canvas.c
src/bin/e_comp_drm.c [new file with mode: 0644]
src/bin/e_comp_drm.h [new file with mode: 0644]
src/bin/e_comp_hwc.c
src/bin/e_comp_wl.c
src/bin/e_includes.h
src/bin/e_output.c [new file with mode: 0644]
src/bin/e_output.h [new file with mode: 0644]
src/modules/Makefile.mk
src/modules/Makefile_wl_drm.mk [deleted file]
src/modules/wl_drm/e_mod_main.c [deleted file]

index 314aece652d67af17e1b5c6a54ddd58f98965656..522bbae438aa258c0022dece084d6dff081514eb 100755 (executable)
@@ -444,7 +444,7 @@ define([CHECK_MODULE_BUFFERQUEUE],
 AM_CONDITIONAL([HAVE_BUFFERQUEUE], [test "x${BUFFERQUEUE}" = "xtrue"])
 
 AC_E_OPTIONAL_MODULE([wl_desktop_shell], $have_wayland, [CHECK_MODULE_WL_DESKTOP_SHELL])
-AC_E_OPTIONAL_MODULE([wl_drm], $have_wayland, [CHECK_MODULE_WL_DRM])
+#AC_E_OPTIONAL_MODULE([wl_drm], $have_wayland, [CHECK_MODULE_WL_DRM])
 AC_E_OPTIONAL_MODULE([bufferqueue], $have_wayland, [CHECK_MODULE_BUFFERQUEUE])
 
 if test "x${have_wayland}" = "xyes"; then
index 805070ba8180f8456a75ba6cc26c4e4f8db7cf6a..3785fc7a583d624fd9428b3ef036ae0ff874ad77 100644 (file)
@@ -59,13 +59,13 @@ src/bin/e_mouse.h \
 src/bin/e_msgbus.h \
 src/bin/e_obj_dialog.h \
 src/bin/e_object.h \
+src/bin/e_output.h \
 src/bin/e_path.h \
 src/bin/e_pixmap.h \
 src/bin/e_place.h \
 src/bin/e_plane.h \
 src/bin/e_pointer.h \
 src/bin/e_prefix.h \
-src/bin/e_randr2.h \
 src/bin/e_remember.h \
 src/bin/e_resist.h \
 src/bin/e_scale.h \
@@ -80,7 +80,8 @@ src/bin/e_xinerama.h \
 src/bin/e_zoomap.h \
 src/bin/e_zone.h \
 src/bin/e_util_transform.h \
-src/bin/e_comp_hwc.h
+src/bin/e_comp_hwc.h \
+src/bin/e_comp_drm.h
 
 if HAVE_WAYLAND
 ENLIGHTENMENTHEADERS += \
@@ -105,6 +106,7 @@ src/bin/e_comp.c \
 src/bin/e_comp_canvas.c \
 src/bin/e_comp_cfdata.c \
 src/bin/e_comp_object.c \
+src/bin/e_comp_drm.c \
 src/bin/e_config.c \
 src/bin/e_config_data.c \
 src/bin/e_dbusmenu.c \
@@ -135,7 +137,6 @@ src/bin/e_place.c \
 src/bin/e_plane.c \
 src/bin/e_pointer.c \
 src/bin/e_prefix.c \
-src/bin/e_randr2.c \
 src/bin/e_remember.c \
 src/bin/e_resist.c \
 src/bin/e_scale.c \
@@ -151,6 +152,7 @@ src/bin/e_zoomap.c \
 src/bin/e_zone.c \
 src/bin/e_util_transform.c \
 src/bin/e_comp_hwc.c \
+src/bin/e_output.c \
 $(ENLIGHTENMENTHEADERS)
 
 if HAVE_WAYLAND
@@ -183,7 +185,7 @@ src/bin/e_main.c \
 $(enlightenment_src)
 
 src_bin_enlightenment_LDFLAGS = -export-dynamic
-src_bin_enlightenment_LDADD = @e_libs@ @dlopen_libs@ @cf_libs@ @VALGRIND_LIBS@ @WAYLAND_LIBS@ @WL_DRM_LIBS@ -lm @SHM_OPEN_LIBS@ $(TTRACE_LIBS)
+src_bin_enlightenment_LDADD = @e_libs@ @dlopen_libs@ @cf_libs@ @VALGRIND_LIBS@ @WAYLAND_LIBS@ -lm @SHM_OPEN_LIBS@ $(TTRACE_LIBS)
 if HAVE_WAYLAND_TBM
 src_bin_enlightenment_LDADD += @WAYLAND_TBM_LIBS@ @ECORE_DRM_LIBS@
 endif
index e372961636f29452645c451834d939f9f93a119b..661140a0eeb65cb5b63bc2b5fcc64d5188a9d3e9 100644 (file)
@@ -1195,8 +1195,6 @@ error:
 EINTERN Eina_Bool
 e_comp_init(void)
 {
-   E_Module *_mod;
-
    _e_comp_log_dom = eina_log_domain_register("e_comp", EINA_COLOR_YELLOW);
    eina_log_domain_level_set("e_comp", EINA_LOG_LEVEL_INFO);
 
@@ -1244,17 +1242,16 @@ e_comp_init(void)
 
    e_comp_new();
 
-   _mod = e_module_new("wl_drm");
-   EINA_SAFETY_ON_NULL_RETURN_VAL(_mod, EINA_FALSE);
-
-   e_comp->comp_type = E_PIXMAP_TYPE_WL;
-
-   if (!e_module_enable(_mod))
+   if (!e_comp_drm_init())
      {
-        ERR("Fail to enable wl_drm module");
+        ERR("Fail to init e_comp_drm");
+        e_object_del(E_OBJECT(e_comp));
+        E_FREE_FUNC(ignores, eina_hash_free);
         return EINA_FALSE;
      }
 
+   e_comp->comp_type = E_PIXMAP_TYPE_WL;
+
    e_comp_canvas_fake_layers_init();
 
 #ifdef HAVE_HWC
@@ -1322,6 +1319,7 @@ e_comp_shutdown(void)
 #endif
 
    e_comp_wl_shutdown();
+   e_comp_drm_shutdown();
 
    e_object_del(E_OBJECT(e_comp));
    E_FREE_LIST(handlers, ecore_event_handler_del);
index a86da537f19ed639636da1e480e6007d3dbf4241..54f52094067cb5ebbd49caaf0b78c77c4624d23b 100644 (file)
@@ -73,7 +73,7 @@ typedef struct E_Comp_Screen_Iface
    /* stop listening for screen events */
    void (*shutdown)(void);
    /* gather screen info */
-   E_Randr2 *(*create)(void);
+   E_Drm_Output *(*create)(void);
    /* apply current config */
    void (*apply)(void);
    /* set dpms (on, standby, suspend, off) */
index a401567f897e79edea890d30ff6b7244aa16cf87..274e0d159e9495062cc43940a1e6043e06aed74f 100644 (file)
@@ -124,7 +124,7 @@ _e_comp_canvas_cb_zone_sort(const void *data1, const void *data2)
 static void
 _e_comp_canvas_resize(Ecore_Evas *ee EINA_UNUSED)
 {
-   e_randr2_screens_setup(e_comp->w, e_comp->h);
+   e_drm_output_screens_setup(e_comp->w, e_comp->h);
    e_comp_canvas_update();
 }
 
diff --git a/src/bin/e_comp_drm.c b/src/bin/e_comp_drm.c
new file mode 100644 (file)
index 0000000..c719f03
--- /dev/null
@@ -0,0 +1,747 @@
+#include "e.h"
+#include <Ecore_Drm.h>
+
+static Eina_List *event_handlers = NULL;
+static Eina_Bool session_state = EINA_FALSE;
+
+static Eina_Bool dont_set_ecore_drm_keymap = EINA_FALSE;
+static Eina_Bool dont_use_xkb_cache = EINA_FALSE;
+
+static Eina_Bool
+_e_comp_drm_cb_activate(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+   Ecore_Drm_Event_Activate *e;
+
+   if (!(e = event)) goto end;
+
+   if (e->active)
+     {
+        E_Client *ec;
+
+        if (session_state) goto end;
+        session_state = EINA_TRUE;
+
+        ecore_evas_show(e_comp->ee);
+        E_CLIENT_FOREACH(ec)
+          {
+             if (ec->visible && (!ec->input_only))
+               e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
+          }
+        e_comp_render_queue();
+        e_comp_shape_queue_block(0);
+        ecore_event_add(E_EVENT_COMPOSITOR_ENABLE, NULL, NULL, NULL);
+     }
+   else
+     {
+        session_state = EINA_FALSE;
+        ecore_evas_hide(e_comp->ee);
+        edje_file_cache_flush();
+        edje_collection_cache_flush();
+        evas_image_cache_flush(e_comp->evas);
+        evas_font_cache_flush(e_comp->evas);
+        evas_render_dump(e_comp->evas);
+
+        e_comp_render_queue();
+        e_comp_shape_queue_block(1);
+        ecore_event_add(E_EVENT_COMPOSITOR_DISABLE, NULL, NULL, NULL);
+     }
+
+end:
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_comp_drm_cb_output(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+   const Eina_List *l;
+   E_Output_Screen *screen;
+   Ecore_Drm_Event_Output *e;
+
+   if (!(e = event)) goto end;
+
+   DBG("WL_DRM OUTPUT CHANGE");
+
+   EINA_LIST_FOREACH(e_drm_output->screens, l, screen)
+     {
+        if ((!strcmp(screen->info.name, e->name)) && 
+            (!strcmp(screen->info.screen, e->model)))
+          {
+             if (e->plug)
+               {
+                  if (!e_comp_wl_output_init(screen->id, e->make, e->model,
+                                             e->x, e->y, e->w, e->h, 
+                                             e->phys_width, e->phys_height,
+                                             e->refresh, e->subpixel_order,
+                                             e->transform))
+                    {
+                       ERR("Could not setup new output: %s", screen->id);
+                    }
+               }
+             else
+               e_comp_wl_output_remove(screen->id);
+
+             break;
+          }
+     }
+
+   /* previous calculation of e_scale gave unsuitable value because
+    * there were no sufficient information to calculate dpi.
+    * so it's considerable to re-calculate e_scale with output geometry.
+    */
+   e_scale_manual_update(((e->w * 254 / e->phys_width) + 5) / 10);
+
+end:
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_comp_drm_cb_input_device_add(void *data, int type, void *event)
+{
+   Ecore_Drm_Event_Input_Device_Add *e;
+   E_Comp *comp = data;
+
+   if (!(e = event)) goto end;
+
+   if (e->caps & EVDEV_SEAT_POINTER)
+     {
+        if (comp->wl_comp_data->ptr.num_devices == 0)
+          {
+             e_pointer_object_set(comp->pointer, NULL, 0, 0);
+             e_comp_wl_input_pointer_enabled_set(EINA_TRUE);
+          }
+        comp->wl_comp_data->ptr.num_devices++;
+     }
+   if (e->caps & EVDEV_SEAT_KEYBOARD)
+     {
+        comp->wl_comp_data->kbd.num_devices++;
+        e_comp_wl_input_keyboard_enabled_set(EINA_TRUE);
+     }
+   if (e->caps & EVDEV_SEAT_TOUCH)
+     {
+        e_comp_wl_input_touch_enabled_set(EINA_TRUE);
+        comp->wl_comp_data->touch.num_devices++;
+     }
+
+end:
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_comp_drm_cb_input_device_del(void *data, int type, void *event)
+{
+   Ecore_Drm_Event_Input_Device_Del *e;
+   E_Comp *comp = data;
+
+   if (!(e = event)) goto end;
+
+   if (e->caps & EVDEV_SEAT_POINTER)
+     {
+        comp->wl_comp_data->ptr.num_devices--;
+        if (comp->wl_comp_data->ptr.num_devices == 0)
+          {
+             e_comp_wl_input_pointer_enabled_set(EINA_FALSE);
+             e_pointer_object_set(comp->pointer, NULL, 0, 0);
+             e_pointer_hide(e_comp->pointer);
+          }
+     }
+
+end:
+   if (!e_drm_output->ignore_hotplug_events)
+     e_drm_output_screen_refresh_queue(EINA_TRUE);
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static void
+_e_comp_drm_cb_ee_resize(Ecore_Evas *ee EINA_UNUSED)
+{
+   e_comp_canvas_update();
+}
+
+static Ecore_Drm_Output_Mode *
+_e_comp_drm_mode_screen_find(E_Output_Screen *s, Ecore_Drm_Output *output)
+{
+   Ecore_Drm_Output_Mode *mode, *m = NULL;
+   const Eina_List *l;
+   int diff, distance = 0x7fffffff;
+
+   EINA_LIST_FOREACH(ecore_drm_output_modes_get(output), l, mode)
+     {
+        diff = (100 * abs(s->config.mode.w - mode->width)) + 
+           (100 * abs(s->config.mode.h - mode->height)) + 
+           fabs((100 * s->config.mode.refresh) - (100 * mode->refresh));
+        if (diff < distance)
+          {
+             m = mode;
+             distance = diff;
+          }
+     }
+
+   return m;
+}
+
+static Eina_Bool
+_e_comp_drm_output_exists(Ecore_Drm_Output *output, unsigned int crtc)
+{
+   /* find out if this output can go into the 'possibles' */
+   return ecore_drm_output_possible_crtc_get(output, crtc);
+}
+
+static char *
+_e_comp_drm_output_screen_get(Ecore_Drm_Output *output)
+{
+   const char *model;
+
+   model = ecore_drm_output_model_get(output);
+   if (!model) return NULL;
+
+   return strdup(model);
+}
+
+EINTERN E_Drm_Output *
+e_comp_drm_create(void)
+{
+   Ecore_Drm_Device *dev;
+   Ecore_Drm_Output *output;
+   const Eina_List *l, *ll;
+   E_Drm_Output *r = NULL;
+
+   r = E_NEW(E_Drm_Output, 1);
+   if (!r) return NULL;
+
+   EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
+     {
+        EINA_LIST_FOREACH(dev->outputs, ll, output)
+          {
+             E_Output_Screen *s;
+             const Eina_List *m;
+             Ecore_Drm_Output_Mode *omode;
+             unsigned int j;
+             int priority;
+             Eina_Bool ok = EINA_FALSE;
+             Eina_Bool possible = EINA_FALSE;
+             int len = 0;
+
+             s = E_NEW(E_Output_Screen, 1);
+             if (!s) continue;
+
+             s->info.name = ecore_drm_output_name_get(output);
+             printf("COMP DRM: .... out %s\n", s->info.name);
+
+             s->info.connected = ecore_drm_output_connected_get(output);
+             printf("COMP DRM: ...... connected %i\n", s->info.connected);
+
+             s->info.screen = _e_comp_drm_output_screen_get(output);
+
+             s->info.edid = ecore_drm_output_edid_get(output);
+             if (s->info.edid)
+               s->id = malloc(strlen(s->info.name) + 1 + strlen(s->info.edid) + 1);
+             else
+               s->id = malloc(strlen(s->info.name) + 1 + 1);
+             if (!s->id)
+               {
+                  free(s->info.screen);
+                  free(s->info.edid);
+                  free(s);
+                  continue;
+               }
+             len = strlen(s->info.name);
+             strncpy(s->id, s->info.name, len + 1);
+             strncat(s->id, "/", 1);
+             if (s->info.edid) strncat(s->id, s->info.edid, strlen(s->info.edid));
+
+             printf("COMP DRM: ...... screen: %s\n", s->id);
+
+             ecore_drm_output_physical_size_get(output, &s->info.size.w,
+                                                &s->info.size.h);
+
+             EINA_LIST_FOREACH(ecore_drm_output_modes_get(output), m, omode)
+               {
+                  E_Output_Mode *rmode;
+
+                  rmode = malloc(sizeof(E_Output_Mode));
+                  if (!rmode) continue;
+
+                  rmode->w = omode->width;
+                  rmode->h = omode->height;
+                  rmode->refresh = omode->refresh;
+                  rmode->preferred = (omode->flags & DRM_MODE_TYPE_PREFERRED);
+
+                  s->info.modes = eina_list_append(s->info.modes, rmode);
+               }
+
+             priority = 0;
+             if (ecore_drm_output_primary_get(dev) == output)
+               priority = 100;
+             s->config.priority = priority;
+
+             for (j = 0; j < dev->crtc_count; j++)
+               {
+                  if (dev->crtcs[j] == ecore_drm_output_crtc_id_get(output))
+                    {
+                       ok = EINA_TRUE;
+                       break;
+                    }
+               }
+
+             if (!ok)
+               {
+                  /* get possible crtcs, compare to output_crtc_id_get */
+                  for (j = 0; j < dev->crtc_count; j++)
+                    {
+                       if (_e_comp_drm_output_exists(output, dev->crtcs[j]))
+                         {
+                            ok = EINA_TRUE;
+                            possible = EINA_TRUE;
+                            break;
+                         }
+                    }
+               }
+
+             if (ok)
+               {
+                  if (!possible)
+                    {
+                       unsigned int refresh;
+
+                       ecore_drm_output_position_get(output, &s->config.geom.x,
+                                                     &s->config.geom.y);
+                       ecore_drm_output_crtc_size_get(output, &s->config.geom.w,
+                                                      &s->config.geom.h);
+
+                       ecore_drm_output_current_resolution_get(output,
+                                                               &s->config.mode.w,
+                                                               &s->config.mode.h,
+                                                               &refresh);
+                       s->config.mode.refresh = refresh;
+                       s->config.enabled = 
+                          ((s->config.mode.w != 0) && (s->config.mode.h != 0));
+
+                       printf("COMP DRM: '%s' %i %i %ix%i\n", s->info.name,
+                              s->config.geom.x, s->config.geom.y,
+                              s->config.geom.w, s->config.geom.h);
+                    }
+
+                  /* TODO: are rotations possible ?? */
+               }
+
+             r->screens = eina_list_append(r->screens, s);
+          }
+     }
+
+   return r;
+}
+
+EINTERN Eina_Bool
+e_comp_drm_available(void)
+{
+   return EINA_TRUE;
+}
+
+EINTERN void
+e_comp_drm_stub(void)
+{}
+
+EINTERN void
+e_comp_drm_apply(void)
+{
+   Ecore_Drm_Device *dev;
+   Ecore_Drm_Output *out;
+   E_Output_Screen *s;
+   const Eina_List *l, *ll;
+   int nw, nh, pw, ph, ww, hh;
+   int minw, minh, maxw, maxh;
+   int top_priority = 0;
+
+   /* TODO: what the actual fuck */
+   nw = e_drm_output->w;
+   nh = e_drm_output->h;
+   EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
+     {
+        ecore_drm_screen_size_range_get(dev, &minw, &minh, &maxw, &maxh);
+        printf("COMP DRM: size range: %ix%i -> %ix%i\n", minw, minh, maxw, maxh);
+
+        ecore_drm_outputs_geometry_get(dev, NULL, NULL, &pw, &ph);
+        if (nw > maxw) nw = maxw;
+        if (nh > maxh) nh = maxh;
+        if (nw < minw) nw = minw;
+        if (nh < minh) nh = minh;
+        ww = nw;
+        hh = nh;
+        if (nw < pw) ww = pw;
+        if (nh < ph) hh = ph;
+
+        printf("COMP DRM: set vsize: %ix%i\n", ww, hh);
+
+        EINA_LIST_FOREACH(e_drm_output->screens, ll, s)
+          {
+             Ecore_Drm_Output_Mode *mode = NULL;
+             printf("COMP DRM: find output for '%s'\n", s->info.name);
+
+             out = ecore_drm_device_output_name_find(dev, s->info.name);
+             if (!out) continue;
+
+             if (s->config.configured)
+               {
+                  printf("\tCOMP DRM: configured by E\n");
+
+                  if (s->config.enabled)
+                    {
+                       printf("\tCOMP DRM: Enabled\n");
+                       mode = _e_comp_drm_mode_screen_find(s, out);
+                    }
+                  else
+                    {
+                       printf("\tCOMP DRM: Disabled\n");
+                    }
+
+                  if (s->config.priority > top_priority)
+                    top_priority = s->config.priority;
+
+                  printf("\tCOMP DRM: Priority: %d\n", s->config.priority);
+
+                  printf("\tCOMP DRM: Geom: %d %d %d %d\n", 
+                         s->config.geom.x, s->config.geom.y,
+                         s->config.geom.w, s->config.geom.h);
+
+                  if (mode)
+                    {
+                       printf("\tCOMP DRM: Found Valid Drm Mode\n");
+                       printf("\t\tCOMP DRM: %dx%d\n", mode->width, mode->height);
+                    }
+                  else
+                    printf("\tCOMP DRM: No Valid Drm Mode Found\n");
+
+                  ecore_drm_output_mode_set(out, mode,
+                                            s->config.geom.x, s->config.geom.y);
+                  if (s->config.priority == top_priority)
+                    ecore_drm_output_primary_set(out);
+
+                  if (s->config.enabled)
+                    ecore_drm_output_enable(out);
+                  else
+                    ecore_drm_output_disable(out);
+
+                  printf("\tCOMP DRM: Mode\n");
+                  printf("\t\tCOMP DRM: Geom: %d %d\n",
+                         s->config.mode.w, s->config.mode.h);
+                  printf("\t\tCOMP DRM: Refresh: %f\n", s->config.mode.refresh);
+                  printf("\t\tCOMP DRM: Preferred: %d\n",
+                         s->config.mode.preferred);
+
+               }
+          }
+     }
+}
+
+EINTERN void
+e_comp_drm_dpms(int set)
+{
+   Ecore_Drm_Device *dev;
+   Ecore_Drm_Output *out;
+   E_Output_Screen *s;
+   const Eina_List *l, *ll;
+
+   EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
+     {
+        EINA_LIST_FOREACH(e_drm_output->screens, ll, s)
+          {
+             out = ecore_drm_device_output_name_find(dev, s->info.name);
+             if (!out) continue;
+
+             if ((!s->config.configured) || s->config.enabled)
+               ecore_drm_output_dpms_set(out, set);
+          }
+     }
+}
+
+// TODO: will remove out after removing dependant e pkgs with E_Comp_Screen_Iface
+static E_Comp_Screen_Iface drmiface =
+{
+   .available = e_comp_drm_available,
+   .init = e_comp_drm_stub,
+   .shutdown = e_comp_drm_stub,
+   .create = e_comp_drm_create,
+   .apply = e_comp_drm_apply,
+   .dpms = e_comp_drm_dpms,
+};
+
+static void
+_drm_read_pixels(E_Comp_Wl_Output *output, void *pixels)
+{
+   Ecore_Drm_Device *dev;
+   Ecore_Drm_Fb *fb;
+   const Eina_List *drm_devs, *l;
+   int i = 0, bstride;
+   unsigned char *s, *d = pixels;
+
+   drm_devs = ecore_drm_devices_get();
+   EINA_LIST_FOREACH(drm_devs, l, dev)
+     {
+        fb = dev->next;
+        if (!fb) fb = dev->current;
+        if (fb) break;
+     }
+
+   if (!fb) return;
+
+   bstride = output->w * sizeof(int);
+
+   for (i = output->y; i < output->y + output->h; i++)
+     {
+        s = fb->mmap;
+        s += (fb->stride * i) + (output->x * sizeof(int));
+        memcpy(d, s, (output->w * sizeof(int)));
+        d += bstride;
+     }
+}
+
+E_API void
+_e_comp_drm_keymap_set(struct xkb_context **ctx, struct xkb_keymap **map)
+{
+   char *keymap_path = NULL;
+   struct xkb_context *context;
+   struct xkb_keymap *keymap;
+   struct xkb_rule_names names = {0,};
+
+   TRACE_INPUT_BEGIN(_e_comp_drm_keymap_set);
+
+   context = xkb_context_new(0);
+   EINA_SAFETY_ON_NULL_RETURN(context);
+
+   /* assemble xkb_rule_names so we can fetch keymap */
+   memset(&names, 0, sizeof(names));
+   names.rules = strdup("evdev");
+   names.model = strdup("pc105");
+   names.layout = strdup("us");
+
+   keymap = e_comp_wl_input_keymap_compile(context, names, &keymap_path);
+   eina_stringshare_del(keymap_path);
+   EINA_SAFETY_ON_NULL_GOTO(keymap, cleanup);
+
+   *ctx = context;
+   *map = keymap;
+
+   if (dont_set_ecore_drm_keymap == EINA_FALSE)
+     {
+        ecore_drm_device_keyboard_cached_context_set(*ctx);
+        ecore_drm_device_keyboard_cached_keymap_set(*map);
+     }
+
+cleanup:
+   free((char *)names.rules);
+   free((char *)names.model);
+   free((char *)names.layout);
+
+   TRACE_INPUT_END();
+}
+
+E_API Eina_Bool
+e_comp_drm_init()
+{
+   E_Comp *comp;
+   int w = 0, h = 0, scr_w = 0, scr_h = 0;
+   const char *env_w, *env_h;
+   struct xkb_context *ctx = NULL;
+   struct xkb_keymap *map = NULL;
+   char buf[1024];
+
+   e_main_ts("\te_comp_drm Init Begin");
+
+   dont_set_ecore_drm_keymap = getenv("NO_ECORE_DRM_KEYMAP_CACHE") ? EINA_TRUE : EINA_FALSE;
+   dont_use_xkb_cache = getenv("NO_KEYMAP_CACHE") ? EINA_TRUE : EINA_FALSE;
+
+   TRACE_DS_BEGIN(WL_DRM:INIT);
+
+   if (!(comp = e_comp))
+     {
+        comp = e_comp_new();
+        if (!comp)
+          {
+             TRACE_DS_END();
+             EINA_SAFETY_ON_NULL_RETURN_VAL(comp, EINA_FALSE);
+          }
+
+        comp->comp_type = E_PIXMAP_TYPE_WL;
+     }
+
+   /* set gl available if we have ecore_evas support */
+   if (ecore_evas_engine_type_supported_get(ECORE_EVAS_ENGINE_OPENGL_DRM))
+     e_comp_gl_set(EINA_TRUE);
+
+   env_w = getenv("E_SCREEN_WIDTH");
+   if (env_w)
+     {
+        snprintf(buf, sizeof(buf), "%s", env_w);
+        scr_w = atoi(buf);
+     }
+
+   env_h = getenv("E_SCREEN_HEIGHT");
+   if (env_h)
+     {
+        snprintf(buf, sizeof(buf), "%s", env_h);
+        scr_h = atoi(buf);
+     }
+
+   if (scr_w <= 0) scr_w = 1;
+   if (scr_h <= 0) scr_h = 1;
+
+   //DBG("GL available:%d config engine:%d screen size:%dx%d",
+   INF("GL available:%d config engine:%d screen size:%dx%d",
+       e_comp_gl_get(), e_comp_config_get()->engine, scr_w, scr_h);
+
+   if (e_config->xkb.use_cache && !dont_use_xkb_cache)
+     {
+        e_main_ts("\tDRM Keymap Init");
+        _e_comp_drm_keymap_set(&ctx, &map);
+        e_main_ts("\tDRM Keymap Init Done");
+     }
+
+   if ((e_comp_gl_get()) &&
+       (e_comp_config_get()->engine == E_COMP_ENGINE_GL))
+     {
+        e_main_ts("\tEE_GL_DRM New");
+        comp->ee = ecore_evas_gl_drm_new(NULL, 0, 0, 0, scr_w, scr_h);
+        snprintf(buf, sizeof(buf), "\tEE_GL_DRM New Done %p %dx%d", comp->ee, scr_w, scr_h);
+        e_main_ts(buf);
+
+        if (!comp->ee)
+          e_comp_gl_set(EINA_FALSE);
+        else
+          {
+             Evas_GL *evasgl = NULL;
+             Evas_GL_API *glapi = NULL;
+
+             e_main_ts("\tEvas_GL New");
+             evasgl = evas_gl_new(ecore_evas_get(comp->ee));
+             if (evasgl)
+               {
+                  glapi = evas_gl_api_get(evasgl);
+                  if (!((glapi) && (glapi->evasglBindWaylandDisplay)))
+                    {
+                       e_comp_gl_set(EINA_FALSE);
+                       ecore_evas_free(comp->ee);
+                       comp->ee = NULL;
+                       e_main_ts("\tEvas_GL New Failed 1");
+                    }
+                  else
+                    {
+                       e_main_ts("\tEvas_GL New Done");
+                    }
+               }
+             else
+               {
+                  e_comp_gl_set(EINA_FALSE);
+                  ecore_evas_free(comp->ee);
+                  comp->ee = NULL;
+                  e_main_ts("\tEvas_GL New Failed 2");
+               }
+             evas_gl_free(evasgl);
+          }
+     }
+
+   /* fallback to framebuffer drm (non-accel) */
+   if (!comp->ee)
+     {
+        e_main_ts("\tEE_DRM New");
+        comp->ee = ecore_evas_drm_new(NULL, 0, 0, 0, scr_w, scr_h);
+        snprintf(buf, sizeof(buf), "\tEE_DRM New Done %p %dx%d", comp->ee, scr_w, scr_h);
+        e_main_ts(buf);
+     }
+
+   if (!comp->ee)
+     {
+        fprintf(stderr, "Could not create ecore_evas_drm canvas");
+        TRACE_DS_END();
+        return EINA_FALSE;
+     }
+
+   ecore_evas_data_set(e_comp->ee, "comp", e_comp);
+
+   /* get the current screen geometry */
+   ecore_evas_screen_geometry_get(e_comp->ee, NULL, NULL, &w, &h);
+
+   /* resize the canvas */
+   if (!((scr_w == w) && (scr_h == h)))
+     {
+        snprintf(buf, sizeof(buf), "\tEE Resize %dx%d -> %dx%d", scr_w, scr_h, w, h);
+        e_main_ts(buf);
+
+        ecore_evas_resize(comp->ee, w, h);
+
+        e_main_ts("\tEE Resize Done");
+     }
+
+   ecore_evas_callback_resize_set(e_comp->ee, _e_comp_drm_cb_ee_resize);
+
+   e_comp->screen = &drmiface;
+
+   e_main_ts("\tE_Comp_Wl Init");
+   if (!e_comp_wl_init())
+     {
+        TRACE_DS_END();
+        return EINA_FALSE;
+     }
+   e_main_ts("\tE_Comp_Wl Init Done");
+
+   e_main_ts("\tE_Comp_Canvas Init");
+   if (!e_comp_canvas_init(w, h))
+     {
+        TRACE_DS_END();
+        return EINA_FALSE;
+     }
+   e_main_ts("\tE_Comp_Canvas Init Done");
+
+   e_comp_wl->screenshooter.read_pixels = _drm_read_pixels;
+
+   ecore_evas_pointer_xy_get(e_comp->ee,
+                             &e_comp_wl->ptr.x,
+                             &e_comp_wl->ptr.y);
+
+   evas_event_feed_mouse_in(e_comp->evas, 0, NULL);
+
+   /* comp->pointer =  */
+   /*   e_pointer_window_new(ecore_evas_window_get(comp->ee), 1); */
+   e_main_ts("\tE_Pointer New");
+   if ((comp->pointer = e_pointer_canvas_new(comp->ee, EINA_TRUE)))
+     {
+        comp->pointer->color = EINA_TRUE;
+        e_pointer_hide(comp->pointer);
+     }
+   e_main_ts("\tE_Pointer New Done");
+
+   /* FIXME: We need a way to trap for user changing the keymap inside of E
+    *        without the event coming from X11 */
+
+   /* FIXME: We should make a decision here ...
+    *
+    * Fetch the keymap from drm, OR set this to what the E config is....
+    */
+
+   /* FIXME: This is just for testing at the moment....
+    * happens to jive with what drm does */
+   e_main_ts("\tE_Comp_WL Keymap Init");
+   e_comp_wl_input_keymap_set("evdev", "pc105", "us", ctx, map);
+   e_main_ts("\tE_Comp_WL Keymap Init Done");
+
+   E_LIST_HANDLER_APPEND(event_handlers, ECORE_DRM_EVENT_ACTIVATE,         _e_comp_drm_cb_activate,         comp);
+   E_LIST_HANDLER_APPEND(event_handlers, ECORE_DRM_EVENT_OUTPUT,           _e_comp_drm_cb_output,           comp);
+   E_LIST_HANDLER_APPEND(event_handlers, ECORE_DRM_EVENT_INPUT_DEVICE_ADD, _e_comp_drm_cb_input_device_add, comp);
+   E_LIST_HANDLER_APPEND(event_handlers, ECORE_DRM_EVENT_INPUT_DEVICE_DEL, _e_comp_drm_cb_input_device_del, comp);
+
+   TRACE_DS_END();
+
+   return EINA_TRUE;
+}
+
+E_API void
+e_comp_drm_shutdown()
+{
+   /* shutdown ecore_drm */
+   /* ecore_drm_shutdown(); */
+
+   dont_set_ecore_drm_keymap = EINA_FALSE;
+   dont_use_xkb_cache = EINA_FALSE;
+   E_FREE_LIST(event_handlers, ecore_event_handler_del);
+
+}
diff --git a/src/bin/e_comp_drm.h b/src/bin/e_comp_drm.h
new file mode 100644 (file)
index 0000000..ed0d53b
--- /dev/null
@@ -0,0 +1,20 @@
+#ifdef E_TYPEDEFS
+
+
+#else
+#ifndef E_COMP_DRM_H
+#define E_COMP_DRM_H
+
+
+EINTERN Eina_Bool e_comp_drm_available(void);
+EINTERN void e_comp_drm_stub(void);
+EINTERN void e_comp_drm_apply(void);
+EINTERN E_Drm_Output * e_comp_drm_create(void);
+EINTERN void e_comp_drm_dpms(int set);
+
+E_API Eina_Bool e_comp_drm_init(void);
+E_API void e_comp_drm_shutdown(void);
+
+#endif /*E_COMP_DRM_H*/
+
+#endif
index 29ddee9fcbd69b82c5b394931b2d4f54e502c7eb..d1f16f0e559192f03f476e8139d56067449d632d 100755 (executable)
@@ -837,13 +837,13 @@ _e_comp_hwc_output_update_geom(E_Comp_Hwc_Output *hwc_output)
 {
    Ecore_Drm_Device *dev;
    Ecore_Drm_Output *drm_output;
-   E_Randr2_Screen *s;
+   E_Output_Screen *s;
    const Eina_List *l, *ll;
    int x, y, w, h;
 
    EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
      {
-        EINA_LIST_FOREACH(e_randr2->screens, ll, s)
+        EINA_LIST_FOREACH(e_drm_output->screens, ll, s)
           {
              ELOGF("HWC", "find output for '%s'", NULL, NULL, s->info.name);
 
@@ -1761,7 +1761,7 @@ e_comp_hwc_plane_init(E_Zone *zone)
    E_Comp_Hwc_Output *hwc_output = NULL;
    Ecore_Drm_Device *dev;
    Ecore_Drm_Output *drm_output;
-   E_Randr2_Screen *s;
+   E_Output_Screen *s;
    const Eina_List *l, *ll;
    E_Output * eout = NULL;
 
@@ -1770,7 +1770,7 @@ e_comp_hwc_plane_init(E_Zone *zone)
    // TODO: canvas, zone shall match with one output
    EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
      {
-        EINA_LIST_FOREACH(e_randr2->screens, ll, s)
+        EINA_LIST_FOREACH(e_drm_output->screens, ll, s)
           {
              int len;
 
index f3133a0f1903a90025a65d2252dfb04c4cf0198e..abb98058ab1e5af3e27313d57aa492b110500e3d 100644 (file)
@@ -1690,12 +1690,12 @@ static Eina_Bool
 _e_comp_wl_cb_randr_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
 {
    Eina_List *l;
-   E_Randr2_Screen *screen;
+   E_Output_Screen *screen;
    unsigned int transform = WL_OUTPUT_TRANSFORM_NORMAL;
 
-   if (!e_randr2) return ECORE_CALLBACK_RENEW;
+   if (!e_drm_output) return ECORE_CALLBACK_RENEW;
 
-   EINA_LIST_FOREACH(e_randr2->screens, l, screen)
+   EINA_LIST_FOREACH(e_drm_output->screens, l, screen)
      {
         if (!screen->config.enabled)
           {
@@ -4265,17 +4265,17 @@ e_comp_wl_init(void)
    e_comp_wl_tbm_init();
 #endif
 
-   if (!e_randr2_init())
+   if (!e_drm_output_init())
      {
-        e_error_message_show(_("Enlightenment cannot initialize randr2!\n"));
+        e_error_message_show(_("Enlightenment cannot initialize drm output!\n"));
         TRACE_DS_END();
         return EINA_FALSE;
      }
 
-   e_randr2_screens_setup(-1, -1);
+   e_drm_output_screens_setup(-1, -1);
 
    /* add event handlers to catch E events */
-   E_LIST_HANDLER_APPEND(handlers, E_EVENT_RANDR_CHANGE,            _e_comp_wl_cb_randr_change,        NULL);
+   E_LIST_HANDLER_APPEND(handlers, E_EVENT_SCREEN_CHANGE,            _e_comp_wl_cb_randr_change,        NULL);
    E_LIST_HANDLER_APPEND(handlers, E_EVENT_COMP_OBJECT_ADD,         _e_comp_wl_cb_comp_object_add,     NULL);
    E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_MOVE,          _e_comp_wl_cb_mouse_move,          NULL);
    E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_BUTTON_CANCEL, _e_comp_wl_cb_mouse_button_cancel, NULL);
index 2af84a3032d908fd51be5b95858ce5bfa15357af..3c2da43f428cd7e78525f6d31c09c5cb461d3d92 100644 (file)
@@ -4,7 +4,6 @@
 #include "e_error.h"
 #include "e_zone.h"
 #include "e_desk.h"
-#include "e_randr2.h"
 #include "e_pixmap.h"
 #include "e_comp_object.h"
 #include "e_util_transform.h"
@@ -52,6 +51,8 @@
 #include "e_hints.h"
 #include "e_plane.h"
 #include "e_comp_hwc.h"
+#include "e_comp_drm.h"
+#include "e_output.h"
 
 #ifdef HAVE_WAYLAND
 # include "e_comp_wl.h"
diff --git a/src/bin/e_output.c b/src/bin/e_output.c
new file mode 100644 (file)
index 0000000..081accd
--- /dev/null
@@ -0,0 +1,516 @@
+#include "e.h"
+
+
+/////////////////////////////////////////////////////////////////////////
+static void                    _animated_apply_abort(void);
+static Eina_Bool               _cb_delay_timer(void *data);
+static Eina_Bool               _cb_fade_animator(void *data);
+static void                    _animated_apply(void);
+static void                    _do_apply(void);
+static void                    _info_free(E_Drm_Output *r);
+static char                   *_screens_fingerprint(E_Drm_Output *r);
+static Eina_Bool               _screens_differ(E_Drm_Output *r1, E_Drm_Output *r2);
+static Eina_Bool               _cb_screen_change_delay(void *data);
+static void                    _screen_config_takeover(void);
+static void                    _screen_config_eval(void);
+static void                    _screen_config_maxsize(void);
+
+/////////////////////////////////////////////////////////////////////////
+
+static Eina_List     *_ev_handlers = NULL;
+static Ecore_Timer   *_screen_delay_timer = NULL;
+static Eina_Bool      event_screen = EINA_FALSE;
+static Eina_Bool      event_ignore = EINA_FALSE;
+
+/////////////////////////////////////////////////////////////////////////
+
+E_API E_Drm_Output        *e_drm_output = NULL;
+
+E_API int              E_EVENT_RANDR_CHANGE = 0;
+E_API int              E_EVENT_SCREEN_CHANGE = 0;
+
+/////////////////////////////////////////////////////////////////////////
+EINTERN Eina_Bool
+e_drm_output_init(void)
+{
+   if (!E_EVENT_SCREEN_CHANGE) E_EVENT_SCREEN_CHANGE = ecore_event_type_new();
+   if (!e_comp_drm_available()) return EINA_FALSE;
+
+   _do_apply();
+
+   ecore_event_add(E_EVENT_SCREEN_CHANGE, NULL, NULL, NULL);
+
+   return EINA_TRUE;
+}
+
+EINTERN int
+e_drm_output_shutdown(void)
+{
+   _animated_apply_abort();
+   // nuke any screen config delay handler
+   if (_screen_delay_timer) ecore_timer_del(_screen_delay_timer);
+   _screen_delay_timer = NULL;
+   // clear up all event handlers
+   E_FREE_LIST(_ev_handlers, ecore_event_handler_del);
+   // free up screen info
+   _info_free(e_drm_output);
+   e_drm_output = NULL;
+
+   return 1;
+}
+
+E_API void
+e_drm_output_config_apply(void)
+{
+   _animated_apply();
+}
+
+E_API void
+e_drm_output_screeninfo_update(void)
+{
+   // re-fetch/update current screen info
+   _info_free(e_drm_output);
+   e_drm_output = e_comp_drm_create();
+   _screen_config_maxsize();
+}
+
+/////////////////////////////////////////////////////////////////////////
+static double _start_time = 0.0;
+static Ecore_Animator *_fade_animator = NULL;
+static Ecore_Timer *_apply_delay = NULL;
+Eina_Bool _applying = EINA_FALSE;
+static int _target_from = 0;
+static int _target_to = 0;
+static Evas_Object *_fade_obj = NULL;
+
+static void
+_animated_apply_abort(void)
+{
+   if (_apply_delay) ecore_timer_del(_apply_delay);
+   if (_fade_animator) ecore_animator_del(_fade_animator);
+   _apply_delay = NULL;
+   _fade_animator = NULL;
+   _applying = EINA_FALSE;
+   _fade_obj = NULL;
+}
+
+static Eina_Bool
+_cb_delay_timer(void *data EINA_UNUSED)
+{
+   _apply_delay = NULL;
+   _target_from = 255;
+   _target_to = 0;
+   _start_time = ecore_loop_time_get();
+   _fade_animator = ecore_animator_add(_cb_fade_animator, NULL);
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+_cb_fade_animator(void *data EINA_UNUSED)
+{
+   double t = ecore_loop_time_get() - _start_time;
+   int v;
+
+   t = t / 0.5;
+   if (t < 0.0) t = 0.0;
+   v = _target_from + ((_target_to - _target_from) * t);
+   if (t >= 1.0) v = _target_to;
+   evas_object_color_set(_fade_obj, 0, 0, 0, v);
+   if (v == _target_to)
+     {
+        if (_target_to == 255)
+          {
+             _apply_delay = ecore_timer_add(3.0, _cb_delay_timer, NULL);
+             _do_apply();
+          }
+        else
+          {
+             evas_object_del(_fade_obj);
+             _fade_obj = NULL;
+             _applying = EINA_FALSE;
+          }
+        _fade_animator = NULL;
+        return EINA_FALSE;
+     }
+   return EINA_TRUE;
+}
+
+static void
+_animated_apply(void)
+{
+   Evas *e;
+
+   // fade out, config, wait 3 seconds, fade back in
+   if (_applying) return;
+   _applying = EINA_TRUE;
+   _start_time = ecore_loop_time_get();
+   e = e_comp->evas;
+   _fade_obj = evas_object_rectangle_add(e);
+   evas_object_pass_events_set(_fade_obj, EINA_TRUE);
+   evas_object_color_set(_fade_obj, 0, 0, 0, 0);
+   evas_object_move(_fade_obj, 0, 0);
+   evas_object_resize(_fade_obj, 999999, 999999);
+   evas_object_layer_set(_fade_obj, EVAS_LAYER_MAX);
+   evas_object_show(_fade_obj);
+   _target_from = 0;
+   _target_to = 255;
+   _fade_animator = ecore_animator_add(_cb_fade_animator, NULL);
+}
+
+static void
+_do_apply(void)
+{
+   // take current screen config and apply it to the driver
+   printf("OUTPUT: re-get info before applying..\n");
+   _info_free(e_drm_output);
+   e_drm_output = e_comp_drm_create();
+   _screen_config_maxsize();
+   printf("OUTPUT: takeover config...\n");
+   _screen_config_takeover();
+   printf("OUTPUT: eval config...\n");
+   _screen_config_eval();
+   printf("OUTPUT: really apply config...\n");
+   e_comp_drm_apply();
+   printf("OUTPUT: done config...\n");
+}
+
+static void
+_info_free(E_Drm_Output *r)
+{
+   E_Output_Screen *s;
+   E_Output_Mode *m;
+
+   if (!r) return;
+   // free up our randr screen data
+   EINA_LIST_FREE(r->screens, s)
+     {
+        free(s->id);
+        free(s->info.screen);
+        free(s->info.name);
+        free(s->info.edid);
+        EINA_LIST_FREE(s->info.modes, m) free(m);
+        free(s);
+     }
+   free(r);
+}
+
+static char *
+_screens_fingerprint(E_Drm_Output *r)
+{
+   Eina_List *l;
+   E_Output_Screen *s;
+   Eina_Strbuf *buf;
+   char *str;
+
+   buf = eina_strbuf_new();
+   if (!buf) return NULL;
+   EINA_LIST_FOREACH(r->screens, l, s)
+     {
+        if (!s->id) eina_strbuf_append(buf, ":NULL:");
+        else
+          {
+             eina_strbuf_append(buf, ":");
+             eina_strbuf_append(buf, s->id);
+             eina_strbuf_append(buf, ":");
+             eina_strbuf_append(buf, ":LO:");
+          }
+     }
+   str = eina_strbuf_string_steal(buf);
+   eina_strbuf_free(buf);
+   return str;
+}
+
+static Eina_Bool
+_screens_differ(E_Drm_Output *r1, E_Drm_Output *r2)
+{
+   char *s1, *s2;
+   Eina_Bool changed = EINA_FALSE;
+   Eina_List *l, *ll;
+   E_Output_Screen *s, *ss;
+
+   // check monitor outputs and edids, plugged in things
+   s1 = _screens_fingerprint(r1);
+   s2 = _screens_fingerprint(r2);
+   if ((!s1) && (!s2)) return EINA_FALSE;
+   printf("OUTPUT: check fingerprint...\n");
+   if ((s1) && (s2) && (strcmp(s1, s2))) changed = EINA_TRUE;
+   printf("OUTPUT: ... fingerprint says %i\n", changed);
+   free(s1);
+   free(s2);
+   // check screen config
+   EINA_LIST_FOREACH(r2->screens, l, s)
+     {
+        if (!s->id) continue;
+        EINA_LIST_FOREACH(r2->screens, ll, ss)
+          {
+             if ((ss->id) && (!strcmp(s->id, ss->id))) break;
+             ss = NULL;
+          }
+        if (!ss) changed = EINA_TRUE;
+        else if ((s->config.geom.x != ss->config.geom.x) ||
+                 (s->config.geom.y != ss->config.geom.y) ||
+                 (s->config.geom.w != ss->config.geom.w) ||
+                 (s->config.geom.h != ss->config.geom.h) ||
+                 (s->config.mode.w != ss->config.mode.w) ||
+                 (s->config.mode.h != ss->config.mode.h) ||
+                 (s->config.enabled != ss->config.enabled))
+          changed = EINA_TRUE;
+     }
+   printf("OUTPUT: changed = %i\n", changed);
+   return changed;
+}
+
+static Eina_Bool
+_cb_screen_change_delay(void *data EINA_UNUSED)
+{
+   _screen_delay_timer = NULL;
+   printf("OUTPUT: ... %i %i\n", event_screen, event_ignore);
+   // if we had a screen plug/unplug etc. event and we shouldnt ignore it...
+   if ((event_screen) && (!event_ignore))
+     {
+        E_Drm_Output *rtemp;
+        Eina_Bool change = EINA_FALSE;
+
+        printf("OUTPUT: reconfigure screens due to event...\n");
+        rtemp = e_comp_drm_create();
+        if (rtemp)
+          {
+             if (_screens_differ(e_drm_output, rtemp)) change = EINA_TRUE;
+             _info_free(rtemp);
+          }
+        printf("OUTPUT: change = %i\n", change);
+        // we plugged or unplugged some monitor - re-apply config so
+        // known screens can be configured
+        if (change) e_drm_output_config_apply();
+     }
+   // update screen info after the above apply or due to external changes
+   e_drm_output_screeninfo_update();
+   e_comp_canvas_resize(e_drm_output->w, e_drm_output->h);
+   e_drm_output_screens_setup(e_comp->w, e_comp->h);
+   e_comp_canvas_update();
+   // tell the rest of e some screen reconfigure thing happened
+   ecore_event_add(E_EVENT_SCREEN_CHANGE, NULL, NULL, NULL);
+   event_screen = EINA_FALSE;
+   event_ignore = EINA_FALSE;
+   return EINA_FALSE;
+}
+
+static void
+_screen_config_takeover(void)
+{
+   Eina_List *l;
+   E_Output_Screen *s;
+   EINA_LIST_FOREACH(e_drm_output->screens, l, s)
+     {
+        s->config.configured = EINA_TRUE;
+        s->config.enabled = EINA_TRUE;
+     }
+}
+
+static void
+_screen_config_eval(void)
+{
+   Eina_List *l;
+   E_Output_Screen *s;
+   int minx, miny, maxx, maxy;
+
+   minx = 65535;
+   miny = 65535;
+   maxx = -65536;
+   maxy = -65536;
+
+   EINA_LIST_FOREACH(e_drm_output->screens, l, s)
+     {
+        if (!s->config.enabled) continue;
+        if (s->config.geom.x < minx) minx = s->config.geom.x;
+        if (s->config.geom.y < miny) miny = s->config.geom.y;
+        if ((s->config.geom.x + s->config.geom.w) > maxx)
+          maxx = s->config.geom.x + s->config.geom.w;
+        if ((s->config.geom.y + s->config.geom.h) > maxy)
+          maxy = s->config.geom.y + s->config.geom.h;
+        printf("OUTPUT: s: '%s' @ %i %i - %ix%i\n",
+               s->info.name,
+               s->config.geom.x, s->config.geom.y,
+               s->config.geom.w, s->config.geom.h);
+     }
+   printf("OUTPUT:--- %i %i -> %i %i\n", minx, miny, maxx, maxy);
+   EINA_LIST_FOREACH(e_drm_output->screens, l, s)
+     {
+        s->config.geom.x -= minx;
+        s->config.geom.y -= miny;
+     }
+   e_drm_output->w = maxx - minx;
+   e_drm_output->h = maxy - miny;
+}
+
+static void
+_screen_config_maxsize(void)
+{
+   Eina_List *l;
+   E_Output_Screen *s;
+   int maxx, maxy;
+
+   maxx = -65536;
+   maxy = -65536;
+   EINA_LIST_FOREACH(e_drm_output->screens, l, s)
+     {
+        if (!s->config.enabled) continue;
+        if ((s->config.geom.x + s->config.geom.w) > maxx)
+          maxx = s->config.geom.x + s->config.geom.w;
+        if ((s->config.geom.y + s->config.geom.h) > maxy)
+          maxy = s->config.geom.y + s->config.geom.h;
+        printf("OUTPUT: '%s': %i %i %ix%i\n",
+               s->info.name,
+               s->config.geom.x, s->config.geom.y,
+               s->config.geom.w, s->config.geom.h);
+     }
+   printf("OUTPUT: result max: %ix%i\n", maxx, maxy);
+   e_drm_output->w = maxx;
+   e_drm_output->h = maxy;
+}
+
+static int
+_screen_sort_cb(const void *data1, const void *data2)
+{
+   const E_Output_Screen *s1 = data1, *s2 = data2;
+   int dif;
+
+   dif = -(s1->config.priority - s2->config.priority);
+   if (dif == 0)
+     {
+        dif = s1->config.geom.x - s2->config.geom.x;
+        if (dif == 0)
+          dif = s1->config.geom.y - s2->config.geom.y;
+     }
+   return dif;
+}
+
+E_API void
+e_drm_output_screen_refresh_queue(Eina_Bool lid_event)
+{ 
+   // delay handling of screen shances as they can come in in a series over
+   // time and thus we can batch up responding to them by waiting 1.0 sec
+   if (_screen_delay_timer)
+     ecore_timer_reset(_screen_delay_timer);
+   else
+     _screen_delay_timer = ecore_timer_add(1.0, _cb_screen_change_delay, NULL);
+   event_screen |= !!lid_event;
+}
+
+E_API void
+e_drm_output_screens_setup(int rw, int rh)
+{
+   int i;
+   E_Screen *screen;
+   Eina_List *screens = NULL, *screens_rem;
+   Eina_List *all_screens = NULL;
+   Eina_List *l, *ll;
+   E_Output_Screen *s, *s2, *s_chosen;
+   Eina_Bool removed;
+
+   if ((!e_drm_output) || (!e_drm_output->screens)) goto out;
+   // put screens in tmp list
+   EINA_LIST_FOREACH(e_drm_output->screens, l, s)
+     {
+        if ((s->config.enabled) &&
+            (s->config.geom.w > 0) &&
+            (s->config.geom.h > 0))
+          {
+             screens = eina_list_append(screens, s);
+          }
+     }
+   // remove overlapping screens - if a set of screens overlap, keep the
+   // smallest/lowest res
+   do
+     {
+        removed = EINA_FALSE;
+
+        EINA_LIST_FOREACH(screens, l, s)
+          {
+             screens_rem = NULL;
+
+             EINA_LIST_FOREACH(l->next, ll, s2)
+               {
+                  if (E_INTERSECTS(s->config.geom.x, s->config.geom.y,
+                                   s->config.geom.w, s->config.geom.h,
+                                   s2->config.geom.x, s2->config.geom.y,
+                                   s2->config.geom.w, s2->config.geom.h))
+                    {
+                       if (!screens_rem)
+                         screens_rem = eina_list_append(screens_rem, s);
+                       screens_rem = eina_list_append(screens_rem, s2);
+                    }
+               }
+             // we have intersecting screens - choose the lowest res one
+             if (screens_rem)
+               {
+                  removed = EINA_TRUE;
+                  // find the smallest screen (chosen one)
+                  s_chosen = NULL;
+                  EINA_LIST_FOREACH(screens_rem, ll, s2)
+                    {
+                       if (!s_chosen) s_chosen = s2;
+                       else
+                         {
+                            if ((s_chosen->config.geom.w *
+                                 s_chosen->config.geom.h) >
+                                (s2->config.geom.w *
+                                 s2->config.geom.h))
+                              s_chosen = s2;
+                         }
+                    }
+                  // remove all from screens but the chosen one
+                  EINA_LIST_FREE(screens_rem, s2)
+                    {
+                       if (s2 != s_chosen)
+                         screens = eina_list_remove_list(screens, l);
+                    }
+                  // break our list walk and try again
+                  break;
+               }
+          }
+     }
+   while (removed);
+   // sort screens by priority etc.
+   screens = eina_list_sort(screens, 0, _screen_sort_cb);
+   i = 0;
+   EINA_LIST_FOREACH(screens, l, s)
+     {
+        screen = E_NEW(E_Screen, 1);
+        screen->escreen = screen->screen = i;
+        screen->x = s->config.geom.x;
+        screen->y = s->config.geom.y;
+        screen->w = s->config.geom.w;
+        screen->h = s->config.geom.h;
+        if (s->id) screen->id = strdup(s->id);
+
+        all_screens = eina_list_append(all_screens, screen);
+        printf("xinerama screen %i %i %ix%i\n", screen->x, screen->y, screen->w, screen->h);
+        INF("E INIT: XINERAMA SCREEN: [%i][%i], %ix%i+%i+%i",
+            i, i, screen->w, screen->h, screen->x, screen->y);
+        i++;
+     }
+   eina_list_free(screens);
+   // if we have NO screens at all (above - i will be 0) AND we have no
+   // existing screens set up in xinerama - then just say root window size
+   // is the entire screen. this should handle the case where you unplug ALL
+   // screens from an existing setup (unplug external monitors and/or close
+   // laptop lid), in which case as long as at least one screen is configured
+   // in xinerama, it will be left-as is until next time we re-eval screen
+   // setup and have at least one screen
+   printf("xinerama setup............... %i %p\n", i, e_xinerama_screens_all_get());
+   if ((i == 0) && (!e_xinerama_screens_all_get()))
+     {
+out:
+        screen = E_NEW(E_Screen, 1);
+        screen->escreen = screen->screen = 0;
+        screen->x = 0;
+        screen->y = 0;
+        if ((rw > 0) && (rh > 0))
+          screen->w = rw, screen->h = rh;
+        else
+          ecore_evas_screen_geometry_get(e_comp->ee, NULL, NULL, &screen->w, &screen->h);
+        all_screens = eina_list_append(all_screens, screen);
+     }
+   e_xinerama_screens_set(all_screens);
+}
diff --git a/src/bin/e_output.h b/src/bin/e_output.h
new file mode 100644 (file)
index 0000000..5cec420
--- /dev/null
@@ -0,0 +1,64 @@
+#ifdef E_TYPEDEFS
+
+typedef struct _E_Drm_Output        E_Drm_Output;
+typedef struct _E_Output_Screen E_Output_Screen;
+typedef struct _E_Output_Mode   E_Output_Mode;
+
+#else
+#ifndef E_OUTPUT_H
+#define E_OUTPUT_H
+
+struct _E_Drm_Output
+{
+   Eina_List *screens; // available screens
+   int        w, h; // virtual resolution needed for screens (calculated)
+   unsigned char  ignore_hotplug_events;
+   unsigned char  ignore_acpi_events; 
+};
+
+struct _E_Output_Mode
+{
+   int    w, h; // resolution width and height
+   double refresh; // refresh in hz
+   Eina_Bool preferred : 1; // is this the preferred mode for the device?
+};
+
+struct _E_Output_Screen
+{
+   char *id; // string id which is "name/edid";
+   struct {
+      char                 *screen; // name of the screen device attached
+      char                 *name; // name of the output itself
+      char                 *edid; // full edid data
+      Eina_Bool             connected : 1; // some screen is plugged in or not
+      Eina_List            *modes; // available screen modes here
+      struct {
+         int                w, h; // physical width and height in mm
+      } size;
+   } info;
+   struct {
+      Eina_Rectangle        geom; // the geometry that is set (as a result)
+      E_Output_Mode         mode; // screen res/refresh to use
+      int                   rotation; // 0, 90, 180, 270
+      int                   priority; // larger num == more important
+      Eina_Bool             enabled : 1; // should this monitor be enabled?
+      Eina_Bool             configured : 1; // has screen been configured by e?
+   } config;
+   Eina_List           *planes;
+   int                  plane_count;
+   E_Zone              *zone;
+};
+
+extern E_API E_Drm_Output *e_drm_output;
+extern E_API int E_EVENT_SCREEN_CHANGE;
+extern E_API int E_EVENT_RANDR_CHANGE; // x randr
+
+EINTERN Eina_Bool e_drm_output_init(void);
+EINTERN int       e_drm_output_shutdown(void);
+E_API    void      e_drm_output_config_apply(void);
+E_API    void      e_drm_output_screeninfo_update(void);
+E_API void e_drm_output_screen_refresh_queue(Eina_Bool lid_event);
+E_API void e_drm_output_screens_setup(int rw, int rh);
+
+#endif
+#endif
index cdc9f37ca14f893197f21bb78ef113cf96556e80..d8907ced6b98ba4bd86f5e3efabf3c063bda2b20 100644 (file)
@@ -11,7 +11,7 @@ MOD_CPPFLAGS = -I. -DE_LOGGING=1 \
 
 MOD_LIBS = @e_libs@ @dlopen_libs@
 
-include src/modules/Makefile_wl_drm.mk
+#include src/modules/Makefile_wl_drm.mk
 
 include src/modules/Makefile_wl_desktop_shell.mk
 
diff --git a/src/modules/Makefile_wl_drm.mk b/src/modules/Makefile_wl_drm.mk
deleted file mode 100644 (file)
index 3609472..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-if USE_MODULE_WL_DRM
-wl_drmdir = $(MDIR)/wl_drm
-
-wl_drmpkgdir = $(MDIR)/wl_drm/$(MODULE_ARCH)
-wl_drmpkg_LTLIBRARIES = src/modules/wl_drm/module.la
-
-src_modules_wl_drm_module_la_DEPENDENCIES = $(MDEPENDENCIES)
-src_modules_wl_drm_module_la_CPPFLAGS  = $(MOD_CPPFLAGS) @WL_DRM_CFLAGS@ @WAYLAND_CFLAGS@
-src_modules_wl_drm_module_la_LIBADD   = $(LIBS) @WL_DRM_LIBS@ @WAYLAND_LIBS@
-src_modules_wl_drm_module_la_LDFLAGS = $(MOD_LDFLAGS)
-src_modules_wl_drm_module_la_SOURCES = src/modules/wl_drm/e_mod_main.c
-
-PHONIES += wl_drm install-wl_drm
-wl_drm: $(wl_drmpkg_LTLIBRARIES) $(wl_drm_DATA)
-install-wl_drm: install-wl_drmpkgLTLIBRARIES
-endif
diff --git a/src/modules/wl_drm/e_mod_main.c b/src/modules/wl_drm/e_mod_main.c
deleted file mode 100644 (file)
index 7180c48..0000000
+++ /dev/null
@@ -1,992 +0,0 @@
-#include "e.h"
-#include <Ecore_Drm.h>
-
-E_API E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Wl_Drm" };
-
-static Eina_List *event_handlers = NULL;
-static Eina_Bool session_state = EINA_FALSE;
-
-static Eina_Bool dont_set_ecore_drm_keymap = EINA_FALSE;
-static Eina_Bool dont_use_xkb_cache = EINA_FALSE;
-
-static Eina_Bool
-_e_mod_drm_cb_activate(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
-{
-   Ecore_Drm_Event_Activate *e;
-
-   if (!(e = event)) goto end;
-
-   if (e->active)
-     {
-        E_Client *ec;
-
-        if (session_state) goto end;
-        session_state = EINA_TRUE;
-
-        ecore_evas_show(e_comp->ee);
-        E_CLIENT_FOREACH(ec)
-          {
-             if (ec->visible && (!ec->input_only))
-               e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
-          }
-        e_comp_render_queue();
-        e_comp_shape_queue_block(0);
-        ecore_event_add(E_EVENT_COMPOSITOR_ENABLE, NULL, NULL, NULL);
-     }
-   else
-     {
-        session_state = EINA_FALSE;
-        ecore_evas_hide(e_comp->ee);
-        edje_file_cache_flush();
-        edje_collection_cache_flush();
-        evas_image_cache_flush(e_comp->evas);
-        evas_font_cache_flush(e_comp->evas);
-        evas_render_dump(e_comp->evas);
-
-        e_comp_render_queue();
-        e_comp_shape_queue_block(1);
-        ecore_event_add(E_EVENT_COMPOSITOR_DISABLE, NULL, NULL, NULL);
-     }
-
-end:
-   return ECORE_CALLBACK_PASS_ON;
-}
-
-static Eina_Bool
-_e_mod_drm_cb_output(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
-{
-   const Eina_List *l;
-   E_Randr2_Screen *screen;
-   Ecore_Drm_Event_Output *e;
-
-   if (!(e = event)) goto end;
-
-   DBG("WL_DRM OUTPUT CHANGE");
-
-   EINA_LIST_FOREACH(e_randr2->screens, l, screen)
-     {
-        if ((!strcmp(screen->info.name, e->name)) && 
-            (!strcmp(screen->info.screen, e->model)))
-          {
-             if (e->plug)
-               {
-                  if (!e_comp_wl_output_init(screen->id, e->make, e->model,
-                                             e->x, e->y, e->w, e->h, 
-                                             e->phys_width, e->phys_height,
-                                             e->refresh, e->subpixel_order,
-                                             e->transform))
-                    {
-                       ERR("Could not setup new output: %s", screen->id);
-                    }
-               }
-             else
-               e_comp_wl_output_remove(screen->id);
-
-             break;
-          }
-     }
-
-   /* previous calculation of e_scale gave unsuitable value because
-    * there were no sufficient information to calculate dpi.
-    * so it's considerable to re-calculate e_scale with output geometry.
-    */
-   e_scale_manual_update(((e->w * 254 / e->phys_width) + 5) / 10);
-
-end:
-   return ECORE_CALLBACK_PASS_ON;
-}
-
-static Eina_Bool
-_e_mod_drm_cb_input_device_add(void *data, int type, void *event)
-{
-   Ecore_Drm_Event_Input_Device_Add *e;
-   E_Comp *comp = data;
-
-   if (!(e = event)) goto end;
-
-   if (e->caps & EVDEV_SEAT_POINTER)
-     {
-        if (comp->wl_comp_data->ptr.num_devices == 0)
-          {
-             e_pointer_object_set(comp->pointer, NULL, 0, 0);
-             e_comp_wl_input_pointer_enabled_set(EINA_TRUE);
-          }
-        comp->wl_comp_data->ptr.num_devices++;
-     }
-   if (e->caps & EVDEV_SEAT_KEYBOARD)
-     {
-        comp->wl_comp_data->kbd.num_devices++;
-        e_comp_wl_input_keyboard_enabled_set(EINA_TRUE);
-     }
-   if (e->caps & EVDEV_SEAT_TOUCH)
-     {
-        e_comp_wl_input_touch_enabled_set(EINA_TRUE);
-        comp->wl_comp_data->touch.num_devices++;
-     }
-
-end:
-   return ECORE_CALLBACK_PASS_ON;
-}
-
-static Eina_Bool
-_e_mod_drm_cb_input_device_del(void *data, int type, void *event)
-{
-   Ecore_Drm_Event_Input_Device_Del *e;
-   E_Comp *comp = data;
-
-   if (!(e = event)) goto end;
-
-   if (e->caps & EVDEV_SEAT_POINTER)
-     {
-        comp->wl_comp_data->ptr.num_devices--;
-        if (comp->wl_comp_data->ptr.num_devices == 0)
-          {
-             e_comp_wl_input_pointer_enabled_set(EINA_FALSE);
-             e_pointer_object_set(comp->pointer, NULL, 0, 0);
-             e_pointer_hide(e_comp->pointer);
-          }
-     }
-
-end:
-   if (!e_randr2_cfg->ignore_hotplug_events)
-     e_randr2_screen_refresh_queue(EINA_TRUE);
-
-   return ECORE_CALLBACK_PASS_ON;
-}
-
-static void
-_e_mod_drm_cb_ee_resize(Ecore_Evas *ee EINA_UNUSED)
-{
-   e_comp_canvas_update();
-}
-
-static Ecore_Drm_Output_Mode *
-_e_mod_drm_mode_screen_find(E_Randr2_Screen *s, Ecore_Drm_Output *output)
-{
-   Ecore_Drm_Output_Mode *mode, *m = NULL;
-   const Eina_List *l;
-   int diff, distance = 0x7fffffff;
-
-   EINA_LIST_FOREACH(ecore_drm_output_modes_get(output), l, mode)
-     {
-        diff = (100 * abs(s->config.mode.w - mode->width)) + 
-          (100 * abs(s->config.mode.h - mode->height)) + 
-          fabs((100 * s->config.mode.refresh) - (100 * mode->refresh));
-        if (diff < distance)
-          {
-             m = mode;
-             distance = diff;
-          }
-     }
-
-   return m;
-}
-
-static Eina_Bool
-_e_mod_drm_output_exists(Ecore_Drm_Output *output, unsigned int crtc)
-{
-   /* find out if this output can go into the 'possibles' */
-   return ecore_drm_output_possible_crtc_get(output, crtc);
-}
-
-static char *
-_e_mod_drm_output_screen_get(Ecore_Drm_Output *output)
-{
-   const char *model;
-
-   model = ecore_drm_output_model_get(output);
-   if (!model) return NULL;
-
-   return strdup(model);
-}
-
-static E_Randr2_Screen *
-_info_unconf_primary_find(E_Randr2 *r)
-{
-   Eina_List *l;
-   E_Randr2_Screen *s, *s_primary = NULL;
-   int priority = 0;
-
-   EINA_LIST_FOREACH(r->screens, l, s)
-     {
-        if (!((s->config.enabled) && 
-              (s->config.mode.w > 0) && (s->config.mode.h > 0) &&
-              (s->config.geom.w > 0) && (s->config.geom.h > 0)))
-          continue;
-        if (s->config.priority > priority)
-          {
-             s_primary = s;
-             priority = s->config.priority;
-          }
-     }
-
-   return s_primary;
-}
-
-static E_Randr2_Screen *
-_info_unconf_left_find(E_Randr2 *r)
-{
-   Eina_List *l;
-   E_Randr2_Screen *s, *s_left = NULL;
-   int left_x = 0x7fffffff;
-   int left_size = 0;
-
-   EINA_LIST_FOREACH(r->screens, l, s)
-     {
-        if (!((s->config.enabled) &&
-              (s->config.mode.w > 0) && (s->config.mode.h > 0) &&
-              (s->config.geom.w > 0) && (s->config.geom.h > 0)))
-          continue;
-        if ((s->config.geom.x <= left_x) &&
-            ((s->config.geom.w * s->config.geom.h) > left_size))
-          {
-             left_size = s->config.geom.w * s->config.geom.h;
-             left_x = s->config.geom.x;
-             s_left = s;
-          }
-     }
-   return s_left;
-}
-
-static E_Randr2_Screen *
-_info_unconf_closest_find(E_Randr2 *r, E_Randr2_Screen *s2, Eina_Bool configured)
-{
-   Eina_List *l;
-   E_Randr2_Screen *s, *s_sel = NULL;
-   int dist = 0x7fffffff;
-   int dx, dy;
-
-   EINA_LIST_FOREACH(r->screens, l, s)
-     {
-        if (s == s2) continue;
-        if (!((s->config.enabled) &&
-              (s->config.mode.w > 0) && (s->config.mode.h > 0) &&
-              (s->config.geom.w > 0) && (s->config.geom.h > 0)))
-          continue;
-        if ((!configured) &&
-            (s->config.relative.mode != E_RANDR2_RELATIVE_UNKNOWN))
-          continue;
-        else if ((configured) &&
-                 (s->config.relative.mode == E_RANDR2_RELATIVE_UNKNOWN))
-          continue;
-        dx = (s->config.geom.x + (s->config.geom.w / 2)) -
-          (s2->config.geom.x + (s2->config.geom.w / 2));
-        dy = (s->config.geom.y + (s->config.geom.h / 2)) -
-          (s2->config.geom.y + (s2->config.geom.h / 2));
-        dx = sqrt((dx * dx) + (dy * dy));
-        if (dx < dist)
-          {
-             s_sel = s;
-             dist = dx;
-          }
-     }
-   return s_sel;
-}
-
-static void
-_e_mod_drm_relative_fixup(E_Randr2 *r)
-{
-   E_Randr2_Screen *s, *s2;
-   int d, dx, dy;
-
-   s = _info_unconf_primary_find(r);
-   if (s)
-     s->config.relative.mode = E_RANDR2_RELATIVE_NONE;
-   else
-     {
-        s = _info_unconf_left_find(r);
-        if (!s) return;
-        s->config.relative.mode = E_RANDR2_RELATIVE_NONE;
-     }
-
-   for (;;)
-     {
-        // find the next screen that is closest to the last one we configured
-        /// that is still not configured yet
-        s = _info_unconf_closest_find(r, s, EINA_FALSE);
-        if (!s) break;
-        s2 = _info_unconf_closest_find(r, s, EINA_TRUE);
-        // fix up s->config.relative.mode, s->config.relative.to and
-        // s->config.relative.align to match (as closely as possible)
-        // the geometry given - config s relative to s2
-        if (!s2) s->config.relative.mode = E_RANDR2_RELATIVE_NONE;
-        else
-          {
-             s->config.relative.to = strdup(s2->id);
-             s->config.relative.align = 0.0;
-             s->config.relative.mode = E_RANDR2_RELATIVE_NONE;
-             if ((s->config.geom.x + s->config.geom.w) <=
-                 s2->config.geom.x)
-               {
-                  s->config.relative.mode = E_RANDR2_RELATIVE_TO_LEFT;
-                  d = s->config.geom.h - s2->config.geom.h;
-                  dy = s2->config.geom.y - s->config.geom.y;
-                  if (d != 0)
-                    s->config.relative.align = ((double)dy) / ((double)d);
-               }
-             else if (s->config.geom.x >=
-                      (s2->config.geom.x + s2->config.geom.w))
-               {
-                  s->config.relative.mode = E_RANDR2_RELATIVE_TO_RIGHT;
-                  d = s->config.geom.h - s2->config.geom.h;
-                  dy = s2->config.geom.y - s->config.geom.y;
-                  if (d != 0)
-                    s->config.relative.align = ((double)dy) / ((double)d);
-               }
-             else if ((s->config.geom.y + s->config.geom.h) <=
-                      s2->config.geom.y)
-               {
-                  s->config.relative.mode = E_RANDR2_RELATIVE_TO_ABOVE;
-                  d = s->config.geom.w - s2->config.geom.w;
-                  dx = s2->config.geom.x - s->config.geom.x;
-                  if (d != 0)
-                    s->config.relative.align = ((double)dx) / ((double)d);
-               }
-             else if (s->config.geom.y >=
-                      (s2->config.geom.y + s2->config.geom.h))
-               {
-                  s->config.relative.mode = E_RANDR2_RELATIVE_TO_BELOW;
-                  d = s->config.geom.w - s2->config.geom.w;
-                  dx = s2->config.geom.x - s->config.geom.x;
-                  if (d != 0)
-                    s->config.relative.align = ((double)dx) / ((double)d);
-               }
-             else if ((s->config.geom.x == s2->config.geom.x) &&
-                      (s->config.geom.y == s2->config.geom.y) &&
-                      (s->config.geom.w == s2->config.geom.w) &&
-                      (s->config.geom.h == s2->config.geom.h))
-               {
-                  s->config.relative.mode = E_RANDR2_RELATIVE_CLONE;
-               }
-             if (s->config.relative.align < 0.0)
-               s->config.relative.align = 0.0;
-             else if (s->config.relative.align > 1.0)
-               s->config.relative.align = 1.0;
-          }
-     }
-}
-
-static E_Randr2 *
-_drm_randr_create(void)
-{
-   Ecore_Drm_Device *dev;
-   Ecore_Drm_Output *output;
-   const Eina_List *l, *ll;
-   E_Randr2 *r = NULL;
-   const char *conn_types[] =
-     {
-        "None", "VGA", "DVI-I", "DVI-D", "DVI-A",
-        "Composite", "S-Video", "LVDS", "Component", "DIN",
-        "DisplayPort", "HDMI-A", "HDMI-B", "TV", "eDP", "Virtual",
-        "DSI", "UNKNOWN"
-     };
-   E_Randr2_Connector rtype[] =
-     {
-        E_RANDR2_CONNECTOR_UNDEFINED,
-        E_RANDR2_CONNECTOR_UNDEFINED,
-        E_RANDR2_CONNECTOR_DVI,
-        E_RANDR2_CONNECTOR_DVI,
-        E_RANDR2_CONNECTOR_DVI,
-        E_RANDR2_CONNECTOR_UNDEFINED,
-        E_RANDR2_CONNECTOR_UNDEFINED,
-        E_RANDR2_CONNECTOR_UNDEFINED,
-        E_RANDR2_CONNECTOR_UNDEFINED,
-        E_RANDR2_CONNECTOR_UNDEFINED,
-        E_RANDR2_CONNECTOR_DISPLAY_PORT,
-        E_RANDR2_CONNECTOR_HDMI_A,
-        E_RANDR2_CONNECTOR_HDMI_B,
-        E_RANDR2_CONNECTOR_UNDEFINED,
-        E_RANDR2_CONNECTOR_DISPLAY_PORT,
-        E_RANDR2_CONNECTOR_UNDEFINED,
-        E_RANDR2_CONNECTOR_UNDEFINED,
-        E_RANDR2_CONNECTOR_UNDEFINED,
-     };
-   unsigned int type;
-
-   printf("DRM RRR: ................. info get!\n");
-
-   r = E_NEW(E_Randr2, 1);
-   if (!r) return NULL;
-
-   EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
-     {
-        EINA_LIST_FOREACH(dev->outputs, ll, output)
-          {
-             E_Randr2_Screen *s;
-             E_Config_Randr2_Screen *cs;
-             const Eina_List *m;
-             Ecore_Drm_Output_Mode *omode;
-             // size_t n, e = 0;
-             unsigned int j;
-             int priority;
-             Eina_Bool ok = EINA_FALSE;
-             Eina_Bool possible = EINA_FALSE;
-             int len = 0;
-
-             s = E_NEW(E_Randr2_Screen, 1);
-             if (!s) continue;
-
-             s->info.name = ecore_drm_output_name_get(output);
-             printf("DRM RRR: .... out %s\n", s->info.name);
-
-             s->info.connected = ecore_drm_output_connected_get(output);
-             printf("DRM RRR: ...... connected %i\n", s->info.connected);
-
-             s->info.screen = _e_mod_drm_output_screen_get(output);
-
-             s->info.edid = ecore_drm_output_edid_get(output);
-             if (s->info.edid)
-               s->id = malloc(strlen(s->info.name) + 1 + strlen(s->info.edid) + 1);
-             else
-               s->id = malloc(strlen(s->info.name) + 1 + 1);
-             if (!s->id)
-               {
-                  free(s->info.screen);
-                  free(s->info.edid);
-                  free(s);
-                  continue;
-               }
-             len = strlen(s->info.name);
-             strncpy(s->id, s->info.name, len + 1);
-             strncat(s->id, "/", 1);
-             if (s->info.edid) strncat(s->id, s->info.edid, strlen(s->info.edid));
-
-             printf("DRM RRR: Created Screen: %s\n", s->id);
-
-             type = MIN(ecore_drm_output_connector_type_get(output),
-                        EINA_C_ARRAY_LENGTH(conn_types) - 1);
-             s->info.connector = rtype[type];
-             s->info.is_lid = ((type == DRM_MODE_CONNECTOR_LVDS) || 
-                               (type == DRM_MODE_CONNECTOR_eDP));
-             s->info.lid_closed = (s->info.is_lid && e_acpi_lid_is_closed());
-             printf("DRM RRR: ...... lid_closed = %i (%i && %i)\n",
-                    s->info.lid_closed, s->info.is_lid, e_acpi_lid_is_closed());
-
-             s->info.backlight = ecore_drm_output_backlight_get(output);
-
-             ecore_drm_output_physical_size_get(output, &s->info.size.w,
-                                                &s->info.size.h);
-
-             EINA_LIST_FOREACH(ecore_drm_output_modes_get(output), m, omode)
-               {
-                  E_Randr2_Mode *rmode;
-
-                  rmode = malloc(sizeof(E_Randr2_Mode));
-                  if (!rmode) continue;
-
-                  rmode->w = omode->width;
-                  rmode->h = omode->height;
-                  rmode->refresh = omode->refresh;
-                  rmode->preferred = (omode->flags & DRM_MODE_TYPE_PREFERRED);
-
-                  s->info.modes = eina_list_append(s->info.modes, rmode);
-               }
-
-             cs = NULL;
-             priority = 0;
-             if (e_randr2_cfg)
-               cs = e_randr2_config_screen_find(s, e_randr2_cfg);
-             if (cs)
-               priority = cs->priority;
-             else if (ecore_drm_output_primary_get(dev) == output)
-               priority = 100;
-             s->config.priority = priority;
-
-             for (j = 0; j < dev->crtc_count; j++)
-               {
-                  if (dev->crtcs[j] == ecore_drm_output_crtc_id_get(output))
-                    {
-                       ok = EINA_TRUE;
-                       break;
-                    }
-               }
-
-             if (!ok)
-               {
-                  /* get possible crtcs, compare to output_crtc_id_get */
-                  for (j = 0; j < dev->crtc_count; j++)
-                    {
-                       if (_e_mod_drm_output_exists(output, dev->crtcs[j]))
-                         {
-                            ok = EINA_TRUE;
-                            possible = EINA_TRUE;
-                            break;
-                         }
-                    }
-               }
-
-             if (ok)
-               {
-                  if (!possible)
-                    {
-                       unsigned int refresh;
-
-                       ecore_drm_output_position_get(output, &s->config.geom.x,
-                                                     &s->config.geom.y);
-                       ecore_drm_output_crtc_size_get(output, &s->config.geom.w,
-                                                      &s->config.geom.h);
-
-                       ecore_drm_output_current_resolution_get(output,
-                                                               &s->config.mode.w,
-                                                               &s->config.mode.h,
-                                                               &refresh);
-                       s->config.mode.refresh = refresh;
-                       s->config.enabled = 
-                         ((s->config.mode.w != 0) && (s->config.mode.h != 0));
-
-                       printf("DRM RRR: '%s' %i %i %ix%i\n", s->info.name,
-                              s->config.geom.x, s->config.geom.y,
-                              s->config.geom.w, s->config.geom.h);
-                    }
-
-                  /* TODO: are rotations possible ?? */
-               }
-
-             r->screens = eina_list_append(r->screens, s);
-          }
-     }
-
-   _e_mod_drm_relative_fixup(r);
-
-   return r;
-}
-
-static Eina_Bool
-_drm_randr_available(void)
-{
-   return EINA_TRUE;
-}
-
-static void
-_drm_randr_stub(void)
-{}
-
-static void
-_drm_randr_apply(void)
-{
-   Ecore_Drm_Device *dev;
-   Ecore_Drm_Output *out;
-   E_Randr2_Screen *s;
-   const Eina_List *l, *ll;
-   int nw, nh, pw, ph, ww, hh;
-   int minw, minh, maxw, maxh;
-   int top_priority = 0;
-
-   /* TODO: what the actual fuck */
-
-   nw = e_randr2->w;
-   nh = e_randr2->h;
-   EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
-     {
-        ecore_drm_screen_size_range_get(dev, &minw, &minh, &maxw, &maxh);
-        printf("DRM RRR: size range: %ix%i -> %ix%i\n", minw, minh, maxw, maxh);
-
-        ecore_drm_outputs_geometry_get(dev, NULL, NULL, &pw, &ph);
-        if (nw > maxw) nw = maxw;
-        if (nh > maxh) nh = maxh;
-        if (nw < minw) nw = minw;
-        if (nh < minh) nh = minh;
-        ww = nw;
-        hh = nh;
-        if (nw < pw) ww = pw;
-        if (nh < ph) hh = ph;
-
-        printf("DRM RRR: set vsize: %ix%i\n", ww, hh);
-
-        EINA_LIST_FOREACH(e_randr2->screens, ll, s)
-          {
-             //int orient; // FIXME
-             Ecore_Drm_Output_Mode *mode = NULL;
-
-             printf("DRM RRR: find output for '%s'\n", s->info.name);
-
-             out = ecore_drm_device_output_name_find(dev, s->info.name);
-             if (!out) continue;
-
-             if (s->config.configured)
-               {
-                  printf("\tDRM RRR: configured by E\n");
-
-                  if (s->config.enabled)
-                    {
-                       printf("\tDRM RRR: Enabled\n");
-                       mode = _e_mod_drm_mode_screen_find(s, out);
-                    }
-                  else
-                    {
-                       printf("\tDRM RRR: Disabled\n");
-                    }
-
-                  if (s->config.priority > top_priority)
-                    top_priority = s->config.priority;
-
-                  printf("\tDRM RRR: Priority: %d\n", s->config.priority);
-
-                  printf("\tDRM RRR: Geom: %d %d %d %d\n", 
-                         s->config.geom.x, s->config.geom.y,
-                         s->config.geom.w, s->config.geom.h);
-
-                  if (mode)
-                    {
-                       printf("\tDRM RRR: Found Valid Drm Mode\n");
-                       printf("\t\tDRM RRR: %dx%d\n", mode->width, mode->height);
-                    }
-                  else
-                    printf("\tDRM RRR: No Valid Drm Mode Found\n");
-
-                  // FIXME
-                  //if (s->config.rotation == 0)
-                  //  orient = (1 << 0);
-                  //else if (s->config.rotation == 90)
-                  //  orient = (1 << 1);
-                  //else if (s->config.rotation == 180)
-                  //  orient = (1 << 2);
-                  //else if (s->config.rotation == 270)
-                  //  orient = (1 << 3);
-
-                  ecore_drm_output_mode_set(out, mode,
-                                            s->config.geom.x, s->config.geom.y);
-                  if (s->config.priority == top_priority)
-                    ecore_drm_output_primary_set(out);
-
-                  if (s->config.enabled)
-                    ecore_drm_output_enable(out);
-                  else
-                    ecore_drm_output_disable(out);
-
-                  printf("\tDRM RRR: Mode\n");
-                  printf("\t\tDRM RRR: Geom: %d %d\n",
-                         s->config.mode.w, s->config.mode.h);
-                  printf("\t\tDRM RRR: Refresh: %f\n", s->config.mode.refresh);
-                  printf("\t\tDRM RRR: Preferred: %d\n",
-                         s->config.mode.preferred);
-
-                  printf("\tDRM RRR: Rotation: %d\n", s->config.rotation);
-
-                  printf("\tDRM RRR: Relative Mode: %d\n",
-                         s->config.relative.mode);
-                  printf("\tDRM RRR: Relative To: %s\n",
-                         s->config.relative.to);
-                  printf("\tDRM RRR: Align: %f\n", s->config.relative.align);
-               }
-          }
-     }
-}
-
-static void
-_drm_dpms(int set)
-{
-   Ecore_Drm_Device *dev;
-   Ecore_Drm_Output *out;
-   E_Randr2_Screen *s;
-   const Eina_List *l, *ll;
-
-   EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
-     {
-        EINA_LIST_FOREACH(e_randr2->screens, ll, s)
-          {
-             out = ecore_drm_device_output_name_find(dev, s->info.name);
-             if (!out) continue;
-
-             if ((!s->config.configured) || s->config.enabled)
-               ecore_drm_output_dpms_set(out, set);
-          }
-     }
-}
-
-static E_Comp_Screen_Iface drmiface =
-{
-   .available = _drm_randr_available,
-   .init = _drm_randr_stub,
-   .shutdown = _drm_randr_stub,
-   .create = _drm_randr_create,
-   .apply = _drm_randr_apply,
-   .dpms = _drm_dpms,
-};
-
-static void
-_drm_read_pixels(E_Comp_Wl_Output *output, void *pixels)
-{
-   Ecore_Drm_Device *dev;
-   Ecore_Drm_Fb *fb;
-   const Eina_List *drm_devs, *l;
-   int i = 0, bstride;
-   unsigned char *s, *d = pixels;
-
-   drm_devs = ecore_drm_devices_get();
-   EINA_LIST_FOREACH(drm_devs, l, dev)
-     {
-        fb = dev->next;
-        if (!fb) fb = dev->current;
-        if (fb) break;
-     }
-
-   if (!fb) return;
-
-   bstride = output->w * sizeof(int);
-
-   for (i = output->y; i < output->y + output->h; i++)
-     {
-        s = fb->mmap;
-        s += (fb->stride * i) + (output->x * sizeof(int));
-        memcpy(d, s, (output->w * sizeof(int)));
-        d += bstride;
-     }
-}
-
-E_API void
-_e_mod_drm_keymap_set(struct xkb_context **ctx, struct xkb_keymap **map)
-{
-   char *keymap_path = NULL;
-   struct xkb_context *context;
-   struct xkb_keymap *keymap;
-   struct xkb_rule_names names = {0,};
-
-   TRACE_INPUT_BEGIN(_e_mod_drm_keymap_set);
-
-   context = xkb_context_new(0);
-   EINA_SAFETY_ON_NULL_RETURN(context);
-
-   /* assemble xkb_rule_names so we can fetch keymap */
-   memset(&names, 0, sizeof(names));
-   names.rules = strdup("evdev");
-   names.model = strdup("pc105");
-   names.layout = strdup("us");
-
-   keymap = e_comp_wl_input_keymap_compile(context, names, &keymap_path);
-   eina_stringshare_del(keymap_path);
-   EINA_SAFETY_ON_NULL_GOTO(keymap, cleanup);
-
-   *ctx = context;
-   *map = keymap;
-
-   if (dont_set_ecore_drm_keymap == EINA_FALSE)
-     {
-        ecore_drm_device_keyboard_cached_context_set(*ctx);
-        ecore_drm_device_keyboard_cached_keymap_set(*map);
-     }
-
-cleanup:
-   free((char *)names.rules);
-   free((char *)names.model);
-   free((char *)names.layout);
-
-   TRACE_INPUT_END();
-}
-
-E_API void *
-e_modapi_init(E_Module *m)
-{
-   E_Comp *comp;
-   int w = 0, h = 0, scr_w = 0, scr_h = 0;
-   const char *env_w, *env_h;
-   struct xkb_context *ctx = NULL;
-   struct xkb_keymap *map = NULL;
-   char buf[1024];
-
-   e_main_ts("\twl_drm Init Begin");
-
-   dont_set_ecore_drm_keymap = getenv("NO_ECORE_DRM_KEYMAP_CACHE") ? EINA_TRUE : EINA_FALSE;
-   dont_use_xkb_cache = getenv("NO_KEYMAP_CACHE") ? EINA_TRUE : EINA_FALSE;
-
-   TRACE_DS_BEGIN(WL_DRM:INIT);
-
-   if (!(comp = e_comp))
-     {
-        comp = e_comp_new();
-        if (!comp)
-          {
-             TRACE_DS_END();
-             EINA_SAFETY_ON_NULL_RETURN_VAL(comp, NULL);
-          }
-
-        comp->comp_type = E_PIXMAP_TYPE_WL;
-     }
-
-   /* set gl available if we have ecore_evas support */
-   if (ecore_evas_engine_type_supported_get(ECORE_EVAS_ENGINE_OPENGL_DRM))
-     e_comp_gl_set(EINA_TRUE);
-
-   env_w = getenv("E_SCREEN_WIDTH");
-   if (env_w)
-     {
-        snprintf(buf, sizeof(buf), "%s", env_w);
-        scr_w = atoi(buf);
-     }
-
-   env_h = getenv("E_SCREEN_HEIGHT");
-   if (env_h)
-     {
-        snprintf(buf, sizeof(buf), "%s", env_h);
-        scr_h = atoi(buf);
-     }
-
-   if (scr_w <= 0) scr_w = 1;
-   if (scr_h <= 0) scr_h = 1;
-
-   DBG("GL available:%d config engine:%d screen size:%dx%d",
-       e_comp_gl_get(), e_comp_config_get()->engine, scr_w, scr_h);
-
-   if (e_config->xkb.use_cache && !dont_use_xkb_cache)
-     {
-        e_main_ts("\tDRM Keymap Init");
-        _e_mod_drm_keymap_set(&ctx, &map);
-        e_main_ts("\tDRM Keymap Init Done");
-     }
-
-   if ((e_comp_gl_get()) &&
-       (e_comp_config_get()->engine == E_COMP_ENGINE_GL))
-     {
-        e_main_ts("\tEE_GL_DRM New");
-        comp->ee = ecore_evas_gl_drm_new(NULL, 0, 0, 0, scr_w, scr_h);
-        snprintf(buf, sizeof(buf), "\tEE_GL_DRM New Done %p %dx%d", comp->ee, scr_w, scr_h);
-        e_main_ts(buf);
-
-        if (!comp->ee)
-          e_comp_gl_set(EINA_FALSE);
-        else
-          {
-             Evas_GL *evasgl = NULL;
-             Evas_GL_API *glapi = NULL;
-
-             e_main_ts("\tEvas_GL New");
-             evasgl = evas_gl_new(ecore_evas_get(comp->ee));
-             if (evasgl)
-               {
-                  glapi = evas_gl_api_get(evasgl);
-                  if (!((glapi) && (glapi->evasglBindWaylandDisplay)))
-                    {
-                       e_comp_gl_set(EINA_FALSE);
-                       ecore_evas_free(comp->ee);
-                       comp->ee = NULL;
-                       e_main_ts("\tEvas_GL New Failed 1");
-                    }
-                  else
-                    {
-                       e_main_ts("\tEvas_GL New Done");
-                    }
-               }
-             else
-               {
-                  e_comp_gl_set(EINA_FALSE);
-                  ecore_evas_free(comp->ee);
-                  comp->ee = NULL;
-                  e_main_ts("\tEvas_GL New Failed 2");
-               }
-             evas_gl_free(evasgl);
-          }
-     }
-
-   /* fallback to framebuffer drm (non-accel) */
-   if (!comp->ee)
-     {
-        e_main_ts("\tEE_DRM New");
-        comp->ee = ecore_evas_drm_new(NULL, 0, 0, 0, scr_w, scr_h);
-        snprintf(buf, sizeof(buf), "\tEE_DRM New Done %p %dx%d", comp->ee, scr_w, scr_h);
-        e_main_ts(buf);
-     }
-
-   if (!comp->ee)
-     {
-        fprintf(stderr, "Could not create ecore_evas_drm canvas");
-        TRACE_DS_END();
-        return NULL;
-     }
-
-   ecore_evas_data_set(e_comp->ee, "comp", e_comp);
-
-   /* get the current screen geometry */
-   ecore_evas_screen_geometry_get(e_comp->ee, NULL, NULL, &w, &h);
-
-   /* resize the canvas */
-   if (!((scr_w == w) && (scr_h == h)))
-     {
-        snprintf(buf, sizeof(buf), "\tEE Resize %dx%d -> %dx%d", scr_w, scr_h, w, h);
-        e_main_ts(buf);
-
-        ecore_evas_resize(comp->ee, w, h);
-
-        e_main_ts("\tEE Resize Done");
-     }
-
-   ecore_evas_callback_resize_set(e_comp->ee, _e_mod_drm_cb_ee_resize);
-
-   e_comp->screen = &drmiface;
-
-   e_main_ts("\tE_Comp_Wl Init");
-   if (!e_comp_wl_init())
-     {
-        TRACE_DS_END();
-        return NULL;
-     }
-   e_main_ts("\tE_Comp_Wl Init Done");
-
-   e_main_ts("\tE_Comp_Canvas Init");
-   if (!e_comp_canvas_init(w, h))
-     {
-        TRACE_DS_END();
-        return NULL;
-     }
-   e_main_ts("\tE_Comp_Canvas Init Done");
-
-   e_comp_wl->screenshooter.read_pixels = _drm_read_pixels;
-
-   ecore_evas_pointer_xy_get(e_comp->ee,
-                             &e_comp_wl->ptr.x,
-                             &e_comp_wl->ptr.y);
-
-   evas_event_feed_mouse_in(e_comp->evas, 0, NULL);
-
-   /* comp->pointer =  */
-   /*   e_pointer_window_new(ecore_evas_window_get(comp->ee), 1); */
-   e_main_ts("\tE_Pointer New");
-   if ((comp->pointer = e_pointer_canvas_new(comp->ee, EINA_TRUE)))
-     {
-        comp->pointer->color = EINA_TRUE;
-        e_pointer_hide(comp->pointer);
-     }
-   e_main_ts("\tE_Pointer New Done");
-
-   /* FIXME: We need a way to trap for user changing the keymap inside of E
-    *        without the event coming from X11 */
-
-   /* FIXME: We should make a decision here ...
-    *
-    * Fetch the keymap from drm, OR set this to what the E config is....
-    */
-
-   /* FIXME: This is just for testing at the moment....
-    * happens to jive with what drm does */
-   e_main_ts("\tE_Comp_WL Keymap Init");
-   e_comp_wl_input_keymap_set("evdev", "pc105", "us", ctx, map);
-   e_main_ts("\tE_Comp_WL Keymap Init Done");
-
-   E_LIST_HANDLER_APPEND(event_handlers, ECORE_DRM_EVENT_ACTIVATE,         _e_mod_drm_cb_activate,         comp);
-   E_LIST_HANDLER_APPEND(event_handlers, ECORE_DRM_EVENT_OUTPUT,           _e_mod_drm_cb_output,           comp);
-   E_LIST_HANDLER_APPEND(event_handlers, ECORE_DRM_EVENT_INPUT_DEVICE_ADD, _e_mod_drm_cb_input_device_add, comp);
-   E_LIST_HANDLER_APPEND(event_handlers, ECORE_DRM_EVENT_INPUT_DEVICE_DEL, _e_mod_drm_cb_input_device_del, comp);
-
-   TRACE_DS_END();
-
-   return m;
-}
-
-E_API int
-e_modapi_shutdown(E_Module *m EINA_UNUSED)
-{
-   /* shutdown ecore_drm */
-   /* ecore_drm_shutdown(); */
-
-   dont_set_ecore_drm_keymap = EINA_FALSE;
-   dont_use_xkb_cache = EINA_FALSE;
-   E_FREE_LIST(event_handlers, ecore_event_handler_del);
-
-   return 1;
-}
-
-E_API int
-e_modapi_save(E_Module *m EINA_UNUSED)
-{
-   // do nothing
-   return 1;
-}