e_comp: hwc policy using e_output, e_plane 03/73003/4
authorJuyeon Lee <juyeonne.lee@samsung.com>
Fri, 3 Jun 2016 12:35:35 +0000 (21:35 +0900)
committerJuyeon Lee <juyeonne.lee@samsung.com>
Thu, 16 Jun 2016 09:38:02 +0000 (18:38 +0900)
Change-Id: I85a2685a1122ecf734b62003ad282b26bedc4821

src/bin/e_comp.c
src/bin/e_comp.h

index 2c3d9b585335be3bf0f1f4b43412b4ccb9f710f9..3db1ba854daa60417c79f0a2c385c6ab2fb551a4 100644 (file)
@@ -287,18 +287,12 @@ _e_comp_fps_update(void)
 }
 
 static Eina_Bool
-_e_comp_hwc_active(void)
+_e_comp_hwc_is_on(void)
 {
-   if (e_comp->hwc_override > 0)
-     return EINA_FALSE;
+   if ((e_comp->hwc_override <= 0) &&
+       (e_comp->hwc_mode))
+     return EINA_TRUE;
 
-   switch (e_comp->hwc_mode)
-     {
-      case E_HWC_MODE_NO_COMPOSITE:
-      case E_HWC_MODE_HWC_COMPOSITE:
-      case E_HWC_MODE_HWC_NO_COMPOSITE:
-         return EINA_TRUE;
-     }
    return EINA_FALSE;
 }
 
@@ -385,20 +379,236 @@ e_comp_nocomp_end(const char *location)
 }
 #ifdef MULTI_PLANE_HWC
 static Eina_Bool
-_e_comp_prepare_overlay(void)
+_hwc_set(E_Output *eout)
 {
-   Eina_List *l, *ll;
+   const Eina_List *ep_l = NULL, *l;
+   E_Plane *ep = NULL, *ep_prime = NULL;
+
+   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 (ep->ec) e_client_redirected_set(ep->ec, 1);
+     }
+
+   ep_l = e_output_planes_get(eout);
+   EINA_LIST_FOREACH(ep_l, l , ep)
+     {
+        if (!ep_prime)
+          {
+             if (e_plane_is_primary(ep))
+               {
+                  ep_prime = ep;
+                  if (ep->prepare_ec)
+                    {
+                       e_client_redirected_set(ep->prepare_ec, 0);
+                       ep->ec = ep->prepare_ec;
+                    }
+               }
+             continue;
+          }
+        if (e_plane_is_cursor(ep)) continue;
+        if (ep->zpos > ep_prime->zpos)
+          {
+             ep_prime = ep;
+             if (ep->prepare_ec)
+               {
+                  e_client_redirected_set(ep->prepare_ec, 0);
+                  ep->ec = ep->prepare_ec;
+               }
+          }
+     }
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_hwc_prepare_set(E_Output *eout, int n_vis, Eina_List *clist)
+{
+   const Eina_List *ep_l = NULL, *l ;
+   Eina_List *hwc_l = NULL, *clist2;
+   E_Plane *ep = NULL, *ep_prime = NULL;
+   int n_ly = 0, n_ec = 0;
+   E_Client *ec = NULL;
+   Eina_Bool ret = EINA_FALSE;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(eout, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(clist, EINA_FALSE);
+
+   ep_l = e_output_planes_get(eout);
+   EINA_LIST_FOREACH(ep_l, l, ep)
+     {
+        if (!ep_prime)
+          {
+             if (e_plane_is_primary(ep))
+               {
+                  ep_prime = ep;
+                  hwc_l = eina_list_append(hwc_l, ep);
+               }
+             continue;
+          }
+        if (e_plane_is_cursor(ep)) continue;
+        if (ep->zpos > ep_prime->zpos)
+          hwc_l = eina_list_append(hwc_l, ep);
+     }
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_l, EINA_FALSE);
+
+   n_ly = eina_list_count(hwc_l);
+   n_ec = eina_list_count(clist);
+   clist2 = eina_list_clone(clist);
+   if ((n_ec == n_vis) &&
+       (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;
+                  del--;
+                  continue;
+               }
+             if (clist) ec = eina_list_data_get(clist);
+             if (ec) ep->prepare_ec = ec;
+             clist = eina_list_next(clist);
+          }
+        ret = EINA_TRUE;
+     }
+   else if ((n_ly < n_vis) || // e_comp->evas on fb target plane
+            (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;
+                  del--;
+                  continue;
+               }
+             if (clist2) ec = eina_list_data_get(clist2);
+             if (ec) ep->prepare_ec = ec;
+             if (e_plane_is_primary(ep)) ep->prepare_ec = NULL;
+             clist2 = eina_list_next(clist2);
+          }
+        ret = EINA_TRUE;
+     }
+
+   eina_list_free(hwc_l);
+   return ret;
+}
+
+static Eina_Bool
+_hwc_cancel(E_Output *eout)
+{
+   Eina_List *l ;
+   E_Plane *ep;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(eout, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(eout->planes, EINA_FALSE);
+
+   e_comp->hwc_mode = 0;
+
+   EINA_LIST_FOREACH(eout->planes, l, ep)
+     {
+        if (ep->ec) e_client_redirected_set(ep->ec, 1);
+        ep->prepare_ec = NULL;
+        ep->ec = NULL;
+     }
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_comp_hwc_apply(E_Output * eout)
+{
+   const Eina_List *ep_l = NULL, *l;
+   E_Plane *ep = NULL, *ep_prime = NULL;
+
+   ep_l = e_output_planes_get(eout);
+   EINA_LIST_FOREACH(ep_l, l, ep)
+     {
+        if (!ep_prime)
+          {
+             if (e_plane_is_primary(ep))
+               {
+                  ep_prime = ep;
+                  if (ep->prepare_ec != NULL) goto hwcompose;
+               }
+             continue;
+          }
+        if (e_plane_is_cursor(ep)) continue;
+        if (ep->zpos > ep_prime->zpos)
+          if (ep->prepare_ec != NULL) goto hwcompose;
+     }
+
+   _hwc_cancel(eout);
+   return EINA_FALSE;
+
+hwcompose:
+   e_comp->hwc_mode = 1;
+   _hwc_set(eout);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_comp_hwc_changed(void)
+{
+   Eina_List *l;
    E_Zone *zone;
 
+   EINA_LIST_FOREACH(e_comp->zones, l, zone)
+     {
+        E_Output *eout = NULL;
+        E_Plane *ep = NULL, *ep_prime = NULL;
+        const Eina_List *ep_l = NULL, *p_l ;
+
+        if (!zone || !zone->output_id) continue;
+
+        eout = e_output_find(zone->output_id);
+        ep_l = e_output_planes_get(eout);
+        EINA_LIST_FOREACH(ep_l, p_l, ep)
+          {
+             if (!ep_prime)
+               {
+                  if (e_plane_is_primary(ep))
+                    {
+                       ep_prime = ep;
+                       if (ep->ec != ep->prepare_ec) return EINA_TRUE;
+                    }
+                  continue;
+               }
+             if (e_plane_is_cursor(ep)) continue;
+             if ((ep->zpos > ep_prime->zpos) &&
+                 (ep->ec != ep->prepare_ec))
+               return EINA_TRUE;
+          }
+     }
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+_e_comp_hwc_prepare(void)
+{
+   Eina_List *l;
+   E_Zone *zone;
+   Eina_Bool ret = EINA_FALSE;
+
    if (!e_comp->hwc) return EINA_FALSE;
 
    // TODO: e_comp->canvases
-   EINA_LIST_FOREACH_SAFE(e_comp->zones, l, ll, zone)
+   EINA_LIST_FOREACH(e_comp->zones, l, zone)
      {
         E_Client *ec;
         E_Output *eout;
-        int mode = E_HWC_MODE_INVALID;
-        int num_of_ly = 0, ly_cnt = 0;
+        int n_visible = 0, n_ec = 0;
         Eina_List *clist = NULL;
 
         if (!zone || !zone->output_id) continue;
@@ -430,54 +640,78 @@ _e_comp_prepare_overlay(void)
                  (cdata->width_from_buffer != cdata->width_from_viewport) ||
                  (cdata->height_from_buffer != cdata->height_from_viewport))
                {
-                  if (ly_cnt) mode = E_HWC_MODE_HWC_COMPOSITE;
-                  else mode = E_HWC_MODE_COMPOSITE;
+                  if (!n_visible) goto fullcomp;
+                  n_visible++;
                   break;
                }
 
-             ly_cnt++;
+             n_visible++;
              clist = eina_list_append(clist, ec);
           }
-        if (mode == E_HWC_MODE_INVALID)
+
+        n_ec = eina_list_count(clist);
+        if ((n_visible < 1) || (n_ec < 1))
           {
-             if (ly_cnt == 1) mode = E_HWC_MODE_NO_COMPOSITE;
-             else if (ly_cnt <= num_of_ly && ly_cnt > 1) mode = E_HWC_MODE_HWC_NO_COMPOSITE;
-             else if (ly_cnt > num_of_ly) mode = E_HWC_MODE_HWC_COMPOSITE;
+             eina_list_free(clist);
+             goto fullcomp;
           }
 
-        //e_output_planes_prepare(eout, mode, clist);
+        ret = _hwc_prepare_set(eout, n_visible, clist);
         eina_list_free(clist);
-        clist = NULL;
      }
 
-   return EINA_TRUE;
+   return ret;
+
+fullcomp:
+   return EINA_FALSE;
 }
 
 static Eina_Bool
 _e_comp_hwc_usable(void)
 {
+   Eina_List *l;
+   E_Zone *zone;
+
    if (!e_comp->hwc) return EINA_FALSE;
 
-   // check whether to use hwcomposer by assignment policy
-   // core policy
-   _e_comp_prepare_overlay();
+   // check whether to use hwc
+   // core assignment policy
+   _e_comp_hwc_prepare();
 
-   // extra policy
+   // extra policy can replace core policy
    _e_comp_hook_call(E_COMP_HOOK_PREPARE_PLANE, NULL);
 
-   switch (e_comp->prepare_mode)
+   EINA_LIST_FOREACH(e_comp->zones, l, zone)
      {
-      case E_HWC_MODE_NO_COMPOSITE:
-      case E_HWC_MODE_HWC_COMPOSITE:
-      case E_HWC_MODE_HWC_NO_COMPOSITE:
-         return EINA_TRUE;
-     }
+        E_Output *eout = NULL;
+        E_Plane *ep = NULL, *ep_prime = NULL;
+        const Eina_List *ep_l = NULL, *p_l;
+
+        if (!zone || !zone->output_id) continue;
 
+        eout = e_output_find(zone->output_id);
+        ep_l = e_output_planes_get(eout);
+        EINA_LIST_FOREACH(ep_l, p_l, ep)
+          {
+             if (!ep_prime)
+               {
+                  if (e_plane_is_primary(ep))
+                    {
+                       ep_prime = ep;
+                       if (ep->prepare_ec != NULL) return EINA_TRUE;
+                    }
+                  continue;
+               }
+             if (e_plane_is_cursor(ep)) continue;
+             if (ep->zpos > ep_prime->zpos)
+               if (ep->prepare_ec != NULL) return EINA_TRUE;
+          }
+     }
    return EINA_FALSE;
 }
 
 static void
-_e_comp_cb_hwc_begin(void)
+_e_comp_hwc_begin(void)
 {
    Eina_List *l;
    E_Zone *zone;
@@ -493,25 +727,25 @@ _e_comp_cb_hwc_begin(void)
         E_Output * eout;
         if (!zone->output_id) continue;
         eout = e_output_find(zone->output_id);
-        if(eout) mode_set |= e_output_planes_apply(eout);
+        if(eout) mode_set |= _e_comp_hwc_apply(eout);
      }
 
    if (!mode_set) return;
-   if (!_e_comp_hwc_active()) return;
+   if (!_e_comp_hwc_is_on()) return;
 
    if (e_comp->calc_fps) e_comp->frametimes[0] = 0;
 
-   INF("HWC : Begin to use HWComposer...");
+   INF("HWC : Begin ...");
 }
 
 static Eina_Bool
-_e_comp_cb_hwc_begin_timeout(void *data EINA_UNUSED)
+_e_comp_hwc_cb_begin_timeout(void *data EINA_UNUSED)
 {
    e_comp->selcomp_delay_timer = NULL;
 
    if (e_comp->hwc_override == 0 && _e_comp_hwc_usable())
      {
-        _e_comp_cb_hwc_begin();
+        _e_comp_hwc_begin();
      }
    return EINA_FALSE;
 }
@@ -521,30 +755,27 @@ _e_comp_hwc_end(const char *location)
 {
    Eina_Bool mode_set = EINA_FALSE;
    E_Zone *zone;
-   Eina_List *l, *ll;
+   Eina_List *l;
 
    if (!e_comp->hwc) return;
-   if (!_e_comp_hwc_active()) return;
+   if (!_e_comp_hwc_is_on()) return;
 
    e_comp->selcomp_want = 0;
    E_FREE_FUNC(e_comp->selcomp_delay_timer, ecore_timer_del);
 
    // e_comp->canvases will be replace e_comp->zones
-   EINA_LIST_FOREACH_SAFE(e_comp->zones, l, ll, zone)
+   EINA_LIST_FOREACH(e_comp->zones, l, zone)
      {
-        E_Output_Screen * eout;
+        E_Output * eout;
         if (!zone->output_id) continue;
-        eout = e_output_screen_id_find(zone->output_id);
-        if (eout) mode_set |= e_output_planes_clear(eout);
+        eout = e_output_find(zone->output_id);
+        if (eout) mode_set |= _hwc_cancel(eout);
      }
 
    if (!mode_set) return;
 
    INF("HWC : End...  at %s", location);
 
-   e_comp->prepare_mode = 0;
-   e_comp->hwc_mode = 0;
-
    e_comp_render_queue();
 }
 #endif
@@ -604,7 +835,7 @@ _e_comp_cb_update(void)
 
    DBG("UPDATE ALL");
    if (e_comp->nocomp) goto setup_hwcompose;
-   if (_e_comp_hwc_active()) goto setup_hwcompose;
+   if (_e_comp_hwc_is_on()) goto setup_hwcompose;
 
    if (conf->grab && (!e_comp->grabbed))
      {
@@ -649,14 +880,14 @@ setup_hwcompose:
 #ifdef MULTI_PLANE_HWC
    if(_e_comp_hwc_usable())
      {
-        if (_e_comp_hwc_active())
+        if (_e_comp_hwc_is_on())
           {
              // FIXME : will remove out this condition
              // new(ec at prepared list) and current(ec on e_plane)
-             if (e_output_planes_need_change)
+             if (_e_comp_hwc_changed())
                 _e_comp_hwc_end("overlay surface changed");
           }
-        else if (!_e_comp_hwc_active())
+        else
           {
              // switch mode
              if (conf->selcomp_use_timer)
@@ -664,19 +895,19 @@ setup_hwcompose:
                   if (!e_comp->selcomp_delay_timer)
                     {
                        e_comp->selcomp_delay_timer = ecore_timer_add(conf->selcomp_begin_timeout,
-                                                                     _e_comp_cb_hwc_begin_timeout,
+                                                                     _e_comp_hwc_cb_begin_timeout,
                                                                      NULL);
                     }
                }
              else
                {
-                  _e_comp_cb_hwc_begin();
+                  _e_comp_hwc_begin();
                }
           }
      }
    else
      {
-        if (_e_comp_hwc_active()) _e_comp_hwc_end(__FUNCTION__);
+        if (_e_comp_hwc_is_on()) _e_comp_hwc_end(__FUNCTION__);
      }
 #else
    ec = _e_comp_fullscreen_check();
@@ -1688,7 +1919,7 @@ e_comp_is_on_overlay(E_Client *ec)
      {
         return e_comp->nocomp_ec == ec;
      }
-   else if (_e_comp_hwc_active())
+   else if (_e_comp_hwc_is_on())
      {
         Eina_List *l, *ll;
         E_Output * eout;
index d88aad8d101346821f347ad2af111882bda18989..c0ecc94c1cb0c03d758e243a48fc1dbac2721344 100644 (file)
@@ -133,13 +133,11 @@ struct _E_Comp
    Ecore_Window    block_win;
    int             block_count; //number of times block window has been requested
 
-   Ecore_Window   cm_selection; //FIXME: move to comp_x ?
+   Ecore_Window    cm_selection; //FIXME: move to comp_x ?
    E_Client       *nocomp_ec;
 
-   Eina_List      *prepare_ec_list; // temp
-   int             hwc_override; //number of times selcomp override has been requested
-   int             prepare_mode;
-   int             hwc_mode;
+   int             hwc_override; //number of times hwc override has been requested
+   Eina_Bool       hwc_mode;
 
    int depth;
    unsigned int    input_key_grabs;