From 21e3ad18aeab01893682bb1e1c2336a7a8d7267e Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Mon, 22 May 2017 14:31:03 +0900 Subject: [PATCH 01/16] tpl_wayland_egl_thread: Deleted an unused handle type. Change-Id: Iabac36d4e22d371263052871b6633185f2d97a26 Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tpl_wayland_egl_thread.h b/src/tpl_wayland_egl_thread.h index 555b754..619f583 100644 --- a/src/tpl_wayland_egl_thread.h +++ b/src/tpl_wayland_egl_thread.h @@ -9,7 +9,6 @@ typedef struct _twe_thread_context twe_thread_context; typedef void* twe_display_h; typedef void* twe_surface_h; -typedef void* twe_buffer_h; twe_thread* twe_thread_create(void); -- 2.7.4 From d601fd09e30ed3222bb0a41d4c86ced24c1edf66 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Wed, 24 May 2017 13:28:34 +0900 Subject: [PATCH 02/16] tpl_wayland_egl_thread: Modified using Wayland API that does not fit in bound version. - wl_surface_damage_buffer -> wl_surface_damage - Since 'wl_surface_damage_buffer' is higher API, it is not nomarlly supported on the current platform. - When wayland client need to use this API, I will add it with version checking syntax. Change-Id: If5d426edc63fb481c637b17f5955949b1b31c1a1 Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index da715db..21f151a 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -844,20 +844,20 @@ _twe_thread_wl_surface_commit(twe_wl_surf_source *surf_source, buf_info->dx, buf_info->dy); if (buf_info->num_rects < 1 || buf_info->rects == NULL) { - wl_surface_damage_buffer(wl_surface, - buf_info->dx, buf_info->dy, - buf_info->width, buf_info->height); + wl_surface_damage(wl_surface, + buf_info->dx, buf_info->dy, + buf_info->width, buf_info->height); } else { int i; for (i = 0; i < buf_info->num_rects; i++) { int inverted_y = buf_info->height - (buf_info->rects[i * 4 + 1] + buf_info->rects[i * 4 + 3]); - wl_surface_damage_buffer(wl_surface, - buf_info->rects[i * 4 + 0], - inverted_y, - buf_info->rects[i * 4 + 2], - buf_info->rects[i * 4 + 3]); + wl_surface_damage(wl_surface, + buf_info->rects[i * 4 + 0], + inverted_y, + buf_info->rects[i * 4 + 2], + buf_info->rects[i * 4 + 3]); } } -- 2.7.4 From 32df6ec3e3f90b8cef33c47afa360dd4537729cc Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Wed, 24 May 2017 14:15:13 +0900 Subject: [PATCH 03/16] tpl_wayland_egl_thread: Modified to do wl_display_read_events only if revent has G_IO_IN. - revent can be G_IO_ERR, in which case do cancel_read and returning FALSE is more correct than returning TRUE for dispatching. Change-Id: I2ccb898a16115cad1f9996e399575a242686eb5d Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index 21f151a..1a0f67c 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -261,7 +261,7 @@ _twe_thread_wl_disp_check(GSource *source) { twe_wl_disp_source *disp_source = (twe_wl_disp_source *)source; - if (disp_source->gfd.revents) { + if (disp_source->gfd.revents & G_IO_IN) { TPL_LOG_T("WL_EGL", "read_events| gsource(%p) wl_display(%p)", source, disp_source->disp); if (wl_display_read_events(disp_source->disp) == -1) -- 2.7.4 From ede7d67933c7836a833d30364879ad40eb51b302 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Wed, 24 May 2017 14:27:12 +0900 Subject: [PATCH 04/16] tpl_wayland_egl_thread: Modified the gsource to validate before the event is processed. - In a short period of time, gsource can be destroyed. - So added exception handling syntax to process event handling only when gsource is valid. Change-Id: I719a7b988a73b44df846b2318b3e96544fb3dea5 Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index 1a0f67c..bfc87d2 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -261,6 +261,11 @@ _twe_thread_wl_disp_check(GSource *source) { twe_wl_disp_source *disp_source = (twe_wl_disp_source *)source; + if (g_source_is_destroyed(source)) { + TPL_ERR("display source(%p) already destroyed.", source); + return FALSE; + } + if (disp_source->gfd.revents & G_IO_IN) { TPL_LOG_T("WL_EGL", "read_events| gsource(%p) wl_display(%p)", source, disp_source->disp); @@ -282,6 +287,11 @@ _twe_thread_wl_disp_dispatch(GSource *source, GSourceFunc cb, gpointer date) { twe_wl_disp_source *disp_source = (twe_wl_disp_source *)source; + if (g_source_is_destroyed(source)) { + TPL_ERR("display source(%p) already destroyed.", source); + return G_SOURCE_REMOVE; + } + if (disp_source->gfd.revents & G_IO_IN) { TPL_LOG_T("WL_EGL", "dispatch| gsource(%p) wl_display(%p)", disp_source, disp_source->disp); @@ -935,6 +945,11 @@ _twe_thread_wl_surface_dispatch(GSource *source, GSourceFunc cb, gpointer date) twe_wl_surf_source *wl_surf_source = (twe_wl_surf_source *)source; GIOCondition cond; + if (g_source_is_destroyed(source)) { + TPL_ERR("surface source(%p) already destroyed.", source); + return G_SOURCE_REMOVE; + } + cond = g_source_query_unix_fd(source, wl_surf_source->tag); if (cond & G_IO_IN) { -- 2.7.4 From 93fa46c0e3708b9f214058da6064659619dffe41 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Wed, 24 May 2017 15:20:48 +0900 Subject: [PATCH 05/16] tpl_wayland_egl_thread: Deleted unnecessary logs that were printed too often. Change-Id: Ibbb51f8a3e4cad25a2096581bd7485e0006517b0 Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index bfc87d2..3323372 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -240,8 +240,6 @@ _twe_thread_wl_disp_prepare(GSource *source, gint *time) { twe_wl_disp_source *disp_source = (twe_wl_disp_source *)source; - TPL_LOG_T("WL_EGL", "prepare| gsource(%p) wl_display(%p)", - source, disp_source->disp); while (wl_display_prepare_read_queue(disp_source->disp, disp_source->ev_queue) != 0) { if (wl_display_dispatch_queue_pending(disp_source->disp, @@ -267,15 +265,11 @@ _twe_thread_wl_disp_check(GSource *source) } if (disp_source->gfd.revents & G_IO_IN) { - TPL_LOG_T("WL_EGL", "read_events| gsource(%p) wl_display(%p)", - source, disp_source->disp); if (wl_display_read_events(disp_source->disp) == -1) _twe_display_print_err(disp_source, "read_event."); return TRUE; } else { - TPL_LOG_T("WL_EGL", "cancel_read| gsource(%p) wl_display(%p)", - source, disp_source->disp); wl_display_cancel_read(disp_source->disp); } @@ -293,8 +287,6 @@ _twe_thread_wl_disp_dispatch(GSource *source, GSourceFunc cb, gpointer date) } if (disp_source->gfd.revents & G_IO_IN) { - TPL_LOG_T("WL_EGL", "dispatch| gsource(%p) wl_display(%p)", - disp_source, disp_source->disp); if (wl_display_dispatch_queue_pending(disp_source->disp, disp_source->ev_queue) == -1) { _twe_display_print_err(disp_source, "dispatch_queue_pending"); @@ -956,8 +948,6 @@ _twe_thread_wl_surface_dispatch(GSource *source, GSourceFunc cb, gpointer date) ssize_t s; uint64_t u; - TPL_LOG_T("WL_EGL", "dispatch| gsource(%p) read event_fd(%d)", - wl_surf_source, wl_surf_source->event_fd); s = read(wl_surf_source->event_fd, &u, sizeof(uint64_t)); if (s != sizeof(uint64_t)) TPL_ERR("Failed to read from event_fd(%d)", -- 2.7.4 From bf1b4fdd0d3879603be348004adaba32d4df5f12 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Wed, 24 May 2017 15:49:53 +0900 Subject: [PATCH 06/16] tpl_wayland_egl_thread: Fixed to do acquire_and_commit until there was no tbm_surface to be consumed. - One or more tbm_surfaces that are not consumed can be in tbm_surface_queue because event_fd has two writes but read may be processed only once. Change-Id: Iae3fa749f411e1ce957317a1b1d9085948a22e55 Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 46 ++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index 3323372..e467a77 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -900,35 +900,35 @@ _twe_thread_wl_surface_acquire_and_commit(twe_wl_surf_source *surf_source) tbm_surface_h tbm_surface = NULL; tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE; - if (!tbm_surface_queue_can_acquire(surf_source->tbm_queue, 0)) { - TPL_ERR("Received acquirable event, but nothing to commit."); - return; - } + /* One or more tbm_surfaces that are not consumed can be in tbm_surface_queue + * because event_fd has two writes but read may be processed only once. + */ + while (tbm_surface_queue_can_acquire(surf_source->tbm_queue, 0)) { + tsq_err = tbm_surface_queue_acquire(surf_source->tbm_queue, &tbm_surface); + if (!tbm_surface || tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) { + TPL_ERR("Failed to acquire from tbm_queue(%p)", + surf_source->tbm_queue); + return; + } - tsq_err = tbm_surface_queue_acquire(surf_source->tbm_queue, &tbm_surface); - if (!tbm_surface || tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) { - TPL_ERR("Failed to acquire from tbm_queue(%p)", - surf_source->tbm_queue); - return; - } + tbm_surface_internal_ref(tbm_surface); - tbm_surface_internal_ref(tbm_surface); + TPL_LOG_T("WL_EGL", "[ACQ] tbm_surface(%p) bo(%d)", + tbm_surface, + tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); - TPL_LOG_T("WL_EGL", "[ACQ] tbm_surface(%p) bo(%d)", - tbm_surface, - tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); + while (!surf_source->vblank_done) { + tdm_error tdm_err = TDM_ERROR_NONE; - while (!surf_source->vblank_done) { - tdm_error tdm_err = TDM_ERROR_NONE; - - tdm_err = tdm_client_handle_events(_twe_ctx->tdm_client); - if (tdm_err != TDM_ERROR_NONE) { - TPL_ERR("Failed to tdm_client_handle_events."); - break; + tdm_err = tdm_client_handle_events(_twe_ctx->tdm_client); + if (tdm_err != TDM_ERROR_NONE) { + TPL_ERR("Failed to tdm_client_handle_events."); + break; + } } - } - _twe_thread_wl_surface_commit(surf_source, tbm_surface); + _twe_thread_wl_surface_commit(surf_source, tbm_surface); + } } static gboolean -- 2.7.4 From 2261c2f859630549ebb65388f900760973fe97e8 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Thu, 25 May 2017 10:20:17 +0900 Subject: [PATCH 07/16] tpl_wayland_egl_thread: Changed the order of surface fini. Change-Id: I191044552c521a435eaf83fa31fecc1615643efd Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index e467a77..d363d18 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -964,21 +964,6 @@ _twe_thread_wl_surface_finalize(GSource *source) { twe_wl_surf_source *surf_source = (twe_wl_surf_source *)source; - if (surf_source->committed_buffers) { - TPL_OBJECT_LOCK(&surf_source->obj); - while (!__tpl_list_is_empty(surf_source->committed_buffers)) { - tbm_surface_h tbm_surface = - (tbm_surface_h)__tpl_list_pop_front( - surf_source->committed_buffers, - NULL); - tbm_surface_internal_unref(tbm_surface); - } - - __tpl_list_free(surf_source->committed_buffers, NULL); - surf_source->committed_buffers = NULL; - TPL_OBJECT_UNLOCK(&surf_source->obj); - } - __tpl_object_fini(&surf_source->obj); g_source_remove_unix_fd(source, surf_source->tag); @@ -1248,6 +1233,21 @@ twe_surface_del(twe_surface_h twe_surface) __tpl_list_free(surf_source->in_use_buffers, NULL); surf_source->in_use_buffers = NULL; + if (surf_source->committed_buffers) { + TPL_OBJECT_LOCK(&surf_source->obj); + while (!__tpl_list_is_empty(surf_source->committed_buffers)) { + tbm_surface_h tbm_surface = + (tbm_surface_h)__tpl_list_pop_front( + surf_source->committed_buffers, + NULL); + tbm_surface_internal_unref(tbm_surface); + } + + __tpl_list_free(surf_source->committed_buffers, NULL); + surf_source->committed_buffers = NULL; + TPL_OBJECT_UNLOCK(&surf_source->obj); + } + _twe_surface_buffer_flusher_fini(surf_source); if (surf_source->tbm_queue) { -- 2.7.4 From c3062c0e0f8d5cf1828c8defbb864bd382ae76ec Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Thu, 25 May 2017 13:27:16 +0900 Subject: [PATCH 08/16] tpl_wayland_egl_thread: Added APIs for thread safety during event processing. - If a new event is handled in the worker_thread while processing the dequeue process in the main thread, it can cause problems. - Thread safety must be guaranteed in the part that uses the same resource (tbm_surface_queue) between threads. - Added APIs twe_display_lock / twe_display_unlock Change-Id: I3cd405147a196ced800faefec80e559b15693673 Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 43 ++++++++++++++++++++++++++++++++++++++++--- src/tpl_wayland_egl_thread.h | 6 ++++++ 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index d363d18..d9f0884 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -50,6 +50,7 @@ struct _twe_wl_disp_source { struct wayland_tbm_client *wl_tbm_client; struct tizen_surface_shm *tss; /* used for surface buffer_flush */ twe_thread *thread; + tpl_object_t obj; /* TODO : surface list */ }; @@ -286,6 +287,7 @@ _twe_thread_wl_disp_dispatch(GSource *source, GSourceFunc cb, gpointer date) return G_SOURCE_REMOVE; } + TPL_OBJECT_LOCK(&disp_source->obj); if (disp_source->gfd.revents & G_IO_IN) { if (wl_display_dispatch_queue_pending(disp_source->disp, disp_source->ev_queue) == -1) { @@ -294,6 +296,7 @@ _twe_thread_wl_disp_dispatch(GSource *source, GSourceFunc cb, gpointer date) } wl_display_flush(disp_source->disp); + TPL_OBJECT_UNLOCK(&disp_source->obj); return G_SOURCE_CONTINUE; } @@ -303,12 +306,16 @@ _twe_thread_wl_disp_finalize(GSource *source) { twe_wl_disp_source *disp_source = (twe_wl_disp_source *)source; + TPL_OBJECT_LOCK(&disp_source->obj); if (wl_display_dispatch_queue_pending(disp_source->disp, disp_source->ev_queue) == -1) { _twe_display_print_err(disp_source, "dispatch_queue_pending"); } wl_event_queue_destroy(disp_source->ev_queue); + TPL_OBJECT_UNLOCK(&disp_source->obj); + + __tpl_object_fini(&disp_source->obj); TPL_LOG_T("WL_EGL", "finalize| wl_event_queue(%p)", disp_source->ev_queue); @@ -474,6 +481,7 @@ twe_display_add(twe_thread* thread, struct wl_display *display) source->gfd.fd = wl_display_get_fd(display); source->gfd.events = G_IO_IN | G_IO_ERR; source->gfd.revents = 0; + __tpl_object_init(&source->obj, TPL_OBJECT_DISPLAY, NULL); _twe_display_shm_init(source); @@ -518,6 +526,30 @@ twe_display_del(twe_display_h twe_display) return TPL_ERROR_NONE; } +tpl_result_t +twe_display_lock(twe_display_h display) +{ + twe_wl_disp_source *disp_source = (twe_wl_disp_source *)display; + if (!disp_source || g_source_is_destroyed(&disp_source->gsource)) { + TPL_ERR("Invalid parameter. display(%p)", display); + return TPL_ERROR_INVALID_PARAMETER; + } + + return TPL_OBJECT_LOCK(&disp_source->obj); +} + +void +twe_display_unlock(twe_display_h display) +{ + twe_wl_disp_source *disp_source = (twe_wl_disp_source *)display; + if (!disp_source || g_source_is_destroyed(&disp_source->gsource)) { + TPL_ERR("Invalid parameter. display(%p)", display); + return; + } + + TPL_OBJECT_UNLOCK(&disp_source->obj); +} + static void __cb_resize_callback(struct wl_egl_window *wl_egl_window, void *private) { @@ -588,12 +620,14 @@ static void __cb_tss_flusher_flush_callback(void *data, - dispatch buffer-release - dispatch queue flush */ + TPL_OBJECT_LOCK(&disp_source->obj); ret = wl_display_dispatch_queue_pending(disp_source->disp, disp_source->ev_queue); if (ret == -1) { _twe_display_print_err(disp_source, "dispatch_queue_pending"); return; } + TPL_OBJECT_UNLOCK(&disp_source->obj); tbm_surface_queue_flush(surf_source->tbm_queue); @@ -1222,9 +1256,6 @@ twe_surface_del(twe_surface_h twe_surface) return TPL_ERROR_INVALID_PARAMETER; } - TPL_LOG_T("WL_EGL", "twe_surface(%p) wl_egl_window(%p) wl_surface(%p)", - surf_source, surf_source->wl_egl_window, surf_source->surf); - /* Should be waited until all in_use_buffers has been retrieved. */ while (!__tpl_list_is_empty(surf_source->in_use_buffers)) { sched_yield(); @@ -1233,6 +1264,7 @@ twe_surface_del(twe_surface_h twe_surface) __tpl_list_free(surf_source->in_use_buffers, NULL); surf_source->in_use_buffers = NULL; + TPL_OBJECT_LOCK(&disp_source->obj); if (surf_source->committed_buffers) { TPL_OBJECT_LOCK(&surf_source->obj); while (!__tpl_list_is_empty(surf_source->committed_buffers)) { @@ -1263,9 +1295,14 @@ twe_surface_del(twe_surface_h twe_surface) /* TODO : surf_source will be removed from surfaces list in disp_source */ + TPL_LOG_T("WL_EGL", "twe_surface(%p) wl_egl_window(%p) wl_surface(%p)", + surf_source, surf_source->wl_egl_window, surf_source->surf); + surf_source->wl_egl_window = NULL; surf_source->surf = NULL; + TPL_OBJECT_UNLOCK(&disp_source->obj); + g_source_destroy(&surf_source->gsource); g_source_unref(&surf_source->gsource); diff --git a/src/tpl_wayland_egl_thread.h b/src/tpl_wayland_egl_thread.h index 619f583..424a539 100644 --- a/src/tpl_wayland_egl_thread.h +++ b/src/tpl_wayland_egl_thread.h @@ -22,6 +22,12 @@ twe_display_add(twe_thread* thread, struct wl_display *display); tpl_result_t twe_display_del(twe_display_h display); +tpl_result_t +twe_display_lock(twe_display_h display); + +void +twe_display_unlock(twe_display_h display); + twe_surface_h twe_surface_add(twe_thread* thread, twe_display_h twe_display, -- 2.7.4 From afdfb5ee98fda86914294256c2e0648cdec88ccd Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Mon, 12 Jun 2017 17:35:18 +0900 Subject: [PATCH 09/16] tpl_wayland_egl_thread: Cleaned up the codes for creating/deleting/dipatching tdm_source. - It has been modified to control tdm resources only within threads to prevent wl_display errors due to thread differences. tdm_source (gsource) - tdm_source will be created when before loop running start. tdm_client_vblank object - vblank object of twe_surf_source will be created newly when surface commit. If both tdm_source and vblank object failed to create, surface commit will fall back to TPL_WAIT_VBLANK disabled mode. Change-Id: I417b36e7f5e8f5964af267a0ecae83899b5a3c2d Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 201 +++++++++++++++++++++++++++++-------------- 1 file changed, 136 insertions(+), 65 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index d9f0884..fb6f859 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -24,6 +24,7 @@ static int buffer_info_key; typedef struct _twe_wl_disp_source twe_wl_disp_source; typedef struct _twe_wl_surf_source twe_wl_surf_source; typedef struct _twe_wl_buffer_info twe_wl_buffer_info; +typedef struct _twe_tdm_source twe_tdm_source; struct _twe_thread_context { int ref_cnt; @@ -31,10 +32,7 @@ struct _twe_thread_context { GThread *twe_thread; GMainLoop *twe_loop; - /*TDM*/ - tdm_client *tdm_client; - int tdm_fd; - GSource *tdm_gsource; + twe_tdm_source *tdm_source; }; struct _twe_thread { @@ -42,6 +40,13 @@ struct _twe_thread { /* TODO : display list */ }; +struct _twe_tdm_source { + GSource gsource; + gpointer tag; + tdm_client *tdm_client; + int tdm_fd; +}; + struct _twe_wl_disp_source { GSource gsource; GPollFD gfd; @@ -62,11 +67,11 @@ struct _twe_wl_surf_source { struct wl_egl_window *wl_egl_window; int rotation; tpl_bool_t rotation_capability; - tpl_bool_t vblank_done; tpl_object_t obj; /* for mutex lock */ tpl_list_t *committed_buffers; tpl_list_t *in_use_buffers; tdm_client_vblank *vblank; + tpl_bool_t vblank_done; struct tizen_surface_shm_flusher *tss_flusher; tbm_surface_queue_h tbm_queue; twe_wl_disp_source *disp_source; @@ -85,11 +90,30 @@ struct _twe_wl_buffer_info { }; static twe_thread_context *_twe_ctx; +static twe_tdm_source * +_twe_thread_tdm_source_create(void); static gpointer _twe_thread_loop(gpointer data) { twe_thread_context *ctx = data; + char *env = getenv("TPL_WAIT_VBLANK"); + + if (env == NULL || atoi(env)) { + twe_tdm_source *tdm_source = _twe_thread_tdm_source_create(); + + if (tdm_source) { + g_source_attach(&tdm_source->gsource, + g_main_loop_get_context(ctx->twe_loop)); + g_source_unref(&tdm_source->gsource); + } + + _twe_ctx->tdm_source = tdm_source; + + if (!ctx->tdm_source) { + TPL_WARN("Failed to create tdm_source. TPL_WAIT_VLANK:DISABLED"); + } + } g_main_loop_run(ctx->twe_loop); @@ -97,45 +121,115 @@ _twe_thread_loop(gpointer data) } static gboolean -_twe_thread_tdm_source_dispatch(gpointer user_data) +_twe_thread_tdm_source_dispatch(GSource *source, GSourceFunc cb, gpointer data) { - twe_thread_context* context = user_data; + twe_tdm_source *tdm_source = (twe_tdm_source *)source; tdm_error tdm_err; + GIOCondition cond; - TPL_LOG_T("WL_EGL", "tdm_dispatch| tdm_client(%p)", context->tdm_client); - tdm_err = tdm_client_handle_events(context->tdm_client); - if (tdm_err) { - TPL_ERR("TDM_ERROR:%d context:%p, tdm_cleint:%p\n", tdm_err, context, context->tdm_client); + if (!source || g_source_is_destroyed(source)) { + TPL_ERR("TDM source(%p) already destroyed.", source); return G_SOURCE_REMOVE; } + cond = g_source_query_unix_fd(source, tdm_source->tag); + + if (cond & G_IO_IN) { + tdm_err = tdm_client_handle_events(tdm_source->tdm_client); + if (tdm_err != TDM_ERROR_NONE) { + TPL_ERR("TDM_ERROR:%d tdm_client:%p\n", + tdm_err, tdm_source->tdm_client); + return G_SOURCE_REMOVE; + } + } + return G_SOURCE_CONTINUE; } static void -_twe_thread_tdm_source_destroy(gpointer user_data) +_twe_thread_tdm_source_finalize(GSource *source) { - twe_thread_context* context = user_data; + twe_tdm_source *tdm_source = (twe_tdm_source *)source; + + TPL_LOG_T("WL_EGL", "tdm_destroy| tdm_source(%p) tdm_client(%p)", + tdm_source, tdm_source->tdm_client); - TPL_LOG_T("WL_EGL", "tdm_destroy| tdm_gsource(%p) tdm_client(%p)", - context->tdm_gsource, context->tdm_client); - g_source_destroy(context->tdm_gsource); - g_source_unref(context->tdm_gsource); - context->tdm_gsource = NULL; + if (tdm_source->tdm_client) { + tdm_client_destroy(tdm_source->tdm_client); + tdm_source->tdm_client = NULL; + } - tdm_client_destroy(context->tdm_client); - context->tdm_client = NULL; + tdm_source->tdm_fd = -1; +} + +static GSourceFuncs _twe_tdm_funcs = { + .prepare = NULL, + .check = NULL, + .dispatch = _twe_thread_tdm_source_dispatch, + .finalize = _twe_thread_tdm_source_finalize, +}; + +static twe_tdm_source * +_twe_thread_tdm_source_create(void) +{ + twe_tdm_source *tdm_source = NULL; + tdm_client *client = NULL; + int tdm_fd = -1; + tdm_error tdm_err = TDM_ERROR_NONE; + + client = tdm_client_create(&tdm_err); + if (!client || tdm_err != TDM_ERROR_NONE) { + TPL_ERR("TDM_ERROR:%d Failed to create tdm_client\n", tdm_err); + return NULL; + } + + tdm_err = tdm_client_get_fd(client, &tdm_fd); + if (tdm_fd < 0 || tdm_err != TDM_ERROR_NONE) { + TPL_ERR("TDM_ERROR:%d Failed to get tdm_client fd\n", tdm_err); + tdm_client_destroy(client); + return NULL; + } + + tdm_source = (twe_tdm_source *)g_source_new(&_twe_tdm_funcs, + sizeof(twe_tdm_source)); + if (!tdm_source) { + TPL_ERR("Failed to create tdm_gsource\n"); + tdm_client_destroy(client); + return NULL; + } + + tdm_source->tdm_client = client; + tdm_source->tdm_fd = tdm_fd; + tdm_source->tag = g_source_add_unix_fd(&tdm_source->gsource, + tdm_fd, + G_IO_IN); + + TPL_LOG_T("WL_EGL", "TPL_WAIT_VBLANK:DEFAULT_ENABLED"); + TPL_LOG_T("WL_EGL", "tdm_source(%p) tdm_client(%p) tdm_fd(%d)", + tdm_source, client, tdm_fd); + + return tdm_source; +} + +static void +_twe_thread_tdm_source_destroy(twe_tdm_source *tdm_source) +{ + if (!tdm_source || g_source_is_destroyed(&tdm_source->gsource)) { + TPL_ERR("TDM source(%p) already destroyed.", tdm_source); + return; + } + + g_source_destroy(&tdm_source->gsource); + g_source_unref(&tdm_source->gsource); } twe_thread* twe_thread_create(void) { twe_thread *thread; - char *env = getenv("TPL_WAIT_VBLANK"); if (!_twe_ctx) { GMainContext *context; - tdm_error tdm_err = TDM_ERROR_NONE; _twe_ctx = calloc(1, sizeof(twe_thread_context)); context = g_main_context_new(); @@ -144,42 +238,6 @@ twe_thread_create(void) _twe_ctx->twe_thread = g_thread_new("twe_thread", _twe_thread_loop, _twe_ctx); - - if (env == NULL || atoi(env)) { - /*Connect to tdm server*/ - _twe_ctx->tdm_client = tdm_client_create(&tdm_err); - if (!_twe_ctx->tdm_client) { - TPL_ERR("Failed to create tdm_client\n"); - } - - TPL_LOG_T("WL_EGL", "TPL_WAIT_VBLANK:DEFAULT_ENABLED"); - - _twe_ctx->tdm_fd = tdm_client_get_fd(_twe_ctx->tdm_client, - &_twe_ctx->tdm_fd); - if (_twe_ctx->tdm_fd < 0) { - TPL_ERR("Failed to get tdm_client fd\n"); - tdm_client_destroy(_twe_ctx->tdm_client); - } else { - _twe_ctx->tdm_gsource = g_unix_fd_source_new(_twe_ctx->tdm_fd, - G_IO_IN); - if (!_twe_ctx->tdm_gsource) { - TPL_ERR("Failed to create tdm_gsource\n"); - tdm_client_destroy(_twe_ctx->tdm_client); - } - - g_source_set_callback(_twe_ctx->tdm_gsource, - _twe_thread_tdm_source_dispatch, - NULL, - NULL); - g_source_attach(_twe_ctx->tdm_gsource, - g_main_loop_get_context(_twe_ctx->twe_loop)); - TPL_LOG_T("WL_EGL", "tdm g_source(%p) attached to twe_loop(%p)", - _twe_ctx->tdm_gsource, _twe_ctx->twe_loop); - } - } else { - TPL_LOG_T("WL_EGL", "TPL_WAIT_VBLANK:DISABLED"); - } - } thread = calloc(1, sizeof(twe_thread)); @@ -196,8 +254,9 @@ twe_thread_destroy(twe_thread* thread) thread->ctx->ref_cnt--; if (thread->ctx->ref_cnt == 0) { - if (thread->ctx->tdm_gsource) { - _twe_thread_tdm_source_destroy(thread->ctx); + if (thread->ctx->tdm_source) { + _twe_thread_tdm_source_destroy(thread->ctx->tdm_source); + thread->ctx->tdm_source = NULL; } g_main_loop_quit(thread->ctx->twe_loop); @@ -278,7 +337,7 @@ _twe_thread_wl_disp_check(GSource *source) } static gboolean -_twe_thread_wl_disp_dispatch(GSource *source, GSourceFunc cb, gpointer date) +_twe_thread_wl_disp_dispatch(GSource *source, GSourceFunc cb, gpointer data) { twe_wl_disp_source *disp_source = (twe_wl_disp_source *)source; @@ -857,6 +916,9 @@ __cb_tdm_client_wait_vblank(tdm_client_vblank *vblank, tdm_error error, surf_source->vblank_done = TPL_TRUE; } +static tdm_client_vblank* +_twe_surface_create_vblank(tdm_client *tdm_client); + static void _twe_thread_wl_surface_commit(twe_wl_surf_source *surf_source, tbm_surface_h tbm_surface) @@ -905,7 +967,16 @@ _twe_thread_wl_surface_commit(twe_wl_surf_source *surf_source, buf_info->wl_buffer, tbm_surface, tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); - if (_twe_ctx->tdm_client && surf_source->vblank) { + if (_twe_ctx->tdm_source && !surf_source->vblank) { + surf_source->vblank = + _twe_surface_create_vblank(_twe_ctx->tdm_source->tdm_client); + if (!surf_source->vblank) { + TPL_WARN("Failed to create vblank. surf_source(%p)", + surf_source); + } + } + + if (_twe_ctx->tdm_source && surf_source->vblank) { tdm_error tdm_err = TDM_ERROR_NONE; tdm_err = tdm_client_vblank_wait(surf_source->vblank, 1, /* TODO: interval */ @@ -954,7 +1025,7 @@ _twe_thread_wl_surface_acquire_and_commit(twe_wl_surf_source *surf_source) while (!surf_source->vblank_done) { tdm_error tdm_err = TDM_ERROR_NONE; - tdm_err = tdm_client_handle_events(_twe_ctx->tdm_client); + tdm_err = tdm_client_handle_events(_twe_ctx->tdm_source->tdm_client); if (tdm_err != TDM_ERROR_NONE) { TPL_ERR("Failed to tdm_client_handle_events."); break; @@ -966,7 +1037,7 @@ _twe_thread_wl_surface_acquire_and_commit(twe_wl_surf_source *surf_source) } static gboolean -_twe_thread_wl_surface_dispatch(GSource *source, GSourceFunc cb, gpointer date) +_twe_thread_wl_surface_dispatch(GSource *source, GSourceFunc cb, gpointer data) { twe_wl_surf_source *wl_surf_source = (twe_wl_surf_source *)source; GIOCondition cond; @@ -1209,7 +1280,7 @@ twe_surface_add(twe_thread* thread, source->disp_source = (twe_wl_disp_source *)twe_display; source->rotation = 0; source->rotation_capability = TPL_FALSE; - source->vblank = _twe_surface_create_vblank(_twe_ctx->tdm_client); + source->vblank = NULL; source->vblank_done = TPL_TRUE; source->committed_buffers = __tpl_list_alloc(); source->in_use_buffers = __tpl_list_alloc(); -- 2.7.4 From e8888623808afd7598097628acd2615c64e15c37 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Wed, 14 Jun 2017 17:19:55 +0900 Subject: [PATCH 10/16] tpl_wayland_egl_thread: Changed to acquire only if vblank_done state is TPL_TRUE. - The function _twe_thread_wl_surface_acquire_and_commit can be called in both situations. One is when acquirable event is received from the main thread, and the other is when __cb_tdm_client_wait_vblank callback is called. The reason for calling the acquire function in the two situations described above is to make only one commit for one vblank. Change-Id: I720ac9290a9338b6e681026ee35104a22da6aecc Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 49 +++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index fb6f859..8b98e52 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -902,6 +902,9 @@ static void __cb_tbm_queue_trace_callback(tbm_surface_queue_h tbm_queue, } static void +_twe_thread_wl_surface_acquire_and_commit(twe_wl_surf_source *surf_source); + +static void __cb_tdm_client_wait_vblank(tdm_client_vblank *vblank, tdm_error error, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data) @@ -914,6 +917,7 @@ __cb_tdm_client_wait_vblank(tdm_client_vblank *vblank, tdm_error error, } surf_source->vblank_done = TPL_TRUE; + _twe_thread_wl_surface_acquire_and_commit(surf_source); } static tdm_client_vblank* @@ -999,40 +1003,39 @@ _twe_thread_wl_surface_commit(twe_wl_surf_source *surf_source, } } +/* The following function _twe_thread_wl_surface_acquire_and_commit can be + * called in both situations. + * One is when acquirable event is received from the main thread, + * and the other is when __cb_tdm_client_wait_vblank callback is called. + * The reason for calling the next function in the two situations described + * above is to make only one commit for one vblank. + */ static void _twe_thread_wl_surface_acquire_and_commit(twe_wl_surf_source *surf_source) { tbm_surface_h tbm_surface = NULL; tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE; - /* One or more tbm_surfaces that are not consumed can be in tbm_surface_queue - * because event_fd has two writes but read may be processed only once. - */ - while (tbm_surface_queue_can_acquire(surf_source->tbm_queue, 0)) { - tsq_err = tbm_surface_queue_acquire(surf_source->tbm_queue, &tbm_surface); - if (!tbm_surface || tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) { - TPL_ERR("Failed to acquire from tbm_queue(%p)", - surf_source->tbm_queue); - return; - } + if (tbm_surface_queue_can_acquire(surf_source->tbm_queue, 0)) { + if (surf_source->vblank_done == TPL_TRUE) { + tsq_err = tbm_surface_queue_acquire(surf_source->tbm_queue, &tbm_surface); + if (!tbm_surface || tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) { + TPL_ERR("Failed to acquire from tbm_queue(%p)", + surf_source->tbm_queue); + return; + } - tbm_surface_internal_ref(tbm_surface); + tbm_surface_internal_ref(tbm_surface); - TPL_LOG_T("WL_EGL", "[ACQ] tbm_surface(%p) bo(%d)", - tbm_surface, - tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); + TPL_LOG_T("WL_EGL", "[ACQ] tbm_surface(%p) bo(%d)", + tbm_surface, + tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); - while (!surf_source->vblank_done) { - tdm_error tdm_err = TDM_ERROR_NONE; + _twe_thread_wl_surface_commit(surf_source, tbm_surface); - tdm_err = tdm_client_handle_events(_twe_ctx->tdm_source->tdm_client); - if (tdm_err != TDM_ERROR_NONE) { - TPL_ERR("Failed to tdm_client_handle_events."); - break; - } + } else { + TPL_LOG_T("WL_EGL", "[ACQ_skip] It will be acquired next vblank."); } - - _twe_thread_wl_surface_commit(surf_source, tbm_surface); } } -- 2.7.4 From 76188aa7445492f388b48b3aec680e90dc936d11 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Wed, 14 Jun 2017 17:31:43 +0900 Subject: [PATCH 11/16] tpl_wayland_egl_thread: Fixed some build warning. Change-Id: Ied55bdacdf5e0e910ae6b4806050c6b51c7a939e Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 6 +----- worker_test/worker_test.c | 4 +++- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index 8b98e52..a8b219d 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -559,7 +559,6 @@ tpl_result_t twe_display_del(twe_display_h twe_display) { gboolean is_destroyed = FALSE; - twe_thread *thread = NULL; twe_wl_disp_source *source = (twe_wl_disp_source *)twe_display; if (!source || (is_destroyed = g_source_is_destroyed(&source->gsource))) { @@ -568,9 +567,6 @@ twe_display_del(twe_display_h twe_display) return TPL_ERROR_INVALID_PARAMETER; } - thread = source->thread; - /* TODO : disp_source will be removed from displays list in thread */ - _twe_display_shm_fini(source); _twe_display_fini_wl_tbm_client(source->wl_tbm_client); source->wl_tbm_client = NULL; @@ -942,7 +938,7 @@ _twe_thread_wl_surface_commit(twe_wl_surf_source *surf_source, wl_egl_window->attached_width = buf_info->width; wl_egl_window->attached_height = buf_info->height; - wl_surface_attach(wl_surface, (struct wl_proxy *)buf_info->wl_buffer, + wl_surface_attach(wl_surface, (void *)buf_info->wl_buffer, buf_info->dx, buf_info->dy); if (buf_info->num_rects < 1 || buf_info->rects == NULL) { diff --git a/worker_test/worker_test.c b/worker_test/worker_test.c index 4a31962..8e89f51 100644 --- a/worker_test/worker_test.c +++ b/worker_test/worker_test.c @@ -120,7 +120,7 @@ _paint_color(tbm_surface_h tbm_surface) tbm_surface_unmap(tbm_surface); } -void +int main(void) { struct wl_event_queue *ev_queue; @@ -187,6 +187,8 @@ main(void) twe_display_del(twe_display); twe_thread_destroy(t_thread); + + return 0; } -- 2.7.4 From bd3c827273308fedf6d759f20257d292d7182ba0 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Wed, 14 Jun 2017 20:03:49 +0900 Subject: [PATCH 12/16] tpl_wayland_egl_thread: Implement free_flush protocol. - Implement free_flush of tizen_surface_shm_flusher. Just flush free_buffer when receive free_flush event from server. If this protocol is active in server, it can reduce quick_panel buffer 3 to 1 in idle time. Change-Id: I69422c1b10f43ea6430c2c059eb330403a18824c Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index a8b219d..dd2a3dc 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -428,6 +428,8 @@ _twe_display_fini_wl_tbm_client(struct wayland_tbm_client *wl_tbm_client) wayland_tbm_client_deinit(wl_tbm_client); } +#define IMPL_TIZEN_SURFACE_SHM_VERSION 2 + void __cb_wl_resistry_global_callback(void *data, struct wl_registry *wl_registry, uint32_t name, const char *interface, @@ -439,7 +441,8 @@ __cb_wl_resistry_global_callback(void *data, struct wl_registry *wl_registry, disp_source->tss = wl_registry_bind(wl_registry, name, &tizen_surface_shm_interface, - version); + ((version < IMPL_TIZEN_SURFACE_SHM_VERSION) ? + version : IMPL_TIZEN_SURFACE_SHM_VERSION)); } } @@ -682,7 +685,6 @@ static void __cb_tss_flusher_flush_callback(void *data, _twe_display_print_err(disp_source, "dispatch_queue_pending"); return; } - TPL_OBJECT_UNLOCK(&disp_source->obj); tbm_surface_queue_flush(surf_source->tbm_queue); @@ -702,11 +704,41 @@ static void __cb_tss_flusher_flush_callback(void *data, } TPL_OBJECT_UNLOCK(&surf_source->obj); } + + TPL_OBJECT_UNLOCK(&disp_source->obj); } +static void __cb_tss_flusher_free_flush_callback(void *data, + struct tizen_surface_shm_flusher *tss_flusher) +{ + twe_wl_surf_source *surf_source = (twe_wl_surf_source *)data; + twe_wl_disp_source *disp_source = surf_source->disp_source; + int ret; + + TPL_LOG_T("WL_EGL", "[FREE_FLUSH_CB] surf_source(%p)", surf_source); + + /* First distach panding queue for TPL + - dispatch buffer-release + - dispatch queue flush + */ + TPL_OBJECT_LOCK(&disp_source->obj); + ret = wl_display_dispatch_queue_pending(disp_source->disp, + disp_source->ev_queue); + if (ret == -1) { + _twe_display_print_err(disp_source, "dispatch_queue_pending"); + return; + } + + tbm_surface_queue_free_flush(surf_source->tbm_queue); + + TPL_OBJECT_UNLOCK(&disp_source->obj); +} + + static const struct tizen_surface_shm_flusher_listener tss_flusher_listener = { - __cb_tss_flusher_flush_callback + __cb_tss_flusher_flush_callback, + __cb_tss_flusher_free_flush_callback }; void -- 2.7.4 From 88cf3252933493ccf019e5e15de79f679b2a516a Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Wed, 14 Jun 2017 21:17:57 +0900 Subject: [PATCH 13/16] integrated tpl_wayland_egl_thread feature. - This feature is disabled defaultly. - It can be enabled with set environment value 'TPL_WL_EGL_THREAD' to '1' when before running gl application. - Also it can be enabled defaultly with set 'ENABLE_DEFAULT_WL_THREAD' to '1' when build this package. - There is a new backend type for wayland_egl using thread. TPL_BACKEND_WAYLAND_THREAD - If enabled the thread feature, backend will be set to TPL_BACKEND_WAYLAND_THREAD and called every backend functions in tpl_wl_egl_thread.c If not enabled the thread feature, tpl's behavior is the same as before this commit. Change-Id: Ib8bb0c7836ef07b53cbf306b0f5e2404d9c119ff Signed-off-by: joonbum.ko --- Makefile | 5 + packaging/libtpl-egl.spec | 5 + src/tpl.c | 32 +- src/tpl.h | 1 + src/tpl_internal.h | 5 + src/tpl_surface.c | 9 +- src/tpl_wayland_egl.c | 9 +- src/tpl_wayland_egl_thread.c | 67 +++-- src/tpl_wl_egl_thread.c | 681 +++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 791 insertions(+), 23 deletions(-) create mode 100644 src/tpl_wl_egl_thread.c diff --git a/Makefile b/Makefile index 3747cd6..efd8024 100644 --- a/Makefile +++ b/Makefile @@ -58,6 +58,10 @@ ifneq ($(call is-feature-enabled,arm_atomic_operation),) CFLAGS += -DARM_ATOMIC_OPERATION endif +ifneq ($(call is-feature-enabled,wl_thread),) + CFLAGS += -DWL_THREAD_DEFAULT_ENABLE=1 +endif + WAYLAND_EGL_OBJ_PATH = ../src/wayland-egl/wayland-egl.o TPL_HEADERS += $(SRC_DIR)/tpl.h @@ -75,6 +79,7 @@ ifneq ($(call is-feature-enabled,winsys_wl),) TPL_HEADERS += $(SRC_DIR)/tpl_worker_thread.h TPL_HEADERS += $(SRC_DIR)/tpl_wayland_egl_thread.h TPL_SRCS += $(SRC_DIR)/tpl_wayland_egl.c +TPL_SRCS += $(SRC_DIR)/tpl_wl_egl_thread.c TPL_SRCS += $(SRC_DIR)/tpl_wayland_egl_thread.c TPL_SRCS += $(SRC_DIR)/tpl_wayland_vk_wsi.c TPL_SRCS += $(SRC_DIR)/tpl_gbm.c diff --git a/packaging/libtpl-egl.spec b/packaging/libtpl-egl.spec index 49c626d..669d6cc 100644 --- a/packaging/libtpl-egl.spec +++ b/packaging/libtpl-egl.spec @@ -15,6 +15,7 @@ %define ENABLE_DEFAULT_DUMP 0 %define ENABLE_OBJECT_HASH_CHECK 1 %define ENABLE_WORKER_TEST_ONLY 1 +%define ENABLE_DEFAULT_WL_THREAD 0 #TPL INSTALL OPTION %define ENABLE_TPL_TEST 0 @@ -158,6 +159,10 @@ TPL_OPTIONS=${TPL_OPTIONS}-default_dump TPL_OPTIONS=${TPL_OPTIONS}-object_hash_check %endif +%if "%{ENABLE_DEFAULT_WL_THREAD}" == "1" +TPL_OPTIONS=${TPL_OPTIONS}-wl_thread +%endif + %ifarch %arm aarch64 TPL_OPTIONS=${TPL_OPTIONS}-arm_atomic_operation %endif diff --git a/src/tpl.c b/src/tpl.c index afde8d8..c8966c4 100644 --- a/src/tpl.c +++ b/src/tpl.c @@ -219,6 +219,16 @@ tpl_backend_type_t __tpl_display_choose_backend(tpl_handle_t native_dpy) { const char *plat_name = NULL; + const char *thread = NULL; +#ifdef WL_THREAD_DEFAULT_ENABLE + int wl_egl_thread = 1; +#else + int wl_egl_thread = 0; + + thread = getenv("TPL_WL_EGL_THREAD"); + if (thread) + wl_egl_thread = atoi(thread); +#endif plat_name = getenv("EGL_PLATFORM"); if (plat_name) { @@ -232,7 +242,12 @@ __tpl_display_choose_backend(tpl_handle_t native_dpy) if (strcmp(plat_name, "tbm") == 0) return TPL_BACKEND_TBM; if (strcmp(plat_name, "tbm_vulkan_wsi") == 0) return TPL_BACKEND_TBM_VULKAN_WSI; - if (strcmp(plat_name, "wayland") == 0) return TPL_BACKEND_WAYLAND; + if (strcmp(plat_name, "wayland") == 0) { + if (wl_egl_thread) + return TPL_BACKEND_WAYLAND_THREAD; + else + return TPL_BACKEND_WAYLAND; + } if (strcmp(plat_name, "wayland_vulkan_wsi") == 0) return TPL_BACKEND_WAYLAND_VULKAN_WSI; if (strcmp(plat_name, "drm") == 0) return TPL_BACKEND_GBM; @@ -244,8 +259,13 @@ __tpl_display_choose_backend(tpl_handle_t native_dpy) return TPL_BACKEND_TBM; if (__tpl_display_choose_backend_gbm(native_dpy) == TPL_TRUE) return TPL_BACKEND_GBM; - if (__tpl_display_choose_backend_wayland_egl(native_dpy) == TPL_TRUE) - return TPL_BACKEND_WAYLAND; + if (wl_egl_thread) { + if (__tpl_display_choose_backend_wl_egl_thread(native_dpy)) + return TPL_BACKEND_WAYLAND_THREAD; + } else { + if (__tpl_display_choose_backend_wayland_egl(native_dpy)) + return TPL_BACKEND_WAYLAND; + } if (__tpl_display_choose_backend_wayland_vk_wsi(native_dpy) == TPL_TRUE) return TPL_BACKEND_WAYLAND_VULKAN_WSI; #endif @@ -274,6 +294,9 @@ __tpl_display_init_backend(tpl_display_t *display, tpl_backend_type_t type) case TPL_BACKEND_WAYLAND: __tpl_display_init_backend_wayland_egl(&display->backend); break; + case TPL_BACKEND_WAYLAND_THREAD: + __tpl_display_init_backend_wl_egl_thread(&display->backend); + break; case TPL_BACKEND_WAYLAND_VULKAN_WSI: __tpl_display_init_backend_wayland_vk_wsi(&display->backend); break; @@ -313,6 +336,9 @@ __tpl_surface_init_backend(tpl_surface_t *surface, tpl_backend_type_t type) case TPL_BACKEND_WAYLAND: __tpl_surface_init_backend_wayland_egl(&surface->backend); break; + case TPL_BACKEND_WAYLAND_THREAD: + __tpl_surface_init_backend_wl_egl_thread(&surface->backend); + break; case TPL_BACKEND_WAYLAND_VULKAN_WSI: __tpl_surface_init_backend_wayland_vk_wsi(&surface->backend); break; diff --git a/src/tpl.h b/src/tpl.h index c20c2c6..341afef 100644 --- a/src/tpl.h +++ b/src/tpl.h @@ -188,6 +188,7 @@ typedef enum { typedef enum { TPL_BACKEND_UNKNOWN = -1, TPL_BACKEND_WAYLAND, /* this backend represend wayland-egl */ + TPL_BACKEND_WAYLAND_THREAD, TPL_BACKEND_GBM, TPL_BACKEND_X11_DRI2, TPL_BACKEND_X11_DRI3, diff --git a/src/tpl_internal.h b/src/tpl_internal.h index 6b3ddfa..0eee34b 100644 --- a/src/tpl_internal.h +++ b/src/tpl_internal.h @@ -99,6 +99,8 @@ struct _tpl_surface_backend { tbm_format format, int width, int height, int buffer_count, int present_mode); tpl_result_t (*destroy_swapchain)(tpl_surface_t *surface); + tpl_result_t (*set_rotation_capability)(tpl_surface_t *surface, + tpl_bool_t set); }; struct _tpl_object { @@ -198,6 +200,7 @@ tpl_backend_type_t __tpl_display_choose_backend(tpl_handle_t native_dpy); tpl_bool_t __tpl_display_choose_backend_gbm(tpl_handle_t native_dpy); tpl_bool_t __tpl_display_choose_backend_tbm(tpl_handle_t native_dpy); tpl_bool_t __tpl_display_choose_backend_wayland_egl(tpl_handle_t native_dpy); +tpl_bool_t __tpl_display_choose_backend_wl_egl_thread(tpl_handle_t native_dpy); tpl_bool_t __tpl_display_choose_backend_wayland_vk_wsi(tpl_handle_t native_dpy); tpl_bool_t __tpl_display_choose_backend_x11_dri2(tpl_handle_t native_dpy); tpl_bool_t __tpl_display_choose_backend_x11_dri3(tpl_handle_t native_dpy); @@ -209,6 +212,7 @@ void __tpl_display_init_backend_gbm(tpl_display_backend_t *backend); void __tpl_display_init_backend_tbm(tpl_display_backend_t *backend, tpl_backend_type_t type); void __tpl_display_init_backend_wayland_egl(tpl_display_backend_t *backend); +void __tpl_display_init_backend_wl_egl_thread(tpl_display_backend_t *backend); void __tpl_display_init_backend_wayland_vk_wsi(tpl_display_backend_t *backend); void __tpl_display_init_backend_x11_dri2(tpl_display_backend_t *backend); void __tpl_display_init_backend_x11_dri3(tpl_display_backend_t *backend); @@ -216,6 +220,7 @@ void __tpl_surface_init_backend_gbm(tpl_surface_backend_t *backend); void __tpl_surface_init_backend_tbm(tpl_surface_backend_t *backend, tpl_backend_type_t type); void __tpl_surface_init_backend_wayland_egl(tpl_surface_backend_t *backend); +void __tpl_surface_init_backend_wl_egl_thread(tpl_surface_backend_t *backend); void __tpl_surface_init_backend_wayland_vk_wsi(tpl_surface_backend_t *backend); void __tpl_surface_init_backend_x11_dri2(tpl_surface_backend_t *backend); void __tpl_surface_init_backend_x11_dri3(tpl_surface_backend_t *backend); diff --git a/src/tpl_surface.c b/src/tpl_surface.c index 3be8cc7..7dd1edc 100644 --- a/src/tpl_surface.c +++ b/src/tpl_surface.c @@ -423,6 +423,8 @@ tpl_surface_set_reset_cb(tpl_surface_t *surface, void *data, tpl_surface_cb_func tpl_result_t tpl_surface_set_rotation_capability(tpl_surface_t *surface, tpl_bool_t set) { + tpl_result_t ret = TPL_ERROR_NONE; + if (!surface || (surface->type != TPL_SURFACE_TYPE_WINDOW)) { TPL_ERR("Invalid surface!"); return TPL_ERROR_INVALID_PARAMETER; @@ -430,9 +432,12 @@ tpl_surface_set_rotation_capability(tpl_surface_t *surface, tpl_bool_t set) TPL_OBJECT_LOCK(surface); - surface->rotation_capability = set; + if (surface->backend.set_rotation_capability) + ret = surface->backend.set_rotation_capability(surface, set); + else + surface->rotation_capability = set; TPL_OBJECT_UNLOCK(surface); - return TPL_ERROR_NONE; + return ret; } diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index 8877eef..27f667b 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include @@ -1150,10 +1149,17 @@ __tpl_wayland_egl_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeou TRACE_ASYNC_BEGIN((int)wayland_egl_buffer, "[DEQ]~[ENQ] BO_NAME:%d", tbm_bo_export(wayland_egl_buffer->bo)); + TPL_LOG_B("WL_EGL", + "[DEQ][R] tpl_wayland_surface_t(%p) wl_buffer(%p) tbm_surface(%p) bo(%d)", + wayland_egl_surface, + wayland_egl_buffer->wl_proxy, + tbm_surface, tbm_bo_export(wayland_egl_buffer->bo)); + wayland_egl_buffer->dx = wl_egl_window->dx; wayland_egl_buffer->dy = wl_egl_window->dy; wayland_egl_buffer->width = wl_egl_window->width; wayland_egl_buffer->height = wl_egl_window->height; + if (wayland_egl_surface->latest_transform != wl_egl_window->transform) { wayland_egl_surface->latest_transform = wl_egl_window->transform; wayland_egl_buffer->transform = wl_egl_window->transform; @@ -1161,6 +1167,7 @@ __tpl_wayland_egl_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeou } else { wayland_egl_buffer->rotated = TPL_FALSE; } + wayland_egl_buffer->reset = TPL_FALSE; if (wayland_egl_surface->is_activated != is_activated) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index dd2a3dc..c2642c1 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -65,6 +65,7 @@ struct _twe_wl_surf_source { int event_fd; struct wl_surface *surf; struct wl_egl_window *wl_egl_window; + int latest_transform; int rotation; tpl_bool_t rotation_capability; tpl_object_t obj; /* for mutex lock */ @@ -81,7 +82,9 @@ struct _twe_wl_buffer_info { struct wl_proxy *wl_buffer; int dx, dy; int width, height; - int rotation; + /* for wl_surface_set_buffer_transform */ + int transform; + tpl_bool_t rotated; /* for damage region */ int num_rects; int *rects; @@ -267,7 +270,7 @@ twe_thread_destroy(twe_thread* thread) thread->ctx = NULL; } - TPL_LOG_T("WL_EGL", "twe_thread(%p)", thread); + TPL_LOG_T("WL_EGL", "[THREAD DESTROY] twe_thread(%p)", thread); thread->ctx = NULL; free(thread); @@ -850,7 +853,11 @@ static void __cb_tbm_queue_trace_callback(tbm_surface_queue_h tbm_queue, (void **)&buf_info); /* If buf_info is already existed, reuse it. */ if (buf_info) { - buf_info->rotation = wl_egl_window->rotation; + if (surf_source->latest_transform != wl_egl_window->transform) { + surf_source->latest_transform = wl_egl_window->transform; + buf_info->rotated = TPL_TRUE; + } + buf_info->transform = wl_egl_window->transform; buf_info->dx = wl_egl_window->dx; buf_info->dy = wl_egl_window->dy; @@ -870,10 +877,10 @@ static void __cb_tbm_queue_trace_callback(tbm_surface_queue_h tbm_queue, } TPL_LOG_T("WL_EGL", - "[REUSE_BUF] buf_info(%p) tbm_surface(%p) bo(%d) (%dx%d) rot(%d)", + "[REUSE_BUF] buf_info(%p) tbm_surface(%p) bo(%d) (%dx%d) transform(%d)", buf_info, tbm_surface, tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0)), - buf_info->width, buf_info->height, buf_info->rotation); + buf_info->width, buf_info->height, buf_info->transform); return; } else { buf_info = (twe_wl_buffer_info *)calloc(1, sizeof(twe_wl_buffer_info)); @@ -896,7 +903,6 @@ static void __cb_tbm_queue_trace_callback(tbm_surface_queue_h tbm_queue, } buf_info->surf_source = surf_source; - buf_info->rotation = wl_egl_window->rotation; buf_info->dx = wl_egl_window->dx; buf_info->dy = wl_egl_window->dy; buf_info->width = wl_egl_window->width; @@ -904,6 +910,11 @@ static void __cb_tbm_queue_trace_callback(tbm_surface_queue_h tbm_queue, buf_info->num_rects = 0; buf_info->rects = NULL; buf_info->need_to_commit = TPL_TRUE; + if (surf_source->latest_transform != wl_egl_window->transform) { + surf_source->latest_transform = wl_egl_window->transform; + buf_info->rotated = TPL_TRUE; + } + buf_info->transform = wl_egl_window->rotation; wl_buffer_add_listener((void *)buf_info->wl_buffer, &wl_buffer_release_listener, tbm_surface); @@ -922,10 +933,10 @@ static void __cb_tbm_queue_trace_callback(tbm_surface_queue_h tbm_queue, } TPL_LOG_T("WL_EGL", - "[NEW_BUF] buf_info(%p) tbm_surface(%p) bo(%d) (%dx%d) rot(%d)", + "[NEW_BUF] buf_info(%p) tbm_surface(%p) bo(%d) (%dx%d) transform(%d)", buf_info, tbm_surface, tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0)), - buf_info->width, buf_info->height, buf_info->rotation); + buf_info->width, buf_info->height, buf_info->transform); } @@ -958,6 +969,7 @@ _twe_thread_wl_surface_commit(twe_wl_surf_source *surf_source, twe_wl_buffer_info *buf_info = NULL; struct wl_surface *wl_surface = surf_source->surf; struct wl_egl_window *wl_egl_window = surf_source->wl_egl_window; + uint32_t version; tbm_surface_internal_get_user_data(tbm_surface, KEY_BUFFER_INFO, (void **)&buf_info); @@ -967,6 +979,12 @@ _twe_thread_wl_surface_commit(twe_wl_surf_source *surf_source, return; } + version = wl_proxy_get_version((struct wl_proxy *)wl_surface); + + if (buf_info->rotated == TPL_TRUE) { + wl_surface_set_buffer_transform(wl_surface, buf_info->transform); + } + wl_egl_window->attached_width = buf_info->width; wl_egl_window->attached_height = buf_info->height; @@ -974,20 +992,34 @@ _twe_thread_wl_surface_commit(twe_wl_surf_source *surf_source, buf_info->dx, buf_info->dy); if (buf_info->num_rects < 1 || buf_info->rects == NULL) { - wl_surface_damage(wl_surface, - buf_info->dx, buf_info->dy, - buf_info->width, buf_info->height); + if (version < 4) { + wl_surface_damage(wl_surface, + buf_info->dx, buf_info->dy, + buf_info->width, buf_info->height); + } else { + wl_surface_damage_buffer(wl_surface, + buf_info->dx, buf_info->dy, + buf_info->width, buf_info->height); + } } else { int i; for (i = 0; i < buf_info->num_rects; i++) { int inverted_y = buf_info->height - (buf_info->rects[i * 4 + 1] + buf_info->rects[i * 4 + 3]); - wl_surface_damage(wl_surface, - buf_info->rects[i * 4 + 0], - inverted_y, - buf_info->rects[i * 4 + 2], - buf_info->rects[i * 4 + 3]); + if (version < 4) { + wl_surface_damage(wl_surface, + buf_info->rects[i * 4 + 0], + inverted_y, + buf_info->rects[i * 4 + 2], + buf_info->rects[i * 4 + 3]); + } else { + wl_surface_damage_buffer(wl_surface, + buf_info->rects[i * 4 + 0], + inverted_y, + buf_info->rects[i * 4 + 2], + buf_info->rects[i * 4 + 3]); + } } } @@ -1248,7 +1280,7 @@ twe_surface_get_tbm_queue(twe_surface_h twe_surface) } if (!source->tbm_queue) { - TPL_ERR("Invalid parameters. twe_surface(%p) tbm_surface_queue(%p)", + TPL_ERR("Invalid parameters. twe_surface(%p) tbm_queue(%p)", source, source->tbm_queue); return NULL; } @@ -1309,6 +1341,7 @@ twe_surface_add(twe_thread* thread, source->wl_egl_window = wl_egl_window; source->tbm_queue = tbm_queue; source->disp_source = (twe_wl_disp_source *)twe_display; + source->latest_transform = wl_egl_window->transform; source->rotation = 0; source->rotation_capability = TPL_FALSE; source->vblank = NULL; diff --git a/src/tpl_wl_egl_thread.c b/src/tpl_wl_egl_thread.c new file mode 100644 index 0000000..dcde2e1 --- /dev/null +++ b/src/tpl_wl_egl_thread.c @@ -0,0 +1,681 @@ +#define inline __inline__ + +#include +#include + +#undef inline + +#include "tpl_internal.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include "tpl_wayland_egl_thread.h" + +/* In wayland, application and compositor create its own drawing buffers. Recommend size is more than 2. */ +#define CLIENT_QUEUE_SIZE 3 + +typedef struct _tpl_wayland_egl_display tpl_wayland_egl_display_t; +typedef struct _tpl_wayland_egl_surface tpl_wayland_egl_surface_t; + +struct _tpl_wayland_egl_display { + twe_thread *wl_egl_thread; + twe_display_h twe_display; +}; + +struct _tpl_wayland_egl_surface { + twe_surface_h twe_surface; + tbm_surface_queue_h tbm_queue; + tpl_bool_t reset; /* TRUE if queue reseted by external */ +}; + +static tpl_result_t +__tpl_wl_egl_display_init(tpl_display_t *display) +{ + tpl_wayland_egl_display_t *wayland_egl_display = NULL; + + TPL_ASSERT(display); + + /* Do not allow default display in wayland. */ + if (!display->native_handle) { + TPL_ERR("Invalid native handle for display."); + return TPL_ERROR_INVALID_PARAMETER; + } + + wayland_egl_display = (tpl_wayland_egl_display_t *) calloc(1, + sizeof(tpl_wayland_egl_display_t)); + if (!wayland_egl_display) { + TPL_ERR("Failed to allocate memory for new tpl_wayland_egl_display_t."); + return TPL_ERROR_OUT_OF_MEMORY; + } + + display->backend.data = wayland_egl_display; + display->bufmgr_fd = -1; + + if (twe_check_native_handle_is_wl_display(display->native_handle)) { + twe_thread *wl_egl_thread = NULL; + twe_display_h twe_display = NULL; + + wl_egl_thread = twe_thread_create(); + if (!wl_egl_thread) { + TPL_ERR("Failed to create twe_thread."); + goto free_display; + } + + twe_display = twe_display_add(wl_egl_thread, display->native_handle); + if (!twe_display) { + TPL_ERR("Failed to add native_display(%p) to thread(%p)", + display->native_handle, wl_egl_thread); + twe_thread_destroy(wl_egl_thread); + goto free_display; + } + + wayland_egl_display->wl_egl_thread = wl_egl_thread; + wayland_egl_display->twe_display = twe_display; + + } else { + TPL_ERR("Invalid native handle for display."); + goto free_display; + } + + TPL_LOG_B("WL_EGL", + "[INIT DISPLAY] wayland_egl_display(%p) twe_thread(%p) twe_display(%p)", + wayland_egl_display, + wayland_egl_display->wl_egl_thread, + wayland_egl_display->twe_display); + + return TPL_ERROR_NONE; + +free_display: + wayland_egl_display->wl_egl_thread = NULL; + wayland_egl_display->twe_display = NULL; + + free(wayland_egl_display); + display->backend.data = NULL; + return TPL_ERROR_INVALID_OPERATION; +} + +static void +__tpl_wl_egl_display_fini(tpl_display_t *display) +{ + tpl_wayland_egl_display_t *wayland_egl_display; + + TPL_ASSERT(display); + + wayland_egl_display = (tpl_wayland_egl_display_t *)display->backend.data; + if (wayland_egl_display) { + + TPL_LOG_B("WL_EGL", + "[FINI] wayland_egl_display(%p) twe_thread(%p) twe_display(%p)", + wayland_egl_display, + wayland_egl_display->wl_egl_thread, + wayland_egl_display->twe_display); + + if (wayland_egl_display->twe_display) { + tpl_result_t ret = TPL_ERROR_NONE; + ret = twe_display_del(wayland_egl_display->twe_display); + if (ret != TPL_ERROR_NONE) + TPL_ERR("Failed to delete twe_display(%p) from twe_thread(%p)", + wayland_egl_display->twe_display, + wayland_egl_display->wl_egl_thread); + wayland_egl_display->twe_display = NULL; + } + + if (wayland_egl_display->wl_egl_thread) { + twe_thread_destroy(wayland_egl_display->wl_egl_thread); + wayland_egl_display->wl_egl_thread = NULL; + } + + free(wayland_egl_display); + } + + display->backend.data = NULL; +} + +static tpl_result_t +__tpl_wl_egl_display_query_config(tpl_display_t *display, + tpl_surface_type_t surface_type, + int red_size, int green_size, + int blue_size, int alpha_size, + int color_depth, int *native_visual_id, + tpl_bool_t *is_slow) +{ + TPL_ASSERT(display); + + if (surface_type == TPL_SURFACE_TYPE_WINDOW && red_size == 8 && + green_size == 8 && blue_size == 8 && + (color_depth == 32 || color_depth == 24)) { + + if (alpha_size == 8) { + if (native_visual_id) *native_visual_id = TBM_FORMAT_ARGB8888; + if (is_slow) *is_slow = TPL_FALSE; + return TPL_ERROR_NONE; + } + if (alpha_size == 0) { + if (native_visual_id) *native_visual_id = TBM_FORMAT_XRGB8888; + if (is_slow) *is_slow = TPL_FALSE; + return TPL_ERROR_NONE; + } + } + + return TPL_ERROR_INVALID_PARAMETER; +} + +static tpl_result_t +__tpl_wl_egl_display_filter_config(tpl_display_t *display, int *visual_id, + int alpha_size) +{ + TPL_IGNORE(display); + TPL_IGNORE(visual_id); + TPL_IGNORE(alpha_size); + return TPL_ERROR_NONE; +} + +static tpl_result_t +__tpl_wl_egl_display_get_window_info(tpl_display_t *display, + tpl_handle_t window, int *width, + int *height, tbm_format *format, + int depth, int a_size) +{ + tpl_result_t ret = TPL_ERROR_NONE; + + TPL_ASSERT(display); + TPL_ASSERT(window); + + if (format) { + if (a_size == 8) + *format = TBM_FORMAT_ARGB8888; + else + *format = TBM_FORMAT_XRGB8888; + } + + if ((ret = twe_get_native_window_info(window, width, height)) + != TPL_ERROR_NONE) { + TPL_ERR("Failed to get size info of native_window(%p)", window); + } + + return ret; +} + +static tpl_result_t +__tpl_wl_egl_display_get_pixmap_info(tpl_display_t *display, + tpl_handle_t pixmap, int *width, + int *height, tbm_format *format) +{ + tbm_surface_h tbm_surface = NULL; + + tbm_surface = twe_get_native_buffer_from_pixmap(pixmap); + if (!tbm_surface) { + TPL_ERR("Failed to get tbm_surface_h from native pixmap."); + return TPL_ERROR_INVALID_OPERATION; + } + + if (width) *width = tbm_surface_get_width(tbm_surface); + if (height) *height = tbm_surface_get_height(tbm_surface); + if (format) *format = tbm_surface_get_format(tbm_surface); + + return TPL_ERROR_NONE; +} + +static tbm_surface_h +__tpl_wl_egl_display_get_buffer_from_native_pixmap(tpl_handle_t pixmap) +{ + tbm_surface_h tbm_surface = NULL; + + TPL_ASSERT(pixmap); + + tbm_surface = twe_get_native_buffer_from_pixmap(pixmap); + if (!tbm_surface) { + TPL_ERR("Failed to get tbm_surface_h from wayland_tbm."); + return NULL; + } + + return tbm_surface; +} + +static void +__cb_tbm_surface_queue_reset_callback(tbm_surface_queue_h surface_queue, + void *data) +{ + tpl_surface_t *surface = NULL; + tpl_wayland_egl_surface_t *wayland_egl_surface = NULL; + + surface = (tpl_surface_t *)data; + TPL_CHECK_ON_NULL_RETURN(surface); + + wayland_egl_surface = (tpl_wayland_egl_surface_t *)surface->backend.data; + TPL_CHECK_ON_NULL_RETURN(wayland_egl_surface); + + TPL_LOG_B("WL_EGL", + "[QUEUE_RESET_CB] tpl_wayland_egl_surface_t(%p) surface_queue(%p)", + data, surface_queue); + + wayland_egl_surface->reset = TPL_TRUE; + + if (surface->reset_cb) + surface->reset_cb(surface->reset_data); +} + +static tpl_result_t +__tpl_wl_egl_surface_init(tpl_surface_t *surface) +{ + tpl_wayland_egl_display_t *wayland_egl_display = NULL; + tpl_wayland_egl_surface_t *wayland_egl_surface = NULL; + tbm_surface_queue_h tbm_queue = NULL; + twe_surface_h twe_surface = NULL; + + 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; + if (!wayland_egl_display) { + TPL_ERR("Invalid parameter. wayland_egl_display(%p)", + wayland_egl_display); + return TPL_ERROR_INVALID_PARAMETER; + } + + wayland_egl_surface = (tpl_wayland_egl_surface_t *) calloc(1, + sizeof(tpl_wayland_egl_surface_t)); + if (!wayland_egl_surface) { + TPL_ERR("Failed to allocate memory for new tpl_wayland_egl_surface_t."); + return TPL_ERROR_OUT_OF_MEMORY; + } + + surface->backend.data = (void *)wayland_egl_surface; + + twe_surface = twe_surface_add(wayland_egl_display->wl_egl_thread, + wayland_egl_display->twe_display, + surface->native_handle); + if (!twe_surface) { + TPL_ERR("Failed to add native_window(%p) to thread(%p)", + surface->native_handle, wayland_egl_display->wl_egl_thread); + goto create_twe_surface_fail; + } + + tbm_queue = twe_surface_get_tbm_queue(twe_surface); + if (!tbm_queue) { + TPL_ERR("Failed to get tbm_queue from twe_surface(%p)", twe_surface); + goto queue_create_fail; + } + + /* Set reset_callback to tbm_queue */ + if (tbm_surface_queue_add_reset_cb(tbm_queue, + __cb_tbm_surface_queue_reset_callback, + (void *)surface)) { + TPL_ERR("TBM surface queue add reset cb failed!"); + goto add_reset_cb_fail; + } + + wayland_egl_surface->reset = TPL_FALSE; + wayland_egl_surface->twe_surface = twe_surface; + wayland_egl_surface->tbm_queue = tbm_queue; + + surface->width = tbm_surface_queue_get_width(tbm_queue); + surface->height = tbm_surface_queue_get_height(tbm_queue); + surface->rotation = twe_surface_get_rotation(twe_surface); + + TPL_LOG_B("WL_EGL", + "[INIT1/2]tpl_surface(%p) tpl_wayland_egl_surface(%p) twe_surface(%p)", + surface, wayland_egl_surface, twe_surface); + TPL_LOG_B("WL_EGL", + "[INIT2/2]size(%dx%d)rot(%d)|tbm_queue(%p)|native_window(%p)", + surface->width, surface->height, surface->rotation, + tbm_queue, surface->native_handle); + + return TPL_ERROR_NONE; + +add_reset_cb_fail: +queue_create_fail: + twe_surface_del(twe_surface); +create_twe_surface_fail: + free(wayland_egl_surface); + surface->backend.data = NULL; + return TPL_ERROR_INVALID_OPERATION; +} + +static void +__tpl_wl_egl_surface_fini(tpl_surface_t *surface) +{ + tpl_wayland_egl_surface_t *wayland_egl_surface = NULL; + tpl_wayland_egl_display_t *wayland_egl_display = NULL; + + TPL_ASSERT(surface); + TPL_ASSERT(surface->display); + + wayland_egl_surface = (tpl_wayland_egl_surface_t *) surface->backend.data; + TPL_CHECK_ON_NULL_RETURN(wayland_egl_surface); + + wayland_egl_display = (tpl_wayland_egl_display_t *) + surface->display->backend.data; + TPL_CHECK_ON_NULL_RETURN(wayland_egl_display); + + if (surface->type == TPL_SURFACE_TYPE_WINDOW) { + TPL_LOG_B("WL_EGL", + "[FINI] wayland_egl_surface(%p) native_window(%p) twe_surface(%p)", + wayland_egl_surface, surface->native_handle, + wayland_egl_surface->twe_surface); + + if (twe_surface_del(wayland_egl_surface->twe_surface) + != TPL_ERROR_NONE) { + TPL_ERR("Failed to delete twe_surface(%p) from thread(%p)", + wayland_egl_surface->twe_surface, + wayland_egl_display->wl_egl_thread); + } + + wayland_egl_surface->twe_surface = NULL; + wayland_egl_surface->tbm_queue = NULL; + } + + free(wayland_egl_surface); + surface->backend.data = NULL; +} + +static tpl_result_t +__tpl_wl_egl_surface_set_rotation_capability(tpl_surface_t *surface, + tpl_bool_t set) +{ + tpl_wayland_egl_surface_t *wayland_egl_surface = NULL; + + if (!surface) { + TPL_ERR("Invalid parameter. tpl_surface(%p)", surface); + return TPL_ERROR_INVALID_PARAMETER; + } + + wayland_egl_surface = (tpl_wayland_egl_surface_t *)surface->backend.data; + if (!wayland_egl_surface) { + TPL_ERR("Invalid parameter. wayland_egl_surface(%p)", + wayland_egl_surface); + return TPL_ERROR_INVALID_PARAMETER; + } + + if (!wayland_egl_surface->twe_surface) { + TPL_ERR("Invalid parameter. wayland_egl_surface(%p) twe_surface(%p)", + wayland_egl_surface, wayland_egl_surface->twe_surface); + return TPL_ERROR_INVALID_PARAMETER; + } + + twe_surface_set_rotation_capablity(wayland_egl_surface->twe_surface, + set); + + return TPL_ERROR_NONE; +} + +static tpl_result_t +__tpl_wl_egl_surface_enqueue_buffer(tpl_surface_t *surface, + tbm_surface_h tbm_surface, + int num_rects, const int *rects, tbm_fd sync_fence) +{ + 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; + tbm_surface_queue_error_e tsq_err; + tpl_result_t ret = TPL_ERROR_NONE; + int bo_name = 0; + + bo_name = tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0)); + + if (!wayland_egl_surface) { + TPL_ERR("Invalid parameter. wayland_egl_surface(%p)", + wayland_egl_surface); + TRACE_ASYNC_END((int)tbm_surface, "[DEQ]~[ENQ] BO_NAME:%d", bo_name); + return TPL_ERROR_INVALID_PARAMETER; + } + + if (!tbm_surface_internal_is_valid(tbm_surface)) { + TPL_ERR("Failed to enqueue tbm_surface(%p) Invalid value.", + tbm_surface); + TRACE_ASYNC_END((int)tbm_surface, "[DEQ]~[ENQ] BO_NAME:%d", bo_name); + return TPL_ERROR_INVALID_PARAMETER; + } + + TRACE_MARK("[ENQ] BO_NAME:%d", bo_name); + + TPL_LOG_B("WL_EGL", + "[ENQ] wayland_egl_surface(%p) tbm_surface(%p) bo(%d)", + wayland_egl_surface, tbm_surface, bo_name); + + /* If there are received region information, + * save it to buf_info in tbm_surface user_data using below API. */ + if (num_rects && rects) { + ret = twe_surface_set_damage_region(tbm_surface, num_rects, rects); + if (ret != TPL_ERROR_NONE) { + TPL_WARN("Failed to set damage region. num_rects(%d) rects(%p)", + num_rects, rects); + } + } + + /* In frontbuffer mode, will skip tbm_surface_queue_enqueue, acquire, and + * commit if surface->frontbuffer that is already set and the tbm_surface + * client want to enqueue are the same. + */ + if (surface->is_frontbuffer_mode && surface->frontbuffer == tbm_surface) { + TPL_LOG_B("WL_EGL", + "[ENQ_SKIP][F] Client already uses frontbuffer(%p)", + surface->frontbuffer); + + /* The first buffer to be activated in frontbuffer mode muse be + * committed. Subsequence frames do not need to be committed because + * the buffer is already displayed. + */ + if (twe_surface_check_commit_needed(wayland_egl_surface->twe_surface, + surface->frontbuffer)) { + twe_surface_commit_without_enqueue(wayland_egl_surface->twe_surface, + surface->frontbuffer); + } + + TRACE_ASYNC_END((int)tbm_surface, "[DEQ]~[ENQ] BO_NAME:%d", bo_name); + + return TPL_ERROR_NONE; + } + + if (sync_fence != -1) { + tbm_sync_fence_wait(sync_fence, -1); + close(sync_fence); + } + + tsq_err = tbm_surface_queue_enqueue(wayland_egl_surface->tbm_queue, + tbm_surface); + if (tsq_err == TBM_SURFACE_QUEUE_ERROR_NONE) { + /* + * If tbm_surface_queue has not been reset, tbm_surface_queue_enqueue + * will return ERROR_NONE. Otherwise, queue has been reset + * this tbm_surface may have only one ref_count. So we need to + * unreference this tbm_surface after getting ERROR_NONE result from + * tbm_surface_queue_enqueue in order to prevent destruction. + */ + tbm_surface_internal_unref(tbm_surface); + } else { + TPL_ERR("Failed to enqueue tbm_surface(%p). tsq_err=%d", + tbm_surface, tsq_err); + TRACE_ASYNC_END((int)tbm_surface, "[DEQ]~[ENQ] BO_NAME:%d", bo_name); + return TPL_ERROR_INVALID_OPERATION; + } + + TRACE_ASYNC_END((int)tbm_surface, "[DEQ]~[ENQ] BO_NAME:%d", bo_name); + + return TPL_ERROR_NONE; +} + +static tpl_bool_t +__tpl_wl_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; + + retval = !(wayland_egl_surface->reset); + + return retval; +} + +static tbm_surface_h +__tpl_wl_egl_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeout_ns, + tbm_fd *sync_fence) +{ + TPL_ASSERT(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_surface_t *wayland_egl_surface = + (tpl_wayland_egl_surface_t *)surface->backend.data; + tpl_wayland_egl_display_t *wayland_egl_display = + (tpl_wayland_egl_display_t *)surface->display->backend.data; + tbm_surface_queue_error_e tsq_err = 0; + int is_activated = 0; + int bo_name = 0; + tpl_result_t lock_ret = TPL_FALSE; + + if (sync_fence) + *sync_fence = -1; + + /* Check whether the surface was resized */ + if (wayland_egl_surface->reset == TPL_TRUE) { + int width, height; + tpl_result_t ret = TPL_ERROR_NONE; + ret = twe_get_native_window_info(surface->native_handle, + &width, &height); + if (ret != TPL_ERROR_NONE) { + TPL_WARN("Failed to get size info from native_handle(%p).", + surface->native_handle); + } else { + surface->width = width; + surface->height = height; + } + wayland_egl_surface->reset = TPL_FALSE; + } + + /* wayland client can check their states (ACTIVATED or DEACTIVATED) with + * below function [wayland_tbm_client_queue_check_activate()]. + * This function has to be called between + * __tpl_wayland_egl_surface_wait_dequeuable and tbm_surface_queue_dequeue() + * in order to know what state the buffer will be dequeued next. + * + * ACTIVATED state means non-composite mode. Client can get buffers which + can be displayed directly(without compositing). + * DEACTIVATED state means composite mode. Client's buffer will be displayed + by compositor(E20) with compositing. + */ + is_activated = twe_surface_check_activated(wayland_egl_surface->twe_surface); + + if (surface->is_frontbuffer_mode && surface->frontbuffer != NULL) { + /* If surface->frontbuffer is already set in frontbuffer mode, + * it will return that frontbuffer if it is still activated, + * otherwise dequeue the new buffer after initializing + * surface->frontbuffer to NULL. */ + if (is_activated) { + TPL_LOG_B("WL_EGL", + "[DEQ][F] surface->frontbuffer(%p) BO_NAME(%d)", + surface->frontbuffer, + tbm_bo_export(tbm_surface_internal_get_bo( + surface->frontbuffer, 0))); + TRACE_ASYNC_BEGIN(surface->frontbuffer, + "[DEQ]~[ENQ] BO_NAME:%d", + tbm_bo_export(tbm_surface_internal_get_bo( + surface->frontbuffer, 0))); + return surface->frontbuffer; + } else + surface->frontbuffer = NULL; + } else { + surface->frontbuffer = NULL; + } + + TPL_OBJECT_UNLOCK(surface); + while (!tbm_surface_queue_can_dequeue(wayland_egl_surface->tbm_queue, 0)) { + + } + TPL_OBJECT_LOCK(surface); + + lock_ret = twe_display_lock(wayland_egl_display->twe_display); + + tsq_err = tbm_surface_queue_dequeue(wayland_egl_surface->tbm_queue, + &tbm_surface); + if (!tbm_surface) { + TPL_ERR("Failed to get tbm_surface from tbm_surface_queue | tsq_err = %d", + tsq_err); + if (lock_ret) twe_display_unlock(wayland_egl_display->twe_display); + return NULL; + } + + tbm_surface_internal_ref(tbm_surface); + bo_name = tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0)); + + if (surface->is_frontbuffer_mode && is_activated) + surface->frontbuffer = tbm_surface; + + TRACE_MARK("[DEQ][NEW]BO_NAME:%d", bo_name); + TRACE_ASYNC_BEGIN((int)tbm_surface, "[DEQ]~[ENQ] BO_NAME:%d", bo_name); + TPL_LOG_B("WL_EGL", "[DEQ][N] tbm_surface(%p) bo(%d)", + tbm_surface, bo_name); + + if (lock_ret == TPL_ERROR_NONE) + twe_display_unlock(wayland_egl_display->twe_display); + + return tbm_surface; +} + +tpl_bool_t +__tpl_display_choose_backend_wl_egl_thread(tpl_handle_t native_dpy) +{ + if (!native_dpy) return TPL_FALSE; + + if (twe_check_native_handle_is_wl_display(native_dpy)) + return TPL_TRUE; + + return TPL_FALSE; +} + +void +__tpl_display_init_backend_wl_egl_thread(tpl_display_backend_t *backend) +{ + TPL_ASSERT(backend); + + backend->type = TPL_BACKEND_WAYLAND_THREAD; + backend->data = NULL; + + backend->init = __tpl_wl_egl_display_init; + backend->fini = __tpl_wl_egl_display_fini; + backend->query_config = __tpl_wl_egl_display_query_config; + backend->filter_config = __tpl_wl_egl_display_filter_config; + backend->get_window_info = __tpl_wl_egl_display_get_window_info; + backend->get_pixmap_info = __tpl_wl_egl_display_get_pixmap_info; + backend->get_buffer_from_native_pixmap = + __tpl_wl_egl_display_get_buffer_from_native_pixmap; +} + +void +__tpl_surface_init_backend_wl_egl_thread(tpl_surface_backend_t *backend) +{ + TPL_ASSERT(backend); + + backend->type = TPL_BACKEND_WAYLAND_THREAD; + backend->data = NULL; + + backend->init = __tpl_wl_egl_surface_init; + backend->fini = __tpl_wl_egl_surface_fini; + backend->validate = __tpl_wl_egl_surface_validate; + backend->dequeue_buffer = __tpl_wl_egl_surface_dequeue_buffer; + backend->enqueue_buffer = __tpl_wl_egl_surface_enqueue_buffer; + backend->set_rotation_capability = + __tpl_wl_egl_surface_set_rotation_capability; +} + -- 2.7.4 From 360bc3809f02a03a90cde8213770dda0c7fe9cfe Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Mon, 19 Jun 2017 16:41:23 +0900 Subject: [PATCH 14/16] tpl: Added a frontend API to cancel dequeued buffer. - Previously, when dequeued buffer was canceled, ref counts were run to be destroyed without tbm_surface_queue_release. However, for the normal operation of wayland_egl_thread, DDK need to cancel the dequeued buffer before using it. - In wayland_egl_thread structure, tbm_surface_queue_release should be called so that tbm_surface can be completely destroyed. - The newly added below API calls tbm_surface_queue_release directly to destroy unused tbm_surface. tpl_surface_cancel_dequeued_buffer(tpl_surface_t *surface, tbm_surface_h tbm_surface) - The type of tpl_surface must be window surface, and tbm_surface must be a buffer in the state before rendering begins. Change-Id: Ibf4950dc2846f1f6a01998ea39bae99bc8300b4f Signed-off-by: joonbum.ko --- src/tpl.h | 13 +++++++++++++ src/tpl_internal.h | 2 ++ src/tpl_surface.c | 31 +++++++++++++++++++++++++++++++ src/tpl_wayland_egl.c | 37 +++++++++++++++++++++++++++++++++++++ src/tpl_wl_egl_thread.c | 36 ++++++++++++++++++++++++++++++++++++ 5 files changed, 119 insertions(+) diff --git a/src/tpl.h b/src/tpl.h index 341afef..8748add 100644 --- a/src/tpl.h +++ b/src/tpl.h @@ -751,6 +751,19 @@ tpl_result_t tpl_surface_set_rotation_capability(tpl_surface_t *surface, tpl_bool_t set); /** + * Cancel dequeued buffer before use. + * + * canceled buffer will be released after unref. + + * @param surface surface used to dequeue. + * - surface type should be TPL_SURFACE_TYPE_WINDOW. + * @param tbm_surface buffer to cancel use. + */ +tpl_result_t +tpl_surface_cancel_dequeued_buffer(tpl_surface_t *surface, + tbm_surface_h tbm_surface); + +/** * Present mode types. * * @TPL_DISPLAY_MODE_IMMEDIATE_KHR: The presentation engine does not wait for diff --git a/src/tpl_internal.h b/src/tpl_internal.h index 0eee34b..c72fde6 100644 --- a/src/tpl_internal.h +++ b/src/tpl_internal.h @@ -86,6 +86,8 @@ struct _tpl_surface_backend { tpl_result_t (*init)(tpl_surface_t *surface); void (*fini)(tpl_surface_t *surface); tpl_bool_t (*validate)(tpl_surface_t *surface); + tpl_result_t (*cancel_dequeued_buffer)(tpl_surface_t *surface, + tbm_surface_h tbm_surface); tbm_surface_h (*dequeue_buffer)(tpl_surface_t *surface, uint64_t timeout_ns, tbm_fd *sync_fence); tpl_result_t (*enqueue_buffer)(tpl_surface_t *surface, diff --git a/src/tpl_surface.c b/src/tpl_surface.c index 7dd1edc..254da8d 100644 --- a/src/tpl_surface.c +++ b/src/tpl_surface.c @@ -192,6 +192,37 @@ tpl_surface_get_post_interval(tpl_surface_t *surface) return interval; } + +tpl_result_t +tpl_surface_cancel_dequeued_buffer(tpl_surface_t *surface, + tbm_surface_h tbm_surface) +{ + tpl_result_t ret = TPL_ERROR_NONE; + + if (!surface || (surface->type != TPL_SURFACE_TYPE_WINDOW)) { + TPL_ERR("Invalid surface(%p)", surface); + return TPL_ERROR_INVALID_PARAMETER; + } + + if (!surface->backend.cancel_dequeued_buffer) { + TPL_ERR("TPL surface has not been initialized correctly!"); + return TPL_ERROR_INVALID_PARAMETER; + } + + if (!tbm_surface) { + TPL_ERR("Invalid parameter. tbm_surface(%p)", tbm_surface); + return TPL_ERROR_INVALID_PARAMETER; + } + + TPL_LOG_F("tpl_surface_t(%p) tbm_surface(%p)", surface, tbm_surface); + + TPL_OBJECT_LOCK(surface); + ret = surface->backend.cancel_dequeued_buffer(surface, tbm_surface); + TPL_OBJECT_UNLOCK(surface); + + return ret; +} + tbm_surface_h tpl_surface_dequeue_buffer(tpl_surface_t *surface) { diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index 27f667b..c5ad096 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -1045,6 +1045,41 @@ __tpl_wayland_egl_surface_wait_dequeuable(tpl_surface_t *surface) return ret; } + +static tpl_result_t +__tpl_wayland_egl_surface_cancel_dequeued_buffer(tpl_surface_t *surface, + tbm_surface_h tbm_surface) +{ + tpl_wayland_egl_surface_t *wayland_egl_surface = NULL; + tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE; + + wayland_egl_surface = (tpl_wayland_egl_surface_t *)surface->backend.data; + if (!wayland_egl_surface) { + TPL_ERR("Invalid backend surface. surface(%p) wayland_egl_surface(%p)", + surface, wayland_egl_surface); + return TPL_ERROR_INVALID_PARAMETER; + } + + if (!tbm_surface_internal_is_valid(tbm_surface)) { + TPL_ERR("Invalid buffer. tbm_surface(%p)", tbm_surface); + return TPL_ERROR_INVALID_PARAMETER; + } + + tbm_surface_internal_unref(tbm_surface); + + tsq_err = tbm_surface_queue_release(wayland_egl_surface->tbm_queue, + tbm_surface); + if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) { + TPL_ERR("Failed to release tbm_surface(%p)", tbm_surface); + return TPL_ERROR_INVALID_OPERATION; + } + + TPL_LOG_B("WL_EGL", "[CANCEL BUFFER] tpl_surface(%p) tbm_surface(%p)", + surface, tbm_surface); + + return TPL_ERROR_NONE; +} + static tbm_surface_h __tpl_wayland_egl_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeout_ns, tbm_fd *sync_fence) @@ -1336,6 +1371,8 @@ __tpl_surface_init_backend_wayland_egl(tpl_surface_backend_t *backend) backend->init = __tpl_wayland_egl_surface_init; backend->fini = __tpl_wayland_egl_surface_fini; backend->validate = __tpl_wayland_egl_surface_validate; + backend->cancel_dequeued_buffer = + __tpl_wayland_egl_surface_cancel_dequeued_buffer; backend->dequeue_buffer = __tpl_wayland_egl_surface_dequeue_buffer; backend->enqueue_buffer = __tpl_wayland_egl_surface_enqueue_buffer; } diff --git a/src/tpl_wl_egl_thread.c b/src/tpl_wl_egl_thread.c index dcde2e1..7006a41 100644 --- a/src/tpl_wl_egl_thread.c +++ b/src/tpl_wl_egl_thread.c @@ -525,6 +525,40 @@ __tpl_wl_egl_surface_validate(tpl_surface_t *surface) return retval; } +static tpl_result_t +__tpl_wl_egl_surface_cancel_dequeued_buffer(tpl_surface_t *surface, + tbm_surface_h tbm_surface) +{ + tpl_wayland_egl_surface_t *wayland_egl_surface = NULL; + tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE; + + wayland_egl_surface = (tpl_wayland_egl_surface_t *)surface->backend.data; + if (!wayland_egl_surface) { + TPL_ERR("Invalid backend surface. surface(%p) wayland_egl_surface(%p)", + surface, wayland_egl_surface); + return TPL_ERROR_INVALID_PARAMETER; + } + + if (!tbm_surface_internal_is_valid(tbm_surface)) { + TPL_ERR("Invalid buffer. tbm_surface(%p)", tbm_surface); + return TPL_ERROR_INVALID_PARAMETER; + } + + tbm_surface_internal_unref(tbm_surface); + + tsq_err = tbm_surface_queue_release(wayland_egl_surface->tbm_queue, + tbm_surface); + if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) { + TPL_ERR("Failed to release tbm_surface(%p)", tbm_surface); + return TPL_ERROR_INVALID_OPERATION; + } + + TPL_LOG_B("WL_EGL", "[CANCEL BUFFER] tpl_surface(%p) tbm_surface(%p)", + surface, tbm_surface); + + return TPL_ERROR_NONE; +} + static tbm_surface_h __tpl_wl_egl_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeout_ns, tbm_fd *sync_fence) @@ -673,6 +707,8 @@ __tpl_surface_init_backend_wl_egl_thread(tpl_surface_backend_t *backend) backend->init = __tpl_wl_egl_surface_init; backend->fini = __tpl_wl_egl_surface_fini; backend->validate = __tpl_wl_egl_surface_validate; + backend->cancel_dequeued_buffer = + __tpl_wl_egl_surface_cancel_dequeued_buffer; backend->dequeue_buffer = __tpl_wl_egl_surface_dequeue_buffer; backend->enqueue_buffer = __tpl_wl_egl_surface_enqueue_buffer; backend->set_rotation_capability = -- 2.7.4 From 340a4acae05f5aa0cb9e30a754cf1e9e4c92ca5e Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Mon, 19 Jun 2017 19:01:34 +0900 Subject: [PATCH 15/16] Package version up to 1.2.0 Change-Id: I2e9f90dbb91549ce2b0fb73a2530ed3ecab98b61 Signed-off-by: joonbum.ko --- packaging/libtpl-egl.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packaging/libtpl-egl.spec b/packaging/libtpl-egl.spec index 669d6cc..dbf739c 100644 --- a/packaging/libtpl-egl.spec +++ b/packaging/libtpl-egl.spec @@ -1,7 +1,7 @@ #TPL VERSION MACROS %define TPL_VER_MAJOR 1 -%define TPL_VER_MINOR 1 -%define TPL_RELEASE 1 +%define TPL_VER_MINOR 2 +%define TPL_RELEASE 0 %define TPL_VERSION %{TPL_VER_MAJOR}.%{TPL_VER_MINOR} %define TPL_VER_FULL %{TPL_VERSION}.%{TPL_RELEASE} -- 2.7.4 From 7af8455c9d33d54ad0e97c5b35735164554f9715 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Thu, 22 Jun 2017 17:00:16 +0900 Subject: [PATCH 16/16] wayland_egl: Added an API to set window_transform. - New API : void wl_egl_set_window_transform(struct wl_egl_window *egl_window, int window_transform) - libwayland-egl package version up to 1.2.0 Change-Id: If1e225d5bdc043f9f1acc3da1c8894caeee12136 Signed-off-by: joonbum.ko --- packaging/libtpl-egl.spec | 2 +- src/wayland-egl/wayland-egl-priv.h | 1 + src/wayland-egl/wayland-egl.c | 19 +++++++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/packaging/libtpl-egl.spec b/packaging/libtpl-egl.spec index dbf739c..c251d96 100644 --- a/packaging/libtpl-egl.spec +++ b/packaging/libtpl-egl.spec @@ -21,7 +21,7 @@ %define ENABLE_TPL_TEST 0 #WAYLAND-EGL VERSION MACROS -%define WL_EGL_VERSION 1.1.0 +%define WL_EGL_VERSION 1.2.0 #TPL WINDOW SYSTEM CHECK %if "%{TPL_WINSYS}" != "DRI2" && "%{TPL_WINSYS}" != "DRI3" && "%{TPL_WINSYS}" != "WL" diff --git a/src/wayland-egl/wayland-egl-priv.h b/src/wayland-egl/wayland-egl-priv.h index f2b2d05..87ff314 100644 --- a/src/wayland-egl/wayland-egl-priv.h +++ b/src/wayland-egl/wayland-egl-priv.h @@ -29,6 +29,7 @@ struct wl_egl_window { wl_egl_window_rotation rotation; int frontbuffer_mode; int transform; + int window_transform; void *private; void (*resize_callback)(struct wl_egl_window *, void *); diff --git a/src/wayland-egl/wayland-egl.c b/src/wayland-egl/wayland-egl.c index 37e81d5..cabefc4 100644 --- a/src/wayland-egl/wayland-egl.c +++ b/src/wayland-egl/wayland-egl.c @@ -210,3 +210,22 @@ wl_egl_window_set_frontbuffer_mode(struct wl_egl_window *egl_window, egl_window->set_frontbuffer_callback(egl_window, egl_window->private, set); } + +WL_EGL_EXPORT void +wl_egl_window_set_window_transform(struct wl_egl_window *egl_window, + int window_transform) +{ + if (egl_window == NULL) { + WL_EGL_ERR("egl_window is NULL"); + return; + } + + if (egl_window->window_transform == window_transform) { + WL_EGL_LOG(2, + "window_transform(%d) already rotated", + window_transform); + return; + } + + egl_window->window_transform = window_transform; +} -- 2.7.4