redesign the e_comp_screen/e_output/e_plane for multi plane hwc
authorSooChan Lim <sc1.lim@samsung.com>
Fri, 17 Jun 2016 13:15:40 +0000 (22:15 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Mon, 25 Jul 2016 09:56:29 +0000 (18:56 +0900)
Change-Id: I13b41d6c10ff8b48662cc03ded4c4b07b5e3ff29

17 files changed:
packaging/enlightenment.spec
src/bin/e_comp.c
src/bin/e_comp.h
src/bin/e_comp_canvas.c
src/bin/e_comp_cfdata.c
src/bin/e_comp_cfdata.h
src/bin/e_comp_hwc.c
src/bin/e_comp_object.c
src/bin/e_comp_object.h
src/bin/e_comp_screen.c
src/bin/e_comp_screen.h
src/bin/e_comp_wl.c
src/bin/e_includes.h
src/bin/e_output.c
src/bin/e_output.h
src/bin/e_plane.c
src/bin/e_plane.h

index a5e1ef3b6e8a815fce6848505306d42cd8aa695a..266e0baccadaeb9fffe7408c24e25451e34d5a39 100755 (executable)
@@ -73,7 +73,8 @@ export LDFLAGS+=" -pie "
 %if "%{MEMCPY_SWC}" == "use"
       --enable-memcpy_swc \
 %endif
-      --enable-quick-init
+      --enable-quick-init \
+      --enable-hwc-multi
 
 make %{?_smp_mflags}
 
index 12051f5b3ce1881db926cbf17ae66cc4e3a37643..1c6863cd70bdc0cb1fb00f8293527d3a32224d2c 100644 (file)
@@ -382,6 +382,7 @@ _hwc_set(E_Output *eout)
 {
    const Eina_List *ep_l = NULL, *l;
    E_Plane *ep = NULL, *ep_fb = NULL;
+   Eina_Bool ret = EINA_FALSE;
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(eout, EINA_FALSE);
    EINA_SAFETY_ON_NULL_RETURN_VAL(eout->planes, EINA_FALSE);
@@ -394,6 +395,7 @@ _hwc_set(E_Output *eout)
    ep_l = e_output_planes_get(eout);
    EINA_LIST_FOREACH(ep_l, l , ep)
      {
+        Eina_Bool set = EINA_FALSE;
         if (!ep_fb)
           {
              if (e_plane_is_fb_target(ep))
@@ -401,8 +403,16 @@ _hwc_set(E_Output *eout)
                   ep_fb = ep;
                   if (ep->prepare_ec)
                     {
-                       e_client_redirected_set(ep->prepare_ec, 0);
-                       ep->ec = ep->prepare_ec;
+
+                       set = e_plane_ec_set(ep, ep->prepare_ec);
+                       if (set)
+                         {
+                            INF("HWC : ec(0x%08x, %s) is set on fb_target( %d)\n", ep->prepare_ec, ep->prepare_ec->icccm.title, ep->zpos);
+                            e_client_redirected_set(ep->prepare_ec, 0);
+                            ret |= EINA_TRUE;
+                         }
+                       else
+                         return EINA_FALSE;
                     }
                }
              continue;
@@ -412,13 +422,20 @@ _hwc_set(E_Output *eout)
           {
              if (ep->prepare_ec)
                {
-                  e_client_redirected_set(ep->prepare_ec, 0);
-                  ep->ec = ep->prepare_ec;
+                  set = e_plane_ec_set(ep, ep->prepare_ec);
+                  if (set)
+                    {
+                       INF("HWC : ec(0x%08x, %s) is set on %d\n", ep->prepare_ec, ep->prepare_ec->icccm.title, ep->zpos);
+                       e_client_redirected_set(ep->prepare_ec, 0);
+                       ret |= EINA_TRUE;
+                    }
+                  else
+                    break;
                }
           }
      }
 
-   return EINA_TRUE;
+   return ret;
 }
 
 static Eina_Bool
@@ -434,6 +451,7 @@ _hwc_prepare_set(E_Output *eout, int n_vis, Eina_List *clist)
    EINA_SAFETY_ON_NULL_RETURN_VAL(eout, EINA_FALSE);
    EINA_SAFETY_ON_NULL_RETURN_VAL(clist, EINA_FALSE);
 
+   // list up available_hw layers E_Client can be set
    ep_l = e_output_planes_get(eout);
    EINA_LIST_FOREACH(ep_l, l, ep)
      {
@@ -446,6 +464,7 @@ _hwc_prepare_set(E_Output *eout, int n_vis, Eina_List *clist)
                }
              continue;
           }
+        if (conf->hwc_use_single_plane) continue;
         if (e_plane_is_cursor(ep)) continue;
         if (ep->zpos > ep_fb->zpos)
           hwc_l = eina_list_append(hwc_l, ep);
@@ -460,18 +479,17 @@ _hwc_prepare_set(E_Output *eout, int n_vis, Eina_List *clist)
        (n_ec <= n_ly)) // full hwc including nocomp
      {
         int del = n_ly - n_ec;
-        INF("HWC : \t fully hwc \t n_ec(%d), n_vis(%d), n_ly(%d), hwc_mode(%d) \n", n_ec, n_vis, n_ly, e_comp->hwc_mode);
         EINA_LIST_REVERSE_FOREACH(hwc_l, l, ep)
           {
              ec = NULL;
              if (del > 0)
                {
-                  ep->prepare_ec = NULL;
+                  e_plane_ec_prepare_set(ep, NULL);
                   del--;
                   continue;
                }
              if (clist) ec = eina_list_data_get(clist);
-             if (ec) ep->prepare_ec = ec;
+             if (ec) e_plane_ec_prepare_set(ep, ec);
              clist = eina_list_next(clist);
           }
         ret = EINA_TRUE;
@@ -480,19 +498,18 @@ _hwc_prepare_set(E_Output *eout, int n_vis, Eina_List *clist)
             (n_ec < n_vis))
      {
         int del = n_ly - n_ec;
-        INF("HWC : \t hybrid \t n_ec(%d), n_vis(%d), n_ly(%d), hwc_mode(%d) \n", n_ec, n_vis, n_ly, e_comp->hwc_mode);
         EINA_LIST_REVERSE_FOREACH(hwc_l, l, ep)
           {
              ec = NULL;
              if (del > 0)
                {
-                  ep->prepare_ec = NULL;
+                  e_plane_ec_prepare_set(ep, NULL);
                   del--;
                   continue;
                }
              if (clist2) ec = eina_list_data_get(clist2);
-             if (ec) ep->prepare_ec = ec;
-             if (e_plane_is_fb_target(ep)) ep->prepare_ec = NULL;
+             if (ec) e_plane_ec_prepare_set(ep, ec);
+             if (e_plane_is_fb_target(ep)) e_plane_ec_prepare_set(ep, NULL);
              clist2 = eina_list_next(clist2);
           }
         ret = EINA_TRUE;
@@ -516,8 +533,30 @@ _hwc_cancel(E_Output *eout)
    EINA_LIST_FOREACH(eout->planes, l, ep)
      {
         if (ep->ec) e_client_redirected_set(ep->ec, 1);
-        ep->prepare_ec = NULL;
-        ep->ec = NULL;
+        e_plane_ec_prepare_set(ep, NULL);
+        e_plane_ec_set(ep, NULL);
+     }
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_hwc_plane_reserved_clean()
+{
+   Eina_List *l, *ll;
+   E_Zone *zone;
+   E_Plane *ep;
+
+   EINA_LIST_FOREACH(e_comp->zones, l, zone)
+     {
+        E_Output * eout;
+        if (!zone->output_id) continue;
+        eout = e_output_find(zone->output_id);
+        EINA_LIST_FOREACH(eout->planes, ll, ep)
+          {
+             if (e_plane_is_reserved(ep))
+                e_plane_reserved_set(ep, 0);
+          }
      }
 
    return EINA_TRUE;
@@ -528,6 +567,7 @@ _e_comp_hwc_apply(E_Output * eout)
 {
    const Eina_List *ep_l = NULL, *l;
    E_Plane *ep = NULL, *ep_fb = NULL;
+   Eina_Bool ret = EINA_FALSE;
 
    ep_l = e_output_planes_get(eout);
    EINA_LIST_FOREACH(ep_l, l, ep)
@@ -546,13 +586,27 @@ _e_comp_hwc_apply(E_Output * eout)
           if (ep->prepare_ec != NULL) goto hwcompose;
      }
 
-   _hwc_cancel(eout);
-   return EINA_FALSE;
+   goto compose;
 
 hwcompose:
-   e_comp->hwc_mode = 1;
-   _hwc_set(eout);
-   return EINA_TRUE;
+   ret = _hwc_set(eout);
+   if (!ret) INF("HWC : it is failed to assign surface on plane\n");
+
+compose:
+   if (ret) e_comp->hwc_mode = 1;
+   else
+     {
+        e_comp->hwc_mode = 0;
+
+        EINA_LIST_FOREACH(ep_l, l, ep)
+          {
+             if (ep->ec)
+               e_client_redirected_set(ep->ec, 1);
+
+             e_plane_ec_prepare_set(ep, NULL);
+          }
+     }
+   return ret;
 }
 
 static Eina_Bool
@@ -595,74 +649,74 @@ _e_comp_hwc_changed(void)
 static Eina_Bool
 _e_comp_hwc_prepare(void)
 {
-   Eina_List *l;
+   Eina_List *l, *vl;
    E_Zone *zone;
    Eina_Bool ret = EINA_FALSE;
 
-   if (!e_comp->hwc) return EINA_FALSE;
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(e_comp->hwc, EINA_FALSE);
 
-   // TODO: e_comp->canvases
    EINA_LIST_FOREACH(e_comp->zones, l, zone)
      {
         E_Client *ec;
-        E_Output *eout;
-        int n_visible = 0, n_ec = 0;
-        Eina_List *clist = NULL;
+        E_Output *output;
+        int n_vis = 0, n_ec = 0;
+        Eina_List *clist = NULL, *vis_clist = NULL;
 
         if (!zone || !zone->output_id) continue;
 
-        eout = e_output_find(zone->output_id);
+        output = e_output_find(zone->output_id);
+        if (!output) continue;
+
+        vis_clist = e_comp_vis_ec_list_get(zone);
+        if (!vis_clist) continue;
 
-        E_CLIENT_REVERSE_FOREACH(ec)
+        EINA_LIST_FOREACH(vis_clist, vl, ec)
           {
              E_Comp_Wl_Client_Data *cdata = (E_Comp_Wl_Client_Data*)ec->comp_data;
+             int cnt = 0;
 
-             if (ec->zone != zone) continue;
-
-             // check clients to skip composite
-             if (ec->ignored || ec->input_only || (!evas_object_visible_get(ec->frame)))
-               continue;
+             // check clients not able to use hwc
+             // if pixmap is launch screen image
+             if ((ec->pixmap) && (e_pixmap_type_get(ec->pixmap) == E_PIXMAP_TYPE_EXT_OBJECT))
+                goto composite;
 
-             if (!E_INTERSECTS(0, 0, e_comp->w, e_comp->h,
-                               ec->client.x, ec->client.y, ec->client.w, ec->client.h))
-               {// check quick panel
-                  continue;
+             // if video client could not draw it on video hw layer
+             if (cdata->sub.below_list || cdata->sub.below_list_pending)
+               {
+                  if (!e_comp_wl_video_client_has(ec))
+                     goto composite;
                }
 
-             if (evas_object_data_get(ec->frame, "comp_skip"))
-               continue;
-
-             // check clients not able to use hwc
-             if ((!cdata->buffer_ref.buffer) ||
+             // if ec has invalid buffer or scaled( transformed )
+             if ((!cdata) ||
+                 (!cdata->buffer_ref.buffer) ||
                  (cdata->buffer_ref.buffer->type != E_COMP_WL_BUFFER_TYPE_NATIVE) ||
                  (cdata->width_from_buffer != cdata->width_from_viewport) ||
                  (cdata->height_from_buffer != cdata->height_from_viewport) ||
                  e_client_transform_core_enable_get(ec))
                {
-                  if (!n_visible) goto fullcomp;
-                  n_visible++;
+                  if (!n_vis) goto composite;
+                  cnt++;
                   break;
                }
 
-             n_visible++;
+             cnt++;
              clist = eina_list_append(clist, ec);
           }
 
+        n_vis = eina_list_count(vis_clist);
         n_ec = eina_list_count(clist);
-        if ((n_visible < 1) || (n_ec < 1))
-          {
-             eina_list_free(clist);
-             goto fullcomp;
-          }
+        if ((n_vis < 1) || (n_ec < 1))
+          goto composite;
+
+        ret |= _hwc_prepare_set(output, n_vis, clist);
 
-        ret = _hwc_prepare_set(eout, n_visible, clist);
+        composite:
         eina_list_free(clist);
+        eina_list_free(vis_clist);
      }
 
    return ret;
-
-fullcomp:
-   return EINA_FALSE;
 }
 
 static Eina_Bool
@@ -670,12 +724,29 @@ _e_comp_hwc_usable(void)
 {
    Eina_List *l;
    E_Zone *zone;
+   Eina_Bool ret = EINA_FALSE;
 
    if (!e_comp->hwc) return EINA_FALSE;
 
+
+   if ((ec->pixmap) && (e_pixmap_type_get(ec->pixmap) == E_PIXMAP_TYPE_EXT_OBJECT))
+     break;
+   
+   if ((!cdata) ||
+       (!cdata->buffer_ref.buffer) ||
+       (cdata->buffer_ref.buffer->type != E_COMP_WL_BUFFER_TYPE_NATIVE))
+     break;
+   
+   if (cdata->sub.below_list || cdata->sub.below_list_pending)
+     {
+        if (!e_comp_wl_video_client_has(ec))
+           break;
+     }
+
    // check whether to use hwc
    // core assignment policy
-   _e_comp_hwc_prepare();
+   ret = _e_comp_hwc_prepare();
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, EINA_FALSE);
 
    // extra policy can replace core policy
    _e_comp_hook_call(E_COMP_HOOK_PREPARE_PLANE, NULL);
@@ -761,6 +832,7 @@ e_comp_hwc_end(const char *location)
 
    e_comp->selcomp_want = 0;
    E_FREE_FUNC(e_comp->selcomp_delay_timer, ecore_timer_del);
+   _hwc_plane_reserved_clean();
 
    if (!e_comp->hwc) return;
    if (!_e_comp_hwc_is_on()) return;
@@ -777,6 +849,10 @@ e_comp_hwc_end(const char *location)
 
    INF("HWC : End...  at %s", location);
 #else
+   if (!e_comp->hwc) return;
+   if (!e_comp->nocomp) return;
+   if (!e_comp->nocomp_ec) return;
+
    e_comp_nocomp_end(location);
 #endif // end of ENABLE_HWC_MULTI
 }
@@ -909,7 +985,7 @@ setup_hwcompose:
      }
    else
      {
-        if (_e_comp_hwc_is_on()) e_comp_hwc_end(__FUNCTION__);
+        e_comp_hwc_end(__FUNCTION__);
      }
 #else
    ec = _e_comp_fullscreen_check();
@@ -1420,8 +1496,8 @@ e_comp_init(void)
    e_comp_canvas_fake_layers_init();
 
 #ifdef HAVE_HWC
-   // TO DO : check hwc init condition
-   if (conf->hwc && e_comp_gl_get())
+   if (conf->hwc &&
+       e_comp_gl_get()) // TODO: check hwc init condition
      {
         e_comp->hwc = e_comp_hwc_init();
         if (!e_comp->hwc)
@@ -1429,6 +1505,7 @@ e_comp_init(void)
         else
           e_comp->hwc_fs = EINA_TRUE; // 1: active hwc policy
      }
+   conf->hwc_use_single_plane = 1; // TODO: 0 if multi plane is working.
 #endif
 
    E_LIST_HANDLER_APPEND(handlers, E_EVENT_SCREENSAVER_ON,  _e_comp_screensaver_on,  NULL);
@@ -1681,13 +1758,9 @@ E_API void
 e_comp_override_add()
 {
    e_comp->hwc_override++;
-   if ((e_comp->hwc_override > 0) &&
-#ifdef ENABLE_HWC_MULTI
-       (_e_comp_hwc_is_on()))
-#else
-       (e_comp->nocomp))
-#endif
+   if (e_comp->hwc_override > 0)
      {
+        // go full compositing
         e_comp_hwc_end(__FUNCTION__);
      }
 }
index 836f51581d7a4730e4105d849ceef502e5c6dbec..632574f34def8df0fba56256b19c6ebfd791caca 100644 (file)
@@ -109,6 +109,8 @@ struct _E_Comp
       void *data;
    } autoclose;
 
+   E_Comp_Screen *e_comp_screen;
+
    Eina_List *debug_rects;
    Eina_List *ignore_wins;
 
index c792afdd7be6793b7379beba1a696b3fdb1935b0..15676169c57e5e469ce869aa466133ee6e7eaf9f 100644 (file)
@@ -126,7 +126,7 @@ _e_comp_canvas_cb_zone_sort(const void *data1, const void *data2)
 static void
 _e_comp_canvas_resize(Ecore_Evas *ee EINA_UNUSED)
 {
-   e_output_screens_setup(e_comp->w, e_comp->h);
+   e_comp_screen_e_screens_setup(e_comp->e_comp_screen, e_comp->w, e_comp->h);
    e_comp_canvas_update();
 }
 
@@ -195,7 +195,7 @@ e_comp_canvas_init(int w, int h)
 
    e_comp->ee_win = ecore_evas_window_get(e_comp->ee);
 
-   screens = (Eina_List *)e_output_screens_get();
+   screens = (Eina_List *)e_comp_screen_e_screens_get(e_comp->e_comp_screen);
    if (screens)
      {
         E_Screen *scr;
@@ -377,7 +377,7 @@ e_comp_canvas_update(void)
    int i;
    Eina_Bool changed = EINA_FALSE;
 
-   screens = (Eina_List *)e_output_screens_get();
+   screens = (Eina_List *)e_comp_screen_e_screens_get(e_comp->e_comp_screen);
 
    if (screens)
      {
index 922261ff473597059e6364f9f155235a273f8261..a5ce934190bd4497aaa50c1e36dc50d0ee4adaed 100644 (file)
@@ -55,6 +55,7 @@ e_comp_cfdata_edd_init(E_Config_DD **conf_edd, E_Config_DD **match_edd)
    E_CONFIG_VAL(D, T, selcomp_use_timer, UCHAR);
    E_CONFIG_VAL(D, T, selcomp_begin_timeout, DOUBLE);
    E_CONFIG_VAL(D, T, hwc, UCHAR);
+   E_CONFIG_VAL(D, T, hwc_use_single_plane, UCHAR);
    E_CONFIG_VAL(D, T, nofade, UCHAR);
    E_CONFIG_VAL(D, T, smooth_windows, UCHAR);
    E_CONFIG_VAL(D, T, first_draw_delay, DOUBLE);
@@ -116,6 +117,7 @@ e_comp_cfdata_config_new(void)
    cfg->selcomp_use_timer = 1;
    cfg->selcomp_begin_timeout = 2.0;
    cfg->hwc = 0;
+   cfg->hwc_use_single_plane = 0;
    cfg->nofade = 0;
    cfg->smooth_windows = 0; // 1 if gl, 0 if not
    cfg->first_draw_delay = 0.15;
index f1037e4b5d56be5ef3028bc6c7f89cfdd5608b06..56c5f78f211e7adf3ccf707344aa6bd6853b5561 100644 (file)
@@ -32,6 +32,7 @@ struct _E_Comp_Config
    unsigned char selcomp_use_timer;
    double        selcomp_begin_timeout;
    unsigned char hwc;
+   unsigned char hwc_use_single_plane;
    unsigned char smooth_windows;
    unsigned char nofade;
    double        first_draw_delay;
index 94b7dfcd6d18d0b5e8e7b958a6db1b6f0cb38898..57ebd0013a43ed484e7dc72ca8aa85148c9e0e83 100644 (file)
@@ -1,6 +1,79 @@
 #include "e.h"
 
 #ifdef HAVE_HWC
+#ifdef ENABLE_HWC_MULTI
+EINTERN Eina_Bool
+e_comp_hwc_init(void)
+{
+   if (!e_comp || !e_comp->e_comp_screen)
+     {
+        e_error_message_show(_("Enlightenment cannot has no e_comp at HWC(HardWare Composite)!\n"));
+        return EINA_FALSE;
+     }
+
+   if (!e_comp_screen_hwc_setup(e_comp->e_comp_screen))
+     {
+        ERR("fail to e_comp_screen_hwc_setup");
+        return EINA_FALSE;
+     }
+
+   return EINA_TRUE;
+}
+
+EINTERN void
+e_comp_hwc_shutdown(void)
+{
+   ;
+}
+
+EINTERN Eina_Bool
+e_comp_hwc_mode_nocomp(E_Client *ec)
+{
+   return EINA_FALSE;
+}
+
+EINTERN void
+e_comp_hwc_display_client(E_Client *ec)
+{
+   ;
+}
+
+EINTERN void
+e_comp_hwc_trace_debug(Eina_Bool onoff)
+{
+   ;
+}
+
+EINTERN void
+e_comp_hwc_info_debug(void)
+{
+   ;
+}
+
+EINTERN Eina_Bool
+e_comp_hwc_native_surface_set(E_Client *ec)
+{
+   return EINA_FALSE;
+}
+
+EINTERN void
+e_comp_hwc_client_commit(E_Client *ec)
+{
+   ;
+}
+
+E_API Eina_Bool
+e_comp_hwc_client_set_layer(E_Client *ec, int zorder)
+{
+   return EINA_FALSE;
+}
+
+E_API void
+e_comp_hwc_client_unset_layer(int zorder)
+{
+   ;
+}
+#else
 # include "e_comp_wl.h"
 # include "e_comp_hwc.h"
 
@@ -926,9 +999,12 @@ _e_comp_hwc_output_geom_update(void)
    Ecore_Drm_Device *dev;
    Ecore_Drm_Output *drm_output;
    E_Output *eout;
+   E_Comp_Screen *e_comp_screen;
    const Eina_List *l, *ll;
    int x, y, w, h;
 
+   e_comp_screen = e_comp->e_comp_screen;
+
    EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
      {
         EINA_LIST_FOREACH(e_comp_screen->outputs, ll, eout)
@@ -1476,6 +1552,21 @@ _e_comp_hwc_remove(E_Comp_Hwc *hwc)
 EINTERN Eina_Bool
 e_comp_hwc_init(void)
 {
+#ifdef ENABLE_HWC_MULTI
+   if (!e_comp || !e_comp->e_comp_screen)
+     {
+        e_error_message_show(_("Enlightenment cannot has no e_comp at HWC(HardWare Composite)!\n"));
+        return EINA_FALSE;
+     }
+
+   if (!e_comp_screen_hwc_setup(e_comp->e_comp_screen))
+     {
+        ERR("fail to e_comp_screen_hwc_setup");
+        return EINA_FALSE;
+     }
+
+   return EINA_TRUE;
+#else
    E_Comp_Hwc *hwc = NULL;
    E_Comp_Hwc_Output *hwc_output = NULL;
    E_Comp_Hwc_Layer *hwc_layer = NULL;
@@ -1611,6 +1702,7 @@ fail:
    _e_comp_hwc_remove(hwc);
 
    return EINA_FALSE;
+#endif
 }
 
 EINTERN void
@@ -1618,7 +1710,10 @@ e_comp_hwc_shutdown(void)
 {
    if (!e_comp) return;
 
+#ifdef ENABLE_HWC_MULTI
+#else
    _e_comp_hwc_remove(g_hwc);
+#endif
 }
 
 
@@ -1885,6 +1980,9 @@ _e_comp_hwc_check_buffer_scanout(E_Client *ec)
 EINTERN Eina_Bool
 e_comp_hwc_native_surface_set(E_Client *ec)
 {
+#ifdef ENABLE_HWC_MULTI
+   return EINA_FALSE;
+#else
    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
 
    E_Comp_Hwc_Client *hwc_client = NULL;
@@ -1914,6 +2012,7 @@ e_comp_hwc_native_surface_set(E_Client *ec)
 #endif
 
    return EINA_TRUE;
+#endif
 }
 
 EINTERN void
@@ -2035,7 +2134,7 @@ e_comp_hwc_disable_output_hwc_rendering(int index, int onoff)
      }
    return;
 }
-
+#endif /* end of ENABLE_HWC_MULTI */
 #else /* HAVE_HWC */
 EINTERN Eina_Bool
 e_comp_hwc_init(void)
index 62618ccb46b5dab5d84430b921e0fb4e17a11126..a11fce24a0417e45fcc0baf33d99dedb1434670e 100644 (file)
@@ -3714,6 +3714,9 @@ e_comp_object_dirty(Evas_Object *obj)
      }
 
 #ifdef HAVE_HWC
+#ifdef ENABLE_HWC_MULTI
+   e_comp_object_native_surface_set(obj, e_comp->gl);
+#else
    if (e_comp->hwc)
      {
         if (!e_comp_hwc_native_surface_set(cw->ec))
@@ -3721,6 +3724,7 @@ e_comp_object_dirty(Evas_Object *obj)
      }
    else
      e_comp_object_native_surface_set(obj, e_comp->gl);
+#endif
 #else
    e_comp_object_native_surface_set(obj, e_comp->gl);
 #endif
@@ -4670,4 +4674,12 @@ e_comp_object_hwc_update_exists(Evas_Object *obj)
 {
    API_ENTRY EINA_FALSE;
    return cw->hwc_need_update;
-}
\ No newline at end of file
+}
+
+// will remove out
+E_API void
+e_comp_object_hwc_update_set(Evas_Object *obj, Eina_Bool set)
+{
+   API_ENTRY;
+   cw->hwc_need_update = set;
+}
index 3f478e732b3cac5bfe6fcef6f135ce92ae0f926b..da9c67d2aa0d434a0c133d0c34a77cef0c9dc564 100644 (file)
@@ -137,7 +137,7 @@ E_API E_Client *e_comp_object_dim_client_get(void);
 E_API void      e_comp_object_clear(Evas_Object *obj);
 
 E_API Eina_Bool e_comp_object_hwc_update_exists(Evas_Object *obj);
-
+E_API void e_comp_object_hwc_update_set(Evas_Object *obj, Eina_Bool set);
 #endif
 #endif
 
index 0f2f5e180dd3edb479954ba83eaa1f130e0252f3..1afa18492c3c72d495cd46fd35afe80893473266 100644 (file)
@@ -7,6 +7,8 @@ static Eina_Bool session_state = EINA_FALSE;
 static Eina_Bool dont_set_ecore_drm_keymap = EINA_FALSE;
 static Eina_Bool dont_use_xkb_cache = EINA_FALSE;
 
+E_API int              E_EVENT_SCREEN_CHANGE = 0;
+
 static Eina_Bool
 _e_comp_screen_cb_activate(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
 {
@@ -51,34 +53,39 @@ end:
 }
 
 static Eina_Bool
-_e_comp_screen_cb_output(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+_e_comp_screen_cb_output_drm(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
 {
    const Eina_List *l;
-   E_Output *eout;
+   E_Output *output;
    Ecore_Drm_Event_Output *e;
+   E_Comp_Screen *e_comp_screen = NULL;
 
    if (!(e = event)) goto end;
+   if (!e_comp) goto end;
+   if (!e_comp->e_comp_screen) goto end;
+
+   e_comp_screen = e_comp->e_comp_screen;
 
    DBG("WL_DRM OUTPUT CHANGE");
 
-   EINA_LIST_FOREACH(e_comp_screen->outputs, l, eout)
+   EINA_LIST_FOREACH(e_comp_screen->outputs, l, output)
      {
-        if ((!strcmp(eout->info.name, e->name)) &&
-            (!strcmp(eout->info.screen, e->model)))
+        if ((!strcmp(output->info.name, e->name)) &&
+            (!strcmp(output->info.screen, e->model)))
           {
              if (e->plug)
                {
-                  if (!e_comp_wl_output_init(eout->id, e->make, e->model,
+                  if (!e_comp_wl_output_init(output->id, e->make, e->model,
                                              e->x, e->y, e->w, e->h,
                                              e->phys_width, e->phys_height,
                                              e->refresh, e->subpixel_order,
                                              e->transform))
                     {
-                       ERR("Could not setup new output: %s", eout->id);
+                       ERR("Could not setup new output: %s", output->id);
                     }
                }
              else
-               e_comp_wl_output_remove(eout->id);
+               e_comp_wl_output_remove(output->id);
 
              break;
           }
@@ -94,6 +101,35 @@ end:
    return ECORE_CALLBACK_PASS_ON;
 }
 
+#ifdef ENABLE_HWC_MULTI
+static Eina_Bool
+_e_comp_screen_commit_idle_cb(void *data EINA_UNUSED)
+{
+   Eina_List *l, *ll;
+   E_Comp_Screen *e_comp_screen = NULL;
+   E_Output *output = NULL;
+
+   if (!e_comp->e_comp_screen) goto end;
+
+   e_comp_screen = e_comp->e_comp_screen;
+
+   EINA_LIST_FOREACH_SAFE(e_comp_screen->outputs, l, ll, output)
+     {
+        if (!output) continue;
+        if (!output->config.enabled) continue;
+
+        if (!e_output_commit(output))
+          {
+             ERR("fail to e_comp_screen->outputs.");
+             continue;
+          }
+     }
+
+end:
+   return ECORE_CALLBACK_RENEW;
+}
+#endif
+
 static Eina_Bool
 _e_comp_screen_cb_input_device_add(void *data, int type, void *event)
 {
@@ -157,17 +193,17 @@ _e_comp_screen_cb_ee_resize(Ecore_Evas *ee EINA_UNUSED)
 }
 
 static Ecore_Drm_Output_Mode *
-_e_comp_screen_mode_screen_find(E_Output *eout, Ecore_Drm_Output *output)
+_e_comp_screen_mode_screen_find(E_Output *output, Ecore_Drm_Output *drm_output)
 {
    Ecore_Drm_Output_Mode *mode, *m = NULL;
    const Eina_List *l;
    int diff, distance = 0x7fffffff;
 
-   EINA_LIST_FOREACH(ecore_drm_output_modes_get(output), l, mode)
+   EINA_LIST_FOREACH(ecore_drm_output_modes_get(drm_output), l, mode)
      {
-        diff = (100 * abs(eout->config.mode.w - mode->width)) +
-           (100 * abs(eout->config.mode.h - mode->height)) +
-           fabs((100 * eout->config.mode.refresh) - (100 * mode->refresh));
+        diff = (100 * abs(output->config.mode.w - mode->width)) +
+           (100 * abs(output->config.mode.h - mode->height)) +
+           fabs((100 * output->config.mode.refresh) - (100 * mode->refresh));
         if (diff < distance)
           {
              m = mode;
@@ -178,185 +214,174 @@ _e_comp_screen_mode_screen_find(E_Output *eout, Ecore_Drm_Output *output)
    return m;
 }
 
-static Eina_Bool
-_e_comp_screen_output_exists(Ecore_Drm_Output *output, unsigned int crtc)
+static E_Comp_Screen *
+_e_comp_screen_new(void)
 {
-   /* find out if this output can go into the 'possibles' */
-   return ecore_drm_output_possible_crtc_get(output, crtc);
+   E_Comp_Screen *e_comp_screen = NULL;
+   tdm_error error = TDM_ERROR_NONE;
+
+   e_comp_screen = E_NEW(E_Comp_Screen, 1);
+   if (!e_comp_screen) return NULL;
+
+   if (e_comp_gl_get())
+     {
+        /* tdm display init */
+        e_comp_screen->tdisplay = tdm_display_init(&error);
+        if (!e_comp_screen->tdisplay)
+          {
+             ERR("fail to get tdm_display\n");
+             free(e_comp_screen);
+             return NULL;
+          }
+     }
+   else
+     {
+        /* Ecore_Drm_Device list */
+        e_comp_screen->devices = ecore_drm_devices_get();
+     }
+
+   return e_comp_screen;
 }
 
-static char *
-_e_comp_screen_output_screen_get(Ecore_Drm_Output *output)
+static void
+_e_comp_screen_del(E_Comp_Screen *e_comp_screen)
 {
-   const char *model;
+   if (!e_comp_screen) return;
 
-   model = ecore_drm_output_model_get(output);
-   if (!model) return NULL;
+   if (e_comp_screen->tdisplay) tdm_display_deinit(e_comp_screen->tdisplay);
 
-   return strdup(model);
+   free(e_comp_screen);
 }
 
-EINTERN E_Comp_Screen *
-e_comp_screen_init_outputs(void)
+static void
+_e_comp_screen_deinit_outputs(E_Comp_Screen *e_comp_screen)
+{
+   E_Output *output;
+
+   // free up e_outputs
+   EINA_LIST_FREE(e_comp_screen->outputs, output)
+     {
+        e_output_del(output);
+     }
+
+   e_output_shutdown();
+}
+
+static Eina_Bool
+_e_comp_screen_init_drm_outputs(E_Comp_Screen *e_comp_screen)
 {
    Ecore_Drm_Device *dev;
    Ecore_Drm_Output *output;
    const Eina_List *l, *ll;
-   E_Comp_Screen *r = NULL;
+   E_Output *eout = NULL;
 
-   r = E_NEW(E_Comp_Screen, 1);
-   if (!r) return NULL;
-
-   EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
+   EINA_LIST_FOREACH(e_comp_screen->devices, l, dev)
      {
         EINA_LIST_FOREACH(dev->outputs, ll, output)
           {
-             E_Output *eout;
-             const Eina_List *m;
-             Ecore_Drm_Output_Mode *omode;
-             unsigned int j;
-             int priority;
-             Eina_Bool ok = EINA_FALSE;
-             Eina_Bool possible = EINA_FALSE;
-             int len = 0;
-
-             eout = E_NEW(E_Output, 1);
+             if (!output) continue;
+             eout = e_output_drm_new(output);
              if (!eout) continue;
-
-             eout->info.name = ecore_drm_output_name_get(output);
-             printf("COMP TDM: .... out %s\n", eout->info.name);
-
-             eout->info.connected = ecore_drm_output_connected_get(output);
-             printf("COMP TDM: ...... connected %i\n", eout->info.connected);
-
-             eout->info.screen = _e_comp_screen_output_screen_get(output);
-
-             eout->info.edid = ecore_drm_output_edid_get(output);
-             if (eout->info.edid)
-               eout->id = malloc(strlen(eout->info.name) + 1 + strlen(eout->info.edid) + 1);
-             else
-               eout->id = malloc(strlen(eout->info.name) + 1 + 1);
-             if (!eout->id)
+             if(!e_output_drm_update(eout))
                {
-                  free(eout->info.screen);
-                  free(eout->info.edid);
-                  free(eout);
-                  continue;
+                  ERR("fail to e_output_update.");
                }
-             len = strlen(eout->info.name);
-             strncpy(eout->id, eout->info.name, len + 1);
-             strncat(eout->id, "/", 1);
-             if (eout->info.edid) strncat(eout->id, eout->info.edid, strlen(eout->info.edid));
-
-             printf("COMP TDM: ...... screen: %s\n", eout->id);
-
-             ecore_drm_output_physical_size_get(output, &eout->info.size.w,
-                                                &eout->info.size.h);
-
-             EINA_LIST_FOREACH(ecore_drm_output_modes_get(output), m, omode)
-               {
-                  E_Output_Mode *rmode;
-
-                  rmode = malloc(sizeof(E_Output_Mode));
-                  if (!rmode) continue;
+             e_comp_screen->outputs = eina_list_append(e_comp_screen->outputs, eout);
+          }
+     }
 
-                  rmode->w = omode->width;
-                  rmode->h = omode->height;
-                  rmode->refresh = omode->refresh;
-                  rmode->preferred = (omode->flags & DRM_MODE_TYPE_PREFERRED);
+   //TODO: if there is no output connected, make the fake output which is connected.
 
-                  eout->info.modes = eina_list_append(eout->info.modes, rmode);
-               }
+   return EINA_TRUE;
+}
 
-             priority = 0;
-             if (ecore_drm_output_primary_get(dev) == output)
-               priority = 100;
-             eout->config.priority = priority;
+static Eina_Bool
+_e_comp_screen_init_outputs(E_Comp_Screen *e_comp_screen)
+{
+   E_Output *output = NULL;
+   E_Output_Mode *mode = NULL;
+   tdm_display *tdisplay = e_comp_screen->tdisplay;
+   int num_outputs;
+   int i;
 
-             for (j = 0; j < dev->crtc_count; j++)
-               {
-                  if (dev->crtcs[j] == ecore_drm_output_crtc_id_get(output))
-                    {
-                       ok = EINA_TRUE;
-                       break;
-                    }
-               }
+   /* init e_output */
+   if (!e_output_init())
+     {
+        ERR("fail to e_output_init.");
+        return EINA_FALSE;
+     }
 
-             if (!ok)
-               {
-                  /* get possible crtcs, compare to output_crtc_id_get */
-                  for (j = 0; j < dev->crtc_count; j++)
-                    {
-                       if (_e_comp_screen_output_exists(output, dev->crtcs[j]))
-                         {
-                            ok = EINA_TRUE;
-                            possible = EINA_TRUE;
-                            break;
-                         }
-                    }
-               }
+   /* get the num of outputs */
+   tdm_display_get_output_count(tdisplay, &num_outputs);
+   if (num_outputs < 1)
+     {
+        ERR("fail to get tdm_display_get_output_count\n");
+        return EINA_FALSE;
+     }
+   e_comp_screen->num_outputs = num_outputs;
 
-             if (ok)
-               {
-                  if (!possible)
-                    {
-                       unsigned int refresh;
+   INF("E_COMP_SCREEN: num_outputs = %i", e_comp_screen->num_outputs);
 
-                       ecore_drm_output_position_get(output, &eout->config.geom.x,
-                                                     &eout->config.geom.y);
-                       ecore_drm_output_crtc_size_get(output, &eout->config.geom.w,
-                                                      &eout->config.geom.h);
+   for (i = 0; i < num_outputs; i++)
+     {
+        output = e_output_new(e_comp_screen, i);
+        if (!output) goto fail;
 
-                       ecore_drm_output_current_resolution_get(output,
-                                                               &eout->config.mode.w,
-                                                               &eout->config.mode.h,
-                                                               &refresh);
-                       eout->config.mode.refresh = refresh;
-                       eout->config.enabled =
-                          ((eout->config.mode.w != 0) && (eout->config.mode.h != 0));
+        if (!e_output_update(output))
+          {
+            ERR("fail to e_output_update.");
+            goto fail;
+          }
 
-                       printf("COMP TDM: '%s' %i %i %ix%i\n", eout->info.name,
-                              eout->config.geom.x, eout->config.geom.y,
-                              eout->config.geom.w, eout->config.geom.h);
+        e_comp_screen->outputs = eina_list_append(e_comp_screen->outputs, output);
 
-                    }
+        if (!e_output_connected(output)) continue;
 
-                  /* TODO: are rotations possible ?? */
-               }
-             eout->plane_count = 1; // TODO: get proper value using libtdm
-             printf("COMP TDM: planes %i\n", eout->plane_count);
-             for (j = 0; j < eout->plane_count; j++)
-               {
-                  printf("COMP TDM: added plane %i\n", j);
-                  Eina_Bool pri = EINA_FALSE;
-                  if (j == 0) pri = EINA_TRUE;
-                  e_plane_new(eout, j, pri);
-               }
+        /* setting with the best mode and enable the output */
+        mode = e_output_best_mode_find(output);
+        if (!mode)
+          {
+             ERR("fail to get best mode.");
+             goto fail;
+          }
 
-             r->outputs = eina_list_append(r->outputs, eout);
+        if (!e_output_mode_apply(output, mode))
+          {
+             ERR("fail to e_output_mode_apply.");
+             goto fail;
+          }
+        if (!e_output_dpms_set(output, E_OUTPUT_DPMS_ON))
+          {
+             ERR("fail to e_output_dpms.");
+             goto fail;
           }
      }
 
-   return r;
-}
+   //TODO: if there is no output connected, make the fake output which is connected.
+
 
-EINTERN Eina_Bool
-e_comp_screen_available(void)
-{
    return EINA_TRUE;
+fail:
+   _e_comp_screen_deinit_outputs(e_comp_screen);
+
+   return EINA_FALSE;
 }
 
-EINTERN void
-e_comp_screen_apply(void)
+static void
+_e_comp_screen_apply(E_Comp_Screen *e_comp_screen)
 {
    Ecore_Drm_Device *dev;
    Ecore_Drm_Output *out;
-   E_Output *eout;
+   E_Output *output;
+
    const Eina_List *l, *ll;
    int nw, nh, pw, ph, ww, hh;
    int minw, minh, maxw, maxh;
    int top_priority = 0;
 
+   EINA_SAFETY_ON_NULL_RETURN(e_comp);
+   EINA_SAFETY_ON_NULL_RETURN(e_comp->e_comp_screen);
+
    /* TODO: what the actual fuck */
    nw = e_comp_screen->w;
    nh = e_comp_screen->h;
@@ -377,24 +402,24 @@ e_comp_screen_apply(void)
 
         printf("COMP TDM: set vsize: %ix%i\n", ww, hh);
 
-        EINA_LIST_FOREACH(e_comp_screen->outputs, ll, eout)
+        EINA_LIST_FOREACH(e_comp_screen->outputs, ll, output)
           {
              Ecore_Drm_Output_Mode *mode = NULL;
-             printf("COMP TDM: find output for '%s'\n", eout->info.name);
+             printf("COMP TDM: find output for '%s'\n", output->info.name);
 
-             out = ecore_drm_device_output_name_find(dev, eout->info.name);
+             out = ecore_drm_device_output_name_find(dev, output->info.name);
              if (!out) continue;
 
-             mode = _e_comp_screen_mode_screen_find(eout, out);
+             mode = _e_comp_screen_mode_screen_find(output, out);
 
-             if (eout->config.priority > top_priority)
-               top_priority = eout->config.priority;
+             if (output->config.priority > top_priority)
+               top_priority = output->config.priority;
 
-             printf("\tCOMP TDM: Priority: %d\n", eout->config.priority);
+             printf("\tCOMP TDM: Priority: %d\n", output->config.priority);
 
              printf("\tCOMP TDM: Geom: %d %d %d %d\n",
-                    eout->config.geom.x, eout->config.geom.y,
-                    eout->config.geom.w, eout->config.geom.h);
+                    output->config.geom.x, output->config.geom.y,
+                    output->config.geom.w, output->config.geom.h);
 
              if (mode)
                {
@@ -405,18 +430,18 @@ e_comp_screen_apply(void)
                printf("\tCOMP TDM: No Valid Drm Mode Found\n");
 
              ecore_drm_output_mode_set(out, mode,
-                                       eout->config.geom.x, eout->config.geom.y);
-             if (eout->config.priority == top_priority)
+                                       output->config.geom.x, output->config.geom.y);
+             if (output->config.priority == top_priority)
                ecore_drm_output_primary_set(out);
 
              ecore_drm_output_enable(out);
 
              printf("\tCOMP TDM: Mode\n");
              printf("\t\tCOMP TDM: Geom: %d %d\n",
-                    eout->config.mode.w, eout->config.mode.h);
-             printf("\t\tCOMP TDM: Refresh: %f\n", eout->config.mode.refresh);
+                    output->config.mode.w, output->config.mode.h);
+             printf("\t\tCOMP TDM: Refresh: %f\n", output->config.mode.refresh);
              printf("\t\tCOMP TDM: Preferred: %d\n",
-                    eout->config.mode.preferred);
+                    output->config.mode.preferred);
           }
      }
 }
@@ -425,7 +450,7 @@ static Eina_Bool
 _drm_read_pixels(E_Comp_Wl_Output *output, void *pixels)
 {
    Ecore_Drm_Device *dev;
-   Ecore_Drm_Fb *fb = NULL;
+   Ecore_Drm_Fb *fb;
    const Eina_List *drm_devs, *l;
    int i = 0, bstride;
    unsigned char *s, *d = pixels;
@@ -438,7 +463,7 @@ _drm_read_pixels(E_Comp_Wl_Output *output, void *pixels)
         if (fb) break;
      }
 
-   EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE);
+   if (!fb) return EINA_FALSE;
 
    bstride = output->w * sizeof(int);
 
@@ -505,30 +530,239 @@ cleanup:
    TRACE_INPUT_END();
 }
 
+static void
+_e_comp_screen_config_eval(E_Comp_Screen *e_comp_screen)
+{
+   Eina_List *l;
+   E_Output *output;
+   int minx, miny, maxx, maxy;
+
+   minx = 65535;
+   miny = 65535;
+   maxx = -65536;
+   maxy = -65536;
+
+   EINA_LIST_FOREACH(e_comp_screen->outputs, l, output)
+     {
+        if (!output->config.enabled) continue;
+        if (output->config.geom.x < minx) minx = output->config.geom.x;
+        if (output->config.geom.y < miny) miny = output->config.geom.y;
+        if ((output->config.geom.x + output->config.geom.w) > maxx)
+          maxx = output->config.geom.x + output->config.geom.w;
+        if ((output->config.geom.y + output->config.geom.h) > maxy)
+          maxy = output->config.geom.y + output->config.geom.h;
+        printf("OUTPUT: s: '%s' @ %i %i - %ix%i\n",
+               output->info.name,
+               output->config.geom.x, output->config.geom.y,
+               output->config.geom.w, output->config.geom.h);
+     }
+   printf("OUTPUT:--- %i %i -> %i %i\n", minx, miny, maxx, maxy);
+   EINA_LIST_FOREACH(e_comp_screen->outputs, l, output)
+     {
+        output->config.geom.x -= minx;
+        output->config.geom.y -= miny;
+     }
+   e_comp_screen->w = maxx - minx;
+   e_comp_screen->h = maxy - miny;
+}
+
+static void
+_e_comp_screen_config_maxsize(E_Comp_Screen *e_comp_screen)
+{
+   Eina_List *l;
+   E_Output *output;
+   int maxx, maxy;
+
+   maxx = -65536;
+   maxy = -65536;
+   EINA_LIST_FOREACH(e_comp_screen->outputs, l, output)
+     {
+        if (!output->config.enabled) continue;
+        if ((output->config.geom.x + output->config.geom.w) > maxx)
+          maxx = output->config.geom.x + output->config.geom.w;
+        if ((output->config.geom.y + output->config.geom.h) > maxy)
+          maxy = output->config.geom.y + output->config.geom.h;
+        printf("OUTPUT: '%s': %i %i %ix%i\n",
+               output->info.name,
+               output->config.geom.x, output->config.geom.y,
+               output->config.geom.w, output->config.geom.h);
+     }
+   printf("OUTPUT: result max: %ix%i\n", maxx, maxy);
+   e_comp_screen->w = maxx;
+   e_comp_screen->h = maxy;
+}
+
+static int
+_e_comp_screen_e_screen_sort_cb(const void *data1, const void *data2)
+{
+   const E_Output *s1 = data1, *s2 = data2;
+   int dif;
+
+   dif = -(s1->config.priority - s2->config.priority);
+   if (dif == 0)
+     {
+        dif = s1->config.geom.x - s2->config.geom.x;
+        if (dif == 0)
+          dif = s1->config.geom.y - s2->config.geom.y;
+     }
+   return dif;
+}
+
+static void
+_e_comp_screen_e_screen_free(E_Screen *scr)
+{
+   free(scr->id);
+   free(scr);
+}
+
+static void
+_e_comp_screen_e_screens_set(E_Comp_Screen *e_comp_screen, Eina_List *screens)
+{
+   E_FREE_LIST(e_comp_screen->e_screens, _e_comp_screen_e_screen_free);
+   e_comp_screen->e_screens = screens;
+}
+
+EINTERN void
+e_comp_screen_e_screens_setup(E_Comp_Screen *e_comp_screen, int rw, int rh)
+{
+   int i;
+   E_Screen *screen;
+   Eina_List *outputs = NULL, *outputs_rem;
+   Eina_List *e_screens = NULL;
+   Eina_List *l, *ll;
+   E_Output *output, *s2, *s_chosen;
+   Eina_Bool removed;
+
+   if (!e_comp_screen->outputs) goto out;
+   // put screens in tmp list
+   EINA_LIST_FOREACH(e_comp_screen->outputs, l, output)
+     {
+        if ((output->config.enabled) &&
+            (output->config.geom.w > 0) &&
+            (output->config.geom.h > 0))
+          {
+             outputs = eina_list_append(outputs, output);
+          }
+     }
+   // remove overlapping screens - if a set of screens overlap, keep the
+   // smallest/lowest res
+   do
+     {
+        removed = EINA_FALSE;
+
+        EINA_LIST_FOREACH(outputs, l, output)
+          {
+             outputs_rem = NULL;
+
+             EINA_LIST_FOREACH(l->next, ll, s2)
+               {
+                  if (E_INTERSECTS(output->config.geom.x, output->config.geom.y,
+                                   output->config.geom.w, output->config.geom.h,
+                                   s2->config.geom.x, s2->config.geom.y,
+                                   s2->config.geom.w, s2->config.geom.h))
+                    {
+                       if (!outputs_rem)
+                         outputs_rem = eina_list_append(outputs_rem, output);
+                       outputs_rem = eina_list_append(outputs_rem, s2);
+                    }
+               }
+             // we have intersecting screens - choose the lowest res one
+             if (outputs_rem)
+               {
+                  removed = EINA_TRUE;
+                  // find the smallest screen (chosen one)
+                  s_chosen = NULL;
+                  EINA_LIST_FOREACH(outputs_rem, ll, s2)
+                    {
+                       if (!s_chosen) s_chosen = s2;
+                       else
+                         {
+                            if ((s_chosen->config.geom.w *
+                                 s_chosen->config.geom.h) >
+                                (s2->config.geom.w *
+                                 s2->config.geom.h))
+                              s_chosen = s2;
+                         }
+                    }
+                  // remove all from screens but the chosen one
+                  EINA_LIST_FREE(outputs_rem, s2)
+                    {
+                       if (s2 != s_chosen)
+                         outputs = eina_list_remove_list(outputs, l);
+                    }
+                  // break our list walk and try again
+                  break;
+               }
+          }
+     }
+   while (removed);
+   // sort screens by priority etc.
+   outputs = eina_list_sort(outputs, 0, _e_comp_screen_e_screen_sort_cb);
+   i = 0;
+   EINA_LIST_FOREACH(outputs, l, output)
+     {
+        screen = E_NEW(E_Screen, 1);
+        screen->escreen = screen->screen = i;
+        screen->x = output->config.geom.x;
+        screen->y = output->config.geom.y;
+        screen->w = output->config.geom.w;
+        screen->h = output->config.geom.h;
+        if (output->id) screen->id = strdup(output->id);
+
+        e_screens = eina_list_append(e_screens, screen);
+        INF("E INIT: SCREEN: [%i][%i], %ix%i+%i+%i",
+            i, i, screen->w, screen->h, screen->x, screen->y);
+        i++;
+     }
+   eina_list_free(outputs);
+   // if we have NO screens at all (above - i will be 0) AND we have no
+   // existing screens set up in xinerama - then just say root window size
+   // is the entire screen. this should handle the case where you unplug ALL
+   // screens from an existing setup (unplug external monitors and/or close
+   // laptop lid), in which case as long as at least one screen is configured
+   // in xinerama, it will be left-as is until next time we re-eval screen
+   // setup and have at least one screen
+   printf("e_comp_screen_e_screens_setup............... %i %p\n", i, e_comp_screen->e_screens);
+   if ((i == 0) && (!e_comp_screen->e_screens))
+     {
+out:
+        screen = E_NEW(E_Screen, 1);
+        screen->escreen = screen->screen = 0;
+        screen->x = 0;
+        screen->y = 0;
+        if ((rw > 0) && (rh > 0))
+          screen->w = rw, screen->h = rh;
+        else
+          ecore_evas_screen_geometry_get(e_comp->ee, NULL, NULL, &screen->w, &screen->h);
+        e_screens = eina_list_append(e_screens, screen);
+     }
+   _e_comp_screen_e_screens_set(e_comp_screen, e_screens);
+}
+
+EINTERN const Eina_List *
+e_comp_screen_e_screens_get(E_Comp_Screen *e_comp_screen)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, NULL);
+
+   return e_comp_screen->e_screens;
+}
+
 E_API Eina_Bool
 e_comp_screen_init()
 {
    E_Comp *comp;
+   E_Comp_Screen *e_comp_screen = NULL;
+
    int w = 0, h = 0, scr_w = 1, scr_h = 1;
    struct xkb_context *ctx = NULL;
    struct xkb_keymap *map = NULL;
    char buf[1024];
 
-   dont_set_ecore_drm_keymap = getenv("NO_ECORE_DRM_KEYMAP_CACHE") ? EINA_TRUE : EINA_FALSE;
-   dont_use_xkb_cache = getenv("NO_KEYMAP_CACHE") ? EINA_TRUE : EINA_FALSE;
-
-   TRACE_DS_BEGIN(WL_DRM:INIT);
-
+   TRACE_DS_BEGIN(E_COMP_SCREEN:INIT);
    if (!(comp = e_comp))
      {
-        comp = e_comp_new();
-        if (!comp)
-          {
-             TRACE_DS_END();
-             EINA_SAFETY_ON_NULL_RETURN_VAL(comp, EINA_FALSE);
-          }
-
-        comp->comp_type = E_PIXMAP_TYPE_WL;
+        TRACE_DS_END();
+        EINA_SAFETY_ON_NULL_RETURN_VAL(comp, EINA_FALSE);
      }
 
    /* set gl available if we have ecore_evas support */
@@ -538,13 +772,6 @@ e_comp_screen_init()
    INF("GL available:%d config engine:%d screen size:%dx%d",
        e_comp_gl_get(), e_comp_config_get()->engine, scr_w, scr_h);
 
-   if (e_config->xkb.use_cache && !dont_use_xkb_cache)
-     {
-        e_main_ts("\tDRM Keymap Init");
-        _e_comp_screen_keymap_set(&ctx, &map);
-        e_main_ts("\tDRM Keymap Init Done");
-     }
-
    if ((e_comp_gl_get()) &&
        (e_comp_config_get()->engine == E_COMP_ENGINE_GL))
      {
@@ -622,15 +849,53 @@ e_comp_screen_init()
 
    ecore_evas_callback_resize_set(e_comp->ee, _e_comp_screen_cb_ee_resize);
 
-   e_main_ts("\tE_Output Init");
-   if (!e_output_init())
+   /* e_comp_screen new */
+   e_comp_screen = _e_comp_screen_new();
+   if (!e_comp_screen)
      {
-        e_error_message_show(_("Enlightenment cannot initialize output!\n"));
         TRACE_DS_END();
-        return EINA_FALSE;
+        EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, EINA_FALSE);
+     }
+   e_comp->e_comp_screen = e_comp_screen;
+
+   e_main_ts("\tE_Outputs Init");
+   if (e_comp_gl_get())
+     {
+        if (!_e_comp_screen_init_outputs(e_comp_screen))
+          {
+             e_error_message_show(_("Enlightenment cannot initialize outputs!\n"));
+             _e_comp_screen_del(e_comp_screen);
+             e_comp->e_comp_screen = NULL;
+             TRACE_DS_END();
+             return EINA_FALSE;
+          }
+     }
+   else
+     {
+        if (!_e_comp_screen_init_drm_outputs(e_comp_screen))
+          {
+             e_error_message_show(_("Enlightenment cannot initialize outputs!\n"));
+             _e_comp_screen_del(e_comp_screen);
+             e_comp->e_comp_screen = NULL;
+             TRACE_DS_END();
+             return EINA_FALSE;
+          }
+
+        // take current e_output config and apply it to the driver
+        _e_comp_screen_config_maxsize(e_comp_screen);
+        printf("OUTPUT: eval config...\n");
+        _e_comp_screen_config_eval(e_comp_screen);
+        printf("OUTPUT: really apply config...\n");
+        _e_comp_screen_apply(e_comp_screen);
+        printf("OUTPUT: done config...\n");
      }
-   e_output_screens_setup(-1, -1);
-   e_main_ts("\tE_Output Init Done");
+
+   if (!E_EVENT_SCREEN_CHANGE) E_EVENT_SCREEN_CHANGE = ecore_event_type_new();
+
+   ecore_event_add(E_EVENT_SCREEN_CHANGE, NULL, NULL, NULL);
+
+   e_comp_screen_e_screens_setup(e_comp_screen, -1, -1);
+   e_main_ts("\tE_Outputs Init Done");
 
    e_main_ts("\tE_Comp_Wl Init");
    if (!e_comp_wl_init())
@@ -640,9 +905,14 @@ e_comp_screen_init()
      }
    e_main_ts("\tE_Comp_Wl Init Done");
 
+   /* canvas */
    e_main_ts("\tE_Comp_Canvas Init");
    if (!e_comp_canvas_init(w, h))
      {
+        e_error_message_show(_("Enlightenment cannot initialize outputs!\n"));
+        _e_comp_screen_deinit_outputs(e_comp->e_comp_screen);
+        _e_comp_screen_del(e_comp_screen);
+        e_comp->e_comp_screen = NULL;
         TRACE_DS_END();
         return EINA_FALSE;
      }
@@ -650,6 +920,7 @@ e_comp_screen_init()
 
    e_comp_wl->screenshooter.read_pixels = _drm_read_pixels;
 
+   /* pointer */
    ecore_evas_pointer_xy_get(e_comp->ee,
                              &e_comp_wl->ptr.x,
                              &e_comp_wl->ptr.y);
@@ -666,6 +937,17 @@ e_comp_screen_init()
      }
    e_main_ts("\tE_Pointer New Done");
 
+   /* keymap */
+   dont_set_ecore_drm_keymap = getenv("NO_ECORE_DRM_KEYMAP_CACHE") ? EINA_TRUE : EINA_FALSE;
+   dont_use_xkb_cache = getenv("NO_KEYMAP_CACHE") ? EINA_TRUE : EINA_FALSE;
+
+   if (e_config->xkb.use_cache && !dont_use_xkb_cache)
+     {
+        e_main_ts("\tDRM Keymap Init");
+        _e_comp_screen_keymap_set(&ctx, &map);
+        e_main_ts("\tDRM Keymap Init Done");
+     }
+
    /* FIXME: We need a way to trap for user changing the keymap inside of E
     *        without the event coming from X11 */
 
@@ -686,10 +968,14 @@ e_comp_screen_init()
    e_main_ts("\tE_Comp_WL Keymap Init Done");
 
    E_LIST_HANDLER_APPEND(event_handlers, ECORE_DRM_EVENT_ACTIVATE,         _e_comp_screen_cb_activate,         comp);
-   E_LIST_HANDLER_APPEND(event_handlers, ECORE_DRM_EVENT_OUTPUT,           _e_comp_screen_cb_output,           comp);
+   E_LIST_HANDLER_APPEND(event_handlers, ECORE_DRM_EVENT_OUTPUT,           _e_comp_screen_cb_output_drm,       comp);
    E_LIST_HANDLER_APPEND(event_handlers, ECORE_DRM_EVENT_INPUT_DEVICE_ADD, _e_comp_screen_cb_input_device_add, comp);
    E_LIST_HANDLER_APPEND(event_handlers, ECORE_DRM_EVENT_INPUT_DEVICE_DEL, _e_comp_screen_cb_input_device_del, comp);
 
+#ifdef ENABLE_HWC_MULTI
+   ecore_idle_enterer_add(_e_comp_screen_commit_idle_cb, comp);
+#endif
+
    TRACE_DS_END();
 
    return EINA_TRUE;
@@ -698,12 +984,42 @@ e_comp_screen_init()
 E_API void
 e_comp_screen_shutdown()
 {
+   if (!e_comp) return;
+   if (!e_comp->e_comp_screen) return;
+
    /* shutdown ecore_drm */
    /* ecore_drm_shutdown(); */
-   e_output_shutdown();
+
+   _e_comp_screen_deinit_outputs(e_comp->e_comp_screen);
 
    dont_set_ecore_drm_keymap = EINA_FALSE;
    dont_use_xkb_cache = EINA_FALSE;
    E_FREE_LIST(event_handlers, ecore_event_handler_del);
 
+   /* delete e_comp_sreen */
+   _e_comp_screen_del(e_comp->e_comp_screen);
+   e_comp->e_comp_screen = NULL;
+}
+
+EINTERN Eina_Bool
+e_comp_screen_hwc_setup(E_Comp_Screen *e_comp_screen)
+{
+   Eina_List *l, *ll;
+   E_Output *output = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, EINA_FALSE);
+
+   EINA_LIST_FOREACH_SAFE(e_comp_screen->outputs, l, ll, output)
+     {
+        if (!output) continue;
+        if (!output->config.enabled) continue;
+
+        if (!e_output_hwc_setup(output))
+          {
+             ERR("fail to e_ouptut_hwc_setup.");
+             continue;
+          }
+     }
+
+   return EINA_TRUE;
 }
index f6b01dba5ac7d12fe77ce91c6579d60cc068ed4c..df9b4834a84db03f8cd1bc1bec612310808c01b7 100644 (file)
@@ -5,15 +5,42 @@
 #ifndef E_COMP_SCREEN_H
 #define E_COMP_SCREEN_H
 
+#include <tdm.h>
 
-EINTERN Eina_Bool       e_comp_screen_available(void);
-EINTERN void            e_comp_screen_stub(void);
-EINTERN void            e_comp_screen_apply(void);
-EINTERN E_Comp_Screen * e_comp_screen_init_outputs(void);
-EINTERN void            e_comp_screen_dpms(int set);
+typedef struct _E_Comp_Screen   E_Comp_Screen;
+typedef struct _E_Screen        E_Screen;
 
-E_API Eina_Bool         e_comp_screen_init(void);
-E_API void              e_comp_screen_shutdown(void);
+struct _E_Comp_Screen
+{
+   Eina_List     *outputs; // available screens
+   int            w, h; // virtual resolution (calculated)
+   unsigned char  ignore_hotplug_events;
+   unsigned char  ignore_acpi_events;
+   Eina_List     *e_screens;
+
+   int            num_outputs;
+   tdm_display   *tdisplay;
+
+   /* for sw compositing */
+   const Eina_List *devices;
+};
+
+
+struct _E_Screen
+{
+   int screen, escreen;
+   int x, y, w, h;
+   char *id; // this is the same id we get from _E_Output so look it up there
+};
+
+extern E_API int E_EVENT_SCREEN_CHANGE;
+
+E_API   Eina_Bool         e_comp_screen_init(void);
+E_API   void              e_comp_screen_shutdown(void);
+EINTERN Eina_Bool         e_comp_screen_hwc_setup(E_Comp_Screen *e_comp_screen);
+
+EINTERN void              e_comp_screen_e_screens_setup(E_Comp_Screen *e_comp_screen, int rw, int rh);
+EINTERN const Eina_List * e_comp_screen_e_screens_get(E_Comp_Screen *e_comp_screen);
 
 #endif /*E_COMP_SCREEN_H*/
 
index 6874485d5a1053778c8fa1d9f25f84d7fb0ab2b1..8e41e7b2340a7b7926b68829f0b597222060239c 100644 (file)
@@ -1803,9 +1803,12 @@ _e_comp_wl_cb_randr_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *e
 {
    Eina_List *l;
    E_Output *eout;
+   E_Comp_Screen *e_comp_screen;
    unsigned int transform = WL_OUTPUT_TRANSFORM_NORMAL;
 
-   if (!e_comp_screen) return ECORE_CALLBACK_RENEW;
+   if (!e_comp) return ECORE_CALLBACK_RENEW;
+   if (!e_comp->e_comp_screen) return ECORE_CALLBACK_RENEW;
+   e_comp_screen = e_comp->e_comp_screen;
 
    EINA_LIST_FOREACH(e_comp_screen->outputs, l, eout)
      {
index 91e6d078539b3cf8b1861f7495d3a3bb90902c6c..86ca87b80bf2138733fa3d9398222e93d1e6a7fc 100644 (file)
@@ -43,6 +43,7 @@
 #include "e_env.h"
 #include "e_log.h"
 #include "e_dbusmenu.h"
+#include "e_comp_screen.h"
 #include "e_comp.h"
 #include "e_comp_cfdata.h"
 #include "e_comp_canvas.h"
@@ -50,7 +51,6 @@
 #include "e_hints.h"
 #include "e_plane.h"
 #include "e_comp_hwc.h"
-#include "e_comp_screen.h"
 #include "e_output.h"
 #include "e_comp_wl.h"
 #include "e_comp_wl_data.h"
index d09799f20988d21fddf78bb71f7ecf775279e126..b12afc9d64eef7bc14afdc20c7dc5352735f6763 100644 (file)
 #include "e.h"
 
+# include <Evas_Engine_GL_Drm.h>
 
-/////////////////////////////////////////////////////////////////////////
-static void                    _do_apply(void);
-static void                    _info_free(E_Comp_Screen *r);
-static void                    _screen_config_eval(void);
-static void                    _screen_config_maxsize(void);
+static void
+_e_output_cb_output_change(tdm_output *toutput,
+                                  tdm_output_change_type type,
+                                  tdm_value value,
+                                  void *user_data)
+{
+   E_Output *e_output = NULL;
+   E_OUTPUT_DPMS edpms;
+   tdm_output_dpms tdpms = (tdm_output_dpms)value.u32;
 
-/////////////////////////////////////////////////////////////////////////
+   EINA_SAFETY_ON_NULL_RETURN(toutput);
+   EINA_SAFETY_ON_NULL_RETURN(user_data);
 
-E_API E_Comp_Screen   *e_comp_screen = NULL;
+   e_output = (E_Output *)user_data;
 
-E_API int              E_EVENT_SCREEN_CHANGE = 0;
+   switch (type)
+     {
+       case TDM_OUTPUT_CHANGE_DPMS:
+          if (tdpms == TDM_OUTPUT_DPMS_OFF) edpms = E_OUTPUT_DPMS_OFF;
+          else if (tdpms == E_OUTPUT_DPMS_ON) edpms = E_OUTPUT_DPMS_ON;
+          else if (tdpms == TDM_OUTPUT_DPMS_STANDBY) edpms = E_OUTPUT_DPMS_STANDBY;
+          else if (tdpms == TDM_OUTPUT_DPMS_SUSPEND) edpms = E_OUTPUT_DPMS_SUSPEND;
+          else edpms = e_output->dpms;
+
+          ERR("[cyeon] dpms change:%d", edpms);
+          e_output->dpms = edpms;
+          break;
+       default:
+          break;
+     }
+}
 
-static Eina_List *all_screens = NULL; // e_screen list
+static void
+_e_output_commit_hanler(tdm_output *output, unsigned int sequence,
+                                  unsigned int tv_sec, unsigned int tv_usec,
+                                  void *user_data)
+{
+   Eina_List *data_list = user_data;
+   E_Plane_Commit_Data *data = NULL;
+   Eina_List *l, *ll;
 
-/////////////////////////////////////////////////////////////////////////
-EINTERN Eina_Bool
-e_output_init(void)
+   EINA_LIST_FOREACH_SAFE(data_list, l, ll, data)
+     {
+        e_plane_commit_data_release(data);
+        data_list = eina_list_remove_list(data_list, l);
+        data = NULL;
+     }
+}
+
+static Eina_Bool
+_e_output_commit(E_Output *output)
 {
-   if (!E_EVENT_SCREEN_CHANGE) E_EVENT_SCREEN_CHANGE = ecore_event_type_new();
-   if (!e_comp_screen_available()) return EINA_FALSE;
+   Eina_List *data_list = NULL;
+   E_Plane_Commit_Data *data = NULL;
+   E_Plane *plane = NULL;
+   Eina_List *l, *ll;
+   tdm_error error;
 
-   e_comp_screen = e_comp_screen_init_outputs();
+   EINA_LIST_REVERSE_FOREACH(output->planes, l, plane)
+     {
+        data = e_plane_commit_data_aquire(plane);
+        if (!data) continue;
+        data_list = eina_list_append(data_list, data);
+     }
 
-   _do_apply();
+   error = tdm_output_commit(output->toutput, 0, _e_output_commit_hanler, data_list);
+   if (error != TDM_ERROR_NONE)
+     {
+        ERR("fail to tdm_output_commit");
+        EINA_LIST_FOREACH_SAFE(data_list, l, ll, data)
+          {
+             data_list = eina_list_remove_list(data_list, l);
+             e_plane_commit_data_release(data);
+             data = NULL;
+          }
+        return EINA_FALSE;
+     }
 
-   ecore_event_add(E_EVENT_SCREEN_CHANGE, NULL, NULL, NULL);
+   return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_output_init(void)
+{
+#if 0
+   Evas_Engine_Info_GL_Drm *einfo;
 
+   /* TODO: enable hwc according to the conf->hwc */
+   if (e_comp_gl_get())
+     {
+        /* get the evas_engine_gl_drm information */
+        einfo = (Evas_Engine_Info_GL_Drm *)evas_engine_info_get(e_comp->evas);
+        if (!einfo) return EINA_FALSE;
+        /* enable hwc to evas engine gl_drm */
+        einfo->info.hwc_enable = EINA_TRUE;
+     }
+#endif
    return EINA_TRUE;
 }
 
-EINTERN int
+EINTERN void
 e_output_shutdown(void)
 {
-   // free up screen info
-   _info_free(e_comp_screen);
-   e_comp_screen = NULL;
-
-   return 1;
+   ;
 }
 
-/////////////////////////////////////////////////////////////////////////
+EINTERN E_Output *
+e_output_drm_new(Ecore_Drm_Output *output)
+{
+   E_Output *eout = NULL;
+   int i;
 
-static void
-_do_apply(void)
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
+
+   eout = E_NEW(E_Output, 1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(eout, NULL);
+
+   eout->info.name = ecore_drm_output_name_get(output);
+   printf("E_OUTPUT: .... out %s\n", eout->info.name);
+
+    // TODO: get proper value using libtdm
+   eout->plane_count = 1;
+   printf("COMP TDM: planes %i\n", eout->plane_count);
+   for (i = 0; i < eout->plane_count; i++)
+     {
+        printf("COMP TDM: added plane %i\n", i);
+        // TODO: primary layer condition (0 is temp condition)
+        e_plane_new(eout, i);
+     }
+
+   eout->output = output;
+
+   return eout;
+}
+
+EINTERN E_Output *
+e_output_new(E_Comp_Screen *e_comp_screen, int index)
 {
-   // take current e_output config and apply it to the driver
-   _screen_config_maxsize();
-   printf("OUTPUT: eval config...\n");
-   _screen_config_eval();
-   printf("OUTPUT: really apply config...\n");
-   e_comp_screen_apply();
-   printf("OUTPUT: done config...\n");
+   E_Output *output = NULL;
+   E_Plane *plane = NULL;
+   tdm_output *toutput = NULL;
+   tdm_error error;
+   char *id = NULL;
+   const char *name;
+   int num_layers;
+   int i;
+   int size = 0;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, NULL);
+
+   output = E_NEW(E_Output, 1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
+   output->index = index;
+
+   toutput = tdm_display_get_output(e_comp_screen->tdisplay, index, NULL);
+   if (!toutput) goto fail;
+   output->toutput = toutput;
+
+   error = tdm_output_get_model_info(toutput, NULL, NULL, &name);
+   if (error != TDM_ERROR_NONE) goto fail;
+
+   error = tdm_output_add_change_handler(toutput, _e_output_cb_output_change, output);
+   EINA_SAFETY_ON_FALSE_GOTO(error == TDM_ERROR_NONE, fail);
+
+   size = strlen(name) + 4;
+   id = calloc(1, size);
+   if (!id) return NULL;
+   snprintf(id, size, "%s-%d", name, index);
+
+   output->id = id;
+   INF("E_OUTPUT: (%d) output_id = %s", index, output->id);
+
+   tdm_output_get_layer_count(toutput, &num_layers);
+   if (num_layers < 1)
+     {
+        ERR("fail to get tdm_output_get_layer_count\n");
+        goto fail;
+     }
+   output->plane_count = num_layers;
+   INF("E_OUTPUT: num_planes %i", output->plane_count);
+
+   if (!e_plane_init())
+     {
+        ERR("fail to e_plane_init.");
+        goto fail;
+     }
+
+   for (i = 0; i < output->plane_count; i++)
+     {
+        plane = e_plane_new(output, i);
+        if (!plane)
+          {
+             ERR("fail to create the e_plane.");
+             goto fail;
+          }
+        output->planes = eina_list_append(output->planes, plane);
+     }
+
+   output->e_comp_screen = e_comp_screen;
+
+
+   return output;
+
+fail:
+   if (output) e_output_del(output);
+
+   return NULL;
 }
 
-static void
-_info_free(E_Comp_Screen *r)
+EINTERN void
+e_output_del(E_Output *output)
 {
-   E_Output *output;
+   E_Plane *plane;
    E_Output_Mode *m;
-   E_Plane *ep;
 
-   if (!r) return;
-   // free up our output screen data
-   EINA_LIST_FREE(r->outputs, output)
+   if (!output) return;
+
+   e_plane_shutdown();
+
+   if (output->id) free(output->id);
+   if (output->info.screen) free(output->info.screen);
+   if (output->info.name) free(output->info.name);
+   if (output->info.edid) free(output->info.edid);
+
+   tdm_output_remove_change_handler(output->toutput, _e_output_cb_output_change, output);
+
+   EINA_LIST_FREE(output->info.modes, m) free(m);
+
+   EINA_LIST_FREE(output->planes, plane) e_plane_free(plane);
+   free(output);
+}
+
+EINTERN Eina_Bool
+e_output_update(E_Output *output)
+{
+   Eina_List *m = NULL;
+   Eina_List *modes = NULL;
+   Eina_Bool connected = EINA_TRUE;
+   tdm_error error;
+   tdm_output_conn_status status;
+   int i;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
+
+   error = tdm_output_get_conn_status(output->toutput, &status);
+   if (error != TDM_ERROR_NONE)
+     {
+        ERR("failt to get conn status.");
+        return EINA_FALSE;
+     }
+
+   if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) connected = EINA_FALSE;
+
+   if (connected)
+     {
+        /* disconnect --> connect */
+        if (connected != output->info.connected)
+          {
+             char *name;
+             const char *screen;
+             const char *maker;
+             unsigned int phy_w, phy_h;
+             const tdm_output_mode *tmodes = NULL;
+             int num_tmodes = 0;
+             int size = 0;
+
+             error = tdm_output_get_model_info(output->toutput, &maker, &screen, NULL);
+             if (error != TDM_ERROR_NONE)
+               {
+                  ERR("fail to get model info.");
+                  return EINA_FALSE;
+               }
+
+             if (maker)
+               {
+                  size = strlen(output->id) + 1 + strlen(maker) + 1;
+                  name = calloc(1, size);
+                  if (!name) return EINA_FALSE;
+                  snprintf(name, size, "%s-%s", output->id, maker);
+               }
+             else
+               {
+                  size = strlen(output->id) + 1;
+                  name = calloc(1, size);
+                  if (!name) return EINA_FALSE;
+                  snprintf(name, size, "%s", output->id);
+               }
+             INF("E_OUTPUT: screen = %s, name = %s", screen, name);
+
+             error = tdm_output_get_physical_size(output->toutput, &phy_w, &phy_h);
+             if (error != TDM_ERROR_NONE)
+               {
+                  ERR("fail to get physical_size.");
+                  free(name);
+                  return EINA_FALSE;
+               }
+
+             error = tdm_output_get_available_modes(output->toutput, &tmodes, &num_tmodes);
+             if (error != TDM_ERROR_NONE || num_tmodes == 0)
+               {
+                  ERR("fail to get tmodes");
+                  free(name);
+                  return EINA_FALSE;
+               }
+
+             for (i = 0; i < num_tmodes; i++)
+               {
+                  E_Output_Mode *rmode;
+
+                  rmode = malloc(sizeof(E_Output_Mode));
+                  if (!rmode) continue;
+
+                  rmode->w = tmodes[i].hdisplay;
+                  rmode->h = tmodes[i].vdisplay;
+                  rmode->refresh = tmodes[i].vrefresh;
+                  rmode->preferred = (tmodes[i].flags & TDM_OUTPUT_MODE_TYPE_PREFERRED);
+                  rmode->tmode = &tmodes[i];
+
+                  modes = eina_list_append(modes, rmode);
+               }
+
+             /* resetting the output->info */
+             if (output->info.screen) free(output->info.screen);
+             if (output->info.name) free(output->info.name);
+             EINA_LIST_FREE(output->info.modes, m) free(m);
+
+             output->info.screen = strdup(screen);
+             output->info.name = name;
+             output->info.modes = modes;
+             output->info.size.w = phy_w;
+             output->info.size.h = phy_h;
+
+             output->info.connected = EINA_TRUE;
+
+             INF("E_OUTPUT: id(%s) connected..", output->id);
+          }
+
+#if 0
+        /* check the crtc setting */
+        if (status != TDM_OUTPUT_CONN_STATUS_MODE_SETTED)
+          {
+              const tdm_output_mode *mode = NULL;
+
+              error = tdm_output_get_mode(output->toutput, &mode);
+              if (error != TDM_ERROR_NONE || mode == NULL)
+                {
+                   ERR("fail to get mode.");
+                   return EINA_FALSE;
+                }
+
+              output->config.geom.x = 0;
+              output->config.geom.y = 0;
+              output->config.geom.w = mode->hdisplay;
+              output->config.geom.h = mode->vdisplay;
+
+              output->config.mode.w = mode->hdisplay;
+              output->config.mode.h = mode->vdisplay;
+              output->config.mode.refresh = mode->vrefresh;
+
+              output->config.enabled = 1;
+
+              INF("E_OUTPUT: '%s' %i %i %ix%i", output->info.name,
+                     output->config.geom.x, output->config.geom.y,
+                     output->config.geom.w, output->config.geom.h);
+          }
+#endif
+
+     }
+   else
      {
-        free(output->id);
-        free(output->info.screen);
-        free(output->info.name);
-        free(output->info.edid);
+        output->info.connected = EINA_FALSE;
+
+        /* reset output info */
+        if (output->info.screen)
+          {
+             free(output->info.screen);
+             output->info.screen = NULL;
+          }
+        if (output->info.name)
+          {
+             free(output->info.name);
+             output->info.name = NULL;
+          }
         EINA_LIST_FREE(output->info.modes, m) free(m);
-        EINA_LIST_FREE(output->planes, ep) e_plane_free(ep);
-        free(output);
+        output->info.modes = NULL;
+
+        output->info.size.w = 0;
+        output->info.size.h = 0;
+
+        /* reset output config */
+        output->config.geom.x = 0;
+        output->config.geom.y = 0;
+        output->config.geom.w = 0;
+        output->config.geom.h = 0;
+
+        output->config.mode.w = 0;
+        output->config.mode.h = 0;
+        output->config.mode.refresh = 0;
+
+        output->config.rotation = 0;
+        output->config.priority = 0;
+        output->config.enabled = 0;
+
+        INF("E_OUTPUT: disconnected.. id: %s", output->id);
      }
-   free(r);
+
+   return EINA_TRUE;
 }
 
-static void
-_screen_config_eval(void)
+EINTERN Eina_Bool
+e_output_mode_apply(E_Output *output, E_Output_Mode *mode)
 {
-   Eina_List *l;
-   E_Output *output;
-   int minx, miny, maxx, maxy;
+   tdm_error error;
 
-   minx = 65535;
-   miny = 65535;
-   maxx = -65536;
-   maxy = -65536;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
 
-   EINA_LIST_FOREACH(e_comp_screen->outputs, l, output)
+   if (!output->info.connected)
      {
-        if (!output->config.enabled) continue;
-        if (output->config.geom.x < minx) minx = output->config.geom.x;
-        if (output->config.geom.y < miny) miny = output->config.geom.y;
-        if ((output->config.geom.x + output->config.geom.w) > maxx)
-          maxx = output->config.geom.x + output->config.geom.w;
-        if ((output->config.geom.y + output->config.geom.h) > maxy)
-          maxy = output->config.geom.y + output->config.geom.h;
-        printf("OUTPUT: s: '%s' @ %i %i - %ix%i\n",
-               output->info.name,
-               output->config.geom.x, output->config.geom.y,
-               output->config.geom.w, output->config.geom.h);
+        ERR("output is not connected.");
+        return EINA_FALSE;
      }
-   printf("OUTPUT:--- %i %i -> %i %i\n", minx, miny, maxx, maxy);
-   EINA_LIST_FOREACH(e_comp_screen->outputs, l, output)
+
+   error = tdm_output_set_mode(output->toutput, mode->tmode);
+   if (error != TDM_ERROR_NONE)
      {
-        output->config.geom.x -= minx;
-        output->config.geom.y -= miny;
+        ERR("fail to set tmode.");
+        return EINA_FALSE;
      }
-   e_comp_screen->w = maxx - minx;
-   e_comp_screen->h = maxy - miny;
+
+   output->config.geom.x = 0;
+   output->config.geom.y = 0;
+   output->config.geom.w = mode->w;
+   output->config.geom.h = mode->h;
+
+   output->config.mode.w = mode->w;
+   output->config.mode.h = mode->h;
+   output->config.mode.refresh = mode->refresh;
+
+   output->config.enabled = 1;
+
+   INF("E_OUTPUT: '%s' %i %i %ix%i", output->info.name,
+       output->config.geom.x, output->config.geom.y,
+       output->config.geom.w, output->config.geom.h);
+
+   return EINA_TRUE;
 }
 
-static void
-_screen_config_maxsize(void)
+EINTERN Eina_Bool
+e_output_hwc_setup(E_Output *output)
 {
-   Eina_List *l;
-   E_Output *output;
-   int maxx, maxy;
+   Eina_List *l, *ll;
+   E_Plane *plane = NULL;
 
-   maxx = -65536;
-   maxy = -65536;
-   EINA_LIST_FOREACH(e_comp_screen->outputs, l, output)
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
+
+   EINA_LIST_FOREACH_SAFE(output->planes, l, ll, plane)
      {
-        if (!output->config.enabled) continue;
-        if ((output->config.geom.x + output->config.geom.w) > maxx)
-          maxx = output->config.geom.x + output->config.geom.w;
-        if ((output->config.geom.y + output->config.geom.h) > maxy)
-          maxy = output->config.geom.y + output->config.geom.h;
-        printf("OUTPUT: '%s': %i %i %ix%i\n",
-               output->info.name,
-               output->config.geom.x, output->config.geom.y,
-               output->config.geom.w, output->config.geom.h);
+        if (plane->is_primary)
+          {
+             if (!e_plane_hwc_setup(plane)) return EINA_FALSE;
+             else return EINA_TRUE;
+          }
      }
-   printf("OUTPUT: result max: %ix%i\n", maxx, maxy);
-   e_comp_screen->w = maxx;
-   e_comp_screen->h = maxy;
+
+   return EINA_FALSE;
 }
 
-static int
-_screen_sort_cb(const void *data1, const void *data2)
+
+EINTERN E_Output_Mode *
+e_output_best_mode_find(E_Output *output)
 {
-   const E_Output *s1 = data1, *s2 = data2;
-   int dif;
+   Eina_List *l = NULL;
+   E_Output_Mode *mode = NULL;
+   E_Output_Mode *best_mode = NULL;
+   int best_size = 0;
+   int size = 0;
+   double best_refresh = 0.0;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output->info.modes, NULL);
+
+  if (!output->info.connected)
+     {
+        ERR("output is not connected.");
+        return EINA_FALSE;
+     }
 
-   dif = -(s1->config.priority - s2->config.priority);
-   if (dif == 0)
+   EINA_LIST_FOREACH(output->info.modes, l, mode)
      {
-        dif = s1->config.geom.x - s2->config.geom.x;
-        if (dif == 0)
-          dif = s1->config.geom.y - s2->config.geom.y;
+        size = mode->w + mode->h;
+        if (size > best_size) best_mode = mode;
+        if (size == best_size && mode->refresh > best_refresh) best_mode = mode;
      }
-   return dif;
+
+   return best_mode;
 }
 
-static void
-_escreen_free(E_Screen *scr)
+EINTERN Eina_Bool
+e_output_connected(E_Output *output)
 {
-   free(scr->id);
-   free(scr);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
+
+   return output->info.connected;
 }
 
-void
-_escreens_set(Eina_List *screens)
+EINTERN Eina_Bool
+e_output_dpms_set(E_Output *output, E_OUTPUT_DPMS val)
 {
-   E_FREE_LIST(all_screens, _escreen_free);
-   all_screens = screens;
+   tdm_output_dpms tval;
+   Eina_Bool ret = EINA_TRUE;
+   tdm_error error;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
+
+   if (val == E_OUTPUT_DPMS_OFF) tval = TDM_OUTPUT_DPMS_OFF;
+   else if (val == E_OUTPUT_DPMS_ON) tval = TDM_OUTPUT_DPMS_ON;
+   else if (val == E_OUTPUT_DPMS_STANDBY) tval = TDM_OUTPUT_DPMS_STANDBY;
+   else if (val == E_OUTPUT_DPMS_SUSPEND) tval = TDM_OUTPUT_DPMS_SUSPEND;
+   else ret = EINA_FALSE;
+
+   if (!ret) return EINA_FALSE;
+
+   error = tdm_output_set_dpms(output->toutput, tval);
+   if (error != TDM_ERROR_NONE)
+     {
+        ERR("fail to set the dpms(value:%d).", tval);
+        return EINA_FALSE;
+     }
+
+   output->dpms = val;
+
+   return EINA_TRUE;
 }
 
-EINTERN void
-e_output_screens_setup(int rw, int rh)
+static char *
+_e_output_drm_model_get(Ecore_Drm_Output *output)
 {
-   int i;
-   E_Screen *screen;
-   Eina_List *outputs = NULL, *outputs_rem;
-   Eina_List *e_screens = NULL;
-   Eina_List *l, *ll;
-   E_Output *output, *s2, *s_chosen;
-   Eina_Bool removed;
+   const char *model;
 
-   if ((!e_comp_screen) || (!e_comp_screen->outputs)) goto out;
-   // put screens in tmp list
-   EINA_LIST_FOREACH(e_comp_screen->outputs, l, output)
+   model = ecore_drm_output_model_get(output);
+   if (!model) return NULL;
+
+   return strdup(model);
+}
+
+EINTERN Eina_Bool
+e_output_drm_update(E_Output *eout)
+{
+   Eina_List *m = NULL;
+   Eina_List *modes = NULL;
+   Eina_Bool connected;
+   E_Comp_Screen *e_comp_screen;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp->e_comp_screen, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(eout, EINA_FALSE);
+
+   e_comp_screen = e_comp->e_comp_screen;
+
+   connected = ecore_drm_output_connected_get(eout->output);
+   if (connected)
      {
-        if ((output->config.enabled) &&
-            (output->config.geom.w > 0) &&
-            (output->config.geom.h > 0))
+        /* disconnect --> connect */
+        if (connected != eout->info.connected)
           {
-             outputs = eina_list_append(outputs, output);
-          }
-     }
-   // remove overlapping screens - if a set of screens overlap, keep the
-   // smallest/lowest res
-   do
-     {
-        removed = EINA_FALSE;
+             int len = 0;
+             char *id;
+             char *screen;
+             char *edid;
+             int phy_w, phy_h;
+             Ecore_Drm_Output_Mode *omode;
+
+             screen = _e_output_drm_model_get(eout->output);
+             edid = ecore_drm_output_edid_get(eout->output);
+             if (eout->info.edid)
+               id = malloc(strlen(eout->info.name) + 1 + strlen(eout->info.edid) + 1);
+             else
+               id = malloc(strlen(eout->info.name) + 1 + 1);
+             if (!id)
+               {
+                  free(edid);
+                  return EINA_FALSE;
+               }
+             len = strlen(eout->info.name);
+             strncpy(id, eout->info.name, len + 1);
+             strncat(id, "/", 1);
+             if (eout->info.edid) strncat(id, edid, strlen(edid));
 
-        EINA_LIST_FOREACH(outputs, l, output)
-          {
-             outputs_rem = NULL;
+             printf("E_OUTPUT: ...... screen: %s\n", id);
 
-             EINA_LIST_FOREACH(l->next, ll, s2)
+             ecore_drm_output_physical_size_get(eout->output, &phy_w, &phy_h);
+
+             EINA_LIST_FOREACH(ecore_drm_output_modes_get(eout->output), m, omode)
                {
-                  if (E_INTERSECTS(output->config.geom.x, output->config.geom.y,
-                                   output->config.geom.w, output->config.geom.h,
-                                   s2->config.geom.x, s2->config.geom.y,
-                                   s2->config.geom.w, s2->config.geom.h))
-                    {
-                       if (!outputs_rem)
-                         outputs_rem = eina_list_append(outputs_rem, output);
-                       outputs_rem = eina_list_append(outputs_rem, s2);
-                    }
+                  E_Output_Mode *rmode;
+
+                  rmode = malloc(sizeof(E_Output_Mode));
+                  if (!rmode) continue;
+
+                  rmode->w = omode->width;
+                  rmode->h = omode->height;
+                  rmode->refresh = omode->refresh;
+                  rmode->preferred = (omode->flags & DRM_MODE_TYPE_PREFERRED);
+
+                  modes = eina_list_append(modes, rmode);
                }
-             // we have intersecting screens - choose the lowest res one
-             if (outputs_rem)
+
+             free(eout->id);
+             free(eout->info.screen);
+             free(eout->info.edid);
+             EINA_LIST_FREE(eout->info.modes, m) free(m);
+
+             eout->id = id;
+             eout->info.screen = screen;
+             eout->info.edid = edid;
+             eout->info.modes = modes;
+             eout->info.size.w = phy_w;
+             eout->info.size.h = phy_h;
+
+             eout->info.connected = EINA_TRUE;
+
+             printf("E_OUTPUT: connected.. id: %s\n", eout->id);
+          }
+
+        /* check the crtc setting */
+        const Eina_List *l;
+        int i;
+        unsigned int refresh;
+        Ecore_Drm_Device *dev;
+
+        EINA_LIST_FOREACH(e_comp_screen->devices, l, dev)
+          {
+             if (ecore_drm_output_primary_get(dev) == eout->output)
+               eout->config.priority = 100;
+
+             for (i = 0; i < dev->crtc_count; i++)
                {
-                  removed = EINA_TRUE;
-                  // find the smallest screen (chosen one)
-                  s_chosen = NULL;
-                  EINA_LIST_FOREACH(outputs_rem, ll, s2)
-                    {
-                       if (!s_chosen) s_chosen = s2;
-                       else
-                         {
-                            if ((s_chosen->config.geom.w *
-                                 s_chosen->config.geom.h) >
-                                (s2->config.geom.w *
-                                 s2->config.geom.h))
-                              s_chosen = s2;
-                         }
-                    }
-                  // remove all from screens but the chosen one
-                  EINA_LIST_FREE(outputs_rem, s2)
+                  if (dev->crtcs[i] == ecore_drm_output_crtc_id_get(eout->output))
                     {
-                       if (s2 != s_chosen)
-                         outputs = eina_list_remove_list(outputs, l);
+                       ecore_drm_output_position_get(eout->output, &eout->config.geom.x,
+                                                     &eout->config.geom.y);
+                       ecore_drm_output_crtc_size_get(eout->output, &eout->config.geom.w,
+                                                      &eout->config.geom.h);
+                       ecore_drm_output_current_resolution_get(eout->output,
+                                                               &eout->config.mode.w,
+                                                               &eout->config.mode.h,
+                                                               &refresh);
+                       eout->config.mode.refresh = refresh;
+                       eout->config.enabled =
+                           ((eout->config.mode.w != 0) && (eout->config.mode.h != 0));
+
+                       printf("E_OUTPUT: '%s' %i %i %ix%i\n", eout->info.name,
+                              eout->config.geom.x, eout->config.geom.y,
+                              eout->config.geom.w, eout->config.geom.h);
+                       break;
                     }
-                  // break our list walk and try again
-                  break;
                }
           }
      }
-   while (removed);
-   // sort screens by priority etc.
-   outputs = eina_list_sort(outputs, 0, _screen_sort_cb);
-   i = 0;
-   EINA_LIST_FOREACH(outputs, l, output)
-     {
-        screen = E_NEW(E_Screen, 1);
-        screen->escreen = screen->screen = i;
-        screen->x = output->config.geom.x;
-        screen->y = output->config.geom.y;
-        screen->w = output->config.geom.w;
-        screen->h = output->config.geom.h;
-        if (output->id) screen->id = strdup(output->id);
-
-        e_screens = eina_list_append(e_screens, screen);
-        INF("E INIT: SCREEN: [%i][%i], %ix%i+%i+%i",
-            i, i, screen->w, screen->h, screen->x, screen->y);
-        i++;
-     }
-   eina_list_free(outputs);
-   // if we have NO screens at all (above - i will be 0) AND we have no
-   // existing screens set up in xinerama - then just say root window size
-   // is the entire screen. this should handle the case where you unplug ALL
-   // screens from an existing setup (unplug external monitors and/or close
-   // laptop lid), in which case as long as at least one screen is configured
-   // in xinerama, it will be left-as is until next time we re-eval screen
-   // setup and have at least one screen
-   printf("e_output_screens_setup............... %i %p\n", i, all_screens);
-   if ((i == 0) && (!all_screens))
+   else
      {
-out:
-        screen = E_NEW(E_Screen, 1);
-        screen->escreen = screen->screen = 0;
-        screen->x = 0;
-        screen->y = 0;
-        if ((rw > 0) && (rh > 0))
-          screen->w = rw, screen->h = rh;
-        else
-          ecore_evas_screen_geometry_get(e_comp->ee, NULL, NULL, &screen->w, &screen->h);
-        e_screens = eina_list_append(e_screens, screen);
+        eout->info.connected = EINA_FALSE;
+
+        /* reset eout info */
+        free(eout->id);
+        free(eout->info.screen);
+        free(eout->info.edid);
+        EINA_LIST_FREE(eout->info.modes, m) free(m);
+
+        eout->id = malloc(strlen(eout->info.name) + 1 + 1);
+        eout->info.size.w = 0;
+        eout->info.size.h = 0;
+
+        printf("E_OUTPUT: disconnected.. id: %s\n", eout->id);
      }
-   _escreens_set(e_screens);
+
+   return EINA_TRUE;
 }
 
-EINTERN const Eina_List *
-e_output_screens_get(void)
+EINTERN Eina_Bool
+e_output_commit(E_Output *output)
 {
-   return all_screens;
+   E_Plane *plane = NULL;
+   Eina_List *l;
+   Eina_Bool commitable = EINA_FALSE;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
+
+   if (!output->config.enabled)
+     {
+        WRN("E_Output disconnected");
+        return EINA_FALSE;
+     }
+
+   if (output->dpms == E_OUTPUT_DPMS_OFF)
+      return EINA_TRUE;
+
+   /* set planes */
+   EINA_LIST_REVERSE_FOREACH(output->planes, l, plane)
+     {
+        if (e_plane_set(plane))
+         {
+            if (!commitable) commitable = EINA_TRUE;
+         }
+     }
+
+   /* commit output */
+   if (commitable)
+     {
+        if (!_e_output_commit(output))
+          {
+             ERR("fail to _e_output_commit.");
+
+             /* unset planes */
+             EINA_LIST_REVERSE_FOREACH(output->planes, l, plane)
+               e_plane_unset(plane);
+
+             return EINA_FALSE;
+          }
+     }
+
+   return EINA_TRUE;
 }
 
+
 E_API E_Output *
 e_output_find(const char *id)
 {
    E_Output *output;
+   E_Comp_Screen *e_comp_screen;
    Eina_List *l;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp->e_comp_screen, NULL);
+
+   e_comp_screen = e_comp->e_comp_screen;
+
    EINA_LIST_FOREACH(e_comp_screen->outputs, l, output)
      {
         if (!strcmp(output->id, id)) return output;
@@ -316,13 +758,18 @@ e_output_planes_get(E_Output *output)
 E_API void
 e_output_util_planes_print(void)
 {
-   Eina_List *l;
+   Eina_List *l, *ll, *p_l;
    E_Output * output = NULL;
+   E_Comp_Screen *e_comp_screen = NULL;
 
-   EINA_LIST_FOREACH(e_comp_screen->outputs, l, output)
+   EINA_SAFETY_ON_NULL_RETURN(e_comp);
+   EINA_SAFETY_ON_NULL_RETURN(e_comp->e_comp_screen);
+
+   e_comp_screen = e_comp->e_comp_screen;
+
+   EINA_LIST_FOREACH_SAFE(e_comp_screen->outputs, l, ll, output)
      {
-        Eina_List *p_l;
-        E_Plane *ep;
+        E_Plane *plane;
         E_Client *ec;
 
         if (!output || !output->planes) continue;
@@ -330,15 +777,15 @@ e_output_util_planes_print(void)
         fprintf(stderr, "HWC in %s .. \n", output->id);
         fprintf(stderr, "HWC \tzPos \t on_plane \t\t\t\t on_prepare \t \n");
 
-        EINA_LIST_FOREACH(output->planes, p_l, ep)
+        EINA_LIST_REVERSE_FOREACH(output->planes, p_l, plane)
           {
-             ec = ep->ec;
+             ec = plane->ec;
              if (ec) fprintf(stderr, "HWC \t[%d]%s\t %s (0x%08x)",
-                             ep->zpos,
-                             ep->is_primary ? "--" : "  ",
+                             plane->zpos,
+                             plane->is_primary ? "--" : "  ",
                              ec->icccm.title, (unsigned int)ec->frame);
 
-             ec = ep->prepare_ec;
+             ec = plane->prepare_ec;
              if (ec) fprintf(stderr, "\t\t\t %s (0x%08x)",
                              ec->icccm.title, (unsigned int)ec->frame);
              fputc('\n', stderr);
index 72ce775e2c15511dd024b8627753b05dff4b28be..b6e9abe310cba11b7c4253ca2ed430cc8b78c5bc 100644 (file)
@@ -1,22 +1,23 @@
 #ifdef E_TYPEDEFS
 
-typedef struct _E_Comp_Screen   E_Comp_Screen;
 typedef struct _E_Output        E_Output;
 typedef struct _E_Output_Mode   E_Output_Mode;
-typedef struct _E_Screen        E_Screen;
-
+typedef enum   _E_Output_Dpms   E_OUTPUT_DPMS;
 #else
 #ifndef E_OUTPUT_H
 #define E_OUTPUT_H
 
 #define E_OUTPUT_TYPE (int)0xE0b11002
 
-struct _E_Comp_Screen
+#include "e_comp_screen.h"
+#include <Ecore_Drm.h>
+
+enum _E_Output_Dpms
 {
-   Eina_List *outputs; // available screens
-   int        w, h; // virtual resolution (calculated)
-   unsigned char  ignore_hotplug_events;
-   unsigned char  ignore_acpi_events;
+   E_OUTPUT_DPMS_ON,
+   E_OUTPUT_DPMS_OFF,
+   E_OUTPUT_DPMS_STANDBY,
+   E_OUTPUT_DPMS_SUSPEND
 };
 
 struct _E_Output_Mode
@@ -24,10 +25,13 @@ struct _E_Output_Mode
    int    w, h; // resolution width and height
    double refresh; // refresh in hz
    Eina_Bool preferred : 1; // is this the preferred mode for the device?
+
+   const tdm_output_mode *tmode;
 };
 
 struct _E_Output
 {
+   int index;
    char *id; // string id which is "name/edid";
    struct {
         char                 *screen; // name of the screen device attached
@@ -50,22 +54,27 @@ struct _E_Output
    int                  plane_count;
    Eina_List           *planes;
    E_Zone              *zone;
-};
 
-struct _E_Screen
-{
-   int screen, escreen;
-   int x, y, w, h;
-   char *id; // this is the same id we get from _E_Output so look it up there
-};
+   tdm_output           *toutput;
+   Ecore_Drm_Output     *output;  // for evas drm engine.
 
-extern E_API E_Comp_Screen *e_comp_screen;
-extern E_API int E_EVENT_SCREEN_CHANGE;
+   E_Comp_Screen        *e_comp_screen;
+   E_OUTPUT_DPMS        dpms;
+};
 
 EINTERN Eina_Bool         e_output_init(void);
-EINTERN int               e_output_shutdown(void);
-EINTERN void              e_output_screens_setup(int rw, int rh);
-EINTERN const Eina_List * e_output_screens_get(void);
+EINTERN void              e_output_shutdown(void);
+EINTERN E_Output        * e_output_new(E_Comp_Screen *e_comp_screen, int index);
+EINTERN E_Output        * e_output_drm_new(Ecore_Drm_Output *output);
+EINTERN void              e_output_del(E_Output *output);
+EINTERN Eina_Bool         e_output_update(E_Output *output);
+EINTERN Eina_Bool         e_output_drm_update(E_Output *output);
+EINTERN Eina_Bool         e_output_mode_apply(E_Output *output, E_Output_Mode *mode);
+EINTERN Eina_Bool         e_output_commit(E_Output *output);
+EINTERN Eina_Bool         e_output_hwc_setup(E_Output *output);
+EINTERN E_Output_Mode   * e_output_best_mode_find(E_Output *output);
+EINTERN Eina_Bool         e_output_connected(E_Output *output);
+EINTERN Eina_Bool         e_output_dpms_set(E_Output *output, E_OUTPUT_DPMS val);
 E_API E_Output          * e_output_find(const char *id);
 E_API const Eina_List   * e_output_planes_get(E_Output *output);
 E_API void                e_output_util_planes_print(void);
index 3a9a2be616553411e079b6a0553636ec0a707d0c..568ae06ec86730b8e2644c6792046ac588067889 100644 (file)
 #include "e.h"
 
+# include <gbm/gbm_tbm.h>
+# include <tdm.h>
+# include <tdm_helper.h>
+# include <tbm_surface.h>
+# include <tbm_surface_internal.h>
+# include <wayland-tbm-server.h>
+# include <Evas_Engine_GL_Drm.h>
+
+# ifndef CLEAR
+# define CLEAR(x) memset(&(x), 0, sizeof (x))
+# endif
+
+# define E_PLANE_CLIENT_SURFACE_FLAGS_RESERVED 7777
+
+typedef struct _E_Plane_Client E_Plane_Client;
+
+struct _E_Plane_Client
+{
+   E_Client *ec;
+
+   E_Plane *plane;
+   Eina_Bool activated;
+
+   E_Comp_Wl_Buffer *buffer;
+   struct wl_listener buffer_destroy_listener;
+
+   Eina_List *exported_surfaces;
+};
+
 /* E_Plane is a child object of E_Output. There is one Output per screen
  * E_plane represents hw overlay and a surface is assigned to disable composition
  * Each Output always has dedicated canvas and a zone
  */
 ///////////////////////////////////////////
 static const char *_e_plane_ec_last_err = NULL;
+static E_Client_Hook *client_hook_new = NULL;
+static E_Client_Hook *client_hook_del = NULL;
+static Eina_Hash *plane_clients = NULL;
+static Eina_List *plane_hdlrs = NULL;
+static Eina_Bool plane_trace_debug = 0;
+
+#if HAVE_MEMCPY_SWC
+extern void *memcpy_swc(void *dest, const void *src, size_t n);
+#endif
+
+static struct wl_resource *
+_get_wl_buffer(E_Client *ec)
+{
+   E_Pixmap *pixmap = ec->pixmap;
+   E_Comp_Wl_Buffer *buffer = e_pixmap_resource_get(pixmap);
+
+   if (!buffer) return NULL;
+
+   return buffer->resource;
+}
+
+static struct wl_resource *
+_get_wl_buffer_ref(E_Client *ec)
+{
+   E_Comp_Wl_Client_Data *cdata = (E_Comp_Wl_Client_Data*)ec->comp_data;
+   if (!cdata) return NULL;
+
+   E_Comp_Wl_Buffer_Ref *buffer_ref = &cdata ->buffer_ref;
+
+   if (!buffer_ref->buffer) return NULL;
+
+   return buffer_ref->buffer->resource;
+}
+
+static struct wl_resource *
+_e_plane_wl_surface_get(E_Client *ec)
+{
+   E_Comp_Wl_Client_Data *cdata = NULL;
+   struct wl_resource *wl_surface = NULL;
+
+   cdata = (E_Comp_Wl_Client_Data *)e_pixmap_cdata_get(ec->pixmap);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(cdata, NULL);
+
+   wl_surface = cdata->wl_surface;
+   if (!wl_surface) return NULL;
+
+   return wl_surface;
+}
+
+struct wayland_tbm_client_queue *
+_e_plane_wayland_tbm_client_queue_get(E_Client *ec)
+{
+   struct wayland_tbm_client_queue * cqueue = NULL;
+   struct wl_resource *wl_surface = NULL;
+   E_Comp_Wl_Data *wl_comp_data = (E_Comp_Wl_Data *)e_comp->wl_comp_data;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(wl_comp_data, NULL);
+
+   wl_surface = _e_plane_wl_surface_get(ec);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(wl_surface, NULL);
+
+   cqueue = wayland_tbm_server_client_queue_get(wl_comp_data->tbm.server, wl_surface);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(cqueue, NULL);
+
+   return cqueue;
+}
+
+static E_Plane_Client *
+_e_plane_client_new(E_Client *ec)
+{
+   E_Plane_Client *plane_client = NULL;
+
+   plane_client = E_NEW(E_Plane_Client, 1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(plane_client, NULL);
+
+   plane_client->ec = ec;
+   plane_client->plane = NULL;
+   plane_client->exported_surfaces = NULL;
+
+   return plane_client;
+}
+
+static E_Plane_Client *
+_e_plane_client_get(E_Client *ec)
+{
+   E_Plane_Client *plane_client = NULL;
+
+   plane_client = eina_hash_find(plane_clients, &ec);
+
+   return plane_client;
+}
+
+static void
+_e_plane_client_cb_new(void *data EINA_UNUSED, E_Client *ec)
+{
+   E_Plane_Client *plane_client = NULL;
+
+   plane_client = _e_plane_client_get(ec);
+   if (!plane_client)
+     {
+        plane_client = _e_plane_client_new(ec);
+        if (plane_client)
+           eina_hash_add(plane_clients, &ec, plane_client);
+     }
+}
+
+static void
+_e_plane_client_cb_del(void *data EINA_UNUSED, E_Client *ec)
+{
+   E_Plane_Client *plane_client = NULL;
+
+   plane_client = _e_plane_client_get(ec);
+   if (plane_client)
+     {
+        /* destroy the plane_client */
+        eina_hash_del_by_key(plane_clients, &ec);
+     }
+}
+
+static tbm_surface_h
+_e_plane_copied_surface_create(E_Client *ec, Eina_Bool refresh)
+{
+   tbm_surface_h tsurface = NULL;
+   tbm_surface_h new_tsurface = NULL;
+   E_Pixmap *pixmap = NULL;
+   E_Comp_Wl_Buffer *buffer = NULL;
+   tbm_surface_info_s src_info, dst_info;
+   E_Comp_Wl_Data *wl_comp_data = (E_Comp_Wl_Data *)e_comp->wl_comp_data;
+
+   pixmap = ec->pixmap;
+
+   if (refresh)
+     e_pixmap_image_refresh(ec->pixmap);
+
+   buffer = e_pixmap_resource_get(pixmap);
+   if (!buffer) return NULL;
+
+   tsurface = wayland_tbm_server_get_surface(wl_comp_data->tbm.server, buffer->resource);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(tsurface, NULL);
+
+   tbm_surface_map(tsurface, TBM_SURF_OPTION_READ, &src_info);
+   tbm_surface_unmap(tsurface);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(src_info.planes[0].ptr, NULL);
+
+   new_tsurface = tbm_surface_create(src_info.width, src_info.height, src_info.format);
+
+   tbm_surface_map(new_tsurface, TBM_SURF_OPTION_WRITE, &dst_info);
+   tbm_surface_unmap(new_tsurface);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(dst_info.planes[0].ptr, NULL);
+
+   /* copy from src to dst */
+#if HAVE_MEMCPY_SWC
+   memcpy_swc(dst_info.planes[0].ptr, src_info.planes[0].ptr, src_info.planes[0].size);
+#else
+   memcpy(dst_info.planes[0].ptr, src_info.planes[0].ptr, src_info.planes[0].size);
+#endif
+
+   return new_tsurface;
+}
+
+static void
+_e_plane_copied_surface_destroy(tbm_surface_h tbm_surface)
+{
+   EINA_SAFETY_ON_NULL_RETURN(tbm_surface);
+
+   tbm_surface_internal_unref(tbm_surface);
+}
+
+static void
+_e_plane_client_backup_buffer_cb_destroy(struct wl_listener *listener, void *data)
+{
+   E_Plane_Client *plane_client = NULL;
+   E_Client *ec = NULL;
+
+   plane_client = container_of(listener, E_Plane_Client, buffer_destroy_listener);
+   EINA_SAFETY_ON_NULL_RETURN(plane_client);
+
+   if ((E_Comp_Wl_Buffer *)data != plane_client->buffer) return;
+
+   ec = plane_client->ec;
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   if (e_pixmap_resource_get(ec->pixmap) == (E_Comp_Wl_Buffer *)data)
+     {
+         e_pixmap_resource_set(ec->pixmap, NULL);
+         e_comp_object_native_surface_set(ec->frame, 0);
+     }
+
+   plane_client->buffer = NULL;
+}
+
+static Eina_Bool
+_e_plane_client_backup_buffer_set(E_Plane_Client *plane_client)
+{
+   E_Comp_Wl_Buffer *backup_buffer = NULL;
+   tbm_surface_h copied_tsurface = NULL;
+   E_Client *ec = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(plane_client, EINA_FALSE);
+
+   ec = plane_client->ec;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
+
+   copied_tsurface = _e_plane_copied_surface_create(ec, 1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(copied_tsurface, EINA_FALSE);
+
+   backup_buffer = e_comp_wl_tbm_buffer_get(copied_tsurface);
+   EINA_SAFETY_ON_NULL_GOTO(backup_buffer, fail);
+
+   if (plane_client->buffer)
+      wl_list_remove(&plane_client->buffer_destroy_listener.link);
+
+   plane_client->buffer = backup_buffer;
+   wl_signal_add(&backup_buffer->destroy_signal, &plane_client->buffer_destroy_listener);
+   plane_client->buffer_destroy_listener.notify = _e_plane_client_backup_buffer_cb_destroy;
+
+   /* reference backup buffer to comp data */
+   e_comp_wl_buffer_reference(&ec->comp_data->buffer_ref, backup_buffer);
+
+   /* set the backup buffer resource to the pixmap */
+   e_pixmap_resource_set(ec->pixmap, backup_buffer);
+   e_pixmap_dirty(ec->pixmap);
+   e_pixmap_refresh(ec->pixmap);
+
+   return EINA_TRUE;
+
+fail :
+   if (copied_tsurface)
+      _e_plane_copied_surface_destroy(copied_tsurface);
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+_e_plane_renderer_disp_surface_find(E_Plane_Renderer *renderer, tbm_surface_h tsurface)
+{
+   Eina_List *l_s;
+   tbm_surface_h tmp_tsurface = NULL;
+
+   EINA_LIST_FOREACH(renderer->disp_surfaces, l_s, tmp_tsurface)
+     {
+        if (!tmp_tsurface) continue;
+        if (tmp_tsurface == tsurface) return EINA_TRUE;
+     }
+
+   return EINA_FALSE;
+}
+
+static void
+_e_plane_surface_queue_release(E_Plane *plane, tbm_surface_h tsurface)
+{
+
+   tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE;
+   E_Plane_Renderer *renderer = NULL;
+   tbm_surface_queue_h tqueue = NULL;
+
+   renderer = plane->renderer;
+   EINA_SAFETY_ON_NULL_RETURN(renderer);
+
+   tqueue = renderer->tqueue;
+   EINA_SAFETY_ON_NULL_RETURN(tqueue);
+
+   /* debug */
+   if (plane_trace_debug)
+     {
+        E_Client *ec = renderer->activated_ec;
+        if (ec)
+          ELOGF("E_PLANE", "Release Layer(%p)     wl_buffer(%p) tsurface(%p) tqueue(%p) wl_buffer_ref(%p)",
+                ec->pixmap, ec, plane, _get_wl_buffer(ec), tsurface, renderer->tqueue, _get_wl_buffer_ref(ec));
+        else
+          ELOGF("E_PLANE", "Release Layer(%p)  tsurface(%p) tqueue(%p)",
+                NULL, NULL, plane, tsurface, renderer->tqueue);
+     }
+
+   tsq_err = tbm_surface_queue_release(tqueue, tsurface);
+   if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE)
+     {
+        ERR("Failed to release tbm_surface(%p) from tbm_surface_queue(%p): tsq_err = %d", tsurface, tqueue, tsq_err);
+        return;
+     }
+}
+
+static Eina_Bool
+_e_plane_client_exported_surface_find(E_Plane_Client *plane_client, tbm_surface_h tsurface)
+{
+   Eina_List *l_s;
+   tbm_surface_h tmp_tsurface = NULL;
+
+   /* destroy the plane_client */
+   EINA_LIST_FOREACH(plane_client->exported_surfaces, l_s, tmp_tsurface)
+     {
+        if (!tmp_tsurface) continue;
+        if (tmp_tsurface == tsurface) return EINA_TRUE;
+     }
+
+   return EINA_FALSE;
+}
+
+static void
+_e_plane_renderer_exported_surface_release(E_Plane_Renderer *renderer, tbm_surface_h tsurface)
+{
+   E_Plane *plane = NULL;
+   tbm_surface_h tmp_tsurface = NULL;
+   Eina_List *l_s, *ll_s;
+
+   EINA_SAFETY_ON_NULL_RETURN(tsurface);
+
+   plane = renderer->plane;
+   EINA_SAFETY_ON_NULL_RETURN(plane);
+
+   EINA_LIST_FOREACH_SAFE(renderer->exported_surfaces, l_s, ll_s, tmp_tsurface)
+     {
+        if (!tmp_tsurface) continue;
+
+        if (tmp_tsurface == tsurface)
+          {
+             if (plane->tsurface != tsurface)
+                _e_plane_surface_queue_release(plane, tsurface);
+
+             renderer->exported_surfaces = eina_list_remove_list(renderer->exported_surfaces, l_s);
+          }
+     }
+
+   if (plane_trace_debug)
+     ELOGF("E_PLANE", "Release exported Renderer(%p)  tsurface(%p) tqueue(%p)",
+           NULL, NULL, renderer, tsurface, renderer->tqueue);
+}
+
+static void
+_e_plane_client_exported_surfaces_release(E_Plane_Client *plane_client, E_Plane_Renderer *renderer)
+{
+   Eina_List *l_s, *ll_s;
+   tbm_surface_h tsurface = NULL;
+   E_Plane *plane = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN(plane_client);
+
+   plane = renderer->plane;
+   EINA_SAFETY_ON_NULL_RETURN(plane);
+
+   EINA_LIST_FOREACH_SAFE(plane_client->exported_surfaces, l_s, ll_s, tsurface)
+     {
+        if (!tsurface) continue;
+
+        if (tsurface == plane->previous_tsurface)
+          {
+             _e_plane_renderer_exported_surface_release(renderer, tsurface);
+             plane_client->exported_surfaces = eina_list_remove_list(plane_client->exported_surfaces, l_s);
+             break;
+          }
+
+     }
+
+   EINA_LIST_FOREACH_SAFE(plane_client->exported_surfaces, l_s, ll_s, tsurface)
+     {
+        if (!tsurface) continue;
+
+        if (tsurface == plane->tsurface)
+          {
+             _e_plane_renderer_exported_surface_release(renderer, tsurface);
+             plane_client->exported_surfaces = eina_list_remove_list(plane_client->exported_surfaces, l_s);
+             break;
+          }
+
+     }
+
+   EINA_LIST_FOREACH_SAFE(plane_client->exported_surfaces, l_s, ll_s, tsurface)
+     {
+        if (!tsurface) continue;
+
+        _e_plane_renderer_exported_surface_release(renderer, tsurface);
+        plane_client->exported_surfaces = eina_list_remove_list(plane_client->exported_surfaces, l_s);
+     }
+}
+
+static void
+_e_plane_client_del(void *data)
+{
+   E_Plane_Client *plane_client = data;
+   E_Plane_Renderer *renderer = NULL;
+
+   if (!plane_client) return;
+
+   if (plane_client->buffer)
+      wl_list_remove(&plane_client->buffer_destroy_listener.link);
+
+   if (plane_client->activated && plane_client->plane)
+     {
+        renderer = plane_client->plane->renderer;
+        if (renderer)
+           _e_plane_client_exported_surfaces_release(plane_client, renderer);
+     }
+
+   free(plane_client);
+}
+
+static uint32_t
+_e_plane_client_surface_flags_get(E_Plane_Client *plane_client)
+{
+   tbm_surface_h tsurface = NULL;
+   E_Comp_Wl_Data *wl_comp_data = (E_Comp_Wl_Data *)e_comp->wl_comp_data;
+   E_Client *ec = plane_client->ec;
+   E_Pixmap *pixmap = ec->pixmap;
+   uint32_t flags = 0;
+   E_Comp_Wl_Buffer *buffer = NULL;
+
+   buffer = e_pixmap_resource_get(pixmap);
+   if (!buffer) return 0;
+
+   switch (buffer->type)
+     {
+       case E_COMP_WL_BUFFER_TYPE_NATIVE:
+       case E_COMP_WL_BUFFER_TYPE_VIDEO:
+         tsurface = wayland_tbm_server_get_surface(wl_comp_data->tbm.server, buffer->resource);
+         EINA_SAFETY_ON_NULL_RETURN_VAL(tsurface, 0);
+
+         flags = wayland_tbm_server_get_buffer_flags(wl_comp_data->tbm.server, buffer->resource);
+         break;
+       default:
+         flags = 0;
+         break;
+     }
+
+   return flags;
+}
+
+static tbm_surface_h
+_e_plane_surface_queue_acquire(E_Plane *plane)
+{
+   tbm_surface_queue_h tqueue = NULL;
+   tbm_surface_h tsurface = NULL;
+   tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE;
+   E_Plane_Renderer *renderer = NULL;
+
+   renderer = plane->renderer;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(renderer, NULL);
+
+   tqueue = renderer->tqueue;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(tqueue, NULL);
+
+   if (tbm_surface_queue_can_acquire(tqueue, 1))
+     {
+        tsq_err = tbm_surface_queue_acquire(tqueue, &tsurface);
+        if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE)
+          {
+             ERR("Failed to acquire tbm_surface from tbm_surface_queue(%p): tsq_err = %d", tqueue, tsq_err);
+             return NULL;
+          }
+     }
+
+   /* if not exist, add the surface to the renderer */
+   if (!_e_plane_renderer_disp_surface_find(renderer, tsurface))
+      renderer->disp_surfaces = eina_list_append(renderer->disp_surfaces, tsurface);
+
+   /* debug */
+   if (plane_trace_debug)
+     {
+        E_Client *ec = renderer->activated_ec;
+        if (ec)
+          ELOGF("E_PLANE", "Acquire Layer(%p)     wl_buffer(%p) tsurface(%p) tqueue(%p) wl_buffer_ref(%p)",
+                ec->pixmap, ec, plane, _get_wl_buffer(ec), tsurface, tqueue, _get_wl_buffer_ref(ec));
+        else
+          ELOGF("E_PLANE", "Acquire Layer(%p)  tsurface(%p) tqueue(%p)",
+                NULL, NULL, plane, tsurface, tqueue);
+     }
+
+   return tsurface;
+}
+
+static Eina_Bool
+_e_plane_surface_queue_enqueue(E_Plane *plane, tbm_surface_h tsurface)
+{
+   tbm_surface_queue_h tqueue = NULL;
+   E_Plane_Renderer *renderer = NULL;
+   tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE;
+
+   renderer = plane->renderer;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(renderer, EINA_FALSE);
+
+   tqueue = renderer->tqueue;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(tqueue, EINA_FALSE);
+
+   /* debug */
+   if (plane_trace_debug)
+    {
+        E_Plane_Renderer *renderer = plane->renderer;
+        E_Client *ec = renderer->activated_ec;
+        ELOGF("E_PLANE", "Enqueue Renderer(%p)  wl_buffer(%p) tsurface(%p) tqueue(%p) wl_buffer_ref(%p)",
+              ec->pixmap, ec, renderer, _get_wl_buffer(ec), tsurface, renderer->tqueue, _get_wl_buffer_ref(ec));
+    }
+
+   tsq_err = tbm_surface_queue_enqueue(tqueue, tsurface);
+   if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE)
+     {
+        ERR("tbm_surface_queue_enqueue failed. tbm_surface_queue(%p) tbm_surface(%p)", tqueue, tsurface);
+        return EINA_FALSE;
+     }
+
+   return EINA_TRUE;
+}
+
+static int
+_e_plane_surface_queue_can_dequeue(E_Plane *plane)
+{
+   tbm_surface_queue_h tqueue = NULL;
+   E_Plane_Renderer *renderer = NULL;
+   int num_free = 0;
+
+   renderer = plane->renderer;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(renderer, EINA_FALSE);
+
+   tqueue = renderer->tqueue;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(tqueue, EINA_FALSE);
+
+   num_free = tbm_surface_queue_can_dequeue(tqueue, 0);
+
+   return num_free;
+}
+
+static tbm_surface_h
+_e_plane_surface_queue_dequeue(E_Plane *plane)
+{
+   E_Plane_Renderer *renderer = NULL;
+   tbm_surface_queue_h tqueue = NULL;
+   tbm_surface_h tsurface = NULL;
+   tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE;
+
+   renderer = plane->renderer;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(renderer, NULL);
+
+   tqueue = renderer->tqueue;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(tqueue, NULL);
+
+   tsq_err = tbm_surface_queue_dequeue(tqueue, &tsurface);
+   if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE)
+     {
+        ERR("fail to tbm_surface_queue_dequeue");
+        return NULL;
+     }
+
+   /* debug */
+   if (plane_trace_debug)
+     {
+         E_Plane_Renderer *renderer = plane->renderer;
+         E_Client *ec = renderer->activated_ec;
+         if (ec)
+           ELOGF("E_PLANE", "Dequeue Renderer(%p)  wl_buffer(%p) tsurface(%p) tqueue(%p) wl_buffer_ref(%p)",
+                 ec->pixmap, ec, renderer, _get_wl_buffer(ec), tsurface, renderer->tqueue, _get_wl_buffer_ref(ec));
+         else
+           ELOGF("E_PLANE", "Dequeue Renderer(%p)  tsurface(%p) tqueue(%p)",
+                 NULL, NULL, renderer, tsurface, renderer->tqueue);
+     }
+   return tsurface;
+}
+
+static Eina_Bool
+_e_plane_renderer_sent_surface_find(E_Plane_Renderer *renderer, tbm_surface_h tsurface)
+{
+   Eina_List *l_s;
+   tbm_surface_h tmp_tsurface = NULL;
+
+   EINA_LIST_FOREACH(renderer->sent_surfaces, l_s, tmp_tsurface)
+     {
+        if (!tmp_tsurface) continue;
+        if (tmp_tsurface == tsurface) return EINA_TRUE;
+     }
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+_e_plane_renderer_exported_surface_find(E_Plane_Renderer *renderer, tbm_surface_h tsurface)
+{
+   Eina_List *l_s;
+   tbm_surface_h tmp_tsurface = NULL;
+
+   EINA_LIST_FOREACH(renderer->exported_surfaces, l_s, tmp_tsurface)
+     {
+        if (!tmp_tsurface) continue;
+        if (tmp_tsurface == tsurface) return EINA_TRUE;
+     }
+
+   return EINA_FALSE;
+}
+
+static void
+_e_plane_renderer_exported_surface_destroy_cb(tbm_surface_h tsurface, void *data)
+{
+   E_Plane_Renderer *renderer = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN(e_comp);
+   EINA_SAFETY_ON_NULL_RETURN(e_comp->e_comp_screen);
+   EINA_SAFETY_ON_NULL_RETURN(tsurface);
+   EINA_SAFETY_ON_NULL_RETURN(data);
+
+   renderer = (E_Plane_Renderer *)data;
+
+   if (plane_trace_debug)
+     ELOGF("E_PLANE", "Destroy Renderer(%p)  tsurface(%p) tqueue(%p)",
+           NULL, NULL, renderer, tsurface, renderer->tqueue);
+}
+
+static void
+_e_plane_ee_post_render_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   E_Plane *plane = data;
+
+   if (!plane) return;
+
+   /* mark when the post_render is called */
+   plane->update_ee = EINA_TRUE;
+}
+
+static void
+_e_plane_renderer_all_disp_surfaces_release(E_Plane_Renderer *renderer)
+{
+   Eina_List *l_s;
+   tbm_surface_h tsurface = NULL;
+
+   EINA_LIST_FOREACH(renderer->disp_surfaces, l_s, tsurface)
+     {
+        if (!tsurface) continue;
+
+        _e_plane_surface_queue_release(renderer->plane, tsurface);
+
+        if (_e_plane_renderer_exported_surface_find(renderer, tsurface))
+           renderer->exported_surfaces = eina_list_remove(renderer->exported_surfaces, tsurface);
+     }
+}
+
+static void
+_e_plane_renderer_surface_export(E_Plane_Renderer *renderer, tbm_surface_h tsurface, E_Client *ec)
+{
+   struct wayland_tbm_client_queue * cqueue = NULL;
+   struct wl_resource *wl_buffer = NULL;
+   E_Plane_Client *plane_client = NULL;
+
+   plane_client = _e_plane_client_get(ec);
+   EINA_SAFETY_ON_NULL_RETURN(plane_client);
+
+   cqueue = _e_plane_wayland_tbm_client_queue_get(ec);
+   EINA_SAFETY_ON_NULL_RETURN(cqueue);
+
+   if (_e_plane_renderer_exported_surface_find(renderer, tsurface)) return;
+
+   /* export the tbm_surface(wl_buffer) to the client_queue */
+   wl_buffer = wayland_tbm_server_client_queue_export_buffer(cqueue, tsurface,
+           E_PLANE_CLIENT_SURFACE_FLAGS_RESERVED, _e_plane_renderer_exported_surface_destroy_cb,
+           (void *)renderer);
+
+   renderer->exported_surfaces = eina_list_append(renderer->exported_surfaces, tsurface);
+
+   /* add a sent surface to the sent list in renderer if it is not in the list */
+   if (!_e_plane_renderer_sent_surface_find(renderer, tsurface))
+       renderer->sent_surfaces = eina_list_append(renderer->sent_surfaces, tsurface);
+
+   if (!_e_plane_client_exported_surface_find(plane_client, tsurface))
+       plane_client->exported_surfaces = eina_list_append(plane_client->exported_surfaces, tsurface);
+
+   if (wl_buffer && plane_trace_debug)
+       ELOGF("E_PLANE", "Export  Renderer(%p)  wl_buffer(%p) tsurface(%p) tqueue(%p)",
+               ec->pixmap, ec, renderer, wl_buffer, tsurface, renderer->tqueue);
+}
+
+
+static void
+_e_plane_renderer_all_disp_surfaces_export(E_Plane_Renderer *renderer, E_Client *ec)
+{
+   struct wayland_tbm_client_queue * cqueue = NULL;
+   Eina_List *l_s, *ll_s;
+   tbm_surface_h tsurface = NULL;
+
+   cqueue = _e_plane_wayland_tbm_client_queue_get(ec);
+   EINA_SAFETY_ON_NULL_RETURN(cqueue);
+
+   EINA_LIST_FOREACH_SAFE(renderer->disp_surfaces, l_s, ll_s, tsurface)
+     {
+        if (!tsurface) continue;
+
+        _e_plane_renderer_surface_export(renderer, tsurface, ec);
+     }
+}
+
+static void
+_e_plane_renderer_dequeuable_surfaces_export(E_Plane_Renderer *renderer, E_Client *ec)
+{
+   E_Plane *plane = NULL;
+   tbm_surface_h tsurface = NULL;
+
+   plane = renderer->plane;
+   EINA_SAFETY_ON_NULL_RETURN(plane);
+
+   /* export dequeuable surface */
+   while(_e_plane_surface_queue_can_dequeue(plane))
+     {
+        /* dequeue */
+        tsurface = _e_plane_surface_queue_dequeue(plane);
+        if (!tsurface) ERR("fail to dequeue surface");
+
+        /* export the surface */
+        if (!_e_plane_renderer_exported_surface_find(renderer, tsurface))
+           _e_plane_renderer_surface_export(renderer, tsurface, ec);
+    }
+}
+
+static tbm_surface_h
+_e_plane_renderer_surface_revice(E_Plane_Renderer *renderer, E_Client *ec)
+{
+   tbm_surface_h tsurface = NULL;
+   E_Comp_Wl_Data *wl_comp_data = (E_Comp_Wl_Data *)e_comp->wl_comp_data;
+   E_Pixmap *pixmap = ec->pixmap;
+   uint32_t flags = 0;
+   E_Comp_Wl_Buffer *buffer = NULL;
+
+   if (renderer->activated_ec != ec)
+     {
+        ERR("Renderer(%p)  activated_ec(%p) != ec(%p)", renderer, renderer->activated_ec, ec);
+        return NULL;
+     }
+
+   buffer = e_pixmap_resource_get(pixmap);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(buffer, NULL);
+
+   tsurface = wayland_tbm_server_get_surface(wl_comp_data->tbm.server, buffer->resource);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(tsurface, NULL);
+
+   flags = wayland_tbm_server_get_buffer_flags(wl_comp_data->tbm.server, buffer->resource);
+
+   if (plane_trace_debug)
+     {
+        E_Comp_Wl_Client_Data *cdata = (E_Comp_Wl_Client_Data*)renderer->activated_ec->comp_data;
+        E_Comp_Wl_Buffer_Ref *buffer_ref = &cdata ->buffer_ref;
+
+        ELOGF("E_PLANE", "Receive Renderer(%p)  wl_buffer(%p) tsurface(%p) tqueue(%p) wl_buffer_ref(%p) flags(%d)",
+        ec->pixmap, ec, renderer, buffer->resource, tsurface, renderer->tqueue, buffer_ref->buffer->resource, flags);
+     }
+   if (flags != E_PLANE_CLIENT_SURFACE_FLAGS_RESERVED)
+     {
+        ERR("the flags of the enqueuing surface is %d. need flags(%d).", flags, E_PLANE_CLIENT_SURFACE_FLAGS_RESERVED);
+        return NULL;
+     }
+
+   /* remove a recieved surface from the sent list in renderer */
+   renderer->sent_surfaces = eina_list_remove(renderer->sent_surfaces, (const void *)tsurface);
+
+   return tsurface;
+}
+
+static void
+_e_plane_renderer_surface_send(E_Plane_Renderer *renderer, E_Client *ec, tbm_surface_h tsurface)
+{
+   /* debug */
+   if (plane_trace_debug)
+     ELOGF("E_PLANE", "Send    Renderer(%p)  wl_buffer(%p) tsurface(%p) tqueue(%p) wl_buffer_ref(%p)",
+           ec->pixmap, ec, renderer, _get_wl_buffer(ec), tsurface, renderer->tqueue, _get_wl_buffer_ref(ec));
+
+   /* wl_buffer release */
+   e_pixmap_image_clear(ec->pixmap, 1);
+
+   /* add a sent surface to the sent list in renderer if it is not in the list */
+   if (!_e_plane_renderer_sent_surface_find(renderer, tsurface))
+     renderer->sent_surfaces = eina_list_append(renderer->sent_surfaces, tsurface);
+}
+
+static Eina_Bool
+_e_plane_renderer_deactivate(E_Plane_Renderer *renderer)
+{
+   struct wayland_tbm_client_queue * cqueue = NULL;
+   struct wl_resource *wl_surface = NULL;
+   E_Comp_Wl_Data *wl_comp_data = (E_Comp_Wl_Data *)e_comp->wl_comp_data;
+   E_Client *ec = NULL;
+   E_Plane_Client *plane_client = NULL;
+   E_Plane_Client *candidate_plane_client = NULL;
+
+   if (renderer->activated_ec)
+     {
+        ec = renderer->activated_ec;
+     }
+   else if (renderer->candidate_ec)
+     {
+        ec = renderer->candidate_ec;
+     }
+   else
+     {
+         ERR("NEVER HERE.");
+         goto done;
+     }
+
+   EINA_SAFETY_ON_NULL_GOTO(wl_comp_data, done);
+
+   if (plane_trace_debug)
+     ELOGF("E_PLANE", "Deactivate", ec->pixmap, ec);
+
+   plane_client = _e_plane_client_get(ec);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(plane_client, EINA_FALSE);
+
+   wl_surface = _e_plane_wl_surface_get(ec);
+   EINA_SAFETY_ON_NULL_GOTO(wl_surface, done);
+
+   cqueue = wayland_tbm_server_client_queue_get(wl_comp_data->tbm.server, wl_surface);
+   EINA_SAFETY_ON_NULL_GOTO(cqueue, done);
+
+   /* deactive */
+   wayland_tbm_server_client_queue_deactivate(cqueue);
+
+   if (_e_plane_client_surface_flags_get(plane_client) == E_PLANE_CLIENT_SURFACE_FLAGS_RESERVED)
+     {
+        if (plane_trace_debug)
+            ELOGF("E_PLANE", "Set Backup Buffer     wl_buffer(%p):Deactivate", ec->pixmap, ec, _get_wl_buffer(ec));
+
+        if (!_e_plane_client_backup_buffer_set(plane_client))
+           ERR("fail to _e_comp_hwc_set_backup_buffer");
+
+        /* force update */
+        e_pixmap_image_refresh(ec->pixmap);
+        e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
+        e_comp_object_dirty(ec->frame);
+        e_comp_object_render(ec->frame);
+     }
+
+done:
+   if (renderer->candidate_ec)
+     {
+        candidate_plane_client = _e_plane_client_get(renderer->candidate_ec);
+        if (candidate_plane_client)
+           _e_plane_client_exported_surfaces_release(candidate_plane_client, renderer);
+
+        renderer->candidate_ec = NULL;
+     }
+
+   if (renderer->activated_ec)
+     {
+        _e_plane_client_exported_surfaces_release(plane_client, renderer);
+        renderer->activated_ec = NULL;
+     }
+
+   plane_client->activated = EINA_FALSE;
+
+   return EINA_TRUE;
+}
+
+static void
+_e_plane_renderer_queue_del(E_Plane_Renderer *renderer)
+{
+   tbm_surface_queue_h tqueue = NULL;
+
+   if (!renderer) return;
+
+   tqueue = renderer->tqueue;
+   EINA_SAFETY_ON_NULL_RETURN(tqueue);
+
+   tbm_surface_queue_destroy(tqueue);
+   renderer->tqueue = NULL;
+
+   renderer->disp_surfaces = eina_list_free(renderer->disp_surfaces);
+}
+
+static Eina_Bool
+_e_plane_renderer_queue_create(E_Plane_Renderer *renderer, int width, int height)
+{
+   E_Plane *plane = NULL;
+   tbm_surface_queue_h tqueue = NULL;
+   tbm_surface_h tsurface = NULL;
+   tdm_error tdm_err = TDM_ERROR_NONE;
+   unsigned int buffer_flags = -1;
+   int format = TBM_FORMAT_ARGB8888;
+   int queue_size = 3; /* query tdm ????? */
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(renderer, EINA_FALSE);
+
+   if (renderer->tqueue)
+     {
+        ERR("already create queue in renderer");
+        return EINA_FALSE;
+     }
+
+   plane = renderer->plane;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(plane, EINA_FALSE);
+
+   tdm_err = tdm_layer_get_buffer_flags(plane->tlayer, &buffer_flags);
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(tdm_err == TDM_ERROR_NONE, EINA_FALSE);
+
+   tqueue = tbm_surface_queue_create(queue_size, width, height, format, buffer_flags);
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(tqueue, EINA_FALSE);
+
+   renderer->tqueue = tqueue;
+
+   /* dequeue the surfaces if the qeueue is available */
+   /* add the surface to the disp_surfaces list, if it is not in the disp_surfaces */
+   while (tbm_surface_queue_can_dequeue(renderer->tqueue, 0))
+      {
+         /* dequeue */
+         tsurface = _e_plane_surface_queue_dequeue(plane);
+         if (!tsurface)
+            {
+               ERR("fail to dequeue surface");
+               continue;
+            }
+
+         /* if not exist, add the surface to the renderer */
+         if (!_e_plane_renderer_disp_surface_find(renderer, tsurface))
+            renderer->disp_surfaces = eina_list_append(renderer->disp_surfaces, tsurface);
+      }
+
+   _e_plane_renderer_all_disp_surfaces_release(renderer);
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_plane_renderer_queue_set(E_Plane_Renderer *renderer, tbm_surface_queue_h tqueue)
+{
+   tbm_surface_h tsurface = NULL;
+   E_Plane *plane = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(renderer, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(tqueue, EINA_FALSE);
+
+   plane = renderer->plane;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(plane, EINA_FALSE);
+
+   renderer->tqueue = tqueue;
+
+   if (renderer->disp_surfaces)
+      renderer->disp_surfaces = eina_list_free(renderer->disp_surfaces);
+
+   /* dequeue the surfaces if the qeueue is available */
+   /* add the surface to the disp_surfaces list, if it is not in the disp_surfaces */
+   while (tbm_surface_queue_can_dequeue(renderer->tqueue, 0))
+      {
+         /* dequeue */
+         tsurface = _e_plane_surface_queue_dequeue(plane);
+         if (!tsurface)
+            {
+               ERR("fail to dequeue surface");
+               continue;
+            }
+
+        /* if not exist, add the surface to the renderer */
+        if (!_e_plane_renderer_disp_surface_find(renderer, tsurface))
+           renderer->disp_surfaces = eina_list_append(renderer->disp_surfaces, tsurface);
+      }
+
+   _e_plane_renderer_all_disp_surfaces_release(renderer);
+
+   return EINA_TRUE;
+}
+
+static E_Plane_Renderer *
+_e_plane_renderer_new(E_Plane *plane)
+{
+   E_Plane_Renderer *renderer = NULL;
+   /* create a renderer */
+   renderer = E_NEW(E_Plane_Renderer, 1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(renderer, NULL);
+   renderer->plane = plane;
+
+   return renderer;
+}
+
+static void
+_e_plane_renderer_del(E_Plane_Renderer *renderer)
+{
+   E_Plane *plane = NULL;
+
+   if (!renderer) return;
+
+   plane = renderer->plane;
+   EINA_SAFETY_ON_NULL_RETURN(plane);
+
+   if (!plane->is_primary)
+      _e_plane_renderer_queue_del(renderer);
+
+   free(renderer);
+}
+
+static Eina_Bool
+_e_plane_renderer_activate(E_Plane_Renderer *renderer, E_Client *ec)
+{
+   struct wayland_tbm_client_queue * cqueue = NULL;
+   tbm_surface_h tsurface = NULL;
+   E_Plane_Client *plane_client = NULL;
+   E_Plane *plane = NULL;
+
+   plane = renderer->plane;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(plane, EINA_FALSE);
+
+   /* deactivate the client of the layer before this call*/
+   if (renderer->activated_ec)
+     {
+        ERR("Previous activated client must be decativated.");
+        return EINA_FALSE;
+     }
+
+   cqueue = _e_plane_wayland_tbm_client_queue_get(ec);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(cqueue, EINA_FALSE);
+
+   /* register the plane client */
+   plane_client = _e_plane_client_get(ec);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(plane_client, EINA_FALSE);
+
+   if (renderer->candidate_ec)
+     {
+        if (renderer->candidate_ec != ec)
+          {
+              /* deactive the candidate_ec */
+              _e_plane_renderer_deactivate(renderer);
+
+              /* activate the client queue */
+              wayland_tbm_server_client_queue_activate(cqueue, 0);
+              plane_client->activated = EINA_TRUE;
+
+              if (_e_plane_client_surface_flags_get(plane_client) != E_PLANE_CLIENT_SURFACE_FLAGS_RESERVED)
+                {
+                   /* check dequeuable */
+                   if (!_e_plane_surface_queue_can_dequeue(renderer->plane))
+                     {
+                        INF("There is any dequeuable surface.");
+                        return EINA_FALSE;
+                     }
+
+                    /* dequeue */
+                    tsurface = _e_plane_surface_queue_dequeue(renderer->plane);
+                    if (!tsurface)
+                      {
+                        ERR("fail to dequeue surface");
+                        return EINA_FALSE;
+                      }/* export the surface */
+
+                    /* export */
+                    _e_plane_renderer_surface_export(renderer, tsurface, ec);
+
+                    if (plane_trace_debug)
+                       ELOGF("E_PLANE", "Candidate Plane(%p)", ec->pixmap, ec, renderer->plane);
+
+                    renderer->candidate_ec = ec;
+
+                    return EINA_FALSE;
+                }
+          }
+        else
+          {
+             if (_e_plane_client_surface_flags_get(plane_client) != E_PLANE_CLIENT_SURFACE_FLAGS_RESERVED)
+               {
+                  INF("ec does not have the scanout surface yet.");
+                  return EINA_FALSE;
+               }
+          }
+     }
+   else
+     {
+         wayland_tbm_server_client_queue_activate(cqueue, 0);
+         plane_client->activated = EINA_TRUE;
+
+         if (_e_plane_client_surface_flags_get(plane_client) != E_PLANE_CLIENT_SURFACE_FLAGS_RESERVED)
+           {
+               /* check dequeuable */
+               if (!_e_plane_surface_queue_can_dequeue(renderer->plane))
+                 {
+                   INF("There is any dequeuable surface.");
+                   return EINA_FALSE;
+                 }
+
+               /* dequeue */
+               tsurface = _e_plane_surface_queue_dequeue(renderer->plane);
+               if (!tsurface)
+                 {
+                    ERR("fail to dequeue surface");
+                    return EINA_FALSE;
+                 }
+
+              /* export */
+              _e_plane_renderer_surface_export(renderer, tsurface, ec);
+
+              if (plane_trace_debug)
+                  ELOGF("E_PLANE", "Candidate Plane(%p)", ec->pixmap, ec, renderer->plane);
+
+              renderer->candidate_ec = ec;
+
+              INF("ec does not have the scanout surface.");
+
+              return EINA_FALSE;
+          }
+     }
+
+   if (plane_trace_debug)
+     ELOGF("E_PLANE", "Activate Plane(%p)", ec->pixmap, ec, plane);
+
+   renderer->activated_ec = ec;
+   renderer->candidate_ec = NULL;
+
+   _e_plane_renderer_dequeuable_surfaces_export(renderer, ec);
+
+   return EINA_TRUE;
+}
+
+
+static Eina_Bool
+_e_plane_surface_set(E_Plane *plane, tbm_surface_h tsurface)
+{
+   tbm_surface_info_s surf_info;
+   tdm_error error;
+   tdm_layer *tlayer = plane->tlayer;
+   E_Output *output = plane->output;
+
+   /* set layer when the layer infomation is different from the previous one */
+   tbm_surface_get_info(tsurface, &surf_info);
+   if (plane->info.src_config.size.h != surf_info.planes[0].stride ||
+       plane->info.src_config.size.v != surf_info.height ||
+       plane->info.src_config.pos.x != 0 ||
+       plane->info.src_config.pos.y != 0 ||
+       plane->info.src_config.pos.w != surf_info.width ||
+       plane->info.src_config.pos.h != surf_info.height ||
+       plane->info.dst_pos.x != output->config.geom.x ||
+       plane->info.dst_pos.y != output->config.geom.y ||
+       plane->info.dst_pos.w != output->config.geom.w ||
+       plane->info.dst_pos.h != output->config.geom.h ||
+       plane->info.transform != TDM_TRANSFORM_NORMAL)
+     {
+        plane->info.src_config.size.h = surf_info.planes[0].stride;
+        plane->info.src_config.size.v = surf_info.height;
+        plane->info.src_config.pos.x = 0;
+        plane->info.src_config.pos.y = 0;
+        plane->info.src_config.pos.w = surf_info.width;
+        plane->info.src_config.pos.h = surf_info.height;
+        plane->info.dst_pos.x = output->config.geom.x;
+        plane->info.dst_pos.y = output->config.geom.y;
+        plane->info.dst_pos.w = output->config.geom.w;
+        plane->info.dst_pos.h = output->config.geom.h;
+        plane->info.transform = TDM_TRANSFORM_NORMAL;
+
+        error = tdm_layer_set_info(tlayer, &plane->info);
+        if (error != TDM_ERROR_NONE)
+          {
+             ERR("fail to tdm_layer_set_info");
+             return EINA_FALSE;
+          }
+     }
+
+   if (plane_trace_debug)
+     {
+        ELOGF("E_PLANE", "Commit  Layer(%p)  tsurface(%p) (%dx%d,[%d,%d,%d,%d]=>[%d,%d,%d,%d])",
+              NULL, NULL, plane, tsurface,
+              plane->info.src_config.size.h, plane->info.src_config.size.h,
+              plane->info.src_config.pos.x, plane->info.src_config.pos.y,
+              plane->info.src_config.pos.w, plane->info.src_config.pos.h,
+              plane->info.dst_pos.x, plane->info.dst_pos.y,
+              plane->info.dst_pos.w, plane->info.dst_pos.h);
+     }
+
+   error = tdm_layer_set_buffer(tlayer, tsurface);
+   if (error != TDM_ERROR_NONE)
+     {
+        ERR("fail to tdm_layer_set_buffer");
+        return EINA_FALSE;
+     }
+
+   return EINA_TRUE;
+}
 
-/* local subsystem functions */
 static void
-_e_plane_reconfigure_clients(E_Plane *plane,
-                             int dx,
-                             int dy,
-                             int dw,
-                             int dh)
+_e_plane_surface_on_client_reserved_release(E_Plane *plane, tbm_surface_h tsurface)
 {
-   EINA_SAFETY_ON_NULL_RETURN(plane->ec);
+   E_Plane_Renderer *renderer = plane->renderer;
+   E_Client *ec = plane->ec;
+
+   if (!ec)
+     {
+        ERR("no ec at plane.");
+        return;
+     }
 
-   /* TODO: config ec refer to resolution */
+   /* release the tsurface */
+   _e_plane_renderer_surface_send(renderer, ec, tsurface);
 }
 
-///////////////////////////////////////////
-EINTERN int
-e_plane_init(void)
+static tbm_surface_h
+_e_plane_surface_from_client_acquire_reserved(E_Plane *plane)
 {
-   _e_plane_ec_last_err = eina_stringshare_add("UNKNOWN");
-   return 1;
+   E_Client *ec = plane->ec;
+   E_Pixmap *pixmap = ec->pixmap;
+   tbm_surface_h tsurface = NULL;
+   E_Plane_Client *plane_client = NULL;
+   E_Plane_Renderer *renderer = plane->renderer;
+
+   if (plane_trace_debug)
+     ELOGF("E_PLANE", "Display Client", ec->pixmap, ec);
+
+   plane_client = _e_plane_client_get(ec);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(plane_client, NULL);
+
+    /* acquire the surface from the client_queue */
+   tsurface = _e_plane_renderer_surface_revice(renderer, ec);
+   if (!tsurface)
+     {
+        e_pixmap_image_clear(pixmap, 1);
+        ERR("fail to _e_plane_renderer_surface_revice");
+        return NULL;
+     }
+
+   /* enqueue the surface to the layer_queue */
+   if (!_e_plane_surface_queue_enqueue(plane, tsurface))
+     {
+        _e_plane_renderer_surface_send(renderer, ec, tsurface);
+        ERR("fail to _e_plane_surface_queue_enqueue");
+        return NULL;
+     }
+
+   /* aquire */
+   tsurface = _e_plane_surface_queue_acquire(plane);
+   if (!tsurface)
+     {
+        _e_plane_renderer_surface_send(renderer, ec, tsurface);
+        ERR("fail _e_plane_surface_queue_acquire");
+        return NULL;
+     }
+
+   return tsurface;
 }
 
-EINTERN int
-e_plane_shutdown(void)
+static void
+_e_plane_surface_on_client_release(E_Plane *plane, tbm_surface_h tsurface)
 {
-   eina_stringshare_del(_e_plane_ec_last_err);
-   return 1;
+   E_Client *ec = plane->ec;
+
+   if (!ec)
+     {
+        ERR("no ec at plane.");
+        return;
+     }
+
+   /* release the tsurface */
+   e_pixmap_image_clear(ec->pixmap, 1);
 }
 
-EINTERN void
-e_plane_free(E_Plane *plane)
+static tbm_surface_h
+_e_plane_surface_from_client_acquire(E_Plane *plane)
 {
-   //printf("@@@@@@@@@@ e_plane_free: %i %i | %i %i %ix%i = %p\n", zone->num, zone->id, zone->x, zone->y, zone->w, zone->h, zone);
+   E_Client *ec = plane->ec;
+   E_Pixmap *pixmap = ec->pixmap;
+   E_Comp_Wl_Buffer *buffer = e_pixmap_resource_get(pixmap);
+   E_Comp_Wl_Data *wl_comp_data = (E_Comp_Wl_Data *)e_comp->wl_comp_data;
+   tbm_surface_h tsurface = NULL;
 
-   if (!plane) return;
-   if (plane->name) eina_stringshare_del(plane->name);
+   if (plane_trace_debug)
+     ELOGF("E_PLANE", "Display Client", pixmap, ec);
 
-   free(plane);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(buffer, NULL);
+
+   tsurface = wayland_tbm_server_get_surface(wl_comp_data->tbm.server, buffer->resource);
+   if (!tsurface)
+     {
+        ERR("fail to _e_plane_renderer_surface_revice");
+        e_pixmap_image_clear(pixmap, 1);
+        return NULL;
+     }
+
+   return tsurface;
 }
 
-EINTERN E_Plane *
-e_plane_new(E_Output *eout,
-            int zpos,
-            Eina_Bool is_pri)
+static void
+_e_plane_surface_on_ecore_evas_release(E_Plane *plane, tbm_surface_h tsurface)
 {
-   E_Plane *plane;
+   /* release the tsurface */
+   _e_plane_surface_queue_release(plane, tsurface);
+}
+
+static tbm_surface_h
+_e_plane_surface_from_ecore_evas_acquire(E_Plane *plane)
+{
+   Evas_Engine_Info_GL_Drm *einfo = NULL;
+   E_Plane_Renderer *renderer = NULL;
+   tbm_surface_h tsurface = NULL;
+   E_Output *output = plane->output;
+
+   einfo = (Evas_Engine_Info_GL_Drm *)evas_engine_info_get(e_comp->evas);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(einfo, NULL);
+
+   renderer = plane->renderer;
+
+   if (renderer->gsurface != einfo->info.surface)
+     {
+        tbm_surface_queue_h tqueue = NULL;
+
+        renderer->gsurface = einfo->info.surface;
+        tqueue = gbm_tbm_get_surface_queue(renderer->gsurface);
+        if (!tqueue)
+          {
+             ERR("no renderer->tqueue");
+             return NULL;
+          }
+
+        if (!_e_plane_renderer_queue_set(renderer, tqueue))
+          {
+             ERR("fail to _e_plane_renderer_queue_set");
+             return NULL;
+          }
+
+        /* dpms on at the first */
+        if (!e_output_dpms_set(output, E_OUTPUT_DPMS_ON))
+           WRN("fail to set the dpms on.");
+     }
+
+   if (plane_trace_debug)
+      ELOGF("E_PLANE", "Display Canvas Layer(%p)", NULL, NULL, plane);
+
+   /* aquire */
+   tsurface = _e_plane_surface_queue_acquire(plane);
+   if (!tsurface)
+     {
+        ERR("tsurface is NULL");
+        return NULL;
+     }
+
+   return tsurface;
+}
+
+static Eina_Bool
+_e_plane_cb_ec_buffer_change(void *data, int type, void *event)
+{
+   E_Client *ec = NULL;
+   E_Event_Client *ev = event;
+   E_Plane_Client *plane_client = NULL;
+
+   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;
+
+   if (e_object_is_del(E_OBJECT(ec))) return ECORE_CALLBACK_PASS_ON;
+
+   plane_client = _e_plane_client_get(ec);
+   if (!plane_client) return ECORE_CALLBACK_PASS_ON;
+
+   if (plane_client->activated) return ECORE_CALLBACK_PASS_ON;
+
+   if (_e_plane_client_surface_flags_get(plane_client) != E_PLANE_CLIENT_SURFACE_FLAGS_RESERVED)
+      return ECORE_CALLBACK_PASS_ON;
+
+   if (plane_trace_debug)
+      ELOGF("E_PLANE", "Set Backup Buffer     wl_buffer(%p):buffer_change", ec->pixmap, ec, _get_wl_buffer(ec));
 
+   if (!_e_plane_client_backup_buffer_set(plane_client))
+      ERR("fail to _e_comp_hwc_set_backup_buffer");
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+EINTERN Eina_Bool
+e_plane_init(void)
+{
+   if (client_hook_new) return EINA_TRUE;
+   if (client_hook_del) return EINA_TRUE;
+
+   client_hook_new =  e_client_hook_add(E_CLIENT_HOOK_NEW_CLIENT, _e_plane_client_cb_new, NULL);
+   client_hook_del =  e_client_hook_add(E_CLIENT_HOOK_DEL, _e_plane_client_cb_del, NULL);
+
+   plane_clients = eina_hash_pointer_new(_e_plane_client_del);
+
+   E_LIST_HANDLER_APPEND(plane_hdlrs, E_EVENT_CLIENT_BUFFER_CHANGE,
+                         _e_plane_cb_ec_buffer_change, NULL);
+
+   // soolim debug
+   plane_trace_debug = EINA_TRUE;
+
+   return EINA_TRUE;
+}
+
+EINTERN void
+e_plane_shutdown(void)
+{
+   if (client_hook_new)
+     {
+        e_client_hook_del(client_hook_new);
+        client_hook_new = NULL;
+     }
+
+   if (client_hook_del)
+     {
+        e_client_hook_del(client_hook_del);
+        client_hook_del = NULL;
+     }
+}
+
+EINTERN E_Plane *
+e_plane_new(E_Output *output, int index)
+{
+   E_Plane *plane = NULL;
+   tdm_layer *tlayer = NULL;
+   tdm_output *toutput = NULL;
+   tdm_layer_capability layer_capabilities;
    char name[40];
+   E_Plane_Renderer *renderer = NULL;
+   int zpos;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
 
-   if (!eout) return NULL;
+   toutput = output->toutput;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(toutput, NULL);
 
    plane = E_NEW(E_Plane, 1);
    EINA_SAFETY_ON_NULL_RETURN_VAL(plane, NULL);
+   plane->index = index;
 
-   snprintf(name, sizeof(name), "Plane %s", eout->id);
+   tlayer = tdm_output_get_layer(toutput, index, NULL);
+   if (!tlayer)
+   {
+      ERR("fail to get layer.");
+      free(plane);
+      return NULL;
+   }
+   plane->tlayer = tlayer;
+
+   snprintf(name, sizeof(name), "%s-plane-%d", output->id, index);
    plane->name = eina_stringshare_add(name);
 
+   CLEAR(layer_capabilities);
+   tdm_layer_get_capabilities(plane->tlayer, &layer_capabilities);
+   /* check the layer is the primary layer */
+   if (layer_capabilities&TDM_LAYER_CAPABILITY_PRIMARY)
+     {
+        plane->is_primary = EINA_TRUE;
+        plane->is_fb = EINA_TRUE; // TODO: query from libtdm if it is fb target plane
+     }
+
+   /* check that the layer uses the reserve nd memory */
+   if (layer_capabilities&TDM_LAYER_CAPABILITY_RESEVED_MEMORY)
+       plane->reserved_memory = EINA_TRUE;
+
+   /* ????? */
    plane->type = E_PLANE_TYPE_INVALID;
-   plane->eout = eout;
 
+   tdm_layer_get_zpos(tlayer, &zpos);
    plane->zpos = zpos;
-   plane->is_primary = is_pri;
-   if (plane->is_primary) plane->is_fb = EINA_TRUE; // FIXME: query from libtdm
 
-   /* config default resolution with output size*/
-   plane->geometry.x = eout->config.geom.x;
-   plane->geometry.y = eout->config.geom.y;
-   plane->geometry.w = eout->config.geom.w;
-   plane->geometry.h = eout->config.geom.h;
+   renderer = _e_plane_renderer_new(plane);
+   if (!renderer)
+     {
+        ERR("fail to _e_plane_renderer_new");
+        free(plane);
+        return NULL;
+     }
 
-   eout->planes = eina_list_append(eout->planes, plane);
+   plane->renderer = renderer;
+   plane->output = output;
 
-   printf("@@@@@@@@@@ e_plane_new:| %i %i %ix%i\n", plane->geometry.x , plane->geometry.y, plane->geometry.w, plane->geometry.h);
+   INF("E_PLANE: (%d) name:%s zpos:%d capa:%s %s",
+       index, plane->name, plane->zpos,plane->is_primary?"primary":"", plane->reserved_memory?"reserved_memory":"");
 
    return plane;
 }
 
-E_API Eina_Bool
-e_plane_resolution_set(E_Plane *plane,
-                       int w,
-                       int h)
+EINTERN void
+e_plane_free(E_Plane *plane)
+{
+   if (!plane) return;
+
+   if (plane->name) eina_stringshare_del(plane->name);
+   if (plane->renderer) _e_plane_renderer_del(plane->renderer);
+
+   free(plane);
+}
+
+EINTERN Eina_Bool
+e_plane_hwc_setup(E_Plane *plane)
+{
+   Evas_Engine_Info_GL_Drm *einfo;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(plane, EINA_FALSE);
+
+   /* we assume that the primary plane gets a ecore_evas */
+   if (!plane->is_primary) return EINA_FALSE;
+
+   /* get the evas_engine_gl_drm information */
+   einfo = (Evas_Engine_Info_GL_Drm *)evas_engine_info_get(e_comp->evas);
+   if (!einfo) return EINA_FALSE;
+   /* enable hwc to evas engine gl_drm */
+   einfo->info.hwc_enable = EINA_TRUE;
+
+   plane->ee = e_comp->ee;
+   plane->evas = ecore_evas_get(plane->ee);
+   evas_event_callback_add(plane->evas, EVAS_CALLBACK_RENDER_POST, _e_plane_ee_post_render_cb, plane);
+   ecore_evas_manual_render_set(plane->ee, 1);
+
+   return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_plane_set(E_Plane *plane)
 {
-   int dx = 0, dy = 0, dw = 0, dh = 0;
+   tbm_surface_h tsurface = NULL;
+   Evas_Engine_Info_GL_Drm *einfo;
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(plane, EINA_FALSE);
 
-   if (plane->is_primary) return EINA_FALSE;
+   if (plane->is_primary && !plane->ec)
+     {
+        ecore_evas_manual_render(plane->ee);
+
+        /* check the post_render is called */
+        if (!plane->update_ee)
+        {
+          ELOGF("E_PLANE", "Post Render callback does not called. Nothing Display.", NULL, NULL);
+          return EINA_FALSE;
+        }
+        plane->update_ee = EINA_FALSE;
+
+        einfo = (Evas_Engine_Info_GL_Drm *)evas_engine_info_get(e_comp->evas);
+        if (!einfo) return EINA_FALSE;
+        /* check outbuf flushed or ont */
+        if (!einfo->info.outbuf_flushed)
+          {
+             if (plane_trace_debug)
+               ELOGF("E_PLANE", "Commit Canvas outbuf flush nothing!. Nothing Display.", NULL, NULL);
+             if (plane->update_ee) plane->update_ee = EINA_FALSE;
+             return EINA_FALSE;
+          }
+
+        /* uncheck the outbuf_flushed flag */
+        einfo->info.outbuf_flushed = EINA_FALSE;
+
+        tsurface = _e_plane_surface_from_ecore_evas_acquire(plane);
+     }
+   else
+     {
+        E_Comp_Wl_Buffer *buffer = NULL;
+
+        if (!plane->ec) return EINA_FALSE;
+
+        if (!e_comp_object_hwc_update_exists(plane->ec->frame)) return EINA_FALSE;
+
+        e_comp_object_hwc_update_set(plane->ec->frame, EINA_FALSE);
 
-   if ((w == plane->geometry.w) && (h == plane->geometry.h))
-     return EINA_FALSE;
+        buffer = e_pixmap_resource_get(plane->ec->pixmap);
+        if (!buffer)
+          {
+            ERR("buffer is null.");
+            return EINA_FALSE;
+          }
 
-   plane->geometry.w = w;
-   plane->geometry.h = h;
+        if (plane->reserved_memory)
+          tsurface = _e_plane_surface_from_client_acquire_reserved(plane);
+        else
+          tsurface = _e_plane_surface_from_client_acquire(plane);
+     }
+
+   plane->previous_tsurface = plane->prepare_tsurface;
+   plane->prepare_tsurface = tsurface;
+
+   /* set plane info and set tsurface to the plane */
+   if (!_e_plane_surface_set(plane, tsurface))
+     {
+        ERR("fail: _e_plane_set_info.");
+        e_plane_unset(plane);
+        return EINA_FALSE;
+     }
 
-   /* TODO: config clist refer to resolution */
-   _e_plane_reconfigure_clients(plane, dx, dy, dw, dh);
    return EINA_TRUE;
 }
 
+EINTERN void
+e_plane_unset(E_Plane *plane)
+{
+   EINA_SAFETY_ON_NULL_RETURN(plane);
+   EINA_SAFETY_ON_NULL_RETURN(plane->prepare_tsurface);
+
+   if (plane->is_primary && !plane->ec)
+     _e_plane_surface_on_ecore_evas_release(plane, plane->prepare_tsurface);
+   else
+     {
+        if (!plane->ec) return;
+        if (plane->reserved_memory) _e_plane_surface_on_client_reserved_release(plane, plane->prepare_tsurface);
+        else _e_plane_surface_on_client_release(plane, plane->prepare_tsurface);
+     }
+
+   /* set plane info and set prevous tsurface to the plane */
+   if (!_e_plane_surface_set(plane, plane->tsurface))
+     {
+        ERR("fail: _e_plane_set_info.");
+        return;
+     }
+}
+
+EINTERN E_Plane_Commit_Data *
+e_plane_commit_data_aquire(E_Plane *plane)
+{
+   E_Plane_Commit_Data *data = NULL;
+   Evas_Engine_Info_GL_Drm *einfo = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(plane, NULL);
+
+   if (plane->is_primary && !plane->ec)
+     {
+        data = E_NEW(E_Plane_Commit_Data, 1);
+        data->plane = plane;
+        data->tsurface = plane->prepare_tsurface;
+        tbm_surface_internal_ref(data->tsurface);
+        data->ec = NULL;
+
+        einfo = (Evas_Engine_Info_GL_Drm *)evas_engine_info_get(e_comp->evas);
+        einfo->info.wait_for_showup = EINA_TRUE;
+
+        return data;
+     }
+   else
+     {
+        if (plane->ec)
+          {
+             data = E_NEW(E_Plane_Commit_Data, 1);
+             data->plane = plane;
+             data->tsurface = plane->prepare_tsurface;
+             tbm_surface_internal_ref(data->tsurface);
+             data->ec = plane->ec;
+             e_comp_wl_buffer_reference(&data->buffer_ref, e_pixmap_resource_get(plane->ec->pixmap));
+
+             /* send frame event enlightenment dosen't send frame evnet in nocomp */
+             e_pixmap_image_clear(plane->ec->pixmap, 1);
+             return data;
+          }
+     }
+
+   return NULL;
+}
+
+EINTERN void
+e_plane_commit_data_release(E_Plane_Commit_Data *data)
+{
+   E_Plane *plane = NULL;
+   E_Plane_Renderer *renderer = NULL;
+   Evas_Engine_Info_GL_Drm *einfo = NULL;
+   tbm_surface_h tsurface = NULL;
+   E_Client *ec = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN(data);
+
+   plane = data->plane;
+   tsurface = data->tsurface;
+   ec = data->ec;
+   renderer = plane->renderer;
+
+   if (plane->is_primary && !ec)
+     {
+        /* composite */
+        /* debug */
+        if (plane_trace_debug)
+          ELOGF("E_PLANE", "Done    Layer(%p)  tsurface(%p) tqueue(%p) data(%p)::Canvas",
+               NULL, NULL, plane, tsurface, renderer->tqueue, data);
+
+        if (plane->reserved_memory)
+          {
+             if (!renderer->activated_ec)
+               {
+                  einfo = (Evas_Engine_Info_GL_Drm *)evas_engine_info_get(e_comp->evas);
+                  einfo->info.wait_for_showup = EINA_FALSE;
+               }
+
+             /* initial setting of tsurface to the layer */
+             if (plane->tsurface == NULL)
+               plane->tsurface = tsurface;
+             else
+               {
+                  _e_plane_surface_queue_release(plane, plane->tsurface);
+                  e_comp_wl_buffer_reference(&plane->displaying_buffer_ref, NULL);
+                  plane->tsurface = tsurface;
+               }
+
+             /* send the done surface to the client,
+                only when the renderer state is active(no composite) */
+             if (renderer->activated_ec)
+                _e_plane_renderer_dequeuable_surfaces_export(renderer, renderer->activated_ec);
+          }
+        else
+          {
+             einfo = (Evas_Engine_Info_GL_Drm *)evas_engine_info_get(e_comp->evas);
+             einfo->info.wait_for_showup = EINA_FALSE;
+
+             /* initial setting of tsurface to the layer */
+             if (plane->tsurface == NULL)
+               plane->tsurface = tsurface;
+             else
+               {
+                  _e_plane_surface_queue_release(plane, plane->tsurface);
+                  plane->tsurface = tsurface;
+               }
+          }
+
+        tbm_surface_internal_unref(tsurface);
+        free(data);
+     }
+   else
+     {
+        /* no composite */
+        /* debug */
+        if (plane_trace_debug)
+           ELOGF("E_PLANE", "Done    Layer(%p)     wl_buffer(%p) tsurface(%p) tqueue(%p) data(%p) wl_buffer_ref(%p) ::Client",
+             ec->pixmap, ec, plane, _get_wl_buffer(ec), tsurface, renderer->tqueue, data, _get_wl_buffer_ref(ec));
+
+        if (plane->reserved_memory)
+          {
+             /* release */
+             if (plane->tsurface)
+               {
+                  _e_plane_surface_queue_release(plane, plane->tsurface);
+                  e_comp_wl_buffer_reference(&plane->displaying_buffer_ref, data->buffer_ref.buffer);
+                  _e_plane_surface_on_client_reserved_release(plane, plane->tsurface);
+                  plane->tsurface = tsurface;
+               }
+
+             /* send the done surface to the client,
+                only when the renderer state is active(no composite) */
+             if (renderer->activated_ec)
+                _e_plane_renderer_dequeuable_surfaces_export(renderer, renderer->activated_ec);
+          }
+        else
+          {
+             /* release wl_buffer */
+             e_pixmap_image_clear(ec->pixmap, 1);
+          }
+
+        tbm_surface_internal_unref(tsurface);
+        e_comp_wl_buffer_reference(&data->buffer_ref, NULL);
+        free(data);
+     }
+}
+
+EINTERN Eina_Bool
+e_plane_is_reserved(E_Plane *plane)
+{
+   return plane->is_reserved;
+}
+
+EINTERN void
+e_plane_reserved_set(E_Plane *plane, Eina_Bool set)
+{
+   plane->is_reserved = set;
+}
+
 E_API Eina_Bool
 e_plane_type_set(E_Plane *plane,
                  E_Plane_Type type)
@@ -134,6 +1802,84 @@ e_plane_ec_get(E_Plane *plane)
    return plane->ec;
 }
 
+E_API Eina_Bool
+e_plane_ec_set(E_Plane *plane, E_Client *ec)
+{
+   E_Plane_Renderer *renderer = NULL;
+   Evas_Engine_Info_GL_Drm *einfo = NULL;
+   E_Plane_Client *plane_client = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(plane, EINA_FALSE);
+
+   renderer = plane->renderer;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(renderer, EINA_FALSE);
+
+   einfo = (Evas_Engine_Info_GL_Drm *)evas_engine_info_get(e_comp->evas);
+
+   if (!ec && renderer->candidate_ec)
+     {
+        if (!plane->is_primary)
+           _e_plane_renderer_queue_del(renderer);
+
+        if (!_e_plane_renderer_deactivate(renderer))
+          {
+             ERR("fail to _e_plane_renderer_deactivate.");
+             return EINA_FALSE;
+          }
+     }
+
+   if (!ec && !plane->ec) return EINA_FALSE;
+
+   /* activate/deactivate the client if the plane is the reserved memory */
+   if (plane->reserved_memory)
+     {
+        if (ec)
+          {
+             if (!plane->is_primary)
+                _e_plane_renderer_queue_create(renderer, ec->client.w, ec->client.h);
+
+             if (!_e_plane_renderer_activate(renderer, ec))
+               {
+                  INF("can't activate ec:%p.", ec);
+
+                  if (!_e_plane_surface_queue_can_dequeue(renderer->plane))
+                     einfo->info.wait_for_showup = EINA_TRUE;
+
+                  return EINA_FALSE;
+               }
+
+             einfo->info.wait_for_showup = EINA_TRUE;
+             e_comp_object_hwc_update_set(ec->frame, EINA_TRUE);
+          }
+        else
+          {
+              if (!plane->is_primary)
+                 _e_plane_renderer_queue_del(renderer);
+
+              if (!_e_plane_renderer_deactivate(renderer))
+                {
+                   ERR("fail to _e_plane_renderer_deactivate.");
+                   return EINA_FALSE;
+                }
+
+             einfo->info.wait_for_showup = EINA_FALSE;
+          }
+     }
+
+   if (ec)
+     {
+        plane_client = _e_plane_client_get(ec);
+        if (plane_client) plane_client->plane = plane;
+     }
+
+   plane->ec = ec;
+
+   if (plane_trace_debug)
+      ELOGF("E_PLANE", "Plane(%p) ec Set", (ec ? ec->pixmap : NULL), ec, plane);
+
+   return EINA_TRUE;
+}
+
 E_API E_Client *
 e_plane_ec_prepare_get(E_Plane *plane)
 {
@@ -142,25 +1888,13 @@ e_plane_ec_prepare_get(E_Plane *plane)
 }
 
 E_API Eina_Bool
-e_plane_ec_prepare_set(E_Plane *plane,
-                       E_Client *ec)
+e_plane_ec_prepare_set(E_Plane *plane, E_Client *ec)
 {
-   if(!plane)
-     {
-        eina_stringshare_replace(&_e_plane_ec_last_err, "Invalid e_plane were passed");
-        goto err;
-     }
+   EINA_SAFETY_ON_NULL_RETURN_VAL(plane, EINA_FALSE);
 
-   if (plane->type == E_PLANE_TYPE_OVERLAY)
-     {
-        eina_stringshare_replace(&_e_plane_ec_last_err, NULL);
-        plane->prepare_ec = ec;
-        return EINA_TRUE;
-     }
-   eina_stringshare_replace(&_e_plane_ec_last_err, "Type dismatch : ec not availabe on e_plane");
-err:
+   plane->prepare_ec = ec;
 
-   return EINA_FALSE;
+   return EINA_TRUE;
 }
 
 E_API const char *
@@ -192,24 +1926,10 @@ e_plane_color_val_get(E_Plane *plane)
    return plane->color;
 }
 
-E_API void
-e_plane_geom_get(E_Plane *plane,
-                 int *x,
-                 int *y,
-                 int *w,
-                 int *h)
-{
-   if (!plane) return;
-   if (x) *x = plane->geometry.x;
-   if (y) *y = plane->geometry.y;
-   if (w) *w = plane->geometry.w;
-   if (h) *h = plane->geometry.h;
-}
-
 E_API Eina_Bool
 e_plane_is_fb_target(E_Plane *plane)
 {
    EINA_SAFETY_ON_NULL_RETURN_VAL(plane, EINA_FALSE);
    if (plane->is_fb) return EINA_TRUE;
    return EINA_FALSE;
-}
\ No newline at end of file
+}
index cae3ebb7dbbd19839d725f680b869899ab8fc3c0..179e42c6bbb4baa20a82b1d966765d874ef60012 100644 (file)
@@ -1,6 +1,6 @@
 #ifdef E_TYPEDEFS
 
-typedef enum _E_Plane_Type_State
+typedef enum _E_Plane_Type
 {
    E_PLANE_TYPE_INVALID,
    E_PLANE_TYPE_VIDEO,
@@ -16,48 +16,95 @@ typedef enum _E_Plane_Color
 } E_Plane_Color;
 
 typedef struct _E_Plane                      E_Plane;
-
+typedef struct _E_Plane_Renderer             E_Plane_Renderer;
+typedef struct _E_Plane_Commit_Data          E_Plane_Commit_Data;
 #else
 #ifndef E_PLANE_H
 #define E_PLANE_H
 
 #define E_PLANE_TYPE (int)0xE0b11001
 
+#include "e_comp_screen.h"
+#include "e_output.h"
+# include "e_comp_wl.h"
+
 struct _E_Plane
 {
+   int                   index;
    int                   zpos;
-   struct
-     {
-        int          x, y, w, h;
-     } geometry;
-
    const char           *name;
    E_Plane_Type          type;
    E_Plane_Color         color;
+   Eina_Bool             is_primary;
+   Eina_Bool             is_fb;        // fb target
+   Eina_Bool             is_reserved;  // surface assignment reserved
 
    E_Client             *ec;
    E_Client             *prepare_ec;
-   E_Output             *eout;
 
-   Eina_Bool             is_primary;
-   Eina_Bool             is_fb; // fb target
+   Eina_Bool             reserved_memory;
+
+   tdm_layer            *tlayer;
+   tdm_info_layer        info;
+   tbm_surface_h         tsurface;
+   tbm_surface_h         previous_tsurface;
+   tbm_surface_h         prepare_tsurface;
+
+   unsigned int          last_sequence;
+   E_Comp_Wl_Buffer_Ref  displaying_buffer_ref;
+
+   E_Plane_Renderer     *renderer;
+   E_Output             *output;
+
+   Ecore_Evas           *ee;
+   Evas                 *evas;
+   Eina_Bool             update_ee;
+
+   Eina_Bool             trace_debug;
+};
+
+struct _E_Plane_Renderer {
+   tbm_surface_queue_h tqueue;
+
+   E_Client           *activated_ec;
+   E_Client           *candidate_ec;
+
+   struct gbm_surface *gsurface;
+   Eina_List          *disp_surfaces;
+   Eina_List          *sent_surfaces;
+   Eina_List          *exported_surfaces;
+
+   E_Plane            *plane;
+};
+
+struct _E_Plane_Commit_Data {
+   tbm_surface_h  tsurface;
+   E_Plane       *plane;
+   E_Client      *ec;
+   E_Comp_Wl_Buffer_Ref  buffer_ref;
 };
 
-EINTERN int                  e_plane_init(void);
-EINTERN int                  e_plane_shutdown(void);
-EINTERN E_Plane             *e_plane_new(E_Output *eout, int zpos, Eina_Bool is_pri);
+EINTERN Eina_Bool            e_plane_init(void);
+EINTERN void                 e_plane_shutdown(void);
+EINTERN E_Plane             *e_plane_new(E_Output *output, int index);
 EINTERN void                 e_plane_free(E_Plane *plane);
-E_API Eina_Bool              e_plane_resolution_set(E_Plane *plane, int w, int h);
+EINTERN Eina_Bool            e_plane_hwc_setup(E_Plane *plane);
+EINTERN Eina_Bool            e_plane_set(E_Plane *plane);
+EINTERN void                 e_plane_unset(E_Plane *plane);
+EINTERN E_Plane_Commit_Data *e_plane_commit_data_aquire(E_Plane *plane);
+EINTERN void                 e_plane_commit_data_release(E_Plane_Commit_Data *data);
+EINTERN Eina_Bool            e_plane_is_reserved(E_Plane *plane);
+EINTERN void                 e_plane_reserved_set(E_Plane *plane, Eina_Bool set);
 E_API Eina_Bool              e_plane_type_set(E_Plane *plane, E_Plane_Type type);
 E_API E_Plane_Type           e_plane_type_get(E_Plane *plane);
 E_API E_Client              *e_plane_ec_get(E_Plane *plane);
+E_API Eina_Bool              e_plane_ec_set(E_Plane *plane, E_Client *ec);
 E_API E_Client              *e_plane_ec_prepare_get(E_Plane *plane);
 E_API Eina_Bool              e_plane_ec_prepare_set(E_Plane *plane, E_Client *ec);
 E_API const char            *e_plane_ec_prepare_set_last_error_get(E_Plane *plane);
 E_API Eina_Bool              e_plane_is_primary(E_Plane *plane);
 E_API Eina_Bool              e_plane_is_cursor(E_Plane *plane);
 E_API E_Plane_Color          e_plane_color_val_get(E_Plane *plane);
-E_API void                   e_plane_geom_get(E_Plane *plane, int *x, int *y, int *w, int *h);
 E_API Eina_Bool              e_plane_is_fb_target(E_Plane *plane);
 
 #endif