From 40a902978dcbc258e434a06d5870468e4a39d279 Mon Sep 17 00:00:00 2001 From: "Mun, Gwan-gyeong" Date: Tue, 30 Aug 2016 22:36:44 +0900 Subject: [PATCH 01/16] tpl_wayland_egl: add TPL_OBJECT_CHECK on __tpl_wayland_egl_surface_enqueue_buffer() and __tpl_wayland_egl_surface_dequeue_buffer() Change-Id: Ie7f230aeb0eccf3689725459307f6f45eb891fa4 Signed-off-by: Mun, Gwan-gyeong --- src/tpl_wayland_egl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index 597defc..2a994c1 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -726,6 +726,7 @@ __tpl_wayland_egl_surface_enqueue_buffer(tpl_surface_t *surface, TPL_ASSERT(surface); TPL_ASSERT(surface->display); TPL_ASSERT(tbm_surface); + TPL_OBJECT_CHECK_RETURN(surface, TPL_ERROR_INVALID_PARAMETER); tpl_wayland_egl_surface_t *wayland_egl_surface = (tpl_wayland_egl_surface_t *) surface->backend.data; @@ -953,6 +954,7 @@ __tpl_wayland_egl_surface_dequeue_buffer(tpl_surface_t *surface, TPL_ASSERT(surface->backend.data); TPL_ASSERT(surface->display); TPL_ASSERT(surface->display->backend.data); + TPL_OBJECT_CHECK_RETURN(surface, NULL); tbm_surface_h tbm_surface = NULL; tpl_wayland_egl_buffer_t *wayland_egl_buffer = NULL; -- 2.7.4 From c2a16a4fc1c92f5fdf9f591094710c3e9592c105 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Fri, 2 Sep 2016 15:35:29 +0900 Subject: [PATCH 02/16] tpl_gbm: Add ttrace infos on DEQ~ENQ. Change-Id: I3f94be8f2a985602b627b0ac786cf0be2a2e4df8 Signed-off-by: joonbum.ko --- src/tpl_gbm.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/tpl_gbm.c b/src/tpl_gbm.c index c95c2db..d0d4bcf 100644 --- a/src/tpl_gbm.c +++ b/src/tpl_gbm.c @@ -337,7 +337,9 @@ __tpl_gbm_surface_enqueue_buffer(tpl_surface_t *surface, tbm_surface_h tbm_surface, int num_rects, const int *rects, tbm_fd sync_fence) { - tbm_bo bo; + tpl_gbm_buffer_t *gbm_buffer = NULL; + tpl_gbm_surface_t *gbm_surface = NULL; + tbm_bo_handle bo_handle; TPL_ASSERT(surface); TPL_ASSERT(surface->display); @@ -346,7 +348,7 @@ __tpl_gbm_surface_enqueue_buffer(tpl_surface_t *surface, TPL_IGNORE(num_rects); TPL_IGNORE(rects); - tpl_gbm_surface_t *gbm_surface = (tpl_gbm_surface_t *)surface->backend.data; + gbm_surface = (tpl_gbm_surface_t *)surface->backend.data; if (!gbm_surface) { TPL_ERR("tpl_gbm_surface_t is invalid. tpl_surface_t(%p)", surface); @@ -358,9 +360,16 @@ __tpl_gbm_surface_enqueue_buffer(tpl_surface_t *surface, return TPL_ERROR_INVALID_PARAMETER; } - bo = tbm_surface_internal_get_bo(tbm_surface, 0); - tbm_bo_handle bo_handle = tbm_bo_get_handle(bo, TBM_DEVICE_CPU); + gbm_buffer = __tpl_gbm_get_gbm_buffer_from_tbm_surface(tbm_surface); + if (!gbm_buffer) { + TPL_ERR("Filed to get gbm_buffer from tbm_surface(%p).", tbm_surface); + return TPL_ERROR_INVALID_PARAMETER; + } + + TRACE_ASYNC_END((int)gbm_buffer, "[DEQ]~[ENQ] BO_NAME:%d", + tbm_bo_export(gbm_buffer->bo)); + bo_handle = tbm_bo_get_handle(gbm_buffer->bo, TBM_DEVICE_CPU); if (bo_handle.ptr) TPL_IMAGE_DUMP(bo_handle.ptr, surface->width, surface->height, surface->dump_count++); @@ -386,9 +395,9 @@ __tpl_gbm_surface_enqueue_buffer(tpl_surface_t *surface, } TPL_LOG_B("GBM", "[ENQ] tpl_gbm_surface_t(%p) tbm_surface(%p) bo(%d)", - gbm_surface, tbm_surface, tbm_bo_export(bo)); + gbm_surface, tbm_surface, tbm_bo_export(gbm_buffer->bo)); - TRACE_MARK("[ENQ] BO_NAME:%d", tbm_bo_export(bo)); + TRACE_MARK("[ENQ] BO_NAME:%d", tbm_bo_export(gbm_buffer->bo)); return TPL_ERROR_NONE; } @@ -441,6 +450,8 @@ __tpl_gbm_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeout_ns, gbm_buffer = __tpl_gbm_get_gbm_buffer_from_tbm_surface(tbm_surface); if (gbm_buffer) { TRACE_MARK("[DEQ][REUSED]BO_NAME:%d", tbm_bo_export(gbm_buffer->bo)); + TRACE_ASYNC_BEGIN((int)gbm_buffer, "[DEQ]~[ENQ] BO_NAME:%d", + tbm_bo_export(gbm_buffer->bo)); TPL_LOG_B("GBM", "[DEQ][R] tpl_gbm_surface_t(%p) tbm_surface(%p) bo(%d)", gbm_surface, tbm_surface, tbm_bo_export(gbm_buffer->bo)); return tbm_surface; @@ -467,6 +478,8 @@ __tpl_gbm_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeout_ns, __tpl_gbm_set_gbm_buffer_to_tbm_surface(tbm_surface, gbm_buffer); TRACE_MARK("[DEQ][NEW]BO_NAME:%d", tbm_bo_export(gbm_buffer->bo)); + TRACE_ASYNC_BEGIN((int)gbm_buffer, "[DEQ]~[ENQ] BO_NAME:%d", + tbm_bo_export(gbm_buffer->bo)); TPL_LOG_B("GBM", "[DEQ][N] tpl_gbm_surface_t(%p) tbm_surface(%p) bo(%d)", gbm_surface, tbm_surface, tbm_bo_export(bo)); return tbm_surface; -- 2.7.4 From 06b5987176dd1ff2960f53ad56839c48d48b2f45 Mon Sep 17 00:00:00 2001 From: "Mun, Gwan-gyeong" Date: Fri, 2 Sep 2016 20:45:21 +0900 Subject: [PATCH 03/16] pkgconfig: package-config file which is generated while building. before: package config's library section is fixed. after : generated package config's library section is selected when package is building. Change-Id: I938c9dd0c5267d3d04eb761ed672863af33fadbe Signed-off-by: Mun, Gwan-gyeong --- packaging/libtpl-egl.spec | 7 +++++++ pkgconfig/CMakeLists.txt | 21 +++++++++++++++++++++ pkgconfig/{tpl-egl.pc => tpl-egl.pc.in} | 2 +- pkgconfig/{wayland-egl.pc => wayland-egl.pc.in} | 2 +- 4 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 pkgconfig/CMakeLists.txt rename pkgconfig/{tpl-egl.pc => tpl-egl.pc.in} (88%) rename pkgconfig/{wayland-egl.pc => wayland-egl.pc.in} (89%) diff --git a/packaging/libtpl-egl.spec b/packaging/libtpl-egl.spec index bf2b968..64438e8 100644 --- a/packaging/libtpl-egl.spec +++ b/packaging/libtpl-egl.spec @@ -45,6 +45,7 @@ Group: Graphics & UI Framework/GL License: MIT Source: %{name}-%{version}.tar.gz +BuildRequires: cmake BuildRequires: pkg-config BuildRequires: pkgconfig(libdrm) BuildRequires: pkgconfig(libtbm) @@ -172,8 +173,14 @@ make all cd src/wayland-egl export WLD_EGL_SO_VER=%{WL_EGL_VERSION} make +cd ../../ %endif +#pkgconfig configure +cd pkgconfig +cmake . +cd .. + %install rm -fr %{buildroot} mkdir -p %{buildroot} diff --git a/pkgconfig/CMakeLists.txt b/pkgconfig/CMakeLists.txt new file mode 100644 index 0000000..680e0b6 --- /dev/null +++ b/pkgconfig/CMakeLists.txt @@ -0,0 +1,21 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(libtpl-egl_package_config) + +SET(BUILD_ARCH "$ENV{RPM_ARCH}") + +IF(${BUILD_ARCH} MATCHES "aarch64") +SET(LIB "lib64") +SET(LIBDIR "/usr/lib64") +ELSEIF(${BUILD_ARCH} MATCHES "x86_64") +SET(LIB "lib64") +SET(LIBDIR "/usr/lib64") +ELSE(${BUILD_ARCH} MATCHES "aarch64") +SET(LIB "lib") +SET(LIBDIR "/usr/lib") +ENDIF(${BUILD_ARCH} MATCHES "aarch64") + +################################################################# +# Build Package Config File +# ------------------------------ +CONFIGURE_FILE(tpl-egl.pc.in tpl-egl.pc @ONLY) +CONFIGURE_FILE(wayland-egl.pc.in wayland-egl.pc @ONLY) diff --git a/pkgconfig/tpl-egl.pc b/pkgconfig/tpl-egl.pc.in similarity index 88% rename from pkgconfig/tpl-egl.pc rename to pkgconfig/tpl-egl.pc.in index fb8cdc5..8640c47 100644 --- a/pkgconfig/tpl-egl.pc +++ b/pkgconfig/tpl-egl.pc.in @@ -1,6 +1,6 @@ prefix=/usr exec_prefix=${prefix} -libdir=${exec_prefix}/lib +libdir=${exec_prefix}/@LIB@ includedir=${prefix}/include Name: libtpl-egl diff --git a/pkgconfig/wayland-egl.pc b/pkgconfig/wayland-egl.pc.in similarity index 89% rename from pkgconfig/wayland-egl.pc rename to pkgconfig/wayland-egl.pc.in index 8d32b34..529d543 100644 --- a/pkgconfig/wayland-egl.pc +++ b/pkgconfig/wayland-egl.pc.in @@ -1,6 +1,6 @@ prefix=/usr exec_prefix=${prefix} -libdir=${exec_prefix}/lib +libdir=${exec_prefix}/@LIB@ includedir=${prefix}/include Name: wayland-egl -- 2.7.4 From d446a98e924c10ec5db97ef18ef4fc2eb42f9537 Mon Sep 17 00:00:00 2001 From: "Mun, Gwan-gyeong" Date: Fri, 2 Sep 2016 21:21:14 +0900 Subject: [PATCH 04/16] tpl_utils_hlist: Fix compile warning on 64bit architecture fix size_t type argument format warning of printf() on 64bit architecture. Change-Id: I6f3f0959f29dec2c26a5456b75dbdf85e00f0020 Signed-off-by: Mun, Gwan-gyeong --- src/tpl_utils_hlist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tpl_utils_hlist.c b/src/tpl_utils_hlist.c index 252cf58..4997732 100644 --- a/src/tpl_utils_hlist.c +++ b/src/tpl_utils_hlist.c @@ -203,7 +203,7 @@ __tpl_hashlist_insert(tpl_hlist_t *list, size_t key, void *data) /* check if key already exists in the list */ prev_node = __tpl_hlist_get_node(list, key); if (prev_node) { - TPL_ERR("key(%d) already exists in tpl_hlist_t(%p).", key, list); + TPL_ERR("key(%zu) already exists in tpl_hlist_t(%p).", key, list); return TPL_ERROR_INVALID_PARAMETER; } -- 2.7.4 From d78d8d4298f1b586db2c9f5a34ffc801cbc8173b Mon Sep 17 00:00:00 2001 From: "Mun, Gwan-gyeong" Date: Mon, 5 Sep 2016 22:42:27 +0900 Subject: [PATCH 05/16] tpl_wayland_vk_wsi: Change strerror to strerror_r for the guaranteee of thread safety. Change-Id: I5947b09c64c439ef9433b5f9c8f47e73d7fa55b9 Signed-off-by: Mun, Gwan-gyeong --- src/tpl_wayland_vk_wsi.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/tpl_wayland_vk_wsi.c b/src/tpl_wayland_vk_wsi.c index e9469ae..3e266e2 100644 --- a/src/tpl_wayland_vk_wsi.c +++ b/src/tpl_wayland_vk_wsi.c @@ -417,8 +417,11 @@ __tpl_wayland_vk_wsi_surface_enqueue_buffer(tpl_surface_t *surface, if (sync_fence != -1) { /* non worker thread mode */ /* TODO: set max wait time */ - if (tbm_sync_fence_wait(sync_fence, -1) != 1) - TPL_ERR("Failed to wait sync. | error: %d(%s)", errno, strerror(errno)); + if (tbm_sync_fence_wait(sync_fence, -1) != 1) { + char buf[1024]; + strerror_r(errno, buf, sizeof(buf)); + TPL_ERR("Failed to wait sync. | error: %d(%s)", errno, buf); + } close(sync_fence); } @@ -554,8 +557,11 @@ __tpl_wayland_vk_wsi_surface_dequeue_buffer(tpl_surface_t *surface, *sync_fence = tbm_sync_fence_create(wayland_vk_wsi_buffer->sync_timeline, name, wayland_vk_wsi_buffer->sync_timestamp); - if (*sync_fence == -1) - TPL_ERR("Failed to create TBM sync fence: %d(%s)", errno, strerror(errno)); + if (*sync_fence == -1) { + char buf[1024]; + strerror_r(errno, buf, sizeof(buf)); + TPL_ERR("Failed to create TBM sync fence: %d(%s)", errno, buf); + } } else { *sync_fence = -1; } @@ -585,7 +591,9 @@ __tpl_wayland_vk_wsi_surface_dequeue_buffer(tpl_surface_t *surface, *sync_fence = -1; wayland_vk_wsi_buffer->sync_timeline = tbm_sync_timeline_create(); if (wayland_vk_wsi_buffer->sync_timeline == -1) { - TPL_ERR("Failed to create TBM sync timeline: %d(%s)", errno, strerror(errno)); + char buf[1024]; + strerror_r(errno, buf, sizeof(buf)); + TPL_ERR("Failed to create TBM sync timeline: %d(%s)", errno, buf); wl_proxy_destroy(wl_proxy); tbm_surface_internal_unref(tbm_surface); free(wayland_vk_wsi_buffer); @@ -948,8 +956,11 @@ __tpl_wayland_vk_wsi_worker_thread_loop(void *arg) __tpl_wayland_vk_wsi_get_wayland_buffer_from_tbm_surface(tbm_surface); TPL_ASSERT(wayland_vk_wsi_buffer); if (wayland_vk_wsi_buffer->wait_sync != -1) { - if (tbm_sync_fence_wait(wayland_vk_wsi_buffer->wait_sync, -1) != 1) - TPL_ERR("Failed to wait sync. | error: %d(%s)", errno, strerror(errno)); + if (tbm_sync_fence_wait(wayland_vk_wsi_buffer->wait_sync, -1) != 1) { + char buf[1024]; + strerror_r(errno, buf, sizeof(buf)); + TPL_ERR("Failed to wait sync. | error: %d(%s)", errno, buf); + } close(wayland_vk_wsi_buffer->wait_sync); wayland_vk_wsi_buffer->wait_sync = -1; } -- 2.7.4 From d3c3f181659b46f8cb6d09278712940ea16aa32b Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Tue, 6 Sep 2016 18:17:22 +0900 Subject: [PATCH 06/16] tpl_wayland_egl: Add object locking mechanism for multi-threads client. - In the multi-threads environment, backend surface's locking mechanism(using tpl_object_t) is needed in order to prevent the case that the tpl_list is concurrently accessed by wayland_event of multi-threaded client. Change-Id: I2957a2893f469d2b8eb3fc4b4c30dd9da3cdfeff Signed-off-by: joonbum.ko --- src/tpl_wayland_egl.c | 67 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 15 deletions(-) diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index 2a994c1..3aa1181 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -40,6 +40,7 @@ struct _tpl_wayland_egl_display { }; struct _tpl_wayland_egl_surface { + tpl_object_t base; tbm_surface_queue_h tbm_queue; tbm_surface_h current_buffer; tpl_bool_t resized; @@ -374,12 +375,15 @@ __cb_tbm_surface_queue_reset_callback(tbm_surface_queue_h surface_queue, wayland_egl_surface->reset = TPL_TRUE; + TPL_OBJECT_LOCK(&wayland_egl_surface->base); + /* Set the reset flag of the buffers which attached but not released to TPL_TRUE. */ __tpl_wayland_egl_buffer_set_reset_flag(wayland_egl_surface->attached_buffers); /* Set the reset flag of the buffers which dequeued but not enqueued to TPL_TRUE. */ __tpl_wayland_egl_buffer_set_reset_flag(wayland_egl_surface->dequeued_buffers); + TPL_OBJECT_UNLOCK(&wayland_egl_surface->base); } static tpl_result_t @@ -437,6 +441,13 @@ __tpl_wayland_egl_surface_init(tpl_surface_t *surface) return TPL_ERROR_INVALID_OPERATION; } + 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; + } + surface->backend.data = (void *)wayland_egl_surface; wayland_egl_surface->tbm_queue = NULL; wayland_egl_surface->resized = TPL_FALSE; @@ -587,6 +598,7 @@ __tpl_wayland_egl_surface_fini(tpl_surface_t *surface) * the list of attached_buffers in order to free the created resources. * (tpl_wayland_egl_buffer_t or wl_buffer) */ if (wayland_egl_surface->attached_buffers) { + TPL_OBJECT_LOCK(&wayland_egl_surface->base); while (!__tpl_list_is_empty(wayland_egl_surface->attached_buffers)) { tbm_surface_h tbm_surface = __tpl_list_pop_front(wayland_egl_surface->attached_buffers, NULL); @@ -595,14 +607,18 @@ __tpl_wayland_egl_surface_fini(tpl_surface_t *surface) __tpl_list_free(wayland_egl_surface->attached_buffers, NULL); wayland_egl_surface->attached_buffers = NULL; + TPL_OBJECT_UNLOCK(&wayland_egl_surface->base); } /* the list of dequeued_buffers just does deletion */ if (wayland_egl_surface->dequeued_buffers) { + TPL_OBJECT_LOCK(&wayland_egl_surface->base); __tpl_list_free(wayland_egl_surface->dequeued_buffers, NULL); wayland_egl_surface->dequeued_buffers = NULL; + TPL_OBJECT_UNLOCK(&wayland_egl_surface->base); } + __tpl_object_fini(&wayland_egl_surface->base); free(wayland_egl_surface); surface->backend.data = NULL; } @@ -697,9 +713,13 @@ __tpl_wayland_egl_surface_commit(tpl_surface_t *surface, wl_egl_window->surface, wl_egl_window, wl_egl_window->width, wl_egl_window->height, wayland_egl_buffer->wl_proxy); - /* Start tracking of this tbm_surface until release_cb called. */ - __tpl_list_push_back(wayland_egl_surface->attached_buffers, - (void *)tbm_surface); + if (wayland_egl_surface->attached_buffers) { + TPL_OBJECT_LOCK(&wayland_egl_surface->base); + /* Start tracking of this tbm_surface until release_cb called. */ + __tpl_list_push_back(wayland_egl_surface->attached_buffers, + (void *)tbm_surface); + TPL_OBJECT_UNLOCK(&wayland_egl_surface->base); + } /* TPL_WAIT_VBLANK = 1 */ if (wayland_egl_display->tdm_client) { @@ -758,9 +778,13 @@ __tpl_wayland_egl_surface_enqueue_buffer(tpl_surface_t *surface, close(sync_fence); } - /* Stop tracking of this render_done tbm_surface. */ - __tpl_list_remove_data(wayland_egl_surface->dequeued_buffers, - (void *)tbm_surface, TPL_FIRST, NULL); + if (wayland_egl_surface->dequeued_buffers) { + TPL_OBJECT_LOCK(&wayland_egl_surface->base); + /* Stop tracking of this render_done tbm_surface. */ + __tpl_list_remove_data(wayland_egl_surface->dequeued_buffers, + (void *)tbm_surface, TPL_FIRST, NULL); + TPL_OBJECT_UNLOCK(&wayland_egl_surface->base); + } wayland_egl_buffer = __tpl_wayland_egl_get_wayland_buffer_from_tbm_surface(tbm_surface); @@ -1011,9 +1035,14 @@ __tpl_wayland_egl_surface_dequeue_buffer(tpl_surface_t *surface, wayland_egl_buffer->wl_proxy, tbm_surface, tbm_bo_export(wayland_egl_buffer->bo)); - /* Start tracking of this tbm_surface until enqueue */ - __tpl_list_push_back(wayland_egl_surface->dequeued_buffers, - (void *)tbm_surface); + if (wayland_egl_surface->dequeued_buffers) { + TPL_OBJECT_LOCK(&wayland_egl_surface->base); + /* Start tracking of this tbm_surface until enqueue */ + __tpl_list_push_back(wayland_egl_surface->dequeued_buffers, + (void *)tbm_surface); + TPL_OBJECT_UNLOCK(&wayland_egl_surface->base); + } + return tbm_surface; } @@ -1071,8 +1100,13 @@ __tpl_wayland_egl_surface_dequeue_buffer(tpl_surface_t *surface, wayland_egl_buffer, wayland_egl_buffer->wl_proxy, tbm_surface, tbm_bo_export(wayland_egl_buffer->bo)); - __tpl_list_push_back(wayland_egl_surface->dequeued_buffers, - (void *)tbm_surface); + if (wayland_egl_surface->dequeued_buffers) { + TPL_OBJECT_LOCK(&wayland_egl_surface->base); + __tpl_list_push_back(wayland_egl_surface->dequeued_buffers, + (void *)tbm_surface); + TPL_OBJECT_UNLOCK(&wayland_egl_surface->base); + } + return tbm_surface; } @@ -1199,10 +1233,13 @@ __cb_client_buffer_release_callback(void *data, struct wl_proxy *proxy) if (wayland_egl_buffer) { wayland_egl_surface = wayland_egl_buffer->wayland_egl_surface; - /* Stop tracking of this released tbm_surface. */ - __tpl_list_remove_data(wayland_egl_surface->attached_buffers, - (void *)tbm_surface, TPL_FIRST, NULL); - + if (wayland_egl_surface->attached_buffers) { + TPL_OBJECT_LOCK(&wayland_egl_surface->base); + /* Stop tracking of this released tbm_surface. */ + __tpl_list_remove_data(wayland_egl_surface->attached_buffers, + (void *)tbm_surface, TPL_FIRST, NULL); + TPL_OBJECT_UNLOCK(&wayland_egl_surface->base); + } /* If tbm_surface_queue was reset before release_cb called out, * tbm_surface_queue_release doesn't have to be done. */ if (wayland_egl_buffer->reset == TPL_FALSE) -- 2.7.4 From 66532f5dc25e2ed997a3d1e927b0d645bdaac150 Mon Sep 17 00:00:00 2001 From: Sangjin Lee Date: Thu, 8 Sep 2016 14:28:12 +0900 Subject: [PATCH 07/16] tpl_wayland_egl: Use seperated event-queue for wl_tbm. the tdm_client related protocol provides wl_tbm, wl_tbm_queue and wl_buffer proxy. if wl_tbm proxy uses the seperated queue from wl_display, then wl_tbm_queue and wl_buffer also use the seperated queue by inherited from wl_tbm proxy's queue. ( if wl_tbm_queue and wl_buffer are gotten before setting of wl_tbm proxy queue. this machanism does not work. therefore, wl_tbm_queue and wl_buffer use wl_display's default queue.) - this patch chages the timing of handling of wl_buffer_release event. wl_buffer_release event is only handled before dequeue_buffer. reference: 1. wl_tbm proxy handles what received below wayland events. - buffer_attached_with_id - buffer_attached_with_fd 2. wl_tbm_queue handles what received below wayland events. - active - deactive Change-Id: Iac8b07016aae3418563ab5b5cc181fa8d2e7712f --- src/tpl_wayland_egl.c | 138 +++++++++++++------------------------------------- 1 file changed, 36 insertions(+), 102 deletions(-) diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index 2a994c1..751555c 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -37,6 +37,7 @@ struct _tpl_wayland_egl_display { struct wl_proxy *wl_tbm; /* wayland_tbm_client proxy */ tdm_client *tdm_client; struct wl_display *wl_dpy; + struct wl_event_queue *wl_tbm_event_queue; }; struct _tpl_wayland_egl_surface { @@ -48,7 +49,6 @@ struct _tpl_wayland_egl_surface { tpl_bool_t vblank_done; tpl_list_t *attached_buffers; /* list for tracking [ACQ]~[REL] buffers */ tpl_list_t *dequeued_buffers; /* list for tracking [DEQ]~[ENQ] buffers */ - struct wl_proxy *wl_tbm_queue; /* wl_tbm_queue proxy */ }; struct _tpl_wayland_egl_buffer { @@ -159,6 +159,16 @@ __tpl_wayland_egl_display_init(tpl_display_t *display) goto free_wl_display; } + wayland_egl_display->wl_tbm_event_queue = + wl_display_create_queue(wl_dpy); + if (!wayland_egl_display->wl_tbm_event_queue) { + TPL_ERR("Failed to create wl_event_queue."); + goto free_wl_display; + } + + wl_proxy_set_queue(wayland_egl_display->wl_tbm, + wayland_egl_display->wl_tbm_event_queue); + if (env == NULL || atoi(env)) { TPL_LOG_B("WL_EGL", "[INIT] ENABLE wait vblank."); wayland_egl_display->tdm_client = tdm_client_create(&tdm_err); @@ -185,11 +195,16 @@ __tpl_wayland_egl_display_init(tpl_display_t *display) free_wl_display: if (wayland_egl_display) { + if ((wayland_egl_display->wl_tbm) && (wayland_egl_display->wl_tbm_event_queue)) + wl_proxy_set_queue(wayland_egl_display->wl_tbm, NULL); if (wayland_egl_display->wl_tbm_client) wayland_tbm_client_deinit(wayland_egl_display->wl_tbm_client); if (wayland_egl_display->tdm_client) tdm_client_destroy(wayland_egl_display->tdm_client); + if (wayland_egl_display->wl_tbm_event_queue) + wl_event_queue_destroy(wayland_egl_display->wl_tbm_event_queue); + wayland_egl_display->wl_tbm_event_queue = NULL; wayland_egl_display->wl_tbm_client = NULL; wayland_egl_display->tdm_client = NULL; wayland_egl_display->wl_tbm = NULL; @@ -213,12 +228,19 @@ __tpl_wayland_egl_display_fini(tpl_display_t *display) TPL_LOG_B("WL_EGL", "[FINI] tpl_wayland_egl_display_t(%p) wl_tbm_client(%p)", wayland_egl_display, wayland_egl_display->wl_tbm_client); + if ((wayland_egl_display->wl_tbm) && (wayland_egl_display->wl_tbm_event_queue)) + wl_proxy_set_queue(wayland_egl_display->wl_tbm, NULL); + if (wayland_egl_display->wl_tbm_client) wayland_tbm_client_deinit(wayland_egl_display->wl_tbm_client); if (wayland_egl_display->tdm_client) tdm_client_destroy(wayland_egl_display->tdm_client); + if (wayland_egl_display->wl_tbm_event_queue) + wl_event_queue_destroy(wayland_egl_display->wl_tbm_event_queue); + + wayland_egl_display->wl_tbm_event_queue = NULL; wayland_egl_display->wl_tbm_client = NULL; wayland_egl_display->tdm_client = NULL; wayland_egl_display->wl_tbm = NULL; @@ -461,24 +483,6 @@ __tpl_wayland_egl_surface_init(tpl_surface_t *surface) wl_egl_window->width, wl_egl_window->height, TBM_FORMAT_ARGB8888); - - /* libtpl-egl processes the wl_proxy(wl_tbm_queue) event at dequeue. - * When libtpl-egl gets the activate event from wl_tbm_queue, - * it gets the scanout wl_buffer from the display server. - * When libtpl-egl gets the decativate event from wl_tbm_queue, - * it release the sacnout wl_buffer and allocates the offscreen wl_buffer - * at the client-side. - * The activate/decactivate events is sent from the display server - * at the no-comoposite mode and the composite mode. - */ - wayland_egl_surface->wl_tbm_queue = - (struct wl_proxy *)wayland_tbm_client_get_wl_tbm_queue( - wayland_egl_display->wl_tbm_client, - wl_egl_window->surface); - if (!wayland_egl_surface->wl_tbm_queue) { - TPL_ERR("Failed to get tbm_queue from wayland_tbm_client."); - return TPL_ERROR_INVALID_OPERATION; - } } else /*Why wl_surafce is NULL ?*/ wayland_egl_surface->tbm_queue = tbm_surface_queue_sequence_create( @@ -836,90 +840,35 @@ __tpl_wayland_egl_surface_validate(tpl_surface_t *surface) static tpl_result_t __tpl_wayland_egl_surface_wait_dequeuable(tpl_surface_t *surface) { - struct wl_event_queue *queue = NULL; tpl_wayland_egl_display_t *wayland_egl_display = NULL; tpl_wayland_egl_surface_t *wayland_egl_surface = NULL; - tpl_wayland_egl_buffer_t *wayland_egl_buffer = NULL; - tbm_surface_h buffers[CLIENT_QUEUE_SIZE]; - int num = 0, i; tpl_result_t ret = TPL_ERROR_NONE; wayland_egl_display = (tpl_wayland_egl_display_t *) surface->display->backend.data; wayland_egl_surface = (tpl_wayland_egl_surface_t *)surface->backend.data; - wl_display_dispatch_pending(wayland_egl_display->wl_dpy); if (tbm_surface_queue_can_dequeue(wayland_egl_surface->tbm_queue, 0)) return TPL_ERROR_NONE; - tbm_surface_queue_get_surfaces(wayland_egl_surface->tbm_queue, buffers, &num); - if (num == 0) { - TPL_ERR("tbm_queue(%p) has no buffer", wayland_egl_surface->tbm_queue); - return TPL_ERROR_INVALID_OPERATION; - } - - queue = wl_display_create_queue(wayland_egl_display->wl_dpy); - if (!queue) { - TPL_ERR("failed to create new wl_display queue."); - return TPL_ERROR_INVALID_OPERATION; - } - - for (i = 0; i < num; i++) { - wayland_egl_buffer = - __tpl_wayland_egl_get_wayland_buffer_from_tbm_surface(buffers[i]); - if (wayland_egl_buffer && wayland_egl_buffer->wl_proxy) - wl_proxy_set_queue(wayland_egl_buffer->wl_proxy, queue); - } + TRACE_BEGIN("WAITING FOR DEQUEUEABLE"); + TPL_OBJECT_UNLOCK(surface); - /* wayland_egl_display->wl_tbm has to receive below wayland events. - * - buffer_attached_with_id - * - buffer_attached_with_fd + /* Dispatching "wayland_egl_display->wl_tbm_event_queue" handles + * wl_buffer_release event, wl_tbm event, and wl_tbm_queue event. * - * wayland_egl_surface->wl_tbm_queue has to receive below wayland events. - * - active - * - deactive - * - * When wayland_egl_surface->wl_tbm_queue - * or wayland_egl_display->wl_tbm( == wayland_tbm_client) - * could not receive any events, tpl_surface cannot get a buffer. - * - * So, we have to manage event queue about [wl_tbm_queue, wayland_tbm_client] - * along with wl_buffer. + * 1. wl_tbm proxy handles what received below wayland events. + * - buffer_attached_with_id + * - buffer_attached_with_fd + * 2. wl_tbm_queue handles what received below wayland events. + * - active + * - deactive */ - - if (wayland_egl_surface->wl_tbm_queue) - wl_proxy_set_queue(wayland_egl_surface->wl_tbm_queue, queue); - - if (wayland_egl_display->wl_tbm) - wl_proxy_set_queue(wayland_egl_display->wl_tbm, queue); - - wl_display_dispatch_pending(wayland_egl_display->wl_dpy); - - if (tbm_surface_queue_can_dequeue(wayland_egl_surface->tbm_queue, 0)) { - for (i = 0; i < num; i++) { - wayland_egl_buffer = - __tpl_wayland_egl_get_wayland_buffer_from_tbm_surface(buffers[i]); - if (wayland_egl_buffer && wayland_egl_buffer->wl_proxy) - wl_proxy_set_queue(wayland_egl_buffer->wl_proxy, NULL); - } - - if (wayland_egl_surface->wl_tbm_queue) - wl_proxy_set_queue(wayland_egl_surface->wl_tbm_queue, NULL); - - if (wayland_egl_display->wl_tbm) - wl_proxy_set_queue(wayland_egl_display->wl_tbm, NULL); - - wl_event_queue_destroy(queue); - - return TPL_ERROR_NONE; - } - - TRACE_BEGIN("WAITING FOR DEQUEUEABLE"); - TPL_OBJECT_UNLOCK(surface); while (tbm_surface_queue_can_dequeue( wayland_egl_surface->tbm_queue, 0) == 0) { /* Application sent all buffers to the server. Wait for server response. */ - if (wl_display_dispatch_queue(wayland_egl_display->wl_dpy, queue) == -1) { + if (wl_display_dispatch_queue(wayland_egl_display->wl_dpy, + wayland_egl_display->wl_tbm_event_queue) == -1) { ret = TPL_ERROR_INVALID_OPERATION; TPL_ERR("falied to wl_display_dispatch_queue."); break; @@ -928,27 +877,12 @@ __tpl_wayland_egl_surface_wait_dequeuable(tpl_surface_t *surface) TPL_OBJECT_LOCK(surface); TRACE_END(); - for (i = 0; i < num; i++) { - wayland_egl_buffer = - __tpl_wayland_egl_get_wayland_buffer_from_tbm_surface(buffers[i]); - if (wayland_egl_buffer && wayland_egl_buffer->wl_proxy) - wl_proxy_set_queue(wayland_egl_buffer->wl_proxy, NULL); - } - - if (wayland_egl_surface->wl_tbm_queue) - wl_proxy_set_queue(wayland_egl_surface->wl_tbm_queue, NULL); - - if (wayland_egl_display->wl_tbm) - wl_proxy_set_queue(wayland_egl_display->wl_tbm, NULL); - - wl_event_queue_destroy(queue); return ret; } static tbm_surface_h __tpl_wayland_egl_surface_dequeue_buffer(tpl_surface_t *surface, - uint64_t timeout_ns, - tbm_fd *sync_fence) + uint64_t timeout_ns, tbm_fd *sync_fence) { TPL_ASSERT(surface); TPL_ASSERT(surface->backend.data); -- 2.7.4 From 019e7ff6cade7d660524cb23f7b7c442011a07dd Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Mon, 19 Sep 2016 19:59:01 +0900 Subject: [PATCH 08/16] tpl_wayland_egl: dispatching before checking whether can dequeue or not. - The event processing can be delayed in case there are idle buffer in free queue. So, in dequeueable procedure, it has to call wl_display_dispatch_queue_pending before checking whether tbm_surface_queue can dequeue or not. It can process that the events related to 'queue flush' more rapidly. Change-Id: I5512e576e985d57dc9181e338f589d344f2b8161 Signed-off-by: joonbum.ko --- src/tpl_wayland_egl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index fe892ba..af23333 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -872,6 +872,9 @@ __tpl_wayland_egl_surface_wait_dequeuable(tpl_surface_t *surface) surface->display->backend.data; wayland_egl_surface = (tpl_wayland_egl_surface_t *)surface->backend.data; + wl_display_dispatch_queue_pending(wayland_egl_display->wl_dpy, + wayland_egl_display->wl_tbm_event_queue); + if (tbm_surface_queue_can_dequeue(wayland_egl_surface->tbm_queue, 0)) return TPL_ERROR_NONE; -- 2.7.4 From 73106ab4db76751bd212a1186ef3afac76f5ad24 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Thu, 22 Sep 2016 11:41:44 +0900 Subject: [PATCH 09/16] tpl: Fixed image dump util. Change-Id: I8c1727194fb1934cda60f6d413590ecc2ff0eb73 Signed-off-by: joonbum.ko --- Makefile | 6 +- packaging/libtpl-egl.spec | 10 +- src/tpl_gbm.c | 6 +- src/tpl_utils.h | 236 +++------------------------------------------- src/tpl_wayland_egl.c | 7 +- src/tpl_wayland_vk_wsi.c | 7 +- 6 files changed, 23 insertions(+), 249 deletions(-) diff --git a/Makefile b/Makefile index e18a35a..23e82a8 100644 --- a/Makefile +++ b/Makefile @@ -47,10 +47,8 @@ endif ifneq ($(call is-feature-enabled,default_log),) CFLAGS += -DLOG_DEFAULT_ENABLE endif -ifneq ($(call is-feature-enabled,pngdump),) - CFLAGS += -DPNG_DUMP_ENABLE - CFLAGS += `pkg-config --cflags libpng` - LDFLAGS += `pkg-config --libs libpng` +ifneq ($(call is-feature-enabled,default_dump),) + CFLAGS += -DDEFAULT_DUMP_ENABLE endif ifneq ($(call is-feature-enabled,object_hash_check),) CFLAGS += -DOBJECT_HASH_CHECK diff --git a/packaging/libtpl-egl.spec b/packaging/libtpl-egl.spec index 64438e8..2eb175c 100644 --- a/packaging/libtpl-egl.spec +++ b/packaging/libtpl-egl.spec @@ -12,7 +12,7 @@ %define ENABLE_TTRACE 0 %define ENABLE_DLOG 0 %define ENABLE_DEFAULT_LOG 0 -%define ENABLE_PNG_DUMP 0 +%define ENABLE_DEFAULT_DUMP 0 %define ENABLE_OBJECT_HASH_CHECK 1 #WAYLAND-EGL VERSION MACROS %define WL_EGL_VERSION 1.0.0 @@ -73,10 +73,6 @@ BuildRequires: pkgconfig(wayland-tbm-client) BuildRequires: pkgconfig(wayland-tbm-server) %endif -%if "%{ENABLE_PNG_DUMP}" == "1" -BuildRequires: pkgconfig(libpng) -%endif - %if "%{ENABLE_TTRACE}" == "1" BuildRequires: pkgconfig(ttrace) %endif @@ -147,8 +143,8 @@ TPL_OPTIONS=${TPL_OPTIONS}-dlog TPL_OPTIONS=${TPL_OPTIONS}-default_log %endif -%if "%{ENABLE_PNG_DUMP}" == "1" -TPL_OPTIONS=${TPL_OPTIONS}-pngdump +%if "%{ENABLE_DEFAULT_DUMP}" == "1" +TPL_OPTIONS=${TPL_OPTIONS}-default_dump %endif %if "%{ENABLE_OBJECT_HASH_CHECK}" == "1" diff --git a/src/tpl_gbm.c b/src/tpl_gbm.c index d0d4bcf..d5d43ce 100644 --- a/src/tpl_gbm.c +++ b/src/tpl_gbm.c @@ -339,7 +339,6 @@ __tpl_gbm_surface_enqueue_buffer(tpl_surface_t *surface, { tpl_gbm_buffer_t *gbm_buffer = NULL; tpl_gbm_surface_t *gbm_surface = NULL; - tbm_bo_handle bo_handle; TPL_ASSERT(surface); TPL_ASSERT(surface->display); @@ -369,10 +368,7 @@ __tpl_gbm_surface_enqueue_buffer(tpl_surface_t *surface, TRACE_ASYNC_END((int)gbm_buffer, "[DEQ]~[ENQ] BO_NAME:%d", tbm_bo_export(gbm_buffer->bo)); - bo_handle = tbm_bo_get_handle(gbm_buffer->bo, TBM_DEVICE_CPU); - if (bo_handle.ptr) - TPL_IMAGE_DUMP(bo_handle.ptr, surface->width, surface->height, - surface->dump_count++); + TPL_IMAGE_DUMP(tbm_surface, surface->width, surface->height); tbm_surface_internal_unref(tbm_surface); diff --git a/src/tpl_utils.h b/src/tpl_utils.h index d8b832a..7c1696e 100644 --- a/src/tpl_utils.h +++ b/src/tpl_utils.h @@ -47,9 +47,8 @@ #include #include -#ifdef PNG_DUMP_ENABLE -#include -#endif /* PNG_DUMP_ENABLE */ +#include +#include /* 0:uninitialized, 1:initialized,no log, 2:user log */ extern unsigned int tpl_log_lvl; @@ -233,11 +232,14 @@ extern unsigned int tpl_dump_lvl; } \ } -#define TPL_IMAGE_DUMP(data, width, height, num) \ +#ifdef DEFAULT_DUMP_ENABLE +#define TPL_IMAGE_DUMP __tpl_util_image_dump +#else +#define TPL_IMAGE_DUMP(data, width, height) \ { \ if (tpl_dump_lvl != 0) \ { \ - __tpl_util_image_dump(__func__, data, tpl_dump_lvl, width, height, num); \ + __tpl_util_image_dump(data, width, height); \ } \ else \ { \ @@ -248,10 +250,10 @@ extern unsigned int tpl_dump_lvl; tpl_dump_lvl = atoi(env); \ \ if (tpl_dump_lvl != 0) \ - __tpl_util_image_dump(__func__, data, tpl_dump_lvl, width, height, num);\ + __tpl_util_image_dump(data, width, height); \ } \ } - +#endif typedef struct _tpl_list_node tpl_list_node_t; @@ -646,223 +648,13 @@ tpl_list_pop_back(tpl_list_t *list, tpl_free_func_t func) return data; } -static TPL_INLINE int -__tpl_util_image_dump_bmp(const char *file, const void *data, int width, - int height) -{ - int i; - - struct { - unsigned char magic[2]; - } bmpfile_magic = { {'B', 'M'} }; - - struct { - unsigned int filesz; - unsigned short creator1; - unsigned short creator2; - unsigned int bmp_offset; - } bmpfile_header = { 0, 0, 0, 0x36 }; - - struct { - unsigned int header_sz; - unsigned int width; - unsigned int height; - unsigned short nplanes; - unsigned short bitspp; - unsigned int compress_type; - unsigned int bmp_bytesz; - unsigned int hres; - unsigned int vres; - unsigned int ncolors; - unsigned int nimpcolors; - } bmp_dib_v3_header_t = { 0x28, 0, 0, 1, 24, 0, 0, 0, 0, 0, 0 }; - unsigned int *blocks; - - if (data == NULL) return -1; - - if (width <= 0 || height <= 0) return -1; - - FILE *fp = NULL; - if ((fp = fopen (file, "wb")) == NULL) { - char ment[256]; - strerror_r(errno, ment, 256); - printf("FILE ERROR:%s\t", ment); - return -2; - } else { - bmpfile_header.filesz = sizeof (bmpfile_magic) + sizeof (bmpfile_header) + - sizeof (bmp_dib_v3_header_t) + width * height * 3; - bmp_dib_v3_header_t.header_sz = sizeof (bmp_dib_v3_header_t); - bmp_dib_v3_header_t.width = width; - bmp_dib_v3_header_t.height = -height; - bmp_dib_v3_header_t.nplanes = 1; - bmp_dib_v3_header_t.bmp_bytesz = width * height * 3; - - if (fwrite(&bmpfile_magic, sizeof (bmpfile_magic), 1, fp) < 1) { - fclose (fp); - return -1; - } - if (fwrite(&bmpfile_header, sizeof (bmpfile_header), 1, fp) < 1) { - fclose (fp); - return -1; - } - if (fwrite(&bmp_dib_v3_header_t, sizeof (bmp_dib_v3_header_t), 1, fp) < 1) { - fclose (fp); - return -1; - } - - blocks = (unsigned int *)data; - for (i = 0; i < height * width; i++) { - if (fwrite(&blocks[i], 3, 1, fp) < 1) { - fclose(fp); - return -1; - } - } - - fclose (fp); - } - - return 0; -} - -#ifdef PNG_DUMP_ENABLE -#define PNG_DEPTH 8 -static TPL_INLINE int -__tpl_util_image_dump_png(const char *file, const void *data, int width, - int height) -{ - TPL_CHECK_ON_FALSE_RETURN_VAL(data != NULL, -1); - TPL_CHECK_ON_FALSE_RETURN_VAL(width > 0, -1); - TPL_CHECK_ON_FALSE_RETURN_VAL(height > 0, -1); - - FILE *fp = fopen(file, "wb"); - int res = -2; - - if (fp) { - res = -1; - png_structp pPngStruct = - png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (pPngStruct) { - png_infop pPngInfo = png_create_info_struct(pPngStruct); - - if (pPngInfo) { - png_init_io(pPngStruct, fp); - png_set_IHDR(pPngStruct, - pPngInfo, - width, - height, - PNG_DEPTH, - PNG_COLOR_TYPE_RGBA, - PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT); - - png_set_bgr(pPngStruct); - png_write_info(pPngStruct, pPngInfo); - - const int pixel_size = 4; // RGBA - png_bytep *row_pointers = - png_malloc(pPngStruct, height * sizeof(png_byte *)); - if (!row_pointers) { - fclose(fp); - return res; - } - - unsigned int *blocks = (unsigned int *) data; - int y = 0; - int x = 0; - - for (; y < height; ++y) { - png_bytep row = png_malloc(pPngStruct, - sizeof(png_byte) * width * - pixel_size); - if (!row) { - fclose(fp); - return res; - } - - row_pointers[y] = (png_bytep) row; - - for (x = 0; x < width; ++x) { - unsigned int curBlock = blocks[y * width + x]; - - row[x * pixel_size] = (curBlock & 0xFF); - row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF; - row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF; - row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF; - } - } - - png_write_image(pPngStruct, row_pointers); - png_write_end(pPngStruct, pPngInfo); - - for (y = 0; y < height; y++) { - png_free(pPngStruct, row_pointers[y]); - } - png_free(pPngStruct, row_pointers); - - png_destroy_write_struct(&pPngStruct, &pPngInfo); - - res = 0; - } - } - fclose(fp); - } - - return res; -} -#endif - static TPL_INLINE void -__tpl_util_image_dump(const char *func, const void *data, int type, - int width, int height, int num) +__tpl_util_image_dump(void *data, int width, int height) { - char name[200]; - char path_name[20] = "/tmp/tpl_dump"; + char path_name[20] = "/tmp"; - if (mkdir (path_name, 0755) == -1) { - if (errno != EEXIST) { - TPL_ERR("Directory creation error!"); - return; - } - } - - if (type == 1) { - snprintf(name, sizeof(name), "%s/[%d][%s][%d][%d][%04d].bmp", - path_name, getpid(), func, width, height, num); - - /*snprintf(name, sizeof(name), "[%d][%04d]", getpid(), num);*/ - switch (__tpl_util_image_dump_bmp(name, data, width, height)) { - case 0: - TPL_DEBUG("%s file is dumped\n", name); - break; - case -1: - TPL_ERR("Dump failed..internal error (data = %p)(width = %d)(height = %d)\n", - data, width, height); - break; - case -2: - TPL_ERR("Dump failed..file pointer error\n"); - break; - } - } -#ifdef PNG_DUMP_ENABLE - else { - snprintf(name, sizeof(name), "%s/[%d][%s][%d][%d][%04d].png", - path_name, getpid(), func, width, height, num); - - /*snprintf(name, sizeof(name), "[%d][%04d]", getpid(), num);*/ - switch (__tpl_util_image_dump_png(name, data, width, height)) { - case 0: - TPL_DEBUG("%s file is dumped\n", name); - break; - case -1: - TPL_ERR("Dump failed..internal error (data = %p)(width = %d)(height = %d)\n", - data, width, height); - break; - case -2: - TPL_ERR("Dump failed..file pointer error\n"); - break; - } - } -#endif + tbm_surface_internal_dump_start(path_name, width, height, 1); + tbm_surface_internal_dump_buffer((tbm_surface_h)data, "png"); + tbm_surface_internal_dump_end(); } #endif /* TPL_UTILS_H */ diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index af23333..d04e209 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -678,12 +678,9 @@ __tpl_wayland_egl_surface_commit(tpl_surface_t *surface, TRACE_ASYNC_END((int)wayland_egl_buffer, "[DEQ]~[ENQ] BO_NAME:%d", tbm_bo_export(wayland_egl_buffer->bo)); - tbm_bo_handle bo_handle = - 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, - surface->dump_count++); + TPL_IMAGE_DUMP(tbm_surface, surface->width, surface->height); + wl_surface_attach(wl_egl_window->surface, (void *)wayland_egl_buffer->wl_proxy, wl_egl_window->dx, wl_egl_window->dy); diff --git a/src/tpl_wayland_vk_wsi.c b/src/tpl_wayland_vk_wsi.c index 3e266e2..69e1fbf 100644 --- a/src/tpl_wayland_vk_wsi.c +++ b/src/tpl_wayland_vk_wsi.c @@ -390,12 +390,7 @@ __tpl_wayland_vk_wsi_surface_enqueue_buffer(tpl_surface_t *surface, __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++); + TPL_IMAGE_DUMP(tbm_surface, surface->width, surface->height); tbm_surface_internal_unref(tbm_surface); -- 2.7.4 From daf6ad30df340d1eec2b241c42c6183b914f7d71 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Thu, 22 Sep 2016 11:52:23 +0900 Subject: [PATCH 10/16] tpl_wayland_egl: Reused buffer's reset flag set to TPL_FALSE. Change-Id: I2edc82f5e61ccb35deb22bdefe9b888568a313f9 Signed-off-by: joonbum.ko --- src/tpl_wayland_egl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index d04e209..5c38105 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -969,6 +969,8 @@ __tpl_wayland_egl_surface_dequeue_buffer(tpl_surface_t *surface, wayland_egl_buffer->wl_proxy, tbm_surface, tbm_bo_export(wayland_egl_buffer->bo)); + wayland_egl_buffer->reset = TPL_FALSE; + if (wayland_egl_surface->dequeued_buffers) { TPL_OBJECT_LOCK(&wayland_egl_surface->base); /* Start tracking of this tbm_surface until enqueue */ -- 2.7.4 From 5c4d65253daf0e6f8e1127f15cc0f5e0bedea979 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Thu, 22 Sep 2016 13:05:09 +0900 Subject: [PATCH 11/16] tpl_wayland_egl: Revert commit 'dispatching before checking whether can dequeue or not.' Change-Id: Ic053d5ce9d98ba94d09224541534f11e54575761 Signed-off-by: joonbum.ko --- src/tpl_wayland_egl.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index 5c38105..ff417de 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -869,9 +869,6 @@ __tpl_wayland_egl_surface_wait_dequeuable(tpl_surface_t *surface) surface->display->backend.data; wayland_egl_surface = (tpl_wayland_egl_surface_t *)surface->backend.data; - wl_display_dispatch_queue_pending(wayland_egl_display->wl_dpy, - wayland_egl_display->wl_tbm_event_queue); - if (tbm_surface_queue_can_dequeue(wayland_egl_surface->tbm_queue, 0)) return TPL_ERROR_NONE; -- 2.7.4 From e3f5ff3d9fd36550ff8cf5640c4821754158251f Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Fri, 23 Sep 2016 13:47:45 +0900 Subject: [PATCH 12/16] tpl_wayland_egl: Release locks while tpl-egl waits for vblank done. - If error occurs on tdm_client_handle_events(), the worker thread may be faced the loop of unlimited. - As a result, after the next tpl_surface API is called , the main thread will be faced the dead lock state Change-Id: I7902678dad6120d540563279f35ccd5a344851cc Signed-off-by: joonbum.ko --- src/tpl_wayland_egl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index ff417de..afda052 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -636,14 +636,17 @@ __tpl_wayland_egl_surface_wait_vblank(tpl_surface_t *surface) tpl_wayland_egl_surface_t *wayland_egl_surface = (tpl_wayland_egl_surface_t *)surface->backend.data; + TPL_OBJECT_UNLOCK(surface); do { tdm_err = tdm_client_handle_events(wayland_egl_display->tdm_client); if (tdm_err != TDM_ERROR_NONE) { TPL_ERR("Failed to tdm_client_handle_events."); + break; } } while (wayland_egl_surface->vblank_done == TPL_FALSE); + TPL_OBJECT_LOCK(surface); } static void -- 2.7.4 From 4815b6fe8c02fa2685817c8503eafe1dac26606a Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Fri, 23 Sep 2016 14:04:54 +0900 Subject: [PATCH 13/16] tpl_wayland_egl: Call wl_display_dispatch_queue_pending with wl_tbm_event_queue instead of dispatching with default_queue on __tpl_wayland_egl_surface_fini(). - __tpl_wayland_egl_surface_fini() should call wl_display_dispatch_queue_pending with wl_tbm_event_queue because of the wl_event_queue is seperated default_queue and wl_tbm_event_queue. Change-Id: I7b80e8752e4d056c4ee6fba5467503cd6c73c0db Signed-off-by: joonbum.ko --- src/tpl_wayland_egl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index afda052..8b969f2 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -582,7 +582,8 @@ __tpl_wayland_egl_surface_fini(tpl_surface_t *surface) } wl_display_flush(wayland_egl_display->wl_dpy); - wl_display_dispatch_pending(wayland_egl_display->wl_dpy); + wl_display_dispatch_queue_pending(wayland_egl_display->wl_dpy, + wayland_egl_display->wl_tbm_event_queue); if (wayland_egl_surface->tdm_vblank) { TPL_LOG_B("WL_EGL", -- 2.7.4 From 257c88f515a54cc190f32accd2c78c580a192ed6 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Mon, 26 Sep 2016 10:49:06 +0900 Subject: [PATCH 14/16] tpl_wayland_egl: Fixed some bugs related to wl_display_dispatch_queue_pending. Temporal fix : Change of tbm_surface's reset state. - Currently, tbm_surface's reset state is changed by tpl_surface_validate() and tbm_surface_queue event handler. When we have good solution of changing of tbm_surface's reset state, tpl_surface_validate()'s wayland egl backend should remove changing of tbm_surface's reset state. - Fixed some bugs about ACTIVE/DEACTIVE(queue_flush) events and finally applied wl_display_dispatch_queue_pending(). - Related with below commit. 019e7ff6cade7d660524cb23f7b7c442011a07dd tpl_wayland_egl: dispatching before checking whether can dequeue or not. - The event processing can be delayed in case there are idle buffer in free queue. So, in dequeueable procedure, it has to call wl_display_dispatch_queue_pending before checking whether tbm_surface_queue can dequeue or not. It can process that the events related to 'queue flush' more rapidly. - In future commit, tpl_surface_validate will be modified to suitable one which is related to reset flag. Change-Id: I0584211aed14ef2dd22531074c3b50e8463dd95f Signed-off-by: joonbum.ko --- src/tpl_wayland_egl.c | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index 8b969f2..37c71fd 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -849,17 +849,30 @@ __tpl_wayland_egl_surface_enqueue_buffer(tpl_surface_t *surface, static tpl_bool_t __tpl_wayland_egl_surface_validate(tpl_surface_t *surface) { + tpl_bool_t retval = TPL_TRUE; + TPL_ASSERT(surface); TPL_ASSERT(surface->backend.data); tpl_wayland_egl_surface_t *wayland_egl_surface = (tpl_wayland_egl_surface_t *)surface->backend.data; - if (wayland_egl_surface->resized || - wayland_egl_surface->reset) - return TPL_FALSE; + retval = !(wayland_egl_surface->reset || wayland_egl_surface->resized); + + /* TODO */ + /* Be planning to revise below line in future commits. + - It is under development so that EGL can realize tbm_surface_queue_reset + immediately. + */ + + /* The tbm_surface_queue_flush (which is occured by ACTIVE, DEACTIVE events) + * only occured in __tpl_wayland_egl_surface_wait_dequeable. + * After tpl_surface_dequeue_buffer(), tpl_surface has to inform to frontend + * surface was reset. (retval) + * The reset flag will be set to TPL_FALSE only here after inform it. */ + wayland_egl_surface->reset = TPL_FALSE; - return TPL_TRUE; + return retval; } static tpl_result_t @@ -873,6 +886,9 @@ __tpl_wayland_egl_surface_wait_dequeuable(tpl_surface_t *surface) surface->display->backend.data; wayland_egl_surface = (tpl_wayland_egl_surface_t *)surface->backend.data; + wl_display_dispatch_queue_pending(wayland_egl_display->wl_dpy, + wayland_egl_display->wl_tbm_event_queue); + if (tbm_surface_queue_can_dequeue(wayland_egl_surface->tbm_queue, 0)) return TPL_ERROR_NONE; @@ -937,12 +953,12 @@ __tpl_wayland_egl_surface_dequeue_buffer(tpl_surface_t *surface, format = tbm_surface_queue_get_format(wayland_egl_surface->tbm_queue); tbm_surface_queue_reset(wayland_egl_surface->tbm_queue, width, height, format); - wayland_egl_surface->resized = TPL_FALSE; surface->width = width; surface->height = height; - } - wayland_egl_surface->reset = TPL_FALSE; + wayland_egl_surface->resized = TPL_FALSE; + wayland_egl_surface->reset = TPL_FALSE; + } if (__tpl_wayland_egl_surface_wait_dequeuable(surface)) { TPL_ERR("Failed to wait dequeeable buffer"); @@ -1013,18 +1029,8 @@ __tpl_wayland_egl_surface_dequeue_buffer(tpl_surface_t *surface, /* reset flag is to check whether it is the buffer before tbm_surface_queue is reset or not. */ wayland_egl_buffer->reset = TPL_FALSE; - wayland_egl_surface->current_buffer = tbm_surface; - /* - * Only when the tbm_surface which it dequeued after tbm_surface_queue_dequeue - * was called is not reused one, the following flag 'reset' has to - * initialize to TPL_FALSE. - * - * If this flag initialized before tbm_surface_queue_dequeue, it cause - * the problem that return TPL_FALSE in tpl_surface_validate() in spite of - * EGL already has valid buffer. - */ - wayland_egl_surface->reset = TPL_FALSE; + wayland_egl_surface->current_buffer = tbm_surface; __tpl_wayland_egl_set_wayland_buffer_to_tbm_surface(tbm_surface, wayland_egl_buffer); -- 2.7.4 From 295d42d2ef720b03fc47b86bba76ec1a17df90ce Mon Sep 17 00:00:00 2001 From: Sangjin Lee Date: Fri, 23 Sep 2016 16:04:07 +0900 Subject: [PATCH 15/16] tpl_wayland_egl: Use the tizen_surface_shm protocol for flushing of buffer If the client's state changes the deiconified state, the tizen display server sends tizen_surface_shm_flusher event to client. So, when the client gets the tizen_surface_shm_flusher event from server, client can flush buffers of surface_queue. And the tizen_surface_shm_flush event is dispatched by client's default event queue in tpl_wayland_egl. Change-Id: Icccb55e621fe264bf299d9d8c81e6f5376cee24d --- Makefile | 1 + src/protocol/tizen-surface-client.h | 103 ++++++++++++++++++++ src/protocol/tizen-surface-protocol.c | 36 +++++++ src/tpl_wayland_egl.c | 178 +++++++++++++++++++++++++++++++++- 4 files changed, 315 insertions(+), 3 deletions(-) create mode 100644 src/protocol/tizen-surface-client.h create mode 100644 src/protocol/tizen-surface-protocol.c diff --git a/Makefile b/Makefile index 23e82a8..ee75eba 100644 --- a/Makefile +++ b/Makefile @@ -73,6 +73,7 @@ ifneq ($(call is-feature-enabled,winsys_wl),) TPL_SRCS += $(SRC_DIR)/tpl_wayland_egl.c 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 endif ifneq ($(call is-feature-enabled,winsys_dri2),) diff --git a/src/protocol/tizen-surface-client.h b/src/protocol/tizen-surface-client.h new file mode 100644 index 0000000..6159a82 --- /dev/null +++ b/src/protocol/tizen-surface-client.h @@ -0,0 +1,103 @@ +#ifndef TIZEN_SURFACE_CLIENT_PROTOCOL_H +#define TIZEN_SURFACE_CLIENT_PROTOCOL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "wayland-client.h" + +struct wl_client; +struct wl_resource; + +struct tizen_surface_shm; +struct tizen_surface_shm_flusher; + +extern const struct wl_interface tizen_surface_shm_interface; +extern const struct wl_interface tizen_surface_shm_flusher_interface; + +#define TIZEN_SURFACE_SHM_GET_FLUSHER 0 + +static inline void +tizen_surface_shm_set_user_data(struct tizen_surface_shm *tizen_surface_shm, + void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) tizen_surface_shm, user_data); +} + +static inline void * +tizen_surface_shm_get_user_data(struct tizen_surface_shm *tizen_surface_shm) +{ + return wl_proxy_get_user_data((struct wl_proxy *) tizen_surface_shm); +} + +static inline void +tizen_surface_shm_destroy(struct tizen_surface_shm *tizen_surface_shm) +{ + wl_proxy_destroy((struct wl_proxy *) tizen_surface_shm); +} + +static inline struct tizen_surface_shm_flusher * +tizen_surface_shm_get_flusher(struct tizen_surface_shm *tizen_surface_shm, + struct wl_surface *surface) +{ + struct wl_proxy *id; + + id = wl_proxy_marshal_constructor((struct wl_proxy *) tizen_surface_shm, + TIZEN_SURFACE_SHM_GET_FLUSHER, &tizen_surface_shm_flusher_interface, NULL, + surface); + + return (struct tizen_surface_shm_flusher *) id; +} + +struct tizen_surface_shm_flusher_listener { + /** + * flush - (none) + */ + void (*flush)(void *data, + struct tizen_surface_shm_flusher *tizen_surface_shm_flusher); +}; + +static inline int +tizen_surface_shm_flusher_add_listener(struct tizen_surface_shm_flusher + *tizen_surface_shm_flusher, + const struct tizen_surface_shm_flusher_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) tizen_surface_shm_flusher, + (void (* *)(void)) listener, data); +} + +#define TIZEN_SURFACE_SHM_FLUSHER_DESTROY 0 + +static inline void +tizen_surface_shm_flusher_set_user_data(struct tizen_surface_shm_flusher + *tizen_surface_shm_flusher, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) tizen_surface_shm_flusher, + user_data); +} + +static inline void * +tizen_surface_shm_flusher_get_user_data(struct tizen_surface_shm_flusher + *tizen_surface_shm_flusher) +{ + return wl_proxy_get_user_data((struct wl_proxy *) tizen_surface_shm_flusher); +} + +static inline void +tizen_surface_shm_flusher_destroy(struct tizen_surface_shm_flusher + *tizen_surface_shm_flusher) +{ + wl_proxy_marshal((struct wl_proxy *) tizen_surface_shm_flusher, + TIZEN_SURFACE_SHM_FLUSHER_DESTROY); + + wl_proxy_destroy((struct wl_proxy *) tizen_surface_shm_flusher); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/protocol/tizen-surface-protocol.c b/src/protocol/tizen-surface-protocol.c new file mode 100644 index 0000000..8420280 --- /dev/null +++ b/src/protocol/tizen-surface-protocol.c @@ -0,0 +1,36 @@ +#include +#include +#include "wayland-util.h" + +extern const struct wl_interface tizen_surface_shm_flusher_interface; +extern const struct wl_interface wl_surface_interface; + +static const struct wl_interface *types[] = { + &tizen_surface_shm_flusher_interface, + &wl_surface_interface, +}; + +static const struct wl_message tizen_surface_shm_requests[] = { + { "get_flusher", "no", types + 0 }, +}; + +WL_EXPORT const struct wl_interface tizen_surface_shm_interface = { + "tizen_surface_shm", 1, + 1, tizen_surface_shm_requests, + 0, NULL, +}; + +static const struct wl_message tizen_surface_shm_flusher_requests[] = { + { "destroy", "", types + 0 }, +}; + +static const struct wl_message tizen_surface_shm_flusher_events[] = { + { "flush", "", types + 0 }, +}; + +WL_EXPORT const struct wl_interface tizen_surface_shm_flusher_interface = { + "tizen_surface_shm_flusher", 1, + 1, tizen_surface_shm_flusher_requests, + 1, tizen_surface_shm_flusher_events, +}; + diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index 37c71fd..4ff75bd 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -23,6 +23,7 @@ #include #include #include +#include "protocol/tizen-surface-client.h" /* In wayland, application and compositor create its own drawing buffers. Recommend size is more than 2. */ #define CLIENT_QUEUE_SIZE 3 @@ -38,6 +39,7 @@ struct _tpl_wayland_egl_display { tdm_client *tdm_client; struct wl_display *wl_dpy; struct wl_event_queue *wl_tbm_event_queue; + struct tizen_surface_shm *tizen_surface_shm; /* used for surface buffer_flush */ }; struct _tpl_wayland_egl_surface { @@ -50,6 +52,7 @@ struct _tpl_wayland_egl_surface { tpl_bool_t vblank_done; tpl_list_t *attached_buffers; /* list for tracking [ACQ]~[REL] buffers */ tpl_list_t *dequeued_buffers; /* list for tracking [DEQ]~[ENQ] buffers */ + struct tizen_surface_shm_flusher *tizen_surface_shm_flusher; /* wl_proxy for buffer flush */ }; struct _tpl_wayland_egl_buffer { @@ -67,8 +70,16 @@ static const struct wl_buffer_listener buffer_release_listener; static int tpl_wayland_egl_buffer_key; #define KEY_tpl_wayland_egl_buffer (unsigned long)(&tpl_wayland_egl_buffer_key) -static void __tpl_wayland_egl_buffer_free(tpl_wayland_egl_buffer_t - *wayland_egl_buffer); +static void +__tpl_wayland_egl_display_buffer_flusher_init(tpl_display_t *display); +static void +__tpl_wayland_egl_display_buffer_flusher_fini(tpl_display_t *display); +static void +__tpl_wayland_egl_surface_buffer_flusher_init(tpl_surface_t *surface); +static void +__tpl_wayland_egl_surface_buffer_flusher_fini(tpl_surface_t *surface); +static void +__tpl_wayland_egl_buffer_free(tpl_wayland_egl_buffer_t *wayland_egl_buffer); static TPL_INLINE tpl_wayland_egl_buffer_t * __tpl_wayland_egl_get_wayland_buffer_from_tbm_surface(tbm_surface_h surface) @@ -183,6 +194,7 @@ __tpl_wayland_egl_display_init(tpl_display_t *display) } wayland_egl_display->wl_dpy = wl_dpy; + __tpl_wayland_egl_display_buffer_flusher_init(display); } else { TPL_ERR("Invalid native handle for display."); @@ -241,6 +253,8 @@ __tpl_wayland_egl_display_fini(tpl_display_t *display) if (wayland_egl_display->wl_tbm_event_queue) wl_event_queue_destroy(wayland_egl_display->wl_tbm_event_queue); + __tpl_wayland_egl_display_buffer_flusher_fini(display); + wayland_egl_display->wl_tbm_event_queue = NULL; wayland_egl_display->wl_tbm_client = NULL; wayland_egl_display->tdm_client = NULL; @@ -535,6 +549,8 @@ __tpl_wayland_egl_surface_init(tpl_surface_t *surface) } } + __tpl_wayland_egl_surface_buffer_flusher_init(surface); + TPL_LOG_B("WL_EGL", "[INIT] tpl_surface_t(%p) tpl_wayland_egl_surface_t(%p) tbm_queue(%p)", surface, wayland_egl_surface, @@ -597,6 +613,8 @@ __tpl_wayland_egl_surface_fini(tpl_surface_t *surface) wayland_egl_surface, wl_egl_window, wayland_egl_surface->tbm_queue); tbm_surface_queue_destroy(wayland_egl_surface->tbm_queue); wayland_egl_surface->tbm_queue = NULL; + + __tpl_wayland_egl_surface_buffer_flusher_fini(surface); } /* When surface is destroyed, unreference tbm_surface which tracked by @@ -923,7 +941,8 @@ __tpl_wayland_egl_surface_wait_dequeuable(tpl_surface_t *surface) static tbm_surface_h __tpl_wayland_egl_surface_dequeue_buffer(tpl_surface_t *surface, - uint64_t timeout_ns, tbm_fd *sync_fence) + uint64_t timeout_ns, + tbm_fd *sync_fence) { TPL_ASSERT(surface); TPL_ASSERT(surface->backend.data); @@ -1223,3 +1242,156 @@ __cb_client_window_resize_callback(struct wl_egl_window *wl_egl_window, || (height != tbm_surface_queue_get_height(wayland_egl_surface->tbm_queue))) wayland_egl_surface->resized = TPL_TRUE; } + +void +__cb_resistry_global_callback(void *data, struct wl_registry *wl_registry, + uint32_t name, const char *interface, + uint32_t version) +{ + tpl_wayland_egl_display_t *wayland_egl_display = data; + + if (!strcmp(interface, "tizen_surface_shm")) { + wayland_egl_display->tizen_surface_shm = + wl_registry_bind(wl_registry, + name, + &tizen_surface_shm_interface, + version); + } +} + +void +__cb_resistry_global_remove_callback(void *data, struct wl_registry *wl_registry, + uint32_t name) +{ +} + +static const struct wl_registry_listener registry_listener = { + __cb_resistry_global_callback, + __cb_resistry_global_remove_callback +}; + +static void +__tpl_wayland_egl_display_buffer_flusher_init(tpl_display_t *display) +{ + tpl_wayland_egl_display_t *wayland_egl_display = display->backend.data; + struct wl_registry *registry = NULL; + struct wl_event_queue *queue = NULL; + int ret; + + queue = wl_display_create_queue(wayland_egl_display->wl_dpy); + if (!queue) { + TPL_ERR("Failed to create wl_queue"); + goto fini; + } + + registry = wl_display_get_registry(wayland_egl_display->wl_dpy); + if (!queue) { + TPL_ERR("Failed to create wl_registry"); + goto fini; + } + + wl_proxy_set_queue((struct wl_proxy *)registry, queue); + if (wl_registry_add_listener(registry, ®istry_listener, + wayland_egl_display)) { + TPL_ERR("Failed to wl_registry_add_listener"); + goto fini; + } + + ret = wl_display_roundtrip_queue(wayland_egl_display->wl_dpy, queue); + if (ret) { + TPL_ERR("Failed to wl_display_roundtrip_queue ret:%d, err:%d", ret, errno); + goto fini; + } + + /* set tizen_surface_shm's queue as client's default queue */ + if (wayland_egl_display->tizen_surface_shm) + wl_proxy_set_queue((struct wl_proxy *)wayland_egl_display->tizen_surface_shm, + NULL); + +fini: + if (queue) + wl_event_queue_destroy(queue); + if (registry) + wl_registry_destroy(registry); +} + +static void +__tpl_wayland_egl_display_buffer_flusher_fini(tpl_display_t *display) +{ + tpl_wayland_egl_display_t *wayland_egl_display = display->backend.data; + + if (wayland_egl_display->tizen_surface_shm) { + tizen_surface_shm_destroy(wayland_egl_display->tizen_surface_shm); + wayland_egl_display->tizen_surface_shm = NULL; + } +} + +static void __cb_tizen_surface_shm_flusher_flush_callback(void *data, + struct tizen_surface_shm_flusher *tizen_surface_shm_flusher) +{ + tpl_surface_t *surface = data; + tpl_wayland_egl_surface_t *wayland_egl_surface; + tpl_wayland_egl_display_t *wayland_egl_display; + int ret; + + TPL_CHECK_ON_NULL_RETURN(surface); + wayland_egl_surface = surface->backend.data; + TPL_CHECK_ON_NULL_RETURN(wayland_egl_surface); + TPL_CHECK_ON_NULL_RETURN(surface->display); + wayland_egl_display = surface->display->backend.data; + TPL_CHECK_ON_NULL_RETURN(wayland_egl_display); + + TPL_CHECK_ON_NULL_RETURN(wayland_egl_display->wl_dpy); + TPL_CHECK_ON_NULL_RETURN(wayland_egl_display->wl_tbm_event_queue); + TPL_CHECK_ON_NULL_RETURN(wayland_egl_surface->tbm_queue); + + /*Fist distach panding queue for TPL + - dispatch buffer-release + - dispatch queue flush + */ + ret = wl_display_dispatch_queue_pending(wayland_egl_display->wl_dpy, + wayland_egl_display->wl_tbm_event_queue); + if (ret) { + TPL_ERR("Failed to wl_display_dispatch_queue_pending ret:%d, err:%d", ret, + errno); + return; + } + + tbm_surface_queue_flush(wayland_egl_surface->tbm_queue); +} + +static const struct tizen_surface_shm_flusher_listener + tizen_surface_shm_flusher_listener = { + __cb_tizen_surface_shm_flusher_flush_callback +}; + +static void +__tpl_wayland_egl_surface_buffer_flusher_init(tpl_surface_t *surface) +{ + tpl_wayland_egl_display_t *wayland_egl_display = surface->display->backend.data; + tpl_wayland_egl_surface_t *wayland_egl_surface = surface->backend.data; + struct wl_egl_window *wl_egl_window = (struct wl_egl_window *) + surface->native_handle; + + if (!wayland_egl_display->tizen_surface_shm) + return; + + wayland_egl_surface->tizen_surface_shm_flusher = + tizen_surface_shm_get_flusher(wayland_egl_display->tizen_surface_shm, + wl_egl_window->surface); + tizen_surface_shm_flusher_add_listener( + wayland_egl_surface->tizen_surface_shm_flusher, + &tizen_surface_shm_flusher_listener, surface); +} + +static void +__tpl_wayland_egl_surface_buffer_flusher_fini(tpl_surface_t *surface) +{ + tpl_wayland_egl_surface_t *wayland_egl_surface = surface->backend.data; + + if (wayland_egl_surface->tizen_surface_shm_flusher) { + tizen_surface_shm_flusher_destroy( + wayland_egl_surface->tizen_surface_shm_flusher); + wayland_egl_surface->tizen_surface_shm_flusher = NULL; + } +} -- 2.7.4 From 851992fc72282446ebf374c642af4361b3652f5a Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Wed, 5 Oct 2016 17:44:52 +0900 Subject: [PATCH 16/16] tpl_wayland_egl: Fix misused return value of wl_display_roundtrip_queue() on buffer_flusher_init() - If there are errors on wl_display_roundtrip_queue then it returns values as '-1'. Change-Id: I754df1768b46f0d815af84255255997429eefa7b Signed-off-by: joonbum.ko --- 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 4ff75bd..7119bf2 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -1298,7 +1298,7 @@ __tpl_wayland_egl_display_buffer_flusher_init(tpl_display_t *display) } ret = wl_display_roundtrip_queue(wayland_egl_display->wl_dpy, queue); - if (ret) { + if (ret == -1) { TPL_ERR("Failed to wl_display_roundtrip_queue ret:%d, err:%d", ret, errno); goto fini; } -- 2.7.4