Support wayland vulkan wsi backend / frontend 72/64672/4 accepted/tizen/common/20160405.132514 accepted/tizen/common/20160412.130601 accepted/tizen/ivi/20160405.013146 accepted/tizen/ivi/20160412.005831 accepted/tizen/mobile/20160405.013054 accepted/tizen/mobile/20160412.005813 accepted/tizen/tv/20160405.013113 accepted/tizen/tv/20160412.005720 accepted/tizen/wearable/20160405.013133 accepted/tizen/wearable/20160412.005741 submit/tizen/20160404.145152 submit/tizen/20160411.104859
authorMun, Gwan-gyeong <kk.moon@samsung.com>
Fri, 1 Apr 2016 12:05:47 +0000 (21:05 +0900)
committerMun, Gwan-gyeong <kk.moon@samsung.com>
Mon, 4 Apr 2016 14:41:07 +0000 (23:41 +0900)
Change-Id: I0ba8249947b470c20d467e536b55ca0ad1d30f17

Makefile
src/tpl.c
src/tpl.h
src/tpl_gbm.c
src/tpl_internal.h
src/tpl_surface.c
src/tpl_tbm.c
src/tpl_wayland_egl.c [moved from src/tpl_wayland.c with 54% similarity]
src/tpl_wayland_vk_wsi.c [new file with mode: 0644]

index d8344cf..1f971fe 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -63,7 +63,8 @@ TPL_SRCS += $(SRC_DIR)/tpl_utils_hlist.c
 TPL_SRCS += $(SRC_DIR)/tpl_utils_map.c
 
 ifneq ($(call is-feature-enabled,winsys_wl),)
-TPL_SRCS += $(SRC_DIR)/tpl_wayland.c
+TPL_SRCS += $(SRC_DIR)/tpl_wayland_egl.c
+TPL_SRCS += $(SRC_DIR)/tpl_wayland_vk_wsi.c
 TPL_SRCS += $(SRC_DIR)/tpl_gbm.c
 endif
 
index ba50ede..e91966b 100644 (file)
--- a/src/tpl.c
+++ b/src/tpl.c
@@ -214,6 +214,8 @@ __tpl_display_choose_backend(tpl_handle_t native_dpy)
 #ifdef TPL_WINSYS_WL
                if (strcmp(plat_name, "tbm") == 0) return TPL_BACKEND_TBM;
                if (strcmp(plat_name, "wayland") == 0) return TPL_BACKEND_WAYLAND;
+               if (strcmp(plat_name, "wayland_vulkan_wsi") == 0) return
+                               TPL_BACKEND_WAYLAND_VULKAN_WSI;
                if (strcmp(plat_name, "drm") == 0) return TPL_BACKEND_GBM;
 #endif
        }
@@ -223,8 +225,10 @@ __tpl_display_choose_backend(tpl_handle_t native_dpy)
                return TPL_BACKEND_TBM;
        if (__tpl_display_choose_backend_gbm(native_dpy) == TPL_TRUE)
                return TPL_BACKEND_GBM;
-       if (__tpl_display_choose_backend_wayland(native_dpy) == TPL_TRUE)
+       if (__tpl_display_choose_backend_wayland_egl(native_dpy) == TPL_TRUE)
                return TPL_BACKEND_WAYLAND;
+       if (__tpl_display_choose_backend_wayland_vk_wsi(native_dpy) == TPL_TRUE)
+               return TPL_BACKEND_WAYLAND_VULKAN_WSI;
 #endif
 #ifdef TPL_WINSYS_DRI2
        if (__tpl_display_choose_backend_x11_dri2(native_dpy) == TPL_TRUE)
@@ -249,7 +253,10 @@ __tpl_display_init_backend(tpl_display_t *display, tpl_backend_type_t type)
                __tpl_display_init_backend_gbm(&display->backend);
                break;
        case TPL_BACKEND_WAYLAND:
-               __tpl_display_init_backend_wayland(&display->backend);
+               __tpl_display_init_backend_wayland_egl(&display->backend);
+               break;
+       case TPL_BACKEND_WAYLAND_VULKAN_WSI:
+               __tpl_display_init_backend_wayland_vk_wsi(&display->backend);
                break;
        case TPL_BACKEND_TBM:
                __tpl_display_init_backend_tbm(&display->backend);
@@ -282,7 +289,10 @@ __tpl_surface_init_backend(tpl_surface_t *surface, tpl_backend_type_t type)
                __tpl_surface_init_backend_gbm(&surface->backend);
                break;
        case TPL_BACKEND_WAYLAND:
-               __tpl_surface_init_backend_wayland(&surface->backend);
+               __tpl_surface_init_backend_wayland_egl(&surface->backend);
+               break;
+       case TPL_BACKEND_WAYLAND_VULKAN_WSI:
+               __tpl_surface_init_backend_wayland_vk_wsi(&surface->backend);
                break;
        case TPL_BACKEND_TBM:
                __tpl_surface_init_backend_tbm(&surface->backend);
index b81f4ae..38b5856 100644 (file)
--- a/src/tpl.h
+++ b/src/tpl.h
@@ -181,11 +181,12 @@ typedef enum {
  */
 typedef enum {
        TPL_BACKEND_UNKNOWN = -1,
-       TPL_BACKEND_WAYLAND,
+       TPL_BACKEND_WAYLAND, /* this backend represend wayland-egl */
        TPL_BACKEND_GBM,
        TPL_BACKEND_X11_DRI2,
        TPL_BACKEND_X11_DRI3,
        TPL_BACKEND_TBM,
+       TPL_BACKEND_WAYLAND_VULKAN_WSI,
        TPL_BACKEND_COUNT,
        TPL_BACKEND_MAX
 } tpl_backend_type_t;
@@ -451,7 +452,9 @@ tpl_surface_validate(tpl_surface_t *surface);
  * Calling this function multiple times within a single frame is not guranteed
  * to return a same buffer.
  *
- * @see tpl_surface_validate()
+ * @see tpl_surface_enqueue_buffer()
+ * @see tpl_surface_enqueue_buffer_with_damage()
+ * @see tpl_surface_get_swapchain_buffers()
  */
 tbm_surface_h
 tpl_surface_dequeue_buffer(tpl_surface_t *surface);
@@ -468,6 +471,9 @@ tpl_surface_dequeue_buffer(tpl_surface_t *surface);
  * @param surface surface to post a frame.
  * @param tbm_surface buffer to post.
  *
+ * @see tpl_surface_enqueue_buffer_with_damage()
+ * @see tpl_surface_dequeue_buffer()
+ * @see tpl_surface_get_swapchain_buffers()
  */
 tpl_result_t
 tpl_surface_enqueue_buffer(tpl_surface_t *surface, tbm_surface_h tbm_surface);
@@ -491,6 +497,8 @@ tpl_surface_enqueue_buffer(tpl_surface_t *surface, tbm_surface_h tbm_surface);
  * @param rects pointer to coordinates of rectangles. x0, y0, w0, h0, x1, y1, w1, h1...
  *
  * @see tpl_surface_enqueue_buffer()
+ * @see tpl_surface_dequeue_buffer()
+ * @see tpl_surface_get_swapchain_buffers()
  */
 tpl_result_t
 tpl_surface_enqueue_buffer_with_damage(tpl_surface_t *surface,
@@ -524,6 +532,75 @@ int
 tpl_surface_get_post_interval(tpl_surface_t *surface);
 
 /**
+ * Create a swapchain for the given TPL surface.
+ *
+ * This function creates buffers for swapchain which is binded to the given tpl surface.
+ *
+ * @param surface surface used for creation of swapchain buffers.
+ * @param format Pixel format of the swapchain
+ * @param width width to the swapchain buffer.
+ * @param height height to the swapchain buffer.
+ * @param buffer_count buffer count to the swapchain.
+ * @return TPL_ERROR_NONE if this function is supported and the tpl_surface is valid, TPL_ERROR otherwise.
+ *
+ * @see tpl_surface_get_swapchain_buffers()
+ * @see tpl_surface_destroy_swapchain()
+ */
+tpl_result_t
+tpl_surface_create_swapchain(tpl_surface_t *surface, tbm_format format,
+                            int width, int height, int buffer_count);
+
+/**
+ * Destroy a swapchain for the given TPL surface.
+ *
+ * @param surface surface used for destroying of swapchain buffers.
+ * @return TPL_ERROR_NONE if this function is supported and the tpl_surface is valid, TPL_ERROR otherwise.
+ *
+ * @see tpl_surface_create_swapchain()
+ * @see tpl_surface_get_swapchain_buffers()
+ */
+tpl_result_t
+tpl_surface_destroy_swapchain(tpl_surface_t *surface);
+
+/**
+ * Get the swapchain buffer list of the given TPL surface.
+ *
+ * This function returns the swapchain buffer list of binding to given TPL surface. Depending on backend,
+ * communication with the server might be required. Returned buffers are used
+ * for render target to draw frame.
+ *
+ * Returned buffers are valid until tpl_surface_enqueue_buffer().
+ * But if tpl_surface_validate() returns TPL_FALSE, previously returned buffers
+ * should no longer be used.
+ * caller reposible for free of the buffer list (only buffer list, do not free buffer list's contents)
+ *
+ * @param surface surface to get buffer list.
+ * @param buffers pointer to receive tbm_surface list value.
+ * @param buffer_count pointer to receive buffer_count value.
+ * @return TPL_ERROR_NONE if this function is supported and the tpl_surface is valid, TPL_ERROR otherwise.
+ *
+ * @see tpl_surface_enqueue_buffer()
+ * @see tpl_surface_enqueue_buffer_with_damage()
+ * @see tpl_surface_dequeue_buffer()
+ * @see tpl_surface_create_swapchain()
+ * @see tpl_surface_destroy_swapchain()
+ */
+tpl_result_t
+tpl_surface_get_swapchain_buffers(tpl_surface_t *surface,
+                                 tbm_surface_h **buffers, int *buffer_count);
+
+/**
+ * Get the buffer count capability of the given TPL surface.
+ *
+ * @paran surface surface to get the buffer count capability
+ * @paran min pointer to receive min buffer count value.
+ * @paran max pointer to receive max buffer count value.
+ */
+tpl_result_t
+tpl_surface_query_supported_buffer_count(tpl_surface_t *surface, int *min,
+               int *max);
+
+/**
  * Query information on the given native window.
  *
  * @param display display used for query.
@@ -561,6 +638,6 @@ tpl_display_get_native_pixmap_info(tpl_display_t *display, tpl_handle_t pixmap,
  */
 tbm_surface_h
 tpl_display_get_buffer_from_native_pixmap(tpl_display_t *display,
-                                         tpl_handle_t pixmap);
+               tpl_handle_t pixmap);
 
 #endif /* TPL_H */
index 4d2f484..13cb2cb 100644 (file)
@@ -275,6 +275,11 @@ __tpl_gbm_surface_init(tpl_surface_t *surface)
                        goto error;
                }
 
+               surface->capabilities.min_buffer =
+                       tbm_surface_queue_get_size(tpl_gbm_surface->tbm_queue);
+               surface->capabilities.max_buffer =
+                       tbm_surface_queue_get_size(tpl_gbm_surface->tbm_queue);
+
                TPL_LOG(3, "window(%p, %p) %dx%d", surface, surface->native_handle,
                        surface->width, surface->height);
                return TPL_ERROR_NONE;
@@ -285,6 +290,7 @@ __tpl_gbm_surface_init(tpl_surface_t *surface)
                        TPL_ERR("Failed to get native pixmap info.");
                        goto error;
                }
+               surface->capabilities.min_buffer = surface->capabilities.max_buffer = 1;
 
                return TPL_ERROR_NONE;
        }
index 5199461..0e1c601 100644 (file)
@@ -60,6 +60,13 @@ struct _tpl_surface_backend {
        tpl_result_t (*enqueue_buffer)(tpl_surface_t *surface,
                                       tbm_surface_h tbm_surface,
                                       int num_rects, const int *rects);
+       tpl_result_t (*get_swapchain_buffers)(tpl_surface_t *surface,
+                                             tbm_surface_h **buffers,
+                                             int *buffer_count);
+       tpl_result_t (*create_swapchain)(tpl_surface_t *surface,
+                                        tbm_format format, int width,
+                                        int height, int buffer_count);
+       tpl_result_t (*destroy_swapchain)(tpl_surface_t *surface);
 };
 
 struct _tpl_object {
@@ -90,6 +97,10 @@ struct _tpl_surface {
        int width, height;
        int post_interval;
        int dump_count;
+       struct {
+               int min_buffer;
+               int max_buffer;
+       } capabilities;
        tpl_surface_backend_t backend;
 };
 
@@ -147,7 +158,8 @@ void __tpl_runtime_remove_display(tpl_display_t *display);
 tpl_backend_type_t __tpl_display_choose_backend(tpl_handle_t native_dpy);
 tpl_bool_t __tpl_display_choose_backend_gbm(tpl_handle_t native_dpy);
 tpl_bool_t __tpl_display_choose_backend_tbm(tpl_handle_t native_dpy);
-tpl_bool_t __tpl_display_choose_backend_wayland(tpl_handle_t native_dpy);
+tpl_bool_t __tpl_display_choose_backend_wayland_egl(tpl_handle_t native_dpy);
+tpl_bool_t __tpl_display_choose_backend_wayland_vk_wsi(tpl_handle_t native_dpy);
 tpl_bool_t __tpl_display_choose_backend_x11_dri2(tpl_handle_t native_dpy);
 tpl_bool_t __tpl_display_choose_backend_x11_dri3(tpl_handle_t native_dpy);
 void __tpl_display_init_backend(tpl_display_t *display,
@@ -156,12 +168,14 @@ void __tpl_surface_init_backend(tpl_surface_t *surface,
                                tpl_backend_type_t type);
 void __tpl_display_init_backend_gbm(tpl_display_backend_t *backend);
 void __tpl_display_init_backend_tbm(tpl_display_backend_t *backend);
-void __tpl_display_init_backend_wayland(tpl_display_backend_t *backend);
+void __tpl_display_init_backend_wayland_egl(tpl_display_backend_t *backend);
+void __tpl_display_init_backend_wayland_vk_wsi(tpl_display_backend_t *backend);
 void __tpl_display_init_backend_x11_dri2(tpl_display_backend_t *backend);
 void __tpl_display_init_backend_x11_dri3(tpl_display_backend_t *backend);
 void __tpl_surface_init_backend_gbm(tpl_surface_backend_t *backend);
 void __tpl_surface_init_backend_tbm(tpl_surface_backend_t *backend);
-void __tpl_surface_init_backend_wayland(tpl_surface_backend_t *backend);
+void __tpl_surface_init_backend_wayland_egl(tpl_surface_backend_t *backend);
+void __tpl_surface_init_backend_wayland_vk_wsi(tpl_surface_backend_t *backend);
 void __tpl_surface_init_backend_x11_dri2(tpl_surface_backend_t *backend);
 void __tpl_surface_init_backend_x11_dri3(tpl_surface_backend_t *backend);
 
index a17b592..336805b 100644 (file)
@@ -262,3 +262,110 @@ tpl_surface_enqueue_buffer_with_damage(tpl_surface_t *surface,
 
        return ret;
 }
+
+tpl_result_t
+tpl_surface_query_supported_buffer_count(tpl_surface_t *surface, int *min,
+               int *max)
+{
+       if (!surface || (surface->type != TPL_SURFACE_TYPE_WINDOW)) {
+               TPL_ERR("Invalid surface!");
+               return TPL_ERROR_INVALID_PARAMETER;
+       }
+
+       if (min) *min = surface->capabilities.min_buffer;
+       if (max) *max = surface->capabilities.max_buffer;
+
+       return TPL_ERROR_NONE;
+
+}
+
+tpl_result_t
+tpl_surface_get_swapchain_buffers(tpl_surface_t *surface,
+                                 tbm_surface_h **buffers, int *buffer_count)
+{
+       tpl_result_t ret = TPL_ERROR_INVALID_OPERATION;
+
+       if (!surface || (surface->type != TPL_SURFACE_TYPE_WINDOW)) {
+               TPL_ERR("Invalid surface!");
+               return TPL_ERROR_INVALID_PARAMETER;
+       }
+
+       if (!buffer_count) {
+               TPL_ERR("Invalid buffer_count!");
+               return TPL_ERROR_INVALID_PARAMETER;
+       }
+
+       if (!surface->backend.get_swapchain_buffers) {
+               TPL_ERR("Backend does not support!");
+               return TPL_ERROR_INVALID_OPERATION;
+       }
+
+       TPL_OBJECT_LOCK(surface);
+
+       ret = surface->backend.get_swapchain_buffers(surface, buffers, buffer_count);
+
+       TPL_OBJECT_UNLOCK(surface);
+
+       return ret;
+}
+
+tpl_result_t
+tpl_surface_create_swapchain(tpl_surface_t *surface, tbm_format format,
+                            int width, int height, int buffer_count)
+{
+       tpl_result_t ret = TPL_ERROR_INVALID_OPERATION;
+
+       if (!surface) {
+               TPL_ERR("Invalid surface!");
+               return TPL_ERROR_INVALID_PARAMETER;
+       }
+
+       if ((width <= 0) || (height <= 0) ) {
+               TPL_ERR("Invalid width or  height!");
+               return TPL_ERROR_INVALID_PARAMETER;
+       }
+
+       if ((buffer_count < surface->capabilities.min_buffer)
+           || (buffer_count > surface->capabilities.max_buffer)) {
+               TPL_ERR("Invalid buffer_count!");
+               return TPL_ERROR_INVALID_PARAMETER;
+       }
+
+       if (!surface->backend.create_swapchain) {
+               TPL_ERR("Backend does not support!");
+               return TPL_ERROR_INVALID_OPERATION;
+       }
+
+       TPL_OBJECT_LOCK(surface);
+
+       ret = surface->backend.create_swapchain(surface, format, width, height,
+                                               buffer_count);
+
+       TPL_OBJECT_UNLOCK(surface);
+
+       return ret;
+}
+
+tpl_result_t
+tpl_surface_destroy_swapchain(tpl_surface_t *surface)
+{
+       tpl_result_t ret = TPL_ERROR_INVALID_OPERATION;
+
+       if (!surface) {
+               TPL_ERR("Invalid surface!");
+               return TPL_ERROR_INVALID_PARAMETER;
+       }
+
+       if (!surface->backend.destroy_swapchain) {
+               TPL_ERR("Backend does not support!");
+               return TPL_ERROR_INVALID_OPERATION;
+       }
+
+       TPL_OBJECT_LOCK(surface);
+
+       ret = surface->backend.destroy_swapchain(surface);
+
+       TPL_OBJECT_UNLOCK(surface);
+
+       return ret;
+}
index 9675559..552dead 100644 (file)
@@ -183,6 +183,11 @@ __tpl_tbm_surface_init(tpl_surface_t *surface)
                        goto error;
                }
 
+               surface->capabilities.min_buffer =
+                       tbm_surface_queue_get_size((tbm_surface_queue_h)surface->native_handle);
+               surface->capabilities.max_buffer =
+                       tbm_surface_queue_get_size((tbm_surface_queue_h)surface->native_handle);
+
                tbm_surface_queue_add_destroy_cb((tbm_surface_queue_h)surface->native_handle,
                                                 __tpl_tbm_surface_queue_notify_cb,
                                                 surface);
@@ -200,6 +205,7 @@ __tpl_tbm_surface_init(tpl_surface_t *surface)
 
                        goto error;
                }
+               surface->capabilities.min_buffer = surface->capabilities.max_buffer = 1;
 
                tbm_surface_internal_ref((tbm_surface_h)surface->native_handle);
 
similarity index 54%
rename from src/tpl_wayland.c
rename to src/tpl_wayland_egl.c
index c48fa03..6a489c4 100644 (file)
 /* In wayland, application and compositor create its own drawing buffers. Recommend size is more than 2. */
 #define CLIENT_QUEUE_SIZE 3
 
-typedef struct _tpl_wayland_display tpl_wayland_display_t;
-typedef struct _tpl_wayland_surface tpl_wayland_surface_t;
-typedef struct _tpl_wayland_buffer tpl_wayland_buffer_t;
+typedef struct _tpl_wayland_egl_display tpl_wayland_egl_display_t;
+typedef struct _tpl_wayland_egl_surface tpl_wayland_egl_surface_t;
+typedef struct _tpl_wayland_egl_buffer tpl_wayland_egl_buffer_t;
 
-struct _tpl_wayland_display {
+struct _tpl_wayland_egl_display {
        tbm_bufmgr bufmgr;
        struct wayland_tbm_client *wl_tbm_client;
        struct wl_event_queue *wl_queue;
        struct wl_registry *wl_registry;
 };
 
-struct _tpl_wayland_surface {
+struct _tpl_wayland_egl_surface {
        tbm_surface_queue_h tbm_queue;
        tbm_surface_h current_buffer;
        tpl_bool_t resized;
 };
 
-struct _tpl_wayland_buffer {
+struct _tpl_wayland_egl_buffer {
        tpl_display_t *display;
        tbm_bo bo;
-       tpl_wayland_surface_t *wayland_surface;
+       tpl_wayland_egl_surface_t *wayland_egl_surface;
        struct wl_proxy *wl_proxy;
 };
 
@@ -56,39 +56,40 @@ static const struct wl_buffer_listener buffer_release_listener;
 
 #define TPL_BUFFER_CACHE_MAX_ENTRIES 40
 
-static int tpl_wayland_buffer_key;
-#define KEY_TPL_WAYLAND_BUFFER  (unsigned long)(&tpl_wayland_buffer_key)
+static int tpl_wayland_egl_buffer_key;
+#define KEY_tpl_wayland_egl_buffer  (unsigned long)(&tpl_wayland_egl_buffer_key)
 
-static void __tpl_wayland_buffer_free(tpl_wayland_buffer_t *wayland_buffer);
+static void __tpl_wayland_egl_buffer_free(tpl_wayland_egl_buffer_t
+               *wayland_egl_buffer);
 
-static TPL_INLINE tpl_wayland_buffer_t *
-__tpl_wayland_get_wayland_buffer_from_tbm_surface(tbm_surface_h surface)
+static TPL_INLINE tpl_wayland_egl_buffer_t *
+__tpl_wayland_egl_get_wayland_buffer_from_tbm_surface(tbm_surface_h surface)
 {
        tbm_bo bo;
-       tpl_wayland_buffer_t *buf = NULL;
+       tpl_wayland_egl_buffer_t *buf = NULL;
 
        bo = tbm_surface_internal_get_bo(surface, 0);
-       tbm_bo_get_user_data(bo, KEY_TPL_WAYLAND_BUFFER, (void **)&buf);
+       tbm_bo_get_user_data(bo, KEY_tpl_wayland_egl_buffer, (void **)&buf);
 
        return buf;
 }
 
 static TPL_INLINE void
-__tpl_wayland_set_wayland_buffer_to_tbm_surface(tbm_surface_h surface,
-               tpl_wayland_buffer_t *buf)
+__tpl_wayland_egl_set_wayland_buffer_to_tbm_surface(tbm_surface_h surface,
+               tpl_wayland_egl_buffer_t *buf)
 {
        tbm_bo bo;
 
        bo = tbm_surface_internal_get_bo(surface, 0);
 
-       tbm_bo_add_user_data(bo, KEY_TPL_WAYLAND_BUFFER,
-                            (tbm_data_free)__tpl_wayland_buffer_free);
+       tbm_bo_add_user_data(bo, KEY_tpl_wayland_egl_buffer,
+                            (tbm_data_free)__tpl_wayland_egl_buffer_free);
 
-       tbm_bo_set_user_data(bo, KEY_TPL_WAYLAND_BUFFER, buf);
+       tbm_bo_set_user_data(bo, KEY_tpl_wayland_egl_buffer, buf);
 }
 
 static TPL_INLINE tpl_bool_t
-__tpl_wayland_display_is_wl_display(tpl_handle_t native_dpy)
+__tpl_wayland_egl_display_is_wl_display(tpl_handle_t native_dpy)
 {
        TPL_ASSERT(native_dpy);
 
@@ -109,10 +110,10 @@ __tpl_wayland_display_is_wl_display(tpl_handle_t native_dpy)
 }
 
 static int
-__tpl_wayland_display_roundtrip(tpl_display_t *display)
+__tpl_wayland_egl_display_roundtrip(tpl_display_t *display)
 {
        struct wl_display *wl_dpy;
-       tpl_wayland_display_t *wayland_display;
+       tpl_wayland_egl_display_t *wayland_egl_display;
        struct wl_callback *callback;
        int done = 0, ret = 0;
 
@@ -121,24 +122,24 @@ __tpl_wayland_display_roundtrip(tpl_display_t *display)
        TPL_ASSERT(display->backend.data);
 
        wl_dpy = (struct wl_display *) display->native_handle;
-       wayland_display = (tpl_wayland_display_t *) display->backend.data;
+       wayland_egl_display = (tpl_wayland_egl_display_t *) display->backend.data;
 
        callback = wl_display_sync(wl_dpy);
        wl_callback_add_listener(callback, &sync_listener, &done);
 
-       wl_proxy_set_queue((struct wl_proxy *) callback, wayland_display->wl_queue);
+       wl_proxy_set_queue((struct wl_proxy *) callback, wayland_egl_display->wl_queue);
 
        while (ret != -1 && !done) {
-               ret = wl_display_dispatch_queue(wl_dpy, wayland_display->wl_queue);
+               ret = wl_display_dispatch_queue(wl_dpy, wayland_egl_display->wl_queue);
        }
 
        return ret;
 }
 
 static tpl_result_t
-__tpl_wayland_display_init(tpl_display_t *display)
+__tpl_wayland_egl_display_init(tpl_display_t *display)
 {
-       tpl_wayland_display_t *wayland_display = NULL;
+       tpl_wayland_egl_display_t *wayland_egl_display = NULL;
 
        TPL_ASSERT(display);
 
@@ -148,41 +149,41 @@ __tpl_wayland_display_init(tpl_display_t *display)
                return TPL_ERROR_INVALID_PARAMETER;
        }
 
-       wayland_display = (tpl_wayland_display_t *) calloc(1,
-                         sizeof(tpl_wayland_display_t));
-       if (!wayland_display) {
-               TPL_ERR("Failed to allocate memory for new tpl_wayland_display_t.");
+       wayland_egl_display = (tpl_wayland_egl_display_t *) calloc(1,
+                             sizeof(tpl_wayland_egl_display_t));
+       if (!wayland_egl_display) {
+               TPL_ERR("Failed to allocate memory for new tpl_wayland_egl_display_t.");
                return TPL_ERROR_INVALID_OPERATION;
        }
 
-       display->backend.data = wayland_display;
+       display->backend.data = wayland_egl_display;
        display->bufmgr_fd = -1;
 
-       if (__tpl_wayland_display_is_wl_display(display->native_handle)) {
+       if (__tpl_wayland_egl_display_is_wl_display(display->native_handle)) {
                struct wl_display *wl_dpy =
                        (struct wl_display *)display->native_handle;
-               wayland_display->wl_tbm_client =
+               wayland_egl_display->wl_tbm_client =
                        wayland_tbm_client_init((struct wl_display *) wl_dpy);
 
-               if (!wayland_display->wl_tbm_client) {
+               if (!wayland_egl_display->wl_tbm_client) {
                        TPL_ERR("Wayland TBM initialization failed!");
                        goto free_wl_display;
                }
 
-               wayland_display->wl_queue = wl_display_create_queue(wl_dpy);
-               if (!wayland_display->wl_queue) {
+               wayland_egl_display->wl_queue = wl_display_create_queue(wl_dpy);
+               if (!wayland_egl_display->wl_queue) {
                        TPL_ERR("Failed to create wl_queue with wl_dpy(%p).", wl_dpy);
                        goto free_wl_display;
                }
 
-               wayland_display->wl_registry = wl_display_get_registry(wl_dpy);
-               if (!wayland_display->wl_registry) {
+               wayland_egl_display->wl_registry = wl_display_get_registry(wl_dpy);
+               if (!wayland_egl_display->wl_registry) {
                        TPL_ERR("Failed to get wl_registry with wl_dpy(%p).", wl_dpy);
                        goto destroy_queue;
                }
 
-               wl_proxy_set_queue((struct wl_proxy *)wayland_display->wl_registry,
-                                  wayland_display->wl_queue);
+               wl_proxy_set_queue((struct wl_proxy *)wayland_egl_display->wl_registry,
+                                  wayland_egl_display->wl_queue);
        } else {
                goto free_wl_display;
        }
@@ -190,38 +191,38 @@ __tpl_wayland_display_init(tpl_display_t *display)
        return TPL_ERROR_NONE;
 
 destroy_queue:
-       wl_event_queue_destroy(wayland_display->wl_queue);
+       wl_event_queue_destroy(wayland_egl_display->wl_queue);
 
 free_wl_display:
-       if (wayland_display) {
-               free(wayland_display);
+       if (wayland_egl_display) {
+               free(wayland_egl_display);
                display->backend.data = NULL;
        }
        return TPL_ERROR_INVALID_OPERATION;
 }
 
 static void
-__tpl_wayland_display_fini(tpl_display_t *display)
+__tpl_wayland_egl_display_fini(tpl_display_t *display)
 {
-       tpl_wayland_display_t *wayland_display;
+       tpl_wayland_egl_display_t *wayland_egl_display;
 
        TPL_ASSERT(display);
 
-       wayland_display = (tpl_wayland_display_t *)display->backend.data;
-       if (wayland_display) {
-               wayland_tbm_client_deinit(wayland_display->wl_tbm_client);
-               free(wayland_display);
+       wayland_egl_display = (tpl_wayland_egl_display_t *)display->backend.data;
+       if (wayland_egl_display) {
+               wayland_tbm_client_deinit(wayland_egl_display->wl_tbm_client);
+               free(wayland_egl_display);
        }
        display->backend.data = NULL;
 }
 
 static tpl_result_t
-__tpl_wayland_display_query_config(tpl_display_t *display,
-                                  tpl_surface_type_t surface_type,
-                                  int red_size, int green_size,
-                                  int blue_size, int alpha_size,
-                                  int color_depth, int *native_visual_id,
-                                  tpl_bool_t *is_slow)
+__tpl_wayland_egl_display_query_config(tpl_display_t *display,
+                                      tpl_surface_type_t surface_type,
+                                      int red_size, int green_size,
+                                      int blue_size, int alpha_size,
+                                      int color_depth, int *native_visual_id,
+                                      tpl_bool_t *is_slow)
 {
        TPL_ASSERT(display);
 
@@ -245,8 +246,8 @@ __tpl_wayland_display_query_config(tpl_display_t *display,
 }
 
 static tpl_result_t
-__tpl_wayland_display_filter_config(tpl_display_t *display, int *visual_id,
-                                   int alpha_size)
+__tpl_wayland_egl_display_filter_config(tpl_display_t *display, int *visual_id,
+                                       int alpha_size)
 {
        TPL_IGNORE(display);
        TPL_IGNORE(visual_id);
@@ -255,10 +256,10 @@ __tpl_wayland_display_filter_config(tpl_display_t *display, int *visual_id,
 }
 
 static tpl_result_t
-__tpl_wayland_display_get_window_info(tpl_display_t *display,
-                                     tpl_handle_t window, int *width,
-                                     int *height, tbm_format *format,
-                                     int depth, int a_size)
+__tpl_wayland_egl_display_get_window_info(tpl_display_t *display,
+               tpl_handle_t window, int *width,
+               int *height, tbm_format *format,
+               int depth, int a_size)
 {
        TPL_ASSERT(display);
        TPL_ASSERT(window);
@@ -283,9 +284,9 @@ __tpl_wayland_display_get_window_info(tpl_display_t *display,
 }
 
 static tpl_result_t
-__tpl_wayland_display_get_pixmap_info(tpl_display_t *display,
-                                     tpl_handle_t pixmap, int *width,
-                                     int *height, tbm_format *format)
+__tpl_wayland_egl_display_get_pixmap_info(tpl_display_t *display,
+               tpl_handle_t pixmap, int *width,
+               int *height, tbm_format *format)
 {
        tbm_surface_h   tbm_surface = NULL;
 
@@ -304,7 +305,7 @@ __tpl_wayland_display_get_pixmap_info(tpl_display_t *display,
 }
 
 static tbm_surface_h
-__tpl_wayland_display_get_buffer_from_native_pixmap(tpl_handle_t pixmap)
+__tpl_wayland_egl_display_get_buffer_from_native_pixmap(tpl_handle_t pixmap)
 {
        tbm_surface_h tbm_surface = NULL;
 
@@ -325,11 +326,11 @@ __cb_client_window_resize_callback(struct wl_egl_window *wl_egl_window,
                                   void *private);
 
 static tpl_result_t
-__tpl_wayland_surface_init(tpl_surface_t *surface)
+__tpl_wayland_egl_surface_init(tpl_surface_t *surface)
 {
-       tpl_wayland_display_t *wayland_display =
-               (tpl_wayland_display_t *) surface->display->backend.data;
-       tpl_wayland_surface_t *wayland_surface = NULL;
+       tpl_wayland_egl_display_t *wayland_egl_display =
+               (tpl_wayland_egl_display_t *) surface->display->backend.data;
+       tpl_wayland_egl_surface_t *wayland_egl_surface = NULL;
 
        struct wl_egl_window *wl_egl_window = (struct wl_egl_window *)
                                              surface->native_handle;
@@ -338,41 +339,46 @@ __tpl_wayland_surface_init(tpl_surface_t *surface)
        TPL_ASSERT(surface->type == TPL_SURFACE_TYPE_WINDOW);
        TPL_ASSERT(surface->native_handle);
 
-       wayland_surface = (tpl_wayland_surface_t *) calloc(1,
-                         sizeof(tpl_wayland_surface_t));
-       if (!wayland_surface) {
-               TPL_ERR("Failed to allocate memory for new tpl_wayland_surface_t.");
+       wayland_egl_surface = (tpl_wayland_egl_surface_t *) calloc(1,
+                             sizeof(tpl_wayland_egl_surface_t));
+       if (!wayland_egl_surface) {
+               TPL_ERR("Failed to allocate memory for new tpl_wayland_egl_surface_t.");
                return TPL_ERROR_INVALID_OPERATION;
        }
 
-       surface->backend.data = (void *)wayland_surface;
-       wayland_surface->tbm_queue = NULL;
-       wayland_surface->resized = TPL_FALSE;
-       wayland_surface->current_buffer = NULL;
+       surface->backend.data = (void *)wayland_egl_surface;
+       wayland_egl_surface->tbm_queue = NULL;
+       wayland_egl_surface->resized = TPL_FALSE;
+       wayland_egl_surface->current_buffer = NULL;
 
        if (wl_egl_window->surface)
-               wayland_surface->tbm_queue = wayland_tbm_client_create_surface_queue(wayland_display->wl_tbm_client,
-                                               wl_egl_window->surface,
-                                               3,
-                                               wl_egl_window->width,
-                                               wl_egl_window->height,
-                                               TBM_FORMAT_ARGB8888);
+               wayland_egl_surface->tbm_queue = wayland_tbm_client_create_surface_queue(
+                               wayland_egl_display->wl_tbm_client,
+                               wl_egl_window->surface,
+                               3,
+                               wl_egl_window->width,
+                               wl_egl_window->height,
+                               TBM_FORMAT_ARGB8888);
        else
                /*Why wl_surafce is NULL ?*/
-               wayland_surface->tbm_queue = tbm_surface_queue_sequence_create(3,
-                                               wl_egl_window->width,
-                                               wl_egl_window->height,
-                                               TBM_FORMAT_ARGB8888,
-                                               0);
+               wayland_egl_surface->tbm_queue = tbm_surface_queue_sequence_create(3,
+                                                wl_egl_window->width,
+                                                wl_egl_window->height,
+                                                TBM_FORMAT_ARGB8888,
+                                                0);
 
-       if (!wayland_surface->tbm_queue) {
+       if (!wayland_egl_surface->tbm_queue) {
                TPL_ERR("TBM surface queue creation failed!");
-               free(wayland_surface);
+               free(wayland_egl_surface);
                return TPL_ERROR_INVALID_OPERATION;
        }
 
        surface->width = wl_egl_window->width;
        surface->height = wl_egl_window->height;
+       surface->capabilities.min_buffer =
+               tbm_surface_queue_get_size(wayland_egl_surface->tbm_queue);
+       surface->capabilities.max_buffer =
+               tbm_surface_queue_get_size(wayland_egl_surface->tbm_queue);
 
        wl_egl_window->private = surface;
        wl_egl_window->resize_callback = (void *)__cb_client_window_resize_callback;
@@ -384,19 +390,20 @@ __tpl_wayland_surface_init(tpl_surface_t *surface)
 }
 
 static void
-__tpl_wayland_surface_fini(tpl_surface_t *surface)
+__tpl_wayland_egl_surface_fini(tpl_surface_t *surface)
 {
-       tpl_wayland_surface_t *wayland_surface = NULL;
-       tpl_wayland_display_t *wayland_display = NULL;
+       tpl_wayland_egl_surface_t *wayland_egl_surface = NULL;
+       tpl_wayland_egl_display_t *wayland_egl_display = NULL;
 
        TPL_ASSERT(surface);
        TPL_ASSERT(surface->display);
 
-       wayland_surface = (tpl_wayland_surface_t *) surface->backend.data;
-       if (wayland_surface == NULL) return;
+       wayland_egl_surface = (tpl_wayland_egl_surface_t *) surface->backend.data;
+       if (wayland_egl_surface == NULL) return;
 
-       wayland_display = (tpl_wayland_display_t *) surface->display->backend.data;
-       if (wayland_display == NULL) return;
+       wayland_egl_display = (tpl_wayland_egl_display_t *)
+                             surface->display->backend.data;
+       if (wayland_egl_display == NULL) return;
 
        TPL_LOG(3, "window(%p, %p)", surface, surface->native_handle);
 
@@ -420,23 +427,23 @@ __tpl_wayland_surface_fini(tpl_surface_t *surface)
                }
 
                wl_display_flush(surface->display->native_handle);
-               __tpl_wayland_display_roundtrip(surface->display);
+               __tpl_wayland_egl_display_roundtrip(surface->display);
 
-               if (wayland_surface->current_buffer)
-                       tbm_surface_internal_unref(wayland_surface->current_buffer);
+               if (wayland_egl_surface->current_buffer)
+                       tbm_surface_internal_unref(wayland_egl_surface->current_buffer);
 
-               tbm_surface_queue_destroy(wayland_surface->tbm_queue);
-               wayland_surface->tbm_queue = NULL;
+               tbm_surface_queue_destroy(wayland_egl_surface->tbm_queue);
+               wayland_egl_surface->tbm_queue = NULL;
        }
 
-       free(wayland_surface);
+       free(wayland_egl_surface);
        surface->backend.data = NULL;
 }
 
 static tpl_result_t
-__tpl_wayland_surface_enqueue_buffer(tpl_surface_t *surface,
-                                    tbm_surface_h tbm_surface,
-                                    int num_rects, const int *rects)
+__tpl_wayland_egl_surface_enqueue_buffer(tpl_surface_t *surface,
+               tbm_surface_h tbm_surface,
+               int num_rects, const int *rects)
 {
        TPL_ASSERT(surface);
        TPL_ASSERT(surface->display);
@@ -444,21 +451,21 @@ __tpl_wayland_surface_enqueue_buffer(tpl_surface_t *surface,
        TPL_ASSERT(tbm_surface);
 
        struct wl_egl_window *wl_egl_window = NULL;
-       tpl_wayland_display_t *wayland_display =
-               (tpl_wayland_display_t *) surface->display->backend.data;
-       tpl_wayland_surface_t *wayland_surface =
-               (tpl_wayland_surface_t *) surface->backend.data;
-       tpl_wayland_buffer_t *wayland_buffer = NULL;
+       tpl_wayland_egl_display_t *wayland_egl_display =
+               (tpl_wayland_egl_display_t *) surface->display->backend.data;
+       tpl_wayland_egl_surface_t *wayland_egl_surface =
+               (tpl_wayland_egl_surface_t *) surface->backend.data;
+       tpl_wayland_egl_buffer_t *wayland_egl_buffer = NULL;
        tbm_surface_queue_error_e tsq_err;
 
        TPL_LOG(3, "window(%p, %p)", surface, surface->native_handle);
 
-       wayland_buffer =
-               __tpl_wayland_get_wayland_buffer_from_tbm_surface(tbm_surface);
-       TPL_ASSERT(wayland_buffer);
+       wayland_egl_buffer =
+               __tpl_wayland_egl_get_wayland_buffer_from_tbm_surface(tbm_surface);
+       TPL_ASSERT(wayland_egl_buffer);
 
        tbm_bo_handle bo_handle =
-               tbm_bo_get_handle(wayland_buffer->bo , TBM_DEVICE_CPU);
+               tbm_bo_get_handle(wayland_egl_buffer->bo , TBM_DEVICE_CPU);
 
        if (bo_handle.ptr)
                TPL_IMAGE_DUMP(bo_handle.ptr, surface->width, surface->height,
@@ -468,21 +475,23 @@ __tpl_wayland_surface_enqueue_buffer(tpl_surface_t *surface,
 
        tbm_surface_internal_unref(tbm_surface);
 
-       tsq_err = tbm_surface_queue_enqueue(wayland_surface->tbm_queue, tbm_surface);
+       tsq_err = tbm_surface_queue_enqueue(wayland_egl_surface->tbm_queue,
+                                           tbm_surface);
        if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) {
                TPL_ERR("Failed to enqeueue tbm_surface. | tsq_err = %d", tsq_err);
                return TPL_ERROR_INVALID_OPERATION;
        }
 
        /* deprecated */
-       tsq_err = tbm_surface_queue_acquire(wayland_surface->tbm_queue, &tbm_surface);
+       tsq_err = tbm_surface_queue_acquire(wayland_egl_surface->tbm_queue,
+                                           &tbm_surface);
        if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) {
                TPL_ERR("Failed to acquire tbm_surface. | tsq_err = %d", tsq_err);
                return TPL_ERROR_INVALID_OPERATION;
        }
 
        tbm_surface_internal_ref(tbm_surface);
-       wl_surface_attach(wl_egl_window->surface, (void *)wayland_buffer->wl_proxy,
+       wl_surface_attach(wl_egl_window->surface, (void *)wayland_egl_buffer->wl_proxy,
                          wl_egl_window->dx, wl_egl_window->dy);
 
        wl_egl_window->attached_width = wl_egl_window->width;
@@ -508,7 +517,7 @@ __tpl_wayland_surface_enqueue_buffer(tpl_surface_t *surface,
                frame_callback = wl_surface_frame(wl_egl_window->surface);
                wl_callback_add_listener(frame_callback, &frame_listener, tbm_surface);
                wl_proxy_set_queue((struct wl_proxy *)frame_callback,
-                                  wayland_display->wl_queue);
+                                  wayland_egl_display->wl_queue);
        }
        wl_surface_commit(wl_egl_window->surface);
 
@@ -518,70 +527,71 @@ __tpl_wayland_surface_enqueue_buffer(tpl_surface_t *surface,
 }
 
 static tpl_bool_t
-__tpl_wayland_surface_validate(tpl_surface_t *surface)
+__tpl_wayland_egl_surface_validate(tpl_surface_t *surface)
 {
        TPL_ASSERT(surface);
        TPL_ASSERT(surface->backend.data);
 
-       tpl_wayland_surface_t *wayland_surface =
-               (tpl_wayland_surface_t *)surface->backend.data;
+       tpl_wayland_egl_surface_t *wayland_egl_surface =
+               (tpl_wayland_egl_surface_t *)surface->backend.data;
 
-       if (wayland_surface->resized) return TPL_FALSE;
+       if (wayland_egl_surface->resized) return TPL_FALSE;
 
        return TPL_TRUE;
 }
 
 static tbm_surface_h
-__tpl_wayland_surface_dequeue_buffer(tpl_surface_t *surface)
+__tpl_wayland_egl_surface_dequeue_buffer(tpl_surface_t *surface)
 {
        TPL_ASSERT(surface);
        TPL_ASSERT(surface->backend.data);
        TPL_ASSERT(surface->display);
 
        tbm_surface_h tbm_surface = NULL;
-       tpl_wayland_buffer_t *wayland_buffer = NULL;
-       tpl_wayland_surface_t *wayland_surface =
-               (tpl_wayland_surface_t *)surface->backend.data;
-       tpl_wayland_display_t *wayland_display =
-               (tpl_wayland_display_t *)surface->display->backend.data;
+       tpl_wayland_egl_buffer_t *wayland_egl_buffer = NULL;
+       tpl_wayland_egl_surface_t *wayland_egl_surface =
+               (tpl_wayland_egl_surface_t *)surface->backend.data;
+       tpl_wayland_egl_display_t *wayland_egl_display =
+               (tpl_wayland_egl_display_t *)surface->display->backend.data;
        struct wl_proxy *wl_proxy = NULL;
        tbm_surface_queue_error_e tsq_err = 0;
 
        /* Check whether the surface was resized by wayland_egl */
-       if (wayland_surface->resized == TPL_TRUE) {
+       if (wayland_egl_surface->resized == TPL_TRUE) {
                struct wl_egl_window *wl_egl_window = (struct wl_egl_window *)
                                                      surface->native_handle;
                int width, height, format;
                width = wl_egl_window->width;
                height = wl_egl_window->height;
-               format = tbm_surface_queue_get_format(wayland_surface->tbm_queue);
+               format = tbm_surface_queue_get_format(wayland_egl_surface->tbm_queue);
 
                /* TODO: In dequeue_buffer case, does it explictly need on unref of current_buffer? */
-               if (wayland_surface->current_buffer)
-                       tbm_surface_internal_unref(wayland_surface->current_buffer);
+               if (wayland_egl_surface->current_buffer)
+                       tbm_surface_internal_unref(wayland_egl_surface->current_buffer);
 
-               tbm_surface_queue_reset(wayland_surface->tbm_queue, width, height, format);
-               wayland_surface->resized = TPL_FALSE;
+               tbm_surface_queue_reset(wayland_egl_surface->tbm_queue, width, height, format);
+               wayland_egl_surface->resized = TPL_FALSE;
                surface->width = width;
                surface->height = height;
        }
 
        TPL_OBJECT_UNLOCK(surface);
-       wl_display_dispatch_queue_pending((struct wl_display *)surface->display->native_handle,
-                                         wayland_display->wl_queue);
-
+       wl_display_dispatch_queue_pending((struct wl_display *)
+                                         surface->display->native_handle,
+                                         wayland_egl_display->wl_queue);
        while (tbm_surface_queue_can_dequeue(
-                      wayland_surface->tbm_queue, 0) == 0) {
+                      wayland_egl_surface->tbm_queue, 0) == 0) {
                /* Application sent all buffers to the server. Wait for server response. */
                if (wl_display_dispatch_queue(surface->display->native_handle,
-                                             wayland_display->wl_queue) == -1) {
+                                             wayland_egl_display->wl_queue) == -1) {
                        TPL_OBJECT_LOCK(surface);
                        return NULL;
                }
        }
        TPL_OBJECT_LOCK(surface);
 
-       tsq_err = tbm_surface_queue_dequeue(wayland_surface->tbm_queue, &tbm_surface);
+       tsq_err = tbm_surface_queue_dequeue(wayland_egl_surface->tbm_queue,
+                                           &tbm_surface);
        if (!tbm_surface) {
                TPL_ERR("Failed to get tbm_surface from tbm_surface_queue | tsq_err = %d",
                        tsq_err);
@@ -590,105 +600,107 @@ __tpl_wayland_surface_dequeue_buffer(tpl_surface_t *surface)
 
        tbm_surface_internal_ref(tbm_surface);
 
-       if ((wayland_buffer =
-                    __tpl_wayland_get_wayland_buffer_from_tbm_surface(tbm_surface)) != NULL) {
+       if ((wayland_egl_buffer =
+                    __tpl_wayland_egl_get_wayland_buffer_from_tbm_surface(tbm_surface)) != NULL) {
                return tbm_surface;
        }
 
-       wayland_buffer = (tpl_wayland_buffer_t *) calloc(1,
-                        sizeof(tpl_wayland_buffer_t));
-       if (!wayland_buffer) {
-               TPL_ERR("Mem alloc for wayland_buffer failed!");
+       wayland_egl_buffer = (tpl_wayland_egl_buffer_t *) calloc(1,
+                            sizeof(tpl_wayland_egl_buffer_t));
+       if (!wayland_egl_buffer) {
+               TPL_ERR("Mem alloc for wayland_egl_buffer failed!");
                tbm_surface_internal_unref(tbm_surface);
                return NULL;
        }
 
        wl_proxy = (struct wl_proxy *)wayland_tbm_client_create_buffer(
-                          wayland_display->wl_tbm_client, tbm_surface);
+                          wayland_egl_display->wl_tbm_client, tbm_surface);
        if (!wl_proxy) {
                TPL_ERR("Failed to create TBM client buffer!");
                tbm_surface_internal_unref(tbm_surface);
-               free(wayland_buffer);
+               free(wayland_egl_buffer);
                return NULL;
        }
 
-       wl_proxy_set_queue(wl_proxy, wayland_display->wl_queue);
+       wl_proxy_set_queue(wl_proxy, wayland_egl_display->wl_queue);
        wl_buffer_add_listener((void *)wl_proxy, &buffer_release_listener,
                               tbm_surface);
 
        wl_display_flush((struct wl_display *)surface->display->native_handle);
 
-       wayland_buffer->display = surface->display;
-       wayland_buffer->wl_proxy = wl_proxy;
-       wayland_buffer->bo = tbm_surface_internal_get_bo(tbm_surface, 0);
-       wayland_buffer->wayland_surface = wayland_surface;
-       wayland_surface->current_buffer = tbm_surface;
+       wayland_egl_buffer->display = surface->display;
+       wayland_egl_buffer->wl_proxy = wl_proxy;
+       wayland_egl_buffer->bo = tbm_surface_internal_get_bo(tbm_surface, 0);
+       wayland_egl_buffer->wayland_egl_surface = wayland_egl_surface;
+       wayland_egl_surface->current_buffer = tbm_surface;
 
-       __tpl_wayland_set_wayland_buffer_to_tbm_surface(tbm_surface, wayland_buffer);
+       __tpl_wayland_egl_set_wayland_buffer_to_tbm_surface(tbm_surface,
+                       wayland_egl_buffer);
 
        return tbm_surface;
 }
 
 static void
-__tpl_wayland_buffer_free(tpl_wayland_buffer_t *wayland_buffer)
+__tpl_wayland_egl_buffer_free(tpl_wayland_egl_buffer_t *wayland_egl_buffer)
 {
-       TPL_ASSERT(wayland_buffer);
-       TPL_ASSERT(wayland_buffer->display);
+       TPL_ASSERT(wayland_egl_buffer);
+       TPL_ASSERT(wayland_egl_buffer->display);
 
-       tpl_wayland_display_t *wayland_display =
-               (tpl_wayland_display_t *)wayland_buffer->display->backend.data;
+       tpl_wayland_egl_display_t *wayland_egl_display =
+               (tpl_wayland_egl_display_t *)wayland_egl_buffer->display->backend.data;
 
-       wl_display_flush((struct wl_display *)wayland_buffer->display->native_handle);
+       wl_display_flush((struct wl_display *)
+                        wayland_egl_buffer->display->native_handle);
 
-       if (wayland_buffer->wl_proxy)
-               wayland_tbm_client_destroy_buffer(wayland_display->wl_tbm_client,
-                                                 (void *)wayland_buffer->wl_proxy);
+       if (wayland_egl_buffer->wl_proxy)
+               wayland_tbm_client_destroy_buffer(wayland_egl_display->wl_tbm_client,
+                                                 (void *)wayland_egl_buffer->wl_proxy);
 
-       free(wayland_buffer);
+       free(wayland_egl_buffer);
 }
 
 tpl_bool_t
-__tpl_display_choose_backend_wayland(tpl_handle_t native_dpy)
+__tpl_display_choose_backend_wayland_egl(tpl_handle_t native_dpy)
 {
        if (!native_dpy) return TPL_FALSE;
 
-       if (__tpl_wayland_display_is_wl_display(native_dpy))
+       if (__tpl_wayland_egl_display_is_wl_display(native_dpy))
                return TPL_TRUE;
 
        return TPL_FALSE;
 }
 
 void
-__tpl_display_init_backend_wayland(tpl_display_backend_t *backend)
+__tpl_display_init_backend_wayland_egl(tpl_display_backend_t *backend)
 {
        TPL_ASSERT(backend);
 
        backend->type = TPL_BACKEND_WAYLAND;
        backend->data = NULL;
 
-       backend->init = __tpl_wayland_display_init;
-       backend->fini = __tpl_wayland_display_fini;
-       backend->query_config = __tpl_wayland_display_query_config;
-       backend->filter_config = __tpl_wayland_display_filter_config;
-       backend->get_window_info = __tpl_wayland_display_get_window_info;
-       backend->get_pixmap_info = __tpl_wayland_display_get_pixmap_info;
+       backend->init = __tpl_wayland_egl_display_init;
+       backend->fini = __tpl_wayland_egl_display_fini;
+       backend->query_config = __tpl_wayland_egl_display_query_config;
+       backend->filter_config = __tpl_wayland_egl_display_filter_config;
+       backend->get_window_info = __tpl_wayland_egl_display_get_window_info;
+       backend->get_pixmap_info = __tpl_wayland_egl_display_get_pixmap_info;
        backend->get_buffer_from_native_pixmap =
-               __tpl_wayland_display_get_buffer_from_native_pixmap;
+               __tpl_wayland_egl_display_get_buffer_from_native_pixmap;
 }
 
 void
-__tpl_surface_init_backend_wayland(tpl_surface_backend_t *backend)
+__tpl_surface_init_backend_wayland_egl(tpl_surface_backend_t *backend)
 {
        TPL_ASSERT(backend);
 
        backend->type = TPL_BACKEND_WAYLAND;
        backend->data = NULL;
 
-       backend->init = __tpl_wayland_surface_init;
-       backend->fini = __tpl_wayland_surface_fini;
-       backend->validate = __tpl_wayland_surface_validate;
-       backend->dequeue_buffer = __tpl_wayland_surface_dequeue_buffer;
-       backend->enqueue_buffer = __tpl_wayland_surface_enqueue_buffer;
+       backend->init = __tpl_wayland_egl_surface_init;
+       backend->fini = __tpl_wayland_egl_surface_fini;
+       backend->validate = __tpl_wayland_egl_surface_validate;
+       backend->dequeue_buffer = __tpl_wayland_egl_surface_dequeue_buffer;
+       backend->enqueue_buffer = __tpl_wayland_egl_surface_enqueue_buffer;
 }
 
 static void
@@ -729,23 +741,23 @@ static const struct wl_callback_listener frame_listener = {
 static void
 __cb_client_buffer_release_callback(void *data, struct wl_proxy *proxy)
 {
-       tpl_wayland_surface_t *wayland_surface = NULL;
-       tpl_wayland_buffer_t *wayland_buffer = NULL;
+       tpl_wayland_egl_surface_t *wayland_egl_surface = NULL;
+       tpl_wayland_egl_buffer_t *wayland_egl_buffer = NULL;
        tbm_surface_h tbm_surface = NULL;
 
        TPL_ASSERT(data);
 
        tbm_surface = (tbm_surface_h) data;
 
-       wayland_buffer =
-               __tpl_wayland_get_wayland_buffer_from_tbm_surface(tbm_surface);
+       wayland_egl_buffer =
+               __tpl_wayland_egl_get_wayland_buffer_from_tbm_surface(tbm_surface);
 
-       if (wayland_buffer) {
-               wayland_surface = wayland_buffer->wayland_surface;
+       if (wayland_egl_buffer) {
+               wayland_egl_surface = wayland_egl_buffer->wayland_egl_surface;
 
                tbm_surface_internal_unref(tbm_surface);
 
-               tbm_surface_queue_release(wayland_surface->tbm_queue, tbm_surface);
+               tbm_surface_queue_release(wayland_egl_surface->tbm_queue, tbm_surface);
        }
 }
 
@@ -762,14 +774,14 @@ __cb_client_window_resize_callback(struct wl_egl_window *wl_egl_window,
 
        int width, height;
        tpl_surface_t *surface = (tpl_surface_t *)private;
-       tpl_wayland_surface_t *wayland_surface = (tpl_wayland_surface_t *)
+       tpl_wayland_egl_surface_t *wayland_egl_surface = (tpl_wayland_egl_surface_t *)
                        surface->backend.data;
 
        width = wl_egl_window->width;
        height = wl_egl_window->height;
 
        /* Check whether the surface was resized by wayland_egl */
-       if ((width != tbm_surface_queue_get_width(wayland_surface->tbm_queue))
-           || (height != tbm_surface_queue_get_height(wayland_surface->tbm_queue)))
-               wayland_surface->resized = TPL_TRUE;
+       if ((width != tbm_surface_queue_get_width(wayland_egl_surface->tbm_queue))
+           || (height != tbm_surface_queue_get_height(wayland_egl_surface->tbm_queue)))
+               wayland_egl_surface->resized = TPL_TRUE;
 }
diff --git a/src/tpl_wayland_vk_wsi.c b/src/tpl_wayland_vk_wsi.c
new file mode 100644 (file)
index 0000000..544f19f
--- /dev/null
@@ -0,0 +1,645 @@
+#define inline __inline__
+#include <wayland-client.h>
+#undef inline
+
+#include "tpl_internal.h"
+
+#include <tbm_surface.h>
+#include <tbm_surface_internal.h>
+#include <tbm_surface_queue.h>
+#include <wayland-tbm-client.h>
+
+#define CLIENT_QUEUE_SIZE 3
+
+typedef struct _tpl_wayland_vk_wsi_display tpl_wayland_vk_wsi_display_t;
+typedef struct _tpl_wayland_vk_wsi_surface tpl_wayland_vk_wsi_surface_t;
+typedef struct _tpl_wayland_vk_wsi_buffer tpl_wayland_vk_wsi_buffer_t;
+
+struct _tpl_wayland_vk_wsi_display {
+       struct wayland_tbm_client *wl_tbm_client;
+};
+
+struct _tpl_wayland_vk_wsi_surface {
+       tbm_surface_queue_h tbm_queue;
+       int buffer_count;
+};
+
+struct _tpl_wayland_vk_wsi_buffer {
+       tpl_display_t *display;
+       tpl_wayland_vk_wsi_surface_t *wayland_vk_wsi_surface;
+       struct wl_proxy *wl_proxy;
+};
+
+static const struct wl_registry_listener registry_listener;
+static const struct wl_callback_listener sync_listener;
+static const struct wl_callback_listener frame_listener;
+static const struct wl_buffer_listener buffer_release_listener;
+
+#define TPL_BUFFER_CACHE_MAX_ENTRIES 40
+
+static int tpl_wayland_vk_wsi_buffer_key;
+#define KEY_tpl_wayland_vk_wsi_buffer  (unsigned long)(&tpl_wayland_vk_wsi_buffer_key)
+
+static void __tpl_wayland_vk_wsi_buffer_free(tpl_wayland_vk_wsi_buffer_t
+               *wayland_vk_wsi_buffer);
+static tpl_result_t __tpl_wayland_vk_wsi_surface_destroy_swapchain(
+       tpl_surface_t *surface);
+
+static TPL_INLINE tpl_wayland_vk_wsi_buffer_t *
+__tpl_wayland_vk_wsi_get_wayland_buffer_from_tbm_surface(tbm_surface_h surface)
+{
+       tpl_wayland_vk_wsi_buffer_t *buf = NULL;
+       tbm_surface_internal_get_user_data(surface, KEY_tpl_wayland_vk_wsi_buffer,
+                                          (void **)&buf);
+       return buf;
+}
+
+static TPL_INLINE void
+__tpl_wayland_vk_wsi_set_wayland_buffer_to_tbm_surface(tbm_surface_h surface,
+               tpl_wayland_vk_wsi_buffer_t *buf)
+{
+       tbm_surface_internal_add_user_data(surface,
+                                          KEY_tpl_wayland_vk_wsi_buffer,
+                                          (tbm_data_free)__tpl_wayland_vk_wsi_buffer_free);
+       tbm_surface_internal_set_user_data(surface,
+                                          KEY_tpl_wayland_vk_wsi_buffer, buf);
+}
+
+static TPL_INLINE tpl_bool_t
+__tpl_wayland_vk_wsi_display_is_wl_display(tpl_handle_t native_dpy)
+{
+       TPL_ASSERT(native_dpy);
+
+       struct wl_interface *wl_egl_native_dpy = *(void **) native_dpy;
+
+       /* MAGIC CHECK: A native display handle is a wl_display if the de-referenced first value
+          is a memory address pointing the structure of wl_display_interface. */
+       if ( wl_egl_native_dpy == &wl_display_interface ) {
+               return TPL_TRUE;
+       }
+
+       if (strncmp(wl_egl_native_dpy->name, wl_display_interface.name,
+                   strlen(wl_display_interface.name)) == 0) {
+               return TPL_TRUE;
+       }
+
+       return TPL_FALSE;
+}
+
+static int
+__tpl_wayland_vk_wsi_display_roundtrip(tpl_display_t *display)
+{
+       struct wl_display *wl_dpy;
+       struct wl_callback *callback;
+       int done = 0, ret = 0;
+
+       TPL_ASSERT(display);
+       TPL_ASSERT(display->native_handle);
+       TPL_ASSERT(display->backend.data);
+
+       wl_dpy = (struct wl_display *) display->native_handle;
+
+       callback = wl_display_sync(wl_dpy);
+       wl_callback_add_listener(callback, &sync_listener, &done);
+
+       while (ret != -1 && !done) {
+               ret = wl_display_dispatch(wl_dpy);
+       }
+
+       return ret;
+}
+
+static tpl_result_t
+__tpl_wayland_vk_wsi_display_init(tpl_display_t *display)
+{
+       tpl_wayland_vk_wsi_display_t *wayland_vk_wsi_display = NULL;
+
+       TPL_ASSERT(display);
+
+       /* Do not allow default display in wayland. */
+       if (!display->native_handle) {
+               TPL_ERR("Invalid native handle for display.");
+               return TPL_ERROR_INVALID_PARAMETER;
+       }
+
+       wayland_vk_wsi_display = (tpl_wayland_vk_wsi_display_t *) calloc(1,
+                                sizeof(tpl_wayland_vk_wsi_display_t));
+       if (!wayland_vk_wsi_display) {
+               TPL_ERR("Failed to allocate memory for new tpl_wayland_vk_wsi_display_t.");
+               return TPL_ERROR_INVALID_OPERATION;
+       }
+
+       display->backend.data = wayland_vk_wsi_display;
+
+       if (__tpl_wayland_vk_wsi_display_is_wl_display(display->native_handle)) {
+               struct wl_display *wl_dpy =
+                       (struct wl_display *)display->native_handle;
+               wayland_vk_wsi_display->wl_tbm_client =
+                       wayland_tbm_client_init((struct wl_display *) wl_dpy);
+
+               if (!wayland_vk_wsi_display->wl_tbm_client) {
+                       TPL_ERR("Wayland TBM initialization failed!");
+                       goto free_wl_display;
+               }
+       } else {
+               goto free_wl_display;
+       }
+
+       return TPL_ERROR_NONE;
+
+free_wl_display:
+       if (wayland_vk_wsi_display) {
+               free(wayland_vk_wsi_display);
+               display->backend.data = NULL;
+       }
+       return TPL_ERROR_INVALID_OPERATION;
+}
+
+static void
+__tpl_wayland_vk_wsi_display_fini(tpl_display_t *display)
+{
+       tpl_wayland_vk_wsi_display_t *wayland_vk_wsi_display;
+
+       TPL_ASSERT(display);
+
+       wayland_vk_wsi_display = (tpl_wayland_vk_wsi_display_t *)display->backend.data;
+       if (wayland_vk_wsi_display) {
+               wayland_tbm_client_deinit(wayland_vk_wsi_display->wl_tbm_client);
+               free(wayland_vk_wsi_display);
+       }
+       display->backend.data = NULL;
+}
+
+static tpl_result_t
+__tpl_wayland_vk_wsi_display_query_config(tpl_display_t *display,
+               tpl_surface_type_t surface_type,
+               int red_size, int green_size,
+               int blue_size, int alpha_size,
+               int color_depth, int *native_visual_id,
+               tpl_bool_t *is_slow)
+{
+       TPL_ASSERT(display);
+
+       if (surface_type == TPL_SURFACE_TYPE_WINDOW && red_size == 8 &&
+           green_size == 8 && blue_size == 8 &&
+           (color_depth == 32 || color_depth == 24)) {
+
+               if (alpha_size == 8) {
+                       if (native_visual_id) *native_visual_id = TBM_FORMAT_ARGB8888;
+                       if (is_slow) *is_slow = TPL_FALSE;
+                       return TPL_ERROR_NONE;
+               }
+               if (alpha_size == 0) {
+                       if (native_visual_id) *native_visual_id = TBM_FORMAT_XRGB8888;
+                       if (is_slow) *is_slow = TPL_FALSE;
+                       return TPL_ERROR_NONE;
+               }
+       }
+
+       return TPL_ERROR_INVALID_PARAMETER;
+}
+
+static tpl_result_t
+__tpl_wayland_vk_wsi_display_filter_config(tpl_display_t *display,
+               int *visual_id,
+               int alpha_size)
+{
+       TPL_IGNORE(display);
+       TPL_IGNORE(visual_id);
+       TPL_IGNORE(alpha_size);
+       return TPL_ERROR_NONE;
+}
+
+static tpl_result_t
+__tpl_wayland_vk_wsi_surface_init(tpl_surface_t *surface)
+{
+       tpl_wayland_vk_wsi_surface_t *wayland_vk_wsi_surface = NULL;
+
+       TPL_ASSERT(surface);
+       TPL_ASSERT(surface->type == TPL_SURFACE_TYPE_WINDOW);
+       TPL_ASSERT(surface->native_handle);
+
+       wayland_vk_wsi_surface = (tpl_wayland_vk_wsi_surface_t *) calloc(1,
+                                sizeof(tpl_wayland_vk_wsi_surface_t));
+       if (!wayland_vk_wsi_surface) {
+               TPL_ERR("Failed to allocate memory for new tpl_wayland_vk_wsi_surface_t.");
+               return TPL_ERROR_INVALID_OPERATION;
+       }
+
+       surface->backend.data = (void *)wayland_vk_wsi_surface;
+       wayland_vk_wsi_surface->tbm_queue = NULL;
+
+       surface->capabilities.min_buffer = 2;
+       surface->capabilities.max_buffer = CLIENT_QUEUE_SIZE;
+
+       TPL_LOG(3, "window(%p, %p) %dx%d", surface, surface->native_handle,
+               surface->width, surface->height);
+
+       return TPL_ERROR_NONE;
+}
+
+static void
+__tpl_wayland_vk_wsi_surface_fini(tpl_surface_t *surface)
+{
+       tpl_wayland_vk_wsi_surface_t *wayland_vk_wsi_surface = NULL;
+       tpl_wayland_vk_wsi_display_t *wayland_vk_wsi_display = NULL;
+
+       TPL_ASSERT(surface);
+       TPL_ASSERT(surface->display);
+
+       wayland_vk_wsi_surface = (tpl_wayland_vk_wsi_surface_t *) surface->backend.data;
+       if (wayland_vk_wsi_surface == NULL) return;
+
+       wayland_vk_wsi_display = (tpl_wayland_vk_wsi_display_t *)
+                                surface->display->backend.data;
+       if (wayland_vk_wsi_display == NULL) return;
+
+       TPL_LOG(3, "window(%p, %p)", surface, surface->native_handle);
+
+       if (wayland_vk_wsi_surface->tbm_queue)
+               __tpl_wayland_vk_wsi_surface_destroy_swapchain(surface);
+
+       free(wayland_vk_wsi_surface);
+       surface->backend.data = NULL;
+}
+
+static tpl_result_t
+__tpl_wayland_vk_wsi_surface_enqueue_buffer(tpl_surface_t *surface,
+               tbm_surface_h tbm_surface,
+               int num_rects, const int *rects)
+{
+       struct wl_surface *wl_sfc = NULL;
+       struct wl_callback *frame_callback = NULL;
+
+       TPL_ASSERT(surface);
+       TPL_ASSERT(surface->display);
+       TPL_ASSERT(surface->display->native_handle);
+       TPL_ASSERT(tbm_surface);
+
+       tpl_wayland_vk_wsi_surface_t *wayland_vk_wsi_surface =
+               (tpl_wayland_vk_wsi_surface_t *) surface->backend.data;
+       tpl_wayland_vk_wsi_buffer_t *wayland_vk_wsi_buffer = NULL;
+       tbm_surface_queue_error_e tsq_err;
+
+       TPL_LOG(3, "window(%p, %p)", surface, surface->native_handle);
+
+       wayland_vk_wsi_buffer =
+               __tpl_wayland_vk_wsi_get_wayland_buffer_from_tbm_surface(tbm_surface);
+       TPL_ASSERT(wayland_vk_wsi_buffer);
+
+       tbm_bo_handle bo_handle =
+               tbm_bo_get_handle(tbm_surface_internal_get_bo(tbm_surface, 0), TBM_DEVICE_CPU);
+
+       if (bo_handle.ptr)
+               TPL_IMAGE_DUMP(bo_handle.ptr, surface->width, surface->height,
+                              surface->dump_count++);
+
+       wl_sfc = (struct wl_surface *)surface->native_handle;
+
+       tbm_surface_internal_unref(tbm_surface);
+
+       tsq_err = tbm_surface_queue_enqueue(wayland_vk_wsi_surface->tbm_queue,
+                                           tbm_surface);
+       if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) {
+               TPL_ERR("Failed to enqeueue tbm_surface. | tsq_err = %d", tsq_err);
+               return TPL_ERROR_INVALID_OPERATION;
+       }
+
+       tsq_err = tbm_surface_queue_acquire(wayland_vk_wsi_surface->tbm_queue,
+                                           &tbm_surface);
+       if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) {
+               TPL_ERR("Failed to acquire tbm_surface. | tsq_err = %d", tsq_err);
+               return TPL_ERROR_INVALID_OPERATION;
+       }
+
+       tbm_surface_internal_ref(tbm_surface);
+       wl_surface_attach(wl_sfc, (void *)wayland_vk_wsi_buffer->wl_proxy, 0, 0);
+
+       wl_surface_damage(wl_sfc, 0, 0, surface->width, surface->height);
+
+       frame_callback = wl_surface_frame(wl_sfc);
+       wl_callback_add_listener(frame_callback, &frame_listener, tbm_surface);
+
+       wl_surface_commit(wl_sfc);
+
+       wl_display_flush(surface->display->native_handle);
+
+       return TPL_ERROR_NONE;
+}
+
+static tpl_bool_t
+__tpl_wayland_vk_wsi_surface_validate(tpl_surface_t *surface)
+{
+       TPL_ASSERT(surface);
+       TPL_ASSERT(surface->backend.data);
+
+       return TPL_TRUE;
+}
+
+static tbm_surface_h
+__tpl_wayland_vk_wsi_surface_dequeue_buffer(tpl_surface_t *surface)
+{
+       TPL_ASSERT(surface);
+       TPL_ASSERT(surface->backend.data);
+       TPL_ASSERT(surface->display);
+
+       tbm_surface_h tbm_surface = NULL;
+       tpl_wayland_vk_wsi_buffer_t *wayland_vk_wsi_buffer = NULL;
+       tpl_wayland_vk_wsi_surface_t *wayland_vk_wsi_surface =
+               (tpl_wayland_vk_wsi_surface_t *)surface->backend.data;
+       tpl_wayland_vk_wsi_display_t *wayland_vk_wsi_display =
+               (tpl_wayland_vk_wsi_display_t *)surface->display->backend.data;
+       struct wl_proxy *wl_proxy = NULL;
+       tbm_surface_queue_error_e tsq_err = 0;
+
+       TPL_OBJECT_UNLOCK(surface);
+       while (tbm_surface_queue_can_dequeue(
+                      wayland_vk_wsi_surface->tbm_queue, 0) == 0) {
+               /* Application sent all buffers to the server. Wait for server response. */
+
+               if (wl_display_dispatch(surface->display->native_handle) == -1) {
+                       TPL_OBJECT_LOCK(surface);
+                       return NULL;
+               }
+       }
+       TPL_OBJECT_LOCK(surface);
+
+       tsq_err = tbm_surface_queue_dequeue(wayland_vk_wsi_surface->tbm_queue,
+                                           &tbm_surface);
+       if (!tbm_surface) {
+               TPL_ERR("Failed to get tbm_surface from tbm_surface_queue | tsq_err = %d",
+                       tsq_err);
+               return NULL;
+       }
+
+       tbm_surface_internal_ref(tbm_surface);
+
+       if ((wayland_vk_wsi_buffer =
+                    __tpl_wayland_vk_wsi_get_wayland_buffer_from_tbm_surface(
+                            tbm_surface)) != NULL) {
+               return tbm_surface;
+       }
+
+       wayland_vk_wsi_buffer = (tpl_wayland_vk_wsi_buffer_t *) calloc(1,
+                               sizeof(tpl_wayland_vk_wsi_buffer_t));
+       if (!wayland_vk_wsi_buffer) {
+               TPL_ERR("Mem alloc for wayland_vk_wsi_buffer failed!");
+               tbm_surface_internal_unref(tbm_surface);
+               return NULL;
+       }
+
+       wl_proxy = (struct wl_proxy *)wayland_tbm_client_create_buffer(
+                          wayland_vk_wsi_display->wl_tbm_client, tbm_surface);
+       if (!wl_proxy) {
+               TPL_ERR("Failed to create TBM client buffer!");
+               tbm_surface_internal_unref(tbm_surface);
+               free(wayland_vk_wsi_buffer);
+               return NULL;
+       }
+
+       wl_buffer_add_listener((void *)wl_proxy, &buffer_release_listener,
+                              tbm_surface);
+
+       wl_display_flush((struct wl_display *)surface->display->native_handle);
+
+       wayland_vk_wsi_buffer->display = surface->display;
+       wayland_vk_wsi_buffer->wl_proxy = wl_proxy;
+       wayland_vk_wsi_buffer->wayland_vk_wsi_surface = wayland_vk_wsi_surface;
+
+       __tpl_wayland_vk_wsi_set_wayland_buffer_to_tbm_surface(tbm_surface,
+                       wayland_vk_wsi_buffer);
+
+       return tbm_surface;
+}
+
+static tpl_result_t
+__tpl_wayland_vk_wsi_surface_get_swapchain_buffers(tpl_surface_t *surface,
+               tbm_surface_h **buffers,
+               int *buffer_count)
+{
+       tbm_surface_h buffer = NULL;
+       tbm_surface_h *swapchain_buffers = NULL;
+       tpl_wayland_vk_wsi_surface_t *wayland_vk_wsi_surface = NULL;
+       tbm_surface_queue_error_e tsq_err;
+       int i;
+
+       TPL_ASSERT(surface);
+       TPL_ASSERT(surface->backend.data);
+       TPL_ASSERT(surface->display);
+       TPL_ASSERT(buffers);
+       TPL_ASSERT(buffer_count);
+
+       wayland_vk_wsi_surface = (tpl_wayland_vk_wsi_surface_t *)surface->backend.data;
+       swapchain_buffers = (tbm_surface_h *)calloc(
+                                   wayland_vk_wsi_surface->buffer_count, sizeof(tbm_surface_h));
+       if (!swapchain_buffers) {
+               TPL_ERR("Failed to allocate memory for buffers.");
+               return TPL_ERROR_INVALID_OPERATION;
+       }
+
+       for (i = 0 ; i < wayland_vk_wsi_surface->buffer_count ; i++) {
+               tsq_err = tbm_surface_queue_dequeue(wayland_vk_wsi_surface->tbm_queue, &buffer);
+               if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) {
+                       TPL_ERR("Failed to get tbm_surface from tbm_surface_queue | tsq_err = %d",
+                               tsq_err);
+                       goto get_buffer_fail;
+               }
+               tsq_err = tbm_surface_queue_release(wayland_vk_wsi_surface->tbm_queue, buffer);
+               if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) {
+                       TPL_ERR("Failed to release tbm_surface. | tsq_err = %d", tsq_err);
+                       goto get_buffer_fail;
+               }
+               swapchain_buffers[i] = buffer;
+       }
+
+       *buffers = swapchain_buffers;
+       *buffer_count = wayland_vk_wsi_surface->buffer_count;
+       return TPL_ERROR_NONE;
+
+get_buffer_fail:
+       free(swapchain_buffers);
+       return TPL_ERROR_INVALID_OPERATION;
+}
+
+static tpl_result_t
+__tpl_wayland_vk_wsi_surface_create_swapchain(tpl_surface_t *surface,
+               tbm_format format, int width,
+               int height, int buffer_count)
+{
+       tpl_wayland_vk_wsi_surface_t *wayland_vk_wsi_surface = NULL;
+
+       TPL_ASSERT(surface);
+       TPL_ASSERT(surface->backend.data);
+       TPL_ASSERT(surface->display);
+
+       wayland_vk_wsi_surface = (tpl_wayland_vk_wsi_surface_t *) surface->backend.data;
+       TPL_ASSERT(wayland_vk_wsi_surface);
+
+       wayland_vk_wsi_surface->tbm_queue = tbm_surface_queue_create(buffer_count,
+                                           width,
+                                           height,
+                                           TBM_FORMAT_ARGB8888,
+                                           0);
+
+       if (!wayland_vk_wsi_surface->tbm_queue) {
+               TPL_ERR("TBM surface queue creation failed!");
+               return TPL_ERROR_INVALID_OPERATION;
+       }
+
+       wayland_vk_wsi_surface->buffer_count = buffer_count;
+
+       surface->width = width;
+       surface->height = height;
+
+       return TPL_ERROR_NONE;
+}
+
+static tpl_result_t
+__tpl_wayland_vk_wsi_surface_destroy_swapchain(tpl_surface_t *surface)
+{
+       tpl_wayland_vk_wsi_surface_t *wayland_vk_wsi_surface = NULL;
+
+       TPL_ASSERT(surface);
+       TPL_ASSERT(surface->backend.data);
+       TPL_ASSERT(surface->display);
+
+       wayland_vk_wsi_surface = (tpl_wayland_vk_wsi_surface_t *) surface->backend.data;
+       TPL_ASSERT(wayland_vk_wsi_surface);
+
+       if (surface->type == TPL_SURFACE_TYPE_WINDOW) {
+
+               wl_display_flush(surface->display->native_handle);
+               __tpl_wayland_vk_wsi_display_roundtrip(surface->display);
+
+               tbm_surface_queue_destroy(wayland_vk_wsi_surface->tbm_queue);
+               wayland_vk_wsi_surface->tbm_queue = NULL;
+       }
+
+       return TPL_ERROR_NONE;
+}
+
+static void
+__tpl_wayland_vk_wsi_buffer_free(tpl_wayland_vk_wsi_buffer_t
+                                *wayland_vk_wsi_buffer)
+{
+       TPL_ASSERT(wayland_vk_wsi_buffer);
+       TPL_ASSERT(wayland_vk_wsi_buffer->display);
+
+       tpl_wayland_vk_wsi_display_t *wayland_vk_wsi_display =
+               (tpl_wayland_vk_wsi_display_t *)wayland_vk_wsi_buffer->display->backend.data;
+
+       wl_display_flush((struct wl_display *)
+                        wayland_vk_wsi_buffer->display->native_handle);
+
+       if (wayland_vk_wsi_buffer->wl_proxy)
+               wayland_tbm_client_destroy_buffer(wayland_vk_wsi_display->wl_tbm_client,
+                                                 (void *)wayland_vk_wsi_buffer->wl_proxy);
+
+       free(wayland_vk_wsi_buffer);
+}
+
+tpl_bool_t
+__tpl_display_choose_backend_wayland_vk_wsi(tpl_handle_t native_dpy)
+{
+       if (!native_dpy) return TPL_FALSE;
+
+       if (__tpl_wayland_vk_wsi_display_is_wl_display(native_dpy))
+               return TPL_TRUE;
+
+       return TPL_FALSE;
+}
+
+void
+__tpl_display_init_backend_wayland_vk_wsi(tpl_display_backend_t *backend)
+{
+       TPL_ASSERT(backend);
+
+       backend->type = TPL_BACKEND_WAYLAND_VULKAN_WSI;
+       backend->data = NULL;
+
+       backend->init = __tpl_wayland_vk_wsi_display_init;
+       backend->fini = __tpl_wayland_vk_wsi_display_fini;
+       backend->query_config = __tpl_wayland_vk_wsi_display_query_config;
+       backend->filter_config = __tpl_wayland_vk_wsi_display_filter_config;
+}
+
+void
+__tpl_surface_init_backend_wayland_vk_wsi(tpl_surface_backend_t *backend)
+{
+       TPL_ASSERT(backend);
+
+       backend->type = TPL_BACKEND_WAYLAND_VULKAN_WSI;
+       backend->data = NULL;
+
+       backend->init = __tpl_wayland_vk_wsi_surface_init;
+       backend->fini = __tpl_wayland_vk_wsi_surface_fini;
+       backend->validate = __tpl_wayland_vk_wsi_surface_validate;
+       backend->dequeue_buffer = __tpl_wayland_vk_wsi_surface_dequeue_buffer;
+       backend->enqueue_buffer = __tpl_wayland_vk_wsi_surface_enqueue_buffer;
+       backend->get_swapchain_buffers =
+               __tpl_wayland_vk_wsi_surface_get_swapchain_buffers;
+       backend->create_swapchain = __tpl_wayland_vk_wsi_surface_create_swapchain;
+       backend->destroy_swapchain = __tpl_wayland_vk_wsi_surface_destroy_swapchain;
+}
+
+static void
+__cb_client_sync_callback(void *data, struct wl_callback *callback,
+                         uint32_t serial)
+{
+       int *done;
+
+       TPL_ASSERT(data);
+
+       done = data;
+       *done = 1;
+
+       wl_callback_destroy(callback);
+}
+
+static const struct wl_callback_listener sync_listener = {
+       __cb_client_sync_callback
+};
+
+static void
+__cb_client_frame_callback(void *data, struct wl_callback *callback,
+                          uint32_t time)
+{
+       /* We moved the buffer reclaim logic to buffer_release_callback().
+          buffer_release_callback() is more suitable point to delete or reuse buffer instead of frame_callback().
+          But we remain this callback because buffer_release_callback() works only when frame_callback() is activated.*/
+       TPL_IGNORE(data);
+       TPL_IGNORE(time);
+
+       wl_callback_destroy(callback);
+}
+
+static const struct wl_callback_listener frame_listener = {
+       __cb_client_frame_callback
+};
+
+static void
+__cb_client_buffer_release_callback(void *data, struct wl_proxy *proxy)
+{
+       tpl_wayland_vk_wsi_surface_t *wayland_vk_wsi_surface = NULL;
+       tpl_wayland_vk_wsi_buffer_t *wayland_vk_wsi_buffer = NULL;
+       tbm_surface_h tbm_surface = NULL;
+
+       TPL_ASSERT(data);
+
+       tbm_surface = (tbm_surface_h) data;
+
+       wayland_vk_wsi_buffer =
+               __tpl_wayland_vk_wsi_get_wayland_buffer_from_tbm_surface(tbm_surface);
+
+       if (wayland_vk_wsi_buffer) {
+               wayland_vk_wsi_surface = wayland_vk_wsi_buffer->wayland_vk_wsi_surface;
+
+               tbm_surface_internal_unref(tbm_surface);
+
+               tbm_surface_queue_release(wayland_vk_wsi_surface->tbm_queue, tbm_surface);
+       }
+}
+
+static const struct wl_buffer_listener buffer_release_listener = {
+       (void *)__cb_client_buffer_release_callback,
+};