e_comp: move hwc policy to e_output_hwc 18/159218/6 accepted/tizen/unified/20171114.132351 submit/tizen/20171114.052113
authorChangyeon Lee <cyeon.lee@samsung.com>
Mon, 11 Sep 2017 09:07:57 +0000 (18:07 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Mon, 13 Nov 2017 23:44:07 +0000 (23:44 +0000)
The hwc policy applys to each E_Output.
The hwc policy is decided in the idle enterer instead of in the job handler(_e_comp_update_cb).
Therefore, e20 can decide the hwc policy without calling e_comp_redner_queue() when the e20 enters the idle.

Change-Id: I835bae1dd931d9ce157c3944bf6e0151764ab9ca

12 files changed:
src/bin/Makefile.mk
src/bin/e_comp.c
src/bin/e_comp.h
src/bin/e_comp_screen.c
src/bin/e_desk.c
src/bin/e_includes.h
src/bin/e_info_server.c
src/bin/e_output.c
src/bin/e_output.h
src/bin/e_output_hwc.c [new file with mode: 0644]
src/bin/e_output_hwc.h [new file with mode: 0644]
src/bin/e_test_helper.c

index f672302723c121c4200007ad2b1b101901fc08cd..bf2761ab5764bf53af15bac0c4901bbb4ae38791 100644 (file)
@@ -84,6 +84,7 @@ src/bin/e_zoomap.h \
 src/bin/e_zone.h \
 src/bin/e_util_transform.h \
 src/bin/e_comp_screen.h \
+src/bin/e_output_hwc.h \
 src/bin/e_info_protocol.h \
 src/bin/e_uuid_store.h \
 src/bin/e_comp_wl_data.h \
@@ -133,6 +134,7 @@ src/bin/e_comp_canvas.c \
 src/bin/e_comp_cfdata.c \
 src/bin/e_comp_object.c \
 src/bin/e_comp_screen.c \
+src/bin/e_output_hwc.c \
 src/bin/e_config.c \
 src/bin/e_config_data.c \
 src/bin/e_dbusmenu.c \
index 15e216b7748a51837a5483439a72bdf0b49859a3..a27e7f7751cbc592fc4e790368bdf30c26f89d88 100644 (file)
@@ -43,13 +43,6 @@ static Eina_Inlist *_e_comp_hooks[] =
    [E_COMP_HOOK_PREPARE_PLANE] = NULL,
 };
 
-typedef enum _E_Comp_HWC_Mode
-{
-   E_HWC_MODE_NO = 0,
-   E_HWC_MODE_HYBRID,
-   E_HWC_MODE_FULL
-} E_Comp_HWC_Mode;
-
 E_API int E_EVENT_COMPOSITOR_RESIZE = -1;
 E_API int E_EVENT_COMPOSITOR_DISABLE = -1;
 E_API int E_EVENT_COMPOSITOR_ENABLE = -1;
@@ -168,7 +161,6 @@ _e_comp_fps_update(void)
      }
 }
 
-#ifdef ENABLE_HWC_MULTI
 static void
 _e_comp_hooks_clean(void)
 {
@@ -186,8 +178,8 @@ _e_comp_hooks_clean(void)
        }
 }
 
-static void
-_e_comp_hook_call(E_Comp_Hook_Point hookpoint, void *data EINA_UNUSED)
+EINTERN void
+e_comp_hook_call(E_Comp_Hook_Point hookpoint, void *data EINA_UNUSED)
 {
    E_Comp_Hook *ch;
 
@@ -202,748 +194,6 @@ _e_comp_hook_call(E_Comp_Hook_Point hookpoint, void *data EINA_UNUSED)
      _e_comp_hooks_clean();
 }
 
-static int
-_hwc_set(E_Output *eout)
-{
-   const Eina_List *ep_l = NULL, *l;
-   E_Plane *ep = NULL;
-   E_Comp_HWC_Mode mode = E_HWC_MODE_NO;
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(eout, EINA_FALSE);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(eout->planes, EINA_FALSE);
-
-   ep_l = e_output_planes_get(eout);
-   EINA_LIST_REVERSE_FOREACH(ep_l, l , ep)
-     {
-        Eina_Bool set = EINA_FALSE;
-
-        if (e_plane_is_fb_target(ep))
-          {
-             if (ep->prepare_ec)
-               {
-                  set = e_plane_ec_set(ep, ep->prepare_ec);
-                  if (set)
-                    {
-                       ELOGF("HWC", "is set on fb_target( %d)", ep->prepare_ec->pixmap, ep->prepare_ec, ep->zpos);
-                       mode = E_HWC_MODE_FULL;
-
-                       // fb target is occupied by a client surface, means compositor disabled
-                       ecore_event_add(E_EVENT_COMPOSITOR_DISABLE, NULL, NULL, NULL);
-                    }
-                  break;
-               }
-          }
-        else if (ep->prepare_ec)
-          {
-             set = e_plane_ec_set(ep, ep->prepare_ec);
-             if (set)
-               {
-                  ELOGF("HWC", "is set on %d", ep->prepare_ec->pixmap, ep->prepare_ec, ep->zpos);
-                  mode |= E_HWC_MODE_HYBRID;
-               }
-             else
-               break;
-          }
-     }
-
-   return mode;
-}
-
-static Eina_Bool
-_hwc_available_get(E_Client *ec)
-{
-   E_Comp_Wl_Client_Data *cdata = (E_Comp_Wl_Client_Data*)ec->comp_data;
-   E_Output *eout;
-   int minw = 0, minh = 0;
-
-   if ((!cdata) ||
-       (!cdata->buffer_ref.buffer) ||
-       (cdata->width_from_buffer != cdata->width_from_viewport) ||
-       (cdata->height_from_buffer != cdata->height_from_viewport) ||
-       cdata->never_hwc)
-     {
-        return EINA_FALSE;
-     }
-
-   if (e_client_transform_core_enable_get(ec)) return EINA_FALSE;
-
-   switch (cdata->buffer_ref.buffer->type)
-     {
-      case E_COMP_WL_BUFFER_TYPE_NATIVE:
-         break;
-      case E_COMP_WL_BUFFER_TYPE_TBM:
-         if (cdata->buffer_ref.buffer->resource)
-           break;
-      case E_COMP_WL_BUFFER_TYPE_SHM:
-         if (!e_util_strcmp("wl_pointer-cursor", ec->icccm.window_role))
-           break;
-
-      default:
-         return EINA_FALSE;
-     }
-
-   if (e_comp_wl_tbm_buffer_sync_timeline_used(cdata->buffer_ref.buffer))
-     return EINA_FALSE;
-
-   eout = e_output_find(ec->zone->output_id);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(eout, EINA_FALSE);
-
-   tdm_output_get_available_size(eout->toutput, &minw, &minh, NULL, NULL, NULL);
-
-   if ((minw > 0) && (minw > cdata->buffer_ref.buffer->w))
-     return EINA_FALSE;
-   if ((minh > 0) && (minh > cdata->buffer_ref.buffer->h))
-     return EINA_FALSE;
-
-   /* If a client doesn't watch the ignore_output_transform events, we can't show
-    * a client buffer to HW overlay directly when the buffer transform is not same
-    * with output transform. If a client watch the ignore_output_transform events,
-    * we can control client's buffer transform. In this case, we don't need to
-    * check client's buffer transform here.
-    */
-   if (!e_comp_screen_rotation_ignore_output_transform_watch(ec))
-     {
-        int transform = e_comp_wl_output_buffer_transform_get(ec);
-
-        if ((eout->config.rotation / 90) != transform)
-          return EINA_FALSE;
-     }
-
-   return EINA_TRUE;
-}
-
-static void
-_hwc_prepare_init(E_Output *eout)
-{
-   const Eina_List *ep_l = NULL, *l ;
-   E_Plane *ep = NULL;
-
-   ep_l = e_output_planes_get(eout);
-   EINA_LIST_FOREACH(ep_l, l, ep)
-     {
-        if (!e_comp->hwc_use_multi_plane &&
-            !e_plane_is_cursor(ep) &&
-            !e_plane_is_fb_target(ep))
-          continue;
-
-        e_plane_ec_prepare_set(ep, NULL);
-     }
-}
-
-static int
-_hwc_prepare_cursor(E_Output *eout, int n_cur, Eina_List *hwc_clist)
-{
-   // policy for cursor layer
-   const Eina_List *ep_l = NULL, *l ;
-   Eina_List *cur_ly = NULL;
-   E_Plane *ep = NULL;
-   int n_skip = 0;
-   int n_curly = 0;
-   int nouse = 0;
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_clist, EINA_FALSE);
-
-   // list up cursor only layers
-   ep_l = e_output_planes_get(eout);
-   EINA_LIST_FOREACH(ep_l, l, ep)
-     {
-        if (e_plane_is_cursor(ep))
-          {
-             cur_ly = eina_list_append(cur_ly, ep);
-             continue;
-          }
-     }
-
-   if (!cur_ly) return 0;
-   n_curly = eina_list_count(cur_ly);
-
-   if (n_cur > 0 && n_curly > 0)
-     {
-        if (n_cur >= n_curly) nouse = 0;
-        else nouse = n_curly - n_cur;
-
-        //assign cursor on cursor only layers
-        EINA_LIST_REVERSE_FOREACH(cur_ly, l, ep)
-          {
-             E_Client *ec = NULL;
-             if (nouse > 0)
-               {
-                  nouse--;
-                  continue;
-               }
-             if (hwc_clist) ec = eina_list_data_get(hwc_clist);
-             if (ec && e_plane_ec_prepare_set(ep, ec))
-               {
-                  n_skip += 1;
-                  hwc_clist = eina_list_next(hwc_clist);
-               }
-          }
-     }
-
-   eina_list_free(cur_ly);
-
-   return n_skip;
-}
-
-static Eina_Bool
-_hwc_prepare(E_Output *eout, int n_vis, int n_skip, Eina_List *hwc_clist)
-{
-   const Eina_List *ep_l = NULL, *l ;
-   Eina_List *hwc_ly = NULL;
-   E_Plane *ep = NULL, *ep_fb = NULL;
-   int n_ly = 0, n_ec = 0;
-   E_Client *ec = NULL;
-   Eina_Bool ret = EINA_FALSE;
-   int nouse = 0;
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(eout, EINA_FALSE);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_clist, EINA_FALSE);
-
-   n_ec = eina_list_count(hwc_clist);
-   if (n_skip > 0)
-     {
-        int i;
-        for (i = 0; i < n_skip; i++)
-          hwc_clist = eina_list_next(hwc_clist);
-
-        n_ec -= n_skip;
-        n_vis -= n_skip;
-     }
-
-   if (n_ec <= 0) return EINA_FALSE;
-
-   // list up available_hw layers E_Client can be set
-   // if e_comp->hwc_use_multi_plane FALSE, than use only fb target plane
-   ep_l = e_output_planes_get(eout);
-   EINA_LIST_FOREACH(ep_l, l, ep)
-     {
-        if (!ep_fb)
-          {
-             if (e_plane_is_fb_target(ep))
-               {
-                  ep_fb = ep;
-                  hwc_ly = eina_list_append(hwc_ly, ep);
-               }
-             continue;
-          }
-        if (!e_comp->hwc_use_multi_plane) continue;
-        if (e_plane_is_cursor(ep)) continue;
-        if (ep->zpos > ep_fb->zpos)
-          hwc_ly = eina_list_append(hwc_ly, ep);
-     }
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_ly, EINA_FALSE);
-
-   // finally, assign client on available_hw layers
-   n_ly = eina_list_count(hwc_ly);
-   if ((n_ec == n_vis) &&
-       (n_ec <= n_ly)) // fully hwc
-     {
-        nouse = n_ly - n_ec;
-     }
-   else if ((n_ly < n_vis) || // e_comp->evas on fb target plane
-            (n_ec < n_vis))
-     {
-        if (n_ec <= n_ly) nouse = n_ly - n_ec - 1;
-        else nouse = 0;
-     }
-
-   EINA_LIST_REVERSE_FOREACH(hwc_ly, l, ep)
-     {
-        ec = NULL;
-        if (nouse > 0)
-          {
-             nouse--;
-             continue;
-          }
-        if (hwc_clist) ec = eina_list_data_get(hwc_clist);
-        if (ec && e_plane_ec_prepare_set(ep, ec))
-          {
-             ret = EINA_TRUE;
-
-             hwc_clist = eina_list_next(hwc_clist);
-             n_ec--; n_vis--;
-          }
-        if (e_plane_is_fb_target(ep))
-          {
-             if (n_ec > 0 || n_vis > 0) e_plane_ec_prepare_set(ep, NULL);
-             break;
-          }
-     }
-
-   eina_list_free(hwc_ly);
-
-   return ret;
-}
-
-static Eina_Bool
-_hwc_cancel(E_Output *eout)
-{
-   Eina_List *l ;
-   E_Plane *ep;
-   Eina_Bool ret = EINA_TRUE;
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(eout, EINA_FALSE);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(eout->planes, EINA_FALSE);
-
-   EINA_LIST_FOREACH(eout->planes, l, ep)
-     {
-        if (!e_comp->hwc_use_multi_plane &&
-            !e_plane_is_cursor(ep) &&
-            !e_plane_is_fb_target(ep))
-          {
-             if (ep->ec) ret = EINA_FALSE; // core cannot end HWC
-             continue;
-          }
-
-        e_plane_ec_prepare_set(ep, NULL);
-        e_plane_ec_set(ep, NULL);
-     }
-
-   return ret;
-}
-
-static Eina_Bool
-_hwc_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);
-        if (!eout) continue;;
-        EINA_LIST_FOREACH(eout->planes, ll, ep)
-          {
-             if (!e_comp->hwc_use_multi_plane &&
-                 !e_plane_is_cursor(ep) &&
-                 !e_plane_is_fb_target(ep))
-               continue;
-
-             if (e_plane_is_reserved(ep))
-                e_plane_reserved_set(ep, 0);
-          }
-     }
-
-   return EINA_TRUE;
-}
-
-static void
-_hwc_plane_unset(E_Plane *ep)
-{
-   if (e_plane_is_reserved(ep))
-     e_plane_reserved_set(ep, 0);
-
-   e_plane_ec_prepare_set(ep, NULL);
-   e_plane_ec_set(ep, NULL);
-
-   ELOGF("HWC", "unset plane %d to NULL", NULL, NULL, ep->zpos);
-}
-
-static Eina_Bool
-_hwc_plane_change_ec(E_Plane *ep, E_Client *old_ec, E_Client *new_ec)
-{
-   Eina_Bool ret = EINA_FALSE;
-
-   if (!new_ec)
-     {
-        if (e_plane_is_reserved(ep))
-          e_plane_reserved_set(ep, 0);
-     }
-
-   e_plane_ec_prepare_set(ep, NULL);
-
-   if (e_plane_ec_set(ep, new_ec))
-     {
-        if (new_ec)
-          {
-             ELOGF("HWC", "new_ec(%s) is set on %d",
-                   new_ec->pixmap, new_ec,
-                   e_client_util_name_get(new_ec) ? new_ec->icccm.name : "no name", ep->zpos);
-          }
-        else
-          {
-             ELOGF("HWC", "NULL is set on %d", NULL, NULL, ep->zpos);
-          }
-        ret = EINA_TRUE;
-     }
-   else
-     {
-        ELOGF("HWC", "failed to set new_ec(%s) on %d",
-              NULL, new_ec,
-              new_ec ? (new_ec->icccm.name ? new_ec->icccm.name : "no name") : "NULL",
-              ep->zpos);
-     }
-
-   return ret;
-}
-
-static Eina_Bool
-_e_comp_hwc_apply(E_Output * eout)
-{
-   const Eina_List *ep_l = NULL, *l;
-   E_Plane *ep = NULL, *ep_fb = NULL;
-   int mode = 0;
-
-   ep_l = e_output_planes_get(eout);
-   EINA_LIST_FOREACH(ep_l, l, ep)
-     {
-        if (!ep_fb)
-          {
-             if (e_plane_is_fb_target(ep))
-               {
-                  ep_fb = ep;
-                  if (ep->prepare_ec != NULL) goto hwcompose;
-               }
-             continue;
-          }
-        if (ep->zpos > ep_fb->zpos)
-          if (ep->prepare_ec != NULL) goto hwcompose;
-     }
-
-   goto compose;
-
-hwcompose:
-   mode = _hwc_set(eout);
-   if (mode == E_HWC_MODE_NO) ELOGF("HWC", "it is failed to assign surface on plane", NULL, NULL);
-
-compose:
-   if (mode != E_HWC_MODE_NO) e_comp->hwc_mode = mode;
-
-   return !!mode;
-}
-
-static Eina_Bool
-_e_comp_hwc_changed(void)
-{
-   Eina_List *l;
-   E_Zone *zone;
-   Eina_Bool ret = EINA_FALSE;
-
-   EINA_LIST_FOREACH(e_comp->zones, l, zone)
-     {
-        E_Output *eout = NULL;
-        E_Plane *ep = NULL;
-        const Eina_List *ep_l = NULL, *p_l;
-        Eina_Bool assign_success = EINA_TRUE;
-        int mode = E_HWC_MODE_NO;
-
-        if (!zone || !zone->output_id) continue;
-
-        eout = e_output_find(zone->output_id);
-        if (!eout) continue;
-        ep_l = e_output_planes_get(eout);
-        EINA_LIST_REVERSE_FOREACH(ep_l, p_l, ep)
-          {
-             if (!assign_success)
-               {
-                  //unset planes from 'assign_success' became EINA_FALSE to the fb target
-                  _hwc_plane_unset(ep);
-                  continue;
-               }
-
-             if (ep->ec != ep->prepare_ec)
-               {
-                  assign_success = _hwc_plane_change_ec(ep, ep->ec, ep->prepare_ec);
-                  ret = EINA_TRUE;
-               }
-             else if (!ep->prepare_ec)
-               {
-                  if (e_plane_is_reserved(ep))
-                    {
-                       e_plane_reserved_set(ep, 0);
-                       ELOGF("HWC", "unset reserved mem on %d", NULL, NULL, ep->zpos);
-                    }
-               }
-
-             if (ep->ec) mode = E_HWC_MODE_HYBRID;
-
-             if (e_plane_is_fb_target(ep))
-               {
-                  if (ep->ec) mode = E_HWC_MODE_FULL;
-                  break;
-               }
-          }
-
-        if (e_comp->hwc_mode != mode)
-          {
-             ELOGF("HWC", "mode changed (from %d to %d) due to surface changes",
-                   NULL, NULL,
-                   e_comp->hwc_mode, mode);
-
-             if (mode == E_HWC_MODE_FULL)
-               {
-                  // fb target is occupied by a client surface, means compositor disabled
-                  ecore_event_add(E_EVENT_COMPOSITOR_DISABLE, NULL, NULL, NULL);
-               }
-             else if (e_comp->hwc_mode == E_HWC_MODE_FULL)
-               {
-                  // fb target is occupied by a client surface, means compositor disabled
-                  ecore_event_add(E_EVENT_COMPOSITOR_ENABLE, NULL, NULL, NULL);
-               }
-
-             e_comp->hwc_mode = mode;
-          }
-     }
-
-   return ret;
-}
-
-static Eina_Bool
-_e_comp_hwc_prepare(void)
-{
-   Eina_List *l, *vl;
-   E_Zone *zone;
-   Eina_Bool ret = EINA_FALSE;
-
-   EINA_SAFETY_ON_FALSE_RETURN_VAL(e_comp->hwc, EINA_FALSE);
-
-   EINA_LIST_FOREACH(e_comp->zones, l, zone)
-     {
-        E_Client *ec;
-        E_Output *output;
-        int n_vis = 0, n_ec = 0, n_cur = 0, n_skip = 0;
-        Eina_List *hwc_ok_clist = NULL, *vis_clist = NULL;
-
-        if (!zone || !zone->output_id) continue;  // no hw layer
-
-        output = e_output_find(zone->output_id);
-        if (!output) continue;
-
-        vis_clist = e_comp_vis_ec_list_get(zone);
-        if (!vis_clist) continue;
-
-        EINA_LIST_FOREACH(vis_clist, vl, ec)
-          {
-             // check clients not able to use hwc
-             if (E_POLICY_QUICKPANEL_LAYER >= evas_object_layer_get(ec->frame))
-               {
-                  // check whether quickpanel is open than break
-                  if (e_qp_visible_get()) break;
-               }
-
-             // if ec->frame is not for client buffer (e.g. launchscreen)
-             if (e_comp_object_content_type_get(ec->frame) != E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE)
-                goto nextzone;
-
-             // if there is UI subfrace, it means need to composite
-             if (e_client_normal_client_has(ec))
-                goto nextzone;
-
-             // if ec has invalid buffer or scaled( transformed ) or forced composite(never_hwc)
-             if (!_hwc_available_get(ec))
-               {
-                  if (!n_ec) goto nextzone;
-                  break;
-               }
-
-             // listup as many as possible from the top most visible order
-             n_ec++;
-             if (!e_util_strcmp("wl_pointer-cursor", ec->icccm.window_role)) n_cur++;
-             hwc_ok_clist = eina_list_append(hwc_ok_clist, ec);
-          }
-
-        n_vis = eina_list_count(vis_clist);
-        if ((n_vis < 1) || (n_ec < 1))
-          goto nextzone;
-
-        _hwc_prepare_init(output);
-
-        if (n_cur >= 1)
-          n_skip = _hwc_prepare_cursor(output, n_cur, hwc_ok_clist);
-
-        if (n_skip > 0) ret = EINA_TRUE;
-
-        ret |= _hwc_prepare(output, n_vis, n_skip, hwc_ok_clist);
-
-        nextzone:
-        eina_list_free(hwc_ok_clist);
-        eina_list_free(vis_clist);
-     }
-
-   return ret;
-}
-
-static Eina_Bool
-_e_comp_hwc_usable(void)
-{
-   Eina_List *l;
-   E_Zone *zone;
-   E_Comp_Wl_Buffer *buffer = NULL;
-
-   if (!e_comp->hwc) return EINA_FALSE;
-
-   // check whether to use hwc and prepare the core assignment policy
-   if (!_e_comp_hwc_prepare()) return EINA_FALSE;
-
-   // extra policy can replace core policy
-   _e_comp_hook_call(E_COMP_HOOK_PREPARE_PLANE, NULL);
-
-   // check the hwc is avaliable.
-   EINA_LIST_FOREACH(e_comp->zones, l, zone)
-     {
-        E_Output *eout = NULL;
-        E_Plane *ep = NULL, *ep_fb = NULL;
-        const Eina_List *ep_l = NULL, *p_l;
-
-        if (!zone || !zone->output_id) continue;
-
-        eout = e_output_find(zone->output_id);
-        if (!eout) continue;
-        ep_l = e_output_planes_get(eout);
-
-        // It is not hwc_usable if cursor is shown when the hw cursor is not supported.
-        if ((eout->cursor_available.max_w == -1) ||
-            (eout->cursor_available.max_h == -1))
-          {
-             // hw cursor is not supported by libtdm, than let's composite
-             if (!e_pointer_is_hidden(e_comp->pointer)) return EINA_FALSE;
-          }
-
-        ep_fb = e_output_fb_target_get(eout);
-        if (!ep_fb) return EINA_FALSE;
-
-        if (ep_fb->prepare_ec)
-          {
-             // It is not hwc_usable if the geometry of the prepare_ec at the ep_fb is not proper.
-             int bw = 0, bh = 0;
-
-             // It is not hwc_usable if attached buffer is not valid.
-             buffer = e_pixmap_resource_get(ep_fb->prepare_ec->pixmap);
-             if (!buffer) return EINA_FALSE;
-
-             e_pixmap_size_get(ep_fb->prepare_ec->pixmap, &bw, &bh);
-
-             // if client and zone's geometry is not match with, or
-             // if plane with reserved_memory(esp. fb target) has assigned smaller buffer,
-             // won't support hwc properly, than let's composite
-             if (ep_fb->reserved_memory &&
-                 ((bw != zone->w) || (bh != zone->h) ||
-                 (ep_fb->prepare_ec->x != zone->x) || (ep_fb->prepare_ec->y != zone->y) ||
-                 (ep_fb->prepare_ec->w != zone->w) || (ep_fb->prepare_ec->h != zone->h)))
-               {
-
-                  DBG("Cannot use HWC if geometry is not 1 on 1 match with reserved_memory");
-                  return EINA_FALSE;
-               }
-          }
-        else
-          {
-             // It is not hwc_usable if the all prepare_ec in every plane are null
-             Eina_Bool all_null = EINA_TRUE;
-
-             EINA_LIST_FOREACH(ep_l, p_l, ep)
-               {
-                  if (ep == ep_fb) continue;
-                  if (ep->prepare_ec)
-                    {
-                       // if attached buffer is not valid, hwc is not usable
-                       buffer = e_pixmap_resource_get(ep->prepare_ec->pixmap);
-                       if (!buffer) return EINA_FALSE;
-
-                       // It is not hwc_usable if the zpos of the ep is over the one of ep_fb
-                       if (ep->zpos < ep_fb->zpos) return EINA_FALSE;
-
-                       all_null = EINA_FALSE;
-                       break;
-                    }
-               }
-             if (all_null) return EINA_FALSE;
-          }
-     }
-
-   return EINA_TRUE;
-}
-
-static void
-_e_comp_hwc_begin(void)
-{
-   Eina_List *l;
-   E_Zone *zone;
-   Eina_Bool mode_set = EINA_FALSE;
-
-   E_FREE_FUNC(e_comp->nocomp_delay_timer, ecore_timer_del);
-
-   if (!e_comp->hwc) return;
-   if (e_comp->nocomp_override > 0) return;
-
-   EINA_LIST_FOREACH(e_comp->zones, l, zone)
-     {
-        E_Output * eout;
-        if (!zone->output_id) continue;
-        eout = e_output_find(zone->output_id);
-        if(eout) mode_set |= _e_comp_hwc_apply(eout);
-     }
-
-   if (!mode_set) return;
-   if (!e_comp->hwc_mode) return;
-
-   if (e_comp->calc_fps) e_comp->frametimes[0] = 0;
-
-   ELOGF("HWC", " Begin ...", NULL, NULL);
-}
-
-static Eina_Bool
-_e_comp_hwc_cb_begin_timeout(void *data EINA_UNUSED)
-{
-   e_comp->nocomp_delay_timer = NULL;
-
-   if (e_comp->nocomp_override == 0)
-     {
-        e_comp_render_queue();
-     }
-   return EINA_FALSE;
-}
-
-E_API void
-e_comp_hwc_end(const char *location)
-{
-   Eina_Bool mode_set = EINA_FALSE;
-   E_Zone *zone;
-   Eina_List *l;
-   Eina_Bool fully_hwc = (e_comp->hwc_mode == E_HWC_MODE_FULL) ? EINA_TRUE : EINA_FALSE;
-
-   E_FREE_FUNC(e_comp->nocomp_delay_timer, ecore_timer_del);
-   _hwc_reserved_clean();
-
-   if (!e_comp->hwc) return;
-   if (!e_comp->hwc_mode) return;
-
-   EINA_LIST_FOREACH(e_comp->zones, l, zone)
-     {
-        E_Output * eout;
-        if (!zone->output_id) continue;
-        eout = e_output_find(zone->output_id);
-        if (eout) mode_set |= _hwc_cancel(eout);
-     }
-
-   if (!mode_set) return;
-
-   e_comp->hwc_mode = E_HWC_MODE_NO;
-
-   if (fully_hwc)
-     ecore_event_add(E_EVENT_COMPOSITOR_ENABLE, NULL, NULL, NULL);
-
-   ELOGF("HWC", " End...  at %s.", NULL, NULL, location);
-}
-
-EINTERN void
-e_comp_hwc_multi_plane_set(Eina_Bool set)
-{
-   if (!conf->hwc_use_multi_plane) return;
-
-   if (e_comp->hwc_use_multi_plane == set) return;
-
-   e_comp_hwc_end(__FUNCTION__);
-   e_comp->hwc_use_multi_plane = set;
-
-   ELOGF("HWC", "e_comp_hwc_multi_plane_set : %d", NULL, NULL, set);
-}
-#endif  // end of ENABLE_HWC_MULTI
-
 static Eina_Bool
 _e_comp_cb_update(void)
 {
@@ -1007,8 +257,6 @@ _e_comp_cb_update(void)
         e_comp_object_dirty(ec->frame);
      }
 
-   if (e_comp->hwc_mode == E_HWC_MODE_FULL) goto setup_hwcompose;
-
 #ifndef ENABLE_HWC_MULTI
    if (conf->fps_show || e_comp->calc_fps)
      {
@@ -1029,52 +277,6 @@ _e_comp_cb_update(void)
    if (e_comp->updates && (!e_comp->update_job))
      ecore_animator_thaw(e_comp->render_animator);
 
-setup_hwcompose:
-#ifdef ENABLE_HWC_MULTI
-   // query if HWC can be used
-   if (!e_comp->hwc ||
-       e_comp->hwc_deactive)
-     {
-        goto end;
-     }
-
-   if(_e_comp_hwc_usable())
-     {
-        if (e_comp->hwc_mode)
-          {
-             if (_e_comp_hwc_changed())
-               {
-                  if (e_comp->hwc_mode == E_HWC_MODE_NO)
-                    ELOGF("HWC", " End...  due to surface changes", NULL, NULL);
-                  else
-                    ELOGF("HWC", " hwc surface changed", NULL, NULL);
-               }
-          }
-        else
-          {
-             // switch mode
-             if (conf->nocomp_use_timer)
-               {
-                  if (!e_comp->nocomp_delay_timer)
-                    {
-                       e_comp->nocomp_delay_timer = ecore_timer_add(conf->nocomp_begin_timeout,
-                                                                     _e_comp_hwc_cb_begin_timeout,
-                                                                     NULL);
-                    }
-               }
-             else
-               {
-                  _e_comp_hwc_begin();
-               }
-          }
-     }
-   else
-     {
-        e_comp_hwc_end(__FUNCTION__);
-     }
-
-end:
-#endif  // end of ENABLE_HWC_MULTI
    TRACE_DS_END();
 
    return ECORE_CALLBACK_RENEW;
@@ -1235,7 +437,18 @@ e_comp_init(void)
 
    e_comp_new();
 
-   if (conf->hwc_ignore_primary) e_comp->hwc_ignore_primary = EINA_TRUE;
+   if (conf->hwc)
+     {
+        e_comp->hwc = EINA_TRUE; // activate hwc policy on the primary output
+        if (conf->hwc_reuse_cursor_buffer) e_comp->hwc_reuse_cursor_buffer = EINA_TRUE;
+        if (conf->hwc_sync_mode_change) e_comp->hwc_sync_mode_change = EINA_TRUE;
+        if (conf->hwc_use_detach) e_comp->hwc_use_detach = EINA_TRUE;
+        if (conf->hwc_deactive) e_comp_hwc_deactive_set(EINA_TRUE);
+        if (conf->hwc_use_multi_plane) e_comp_hwc_multi_plane_set(EINA_TRUE);
+        if (conf->hwc_ignore_primary) e_comp->hwc_ignore_primary = EINA_TRUE;
+     }
+
+   if (conf->use_native_type_buffer) e_comp->use_native_type_buffer = EINA_TRUE;
 
    e_main_ts_begin("\tE_Comp_Screen Init");
    if (!e_comp_screen_init())
@@ -1252,16 +465,6 @@ e_comp_init(void)
 
    e_comp_canvas_fake_layers_init();
 
-   if (conf->hwc) e_comp->hwc = EINA_TRUE; // activate hwc policy
-   if (conf->hwc_deactive) e_comp->hwc_deactive = EINA_TRUE; // deactive hwc policy
-   if (conf->hwc_reuse_cursor_buffer) e_comp->hwc_reuse_cursor_buffer = EINA_TRUE;
-   if (conf->hwc_sync_mode_change) e_comp->hwc_sync_mode_change = EINA_TRUE;
-   if (conf->hwc_use_detach) e_comp->hwc_use_detach = EINA_TRUE;
-#ifdef ENABLE_HWC_MULTI
-   if (conf->hwc_use_multi_plane) e_comp->hwc_use_multi_plane = EINA_TRUE;
-#endif
-   if (conf->use_native_type_buffer) e_comp->use_native_type_buffer = EINA_TRUE;
-
    E_LIST_HANDLER_APPEND(handlers, E_EVENT_SCREENSAVER_ON,  _e_comp_screensaver_on,  NULL);
    E_LIST_HANDLER_APPEND(handlers, E_EVENT_SCREENSAVER_OFF, _e_comp_screensaver_off, NULL);
    E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_KEY_DOWN,    _e_comp_key_down,        NULL);
@@ -1720,25 +923,45 @@ e_comp_hook_del(E_Comp_Hook *ch)
 EINTERN Eina_Bool
 e_comp_is_on_overlay(E_Client *ec)
 {
+   Eina_List *l, *ll;
+   E_Output *eout;
+   E_Plane *ep;
+
    if (!ec) return EINA_FALSE;
-   if (e_comp->hwc_mode)
+   if (!ec->zone || !ec->zone->output_id) return EINA_FALSE;
+
+   eout = e_output_find(ec->zone->output_id);
+   if (!eout) return EINA_FALSE;
+   if (!e_output_hwc_mode_get(eout->output_hwc)) return EINA_FALSE;
+
+   EINA_LIST_FOREACH_SAFE(eout->planes, l, ll, ep)
      {
-        Eina_List *l, *ll;
-        E_Output * eout;
-        E_Plane *ep;
-
-        if (!ec->zone || !ec->zone->output_id) return EINA_FALSE;
-        eout = e_output_find(ec->zone->output_id);
-        if (!eout) return EINA_FALSE;
-        EINA_LIST_FOREACH_SAFE(eout->planes, l, ll, ep)
-          {
-             E_Client *overlay_ec = ep->ec;
-             if (overlay_ec == ec) return EINA_TRUE;
-          }
+        E_Client *overlay_ec = ep->ec;
+        if (overlay_ec == ec) return EINA_TRUE;
      }
+
    return EINA_FALSE;
 }
 
+EINTERN E_Zone *
+e_comp_zone_find(const char *output_id)
+{
+   Eina_List *l = NULL;
+   E_Zone *zone = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output_id, NULL);
+
+   EINA_LIST_FOREACH(e_comp->zones, l, zone)
+     {
+        if (!zone) continue;
+        if (!strcmp(zone->output_id, output_id)) return zone;
+     }
+
+   return NULL;
+}
+
+
 E_API Eina_List *
 e_comp_vis_ec_list_get(E_Zone *zone)
 {
@@ -2013,3 +1236,79 @@ e_comp_socket_init(const char *name)
 
    return EINA_TRUE;
 }
+
+/* set the deactive value to the only primary output */
+EINTERN void
+e_comp_hwc_deactive_set(Eina_Bool set)
+{
+   E_Output *output = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN(e_comp);
+   EINA_SAFETY_ON_NULL_RETURN(e_comp->e_comp_screen);
+
+   output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
+   EINA_SAFETY_ON_NULL_RETURN(output);
+
+   e_output_hwc_deactive_set(output->output_hwc, EINA_TRUE);
+}
+
+/* get the deactive value to the only primary output */
+EINTERN Eina_Bool
+e_comp_hwc_deactive_get(void)
+{
+   E_Output *output = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp->e_comp_screen, EINA_FALSE);
+
+   output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
+
+   return e_output_hwc_deactive_get(output->output_hwc);
+}
+
+/* set the multi_plane value to the only primary output */
+EINTERN void
+e_comp_hwc_multi_plane_set(Eina_Bool set)
+{
+   E_Output *output = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN(e_comp);
+   EINA_SAFETY_ON_NULL_RETURN(e_comp->e_comp_screen);
+
+   output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
+   EINA_SAFETY_ON_NULL_RETURN(output);
+
+   e_output_hwc_multi_plane_set(output->output_hwc, EINA_TRUE);
+}
+
+/* get the multi_plane value to the only primary output */
+EINTERN Eina_Bool
+e_comp_hwc_multi_plane_get(void)
+{
+   E_Output *output = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp->e_comp_screen, EINA_FALSE);
+
+   output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
+
+   return e_output_hwc_multi_plane_get(output->output_hwc);
+}
+
+/* end the hwc policy at the primary output */
+E_API void
+e_comp_hwc_end(const char *location)
+{
+   E_Output *output = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN(e_comp);
+   EINA_SAFETY_ON_NULL_RETURN(e_comp->e_comp_screen);
+
+   output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
+   EINA_SAFETY_ON_NULL_RETURN(output);
+
+   e_output_hwc_end(output->output_hwc, location);
+}
+
index d42e274970199ad8c3759afdce7ab270308d3bc7..1a3a733f6528de44432a3f6a85b8c86a0910740d 100644 (file)
@@ -139,13 +139,10 @@ struct _E_Comp
    Ecore_Timer    *nocomp_override_timer;
    int             nocomp_override; //number of times hwc override has been requested
    Eina_Bool       nocomp : 1; // TODO: remove it from E_Comp!!
-   int             hwc_mode;
    Eina_Bool       hwc : 1;
-   Eina_Bool       hwc_deactive : 1; // deactive hwc policy
    Eina_Bool       hwc_reuse_cursor_buffer;
    Eina_Bool       hwc_sync_mode_change;
    Eina_Bool       hwc_use_detach;
-   Eina_Bool       hwc_use_multi_plane;
    Eina_Bool       hwc_ignore_primary;
    Eina_Bool       use_native_type_buffer : 1; // use native buffer type
 
@@ -239,15 +236,19 @@ E_API void e_comp_post_update_purge(E_Client *ec);
 
 E_API E_Comp_Hook *e_comp_hook_add(E_Comp_Hook_Point hookpoint, E_Comp_Hook_Cb func, const void *data);
 E_API void e_comp_hook_del(E_Comp_Hook *ph);
+EINTERN void e_comp_hook_call(E_Comp_Hook_Point hookpoint, void *data EINA_UNUSED);
+
 EINTERN Eina_Bool e_comp_is_on_overlay(E_Client *ec);
+EINTERN E_Zone *e_comp_zone_find(const char *output_id);
 E_API Eina_List *e_comp_vis_ec_list_get(E_Zone *zone); // visible ec list sorted by z order
 
-#ifdef ENABLE_HWC_MULTI
-E_API void e_comp_hwc_end(const char *location);
-EINTERN void e_comp_hwc_multi_plane_set(Eina_Bool set);
-#endif
-
 E_API Eina_Bool e_comp_socket_init(const char *name);
 
+EINTERN void      e_comp_hwc_deactive_set(Eina_Bool set);
+EINTERN Eina_Bool e_comp_hwc_deactive_get(void);
+EINTERN void      e_comp_hwc_multi_plane_set(Eina_Bool set);
+EINTERN Eina_Bool e_comp_hwc_multi_plane_get(void);
+E_API   void      e_comp_hwc_end(const char *location);
+
 #endif
 #endif
index 427b343254da1d40c343c0e511df4647e2f8b47b..0c7724e6165aa13fffc27a5678d134fa603e7975 100644 (file)
@@ -250,11 +250,11 @@ _e_comp_screen_commit_idle_cb(void *data EINA_UNUSED)
         if (!e_output_commit(output))
              ERR("fail to commit e_comp_screen->outputs.");
 
+        e_output_hwc_apply(output->output_hwc);
+
         if (!e_output_render(output))
              ERR("fail to render e_comp_screen->outputs.");
-
      }
-
 end:
    return ECORE_CALLBACK_RENEW;
 }
@@ -1160,7 +1160,7 @@ e_comp_screen_setup(E_Comp_Screen *e_comp_screen)
 
         if (!e_output_setup(output))
           {
-             ERR("fail to e_ouptut_hwc_setup.");
+             ERR("fail to e_output_setup.");
              continue;
           }
      }
index f62cc8fe0f13489cea76f9a9eeab0ab4eeaaf347..57cdecb6be8fd4df5e27d98d111b523acacc4728 100644 (file)
@@ -1310,7 +1310,8 @@ _e_desk_util_comp_hwc_disable_set(Eina_Bool disable)
 {
    if (disable)
      e_comp_hwc_end("in runtime by e_desk");
-   e_comp->hwc_deactive = disable;
+
+   e_comp_hwc_deactive_set(disable);
 }
 
 static void
index 556ba8217586110fa01c0f453270db9f50361366..b2c9e549ee58a5ce8df878bcf8161e8119091fd8 100644 (file)
@@ -43,6 +43,7 @@
 #include "e_log.h"
 #include "e_dbusmenu.h"
 #include "e_comp_screen.h"
+#include "e_output_hwc.h"
 #include "e_comp.h"
 #include "e_comp_cfdata.h"
 #include "e_comp_canvas.h"
index e4d2e74c3e278d777b9ef7fff52cdea60d596809..4926069a0dd7b759bb61faf16ecbae62a25a0fc6 100644 (file)
@@ -183,7 +183,7 @@ _e_info_server_ec_hwc_info_get(E_Client *ec, int *hwc, int *pl_zpos)
    *hwc = -1;
    *pl_zpos = -999;
 
-   if ((!e_comp->hwc) || (e_comp->hwc_deactive))
+   if ((!e_comp->hwc) || e_comp_hwc_deactive_get())
      return;
 
    *hwc = 0;
@@ -3970,13 +3970,11 @@ e_info_server_cb_hwc(const Eldbus_Service_Interface *iface EINA_UNUSED, const El
      }
 
    if (onoff == 1)
-     {
-        e_comp->hwc_deactive = EINA_FALSE;
-     }
+     e_comp_hwc_deactive_set(EINA_FALSE);
    else if (onoff == 0)
      {
         e_comp_hwc_end("in runtime by e_info..");
-        e_comp->hwc_deactive = EINA_TRUE;
+        e_comp_hwc_deactive_set(EINA_TRUE);
      }
 
    return reply;
index 9f25eda9def1321f630d90f654722c2906a95de9..61306256e073dbfb9f3fcd33f144a70712bd9c9d 100644 (file)
@@ -1729,6 +1729,8 @@ e_output_del(E_Output *output)
 
    if (!output) return;
 
+   if (output->output_hwc) e_output_hwc_del(output->output_hwc);
+
    e_plane_shutdown();
 
    if (output->id) free(output->id);
@@ -2029,11 +2031,21 @@ e_output_mode_apply(E_Output *output, E_Output_Mode *mode)
 EINTERN Eina_Bool
 e_output_setup(E_Output *output)
 {
+   E_Output_Hwc *output_hwc = NULL;
    Eina_List *l, *ll;
    E_Plane *plane = NULL;
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
 
+   /* available only the primary output now. */
+   if (e_comp->hwc)
+     {
+        output_hwc = e_output_hwc_new(output);
+        EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, EINA_FALSE);
+        output->output_hwc = output_hwc;
+     }
+
+   /* ecore evas engine setup */
    EINA_LIST_FOREACH_SAFE(output->planes, l, ll, plane)
      {
         if (plane->is_fb)
@@ -2303,6 +2315,14 @@ e_output_commit(E_Output *output)
    return EINA_TRUE;
 }
 
+EINTERN const char *
+e_output_output_id_get(E_Output *output)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
+
+   return output->id;
+}
+
 E_API E_Output *
 e_output_find(const char *id)
 {
@@ -2551,7 +2571,7 @@ e_output_zoom_set(E_Output *output, double zoomx, double zoomy, int cx, int cy)
    EINA_SAFETY_ON_NULL_RETURN_VAL(ep, EINA_FALSE);
 
 #ifdef ENABLE_HWC_MULTI
-   e_comp_hwc_multi_plane_set(EINA_FALSE);
+   e_output_hwc_multi_plane_set(output->output_hwc, EINA_FALSE);
 #endif
 
    output->zoom_conf.zoomx = zoomx;
@@ -2570,7 +2590,7 @@ e_output_zoom_set(E_Output *output, double zoomx, double zoomy, int cx, int cy)
      {
         ERR("e_plane_zoom_set failed.");
 #ifdef ENABLE_HWC_MULTI
-        e_comp_hwc_multi_plane_set(EINA_TRUE);
+        e_output_hwc_multi_plane_set(output->output_hwc, EINA_TRUE);
 #endif
         return EINA_FALSE;
      }
@@ -2627,7 +2647,7 @@ e_output_zoom_unset(E_Output *output)
    output->zoom_set = EINA_FALSE;
 
 #ifdef ENABLE_HWC_MULTI
-   e_comp_hwc_multi_plane_set(EINA_TRUE);
+   e_output_hwc_multi_plane_set(output->output_hwc, EINA_TRUE);
 #endif
 
    /* update the ecore_evas */
index 7fdbc0258411f553f6ee116eed05f5744b4d95a8..169f1cccc6d2299a616895c7b373046d82f4e0f5 100644 (file)
@@ -106,6 +106,9 @@ struct _E_Output
       Ecore_Timer      *timer;
       Eina_Bool         wait_vblank;
    } stream_capture;
+
+   /* output hwc */
+   E_Output_Hwc *output_hwc;
 };
 
 enum _E_Output_Hook_Point
@@ -165,6 +168,7 @@ EINTERN Eina_Bool         e_output_stream_capture_queue(E_Output *output, tbm_su
 EINTERN Eina_Bool         e_output_stream_capture_dequeue(E_Output *output, tbm_surface_h surface);
 EINTERN Eina_Bool         e_output_stream_capture_start(E_Output *output);
 EINTERN void              e_output_stream_capture_stop(E_Output *output);
+EINTERN const char      * e_output_output_id_get(E_Output *output);
 E_API E_Output          * e_output_find(const char *id);
 E_API E_Output          * e_output_find_by_index(int index);
 E_API const Eina_List   * e_output_planes_get(E_Output *output);
@@ -178,6 +182,5 @@ E_API void                e_output_hook_del(E_Output_Hook *ch);
 E_API E_Output_Intercept_Hook * e_output_intercept_hook_add(E_Output_Intercept_Hook_Point hookpoint, E_Output_Intercept_Hook_Cb func, const void *data);
 E_API void                e_output_intercept_hook_del(E_Output_Intercept_Hook *ch);
 
-
 #endif
 #endif
diff --git a/src/bin/e_output_hwc.c b/src/bin/e_output_hwc.c
new file mode 100644 (file)
index 0000000..1569d50
--- /dev/null
@@ -0,0 +1,763 @@
+#include "e.h"
+
+static int
+_hwc_set(E_Output *eout)
+{
+   const Eina_List *ep_l = NULL, *l;
+   E_Plane *ep = NULL;
+   E_Output_Hwc_Mode mode = E_OUTPUT_HWC_MODE_NO;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(eout, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(eout->planes, EINA_FALSE);
+
+   ep_l = e_output_planes_get(eout);
+   EINA_LIST_REVERSE_FOREACH(ep_l, l , ep)
+     {
+        Eina_Bool set = EINA_FALSE;
+
+        if (e_plane_is_fb_target(ep))
+          {
+             if (ep->prepare_ec)
+               {
+                  set = e_plane_ec_set(ep, ep->prepare_ec);
+                  if (set)
+                    {
+                       ELOGF("HWC", "is set on fb_target( %d)", ep->prepare_ec->pixmap, ep->prepare_ec, ep->zpos);
+                       mode = E_OUTPUT_HWC_MODE_FULL;
+
+                       // fb target is occupied by a client surface, means compositor disabled
+                       ecore_event_add(E_EVENT_COMPOSITOR_DISABLE, NULL, NULL, NULL);
+                    }
+                  break;
+               }
+          }
+        else if (ep->prepare_ec)
+          {
+             set = e_plane_ec_set(ep, ep->prepare_ec);
+             if (set)
+               {
+                  ELOGF("HWC", "is set on %d", ep->prepare_ec->pixmap, ep->prepare_ec, ep->zpos);
+                  mode |= E_OUTPUT_HWC_MODE_HYBRID;
+               }
+             else
+               break;
+          }
+     }
+
+   return mode;
+}
+
+static Eina_Bool
+_hwc_available_get(E_Client *ec)
+{
+   E_Comp_Wl_Client_Data *cdata = (E_Comp_Wl_Client_Data*)ec->comp_data;
+   E_Output *eout;
+   int minw = 0, minh = 0;
+
+   if ((!cdata) ||
+       (!cdata->buffer_ref.buffer) ||
+       (cdata->width_from_buffer != cdata->width_from_viewport) ||
+       (cdata->height_from_buffer != cdata->height_from_viewport) ||
+       cdata->never_hwc)
+     {
+        return EINA_FALSE;
+     }
+
+   if (e_client_transform_core_enable_get(ec)) return EINA_FALSE;
+
+   switch (cdata->buffer_ref.buffer->type)
+     {
+      case E_COMP_WL_BUFFER_TYPE_NATIVE:
+         break;
+      case E_COMP_WL_BUFFER_TYPE_TBM:
+         if (cdata->buffer_ref.buffer->resource)
+           break;
+      case E_COMP_WL_BUFFER_TYPE_SHM:
+         if (!e_util_strcmp("wl_pointer-cursor", ec->icccm.window_role))
+           break;
+
+      default:
+         return EINA_FALSE;
+     }
+
+   if (e_comp_wl_tbm_buffer_sync_timeline_used(cdata->buffer_ref.buffer))
+     return EINA_FALSE;
+
+   eout = e_output_find(ec->zone->output_id);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(eout, EINA_FALSE);
+
+   tdm_output_get_available_size(eout->toutput, &minw, &minh, NULL, NULL, NULL);
+
+   if ((minw > 0) && (minw > cdata->buffer_ref.buffer->w))
+     return EINA_FALSE;
+   if ((minh > 0) && (minh > cdata->buffer_ref.buffer->h))
+     return EINA_FALSE;
+
+   /* If a client doesn't watch the ignore_output_transform events, we can't show
+    * a client buffer to HW overlay directly when the buffer transform is not same
+    * with output transform. If a client watch the ignore_output_transform events,
+    * we can control client's buffer transform. In this case, we don't need to
+    * check client's buffer transform here.
+    */
+   if (!e_comp_screen_rotation_ignore_output_transform_watch(ec))
+     {
+        int transform = e_comp_wl_output_buffer_transform_get(ec);
+
+        if ((eout->config.rotation / 90) != transform)
+          return EINA_FALSE;
+     }
+
+   return EINA_TRUE;
+}
+
+static void
+_hwc_prepare_init(E_Output_Hwc *output_hwc)
+{
+   const Eina_List *ep_l = NULL, *l ;
+   E_Plane *ep = NULL;
+   E_Output *eout = output_hwc->output;
+
+   EINA_SAFETY_ON_NULL_RETURN(output_hwc);
+
+   ep_l = e_output_planes_get(eout);
+   EINA_LIST_FOREACH(ep_l, l, ep)
+     {
+        if (!output_hwc->hwc_use_multi_plane &&
+            !e_plane_is_cursor(ep) &&
+            !e_plane_is_fb_target(ep))
+          continue;
+
+        e_plane_ec_prepare_set(ep, NULL);
+     }
+}
+
+static int
+_hwc_prepare_cursor(E_Output *eout, int n_cur, Eina_List *hwc_clist)
+{
+   // policy for cursor layer
+   const Eina_List *ep_l = NULL, *l ;
+   Eina_List *cur_ly = NULL;
+   E_Plane *ep = NULL;
+   int n_skip = 0;
+   int n_curly = 0;
+   int nouse = 0;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_clist, EINA_FALSE);
+
+   // list up cursor only layers
+   ep_l = e_output_planes_get(eout);
+   EINA_LIST_FOREACH(ep_l, l, ep)
+     {
+        if (e_plane_is_cursor(ep))
+          {
+             cur_ly = eina_list_append(cur_ly, ep);
+             continue;
+          }
+     }
+
+   if (!cur_ly) return 0;
+   n_curly = eina_list_count(cur_ly);
+
+   if (n_cur > 0 && n_curly > 0)
+     {
+        if (n_cur >= n_curly) nouse = 0;
+        else nouse = n_curly - n_cur;
+
+        //assign cursor on cursor only layers
+        EINA_LIST_REVERSE_FOREACH(cur_ly, l, ep)
+          {
+             E_Client *ec = NULL;
+             if (nouse > 0)
+               {
+                  nouse--;
+                  continue;
+               }
+             if (hwc_clist) ec = eina_list_data_get(hwc_clist);
+             if (ec && e_plane_ec_prepare_set(ep, ec))
+               {
+                  n_skip += 1;
+                  hwc_clist = eina_list_next(hwc_clist);
+               }
+          }
+     }
+
+   eina_list_free(cur_ly);
+
+   return n_skip;
+}
+
+static Eina_Bool
+_hwc_prepare(E_Output_Hwc *output_hwc, int n_vis, int n_skip, Eina_List *hwc_clist)
+{
+   const Eina_List *ep_l = NULL, *l ;
+   Eina_List *hwc_ly = NULL;
+   E_Plane *ep = NULL, *ep_fb = NULL;
+   int n_ly = 0, n_ec = 0;
+   E_Client *ec = NULL;
+   Eina_Bool ret = EINA_FALSE;
+   int nouse = 0;
+   E_Output *eout = output_hwc->output;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_clist, EINA_FALSE);
+
+   n_ec = eina_list_count(hwc_clist);
+   if (n_skip > 0)
+     {
+        int i;
+        for (i = 0; i < n_skip; i++)
+          hwc_clist = eina_list_next(hwc_clist);
+
+        n_ec -= n_skip;
+        n_vis -= n_skip;
+     }
+
+   if (n_ec <= 0) return EINA_FALSE;
+
+   // list up available_hw layers E_Client can be set
+   // if e_comp->hwc_use_multi_plane FALSE, than use only fb target plane
+   ep_l = e_output_planes_get(eout);
+   EINA_LIST_FOREACH(ep_l, l, ep)
+     {
+        if (!ep_fb)
+          {
+             if (e_plane_is_fb_target(ep))
+               {
+                  ep_fb = ep;
+                  hwc_ly = eina_list_append(hwc_ly, ep);
+               }
+             continue;
+          }
+        if (!output_hwc->hwc_use_multi_plane) continue;
+        if (e_plane_is_cursor(ep)) continue;
+        if (ep->zpos > ep_fb->zpos)
+          hwc_ly = eina_list_append(hwc_ly, ep);
+     }
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_ly, EINA_FALSE);
+
+   // finally, assign client on available_hw layers
+   n_ly = eina_list_count(hwc_ly);
+   if ((n_ec == n_vis) &&
+       (n_ec <= n_ly)) // fully hwc
+     {
+        nouse = n_ly - n_ec;
+     }
+   else if ((n_ly < n_vis) || // e_comp->evas on fb target plane
+            (n_ec < n_vis))
+     {
+        if (n_ec <= n_ly) nouse = n_ly - n_ec - 1;
+        else nouse = 0;
+     }
+
+   EINA_LIST_REVERSE_FOREACH(hwc_ly, l, ep)
+     {
+        ec = NULL;
+        if (nouse > 0)
+          {
+             nouse--;
+             continue;
+          }
+        if (hwc_clist) ec = eina_list_data_get(hwc_clist);
+        if (ec && e_plane_ec_prepare_set(ep, ec))
+          {
+             ret = EINA_TRUE;
+
+             hwc_clist = eina_list_next(hwc_clist);
+             n_ec--; n_vis--;
+          }
+        if (e_plane_is_fb_target(ep))
+          {
+             if (n_ec > 0 || n_vis > 0) e_plane_ec_prepare_set(ep, NULL);
+             break;
+          }
+     }
+
+   eina_list_free(hwc_ly);
+
+   return ret;
+}
+
+static Eina_Bool
+_hwc_cancel(E_Output_Hwc *output_hwc)
+{
+   Eina_List *l ;
+   E_Plane *ep;
+   Eina_Bool ret = EINA_TRUE;
+   E_Output *eout = output_hwc->output;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(eout, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(eout->planes, EINA_FALSE);
+
+   EINA_LIST_FOREACH(eout->planes, l, ep)
+     {
+        if (!output_hwc->hwc_use_multi_plane &&
+            !e_plane_is_cursor(ep) &&
+            !e_plane_is_fb_target(ep))
+          {
+             if (ep->ec) ret = EINA_FALSE; // core cannot end HWC
+             continue;
+          }
+
+        e_plane_ec_prepare_set(ep, NULL);
+        e_plane_ec_set(ep, NULL);
+     }
+
+   return ret;
+}
+
+static Eina_Bool
+_hwc_reserved_clean(E_Output_Hwc *output_hwc)
+{
+   Eina_List *l;
+   E_Plane *ep;
+   E_Output *eout = output_hwc->output;
+
+   EINA_LIST_FOREACH(eout->planes, l, ep)
+     {
+        if (!output_hwc->hwc_use_multi_plane &&
+            !e_plane_is_cursor(ep) &&
+            !e_plane_is_fb_target(ep))
+          continue;
+
+        if (e_plane_is_reserved(ep))
+            e_plane_reserved_set(ep, 0);
+     }
+
+   return EINA_TRUE;
+}
+
+static void
+_hwc_plane_unset(E_Plane *ep)
+{
+   if (e_plane_is_reserved(ep))
+     e_plane_reserved_set(ep, 0);
+
+   e_plane_ec_prepare_set(ep, NULL);
+   e_plane_ec_set(ep, NULL);
+
+   ELOGF("HWC", "unset plane %d to NULL", NULL, NULL, ep->zpos);
+}
+
+static Eina_Bool
+_hwc_plane_change_ec(E_Plane *ep, E_Client *old_ec, E_Client *new_ec)
+{
+   Eina_Bool ret = EINA_FALSE;
+
+   if (!new_ec)
+     {
+        if (e_plane_is_reserved(ep))
+          e_plane_reserved_set(ep, 0);
+     }
+
+   e_plane_ec_prepare_set(ep, NULL);
+
+   if (e_plane_ec_set(ep, new_ec))
+     {
+        if (new_ec)
+          {
+             ELOGF("HWC", "new_ec(%s) is set on %d",
+                   new_ec->pixmap, new_ec,
+                   e_client_util_name_get(new_ec) ? new_ec->icccm.name : "no name", ep->zpos);
+          }
+        else
+          {
+             ELOGF("HWC", "NULL is set on %d", NULL, NULL, ep->zpos);
+          }
+        ret = EINA_TRUE;
+     }
+   else
+     {
+        ELOGF("HWC", "failed to set new_ec(%s) on %d",
+              NULL, new_ec,
+              new_ec ? (new_ec->icccm.name ? new_ec->icccm.name : "no name") : "NULL",
+              ep->zpos);
+     }
+
+   return ret;
+}
+
+static Eina_Bool
+_e_output_hwc_apply(E_Output_Hwc *output_hwc)
+{
+   const Eina_List *ep_l = NULL, *l;
+   E_Plane *ep = NULL, *ep_fb = NULL;
+   int mode = 0;
+   E_Output *eout = output_hwc->output;
+
+   ep_l = e_output_planes_get(eout);
+   EINA_LIST_FOREACH(ep_l, l, ep)
+     {
+        if (!ep_fb)
+          {
+             if (e_plane_is_fb_target(ep))
+               {
+                  ep_fb = ep;
+                  if (ep->prepare_ec != NULL) goto hwcompose;
+               }
+             continue;
+          }
+        if (ep->zpos > ep_fb->zpos)
+          if (ep->prepare_ec != NULL) goto hwcompose;
+     }
+
+   goto compose;
+
+hwcompose:
+   mode = _hwc_set(eout);
+   if (mode == E_OUTPUT_HWC_MODE_NO) ELOGF("HWC", "it is failed to assign surface on plane", NULL, NULL);
+
+compose:
+   if (mode != E_OUTPUT_HWC_MODE_NO) output_hwc->hwc_mode = mode;
+
+   return !!mode;
+}
+
+static Eina_Bool
+_e_output_hwc_changed(E_Output_Hwc *output_hwc)
+{
+   Eina_Bool ret = EINA_FALSE;
+   E_Plane *ep = NULL;
+   const Eina_List *ep_l = NULL, *p_l;
+   Eina_Bool assign_success = EINA_TRUE;
+   int mode = E_OUTPUT_HWC_MODE_NO;
+   E_Output *eout = output_hwc->output;
+
+   ep_l = e_output_planes_get(eout);
+   EINA_LIST_REVERSE_FOREACH(ep_l, p_l, ep)
+     {
+        if (!assign_success)
+          {
+             //unset planes from 'assign_success' became EINA_FALSE to the fb target
+             _hwc_plane_unset(ep);
+             continue;
+          }
+
+        if (ep->ec != ep->prepare_ec)
+          {
+             assign_success = _hwc_plane_change_ec(ep, ep->ec, ep->prepare_ec);
+             ret = EINA_TRUE;
+          }
+        else if (!ep->prepare_ec)
+          {
+             if (e_plane_is_reserved(ep))
+               {
+                  e_plane_reserved_set(ep, 0);
+                  ELOGF("HWC", "unset reserved mem on %d", NULL, NULL, ep->zpos);
+               }
+          }
+
+        if (ep->ec) mode = E_OUTPUT_HWC_MODE_HYBRID;
+
+        if (e_plane_is_fb_target(ep))
+          {
+             if (ep->ec) mode = E_OUTPUT_HWC_MODE_FULL;
+             break;
+          }
+     }
+
+   if (output_hwc->hwc_mode != mode)
+     {
+        ELOGF("HWC", "mode changed (from %d to %d) due to surface changes",
+              NULL, NULL,
+              output_hwc->hwc_mode, mode);
+
+        if (mode == E_OUTPUT_HWC_MODE_FULL)
+          {
+             // fb target is occupied by a client surface, means compositor disabled
+             ecore_event_add(E_EVENT_COMPOSITOR_DISABLE, NULL, NULL, NULL);
+          }
+        else if (output_hwc->hwc_mode == E_OUTPUT_HWC_MODE_FULL)
+          {
+             // fb target is occupied by a client surface, means compositor disabled
+             ecore_event_add(E_EVENT_COMPOSITOR_ENABLE, NULL, NULL, NULL);
+          }
+
+        output_hwc->hwc_mode = mode;
+     }
+
+   return ret;
+}
+
+static Eina_Bool
+_e_output_hwc_prepare(E_Output_Hwc *output_hwc, E_Zone *zone)
+{
+   Eina_List *vl;
+   Eina_Bool ret = EINA_FALSE;
+   E_Client *ec;
+   int n_vis = 0, n_ec = 0, n_cur = 0, n_skip = 0;
+   Eina_List *hwc_ok_clist = NULL, *vis_clist = NULL;
+   E_Output *output = output_hwc->output;
+
+   vis_clist = e_comp_vis_ec_list_get(zone);
+   if (!vis_clist) return EINA_FALSE;
+
+   EINA_LIST_FOREACH(vis_clist, vl, ec)
+     {
+        // check clients not able to use hwc
+        // if ec->frame is not for client buffer (e.g. launchscreen)
+        if (e_comp_object_content_type_get(ec->frame) != E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE)
+           goto done;
+
+        // if there is UI subfrace, it means need to composite
+        if (e_client_normal_client_has(ec))
+           goto done;
+
+        // if ec has invalid buffer or scaled( transformed ) or forced composite(never_hwc)
+        if (!_hwc_available_get(ec))
+          {
+             if (!n_ec) goto done;
+             break;
+          }
+
+        // listup as many as possible from the top most visible order
+        n_ec++;
+        if (!e_util_strcmp("wl_pointer-cursor", ec->icccm.window_role)) n_cur++;
+        hwc_ok_clist = eina_list_append(hwc_ok_clist, ec);
+     }
+
+   n_vis = eina_list_count(vis_clist);
+   if ((n_vis < 1) || (n_ec < 1))
+     goto done;
+
+   _hwc_prepare_init(output_hwc);
+
+   if (n_cur >= 1)
+     n_skip = _hwc_prepare_cursor(output, n_cur, hwc_ok_clist);
+
+   if (n_skip > 0) ret = EINA_TRUE;
+
+   ret |= _hwc_prepare(output_hwc, n_vis, n_skip, hwc_ok_clist);
+
+done:
+   eina_list_free(hwc_ok_clist);
+   eina_list_free(vis_clist);
+
+   return ret;
+}
+
+static Eina_Bool
+_e_output_hwc_usable(E_Output_Hwc *output_hwc)
+{
+   E_Output *eout = output_hwc->output;
+   E_Comp_Wl_Buffer *buffer = NULL;
+   E_Zone *zone = NULL;
+
+   zone = e_comp_zone_find(e_output_output_id_get(eout));
+   EINA_SAFETY_ON_NULL_RETURN_VAL(zone, EINA_FALSE);
+
+   // check whether to use hwc and prepare the core assignment policy
+   if (!_e_output_hwc_prepare(output_hwc, zone)) return EINA_FALSE;
+
+   // extra policy can replace core policy
+   e_comp_hook_call(E_COMP_HOOK_PREPARE_PLANE, NULL);
+
+   // check the hwc is avaliable.
+   E_Plane *ep = NULL, *ep_fb = NULL;
+   const Eina_List *ep_l = NULL, *p_l;
+
+   ep_l = e_output_planes_get(eout);
+
+   // It is not hwc_usable if cursor is shown when the hw cursor is not supported.
+   if ((eout->cursor_available.max_w == -1) ||
+       (eout->cursor_available.max_h == -1))
+     {
+        // hw cursor is not supported by libtdm, than let's composite
+        if (!e_pointer_is_hidden(e_comp->pointer)) return EINA_FALSE;
+     }
+
+   ep_fb = e_output_fb_target_get(eout);
+   if (!ep_fb) return EINA_FALSE;
+
+   if (ep_fb->prepare_ec)
+     {
+        // It is not hwc_usable if the geometry of the prepare_ec at the ep_fb is not proper.
+        int bw = 0, bh = 0;
+
+        // It is not hwc_usable if attached buffer is not valid.
+        buffer = e_pixmap_resource_get(ep_fb->prepare_ec->pixmap);
+        if (!buffer) return EINA_FALSE;
+
+        e_pixmap_size_get(ep_fb->prepare_ec->pixmap, &bw, &bh);
+
+        // if client and zone's geometry is not match with, or
+        // if plane with reserved_memory(esp. fb target) has assigned smaller buffer,
+        // won't support hwc properly, than let's composite
+        if (ep_fb->reserved_memory &&
+            ((bw != zone->w) || (bh != zone->h) ||
+            (ep_fb->prepare_ec->x != zone->x) || (ep_fb->prepare_ec->y != zone->y) ||
+            (ep_fb->prepare_ec->w != zone->w) || (ep_fb->prepare_ec->h != zone->h)))
+          {
+             DBG("Cannot use HWC if geometry is not 1 on 1 match with reserved_memory");
+             return EINA_FALSE;
+          }
+     }
+   else
+     {
+        // It is not hwc_usable if the all prepare_ec in every plane are null
+        Eina_Bool all_null = EINA_TRUE;
+
+        EINA_LIST_FOREACH(ep_l, p_l, ep)
+          {
+             if (ep == ep_fb) continue;
+             if (ep->prepare_ec)
+               {
+                  // if attached buffer is not valid, hwc is not usable
+                  buffer = e_pixmap_resource_get(ep->prepare_ec->pixmap);
+                  if (!buffer) return EINA_FALSE;
+
+                  // It is not hwc_usable if the zpos of the ep is over the one of ep_fb
+                  if (ep->zpos < ep_fb->zpos) return EINA_FALSE;
+
+                  all_null = EINA_FALSE;
+                  break;
+               }
+          }
+        if (all_null) return EINA_FALSE;
+     }
+
+   return EINA_TRUE;
+}
+
+static void
+_e_output_hwc_begin(E_Output_Hwc *output_hwc)
+{
+   Eina_Bool mode_set = EINA_FALSE;
+
+   if (e_comp->nocomp_override > 0) return;
+
+   mode_set = _e_output_hwc_apply(output_hwc);
+   if (!mode_set) return;
+   if (!output_hwc->hwc_mode) return;
+
+   ELOGF("HWC", " Begin ...", NULL, NULL);
+}
+
+EINTERN void
+e_output_hwc_end(E_Output_Hwc *output_hwc, const char *location)
+{
+   Eina_Bool mode_set = EINA_FALSE;
+   E_Zone *zone;
+   Eina_List *l;
+   Eina_Bool fully_hwc;
+
+   EINA_SAFETY_ON_NULL_RETURN(output_hwc);
+
+  fully_hwc = (output_hwc->hwc_mode == E_OUTPUT_HWC_MODE_FULL) ? EINA_TRUE : EINA_FALSE;
+
+   _hwc_reserved_clean(output_hwc);
+
+   if (!e_comp->hwc) return;
+   if (!output_hwc->hwc_mode) return;
+
+   EINA_LIST_FOREACH(e_comp->zones, l, zone)
+     {
+        E_Output * eout;
+        if (!zone->output_id) continue;
+        eout = e_output_find(zone->output_id);
+        if (eout) mode_set |= _hwc_cancel(output_hwc);
+     }
+
+   if (!mode_set) return;
+
+   output_hwc->hwc_mode = E_OUTPUT_HWC_MODE_NO;
+
+   if (fully_hwc)
+     ecore_event_add(E_EVENT_COMPOSITOR_ENABLE, NULL, NULL, NULL);
+
+   ELOGF("HWC", " End...  at %s.", NULL, NULL, location);
+}
+
+EINTERN void
+e_output_hwc_multi_plane_set(E_Output_Hwc *output_hwc, Eina_Bool set)
+{
+   EINA_SAFETY_ON_NULL_RETURN(output_hwc);
+
+   e_output_hwc_end(output_hwc, __FUNCTION__);
+   output_hwc->hwc_use_multi_plane = set;
+
+   ELOGF("HWC", "e_output_hwc_multi_plane_set : %d", NULL, NULL, set);
+}
+
+EINTERN Eina_Bool
+e_output_hwc_multi_plane_get(E_Output_Hwc *output_hwc)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, EINA_FALSE);
+
+   return output_hwc->hwc_use_multi_plane;
+}
+
+EINTERN void
+e_output_hwc_deactive_set(E_Output_Hwc *output_hwc, Eina_Bool set)
+{
+   EINA_SAFETY_ON_NULL_RETURN(output_hwc);
+
+   e_output_hwc_end(output_hwc, __FUNCTION__);
+   output_hwc->hwc_deactive = set;
+
+   ELOGF("HWC", "e_output_hwc_deactive_set : %d", NULL, NULL, set);
+}
+
+EINTERN Eina_Bool
+e_output_hwc_deactive_get(E_Output_Hwc *output_hwc)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, EINA_FALSE);
+
+   return output_hwc->hwc_deactive;
+}
+
+EINTERN void
+e_output_hwc_apply(E_Output_Hwc *output_hwc)
+{
+   EINA_SAFETY_ON_NULL_RETURN(output_hwc);
+   EINA_SAFETY_ON_NULL_RETURN(output_hwc->output);
+
+   if(_e_output_hwc_usable(output_hwc))
+     {
+        if (output_hwc->hwc_mode)
+          {
+             if (_e_output_hwc_changed(output_hwc))
+               {
+                  if (output_hwc->hwc_mode == E_OUTPUT_HWC_MODE_NO)
+                    ELOGF("HWC", " End...  due to surface changes", NULL, NULL);
+                  else
+                    ELOGF("HWC", " hwc surface changed", NULL, NULL);
+               }
+          }
+        else
+          _e_output_hwc_begin(output_hwc);
+     }
+   else
+     e_output_hwc_end(output_hwc, __FUNCTION__);
+}
+
+EINTERN E_Output_Hwc_Mode
+e_output_hwc_mode_get(E_Output_Hwc *output_hwc)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, E_OUTPUT_HWC_MODE_NO);
+
+   return output_hwc->hwc_mode;
+}
+
+EINTERN E_Output_Hwc *
+e_output_hwc_new(E_Output *output)
+{
+   E_Output_Hwc *output_hwc = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
+
+   output_hwc = E_NEW(E_Output_Hwc, 1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, NULL);
+
+   output_hwc->output = output;
+
+   return output_hwc;
+}
+
+EINTERN void
+e_output_hwc_del(E_Output_Hwc *output_hwc)
+{
+   if (!output_hwc) return;
+
+   E_FREE(output_hwc);
+}
diff --git a/src/bin/e_output_hwc.h b/src/bin/e_output_hwc.h
new file mode 100644 (file)
index 0000000..5e44103
--- /dev/null
@@ -0,0 +1,38 @@
+#ifdef E_TYPEDEFS
+
+typedef struct _E_Output_Hwc     E_Output_Hwc;
+
+typedef enum _E_Output_Hwc_Mode
+{
+   E_OUTPUT_HWC_MODE_NO = 0,
+   E_OUTPUT_HWC_MODE_HYBRID,
+   E_OUTPUT_HWC_MODE_FULL
+} E_Output_Hwc_Mode;
+
+#else
+#ifndef E_OUTPUT_HWC_H
+#define E_OUTPUT_HWC_H
+
+struct _E_Output_Hwc
+{
+   E_Output          *output;
+   E_Output_Hwc_Mode  hwc_mode;
+   Eina_Bool          hwc_deactive : 1; // deactive hwc policy
+   Eina_Bool          hwc_use_multi_plane;
+};
+
+EINTERN E_Output_Hwc  *e_output_hwc_new(E_Output *output);
+EINTERN void           e_output_hwc_del(E_Output_Hwc *output_hwc);
+
+EINTERN void           e_output_hwc_apply(E_Output_Hwc *output_hwc);
+
+EINTERN E_Output_Hwc_Mode e_output_hwc_mode_get(E_Output_Hwc *output_hwc);
+
+EINTERN void e_output_hwc_deactive_set(E_Output_Hwc *output_hwc, Eina_Bool set);
+EINTERN Eina_Bool e_output_hwc_deactive_get(E_Output_Hwc *output_hwc);
+EINTERN void e_output_hwc_multi_plane_set(E_Output_Hwc *output_hwc, Eina_Bool set);
+EINTERN Eina_Bool e_output_hwc_multi_plane_get(E_Output_Hwc *output_hwc);
+
+EINTERN void e_output_hwc_end(E_Output_Hwc *output_hwc, const char *location);
+#endif
+#endif
index 748592cbc22e92484e37803db888dae086594d3c..d51d8ca6a1044034125a326c56fe0a444bd1600d 100644 (file)
@@ -460,8 +460,8 @@ _e_test_helper_cb_hwc(const Eldbus_Service_Interface *iface, const Eldbus_Messag
      {
         switch (on)
           {
-           case 0: accept = EINA_TRUE; e_comp->hwc_deactive = EINA_TRUE; break;
-           case 1: accept = EINA_TRUE; e_comp->hwc_deactive = EINA_FALSE;  break;
+           case 0: accept = EINA_TRUE; e_comp_hwc_deactive_set(EINA_TRUE); break;
+           case 1: accept = EINA_TRUE; e_comp_hwc_deactive_set(EINA_FALSE); break;
            default: break;
           }
      }