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
#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
}
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)
__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);
__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);
*/
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;
* 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);
* @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);
* @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,
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.
*/
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 */
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;
TPL_ERR("Failed to get native pixmap info.");
goto error;
}
+ surface->capabilities.min_buffer = surface->capabilities.max_buffer = 1;
return TPL_ERROR_NONE;
}
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 {
int width, height;
int post_interval;
int dump_count;
+ struct {
+ int min_buffer;
+ int max_buffer;
+ } capabilities;
tpl_surface_backend_t backend;
};
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,
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);
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;
+}
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);
goto error;
}
+ surface->capabilities.min_buffer = surface->capabilities.max_buffer = 1;
tbm_surface_internal_ref((tbm_surface_h)surface->native_handle);
/* 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;
};
#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);
}
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;
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);
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;
}
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);
}
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);
}
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);
}
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;
}
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;
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;
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;
}
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);
}
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);
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,
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;
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);
}
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);
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
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);
}
}
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;
}
--- /dev/null
+#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,
+};