basic implementation of multi output supprot. consideration of review remarks 26/78226/1
authorRoman Peresipkyn <r.peresipkyn@samsung.com>
Fri, 10 Jun 2016 08:07:35 +0000 (11:07 +0300)
committerRoman Peresipkyn <r.peresipkyn@samsung.com>
Mon, 4 Jul 2016 14:42:41 +0000 (17:42 +0300)
The commit is a carcass multi output support and extended mode will
be implemented over. It is big and messy commit which represent itself
as squash of commits which were not accepted. To fit requirements and
review remarks next improvements have been bringed in:
1: code style following
2: none E Module API have been removed
3: EOM protocol does not send output name anymore
4: using none accepted Enlightenment API have been removed from EOM
5: Review remarks have been considered and corrected

Change-Id: I4f3a5de25512ca4f948ac0dcbc912152da545801
Signed-off-by: Roman Peresipkyn <r.peresipkyn@samsung.com>
configure.ac
packaging/e-mod-tizen-eom.spec
protocol/eom-client-protocol.h
protocol/eom-protocol.c
protocol/eom-server-protocol.h
src/e_mod_main.c
src/e_mod_main.h

index 37a7a06..56d3d27 100644 (file)
@@ -35,7 +35,7 @@ fi
 
 PKG_CHECK_MODULES(WAYLAND_SCANNER, wayland-scanner)
 PKG_CHECK_MODULES(WAYLAND, [wayland-server])
-PKG_CHECK_MODULES(ENLIGHTENMENT, [enlightenment, elementary, eom])
+PKG_CHECK_MODULES(ENLIGHTENMENT, [enlightenment, elementary, eom, wayland-tbm-server])
 
 dnl ========================================================================
 # checks for wayland only argument
index bb162a4..d0b941d 100644 (file)
@@ -19,6 +19,7 @@ BuildRequires:  pkgconfig(x11)
 %if %{with wayland}
 BuildRequires:  pkgconfig(wayland-server)
 BuildRequires:  pkgconfig(libtbm)
+BuildRequires:  pkgconfig(wayland-tbm-server)
 %endif
 BuildRequires:  pkgconfig(dlog)
 %if "%{?profile}" == "common"
index d38e84a..9a26b78 100644 (file)
@@ -145,6 +145,8 @@ enum wl_eom_attribute_state {
 
 /**
  * wl_eom - an interface to get the information of the external outputs
+ * @output_count: (none)
+ * @output_info: (none)
  * @output_type: (none)
  * @output_mode: (none)
  * @output_attribute: (none)
@@ -157,8 +159,8 @@ struct wl_eom_listener {
         * @count: (none)
         */
        void (*output_count)(void *data,
-                           struct wl_eom *wl_eom,
-                           uint32_t count);
+                            struct wl_eom *wl_eom,
+                            uint32_t count);
        /**
         * output_info - (none)
         * @output_id: (none)
@@ -171,16 +173,15 @@ struct wl_eom_listener {
         * @connection: (none)
         */
        void (*output_info)(void *data,
-                               struct wl_eom *wl_eom,
-                               uint32_t output_id,
-                               uint32_t type,
-                               uint32_t mode,
-                               uint32_t w,
-                               uint32_t h,
-                               uint32_t w_mm,
-                               uint32_t h_mm,
-                               uint32_t connection);
-
+                           struct wl_eom *wl_eom,
+                           uint32_t output_id,
+                           uint32_t type,
+                           uint32_t mode,
+                           uint32_t w,
+                           uint32_t h,
+                           uint32_t w_mm,
+                           uint32_t h_mm,
+                           uint32_t connection);
        /**
         * output_type - (none)
         * @output_id: (none)
@@ -225,9 +226,10 @@ wl_eom_add_listener(struct wl_eom *wl_eom,
 }
 
 #define WL_EOM_SET_ATTRIBUTE   0
-#define WL_EOM_GET_INFO                        1
+#define WL_EOM_GET_OUTPUT_INFO 1
 
 #define WL_EOM_SET_ATTRIBUTE_SINCE_VERSION     1
+#define WL_EOM_GET_OUTPUT_INFO_SINCE_VERSION   1
 
 static inline void
 wl_eom_set_user_data(struct wl_eom *wl_eom, void *user_data)
@@ -264,7 +266,7 @@ static inline void
 wl_eom_get_output_info(struct wl_eom *wl_eom, uint32_t output_id)
 {
        wl_proxy_marshal((struct wl_proxy *) wl_eom,
-                       WL_EOM_GET_INFO, output_id);
+                        WL_EOM_GET_OUTPUT_INFO, output_id);
 }
 
 #ifdef  __cplusplus
index ed56ef6..0568c61 100644 (file)
@@ -11,6 +11,7 @@ static const struct wl_interface *types[] = {
        NULL,
        NULL,
        NULL,
+       NULL,
 };
 
 static const struct wl_message wl_eom_requests[] = {
index 8ee0777..8c0e929 100644 (file)
@@ -146,6 +146,7 @@ enum wl_eom_attribute_state {
 /**
  * wl_eom - an interface to get the information of the external outputs
  * @set_attribute: (none)
+ * @get_output_info: (none)
  *
  * ***** TODO ******
  */
@@ -164,8 +165,8 @@ struct wl_eom_interface {
         * @output_id: (none)
         */
        void (*get_output_info)(struct wl_client *client,
-                             struct wl_resource *resource,
-                             uint32_t output_id);
+                               struct wl_resource *resource,
+                               uint32_t output_id);
 };
 
 #define WL_EOM_OUTPUT_COUNT    0
@@ -174,19 +175,20 @@ struct wl_eom_interface {
 #define WL_EOM_OUTPUT_MODE     3
 #define WL_EOM_OUTPUT_ATTRIBUTE        4
 
+#define WL_EOM_OUTPUT_COUNT_SINCE_VERSION      1
+#define WL_EOM_OUTPUT_INFO_SINCE_VERSION       1
 #define WL_EOM_OUTPUT_TYPE_SINCE_VERSION       1
 #define WL_EOM_OUTPUT_MODE_SINCE_VERSION       1
 #define WL_EOM_OUTPUT_ATTRIBUTE_SINCE_VERSION  1
 
 static inline void
-wl_eom_send_output_count(struct wl_resource *resource_, uint32_t output_id, uint32_t count)
+wl_eom_send_output_count(struct wl_resource *resource_, uint32_t count)
 {
-       wl_resource_post_event(resource_, WL_EOM_OUTPUT_COUNT, output_id, count);
+       wl_resource_post_event(resource_, WL_EOM_OUTPUT_COUNT, count);
 }
 
 static inline void
-wl_eom_send_output_info(struct wl_resource *resource_, uint32_t output_id, uint32_t type, uint32_t mode,
-                                                               uint32_t w, uint32_t h, uint32_t w_mm, uint32_t h_mm, uint32_t connection)
+wl_eom_send_output_info(struct wl_resource *resource_, uint32_t output_id, uint32_t type, uint32_t mode, uint32_t w, uint32_t h, uint32_t w_mm, uint32_t h_mm, uint32_t connection)
 {
        wl_resource_post_event(resource_, WL_EOM_OUTPUT_INFO, output_id, type, mode, w, h, w_mm, h_mm, connection);
 }
index 54203d5..06807e0 100644 (file)
@@ -9,12 +9,17 @@
 #include "e_mod_main.h"
 #include "eom-server-protocol.h"
 #include "Ecore_Drm.h"
+#include <wayland-tbm-server.h>
 
 E_API E_Module_Api e_modapi = { E_MODULE_API_VERSION, "EOM Module" };
-static E_EomEventData g_eom_event_data;
-static E_EomFakeBuffers fake_buffers;
 static E_EomPtr g_eom = NULL;
 
+static const struct wl_eom_interface _e_eom_wl_implementation =
+{
+   _e_eom_cb_wl_request_set_attribute,
+   _e_eom_cb_wl_request_get_output_info
+};
+
 /* EOM Output Attributes
 
    +----------------+------------+----------------+-------------+
@@ -45,655 +50,959 @@ static const char *eom_conn_types[] =
    "DSI",
 };
 
-static inline enum wl_eom_mode
-_e_eom_get_eom_mode()
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static inline eom_output_mode_e
+_e_eom_output_state_get_mode(E_EomOutputPtr output)
 {
-   return g_eom->eom_mode;
+   if (output == NULL)
+     return EOM_OUTPUT_MODE_NONE;
+   return output->mode;
 }
 
 static inline void
-_e_eom_set_eom_mode(enum wl_eom_mode mode)
+_e_eom_output_state_set_mode(E_EomOutputPtr output, eom_output_mode_e mode)
 {
-   g_eom->eom_mode = mode;
+   if (output == NULL)
+     return;
+   output->mode = mode;
 }
 
-static inline enum wl_eom_attribute_state
-_e_eom_get_eom_attribute_state()
+static inline eom_output_attribute_e
+_e_eom_output_state_get_attribute_state(E_EomOutputPtr output)
 {
-   return g_eom->eom_attribute_state;
+   if (output == NULL)
+     return EOM_OUTPUT_ATTRIBUTE_STATE_NONE;
+   return output->attribute_state;
 }
 
 static inline void
-_e_eom_set_eom_attribute_state(enum wl_eom_attribute_state attribute_state)
+_e_eom_output_attribute_state_set(E_EomOutputPtr output, eom_output_attribute_e attribute_state)
 {
-   g_eom->eom_attribute_state = attribute_state;
+   if (output == NULL)
+     return;
+   output->attribute_state = attribute_state;
 }
 
-static inline enum wl_eom_attribute
-_e_eom_get_eom_attribute()
+static inline eom_output_attribute_e
+_e_eom_output_state_get_attribute(E_EomOutputPtr output)
 {
-   return g_eom->eom_attribute;
+   if (output == NULL)
+     return EOM_OUTPUT_ATTRIBUTE_NONE;
+   return output->attribute;
 }
 
 static inline void
-_e_eom_set_eom_attribute_by_current_client(enum wl_eom_attribute attribute)
+_e_eom_output_state_set_force_attribute(E_EomOutputPtr output, eom_output_attribute_e attribute)
 {
-   g_eom->eom_attribute = attribute;
+   if (output == NULL)
+     return;
+   output->attribute = attribute;
 }
 
 static inline Eina_Bool
-_e_eom_set_eom_attribute(enum wl_eom_attribute attribute)
+_e_eom_output_state_set_attribute(E_EomOutputPtr output, eom_output_attribute_e attribute)
 {
-   if (attribute == WL_EOM_ATTRIBUTE_NONE || g_eom->eom_attribute == WL_EOM_ATTRIBUTE_NONE)
+   if (output == NULL)
+     return EINA_FALSE;
+
+   if (attribute == EOM_OUTPUT_ATTRIBUTE_NONE || output->attribute == EOM_OUTPUT_ATTRIBUTE_NONE)
      {
-        g_eom->eom_attribute = attribute;
+        output->attribute = attribute;
         return EINA_TRUE;
      }
 
-   if (eom_output_attributes[g_eom->eom_attribute - 1][attribute - 1] == 1)
+   if (eom_output_attributes[output->attribute - 1][attribute - 1] == 1)
      {
-        g_eom->eom_attribute = attribute;
+        output->attribute = attribute;
         return EINA_TRUE;
      }
 
    return EINA_FALSE;
 }
 
-static inline enum wl_eom_status
-_e_eom_get_eom_status()
+static inline tdm_output_conn_status
+_e_eom_output_state_get_status(E_EomOutputPtr output)
 {
-   return g_eom->eom_status;
+   if (output == NULL)
+     return TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
+   return output->status;
 }
 
 static inline void
-_e_eom_set_eom_status(enum wl_eom_status status)
+_e_eom_output_state_set_status(E_EomOutputPtr output, tdm_output_conn_status status)
 {
-   g_eom->eom_status = status;
+   if (output == NULL)
+     return;
+   output->status = status;
 }
 
 static void
-_e_eom_pp_cb(tbm_surface_h surface, void *user_data)
+_e_eom_cb_wl_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
 {
-   tdm_error tdm_err = TDM_ERROR_NONE;
-   E_EomEventDataPtr eom_data = NULL;
+   struct wl_resource *resource = NULL;
+   E_EomClientPtr new_client = NULL;
 
-   RETURNIFTRUE(user_data == NULL, "ERROR: PP EVENT: user data is NULL");
+   RETURNIFTRUE(data == NULL, "ERROR: data is NULL");
 
-   eom_data = (E_EomEventDataPtr)user_data;
+   E_EomPtr eom = data;
 
-   tdm_buffer_remove_release_handler(eom_data->dst_buffers[eom_data->pp_buffer],
-                                     _e_eom_pp_cb, eom_data);
+   resource = wl_resource_create(client,
+                         &wl_eom_interface,
+                         MIN(version, 1),
+                         id);
+   if (resource == NULL)
+     {
+        EOM_ERR("error. resource is null. (version :%d, id:%d)\n", version, id);
+        wl_client_post_no_memory(client);
+        return;
+     }
 
-   /* Stop EOM */
-   if (g_eom->eom_sate != UP)
-     return;
+   wl_resource_set_implementation(resource,
+                                  &_e_eom_wl_implementation,
+                                  eom,
+                                  _e_eom_cb_wl_resource_destory);
 
-   /* TODO: lock that flag??? */
-   /* If a client has committed its buffer stop mirror mode */
-   if (g_eom->is_mirror_mode == DOWN)
-     return;
+   EOM_DBG("send - output count : %d\n", g_eom->output_count);
 
-   tbm_surface_h src_buffer;
-   src_buffer = _e_eom_root_internal_tdm_surface_get(g_eom->int_output_name);
-   RETURNIFTRUE(src_buffer == NULL, "ERROR: PP EVENT: get root tdm surface");
+   wl_eom_send_output_count(resource, g_eom->output_count);
 
-   g_eom_event_data.pp_buffer = !g_eom_event_data.current_buffer;
+   if (g_eom->outputs)
+     {
+        Eina_List *l;
+        E_EomOutputPtr output = NULL;
 
-   tdm_err = tdm_buffer_add_release_handler(g_eom_event_data.dst_buffers[g_eom_event_data.pp_buffer],
-                                            _e_eom_pp_cb, &g_eom_event_data);
-   RETURNIFTRUE(tdm_err != TDM_ERROR_NONE, "ERROR: PP EVENT: set pp hadler:%d", tdm_err );
+        EINA_LIST_FOREACH(g_eom->outputs, l, output)
+          {
+             EOM_DBG("send - id : %d, type : %d, mode : %d, w : %d, h : %d, w_mm : %d, h_mm : %d, conn : %d\n",
+                     output->id, output->type, output->mode, output->width, output->height,
+                     output->phys_width, output->phys_height, output->status);
+             wl_eom_send_output_info(resource, output->id, output->type, output->mode, output->width, output->height,
+                                     output->phys_width, output->phys_height, output->status);
 
-   tdm_err = tdm_pp_attach(eom_data->pp, src_buffer, g_eom_event_data.dst_buffers[g_eom_event_data.pp_buffer]);
-   RETURNIFTRUE(tdm_err != TDM_ERROR_NONE, "ERROR: pp attach:%d\n", tdm_err);
+             wl_eom_send_output_attribute(resource,
+                                          output->id,
+                                          _e_eom_output_state_get_attribute(output),
+                                          _e_eom_output_state_get_attribute_state(output),
+                                          EOM_ERROR_NONE);
+          }
+     }
 
-   tdm_err = tdm_pp_commit(g_eom_event_data.pp);
-   RETURNIFTRUE(tdm_err != TDM_ERROR_NONE, "ERROR: PP EVENT: pp commit:%d", tdm_err );
+   new_client = E_NEW(E_EomClient, 1);
+   if (new_client == NULL)
+     {
+        EOM_ERR("allocate new client");
+        /*TODO: should resource be deleted?*/
+        return;
+     }
+
+   new_client->resource = resource;
+   new_client->current = EINA_FALSE;
+   new_client->output_id = -1;
+   new_client->buffers = NULL;
+
+   g_eom->clients = eina_list_append(g_eom->clients, new_client);
 }
 
 static void
-_e_eom_commit_cb(tdm_output *output EINA_UNUSED, unsigned int sequence EINA_UNUSED,
-                           unsigned int tv_sec EINA_UNUSED, unsigned int tv_usec EINA_UNUSED,
-                           void *user_data)
+_e_eom_cb_wl_resource_destory(struct wl_resource *resource)
 {
-   E_EomClientBufferPtr client_buffer = NULL;
-   E_EomEventDataPtr eom_data = NULL;
-   tdm_error err = TDM_ERROR_NONE;
-
-   RETURNIFTRUE(user_data == NULL, "ERROR: PP EVENT: user data is NULL");
-
-   eom_data = (E_EomEventDataPtr)user_data;
+   E_EomClientPtr client = NULL, iterator = NULL;
+   E_EomOutputPtr output = NULL;
+   Eina_List *l = NULL;
+   Eina_Bool ret;
 
-   /* Stop EOM */
-   if (g_eom->eom_sate != UP)
-     return;
+   EOM_DBG("client unbind\n");
 
-   /* TODO: Maybe better to separating that callback on to mirror and extended callbacks */
-   if (g_eom->is_mirror_mode == UP)
-     {
-        if (eom_data->current_buffer == 1)
-         {
-            eom_data->current_buffer = 0;
-
-            err = tdm_layer_set_buffer(eom_data->layer,
-                                       eom_data->dst_buffers[!eom_data->pp_buffer]);
-            RETURNIFTRUE(err != TDM_ERROR_NONE, "ERROR: EVENT: set buffer 0 err:%d", err);
-         }
-       else
-         {
-            eom_data->current_buffer = 1;
-
-            err = tdm_layer_set_buffer(eom_data->layer,
-                                       eom_data->dst_buffers[!eom_data->pp_buffer]);
-            RETURNIFTRUE(err != TDM_ERROR_NONE, "ERROR: EVENT: set buffer 1 err:%d", err);
-         }
-
-       err = tdm_output_commit(eom_data->output, 0, _e_eom_commit_cb, eom_data);
-       RETURNIFTRUE(err != TDM_ERROR_NONE, "ERROR: EVENT commit");
-     }
-   else
-     {
-        client_buffer = _e_eom_get_client_buffer_from_list();
-        RETURNIFTRUE(client_buffer == NULL, "ERROR: EVENT: client buffer is NULL");
+   client = _e_eom_client_get_by_resource(resource);
+   RETURNIFTRUE(client == NULL, "destroy client: client is NULL");
 
-        err = tdm_layer_set_buffer(eom_data->layer, client_buffer->tbm_buffer);
-        RETURNIFTRUE(err != TDM_ERROR_NONE, "ERROR: EVENT: set buffer 1");
+   g_eom->clients = eina_list_remove(g_eom->clients, client);
 
-        err = tdm_output_commit(eom_data->output, 0, _e_eom_commit_cb, eom_data);
-        RETURNIFTRUE(err != TDM_ERROR_NONE, "ERROR: EVENT: commit");
-     }
-}
+   /* If it is not current client do nothing */
+   GOTOIFTRUE(client->current == EINA_FALSE, end2, "");
 
-static void
-_e_eom_deinit_external_output()
-{
-   tdm_error err = TDM_ERROR_NONE;
-   int i = 0;
+   output = _e_eom_output_get_by_id(client->output_id);
+   GOTOIFTRUE(output == NULL, end2, "destroy client: client is NULL");
 
-   if (g_eom_event_data.layer)
-     {
-        err = tdm_layer_unset_buffer(g_eom_event_data.layer);
-        if (err != TDM_ERROR_NONE)
-          EOM_DBG("EXT OUTPUT DEINIT: fail unset buffer:%d\n", err);
-        else
-          EOM_DBG("EXT OUTPUT DEINIT: ok unset buffer:%d\n", err);
+   _e_eom_client_free_buffers(client);
 
-        err = tdm_output_commit(g_eom_event_data.output, 0, NULL, &g_eom_event_data);
-        if (err != TDM_ERROR_NONE)
-          EOM_DBG ("EXT OUTPUT DEINIT: fail commit:%d\n", err);
-        else
-          EOM_DBG("EXT OUTPUT DEINIT: ok commit:%d\n", err);
-    }
+   _e_eom_output_state_set_mode(output, EOM_OUTPUT_MODE_MIRROR);
+   ret = _e_eom_output_state_set_attribute(output, EOM_OUTPUT_ATTRIBUTE_NONE);
+   (void)ret;
 
-   /* TODO: do I need to do DPMS off? */
-   err = tdm_output_set_dpms(g_eom_event_data.output, TDM_OUTPUT_DPMS_OFF);
-   if (err != TDM_ERROR_NONE)
-     EOM_ERR("EXT OUTPUT DEINIT: failed set DPMS off:%d\n", err);
+   /* TODO: process case when output is not connected */
+   if (output->state == NONE)
+     goto end;
 
-   for (i = 0; i < NUM_MAIN_BUF; i++)
+   /* If a client has been disconnected and mirror mode has not
+    * been restored, start mirror mode
+    */
+   if (output->state != MIRROR)
      {
-        tdm_buffer_remove_release_handler(g_eom_event_data.dst_buffers[i],
-                                          _e_eom_pp_cb, &g_eom_event_data);
-        if (g_eom_event_data.dst_buffers[i])
-          tbm_surface_destroy(g_eom_event_data.dst_buffers[i]);
-    }
+        output->state = MIRROR;
 
-   if (g_eom->eom_sate == DOWN)
-      _e_eom_client_buffers_list_free(g_eom->eom_clients);
+        ret = _e_eom_output_start_pp(output);
+        GOTOIFTRUE(ret == EINA_FALSE, end,
+                   "ERROR: restore mirror mode after a client disconnection\n");
+     }
 
-   if (g_eom->int_output_name)
+end:
+   /* Notify eom clients which are binded to a concrete output that the
+    * state and mode of the output has been changed */
+   EINA_LIST_FOREACH(g_eom->clients, l, iterator)
      {
-        free(g_eom->int_output_name);
-        g_eom->int_output_name = NULL;
+        if (iterator && iterator->output_id == output->id)
+          {
+             wl_eom_send_output_attribute(iterator->resource,
+                                          output->id,
+                                          _e_eom_output_state_get_attribute(output),
+                                          _e_eom_output_state_get_attribute_state(output),
+                                          EOM_OUTPUT_MODE_NONE);
+
+             wl_eom_send_output_mode(iterator->resource,
+                                     output->id,
+                                     _e_eom_output_state_get_mode(output));
+          }
      }
 
-   if (g_eom->ext_output_name)
-    {
-       free(g_eom->ext_output_name);
-       g_eom->ext_output_name = NULL;
-    }
-
-   if (g_eom->wl_output)
-      g_eom->wl_output = NULL;
+end2:
+   free(client);
 }
 
-
-static tdm_layer *
-_e_eom_hal_layer_get(tdm_output *output, int width, int height)
+static Eina_Bool
+_e_eom_cb_ecore_drm_output(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
 {
-   int i = 0;
-   int count = 0;
-   tdm_layer *layer = NULL;
-   tdm_error err = TDM_ERROR_NONE;
-   tdm_layer_capability capa;
-   tdm_info_layer layer_info;
+   Ecore_Drm_Event_Output *e = NULL;
+   char buff[PATH_MAX];
+
+   if (!(e = event))  return ECORE_CALLBACK_PASS_ON;;
 
+   EOM_DBG("id:%d (x,y,w,h):(%d,%d,%d,%d) (w_mm,h_mm):(%d,%d) refresh:%d subpixel_order:%d transform:%d make:%s model:%s name:%s plug:%d\n",
+            e->id, e->x, e->y, e->w, e->h, e->phys_width, e->phys_height, e->refresh, e->subpixel_order, e->transform, e->make, e->model, e->name, e->plug);
 
-   err = tdm_output_get_layer_count(output, &count);
-   if (err != TDM_ERROR_NONE)
-     {
-        EOM_DBG ("tdm_output_get_layer_count fail(%d)\n", err);
-        return NULL;
-     }
+   snprintf(buff, sizeof(buff), "%s", e->name);
 
-   for (i = 0; i < count; i++)
+   /* main output */
+   if (e->id == 0)
      {
-        layer = (tdm_layer *)tdm_output_get_layer(output, i, &err);
-        RETURNVALIFTRUE(err != TDM_ERROR_NONE, NULL, "tdm_output_get_layer fail(%d)\n", err);
-
-        err = tdm_layer_get_capabilities(layer, &capa);
-        RETURNVALIFTRUE(err != TDM_ERROR_NONE, NULL, "tdm_layer_get_capabilities fail(%d)\n", err);
+        if (e->plug == 1)
+          {
+              g_eom->width = e->w;
+              g_eom->height = e->h;
+              if (g_eom->main_output_name == NULL)
+                g_eom->main_output_name = strdup(buff);
 
-        if (capa & TDM_LAYER_CAPABILITY_PRIMARY)
+              g_eom->main_output_state = UP;
+          }
+        else
           {
-             EOM_DBG("TDM_LAYER_CAPABILITY_PRIMARY layer found : %d\n", i);
-             break;
+             g_eom->width = -1;
+             g_eom->height = -1;
+             if (g_eom->main_output_name)
+               free(g_eom->main_output_name);
+
+             g_eom->main_output_state = DOWN;
           }
      }
 
-   memset(&layer_info, 0x0, sizeof(tdm_info_layer));
-   layer_info.src_config.size.h = width;
-   layer_info.src_config.size.v = height;
-   layer_info.src_config.pos.x = 0;
-   layer_info.src_config.pos.y = 0;
-   layer_info.src_config.pos.w = width;
-   layer_info.src_config.pos.h = height;
-   layer_info.src_config.format = TBM_FORMAT_ARGB8888;
-   layer_info.dst_pos.x = 0;
-   layer_info.dst_pos.y = 0;
-   layer_info.dst_pos.w = width;
-   layer_info.dst_pos.h = height;
-   layer_info.transform = TDM_TRANSFORM_NORMAL;
-
-   err = tdm_layer_set_info(layer, &layer_info);
-   RETURNVALIFTRUE(err != TDM_ERROR_NONE, NULL, "tdm_layer_set_info fail(%d)\n", err);
-
-   return layer;
+   return ECORE_CALLBACK_PASS_ON;
 }
 
-/* TODO: Models commited clients buffers */
-/*
-static void
-_e_eom_create_fake_buffers(int width, int height)
+static Eina_Bool
+_e_eom_cb_ecore_drm_activate(void *data, int type EINA_UNUSED, void *event)
 {
-   tbm_surface_info_s buffer_info;
-   tbm_surface_h buffer = NULL;
+ /*
+   Ecore_Drm_Event_Activate *e = NULL;
+   E_EomPtr eom = NULL;
 
-   buffer = tbm_surface_internal_create_with_flags(width, height, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
-   GOTOIFTRUE(buffer == NULL, err, "can not create fake_buffer\n");
+   EOM_DBG("_e_eom_cb_ecore_drm_activate called\n");
 
-   memset(&buffer_info, 0x0, sizeof(tbm_surface_info_s));
-   if (tbm_surface_map(buffer,
-                  TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE,
-                  &buffer_info) != TBM_SURFACE_ERROR_NONE)
+   if ((!event) || (!data)) goto end;
+   e = event;
+   eom = data;
+
+   EOM_DBG("e->active:%d\n", e->active);
+
+   if (e->active)
      {
-        EOM_DBG("can not mmap fake_buffer\n");
-        goto err;
+        ;
+     }
+   else
+     {
+        ;
      }
 
-   memset(buffer_info.planes[0].ptr, 0xFF, buffer_info.planes[0].size);
-   tbm_surface_unmap(buffer);
-
-   fake_buffers.fake_buffers[0] = buffer;
+end:
 
-err:
-   return;
-}
 */
+   return ECORE_CALLBACK_PASS_ON;
+}
 
 static Eina_Bool
-_e_eom_create_output_buffers(E_EomEventDataPtr eom_data, int width, int height)
+_e_eom_cb_client_buffer_change(void *data, int type, void *event)
 {
-   tbm_surface_info_s buffer_info;
-   tbm_surface_h buffer = NULL;
-
-   /*
-    * TODO: Add support of other formats
-    */
-   buffer = tbm_surface_internal_create_with_flags(width, height, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
-   GOTOIFTRUE(buffer == NULL, err, "can not create dst_buffer 1");
+   E_Comp_Wl_Buffer *external_wl_buffer = NULL;
+   E_EomClientBufferPtr client_buffer = NULL;
+   E_EomClientPtr client = NULL;
+   E_EomOutputPtr output = NULL;
+   E_Event_Client *ev = event;
+   E_Client *ec = NULL;
+   const char *output_name = NULL;
+   tbm_surface_h external_tbm_buffer = NULL;
+/*
+   tbm_surface_info_s surface_info;
+   int ret;
+*/
 
-   /*
-    * TODO: temp code for testing, actual convert will be in _e_eom_put_src_to_dst()
-    */
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ev->ec, ECORE_CALLBACK_PASS_ON);
 
-   memset(&buffer_info, 0x0, sizeof(tbm_surface_info_s));
-   if (tbm_surface_map(buffer,
-                       TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE,
-                       &buffer_info) != TBM_SURFACE_ERROR_NONE)
+   ec = ev->ec;
+   if (e_object_is_del(E_OBJECT(ec)))
      {
-        EOM_DBG("can not mmap buffer\n");
-        goto err;
+        EOM_ERR("ERROR: BUFF CHANGE: ec objects is del\n");
+        return ECORE_CALLBACK_PASS_ON;
      }
 
-   memset(buffer_info.planes[0].ptr, 0x0, buffer_info.planes[0].size);
-   tbm_surface_unmap(buffer);
+   /* TODO: implemente new client's buffers hooking mechanism */
+   return ECORE_CALLBACK_PASS_ON;
 
-   eom_data->dst_buffers[0] = buffer;
+   output = _e_eom_output_get_by_name(output_name);
+   RETURNVALIFTRUE(output == NULL,
+                   ECORE_CALLBACK_PASS_ON,
+                   "ERROR:BUFF CHANGE: eom_output is NULL\n");
 
-   /*
-    * TODO: Add support of other formats
-    */
-   buffer = tbm_surface_internal_create_with_flags(width, height, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
-   GOTOIFTRUE(buffer == NULL, err, "can not create dst_buffer 2");
+   if (ec->pixmap == NULL)
+     return ECORE_CALLBACK_PASS_ON;
 
-   /*
-    * TODO: temp code for testing, actual convert will be in _e_eom_put_src_to_dst()
-    */
-   memset(&buffer_info, 0x00, sizeof(tbm_surface_info_s));
-   if (tbm_surface_map(buffer,
-                       TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE,
-                       &buffer_info) != TBM_SURFACE_ERROR_NONE)
+   external_wl_buffer = e_pixmap_resource_get(ec->pixmap);
+   RETURNVALIFTRUE(external_wl_buffer == NULL,
+                   ECORE_CALLBACK_PASS_ON,
+                   "ERROR:BUFF CHANGE: wl buffer is NULL\n");
+/*
+   EOM_DBG("BUFF CHANGE: wl_buff:%dx%d type:%d",
+            external_wl_buffer->w,
+            external_wl_buffer->h,
+            external_wl_buffer->type);
+*/
+
+   /* TODO: support buffers smaller then output resolution */
+   if (external_wl_buffer->w != output->width ||
+       external_wl_buffer->h != output->height )
      {
-        EOM_DBG("can not mmap buffer\n");
-        goto err;
+        EOM_ERR("BUFF CHANGE: ERROR: tbm_buffer does not fit output's resolution");
+        return ECORE_CALLBACK_PASS_ON;
      }
 
-   memset(buffer_info.planes[0].ptr, 0x0, buffer_info.planes[0].size);
-   tbm_surface_unmap(buffer);
-
-   eom_data->dst_buffers[1] = buffer;
+   /* TODO: support different external_wl_buffer->type */
 
-   return EINA_TRUE;
+   if (external_wl_buffer->resource == NULL)
+     {
+        EOM_ERR("ERROR: BUFF CHANGE: resource is NULL\n");
+        return ECORE_CALLBACK_PASS_ON;
+     }
 
-err:
+   external_tbm_buffer = wayland_tbm_server_get_surface(
+                            e_comp->wl_comp_data->tbm.server,
+                            external_wl_buffer->resource);
+   if (external_tbm_buffer == NULL)
+     {
+        EOM_ERR("ERROR: BUFF CHANGE: client tbm buffer is NULL\n");
+        return ECORE_CALLBACK_PASS_ON;
+     }
 
-/*
- * Add deinitialization
- */
-   return EINA_FALSE;
-}
+   EOM_DBG("BUFF CHANGE: tbm_buffer %p", external_tbm_buffer);
 
-static enum wl_eom_type
-_e_eom_output_name_to_eom_type(const char *output_name)
-{
-   enum wl_eom_type eom_type;
+#if 0
+   _e_eom_util_draw(external_tbm_buffer);
+#endif
 
-   if (output_name == NULL)
-     return WL_EOM_TYPE_NONE;
+   /* mmap that buffer to get width and height for test's sake */
+   /*
+   memset(&surface_info, 0, sizeof(tbm_surface_info_s));
+   ret = tbm_surface_map(external_tbm_buffer, TBM_SURF_OPTION_READ |
+                       TBM_SURF_OPTION_WRITE, &surface_info);
+   if (ret != TBM_SURFACE_ERROR_NONE)
+     {
+        EOM_ERR("BUFF CHANGE: failed mmap buffer: %d", ret);
+        return ECORE_CALLBACK_PASS_ON;
+     }
 
-   /* TODO: Add other external outputs */
-   if (strcmp(output_name, "HDMI-A-0") == 0)
-     eom_type = WL_EOM_TYPE_HDMIA;
-   else
-     eom_type = WL_EOM_TYPE_NONE;
+   EOM_DBG("BUFF CHANGE: tbm_buffer: %dx%d", surface_info.width, surface_info.height);
 
-   return eom_type;
+   tbm_surface_unmap(external_tbm_buffer);
+   */
+
+   client_buffer = _e_eom_util_create_client_buffer(external_wl_buffer, external_tbm_buffer);
+   /* client_buffer = _e_eom_util_create_client_buffer(external_wl_buffer, output->fake_buffer); */
+   RETURNVALIFTRUE(client_buffer == NULL,
+                   ECORE_CALLBACK_PASS_ON,
+                   "ERROR: BUFF CHANGE: alloc client buffer");
+
+   /* TODO: What if not current client has committed a buffer */
+   client = _e_eom_client_current_by_id_get(output->id);
+   if (client == NULL)
+     {
+        EOM_ERR("ERROR: BUFF CHANGE: current client is NULL");
+        E_FREE(client_buffer);
+        return ECORE_CALLBACK_PASS_ON;
+     }
+
+   _e_eom_client_add_buffer(client, client_buffer);
+
+   output->state = PRESENTATION;
+
+   return ECORE_CALLBACK_PASS_ON;
 }
 
-static Eina_Bool
-_e_eom_mirror_start(const char *output_name, int width, int height)
+static void
+_e_eom_cb_pp(tbm_surface_h surface, void *user_data)
 {
-   /* should be changed in HWC enable environment */
-   tbm_surface_info_s src_buffer_info;
-   tbm_surface_h src_buffer = NULL;
-   Eina_Bool ret = EINA_FALSE;
+   tdm_error tdm_err = TDM_ERROR_NONE;
+   E_EomOutputPtr eom_output = NULL;
 
-   src_buffer = _e_eom_root_internal_tdm_surface_get(output_name);
-   RETURNVALIFTRUE(src_buffer == NULL, EINA_FALSE, "ERROR: get root tdm surfcae\n");
+   eom_output = (E_EomOutputPtr)user_data;
+   RETURNIFTRUE(user_data == NULL, "ERROR: PP EVENT: user data is NULL");
 
-   tbm_surface_get_info(src_buffer, &src_buffer_info );
+   tdm_buffer_remove_release_handler(eom_output->dst_buffers[eom_output->pp_buffer],
+                                     _e_eom_cb_pp, eom_output);
 
-   EOM_DBG("FRAMEBUFFER TDM: %dx%d   bpp:%d   size:%d",
-           src_buffer_info.width, src_buffer_info.height,
-           src_buffer_info.bpp, src_buffer_info.size);
+   /* TODO: lock these flags??? */
+   if (g_eom->main_output_state == DOWN)
+     return;
 
-   /*
-   g_eom->src_mode.w = width;
-   g_eom->src_mode.h = height;
-   g_eom->int_output_name = strdup(output_name);
-   */
+   /* If a client has committed its buffer stop mirror mode */
+   if (eom_output->state != MIRROR)
+     return;
 
-   /* TODO: if internal and external outputs are equal */
-   ret = _e_eom_pp_is_needed(g_eom->src_mode.w, g_eom->src_mode.h,
-                             g_eom->dst_mode.w, g_eom->dst_mode.h);
-   RETURNVALIFTRUE(ret == EINA_FALSE, EINA_TRUE, "pp is not required\n");
+   tbm_surface_h src_buffer;
+   src_buffer = _e_eom_util_get_output_surface(g_eom->main_output_name);
+   RETURNIFTRUE(src_buffer == NULL, "ERROR: PP EVENT: get root tdm surface");
 
-   ret = _e_eom_pp_src_to_dst(src_buffer);
-   RETURNVALIFTRUE(ret == EINA_FALSE, EINA_FALSE, "ERROR: init pp\n");
+   /*TODO: rewrite the mirror mode buffer's switching */
+   eom_output->pp_buffer ^= 1;
 
-   return EINA_TRUE;
+   tdm_err = tdm_buffer_add_release_handler(eom_output->dst_buffers[eom_output->pp_buffer],
+                                            _e_eom_cb_pp, eom_output);
+   RETURNIFTRUE(tdm_err != TDM_ERROR_NONE, "ERROR: PP EVENT: set pp hadler:%d", tdm_err );
+
+   tdm_err = tdm_pp_attach(eom_output->pp, src_buffer, eom_output->dst_buffers[eom_output->pp_buffer]);
+   RETURNIFTRUE(tdm_err != TDM_ERROR_NONE, "ERROR: pp attach:%d\n", tdm_err);
+
+   tdm_err = tdm_pp_commit(eom_output->pp);
+   RETURNIFTRUE(tdm_err != TDM_ERROR_NONE, "ERROR: PP EVENT: pp commit:%d", tdm_err );
 }
 
-static tbm_surface_h
-_e_eom_root_internal_tdm_surface_get(const char *name)
+static void
+_e_eom_cb_commit(tdm_output *output EINA_UNUSED, unsigned int sequence EINA_UNUSED,
+                           unsigned int tv_sec EINA_UNUSED, unsigned int tv_usec EINA_UNUSED,
+                           void *user_data)
 {
-   Ecore_Drm_Output *primary_output = NULL;
-   Ecore_Drm_Device *dev;
-   const Eina_List *l;
-#if 0
-   Ecore_Drm_Fb *fb;
-#else
-   tdm_output *tdm_output_obj = NULL;
-   tbm_surface_h tbm = NULL;
+   E_EomClientBufferPtr client_buffer = NULL;
+   E_EomOutputPtr eom_output = NULL;
+   E_EomClientPtr eom_client = NULL;
    tdm_error err = TDM_ERROR_NONE;
-   int count = 0, i = 0;
-#endif
 
-   EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
+   eom_output = (E_EomOutputPtr)user_data;
+   RETURNIFTRUE(user_data == NULL, "ERROR: COMMIT EVENT: user data is NULL");
+
+   if (g_eom->main_output_state == DOWN)
+     return;
+
+   /* TODO: Maybe better to separating that callback on to mirror and extended callbacks */
+   if (eom_output->state == MIRROR)
      {
-        primary_output = ecore_drm_device_output_name_find(dev, name);
-        if (primary_output != NULL)
-          break;
+        /*TODO: rewrite the mirror mode buffer's switching */
+        eom_output->current_buffer ^= 1;
+        err = tdm_layer_set_buffer(eom_output->layer,
+                                   eom_output->dst_buffers[eom_output->current_buffer]);
+
+        RETURNIFTRUE(err != TDM_ERROR_NONE, "ERROR: COMMIT EVENT: MIRROR: set buffer 0 err:%d", err);
+
+        err = tdm_output_commit(eom_output->output, 0, _e_eom_cb_commit, eom_output);
+        RETURNIFTRUE(err != TDM_ERROR_NONE, "ERROR: COMMIT EVENT: MIRROR: commit");
      }
+   else if (eom_output->state == PRESENTATION)
+     {
+        eom_client = _e_eom_client_current_by_id_get(eom_output->id);
 
-#if 0
-   RETURNVALIFTRUE(primary_output == NULL, NULL,
-                   "ERROR: get primary output.(%s)\n",
-                   name);
-
-   /* I think it is more convenient than one upon, but E took first
-    * output as primary and it can be not internal output
-    *
-   primary_output = ecore_drm_output_primary_get();
-   RETURNVALIFTRUE(primary_output == NULL, NULL, "ERROR: get primary output\n");
-   */
-#else
+        client_buffer = _e_eom_client_get_buffer(eom_client);
+        RETURNIFTRUE(client_buffer == NULL, "ERROR: COMMIT EVENT: PRESENTATION: client buffer is NULL");
 
-   if (primary_output == NULL)
+        err = tdm_layer_set_buffer(eom_output->layer, client_buffer->tbm_buffer);
+        RETURNIFTRUE(err != TDM_ERROR_NONE, "ERROR: COMMIT EVENT: PRESENTATION: set client buffer");
+
+        err = tdm_output_commit(eom_output->output, 0, _e_eom_cb_commit, eom_output);
+        RETURNIFTRUE(err != TDM_ERROR_NONE, "ERROR: COMMIT EVENT: PRESENTATION: commit");
+     }
+}
+
+static void
+_e_eom_cb_tdm_output_status_change(tdm_output *output, tdm_output_change_type type, tdm_value value, void *user_data)
+{
+   tdm_output_type tdm_type;
+   tdm_error ret = TDM_ERROR_NONE;
+   tdm_output_conn_status status;
+   tdm_output_conn_status status2;
+   const char *maker = NULL, *model = NULL, *name = NULL;
+   const char *tmp_name;
+   char new_name[DRM_CONNECTOR_NAME_LEN];
+   E_EomOutputPtr eom_output = NULL;
+   tdm_output_conn_status plug;
+   E_EomClientPtr iterator = NULL;
+   Eina_List *l;
+
+   if (type == TDM_OUTPUT_CHANGE_DPMS || g_eom->main_output_state == DOWN)
+     return;
+
+   if (g_eom->outputs)
      {
-        EOM_ERR("ERROR: get primary output.(%s)\n", name);
-        EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
-          {
-             primary_output = ecore_drm_output_primary_get(dev);
-             if (primary_output != NULL)
-               break;
-          }
+        Eina_List *l;
+        E_EomOutputPtr eom_output_tmp;
 
-        if (primary_output == NULL)
+        EINA_LIST_FOREACH(g_eom->outputs, l, eom_output_tmp)
           {
-             EOM_ERR("ERROR: get primary output.(%s)\n", name);
-             return NULL;
+             if (eom_output_tmp->output == output)
+               eom_output = eom_output_tmp;
           }
      }
-#endif
 
-#if 0
-   fb = ecore_drm_display_output_primary_layer_fb_get(primary_output);
-   RETURNVALIFTRUE(fb == NULL, NULL, "ERROR: get primary frambuffer\n");
-   /*EOM_DBG("FRAMEBUFFER ECORE_DRM: is_client:%d mode%dx%d\n", fb->from_client, fb->w, fb->h);*/
+   ret = tdm_output_get_output_type(output, &tdm_type);
+   RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_get_output_type fail(%d)", ret);
 
-   return (tbm_surface_h)fb->hal_buffer;
-#else
-   tdm_output_obj = tdm_display_get_output(g_eom->dpy, 0, &err);
-   if (tdm_output_obj == NULL || err != TDM_ERROR_NONE)
+   ret = tdm_output_get_model_info(output, &maker, &model, &name);
+   RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_get_model_info fail(%d)", ret);
+
+   ret = tdm_output_get_conn_status(output, &status);
+   RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_get_conn_status fail(%d)", ret);
+
+   status2 = value.u32;
+
+   EOM_DBG("id (%d), type(%d, %d), status(%d, %d) (%s,%s,%s)", eom_output->id, type, tdm_type, status, status2, maker, model, name);
+
+   if (tdm_type < ALEN(eom_conn_types))
+     tmp_name = eom_conn_types[tdm_type];
+   else
+     tmp_name = "unknown";
+   /*TODO: What if there will more then one output of same type.
+    *e.g. "HDMI and HDMI" "LVDS and LVDS"*/
+   snprintf(new_name, sizeof(new_name), "%s-%d", tmp_name, 0);
+
+   plug = value.u32;
+
+   if (plug == TDM_OUTPUT_CONN_STATUS_CONNECTED || plug == TDM_OUTPUT_CONN_STATUS_MODE_SETTED)
      {
-        EOM_ERR("tdm_display_get_output 0 fail\n");
-        return NULL;
+        unsigned int mmWidth, mmHeight, subpixel;
+        const tdm_output_mode *mode;
+        int x = 0;
+
+        ret = tdm_output_get_physical_size(output, &mmWidth, &mmHeight);
+        RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_get_physical_size fail(%d)", ret);
+
+        ret = tdm_output_get_subpixel(output, &subpixel);
+        RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_get_subpixel fail(%d)", ret);
+
+        mode = _e_eom_output_get_best_mode(output);
+        RETURNIFTRUE(mode == NULL, "_e_eom_get_best_resolution fail");
+
+        ret = tdm_output_set_mode(output, mode);
+        RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_set_mode fail(%d)", ret);
+
+        x = _e_eom_output_get_position();
+        EOM_DBG("mode: %dx%d, phy(%dx%d), pos(%d,0), refresh:%d, subpixel:%d",
+                mode->hdisplay, mode->vdisplay, mmWidth, mmHeight, x, mode->vrefresh, subpixel);
+
+        /* model is substituted with new_name.
+         * It used to bind wl_output with eom_output in libeom. */
+        if (!e_comp_wl_output_init(new_name, maker, new_name, x, 0,
+                                   mode->hdisplay, mode->vdisplay,
+                                   mmWidth, mmHeight, mode->vrefresh, subpixel, 0))
+          {
+             EOM_ERR("Could not setup new output: %s", new_name);
+             return;
+          }
+        EOM_DBG("Setup new output: %s", new_name);
+
+        /* update eom_output connect */
+        eom_output->width = mode->hdisplay;
+        eom_output->height = mode->vdisplay;
+        eom_output->phys_width = mmWidth;
+        eom_output->phys_height = mmHeight;
+        eom_output->status = plug;
+        eom_output->name = eina_stringshare_add(new_name);
+        eom_output->type = (eom_output_type_e)tdm_type;
+
+        /* Create fake buffer */
+        eom_output->fake_buffer = _e_eom_util_create_fake_buffer(eom_output->width, eom_output->height);
+
+        /* TODO: check output mode(presentation set) and HDMI type */
+        _e_eom_output_start_mirror(eom_output, mode->hdisplay, mode->vdisplay);
+
+        /* If there were previously connected clients to the output - notify them */
+        EINA_LIST_FOREACH(g_eom->clients, l, iterator)
+          {
+             if (iterator)
+               {
+                  EOM_DBG("Send MIRROR ON notification to clients");
+
+                  wl_eom_send_output_info(iterator->resource, eom_output->id,
+                                          eom_output->type, eom_output->mode,
+                                          eom_output->width, eom_output->height,
+                                          eom_output->phys_width, eom_output->phys_height,
+                                          eom_output->status);
+
+                  wl_eom_send_output_attribute(iterator->resource,
+                                               eom_output->id,
+                                               _e_eom_output_state_get_attribute(eom_output),
+                                               _e_eom_output_state_get_attribute_state(eom_output),
+                                               EOM_ERROR_NONE);
+               }
+          }
      }
-   err = tdm_output_get_layer_count(tdm_output_obj, &count);
-   if (err != TDM_ERROR_NONE)
+   else /*TDM_OUTPUT_CONN_STATUS_DISCONNECTED*/
      {
-        EOM_ERR("tdm_output_get_layer_count fail\n");
-        return NULL;
-     }
+        if (eom_output->state == MIRROR)
+          _e_eom_output_stop_mirror(eom_output);
 
-   for (i = 0; i < count; i++)
-     {
-        tdm_layer *layer = tdm_output_get_layer(tdm_output_obj, i, NULL);
-        tdm_layer_capability capabilities = 0;
-        tdm_layer_get_capabilities(layer, &capabilities);
-        if (capabilities & TDM_LAYER_CAPABILITY_PRIMARY)
+        /* update eom_output disconnect */
+        eom_output->width = 0;
+        eom_output->height = 0;
+        eom_output->phys_width = 0;
+        eom_output->phys_height = 0;
+        eom_output->status = plug;
+
+        /* If there were previously connected clients to the output - notify them */
+        EINA_LIST_FOREACH(g_eom->clients, l, iterator)
           {
-             tbm = tdm_layer_get_displaying_buffer(layer, &err);
-             if (err != TDM_ERROR_NONE)
+             if (iterator)
                {
-                  EOM_ERR("tdm_layer_get_displaying_buffer fail\n");
-                  return NULL;
+                  EOM_DBG("Send MIRROR OFF notification to clients");
+
+                  wl_eom_send_output_info(iterator->resource, eom_output->id,
+                                          eom_output->type, eom_output->mode,
+                                          eom_output->width, eom_output->height,
+                                          eom_output->phys_width, eom_output->phys_height,
+                                          eom_output->status);
+
+                  wl_eom_send_output_attribute(iterator->resource,
+                                               eom_output->id,
+                                               _e_eom_output_state_get_attribute(eom_output),
+                                               EOM_OUTPUT_ATTRIBUTE_STATE_LOST,
+                                               EOM_ERROR_NONE);
                }
-           break;
-        }
-     }
+          }
 
-   return tbm;
-#endif
+        if (eom_output->fake_buffer)
+          tbm_surface_destroy(eom_output->fake_buffer);
+
+        e_comp_wl_output_remove(new_name);
+        EOM_DBG("Destory output: %s", new_name);
+        eina_stringshare_del(eom_output->name);
+     }
 }
 
 static void
-_e_eom_calculate_fullsize(int src_h, int src_v, int dst_size_h, int dst_size_v,
-                          int *dst_x, int *dst_y, int *dst_w, int *dst_h)
+_e_eom_cb_wl_request_set_attribute(struct wl_client *client, struct wl_resource *resource, uint32_t output_id, uint32_t attribute)
 {
-   double h_ratio, v_ratio;
+   eom_error_e eom_error = EOM_ERROR_NONE;
+   E_EomClientPtr eom_client = NULL, iterator = NULL;
+   E_EomOutputPtr eom_output = NULL;
+   Eina_Bool changes = EINA_FALSE;
+   Eina_Bool mode_change = EINA_FALSE;
+   Eina_Bool ret = EINA_FALSE;
+   Eina_List *l;
 
-   h_ratio = src_h / dst_size_h;
-   v_ratio = src_v / dst_size_v;
+   eom_client = _e_eom_client_get_by_resource(resource);
+   RETURNIFTRUE(eom_client == NULL, "client is NULL");
 
-   if (h_ratio == v_ratio)
+   /* Bind the client with a concrete output */
+   if (eom_client->output_id  == -1)
+     eom_client->output_id = output_id;
+
+   eom_output = _e_eom_output_get_by_id(output_id);
+   GOTOIFTRUE(eom_output == NULL, no_output, "output is NULL");
+
+   if (eom_client->current == EINA_TRUE && eom_output->id == eom_client->output_id)
      {
-        *dst_x = 0;
-        *dst_y = 0;
-        *dst_w = dst_size_h;
-        *dst_h = dst_size_v;
+        /* Current client can set any flag it wants */
+        _e_eom_output_state_set_force_attribute(eom_output, attribute);
+        changes = EINA_TRUE;
      }
-   else if (h_ratio < v_ratio)
+   else
      {
-        *dst_y = 0;
-        *dst_h = dst_size_v;
-        *dst_w = dst_size_v * src_h / src_v;
-        *dst_x = (dst_size_h - *dst_w) / 2;
+        ret = _e_eom_output_state_set_attribute(eom_output, attribute);
+        if (ret == EINA_FALSE)
+          {
+             EOM_DBG("set attribute FAILED\n");
+
+             eom_error = EOM_ERROR_INVALID_PARAMETER;
+             goto end;
+          }
+
+        eom_client->output_id = output_id;
+        changes = EINA_TRUE;
      }
-   else /* (h_ratio > v_ratio) */
+
+   EOM_DBG("set attribute OK\n");
+
+   /* If client has set EOM_OUTPUT_ATTRIBUTE_NONE, eom will be
+    * switched to mirror mode
+    */
+   if (attribute == EOM_OUTPUT_ATTRIBUTE_NONE && eom_output->state != MIRROR)
      {
-        *dst_x = 0;
-        *dst_w = dst_size_h;
-        *dst_h = dst_size_h * src_h / src_v;
-        *dst_y = (dst_size_v - *dst_h) / 2;
-     }
-}
+        eom_output->state = MIRROR;
+        eom_client->current = EINA_FALSE;
 
-static Eina_Bool
-_e_eom_pp_src_to_dst(tbm_surface_h src_buffer)
-{
-   tdm_error err = TDM_ERROR_NONE;
-   tdm_info_pp pp_info;
-   tdm_pp *pp = NULL;
-   int x, y, w, h;
+        _e_eom_output_state_set_mode(eom_output, EOM_OUTPUT_ATTRIBUTE_NONE);
+        mode_change = EINA_TRUE;
 
-   pp = tdm_display_create_pp(g_eom->dpy, &err);
-   RETURNVALIFTRUE(err != TDM_ERROR_NONE, EINA_FALSE, "ERROR: create pp:%d\n", err);
+        ret = _e_eom_output_state_set_attribute(eom_output, EOM_OUTPUT_ATTRIBUTE_NONE);
+        (void)ret;
 
-   /* TO DO : consider rotation */
-   _e_eom_calculate_fullsize(g_eom->src_mode.w, g_eom->src_mode.h,
-                             g_eom->dst_mode.w, g_eom->dst_mode.h,
-                             &x, &y, &w, &h);
-   EOM_DBG("x:%d, y:%d, w:%d, h:%d\n", x, y, w, h);
+        _e_eom_client_free_buffers(eom_client);
 
-   g_eom_event_data.pp = pp;
+        if (eom_output->status == 0)
+          {
+             EOM_DBG("ATTRIBUTE: output:%d is disconnected", output_id);
+             goto end;
+          }
 
-   pp_info.src_config.size.h = g_eom->src_mode.w;
-   pp_info.src_config.size.v = g_eom->src_mode.h;
-   pp_info.src_config.pos.x = 0;
-   pp_info.src_config.pos.y = 0;
-   pp_info.src_config.pos.w = g_eom->src_mode.w;
-   pp_info.src_config.pos.h = g_eom->src_mode.h;
-   pp_info.src_config.format = TBM_FORMAT_ARGB8888;
+        ret = _e_eom_output_start_pp(eom_output);
+        GOTOIFTRUE(ret == EINA_FALSE, end,
+                   "ERROR: restore mirror mode after a client disconnection\n");
+        goto end;
+     }
 
-   pp_info.dst_config.size.h = g_eom->dst_mode.w;
-   pp_info.dst_config.size.v = g_eom->dst_mode.h;
-   pp_info.dst_config.pos.x = x;
-   pp_info.dst_config.pos.y = y;
-   pp_info.dst_config.pos.w = w;
-   pp_info.dst_config.pos.h = h;
-   pp_info.dst_config.format = TBM_FORMAT_ARGB8888;
+end:
+   wl_eom_send_output_attribute(eom_client->resource,
+                                eom_output->id,
+                                _e_eom_output_state_get_attribute(eom_output),
+                                _e_eom_output_state_get_attribute_state(eom_output),
+                                eom_error);
 
-   /* TO DO : get rotation */
-   pp_info.transform = TDM_TRANSFORM_NORMAL;
-   pp_info.sync = 0;
-   pp_info.flags = 0;
+   /* Notify eom clients that eom state has been changed */
+   if (changes == EINA_TRUE)
+     {
+        EINA_LIST_FOREACH(g_eom->clients, l, iterator)
+          {
+             if (iterator && iterator->resource == resource)
+               continue;
 
-   err = tdm_pp_set_info(pp, &pp_info);
-   RETURNVALIFTRUE(err != TDM_ERROR_NONE, EINA_FALSE, "ERROR: set pp info:%d\n", err);
+             if (iterator && iterator->output_id == eom_output->id)
+               {
+                  iterator->current = 0;
+
+                  if (eom_output->state == MIRROR)
+                    {
+                       wl_eom_send_output_attribute(iterator->resource,
+                                                    eom_output->id,
+                                                    _e_eom_output_state_get_attribute(eom_output),
+                                                    _e_eom_output_state_get_attribute_state(eom_output),
+                                                    EOM_ERROR_NONE);
+                    }
+                  else
+                    {
+                       wl_eom_send_output_attribute(iterator->resource,
+                                                    eom_output->id,
+                                                    _e_eom_output_state_get_attribute(eom_output),
+                                                    EOM_OUTPUT_ATTRIBUTE_STATE_LOST,
+                                                    EOM_ERROR_NONE);
+                    }
+
+                  if (mode_change == EINA_TRUE)
+                    {
+                       wl_eom_send_output_mode(iterator->resource,
+                                               eom_output->id,
+                                               _e_eom_output_state_get_mode(eom_output));
+                    }
+               }
+          }
 
-   g_eom_event_data.pp_buffer = !g_eom_event_data.current_buffer;
-   EOM_DBG("PP: curr:%d  pp:%d\n",
-           g_eom_event_data.current_buffer,
-           g_eom_event_data.pp_buffer);
+        eom_client->current= EINA_TRUE;
+     }
 
-   err = tdm_buffer_add_release_handler(g_eom_event_data.dst_buffers[g_eom_event_data.pp_buffer],
-                                      _e_eom_pp_cb, &g_eom_event_data);
-   RETURNVALIFTRUE(err != TDM_ERROR_NONE, EINA_FALSE, "ERROR: set pp hadler:%d\n", err);
+   return;
 
-   err = tdm_pp_attach(pp, src_buffer,
-                       g_eom_event_data.dst_buffers[g_eom_event_data.pp_buffer]);
-   RETURNVALIFTRUE(err != TDM_ERROR_NONE, EINA_FALSE, "ERROR: pp attach:%d\n", err);
+   /* Get here if EOM does not have output with output_id is */
+no_output:
 
-   err = tdm_pp_commit(g_eom_event_data.pp);
-   RETURNVALIFTRUE(err != TDM_ERROR_NONE, EINA_FALSE, "ERROR: pp commit:%d\n", err);
+   wl_eom_send_output_attribute(eom_client->resource,
+                                output_id,
+                                EOM_OUTPUT_ATTRIBUTE_NONE,
+                                EOM_OUTPUT_ATTRIBUTE_STATE_NONE,
+                                EOM_ERROR_NO_SUCH_DEVICE);
 
-   return EINA_TRUE;
+   wl_eom_send_output_mode(eom_client->resource,
+                           output_id,
+                           EOM_OUTPUT_MODE_NONE);
+
+   wl_eom_send_output_type(eom_client->resource,
+                           output_id,
+                           EOM_OUTPUT_ATTRIBUTE_STATE_NONE,
+                           TDM_OUTPUT_CONN_STATUS_DISCONNECTED);
+   return;
 }
 
-static Eina_Bool
-_e_eom_pp_is_needed(int src_w, int src_h, int dst_w, int dst_h)
+static void
+_e_eom_cb_wl_request_get_output_info(struct wl_client *client, struct wl_resource *resource, uint32_t output_id)
 {
-   if (src_w != dst_w)
-     return EINA_TRUE;
+   EOM_DBG("output:%d\n", output_id);
 
-   if (src_h != dst_h)
-     return EINA_TRUE;
+   if (g_eom->outputs)
+     {
+        Eina_List *l;
+        E_EomOutputPtr output = NULL;
 
-   return EINA_FALSE;
+        EINA_LIST_FOREACH(g_eom->outputs, l, output)
+          {
+             if (output->id == output_id)
+               {
+                  EOM_DBG("send - id : %d, type : %d, mode : %d, w : %d, h : %d, w_mm : %d, h_mm : %d, conn : %d\n",
+                          output->id, output->type, output->mode, output->width, output->height,
+                          output->phys_width, output->phys_height, output->status);
+
+                  wl_eom_send_output_info(resource, output->id, output->type, output->mode, output->width, output->height,
+                                          output->phys_width, output->phys_height, output->status);
+               }
+          }
+     }
 }
 
 static Eina_Bool
-_e_eom_ecore_drm_output_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+_e_eom_output_init(tdm_display *dpy)
 {
-   Ecore_Drm_Event_Output *e = NULL;
-   char buff[PATH_MAX];
-
-   if (!(e = event))  return ECORE_CALLBACK_PASS_ON;;
+   tdm_error ret = TDM_ERROR_NONE;
+   int i, count;
 
-   EOM_DBG("id:%d (x,y,w,h):(%d,%d,%d,%d) (w_mm,h_mm):(%d,%d) refresh:%d subpixel_order:%d transform:%d make:%s model:%s name:%s plug:%d\n",
-            e->id, e->x, e->y, e->w, e->h, e->phys_width, e->phys_height, e->refresh, e->subpixel_order, e->transform, e->make, e->model, e->name, e->plug);
+   ret = tdm_display_get_output_count(dpy, &count);
+   RETURNVALIFTRUE(ret != TDM_ERROR_NONE,
+                   EINA_FALSE,
+                   "tdm_display_get_output_count fail");
+   RETURNVALIFTRUE(count <= 1,
+                   EINA_FALSE,
+                   "output count is 1. device doesn't support external outputs.\n");
 
-   snprintf(buff, sizeof(buff), "%s", e->name);
+   g_eom->output_count = count - 1;
+   EOM_DBG("external output count : %d\n", g_eom->output_count);
 
-   if (e->id == 0) /* main output */
+   /* skip main output id:0 */
+   /* start from 1 */
+   for (i = 1; i < count; i++)
      {
-        if (e->plug == 1)
+        const tdm_output_mode *mode = NULL;
+        E_EomOutputPtr new_output = NULL;
+        unsigned int mmWidth, mmHeight;
+        tdm_output_conn_status status;
+        tdm_output *output = NULL;
+        tdm_output_type type;
+
+        output = tdm_display_get_output(dpy, i, &ret);
+        GOTOIFTRUE(ret != TDM_ERROR_NONE,
+                   err,
+                   "tdm_display_get_output fail(ret:%d)", ret);
+
+        GOTOIFTRUE(output == NULL,
+                   err,
+                   "tdm_display_get_output fail(no output:%d)", ret);
+
+        ret = tdm_output_get_output_type(output, &type);
+        GOTOIFTRUE(ret != TDM_ERROR_NONE,
+                   err,
+                   "tdm_output_get_output_type fail(%d)", ret);
+
+        new_output = E_NEW(E_EomOutput, 1);
+        GOTOIFTRUE(new_output == NULL,
+                   err,
+                   "calloc fail");
+
+        ret = tdm_output_get_conn_status(output, &status);
+        if (ret != TDM_ERROR_NONE)
+          {
+             EOM_ERR("tdm_output_get_conn_status fail(%d)", ret);
+             free(new_output);
+             goto err;
+          }
+        new_output->id = i;
+        new_output->type = type;
+        new_output->status = status;
+        new_output->mode = EOM_OUTPUT_MODE_NONE;
+        new_output->output = output;
+
+        ret = tdm_output_add_change_handler(output, _e_eom_cb_tdm_output_status_change, NULL);
+        if (ret != TDM_ERROR_NONE)
           {
-              g_eom->src_mode.w = e->w;
-              g_eom->src_mode.h = e->h;
-              if (g_eom->int_output_name == NULL)
-                g_eom->int_output_name = strdup(buff);
+              EOM_ERR("tdm_output_add_change_handler fail(%d)", ret);
+              free(new_output);
+              goto err;
+          }
 
-              g_eom->eom_sate = UP;
+        if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED)
+          {
+             EOM_DBG("create(%d)output, type:%d, status:%d",
+                     new_output->id, new_output->type, new_output->status);
+             g_eom->outputs = eina_list_append(g_eom->outputs, new_output);
+             continue;
           }
+        new_output->status = TDM_OUTPUT_CONN_STATUS_CONNECTED;
+
+        ret = tdm_output_get_mode(output, &mode);
+        if (ret != TDM_ERROR_NONE)
+          {
+             EOM_ERR("tdm_output_get_mode fail(%d)", ret);
+             free(new_output);
+             goto err;
+          }
+
+        if (mode == NULL)
+          {
+             new_output->width = 0;
+             new_output->height = 0;
+          }
+
         else
           {
-             g_eom->src_mode.w = -1;
-             g_eom->src_mode.h = -1;
-             if (g_eom->int_output_name)
-               free(g_eom->int_output_name);
+             new_output->width = mode->hdisplay;
+             new_output->height = mode->vdisplay;
+          }
 
-             g_eom->eom_sate = DOWN;
+        ret = tdm_output_get_physical_size(output, &mmWidth, &mmHeight);
+        if (ret != TDM_ERROR_NONE)
+          {
+             EOM_ERR("tdm_output_get_conn_status fail(%d)", ret);
+             free(new_output);
+             goto err;
           }
+        new_output->phys_width = mmWidth;
+        new_output->phys_height = mmHeight;
+
+        EOM_DBG("create(%d)output, type:%d, status:%d, w:%d, h:%d, mm_w:%d, mm_h:%d",
+                new_output->id, new_output->type, new_output->status,
+                new_output->width, new_output->height, new_output->phys_width, new_output->phys_height);
+
+        g_eom->outputs = eina_list_append(g_eom->outputs, new_output);
      }
 
-   return ECORE_CALLBACK_PASS_ON;
+   return EINA_TRUE;
+
+err:
+   if (g_eom->outputs)
+     {
+        Eina_List *l;
+        E_EomOutputPtr output;
+
+        EINA_LIST_FOREACH(g_eom->outputs, l, output)
+          {
+             free(output);
+          }
+        eina_list_free(g_eom->outputs);
+     }
+
+   return EINA_FALSE;
 }
 
 static const tdm_output_mode *
-_e_eom_get_best_mode(tdm_output *output)
+_e_eom_output_get_best_mode(tdm_output *output)
 {
    tdm_error ret = TDM_ERROR_NONE;
    const tdm_output_mode *modes;
@@ -703,34 +1012,13 @@ _e_eom_get_best_mode(tdm_output *output)
    unsigned int value;
    int i, count = 0;
 
-   ret = tdm_output_get_available_modes(output, &modes, &count);
-   if (ret != TDM_ERROR_NONE)
-     {
-        EOM_ERR("tdm_output_get_available_modes fail(%d)\n", ret);
-        return NULL;
-     }
-#if 0
-   /* kernel error */
-   for (i = 0; i < count; i++)
-     {
-        value = modes[i].vdisplay + modes[i].hdisplay;
-        if (value > best_value)
-          best_value = value;
-     }
-
-   for (i = 0; i < count; i++)
-     {
-        value = modes[i].vdisplay + modes[i].hdisplay;
-        if (value != best_value)
-          continue;
-
-        if (modes[i].vrefresh > vrefresh)
-          {
-             mode = &modes[i];
-             vrefresh = modes[i].vrefresh;
-          }
+   ret = tdm_output_get_available_modes(output, &modes, &count);
+   if (ret != TDM_ERROR_NONE)
+     {
+        EOM_ERR("tdm_output_get_available_modes fail(%d)\n", ret);
+        return NULL;
      }
-#else
+
    for (i = 0; i < count; i++)
      {
         value = modes[i].vdisplay + modes[i].hdisplay;
@@ -740,7 +1028,7 @@ _e_eom_get_best_mode(tdm_output *output)
              mode = &modes[i];
           }
      }
-#endif
+
    EOM_DBG("bestmode : %s, (%dx%d) r(%d), f(%d), t(%d)",
            mode->name, mode->hdisplay, mode->vdisplay, mode->vrefresh, mode->flags, mode->type);
 
@@ -748,7 +1036,7 @@ _e_eom_get_best_mode(tdm_output *output)
 }
 
 static int
-_e_eom_get_output_position(void)
+_e_eom_output_get_position(void)
 {
    tdm_output *output_main = NULL;
    const tdm_output_mode *mode;
@@ -775,7 +1063,7 @@ _e_eom_get_output_position(void)
         EINA_LIST_FOREACH(g_eom->outputs, l, eom_output_tmp)
           {
              if (eom_output_tmp->status != TDM_OUTPUT_CONN_STATUS_DISCONNECTED)
-               x += eom_output_tmp->w;
+               x += eom_output_tmp->width;
           }
      }
 
@@ -783,23 +1071,22 @@ _e_eom_get_output_position(void)
 }
 
 static void
-_e_eom_start_mirror(E_EomOutputPtr eom_output, int width, int height)
+_e_eom_output_start_mirror(E_EomOutputPtr eom_output, int width, int height)
 {
    tdm_output *output;
    tdm_layer *hal_layer;
    tdm_info_layer layer_info;
    tdm_error tdm_err = TDM_ERROR_NONE;
-   E_EomEventDataPtr eom_event_data = &g_eom_event_data;
    int ret = 0;
 
-   if (eom_output->mirror_run == UP)
+   if (eom_output->state == MIRROR)
      return;
 
    output = eom_output->output;
-   hal_layer = _e_eom_hal_layer_get(output, width, height);
+   hal_layer = _e_eom_output_get_layer(output, width, height);
    GOTOIFTRUE(hal_layer == NULL, err, "ERROR: get hal layer\n");
 
-   ret = _e_eom_create_output_buffers(eom_event_data, width, height);
+   ret = _e_eom_util_create_buffers(eom_output, width, height);
    GOTOIFTRUE(ret == EINA_FALSE, err, "ERROR: create buffers \n");
 
    tdm_err = tdm_layer_get_info(hal_layer, &layer_info);
@@ -812,34 +1099,26 @@ _e_eom_start_mirror(E_EomOutputPtr eom_output, int width, int height)
            layer_info.dst_pos.x, layer_info.dst_pos.y,
            layer_info.dst_pos.w, layer_info.dst_pos.h);
 
-   g_eom->dst_mode.w = width;
-   g_eom->dst_mode.h = height;
-   /* TODO: free that memory */
-   /*g_eom->ext_output_name = strdup(output_name);*/
+   eom_output->layer = hal_layer;
+   eom_output->output = output;
+   eom_output->current_buffer = 0;
 
-   eom_event_data->layer = hal_layer;
-   eom_event_data->output = output;
-   eom_event_data->current_buffer = 0;
-
-   tdm_err = tdm_layer_set_buffer(hal_layer, eom_event_data->dst_buffers[eom_event_data->current_buffer]);
+   tdm_err = tdm_layer_set_buffer(hal_layer, eom_output->dst_buffers[eom_output->current_buffer]);
    GOTOIFTRUE(tdm_err != TDM_ERROR_NONE, err, "ERROR: set buffer on layer:%d\n", tdm_err);
 
-   g_eom->is_external_init = 1;
-   g_eom->id = eom_output->id;
-
    tdm_err = tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_ON);
    GOTOIFTRUE(tdm_err != TDM_ERROR_NONE, err, "ERROR: tdm_output_set_dpms on\n");
 
    /* get main surface */
-   ret = _e_eom_mirror_start(g_eom->int_output_name, g_eom->src_mode.w, g_eom->src_mode.h);
+   ret = _e_eom_output_start_pp(eom_output);
    GOTOIFTRUE(ret == EINA_FALSE, err, "ERROR: get root surfcae\n");
 
-   tdm_err = tdm_output_commit(output, 0, _e_eom_commit_cb, &g_eom_event_data);
+   tdm_err = tdm_output_commit(output, 0, _e_eom_cb_commit, eom_output);
    GOTOIFTRUE(tdm_err != TDM_ERROR_NONE, err, "ERROR: commit crtc:%d\n", tdm_err);
 
-   _e_eom_set_eom_mode(WL_EOM_MODE_MIRROR);
-
-   eom_output->mirror_run = UP;
+   _e_eom_output_state_set_mode(eom_output, EOM_OUTPUT_MODE_MIRROR);
+   _e_eom_output_state_set_attribute(eom_output, EOM_OUTPUT_ATTRIBUTE_NONE);
+   eom_output->state = MIRROR;
 
    return;
 
@@ -851,266 +1130,347 @@ err:
 }
 
 static void
-_e_eom_stop_mirror(E_EomOutputPtr eom_output)
+_e_eom_output_stop_mirror(E_EomOutputPtr eom_output)
 {
-   if (eom_output->mirror_run == DOWN)
+   if (eom_output->state == NONE)
      return;
 
-   g_eom->is_external_init = 0;
-   g_eom->is_internal_grab = 0;
-   g_eom->id = -1;
-
-   _e_eom_set_eom_status(WL_EOM_STATUS_DISCONNECTION);
-   _e_eom_set_eom_mode(WL_EOM_MODE_NONE);
+   _e_eom_output_state_set_status(eom_output, TDM_OUTPUT_CONN_STATUS_DISCONNECTED);
+   _e_eom_output_state_set_mode(eom_output, EOM_OUTPUT_MODE_NONE);
+   _e_eom_output_state_set_attribute(eom_output, EOM_OUTPUT_ATTRIBUTE_NONE);
 
-   _e_eom_deinit_external_output();
+   _e_eom_output_deinit(eom_output);
 
-   eom_output->mirror_run = DOWN;
+   eom_output->state = NONE;
 }
 
 static void
-_e_eom_tdm_output_status_change_cb(tdm_output *output, tdm_output_change_type type, tdm_value value, void *user_data)
+_e_eom_output_deinit(E_EomOutputPtr eom_output)
 {
-   tdm_output_type tdm_type;
-   tdm_error ret = TDM_ERROR_NONE;
-   tdm_output_conn_status status;
-   tdm_output_conn_status status2;
-   const char *maker = NULL, *model = NULL, *name = NULL;
-   const char *tmp_name;
-   char new_name[DRM_CONNECTOR_NAME_LEN];
-   E_EomOutputPtr eom_output = NULL;
-   tdm_output_conn_status plug;
-
-   if (type == TDM_OUTPUT_CHANGE_DPMS)
-     return;
+   tdm_error err = TDM_ERROR_NONE;
+   E_EomClientPtr iterator = NULL;
+   Eina_List *l;
+   int i = 0;
 
-   if (g_eom->outputs)
+   if (eom_output->layer)
      {
-        Eina_List *l;
-        E_EomOutputPtr eom_output_tmp;
+        err = tdm_layer_unset_buffer(eom_output->layer);
+        if (err != TDM_ERROR_NONE)
+          EOM_DBG("EXT OUTPUT DEINIT: fail unset buffer:%d\n", err);
+        else
+          EOM_DBG("EXT OUTPUT DEINIT: ok unset buffer:%d\n", err);
 
-        EINA_LIST_FOREACH(g_eom->outputs, l, eom_output_tmp)
-          {
-             if (eom_output_tmp->output == output)
-               eom_output = eom_output_tmp;
-          }
-     }
+        err = tdm_output_commit(eom_output->output, 0, NULL, eom_output);
+        if (err != TDM_ERROR_NONE)
+          EOM_DBG ("EXT OUTPUT DEINIT: fail commit:%d\n", err);
+        else
+          EOM_DBG("EXT OUTPUT DEINIT: ok commit:%d\n", err);
+    }
 
-   ret = tdm_output_get_output_type(output, &tdm_type);
-   RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_get_output_type fail(%d)", ret);
+   /* TODO: do I need to do DPMS off? */
 
-   ret = tdm_output_get_model_info(output, &maker, &model, &name);
-   RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_get_model_info fail(%d)", ret);
+   err = tdm_output_set_dpms(eom_output->output, TDM_OUTPUT_DPMS_OFF);
+   if (err != TDM_ERROR_NONE)
+     EOM_ERR("EXT OUTPUT DEINIT: failed set DPMS off:%d\n", err);
 
-   ret = tdm_output_get_conn_status(output, &status);
-   RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_get_conn_status fail(%d)", ret);
+   for (i = 0; i < NUM_MAIN_BUF; i++)
+     {
+        tdm_buffer_remove_release_handler(eom_output->dst_buffers[i],
+                                          _e_eom_cb_pp, eom_output);
 
-   status2 = value.u32;
+        if (eom_output->dst_buffers[i])
+          tbm_surface_destroy(eom_output->dst_buffers[i]);
+    }
 
-   EOM_DBG("type(%d, %d), status(%d, %d) (%s,%s,%s)", type, tdm_type, status, status2, maker, model, name);
+   /*TODO: what is that for?*/
+   if (g_eom->main_output_state == DOWN)
+     EINA_LIST_FOREACH(g_eom->clients, l, iterator)
+       {
+          if (iterator && iterator->output_id == eom_output->id)
+            _e_eom_client_free_buffers(iterator);
+       }
+}
 
-   if (tdm_type < ALEN(eom_conn_types))
-     tmp_name = eom_conn_types[tdm_type];
-   else
-     tmp_name = "unknown";
-   snprintf(new_name, sizeof(new_name), "%s-%d", tmp_name, 0);
+static tdm_layer *
+_e_eom_output_get_layer(tdm_output *output, int width, int height)
+{
+   int i = 0;
+   int count = 0;
+   tdm_layer *layer = NULL;
+   tdm_error err = TDM_ERROR_NONE;
+   tdm_layer_capability capa;
+   tdm_info_layer layer_info;
 
-   plug = value.u32;
+   err = tdm_output_get_layer_count(output, &count);
+   if (err != TDM_ERROR_NONE)
+     {
+        EOM_DBG ("tdm_output_get_layer_count fail(%d)\n", err);
+        return NULL;
+     }
 
-   if (plug == TDM_OUTPUT_CONN_STATUS_CONNECTED)
+   for (i = 0; i < count; i++)
      {
-        unsigned int mmWidth, mmHeight, subpixel;
-        const tdm_output_mode *mode;
-        int x = 0;
+        layer = (tdm_layer *)tdm_output_get_layer(output, i, &err);
+        RETURNVALIFTRUE(err != TDM_ERROR_NONE, NULL, "tdm_output_get_layer fail(%d)\n", err);
 
-        ret = tdm_output_get_physical_size(output, &mmWidth, &mmHeight);
-        RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_get_physical_size fail(%d)", ret);
+        err = tdm_layer_get_capabilities(layer, &capa);
+        RETURNVALIFTRUE(err != TDM_ERROR_NONE, NULL, "tdm_layer_get_capabilities fail(%d)\n", err);
 
-        ret = tdm_output_get_subpixel(output, &subpixel);
-        RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_get_subpixel fail(%d)", ret);
+        if (capa & TDM_LAYER_CAPABILITY_PRIMARY)
+          {
+             EOM_DBG("TDM_LAYER_CAPABILITY_PRIMARY layer found : %d\n", i);
+             break;
+          }
+     }
 
-        mode = _e_eom_get_best_mode(output);
-        RETURNIFTRUE(mode == NULL, "_e_eom_get_best_resolution fail");
+   memset(&layer_info, 0x0, sizeof(tdm_info_layer));
+   layer_info.src_config.size.h = width;
+   layer_info.src_config.size.v = height;
+   layer_info.src_config.pos.x = 0;
+   layer_info.src_config.pos.y = 0;
+   layer_info.src_config.pos.w = width;
+   layer_info.src_config.pos.h = height;
+   layer_info.src_config.format = TBM_FORMAT_ARGB8888;
+   layer_info.dst_pos.x = 0;
+   layer_info.dst_pos.y = 0;
+   layer_info.dst_pos.w = width;
+   layer_info.dst_pos.h = height;
+   layer_info.transform = TDM_TRANSFORM_NORMAL;
 
-        ret = tdm_output_set_mode(output, mode);
-        RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_set_mode fail(%d)", ret);
+   err = tdm_layer_set_info(layer, &layer_info);
+   RETURNVALIFTRUE(err != TDM_ERROR_NONE, NULL, "tdm_layer_set_info fail(%d)\n", err);
 
-        x = _e_eom_get_output_position();
-        EOM_DBG("mode: %dx%d, phy(%dx%d), pos(%d,0), refresh:%d, subpixel:%d",
-                mode->hdisplay, mode->vdisplay, mmWidth, mmHeight, x, mode->vrefresh, subpixel);
+   return layer;
+}
 
-        if (!e_comp_wl_output_init(new_name, maker, model, x, 0,
-                                   mode->hdisplay, mode->vdisplay,
-                                   mmWidth, mmHeight, mode->vrefresh, subpixel, 0))
-          {
-             EOM_ERR("Could not setup new output: %s", new_name);
-             return;
-          }
-        EOM_DBG("Setup new output: %s", new_name);
+static E_EomOutputPtr
+_e_eom_output_get_by_id(int id)
+{
+   Eina_List *l;
+   E_EomOutputPtr output;
 
-        /* update eom_output connect */
-        eom_output->w = mode->hdisplay;
-        eom_output->h = mode->vdisplay;
-        eom_output->phys_width = mmWidth;
-        eom_output->phys_height = mmHeight;
-        eom_output->status = plug;
+   EINA_LIST_FOREACH(g_eom->outputs, l, output)
+     {
+        if (output && output->id == id)
+          return output;
+     }
 
-        g_eom->is_mirror_mode = UP;
-        g_eom->eom_sate = UP;
+   return NULL;
+}
 
-        /* TODO: check output mode(presentation set) and HDMI type */
-        _e_eom_start_mirror(eom_output, mode->hdisplay, mode->vdisplay);
-     }
-   else if (plug == TDM_OUTPUT_CONN_STATUS_DISCONNECTED)
+static E_EomOutputPtr
+_e_eom_output_get_by_name(const char *name)
+{
+   Eina_List *l;
+   E_EomOutputPtr output;
+
+   EINA_LIST_FOREACH(g_eom->outputs, l, output)
      {
-        if (eom_output->mirror_run == UP)
-          _e_eom_stop_mirror(eom_output);
+        if (output && strcmp(output->name, name) == 0)
+          return output;
+     }
 
-        /* update eom_output disconnect */
-        eom_output->w = 0;
-        eom_output->h = 0;
-        eom_output->phys_width = 0;
-        eom_output->phys_height = 0;
-        eom_output->status = plug;
+   return NULL;
+}
+
+static Eina_Bool
+_e_eom_output_start_pp(E_EomOutputPtr eom_output)
+{
+   /* should be changed in HWC enable environment */
+   tbm_surface_info_s src_buffer_info;
+   tbm_surface_h src_buffer = NULL;
+   Eina_Bool ret = EINA_FALSE;
 
-        g_eom->is_mirror_mode = DOWN;
-        g_eom->eom_sate = DOWN;
+   src_buffer = _e_eom_util_get_output_surface(g_eom->main_output_name);
+   RETURNVALIFTRUE(src_buffer == NULL, EINA_FALSE, "ERROR: get root tdm surfcae\n");
 
-        e_comp_wl_output_remove(new_name);
-        EOM_DBG("Destory output: %s", new_name);
-     }
+   tbm_surface_get_info(src_buffer, &src_buffer_info);
+
+   EOM_DBG("FRAMEBUFFER TDM: %dx%d   bpp:%d   size:%d",
+           src_buffer_info.width, src_buffer_info.height,
+           src_buffer_info.bpp, src_buffer_info.size);
+
+   /* TODO: if internal and external outputs are equal */
+   ret = _e_eom_pp_is_needed(g_eom->width, g_eom->height,
+                             eom_output->width, eom_output->height);
+   RETURNVALIFTRUE(ret == EINA_FALSE, EINA_TRUE, "pp is not required\n");
+
+   ret = _e_eom_pp_init(eom_output, src_buffer);
+   RETURNVALIFTRUE(ret == EINA_FALSE, EINA_FALSE, "ERROR: init pp\n");
+
+   return EINA_TRUE;
 }
 
 static Eina_Bool
-_e_eom_client_buffer_change(void *data, int type, void *event)
+_e_eom_pp_init(E_EomOutputPtr eom_output, tbm_surface_h src_buffer)
 {
-   E_Comp_Wl_Buffer *external_wl_buffer = NULL;
-   E_EomClientBufferPtr client_buffer = NULL;
-   E_Event_Client *ev = event;
-   E_Client *ec = NULL;
-   /* Eina_Bool ret_err; */
-   /*
-   tbm_surface_h external_tbm_buffer = NULL;
-   tbm_surface_info_s surface_info;
-   int ret;
-   */
+   tdm_error err = TDM_ERROR_NONE;
+   tdm_info_pp pp_info;
+   tdm_pp *pp = NULL;
+   int x, y, w, h;
 
-   EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(ev->ec, ECORE_CALLBACK_PASS_ON);
+   pp = tdm_display_create_pp(g_eom->dpy, &err);
+   RETURNVALIFTRUE(err != TDM_ERROR_NONE, EINA_FALSE, "ERROR: create pp:%d\n", err);
 
-   return ECORE_CALLBACK_PASS_ON;
+   eom_output->pp = pp;
 
-   ec = ev->ec;
-   if (e_object_is_del(E_OBJECT(ec)))
-     {
-        EOM_ERR("ERROR: BUFF CHANGE: ec objects is del\n");
-        return ECORE_CALLBACK_PASS_ON;
-     }
+   /* TO DO : consider rotation */
+   _e_eom_util_calculate_fullsize(g_eom->width, g_eom->height,
+                             eom_output->width, eom_output->height,
+                             &x, &y, &w, &h);
+   EOM_DBG("x:%d, y:%d, w:%d, h:%d\n", x, y, w, h);
 
-   /* TODO: Make all goto same, not err, end, ret etc. */
-   /* We are not interested in non external clients */
-   /*
-   ret_err = e_client_is_external_output_client(ec);
-   RETURNVALIFTRUE(ret_err != EINA_TRUE,
-                   ECORE_CALLBACK_PASS_ON,
-                   "ERROR: BUFF CHANGE: ec is not external\n");
-   */
+   pp_info.src_config.size.h = g_eom->width;
+   pp_info.src_config.size.v = g_eom->height;
+   pp_info.src_config.pos.x = 0;
+   pp_info.src_config.pos.y = 0;
+   pp_info.src_config.pos.w = g_eom->width;
+   pp_info.src_config.pos.h = g_eom->height;
+   pp_info.src_config.format = TBM_FORMAT_ARGB8888;
 
-   if (ec->pixmap == NULL)
-     return ECORE_CALLBACK_PASS_ON;
+   pp_info.dst_config.size.h = eom_output->width;
+   pp_info.dst_config.size.v = eom_output->height;
+   pp_info.dst_config.pos.x = x;
+   pp_info.dst_config.pos.y = y;
+   pp_info.dst_config.pos.w = w;
+   pp_info.dst_config.pos.h = h;
+   pp_info.dst_config.format = TBM_FORMAT_ARGB8888;
 
-   external_wl_buffer = e_pixmap_resource_get(ec->pixmap);
-   RETURNVALIFTRUE(external_wl_buffer == NULL,
-                   ECORE_CALLBACK_PASS_ON,
-                   "ERROR:BUFF CHANGE: wl buffer is NULL\n");
+   /* TO DO : get rotation */
+   pp_info.transform = TDM_TRANSFORM_NORMAL;
+   pp_info.sync = 0;
+   pp_info.flags = 0;
 
-   EOM_DBG("BUFF CHANGE: wl_buff:%dx%d",
-            external_wl_buffer->w,
-            external_wl_buffer->h);
+   err = tdm_pp_set_info(pp, &pp_info);
+   RETURNVALIFTRUE(err != TDM_ERROR_NONE, EINA_FALSE, "ERROR: set pp info:%d\n", err);
 
-   if (external_wl_buffer->w == 1 && external_wl_buffer->h == 1)
-     {
-        EOM_ERR("ERROR:BUFF CHANGE: skip first 1x1 client buffer\n");
-        return ECORE_CALLBACK_PASS_ON;
-     }
+   eom_output->pp_buffer = !eom_output->current_buffer;
+   EOM_DBG("PP: curr:%d  pp:%d\n",
+           eom_output->current_buffer,
+           eom_output->pp_buffer);
 
-   /*TODO: wayland_tbm_server_get_surface is implicit declarated */
-   /*external_tbm_buffer = wayland_tbm_server_get_surface(NULL,
-                              external_wl_buffer->resource);
-   if (external_tbm_buffer == NULL)
-     {
-        EOM_ERR("ERROR: BUFF CHANGE: client tbm buffer is NULL\n");
-        return ECORE_CALLBACK_PASS_ON;
-     }
+   err = tdm_buffer_add_release_handler(eom_output->dst_buffers[eom_output->pp_buffer],
+                                      _e_eom_cb_pp, eom_output);
+   RETURNVALIFTRUE(err != TDM_ERROR_NONE, EINA_FALSE, "ERROR: set pp hadler:%d\n", err);
 
-   EOM_DBG("BUFF CHANGE: tbm_buffer %p", external_tbm_buffer);
-   */
+   err = tdm_pp_attach(pp, src_buffer,
+                       eom_output->dst_buffers[eom_output->pp_buffer]);
+   RETURNVALIFTRUE(err != TDM_ERROR_NONE, EINA_FALSE, "ERROR: pp attach:%d\n", err);
+
+   err = tdm_pp_commit(eom_output->pp);
+   RETURNVALIFTRUE(err != TDM_ERROR_NONE, EINA_FALSE, "ERROR: pp commit:%d\n", err);
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_eom_pp_is_needed(int src_w, int src_h, int dst_w, int dst_h)
+{
+   if (src_w != dst_w)
+     return EINA_TRUE;
+
+   if (src_h != dst_h)
+     return EINA_TRUE;
+
+   return EINA_FALSE;
+}
+
+static tbm_surface_h
+_e_eom_util_create_fake_buffer(int width, int height)
+{
+   tbm_surface_info_s buffer_info;
+   tbm_surface_h buffer = NULL;
 
-   /* mmap that buffer to get width and height for test's sake */
-   /*
-   memset(&surface_info, 0, sizeof(tbm_surface_info_s));
-   ret = tbm_surface_map(external_tbm_buffer, TBM_SURF_OPTION_READ |
-                       TBM_SURF_OPTION_WRITE, &surface_info);
-   if (ret != TBM_SURFACE_ERROR_NONE)
+   buffer = tbm_surface_internal_create_with_flags(width, height, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
+   GOTOIFTRUE(buffer == NULL, err, "can not create fake_buffer\n");
+
+   memset(&buffer_info, 0x0, sizeof(tbm_surface_info_s));
+   if (tbm_surface_map(buffer,
+                  TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE,
+                  &buffer_info) != TBM_SURFACE_ERROR_NONE)
      {
-        EOM_ERR("BUFF CHANGE: failed mmap buffer: %d", ret);
-        //return ECORE_CALLBACK_PASS_ON;
+        EOM_DBG("can not mmap fake_buffer\n");
+        goto err;
      }
 
-   EOM_DBG("BUFF CHANGE: tbm_buffer: %dx%d", surface_info.width, surface_info.height);
+   memset(buffer_info.planes[0].ptr, 0xFF, buffer_info.planes[0].size);
+   tbm_surface_unmap(buffer);
 
-   tbm_surface_unmap(external_tbm_buffer);
-   */
+   return buffer;
+err:
 
-   /* TODO: Must find proper way of getting tbm_surface */
-   /*client_buffer = _e_eom_create_client_buffer(external_wl_buffer, external_tbm_buffer);*/
-   client_buffer = _e_eom_create_client_buffer(external_wl_buffer, fake_buffers.fake_buffers[0]);
-   RETURNVALIFTRUE(client_buffer == NULL,
-                   ECORE_CALLBACK_PASS_ON,
-                   "ERROR: BUFF CHANGE: alloc client buffer");
+   if (buffer)
+     tbm_surface_destroy(buffer);
 
-   _e_eom_add_client_buffer_to_list(client_buffer);
+   /* TODO: check if the fake buffer is NULL along the code */
+   return NULL;
+}
 
-   /* Stop mirror mode */
-   g_eom->is_mirror_mode = DOWN;
+static Eina_Bool
+_e_eom_util_create_buffers(E_EomOutputPtr eom_output, int width, int height)
+{
+   tbm_surface_info_s buffer_info;
+   tbm_surface_h buffer = NULL;
+   int i = 0;
 
-   return ECORE_CALLBACK_PASS_ON;
+   /*
+    * TODO: Add support of other formats
+    */
+   buffer = tbm_surface_internal_create_with_flags(width, height, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
+   GOTOIFTRUE(buffer == NULL, err, "can not create dst_buffer 1");
 
-   /* TODO: deinitialization */
-}
+   /*
+    * TODO: temp code for testing, actual convert will be in _e_eom_put_src_to_dst()
+    */
+   memset(&buffer_info, 0x0, sizeof(tbm_surface_info_s));
+   if (tbm_surface_map(buffer,
+                       TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE,
+                       &buffer_info) != TBM_SURFACE_ERROR_NONE)
+     {
+        EOM_DBG("can not mmap buffer\n");
+        goto err;
+     }
 
-static void
-_e_eom_add_client_buffer_to_list(E_EomClientBufferPtr client_buffer)
-{
-   _e_eom_client_buffers_list_free();
+   memset(buffer_info.planes[0].ptr, 0x0, buffer_info.planes[0].size);
+   tbm_surface_unmap(buffer);
 
-   g_eom_event_data.client_buffers_list = eina_list_append(g_eom_event_data.client_buffers_list, client_buffer);
-}
+   eom_output->dst_buffers[0] = buffer;
 
-static void
-_e_eom_client_buffers_list_free()
-{
-   E_EomClientBufferPtr *buffer = NULL;
-   Eina_List *l;
+   /*
+    * TODO: Add support of other formats
+    */
+   buffer = tbm_surface_internal_create_with_flags(width, height, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
+   GOTOIFTRUE(buffer == NULL, err, "can not create dst_buffer 2");
 
-   EINA_LIST_FOREACH(g_eom_event_data.client_buffers_list, l, buffer)
+   /*
+    * TODO: temp code for testing, actual convert will be in _e_eom_put_src_to_dst()
+    */
+   memset(&buffer_info, 0x00, sizeof(tbm_surface_info_s));
+   if (tbm_surface_map(buffer,
+                       TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE,
+                       &buffer_info) != TBM_SURFACE_ERROR_NONE)
      {
-        if (buffer)
-          {
-             /* I am not sure if it is necessary */
-             /* tbm_surface_internal_unref(buffer->tbm_buffer); */
+        EOM_DBG("can not mmap buffer\n");
+        goto err;
+     }
 
-             /* TODO: Do we need reference that buffer? */
-             /*e_comp_wl_buffer_reference(buffer->tbm_buffer, NULL);*/
+   memset(buffer_info.planes[0].ptr, 0x0, buffer_info.planes[0].size);
+   tbm_surface_unmap(buffer);
 
-             g_eom_event_data.client_buffers_list = eina_list_remove(g_eom_event_data.client_buffers_list, buffer);
-             E_FREE(buffer);
-          }
-     }
+   eom_output->dst_buffers[1] = buffer;
+
+   return EINA_TRUE;
+
+err:
+   for (i = 0; i < NUM_MAIN_BUF; i++)
+     if (eom_output->dst_buffers[i])
+       tbm_surface_destroy(eom_output->dst_buffers[i]);
+
+   return EINA_FALSE;
 }
 
 static E_EomClientBufferPtr
-_e_eom_create_client_buffer(E_Comp_Wl_Buffer *wl_buffer, tbm_surface_h tbm_buffer)
+_e_eom_util_create_client_buffer(E_Comp_Wl_Buffer *wl_buffer, tbm_surface_h tbm_buffer)
 {
    E_EomClientBufferPtr buffer = NULL;
 
@@ -1121,463 +1481,268 @@ _e_eom_create_client_buffer(E_Comp_Wl_Buffer *wl_buffer, tbm_surface_h tbm_buffe
    buffer->wl_buffer = wl_buffer;
    buffer->tbm_buffer = tbm_buffer;
    /* TODO: It is not used right now */
-   buffer->stamp = _e_eom_get_time_in_mseconds();
+   buffer->stamp = _e_eom_util_get_stamp();
 
    /* I am not sure if it is necessary */
-   /* tbm_surface_internal_ref(tbm_buffer); */
+   tbm_surface_internal_ref(tbm_buffer);
 
    /* TODO: Do we need reference that buffer? */
-   /*e_comp_wl_buffer_reference(buffer->tbm_buffer, NULL);*/
+   /* e_comp_wl_buffer_reference(buffer->tbm_buffer, NULL);*/
 
    return buffer;
 }
 
-static E_EomClientBufferPtr
-_e_eom_get_client_buffer_from_list()
-{
-   E_EomClientBufferPtr buffer = NULL;
-   Eina_List *l;
-
-   /* There must be only one buffer */
-   EINA_LIST_FOREACH(g_eom_event_data.client_buffers_list, l, buffer)
-     {
-        if (buffer)
-          return buffer;
-     }
-
-   return NULL;
-}
-
-static int
-_e_eom_get_time_in_mseconds()
-{
-   struct timespec tp;
-
-   clock_gettime(CLOCK_MONOTONIC, &tp);
-
-   return ((tp.tv_sec * 1000) + (tp.tv_nsec / 1000));
-}
-
-static Eina_Bool
-_e_eom_ecore_drm_activate_cb(void *data, int type EINA_UNUSED, void *event)
+static tbm_surface_h
+_e_eom_util_get_output_surface(const char *name)
 {
- /*
-   Ecore_Drm_Event_Activate *e = NULL;
-   E_EomPtr eom = NULL;
-
-   EOM_DBG("_e_eom_ecore_drm_activate_cb called\n");
-
-   if ((!event) || (!data)) goto end;
-   e = event;
-   eom = data;
-
-   EOM_DBG("e->active:%d\n", e->active);
+   Ecore_Drm_Output *primary_output = NULL;
+   Ecore_Drm_Device *dev;
+   const Eina_List *l;
+   tdm_output *tdm_output_obj = NULL;
+   tbm_surface_h tbm = NULL;
+   tdm_error err = TDM_ERROR_NONE;
+   int count = 0, i = 0;
 
-   if (e->active)
-     {
-        ;
-     }
-   else
+   EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
      {
-        ;
+        primary_output = ecore_drm_device_output_name_find(dev, name);
+        if (primary_output != NULL)
+          break;
      }
 
-end:
-
-*/
-   return ECORE_CALLBACK_PASS_ON;
-}
-
-static void
-_e_eom_wl_request_set_attribute_cb(struct wl_client *client, struct wl_resource *resource, uint32_t output_id, uint32_t attribute)
-{
-   enum wl_eom_error eom_error = WL_EOM_ERROR_NONE;
-   struct wl_resource *iterator = NULL;
-   Eina_Bool changes = EINA_FALSE;
-   Eina_Bool ret = EINA_FALSE;
-   Eina_List *l;
-
-   if (resource == g_eom->current_client)
-     {
-        /* Current client can set any flag it wants */
-        _e_eom_set_eom_attribute_by_current_client(attribute);
-        changes = EINA_TRUE;
-     }
-   else
+   if (primary_output == NULL)
      {
-        ret = _e_eom_set_eom_attribute(attribute);
-        if (ret == EINA_FALSE)
+        EOM_ERR("ERROR: get primary output.(%s)\n", name);
+        EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
           {
-             EOM_DBG("set attribute FAILED\n");
-
-             eom_error = WL_EOM_ERROR_OUTPUT_OCCUPIED;
-             goto end;
+             primary_output = ecore_drm_output_primary_get(dev);
+             if (primary_output != NULL)
+               break;
           }
 
-        changes = EINA_TRUE;
+        if (primary_output == NULL)
+          {
+             EOM_ERR("ERROR: get primary output.(%s)\n", name);
+             return NULL;
+          }
      }
 
-   EOM_DBG("set attribute OK\n");
-
-   /* If client has set WL_EOM_ATTRIBUTE_NONE, eom will be
-    * switched to mirror mode
-    */
-   if (attribute == WL_EOM_ATTRIBUTE_NONE && g_eom->is_mirror_mode == DOWN)
+   tdm_output_obj = tdm_display_get_output(g_eom->dpy, 0, &err);
+   if (tdm_output_obj == NULL || err != TDM_ERROR_NONE)
      {
-        g_eom->is_mirror_mode = UP;
-        ret = _e_eom_set_eom_attribute(WL_EOM_ATTRIBUTE_NONE);
-        _e_eom_set_eom_mode(WL_EOM_MODE_MIRROR);
-
-        _e_eom_client_buffers_list_free();
-
-        ret = _e_eom_mirror_start(g_eom->int_output_name,
-                                  g_eom->src_mode.w,
-                                  g_eom->src_mode.h);
-        GOTOIFTRUE(ret == EINA_FALSE,
-                   end,
-                   "ERROR: restore mirror mode after a client disconnection\n");
-
-        goto end;
+        EOM_ERR("tdm_display_get_output 0 fail\n");
+        return NULL;
+     }
+   err = tdm_output_get_layer_count(tdm_output_obj, &count);
+   if (err != TDM_ERROR_NONE)
+     {
+        EOM_ERR("tdm_output_get_layer_count fail\n");
+        return NULL;
      }
 
-end:
-   wl_eom_send_output_attribute(resource,
-                                g_eom->id,
-                                _e_eom_get_eom_attribute(),
-                                _e_eom_get_eom_attribute_state(),
-                                eom_error);
-
-   /* Notify eom clients that eom state has been changed */
-   if (changes == EINA_TRUE)
+   for (i = 0; i < count; i++)
      {
-        EINA_LIST_FOREACH(g_eom->eom_clients, l, iterator)
+        tdm_layer *layer = tdm_output_get_layer(tdm_output_obj, i, NULL);
+        tdm_layer_capability capabilities = 0;
+        tdm_layer_get_capabilities(layer, &capabilities);
+        if (capabilities & TDM_LAYER_CAPABILITY_PRIMARY)
           {
-             if (iterator == resource)
-               continue;
-
-             if (iterator)
+             tbm = tdm_layer_get_displaying_buffer(layer, &err);
+             if (err != TDM_ERROR_NONE)
                {
-                 if (g_eom->is_mirror_mode == UP)
-                   wl_eom_send_output_attribute(iterator,
-                                                g_eom->id,
-                                                _e_eom_get_eom_attribute(),
-                                                _e_eom_get_eom_attribute_state(),
-                                                WL_EOM_ERROR_NONE);
-                 else
-                   wl_eom_send_output_attribute(iterator,
-                                                g_eom->id,
-                                                _e_eom_get_eom_attribute(),
-                                                WL_EOM_ATTRIBUTE_STATE_LOST,
-                                                WL_EOM_ERROR_NONE);
+                  EOM_ERR("tdm_layer_get_displaying_buffer fail\n");
+                  return NULL;
                }
-          }
-
-        g_eom->current_client = resource;
+           break;
+        }
      }
 
-   return;
+   return tbm;
 }
 
 static void
-_e_eom_wl_request_get_output_info_cb(struct wl_client *client, struct wl_resource *resource, uint32_t output_id)
+_e_eom_util_calculate_fullsize(int src_h, int src_v, int dst_size_h, int dst_size_v,
+                          int *dst_x, int *dst_y, int *dst_w, int *dst_h)
 {
-   EOM_DBG("output:%d\n", output_id);
-
-   if (g_eom->outputs)
-     {
-        Eina_List *l;
-        E_EomOutputPtr output = NULL;
+   double h_ratio, v_ratio;
 
-        EINA_LIST_FOREACH(g_eom->outputs, l, output)
-          {
-             if (output->id == output_id)
-               {
-                  EOM_DBG("send - id : %d, type : %d, mode : %d, w : %d, h : %d, w_mm : %d, h_mm : %d, conn : %d\n",
-                          output->id, output->type, output->mode, output->w, output->h,
-                          output->phys_width, output->phys_height, output->status);
+   h_ratio = src_h / dst_size_h;
+   v_ratio = src_v / dst_size_v;
 
-                  wl_eom_send_output_info(resource, output->id, output->type, output->mode, output->w, output->h,
-                                          output->phys_width, output->phys_height, output->status);
-               }
-          }
+   if (h_ratio == v_ratio)
+     {
+        *dst_x = 0;
+        *dst_y = 0;
+        *dst_w = dst_size_h;
+        *dst_h = dst_size_v;
+     }
+   else if (h_ratio < v_ratio)
+     {
+        *dst_y = 0;
+        *dst_h = dst_size_v;
+        *dst_w = dst_size_v * src_h / src_v;
+        *dst_x = (dst_size_h - *dst_w) / 2;
+     }
+   else /* (h_ratio > v_ratio) */
+     {
+        *dst_x = 0;
+        *dst_w = dst_size_h;
+        *dst_h = dst_size_h * src_h / src_v;
+        *dst_y = (dst_size_v - *dst_h) / 2;
      }
 }
 
-static const struct wl_eom_interface _e_eom_wl_implementation =
-{
-   _e_eom_wl_request_set_attribute_cb,
-   _e_eom_wl_request_get_output_info_cb
-};
-
-/* wl_eom global object destroy function */
-static void
-_e_eom_wl_resource_destory_cb(struct wl_resource *resource)
+static int
+_e_eom_util_get_stamp()
 {
-   struct wl_resource *iterator = NULL;
-   Eina_List *l = NULL;
-   Eina_Bool ret;
+   struct timespec tp;
 
-   EOM_DBG("client unbind\n");
+   clock_gettime(CLOCK_MONOTONIC, &tp);
 
-   g_eom->eom_clients = eina_list_remove(g_eom->eom_clients, resource);
+   return ((tp.tv_sec * 1000) + (tp.tv_nsec / 1000));
+}
 
-   /* If not current client has been destroyed do nothing */
-   if (resource != g_eom->current_client)
-     goto end2;
+#if 0
+static void
+_e_eom_util_draw(tbm_surface_h surface)
+{
+   int i = 0, j = 0;
 
-   /* If a client has been disconnected and mirror mode has not
-    * been restore, start mirror mode
-    */
-   if (g_eom->is_mirror_mode == DOWN)
-     {
-        g_eom->is_mirror_mode = UP;
-        ret = _e_eom_set_eom_attribute(WL_EOM_ATTRIBUTE_NONE);
-        _e_eom_set_eom_mode(WL_EOM_MODE_MIRROR);
+   tbm_bo bo = tbm_surface_internal_get_bo(surface, 0);
+   RETURNIFTRUE(bo == NULL, "bo is NULL");
 
-        _e_eom_client_buffers_list_free();
+   unsigned int *mm = (unsigned int *)tbm_bo_map(bo, TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE).ptr;
+   RETURNIFTRUE(mm == NULL, "mm is NULL");
 
-        ret = _e_eom_mirror_start(g_eom->int_output_name,
-                                  g_eom->src_mode.w,
-                                  g_eom->src_mode.h);
-        GOTOIFTRUE(ret == EINA_FALSE,
-                   end,
-                   "ERROR: restore mirror mode after a client disconnection\n");
-     }
+   unsigned char r = 0;
+   unsigned char g = 255;
+   unsigned char b = 0;
+   unsigned char a = 0;
 
-end:
-   /* Notify eom clients that eom state has been changed */
-   EINA_LIST_FOREACH(g_eom->eom_clients, l, iterator)
-     {
-        if (iterator)
-          {
-             wl_eom_send_output_attribute(iterator,
-                                          g_eom->id,
-                                          _e_eom_get_eom_attribute(),
-                                          _e_eom_get_eom_attribute_state(),
-                                          WL_EOM_ERROR_NONE);
-          }
-     }
+   int w = (int)tbm_surface_get_width(surface);
+   int h = (int)tbm_surface_get_height(surface);
 
-end2:
-   g_eom->current_client = NULL;
+   for (i = 0; i < w; i++)
+     for (j = 0; j < h/2; j++)
+       {
+          mm[i*w + j] = r << 24 | g << 16 | b << 8 | a;
+       }
 }
+#endif
 
-/* wl_eom global object bind function */
 static void
-_e_eom_wl_bind_cb(struct wl_client *client, void *data, uint32_t version, uint32_t id)
+_e_eom_client_add_buffer(E_EomClientPtr client, E_EomClientBufferPtr buffer)
 {
-   enum wl_eom_type eom_type = WL_EOM_TYPE_NONE;
-   struct wl_resource *resource = NULL;
+   _e_eom_client_free_buffers(client);
 
-   RETURNIFTRUE(data == NULL, "ERROR: data is NULL");
+   client->buffers = eina_list_append(client->buffers, buffer);
+}
 
-   E_EomPtr eom = data;
+static void
+_e_eom_client_free_buffers(E_EomClientPtr client)
+{
+   E_EomClientBufferPtr buffer = NULL;
+   Eina_List *l;
 
-   resource = wl_resource_create(client,
-                         &wl_eom_interface,
-                         MIN(version, 1),
-                         id);
-   if (resource == NULL)
+   EINA_LIST_FOREACH(client->buffers, l, buffer)
      {
-        EOM_ERR("error. resource is null. (version :%d, id:%d)\n", version, id);
-        wl_client_post_no_memory(client);
-        return;
-     }
-
-   wl_resource_set_implementation(resource,
-                                  &_e_eom_wl_implementation,
-                                  eom,
-                                  _e_eom_wl_resource_destory_cb);
-
-   eom_type = _e_eom_output_name_to_eom_type(g_eom->ext_output_name);
-
-   wl_eom_send_output_type(resource,
-                           eom->id,
-                           eom_type,
-                           _e_eom_get_eom_status());
-
-   wl_eom_send_output_attribute(resource,
-                                eom->id,
-                                _e_eom_get_eom_attribute(),
-                                _e_eom_get_eom_attribute_state(),
-                                WL_EOM_ERROR_NONE);
-
-   wl_eom_send_output_mode(resource,
-                           eom->id,
-                           _e_eom_get_eom_mode());
-
-   EOM_DBG("send - output count : %d\n", g_eom->output_count);
-   wl_eom_send_output_count(resource,
-                            g_eom->output_count);
+        if (buffer)
+          {
+             /* I am not sure if it is necessary */
+             if (buffer->tbm_buffer)
+               tbm_surface_internal_unref(buffer->tbm_buffer);
 
-   if (g_eom->outputs)
-     {
-        Eina_List *l;
-        E_EomOutputPtr output = NULL;
+             /* TODO: Do we need reference that buffer? */
+             /* e_comp_wl_buffer_reference(buffer->tbm_buffer, NULL); */
 
-        EINA_LIST_FOREACH(g_eom->outputs, l, output)
-          {
-             EOM_DBG("send - id : %d, type : %d, mode : %d, w : %d, h : %d, w_mm : %d, h_mm : %d, conn : %d\n",
-                     output->id, output->type, output->mode, output->w, output->h,
-                     output->phys_width, output->phys_height, output->status);
-             wl_eom_send_output_info(resource, output->id, output->type, output->mode, output->w, output->h,
-                                     output->phys_width, output->phys_height, output->status);
+             client->buffers = eina_list_remove(client->buffers, buffer);
+             E_FREE(buffer);
           }
      }
-
-   g_eom->eom_clients = eina_list_append(g_eom->eom_clients, resource);
 }
 
-static void
-_e_eom_deinit()
+static E_EomClientBufferPtr
+_e_eom_client_get_buffer(E_EomClientPtr client)
 {
-   Ecore_Event_Handler *h = NULL;
-
-   if (g_eom == NULL) return;
+   E_EomClientBufferPtr buffer = NULL;
+   Eina_List *l;
 
-   if (g_eom->handlers)
+   /* There must be only one buffer */
+   EINA_LIST_FOREACH(client->buffers, l, buffer)
      {
-        EINA_LIST_FREE(g_eom->handlers, h)
-        ecore_event_handler_del(h);
+        if (buffer)
+          return buffer;
      }
 
-   if (g_eom->dpy) tdm_display_deinit(g_eom->dpy);
-   if (g_eom->bufmgr) tbm_bufmgr_deinit(g_eom->bufmgr);
-
-   if (g_eom->global) wl_global_destroy(g_eom->global);
-
-   E_FREE(g_eom);
+   return NULL;
 }
 
-static Eina_Bool
-_e_eom_output_info_get(tdm_display *dpy)
+static E_EomClientPtr
+_e_eom_client_get_by_resource(struct wl_resource *resource)
 {
-   tdm_error ret = TDM_ERROR_NONE;
-   int i, count;
-
-   ret = tdm_display_get_output_count(dpy, &count);
-   RETURNVALIFTRUE(ret != TDM_ERROR_NONE,
-                   EINA_FALSE,
-                   "tdm_display_get_output_count fail");
-   RETURNVALIFTRUE(count <= 1,
-                   EINA_FALSE,
-                   "output count is 1. device doesn't support external outputs.\n");
-
-   g_eom->output_count = count - 1;
-   EOM_DBG("external output count : %d\n", g_eom->output_count);
+   Eina_List *l;
+   E_EomClientPtr client;
 
-   /* skip main output id:0 */
-   /* start from 1 */
-   for (i = 1; i < count; i++)
+   EINA_LIST_FOREACH(g_eom->clients, l, client)
      {
-        const tdm_output_mode *mode = NULL;
-        E_EomOutputPtr new_output = NULL;
-        unsigned int mmWidth, mmHeight;
-        tdm_output_conn_status status;
-        tdm_output *output = NULL;
-        tdm_output_type type;
+        if (client && client->resource == resource)
+          return client;
+     }
 
-        output = tdm_display_get_output(dpy, i, &ret);
-        GOTOIFTRUE(ret != TDM_ERROR_NONE,
-                   err,
-                   "tdm_display_get_output fail(ret:%d)", ret);
+   return NULL;
+}
 
-        GOTOIFTRUE(output == NULL,
-                   err,
-                   "tdm_display_get_output fail(no output:%d)", ret);
+static E_EomClientPtr
+_e_eom_client_current_by_id_get(int id)
+{
+   Eina_List *l;
+   E_EomClientPtr client;
 
-        ret = tdm_output_get_output_type(output, &type);
-        GOTOIFTRUE(ret != TDM_ERROR_NONE,
-                   err,
-                   "tdm_output_get_output_type fail(%d)", ret);
+   EINA_LIST_FOREACH(g_eom->clients, l, client)
+     {
+        if (client &&
+            client->current == EINA_TRUE &&
+            client->output_id == id)
+          return client;
+     }
 
-        new_output = E_NEW(E_EomOutput, 1);
-        GOTOIFTRUE(new_output == NULL,
-                   err,
-                   "calloc fail");
+   return NULL;
+}
 
-        ret = tdm_output_get_conn_status(output, &status);
-        if (ret != TDM_ERROR_NONE)
-          {
-             EOM_ERR("tdm_output_get_conn_status fail(%d)", ret);
-             free(new_output);
-             goto err;
-          }
-        new_output->id = i;
-        new_output->type = type;
-        new_output->status = status;
-        new_output->mode = EOM_OUTPUT_MODE_NONE;
-        new_output->output = output;
+static Eina_Bool
+_e_eom_init()
+{
+   Eina_Bool ret = EINA_FALSE;
 
-        ret = tdm_output_add_change_handler(output, _e_eom_tdm_output_status_change_cb, NULL);
-        if (ret != TDM_ERROR_NONE)
-          {
-              EOM_ERR("tdm_output_add_change_handler fail(%d)", ret);
-              free(new_output);
-              goto err;
-          }
+   EINA_SAFETY_ON_NULL_GOTO(e_comp_wl, err);
 
-        if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED)
-          {
-             EOM_DBG("create(%d)output, type:%d, status:%d",
-                     new_output->id, new_output->type, new_output->status);
-             g_eom->outputs = eina_list_append(g_eom->outputs, new_output);
-             continue;
-          }
-        new_output->status = TDM_OUTPUT_CONN_STATUS_CONNECTED;
+   g_eom = E_NEW(E_Eom, 1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(g_eom, EINA_FALSE);
 
-        ret = tdm_output_get_mode(output, &mode);
-        if (ret != TDM_ERROR_NONE)
-          {
-             EOM_ERR("tdm_output_get_mode fail(%d)", ret);
-             free(new_output);
-             goto err;
-          }
+   g_eom->global = wl_global_create(e_comp_wl->wl.disp,
+                           &wl_eom_interface,
+                           1,
+                           g_eom,
+                           _e_eom_cb_wl_bind);
 
-        if (mode == NULL)
-          {
-             new_output->w = 0;
-             new_output->h = 0;
-          }
+   uint32_t id = wl_display_get_serial(e_comp_wl->wl.disp);
+   EOM_DBG("eom name: %d", id);
 
-        else
-          {
-             new_output->w = mode->hdisplay;
-             new_output->h = mode->vdisplay;
-          }
+   EINA_SAFETY_ON_NULL_GOTO(g_eom->global, err);
 
-        ret = tdm_output_get_physical_size(output, &mmWidth, &mmHeight);
-        if (ret != TDM_ERROR_NONE)
-          {
-             EOM_ERR("tdm_output_get_conn_status fail(%d)", ret);
-             free(new_output);
-             goto err;
-          }
-        new_output->phys_width = mmWidth;
-        new_output->phys_height = mmHeight;
+   ret = _e_eom_init_internal();
+   GOTOIFTRUE(ret == EINA_FALSE, err, "failed init_internal()");
 
-        EOM_DBG("create(%d)output, type:%d, status:%d, w:%d, h:%d, mm_w:%d, mm_h:%d",
-                new_output->id, new_output->type, new_output->status,
-                new_output->w, new_output->h, new_output->phys_width, new_output->phys_height);
+   E_LIST_HANDLER_APPEND(g_eom->handlers, ECORE_DRM_EVENT_ACTIVATE, _e_eom_cb_ecore_drm_activate, g_eom);
+   E_LIST_HANDLER_APPEND(g_eom->handlers, ECORE_DRM_EVENT_OUTPUT, _e_eom_cb_ecore_drm_output, g_eom);
+   E_LIST_HANDLER_APPEND(g_eom->handlers, E_EVENT_CLIENT_BUFFER_CHANGE, _e_eom_cb_client_buffer_change, NULL);
 
-        g_eom->outputs = eina_list_append(g_eom->outputs, new_output);
-     }
+   g_eom->main_output_name = NULL;
 
    return EINA_TRUE;
 
 err:
-   if (g_eom->outputs)
-     {
-        Eina_List *l;
-        E_EomOutputPtr output;
-
-        EINA_LIST_FOREACH(g_eom->outputs, l, output)
-          {
-             free(output);
-          }
-        eina_list_free(g_eom->outputs);
-     }
-
+   _e_eom_deinit();
    return EINA_FALSE;
 }
 
@@ -1595,9 +1760,9 @@ _e_eom_init_internal()
    g_eom->bufmgr = tbm_bufmgr_init(g_eom->fd);
    GOTOIFTRUE(g_eom->bufmgr == NULL, err, "tbm_bufmgr_init fail");
 
-   if (_e_eom_output_info_get(g_eom->dpy) != EINA_TRUE)
+   if (_e_eom_output_init(g_eom->dpy) != EINA_TRUE)
      {
-        EOM_ERR("_e_eom_output_info_get fail\n");
+        EOM_ERR("_e_eom_output_init fail\n");
         goto err;
      }
 
@@ -1613,48 +1778,25 @@ err:
    return EINA_FALSE;
 }
 
-static Eina_Bool
-_e_eom_init()
+static void
+_e_eom_deinit()
 {
-   Eina_Bool ret = EINA_FALSE;
-
-   EINA_SAFETY_ON_NULL_GOTO(e_comp_wl, err);
-
-   g_eom = E_NEW(E_Eom, 1);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(g_eom, EINA_FALSE);
-
-   g_eom->global = wl_global_create(e_comp_wl->wl.disp,
-                           &wl_eom_interface,
-                           1,
-                           g_eom,
-                           _e_eom_wl_bind_cb);
-
-   EINA_SAFETY_ON_NULL_GOTO(g_eom->global, err);
-
-   ret = _e_eom_init_internal();
-   GOTOIFTRUE(ret == EINA_FALSE, err, "failed init_internal()");
-
-   E_LIST_HANDLER_APPEND(g_eom->handlers, ECORE_DRM_EVENT_ACTIVATE, _e_eom_ecore_drm_activate_cb, g_eom);
-   E_LIST_HANDLER_APPEND(g_eom->handlers, ECORE_DRM_EVENT_OUTPUT, _e_eom_ecore_drm_output_cb, g_eom);
-   E_LIST_HANDLER_APPEND(g_eom->handlers, E_EVENT_CLIENT_BUFFER_CHANGE, _e_eom_client_buffer_change, NULL);
+   Ecore_Event_Handler *h = NULL;
 
-   g_eom->is_external_init = DOWN;
-   g_eom->is_internal_grab = DOWN;
-   g_eom->ext_output_name = NULL;
-   g_eom->int_output_name = NULL;
+   if (g_eom == NULL) return;
 
-   g_eom->current_client = NULL;
+   if (g_eom->handlers)
+     {
+        EINA_LIST_FREE(g_eom->handlers, h)
+        ecore_event_handler_del(h);
+     }
 
-   _e_eom_set_eom_attribute_state(WL_EOM_ATTRIBUTE_STATE_NONE);
-   _e_eom_set_eom_attribute(WL_EOM_ATTRIBUTE_NONE);
-   _e_eom_set_eom_status(WL_EOM_STATUS_NONE);
-   _e_eom_set_eom_mode(WL_EOM_MODE_NONE);
+   if (g_eom->dpy) tdm_display_deinit(g_eom->dpy);
+   if (g_eom->bufmgr) tbm_bufmgr_deinit(g_eom->bufmgr);
 
-   return EINA_TRUE;
+   if (g_eom->global) wl_global_destroy(g_eom->global);
 
-err:
-   _e_eom_deinit();
-   return EINA_FALSE;
+   E_FREE(g_eom);
 }
 
 E_API void *
@@ -1676,3 +1818,4 @@ e_modapi_save(E_Module *m EINA_UNUSED)
    /* Save something to be kept */
    return 1;
 }
+
index a1dfe95..6e56ca7 100644 (file)
@@ -46,9 +46,7 @@ E_API int   e_modapi_save(E_Module *m);
 
 typedef struct _E_Eom E_Eom, *E_EomPtr;
 typedef struct _E_Eom_Out_Mode E_EomOutMode, *E_EomOutModePtr;
-typedef struct _E_Eom_Event_Data E_EomEventData, *E_EomEventDataPtr;
 typedef struct _E_Eom_Output E_EomOutput, *E_EomOutputPtr;
-typedef struct _E_Eom_Fake_Buffers E_EomFakeBuffers, *E_EomFakeBuffersPtr;
 typedef struct _E_Eom_Client_Buffer E_EomClientBuffer, *E_EomClientBufferPtr;
 typedef struct _E_Eom_Client E_EomClient, *E_EomClientPtr;
 
@@ -58,6 +56,13 @@ typedef enum
    UP,
 } E_EomFlag;
 
+typedef enum
+{
+   NONE = 0,
+   MIRROR,
+   PRESENTATION,
+} E_EomOutputState;
+
 struct _E_Eom_Out_Mode
 {
    int w;
@@ -69,82 +74,65 @@ struct _E_Eom_Output
    unsigned int id;
    eom_output_type_e type;
    eom_output_mode_e mode;
-   unsigned int w;
-   unsigned int h;
+   unsigned int width;
+   unsigned int height;
    unsigned int phys_width;
    unsigned int phys_height;
 
+   const char *name;
+
    tdm_output *output;
+   tdm_layer *layer;
+   tdm_pp *pp;
 
+   E_EomOutputState state;
    tdm_output_conn_status status;
-   E_EomFlag mirror_run;
    eom_output_attribute_e attribute;
    eom_output_attribute_state_e attribute_state;
 
    /* external output data */
-   char *ext_output_name;
-   E_EomFlag is_external_init;
-   E_EomOutMode src_mode;
    E_Comp_Wl_Output *wl_output;
 
-   /* internal output data */
-   char *int_output_name;
-   E_EomFlag is_internal_grab;
-   E_EomOutMode dst_mode;
+   /* mirror mode data */
+   tbm_surface_h dst_buffers[NUM_MAIN_BUF];
+   int current_buffer;
+   int pp_buffer;
+
+   tbm_surface_h fake_buffer;
 };
 
 struct _E_Eom
 {
    struct wl_global *global;
-   Eina_List *eom_clients;
-   Eina_List *handlers;
 
    tdm_display *dpy;
    tbm_bufmgr bufmgr;
    int fd;
 
+   /* Internal output data */
+   E_EomFlag main_output_state;
+   char *main_output_name;
+   int width;
+   int height;
+
+   Eina_List *clients;
+   Eina_List *handlers;
    Eina_List *outputs;
    unsigned int output_count;
-
-#if 1
-   /* eom state */
-   E_EomFlag eom_sate;
-   enum wl_eom_mode eom_mode;
-   enum wl_eom_attribute eom_attribute;
-   enum wl_eom_attribute_state eom_attribute_state;
-   enum wl_eom_status eom_status;
-
-   /*data related to cooperating with clients */
-   E_EomFlag is_mirror_mode;
-   struct wl_resource *current_client;
-
-   /* external output data */
-   char *ext_output_name;
-   E_EomFlag is_external_init;
-   int id;
-   E_EomOutMode src_mode;
-   E_Comp_Wl_Output *wl_output;
-
-   /* internal output data */
-   char *int_output_name;
-   E_EomFlag is_internal_grab;
-   E_EomOutMode dst_mode;
-#endif
 };
 
-struct _E_Eom_Event_Data
+struct _E_Eom_Client
 {
-   tdm_output *output;
-   tdm_layer *layer;
-   tdm_pp *pp;
+   struct wl_resource *resource;
+   Eina_Bool current;
 
-   /* mirror mode data*/
-   tbm_surface_h dst_buffers[NUM_MAIN_BUF];
-   int current_buffer;
-   int pp_buffer;
+   /* Output a client related to */
+   int output_id;
 
-   /* extended mode data */
-   Eina_List *client_buffers_list;
+   /*TODO: As I understand there are cannot be more than one client buffer on
+    *server side, but for future extendabilty store it in the list */
+   /*Client's buffers */
+   Eina_List *buffers;
 };
 
 struct _E_Eom_Client_Buffer
@@ -155,52 +143,60 @@ struct _E_Eom_Client_Buffer
    unsigned long stamp;
 };
 
-struct _E_Eom_Client
-{
-       struct wl_resource *resource;
-       Eina_Bool curent;
-};
-
-struct _E_Eom_Fake_Buffers
-{
-   tbm_surface_h fake_buffers[NUM_MAIN_BUF];
-   int current_fake_buffer;
-};
-
-/* handle external output */
-static tdm_layer * _e_eom_hal_layer_get(tdm_output *output, int width, int height);
-static Eina_Bool _e_eom_create_output_buffers(E_EomEventDataPtr eom_data, int width, int height);
-static enum wl_eom_type _e_eom_output_name_to_eom_type(const char *output_name);
-
-/* handle internal output, pp */
-static Eina_Bool _e_eom_mirror_start(const char *output_name, int width, int height);
-static tbm_surface_h _e_eom_root_internal_tdm_surface_get(const char *name);
-static Eina_Bool _e_eom_pp_src_to_dst(tbm_surface_h src_buffer);
+static Eina_Bool _e_eom_init();
+static Eina_Bool _e_eom_init_internal();
+static void _e_eom_deinit();
+
+static void _e_eom_cb_wl_request_set_attribute(struct wl_client *client,
+                                               struct wl_resource *resource,
+                                               uint32_t output_id,
+                                               uint32_t attribute);
+static void _e_eom_cb_wl_request_get_output_info(struct wl_client *client,
+                                                 struct wl_resource *resource,
+                                                 uint32_t output_id);
+static void _e_eom_cb_wl_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id);
+static void _e_eom_cb_wl_resource_destory(struct wl_resource *resource);
+static Eina_Bool _e_eom_cb_ecore_drm_output(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
+static Eina_Bool _e_eom_cb_ecore_drm_activate(void *data, int type EINA_UNUSED, void *event);
+static Eina_Bool _e_eom_cb_client_buffer_change(void *data, int type, void *event);
+static void _e_eom_cb_pp(tbm_surface_h surface, void *user_data);
+static void _e_eom_cb_commit(tdm_output *output EINA_UNUSED, unsigned int sequence EINA_UNUSED,
+                             unsigned int tv_sec EINA_UNUSED, unsigned int tv_usec EINA_UNUSED,
+                             void *user_data);
+static void _e_eom_cb_tdm_output_status_change(tdm_output *output, tdm_output_change_type type,
+                                               tdm_value value, void *user_data);
+
+static Eina_Bool _e_eom_output_init(tdm_display *dpy);
+static const tdm_output_mode *_e_eom_output_get_best_mode(tdm_output *output);
+static int _e_eom_output_get_position(void);
+static void _e_eom_output_start_mirror(E_EomOutputPtr eom_output, int width, int height);
+static void _e_eom_output_stop_mirror(E_EomOutputPtr eom_output);
+static void _e_eom_output_deinit(E_EomOutputPtr eom_output);
+static tdm_layer *_e_eom_output_get_layer(tdm_output *output, int width, int height);
+static E_EomOutputPtr _e_eom_output_get_by_id(int id);
+static E_EomOutputPtr _e_eom_output_get_by_name(const char *name);
+static Eina_Bool _e_eom_output_start_pp(E_EomOutputPtr eom_output);
+
+static Eina_Bool _e_eom_pp_init(E_EomOutputPtr eom_output, tbm_surface_h src_buffer);
 static Eina_Bool _e_eom_pp_is_needed(int src_w, int src_h, int dst_w, int dst_h);
-static void _e_eom_calculate_fullsize(int src_h, int src_v, int dst_size_h, int dst_size_v,
-                                      int *dst_x, int *dst_y, int *dst_w, int *dst_h);
-
-/* tdm handlers */
-static void _e_eom_pp_cb(tbm_surface_h surface, void *user_data);
-static void _e_eom_commit_cb(tdm_output *output EINA_UNUSED, unsigned int sequence EINA_UNUSED,
-                                    unsigned int tv_sec EINA_UNUSED, unsigned int tv_usec EINA_UNUSED,
-                                    void *user_data);
-
-/* handle clients buffers
- * The work flow is very simple, when a client does commit we take a client's
- * buffer and add it to list. During page flip we show that buffer. When a
- * new client's buffer has been send we destroy previous buffer and add new
- * one to the list. And so on
- * We created that list for future possible extending
- */
-static E_EomClientBufferPtr _e_eom_create_client_buffer(E_Comp_Wl_Buffer *wl_buffer, tbm_surface_h tbm_buffer);
-static void _e_eom_add_client_buffer_to_list(E_EomClientBufferPtr client_buffer);
-static void _e_eom_client_buffers_list_free();
-static E_EomClientBufferPtr _e_eom_get_client_buffer_from_list();
-
-/*eom utils functions*/
-static int _e_eom_get_time_in_mseconds();
-/*static void _e_eom_create_fake_buffers(int width, int height);*/
 
+static Eina_Bool _e_eom_util_create_buffers(E_EomOutputPtr eom_output, int width, int height);
+static E_EomClientBufferPtr _e_eom_util_create_client_buffer(E_Comp_Wl_Buffer *wl_buffer,
+                                                        tbm_surface_h tbm_buffer);
+static tbm_surface_h _e_eom_util_create_fake_buffer(int width, int height);
+static void _e_eom_util_calculate_fullsize(int src_h, int src_v, int dst_size_h, int dst_size_v,
+                                           int *dst_x, int *dst_y, int *dst_w, int *dst_h);
+static tbm_surface_h _e_eom_util_get_output_surface(const char *name);
+static int _e_eom_util_get_stamp();
+#if 0
+static void _e_eom_util_draw(tbm_surface_h surface);
+#endif
+
+static void _e_eom_client_add_buffer(E_EomClientPtr client, E_EomClientBufferPtr buffer);
+static void _e_eom_client_free_buffers(E_EomClientPtr client);
+static E_EomClientBufferPtr _e_eom_client_get_buffer(E_EomClientPtr client);
+static E_EomClientPtr _e_eom_client_get_by_resource(struct wl_resource *resource);
+static E_EomClientPtr _e_eom_client_current_by_id_get(int id);
 
 #endif
+