From 9fb800fc3402427caa9e369b8eb1f48bdd7480c1 Mon Sep 17 00:00:00 2001 From: "deasung.kim" Date: Tue, 25 Oct 2016 15:31:01 +0900 Subject: [PATCH 01/16] worker_thread: added epoll_wait continue condition If errno is EINTR goto epoll_wait Change-Id: If937e95a08b0abc7a27e7cb75a087e5b1d361934 --- src/tpl_worker_thread.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/tpl_worker_thread.c b/src/tpl_worker_thread.c index 658c574..6d62c4b 100644 --- a/src/tpl_worker_thread.c +++ b/src/tpl_worker_thread.c @@ -318,10 +318,12 @@ __tpl_worker_thread_loop(void *arg) pthread_mutex_unlock(&tpl_worker_thread.surface_mutex); /* wait events */ +cont_epoll_wait: ret = epoll_wait(epoll_fd, ev_list, EPOLL_MAX_SIZE, -1); if (ret == -1) { - TPL_ERR_ERRNO("epoll fd: %d.", epoll_fd); - continue; + if (errno != EINTR) + TPL_ERR_ERRNO("epoll fd: %d.", epoll_fd); + goto cont_epoll_wait; } for (i = 0; i < ret; i++) { -- 2.7.4 From 6b9c9ba4f6a24d7a31a8776409c01be2aeb624fa Mon Sep 17 00:00:00 2001 From: "Mun, Gwan-gyeong" Date: Wed, 30 Nov 2016 19:52:56 +0900 Subject: [PATCH 02/16] tpl_wayland_egl: Add missing error-checking to __tpl_wayland_egl_display_buffer_flusher_init When the wl_display_get_registry() fails on __tpl_wayland_egl_display_buffer_flusher_init(), this patch makes to return and deinitialize allocated resource. Change-Id: I773089d55f7555d269e183f3c129e2171c0243eb Signed-off-by: Mun, Gwan-gyeong --- src/tpl_wayland_egl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index 2569a00..d6c5cac 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -1255,7 +1255,7 @@ __tpl_wayland_egl_display_buffer_flusher_init( } registry = wl_display_get_registry(wayland_egl_display->wl_dpy); - if (!queue) { + if (!registry) { TPL_ERR("Failed to create wl_registry"); goto fini; } -- 2.7.4 From b9075f4473e8d08c83f21903c792385eca4fc5cf Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Wed, 30 Nov 2016 21:18:26 +0900 Subject: [PATCH 03/16] tpl_tbm: Delete TPL_ASSERT checking to __tpl_tbm_display_get_window_info. - Unused parameter(tpl_display) change TPL_ASSERT to TPL_IGNORE. - TPL_ASSERT(window) doesn't the necessity because there are NULL checking for window and log printing. Change-Id: Ie3412ca8a33e59436caee8c3546781f949b672e0 Signed-off-by: joonbum.ko --- src/tpl_tbm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/tpl_tbm.c b/src/tpl_tbm.c index b656306..cfdbd84 100644 --- a/src/tpl_tbm.c +++ b/src/tpl_tbm.c @@ -117,12 +117,11 @@ __tpl_tbm_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); + TPL_IGNORE(display); tbm_surface_queue_h surf_queue = (tbm_surface_queue_h)window; if (!surf_queue) { - TPL_ERR("Native widow(%p) is invalid.", window); + TPL_ERR("Native window(%p) is invalid.", window); return TPL_ERROR_INVALID_PARAMETER; } -- 2.7.4 From 4b09350a21ae3fa4f726f4c9a8fff9d4e1222471 Mon Sep 17 00:00:00 2001 From: "Mun, Gwan-gyeong" Date: Wed, 30 Nov 2016 21:21:04 +0900 Subject: [PATCH 04/16] tpl_worker_thread: drop checking of fence_result on __tpl_worker_thread_loop() fence_result is always 1 in the switch case statement of fence_result == 1 so we should drop checking of fence_result on __tpl_worker_thread_loop() Change-Id: Iae6db812889dcb0adaeb202d90711f7c1089d889 --- src/tpl_worker_thread.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/tpl_worker_thread.c b/src/tpl_worker_thread.c index 6d62c4b..7946e4f 100644 --- a/src/tpl_worker_thread.c +++ b/src/tpl_worker_thread.c @@ -377,9 +377,7 @@ cont_epoll_wait: if (surface->draw_done) surface->draw_done(surface->surface, surface->draw_wait_buffer, - fence_result == 1 ? - TPL_ERROR_NONE : - TPL_ERROR_INVALID_OPERATION); + TPL_ERROR_NONE); surface->draw_wait_buffer = NULL; break; case -1: -- 2.7.4 From e31a5104bf9eb31ee1ca28230d99812c84e25818 Mon Sep 17 00:00:00 2001 From: "Mun, Gwan-gyeong" Date: Wed, 9 Nov 2016 17:36:40 +0900 Subject: [PATCH 05/16] tpl: Add tpl_surface_get_rotation() / tpl_surface_set_rotation_capability() apis tpl_wayland_egl: implement getting of tpl_surface angle. implement getting of tpl_surface's capabilities wayland-egl: Add wl_egl_window_set_rotation() / wl_egl_window_get_capabilities() - tpl_surface_get_rotation() api used for getting the current rotation-angle of the given TPL surface. tpl_surface's angle can be in 0, 90, 180, 270. - wl_egl_window_set_rotation api used fo setting the current egl_window's angle. - wl_egl_window_get_capabilities api used for getting capabilities of egl_window. Change-Id: If051e890c040aff40097f88d26276b3b0b2bf4fd Signed-off-by: Mun, Gwan-gyeong --- src/tpl.h | 19 +++++++++++ src/tpl_internal.h | 2 ++ src/tpl_surface.c | 29 +++++++++++++++++ src/tpl_wayland_egl.c | 47 +++++++++++++++++++++++++++ src/wayland-egl/wayland-egl-priv.h | 5 +++ src/wayland-egl/wayland-egl.c | 65 +++++++++++++++++++++++++++++++++++++- 6 files changed, 166 insertions(+), 1 deletion(-) diff --git a/src/tpl.h b/src/tpl.h index 4d9145f..82cf601 100644 --- a/src/tpl.h +++ b/src/tpl.h @@ -426,6 +426,17 @@ tpl_result_t tpl_surface_get_size(tpl_surface_t *surface, int *width, int *height); /** + * Get the current rotation-angle of the given TPL surface. + * + * tpl_surface's angle can be in 0, 90, 180, 270. + * + * @param surface surface to get rotation-angle. + * @param rotation pointer to receive rotation-angle value. + */ +tpl_result_t +tpl_surface_get_rotation(tpl_surface_t *surface, int *rotation); + +/** * Validate current frame of the given TPL surface. * * Users should call this function before getting actual final render target @@ -730,6 +741,14 @@ tpl_surface_set_reset_cb(tpl_surface_t *surface, void* data, tpl_surface_cb_func_t reset_cb); /** + * Set rotation capability to the given tpl_surface + * @param surface surface used for set + * @param set TPL_TRUE if user want to set to enable / disable capability of rotation + */ +tpl_result_t +tpl_surface_set_rotation_capability(tpl_surface_t *surface, tpl_bool_t set); + +/** * Present mode types. * * @TPL_DISPLAY_MODE_IMMEDIATE_KHR: The presentation engine does not wait for diff --git a/src/tpl_internal.h b/src/tpl_internal.h index 2297db4..a881013 100644 --- a/src/tpl_internal.h +++ b/src/tpl_internal.h @@ -128,8 +128,10 @@ struct _tpl_surface { tpl_surface_type_t type; tbm_format format; int width, height; + int rotation; int post_interval; int dump_count; + tpl_bool_t rotation_capability; tpl_surface_backend_t backend; /*For frontbuffer extension*/ diff --git a/src/tpl_surface.c b/src/tpl_surface.c index ed8cc9f..c991868 100644 --- a/src/tpl_surface.c +++ b/src/tpl_surface.c @@ -119,6 +119,18 @@ tpl_surface_get_size(tpl_surface_t *surface, int *width, int *height) return TPL_ERROR_NONE; } +tpl_result_t +tpl_surface_get_rotation(tpl_surface_t *surface, int *rotation) +{ + if (!surface) { + TPL_ERR("Surface is NULL!"); + return TPL_ERROR_INVALID_PARAMETER; + } + + if (rotation) *rotation = surface->rotation; + + return TPL_ERROR_NONE; +} tpl_bool_t tpl_surface_validate(tpl_surface_t *surface) @@ -425,3 +437,20 @@ tpl_surface_set_reset_cb(tpl_surface_t *surface, void *data, tpl_surface_cb_func return ret; } + +tpl_result_t +tpl_surface_set_rotation_capability(tpl_surface_t *surface, tpl_bool_t set) +{ + if (!surface || (surface->type != TPL_SURFACE_TYPE_WINDOW)) { + TPL_ERR("Invalid surface!"); + return TPL_ERROR_INVALID_PARAMETER; + } + + TPL_OBJECT_LOCK(surface); + + surface->rotation_capability = set; + + TPL_OBJECT_UNLOCK(surface); + + return TPL_ERROR_NONE; +} diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index d6c5cac..2b89173 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -373,6 +373,14 @@ static void __cb_client_window_resize_callback(struct wl_egl_window *wl_egl_window, void *private); +static void +__cb_client_window_rotate_callback(struct wl_egl_window *wl_egl_window, + void *private); + +static int +__cb_client_window_get_rotation_capability(struct wl_egl_window *wl_egl_window, + void *private); + static TPL_INLINE void __tpl_wayland_egl_buffer_set_reset_flag(tpl_list_t *tracking_list) { @@ -539,9 +547,13 @@ __tpl_wayland_egl_surface_init(tpl_surface_t *surface) surface->width = wl_egl_window->width; surface->height = wl_egl_window->height; + surface->rotation = wl_egl_window->rotation; + surface->rotation_capability = TPL_FALSE; wl_egl_window->private = surface; wl_egl_window->resize_callback = (void *)__cb_client_window_resize_callback; + wl_egl_window->rotate_callback = (void *)__cb_client_window_rotate_callback; + wl_egl_window->get_rotation_capability = (void *)__cb_client_window_get_rotation_capability; /* tdm_vblank object decide to be maintained every tpl_wayland_egl_surface for the case where the several surfaces is created in one display connection. */ @@ -1212,6 +1224,41 @@ __cb_client_window_resize_callback(struct wl_egl_window *wl_egl_window, wayland_egl_surface->resized = TPL_TRUE; } +static void +__cb_client_window_rotate_callback(struct wl_egl_window *wl_egl_window, + void *private) +{ + TPL_ASSERT(private); + TPL_ASSERT(wl_egl_window); + + int rotation; + tpl_surface_t *surface = (tpl_surface_t *)private; + + rotation = wl_egl_window->rotation; + + TPL_LOG_B("WL_EGL", "[ROTATE_CB] wl_egl_window(%p) (%d) -> (%d)", + wl_egl_window, surface->rotation, rotation); + /* Check whether the surface was resized by wayland_egl */ + surface->rotation = rotation; +} + +static int +__cb_client_window_get_rotation_capability(struct wl_egl_window *wl_egl_window, + void *private) +{ + int rotation_capability = WL_EGL_WINDOW_CAPABILITY_NONE; + TPL_ASSERT(private); + TPL_ASSERT(wl_egl_window); + tpl_surface_t *surface = (tpl_surface_t *)private; + if (TPL_TRUE == surface->rotation_capability) + rotation_capability = WL_EGL_WINDOW_CAPABILITY_ROTATION_SUPPORTED; + else + rotation_capability = WL_EGL_WINDOW_CAPABILITY_ROTATION_UNSUPPORTED; + + return rotation_capability; +} + + void __cb_resistry_global_callback(void *data, struct wl_registry *wl_registry, uint32_t name, const char *interface, diff --git a/src/wayland-egl/wayland-egl-priv.h b/src/wayland-egl/wayland-egl-priv.h index da25be9..3c284fc 100644 --- a/src/wayland-egl/wayland-egl-priv.h +++ b/src/wayland-egl/wayland-egl-priv.h @@ -13,6 +13,7 @@ extern "C" { #endif #include +#include struct wl_egl_window { struct wl_surface *surface; @@ -25,8 +26,12 @@ struct wl_egl_window { int attached_width; int attached_height; + wl_egl_window_rotation rotation; + void *private; void (*resize_callback)(struct wl_egl_window *, void *); + void (*rotate_callback)(struct wl_egl_window *, void *); + int (*get_rotation_capability)(struct wl_egl_window *, void *); }; #ifdef __cplusplus diff --git a/src/wayland-egl/wayland-egl.c b/src/wayland-egl/wayland-egl.c index f577bcc..77e8e22 100644 --- a/src/wayland-egl/wayland-egl.c +++ b/src/wayland-egl/wayland-egl.c @@ -1,7 +1,6 @@ #include #include -#include "wayland-egl.h" #include "wayland-egl-priv.h" #define WL_EGL_DEBUG 1 @@ -98,6 +97,7 @@ wl_egl_window_create(struct wl_surface *surface, wl_egl_window_resize(egl_window, width, height, 0, 0); egl_window->attached_width = 0; egl_window->attached_height = 0; + egl_window->rotation = ROTATION_0; WL_EGL_LOG(2, "surf:%10p WxH:%dx%d egl_win:%10p priv:%10p", surface, width, height, egl_window, egl_window->private); @@ -131,3 +131,66 @@ wl_egl_window_get_attached_size(struct wl_egl_window *egl_window, egl_window, width, height, egl_window->attached_width, egl_window->attached_height); } + +WL_EGL_EXPORT void +wl_egl_window_set_rotation(struct wl_egl_window *egl_window, + wl_egl_window_rotation rotation) +{ + int resize = 0; + + if (egl_window == NULL) { + WL_EGL_ERR("egl_window is NULL"); + return; + } + + if (egl_window->rotation == rotation) { + WL_EGL_ERR("rotation value is same"); + return; + } + + switch (rotation) { + case ROTATION_0: + case ROTATION_180: + if (egl_window->rotation == ROTATION_90 || egl_window->rotation == ROTATION_270) + resize = 1; + break; + case ROTATION_90: + case ROTATION_270: + if (egl_window->rotation == ROTATION_0 || egl_window->rotation == ROTATION_180) + resize = 1; + break; + default: + WL_EGL_ERR("Invalid rotation value"); + return; + } + + WL_EGL_LOG(2, "egl_win:%10p prev_rotation:%d curr_rotation: %d", + egl_window, egl_window->rotation, rotation); + + egl_window->rotation = rotation; + + if (egl_window->rotate_callback) + egl_window->rotate_callback(egl_window, egl_window->private); + + if (resize) { + wl_egl_window_resize(egl_window, egl_window->height, egl_window->width, + egl_window->dx, egl_window->dy); + } +} + +WL_EGL_EXPORT int +wl_egl_window_get_capabilities(struct wl_egl_window *egl_window) +{ + int capabilities = WL_EGL_WINDOW_CAPABILITY_NONE; + if (egl_window == NULL) { + WL_EGL_ERR("egl_window is NULL"); + return capabilities; + } + + if (egl_window->get_rotation_capability) + capabilities = egl_window->get_rotation_capability(egl_window, egl_window->private); + else + capabilities = WL_EGL_WINDOW_CAPABILITY_ROTATION_UNKNOWN; + + return capabilities; +} -- 2.7.4 From 017b45802a3c241c0c1ac3dc2d1b5eb98d12f206 Mon Sep 17 00:00:00 2001 From: "deasung.kim" Date: Wed, 7 Dec 2016 12:04:33 +0900 Subject: [PATCH 06/16] wayland-vulkan: added wayland-vulkan protocol it need to server side present mode Change-Id: Ia12b36260c6651b4cf34c5ea222557a00b7ef2de --- src/wayland-vulkan/Makefile | 30 ++++++++++++++++++++++++++ src/wayland-vulkan/wayland-vulkan-protocol.xml | 17 +++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 src/wayland-vulkan/Makefile create mode 100644 src/wayland-vulkan/wayland-vulkan-protocol.xml diff --git a/src/wayland-vulkan/Makefile b/src/wayland-vulkan/Makefile new file mode 100644 index 0000000..8300a88 --- /dev/null +++ b/src/wayland-vulkan/Makefile @@ -0,0 +1,30 @@ +.SUFFIXES: .c .o .a + +CFLAGS += -Wall -fno-strict-aliasing -Wno-strict-aliasing -Wno-long-long -O3 -fPIC + +WAYLAND_VULKAN_PROTOCOLS = wayland-vulkan-protocol.xml + +wayland-vulkan-protocol.c : $(WAYLAND_VULKAN_PROTOCOLS) + wayland-scanner code < $< > $@ + +wayland-vulkan-server-protocol.h : $(WAYLAND_VULKAN_PROTOCOLS) + wayland-scanner server-header < $< > $@ + +wayland-vulkan-client-protocol.h : $(WAYLAND_VULKAN_PROTOCOLS) + wayland-scanner client-header < $< > $@ + +.PHONY: all clean client server +.DEFAULT_GOAL = all +all: client server + +client: wayland-vulkan-protocol.c wayland-vulkan-client-protocol.h + +server: wayland-vulkan-protocol.c wayland-vulkan-server-protocol.h + +clean: + rm -rf wayland-vulkan-protocol.c \ + wayland-vulkan-server-protocol.h \ + wayland-vulkan-client-protocol.h + +install: all + diff --git a/src/wayland-vulkan/wayland-vulkan-protocol.xml b/src/wayland-vulkan/wayland-vulkan-protocol.xml new file mode 100644 index 0000000..b4fe5dc --- /dev/null +++ b/src/wayland-vulkan/wayland-vulkan-protocol.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + -- 2.7.4 From 37db13d8742d812bdae8c1a45bd7b6883d7e0557 Mon Sep 17 00:00:00 2001 From: "deasung.kim" Date: Mon, 12 Dec 2016 13:42:31 +0900 Subject: [PATCH 07/16] tpl_tbm: added vulkan support funcs __tpl_tbm_display_query_window_supported_buffer_count : return min 0, max 0 (no limits) __tpl_tbm_display_query_window_supported_present_modes : return MAILBOX/IMMEDIATE (FIFO after apply worker) __tpl_tbm_surface_create_swapchain : just set present mode __tpl_tbm_surface_get_swapchain_buffers : same tpl_wayland_vk_wsi Change-Id: I99f3d3192cb835698a3534a8cc1a8ca851740b4b --- src/tpl_tbm.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) diff --git a/src/tpl_tbm.c b/src/tpl_tbm.c index cfdbd84..44c581e 100644 --- a/src/tpl_tbm.c +++ b/src/tpl_tbm.c @@ -19,6 +19,7 @@ struct _tpl_tbm_display { struct _tpl_tbm_surface { int dummy; + int present_mode; }; static tpl_result_t @@ -321,6 +322,102 @@ __tpl_tbm_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeout_ns, return tbm_surface; } +static tpl_result_t +__tpl_tbm_surface_get_swapchain_buffers(tpl_surface_t *surface, + tbm_surface_h **buffers, + int *buffer_count) +{ + tbm_surface_h buffer = NULL; + tbm_surface_queue_h tbm_queue = NULL; + tbm_surface_h *swapchain_buffers = NULL; + tbm_surface_queue_error_e tsq_err; + tpl_result_t ret = TPL_ERROR_NONE; + int i, queue_size, dequeue_count = 0; + + TPL_ASSERT(surface); + TPL_ASSERT(buffers); + TPL_ASSERT(buffer_count); + + tbm_queue = (tbm_surface_queue_h)surface->native_handle; + TPL_ASSERT(tbm_queue); + + queue_size = tbm_surface_queue_get_size(tbm_queue); + swapchain_buffers = (tbm_surface_h *)calloc(1, sizeof(tbm_surface_h) * queue_size); + if (!swapchain_buffers) { + TPL_ERR("Failed to allocate memory for buffers."); + return TPL_ERROR_OUT_OF_MEMORY; + } + + for (i = 0; i < queue_size; i++) { + tsq_err = tbm_surface_queue_dequeue(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); + dequeue_count = i; + ret = TPL_ERROR_OUT_OF_MEMORY; + goto get_buffer_fail; + } + swapchain_buffers[i] = buffer; + } + + for (i = 0 ; i < queue_size; i++) { + tsq_err = tbm_surface_queue_release(tbm_queue, swapchain_buffers[i]); + if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) { + TPL_ERR("Failed to release tbm_surface. | tsq_err = %d", tsq_err); + ret = TPL_ERROR_INVALID_OPERATION; + goto release_buffer_fail; + } + } + + *buffers = swapchain_buffers; + *buffer_count = queue_size; + return TPL_ERROR_NONE; + +get_buffer_fail: + for (i = 0 ; i < dequeue_count ; i++) { + tsq_err = tbm_surface_queue_release(tbm_queue, swapchain_buffers[i]); + if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) { + TPL_ERR("Failed to release tbm_surface. | tsq_err = %d", tsq_err); + goto release_buffer_fail; + } + } + +release_buffer_fail: + free(swapchain_buffers); + return ret; + +} + +static tpl_result_t +__tpl_tbm_surface_create_swapchain(tpl_surface_t *surface, + tbm_format format, int width, + int height, int buffer_count, int present_mode) +{ + tpl_tbm_surface_t *tpl_tbm_surface = NULL; + + TPL_ASSERT(surface); + + tpl_tbm_surface = (tpl_tbm_surface_t *) surface->backend.data; + TPL_ASSERT(tpl_tbm_surface); + + /* FIXME: vblank has performance problem so replace all present mode to MAILBOX */ + present_mode = TPL_DISPLAY_PRESENT_MODE_MAILBOX; + + /* TODO: check server supported present modes */ + switch (present_mode) { + case TPL_DISPLAY_PRESENT_MODE_MAILBOX: + case TPL_DISPLAY_PRESENT_MODE_IMMEDIATE: + break; + default: + TPL_ERR("Unsupported present mode: %d", present_mode); + return TPL_ERROR_INVALID_PARAMETER; + } + + tpl_tbm_surface->present_mode = present_mode; + + return TPL_ERROR_NONE; +} + tpl_bool_t __tpl_display_choose_backend_tbm(tpl_handle_t native_dpy) { @@ -338,6 +435,36 @@ __tpl_display_choose_backend_tbm(tpl_handle_t native_dpy) return ret; } +static tpl_result_t +__tpl_tbm_display_query_window_supported_buffer_count( + tpl_display_t *display, + tpl_handle_t window, int *min, int *max) +{ + TPL_ASSERT(display); + + if (!display->backend.data) return TPL_ERROR_INVALID_OPERATION; + + if (min) *min = 0; + if (max) *max = 0; /* 0 mean no limit in vulkan */ + + return TPL_ERROR_NONE; +} + +static tpl_result_t +__tpl_tbm_display_query_window_supported_present_modes( + tpl_display_t *display, + tpl_handle_t window, int *modes) +{ + TPL_ASSERT(display); + + if (!display->backend.data) return TPL_ERROR_INVALID_OPERATION; + + if (modes) + *modes = TPL_DISPLAY_PRESENT_MODE_MAILBOX | TPL_DISPLAY_PRESENT_MODE_IMMEDIATE; + + return TPL_ERROR_NONE; +} + void __tpl_display_init_backend_tbm(tpl_display_backend_t *backend) { @@ -354,6 +481,11 @@ __tpl_display_init_backend_tbm(tpl_display_backend_t *backend) backend->get_pixmap_info = __tpl_tbm_display_get_pixmap_info; backend->get_buffer_from_native_pixmap = __tpl_tbm_display_get_buffer_from_native_pixmap; + backend->query_window_supported_buffer_count = + __tpl_tbm_display_query_window_supported_buffer_count; + backend->query_window_supported_present_modes = + __tpl_tbm_display_query_window_supported_present_modes; + } void @@ -369,5 +501,8 @@ __tpl_surface_init_backend_tbm(tpl_surface_backend_t *backend) backend->validate = __tpl_tbm_surface_validate; backend->dequeue_buffer = __tpl_tbm_surface_dequeue_buffer; backend->enqueue_buffer = __tpl_tbm_surface_enqueue_buffer; + backend->create_swapchain = __tpl_tbm_surface_create_swapchain; + backend->get_swapchain_buffers = + __tpl_tbm_surface_get_swapchain_buffers; } -- 2.7.4 From 323c55bed8983f295e842ed9c41cda4d0e83ceeb Mon Sep 17 00:00:00 2001 From: "deasung.kim" Date: Mon, 12 Dec 2016 14:43:30 +0900 Subject: [PATCH 08/16] tpl_worker_thread: added new interface draw_wait_buffer_get if draw_wait_buffer_get is not NULL worker call that function to get draw wait buffer this patch for tpl_tbm Change-Id: I52d366615576bc5e1f0fbd6ab34c56a201de6c58 --- src/tpl_worker_thread.c | 31 ++++++++++++++++++++++++++++++- src/tpl_worker_thread.h | 1 + 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/tpl_worker_thread.c b/src/tpl_worker_thread.c index 7946e4f..60d01ee 100644 --- a/src/tpl_worker_thread.c +++ b/src/tpl_worker_thread.c @@ -41,7 +41,6 @@ void __tpl_worker_surface_list_insert(tpl_worker_surface_t *surface) { TPL_ASSERT(surface->surface); - TPL_ASSERT(surface->tbm_queue); if (pthread_mutex_lock(&tpl_worker_thread.surface_mutex) != 0) { TPL_ERR_ERRNO("surface list mutex lock failed"); @@ -94,6 +93,36 @@ __tpl_worker_prepare_draw_wait_buffer(int epoll_fd, if (surface->draw_wait_buffer) return; + if (surface->draw_wait_buffer_get) { + int wait_fd = -1; + tbm_surface_h tbm_surface; + + while ((tbm_surface = surface->draw_wait_buffer_get(surface->surface)) != NULL) { + if (surface->draw_wait_fd_get) + wait_fd = surface->draw_wait_fd_get(surface->surface, tbm_surface); + + if (wait_fd != -1) { + struct epoll_event wait_fence_event; + int epoll_err; + + wait_fence_event.events = EPOLLIN; + wait_fence_event.data.ptr = surface; + epoll_err = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, + wait_fd, + &wait_fence_event); + if (epoll_err == 0) { + surface->draw_wait_buffer = tbm_surface; + return; + } + } /* else can't(or not need) wait fence in poll */ + + if (surface->draw_done) + surface->draw_done(surface->surface, tbm_surface, + TPL_ERROR_INVALID_OPERATION); + } + return; + } + while (tbm_surface_queue_can_acquire(surface->tbm_queue, 0)) { tbm_surface_h tbm_surface = NULL; tbm_surface_queue_error_e tsq_err; diff --git a/src/tpl_worker_thread.h b/src/tpl_worker_thread.h index 5afa75b..f7562a9 100644 --- a/src/tpl_worker_thread.h +++ b/src/tpl_worker_thread.h @@ -17,6 +17,7 @@ struct __tpl_worker_surface { int (*draw_wait_fd_get)(tpl_surface_t *surface, tbm_surface_h tbm_surface); void (*vblank)(tpl_surface_t *surface, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec); + tbm_surface_h (*draw_wait_buffer_get)(tpl_surface_t *surface); tbm_surface_h draw_wait_buffer; }; -- 2.7.4 From fc0a372ba355f6f346ef13e6ba84f27ed65d1fa3 Mon Sep 17 00:00:00 2001 From: "deasung.kim" Date: Mon, 12 Dec 2016 14:45:33 +0900 Subject: [PATCH 09/16] tpl_tbm: implement worker thread interface tpl_enqueue_with_sync() -> wait sync in worker thread draw done -> insert vblank queue or tbm_surface_queue_enqueue() Change-Id: I09922f02bbccaa87c8630594e7f979f66e65c197 --- src/tpl_tbm.c | 361 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 328 insertions(+), 33 deletions(-) diff --git a/src/tpl_tbm.c b/src/tpl_tbm.c index 44c581e..56be0ef 100644 --- a/src/tpl_tbm.c +++ b/src/tpl_tbm.c @@ -9,8 +9,22 @@ #include #include +#define USE_WORKER_THREAD +#ifndef USE_WORKER_THREAD +#define USE_WORKER_THREAD 0 +#else +#include "tpl_worker_thread.h" +#include +#include +#undef USE_WORKER_THREAD +#define USE_WORKER_THREAD 1 +#endif + typedef struct _tpl_tbm_display tpl_tbm_display_t; typedef struct _tpl_tbm_surface tpl_tbm_surface_t; +#if USE_WORKER_THREAD == 1 +typedef struct _tpl_tbm_buffer tpl_tbm_buffer_t; +#endif struct _tpl_tbm_display { int need_dpy_deinit; @@ -18,10 +32,72 @@ struct _tpl_tbm_display { }; struct _tpl_tbm_surface { - int dummy; +#if USE_WORKER_THREAD == 1 + /* tbm_surface list */ + tpl_list_t vblank_list; + pthread_mutex_t vblank_list_mutex; + + tpl_list_t draw_waiting_queue; + pthread_mutex_t draw_waiting_mutex; + + tpl_bool_t vblank_done; + + tpl_worker_surface_t worker_surface; + + tpl_bool_t need_worker_clear; +#endif int present_mode; }; +#if USE_WORKER_THREAD == 1 +struct _tpl_tbm_buffer { + tbm_fd wait_sync; +}; + +static int tpl_tbm_buffer_key; +#define KEY_tpl_tbm_buffer (unsigned long)(&tpl_tbm_buffer_key) + +static void +__tpl_tbm_buffer_free(tpl_tbm_buffer_t *tbm_buffer) +{ + TPL_ASSERT(tbm_buffer); + if (tbm_buffer->wait_sync != -1) + close(tbm_buffer->wait_sync); + free(tbm_buffer); +} + +static void +__tpl_tbm_buffer_remove_from_list(void *data) +{ + tbm_surface_h tbm_surface = data; + tbm_surface_internal_unref(tbm_surface); +} + +static TPL_INLINE tpl_tbm_buffer_t * +__tpl_tbm_get_tbm_buffer_from_tbm_surface(tbm_surface_h surface) +{ + tpl_tbm_buffer_t *buf = NULL; + + if (!tbm_surface_internal_is_valid(surface)) + return NULL; + + tbm_surface_internal_get_user_data(surface, KEY_tpl_tbm_buffer, + (void **)&buf); + return buf; +} + +static TPL_INLINE void +__tpl_tbm_set_tbm_buffer_to_tbm_surface(tbm_surface_h surface, + tpl_tbm_buffer_t *buf) +{ + tbm_surface_internal_add_user_data(surface, + KEY_tpl_tbm_buffer, + (tbm_data_free)__tpl_tbm_buffer_free); + tbm_surface_internal_set_user_data(surface, + KEY_tpl_tbm_buffer, buf); +} +#endif + static tpl_result_t __tpl_tbm_display_init(tpl_display_t *display) { @@ -165,6 +241,202 @@ __tpl_tbm_surface_queue_notify_cb(tbm_surface_queue_h surface_queue, void *data) /* Do something */ } +#if USE_WORKER_THREAD == 1 +static void +__tpl_tbm_draw_done(tpl_surface_t *surface, tbm_surface_h tbm_surface, tpl_result_t result) +{ + tpl_tbm_surface_t *tpl_tbm_surface = NULL; + tpl_tbm_buffer_t *tpl_tbm_buffer = NULL; + tbm_surface_queue_h tbm_queue = NULL; + + TPL_ASSERT(surface); + TPL_ASSERT(tbm_surface); + TPL_ASSERT(tbm_surface_internal_is_valid(tbm_surface)); + + tpl_tbm_surface = (tpl_tbm_surface_t *)surface->backend.data; + tpl_tbm_buffer = __tpl_tbm_get_tbm_buffer_from_tbm_surface(tbm_surface); + tbm_queue = (tbm_surface_queue_h)surface->native_handle; + + TPL_ASSERT(tpl_tbm_surface); + TPL_ASSERT(tpl_tbm_buffer); + TPL_ASSERT(tbm_queue); + + close(tpl_tbm_buffer->wait_sync); + tpl_tbm_buffer->wait_sync = -1; + + /* if server supported current supported mode then just send */ + + if (tpl_tbm_surface->present_mode == TPL_DISPLAY_PRESENT_MODE_FIFO) { + pthread_mutex_lock(&tpl_tbm_surface->vblank_list_mutex); + /* unref in tpl list remove callback + (__tpl_tbm_buffer_remove_from_list) */ + tbm_surface_internal_ref(tbm_surface); + __tpl_list_push_back(&tpl_tbm_surface->vblank_list, tbm_surface); + pthread_mutex_unlock(&tpl_tbm_surface->vblank_list_mutex); + } else if (tpl_tbm_surface->present_mode == TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED && + tpl_tbm_surface->vblank_done == TPL_FALSE) { + /* if can't process previous vblank event, send buffer immediately */ + pthread_mutex_lock(&tpl_tbm_surface->vblank_list_mutex); + /* unref in tpl list remove callback + (__tpl_tbm_buffer_remove_from_list) */ + tbm_surface_internal_ref(tbm_surface); + __tpl_list_push_back(&tpl_tbm_surface->vblank_list, tbm_surface); + tpl_tbm_surface->vblank_done = TPL_TRUE; + pthread_mutex_unlock(&tpl_tbm_surface->vblank_list_mutex); + } else { + tbm_surface_internal_unref(tbm_surface); + if (tbm_surface_queue_enqueue(tbm_queue, tbm_surface) != TBM_SURFACE_QUEUE_ERROR_NONE) { + TPL_ERR("tbm_surface_queue_enqueue failed. tbm_queue(%p) tbm_surface(%p)", + tbm_queue, tbm_surface); + } + } +} + +static int +__tpl_tbm_draw_wait_fd_get(tpl_surface_t *surface, tbm_surface_h tbm_surface) +{ + tpl_tbm_buffer_t *tpl_tbm_buffer; + + TPL_ASSERT(tbm_surface); + TPL_ASSERT(tbm_surface_internal_is_valid(tbm_surface)); + + tpl_tbm_buffer = __tpl_tbm_get_tbm_buffer_from_tbm_surface(tbm_surface); + return tpl_tbm_buffer->wait_sync; +} + +static void +__tpl_tbm_vblank(tpl_surface_t *surface, unsigned int sequence, unsigned int tv_sec, + unsigned int tv_usec) +{ + tpl_tbm_surface_t *tpl_tbm_surface; + tbm_surface_h tbm_surface; + + TPL_ASSERT(surface); + + tpl_tbm_surface = (tpl_tbm_surface_t *)surface->backend.data; + + TPL_ASSERT(tpl_tbm_surface); + + if ((tpl_tbm_surface->present_mode & + (TPL_DISPLAY_PRESENT_MODE_FIFO | TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED)) == 0) + return; + + pthread_mutex_lock(&tpl_tbm_surface->vblank_list_mutex); + tbm_surface = __tpl_list_pop_front(&tpl_tbm_surface->vblank_list, + __tpl_tbm_buffer_remove_from_list); + pthread_mutex_unlock(&tpl_tbm_surface->vblank_list_mutex); + + if (tbm_surface_internal_is_valid(tbm_surface)) { + tbm_surface_queue_h tbm_queue = (tbm_surface_queue_h)surface->native_handle; + if (tbm_surface_queue_enqueue(tbm_queue, tbm_surface) != TBM_SURFACE_QUEUE_ERROR_NONE) { + TPL_ERR("tbm_surface_queue_enqueue failed. tbm_queue(%p) tbm_surface(%p)", + tbm_queue, tbm_surface); + } + tpl_tbm_surface->vblank_done = TPL_TRUE; + } else { + tpl_tbm_surface->vblank_done = TPL_FALSE; + } + +} + +static tbm_surface_h +__tpl_tbm_draw_wait_buffer_get(tpl_surface_t *surface) +{ + tpl_tbm_surface_t *tpl_tbm_surface; + tbm_surface_h tbm_surface; + + tpl_tbm_surface = surface->backend.data; + pthread_mutex_init(&tpl_tbm_surface->draw_waiting_mutex, NULL); + tbm_surface = __tpl_list_pop_front(&tpl_tbm_surface->draw_waiting_queue, NULL); + pthread_mutex_unlock(&tpl_tbm_surface->draw_waiting_mutex); + + return tbm_surface; +} +#endif + +static tpl_result_t +__tpl_tbm_surface_create_swapchain(tpl_surface_t *surface, + tbm_format format, int width, + int height, int buffer_count, int present_mode) +{ + tpl_tbm_surface_t *tpl_tbm_surface = NULL; + + TPL_ASSERT(surface); + + tpl_tbm_surface = (tpl_tbm_surface_t *) surface->backend.data; + TPL_ASSERT(tpl_tbm_surface); + + /* FIXME: vblank has performance problem so replace all present mode to MAILBOX */ + present_mode = TPL_DISPLAY_PRESENT_MODE_MAILBOX; + + /* TODO: check server supported present modes */ + switch (present_mode) { + case TPL_DISPLAY_PRESENT_MODE_MAILBOX: + case TPL_DISPLAY_PRESENT_MODE_IMMEDIATE: + break; +#if USE_WORKER_THREAD == 1 + case TPL_DISPLAY_PRESENT_MODE_FIFO: + case TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED: + if (__tpl_worker_support_vblank() == TPL_FALSE) { + TPL_ERR("Unsupported present mode: %d, worker not support vblank", + present_mode); + return TPL_ERROR_INVALID_PARAMETER; + } +#endif + default: + TPL_ERR("Unsupported present mode: %d", present_mode); + return TPL_ERROR_INVALID_PARAMETER; + } + + tpl_tbm_surface->present_mode = present_mode; + +#if USE_WORKER_THREAD == 1 + tpl_tbm_surface->worker_surface.surface = surface; + tpl_tbm_surface->worker_surface.draw_done = __tpl_tbm_draw_done; + tpl_tbm_surface->worker_surface.draw_wait_fd_get = __tpl_tbm_draw_wait_fd_get; + tpl_tbm_surface->worker_surface.vblank = __tpl_tbm_vblank; + tpl_tbm_surface->worker_surface.draw_wait_buffer_get = __tpl_tbm_draw_wait_buffer_get; + + __tpl_list_init(&tpl_tbm_surface->vblank_list); + __tpl_list_init(&tpl_tbm_surface->draw_waiting_queue); + pthread_mutex_init(&tpl_tbm_surface->vblank_list_mutex, NULL); + pthread_mutex_init(&tpl_tbm_surface->draw_waiting_mutex, NULL); + + __tpl_worker_surface_list_insert(&tpl_tbm_surface->worker_surface); + tpl_tbm_surface->need_worker_clear = TPL_TRUE; +#endif + + return TPL_ERROR_NONE; +} + +#if USE_WORKER_THREAD == 1 +static tpl_result_t +__tpl_tbm_surface_destroy_swapchain(tpl_surface_t *surface) +{ + tpl_tbm_surface_t *tpl_tbm_surface = NULL; + + TPL_ASSERT(surface); + + tpl_tbm_surface = (tpl_tbm_surface_t *) surface->backend.data; + TPL_ASSERT(tpl_tbm_surface); + + __tpl_worker_surface_list_remove(&tpl_tbm_surface->worker_surface); + + pthread_mutex_lock(&tpl_tbm_surface->vblank_list_mutex); + __tpl_list_fini(&tpl_tbm_surface->vblank_list, NULL); + pthread_mutex_unlock(&tpl_tbm_surface->vblank_list_mutex); + pthread_mutex_destroy(&tpl_tbm_surface->vblank_list_mutex); + + pthread_mutex_lock(&tpl_tbm_surface->draw_waiting_mutex); + __tpl_list_fini(&tpl_tbm_surface->draw_waiting_queue, NULL); + pthread_mutex_unlock(&tpl_tbm_surface->draw_waiting_mutex); + pthread_mutex_destroy(&tpl_tbm_surface->draw_waiting_mutex); + tpl_tbm_surface->need_worker_clear = TPL_FALSE; + + return TPL_ERROR_NONE; +} +#endif + static tpl_result_t __tpl_tbm_surface_init(tpl_surface_t *surface) { @@ -218,6 +490,18 @@ error: static void __tpl_tbm_surface_fini(tpl_surface_t *surface) { +#if USE_WORKER_THREAD == 1 + tpl_tbm_surface_t *tpl_tbm_surface = NULL; + + TPL_ASSERT(surface); + + tpl_tbm_surface = (tpl_tbm_surface_t *) surface->backend.data; + TPL_ASSERT(tpl_tbm_surface); + + if (tpl_tbm_surface->need_worker_clear) + __tpl_tbm_surface_destroy_swapchain(surface); +#endif + TPL_ASSERT(surface); TPL_ASSERT(surface->display); @@ -237,6 +521,13 @@ __tpl_tbm_surface_enqueue_buffer(tpl_surface_t *surface, tbm_surface_h tbm_surface, int num_rects, const int *rects, tbm_fd sync_fence) { +#if USE_WORKER_THREAD == 1 + tpl_tbm_surface_t *tpl_tbm_surface = NULL; + tpl_tbm_buffer_t *tpl_tbm_buffer = NULL; +#else + tbm_surface_queue_h tbm_queue; +#endif + TPL_ASSERT(surface); TPL_ASSERT(surface->display); TPL_ASSERT(surface->display->native_handle); @@ -256,8 +547,19 @@ __tpl_tbm_surface_enqueue_buffer(tpl_surface_t *surface, surface->native_handle); return TPL_ERROR_INVALID_PARAMETER; } +#if USE_WORKER_THREAD == 1 + tpl_tbm_surface = surface->backend.data; - tbm_surface_queue_h tbm_queue = (tbm_surface_queue_h)surface->native_handle; + tpl_tbm_buffer = __tpl_tbm_get_tbm_buffer_from_tbm_surface(tbm_surface); + tpl_tbm_buffer->wait_sync = sync_fence; + + tbm_surface_internal_ref(tbm_surface); + pthread_mutex_init(&tpl_tbm_surface->draw_waiting_mutex, NULL); + __tpl_list_push_back(&tpl_tbm_surface->draw_waiting_queue, tbm_surface); + pthread_mutex_unlock(&tpl_tbm_surface->draw_waiting_mutex); + __tpl_worker_new_buffer_notify(&tpl_tbm_surface->worker_surface); +#else + tbm_queue = (tbm_surface_queue_h)surface->native_handle; if (!tbm_queue) { TPL_ERR("tbm_surface_queue is invalid."); @@ -275,6 +577,7 @@ __tpl_tbm_surface_enqueue_buffer(tpl_surface_t *surface, tbm_queue, tbm_surface); return TPL_ERROR_INVALID_OPERATION; } +#endif return TPL_ERROR_NONE; } @@ -294,6 +597,9 @@ __tpl_tbm_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeout_ns, tbm_surface_h tbm_surface = NULL; tbm_surface_queue_h tbm_queue = NULL; tbm_surface_queue_error_e tsq_err = 0; +#if USE_WORKER_THREAD == 1 + tpl_tbm_buffer_t *tpl_tbm_buffer = NULL; +#endif TPL_ASSERT(surface); TPL_ASSERT(surface->native_handle); @@ -315,6 +621,16 @@ __tpl_tbm_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeout_ns, } } +#if USE_WORKER_THREAD == 1 + if ((tpl_tbm_buffer =__tpl_tbm_get_tbm_buffer_from_tbm_surface(tbm_surface)) == NULL) { + tpl_tbm_buffer = (tpl_tbm_buffer_t *) calloc(1, sizeof(tpl_tbm_buffer_t)); + if (!tpl_tbm_buffer) { + TPL_ERR("Mem alloc for tpl_tbm_buffer failed!"); + return NULL; + } + } +#endif + /* Inc ref count about tbm_surface */ /* It will be dec when before tbm_surface_queue_enqueue called */ tbm_surface_internal_ref(tbm_surface); @@ -388,36 +704,6 @@ release_buffer_fail: } -static tpl_result_t -__tpl_tbm_surface_create_swapchain(tpl_surface_t *surface, - tbm_format format, int width, - int height, int buffer_count, int present_mode) -{ - tpl_tbm_surface_t *tpl_tbm_surface = NULL; - - TPL_ASSERT(surface); - - tpl_tbm_surface = (tpl_tbm_surface_t *) surface->backend.data; - TPL_ASSERT(tpl_tbm_surface); - - /* FIXME: vblank has performance problem so replace all present mode to MAILBOX */ - present_mode = TPL_DISPLAY_PRESENT_MODE_MAILBOX; - - /* TODO: check server supported present modes */ - switch (present_mode) { - case TPL_DISPLAY_PRESENT_MODE_MAILBOX: - case TPL_DISPLAY_PRESENT_MODE_IMMEDIATE: - break; - default: - TPL_ERR("Unsupported present mode: %d", present_mode); - return TPL_ERROR_INVALID_PARAMETER; - } - - tpl_tbm_surface->present_mode = present_mode; - - return TPL_ERROR_NONE; -} - tpl_bool_t __tpl_display_choose_backend_tbm(tpl_handle_t native_dpy) { @@ -459,8 +745,14 @@ __tpl_tbm_display_query_window_supported_present_modes( if (!display->backend.data) return TPL_ERROR_INVALID_OPERATION; - if (modes) + if (modes) { *modes = TPL_DISPLAY_PRESENT_MODE_MAILBOX | TPL_DISPLAY_PRESENT_MODE_IMMEDIATE; +#if USE_WORKER_THREAD == 1 + if (__tpl_worker_support_vblank() == TPL_TRUE) + *modes |= TPL_DISPLAY_PRESENT_MODE_FIFO | TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED; +#endif + } + return TPL_ERROR_NONE; } @@ -502,6 +794,9 @@ __tpl_surface_init_backend_tbm(tpl_surface_backend_t *backend) backend->dequeue_buffer = __tpl_tbm_surface_dequeue_buffer; backend->enqueue_buffer = __tpl_tbm_surface_enqueue_buffer; backend->create_swapchain = __tpl_tbm_surface_create_swapchain; +#if USE_WORKER_THREAD == 1 + backend->destroy_swapchain = __tpl_tbm_surface_destroy_swapchain; +#endif backend->get_swapchain_buffers = __tpl_tbm_surface_get_swapchain_buffers; } -- 2.7.4 From fe7299d1f6f0d7685ef59722a076b55343527db7 Mon Sep 17 00:00:00 2001 From: YoungJun Cho Date: Wed, 21 Dec 2016 14:02:34 +0900 Subject: [PATCH 10/16] tpl_tbm: clean up __tpl_tbm_surface_fini() This patch cleans up __tpl_tbm_surface_fini(). For surface->type is TPL_SURFACE_TYPE_WINDOW, the added destroy callback should be removed. Change-Id: Ied7564b611bdddd1c606347190244d28f4cd1bac Signed-off-by: YoungJun Cho --- src/tpl_tbm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/tpl_tbm.c b/src/tpl_tbm.c index cfdbd84..e5e43d5 100644 --- a/src/tpl_tbm.c +++ b/src/tpl_tbm.c @@ -222,8 +222,10 @@ __tpl_tbm_surface_fini(tpl_surface_t *surface) if (surface->type == TPL_SURFACE_TYPE_PIXMAP) tbm_surface_internal_unref((tbm_surface_h)surface->native_handle); - - if (surface->type == TPL_SURFACE_TYPE_WINDOW) { + else if (surface->type == TPL_SURFACE_TYPE_WINDOW) { + tbm_surface_queue_remove_destroy_cb( + (tbm_surface_queue_h)surface->native_handle, + __tpl_tbm_surface_queue_notify_cb, surface); /*TODO: we need fix for dequeued surface*/ } -- 2.7.4 From 45e6975c6343e5983ef0690a836cd7d0bef00a01 Mon Sep 17 00:00:00 2001 From: "deasung.kim" Date: Wed, 7 Dec 2016 12:06:03 +0900 Subject: [PATCH 11/16] tpl_wayland_vk_wsi: apply wayland-vulkan protocol get from server supproted present mode send client's present mode to server if client's present mode supported by server send buffer after draw done (not handle present mode in client) Change-Id: Icd4ab09dfdc84e6e98cf8e7c09ab3a2f502b4583 --- Makefile | 1 + packaging/libtpl-egl.spec | 12 +++++ src/tpl_wayland_vk_wsi.c | 120 +++++++++++++++++++++++++++++++++++++++------- 3 files changed, 116 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index a755695..b1f040e 100644 --- a/Makefile +++ b/Makefile @@ -76,6 +76,7 @@ TPL_SRCS += $(SRC_DIR)/tpl_wayland_vk_wsi.c TPL_SRCS += $(SRC_DIR)/tpl_gbm.c TPL_SRCS += $(SRC_DIR)/protocol/tizen-surface-protocol.c TPL_SRCS += $(SRC_DIR)/tpl_worker_thread.c +TPL_SRCS += $(SRC_DIR)/wayland-vulkan/wayland-vulkan-protocol.c endif ifneq ($(call is-feature-enabled,winsys_dri2),) diff --git a/packaging/libtpl-egl.spec b/packaging/libtpl-egl.spec index eedabda..fabb59a 100644 --- a/packaging/libtpl-egl.spec +++ b/packaging/libtpl-egl.spec @@ -162,6 +162,13 @@ export TPL_VER_MAJOR=%{TPL_VER_MAJOR} export TPL_VER_MINOR=%{TPL_VER_MINOR} export TPL_RELEASE=%{TPL_RELEASE} +#wayland-vulkan build +%if "%{TPL_WINSYS}" == "WL" +cd src/wayland-vulkan +make +cd - +%endif + make all #libwayland-egl build @@ -207,6 +214,11 @@ cp libwayland-egl.so.%{WL_EGL_VERSION} %{buildroot}%{_libdir}/libwayland-egl.so. cp -a %{_builddir}/%{buildsubdir}/COPYING %{buildroot}/%{TZ_SYS_RO_SHARE}/license/libwayland-egl export WLD_EGL_SO_VER=%{WL_EGL_VERSION} %makeinstall +cd - + +cd src/wayland-vulkan +%makeinstall +cd - %endif %post -p /sbin/ldconfig diff --git a/src/tpl_wayland_vk_wsi.c b/src/tpl_wayland_vk_wsi.c index a305762..136ab83 100644 --- a/src/tpl_wayland_vk_wsi.c +++ b/src/tpl_wayland_vk_wsi.c @@ -11,6 +11,8 @@ #include +#include "wayland-vulkan/wayland-vulkan-client-protocol.h" + #define CLIENT_QUEUE_SIZE 3 #define USE_WORKER_THREAD @@ -33,7 +35,9 @@ struct _tpl_wayland_vk_wsi_display { struct { int min_buffer; int max_buffer; + int present_modes; } surface_capabilities; + struct wayland_vulkan *wl_vk_client; }; struct _tpl_wayland_vk_wsi_surface { @@ -153,6 +157,56 @@ __tpl_wayland_vk_wsi_display_roundtrip(tpl_display_t *display) return ret; } +static void +__tpl_wayland_vk_wsi_support_present_mode_listener(void *data, + struct wayland_vulkan *wayland_vulkan, + uint32_t mode) +{ + tpl_wayland_vk_wsi_display_t *wayland_vk_wsi_display = data; + + switch (mode) { + case WAYLAND_VULKAN_PRESENT_MODE_TYPE_IMMEDIATE: + wayland_vk_wsi_display->surface_capabilities.present_modes + |= TPL_DISPLAY_PRESENT_MODE_IMMEDIATE; + break; + case WAYLAND_VULKAN_PRESENT_MODE_TYPE_MAILBOX: + wayland_vk_wsi_display->surface_capabilities.present_modes + |= TPL_DISPLAY_PRESENT_MODE_MAILBOX; + break; + case WAYLAND_VULKAN_PRESENT_MODE_TYPE_FIFO: + wayland_vk_wsi_display->surface_capabilities.present_modes + |= TPL_DISPLAY_PRESENT_MODE_FIFO; + break; + case WAYLAND_VULKAN_PRESENT_MODE_TYPE_FIFO_RELAXED: + wayland_vk_wsi_display->surface_capabilities.present_modes + |= TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED; + break; + default: + TPL_WARN("server sent unknown present type: %d", mode); + } +} + +static struct wayland_vulkan_listener wl_vk_listener = { + __tpl_wayland_vk_wsi_support_present_mode_listener, +}; + +static void +__tpl_wayland_vk_wsi_registry_handle_global(void *data, struct wl_registry *registry, + uint32_t name, const char *interface, uint32_t version) +{ + tpl_wayland_vk_wsi_display_t *wayland_vk_wsi_display = data; + + if (!strcmp(interface, "wayland_vulkan")) { + wayland_vk_wsi_display->wl_vk_client = + wl_registry_bind(registry, name, &wayland_vulkan_interface, version); + } +} + +static const struct wl_registry_listener registry_listener = { + __tpl_wayland_vk_wsi_registry_handle_global, + NULL +}; + static tpl_result_t __tpl_wayland_vk_wsi_display_init(tpl_display_t *display) { @@ -175,12 +229,16 @@ __tpl_wayland_vk_wsi_display_init(tpl_display_t *display) wayland_vk_wsi_display->surface_capabilities.min_buffer = 2; wayland_vk_wsi_display->surface_capabilities.max_buffer = CLIENT_QUEUE_SIZE; + wayland_vk_wsi_display->surface_capabilities.present_modes = + TPL_DISPLAY_PRESENT_MODE_MAILBOX; 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; + struct wl_registry *wl_registry; + wayland_vk_wsi_display->wl_tbm_client = wayland_tbm_client_init((struct wl_display *) wl_dpy); @@ -188,6 +246,18 @@ __tpl_wayland_vk_wsi_display_init(tpl_display_t *display) TPL_ERR("Wayland TBM initialization failed!"); goto free_wl_display; } + + wl_registry = wl_display_get_registry(wl_dpy); + /* check wl_registry */ + wl_registry_add_listener(wl_registry, ®istry_listener, wayland_vk_wsi_display); + wl_display_roundtrip(wl_dpy); + + if (wayland_vk_wsi_display->wl_vk_client) + wayland_vulkan_add_listener(wayland_vk_wsi_display->wl_vk_client, + &wl_vk_listener, wayland_vk_wsi_display); + + wl_display_roundtrip(wl_dpy); + wl_registry_destroy(wl_registry); } else { goto free_wl_display; } @@ -212,6 +282,8 @@ __tpl_wayland_vk_wsi_display_fini(tpl_display_t *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); + if (wayland_vk_wsi_display->wl_vk_client) + wayland_vulkan_destroy(wayland_vk_wsi_display->wl_vk_client); free(wayland_vk_wsi_display); } display->backend.data = NULL; @@ -292,7 +364,8 @@ __tpl_wayland_vk_wsi_display_query_window_supported_present_modes( if (!wayland_vk_wsi_display) return TPL_ERROR_INVALID_OPERATION; if (modes) { - *modes = TPL_DISPLAY_PRESENT_MODE_MAILBOX | TPL_DISPLAY_PRESENT_MODE_IMMEDIATE; + *modes = TPL_DISPLAY_PRESENT_MODE_MAILBOX | TPL_DISPLAY_PRESENT_MODE_IMMEDIATE | + wayland_vk_wsi_display->surface_capabilities.present_modes; #if USE_WORKER_THREAD == 1 if (__tpl_worker_support_vblank() == TPL_TRUE) *modes |= TPL_DISPLAY_PRESENT_MODE_FIFO | TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED; @@ -709,6 +782,7 @@ __tpl_wayland_vk_wsi_process_draw_done(tpl_surface_t *surface, { tpl_wayland_vk_wsi_surface_t *wayland_vk_wsi_surface = NULL; tpl_wayland_vk_wsi_buffer_t *wayland_vk_wsi_buffer = NULL; + tpl_wayland_vk_wsi_display_t *wayland_vk_wsi_display = NULL; TPL_ASSERT(surface); TPL_ASSERT(tbm_surface); @@ -718,15 +792,24 @@ __tpl_wayland_vk_wsi_process_draw_done(tpl_surface_t *surface, (tpl_wayland_vk_wsi_surface_t *)surface->backend.data; wayland_vk_wsi_buffer = __tpl_wayland_vk_wsi_get_wayland_buffer_from_tbm_surface(tbm_surface); + wayland_vk_wsi_display = (tpl_wayland_vk_wsi_display_t *) + surface->display->backend.data; TPL_ASSERT(wayland_vk_wsi_surface); TPL_ASSERT(wayland_vk_wsi_buffer); - - /* TODO: send buffer to server immediate when server support present mode */ + TPL_ASSERT(wayland_vk_wsi_display); close(wayland_vk_wsi_buffer->wait_sync); wayland_vk_wsi_buffer->wait_sync = -1; + /* if server supported current supported mode then just send */ + + if (wayland_vk_wsi_surface->present_mode & + wayland_vk_wsi_display->surface_capabilities.present_modes) { + __tpl_wayland_vk_wsi_surface_commit_buffer(surface, tbm_surface); + return; + } + if (wayland_vk_wsi_surface->present_mode == TPL_DISPLAY_PRESENT_MODE_FIFO) { pthread_mutex_lock(&wayland_vk_wsi_surface->vblank_list_mutex); /* unref in tpl list remove callback @@ -833,22 +916,25 @@ __tpl_wayland_vk_wsi_surface_create_swapchain(tpl_surface_t *surface, /* FIXME: vblank has performance problem so replace all present mode to MAILBOX */ present_mode = TPL_DISPLAY_PRESENT_MODE_MAILBOX; - /* TODO: check server supported present modes */ - switch (present_mode) { + if ((present_mode & wayland_vk_wsi_display->surface_capabilities.present_modes) == 0) { + /* server not supported current mode check client mode */ + switch (present_mode) { #if USE_WORKER_THREAD == 1 - case TPL_DISPLAY_PRESENT_MODE_FIFO: - case TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED: - if (__tpl_worker_support_vblank() == TPL_FALSE) { - TPL_ERR("Unsupported present mode: %d, worker not support vblank", present_mode); - return TPL_ERROR_INVALID_PARAMETER; - } + case TPL_DISPLAY_PRESENT_MODE_FIFO: + case TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED: + if (__tpl_worker_support_vblank() == TPL_FALSE) { + TPL_ERR("Unsupported present mode: %d, worker not support vblank", + present_mode); + return TPL_ERROR_INVALID_PARAMETER; + } #endif - case TPL_DISPLAY_PRESENT_MODE_MAILBOX: - case TPL_DISPLAY_PRESENT_MODE_IMMEDIATE: - break; - default: - TPL_ERR("Unsupported present mode: %d", present_mode); - return TPL_ERROR_INVALID_PARAMETER; + case TPL_DISPLAY_PRESENT_MODE_MAILBOX: + case TPL_DISPLAY_PRESENT_MODE_IMMEDIATE: + break; + default: + TPL_ERR("Unsupported present mode: %d", present_mode); + return TPL_ERROR_INVALID_PARAMETER; + } } wayland_vk_wsi_surface->present_mode = present_mode; -- 2.7.4 From c6b5e3584a11af18250e7b0cf5214a33500d6f70 Mon Sep 17 00:00:00 2001 From: YoungJun Cho Date: Fri, 2 Dec 2016 14:17:08 +0900 Subject: [PATCH 12/16] tpl_display: modify return value of tpl_display_create() when it is already existed This patch modifies return value of tpl_display_create() when it is already existed. Change-Id: Icd9a73b5cf03d284fd20f42edeebf86eebc80799 Signed-off-by: YoungJun Cho --- src/tpl_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tpl_display.c b/src/tpl_display.c index b58da59..d78f67a 100644 --- a/src/tpl_display.c +++ b/src/tpl_display.c @@ -30,8 +30,8 @@ tpl_display_create(tpl_backend_type_t type, tpl_handle_t native_dpy) /* Search for an already connected display for the given native display. */ display = __tpl_runtime_find_display(type, native_dpy); - /* If tpl_display already exists, then return NULL */ - TPL_CHECK_ON_TRUE_RETURN_VAL(display, NULL); + /* If tpl_display already exists, then return it */ + TPL_CHECK_ON_TRUE_RETURN_VAL(display, display); /* if backend is unknown, try to find the best match from the list of supported types */ if (TPL_BACKEND_UNKNOWN == type) -- 2.7.4 From 9d0dd2c0fee1f986913232a3c12b76bb773439b8 Mon Sep 17 00:00:00 2001 From: YoungJun Cho Date: Tue, 13 Dec 2016 17:11:41 +0900 Subject: [PATCH 13/16] wayland-egl: clean up wl_egl_window_create() This patch cleans up wl_egl_window_create(). Some callbacks are also initialized. Change-Id: I3361d02299287af0313ed96371ea61c8984fb964 Signed-off-by: YoungJun Cho --- src/wayland-egl/wayland-egl.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/wayland-egl/wayland-egl.c b/src/wayland-egl/wayland-egl.c index 77e8e22..1034539 100644 --- a/src/wayland-egl/wayland-egl.c +++ b/src/wayland-egl/wayland-egl.c @@ -78,29 +78,37 @@ wl_egl_window_resize(struct wl_egl_window *egl_window, WL_EGL_EXPORT struct wl_egl_window * wl_egl_window_create(struct wl_surface *surface, - int width, int height) + int width, int height) { struct wl_egl_window *egl_window; - if (width <= 0 || height <= 0) return NULL; - if (!surface) return NULL; + if (width <= 0 || height <= 0) + return NULL; + if (!surface) + return NULL; - egl_window = malloc(sizeof * egl_window); + egl_window = malloc(sizeof *egl_window); if (!egl_window) { WL_EGL_ERR("failed to allocate memory for egl_window"); return NULL; } egl_window->surface = surface; - egl_window->private = NULL; + egl_window->resize_callback = NULL; wl_egl_window_resize(egl_window, width, height, 0, 0); + egl_window->attached_width = 0; egl_window->attached_height = 0; + egl_window->rotation = ROTATION_0; + egl_window->private = NULL; + egl_window->rotate_callback = NULL; + egl_window->get_rotation_capability = NULL; + WL_EGL_LOG(2, "surf:%10p WxH:%dx%d egl_win:%10p priv:%10p", - surface, width, height, egl_window, egl_window->private); + surface, width, height, egl_window, egl_window->private); return egl_window; } -- 2.7.4 From 746724642f44c339c2da73c07ef7a11977be5c34 Mon Sep 17 00:00:00 2001 From: YoungJun Cho Date: Tue, 13 Dec 2016 17:09:56 +0900 Subject: [PATCH 14/16] tpl_wayland_egl: clean up __cb_client_window_resize_callback() This patch cleans up __cb_client_window_resize_callback(). It seems to be better to call tbm_surface_queue_get_width/height APIs once. Change-Id: Ib5668f472c8fffdeca020317b265cb491538e45c Signed-off-by: YoungJun Cho --- src/tpl_wayland_egl.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index 2b89173..adf21f3 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -1199,28 +1199,26 @@ static const struct wl_buffer_listener buffer_release_listener = { static void __cb_client_window_resize_callback(struct wl_egl_window *wl_egl_window, - void *private) + void *private) { TPL_ASSERT(private); TPL_ASSERT(wl_egl_window); - int width, height; + int cur_w, cur_h, req_w, req_h; tpl_surface_t *surface = (tpl_surface_t *)private; - tpl_wayland_egl_surface_t *wayland_egl_surface = (tpl_wayland_egl_surface_t *) - surface->backend.data; + 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; + cur_w = tbm_surface_queue_get_width(wayland_egl_surface->tbm_queue); + cur_h = tbm_surface_queue_get_height(wayland_egl_surface->tbm_queue); + req_w = wl_egl_window->width; + req_h = wl_egl_window->height; TPL_LOG_B("WL_EGL", "[RESIZE_CB] wl_egl_window(%p) (%dx%d) -> (%dx%d)", - wl_egl_window, - tbm_surface_queue_get_width(wayland_egl_surface->tbm_queue), - tbm_surface_queue_get_height(wayland_egl_surface->tbm_queue), - width, - height); + wl_egl_window, cur_w, cur_h, req_w, req_h); + /* Check whether the surface was resized by wayland_egl */ - if ((width != tbm_surface_queue_get_width(wayland_egl_surface->tbm_queue)) - || (height != tbm_surface_queue_get_height(wayland_egl_surface->tbm_queue))) + if ((req_w != cur_w) || (req_h != cur_h)) wayland_egl_surface->resized = TPL_TRUE; } -- 2.7.4 From ab2f2d093d0b35c500f61383a4959832e705c404 Mon Sep 17 00:00:00 2001 From: YoungJun Cho Date: Wed, 21 Dec 2016 15:19:07 +0900 Subject: [PATCH 15/16] tpl_wayland_egl: clean up __tpl_wayland_egl_surface_init() This patch cleans up __tpl_wayland_egl_surface_init(). There are som omitted error routines. Change-Id: I781a89b1f685d2586bbd03eebf028d4c4b8fba6e Signed-off-by: YoungJun Cho --- src/tpl_wayland_egl.c | 68 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index adf21f3..5dea7ed 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -115,9 +115,8 @@ __tpl_wayland_egl_display_is_wl_display(tpl_handle_t 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 ) { + 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) { @@ -495,8 +494,7 @@ __tpl_wayland_egl_surface_init(tpl_surface_t *surface) if (__tpl_object_init(&wayland_egl_surface->base, TPL_OBJECT_SURFACE, NULL) != TPL_ERROR_NONE) { TPL_ERR("Failed to initialize backend surface's base class!"); - free(wayland_egl_surface); - return TPL_ERROR_INVALID_OPERATION; + goto tpl_object_init_fail; } surface->backend.data = (void *)wayland_egl_surface; @@ -507,13 +505,15 @@ __tpl_wayland_egl_surface_init(tpl_surface_t *surface) wayland_egl_surface->current_buffer = NULL; wayland_egl_surface->attached_buffers = __tpl_list_alloc(); + if (!wayland_egl_surface->attached_buffers) { + TPL_ERR("Failed to allocate attached buffers tracking lists."); + goto alloc_attached_buffers_fail; + } + wayland_egl_surface->dequeued_buffers = __tpl_list_alloc(); - if (!wayland_egl_surface->attached_buffers - || !wayland_egl_surface->dequeued_buffers) { - TPL_ERR("Failed to allocate tracking lists."); - free(wayland_egl_surface); - surface->backend.data = NULL; - return TPL_ERROR_INVALID_OPERATION; + if (!wayland_egl_surface->dequeued_buffers) { + TPL_ERR("Failed to allocate dequeue buffers tracking lists."); + goto alloc_dequeue_buffers_fail; } if (wl_egl_window->surface) { @@ -535,15 +535,16 @@ __tpl_wayland_egl_surface_init(tpl_surface_t *surface) if (!wayland_egl_surface->tbm_queue) { TPL_ERR("TBM surface queue creation failed!"); - free(wayland_egl_surface); - surface->backend.data = NULL; - return TPL_ERROR_INVALID_OPERATION; + goto queue_create_fail; } /* Set reset_callback to tbm_queue */ - tbm_surface_queue_add_reset_cb(wayland_egl_surface->tbm_queue, - __cb_tbm_surface_queue_reset_callback, - (void *)surface); + if (tbm_surface_queue_add_reset_cb(wayland_egl_surface->tbm_queue, + __cb_tbm_surface_queue_reset_callback, + (void *)surface)) { + TPL_ERR("TBM surface queue add reset cb failed!"); + goto add_reset_cb_fail; + } surface->width = wl_egl_window->width; surface->height = wl_egl_window->height; @@ -553,18 +554,17 @@ __tpl_wayland_egl_surface_init(tpl_surface_t *surface) wl_egl_window->private = surface; wl_egl_window->resize_callback = (void *)__cb_client_window_resize_callback; wl_egl_window->rotate_callback = (void *)__cb_client_window_rotate_callback; - wl_egl_window->get_rotation_capability = (void *)__cb_client_window_get_rotation_capability; + wl_egl_window->get_rotation_capability = (void *) + __cb_client_window_get_rotation_capability; /* tdm_vblank object decide to be maintained every tpl_wayland_egl_surface for the case where the several surfaces is created in one display connection. */ if (wayland_egl_display->tdm_client) { if (TPL_ERROR_NONE != __tpl_wayland_egl_surface_create_vblank( - wayland_egl_surface, - wayland_egl_display->tdm_client)) { - tbm_surface_queue_destroy(wayland_egl_surface->tbm_queue); - free(wayland_egl_surface); - surface->backend.data = NULL; - return TPL_ERROR_INVALID_OPERATION; + wayland_egl_surface, + wayland_egl_display->tdm_client)) { + TPL_ERR("TBM surface create vblank failed!"); + goto create_vblank_fail; } } @@ -579,6 +579,23 @@ __tpl_wayland_egl_surface_init(tpl_surface_t *surface) wayland_egl_surface, wl_egl_window, surface->width, surface->height); return TPL_ERROR_NONE; + +create_vblank_fail: + tbm_surface_queue_remove_reset_cb(wayland_egl_surface->tbm_queue, + __cb_tbm_surface_queue_reset_callback, + (void *)surface); +add_reset_cb_fail: + tbm_surface_queue_destroy(wayland_egl_surface->tbm_queue); +queue_create_fail: + __tpl_list_free(wayland_egl_surface->attached_buffers, NULL); +alloc_dequeue_buffers_fail: + __tpl_list_free(wayland_egl_surface->dequeued_buffers, NULL); +alloc_attached_buffers_fail: + __tpl_object_fini(&wayland_egl_surface->base); +tpl_object_init_fail: + free(wayland_egl_surface); + surface->backend.data = NULL; + return TPL_ERROR_INVALID_OPERATION; } static void @@ -764,7 +781,7 @@ __tpl_wayland_egl_surface_commit(tpl_surface_t *surface, if (tdm_err == TDM_ERROR_NONE) wayland_egl_surface->vblank_done = TPL_FALSE; else - TPL_ERR ("Failed to tdm_client_wait_vblank. error:%d", tdm_err); + TPL_ERR("Failed to tdm_client_wait_vblank. error:%d", tdm_err); } TRACE_ASYNC_BEGIN((int)tbm_surface, "[COMMIT ~ RELEASE_CB] BO_NAME:%d", @@ -802,9 +819,8 @@ __tpl_wayland_egl_surface_enqueue_buffer(tpl_surface_t *surface, wayland_egl_surface, wayland_egl_surface->tbm_queue, tbm_surface, tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); - if (wayland_egl_surface->vblank_done == TPL_FALSE) { + if (wayland_egl_surface->vblank_done == TPL_FALSE) __tpl_wayland_egl_surface_wait_vblank(surface); - } if (sync_fence != -1) { tbm_sync_fence_wait(sync_fence, -1); -- 2.7.4 From 3920ae0d142cfca913374c9682b9073e8c0b3e2e Mon Sep 17 00:00:00 2001 From: "Mun, Gwan-gyeong" Date: Fri, 30 Dec 2016 09:47:55 +0900 Subject: [PATCH 16/16] tpl_wayland_egl: When wl_display_dispatch_queue() fails, print infomation of error in detail on __tpl_wayland_egl_surface_wait_dequeuable() When the wl_display_dispatch_queue() fails on __tpl_wayland_egl_surface_wait_dequeuable(), it generally prints errno and errno_str. If errno is EPROTO, it prints error interface name and error enumeration code. Change-Id: I774774294a396164a9b9c66492c9cb79f18257cc Signed-off-by: Mun, Gwan-gyeong --- src/tpl_wayland_egl.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index 5dea7ed..358432c 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -941,8 +941,24 @@ __tpl_wayland_egl_surface_wait_dequeuable(tpl_surface_t *surface) /* Application sent all buffers to the server. Wait for server response. */ if (wl_display_dispatch_queue(wayland_egl_display->wl_dpy, wayland_egl_display->wl_tbm_event_queue) == -1) { + int dpy_err; + char buf[1024]; + strerror_r(errno, buf, sizeof(buf)); + + TPL_ERR("falied to wl_display_dispatch_queue. error:%d(%s)", errno, + buf); + + dpy_err = wl_display_get_error(wayland_egl_display->wl_dpy); + if (dpy_err == EPROTO) { + const struct wl_interface *err_interface; + uint32_t err_proxy_id, err_code; + err_code = wl_display_get_protocol_error(wayland_egl_display->wl_dpy, + &err_interface, &err_proxy_id); + TPL_ERR("[Protocol Error] interface: %s, error_code: %d, proxy_id: %d", + err_interface->name, err_code, err_proxy_id); + } + ret = TPL_ERROR_INVALID_OPERATION; - TPL_ERR("falied to wl_display_dispatch_queue."); break; } } -- 2.7.4