Added APIs to handle displaying video internally.
authorSeunghun Lee <shiin.lee@samsung.com>
Thu, 22 Nov 2018 07:12:09 +0000 (16:12 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Fri, 12 Apr 2019 10:00:22 +0000 (19:00 +0900)
Created APIs of 'E_Client_Video' which handles displaying video client
automatically. 'E_Client_Video' will make interface internally according to
its capable of hardware compositing.

3 headers are introduced, and purpose of each header is as follow.
 - e_video_debug.h: Set and get video debug setting.
 - e_client_video.h: Handle given E_Client as a video client.
 - e_zone_video.h: Provides informations of corresponding E_Zone which is needed
                   by video implementation.

Change-Id: Ia5e7cbf3dfa17c85c605f68675e9375b84a347e1

21 files changed:
src/bin/Makefile.mk
src/bin/e_comp_screen.c
src/bin/e_comp_screen.h
src/bin/e_comp_wl_video.c [deleted file]
src/bin/e_comp_wl_video.h [deleted file]
src/bin/e_comp_wl_video_buffer.c [deleted file]
src/bin/e_comp_wl_video_buffer.h [deleted file]
src/bin/e_includes.h
src/bin/video/e_client_video.c [new file with mode: 0644]
src/bin/video/e_client_video.h [new file with mode: 0644]
src/bin/video/e_comp_wl_video.c [new file with mode: 0644]
src/bin/video/e_comp_wl_video.h [new file with mode: 0644]
src/bin/video/e_comp_wl_video_buffer.c [new file with mode: 0644]
src/bin/video/e_comp_wl_video_buffer.h [new file with mode: 0644]
src/bin/video/e_video_debug.c [new file with mode: 0644]
src/bin/video/e_video_debug.h [new file with mode: 0644]
src/bin/video/e_video_internal.h [new file with mode: 0644]
src/bin/video/e_zone_video.c [new file with mode: 0644]
src/bin/video/e_zone_video.h [new file with mode: 0644]
src/bin/video/iface/e_video_fallback.c [new file with mode: 0644]
src/bin/video/iface/e_video_hwc_planes.c [new file with mode: 0644]

index 515b8027ad71cf69b7c518a26c604c971dec0c2a..b4afcf75bfedbb286b3594a19bcb6b505cabb4d4 100644 (file)
@@ -102,8 +102,11 @@ endif
 
 ENLIGHTENMENTHEADERS += \
 src/bin/e_comp_wl_rsm.h \
-src/bin/e_comp_wl_video.h \
-src/bin/e_comp_wl_video_buffer.h \
+src/bin/video/e_comp_wl_video.h \
+src/bin/video/e_comp_wl_video_buffer.h \
+src/bin/video/e_client_video.h \
+src/bin/video/e_zone_video.h \
+src/bin/video/e_video_debug.h \
 src/bin/e_comp_wl_viewport.h \
 src/bin/e_comp_wl_screenshooter.h \
 src/bin/e_comp_wl_shell.h \
@@ -210,8 +213,13 @@ endif
 
 enlightenment_src += \
 src/bin/e_comp_wl_rsm.c \
-src/bin/e_comp_wl_video.c \
-src/bin/e_comp_wl_video_buffer.c \
+src/bin/video/e_comp_wl_video.c \
+src/bin/video/e_comp_wl_video_buffer.c \
+src/bin/video/e_client_video.c \
+src/bin/video/e_zone_video.c \
+src/bin/video/e_video_debug.c \
+src/bin/video/iface/e_video_hwc_planes.c \
+src/bin/video/iface/e_video_fallback.c \
 src/bin/e_comp_wl_viewport.c \
 src/bin/e_comp_wl_screenshooter.c \
 src/bin/e_comp_wl_shell.c \
index 03e995c46842412ed68ecbc66b8b1c17714f8ad7..997d252bf100a702575d05b5e6cd37762dc43691 100644 (file)
@@ -1334,3 +1334,129 @@ e_comp_screen_hwc_info_debug(void)
      }
    INF("HWC: =========================================================================");
 }
+
+#define NUM_SW_FORMAT   (sizeof(sw_formats) / sizeof(sw_formats[0]))
+
+static tbm_format sw_formats[] = {
+     TBM_FORMAT_ARGB8888,
+     TBM_FORMAT_XRGB8888,
+     TBM_FORMAT_YUV420,
+     TBM_FORMAT_YVU420,
+};
+
+static tdm_layer *
+_e_comp_screen_video_tdm_layer_get(tdm_output *output)
+{
+   int i, count = 0;
+#ifdef CHECKING_PRIMARY_ZPOS
+   int primary_idx = 0, primary_zpos = 0;
+   tdm_layer *primary_layer;
+#endif
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
+
+   tdm_output_get_layer_count(output, &count);
+   for (i = 0; i < count; i++)
+     {
+        tdm_layer *layer = tdm_output_get_layer(output, i, NULL);
+        tdm_layer_capability capabilities = 0;
+        EINA_SAFETY_ON_NULL_RETURN_VAL(layer, NULL);
+
+        tdm_layer_get_capabilities(layer, &capabilities);
+        if (capabilities & TDM_LAYER_CAPABILITY_VIDEO)
+          return layer;
+     }
+
+#ifdef CHECKING_PRIMARY_ZPOS
+   tdm_output_get_primary_index(output, &primary_idx);
+   primary_layer = tdm_output_get_layer(output, primary_idx, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(primary_layer, NULL);
+   tdm_layer_get_zpos(primary_layer, &primary_zpos);
+#endif
+
+   for (i = 0; i < count; i++)
+     {
+        tdm_layer *layer = tdm_output_get_layer(output, i, NULL);
+        tdm_layer_capability capabilities = 0;
+        EINA_SAFETY_ON_NULL_RETURN_VAL(layer, NULL);
+
+        tdm_layer_get_capabilities(layer, &capabilities);
+        if (capabilities & TDM_LAYER_CAPABILITY_OVERLAY)
+          {
+#ifdef CHECKING_PRIMARY_ZPOS
+             int zpos = 0;
+             tdm_layer_get_zpos(layer, &zpos);
+             if (zpos >= primary_zpos) continue;
+#endif
+             return layer;
+          }
+     }
+
+   return NULL;
+}
+
+static E_Output *
+_e_comp_screen_eoutput_get_by_toutput(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;
+}
+
+EINTERN Eina_Bool
+e_comp_screen_available_video_formats_get(const tbm_format **formats, int *count)
+{
+   E_Output *output;
+   tdm_output *toutput;
+   tdm_layer *layer;
+   tdm_error error;
+
+   *count = 0;
+
+   if (e_comp_screen_pp_support())
+     {
+        error = tdm_display_get_pp_available_formats(e_comp->e_comp_screen->tdisplay, formats, count);
+        if (error == TDM_ERROR_NONE)
+          return EINA_TRUE;
+     }
+
+   /* get the first output */
+   toutput = tdm_display_get_output(e_comp->e_comp_screen->tdisplay, 0, NULL);
+   if (!toutput)
+     return EINA_FALSE;
+
+   output = _e_comp_screen_eoutput_get_by_toutput(toutput);
+   if (!output)
+     return EINA_FALSE;
+
+   if (e_hwc_policy_get(output->hwc) != E_HWC_POLICY_WINDOWS)
+     {
+        /* get the first suitable layer */
+        layer = _e_comp_screen_video_tdm_layer_get(toutput);
+        if (layer)
+          {
+             tdm_layer_get_available_formats(layer, formats, count);
+          }
+        else
+          {
+             *formats = sw_formats;
+             *count = NUM_SW_FORMAT;
+          }
+     }
+   else
+     {
+        error = tdm_hwc_get_video_supported_formats(output->hwc->thwc, formats, count);
+        if (error != TDM_ERROR_NONE)
+          {
+             *formats = sw_formats;
+             *count = NUM_SW_FORMAT;
+          }
+     }
+
+   return EINA_TRUE;
+}
index 75c60460e71755623ef9bf61e22c63721a9477d6..cb8ee5293bc9d64fe6edd91749d30577adfeeeec 100644 (file)
@@ -61,6 +61,8 @@ EINTERN E_Output        * e_comp_screen_primary_output_get(E_Comp_Screen *e_comp
 
 EINTERN Eina_Bool         e_comp_screen_pp_support(void);
 EINTERN Eina_List       * e_comp_screen_pp_available_formats_get(void);
+EINTERN Eina_Bool         e_comp_screen_available_video_formats_get(const tbm_format **formats, int *count);
+
 
 #endif /*E_COMP_SCREEN_H*/
 
diff --git a/src/bin/e_comp_wl_video.c b/src/bin/e_comp_wl_video.c
deleted file mode 100644 (file)
index 10c6f83..0000000
+++ /dev/null
@@ -1,3387 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "e.h"
-#include <tdm.h>
-#include <values.h>
-#include <tdm_helper.h>
-#include <wayland-tbm-server.h>
-#include <tizen-extension-server-protocol.h>
-
-//#define DUMP_BUFFER
-#define CHECKING_PRIMARY_ZPOS
-
-static int _video_detail_log_dom = -1;
-static Eina_Bool video_to_primary;
-static Eina_Bool video_punch;
-
-#define BUFFER_MAX_COUNT   5
-#define MIN_WIDTH   32
-
-#undef NEVER_GET_HERE
-#define NEVER_GET_HERE()     CRI("** need to improve more **")
-
-#ifndef CLEAR
-#define CLEAR(x) memset(&(x), 0, sizeof(x))
-#endif
-
-#define VER(fmt, arg...) ELOGF("VIDEO", "<ERR> window(0x%08"PRIxPTR"): "fmt, \
-                               video->ec->pixmap, video->ec, video->window, ##arg)
-#define VWR(fmt, arg...) ELOGF("VIDEO", "<WRN> window(0x%08"PRIxPTR"): "fmt, \
-                               video->ec->pixmap, video->ec, video->window, ##arg)
-#define VIN(fmt, arg...) ELOGF("VIDEO", "<INF> window(0x%08"PRIxPTR"): "fmt, \
-                               video->ec->pixmap, video->ec, video->window, ##arg)
-#define VDB(fmt, arg...) DBG("window(0x%08"PRIxPTR") ec(%p): "fmt, video->window, video->ec, ##arg)
-
-#define DET(...)          EINA_LOG_DOM_DBG(_video_detail_log_dom, __VA_ARGS__)
-#define VDT(fmt, arg...)   DET("window(0x%08"PRIxPTR"): "fmt, video->window, ##arg)
-
-#define GEO_FMT   "%dx%d(%dx%d+%d+%d) -> (%dx%d+%d+%d) transform(%d)"
-#define GEO_ARG(g) \
-   (g)->input_w, (g)->input_h, \
-   (g)->input_r.w, (g)->input_r.h, (g)->input_r.x, (g)->input_r.y, \
-   (g)->output_r.w, (g)->output_r.h, (g)->output_r.x, (g)->output_r.y, \
-   (g)->transform
-
-struct _E_Video_Info_Layer
-{
-   tdm_info_config src_config;
-   tdm_pos dst_pos;
-   tdm_transform transform;
-};
-
-/* the new TDM API doesn't have layers, so we have to invent layer here*/
-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
-{
-   struct wl_resource *video_object;
-   struct wl_resource *surface;
-   E_Client *ec;
-   Ecore_Window window;
-   tdm_output *output;
-   E_Output *e_output;
-   E_Video_Layer *layer;
-   E_Plane *e_plane;
-   Eina_Bool external_video;
-
-   /* input info */
-   tbm_format tbmfmt;
-   Eina_List *input_buffer_list;
-
-   /* in screen coordinates */
-   struct
-     {
-        int input_w, input_h;    /* input buffer's size */
-        Eina_Rectangle input_r;  /* input buffer's content rect */
-        Eina_Rectangle output_r; /* video plane rect */
-        uint transform;          /* rotate, flip */
-
-        Eina_Rectangle tdm_output_r; /* video plane rect in physical output coordinates */
-        uint tdm_transform;          /* rotate, flip in physical output coordinates */
-     } geo, old_geo;
-
-   E_Comp_Wl_Buffer *old_comp_buffer;
-
-   /* converter info */
-   tbm_format pp_tbmfmt;
-   tdm_pp *pp;
-   Eina_Rectangle pp_r;    /* converter dst content rect */
-   Eina_List *pp_buffer_list;
-   Eina_List *next_buffer;
-   Eina_Bool pp_scanout;
-
-   int output_align;
-   int pp_align;
-   int pp_minw, pp_minh, pp_maxw, pp_maxh;
-   int video_align;
-
-   /* When a video buffer be attached, it will be appended to the end of waiting_list .
-    * And when it's committed, it will be moved to committed_list.
-    * Finally when the commit handler is called, it will become current_fb.
-    */
-   Eina_List    *waiting_list;   /* buffers which are not committed yet */
-   Eina_List    *committed_list; /* buffers which are committed, but not shown on screen yet */
-   E_Comp_Wl_Video_Buf *current_fb;     /* buffer which is showing on screen currently */
-   Eina_Bool     waiting_vblank;
-
-   /* attributes */
-   Eina_List *tdm_prop_list;
-   Eina_List *late_tdm_prop_list;
-   int tdm_mute_id;
-
-   Eina_Bool  cb_registered;
-   Eina_Bool  need_force_render;
-   Eina_Bool  follow_topmost_visibility;
-   Eina_Bool  allowed_attribute;
-
-   E_Plane_Hook *video_plane_ready_handler;
-};
-
-typedef struct _Tdm_Prop_Value
-{
-   unsigned int id;
-   char name[TDM_NAME_LEN];
-   tdm_value value;
-} Tdm_Prop_Value;
-
-static tbm_format sw_formats[] = {
-       TBM_FORMAT_ARGB8888,
-       TBM_FORMAT_XRGB8888,
-       TBM_FORMAT_YUV420,
-       TBM_FORMAT_YVU420,
-};
-
-#define NUM_SW_FORMAT   (sizeof(sw_formats) / sizeof(sw_formats[0]))
-
-static Eina_List *video_list = NULL;
-static Eina_List *video_layers = NULL;
-
-static void _e_video_set(E_Video *video, E_Client *ec);
-static void _e_video_destroy(E_Video *video);
-static void _e_video_render(E_Video *video, const char *func);
-static Eina_Bool _e_video_frame_buffer_show(E_Video *video, E_Comp_Wl_Video_Buf *vbuf);
-static void _e_video_video_set_hook(void *data, E_Plane *plane);
-
-static tdm_layer* _e_video_tdm_video_layer_get(tdm_output *output);
-static tdm_layer* _e_video_tdm_available_video_layer_get(tdm_output *output);
-static void _e_video_tdm_set_layer_usable(tdm_layer *layer, Eina_Bool usable);
-static Eina_Bool _e_video_tdm_get_layer_usable(tdm_layer *layer);
-
-static void _e_video_vblank_handler(tdm_output *output, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data);
-
-static int
-gcd(int a, int b)
-{
-   if (a % b == 0)
-     return b;
-   return gcd(b, a % b);
-}
-
-static int
-lcm(int a, int b)
-{
-   return a * b / gcd(a, b);
-}
-
-static void
-buffer_transform(int width, int height, uint32_t transform, int32_t scale,
-                 int sx, int sy, int *dx, int *dy)
-{
-   switch (transform)
-     {
-      case WL_OUTPUT_TRANSFORM_NORMAL:
-      default:
-         *dx = sx, *dy = sy;
-         break;
-      case WL_OUTPUT_TRANSFORM_FLIPPED:
-         *dx = width - sx, *dy = sy;
-         break;
-      case WL_OUTPUT_TRANSFORM_90:
-         *dx = height - sy, *dy = sx;
-         break;
-      case WL_OUTPUT_TRANSFORM_FLIPPED_90:
-         *dx = height - sy, *dy = width - sx;
-         break;
-      case WL_OUTPUT_TRANSFORM_180:
-         *dx = width - sx, *dy = height - sy;
-         break;
-      case WL_OUTPUT_TRANSFORM_FLIPPED_180:
-         *dx = sx, *dy = height - sy;
-         break;
-      case WL_OUTPUT_TRANSFORM_270:
-         *dx = sy, *dy = width - sx;
-         break;
-      case WL_OUTPUT_TRANSFORM_FLIPPED_270:
-         *dx = sy, *dy = sx;
-         break;
-     }
-
-   *dx *= scale;
-   *dy *= scale;
-}
-
-static E_Video *
-find_video_with_surface(struct wl_resource *surface)
-{
-   E_Video *video;
-   Eina_List *l;
-   EINA_LIST_FOREACH(video_list, l, video)
-     {
-        if (video->surface == surface)
-          return video;
-     }
-   return NULL;
-}
-
-static E_Client *
-find_video_child_get(E_Client *ec)
-{
-   E_Client *subc = NULL;
-   Eina_List *l;
-   if (!ec) return NULL;
-   if (e_object_is_del(E_OBJECT(ec))) return NULL;
-   if (!ec->comp_data) return NULL;
-
-   if (ec->comp_data->video_client) return ec;
-
-   EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
-     {
-        E_Client *temp= NULL;
-        if (!subc->comp_data || e_object_is_del(E_OBJECT(subc))) continue;
-        temp = find_video_child_get(subc);
-        if(temp) return temp;
-     }
-
-   return NULL;
-}
-
-static E_Client *
-find_offscreen_parent_get(E_Client *ec)
-{
-   E_Client *parent = NULL;
-
-   if (!ec->comp_data || !ec->comp_data->sub.data)
-     return NULL;
-
-   parent = ec->comp_data->sub.data->parent;
-   while (parent)
-     {
-        if (!parent->comp_data || !parent->comp_data->sub.data)
-          return NULL;
-
-        if (parent->comp_data->sub.data->remote_surface.offscreen_parent)
-          return parent->comp_data->sub.data->remote_surface.offscreen_parent;
-
-        parent = parent->comp_data->sub.data->parent;
-     }
-
-   return NULL;
-}
-
-static E_Comp_Wl_Video_Buf *
-_e_video_vbuf_find(Eina_List *list, tbm_surface_h buffer)
-{
-   E_Comp_Wl_Video_Buf *vbuf;
-   Eina_List *l = NULL;
-
-   EINA_LIST_FOREACH(list, l, vbuf)
-     {
-        if (vbuf->tbm_surface == buffer)
-          return vbuf;
-     }
-
-   return NULL;
-}
-
-static E_Comp_Wl_Video_Buf *
-_e_video_vbuf_find_with_comp_buffer(Eina_List *list, E_Comp_Wl_Buffer *comp_buffer)
-{
-   E_Comp_Wl_Video_Buf *vbuf;
-   Eina_List *l = NULL;
-
-   EINA_LIST_FOREACH(list, l, vbuf)
-     {
-        if (vbuf->comp_buffer == comp_buffer)
-          return vbuf;
-     }
-
-   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 *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);
-
-   if (e_hwc_policy_get(output->hwc) != E_HWC_POLICY_WINDOWS)
-     {
-        /* get the first suitable layer */
-        layer = _e_video_tdm_video_layer_get(toutput);
-        if (!layer)
-          return EINA_FALSE;
-
-        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;
-}
-
-E_Video_Layer *
-_e_video_available_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->video = video;
-   layer->e_client = video->ec;
-
-   if (e_hwc_policy_get(video->e_output->hwc) != E_HWC_POLICY_WINDOWS)
-     {
-        layer->tdm_layer = _e_video_tdm_available_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
-     {
-       /*
-        * 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->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;
-     }
-
-   return layer;
-}
-
-/* this function is called on the start work with client while the video interface is bind */
-static void
-_e_video_get_available_formats(const tbm_format **formats, int *count)
-{
-   E_Output *output;
-   tdm_output *toutput;
-   tdm_layer *layer;
-
-   *count = 0;
-
-   /* get the first output */
-   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);
-
-   if (e_hwc_policy_get(output->hwc) != E_HWC_POLICY_WINDOWS)
-     {
-        /* get the first suitable layer */
-        layer = _e_video_tdm_video_layer_get(toutput);
-        if (layer)
-          {
-             tdm_layer_get_available_formats(layer, formats, count);
-          }
-        else
-          {
-             *formats = sw_formats;
-             *count = NUM_SW_FORMAT;
-          }
-     }
-   else
-     {
-        tdm_error error;
-        error = tdm_hwc_get_video_supported_formats(output->hwc->thwc, formats, count);
-        if (error != TDM_ERROR_NONE)
-          {
-             *formats = sw_formats;
-             *count = NUM_SW_FORMAT;
-          }
-     }
-}
-
-static int
-_e_video_get_prop_id(E_Video *video, const char *name)
-{
-   tdm_layer *layer;
-   const tdm_prop *props;
-   int i, count = 0;
-
-   if (e_hwc_policy_get(video->e_output->hwc) != E_HWC_POLICY_WINDOWS)
-     {
-        layer = _e_video_tdm_video_layer_get(video->output);
-        tdm_layer_get_available_properties(layer, &props, &count);
-
-        for (i = 0; i < count; i++)
-          {
-             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_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_hwc_policy_get(video->e_output->hwc) == E_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)
-{
-   tdm_error ret = TDM_ERROR_NONE;
-   tdm_info_layer tinfo = {0};
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(layer, TDM_ERROR_INVALID_PARAMETER);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(vinfo, TDM_ERROR_INVALID_PARAMETER);
-
-   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;
-     }
-
-   return ret;
-}
-
-static tdm_error
-_e_video_layer_set_info(E_Video_Layer *layer, E_Video_Info_Layer *vinfo)
-{
-   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);
-
-   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);
-     }
-
-   return ret;
-}
-
-static tdm_error
-_e_video_layer_set_buffer(E_Video_Layer * layer, tbm_surface_h buff)
-{
-   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);
-
-   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;
-}
-
-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);
-
-   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, EINA_TRUE);
-        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;
-}
-
-/*
- * This function checks if this layer was set
- */
-static tdm_error
-_e_video_layer_is_usable(E_Video_Layer * layer, unsigned int *usable)
-{
-   tdm_error ret;
-
-   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;
-}
-
-static tdm_error
-_e_video_layer_commit(E_Video_Layer *layer, tdm_layer_commit_handler func, void *user_data)
-{
-   tdm_error ret = TDM_ERROR_NONE;
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(layer, TDM_ERROR_BAD_REQUEST);
-
-   if (_is_video_hwc_windows(layer->video))
-     ret = TDM_ERROR_NONE;
-   else
-     ret = tdm_layer_commit(layer->tdm_layer, func, user_data);
-
-   return ret;
-}
-
-static tbm_surface_h
-_e_video_layer_get_displaying_buffer(E_Video_Layer *layer, int *tdm_error)
-{
-   EINA_SAFETY_ON_NULL_RETURN_VAL(layer, NULL);
-
-   if (tdm_error)
-     *tdm_error = TDM_ERROR_OPERATION_FAILED;
-
-   if (_is_video_hwc_windows(layer->video))
-     {
-        E_Hwc_Window *hwc_window;
-
-        hwc_window = layer->e_client->hwc_window;
-        EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, NULL);
-
-        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);
-}
-
-static tdm_error
-_e_video_layer_get_available_properties(E_Video_Layer * layer, const tdm_prop **props,
-    int *count)
-{
-  tdm_error ret = TDM_ERROR_OPERATION_FAILED;
-
-  EINA_SAFETY_ON_NULL_RETURN_VAL(layer, TDM_ERROR_BAD_REQUEST);
-  EINA_SAFETY_ON_NULL_RETURN_VAL(props, TDM_ERROR_BAD_REQUEST);
-  EINA_SAFETY_ON_NULL_RETURN_VAL(count, TDM_ERROR_BAD_REQUEST);
-
-  if (_is_video_hwc_windows(layer->video))
-    {
-       *count = 0;
-#if 0 //TODO:
-       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);
-#endif
-    }
-  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_available_video_layer_get(layer->video->output);
-       ret = tdm_layer_get_available_properties(tlayer, props, count);
-    }
-
-  return ret;
-}
-
-static tdm_error
-_e_video_layer_get_property(E_Video_Layer * layer, unsigned id, tdm_value *value)
-{
-  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);
-
-  if (_is_video_hwc_windows(layer->video))
-    {
-#if 0 //TODO:
-       if (layer->e_client->hwc_window->thwc_window)
-         ret = tdm_hwc_window_video_get_property(
-                      layer->e_client->hwc_window->thwc_window, id, value);
-       else
-#endif
-         ret = TDM_ERROR_BAD_MODULE;
-    }
-  else
-    ret = tdm_layer_get_property(layer->tdm_layer, id, value);
-
-  return ret;
-}
-
-static tdm_error
-_e_video_layer_set_property(E_Video_Layer * layer, Tdm_Prop_Value *prop)
-{
-   tdm_error ret;
-
-   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;
-}
-
-static void
-_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);
-
-   free(layer);
-}
-
-static Eina_Bool
-_e_video_set_layer(E_Video *video, Eina_Bool set)
-{
-   Eina_Bool need_wait;
-
-   if (!set)
-     {
-        unsigned int usable = 1;
-        if (!video->layer) return EINA_TRUE;
-
-        _e_video_layer_is_usable(video->layer, &usable);
-        if (!usable && !video->video_plane_ready_handler)
-          {
-             VIN("stop video");
-             _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;
-
-        if (e_hwc_policy_get(video->e_output->hwc) != E_HWC_POLICY_WINDOWS)
-          {
-             e_plane_video_set(video->e_plane, EINA_FALSE, NULL);
-             video->e_plane = NULL;
-          }
-
-        E_FREE_FUNC(video->video_plane_ready_handler, e_plane_hook_del);
-     }
-   else
-     {
-        int zpos;
-        tdm_error ret;
-
-        if (video->layer) return EINA_TRUE;
-
-        video->layer = _e_video_available_video_layer_get(video);
-        if (!video->layer)
-          {
-             VWR("no available layer for video");
-             return EINA_FALSE;
-          }
-
-        if (e_hwc_policy_get(video->e_output->hwc) != E_HWC_POLICY_WINDOWS)
-          {
-             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, &need_wait))
-               {
-                  VWR("fail set video to e_plane");
-                  _e_video_layer_destroy(video->layer);
-                  video->layer = NULL;
-                  video->e_plane = NULL;
-                  return EINA_FALSE;
-               }
-             if (need_wait)
-               {
-                    video->video_plane_ready_handler =
-                       e_plane_hook_add(E_PLANE_HOOK_VIDEO_SET,
-                                        _e_video_video_set_hook, video);
-               }
-          }
-
-        VIN("assign layer: %p", video->layer);
-     }
-
-   return EINA_TRUE;
-}
-
-static Eina_Bool
-_e_video_is_visible(E_Video *video)
-{
-   E_Client *offscreen_parent;
-
-   if (e_object_is_del(E_OBJECT(video->ec))) return EINA_FALSE;
-
-   if (!e_pixmap_resource_get(video->ec->pixmap))
-     {
-        VDB("no comp buffer");
-        return EINA_FALSE;
-     }
-
-   if (video->ec->comp_data->sub.data && video->ec->comp_data->sub.data->stand_alone)
-     return EINA_TRUE;
-
-   offscreen_parent = find_offscreen_parent_get(video->ec);
-   if (offscreen_parent && offscreen_parent->visibility.obscured == E_VISIBILITY_FULLY_OBSCURED)
-     {
-        VDB("video surface invisible: offscreen fully obscured");
-        return EINA_FALSE;
-     }
-
-   if (!evas_object_visible_get(video->ec->frame))
-     {
-        VDB("evas obj invisible");
-        return EINA_FALSE;
-     }
-
-   return EINA_TRUE;
-}
-
-static Eina_Bool
-_e_video_parent_is_viewable(E_Video *video)
-{
-   E_Client *topmost_parent;
-
-   if (e_object_is_del(E_OBJECT(video->ec))) return EINA_FALSE;
-
-   topmost_parent = e_comp_wl_topmost_parent_get(video->ec);
-
-   if (!topmost_parent)
-     return EINA_FALSE;
-
-   if (topmost_parent == video->ec)
-     {
-        VDB("There is no video parent surface");
-        return EINA_FALSE;
-     }
-
-   if (!topmost_parent->visible)
-     {
-        VDB("parent(0x%08"PRIxPTR") not viewable", (Ecore_Window)e_client_util_win_get(topmost_parent));
-        return EINA_FALSE;
-     }
-
-   if (!e_pixmap_resource_get(topmost_parent->pixmap))
-     {
-        VDB("parent(0x%08"PRIxPTR") no comp buffer", (Ecore_Window)e_client_util_win_get(topmost_parent));
-        return EINA_FALSE;
-     }
-
-   return EINA_TRUE;
-}
-
-static void
-_e_video_input_buffer_cb_free(E_Comp_Wl_Video_Buf *vbuf, void *data)
-{
-   E_Video *video = data;
-   Eina_Bool need_hide = EINA_FALSE;
-
-   VDT("Buffer(%p) to be free, refcnt(%d)", vbuf, vbuf->ref_cnt);
-
-   video->input_buffer_list = eina_list_remove(video->input_buffer_list, vbuf);
-
-   if (vbuf->comp_buffer)
-     e_comp_wl_buffer_reference(&vbuf->buffer_ref, NULL);
-
-   if (video->current_fb == vbuf)
-     {
-        VIN("current fb destroyed");
-        e_comp_wl_video_buffer_set_use(video->current_fb, EINA_FALSE);
-        video->current_fb = NULL;
-        need_hide = EINA_TRUE;
-     }
-
-   if (eina_list_data_find(video->committed_list, vbuf))
-     {
-        VIN("committed fb destroyed");
-        video->committed_list = eina_list_remove(video->committed_list, vbuf);
-        e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
-        need_hide = EINA_TRUE;
-     }
-
-   if (eina_list_data_find(video->waiting_list, vbuf))
-     {
-        VIN("waiting fb destroyed");
-        video->waiting_list = eina_list_remove(video->waiting_list, vbuf);
-     }
-
-   if (need_hide && video->layer)
-     _e_video_frame_buffer_show(video, NULL);
-}
-
-static Eina_Bool
-_e_video_input_buffer_scanout_check(E_Comp_Wl_Video_Buf *vbuf)
-{
-   tbm_surface_h tbm_surface = NULL;
-   tbm_bo bo = NULL;
-   int flag;
-
-   tbm_surface = vbuf->tbm_surface;
-   EINA_SAFETY_ON_NULL_RETURN_VAL(tbm_surface, EINA_FALSE);
-
-   bo = tbm_surface_internal_get_bo(tbm_surface, 0);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(bo, EINA_FALSE);
-
-   flag = tbm_bo_get_flags(bo);
-   if (flag == TBM_BO_SCANOUT)
-      return EINA_TRUE;
-
-   return EINA_FALSE;
-}
-
-static E_Comp_Wl_Video_Buf *
-_e_video_input_buffer_copy(E_Video *video, E_Comp_Wl_Buffer *comp_buf, E_Comp_Wl_Video_Buf *vbuf, Eina_Bool scanout)
-{
-   E_Comp_Wl_Video_Buf *temp = NULL;
-   int aligned_width = ROUNDUP(vbuf->width_from_pitch, video->pp_align);
-
-   temp = e_comp_wl_video_buffer_alloc(aligned_width, vbuf->height, vbuf->tbmfmt, scanout);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(temp, NULL);
-
-   temp->comp_buffer = comp_buf;
-
-   VDB("copy vbuf(%d,%dx%d) => vbuf(%d,%dx%d)",
-       MSTAMP(vbuf), vbuf->width_from_pitch, vbuf->height,
-       MSTAMP(temp), temp->width_from_pitch, temp->height);
-
-   e_comp_wl_video_buffer_copy(vbuf, temp);
-   e_comp_wl_video_buffer_unref(vbuf);
-
-   video->geo.input_w = vbuf->width_from_pitch;
-#ifdef DUMP_BUFFER
-   char file[256];
-   static int i;
-   snprintf(file, sizeof file, "/tmp/dump/%s_%d.png", "cpy", i++);
-   tdm_helper_dump_buffer(temp->tbm_surface, file);
-#endif
-
-   return temp;
-}
-
-static E_Comp_Wl_Video_Buf *
-_e_video_input_buffer_get(E_Video *video, E_Comp_Wl_Buffer *comp_buffer, Eina_Bool scanout)
-{
-   E_Comp_Wl_Video_Buf *vbuf;
-   Eina_Bool need_pp_scanout = EINA_FALSE;
-
-   vbuf = _e_video_vbuf_find_with_comp_buffer(video->input_buffer_list, comp_buffer);
-   if (vbuf)
-     {
-        vbuf->content_r = video->geo.input_r;
-        return vbuf;
-     }
-
-   vbuf = e_comp_wl_video_buffer_create_comp(comp_buffer);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(vbuf, NULL);
-
-   if (video->pp_scanout)
-     {
-        Eina_Bool input_buffer_scanout = EINA_FALSE;
-        input_buffer_scanout = _e_video_input_buffer_scanout_check(vbuf);
-        if (!input_buffer_scanout) need_pp_scanout = EINA_TRUE;
-     }
-
-   if (video->pp)
-     {
-        if ((video->pp_align != -1 && (vbuf->width_from_pitch % video->pp_align)) ||
-            need_pp_scanout)
-          {
-             E_Comp_Wl_Video_Buf *temp;
-
-             if (need_pp_scanout)
-               temp = _e_video_input_buffer_copy(video, comp_buffer, vbuf, EINA_TRUE);
-             else
-               temp = _e_video_input_buffer_copy(video, comp_buffer, vbuf, scanout);
-             if (!temp)
-               {
-                  e_comp_wl_video_buffer_unref(vbuf);
-                  return NULL;
-               }
-             vbuf = temp;
-          }
-     }
-
-   vbuf->content_r = video->geo.input_r;
-
-   video->input_buffer_list = eina_list_append(video->input_buffer_list, vbuf);
-   e_comp_wl_video_buffer_free_func_add(vbuf, _e_video_input_buffer_cb_free, video);
-
-   VDT("Client(%s):PID(%d) RscID(%d), Buffer(%p) created, refcnt:%d"
-       " scanout=%d", e_client_util_name_get(video->ec) ?: "No Name" ,
-       video->ec->netwm.pid, wl_resource_get_id(video->surface), vbuf,
-       vbuf->ref_cnt, scanout);
-
-   return vbuf;
-}
-
-static void
-_e_video_input_buffer_valid(E_Video *video, E_Comp_Wl_Buffer *comp_buffer)
-{
-   E_Comp_Wl_Video_Buf *vbuf;
-   Eina_List *l;
-
-   EINA_LIST_FOREACH(video->input_buffer_list, l, vbuf)
-     {
-        tbm_surface_h tbm_surf;
-        tbm_bo bo;
-        uint32_t size = 0, offset = 0, pitch = 0;
-
-        if (!vbuf->comp_buffer) continue;
-        if (vbuf->resource == comp_buffer->resource)
-          {
-             WRN("got wl_buffer@%d twice", wl_resource_get_id(comp_buffer->resource));
-             return;
-          }
-
-        tbm_surf = wayland_tbm_server_get_surface(e_comp->wl_comp_data->tbm.server, comp_buffer->resource);
-        bo = tbm_surface_internal_get_bo(tbm_surf, 0);
-        tbm_surface_internal_get_plane_data(tbm_surf, 0, &size, &offset, &pitch);
-
-        if (vbuf->names[0] == tbm_bo_export(bo) && vbuf->offsets[0] == offset)
-          {
-             WRN("can tearing: wl_buffer@%d, wl_buffer@%d are same. gem_name(%d)",
-                 wl_resource_get_id(vbuf->resource),
-                 wl_resource_get_id(comp_buffer->resource), vbuf->names[0]);
-             return;
-          }
-     }
-}
-
-static void
-_e_video_pp_buffer_cb_free(E_Comp_Wl_Video_Buf *vbuf, void *data)
-{
-   E_Video *video = data;
-
-   e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
-
-   if (video->current_fb == vbuf)
-     video->current_fb = NULL;
-
-   video->committed_list = eina_list_remove(video->committed_list, vbuf);
-
-   video->waiting_list = eina_list_remove(video->waiting_list, vbuf);
-
-   video->pp_buffer_list = eina_list_remove(video->pp_buffer_list, vbuf);
-}
-
-static E_Comp_Wl_Video_Buf *
-_e_video_pp_buffer_get(E_Video *video, int width, int height)
-{
-   E_Comp_Wl_Video_Buf *vbuf;
-   Eina_List *l;
-   int i = 0;
-   int aligned_width;
-
-   if (video->video_align != -1)
-     aligned_width = ROUNDUP(width, video->video_align);
-   else
-     aligned_width = width;
-
-   if (video->pp_buffer_list)
-     {
-        vbuf = eina_list_data_get(video->pp_buffer_list);
-        EINA_SAFETY_ON_NULL_RETURN_VAL(vbuf, NULL);
-
-        /* if we need bigger pp_buffers, destroy all pp_buffers and create */
-        if (aligned_width > vbuf->width_from_pitch || height != vbuf->height)
-          {
-             Eina_List *ll;
-
-             VIN("pp buffer changed: %dx%d => %dx%d",
-                 vbuf->width_from_pitch, vbuf->height,
-                 aligned_width, height);
-
-             EINA_LIST_FOREACH_SAFE(video->pp_buffer_list, l, ll, vbuf)
-               {
-                  /* free forcely */
-                  e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
-                  e_comp_wl_video_buffer_unref(vbuf);
-               }
-             if (video->pp_buffer_list)
-               NEVER_GET_HERE();
-
-             if (video->waiting_list)
-               NEVER_GET_HERE();
-          }
-     }
-
-   if (!video->pp_buffer_list)
-     {
-        for (i = 0; i < BUFFER_MAX_COUNT; i++)
-          {
-             vbuf = e_comp_wl_video_buffer_alloc(aligned_width, height, video->pp_tbmfmt, EINA_TRUE);
-             EINA_SAFETY_ON_NULL_RETURN_VAL(vbuf, NULL);
-
-             e_comp_wl_video_buffer_free_func_add(vbuf, _e_video_pp_buffer_cb_free, video);
-             video->pp_buffer_list = eina_list_append(video->pp_buffer_list, vbuf);
-
-          }
-
-        VIN("pp buffer created: %dx%d, %c%c%c%c",
-            vbuf->width_from_pitch, height, FOURCC_STR(video->pp_tbmfmt));
-
-        video->next_buffer = video->pp_buffer_list;
-     }
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(video->pp_buffer_list, NULL);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(video->next_buffer, NULL);
-
-   l = video->next_buffer;
-   while ((vbuf = video->next_buffer->data))
-     {
-        video->next_buffer = (video->next_buffer->next) ? video->next_buffer->next : video->pp_buffer_list;
-
-        if (!vbuf->in_use)
-          return vbuf;
-
-        if (l == video->next_buffer)
-          {
-             VWR("all video framebuffers in use (max:%d)", BUFFER_MAX_COUNT);
-             return NULL;
-          }
-     }
-
-   return NULL;
-}
-
-/* convert from logical screen to physical output */
-static void
-_e_video_geometry_cal_physical(E_Video *video)
-{
-   E_Zone *zone;
-   E_Comp_Wl_Output *output;
-   E_Client *topmost;
-   int tran, flip;
-   int transform;
-
-   topmost = e_comp_wl_topmost_parent_get(video->ec);
-   EINA_SAFETY_ON_NULL_GOTO(topmost, normal);
-
-   output = e_comp_wl_output_find(topmost);
-   EINA_SAFETY_ON_NULL_GOTO(output, normal);
-
-   zone = e_comp_zone_xy_get(topmost->x, topmost->y);
-   EINA_SAFETY_ON_NULL_GOTO(zone, normal);
-
-   tran = video->geo.transform & 0x3;
-   flip = video->geo.transform & 0x4;
-   transform = flip + (tran + output->transform) % 4;
-   switch(transform)
-     {
-      case WL_OUTPUT_TRANSFORM_90:
-         video->geo.tdm_transform = TDM_TRANSFORM_270;
-         break;
-      case WL_OUTPUT_TRANSFORM_180:
-         video->geo.tdm_transform = TDM_TRANSFORM_180;
-         break;
-      case WL_OUTPUT_TRANSFORM_270:
-         video->geo.tdm_transform = TDM_TRANSFORM_90;
-         break;
-      case WL_OUTPUT_TRANSFORM_FLIPPED:
-         video->geo.tdm_transform = TDM_TRANSFORM_FLIPPED;
-         break;
-      case WL_OUTPUT_TRANSFORM_FLIPPED_90:
-         video->geo.tdm_transform = TDM_TRANSFORM_FLIPPED_270;
-         break;
-      case WL_OUTPUT_TRANSFORM_FLIPPED_180:
-         video->geo.tdm_transform = TDM_TRANSFORM_FLIPPED_180;
-         break;
-      case WL_OUTPUT_TRANSFORM_FLIPPED_270:
-         video->geo.tdm_transform = TDM_TRANSFORM_FLIPPED_90;
-         break;
-      case WL_OUTPUT_TRANSFORM_NORMAL:
-      default:
-         video->geo.tdm_transform = TDM_TRANSFORM_NORMAL;
-         break;
-     }
-
-   if (output->transform % 2)
-     {
-        if (video->geo.tdm_transform == TDM_TRANSFORM_FLIPPED)
-          video->geo.tdm_transform = TDM_TRANSFORM_FLIPPED_180;
-        else if (video->geo.tdm_transform == TDM_TRANSFORM_FLIPPED_90)
-          video->geo.tdm_transform = TDM_TRANSFORM_FLIPPED_270;
-        else if (video->geo.tdm_transform == TDM_TRANSFORM_FLIPPED_180)
-          video->geo.tdm_transform = TDM_TRANSFORM_FLIPPED;
-        else if (video->geo.tdm_transform == TDM_TRANSFORM_FLIPPED_270)
-          video->geo.tdm_transform = TDM_TRANSFORM_FLIPPED_90;
-     }
-
-   if (output->transform == 0)
-     video->geo.tdm_output_r = video->geo.output_r;
-   else
-     e_comp_wl_rect_convert(zone->w, zone->h, output->transform, 1,
-                            video->geo.output_r.x, video->geo.output_r.y,
-                            video->geo.output_r.w, video->geo.output_r.h,
-                            &video->geo.tdm_output_r.x, &video->geo.tdm_output_r.y,
-                            &video->geo.tdm_output_r.w, &video->geo.tdm_output_r.h);
-
-   VDB("geomtry: screen(%d,%d %dx%d | %d) => %d => physical(%d,%d %dx%d | %d)",
-       EINA_RECTANGLE_ARGS(&video->geo.output_r), video->geo.transform, transform,
-       EINA_RECTANGLE_ARGS(&video->geo.tdm_output_r), video->geo.tdm_transform);
-
-   return;
-normal:
-   video->geo.tdm_output_r = video->geo.output_r;
-   video->geo.tdm_transform = video->geo.transform;
-}
-
-static Eina_Bool
-_e_video_geometry_cal_viewport(E_Video *video)
-{
-   E_Client *ec = video->ec;
-   E_Comp_Wl_Buffer_Viewport *vp = &ec->comp_data->scaler.buffer_viewport;
-   E_Comp_Wl_Subsurf_Data *sdata;
-   int x1, y1, x2, y2;
-   int tx1, ty1, tx2, ty2;
-   E_Comp_Wl_Buffer *comp_buffer;
-   tbm_surface_h tbm_surf;
-   uint32_t size = 0, offset = 0, pitch = 0;
-   int bw, bh;
-   int width_from_buffer, height_from_buffer;
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
-
-   comp_buffer = e_pixmap_resource_get(video->ec->pixmap);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(comp_buffer, EINA_FALSE);
-
-   tbm_surf = wayland_tbm_server_get_surface(e_comp->wl_comp_data->tbm.server, comp_buffer->resource);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(tbm_surf, EINA_FALSE);
-
-   tbm_surface_internal_get_plane_data(tbm_surf, 0, &size, &offset, &pitch);
-
-   /* input geometry */
-   if (IS_RGB(video->tbmfmt))
-     video->geo.input_w = pitch / 4;
-   else
-     video->geo.input_w = pitch;
-
-   video->geo.input_h = tbm_surface_get_height(tbm_surf);
-
-   bw = tbm_surface_get_width(tbm_surf);
-   bh = tbm_surface_get_height(tbm_surf);
-
-   switch (vp->buffer.transform)
-     {
-      case WL_OUTPUT_TRANSFORM_90:
-      case WL_OUTPUT_TRANSFORM_270:
-      case WL_OUTPUT_TRANSFORM_FLIPPED_90:
-      case WL_OUTPUT_TRANSFORM_FLIPPED_270:
-         width_from_buffer = bh / vp->buffer.scale;
-         height_from_buffer = bw / vp->buffer.scale;
-         break;
-      default:
-         width_from_buffer = bw / vp->buffer.scale;
-         height_from_buffer = bh / vp->buffer.scale;
-         break;
-     }
-
-
-   if (vp->buffer.src_width == wl_fixed_from_int(-1))
-     {
-        x1 = 0.0;
-        y1 = 0.0;
-        x2 = width_from_buffer;
-        y2 = height_from_buffer;
-     }
-   else
-     {
-        x1 = wl_fixed_to_int(vp->buffer.src_x);
-        y1 = wl_fixed_to_int(vp->buffer.src_y);
-        x2 = wl_fixed_to_int(vp->buffer.src_x + vp->buffer.src_width);
-        y2 = wl_fixed_to_int(vp->buffer.src_y + vp->buffer.src_height);
-     }
-
-#if 0
-   VDB("transform(%d) scale(%d) buffer(%dx%d) src(%d,%d %d,%d) viewport(%dx%d)",
-       vp->buffer.transform, vp->buffer.scale,
-       width_from_buffer, height_from_buffer,
-       x1, y1, x2 - x1, y2 - y1,
-       ec->comp_data->width_from_viewport, ec->comp_data->height_from_viewport);
-#endif
-
-   buffer_transform(width_from_buffer, height_from_buffer,
-                    vp->buffer.transform, vp->buffer.scale, x1, y1, &tx1, &ty1);
-   buffer_transform(width_from_buffer, height_from_buffer,
-                    vp->buffer.transform, vp->buffer.scale, x2, y2, &tx2, &ty2);
-
-   video->geo.input_r.x = (tx1 <= tx2) ? tx1 : tx2;
-   video->geo.input_r.y = (ty1 <= ty2) ? ty1 : ty2;
-   video->geo.input_r.w = (tx1 <= tx2) ? tx2 - tx1 : tx1 - tx2;
-   video->geo.input_r.h = (ty1 <= ty2) ? ty2 - ty1 : ty1 - ty2;
-
-   /* output geometry */
-   if ((sdata = ec->comp_data->sub.data))
-     {
-        if (sdata->parent)
-          {
-             video->geo.output_r.x = sdata->parent->x + sdata->position.x;
-             video->geo.output_r.y = sdata->parent->y + sdata->position.y;
-          }
-        else
-          {
-             video->geo.output_r.x = sdata->position.x;
-             video->geo.output_r.y = sdata->position.y;
-          }
-     }
-   else
-     {
-        video->geo.output_r.x = ec->x;
-        video->geo.output_r.y = ec->y;
-     }
-
-   video->geo.output_r.w = ec->comp_data->width_from_viewport;
-   video->geo.output_r.w = (video->geo.output_r.w + 1) & ~1;
-   video->geo.output_r.h = ec->comp_data->height_from_viewport;
-
-   e_comp_object_frame_xy_unadjust(ec->frame,
-                                   video->geo.output_r.x, video->geo.output_r.y,
-                                   &video->geo.output_r.x, &video->geo.output_r.y);
-   e_comp_object_frame_wh_unadjust(ec->frame,
-                                   video->geo.output_r.w, video->geo.output_r.h,
-                                   &video->geo.output_r.w, &video->geo.output_r.h);
-
-   video->geo.transform = vp->buffer.transform;
-
-   _e_video_geometry_cal_physical(video);
-
-#if 0
-   VDB("geometry(%dx%d  %d,%d %dx%d  %d,%d %dx%d  %d)",
-       video->geo.input_w, video->geo.input_h,
-       EINA_RECTANGLE_ARGS(&video->geo.input_r),
-       EINA_RECTANGLE_ARGS(&video->geo.output_r),
-       video->geo.transform);
-#endif
-
-   return EINA_TRUE;
-}
-
-static Eina_Bool
-_e_video_geometry_cal_map(E_Video *video)
-{
-   E_Client *ec;
-   const Evas_Map *m;
-   Evas_Coord x1, x2, y1, y2;
-   Eina_Rectangle output_r;
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(video, EINA_FALSE);
-
-   ec = video->ec;
-   EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(ec->frame, EINA_FALSE);
-
-   m = evas_object_map_get(ec->frame);
-   if (!m) return EINA_TRUE;
-
-   /* If frame has map, it means that ec's geometry is decided by map's geometry.
-    * ec->x,y,w,h and ec->client.x,y,w,h is not useful.
-    */
-
-   evas_map_point_coord_get(m, 0, &x1, &y1, NULL);
-   evas_map_point_coord_get(m, 2, &x2, &y2, NULL);
-
-   output_r.x = x1;
-   output_r.y = y1;
-   output_r.w = x2 - x1;
-   output_r.w = (output_r.w + 1) & ~1;
-   output_r.h = y2 - y1;
-   output_r.h = (output_r.h + 1) & ~1;
-
-   if (!memcmp(&video->geo.output_r, &output_r, sizeof(Eina_Rectangle)))
-     return EINA_FALSE;
-
-   VDB("frame(%p) m(%p) output(%d,%d %dx%d) => (%d,%d %dx%d)", ec->frame, m,
-       EINA_RECTANGLE_ARGS(&video->geo.output_r), EINA_RECTANGLE_ARGS(&output_r));
-
-   video->geo.output_r = output_r;
-
-   _e_video_geometry_cal_physical(video);
-
-   return EINA_TRUE;
-}
-
-static void
-_e_video_geometry_cal_to_input(int output_w, int output_h, int input_w, int input_h,
-                               uint32_t trasnform, int ox, int oy, int *ix, int *iy)
-{
-   float ratio_w, ratio_h;
-
-   switch(trasnform)
-     {
-      case WL_OUTPUT_TRANSFORM_NORMAL:
-      default:
-         *ix = ox, *iy = oy;
-         break;
-      case WL_OUTPUT_TRANSFORM_270:
-         *ix = oy, *iy = output_w - ox;
-         break;
-      case WL_OUTPUT_TRANSFORM_180:
-         *ix = output_w - ox, *iy = output_h - oy;
-         break;
-      case WL_OUTPUT_TRANSFORM_90:
-         *ix = output_h - oy, *iy = ox;
-         break;
-      case WL_OUTPUT_TRANSFORM_FLIPPED:
-         *ix = output_w - ox, *iy = oy;
-         break;
-      case WL_OUTPUT_TRANSFORM_FLIPPED_270:
-         *ix = oy, *iy = ox;
-         break;
-      case WL_OUTPUT_TRANSFORM_FLIPPED_180:
-         *ix = ox, *iy = output_h - oy;
-         break;
-      case WL_OUTPUT_TRANSFORM_FLIPPED_90:
-         *ix = output_h - oy, *iy = output_w - ox;
-         break;
-     }
-   if (trasnform & 0x1)
-     {
-        ratio_w = (float)input_w / output_h;
-        ratio_h = (float)input_h / output_w;
-     }
-   else
-     {
-        ratio_w = (float)input_w / output_w;
-        ratio_h = (float)input_h / output_h;
-     }
-   *ix *= ratio_w;
-   *iy *= ratio_h;
-}
-
-static void
-_e_video_geometry_cal_to_input_rect(E_Video * video, Eina_Rectangle *srect, Eina_Rectangle *drect)
-{
-   int xf1, yf1, xf2, yf2;
-
-   /* first transform box coordinates if the scaler is set */
-
-   xf1 = srect->x;
-   yf1 = srect->y;
-   xf2 = srect->x + srect->w;
-   yf2 = srect->y + srect->h;
-
-   _e_video_geometry_cal_to_input(video->geo.output_r.w, video->geo.output_r.h,
-                                  video->geo.input_r.w, video->geo.input_r.h,
-                                  video->geo.transform, xf1, yf1, &xf1, &yf1);
-   _e_video_geometry_cal_to_input(video->geo.output_r.w, video->geo.output_r.h,
-                                  video->geo.input_r.w, video->geo.input_r.h,
-                                  video->geo.transform, xf2, yf2, &xf2, &yf2);
-
-   drect->x = MIN(xf1, xf2);
-   drect->y = MIN(yf1, yf2);
-   drect->w = MAX(xf1, xf2) - drect->x;
-   drect->h = MAX(yf1, yf2) - drect->y;
-}
-
-static Eina_Bool
-_e_video_geometry_cal(E_Video * video)
-{
-   Eina_Rectangle screen = {0,};
-   Eina_Rectangle output_r = {0,}, input_r = {0,};
-   const tdm_output_mode *mode = NULL;
-   tdm_error tdm_err = TDM_ERROR_NONE;
-
-   /* get geometry information with buffer scale, transform and viewport. */
-   if (!_e_video_geometry_cal_viewport(video))
-     return EINA_FALSE;
-
-   _e_video_geometry_cal_map(video);
-
-   if (e_config->eom_enable == EINA_TRUE && video->external_video)
-     {
-        tdm_err = tdm_output_get_mode(video->output, &mode);
-        if (tdm_err != TDM_ERROR_NONE)
-          return EINA_FALSE;
-
-        if (mode == NULL)
-          return EINA_FALSE;
-
-        screen.w = mode->hdisplay;
-        screen.h = mode->vdisplay;
-     }
-   else
-     {
-        E_Zone *zone;
-        E_Client *topmost;
-
-        topmost = e_comp_wl_topmost_parent_get(video->ec);
-        EINA_SAFETY_ON_NULL_RETURN_VAL(topmost, EINA_FALSE);
-
-        zone = e_comp_zone_xy_get(topmost->x, topmost->y);
-        EINA_SAFETY_ON_NULL_RETURN_VAL(zone, EINA_FALSE);
-
-        screen.w = zone->w;
-        screen.h = zone->h;
-     }
-
-   e_comp_wl_video_buffer_size_get(video->ec, &input_r.w, &input_r.h);
-   // when topmost is not mapped, input size can be abnormal.
-   // in this case, it will be render by topmost showing.
-   if (!eina_rectangle_intersection(&video->geo.input_r, &input_r) || (video->geo.input_r.w <= 10 || video->geo.input_r.h <= 10))
-     {
-        VER("input area is empty");
-        return EINA_FALSE;
-     }
-
-   if (video->geo.output_r.x >= 0 && video->geo.output_r.y >= 0 &&
-       (video->geo.output_r.x + video->geo.output_r.w) <= screen.w &&
-       (video->geo.output_r.y + video->geo.output_r.h) <= screen.h)
-     return EINA_TRUE;
-
-   /* TODO: need to improve */
-
-   output_r = video->geo.output_r;
-   if (!eina_rectangle_intersection(&output_r, &screen))
-     {
-        VER("output_r(%d,%d %dx%d) screen(%d,%d %dx%d) => intersect(%d,%d %dx%d)",
-            EINA_RECTANGLE_ARGS(&video->geo.output_r),
-            EINA_RECTANGLE_ARGS(&screen), EINA_RECTANGLE_ARGS(&output_r));
-        return EINA_TRUE;
-     }
-
-   output_r.x -= video->geo.output_r.x;
-   output_r.y -= video->geo.output_r.y;
-
-   if (output_r.w <= 0 || output_r.h <= 0)
-     {
-        VER("output area is empty");
-        return EINA_FALSE;
-     }
-
-   VDB("output(%d,%d %dx%d) input(%d,%d %dx%d)",
-       EINA_RECTANGLE_ARGS(&output_r), EINA_RECTANGLE_ARGS(&input_r));
-
-   _e_video_geometry_cal_to_input_rect(video, &output_r, &input_r);
-
-   VDB("output(%d,%d %dx%d) input(%d,%d %dx%d)",
-       EINA_RECTANGLE_ARGS(&output_r), EINA_RECTANGLE_ARGS(&input_r));
-
-   output_r.x += video->geo.output_r.x;
-   output_r.y += video->geo.output_r.y;
-
-   input_r.x += video->geo.input_r.x;
-   input_r.y += video->geo.input_r.y;
-
-   output_r.x = output_r.x & ~1;
-   output_r.w = (output_r.w + 1) & ~1;
-
-   input_r.x = input_r.x & ~1;
-   input_r.w = (input_r.w + 1) & ~1;
-
-   video->geo.output_r = output_r;
-   video->geo.input_r = input_r;
-
-   _e_video_geometry_cal_physical(video);
-
-   return EINA_TRUE;
-}
-
-static void
-_e_video_format_info_get(E_Video *video)
-{
-   E_Comp_Wl_Buffer *comp_buffer;
-   tbm_surface_h tbm_surf;
-
-   comp_buffer = e_pixmap_resource_get(video->ec->pixmap);
-   EINA_SAFETY_ON_NULL_RETURN(comp_buffer);
-
-   tbm_surf = wayland_tbm_server_get_surface(e_comp->wl_comp_data->tbm.server, comp_buffer->resource);
-   EINA_SAFETY_ON_NULL_RETURN(tbm_surf);
-
-   video->tbmfmt = tbm_surface_get_format(tbm_surf);
-}
-
-static Eina_Bool
-_e_video_can_commit(E_Video *video)
-{
-   if (e_config->eom_enable == EINA_TRUE)
-     {
-        if (!video->external_video && e_output_dpms_get(video->e_output))
-          return EINA_FALSE;
-     }
-   else
-     if (e_output_dpms_get(video->e_output))
-       return EINA_FALSE;
-
-   if (!_e_video_is_visible(video))
-     return EINA_FALSE;
-
-   return EINA_TRUE;
-}
-
-static void
-_e_video_commit_handler(tdm_layer *layer, unsigned int sequence,
-                        unsigned int tv_sec, unsigned int tv_usec,
-                        void *user_data)
-{
-   E_Video *video;
-   Eina_List *l;
-   E_Comp_Wl_Video_Buf *vbuf;
-
-   EINA_LIST_FOREACH(video_list, l, video)
-     {
-        if (video == user_data) break;
-     }
-
-   if (!video) return;
-   if (!video->committed_list) return;
-
-   if (_e_video_can_commit(video))
-     {
-        tbm_surface_h displaying_buffer = _e_video_layer_get_displaying_buffer(video->layer, NULL);
-
-        EINA_LIST_FOREACH(video->committed_list, l, vbuf)
-          {
-             if (vbuf->tbm_surface == displaying_buffer) break;
-          }
-        if (!vbuf) return;
-     }
-   else
-     vbuf = eina_list_nth(video->committed_list, 0);
-
-   video->committed_list = eina_list_remove(video->committed_list, vbuf);
-
-   /* client can attachs the same wl_buffer twice. */
-   if (video->current_fb && VBUF_IS_VALID(video->current_fb) && vbuf != video->current_fb)
-     {
-        e_comp_wl_video_buffer_set_use(video->current_fb, EINA_FALSE);
-
-        if (video->current_fb->comp_buffer)
-          e_comp_wl_buffer_reference(&video->current_fb->buffer_ref, NULL);
-     }
-
-   video->current_fb = vbuf;
-
-   VDB("current_fb(%d)", MSTAMP(video->current_fb));
-}
-
-static void
-_e_video_commit_buffer(E_Video *video, E_Comp_Wl_Video_Buf *vbuf)
-{
-   video->committed_list = eina_list_append(video->committed_list, vbuf);
-
-   if (!_e_video_can_commit(video))
-     goto no_commit;
-
-   if (!_e_video_frame_buffer_show(video, vbuf))
-     goto no_commit;
-
-   return;
-
-no_commit:
-   _e_video_commit_handler(NULL, 0, 0, 0, video);
-   _e_video_vblank_handler(NULL, 0, 0, 0, video);
-}
-
-static void
-_e_video_commit_from_waiting_list(E_Video *video)
-{
-   E_Comp_Wl_Video_Buf *vbuf;
-
-   vbuf = eina_list_nth(video->waiting_list, 0);
-   video->waiting_list = eina_list_remove(video->waiting_list, vbuf);
-
-   _e_video_commit_buffer(video, vbuf);
-}
-
-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;
-   if (!ec) return 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,
-                        void *user_data)
-{
-   E_Video *video;
-   Eina_List *l;
-
-   EINA_LIST_FOREACH(video_list, l, video)
-     {
-        if (video == user_data) break;
-     }
-
-   if (!video) return;
-
-   video->waiting_vblank = EINA_FALSE;
-
-   if (video->video_plane_ready_handler) return;
-
-   if (video->waiting_list)
-     _e_video_commit_from_waiting_list(video);
-}
-
-static void
-_e_video_video_set_hook(void *data, E_Plane *plane)
-{
-   E_Video *video = (E_Video *)data;
-
-   if (video->e_plane != plane) return;
-   if (video->waiting_vblank) return;
-
-   if (video->waiting_list)
-     _e_video_commit_from_waiting_list(video);
-
-   E_FREE_FUNC(video->video_plane_ready_handler, e_plane_hook_del);
-}
-
-static Eina_Bool
-_e_video_frame_buffer_show(E_Video *video, E_Comp_Wl_Video_Buf *vbuf)
-{
-   E_Video_Info_Layer info, old_info;
-   tdm_error ret;
-   E_Client *topmost;
-   Tdm_Prop_Value *prop;
-
-   if (!vbuf)
-     {
-        if (video->layer)
-          {
-             VIN("unset layer: hide");
-             _e_video_set_layer(video, EINA_FALSE);
-          }
-        return EINA_TRUE;
-     }
-
-   if (!video->layer)
-     {
-        VIN("set layer: show");
-        if (!_e_video_set_layer(video, EINA_TRUE))
-          {
-             VER("set layer failed");
-             return EINA_FALSE;
-          }
-        // need call tdm property in list
-        Tdm_Prop_Value *prop;
-        EINA_LIST_FREE(video->tdm_prop_list, prop)
-          {
-             VIN("call property(%s), value(%d)", prop->name, (unsigned int)prop->value.u32);
-             _e_video_layer_set_property(video->layer, prop);
-             free(prop);
-          }
-     }
-
-   CLEAR(old_info);
-   ret = _e_video_layer_get_info(video->layer, &old_info);
-   EINA_SAFETY_ON_FALSE_RETURN_VAL(ret == TDM_ERROR_NONE, EINA_FALSE);
-
-   CLEAR(info);
-   info.src_config.size.h = vbuf->width_from_pitch;
-   info.src_config.size.v = vbuf->height_from_size;
-   info.src_config.pos.x = vbuf->content_r.x;
-   info.src_config.pos.y = vbuf->content_r.y;
-   info.src_config.pos.w = vbuf->content_r.w;
-   info.src_config.pos.h = vbuf->content_r.h;
-   info.src_config.format = vbuf->tbmfmt;
-   info.dst_pos.x = video->geo.tdm_output_r.x;
-   info.dst_pos.y = video->geo.tdm_output_r.y;
-   info.dst_pos.w = video->geo.tdm_output_r.w;
-   info.dst_pos.h = video->geo.tdm_output_r.h;
-   info.transform = vbuf->content_t;
-
-   if (memcmp(&old_info, &info, sizeof(tdm_info_layer)))
-     {
-        ret = _e_video_layer_set_info(video->layer, &info);
-        EINA_SAFETY_ON_FALSE_RETURN_VAL(ret == TDM_ERROR_NONE, EINA_FALSE);
-     }
-
-   ret = _e_video_layer_set_buffer(video->layer, vbuf->tbm_surface);
-   EINA_SAFETY_ON_FALSE_RETURN_VAL(ret == TDM_ERROR_NONE, EINA_FALSE);
-
-   ret = _e_video_layer_commit(video->layer, _e_video_commit_handler, video);
-   EINA_SAFETY_ON_FALSE_RETURN_VAL(ret == TDM_ERROR_NONE, EINA_FALSE);
-
-   ret = tdm_output_wait_vblank(video->output, 1, 0, _e_video_vblank_handler, video);
-   EINA_SAFETY_ON_FALSE_RETURN_VAL(ret == TDM_ERROR_NONE, EINA_FALSE);
-
-   video->waiting_vblank = EINA_TRUE;
-
-   EINA_LIST_FREE(video->late_tdm_prop_list, prop)
-     {
-        VIN("call property(%s), value(%d)", prop->name, (unsigned int)prop->value.u32);
-        _e_video_layer_set_property(video->layer, prop);
-        free(prop);
-     }
-
-   topmost = e_comp_wl_topmost_parent_get(video->ec);
-   if (topmost && topmost->argb && !e_comp_object_mask_has(video->ec->frame))
-     {
-        Eina_Bool do_punch = EINA_TRUE;
-
-        /* FIXME: the mask obj can be drawn at the wrong position in the beginnig
-         * time. It happens caused by window manager policy.
-         */
-        if ((topmost->fullscreen || topmost->maximized) &&
-            (video->geo.output_r.x == 0 || video->geo.output_r.y == 0))
-          {
-             int bw, bh;
-
-             e_pixmap_size_get(topmost->pixmap, &bw, &bh);
-
-             if (bw > 100 && bh > 100 &&
-                 video->geo.output_r.w < 100 && video->geo.output_r.h < 100)
-               {
-                  VIN("don't punch. (%dx%d, %dx%d)",
-                      bw, bh, video->geo.output_r.w, video->geo.output_r.h);
-                  do_punch = EINA_FALSE;
-               }
-          }
-
-        if (do_punch)
-          {
-             e_comp_object_mask_set(video->ec->frame, EINA_TRUE);
-             VIN("punched");
-          }
-     }
-
-   if (video_punch)
-     {
-        e_comp_object_mask_set(video->ec->frame, EINA_TRUE);
-        VIN("punched");
-     }
-
-   VDT("Client(%s):PID(%d) RscID(%d), Buffer(%p, refcnt:%d) is shown."
-       "Geometry details are : buffer size(%dx%d) src(%d,%d, %dx%d)"
-       " dst(%d,%d, %dx%d), transform(%d)",
-       e_client_util_name_get(video->ec) ?: "No Name" , video->ec->netwm.pid,
-       wl_resource_get_id(video->surface), vbuf, vbuf->ref_cnt,
-       info.src_config.size.h, info.src_config.size.v, info.src_config.pos.x,
-       info.src_config.pos.y, info.src_config.pos.w, info.src_config.pos.h,
-       info.dst_pos.x, info.dst_pos.y, info.dst_pos.w, info.dst_pos.h, info.transform);
-
-
-   return EINA_TRUE;
-}
-
-static void
-_e_video_buffer_show(E_Video *video, E_Comp_Wl_Video_Buf *vbuf, unsigned int transform)
-{
-   vbuf->content_t = transform;
-
-   e_comp_wl_video_buffer_set_use(vbuf, EINA_TRUE);
-
-   if (vbuf->comp_buffer)
-     e_comp_wl_buffer_reference(&vbuf->buffer_ref, vbuf->comp_buffer);
-
-   if (video->waiting_vblank || video->video_plane_ready_handler)
-     {
-        video->waiting_list = eina_list_append(video->waiting_list, vbuf);
-        VDB("There are waiting fbs more than 1");
-        return;
-     }
-
-   _e_video_commit_buffer(video, vbuf);
-}
-
-static void
-_e_video_cb_evas_resize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
-{
-   E_Video *video = data;
-
-   if (_e_video_geometry_cal_map(video))
-     _e_video_render(video, __FUNCTION__);
-}
-
-static void
-_e_video_cb_evas_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
-{
-   E_Video *video = data;
-
-   if (_e_video_geometry_cal_map(video))
-     _e_video_render(video, __FUNCTION__);
-}
-
-static void
-_e_video_cb_evas_show(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
-{
-   E_Video *video = data;
-
-   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..");
-        _e_video_render(video, __FUNCTION__);
-     }
-
-   /* if stand_alone is true, not show */
-   if ((video->ec->comp_data->sub.data && video->ec->comp_data->sub.data->stand_alone) ||
-       (video->ec->comp_data->sub.data && video->follow_topmost_visibility))
-     {
-#if 0 //mute off is managed by client. mute off in server made many issues.
-        if (!video->layer) return;
-
-        if (video->tdm_mute_id != -1)
-          {
-             Tdm_Prop_Value prop = {.id = video->tdm_mute_id, .value.u32 = 0};
-             VIN("video surface show. mute off (ec:%p)", video->ec);
-             _e_video_layer_set_property(video->layer, &prop);
-          }
-#endif
-        return;
-     }
-
-   if (!video->layer)
-     {
-        VIN("set layer: show");
-        if (!_e_video_set_layer(video, EINA_TRUE))
-          {
-             VER("set layer failed");
-             return;
-          }
-        // need call tdm property in list
-        Tdm_Prop_Value *prop;
-        EINA_LIST_FREE(video->tdm_prop_list, prop)
-          {
-             VIN("call property(%s), value(%d)", prop->name, (unsigned int)prop->value.u32);
-             _e_video_layer_set_property(video->layer, prop);
-             free(prop);
-          }
-     }
-
-   VIN("evas show (ec:%p)", video->ec);
-   if (video->current_fb)
-     _e_video_buffer_show(video, video->current_fb, video->current_fb->content_t);
-}
-
-static void
-_e_video_cb_evas_hide(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
-{
-   E_Video *video = data;
-
-   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)
-     {
-        if (!video->layer) return;
-
-        if (video->tdm_mute_id != -1)
-          {
-             Tdm_Prop_Value prop = {.id = video->tdm_mute_id, .value.u32 = 1};
-             VIN("video surface hide. mute on (ec:%p)", video->ec);
-             _e_video_layer_set_property(video->layer, &prop);
-          }
-        return;
-     }
-
-   VIN("evas hide (ec:%p)", video->ec);
-   _e_video_frame_buffer_show(video, NULL);
-}
-
-static E_Video *
-_e_video_create(struct wl_resource *video_object, struct wl_resource *surface)
-{
-   E_Video *video;
-   E_Client *ec;
-
-   ec = wl_resource_get_user_data(surface);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
-   EINA_SAFETY_ON_TRUE_RETURN_VAL(e_object_is_del(E_OBJECT(ec)), NULL);
-
-   video = calloc(1, sizeof *video);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(video, NULL);
-
-   video->video_object = video_object;
-   video->surface = surface;
-   video->output_align = -1;
-   video->pp_align = -1;
-   video->video_align = -1;
-   video->tdm_mute_id = -1;
-
-   VIN("create. ec(%p) wl_surface@%d", ec, wl_resource_get_id(video->surface));
-
-   video_list = eina_list_append(video_list, video);
-
-   _e_video_set(video, ec);
-
-   return video;
-}
-
-static void
-_e_video_set(E_Video *video, E_Client *ec)
-{
-   int ominw = -1, ominh = -1, omaxw = -1, omaxh = -1;
-   int i, count = 0;
-   const tdm_prop *props;
-
-   video->ec = ec;
-   video->window = e_client_util_win_get(ec);
-
-   evas_object_event_callback_add(video->ec->frame, EVAS_CALLBACK_HIDE,
-                                  _e_video_cb_evas_hide, video);
-   evas_object_event_callback_add(video->ec->frame, EVAS_CALLBACK_SHOW,
-                                  _e_video_cb_evas_show, video);
-
-   if (e_config->eom_enable == EINA_TRUE)
-     {
-        video->external_video = e_eom_is_ec_external(ec);
-        if (video->external_video)
-          {
-             tdm_error ret;
-             unsigned int index = 0;
-
-             video->output = e_eom_tdm_output_by_ec_get(ec);
-             EINA_SAFETY_ON_NULL_RETURN(video->output);
-
-             ret = tdm_output_get_pipe(video->output, &index);
-             EINA_SAFETY_ON_FALSE_RETURN(ret == TDM_ERROR_NONE);
-
-             video->e_output = e_output_find_by_index(index);
-             EINA_SAFETY_ON_NULL_RETURN(video->e_output);
-
-             ec->comp_data->video_client = 1;
-
-             return;
-          }
-     }
-
-   EINA_SAFETY_ON_NULL_RETURN(video->ec->zone);
-
-   video->e_output = e_output_find(video->ec->zone->output_id);
-   EINA_SAFETY_ON_NULL_RETURN(video->e_output);
-
-   video->output = video->e_output->toutput;
-   EINA_SAFETY_ON_NULL_RETURN(video->output);
-
-   if (video_to_primary)
-     {
-        VIN("show video to primary layer");
-        ec->comp_data->video_client = 0;
-        e_policy_animatable_lock(ec, E_POLICY_ANIMATABLE_NEVER, 1);
-     }
-   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");
-        ec->comp_data->video_client = 1;
-     }
-   else
-     {
-        /* If tdm doesn't offer video layers, we assign a tdm layer now. If failed,
-         * video will be displayed via the UI rendering path.
-         */
-        if (_e_video_set_layer(video, EINA_TRUE))
-          {
-             VIN("video client");
-             ec->comp_data->video_client = 1;
-          }
-        else
-          {
-             VIN("no video client");
-             ec->comp_data->video_client = 0;
-             e_policy_animatable_lock(ec, E_POLICY_ANIMATABLE_NEVER, 1);
-          }
-     }
-
-   tdm_output_get_available_size(video->output, &ominw, &ominh, &omaxw, &omaxh, &video->output_align);
-
-   if (!e_comp_screen_pp_support())
-     {
-        video->video_align = video->output_align;
-        tizen_video_object_send_size(video->video_object,
-                                     ominw, ominh, omaxw, omaxh, video->output_align);
-     }
-   else
-     {
-        int minw = -1, minh = -1, maxw = -1, maxh = -1;
-        int pminw = -1, pminh = -1, pmaxw = -1, pmaxh = -1;
-
-        tdm_display_get_pp_available_size(e_comp->e_comp_screen->tdisplay, &pminw, &pminh, &pmaxw, &pmaxh, &video->pp_align);
-
-        minw = MAX(ominw, pminw);
-        minh = MAX(ominh, pminh);
-
-        if (omaxw != -1 && pmaxw == -1)
-          maxw = omaxw;
-        else if (omaxw == -1 && pmaxw != -1)
-          maxw = pmaxw;
-        else
-          maxw = MIN(omaxw, pmaxw);
-
-        if (omaxh != -1 && pmaxh == -1)
-          maxh = omaxh;
-        else if (omaxh == -1 && pmaxh != -1)
-          maxh = pmaxh;
-        else
-          maxh = MIN(omaxh, pmaxh);
-
-        if (video->output_align != -1 && video->pp_align == -1)
-          video->video_align = video->output_align;
-        else if (video->output_align == -1 && video->pp_align != -1)
-          video->video_align = video->pp_align;
-        else if (video->output_align == -1 && video->pp_align == -1)
-          video->video_align = video->pp_align;
-        else if (video->output_align > 0 && video->pp_align > 0)
-          video->video_align = lcm(video->output_align, video->pp_align);
-        else
-          ERR("invalid align: %d, %d", video->output_align, video->pp_align);
-
-        tizen_video_object_send_size(video->video_object,
-                                     minw, minh, maxw, maxh, video->video_align);
-        VIN("align width: output(%d) pp(%d) video(%d)",
-            video->output_align, video->pp_align, video->video_align);
-     }
-
-   _e_video_layer_get_available_properties(video->layer, &props, &count);
-   for (i = 0; i < count; i++)
-     {
-        tdm_value value;
-        _e_video_layer_get_property(video->layer, props[i].id, &value);
-        tizen_video_object_send_attribute(video->video_object, props[i].name, value.u32);
-
-        if (!strncmp(props[i].name, "mute", TDM_NAME_LEN))
-          video->tdm_mute_id = props[i].id;
-     }
-}
-
-static void
-_e_video_hide(E_Video *video)
-{
-   E_Comp_Wl_Video_Buf *vbuf;
-
-   if (video->current_fb || video->committed_list)
-     _e_video_frame_buffer_show(video, NULL);
-
-   if (video->current_fb)
-     {
-        e_comp_wl_video_buffer_set_use(video->current_fb, EINA_FALSE);
-        video->current_fb = NULL;
-     }
-
-   if (video->old_comp_buffer)
-     video->old_comp_buffer = NULL;
-
-   EINA_LIST_FREE(video->committed_list, vbuf)
-      e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
-
-   EINA_LIST_FREE(video->waiting_list, vbuf)
-      e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
-}
-
-static void
-_e_video_destroy(E_Video *video)
-{
-   E_Comp_Wl_Video_Buf *vbuf;
-   Eina_List *l = NULL, *ll = NULL;
-
-   if (!video)
-     return;
-
-   VIN("destroy");
-
-   if (video->cb_registered)
-     {
-        evas_object_event_callback_del_full(video->ec->frame, EVAS_CALLBACK_RESIZE,
-                                            _e_video_cb_evas_resize, video);
-        evas_object_event_callback_del_full(video->ec->frame, EVAS_CALLBACK_MOVE,
-                                            _e_video_cb_evas_move, video);
-     }
-
-   evas_object_event_callback_del_full(video->ec->frame, EVAS_CALLBACK_HIDE,
-                                       _e_video_cb_evas_hide, video);
-   evas_object_event_callback_del_full(video->ec->frame, EVAS_CALLBACK_SHOW,
-                                       _e_video_cb_evas_show, video);
-
-   wl_resource_set_destructor(video->video_object, NULL);
-
-   _e_video_hide(video);
-
-   /* others */
-   EINA_LIST_FOREACH_SAFE(video->input_buffer_list, l, ll, vbuf)
-     {
-        e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
-        e_comp_wl_video_buffer_unref(vbuf);
-     }
-
-   EINA_LIST_FOREACH_SAFE(video->pp_buffer_list, l, ll, vbuf)
-     {
-        e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
-        e_comp_wl_video_buffer_unref(vbuf);
-     }
-
-   if(video->tdm_prop_list)
-     {
-        Tdm_Prop_Value *tdm_prop;
-        EINA_LIST_FREE(video->tdm_prop_list, tdm_prop)
-          {
-             free(tdm_prop);
-          }
-     }
-   if(video->late_tdm_prop_list)
-     {
-        Tdm_Prop_Value *tdm_prop;
-        EINA_LIST_FREE(video->late_tdm_prop_list, tdm_prop)
-          {
-             free(tdm_prop);
-          }
-     }
-
-   if (video->input_buffer_list)
-     NEVER_GET_HERE();
-   if (video->pp_buffer_list)
-     NEVER_GET_HERE();
-   if (video->tdm_prop_list)
-     NEVER_GET_HERE();
-   if (video->late_tdm_prop_list)
-     NEVER_GET_HERE();
-
-   /* destroy converter second */
-   if (video->pp)
-     tdm_pp_destroy(video->pp);
-
-   if (video->layer)
-     {
-        VIN("unset layer: destroy");
-        _e_video_set_layer(video, EINA_FALSE);
-     }
-
-   video_list = eina_list_remove(video_list, video);
-
-   free(video);
-
-#if 0
-   if (e_comp_wl_video_buffer_list_length() > 0)
-     e_comp_wl_video_buffer_list_print(NULL);
-#endif
-}
-
-static Eina_Bool
-_e_video_check_if_pp_needed(E_Video *video)
-{
-   int i, count = 0;
-   const tbm_format *formats;
-   Eina_Bool found = EINA_FALSE;
-   tdm_layer_capability capabilities = 0;
-
-   if (e_hwc_policy_get(video->e_output->hwc) != E_HWC_POLICY_WINDOWS)
-     {
-        tdm_layer *layer = _e_video_tdm_video_layer_get(video->output);
-
-        tdm_layer_get_capabilities(layer, &capabilities);
-
-        /* 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;
-          }
-
-        if (capabilities & TDM_LAYER_CAPABILITY_SCANOUT)
-          goto need_pp;
-
-        /* check size */
-        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;
-
-        /* check rotate */
-        if (video->geo.transform || e_comp->e_comp_screen->rotation > 0)
-          if (!(capabilities & TDM_LAYER_CAPABILITY_TRANSFORM))
-            goto need_pp;
-     }
-   else
-     {
-        tdm_hwc_capability capabilities = 0;
-        tdm_error error;
-
-        error = tdm_hwc_get_video_supported_formats(video->e_output->hwc->thwc, &formats, &count);
-        if (error != TDM_ERROR_NONE)
-          {
-             video->pp_tbmfmt = TBM_FORMAT_ARGB8888;
-             return EINA_TRUE;
-          }
-        for (i = 0; i < count; i++)
-          if (formats[i] == video->tbmfmt)
-            {
-               found = EINA_TRUE;
-               break;
-            }
-
-        if (!found)
-          {
-             video->pp_tbmfmt = TBM_FORMAT_ARGB8888;
-             return EINA_TRUE;
-          }
-
-        error = tdm_hwc_get_capabilities(video->e_output->hwc->thwc, &capabilities);
-        if (error != TDM_ERROR_NONE)
-          {
-             video->pp_tbmfmt = TBM_FORMAT_ARGB8888;
-             return EINA_TRUE;
-          }
-
-        /* check size */
-        if (capabilities & TDM_HWC_CAPABILITY_VIDEO_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_CAPABILITY_VIDEO_SCALE))
-            goto need_pp;
-
-        /* check rotate */
-        if (video->geo.transform || e_comp->e_comp_screen->rotation > 0)
-          if (!(capabilities & TDM_HWC_CAPABILITY_VIDEO_TRANSFORM))
-            goto need_pp;
-     }
-
-   return EINA_FALSE;
-
-need_pp:
-   video->pp_tbmfmt = video->tbmfmt;
-   return EINA_TRUE;
-}
-
-static void
-_e_video_pp_cb_done(tdm_pp *pp, tbm_surface_h sb, tbm_surface_h db, void *user_data)
-{
-   E_Video *video = (E_Video*)user_data;
-   E_Comp_Wl_Video_Buf *input_buffer, *pp_buffer;
-
-   input_buffer = _e_video_vbuf_find(video->input_buffer_list, sb);
-   if (input_buffer)
-     e_comp_wl_video_buffer_unref(input_buffer);
-
-   pp_buffer = _e_video_vbuf_find(video->pp_buffer_list, db);
-   if (pp_buffer)
-     {
-        e_comp_wl_video_buffer_set_use(pp_buffer, EINA_FALSE);
-        if (!_e_video_is_visible(video)) return;
-
-        _e_video_buffer_show(video, pp_buffer, 0);
-     }
-   else
-     {
-        VER("There is no pp_buffer");
-        // there is no way to set in_use flag.
-        // This will cause issue when server get available pp_buffer.
-     }
-}
-
-static void
-_e_video_render(E_Video *video, const char *func)
-{
-   E_Comp_Wl_Buffer *comp_buffer;
-   E_Comp_Wl_Video_Buf *pp_buffer = NULL;
-   E_Comp_Wl_Video_Buf *input_buffer = NULL;
-   E_Client *topmost;
-
-   EINA_SAFETY_ON_NULL_RETURN(video->ec);
-
-   /* buffer can be NULL when camera/video's mode changed. Do nothing and
-    * keep previous frame in this case.
-    */
-   if (!video->ec->pixmap)
-     return;
-
-   if (!_e_video_is_visible(video))
-     {
-        _e_video_hide(video);
-        return;
-     }
-
-   comp_buffer = e_pixmap_resource_get(video->ec->pixmap);
-   if (!comp_buffer) return;
-
-   _e_video_format_info_get(video);
-
-   /* not interested with other buffer type */
-   if (!wayland_tbm_server_get_surface(NULL, comp_buffer->resource))
-     return;
-
-   topmost = e_comp_wl_topmost_parent_get(video->ec);
-   EINA_SAFETY_ON_NULL_RETURN(topmost);
-
-   if(e_comp_wl_viewport_is_changed(topmost))
-     {
-        VIN("need update viewport: apply topmost");
-        e_comp_wl_viewport_apply(topmost);
-     }
-
-   if (!_e_video_geometry_cal(video))
-     {
-        if(!video->need_force_render && !_e_video_parent_is_viewable(video))
-          {
-             VIN("need force render");
-             video->need_force_render = EINA_TRUE;
-          }
-        return;
-     }
-
-   if (!memcmp(&video->old_geo, &video->geo, sizeof video->geo) &&
-       video->old_comp_buffer == comp_buffer)
-     return;
-
-   video->need_force_render = EINA_FALSE;
-
-   DBG("====================================== (%s)", func);
-   VDB("old: "GEO_FMT" buf(%p)", GEO_ARG(&video->old_geo), video->old_comp_buffer);
-   VDB("new: "GEO_FMT" buf(%p) %c%c%c%c", GEO_ARG(&video->geo), comp_buffer, FOURCC_STR(video->tbmfmt));
-
-   _e_video_input_buffer_valid(video, comp_buffer);
-
-   if (!_e_video_check_if_pp_needed(video))
-     {
-        /* 1. non converting case */
-        input_buffer = _e_video_input_buffer_get(video, comp_buffer, EINA_TRUE);
-        EINA_SAFETY_ON_NULL_GOTO(input_buffer, render_fail);
-
-        _e_video_buffer_show(video, input_buffer, video->geo.tdm_transform);
-
-        video->old_geo = video->geo;
-        video->old_comp_buffer = comp_buffer;
-
-        goto done;
-     }
-
-   /* 2. converting case */
-   if (!video->pp)
-     {
-        tdm_pp_capability pp_cap;
-        tdm_error error = TDM_ERROR_NONE;
-
-        video->pp = tdm_display_create_pp(e_comp->e_comp_screen->tdisplay, NULL);
-        EINA_SAFETY_ON_NULL_GOTO(video->pp, render_fail);
-
-        tdm_display_get_pp_available_size(e_comp->e_comp_screen->tdisplay, &video->pp_minw, &video->pp_minh,
-                                          &video->pp_maxw, &video->pp_maxh, &video->pp_align);
-
-        error = tdm_display_get_pp_capabilities(e_comp->e_comp_screen->tdisplay, &pp_cap);
-        if (error == TDM_ERROR_NONE)
-          {
-             if (pp_cap & TDM_PP_CAPABILITY_SCANOUT)
-               video->pp_scanout = EINA_TRUE;
-          }
-     }
-
-   if ((video->pp_minw > 0 && (video->geo.input_r.w < video->pp_minw || video->geo.tdm_output_r.w < video->pp_minw)) ||
-       (video->pp_minh > 0 && (video->geo.input_r.h < video->pp_minh || video->geo.tdm_output_r.h < video->pp_minh)) ||
-       (video->pp_maxw > 0 && (video->geo.input_r.w > video->pp_maxw || video->geo.tdm_output_r.w > video->pp_maxw)) ||
-       (video->pp_maxh > 0 && (video->geo.input_r.h > video->pp_maxh || video->geo.tdm_output_r.h > video->pp_maxh)))
-     {
-        INF("size(%dx%d, %dx%d) is out of PP range",
-            video->geo.input_r.w, video->geo.input_r.h, video->geo.tdm_output_r.w, video->geo.tdm_output_r.h);
-        goto done;
-     }
-
-   input_buffer = _e_video_input_buffer_get(video, comp_buffer, EINA_FALSE);
-   EINA_SAFETY_ON_NULL_GOTO(input_buffer, render_fail);
-
-   pp_buffer = _e_video_pp_buffer_get(video, video->geo.tdm_output_r.w, video->geo.tdm_output_r.h);
-   EINA_SAFETY_ON_NULL_GOTO(pp_buffer, render_fail);
-
-   if (memcmp(&video->old_geo, &video->geo, sizeof video->geo))
-     {
-        tdm_info_pp info;
-
-        CLEAR(info);
-        info.src_config.size.h = input_buffer->width_from_pitch;
-        info.src_config.size.v = input_buffer->height_from_size;
-        info.src_config.pos.x = video->geo.input_r.x;
-        info.src_config.pos.y = video->geo.input_r.y;
-        info.src_config.pos.w = video->geo.input_r.w;
-        info.src_config.pos.h = video->geo.input_r.h;
-        info.src_config.format = video->tbmfmt;
-        info.dst_config.size.h = pp_buffer->width_from_pitch;
-        info.dst_config.size.v = pp_buffer->height_from_size;
-        info.dst_config.pos.w = video->geo.tdm_output_r.w;
-        info.dst_config.pos.h = video->geo.tdm_output_r.h;
-        info.dst_config.format = video->pp_tbmfmt;
-        info.transform = video->geo.tdm_transform;
-
-        if (tdm_pp_set_info(video->pp, &info))
-          {
-             VER("tdm_pp_set_info() failed");
-             goto render_fail;
-          }
-
-        if (tdm_pp_set_done_handler(video->pp, _e_video_pp_cb_done, video))
-          {
-             VER("tdm_pp_set_done_handler() failed");
-             goto render_fail;
-          }
-
-        CLEAR(video->pp_r);
-        video->pp_r.w = info.dst_config.pos.w;
-        video->pp_r.h = info.dst_config.pos.h;
-     }
-
-   pp_buffer->content_r = video->pp_r;
-
-   if (tdm_pp_attach(video->pp, input_buffer->tbm_surface, pp_buffer->tbm_surface))
-     {
-        VER("tdm_pp_attach() failed");
-        goto render_fail;
-     }
-
-   e_comp_wl_video_buffer_set_use(pp_buffer, EINA_TRUE);
-
-   e_comp_wl_buffer_reference(&input_buffer->buffer_ref, comp_buffer);
-
-   if (tdm_pp_commit(video->pp))
-     {
-        VER("tdm_pp_commit() failed");
-        e_comp_wl_video_buffer_set_use(pp_buffer, EINA_FALSE);
-        goto render_fail;
-     }
-
-   video->old_geo = video->geo;
-   video->old_comp_buffer = comp_buffer;
-
-   goto done;
-
-render_fail:
-   if (input_buffer)
-     e_comp_wl_video_buffer_unref(input_buffer);
-
-done:
-   if (!video->cb_registered)
-     {
-        evas_object_event_callback_add(video->ec->frame, EVAS_CALLBACK_RESIZE,
-                                       _e_video_cb_evas_resize, video);
-        evas_object_event_callback_add(video->ec->frame, EVAS_CALLBACK_MOVE,
-                                       _e_video_cb_evas_move, video);
-        video->cb_registered = EINA_TRUE;
-     }
-   DBG("======================================.");
-}
-
-static Eina_Bool
-_e_video_cb_ec_buffer_change(void *data, int type, void *event)
-{
-   E_Client *ec;
-   E_Event_Client *ev = event;
-   E_Video *video;
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(ev->ec, ECORE_CALLBACK_PASS_ON);
-
-   ec = ev->ec;
-   if (e_object_is_del(E_OBJECT(ec)))
-     return ECORE_CALLBACK_PASS_ON;
-
-   /* not interested with non video_surface,  */
-   video = find_video_with_surface(ec->comp_data->surface);
-   if (!video) return ECORE_CALLBACK_PASS_ON;
-
-   if (!video->ec->comp_data->video_client)
-     return ECORE_CALLBACK_PASS_ON;
-
-   if (e_config->eom_enable == EINA_TRUE)
-     {
-        /* skip external client buffer if its top parent is not current for eom anymore */
-        if (video->external_video && e_eom_is_ec_external(ec))
-          {
-             VWR("skip external buffer");
-             return ECORE_CALLBACK_PASS_ON;
-          }
-     }
-
-   _e_video_render(video, __FUNCTION__);
-
-   return ECORE_CALLBACK_PASS_ON;
-}
-
-static Eina_Bool
-_e_video_cb_ec_remove(void *data, int type, void *event)
-{
-   E_Event_Client *ev = event;
-   E_Client *ec;
-   E_Video *video;
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(ev->ec, ECORE_CALLBACK_PASS_ON);
-
-   ec = ev->ec;
-   if (!ec->comp_data) return ECORE_CALLBACK_PASS_ON;
-
-   video = find_video_with_surface(ec->comp_data->surface);
-   if (!video) return ECORE_CALLBACK_PASS_ON;
-
-   _e_video_destroy(video);
-
-   return ECORE_CALLBACK_PASS_ON;
-}
-
-static Eina_Bool
-_e_video_cb_ec_client_show(void *data, int type, void *event)
-{
-   E_Event_Client *ev = event;
-   E_Client *ec;
-   E_Client *video_ec = NULL;
-   E_Video *video = NULL;
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(ev->ec, ECORE_CALLBACK_PASS_ON);
-
-   ec = ev->ec;
-   if (!ec->comp_data) return ECORE_CALLBACK_PASS_ON;
-
-   video_ec = find_video_child_get(ec);
-   if (!video_ec) return ECORE_CALLBACK_PASS_ON;
-
-   video = find_video_with_surface(video_ec->comp_data->surface);
-   if (!video) return ECORE_CALLBACK_PASS_ON;
-
-   VIN("client(0x%08"PRIxPTR") show: find video child(0x%08"PRIxPTR")", (Ecore_Window)e_client_util_win_get(ec), (Ecore_Window)e_client_util_win_get(video_ec));
-   if(video->old_comp_buffer)
-     {
-        VIN("video already rendering..");
-        return ECORE_CALLBACK_PASS_ON;
-     }
-
-   if (ec == e_comp_wl_topmost_parent_get(video->ec))
-     {
-        if (e_config->eom_enable == EINA_TRUE)
-          {
-             /* skip external client buffer if its top parent is not current for eom anymore */
-             if (video->external_video && e_eom_is_ec_external(ec))
-               {
-                  VWR("skip external buffer");
-                  return ECORE_CALLBACK_PASS_ON;
-               }
-          }
-
-        VIN("video need rendering..");
-        e_comp_wl_viewport_apply(ec);
-        _e_video_render(video, __FUNCTION__);
-     }
-
-   return ECORE_CALLBACK_PASS_ON;
-}
-
-static Eina_Bool
-_e_video_cb_ec_visibility_change(void *data, int type, void *event)
-{
-   E_Event_Remote_Surface_Provider *ev = event;
-   E_Client *ec = ev->ec;
-   E_Video *video;
-   Eina_List *l;
-
-   EINA_LIST_FOREACH(video_list, l, video)
-     {
-        E_Client *offscreen_parent = find_offscreen_parent_get(video->ec);
-        if (!offscreen_parent) continue;
-        if (offscreen_parent != ec) continue;
-        switch (ec->visibility.obscured)
-          {
-           case E_VISIBILITY_FULLY_OBSCURED:
-              _e_video_cb_evas_hide(video, NULL, NULL, NULL);
-              break;
-           case E_VISIBILITY_UNOBSCURED:
-              _e_video_cb_evas_show(video, NULL, NULL, NULL);
-              break;
-           default:
-              VER("Not implemented");
-              return ECORE_CALLBACK_PASS_ON;
-          }
-     }
-
-   return ECORE_CALLBACK_PASS_ON;
-}
-
-static Eina_Bool
-_e_video_cb_topmost_ec_visibility_change(void *data, int type, void *event)
-{
-   E_Event_Client *ev = event;
-   E_Client *ec = ev->ec;
-   E_Video *video;
-   Eina_List *l = NULL;
-
-   EINA_LIST_FOREACH(video_list, l, video)
-     {
-        E_Client *topmost = e_comp_wl_topmost_parent_get(video->ec);
-        if (!topmost) continue;
-        if (topmost == video->ec) continue;
-        if (topmost != ec) continue;
-        if (video->follow_topmost_visibility)
-          {
-             switch (ec->visibility.obscured)
-               {
-                case E_VISIBILITY_FULLY_OBSCURED:
-                   VIN("follow_topmost_visibility: fully_obscured");
-                   _e_video_cb_evas_hide(video, NULL, NULL, NULL);
-                   break;
-                case E_VISIBILITY_UNOBSCURED:
-                   VIN("follow_topmost_visibility: UNOBSCURED");
-                   _e_video_cb_evas_show(video, NULL, NULL, NULL);
-                   break;
-                default:
-                   return ECORE_CALLBACK_PASS_ON;
-               }
-          }
-     }
-
-   return ECORE_CALLBACK_PASS_ON;
-}
-
-static void
-_e_comp_wl_video_object_destroy(struct wl_resource *resource)
-{
-   E_Video *video = wl_resource_get_user_data(resource);
-   EINA_SAFETY_ON_NULL_RETURN(video);
-
-   VDT("Video from Client(%s):PID(%d) is being destroyed, details are: "
-       "Buffer(%p), Video_Format(%c%c%c%c), "
-       "Buffer_Size(%dx%d), Src Rect(%d,%d, %dx%d), Dest Rect(%d,%d, %dx%d),"
-       " Transformed(%d)",
-       e_client_util_name_get(video->ec) ?: "No Name" , video->ec->netwm.pid,
-       video->current_fb, FOURCC_STR(video->tbmfmt),
-       video->geo.input_w, video->geo.input_h, video->geo.input_r.x ,
-       video->geo.input_r.y, video->geo.input_r.w, video->geo.input_r.h,
-       video->geo.output_r.x ,video->geo.output_r.y, video->geo.output_r.w,
-       video->geo.output_r.h, video->geo.transform);
-
-   _e_video_destroy(video);
-}
-
-static void
-_e_comp_wl_video_object_cb_destroy(struct wl_client *client, struct wl_resource *resource)
-{
-   wl_resource_destroy(resource);
-}
-
-static void
-_e_comp_wl_video_object_cb_set_attribute(struct wl_client *client,
-                                         struct wl_resource *resource,
-                                         const char *name,
-                                         int32_t value)
-{
-   E_Video *video;
-   int id;
-
-   video = wl_resource_get_user_data(resource);
-   EINA_SAFETY_ON_NULL_RETURN(video);
-
-   if(video->ec)
-     VDT("Client(%s):PID(%d) RscID(%d) Attribute:%s, Value:%d",
-         e_client_util_name_get(video->ec) ?: "No Name",
-         video->ec->netwm.pid, wl_resource_get_id(video->surface),
-         name, value);
-
-   // check available property & count
-   id = _e_video_get_prop_id(video, name);
-   if(id < 0)
-     {
-        VIN("no available property");
-        return;
-     }
-
-   if (!video->layer && video->allowed_attribute)
-     {
-        VIN("set layer: set_attribute");
-        if (!_e_video_set_layer(video, EINA_TRUE))
-          {
-             VER("set layer failed");
-             return;
-          }
-     }
-
-   if (!_e_video_is_visible(video) || !video->layer)
-     {
-        /* if mute off, need to do it after buffer commit */
-        if (!strncmp(name, "mute", TDM_NAME_LEN) && value == 0)
-          {
-             Tdm_Prop_Value *prop = NULL;
-             const Eina_List *l = NULL;
-
-             EINA_LIST_FOREACH(video->late_tdm_prop_list, l, prop)
-               {
-                  if (!strncmp(name, prop->name, TDM_NAME_LEN))
-                    {
-                       prop->value.u32 = value;
-                       VDB("update property(%s) value(%d)", prop->name, value);
-                       return;
-                    }
-               }
-
-             prop = calloc(1, sizeof(Tdm_Prop_Value));
-             if(!prop) return;
-
-             prop->value.u32 = value;
-             prop->id = id;
-             memcpy(prop->name, name, sizeof(TDM_NAME_LEN));
-             VIN("Add property(%s) value(%d)", prop->name, value);
-             video->late_tdm_prop_list = eina_list_append(video->late_tdm_prop_list, prop);
-             return;
-          }
-     }
-
-   // check set video layer
-   if(!video->layer)
-     {
-        VIN("no layer: save property value");
-
-        Tdm_Prop_Value *prop = NULL;
-        const Eina_List *l = NULL;
-
-        EINA_LIST_FOREACH(video->tdm_prop_list, l, prop)
-          {
-             if (!strncmp(name, prop->name, TDM_NAME_LEN))
-               {
-                  VDB("find prop data(%s) update value(%d -> %d)", prop->name, (unsigned int)prop->value.u32, (unsigned int)value);
-                  prop->value.u32 = value;
-                  return;
-               }
-          }
-        EINA_LIST_FOREACH(video->late_tdm_prop_list, l, prop)
-          {
-             if (!strncmp(name, prop->name, TDM_NAME_LEN))
-               {
-                  VDB("find prop data(%s) update value(%d -> %d)", prop->name, (unsigned int)prop->value.u32, (unsigned int)value);
-                  prop->value.u32 = value;
-                  return;
-               }
-          }
-
-        prop = calloc(1, sizeof(Tdm_Prop_Value));
-        if(!prop) return;
-        prop->value.u32 = value;
-        prop->id = id;
-        memcpy(prop->name, name, sizeof(TDM_NAME_LEN));
-        VIN("Add property(%s) value(%d)", prop->name, value);
-        video->tdm_prop_list = eina_list_append(video->tdm_prop_list, prop);
-     }
-   // if set layer call property
-   else
-     {
-        Tdm_Prop_Value prop = {.id = id, .value.u32 = value};
-        VIN("set layer: call property(%s), value(%d)", name, value);
-        _e_video_layer_set_property(video->layer, &prop);
-     }
-}
-
-static void
-_e_comp_wl_video_object_cb_follow_topmost_visibility(struct wl_client *client,
-                                                     struct wl_resource *resource)
-{
-   E_Video *video;
-
-   video = wl_resource_get_user_data(resource);
-   EINA_SAFETY_ON_NULL_RETURN(video);
-
-   if(!video->ec || video->follow_topmost_visibility)
-     return;
-
-   VIN("set follow_topmost_visibility");
-
-   video->follow_topmost_visibility= EINA_TRUE;
-
-}
-
-static void
-_e_comp_wl_video_object_cb_unfollow_topmost_visibility(struct wl_client *client,
-                                                       struct wl_resource *resource)
-{
-   E_Video *video;
-
-   video = wl_resource_get_user_data(resource);
-   EINA_SAFETY_ON_NULL_RETURN(video);
-
-   if(!video->ec || !video->follow_topmost_visibility)
-     return;
-
-   VIN("set unfollow_topmost_visibility");
-
-   video->follow_topmost_visibility= EINA_FALSE;
-
-}
-
-static void
-_e_comp_wl_video_object_cb_allowed_attribute(struct wl_client *client,
-                                             struct wl_resource *resource)
-{
-   E_Video *video;
-
-   video = wl_resource_get_user_data(resource);
-   EINA_SAFETY_ON_NULL_RETURN(video);
-
-   if(!video->ec || video->allowed_attribute)
-     return;
-
-   VIN("set allowed_attribute");
-
-   video->allowed_attribute = EINA_TRUE;
-
-}
-
-static void
-_e_comp_wl_video_object_cb_disallowed_attribute(struct wl_client *client,
-                                                struct wl_resource *resource)
-{
-   E_Video *video;
-
-   video = wl_resource_get_user_data(resource);
-   EINA_SAFETY_ON_NULL_RETURN(video);
-
-   if(!video->ec || !video->allowed_attribute)
-     return;
-
-   VIN("set disallowed_attribute");
-
-   video->allowed_attribute = EINA_FALSE;
-
-}
-
-static const struct tizen_video_object_interface _e_comp_wl_video_object_interface =
-{
-   _e_comp_wl_video_object_cb_destroy,
-   _e_comp_wl_video_object_cb_set_attribute,
-   _e_comp_wl_video_object_cb_follow_topmost_visibility,
-   _e_comp_wl_video_object_cb_unfollow_topmost_visibility,
-   _e_comp_wl_video_object_cb_allowed_attribute,
-   _e_comp_wl_video_object_cb_disallowed_attribute,
-};
-
-static void
-_e_comp_wl_video_cb_get_object(struct wl_client *client,
-                               struct wl_resource *resource,
-                               uint32_t id,
-                               struct wl_resource *surface)
-{
-   E_Video *video;
-   int version = wl_resource_get_version(resource);
-   struct wl_resource *res;
-
-   res = wl_resource_create(client, &tizen_video_object_interface, version, id);
-   if (res == NULL)
-     {
-        wl_client_post_no_memory(client);
-        return;
-     }
-
-   if (!(video = _e_video_create(res, surface)))
-     {
-        wl_resource_destroy(res);
-        wl_client_post_no_memory(client);
-        return;
-     }
-
-   wl_resource_set_implementation(res, &_e_comp_wl_video_object_interface,
-                                  video, _e_comp_wl_video_object_destroy);
-}
-
-static void
-_e_comp_wl_video_cb_get_viewport(struct wl_client *client,
-                                 struct wl_resource *resource,
-                                 uint32_t id,
-                                 struct wl_resource *surface)
-{
-   E_Client *ec;
-
-   if (!(ec = wl_resource_get_user_data(surface))) return;
-   if (!ec->comp_data) return;
-
-   if (ec->comp_data && ec->comp_data->scaler.viewport)
-     {
-        wl_resource_post_error(resource,
-                               TIZEN_VIDEO_ERROR_VIEWPORT_EXISTS,
-                               "a viewport for that subsurface already exists");
-        return;
-     }
-
-   if (!e_comp_wl_viewport_create(resource, id, surface))
-     {
-        ERR("Failed to create viewport for wl_surface@%d",
-            wl_resource_get_id(surface));
-        wl_client_post_no_memory(client);
-        return;
-     }
-}
-
-static void
-_e_comp_wl_video_cb_destroy(struct wl_client *client, struct wl_resource *resource)
-{
-   wl_resource_destroy(resource);
-}
-
-static const struct tizen_video_interface _e_comp_wl_video_interface =
-{
-   _e_comp_wl_video_cb_get_object,
-   _e_comp_wl_video_cb_get_viewport,
-   _e_comp_wl_video_cb_destroy,
-};
-
-static void
-_e_comp_wl_video_cb_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
-{
-   struct wl_resource *res;
-   const uint32_t *formats = NULL;
-   int i, count = 0;
-   Eina_List *pp_format_list = NULL;
-   Eina_List *l = NULL;
-   uint32_t *pp_format;
-
-   if (!(res = wl_resource_create(client, &tizen_video_interface, version, id)))
-     {
-        ERR("Could not create tizen_video_interface resource: %m");
-        wl_client_post_no_memory(client);
-        return;
-     }
-
-   wl_resource_set_implementation(res, &_e_comp_wl_video_interface, NULL, NULL);
-
-   /* 1st, use pp information. */
-   if (e_comp_screen_pp_support())
-     pp_format_list = e_comp_screen_pp_available_formats_get();
-
-   if (pp_format_list)
-     {
-        EINA_LIST_FOREACH(pp_format_list, l, pp_format)
-          tizen_video_send_format(res, *pp_format);
-     }
-   else
-     {
-        _e_video_get_available_formats(&formats, &count);
-        for (i = 0; i < count; i++)
-          tizen_video_send_format(res, formats[i]);
-     }
-}
-
-static Eina_List *video_hdlrs;
-
-static void
-_e_comp_wl_vbuf_print(void *data, const char *log_path)
-{
-   e_comp_wl_video_buffer_list_print(log_path);
-}
-
-static void
-_e_comp_wl_video_to_primary(void *data, const char *log_path)
-{
-   video_to_primary = !video_to_primary;
-}
-
-static void
-_e_comp_wl_video_punch(void *data, const char *log_path)
-{
-   video_punch = !video_punch;
-}
-
-EINTERN int
-e_comp_wl_video_init(void)
-{
-   e_comp->wl_comp_data->available_hw_accel.underlay = EINA_TRUE;
-   DBG("enable HW underlay");
-
-   e_comp->wl_comp_data->available_hw_accel.scaler = EINA_TRUE;
-   DBG("enable HW scaler");
-
-   if (!e_comp_wl) return 0;
-   if (!e_comp_wl->wl.disp) return 0;
-   if (e_comp->wl_comp_data->video.global) return 1;
-
-   e_info_server_hook_set("vbuf", _e_comp_wl_vbuf_print, NULL);
-   e_info_server_hook_set("video-to-primary", _e_comp_wl_video_to_primary, NULL);
-   e_info_server_hook_set("video-punch", _e_comp_wl_video_punch, NULL);
-
-   _video_detail_log_dom = eina_log_domain_register("e-comp-wl-video", EINA_COLOR_BLUE);
-   if (_video_detail_log_dom < 0)
-     {
-        ERR("Failed eina_log_domain_register()..!\n");
-        return 0;
-     }
-
-   /* try to add tizen_video to wayland globals */
-   e_comp->wl_comp_data->video.global =
-      wl_global_create(e_comp_wl->wl.disp, &tizen_video_interface, 1, NULL, _e_comp_wl_video_cb_bind);
-
-   if (!e_comp->wl_comp_data->video.global)
-     {
-        ERR("Could not add tizen_video to wayland globals");
-        return 0;
-     }
-
-   E_LIST_HANDLER_APPEND(video_hdlrs, E_EVENT_CLIENT_BUFFER_CHANGE,
-                         _e_video_cb_ec_buffer_change, NULL);
-   E_LIST_HANDLER_APPEND(video_hdlrs, E_EVENT_CLIENT_REMOVE,
-                         _e_video_cb_ec_remove, NULL);
-   E_LIST_HANDLER_APPEND(video_hdlrs, E_EVENT_CLIENT_SHOW,
-                         _e_video_cb_ec_client_show, NULL);
-   E_LIST_HANDLER_APPEND(video_hdlrs, E_EVENT_REMOTE_SURFACE_PROVIDER_VISIBILITY_CHANGE,
-                         _e_video_cb_ec_visibility_change, NULL);
-   E_LIST_HANDLER_APPEND(video_hdlrs, E_EVENT_CLIENT_VISIBILITY_CHANGE,
-                         _e_video_cb_topmost_ec_visibility_change, NULL);
-
-   return 1;
-}
-
-EINTERN void
-e_comp_wl_video_shutdown(void)
-{
-   e_comp->wl_comp_data->available_hw_accel.underlay = EINA_FALSE;
-   e_comp->wl_comp_data->available_hw_accel.scaler = EINA_FALSE;
-
-   E_FREE_FUNC(e_comp->wl_comp_data->video.global, wl_global_destroy);
-   E_FREE_LIST(video_hdlrs, ecore_event_handler_del);
-
-   e_info_server_hook_set("vbuf", NULL, NULL);
-   e_info_server_hook_set("video-dst-change", NULL, NULL);
-   e_info_server_hook_set("video-to-primary", NULL, NULL);
-   e_info_server_hook_set("video-punch", NULL, NULL);
-
-   eina_log_domain_unregister(_video_detail_log_dom);
-   _video_detail_log_dom = -1;
-}
-
-static tdm_layer *
-_e_video_tdm_video_layer_get(tdm_output *output)
-{
-   int i, count = 0;
-#ifdef CHECKING_PRIMARY_ZPOS
-   int primary_idx = 0, primary_zpos = 0;
-   tdm_layer *primary_layer;
-#endif
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
-
-   tdm_output_get_layer_count(output, &count);
-   for (i = 0; i < count; i++)
-     {
-        tdm_layer *layer = tdm_output_get_layer(output, i, NULL);
-        tdm_layer_capability capabilities = 0;
-        EINA_SAFETY_ON_NULL_RETURN_VAL(layer, NULL);
-
-        tdm_layer_get_capabilities(layer, &capabilities);
-        if (capabilities & TDM_LAYER_CAPABILITY_VIDEO)
-          return layer;
-     }
-
-#ifdef CHECKING_PRIMARY_ZPOS
-   tdm_output_get_primary_index(output, &primary_idx);
-   primary_layer = tdm_output_get_layer(output, primary_idx, NULL);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(primary_layer, NULL);
-   tdm_layer_get_zpos(primary_layer, &primary_zpos);
-#endif
-
-   for (i = 0; i < count; i++)
-     {
-        tdm_layer *layer = tdm_output_get_layer(output, i, NULL);
-        tdm_layer_capability capabilities = 0;
-        EINA_SAFETY_ON_NULL_RETURN_VAL(layer, NULL);
-
-        tdm_layer_get_capabilities(layer, &capabilities);
-        if (capabilities & TDM_LAYER_CAPABILITY_OVERLAY)
-          {
-#ifdef CHECKING_PRIMARY_ZPOS
-             int zpos = 0;
-             tdm_layer_get_zpos(layer, &zpos);
-             if (zpos >= primary_zpos) continue;
-#endif
-             return layer;
-          }
-     }
-
-   return NULL;
-}
-
-static tdm_layer *
-_e_video_tdm_available_video_layer_get(tdm_output *output)
-{
-   Eina_Bool has_video_layer = EINA_FALSE;
-   int i, count = 0;
-#ifdef CHECKING_PRIMARY_ZPOS
-   int primary_idx = 0, primary_zpos = 0;
-   tdm_layer *primary_layer;
-#endif
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
-
-   /* check video layers first */
-   tdm_output_get_layer_count(output, &count);
-   for (i = 0; i < count; i++)
-     {
-        tdm_layer *layer = tdm_output_get_layer(output, i, NULL);
-        tdm_layer_capability capabilities = 0;
-        EINA_SAFETY_ON_NULL_RETURN_VAL(layer, NULL);
-
-        tdm_layer_get_capabilities(layer, &capabilities);
-        if (capabilities & TDM_LAYER_CAPABILITY_VIDEO)
-          {
-             has_video_layer = EINA_TRUE;
-             if (!_e_video_tdm_get_layer_usable(layer)) continue;
-             return layer;
-          }
-     }
-
-   /* if a output has video layers, it means that there is no available video layer for video */
-   if (has_video_layer)
-     return NULL;
-
-   /* check graphic layers second */
-#ifdef CHECKING_PRIMARY_ZPOS
-   tdm_output_get_primary_index(output, &primary_idx);
-   primary_layer = tdm_output_get_layer(output, primary_idx, NULL);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(primary_layer, NULL);
-   tdm_layer_get_zpos(primary_layer, &primary_zpos);
-#endif
-
-   for (i = 0; i < count; i++)
-     {
-        tdm_layer *layer = tdm_output_get_layer(output, i, NULL);
-        tdm_layer_capability capabilities = 0;
-        EINA_SAFETY_ON_NULL_RETURN_VAL(layer, NULL);
-
-        tdm_layer_get_capabilities(layer, &capabilities);
-        if (capabilities & TDM_LAYER_CAPABILITY_OVERLAY)
-          {
-#ifdef CHECKING_PRIMARY_ZPOS
-             int zpos = 0;
-             tdm_layer_get_zpos(layer, &zpos);
-             if (zpos >= primary_zpos) continue;
-#endif
-             if (!_e_video_tdm_get_layer_usable(layer)) continue;
-             return layer;
-          }
-     }
-
-   return NULL;
-}
-
-static void
-_e_video_tdm_set_layer_usable(tdm_layer *layer, Eina_Bool usable)
-{
-   if (usable)
-     video_layers = eina_list_remove(video_layers, layer);
-   else
-     {
-        tdm_layer *used_layer;
-        Eina_List *l = NULL;
-        EINA_LIST_FOREACH(video_layers, l, used_layer)
-           if (used_layer == layer) return;
-        video_layers = eina_list_append(video_layers, layer);
-     }
-}
-
-static Eina_Bool
-_e_video_tdm_get_layer_usable(tdm_layer *layer)
-{
-   tdm_layer *used_layer;
-   Eina_List *l = NULL;
-   EINA_LIST_FOREACH(video_layers, l, used_layer)
-      if (used_layer == layer)
-        return EINA_FALSE;
-   return EINA_TRUE;
-}
diff --git a/src/bin/e_comp_wl_video.h b/src/bin/e_comp_wl_video.h
deleted file mode 100644 (file)
index ceedd5c..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifdef E_TYPEDEFS
-
-#else
-#ifndef E_COMP_WL_VIDEO_H
-#define E_COMP_WL_VIDEO_H
-
-#define E_COMP_WL
-
-typedef struct _E_Video E_Video;
-typedef struct _E_Video_Layer E_Video_Layer;
-typedef struct _E_Video_Info_Layer E_Video_Info_Layer;
-
-EINTERN int e_comp_wl_video_init(void);
-EINTERN void e_comp_wl_video_shutdown(void);
-
-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)
-#define ROUNDUP(s,c)        (((s) + (c-1)) & ~(c-1))
-
-#endif
-#endif
diff --git a/src/bin/e_comp_wl_video_buffer.c b/src/bin/e_comp_wl_video_buffer.c
deleted file mode 100644 (file)
index 20fd462..0000000
+++ /dev/null
@@ -1,966 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "e.h"
-#include <wayland-tbm-server.h>
-#include <sys/mman.h>
-#include <pixman.h>
-#include <tdm_helper.h>
-
-//#define DEBUG_LIFECYCLE
-
-#define BER(fmt,arg...)   ERR("%d: "fmt, vbuf ? vbuf->stamp : 0, ##arg)
-#define BWR(fmt,arg...)   WRN("%d: "fmt, vbuf ? vbuf->stamp : 0, ##arg)
-#define BIN(fmt,arg...)   INF("%d: "fmt, vbuf ? vbuf->stamp : 0, ##arg)
-#define BDB(fmt,arg...)   DBG("%d: "fmt, vbuf ? vbuf->stamp : 0, ##arg)
-
-#define VBUF_RETURN_IF_FAIL(cond) \
-   {if (!(cond)) { BER("'%s' failed", #cond); return; }}
-#define VBUF_RETURN_VAL_IF_FAIL(cond, val) \
-   {if (!(cond)) { BER("'%s' failed", #cond); return val; }}
-
-#ifdef DEBUG_LIFECYCLE
-#undef BDB
-#define BDB BIN
-#endif
-
-typedef struct _VBufFreeFuncInfo
-{
-   VBuf_Free_Func func;
-   void *data;
-} VBufFreeFuncInfo;
-
-static void _e_comp_wl_video_buffer_cb_destroy(struct wl_listener *listener, void *data);
-static void _e_comp_wl_video_buffer_free(E_Comp_Wl_Video_Buf *vbuf);
-#define e_comp_wl_video_buffer_free(b) _e_comp_wl_video_buffer_free(b)
-
-static Eina_List *vbuf_lists;
-
-static E_Comp_Wl_Video_Buf*
-_find_vbuf(uint stamp)
-{
-   E_Comp_Wl_Video_Buf *vbuf;
-   Eina_List *l;
-
-   if (!vbuf_lists)
-     return NULL;
-
-   EINA_LIST_FOREACH(vbuf_lists, l, vbuf)
-     {
-        if (vbuf->stamp == stamp)
-          return vbuf;
-     }
-
-   return NULL;
-}
-
-static Eina_Bool
-_e_comp_wl_video_buffer_access_data_begin(E_Comp_Wl_Video_Buf *vbuf)
-{
-   EINA_SAFETY_ON_NULL_RETURN_VAL(vbuf, EINA_FALSE);
-
-   vbuf->ptrs[0] = vbuf->ptrs[1] = vbuf->ptrs[2] = NULL;
-
-   if (vbuf->type == E_COMP_WL_VIDEO_BUF_TYPE_SHM)
-     {
-        struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get(vbuf->resource);
-        EINA_SAFETY_ON_NULL_RETURN_VAL(shm_buffer, EINA_FALSE);
-        vbuf->ptrs[0] = wl_shm_buffer_get_data(shm_buffer);
-        EINA_SAFETY_ON_NULL_RETURN_VAL(vbuf->ptrs[0], EINA_FALSE);
-        return EINA_TRUE;
-     }
-   else if (vbuf->type == E_COMP_WL_VIDEO_BUF_TYPE_TBM)
-     {
-        int i, j;
-        tbm_bo bos[4] = {0,};
-
-        for (i = 0; i < 3; i++)
-          {
-             tbm_bo_handle bo_handles;
-
-             bos[i] = tbm_surface_internal_get_bo(vbuf->tbm_surface, i);
-             if (!bos[i]) continue;
-
-             bo_handles = tbm_bo_map(bos[i], TBM_DEVICE_CPU, TBM_OPTION_READ);
-             if (!bo_handles.ptr)
-               {
-                  for (j = 0; j < i; j++)
-                    tbm_bo_unmap(bos[j]);
-                  return EINA_FALSE;
-               }
-
-             vbuf->ptrs[i] = bo_handles.ptr;
-          }
-
-        EINA_SAFETY_ON_NULL_RETURN_VAL(vbuf->ptrs[0], EINA_FALSE);
-
-        switch(vbuf->tbmfmt)
-          {
-           case TBM_FORMAT_YVU420:
-           case TBM_FORMAT_YUV420:
-              if (!vbuf->ptrs[1])
-                vbuf->ptrs[1] = vbuf->ptrs[0];
-              if (!vbuf->ptrs[2])
-                vbuf->ptrs[2] = vbuf->ptrs[1];
-              break;
-           case TBM_FORMAT_NV12:
-           case TBM_FORMAT_NV21:
-              if (!vbuf->ptrs[1])
-                vbuf->ptrs[1] = vbuf->ptrs[0];
-              break;
-           default:
-              break;
-          }
-
-        return EINA_TRUE;
-     }
-
-   return EINA_FALSE;
-}
-
-static void
-_e_comp_wl_video_buffer_access_data_end(E_Comp_Wl_Video_Buf *vbuf)
-{
-   EINA_SAFETY_ON_NULL_RETURN(vbuf);
-
-   if (vbuf->type == E_COMP_WL_VIDEO_BUF_TYPE_SHM)
-     {
-        vbuf->ptrs[0] = NULL;
-     }
-   else if (vbuf->type == E_COMP_WL_VIDEO_BUF_TYPE_TBM)
-     {
-        int i;
-        tbm_bo bos[4] = {0,};
-
-        for (i = 0; i < 3; i++)
-          {
-             bos[i] = tbm_surface_internal_get_bo(vbuf->tbm_surface, i);
-             if (!bos[i]) continue;
-
-             tbm_bo_unmap(bos[i]);
-             vbuf->ptrs[i] = NULL;
-          }
-     }
-}
-
-static E_Comp_Wl_Video_Buf*
-_e_comp_wl_video_buffer_create_res(struct wl_resource *resource)
-{
-   E_Comp_Wl_Video_Buf *vbuf = NULL;
-   struct wl_shm_buffer *shm_buffer;
-   tbm_surface_h tbm_surface;
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(resource, NULL);
-
-   vbuf = calloc(1, sizeof(E_Comp_Wl_Video_Buf));
-   EINA_SAFETY_ON_FALSE_GOTO(vbuf != NULL, create_fail);
-
-   vbuf->ref_cnt = 1;
-   vbuf->stamp = e_comp_wl_video_buffer_get_mills();
-   while (_find_vbuf(vbuf->stamp))
-     vbuf->stamp++;
-
-   vbuf->resource = resource;
-
-   if ((shm_buffer = wl_shm_buffer_get(resource)))
-     {
-        uint32_t tbmfmt = wl_shm_buffer_get_format(shm_buffer);
-
-        vbuf->type = E_COMP_WL_VIDEO_BUF_TYPE_SHM;
-
-        if (tbmfmt == WL_SHM_FORMAT_ARGB8888)
-          vbuf->tbmfmt = TBM_FORMAT_ARGB8888;
-        else if (tbmfmt == WL_SHM_FORMAT_XRGB8888)
-          vbuf->tbmfmt = TBM_FORMAT_XRGB8888;
-        else
-          vbuf->tbmfmt = tbmfmt;
-
-        vbuf->width = wl_shm_buffer_get_width(shm_buffer);
-        vbuf->height = wl_shm_buffer_get_height(shm_buffer);
-        vbuf->pitches[0] = wl_shm_buffer_get_stride(shm_buffer);
-
-        vbuf->width_from_pitch = vbuf->width;
-        vbuf->height_from_size = vbuf->height;;
-     }
-   else if ((tbm_surface = wayland_tbm_server_get_surface(e_comp->wl_comp_data->tbm.server, resource)))
-     {
-        int i;
-
-        vbuf->type = E_COMP_WL_VIDEO_BUF_TYPE_TBM;
-        vbuf->tbm_surface = tbm_surface;
-        tbm_surface_internal_ref(tbm_surface);
-
-        vbuf->tbmfmt = tbm_surface_get_format(tbm_surface);
-        vbuf->width = tbm_surface_get_width(tbm_surface);
-        vbuf->height = tbm_surface_get_height(tbm_surface);
-
-        /* NOTE Some format such a NVxx and a YUVxxx can have multiple handles */
-        for (i = 0; i < 3; i++)
-          {
-             uint32_t size = 0, offset = 0, pitch = 0;
-             tbm_bo bo;
-
-             bo = tbm_surface_internal_get_bo(tbm_surface, i);
-             if (bo)
-               {
-                  vbuf->handles[i] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32;
-                  EINA_SAFETY_ON_FALSE_GOTO(vbuf->handles[i] > 0, create_fail);
-
-                  vbuf->names[i] = tbm_bo_export(bo);
-                  EINA_SAFETY_ON_FALSE_GOTO(vbuf->names[i] > 0, create_fail);
-               }
-
-             tbm_surface_internal_get_plane_data(tbm_surface, i, &size, &offset, &pitch);
-             vbuf->pitches[i] = pitch;
-             vbuf->offsets[i] = offset;
-          }
-
-        tdm_helper_get_buffer_full_size(tbm_surface, &vbuf->width_from_pitch, &vbuf->height_from_size);
-     }
-   else
-     {
-        ERR("unknown buffer resource");
-        goto create_fail;
-     }
-
-   vbuf_lists = eina_list_append(vbuf_lists, vbuf);
-
-   BDB("type(%d) %dx%d(%dx%d), %c%c%c%c, name(%d,%d,%d) hnd(%d,%d,%d), pitch(%d,%d,%d), offset(%d,%d,%d)",
-       vbuf->type, vbuf->width_from_pitch, vbuf->height_from_size,
-       vbuf->width, vbuf->height, FOURCC_STR(vbuf->tbmfmt),
-       vbuf->names[0], vbuf->names[1], vbuf->names[2],
-       vbuf->handles[0], vbuf->handles[1], vbuf->handles[2],
-       vbuf->pitches[0], vbuf->pitches[1], vbuf->pitches[2],
-       vbuf->offsets[0], vbuf->offsets[1], vbuf->offsets[2]);
-
-   return vbuf;
-
-create_fail:
-   _e_comp_wl_video_buffer_free(vbuf);
-
-   return NULL;
-}
-
-EINTERN E_Comp_Wl_Video_Buf*
-e_comp_wl_video_buffer_create(struct wl_resource *resource)
-{
-   E_Comp_Wl_Video_Buf *vbuf = _e_comp_wl_video_buffer_create_res(resource);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(vbuf, NULL);
-
-   vbuf->destroy_listener.notify = _e_comp_wl_video_buffer_cb_destroy;
-   wl_resource_add_destroy_listener(resource, &vbuf->destroy_listener);
-
-   return vbuf;
-}
-
-EINTERN E_Comp_Wl_Video_Buf*
-e_comp_wl_video_buffer_create_comp(E_Comp_Wl_Buffer *comp_buffer)
-{
-   E_Comp_Wl_Video_Buf *vbuf;
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(comp_buffer, NULL);
-
-   vbuf = _e_comp_wl_video_buffer_create_res(comp_buffer->resource);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(vbuf, NULL);
-
-   vbuf->comp_buffer = comp_buffer;
-
-   vbuf->destroy_listener.notify = _e_comp_wl_video_buffer_cb_destroy;
-   wl_resource_add_destroy_listener(comp_buffer->resource, &vbuf->destroy_listener);
-
-   return vbuf;
-}
-
-EINTERN E_Comp_Wl_Video_Buf*
-e_comp_wl_video_buffer_create_tbm(tbm_surface_h tbm_surface)
-{
-   E_Comp_Wl_Video_Buf *vbuf;
-   int i;
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(tbm_surface, NULL);
-
-   vbuf = calloc(1, sizeof(E_Comp_Wl_Video_Buf));
-   EINA_SAFETY_ON_FALSE_GOTO(vbuf != NULL, create_fail);
-
-   vbuf->ref_cnt = 1;
-   vbuf->stamp = e_comp_wl_video_buffer_get_mills();
-   while (_find_vbuf(vbuf->stamp))
-     vbuf->stamp++;
-
-   vbuf->type = E_COMP_WL_VIDEO_BUF_TYPE_TBM;
-   vbuf->tbm_surface = tbm_surface;
-   tbm_surface_internal_ref(tbm_surface);
-
-   vbuf->tbmfmt = tbm_surface_get_format(tbm_surface);
-   vbuf->width = tbm_surface_get_width(tbm_surface);
-   vbuf->height = tbm_surface_get_height(tbm_surface);
-
-   for (i = 0; i < 3; i++)
-     {
-        uint32_t size = 0, offset = 0, pitch = 0;
-        tbm_bo bo;
-
-        bo = tbm_surface_internal_get_bo(tbm_surface, i);
-        if (bo)
-          {
-             vbuf->handles[i] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32;
-             EINA_SAFETY_ON_FALSE_GOTO(vbuf->handles[i] > 0, create_fail);
-
-             vbuf->names[i] = tbm_bo_export(bo);
-             EINA_SAFETY_ON_FALSE_GOTO(vbuf->names[i] > 0, create_fail);
-          }
-
-        tbm_surface_internal_get_plane_data(tbm_surface, i, &size, &offset, &pitch);
-        vbuf->pitches[i] = pitch;
-        vbuf->offsets[i] = offset;
-     }
-
-   tdm_helper_get_buffer_full_size(tbm_surface, &vbuf->width_from_pitch, &vbuf->height_from_size);
-
-   vbuf_lists = eina_list_append(vbuf_lists, vbuf);
-
-   BDB("type(%d) %dx%d(%dx%d), %c%c%c%c, name(%d,%d,%d) hnd(%d,%d,%d), pitch(%d,%d,%d), offset(%d,%d,%d)",
-       vbuf->type, vbuf->width_from_pitch, vbuf->height_from_size,
-       vbuf->width, vbuf->height, FOURCC_STR(vbuf->tbmfmt),
-       vbuf->names[0], vbuf->names[1], vbuf->names[2],
-       vbuf->handles[0], vbuf->handles[1], vbuf->handles[2],
-       vbuf->pitches[0], vbuf->pitches[1], vbuf->pitches[2],
-       vbuf->offsets[0], vbuf->offsets[1], vbuf->offsets[2]);
-
-   return vbuf;
-
-create_fail:
-   _e_comp_wl_video_buffer_free(vbuf);
-
-   return NULL;
-}
-
-EINTERN E_Comp_Wl_Video_Buf*
-e_comp_wl_video_buffer_alloc(int width, int height, tbm_format tbmfmt, Eina_Bool scanout)
-{
-   E_Comp_Wl_Video_Buf *vbuf = NULL;
-   tbm_surface_h tbm_surface = NULL;
-   int i;
-
-   EINA_SAFETY_ON_FALSE_RETURN_VAL(width > 0, NULL);
-   EINA_SAFETY_ON_FALSE_RETURN_VAL(height > 0, NULL);
-
-   vbuf = calloc(1, sizeof(E_Comp_Wl_Video_Buf));
-   EINA_SAFETY_ON_FALSE_GOTO(vbuf != NULL, alloc_fail);
-
-   vbuf->ref_cnt = 1;
-   vbuf->stamp = e_comp_wl_video_buffer_get_mills();
-   while (_find_vbuf(vbuf->stamp))
-     vbuf->stamp++;
-
-   if (scanout)
-     tbm_surface = tbm_surface_internal_create_with_flags(width, height, tbmfmt, TBM_BO_SCANOUT);
-   else
-     tbm_surface = tbm_surface_internal_create_with_flags(width, height, tbmfmt, TBM_BO_DEFAULT);
-   EINA_SAFETY_ON_NULL_GOTO(tbm_surface, alloc_fail);
-
-   vbuf->type = E_COMP_WL_VIDEO_BUF_TYPE_TBM;
-   vbuf->tbm_surface = tbm_surface;
-   tbm_surface_internal_ref(tbm_surface);
-
-   vbuf->tbmfmt = tbmfmt;
-   vbuf->width = width;
-   vbuf->height = height;
-
-   for (i = 0; i < 3; i++)
-     {
-        uint32_t size = 0, offset = 0, pitch = 0;
-        tbm_bo bo;
-
-        bo = tbm_surface_internal_get_bo(tbm_surface, i);
-        if (bo)
-          {
-             vbuf->handles[i] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32;
-             EINA_SAFETY_ON_FALSE_GOTO(vbuf->handles[i] > 0, alloc_fail);
-
-             vbuf->names[i] = tbm_bo_export(bo);
-             EINA_SAFETY_ON_FALSE_GOTO(vbuf->names[i] > 0, alloc_fail);
-          }
-
-        tbm_surface_internal_get_plane_data(tbm_surface, i, &size, &offset, &pitch);
-        vbuf->pitches[i] = pitch;
-        vbuf->offsets[i] = offset;
-     }
-
-   tdm_helper_get_buffer_full_size(tbm_surface, &vbuf->width_from_pitch, &vbuf->height_from_size);
-
-   tbm_surface_internal_unref(tbm_surface);
-
-   vbuf_lists = eina_list_append(vbuf_lists, vbuf);
-
-   BDB("type(%d) %dx%d(%dx%d) %c%c%c%c nm(%d,%d,%d) hnd(%d,%d,%d) pitch(%d,%d,%d) offset(%d,%d,%d)",
-       vbuf->type, vbuf->width_from_pitch, vbuf->height_from_size,
-       vbuf->width, vbuf->height, FOURCC_STR(vbuf->tbmfmt),
-       vbuf->names[0], vbuf->names[1], vbuf->names[2],
-       vbuf->handles[0], vbuf->handles[1], vbuf->handles[2],
-       vbuf->pitches[0], vbuf->pitches[1], vbuf->pitches[2],
-       vbuf->offsets[0], vbuf->offsets[1], vbuf->offsets[2]);
-
-   return vbuf;
-
-alloc_fail:
-   if (tbm_surface)
-     tbm_surface_internal_unref(tbm_surface);
-   _e_comp_wl_video_buffer_free(vbuf);
-   return NULL;
-}
-
-EINTERN E_Comp_Wl_Video_Buf*
-e_comp_wl_video_buffer_ref(E_Comp_Wl_Video_Buf *vbuf)
-{
-   if (!vbuf)
-     return NULL;
-
-   EINA_SAFETY_ON_FALSE_RETURN_VAL(VBUF_IS_VALID(vbuf), NULL);
-
-   vbuf->ref_cnt++;
-   BDB("count(%d) ref", vbuf->ref_cnt);
-
-   return vbuf;
-}
-
-EINTERN void
-e_comp_wl_video_buffer_unref(E_Comp_Wl_Video_Buf *vbuf)
-{
-   if (!vbuf)
-     return;
-
-   VBUF_RETURN_IF_FAIL(e_comp_wl_video_buffer_valid(vbuf));
-
-   vbuf->ref_cnt--;
-   BDB("count(%d) unref", vbuf->ref_cnt);
-
-   if (!vbuf->buffer_destroying && vbuf->ref_cnt == 0)
-     _e_comp_wl_video_buffer_free(vbuf);
-}
-
-static void
-_e_comp_wl_video_buffer_free(E_Comp_Wl_Video_Buf *vbuf)
-{
-   VBufFreeFuncInfo *info;
-   Eina_List *l, *ll;
-
-   if (!vbuf)
-     return;
-
-   VBUF_RETURN_IF_FAIL(e_comp_wl_video_buffer_valid(vbuf));
-
-   BDB("vbuf(%p) tbm_surface(%p) freed", vbuf, vbuf->tbm_surface);
-
-   vbuf->buffer_destroying = EINA_TRUE;
-
-   if (vbuf->destroy_listener.notify)
-     {
-        wl_list_remove(&vbuf->destroy_listener.link);
-        vbuf->destroy_listener.notify = NULL;
-     }
-
-   EINA_LIST_FOREACH_SAFE(vbuf->free_funcs, l, ll, info)
-     {
-        /* call before tmb_bo_unref */
-        vbuf->free_funcs = eina_list_remove_list(vbuf->free_funcs, l);
-        if (info->func)
-          info->func(vbuf, info->data);
-        free(info);
-     }
-
-#if 0
-   /* DO not check ref_count here. Even if ref_count is not 0, vbuf can be
-    * be destroyed by wl_buffer_destroy forcely. video or screenmirror should add
-    * the vbuf free function and handle the destroying vbuf situation.
-    */
-   if (!vbuf->buffer_destroying)
-     VBUF_RETURN_IF_FAIL(vbuf->ref_cnt == 0);
-#endif
-
-   /* make sure all operation is done */
-   VBUF_RETURN_IF_FAIL(vbuf->in_use == EINA_FALSE);
-
-   if (vbuf->type == E_COMP_WL_VIDEO_BUF_TYPE_TBM && vbuf->tbm_surface)
-     {
-        tbm_surface_internal_unref(vbuf->tbm_surface);
-        vbuf->tbm_surface = NULL;
-     }
-
-   vbuf_lists = eina_list_remove(vbuf_lists, vbuf);
-
-   vbuf->stamp = 0;
-
-   free(vbuf);
-}
-
-static void
-_e_comp_wl_video_buffer_cb_destroy(struct wl_listener *listener, void *data)
-{
-   E_Comp_Wl_Video_Buf *vbuf = container_of(listener, E_Comp_Wl_Video_Buf, destroy_listener);
-
-   if (!vbuf) return;
-
-   vbuf->comp_buffer = NULL;
-
-   if (vbuf->buffer_destroying == EINA_FALSE)
-     {
-        vbuf->destroy_listener.notify = NULL;
-        _e_comp_wl_video_buffer_free(vbuf);
-     }
-}
-
-EINTERN void
-e_comp_wl_video_buffer_clear(E_Comp_Wl_Video_Buf *vbuf)
-{
-   EINA_SAFETY_ON_NULL_RETURN(vbuf);
-
-   if (!_e_comp_wl_video_buffer_access_data_begin(vbuf))
-     {
-        BER("can't access ptr");
-        return;
-     }
-
-   switch(vbuf->tbmfmt)
-     {
-      case TBM_FORMAT_ARGB8888:
-      case TBM_FORMAT_XRGB8888:
-         memset(vbuf->ptrs[0], 0, vbuf->pitches[0] * vbuf->height);
-         break;
-      case TBM_FORMAT_YVU420:
-      case TBM_FORMAT_YUV420:
-         memset((char*)vbuf->ptrs[0] + vbuf->offsets[0], 0x10, vbuf->pitches[0] * vbuf->height);
-         memset((char*)vbuf->ptrs[1] + vbuf->offsets[1], 0x80, vbuf->pitches[1] * (vbuf->height >> 1));
-         memset((char*)vbuf->ptrs[2] + vbuf->offsets[2], 0x80, vbuf->pitches[2] * (vbuf->height >> 1));
-         break;
-      case TBM_FORMAT_NV12:
-      case TBM_FORMAT_NV21:
-         memset((char*)vbuf->ptrs[0] + vbuf->offsets[0], 0x10, vbuf->pitches[0] * vbuf->height);
-         memset((char*)vbuf->ptrs[1] + vbuf->offsets[1], 0x80, vbuf->pitches[1] * (vbuf->height >> 1));
-         break;
-      case TBM_FORMAT_YUYV:
-           {
-              int *ibuf = (int*)vbuf->ptrs[0];
-              int i, size = vbuf->pitches[0] * vbuf->height / 4;
-
-              for (i = 0 ; i < size ; i++)
-                ibuf[i] = 0x10801080;
-           }
-         break;
-      case TBM_FORMAT_UYVY:
-           {
-              int *ibuf = (int*)vbuf->ptrs[0];
-              int i, size = vbuf->pitches[0] * vbuf->height / 4;
-
-              for (i = 0 ; i < size ; i++)
-                ibuf[i] = 0x80108010; /* YUYV -> 0xVYUY */
-           }
-         break;
-      default:
-         BWR("can't clear %c%c%c%c buffer", FOURCC_STR(vbuf->tbmfmt));
-         break;
-     }
-
-   _e_comp_wl_video_buffer_access_data_end(vbuf);
-}
-
-EINTERN Eina_Bool
-e_comp_wl_video_buffer_valid(E_Comp_Wl_Video_Buf *vbuf)
-{
-   E_Comp_Wl_Video_Buf *temp;
-   Eina_List *l;
-
-   VBUF_RETURN_VAL_IF_FAIL(vbuf != NULL, EINA_FALSE);
-   VBUF_RETURN_VAL_IF_FAIL(vbuf->stamp != 0, EINA_FALSE);
-
-   EINA_LIST_FOREACH(vbuf_lists, l, temp)
-     {
-        if (temp->stamp == vbuf->stamp)
-          return EINA_TRUE;
-     }
-
-   BDB("vbuf(%p) invalid", vbuf);
-
-   return EINA_FALSE;
-}
-
-static VBufFreeFuncInfo*
-_e_comp_wl_video_buffer_free_func_find(E_Comp_Wl_Video_Buf *vbuf, VBuf_Free_Func func, void *data)
-{
-   VBufFreeFuncInfo *info;
-   Eina_List *l;
-
-   EINA_LIST_FOREACH(vbuf->free_funcs, l, info)
-     {
-        if (info->func == func && info->data == data)
-          return info;
-     }
-
-   return NULL;
-}
-
-EINTERN void
-e_comp_wl_video_buffer_free_func_add(E_Comp_Wl_Video_Buf *vbuf, VBuf_Free_Func func, void *data)
-{
-   VBufFreeFuncInfo *info;
-
-   EINA_SAFETY_ON_FALSE_RETURN(VBUF_IS_VALID(vbuf));
-   EINA_SAFETY_ON_NULL_RETURN(func);
-
-   info = _e_comp_wl_video_buffer_free_func_find(vbuf, func, data);
-   if (info)
-     return;
-
-   info = calloc(1, sizeof(VBufFreeFuncInfo));
-   EINA_SAFETY_ON_NULL_RETURN(info);
-
-   info->func = func;
-   info->data = data;
-
-   vbuf->free_funcs = eina_list_append(vbuf->free_funcs, info);
-}
-
-EINTERN void
-e_comp_wl_video_buffer_free_func_del(E_Comp_Wl_Video_Buf *vbuf, VBuf_Free_Func func, void *data)
-{
-   VBufFreeFuncInfo *info;
-
-   EINA_SAFETY_ON_FALSE_RETURN(VBUF_IS_VALID(vbuf));
-   EINA_SAFETY_ON_NULL_RETURN(func);
-
-   info = _e_comp_wl_video_buffer_free_func_find(vbuf, func, data);
-   if (!info)
-     return;
-
-   vbuf->free_funcs = eina_list_remove(vbuf->free_funcs, info);
-
-   free(info);
-}
-
-static pixman_format_code_t
-_e_comp_wl_video_buffer_pixman_format_get(E_Comp_Wl_Video_Buf *vbuf)
-{
-   switch(vbuf->tbmfmt)
-     {
-      case TBM_FORMAT_ARGB8888: return PIXMAN_a8r8g8b8;
-      case TBM_FORMAT_XRGB8888: return PIXMAN_x8r8g8b8;
-      default:                  return 0;
-     }
-   return 0;
-}
-
-EINTERN void
-e_comp_wl_video_buffer_convert(E_Comp_Wl_Video_Buf *srcbuf, E_Comp_Wl_Video_Buf *dstbuf,
-                               int sx, int sy, int sw, int sh,
-                               int dx, int dy, int dw, int dh,
-                               Eina_Bool over, int rotate, int hflip, int vflip)
-{
-   pixman_image_t *src_img = NULL, *dst_img = NULL;
-   pixman_format_code_t src_format, dst_format;
-   double scale_x, scale_y;
-   int rotate_step;
-   pixman_transform_t t;
-   struct pixman_f_transform ft;
-   pixman_op_t op;
-   int src_stride, dst_stride;
-   int buf_width;
-
-   EINA_SAFETY_ON_FALSE_RETURN(VBUF_IS_VALID(srcbuf));
-   EINA_SAFETY_ON_FALSE_RETURN(VBUF_IS_VALID(dstbuf));
-
-   if (!_e_comp_wl_video_buffer_access_data_begin(srcbuf))
-     return;
-   if (!_e_comp_wl_video_buffer_access_data_begin(dstbuf))
-     {
-        _e_comp_wl_video_buffer_access_data_end(srcbuf);
-        return;
-     }
-
-   /* not handle buffers which have 2 more gem handles */
-   EINA_SAFETY_ON_NULL_GOTO(srcbuf->ptrs[0], cant_convert);
-   EINA_SAFETY_ON_NULL_GOTO(dstbuf->ptrs[0], cant_convert);
-   EINA_SAFETY_ON_FALSE_RETURN(!srcbuf->ptrs[1]);
-   EINA_SAFETY_ON_FALSE_RETURN(!dstbuf->ptrs[1]);
-
-   src_format = _e_comp_wl_video_buffer_pixman_format_get(srcbuf);
-   EINA_SAFETY_ON_FALSE_GOTO(src_format > 0, cant_convert);
-   dst_format = _e_comp_wl_video_buffer_pixman_format_get(dstbuf);
-   EINA_SAFETY_ON_FALSE_GOTO(dst_format > 0, cant_convert);
-
-   buf_width = IS_RGB(srcbuf->tbmfmt)?(srcbuf->pitches[0]/4):srcbuf->pitches[0];
-   src_stride = IS_RGB(srcbuf->tbmfmt)?(srcbuf->pitches[0]):buf_width * (PIXMAN_FORMAT_BPP(src_format) / 8);
-   src_img = pixman_image_create_bits(src_format, buf_width, srcbuf->height,
-                                      (uint32_t*)srcbuf->ptrs[0], src_stride);
-   EINA_SAFETY_ON_NULL_GOTO(src_img, cant_convert);
-
-   buf_width = IS_RGB(dstbuf->tbmfmt)?(dstbuf->pitches[0]/4):dstbuf->pitches[0];
-   dst_stride = IS_RGB(srcbuf->tbmfmt)?(dstbuf->pitches[0]):buf_width * (PIXMAN_FORMAT_BPP(dst_format) / 8);
-   dst_img = pixman_image_create_bits(dst_format, buf_width, dstbuf->height,
-                                      (uint32_t*)dstbuf->ptrs[0], dst_stride);
-   EINA_SAFETY_ON_NULL_GOTO(dst_img, cant_convert);
-
-   pixman_f_transform_init_identity(&ft);
-
-   if (hflip)
-     {
-        pixman_f_transform_scale(&ft, NULL, -1, 1);
-        pixman_f_transform_translate(&ft, NULL, dw, 0);
-     }
-
-   if (vflip)
-     {
-        pixman_f_transform_scale(&ft, NULL, 1, -1);
-        pixman_f_transform_translate(&ft, NULL, 0, dh);
-     }
-
-   rotate_step = (rotate + 360) / 90 % 4;
-   if (rotate_step > 0)
-     {
-        int c, s, tx = 0, ty = 0;
-        switch (rotate_step)
-          {
-           case 1:
-              c = 0, s = -1, tx = -dw;
-              break;
-           case 2:
-              c = -1, s = 0, tx = -dw, ty = -dh;
-              break;
-           case 3:
-              c = 0, s = 1, ty = -dh;
-              break;
-          }
-        pixman_f_transform_translate(&ft, NULL, tx, ty);
-        pixman_f_transform_rotate(&ft, NULL, c, s);
-     }
-
-   if (rotate_step % 2 == 0)
-     {
-        scale_x = (double)sw / dw;
-        scale_y = (double)sh / dh;
-     }
-   else
-     {
-        scale_x = (double)sw / dh;
-        scale_y = (double)sh / dw;
-     }
-
-   pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
-   pixman_f_transform_translate(&ft, NULL, sx, sy);
-   pixman_transform_from_pixman_f_transform(&t, &ft);
-   pixman_image_set_transform(src_img, &t);
-
-   if (!over) op = PIXMAN_OP_SRC;
-   else op = PIXMAN_OP_OVER;
-
-   pixman_image_composite(op, src_img, NULL, dst_img, 0, 0, 0, 0,
-                          dx, dy, dw, dh);
-cant_convert:
-   if (src_img) pixman_image_unref(src_img);
-   if (dst_img) pixman_image_unref(dst_img);
-
-   _e_comp_wl_video_buffer_access_data_end(srcbuf);
-   _e_comp_wl_video_buffer_access_data_end(dstbuf);
-}
-
-EINTERN Eina_Bool
-e_comp_wl_video_buffer_copy(E_Comp_Wl_Video_Buf *srcbuf, E_Comp_Wl_Video_Buf *dstbuf)
-{
-   int i, j, c_height;
-   unsigned char *s, *d;
-
-   EINA_SAFETY_ON_FALSE_RETURN_VAL(VBUF_IS_VALID(srcbuf), EINA_FALSE);
-   EINA_SAFETY_ON_FALSE_RETURN_VAL(VBUF_IS_VALID(dstbuf), EINA_FALSE);
-
-   if (!_e_comp_wl_video_buffer_access_data_begin(srcbuf))
-     return EINA_FALSE;
-   if (!_e_comp_wl_video_buffer_access_data_begin(dstbuf))
-     {
-        _e_comp_wl_video_buffer_access_data_end(srcbuf);
-        return EINA_FALSE;
-     }
-
-   switch (srcbuf->tbmfmt)
-     {
-      case TBM_FORMAT_ARGB8888:
-      case TBM_FORMAT_XRGB8888:
-      case TBM_FORMAT_YUV422:
-      case TBM_FORMAT_YVU422:
-         s = (unsigned char*)srcbuf->ptrs[0];
-         d = (unsigned char*)dstbuf->ptrs[0];
-         for (i = 0; i < srcbuf->height; i++)
-           {
-              memcpy(d, s, srcbuf->pitches[0]);
-              s += srcbuf->pitches[0];
-              d += dstbuf->pitches[0];
-           }
-         break;
-      case TBM_FORMAT_YUV420:
-      case TBM_FORMAT_YVU420:
-         for (i = 0; i < 3; i++)
-           {
-              s = (unsigned char*)srcbuf->ptrs[i] + srcbuf->offsets[i];
-              d = (unsigned char*)dstbuf->ptrs[i] + dstbuf->offsets[i];
-              c_height = (i == 0) ? srcbuf->height : srcbuf->height / 2;
-              for (j = 0; j < c_height; j++)
-                {
-                   memcpy(d, s, srcbuf->pitches[i]);
-                   s += srcbuf->pitches[i];
-                   d += dstbuf->pitches[i];
-                }
-           }
-         break;
-      case TBM_FORMAT_NV12:
-      case TBM_FORMAT_NV21:
-         for (i = 0; i < 2; i++)
-           {
-              s = (unsigned char*)srcbuf->ptrs[i] + srcbuf->offsets[i];
-              d = (unsigned char*)dstbuf->ptrs[i] + dstbuf->offsets[i];
-              c_height = (i == 0) ? srcbuf->height : srcbuf->height / 2;
-              for (j = 0; j < c_height; j++)
-                {
-                   memcpy(d, s, srcbuf->pitches[i]);
-                   s += srcbuf->pitches[i];
-                   d += dstbuf->pitches[i];
-                }
-           }
-         break;
-      default:
-         ERR("not implemented for %c%c%c%c", FOURCC_STR(srcbuf->tbmfmt));
-         _e_comp_wl_video_buffer_access_data_end(srcbuf);
-         _e_comp_wl_video_buffer_access_data_end(dstbuf);
-
-         return EINA_FALSE;
-     }
-
-   _e_comp_wl_video_buffer_access_data_end(srcbuf);
-   _e_comp_wl_video_buffer_access_data_end(dstbuf);
-
-   return EINA_TRUE;
-}
-
-EINTERN uint
-e_comp_wl_video_buffer_get_mills(void)
-{
-   struct timespec tp;
-
-   clock_gettime(CLOCK_MONOTONIC, &tp);
-
-   return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
-}
-
-EINTERN int
-e_comp_wl_video_buffer_list_length(void)
-{
-   return eina_list_count(vbuf_lists);
-}
-
-EINTERN void
-e_comp_wl_video_buffer_list_print(const char *log_path)
-{
-   E_Comp_Wl_Video_Buf *vbuf;
-   Eina_List *l;
-   FILE *log_fl;
-
-   log_fl = fopen(log_path, "a");
-   if (!log_fl)
-     {
-        ERR("failed: open file(%s)", log_path);
-        return;
-     }
-
-   setvbuf(log_fl, NULL, _IOLBF, 512);
-
-   fprintf(log_fl, "* Video Buffers:\n");
-   fprintf(log_fl, "stamp\tsize\tformat\thandles\tpitches\toffsets\tin_use\n");
-   EINA_LIST_FOREACH(vbuf_lists, l, vbuf)
-     {
-        fprintf(log_fl, "%d\t%dx%d\t%c%c%c%c\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d\t%d\n",
-                vbuf->stamp, vbuf->width, vbuf->height, FOURCC_STR(vbuf->tbmfmt),
-                vbuf->handles[0], vbuf->handles[1], vbuf->handles[2],
-                vbuf->pitches[0], vbuf->pitches[1], vbuf->pitches[2],
-                vbuf->offsets[0], vbuf->offsets[1], vbuf->offsets[2],
-                vbuf->in_use);
-     }
-
-   fclose(log_fl);
-}
-
-EINTERN void
-e_comp_wl_video_buffer_size_get(E_Client *ec, int *bw, int *bh)
-{
-   E_Comp_Wl_Buffer *buffer = e_pixmap_resource_get(ec->pixmap);
-
-   if (bw) *bw = 0;
-   if (bh) *bh = 0;
-
-   if (!buffer)
-     {
-        INF("no buffer. using ec(%p) size(%dx%d)", ec, ec->w, ec->h);
-        if (bw) *bw = ec->w;
-        if (bh) *bh = ec->h;
-        return;
-     }
-
-   if (buffer->type == E_COMP_WL_BUFFER_TYPE_VIDEO)
-     {
-        tbm_surface_h tbm_surface = wayland_tbm_server_get_surface(NULL, buffer->resource);
-
-        if (bw) *bw = tbm_surface_get_width(tbm_surface);
-        if (bh) *bh = tbm_surface_get_height(tbm_surface);
-     }
-   else
-     {
-        if (bw) *bw = buffer->w;
-        if (bh) *bh = buffer->h;
-     }
-}
-
-EINTERN void
-e_comp_wl_video_buffer_transform_scale_size_get(E_Client *ec, int *bw, int *bh)
-{
-   E_Comp_Wl_Buffer *buffer = e_pixmap_resource_get(ec->pixmap);
-   E_Comp_Wl_Buffer_Viewport *vp = &ec->comp_data->scaler.buffer_viewport;
-   int w, h, transform;
-
-   if (bw) *bw = 0;
-   if (bh) *bh = 0;
-
-   if (!buffer)
-     {
-        INF("no buffer. using ec(%p) size(%dx%d)", ec, ec->w, ec->h);
-        if (bw) *bw = ec->w;
-        if (bh) *bh = ec->h;
-        return;
-     }
-
-   if (buffer->type == E_COMP_WL_BUFFER_TYPE_VIDEO)
-     {
-        tbm_surface_h tbm_surface = wayland_tbm_server_get_surface(NULL, buffer->resource);
-
-        w = tbm_surface_get_width(tbm_surface);
-        h = tbm_surface_get_height(tbm_surface);
-     }
-   else
-     {
-        w = buffer->w;
-        h = buffer->h;
-     }
-
-   transform = e_comp_wl_output_buffer_transform_get(ec);
-
-   switch (transform)
-     {
-      case WL_OUTPUT_TRANSFORM_90:
-      case WL_OUTPUT_TRANSFORM_270:
-      case WL_OUTPUT_TRANSFORM_FLIPPED_90:
-      case WL_OUTPUT_TRANSFORM_FLIPPED_270:
-         if (bw) *bw = h / vp->buffer.scale;
-         if (bh) *bh = w / vp->buffer.scale;
-         break;
-      default:
-         if (bw) *bw = w / vp->buffer.scale;
-         if (bh) *bh = h / vp->buffer.scale;
-         break;
-     }
-}
diff --git a/src/bin/e_comp_wl_video_buffer.h b/src/bin/e_comp_wl_video_buffer.h
deleted file mode 100644 (file)
index c2d980e..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-#ifdef E_TYPEDEFS
-
-typedef enum _E_Comp_Wl_Video_Buf_Type
-{
-   E_COMP_WL_VIDEO_BUF_TYPE_SHM,
-   E_COMP_WL_VIDEO_BUF_TYPE_TBM,
-} E_Comp_Wl_Video_Buf_Type;
-
-typedef struct _E_Comp_Wl_Video_Buf E_Comp_Wl_Video_Buf;
-
-#else
-#ifndef E_COMP_WL_VIDEO_BUFFER_H
-#define E_COMP_WL_VIDEO_BUFFER_H
-
-#include "e_comp_wl_tbm.h"
-
-struct _E_Comp_Wl_Video_Buf
-{
-   /* to manage lifecycle */
-   uint ref_cnt;
-
-   /* to check valid */
-   uint stamp;
-
-   /* to manage wl_resource */
-   struct wl_resource *resource;
-   struct wl_listener destroy_listener;
-
-   Eina_Bool buffer_destroying;
-
-   E_Comp_Wl_Video_Buf_Type type;
-   tbm_surface_h tbm_surface;
-
-   /* pitch contains the full buffer width.
-    * width indicates the content area width.
-    */
-   tbm_format tbmfmt;
-   int width;
-   int height;
-   uint handles[4];
-   uint pitches[4];
-   uint offsets[4];
-   int names[4];
-   void *ptrs[4];
-
-   int width_from_pitch;
-   int height_from_size;
-
-   /* to avoid reading & write at same time */
-   Eina_Bool in_use;
-
-   Eina_List *free_funcs;
-
-   /* for wl_buffer.release event */
-   E_Comp_Wl_Buffer *comp_buffer;
-   E_Comp_Wl_Buffer_Ref buffer_ref;
-   Eina_Rectangle content_r;        /* content rect */
-   unsigned int content_t;          /* content transform */
-};
-
-EINTERN E_Comp_Wl_Video_Buf* e_comp_wl_video_buffer_create(struct wl_resource *resource);
-EINTERN E_Comp_Wl_Video_Buf* e_comp_wl_video_buffer_create_comp(E_Comp_Wl_Buffer *comp_buffer);
-EINTERN E_Comp_Wl_Video_Buf* e_comp_wl_video_buffer_create_tbm(tbm_surface_h tbm_surface);
-EINTERN E_Comp_Wl_Video_Buf* e_comp_wl_video_buffer_alloc(int width, int height, tbm_format tbmfmt, Eina_Bool scanout);
-EINTERN E_Comp_Wl_Video_Buf* e_comp_wl_video_buffer_ref(E_Comp_Wl_Video_Buf *vbuf);
-EINTERN void          e_comp_wl_video_buffer_unref(E_Comp_Wl_Video_Buf *vbuf);
-EINTERN Eina_Bool     e_comp_wl_video_buffer_valid(E_Comp_Wl_Video_Buf *vbuf);
-
-#define VBUF_IS_VALID(b)   e_comp_wl_video_buffer_valid(b)
-#define MSTAMP(b)          ((b)?(b)->stamp:0)
-
-#define e_comp_wl_video_buffer_set_use(b, v)    \
-   do { \
-      if (b) b->in_use = v; \
-   } while (0)
-
-typedef void (*VBuf_Free_Func) (E_Comp_Wl_Video_Buf *vbuf, void *data);
-EINTERN void e_comp_wl_video_buffer_free_func_add(E_Comp_Wl_Video_Buf *vbuf, VBuf_Free_Func func, void *data);
-EINTERN void e_comp_wl_video_buffer_free_func_del(E_Comp_Wl_Video_Buf *vbuf, VBuf_Free_Func func, void *data);
-
-EINTERN void e_comp_wl_video_buffer_clear(E_Comp_Wl_Video_Buf *vbuf);
-EINTERN Eina_Bool e_comp_wl_video_buffer_copy(E_Comp_Wl_Video_Buf *srcbuf, E_Comp_Wl_Video_Buf *dstbuf);
-EINTERN void e_comp_wl_video_buffer_convert(E_Comp_Wl_Video_Buf *srcbuf, E_Comp_Wl_Video_Buf *dstbuf,
-                                            int sx, int sy, int sw, int sh,
-                                            int dx, int dy, int dw, int dh,
-                                            Eina_Bool over, int rotate, int hflip, int vflip);
-
-EINTERN uint e_comp_wl_video_buffer_get_mills(void);
-EINTERN int  e_comp_wl_video_buffer_list_length(void);
-EINTERN void e_comp_wl_video_buffer_list_print(const char *log_path);
-
-EINTERN void e_comp_wl_video_buffer_size_get(E_Client *ec, int *bw, int *bh);
-EINTERN void e_comp_wl_video_buffer_transform_scale_size_get(E_Client *ec, int *bw, int *bh);
-
-#endif
-#endif
index 939754e29ad32f6735a489771db37dae509b3798..9ac2e82a6db969c96e4221047c87c4ae0c890e3a 100644 (file)
@@ -65,8 +65,6 @@
 #endif
 #include "e_comp_wl_rsm.h"
 #include "e_comp_wl_screenshooter.h"
-#include "e_comp_wl_video.h"
-#include "e_comp_wl_video_buffer.h"
 #include "e_comp_wl_viewport.h"
 #include "e_comp_wl_shell.h"
 #include "e_policy.h"
@@ -84,3 +82,9 @@
 #include "e_dbus_conn.h"
 #include "e_xdg_shell_v6.h"
 #include "e_devicemgr.h"
+
+#include "video/e_video_debug.h"
+#include "video/e_client_video.h"
+#include "video/e_zone_video.h"
+#include "video/e_comp_wl_video.h"
+#include "video/e_comp_wl_video_buffer.h"
diff --git a/src/bin/video/e_client_video.c b/src/bin/video/e_client_video.c
new file mode 100644 (file)
index 0000000..04f1586
--- /dev/null
@@ -0,0 +1,341 @@
+#include "e_video_internal.h"
+
+#define EO_DATA_KEY  "E_Client_Video"
+
+#define INTERNAL_DATA_GET                             \
+   E_Client_Video *ecv;                               \
+   ecv = evas_object_data_get(ec->frame, EO_DATA_KEY)
+
+#define API_ENTRY                                     \
+   INTERNAL_DATA_GET;                                 \
+   EINA_SAFETY_ON_NULL_RETURN(ecv)
+
+#define API_ENTRY_RET(ret)                            \
+   INTERNAL_DATA_GET;                                 \
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ecv, ret)
+
+typedef struct _E_Client_Video E_Client_Video;
+
+struct _E_Client_Video
+{
+   /* Composite interface ( hwc planes / hwc windows / fallback ) */
+   E_Video_Comp_Iface *iface;
+
+   E_Client *ec;
+
+   Ecore_Event_Handler *eeh_zone_set;
+};
+
+static void
+_e_client_video_comp_iface_deinit(E_Client_Video *ecv)
+{
+   ecv->iface->destroy(ecv->iface);
+   ecv->iface = NULL;
+}
+
+static Eina_Bool
+_e_client_video_comp_iface_init(E_Client_Video *ecv, E_Client *ec)
+{
+   E_Video_Comp_Iface *iface = NULL;
+   E_Output *eout;
+   E_Hwc_Policy hwc_pol;
+
+   if ((e_config->eom_enable == EINA_TRUE) && (e_eom_is_ec_external(ec)))
+     {
+        /* FIXME workaround
+         * eom will be handled by hwc_planes implementation for now */
+        INF("Try to intialize the eom interface");
+        iface = e_video_hwc_planes_iface_create(ec);
+        goto end;
+     }
+
+   if (e_video_debug_display_primary_plane_value_get())
+     {
+        INF("Select SW Compositing mode according to configuration");
+        goto end;
+     }
+
+   eout = e_output_find(ec->zone->output_id);
+   if (!eout)
+     {
+        ERR("Something wrong, couldn't find 'E_Output' from 'E_Zone'");
+        goto end;
+     }
+
+   hwc_pol = e_hwc_policy_get(eout->hwc);
+   if (hwc_pol == E_HWC_POLICY_WINDOWS)
+     {
+        /* TODO */
+        INF("Try to initialize the interface for HWC WINDOWS mode");
+        WRN("* Not Implemented *");
+        iface = NULL;
+     }
+   else if (hwc_pol == E_HWC_POLICY_PLANES)
+     iface = e_video_hwc_planes_iface_create(ec);
+
+end:
+   if (!iface)
+     {
+        iface = e_video_fallback_iface_create(ec);
+        if (!iface)
+          {
+             ERR("Failed to create 'E_Video_Comp_Iface'");
+             return EINA_FALSE;
+          }
+     }
+
+   ecv->iface = iface;
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_client_video_cb_ec_zone_set(void *data, int type EINA_UNUSED, void *event)
+{
+   E_Client_Video *ecv;
+   E_Event_Client_Zone_Set *ev;
+
+   ecv = data;
+   ev = event;
+
+   if (ecv->ec != ev->ec)
+     goto end;
+
+   /* TODO
+    * if compositing policy of given E_Zone is changed, de-initialize previous
+    * compositing interface and initialize new compositing interface. */
+
+end:
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_client_video_init(E_Client_Video *ecv, E_Client *ec)
+{
+   Eina_Bool res;
+
+   res = _e_client_video_comp_iface_init(ecv, ec);
+   if (!res)
+     {
+        ERR("Failed to initialize the composition interface for video");
+        return EINA_FALSE;
+     }
+
+   ecv->ec = ec;
+   ecv->eeh_zone_set = ecore_event_handler_add(E_EVENT_CLIENT_ZONE_SET,
+                                               _e_client_video_cb_ec_zone_set,
+                                               ecv);
+
+   return EINA_TRUE;
+}
+
+static void
+_e_client_video_deinit(E_Client_Video *ecv)
+{
+   _e_client_video_comp_iface_deinit(ecv);
+
+   E_FREE_FUNC(ecv->eeh_zone_set, ecore_event_handler_del);
+}
+
+EINTERN Eina_Bool
+e_client_video_set(E_Client *ec)
+{
+   E_Client_Video *ecv;
+   Eina_Bool res;
+
+   ELOGF("VIDEO", "<INF> video set", ec->pixmap, ec);
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ec->frame, EINA_FALSE);
+
+   if (e_object_is_del(E_OBJECT(ec)))
+     {
+        ERR("Can't handle deleted client (%p)", ec);
+        return EINA_FALSE;
+     }
+
+   ecv = evas_object_data_get(ec->frame, EO_DATA_KEY);
+   if (ecv)
+     {
+        ERR("Given client (%p) was already set as Video client", ec);
+        return EINA_FALSE;
+     }
+
+   ecv = E_NEW(E_Client_Video, 1);
+   if (!ecv)
+     {
+        ERR("Failed to allocate memory");
+        return EINA_FALSE;
+     }
+
+   res = _e_client_video_init(ecv, ec);
+   if (!res)
+     {
+        ERR("Failed to initialize video setting");
+        free(ecv);
+        return EINA_FALSE;
+     }
+
+   evas_object_data_set(ec->frame, EO_DATA_KEY, ecv);
+   e_object_ref(E_OBJECT(ec));
+
+   return EINA_TRUE;
+}
+
+EINTERN void
+e_client_video_unset(E_Client *ec)
+{
+   API_ENTRY;
+
+   ELOGF("VIDEO", "<INF> unset video", ec->pixmap, ec);
+
+   _e_client_video_deinit(ecv);
+
+   evas_object_data_del(ec->frame, EO_DATA_KEY);
+   e_object_unref(E_OBJECT(ec));
+
+   free(ecv);
+}
+
+EINTERN Eina_Bool
+e_client_video_topmost_visibility_follow(E_Client *ec)
+{
+   API_ENTRY_RET(EINA_FALSE);
+
+   ELOGF("VIDEO", "<INF> follow topmost visibility", ec->pixmap, ec);
+
+   if (!ecv->iface->follow_topmost_visibility)
+     return EINA_FALSE;
+
+   return ecv->iface->follow_topmost_visibility(ecv->iface);
+}
+
+EINTERN Eina_Bool
+e_client_video_topmost_visibility_unfollow(E_Client *ec)
+{
+   API_ENTRY_RET(EINA_FALSE);
+
+   ELOGF("VIDEO", "<INF> unfollow topmost visibility", ec->pixmap, ec);
+
+   if (!ecv->iface->unfollow_topmost_visibility)
+     return EINA_FALSE;
+
+   return ecv->iface->unfollow_topmost_visibility(ecv->iface);
+}
+
+EINTERN Eina_Bool
+e_client_video_property_allow(E_Client *ec)
+{
+   API_ENTRY_RET(EINA_FALSE);
+
+   ELOGF("VIDEO", "<INF> allowed property", ec->pixmap, ec);
+
+   if (!ecv->iface->allowed_property)
+     return EINA_FALSE;
+
+   return ecv->iface->allowed_property(ecv->iface);
+}
+
+EINTERN Eina_Bool
+e_client_video_property_disallow(E_Client *ec)
+{
+   API_ENTRY_RET(EINA_FALSE);
+
+   ELOGF("VIDEO", "<INF> disallowed property", ec->pixmap, ec);
+
+   if (!ecv->iface->disallowed_property)
+     return EINA_FALSE;
+
+   return ecv->iface->disallowed_property(ecv->iface);
+}
+
+EINTERN Eina_Bool
+e_client_video_property_get(E_Client *ec, unsigned int id, tdm_value *value)
+{
+   API_ENTRY_RET(EINA_FALSE);
+
+   ELOGF("VIDEO", "<INF> get property", ec->pixmap, ec);
+
+   if (!ecv->iface->property_get)
+     return EINA_FALSE;
+
+   return ecv->iface->property_get(ecv->iface, id, value);
+}
+
+EINTERN Eina_Bool
+e_client_video_property_set(E_Client *ec, unsigned int id, tdm_value value)
+{
+   API_ENTRY_RET(EINA_FALSE);
+
+   ELOGF("VIDEO", "<INF> set property", ec->pixmap, ec);
+
+   if (!ecv->iface->property_set)
+     return EINA_FALSE;
+
+   return ecv->iface->property_set(ecv->iface, id, value);
+}
+
+EINTERN Eina_Bool
+e_client_video_property_delay_set(E_Client *ec, unsigned int id, tdm_value value)
+{
+   API_ENTRY_RET(EINA_FALSE);
+
+   ELOGF("VIDEO", "<INF> delay set property", ec->pixmap, ec);
+
+   if (!ecv->iface->property_delay_set)
+     return EINA_FALSE;
+
+   return ecv->iface->property_delay_set(ecv->iface, id, value);
+}
+
+EINTERN Eina_Bool
+e_client_video_available_properties_get(E_Client *ec, const tdm_prop **props, int *count)
+{
+   API_ENTRY_RET(EINA_FALSE);
+
+   ELOGF("VIDEO", "<INF> get available properties", ec->pixmap, ec);
+
+   if (!ecv->iface->available_properties_get)
+     return EINA_FALSE;
+
+   return ecv->iface->available_properties_get(ecv->iface, props, count);
+}
+
+EINTERN Eina_Bool
+e_client_video_info_get(E_Client *ec, E_Client_Video_Info *info)
+{
+   API_ENTRY_RET(EINA_FALSE);
+
+   ELOGF("VIDEO", "<INF> get info", ec->pixmap, ec);
+
+   if (!ecv->iface->info_get)
+     return EINA_FALSE;
+
+   return ecv->iface->info_get(ecv->iface, info);
+}
+
+EINTERN Eina_Bool
+e_client_video_commit_data_release(E_Client *ec, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec)
+{
+   API_ENTRY_RET(EINA_FALSE);
+
+   ELOGF("VIDEO", "<INF> release commit data", ec->pixmap, ec);
+
+   if (!ecv->iface->commit_data_release)
+     return EINA_FALSE;
+
+   return ecv->iface->commit_data_release(ecv->iface, sequence, tv_sec, tv_usec);
+}
+
+EINTERN tbm_surface_h
+e_client_video_tbm_surface_get(E_Client *ec)
+{
+   API_ENTRY_RET(NULL);
+
+   ELOGF("VIDEO", "<INF> get tbm_surface_h", ec->pixmap, ec);
+
+   if (!ecv->iface->tbm_surface_get)
+     return NULL;
+
+   return ecv->iface->tbm_surface_get(ecv->iface);
+}
diff --git a/src/bin/video/e_client_video.h b/src/bin/video/e_client_video.h
new file mode 100644 (file)
index 0000000..f348736
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef _E_CLIENT_VIDEO_H_
+#define _E_CLIENT_VIDEO_H_
+
+#include <tdm.h>
+#include <tdm_helper.h>
+#include <tbm_surface.h>
+#include <values.h>
+
+typedef struct _E_Client_Video_Info E_Client_Video_Info;
+
+struct _E_Client_Video_Info
+{
+   tdm_info_config src_config;
+   tdm_pos dst_pos;
+   tdm_transform transform;
+};
+
+EINTERN Eina_Bool    e_client_video_set(E_Client *ec);
+EINTERN void         e_client_video_unset(E_Client *ec);
+
+EINTERN Eina_Bool    e_client_video_topmost_visibility_follow(E_Client *ec);
+EINTERN Eina_Bool    e_client_video_topmost_visibility_unfollow(E_Client *ec);
+EINTERN Eina_Bool    e_client_video_property_allow(E_Client *ec);
+EINTERN Eina_Bool    e_client_video_property_disallow(E_Client *ec);
+
+EINTERN Eina_Bool    e_client_video_available_properties_get(E_Client *ec, const tdm_prop **props, int *count);
+EINTERN Eina_Bool    e_client_video_property_get(E_Client *ec, unsigned int id, tdm_value *value);
+EINTERN Eina_Bool    e_client_video_property_set(E_Client *ec, unsigned int id, tdm_value value);
+EINTERN Eina_Bool    e_client_video_property_delay_set(E_Client *ec, unsigned int id, tdm_value value);
+
+EINTERN Eina_Bool    e_client_video_info_get(E_Client *ec, E_Client_Video_Info *info);
+EINTERN Eina_Bool    e_client_video_commit_data_release(E_Client *ec, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec);
+
+EINTERN tbm_surface_h  e_client_video_tbm_surface_get(E_Client *ec);
+
+#endif
diff --git a/src/bin/video/e_comp_wl_video.c b/src/bin/video/e_comp_wl_video.c
new file mode 100644 (file)
index 0000000..0b41653
--- /dev/null
@@ -0,0 +1,614 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "e.h"
+#include <tdm.h>
+#include <values.h>
+#include <tdm_helper.h>
+#include <wayland-tbm-server.h>
+#include <tizen-extension-server-protocol.h>
+
+static int _video_detail_log_dom = -1;
+
+#define VER(fmt, arg...) ELOGF("VIDEO", "<ERR> window(0x%08"PRIxPTR"): "fmt, \
+                               video->ec->pixmap, video->ec, video->window, ##arg)
+#define VWR(fmt, arg...) ELOGF("VIDEO", "<WRN> window(0x%08"PRIxPTR"): "fmt, \
+                               video->ec->pixmap, video->ec, video->window, ##arg)
+#define VIN(fmt, arg...) ELOGF("VIDEO", "<INF> window(0x%08"PRIxPTR"): "fmt, \
+                               video->ec->pixmap, video->ec, video->window, ##arg)
+#define VDB(fmt, arg...) DBG("window(0x%08"PRIxPTR") ec(%p): "fmt, video->window, video->ec, ##arg)
+
+#define DET(...)          EINA_LOG_DOM_DBG(_video_detail_log_dom, __VA_ARGS__)
+#define VDT(fmt, arg...)   DET("window(0x%08"PRIxPTR"): "fmt, video->window, ##arg)
+
+typedef struct _E_Video E_Video;
+
+struct _E_Video
+{
+   struct wl_resource *video_object;
+   struct wl_resource *surface;
+   E_Client *ec;
+   Ecore_Window window;
+
+   Eina_Bool  follow_topmost_visibility;
+   Eina_Bool  allowed_attribute;
+
+};
+
+static Eina_List *video_list = NULL;
+
+static void _e_video_set(E_Video *video, E_Client *ec);
+static void _e_video_destroy(E_Video *video);
+
+static E_Video *
+find_video_with_surface(struct wl_resource *surface)
+{
+   E_Video *video;
+   Eina_List *l;
+   EINA_LIST_FOREACH(video_list, l, video)
+     {
+        if (video->surface == surface)
+          return video;
+     }
+   return NULL;
+}
+
+static E_Client *
+find_offscreen_parent_get(E_Client *ec)
+{
+   E_Client *parent = NULL;
+
+   if (!ec->comp_data || !ec->comp_data->sub.data)
+     return NULL;
+
+   parent = ec->comp_data->sub.data->parent;
+   while (parent)
+     {
+        if (!parent->comp_data || !parent->comp_data->sub.data)
+          return NULL;
+
+        if (parent->comp_data->sub.data->remote_surface.offscreen_parent)
+          return parent->comp_data->sub.data->remote_surface.offscreen_parent;
+
+        parent = parent->comp_data->sub.data->parent;
+     }
+
+   return NULL;
+}
+
+static int
+_e_video_get_prop_id(E_Video *video, const char *name)
+{
+   const tdm_prop *props;
+   int i, count = 0;
+
+   e_client_video_available_properties_get(video->ec, &props, &count);
+   for (i = 0; i < count; i++)
+     {
+        if (!strncmp(name, props[i].name, TDM_NAME_LEN))
+          {
+             VDB("check property(%s)", name);
+             return props[i].id;
+          }
+     }
+
+   return -1;
+}
+
+static Eina_Bool
+_e_video_is_visible(E_Video *video)
+{
+   E_Client *offscreen_parent;
+
+   if (e_object_is_del(E_OBJECT(video->ec))) return EINA_FALSE;
+
+   if (!e_pixmap_resource_get(video->ec->pixmap))
+     {
+        VDB("no comp buffer");
+        return EINA_FALSE;
+     }
+
+   if (video->ec->comp_data->sub.data && video->ec->comp_data->sub.data->stand_alone)
+     return EINA_TRUE;
+
+   offscreen_parent = find_offscreen_parent_get(video->ec);
+   if (offscreen_parent && offscreen_parent->visibility.obscured == E_VISIBILITY_FULLY_OBSCURED)
+     {
+        VDB("video surface invisible: offscreen fully obscured");
+        return EINA_FALSE;
+     }
+
+   if (!evas_object_visible_get(video->ec->frame))
+     {
+        VDB("evas obj invisible");
+        return EINA_FALSE;
+     }
+
+   return EINA_TRUE;
+}
+
+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;
+
+   EINA_SAFETY_ON_NULL_RETURN(hwc_window);
+
+   ec = hwc_window->ec;
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   e_client_video_commit_data_release(ec, sequence, tv_sec, tv_usec);
+}
+
+EINTERN tbm_surface_h
+e_comp_wl_video_hwc_widow_surface_get(E_Hwc_Window *hwc_window)
+{
+   E_Client *ec = NULL;
+
+   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;
+   if (!ec) return NULL;
+
+   return e_client_video_tbm_surface_get(ec);
+}
+
+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;
+   E_Client_Video_Info 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);
+
+   if (!e_client_video_info_get(ec, &vinfo))
+     return 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 E_Video *
+_e_video_create(struct wl_resource *video_object, struct wl_resource *surface)
+{
+   E_Video *video;
+   E_Client *ec;
+
+   ec = wl_resource_get_user_data(surface);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
+   EINA_SAFETY_ON_TRUE_RETURN_VAL(e_object_is_del(E_OBJECT(ec)), NULL);
+
+   video = calloc(1, sizeof *video);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(video, NULL);
+
+   video->video_object = video_object;
+   video->surface = surface;
+
+   VIN("create. ec(%p) wl_surface@%d", ec, wl_resource_get_id(video->surface));
+
+   video_list = eina_list_append(video_list, video);
+
+   _e_video_set(video, ec);
+
+   return video;
+}
+
+static void
+_e_video_set(E_Video *video, E_Client *ec)
+{
+   Eina_Bool res;
+   int minw = -1, minh = -1, maxw = -1, maxh = -1;
+   int align = -1;
+   int i, count = 0;
+   const tdm_prop *props;
+
+   video->ec = ec;
+   video->window = e_client_util_win_get(ec);
+
+   EINA_SAFETY_ON_NULL_RETURN(video->ec->zone);
+
+   e_client_video_set(ec);
+   /* FIXME workaround */
+   if ((e_config->eom_enable == EINA_TRUE) &&
+       (e_eom_is_ec_external(ec)))
+     return;
+
+   res = e_zone_video_available_size_get(ec->zone, &minw, &minh, &maxw, &maxh, &align);
+   if (res)
+     {
+        tizen_video_object_send_size(video->video_object,
+                                     minw, minh, maxw, maxh, align);
+        /* VIN("align width: output(%d) pp(%d) video(%d)",
+            video->output_align, video->pp_align, video->video_align); */
+     }
+   else
+     VER("Failed to get video available size");
+
+   e_client_video_available_properties_get(ec, &props, &count);
+   for (i = 0; i < count; i++)
+     {
+        tdm_value value;
+
+        res = e_client_video_property_get(ec, props[i].id, &value);
+        if (!res)
+          {
+             VER("Failed to get property name %s value %d", props[i].name, value.u32);
+             continue;
+          }
+
+        tizen_video_object_send_attribute(video->video_object, props[i].name, value.u32);
+     }
+}
+
+static void
+_e_video_destroy(E_Video *video)
+{
+   if (!video)
+     return;
+
+   VIN("destroy");
+
+   wl_resource_set_destructor(video->video_object, NULL);
+
+   e_client_video_unset(video->ec);
+
+   video_list = eina_list_remove(video_list, video);
+
+   free(video);
+
+#if 0
+   if (e_comp_wl_video_buffer_list_length() > 0)
+     e_comp_wl_video_buffer_list_print(NULL);
+#endif
+}
+
+static Eina_Bool
+_e_video_cb_ec_remove(void *data, int type, void *event)
+{
+   E_Event_Client *ev = event;
+   E_Client *ec;
+   E_Video *video;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ev->ec, ECORE_CALLBACK_PASS_ON);
+
+   ec = ev->ec;
+   if (!ec->comp_data) return ECORE_CALLBACK_PASS_ON;
+
+   video = find_video_with_surface(ec->comp_data->surface);
+   if (!video) return ECORE_CALLBACK_PASS_ON;
+
+   _e_video_destroy(video);
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static void
+_e_comp_wl_video_object_destroy(struct wl_resource *resource)
+{
+   E_Video *video = wl_resource_get_user_data(resource);
+   EINA_SAFETY_ON_NULL_RETURN(video);
+
+   _e_video_destroy(video);
+}
+
+static void
+_e_comp_wl_video_object_cb_destroy(struct wl_client *client, struct wl_resource *resource)
+{
+   wl_resource_destroy(resource);
+}
+
+static void
+_e_comp_wl_video_object_cb_set_attribute(struct wl_client *client,
+                                         struct wl_resource *resource,
+                                         const char *name,
+                                         int32_t value)
+{
+   E_Video *video;
+   tdm_value v;
+   int id;
+
+   video = wl_resource_get_user_data(resource);
+   EINA_SAFETY_ON_NULL_RETURN(video);
+
+   if(video->ec)
+     VDT("Client(%s):PID(%d) RscID(%d) Attribute:%s, Value:%d",
+         e_client_util_name_get(video->ec) ?: "No Name",
+         video->ec->netwm.pid, wl_resource_get_id(video->surface),
+         name, value);
+
+   // check available property & count
+   id = _e_video_get_prop_id(video, name);
+   if(id < 0)
+     {
+        VIN("no available property");
+        return;
+     }
+
+   v.u32 = value;
+   if ((!_e_video_is_visible(video)) &&
+       /* if mute off, need to do it after buffer commit */
+       ((!strncmp(name, "mute", TDM_NAME_LEN)) && (value == 0)))
+     {
+        e_client_video_property_delay_set(video->ec, id, v);
+        return;
+     }
+   else
+     e_client_video_property_set(video->ec, id, v);
+}
+
+static void
+_e_comp_wl_video_object_cb_follow_topmost_visibility(struct wl_client *client,
+                                                     struct wl_resource *resource)
+{
+   E_Video *video;
+
+   video = wl_resource_get_user_data(resource);
+   EINA_SAFETY_ON_NULL_RETURN(video);
+
+   if(!video->ec || video->follow_topmost_visibility)
+     return;
+
+   VIN("set follow_topmost_visibility");
+
+   video->follow_topmost_visibility= EINA_TRUE;
+   e_client_video_topmost_visibility_follow(video->ec);
+}
+
+static void
+_e_comp_wl_video_object_cb_unfollow_topmost_visibility(struct wl_client *client,
+                                                       struct wl_resource *resource)
+{
+   E_Video *video;
+
+   video = wl_resource_get_user_data(resource);
+   EINA_SAFETY_ON_NULL_RETURN(video);
+
+   if(!video->ec || !video->follow_topmost_visibility)
+     return;
+
+   VIN("set unfollow_topmost_visibility");
+
+   video->follow_topmost_visibility= EINA_FALSE;
+   e_client_video_topmost_visibility_unfollow(video->ec);
+}
+
+static void
+_e_comp_wl_video_object_cb_allowed_attribute(struct wl_client *client,
+                                             struct wl_resource *resource)
+{
+   E_Video *video;
+
+   video = wl_resource_get_user_data(resource);
+   EINA_SAFETY_ON_NULL_RETURN(video);
+
+   if(!video->ec || video->allowed_attribute)
+     return;
+
+   VIN("set allowed_attribute");
+
+   video->allowed_attribute = EINA_TRUE;
+   e_client_video_property_allow(video->ec);
+}
+
+static void
+_e_comp_wl_video_object_cb_disallowed_attribute(struct wl_client *client,
+                                                struct wl_resource *resource)
+{
+   E_Video *video;
+
+   video = wl_resource_get_user_data(resource);
+   EINA_SAFETY_ON_NULL_RETURN(video);
+
+   if(!video->ec || !video->allowed_attribute)
+     return;
+
+   VIN("set disallowed_attribute");
+
+   video->allowed_attribute = EINA_FALSE;
+   e_client_video_property_disallow(video->ec);
+}
+
+static const struct tizen_video_object_interface _e_comp_wl_video_object_interface =
+{
+   _e_comp_wl_video_object_cb_destroy,
+   _e_comp_wl_video_object_cb_set_attribute,
+   _e_comp_wl_video_object_cb_follow_topmost_visibility,
+   _e_comp_wl_video_object_cb_unfollow_topmost_visibility,
+   _e_comp_wl_video_object_cb_allowed_attribute,
+   _e_comp_wl_video_object_cb_disallowed_attribute,
+};
+
+static void
+_e_comp_wl_video_cb_get_object(struct wl_client *client,
+                               struct wl_resource *resource,
+                               uint32_t id,
+                               struct wl_resource *surface)
+{
+   E_Video *video;
+   int version = wl_resource_get_version(resource);
+   struct wl_resource *res;
+
+   res = wl_resource_create(client, &tizen_video_object_interface, version, id);
+   if (res == NULL)
+     {
+        wl_client_post_no_memory(client);
+        return;
+     }
+
+   if (!(video = _e_video_create(res, surface)))
+     {
+        wl_resource_destroy(res);
+        wl_client_post_no_memory(client);
+        return;
+     }
+
+   wl_resource_set_implementation(res, &_e_comp_wl_video_object_interface,
+                                  video, _e_comp_wl_video_object_destroy);
+}
+
+static void
+_e_comp_wl_video_cb_get_viewport(struct wl_client *client,
+                                 struct wl_resource *resource,
+                                 uint32_t id,
+                                 struct wl_resource *surface)
+{
+   E_Client *ec;
+
+   if (!(ec = wl_resource_get_user_data(surface))) return;
+   if (!ec->comp_data) return;
+
+   if (ec->comp_data && ec->comp_data->scaler.viewport)
+     {
+        wl_resource_post_error(resource,
+                               TIZEN_VIDEO_ERROR_VIEWPORT_EXISTS,
+                               "a viewport for that subsurface already exists");
+        return;
+     }
+
+   if (!e_comp_wl_viewport_create(resource, id, surface))
+     {
+        ERR("Failed to create viewport for wl_surface@%d",
+            wl_resource_get_id(surface));
+        wl_client_post_no_memory(client);
+        return;
+     }
+}
+
+static void
+_e_comp_wl_video_cb_destroy(struct wl_client *client, struct wl_resource *resource)
+{
+   wl_resource_destroy(resource);
+}
+
+static const struct tizen_video_interface _e_comp_wl_video_interface =
+{
+   _e_comp_wl_video_cb_get_object,
+   _e_comp_wl_video_cb_get_viewport,
+   _e_comp_wl_video_cb_destroy,
+};
+
+static void
+_e_comp_wl_video_cb_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
+{
+   struct wl_resource *res;
+   const uint32_t *formats = NULL;
+   int i, count = 0;
+
+   if (!(res = wl_resource_create(client, &tizen_video_interface, version, id)))
+     {
+        ERR("Could not create tizen_video_interface resource: %m");
+        wl_client_post_no_memory(client);
+        return;
+     }
+
+   wl_resource_set_implementation(res, &_e_comp_wl_video_interface, NULL, NULL);
+
+   e_comp_screen_available_video_formats_get(&formats, &count);
+   for (i = 0; i < count; i++)
+     tizen_video_send_format(res, formats[i]);
+}
+
+static Eina_List *video_hdlrs;
+
+static void
+_e_comp_wl_vbuf_print(void *data, const char *log_path)
+{
+   e_comp_wl_video_buffer_list_print(log_path);
+}
+
+static void
+_e_comp_wl_video_to_primary(void *data, const char *log_path)
+{
+   Eina_Bool flag;
+
+   flag = e_video_debug_display_primary_plane_value_get();
+   e_video_debug_display_primary_plane_set(!flag);
+}
+
+static void
+_e_comp_wl_video_punch(void *data, const char *log_path)
+{
+   Eina_Bool flag;
+
+   flag = e_video_debug_punch_value_get();
+   e_video_debug_punch_set(!flag);
+}
+
+EINTERN int
+e_comp_wl_video_init(void)
+{
+   e_comp->wl_comp_data->available_hw_accel.underlay = EINA_TRUE;
+   DBG("enable HW underlay");
+
+   e_comp->wl_comp_data->available_hw_accel.scaler = EINA_TRUE;
+   DBG("enable HW scaler");
+
+   if (!e_comp_wl) return 0;
+   if (!e_comp_wl->wl.disp) return 0;
+   if (e_comp->wl_comp_data->video.global) return 1;
+
+   e_info_server_hook_set("vbuf", _e_comp_wl_vbuf_print, NULL);
+   e_info_server_hook_set("video-to-primary", _e_comp_wl_video_to_primary, NULL);
+   e_info_server_hook_set("video-punch", _e_comp_wl_video_punch, NULL);
+
+   _video_detail_log_dom = eina_log_domain_register("e-comp-wl-video", EINA_COLOR_BLUE);
+   if (_video_detail_log_dom < 0)
+     {
+        ERR("Failed eina_log_domain_register()..!\n");
+        return 0;
+     }
+
+   /* try to add tizen_video to wayland globals */
+   e_comp->wl_comp_data->video.global =
+      wl_global_create(e_comp_wl->wl.disp, &tizen_video_interface, 1, NULL, _e_comp_wl_video_cb_bind);
+
+   if (!e_comp->wl_comp_data->video.global)
+     {
+        ERR("Could not add tizen_video to wayland globals");
+        return 0;
+     }
+
+   E_LIST_HANDLER_APPEND(video_hdlrs, E_EVENT_CLIENT_REMOVE,
+                         _e_video_cb_ec_remove, NULL);
+
+   return 1;
+}
+
+EINTERN void
+e_comp_wl_video_shutdown(void)
+{
+   e_comp->wl_comp_data->available_hw_accel.underlay = EINA_FALSE;
+   e_comp->wl_comp_data->available_hw_accel.scaler = EINA_FALSE;
+
+   E_FREE_FUNC(e_comp->wl_comp_data->video.global, wl_global_destroy);
+   E_FREE_LIST(video_hdlrs, ecore_event_handler_del);
+
+   e_info_server_hook_set("vbuf", NULL, NULL);
+   e_info_server_hook_set("video-dst-change", NULL, NULL);
+   e_info_server_hook_set("video-to-primary", NULL, NULL);
+   e_info_server_hook_set("video-punch", NULL, NULL);
+
+   eina_log_domain_unregister(_video_detail_log_dom);
+   _video_detail_log_dom = -1;
+}
diff --git a/src/bin/video/e_comp_wl_video.h b/src/bin/video/e_comp_wl_video.h
new file mode 100644 (file)
index 0000000..fc9bac3
--- /dev/null
@@ -0,0 +1,22 @@
+#ifdef E_TYPEDEFS
+
+#else
+#ifndef E_COMP_WL_VIDEO_H
+#define E_COMP_WL_VIDEO_H
+
+#define E_COMP_WL
+
+EINTERN int e_comp_wl_video_init(void);
+EINTERN void e_comp_wl_video_shutdown(void);
+
+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)
+#define ROUNDUP(s,c)        (((s) + (c-1)) & ~(c-1))
+
+#endif
+#endif
diff --git a/src/bin/video/e_comp_wl_video_buffer.c b/src/bin/video/e_comp_wl_video_buffer.c
new file mode 100644 (file)
index 0000000..20fd462
--- /dev/null
@@ -0,0 +1,966 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "e.h"
+#include <wayland-tbm-server.h>
+#include <sys/mman.h>
+#include <pixman.h>
+#include <tdm_helper.h>
+
+//#define DEBUG_LIFECYCLE
+
+#define BER(fmt,arg...)   ERR("%d: "fmt, vbuf ? vbuf->stamp : 0, ##arg)
+#define BWR(fmt,arg...)   WRN("%d: "fmt, vbuf ? vbuf->stamp : 0, ##arg)
+#define BIN(fmt,arg...)   INF("%d: "fmt, vbuf ? vbuf->stamp : 0, ##arg)
+#define BDB(fmt,arg...)   DBG("%d: "fmt, vbuf ? vbuf->stamp : 0, ##arg)
+
+#define VBUF_RETURN_IF_FAIL(cond) \
+   {if (!(cond)) { BER("'%s' failed", #cond); return; }}
+#define VBUF_RETURN_VAL_IF_FAIL(cond, val) \
+   {if (!(cond)) { BER("'%s' failed", #cond); return val; }}
+
+#ifdef DEBUG_LIFECYCLE
+#undef BDB
+#define BDB BIN
+#endif
+
+typedef struct _VBufFreeFuncInfo
+{
+   VBuf_Free_Func func;
+   void *data;
+} VBufFreeFuncInfo;
+
+static void _e_comp_wl_video_buffer_cb_destroy(struct wl_listener *listener, void *data);
+static void _e_comp_wl_video_buffer_free(E_Comp_Wl_Video_Buf *vbuf);
+#define e_comp_wl_video_buffer_free(b) _e_comp_wl_video_buffer_free(b)
+
+static Eina_List *vbuf_lists;
+
+static E_Comp_Wl_Video_Buf*
+_find_vbuf(uint stamp)
+{
+   E_Comp_Wl_Video_Buf *vbuf;
+   Eina_List *l;
+
+   if (!vbuf_lists)
+     return NULL;
+
+   EINA_LIST_FOREACH(vbuf_lists, l, vbuf)
+     {
+        if (vbuf->stamp == stamp)
+          return vbuf;
+     }
+
+   return NULL;
+}
+
+static Eina_Bool
+_e_comp_wl_video_buffer_access_data_begin(E_Comp_Wl_Video_Buf *vbuf)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(vbuf, EINA_FALSE);
+
+   vbuf->ptrs[0] = vbuf->ptrs[1] = vbuf->ptrs[2] = NULL;
+
+   if (vbuf->type == E_COMP_WL_VIDEO_BUF_TYPE_SHM)
+     {
+        struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get(vbuf->resource);
+        EINA_SAFETY_ON_NULL_RETURN_VAL(shm_buffer, EINA_FALSE);
+        vbuf->ptrs[0] = wl_shm_buffer_get_data(shm_buffer);
+        EINA_SAFETY_ON_NULL_RETURN_VAL(vbuf->ptrs[0], EINA_FALSE);
+        return EINA_TRUE;
+     }
+   else if (vbuf->type == E_COMP_WL_VIDEO_BUF_TYPE_TBM)
+     {
+        int i, j;
+        tbm_bo bos[4] = {0,};
+
+        for (i = 0; i < 3; i++)
+          {
+             tbm_bo_handle bo_handles;
+
+             bos[i] = tbm_surface_internal_get_bo(vbuf->tbm_surface, i);
+             if (!bos[i]) continue;
+
+             bo_handles = tbm_bo_map(bos[i], TBM_DEVICE_CPU, TBM_OPTION_READ);
+             if (!bo_handles.ptr)
+               {
+                  for (j = 0; j < i; j++)
+                    tbm_bo_unmap(bos[j]);
+                  return EINA_FALSE;
+               }
+
+             vbuf->ptrs[i] = bo_handles.ptr;
+          }
+
+        EINA_SAFETY_ON_NULL_RETURN_VAL(vbuf->ptrs[0], EINA_FALSE);
+
+        switch(vbuf->tbmfmt)
+          {
+           case TBM_FORMAT_YVU420:
+           case TBM_FORMAT_YUV420:
+              if (!vbuf->ptrs[1])
+                vbuf->ptrs[1] = vbuf->ptrs[0];
+              if (!vbuf->ptrs[2])
+                vbuf->ptrs[2] = vbuf->ptrs[1];
+              break;
+           case TBM_FORMAT_NV12:
+           case TBM_FORMAT_NV21:
+              if (!vbuf->ptrs[1])
+                vbuf->ptrs[1] = vbuf->ptrs[0];
+              break;
+           default:
+              break;
+          }
+
+        return EINA_TRUE;
+     }
+
+   return EINA_FALSE;
+}
+
+static void
+_e_comp_wl_video_buffer_access_data_end(E_Comp_Wl_Video_Buf *vbuf)
+{
+   EINA_SAFETY_ON_NULL_RETURN(vbuf);
+
+   if (vbuf->type == E_COMP_WL_VIDEO_BUF_TYPE_SHM)
+     {
+        vbuf->ptrs[0] = NULL;
+     }
+   else if (vbuf->type == E_COMP_WL_VIDEO_BUF_TYPE_TBM)
+     {
+        int i;
+        tbm_bo bos[4] = {0,};
+
+        for (i = 0; i < 3; i++)
+          {
+             bos[i] = tbm_surface_internal_get_bo(vbuf->tbm_surface, i);
+             if (!bos[i]) continue;
+
+             tbm_bo_unmap(bos[i]);
+             vbuf->ptrs[i] = NULL;
+          }
+     }
+}
+
+static E_Comp_Wl_Video_Buf*
+_e_comp_wl_video_buffer_create_res(struct wl_resource *resource)
+{
+   E_Comp_Wl_Video_Buf *vbuf = NULL;
+   struct wl_shm_buffer *shm_buffer;
+   tbm_surface_h tbm_surface;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(resource, NULL);
+
+   vbuf = calloc(1, sizeof(E_Comp_Wl_Video_Buf));
+   EINA_SAFETY_ON_FALSE_GOTO(vbuf != NULL, create_fail);
+
+   vbuf->ref_cnt = 1;
+   vbuf->stamp = e_comp_wl_video_buffer_get_mills();
+   while (_find_vbuf(vbuf->stamp))
+     vbuf->stamp++;
+
+   vbuf->resource = resource;
+
+   if ((shm_buffer = wl_shm_buffer_get(resource)))
+     {
+        uint32_t tbmfmt = wl_shm_buffer_get_format(shm_buffer);
+
+        vbuf->type = E_COMP_WL_VIDEO_BUF_TYPE_SHM;
+
+        if (tbmfmt == WL_SHM_FORMAT_ARGB8888)
+          vbuf->tbmfmt = TBM_FORMAT_ARGB8888;
+        else if (tbmfmt == WL_SHM_FORMAT_XRGB8888)
+          vbuf->tbmfmt = TBM_FORMAT_XRGB8888;
+        else
+          vbuf->tbmfmt = tbmfmt;
+
+        vbuf->width = wl_shm_buffer_get_width(shm_buffer);
+        vbuf->height = wl_shm_buffer_get_height(shm_buffer);
+        vbuf->pitches[0] = wl_shm_buffer_get_stride(shm_buffer);
+
+        vbuf->width_from_pitch = vbuf->width;
+        vbuf->height_from_size = vbuf->height;;
+     }
+   else if ((tbm_surface = wayland_tbm_server_get_surface(e_comp->wl_comp_data->tbm.server, resource)))
+     {
+        int i;
+
+        vbuf->type = E_COMP_WL_VIDEO_BUF_TYPE_TBM;
+        vbuf->tbm_surface = tbm_surface;
+        tbm_surface_internal_ref(tbm_surface);
+
+        vbuf->tbmfmt = tbm_surface_get_format(tbm_surface);
+        vbuf->width = tbm_surface_get_width(tbm_surface);
+        vbuf->height = tbm_surface_get_height(tbm_surface);
+
+        /* NOTE Some format such a NVxx and a YUVxxx can have multiple handles */
+        for (i = 0; i < 3; i++)
+          {
+             uint32_t size = 0, offset = 0, pitch = 0;
+             tbm_bo bo;
+
+             bo = tbm_surface_internal_get_bo(tbm_surface, i);
+             if (bo)
+               {
+                  vbuf->handles[i] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32;
+                  EINA_SAFETY_ON_FALSE_GOTO(vbuf->handles[i] > 0, create_fail);
+
+                  vbuf->names[i] = tbm_bo_export(bo);
+                  EINA_SAFETY_ON_FALSE_GOTO(vbuf->names[i] > 0, create_fail);
+               }
+
+             tbm_surface_internal_get_plane_data(tbm_surface, i, &size, &offset, &pitch);
+             vbuf->pitches[i] = pitch;
+             vbuf->offsets[i] = offset;
+          }
+
+        tdm_helper_get_buffer_full_size(tbm_surface, &vbuf->width_from_pitch, &vbuf->height_from_size);
+     }
+   else
+     {
+        ERR("unknown buffer resource");
+        goto create_fail;
+     }
+
+   vbuf_lists = eina_list_append(vbuf_lists, vbuf);
+
+   BDB("type(%d) %dx%d(%dx%d), %c%c%c%c, name(%d,%d,%d) hnd(%d,%d,%d), pitch(%d,%d,%d), offset(%d,%d,%d)",
+       vbuf->type, vbuf->width_from_pitch, vbuf->height_from_size,
+       vbuf->width, vbuf->height, FOURCC_STR(vbuf->tbmfmt),
+       vbuf->names[0], vbuf->names[1], vbuf->names[2],
+       vbuf->handles[0], vbuf->handles[1], vbuf->handles[2],
+       vbuf->pitches[0], vbuf->pitches[1], vbuf->pitches[2],
+       vbuf->offsets[0], vbuf->offsets[1], vbuf->offsets[2]);
+
+   return vbuf;
+
+create_fail:
+   _e_comp_wl_video_buffer_free(vbuf);
+
+   return NULL;
+}
+
+EINTERN E_Comp_Wl_Video_Buf*
+e_comp_wl_video_buffer_create(struct wl_resource *resource)
+{
+   E_Comp_Wl_Video_Buf *vbuf = _e_comp_wl_video_buffer_create_res(resource);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(vbuf, NULL);
+
+   vbuf->destroy_listener.notify = _e_comp_wl_video_buffer_cb_destroy;
+   wl_resource_add_destroy_listener(resource, &vbuf->destroy_listener);
+
+   return vbuf;
+}
+
+EINTERN E_Comp_Wl_Video_Buf*
+e_comp_wl_video_buffer_create_comp(E_Comp_Wl_Buffer *comp_buffer)
+{
+   E_Comp_Wl_Video_Buf *vbuf;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(comp_buffer, NULL);
+
+   vbuf = _e_comp_wl_video_buffer_create_res(comp_buffer->resource);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(vbuf, NULL);
+
+   vbuf->comp_buffer = comp_buffer;
+
+   vbuf->destroy_listener.notify = _e_comp_wl_video_buffer_cb_destroy;
+   wl_resource_add_destroy_listener(comp_buffer->resource, &vbuf->destroy_listener);
+
+   return vbuf;
+}
+
+EINTERN E_Comp_Wl_Video_Buf*
+e_comp_wl_video_buffer_create_tbm(tbm_surface_h tbm_surface)
+{
+   E_Comp_Wl_Video_Buf *vbuf;
+   int i;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(tbm_surface, NULL);
+
+   vbuf = calloc(1, sizeof(E_Comp_Wl_Video_Buf));
+   EINA_SAFETY_ON_FALSE_GOTO(vbuf != NULL, create_fail);
+
+   vbuf->ref_cnt = 1;
+   vbuf->stamp = e_comp_wl_video_buffer_get_mills();
+   while (_find_vbuf(vbuf->stamp))
+     vbuf->stamp++;
+
+   vbuf->type = E_COMP_WL_VIDEO_BUF_TYPE_TBM;
+   vbuf->tbm_surface = tbm_surface;
+   tbm_surface_internal_ref(tbm_surface);
+
+   vbuf->tbmfmt = tbm_surface_get_format(tbm_surface);
+   vbuf->width = tbm_surface_get_width(tbm_surface);
+   vbuf->height = tbm_surface_get_height(tbm_surface);
+
+   for (i = 0; i < 3; i++)
+     {
+        uint32_t size = 0, offset = 0, pitch = 0;
+        tbm_bo bo;
+
+        bo = tbm_surface_internal_get_bo(tbm_surface, i);
+        if (bo)
+          {
+             vbuf->handles[i] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32;
+             EINA_SAFETY_ON_FALSE_GOTO(vbuf->handles[i] > 0, create_fail);
+
+             vbuf->names[i] = tbm_bo_export(bo);
+             EINA_SAFETY_ON_FALSE_GOTO(vbuf->names[i] > 0, create_fail);
+          }
+
+        tbm_surface_internal_get_plane_data(tbm_surface, i, &size, &offset, &pitch);
+        vbuf->pitches[i] = pitch;
+        vbuf->offsets[i] = offset;
+     }
+
+   tdm_helper_get_buffer_full_size(tbm_surface, &vbuf->width_from_pitch, &vbuf->height_from_size);
+
+   vbuf_lists = eina_list_append(vbuf_lists, vbuf);
+
+   BDB("type(%d) %dx%d(%dx%d), %c%c%c%c, name(%d,%d,%d) hnd(%d,%d,%d), pitch(%d,%d,%d), offset(%d,%d,%d)",
+       vbuf->type, vbuf->width_from_pitch, vbuf->height_from_size,
+       vbuf->width, vbuf->height, FOURCC_STR(vbuf->tbmfmt),
+       vbuf->names[0], vbuf->names[1], vbuf->names[2],
+       vbuf->handles[0], vbuf->handles[1], vbuf->handles[2],
+       vbuf->pitches[0], vbuf->pitches[1], vbuf->pitches[2],
+       vbuf->offsets[0], vbuf->offsets[1], vbuf->offsets[2]);
+
+   return vbuf;
+
+create_fail:
+   _e_comp_wl_video_buffer_free(vbuf);
+
+   return NULL;
+}
+
+EINTERN E_Comp_Wl_Video_Buf*
+e_comp_wl_video_buffer_alloc(int width, int height, tbm_format tbmfmt, Eina_Bool scanout)
+{
+   E_Comp_Wl_Video_Buf *vbuf = NULL;
+   tbm_surface_h tbm_surface = NULL;
+   int i;
+
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(width > 0, NULL);
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(height > 0, NULL);
+
+   vbuf = calloc(1, sizeof(E_Comp_Wl_Video_Buf));
+   EINA_SAFETY_ON_FALSE_GOTO(vbuf != NULL, alloc_fail);
+
+   vbuf->ref_cnt = 1;
+   vbuf->stamp = e_comp_wl_video_buffer_get_mills();
+   while (_find_vbuf(vbuf->stamp))
+     vbuf->stamp++;
+
+   if (scanout)
+     tbm_surface = tbm_surface_internal_create_with_flags(width, height, tbmfmt, TBM_BO_SCANOUT);
+   else
+     tbm_surface = tbm_surface_internal_create_with_flags(width, height, tbmfmt, TBM_BO_DEFAULT);
+   EINA_SAFETY_ON_NULL_GOTO(tbm_surface, alloc_fail);
+
+   vbuf->type = E_COMP_WL_VIDEO_BUF_TYPE_TBM;
+   vbuf->tbm_surface = tbm_surface;
+   tbm_surface_internal_ref(tbm_surface);
+
+   vbuf->tbmfmt = tbmfmt;
+   vbuf->width = width;
+   vbuf->height = height;
+
+   for (i = 0; i < 3; i++)
+     {
+        uint32_t size = 0, offset = 0, pitch = 0;
+        tbm_bo bo;
+
+        bo = tbm_surface_internal_get_bo(tbm_surface, i);
+        if (bo)
+          {
+             vbuf->handles[i] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32;
+             EINA_SAFETY_ON_FALSE_GOTO(vbuf->handles[i] > 0, alloc_fail);
+
+             vbuf->names[i] = tbm_bo_export(bo);
+             EINA_SAFETY_ON_FALSE_GOTO(vbuf->names[i] > 0, alloc_fail);
+          }
+
+        tbm_surface_internal_get_plane_data(tbm_surface, i, &size, &offset, &pitch);
+        vbuf->pitches[i] = pitch;
+        vbuf->offsets[i] = offset;
+     }
+
+   tdm_helper_get_buffer_full_size(tbm_surface, &vbuf->width_from_pitch, &vbuf->height_from_size);
+
+   tbm_surface_internal_unref(tbm_surface);
+
+   vbuf_lists = eina_list_append(vbuf_lists, vbuf);
+
+   BDB("type(%d) %dx%d(%dx%d) %c%c%c%c nm(%d,%d,%d) hnd(%d,%d,%d) pitch(%d,%d,%d) offset(%d,%d,%d)",
+       vbuf->type, vbuf->width_from_pitch, vbuf->height_from_size,
+       vbuf->width, vbuf->height, FOURCC_STR(vbuf->tbmfmt),
+       vbuf->names[0], vbuf->names[1], vbuf->names[2],
+       vbuf->handles[0], vbuf->handles[1], vbuf->handles[2],
+       vbuf->pitches[0], vbuf->pitches[1], vbuf->pitches[2],
+       vbuf->offsets[0], vbuf->offsets[1], vbuf->offsets[2]);
+
+   return vbuf;
+
+alloc_fail:
+   if (tbm_surface)
+     tbm_surface_internal_unref(tbm_surface);
+   _e_comp_wl_video_buffer_free(vbuf);
+   return NULL;
+}
+
+EINTERN E_Comp_Wl_Video_Buf*
+e_comp_wl_video_buffer_ref(E_Comp_Wl_Video_Buf *vbuf)
+{
+   if (!vbuf)
+     return NULL;
+
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(VBUF_IS_VALID(vbuf), NULL);
+
+   vbuf->ref_cnt++;
+   BDB("count(%d) ref", vbuf->ref_cnt);
+
+   return vbuf;
+}
+
+EINTERN void
+e_comp_wl_video_buffer_unref(E_Comp_Wl_Video_Buf *vbuf)
+{
+   if (!vbuf)
+     return;
+
+   VBUF_RETURN_IF_FAIL(e_comp_wl_video_buffer_valid(vbuf));
+
+   vbuf->ref_cnt--;
+   BDB("count(%d) unref", vbuf->ref_cnt);
+
+   if (!vbuf->buffer_destroying && vbuf->ref_cnt == 0)
+     _e_comp_wl_video_buffer_free(vbuf);
+}
+
+static void
+_e_comp_wl_video_buffer_free(E_Comp_Wl_Video_Buf *vbuf)
+{
+   VBufFreeFuncInfo *info;
+   Eina_List *l, *ll;
+
+   if (!vbuf)
+     return;
+
+   VBUF_RETURN_IF_FAIL(e_comp_wl_video_buffer_valid(vbuf));
+
+   BDB("vbuf(%p) tbm_surface(%p) freed", vbuf, vbuf->tbm_surface);
+
+   vbuf->buffer_destroying = EINA_TRUE;
+
+   if (vbuf->destroy_listener.notify)
+     {
+        wl_list_remove(&vbuf->destroy_listener.link);
+        vbuf->destroy_listener.notify = NULL;
+     }
+
+   EINA_LIST_FOREACH_SAFE(vbuf->free_funcs, l, ll, info)
+     {
+        /* call before tmb_bo_unref */
+        vbuf->free_funcs = eina_list_remove_list(vbuf->free_funcs, l);
+        if (info->func)
+          info->func(vbuf, info->data);
+        free(info);
+     }
+
+#if 0
+   /* DO not check ref_count here. Even if ref_count is not 0, vbuf can be
+    * be destroyed by wl_buffer_destroy forcely. video or screenmirror should add
+    * the vbuf free function and handle the destroying vbuf situation.
+    */
+   if (!vbuf->buffer_destroying)
+     VBUF_RETURN_IF_FAIL(vbuf->ref_cnt == 0);
+#endif
+
+   /* make sure all operation is done */
+   VBUF_RETURN_IF_FAIL(vbuf->in_use == EINA_FALSE);
+
+   if (vbuf->type == E_COMP_WL_VIDEO_BUF_TYPE_TBM && vbuf->tbm_surface)
+     {
+        tbm_surface_internal_unref(vbuf->tbm_surface);
+        vbuf->tbm_surface = NULL;
+     }
+
+   vbuf_lists = eina_list_remove(vbuf_lists, vbuf);
+
+   vbuf->stamp = 0;
+
+   free(vbuf);
+}
+
+static void
+_e_comp_wl_video_buffer_cb_destroy(struct wl_listener *listener, void *data)
+{
+   E_Comp_Wl_Video_Buf *vbuf = container_of(listener, E_Comp_Wl_Video_Buf, destroy_listener);
+
+   if (!vbuf) return;
+
+   vbuf->comp_buffer = NULL;
+
+   if (vbuf->buffer_destroying == EINA_FALSE)
+     {
+        vbuf->destroy_listener.notify = NULL;
+        _e_comp_wl_video_buffer_free(vbuf);
+     }
+}
+
+EINTERN void
+e_comp_wl_video_buffer_clear(E_Comp_Wl_Video_Buf *vbuf)
+{
+   EINA_SAFETY_ON_NULL_RETURN(vbuf);
+
+   if (!_e_comp_wl_video_buffer_access_data_begin(vbuf))
+     {
+        BER("can't access ptr");
+        return;
+     }
+
+   switch(vbuf->tbmfmt)
+     {
+      case TBM_FORMAT_ARGB8888:
+      case TBM_FORMAT_XRGB8888:
+         memset(vbuf->ptrs[0], 0, vbuf->pitches[0] * vbuf->height);
+         break;
+      case TBM_FORMAT_YVU420:
+      case TBM_FORMAT_YUV420:
+         memset((char*)vbuf->ptrs[0] + vbuf->offsets[0], 0x10, vbuf->pitches[0] * vbuf->height);
+         memset((char*)vbuf->ptrs[1] + vbuf->offsets[1], 0x80, vbuf->pitches[1] * (vbuf->height >> 1));
+         memset((char*)vbuf->ptrs[2] + vbuf->offsets[2], 0x80, vbuf->pitches[2] * (vbuf->height >> 1));
+         break;
+      case TBM_FORMAT_NV12:
+      case TBM_FORMAT_NV21:
+         memset((char*)vbuf->ptrs[0] + vbuf->offsets[0], 0x10, vbuf->pitches[0] * vbuf->height);
+         memset((char*)vbuf->ptrs[1] + vbuf->offsets[1], 0x80, vbuf->pitches[1] * (vbuf->height >> 1));
+         break;
+      case TBM_FORMAT_YUYV:
+           {
+              int *ibuf = (int*)vbuf->ptrs[0];
+              int i, size = vbuf->pitches[0] * vbuf->height / 4;
+
+              for (i = 0 ; i < size ; i++)
+                ibuf[i] = 0x10801080;
+           }
+         break;
+      case TBM_FORMAT_UYVY:
+           {
+              int *ibuf = (int*)vbuf->ptrs[0];
+              int i, size = vbuf->pitches[0] * vbuf->height / 4;
+
+              for (i = 0 ; i < size ; i++)
+                ibuf[i] = 0x80108010; /* YUYV -> 0xVYUY */
+           }
+         break;
+      default:
+         BWR("can't clear %c%c%c%c buffer", FOURCC_STR(vbuf->tbmfmt));
+         break;
+     }
+
+   _e_comp_wl_video_buffer_access_data_end(vbuf);
+}
+
+EINTERN Eina_Bool
+e_comp_wl_video_buffer_valid(E_Comp_Wl_Video_Buf *vbuf)
+{
+   E_Comp_Wl_Video_Buf *temp;
+   Eina_List *l;
+
+   VBUF_RETURN_VAL_IF_FAIL(vbuf != NULL, EINA_FALSE);
+   VBUF_RETURN_VAL_IF_FAIL(vbuf->stamp != 0, EINA_FALSE);
+
+   EINA_LIST_FOREACH(vbuf_lists, l, temp)
+     {
+        if (temp->stamp == vbuf->stamp)
+          return EINA_TRUE;
+     }
+
+   BDB("vbuf(%p) invalid", vbuf);
+
+   return EINA_FALSE;
+}
+
+static VBufFreeFuncInfo*
+_e_comp_wl_video_buffer_free_func_find(E_Comp_Wl_Video_Buf *vbuf, VBuf_Free_Func func, void *data)
+{
+   VBufFreeFuncInfo *info;
+   Eina_List *l;
+
+   EINA_LIST_FOREACH(vbuf->free_funcs, l, info)
+     {
+        if (info->func == func && info->data == data)
+          return info;
+     }
+
+   return NULL;
+}
+
+EINTERN void
+e_comp_wl_video_buffer_free_func_add(E_Comp_Wl_Video_Buf *vbuf, VBuf_Free_Func func, void *data)
+{
+   VBufFreeFuncInfo *info;
+
+   EINA_SAFETY_ON_FALSE_RETURN(VBUF_IS_VALID(vbuf));
+   EINA_SAFETY_ON_NULL_RETURN(func);
+
+   info = _e_comp_wl_video_buffer_free_func_find(vbuf, func, data);
+   if (info)
+     return;
+
+   info = calloc(1, sizeof(VBufFreeFuncInfo));
+   EINA_SAFETY_ON_NULL_RETURN(info);
+
+   info->func = func;
+   info->data = data;
+
+   vbuf->free_funcs = eina_list_append(vbuf->free_funcs, info);
+}
+
+EINTERN void
+e_comp_wl_video_buffer_free_func_del(E_Comp_Wl_Video_Buf *vbuf, VBuf_Free_Func func, void *data)
+{
+   VBufFreeFuncInfo *info;
+
+   EINA_SAFETY_ON_FALSE_RETURN(VBUF_IS_VALID(vbuf));
+   EINA_SAFETY_ON_NULL_RETURN(func);
+
+   info = _e_comp_wl_video_buffer_free_func_find(vbuf, func, data);
+   if (!info)
+     return;
+
+   vbuf->free_funcs = eina_list_remove(vbuf->free_funcs, info);
+
+   free(info);
+}
+
+static pixman_format_code_t
+_e_comp_wl_video_buffer_pixman_format_get(E_Comp_Wl_Video_Buf *vbuf)
+{
+   switch(vbuf->tbmfmt)
+     {
+      case TBM_FORMAT_ARGB8888: return PIXMAN_a8r8g8b8;
+      case TBM_FORMAT_XRGB8888: return PIXMAN_x8r8g8b8;
+      default:                  return 0;
+     }
+   return 0;
+}
+
+EINTERN void
+e_comp_wl_video_buffer_convert(E_Comp_Wl_Video_Buf *srcbuf, E_Comp_Wl_Video_Buf *dstbuf,
+                               int sx, int sy, int sw, int sh,
+                               int dx, int dy, int dw, int dh,
+                               Eina_Bool over, int rotate, int hflip, int vflip)
+{
+   pixman_image_t *src_img = NULL, *dst_img = NULL;
+   pixman_format_code_t src_format, dst_format;
+   double scale_x, scale_y;
+   int rotate_step;
+   pixman_transform_t t;
+   struct pixman_f_transform ft;
+   pixman_op_t op;
+   int src_stride, dst_stride;
+   int buf_width;
+
+   EINA_SAFETY_ON_FALSE_RETURN(VBUF_IS_VALID(srcbuf));
+   EINA_SAFETY_ON_FALSE_RETURN(VBUF_IS_VALID(dstbuf));
+
+   if (!_e_comp_wl_video_buffer_access_data_begin(srcbuf))
+     return;
+   if (!_e_comp_wl_video_buffer_access_data_begin(dstbuf))
+     {
+        _e_comp_wl_video_buffer_access_data_end(srcbuf);
+        return;
+     }
+
+   /* not handle buffers which have 2 more gem handles */
+   EINA_SAFETY_ON_NULL_GOTO(srcbuf->ptrs[0], cant_convert);
+   EINA_SAFETY_ON_NULL_GOTO(dstbuf->ptrs[0], cant_convert);
+   EINA_SAFETY_ON_FALSE_RETURN(!srcbuf->ptrs[1]);
+   EINA_SAFETY_ON_FALSE_RETURN(!dstbuf->ptrs[1]);
+
+   src_format = _e_comp_wl_video_buffer_pixman_format_get(srcbuf);
+   EINA_SAFETY_ON_FALSE_GOTO(src_format > 0, cant_convert);
+   dst_format = _e_comp_wl_video_buffer_pixman_format_get(dstbuf);
+   EINA_SAFETY_ON_FALSE_GOTO(dst_format > 0, cant_convert);
+
+   buf_width = IS_RGB(srcbuf->tbmfmt)?(srcbuf->pitches[0]/4):srcbuf->pitches[0];
+   src_stride = IS_RGB(srcbuf->tbmfmt)?(srcbuf->pitches[0]):buf_width * (PIXMAN_FORMAT_BPP(src_format) / 8);
+   src_img = pixman_image_create_bits(src_format, buf_width, srcbuf->height,
+                                      (uint32_t*)srcbuf->ptrs[0], src_stride);
+   EINA_SAFETY_ON_NULL_GOTO(src_img, cant_convert);
+
+   buf_width = IS_RGB(dstbuf->tbmfmt)?(dstbuf->pitches[0]/4):dstbuf->pitches[0];
+   dst_stride = IS_RGB(srcbuf->tbmfmt)?(dstbuf->pitches[0]):buf_width * (PIXMAN_FORMAT_BPP(dst_format) / 8);
+   dst_img = pixman_image_create_bits(dst_format, buf_width, dstbuf->height,
+                                      (uint32_t*)dstbuf->ptrs[0], dst_stride);
+   EINA_SAFETY_ON_NULL_GOTO(dst_img, cant_convert);
+
+   pixman_f_transform_init_identity(&ft);
+
+   if (hflip)
+     {
+        pixman_f_transform_scale(&ft, NULL, -1, 1);
+        pixman_f_transform_translate(&ft, NULL, dw, 0);
+     }
+
+   if (vflip)
+     {
+        pixman_f_transform_scale(&ft, NULL, 1, -1);
+        pixman_f_transform_translate(&ft, NULL, 0, dh);
+     }
+
+   rotate_step = (rotate + 360) / 90 % 4;
+   if (rotate_step > 0)
+     {
+        int c, s, tx = 0, ty = 0;
+        switch (rotate_step)
+          {
+           case 1:
+              c = 0, s = -1, tx = -dw;
+              break;
+           case 2:
+              c = -1, s = 0, tx = -dw, ty = -dh;
+              break;
+           case 3:
+              c = 0, s = 1, ty = -dh;
+              break;
+          }
+        pixman_f_transform_translate(&ft, NULL, tx, ty);
+        pixman_f_transform_rotate(&ft, NULL, c, s);
+     }
+
+   if (rotate_step % 2 == 0)
+     {
+        scale_x = (double)sw / dw;
+        scale_y = (double)sh / dh;
+     }
+   else
+     {
+        scale_x = (double)sw / dh;
+        scale_y = (double)sh / dw;
+     }
+
+   pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
+   pixman_f_transform_translate(&ft, NULL, sx, sy);
+   pixman_transform_from_pixman_f_transform(&t, &ft);
+   pixman_image_set_transform(src_img, &t);
+
+   if (!over) op = PIXMAN_OP_SRC;
+   else op = PIXMAN_OP_OVER;
+
+   pixman_image_composite(op, src_img, NULL, dst_img, 0, 0, 0, 0,
+                          dx, dy, dw, dh);
+cant_convert:
+   if (src_img) pixman_image_unref(src_img);
+   if (dst_img) pixman_image_unref(dst_img);
+
+   _e_comp_wl_video_buffer_access_data_end(srcbuf);
+   _e_comp_wl_video_buffer_access_data_end(dstbuf);
+}
+
+EINTERN Eina_Bool
+e_comp_wl_video_buffer_copy(E_Comp_Wl_Video_Buf *srcbuf, E_Comp_Wl_Video_Buf *dstbuf)
+{
+   int i, j, c_height;
+   unsigned char *s, *d;
+
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(VBUF_IS_VALID(srcbuf), EINA_FALSE);
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(VBUF_IS_VALID(dstbuf), EINA_FALSE);
+
+   if (!_e_comp_wl_video_buffer_access_data_begin(srcbuf))
+     return EINA_FALSE;
+   if (!_e_comp_wl_video_buffer_access_data_begin(dstbuf))
+     {
+        _e_comp_wl_video_buffer_access_data_end(srcbuf);
+        return EINA_FALSE;
+     }
+
+   switch (srcbuf->tbmfmt)
+     {
+      case TBM_FORMAT_ARGB8888:
+      case TBM_FORMAT_XRGB8888:
+      case TBM_FORMAT_YUV422:
+      case TBM_FORMAT_YVU422:
+         s = (unsigned char*)srcbuf->ptrs[0];
+         d = (unsigned char*)dstbuf->ptrs[0];
+         for (i = 0; i < srcbuf->height; i++)
+           {
+              memcpy(d, s, srcbuf->pitches[0]);
+              s += srcbuf->pitches[0];
+              d += dstbuf->pitches[0];
+           }
+         break;
+      case TBM_FORMAT_YUV420:
+      case TBM_FORMAT_YVU420:
+         for (i = 0; i < 3; i++)
+           {
+              s = (unsigned char*)srcbuf->ptrs[i] + srcbuf->offsets[i];
+              d = (unsigned char*)dstbuf->ptrs[i] + dstbuf->offsets[i];
+              c_height = (i == 0) ? srcbuf->height : srcbuf->height / 2;
+              for (j = 0; j < c_height; j++)
+                {
+                   memcpy(d, s, srcbuf->pitches[i]);
+                   s += srcbuf->pitches[i];
+                   d += dstbuf->pitches[i];
+                }
+           }
+         break;
+      case TBM_FORMAT_NV12:
+      case TBM_FORMAT_NV21:
+         for (i = 0; i < 2; i++)
+           {
+              s = (unsigned char*)srcbuf->ptrs[i] + srcbuf->offsets[i];
+              d = (unsigned char*)dstbuf->ptrs[i] + dstbuf->offsets[i];
+              c_height = (i == 0) ? srcbuf->height : srcbuf->height / 2;
+              for (j = 0; j < c_height; j++)
+                {
+                   memcpy(d, s, srcbuf->pitches[i]);
+                   s += srcbuf->pitches[i];
+                   d += dstbuf->pitches[i];
+                }
+           }
+         break;
+      default:
+         ERR("not implemented for %c%c%c%c", FOURCC_STR(srcbuf->tbmfmt));
+         _e_comp_wl_video_buffer_access_data_end(srcbuf);
+         _e_comp_wl_video_buffer_access_data_end(dstbuf);
+
+         return EINA_FALSE;
+     }
+
+   _e_comp_wl_video_buffer_access_data_end(srcbuf);
+   _e_comp_wl_video_buffer_access_data_end(dstbuf);
+
+   return EINA_TRUE;
+}
+
+EINTERN uint
+e_comp_wl_video_buffer_get_mills(void)
+{
+   struct timespec tp;
+
+   clock_gettime(CLOCK_MONOTONIC, &tp);
+
+   return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
+}
+
+EINTERN int
+e_comp_wl_video_buffer_list_length(void)
+{
+   return eina_list_count(vbuf_lists);
+}
+
+EINTERN void
+e_comp_wl_video_buffer_list_print(const char *log_path)
+{
+   E_Comp_Wl_Video_Buf *vbuf;
+   Eina_List *l;
+   FILE *log_fl;
+
+   log_fl = fopen(log_path, "a");
+   if (!log_fl)
+     {
+        ERR("failed: open file(%s)", log_path);
+        return;
+     }
+
+   setvbuf(log_fl, NULL, _IOLBF, 512);
+
+   fprintf(log_fl, "* Video Buffers:\n");
+   fprintf(log_fl, "stamp\tsize\tformat\thandles\tpitches\toffsets\tin_use\n");
+   EINA_LIST_FOREACH(vbuf_lists, l, vbuf)
+     {
+        fprintf(log_fl, "%d\t%dx%d\t%c%c%c%c\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d\t%d\n",
+                vbuf->stamp, vbuf->width, vbuf->height, FOURCC_STR(vbuf->tbmfmt),
+                vbuf->handles[0], vbuf->handles[1], vbuf->handles[2],
+                vbuf->pitches[0], vbuf->pitches[1], vbuf->pitches[2],
+                vbuf->offsets[0], vbuf->offsets[1], vbuf->offsets[2],
+                vbuf->in_use);
+     }
+
+   fclose(log_fl);
+}
+
+EINTERN void
+e_comp_wl_video_buffer_size_get(E_Client *ec, int *bw, int *bh)
+{
+   E_Comp_Wl_Buffer *buffer = e_pixmap_resource_get(ec->pixmap);
+
+   if (bw) *bw = 0;
+   if (bh) *bh = 0;
+
+   if (!buffer)
+     {
+        INF("no buffer. using ec(%p) size(%dx%d)", ec, ec->w, ec->h);
+        if (bw) *bw = ec->w;
+        if (bh) *bh = ec->h;
+        return;
+     }
+
+   if (buffer->type == E_COMP_WL_BUFFER_TYPE_VIDEO)
+     {
+        tbm_surface_h tbm_surface = wayland_tbm_server_get_surface(NULL, buffer->resource);
+
+        if (bw) *bw = tbm_surface_get_width(tbm_surface);
+        if (bh) *bh = tbm_surface_get_height(tbm_surface);
+     }
+   else
+     {
+        if (bw) *bw = buffer->w;
+        if (bh) *bh = buffer->h;
+     }
+}
+
+EINTERN void
+e_comp_wl_video_buffer_transform_scale_size_get(E_Client *ec, int *bw, int *bh)
+{
+   E_Comp_Wl_Buffer *buffer = e_pixmap_resource_get(ec->pixmap);
+   E_Comp_Wl_Buffer_Viewport *vp = &ec->comp_data->scaler.buffer_viewport;
+   int w, h, transform;
+
+   if (bw) *bw = 0;
+   if (bh) *bh = 0;
+
+   if (!buffer)
+     {
+        INF("no buffer. using ec(%p) size(%dx%d)", ec, ec->w, ec->h);
+        if (bw) *bw = ec->w;
+        if (bh) *bh = ec->h;
+        return;
+     }
+
+   if (buffer->type == E_COMP_WL_BUFFER_TYPE_VIDEO)
+     {
+        tbm_surface_h tbm_surface = wayland_tbm_server_get_surface(NULL, buffer->resource);
+
+        w = tbm_surface_get_width(tbm_surface);
+        h = tbm_surface_get_height(tbm_surface);
+     }
+   else
+     {
+        w = buffer->w;
+        h = buffer->h;
+     }
+
+   transform = e_comp_wl_output_buffer_transform_get(ec);
+
+   switch (transform)
+     {
+      case WL_OUTPUT_TRANSFORM_90:
+      case WL_OUTPUT_TRANSFORM_270:
+      case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+      case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+         if (bw) *bw = h / vp->buffer.scale;
+         if (bh) *bh = w / vp->buffer.scale;
+         break;
+      default:
+         if (bw) *bw = w / vp->buffer.scale;
+         if (bh) *bh = h / vp->buffer.scale;
+         break;
+     }
+}
diff --git a/src/bin/video/e_comp_wl_video_buffer.h b/src/bin/video/e_comp_wl_video_buffer.h
new file mode 100644 (file)
index 0000000..c2d980e
--- /dev/null
@@ -0,0 +1,96 @@
+#ifdef E_TYPEDEFS
+
+typedef enum _E_Comp_Wl_Video_Buf_Type
+{
+   E_COMP_WL_VIDEO_BUF_TYPE_SHM,
+   E_COMP_WL_VIDEO_BUF_TYPE_TBM,
+} E_Comp_Wl_Video_Buf_Type;
+
+typedef struct _E_Comp_Wl_Video_Buf E_Comp_Wl_Video_Buf;
+
+#else
+#ifndef E_COMP_WL_VIDEO_BUFFER_H
+#define E_COMP_WL_VIDEO_BUFFER_H
+
+#include "e_comp_wl_tbm.h"
+
+struct _E_Comp_Wl_Video_Buf
+{
+   /* to manage lifecycle */
+   uint ref_cnt;
+
+   /* to check valid */
+   uint stamp;
+
+   /* to manage wl_resource */
+   struct wl_resource *resource;
+   struct wl_listener destroy_listener;
+
+   Eina_Bool buffer_destroying;
+
+   E_Comp_Wl_Video_Buf_Type type;
+   tbm_surface_h tbm_surface;
+
+   /* pitch contains the full buffer width.
+    * width indicates the content area width.
+    */
+   tbm_format tbmfmt;
+   int width;
+   int height;
+   uint handles[4];
+   uint pitches[4];
+   uint offsets[4];
+   int names[4];
+   void *ptrs[4];
+
+   int width_from_pitch;
+   int height_from_size;
+
+   /* to avoid reading & write at same time */
+   Eina_Bool in_use;
+
+   Eina_List *free_funcs;
+
+   /* for wl_buffer.release event */
+   E_Comp_Wl_Buffer *comp_buffer;
+   E_Comp_Wl_Buffer_Ref buffer_ref;
+   Eina_Rectangle content_r;        /* content rect */
+   unsigned int content_t;          /* content transform */
+};
+
+EINTERN E_Comp_Wl_Video_Buf* e_comp_wl_video_buffer_create(struct wl_resource *resource);
+EINTERN E_Comp_Wl_Video_Buf* e_comp_wl_video_buffer_create_comp(E_Comp_Wl_Buffer *comp_buffer);
+EINTERN E_Comp_Wl_Video_Buf* e_comp_wl_video_buffer_create_tbm(tbm_surface_h tbm_surface);
+EINTERN E_Comp_Wl_Video_Buf* e_comp_wl_video_buffer_alloc(int width, int height, tbm_format tbmfmt, Eina_Bool scanout);
+EINTERN E_Comp_Wl_Video_Buf* e_comp_wl_video_buffer_ref(E_Comp_Wl_Video_Buf *vbuf);
+EINTERN void          e_comp_wl_video_buffer_unref(E_Comp_Wl_Video_Buf *vbuf);
+EINTERN Eina_Bool     e_comp_wl_video_buffer_valid(E_Comp_Wl_Video_Buf *vbuf);
+
+#define VBUF_IS_VALID(b)   e_comp_wl_video_buffer_valid(b)
+#define MSTAMP(b)          ((b)?(b)->stamp:0)
+
+#define e_comp_wl_video_buffer_set_use(b, v)    \
+   do { \
+      if (b) b->in_use = v; \
+   } while (0)
+
+typedef void (*VBuf_Free_Func) (E_Comp_Wl_Video_Buf *vbuf, void *data);
+EINTERN void e_comp_wl_video_buffer_free_func_add(E_Comp_Wl_Video_Buf *vbuf, VBuf_Free_Func func, void *data);
+EINTERN void e_comp_wl_video_buffer_free_func_del(E_Comp_Wl_Video_Buf *vbuf, VBuf_Free_Func func, void *data);
+
+EINTERN void e_comp_wl_video_buffer_clear(E_Comp_Wl_Video_Buf *vbuf);
+EINTERN Eina_Bool e_comp_wl_video_buffer_copy(E_Comp_Wl_Video_Buf *srcbuf, E_Comp_Wl_Video_Buf *dstbuf);
+EINTERN void e_comp_wl_video_buffer_convert(E_Comp_Wl_Video_Buf *srcbuf, E_Comp_Wl_Video_Buf *dstbuf,
+                                            int sx, int sy, int sw, int sh,
+                                            int dx, int dy, int dw, int dh,
+                                            Eina_Bool over, int rotate, int hflip, int vflip);
+
+EINTERN uint e_comp_wl_video_buffer_get_mills(void);
+EINTERN int  e_comp_wl_video_buffer_list_length(void);
+EINTERN void e_comp_wl_video_buffer_list_print(const char *log_path);
+
+EINTERN void e_comp_wl_video_buffer_size_get(E_Client *ec, int *bw, int *bh);
+EINTERN void e_comp_wl_video_buffer_transform_scale_size_get(E_Client *ec, int *bw, int *bh);
+
+#endif
+#endif
diff --git a/src/bin/video/e_video_debug.c b/src/bin/video/e_video_debug.c
new file mode 100644 (file)
index 0000000..d0d84cf
--- /dev/null
@@ -0,0 +1,28 @@
+#include "e_video_internal.h"
+
+static Eina_Bool video_to_primary = EINA_FALSE;
+static Eina_Bool video_punch = EINA_FALSE;
+
+EINTERN Eina_Bool
+e_video_debug_display_primary_plane_value_get(void)
+{
+   return video_to_primary;
+}
+
+EINTERN void
+e_video_debug_display_primary_plane_set(Eina_Bool set)
+{
+   video_to_primary = set;
+}
+
+EINTERN Eina_Bool
+e_video_debug_punch_value_get(void)
+{
+   return video_punch;
+}
+
+EINTERN void
+e_video_debug_punch_set(Eina_Bool set)
+{
+   video_punch = set;
+}
diff --git a/src/bin/video/e_video_debug.h b/src/bin/video/e_video_debug.h
new file mode 100644 (file)
index 0000000..5c75d38
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _E_VIDEO_DEBUG_H_
+#define _E_VIDEO_DEBUG_H_
+
+#include <Eina.h>
+
+EINTERN Eina_Bool   e_video_debug_display_primary_plane_value_get(void);
+EINTERN void        e_video_debug_display_primary_plane_set(Eina_Bool set);
+EINTERN Eina_Bool   e_video_debug_punch_value_get(void);
+EINTERN void        e_video_debug_punch_set(Eina_Bool set);
+
+#endif
diff --git a/src/bin/video/e_video_internal.h b/src/bin/video/e_video_internal.h
new file mode 100644 (file)
index 0000000..de39dc1
--- /dev/null
@@ -0,0 +1,77 @@
+#ifndef _E_VIDEO_INTERNAL_H_
+#define _E_VIDEO_INTERNAL_H_
+
+#include "e.h"
+
+#include "e_video_debug.h"
+#include "e_zone_video.h"
+#include "e_comp_wl_video_buffer.h"
+
+#include <tdm.h>
+#include <values.h>
+#include <tdm_helper.h>
+#include <tbm_surface.h>
+#include <wayland-tbm-server.h>
+
+#ifdef VER
+# undef VER
+#endif
+
+#ifdef VWR
+# undef VWR
+#endif
+
+#ifdef VIN
+# undef VIN
+#endif
+
+#ifdef VDB
+# undef VDB
+#endif
+
+#ifdef DET
+# undef DET
+#endif
+
+#ifdef VDT
+# undef VDT
+#endif
+
+#define VER(fmt, arg...)   ELOGF("VIDEO", "<ERR> window(0x%08"PRIxPTR"): "fmt, \
+                                 evhp->ec->pixmap, evhp->ec, evhp->window, ##arg)
+#define VWR(fmt, arg...)   ELOGF("VIDEO", "<WRN> window(0x%08"PRIxPTR"): "fmt, \
+                                 evhp->ec->pixmap, evhp->ec, evhp->window, ##arg)
+#define VIN(fmt, arg...)   ELOGF("VIDEO", "<INF> window(0x%08"PRIxPTR"): "fmt, \
+                                 evhp->ec->pixmap, evhp->ec, evhp->window, ##arg)
+#define VDB(fmt, arg...)   DBG("window(0x%08"PRIxPTR") ec(%p): "fmt, evhp->window, evhp->ec, ##arg)
+
+#define GEO_FMT   "%dx%d(%dx%d+%d+%d) -> (%dx%d+%d+%d) transform(%d)"
+#define GEO_ARG(g) \
+   (g)->input_w, (g)->input_h, \
+   (g)->input_r.w, (g)->input_r.h, (g)->input_r.x, (g)->input_r.y, \
+   (g)->output_r.w, (g)->output_r.h, (g)->output_r.x, (g)->output_r.y, \
+   (g)->transform
+
+typedef struct _E_Video_Comp_Iface E_Video_Comp_Iface;
+
+struct _E_Video_Comp_Iface
+{
+   void            (*destroy)(E_Video_Comp_Iface *iface);
+   Eina_Bool       (*follow_topmost_visibility)(E_Video_Comp_Iface *iface);
+   Eina_Bool       (*unfollow_topmost_visibility)(E_Video_Comp_Iface *iface);
+   Eina_Bool       (*allowed_property)(E_Video_Comp_Iface *iface);
+   Eina_Bool       (*disallowed_property)(E_Video_Comp_Iface *iface);
+   Eina_Bool       (*property_get)(E_Video_Comp_Iface *iface, unsigned int id, tdm_value *value);
+   Eina_Bool       (*property_set)(E_Video_Comp_Iface *iface, unsigned int id, tdm_value value);
+   Eina_Bool       (*property_delay_set)(E_Video_Comp_Iface *iface, unsigned int id, tdm_value value);
+   Eina_Bool       (*available_properties_get)(E_Video_Comp_Iface *iface, const tdm_prop **props, int *count);
+   /* FIXME for hwc windows mode */
+   Eina_Bool       (*info_get)(E_Video_Comp_Iface *iface, E_Client_Video_Info *info);
+   Eina_Bool       (*commit_data_release)(E_Video_Comp_Iface *iface, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec);
+   tbm_surface_h   (*tbm_surface_get)(E_Video_Comp_Iface *iface);
+};
+
+EINTERN E_Video_Comp_Iface  *e_video_hwc_planes_iface_create(E_Client *ec);
+EINTERN E_Video_Comp_Iface  *e_video_fallback_iface_create(E_Client *ec);
+
+#endif
diff --git a/src/bin/video/e_zone_video.c b/src/bin/video/e_zone_video.c
new file mode 100644 (file)
index 0000000..6c55b85
--- /dev/null
@@ -0,0 +1,89 @@
+#include "e_video_internal.h"
+
+static int
+gcd(int a, int b)
+{
+   if (a % b == 0)
+     return b;
+   return gcd(b, a % b);
+}
+
+static int
+lcm(int a, int b)
+{
+   return a * b / gcd(a, b);
+}
+
+EINTERN Eina_Bool
+e_zone_video_available_size_get(E_Zone *zone, int *minw, int *minh, int *maxw, int *maxh, int *align)
+{
+   E_Output *output;
+   int ominw = -1, ominh = -1, omaxw = -1, omaxh = -1, oalign = -1;
+   int pminw = -1, pminh = -1, pmaxw = -1, pmaxh = -1, palign = -1;
+   int rminw = -1, rminh = -1, rmaxw = -1, rmaxh = -1, ralign = -1;
+
+   output = e_output_find(zone->output_id);
+
+   tdm_output_get_available_size(output->toutput, &ominw, &ominh, &omaxw, &omaxh, &oalign);
+   if (!e_comp_screen_pp_support())
+     {
+        rminw = ominw;
+        rminh = ominh;
+        rmaxw = omaxw;
+        rmaxh = omaxh;
+        ralign = oalign;
+
+        goto end;
+     }
+   else
+     {
+        tdm_display_get_pp_available_size(e_comp->e_comp_screen->tdisplay,
+                                          &pminw, &pminh, &pmaxw, &pmaxh,
+                                          &palign);
+
+        rminw = MAX(ominw, pminw);
+        rminh = MAX(ominh, pminh);
+
+        if (omaxw != -1 && pmaxw == -1)
+          rmaxw = omaxw;
+        else if (omaxw == -1 && pmaxw != -1)
+          rmaxw = pmaxw;
+        else
+          rmaxw = MIN(omaxw, pmaxw);
+
+        if (omaxh != -1 && pmaxh == -1)
+          rmaxh = omaxh;
+        else if (omaxh == -1 && pmaxh != -1)
+          rmaxh = pmaxh;
+        else
+          rmaxh = MIN(omaxh, pmaxh);
+
+        if (oalign != -1 && palign == -1)
+          ralign = oalign;
+        else if (oalign == -1 && palign != -1)
+          ralign = palign;
+        else if (oalign == -1 && palign == -1)
+          ralign = palign;
+        else if (oalign > 0 && palign > 0)
+          ralign = lcm(oalign, palign);
+        else
+          {
+             // ERR("invalid align: %d, %d", video->output_align, video->pp_align);
+             return EINA_FALSE;
+          }
+
+        /*
+           VIN("align width: output(%d) pp(%d) video(%d)",
+           video->output_align, video->pp_align, video->video_align);
+           */
+     }
+
+end:
+   if (minw) *minw = rminw;
+   if (minh) *minh = rminh;
+   if (maxw) *maxw = rmaxw;
+   if (maxw) *maxh = rmaxh;
+   if (align) *align = ralign;
+
+   return EINA_TRUE;
+}
diff --git a/src/bin/video/e_zone_video.h b/src/bin/video/e_zone_video.h
new file mode 100644 (file)
index 0000000..76ef856
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _E_ZONE_VIDEO_H_
+#define _E_ZONE_VIDEO_H_
+
+EINTERN Eina_Bool    e_zone_video_available_size_get(E_Zone *zone, int *minw, int *minh, int *maxw, int *maxh, int *align);
+
+#endif
diff --git a/src/bin/video/iface/e_video_fallback.c b/src/bin/video/iface/e_video_fallback.c
new file mode 100644 (file)
index 0000000..5436824
--- /dev/null
@@ -0,0 +1,53 @@
+#include "../e_video_internal.h"
+
+typedef struct _E_Video_Fallback E_Video_Fallback;
+
+struct _E_Video_Fallback
+{
+   E_Video_Comp_Iface base;
+   E_Client *ec;
+};
+
+static void
+_e_video_fallback_iface_destroy(E_Video_Comp_Iface *iface)
+{
+   E_Video_Fallback *evs;
+
+   evs = container_of(iface, E_Video_Fallback, base);
+
+   /* Unset animatable lock */
+   e_policy_animatable_lock(evs->ec, E_POLICY_ANIMATABLE_NEVER, 0);
+
+   free(evs);
+}
+
+static void
+_e_video_fallback_init(E_Client *ec)
+{
+   /* software compositing */
+   ec->comp_data->video_client = 0;
+   /* Set animatable lock */
+   e_policy_animatable_lock(ec, E_POLICY_ANIMATABLE_NEVER, 1);
+}
+
+EINTERN E_Video_Comp_Iface *
+e_video_fallback_iface_create(E_Client *ec)
+{
+   E_Video_Fallback *evs;
+
+   INF("Intializing SW Compositing mode");
+
+   evs = E_NEW(E_Video_Fallback, 1);
+   if (!evs)
+     {
+        ERR("Failed to create E_Video_Fallback");
+        return NULL;
+     }
+
+   _e_video_fallback_init(ec);
+
+   evs->ec = ec;
+   evs->base.destroy = _e_video_fallback_iface_destroy;
+
+   return &evs->base;
+}
diff --git a/src/bin/video/iface/e_video_hwc_planes.c b/src/bin/video/iface/e_video_hwc_planes.c
new file mode 100644 (file)
index 0000000..6dffbe6
--- /dev/null
@@ -0,0 +1,2805 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "../e_video_internal.h"
+
+//#define DUMP_BUFFER
+#define CHECKING_PRIMARY_ZPOS
+
+#define BUFFER_MAX_COUNT   5
+#define MIN_WIDTH   32
+
+#undef NEVER_GET_HERE
+#define NEVER_GET_HERE()     CRI("** need to improve more **")
+
+#ifndef CLEAR
+#define CLEAR(x) memset(&(x), 0, sizeof(x))
+#endif
+
+#define IFACE_ENTRY                                      \
+   E_Video_Hwc_Planes *evhp;                              \
+   evhp = container_of(iface, E_Video_Hwc_Planes, base)
+
+typedef struct _E_Video_Hwc_Planes E_Video_Hwc_Planes;
+typedef struct _E_Video_Layer E_Video_Layer;
+typedef struct _E_Video_Info_Layer E_Video_Info_Layer;
+
+/* the new TDM API doesn't have layers, so we have to invent layer here*/
+struct _E_Video_Layer
+{
+   E_Video_Hwc_Planes *evhp;
+
+   tdm_layer *tdm_layer;
+
+   /* for hwc_window */
+   E_Client_Video_Info info;
+   tbm_surface_h cur_tsurface; // tsurface to be set this layer.
+   E_Client *e_client;
+};
+
+struct _E_Video_Hwc_Planes
+{
+   E_Video_Comp_Iface base;
+
+   E_Client *ec;
+   Ecore_Window window;
+   tdm_output *output;
+   E_Output *e_output;
+   E_Video_Layer *layer;
+   E_Plane *e_plane;
+   Eina_Bool external_video;
+
+   Eina_List *ec_event_handler;
+
+   /* input info */
+   tbm_format tbmfmt;
+   Eina_List *input_buffer_list;
+
+   /* in screen coordinates */
+   struct
+     {
+        int input_w, input_h;    /* input buffer's size */
+        Eina_Rectangle input_r;  /* input buffer's content rect */
+        Eina_Rectangle output_r; /* video plane rect */
+        uint transform;          /* rotate, flip */
+
+        Eina_Rectangle tdm_output_r; /* video plane rect in physical output coordinates */
+        uint tdm_transform;          /* rotate, flip in physical output coordinates */
+     } geo, old_geo;
+
+   E_Comp_Wl_Buffer *old_comp_buffer;
+
+   /* converter info */
+   tbm_format pp_tbmfmt;
+   tdm_pp *pp;
+   Eina_Rectangle pp_r;    /* converter dst content rect */
+   Eina_List *pp_buffer_list;
+   Eina_List *next_buffer;
+   Eina_Bool pp_scanout;
+
+   int pp_align;
+   int pp_minw, pp_minh, pp_maxw, pp_maxh;
+   int video_align;
+
+   /* When a video buffer be attached, it will be appended to the end of waiting_list .
+    * And when it's committed, it will be moved to committed_list.
+    * Finally when the commit handler is called, it will become current_fb.
+    */
+   Eina_List    *waiting_list;   /* buffers which are not committed yet */
+   Eina_List    *committed_list; /* buffers which are committed, but not shown on screen yet */
+   E_Comp_Wl_Video_Buf *current_fb;     /* buffer which is showing on screen currently */
+   Eina_Bool     waiting_vblank;
+
+   /* attributes */
+   Eina_List *tdm_prop_list;
+   Eina_List *late_tdm_prop_list;
+   int tdm_mute_id;
+
+   Eina_Bool  cb_registered;
+   Eina_Bool  need_force_render;
+   Eina_Bool  follow_topmost_visibility;
+   Eina_Bool  allowed_attribute;
+
+   E_Plane_Hook *video_plane_ready_handler;
+};
+
+typedef struct _Tdm_Prop_Value
+{
+   unsigned int id;
+   char name[TDM_NAME_LEN];
+   tdm_value value;
+} Tdm_Prop_Value;
+
+static Eina_List *video_list = NULL;
+static Eina_List *video_layers = NULL;
+
+static Eina_Bool _e_video_set(E_Video_Hwc_Planes *evhp, E_Client *ec);
+static void _e_video_destroy(E_Video_Hwc_Planes *evhp);
+static void _e_video_render(E_Video_Hwc_Planes *evhp, const char *func);
+static Eina_Bool _e_video_frame_buffer_show(E_Video_Hwc_Planes *evhp, E_Comp_Wl_Video_Buf *vbuf);
+static void _e_video_video_set_hook(void *data, E_Plane *plane);
+
+static tdm_layer* _e_video_tdm_video_layer_get(tdm_output *output);
+static tdm_layer* _e_video_tdm_available_video_layer_get(tdm_output *output);
+static void _e_video_tdm_set_layer_usable(tdm_layer *layer, Eina_Bool usable);
+static Eina_Bool _e_video_tdm_get_layer_usable(tdm_layer *layer);
+
+static void _e_video_vblank_handler(tdm_output *output, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data);
+
+static void
+buffer_transform(int width, int height, uint32_t transform, int32_t scale,
+                 int sx, int sy, int *dx, int *dy)
+{
+   switch (transform)
+     {
+      case WL_OUTPUT_TRANSFORM_NORMAL:
+      default:
+         *dx = sx, *dy = sy;
+         break;
+      case WL_OUTPUT_TRANSFORM_FLIPPED:
+         *dx = width - sx, *dy = sy;
+         break;
+      case WL_OUTPUT_TRANSFORM_90:
+         *dx = height - sy, *dy = sx;
+         break;
+      case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+         *dx = height - sy, *dy = width - sx;
+         break;
+      case WL_OUTPUT_TRANSFORM_180:
+         *dx = width - sx, *dy = height - sy;
+         break;
+      case WL_OUTPUT_TRANSFORM_FLIPPED_180:
+         *dx = sx, *dy = height - sy;
+         break;
+      case WL_OUTPUT_TRANSFORM_270:
+         *dx = sy, *dy = width - sx;
+         break;
+      case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+         *dx = sy, *dy = sx;
+         break;
+     }
+
+   *dx *= scale;
+   *dy *= scale;
+}
+
+static E_Client *
+find_video_child_get(E_Client *ec)
+{
+   E_Client *subc = NULL;
+   Eina_List *l;
+   if (!ec) return NULL;
+   if (e_object_is_del(E_OBJECT(ec))) return NULL;
+   if (!ec->comp_data) return NULL;
+
+   if (ec->comp_data->video_client) return ec;
+
+   EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
+     {
+        E_Client *temp= NULL;
+        if (!subc->comp_data || e_object_is_del(E_OBJECT(subc))) continue;
+        temp = find_video_child_get(subc);
+        if(temp) return temp;
+     }
+
+   return NULL;
+}
+
+static E_Client *
+find_offscreen_parent_get(E_Client *ec)
+{
+   E_Client *parent = NULL;
+
+   if (!ec->comp_data || !ec->comp_data->sub.data)
+     return NULL;
+
+   parent = ec->comp_data->sub.data->parent;
+   while (parent)
+     {
+        if (!parent->comp_data || !parent->comp_data->sub.data)
+          return NULL;
+
+        if (parent->comp_data->sub.data->remote_surface.offscreen_parent)
+          return parent->comp_data->sub.data->remote_surface.offscreen_parent;
+
+        parent = parent->comp_data->sub.data->parent;
+     }
+
+   return NULL;
+}
+
+static E_Comp_Wl_Video_Buf *
+_e_video_vbuf_find(Eina_List *list, tbm_surface_h buffer)
+{
+   E_Comp_Wl_Video_Buf *vbuf;
+   Eina_List *l = NULL;
+
+   EINA_LIST_FOREACH(list, l, vbuf)
+     {
+        if (vbuf->tbm_surface == buffer)
+          return vbuf;
+     }
+
+   return NULL;
+}
+
+static E_Comp_Wl_Video_Buf *
+_e_video_vbuf_find_with_comp_buffer(Eina_List *list, E_Comp_Wl_Buffer *comp_buffer)
+{
+   E_Comp_Wl_Video_Buf *vbuf;
+   Eina_List *l = NULL;
+
+   EINA_LIST_FOREACH(list, l, vbuf)
+     {
+        if (vbuf->comp_buffer == comp_buffer)
+          return vbuf;
+     }
+
+   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 *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(toutput);
+   if (!layer)
+     return EINA_FALSE;
+
+   tdm_layer_get_capabilities(layer, &lyr_capabilities);
+   if (lyr_capabilities & TDM_LAYER_CAPABILITY_VIDEO)
+     return EINA_TRUE;
+
+   return EINA_FALSE;
+}
+
+static E_Video_Layer *
+_e_video_available_video_layer_get(E_Video_Hwc_Planes *evhp)
+{
+   E_Video_Layer *layer = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(evhp, NULL);
+
+   layer = calloc(1, sizeof(E_Video_Layer));
+   EINA_SAFETY_ON_NULL_RETURN_VAL(layer, NULL);
+
+   layer->evhp = evhp;
+   layer->e_client = evhp->ec;
+
+
+   /* layer->tdm_layer = e_output_video_available_tdm_layer_get(evhp->e_output); */
+   layer->tdm_layer = _e_video_tdm_available_video_layer_get(evhp->output);
+   if (!layer->tdm_layer)
+     {
+        free(layer);
+        return NULL;
+     }
+   _e_video_tdm_set_layer_usable(layer->tdm_layer, EINA_FALSE);
+
+   return layer;
+}
+
+static tdm_error
+_e_video_layer_get_info(E_Video_Layer *layer, E_Client_Video_Info *vinfo)
+{
+   tdm_error ret = TDM_ERROR_NONE;
+   tdm_info_layer tinfo = {0};
+
+   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);
+
+   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;
+}
+
+static tdm_error
+_e_video_layer_set_info(E_Video_Layer *layer, E_Client_Video_Info *vinfo)
+{
+   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;
+
+   ret = tdm_layer_set_info(layer->tdm_layer, &info_layer);
+
+   return ret;
+}
+
+static tdm_error
+_e_video_layer_set_buffer(E_Video_Layer * layer, tbm_surface_h buff)
+{
+   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);
+
+   return ret;
+}
+
+static tdm_error
+_e_video_layer_unset_buffer(E_Video_Layer *layer)
+{
+   tdm_error ret;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(layer, TDM_ERROR_BAD_REQUEST);
+
+   ret = tdm_layer_unset_buffer(layer->tdm_layer);
+
+   return ret;
+}
+
+/*
+ * This function checks if this layer was set
+ */
+static tdm_error
+_e_video_layer_is_usable(E_Video_Layer * layer, unsigned int *usable)
+{
+   tdm_error ret;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(layer, TDM_ERROR_BAD_REQUEST);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(usable, TDM_ERROR_BAD_REQUEST);
+
+   ret = tdm_layer_is_usable(layer->tdm_layer, usable);
+   return ret;
+}
+
+static tdm_error
+_e_video_layer_commit(E_Video_Layer *layer, tdm_layer_commit_handler func, void *user_data)
+{
+   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);
+
+   return ret;
+}
+
+static tbm_surface_h
+_e_video_layer_get_displaying_buffer(E_Video_Layer *layer, int *tdm_error)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(layer, NULL);
+
+   return tdm_layer_get_displaying_buffer(layer->tdm_layer, tdm_error);
+}
+
+static tdm_error
+_e_video_layer_set_property(E_Video_Layer * layer, Tdm_Prop_Value *prop)
+{
+   tdm_error ret;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(layer, TDM_ERROR_BAD_REQUEST);
+
+   ret = tdm_layer_set_property(layer->tdm_layer, prop->id, prop->value);
+   return ret;
+}
+
+static void
+_e_video_layer_destroy(E_Video_Layer *layer)
+{
+   EINA_SAFETY_ON_NULL_RETURN(layer);
+
+   if (layer->tdm_layer)
+     _e_video_tdm_set_layer_usable(layer->tdm_layer, EINA_TRUE);
+
+   free(layer);
+}
+
+static Eina_Bool
+_e_video_set_layer(E_Video_Hwc_Planes *evhp, Eina_Bool set)
+{
+   Eina_Bool need_wait;
+
+   if (!set)
+     {
+        unsigned int usable = 1;
+        if (!evhp->layer) return EINA_TRUE;
+
+        _e_video_layer_is_usable(evhp->layer, &usable);
+        if (!usable && !evhp->video_plane_ready_handler)
+          {
+             VIN("stop video");
+             _e_video_layer_unset_buffer(evhp->layer);
+             _e_video_layer_commit(evhp->layer, NULL, NULL);
+          }
+
+        VIN("release layer: %p", evhp->layer);
+        _e_video_layer_destroy(evhp->layer);
+        evhp->layer = NULL;
+        evhp->old_comp_buffer = NULL;
+
+        e_plane_video_set(evhp->e_plane, EINA_FALSE, NULL);
+        evhp->e_plane = NULL;
+
+        E_FREE_FUNC(evhp->video_plane_ready_handler, e_plane_hook_del);
+     }
+   else
+     {
+        int zpos;
+        tdm_error ret;
+
+        if (evhp->layer) return EINA_TRUE;
+
+        evhp->layer = _e_video_available_video_layer_get(evhp);
+        if (!evhp->layer)
+          {
+             VWR("no available layer for evhp");
+             return EINA_FALSE;
+          }
+
+
+        ret = tdm_layer_get_zpos(evhp->layer->tdm_layer, &zpos);
+        if (ret == TDM_ERROR_NONE)
+          evhp->e_plane = e_output_plane_get_by_zpos(evhp->e_output, zpos);
+
+        if (!evhp->e_plane)
+          {
+             VWR("fail get e_plane");
+             _e_video_layer_destroy(evhp->layer);
+             evhp->layer = NULL;
+             return EINA_FALSE;
+          }
+
+        if (!e_plane_video_set(evhp->e_plane, EINA_TRUE, &need_wait))
+          {
+             VWR("fail set video to e_plane");
+             _e_video_layer_destroy(evhp->layer);
+             evhp->layer = NULL;
+             evhp->e_plane = NULL;
+             return EINA_FALSE;
+          }
+        if (need_wait)
+          {
+             evhp->video_plane_ready_handler =
+                e_plane_hook_add(E_PLANE_HOOK_VIDEO_SET,
+                                 _e_video_video_set_hook, evhp);
+          }
+
+        VIN("assign layer: %p", evhp->layer);
+     }
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_video_is_visible(E_Video_Hwc_Planes *evhp)
+{
+   E_Client *offscreen_parent;
+
+   if (e_object_is_del(E_OBJECT(evhp->ec))) return EINA_FALSE;
+
+   if (!e_pixmap_resource_get(evhp->ec->pixmap))
+     {
+        VDB("no comp buffer");
+        return EINA_FALSE;
+     }
+
+   if (evhp->ec->comp_data->sub.data && evhp->ec->comp_data->sub.data->stand_alone)
+     return EINA_TRUE;
+
+   offscreen_parent = find_offscreen_parent_get(evhp->ec);
+   if (offscreen_parent && offscreen_parent->visibility.obscured == E_VISIBILITY_FULLY_OBSCURED)
+     {
+        VDB("video surface invisible: offscreen fully obscured");
+        return EINA_FALSE;
+     }
+
+   if (!evas_object_visible_get(evhp->ec->frame))
+     {
+        VDB("evas obj invisible");
+        return EINA_FALSE;
+     }
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_video_parent_is_viewable(E_Video_Hwc_Planes *evhp)
+{
+   E_Client *topmost_parent;
+
+   if (e_object_is_del(E_OBJECT(evhp->ec))) return EINA_FALSE;
+
+   topmost_parent = e_comp_wl_topmost_parent_get(evhp->ec);
+
+   if (!topmost_parent)
+     return EINA_FALSE;
+
+   if (topmost_parent == evhp->ec)
+     {
+        VDB("There is no video parent surface");
+        return EINA_FALSE;
+     }
+
+   if (!topmost_parent->visible)
+     {
+        VDB("parent(0x%08"PRIxPTR") not viewable", (Ecore_Window)e_client_util_win_get(topmost_parent));
+        return EINA_FALSE;
+     }
+
+   if (!e_pixmap_resource_get(topmost_parent->pixmap))
+     {
+        VDB("parent(0x%08"PRIxPTR") no comp buffer", (Ecore_Window)e_client_util_win_get(topmost_parent));
+        return EINA_FALSE;
+     }
+
+   return EINA_TRUE;
+}
+
+static void
+_e_video_input_buffer_cb_free(E_Comp_Wl_Video_Buf *vbuf, void *data)
+{
+   E_Video_Hwc_Planes *evhp = data;
+   Eina_Bool need_hide = EINA_FALSE;
+
+   DBG("Buffer(%p) to be free, refcnt(%d)", vbuf, vbuf->ref_cnt);
+
+   evhp->input_buffer_list = eina_list_remove(evhp->input_buffer_list, vbuf);
+
+   if (vbuf->comp_buffer)
+     e_comp_wl_buffer_reference(&vbuf->buffer_ref, NULL);
+
+   if (evhp->current_fb == vbuf)
+     {
+        VIN("current fb destroyed");
+        e_comp_wl_video_buffer_set_use(evhp->current_fb, EINA_FALSE);
+        evhp->current_fb = NULL;
+        need_hide = EINA_TRUE;
+     }
+
+   if (eina_list_data_find(evhp->committed_list, vbuf))
+     {
+        VIN("committed fb destroyed");
+        evhp->committed_list = eina_list_remove(evhp->committed_list, vbuf);
+        e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
+        need_hide = EINA_TRUE;
+     }
+
+   if (eina_list_data_find(evhp->waiting_list, vbuf))
+     {
+        VIN("waiting fb destroyed");
+        evhp->waiting_list = eina_list_remove(evhp->waiting_list, vbuf);
+     }
+
+   if (need_hide && evhp->layer)
+     _e_video_frame_buffer_show(evhp, NULL);
+}
+
+static Eina_Bool
+_e_video_input_buffer_scanout_check(E_Comp_Wl_Video_Buf *vbuf)
+{
+   tbm_surface_h tbm_surface = NULL;
+   tbm_bo bo = NULL;
+   int flag;
+
+   tbm_surface = vbuf->tbm_surface;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(tbm_surface, EINA_FALSE);
+
+   bo = tbm_surface_internal_get_bo(tbm_surface, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(bo, EINA_FALSE);
+
+   flag = tbm_bo_get_flags(bo);
+   if (flag == TBM_BO_SCANOUT)
+      return EINA_TRUE;
+
+   return EINA_FALSE;
+}
+
+static E_Comp_Wl_Video_Buf *
+_e_video_input_buffer_copy(E_Video_Hwc_Planes *evhp, E_Comp_Wl_Buffer *comp_buf, E_Comp_Wl_Video_Buf *vbuf, Eina_Bool scanout)
+{
+   E_Comp_Wl_Video_Buf *temp = NULL;
+   int aligned_width = ROUNDUP(vbuf->width_from_pitch, evhp->pp_align);
+
+   temp = e_comp_wl_video_buffer_alloc(aligned_width, vbuf->height, vbuf->tbmfmt, scanout);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(temp, NULL);
+
+   temp->comp_buffer = comp_buf;
+
+   VDB("copy vbuf(%d,%dx%d) => vbuf(%d,%dx%d)",
+       MSTAMP(vbuf), vbuf->width_from_pitch, vbuf->height,
+       MSTAMP(temp), temp->width_from_pitch, temp->height);
+
+   e_comp_wl_video_buffer_copy(vbuf, temp);
+   e_comp_wl_video_buffer_unref(vbuf);
+
+   evhp->geo.input_w = vbuf->width_from_pitch;
+#ifdef DUMP_BUFFER
+   char file[256];
+   static int i;
+   snprintf(file, sizeof file, "/tmp/dump/%s_%d.png", "cpy", i++);
+   tdm_helper_dump_buffer(temp->tbm_surface, file);
+#endif
+
+   return temp;
+}
+
+static E_Comp_Wl_Video_Buf *
+_e_video_input_buffer_get(E_Video_Hwc_Planes *evhp, E_Comp_Wl_Buffer *comp_buffer, Eina_Bool scanout)
+{
+   E_Comp_Wl_Video_Buf *vbuf;
+   Eina_Bool need_pp_scanout = EINA_FALSE;
+
+   vbuf = _e_video_vbuf_find_with_comp_buffer(evhp->input_buffer_list, comp_buffer);
+   if (vbuf)
+     {
+        vbuf->content_r = evhp->geo.input_r;
+        return vbuf;
+     }
+
+   vbuf = e_comp_wl_video_buffer_create_comp(comp_buffer);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(vbuf, NULL);
+
+   if (evhp->pp_scanout)
+     {
+        Eina_Bool input_buffer_scanout = EINA_FALSE;
+        input_buffer_scanout = _e_video_input_buffer_scanout_check(vbuf);
+        if (!input_buffer_scanout) need_pp_scanout = EINA_TRUE;
+     }
+
+   if (evhp->pp)
+     {
+        if ((evhp->pp_align != -1 && (vbuf->width_from_pitch % evhp->pp_align)) ||
+            need_pp_scanout)
+          {
+             E_Comp_Wl_Video_Buf *temp;
+
+             if (need_pp_scanout)
+               temp = _e_video_input_buffer_copy(evhp, comp_buffer, vbuf, EINA_TRUE);
+             else
+               temp = _e_video_input_buffer_copy(evhp, comp_buffer, vbuf, scanout);
+             if (!temp)
+               {
+                  e_comp_wl_video_buffer_unref(vbuf);
+                  return NULL;
+               }
+             vbuf = temp;
+          }
+     }
+
+   vbuf->content_r = evhp->geo.input_r;
+
+   evhp->input_buffer_list = eina_list_append(evhp->input_buffer_list, vbuf);
+   e_comp_wl_video_buffer_free_func_add(vbuf, _e_video_input_buffer_cb_free, evhp);
+
+   DBG("Client(%s):PID(%d) RscID(%d), Buffer(%p) created, refcnt:%d"
+       " scanout=%d", e_client_util_name_get(evhp->ec) ?: "No Name" ,
+       evhp->ec->netwm.pid, wl_resource_get_id(evhp->ec->comp_data->surface), vbuf,
+       vbuf->ref_cnt, scanout);
+
+   return vbuf;
+}
+
+static void
+_e_video_input_buffer_valid(E_Video_Hwc_Planes *evhp, E_Comp_Wl_Buffer *comp_buffer)
+{
+   E_Comp_Wl_Video_Buf *vbuf;
+   Eina_List *l;
+
+   EINA_LIST_FOREACH(evhp->input_buffer_list, l, vbuf)
+     {
+        tbm_surface_h tbm_surf;
+        tbm_bo bo;
+        uint32_t size = 0, offset = 0, pitch = 0;
+
+        if (!vbuf->comp_buffer) continue;
+        if (vbuf->resource == comp_buffer->resource)
+          {
+             WRN("got wl_buffer@%d twice", wl_resource_get_id(comp_buffer->resource));
+             return;
+          }
+
+        tbm_surf = wayland_tbm_server_get_surface(e_comp->wl_comp_data->tbm.server, comp_buffer->resource);
+        bo = tbm_surface_internal_get_bo(tbm_surf, 0);
+        tbm_surface_internal_get_plane_data(tbm_surf, 0, &size, &offset, &pitch);
+
+        if (vbuf->names[0] == tbm_bo_export(bo) && vbuf->offsets[0] == offset)
+          {
+             WRN("can tearing: wl_buffer@%d, wl_buffer@%d are same. gem_name(%d)",
+                 wl_resource_get_id(vbuf->resource),
+                 wl_resource_get_id(comp_buffer->resource), vbuf->names[0]);
+             return;
+          }
+     }
+}
+
+static void
+_e_video_pp_buffer_cb_free(E_Comp_Wl_Video_Buf *vbuf, void *data)
+{
+   E_Video_Hwc_Planes *evhp = data;
+
+   e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
+
+   if (evhp->current_fb == vbuf)
+     evhp->current_fb = NULL;
+
+   evhp->committed_list = eina_list_remove(evhp->committed_list, vbuf);
+
+   evhp->waiting_list = eina_list_remove(evhp->waiting_list, vbuf);
+
+   evhp->pp_buffer_list = eina_list_remove(evhp->pp_buffer_list, vbuf);
+}
+
+static E_Comp_Wl_Video_Buf *
+_e_video_pp_buffer_get(E_Video_Hwc_Planes *evhp, int width, int height)
+{
+   E_Comp_Wl_Video_Buf *vbuf;
+   Eina_List *l;
+   int i = 0;
+   int aligned_width;
+
+   if (evhp->video_align != -1)
+     aligned_width = ROUNDUP(width, evhp->video_align);
+   else
+     aligned_width = width;
+
+   if (evhp->pp_buffer_list)
+     {
+        vbuf = eina_list_data_get(evhp->pp_buffer_list);
+        EINA_SAFETY_ON_NULL_RETURN_VAL(vbuf, NULL);
+
+        /* if we need bigger pp_buffers, destroy all pp_buffers and create */
+        if (aligned_width > vbuf->width_from_pitch || height != vbuf->height)
+          {
+             Eina_List *ll;
+
+             VIN("pp buffer changed: %dx%d => %dx%d",
+                 vbuf->width_from_pitch, vbuf->height,
+                 aligned_width, height);
+
+             EINA_LIST_FOREACH_SAFE(evhp->pp_buffer_list, l, ll, vbuf)
+               {
+                  /* free forcely */
+                  e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
+                  e_comp_wl_video_buffer_unref(vbuf);
+               }
+             if (evhp->pp_buffer_list)
+               NEVER_GET_HERE();
+
+             if (evhp->waiting_list)
+               NEVER_GET_HERE();
+          }
+     }
+
+   if (!evhp->pp_buffer_list)
+     {
+        for (i = 0; i < BUFFER_MAX_COUNT; i++)
+          {
+             vbuf = e_comp_wl_video_buffer_alloc(aligned_width, height, evhp->pp_tbmfmt, EINA_TRUE);
+             EINA_SAFETY_ON_NULL_RETURN_VAL(vbuf, NULL);
+
+             e_comp_wl_video_buffer_free_func_add(vbuf, _e_video_pp_buffer_cb_free, evhp);
+             evhp->pp_buffer_list = eina_list_append(evhp->pp_buffer_list, vbuf);
+
+          }
+
+        VIN("pp buffer created: %dx%d, %c%c%c%c",
+            vbuf->width_from_pitch, height, FOURCC_STR(evhp->pp_tbmfmt));
+
+        evhp->next_buffer = evhp->pp_buffer_list;
+     }
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(evhp->pp_buffer_list, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(evhp->next_buffer, NULL);
+
+   l = evhp->next_buffer;
+   while ((vbuf = evhp->next_buffer->data))
+     {
+        evhp->next_buffer = (evhp->next_buffer->next) ? evhp->next_buffer->next : evhp->pp_buffer_list;
+
+        if (!vbuf->in_use)
+          return vbuf;
+
+        if (l == evhp->next_buffer)
+          {
+             VWR("all video framebuffers in use (max:%d)", BUFFER_MAX_COUNT);
+             return NULL;
+          }
+     }
+
+   return NULL;
+}
+
+/* convert from logical screen to physical output */
+static void
+_e_video_geometry_cal_physical(E_Video_Hwc_Planes *evhp)
+{
+   E_Zone *zone;
+   E_Comp_Wl_Output *output;
+   E_Client *topmost;
+   int tran, flip;
+   int transform;
+
+   topmost = e_comp_wl_topmost_parent_get(evhp->ec);
+   EINA_SAFETY_ON_NULL_GOTO(topmost, normal);
+
+   output = e_comp_wl_output_find(topmost);
+   EINA_SAFETY_ON_NULL_GOTO(output, normal);
+
+   zone = e_comp_zone_xy_get(topmost->x, topmost->y);
+   EINA_SAFETY_ON_NULL_GOTO(zone, normal);
+
+   tran = evhp->geo.transform & 0x3;
+   flip = evhp->geo.transform & 0x4;
+   transform = flip + (tran + output->transform) % 4;
+   switch(transform)
+     {
+      case WL_OUTPUT_TRANSFORM_90:
+         evhp->geo.tdm_transform = TDM_TRANSFORM_270;
+         break;
+      case WL_OUTPUT_TRANSFORM_180:
+         evhp->geo.tdm_transform = TDM_TRANSFORM_180;
+         break;
+      case WL_OUTPUT_TRANSFORM_270:
+         evhp->geo.tdm_transform = TDM_TRANSFORM_90;
+         break;
+      case WL_OUTPUT_TRANSFORM_FLIPPED:
+         evhp->geo.tdm_transform = TDM_TRANSFORM_FLIPPED;
+         break;
+      case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+         evhp->geo.tdm_transform = TDM_TRANSFORM_FLIPPED_270;
+         break;
+      case WL_OUTPUT_TRANSFORM_FLIPPED_180:
+         evhp->geo.tdm_transform = TDM_TRANSFORM_FLIPPED_180;
+         break;
+      case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+         evhp->geo.tdm_transform = TDM_TRANSFORM_FLIPPED_90;
+         break;
+      case WL_OUTPUT_TRANSFORM_NORMAL:
+      default:
+         evhp->geo.tdm_transform = TDM_TRANSFORM_NORMAL;
+         break;
+     }
+
+   if (output->transform % 2)
+     {
+        if (evhp->geo.tdm_transform == TDM_TRANSFORM_FLIPPED)
+          evhp->geo.tdm_transform = TDM_TRANSFORM_FLIPPED_180;
+        else if (evhp->geo.tdm_transform == TDM_TRANSFORM_FLIPPED_90)
+          evhp->geo.tdm_transform = TDM_TRANSFORM_FLIPPED_270;
+        else if (evhp->geo.tdm_transform == TDM_TRANSFORM_FLIPPED_180)
+          evhp->geo.tdm_transform = TDM_TRANSFORM_FLIPPED;
+        else if (evhp->geo.tdm_transform == TDM_TRANSFORM_FLIPPED_270)
+          evhp->geo.tdm_transform = TDM_TRANSFORM_FLIPPED_90;
+     }
+
+   if (output->transform == 0)
+     evhp->geo.tdm_output_r = evhp->geo.output_r;
+   else
+     e_comp_wl_rect_convert(zone->w, zone->h, output->transform, 1,
+                            evhp->geo.output_r.x, evhp->geo.output_r.y,
+                            evhp->geo.output_r.w, evhp->geo.output_r.h,
+                            &evhp->geo.tdm_output_r.x, &evhp->geo.tdm_output_r.y,
+                            &evhp->geo.tdm_output_r.w, &evhp->geo.tdm_output_r.h);
+
+   VDB("geomtry: screen(%d,%d %dx%d | %d) => %d => physical(%d,%d %dx%d | %d)",
+       EINA_RECTANGLE_ARGS(&evhp->geo.output_r), evhp->geo.transform, transform,
+       EINA_RECTANGLE_ARGS(&evhp->geo.tdm_output_r), evhp->geo.tdm_transform);
+
+   return;
+normal:
+   evhp->geo.tdm_output_r = evhp->geo.output_r;
+   evhp->geo.tdm_transform = evhp->geo.transform;
+}
+
+static Eina_Bool
+_e_video_geometry_cal_viewport(E_Video_Hwc_Planes *evhp)
+{
+   E_Client *ec = evhp->ec;
+   E_Comp_Wl_Buffer_Viewport *vp = &ec->comp_data->scaler.buffer_viewport;
+   E_Comp_Wl_Subsurf_Data *sdata;
+   int x1, y1, x2, y2;
+   int tx1, ty1, tx2, ty2;
+   E_Comp_Wl_Buffer *comp_buffer;
+   tbm_surface_h tbm_surf;
+   uint32_t size = 0, offset = 0, pitch = 0;
+   int bw, bh;
+   int width_from_buffer, height_from_buffer;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
+
+   comp_buffer = e_pixmap_resource_get(evhp->ec->pixmap);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(comp_buffer, EINA_FALSE);
+
+   tbm_surf = wayland_tbm_server_get_surface(e_comp->wl_comp_data->tbm.server, comp_buffer->resource);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(tbm_surf, EINA_FALSE);
+
+   tbm_surface_internal_get_plane_data(tbm_surf, 0, &size, &offset, &pitch);
+
+   /* input geometry */
+   if (IS_RGB(evhp->tbmfmt))
+     evhp->geo.input_w = pitch / 4;
+   else
+     evhp->geo.input_w = pitch;
+
+   evhp->geo.input_h = tbm_surface_get_height(tbm_surf);
+
+   bw = tbm_surface_get_width(tbm_surf);
+   bh = tbm_surface_get_height(tbm_surf);
+   VDB("TBM buffer size %d %d", bw, bh);
+
+   switch (vp->buffer.transform)
+     {
+      case WL_OUTPUT_TRANSFORM_90:
+      case WL_OUTPUT_TRANSFORM_270:
+      case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+      case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+         width_from_buffer = bh / vp->buffer.scale;
+         height_from_buffer = bw / vp->buffer.scale;
+         break;
+      default:
+         width_from_buffer = bw / vp->buffer.scale;
+         height_from_buffer = bh / vp->buffer.scale;
+         break;
+     }
+
+
+   if (vp->buffer.src_width == wl_fixed_from_int(-1))
+     {
+        x1 = 0.0;
+        y1 = 0.0;
+        x2 = width_from_buffer;
+        y2 = height_from_buffer;
+     }
+   else
+     {
+        x1 = wl_fixed_to_int(vp->buffer.src_x);
+        y1 = wl_fixed_to_int(vp->buffer.src_y);
+        x2 = wl_fixed_to_int(vp->buffer.src_x + vp->buffer.src_width);
+        y2 = wl_fixed_to_int(vp->buffer.src_y + vp->buffer.src_height);
+     }
+
+   VDB("transform(%d) scale(%d) buffer(%dx%d) src(%d,%d %d,%d) viewport(%dx%d)",
+       vp->buffer.transform, vp->buffer.scale,
+       width_from_buffer, height_from_buffer,
+       x1, y1, x2 - x1, y2 - y1,
+       ec->comp_data->width_from_viewport, ec->comp_data->height_from_viewport);
+
+   buffer_transform(width_from_buffer, height_from_buffer,
+                    vp->buffer.transform, vp->buffer.scale, x1, y1, &tx1, &ty1);
+   buffer_transform(width_from_buffer, height_from_buffer,
+                    vp->buffer.transform, vp->buffer.scale, x2, y2, &tx2, &ty2);
+
+   evhp->geo.input_r.x = (tx1 <= tx2) ? tx1 : tx2;
+   evhp->geo.input_r.y = (ty1 <= ty2) ? ty1 : ty2;
+   evhp->geo.input_r.w = (tx1 <= tx2) ? tx2 - tx1 : tx1 - tx2;
+   evhp->geo.input_r.h = (ty1 <= ty2) ? ty2 - ty1 : ty1 - ty2;
+
+   /* output geometry */
+   if ((sdata = ec->comp_data->sub.data))
+     {
+        if (sdata->parent)
+          {
+             evhp->geo.output_r.x = sdata->parent->x + sdata->position.x;
+             evhp->geo.output_r.y = sdata->parent->y + sdata->position.y;
+          }
+        else
+          {
+             evhp->geo.output_r.x = sdata->position.x;
+             evhp->geo.output_r.y = sdata->position.y;
+          }
+     }
+   else
+     {
+        evhp->geo.output_r.x = ec->x;
+        evhp->geo.output_r.y = ec->y;
+     }
+
+   evhp->geo.output_r.w = ec->comp_data->width_from_viewport;
+   evhp->geo.output_r.w = (evhp->geo.output_r.w + 1) & ~1;
+   evhp->geo.output_r.h = ec->comp_data->height_from_viewport;
+
+   e_comp_object_frame_xy_unadjust(ec->frame,
+                                   evhp->geo.output_r.x, evhp->geo.output_r.y,
+                                   &evhp->geo.output_r.x, &evhp->geo.output_r.y);
+   e_comp_object_frame_wh_unadjust(ec->frame,
+                                   evhp->geo.output_r.w, evhp->geo.output_r.h,
+                                   &evhp->geo.output_r.w, &evhp->geo.output_r.h);
+
+   evhp->geo.transform = vp->buffer.transform;
+
+   _e_video_geometry_cal_physical(evhp);
+
+   VDB("geometry(%dx%d  %d,%d %dx%d  %d,%d %dx%d  %d)",
+       evhp->geo.input_w, evhp->geo.input_h,
+       EINA_RECTANGLE_ARGS(&evhp->geo.input_r),
+       EINA_RECTANGLE_ARGS(&evhp->geo.output_r),
+       evhp->geo.transform);
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_video_geometry_cal_map(E_Video_Hwc_Planes *evhp)
+{
+   E_Client *ec;
+   const Evas_Map *m;
+   Evas_Coord x1, x2, y1, y2;
+   Eina_Rectangle output_r;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(evhp, EINA_FALSE);
+
+   ec = evhp->ec;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ec->frame, EINA_FALSE);
+
+   m = evas_object_map_get(ec->frame);
+   if (!m) return EINA_TRUE;
+
+   /* If frame has map, it means that ec's geometry is decided by map's geometry.
+    * ec->x,y,w,h and ec->client.x,y,w,h is not useful.
+    */
+
+   evas_map_point_coord_get(m, 0, &x1, &y1, NULL);
+   evas_map_point_coord_get(m, 2, &x2, &y2, NULL);
+
+   output_r.x = x1;
+   output_r.y = y1;
+   output_r.w = x2 - x1;
+   output_r.w = (output_r.w + 1) & ~1;
+   output_r.h = y2 - y1;
+   output_r.h = (output_r.h + 1) & ~1;
+
+   if (!memcmp(&evhp->geo.output_r, &output_r, sizeof(Eina_Rectangle)))
+     return EINA_FALSE;
+
+   VDB("frame(%p) m(%p) output(%d,%d %dx%d) => (%d,%d %dx%d)", ec->frame, m,
+       EINA_RECTANGLE_ARGS(&evhp->geo.output_r), EINA_RECTANGLE_ARGS(&output_r));
+
+   evhp->geo.output_r = output_r;
+
+   _e_video_geometry_cal_physical(evhp);
+
+   return EINA_TRUE;
+}
+
+static void
+_e_video_geometry_cal_to_input(int output_w, int output_h, int input_w, int input_h,
+                               uint32_t trasnform, int ox, int oy, int *ix, int *iy)
+{
+   float ratio_w, ratio_h;
+
+   switch(trasnform)
+     {
+      case WL_OUTPUT_TRANSFORM_NORMAL:
+      default:
+         *ix = ox, *iy = oy;
+         break;
+      case WL_OUTPUT_TRANSFORM_270:
+         *ix = oy, *iy = output_w - ox;
+         break;
+      case WL_OUTPUT_TRANSFORM_180:
+         *ix = output_w - ox, *iy = output_h - oy;
+         break;
+      case WL_OUTPUT_TRANSFORM_90:
+         *ix = output_h - oy, *iy = ox;
+         break;
+      case WL_OUTPUT_TRANSFORM_FLIPPED:
+         *ix = output_w - ox, *iy = oy;
+         break;
+      case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+         *ix = oy, *iy = ox;
+         break;
+      case WL_OUTPUT_TRANSFORM_FLIPPED_180:
+         *ix = ox, *iy = output_h - oy;
+         break;
+      case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+         *ix = output_h - oy, *iy = output_w - ox;
+         break;
+     }
+   if (trasnform & 0x1)
+     {
+        ratio_w = (float)input_w / output_h;
+        ratio_h = (float)input_h / output_w;
+     }
+   else
+     {
+        ratio_w = (float)input_w / output_w;
+        ratio_h = (float)input_h / output_h;
+     }
+   *ix *= ratio_w;
+   *iy *= ratio_h;
+}
+
+static void
+_e_video_geometry_cal_to_input_rect(E_Video_Hwc_Planes * evhp, Eina_Rectangle *srect, Eina_Rectangle *drect)
+{
+   int xf1, yf1, xf2, yf2;
+
+   /* first transform box coordinates if the scaler is set */
+
+   xf1 = srect->x;
+   yf1 = srect->y;
+   xf2 = srect->x + srect->w;
+   yf2 = srect->y + srect->h;
+
+   _e_video_geometry_cal_to_input(evhp->geo.output_r.w, evhp->geo.output_r.h,
+                                  evhp->geo.input_r.w, evhp->geo.input_r.h,
+                                  evhp->geo.transform, xf1, yf1, &xf1, &yf1);
+   _e_video_geometry_cal_to_input(evhp->geo.output_r.w, evhp->geo.output_r.h,
+                                  evhp->geo.input_r.w, evhp->geo.input_r.h,
+                                  evhp->geo.transform, xf2, yf2, &xf2, &yf2);
+
+   drect->x = MIN(xf1, xf2);
+   drect->y = MIN(yf1, yf2);
+   drect->w = MAX(xf1, xf2) - drect->x;
+   drect->h = MAX(yf1, yf2) - drect->y;
+}
+
+static Eina_Bool
+_e_video_geometry_cal(E_Video_Hwc_Planes *evhp)
+{
+   Eina_Rectangle screen = {0,};
+   Eina_Rectangle output_r = {0,}, input_r = {0,};
+   const tdm_output_mode *mode = NULL;
+   tdm_error tdm_err = TDM_ERROR_NONE;
+
+   /* get geometry information with buffer scale, transform and viewport. */
+   if (!_e_video_geometry_cal_viewport(evhp))
+     return EINA_FALSE;
+
+   _e_video_geometry_cal_map(evhp);
+
+   if (e_config->eom_enable == EINA_TRUE && evhp->external_video)
+     {
+        tdm_err = tdm_output_get_mode(evhp->output, &mode);
+        if (tdm_err != TDM_ERROR_NONE)
+          return EINA_FALSE;
+
+        if (mode == NULL)
+          return EINA_FALSE;
+
+        screen.w = mode->hdisplay;
+        screen.h = mode->vdisplay;
+     }
+   else
+     {
+        E_Zone *zone;
+        E_Client *topmost;
+
+        topmost = e_comp_wl_topmost_parent_get(evhp->ec);
+        EINA_SAFETY_ON_NULL_RETURN_VAL(topmost, EINA_FALSE);
+
+        zone = e_comp_zone_xy_get(topmost->x, topmost->y);
+        EINA_SAFETY_ON_NULL_RETURN_VAL(zone, EINA_FALSE);
+
+        screen.w = zone->w;
+        screen.h = zone->h;
+     }
+
+   e_comp_wl_video_buffer_size_get(evhp->ec, &input_r.w, &input_r.h);
+   // when topmost is not mapped, input size can be abnormal.
+   // in this case, it will be render by topmost showing.
+   if (!eina_rectangle_intersection(&evhp->geo.input_r, &input_r) || (evhp->geo.input_r.w <= 10 || evhp->geo.input_r.h <= 10))
+     {
+        VER("input area is empty");
+        return EINA_FALSE;
+     }
+
+   if (evhp->geo.output_r.x >= 0 && evhp->geo.output_r.y >= 0 &&
+       (evhp->geo.output_r.x + evhp->geo.output_r.w) <= screen.w &&
+       (evhp->geo.output_r.y + evhp->geo.output_r.h) <= screen.h)
+     return EINA_TRUE;
+
+   /* TODO: need to improve */
+
+   output_r = evhp->geo.output_r;
+   if (!eina_rectangle_intersection(&output_r, &screen))
+     {
+        VER("output_r(%d,%d %dx%d) screen(%d,%d %dx%d) => intersect(%d,%d %dx%d)",
+            EINA_RECTANGLE_ARGS(&evhp->geo.output_r),
+            EINA_RECTANGLE_ARGS(&screen), EINA_RECTANGLE_ARGS(&output_r));
+        return EINA_TRUE;
+     }
+
+   output_r.x -= evhp->geo.output_r.x;
+   output_r.y -= evhp->geo.output_r.y;
+
+   if (output_r.w <= 0 || output_r.h <= 0)
+     {
+        VER("output area is empty");
+        return EINA_FALSE;
+     }
+
+   VDB("output(%d,%d %dx%d) input(%d,%d %dx%d)",
+       EINA_RECTANGLE_ARGS(&output_r), EINA_RECTANGLE_ARGS(&input_r));
+
+   _e_video_geometry_cal_to_input_rect(evhp, &output_r, &input_r);
+
+   VDB("output(%d,%d %dx%d) input(%d,%d %dx%d)",
+       EINA_RECTANGLE_ARGS(&output_r), EINA_RECTANGLE_ARGS(&input_r));
+
+   output_r.x += evhp->geo.output_r.x;
+   output_r.y += evhp->geo.output_r.y;
+
+   input_r.x += evhp->geo.input_r.x;
+   input_r.y += evhp->geo.input_r.y;
+
+   output_r.x = output_r.x & ~1;
+   output_r.w = (output_r.w + 1) & ~1;
+
+   input_r.x = input_r.x & ~1;
+   input_r.w = (input_r.w + 1) & ~1;
+
+   evhp->geo.output_r = output_r;
+   evhp->geo.input_r = input_r;
+
+   _e_video_geometry_cal_physical(evhp);
+
+   return EINA_TRUE;
+}
+
+static void
+_e_video_format_info_get(E_Video_Hwc_Planes *evhp)
+{
+   E_Comp_Wl_Buffer *comp_buffer;
+   tbm_surface_h tbm_surf;
+
+   comp_buffer = e_pixmap_resource_get(evhp->ec->pixmap);
+   EINA_SAFETY_ON_NULL_RETURN(comp_buffer);
+
+   tbm_surf = wayland_tbm_server_get_surface(e_comp->wl_comp_data->tbm.server, comp_buffer->resource);
+   EINA_SAFETY_ON_NULL_RETURN(tbm_surf);
+
+   evhp->tbmfmt = tbm_surface_get_format(tbm_surf);
+}
+
+static Eina_Bool
+_e_video_can_commit(E_Video_Hwc_Planes *evhp)
+{
+   if (e_config->eom_enable == EINA_TRUE)
+     {
+        if (!evhp->external_video && e_output_dpms_get(evhp->e_output))
+          return EINA_FALSE;
+     }
+   else
+     if (e_output_dpms_get(evhp->e_output))
+       return EINA_FALSE;
+
+   if (!_e_video_is_visible(evhp))
+     return EINA_FALSE;
+
+   return EINA_TRUE;
+}
+
+static void
+_e_video_commit_handler(tdm_layer *layer, unsigned int sequence,
+                        unsigned int tv_sec, unsigned int tv_usec,
+                        void *user_data)
+{
+   E_Video_Hwc_Planes *evhp;
+   Eina_List *l;
+   E_Comp_Wl_Video_Buf *vbuf;
+
+   EINA_LIST_FOREACH(video_list, l, evhp)
+     {
+        if (evhp == user_data) break;
+     }
+
+   if (!evhp) return;
+   if (!evhp->committed_list) return;
+
+   if (_e_video_can_commit(evhp))
+     {
+        tbm_surface_h displaying_buffer = _e_video_layer_get_displaying_buffer(evhp->layer, NULL);
+
+        EINA_LIST_FOREACH(evhp->committed_list, l, vbuf)
+          {
+             if (vbuf->tbm_surface == displaying_buffer) break;
+          }
+        if (!vbuf) return;
+     }
+   else
+     vbuf = eina_list_nth(evhp->committed_list, 0);
+
+   evhp->committed_list = eina_list_remove(evhp->committed_list, vbuf);
+
+   /* client can attachs the same wl_buffer twice. */
+   if (evhp->current_fb && VBUF_IS_VALID(evhp->current_fb) && vbuf != evhp->current_fb)
+     {
+        e_comp_wl_video_buffer_set_use(evhp->current_fb, EINA_FALSE);
+
+        if (evhp->current_fb->comp_buffer)
+          e_comp_wl_buffer_reference(&evhp->current_fb->buffer_ref, NULL);
+     }
+
+   evhp->current_fb = vbuf;
+
+   VDB("current_fb(%d)", MSTAMP(evhp->current_fb));
+}
+
+static void
+_e_video_commit_buffer(E_Video_Hwc_Planes *evhp, E_Comp_Wl_Video_Buf *vbuf)
+{
+   evhp->committed_list = eina_list_append(evhp->committed_list, vbuf);
+
+   if (!_e_video_can_commit(evhp))
+     goto no_commit;
+
+   if (!_e_video_frame_buffer_show(evhp, vbuf))
+     goto no_commit;
+
+   return;
+
+no_commit:
+   _e_video_commit_handler(NULL, 0, 0, 0, evhp);
+   _e_video_vblank_handler(NULL, 0, 0, 0, evhp);
+}
+
+static void
+_e_video_commit_from_waiting_list(E_Video_Hwc_Planes *evhp)
+{
+   E_Comp_Wl_Video_Buf *vbuf;
+
+   vbuf = eina_list_nth(evhp->waiting_list, 0);
+   evhp->waiting_list = eina_list_remove(evhp->waiting_list, vbuf);
+
+   _e_video_commit_buffer(evhp, vbuf);
+}
+
+static void
+_e_video_vblank_handler(tdm_output *output, unsigned int sequence,
+                        unsigned int tv_sec, unsigned int tv_usec,
+                        void *user_data)
+{
+   E_Video_Hwc_Planes *evhp;
+   Eina_List *l;
+
+   EINA_LIST_FOREACH(video_list, l, evhp)
+     {
+        if (evhp == user_data) break;
+     }
+
+   if (!evhp) return;
+
+   evhp->waiting_vblank = EINA_FALSE;
+
+   if (evhp->video_plane_ready_handler) return;
+
+   if (evhp->waiting_list)
+     _e_video_commit_from_waiting_list(evhp);
+}
+
+static void
+_e_video_video_set_hook(void *data, E_Plane *plane)
+{
+   E_Video_Hwc_Planes *evhp = (E_Video_Hwc_Planes *)data;
+
+   if (evhp->e_plane != plane) return;
+   if (evhp->waiting_vblank) return;
+
+   if (evhp->waiting_list)
+     _e_video_commit_from_waiting_list(evhp);
+
+   E_FREE_FUNC(evhp->video_plane_ready_handler, e_plane_hook_del);
+}
+
+static Eina_Bool
+_e_video_frame_buffer_show(E_Video_Hwc_Planes *evhp, E_Comp_Wl_Video_Buf *vbuf)
+{
+   E_Client_Video_Info info, old_info;
+   tdm_error ret;
+   E_Client *topmost;
+   Tdm_Prop_Value *prop;
+
+   if (!vbuf)
+     {
+        if (evhp->layer)
+          {
+             VIN("unset layer: hide");
+             _e_video_set_layer(evhp, EINA_FALSE);
+          }
+        return EINA_TRUE;
+     }
+
+   if (!evhp->layer)
+     {
+        VIN("set layer: show");
+        if (!_e_video_set_layer(evhp, EINA_TRUE))
+          {
+             VER("set layer failed");
+             return EINA_FALSE;
+          }
+        // need call tdm property in list
+        Tdm_Prop_Value *prop;
+        EINA_LIST_FREE(evhp->tdm_prop_list, prop)
+          {
+             VIN("call property(%s), value(%d)", prop->name, (unsigned int)prop->value.u32);
+             _e_video_layer_set_property(evhp->layer, prop);
+             free(prop);
+          }
+     }
+
+   CLEAR(old_info);
+   ret = _e_video_layer_get_info(evhp->layer, &old_info);
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(ret == TDM_ERROR_NONE, EINA_FALSE);
+
+   CLEAR(info);
+   info.src_config.size.h = vbuf->width_from_pitch;
+   info.src_config.size.v = vbuf->height_from_size;
+   info.src_config.pos.x = vbuf->content_r.x;
+   info.src_config.pos.y = vbuf->content_r.y;
+   info.src_config.pos.w = vbuf->content_r.w;
+   info.src_config.pos.h = vbuf->content_r.h;
+   info.src_config.format = vbuf->tbmfmt;
+   info.dst_pos.x = evhp->geo.tdm_output_r.x;
+   info.dst_pos.y = evhp->geo.tdm_output_r.y;
+   info.dst_pos.w = evhp->geo.tdm_output_r.w;
+   info.dst_pos.h = evhp->geo.tdm_output_r.h;
+   info.transform = vbuf->content_t;
+
+   if (memcmp(&old_info, &info, sizeof(tdm_info_layer)))
+     {
+        ret = _e_video_layer_set_info(evhp->layer, &info);
+        EINA_SAFETY_ON_FALSE_RETURN_VAL(ret == TDM_ERROR_NONE, EINA_FALSE);
+     }
+
+   ret = _e_video_layer_set_buffer(evhp->layer, vbuf->tbm_surface);
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(ret == TDM_ERROR_NONE, EINA_FALSE);
+
+   ret = _e_video_layer_commit(evhp->layer, _e_video_commit_handler, evhp);
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(ret == TDM_ERROR_NONE, EINA_FALSE);
+
+   ret = tdm_output_wait_vblank(evhp->output, 1, 0, _e_video_vblank_handler, evhp);
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(ret == TDM_ERROR_NONE, EINA_FALSE);
+
+   evhp->waiting_vblank = EINA_TRUE;
+
+   EINA_LIST_FREE(evhp->late_tdm_prop_list, prop)
+     {
+        VIN("call property(%s), value(%d)", prop->name, (unsigned int)prop->value.u32);
+        _e_video_layer_set_property(evhp->layer, prop);
+        free(prop);
+     }
+
+   topmost = e_comp_wl_topmost_parent_get(evhp->ec);
+   if (topmost && topmost->argb && !e_comp_object_mask_has(evhp->ec->frame))
+     {
+        Eina_Bool do_punch = EINA_TRUE;
+
+        /* FIXME: the mask obj can be drawn at the wrong position in the beginnig
+         * time. It happens caused by window manager policy.
+         */
+        if ((topmost->fullscreen || topmost->maximized) &&
+            (evhp->geo.output_r.x == 0 || evhp->geo.output_r.y == 0))
+          {
+             int bw, bh;
+
+             e_pixmap_size_get(topmost->pixmap, &bw, &bh);
+
+             if (bw > 100 && bh > 100 &&
+                 evhp->geo.output_r.w < 100 && evhp->geo.output_r.h < 100)
+               {
+                  VIN("don't punch. (%dx%d, %dx%d)",
+                      bw, bh, evhp->geo.output_r.w, evhp->geo.output_r.h);
+                  do_punch = EINA_FALSE;
+               }
+          }
+
+        if (do_punch)
+          {
+             e_comp_object_mask_set(evhp->ec->frame, EINA_TRUE);
+             VIN("punched");
+          }
+     }
+
+   if (e_video_debug_punch_value_get())
+     {
+        e_comp_object_mask_set(evhp->ec->frame, EINA_TRUE);
+        VIN("punched");
+     }
+
+   DBG("Client(%s):PID(%d) RscID(%d), Buffer(%p, refcnt:%d) is shown."
+       "Geometry details are : buffer size(%dx%d) src(%d,%d, %dx%d)"
+       " dst(%d,%d, %dx%d), transform(%d)",
+       e_client_util_name_get(evhp->ec) ?: "No Name" , evhp->ec->netwm.pid,
+       wl_resource_get_id(evhp->ec->comp_data->surface), vbuf, vbuf->ref_cnt,
+       info.src_config.size.h, info.src_config.size.v, info.src_config.pos.x,
+       info.src_config.pos.y, info.src_config.pos.w, info.src_config.pos.h,
+       info.dst_pos.x, info.dst_pos.y, info.dst_pos.w, info.dst_pos.h, info.transform);
+
+
+   return EINA_TRUE;
+}
+
+static void
+_e_video_buffer_show(E_Video_Hwc_Planes *evhp, E_Comp_Wl_Video_Buf *vbuf, unsigned int transform)
+{
+   vbuf->content_t = transform;
+
+   e_comp_wl_video_buffer_set_use(vbuf, EINA_TRUE);
+
+   if (vbuf->comp_buffer)
+     e_comp_wl_buffer_reference(&vbuf->buffer_ref, vbuf->comp_buffer);
+
+   if (evhp->waiting_vblank || evhp->video_plane_ready_handler)
+     {
+        evhp->waiting_list = eina_list_append(evhp->waiting_list, vbuf);
+        VDB("There are waiting fbs more than 1");
+        return;
+     }
+
+   _e_video_commit_buffer(evhp, vbuf);
+}
+
+static void
+_e_video_cb_evas_resize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
+{
+   E_Video_Hwc_Planes *evhp = data;
+
+   if (_e_video_geometry_cal_map(evhp))
+     _e_video_render(evhp, __FUNCTION__);
+}
+
+static void
+_e_video_cb_evas_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   E_Video_Hwc_Planes *evhp = data;
+
+   if (_e_video_geometry_cal_map(evhp))
+     _e_video_render(evhp, __FUNCTION__);
+}
+
+static void
+_e_video_cb_evas_show(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   E_Video_Hwc_Planes *evhp = data;
+
+   if (e_object_is_del(E_OBJECT(evhp->ec))) return;
+
+   if (!evhp->ec->comp_data->video_client)
+     return;
+
+   if (evhp->need_force_render)
+     {
+        VIN("video forcely rendering..");
+        _e_video_render(evhp, __FUNCTION__);
+     }
+
+   /* if stand_alone is true, not show */
+   if ((evhp->ec->comp_data->sub.data && evhp->ec->comp_data->sub.data->stand_alone) ||
+       (evhp->ec->comp_data->sub.data && evhp->follow_topmost_visibility))
+     {
+#if 0 //mute off is managed by client. mute off in server made many issues.
+        if (!evhp->layer) return;
+
+        if (evhp->tdm_mute_id != -1)
+          {
+             Tdm_Prop_Value prop = {.id = evhp->tdm_mute_id, .value.u32 = 0};
+             VIN("video surface show. mute off (ec:%p)", evhp->ec);
+             _e_video_layer_set_property(evhp->layer, &prop);
+          }
+#endif
+        return;
+     }
+
+   if (!evhp->layer)
+     {
+        VIN("set layer: show");
+        if (!_e_video_set_layer(evhp, EINA_TRUE))
+          {
+             VER("set layer failed");
+             return;
+          }
+        // need call tdm property in list
+        Tdm_Prop_Value *prop;
+        EINA_LIST_FREE(evhp->tdm_prop_list, prop)
+          {
+             VIN("call property(%s), value(%d)", prop->name, (unsigned int)prop->value.u32);
+             _e_video_layer_set_property(evhp->layer, prop);
+             free(prop);
+          }
+     }
+
+   VIN("evas show (ec:%p)", evhp->ec);
+   if (evhp->current_fb)
+     _e_video_buffer_show(evhp, evhp->current_fb, evhp->current_fb->content_t);
+}
+
+static void
+_e_video_cb_evas_hide(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   E_Video_Hwc_Planes *evhp = data;
+
+   if (e_object_is_del(E_OBJECT(evhp->ec))) return;
+
+   if (!evhp->ec->comp_data->video_client)
+     return;
+
+   /* if stand_alone is true, not hide */
+   if (evhp->ec->comp_data->sub.data && evhp->ec->comp_data->sub.data->stand_alone)
+     {
+        if (!evhp->layer) return;
+
+        if (evhp->tdm_mute_id != -1)
+          {
+             Tdm_Prop_Value prop = {.id = evhp->tdm_mute_id, .value.u32 = 1};
+             VIN("video surface hide. mute on (ec:%p)", evhp->ec);
+             _e_video_layer_set_property(evhp->layer, &prop);
+          }
+        return;
+     }
+
+   VIN("evas hide (ec:%p)", evhp->ec);
+   _e_video_frame_buffer_show(evhp, NULL);
+}
+
+static E_Video_Hwc_Planes *
+_e_video_create(E_Client *ec)
+{
+   E_Video_Hwc_Planes *evhp;
+
+   evhp = calloc(1, sizeof *evhp);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(evhp, NULL);
+
+   evhp->ec = ec;
+   evhp->pp_align = -1;
+   evhp->video_align = -1;
+   evhp->tdm_mute_id = -1;
+
+   if (!_e_video_set(evhp, ec))
+     {
+        free(evhp);
+        return NULL;
+     }
+
+   VIN("create. ec(%p) wl_surface@%d", ec, wl_resource_get_id(evhp->ec->comp_data->surface));
+
+   video_list = eina_list_append(video_list, evhp);
+
+   return evhp;
+}
+
+static tdm_error
+_e_video_layer_get_available_properties(E_Video_Layer *layer,
+                                        const tdm_prop **props,
+                                        int *count)
+{
+   tdm_error ret = TDM_ERROR_OPERATION_FAILED;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(layer, TDM_ERROR_BAD_REQUEST);
+   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_output_video_available_tdm_layer_get(evhp->e_output); */
+        tlayer = _e_video_tdm_available_video_layer_get(layer->evhp->output);
+     }
+   ret = tdm_layer_get_available_properties(tlayer, props, count);
+
+   return ret;
+}
+
+static tdm_error
+_e_video_layer_get_property(E_Video_Layer * layer, unsigned id, tdm_value *value)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(layer, TDM_ERROR_BAD_REQUEST);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(value, TDM_ERROR_BAD_REQUEST);
+
+   return tdm_layer_get_property(layer->tdm_layer, id, value);
+}
+
+static Eina_Bool
+_e_video_set(E_Video_Hwc_Planes *evhp, E_Client *ec)
+{
+   const tdm_prop *props;
+   int i, count = 0;
+
+   evhp->ec = ec;
+   evhp->window = e_client_util_win_get(ec);
+
+   if (e_config->eom_enable == EINA_TRUE)
+     {
+        evhp->external_video = e_eom_is_ec_external(ec);
+        if (evhp->external_video)
+          {
+             tdm_error ret;
+             unsigned int index = 0;
+
+             evhp->output = e_eom_tdm_output_by_ec_get(ec);
+             EINA_SAFETY_ON_NULL_RETURN_VAL(evhp->output, EINA_FALSE);
+
+             ret = tdm_output_get_pipe(evhp->output, &index);
+             EINA_SAFETY_ON_FALSE_RETURN_VAL(ret == TDM_ERROR_NONE, EINA_FALSE);
+
+             evhp->e_output = e_output_find_by_index(index);
+             EINA_SAFETY_ON_NULL_RETURN_VAL(evhp->e_output, EINA_FALSE);
+
+             ec->comp_data->video_client = 1;
+
+             return EINA_TRUE;
+          }
+     }
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(evhp->ec->zone, EINA_FALSE);
+
+   evhp->e_output = e_output_find(evhp->ec->zone->output_id);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(evhp->e_output, EINA_FALSE);
+
+   evhp->output = evhp->e_output->toutput;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(evhp->output, EINA_FALSE);
+
+   /* if (e_output_video_capability_get(evhp->e_output)) */
+   if (_e_video_tdm_output_has_video_layer(evhp->output))
+     {
+        /* If tdm offers video layers, we will assign a tdm layer when showing */
+        VIN("video client");
+        ec->comp_data->video_client = 1;
+     }
+   else if (_e_video_set_layer(evhp, EINA_TRUE))
+     {
+        /* If tdm doesn't offer video layers, we assign a tdm layer now. If failed,
+         * video will be displayed via the UI rendering path.
+         */
+        VIN("video client");
+        ec->comp_data->video_client = 1;
+     }
+   else
+     return EINA_FALSE;
+
+   e_zone_video_available_size_get(ec->zone, NULL, NULL, NULL, NULL, &evhp->video_align);
+
+   _e_video_layer_get_available_properties(evhp->layer, &props, &count);
+   for (i = 0; i < count; i++)
+     {
+        tdm_value value;
+
+        _e_video_layer_get_property(evhp->layer, props[i].id, &value);
+        if (!strncmp(props[i].name, "mute", TDM_NAME_LEN))
+          evhp->tdm_mute_id = props[i].id;
+     }
+
+   return EINA_TRUE;
+}
+
+static void
+_e_video_hide(E_Video_Hwc_Planes *evhp)
+{
+   E_Comp_Wl_Video_Buf *vbuf;
+
+   if (evhp->current_fb || evhp->committed_list)
+     _e_video_frame_buffer_show(evhp, NULL);
+
+   if (evhp->current_fb)
+     {
+        e_comp_wl_video_buffer_set_use(evhp->current_fb, EINA_FALSE);
+        evhp->current_fb = NULL;
+     }
+
+   if (evhp->old_comp_buffer)
+     evhp->old_comp_buffer = NULL;
+
+   EINA_LIST_FREE(evhp->committed_list, vbuf)
+      e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
+
+   EINA_LIST_FREE(evhp->waiting_list, vbuf)
+      e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
+}
+
+static void
+_e_video_destroy(E_Video_Hwc_Planes *evhp)
+{
+   E_Comp_Wl_Video_Buf *vbuf;
+   Eina_List *l = NULL, *ll = NULL;
+
+   if (!evhp)
+     return;
+
+   VIN("destroy");
+
+   if (evhp->cb_registered)
+     {
+        evas_object_event_callback_del_full(evhp->ec->frame, EVAS_CALLBACK_RESIZE,
+                                            _e_video_cb_evas_resize, evhp);
+        evas_object_event_callback_del_full(evhp->ec->frame, EVAS_CALLBACK_MOVE,
+                                            _e_video_cb_evas_move, evhp);
+     }
+
+   _e_video_hide(evhp);
+
+   /* others */
+   EINA_LIST_FOREACH_SAFE(evhp->input_buffer_list, l, ll, vbuf)
+     {
+        e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
+        e_comp_wl_video_buffer_unref(vbuf);
+     }
+
+   EINA_LIST_FOREACH_SAFE(evhp->pp_buffer_list, l, ll, vbuf)
+     {
+        e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
+        e_comp_wl_video_buffer_unref(vbuf);
+     }
+
+   if(evhp->tdm_prop_list)
+     {
+        Tdm_Prop_Value *tdm_prop;
+        EINA_LIST_FREE(evhp->tdm_prop_list, tdm_prop)
+          {
+             free(tdm_prop);
+          }
+     }
+   if(evhp->late_tdm_prop_list)
+     {
+        Tdm_Prop_Value *tdm_prop;
+        EINA_LIST_FREE(evhp->late_tdm_prop_list, tdm_prop)
+          {
+             free(tdm_prop);
+          }
+     }
+
+   if (evhp->input_buffer_list)
+     NEVER_GET_HERE();
+   if (evhp->pp_buffer_list)
+     NEVER_GET_HERE();
+   if (evhp->tdm_prop_list)
+     NEVER_GET_HERE();
+   if (evhp->late_tdm_prop_list)
+     NEVER_GET_HERE();
+
+   /* destroy converter second */
+   if (evhp->pp)
+     tdm_pp_destroy(evhp->pp);
+
+   if (evhp->layer)
+     {
+        VIN("unset layer: destroy");
+        _e_video_set_layer(evhp, EINA_FALSE);
+     }
+
+   video_list = eina_list_remove(video_list, evhp);
+
+   free(evhp);
+
+#if 0
+   if (e_comp_wl_video_buffer_list_length() > 0)
+     e_comp_wl_video_buffer_list_print(NULL);
+#endif
+}
+
+static Eina_Bool
+_e_video_check_if_pp_needed(E_Video_Hwc_Planes *evhp)
+{
+   int i, count = 0;
+   const tbm_format *formats;
+   Eina_Bool found = EINA_FALSE;
+   tdm_layer_capability capabilities = 0;
+
+
+   tdm_layer *layer = _e_video_tdm_video_layer_get(evhp->output);
+
+   tdm_layer_get_capabilities(layer, &capabilities);
+
+   /* 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] == evhp->tbmfmt)
+       {
+          found = EINA_TRUE;
+          break;
+       }
+
+   if (!found)
+     {
+        if (formats && count > 0)
+          evhp->pp_tbmfmt = formats[0];
+        else
+          {
+             WRN("No layer format information!!!");
+             evhp->pp_tbmfmt = TBM_FORMAT_ARGB8888;
+          }
+        return EINA_TRUE;
+     }
+
+   if (capabilities & TDM_LAYER_CAPABILITY_SCANOUT)
+     goto need_pp;
+
+   /* check size */
+   if (evhp->geo.input_r.w != evhp->geo.output_r.w || evhp->geo.input_r.h != evhp->geo.output_r.h)
+     if (!(capabilities & TDM_LAYER_CAPABILITY_SCALE))
+       goto need_pp;
+
+   /* check rotate */
+   if (evhp->geo.transform || e_comp->e_comp_screen->rotation > 0)
+     if (!(capabilities & TDM_LAYER_CAPABILITY_TRANSFORM))
+       goto need_pp;
+
+   return EINA_FALSE;
+
+need_pp:
+   evhp->pp_tbmfmt = evhp->tbmfmt;
+   return EINA_TRUE;
+}
+
+static void
+_e_video_pp_cb_done(tdm_pp *pp, tbm_surface_h sb, tbm_surface_h db, void *user_data)
+{
+   E_Video_Hwc_Planes *evhp = (E_Video_Hwc_Planes*)user_data;
+   E_Comp_Wl_Video_Buf *input_buffer, *pp_buffer;
+
+   input_buffer = _e_video_vbuf_find(evhp->input_buffer_list, sb);
+   if (input_buffer)
+     e_comp_wl_video_buffer_unref(input_buffer);
+
+   pp_buffer = _e_video_vbuf_find(evhp->pp_buffer_list, db);
+   if (pp_buffer)
+     {
+        e_comp_wl_video_buffer_set_use(pp_buffer, EINA_FALSE);
+        if (!_e_video_is_visible(evhp)) return;
+
+        _e_video_buffer_show(evhp, pp_buffer, 0);
+     }
+   else
+     {
+        VER("There is no pp_buffer");
+        // there is no way to set in_use flag.
+        // This will cause issue when server get available pp_buffer.
+     }
+}
+
+static void
+_e_video_render(E_Video_Hwc_Planes *evhp, const char *func)
+{
+   E_Comp_Wl_Buffer *comp_buffer;
+   E_Comp_Wl_Video_Buf *pp_buffer = NULL;
+   E_Comp_Wl_Video_Buf *input_buffer = NULL;
+   E_Client *topmost;
+
+   EINA_SAFETY_ON_NULL_RETURN(evhp->ec);
+
+   /* buffer can be NULL when camera/video's mode changed. Do nothing and
+    * keep previous frame in this case.
+    */
+   if (!evhp->ec->pixmap)
+     return;
+
+   if (!_e_video_is_visible(evhp))
+     {
+        _e_video_hide(evhp);
+        return;
+     }
+
+   comp_buffer = e_pixmap_resource_get(evhp->ec->pixmap);
+   if (!comp_buffer) return;
+
+   _e_video_format_info_get(evhp);
+
+   /* not interested with other buffer type */
+   if (!wayland_tbm_server_get_surface(NULL, comp_buffer->resource))
+     return;
+
+   topmost = e_comp_wl_topmost_parent_get(evhp->ec);
+   EINA_SAFETY_ON_NULL_RETURN(topmost);
+
+   if(e_comp_wl_viewport_is_changed(topmost))
+     {
+        VIN("need update viewport: apply topmost");
+        e_comp_wl_viewport_apply(topmost);
+     }
+
+   if (!_e_video_geometry_cal(evhp))
+     {
+        if(!evhp->need_force_render && !_e_video_parent_is_viewable(evhp))
+          {
+             VIN("need force render");
+             evhp->need_force_render = EINA_TRUE;
+          }
+        return;
+     }
+
+   DBG("====================================== (%s)", func);
+   VDB("old: "GEO_FMT" buf(%p)", GEO_ARG(&evhp->old_geo), evhp->old_comp_buffer);
+   VDB("new: "GEO_FMT" buf(%p) %c%c%c%c", GEO_ARG(&evhp->geo), comp_buffer, FOURCC_STR(evhp->tbmfmt));
+
+   if (!memcmp(&evhp->old_geo, &evhp->geo, sizeof evhp->geo) &&
+       evhp->old_comp_buffer == comp_buffer)
+     return;
+
+   evhp->need_force_render = EINA_FALSE;
+
+   _e_video_input_buffer_valid(evhp, comp_buffer);
+
+   if (!_e_video_check_if_pp_needed(evhp))
+     {
+        /* 1. non converting case */
+        input_buffer = _e_video_input_buffer_get(evhp, comp_buffer, EINA_TRUE);
+        EINA_SAFETY_ON_NULL_GOTO(input_buffer, render_fail);
+
+        _e_video_buffer_show(evhp, input_buffer, evhp->geo.tdm_transform);
+
+        evhp->old_geo = evhp->geo;
+        evhp->old_comp_buffer = comp_buffer;
+
+        goto done;
+     }
+
+   /* 2. converting case */
+   if (!evhp->pp)
+     {
+        tdm_pp_capability pp_cap;
+        tdm_error error = TDM_ERROR_NONE;
+
+        evhp->pp = tdm_display_create_pp(e_comp->e_comp_screen->tdisplay, NULL);
+        EINA_SAFETY_ON_NULL_GOTO(evhp->pp, render_fail);
+
+        tdm_display_get_pp_available_size(e_comp->e_comp_screen->tdisplay, &evhp->pp_minw, &evhp->pp_minh,
+                                          &evhp->pp_maxw, &evhp->pp_maxh, &evhp->pp_align);
+
+        error = tdm_display_get_pp_capabilities(e_comp->e_comp_screen->tdisplay, &pp_cap);
+        if (error == TDM_ERROR_NONE)
+          {
+             if (pp_cap & TDM_PP_CAPABILITY_SCANOUT)
+               evhp->pp_scanout = EINA_TRUE;
+          }
+     }
+
+   if ((evhp->pp_minw > 0 && (evhp->geo.input_r.w < evhp->pp_minw || evhp->geo.tdm_output_r.w < evhp->pp_minw)) ||
+       (evhp->pp_minh > 0 && (evhp->geo.input_r.h < evhp->pp_minh || evhp->geo.tdm_output_r.h < evhp->pp_minh)) ||
+       (evhp->pp_maxw > 0 && (evhp->geo.input_r.w > evhp->pp_maxw || evhp->geo.tdm_output_r.w > evhp->pp_maxw)) ||
+       (evhp->pp_maxh > 0 && (evhp->geo.input_r.h > evhp->pp_maxh || evhp->geo.tdm_output_r.h > evhp->pp_maxh)))
+     {
+        INF("size(%dx%d, %dx%d) is out of PP range",
+            evhp->geo.input_r.w, evhp->geo.input_r.h, evhp->geo.tdm_output_r.w, evhp->geo.tdm_output_r.h);
+        goto done;
+     }
+
+   input_buffer = _e_video_input_buffer_get(evhp, comp_buffer, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_GOTO(input_buffer, render_fail);
+
+   pp_buffer = _e_video_pp_buffer_get(evhp, evhp->geo.tdm_output_r.w, evhp->geo.tdm_output_r.h);
+   EINA_SAFETY_ON_NULL_GOTO(pp_buffer, render_fail);
+
+   if (memcmp(&evhp->old_geo, &evhp->geo, sizeof evhp->geo))
+     {
+        tdm_info_pp info;
+
+        CLEAR(info);
+        info.src_config.size.h = input_buffer->width_from_pitch;
+        info.src_config.size.v = input_buffer->height_from_size;
+        info.src_config.pos.x = evhp->geo.input_r.x;
+        info.src_config.pos.y = evhp->geo.input_r.y;
+        info.src_config.pos.w = evhp->geo.input_r.w;
+        info.src_config.pos.h = evhp->geo.input_r.h;
+        info.src_config.format = evhp->tbmfmt;
+        info.dst_config.size.h = pp_buffer->width_from_pitch;
+        info.dst_config.size.v = pp_buffer->height_from_size;
+        info.dst_config.pos.w = evhp->geo.tdm_output_r.w;
+        info.dst_config.pos.h = evhp->geo.tdm_output_r.h;
+        info.dst_config.format = evhp->pp_tbmfmt;
+        info.transform = evhp->geo.tdm_transform;
+
+        if (tdm_pp_set_info(evhp->pp, &info))
+          {
+             VER("tdm_pp_set_info() failed");
+             goto render_fail;
+          }
+
+        if (tdm_pp_set_done_handler(evhp->pp, _e_video_pp_cb_done, evhp))
+          {
+             VER("tdm_pp_set_done_handler() failed");
+             goto render_fail;
+          }
+
+        CLEAR(evhp->pp_r);
+        evhp->pp_r.w = info.dst_config.pos.w;
+        evhp->pp_r.h = info.dst_config.pos.h;
+     }
+
+   pp_buffer->content_r = evhp->pp_r;
+
+   if (tdm_pp_attach(evhp->pp, input_buffer->tbm_surface, pp_buffer->tbm_surface))
+     {
+        VER("tdm_pp_attach() failed");
+        goto render_fail;
+     }
+
+   e_comp_wl_video_buffer_set_use(pp_buffer, EINA_TRUE);
+
+   e_comp_wl_buffer_reference(&input_buffer->buffer_ref, comp_buffer);
+
+   if (tdm_pp_commit(evhp->pp))
+     {
+        VER("tdm_pp_commit() failed");
+        e_comp_wl_video_buffer_set_use(pp_buffer, EINA_FALSE);
+        goto render_fail;
+     }
+
+   evhp->old_geo = evhp->geo;
+   evhp->old_comp_buffer = comp_buffer;
+
+   goto done;
+
+render_fail:
+   if (input_buffer)
+     e_comp_wl_video_buffer_unref(input_buffer);
+
+done:
+   if (!evhp->cb_registered)
+     {
+        evas_object_event_callback_add(evhp->ec->frame, EVAS_CALLBACK_RESIZE,
+                                       _e_video_cb_evas_resize, evhp);
+        evas_object_event_callback_add(evhp->ec->frame, EVAS_CALLBACK_MOVE,
+                                       _e_video_cb_evas_move, evhp);
+        evhp->cb_registered = EINA_TRUE;
+     }
+   DBG("======================================.");
+}
+
+static Eina_Bool
+_e_video_cb_ec_buffer_change(void *data, int type, void *event)
+{
+   E_Client *ec;
+   E_Event_Client *ev = event;
+   E_Video_Hwc_Planes *evhp;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ev->ec, ECORE_CALLBACK_PASS_ON);
+
+   evhp = data;
+   ec = ev->ec;
+
+   if (evhp->ec != ec)
+     return ECORE_CALLBACK_PASS_ON;
+
+   if (e_object_is_del(E_OBJECT(ec)))
+     return ECORE_CALLBACK_PASS_ON;
+
+   /* not interested with non video_surface,  */
+   if (!evhp->ec->comp_data->video_client)
+     return ECORE_CALLBACK_PASS_ON;
+
+   if (e_config->eom_enable == EINA_TRUE)
+     {
+        /* skip external client buffer if its top parent is not current for eom anymore */
+        if (evhp->external_video && e_eom_is_ec_external(ec))
+          {
+             VWR("skip external buffer");
+             return ECORE_CALLBACK_PASS_ON;
+          }
+     }
+
+   _e_video_render(evhp, __FUNCTION__);
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_video_cb_ec_client_show(void *data, int type, void *event)
+{
+   E_Event_Client *ev = event;
+   E_Client *ec;
+   E_Client *video_ec = NULL;
+   E_Video_Hwc_Planes *evhp = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ev->ec, ECORE_CALLBACK_PASS_ON);
+
+   ec = ev->ec;
+   if (!ec->comp_data) return ECORE_CALLBACK_PASS_ON;
+
+   video_ec = find_video_child_get(ec);
+   if (!video_ec) return ECORE_CALLBACK_PASS_ON;
+
+   evhp = data;
+   if (!evhp) return ECORE_CALLBACK_PASS_ON;
+
+   VIN("client(0x%08"PRIxPTR") show: find video child(0x%08"PRIxPTR")", (Ecore_Window)e_client_util_win_get(ec), (Ecore_Window)e_client_util_win_get(video_ec));
+   if(evhp->old_comp_buffer)
+     {
+        VIN("video already rendering..");
+        return ECORE_CALLBACK_PASS_ON;
+     }
+
+   if (ec == e_comp_wl_topmost_parent_get(evhp->ec))
+     {
+        if (e_config->eom_enable == EINA_TRUE)
+          {
+             /* skip external client buffer if its top parent is not current for eom anymore */
+             if (evhp->external_video && e_eom_is_ec_external(ec))
+               {
+                  VWR("skip external buffer");
+                  return ECORE_CALLBACK_PASS_ON;
+               }
+          }
+
+        VIN("video need rendering..");
+        e_comp_wl_viewport_apply(ec);
+        _e_video_render(evhp, __FUNCTION__);
+     }
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_video_cb_ec_visibility_change(void *data, int type, void *event)
+{
+   E_Event_Remote_Surface_Provider *ev = event;
+   E_Client *ec = ev->ec;
+   E_Video_Hwc_Planes *evhp;
+   Eina_List *l;
+
+   EINA_LIST_FOREACH(video_list, l, evhp)
+     {
+        E_Client *offscreen_parent = find_offscreen_parent_get(evhp->ec);
+        if (!offscreen_parent) continue;
+        if (offscreen_parent != ec) continue;
+        switch (ec->visibility.obscured)
+          {
+           case E_VISIBILITY_FULLY_OBSCURED:
+              _e_video_cb_evas_hide(evhp, NULL, NULL, NULL);
+              break;
+           case E_VISIBILITY_UNOBSCURED:
+              _e_video_cb_evas_show(evhp, NULL, NULL, NULL);
+              break;
+           default:
+              VER("Not implemented");
+              return ECORE_CALLBACK_PASS_ON;
+          }
+     }
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_video_cb_topmost_ec_visibility_change(void *data, int type, void *event)
+{
+   E_Event_Client *ev = event;
+   E_Client *ec = ev->ec;
+   E_Video_Hwc_Planes *evhp;
+   Eina_List *l = NULL;
+
+   EINA_LIST_FOREACH(video_list, l, evhp)
+     {
+        E_Client *topmost = e_comp_wl_topmost_parent_get(evhp->ec);
+        if (!topmost) continue;
+        if (topmost == evhp->ec) continue;
+        if (topmost != ec) continue;
+        if (evhp->follow_topmost_visibility)
+          {
+             switch (ec->visibility.obscured)
+               {
+                case E_VISIBILITY_FULLY_OBSCURED:
+                   VIN("follow_topmost_visibility: fully_obscured");
+                   _e_video_cb_evas_hide(evhp, NULL, NULL, NULL);
+                   break;
+                case E_VISIBILITY_UNOBSCURED:
+                   VIN("follow_topmost_visibility: UNOBSCURED");
+                   _e_video_cb_evas_show(evhp, NULL, NULL, NULL);
+                   break;
+                default:
+                   return ECORE_CALLBACK_PASS_ON;
+               }
+          }
+     }
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static tdm_layer *
+_e_video_tdm_video_layer_get(tdm_output *output)
+{
+   int i, count = 0;
+#ifdef CHECKING_PRIMARY_ZPOS
+   int primary_idx = 0, primary_zpos = 0;
+   tdm_layer *primary_layer;
+#endif
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
+
+   tdm_output_get_layer_count(output, &count);
+   for (i = 0; i < count; i++)
+     {
+        tdm_layer *layer = tdm_output_get_layer(output, i, NULL);
+        tdm_layer_capability capabilities = 0;
+        EINA_SAFETY_ON_NULL_RETURN_VAL(layer, NULL);
+
+        tdm_layer_get_capabilities(layer, &capabilities);
+        if (capabilities & TDM_LAYER_CAPABILITY_VIDEO)
+          return layer;
+     }
+
+#ifdef CHECKING_PRIMARY_ZPOS
+   tdm_output_get_primary_index(output, &primary_idx);
+   primary_layer = tdm_output_get_layer(output, primary_idx, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(primary_layer, NULL);
+   tdm_layer_get_zpos(primary_layer, &primary_zpos);
+#endif
+
+   for (i = 0; i < count; i++)
+     {
+        tdm_layer *layer = tdm_output_get_layer(output, i, NULL);
+        tdm_layer_capability capabilities = 0;
+        EINA_SAFETY_ON_NULL_RETURN_VAL(layer, NULL);
+
+        tdm_layer_get_capabilities(layer, &capabilities);
+        if (capabilities & TDM_LAYER_CAPABILITY_OVERLAY)
+          {
+#ifdef CHECKING_PRIMARY_ZPOS
+             int zpos = 0;
+             tdm_layer_get_zpos(layer, &zpos);
+             if (zpos >= primary_zpos) continue;
+#endif
+             return layer;
+          }
+     }
+
+   return NULL;
+}
+
+static tdm_layer *
+_e_video_tdm_available_video_layer_get(tdm_output *output)
+{
+   Eina_Bool has_video_layer = EINA_FALSE;
+   int i, count = 0;
+#ifdef CHECKING_PRIMARY_ZPOS
+   int primary_idx = 0, primary_zpos = 0;
+   tdm_layer *primary_layer;
+#endif
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
+
+   /* check video layers first */
+   tdm_output_get_layer_count(output, &count);
+   for (i = 0; i < count; i++)
+     {
+        tdm_layer *layer = tdm_output_get_layer(output, i, NULL);
+        tdm_layer_capability capabilities = 0;
+        EINA_SAFETY_ON_NULL_RETURN_VAL(layer, NULL);
+
+        tdm_layer_get_capabilities(layer, &capabilities);
+        if (capabilities & TDM_LAYER_CAPABILITY_VIDEO)
+          {
+             has_video_layer = EINA_TRUE;
+             if (!_e_video_tdm_get_layer_usable(layer)) continue;
+             return layer;
+          }
+     }
+
+   /* if a output has video layers, it means that there is no available video layer for video */
+   if (has_video_layer)
+     return NULL;
+
+   /* check graphic layers second */
+#ifdef CHECKING_PRIMARY_ZPOS
+   tdm_output_get_primary_index(output, &primary_idx);
+   primary_layer = tdm_output_get_layer(output, primary_idx, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(primary_layer, NULL);
+   tdm_layer_get_zpos(primary_layer, &primary_zpos);
+#endif
+
+   for (i = 0; i < count; i++)
+     {
+        tdm_layer *layer = tdm_output_get_layer(output, i, NULL);
+        tdm_layer_capability capabilities = 0;
+        EINA_SAFETY_ON_NULL_RETURN_VAL(layer, NULL);
+
+        tdm_layer_get_capabilities(layer, &capabilities);
+        if (capabilities & TDM_LAYER_CAPABILITY_OVERLAY)
+          {
+#ifdef CHECKING_PRIMARY_ZPOS
+             int zpos = 0;
+             tdm_layer_get_zpos(layer, &zpos);
+             if (zpos >= primary_zpos) continue;
+#endif
+             if (!_e_video_tdm_get_layer_usable(layer)) continue;
+             return layer;
+          }
+     }
+
+   return NULL;
+}
+
+static void
+_e_video_tdm_set_layer_usable(tdm_layer *layer, Eina_Bool usable)
+{
+   if (usable)
+     video_layers = eina_list_remove(video_layers, layer);
+   else
+     {
+        tdm_layer *used_layer;
+        Eina_List *l = NULL;
+        EINA_LIST_FOREACH(video_layers, l, used_layer)
+           if (used_layer == layer) return;
+        video_layers = eina_list_append(video_layers, layer);
+     }
+}
+
+static Eina_Bool
+_e_video_tdm_get_layer_usable(tdm_layer *layer)
+{
+   tdm_layer *used_layer;
+   Eina_List *l = NULL;
+   EINA_LIST_FOREACH(video_layers, l, used_layer)
+      if (used_layer == layer)
+        return EINA_FALSE;
+   return EINA_TRUE;
+}
+
+static void
+_e_video_hwc_planes_ec_event_deinit(E_Video_Hwc_Planes *evhp)
+{
+   E_Client *ec;
+
+   ec = evhp->ec;
+
+   evas_object_event_callback_del_full(ec->frame, EVAS_CALLBACK_SHOW,
+                                       _e_video_cb_evas_show, evhp);
+   evas_object_event_callback_del_full(ec->frame, EVAS_CALLBACK_HIDE,
+                                       _e_video_cb_evas_hide, evhp);
+
+   E_FREE_LIST(evhp->ec_event_handler, ecore_event_handler_del);
+}
+
+const char *
+_e_video_hwc_planes_prop_name_get_by_id(E_Video_Hwc_Planes *evhp, unsigned int id)
+{
+   tdm_layer *layer;
+   const tdm_prop *props;
+   int i, count = 0;
+
+   layer = _e_video_tdm_video_layer_get(evhp->output);
+   tdm_layer_get_available_properties(layer, &props, &count);
+   for (i = 0; i < count; i++)
+     {
+        if (props[i].id == id)
+          {
+             VDB("check property(%s)", props[i].name);
+             return props[i].name;
+          }
+     }
+
+   return NULL;
+}
+
+static Eina_Bool
+_e_video_hwc_planes_property_post_set(E_Video_Hwc_Planes *evhp,
+                                      unsigned int id,
+                                      const char *name,
+                                      tdm_value value)
+{
+   Tdm_Prop_Value *prop = NULL;
+   const Eina_List *l = NULL;
+
+   EINA_LIST_FOREACH(evhp->late_tdm_prop_list, l, prop)
+     {
+        if (!strncmp(name, prop->name, TDM_NAME_LEN))
+          {
+             prop->value.u32 = value.u32;
+             VDB("update property(%s) value(%d)", prop->name, value.u32);
+             return EINA_FALSE;
+          }
+     }
+
+   prop = calloc(1, sizeof(Tdm_Prop_Value));
+   if(!prop) return EINA_FALSE;
+
+   prop->value.u32 = value.u32;
+   prop->id = id;
+   memcpy(prop->name, name, sizeof(TDM_NAME_LEN));
+   VIN("Add property(%s) value(%d)", prop->name, value.u32);
+   evhp->late_tdm_prop_list = eina_list_append(evhp->late_tdm_prop_list, prop);
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_video_hwc_planes_property_pre_set(E_Video_Hwc_Planes *evhp,
+                                     unsigned int id,
+                                     const char *name,
+                                     tdm_value value)
+{
+   Tdm_Prop_Value *prop = NULL;
+   const Eina_List *l = NULL;
+
+   EINA_LIST_FOREACH(evhp->tdm_prop_list, l, prop)
+     {
+        if (!strncmp(name, prop->name, TDM_NAME_LEN))
+          {
+             VDB("find prop data(%s) update value(%d -> %d)",
+                 prop->name, (unsigned int)prop->value.u32, (unsigned int)value.u32);
+             prop->value.u32 = value.u32;
+             return EINA_TRUE;
+          }
+     }
+   EINA_LIST_FOREACH(evhp->late_tdm_prop_list, l, prop)
+     {
+        if (!strncmp(name, prop->name, TDM_NAME_LEN))
+          {
+             VDB("find prop data(%s) update value(%d -> %d)",
+                 prop->name, (unsigned int)prop->value.u32, (unsigned int)value.u32);
+             prop->value.u32 = value.u32;
+             return EINA_TRUE;
+          }
+     }
+
+   prop = calloc(1, sizeof(Tdm_Prop_Value));
+   if(!prop) return EINA_FALSE;
+   prop->value.u32 = value.u32;
+   prop->id = id;
+   memcpy(prop->name, name, sizeof(TDM_NAME_LEN));
+   VIN("Add property(%s) value(%d)", prop->name, value.u32);
+   evhp->tdm_prop_list = eina_list_append(evhp->tdm_prop_list, prop);
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_video_hwc_planes_property_save(E_Video_Hwc_Planes *evhp, unsigned int id, const char *name, tdm_value value)
+{
+   /* FIXME workaround
+    * if mute off, need to do it after buffer commit */
+   if ((id == evhp->tdm_mute_id) && value.u32 == 0)
+     return _e_video_hwc_planes_property_post_set(evhp, id, name, value);
+   else
+     return _e_video_hwc_planes_property_pre_set(evhp, id, name, value);
+}
+
+static void
+_e_video_hwc_planes_ec_event_init(E_Video_Hwc_Planes *evhp)
+{
+   E_Client *ec;
+
+   ec = evhp->ec;
+
+   evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_SHOW,
+                                  _e_video_cb_evas_show, evhp);
+   evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_HIDE,
+                                  _e_video_cb_evas_hide, evhp);
+
+   E_LIST_HANDLER_APPEND(evhp->ec_event_handler, E_EVENT_CLIENT_BUFFER_CHANGE,
+                         _e_video_cb_ec_buffer_change, evhp);
+   E_LIST_HANDLER_APPEND(evhp->ec_event_handler, E_EVENT_CLIENT_SHOW,
+                         _e_video_cb_ec_client_show, evhp);
+   E_LIST_HANDLER_APPEND(evhp->ec_event_handler, E_EVENT_REMOTE_SURFACE_PROVIDER_VISIBILITY_CHANGE,
+                         _e_video_cb_ec_visibility_change, evhp);
+   E_LIST_HANDLER_APPEND(evhp->ec_event_handler, E_EVENT_CLIENT_VISIBILITY_CHANGE,
+                         _e_video_cb_topmost_ec_visibility_change, evhp);
+}
+
+static void
+_e_video_hwc_planes_iface_destroy(E_Video_Comp_Iface *iface)
+{
+   IFACE_ENTRY;
+
+   _e_video_hwc_planes_ec_event_deinit(evhp);
+   _e_video_destroy(evhp);
+}
+
+static Eina_Bool
+_e_video_hwc_planes_iface_follow_topmost_visibility(E_Video_Comp_Iface *iface)
+{
+   IFACE_ENTRY;
+
+   evhp->follow_topmost_visibility = EINA_TRUE;
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_video_hwc_planes_iface_unfollow_topmost_visibility(E_Video_Comp_Iface *iface)
+{
+   IFACE_ENTRY;
+
+   evhp->follow_topmost_visibility = EINA_FALSE;
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_video_hwc_planes_iface_allowed_property(E_Video_Comp_Iface *iface)
+{
+   IFACE_ENTRY;
+
+   evhp->allowed_attribute = EINA_TRUE;
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_video_hwc_planes_iface_disallowed_property(E_Video_Comp_Iface *iface)
+{
+   IFACE_ENTRY;
+
+   evhp->allowed_attribute = EINA_FALSE;
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_video_hwc_planes_iface_property_get(E_Video_Comp_Iface *iface, unsigned int id, tdm_value *value)
+{
+   tdm_error ret;
+
+   IFACE_ENTRY;
+
+   ret = _e_video_layer_get_property(evhp->layer, id, value);
+   if (ret != TDM_ERROR_NONE)
+     return EINA_FALSE;
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_video_hwc_planes_iface_property_set(E_Video_Comp_Iface *iface, unsigned int id, tdm_value value)
+{
+   Tdm_Prop_Value prop;
+   const char *name;
+
+   IFACE_ENTRY;
+
+   VIN("set layer: set_attribute");
+
+   name = _e_video_hwc_planes_prop_name_get_by_id(evhp, id);
+
+   if (!evhp->layer)
+     {
+        /* FIXME
+         * Set property with assigning layer right away if allowed_attribute
+         * flag is set. The reason why we have to do like this isn't figured
+         * yet. It's for backward compatibility. */
+        if (evhp->allowed_attribute)
+          {
+             if (!_e_video_set_layer(evhp, EINA_TRUE))
+               {
+                  VER("set layer failed");
+                  return EINA_FALSE;
+               }
+          }
+        else
+          {
+             VIN("no layer: save property value");
+             if (!_e_video_hwc_planes_property_save(evhp, id, name, value))
+               {
+                  VER("save property failed");
+                  return EINA_FALSE;
+               }
+
+             return EINA_TRUE;
+          }
+     }
+
+   VIN("set layer: call property(%s), value(%d)", name, value.u32);
+
+   prop.id = id;
+   prop.value = value;
+   _e_video_layer_set_property(evhp->layer, &prop);
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_video_hwc_planes_iface_property_delay_set(E_Video_Comp_Iface *iface, unsigned int id, tdm_value value)
+{
+   const char *name;
+
+   IFACE_ENTRY;
+
+   name = _e_video_hwc_planes_prop_name_get_by_id(evhp, id);
+
+   _e_video_hwc_planes_property_post_set(evhp, id, name, value);
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_video_hwc_planes_iface_available_properties_get(E_Video_Comp_Iface *iface, const tdm_prop **props, int *count)
+{
+   tdm_error ret;
+
+   IFACE_ENTRY;
+
+   ret = _e_video_layer_get_available_properties(evhp->layer, props, count);
+   if (ret != TDM_ERROR_NONE)
+     return EINA_FALSE;
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_video_hwc_planes_iface_info_get(E_Video_Comp_Iface *iface, E_Client_Video_Info *info)
+{
+   tdm_error ret;
+
+   IFACE_ENTRY;
+
+   ret = _e_video_layer_get_info(evhp->layer, info);
+   if (ret != TDM_ERROR_NONE)
+     return EINA_FALSE;
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_video_hwc_planes_iface_commit_data_release(E_Video_Comp_Iface *iface, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec)
+{
+   IFACE_ENTRY;
+
+   if (!evhp->layer)
+     return EINA_FALSE;
+
+   _e_video_commit_handler(NULL, sequence, tv_sec, tv_usec, evhp);
+
+   return EINA_TRUE;
+}
+
+static tbm_surface_h
+_e_video_hwc_planes_iface_tbm_surface_get(E_Video_Comp_Iface *iface)
+{
+   IFACE_ENTRY;
+
+   if (!evhp->layer)
+     return NULL;
+
+   return evhp->layer->cur_tsurface;
+}
+
+EINTERN E_Video_Comp_Iface *
+e_video_hwc_planes_iface_create(E_Client *ec)
+{
+   E_Video_Hwc_Planes *evhp;
+
+   INF("Initializing HWC Planes mode");
+
+   evhp = _e_video_create(ec);
+   if (!evhp)
+     {
+        ERR("Failed to create 'E_Video_Hwc_Planes'");
+        return NULL;
+     }
+
+   _e_video_hwc_planes_ec_event_init(evhp);
+
+   evhp->base.destroy = _e_video_hwc_planes_iface_destroy;
+   evhp->base.follow_topmost_visibility = _e_video_hwc_planes_iface_follow_topmost_visibility;
+   evhp->base.unfollow_topmost_visibility = _e_video_hwc_planes_iface_unfollow_topmost_visibility;
+   evhp->base.allowed_property = _e_video_hwc_planes_iface_allowed_property;
+   evhp->base.disallowed_property = _e_video_hwc_planes_iface_disallowed_property;
+   evhp->base.property_get = _e_video_hwc_planes_iface_property_get;
+   evhp->base.property_set = _e_video_hwc_planes_iface_property_set;
+   evhp->base.property_delay_set = _e_video_hwc_planes_iface_property_delay_set;
+   evhp->base.available_properties_get = _e_video_hwc_planes_iface_available_properties_get;
+   evhp->base.info_get = _e_video_hwc_planes_iface_info_get;
+   evhp->base.commit_data_release = _e_video_hwc_planes_iface_commit_data_release;
+   evhp->base.tbm_surface_get = _e_video_hwc_planes_iface_tbm_surface_get;
+
+   return &evhp->base;
+}