From ff613e3bebbfcb1ca2a9abe376a53559cec56327 Mon Sep 17 00:00:00 2001 From: "deasung.kim" Date: Sat, 24 Sep 2016 18:06:08 +0900 Subject: [PATCH 01/16] tpl_worker_thread: added vblank event added vblank event use tdm client for present mode FIFO Change-Id: I86830125cf9091e634a03375857a7723f7f9cafc --- src/tpl_worker_thread.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++ src/tpl_worker_thread.h | 3 ++ 2 files changed, 137 insertions(+) diff --git a/src/tpl_worker_thread.c b/src/tpl_worker_thread.c index 784bbe6..1c8af05 100644 --- a/src/tpl_worker_thread.c +++ b/src/tpl_worker_thread.c @@ -6,6 +6,7 @@ #include #include #include +#include #define TPL_ERR_ERRNO(f, x...) \ do { int err = errno; char buf[256] = {0,}; \ @@ -27,8 +28,15 @@ static struct { pthread_t worker_id; tpl_list_t surface_list; pthread_mutex_t surface_mutex; + tpl_bool_t support_vblank; } tpl_worker_thread; +tpl_bool_t +__tpl_worker_support_vblank() +{ + return tpl_worker_thread.support_vblank; +} + void __tpl_worker_surface_list_insert(tpl_worker_surface_t *surface) { @@ -135,6 +143,51 @@ __tpl_worker_new_buffer_notify(tpl_worker_surface_t *surface) pthread_mutex_unlock(&tpl_worker_thread.surface_mutex); } +static tpl_bool_t +__tpl_worker_regist_vblank_handler(tdm_client_vblank *tdm_vblank); + +static void +__tpl_worker_cb_vblank(tdm_client_vblank *tdm_vblank, tdm_error error, + unsigned int sequence, unsigned int tv_sec, + unsigned int tv_usec, void *user_data) +{ + tpl_list_node_t *trail; + + if (pthread_mutex_lock(&tpl_worker_thread.surface_mutex) != 0) { + TPL_ERR_ERRNO("surface list mutex lock failed"); + return; + } + + for (trail = __tpl_list_get_front_node(&tpl_worker_thread.surface_list); + trail != NULL; + trail = __tpl_list_node_next(trail)) { + tpl_worker_surface_t *surface; + + surface = __tpl_list_node_get_data(trail); + if (surface->vblank) + surface->vblank(surface->surface, sequence, tv_sec, tv_usec); + } + pthread_mutex_unlock(&tpl_worker_thread.surface_mutex); + + __tpl_worker_regist_vblank_handler(tdm_vblank); +} + +static tpl_bool_t +__tpl_worker_regist_vblank_handler(tdm_client_vblank *tdm_vblank) +{ + tdm_error tdm_err; + + tdm_err = tdm_client_vblank_wait(tdm_vblank, + 1, /* interval */ + __tpl_worker_cb_vblank, /* handler */ + NULL); + if (tdm_err != TDM_ERROR_NONE) { + TPL_ERR ("Failed to tdm_client_wait_vblank. error:%d", tdm_err); + return TPL_FALSE; + } + return TPL_TRUE; +} + static int __tpl_worker_prepare_event_fd(int epoll_fd) { @@ -158,12 +211,79 @@ __tpl_worker_prepare_event_fd(int epoll_fd) return event_fd; } +static tpl_bool_t +__tpl_worker_prepare_vblank(int epoll_fd, tdm_client **ret_client, tdm_client_vblank **ret_vblank) +{ + tdm_error tdm_err; + tdm_client *tdm_client = NULL; + tdm_client_output *tdm_output = NULL; + tdm_client_vblank *tdm_vblank = NULL; + int tdm_fd, ret; + struct epoll_event event; + + TPL_ASSERT(ret_client); + TPL_ASSERT(ret_vblank); + + tdm_client = tdm_client_create(&tdm_err); + if (!tdm_client) { + TPL_ERR("tdm_client_create failed | tdm_err: %d\n", tdm_err); + goto error_cleanup; + } + + tdm_err = tdm_client_get_fd(tdm_client, &tdm_fd); + if (tdm_err != TDM_ERROR_NONE || tdm_fd < 0) { + TPL_ERR("tdm_client_get_fd failed | tdm_err: %d\n", tdm_err); + goto error_cleanup; + } + + tdm_output = tdm_client_get_output(tdm_client, "primary", &tdm_err); + if (!tdm_output) { + TPL_ERR("Failed to get tdm client output. tdm_err(%d)", tdm_err); + goto error_cleanup; + } + + tdm_vblank = tdm_client_output_create_vblank(tdm_output, &tdm_err); + if (!tdm_vblank) { + TPL_ERR("Failed to create tdm vblank output. tdm_err(%d)", tdm_err); + goto error_cleanup; + } + + tdm_client_vblank_set_enable_fake(tdm_vblank, 1); + tdm_client_vblank_set_sync(tdm_vblank, 0); + + if (__tpl_worker_regist_vblank_handler(tdm_vblank) == TPL_FALSE) + goto error_cleanup; + + event.events = EPOLLIN; + event.data.ptr = tdm_client; + ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, tdm_fd, &event); + if (ret != 0) { + TPL_ERR_ERRNO("tdm epoll ctl epoll_fd: %d, tdm_fd: %d.", + epoll_fd, tdm_fd); + goto error_cleanup; + } + + *ret_vblank = tdm_vblank; + *ret_client = tdm_client; + + return TPL_TRUE; + +error_cleanup: + if (tdm_vblank) + tdm_client_vblank_destroy(tdm_vblank); + if (tdm_client) + tdm_client_destroy(tdm_client); + return TPL_FALSE; +} + static void * __tpl_worker_thread_loop(void *arg) { #define EPOLL_MAX_SIZE 100 int ret, epoll_fd = epoll_create(EPOLL_MAX_SIZE); struct epoll_event ev_list[EPOLL_MAX_SIZE]; + tdm_client *tdm_client = NULL; + tdm_client_vblank *tdm_vblank = NULL; if (epoll_fd == -1) { TPL_ERR_ERRNO("epoll create failed"); @@ -175,6 +295,10 @@ __tpl_worker_thread_loop(void *arg) if (tpl_worker_thread.event_fd == -1) goto cleanup; + /* vblank fd */ + if (__tpl_worker_prepare_vblank(epoll_fd, &tdm_client, &tdm_vblank)) + tpl_worker_thread.support_vblank = TPL_TRUE; + while(tpl_worker_thread.running) { int i; tpl_list_node_t *trail; @@ -218,6 +342,10 @@ __tpl_worker_thread_loop(void *arg) break; } } + } else if (ev_list[i].data.ptr == tdm_client) { + /* vblank */ + tdm_client_handle_events(tdm_client); + /* process in __tpl_worker_cb_vblank */ } else { /* draw done */ tpl_worker_surface_t *surface = ev_list[i].data.ptr; @@ -265,6 +393,11 @@ __tpl_worker_thread_loop(void *arg) cleanup: /* thread cleanup */ + if (tdm_vblank) + tdm_client_vblank_destroy(tdm_vblank); + if (tdm_client) + tdm_client_destroy(tdm_client); + close(epoll_fd); close(tpl_worker_thread.event_fd); tpl_worker_thread.event_fd = -1; @@ -280,6 +413,7 @@ __tpl_worker_init(void) * with pthread_once */ tpl_worker_thread.running = 1; + tpl_worker_thread.support_vblank = TPL_FALSE; if (pthread_mutex_init(&tpl_worker_thread.surface_mutex, NULL) != 0) { TPL_ERR_ERRNO("surface list mutex init failed"); diff --git a/src/tpl_worker_thread.h b/src/tpl_worker_thread.h index 3f195d4..08b8bfc 100644 --- a/src/tpl_worker_thread.h +++ b/src/tpl_worker_thread.h @@ -14,10 +14,13 @@ struct __tpl_worker_surface { void (*draw_done)(tpl_surface_t *surface, tbm_surface_h tbm_surface, tpl_result_t result); 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; }; +tpl_bool_t __tpl_worker_support_vblank(); void __tpl_worker_surface_list_insert(tpl_worker_surface_t *surface); void __tpl_worker_surface_list_remove(tpl_worker_surface_t *surface); void __tpl_worker_new_buffer_notify(tpl_worker_surface_t *surface); -- 2.7.4 From 6e8adbdb572bab67283b6bcdcfed2195f093aed6 Mon Sep 17 00:00:00 2001 From: "deasung.kim" Date: Sat, 24 Sep 2016 18:26:46 +0900 Subject: [PATCH 02/16] tpl: tpl_surface_create_swapchain() API is modified for present mode support tpl_display_query_supported_present_modes_from_native_window() is added for querying of present mode - Add enum of tpl_display_present_mode_t it's comments is referred from vulkan present mode comments of vulkan spec. Change-Id: Ief1f322dbb083996d7b77afed7832860dc6e063a --- src/tpl.h | 69 +++++++++++++++++++++++++++++++++++++++++++++++- src/tpl_display.c | 14 ++++++++++ src/tpl_internal.h | 5 +++- src/tpl_surface.c | 4 +-- src/tpl_wayland_vk_wsi.c | 2 +- 5 files changed, 89 insertions(+), 5 deletions(-) diff --git a/src/tpl.h b/src/tpl.h index b4a9fbe..4d9145f 100644 --- a/src/tpl.h +++ b/src/tpl.h @@ -598,14 +598,16 @@ tpl_surface_get_post_interval(tpl_surface_t *surface); * @param width width to the swapchain buffer. * @param height height to the swapchain buffer. * @param buffer_count buffer count to the swapchain. + * @param buffer present mode to the swapchain. * @return TPL_ERROR_NONE if this function is supported and the tpl_surface is valid, TPL_ERROR otherwise. * * @see tpl_surface_get_swapchain_buffers() * @see tpl_surface_destroy_swapchain() + * @see tpl_display_present_mode_t */ tpl_result_t tpl_surface_create_swapchain(tpl_surface_t *surface, tbm_format format, - int width, int height, int buffer_count); + int width, int height, int buffer_count, int present_mode); /** * Destroy a swapchain for the given TPL surface. @@ -726,4 +728,69 @@ tpl_surface_set_frontbuffer_mode(tpl_surface_t *surface, tpl_bool_t set); tpl_result_t tpl_surface_set_reset_cb(tpl_surface_t *surface, void* data, tpl_surface_cb_func_t reset_cb); + +/** + * Present mode types. + * + * @TPL_DISPLAY_MODE_IMMEDIATE_KHR: The presentation engine does not wait for + * a vertical blanking period to update the current image, meaning this + * mode may result in visible tearing. + * No internal queuing of presentation requests is needed, + * as the requests are applied immediately. + * @TPL_DISPLAY_MODE_MAILBOX_KHR: The presentation engine waits for the next + * vertical blanking period to update the current image. + * Tearing cannot be observed. An internal single-entry queue is used + * to hold pending presentation requests. If the queue is full when + * a new presentation request is received, the new request replaces the + * existing entry, and any images associated with the prior entry become + * available for re-use by the application. One request is removed from + * the queue and processed during each vertical blanking period in + * which the queue is non-empty. + * @TPL_DISPLAY_MODE_FIFO_KHR: The presentation engine waits for the next + * vertical blanking period to update the current image. + * Tearing cannot be observed. An internal queue is used to hold pending + * presentation requests. New requests are appended to the end of the queue, + * and one request is removed from the beginning of the queue and processed + * during each vertical blanking period in which the queue is non-empty. + * This is the only value of presentMode that is required to be supported. + * @TPL_DISPLAY_MODE_FIFO_RELAXED_KHR: The presentation engine generally waits + * for the next vertical blanking period to update the current image. + * If a vertical blanking period has already passed since the last update + * of the current image then the presentation engine does not wait for + * another vertical blanking period for the update, meaning this mode may + * result in visible tearing in this case. This mode is useful for reducing + * visual stutter with an application that will mostly present + * a new image before the next vertical blanking period, but may + * occasionally be late, and present a new image just after the next + * vertical blanking period. + * An internal queue is used to hold pending presentation requests. + * New requests are appended to the end of the queue, + * and one request is removed from the beginning of the queue and processed + * during or after each vertical blanking period in which the queue is non-empty. + * default TPL_DISPLAY_PRESENT_MODE_MAILBOX + * + * @see tpl_display_query_supported_present_mode_from_native_window + */ +typedef enum { + TPL_DISPLAY_PRESENT_MODE_MAILBOX = 1, + TPL_DISPLAY_PRESENT_MODE_FIFO = 2, + TPL_DISPLAY_PRESENT_MODE_IMMEDIATE = 4, + TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED = 8, + TPL_DISPLAY_PRESENT_MODE_MAX, +} tpl_display_present_mode_t; + +/** + * Get the present mode capability of the given native window. + * + * @param display display used for query. + * @param window window used for query the present mode capability + * @paran modes pointer to receive present modes bitwise or. + * @return TPL_ERROR_NONE if this function is supported and the window is valid, TPL_ERROR otherwise. + * + * @see tpl_display_present_mode_t + */ +tpl_result_t +tpl_display_query_supported_present_modes_from_native_window(tpl_display_t *display, + tpl_handle_t window, + int *modes); #endif /* TPL_H */ diff --git a/src/tpl_display.c b/src/tpl_display.c index 69295b0..b58da59 100644 --- a/src/tpl_display.c +++ b/src/tpl_display.c @@ -190,3 +190,17 @@ tpl_display_get_buffer_from_native_pixmap(tpl_display_t *display, return display->backend.get_buffer_from_native_pixmap(pixmap); } + +tpl_result_t +tpl_display_query_supported_present_modes_from_native_window(tpl_display_t *display, + tpl_handle_t window, + int *modes) +{ + if (!display->backend.query_window_supported_present_modes) { + TPL_ERR("Backend for display has not been initialized!"); + return TPL_ERROR_INVALID_OPERATION; + } + + return display->backend.query_window_supported_present_modes(display, window, + modes); +} diff --git a/src/tpl_internal.h b/src/tpl_internal.h index 41da0a4..2297db4 100644 --- a/src/tpl_internal.h +++ b/src/tpl_internal.h @@ -74,6 +74,9 @@ struct _tpl_display_backend { tpl_result_t (*query_window_supported_buffer_count)(tpl_display_t *display, tpl_handle_t window, int *min, int *max); + tpl_result_t (*query_window_supported_present_modes)(tpl_display_t *display, + tpl_handle_t window, + int *modes); }; struct _tpl_surface_backend { @@ -94,7 +97,7 @@ struct _tpl_surface_backend { int *buffer_count); tpl_result_t (*create_swapchain)(tpl_surface_t *surface, tbm_format format, int width, - int height, int buffer_count); + int height, int buffer_count, int present_mode); tpl_result_t (*destroy_swapchain)(tpl_surface_t *surface); }; diff --git a/src/tpl_surface.c b/src/tpl_surface.c index 762a597..91aefc1 100644 --- a/src/tpl_surface.c +++ b/src/tpl_surface.c @@ -322,7 +322,7 @@ tpl_surface_get_swapchain_buffers(tpl_surface_t *surface, tpl_result_t tpl_surface_create_swapchain(tpl_surface_t *surface, tbm_format format, - int width, int height, int buffer_count) + int width, int height, int buffer_count, int present_mode) { tpl_result_t ret = TPL_ERROR_INVALID_OPERATION; @@ -347,7 +347,7 @@ tpl_surface_create_swapchain(tpl_surface_t *surface, tbm_format format, TPL_OBJECT_LOCK(surface); ret = surface->backend.create_swapchain(surface, format, width, height, - buffer_count); + buffer_count, present_mode); TPL_OBJECT_UNLOCK(surface); diff --git a/src/tpl_wayland_vk_wsi.c b/src/tpl_wayland_vk_wsi.c index 6f01e1d..68ea5cc 100644 --- a/src/tpl_wayland_vk_wsi.c +++ b/src/tpl_wayland_vk_wsi.c @@ -714,7 +714,7 @@ __tpl_wayland_vk_wsi_draw_wait_fd_get(tpl_surface_t *surface, static tpl_result_t __tpl_wayland_vk_wsi_surface_create_swapchain(tpl_surface_t *surface, tbm_format format, int width, - int height, int buffer_count) + int height, int buffer_count, int present_mode) { tpl_wayland_vk_wsi_surface_t *wayland_vk_wsi_surface = NULL; tpl_wayland_vk_wsi_display_t *wayland_vk_wsi_display = NULL; -- 2.7.4 From d678b7a9d2abb01f633239cccd29dd1c6a39ff63 Mon Sep 17 00:00:00 2001 From: "deasung.kim" Date: Mon, 10 Oct 2016 18:44:13 +0900 Subject: [PATCH 03/16] tpl_worker_thread: change the timing of calling of epoll_ctl_add() on "next draw wait buffer". - before: __tpl_worker_thread_loop() iterates all surfaces before calling of epoll_wait() after : __tpl_worker_thread_loop() calls once __tpl_worker_prepare_draw_wait_buffer after handling of "current surface's buffer draw-done event". Change-Id: Ia8ffb537794eb01c19f4fff33acf40e3071f1184 --- src/tpl_worker_thread.c | 114 ++++++++++++++++++++++++++++-------------------- src/tpl_worker_thread.h | 2 + 2 files changed, 68 insertions(+), 48 deletions(-) diff --git a/src/tpl_worker_thread.c b/src/tpl_worker_thread.c index 1c8af05..69cd6bd 100644 --- a/src/tpl_worker_thread.c +++ b/src/tpl_worker_thread.c @@ -49,6 +49,10 @@ __tpl_worker_surface_list_insert(tpl_worker_surface_t *surface) } surface->draw_wait_buffer = NULL; + + if (pthread_mutex_init(&surface->mutex, NULL) != 0) + TPL_ERR_ERRNO("surface mutex init failed"); + __tpl_list_push_back(&tpl_worker_thread.surface_list, surface); pthread_mutex_unlock(&tpl_worker_thread.surface_mutex); @@ -65,6 +69,23 @@ __tpl_worker_surface_list_remove(tpl_worker_surface_t *surface) __tpl_list_remove_data(&tpl_worker_thread.surface_list, surface, TPL_FIRST, NULL); + if (pthread_mutex_lock(&surface->mutex) != 0) + TPL_ERR_ERRNO("surface list mutex lock failed"); + + if (surface->draw_wait_buffer) { + int wait_fd; + + wait_fd = surface->draw_wait_fd_get(surface->surface, + surface->draw_wait_buffer); + if (wait_fd != -1) + epoll_ctl(tpl_worker_thread.epoll_fd, EPOLL_CTL_DEL, wait_fd, NULL); + surface->draw_wait_buffer = NULL; + } + pthread_mutex_unlock(&surface->mutex); + + if (pthread_mutex_destroy(&surface->mutex) != 0) + TPL_ERR_ERRNO("surface mutex init failed"); + pthread_mutex_unlock(&tpl_worker_thread.surface_mutex); } @@ -134,13 +155,12 @@ __tpl_worker_new_buffer_notify(tpl_worker_surface_t *surface) { TPL_ASSERT(surface->surface); - if (pthread_mutex_lock(&tpl_worker_thread.surface_mutex) != 0) { + if (pthread_mutex_lock(&surface->mutex) != 0) TPL_ERR_ERRNO("surface list mutex lock failed"); - return; - } __tpl_worker_prepare_draw_wait_buffer(tpl_worker_thread.epoll_fd, surface); - pthread_mutex_unlock(&tpl_worker_thread.surface_mutex); + + pthread_mutex_unlock(&surface->mutex); } static tpl_bool_t @@ -164,8 +184,14 @@ __tpl_worker_cb_vblank(tdm_client_vblank *tdm_vblank, tdm_error error, tpl_worker_surface_t *surface; surface = __tpl_list_node_get_data(trail); + + if (pthread_mutex_lock(&surface->mutex) != 0) + TPL_ERR_ERRNO("surface list mutex lock failed"); + if (surface->vblank) surface->vblank(surface->surface, sequence, tv_sec, tv_usec); + + pthread_mutex_unlock(&surface->mutex); } pthread_mutex_unlock(&tpl_worker_thread.surface_mutex); @@ -301,23 +327,6 @@ __tpl_worker_thread_loop(void *arg) while(tpl_worker_thread.running) { int i; - tpl_list_node_t *trail; - - /* set buffer's sync fd and vblank list */ - if (pthread_mutex_lock(&tpl_worker_thread.surface_mutex) != 0) { - TPL_ERR_ERRNO("surface list mutex lock failed"); - goto cleanup; - } - - for (trail = __tpl_list_get_front_node(&tpl_worker_thread.surface_list); - trail != NULL; - trail = __tpl_list_node_next(trail)) { - tpl_worker_surface_t *surface = __tpl_list_node_get_data(trail); - TPL_ASSERT(surface); - - __tpl_worker_prepare_draw_wait_buffer(epoll_fd, surface); - } - pthread_mutex_unlock(&tpl_worker_thread.surface_mutex); /* wait events */ ret = epoll_wait(epoll_fd, ev_list, EPOLL_MAX_SIZE, -1); @@ -332,6 +341,7 @@ __tpl_worker_thread_loop(void *arg) if (ev_list[i].events & EPOLLIN) { int len; uint64_t read_buf; + len = read(tpl_worker_thread.event_fd, &read_buf, sizeof(uint64_t)); if (len < 0) { @@ -349,44 +359,52 @@ __tpl_worker_thread_loop(void *arg) } else { /* draw done */ tpl_worker_surface_t *surface = ev_list[i].data.ptr; - int wait_fd; - int fence_result; if (!(ev_list[i].events & EPOLLIN)) continue; - if (!surface->draw_wait_buffer) { - TPL_WARN("recieve already signaled event\n"); - continue; - } + if (pthread_mutex_lock(&surface->mutex) != 0) + TPL_ERR_ERRNO("surface list mutex lock failed"); - wait_fd = surface->draw_wait_fd_get(surface->surface, surface->draw_wait_buffer); - if (wait_fd == -1) { - if (surface->draw_done) - surface->draw_done(surface->surface, surface->draw_wait_buffer, - TPL_ERROR_INVALID_OPERATION); - surface->draw_wait_buffer = NULL; - continue; - } + if (surface->draw_wait_buffer) { + int wait_fd; - switch (fence_result = tbm_sync_fence_wait(wait_fd, 0)) { - case 0: - TPL_ERR_ERRNO("sync_fence_wait return error."); - case 1: - /* some time recieve event two times */ - epoll_ctl(epoll_fd, EPOLL_CTL_DEL, wait_fd, NULL); + wait_fd = surface->draw_wait_fd_get(surface->surface, + surface->draw_wait_buffer); + if (wait_fd == -1) { 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_INVALID_OPERATION); surface->draw_wait_buffer = NULL; - break; - case -1: - TPL_WARN("sync_fence_wait return timeout."); - break; + } else { + int fence_result; + + switch (fence_result = tbm_sync_fence_wait(wait_fd, 0)) { + case 0: + TPL_ERR_ERRNO("sync_fence_wait return error."); + case 1: + /* some time recieve event two times */ + epoll_ctl(epoll_fd, EPOLL_CTL_DEL, wait_fd, NULL); + if (surface->draw_done) + surface->draw_done(surface->surface, + surface->draw_wait_buffer, + fence_result == 1 ? + TPL_ERROR_NONE : + TPL_ERROR_INVALID_OPERATION); + surface->draw_wait_buffer = NULL; + break; + case -1: + TPL_WARN("sync_fence_wait return timeout."); + break; + } + } + } else { + TPL_WARN("recieve already signaled event\n"); } - /* prepare next buffer in loop start time */ + if (surface->draw_wait_buffer == NULL) + __tpl_worker_prepare_draw_wait_buffer(epoll_fd, surface); + pthread_mutex_unlock(&surface->mutex); } } } diff --git a/src/tpl_worker_thread.h b/src/tpl_worker_thread.h index 08b8bfc..987dbb1 100644 --- a/src/tpl_worker_thread.h +++ b/src/tpl_worker_thread.h @@ -5,6 +5,7 @@ #include #include #include +#include typedef struct __tpl_worker_surface tpl_worker_surface_t; @@ -18,6 +19,7 @@ struct __tpl_worker_surface { unsigned int tv_usec); tbm_surface_h draw_wait_buffer; + pthread_mutex_t mutex; }; tpl_bool_t __tpl_worker_support_vblank(); -- 2.7.4 From 5747d3d3ab316fdaa23d4e1e3083d810ed11b1d1 Mon Sep 17 00:00:00 2001 From: "deasung.kim" Date: Sat, 24 Sep 2016 19:59:45 +0900 Subject: [PATCH 04/16] tpl_wayland_vk_wsi: implement the wsi's present mode implement __tpl_wayland_vk_wsi_display_query_window_supported_present_modes vblank event feature supports FIFO/FIFO_RELAXED modes Change-Id: Id4fafee58ad3b2772449c3fb050ede2c004c52a9 --- src/tpl_wayland_vk_wsi.c | 140 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 136 insertions(+), 4 deletions(-) diff --git a/src/tpl_wayland_vk_wsi.c b/src/tpl_wayland_vk_wsi.c index 68ea5cc..7350f2b 100644 --- a/src/tpl_wayland_vk_wsi.c +++ b/src/tpl_wayland_vk_wsi.c @@ -48,8 +48,15 @@ struct _tpl_wayland_vk_wsi_surface { pthread_mutex_t free_queue_mutex; pthread_cond_t free_queue_cond; + /* tbm_surface list */ + tpl_list_t vblank_list; + pthread_mutex_t vblank_list_mutex; + + tpl_bool_t vblank_done; + tpl_worker_surface_t worker_surface; #endif + int present_mode; }; struct _tpl_wayland_vk_wsi_buffer { @@ -167,7 +174,7 @@ __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.max_buffer = CLIENT_QUEUE_SIZE; display->backend.data = wayland_vk_wsi_display; @@ -270,6 +277,30 @@ __tpl_wayland_vk_wsi_display_query_window_supported_buffer_count( return TPL_ERROR_NONE; } +static tpl_result_t +__tpl_wayland_vk_wsi_display_query_window_supported_present_modes( + tpl_display_t *display, + tpl_handle_t window, int *modes) +{ + tpl_wayland_vk_wsi_display_t *wayland_vk_wsi_display = NULL; + + TPL_ASSERT(display); + TPL_ASSERT(window); + + wayland_vk_wsi_display = (tpl_wayland_vk_wsi_display_t *)display->backend.data; + + if (!wayland_vk_wsi_display) return TPL_ERROR_INVALID_OPERATION; + + 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; +} static tpl_result_t __tpl_wayland_vk_wsi_surface_init(tpl_surface_t *surface) @@ -324,6 +355,7 @@ __tpl_wayland_vk_wsi_surface_commit_buffer(tpl_surface_t *surface, TPL_ASSERT(surface->display); TPL_ASSERT(surface->display->native_handle); TPL_ASSERT(tbm_surface); + TPL_ASSERT(tbm_surface_internal_is_valid(tbm_surface)); struct wl_surface *wl_sfc = NULL; struct wl_callback *frame_callback = NULL; @@ -675,21 +707,46 @@ __tpl_wayland_vk_wsi_process_draw_done(tpl_surface_t *surface, tbm_surface_h tbm_surface, tpl_result_t result) { + tpl_wayland_vk_wsi_surface_t *wayland_vk_wsi_surface = NULL; tpl_wayland_vk_wsi_buffer_t *wayland_vk_wsi_buffer = NULL; - /*TPL_ASSERT(surface);*/ + TPL_ASSERT(surface); TPL_ASSERT(tbm_surface); + TPL_ASSERT(tbm_surface_internal_is_valid(tbm_surface)); + wayland_vk_wsi_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); + TPL_ASSERT(wayland_vk_wsi_surface); TPL_ASSERT(wayland_vk_wsi_buffer); + /* TODO: send buffer to server immediate when server support present mode */ + close(wayland_vk_wsi_buffer->wait_sync); wayland_vk_wsi_buffer->wait_sync = -1; - /* TODO: check present mode and prepare vblank */ - __tpl_wayland_vk_wsi_surface_commit_buffer(surface, tbm_surface); + 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 + (__tpl_wayland_vk_wsi_buffer_remove_from_vblank_list) */ + tbm_surface_internal_ref(tbm_surface); + __tpl_list_push_back(&wayland_vk_wsi_surface->vblank_list, tbm_surface); + pthread_mutex_unlock(&wayland_vk_wsi_surface->vblank_list_mutex); + } else if (wayland_vk_wsi_surface->present_mode == TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED && + wayland_vk_wsi_surface->vblank_done == TPL_FALSE) { + /* if can't process previous vblank event, send buffer immediately */ + pthread_mutex_lock(&wayland_vk_wsi_surface->vblank_list_mutex); + /* unref in tpl list remove callback + (__tpl_wayland_vk_wsi_buffer_remove_from_vblank_list) */ + tbm_surface_internal_ref(tbm_surface); + __tpl_list_push_back(&wayland_vk_wsi_surface->vblank_list, tbm_surface); + wayland_vk_wsi_surface->vblank_done = TPL_TRUE; + pthread_mutex_unlock(&wayland_vk_wsi_surface->vblank_list_mutex); + } else { + __tpl_wayland_vk_wsi_surface_commit_buffer(surface, tbm_surface); + } } static int @@ -709,6 +766,43 @@ __tpl_wayland_vk_wsi_draw_wait_fd_get(tpl_surface_t *surface, return wayland_vk_wsi_buffer->wait_sync; } +static void +__tpl_wayland_vk_wsi_buffer_remove_from_vblank_list(void *data) +{ + tbm_surface_h tbm_surface = data; + tbm_surface_internal_unref(tbm_surface); +} + +static void +__tpl_wayland_vk_wsi_vblank(tpl_surface_t *surface, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec) +{ + tpl_wayland_vk_wsi_surface_t *wayland_vk_wsi_surface; + tbm_surface_h tbm_surface; + + TPL_ASSERT(surface); + + wayland_vk_wsi_surface = + (tpl_wayland_vk_wsi_surface_t *) surface->backend.data; + + TPL_ASSERT(wayland_vk_wsi_surface); + + if ((wayland_vk_wsi_surface->present_mode & + (TPL_DISPLAY_PRESENT_MODE_FIFO | TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED)) == 0) + return; + + pthread_mutex_lock(&wayland_vk_wsi_surface->vblank_list_mutex); + tbm_surface = __tpl_list_pop_front(&wayland_vk_wsi_surface->vblank_list, + __tpl_wayland_vk_wsi_buffer_remove_from_vblank_list); + pthread_mutex_unlock(&wayland_vk_wsi_surface->vblank_list_mutex); + + if (tbm_surface_internal_is_valid(tbm_surface)) { + __tpl_wayland_vk_wsi_surface_commit_buffer(surface, tbm_surface); + wayland_vk_wsi_surface->vblank_done = TPL_TRUE; + } else { + wayland_vk_wsi_surface->vblank_done = TPL_FALSE; + } +} #endif static tpl_result_t @@ -736,6 +830,26 @@ __tpl_wayland_vk_wsi_surface_create_swapchain(tpl_surface_t *surface, return TPL_ERROR_INVALID_PARAMETER; } + /* TODO: check server supported present modes */ + 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; + } +#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; + } + + wayland_vk_wsi_surface->present_mode = present_mode; + wayland_vk_wsi_surface->tbm_queue = tbm_surface_queue_create(buffer_count, width, height, @@ -764,6 +878,13 @@ __tpl_wayland_vk_wsi_surface_create_swapchain(tpl_surface_t *surface, __tpl_wayland_vk_wsi_process_draw_done; wayland_vk_wsi_surface->worker_surface.draw_wait_fd_get = __tpl_wayland_vk_wsi_draw_wait_fd_get; + if ((wayland_vk_wsi_surface->present_mode & + (TPL_DISPLAY_PRESENT_MODE_FIFO | TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED))) { + wayland_vk_wsi_surface->worker_surface.vblank = + __tpl_wayland_vk_wsi_vblank; + pthread_mutex_init(&wayland_vk_wsi_surface->vblank_list_mutex, NULL); + __tpl_list_init(&wayland_vk_wsi_surface->vblank_list); + } __tpl_worker_surface_list_insert(&wayland_vk_wsi_surface->worker_surface); #endif @@ -795,6 +916,15 @@ __tpl_wayland_vk_wsi_surface_destroy_swapchain(tpl_surface_t *surface) } #if USE_WORKER_THREAD == 1 + if ((wayland_vk_wsi_surface->present_mode & + (TPL_DISPLAY_PRESENT_MODE_FIFO | TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED))) { + pthread_mutex_lock(&wayland_vk_wsi_surface->vblank_list_mutex); + __tpl_list_fini(&wayland_vk_wsi_surface->vblank_list, + __tpl_wayland_vk_wsi_buffer_remove_from_vblank_list); + pthread_mutex_unlock(&wayland_vk_wsi_surface->vblank_list_mutex); + pthread_mutex_destroy(&wayland_vk_wsi_surface->vblank_list_mutex); + } + pthread_cond_destroy(&wayland_vk_wsi_surface->free_queue_cond); pthread_mutex_destroy(&wayland_vk_wsi_surface->free_queue_mutex); #endif @@ -849,6 +979,8 @@ __tpl_display_init_backend_wayland_vk_wsi(tpl_display_backend_t *backend) backend->filter_config = __tpl_wayland_vk_wsi_display_filter_config; backend->query_window_supported_buffer_count = __tpl_wayland_vk_wsi_display_query_window_supported_buffer_count; + backend->query_window_supported_present_modes = + __tpl_wayland_vk_wsi_display_query_window_supported_present_modes; } void -- 2.7.4 From 43f3ba0d0ef58d2ccf2a2c69eea9691b50dbf441 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Wed, 12 Oct 2016 17:31:13 +0900 Subject: [PATCH 05/16] tpl_util: Revised in order to use dlog as the default tpl logs. - If set ENABLE_DLOG which is the flag in the spec file with 0, default log change to fprintf. - To distinguish the kind of logs, I added several below font colors. FONT_DEFAULT, FONT_RED(error), FONT_YELLOW(warning), FONT_GREEN(frontend), FONT_BLUE(backend), FONT_MAGENTA(debug) Change-Id: I13f41add53e0e3f3346bc89d4d056623f9bd98d1 Signed-off-by: joonbum.ko --- packaging/libtpl-egl.spec | 2 +- src/tpl_utils.h | 85 ++++++++++++++++++++++++++--------------------- 2 files changed, 49 insertions(+), 38 deletions(-) diff --git a/packaging/libtpl-egl.spec b/packaging/libtpl-egl.spec index 2eb175c..eedabda 100644 --- a/packaging/libtpl-egl.spec +++ b/packaging/libtpl-egl.spec @@ -10,7 +10,7 @@ #TPL FEATURE OPTION %define ENABLE_TTRACE 0 -%define ENABLE_DLOG 0 +%define ENABLE_DLOG 1 %define ENABLE_DEFAULT_LOG 0 %define ENABLE_DEFAULT_DUMP 0 %define ENABLE_OBJECT_HASH_CHECK 1 diff --git a/src/tpl_utils.h b/src/tpl_utils.h index 2b8580b..386174e 100644 --- a/src/tpl_utils.h +++ b/src/tpl_utils.h @@ -55,25 +55,50 @@ extern unsigned int tpl_log_lvl; extern unsigned int tpl_log_initialized; extern unsigned int tpl_dump_lvl; +#define FONT_DEFAULT "\033[0m" /* for reset to default color */ +#define FONT_RED "\033[31m" /* for error logs */ +#define FONT_YELLOW "\033[33m" /* for warning logs */ +#define FONT_GREEN "\033[32m" /* for frontend API logs */ +#define FONT_BLUE "\033[34m" /* for backend logs */ +#define FONT_MAGENTA "\033[35m" /* for debug logs */ + #ifdef DLOG_DEFAULT_ENABLE #define LOG_TAG "TPL" #include -#define TPL_LOG_F(f, x...) LOGD(f, ##x) -#define TPL_LOG_B(b, f, x...) LOGD(f, ##x) -#define TPL_DEBUG(f, x...) LOGD(f, ##x) -#define TPL_ERR(f, x...) LOGE(f, ##x) -#define TPL_WARN(f, x...) LOGW(f, ##x) +#endif + +#ifdef DLOG_DEFAULT_ENABLE +#define tpl_log_f(t, f, x...) LOGD(FONT_GREEN t FONT_DEFAULT " " f, ##x) +#define tpl_log_b(t, f, x...) LOGD(FONT_BLUE t FONT_DEFAULT " " f, ##x) +#define tpl_log_d(t, f, x...) LOGD(FONT_MAGENTA t FONT_DEFAULT " " f, ##x) +#define tpl_log_e(t, f, x...) LOGE(FONT_RED t " " f FONT_DEFAULT, ##x) +#define tpl_log_w(t, f, x...) LOGW(FONT_YELLOW t " " f FONT_DEFAULT, ##x) #else /* DLOG_DEFAULT_ENABLE */ +#define tpl_log_f(t, f, x...) \ + fprintf(stderr, FONT_GREEN t FONT_DEFAULT "[(pid:%d)(%s)] " f "\n", \ + getpid(), __func__, ##x) +#define tpl_log_b(t, f, x...) \ + fprintf(stderr, FONT_BLUE t FONT_DEFAULT "[(pid:%d)(%s)] " f "\n", \ + getpid(), __func__, ##x) +#define tpl_log_d(t, f, x...) \ + fprintf(stderr, FONT_MAGENTA t FONT_DEFAULT "[(pid:%d)(%s)] " f "\n",\ + getpid(), __func__, ##x) +#define tpl_log_e(t, f, x...) \ + fprintf(stderr, FONT_RED t "[(pid:%d)(%s)] " f FONT_DEFAULT "\n", \ + getpid(), __func__, ##x) +#define tpl_log_w(t, f, x...) \ + fprintf(stderr, FONT_YELLOW t "[(pid:%d)(%s)] " f FONT_DEFAULT "\n",\ + getpid(), __func__, ##x) +#endif /* DLOG_DEFAULT_ENABLE */ + + +#define TPL_ERR(f, x...) tpl_log_e("[TPL_ERROR]", f, ##x) +#define TPL_WARN(f, x...) tpl_log_w("[TPL_WARNING]", f, ##x) + #ifdef LOG_DEFAULT_ENABLE -#define TPL_LOG_F(f, x...) \ - fprintf(stderr, "[TPL_F(%d):%s(%d)] " f "\n", \ - getpid(), __func__, __LINE__, ##x) -#define TPL_LOG_B(b, f, x...) \ - fprintf(stderr, "[TPL_" b "(%d):%s(%d)] " f "\n", \ - getpid(), __FILE__, __LINE__, ##x) -#define TPL_DEBUG(f, x...) \ - fprintf(stderr, "[TPL_D(%d):%s(%d)] " f "\n", \ - getpid(), __func__, __LINE__, ##x) +#define TPL_LOG_F(f, x...) tpl_log_f("[TPL_F]", f, ##x) +#define TPL_LOG_B(b, f, x...) tpl_log_b("[TPL_" b "]", f, ##x) +#define TPL_DEBUG(f, x...) tpl_log_d("[TPL_DEBUG]", f, ##x) #else /* LOG_DEFAULT_ENABLE */ /* * TPL_LOG_LEVEL @@ -102,45 +127,31 @@ extern unsigned int tpl_dump_lvl; { \ LOG_INIT(); \ if (tpl_log_lvl > 0 && tpl_log_lvl < 4) \ - fprintf(stderr, "[TPL_F(%d):%s(%d)] " f "\n",\ - getpid(), __func__, __LINE__, ##x); \ + tpl_log_f("[TPL_F]", f, ##x); \ } -#define TPL_LOG_B(b, f, x...) \ - { \ - LOG_INIT(); \ - if (tpl_log_lvl > 1 && tpl_log_lvl < 4) \ - fprintf(stderr, "[TPL_" b "(%d):%s(%d)] " f "\n",\ - getpid(), __FILE__, __LINE__, ##x); \ +#define TPL_LOG_B(b, f, x...) \ + { \ + LOG_INIT(); \ + if (tpl_log_lvl > 1 && tpl_log_lvl < 4) \ + tpl_log_b("[TPL_" b "]", f, ##x); \ } #define TPL_DEBUG(f, x...) \ { \ LOG_INIT(); \ if (tpl_log_lvl > 2) \ - fprintf(stderr, "[TPL_D(%d):%s(%d)] " f "\n",\ - getpid(), __func__, __LINE__, ##x); \ + tpl_log_d("[TPL_DEBUG]", f, ##x); \ } - #endif /* LOG_DEFAULT_ENABLE */ - -#define TPL_ERR(f, x...) \ - fprintf(stderr, \ - "[TPL_ERR(%d):%s(%d)] " f "\n", \ - getpid(), __func__, __LINE__, ##x) - -#define TPL_WARN(f, x...) \ - fprintf(stderr, \ - "[TPL_WARN(%d):%s(%d)] " f "\n", \ - getpid(), __func__, __LINE__, ##x) -#endif /* DLOG_DEFAULT_ENABLE */ #else /* NDEBUG */ #define TPL_LOG_F(f, x...) #define TPL_LOG_B(b, f, x...) #define TPL_DEBUG(f, x...) #define TPL_ERR(f, x...) #define TPL_WARN(f, x...) -#endif /* NDEBUG */ +#endif + #define TPL_CHECK_ON_NULL_RETURN(exp) \ { \ -- 2.7.4 From 44cd41d20691b02ec7ae65bd5099d5e7ceb13297 Mon Sep 17 00:00:00 2001 From: "deasung.kim" Date: Thu, 13 Oct 2016 14:22:44 +0900 Subject: [PATCH 06/16] tpl_worker_thread: remove regist vblank handler. vblank handler raises performance regression. remove regist vblank handler and replace all present mode to MAILBOX. Change-Id: I4a56b77aea2ff67dbe0f09dc322d3219a2c69190 --- src/tpl_wayland_vk_wsi.c | 3 +++ src/tpl_worker_thread.c | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/tpl_wayland_vk_wsi.c b/src/tpl_wayland_vk_wsi.c index 7350f2b..a305762 100644 --- a/src/tpl_wayland_vk_wsi.c +++ b/src/tpl_wayland_vk_wsi.c @@ -830,6 +830,9 @@ __tpl_wayland_vk_wsi_surface_create_swapchain(tpl_surface_t *surface, return TPL_ERROR_INVALID_PARAMETER; } + /* 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 USE_WORKER_THREAD == 1 diff --git a/src/tpl_worker_thread.c b/src/tpl_worker_thread.c index 69cd6bd..e50c755 100644 --- a/src/tpl_worker_thread.c +++ b/src/tpl_worker_thread.c @@ -322,8 +322,10 @@ __tpl_worker_thread_loop(void *arg) goto cleanup; /* vblank fd */ - if (__tpl_worker_prepare_vblank(epoll_fd, &tdm_client, &tdm_vblank)) - tpl_worker_thread.support_vblank = TPL_TRUE; + /* FIXME: vblank has performance problem */ + /*if (__tpl_worker_prepare_vblank(epoll_fd, &tdm_client, &tdm_vblank)) + tpl_worker_thread.support_vblank = TPL_TRUE;*/ + tpl_worker_thread.support_vblank = TPL_TRUE; while(tpl_worker_thread.running) { int i; -- 2.7.4 From e1c9894a2e87232522ef00170ab43ad573b071a2 Mon Sep 17 00:00:00 2001 From: YoungJun Cho Date: Fri, 21 Oct 2016 10:46:58 +0900 Subject: [PATCH 07/16] tpl_surface: narrow the lock section This patch narrows the lock section. The 'tbm_surface' NULL checking routine is not related with tpl surface. Change-Id: Ic547e0784933dcfe1f779aaa2748ebf463f084a8 Signed-off-by: YoungJun Cho --- src/tpl_surface.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/tpl_surface.c b/src/tpl_surface.c index 91aefc1..690f7e6 100644 --- a/src/tpl_surface.c +++ b/src/tpl_surface.c @@ -257,16 +257,14 @@ tpl_surface_enqueue_buffer_with_damage_and_sync(tpl_surface_t *surface, return TPL_ERROR_INVALID_PARAMETER; } - TRACE_BEGIN("TPL:ENQUEUE_BUFFER_WITH_DAMAGE"); - TPL_OBJECT_LOCK(surface); - if (!tbm_surface) { - TPL_OBJECT_UNLOCK(surface); - TRACE_END(); TPL_ERR("tbm surface is invalid."); return TPL_ERROR_INVALID_PARAMETER; } + TRACE_BEGIN("TPL:ENQUEUE_BUFFER_WITH_DAMAGE"); + TPL_OBJECT_LOCK(surface); + if (surface->is_frontbuffer_mode) { if (surface->frontbuffer == tbm_surface) { TPL_OBJECT_UNLOCK(surface); -- 2.7.4 From 5c3980d224b1b31ac3b54be98ca9ba73074ca16b Mon Sep 17 00:00:00 2001 From: YoungJun Cho Date: Fri, 21 Oct 2016 11:00:21 +0900 Subject: [PATCH 08/16] tpl_surface: add missed unlock This patch adds missed unlock for tpl_surface_set_frontbuffer_mode(). Change-Id: Ic5947e526b1df44380fa9b0f8e2a56f8f1170e01 Signed-off-by: YoungJun Cho --- src/tpl_surface.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tpl_surface.c b/src/tpl_surface.c index 690f7e6..a4233f5 100644 --- a/src/tpl_surface.c +++ b/src/tpl_surface.c @@ -391,6 +391,7 @@ tpl_surface_set_frontbuffer_mode(tpl_surface_t *surface, tpl_bool_t set) TPL_OBJECT_LOCK(surface); if (surface->is_frontbuffer_mode == set) { + TPL_OBJECT_UNLOCK(surface); return ret; } else { surface->is_frontbuffer_mode = set; -- 2.7.4 From 6b383c7089167f0fc562f1b86e4c9e160643acc6 Mon Sep 17 00:00:00 2001 From: YoungJun Cho Date: Fri, 21 Oct 2016 16:14:12 +0900 Subject: [PATCH 09/16] tpl_gbm: add backend data initialization for error case This patch adds backend data initialization for error case for __tpl_gbm_surface_init(). Change-Id: I6f2f374c6c6bad7e471670c0be0a12609057c888 Signed-off-by: YoungJun Cho --- src/tpl_gbm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tpl_gbm.c b/src/tpl_gbm.c index 6875db0..42f1a90 100644 --- a/src/tpl_gbm.c +++ b/src/tpl_gbm.c @@ -307,6 +307,7 @@ __tpl_gbm_surface_init(tpl_surface_t *surface) error: free(tpl_gbm_surface); + surface->backend.data = NULL; return TPL_ERROR_INVALID_OPERATION; } -- 2.7.4 From 58b96d5185131e04d298ea56f54d89f54ce17d79 Mon Sep 17 00:00:00 2001 From: YoungJun Cho Date: Mon, 24 Oct 2016 14:28:55 +0900 Subject: [PATCH 10/16] tpl_wayland_egl: clean up codes __tpl_wayland_egl_buffer_set_reset_flag() This patch cleans up code for __tpl_wayland_egl_buffer_set_reset_flag(). There is a possibility to reuse wayland_egl_buffer when tbm_surface is NULL. Change-Id: If1b5580ecea47c435eccec44e0d0c78ae5696162 Signed-off-by: YoungJun Cho --- src/tpl_wayland_egl.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index 0323dfc..e93c66d 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -378,19 +378,19 @@ __cb_client_window_resize_callback(struct wl_egl_window *wl_egl_window, static TPL_INLINE void __tpl_wayland_egl_buffer_set_reset_flag(tpl_list_t *tracking_list) { - tpl_wayland_egl_buffer_t *wayland_egl_buffer = NULL; - tbm_surface_h tbm_surface = NULL; tpl_list_node_t *node = __tpl_list_get_front_node(tracking_list); while (node) { - tbm_surface = (tbm_surface_h) __tpl_list_node_get_data(node); + tbm_surface_h tbm_surface = + (tbm_surface_h)__tpl_list_node_get_data(node); - if (tbm_surface) - wayland_egl_buffer = + if (tbm_surface) { + tpl_wayland_egl_buffer_t *wayland_egl_buffer = __tpl_wayland_egl_get_wayland_buffer_from_tbm_surface(tbm_surface); - if (wayland_egl_buffer) - wayland_egl_buffer->reset = TPL_TRUE; + if (wayland_egl_buffer) + wayland_egl_buffer->reset = TPL_TRUE; + } node = __tpl_list_node_next(node); } -- 2.7.4 From 6e81fe157393c476524c93228b3f73d16fb57fdc Mon Sep 17 00:00:00 2001 From: YoungJun Cho Date: Mon, 24 Oct 2016 15:35:14 +0900 Subject: [PATCH 11/16] tpl_wayland_egl: remove duplicated routine in __cb_tbm_surface_queue_reset_callback() This patch removes duplicated routine in __cb_tbm_surface_queue_reset_callback(). The TPL_CHECK_ON_NULL_RETURN() already checks wayland_egl_surface is NULL or not. Change-Id: Ia17386495cf5fa15210e6e8847ffc7b2e8bf92cc Signed-off-by: YoungJun Cho --- src/tpl_wayland_egl.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index e93c66d..d22f7c4 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -409,8 +409,6 @@ __cb_tbm_surface_queue_reset_callback(tbm_surface_queue_h surface_queue, wayland_egl_surface = (tpl_wayland_egl_surface_t *)surface->backend.data; TPL_CHECK_ON_NULL_RETURN(wayland_egl_surface); - if (!wayland_egl_surface) return; - TPL_LOG_B("WL_EGL", "[QUEUE_RESET_CB] tpl_wayland_egl_surface_t(%p) surface_queue(%p)", data, surface_queue); -- 2.7.4 From e4fcd80ac08ad31ba7265667f9219aacac4e1a6b Mon Sep 17 00:00:00 2001 From: YoungJun Cho Date: Mon, 24 Oct 2016 15:37:31 +0900 Subject: [PATCH 12/16] tpl_surface: add missed lock in tpl_surface_set_reset_cb() This patch adds missed lock in tpl_surface_set_reset_cb(). The 'surface' should be protected. Change-Id: I195018753051d687a1c71762e00568fe4b1fe793 Signed-off-by: YoungJun Cho --- src/tpl_surface.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tpl_surface.c b/src/tpl_surface.c index 91aefc1..00e1d51 100644 --- a/src/tpl_surface.c +++ b/src/tpl_surface.c @@ -417,8 +417,12 @@ tpl_surface_set_reset_cb(tpl_surface_t *surface, void *data, tpl_surface_cb_func return TPL_ERROR_INVALID_PARAMETER; } + TPL_OBJECT_LOCK(surface); + surface->reset_data = data; surface->reset_cb = reset_cb; + TPL_OBJECT_UNLOCK(surface); + return ret; } -- 2.7.4 From 93b934d0321d7fef5880f8e5e9b58389689ca6c6 Mon Sep 17 00:00:00 2001 From: YoungJun Cho Date: Fri, 21 Oct 2016 17:31:27 +0900 Subject: [PATCH 13/16] tpl_wayland_egl: clean up code for __tpl_wayland_egl_display_init() This patch cleans up code for __tpl_wayland_egl_display_init() error routine. There is no case that the wayland_egl_display is NULL and this patch re-arranges fini functions with reverse order. Change-Id: I55f89400f612ea74fb7fa1bdf392aba324bda397 Signed-off-by: YoungJun Cho --- src/tpl_wayland_egl.c | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index 0323dfc..331b330 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -207,25 +207,23 @@ __tpl_wayland_egl_display_init(tpl_display_t *display) return TPL_ERROR_NONE; 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; - wayland_egl_display->wl_dpy = NULL; - - free(wayland_egl_display); - display->backend.data = NULL; - } + if (wayland_egl_display->tdm_client) + tdm_client_destroy(wayland_egl_display->tdm_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_event_queue) + wl_event_queue_destroy(wayland_egl_display->wl_tbm_event_queue); + if (wayland_egl_display->wl_tbm_client) + wayland_tbm_client_deinit(wayland_egl_display->wl_tbm_client); + + 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; + wayland_egl_display->wl_dpy = NULL; + + free(wayland_egl_display); + display->backend.data = NULL; return TPL_ERROR_INVALID_OPERATION; } -- 2.7.4 From 1743e26ce13ad30c2da69aa78d9ccaa76fcc6ab5 Mon Sep 17 00:00:00 2001 From: YoungJun Cho Date: Mon, 24 Oct 2016 11:51:41 +0900 Subject: [PATCH 14/16] tpl_wayland_egl: clean up codes for __tpl_wayland_egl_display_fini() This patch cleans up codes for __tpl_wayland_egl_display_fini().. It re-arranges fini functions with reverse order. Change-Id: Ia5cda03e12e80b01e462b4b7a845bca7f44b0938 Signed-off-by: YoungJun Cho --- src/tpl_wayland_egl.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index 0323dfc..65bb168 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -241,19 +241,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); + __tpl_wayland_egl_display_buffer_flusher_fini(display); if (wayland_egl_display->tdm_client) tdm_client_destroy(wayland_egl_display->tdm_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_event_queue) wl_event_queue_destroy(wayland_egl_display->wl_tbm_event_queue); - __tpl_wayland_egl_display_buffer_flusher_fini(display); + if (wayland_egl_display->wl_tbm_client) + wayland_tbm_client_deinit(wayland_egl_display->wl_tbm_client); wayland_egl_display->wl_tbm_event_queue = NULL; wayland_egl_display->wl_tbm_client = NULL; -- 2.7.4 From d6b559c2fc0b33e1cd46cf20edddf1332330b808 Mon Sep 17 00:00:00 2001 From: YoungJun Cho Date: Mon, 24 Oct 2016 13:37:04 +0900 Subject: [PATCH 15/16] tpl_wayland_egl: clean up codes __tpl_wayland_egl_display_buffer_flusher_init/fini() This patch cleans up codes for __tpl_wayland_egl_display_buffer_flusher_init/fini(). These functions do not use tpl_display_t type display except getting wayland_egl_display. So it seems better to use tpl_wayland_egl_display_t type wayland_egl_display directly. Change-Id: I6d00e564a2d42164c010580cc01aedb59dd4e9c3 Signed-off-by: YoungJun Cho --- src/tpl_wayland_egl.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index 54113ab..f4a6a90 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -35,7 +35,7 @@ typedef struct _tpl_wayland_egl_buffer tpl_wayland_egl_buffer_t; struct _tpl_wayland_egl_display { tbm_bufmgr bufmgr; struct wayland_tbm_client *wl_tbm_client; - struct wl_proxy *wl_tbm; /* wayland_tbm_client proxy */ + 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; @@ -47,7 +47,7 @@ struct _tpl_wayland_egl_surface { tbm_surface_queue_h tbm_queue; tbm_surface_h current_buffer; tpl_bool_t resized; - tpl_bool_t reset; /* TRUE if queue reseted by external */ + tpl_bool_t reset; /* TRUE if queue reseted by external */ tdm_client_vblank *tdm_vblank; /* vblank object for each wl_surface */ tpl_bool_t vblank_done; tpl_list_t *attached_buffers; /* list for tracking [ACQ]~[REL] buffers */ @@ -71,9 +71,11 @@ 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_display_buffer_flusher_init(tpl_display_t *display); +__tpl_wayland_egl_display_buffer_flusher_init( + tpl_wayland_egl_display_t *wayland_egl_display); static void -__tpl_wayland_egl_display_buffer_flusher_fini(tpl_display_t *display); +__tpl_wayland_egl_display_buffer_flusher_fini( + tpl_wayland_egl_display_t *wayland_egl_display); static void __tpl_wayland_egl_surface_buffer_flusher_init(tpl_surface_t *surface); static void @@ -194,7 +196,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); + __tpl_wayland_egl_display_buffer_flusher_init(wayland_egl_display); } else { TPL_ERR("Invalid native handle for display."); @@ -239,7 +241,7 @@ __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); - __tpl_wayland_egl_display_buffer_flusher_fini(display); + __tpl_wayland_egl_display_buffer_flusher_fini(wayland_egl_display); if (wayland_egl_display->tdm_client) tdm_client_destroy(wayland_egl_display->tdm_client); @@ -935,8 +937,7 @@ __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, +__tpl_wayland_egl_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeout_ns, tbm_fd *sync_fence) { TPL_ASSERT(surface); @@ -1257,7 +1258,8 @@ __cb_resistry_global_callback(void *data, struct wl_registry *wl_registry, } void -__cb_resistry_global_remove_callback(void *data, struct wl_registry *wl_registry, +__cb_resistry_global_remove_callback(void *data, + struct wl_registry *wl_registry, uint32_t name) { } @@ -1268,9 +1270,9 @@ static const struct wl_registry_listener registry_listener = { }; static void -__tpl_wayland_egl_display_buffer_flusher_init(tpl_display_t *display) +__tpl_wayland_egl_display_buffer_flusher_init( + tpl_wayland_egl_display_t *wayland_egl_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; @@ -1313,10 +1315,9 @@ fini: } static void -__tpl_wayland_egl_display_buffer_flusher_fini(tpl_display_t *display) +__tpl_wayland_egl_display_buffer_flusher_fini( + tpl_wayland_egl_display_t *wayland_egl_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; @@ -1375,8 +1376,8 @@ static void __cb_tizen_surface_shm_flusher_flush_callback(void *data, } static const struct tizen_surface_shm_flusher_listener - tizen_surface_shm_flusher_listener = { - __cb_tizen_surface_shm_flusher_flush_callback +tizen_surface_shm_flusher_listener = { + __cb_tizen_surface_shm_flusher_flush_callback }; static void -- 2.7.4 From ba7efea5e40ba59e966b29f40385db0951bc4da1 Mon Sep 17 00:00:00 2001 From: YoungJun Cho Date: Tue, 25 Oct 2016 11:26:48 +0900 Subject: [PATCH 16/16] tpl_wayland_egl: clean up code __tpl_wayland_egl_surface_init() This patch cleans up code __tpl_wayland_egl_surface_init(). The original TPL_ASSERT()s are called after using those pointer already. And the 'surface->backend.data' re-initialization code is missed. Change-Id: I34b4d2ac65d57f555b097da77302febffe177a97 Signed-off-by: YoungJun Cho --- src/tpl_wayland_egl.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index d796dd1..8e92f0b 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -466,17 +466,19 @@ __tpl_wayland_egl_surface_create_vblank(tpl_wayland_egl_surface_t static tpl_result_t __tpl_wayland_egl_surface_init(tpl_surface_t *surface) { - tpl_wayland_egl_display_t *wayland_egl_display = - (tpl_wayland_egl_display_t *) surface->display->backend.data; - tpl_wayland_egl_surface_t *wayland_egl_surface = NULL; - - struct wl_egl_window *wl_egl_window = (struct wl_egl_window *) - surface->native_handle; + tpl_wayland_egl_display_t *wayland_egl_display; + tpl_wayland_egl_surface_t *wayland_egl_surface; + struct wl_egl_window *wl_egl_window; TPL_ASSERT(surface); + TPL_ASSERT(surface->display); TPL_ASSERT(surface->type == TPL_SURFACE_TYPE_WINDOW); TPL_ASSERT(surface->native_handle); + wayland_egl_display = + (tpl_wayland_egl_display_t *)surface->display->backend.data; + wl_egl_window = (struct wl_egl_window *)surface->native_handle; + wayland_egl_surface = (tpl_wayland_egl_surface_t *) calloc(1, sizeof(tpl_wayland_egl_surface_t)); if (!wayland_egl_surface) { @@ -517,7 +519,7 @@ __tpl_wayland_egl_surface_init(tpl_surface_t *surface) wl_egl_window->height, TBM_FORMAT_ARGB8888); } else - /*Why wl_surafce is NULL ?*/ + /*Why wl_surface is NULL ?*/ wayland_egl_surface->tbm_queue = tbm_surface_queue_sequence_create( CLIENT_QUEUE_SIZE, wl_egl_window->width, @@ -528,6 +530,7 @@ __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; } @@ -536,7 +539,6 @@ __tpl_wayland_egl_surface_init(tpl_surface_t *surface) __cb_tbm_surface_queue_reset_callback, (void *)surface); - surface->width = wl_egl_window->width; surface->height = wl_egl_window->height; @@ -546,13 +548,12 @@ __tpl_wayland_egl_surface_init(tpl_surface_t *surface) /* 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) { - tpl_result_t tpl_ret = TPL_ERROR_NONE; - tpl_ret = - __tpl_wayland_egl_surface_create_vblank(wayland_egl_surface, - wayland_egl_display->tdm_client); - if (tpl_ret != TPL_ERROR_NONE) { + 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; } } -- 2.7.4