From: Joonbum Ko Date: Wed, 25 Jul 2018 06:40:09 +0000 (+0900) Subject: tpl_wayland_egl: Modified to track committed wl_buffer using global list. X-Git-Tag: accepted/tizen/unified/20180726.064919~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F03%2F185003%2F1;p=platform%2Fcore%2Fuifw%2Flibtpl-egl.git tpl_wayland_egl: Modified to track committed wl_buffer using global list. - If more than one release event is processed for only once committed wl_buffer, the tbm_surface that should not be destroyed can be destroyed. - Save wl_buffer during from wl_surface_commit to wl_buffer_release to a global list called committed_wl_buffers to filter out unwanted release events. [The cases of the problem] 1. Multi-surfaces client. 2. client want to render in iconified status. Change-Id: I09ea2f0ba26b7066695971238d9bed003443e9e4 Signed-off-by: Joonbum Ko --- diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index b2e5fbb..3dc6f43 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -66,6 +66,9 @@ struct _tpl_wayland_egl_buffer { struct wl_proxy *wl_proxy; /* wl_buffer proxy */ }; +static tpl_list_t *committed_wl_buffers = NULL; +static pthread_mutex_t g_list_mutex; + static const struct wl_buffer_listener buffer_release_listener; static int tpl_wayland_egl_buffer_key; @@ -201,6 +204,14 @@ __tpl_wayland_egl_display_init(tpl_display_t *display) goto free_wl_display; } + if (!committed_wl_buffers) { + committed_wl_buffers = __tpl_list_alloc(); + if (!committed_wl_buffers) + TPL_ERR("Failed to allocate committed_wl_buffers list."); + if (pthread_mutex_init(&g_list_mutex, NULL) != 0) + TPL_ERR("g_list_mutex init failed."); + } + wayland_egl_display->wl_dpy = wl_dpy; __tpl_wayland_egl_display_buffer_flusher_init(wayland_egl_display); @@ -285,6 +296,16 @@ __tpl_wayland_egl_display_fini(tpl_display_t *display) free(wayland_egl_display); } + if (pthread_mutex_lock(&g_list_mutex) == 0) { + if (committed_wl_buffers) + __tpl_list_free(committed_wl_buffers, NULL); + committed_wl_buffers = NULL; + pthread_mutex_unlock(&g_list_mutex); + } + + if (pthread_mutex_destroy(&g_list_mutex) != 0) + TPL_ERR("Failed to destroy g_list_mutex"); + display->backend.data = NULL; } @@ -606,9 +627,9 @@ add_reset_cb_fail: tbm_surface_queue_destroy(wayland_egl_surface->tbm_queue); wayland_egl_surface->tbm_queue = NULL; queue_create_fail: - __tpl_list_free(wayland_egl_surface->attached_buffers, NULL); -alloc_dequeue_buffers_fail: __tpl_list_free(wayland_egl_surface->dequeued_buffers, NULL); +alloc_dequeue_buffers_fail: + __tpl_list_free(wayland_egl_surface->attached_buffers, NULL); alloc_attached_buffers_fail: __tpl_object_fini(&wayland_egl_surface->base); tpl_object_init_fail: @@ -662,8 +683,8 @@ __tpl_wayland_egl_surface_fini(tpl_surface_t *surface) /* When surface is destroyed, unreference tbm_surface which tracked by * the list of attached_buffers in order to free the created resources. * (tpl_wayland_egl_buffer_t or wl_buffer) */ + TPL_OBJECT_LOCK(&wayland_egl_surface->base); 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_queue_error_e tsq_err; tbm_surface_h tbm_surface = @@ -680,8 +701,8 @@ __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); } + TPL_OBJECT_UNLOCK(&wayland_egl_surface->base); if (lock_res == 0) pthread_mutex_unlock(&wayland_egl_display->wl_event_mutex); @@ -842,12 +863,21 @@ __tpl_wayland_egl_surface_commit(tpl_surface_t *surface, wayland_egl_buffer->wl_proxy, wayland_egl_buffer->width, wayland_egl_buffer->height); + TPL_OBJECT_LOCK(&wayland_egl_surface->base); 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_OBJECT_UNLOCK(&wayland_egl_surface->base); + + if (pthread_mutex_lock(&g_list_mutex) == 0) { + if (committed_wl_buffers) { + /* Start tracking of wl_buffer which is committed by this wayland_egl_surface */ + __tpl_list_push_back(committed_wl_buffers, + (void *)wayland_egl_buffer->wl_proxy); + } + pthread_mutex_unlock(&g_list_mutex); } /* TPL_WAIT_VBLANK = 1 */ @@ -1411,7 +1441,26 @@ __cb_client_buffer_release_callback(void *data, struct wl_proxy *proxy) tbm_surface_h tbm_surface = NULL; tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE; - TPL_ASSERT(data); + if (proxy && (pthread_mutex_lock(&g_list_mutex) == 0)) { + if (committed_wl_buffers) { + /* Look for the given wl_proxy in the global list(committed_wl_buffers), + * whether its release event has not been processed since wl_surface_commit + * with this wl_proxy */ + tpl_list_node_t *node = + __tpl_list_find_node(committed_wl_buffers, (void *)proxy, + TPL_FIRST, NULL); + + /* If the proxy can not be found in the committed_wl_buffers list, + * it has not been committed or has already been released. + * In this case, it is not an error, but the log will be printed. */ + if (!node) { + TPL_ERR("wl_buffer(%p) already has been released.", proxy); + pthread_mutex_unlock(&g_list_mutex); + return; + } + } + pthread_mutex_unlock(&g_list_mutex); + } tbm_surface = (tbm_surface_h) data; @@ -1432,13 +1481,13 @@ __cb_client_buffer_release_callback(void *data, struct wl_proxy *proxy) if (wayland_egl_buffer->need_to_release) { wayland_egl_surface = wayland_egl_buffer->wayland_egl_surface; + TPL_OBJECT_LOCK(&wayland_egl_surface->base); 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); } + TPL_OBJECT_UNLOCK(&wayland_egl_surface->base); tsq_err = tbm_surface_queue_release(wayland_egl_surface->tbm_queue, tbm_surface); @@ -1449,12 +1498,22 @@ __cb_client_buffer_release_callback(void *data, struct wl_proxy *proxy) wayland_egl_buffer->need_to_release = TPL_FALSE; tbm_surface_internal_unref(tbm_surface); + + if (pthread_mutex_lock(&g_list_mutex) == 0) { + /* This wl_buffer should be removed from committed_wl_buffers list. */ + __tpl_list_remove_data(committed_wl_buffers, (void *)proxy, + TPL_FIRST, NULL); + pthread_mutex_unlock(&g_list_mutex); + } + } else { TPL_WARN("No need to release buffer | wl_buffer(%p) tbm_surface(%p) bo(%d)", proxy, tbm_surface, tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); } } + } else { + TPL_ERR("Failed to process release_event. Invalid tbm_surface(%p)", tbm_surface); } } @@ -1668,8 +1727,9 @@ static void __cb_tizen_surface_shm_flusher_flush_callback(void *data, * Then, client does not need to wait for release_callback to unreference * attached buffer. */ + + TPL_OBJECT_LOCK(&wayland_egl_surface->base); 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_queue_error_e tsq_err; tbm_surface_h tbm_surface = @@ -1683,7 +1743,12 @@ static void __cb_tizen_surface_shm_flusher_flush_callback(void *data, TPL_ERR("Failed to release. tbm_surface(%p) tsq_err(%d)", tbm_surface, tsq_err); } - TPL_OBJECT_UNLOCK(&wayland_egl_surface->base); + } + TPL_OBJECT_UNLOCK(&wayland_egl_surface->base); + + if (pthread_mutex_lock(&g_list_mutex) == 0) { + __tpl_list_fini(committed_wl_buffers, NULL); + pthread_mutex_unlock(&g_list_mutex); } if (lock_res == 0) pthread_mutex_unlock(&wayland_egl_display->wl_event_mutex);