e_eom: refactoring the eom and the external outputs 57/211857/2
authorSooChan Lim <sc1.lim@samsung.com>
Tue, 6 Aug 2019 04:07:01 +0000 (13:07 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Fri, 9 Aug 2019 11:19:18 +0000 (20:19 +0900)
E20 needs to redesign the code for the support of the multi-dipslay.

Change-Id: I14ace20c2d0011d7acf3245e4bded46ab20cb6a5

src/bin/e_eom.c
src/bin/e_eom.h
src/bin/e_hwc.h
src/bin/e_hwc_planes.c
src/bin/e_hwc_planes.h
src/bin/e_hwc_windows.c
src/bin/e_hwc_windows.h
src/bin/e_output.c
src/bin/e_output.h

index f7bb76f768d001e8e135801cb11a41d8f5f254a0..9d4acaa6fcb0ae96ea2e362d133c656606003a87 100644 (file)
 #include <time.h>
 #endif
 
-/*
-#define EOM_DUMP_MIRROR_BUFFERS
-#define EOM_DUMP_PRESENTATION_BUFFERS
-*/
+static int eom_trace_debug = 0;
 
 #define ALEN(array) (sizeof(array) / sizeof(array)[0])
 
 #define EOM_NUM_ATTR 3
-#define EOM_CONNECT_CHECK_TIMEOUT 10.0
-#define EOM_DELAY_CHECK_TIMEOUT 1.0
-#define EOM_DELAY_CONNECT_CHECK_TIMEOUT 3.0
-
-#define TDM_CONNECTOR_NAME_LEN 32
-
-#ifndef CLEAR
-#define CLEAR(x) memset(&(x), 0, sizeof (x))
-#endif
+#define EOM_CONNECT_CHECK_TIMEOUT 4.0
 
 #define EOERR(f, output, x...)                               \
    do                                                            \
      }                                                           \
    while (0)
 
-typedef struct _E_Eom E_Eom, *E_EomPtr;
-typedef struct _E_Eom_Out_Mode E_EomOutMode, *E_EomOutModePtr;
-typedef struct _E_Eom_Output E_EomOutput, *E_EomOutputPtr;
+typedef struct _E_Eom        E_Eom,       *E_EomPtr;
 typedef struct _E_Eom_Client E_EomClient, *E_EomClientPtr;
+typedef struct _E_Eom_Output E_EomOutput, *E_EomOutputPtr;
 typedef struct _E_Eom_Comp_Object_Intercept_Hook_Data E_EomCompObjectInterceptHookData;
-typedef struct _E_Eom_Output_Buffer E_EomOutputBuffer, *E_EomOutputBufferPtr;
-typedef struct _E_Eom_Buffer E_EomBuffer, *E_EomBufferPtr;
-typedef struct _E_Eom_Output_Pp E_EomOutputPp, *E_EomOutputPpPtr;
-typedef struct _E_Eom_Pp_Data E_EomPpData, *E_EomPpDataPtr;
-typedef void(*E_EomEndShowingEventPtr)(E_EomOutputPtr eom_output, tbm_surface_h srfc, void * user_data);
-
-typedef enum
-{
-   NONE,
-   MIRROR,
-   PRESENTATION,
-   WAIT_PRESENTATION,    /* It is used for delayed runnig of Presentation mode */
-} E_EomOutputState;
-
-typedef enum
-{
-   ROTATE_NONE,
-   ROTATE_INIT,
-   ROTATE_PENDING,
-   ROTATE_CANCEL,
-   ROTATE_DONE
-} E_EomOutputRotate;
 
 struct _E_Eom
 {
    struct wl_global *global;
 
-   tdm_display *dpy;
-
    unsigned int eom_output_count;
    Eina_List *eom_outputs;
    Eina_List *clients;
    Eina_List *handlers;
    Eina_List *hooks;
    Eina_List *comp_object_intercept_hooks;
-   Eina_List *added_outputs;
    E_Output_Hook *output_connect_status_hook;
    E_Output_Hook *output_mode_changes_hook;
    E_Output_Hook *output_add_hook;
    E_Output_Hook *output_remove_hook;
-
-   /* Internal output data */
-   E_Output *output_primary;
-   char check_first_boot;
-   Ecore_Timer *timer;
-};
-
-struct _E_Eom_Output
-{
-   unsigned int id;
-   eom_output_type_e type;
-   eom_output_mode_e mode;
-   unsigned int width;
-   unsigned int height;
-   unsigned int phys_width;
-   unsigned int phys_height;
-
-   const char *name;
-
-   tdm_output *output;
-   tdm_layer *primary_layer;
-   tdm_layer *overlay_layer;
-   Eina_Bool need_overlay_pp;
-
-   E_EomOutputState state;
-   Eina_Bool connection_status;
-   enum wl_eom_status connection;
-   eom_output_attribute_e attribute;
-
-   /* pp overlay (presentation mode subsurface data) */
-   E_EomOutputPpPtr pp_overlay;
-   Eina_Bool pp_overlay_converting;
-   Eina_Bool pp_overlay_deinit;
-   Eina_List *pending_overlay_buff;       /* can be deleted any time */
-   E_EomOutputBufferPtr wait_overlay_buff; /* wait end of commit, can't be deleted */
-   E_EomOutputBufferPtr show_overlay_buff; /* current showed buffer, can be deleted only after commit event with different buff */
-   Eina_List *pending_pp_overlay;
-   Eina_List *pp_overlay_data;
-
-   /* If attribute has been set while external output is disconnected
-    * then show black screen and wait until EOM client start sending
-    * buffers. After expiring of the delay start mirroring */
-   Ecore_Timer *delay_timer;
-
-   E_Output *eout;
-   Eina_Bool added;
 };
 
 struct _E_Eom_Client
@@ -158,40 +75,23 @@ struct _E_Eom_Client
    E_Client *ec;
 };
 
-struct _E_Eom_Output_Buffer
-{
-   E_EomOutputPtr eom_output;
-   tbm_surface_h tbm_surface;
-   E_EomEndShowingEventPtr cb_func;
-   void *cb_user_data;
-};
-
-struct _E_Eom_Buffer
+struct _E_Eom_Output
 {
-   E_Comp_Wl_Buffer *wl_buffer;
-   E_Comp_Wl_Buffer_Ref comp_wl_buffer_ref;
-
-   /* double reference to avoid sigterm crash */
-   E_Comp_Wl_Buffer_Ref comp_wl_buffer_ref_2;
-};
+   unsigned int id;
+   eom_output_type_e type;
+   eom_output_attribute_e attribute;
+   enum wl_eom_status connection;
 
-struct _E_Eom_Output_Pp
-{
-   tdm_pp *pp;
-   tbm_surface_queue_h queue;
-   tdm_info_pp pp_info;
-};
+   E_Output *output;
+   Eina_Bool added;
 
-struct _E_Eom_Pp_Data
-{
-   E_EomOutputPtr eom_output;
-   E_EomBufferPtr eom_buffer;
-   tbm_surface_h tsurface;
+   E_EomClientPtr eom_client;
 };
 
 struct _E_Eom_Comp_Object_Intercept_Hook_Data
 {
    E_Client *ec;
+   E_EomOutput *eom_output;
    E_Comp_Object_Intercept_Hook *hook;
 };
 
@@ -218,99 +118,37 @@ static int eom_output_attributes[EOM_NUM_ATTR][EOM_NUM_ATTR] =
 };
 
 static E_EomPtr g_eom = NULL;
-static Eina_Bool eom_trace_debug = 0;
-
-static void _e_eom_presentation_pp_run(E_EomOutputPtr eom_output, tbm_surface_h src_surface, E_EomBufferPtr eom_buff);
-
-static E_EomOutputBufferPtr
-_e_eom_output_buff_create(E_EomOutputPtr eom_output, tbm_surface_h tbm_surface, E_EomEndShowingEventPtr cb_func, void *cb_user_data)
-{
-   EINA_SAFETY_ON_NULL_RETURN_VAL(tbm_surface, NULL);
-   E_EomOutputBufferPtr outbuff = E_NEW(E_EomOutputBuffer, 1);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(outbuff, NULL);
-
-   if (eom_trace_debug)
-     EOINF("Allocate output buffer:%p", eom_output->eout, outbuff);
-
-   outbuff->eom_output = eom_output;
-
-   tbm_surface_internal_ref(tbm_surface);
-   outbuff->tbm_surface = tbm_surface;
-
-   outbuff->cb_func = cb_func;
-   outbuff->cb_user_data = cb_user_data;
-
-   return outbuff;
-}
-
-static void
-_e_eom_output_buff_delete(E_EomOutputBufferPtr buff)
-{
-   if (buff)
-     {
-        tbm_surface_internal_unref(buff->tbm_surface);
-        if (buff->cb_func)
-          buff->cb_func(buff->eom_output, buff->tbm_surface, buff->cb_user_data);
-        E_FREE(buff);
-     }
-}
-
-static E_EomBuffer *
-_e_eom_buffer_create(E_EomOutputPtr eom_output, E_Comp_Wl_Buffer *wl_buffer)
-{
-   E_EomBuffer * eom_buffer = E_NEW(E_EomBuffer, 1);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(eom_buffer, NULL);
-
-   eom_buffer->wl_buffer = wl_buffer;
-
-   /* Forbid E sending 'wl_buffer_send_release' event to external clients */
-   e_comp_wl_buffer_reference(&eom_buffer->comp_wl_buffer_ref, wl_buffer);
-
-   /* double reference to avoid sigterm crash */
-   e_comp_wl_buffer_reference(&eom_buffer->comp_wl_buffer_ref_2, wl_buffer);
-
-   if (eom_trace_debug)
-     EOINF("E_EomBuffer:%p wl_buffer:%p busy:%d", eom_output->eout, eom_buffer, wl_buffer, wl_buffer->busy);
 
-   return eom_buffer;
-}
-
-static void
-_e_eom_buffer_destroy(E_EomOutputPtr eom_output, E_EomBuffer *eom_buffer)
+static Eina_Bool
+_e_eom_cb_comp_object_redirected(void *data, E_Client *ec)
 {
-   EINA_SAFETY_ON_NULL_RETURN(eom_buffer);
+   E_EomCompObjectInterceptHookData *hook_data;
 
-   if (eom_trace_debug)
-     EOINF("wl_buffer:%p busy:%d", eom_output->eout, eom_buffer->wl_buffer, eom_buffer->wl_buffer->busy);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_TRUE);
 
-   eom_buffer->wl_buffer = NULL;
+   hook_data = (E_EomCompObjectInterceptHookData* )data;
 
-   e_comp_wl_buffer_reference(&eom_buffer->comp_wl_buffer_ref, NULL);
+   if (!hook_data->ec || !hook_data->hook)
+     return EINA_TRUE;
 
-   /* double reference to avoid sigterm crash */
-   e_comp_wl_buffer_reference(&eom_buffer->comp_wl_buffer_ref_2, NULL);
+   if (hook_data->ec != ec)
+     return EINA_TRUE;
 
-   E_FREE(eom_buffer);
-}
+   /* Hide the window from Enlightenment main screen */
+   e_client_redirected_set(ec, EINA_FALSE);
 
-static inline eom_output_mode_e
-_e_eom_output_state_get_mode(E_EomOutputPtr eom_output)
-{
-   if (eom_output == NULL) return EOM_OUTPUT_MODE_NONE;
+   EOINF("Redirect ec:%p, ec->frame:%p", hook_data->eom_output->output, ec, ec->frame);
 
-   return eom_output->mode;
-}
+   e_comp_object_intercept_hook_del(hook_data->hook);
+   g_eom->comp_object_intercept_hooks = eina_list_remove(g_eom->comp_object_intercept_hooks, hook_data);
 
-static inline void
-_e_eom_output_state_set_mode(E_EomOutputPtr eom_output, eom_output_mode_e mode)
-{
-   if (eom_output == NULL) return;
+   free(hook_data);
 
-   eom_output->mode = mode;
+   return EINA_TRUE;
 }
 
 static inline eom_output_attribute_e
-_e_eom_output_state_get_attribute(E_EomOutputPtr eom_output)
+_e_eom_output_attribute_get(E_EomOutputPtr eom_output)
 {
    if (eom_output == NULL) return EOM_OUTPUT_ATTRIBUTE_NONE;
 
@@ -318,7 +156,7 @@ _e_eom_output_state_get_attribute(E_EomOutputPtr eom_output)
 }
 
 static inline void
-_e_eom_output_state_set_force_attribute(E_EomOutputPtr eom_output, eom_output_attribute_e attribute)
+_e_eom_output_attribute_force_set(E_EomOutputPtr eom_output, eom_output_attribute_e attribute)
 {
    if (eom_output == NULL) return;
 
@@ -326,7 +164,7 @@ _e_eom_output_state_set_force_attribute(E_EomOutputPtr eom_output, eom_output_at
 }
 
 static inline Eina_Bool
-_e_eom_output_state_set_attribute(E_EomOutputPtr eom_output, eom_output_attribute_e attribute)
+_e_eom_output_attribute_set(E_EomOutputPtr eom_output, eom_output_attribute_e attribute)
 {
    if (attribute == EOM_OUTPUT_ATTRIBUTE_NONE || eom_output->attribute == EOM_OUTPUT_ATTRIBUTE_NONE)
      {
@@ -343,11 +181,34 @@ _e_eom_output_state_set_attribute(E_EomOutputPtr eom_output, eom_output_attribut
    return EINA_FALSE;
 }
 
+static eom_output_mode_e
+_e_eom_output_mode_get(E_Output_Display_Mode display_mode)
+{
+   switch (display_mode)
+     {
+      case E_OUTPUT_DISPLAY_MODE_NONE:
+         return EOM_OUTPUT_MODE_NONE;
+      case E_OUTPUT_DISPLAY_MODE_MIRROR:
+         return EOM_OUTPUT_MODE_MIRROR;
+      case E_OUTPUT_DISPLAY_MODE_PRESENTATION:
+         return EOM_OUTPUT_MODE_PRESENTATION;
+      default:
+         break;
+     }
+
+   return EOM_OUTPUT_MODE_NONE;
+}
+
 static void
 _e_eom_output_info_broadcast(E_EomOutputPtr eom_output, eom_output_attribute_state_e attribute_state)
 {
    E_EomClientPtr eom_client = NULL;
    Eina_List *l = NULL;
+   int w, h, pw, ph;
+
+   /* get the output size */
+   e_output_size_get(eom_output->output, &w, &h);
+   e_output_phys_size_get(eom_output->output, &pw, &ph);
 
    /* If there were previously connected clients to the output - notify them */
    EINA_LIST_FOREACH(g_eom->clients, l, eom_client)
@@ -356,25 +217,27 @@ _e_eom_output_info_broadcast(E_EomOutputPtr eom_output, eom_output_attribute_sta
         if (!eom_client->resource) continue;
 
         if (attribute_state == EOM_OUTPUT_ATTRIBUTE_STATE_ACTIVE)
-          EOINF("Send output connected notification to client: %p", eom_output->eout, eom_client);
+          EOINF("Send output connected notification to client: %p", eom_output->output, eom_client);
         if (attribute_state == EOM_OUTPUT_ATTRIBUTE_STATE_INACTIVE)
-          EOINF("Send output disconnected notification to client: %p", eom_output->eout, eom_client);
-
-        if (eom_client->current)
-          wl_eom_send_output_info(eom_client->resource, eom_output->id,
-                                  eom_output->type, eom_output->mode,
-                                  eom_output->width, eom_output->height,
-                                  eom_output->phys_width, eom_output->phys_height,
+          EOINF("Send output disconnected notification to client: %p", eom_output->output, eom_client);
+
+        if (eom_client->ec == e_output_presentation_ec_get(eom_output->output))
+          wl_eom_send_output_info(eom_client->resource,
+                                  eom_output->id,
+                                  eom_output->type,
+                                  e_output_display_mode_get(eom_output->output),
+                                  w, h, pw, ph,
                                   eom_output->connection,
                                   0,
-                                  _e_eom_output_state_get_attribute(eom_output),
+                                  _e_eom_output_attribute_get(eom_output),
                                   attribute_state,
                                   EOM_ERROR_NONE);
         else
-          wl_eom_send_output_info(eom_client->resource, eom_output->id,
-                                  eom_output->type, eom_output->mode,
-                                  eom_output->width, eom_output->height,
-                                  eom_output->phys_width, eom_output->phys_height,
+          wl_eom_send_output_info(eom_client->resource,
+                                  eom_output->id,
+                                  eom_output->type,
+                                  e_output_display_mode_get(eom_output->output),
+                                  w, h, pw, ph,
                                   eom_output->connection,
                                   1, 0, 0, 0);
      }
@@ -385,6 +248,7 @@ _e_eom_output_status_broadcast(E_EomOutputPtr eom_output, E_EomClientPtr except_
 {
    E_EomClientPtr eom_client = NULL;
    Eina_List *l = NULL;
+   E_Output_Display_Mode display_mode;
 
    EINA_LIST_FOREACH(g_eom->clients, l, eom_client)
      {
@@ -393,1940 +257,646 @@ _e_eom_output_status_broadcast(E_EomOutputPtr eom_output, E_EomClientPtr except_
         if (eom_client == except_client) continue;
 
         wl_eom_send_output_attribute(eom_client->resource, eom_output->id,
-                                     _e_eom_output_state_get_attribute(eom_output),
+                                     _e_eom_output_attribute_get(eom_output),
                                      attribute_state,
                                      EOM_ERROR_NONE);
 
-        wl_eom_send_output_mode(eom_client->resource, eom_output->id,
-                                _e_eom_output_state_get_mode(eom_output));
+        display_mode = e_output_display_mode_get(eom_output->output);
+        wl_eom_send_output_mode(eom_client->resource, eom_output->id, _e_eom_output_mode_get(display_mode));
      }
 }
 
-static Eina_Bool
-_e_eom_output_video_layer_find(E_EomOutputPtr eom_output, tbm_format format)
+static E_EomOutputPtr
+_e_eom_output_find(E_Output *output)
 {
-   tdm_layer *layer = NULL;
-   tdm_layer *tmp_overlay_layer = NULL;
-   tdm_error err = TDM_ERROR_NONE;
-   tdm_layer_capability capa;
-   int i, count, format_count;
-   int primary_index = 0;
-   const tbm_format *formats;
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(eom_output, EINA_FALSE);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(eom_output->output, EINA_FALSE);
-
-   if (eom_output->overlay_layer)
-     {
-       if (eom_output->need_overlay_pp)
-         return EINA_FALSE;
-       else
-         return EINA_TRUE;
-     }
-
-   err = tdm_output_get_layer_count(eom_output->output, &count);
-   if (err != TDM_ERROR_NONE)
-     {
-        EOERR("tdm_output_get_layer_count fail(%d)", eom_output->eout, err);
-        return EINA_FALSE;
-     }
+   E_EomOutputPtr eom_output = NULL;
+   Eina_List *l;
 
-   for (i = 0; i < count; i++)
+   EINA_LIST_FOREACH(g_eom->eom_outputs, l, eom_output)
      {
-        layer = (tdm_layer *)tdm_output_get_layer(eom_output->output, i, &err);
-        EINA_SAFETY_ON_FALSE_RETURN_VAL(err == TDM_ERROR_NONE, EINA_FALSE);
-
-        err = tdm_layer_get_capabilities(layer, &capa);
-        EINA_SAFETY_ON_FALSE_RETURN_VAL(err == TDM_ERROR_NONE, EINA_FALSE);
-
-        if (capa & TDM_LAYER_CAPABILITY_PRIMARY)
-          {
-             primary_index = i + 1;
-             continue;
-          }
-
-        if (primary_index == i)
-          tmp_overlay_layer = layer;
-
-        if (capa & TDM_LAYER_CAPABILITY_VIDEO)
-          {
-             eom_output->overlay_layer = layer;
-             break;
-          }
+       if (eom_output->output == output)
+         return eom_output;
      }
 
-   if (eom_output->overlay_layer)
-     return EINA_TRUE;
+   return NULL;
+}
 
-   for (i = 0; i < count; i++)
-     {
-        layer = (tdm_layer *)tdm_output_get_layer(eom_output->output, i, &err);
-        EINA_SAFETY_ON_FALSE_RETURN_VAL(err == TDM_ERROR_NONE, EINA_FALSE);
+static Eina_Bool
+_e_eom_output_create(E_Output *output, Eina_Bool added)
+{
+   E_EomOutputPtr eom_output = NULL;
 
-        err = tdm_layer_get_capabilities(layer, &capa);
-        EINA_SAFETY_ON_FALSE_RETURN_VAL(err == TDM_ERROR_NONE, EINA_FALSE);
+   if (!g_eom) return EINA_TRUE;
 
-        if ((capa & TDM_LAYER_CAPABILITY_PRIMARY) || (capa & TDM_LAYER_CAPABILITY_CURSOR))
-          continue;
+   eom_output = E_NEW(E_EomOutput, 1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(eom_output, EINA_FALSE);
 
-        if (capa & TDM_LAYER_CAPABILITY_SCALE)
-          {
-             format_count = 0;
-             err = tdm_layer_get_available_formats(layer, &formats, &format_count);
-             EINA_SAFETY_ON_FALSE_RETURN_VAL(err == TDM_ERROR_NONE, EINA_FALSE);
+   eom_output->id = output->index;
+   eom_output->connection = WL_EOM_STATUS_NONE;
+   eom_output->output = output;
+   eom_output->type = (eom_output_type_e)output->toutput_type;
+   eom_output->added = added;
 
-             for (i = 0; i < count; i++)
-               {
-                  if (formats[i] == format)
-                    {
-                       eom_output->overlay_layer = layer;
-                       break;
-                    }
-               }
-          }
-     }
-   if (eom_output->overlay_layer)
-     return EINA_TRUE;
+   g_eom->eom_outputs = eina_list_append(g_eom->eom_outputs, eom_output);
 
-   eom_output->overlay_layer = tmp_overlay_layer;
+   EOINF("create (%d)output, type:%d, added:%d", eom_output->output,
+         eom_output->id, eom_output->type, eom_output->added);
 
-   return EINA_FALSE;
+   return EINA_TRUE;
 }
 
 static Eina_Bool
-_e_eom_pp_init(E_EomOutputPtr eom_output)
+_e_eom_output_destroy(E_Output *output)
 {
-   tdm_error err = TDM_ERROR_NONE;
-   E_EomOutputPpPtr eom_pp = NULL;
-   tdm_pp *pp = NULL;
-   tbm_surface_queue_h queue = NULL;
+   E_EomOutputPtr eom_output = NULL;
 
-   if (eom_output->pp_overlay != NULL)
-     return EINA_TRUE;
+   if (!g_eom) return EINA_TRUE;
 
-   eom_pp = E_NEW(E_EomOutputPp, 1);
-   if (!eom_pp)
-     return EINA_FALSE;
+   eom_output = _e_eom_output_find(output);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(eom_output, EINA_FALSE);
 
-   pp = tdm_display_create_pp(g_eom->dpy, &err);
-   EINA_SAFETY_ON_FALSE_GOTO(err == TDM_ERROR_NONE, error);
-   /* TODO: Add support for other formats */
-   queue = tbm_surface_queue_create(3, eom_output->width,eom_output->height,
-                                    TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
-   EINA_SAFETY_ON_NULL_GOTO(queue, error);
+   EOINF("destroy (%d)output, type:%d, added:%d", eom_output->output,
+         eom_output->id, eom_output->type, eom_output->added);
 
-   eom_pp->pp = pp;
-   eom_pp->queue = queue;
+   g_eom->eom_outputs = eina_list_remove(g_eom->eom_outputs, eom_output);
 
-   eom_output->pp_overlay = eom_pp;
+   E_FREE(eom_output);
 
    return EINA_TRUE;
+}
 
-error:
-   if (pp)
-     tdm_pp_destroy(pp);
+static E_EomOutputPtr
+_e_eom_output_get_by_id(int id)
+{
+   E_EomOutputPtr eom_output;
+   Eina_List *l;
 
-   if (eom_pp)
-     E_FREE(eom_pp);
+   EINA_LIST_FOREACH(g_eom->eom_outputs, l, eom_output)
+     {
+        if (eom_output && eom_output->id == id)
+          return eom_output;
+     }
 
-   return EINA_FALSE;
+   return NULL;
 }
 
-static void
-_e_eom_pp_deinit(E_EomOutputPtr eom_output)
+static E_EomOutputPtr
+_e_eom_output_by_ec_child_get(E_Client *ec)
 {
-   E_EomOutputPpPtr eom_pp = NULL;
+   E_EomOutputPtr eom_output = NULL;
+   E_Client *parent_ec = NULL, *output_ec = NULL;
+   Eina_List *l;
 
-   eom_pp = eom_output->pp_overlay;
+   EINA_LIST_FOREACH(g_eom->eom_outputs, l, eom_output)
+     {
+        output_ec = e_output_presentation_ec_get(eom_output->output);
+        if (!output_ec) continue;
 
-   if (!eom_pp)
-     return;
+        if (output_ec == ec) return eom_output;
 
-   if (eom_pp->queue)
-     {
-        if (eom_trace_debug)
-          EOINF("flush and destroy queue", eom_output->eout);
-        tbm_surface_queue_flush(eom_pp->queue);
-        tbm_surface_queue_destroy(eom_pp->queue);
-     }
+        if (!ec->comp_data) continue;
+        if (!ec->comp_data->sub.data) continue;
 
-   if (eom_pp->pp)
-     tdm_pp_destroy(eom_pp->pp);
+        parent_ec = ec->comp_data->sub.data->parent;
+        while (parent_ec)
+          {
+             if (parent_ec == output_ec) return eom_output;
+             if (!parent_ec->comp_data) break;
+             if (!parent_ec->comp_data->sub.data) break;
 
-   E_FREE(eom_pp);
+             parent_ec = parent_ec->comp_data->sub.data->parent;
+          }
+     }
 
-   eom_output->pp_overlay = NULL;
+   return NULL;
 }
 
 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)
+_e_eom_output_send_configure_event(E_EomOutput *eom_output, E_Client *ec)
 {
-   double h_ratio, v_ratio;
-
-   h_ratio = (double)src_h / (double)dst_size_h;
-   v_ratio = (double)src_v / (double)dst_size_v;
+   E_Comp_Client_Data *cdata = NULL;
+   E_EomCompObjectInterceptHookData *hook_data = NULL;
+   E_Comp_Object_Intercept_Hook *hook = NULL;
+   int w, h;
 
-   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;
-     }
-}
+   ec = e_output_presentation_ec_get(eom_output->output);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
 
-static void
-_e_eom_tbm_buffer_release_pp_overlay(E_EomOutputPtr eom_output, tbm_surface_h surface, void *eom_buff)
-{
-   if (eom_trace_debug)
-     EOINF("release pp_overlay tbm_surface_h:%p data:%p", eom_output->eout, surface, eom_buff);
+   cdata = ec->comp_data;
+   EINA_SAFETY_ON_NULL_RETURN(cdata);
+   EINA_SAFETY_ON_NULL_RETURN(cdata->shell.configure_send);
 
-   if (!eom_output->pp_overlay || !eom_output->pp_overlay->queue)
-     return;
+   hook_data = E_NEW(E_EomCompObjectInterceptHookData, 1);
+   EINA_SAFETY_ON_NULL_RETURN(hook_data);
 
-   tbm_surface_queue_release(eom_output->pp_overlay->queue, surface);
+   hook = e_comp_object_intercept_hook_add(E_COMP_OBJECT_INTERCEPT_HOOK_SHOW_HELPER,
+                                           _e_eom_cb_comp_object_redirected, hook_data);
+   EINA_SAFETY_ON_NULL_GOTO(hook, err);
 
-   _e_eom_buffer_destroy(eom_output, eom_buff);
-}
+   hook_data->ec = ec;
+   hook_data->eom_output = eom_output;
+   hook_data->hook = hook;
 
-static void
-_e_eom_cb_layer_commit(tdm_layer *layer EINA_UNUSED, unsigned int sequence EINA_UNUSED,
-                       unsigned int tv_sec EINA_UNUSED, unsigned int tv_usec EINA_UNUSED,
-                       void *user_data)
-{
-   E_EomOutputBufferPtr outbuff = NULL;
-   E_EomOutputPtr eom_output = NULL;
-   tdm_error err = TDM_ERROR_NONE;
-   E_EomOutputBufferPtr wait_buff;
-   E_EomOutputBufferPtr show_buff;
-   E_EomPpDataPtr pending_pp = NULL;
-   tdm_layer *tlayer;
-   tbm_surface_h tsurface;
-   E_EomBufferPtr eom_buffer;
+   g_eom->comp_object_intercept_hooks = eina_list_append(g_eom->comp_object_intercept_hooks, hook_data);
 
-   EINA_SAFETY_ON_NULL_RETURN(user_data);
-   outbuff = (E_EomOutputBufferPtr)user_data;
+   /* get the output size */
+   e_output_size_get(eom_output->output, &w, &h);
+   cdata->shell.configure_send(ec->comp_data->shell.surface, 0, w, h);
 
-   eom_output = outbuff->eom_output;
-   EINA_SAFETY_ON_NULL_RETURN(eom_output);
+   EOINF("Send Configure Event for Presentation (%d X %d)", eom_output->output, w, h);
+err:
+   if (hook_data)
+     free(hook_data);
+}
 
-   if (eom_trace_debug)
-     EOINF("========================>  CM  END     tbm_buff:%p", eom_output->eout, outbuff->tbm_surface);
+static E_EomClientPtr
+_e_eom_client_get_by_resource(struct wl_resource *resource)
+{
+   Eina_List *l;
+   E_EomClientPtr client;
 
-   /*it means that eom_output has been canceled*/
-   if (eom_output->wait_overlay_buff == NULL)
+   EINA_LIST_FOREACH(g_eom->clients, l, client)
      {
-        _e_eom_output_buff_delete(outbuff);
-        return;
+        if (client && client->resource == resource)
+          return client;
      }
-   wait_buff = eom_output->wait_overlay_buff;
-   show_buff = eom_output->show_overlay_buff;
-   tlayer = eom_output->overlay_layer;
 
-   EINA_SAFETY_ON_FALSE_RETURN(wait_buff == outbuff);
+   return NULL;
+}
 
-   if (eom_trace_debug)
-     EOINF("commit finish tbm_surface_h:%p", eom_output->eout, outbuff->tbm_surface);
+static E_EomClientPtr
+_e_eom_client_get_current_by_ec(E_Client *ec)
+{
+   Eina_List *l;
+   E_EomClientPtr client;
 
-   /* check if show buffer is present */
-   if (show_buff != NULL)
+   EINA_LIST_FOREACH(g_eom->clients, l, client)
      {
-        if (eom_trace_debug)
-          EOINF("delete show buffer tbm_surface_h:%p", eom_output->eout, show_buff->tbm_surface);
-        _e_eom_output_buff_delete(show_buff);
-        eom_output->show_overlay_buff = NULL;
+        if (client && client->current == EINA_TRUE && client->ec == ec)
+          return client;
      }
 
-   /* set wait_buffer as show_buff */
-   if (eom_trace_debug)
-     EOINF("set wait_buffer as show_buff tbm_surface_h:%p", eom_output->eout, outbuff->tbm_surface);
+   return NULL;
+}
+
+static E_EomClientPtr
+_e_eom_client_get_current_by_ec_parrent(E_Client *ec)
+{
+   Eina_List *l;
+   E_EomClientPtr client;
+   E_Client *parent = NULL;
 
-   eom_output->wait_overlay_buff = NULL;
-   eom_output->show_overlay_buff = outbuff;
+   if (!ec->comp_data || !ec->comp_data->sub.data)
+     return NULL;
 
-   /* check if pending buffer is present */
-   if (eina_list_count(eom_output->pending_overlay_buff) != 0)
+   EINA_LIST_FOREACH(g_eom->clients, l, client)
      {
-        outbuff = eina_list_nth(eom_output->pending_overlay_buff, 0);
-        if (outbuff != NULL)
+        parent = ec->comp_data->sub.data->parent;
+        while (parent)
           {
-             eom_output->pending_overlay_buff = eina_list_remove(eom_output->pending_overlay_buff, outbuff);
-
-             if (eom_trace_debug)
-               {
-                  EOINF("========================>  CM- START   tbm_buff:%p", eom_output->eout, outbuff->tbm_surface);
-                  EOINF("do commit tdm_output:%p tdm_layer:%p tbm_surface_h:%p", eom_output->eout,
-                        eom_output->output, tlayer, outbuff->tbm_surface);
-               }
-             err = tdm_layer_set_buffer(tlayer, outbuff->tbm_surface);
-             EINA_SAFETY_ON_FALSE_GOTO(err == TDM_ERROR_NONE, error);
+             if (client->ec == parent)
+               return client;
 
-             err = tdm_layer_commit(tlayer, _e_eom_cb_layer_commit, outbuff);
-             EINA_SAFETY_ON_FALSE_GOTO(err == TDM_ERROR_NONE, error2);
+             if (!parent->comp_data || !parent->comp_data->sub.data)
+               break;
 
-             eom_output->wait_overlay_buff = outbuff;
+             parent = parent->comp_data->sub.data->parent;
           }
      }
 
-   if (eina_list_count(eom_output->pending_pp_overlay) != 0)
-     {
-        pending_pp = eina_list_nth(eom_output->pending_pp_overlay, 0);
-        if (pending_pp != NULL)
-          {
-             if (!tbm_surface_queue_can_dequeue(eom_output->pp_overlay->queue, 0))
-               return;
-
-             eom_output->pending_pp_overlay = eina_list_remove(eom_output->pending_pp_overlay, pending_pp);
-
-             tsurface = pending_pp->tsurface;
-             eom_buffer = pending_pp->eom_buffer;
-
-             E_FREE(pending_pp);
-
-             _e_eom_presentation_pp_run(eom_output, tsurface, eom_buffer);
-          }
-     }
-
-   return;
-
-error2:
-   tdm_layer_unset_buffer(tlayer);
-
-error:
-   EOINF("========================>  CM- ENDERR  tbm_buff:%p", eom_output->eout, outbuff->tbm_surface);
-
-   _e_eom_output_buff_delete(outbuff);
+   return NULL;
 }
 
 static Eina_Bool
-_e_eom_output_show(E_EomOutputPtr eom_output, tbm_surface_h tbm_srfc,
-                   E_EomEndShowingEventPtr cb_func, void *cb_user_data)
+_e_eom_cb_client_buffer_change(void *data, int type, void *event)
 {
-   tdm_error err = TDM_ERROR_NONE;
-   tdm_layer *layer;
-
-   /* create new output buffer */
-   E_EomOutputBufferPtr outbuff = _e_eom_output_buff_create(eom_output, tbm_srfc, cb_func, cb_user_data);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(outbuff, EINA_FALSE);
+   E_EomClientPtr eom_client = NULL, eom_client_itr = NULL;
+   E_EomOutputPtr eom_output = NULL;
+   E_Event_Client *ev = event;
+   E_Client *ec = NULL;
+   E_Comp_Wl_Buffer *wl_buffer = NULL;
+   tbm_surface_h tbm_buffer = NULL;
+   Eina_List *l;
+   E_Output_Display_Mode display_mode;
+   int width, height;
 
-   /* check if output free to commit */
-   if (eina_list_count(eom_output->pending_overlay_buff) != 0)
-     {
-        eom_output->pending_overlay_buff = eina_list_append(eom_output->pending_overlay_buff, outbuff);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ev->ec, ECORE_CALLBACK_PASS_ON);
 
-        if (eom_trace_debug)
-          EOINF("add to pending list tdm_output:%p tdm_layer:%p tbm_surface_h:%p", eom_output->eout,
-                eom_output->output, eom_output->overlay_layer, outbuff->tbm_surface);
+   ec = ev->ec;
+   EINA_SAFETY_ON_TRUE_RETURN_VAL(e_object_is_del(E_OBJECT(ec)), ECORE_CALLBACK_PASS_ON);
 
-        return EINA_TRUE;
-     }
-   else
+   eom_client = _e_eom_client_get_current_by_ec(ec);
+   if (eom_client == NULL)
      {
-        layer = eom_output->overlay_layer;
+        eom_client = _e_eom_client_get_current_by_ec_parrent(ec);
+        if (eom_client == NULL)
+          return ECORE_CALLBACK_PASS_ON;
      }
 
-   if (eom_trace_debug)
-     {
-        EOINF("========================>  CM  START   tbm_buff:%p", eom_output->eout, tbm_srfc);
-        EOINF("do commit tdm_output:%p tdm_layer:%p tbm_surface_h:%p", eom_output->eout,
-              eom_output->output, layer, outbuff->tbm_surface);
-     }
-   err = tdm_layer_set_buffer(layer, outbuff->tbm_surface);
-   EINA_SAFETY_ON_FALSE_GOTO(err == TDM_ERROR_NONE, error);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ec->pixmap, ECORE_CALLBACK_PASS_ON);
 
-   err = tdm_layer_commit(layer, _e_eom_cb_layer_commit, outbuff);
-   EINA_SAFETY_ON_FALSE_GOTO(err == TDM_ERROR_NONE, error2);
+   wl_buffer = e_pixmap_resource_get(ec->pixmap);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(wl_buffer, ECORE_CALLBACK_PASS_ON);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(wl_buffer->resource, ECORE_CALLBACK_PASS_ON);
 
-   eom_output->wait_overlay_buff = outbuff;
+   /* TODO: support different SHMEM buffers etc. */
+   tbm_buffer = wayland_tbm_server_get_surface(e_comp->wl_comp_data->tbm.server, wl_buffer->resource);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(tbm_buffer, ECORE_CALLBACK_PASS_ON);
 
-   return EINA_TRUE;
+   width = tbm_surface_get_width(tbm_buffer);
+   height = tbm_surface_get_height(tbm_buffer);
 
-error2:
-   tdm_layer_unset_buffer(layer);
+   if ((width <= 1) || (height <= 1)) return ECORE_CALLBACK_PASS_ON;
 
-error:
-   if (outbuff)
-     _e_eom_output_buff_delete(outbuff);
+   eom_output = _e_eom_output_get_by_id(eom_client->output_id);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(eom_output, ECORE_CALLBACK_PASS_ON);
 
    if (eom_trace_debug)
-     EOINF("========================>  CM  ENDERR  tbm_buff:%p", eom_output->eout, tbm_srfc);
-
-   return EINA_FALSE;
-}
+     EOINF("===============>  EXT START", eom_output->output);
 
-static unsigned int
-_e_eom_aligned_width_get(E_EomOutputPtr eom_output, tbm_surface_info_s *surf_info)
-{
-   unsigned int aligned_width = 0;
-
-   switch (surf_info->format)
+   /* TODO: It works but maybe there is better solution exists ?
+    * Also I do not know how it affects on performance */
+   if (ec->map_timer)
      {
-      case TBM_FORMAT_YUV420:
-      case TBM_FORMAT_YVU420:
-      case TBM_FORMAT_YUV422:
-      case TBM_FORMAT_YVU422:
-      case TBM_FORMAT_NV12:
-      case TBM_FORMAT_NV21:
-        aligned_width = surf_info->planes[0].stride;
-        break;
-      case TBM_FORMAT_YUYV:
-      case TBM_FORMAT_UYVY:
-        aligned_width = surf_info->planes[0].stride >> 1;
-        break;
-      case TBM_FORMAT_ARGB8888:
-      case TBM_FORMAT_XRGB8888:
-        aligned_width = surf_info->planes[0].stride >> 2;
-        break;
-      default:
-        EOERR("not supported format: %x", eom_output->eout, surf_info->format);
+        if (eom_trace_debug)
+          EOINF("delete map_timer", eom_output->output);
+        E_FREE_FUNC(ec->map_timer, ecore_timer_del);
      }
 
-   return aligned_width;
-}
-
-static Eina_Bool
-_e_eom_pp_info_set(E_EomOutputPtr eom_output, tbm_surface_h src, tbm_surface_h dst)
-{
-   tdm_error err = TDM_ERROR_NONE;
-   tdm_info_pp pp_info;
-   int x = 0, y = 0, w = 0, h = 0;
-   int width = 0, height = 0;
-   tbm_surface_info_s src_info;
-   tbm_surface_info_s dst_info;
-   unsigned int src_aligned_w;
-   unsigned int dst_aligned_w;
-
-   memset(&pp_info, 0, sizeof(tdm_info_pp));
-
-   tbm_surface_get_info(src, &src_info);
-   tbm_surface_get_info(dst, &dst_info);
-   src_aligned_w = _e_eom_aligned_width_get(eom_output, &src_info);
-   dst_aligned_w = _e_eom_aligned_width_get(eom_output, &dst_info);
-
-   width = src_aligned_w;
-   height = src_info.height;
-
-   _e_eom_util_calculate_fullsize(width, height, eom_output->width, eom_output->height,
-                                  &x, &y, &w, &h);
-
    if (eom_trace_debug)
-     {
-        EOINF("PP prentation: src:%dx%d, dst:%dx%d", eom_output->eout, src_info.width, src_info.height, dst_info.width, dst_info.height);
-        EOINF("PP prentation calculation: x:%d, y:%d, w:%d, h:%d", eom_output->eout, x, y, w, h);
-     }
-
-   pp_info.src_config.size.h = src_aligned_w;
-   pp_info.src_config.size.v = src_info.height;
-   pp_info.src_config.pos.x = 0;
-   pp_info.src_config.pos.y = 0;
-   pp_info.src_config.pos.w = src_info.width;
-   pp_info.src_config.pos.h = src_info.height;
-   pp_info.src_config.format = src_info.format;
-
-   pp_info.dst_config.size.h = dst_aligned_w;
-   pp_info.dst_config.size.v = dst_info.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 = dst_info.format;
-
-   pp_info.transform = TDM_TRANSFORM_NORMAL;
-
-   pp_info.sync = 0;
-   pp_info.flags = 0;
-
-   if (memcmp(&eom_output->pp_overlay->pp_info, &pp_info, sizeof(tdm_info_layer)))
-     {
-        err = tdm_pp_set_info(eom_output->pp_overlay->pp, &pp_info);
-        EINA_SAFETY_ON_FALSE_RETURN_VAL(err == TDM_ERROR_NONE, EINA_FALSE);
-        memcpy(&eom_output->pp_overlay->pp_info, &pp_info, sizeof(tdm_info_layer));
-     }
-
-   return EINA_TRUE;
-}
-
-static void
-_e_eom_layer_overlay_set(E_EomOutputPtr eom_output, tbm_surface_h tsurface)
-{
-   tdm_info_layer layer_info, old_info;
-   tdm_error err = TDM_ERROR_NONE;
-   tbm_surface_info_s dst_info;
-   unsigned int width;
-
-   CLEAR(old_info);
-   err = tdm_layer_get_info(eom_output->overlay_layer, &old_info);
-   EINA_SAFETY_ON_FALSE_RETURN(err == TDM_ERROR_NONE);
-
-   tbm_surface_get_info(tsurface, &dst_info);
-   width = _e_eom_aligned_width_get(eom_output, &dst_info);
-
-   memset(&layer_info, 0x0, sizeof(tdm_info_layer));
-   layer_info.src_config.size.h = width;
-   layer_info.src_config.size.v = dst_info.height;
-   layer_info.src_config.pos.x = 0;
-   layer_info.src_config.pos.y = 0;
-   layer_info.src_config.pos.w = dst_info.width;
-   layer_info.src_config.pos.h = dst_info.height;
-   layer_info.src_config.format = dst_info.format;
-   layer_info.dst_pos.x = 0;
-   layer_info.dst_pos.y = 0;
-   layer_info.dst_pos.w = eom_output->width;
-   layer_info.dst_pos.h = eom_output->height;
-   layer_info.transform = TDM_TRANSFORM_NORMAL;
-
-   if (memcmp(&old_info, &layer_info, sizeof(tdm_info_layer)))
-     {
-        err = tdm_layer_set_info(eom_output->overlay_layer, &layer_info);
-        EINA_SAFETY_ON_FALSE_RETURN(err == TDM_ERROR_NONE);
-     }
-}
-
-static void
-_e_eom_cb_pp_presentation(E_EomOutputPtr eom_output, E_EomPpDataPtr ppdata, E_EomOutputPpPtr eom_pp)
-{
-   E_EomBufferPtr eom_buff;
-   tbm_surface_h tsurface;
-
-   eom_buff = ppdata->eom_buffer;
-   tsurface = ppdata->tsurface;
-
-   E_FREE(ppdata);
-
-   if (!eom_output)
-     {
-        tbm_surface_queue_release(eom_pp->queue, tsurface);
-        return;
-     }
-
-   if (!e_output_connected(g_eom->output_primary))
-     {
-        tbm_surface_queue_release(eom_pp->queue, tsurface);
-        return;
-     }
+     EOINF("buffer_changed callback ec:%p", eom_output->output, ec);
 
-   if (eom_output->state == MIRROR)
+   /* set the ec to the output for presentation. */
+   if (!e_output_presentation_update(eom_output->output, eom_client->ec))
      {
-        tbm_surface_queue_release(eom_pp->queue, tsurface);
-        return;
+        EOERR("e_output_presentation_update fails.", eom_output->output);
+        return ECORE_CALLBACK_PASS_ON;
      }
 
-#ifdef EOM_DUMP_PRESENTATION_BUFFERS
-   char file[256];
-   static int i;
-   snprintf(file, sizeof file, "%s_%d", "eom_external", i++);
-   tbm_surface_internal_dump_buffer(tsurface, file, i++, 0);
-#endif
-
-   _e_eom_layer_overlay_set(eom_output, tsurface);
-
-   if (!_e_eom_output_show(eom_output, tsurface, _e_eom_tbm_buffer_release_pp_overlay, eom_buff))
+   EINA_LIST_FOREACH(g_eom->clients, l, eom_client_itr)
      {
-        EOERR("pp show fail", eom_output->eout);
-        tbm_surface_queue_release(eom_output->pp_overlay->queue, tsurface);
+        if (eom_client_itr->output_id == eom_output->id)
+          {
+             display_mode = e_output_display_mode_get(eom_output->output);
+             wl_eom_send_output_mode(eom_client->resource, eom_output->id, _e_eom_output_mode_get(display_mode));
+          }
      }
 
    if (eom_trace_debug)
-     EOINF("==============================<  presentation PP", eom_output->eout);
-}
-
-static E_EomPpDataPtr
-_e_eom_pp_data_get(E_EomOutputPtr eom_output, tbm_surface_h tsurface)
-{
-   Eina_List *l;
-   E_EomPpDataPtr ppdata = NULL;
-
-   EINA_LIST_FOREACH(eom_output->pp_overlay_data, l, ppdata)
-     {
-        if (!ppdata) continue;
-
-        if (ppdata->tsurface == tsurface)
-          return ppdata;
-     }
+     EOINF("===============<  EXT START", eom_output->output);
 
-   return NULL;
+   return ECORE_CALLBACK_PASS_ON;
 }
 
 static void
-_e_eom_cb_pp_presentation_overlay(tdm_pp *pp, tbm_surface_h tsurface_src, tbm_surface_h tsurface_dst, void *user_data)
+_e_eom_cb_wl_request_set_attribute(struct wl_client *client, struct wl_resource *resource, uint32_t output_id, uint32_t attribute)
 {
+   E_EomClientPtr eom_client = NULL;
    E_EomOutputPtr eom_output = NULL;
-   E_EomPpDataPtr ppdata = NULL;
-
-   EINA_SAFETY_ON_NULL_RETURN(user_data);
-   eom_output = (E_EomOutputPtr)user_data;
+   E_Output *primary_output = NULL;
 
-   ppdata = _e_eom_pp_data_get(eom_output, tsurface_src);
-   EINA_SAFETY_ON_NULL_RETURN(ppdata);
-
-   eom_output->pp_overlay_data = eina_list_remove(eom_output->pp_overlay_data, ppdata);
-
-   tbm_surface_internal_unref(tsurface_src);
-   tbm_surface_internal_unref(tsurface_dst);
+   eom_client = _e_eom_client_get_by_resource(resource);
+   EINA_SAFETY_ON_NULL_RETURN(eom_client);
 
-   eom_output->pp_overlay_converting = EINA_FALSE;
+   eom_output = _e_eom_output_get_by_id(output_id);
+   EINA_SAFETY_ON_NULL_GOTO(eom_output, no_eom_output);
 
-   if (eom_output->pp_overlay_deinit)
-     {
-        eom_output->pp_overlay_deinit = EINA_FALSE;
-        _e_eom_pp_deinit(eom_output);
-     }
+   EOINF("Set attribute:%d, client:%p", eom_output->output, attribute, eom_client);
 
-   if (eom_trace_debug)
-     EOINF("==============================>  presentation PP  END  overlay   tbm_buff:%p  ppdata:%p", eom_output->eout, tsurface_dst, ppdata);
+   /* Bind the client with a concrete output */
+   eom_client->output_id = output_id;
 
-   if (eom_output->pp_overlay == NULL)
+   /* Set the attribute to the eom_client */
+   if (eom_output->eom_client)
      {
-        E_FREE(ppdata);
-        return;
-     }
-
-   ppdata->tsurface = tsurface_dst;
-
-   _e_eom_cb_pp_presentation(eom_output, ppdata, eom_output->pp_overlay);
-}
-
-static void
-_e_eom_presentation_pp_run(E_EomOutputPtr eom_output, tbm_surface_h src_surface, E_EomBufferPtr eom_buff)
-{
-   tdm_error tdm_err = TDM_ERROR_NONE;
-   tbm_surface_h dst_surface = NULL;
-   Eina_Bool ret = EINA_FALSE;
-   E_EomOutputPpPtr eom_pp = NULL;
-   E_EomPpDataPtr ppdata = NULL;
-
-   if (!e_output_connected(g_eom->output_primary))
-     return;
+        // if eom_ouitput->eom_client == eom_client
+        if (eom_output->eom_client == eom_client)
+          {
+             /* Current client can set any flag it wants */
+             _e_eom_output_attribute_force_set(eom_output, attribute);
+
+             if (attribute == EOM_OUTPUT_ATTRIBUTE_NONE)
+               wl_eom_send_output_attribute(eom_client->resource, eom_output->id,
+                                            _e_eom_output_attribute_get(eom_output),
+                                            EOM_OUTPUT_ATTRIBUTE_STATE_LOST,
+                                            EOM_ERROR_NONE);
+          }
+        else
+          {
+             /* A client is trying to set new attribute */
+             if (!_e_eom_output_attribute_set(eom_output, attribute))
+               {
+                  EOINF("client failed to set attribute", eom_output->output);
+                  wl_eom_send_output_attribute(eom_client->resource, eom_output->id,
+                                               _e_eom_output_attribute_get(eom_output),
+                                               EOM_OUTPUT_ATTRIBUTE_STATE_LOST,
+                                               EOM_ERROR_INVALID_PARAMETER);
+                  return;
+               }
 
-   eom_pp = eom_output->pp_overlay;
+             EOINF("Send changes to previous current client", eom_output->output);
+             /* eom_output->eom_client is lost the attribute */
+             wl_eom_send_output_attribute(eom_output->eom_client->resource, eom_output->id,
+                                          _e_eom_output_attribute_get(eom_output),
+                                          EOM_OUTPUT_ATTRIBUTE_STATE_LOST,
+                                          EOM_ERROR_NONE);
 
-   if (!eom_pp || !eom_pp->pp || !eom_pp->queue)
-     {
-        EOERR("no pp data", eom_output->eout);
-        _e_eom_buffer_destroy(eom_output, eom_buff);
-        return;
+             eom_output->eom_client->current = EINA_FALSE;
+             eom_output->eom_client = NULL;
+          }
      }
-
-   ppdata = E_NEW(E_EomPpData, 1);
-   if (!ppdata)
+   else
      {
-        EOERR("make pp data fail", eom_output->eout);
-        _e_eom_buffer_destroy(eom_output, eom_buff);
-        return;
+        /* Current client can set any flag it wants */
+        _e_eom_output_attribute_force_set(eom_output, attribute);
      }
-   ppdata->eom_output = eom_output;
-   ppdata->eom_buffer = eom_buff;
-   ppdata->tsurface = src_surface;
 
-   if (!tbm_surface_queue_can_dequeue(eom_pp->queue, 0))
+   /* set the output display_mode */
+   if (_e_eom_output_attribute_get(eom_output) == EOM_OUTPUT_ATTRIBUTE_NONE)
      {
-        if (eom_trace_debug)
-          EOINF("all pp buffers are busy, wait release queue(%p)", eom_output->eout, eom_pp->queue);
+        if (e_output_presentation_ec_get(eom_output->output) == eom_client->ec)
+          e_output_presentation_unset(eom_output->output);
 
-        eom_output->pending_pp_overlay = eina_list_append(eom_output->pending_pp_overlay, ppdata);
+        primary_output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
+        if (!e_output_mirror_set(eom_output->output, primary_output))
+          {
+             EOERR("e_output_mirror_set fails", eom_output->output);
+             goto no_eom_output;
+          }
 
+        /* broadcast the status */
+        _e_eom_output_status_broadcast(eom_output, NULL, EOM_OUTPUT_ATTRIBUTE_STATE_NONE);
         return;
      }
-
-   tdm_err = tbm_surface_queue_dequeue(eom_pp->queue, &dst_surface);
-   EINA_SAFETY_ON_FALSE_GOTO(tdm_err == TDM_ERROR_NONE, error);
-
-   if (eom_trace_debug)
-     EOINF("============================>  presentation PP  START   tbm_buff:%p ppdata:%p", eom_output->eout, dst_surface, ppdata);
-
-   ret = _e_eom_pp_info_set(eom_output, src_surface, dst_surface);
-   EINA_SAFETY_ON_FALSE_GOTO(ret == EINA_TRUE, error);
-
-   eom_output->pp_overlay_data = eina_list_append(eom_output->pp_overlay_data, ppdata);
-
-   tdm_err = tdm_pp_set_done_handler(eom_pp->pp, _e_eom_cb_pp_presentation_overlay, eom_output);
-   EINA_SAFETY_ON_FALSE_GOTO(tdm_err == TDM_ERROR_NONE, error);
-
-   tbm_surface_internal_ref(src_surface);
-   tbm_surface_internal_ref(dst_surface);
-
-   tdm_err = tdm_pp_attach(eom_pp->pp, src_surface, dst_surface);
-   EINA_SAFETY_ON_FALSE_GOTO(tdm_err == TDM_ERROR_NONE, attach_fail);
-
-   eom_output->pp_overlay_converting = EINA_TRUE;
-
-   tdm_err = tdm_pp_commit(eom_pp->pp);
-   EINA_SAFETY_ON_FALSE_GOTO(tdm_err == TDM_ERROR_NONE, commit_fail);
-
-   if (eom_trace_debug)
+   else
      {
-        EOINF("do presentation pp commit tdm_output:%p tbm_surface_h(src:%p dst:%p)", eom_output->eout,
-              eom_output->output, src_surface, dst_surface);
-        EOERR("============================<  presentation PP  done   tbm_buff:%p", eom_output->eout, dst_surface);
-     }
-
-   return;
-
-commit_fail:
-   eom_output->pp_overlay_converting = EINA_FALSE;
-
-attach_fail:
-   tbm_surface_internal_unref(dst_surface);
-   tbm_surface_internal_unref(src_surface);
+        /* Set the client as current client of the eom_output */
+        eom_client->current = EINA_TRUE;
+        eom_output->eom_client = eom_client;
 
-error:
-   EOERR("failed run pp tdm error: %d", eom_output->eout, tdm_err);
-
-   eom_output->pp_overlay_data = eina_list_remove(eom_output->pp_overlay_data, ppdata);
+        if (e_output_presentation_wait_set(eom_output->output, eom_client->ec))
+          {
+             EOERR("e_output_presentation_wait_set fails\n", NULL);
+             return;
+          }
 
-   if (dst_surface)
-     {
-        if (eom_trace_debug)
-          EOINF("============================>  presentation PP  ENDERR  tbm_buff:%p", eom_output->eout, dst_surface);
-        tbm_surface_queue_release(eom_pp->queue, dst_surface);
+        /* Send changes to the caller-client */
+        wl_eom_send_output_attribute(eom_client->resource, eom_output->id,
+                                     _e_eom_output_attribute_get(eom_output),
+                                     EOM_OUTPUT_ATTRIBUTE_STATE_NONE,
+                                     EOM_ERROR_NONE);
      }
 
-   _e_eom_buffer_destroy(eom_output, eom_buff);
-
-   E_FREE(ppdata);
-}
+   return;
 
-static E_EomClientPtr
-_e_eom_client_get_current_by_id(int id)
-{
-   Eina_List *l;
-   E_EomClientPtr client;
+no_eom_output:
+   /* Get here if EOM does not have output referred by output_id */
+   wl_eom_send_output_attribute(eom_client->resource, output_id,
+                                EOM_OUTPUT_ATTRIBUTE_NONE,
+                                EOM_OUTPUT_ATTRIBUTE_STATE_NONE,
+                                EOM_ERROR_NO_SUCH_DEVICE);
 
-   EINA_LIST_FOREACH(g_eom->clients, l, client)
-     {
-        if (client &&
-            client->current == EINA_TRUE &&
-            client->output_id == id)
-          return client;
-     }
+   wl_eom_send_output_mode(eom_client->resource, output_id, EOM_OUTPUT_MODE_NONE);
 
-   return NULL;
+   wl_eom_send_output_type(eom_client->resource, output_id,
+                           EOM_OUTPUT_ATTRIBUTE_STATE_NONE,
+                           TDM_OUTPUT_CONN_STATUS_DISCONNECTED);
 }
 
 static void
-_e_eom_output_overlay_buff_release(E_EomOutputPtr eom_output)
+_e_eom_cb_wl_request_set_shell_window(struct wl_client *client, struct wl_resource *resource, uint32_t output_id, struct wl_resource *surface)
 {
-   Eina_List *l, *ll;
-   E_EomOutputBufferPtr buff = NULL;
-   E_EomPpDataPtr ppdata = NULL;
+   E_EomOutputPtr eom_output = NULL;
+   E_EomClientPtr eom_client = NULL;
+   E_Client *ec = NULL;
 
-   EINA_LIST_FOREACH_SAFE(eom_output->pending_overlay_buff, l, ll, buff)
+   if (!(ec = wl_resource_get_user_data(surface)))
      {
-        if (eom_trace_debug)
-          EOINF("delete pending overlay tbm_buff:%p", eom_output->eout, buff->tbm_surface);
-        eom_output->pending_overlay_buff = eina_list_remove_list(eom_output->pending_overlay_buff, l);
-        _e_eom_output_buff_delete(buff);
+        wl_resource_post_error(surface, WL_DISPLAY_ERROR_INVALID_OBJECT, "No Client For Shell Surface");
+        return;
      }
-   eina_list_free(eom_output->pending_overlay_buff);
-   eom_output->wait_overlay_buff = NULL;
 
-   if (eom_trace_debug)
-     EOINF("delete show overlay tbm_buff:%p", eom_output->eout, eom_output->show_overlay_buff ? eom_output->show_overlay_buff->tbm_surface : NULL);
-   _e_eom_output_buff_delete(eom_output->show_overlay_buff);
-   eom_output->show_overlay_buff = NULL;
+   EOINF("set shell output id:%d resource:%p surface:%p", NULL, output_id, resource, surface);
 
-   EINA_LIST_FOREACH_SAFE(eom_output->pending_pp_overlay, l, ll, ppdata)
-     {
-        if (eom_trace_debug)
-          EOINF("delete pending overlay pp data:%p", eom_output->eout, ppdata);
-        eom_output->pending_pp_overlay = eina_list_remove_list(eom_output->pending_pp_overlay, l);
-        _e_eom_buffer_destroy(eom_output, ppdata->eom_buffer);
-        E_FREE(ppdata);
-     }
-   eina_list_free(eom_output->pending_pp_overlay);
-   eom_output->pending_pp_overlay = NULL;
-}
+   eom_client = _e_eom_client_get_by_resource(resource);
+   EINA_SAFETY_ON_NULL_RETURN(eom_client);
 
-static E_EomOutputPtr
-_e_eom_output_find(E_Output *output)
-{
-   E_EomOutputPtr eom_output = NULL, eom_output_tmp = NULL;
-   Eina_List *l;
+   /* ec is used in buffer_change callback for distinguishing external ec and its buffers */
+   eom_client->ec = ec;
 
-   EINA_LIST_FOREACH(g_eom->eom_outputs, l, eom_output_tmp)
+   eom_output = _e_eom_output_get_by_id(output_id);
+   if (eom_output == NULL)
      {
-       if (eom_output_tmp->output == output->toutput)
-         eom_output = eom_output_tmp;
+        wl_eom_send_output_set_window(resource, output_id, WL_EOM_ERROR_NO_OUTPUT);
+        EOERR("no eom_output error\n", NULL);
+        return;
      }
 
-   return eom_output;
-}
-
-static E_EomOutputPtr
-_e_eom_output_find_added_output(E_Output *output)
-{
-   E_EomOutputPtr eom_output = NULL, eom_output_tmp = NULL;
-   Eina_List *l;
-
-   EINA_LIST_FOREACH(g_eom->added_outputs, l, eom_output_tmp)
+   if (ec == e_output_presentation_ec_get(eom_output->output))
      {
-        if (eom_output_tmp->output == output->toutput)
-          eom_output = eom_output_tmp;
+        wl_eom_send_output_set_window(resource, output_id, WL_EOM_ERROR_OUTPUT_OCCUPIED);
+        return;
      }
 
-   return eom_output;
+   _e_eom_output_send_configure_event(eom_output, ec);
+
+   wl_eom_send_output_set_window(resource, output_id, WL_EOM_ERROR_NONE);
 }
 
-static Eina_Bool
-_e_eom_create(E_Output *output, Eina_Bool added)
+static void
+_e_eom_cb_wl_request_get_output_info(struct wl_client *client, struct wl_resource *resource, uint32_t output_id)
 {
    E_EomOutputPtr eom_output = NULL;
+   int w, h, pw, ph;
 
-   if (!g_eom) return EINA_TRUE;
-
-   eom_output = E_NEW(E_EomOutput, 1);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(eom_output, EINA_FALSE);
-
-   eom_output->id = output->index;
-   eom_output->mode = EOM_OUTPUT_MODE_NONE;
-   eom_output->connection = WL_EOM_STATUS_NONE;
-   eom_output->eout = output;
-   EINA_SAFETY_ON_NULL_GOTO(eom_output->eout, err);
+   EOINF("get output info:%d", NULL, output_id);
 
-   eom_output->output = output->toutput;
-   eom_output->type = (eom_output_type_e)output->toutput_type;
+   eom_output = _e_eom_output_get_by_id(output_id);
+   EINA_SAFETY_ON_FALSE_RETURN(eom_output);
 
-   eom_output->connection_status = EINA_FALSE;
-   eom_output->width = 0;
-   eom_output->height = 0;
-   eom_output->phys_width = 0;
-   eom_output->phys_height = 0;
-   eom_output->added = added;
-
-   if (eom_output->added)
-     g_eom->added_outputs = eina_list_append(g_eom->added_outputs, eom_output);
-   else
-     g_eom->eom_outputs = eina_list_append(g_eom->eom_outputs, eom_output);
-
-   EOINF("create (%d)output, type:%d, name:%s added:%d", eom_output->eout,
-         eom_output->id, eom_output->type, eom_output->name, eom_output->added);
-
-   return EINA_TRUE;
-
-err:
-   E_FREE(eom_output);
-
-   return EINA_FALSE;
-}
-
-static Eina_Bool
-_e_eom_destroy(E_Output *output)
-{
-   E_EomOutputPtr eom_output = NULL;
-
-   if (!g_eom) return EINA_TRUE;
-
-   eom_output = _e_eom_output_find_added_output(output);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(eom_output, EINA_FALSE);
-
-   EOINF("destroy (%d)output, type:%d, name:%s added:%d", eom_output->eout,
-         eom_output->id, eom_output->type, eom_output->name, eom_output->added);
-
-   if (eom_output->added)
-     g_eom->added_outputs = eina_list_remove(g_eom->added_outputs, eom_output);
-   else
-     g_eom->eom_outputs = eina_list_remove(g_eom->eom_outputs, eom_output);
-
-   E_FREE(eom_output);
-
-   return EINA_TRUE;
-}
-
-static void
-_e_eom_output_deinit(void)
-{
-   E_EomOutputPtr eom_output;
-   Eina_List *l;
-
-   if (!g_eom) return;
-   if (!g_eom->eom_outputs) return;
-
-   EINA_LIST_FOREACH(g_eom->added_outputs, l, eom_output)
-     _e_eom_destroy(eom_output->eout);
-
-   eina_list_free(g_eom->eom_outputs);
-   g_eom->added_outputs = NULL;
-
-   EINA_LIST_FOREACH(g_eom->eom_outputs, l, eom_output)
-     _e_eom_destroy(eom_output->eout);
-
-   eina_list_free(g_eom->eom_outputs);
-   g_eom->eom_outputs = NULL;
-}
-
-static Eina_Bool
-_e_eom_output_init(void)
-{
-   E_Comp_Screen *e_comp_screen = NULL;
-   E_Output *output = NULL;
-   Eina_List *l;
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, EINA_FALSE);
-
-   e_comp_screen = e_comp->e_comp_screen;
-   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, EINA_FALSE);
-
-   g_eom->eom_output_count = e_comp_screen->num_outputs - 1;
-   EOINF("external output count : %d", NULL, g_eom->eom_output_count);
-
-   /* create the eom_output except for the primary output */
-   EINA_LIST_FOREACH(e_comp_screen->outputs, l, output)
-     {
-        if (!output) continue;
-        if (output == g_eom->output_primary) continue;
-
-        if (!_e_eom_create(output, EINA_FALSE))
-          {
-             EOERR("_e_eom_create fails.", output);
-             goto err;
-          }
-     }
-
-   return EINA_TRUE;
-
-err:
-   _e_eom_output_deinit();
-
-   return EINA_FALSE;
-}
-
-static Eina_Bool
-_e_eom_boot_connection_check(void *data)
-{
-   E_EomOutputPtr eom_output;
-   E_Output *eout = NULL;
-   Eina_List *l;
-
-   if (g_eom->check_first_boot != 0)
-     {
-        g_eom->timer = NULL;
-        return ECORE_CALLBACK_CANCEL;
-     }
-
-   g_eom->check_first_boot = 1;
-
-   EINA_LIST_FOREACH(g_eom->eom_outputs, l, eom_output)
-     {
-        if (eom_output->id == 0)
-          continue;
-
-        eout = eom_output->eout;
-
-        if (!e_output_connected(eout)) continue;
-
-        e_output_external_update(eout);
-     }
-
-   g_eom->timer = NULL;
-
-   return ECORE_CALLBACK_CANCEL;
-}
-
-static Eina_Bool
-_e_eom_presentation_check(void *data)
-{
-   E_EomOutputPtr eom_output = NULL;
-
-   if (!data) return ECORE_CALLBACK_CANCEL;
-
-   eom_output = (E_EomOutputPtr)data;
-
-   eom_output->delay_timer = NULL;
-
-   if (eom_output->state == WAIT_PRESENTATION)
-     e_output_external_set(eom_output->eout, E_OUTPUT_DISPLAY_MODE_MIRROR);
-
-   return ECORE_CALLBACK_CANCEL;
-}
-
-static E_EomClientPtr
-_e_eom_client_get_by_resource(struct wl_resource *resource)
-{
-   Eina_List *l;
-   E_EomClientPtr client;
-
-   EINA_LIST_FOREACH(g_eom->clients, l, client)
-     {
-        if (client && client->resource == resource)
-          return client;
-     }
-
-   return NULL;
-}
-
-static E_EomOutputPtr
-_e_eom_output_get_by_id(int id)
-{
-   E_EomOutputPtr eom_output;
-   Eina_List *l;
-
-   EINA_LIST_FOREACH(g_eom->eom_outputs, l, eom_output)
-     {
-        if (eom_output && eom_output->id == id)
-          return eom_output;
-     }
-
-   return NULL;
-}
-
-static E_EomOutputPtr
-_e_eom_output_by_ec_child_get(E_Client *ec)
-{
-   E_EomOutputPtr eom_output = NULL;
-   E_EomClientPtr eom_client = NULL;
-   E_Client *parent = NULL;
-   Eina_List *l;
-
-   EINA_LIST_FOREACH(g_eom->eom_outputs, l, eom_output)
-     {
-        eom_client = _e_eom_client_get_current_by_id(eom_output->id);
-        if (!eom_client)
-          continue;
-
-        if (eom_client->ec == ec)
-          return eom_output;
-
-        if (!ec->comp_data || !ec->comp_data->sub.data)
-          continue;
-
-        parent = ec->comp_data->sub.data->parent;
-        while (parent)
-          {
-             if (parent == eom_client->ec)
-               return eom_output;
-
-             if (!parent->comp_data || !parent->comp_data->sub.data)
-               break;
-
-             parent = parent->comp_data->sub.data->parent;
-          }
-     }
-
-   return NULL;
-}
-
-static void
-_e_eom_cb_wl_eom_client_destroy(struct wl_resource *resource)
-{
-   E_EomClientPtr client = NULL;
-   E_EomOutputPtr eom_output = NULL;
-   E_Output *output = NULL;
-   E_Plane *ep = NULL;
-
-   EOINF("=======================>  CLIENT DESTROY", NULL);
-
-   EINA_SAFETY_ON_NULL_RETURN(resource);
-
-   client = _e_eom_client_get_by_resource(resource);
-   EINA_SAFETY_ON_NULL_RETURN(client);
-
-   g_eom->clients = eina_list_remove(g_eom->clients, client);
-
-   if (client->current == EINA_FALSE)
-     goto end2;
-
-   eom_output = _e_eom_output_get_by_id(client->output_id);
-   EINA_SAFETY_ON_NULL_GOTO(eom_output, end2);
-
-   _e_eom_output_state_set_attribute(eom_output, EOM_OUTPUT_ATTRIBUTE_NONE);
-
-   if (eom_output->state == NONE)
-     goto end;
-
-   if (eom_output->state == WAIT_PRESENTATION)
-     {
-        eom_output->state = NONE;
-        goto end;
-     }
-
-   if (eom_output->overlay_layer)
-     {
-        tdm_error err = TDM_ERROR_NONE;
-
-        err = tdm_layer_unset_buffer(eom_output->overlay_layer);
-        if (err != TDM_ERROR_NONE)
-          EOERR("fail unset buffer:%d", eom_output->eout, err);
-
-        err = tdm_layer_commit(eom_output->overlay_layer, NULL, eom_output);
-        if (err != TDM_ERROR_NONE)
-          EOERR("fail commit on deleting output err:%d", eom_output->eout, err);
-     }
-   _e_eom_output_overlay_buff_release(eom_output);
-
-   if (!eom_output->pp_overlay_converting)
-     _e_eom_pp_deinit(eom_output);
-   else
-     eom_output->pp_overlay_deinit = EINA_TRUE;
-
-   if (e_output_connected(eom_output->eout))
-     {
-        EOINF("Start Mirroring", eom_output->eout);
-        e_output_external_set(output, E_OUTPUT_DISPLAY_MODE_MIRROR);
-        eom_output->state = MIRROR;
-
-        ep = e_output_default_fb_target_get(eom_output->eout);
-        if (ep->prepare_ec)
-          {
-             e_plane_ec_prepare_set(ep, NULL);
-             e_plane_ec_set(ep, NULL);
-          }
-     }
-end:
-   /* Notify eom clients which are binded to a concrete output that the
-    * state and mode of the output has been changed */
-   _e_eom_output_status_broadcast(eom_output, client, EOM_OUTPUT_ATTRIBUTE_STATE_NONE);
-
-end2:
-   free(client);
-}
-
-static Eina_Bool
-_e_eom_mirror_start(E_EomOutput *eom_output, E_EomClient *eom_client)
-{
-   E_Output *output = NULL;
-   E_Plane *ep = NULL;
-
-   eom_client->current = EINA_FALSE;
-   output = eom_output->eout;
-
-   _e_eom_output_state_set_mode(eom_output, EOM_OUTPUT_MODE_NONE);
-
-   if (e_output_connected(output))
-    {
-       EOINF("Start Mirroring", eom_output->eout);
-       e_output_external_set(output, E_OUTPUT_DISPLAY_MODE_MIRROR);
-       eom_output->state = MIRROR;
-
-       ep = e_output_default_fb_target_get(output);
-
-       if (ep->prepare_ec)
-         {
-            e_plane_ec_prepare_set(ep, NULL);
-            e_plane_ec_set(ep, NULL);
-         }
-
-       if (eom_output->overlay_layer)
-         {
-            tdm_error err = TDM_ERROR_NONE;
-
-            err = tdm_layer_unset_buffer(eom_output->overlay_layer);
-            if (err != TDM_ERROR_NONE)
-              EOERR("fail unset buffer:%d", eom_output->eout, err);
-
-            err = tdm_layer_commit(eom_output->overlay_layer, NULL, eom_output);
-            if (err != TDM_ERROR_NONE)
-              EOERR("fail commit on deleting output err:%d", eom_output->eout, err);
-         }
-       _e_eom_output_overlay_buff_release(eom_output);
-
-       if (!eom_output->pp_overlay_converting)
-         _e_eom_pp_deinit(eom_output);
-       else
-         eom_output->pp_overlay_deinit = EINA_TRUE;
-    }
-  /* If mirror mode has been run notify all clients about that */
-  if (eom_trace_debug)
-    EOINF("client set NONE attribute, send new info to previous current client", eom_output->eout);
-
-  /* broadcast the status */
-  _e_eom_output_status_broadcast(eom_output, NULL, EOM_OUTPUT_ATTRIBUTE_STATE_NONE);
-
-  return EINA_TRUE;
-}
-
-static void
-_e_eom_cb_wl_request_set_attribute_result_send(E_EomOutput *eom_output, E_EomClient *eom_client)
-{
-   E_EomClientPtr current_eom_client = NULL;
-   E_Output *output = NULL;
-   E_Plane *ep = NULL;
-
-   /* Send changes to the caller-client */
-   wl_eom_send_output_attribute(eom_client->resource, eom_output->id,
-                                _e_eom_output_state_get_attribute(eom_output),
-                                EOM_OUTPUT_ATTRIBUTE_STATE_NONE,
-                                EOM_ERROR_NONE);
-
-   current_eom_client = _e_eom_client_get_current_by_id(eom_output->id);
-   EOINF("Substitute current client: new:%p, old:%p", NULL, eom_client, current_eom_client);
-
-   /* Send changes to previous current client */
-   if (eom_client->current == EINA_FALSE && current_eom_client)
-     {
-        EOINF("Send changes to previous current client", eom_output->eout);
-
-        wl_eom_send_output_attribute(current_eom_client->resource, eom_output->id,
-                                     _e_eom_output_state_get_attribute(eom_output),
-                                     EOM_OUTPUT_ATTRIBUTE_STATE_LOST,
-                                     EOM_ERROR_NONE);
-
-        current_eom_client->current = EINA_FALSE;
-
-        output = eom_output->eout;
-
-        if (e_output_connected(output))
-          {
-             EOINF("Start Mirroring", eom_output->eout);
-             e_output_external_set(output, E_OUTPUT_DISPLAY_MODE_MIRROR);
-             eom_output->state = MIRROR;
-
-             ep = e_output_default_fb_target_get(eom_output->eout);
-
-             if (ep->prepare_ec)
-               {
-                  e_plane_ec_prepare_set(ep, NULL);
-                  e_plane_ec_set(ep, NULL);
-               }
-
-             if (eom_output->overlay_layer)
-               {
-                  tdm_error err = TDM_ERROR_NONE;
-
-                  err = tdm_layer_unset_buffer(eom_output->overlay_layer);
-                  if (err != TDM_ERROR_NONE)
-                    EOERR("fail unset buffer:%d", eom_output->eout, err);
-
-                  err = tdm_layer_commit(eom_output->overlay_layer, NULL, eom_output);
-                  if (err != TDM_ERROR_NONE)
-                    EOERR("fail commit on deleting output err:%d", eom_output->eout, err);
-               }
-             _e_eom_output_overlay_buff_release(eom_output);
-
-             if (!eom_output->pp_overlay_converting)
-               _e_eom_pp_deinit(eom_output);
-             else
-               eom_output->pp_overlay_deinit = EINA_TRUE;
-          }
-     }
-
-   /* Set the client as current client of the eom_output */
-   eom_client->current = EINA_TRUE;
-
-   if (eom_output->connection_status == EINA_FALSE)
-     eom_output->state = WAIT_PRESENTATION;
-   else
-     {
-        if (eom_output->delay_timer)
-          {
-            ecore_timer_del(eom_output->delay_timer);
-            eom_output->delay_timer = ecore_timer_add(EOM_DELAY_CHECK_TIMEOUT, _e_eom_presentation_check, eom_output);
-          }
-     }
-}
-
-static void
-_e_eom_cb_wl_request_set_attribute(struct wl_client *client, struct wl_resource *resource, uint32_t output_id, uint32_t attribute)
-{
-   eom_error_e eom_error = EOM_ERROR_NONE;
-   E_EomClientPtr eom_client = NULL;//, current_eom_client = NULL, iterator = NULL;
-   E_EomOutputPtr eom_output = NULL;
-   Eina_Bool ret = EINA_FALSE;
-
-   eom_client = _e_eom_client_get_by_resource(resource);
-   EINA_SAFETY_ON_NULL_RETURN(eom_client);
-
-   /* Bind the client with a concrete output */
-   eom_client->output_id = output_id;
-
-   eom_output = _e_eom_output_get_by_id(output_id);
-   EINA_SAFETY_ON_NULL_GOTO(eom_output, no_eom_output);
-
-   EOINF("Set attribute:%d, client:%p", eom_output->eout, attribute, eom_client);
-
-   if (eom_client->current == EINA_TRUE && eom_output->id == eom_client->output_id)
-     {
-        /* Current client can set any flag it wants */
-        _e_eom_output_state_set_force_attribute(eom_output, attribute);
-     }
-   else if (eom_output->id == eom_client->output_id)
-     {
-        /* A client is trying to set new attribute */
-        ret = _e_eom_output_state_set_attribute(eom_output, attribute);
-        if (ret == EINA_FALSE)
-          {
-             EOINF("client failed to set attribute", eom_output->eout);
-             eom_error = EOM_ERROR_INVALID_PARAMETER;
-             wl_eom_send_output_attribute(eom_client->resource, eom_output->id,
-                                          _e_eom_output_state_get_attribute(eom_output),
-                                          EOM_OUTPUT_ATTRIBUTE_STATE_LOST,
-                                          eom_error);
-             return;
-          }
-     }
-   else
-     return;
-
-   if (attribute == EOM_OUTPUT_ATTRIBUTE_NONE && eom_output->state != MIRROR)
-     {
-        if (!_e_eom_mirror_start(eom_output, eom_client))
-          {
-             EOINF("mirror start FAILED", eom_output->eout);
-             return;
-          }
-
-        wl_eom_send_output_attribute(eom_client->resource, eom_output->id,
-                                     _e_eom_output_state_get_attribute(eom_output),
-                                     EOM_OUTPUT_ATTRIBUTE_STATE_LOST,
-                                     eom_error);
-        return;
-      }
-
-   _e_eom_cb_wl_request_set_attribute_result_send(eom_output, eom_client);
-
-   return;
-
-   /* Get here if EOM does not have output referred by output_id */
-no_eom_output:
-   wl_eom_send_output_attribute(eom_client->resource, output_id,
-                                EOM_OUTPUT_ATTRIBUTE_NONE,
-                                EOM_OUTPUT_ATTRIBUTE_STATE_NONE,
-                                EOM_ERROR_NO_SUCH_DEVICE);
-
-   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);
-}
-
-static Eina_Bool
-_e_eom_cb_comp_object_redirected(void *data, E_Client *ec)
-{
-   E_EomCompObjectInterceptHookData *hook_data;
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_TRUE);
-
-   hook_data = (E_EomCompObjectInterceptHookData* )data;
-
-   if (!hook_data->ec || !hook_data->hook)
-     return EINA_TRUE;
-
-   if (hook_data->ec != ec)
-     return EINA_TRUE;
-
-   /* Hide the window from Enlightenment main screen */
-   e_client_redirected_set(ec, EINA_FALSE);
-
-   e_comp_object_intercept_hook_del(hook_data->hook);
-
-   g_eom->comp_object_intercept_hooks = eina_list_remove(g_eom->comp_object_intercept_hooks, hook_data);
-
-   free(hook_data);
-
-   return EINA_TRUE;
-}
-
-static Eina_Bool
-_e_eom_util_add_comp_object_redirected_hook(E_Client *ec)
-{
-   E_EomCompObjectInterceptHookData *hook_data = NULL;
-   E_Comp_Object_Intercept_Hook *hook = NULL;
-
-   hook_data = E_NEW(E_EomCompObjectInterceptHookData, 1);
-   EINA_SAFETY_ON_NULL_GOTO(hook_data, err);
-
-   hook_data->ec = ec;
-
-   hook = e_comp_object_intercept_hook_add(E_COMP_OBJECT_INTERCEPT_HOOK_SHOW_HELPER,
-                                           _e_eom_cb_comp_object_redirected, hook_data);
-   EINA_SAFETY_ON_NULL_GOTO(hook, err);
-
-   hook_data->hook = hook;
-
-   g_eom->comp_object_intercept_hooks = eina_list_append(g_eom->comp_object_intercept_hooks, hook_data);
-
-   return EINA_TRUE;
-
-err:
-   if (hook_data)
-     free(hook_data);
-
-   return EINA_FALSE;
-}
-
-static void
-_e_eom_send_configure_event()
-{
-   E_EomOutput *eom_output = NULL;
-   E_EomClientPtr eom_client = NULL;
-   E_Client *ec = NULL;
-   Eina_List *l;
-   Eina_Bool ret = EINA_FALSE;
-   E_Comp_Client_Data *cdata = NULL;
-   E_Plane *ep = NULL;
-
-   EINA_LIST_FOREACH(g_eom->clients, l, eom_client)
-     {
-        if (eom_client->current == EINA_TRUE)
-          {
-             EINA_SAFETY_ON_NULL_RETURN(eom_client->ec);
-
-             ec = eom_client->ec;
-
-             cdata = ec->comp_data;
-             EINA_SAFETY_ON_NULL_RETURN(cdata);
-             EINA_SAFETY_ON_NULL_RETURN(cdata->shell.configure_send);
-
-             eom_output = _e_eom_output_get_by_id(eom_client->output_id);
-             if (eom_output == NULL)
-               {
-                  EOERR("no eom_output error\n", NULL);
-                  return;
-               }
-
-             EOINF("e_comp_object_redirected_set (ec:%p)(ec->frame:%p)\n", eom_output->eout, ec, ec->frame);
-             ret = _e_eom_util_add_comp_object_redirected_hook(eom_client->ec);
-             EINA_SAFETY_ON_FALSE_RETURN(ret == EINA_TRUE);
-
-             cdata->shell.configure_send(ec->comp_data->shell.surface, 0, eom_output->width, eom_output->height);
-
-             ep = e_output_default_fb_target_get(eom_output->eout);
-             e_plane_ec_prepare_set(ep, ec);
-
-             return;
-          }
-     }
-}
-
-static void
-_e_eom_window_set_internal(struct wl_resource *resource, int output_id, E_Client *ec)
-{
-   E_EomOutputPtr eom_output = NULL;
-   E_EomClientPtr eom_client = NULL;
-   E_Comp_Client_Data *cdata = NULL;
-   Eina_Bool ret = EINA_FALSE;
-   E_Plane *ep = NULL;
-
-   if (!resource || output_id <= 0 || !ec || e_object_is_del(E_OBJECT(ec)))
-     return;
-
-   eom_client = _e_eom_client_get_by_resource(resource);
-   EINA_SAFETY_ON_NULL_RETURN(eom_client);
-
-   eom_output = _e_eom_output_get_by_id(output_id);
-   if (eom_output == NULL)
-     {
-        wl_eom_send_output_set_window(resource, output_id, WL_EOM_ERROR_NO_OUTPUT);
-        EOERR("no eom_output error\n", NULL);
-        return;
-     }
-
-   if (!eom_client->current)
-     {
-        wl_eom_send_output_set_window(resource, output_id, WL_EOM_ERROR_OUTPUT_OCCUPIED);
-        return;
-     }
-
-   ret = _e_eom_util_add_comp_object_redirected_hook(ec);
-   EINA_SAFETY_ON_FALSE_RETURN(ret == EINA_TRUE);
-
-   EOINF("e_comp_object_redirected_set (ec:%p)(ec->frame:%p)\n", eom_output->eout, ec, ec->frame);
-
-   /* ec is used in buffer_change callback for distinguishing external ec and its buffers */
-   eom_client->ec = ec;
-
-   /* Send reconfigure event to a client which will resize its window to
-    * external output resolution in respond */
-   cdata = ec->comp_data;
-   EINA_SAFETY_ON_NULL_RETURN(cdata);
-   EINA_SAFETY_ON_NULL_RETURN(cdata->shell.configure_send);
-
-   cdata->shell.configure_send(ec->comp_data->shell.surface, 0, eom_output->width, eom_output->height);
-
-   ep = e_output_default_fb_target_get(eom_output->eout);
-   e_plane_ec_prepare_set(ep, ec);
-
-   wl_eom_send_output_set_window(resource, output_id, WL_EOM_ERROR_NONE);
-}
-
-static void
-_e_eom_cb_wl_request_set_shell_window(struct wl_client *client, struct wl_resource *resource, uint32_t output_id, struct wl_resource *surface)
-{
-   E_Client *ec = NULL;
-
-   if (resource == NULL || output_id <= 0 || surface == NULL)
-     return;
-
-   EOINF("set shell output id:%d resource:%p surface:%p", NULL, output_id, resource, surface);
-
-   if (!(ec = wl_resource_get_user_data(surface)))
-     {
-        wl_resource_post_error(surface, WL_DISPLAY_ERROR_INVALID_OBJECT, "No Client For Shell Surface");
-        return;
-     }
-
-   _e_eom_window_set_internal(resource, output_id, ec);
-}
-
-static void
-_e_eom_cb_wl_request_get_output_info(struct wl_client *client, struct wl_resource *resource, uint32_t output_id)
-{
-   E_EomOutputPtr eom_output = NULL;
-
-   EOINF("get output info:%d", NULL, output_id);
-
-   eom_output = _e_eom_output_get_by_id(output_id);
-   EINA_SAFETY_ON_FALSE_RETURN(eom_output);
-
-   wl_eom_send_output_info(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->connection,
-                           1, 0, 0, 0);
-
-   EOINF("send - id : %d, type : %d, mode : %d, w : %d, h : %d, w_mm : %d, h_mm : %d, conn : %d", NULL,
-         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->connection_status);
-}
-
-static const struct wl_eom_interface _e_eom_wl_implementation =
-{
-   _e_eom_cb_wl_request_set_attribute,
-   _e_eom_cb_wl_request_set_shell_window,
-   _e_eom_cb_wl_request_get_output_info
-};
-
-static void
-_e_eom_cb_wl_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
-{
-   struct wl_resource *resource = NULL;
-   E_EomPtr eom = NULL;
-   E_EomClientPtr new_client = NULL;
-   E_EomOutputPtr eom_output = NULL;
-   Eina_List *l;
-
-   EINA_SAFETY_ON_NULL_RETURN(data);
-   eom = data;
-
-   resource = wl_resource_create(client, &wl_eom_interface, MIN(version, 1), id);
-   if (resource == NULL)
-     {
-        EOERR("resource is null. (version :%d, id:%d)", NULL, version, id);
-        wl_client_post_no_memory(client);
-        return;
-     }
-
-   wl_resource_set_implementation(resource, &_e_eom_wl_implementation, eom, _e_eom_cb_wl_eom_client_destroy);
-
-   wl_eom_send_output_count(resource, g_eom->eom_output_count);
-
-   EINA_LIST_FOREACH(g_eom->eom_outputs, l, eom_output)
-     {
-        if (!eom_output) continue;
-
-        wl_eom_send_output_info(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->connection,
-                                1, 0, 0, 0);
-
-        EOINF("send - id : %d, type : %d, mode : %d, w : %d, h : %d, w_mm : %d, h_mm : %d, conn : %d", eom_output->eout,
-              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->connection_status);
-     }
-
-   new_client = E_NEW(E_EomClient, 1);
-   EINA_SAFETY_ON_NULL_RETURN(new_client);
-
-   new_client->resource = resource;
-   new_client->current = EINA_FALSE;
-   new_client->output_id = -1;
-   new_client->ec = NULL;
-
-   g_eom->clients = eina_list_append(g_eom->clients, new_client);
-
-   EOINF("=======================>  BIND CLIENT", NULL);
-}
-
-static E_EomClientPtr
-_e_eom_client_get_current_by_ec(E_Client *ec)
-{
-   Eina_List *l;
-   E_EomClientPtr client;
-
-   EINA_LIST_FOREACH(g_eom->clients, l, client)
-     {
-        if (client && client->current == EINA_TRUE && client->ec == ec)
-          return client;
-     }
-
-   return NULL;
-}
-
-static void
-_e_eom_tbm_buffer_release_ext_mod(E_EomOutputPtr eom_output, tbm_surface_h srfc, void *eom_buff)
-{
-   if (eom_trace_debug)
-     EOINF("============>  EXT END     tbm_buff:%p E_EomBuffer:%p", eom_output->eout, srfc, eom_buff);
-   _e_eom_buffer_destroy(eom_output, eom_buff);
-}
-
-static E_EomClientPtr
-_e_eom_client_get_current_by_ec_parrent(E_Client *ec)
-{
-   Eina_List *l;
-   E_EomClientPtr client;
-   E_Client *parent = NULL;
-
-   if (!ec->comp_data || !ec->comp_data->sub.data)
-     return NULL;
-
-   EINA_LIST_FOREACH(g_eom->clients, l, client)
-     {
-        parent = ec->comp_data->sub.data->parent;
-        while (parent)
-          {
-             if (client->ec == parent)
-               return client;
-
-             if (!parent->comp_data || !parent->comp_data->sub.data)
-               break;
-
-             parent = parent->comp_data->sub.data->parent;
-          }
-     }
-
-   return NULL;
-}
-
-static Eina_Bool
-_e_eom_cb_client_buffer_change(void *data, int type, void *event)
-{
-   E_Comp_Wl_Buffer *wl_buffer = NULL;
-   E_EomClientPtr eom_client = NULL, eom_client_itr = NULL;
-   E_EomOutputPtr eom_output = NULL;
-   E_Event_Client *ev = event;
-   E_Client *ec = NULL;
-   tbm_surface_h tbm_buffer = NULL;
-   Eina_List *l;
-   Eina_Bool overlay = EINA_FALSE;
-   int width, height;
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(ev->ec, ECORE_CALLBACK_PASS_ON);
-
-   ec = ev->ec;
-   EINA_SAFETY_ON_TRUE_RETURN_VAL(e_object_is_del(E_OBJECT(ec)),
-                                  ECORE_CALLBACK_PASS_ON);
-
-   eom_client = _e_eom_client_get_current_by_ec(ec);
-   if (eom_client == NULL)
-     {
-        eom_client = _e_eom_client_get_current_by_ec_parrent(ec);
-        if (eom_client == NULL)
-          return ECORE_CALLBACK_PASS_ON;
-
-        overlay = EINA_TRUE;
-     }
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(ec->pixmap, ECORE_CALLBACK_PASS_ON);
-
-   wl_buffer = e_pixmap_resource_get(ec->pixmap);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(wl_buffer, ECORE_CALLBACK_PASS_ON);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(wl_buffer->resource, ECORE_CALLBACK_PASS_ON);
-
-   /* TODO: support different SHMEM buffers etc. */
-   tbm_buffer = wayland_tbm_server_get_surface(e_comp->wl_comp_data->tbm.server, wl_buffer->resource);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(tbm_buffer, ECORE_CALLBACK_PASS_ON);
-
-   width = tbm_surface_get_width(tbm_buffer);
-   height = tbm_surface_get_height(tbm_buffer);
-
-   if ((width <= 1) || (height <= 1))
-     return ECORE_CALLBACK_PASS_ON;
-
-   eom_output = _e_eom_output_get_by_id(eom_client->output_id);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(eom_output, ECORE_CALLBACK_PASS_ON);
-
-   if (eom_trace_debug)
-     EOINF("===============>  EXT START", eom_output->eout);
-
-   if (eom_output->delay_timer)
-     ecore_timer_del(eom_output->delay_timer);
-   eom_output->delay_timer = NULL;
-
-   e_output_external_set(eom_output->eout, E_OUTPUT_DISPLAY_MODE_PRESENTATION);
-
-   /* TODO: It works but maybe there is better solution exists ?
-    * Also I do not know how it affects on performance */
-   if (ec->map_timer)
-     {
-        if (eom_trace_debug)
-          EOINF("delete map_timer", eom_output->eout);
-        E_FREE_FUNC(ec->map_timer, ecore_timer_del);
-     }
-
-   if (eom_trace_debug)
-     EOINF("buffer_changed callback ec:%p, overlay:%d", eom_output->eout, ec, overlay);
-
-   if (overlay)
-     {
-        Eina_Bool video_layer = EINA_FALSE;
-        tbm_format format;
-        Eina_Bool need_pp = EINA_FALSE;
-
-        E_EomBufferPtr eom_buff = _e_eom_buffer_create(eom_output, wl_buffer);
-        EINA_SAFETY_ON_NULL_RETURN_VAL(eom_buff, ECORE_CALLBACK_PASS_ON);
-
-        format = tbm_surface_get_format(tbm_buffer);
-        video_layer = _e_eom_output_video_layer_find(eom_output, format);
-        if (!video_layer)
-          {
-             /* need pp */
-             need_pp = EINA_TRUE;
-             eom_output->need_overlay_pp = EINA_TRUE;
-             if (!_e_eom_pp_init(eom_output))
-               {
-                  EOERR("pp_init for overlay fail", eom_output->eout);
-                  _e_eom_buffer_destroy(eom_output, eom_buff);
-                  return ECORE_CALLBACK_PASS_ON;
-               }
-          }
+   /* get the output size */
+   e_output_size_get(eom_output->output, &w, &h);
+   e_output_phys_size_get(eom_output->output, &pw, &ph);
 
-        if (eom_output->state != PRESENTATION)
-          {
-             _e_eom_output_state_set_mode(eom_output, EOM_OUTPUT_MODE_PRESENTATION);
+   wl_eom_send_output_info(resource,
+                           eom_output->id,
+                           eom_output->type,
+                           e_output_display_mode_get(eom_output->output),
+                           w, h, pw, ph,
+                           eom_output->connection,
+                           1, 0, 0, 0);
 
-             EINA_LIST_FOREACH(g_eom->clients, l, eom_client_itr)
-               {
-                  if (eom_client_itr->output_id == eom_output->id)
-                    wl_eom_send_output_mode(eom_client_itr->resource, eom_output->id,
-                                            _e_eom_output_state_get_mode(eom_output));
-               }
+   EOINF("send - id : %d, type : %d, mode : %d, w : %d, h : %d, w_mm : %d, h_mm : %d, conn : %d", NULL,
+         eom_output->id, eom_output->type, e_output_display_mode_get(eom_output->output),
+         w, h, pw, ph, e_output_connected(eom_output->output));
+}
 
-             eom_output->state = PRESENTATION;
-          }
+static const struct wl_eom_interface _e_eom_wl_implementation =
+{
+   _e_eom_cb_wl_request_set_attribute,
+   _e_eom_cb_wl_request_set_shell_window,
+   _e_eom_cb_wl_request_get_output_info
+};
 
-        if (need_pp)
-          {
-             if (eom_trace_debug)
-               EOINF("run _e_eom_presentation_pp_run", eom_output->eout);
-             _e_eom_presentation_pp_run(eom_output, tbm_buffer, eom_buff);
-          }
-        else
-          {
-             if (eom_trace_debug)
-               EOINF("run direct show", eom_output->eout);
-             _e_eom_layer_overlay_set(eom_output, tbm_buffer);
+static void
+_e_eom_cb_wl_eom_client_destroy(struct wl_resource *resource)
+{
+   E_EomClientPtr eom_client = NULL;
+   E_EomOutputPtr eom_output = NULL;
+   E_Output *primary_output = NULL;
+   E_Client *output_ec = NULL;
 
-             if (!_e_eom_output_show(eom_output, tbm_buffer, _e_eom_tbm_buffer_release_ext_mod, eom_buff))
-               {
-                  if (eom_trace_debug)
-                    {
-                       EOINF("===============>  EXT ENDERR  tbm_buff:%p", eom_output->eout, tbm_buffer);
-                       EOINF("_e_eom_add_buff_to_show fail tbm_buff:%p", eom_output->eout, tbm_buffer);
-                    }
-                  _e_eom_buffer_destroy(eom_output, eom_buff);
-                  return ECORE_CALLBACK_PASS_ON;
-               }
-          }
-     }
-   else
-     {
-        E_Plane *ep = NULL;
+   EOINF("=======================>  CLIENT DESTROY", NULL);
+
+   EINA_SAFETY_ON_NULL_RETURN(resource);
 
-        ep = e_output_default_fb_target_get(eom_output->eout);
+   eom_client = _e_eom_client_get_by_resource(resource);
+   EINA_SAFETY_ON_NULL_RETURN(eom_client);
 
-        if (ep->prepare_ec)
-          e_plane_ec_set(ep, ec);
+   g_eom->clients = eina_list_remove(g_eom->clients, eom_client);
 
-        if (eom_output->state != PRESENTATION)
-          {
-             _e_eom_output_state_set_mode(eom_output, EOM_OUTPUT_MODE_PRESENTATION);
+   eom_output = _e_eom_output_get_by_id(eom_client->output_id);
+   EINA_SAFETY_ON_NULL_GOTO(eom_output, end);
 
-             EINA_LIST_FOREACH(g_eom->clients, l, eom_client_itr)
-               {
-                  if (eom_client_itr->output_id == eom_output->id)
-                    wl_eom_send_output_mode(eom_client_itr->resource, eom_output->id,
-                                            _e_eom_output_state_get_mode(eom_output));
-               }
-             eom_output->state = PRESENTATION;
-          }
+   output_ec = e_output_presentation_ec_get(eom_output->output);
+   if (eom_client->ec == output_ec)
+     {
+        _e_eom_output_attribute_set(eom_output, EOM_OUTPUT_ATTRIBUTE_NONE);
+        e_output_presentation_unset(eom_output->output);
 
-        e_comp_object_hwc_update_set(ec->frame, EINA_TRUE);
+        primary_output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
+        if (!e_output_mirror_set(eom_output->output, primary_output))
+          EOERR("e_output_mirror_set fails", eom_output->output);
      }
 
-   if (eom_trace_debug)
-        EOINF("===============<  EXT START", eom_output->eout);
+end:
+   /* Notify eom clients which are binded to a concrete output that the
+    * state and mode of the output has been changed */
+   if (eom_output)
+     _e_eom_output_status_broadcast(eom_output, eom_client, EOM_OUTPUT_ATTRIBUTE_STATE_NONE);
 
-   return ECORE_CALLBACK_PASS_ON;
+   free(eom_client);
 }
 
-static Eina_Bool
-_e_eom_connect(E_Output *output)
+static void
+_e_eom_cb_wl_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
 {
+   struct wl_resource *resource = NULL;
+   E_EomPtr eom = NULL;
+   E_EomClientPtr eom_client = NULL;
    E_EomOutputPtr eom_output = NULL;
+   Eina_List *l;
+   int w, h, pw, ph;
 
-   if (!g_eom) return EINA_TRUE;
-
-   g_eom->check_first_boot = 1;
+   EINA_SAFETY_ON_NULL_RETURN(data);
+   eom = data;
 
-   eom_output = _e_eom_output_find(output);
-   if (eom_output == NULL)
+   resource = wl_resource_create(client, &wl_eom_interface, MIN(version, 1), id);
+   if (resource == NULL)
      {
-        eom_output = _e_eom_output_find_added_output(output);
-        if (!eom_output)
-          {
-             EOERR("cannot find eom_output", NULL);
-             return EINA_FALSE;
-          }
+        EOERR("resource is null. (version :%d, id:%d)", NULL, version, id);
+        wl_client_post_no_memory(client);
+        return;
      }
 
-   if (eom_output->connection_status == EINA_TRUE)
-     return EINA_TRUE;
-
-   /* update eom_output connect */
-   eom_output->width = output->config.mode.w;
-   eom_output->height = output->config.mode.h;
-   eom_output->phys_width = output->info.size.w;
-   eom_output->phys_height = output->info.size.h;
-   eom_output->name = eina_stringshare_add(output->id);
-   eom_output->connection_status = EINA_TRUE;
+   wl_resource_set_implementation(resource, &_e_eom_wl_implementation, eom, _e_eom_cb_wl_eom_client_destroy);
 
-   EOINF("Setup new eom_output: (%dx%d)", eom_output->eout, eom_output->width, eom_output->height);
+   wl_eom_send_output_count(resource, g_eom->eom_output_count);
 
-   /* TODO: check eom_output mode(presentation set) and HDMI type */
-   if (eom_output->state == WAIT_PRESENTATION)
+   EINA_LIST_FOREACH(g_eom->eom_outputs, l, eom_output)
      {
-        EOINF("Start wait Presentation", eom_output->eout);
+        if (!eom_output) continue;
 
-        _e_eom_send_configure_event();
+        /* get the output size */
+        e_output_size_get(eom_output->output, &w, &h);
+        e_output_phys_size_get(eom_output->output, &pw, &ph);
 
-        if (eom_output->delay_timer)
-          ecore_timer_del(eom_output->delay_timer);
-        eom_output->delay_timer = ecore_timer_add(EOM_DELAY_CONNECT_CHECK_TIMEOUT, _e_eom_presentation_check, eom_output);
-     }
-   else
-     {
-        EOINF("Start Mirroring", eom_output->eout);
-        _e_eom_output_state_set_mode(eom_output, EOM_OUTPUT_MODE_MIRROR);
-        eom_output->state = MIRROR;
-        e_output_external_set(output, E_OUTPUT_DISPLAY_MODE_MIRROR);
+        wl_eom_send_output_info(resource,
+                                eom_output->id,
+                                eom_output->type,
+                                e_output_display_mode_get(eom_output->output),
+                                w, h, pw, ph,
+                                eom_output->connection,
+                                1, 0, 0, 0);
+
+        EOINF("send - id : %d, type : %d, mode : %d, w : %d, h : %d, w_mm : %d, h_mm : %d, conn : %d", eom_output->output,
+              eom_output->id, eom_output->type, e_output_display_mode_get(eom_output->output),
+              w, h, pw, ph, e_output_connected(eom_output->output));
      }
 
-   eom_output->connection = WL_EOM_STATUS_CONNECTION;
+   eom_client = E_NEW(E_EomClient, 1);
+   EINA_SAFETY_ON_NULL_RETURN(eom_client);
 
-   /* If there were previously connected clients to the output - notify them */
-   _e_eom_output_info_broadcast(eom_output, EOM_OUTPUT_ATTRIBUTE_STATE_ACTIVE);
+   eom_client->resource = resource;
+   eom_client->current = EINA_FALSE;
+   eom_client->output_id = -1;
+   eom_client->ec = NULL;
 
-   return EINA_TRUE;
+   g_eom->clients = eina_list_append(g_eom->clients, eom_client);
+
+   EOINF("=======================>  BIND CLIENT", NULL);
 }
 
 static Eina_Bool
-_e_eom_disconnect(E_Output *output)
+_e_eom_connect(E_Output *output)
 {
    E_EomOutputPtr eom_output = NULL;
+   E_Client *ec = NULL;
+   int w, h;
 
    if (!g_eom) return EINA_TRUE;
 
-   g_eom->check_first_boot = 1;
-
    eom_output = _e_eom_output_find(output);
-   if (eom_output == NULL)
+   if (!eom_output)
      {
-        eom_output = _e_eom_output_find_added_output(output);
-        if (!eom_output)
-          {
-             EOERR("cannot find output", NULL);
-             return EINA_FALSE;
-          }
+        EOERR("cannot find eom_output", NULL);
+        return EINA_FALSE;
      }
 
-   if (eom_output->connection_status == EINA_FALSE)
-     return EINA_TRUE;
-
-   if (eom_output->delay_timer)
-     ecore_timer_del(eom_output->delay_timer);
-   eom_output->delay_timer = NULL;
-
-   /* update eom_output disconnect */
-   eom_output->width = 0;
-   eom_output->height = 0;
-   eom_output->phys_width = 0;
-   eom_output->phys_height = 0;
-   eom_output->connection = WL_EOM_STATUS_DISCONNECTION;
-
-   e_output_external_unset(output);
+   if (e_output_display_mode_get(eom_output->output) == E_OUTPUT_DISPLAY_MODE_WAIT_PRESENTATION)
+     {
+        EOINF("Send Configure Event for Presentation", eom_output->output);
 
-   eom_output->connection_status = EINA_FALSE;
+        ec = e_output_presentation_ec_get(eom_output->output);
+        EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
 
-   _e_eom_output_state_set_mode(eom_output, EOM_OUTPUT_MODE_NONE);
+        _e_eom_output_send_configure_event(eom_output, ec);
+     }
 
-   if (_e_eom_client_get_current_by_id(eom_output->id))
-     eom_output->state = WAIT_PRESENTATION;
-   else
-     eom_output->state = NONE;
+   eom_output->connection = WL_EOM_STATUS_CONNECTION;
 
    /* If there were previously connected clients to the output - notify them */
-   _e_eom_output_info_broadcast(eom_output, EOM_OUTPUT_ATTRIBUTE_STATE_INACTIVE);
+   _e_eom_output_info_broadcast(eom_output, EOM_OUTPUT_ATTRIBUTE_STATE_ACTIVE);
 
-   EOINF("Destory output: %s", eom_output->eout, eom_output->name);
-   eina_stringshare_del(eom_output->name);
-   eom_output->name = NULL;
+   /* get the output size */
+   e_output_size_get(eom_output->output, &w, &h);
+   EOINF("Setup new eom_output: (%dx%d)", eom_output->output, w, h);
 
    return EINA_TRUE;
 }
 
 static Eina_Bool
-_e_eom_mode_change(E_Output *output, E_Output_Mode *emode)
+_e_eom_disconnect(E_Output *output)
 {
    E_EomOutputPtr eom_output = NULL;
-   E_Output *output_primary = NULL;
 
    if (!g_eom) return EINA_TRUE;
 
-   EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
-
-   output_primary = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(output_primary, EINA_FALSE);
-   EINA_SAFETY_ON_TRUE_RETURN_VAL(output_primary == output, EINA_FALSE);
-
    eom_output = _e_eom_output_find(output);
-   if (eom_output == NULL)
+   if (!eom_output)
      {
-        eom_output = _e_eom_output_find_added_output(output);
-        if (!eom_output)
-          {
-             EOERR("cannot find output", NULL);
-             return EINA_FALSE;
-          }
+        EOERR("cannot find output", NULL);
+        return EINA_FALSE;
      }
 
-   if (eom_output->connection_status == EINA_FALSE)
-     return EINA_FALSE;
-
-   if (eom_output->delay_timer)
-     ecore_timer_del(eom_output->delay_timer);
-   eom_output->delay_timer = NULL;
-
-   /* update eom_output connect */
-   eom_output->width = output->config.mode.w;
-   eom_output->height = output->config.mode.h;
-   eom_output->phys_width = output->info.size.w;
-   eom_output->phys_height = output->info.size.h;
-   eom_output->name = eina_stringshare_add(output->id);
-   eom_output->connection_status = EINA_TRUE;
+   /* update eom_output disconnect */
+   eom_output->connection = WL_EOM_STATUS_DISCONNECTION;
 
-   EOINF("mode change output: (%dx%d)", eom_output->eout, eom_output->width, eom_output->height);
-   if (eom_output->state == PRESENTATION)
-     {
-        eom_output->state = WAIT_PRESENTATION;
-        _e_eom_send_configure_event();
+   /* If there were previously connected clients to the output - notify them */
+   _e_eom_output_info_broadcast(eom_output, EOM_OUTPUT_ATTRIBUTE_STATE_INACTIVE);
 
-        eom_output->delay_timer = ecore_timer_add(EOM_DELAY_CONNECT_CHECK_TIMEOUT, _e_eom_presentation_check, eom_output);
-     }
+   EOINF("Destory output.", eom_output->output);
 
    return EINA_TRUE;
 }
@@ -2334,130 +904,109 @@ _e_eom_mode_change(E_Output *output, E_Output_Mode *emode)
 static void
 _e_eom_output_cb_output_connect_status_change(void *data, E_Output *output)
 {
-   EINA_SAFETY_ON_NULL_RETURN(g_eom->output_primary);
-
-   /* doesn't care about the pirmary output */
-   if (g_eom->output_primary == output) return;
-
    if (e_output_connected(output))
-     {
-        _e_eom_connect(output);
-     }
+     _e_eom_connect(output);
    else
-     {
-        _e_eom_disconnect(output);
-     }
+     _e_eom_disconnect(output);
 }
 
 static void
 _e_eom_output_cb_output_mode_change(void *data, E_Output *output)
 {
-   E_Output_Mode *emode;
-
-   EINA_SAFETY_ON_NULL_RETURN(g_eom->output_primary);
-
-   /* doesn't care about the pirmary output */
-   if (g_eom->output_primary == output) return;
+   E_EomOutputPtr eom_output = NULL;
+   E_Client *ec = NULL;
 
-   if (!e_output_connected(output))
+   /* if presentation, send configure notify to all eom_clients */
+   if (e_output_display_mode_get(output) == E_OUTPUT_DISPLAY_MODE_PRESENTATION)
      {
-        EOERR("output is disconnected.", output);
-        return;
-     }
+       eom_output = _e_eom_output_find(output);
+       EINA_SAFETY_ON_NULL_RETURN(eom_output);
 
-   emode = e_output_current_mode_get(output);
-   EINA_SAFETY_ON_FALSE_RETURN(emode);
+       ec = e_output_presentation_ec_get(output);
+       EINA_SAFETY_ON_NULL_RETURN(ec);
 
-   if (!_e_eom_mode_change(output, emode))
-     {
-        EOERR("_e_eom_mode_change fails.", output);
-        return;
+       _e_eom_output_send_configure_event(eom_output, ec);
      }
 }
 
 static void
 _e_eom_output_cb_output_add(void *data, E_Output *output)
 {
-   EINA_SAFETY_ON_NULL_RETURN(g_eom->output_primary);
-
-   /* doesn't care about the pirmary output */
-   if (g_eom->output_primary == output) return;
-
-   if (!_e_eom_create(output, EINA_TRUE))
+   if (!_e_eom_output_create(output, EINA_TRUE))
      {
-        EOERR("_e_eom_create fails.", output);
+        EOERR("_e_eom_output_create fails.", output);
         return;
      }
 }
 
 static void
-_e_eom_output_cb_output_remove(void *data, E_Output *output)
+_e_eom_output_cb_output_del(void *data, E_Output *output)
 {
-   EINA_SAFETY_ON_NULL_RETURN(g_eom->output_primary);
-
-   /* doesn't care about the pirmary output */
-   if (g_eom->output_primary == output) return;
-
-   if (!_e_eom_destroy(output))
+   if (!_e_eom_output_destroy(output))
      {
-        EOERR("_e_eom_destroy fails.", output);
+        EOERR("_e_eom_output_destroy fails.", output);
         return;
      }
 }
 
 static void
-_e_eom_deinit()
+_e_eom_output_deinit(void)
 {
-   Ecore_Event_Handler *h = NULL;
+   E_EomOutputPtr eom_output;
+   Eina_List *l;
 
-   if (g_eom == NULL) return;
+   if (!g_eom) return;
+   if (!g_eom->eom_outputs) return;
 
-   if (g_eom->output_remove_hook)
-     {
-        e_output_hook_del(g_eom->output_remove_hook);
-        g_eom->output_remove_hook = NULL;
-     }
+   EINA_LIST_FOREACH(g_eom->eom_outputs, l, eom_output)
+     _e_eom_output_destroy(eom_output->output);
 
-   if (g_eom->output_add_hook)
-     {
-        e_output_hook_del(g_eom->output_add_hook);
-        g_eom->output_add_hook = NULL;
-     }
+   eina_list_free(g_eom->eom_outputs);
+   g_eom->eom_outputs = NULL;
+}
 
-   if (g_eom->output_mode_changes_hook)
-     {
-        e_output_hook_del(g_eom->output_mode_changes_hook);
-        g_eom->output_mode_changes_hook = NULL;
-     }
+static Eina_Bool
+_e_eom_output_init(void)
+{
+   E_Comp_Screen *e_comp_screen = NULL;
+   E_Output *output = NULL;
+   E_Output *primary_output = NULL;
+   Eina_List *l;
 
-   if (g_eom->output_connect_status_hook)
-     {
-        e_output_hook_del(g_eom->output_connect_status_hook);
-        g_eom->output_connect_status_hook = NULL;
-     }
+   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, EINA_FALSE);
 
-   if (g_eom->handlers)
+   e_comp_screen = e_comp->e_comp_screen;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, EINA_FALSE);
+
+   primary_output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(primary_output, EINA_FALSE);
+
+   g_eom->eom_output_count = e_comp_screen->num_outputs - 1;
+   EOINF("external output count : %d", NULL, g_eom->eom_output_count);
+
+   /* create the eom_output except for the primary output */
+   EINA_LIST_FOREACH(e_comp_screen->outputs, l, output)
      {
-        EINA_LIST_FREE(g_eom->handlers, h)
-          ecore_event_handler_del(h);
+        if (!output) continue;
+        if (output == primary_output) continue;
 
-        g_eom->handlers = NULL;
+        if (!_e_eom_output_create(output, EINA_FALSE))
+          {
+             EOERR("_e_eom_output_create fails.", output);
+             goto err;
+          }
      }
 
-   _e_eom_output_deinit();
-
-   if (g_eom->dpy)
-     g_eom->dpy = NULL;
+   return EINA_TRUE;
 
-   if (g_eom->global)
-     wl_global_destroy(g_eom->global);
-   g_eom->global = NULL;
+err:
+   _e_eom_output_deinit();
 
-   E_FREE(g_eom);
+   return EINA_FALSE;
 }
 
-static Eina_Bool
-_e_eom_init()
+EINTERN Eina_Bool
+e_eom_init(void)
 {
    EINA_SAFETY_ON_NULL_GOTO(e_comp_wl, err);
 
@@ -2470,54 +1019,72 @@ _e_eom_init()
    g_eom->global = wl_global_create(e_comp_wl->wl.disp, &wl_eom_interface, 1, g_eom, _e_eom_cb_wl_bind);
    EINA_SAFETY_ON_NULL_GOTO(g_eom->global, err);
 
-   g_eom->dpy = e_comp->e_comp_screen->tdisplay;
-   EINA_SAFETY_ON_NULL_GOTO(g_eom->dpy, err);
-
-   g_eom->output_primary = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
-   EINA_SAFETY_ON_NULL_GOTO(g_eom->output_primary, err);
-
    if (!_e_eom_output_init())
      {
         EOERR("_e_eom_output_init fail", NULL);
         goto err;
      }
 
-   g_eom->timer = ecore_timer_add(EOM_CONNECT_CHECK_TIMEOUT, _e_eom_boot_connection_check, NULL);
-
-   E_LIST_HANDLER_APPEND(g_eom->handlers, E_EVENT_CLIENT_BUFFER_CHANGE, _e_eom_cb_client_buffer_change, NULL);
-
    g_eom->output_connect_status_hook = e_output_hook_add(E_OUTPUT_HOOK_CONNECT_STATUS_CHANGE, _e_eom_output_cb_output_connect_status_change, g_eom);
    g_eom->output_mode_changes_hook = e_output_hook_add(E_OUTPUT_HOOK_MODE_CHANGE, _e_eom_output_cb_output_mode_change, g_eom);
    g_eom->output_add_hook = e_output_hook_add(E_OUTPUT_HOOK_ADD, _e_eom_output_cb_output_add, g_eom);
-   g_eom->output_remove_hook = e_output_hook_add(E_OUTPUT_HOOK_REMOVE, _e_eom_output_cb_output_remove, g_eom);
+   g_eom->output_remove_hook = e_output_hook_add(E_OUTPUT_HOOK_REMOVE, _e_eom_output_cb_output_del, g_eom);
+
+   E_LIST_HANDLER_APPEND(g_eom->handlers, E_EVENT_CLIENT_BUFFER_CHANGE, _e_eom_cb_client_buffer_change, g_eom);
 
    return EINA_TRUE;
 
 err:
-   _e_eom_deinit();
+   e_eom_shutdown();
 
    return EINA_FALSE;
 }
 
 EINTERN int
-e_eom_init(void)
+e_eom_shutdown(void)
 {
-   Eina_Bool ret = EINA_FALSE;
+   Ecore_Event_Handler *h = NULL;
 
-   ret = _e_eom_init();
+   if (!g_eom) return 1;
 
-   if (ret == EINA_FALSE)
-     return 0;
+   if (g_eom->handlers)
+     {
+        EINA_LIST_FREE(g_eom->handlers, h)
+          ecore_event_handler_del(h);
+        g_eom->handlers = NULL;
+     }
 
-   return 1;
-}
+   if (g_eom->output_remove_hook)
+     {
+        e_output_hook_del(g_eom->output_remove_hook);
+        g_eom->output_remove_hook = NULL;
+     }
 
-EINTERN int
-e_eom_shutdown(void)
-{
-   if (!g_eom) return 1;
+   if (g_eom->output_add_hook)
+     {
+        e_output_hook_del(g_eom->output_add_hook);
+        g_eom->output_add_hook = NULL;
+     }
+
+   if (g_eom->output_mode_changes_hook)
+     {
+        e_output_hook_del(g_eom->output_mode_changes_hook);
+        g_eom->output_mode_changes_hook = NULL;
+     }
+
+   if (g_eom->output_connect_status_hook)
+     {
+        e_output_hook_del(g_eom->output_connect_status_hook);
+        g_eom->output_connect_status_hook = NULL;
+     }
 
-   _e_eom_deinit();
+   _e_eom_output_deinit();
+
+   if (g_eom->global)
+     wl_global_destroy(g_eom->global);
+   g_eom->global = NULL;
+
+   E_FREE(g_eom);
 
    return 1;
 }
@@ -2530,8 +1097,7 @@ e_eom_is_ec_external(E_Client *ec)
    if (!g_eom) return EINA_FALSE;
 
    eom_output = _e_eom_output_by_ec_child_get(ec);
-   if (!eom_output)
-     return EINA_FALSE;
+   if (!eom_output) return EINA_FALSE;
 
    return EINA_TRUE;
 }
\ No newline at end of file
index 0f5761d59aee40133e8d216cd626e30a2a1f61ae..a813851899cc092cb3daa207d85fa46c67782705 100644 (file)
@@ -4,10 +4,8 @@
 #ifndef E_COMP_WL_EOM_H
 #define E_COMP_WL_EOM_H
 
-#include <tdm.h>
-
-EINTERN int e_eom_init(void);
-EINTERN int e_eom_shutdown(void);
+EINTERN Eina_Bool e_eom_init(void);
+EINTERN int       e_eom_shutdown(void);
 
 E_API   Eina_Bool e_eom_is_ec_external(E_Client *ec);
 
index 11f95bbda5a9bd9d09c7b13066d914ca3309e488..37fe385464b2edf8fbc346fa1da1840041ce3b41 100644 (file)
@@ -121,8 +121,10 @@ struct _E_Hwc
    /* external output */
    Eina_Rectangle       mirror_rect;
    E_Hwc               *mirror_src_hwc;
+   tbm_surface_h        mirror_src_tsurface;
    Eina_List           *mirror_dst_hwc;
-   E_Output_Display_Mode    display_mode;
+   tbm_surface_h        presentation_tsurface;
+   E_Hwc_Window        *presentation_hwc_window;
 
    int                  norender;
 
index 1e91ed3aba5b5c446f6e65a2f4d3054ea7b8b674..8da83ffda72f43fce2e523a84bc439f06a361847 100644 (file)
@@ -759,3 +759,179 @@ e_hwc_planes_apply(E_Hwc *hwc)
    else
      _e_hwc_planes_changed(hwc);
 }
+
+EINTERN Eina_Bool
+e_hwc_planes_mirror_set(E_Hwc *hwc, E_Hwc *src_hwc, Eina_Rectangle *rect)
+{
+   E_Output *output, *src_output;
+   E_Plane *ep;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(src_hwc, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(rect, EINA_FALSE);
+
+   ELOGF("HWC-PLNS", "e_hwc_planes_mirror_set. rect(%d,%d)(%d,%d)", NULL,
+         rect->x, rect->y, rect->w, rect->h);
+
+   output = hwc->output;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
+
+   src_output = src_hwc->output;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(src_output, EINA_FALSE);
+
+   ep = e_output_fb_target_get(output);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ep, EINA_FALSE);
+
+   ep->output_primary = src_output;
+   if (!e_plane_external_set(ep, rect, E_OUTPUT_DISPLAY_MODE_MIRROR))
+      {
+         ERR("e_plane_mirror_set failed.");
+         return EINA_FALSE;
+      }
+
+   /* add mirror_src to the hwc*/
+   hwc->mirror_src_hwc = src_hwc;
+
+   /* add mirror_dst list to the src_hwc */
+   src_hwc->mirror_dst_hwc = eina_list_append(src_hwc->mirror_dst_hwc, hwc);
+
+   /* make the src_hwc be full gl-compositing */
+   e_hwc_deactive_set(src_hwc, EINA_TRUE);
+   //e_comp_hwc_multi_plane_set(EINA_FALSE);
+
+   return EINA_TRUE;
+}
+
+EINTERN void
+e_hwc_planes_mirror_unset(E_Hwc *hwc)
+{
+   E_Output *output;
+   E_Hwc *src_hwc;
+   E_Plane *ep = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN(hwc);
+
+   output = hwc->output;
+   EINA_SAFETY_ON_NULL_RETURN(output);
+
+   src_hwc = hwc->mirror_src_hwc;
+   EINA_SAFETY_ON_NULL_RETURN(src_hwc);
+
+   ep = e_output_fb_target_get(output);
+   EINA_SAFETY_ON_NULL_RETURN(ep);
+
+   e_plane_external_unset(ep);
+
+   /* remove mirror_dst list at the src_hwc */
+   src_hwc->mirror_dst_hwc = eina_list_remove(src_hwc->mirror_dst_hwc, hwc);
+
+   /* remove mirror_src at the hwc */
+   hwc->mirror_src_hwc = NULL;
+
+   e_hwc_deactive_set(src_hwc, EINA_FALSE);
+   //e_comp_hwc_multi_plane_set(EINA_TRUEE);
+
+   ELOGF("HWC-PLNS", "e_hwc_planes_mirror_unset", NULL);
+}
+
+EINTERN Eina_Bool
+e_hwc_planes_presentation_update(E_Hwc *hwc, E_Client *ec)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
+
+#if 0
+   if (overlay)
+     {
+        Eina_Bool video_layer = EINA_FALSE;
+        tbm_format format;
+        Eina_Bool need_pp = EINA_FALSE;
+
+        E_EomBufferPtr eom_buff = _e_eom_buffer_create(eom_output, wl_buffer);
+        EINA_SAFETY_ON_NULL_RETURN_VAL(eom_buff, ECORE_CALLBACK_PASS_ON);
+
+        format = tbm_surface_get_format(tbm_buffer);
+        video_layer = _e_eom_output_video_layer_find(eom_output, format);
+        if (!video_layer)
+          {
+             /* need pp */
+             need_pp = EINA_TRUE;
+             eom_output->need_overlay_pp = EINA_TRUE;
+             if (!_e_eom_pp_init(eom_output))
+               {
+                  EOERR("pp_init for overlay fail", eom_output->eout);
+                  _e_eom_buffer_destroy(eom_output, eom_buff);
+                  return ECORE_CALLBACK_PASS_ON;
+               }
+          }
+
+        if (need_pp)
+          {
+             if (eom_trace_debug)
+               EOINF("run _e_eom_presentation_pp_run", eom_output->eout);
+             _e_eom_presentation_pp_run(eom_output, tbm_buffer, eom_buff);
+          }
+        else
+          {
+             if (eom_trace_debug)
+               EOINF("run direct show", eom_output->eout);
+             _e_eom_layer_overlay_set(eom_output, tbm_buffer);
+
+             if (!_e_eom_output_show(eom_output, tbm_buffer, _e_eom_tbm_buffer_release_ext_mod, eom_buff))
+               {
+                  if (eom_trace_debug)
+                    {
+                       EOINF("===============>  EXT ENDERR  tbm_buff:%p", eom_output->eout, tbm_buffer);
+                       EOINF("_e_eom_add_buff_to_show fail tbm_buff:%p", eom_output->eout, tbm_buffer);
+                    }
+                  _e_eom_buffer_destroy(eom_output, eom_buff);
+                  return ECORE_CALLBACK_PASS_ON;
+               }
+          }
+     }
+   else
+     {
+        E_Plane *ep = NULL;
+
+        ep = e_output_default_fb_target_get(eom_output->eout);
+
+        if (ep->prepare_ec)
+          e_plane_ec_set(ep, ec);
+
+        e_comp_object_hwc_update_set(ec->frame, EINA_TRUE);
+     }
+#endif
+
+   return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_hwc_planes_external_commit(E_Hwc *hwc)
+{
+   E_Output *output;
+   E_Plane *plane = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
+
+   output = hwc->output;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc->output, EINA_FALSE);
+
+   /* external commit only primary */
+   plane = e_output_fb_target_get(output);
+
+   /* external commit */
+   if (e_output_dpms_get(output))
+     return EINA_TRUE;
+
+   if (!e_plane_external_fetch(plane))
+     return EINA_TRUE;
+
+   if (!e_plane_external_commit(plane))
+     {
+        ERR("fail to e_plane_ex_commit");
+        return EINA_FALSE;
+     }
+
+   return EINA_TRUE;
+}
+
index 11217d22d621c3c4f10a3d6acb19acc463d02a70..7546908a9f0a71d1aa46b13ad029447bc9ff266f 100644 (file)
@@ -14,5 +14,10 @@ EINTERN void                 e_hwc_planes_apply(E_Hwc *hwc);
 EINTERN void                 e_hwc_planes_multi_plane_set(E_Hwc *hwc, Eina_Bool set);
 EINTERN Eina_Bool            e_hwc_planes_multi_plane_get(E_Hwc *hwc);
 
+EINTERN Eina_Bool            e_hwc_planes_mirror_set(E_Hwc *hwc, E_Hwc *src_hwc, Eina_Rectangle *rect);
+EINTERN void                 e_hwc_planes_mirror_unset(E_Hwc *hwc);
+EINTERN Eina_Bool            e_hwc_planes_presentation_update(E_Hwc *hwc, E_Client *ec);
+EINTERN Eina_Bool            e_hwc_planes_external_commit(E_Hwc *hwc);
+
 #endif
 #endif
index 1e63621c80afa4d239d295fd7f47030030c98de9..95ede75a08f88a0d6f3b9382bf56e845e32c5d9a 100644 (file)
@@ -2,7 +2,9 @@
 #include "services/e_service_quickpanel.h"
 # include <Evas_Engine_GL_Tbm.h>
 # include <Evas_Engine_Software_Tbm.h>
+# include <wayland-tbm-server.h>
 # include <sys/eventfd.h>
+# include <pixman.h>
 
 #define DBG_EVALUATE 1
 
@@ -902,6 +904,7 @@ _e_hwc_windows_target_window_new(E_Hwc *hwc)
       !strcmp("gl_tbm_ES", name))
      {
         ecore_evas_manual_render_set(hwc->ee, 1);
+        ecore_evas_show(hwc->ee);
      }
 
    target_hwc_window = E_OBJECT_ALLOC(E_Hwc_Window_Target, E_HWC_WINDOW_TYPE, _e_hwc_windows_target_window_free);
@@ -2548,37 +2551,44 @@ e_hwc_windows_zoom_set(E_Hwc *hwc, Eina_Rectangle *rect)
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
 
-   if ((hwc->pp_rect.x == rect->x) &&
-       (hwc->pp_rect.y == rect->y) &&
-       (hwc->pp_rect.w == rect->w) &&
-       (hwc->pp_rect.h == rect->h))
+   if ((hwc->pp_rect.x == rect->x) && (hwc->pp_rect.y == rect->y) &&
+       (hwc->pp_rect.w == rect->w) && (hwc->pp_rect.h == rect->h))
      return EINA_TRUE;
 
    e_comp_screen = e_comp->e_comp_screen;
    e_output_size_get(hwc->output, &w, &h);
 
-   if (!hwc->tpp)
+   if (e_comp_screen_pp_support())
      {
-        hwc->tpp = tdm_display_create_pp(e_comp_screen->tdisplay, &ret);
-        if (ret != TDM_ERROR_NONE)
+        if (!hwc->tpp)
           {
-             EHWSERR("fail tdm pp create", hwc);
-             goto fail;
-          }
+             hwc->tpp = tdm_display_create_pp(e_comp_screen->tdisplay, &ret);
+             if (ret != TDM_ERROR_NONE)
+               {
+                  EHWSERR("fail tdm pp create", hwc);
+                  goto fail;
+               }
 
-        ret = tdm_pp_set_done_handler(hwc->tpp, _e_hwc_windows_pp_commit_handler, hwc);
-        EINA_SAFETY_ON_FALSE_GOTO(ret == TDM_ERROR_NONE, fail);
-     }
+             ret = tdm_pp_set_done_handler(hwc->tpp, _e_hwc_windows_pp_commit_handler, hwc);
+             EINA_SAFETY_ON_FALSE_GOTO(ret == TDM_ERROR_NONE, fail);
+          }
 
-   if (!hwc->pp_tqueue)
-     {
-        //TODO: Does e20 get the buffer flags from the tdm backend?
-        hwc->pp_tqueue = tbm_surface_queue_create(3, w, h, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
         if (!hwc->pp_tqueue)
           {
-             EHWSERR("fail tbm_surface_queue_create", hwc);
-             goto fail;
+             //TODO: Does e20 get the buffer flags from the tdm backend?
+             hwc->pp_tqueue = tbm_surface_queue_create(3, w, h, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
+             if (!hwc->pp_tqueue)
+               {
+                  EHWSERR("fail tbm_surface_queue_create", hwc);
+                  goto fail;
+               }
           }
+
+        hwc->pp_set = EINA_TRUE;
+        hwc->pp_set_info = EINA_TRUE;
+        hwc->pp_unset = EINA_FALSE;
+        hwc->pp_hwc_window = NULL;
+        hwc->target_hwc_window->skip_surface_set = EINA_TRUE;
      }
 
    hwc->pp_rect.x = rect->x;
@@ -2586,12 +2596,6 @@ e_hwc_windows_zoom_set(E_Hwc *hwc, Eina_Rectangle *rect)
    hwc->pp_rect.w = rect->w;
    hwc->pp_rect.h = rect->h;
 
-   hwc->pp_set = EINA_TRUE;
-   hwc->target_hwc_window->skip_surface_set = EINA_TRUE;
-   hwc->pp_set_info = EINA_TRUE;
-   hwc->pp_unset = EINA_FALSE;
-   hwc->pp_hwc_window = NULL;
-
    /* to wake up main loop */
    uint64_t value = 1;
    if (write(hwc->target_hwc_window->event_fd, &value, sizeof(value)) < 0)
@@ -2614,39 +2618,42 @@ e_hwc_windows_zoom_unset(E_Hwc *hwc)
 {
    EINA_SAFETY_ON_NULL_RETURN(hwc);
 
-   hwc->pp_set_info = EINA_FALSE;
-   hwc->target_hwc_window->skip_surface_set = EINA_FALSE;
-   hwc->pp_set = EINA_FALSE;
-   hwc->pp_hwc_window = NULL;
-   hwc->pp_unset = EINA_TRUE;
-
    hwc->pp_rect.x = 0;
    hwc->pp_rect.y = 0;
    hwc->pp_rect.w = 0;
    hwc->pp_rect.h = 0;
 
-   _e_hwc_windows_pp_pending_data_remove(hwc);
+   if (e_comp_screen_pp_support())
+     {
+        hwc->target_hwc_window->skip_surface_set = EINA_FALSE;
+        hwc->pp_set_info = EINA_FALSE;
+        hwc->pp_set = EINA_FALSE;
+        hwc->pp_hwc_window = NULL;
+        hwc->pp_unset = EINA_TRUE;
 
-   if (hwc->pp_tsurface)
-     tbm_surface_queue_release(hwc->pp_tqueue, hwc->pp_tsurface);
+        _e_hwc_windows_pp_pending_data_remove(hwc);
 
-   if (hwc->pp_tqueue)
-     {
-        tbm_surface_queue_destroy(hwc->pp_tqueue);
-        hwc->pp_tqueue = NULL;
-     }
+        if (hwc->pp_tsurface)
+          tbm_surface_queue_release(hwc->pp_tqueue, hwc->pp_tsurface);
 
-   if (!hwc->pp_commit)
-     {
-        if (hwc->tpp)
+        if (hwc->pp_tqueue)
           {
-             tdm_pp_destroy(hwc->tpp);
-             hwc->tpp = NULL;
+             tbm_surface_queue_destroy(hwc->pp_tqueue);
+             hwc->pp_tqueue = NULL;
           }
-     }
 
-   if (hwc->pp_output_commit_data)
-     hwc->wait_commit = EINA_TRUE;
+        if (!hwc->pp_commit)
+          {
+             if (hwc->tpp)
+               {
+                  tdm_pp_destroy(hwc->tpp);
+                  hwc->tpp = NULL;
+               }
+          }
+
+        if (hwc->pp_output_commit_data)
+          hwc->wait_commit = EINA_TRUE;
+     }
 
    /* to wake up main loop */
    uint64_t value = 1;
@@ -2903,14 +2910,20 @@ EINTERN Eina_Bool
 e_hwc_windows_mirror_set(E_Hwc *hwc, E_Hwc *src_hwc, Eina_Rectangle *rect)
 {
    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(src_hwc, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(rect, EINA_FALSE);
 
-   EHWSTRACE("e_hwc_windows_mirror_set. rect(%d,%d)(%d,%d)",
-             NULL, hwc, rect->x, rect->y, rect->w, rect->h);
+   EHWSINF("e_hwc_windows_mirror_set. rect(%d,%d)(%d,%d)",
+           NULL, hwc, rect->x, rect->y, rect->w, rect->h);
 
-   hwc->mirror_rect.x = rect->x;
-   hwc->mirror_rect.y = rect->y;
-   hwc->mirror_rect.w = rect->w;
-   hwc->mirror_rect.h = rect->h;
+   hwc->mirror_src_tsurface = NULL;
+
+   /* set the zoom to the hwc. */
+   if (!e_hwc_windows_zoom_set(hwc, rect))
+     {
+        EHWSERR("e_hwc_windows_zoom_set failed.", hwc);
+        return EINA_FALSE;
+     }
 
    /* add mirror_src to the hwc*/
    hwc->mirror_src_hwc = src_hwc;
@@ -2918,8 +2931,6 @@ e_hwc_windows_mirror_set(E_Hwc *hwc, E_Hwc *src_hwc, Eina_Rectangle *rect)
    /* add mirror_dst list to the src_hwc */
    src_hwc->mirror_dst_hwc = eina_list_append(src_hwc->mirror_dst_hwc, hwc);
 
-   hwc->display_mode = E_OUTPUT_DISPLAY_MODE_MIRROR;
-
    /* make the src_hwc be full gl-compositing */
    e_hwc_deactive_set(src_hwc, EINA_TRUE);
 
@@ -2938,7 +2949,8 @@ e_hwc_windows_mirror_unset(E_Hwc *hwc)
 
    e_hwc_deactive_set(src_hwc, EINA_FALSE);
 
-   hwc->display_mode = E_OUTPUT_DISPLAY_MODE_NONE;
+   /* unset the zoom. */
+   e_hwc_windows_zoom_unset(hwc);
 
    /* remove mirror_dst list at the src_hwc */
    src_hwc->mirror_dst_hwc = eina_list_remove(src_hwc->mirror_dst_hwc, hwc);
@@ -2946,10 +2958,338 @@ e_hwc_windows_mirror_unset(E_Hwc *hwc)
    /* remove mirror_src at the hwc */
    hwc->mirror_src_hwc = NULL;
 
-   hwc->mirror_rect.x = 0;
-   hwc->mirror_rect.y = 0;
-   hwc->mirror_rect.w = 0;
-   hwc->mirror_rect.h = 0;
+   hwc->mirror_src_tsurface = NULL;
+
+   EHWSINF("e_hwc_windows_mirror_unset", NULL, hwc);
+}
+
+EINTERN Eina_Bool
+e_hwc_windows_presentation_update(E_Hwc *hwc, E_Client *ec)
+{
+   E_Comp_Wl_Buffer *wl_buffer = NULL;
+   tbm_surface_h tsurface = NULL;
+   E_Hwc_Window *hwc_window = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
+
+   if (ec)
+     {
+        if (!hwc->presentation_hwc_window)
+          {
+             /* create the hwc_window on the external hwc. */
+             hwc->presentation_hwc_window = e_hwc_window_new(hwc, ec, E_HWC_WINDOW_STATE_DEVICE);
+             EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+             // TODO: deal with the video
+          }
+
+        /* update the target_buffer */
+        wl_buffer = e_pixmap_resource_get(ec->pixmap);
+        EINA_SAFETY_ON_NULL_RETURN_VAL(wl_buffer, EINA_FALSE);
+        EINA_SAFETY_ON_NULL_RETURN_VAL(wl_buffer->resource, EINA_FALSE);
+
+        tsurface = wayland_tbm_server_get_surface(e_comp->wl_comp_data->tbm.server, wl_buffer->resource);
+        EINA_SAFETY_ON_NULL_RETURN_VAL(tsurface, EINA_FALSE);
+
+        hwc->presentation_tsurface = tsurface;
+     }
+   else
+     {
+        hwc->presentation_tsurface = NULL;
+
+        if (hwc->presentation_hwc_window)
+          {
+             e_hwc_window_free(hwc_window);
+             hwc->presentation_hwc_window = NULL;
+          }
+     }
+
+   return EINA_TRUE;
+}
+
+static void
+_e_hwc_windows_pixman_copy(E_Hwc *hwc, tbm_surface_h src_tsurface, tbm_surface_h dst_tsurface)
+{
+   pixman_image_t *src_img = NULL, *dst_img = NULL;
+   pixman_format_code_t src_format, dst_format;
+   double scale_x, scale_y;
+   pixman_transform_t t;
+   struct pixman_f_transform ft;
+   tbm_surface_info_s src_tinfo = {0};
+   tbm_surface_info_s dst_tinfo = {0};
+   int ret = TBM_SURFACE_ERROR_NONE;
+
+   ret = tbm_surface_map(src_tsurface, TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE, &src_tinfo);
+   if (ret != TBM_SURFACE_ERROR_NONE)
+     {
+        EHWSERR("tbm_surface_map fails on src_tsurface.", hwc);
+        goto end;
+     }
+
+   ret = tbm_surface_map(dst_tsurface, TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE, &dst_tinfo);
+   if (ret != TBM_SURFACE_ERROR_NONE)
+     {
+        EHWSERR("tbm_surface_map fails on dst_tsurface.", hwc);
+        goto src_unmap;
+     }
+
+   src_format = PIXMAN_a8r8g8b8;
+   dst_format = PIXMAN_a8r8g8b8;
+
+   src_img = pixman_image_create_bits(src_format, src_tinfo.width, src_tinfo.height,
+                                      (uint32_t*)src_tinfo.planes[0].ptr,
+                                      src_tinfo.planes[0].stride);
+   EINA_SAFETY_ON_NULL_GOTO(src_img, free_img);
+
+   dst_img = pixman_image_create_bits(dst_format, dst_tinfo.width, dst_tinfo.height,
+                                      (uint32_t*)dst_tinfo.planes[0].ptr,
+                                      dst_tinfo.planes[0].stride);
+   EINA_SAFETY_ON_NULL_GOTO(dst_img, free_img);
+
+   if (dst_tinfo.width > 0)
+     scale_x = (double)src_tinfo.width / dst_tinfo.width;
+   else
+     scale_x = (double)src_tinfo.width;
+
+   if (dst_tinfo.height > 0)
+     scale_y = (double)src_tinfo.height / dst_tinfo.height;
+   else
+     scale_y = (double)src_tinfo.height;
+
+   pixman_f_transform_init_identity(&ft);
+
+   pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
+   pixman_f_transform_translate(&ft, NULL, 0, 0);
+   pixman_transform_from_pixman_f_transform(&t, &ft);
+   pixman_image_set_transform(src_img, &t);
+
+   pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img, 0, 0, 0, 0,
+                          0, 0, dst_tinfo.width, dst_tinfo.height);
+
+free_img:
+   if (src_img) pixman_image_unref(src_img);
+   if (dst_img) pixman_image_unref(dst_img);
+
+   tbm_surface_unmap(dst_tsurface);
+src_unmap:
+   tbm_surface_unmap(src_tsurface);
+end:
+   return;
+}
+
+static Eina_Bool
+_e_hwc_windows_mirror_changes_update(E_Hwc *hwc)
+{
+   E_Hwc *mirror_src_hwc;
+   E_Hwc_Window_Target *target_hwc_window, *src_target_hwc_window;
+   tbm_surface_h target_tsurface, src_target_tsurface;
+   E_Hwc_Window_Queue *queue;
+   E_Hwc_Window_Queue_Buffer *queue_buffer = NULL;
+
+   mirror_src_hwc = hwc->mirror_src_hwc;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(mirror_src_hwc, EINA_FALSE);
+
+   target_hwc_window = hwc->target_hwc_window;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
+
+   src_target_hwc_window = mirror_src_hwc->target_hwc_window;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(src_target_hwc_window, EINA_FALSE);
+
+   target_tsurface = target_hwc_window->hwc_window.buffer.tsurface;
+   src_target_tsurface = src_target_hwc_window->hwc_window.buffer.tsurface;
+
+   if (hwc->mirror_src_tsurface == src_target_tsurface) return EINA_FALSE;
+
+   if (hwc->pp_set)
+     { // TODO: mirror with pp
+       ;
+     }
+   else
+     {  // mirror with sw copy fallback
+        queue = ((E_Hwc_Window *)target_hwc_window)->queue;
+        EINA_SAFETY_ON_NULL_RETURN_VAL(queue, EINA_FALSE);
+
+        /* dequeue buffer */
+        queue_buffer = e_hwc_window_queue_buffer_dequeue(queue);
+        EINA_SAFETY_ON_NULL_RETURN_VAL(queue_buffer, EINA_FALSE);
+
+        /* copy */
+        target_tsurface = queue_buffer->tsurface;
+        _e_hwc_windows_pixman_copy(hwc, src_target_tsurface, target_tsurface);
+
+        /* enqueue buffer */
+        e_hwc_window_queue_buffer_enqueue(queue, queue_buffer);
+
+        /* fetch the buffer */
+        _e_hwc_windows_target_buffer_fetch(hwc, EINA_TRUE);
+     }
+
+   hwc->mirror_src_tsurface = src_target_tsurface;
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_hwc_windows_presentation_changes_update(E_Hwc *hwc)
+{
+   /* set buffer */
+   if (!e_hwc_window_buffer_fetch(hwc->presentation_hwc_window, EINA_TRUE))
+     return EINA_FALSE;
+
+   e_hwc_window_zpos_set(hwc->presentation_hwc_window, 0);
+   e_hwc_window_state_set(hwc->presentation_hwc_window, E_HWC_WINDOW_STATE_DEVICE, EINA_TRUE);
+   e_hwc_window_info_update(hwc->presentation_hwc_window);
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_hwc_windows_presentation_evaluation_check(E_Hwc *hwc)
+{
+   E_Hwc_Window_State state;
+   E_Hwc_Window_Target *target_hwc_window;
+   tbm_surface_h target_tsurface, src_tsurface;
+   E_Hwc_Window_Queue *queue;
+   E_Hwc_Window_Queue_Buffer *queue_buffer = NULL;
+
+   /* check if the window has the devcie type. */
+   state = e_hwc_window_state_get(hwc->presentation_hwc_window);
+   if (state == E_HWC_WINDOW_STATE_DEVICE) return EINA_TRUE;
+
+   /* copy the presentation_hwc_window to the target_window. */
+   target_hwc_window = hwc->target_hwc_window;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
+
+   target_tsurface = target_hwc_window->hwc_window.buffer.tsurface;
+
+   queue = ((E_Hwc_Window *)target_hwc_window)->queue;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(queue, EINA_FALSE);
+
+   /* dequeue buffer */
+   queue_buffer = e_hwc_window_queue_buffer_dequeue(queue);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(queue_buffer, EINA_FALSE);
+
+   /* copy */
+   src_tsurface = hwc->presentation_hwc_window->buffer.tsurface;
+   target_tsurface = queue_buffer->tsurface;
+   _e_hwc_windows_pixman_copy(hwc, src_tsurface, target_tsurface);
+
+   /* enqueue buffer */
+   e_hwc_window_queue_buffer_enqueue(queue, queue_buffer);
+
+   /* fetch the buffer */
+   _e_hwc_windows_target_buffer_fetch(hwc, EINA_TRUE);
+
+   return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_hwc_windows_external_commit(E_Hwc *hwc, E_Output_Display_Mode display_mode)
+{
+   E_Output *output = NULL;
+   tdm_error error = TDM_ERROR_NONE;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
+
+   output = hwc->output;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
+
+   if (hwc->wait_commit) return EINA_TRUE;
+
+   /* set the target_buffer if the output need to update */
+#if 1
+  if (display_mode == E_OUTPUT_DISPLAY_MODE_MIRROR)
+    {
+       if (!_e_hwc_windows_mirror_changes_update(hwc))
+         return EINA_TRUE;
+
+       if (!_e_hwc_windows_evaluate(hwc))
+         return EINA_TRUE;
+    }
+  else if (display_mode == E_OUTPUT_DISPLAY_MODE_PRESENTATION)
+    {
+       if (!_e_hwc_windows_presentation_changes_update(hwc))
+         return EINA_TRUE;
+
+       if (!_e_hwc_windows_evaluate(hwc))
+         return EINA_TRUE;
+
+       /* if the presentation window is client type. copy it on the target window. */
+       if (!_e_hwc_windows_presentation_evaluation_check(hwc))
+         return EINA_TRUE;
+    }
+  else
+    {
+       EHWSERR("Unknown display_mode : %d", hwc, display_mode);
+       goto fail;
+    }
+#else
+   if (!_e_hwc_windows_changes_update(hwc))
+     return EINA_TRUE;
+
+   if (!_e_hwc_windows_evaluate(hwc))
+     return EINA_TRUE;
+#endif
+
+   if (e_hwc_norender_get(hwc) > 0)
+     {
+        EHWSTRACE(" Block Display... NoRender get.", NULL, hwc);
+        return EINA_TRUE;
+     }
+
+   if (hwc->hwc_mode != E_HWC_MODE_FULL) {
+     if (!_e_hwc_windows_target_buffer_prepared(hwc))
+       return EINA_TRUE;
+   }
 
-   EHWSTRACE("e_hwc_windows_mirror_unset", NULL, hwc);
+   if ((output->dpms == E_OUTPUT_DPMS_OFF) || (output->fake_config))
+     {
+        _e_hwc_windows_offscreen_commit(hwc);
+        return EINA_TRUE;
+     }
+
+   if (hwc->pp_set)
+     {
+        if (_e_hwc_windos_pp_pending_window_check(hwc))
+          return EINA_TRUE;
+     }
+
+   if (!_e_hwc_windows_commit_data_acquire(hwc))
+     return EINA_TRUE;
+
+   if (hwc->pp_unset)
+     hwc->pp_unset = EINA_FALSE;
+
+   if (hwc->pp_set)
+     {
+        e_output_zoom_rotating_check(output);
+        _e_hwc_windows_update_fps(hwc);
+        if (!_e_hwc_windows_pp_commit(hwc))
+          {
+            EHWSERR("_e_hwc_windows_pp_commit failed.", hwc);
+            goto fail;
+          }
+     }
+   else
+     {
+        EHWSTRACE("!!!!!!!! HWC Commit !!!!!!!!", NULL, hwc);
+        _e_hwc_windows_update_fps(hwc);
+
+        hwc->wait_commit = EINA_TRUE;
+
+        error = tdm_hwc_commit(hwc->thwc, 0, _e_hwc_windows_commit_handler, hwc);
+        if (error != TDM_ERROR_NONE)
+          {
+             EHWSERR("tdm_hwc_commit failed.", hwc);
+             _e_hwc_windows_commit_handler(hwc->thwc, 0, 0, 0, hwc);
+             goto fail;
+          }
+     }
+
+   return EINA_TRUE;
+
+fail:
+   hwc->wait_commit = EINA_FALSE;
+
+   return EINA_FALSE;
 }
+
index a9137112febfbf71567983a825ef9e0b1e79ac16..43050b9721b11e063f9b19b22969acfc6cb1bcb2 100644 (file)
@@ -38,6 +38,8 @@ EINTERN void                 e_hwc_windows_debug_info_get(Eldbus_Message_Iter *i
 
 EINTERN Eina_Bool            e_hwc_windows_mirror_set(E_Hwc *hwc, E_Hwc *src_hwc, Eina_Rectangle *rect);
 EINTERN void                 e_hwc_windows_mirror_unset(E_Hwc *hwc);
+EINTERN Eina_Bool            e_hwc_windows_presentation_update(E_Hwc *hwc, E_Client *ec);
+EINTERN Eina_Bool            e_hwc_windows_external_commit(E_Hwc *hwc, E_Output_Display_Mode display_mode);
 
 #endif
 #endif
index edff50d4eba3b921b1857bcdbff6f202b9d2259f..eac47c7c21fbfe6260dcd8cf50c4971735bfc2cc 100644 (file)
@@ -25,6 +25,8 @@
    while (0)
 
 #define DUMP_FPS 30
+#define OUTPUT_DELAY_CONNECT_CHECK_TIMEOUT 3.0
+#define OUTPUT_DELAY_CHECK_TIMEOUT 1.0
 
 typedef struct _E_Output_Capture E_Output_Capture;
 typedef struct _E_Output_Layer E_Output_Layer;
@@ -73,6 +75,68 @@ static Eina_Bool _e_output_capture(E_Output *output, tbm_surface_h tsurface, Ein
 static void _e_output_vblank_handler(tdm_output *output, unsigned int sequence,
                                      unsigned int tv_sec, unsigned int tv_usec, void *data);
 
+static unsigned int
+_e_output_aligned_width_get(E_Output *output, tbm_surface_h tsurface)
+{
+   unsigned int aligned_width = 0;
+   tbm_surface_info_s surf_info;
+
+   tbm_surface_get_info(tsurface, &surf_info);
+
+   switch (surf_info.format)
+     {
+      case TBM_FORMAT_YUV420:
+      case TBM_FORMAT_YVU420:
+      case TBM_FORMAT_YUV422:
+      case TBM_FORMAT_YVU422:
+      case TBM_FORMAT_NV12:
+      case TBM_FORMAT_NV21:
+        aligned_width = surf_info.planes[0].stride;
+        break;
+      case TBM_FORMAT_YUYV:
+      case TBM_FORMAT_UYVY:
+        aligned_width = surf_info.planes[0].stride >> 1;
+        break;
+      case TBM_FORMAT_ARGB8888:
+      case TBM_FORMAT_XRGB8888:
+        aligned_width = surf_info.planes[0].stride >> 2;
+        break;
+      default:
+        EOERR("not supported format: %x", output, surf_info.format);
+     }
+
+   return aligned_width;
+}
+
+static Eina_Bool
+_e_output_presentation_check(void *data)
+{
+   E_Output *output;
+   E_Output *primary_output;
+
+   if (!data) return ECORE_CALLBACK_CANCEL;
+
+   output = (E_Output *)data;
+
+   if (e_output_display_mode_get(output) == E_OUTPUT_DISPLAY_MODE_WAIT_PRESENTATION)
+     {
+        primary_output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
+        e_output_mirror_set(output, primary_output);
+     }
+
+   output->delay_timer = NULL;
+
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static inline void
+_e_output_display_mode_set(E_Output *output, E_Output_Display_Mode display_mode)
+{
+   if (output == NULL) return;
+   if (output->display_mode == display_mode) return;
+
+   output->display_mode = display_mode;
+}
 
 static void
 _e_output_hooks_clean(void)
@@ -704,6 +768,71 @@ _e_output_client_resize(int w, int h)
      }
 }
 
+static Eina_Bool
+_e_output_external_connect_display_set(E_Output *output)
+{
+   E_Output *primary_output = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
+
+   if (e_output_display_mode_get(output) == E_OUTPUT_DISPLAY_MODE_WAIT_PRESENTATION)
+     {
+        EOINF("Start Wait Presentation", output);
+
+        /* the fallback timer for not setting the presentation. */
+        if (output->delay_timer) ecore_timer_del(output->delay_timer);
+        output->delay_timer = ecore_timer_add(OUTPUT_DELAY_CONNECT_CHECK_TIMEOUT, _e_output_presentation_check, output);
+     }
+   else
+     {
+        EOINF("Start Mirroring", output);
+
+        primary_output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
+        if (!e_output_mirror_set(output, primary_output))
+          {
+             EOERR("e_output_mirror_set fails.", output);
+             return EINA_FALSE;
+          }
+     }
+
+   EOINF("_e_output_external_connect_display_set done: display_mode:%d", output, e_output_display_mode_get(output));
+
+   return EINA_TRUE;
+}
+
+static void
+_e_output_external_disconnect_display_set(E_Output *output)
+{
+   EINA_SAFETY_ON_NULL_RETURN(output);
+
+   switch (e_output_display_mode_get(output))
+     {
+      case E_OUTPUT_DISPLAY_MODE_NONE:
+        break;
+      case E_OUTPUT_DISPLAY_MODE_MIRROR:
+        /* unset mirror */
+        e_output_mirror_unset(output);
+        break;
+      case E_OUTPUT_DISPLAY_MODE_PRESENTATION:
+        /* only change the display_mode */
+        _e_output_display_mode_set(output, E_OUTPUT_DISPLAY_MODE_WAIT_PRESENTATION);
+        break;
+      case E_OUTPUT_DISPLAY_MODE_WAIT_PRESENTATION:
+        /* delete presentation_delay_timer */
+        if (output->delay_timer)
+          {
+             ecore_timer_del(output->delay_timer);
+             output->delay_timer = NULL;
+          }
+        break;
+      default:
+        EOERR("unknown display_mode:%d", output, output->display_mode);
+        break;
+     }
+
+   EOINF("_e_output_external_disconnect_display_set done.", output);
+}
+
 static void
 _e_output_primary_update(E_Output *output)
 {
@@ -771,6 +900,101 @@ _e_output_primary_update(E_Output *output)
      }
 }
 
+static Eina_Bool
+_e_output_external_update(E_Output *output)
+{
+   E_Comp_Screen *e_comp_screen = NULL;
+   E_Output_Mode *mode = NULL;
+   E_Output *output_pri = NULL;
+   Eina_Bool ret;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
+
+   e_comp_screen = e_comp->e_comp_screen;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, EINA_FALSE);
+
+   output_pri = e_comp_screen_primary_output_get(e_comp_screen);
+   if (!output_pri)
+     {
+        e_error_message_show(_("Fail to get the primary output!\n"));
+        return EINA_FALSE;
+     }
+
+   if (output_pri == output)
+     return EINA_FALSE;
+
+
+   ret = e_output_update(output);
+   if (ret == EINA_FALSE)
+     {
+        EOERR("fail e_output_update.", output);
+        return EINA_FALSE;
+     }
+
+   if (e_output_connected(output))
+     {
+        mode = e_output_best_mode_find(output);
+        if (!mode)
+          {
+             EOERR("fail to get best mode.", output);
+             return EINA_FALSE;
+          }
+
+        ret = e_output_mode_apply(output, mode);
+        if (ret == EINA_FALSE)
+          {
+             EOERR("fail to e_output_mode_apply.", output);
+             return EINA_FALSE;
+          }
+        ret = e_output_dpms_set(output, E_OUTPUT_DPMS_ON);
+        if (ret == EINA_FALSE)
+          {
+             EOERR("fail to e_output_dpms.", output);
+             return EINA_FALSE;
+          }
+
+        ret = e_output_hwc_setup(output);
+        if (ret == EINA_FALSE)
+          {
+             EOERR("fail to e_output_hwc_setup.", output);
+             return EINA_FALSE;
+          }
+
+        _e_output_hook_call(E_OUTPUT_HOOK_CONNECT_STATUS_CHANGE, output);
+
+        ret = _e_output_external_connect_display_set(output);
+        if (ret == EINA_FALSE)
+          {
+             EOERR("fail to _e_output_external_connect_display_set.", output);
+             return EINA_FALSE;
+          }
+
+        EOINF("Connect the external output", output);
+     }
+   else
+     {
+        EOINF("Disconnect the external output", output);
+
+        _e_output_hook_call(E_OUTPUT_HOOK_CONNECT_STATUS_CHANGE, output);
+
+        _e_output_external_disconnect_display_set(output);
+
+        if (output->hwc)
+          {
+             e_hwc_del(output->hwc);
+             output->hwc = NULL;
+          }
+
+        if (!e_output_dpms_set(output, E_OUTPUT_DPMS_OFF))
+          {
+             EOERR("fail to e_output_dpms.", output);
+             return EINA_FALSE;
+          }
+     }
+
+   return EINA_TRUE;
+}
+
 static void
 _e_output_cb_output_change(tdm_output *toutput,
                                   tdm_output_change_type type,
@@ -802,7 +1026,7 @@ _e_output_cb_output_change(tdm_output *toutput,
              if (primary == output)
                _e_output_primary_update(output);
              else
-               e_output_external_update(output);
+               _e_output_external_update(output);
           }
         break;
        case TDM_OUTPUT_CHANGE_DPMS:
@@ -1031,39 +1255,6 @@ _e_output_capture_position_get(E_Output *output, int dst_w, int dst_h, Eina_Rect
    return EINA_TRUE;
 }
 
-static unsigned int
-_e_output_aligned_width_get(E_Output *output, tbm_surface_h tsurface)
-{
-   unsigned int aligned_width = 0;
-   tbm_surface_info_s surf_info;
-
-   tbm_surface_get_info(tsurface, &surf_info);
-
-   switch (surf_info.format)
-     {
-      case TBM_FORMAT_YUV420:
-      case TBM_FORMAT_YVU420:
-      case TBM_FORMAT_YUV422:
-      case TBM_FORMAT_YVU422:
-      case TBM_FORMAT_NV12:
-      case TBM_FORMAT_NV21:
-        aligned_width = surf_info.planes[0].stride;
-        break;
-      case TBM_FORMAT_YUYV:
-      case TBM_FORMAT_UYVY:
-        aligned_width = surf_info.planes[0].stride >> 1;
-        break;
-      case TBM_FORMAT_ARGB8888:
-      case TBM_FORMAT_XRGB8888:
-        aligned_width = surf_info.planes[0].stride >> 2;
-        break;
-      default:
-        EOERR("not supported format: %x", output, surf_info.format);
-     }
-
-   return aligned_width;
-}
-
 static E_Output_Capture *
 _e_output_tdm_stream_capture_find_data(E_Output *output, tbm_surface_h tsurface)
 {
@@ -2099,42 +2290,6 @@ _e_output_external_rect_get(E_Output *output, int src_w, int src_h, int dst_w, i
      _e_output_center_rect_get(src_w, src_h, dst_w, dst_h, rect);
 }
 
-static Eina_Bool
-_e_output_external_commit(E_Output *output)
-{
-   E_Plane *plane = NULL;
-
-   if (!output->external_set) return EINA_TRUE;
-
-   if (e_hwc_policy_get(output->hwc) == E_HWC_POLICY_PLANES)
-     {
-        /* external commit only primary */
-        plane = e_output_fb_target_get(output);
-
-        /* external commit */
-        if (e_output_dpms_get(output))
-          return EINA_TRUE;
-
-        if (!e_plane_external_fetch(plane))
-          return EINA_TRUE;
-
-        if (!e_plane_external_commit(plane))
-          {
-             EOERR("fail to e_plane_ex_commit", output);
-             return EINA_FALSE;
-          }
-     }
-   else
-     {
-        /* TODO: HWC Windows */;
-        /* external commit */
-        if (e_output_dpms_get(output))
-          return EINA_TRUE;
-     }
-
-   return EINA_TRUE;
-}
-
 static Eina_Bool
 _e_output_planes_commit(E_Output *output)
 {
@@ -2369,6 +2524,9 @@ e_output_new(E_Comp_Screen *e_comp_screen, int index)
    if (output_caps & TDM_OUTPUT_CAPABILITY_ASYNC_DPMS)
      output->dpms_async = EINA_TRUE;
 
+   if (output_caps & TDM_OUTPUT_CAPABILITY_MIRROR)
+     output->tdm_mirror = EINA_TRUE;
+
    /* call output add hook */
    _e_output_hook_call(E_OUTPUT_HOOK_ADD, output);
 
@@ -3056,10 +3214,13 @@ e_output_render(E_Output *output)
   return EINA_TRUE;
 }
 
+static int boot_launch = 0;
+
 EINTERN Eina_Bool
 e_output_commit(E_Output *output)
 {
    E_Output *output_primary = NULL;
+   E_Output_Display_Mode display_mode;
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
 
@@ -3086,21 +3247,53 @@ e_output_commit(E_Output *output)
           }
         else
           {
-             if (!_e_output_external_commit(output))
+             display_mode = e_output_display_mode_get(output);
+
+             /* output donot care about the external_commit
+                when tdm has the mirror capability */
+             if (display_mode == E_OUTPUT_DISPLAY_MODE_MIRROR &&
+                 output->tdm_mirror)
+               return EINA_TRUE;
+
+             if (!e_hwc_planes_external_commit(output->hwc))
                {
-                  EOERR("fail _e_output_external_commit", output);
+                  EOERR("fail e_hwc_planes_external_commit", output);
                   return EINA_FALSE;
                }
           }
      }
    else
      {
-        /* commit the only primary output */
-        if (output != output_primary) return EINA_TRUE;
-
-        if (!e_hwc_windows_commit(output->hwc))
+        if (output == output_primary)
           {
-            return EINA_FALSE;
+             if (!e_hwc_windows_commit(output->hwc))
+               {
+                  EOERR("fail e_hwc_windows_commit", output);
+                  return EINA_FALSE;
+               }
+          }
+        else
+          {
+             /* trigger the output_external_update at the launching time */
+             if (!boot_launch)
+               {
+                  boot_launch = 1;
+                  _e_output_external_update(output);
+               }
+
+             display_mode = e_output_display_mode_get(output);
+
+             /* output donot care about the external_commit
+                when tdm has the mirror capability */
+             if (display_mode == E_OUTPUT_DISPLAY_MODE_MIRROR &&
+                 output->tdm_mirror)
+               return EINA_TRUE;
+
+             if (!e_hwc_windows_external_commit(output->hwc, display_mode))
+               {
+                  EOERR("fail e_hwc_windows_external_commit", output);
+                  return EINA_FALSE;
+               }
           }
      }
 
@@ -3798,256 +3991,286 @@ e_output_stream_capture_stop(E_Output *output)
 }
 
 EINTERN Eina_Bool
-e_output_external_set(E_Output *output, E_Output_Display_Mode display_mode)
+e_output_external_mode_change(E_Output *output, E_Output_Mode *mode)
 {
+   E_Output_Mode *emode = NULL, *current_emode = NULL;
+   Eina_List *l;
+   Eina_Bool found = EINA_FALSE;
    E_Output *output_primary = NULL;
    E_Plane *ep = NULL;
    int w, h, p_w, p_h;
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(mode, EINA_FALSE);
 
-   output_primary = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(output_primary, EINA_FALSE);
-   EINA_SAFETY_ON_TRUE_RETURN_VAL(output_primary == output, EINA_FALSE);
+   if (e_output_connected(output) != EINA_TRUE)
+     return EINA_FALSE;
 
-   if (output->display_mode == display_mode)
-     return EINA_TRUE;
-   output->display_mode = display_mode;
+   current_emode = e_output_current_mode_get( output);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(current_emode, EINA_FALSE);
 
-   e_output_size_get(output, &w, &h);
-   e_output_size_get(output_primary, &p_w, &p_h);
+   if (current_emode == mode)
+     return EINA_TRUE;
 
-   if (e_hwc_policy_get(output->hwc) == E_HWC_POLICY_PLANES)
+   EINA_LIST_FOREACH(output->info.modes, l, emode)
      {
-        ep = e_output_fb_target_get(output);
-        EINA_SAFETY_ON_NULL_RETURN_VAL(ep, EINA_FALSE);
-
-        _e_output_external_rect_get(output_primary, p_w, p_h, w, h, &output->zoom_conf.rect);
-
-        e_hwc_planes_multi_plane_set(output_primary->hwc, EINA_FALSE);
-
-        ep->output_primary = output_primary;
-        if (!e_plane_external_set(ep, &output->zoom_conf.rect, display_mode))
+        if (mode == emode)
           {
-             EOERR("e_plane_mirror_set failed.", output);
-             e_hwc_planes_multi_plane_set(output_primary->hwc, EINA_TRUE);
-
-             return EINA_FALSE;
+             found = EINA_TRUE;
+             break;
           }
      }
-   else
-     {
-        /* TODO: HWC Windows */;
-        return EINA_FALSE;
-     }
-
-   output->display_mode = display_mode;
-   output->external_set = EINA_TRUE;
-
-   EOINF("e_output_external_set done: display_mode:%d", output, display_mode);
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(found == EINA_TRUE, EINA_FALSE);
 
-   /* update the ecore_evas */
-   _e_output_force_render_set(output_primary);
+   output_primary = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output_primary, EINA_FALSE);
+   EINA_SAFETY_ON_TRUE_RETURN_VAL(output_primary == output, EINA_FALSE);
 
-   return EINA_TRUE;
-}
+   e_output_size_get(output, &w, &h);
+   e_output_size_get(output_primary, &p_w, &p_h);
 
-EINTERN void
-e_output_external_unset(E_Output *output)
-{
-   E_Output *output_primary = NULL;
-   E_Plane *ep = NULL;
+   e_comp_canvas_norender_push();
 
-   EINA_SAFETY_ON_NULL_RETURN(output);
+   if (e_output_mode_apply(output, mode) == EINA_FALSE)
+     {
+        EOERR("fail to e_output_mode_apply.", output);
+        e_comp_canvas_norender_pop();
+        return EINA_FALSE;
+     }
 
-   output_primary = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
-   EINA_SAFETY_ON_NULL_RETURN(output_primary);
-   EINA_SAFETY_ON_TRUE_RETURN(output_primary == output);
+   _e_output_external_rect_get(output_primary, p_w, p_h, w, h, &output->zoom_conf.rect);
 
-   if (output->display_mode == E_OUTPUT_DISPLAY_MODE_NONE)
-     return;
+   /* call mode change hook */
+   _e_output_hook_call(E_OUTPUT_HOOK_MODE_CHANGE, output);
 
-   output->external_set = EINA_FALSE;
-   output->display_mode = E_OUTPUT_DISPLAY_MODE_NONE;
+   EOINF("mode change output: (%dx%d)", output, w, h);
+   if (e_output_display_mode_get(output) == E_OUTPUT_DISPLAY_MODE_PRESENTATION)
+     {
+        _e_output_display_mode_set(output, E_OUTPUT_DISPLAY_MODE_WAIT_PRESENTATION);
+        if (output->delay_timer) ecore_timer_del(output->delay_timer);
+        output->delay_timer = ecore_timer_add(OUTPUT_DELAY_CONNECT_CHECK_TIMEOUT, _e_output_presentation_check, output);
+     }
 
    if (e_hwc_policy_get(output->hwc) == E_HWC_POLICY_PLANES)
      {
         ep = e_output_fb_target_get(output);
-        EINA_SAFETY_ON_NULL_RETURN(ep);
-
-        e_plane_external_unset(ep);
+        EINA_SAFETY_ON_NULL_RETURN_VAL(ep, EINA_FALSE);
 
-        e_hwc_planes_multi_plane_set(output_primary->hwc, EINA_TRUE);
+        e_plane_external_reset(ep, &output->zoom_conf.rect);
      }
    else
      {
         /* TODO: HWC Windows */;
      }
 
-   output->zoom_conf.rect.x = 0;
-   output->zoom_conf.rect.y = 0;
-   output->zoom_conf.rect.w = 0;
-   output->zoom_conf.rect.h = 0;
+   _e_output_render_update(output_primary);
+   e_comp_canvas_norender_pop();
 
-   /* update the ecore_evas */
-   _e_output_force_render_set(output_primary);
+   EOINF("e_output_external_reset done.(%dx%d)", output, mode->w, mode->h);
 
-   EOINF("e_output_external_unset done.", output);
+   return EINA_TRUE;
 }
 
 EINTERN Eina_Bool
-e_output_external_update(E_Output *output)
+e_output_mirror_set(E_Output *output, E_Output *src_output)
 {
-   E_Comp_Screen *e_comp_screen = NULL;
-   E_Output_Mode *mode = NULL;
-   E_Output *output_pri = NULL;
-   Eina_Bool ret;
+   tdm_error ret;
+   int w, h, p_w, p_h;
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(src_output, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output->hwc, EINA_FALSE);
 
-   e_comp_screen = e_comp->e_comp_screen;
-   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, EINA_FALSE);
-
-   output_pri = e_comp_screen_primary_output_get(e_comp_screen);
-   if (!output_pri)
+   if (output->display_mode == E_OUTPUT_DISPLAY_MODE_MIRROR)
      {
-        e_error_message_show(_("Fail to get the primary output!\n"));
-        return EINA_FALSE;
+        EOINF("Already Set MIRROR_MODE", output);
+        return EINA_TRUE;
      }
 
-   if (output_pri == output)
-     return EINA_FALSE;
-
-
-   ret = e_output_update(output);
-   if (ret == EINA_FALSE)
+   if (output->tdm_mirror)
      {
-        EOERR("fail e_output_update.", output);
-        return EINA_FALSE;
-     }
+        EOINF("TDM supports the output mirroring.", output);
 
-   if (e_output_connected(output))
-     {
-        mode = e_output_best_mode_find(output);
-        if (!mode)
+        ret = tdm_output_set_mirror(output->toutput, src_output->toutput, TDM_TRANSFORM_NORMAL);
+        if (ret != TDM_ERROR_NONE)
           {
-             EOERR("fail to get best mode.", output);
+             EOINF("tdm_output_set_mirror fails.", output);
              return EINA_FALSE;
           }
+     }
+   else
+     {
+        e_output_size_get(output, &w, &h);
+        e_output_size_get(src_output, &p_w, &p_h);
 
-        ret = e_output_mode_apply(output, mode);
-        if (ret == EINA_FALSE)
+        _e_output_external_rect_get(src_output, p_w, p_h, w, h, &output->zoom_conf.rect);
+
+        if (e_hwc_policy_get(output->hwc) == E_HWC_POLICY_PLANES)
           {
-             EOERR("fail to e_output_mode_apply.", output);
-             return EINA_FALSE;
+             if (!e_hwc_planes_mirror_set(output->hwc, src_output->hwc, &output->zoom_conf.rect))
+               {
+                  EOERR("e_hwc_planes_mirror_set failed.", output);
+                  return EINA_FALSE;
+               }
           }
-        ret = e_output_dpms_set(output, E_OUTPUT_DPMS_ON);
-        if (ret == EINA_FALSE)
+        else
           {
-             EOERR("fail to e_output_dpms.", output);
-             return EINA_FALSE;
+             /* set the target_buffer of the src_hwc to the target_buffer of the dst_hwc with zoom rect */
+             if (!e_hwc_windows_mirror_set(output->hwc, src_output->hwc, &output->zoom_conf.rect))
+               {
+                  EOERR("e_hwc_windows_mirror_set failed.", output);
+                  return EINA_FALSE;
+               }
           }
+     }
 
-        ret = e_output_hwc_setup(output);
-        if (ret == EINA_FALSE)
-          {
-             EOERR("fail to e_output_hwc_setup.", output);
-             return EINA_FALSE;
-          }
+   output->mirror_src_output = src_output;
 
-        _e_output_hook_call(E_OUTPUT_HOOK_CONNECT_STATUS_CHANGE, output);
+   _e_output_display_mode_set(output, E_OUTPUT_DISPLAY_MODE_MIRROR);
+   output->external_set = EINA_TRUE;
+
+   /* update the ecore_evas of the src_output */
+   _e_output_force_render_set(src_output);
+
+   EOINF("e_output_mirror_set done: E_OUTPUT_DISPLAY_MODE_MIRROR", output);
+
+   return EINA_TRUE;
+}
+
+EINTERN void
+e_output_mirror_unset(E_Output *output)
+{
+   E_Output *src_output;
+   tdm_error ret;
+
+   EINA_SAFETY_ON_NULL_RETURN(output);
+
+   EOINF("e_output_mirror_unset: E_OUTPUT_DISPLAY_MODE_NONE", output);
+
+   src_output = output->mirror_src_output;
+
+   /* update the ecore_evas of the src_output */
+   _e_output_render_update(src_output);
+
+   output->external_set = EINA_FALSE;
+   _e_output_display_mode_set(output, E_OUTPUT_DISPLAY_MODE_NONE);
+
+   output->mirror_src_output = NULL;
+
+   if (output->tdm_mirror)
+     {
+        ret = tdm_output_unset_mirror(output->toutput);
+        if (ret != TDM_ERROR_NONE)
+          EOERR("tdm_output_unset_mirror fails.", output);
      }
    else
      {
-        _e_output_hook_call(E_OUTPUT_HOOK_CONNECT_STATUS_CHANGE, output);
+        if (e_hwc_policy_get(output->hwc) == E_HWC_POLICY_PLANES)
+          e_hwc_planes_mirror_unset(output->hwc);
+        else
+          e_hwc_windows_mirror_unset(output->hwc);
+     }
+}
 
-        if (output->hwc)
-          {
-             e_hwc_del(output->hwc);
-             output->hwc = NULL;
-          }
+EINTERN Eina_Bool
+e_output_presentation_wait_set(E_Output *output, E_Client *ec)
+{
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(output, EINA_FALSE);
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(ec, EINA_FALSE);
 
-        if (!e_output_dpms_set(output, E_OUTPUT_DPMS_OFF))
-          {
-             EOERR("fail to e_output_dpms.", output);
-             return EINA_FALSE;
-          }
+   _e_output_display_mode_set(output, E_OUTPUT_DISPLAY_MODE_WAIT_PRESENTATION);
+
+   /* the ec does not commit the buffer to the exernal output
+    * Therefore, it needs the timer to prevent the eternal waiting.
+    */
+   if (output->delay_timer)
+     {
+        ecore_timer_del(output->delay_timer);
+        output->delay_timer = ecore_timer_add(OUTPUT_DELAY_CHECK_TIMEOUT, _e_output_presentation_check, output);
      }
 
+   EOINF("e_output_presentation_wait_set done: E_OUTPUT_DISPLAY_MODE_WAIT_PRESENTATION", output);
+
    return EINA_TRUE;
 }
 
 EINTERN Eina_Bool
-e_output_external_mode_change(E_Output *output, E_Output_Mode *mode)
+e_output_presentation_update(E_Output *output, E_Client *ec)
 {
-   E_Output_Mode *emode = NULL, *current_emode = NULL;
-   Eina_List *l;
-   Eina_Bool found = EINA_FALSE;
-   E_Output *output_primary = NULL;
-   E_Plane *ep = NULL;
-   int w, h, p_w, p_h;
+   E_Hwc *hwc;
+   E_Output_Display_Mode display_mode;
 
-   EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(mode, EINA_FALSE);
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(output, EINA_FALSE);
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(ec, EINA_FALSE);
 
-   if (e_output_connected(output) != EINA_TRUE)
-     return EINA_FALSE;
+   hwc = output->hwc;
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(hwc, EINA_FALSE);
 
-   current_emode = e_output_current_mode_get( output);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(current_emode, EINA_FALSE);
+   display_mode = e_output_display_mode_get(output);
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(display_mode == E_OUTPUT_DISPLAY_MODE_WAIT_PRESENTATION, EINA_FALSE);
 
-   if (current_emode == mode)
-     return EINA_TRUE;
+   /* delete the delay timer on E_OUTPUT_DISPLAY_MODE_WAIT_PRESENTATION */
+   if (output->delay_timer) ecore_timer_del(output->delay_timer);
+   output->delay_timer = NULL;
 
-   EINA_LIST_FOREACH(output->info.modes, l, emode)
+   if (e_hwc_policy_get(hwc) == E_HWC_POLICY_PLANES)
      {
-        if (mode == emode)
+        if (!e_hwc_planes_presentation_update(hwc, ec))
           {
-             found = EINA_TRUE;
-             break;
+             EOERR("e_hwc_planes_presentation_update fails.", output);
+             return EINA_FALSE;
+          }
+     }
+   else
+     {
+        if (!e_hwc_windows_presentation_update(hwc, ec))
+          {
+             EOERR("e_hwc_windows_presentation_update fails.", output);
+             return EINA_FALSE;
           }
      }
-   EINA_SAFETY_ON_FALSE_RETURN_VAL(found == EINA_TRUE, EINA_FALSE);
 
-   output_primary = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(output_primary, EINA_FALSE);
-   EINA_SAFETY_ON_TRUE_RETURN_VAL(output_primary == output, EINA_FALSE);
+   output->presentation_ec = ec;
+   _e_output_display_mode_set(output, E_OUTPUT_DISPLAY_MODE_PRESENTATION);
 
-   e_output_size_get(output, &w, &h);
-   e_output_size_get(output_primary, &p_w, &p_h);
+   output->external_set = EINA_TRUE;
 
-   ep = e_output_fb_target_get(output);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(ep, EINA_FALSE);
+   EOINF("e_output_presentation_update done: E_OUTPUT_DISPLAY_MODE_PRESENTATION", output);
 
-   e_comp_canvas_norender_push();
+   return EINA_TRUE;
+}
 
-   if (e_output_mode_apply(output, mode) == EINA_FALSE)
-     {
-        EOERR("fail to e_output_mode_apply.", output);
-        e_comp_canvas_norender_pop();
-        return EINA_FALSE;
-     }
+EINTERN void
+e_output_presentation_unset(E_Output *output)
+{
+   E_Hwc *hwc;
 
-   _e_output_external_rect_get(output_primary, p_w, p_h, w, h, &output->zoom_conf.rect);
+   EINA_SAFETY_ON_FALSE_RETURN(output);
 
-   /* call mode change hook */
-   _e_output_hook_call(E_OUTPUT_HOOK_MODE_CHANGE, output);
+   hwc = output->hwc;
+   EINA_SAFETY_ON_FALSE_RETURN(hwc);
 
-   if (e_hwc_policy_get(output->hwc) == E_HWC_POLICY_PLANES)
-     {
-        e_plane_external_reset(ep, &output->zoom_conf.rect);
-     }
-   else
-     {
-        /* TODO: HWC Windows */;
-     }
+   /* delete the delay timer on E_OUTPUT_DISPLAY_MODE_WAIT_PRESENTATION */
+   if (output->delay_timer) ecore_timer_del(output->delay_timer);
+   output->delay_timer = NULL;
 
-   _e_output_render_update(output_primary);
-   e_comp_canvas_norender_pop();
+   output->external_set = EINA_FALSE;
 
-   EOINF("e_output_external_reset done.(%dx%d)", output, mode->w, mode->h);
+   _e_output_display_mode_set(output, E_OUTPUT_DISPLAY_MODE_NONE);
+   output->presentation_ec = NULL;
 
-   return EINA_TRUE;
+   if (e_hwc_policy_get(hwc) == E_HWC_POLICY_PLANES)
+     e_hwc_planes_presentation_update(hwc, NULL);
+   else
+     e_hwc_windows_presentation_update(hwc, NULL);
+}
+
+EINTERN E_Client *
+e_output_presentation_ec_get(E_Output *output)
+{
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(output, NULL);
+
+   return output->presentation_ec;
 }
 
 EINTERN E_Output_Display_Mode
index a999e84d62ff3b71c3a45ac0e7c4e2349f369c45..9ec81aecc7640f5cfb04a1a88aa583052bdb26e2 100644 (file)
@@ -128,7 +128,17 @@ struct _E_Output
 
    /* external */
    Eina_Bool                external_set;
+   Eina_Bool                tdm_mirror;
+   E_Output                *mirror_src_output;
    E_Output_Display_Mode    display_mode;
+   tdm_layer               *overlay_layer;
+   Eina_Bool                need_overlay_pp;
+   E_Client                *presentation_ec;
+   /* If attribute has been set while external output is disconnected
+    * then show black screen and wait until EOM client start sending
+    * buffers. After expiring of the delay start mirroring */
+   Ecore_Timer *delay_timer;
+
    Eina_Bool                force_render;
 
    Eina_Bool fake_config;
@@ -228,10 +238,14 @@ EINTERN Eina_Bool         e_output_stream_capture_dequeue(E_Output *output, tbm_
 EINTERN Eina_Bool         e_output_stream_capture_start(E_Output *output);
 EINTERN void              e_output_stream_capture_stop(E_Output *output);
 EINTERN const char      * e_output_output_id_get(E_Output *output);
-EINTERN Eina_Bool         e_output_external_set(E_Output *output, E_Output_Display_Mode display_mode);
-EINTERN void              e_output_external_unset(E_Output *output);
-EINTERN Eina_Bool         e_output_external_update(E_Output *output);
+
 EINTERN Eina_Bool         e_output_external_mode_change(E_Output *output, E_Output_Mode *mode);
+EINTERN Eina_Bool         e_output_mirror_set(E_Output *output, E_Output *src_output);
+EINTERN void              e_output_mirror_unset(E_Output *output);
+EINTERN Eina_Bool         e_output_presentation_wait_set(E_Output *output, E_Client *ec);
+EINTERN Eina_Bool         e_output_presentation_update(E_Output *output, E_Client *ec);
+EINTERN void              e_output_presentation_unset(E_Output *output);
+EINTERN E_Client        * e_output_presentation_ec_get(E_Output *output);
 
 EINTERN E_Output_Display_Mode  e_output_display_mode_get(E_Output *output);