From 64548b108119a23117924598442f621a04675369 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 7 Aug 2017 16:53:34 +0900 Subject: [PATCH 01/16] fix memory leak Change-Id: I3e259c314d069bc76884b96dba2b08d975060716 --- src/tdm_capture.c | 2 ++ src/tdm_pp.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/tdm_capture.c b/src/tdm_capture.c index 4772332..2bd1986 100644 --- a/src/tdm_capture.c +++ b/src/tdm_capture.c @@ -578,6 +578,8 @@ tdm_capture_commit(tdm_capture *capture) tdm_buffer_unref_backend(b->buffer); _pthread_mutex_lock(&private_display->lock); LIST_DEL(&b->link); + + free(b); } } diff --git a/src/tdm_pp.c b/src/tdm_pp.c index 02de669..52ef19b 100644 --- a/src/tdm_pp.c +++ b/src/tdm_pp.c @@ -496,6 +496,8 @@ tdm_pp_commit(tdm_pp *pp) tdm_buffer_unref_backend(b->dst); _pthread_mutex_lock(&private_display->lock); LIST_DEL(&b->link); + + free(b); } } -- 2.7.4 From 6aac53b7e9506ce76a53e2f5e8852f09b90b4c5d Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 7 Aug 2017 16:57:16 +0900 Subject: [PATCH 02/16] remove buffers from commit_buffer_list when commit failed. When pp, commit is the sync operation, cb_done() will be called at the line of commit(). In this case, buffers will be freed in cb_done() before LIST_FOR_EACH_ENTRY_SAFE(b, bb, &commit_buffer_list, commit_link) line done. So commit_link should be deleted when freed. When commit() successed, commit_link will be deleted twice. So we need to use LIST_DELINIT instead of LIST_DEL Change-Id: I6a09878e1eae49d31eb3f3626e005a3ae10841d8 --- src/tdm_capture.c | 3 ++- src/tdm_pp.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/tdm_capture.c b/src/tdm_capture.c index 2bd1986..6be39eb 100644 --- a/src/tdm_capture.c +++ b/src/tdm_capture.c @@ -149,6 +149,7 @@ tdm_capture_cb_done(tdm_capture *capture_backend, tbm_surface_h buffer, if ((capture_buffer = _tdm_capture_find_tbm_buffer(&private_capture->buffer_list, buffer))) { LIST_DEL(&capture_buffer->link); + LIST_DELINIT(&capture_buffer->commit_link); _pthread_mutex_unlock(&private_display->lock); if (private_capture->done_func) @@ -561,7 +562,7 @@ tdm_capture_commit(tdm_capture *capture) TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); LIST_FOR_EACH_ENTRY_SAFE(b, bb, &commit_buffer_list, commit_link) { - LIST_DEL(&b->commit_link); + LIST_DELINIT(&b->commit_link); if (!_tdm_capture_find_buffer(&private_capture->buffer_list, b)) continue; diff --git a/src/tdm_pp.c b/src/tdm_pp.c index 52ef19b..ab95105 100644 --- a/src/tdm_pp.c +++ b/src/tdm_pp.c @@ -150,6 +150,7 @@ tdm_pp_cb_done(tdm_pp *pp_backend, tbm_surface_h src, tbm_surface_h dst, if ((pp_buffer = _tdm_pp_find_tbm_buffers(&private_pp->buffer_list, src, dst))) { LIST_DEL(&pp_buffer->link); + LIST_DELINIT(&pp_buffer->commit_link); _pthread_mutex_unlock(&private_display->lock); if (private_pp->done_func) @@ -477,7 +478,7 @@ tdm_pp_commit(tdm_pp *pp) TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); LIST_FOR_EACH_ENTRY_SAFE(b, bb, &commit_buffer_list, commit_link) { - LIST_DEL(&b->commit_link); + LIST_DELINIT(&b->commit_link); if (!_tdm_pp_find_buffer(&private_pp->buffer_list, b)) continue; -- 2.7.4 From ac1f0059fbb5b8acb87137e06530601b08985a1f Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Mon, 7 Aug 2017 15:27:41 +0900 Subject: [PATCH 03/16] adapt ASLR for tdm-monitor and tools Change-Id: I14544a6fa5f4a9d4ded753ec12f031a7e09309ef --- client/Makefile.am | 5 ++++- tools/Makefile.am | 10 ++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/client/Makefile.am b/client/Makefile.am index becccc6..af2503f 100644 --- a/client/Makefile.am +++ b/client/Makefile.am @@ -36,9 +36,12 @@ bin_PROGRAMS = \ tdm_monitor_SOURCES = \ $(top_srcdir)/protocol/tdm-protocol.c \ tdm_monitor.c -tdm_monitor_LDFLAGS = ${LDFLAGS} +tdm_monitor_LDFLAGS = \ + -pie \ + ${LDFLAGS} tdm_monitor_LDADD = $(TDM_CLIENT_LIBS) ../common/libtdm-common.la tdm_monitor_CFLAGS = \ + -fPIE \ $(TDM_CFLAGS) \ -I$(top_srcdir)/include \ -I$(top_srcdir)/protocol \ diff --git a/tools/Makefile.am b/tools/Makefile.am index 2057e4a..d19e5e6 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -6,8 +6,11 @@ bin_PROGRAMS = \ tdm_test_server_SOURCES = \ buffers.c \ tdm_test_server.c -tdm_test_server_LDFLAGS = ${LDFLAGS} +tdm_test_server_LDFLAGS = \ + -pie \ + ${LDFLAGS} tdm_test_server_CFLAGS = \ + -fPIE \ $(TDM_CFLAGS) \ -I$(top_srcdir)/include \ -I$(top_srcdir)/src @@ -18,8 +21,11 @@ tdm_test_server_LDADD = \ #tdm-test-cliet tdm_test_client_SOURCES = \ tdm_test_client.c -tdm_test_client_LDFLAGS = ${LDFLAGS} +tdm_test_client_LDFLAGS = \ + -pie \ + ${LDFLAGS} tdm_test_client_CFLAGS = \ + -fPIE \ $(TDM_CFLAGS) \ -I$(top_srcdir)/include \ -I$(top_srcdir)/client \ -- 2.7.4 From ef47b57f107531c8db9d259da688655bed167df1 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 7 Aug 2017 19:30:08 +0900 Subject: [PATCH 04/16] package version up to 1.7.5 Change-Id: Id40ac9c7d9193125051433a0603f0abbf3a01871 --- packaging/libtdm.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libtdm.spec b/packaging/libtdm.spec index 5862dcf..574bf0c 100644 --- a/packaging/libtdm.spec +++ b/packaging/libtdm.spec @@ -1,7 +1,7 @@ %bcond_with utest Name: libtdm -Version: 1.7.4 +Version: 1.7.5 Release: 0 Summary: User Library of Tizen Display Manager Group: Development/Libraries -- 2.7.4 From ed1b259294d55a8f9876695482e403aca9665149 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Wed, 16 Aug 2017 14:04:00 +0900 Subject: [PATCH 05/16] client: enhance vblank logs Change-Id: I6b12bc6aa56a1d4cdd2c319d7172dc46945fbd20 --- client/tdm_client.c | 47 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index 4d8ba30..1604ca7 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -94,6 +94,8 @@ struct _tdm_private_client_vblank { unsigned int started; + double last_time; + struct list_head link; }; @@ -113,8 +115,7 @@ typedef struct _tdm_client_wait_info { void *user_data; unsigned int req_id; - unsigned int req_sec; - unsigned int req_usec; + double req_time; int need_free; struct list_head link; @@ -130,12 +131,20 @@ _tdm_client_vblank_cb_done(void *data, struct wl_tdm_vblank *wl_tdm_vblank, TDM_RETURN_IF_FAIL(private_vblank != NULL); + private_vblank->last_time = TDM_TIME(tv_sec, tv_usec); + + TDM_DBG("vblank(%p) req_id(%u) sequence(%u) time(%.6f)", + private_vblank, req_id, sequence, TDM_TIME(tv_sec, tv_usec)); + TDM_TRACE_COUNT(ClientDoneVBlank, req_id); LIST_FOR_EACH_ENTRY_SAFE(w, ww, &private_vblank->wait_list, link) { if (w->req_id != req_id) continue; + if (w->req_time >= private_vblank->last_time) + TDM_ERR("'req(%.6f) < last(%.6f)' failed", w->req_time, private_vblank->last_time); + if (w->func) w->func(private_vblank, error, sequence, tv_sec, tv_usec, w->user_data); @@ -751,6 +760,7 @@ tdm_client_vblank_wait(tdm_client_vblank *vblank, unsigned int interval, tdm_cli tdm_private_client_vblank *private_vblank; tdm_client_wait_info *w; struct timespec tp; + unsigned int req_sec, req_usec; int ret = 0; TDM_RETURN_VAL_IF_FAIL(vblank != NULL, TDM_ERROR_INVALID_PARAMETER); @@ -786,15 +796,23 @@ tdm_client_vblank_wait(tdm_client_vblank *vblank, unsigned int interval, tdm_cli LIST_ADDTAIL(&w->link, &private_vblank->wait_list); clock_gettime(CLOCK_MONOTONIC, &tp); + req_sec = (unsigned int)tp.tv_sec; + req_usec = (unsigned int)(tp.tv_nsec / 1000); + w->req_id = ++private_output->req_id; - w->req_sec = (unsigned int)tp.tv_sec; - w->req_usec = (unsigned int)(tp.tv_nsec / 1000); + w->req_time = TDM_TIME(req_sec, req_usec); w->need_free = (private_vblank->sync) ? 0 : 1; - wl_tdm_vblank_wait_vblank(private_vblank->vblank, interval, w->req_id, w->req_sec, w->req_usec); + wl_tdm_vblank_wait_vblank(private_vblank->vblank, interval, w->req_id, req_sec, req_usec); TDM_TRACE_COUNT(ClientWaitVBlank, w->req_id); + TDM_DBG("vblank(%p) interval(%u) req_id(%d) req(%.6f)", + vblank, interval, w->req_id, TDM_TIME(req_sec, req_usec)); + + if (private_vblank->last_time >= w->req_time) + TDM_ERR("'last(%.6f) < req(%.6f)' failed", private_vblank->last_time, w->req_time); + if (!private_vblank->sync) { wl_display_flush(private_client->display); return TDM_ERROR_NONE; @@ -806,7 +824,7 @@ tdm_client_vblank_wait(tdm_client_vblank *vblank, unsigned int interval, tdm_cli clock_gettime(CLOCK_MONOTONIC, &tp); TDM_DBG("block during %d us", ((unsigned int)(tp.tv_sec * 1000000) + (unsigned int)(tp.tv_nsec / 1000)) - - (w->req_sec * 1000000 + w->req_usec)); + - (req_sec * 1000000 + req_usec)); LIST_DEL(&w->link); free(w); @@ -823,6 +841,7 @@ tdm_client_vblank_wait_seq(tdm_client_vblank *vblank, unsigned int sequence, tdm_private_client_vblank *private_vblank; tdm_client_wait_info *w; struct timespec tp; + unsigned int req_sec, req_usec; int ret = 0; TDM_RETURN_VAL_IF_FAIL(vblank != NULL, TDM_ERROR_INVALID_PARAMETER); @@ -853,15 +872,23 @@ tdm_client_vblank_wait_seq(tdm_client_vblank *vblank, unsigned int sequence, LIST_ADDTAIL(&w->link, &private_vblank->wait_list); clock_gettime(CLOCK_MONOTONIC, &tp); + req_sec = (unsigned int)tp.tv_sec; + req_usec = (unsigned int)(tp.tv_nsec / 1000); + w->req_id = ++private_output->req_id; - w->req_sec = (unsigned int)tp.tv_sec; - w->req_usec = (unsigned int)(tp.tv_nsec / 1000); + w->req_time = TDM_TIME(req_sec, req_usec); w->need_free = (private_vblank->sync) ? 0 : 1; - wl_tdm_vblank_wait_vblank_seq(private_vblank->vblank, sequence, w->req_id, w->req_sec, w->req_usec); + wl_tdm_vblank_wait_vblank_seq(private_vblank->vblank, sequence, w->req_id, req_sec, req_usec); TDM_TRACE_COUNT(ClientWaitVBlank, w->req_id); + TDM_DBG("vblank(%p) sequence(%u) req_id(%d) req(%.6f)", + vblank, sequence, w->req_id, TDM_TIME(req_sec, req_usec)); + + if (private_vblank->last_time >= w->req_time) + TDM_ERR("'last(%.6f) < req(%.6f)' failed", private_vblank->last_time, w->req_time); + if (!private_vblank->sync) { wl_display_flush(private_client->display); return TDM_ERROR_NONE; @@ -873,7 +900,7 @@ tdm_client_vblank_wait_seq(tdm_client_vblank *vblank, unsigned int sequence, clock_gettime(CLOCK_MONOTONIC, &tp); TDM_DBG("block during %d us", ((unsigned int)(tp.tv_sec * 1000000) + (unsigned int)(tp.tv_nsec / 1000)) - - (w->req_sec * 1000000 + w->req_usec)); + - (req_sec * 1000000 + req_usec)); LIST_DEL(&w->link); free(w); -- 2.7.4 From 37d61fb89d1ac9c1a8a7081a7dd9883c6c221eaa Mon Sep 17 00:00:00 2001 From: Boram Park Date: Wed, 16 Aug 2017 14:06:44 +0900 Subject: [PATCH 06/16] vblank: correct the client request time The client request time SHOULD be bigger than the last vblank time. To make sure it, we forcely set the last vblank time to the client request time when the req_time is smaller than the last_time. Change-Id: Ib1dbec907fa04693d6df05b8260e300f6032563e --- src/tdm_vblank.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/tdm_vblank.c b/src/tdm_vblank.c index 88a5084..0cff134 100644 --- a/src/tdm_vblank.c +++ b/src/tdm_vblank.c @@ -818,6 +818,10 @@ _tdm_vblank_wait_HW(tdm_vblank_wait_info *wait_info) last = private_vblank->last_time; req = wait_info->req_time; + /* make sure that req time is bigger than last. */ + if (req < last) + req = last; + skip = (unsigned int)((req - last) / private_vblank->vblank_gap + TDM_TIME_MARGIN); prev = last + private_vblank->vblank_gap * skip; @@ -965,6 +969,10 @@ _tdm_vblank_wait_SW(tdm_vblank_wait_info *wait_info) last = private_vblank->last_time; req = wait_info->req_time; + /* make sure that req time is bigger than last. */ + if (req < last) + req = last; + skip = (unsigned int)((req - last) / private_vblank->vblank_gap + TDM_TIME_MARGIN); prev = last + private_vblank->vblank_gap * skip; -- 2.7.4 From aab186afb9fd1c1b41fce0793c852e7db07e099f Mon Sep 17 00:00:00 2001 From: Boram Park Date: Wed, 16 Aug 2017 14:23:05 +0900 Subject: [PATCH 07/16] client: change log level Change-Id: I7e3cdf1e0104cc556da6b0407d1dc403c36f75e5 --- client/tdm_client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index 1604ca7..858e4f5 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -143,7 +143,7 @@ _tdm_client_vblank_cb_done(void *data, struct wl_tdm_vblank *wl_tdm_vblank, continue; if (w->req_time >= private_vblank->last_time) - TDM_ERR("'req(%.6f) < last(%.6f)' failed", w->req_time, private_vblank->last_time); + TDM_WRN("'req(%.6f) < last(%.6f)' failed", w->req_time, private_vblank->last_time); if (w->func) w->func(private_vblank, error, sequence, tv_sec, tv_usec, w->user_data); -- 2.7.4 From b65dd59a429bac51cbb52037988f20a5c66aac62 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Wed, 16 Aug 2017 14:23:43 +0900 Subject: [PATCH 08/16] package version up to 1.7.6 Change-Id: I8598c7f16df9c651f79f53aabf6bc7009e691b21 --- packaging/libtdm.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libtdm.spec b/packaging/libtdm.spec index 574bf0c..1003c6a 100644 --- a/packaging/libtdm.spec +++ b/packaging/libtdm.spec @@ -1,7 +1,7 @@ %bcond_with utest Name: libtdm -Version: 1.7.5 +Version: 1.7.6 Release: 0 Summary: User Library of Tizen Display Manager Group: Development/Libraries -- 2.7.4 From 6d033cebc3f8455d76431c608cfc5c00cc2ac358 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Sat, 19 Aug 2017 16:41:33 +0900 Subject: [PATCH 09/16] layer: dump layer buffers when showing Change-Id: I157ff0b26fdbbb71cea08d5c65a99691dffbbae2 --- src/tdm_layer.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/tdm_layer.c b/src/tdm_layer.c index e751f54..1488e28 100644 --- a/src/tdm_layer.c +++ b/src/tdm_layer.c @@ -281,13 +281,23 @@ _tdm_layer_dump_buffer(tdm_layer *layer, tbm_surface_h buffer) tdm_private_layer *private_layer = (tdm_private_layer*)layer; tdm_private_output *private_output = private_layer->private_output; unsigned int pipe; - int zpos; - char fname[PATH_MAX]; + char fname[PATH_MAX], bufs[PATH_MAX]; + int zpos, len = PATH_MAX; + tdm_private_layer *l = NULL; + char *p = bufs; + int *remain = &len; pipe = private_output->pipe; zpos = private_layer->caps.zpos; - snprintf(fname, sizeof(fname), "tdm_%d_lyr_%d", pipe, zpos); + bufs[0] = '\0'; + LIST_FOR_EACH_ENTRY(l, &private_output->layer_list, link) { + if (!l->showing_buffer) + continue; + TDM_SNPRINTF(p, remain, "_%p", l->showing_buffer->buffer); + } + + snprintf(fname, sizeof(fname), "tdm_%d_lyr_%d%s", pipe, zpos, bufs); tbm_surface_internal_dump_buffer(buffer, fname); TDM_DBG("%s dump excute", fname); @@ -431,10 +441,6 @@ tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer) ret = func_layer->layer_set_buffer(private_layer->layer_backend, buffer); TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); - /* dump buffer */ - if (tdm_dump_enable && !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) - _tdm_layer_dump_buffer(layer, buffer); - if (ret == TDM_ERROR_NONE) { if (private_layer->waiting_buffer) _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer); @@ -510,6 +516,10 @@ tdm_layer_committed(tdm_private_layer *private_layer, tdm_private_layer_buffer * private_layer->showing_buffer = *committed_buffer; *committed_buffer = NULL; + /* dump buffer */ + if (tdm_dump_enable && !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO) && private_layer->showing_buffer) + _tdm_layer_dump_buffer(private_layer, private_layer->showing_buffer->buffer); + if (tdm_debug_module & TDM_DEBUG_BUFFER) TDM_INFO("layer(%p) committed_buffer(%p) showing_buffer(%p)", private_layer, *committed_buffer, -- 2.7.4 From c15f22ca21d310185c6a4f4b3fc4b55c8389d773 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Tue, 22 Aug 2017 13:23:35 +0900 Subject: [PATCH 10/16] correct wrong description Change-Id: I2b5110d70a8ae81ac805d557c0b6715256947cbc --- include/tdm_helper.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/include/tdm_helper.h b/include/tdm_helper.h index ef0a657..176279b 100644 --- a/include/tdm_helper.h +++ b/include/tdm_helper.h @@ -81,12 +81,6 @@ tdm_helper_dump_buffer(tbm_surface_h buffer, const char *file); * This function supports only if a buffer has below formats. * - TBM_FORMAT_ARGB8888 * - TBM_FORMAT_XRGB8888 - * - TBM_FORMAT_YVU420 - * - TBM_FORMAT_YUV420 - * - TBM_FORMAT_NV12 - * - TBM_FORMAT_NV21 - * - TBM_FORMAT_YUYV - * - TBM_FORMAT_UYVY * @param[in] buffer A TDM buffer */ void -- 2.7.4 From 224add70bc00208471268a44ff1a49a0ad9daaec Mon Sep 17 00:00:00 2001 From: Boram Park Date: Tue, 22 Aug 2017 13:24:19 +0900 Subject: [PATCH 11/16] add tdm_helper_clear_buffer_color function Change-Id: I033f2212eb057b9896cb5d37e0d6eacb059994a5 --- include/tdm_helper.h | 11 +++++++++++ src/tdm_helper.c | 16 ++++++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/include/tdm_helper.h b/include/tdm_helper.h index 176279b..1459e72 100644 --- a/include/tdm_helper.h +++ b/include/tdm_helper.h @@ -87,6 +87,17 @@ void tdm_helper_clear_buffer_pos(tbm_surface_h buffer, tdm_pos *pos); /** + * @brief fill a buffer with 0 for given pos. + * @details + * This function supports only if a buffer has below formats. + * - TBM_FORMAT_ARGB8888 + * - TBM_FORMAT_XRGB8888 + * @param[in] buffer A TDM buffer + */ +void +tdm_helper_clear_buffer_color(tbm_surface_h buffer, tdm_pos *pos, unsigned int color); + +/** * @brief fill a buffer with 0. * @details * This function supports only if a buffer has below formats. diff --git a/src/tdm_helper.c b/src/tdm_helper.c index 947d41e..fc271fb 100644 --- a/src/tdm_helper.c +++ b/src/tdm_helper.c @@ -350,8 +350,8 @@ tdm_helper_dump_buffer(tbm_surface_h buffer, const char *file) TDM_INFO("dump %s", file); } -void -tdm_helper_clear_buffer_pos(tbm_surface_h buffer, tdm_pos *pos) +EXTERN void +tdm_helper_clear_buffer_color(tbm_surface_h buffer, tdm_pos *pos, unsigned int color) { tbm_surface_info_s info; int ret; @@ -372,8 +372,8 @@ tdm_helper_clear_buffer_pos(tbm_surface_h buffer, tdm_pos *pos) for (y = pos->y; y <= (pos->y + pos->h); y++) { p = info.planes[0].ptr + info.planes[0].stride * y; for (x = pos->x; x <= (pos->x + pos->w); x++) { - int *ibuf = (int*)p; - ibuf[x] = 0x00000000; + unsigned int *ibuf = (unsigned int*)p; + ibuf[x] = color; } } } @@ -414,6 +414,14 @@ tdm_helper_clear_buffer_pos(tbm_surface_h buffer, tdm_pos *pos) } EXTERN void +tdm_helper_clear_buffer_pos(tbm_surface_h buffer, tdm_pos *pos) +{ + TDM_RETURN_IF_FAIL(buffer != NULL); + + tdm_helper_clear_buffer_color(buffer, pos, 0); +} + +EXTERN void tdm_helper_clear_buffer(tbm_surface_h buffer) { TDM_RETURN_IF_FAIL(buffer != NULL); -- 2.7.4 From 2f78ce60d7d46d28f5cbbe6ef4dcc6ff2d8e5061 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Tue, 22 Aug 2017 13:25:48 +0900 Subject: [PATCH 12/16] dump layer when calling tdm_layer_set_buffer To dump all buffers of a layer, set_buffer function is much better than layer_committed function. Change-Id: I51c3daf926490a23764067e4a75fa6a12cab5f18 --- src/tdm_layer.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tdm_layer.c b/src/tdm_layer.c index 1488e28..c6128a8 100644 --- a/src/tdm_layer.c +++ b/src/tdm_layer.c @@ -441,6 +441,10 @@ tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer) ret = func_layer->layer_set_buffer(private_layer->layer_backend, buffer); TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); + /* dump buffer */ + if (tdm_dump_enable && !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) + _tdm_layer_dump_buffer(layer, buffer); + if (ret == TDM_ERROR_NONE) { if (private_layer->waiting_buffer) _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer); @@ -516,10 +520,6 @@ tdm_layer_committed(tdm_private_layer *private_layer, tdm_private_layer_buffer * private_layer->showing_buffer = *committed_buffer; *committed_buffer = NULL; - /* dump buffer */ - if (tdm_dump_enable && !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO) && private_layer->showing_buffer) - _tdm_layer_dump_buffer(private_layer, private_layer->showing_buffer->buffer); - if (tdm_debug_module & TDM_DEBUG_BUFFER) TDM_INFO("layer(%p) committed_buffer(%p) showing_buffer(%p)", private_layer, *committed_buffer, -- 2.7.4 From 33bb942033e5e34a5e56bd7bf2454dd1dcd8e49c Mon Sep 17 00:00:00 2001 From: Boram Park Date: Tue, 22 Aug 2017 15:14:06 +0900 Subject: [PATCH 13/16] package version up to 1.7.7 Change-Id: I523415f93746816f933806d07f6c1d2f03088895 --- packaging/libtdm.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libtdm.spec b/packaging/libtdm.spec index 1003c6a..8c78b8b 100644 --- a/packaging/libtdm.spec +++ b/packaging/libtdm.spec @@ -1,7 +1,7 @@ %bcond_with utest Name: libtdm -Version: 1.7.6 +Version: 1.7.7 Release: 0 Summary: User Library of Tizen Display Manager Group: Development/Libraries -- 2.7.4 From cc83dac60da6c4960a9e740ac5a74cde8197b685 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Thu, 31 Aug 2017 14:31:56 +0900 Subject: [PATCH 14/16] tdm-monitor: fix big message issue Wayland has the 4096 message size restriction. So if tdm debug message is bigger than that, the message will be devided. Change-Id: I3ba57801bb149c489577ad1adff2c8befc69e69f --- client/tdm_monitor.c | 32 ++++++++++++++++++++++++++------ protocol/tdm.xml | 4 +++- src/tdm_macro.h | 4 ++++ src/tdm_server.c | 27 +++++++++++++++++++++++---- src/tdm_vblank.c | 10 ++++++---- 5 files changed, 62 insertions(+), 15 deletions(-) diff --git a/client/tdm_monitor.c b/client/tdm_monitor.c index fe69cce..cdfa1f7 100644 --- a/client/tdm_monitor.c +++ b/client/tdm_monitor.c @@ -54,20 +54,36 @@ typedef struct _tdm_monitor_info { struct wl_display *display; struct wl_registry *registry; struct wl_tdm *tdm; + + struct { + int done; + char message[TDM_SERVER_REPLY_MSG_LEN]; + char *m; + int len; + int *l; + } debug; } tdm_monitor_info; static tdm_monitor_info td_info; -static int done; static void -_tdm_monitor_cb_debug_done(void *data, struct wl_tdm *wl_tdm, const char *message) +_tdm_monitor_cb_debug_message(void *data, struct wl_tdm *wl_tdm, const char *message) { - printf("%s", message); + tdm_monitor_info *info = data; + TDM_SNPRINTF(info->debug.m, info->debug.l, "%s", message); +} - done = 1; +static void +_tdm_monitor_cb_debug_done(void *data, struct wl_tdm *wl_tdm) +{ + tdm_monitor_info *info = data; + info->debug.done = 1; + *(info->debug.m) = '\0'; + printf("%s", info->debug.message); } static const struct wl_tdm_listener tdm_monitor_listener = { + _tdm_monitor_cb_debug_message, _tdm_monitor_cb_debug_done, }; @@ -137,11 +153,15 @@ main(int argc, char ** argv) for (i = 0; i < argc; i++) TDM_SNPRINTF(str_buf, len_buf, "%s ", argv[i]); - done = 0; + info->debug.done = 0; + info->debug.message[0] = '\0'; + info->debug.len = sizeof(info->debug.message); + info->debug.m = info->debug.message; + info->debug.l = &info->debug.len; wl_tdm_debug(info->tdm, options); - while (!done && ret >= 0) + while (!info->debug.done && ret >= 0) ret = wl_display_dispatch(info->display); if (info->tdm) diff --git a/protocol/tdm.xml b/protocol/tdm.xml index bd5ed89..47e6536 100644 --- a/protocol/tdm.xml +++ b/protocol/tdm.xml @@ -8,10 +8,12 @@ TDM uses the wayland protocol to communicate between tdm client and tdm server. - + + + diff --git a/src/tdm_macro.h b/src/tdm_macro.h index 6da02b4..504315a 100644 --- a/src/tdm_macro.h +++ b/src/tdm_macro.h @@ -49,6 +49,7 @@ extern "C" { #endif #define TDM_SERVER_REPLY_MSG_LEN 8192 +#define TDM_DEBUG_REPLY_MSG_LEN 2048 #undef EXTERN #undef DEPRECATED @@ -138,6 +139,9 @@ extern "C" { #define TDM_NOT_DEFINED_VALUE (-1) #define TDM_FRONT_VALUE(n) (((n) > 0) ? (n) : TDM_NOT_DEFINED_VALUE) +#define TDM_MAX(x, y) (((x) > (y)) ? (x) : (y)) +#define TDM_MIN(x, y) (((x) < (y)) ? (x) : (y)) + #define TDM_TIME(sec, usec) ((double)(sec) + ((double)(usec)) / 1000000.0) #define TDM_TIME_SEC(time) ((unsigned int)(time)) #define TDM_TIME_USEC(time) (unsigned int)(((time) - (unsigned int)(time)) * 1000000.0) diff --git a/src/tdm_server.c b/src/tdm_server.c index bd9cd9f..b69926b 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -546,19 +546,38 @@ _tdm_server_cb_debug(struct wl_client *client, struct wl_resource *resource, con tdm_private_server *private_server = wl_resource_get_user_data(resource); tdm_private_loop *private_loop = private_server->private_loop; char message[TDM_SERVER_REPLY_MSG_LEN]; - int size = sizeof(message); + char *m; + int len = sizeof(message), size; uid_t uid; wl_client_get_credentials(client, NULL, &uid, NULL); if (uid != 0) { - snprintf(message, size, "tdm-monitor: SHOULD be a superuser.\n"); + snprintf(message, len, "tdm-monitor: SHOULD be a superuser.\n"); TDM_ERR("%s", message); } else { - tdm_monitor_server_command(private_loop->dpy, options, message, &size); + tdm_monitor_server_command(private_loop->dpy, options, message, &len); } - wl_tdm_send_debug_done(resource, message); + size = sizeof(message) - len; + m = message; + + wl_client_flush(wl_resource_get_client(resource)); + + while (size > 0) { + char buffer[TDM_DEBUG_REPLY_MSG_LEN]; + int copylen = TDM_MIN(size, sizeof(buffer) - 1); + + strncpy(buffer, m, copylen); + m += copylen; + size -= copylen; + + buffer[copylen] = '\0'; + + wl_tdm_send_debug_message(resource, buffer); + } + + wl_tdm_send_debug_done(resource); } static void diff --git a/src/tdm_vblank.c b/src/tdm_vblank.c index 0cff134..97deab5 100644 --- a/src/tdm_vblank.c +++ b/src/tdm_vblank.c @@ -1196,13 +1196,15 @@ tdm_vblank_get_vblank_list_information(tdm_display *dpy, char *reply, int *len) pthread_mutex_lock(&valid_list_lock); LIST_FOR_EACH_ENTRY(v, &valid_vblank_list, valid_link) { - struct wl_client *client = wl_resource_get_client(v->resource); const char *proc_name = NULL; pid_t pid = 0; - if (client) { - wl_client_get_credentials(client, &pid, NULL, NULL); - proc_name = tdm_server_get_client_name(pid); + if (v->resource) { + struct wl_client *client = wl_resource_get_client(v->resource); + if (client) { + wl_client_get_credentials(client, &pid, NULL, NULL); + proc_name = tdm_server_get_client_name(pid); + } } TDM_SNPRINTF(reply, len, "%-12s %u %u %d %u %s (pid: %u)\n", -- 2.7.4 From d2014e64bf637ccf6399aed6abc1f91ed30d820b Mon Sep 17 00:00:00 2001 From: Boram Park Date: Fri, 8 Sep 2017 11:07:43 +0900 Subject: [PATCH 15/16] add get_dpms, get_connection, get_mode request If a client adds the change_handler, we might be able to guess that the client will watch the tdm client's fd and handle tdm events in event loop. Otherwise, we CAN'T make sure if a client has event loop which handles tdm events. Change-Id: I49685d7eb3b88cda59b167f5ae66a7e9501a2315 --- client/tdm_client.c | 66 +++++++++++++++++++++++++---- protocol/tdm.xml | 6 +++ src/tdm_server.c | 120 +++++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 167 insertions(+), 25 deletions(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index 858e4f5..04c9d2f 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -76,6 +76,7 @@ typedef struct _tdm_private_client_output { struct list_head change_handler_list; unsigned int req_id; + unsigned int watch_output_changes; struct list_head link; } tdm_private_client_output; @@ -508,9 +509,18 @@ tdm_client_output_add_change_handler(tdm_client_output *output, h = calloc(1, sizeof *h); TDM_RETURN_VAL_IF_FAIL(h != NULL, TDM_ERROR_OUT_OF_MEMORY); - if (LIST_IS_EMPTY(&private_output->change_handler_list)) + if (LIST_IS_EMPTY(&private_output->change_handler_list)) { wl_tdm_output_watch_output_changes(private_output->output, 1); + /* TODO: this is very tricky. + * If a client adds the change_handler, we might be able to guess that + * the client will watch the tdm client's fd and handle tdm events in + * event loop. Otherwise, we CAN'T make sure if a client has event loop + * which handles tdm events. + */ + private_output->watch_output_changes = 1; + } + h->private_output = private_output; h->func = func; h->user_data = user_data; @@ -550,12 +560,24 @@ tdm_error tdm_client_output_get_refresh_rate(tdm_client_output *output, unsigned int *refresh) { tdm_private_client_output *private_output; + tdm_private_client *private_client; TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); TDM_RETURN_VAL_IF_FAIL(refresh != NULL, TDM_ERROR_INVALID_PARAMETER); private_output = (tdm_private_client_output*)output; + if (private_output->watch_output_changes) { + *refresh = private_output->refresh; + return TDM_ERROR_NONE; + } + + private_client = private_output->private_client; + TDM_RETURN_VAL_IF_FAIL(private_client != NULL, TDM_ERROR_INVALID_PARAMETER); + + wl_tdm_output_get_mode(private_output->output); + wl_display_roundtrip(private_client->display); + *refresh = private_output->refresh; return TDM_ERROR_NONE; @@ -565,12 +587,24 @@ tdm_error tdm_client_output_get_conn_status(tdm_client_output *output, tdm_output_conn_status *status) { tdm_private_client_output *private_output; + tdm_private_client *private_client; TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); TDM_RETURN_VAL_IF_FAIL(status != NULL, TDM_ERROR_INVALID_PARAMETER); private_output = (tdm_private_client_output*)output; + if (private_output->watch_output_changes) { + *status = private_output->connection; + return TDM_ERROR_NONE; + } + + private_client = private_output->private_client; + TDM_RETURN_VAL_IF_FAIL(private_client != NULL, TDM_ERROR_INVALID_PARAMETER); + + wl_tdm_output_get_connection(private_output->output); + wl_display_roundtrip(private_client->display); + *status = private_output->connection; return TDM_ERROR_NONE; @@ -580,12 +614,24 @@ tdm_error tdm_client_output_get_dpms(tdm_client_output *output, tdm_output_dpms *dpms) { tdm_private_client_output *private_output; + tdm_private_client *private_client; TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); TDM_RETURN_VAL_IF_FAIL(dpms != NULL, TDM_ERROR_INVALID_PARAMETER); private_output = (tdm_private_client_output*)output; + if (private_output->watch_output_changes) { + *dpms = private_output->dpms; + return TDM_ERROR_NONE; + } + + private_client = private_output->private_client; + TDM_RETURN_VAL_IF_FAIL(private_client != NULL, TDM_ERROR_INVALID_PARAMETER); + + wl_tdm_output_get_dpms(private_output->output); + wl_display_roundtrip(private_client->display); + *dpms = private_output->dpms; return TDM_ERROR_NONE; @@ -778,10 +824,11 @@ tdm_client_vblank_wait(tdm_client_vblank *vblank, unsigned int interval, tdm_cli if (!private_vblank->started) private_vblank->started = 1; - if (private_output->dpms != TDM_OUTPUT_DPMS_ON && !private_vblank->enable_fake) { - TDM_INFO("dpms off"); - return TDM_ERROR_DPMS_OFF; - } + if (private_output->watch_output_changes) + if (private_output->dpms != TDM_OUTPUT_DPMS_ON && !private_vblank->enable_fake) { + TDM_INFO("dpms off"); + return TDM_ERROR_DPMS_OFF; + } w = calloc(1, sizeof *w); if (!w) { @@ -854,10 +901,11 @@ tdm_client_vblank_wait_seq(tdm_client_vblank *vblank, unsigned int sequence, if (!private_vblank->started) private_vblank->started = 1; - if (private_output->dpms != TDM_OUTPUT_DPMS_ON && !private_vblank->enable_fake) { - TDM_INFO("dpms off"); - return TDM_ERROR_DPMS_OFF; - } + if (private_output->watch_output_changes) + if (private_output->dpms != TDM_OUTPUT_DPMS_ON && !private_vblank->enable_fake) { + TDM_INFO("dpms off"); + return TDM_ERROR_DPMS_OFF; + } w = calloc(1, sizeof *w); if (!w) { diff --git a/protocol/tdm.xml b/protocol/tdm.xml index 47e6536..dcd99ed 100644 --- a/protocol/tdm.xml +++ b/protocol/tdm.xml @@ -61,6 +61,12 @@ + + + + + + diff --git a/src/tdm_server.c b/src/tdm_server.c index b69926b..c49e9db 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -451,10 +451,94 @@ _tdm_server_output_cb_watch_output_changes(struct wl_client *client, struct wl_r output_info->watch_output_changes = enable; } +static void +_tdm_server_output_cb_get_connection(struct wl_client *client, struct wl_resource *resource) +{ + tdm_server_output_info *output_info = wl_resource_get_user_data(resource); + tdm_output_conn_status status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED; + tdm_error ret; + + TDM_RETURN_IF_FAIL(output_info != NULL); + + ret = tdm_output_get_conn_status(output_info->output, &status); + TDM_GOTO_IF_FAIL(ret != TDM_ERROR_NONE, failed); + + wl_tdm_output_send_connection(output_info->resource, status); + + return; + +failed: + wl_tdm_output_send_connection(output_info->resource, TDM_OUTPUT_CONN_STATUS_DISCONNECTED); +} + +static void +_tdm_server_output_cb_get_mode(struct wl_client *client, struct wl_resource *resource) +{ + tdm_server_output_info *output_info = wl_resource_get_user_data(resource); + tdm_output_conn_status status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED; + tdm_error ret; + + TDM_RETURN_IF_FAIL(output_info != NULL); + + ret = tdm_output_get_conn_status(output_info->output, &status); + TDM_GOTO_IF_FAIL(ret != TDM_ERROR_NONE, failed); + + if (status != TDM_OUTPUT_CONN_STATUS_DISCONNECTED) { + const tdm_output_mode *mode = NULL; + unsigned int hdisplay, vdisplay, vrefresh; + + ret = tdm_output_get_mode(output_info->output, &mode); + TDM_GOTO_IF_FAIL(ret != TDM_ERROR_NONE, failed); + + hdisplay = (mode) ? mode->hdisplay : 0; + vdisplay = (mode) ? mode->vdisplay : 0; + vrefresh = (mode) ? mode->vrefresh : 0; + + wl_tdm_output_send_mode(output_info->resource, hdisplay, vdisplay, vrefresh); + } else { + wl_tdm_output_send_mode(output_info->resource, 0, 0, 0); + } + + return; +failed: + wl_tdm_output_send_mode(output_info->resource, 0, 0, 0); +} + +static void +_tdm_server_output_cb_get_dpms(struct wl_client *client, struct wl_resource *resource) +{ + tdm_server_output_info *output_info = wl_resource_get_user_data(resource); + tdm_output_conn_status status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED; + tdm_error ret; + + TDM_RETURN_IF_FAIL(output_info != NULL); + + ret = tdm_output_get_conn_status(output_info->output, &status); + TDM_GOTO_IF_FAIL(ret != TDM_ERROR_NONE, failed); + + if (status != TDM_OUTPUT_CONN_STATUS_DISCONNECTED) { + tdm_output_dpms dpms_value = TDM_OUTPUT_DPMS_OFF; + + ret = tdm_output_get_dpms(output_info->output, &dpms_value); + TDM_GOTO_IF_FAIL(ret != TDM_ERROR_NONE, failed); + + wl_tdm_output_send_dpms(output_info->resource, dpms_value); + } else { + wl_tdm_output_send_dpms(output_info->resource, TDM_OUTPUT_DPMS_OFF); + } + + return; +failed: + wl_tdm_output_send_dpms(output_info->resource, TDM_OUTPUT_DPMS_OFF); +} + static const struct wl_tdm_output_interface tdm_output_implementation = { _tdm_server_output_cb_destroy, _tdm_server_output_cb_create_vblank, _tdm_server_output_cb_watch_output_changes, + _tdm_server_output_cb_get_connection, + _tdm_server_output_cb_get_mode, + _tdm_server_output_cb_get_dpms, }; static void @@ -484,9 +568,7 @@ _tdm_server_cb_create_output(struct wl_client *client, struct wl_resource *resou tdm_server_output_info *output_info; struct wl_resource *output_resource = NULL; tdm_output *output; - const tdm_output_mode *mode = NULL; - tdm_output_dpms dpms_value; - tdm_output_conn_status status; + tdm_output_conn_status status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED; output = _tdm_server_find_output(private_server, name); if (!output) { @@ -496,17 +578,6 @@ _tdm_server_cb_create_output(struct wl_client *client, struct wl_resource *resou return; } - tdm_output_get_mode(output, &mode); - if (!mode) { - TDM_ERR("no mode for '%s' output", name); - wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, - "no mode for '%s' output", name); - return; - } - - tdm_output_get_dpms(output, &dpms_value); - tdm_output_get_conn_status(output, &status); - output_resource = wl_resource_create(client, &wl_tdm_output_interface, wl_resource_get_version(resource), id); @@ -535,9 +606,26 @@ _tdm_server_cb_create_output(struct wl_client *client, struct wl_resource *resou wl_resource_set_implementation(output_resource, &tdm_output_implementation, output_info, destroy_output_callback); - wl_tdm_output_send_mode(output_resource, mode->hdisplay, mode->vdisplay, mode->vrefresh); - wl_tdm_output_send_dpms(output_resource, dpms_value); + tdm_output_get_conn_status(output, &status); wl_tdm_output_send_connection(output_resource, status); + + if (status != TDM_OUTPUT_CONN_STATUS_DISCONNECTED) { + tdm_output_dpms dpms_value = TDM_OUTPUT_DPMS_OFF; + const tdm_output_mode *mode = NULL; + unsigned int hdisplay, vdisplay, vrefresh; + + tdm_output_get_mode(output, &mode); + hdisplay = (mode) ? mode->hdisplay : 0; + vdisplay = (mode) ? mode->vdisplay : 0; + vrefresh = (mode) ? mode->vrefresh : 0; + wl_tdm_output_send_mode(output_resource, hdisplay, vdisplay, vrefresh); + + tdm_output_get_dpms(output, &dpms_value); + wl_tdm_output_send_dpms(output_resource, dpms_value); + } else { + wl_tdm_output_send_mode(output_resource, 0, 0, 0); + wl_tdm_output_send_dpms(output_resource, TDM_OUTPUT_DPMS_OFF); + } } static void -- 2.7.4 From db326e629f76e9470f540d2719675c28dea2a26a Mon Sep 17 00:00:00 2001 From: Boram Park Date: Fri, 8 Sep 2017 11:57:25 +0900 Subject: [PATCH 16/16] add error type for output disconnection Change-Id: I7450a453217d138cb73e8be289e72682a13bf768 --- include/tdm_common.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/tdm_common.h b/include/tdm_common.h index dfb3f8e..054cb5e 100644 --- a/include/tdm_common.h +++ b/include/tdm_common.h @@ -67,6 +67,7 @@ typedef enum { TDM_ERROR_NOT_IMPLEMENTED = -8, /**< not implemented */ TDM_ERROR_NO_CAPABILITY = -9, /**< no capability */ TDM_ERROR_DPMS_OFF = -10, /**< dpms off */ + TDM_ERROR_OUTPUT_DISCONNECTED = -11, /**< output disconnected */ } tdm_error; /** -- 2.7.4