hwc: initial code for hwc windows policy. 23/169323/7
authorSooChan Lim <sc1.lim@samsung.com>
Tue, 6 Feb 2018 04:03:26 +0000 (13:03 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Wed, 7 Feb 2018 23:45:32 +0000 (23:45 +0000)
Add the code for hwc windows(Vendor Driven HWC).
It uses the tdm_hwc with which
the hwc policy is decided by the tdm backends and
E20 does not use the E_Plane(tdm_layer).

Change-Id: Ifc8c3ee8f44741ee6d781403b86f55859fc82c35

18 files changed:
src/bin/Makefile.mk
src/bin/e_client.h
src/bin/e_comp.c
src/bin/e_comp_object.c
src/bin/e_comp_screen.c
src/bin/e_comp_wl_video.c
src/bin/e_comp_wl_video.h
src/bin/e_hwc_window.c [new file with mode: 0644]
src/bin/e_hwc_window.h [new file with mode: 0644]
src/bin/e_includes.h
src/bin/e_info_client.c
src/bin/e_info_server.c
src/bin/e_output.c
src/bin/e_output_hwc.c
src/bin/e_output_hwc.h
src/bin/e_output_hwc_windows.c [new file with mode: 0644]
src/bin/e_output_hwc_windows.h [new file with mode: 0644]
src/bin/e_plane.c

index 386b9cfb11eba4431e9fc0b4b986861e4e58871a..054465066d886211e69d267486ad2cf395744a09 100644 (file)
@@ -90,7 +90,9 @@ src/bin/e_comp_wl_data.h \
 src/bin/e_comp_wl_input.h \
 src/bin/e_comp_wl.h \
 src/bin/e_output_hwc.h \
-src/bin/e_output_hwc_planes.h
+src/bin/e_output_hwc_planes.h \
+src/bin/e_output_hwc_windows.h \
+src/bin/e_hwc_window.h
 
 if HAVE_WAYLAND_TBM
 ENLIGHTENMENTHEADERS += \
@@ -190,6 +192,8 @@ src/bin/e_comp_wl_input.c \
 src/bin/e_comp_wl.c \
 src/bin/e_output_hwc.c \
 src/bin/e_output_hwc_planes.c \
+src/bin/e_output_hwc_windows.c \
+src/bin/e_hwc_window.c \
 $(ENLIGHTENMENTHEADERS)
 
 if HAVE_WAYLAND_TBM
index 052d593b308cd8c4e946b7f51de1d3a1e75077ef..3dce14eaac83e9e85a053bf92936d7b216425d0e 100644 (file)
@@ -941,6 +941,8 @@ struct E_Client
    Eina_Bool use_splash : 1;
    Eina_Bool saved_img : 1; // indicates that window has been saved as the image file even once
    Eina_Bool skip_save_img: 1; // indicates that window doesn't want to save its image file
+
+   E_Hwc_Window *hwc_window; // hwc window for the tdm_output_hwc.
 };
 
 #define e_client_focus_policy_click(ec) \
index 42419145c689a1b3e3f1906521888a6e316df735..c70c4d0d828a5e6c0361dc9e35117a908776b440 100644 (file)
@@ -925,18 +925,31 @@ e_comp_is_on_overlay(E_Client *ec)
    Eina_List *l, *ll;
    E_Output *eout;
    E_Plane *ep;
+   E_Hwc_Window *hwc_window;
 
-   if (!ec) return EINA_FALSE;
-   if (!ec->zone || !ec->zone->output_id) return EINA_FALSE;
+   EINA_SAFETY_ON_TRUE_RETURN_VAL(!ec, EINA_FALSE);
+   EINA_SAFETY_ON_TRUE_RETURN_VAL(!ec->zone, EINA_FALSE);
+   EINA_SAFETY_ON_TRUE_RETURN_VAL(!ec->zone->output_id, 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)
+   if (e_output_hwc_policy_get(eout->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
      {
-        E_Client *overlay_ec = ep->ec;
-        if (overlay_ec == ec) return EINA_TRUE;
+        if (!e_output_hwc_mode_get(eout->output_hwc)) 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;
+          }
+     }
+   else
+     {
+        hwc_window = ec->hwc_window;
+        EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+        if (e_hwc_window_is_on_hw_overlay(hwc_window)) return EINA_TRUE;
      }
 
    return EINA_FALSE;
index 2e2d036da1dda756162f8152dd64a9c8dad0f53e..5a752b0b2a6f56d0017ebb9fc6d50ac219fe610f 100644 (file)
@@ -1229,6 +1229,21 @@ _e_comp_object_pixels_get(void *data, Evas_Object *obj EINA_UNUSED)
      e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
 }
 
+
+static void
+_e_comp_object_pixels_noti(void *data, Evas_Object *obj EINA_UNUSED)
+{
+   E_Comp_Object *cw = data;
+   E_Client *ec = cw->ec;
+
+   if (e_object_is_del(E_OBJECT(ec))) return;
+   if (cw->external_content) return;
+
+   if (!ec->hwc_window) return;
+
+   e_hwc_window_render_list_add(ec->hwc_window);
+}
+
 /////////////////////////////////////////////
 
 static void
@@ -2148,6 +2163,7 @@ _e_comp_intercept_show(void *data, Evas_Object *obj EINA_UNUSED)
              evas_object_image_border_center_fill_set(cw->obj, EVAS_BORDER_FILL_SOLID);
              e_util_size_debug_set(cw->obj, 1);
              evas_object_image_pixels_get_callback_set(cw->obj, _e_comp_object_pixels_get, cw);
+             evas_object_image_pixels_noti_callback_set(cw->obj, _e_comp_object_pixels_noti, cw);
              evas_object_image_smooth_scale_set(cw->obj, e_comp_config_get()->smooth_windows);
              evas_object_name_set(cw->obj, "cw->obj");
              evas_object_image_colorspace_set(cw->obj, EVAS_COLORSPACE_ARGB8888);
index 971bf74dd62087a6033e83cf7ad5978508a99223..9345092b1b96f05f1b237e1d62971819e119b5d9 100644 (file)
@@ -1350,30 +1350,41 @@ e_comp_screen_hwc_info_debug(void)
    EINA_LIST_FOREACH_SAFE(e_comp_screen->outputs, l_o, ll_o, output)
      {
         if (!output) continue;
-        tdm_output_get_conn_status(output->toutput, &conn_status);
-        if (conn_status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) continue;
-
-        INF("HWC: HWC Output(%d):(x, y, w, h)=(%d, %d, %d, %d) Information.",
-            ++output_idx,
-            output->config.geom.x, output->config.geom.y, output->config.geom.w, output->config.geom.h);
-        INF("HWC:  num_layers=%d", output->plane_count);
-        EINA_LIST_FOREACH_SAFE(output->planes, l_l, ll_l, plane)
+
+        if (e_output_hwc_policy_get(output->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
           {
-              if (!plane) continue;
-              tdm_layer_get_capabilities(plane->tlayer, &layer_capabilities);
-              snprintf(layer_cap, sizeof(layer_cap), "%s%s%s%s%s%s%s%s",
-                       _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_CURSOR),
-                       _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_PRIMARY),
-                       _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_OVERLAY),
-                       _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_GRAPHIC),
-                       _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_VIDEO),
-                       _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_TRANSFORM),
-                       _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_RESEVED_MEMORY),
-                       _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_NO_CROP));
-              INF("HWC:  index=%d zpos=%d ec=%p %s",
-                  plane->index, plane->zpos,
-                  plane->ec?plane->ec:NULL,
-                  layer_cap);
+             tdm_output_get_conn_status(output->toutput, &conn_status);
+             if (conn_status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) continue;
+
+             INF("HWC: HWC Output(%d):(x, y, w, h)=(%d, %d, %d, %d) Information.",
+                 ++output_idx,
+                 output->config.geom.x, output->config.geom.y, output->config.geom.w, output->config.geom.h);
+             INF("HWC:  num_layers=%d", output->plane_count);
+             EINA_LIST_FOREACH_SAFE(output->planes, l_l, ll_l, plane)
+               {
+                   if (!plane) continue;
+                   /* FIXME: hwc extension doesn't provide thing like layer */
+                   tdm_layer_get_capabilities(plane->tlayer, &layer_capabilities);
+                   snprintf(layer_cap, sizeof(layer_cap), "%s%s%s%s%s%s%s%s",
+                            _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_CURSOR),
+                            _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_PRIMARY),
+                            _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_OVERLAY),
+                            _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_GRAPHIC),
+                            _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_VIDEO),
+                            _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_TRANSFORM),
+                            _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_RESEVED_MEMORY),
+                            _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_NO_CROP));
+                   INF("HWC:  index=%d zpos=%d ec=%p %s",
+                       plane->index, plane->zpos,
+                       plane->ec?plane->ec:NULL,
+                       layer_cap);
+               }
+          }
+        else
+          {
+             /* TODO: construct debug info for outputs managed by the hwc-wins */
+             INF("HWC: HWC Output(%d) managed by hwc-wins.", ++output_idx);
+             continue;
           }
      }
    INF("HWC: =========================================================================");
index 3061e5308cfb970fa5144a61a516f4cff96e18f8..b9f82139423189d2e4f019ce2c5e8b54d5992e8a 100644 (file)
@@ -52,6 +52,11 @@ struct _E_Video_Layer
    E_Video *video;
 
    tdm_layer *tdm_layer;
+
+   /* for hwc_window */
+   E_Video_Info_Layer info;
+   tbm_surface_h cur_tsurface; // tsurface to be set this layer.
+   E_Client *e_client;
 };
 
 struct _E_Video
@@ -309,20 +314,44 @@ _e_video_vbuf_find_with_comp_buffer(Eina_List *list, E_Comp_Wl_Buffer *comp_buff
    return NULL;
 }
 
+static E_Output*
+_get_e_output(tdm_output *output)
+{
+   Eina_List *l;
+   E_Output *eo;
+
+   EINA_LIST_FOREACH(e_comp->e_comp_screen->outputs, l, eo)
+      if (eo->toutput == output)
+         return eo;
+
+   return NULL;
+}
 
 static Eina_Bool
-_e_video_tdm_output_has_video_layer(tdm_output *output)
+_e_video_tdm_output_has_video_layer(tdm_output *toutput)
 {
+   E_Output *output = NULL;
    tdm_layer *layer;
    tdm_layer_capability lyr_capabilities = 0;
 
+   EINA_SAFETY_ON_NULL_RETURN_VAL(toutput, EINA_FALSE);
+
+   output = _get_e_output(toutput);
    EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
 
-   /* get the first suitable layer */
-   layer = _e_video_tdm_video_layer_get(output);
-   tdm_layer_get_capabilities(layer, &lyr_capabilities);
-   if (lyr_capabilities & TDM_LAYER_CAPABILITY_VIDEO)
-     return EINA_TRUE;
+   if (e_output_hwc_policy_get(output->output_hwc) != E_OUTPUT_HWC_POLICY_WINDOWS)
+     {
+        /* get the first suitable layer */
+        layer = _e_video_tdm_video_layer_get(output);
+        tdm_layer_get_capabilities(layer, &lyr_capabilities);
+        if (lyr_capabilities & TDM_LAYER_CAPABILITY_VIDEO)
+          return EINA_TRUE;
+     }
+   else
+     {
+        /* TODO: add the hwc_window video support */
+        ;;;;
+     }
 
    return EINA_FALSE;
 }
@@ -331,19 +360,47 @@ E_Video_Layer *
 _e_video_avaiable_video_layer_get(E_Video *video)
 {
    E_Video_Layer *layer = NULL;
+   E_Hwc_Window *hwc_window = NULL;
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(video, NULL);
 
    layer = calloc(1, sizeof(E_Video_Layer));
    EINA_SAFETY_ON_NULL_RETURN_VAL(layer, NULL);
 
-   layer->tdm_layer = _e_video_tdm_avaiable_video_layer_get(video->output);
-   if (!layer->tdm_layer)
+   layer->video = video;
+   layer->e_client = video->ec;
+
+   if (e_output_hwc_policy_get(video->e_output->output_hwc) != E_OUTPUT_HWC_POLICY_WINDOWS)
+     {
+        layer->tdm_layer = _e_video_tdm_avaiable_video_layer_get(video->output);
+        if (!layer->tdm_layer)
+          {
+             free(layer);
+             return NULL;
+          }
+        _e_video_tdm_set_layer_usable(layer->tdm_layer, EINA_FALSE);
+     }
+   else
      {
-        free(layer);
-        return NULL;
+       /*
+        * Try to create a video hwc window.
+        * In this moment the video resource will be held.
+        */
+        hwc_window = e_hwc_window_new(video->e_output->output_hwc, video->ec, E_HWC_WINDOW_STATE_VIDEO);
+        if (!hwc_window)
+          {
+             VER("hwc_opt: cannot create new video hwc window for ec(%p)", video->ec);
+             free(layer);
+             return NULL;
+          }
+
+        /* free previous hwc_window */
+        if (video->ec->hwc_window)
+           e_hwc_window_free(video->ec->hwc_window);
+
+        /* set new hwc_window to the e_client */
+        video->ec->hwc_window = hwc_window;
      }
-   _e_video_tdm_set_layer_usable(layer->tdm_layer, EINA_FALSE);
 
    return layer;
 }
@@ -352,25 +409,42 @@ _e_video_avaiable_video_layer_get(E_Video *video)
 static void
 _e_video_get_available_formats(const tbm_format **formats, int *count)
 {
-   tdm_output *output;
+   E_Output *output;
+   tdm_output *toutput;
    tdm_layer *layer;
+   tdm_error error;
 
    *count = 0;
 
    /* get the first output */
-   output = tdm_display_get_output(e_comp->e_comp_screen->tdisplay, 0, NULL);
+   toutput = tdm_display_get_output(e_comp->e_comp_screen->tdisplay, 0, NULL);
+   EINA_SAFETY_ON_NULL_RETURN(toutput);
+
+   output = _get_e_output(toutput);
    EINA_SAFETY_ON_NULL_RETURN(output);
 
-   /* get the first suitable layer */
-   layer = _e_video_tdm_video_layer_get(output);
-   if (layer)
+   if (e_output_hwc_policy_get(output->output_hwc) != E_OUTPUT_HWC_POLICY_WINDOWS)
      {
-        tdm_layer_get_available_formats(layer, formats, count);
+        /* get the first suitable layer */
+        layer = _e_video_tdm_video_layer_get(output);
+        if (layer)
+          {
+             tdm_layer_get_available_formats(layer, formats, count);
+          }
+        else
+          {
+             *formats = sw_formats;
+             *count = NUM_SW_FORMAT;
+          }
      }
    else
      {
-        *formats = sw_formats;
-        *count = NUM_SW_FORMAT;
+        error = tdm_output_hwc_get_video_supported_formats(output, formats, count);
+        if (error != TDM_ERROR_NONE)
+          {
+             *formats = sw_formats;
+             *count = NUM_SW_FORMAT;
+          }
      }
 }
 
@@ -381,21 +455,45 @@ _e_video_get_prop_id(E_Video *video, const char *name)
    const tdm_prop *props;
    int i, count = 0;
 
-   layer = _e_video_tdm_video_layer_get(video->output);
-   tdm_layer_get_available_properties(layer, &props, &count);
-
-   for (i = 0; i < count; i++)
+   if (e_output_hwc_policy_get(video->e_output->output_hwc) != E_OUTPUT_HWC_POLICY_WINDOWS)
      {
-        if (!strncmp(name, props[i].name, TDM_NAME_LEN))
+        layer = _e_video_tdm_video_layer_get(video->output);
+        tdm_layer_get_available_properties(layer, &props, &count);
+
+        for (i = 0; i < count; i++)
           {
-             VDB("check property(%s)", name);
-             return props[i].id;
+             if (!strncmp(name, props[i].name, TDM_NAME_LEN))
+               {
+                  VDB("check property(%s)", name);
+                  return props[i].id;
+               }
           }
      }
+   else
+     {
+       // TODO: hwc windows don't have any properties yet
+       //       video hwc_window has to get and set the property id.
+       // tdm_error tdm_hwc_window_video_get_property(tdm_hwc_window *hwc_window, uint32_t id, tdm_value *value);
+       ;;;;;
+     }
 
    return -1;
 }
 
+// TODO: this function has to be removed.....
+//       Use. e_output_hwc_policy_get();
+static Eina_Bool
+_is_video_hwc_windows(E_Video *video)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(video, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(video->e_output, EINA_FALSE);
+
+   if (e_output_hwc_policy_get(video->e_output->output_hwc) == E_OUTPUT_HWC_POLICY_WINDOWS)
+     return EINA_TRUE;
+
+   return EINA_FALSE;
+}
+
 static tdm_error
 _e_video_layer_get_info(E_Video_Layer *layer, E_Video_Info_Layer *vinfo)
 {
@@ -405,12 +503,17 @@ _e_video_layer_get_info(E_Video_Layer *layer, E_Video_Info_Layer *vinfo)
    EINA_SAFETY_ON_NULL_RETURN_VAL(layer, TDM_ERROR_INVALID_PARAMETER);
    EINA_SAFETY_ON_NULL_RETURN_VAL(vinfo, TDM_ERROR_INVALID_PARAMETER);
 
-   ret = tdm_layer_get_info(layer->tdm_layer, &tinfo);
-   EINA_SAFETY_ON_TRUE_RETURN_VAL(ret != TDM_ERROR_NONE, ret);
+   if (_is_video_hwc_windows(layer->video))
+        memcpy(vinfo, &layer->info, sizeof(E_Video_Info_Layer));
+   else
+     {
+        ret = tdm_layer_get_info(layer->tdm_layer, &tinfo);
+        EINA_SAFETY_ON_TRUE_RETURN_VAL(ret != TDM_ERROR_NONE, ret);
 
-   memcpy(&vinfo->src_config, &tinfo.src_config, sizeof(tdm_info_config));
-   memcpy(&vinfo->dst_pos, &tinfo.dst_pos, sizeof(tdm_pos));
-   vinfo->transform = tinfo.transform;
+        memcpy(&vinfo->src_config, &tinfo.src_config, sizeof(tdm_info_config));
+        memcpy(&vinfo->dst_pos, &tinfo.dst_pos, sizeof(tdm_pos));
+        vinfo->transform = tinfo.transform;
+     }
 
    return ret;
 }
@@ -418,17 +521,23 @@ _e_video_layer_get_info(E_Video_Layer *layer, E_Video_Info_Layer *vinfo)
 static tdm_error
 _e_video_layer_set_info(E_Video_Layer *layer, E_Video_Info_Layer *vinfo)
 {
-   tdm_error ret;
+   tdm_error ret = TDM_ERROR_NONE;
    tdm_info_layer info_layer = {0};
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(layer, TDM_ERROR_INVALID_PARAMETER);
    EINA_SAFETY_ON_NULL_RETURN_VAL(vinfo, TDM_ERROR_INVALID_PARAMETER);
 
-   memcpy(&info_layer.src_config, &vinfo->src_config, sizeof(tdm_info_config));
-   memcpy(&info_layer.dst_pos, &vinfo->dst_pos, sizeof(tdm_pos));
-   info_layer.transform = vinfo->transform;
+   if (_is_video_hwc_windows(layer->video))
+     memcpy(&layer->info, vinfo, sizeof(E_Video_Info_Layer));
+   else
+     {
+
+        memcpy(&info_layer.src_config, &vinfo->src_config, sizeof(tdm_info_config));
+        memcpy(&info_layer.dst_pos, &vinfo->dst_pos, sizeof(tdm_pos));
+        info_layer.transform = vinfo->transform;
 
-   ret = tdm_layer_set_info(layer->tdm_layer, &info_layer);
+        ret = tdm_layer_set_info(layer->tdm_layer, &info_layer);
+     }
 
    return ret;
 }
@@ -436,12 +545,15 @@ _e_video_layer_set_info(E_Video_Layer *layer, E_Video_Info_Layer *vinfo)
 static tdm_error
 _e_video_layer_set_buffer(E_Video_Layer * layer, tbm_surface_h buff)
 {
-   tdm_error ret;
+   tdm_error ret = TDM_ERROR_NONE;
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(layer, TDM_ERROR_BAD_REQUEST);
    EINA_SAFETY_ON_NULL_RETURN_VAL(buff, TDM_ERROR_BAD_REQUEST);
 
-   ret = tdm_layer_set_buffer(layer->tdm_layer, buff);
+   if (_is_video_hwc_windows(layer->video))
+     layer->cur_tsurface = buff; // set the buffer to the tdm at the e_hwc_window_buffer_update();
+   else
+     ret = tdm_layer_set_buffer(layer->tdm_layer, buff);
 
    return ret;
 }
@@ -450,10 +562,22 @@ static tdm_error
 _e_video_layer_unset_buffer(E_Video_Layer *layer)
 {
    tdm_error ret;
+   E_Hwc_Window *hwc_window;
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(layer, TDM_ERROR_BAD_REQUEST);
 
-   ret = tdm_layer_unset_buffer(layer->tdm_layer);
+   if (_is_video_hwc_windows(layer->video))
+     {
+        hwc_window = layer->e_client->hwc_window;
+        EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, TDM_ERROR_OPERATION_FAILED);
+
+        e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE);
+        layer->cur_tsurface = NULL; // set the buffer to the tdm at the e_hwc_window_buffer_update();
+
+        ret = TDM_ERROR_NONE;
+     }
+   else
+     ret = tdm_layer_unset_buffer(layer->tdm_layer);
 
    return ret;
 }
@@ -469,6 +593,23 @@ _e_video_layer_is_usable(E_Video_Layer * layer, unsigned int *usable)
    EINA_SAFETY_ON_NULL_RETURN_VAL(layer, TDM_ERROR_BAD_REQUEST);
    EINA_SAFETY_ON_NULL_RETURN_VAL(usable, TDM_ERROR_BAD_REQUEST);
 
+   if (_is_video_hwc_windows(layer->video))
+     {
+        E_Hwc_Window *hwc_window;
+        E_Hwc_Window_State state;
+
+        hwc_window = layer->e_client->hwc_window;
+        EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, TDM_ERROR_OPERATION_FAILED);
+
+        state = e_hwc_window_state_get(hwc_window);
+        if (state == E_HWC_WINDOW_STATE_NONE || state == E_HWC_WINDOW_STATE_CLIENT)
+          *usable = 1;
+        else
+          *usable = 0;
+
+        return TDM_ERROR_NONE;
+     }
+
    ret = tdm_layer_is_usable(layer->tdm_layer, usable);
    return ret;
 }
@@ -476,11 +617,15 @@ _e_video_layer_is_usable(E_Video_Layer * layer, unsigned int *usable)
 static tdm_error
 _e_video_layer_commit(E_Video_Layer *layer, tdm_layer_commit_handler func, void *user_data)
 {
-   tdm_error ret;
+   tdm_error ret = TDM_ERROR_NONE;
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(layer, TDM_ERROR_BAD_REQUEST);
 
-   ret = tdm_layer_commit(layer->tdm_layer, func, user_data);
+   if (_is_video_hwc_windows(layer->video))
+     ret = TDM_ERROR_NONE;
+   else
+     ret = tdm_layer_commit(layer->tdm_layer, func, user_data);
+
    return ret;
 }
 
@@ -492,6 +637,23 @@ _e_video_layer_get_displaying_buffer(E_Video_Layer *layer, int *tdm_error)
    if (tdm_error)
      *tdm_error = TDM_ERROR_OPERATION_FAILED;
 
+   if (_is_video_hwc_windows(layer->video))
+     {
+        E_Hwc_Window *hwc_window;
+        E_Video *video;
+
+        hwc_window = layer->e_client->hwc_window;
+        EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, NULL);
+
+        video = find_video_with_surface(layer->e_client->comp_data->surface);
+        EINA_SAFETY_ON_NULL_RETURN_VAL(video, EINA_FALSE);
+
+        if (tdm_error)
+          *tdm_error = TDM_ERROR_NONE;
+
+        return e_hwc_window_displaying_surface_get(hwc_window);
+     }
+
    return tdm_layer_get_displaying_buffer(layer->tdm_layer, tdm_error);
 }
 
@@ -505,11 +667,21 @@ _e_video_layer_get_available_properties(E_Video_Layer * layer, const tdm_prop **
   EINA_SAFETY_ON_NULL_RETURN_VAL(props, TDM_ERROR_BAD_REQUEST);
   EINA_SAFETY_ON_NULL_RETURN_VAL(count, TDM_ERROR_BAD_REQUEST);
 
-  tdm_layer *tlayer = layer->tdm_layer;
-  /* if layer wasn't set then get an any available tdm_layer */
-  if (tlayer == NULL)
-    tlayer = _e_video_tdm_avaiable_video_layer_get(layer->video->output);
-  ret = tdm_layer_get_available_properties(tlayer, props, count);
+  if (_is_video_hwc_windows(layer->video))
+    {
+       *count = 0;
+       if (layer->e_client->hwc_window->thwc_window)
+         ret = tdm_hwc_window_video_get_available_properties(
+                         layer->e_client->hwc_window->thwc_window, props, count);
+    }
+  else
+    {
+       tdm_layer *tlayer = layer->tdm_layer;
+       /* if layer wasn't set then get an any available tdm_layer */
+       if (tlayer == NULL)
+         tlayer = _e_video_tdm_avaiable_video_layer_get(layer->video->output);
+       ret = tdm_layer_get_available_properties(tlayer, props, count);
+    }
 
   return ret;
 }
@@ -517,12 +689,21 @@ _e_video_layer_get_available_properties(E_Video_Layer * layer, const tdm_prop **
 static tdm_error
 _e_video_layer_get_property(E_Video_Layer * layer, unsigned id, tdm_value *value)
 {
-  tdm_error ret;
+  tdm_error ret = TDM_ERROR_OPERATION_FAILED;
 
   EINA_SAFETY_ON_NULL_RETURN_VAL(layer, TDM_ERROR_BAD_REQUEST);
   EINA_SAFETY_ON_NULL_RETURN_VAL(value, TDM_ERROR_BAD_REQUEST);
 
-  ret = tdm_layer_get_property(layer->tdm_layer, id, value);
+  if (_is_video_hwc_windows(layer->video))
+    {
+       if (layer->e_client->hwc_window->thwc_window)
+         ret = tdm_hwc_window_video_get_property(
+                      layer->e_client->hwc_window->thwc_window, id, value);
+
+       ret = TDM_ERROR_BAD_MODULE;
+    }
+  else
+    ret = tdm_layer_get_property(layer->tdm_layer, id, value);
 
   return ret;
 }
@@ -534,6 +715,9 @@ _e_video_layer_set_property(E_Video_Layer * layer, Tdm_Prop_Value *prop)
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(layer, TDM_ERROR_BAD_REQUEST);
 
+   if (_is_video_hwc_windows(layer->video))
+     return TDM_ERROR_BAD_MODULE;
+
    ret = tdm_layer_set_property(layer->tdm_layer, prop->id, prop->value);
    return ret;
 }
@@ -543,6 +727,20 @@ _e_video_layer_destroy(E_Video_Layer *layer)
 {
    EINA_SAFETY_ON_NULL_RETURN(layer);
 
+   if (layer->e_client && layer->e_client->hwc_window)
+     {
+        E_Hwc_Window *hwc_window;
+
+        hwc_window = layer->e_client->hwc_window;
+        EINA_SAFETY_ON_FALSE_RETURN(hwc_window);
+
+        e_hwc_window_free(hwc_window);
+        layer->e_client->hwc_window = NULL;
+
+        /* to re-evaluate the window policy */
+        e_comp_render_queue();
+     }
+
    if (layer->tdm_layer)
      _e_video_tdm_set_layer_usable(layer->tdm_layer, EINA_TRUE);
 
@@ -556,6 +754,7 @@ _e_video_set_layer(E_Video *video, Eina_Bool set)
      {
         unsigned int usable = 1;
         if (!video->layer) return EINA_TRUE;
+
         _e_video_layer_is_usable(video->layer, &usable);
         if (!usable && !video->waiting_video_set)
           {
@@ -563,13 +762,18 @@ _e_video_set_layer(E_Video *video, Eina_Bool set)
              _e_video_layer_unset_buffer(video->layer);
              _e_video_layer_commit(video->layer, NULL, NULL);
           }
+
         VIN("release layer: %p", video->layer);
         _e_video_layer_destroy(video->layer);
         video->layer = NULL;
         video->old_comp_buffer = NULL;
 
-        e_plane_video_set(video->e_plane, EINA_FALSE, NULL);
-        video->e_plane = NULL;
+        if (e_output_hwc_policy_get(video->e_output->output_hwc) != E_OUTPUT_HWC_POLICY_WINDOWS)
+          {
+             e_plane_video_set(video->e_plane, EINA_FALSE, NULL);
+             video->e_plane = NULL;
+          }
+
         video->waiting_video_set = EINA_FALSE;
         if (video->video_set_hook)
           {
@@ -591,29 +795,33 @@ _e_video_set_layer(E_Video *video, Eina_Bool set)
              return EINA_FALSE;
           }
 
-        ret = tdm_layer_get_zpos(video->layer->tdm_layer, &zpos);
-        if (ret == TDM_ERROR_NONE)
-          video->e_plane = e_output_plane_get_by_zpos(video->e_output, zpos);
-
-        if (!video->e_plane)
-          {
-             VWR("fail get e_plane");
-             _e_video_layer_destroy(video->layer);
-             video->layer = NULL;
-             return EINA_FALSE;
-          }
-        if (!e_plane_video_set(video->e_plane, EINA_TRUE, &video->waiting_video_set))
-          {
-             VWR("fail set video to e_plane");
-             _e_video_layer_destroy(video->layer);
-             video->layer = NULL;
-             video->e_plane = NULL;
-             return EINA_FALSE;
-          }
-        if (video->waiting_video_set)
+        if (e_output_hwc_policy_get(video->e_output->output_hwc) != E_OUTPUT_HWC_POLICY_WINDOWS)
           {
-             if (!video->video_set_hook)
-               video->video_set_hook = e_plane_hook_add(E_PLANE_HOOK_VIDEO_SET, _e_video_video_set_hook, video);
+             ret = tdm_layer_get_zpos(video->layer->tdm_layer, &zpos);
+             if (ret == TDM_ERROR_NONE)
+               video->e_plane = e_output_plane_get_by_zpos(video->e_output, zpos);
+
+             if (!video->e_plane)
+               {
+                  VWR("fail get e_plane");
+                  _e_video_layer_destroy(video->layer);
+                  video->layer = NULL;
+                  return EINA_FALSE;
+               }
+
+             if (!e_plane_video_set(video->e_plane, EINA_TRUE, &video->waiting_video_set))
+               {
+                  VWR("fail set video to e_plane");
+                  _e_video_layer_destroy(video->layer);
+                  video->layer = NULL;
+                  video->e_plane = NULL;
+                  return EINA_FALSE;
+               }
+             if (video->waiting_video_set)
+               {
+                  if (!video->video_set_hook)
+                    video->video_set_hook = e_plane_hook_add(E_PLANE_HOOK_VIDEO_SET, _e_video_video_set_hook, video);
+               }
           }
 
         VIN("assign layer: %p", video->layer);
@@ -1472,6 +1680,96 @@ _e_video_commit_handler(tdm_layer *layer, unsigned int sequence,
    VDB("current_fb(%d)", MSTAMP(video->current_fb));
 }
 
+EINTERN void
+e_comp_wl_video_hwc_window_commit_data_release(E_Hwc_Window *hwc_window, unsigned int sequence,
+                            unsigned int tv_sec, unsigned int tv_usec)
+{
+   E_Client *ec = NULL;
+   E_Video *video = NULL;
+   Eina_List *l = NULL;
+   E_Video_Layer *video_layer;
+
+   EINA_SAFETY_ON_NULL_RETURN(hwc_window);
+
+   ec = hwc_window->ec;
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   EINA_LIST_FOREACH(video_list, l, video)
+     if (video->ec == ec) break;
+   EINA_SAFETY_ON_NULL_RETURN(video);
+
+   video_layer = video->layer;
+   EINA_SAFETY_ON_NULL_RETURN(video_layer);
+
+   _e_video_commit_handler(NULL, sequence, tv_sec, tv_usec, video);
+}
+
+EINTERN tbm_surface_h
+e_comp_wl_video_hwc_widow_surface_get(E_Hwc_Window *hwc_window)
+{
+   E_Client *ec = NULL;
+   Eina_List *l = NULL;
+   E_Video *video = NULL;
+   E_Video_Layer *video_layer;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, NULL);
+
+   if (!e_hwc_window_is_video(hwc_window))
+     {
+       ERR("ehw:%p is NOT Video HWC window.", hwc_window);
+       return NULL;
+     }
+
+   ec = hwc_window->ec;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
+
+   EINA_LIST_FOREACH(video_list, l, video)
+     if (video->ec == ec) break;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(video, NULL);
+
+   video_layer = video->layer;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(video_layer, NULL);
+
+   return video_layer->cur_tsurface;
+}
+
+EINTERN Eina_Bool
+e_comp_wl_video_hwc_window_info_get(E_Hwc_Window *hwc_window, tdm_hwc_window_info *hwc_win_info)
+{
+   E_Client *ec = NULL;
+   Eina_List *l = NULL;
+   E_Video *video = NULL;
+   E_Video_Layer *video_layer;
+   E_Video_Info_Layer *vinfo;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+   if (!e_hwc_window_is_video(hwc_window))
+     {
+       ERR("ehw:%p is NOT Video HWC window.", hwc_window);
+       return EINA_FALSE;
+     }
+
+   ec = hwc_window->ec;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
+
+   EINA_LIST_FOREACH(video_list, l, video)
+     if (video->ec == ec) break;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(video,EINA_FALSE);
+
+   video_layer = video->layer;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(video_layer, EINA_FALSE);
+
+   vinfo = &video_layer->info;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(vinfo, EINA_FALSE);
+
+   memcpy(&hwc_win_info->src_config, &vinfo->src_config, sizeof(tdm_info_config));
+   memcpy(&hwc_win_info->dst_pos, &vinfo->dst_pos, sizeof(tdm_pos));
+   hwc_win_info->transform = vinfo->transform;
+
+   return EINA_TRUE;
+}
+
 static void
 _e_video_vblank_handler(tdm_output *output, unsigned int sequence,
                         unsigned int tv_sec, unsigned int tv_usec,
@@ -1733,6 +2031,9 @@ _e_video_cb_evas_show(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNU
 
    if (e_object_is_del(E_OBJECT(video->ec))) return;
 
+   if (!video->ec->comp_data->video_client)
+     return;
+
    if (video->need_force_render)
      {
         VIN("video forcely rendering..");
@@ -1786,6 +2087,9 @@ _e_video_cb_evas_hide(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNU
 
    if (e_object_is_del(E_OBJECT(video->ec))) return;
 
+   if (!video->ec->comp_data->video_client)
+     return;
+
    /* if stand_alone is true, not hide */
    if (video->ec->comp_data->sub.data && video->ec->comp_data->sub.data->stand_alone)
      {
@@ -1902,7 +2206,13 @@ _e_video_set(E_Video *video, E_Client *ec)
         EINA_SAFETY_ON_NULL_RETURN(video->output);
      }
 
-   if (_e_video_tdm_output_has_video_layer(video->output))
+   if (video_to_primary)
+     {
+        VIN("show video to primary layer");
+        ec->comp_data->video_client = 0;
+        ec->animatable = 0;
+     }
+   else if (_e_video_tdm_output_has_video_layer(video->output))
      {
         /* If tdm offers video layers, we will assign a tdm layer when showing */
         VIN("video client");
@@ -1926,13 +2236,6 @@ _e_video_set(E_Video *video, E_Client *ec)
           }
      }
 
-   if (video_to_primary)
-     {
-        VIN("show video to primary layer");
-        ec->comp_data->video_client = 0;
-        ec->animatable = 0;
-     }
-
    tdm_output_get_available_size(video->output, &ominw, &ominh, &omaxw, &omaxh, &video->output_align);
 
    tdm_display_get_capabilities(e_comp->e_comp_screen->tdisplay, &disp_capabilities);
@@ -2114,47 +2417,96 @@ _e_video_check_if_pp_needed(E_Video *video)
    const tbm_format *formats;
    Eina_Bool found = EINA_FALSE;
    tdm_layer_capability capabilities = 0;
-   tdm_layer *layer = _e_video_tdm_video_layer_get(video->output);
+   tdm_error error;
 
-   tdm_layer_get_capabilities(layer, &capabilities);
+   if (e_output_hwc_policy_get(video->e_output->output_hwc) != E_OUTPUT_HWC_POLICY_WINDOWS)
+     {
+        tdm_layer *layer = _e_video_tdm_video_layer_get(video->output);
 
-   /* don't need pp if a layer has TDM_LAYER_CAPABILITY_VIDEO capability*/
-   if (capabilities & TDM_LAYER_CAPABILITY_VIDEO)
-     return EINA_FALSE;
+        tdm_layer_get_capabilities(layer, &capabilities);
 
-   /* check formats */
-   tdm_layer_get_available_formats(layer, &formats, &count);
-   for (i = 0; i < count; i++)
-     if (formats[i] == video->tbmfmt)
-       {
-          found = EINA_TRUE;
-          break;
-       }
+        /* don't need pp if a layer has TDM_LAYER_CAPABILITY_VIDEO capability*/
+        if (capabilities & TDM_LAYER_CAPABILITY_VIDEO)
+          return EINA_FALSE;
+
+        /* check formats */
+        tdm_layer_get_available_formats(layer, &formats, &count);
+        for (i = 0; i < count; i++)
+          if (formats[i] == video->tbmfmt)
+            {
+               found = EINA_TRUE;
+               break;
+            }
+
+        if (!found)
+          {
+             if (formats && count > 0)
+               video->pp_tbmfmt = formats[0];
+             else
+               {
+                  WRN("No layer format information!!!");
+                  video->pp_tbmfmt = TBM_FORMAT_ARGB8888;
+               }
+             return EINA_TRUE;
+          }
+
+        /* check size */
+        if (capabilities & TDM_LAYER_CAPABILITY_SCANOUT)
+          goto need_pp;
+
+        if (video->geo.input_r.w != video->geo.output_r.w || video->geo.input_r.h != video->geo.output_r.h)
+          if (!(capabilities & TDM_LAYER_CAPABILITY_SCALE))
+            goto need_pp;
 
-   if (!found)
+        /* check rotate */
+        if (video->geo.transform || e_comp->e_comp_screen->rotation > 0)
+          if (!(capabilities & TDM_LAYER_CAPABILITY_TRANSFORM))
+            goto need_pp;
+     }
+   else
      {
-        if (formats && count > 0)
-          video->pp_tbmfmt = formats[0];
-        else
+        E_Hwc_Window *hwc_window = video->ec->hwc_window;
+        tdm_hwc_window_video_capability capabilities = 0;
+
+        error = tdm_output_hwc_get_video_supported_formats(video->output, &formats, &count);
+        if (error != TDM_ERROR_NONE)
           {
-             WRN("No layer format information!!!");
              video->pp_tbmfmt = TBM_FORMAT_ARGB8888;
+             return EINA_TRUE;
           }
-        return EINA_TRUE;
-     }
+        for (i = 0; i < count; i++)
+          if (formats[i] == video->tbmfmt)
+            {
+               found = EINA_TRUE;
+               break;
+            }
 
-   /* check size */
-   if (capabilities & TDM_LAYER_CAPABILITY_SCANOUT)
-     goto need_pp;
+        if (!found)
+          {
+             video->pp_tbmfmt = TBM_FORMAT_ARGB8888;
+             return EINA_TRUE;
+          }
 
-   if (video->geo.input_r.w != video->geo.output_r.w || video->geo.input_r.h != video->geo.output_r.h)
-     if (!(capabilities & TDM_LAYER_CAPABILITY_SCALE))
-       goto need_pp;
+        error = tdm_hwc_window_video_get_capability(hwc_window->thwc_window, &capabilities);
+        if (error != TDM_ERROR_NONE)
+          {
+             video->pp_tbmfmt = TBM_FORMAT_ARGB8888;
+             return EINA_TRUE;
+          }
 
-   /* check rotate */
-   if (video->geo.transform || e_comp->e_comp_screen->rotation > 0)
-     if (!(capabilities & TDM_LAYER_CAPABILITY_TRANSFORM))
-       goto need_pp;
+        /* check size */
+        if (capabilities & TDM_HWC_WINDOW_VIDEO_CAPABILITY_SCANOUT)
+          goto need_pp;
+
+        if (video->geo.input_r.w != video->geo.output_r.w || video->geo.input_r.h != video->geo.output_r.h)
+          if (!(capabilities & TDM_HWC_WINDOW_VIDEO_CAPABILITY_SCALE))
+            goto need_pp;
+
+        /* check rotate */
+        if (video->geo.transform || e_comp->e_comp_screen->rotation > 0)
+          if (!(capabilities & TDM_HWC_WINDOW_VIDEO_CAPABILITY_TRANSFORM))
+            goto need_pp;
+     }
 
    return EINA_FALSE;
 
index 75333ad2de7bb51bac5ce99d1ae957176558055a..e9d5881494b2b537d09811d6f23751baba4b7859 100644 (file)
@@ -15,6 +15,10 @@ EINTERN void e_comp_wl_video_shutdown(void);
 
 EINTERN tdm_layer* e_comp_wl_video_layer_get(tdm_output *output);
 
+EINTERN void          e_comp_wl_video_hwc_window_commit_data_release(E_Hwc_Window *hwc_window, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec);
+EINTERN tbm_surface_h e_comp_wl_video_hwc_widow_surface_get(E_Hwc_Window *hwc_window);
+EINTERN Eina_Bool     e_comp_wl_video_hwc_window_info_get(E_Hwc_Window *hwc_window, tdm_hwc_window_info *hwc_win_info);
+
 #define C(b,m)              (((b) >> (m)) & 0xFF)
 #define FOURCC_STR(id)      C(id,0), C(id,8), C(id,16), C(id,24)
 #define IS_RGB(f)           ((f) == TBM_FORMAT_XRGB8888 || (f) == TBM_FORMAT_ARGB8888)
diff --git a/src/bin/e_hwc_window.c b/src/bin/e_hwc_window.c
new file mode 100644 (file)
index 0000000..3f79e3b
--- /dev/null
@@ -0,0 +1,1823 @@
+#include "e.h"
+
+# include <Evas_Engine_GL_Drm.h>
+# include <Evas_Engine_GL_Tbm.h>
+# include <Evas_Engine_Software_Tbm.h>
+# include <sys/eventfd.h>
+# include <gbm/gbm_tbm.h>
+# include <pixman.h>
+
+static E_Client_Hook *client_hook_new = NULL;
+static E_Client_Hook *client_hook_del = NULL;
+static Ecore_Event_Handler *zone_set_event_handler = NULL;
+static uint64_t ee_rendered_hw_list_key;
+
+static E_Comp_Wl_Buffer *
+_e_hwc_window_comp_wl_buffer_get(E_Hwc_Window *hwc_window)
+{
+   E_Client *ec = hwc_window->ec;
+   E_Comp_Wl_Client_Data *cdata = (E_Comp_Wl_Client_Data*)ec->comp_data;
+   E_Comp_Wl_Buffer_Ref *buffer_ref;
+
+   if (!cdata) return NULL;
+
+   buffer_ref = &cdata->buffer_ref;
+
+   return buffer_ref->buffer;
+}
+
+struct wayland_tbm_client_queue *
+_get_wayland_tbm_client_queue(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;
+   E_Comp_Wl_Client_Data *cdata = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(wl_comp_data, 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;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(wl_surface, NULL);
+
+   cqueue = wayland_tbm_server_client_queue_get(wl_comp_data->tbm.server, wl_surface);
+   if (!cqueue)
+     {
+        ELOGF("HWC-WINS", " ehw:%p has no wl_tbm_server_client_queue. -- {%25s}, state:%s, zpos:%d, deleted:%s",
+              ec->pixmap, ec, ec->hwc_window, ec->icccm.title,
+              e_hwc_window_state_string_get(ec->hwc_window->state),
+              ec->hwc_window->zpos, ec->hwc_window->is_deleted ? "yes" : "no");
+     }
+   EINA_SAFETY_ON_NULL_RETURN_VAL(cqueue, NULL);
+
+   return cqueue;
+}
+
+static tbm_surface_queue_h
+_get_tbm_surface_queue()
+{
+   return e_comp->e_comp_screen->tqueue;
+}
+
+static tdm_hwc_window_composition
+_get_composition_type(E_Hwc_Window_State state)
+{
+   tdm_hwc_window_composition composition_type = TDM_COMPOSITION_NONE;
+
+   switch (state)
+     {
+      case E_HWC_WINDOW_STATE_NONE:
+        composition_type = TDM_COMPOSITION_NONE;
+        break;
+      case E_HWC_WINDOW_STATE_CLIENT:
+        composition_type = TDM_COMPOSITION_CLIENT;
+        break;
+      case E_HWC_WINDOW_STATE_DEVICE:
+        composition_type = TDM_COMPOSITION_DEVICE;
+        break;
+      case E_HWC_WINDOW_STATE_DEVICE_CANDIDATE:
+        composition_type = TDM_COMPOSITION_DEVICE_CANDIDATE;
+        break;
+      case E_HWC_WINDOW_STATE_CURSOR:
+        composition_type = TDM_COMPOSITION_CURSOR;
+        break;
+      case E_HWC_WINDOW_STATE_VIDEO:
+        composition_type = TDM_COMPOSITION_VIDEO;
+        break;
+      default:
+        composition_type = TDM_COMPOSITION_NONE;
+        ERR("hwc-opt: unknown state of hwc_window.");
+     }
+
+   return composition_type;
+}
+
+static unsigned int
+_get_aligned_width(tbm_surface_h tsurface)
+{
+   unsigned int aligned_width = 0;
+   tbm_surface_info_s surf_info;
+
+   tbm_surface_get_info(tsurface, &surf_info);
+
+   switch (surf_info.format)
+     {
+      case TBM_FORMAT_YUV420:
+      case TBM_FORMAT_YVU420:
+      case TBM_FORMAT_YUV422:
+      case TBM_FORMAT_YVU422:
+      case TBM_FORMAT_NV12:
+      case TBM_FORMAT_NV21:
+        aligned_width = surf_info.planes[0].stride;
+        break;
+      case TBM_FORMAT_YUYV:
+      case TBM_FORMAT_UYVY:
+        aligned_width = surf_info.planes[0].stride >> 1;
+        break;
+      case TBM_FORMAT_ARGB8888:
+      case TBM_FORMAT_XRGB8888:
+        aligned_width = surf_info.planes[0].stride >> 2;
+        break;
+      default:
+        ERR("not supported format: %x", surf_info.format);
+     }
+
+   return aligned_width;
+}
+
+static tbm_surface_h
+_e_hwc_window_target_window_surface_acquire(E_Hwc_Window_Target *target_hwc_window)
+{
+   tbm_surface_queue_h queue = NULL;
+   tbm_surface_h surface = NULL;
+   tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, NULL);
+
+   queue = target_hwc_window->queue;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(queue, NULL);
+
+   if (tbm_surface_queue_can_acquire(queue, 0))
+     {
+        tsq_err = tbm_surface_queue_acquire(queue, &surface);
+
+        if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE)
+          {
+             ERR("Failed to acquire tbm_surface from tbm_surface_queue(%p): tsq_err = %d", queue, tsq_err);
+             return NULL;
+          }
+     }
+   else
+     {
+        return NULL;
+     }
+
+   return surface;
+}
+
+static void
+_e_hwc_window_target_window_surface_release(E_Hwc_Window_Target *target_hwc_window, tbm_surface_h tsurface)
+{
+   tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE;
+   tbm_surface_queue_h tqueue = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN(target_hwc_window);
+   EINA_SAFETY_ON_NULL_RETURN(tsurface);
+
+   tqueue = target_hwc_window->queue;
+   EINA_SAFETY_ON_NULL_RETURN(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 void
+_e_hwc_window_target_window_surface_data_free(void *data)
+{
+   Eina_List *ee_rendered_hw_list = (Eina_List *)data;
+
+   eina_list_free(ee_rendered_hw_list);
+}
+
+/* gets called as somebody modifies target_window's queue */
+static void
+_e_hwc_window_target_window_surface_queue_trace_cb(tbm_surface_queue_h surface_queue,
+        tbm_surface_h tsurface, tbm_surface_queue_trace trace, void *data)
+{
+   E_Hwc_Window_Target *target_hwc_window = (E_Hwc_Window_Target *)data;
+
+   /* gets called as evas_renderer dequeues a new buffer from the queue */
+   if (trace == TBM_SURFACE_QUEUE_TRACE_DEQUEUE)
+     {
+        ELOGF("HWC-WINS", " ehw:%p gets dequeue noti ts:%p -- {%s}.",
+              NULL, NULL, target_hwc_window, tsurface, "@TARGET WINDOW@");
+
+        tbm_surface_internal_add_user_data(tsurface, ee_rendered_hw_list_key, _e_hwc_window_target_window_surface_data_free);
+        target_hwc_window->dequeued_tsurface = tsurface;
+     }
+   /* gets called as evas_renderer enqueues a new buffer into the queue */
+   if (trace == TBM_SURFACE_QUEUE_TRACE_ENQUEUE)
+     {
+        uint64_t value = 1;
+        int ret;
+
+        ret = write(target_hwc_window->event_fd, &value, sizeof(value));
+        if (ret == -1)
+          ERR("failed to send acquirable event:%m");
+
+        ELOGF("HWC-WINS", " ehw:%p gets enqueue noti ts:%p -- {%s}.",
+              NULL, NULL, target_hwc_window, tsurface, "@TARGET WINDOW@");
+
+        tbm_surface_internal_add_user_data(tsurface, ee_rendered_hw_list_key, _e_hwc_window_target_window_surface_data_free);
+        target_hwc_window->dequeued_tsurface = tsurface;
+     }
+   /* tsurface has been released at the queue */
+   if (trace == TBM_SURFACE_QUEUE_TRACE_RELEASE)
+     {
+        tbm_surface_internal_delete_user_data(tsurface, ee_rendered_hw_list_key);
+        ELOGF("HWC-WINS", " ehw:%p gets release noti ts:%p -- {%s}.",
+              NULL, NULL, target_hwc_window, tsurface, "@TARGET WINDOW@");
+     }
+}
+
+/* gets called as evas_renderer enqueues a new buffer into the queue */
+static void
+_e_hwc_window_target_window_surface_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data)
+{
+ // TODO: This function to be deprecated.
+#if 0
+    E_Hwc_Window_Target *target_hwc_window = (E_Hwc_Window_Target *)data;
+    uint64_t value = 1;
+    int ret;
+
+    ret = write(target_hwc_window->event_fd, &value, sizeof(value));
+    if (ret == -1)
+      ERR("failed to send acquirable event:%m");
+#endif
+}
+
+/* gets called at the beginning of an ecore_main_loop iteration */
+static Eina_Bool
+_e_hwc_window_target_window_render_finished_cb(void *data, Ecore_Fd_Handler *fd_handler)
+{
+   int len;
+   int fd;
+   char buffer[64];
+
+   ELOGF("HWC-WINS", " ecore_main_loop: the new iteration.", NULL, NULL);
+
+   fd = ecore_main_fd_handler_fd_get(fd_handler);
+   len = read(fd, buffer, sizeof(buffer));
+   if (len == -1)
+     ERR("failed to read queue acquire event fd:%m");
+
+   return ECORE_CALLBACK_RENEW;
+}
+
+static void
+_e_hwc_window_target_window_render_flush_post_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   E_Hwc_Window_Target *target_hwc_window = (E_Hwc_Window_Target *)data;
+   Eina_List *ee_rendered_hw_list;
+
+   ELOGF("HWC-WINS", " ehw:%p gets render_flush_post noti ------ {@TARGET WINDOW@}", NULL, NULL, target_hwc_window);
+
+   /* all ecs have been composited so we can attach a list of composited e_thwc_windows to the surface
+    * which contains their ecs composited */
+
+   ee_rendered_hw_list = eina_list_clone(target_hwc_window->ee_rendered_hw_list);
+
+   tbm_surface_internal_set_user_data(target_hwc_window->dequeued_tsurface,
+           ee_rendered_hw_list_key, ee_rendered_hw_list);
+
+   eina_list_free(target_hwc_window->ee_rendered_hw_list);
+   target_hwc_window->ee_rendered_hw_list = NULL;
+   target_hwc_window->dequeued_tsurface = NULL;
+}
+
+static E_Hwc_Window_Target *
+_e_hwc_window_target_new(E_Output_Hwc *output_hwc)
+{
+   const char *name = NULL;
+   E_Hwc_Window_Target *target_hwc_window = NULL;
+
+   name = ecore_evas_engine_name_get(e_comp->ee);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
+
+   if (!strcmp("gl_drm", name))
+     {
+        Evas_Engine_Info_GL_Drm *einfo = NULL;
+        /* get the evas_engine_gl_drm information */
+        einfo = (Evas_Engine_Info_GL_Drm *)evas_engine_info_get(e_comp->evas);
+        if (!einfo)
+          {
+             ERR("fail to get the GL_Drm einfo.");
+             goto fail;
+          }
+        /* enable hwc to evas engine gl_drm */
+        einfo->info.hwc_enable = EINA_TRUE;
+        ecore_evas_manual_render_set(e_comp->ee, 1);
+     }
+   else if(!strcmp("gl_drm_tbm", name))
+     {
+        ecore_evas_manual_render_set(e_comp->ee, 1);
+     }
+   else if(!strcmp("drm_tbm", name))
+     {
+        ecore_evas_manual_render_set(e_comp->ee, 1);
+     }
+   else if(!strcmp("gl_tbm", name))
+     {
+        ecore_evas_manual_render_set(e_comp->ee, 1);
+     }
+   else if(!strcmp("software_tbm", name))
+     {
+        ecore_evas_manual_render_set(e_comp->ee, 1);
+     }
+
+   target_hwc_window = E_NEW(E_Hwc_Window_Target, 1);
+   EINA_SAFETY_ON_NULL_GOTO(target_hwc_window, fail);
+
+   ((E_Hwc_Window *)target_hwc_window)->is_target = EINA_TRUE;
+   ((E_Hwc_Window *)target_hwc_window)->state = E_HWC_WINDOW_STATE_DEVICE;
+   ((E_Hwc_Window *)target_hwc_window)->output_hwc = output_hwc;
+
+   target_hwc_window->ee = e_comp->ee;
+   target_hwc_window->evas = ecore_evas_get(target_hwc_window->ee);
+   target_hwc_window->event_fd = eventfd(0, EFD_NONBLOCK);
+   target_hwc_window->event_hdlr =
+            ecore_main_fd_handler_add(target_hwc_window->event_fd, ECORE_FD_READ,
+                                      _e_hwc_window_target_window_render_finished_cb,
+                                      (void *)target_hwc_window, NULL, NULL);
+
+   ecore_evas_manual_render(target_hwc_window->ee);
+
+   target_hwc_window->queue = _get_tbm_surface_queue();
+
+   /* as evas_renderer has finished its work (to provide a composited buffer) it enqueues
+    * the result buffer into this queue and acquirable cb gets called; this cb does nothing
+    * except the writing into the event_fd object, this writing causes the new ecore_main loop
+    * iteration to be triggered ('cause we've registered ecore_main fd handler to check this writing);
+    * so it's just a way to inform E20's HWC that evas_renderer has done its work */
+   tbm_surface_queue_add_acquirable_cb(target_hwc_window->queue, _e_hwc_window_target_window_surface_queue_acquirable_cb, (void *)target_hwc_window);
+
+   /* TODO: we can use this call instead of an add_acquirable_cb and an add_dequeue_cb calls. */
+   tbm_surface_queue_add_trace_cb(target_hwc_window->queue, _e_hwc_window_target_window_surface_queue_trace_cb, (void *)target_hwc_window);
+
+   evas_event_callback_add(e_comp->evas, EVAS_CALLBACK_RENDER_FLUSH_POST, _e_hwc_window_target_window_render_flush_post_cb, target_hwc_window);
+
+   /* sorry..., current version of gcc requires an initializer to be evaluated at compile time */
+   ee_rendered_hw_list_key = (uintptr_t)&ee_rendered_hw_list_key;
+
+   return target_hwc_window;
+
+fail:
+   ecore_evas_manual_render_set(e_comp->ee, 0);
+
+   return NULL;
+}
+
+static E_Hwc_Window_Target *
+_e_hwc_window_target_window_get(E_Hwc_Window *hwc_window)
+{
+   E_Hwc_Window_Target *target_hwc_window;
+   E_Output_Hwc *output_hwc;
+
+   output_hwc = hwc_window->output_hwc;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, NULL);
+
+   target_hwc_window = output_hwc->target_hwc_window;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, NULL);
+
+   return target_hwc_window;
+}
+
+static Eina_Bool
+_e_hwc_window_target_window_clear(E_Hwc_Window_Target *target_hwc_window)
+{
+   tbm_surface_queue_h tqueue = NULL;
+   tbm_surface_h tsurface = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
+
+   tqueue = target_hwc_window->queue;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(tqueue, EINA_FALSE);
+
+   while ((tsurface = _e_hwc_window_target_window_surface_acquire(target_hwc_window)))
+     _e_hwc_window_target_window_surface_release(target_hwc_window, tsurface);
+
+  return EINA_TRUE;
+}
+
+static void
+_e_hwc_window_client_cb_new(void *data EINA_UNUSED, E_Client *ec)
+{
+   E_Output *output;
+   E_Hwc_Window *hwc_window;
+   E_Zone *zone;
+
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   zone = ec->zone;
+   if (!zone)
+     {
+        ELOGF("HWC-WINS", "Try to create hwc_window, but it couldn't.(no zone)", ec->pixmap, ec);
+        return;
+     }
+
+   EINA_SAFETY_ON_NULL_RETURN(zone->output_id);
+
+   output = e_output_find(zone->output_id);
+   EINA_SAFETY_ON_NULL_RETURN(output);
+
+   /* If an e_client belongs to the e_output managed by hwc_plane policy,
+    * there's no need to deal with hwc_windows. */
+   if (e_output_hwc_policy_get(output->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
+     return;
+
+   hwc_window = e_hwc_window_new(output->output_hwc, ec, E_HWC_WINDOW_STATE_NONE);
+   EINA_SAFETY_ON_NULL_RETURN(hwc_window);
+
+   /* set the hwc window to the e client */
+   ec->hwc_window = hwc_window;
+
+   return;
+}
+
+static void
+_e_hwc_window_client_cb_del(void *data EINA_UNUSED, E_Client *ec)
+{
+   E_Output *output;
+   E_Zone *zone;
+
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   zone = ec->zone;
+   EINA_SAFETY_ON_NULL_RETURN(zone);
+   EINA_SAFETY_ON_NULL_RETURN(zone->output_id);
+
+   output = e_output_find(zone->output_id);
+   EINA_SAFETY_ON_NULL_RETURN(output);
+
+   /* If an e_client belongs to the e_output managed by hwc_plane policy,
+    * there's no need to deal with hwc_windows. */
+   if (e_output_hwc_policy_get(output->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
+     return;
+
+   if (!ec->hwc_window) return;
+
+   e_hwc_window_free(ec->hwc_window);
+   ec->hwc_window = NULL;
+}
+
+static Eina_Bool
+_e_hwc_window_client_cb_zone_set(void *data, int type, void *event)
+{
+   E_Event_Client *ev;
+   E_Client *ec;
+   E_Zone *zone;
+   E_Output *output;
+   E_Hwc_Window *hwc_window = NULL;
+
+   ev = event;
+   EINA_SAFETY_ON_NULL_GOTO(ev, end);
+
+   ec = ev->ec;
+   EINA_SAFETY_ON_NULL_GOTO(ec, end);
+
+   zone = ec->zone;
+   EINA_SAFETY_ON_NULL_GOTO(zone, end);
+   EINA_SAFETY_ON_NULL_GOTO(zone->output_id, end);
+
+   output = e_output_find(zone->output_id);
+   EINA_SAFETY_ON_NULL_GOTO(output, end);
+
+   /* If an e_client belongs to the e_output managed by hwc_plane policy,
+    * there's no need to deal with hwc_windows. */
+   if (e_output_hwc_policy_get(output->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
+      return ECORE_CALLBACK_PASS_ON;
+
+   if (ec->hwc_window)
+     {
+        /* we manage the video window in the video module */
+        if (e_hwc_window_is_video(ec->hwc_window)) goto end;
+        if (ec->hwc_window->output_hwc == output->output_hwc) goto end;
+
+        e_hwc_window_free(ec->hwc_window);
+        ec->hwc_window = NULL;
+     }
+
+   hwc_window = e_hwc_window_new(output->output_hwc, ec, E_HWC_WINDOW_STATE_NONE);
+   EINA_SAFETY_ON_NULL_GOTO(hwc_window, end);
+
+   /* set the hwc window to the e client */
+   ec->hwc_window = hwc_window;
+
+   ELOGF("HWC-WINS", "ehw:%p is set on eout:%p, zone_id:%d.",
+         hwc_window->ec ? ec->pixmap : NULL, hwc_window->ec,
+         hwc_window, output, zone->id);
+
+end:
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static tbm_surface_h
+_e_hwc_window_client_surface_acquire(E_Hwc_Window *hwc_window)
+{
+   E_Comp_Wl_Buffer *buffer = _e_hwc_window_comp_wl_buffer_get(hwc_window);
+   E_Comp_Wl_Data *wl_comp_data = (E_Comp_Wl_Data *)e_comp->wl_comp_data;
+   tbm_surface_h tsurface = NULL;
+
+   if (!buffer)
+   {
+      ELOGF("HWC-WINS", "[soolim] ehw:%p E_Comp_Wl_Buffer is null.",
+            hwc_window->ec ? ec->pixmap : NULL, hwc_window->ec,
+            hwc_window);
+      return NULL;
+   }
+
+   tsurface = wayland_tbm_server_get_surface(wl_comp_data->tbm.server, buffer->resource);
+   if (!tsurface)
+     {
+        ERR("fail to wayland_tbm_server_get_surface");
+        return NULL;
+     }
+
+   return tsurface;
+}
+
+
+static void
+_e_hwc_window_client_recover(E_Hwc_Window *hwc_window)
+{
+   E_Client *ec = hwc_window->ec;
+   E_Comp_Wl_Client_Data *cdata = NULL;
+   E_Comp_Wl_Buffer *buffer = NULL;
+   tbm_surface_h tsurface =NULL;
+
+   if (!ec) return;
+
+   cdata = ec->comp_data;
+   if (!cdata) return;
+
+   buffer = cdata->buffer_ref.buffer;
+
+   if (!buffer)
+     {
+        tsurface = e_hwc_window_displaying_surface_get(hwc_window);
+        if (!tsurface) return;
+
+        tbm_surface_internal_ref(tsurface);
+        buffer = e_comp_wl_tbm_buffer_get(tsurface);
+        if (!buffer)
+          {
+             tbm_surface_internal_unref(tsurface);
+             return;
+          }
+     }
+
+   /* force update */
+   e_pixmap_resource_set(ec->pixmap, buffer);
+   e_pixmap_dirty(ec->pixmap);
+   e_pixmap_refresh(ec->pixmap);
+
+   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);
+
+   return;
+}
+
+static void
+_e_hwc_window_cursor_image_draw(E_Comp_Wl_Buffer *buffer, tbm_surface_info_s *tsurface_info, int rotation)
+{
+   int src_width, src_height, src_stride;
+   pixman_image_t *src_img = NULL, *dst_img = NULL;
+   pixman_transform_t t;
+   struct pixman_f_transform ft;
+   void *src_ptr = NULL, *dst_ptr = NULL;
+   int c = 0, s = 0, tx = 0, ty = 0;
+   int i, rotate;
+
+   src_width = wl_shm_buffer_get_width(buffer->shm_buffer);
+   src_height = wl_shm_buffer_get_height(buffer->shm_buffer);
+   src_stride = wl_shm_buffer_get_stride(buffer->shm_buffer);
+   src_ptr = wl_shm_buffer_get_data(buffer->shm_buffer);
+
+   dst_ptr = tsurface_info->planes[0].ptr;
+   memset(dst_ptr, 0, tsurface_info->planes[0].stride * tsurface_info->height);
+
+   if (rotation)
+     {
+        src_img = pixman_image_create_bits(PIXMAN_a8r8g8b8, src_width, src_height, (uint32_t*)src_ptr, src_stride);
+        EINA_SAFETY_ON_NULL_GOTO(src_img, error);
+
+        dst_img = pixman_image_create_bits(PIXMAN_a8r8g8b8, tsurface_info->width, tsurface_info->height,
+                                          (uint32_t*)dst_ptr, tsurface_info->planes[0].stride);
+        EINA_SAFETY_ON_NULL_GOTO(dst_img, error);
+
+        if (rotation == 90)
+           rotation = 270;
+        else if (rotation == 270)
+           rotation = 90;
+
+        rotate = (rotation + 360) / 90 % 4;
+        switch (rotate)
+          {
+           case 1:
+              c = 0, s = -1, tx = -tsurface_info->width;
+              break;
+           case 2:
+              c = -1, s = 0, tx = -tsurface_info->width, ty = -tsurface_info->height;
+              break;
+           case 3:
+              c = 0, s = 1, ty = -tsurface_info->width;
+              break;
+          }
+
+        pixman_f_transform_init_identity(&ft);
+        pixman_f_transform_translate(&ft, NULL, tx, ty);
+        pixman_f_transform_rotate(&ft, NULL, c, s);
+
+        pixman_transform_from_pixman_f_transform(&t, &ft);
+        pixman_image_set_transform(src_img, &t);
+
+        pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img, 0, 0, 0, 0, 0, 0,
+                               tsurface_info->width, tsurface_info->height);
+     }
+   else
+     {
+        for (i = 0 ; i < src_height ; i++)
+          {
+             memcpy(dst_ptr, src_ptr, src_stride);
+             dst_ptr += tsurface_info->planes[0].stride;
+             src_ptr += src_stride;
+          }
+     }
+
+error:
+   if (src_img) pixman_image_unref(src_img);
+   if (dst_img) pixman_image_unref(dst_img);
+}
+
+static Eina_Bool
+_e_hwc_window_cursor_surface_refresh(E_Hwc_Window *hwc_window, E_Pointer *pointer)
+{
+   E_Output_Hwc *output_hwc = NULL;
+   E_Output *output = NULL;
+   int w, h, tw, th;
+   int tsurface_w, tsurface_h;
+   void *src_ptr = NULL;
+   tbm_surface_h tsurface = NULL;
+   E_Comp_Wl_Buffer *buffer = NULL;
+   tbm_surface_error_e ret = TBM_SURFACE_ERROR_NONE;
+   tbm_surface_info_s tsurface_info;
+   E_Client *ec;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+   ec = hwc_window->ec;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
+
+   output_hwc = hwc_window->output_hwc;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, EINA_FALSE);
+
+   output = output_hwc->output;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
+
+   buffer = ec->comp_data->buffer_ref.buffer;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(buffer, EINA_FALSE);
+
+   if ((hwc_window->display_info.buffer_ref.buffer == buffer) &&
+       (hwc_window->cursor_tsurface) &&
+       (hwc_window->cursor_rotation == pointer->rotation))
+     return EINA_TRUE;
+
+   /* TODO: TBM TYPE, NATIVE_WL */
+   if (buffer->type == E_COMP_WL_BUFFER_TYPE_SHM)
+     {
+        src_ptr = wl_shm_buffer_get_data(buffer->shm_buffer);
+        if (!src_ptr)
+          {
+             ERR("Failed get data shm buffer");
+             return EINA_FALSE;
+          }
+     }
+   else
+     {
+        ERR("unkown buffer type:%d", ec->comp_data->buffer_ref.buffer->type);
+        return EINA_FALSE;
+     }
+
+   if (pointer->rotation == 90)
+      tw = ec->h, th = ec->w;
+   else if (pointer->rotation == 180)
+      tw = ec->w, th = ec->h;
+   else if (pointer->rotation == 270)
+      tw = ec->h, th = ec->w;
+   else
+      tw = ec->w, th = ec->h;
+
+   hwc_window->cursor_rotation = pointer->rotation;
+
+   w = (output->cursor_available.min_w > tw) ? output->cursor_available.min_w : tw;
+   h = (output->cursor_available.min_h > th) ? output->cursor_available.min_h : th;
+
+   if (e_comp->hwc_reuse_cursor_buffer)
+     {
+        if (hwc_window->cursor_tsurface)
+          {
+             tsurface_w = tbm_surface_get_width(hwc_window->cursor_tsurface);
+             tsurface_h = tbm_surface_get_height(hwc_window->cursor_tsurface);
+
+             if (w != tsurface_w || h != tsurface_h)
+               {
+                  tbm_surface_destroy(hwc_window->cursor_tsurface);
+                  hwc_window->cursor_tsurface = NULL;
+               }
+          }
+     }
+   else
+     {
+        if (hwc_window->cursor_tsurface)
+          {
+             tbm_surface_destroy(hwc_window->cursor_tsurface);
+             hwc_window->cursor_tsurface = NULL;
+          }
+     }
+
+   if (!hwc_window->cursor_tsurface)
+     {
+        /* Which tbm flags should be used? */
+        tsurface = tbm_surface_internal_create_with_flags(w, h, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
+        if (!tsurface) return EINA_FALSE;
+     }
+   else
+     {
+        tsurface = hwc_window->cursor_tsurface;
+     }
+
+   ret = tbm_surface_map(tsurface, TBM_SURF_OPTION_WRITE, &tsurface_info);
+   if (ret != TBM_SURFACE_ERROR_NONE)
+     {
+        ERR("Failed to map tsurface");
+        tbm_surface_destroy(tsurface);
+        return EINA_FALSE;
+     }
+
+   _e_hwc_window_cursor_image_draw(buffer, &tsurface_info, pointer->rotation);
+
+   tbm_surface_unmap(tsurface);
+
+   hwc_window->cursor_tsurface = tsurface;
+
+   /* to set the hwc_window_cursor_tsurface to the hwc_window->tsurface */
+   e_comp_object_hwc_update_set(ec->frame, EINA_TRUE);
+
+   return EINA_TRUE;
+}
+
+static tbm_surface_h
+_e_hwc_window_cursor_surface_acquire(E_Hwc_Window *hwc_window)
+{
+   tbm_surface_h tsurface = NULL;
+   E_Client *ec = hwc_window->ec;
+   E_Comp_Wl_Buffer *buffer = NULL;
+   E_Pointer *pointer = NULL;
+
+   pointer = e_pointer_get(ec);
+   if (!pointer)
+     {
+        ELOGF("HWC-WINS", "[soolim] ehw:%p Pointer is null.(Cursor)",
+             hwc_window->ec ? ec->pixmap : NULL, hwc_window->ec,
+             hwc_window);
+        return NULL;
+     }
+
+   buffer = ec->comp_data->buffer_ref.buffer;
+   if (!buffer)
+     {
+        ELOGF("HWC-WINS", "[soolim] ehw:%p E_Comp_Wl_Buffer is null.(Cursor)",
+             hwc_window->ec ? ec->pixmap : NULL, hwc_window->ec,
+             hwc_window);
+        return NULL;
+     }
+#if 1
+   if (hwc_window->cursor_tsurface) return hwc_window->cursor_tsurface;
+#else
+   /* return the exist tsurface when there is no update on cursor image(pointer image) */
+   if (!e_comp_object_hwc_update_exists(ec->frame) && hwc_window->tsurface)
+     return hwc_window->tsurface;
+#endif
+
+   //e_comp_object_hwc_update_set(ec->frame, EINA_FALSE);
+
+   if (!_e_hwc_window_cursor_surface_refresh(hwc_window, pointer))
+     {
+        ERR("Failed to _e_hwc_window_cursor_surface_refresh");
+        return NULL;
+     }
+
+   tsurface = hwc_window->cursor_tsurface;
+
+   return tsurface;
+}
+
+static Eina_Bool
+_e_hwc_window_info_set(E_Hwc_Window *hwc_window, tbm_surface_h tsurface)
+{
+   E_Output_Hwc *output_hwc = hwc_window->output_hwc;
+   E_Output *output = output_hwc->output;
+   E_Client *ec = hwc_window->ec;
+   tbm_surface_info_s surf_info;
+   int size_w, size_h, src_x, src_y, src_w, src_h;
+   int dst_x, dst_y, dst_w, dst_h;
+   tbm_format format;
+   tdm_hwc_window_info hwc_win_info = {0};
+   tdm_error error;
+
+   if (e_hwc_window_is_video(hwc_window))
+     {
+        if (!e_comp_wl_video_hwc_window_info_get(hwc_window, &hwc_win_info))
+          {
+             ERR("Video window does not get the hwc_win_info.");
+             return EINA_FALSE;
+          }
+
+        error = tdm_hwc_window_set_info(hwc_window->thwc_window, &hwc_win_info);
+        EINA_SAFETY_ON_TRUE_RETURN_VAL(error != TDM_ERROR_NONE, EINA_FALSE);
+
+        return EINA_TRUE;
+     }
+
+   /* set hwc_window when the layer infomation is different from the previous one */
+   tbm_surface_get_info(tsurface, &surf_info);
+
+   format = surf_info.format;
+
+   size_w = _get_aligned_width(tsurface);
+   EINA_SAFETY_ON_TRUE_RETURN_VAL(size_w == 0, EINA_FALSE);
+
+   size_h = surf_info.height;
+
+   src_x = 0;
+   src_y = 0;
+   src_w = surf_info.width;
+   src_h = surf_info.height;
+
+   if (e_hwc_window_is_cursor(hwc_window))
+     {
+        E_Pointer *pointer = e_pointer_get(ec);
+        if (!pointer)
+          {
+             ERR("ec doesn't have E_Pointer");
+             return EINA_FALSE;
+          }
+
+        dst_x = pointer->x - pointer->hot.x;
+        dst_y = pointer->y - pointer->hot.y;
+     }
+   else
+     {
+        dst_x = ec->x;
+        dst_y = ec->y;
+     }
+
+   /* if output is transformed, the position of a buffer on screen should be also
+   * transformed.
+   */
+   if (output->config.rotation > 0)
+     {
+        int bw, bh;
+        e_pixmap_size_get(ec->pixmap, &bw, &bh);
+        e_comp_wl_rect_convert(ec->zone->w, ec->zone->h,
+                               output->config.rotation / 90, 1,
+                               dst_x, dst_y, bw, bh,
+                               &dst_x, &dst_y, NULL, NULL);
+     }
+
+   dst_w = surf_info.width;
+   dst_h = surf_info.height;
+
+   if (hwc_window->info.src_config.size.h != size_w ||
+            hwc_window->info.src_config.size.v != size_h ||
+            hwc_window->info.src_config.pos.x != src_x ||
+            hwc_window->info.src_config.pos.y != src_y ||
+            hwc_window->info.src_config.pos.w != src_w ||
+            hwc_window->info.src_config.pos.h != src_h ||
+            hwc_window->info.src_config.format != format ||
+            hwc_window->info.dst_pos.x != dst_x ||
+            hwc_window->info.dst_pos.y != dst_y ||
+            hwc_window->info.dst_pos.w != dst_w ||
+            hwc_window->info.dst_pos.h != dst_h)
+     {
+        tdm_error error;
+
+        /* change the information at plane->info */
+        hwc_window->info.src_config.size.h = size_w;
+        hwc_window->info.src_config.size.v = size_h;
+        hwc_window->info.src_config.pos.x = src_x;
+        hwc_window->info.src_config.pos.y = src_y;
+        hwc_window->info.src_config.pos.w = src_w;
+        hwc_window->info.src_config.pos.h = src_h;
+        hwc_window->info.dst_pos.x = dst_x;
+        hwc_window->info.dst_pos.y = dst_y;
+        hwc_window->info.dst_pos.w = dst_w;
+        hwc_window->info.dst_pos.h = dst_h;
+        hwc_window->info.transform = TDM_TRANSFORM_NORMAL;
+        hwc_window->info.src_config.format = format;
+
+        error = tdm_hwc_window_set_info(hwc_window->thwc_window, &hwc_window->info);
+        EINA_SAFETY_ON_TRUE_RETURN_VAL(error != TDM_ERROR_NONE, EINA_FALSE);
+     }
+
+   return EINA_TRUE;
+}
+
+#if 0
+static Eina_Bool
+_e_hwc_window_correct_transformation_check(E_Hwc_Window *hwc_window)
+{
+   E_Client *ec;
+   int transform;
+   E_Output_Hwc *output_hwc = hwc_window->output_hwc;
+   E_Output *output = output_hwc->output;
+
+   /* do not check the transformation of the video window */
+   if (e_hwc_window_is_video(hwc_window)) return EINA_TRUE;
+
+   ec = hwc_window->ec;
+
+   transform = e_comp_wl_output_buffer_transform_get(ec);
+
+   /* request an ec to change its transformation if it doesn't fit the transformation */
+   if ((output->config.rotation / 90) != transform)
+     {
+        if (!e_config->screen_rotation_client_ignore && hwc_window->need_change_buffer_transform)
+          {
+             hwc_window->need_change_buffer_transform = EINA_FALSE;
+
+             /* TODO: why e_comp_wl_output_init() call ins't enough? why additional
+              * tizen_screen_rotation_send_ignore_output_transform() call is needed? */
+             e_comp_screen_rotation_ignore_output_transform_send(ec, EINA_FALSE);
+
+             ELOGF("HWC-WINS", " request {%25s} to change transformation to %d.",
+                     ec->pixmap, ec, ec->icccm.title, output->config.rotation);
+          }
+
+        return EINA_FALSE;
+     }
+   else
+      hwc_window->need_change_buffer_transform = EINA_TRUE;
+
+   return EINA_TRUE;
+}
+#endif
+
+EINTERN Eina_Bool
+e_hwc_window_init(E_Output_Hwc *output_hwc)
+{
+   E_Hwc_Window_Target *target_hwc_window;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, EINA_FALSE);
+
+   if (e_output_hwc_policy_get(output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
+     return EINA_FALSE;
+
+   client_hook_new =  e_client_hook_add(E_CLIENT_HOOK_NEW_CLIENT,
+                                        _e_hwc_window_client_cb_new, NULL);
+   if (!client_hook_new)
+     {
+        ERR("fail to add the E_CLIENT_HOOK_NEW_CLIENT hook.");
+        return EINA_FALSE;
+     }
+   client_hook_del =  e_client_hook_add(E_CLIENT_HOOK_DEL,
+                                        _e_hwc_window_client_cb_del, NULL);
+   if (!client_hook_del)
+     {
+        ERR("fail to add the E_CLIENT_HOOK_DEL hook.");
+        return EINA_FALSE;
+     }
+
+   zone_set_event_handler =
+            ecore_event_handler_add(E_EVENT_CLIENT_ZONE_SET, _e_hwc_window_client_cb_zone_set, NULL);
+   if (!zone_set_event_handler)
+     {
+        ERR("fail to add the E_EVENT_CLIENT_ZONE_SET event handler.");
+        return EINA_FALSE;
+     }
+
+   target_hwc_window = _e_hwc_window_target_new(output_hwc);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
+
+   /* set the target_window to the output_hwc */
+   output_hwc->target_hwc_window = target_hwc_window;
+
+   output_hwc->hwc_windows = eina_list_append(output_hwc->hwc_windows, target_hwc_window);
+
+   return EINA_TRUE;
+}
+
+// TODO:
+EINTERN void
+e_hwc_window_deinit(E_Output_Hwc *output_hwc)
+{
+   EINA_SAFETY_ON_NULL_RETURN(output_hwc);
+
+   // TODO:
+}
+
+EINTERN E_Hwc_Window *
+e_hwc_window_new(E_Output_Hwc *output_hwc, E_Client *ec, E_Hwc_Window_State state)
+{
+   E_Hwc_Window *hwc_window = NULL;
+   tdm_output *toutput;
+   tdm_error error;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc->output, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
+
+   toutput = output_hwc->output->toutput;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(toutput, EINA_FALSE);
+
+   hwc_window = E_NEW(E_Hwc_Window, 1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, NULL);
+
+   hwc_window->output_hwc = output_hwc;
+   hwc_window->ec = ec;
+   hwc_window->state = state;
+   hwc_window->need_change_buffer_transform = EINA_TRUE;
+
+   if (state == E_HWC_WINDOW_STATE_VIDEO)
+     hwc_window->thwc_window = tdm_output_hwc_create_video_window(toutput, &error);
+   else
+     hwc_window->thwc_window = tdm_output_hwc_create_window(toutput, &error);
+   if (error != TDM_ERROR_NONE)
+     {
+        ERR("cannot create tdm_hwc_window for toutput(%p)", toutput);
+        E_FREE(hwc_window);
+        return NULL;
+     }
+
+   /* cursor window */
+   if (e_policy_client_is_cursor(ec))
+     hwc_window->is_cursor = EINA_TRUE;
+
+   /* video window */
+   if (state == E_HWC_WINDOW_STATE_VIDEO)
+     hwc_window->is_video = EINA_TRUE;
+
+   output_hwc->hwc_windows = eina_list_append(output_hwc->hwc_windows, hwc_window);
+
+   ELOGF("HWC-WINS", "ehw:%p is created on eout:%p, zone_id:%d",
+         hwc_window->ec ? hwc_window->ec->pixmap : NULL, hwc_window->ec,
+         hwc_window, output_hwc->output, ec->zone->id);
+
+   return hwc_window;
+}
+
+EINTERN void
+e_hwc_window_free(E_Hwc_Window *hwc_window)
+{
+   E_Output_Hwc *output_hwc = NULL;
+   E_Output *output = NULL;
+   tdm_output *toutput = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN(hwc_window);
+   EINA_SAFETY_ON_NULL_RETURN(hwc_window->output_hwc);
+
+   output_hwc = hwc_window->output_hwc;
+   EINA_SAFETY_ON_NULL_RETURN(output_hwc);
+
+   output = output_hwc->output;
+   EINA_SAFETY_ON_NULL_RETURN(output_hwc->output);
+
+   toutput = output->toutput;
+   EINA_SAFETY_ON_NULL_RETURN(toutput);
+
+   /* we cannot remove the hwc_window because we need to release the commit_data */
+   if (e_hwc_window_displaying_surface_get(hwc_window))
+     {
+        ELOGF("HWC-WINS", "ehw:%p is destroyed on eout:%p. displaying surface.",
+              hwc_window->ec ? hwc_window->ec->pixmap : NULL, hwc_window->ec,
+              hwc_window, output_hwc->output);
+
+        /* mark as deleted and delete when commit_data will be released */
+        hwc_window->is_deleted = EINA_TRUE;
+        hwc_window->ec = NULL;
+        e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE);
+        return;
+     }
+   else
+     ELOGF("HWC-WINS", "ehw:%p is destroyed on eout:%p",
+           hwc_window->ec ? hwc_window->ec->pixmap : NULL, hwc_window->ec,
+           hwc_window, output_hwc->output);
+
+   if (hwc_window->thwc_window)
+      tdm_output_hwc_destroy_window(toutput, hwc_window->thwc_window);
+
+   output_hwc->hwc_windows = eina_list_remove(output_hwc->hwc_windows, hwc_window);
+
+   free(hwc_window);
+}
+
+EINTERN Eina_Bool
+e_hwc_window_zpos_set(E_Hwc_Window *hwc_window, int zpos)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+   if (hwc_window->zpos != zpos) hwc_window->zpos = zpos;
+
+   return EINA_TRUE;
+}
+
+EINTERN int
+e_hwc_window_zpos_get(E_Hwc_Window *hwc_window)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+   if (hwc_window->state == E_HWC_WINDOW_STATE_NONE) return -999;
+
+   return hwc_window->zpos;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_compsition_update(E_Hwc_Window *hwc_window)
+{
+   tdm_hwc_window *thwc_window;
+   tdm_hwc_window_composition composition_type;
+   tdm_error error;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+   if (e_hwc_window_is_target(hwc_window))
+   {
+      ERR("HWC-WINS: target window cannot update at e_hwc_window_compsition_update.");
+      return EINA_FALSE;
+   }
+
+   thwc_window = hwc_window->thwc_window;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(thwc_window, EINA_FALSE);
+
+   /* set composition type */
+   composition_type = _get_composition_type(hwc_window->state);
+   error = tdm_hwc_window_set_composition_type(hwc_window->thwc_window, composition_type);
+   EINA_SAFETY_ON_TRUE_RETURN_VAL(error != TDM_ERROR_NONE, EINA_FALSE);
+
+   return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_buffer_update(E_Hwc_Window *hwc_window)
+{
+   tbm_surface_h tsurface = NULL;
+   tdm_hwc_window *thwc_window;
+   tdm_error error;
+   Eina_Bool result;
+
+   thwc_window = hwc_window->thwc_window;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(thwc_window, EINA_FALSE);
+
+   tsurface = hwc_window->tsurface;
+   if (tsurface)
+     {
+        /* set window info */
+        result = _e_hwc_window_info_set(hwc_window, tsurface);
+        EINA_SAFETY_ON_TRUE_RETURN_VAL(result != EINA_TRUE, EINA_FALSE);
+     }
+
+   /* set buffer */
+   error = tdm_hwc_window_set_buffer(thwc_window, hwc_window->tsurface);
+   EINA_SAFETY_ON_TRUE_RETURN_VAL(error != TDM_ERROR_NONE, EINA_FALSE);
+
+   return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_is_target(E_Hwc_Window *hwc_window)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+   return hwc_window->is_target;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_is_video(E_Hwc_Window *hwc_window)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+   return hwc_window->is_video;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_is_cursor(E_Hwc_Window *hwc_window)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+   return hwc_window->is_cursor;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_buffer_fetch(E_Hwc_Window *hwc_window)
+{
+   tbm_surface_h tsurface = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+   if (hwc_window->is_deleted)
+     {
+        hwc_window->tsurface = NULL;
+        hwc_window->update_exist = EINA_TRUE;
+        return EINA_TRUE;
+     }
+
+   /* set the buffer to be null  */
+   if (hwc_window->state == E_HWC_WINDOW_STATE_NONE)
+     {
+        if (hwc_window->cursor_tsurface)
+          {
+             tbm_surface_destroy(hwc_window->cursor_tsurface);
+             hwc_window->cursor_tsurface = NULL;
+          }
+
+        if (hwc_window->tsurface == NULL) return EINA_FALSE;
+
+        hwc_window->update_exist = EINA_TRUE;
+        hwc_window->tsurface = NULL;
+     }
+   else
+     {
+        /* for video we set buffer in the video module */
+        if (e_hwc_window_is_video(hwc_window))
+          {
+             tsurface = e_comp_wl_video_hwc_widow_surface_get(hwc_window);
+             if (!tsurface)
+                {
+                   ELOGF("HWC-WINS", " ehw:%p no video buffer yet -- {%25s}, state:%s, zpos:%d, deleted:%s (Video)",
+                         hwc_window->ec ? hwc_window->ec->pixmap : NULL, hwc_window->ec,
+                         hwc_window, hwc_window->ec ? hwc_window->ec->icccm.title : "UNKNOWN",
+                         e_hwc_window_state_string_get(hwc_window->state),
+                         hwc_window->zpos, hwc_window->is_deleted ? "yes" : "no");
+                   return EINA_FALSE;
+                }
+             hwc_window->update_exist = EINA_TRUE;
+
+             ELOGF("HWC-WINS", " ehw:%p sets ts:%10p ------- {%25s}, state:%s, zpos:%d, deleted:%s (Video)",
+                   hwc_window->ec ? hwc_window->ec->pixmap : NULL, hwc_window->ec,
+                   hwc_window, tsurface, hwc_window->ec ? hwc_window->ec->icccm.title : "UNKNOWN",
+                   e_hwc_window_state_string_get(hwc_window->state),
+                   hwc_window->zpos, hwc_window->is_deleted ? "yes" : "no");
+          }
+        else if (e_hwc_window_is_cursor(hwc_window))
+          {
+             tsurface = _e_hwc_window_cursor_surface_acquire(hwc_window);
+             if (!tsurface)
+               {
+                  ELOGF("HWC-WINS", " ehw:%10p cursor buffer is null.",
+                        hwc_window->ec ? ec->pixmap : NULL, hwc_window->ec, hwc_window);
+                  return EINA_FALSE;
+               }
+            if (!e_comp_object_hwc_update_exists(hwc_window->ec->frame)) return EINA_FALSE;
+
+            e_comp_object_hwc_update_set(hwc_window->ec->frame, EINA_FALSE);
+            hwc_window->update_exist = EINA_TRUE;
+
+            ELOGF("HWC-WINS", " ehw:%p sets ts:%10p ------- {%25s}, state:%s, zpos:%d, deleted:%s (Cusor)",
+                  hwc_window->ec ? hwc_window->ec->pixmap : NULL, hwc_window->ec,
+                  hwc_window, tsurface, hwc_window->ec ? hwc_window->ec->icccm.title : "UNKNOWN",
+                  e_hwc_window_state_string_get(hwc_window->state),
+                  hwc_window->zpos, hwc_window->is_deleted ? "yes" : "no");
+          }
+        else
+          {
+             /* acquire the surface */
+             tsurface = _e_hwc_window_client_surface_acquire(hwc_window);
+             if (!tsurface)
+               {
+                  ELOGF("HWC-WINS", " ehw:%p client buffer is null.",
+                        hwc_window->ec ? ec->pixmap : NULL, hwc_window->ec, hwc_window);
+                  return EINA_FALSE;
+               }
+             if (tsurface == hwc_window->tsurface) return EINA_FALSE;
+
+             hwc_window->update_exist = EINA_TRUE;
+
+             ELOGF("HWC-WINS", " ehw:%p sets ts:%10p ------- {%25s}, state:%s, zpos:%d, deleted:%s (Window)",
+                   hwc_window->ec ? hwc_window->ec->pixmap : NULL, hwc_window->ec,
+                   hwc_window, tsurface, hwc_window->ec ? hwc_window->ec->icccm.title : "UNKNOWN",
+                   e_hwc_window_state_string_get(hwc_window->state),
+                   hwc_window->zpos, hwc_window->is_deleted ? "yes" : "no");
+          }
+     }
+
+   /* exist tsurface for update hwc_window */
+   hwc_window->tsurface = tsurface;
+
+   return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_commit_data_aquire(E_Hwc_Window *hwc_window)
+{
+   E_Hwc_Window_Commit_Data *commit_data = NULL;
+
+
+   if (hwc_window->update_exist == EINA_FALSE) return EINA_FALSE;
+
+#if 0
+   if (!e_hwc_window_is_on_hw_overlay(hwc_window))
+     {
+        hwc_window->update_exist = EINA_FALSE;
+
+        /* right after an hwc_window's type has been changed from DEVICE to CLIENT
+         * we have to wait till hwc_window's buffer being composited to target_buffer
+         * and this target_buffer gets scheduled and only after this we can issue
+         * a 'fake commit_data' request to allow tdm_commit() to be called to unset
+         * an underlying hw overlay;
+         * target_wnd's hwc can't ever be at target_wnd :), so we pass it immediately */
+        if (e_hwc_window_displaying_surface_get(hwc_window) &&
+            !_e_hwc_window_is_device_to_client_transition(hwc_window))
+          {
+             commit_data = E_NEW(E_Hwc_Window_Commit_Data, 1);
+             EINA_SAFETY_ON_NULL_RETURN_VAL(commit_data, EINA_FALSE);
+
+             hwc_window->commit_data = commit_data;
+             hwc_window->is_device_to_client_transition = EINA_FALSE;
+
+             return EINA_TRUE;
+          }
+
+        return EINA_FALSE;
+     }
+
+   /* If there are not updates and there is not displaying surface, it means the
+    * hwc_window's composition type just became TDM_COMPOSITION_DEVICE. Buffer
+    * for this hwc_window was set in the previous e_hwc_window_buffer_fetch but ref for
+    * buffer didn't happen because hwc_window had TDM_COMPOSITION_CLIENT type.
+    * So e20 needs to make ref for the current buffer which is set on the hwc_window.
+    */
+   if (!hwc_window->update_exist && e_hwc_window_displaying_surface_get(hwc_window))
+     {
+        return EINA_FALSE;
+     }
+#endif
+
+   commit_data = E_NEW(E_Hwc_Window_Commit_Data, 1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(commit_data, EINA_FALSE);
+
+   /* fake commit data for free the e_hwc_window resource */
+   if (hwc_window->is_deleted) goto done;
+
+   if (e_hwc_window_is_target(hwc_window) ||
+       e_hwc_window_is_video(hwc_window))
+     {
+        commit_data->tsurface = hwc_window->tsurface;
+        tbm_surface_internal_ref(commit_data->tsurface);
+     }
+   else
+     {
+        commit_data->tsurface = hwc_window->tsurface;
+        tbm_surface_internal_ref(commit_data->tsurface);
+
+        e_comp_wl_buffer_reference(&commit_data->buffer_ref, _e_hwc_window_comp_wl_buffer_get(hwc_window));
+     }
+
+done:
+   hwc_window->commit_data = commit_data;
+   hwc_window->update_exist = EINA_FALSE;
+
+   return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_commit_data_release(E_Hwc_Window *hwc_window)
+{
+   tbm_surface_h tsurface = NULL;
+   tbm_surface_h displaying_surface;
+
+   /* we don't have data to release */
+   if (!hwc_window->commit_data) return EINA_FALSE;
+
+   if (hwc_window->is_deleted)
+     {
+        displaying_surface = e_hwc_window_displaying_surface_get(hwc_window);
+        if (displaying_surface) tbm_surface_internal_unref(displaying_surface);
+        hwc_window->display_info.tsurface = NULL;
+
+        free(hwc_window->commit_data);
+        e_hwc_window_free(hwc_window);
+     }
+   else
+     {
+        tsurface = hwc_window->commit_data->tsurface;
+
+        if (!tsurface)
+          {
+             e_comp_wl_buffer_reference(&hwc_window->display_info.buffer_ref, NULL);
+          }
+        else if (e_hwc_window_is_target(hwc_window) || e_hwc_window_is_video(hwc_window))
+          {
+             e_comp_wl_buffer_reference(&hwc_window->display_info.buffer_ref, NULL);
+          }
+        else
+          {
+             e_comp_wl_buffer_reference(&hwc_window->display_info.buffer_ref, hwc_window->commit_data->buffer_ref.buffer);
+          }
+
+        e_comp_wl_buffer_reference(&hwc_window->commit_data->buffer_ref, NULL);
+
+        /* release and unreference the previous surface */
+        displaying_surface = e_hwc_window_displaying_surface_get(hwc_window);
+        if (displaying_surface)
+          {
+             if (e_hwc_window_is_target(hwc_window))
+               {
+                  _e_hwc_window_target_window_surface_release((E_Hwc_Window_Target *)hwc_window, displaying_surface);
+               }
+             tbm_surface_internal_unref(displaying_surface);
+          }
+
+        /* update hwc_window display info */
+        hwc_window->display_info.tsurface = tsurface;
+
+        free(hwc_window->commit_data);
+        hwc_window->commit_data = NULL;
+     }
+
+   return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_target_surface_queue_can_dequeue(E_Hwc_Window_Target *target_hwc_window)
+{
+   tbm_surface_queue_h tqueue = NULL;
+   int num_free = 0;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
+
+   tqueue = target_hwc_window->queue;
+   if (!tqueue)
+     {
+        WRN("tbm_surface_queue is NULL");
+        return EINA_FALSE;
+     }
+
+   num_free = tbm_surface_queue_can_dequeue(tqueue, 0);
+
+   if (num_free <= 0) return EINA_FALSE;
+
+   return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_target_enabled(E_Hwc_Window_Target *target_hwc_window)
+{
+   E_Hwc_Window *hwc_window;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
+
+   hwc_window = (E_Hwc_Window *)target_hwc_window;
+
+   if (hwc_window->state != E_HWC_WINDOW_STATE_DEVICE)
+      return EINA_FALSE;
+
+   return EINA_TRUE;
+}
+
+/* set the tsurface to the target_window->tsurface according to the state.
+ *  1. try to set the tsurface to the target_window at E_HWC_WINDOW_STATE_DEVICE.
+ *  2. try to set NULL and release(clear) tsurface_queue of the target_window at E_HWC_WINDOW_STATE_NONE.
+ *  Returing EINA_FALSE means that there is no update for the target_window->tsurface.
+ **/
+EINTERN Eina_Bool
+e_hwc_window_target_buffer_fetch(E_Hwc_Window_Target *target_hwc_window)
+{
+   E_Output *output;
+   E_Output_Hwc *output_hwc;
+   E_Hwc_Window *hwc_window, *hw;
+   tbm_surface_h tsurface;
+   tdm_hwc_region fb_damage;
+   Eina_List *ee_rendered_hw_list = NULL;
+   uint32_t n_thw = 0;
+   const Eina_List *l;
+   int i;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
+
+   hwc_window = (E_Hwc_Window *)target_hwc_window;
+
+   hwc_window->update_exist = EINA_FALSE;
+
+   if (hwc_window->state == E_HWC_WINDOW_STATE_DEVICE)
+     {
+        /* acquire the surface */
+        tsurface = _e_hwc_window_target_window_surface_acquire((E_Hwc_Window_Target *)hwc_window);
+        if (!tsurface)
+          {
+             //ELOGF("HWC-WINS", " the surface of target is null.(E_HWC_WINDOW_STATE_DEVICE)", NULL, NULL);
+             return EINA_FALSE;
+          }
+        if (tsurface == hwc_window->tsurface)
+          {
+             //ELOGF("HWC-WINS", " aquired buffer is same.(ts:%p)(E_HWC_WINDOW_STATE_DEVICE)", NULL, NULL, hwc_window->tsurface);
+             return EINA_FALSE;
+          }
+
+        hwc_window->tsurface = tsurface;
+
+        output_hwc = hwc_window->output_hwc;
+        EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, EINA_FALSE);
+
+        output = output_hwc->output;
+        EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
+
+        /* the damage isn't supported by hwc extension yet */
+        memset(&fb_damage, 0, sizeof(fb_damage));
+
+        tdm_output_hwc_set_client_target_buffer(output->toutput, hwc_window->tsurface, fb_damage);
+
+        ee_rendered_hw_list = e_hwc_window_target_window_ee_rendered_hw_list_get(target_hwc_window);
+        n_thw = eina_list_count(ee_rendered_hw_list);
+        if (n_thw)
+          {
+             ELOGF("HWC-WINS", " ehw:%p sets ts:%10p ------- {%25s}, state:%s",
+                   NULL, NULL, hwc_window, hwc_window->tsurface, "@TARGET WINDOW@",
+                   e_hwc_window_state_string_get(hwc_window->state));
+
+             i = 0;
+             EINA_LIST_FOREACH(ee_rendered_hw_list, l, hw)
+               {
+                  ELOGF("HWC-WINS", "  (%d) with ehw:%p, ts:%10p ------- {%25s}, state:%s, zpos:%d, deleted:%s",
+                        hwc_window->ec ? hwc_window->ec->pixmap : NULL, hwc_window->ec,
+                        i++, hw, hw->tsurface, hw->ec ? hw->ec->icccm.title : "UNKNOWN",
+                        e_hwc_window_state_string_get(hw->state),
+                        hwc_window->zpos, hwc_window->is_deleted ? "yes" : "no");
+               }
+          }
+        else
+          ELOGF("HWC-WINS", " ehw:%p sets ts:%10p ------- {%25s}, state:%s, zpos:%d no hwc_windows to render.",
+                NULL, NULL, hwc_window, hwc_window->tsurface, "@TARGET WINDOW@",
+                e_hwc_window_state_string_get(hwc_window->state), hwc_window->zpos);
+     }
+   else
+     {
+        if (hwc_window->tsurface == NULL)
+          {
+             //ELOGF("HWC-WINS", " the surface of target is null.(E_HWC_WINDOW_STATE_NONE)", NULL, NULL);
+             return EINA_FALSE;
+          }
+
+        if (hwc_window->tsurface)
+          _e_hwc_window_target_window_surface_release((E_Hwc_Window_Target *)hwc_window, hwc_window->tsurface);
+
+        if (!_e_hwc_window_target_window_clear((E_Hwc_Window_Target *)hwc_window))
+          ERR("fail to _e_hwc_window_target_window_clear");
+
+        hwc_window->tsurface = NULL;
+
+        //TODO: Do we set the target_buffer to be NULL?
+
+        ELOGF("HWC-WINS", " ehw:%p sets ts:%10p ------- {%25s}, state:%s",
+              NULL, NULL, hwc_window, hwc_window->tsurface, "@TARGET WINDOW@",
+              e_hwc_window_state_string_get(hwc_window->state));
+     }
+
+   hwc_window->update_exist = EINA_TRUE;
+
+   return EINA_TRUE;
+}
+
+EINTERN Eina_List *
+e_hwc_window_target_window_ee_rendered_hw_list_get(E_Hwc_Window_Target *target_window)
+{
+   Eina_List *ee_rendered_hw_list = NULL, *new_list = NULL;
+   E_Hwc_Window *hw1, *hw2;
+   const Eina_List *l, *ll;
+   E_Output_Hwc *output_hwc;
+   tbm_surface_h target_tsurface;
+
+   output_hwc = target_window->hwc_window.output_hwc;
+
+   target_tsurface = target_window->hwc_window.tsurface;
+   tbm_surface_internal_get_user_data(target_tsurface, ee_rendered_hw_list_key, (void**)&ee_rendered_hw_list);
+
+   /* refresh list of composited e_thwc_windows according to existed ones */
+   EINA_LIST_FOREACH(ee_rendered_hw_list, l, hw1)
+      EINA_LIST_FOREACH(output_hwc->hwc_windows, ll, hw2)
+         if (hw1 == hw2) new_list = eina_list_append(new_list, hw1);
+
+   return new_list;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_activate(E_Hwc_Window *hwc_window)
+{
+   struct wayland_tbm_client_queue *cqueue = NULL;
+   E_Client *ec;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+   if (hwc_window->activation_state == E_HWC_WINDOW_ACTIVATION_STATE_ACTIVATED)
+     return EINA_TRUE;
+
+   ec = hwc_window->ec;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
+
+   /* set the redirected to FALSE */
+   e_client_redirected_set(ec, EINA_FALSE);
+
+   cqueue = _get_wayland_tbm_client_queue(ec);
+
+   if (cqueue)
+     wayland_tbm_server_client_queue_activate(cqueue, 0, 0, 0);
+
+   if (e_hwc_window_is_cursor(hwc_window))
+     {
+        E_Pointer *pointer = NULL;
+
+        pointer = e_pointer_get(ec);
+        EINA_SAFETY_ON_NULL_RETURN_VAL(pointer, EINA_FALSE);
+
+        e_pointer_hwc_set(pointer, EINA_TRUE);
+     }
+
+   hwc_window->activation_state = E_HWC_WINDOW_ACTIVATION_STATE_ACTIVATED;
+
+   return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_deactivate(E_Hwc_Window *hwc_window)
+{
+   struct wayland_tbm_client_queue * cqueue = NULL;
+   E_Client *ec = NULL;
+   int transform;
+   E_Output *output = NULL;
+   E_Output_Hwc *output_hwc = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+   if (hwc_window->activation_state == E_HWC_WINDOW_ACTIVATION_STATE_DEACTIVATED)
+     return EINA_TRUE;
+
+   ec = hwc_window->ec;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
+
+   /* set the redirected to TRUE */
+   e_client_redirected_set(ec, EINA_TRUE);
+
+   cqueue = _get_wayland_tbm_client_queue(ec);
+   if (cqueue)
+     /* TODO: do we have to immediately inform a wayland client
+      *       that an e_client got redirected or wait till it's being composited
+      *       on the fb_target and a hw overlay owned by it gets free? */
+     wayland_tbm_server_client_queue_deactivate(cqueue);
+
+   output_hwc = hwc_window->output_hwc;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, EINA_FALSE);
+
+   output = output_hwc->output;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
+
+   transform = e_comp_wl_output_buffer_transform_get(ec);
+
+   if (output->config.rotation != 0 && (output->config.rotation / 90) == transform)
+      e_comp_screen_rotation_ignore_output_transform_send(ec, EINA_TRUE);
+
+   _e_hwc_window_client_recover(hwc_window);
+
+   if (e_hwc_window_is_cursor(hwc_window))
+     {
+        E_Pointer *pointer = NULL;
+
+        pointer = e_pointer_get(ec);
+        if (pointer)
+          e_pointer_hwc_set(pointer, EINA_FALSE);
+     }
+
+   hwc_window->activation_state = E_HWC_WINDOW_ACTIVATION_STATE_DEACTIVATED;
+
+   return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_is_on_hw_overlay(E_Hwc_Window *hwc_window)
+{
+   E_Hwc_Window_State state = E_HWC_WINDOW_STATE_NONE;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+   state = e_hwc_window_state_get(hwc_window);
+
+   if (state == E_HWC_WINDOW_STATE_DEVICE) return EINA_TRUE;
+   if (state == E_HWC_WINDOW_STATE_CURSOR) return EINA_TRUE;
+   if (state == E_HWC_WINDOW_STATE_VIDEO) return EINA_TRUE;
+
+   return EINA_FALSE;
+}
+
+EINTERN tbm_surface_h
+e_hwc_window_displaying_surface_get(E_Hwc_Window *hwc_window)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, NULL);
+
+   return hwc_window->display_info.tsurface;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_state_set(E_Hwc_Window *hwc_window, E_Hwc_Window_State state)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+   if (hwc_window->state != state) hwc_window->state = state;
+
+   /* zpos is -999 at state none */
+   if (state == E_HWC_WINDOW_STATE_NONE)
+     e_hwc_window_zpos_set(hwc_window, -999);
+
+   return EINA_TRUE;
+}
+
+EINTERN E_Hwc_Window_State
+e_hwc_window_state_get(E_Hwc_Window *hwc_window)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, E_HWC_WINDOW_STATE_NONE);
+
+   return hwc_window->state;
+}
+
+EINTERN void
+e_hwc_window_prev_state_update(E_Hwc_Window *hwc_window)
+{
+   EINA_SAFETY_ON_NULL_RETURN(hwc_window);
+
+   if (hwc_window->uncompleted_transition != E_HWC_WINDOW_TRANSITION_NONE_TO_NONE)
+     return;
+
+   hwc_window->prev_state = hwc_window->state;
+}
+
+EINTERN E_Hwc_Window_State
+e_hwc_window_prev_state_get(E_Hwc_Window *hwc_window)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, E_HWC_WINDOW_STATE_NONE);
+
+   return hwc_window->prev_state;
+}
+
+// add hwc_window to the render_list
+EINTERN void
+e_hwc_window_render_list_add(E_Hwc_Window *hwc_window)
+{
+   E_Hwc_Window_Target *target_hwc_window;
+   E_Client *ec;
+
+   EINA_SAFETY_ON_NULL_RETURN(hwc_window);
+
+   ec = hwc_window->ec;
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   target_hwc_window = _e_hwc_window_target_window_get(hwc_window);
+   EINA_SAFETY_ON_NULL_RETURN(target_hwc_window);
+
+   target_hwc_window->ee_rendered_hw_list =
+           eina_list_append(target_hwc_window->ee_rendered_hw_list, hwc_window);
+
+   ELOGF("HWC-WINS", " added the render_list -- ehw:%p -- {%25s}.", ec->pixmap, ec, hwc_window, ec->icccm.title);
+}
+
+EINTERN Eina_Bool
+e_hwc_window_is_on_target_window(E_Hwc_Window *hwc_window)
+{
+   Eina_List *ee_rendered_hw_list = NULL;
+   E_Hwc_Window_Target *target_hwc_window;
+   E_Hwc_Window *target_window;
+   E_Hwc_Window *hw;
+   const Eina_List *l;
+   tbm_surface_h target_tsurface;
+
+   target_hwc_window = _e_hwc_window_target_window_get(hwc_window);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
+
+   target_window = (E_Hwc_Window *)target_hwc_window;
+   if (e_hwc_window_state_get(target_window) != E_HWC_WINDOW_STATE_DEVICE) return EINA_FALSE;
+
+   target_tsurface = target_hwc_window->hwc_window.tsurface;
+
+   tbm_surface_internal_get_user_data(target_tsurface, ee_rendered_hw_list_key, (void**)&ee_rendered_hw_list);
+
+   EINA_LIST_FOREACH(ee_rendered_hw_list, l, hw)
+     if (hw == hwc_window) return EINA_TRUE;
+
+   return EINA_FALSE;
+}
+
+
+EINTERN const char*
+e_hwc_window_state_string_get(E_Hwc_Window_State hwc_window_state)
+{
+    switch (hwc_window_state)
+    {
+     case E_HWC_WINDOW_STATE_NONE:
+       return "NO"; // None
+     case E_HWC_WINDOW_STATE_CLIENT:
+       return "CL"; // Client
+     case E_HWC_WINDOW_STATE_DEVICE:
+       return "DV"; // Deivce
+     case E_HWC_WINDOW_STATE_VIDEO:
+       return "VD"; // Video
+     case E_HWC_WINDOW_STATE_DEVICE_CANDIDATE:
+       return "DC"; // Deivce Candidate
+     case E_HWC_WINDOW_STATE_CURSOR:
+       return "CS"; // Cursor
+     default:
+       return "UNKNOWN";
+    }
+}
diff --git a/src/bin/e_hwc_window.h b/src/bin/e_hwc_window.h
new file mode 100644 (file)
index 0000000..3498144
--- /dev/null
@@ -0,0 +1,147 @@
+#ifdef E_TYPEDEFS
+
+typedef struct _E_Hwc_Window                     E_Hwc_Window;
+typedef struct _E_Hwc_Window_Target              E_Hwc_Window_Target;
+typedef struct _E_Hwc_Window_Commit_Data         E_Hwc_Window_Commit_Data;
+
+#else
+#ifndef E_HWC_WINDOW_H
+#define E_HWC_WINDOW_H
+
+typedef enum _E_Hwc_Window_State
+{
+   E_HWC_WINDOW_STATE_NONE,
+   E_HWC_WINDOW_STATE_CLIENT,
+   E_HWC_WINDOW_STATE_DEVICE,
+   E_HWC_WINDOW_STATE_VIDEO,
+   E_HWC_WINDOW_STATE_DEVICE_CANDIDATE,
+   E_HWC_WINDOW_STATE_CURSOR
+} E_Hwc_Window_State;
+
+typedef enum _E_Hwc_Window_Transition
+{
+   E_HWC_WINDOW_TRANSITION_NONE_TO_NONE,
+   E_HWC_WINDOW_TRANSITION_NONE_TO_CLIENT,
+   E_HWC_WINDOW_TRANSITION_NONE_TO_DEVICE,
+   E_HWC_WINDOW_TRANSITION_NONE_TO_CURSOR,
+   E_HWC_WINDOW_TRANSITION_CLIENT_TO_NONE,
+   E_HWC_WINDOW_TRANSITION_CLIENT_TO_CLIENT,
+   E_HWC_WINDOW_TRANSITION_CLIENT_TO_DEVICE,
+   E_HWC_WINDOW_TRANSITION_CLIENT_TO_CURSOR,
+   E_HWC_WINDOW_TRANSITION_DEVICE_TO_NONE,
+   E_HWC_WINDOW_TRANSITION_DEVICE_TO_CLIENT,
+   E_HWC_WINDOW_TRANSITION_DEVICE_TO_DEVICE,
+   E_HWC_WINDOW_TRANSITION_CURSOR_TO_NONE,
+   E_HWC_WINDOW_TRANSITION_CURSOR_TO_CLIENT,
+   E_HWC_WINDOW_TRANSITION_CURSOR_TO_CURSOR
+} E_Hwc_Window_Transition;
+
+typedef enum _E_Hwc_Window_Activation_State
+{
+   E_HWC_WINDOW_ACTIVATION_STATE_NONE = 0,
+   E_HWC_WINDOW_ACTIVATION_STATE_ACTIVATED,
+   E_HWC_WINDOW_ACTIVATION_STATE_DEACTIVATED,
+} E_Hwc_Window_Activation_State;
+
+struct _E_Hwc_Window
+{
+   E_Client                      *ec;
+   E_Output_Hwc                  *output_hwc;
+   tdm_hwc_window                *thwc_window;
+   int                            zpos;
+   Eina_Bool                      is_target;
+   Eina_Bool                      is_video;
+   Eina_Bool                      is_cursor;
+   Eina_Bool                      is_deleted;
+   Eina_Bool                      update_exist;
+   tbm_surface_h                  tsurface;
+   E_Hwc_Window_Activation_State  activation_state; /* hwc_window has occupied the hw layer or not */
+   tdm_hwc_window_info info;
+
+   E_Hwc_Window_State             state;
+   E_Hwc_Window_State             prev_state;
+   E_Hwc_Window_Transition        transition;
+   E_Hwc_Window_Transition        uncompleted_transition;
+
+   /* current display information */
+   struct
+   {
+      E_Comp_Wl_Buffer_Ref  buffer_ref;
+      tbm_surface_h         tsurface;
+   } display_info;
+
+   E_Hwc_Window_Commit_Data       *commit_data;
+
+   Eina_Bool hwc_acceptable;
+   Eina_Bool need_change_buffer_transform;
+
+   tbm_surface_h       cursor_tsurface;
+   int                 cursor_rotation;
+
+   Eina_Bool is_device_to_client_transition;
+};
+
+struct _E_Hwc_Window_Target
+{
+   E_Hwc_Window        hwc_window; /* don't move this field */
+
+   Ecore_Evas         *ee;
+   Evas               *evas;
+   int                 event_fd;
+   Ecore_Fd_Handler   *event_hdlr;
+
+   tbm_surface_queue_h queue;
+
+   /* a surface the rendering is currently performing at */
+   tbm_surface_h       dequeued_tsurface;
+   Eina_List          *ee_rendered_hw_list;
+
+   Eina_Bool skip_surface_set;
+};
+
+struct _E_Hwc_Window_Commit_Data {
+   E_Comp_Wl_Buffer_Ref  buffer_ref;
+   tbm_surface_h         tsurface;
+};
+
+EINTERN Eina_Bool          e_hwc_window_init(E_Output_Hwc *output_hwc);
+EINTERN void               e_hwc_window_deinit(E_Output_Hwc *output_hwc); // TODO:
+
+EINTERN E_Hwc_Window      *e_hwc_window_new(E_Output_Hwc *output_hwc, E_Client *ec, E_Hwc_Window_State state);
+EINTERN void               e_hwc_window_free(E_Hwc_Window *hwc_window);
+
+EINTERN Eina_Bool          e_hwc_window_zpos_set(E_Hwc_Window *hwc_window, int zpos);
+EINTERN int                e_hwc_window_zpos_get(E_Hwc_Window *hwc_window);
+EINTERN Eina_Bool          e_hwc_window_compsition_update(E_Hwc_Window *hwc_window);
+EINTERN Eina_Bool          e_hwc_window_buffer_update(E_Hwc_Window *hwc_window);
+EINTERN Eina_Bool          e_hwc_window_is_target(E_Hwc_Window *hwc_window);
+EINTERN Eina_Bool          e_hwc_window_is_video(E_Hwc_Window *hwc_window);
+EINTERN Eina_Bool          e_hwc_window_is_cursor(E_Hwc_Window *hwc_window);
+EINTERN Eina_Bool          e_hwc_window_buffer_fetch(E_Hwc_Window *hwc_window);
+
+EINTERN Eina_Bool          e_hwc_window_commit_data_aquire(E_Hwc_Window *hwc_window);
+EINTERN Eina_Bool          e_hwc_window_commit_data_release(E_Hwc_Window *hwc_window);
+
+EINTERN Eina_Bool          e_hwc_window_target_surface_queue_can_dequeue(E_Hwc_Window_Target *target_hwc_window);
+EINTERN Eina_Bool          e_hwc_window_target_enabled(E_Hwc_Window_Target *target_hwc_window);
+EINTERN Eina_Bool          e_hwc_window_target_buffer_fetch(E_Hwc_Window_Target *target_hwc_window);
+EINTERN Eina_List         *e_hwc_window_target_window_ee_rendered_hw_list_get(E_Hwc_Window_Target *target_window);
+
+EINTERN Eina_Bool          e_hwc_window_activate(E_Hwc_Window *hwc_window);
+EINTERN Eina_Bool          e_hwc_window_deactivate(E_Hwc_Window *hwc_window);
+EINTERN Eina_Bool          e_hwc_window_is_on_hw_overlay(E_Hwc_Window *hwc_window);
+EINTERN tbm_surface_h      e_hwc_window_displaying_surface_get(E_Hwc_Window *hwc_window);
+
+EINTERN Eina_Bool          e_hwc_window_state_set(E_Hwc_Window *hwc_window, E_Hwc_Window_State state);
+EINTERN E_Hwc_Window_State e_hwc_window_state_get(E_Hwc_Window *hwc_window);
+EINTERN void               e_hwc_window_prev_state_update(E_Hwc_Window *hwc_window);
+EINTERN E_Hwc_Window_State e_hwc_window_prev_state_get(E_Hwc_Window *hwc_window);
+
+EINTERN void               e_hwc_window_render_list_add(E_Hwc_Window *hwc_window);
+
+EINTERN Eina_Bool          e_hwc_window_is_on_target_window(E_Hwc_Window *hwc_window);
+
+EINTERN const char        *e_hwc_window_state_string_get(E_Hwc_Window_State hwc_window_state);
+
+#endif // E_HWC_WINDOW_H
+#endif
index d399f90afdcc1f4b7bb88ace650163761d84193a..b267502b6e55333d691be88302c171dfc3282a3d 100644 (file)
@@ -53,6 +53,8 @@
 #include "e_output.h"
 #include "e_output_hwc.h"
 #include "e_output_hwc_planes.h"
+#include "e_output_hwc_windows.h"
+#include "e_hwc_window.h"
 #include "e_comp_wl.h"
 #include "e_comp_wl_data.h"
 #include "e_comp_wl_input.h"
index 1ab50565b258aa14565875ceba55e035deb25244..403cfad70ce22facb7e90a4e0d1e6691a245d2e3 100644 (file)
@@ -15,7 +15,7 @@ typedef struct _E_Info_Client
    Eldbus_Object     *obj;
 
    /* topvwins */
-   int                use_gl, use_hwc, use_multi_layer, hwc;
+   int                use_gl, use_hwc, use_multi_layer, hwc, hwc_windows;
    int                use_buffer_flush, deiconify_approve;
    const char        *engine;
    Eina_List         *win_list;
@@ -487,9 +487,9 @@ _cb_vwindow_info_get(const Eldbus_Message *msg)
    res = eldbus_message_error_get(msg, &name, &text);
    EINA_SAFETY_ON_TRUE_GOTO(res, finish);
 
-   res = eldbus_message_arguments_get(msg, "iiiisiia("VALUE_TYPE_FOR_TOPVWINS")",
+   res = eldbus_message_arguments_get(msg, "iiiiisiia("VALUE_TYPE_FOR_TOPVWINS")",
                                       &e_info_client.use_gl, &e_info_client.use_hwc, &e_info_client.use_multi_layer,
-                                      &e_info_client.hwc, &engine,
+                                      &e_info_client.hwc, &e_info_client.hwc_windows, &engine,
                                       &e_info_client.use_buffer_flush, &e_info_client.deiconify_approve,
                                       &array);
    EINA_SAFETY_ON_FALSE_GOTO(res, finish);
@@ -980,9 +980,20 @@ _e_info_client_proc_topvwins_info(int argc, char **argv)
    printf("ENG:  %s\n", e_info_client.engine);
    if (e_info_client.use_hwc)
      {
-        printf("HWC:  %s\n", e_info_client.hwc ? "on":"off");
-        printf("Multi Plane:  %s\n", e_info_client.use_multi_layer ? "on":"off");
+        if (e_info_client.hwc)
+          {
+             printf("HWC:  ");
+             if (e_info_client.hwc_windows)
+               printf("hwc windows policy\n");
+             else
+               printf("hwc planes policy and multiple plane is %s\n", e_info_client.use_multi_layer ? "on":"off");
+          }
+        else
+          printf("HWC:  off");
      }
+   else
+     printf("HWC:  configuration is off");
+
    printf("Buffer flush: %s\n", e_info_client.use_buffer_flush ? "on":"off");
    if (e_info_client.use_buffer_flush)
      printf("Deiconify Approve: %s\n", "auto on");
@@ -1018,8 +1029,13 @@ _e_info_client_proc_topvwins_info(int argc, char **argv)
           {
              if ((!win->iconic) && (win->frame_visible))
                {
-                  if (win->hwc) snprintf(tmp, sizeof(tmp), "hwc@%i", win->pl_zpos);
-                  else snprintf(tmp, sizeof(tmp), "comp@%i", win->pl_zpos);
+                  if (win->pl_zpos == -999)
+                    snprintf(tmp, sizeof(tmp), " - ");
+                  else
+                    {
+                       if (win->hwc) snprintf(tmp, sizeof(tmp), "hwc@%i", win->pl_zpos);
+                       else snprintf(tmp, sizeof(tmp), "comp@%i", win->pl_zpos);
+                    }
                }
              else
                snprintf(tmp, sizeof(tmp), " - ");
@@ -1092,8 +1108,13 @@ _e_info_client_proc_topwins_info(int argc, char **argv)
           {
              if ((!win->iconic) && (win->frame_visible))
                {
-                  if (win->hwc) snprintf(tmp, sizeof(tmp), "hwc@%i", win->pl_zpos);
-                  else snprintf(tmp, sizeof(tmp), "comp@%i", win->pl_zpos);
+                  if (win->pl_zpos == -999)
+                    snprintf(tmp, sizeof(tmp), " - ");
+                  else
+                    {
+                       if (win->hwc) snprintf(tmp, sizeof(tmp), "hwc@%i", win->pl_zpos);
+                       else snprintf(tmp, sizeof(tmp), "comp@%i", win->pl_zpos);
+                    }
                }
              else
                snprintf(tmp, sizeof(tmp), " - ");
@@ -3551,8 +3572,13 @@ _e_info_client_cb_wininfo(const Eldbus_Message *msg)
      {
         if ((!iconic) && (frame_visible))
           {
-             if (hwc) printf(" hwc@%i\n", pl_zpos);
-             else printf(" comp@%i\n", pl_zpos);
+             if (pl_zpos == -999)
+               printf(" - ");
+             else
+               {
+                  if (hwc) printf(" hwc@%i\n", pl_zpos);
+                  else printf(" comp@%i\n", pl_zpos);
+               }
           }
         else
           printf(" - \n");
@@ -3618,8 +3644,13 @@ _e_info_client_cb_wininfo_tree(const Eldbus_Message *msg)
         else
           printf("0x%lx \"%s\":", (unsigned long)child_win, child_name);
         printf (" %dx%d+%d+%d", w, h, x, y);
-        if (hwc > 0) printf(" hwc@%i", pl_zpos);
-        else if (!hwc) printf(" comp@%i", pl_zpos);
+        if (pl_zpos == -999)
+          printf(" - ");
+        else
+          {
+             if (hwc > 0) printf(" hwc@%i", pl_zpos);
+             else if (!hwc) printf(" comp@%i", pl_zpos);
+          }
         printf("\n");
         if (num_children > 0)
           {
index c7c1627fbd0723790e0605dc30af185dc5edd8de..c9101d3f4a887dfafab529ee0a3f4807d73c9e3a 100644 (file)
@@ -180,6 +180,7 @@ _e_info_server_ec_hwc_info_get(E_Client *ec, int *hwc, int *pl_zpos)
    Eina_List *l;
    E_Output *eout;
    E_Plane *ep;
+   E_Hwc_Window *hwc_window = NULL;
 
    *hwc = -1;
    *pl_zpos = -999;
@@ -191,18 +192,31 @@ _e_info_server_ec_hwc_info_get(E_Client *ec, int *hwc, int *pl_zpos)
 
    eout = e_output_find(ec->zone->output_id);
    if (!eout) return;
-   EINA_LIST_FOREACH(eout->planes, l, ep)
-     {
-        if (e_plane_is_fb_target(ep))
-          *pl_zpos = ep->zpos;
 
-        if (ep->ec == ec)
+   if (e_output_hwc_policy_get(eout->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
+     {
+        EINA_LIST_FOREACH(eout->planes, l, ep)
           {
-             *hwc = 1;
-             *pl_zpos = ep->zpos;
-             break;
+             if (e_plane_is_fb_target(ep))
+               *pl_zpos = ep->zpos;
+
+             if (ep->ec == ec)
+               {
+                  *hwc = 1;
+                  *pl_zpos = ep->zpos;
+                  break;
+               }
           }
      }
+   else
+     {
+        if (!ec->hwc_window) return;
+        hwc_window = ec->hwc_window;
+        if (e_hwc_window_is_on_hw_overlay(hwc_window))
+          *hwc = 1;
+
+        *pl_zpos = e_hwc_window_zpos_get(hwc_window);
+     }
 }
 
 static void
@@ -279,6 +293,21 @@ _msg_clients_append(Eldbus_Message_Iter *iter, Eina_Bool is_visible)
    eldbus_message_iter_container_close(iter, array_of_ec);
 }
 
+static int
+_e_info_server_is_hwc_windows()
+{
+   E_Output *primary_output;
+
+   primary_output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
+   if (!primary_output)
+      return 0;
+
+   if (e_output_hwc_policy_get(primary_output->output_hwc) == E_OUTPUT_HWC_POLICY_WINDOWS)
+     return 1;
+
+   return 0;
+}
+
 /* Method Handlers */
 static Eldbus_Message *
 _e_info_server_cb_window_info_get(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
@@ -290,6 +319,7 @@ _e_info_server_cb_window_info_get(const Eldbus_Service_Interface *iface EINA_UNU
    eldbus_message_iter_basic_append(iter, 'i', e_comp_config_get()->hwc);
    eldbus_message_iter_basic_append(iter, 'i', e_comp_config_get()->hwc_use_multi_plane);
    eldbus_message_iter_basic_append(iter, 'i', e_comp->hwc);
+   eldbus_message_iter_basic_append(iter, 'i', _e_info_server_is_hwc_windows());
    eldbus_message_iter_basic_append(iter, 's', ecore_evas_engine_name_get(e_comp->ee));
    eldbus_message_iter_basic_append(iter, 'i', e_config->use_buffer_flush);
    eldbus_message_iter_basic_append(iter, 'i', e_config->deiconify_approve);
@@ -5254,7 +5284,7 @@ _e_info_server_cb_deiconify_approve(const Eldbus_Service_Interface *iface EINA_U
 
 //{ "method_name", arguments_from_client, return_values_to_client, _method_cb, ELDBUS_METHOD_FLAG },
 static const Eldbus_Method methods[] = {
-   { "get_window_info", NULL, ELDBUS_ARGS({"iiiisa("VALUE_TYPE_FOR_TOPVWINS")", "array of ec"}), _e_info_server_cb_window_info_get, 0 },
+   { "get_window_info", NULL, ELDBUS_ARGS({"iiiiisa("VALUE_TYPE_FOR_TOPVWINS")", "array of ec"}), _e_info_server_cb_window_info_get, 0 },
    { "get_all_window_info", NULL, ELDBUS_ARGS({"a("VALUE_TYPE_FOR_TOPVWINS")", "array of ec"}), _e_info_server_cb_all_window_info_get, 0 },
    { "compobjs", NULL, ELDBUS_ARGS({"a("SIGNATURE_COMPOBJS_CLIENT")", "array of comp objs"}), _e_info_server_cb_compobjs, 0 },
    { "subsurface", NULL, ELDBUS_ARGS({"a("SIGNATURE_SUBSURFACE")", "array of ec"}), _e_info_server_cb_subsurface, 0 },
index 40cb847e57cfd9f5bfbb9468b60743c3ac47110e..6d778c2bd48579e92ea13d15107ec58c598330c5 100644 (file)
@@ -500,20 +500,34 @@ _e_output_zoom_rotate(E_Output *output)
    DBG("zoom_rect rotate(x:%d,y:%d) (w:%d,h:%d)",
        output->zoom_conf.rect.x, output->zoom_conf.rect.y, output->zoom_conf.rect.w, output->zoom_conf.rect.h);
 
-   EINA_LIST_FOREACH(output->planes, l, ep)
+   if (e_output_hwc_policy_get(output->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
      {
-        if (!e_plane_is_fb_target(ep)) continue;
+        EINA_LIST_FOREACH(output->planes, l, ep)
+          {
+             if (!e_plane_is_fb_target(ep)) continue;
 
-        e_plane_zoom_set(ep, &output->zoom_conf.rect);
-        break;
+             e_plane_zoom_set(ep, &output->zoom_conf.rect);
+             break;
+          }
+
+        if (!_e_output_zoom_touch_set(output))
+          ERR("fail _e_output_zoom_touch_set");
+
+        /* update the ecore_evas */
+        if (e_plane_pp_commit_possible_check(ep))
+          _e_output_render_update(output);
      }
+   else
+     {
+        e_output_hwc_windows_zoom_set(output->output_hwc, &output->zoom_conf.rect);
 
-   if (!_e_output_zoom_touch_set(output))
-     ERR("fail _e_output_zoom_touch_set");
+        if (!_e_output_zoom_touch_set(output))
+          ERR("fail _e_output_zoom_touch_set");
 
-   /* update the ecore_evas */
-   if (e_plane_pp_commit_possible_check(ep))
-     _e_output_render_update(output);
+        /* update the ecore_evas */
+        if (e_output_hwc_windows_pp_commit_possible_check(output->output_hwc))
+          _e_output_render_update(output);
+     }
 }
 
 EINTERN void
@@ -2250,15 +2264,31 @@ e_output_setup(E_Output *output)
         output->output_hwc = output_hwc;
      }
 
-   /* ecore evas engine setup */
-   EINA_LIST_FOREACH_SAFE(output->planes, l, ll, plane)
+   if (e_output_hwc_policy_get(output->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
      {
-        if (plane->is_fb)
+        /* ecore evas engine setup */
+        EINA_LIST_FOREACH_SAFE(output->planes, l, ll, plane)
           {
-             if (!e_plane_setup(plane)) return EINA_FALSE;
-             else return EINA_TRUE;
+             if (plane->is_fb)
+               {
+                  if (!e_plane_setup(plane)) return EINA_FALSE;
+                  else return EINA_TRUE;
+               }
           }
      }
+   else
+     {
+#if 0
+       Evas_Object *canvas_bg = NULL;
+       unsigned int r, g, b, a;
+
+        /* set the color of the canvas_gb object */
+        r = 0; g = 0; b = 0; a = 1;
+        canvas_bg = e_comp->bg_blank_object;
+        evas_object_color_set(canvas_bg, r, g, b, a);
+#endif
+        return EINA_TRUE;
+     }
 
    return EINA_FALSE;
 }
@@ -2422,13 +2452,24 @@ e_output_render(E_Output *output)
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
 
-   EINA_LIST_REVERSE_FOREACH(output->planes, l, plane)
+   if (e_output_hwc_policy_get(output->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
      {
-        if (!e_plane_render(plane))
-         {
-            ERR("fail to e_plane_render.");
-            return EINA_FALSE;
-         }
+        EINA_LIST_REVERSE_FOREACH(output->planes, l, plane)
+          {
+             if (!e_plane_render(plane))
+               {
+                   ERR("fail to e_plane_render.");
+                   return EINA_FALSE;
+               }
+          }
+     }
+   else
+     {
+        if (!e_output_hwc_windows_render(output->output_hwc))
+          {
+             ERR("fail to e_output_hwc_windows_render.");
+             return EINA_FALSE;
+          }
      }
 
   return EINA_TRUE;
@@ -2450,19 +2491,29 @@ e_output_commit(E_Output *output)
    output_primary = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
    EINA_SAFETY_ON_NULL_RETURN_VAL(output_primary, EINA_FALSE);
 
-   if (output == output_primary)
+   if (e_output_hwc_policy_get(output->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
      {
-        if (!_e_output_planes_commit(output))
+        if (output == output_primary)
           {
-             ERR("fail _e_output_planes_commit");
-             return EINA_FALSE;
+             if (!_e_output_planes_commit(output))
+               {
+                   ERR("fail to _e_output_commit.");
+                   return EINA_FALSE;
+               }
+          }
+        else
+          {
+             if (!_e_output_external_commit(output))
+               {
+                  ERR("fail _e_output_external_commit");
+                  return EINA_FALSE;
+               }
           }
      }
    else
      {
-        if (!_e_output_external_commit(output))
+        if (!e_output_hwc_windows_commit(output->output_hwc))
           {
-             ERR("fail _e_output_external_commit");
              return EINA_FALSE;
           }
      }
@@ -2526,23 +2577,26 @@ e_output_util_planes_print(void)
 
         if (!output || !output->planes) continue;
 
-        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_REVERSE_FOREACH(output->planes, p_l, plane)
+        if (e_output_hwc_policy_get(output->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
           {
-             ec = plane->ec;
-             if (ec) fprintf(stderr, "HWC \t[%d]%s\t %s (0x%08x)",
-                             plane->zpos,
-                             plane->is_primary ? "--" : "  ",
-                             ec->icccm.title, (unsigned int)ec->frame);
+             fprintf(stderr, "HWC in %s .. \n", output->id);
+             fprintf(stderr, "HWC \tzPos \t on_plane \t\t\t\t on_prepare \t \n");
 
-             ec = plane->prepare_ec;
-             if (ec) fprintf(stderr, "\t\t\t %s (0x%08x)",
-                             ec->icccm.title, (unsigned int)ec->frame);
+             EINA_LIST_REVERSE_FOREACH(output->planes, p_l, plane)
+               {
+                  ec = plane->ec;
+                  if (ec) fprintf(stderr, "HWC \t[%d]%s\t %s (0x%08x)",
+                                  plane->zpos,
+                                  plane->is_primary ? "--" : "  ",
+                                  ec->icccm.title, (unsigned int)ec->frame);
+
+                  ec = plane->prepare_ec;
+                  if (ec) fprintf(stderr, "\t\t\t %s (0x%08x)",
+                                  ec->icccm.title, (unsigned int)ec->frame);
+                  fputc('\n', stderr);
+               }
              fputc('\n', stderr);
           }
-        fputc('\n', stderr);
      }
 }
 
@@ -2744,29 +2798,44 @@ e_output_zoom_set(E_Output *output, double zoomx, double zoomy, int cx, int cy)
    _e_output_zoom_coordinate_cal(output);
    _e_output_zoom_touch_rect_get(output);
 
-   ep = e_output_fb_target_get(output);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(ep, EINA_FALSE);
-
-   if (!output->zoom_set)
+   if (e_output_hwc_policy_get(output->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
      {
-        if (_e_output_fb_over_plane_check(output))
-          output->zoom_conf.unset_skip = EINA_TRUE;
-     }
+        ep = e_output_fb_target_get(output);
+        EINA_SAFETY_ON_NULL_RETURN_VAL(ep, EINA_FALSE);
 
-   e_output_hwc_planes_multi_plane_set(output->output_hwc, EINA_FALSE);
+        if (!output->zoom_set)
+          {
+             if (_e_output_fb_over_plane_check(output))
+               output->zoom_conf.unset_skip = EINA_TRUE;
+          }
 
-   if (!e_plane_zoom_set(ep, &output->zoom_conf.rect))
-     {
-        ERR("e_plane_zoom_set failed.");
-        output->zoom_conf.unset_skip = EINA_FALSE;
-        e_output_hwc_planes_multi_plane_set(output->output_hwc, EINA_TRUE);
+        e_output_hwc_planes_multi_plane_set(output->output_hwc, EINA_FALSE);
 
-        return EINA_FALSE;
+        if (!e_plane_zoom_set(ep, &output->zoom_conf.rect))
+          {
+             ERR("e_plane_zoom_set failed.");
+             output->zoom_conf.unset_skip = EINA_FALSE;
+             e_output_hwc_planes_multi_plane_set(output->output_hwc, EINA_TRUE);
+
+             return EINA_FALSE;
+          }
+
+        /* update the ecore_evas */
+        if (e_plane_pp_commit_possible_check(ep))
+          _e_output_render_update(output);
      }
+   else
+     {
+        if (!e_output_hwc_windows_zoom_set(output->output_hwc, &output->zoom_conf.rect))
+          {
+             ERR("e_output_hwc_windows_zoom_set failed.");
+             return EINA_FALSE;
+          }
 
-   /* update the ecore_evas */
-   if (e_plane_pp_commit_possible_check(ep))
-     _e_output_render_update(output);
+        /* update the ecore_evas */
+        if (e_output_hwc_windows_pp_commit_possible_check(output->output_hwc))
+          _e_output_render_update(output);
+     }
 
    if (!_e_output_zoom_touch_set(output))
      ERR("fail _e_output_zoom_touch_set");
@@ -2795,10 +2864,17 @@ e_output_zoom_unset(E_Output *output)
    if (!_e_output_zoom_touch_unset(output))
      ERR("fail _e_output_zoom_touch_unset");
 
-   ep = e_output_fb_target_get(output);
-   if (ep) e_plane_zoom_unset(ep);
+   if (e_output_hwc_policy_get(output->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
+     {
+        ep = e_output_fb_target_get(output);
+        if (ep) e_plane_zoom_unset(ep);
 
-   e_output_hwc_planes_multi_plane_set(output->output_hwc, EINA_TRUE);
+        e_output_hwc_planes_multi_plane_set(output->output_hwc, EINA_TRUE);
+     }
+   else
+     {
+        e_output_hwc_windows_zoom_unset(output->output_hwc);
+     }
 
    output->zoom_conf.zoomx = 0;
    output->zoom_conf.zoomy = 0;
@@ -3119,12 +3195,14 @@ e_output_external_set(E_Output *output, E_Output_Ext_State state)
    _e_output_external_rect_get(output_primary, p_w, p_h, w, h, &output->zoom_conf.rect);
 
    e_output_hwc_planes_multi_plane_set(output_primary->output_hwc, EINA_FALSE);
+   e_output_hwc_deactive_set(output_primary->output_hwc, EINA_TRUE);
 
    ep->output_primary = output_primary;
    if (!e_plane_external_set(ep, &output->zoom_conf.rect, state))
      {
         ERR("e_plane_mirror_set failed.");
         e_output_hwc_planes_multi_plane_set(output_primary->output_hwc, EINA_TRUE);
+        e_output_hwc_deactive_set(output_primary->output_hwc, EINA_FALSE);
 
         return EINA_FALSE;
      }
index 952fcc53c2411d947bbf87cbe8fa1862d494c895..e64472d51c7c37de5b2545f8134b0350d66d3514 100644 (file)
@@ -34,7 +34,26 @@ e_output_hwc_new(E_Output *output)
         INF("Output uses the HWC PLANES Policy.");
      }
    else
-     output_hwc->hwc_policy = E_OUTPUT_HWC_POLICY_WINDOWS;
+     {
+        output_hwc->hwc_policy = E_OUTPUT_HWC_POLICY_WINDOWS;
+
+        if (!e_output_hwc_windows_init(output_hwc))
+          {
+             ERR("hwc_opt: e_output_hwc_windows_init failed");
+             goto fail;
+          }
+
+        if (!e_hwc_window_init(output_hwc))
+          {
+             ERR("hwc_opt: E_Hwc_Window init failed");
+             goto fail;
+          }
+
+        /* turn on sw compositor at the start */
+        ecore_event_add(E_EVENT_COMPOSITOR_ENABLE, NULL, NULL, NULL);
+
+        INF("Output uses the HWC WINDOWS Policy.");
+     }
 
    return output_hwc;
 
@@ -51,6 +70,11 @@ e_output_hwc_del(E_Output_Hwc *output_hwc)
 
    if (output_hwc->hwc_policy == E_OUTPUT_HWC_POLICY_PLANES)
       e_output_hwc_planes_deinit();
+   else
+     {
+        e_hwc_window_deinit(output_hwc);
+        e_output_hwc_windows_deinit();
+     }
 
    E_FREE(output_hwc);
 }
@@ -60,28 +84,26 @@ 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_policy_get(output_hwc) == E_OUTPUT_HWC_POLICY_NONE) return;
+   if (e_output_hwc_policy_get(output_hwc) == E_OUTPUT_HWC_POLICY_NONE ||
+       e_output_hwc_policy_get(output_hwc) == E_OUTPUT_HWC_POLICY_WINDOWS) return;
 
-   if (e_output_hwc_policy_get(output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
+   if (e_output_hwc_deactive_get(output_hwc))
      {
-        if (e_output_hwc_deactive_get(output_hwc))
-          {
-             if (output_hwc->hwc_mode != E_OUTPUT_HWC_MODE_NONE)
-               e_output_hwc_planes_end(output_hwc, "deactive set.");
-             return;
-          }
-
-        if (!e_output_hwc_planes_usable(output_hwc))
-          {
-             e_output_hwc_planes_end(output_hwc, __FUNCTION__);
-             return;
-          }
+        if (output_hwc->hwc_mode != E_OUTPUT_HWC_MODE_NONE)
+          e_output_hwc_planes_end(output_hwc, "deactive set.");
+        return;
+     }
 
-        if (output_hwc->hwc_mode == E_OUTPUT_HWC_MODE_NONE)
-          e_output_hwc_planes_begin(output_hwc);
-        else
-          e_output_hwc_planes_changed(output_hwc);
+   if (!e_output_hwc_planes_usable(output_hwc))
+     {
+        e_output_hwc_planes_end(output_hwc, __FUNCTION__);
+        return;
      }
+
+   if (output_hwc->hwc_mode == E_OUTPUT_HWC_MODE_NONE)
+     e_output_hwc_planes_begin(output_hwc);
+   else
+     e_output_hwc_planes_changed(output_hwc);
 }
 
 EINTERN E_Output_Hwc_Mode
@@ -95,7 +117,7 @@ e_output_hwc_mode_get(E_Output_Hwc *output_hwc)
 EINTERN E_Output_Hwc_Policy
 e_output_hwc_policy_get(E_Output_Hwc *output_hwc)
 {
-   EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, E_OUTPUT_HWC_MODE_NONE);
 
    return output_hwc->hwc_policy;
 }
@@ -117,4 +139,4 @@ 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;
-}
\ No newline at end of file
+}
index a677f59c474ef72f1f4560ff1254281125a1bd35..36f9496cead3b3c00bbdab31722422945aafdcde 100644 (file)
@@ -30,6 +30,27 @@ struct _E_Output_Hwc
 
    /* variables for hwc_planes polic  */
    Eina_Bool          hwc_use_multi_plane;
+
+   /* variables for hwc_windows policy  */
+   Eina_Bool            hwc_wins;
+   Eina_List           *hwc_windows;
+   E_Hwc_Window_Target *target_hwc_window;
+   Eina_Bool            wait_commit;
+   int                  num_visible_windows;
+
+   /* variables for pp at hwc_windows policy */
+   tdm_pp               *tpp;
+   Eina_List            *pp_hwc_window_list;
+   Eina_List            *pending_pp_hwc_window_list;
+   Eina_List            *pending_pp_commit_data_list;
+   tbm_surface_queue_h   pp_tqueue;
+   tbm_surface_h         pp_tsurface;
+   Eina_Bool             pp_set_info;
+   Eina_Bool             pp_set;
+   Eina_Bool             pp_commit;
+   Eina_Bool             pp_output_commit;
+   E_Hwc_Window_Commit_Data  *pp_output_commit_data;
+   Eina_Rectangle        pp_rect;
 };
 
 EINTERN E_Output_Hwc        *e_output_hwc_new(E_Output *output);
diff --git a/src/bin/e_output_hwc_windows.c b/src/bin/e_output_hwc_windows.c
new file mode 100644 (file)
index 0000000..9e56a6e
--- /dev/null
@@ -0,0 +1,1689 @@
+#include "e.h"
+#include "services/e_service_quickpanel.h"
+
+#define DBG_EVALUATE 1
+
+#define ZPOS_NONE -999
+
+static Eina_Bool _e_output_hwc_windows_pp_output_data_commit(E_Output_Hwc *output_hwc, E_Hwc_Window_Commit_Data *data);
+static Eina_Bool _e_output_hwc_windows_pp_window_commit(E_Output_Hwc *output_hwc, E_Hwc_Window *hwc_window);
+
+// if ec has invalid buffer or scaled( transformed ) or forced composite(never_hwc)
+static Eina_Bool
+_e_output_hwc_windows_device_state_check(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;
+   int transform;
+
+   if ((!cdata) || (!cdata->buffer_ref.buffer))
+     {
+        ELOGF("HWC-WINS", "   ehw:%p -- {%25s} is forced to set CL state.(null cdata or buffer)",
+              ec->pixmap, ec, ec->hwc_window, ec->icccm.title);
+        return EINA_FALSE;
+     }
+
+   if ((cdata->width_from_buffer != cdata->width_from_viewport) ||
+       (cdata->height_from_buffer != cdata->height_from_viewport))
+     {
+        ELOGF("HWC-WINS", "   ehw:%p -- {%25s} is forced to set CL state.(size_from_viewport)",
+              ec->pixmap, ec, ec->hwc_window, ec->icccm.title);
+        return EINA_FALSE;
+     }
+
+   if (cdata->never_hwc)
+     {
+        ELOGF("HWC-WINS", "   ehw:%p -- {%25s} is forced to set CL state.(never_hwc)",
+              ec->pixmap, ec, ec->hwc_window, ec->icccm.title);
+        return EINA_FALSE;
+     }
+
+   if (e_client_transform_core_enable_get(ec))
+     {
+        ELOGF("HWC-WINS", "   ehw:%p -- {%25s} is forced to set CL state.(transfrom_core)",
+        ec->pixmap, ec, ec->hwc_window, ec->icccm.title);
+        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:
+         ELOGF("HWC-WINS", "   ehw:%p -- {%25s} is forced to set CL state.(buffer_type)",
+               ec->pixmap, ec, ec->hwc_window, ec->icccm.title);
+         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))
+     {
+        ELOGF("HWC-WINS", "   ehw:%p -- {%25s} is forced to set CL state.(minw:%d > buffer->w:%d)",
+              ec->pixmap, ec, ec->hwc_window, ec->icccm.title, minw, cdata->buffer_ref.buffer->w);
+        return EINA_FALSE;
+     }
+
+   if ((minh > 0) && (minh > cdata->buffer_ref.buffer->h))
+     {
+        ELOGF("HWC-WINS", "   ehw:%p -- {%25s} is forced to set CL state.(minh:%d > buffer->h:%d)",
+              ec->pixmap, ec, ec->hwc_window, ec->icccm.title, minh, cdata->buffer_ref.buffer->h);
+        return EINA_FALSE;
+     }
+
+   transform = e_comp_wl_output_buffer_transform_get(ec);
+
+   /* 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))
+     {
+        if ((eout->config.rotation / 90) != transform)
+          {
+             ELOGF("HWC-WINS", "   ehw:%p -- {%25s} is forced to set CL state.(no igrore_transfrom)",
+                   ec->pixmap, ec, ec->hwc_window, ec->icccm.title);
+             return EINA_FALSE;
+          }
+     }
+
+   return EINA_TRUE;
+}
+
+static E_Output_Hwc_Mode
+_e_output_hwc_windows_hwc_mode_get(E_Output_Hwc *output_hwc)
+{
+   Eina_List *l;
+   E_Hwc_Window *hwc_window;
+   E_Output_Hwc_Mode hwc_mode = E_OUTPUT_HWC_MODE_NONE;
+   int num_visible = 0;
+   int num_visible_client = 0;
+
+   EINA_LIST_FOREACH(output_hwc->hwc_windows, l, hwc_window)
+     {
+        if (e_hwc_window_is_target(hwc_window)) continue;
+
+        if (hwc_window->state == E_HWC_WINDOW_STATE_NONE) continue;
+        if (hwc_window->state == E_HWC_WINDOW_STATE_VIDEO) continue;
+
+        if (hwc_window->state == E_HWC_WINDOW_STATE_CLIENT)
+          num_visible_client++;
+
+        num_visible++;
+     }
+
+   if (!num_visible)
+     hwc_mode = E_OUTPUT_HWC_MODE_NONE;
+   else if (num_visible_client > 0)
+     hwc_mode = E_OUTPUT_HWC_MODE_HYBRID;
+   else
+     hwc_mode = E_OUTPUT_HWC_MODE_FULL;
+
+   return hwc_mode;
+}
+
+static int
+_e_output_hwc_windows_sort_cb(const void *d1, const void *d2)
+{
+   E_Hwc_Window *hwc_window_1 = (E_Hwc_Window *)d1;
+   E_Hwc_Window *hwc_window_2 = (E_Hwc_Window *)d2;
+
+   if (!hwc_window_1) return(-1);
+   if (!hwc_window_2) return(1);
+
+   return (hwc_window_2->zpos - hwc_window_1->zpos);
+}
+
+static unsigned int
+_e_output_hwc_windows_aligned_width_get(tbm_surface_h tsurface)
+{
+   unsigned int aligned_width = 0;
+   tbm_surface_info_s surf_info;
+
+   tbm_surface_get_info(tsurface, &surf_info);
+
+   switch (surf_info.format)
+     {
+      case TBM_FORMAT_YUV420:
+      case TBM_FORMAT_YVU420:
+      case TBM_FORMAT_YUV422:
+      case TBM_FORMAT_YVU422:
+      case TBM_FORMAT_NV12:
+      case TBM_FORMAT_NV21:
+        aligned_width = surf_info.planes[0].stride;
+        break;
+      case TBM_FORMAT_YUYV:
+      case TBM_FORMAT_UYVY:
+        aligned_width = surf_info.planes[0].stride >> 1;
+        break;
+      case TBM_FORMAT_ARGB8888:
+      case TBM_FORMAT_XRGB8888:
+        aligned_width = surf_info.planes[0].stride >> 2;
+        break;
+      default:
+        ERR("not supported format: %x", surf_info.format);
+     }
+
+   return aligned_width;
+}
+
+
+
+static void
+_e_output_hwc_windows_commit_handler(tdm_output *toutput, unsigned int sequence,
+                                  unsigned int tv_sec, unsigned int tv_usec,
+                                  void *user_data)
+{
+   const Eina_List *l;
+   E_Hwc_Window *hwc_window;
+   E_Output_Hwc *output_hwc = (E_Output_Hwc *)user_data;
+
+   EINA_SAFETY_ON_NULL_RETURN(output_hwc);
+
+   if (output_hwc->pp_tsurface && !output_hwc->output->zoom_set)
+     {
+        tbm_surface_internal_unref(output_hwc->pp_tsurface);
+        output_hwc->pp_tsurface = NULL;
+     }
+
+   ELOGF("HWC-WINS", "!!!!!!!! Output Commit Handler !!!!!!!!", NULL, NULL);
+
+   EINA_LIST_FOREACH(e_output_hwc_windows_get(output_hwc), l, hwc_window)
+     {
+         if (!e_hwc_window_commit_data_release(hwc_window)) continue;
+         if (e_hwc_window_is_video(hwc_window))
+           {
+              ELOGF("HWC-WINS", "!!!!!!!! Output Commit Handler (VIDEO)!!!!!!!!", NULL, NULL);
+              e_comp_wl_video_hwc_window_commit_data_release(hwc_window, sequence, tv_sec, tv_usec);
+           }
+     }
+
+   /* 'wait_commit' is mechanism to make 'fetch and commit' no more than one time per a frame;
+    * a 'page flip' happened so it's time to allow to make 'fetch and commit' for the e_output */
+   output_hwc->wait_commit = EINA_FALSE;
+}
+
+static Eina_Bool
+_e_output_hwc_windows_prepare_commit(E_Output *output, E_Hwc_Window *hwc_window)
+{
+   if (!e_hwc_window_commit_data_aquire(hwc_window))
+     return EINA_FALSE;
+
+   /* send frame event enlightenment dosen't send frame evnet in nocomp */
+   if (hwc_window->ec)
+     e_pixmap_image_clear(hwc_window->ec->pixmap, 1);
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_output_hwc_windows_offscreen_commit(E_Output *output, E_Hwc_Window *hwc_window)
+{
+   if (!e_hwc_window_commit_data_aquire(hwc_window))
+     return EINA_FALSE;
+
+   /* send frame event enlightenment doesn't send frame event in nocomp */
+   if (hwc_window->ec)
+     e_pixmap_image_clear(hwc_window->ec->pixmap, 1);
+
+   e_hwc_window_commit_data_release(hwc_window);
+
+   return EINA_TRUE;
+}
+
+static E_Hwc_Window *
+_e_output_hwc_windows_pp_window_get(E_Output_Hwc *output_hwc, tbm_surface_h tsurface)
+{
+   Eina_List *l;
+   E_Hwc_Window *hwc_window = NULL;
+
+   EINA_LIST_FOREACH(output_hwc->pp_hwc_window_list, l, hwc_window)
+     {
+        if (!hwc_window) continue;
+        if (!hwc_window->commit_data) continue;
+
+        if (hwc_window->commit_data->tsurface == tsurface)
+          return hwc_window;
+     }
+
+   return NULL;
+}
+
+static void
+_e_output_hwc_windows_pp_pending_data_remove(E_Output_Hwc *output_hwc)
+{
+   E_Hwc_Window_Commit_Data *data = NULL;
+   Eina_List *l = NULL, *ll = NULL;
+
+   if (eina_list_count(output_hwc->pending_pp_commit_data_list) != 0)
+     {
+        EINA_LIST_FOREACH_SAFE(output_hwc->pending_pp_commit_data_list, l, ll, data)
+          {
+             if (!data) continue;
+             output_hwc->pending_pp_commit_data_list = eina_list_remove_list(output_hwc->pending_pp_commit_data_list, l);
+             tbm_surface_queue_release(output_hwc->pp_tqueue, data->tsurface);
+             tbm_surface_internal_unref(data->tsurface);
+             E_FREE(data);
+          }
+     }
+   eina_list_free(output_hwc->pending_pp_commit_data_list);
+   output_hwc->pending_pp_commit_data_list = NULL;
+
+   if (eina_list_count(output_hwc->pending_pp_hwc_window_list) != 0)
+     {
+        E_Hwc_Window *hwc_window;
+        EINA_LIST_FOREACH_SAFE(output_hwc->pending_pp_hwc_window_list, l, ll, hwc_window)
+          {
+             if (!hwc_window) continue;
+             output_hwc->pending_pp_hwc_window_list = eina_list_remove_list(output_hwc->pending_pp_hwc_window_list, l);
+
+             if (hwc_window->ec) e_pixmap_image_clear(hwc_window->ec->pixmap, 1);
+             e_hwc_window_commit_data_release(hwc_window);
+          }
+     }
+   eina_list_free(output_hwc->pending_pp_hwc_window_list);
+   output_hwc->pending_pp_hwc_window_list = NULL;
+}
+
+static void
+_e_output_hwc_windows_pp_output_commit_handler(tdm_output *toutput, unsigned int sequence,
+                                              unsigned int tv_sec, unsigned int tv_usec,
+                                              void *user_data)
+{
+   E_Output_Hwc *output_hwc;
+   E_Hwc_Window_Commit_Data *data = NULL;
+   E_Output *output = NULL;
+   const Eina_List *l;
+   E_Hwc_Window *window;
+
+   EINA_SAFETY_ON_NULL_RETURN(user_data);
+
+   output_hwc = user_data;
+
+   output_hwc->pp_output_commit = EINA_FALSE;
+
+   EINA_LIST_FOREACH(e_output_hwc_windows_get(output_hwc), l, window)
+     {
+        if (window->commit_data && !window->commit_data->tsurface)
+          e_hwc_window_commit_data_release(window);
+     }
+
+   /* layer already resetted */
+   if (output_hwc->pp_output_commit_data)
+     {
+        data = output_hwc->pp_output_commit_data;
+        output_hwc->pp_output_commit_data = NULL;
+
+        /* if pp_set is false, do not deal with pending list */
+        if (!output_hwc->pp_set)
+          {
+             if (output_hwc->pp_tsurface)
+               tbm_surface_internal_unref(output_hwc->pp_tsurface);
+
+             output_hwc->pp_tsurface = data->tsurface;
+             output_hwc->wait_commit = EINA_FALSE;
+
+             E_FREE(data);
+
+             return;
+          }
+
+        if (output_hwc->pp_tqueue && output_hwc->pp_tsurface)
+          {
+             /* release and unref the current pp surface on the plane */
+             tbm_surface_queue_release(output_hwc->pp_tqueue, output_hwc->pp_tsurface);
+             tbm_surface_internal_unref(output_hwc->pp_tsurface);
+          }
+
+        /* set the new pp surface to the plane */
+        output_hwc->pp_tsurface = data->tsurface;
+
+        E_FREE(data);
+     }
+
+   ELOGF("HWC-WINS", "PP Output Commit Handler Output_Hwc(%p)", NULL, NULL, output_hwc);
+
+   output = output_hwc->output;
+   if (e_output_dpms_get(output))
+     {
+        _e_output_hwc_windows_pp_pending_data_remove(output_hwc);
+        return;
+     }
+
+   /* deal with the pending layer commit */
+   if (eina_list_count(output_hwc->pending_pp_commit_data_list) != 0)
+     {
+        data = eina_list_nth(output_hwc->pending_pp_commit_data_list, 0);
+        if (data)
+          {
+             output_hwc->pending_pp_commit_data_list = eina_list_remove(output_hwc->pending_pp_commit_data_list, data);
+
+             ELOGF("HWC-WINS", "PP Output Commit Handler start pending commit data(%p) tsurface(%p)", NULL, NULL, data, data->tsurface);
+
+             if (!_e_output_hwc_windows_pp_output_data_commit(output_hwc, data))
+               {
+                  ERR("fail to _e_output_hwc_windows_pp_output_data_commit");
+                  return;
+               }
+          }
+     }
+
+   /* deal with the pending pp commit */
+   if (eina_list_count(output_hwc->pending_pp_hwc_window_list) != 0)
+     {
+        E_Hwc_Window *hwc_window;
+
+        hwc_window = eina_list_nth(output_hwc->pending_pp_hwc_window_list, 0);
+        if (hwc_window)
+          {
+             if (!tbm_surface_queue_can_dequeue(output_hwc->pp_tqueue, 0))
+               return;
+
+             output_hwc->pending_pp_hwc_window_list = eina_list_remove(output_hwc->pending_pp_hwc_window_list, hwc_window);
+
+             if (data)
+               ELOGF("HWC-WINS", "PP Layer Commit Handler start pending pp data(%p) tsurface(%p)", NULL, NULL, data, data->tsurface);
+             else
+               ELOGF("HWC-WINS", "PP Layer Commit Handler start pending pp data(%p) tsurface(%p)", NULL, NULL, NULL, NULL);
+
+             if (!_e_output_hwc_windows_pp_window_commit(output_hwc, hwc_window))
+               {
+                  ERR("fail _e_output_hwc_windows_pp_data_commit");
+                  e_hwc_window_commit_data_release(hwc_window);
+                  return;
+               }
+          }
+     }
+}
+
+static Eina_Bool
+_e_output_hwc_windows_pp_output_data_commit(E_Output_Hwc *output_hwc, E_Hwc_Window_Commit_Data *data)
+{
+   E_Output *output = NULL;
+   tdm_layer *toutput = NULL;
+   tdm_error terror;
+   tdm_hwc_region fb_damage;
+
+   /* the damage isn't supported by hwc extension yet */
+   memset(&fb_damage, 0, sizeof(fb_damage));
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
+
+   output = output_hwc->output;
+   toutput = output->toutput;
+
+   if (e_output_dpms_get(output))
+     {
+        _e_output_hwc_windows_pp_pending_data_remove(output_hwc);
+        goto fail;
+     }
+
+   /* no need to pass composited_wnds list because smooth transition isn't
+    * used is this case */
+   terror = tdm_output_hwc_set_client_target_buffer(toutput, data->tsurface, fb_damage);
+   if (terror != TDM_ERROR_NONE)
+     {
+        ERR("fail to tdm_output_hwc_set_client_target_buffer");
+        goto fail;
+     }
+
+   terror = tdm_output_commit(toutput, 0, _e_output_hwc_windows_pp_output_commit_handler, output_hwc);
+
+   if (terror != TDM_ERROR_NONE)
+     {
+        ERR("fail to tdm_output_commit output_hwc:%p", output_hwc);
+        goto fail;
+     }
+
+   output_hwc->pp_output_commit = EINA_TRUE;
+   output_hwc->pp_output_commit_data = data;
+
+   return EINA_TRUE;
+
+fail:
+   tbm_surface_internal_unref(data->tsurface);
+   tbm_surface_queue_release(output_hwc->pp_tqueue, data->tsurface);
+   E_FREE(data);
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+_e_output_hwc_windows_pp_output_commit(E_Output_Hwc *output_hwc, tbm_surface_h tsurface)
+{
+   tbm_surface_h pp_tsurface = NULL;
+   tbm_error_e tbm_err;
+   E_Hwc_Window_Commit_Data *data = NULL;
+
+   ELOGF("HWC-WINS", "PP Layer Commit  output_hwc(%p)     pp_tsurface(%p)", NULL, NULL, output_hwc, tsurface);
+
+   tbm_err = tbm_surface_queue_enqueue(output_hwc->pp_tqueue, tsurface);
+   if (tbm_err != TBM_ERROR_NONE)
+     {
+        ERR("fail tbm_surface_queue_enqueue");
+        goto fail;
+     }
+
+   tbm_err = tbm_surface_queue_acquire(output_hwc->pp_tqueue, &pp_tsurface);
+   if (tbm_err != TBM_ERROR_NONE)
+     {
+        ERR("fail tbm_surface_queue_acquire");
+        goto fail;
+     }
+
+   data = E_NEW(E_Hwc_Window_Commit_Data, 1);
+   if (!data) goto fail;
+   data->tsurface = pp_tsurface;
+   tbm_surface_internal_ref(data->tsurface);
+
+   if (output_hwc->pp_output_commit)
+     {
+        output_hwc->pending_pp_commit_data_list = eina_list_append(output_hwc->pending_pp_commit_data_list, data);
+        return EINA_TRUE;
+     }
+
+   if (!_e_output_hwc_windows_pp_output_data_commit(output_hwc, data))
+     {
+        ERR("fail to _e_output_hwc_windows_pp_output_data_commit");
+        return EINA_FALSE;
+     }
+
+   return EINA_TRUE;
+
+fail:
+   tbm_surface_queue_release(output_hwc->pp_tqueue, tsurface);
+   if (pp_tsurface && pp_tsurface != tsurface)
+     tbm_surface_queue_release(output_hwc->pp_tqueue, pp_tsurface);
+
+   return EINA_FALSE;
+}
+
+static void
+_e_output_hwc_windows_pp_commit_handler(tdm_pp *pp, tbm_surface_h tsurface_src, tbm_surface_h tsurface_dst, void *user_data)
+{
+   E_Output *output = NULL;
+   E_Output_Hwc *output_hwc = NULL;
+   E_Hwc_Window *hwc_window = NULL;
+
+   output_hwc = (E_Output_Hwc *)user_data;
+   EINA_SAFETY_ON_NULL_RETURN(output_hwc);
+   hwc_window = _e_output_hwc_windows_pp_window_get(output_hwc, tsurface_src);
+   EINA_SAFETY_ON_NULL_RETURN(hwc_window);
+
+   output_hwc->pp_hwc_window_list = eina_list_remove(output_hwc->pp_hwc_window_list, hwc_window);
+
+   if (hwc_window->ec) e_pixmap_image_clear(hwc_window->ec->pixmap, 1);
+   e_hwc_window_commit_data_release(hwc_window);
+
+   if (eina_list_count(output_hwc->pending_pp_hwc_window_list) == 0)
+     {
+        output_hwc->wait_commit = EINA_FALSE;
+        output_hwc->pp_commit = EINA_FALSE;
+     }
+
+   ELOGF("HWC-WINS", "PP Commit Handler output_hwc(%p) tsurface src(%p) dst(%p)",
+         NULL, NULL, output_hwc, tsurface_src, tsurface_dst);
+
+   /* if pp_set is false, skip the commit */
+   if (!output_hwc->pp_set)
+     {
+        if (output_hwc->tpp)
+          {
+             tdm_pp_destroy(output_hwc->tpp);
+             output_hwc->tpp = NULL;
+          }
+        goto done;
+     }
+
+   output = output_hwc->output;
+   if (e_output_dpms_get(output))
+     {
+        _e_output_hwc_windows_pp_pending_data_remove(output_hwc);
+        tbm_surface_queue_release(output_hwc->pp_tqueue, tsurface_dst);
+
+        goto done;
+     }
+
+   if (!_e_output_hwc_windows_pp_output_commit(output_hwc, tsurface_dst))
+     ERR("fail to _e_output_hwc_windows_pp_output_commit");
+
+done:
+   tbm_surface_internal_unref(tsurface_src);
+   tbm_surface_internal_unref(tsurface_dst);
+}
+
+static Eina_Bool
+_e_output_hwc_pp_windows_info_set(E_Output_Hwc *output_hwc, E_Hwc_Window *hwc_window,
+                                  tbm_surface_h dst_tsurface)
+{
+   tdm_info_pp pp_info;
+   tdm_error ret = TDM_ERROR_NONE;
+   unsigned int aligned_width_src = 0, aligned_width_dst = 0;
+   tbm_surface_info_s surf_info_src, surf_info_dst;
+   tbm_surface_h src_tsurface = hwc_window->commit_data->tsurface;
+
+   /* when the pp_set_info is true, change the pp set_info */
+   if (!output_hwc->pp_set_info) return EINA_TRUE;
+   output_hwc->pp_set_info = EINA_FALSE;
+
+   tbm_surface_get_info(src_tsurface, &surf_info_src);
+
+   aligned_width_src = _e_output_hwc_windows_aligned_width_get(src_tsurface);
+   if (aligned_width_src == 0) return EINA_FALSE;
+
+   tbm_surface_get_info(dst_tsurface, &surf_info_dst);
+
+   aligned_width_dst = _e_output_hwc_windows_aligned_width_get(dst_tsurface);
+   if (aligned_width_dst == 0) return EINA_FALSE;
+
+   pp_info.src_config.size.h = aligned_width_src;
+   pp_info.src_config.size.v = surf_info_src.height;
+   pp_info.src_config.format = surf_info_src.format;
+
+   pp_info.dst_config.size.h = aligned_width_dst;
+   pp_info.dst_config.size.v = surf_info_dst.height;
+   pp_info.dst_config.format = surf_info_dst.format;
+
+   pp_info.transform = TDM_TRANSFORM_NORMAL;
+   pp_info.sync = 0;
+   pp_info.flags = 0;
+
+   pp_info.src_config.pos.x = output_hwc->pp_rect.x;
+   pp_info.src_config.pos.y = output_hwc->pp_rect.y;
+   pp_info.src_config.pos.w = output_hwc->pp_rect.w;
+   pp_info.src_config.pos.h = output_hwc->pp_rect.h;
+   pp_info.dst_config.pos.x = 0;
+   pp_info.dst_config.pos.y = 0;
+   pp_info.dst_config.pos.w = surf_info_dst.width;
+   pp_info.dst_config.pos.h = surf_info_dst.height;
+
+   ret = tdm_pp_set_info(output_hwc->tpp, &pp_info);
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(ret == TDM_ERROR_NONE, EINA_FALSE);
+
+   ELOGF("HWC-WINS", "PP Info  Output_Hwc(%p) src_rect(%d,%d),(%d,%d), dst_rect(%d,%d),(%d,%d)",
+         NULL, NULL, output_hwc,
+         pp_info.src_config.pos.x, pp_info.src_config.pos.y, pp_info.src_config.pos.w, pp_info.src_config.pos.h,
+         pp_info.dst_config.pos.x, pp_info.dst_config.pos.y, pp_info.dst_config.pos.w, pp_info.dst_config.pos.h);
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_output_hwc_windows_pp_window_commit(E_Output_Hwc *output_hwc, E_Hwc_Window *hwc_window)
+{
+   E_Output *output = NULL;
+   tbm_surface_h pp_tsurface = NULL;
+   tbm_error_e tbm_err = TBM_ERROR_NONE;
+   tdm_error terror = TDM_ERROR_NONE;
+   E_Hwc_Window_Commit_Data *commit_data = hwc_window->commit_data;
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(commit_data, EINA_FALSE);
+
+   tbm_surface_h tsurface = commit_data->tsurface;
+
+   ELOGF("HWC-WINS", "PP Commit  Output_Hwc(%p)   tsurface(%p) tqueue(%p) wl_buffer(%p) data(%p)",
+            NULL, NULL, output_hwc, commit_data->tsurface, output_hwc->pp_tqueue,
+            commit_data->buffer_ref.buffer ? commit_data->buffer_ref.buffer->resource : NULL, commit_data);
+
+   output = output_hwc->output;
+   if (e_output_dpms_get(output))
+     {
+        _e_output_hwc_windows_pp_pending_data_remove(output_hwc);
+        return EINA_FALSE;
+     }
+
+   tbm_err = tbm_surface_queue_dequeue(output_hwc->pp_tqueue, &pp_tsurface);
+   if (tbm_err != TBM_ERROR_NONE)
+     {
+        ERR("fail tbm_surface_queue_dequeue");
+        return EINA_FALSE;
+     }
+
+   if (!_e_output_hwc_pp_windows_info_set(output_hwc, hwc_window, pp_tsurface))
+     {
+        ERR("fail _e_output_hwc_windows_info_set");
+        goto pp_fail;
+     }
+
+   terror = tdm_pp_set_done_handler(output_hwc->tpp, _e_output_hwc_windows_pp_commit_handler, output_hwc);
+   EINA_SAFETY_ON_FALSE_GOTO(terror == TDM_ERROR_NONE, pp_fail);
+
+   tbm_surface_internal_ref(pp_tsurface);
+   tbm_surface_internal_ref(commit_data->tsurface);
+   terror = tdm_pp_attach(output_hwc->tpp, commit_data->tsurface, pp_tsurface);
+   EINA_SAFETY_ON_FALSE_GOTO(terror == TDM_ERROR_NONE, attach_fail);
+
+   output_hwc->pp_hwc_window_list = eina_list_append(output_hwc->pp_hwc_window_list, hwc_window);
+
+   terror = tdm_pp_commit(output_hwc->tpp);
+   EINA_SAFETY_ON_FALSE_GOTO(terror == TDM_ERROR_NONE, commit_fail);
+
+   output_hwc->wait_commit = EINA_TRUE;
+   output_hwc->pp_commit = EINA_TRUE;
+
+   return EINA_TRUE;
+
+commit_fail:
+   output_hwc->pp_hwc_window_list = eina_list_remove(output_hwc->pp_hwc_window_list, hwc_window);
+attach_fail:
+   tbm_surface_internal_unref(pp_tsurface);
+   tbm_surface_internal_unref(tsurface);
+pp_fail:
+   tbm_surface_queue_release(output_hwc->pp_tqueue, pp_tsurface);
+
+   ERR("failed _e_output_hwc_windows_pp_data_commit");
+
+   return EINA_FALSE;
+}
+
+static E_Hwc_Window *
+_e_output_hwc_windows_pp_get_hwc_window_for_zoom(E_Output_Hwc *output_hwc)
+{
+   const Eina_List *hwc_windows, *l;
+   E_Hwc_Window *hwc_window = NULL;
+   E_Hwc_Window *hwc_window_for_zoom = NULL;
+   int num = 0;
+   int w, h;
+
+   e_output_size_get(output_hwc->output, &w, &h);
+
+   hwc_windows = e_output_hwc_windows_get(output_hwc);
+   EINA_LIST_FOREACH(hwc_windows, l, hwc_window)
+   {
+      if (!e_hwc_window_is_on_hw_overlay(hwc_window)) continue;
+
+      hwc_window_for_zoom = hwc_window;
+      num++;
+   }
+
+   if (num != 1) return NULL;
+   if (!hwc_window_for_zoom->tsurface) return NULL;
+   if (tbm_surface_get_width(hwc_window_for_zoom->tsurface) != w ||
+       tbm_surface_get_height(hwc_window_for_zoom->tsurface) != h)
+     return NULL;
+
+   return hwc_window_for_zoom;
+}
+
+static Eina_Bool
+_e_output_hwc_windows_pp_commit(E_Output_Hwc *output_hwc)
+{
+   E_Hwc_Window_Commit_Data *commit_data = NULL;
+   E_Hwc_Window *hwc_window = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc->pp_tqueue, EINA_FALSE);
+
+   hwc_window = _e_output_hwc_windows_pp_get_hwc_window_for_zoom(output_hwc);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+   commit_data = hwc_window->commit_data;
+   if (!commit_data) return EINA_TRUE;
+   if (!commit_data->tsurface) return EINA_TRUE;
+
+   if (!tbm_surface_queue_can_dequeue(output_hwc->pp_tqueue, 0))
+     {
+        ELOGF("HWC-WINS", "PP Commit  Can Dequeue failed Output_Hwc(%p)   tsurface(%p) tqueue(%p) wl_buffer(%p) data(%p)",
+              NULL, NULL, output_hwc, commit_data->tsurface, output_hwc->pp_tqueue,
+              commit_data->buffer_ref.buffer ? commit_data->buffer_ref.buffer->resource : NULL, commit_data);
+        output_hwc->pending_pp_hwc_window_list = eina_list_append(output_hwc->pending_pp_hwc_window_list, hwc_window);
+
+        output_hwc->wait_commit = EINA_TRUE;
+
+        return EINA_TRUE;
+     }
+
+   if (eina_list_count(output_hwc->pending_pp_hwc_window_list) != 0)
+     {
+        ELOGF("HWC-WINS", "PP Commit  Pending pp data remained Output_Hwc(%p)   tsurface(%p) tqueue(%p) wl_buffer(%p) data(%p)",
+              NULL, NULL, output_hwc, commit_data->tsurface, output_hwc->pp_tqueue,
+              commit_data->buffer_ref.buffer ? commit_data->buffer_ref.buffer->resource : NULL, commit_data);
+        output_hwc->pending_pp_hwc_window_list = eina_list_append(output_hwc->pending_pp_hwc_window_list, hwc_window);
+
+        output_hwc->wait_commit = EINA_TRUE;
+
+        return EINA_TRUE;
+     }
+
+   if (!_e_output_hwc_windows_pp_window_commit(output_hwc, hwc_window))
+     {
+        ERR("fail _e_output_hwc_windows_pp_data_commit");
+        e_hwc_window_commit_data_release(hwc_window);
+        return EINA_FALSE;
+     }
+
+   return EINA_TRUE;
+}
+
+static void
+_e_output_hwc_windows_status_print(E_Output_Hwc *output_hwc, Eina_Bool with_target)
+{
+    const Eina_List *l;
+    Eina_List *sort_wnds;
+    E_Hwc_Window *hwc_window;
+
+    sort_wnds = eina_list_clone(output_hwc->hwc_windows);
+    sort_wnds = eina_list_sort(sort_wnds, eina_list_count(sort_wnds), _e_output_hwc_windows_sort_cb);
+
+    EINA_LIST_FOREACH(sort_wnds, l, hwc_window)
+      {
+         if (hwc_window->state == E_HWC_WINDOW_STATE_NONE) continue;
+
+         if (e_hwc_window_is_target(hwc_window))
+           {
+              if (!with_target) continue;
+
+              ELOGF("HWC-WINS", "  ehw:%p ts:%p -- {%25s}, state:%s",
+                    NULL, NULL, hwc_window, hwc_window->tsurface, "@TARGET WINDOW@",
+                    e_hwc_window_state_string_get(hwc_window->state));
+              continue;
+           }
+
+         ELOGF("HWC-WINS", "  ehw:%p ts:%p -- {%25s}, state:%s, zpos:%d, deleted:%s",
+               hwc_window->ec ? hwc_window->ec->pixmap : NULL, hwc_window->ec,
+               hwc_window, hwc_window->tsurface, hwc_window->ec ? hwc_window->ec->icccm.title : "UNKNOWN",
+               e_hwc_window_state_string_get(hwc_window->state),
+               hwc_window->zpos, hwc_window->is_deleted ? "yes" : "no");
+      }
+
+    eina_list_free(sort_wnds);
+}
+
+static void
+_e_output_hwc_windows_ouput_commit_dump(E_Output_Hwc *output_hwc)
+{
+    const Eina_List *l;
+    Eina_List *sort_wnds;
+    E_Hwc_Window *hwc_window;
+    char fname[PATH_MAX];
+    Ecore_Window ec_win;
+    int i = 0;
+
+    sort_wnds = eina_list_clone(output_hwc->hwc_windows);
+    sort_wnds = eina_list_sort(sort_wnds, eina_list_count(sort_wnds), _e_output_hwc_windows_sort_cb);
+
+    EINA_LIST_FOREACH(sort_wnds, l, hwc_window)
+      {
+         if (hwc_window->state == E_HWC_WINDOW_STATE_NONE) continue;
+
+         ec_win = e_client_util_win_get(hwc_window->ec);
+
+         if (e_hwc_window_is_target(hwc_window))
+           snprintf(fname, sizeof(fname), "(%d)_output_commit_0x%08x_%s", i++, ec_win, e_hwc_window_state_string_get(hwc_window->state));
+         else
+           snprintf(fname, sizeof(fname), "(%d)_output_commit_0x%08x_%s_%d", i++, ec_win, e_hwc_window_state_string_get(hwc_window->state), hwc_window->zpos);
+
+         tbm_surface_internal_dump_buffer(hwc_window->tsurface, fname);
+      }
+
+    eina_list_free(sort_wnds);
+}
+
+static E_Hwc_Window *
+_e_output_hwc_windows_window_find_by_twin(E_Output_Hwc *output_hwc, tdm_hwc_window *hwc_win)
+{
+   Eina_List *l;
+   E_Hwc_Window *hwc_window;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_win, NULL);
+
+   EINA_LIST_FOREACH(output_hwc->hwc_windows, l, hwc_window)
+     {
+        if (hwc_window->thwc_window == hwc_win) return hwc_window;
+     }
+
+   return NULL;
+}
+
+static Eina_Bool
+_e_output_hwc_windows_compsitions_update(E_Output_Hwc *output_hwc)
+{
+   const Eina_List *l;
+   E_Hwc_Window *hwc_window;
+
+   EINA_LIST_FOREACH(e_output_hwc_windows_get(output_hwc), l, hwc_window)
+     {
+        if (e_hwc_window_is_target(hwc_window)) continue;
+
+        if (!e_hwc_window_compsition_update(hwc_window))
+          {
+             ERR("HWC-WINS: cannot update E_Hwc_Window(%p)", hwc_window);
+             return EINA_FALSE;
+          }
+    }
+
+#if DBG_EVALUATE
+   ELOGF("HWC-WINS", " Request HWC Validation to TDM HWC:", NULL, NULL);
+   _e_output_hwc_windows_status_print(output_hwc, EINA_FALSE);
+#endif
+
+   return EINA_TRUE;
+}
+
+static E_Hwc_Window_State
+_e_output_hwc_windows_window_state_get(tdm_hwc_window_composition composition_type)
+{
+   E_Hwc_Window_State state = E_HWC_WINDOW_STATE_NONE;
+
+   switch (composition_type)
+     {
+      case TDM_COMPOSITION_NONE:
+        state = E_HWC_WINDOW_STATE_NONE;
+        break;
+      case TDM_COMPOSITION_CLIENT:
+        state = E_HWC_WINDOW_STATE_CLIENT;
+        break;
+      case TDM_COMPOSITION_DEVICE:
+        state = E_HWC_WINDOW_STATE_DEVICE;
+        break;
+      case TDM_COMPOSITION_DEVICE_CANDIDATE:
+        state = E_HWC_WINDOW_STATE_DEVICE_CANDIDATE;
+        break;
+      case TDM_COMPOSITION_CURSOR:
+        state = E_HWC_WINDOW_STATE_CURSOR;
+        break;
+      case TDM_COMPOSITION_VIDEO:
+        state = E_HWC_WINDOW_STATE_VIDEO;
+        break;
+      default:
+        state = E_HWC_WINDOW_STATE_NONE;
+        ERR("HWC-WINS: unknown state of hwc_window.");
+     }
+
+   return state;
+}
+
+static Eina_Bool
+_e_output_hwc_windows_accept(E_Output_Hwc *output_hwc, uint32_t num_changes)
+{
+   E_Output *output = output_hwc->output;
+   E_Hwc_Window *hwc_window;
+   E_Hwc_Window_State state;
+   tdm_error terror;
+   tdm_output *toutput = output->toutput;
+   tdm_hwc_window **changed_hwc_window = NULL;
+   tdm_hwc_window_composition *composition_types = NULL;
+   Eina_Bool accept_changes = EINA_TRUE;
+   int i;
+
+   changed_hwc_window = E_NEW(tdm_hwc_window *, num_changes);
+   EINA_SAFETY_ON_NULL_GOTO(changed_hwc_window, fail);
+
+   composition_types = E_NEW(tdm_hwc_window_composition, num_changes);
+   EINA_SAFETY_ON_NULL_GOTO(composition_types, fail);
+
+   terror = tdm_output_hwc_get_changed_composition_types(toutput,
+                                         &num_changes, changed_hwc_window,
+                                         composition_types);
+   if (terror != TDM_ERROR_NONE)
+     {
+        ERR("HWC-WINS: failed to get changed composition types");
+        goto fail;
+     }
+
+   ELOGF("HWC-WINS", " Accept Changes NUM : %d", NULL, NULL, num_changes);
+
+   for (i = 0; i < num_changes; ++i)
+     {
+        hwc_window = _e_output_hwc_windows_window_find_by_twin(output_hwc, changed_hwc_window[i]);
+        if (!hwc_window)
+          {
+             ERR("HWC-WINS: cannot find the E_Hwc_Window by hwc hwc_window");
+             goto fail;
+          }
+
+        /* accept_changes failed at DEVICE to CLIENT transition */
+        if (hwc_window->prev_state == E_HWC_WINDOW_STATE_DEVICE &&
+            composition_types[i] == TDM_COMPOSITION_CLIENT)
+          {
+             if (!e_hwc_window_is_on_target_window(hwc_window))
+               {
+                  hwc_window->uncompleted_transition = E_HWC_WINDOW_TRANSITION_DEVICE_TO_CLIENT;
+                  accept_changes = EINA_FALSE;
+
+                  ELOGF("HWC-WINS", " E_HWC_WINDOW_TRANSITION_DEVICE_TO_CLIENT is set.(Accept_Changes)",
+                        hwc_window->ec ? ec->pixmap : NULL, hwc_window->ec);
+               }
+          }
+
+        /* update the state with the changed compsition */
+        state = _e_output_hwc_windows_window_state_get(composition_types[i]);
+        e_hwc_window_state_set(hwc_window, state);
+     }
+
+#if DBG_EVALUATE
+   ELOGF("HWC-WINS", " Modified after HWC Validation:", NULL, NULL);
+   _e_output_hwc_windows_status_print(output_hwc, EINA_FALSE);
+#endif
+
+   /* re-validate when there is a DEVICE_TO_CLIENT transition */
+   if (!accept_changes) goto fail;
+
+   /* accept changes */
+   terror = tdm_output_hwc_accept_changes(toutput);
+   if (terror != TDM_ERROR_NONE)
+     {
+        ERR("HWC-WINS: failed to accept changes required by the hwc extension");
+        goto fail;
+     }
+
+   free(changed_hwc_window);
+   free(composition_types);
+
+   return EINA_TRUE;
+
+fail:
+   if (changed_hwc_window) free(changed_hwc_window);
+   if (composition_types) free(composition_types);
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+_e_output_hwc_windows_validate(E_Output_Hwc *output_hwc, Eina_List *visible_windows_list, uint32_t *num_changes)
+{
+   E_Output *output = output_hwc->output;
+   tdm_error terror;
+   tdm_output *toutput = output->toutput;
+   tdm_hwc_window **thwc_windows = NULL;
+   int i, n_thw;
+   E_Hwc_Window *hwc_window;
+   const Eina_List *l;
+
+   n_thw = eina_list_count(visible_windows_list);
+   if (n_thw)
+     {
+        thwc_windows = E_NEW(tdm_hwc_window *, n_thw);
+        EINA_SAFETY_ON_NULL_GOTO(thwc_windows, error);
+
+        i = 0;
+        EINA_LIST_FOREACH(visible_windows_list, l, hwc_window)
+          thwc_windows[i++] = hwc_window->thwc_window;
+     }
+
+   /* make hwc extension choose which clients will own hw overlays */
+   terror = tdm_output_hwc_validate(toutput, thwc_windows, n_thw, num_changes);
+   if (terror != TDM_ERROR_NONE) goto error;
+
+   E_FREE(thwc_windows);
+
+   return EINA_TRUE;
+
+error:
+   ERR("HWC-WINS: failed to validate the output(%p)", toutput);
+   E_FREE(thwc_windows);
+
+   return EINA_FALSE;
+}
+
+static void
+_e_output_hwc_windows_activation_states_update(E_Output_Hwc *output_hwc)
+{
+   E_Hwc_Window *hwc_window;
+   const Eina_List *l;
+
+   /* mark the active/deactive on hwc_window */
+   EINA_LIST_FOREACH(e_output_hwc_windows_get(output_hwc), l, hwc_window)
+     {
+        if (hwc_window->is_deleted) continue;
+        if (e_hwc_window_is_target(hwc_window)) continue;
+
+        if (e_hwc_window_is_on_hw_overlay(hwc_window))
+          /* notify the hwc_window that it will be displayed on hw layer */
+          e_hwc_window_activate(hwc_window);
+        else
+          /* notify the hwc_window that it will be composite on the target buffer */
+          e_hwc_window_deactivate(hwc_window);
+      }
+}
+
+static Eina_Bool
+_e_output_hwc_windows_target_window_render(E_Output *output, E_Hwc_Window_Target *target_hwc_window)
+{
+    if (target_hwc_window->hwc_window.state == E_HWC_WINDOW_STATE_NONE) return EINA_TRUE;
+
+    if (e_comp_canvas_norender_get() > 0)
+      {
+           ELOGF("HWC-WINS", " NoRender get. Do not ecore_evas_manual_render.", NULL, NULL);
+          return EINA_TRUE;
+      }
+
+   /* render the ecore_evas and
+      update_ee is to be true at post_render_cb when the render is successful. */
+   TRACE_DS_BEGIN(MANUAL RENDER);
+
+   if (e_hwc_window_target_surface_queue_can_dequeue(target_hwc_window))
+     {
+        ELOGF("HWC-WINS", "###### Render target window(ecore_evas_manual_render))", NULL, NULL);
+        ecore_evas_manual_render(target_hwc_window->ee);
+     }
+
+   TRACE_DS_END();
+
+   return EINA_TRUE;
+}
+
+static Eina_List *
+_e_output_hwc_windows_visible_windows_list_get(E_Output_Hwc *output_hwc)
+{
+   Eina_List *windows_list = NULL;
+   Eina_List *l;
+   E_Hwc_Window *hwc_window;
+   E_Client  *ec;
+   Evas_Object *o;
+   int scr_w, scr_h;
+   int zpos = 0;
+   E_Comp_Wl_Client_Data *cdata = NULL;
+
+   for (o = evas_object_top_get(e_comp->evas); o; o = evas_object_below_get(o))
+     {
+        ec = evas_object_data_get(o, "E_Client");
+        if (!ec) continue;
+        if (!ec->hwc_window) continue;
+        if (e_object_is_del(E_OBJECT(ec))) continue;
+
+        hwc_window = ec->hwc_window;
+
+        // check clients to skip composite
+        if (e_client_util_ignored_get(ec) || (!evas_object_visible_get(ec->frame)))
+          {
+             e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE);
+             continue;
+          }
+
+        // check geometry if located out of screen such as quick panel
+        ecore_evas_geometry_get(e_comp->ee, NULL, NULL, &scr_w, &scr_h);
+        if (!E_INTERSECTS(0, 0, scr_w, scr_h, ec->client.x, ec->client.y, ec->client.w, ec->client.h))
+          {
+             e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE);
+             e_hwc_window_zpos_set(hwc_window, ZPOS_NONE);
+             continue;
+          }
+
+        if (evas_object_data_get(ec->frame, "comp_skip"))
+          {
+             e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE);
+             continue;
+          }
+
+        /* skip all small clients except the video clients */
+        if ((ec->w == 1 || ec->h == 1) && !e_hwc_window_is_video(hwc_window))
+          {
+             e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE);
+             continue;
+          }
+
+        /* skip the cdata is null */
+        cdata = (E_Comp_Wl_Client_Data*)ec->comp_data;
+        if (!cdata)
+          {
+             e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE);
+             ELOGF("HWC-WINS", "   ehw:%p -- {%25s} cdata is NULL. Set E_HWC_WINDOW_STATE_NONE.",
+                   ec->pixmap, ec, ec->hwc_window, ec->icccm.title);
+             continue;
+          }
+
+        /* skip the cdata->buffer_ref.buffer is null */
+        if (!cdata->buffer_ref.buffer)
+          {
+             e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE);
+             ELOGF("HWC-WINS", "   ehw:%p -- {%25s} cdata->buffer_ref.buffer is NULL. Set E_HWC_WINDOW_STATE_NONE.",
+                   ec->pixmap, ec, ec->hwc_window, ec->icccm.title);
+             continue;
+          }
+
+        if (e_hwc_window_is_video(hwc_window))
+          {
+             e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_VIDEO);
+             continue;
+          }
+
+        windows_list = eina_list_append(windows_list, hwc_window);
+     }
+
+   /* assign zpos */
+   EINA_LIST_REVERSE_FOREACH(windows_list, l, hwc_window)
+     e_hwc_window_zpos_set(hwc_window, zpos++);
+
+   output_hwc->num_visible_windows = eina_list_count(windows_list);
+
+#if DBG_EVALUATE
+   ELOGF("HWC-WINS", " The number of visible clients:%d.", NULL, NULL, output_hwc->num_visible_windows);
+#endif
+   return windows_list;
+}
+
+static Eina_Bool
+_e_output_hwc_windows_full_gl_composite_check(E_Output_Hwc *output_hwc, Eina_List *visible_windows_list)
+{
+   Eina_List *l;
+   E_Client *ec;
+   E_Hwc_Window *hwc_window = NULL;
+
+   /* make the full_gl_composite when the zoom is enabled */
+   if (output_hwc->output->zoom_set) goto full_gl_composite;
+
+   /* full composite is forced to be set */
+   if (e_output_hwc_deactive_get(output_hwc)) goto full_gl_composite;
+
+   /* hwc_window manager required full GLES composition */
+   if (e_comp->nocomp_override > 0)
+     {
+        ELOGF("HWC-WINS", "  HWC_MODE_HYBRID due to nocomp_override > 0.", NULL, NULL);
+        goto full_gl_composite;
+     }
+
+   EINA_LIST_FOREACH(visible_windows_list, l, hwc_window)
+     {
+        ec = hwc_window->ec;
+
+        // if there is a ec which is lower than quickpanel and quickpanel is opened.
+        if (E_POLICY_QUICKPANEL_LAYER >= evas_object_layer_get(ec->frame))
+          {
+             // check whether quickpanel is open than break
+             if (e_qp_visible_get())
+               {
+                   ELOGF("HWC-WINS", "    HWC_MODE_NONE due to quickpanel is opened.{%25s}.",
+                         ec->pixmap, ec, ec->icccm.title);
+                   goto full_gl_composite;
+               }
+          }
+
+        // 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)
+          {
+             ELOGF("HWC-WINS", "  HWC_MODE_NONE due to E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE{%25s}.",
+                   ec->pixmap, ec, ec->icccm.title);
+             goto full_gl_composite;
+          }
+
+        // if there is UI subfrace, it means need to composite
+        if (e_client_normal_client_has(ec))
+          {
+            ELOGF("HWC-WINS", "  HWC_MODE_NONE due to UI subfrace{%25s}.",
+                  ec->pixmap, ec, ec->icccm.title);
+            goto full_gl_composite;
+          }
+     }
+
+   return EINA_FALSE;
+
+full_gl_composite:
+   EINA_LIST_FOREACH(visible_windows_list, l, hwc_window)
+     {
+        /* The video window is not composited by gl compositor */
+        if (e_hwc_window_is_video(hwc_window)) continue;
+
+        e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_CLIENT);
+
+        ELOGF("HWC-WINS", "   ehw:%p -- {%25s} is NOT hwc_acceptable.",
+              hwc_window->ec->pixmap, hwc_window->ec, hwc_window, hwc_window->ec->icccm.title);
+     }
+   return EINA_TRUE;
+}
+
+/* filter visible clients by the hwc_window manager
+ *
+ * returns list of clients which are acceptable to be composited by hw,
+ * it's a caller responsibility to free it
+ *
+ * for optimized hwc the returned list contains ALL clients
+ */
+static void
+_e_output_hwc_windows_hwc_acceptable_check(Eina_List *visible_windows_list)
+{
+   Eina_List *l;
+   E_Hwc_Window *hwc_window = NULL;
+
+   EINA_LIST_FOREACH(visible_windows_list, l, hwc_window)
+     {
+        /* The video window is not composited by gl compositor */
+        if (e_hwc_window_is_video(hwc_window)) continue;
+
+        // check clients are able to use hwc
+        if (_e_output_hwc_windows_device_state_check(hwc_window->ec))
+          e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_DEVICE);
+        else
+          e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_CLIENT);
+     }
+}
+
+static Eina_Bool
+_e_output_hwc_windows_composition_evaulate(E_Output_Hwc *output_hwc, Eina_List *visible_windows_list)
+{
+   Eina_Bool ret = EINA_FALSE;
+   uint32_t num_changes;
+
+   /* evaluate the transition */
+   if (!_e_output_hwc_windows_compsitions_update(output_hwc))
+     {
+        ERR("HWC-WINS: _e_output_hwc_windows_compsitions_update failed.");
+        ret = EINA_FALSE;
+        goto done;
+     }
+
+   /* validate the updated hwc_windows by asking tdm_hwc_output */
+   if (!_e_output_hwc_windows_validate(output_hwc, visible_windows_list, &num_changes))
+     {
+        ERR("HWC-WINS: _e_output_hwc_windows_validate failed.");
+        ret = EINA_FALSE;
+        goto done;
+     }
+
+   if (num_changes > 0)
+     {
+        if (_e_output_hwc_windows_accept(output_hwc, num_changes))
+          ret = EINA_TRUE;
+        else
+          ret = EINA_FALSE;
+     }
+   else
+     ret = EINA_TRUE;
+
+done:
+
+   return ret;
+}
+
+static Eina_List *
+_e_output_hwc_windows_states_evaluate(E_Output_Hwc *output_hwc)
+{
+   Eina_List *visible_windows_list = NULL;
+
+   /* get the visible ecs */
+   visible_windows_list = _e_output_hwc_windows_visible_windows_list_get(output_hwc);
+
+   /* check the gles composite with all hwc_windows. */
+   if (!_e_output_hwc_windows_full_gl_composite_check(output_hwc, visible_windows_list))
+     {
+        /* by demand of hwc_window manager to prevent some e_clients to be shown by hw directly */
+        _e_output_hwc_windows_hwc_acceptable_check(visible_windows_list);
+     }
+
+   return visible_windows_list;
+}
+
+/* evaluate the hwc_windows */
+static Eina_Bool
+_e_output_hwc_windows_evaluate(E_Output_Hwc *output_hwc, Eina_List *visible_windows_list)
+{
+   E_Output_Hwc_Mode hwc_mode = E_OUTPUT_HWC_MODE_NONE;
+   E_Hwc_Window *target_window = (E_Hwc_Window *)output_hwc->target_hwc_window;
+
+   ELOGF("HWC-WINS", "====================== Output HWC Apply (evaluate) ======================", NULL, NULL);
+
+   /* evaulate the compositions with the states*/
+   if (_e_output_hwc_windows_composition_evaulate(output_hwc, visible_windows_list))
+        ELOGF("HWC-WINS", " Succeed the compsition_evaulation.", NULL, NULL);
+   else
+        ELOGF("HWC-WINS", " Need the comopsition re-evaulation.", NULL, NULL);
+
+   /* update the activate/decativate state */
+   _e_output_hwc_windows_activation_states_update(output_hwc);
+
+   /* decide the E_OUTPUT_HWC_MODE */
+   hwc_mode = _e_output_hwc_windows_hwc_mode_get(output_hwc);
+   if (output_hwc->hwc_mode != hwc_mode)
+     {
+        if (hwc_mode == E_OUTPUT_HWC_MODE_HYBRID || hwc_mode == E_OUTPUT_HWC_MODE_NONE)
+          ecore_event_add(E_EVENT_COMPOSITOR_ENABLE, NULL, NULL, NULL);
+        else
+          ecore_event_add(E_EVENT_COMPOSITOR_DISABLE, NULL, NULL, NULL);
+
+        output_hwc->hwc_mode  = hwc_mode;
+     }
+
+#if DBG_EVALUATE
+   if (hwc_mode == E_OUTPUT_HWC_MODE_NONE)
+     ELOGF("HWC-WINS", " HWC_MODE is NONE composition.", NULL, NULL);
+   else if (hwc_mode == E_OUTPUT_HWC_MODE_HYBRID)
+     ELOGF("HWC-WINS", " HWC_MODE is HYBRID composition.", NULL, NULL);
+   else
+     ELOGF("HWC-WINS", " HWC_MODE is FULL HW composition.", NULL, NULL);
+#endif
+
+   /* set the state of the target_window */
+   if (hwc_mode == E_OUTPUT_HWC_MODE_HYBRID || hwc_mode == E_OUTPUT_HWC_MODE_NONE)
+     e_hwc_window_state_set(target_window, E_HWC_WINDOW_STATE_DEVICE);
+   else
+     e_hwc_window_state_set(target_window, E_HWC_WINDOW_STATE_NONE);
+
+    /* target state is DEVICE and no surface, then return false */
+    if (e_hwc_window_state_get(target_window) == E_HWC_WINDOW_STATE_DEVICE &&
+        target_window->tsurface == NULL)
+      {
+         ELOGF("HWC-WINS", "Need target_window buffer.", NULL, NULL);
+         return EINA_FALSE;
+      }
+
+   return EINA_TRUE;
+}
+
+static void
+_e_output_hwc_windows_prev_states_update(E_Output_Hwc *output_hwc)
+{
+   E_Hwc_Window *hwc_window = NULL;
+   Eina_List *l;
+
+   EINA_LIST_FOREACH(output_hwc->hwc_windows, l, hwc_window)
+      e_hwc_window_prev_state_update(hwc_window);
+}
+
+/* check if there is a need to update the output */
+static Eina_Bool
+_e_output_hwc_windows_update_changes(E_Output_Hwc *output_hwc)
+{
+   const Eina_List *l;
+   E_Hwc_Window *hwc_window;
+   Eina_Bool update_changes = EINA_FALSE;
+
+   /* fetch the target buffer */
+   if (e_hwc_window_target_buffer_fetch(output_hwc->target_hwc_window)) // try aquire
+     update_changes = EINA_TRUE;
+
+   /* fetch the windows buffers */
+   EINA_LIST_FOREACH(e_output_hwc_windows_get(output_hwc), l, hwc_window)
+     {
+        if (e_hwc_window_is_target(hwc_window)) continue;
+
+        if (!e_hwc_window_buffer_fetch(hwc_window))
+             continue;
+
+        if (!e_hwc_window_buffer_update(hwc_window))
+          {
+             ERR("HWC-WINS: cannot update E_Hwc_Window(%p)", hwc_window);
+             continue;
+          }
+
+        update_changes = EINA_TRUE;
+     }
+
+   return update_changes;
+}
+
+EINTERN Eina_Bool
+e_output_hwc_windows_init(E_Output_Hwc *output_hwc)
+{
+   return EINA_TRUE;
+}
+
+EINTERN void
+e_output_hwc_windows_deinit(void)
+{
+   // TDOO:
+   ;;;
+}
+
+EINTERN const Eina_List *
+e_output_hwc_windows_get(E_Output_Hwc *output_hwc)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, NULL);
+
+   return output_hwc->hwc_windows;
+}
+
+EINTERN Eina_Bool
+e_output_hwc_windows_render(E_Output_Hwc *output_hwc)
+{
+   E_Output *output = output_hwc->output;
+   E_Hwc_Window_Target *target_hwc_window;
+
+   target_hwc_window = output_hwc->target_hwc_window;
+   if (!target_hwc_window)
+     {
+        ERR("fail to get target hwc_window for output(%p).", output);
+        return EINA_FALSE;
+     }
+
+   if (!_e_output_hwc_windows_target_window_render(output, target_hwc_window))
+     ERR("fail to render output(%p).", output);
+
+   return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_output_hwc_windows_commit(E_Output_Hwc *output_hwc)
+{
+   E_Hwc_Window *hwc_window = NULL;
+   Eina_List *l;
+   E_Output *output = NULL;
+   tdm_error error = TDM_ERROR_NONE;
+   Eina_List *visible_windows_list = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, EINA_FALSE);
+
+   output = output_hwc->output;
+
+   if (output_hwc->wait_commit)
+     {
+        ELOGF("HWC-WINS", "!!!!!!!! Didn't get Output Commit Handler Yet !!!!!!!!", NULL, NULL);
+        return EINA_TRUE;
+     }
+
+   if (e_comp_canvas_norender_get() > 0)
+     {
+        ELOGF("HWC-WINS", " Block Display... NoRender get.", NULL, NULL);
+        return EINA_TRUE;
+     }
+
+   if (output->dpms == E_OUTPUT_DPMS_OFF)
+     {
+        EINA_LIST_FOREACH(output_hwc->hwc_windows, l, hwc_window)
+           _e_output_hwc_windows_offscreen_commit(output, hwc_window);
+
+        return EINA_TRUE;
+     }
+
+   /* evaulate the current states */
+   visible_windows_list = _e_output_hwc_windows_states_evaluate(output_hwc);
+
+   if (_e_output_hwc_windows_update_changes(output_hwc) ||
+       output_hwc->hwc_mode == E_OUTPUT_HWC_MODE_NONE)
+     {
+        if (!_e_output_hwc_windows_evaluate(output_hwc, visible_windows_list))
+          {
+             ELOGF("HWC-WINS", "Evaluation is not completed. No Commit at this time.", NULL, NULL);
+             /* update the previous states. */
+             _e_output_hwc_windows_prev_states_update(output_hwc);
+             goto fail;
+          }
+
+        EINA_LIST_FOREACH(output_hwc->hwc_windows, l, hwc_window)
+           _e_output_hwc_windows_prepare_commit(output, hwc_window);
+
+        if (output->zoom_set)
+          {
+             e_output_zoom_rotating_check(output);
+             ELOGF("HWC-WINS", "###### PP Commit", NULL, NULL);
+             if (!_e_output_hwc_windows_pp_commit(output_hwc))
+               {
+                  ERR("_e_output_hwc_windows_pp_commit failed.");
+                  goto fail;
+               }
+          }
+        else
+          {
+             ELOGF("HWC-WINS", "!!!!!!!! Output Commit !!!!!!!!", NULL, NULL);
+             ELOGF("HWC-WINS", " The number of visible clients:%d.", NULL, NULL, output_hwc->num_visible_windows);
+             _e_output_hwc_windows_status_print(output_hwc, EINA_TRUE);
+             _e_output_hwc_windows_ouput_commit_dump(output_hwc);
+
+             error = tdm_output_commit(output->toutput, 0, _e_output_hwc_windows_commit_handler, output_hwc);
+             if (error != TDM_ERROR_NONE)
+             {
+                ERR("tdm_output_commit failed.");
+                _e_output_hwc_windows_commit_handler(output->toutput, 0, 0, 0, output_hwc);
+                goto fail;
+             }
+
+             output_hwc->wait_commit = EINA_TRUE;
+          }
+
+       /* update the previous states. */
+       _e_output_hwc_windows_prev_states_update(output_hwc);
+     }
+
+   if (visible_windows_list)
+     eina_list_free(visible_windows_list);
+
+   return EINA_TRUE;
+
+fail:
+
+   if (visible_windows_list)
+     eina_list_free(visible_windows_list);
+
+   return EINA_FALSE;
+}
+
+EINTERN Eina_Bool
+e_output_hwc_windows_pp_commit_possible_check(E_Output_Hwc *output_hwc)
+{
+   if (!output_hwc->pp_set) return EINA_FALSE;
+
+   if (output_hwc->pp_tqueue)
+     {
+        if (!tbm_surface_queue_can_dequeue(output_hwc->pp_tqueue, 0))
+          return EINA_FALSE;
+     }
+
+   if (output_hwc->pending_pp_hwc_window_list)
+     {
+        if (eina_list_count(output_hwc->pending_pp_hwc_window_list) != 0)
+          return EINA_FALSE;
+     }
+
+   return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_output_hwc_windows_zoom_set(E_Output_Hwc *output_hwc, Eina_Rectangle *rect)
+{
+   E_Comp_Screen *e_comp_screen = NULL;
+   tdm_error ret = TDM_ERROR_NONE;
+   int w, h;
+   Eina_List *l;
+   E_Hwc_Window *hwc_window;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, EINA_FALSE);
+
+   if ((output_hwc->pp_rect.x == rect->x) &&
+       (output_hwc->pp_rect.y == rect->y) &&
+       (output_hwc->pp_rect.w == rect->w) &&
+       (output_hwc->pp_rect.h == rect->h))
+     return EINA_TRUE;
+
+   e_comp_screen = e_comp->e_comp_screen;
+   e_output_size_get(output_hwc->output, &w, &h);
+
+   if (!output_hwc->tpp)
+     {
+        output_hwc->tpp = tdm_display_create_pp(e_comp_screen->tdisplay, &ret);
+        if (ret != TDM_ERROR_NONE)
+          {
+             ERR("fail tdm pp create");
+             goto fail;
+          }
+     }
+
+   if (!output_hwc->pp_tqueue)
+     {
+        //TODO: Does e20 get the buffer flags from the tdm backend?
+        output_hwc->pp_tqueue = tbm_surface_queue_create(3, w, h, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
+        if (!output_hwc->pp_tqueue)
+          {
+             ERR("fail tbm_surface_queue_create");
+             goto fail;
+          }
+     }
+
+   output_hwc->pp_rect.x = rect->x;
+   output_hwc->pp_rect.y = rect->y;
+   output_hwc->pp_rect.w = rect->w;
+   output_hwc->pp_rect.h = rect->h;
+
+   output_hwc->pp_set = EINA_TRUE;
+   output_hwc->target_hwc_window->skip_surface_set = EINA_TRUE;
+   output_hwc->pp_set_info = EINA_TRUE;
+
+   EINA_LIST_FOREACH(output_hwc->hwc_windows, l, hwc_window)
+     {
+        if (e_hwc_window_state_get(hwc_window) ==E_HWC_WINDOW_STATE_NONE) continue;
+        if (e_hwc_window_is_target(hwc_window)) continue;
+        if (e_hwc_window_is_video(hwc_window)) continue;
+
+        hwc_window->update_exist = EINA_TRUE;
+     }
+
+   /* to wake up main loop */
+   uint64_t value = 1;
+   if (write(output_hwc->target_hwc_window->event_fd, &value, sizeof(value)) < 0)
+     ERR("failed to wake up main loop:%m");
+
+   return EINA_TRUE;
+
+fail:
+   if (output_hwc->tpp)
+     {
+        tdm_pp_destroy(output_hwc->tpp);
+        output_hwc->tpp = NULL;
+     }
+
+   return EINA_FALSE;
+}
+
+EINTERN void
+e_output_hwc_windows_zoom_unset(E_Output_Hwc *output_hwc)
+{
+   EINA_SAFETY_ON_NULL_RETURN(output_hwc);
+
+   output_hwc->pp_set_info = EINA_FALSE;
+   output_hwc->target_hwc_window->skip_surface_set = EINA_FALSE;
+   output_hwc->pp_set = EINA_FALSE;
+
+   output_hwc->pp_rect.x = 0;
+   output_hwc->pp_rect.y = 0;
+   output_hwc->pp_rect.w = 0;
+   output_hwc->pp_rect.h = 0;
+
+   _e_output_hwc_windows_pp_pending_data_remove(output_hwc);
+
+   if (output_hwc->pp_tsurface)
+     tbm_surface_queue_release(output_hwc->pp_tqueue, output_hwc->pp_tsurface);
+
+   if (output_hwc->pp_tqueue)
+     {
+        tbm_surface_queue_destroy(output_hwc->pp_tqueue);
+        output_hwc->pp_tqueue = NULL;
+     }
+
+   if (!output_hwc->pp_commit)
+     {
+        if (output_hwc->tpp)
+          {
+             tdm_pp_destroy(output_hwc->tpp);
+             output_hwc->tpp = NULL;
+          }
+     }
+
+   if (output_hwc->pp_output_commit_data)
+     output_hwc->wait_commit = EINA_TRUE;
+
+   /* to wake up main loop */
+   uint64_t value = 1;
+   if (write(output_hwc->target_hwc_window->event_fd, &value, sizeof(value)) < 0)
+     ERR("failed to wake up main loop:%m");
+}
+
diff --git a/src/bin/e_output_hwc_windows.h b/src/bin/e_output_hwc_windows.h
new file mode 100644 (file)
index 0000000..21fd69e
--- /dev/null
@@ -0,0 +1,18 @@
+#ifdef E_TYPEDEFS
+#else
+#ifndef E_OUTPUT_HWC_WINDOWS_H
+#define E_OUTPUT_HWC_WINDOWS_H
+
+EINTERN Eina_Bool            e_output_hwc_windows_init(E_Output_Hwc *output_hwc);
+EINTERN void                 e_output_hwc_windows_deinit(void);
+
+EINTERN const Eina_List     *e_output_hwc_windows_get(E_Output_Hwc *output_hwc);
+EINTERN Eina_Bool            e_output_hwc_windows_render(E_Output_Hwc *output_hwc);
+EINTERN Eina_Bool            e_output_hwc_windows_commit(E_Output_Hwc *output_hwc);
+
+EINTERN Eina_Bool            e_output_hwc_windows_pp_commit_possible_check(E_Output_Hwc *output_hwc);
+EINTERN Eina_Bool            e_output_hwc_windows_zoom_set(E_Output_Hwc *output_hwc, Eina_Rectangle *rect);
+EINTERN void                 e_output_hwc_windows_zoom_unset(E_Output_Hwc *output_hwc);
+
+#endif
+#endif
index 9e2d83aa2363f49e0dccc8ef501287f823f5253d..39d9edd53cb164a07c3b481f0469b0d3a8a79294 100644 (file)
@@ -597,19 +597,27 @@ _e_plane_external_surface_acquire(E_Plane *plane)
    tdm_error ret = TDM_ERROR_NONE;
    E_Plane *plane_primary_output_fb = NULL;
 
-   plane_primary_output_fb = e_output_fb_target_get(plane->output_primary);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(plane_primary_output_fb, NULL);
-
    if (plane->ext_state == E_OUTPUT_EXT_MIRROR)
      {
-        if ((plane->pp_rect.x != plane->mirror_rect.x) ||
-            (plane->pp_rect.y != plane->mirror_rect.y) ||
-            (plane->pp_rect.w != plane->mirror_rect.w) ||
-            (plane->pp_rect.h != plane->mirror_rect.h))
-           e_plane_zoom_set(plane, &plane->mirror_rect);
+        if (e_output_hwc_policy_get(plane->output_primary->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
+          {
+             plane_primary_output_fb = e_output_fb_target_get(plane->output_primary);
+             EINA_SAFETY_ON_NULL_RETURN_VAL(plane_primary_output_fb, NULL);
 
-        tsurface = tdm_layer_get_displaying_buffer(plane_primary_output_fb->tlayer, &ret);
-        EINA_SAFETY_ON_FALSE_RETURN_VAL(ret == TDM_ERROR_NONE, NULL);
+             if ((plane->pp_rect.x != plane->mirror_rect.x) ||
+                 (plane->pp_rect.y != plane->mirror_rect.y) ||
+                 (plane->pp_rect.w != plane->mirror_rect.w) ||
+                 (plane->pp_rect.h != plane->mirror_rect.h))
+               e_plane_zoom_set(plane, &plane->mirror_rect);
+
+             tsurface = tdm_layer_get_displaying_buffer(plane_primary_output_fb->tlayer, &ret);
+             EINA_SAFETY_ON_FALSE_RETURN_VAL(ret == TDM_ERROR_NONE, NULL);
+          }
+        else
+          {
+             tsurface = plane->output_primary->output_hwc->target_hwc_window->hwc_window.tsurface;
+             EINA_SAFETY_ON_NULL_RETURN_VAL(tsurface, NULL);
+          }
      }
    else if (plane->ext_state == E_OUTPUT_EXT_PRESENTATION)
      {