From 8f6880f3201d181533298cabf83a9e6f1006529c Mon Sep 17 00:00:00 2001 From: Boram Park Date: Wed, 17 Jan 2018 09:55:00 +0900 Subject: [PATCH 01/16] fix typo Change-Id: I37f372b390417910997ec3f059afc52aa1e23a3c --- configure.ac | 2 +- src/tdm_output.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 739c1b7..26ba06d 100644 --- a/configure.ac +++ b/configure.ac @@ -64,7 +64,7 @@ AC_SUBST(TDM_LIBS) AC_SUBST(TDM_CLIENT_CFLAGS) AC_SUBST(TDM_CLIENT_LIBS) -# set the dir for the tbm module +# set the dir for the tdm module DEFAULT_TDM_MODULE_PATH="${libdir}/tdm" AC_ARG_WITH(tdm-module-path, AS_HELP_STRING([--with-tdm-module-path=PATH], [tdm module dir]), [ TDM_MODULE_PATH="$withval" ], diff --git a/src/tdm_output.c b/src/tdm_output.c index c58c272..c9fba68 100644 --- a/src/tdm_output.c +++ b/src/tdm_output.c @@ -202,7 +202,7 @@ tdm_output_add_change_handler(tdm_output *output, TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER); - pthread_mutex_lock(&private_display->lock); + _pthread_mutex_lock(&private_display->lock); change_handler = calloc(1, sizeof(tdm_private_change_handler)); if (!change_handler) { -- 2.7.4 From 3839085bf20014f21172bdd5dbcd2d6d76b03053 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Wed, 17 Jan 2018 10:30:28 +0900 Subject: [PATCH 02/16] add debugging log Change-Id: I7c758cba21e6398890e7441071b63d6354425f65 --- src/tdm_thread.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/tdm_thread.c b/src/tdm_thread.c index 22d67af..f71f3a1 100644 --- a/src/tdm_thread.c +++ b/src/tdm_thread.c @@ -245,7 +245,8 @@ tdm_thread_handle_cb(tdm_private_loop *private_loop) tdm_private_thread *private_thread; tdm_thread_cb_base *base; char buffer[1024]; - unsigned int len, i; + unsigned int i; + int len; /* DON'T check TDM_MUTEX_IS_LOCKED here */ @@ -255,16 +256,23 @@ tdm_thread_handle_cb(tdm_private_loop *private_loop) private_thread = private_loop->private_thread; private_display = private_loop->dpy; - len = read(private_thread->pipe[0], buffer, sizeof buffer); + do { + len = read(private_thread->pipe[0], buffer, sizeof buffer); + } while (len < 0 && errno == EINTR); if (tdm_debug_module & TDM_DEBUG_THREAD) TDM_INFO("fd(%d) read length(%d)", private_thread->pipe[0], len); + if (len < 0) { + TDM_ERR("read failed: errno(%d), len(%d) %m", errno, len); + return TDM_ERROR_OPERATION_FAILED; + } + if (len == 0) return TDM_ERROR_NONE; if (len < sizeof * base) { - TDM_NEVER_GET_HERE(); + TDM_ERR("read failed: len(%d)", len); return TDM_ERROR_OPERATION_FAILED; } -- 2.7.4 From 7d1e761e8277ef3cb5d07593cbdd592ace8e6c99 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Thu, 18 Jan 2018 07:59:17 +0900 Subject: [PATCH 03/16] macro: re-ordered Change-Id: I91dbc2259a1bc08ecf43d28e3bfb4e863e557a41 --- src/tdm_macro.h | 215 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 111 insertions(+), 104 deletions(-) diff --git a/src/tdm_macro.h b/src/tdm_macro.h index 78e2643..428b38f 100644 --- a/src/tdm_macro.h +++ b/src/tdm_macro.h @@ -50,96 +50,7 @@ extern "C" { #endif -#define TDM_DUMP_DIR "/tmp" - -#define TDM_SERVER_REPLY_MSG_LEN 8192 -#define TDM_DEBUG_REPLY_MSG_LEN 2048 - -#undef EXTERN -#undef DEPRECATED -#undef INTERN - -#if defined(__GNUC__) && __GNUC__ >= 4 -#define EXTERN __attribute__ ((visibility("default"))) -#else -#define EXTERN -#endif - -#if defined(__GNUC__) && __GNUC__ >= 4 -#define INTERN __attribute__ ((visibility("hidden"))) -#else -#define INTERN -#endif - -#if defined(__GNUC__) && __GNUC__ >= 4 -#define DEPRECATED __attribute__ ((deprecated)) -#else -#define DEPRECATED -#endif - -/* check condition */ -#define TDM_RETURN_IF_FAIL(cond) { \ - if (!(cond)) { \ - TDM_ERR("'%s' failed", #cond); \ - return; \ - } \ -} -#define TDM_RETURN_VAL_IF_FAIL(cond, val) { \ - if (!(cond)) { \ - TDM_ERR("'%s' failed", #cond); \ - return val; \ - } \ -} -#define TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(cond, error_v, val) { \ - if (!(cond)) { \ - TDM_ERR("'%s' failed", #cond); \ - ret = error_v; \ - if (error) *error = ret; \ - return val; \ - } \ -} - -#define TDM_WARNING_IF_FAIL(cond) { \ - if (!(cond)) \ - TDM_WRN("'%s' failed", #cond); \ -} -#define TDM_GOTO_IF_FAIL(cond, dst) { \ - if (!(cond)) { \ - TDM_ERR("'%s' failed", #cond); \ - goto dst; \ - } \ -} -#define TDM_EXIT_IF_FAIL(cond) { \ - if (!(cond)) { \ - TDM_ERR("'%s' failed", #cond); \ - exit(0); \ - } \ -} - -#define TDM_NEVER_GET_HERE() TDM_WRN("** NEVER GET HERE **") - -#define TDM_SNPRINTF(p, len, fmt, ARG...) \ - do { \ - if (p && len && *len > 0) { \ - int s = snprintf(p, *len, fmt, ##ARG); \ - p += s; \ - *len -= s; \ - } \ - } while (0) - -#define TDM_DBG_RETURN_IF_FAIL(cond) { \ - if (!(cond)) { \ - TDM_SNPRINTF(reply, len, "[%s %d] '%s' failed\n", __func__, __LINE__, #cond); \ - return; \ - } \ -} -#define TDM_DBG_GOTO_IF_FAIL(cond, dst) { \ - if (!(cond)) { \ - TDM_SNPRINTF(reply, len, "[%s %d] '%s' failed\n", __func__, __LINE__, #cond); \ - goto dst; \ - } \ -} - +/* not-categorized **********************************************************/ #define TDM_NOT_DEFINED_VALUE (-1) #define TDM_FRONT_VALUE(n) (((n) > 0) ? (n) : TDM_NOT_DEFINED_VALUE) @@ -163,6 +74,25 @@ extern "C" { #define TDM_SWAP(a, b) ({ int t; t = a; a = b; b = t; }) #define TDM_ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +#define TDM_NEVER_GET_HERE() TDM_WRN("** NEVER GET HERE **") + +#define TDM_SNPRINTF(p, len, fmt, ARG...) \ + do { \ + if (p && len && *len > 0) { \ + int s = snprintf(p, *len, fmt, ##ARG); \ + p += s; \ + *len -= s; \ + } \ + } while (0) + +/* dump directory ***********************************************************/ +#define TDM_DUMP_DIR "/tmp" + +/* message length ***********************************************************/ +#define TDM_SERVER_REPLY_MSG_LEN 8192 +#define TDM_DEBUG_REPLY_MSG_LEN 2048 + +/* DPMS *********************************************************************/ /* can't export VSYNC macro because we can't define the exact meaning of vsync off * at this time. Does committing in standy mode work? Doesn't committing in suspend mode work? */ @@ -170,6 +100,46 @@ extern "C" { #define TDM_OUTPUT_DPMS_VSYNC_OFF_MASK 0x2 #define TDM_OUTPUT_DPMS_VSYNC_IS_OFF(dpms) ((dpms) & TDM_OUTPUT_DPMS_VSYNC_OFF_MASK) +/* strtostr *****************************************************************/ +static inline char* +strtostr(char *buf, int len, char *str, char *delim) +{ + char *end; + end = strpbrk(str, delim); + if (end) + len = ((end - str + 1) < len) ? (end - str + 1) : len; + else { + int l = strlen(str); + len = ((l + 1) < len) ? (l + 1) : len; + } + snprintf(buf, len, "%s", str); + return str + len - 1; +} + +/* EXTERN, INTERN, DEPRECATED ***********************************************/ +#undef EXTERN +#undef DEPRECATED +#undef INTERN + +#if defined(__GNUC__) && __GNUC__ >= 4 +#define EXTERN __attribute__ ((visibility("default"))) +#else +#define EXTERN +#endif + +#if defined(__GNUC__) && __GNUC__ >= 4 +#define INTERN __attribute__ ((visibility("hidden"))) +#else +#define INTERN +#endif + +#if defined(__GNUC__) && __GNUC__ >= 4 +#define DEPRECATED __attribute__ ((deprecated)) +#else +#define DEPRECATED +#endif + +/* type to string ***********************************************************/ struct tdm_type_name { int type; const char *name; @@ -325,21 +295,57 @@ static const char *tdm_capture_caps_names[] = { }; TDM_BIT_NAME_FB(capture_caps) -static inline char* -strtostr(char *buf, int len, char *str, char *delim) -{ - char *end; - end = strpbrk(str, delim); - if (end) - len = ((end - str + 1) < len) ? (end - str + 1) : len; - else { - int l = strlen(str); - len = ((l + 1) < len) ? (l + 1) : len; - } - snprintf(buf, len, "%s", str); - return str + len - 1; +/* check condition **********************************************************/ +#define TDM_RETURN_IF_FAIL(cond) { \ + if (!(cond)) { \ + TDM_ERR("'%s' failed", #cond); \ + return; \ + } \ +} +#define TDM_RETURN_VAL_IF_FAIL(cond, val) { \ + if (!(cond)) { \ + TDM_ERR("'%s' failed", #cond); \ + return val; \ + } \ +} +#define TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(cond, error_v, val) { \ + if (!(cond)) { \ + TDM_ERR("'%s' failed", #cond); \ + ret = error_v; \ + if (error) *error = ret; \ + return val; \ + } \ +} +#define TDM_WARNING_IF_FAIL(cond) { \ + if (!(cond)) \ + TDM_WRN("'%s' failed", #cond); \ +} +#define TDM_GOTO_IF_FAIL(cond, dst) { \ + if (!(cond)) { \ + TDM_ERR("'%s' failed", #cond); \ + goto dst; \ + } \ +} +#define TDM_EXIT_IF_FAIL(cond) { \ + if (!(cond)) { \ + TDM_ERR("'%s' failed", #cond); \ + exit(0); \ + } \ +} +#define TDM_DBG_RETURN_IF_FAIL(cond) { \ + if (!(cond)) { \ + TDM_SNPRINTF(reply, len, "[%s %d] '%s' failed\n", __func__, __LINE__, #cond); \ + return; \ + } \ +} +#define TDM_DBG_GOTO_IF_FAIL(cond, dst) { \ + if (!(cond)) { \ + TDM_SNPRINTF(reply, len, "[%s %d] '%s' failed\n", __func__, __LINE__, #cond); \ + goto dst; \ + } \ } +/* trace ********************************************************************/ #ifdef HAVE_TTRACE #include #define TDM_TRACE_BEGIN(fmt, ...) traceBegin(TTRACE_TAG_GRAPHICS, fmt, ##__VA_ARGS__) @@ -357,7 +363,7 @@ strtostr(char *buf, int len, char *str, char *delim) #define TDM_TRACE_MARK(fmt, ...) #endif - +/* display mutex ************************************************************/ extern pthread_mutex_t tdm_mutex_check_lock; extern int tdm_mutex_locked; extern const char *tdm_mutex_lock_func; @@ -408,6 +414,7 @@ static inline int TDM_MUTEX_IS_LOCKED(void) #define tdm_display_lock(dpy) _pthread_mutex_lock(&((tdm_private_display *)dpy)->lock) #define tdm_display_unlock(dpy) _pthread_mutex_unlock(&((tdm_private_display *)dpy)->lock) + #ifdef __cplusplus } #endif -- 2.7.4 From 15c12bf72c24f1ad4a1b98c29d36b1e2beecd465 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Thu, 18 Jan 2018 08:38:17 +0900 Subject: [PATCH 04/16] macro: add error string to make debugging easier Change-Id: I08b618f77afb06e4986f71a22b75af23dd87c54a --- src/tdm_macro.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/tdm_macro.h b/src/tdm_macro.h index 428b38f..4ac6a4f 100644 --- a/src/tdm_macro.h +++ b/src/tdm_macro.h @@ -156,6 +156,22 @@ static inline const char * tdm_##res##_str(int type) \ return "(invalid)"; \ } +static struct tdm_type_name tdm_error_names[] = { + { TDM_ERROR_NONE, "Success" }, + { TDM_ERROR_BAD_REQUEST, "bad request" }, + { TDM_ERROR_OPERATION_FAILED, "operaion failed" }, + { TDM_ERROR_INVALID_PARAMETER, "wrong input parameter" }, + { TDM_ERROR_PERMISSION_DENIED, "access denied" }, + { TDM_ERROR_BUSY, "hardware resource busy" }, + { TDM_ERROR_OUT_OF_MEMORY, "no free memory" }, + { TDM_ERROR_BAD_MODULE, "bad backend module" }, + { TDM_ERROR_NOT_IMPLEMENTED, "not implemented" }, + { TDM_ERROR_NO_CAPABILITY, "no capability" }, + { TDM_ERROR_DPMS_OFF, "dpms off" }, + { TDM_ERROR_OUTPUT_DISCONNECTED, "output disconnected" }, +}; +TDM_TYPE_NAME_FN(error) + static struct tdm_type_name tdm_dpms_names[] = { { TDM_OUTPUT_DPMS_ON, "on" }, { TDM_OUTPUT_DPMS_STANDBY, "standby" }, -- 2.7.4 From ae652c71b3b123682832bd4d5b60b24de8628cb9 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Fri, 19 Jan 2018 10:47:54 +0900 Subject: [PATCH 05/16] vblank: add server ttrace information Change-Id: I4ab060b514b04be0bd48606b8c56a5308b6bbe20 --- client/tdm_client.c | 21 +++++++++++++++++++++ src/tdm.c | 12 ++++++++---- src/tdm_monitor_server.c | 2 +- src/tdm_private_types.h | 12 +++++++----- src/tdm_server.c | 12 +++++++++++- src/tdm_vblank.c | 6 ++++++ 6 files changed, 54 insertions(+), 11 deletions(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index 349c454..f126490 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -60,6 +60,9 @@ typedef struct _tdm_private_client { struct wl_tdm *tdm; struct list_head output_list; + unsigned int enable_ttrace; + unsigned int stamp; + tdm_private_client_vblank *temp_vblank; } tdm_private_client; @@ -130,10 +133,16 @@ static void _tdm_client_vblank_cb_stamp(void *data, struct wl_tdm_vblank *wl_tdm_vblank, uint32_t stamp) { tdm_private_client_vblank *private_vblank = data; + tdm_private_client *private_client; TDM_RETURN_IF_FAIL(private_vblank != NULL); private_vblank->stamp = stamp; + + TDM_RETURN_IF_FAIL(private_vblank->private_output != NULL); + private_client = private_vblank->private_output->private_client; + + private_client->stamp = stamp; } /* LCOV_EXCL_START */ @@ -180,10 +189,16 @@ static void _tdm_client_vblank_cb_ttrace(void *data, struct wl_tdm_vblank *wl_tdm_vblank, uint32_t enable) { tdm_private_client_vblank *private_vblank = data; + tdm_private_client *private_client; TDM_RETURN_IF_FAIL(private_vblank != NULL); private_vblank->enable_ttrace = enable; + + TDM_RETURN_IF_FAIL(private_vblank->private_output != NULL); + private_client = private_vblank->private_output->private_client; + + private_client->enable_ttrace = enable; } /* LCOV_EXCL_STOP */ @@ -432,8 +447,14 @@ tdm_client_handle_events(tdm_client *client) /* LCOV_EXCL_START */ private_client = (tdm_private_client*)client; + if (private_client->enable_ttrace) + TDM_TRACE_ASYNC_BEGIN((int)private_client->stamp, "TDM_Client_Events:%u", (unsigned int)private_client->stamp); + wl_display_dispatch(private_client->display); + if (private_client->enable_ttrace) + TDM_TRACE_ASYNC_END((int)private_client->stamp, "TDM_Client_Events:%u", (unsigned int)private_client->stamp); + return TDM_ERROR_NONE; /* LCOV_EXCL_STOP */ } diff --git a/src/tdm.c b/src/tdm.c index 30b4a91..e20e7dd 100644 --- a/src/tdm.c +++ b/src/tdm.c @@ -1425,10 +1425,14 @@ tdm_display_enable_ttrace(tdm_private_display *private_display, const char *ttra tdm_ttrace_module = 0; else if (!strncmp(arg, "all", 3)) tdm_ttrace_module = 0xFFFFFFFF; + else if (!strncmp(arg, "vsync", 5)) + tdm_ttrace_module |= TDM_TTRACE_VSYNC; + else if (!strncmp(arg, "client_vblank", 13)) + tdm_ttrace_module |= TDM_TTRACE_CLIENT_VBLANK; + else if (!strncmp(arg, "server_vblank", 13)) + tdm_ttrace_module |= TDM_TTRACE_SERVER_VBLANK; else if (!strncmp(arg, "vblank", 6)) tdm_ttrace_module |= TDM_TTRACE_VBLANK; - else if (!strncmp(arg, "client", 6)) - tdm_ttrace_module |= TDM_TTRACE_CLIENT; else if (!strncmp(arg, "layer", 5)) tdm_ttrace_module |= TDM_TTRACE_LAYER; else if (!strncmp(arg, "pp", 2)) @@ -1448,12 +1452,12 @@ tdm_display_enable_ttrace(tdm_private_display *private_display, const char *ttra TDM_SNPRINTF(reply, len, "ttrace debugging... '%s' %x\n", ttrace, tdm_ttrace_module); - if (tdm_ttrace_module & TDM_TTRACE_VBLANK) + if (tdm_ttrace_module & TDM_TTRACE_VSYNC) tdm_display_enable_ttrace_vblank(private_display, output, 1); else tdm_display_enable_ttrace_vblank(private_display, NULL, 0); - if (tdm_ttrace_module & TDM_TTRACE_CLIENT) + if (tdm_ttrace_module & TDM_TTRACE_CLIENT_VBLANK) tdm_server_enable_ttrace_client_vblank(private_display, output, 1); else tdm_server_enable_ttrace_client_vblank(private_display, NULL, 0); diff --git a/src/tdm_monitor_server.c b/src/tdm_monitor_server.c index 8b28fa8..6fdb190 100644 --- a/src/tdm_monitor_server.c +++ b/src/tdm_monitor_server.c @@ -505,7 +505,7 @@ static struct { }, { "ttrace", _tdm_monitor_server_ttrace, - "enable/disable ttrace (module: none, vblank, client, layer, pp, capture, all", + "enable/disable ttrace (module: none,vsync,client_vblank,server_vblank,vblank,layer,pp,capture,all", "[@]", NULL }, diff --git a/src/tdm_private_types.h b/src/tdm_private_types.h index fd641c1..a406ecd 100644 --- a/src/tdm_private_types.h +++ b/src/tdm_private_types.h @@ -68,11 +68,13 @@ enum { enum { TDM_TTRACE_NONE, - TDM_TTRACE_VBLANK = (1 << 0), - TDM_TTRACE_CLIENT = (1 << 1), - TDM_TTRACE_LAYER = (1 << 2), - TDM_TTRACE_PP = (1 << 3), - TDM_TTRACE_CAPTURE = (1 << 4), + TDM_TTRACE_VSYNC = (1 << 0), + TDM_TTRACE_CLIENT_VBLANK = (1 << 1), + TDM_TTRACE_SERVER_VBLANK = (1 << 2), + TDM_TTRACE_VBLANK = (1 << 3), + TDM_TTRACE_LAYER = (1 << 4), + TDM_TTRACE_PP = (1 << 5), + TDM_TTRACE_CAPTURE = (1 << 6), }; typedef enum { diff --git a/src/tdm_server.c b/src/tdm_server.c index 0a359f4..c1b1359 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -182,6 +182,10 @@ _tdm_server_send_done(tdm_server_wait_info *wait_info, tdm_error error, TDM_DBG("req_id(%d) done", wait_info->req_id); vblank_info = wait_info->vblank_info; + + if (tdm_ttrace_module & TDM_TTRACE_SERVER_VBLANK) + TDM_TRACE_ASYNC_END((int)wait_info->req_time, "TDM_Server_Vblank:%u", vblank_info->stamp); + wl_tdm_vblank_send_done(vblank_info->resource, wait_info->req_id, sequence, tv_sec, tv_usec, error); @@ -338,6 +342,9 @@ _tdm_server_vblank_cb_wait_vblank(struct wl_client *client, struct wl_resource * if (tdm_debug_module & TDM_DEBUG_VBLANK) TDM_DBG("req_id(%d) wait", req_id); + if (tdm_ttrace_module & TDM_TTRACE_SERVER_VBLANK) + TDM_TRACE_ASYNC_BEGIN((int)wait_info->req_time, "TDM_Server_Vblank:%u", vblank_info->stamp); + ret = tdm_vblank_wait(vblank_info->vblank, req_sec, req_usec, interval, _tdm_server_cb_vblank, wait_info); tdm_vblank_get_enable_fake(vblank_info->vblank, &enable_fake); @@ -387,6 +394,9 @@ _tdm_server_vblank_cb_wait_vblank_seq(struct wl_client *client, struct wl_resour if (tdm_debug_module & TDM_DEBUG_VBLANK) TDM_DBG("req_id(%d) wait", req_id); + if (tdm_ttrace_module & TDM_TTRACE_SERVER_VBLANK) + TDM_TRACE_ASYNC_BEGIN((int)wait_info->req_time, "TDM_Server_Vblank:%u", vblank_info->stamp); + ret = tdm_vblank_wait_seq(vblank_info->vblank, req_sec, req_usec, sequence, _tdm_server_cb_vblank, wait_info); tdm_vblank_get_enable_fake(vblank_info->vblank, &enable_fake); @@ -485,7 +495,7 @@ _tdm_server_output_cb_create_vblank(struct wl_client *client, struct wl_resource wl_tdm_vblank_send_stamp(vblank_info->resource, vblank_info->stamp); - if (tdm_ttrace_module & TDM_TTRACE_CLIENT) { + if (tdm_ttrace_module & TDM_TTRACE_CLIENT_VBLANK) { tdm_output *output = tdm_display_get_output(private_loop->dpy, tdm_ttrace_output, NULL); if (output == output_info->output) wl_tdm_vblank_send_ttrace(vblank_info->resource, 1); diff --git a/src/tdm_vblank.c b/src/tdm_vblank.c index 4a0d03f..16c1838 100644 --- a/src/tdm_vblank.c +++ b/src/tdm_vblank.c @@ -1040,6 +1040,9 @@ _tdm_vblank_cb_vblank_HW(tdm_output *output, unsigned int sequence, VDB("wait(%p) last(%.6f) sequence(%u) done", wait_info, private_vblank->last_time, wait_info->target_seq); + if (tdm_ttrace_module & TDM_TTRACE_VBLANK) + TDM_TRACE_ASYNC_END((int)wait_info->req_time, "TDM_Vblank:%u", (unsigned int)private_vblank->stamp); + if (wait_info->func) wait_info->func(private_vblank, TDM_ERROR_NONE, wait_info->target_seq, tv_sec, tv_usec, wait_info->user_data); @@ -1109,6 +1112,9 @@ _tdm_vblank_wait_HW(tdm_vblank_wait_info *wait_info) private_vblank->last_interval = hw_interval; + if (tdm_ttrace_module & TDM_TTRACE_VBLANK) + TDM_TRACE_ASYNC_BEGIN((int)wait_info->req_time, "TDM_Vblank:%u", (unsigned int)private_vblank->stamp); + if (private_vblank->add_front) ret = tdm_output_wait_vblank_add_front(private_vblank->output, hw_interval, 0, _tdm_vblank_cb_vblank_HW, wait_info); -- 2.7.4 From 306c587fec093501cd537c72eb22096aa5ea37a5 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 22 Jan 2018 20:29:43 +0900 Subject: [PATCH 06/16] log: add monotonic time logs Change-Id: If220dfb11bf82ead8a2aa89ed307543231004165 --- include/tdm_log.h | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/include/tdm_log.h b/include/tdm_log.h index e43a4af..d402a99 100644 --- a/include/tdm_log.h +++ b/include/tdm_log.h @@ -38,6 +38,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -70,17 +71,37 @@ void tdm_log_set_debug_level(int level); void tdm_log_print(int level, const char *fmt, ...); #define TDM_DBG(fmt, args...) \ - tdm_log_print(TDM_LOG_LEVEL_DBG, "[%d][%s %d]"fmt"\n", \ - (int)syscall(SYS_gettid), __FUNCTION__, __LINE__, ##args) + do { \ + struct timespec ts; \ + clock_gettime(CLOCK_MONOTONIC, &ts); \ + tdm_log_print(TDM_LOG_LEVEL_DBG, "[%5d.%06d][%d][%s %d]"fmt"\n", \ + (int)ts.tv_sec, (int)ts.tv_nsec / 1000, \ + (int)syscall(SYS_gettid), __FUNCTION__, __LINE__, ##args); \ + } while (0) #define TDM_INFO(fmt, args...) \ - tdm_log_print(TDM_LOG_LEVEL_INFO, "[%d][%s %d]"fmt"\n", \ - (int)syscall(SYS_gettid), __FUNCTION__, __LINE__, ##args) + do { \ + struct timespec ts; \ + clock_gettime(CLOCK_MONOTONIC, &ts); \ + tdm_log_print(TDM_LOG_LEVEL_INFO, "[%5d.%06d][%d][%s %d]"fmt"\n", \ + (int)ts.tv_sec, (int)ts.tv_nsec / 1000, \ + (int)syscall(SYS_gettid), __FUNCTION__, __LINE__, ##args); \ + } while (0) #define TDM_WRN(fmt, args...) \ - tdm_log_print(TDM_LOG_LEVEL_WRN, "[%d][%s %d]"fmt"\n", \ - (int)syscall(SYS_gettid), __FUNCTION__, __LINE__, ##args) + do { \ + struct timespec ts; \ + clock_gettime(CLOCK_MONOTONIC, &ts); \ + tdm_log_print(TDM_LOG_LEVEL_WRN, "[%5d.%06d][%d][%s %d]"fmt"\n", \ + (int)ts.tv_sec, (int)ts.tv_nsec / 1000, \ + (int)syscall(SYS_gettid), __FUNCTION__, __LINE__, ##args); \ + } while (0) #define TDM_ERR(fmt, args...) \ - tdm_log_print(TDM_LOG_LEVEL_ERR, "[%d][%s %d]"fmt"\n", \ - (int)syscall(SYS_gettid), __FUNCTION__, __LINE__, ##args) + do { \ + struct timespec ts; \ + clock_gettime(CLOCK_MONOTONIC, &ts); \ + tdm_log_print(TDM_LOG_LEVEL_ERR, "[%5d.%06d][%d][%s %d]"fmt"\n", \ + (int)ts.tv_sec, (int)ts.tv_nsec / 1000, \ + (int)syscall(SYS_gettid), __FUNCTION__, __LINE__, ##args); \ + } while (0) #ifdef __cplusplus } -- 2.7.4 From 9ac5dd067409e9f713508916b15225f04da2a4e8 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Fri, 26 Jan 2018 20:31:38 +0900 Subject: [PATCH 07/16] client: use queue to handle internal events Change-Id: Id5fe565fcc177325661830ea5229515bab24c70e --- client/tdm_client.c | 57 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index f126490..81806d4 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -56,6 +56,7 @@ typedef struct _tdm_private_client_vblank tdm_private_client_vblank; typedef struct _tdm_private_client { struct wl_display *display; + struct wl_event_queue *queue; struct wl_registry *registry; struct wl_tdm *tdm; struct list_head output_list; @@ -373,6 +374,9 @@ tdm_client_create(tdm_error *error) private_client->display = wl_display_connect("tdm-socket"); TDM_GOTO_IF_FAIL(private_client->display != NULL, create_failed); + private_client->queue = wl_display_create_queue(private_client->display); + TDM_GOTO_IF_FAIL(private_client->queue != NULL, create_failed); + private_client->registry = wl_display_get_registry(private_client->display); TDM_GOTO_IF_FAIL(private_client->registry != NULL, create_failed); @@ -414,6 +418,8 @@ tdm_client_destroy(tdm_client *client) wl_tdm_destroy(private_client->tdm); if (private_client->registry) wl_registry_destroy(private_client->registry); + if (private_client->queue) + wl_event_queue_destroy(private_client->queue); if (private_client->display) wl_display_disconnect(private_client->display); @@ -521,6 +527,7 @@ tdm_client_get_output(tdm_client *client, char *name, tdm_error *error) { tdm_private_client *private_client; tdm_private_client_output *private_output = NULL; + struct wl_proxy *wrapper; if (error) *error = TDM_ERROR_NONE; @@ -542,10 +549,20 @@ tdm_client_get_output(tdm_client *client, char *name, tdm_error *error) return (tdm_client_output*)private_output; } + wrapper = wl_proxy_create_wrapper(private_client->tdm); + if (!wrapper) { + TDM_ERR("create output_wrapper failed"); + if (error) + *error = TDM_ERROR_OUT_OF_MEMORY; + return NULL; + } + + wl_proxy_set_queue(wrapper, private_client->queue); + private_output = calloc(1, sizeof *private_output); if (!private_output) { /* LCOV_EXCL_START */ - + wl_proxy_wrapper_destroy(wrapper); TDM_ERR("alloc failed"); if (error) *error = TDM_ERROR_OUT_OF_MEMORY; @@ -557,7 +574,8 @@ tdm_client_get_output(tdm_client *client, char *name, tdm_error *error) private_output->private_client = private_client; snprintf(private_output->name, TDM_NAME_LEN, "%s", name); - private_output->output = wl_tdm_create_output(private_client->tdm, private_output->name); + private_output->output = wl_tdm_create_output((struct wl_tdm *)wrapper, private_output->name); + wl_proxy_wrapper_destroy(wrapper); if (!private_output->output) { /* LCOV_EXCL_START */ @@ -576,7 +594,9 @@ tdm_client_get_output(tdm_client *client, char *name, tdm_error *error) wl_tdm_output_add_listener(private_output->output, &tdm_client_output_listener, private_output); - wl_display_roundtrip(private_client->display); + wl_display_roundtrip_queue(private_client->display, private_client->queue); + + wl_proxy_set_queue((struct wl_proxy *)private_output->output, NULL); return (tdm_client_output*)private_output; } @@ -663,8 +683,10 @@ tdm_client_output_get_refresh_rate(tdm_client_output *output, unsigned int *refr private_client = private_output->private_client; TDM_RETURN_VAL_IF_FAIL(private_client != NULL, TDM_ERROR_INVALID_PARAMETER); + wl_proxy_set_queue((struct wl_proxy *)private_output->output, private_client->queue); wl_tdm_output_get_mode(private_output->output); - wl_display_roundtrip(private_client->display); + wl_display_roundtrip_queue(private_client->display, private_client->queue); + wl_proxy_set_queue((struct wl_proxy *)private_output->output, NULL); *refresh = private_output->refresh; @@ -690,8 +712,10 @@ tdm_client_output_get_conn_status(tdm_client_output *output, tdm_output_conn_sta private_client = private_output->private_client; TDM_RETURN_VAL_IF_FAIL(private_client != NULL, TDM_ERROR_INVALID_PARAMETER); + wl_proxy_set_queue((struct wl_proxy *)private_output->output, private_client->queue); wl_tdm_output_get_connection(private_output->output); - wl_display_roundtrip(private_client->display); + wl_display_roundtrip_queue(private_client->display, private_client->queue); + wl_proxy_set_queue((struct wl_proxy *)private_output->output, NULL); *status = private_output->connection; @@ -717,8 +741,10 @@ tdm_client_output_get_dpms(tdm_client_output *output, tdm_output_dpms *dpms) private_client = private_output->private_client; TDM_RETURN_VAL_IF_FAIL(private_client != NULL, TDM_ERROR_INVALID_PARAMETER); + wl_proxy_set_queue((struct wl_proxy *)private_output->output, private_client->queue); wl_tdm_output_get_dpms(private_output->output); - wl_display_roundtrip(private_client->display); + wl_display_roundtrip_queue(private_client->display, private_client->queue); + wl_proxy_set_queue((struct wl_proxy *)private_output->output, NULL); *dpms = private_output->dpms; @@ -731,6 +757,7 @@ tdm_client_output_create_vblank(tdm_client_output *output, tdm_error *error) tdm_private_client *private_client; tdm_private_client_output *private_output; tdm_private_client_vblank *private_vblank; + struct wl_proxy *wrapper; if (error) *error = TDM_ERROR_NONE; @@ -752,11 +779,22 @@ tdm_client_output_create_vblank(tdm_client_output *output, tdm_error *error) return NULL; } + wrapper = wl_proxy_create_wrapper(private_output->output); + if (!wrapper) { + TDM_ERR("create output_wrapper failed"); + if (error) + *error = TDM_ERROR_OUT_OF_MEMORY; + return NULL; + } + + wl_proxy_set_queue(wrapper, private_client->queue); + private_vblank = calloc(1, sizeof *private_vblank); if (!private_vblank) { /* LCOV_EXCL_START */ TDM_ERR("alloc failed"); + wl_proxy_wrapper_destroy(wrapper); if (error) *error = TDM_ERROR_OUT_OF_MEMORY; return NULL; @@ -766,7 +804,8 @@ tdm_client_output_create_vblank(tdm_client_output *output, tdm_error *error) private_vblank->private_output = private_output; - private_vblank->vblank = wl_tdm_output_create_vblank(private_output->output); + private_vblank->vblank = wl_tdm_output_create_vblank((struct wl_tdm_output*)wrapper); + wl_proxy_wrapper_destroy(wrapper); if (!private_vblank->vblank) { /* LCOV_EXCL_START */ @@ -789,7 +828,9 @@ tdm_client_output_create_vblank(tdm_client_output *output, tdm_error *error) wl_tdm_vblank_add_listener(private_vblank->vblank, &tdm_client_vblank_listener, private_vblank); - wl_display_roundtrip(private_client->display); + wl_display_roundtrip_queue(private_client->display, private_client->queue); + + wl_proxy_set_queue((struct wl_proxy *)private_vblank->vblank, NULL); return (tdm_client_vblank*)private_vblank; } -- 2.7.4 From 10de61c4b401e727f63bc3fbc965ccd0bc0304ae Mon Sep 17 00:00:00 2001 From: Boram Park Date: Tue, 30 Jan 2018 10:35:36 +0900 Subject: [PATCH 08/16] client: add mutex lock Change-Id: I2c2cb6f7a06b67dcacfd6e1bcf502877ead20dc5 --- client/tdm_client.c | 246 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 208 insertions(+), 38 deletions(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index 81806d4..51e5c5e 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -55,6 +55,8 @@ typedef struct _tdm_private_client_vblank tdm_private_client_vblank; typedef struct _tdm_private_client { + pthread_mutex_t lock; + struct wl_display *display; struct wl_event_queue *queue; struct wl_registry *registry; @@ -115,6 +117,7 @@ typedef struct _tdm_client_output_handler_info { void *user_data; struct list_head link; + struct list_head call_link; } tdm_client_output_handler_info; typedef struct _tdm_client_wait_info { @@ -128,6 +131,7 @@ typedef struct _tdm_client_wait_info { int need_free; struct list_head link; + struct list_head call_link; } tdm_client_wait_info; static void @@ -153,35 +157,50 @@ _tdm_client_vblank_cb_done(void *data, struct wl_tdm_vblank *wl_tdm_vblank, uint32_t tv_usec, uint32_t error) { tdm_private_client_vblank *private_vblank = data; - tdm_client_wait_info *w = NULL, *ww = NULL; + tdm_private_client *private_client; + tdm_client_wait_info *w = NULL, *wait_info = NULL; TDM_RETURN_IF_FAIL(private_vblank != NULL); + private_client = private_vblank->private_output->private_client; + 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)); - LIST_FOR_EACH_ENTRY_SAFE(w, ww, &private_vblank->wait_list, link) { + LIST_FOR_EACH_ENTRY(w, &private_vblank->wait_list, link) { if (w->req_id != req_id) continue; - if (private_vblank->enable_ttrace) - TDM_TRACE_ASYNC_END((int)w->req_time, "TDM_Client_Vblank:%u", private_vblank->stamp); + wait_info = w; + break; + } + + if (!wait_info) { + TDM_ERR("no wait infomation for req_id(%d)", req_id); + return; + } - if (w->req_time >= private_vblank->last_time) - TDM_WRN("'req(%.6f) < last(%.6f)' failed", w->req_time, private_vblank->last_time); + if (private_vblank->enable_ttrace) + TDM_TRACE_ASYNC_END((int)wait_info->req_time, "TDM_Client_Vblank:%u", private_vblank->stamp); - if (w->func) - w->func(private_vblank, error, sequence, tv_sec, tv_usec, w->user_data); + if (wait_info->req_time >= private_vblank->last_time) + TDM_WRN("'req(%.6f) < last(%.6f)' failed. error(%d)", wait_info->req_time, private_vblank->last_time, error); - if (w->need_free) { - LIST_DEL(&w->link); - free(w); - } else - w->need_free = 1; - return; + if (wait_info->need_free) + LIST_DEL(&wait_info->link); + + if (wait_info->func) { + pthread_mutex_unlock(&private_client->lock); + wait_info->func(private_vblank, error, sequence, tv_sec, tv_usec, wait_info->user_data); + pthread_mutex_lock(&private_client->lock); } + + if (wait_info->need_free) + free(w); + else + wait_info->need_free = 1; } /* LCOV_EXCL_STOP */ @@ -257,11 +276,15 @@ static void _tdm_client_output_cb_connection(void *data, struct wl_tdm_output *wl_tdm_output, uint32_t value, uint32_t error) { tdm_private_client_output *private_output = (tdm_private_client_output*)data; - tdm_client_output_handler_info *h = NULL; + tdm_private_client *private_client; + tdm_client_output_handler_info *h = NULL, *hh = NULL; tdm_value v; + struct list_head call_list; TDM_RETURN_IF_FAIL(private_output != NULL); + private_client = private_output->private_client; + if (private_output->connection == value) return; @@ -275,22 +298,34 @@ _tdm_client_output_cb_connection(void *data, struct wl_tdm_output *wl_tdm_output wl_proxy_get_id((struct wl_proxy*)private_output->output), value); - v.u32 = value; + LIST_INITHEAD(&call_list); + LIST_FOR_EACH_ENTRY(h, &private_output->change_handler_list, link) { + LIST_ADDTAIL(&h->call_link, &call_list); + } + + v.u32 = value; + pthread_mutex_unlock(&private_client->lock); + LIST_FOR_EACH_ENTRY_SAFE(h, hh, &call_list, call_link) { if (h->func) h->func(private_output, TDM_OUTPUT_CHANGE_CONNECTION, v, h->user_data); } + pthread_mutex_lock(&private_client->lock); } static void _tdm_client_output_cb_dpms(void *data, struct wl_tdm_output *wl_tdm_output, uint32_t value, uint32_t error) { tdm_private_client_output *private_output = (tdm_private_client_output*)data; - tdm_client_output_handler_info *h = NULL; + tdm_private_client *private_client; + tdm_client_output_handler_info *h = NULL, *hh = NULL; tdm_value v; + struct list_head call_list; TDM_RETURN_IF_FAIL(private_output != NULL); + private_client = private_output->private_client; + /* If value is extended value, we handle it as DPMS on in client side * The extended DPMS value is valid only in server side. * Or, need to export to client side also? @@ -311,11 +346,19 @@ _tdm_client_output_cb_dpms(void *data, struct wl_tdm_output *wl_tdm_output, uint wl_proxy_get_id((struct wl_proxy*)private_output->output), value); - v.u32 = value; + LIST_INITHEAD(&call_list); + LIST_FOR_EACH_ENTRY(h, &private_output->change_handler_list, link) { + LIST_ADDTAIL(&h->call_link, &call_list); + } + + v.u32 = value; + pthread_mutex_unlock(&private_client->lock); + LIST_FOR_EACH_ENTRY_SAFE(h, hh, &call_list, call_link) { if (h->func) h->func(private_output, TDM_OUTPUT_CHANGE_DPMS, v, h->user_data); } + pthread_mutex_lock(&private_client->lock); } static const struct wl_tdm_output_listener tdm_client_output_listener = { @@ -369,6 +412,14 @@ tdm_client_create(tdm_error *error) /* LCOV_EXCL_STOP */ } + if (pthread_mutex_init(&private_client->lock, NULL)) { + TDM_ERR("mutex init failed: %m"); + free(private_client); + if (error) + *error = TDM_ERROR_OUT_OF_MEMORY; + return NULL; + } + LIST_INITHEAD(&private_client->output_list); private_client->display = wl_display_connect("tdm-socket"); @@ -407,6 +458,8 @@ tdm_client_destroy(tdm_client *client) if (!private_client) return; + pthread_mutex_lock(&private_client->lock); + if (private_client->temp_vblank) tdm_client_vblank_destroy(private_client->temp_vblank); @@ -423,6 +476,9 @@ tdm_client_destroy(tdm_client *client) if (private_client->display) wl_display_disconnect(private_client->display); + pthread_mutex_unlock(&private_client->lock); + pthread_mutex_destroy(&private_client->lock); + free(private_client); } @@ -436,7 +492,12 @@ tdm_client_get_fd(tdm_client *client, int *fd) private_client = (tdm_private_client*)client; + pthread_mutex_lock(&private_client->lock); + *fd = wl_display_get_fd(private_client->display); + + pthread_mutex_unlock(&private_client->lock); + if (*fd < 0) return TDM_ERROR_OPERATION_FAILED; @@ -453,6 +514,8 @@ tdm_client_handle_events(tdm_client *client) /* LCOV_EXCL_START */ private_client = (tdm_private_client*)client; + pthread_mutex_lock(&private_client->lock); + if (private_client->enable_ttrace) TDM_TRACE_ASYNC_BEGIN((int)private_client->stamp, "TDM_Client_Events:%u", (unsigned int)private_client->stamp); @@ -461,6 +524,8 @@ tdm_client_handle_events(tdm_client *client) if (private_client->enable_ttrace) TDM_TRACE_ASYNC_END((int)private_client->stamp, "TDM_Client_Events:%u", (unsigned int)private_client->stamp); + pthread_mutex_unlock(&private_client->lock); + return TDM_ERROR_NONE; /* LCOV_EXCL_STOP */ } @@ -476,11 +541,20 @@ _tdm_client_vblank_handler_temp(tdm_client_vblank *vblank, tdm_error error, unsi unsigned int tv_sec, unsigned int tv_usec, void *user_data) { tdm_client_vblank_temp *vblank_temp = user_data; + tdm_private_client_vblank *private_vblank; + tdm_private_client *private_client; TDM_RETURN_IF_FAIL(vblank_temp != NULL); + TDM_RETURN_IF_FAIL(vblank != NULL); + + private_vblank = vblank; + private_client = private_vblank->private_output->private_client; - if (vblank_temp->func) + if (vblank_temp->func) { + pthread_mutex_unlock(&private_client->lock); vblank_temp->func(sequence, tv_sec, tv_usec, vblank_temp->user_data); + pthread_mutex_lock(&private_client->lock); + } free(vblank_temp); } @@ -541,12 +615,16 @@ tdm_client_get_output(tdm_client *client, char *name, tdm_error *error) private_client = (tdm_private_client*)client; + pthread_mutex_lock(&private_client->lock); + if (!name) name = "primary"; LIST_FOR_EACH_ENTRY(private_output, &private_client->output_list, link) { - if (!strncmp(private_output->name, name, TDM_NAME_LEN)) + if (!strncmp(private_output->name, name, TDM_NAME_LEN)) { + pthread_mutex_unlock(&private_client->lock); return (tdm_client_output*)private_output; + } } wrapper = wl_proxy_create_wrapper(private_client->tdm); @@ -554,6 +632,7 @@ tdm_client_get_output(tdm_client *client, char *name, tdm_error *error) TDM_ERR("create output_wrapper failed"); if (error) *error = TDM_ERROR_OUT_OF_MEMORY; + pthread_mutex_unlock(&private_client->lock); return NULL; } @@ -566,6 +645,7 @@ tdm_client_get_output(tdm_client *client, char *name, tdm_error *error) TDM_ERR("alloc failed"); if (error) *error = TDM_ERROR_OUT_OF_MEMORY; + pthread_mutex_unlock(&private_client->lock); return NULL; /* LCOV_EXCL_STOP */ @@ -583,6 +663,7 @@ tdm_client_get_output(tdm_client *client, char *name, tdm_error *error) free(private_output); if (error) *error = TDM_ERROR_OUT_OF_MEMORY; + pthread_mutex_unlock(&private_client->lock); return NULL; /* LCOV_EXCL_STOP */ @@ -598,6 +679,8 @@ tdm_client_get_output(tdm_client *client, char *name, tdm_error *error) wl_proxy_set_queue((struct wl_proxy *)private_output->output, NULL); + pthread_mutex_unlock(&private_client->lock); + return (tdm_client_output*)private_output; } @@ -607,16 +690,20 @@ tdm_client_output_add_change_handler(tdm_client_output *output, void *user_data) { tdm_private_client_output *private_output; + tdm_private_client *private_client; tdm_client_output_handler_info *h; TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER); private_output = (tdm_private_client_output*)output; + private_client = private_output->private_client; h = calloc(1, sizeof *h); TDM_RETURN_VAL_IF_FAIL(h != NULL, TDM_ERROR_OUT_OF_MEMORY); + pthread_mutex_lock(&private_client->lock); + if (LIST_IS_EMPTY(&private_output->change_handler_list)) { wl_tdm_output_watch_output_changes(private_output->output, 1); @@ -633,8 +720,11 @@ tdm_client_output_add_change_handler(tdm_client_output *output, h->func = func; h->user_data = user_data; LIST_ADDTAIL(&h->link, &private_output->change_handler_list); + LIST_INITHEAD(&h->call_link); + + pthread_mutex_unlock(&private_client->lock); - return TDM_ERROR_NOT_IMPLEMENTED; + return TDM_ERROR_NONE; } void @@ -643,12 +733,16 @@ tdm_client_output_remove_change_handler(tdm_client_output *output, void *user_data) { tdm_private_client_output *private_output; + tdm_private_client *private_client; tdm_client_output_handler_info *h = NULL; TDM_RETURN_IF_FAIL(output != NULL); TDM_RETURN_IF_FAIL(func != NULL); private_output = (tdm_private_client_output*)output; + private_client = private_output->private_client; + + pthread_mutex_lock(&private_client->lock); LIST_FOR_EACH_ENTRY(h, &private_output->change_handler_list, link) { if (h->func != func || h->user_data != user_data) @@ -660,8 +754,12 @@ tdm_client_output_remove_change_handler(tdm_client_output *output, if (LIST_IS_EMPTY(&private_output->change_handler_list)) wl_tdm_output_watch_output_changes(private_output->output, 0); + pthread_mutex_unlock(&private_client->lock); + return; } + + pthread_mutex_unlock(&private_client->lock); } tdm_error @@ -674,15 +772,16 @@ tdm_client_output_get_refresh_rate(tdm_client_output *output, unsigned int *refr TDM_RETURN_VAL_IF_FAIL(refresh != NULL, TDM_ERROR_INVALID_PARAMETER); private_output = (tdm_private_client_output*)output; + private_client = private_output->private_client; + + pthread_mutex_lock(&private_client->lock); if (private_output->watch_output_changes) { *refresh = private_output->refresh; + pthread_mutex_unlock(&private_client->lock); return TDM_ERROR_NONE; } - private_client = private_output->private_client; - TDM_RETURN_VAL_IF_FAIL(private_client != NULL, TDM_ERROR_INVALID_PARAMETER); - wl_proxy_set_queue((struct wl_proxy *)private_output->output, private_client->queue); wl_tdm_output_get_mode(private_output->output); wl_display_roundtrip_queue(private_client->display, private_client->queue); @@ -690,6 +789,8 @@ tdm_client_output_get_refresh_rate(tdm_client_output *output, unsigned int *refr *refresh = private_output->refresh; + pthread_mutex_unlock(&private_client->lock); + return TDM_ERROR_NONE; } @@ -703,15 +804,16 @@ tdm_client_output_get_conn_status(tdm_client_output *output, tdm_output_conn_sta TDM_RETURN_VAL_IF_FAIL(status != NULL, TDM_ERROR_INVALID_PARAMETER); private_output = (tdm_private_client_output*)output; + private_client = private_output->private_client; + + pthread_mutex_lock(&private_client->lock); if (private_output->watch_output_changes) { *status = private_output->connection; + pthread_mutex_unlock(&private_client->lock); return TDM_ERROR_NONE; } - private_client = private_output->private_client; - TDM_RETURN_VAL_IF_FAIL(private_client != NULL, TDM_ERROR_INVALID_PARAMETER); - wl_proxy_set_queue((struct wl_proxy *)private_output->output, private_client->queue); wl_tdm_output_get_connection(private_output->output); wl_display_roundtrip_queue(private_client->display, private_client->queue); @@ -719,6 +821,8 @@ tdm_client_output_get_conn_status(tdm_client_output *output, tdm_output_conn_sta *status = private_output->connection; + pthread_mutex_unlock(&private_client->lock); + return TDM_ERROR_NONE; } @@ -732,14 +836,14 @@ tdm_client_output_get_dpms(tdm_client_output *output, tdm_output_dpms *dpms) TDM_RETURN_VAL_IF_FAIL(dpms != NULL, TDM_ERROR_INVALID_PARAMETER); private_output = (tdm_private_client_output*)output; + private_client = private_output->private_client; 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); + pthread_mutex_lock(&private_client->lock); wl_proxy_set_queue((struct wl_proxy *)private_output->output, private_client->queue); wl_tdm_output_get_dpms(private_output->output); @@ -748,6 +852,8 @@ tdm_client_output_get_dpms(tdm_client_output *output, tdm_output_dpms *dpms) *dpms = private_output->dpms; + pthread_mutex_unlock(&private_client->lock); + return TDM_ERROR_NONE; } @@ -772,18 +878,14 @@ tdm_client_output_create_vblank(tdm_client_output *output, tdm_error *error) private_output = (tdm_private_client_output*)output; private_client = private_output->private_client; - if (!private_client) { - TDM_ERR("'!private_client' failed"); - if (error) - *error = TDM_ERROR_INVALID_PARAMETER; - return NULL; - } + pthread_mutex_lock(&private_client->lock); wrapper = wl_proxy_create_wrapper(private_output->output); if (!wrapper) { TDM_ERR("create output_wrapper failed"); if (error) *error = TDM_ERROR_OUT_OF_MEMORY; + pthread_mutex_unlock(&private_client->lock); return NULL; } @@ -797,6 +899,7 @@ tdm_client_output_create_vblank(tdm_client_output *output, tdm_error *error) wl_proxy_wrapper_destroy(wrapper); if (error) *error = TDM_ERROR_OUT_OF_MEMORY; + pthread_mutex_unlock(&private_client->lock); return NULL; /* LCOV_EXCL_STOP */ @@ -813,6 +916,7 @@ tdm_client_output_create_vblank(tdm_client_output *output, tdm_error *error) free(private_vblank); if (error) *error = TDM_ERROR_OUT_OF_MEMORY; + pthread_mutex_unlock(&private_client->lock); return NULL; /* LCOV_EXCL_STOP */ @@ -832,6 +936,8 @@ tdm_client_output_create_vblank(tdm_client_output *output, tdm_error *error) wl_proxy_set_queue((struct wl_proxy *)private_vblank->vblank, NULL); + pthread_mutex_unlock(&private_client->lock); + return (tdm_client_vblank*)private_vblank; } @@ -839,11 +945,16 @@ void tdm_client_vblank_destroy(tdm_client_vblank *vblank) { tdm_private_client_vblank *private_vblank; + tdm_private_client *private_client; tdm_client_wait_info *w = NULL, *ww = NULL; TDM_RETURN_IF_FAIL(vblank != NULL); private_vblank = vblank; + private_client = private_vblank->private_output->private_client; + + pthread_mutex_lock(&private_client->lock); + LIST_DEL(&private_vblank->link); LIST_FOR_EACH_ENTRY_SAFE(w, ww, &private_vblank->wait_list, link) { @@ -854,16 +965,22 @@ tdm_client_vblank_destroy(tdm_client_vblank *vblank) wl_tdm_vblank_destroy(private_vblank->vblank); free(private_vblank); + + pthread_mutex_unlock(&private_client->lock); } tdm_error tdm_client_vblank_set_name(tdm_client_vblank *vblank, const char *name) { tdm_private_client_vblank *private_vblank; + tdm_private_client *private_client; TDM_RETURN_VAL_IF_FAIL(vblank != NULL, TDM_ERROR_INVALID_PARAMETER); private_vblank = vblank; + private_client = private_vblank->private_output->private_client; + + pthread_mutex_lock(&private_client->lock); if (!name) name = TDM_VBLANK_DEFAULT_NAME; @@ -873,6 +990,8 @@ tdm_client_vblank_set_name(tdm_client_vblank *vblank, const char *name) wl_tdm_vblank_set_name(private_vblank->vblank, private_vblank->name); + pthread_mutex_unlock(&private_client->lock); + return TDM_ERROR_NONE; } @@ -880,11 +999,16 @@ tdm_error tdm_client_vblank_set_sync(tdm_client_vblank *vblank, unsigned int sync) { tdm_private_client_vblank *private_vblank; + tdm_private_client *private_client; TDM_RETURN_VAL_IF_FAIL(vblank != NULL, TDM_ERROR_INVALID_PARAMETER); private_vblank = vblank; + private_client = private_vblank->private_output->private_client; + + pthread_mutex_lock(&private_client->lock); private_vblank->sync = sync; + pthread_mutex_unlock(&private_client->lock); return TDM_ERROR_NONE; } @@ -893,18 +1017,27 @@ tdm_error tdm_client_vblank_set_fps(tdm_client_vblank *vblank, unsigned int fps) { tdm_private_client_vblank *private_vblank; + tdm_private_client *private_client; TDM_RETURN_VAL_IF_FAIL(vblank != NULL, TDM_ERROR_INVALID_PARAMETER); TDM_RETURN_VAL_IF_FAIL(fps > 0, TDM_ERROR_INVALID_PARAMETER); private_vblank = vblank; + private_client = private_vblank->private_output->private_client; - if (private_vblank->fps == fps) + pthread_mutex_lock(&private_client->lock); + + if (private_vblank->fps == fps) { + pthread_mutex_unlock(&private_client->lock); return TDM_ERROR_NONE; + } + private_vblank->fps = fps; wl_tdm_vblank_set_fps(private_vblank->vblank, fps); + pthread_mutex_unlock(&private_client->lock); + return TDM_ERROR_NONE; } @@ -912,18 +1045,28 @@ tdm_error tdm_client_vblank_set_offset(tdm_client_vblank *vblank, int offset_ms) { tdm_private_client_vblank *private_vblank; + tdm_private_client *private_client; TDM_RETURN_VAL_IF_FAIL(vblank != NULL, TDM_ERROR_INVALID_PARAMETER); private_vblank = vblank; TDM_RETURN_VAL_IF_FAIL(private_vblank->started == 0, TDM_ERROR_BAD_REQUEST); - if (private_vblank->offset == offset_ms) + private_client = private_vblank->private_output->private_client; + + pthread_mutex_lock(&private_client->lock); + + if (private_vblank->offset == offset_ms) { + pthread_mutex_unlock(&private_client->lock); return TDM_ERROR_NONE; + } + private_vblank->offset = offset_ms; wl_tdm_vblank_set_offset(private_vblank->vblank, offset_ms); + pthread_mutex_unlock(&private_client->lock); + return TDM_ERROR_NONE; } @@ -931,17 +1074,26 @@ tdm_error tdm_client_vblank_set_enable_fake(tdm_client_vblank *vblank, unsigned int enable_fake) { tdm_private_client_vblank *private_vblank; + tdm_private_client *private_client; TDM_RETURN_VAL_IF_FAIL(vblank != NULL, TDM_ERROR_INVALID_PARAMETER); private_vblank = vblank; + private_client = private_vblank->private_output->private_client; + + pthread_mutex_lock(&private_client->lock); - if (private_vblank->enable_fake == enable_fake) + if (private_vblank->enable_fake == enable_fake) { + pthread_mutex_unlock(&private_client->lock); return TDM_ERROR_NONE; + } + private_vblank->enable_fake = enable_fake; wl_tdm_vblank_set_enable_fake(private_vblank->vblank, enable_fake); + pthread_mutex_unlock(&private_client->lock); + return TDM_ERROR_NONE; } @@ -968,16 +1120,20 @@ tdm_client_vblank_wait(tdm_client_vblank *vblank, unsigned int interval, tdm_cli private_output = private_vblank->private_output; private_client = private_output->private_client; + pthread_mutex_lock(&private_client->lock); + if (!private_vblank->started) private_vblank->started = 1; if (private_output->watch_output_changes && !private_vblank->enable_fake) { if (private_output->connection == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) { TDM_ERR("output disconnected"); + pthread_mutex_unlock(&private_client->lock); return TDM_ERROR_OUTPUT_DISCONNECTED; } if (TDM_OUTPUT_DPMS_VSYNC_IS_OFF(private_output->dpms)) { TDM_ERR("dpms %s", tdm_dpms_str(private_output->dpms)); + pthread_mutex_unlock(&private_client->lock); return TDM_ERROR_DPMS_OFF; } } @@ -987,6 +1143,7 @@ tdm_client_vblank_wait(tdm_client_vblank *vblank, unsigned int interval, tdm_cli /* LCOV_EXCL_START */ TDM_ERR("alloc failed"); + pthread_mutex_unlock(&private_client->lock); return TDM_ERROR_OUT_OF_MEMORY; /* LCOV_EXCL_STOP */ @@ -997,6 +1154,7 @@ tdm_client_vblank_wait(tdm_client_vblank *vblank, unsigned int interval, tdm_cli w->user_data = user_data; LIST_ADDTAIL(&w->link, &private_vblank->wait_list); + LIST_INITHEAD(&w->call_link); clock_gettime(CLOCK_MONOTONIC, &tp); req_sec = (unsigned int)tp.tv_sec; @@ -1021,6 +1179,7 @@ tdm_client_vblank_wait(tdm_client_vblank *vblank, unsigned int interval, tdm_cli if (!private_vblank->sync) { wl_display_flush(private_client->display); + pthread_mutex_unlock(&private_client->lock); return TDM_ERROR_NONE; } @@ -1037,6 +1196,8 @@ tdm_client_vblank_wait(tdm_client_vblank *vblank, unsigned int interval, tdm_cli LIST_DEL(&w->link); free(w); + pthread_mutex_unlock(&private_client->lock); + return TDM_ERROR_NONE; /* LCOV_EXCL_STOP */ @@ -1061,16 +1222,20 @@ tdm_client_vblank_wait_seq(tdm_client_vblank *vblank, unsigned int sequence, private_output = private_vblank->private_output; private_client = private_output->private_client; + pthread_mutex_lock(&private_client->lock); + if (!private_vblank->started) private_vblank->started = 1; if (private_output->watch_output_changes && !private_vblank->enable_fake) { if (private_output->connection == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) { TDM_ERR("output disconnected"); + pthread_mutex_unlock(&private_client->lock); return TDM_ERROR_OUTPUT_DISCONNECTED; } if (TDM_OUTPUT_DPMS_VSYNC_IS_OFF(private_output->dpms)) { TDM_ERR("dpms %s", tdm_dpms_str(private_output->dpms)); + pthread_mutex_unlock(&private_client->lock); return TDM_ERROR_DPMS_OFF; } } @@ -1080,6 +1245,7 @@ tdm_client_vblank_wait_seq(tdm_client_vblank *vblank, unsigned int sequence, /* LCOV_EXCL_START */ TDM_ERR("alloc failed"); + pthread_mutex_unlock(&private_client->lock); return TDM_ERROR_OUT_OF_MEMORY; /* LCOV_EXCL_STOP */ @@ -1090,6 +1256,7 @@ tdm_client_vblank_wait_seq(tdm_client_vblank *vblank, unsigned int sequence, w->user_data = user_data; LIST_ADDTAIL(&w->link, &private_vblank->wait_list); + LIST_INITHEAD(&w->call_link); clock_gettime(CLOCK_MONOTONIC, &tp); req_sec = (unsigned int)tp.tv_sec; @@ -1114,6 +1281,7 @@ tdm_client_vblank_wait_seq(tdm_client_vblank *vblank, unsigned int sequence, if (!private_vblank->sync) { wl_display_flush(private_client->display); + pthread_mutex_unlock(&private_client->lock); return TDM_ERROR_NONE; } @@ -1130,6 +1298,8 @@ tdm_client_vblank_wait_seq(tdm_client_vblank *vblank, unsigned int sequence, LIST_DEL(&w->link); free(w); + pthread_mutex_unlock(&private_client->lock); + return TDM_ERROR_NONE; /* LCOV_EXCL_STOP */ -- 2.7.4 From 27fa81155e51aa9b80b89e51ed72630c03834ebd Mon Sep 17 00:00:00 2001 From: Boram Park Date: Fri, 26 Jan 2018 21:42:32 +0900 Subject: [PATCH 09/16] log: change dlog log_id Change-Id: I0d11c0b89da0b5a83fd4f02371b40a34d42e798a --- common/tdm_log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/tdm_log.c b/common/tdm_log.c index 593dc5e..7cce09c 100644 --- a/common/tdm_log.c +++ b/common/tdm_log.c @@ -154,7 +154,7 @@ tdm_log_print(int level, const char *fmt, ...) return; } va_start(arg, fmt); - dlog_vprint(dlog_prio, LOG_TAG, fmt, arg); + __dlog_vprint(LOG_ID_SYSTEM, dlog_prio, LOG_TAG, fmt, arg); va_end(arg); } else { struct timespec ts; -- 2.7.4 From 6c44c537242e006e8a10d4fe097b79ed0501e198 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 29 Jan 2018 08:17:49 +0900 Subject: [PATCH 10/16] add timeout logs (1000ms) Change-Id: Ie9bbcba3d1b109d5c80734a8c55cd8959b6cdef7 --- src/tdm.c | 3 + src/tdm_output.c | 71 +++++++++++++++++++++ src/tdm_private.h | 2 + src/tdm_private_types.h | 4 ++ src/tdm_server.c | 5 +- src/tdm_vblank.c | 165 ++++++++++++++++++++++++++++++++++++++++++------ 6 files changed, 228 insertions(+), 22 deletions(-) diff --git a/src/tdm.c b/src/tdm.c index e20e7dd..de6c179 100644 --- a/src/tdm.c +++ b/src/tdm.c @@ -161,6 +161,9 @@ _tdm_display_destroy_private_output(tdm_private_output *private_output) free(private_output->layers_ptr); + if (private_output->vblank_timeout_timer) + tdm_event_loop_source_remove(private_output->vblank_timeout_timer); + LIST_FOR_EACH_ENTRY_SAFE(v, vv, &private_output->vblank_handler_list, link) { LIST_DEL(&v->link); free(v); diff --git a/src/tdm_output.c b/src/tdm_output.c index c9fba68..4105ced 100644 --- a/src/tdm_output.c +++ b/src/tdm_output.c @@ -57,6 +57,69 @@ private_output = (tdm_private_output*)output; \ private_display = private_output->private_display +static void +_tdm_output_vblank_timeout_update(tdm_private_output *private_output, int ms_delay); + +static tdm_error +_tdm_output_vblank_timeout_cb(void *user_data) +{ + tdm_private_output *private_output = user_data; + tdm_private_vblank_handler *v = NULL; + + TDM_RETURN_VAL_IF_FAIL(private_output != NULL, TDM_ERROR_OPERATION_FAILED); + + TDM_ERR("TDM output(%d) vblank TIMEOUT!!", private_output->pipe); + + LIST_FOR_EACH_ENTRY(v, &private_output->vblank_handler_list, link) { + TDM_ERR("vblank_handler(%p) interval(%d) sync(%d) sent_to_frontend(%u) owner_tid(%d)", + v, v->interval, v->sync, v->sent_to_frontend, v->owner_tid); + } + + return TDM_ERROR_NONE; +} + +INTERN void +tdm_output_vblank_print_wait_information(tdm_private_output *private_output, void *user_data) +{ + tdm_private_vblank_handler *v = NULL; + + TDM_RETURN_IF_FAIL(private_output != NULL); + TDM_RETURN_IF_FAIL(user_data != NULL); + + TDM_ERR("TDM output(%d) vblank user_data(%p) info!!", private_output->pipe, user_data); + + LIST_FOR_EACH_ENTRY(v, &private_output->vblank_handler_list, link) { + if (v->user_data != user_data) + continue; + TDM_ERR("vblank_handler(%p) interval(%d) sync(%d) sent_to_frontend(%u) owner_tid(%d)", + v, v->interval, v->sync, v->sent_to_frontend, v->owner_tid); + } +} + +static void +_tdm_output_vblank_timeout_update(tdm_private_output *private_output, int ms_delay) +{ + tdm_error ret; + + if (!private_output->vblank_timeout_timer) { + private_output->vblank_timeout_timer = + tdm_event_loop_add_timer_handler(private_output->private_display, + _tdm_output_vblank_timeout_cb, + private_output, + &ret); + if (!private_output->vblank_timeout_timer) { + TDM_ERR("output(%d) couldn't add timer", private_output->pipe); + return; + } + TDM_INFO("output(%d) create vblank timeout timer", private_output->pipe); + } + + ret = tdm_event_loop_source_timer_update(private_output->vblank_timeout_timer, ms_delay); + if (ret != TDM_ERROR_NONE) { + TDM_ERR("output(%d) couldn't update timer", private_output->pipe); + return; + } +} static tdm_private_hwc_window * _tdm_output_find_private_hwc_window(tdm_private_output *private_output, @@ -602,6 +665,8 @@ tdm_output_cb_vblank(tdm_output *output_backend, unsigned int sequence, tdm_thread_cb_output_vblank output_vblank; tdm_error ret; + vblank_handler->sent_to_frontend = 1; + output_vblank.base.type = TDM_THREAD_CB_OUTPUT_VBLANK; output_vblank.base.length = sizeof output_vblank; output_vblank.output_stamp = vblank_handler->private_output->stamp; @@ -616,6 +681,10 @@ tdm_output_cb_vblank(tdm_output *output_backend, unsigned int sequence, return; } + vblank_handler->sent_to_frontend = 0; + + _tdm_output_vblank_timeout_update(private_output, 0); + if (vblank_handler->owner_tid != tid) TDM_NEVER_GET_HERE(); @@ -787,6 +856,8 @@ _tdm_output_wait_vblank(tdm_output *output, int interval, int sync, sync, vblank_handler); TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed); + _tdm_output_vblank_timeout_update(private_output, 1000); + if (tdm_debug_module & TDM_DEBUG_COMMIT) TDM_INFO("output(%d) backend wait_vblank", private_output->pipe); } diff --git a/src/tdm_private.h b/src/tdm_private.h index 058c228..6cf2a6d 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -113,6 +113,8 @@ tdm_output_cb_dpms(tdm_output *output_backend, tdm_output_dpms dpms, tdm_error tdm_output_cb_need_validate(tdm_private_output *private_output); +void +tdm_output_vblank_print_wait_information(tdm_private_output *private_output, void *user_data); tdm_error tdm_output_wait_vblank_add_front(tdm_output *output, int interval, int sync, tdm_output_vblank_handler func, void *user_data); diff --git a/src/tdm_private_types.h b/src/tdm_private_types.h index a406ecd..8f7fb7d 100644 --- a/src/tdm_private_types.h +++ b/src/tdm_private_types.h @@ -186,6 +186,8 @@ struct _tdm_private_output { tdm_vblank *vblank; int layer_waiting_vblank; + tdm_event_loop_source *vblank_timeout_timer; + /* seperate list for multi-thread*/ struct list_head change_handler_list_main; struct list_head change_handler_list_sub; @@ -341,6 +343,8 @@ struct _tdm_private_vblank_handler { tdm_output_vblank_handler func; void *user_data; + unsigned int sent_to_frontend; + pid_t owner_tid; }; diff --git a/src/tdm_server.c b/src/tdm_server.c index c1b1359..8fc2336 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -168,13 +168,12 @@ _tdm_server_send_done(tdm_server_wait_info *wait_info, tdm_error error, tdm_server_wait_info *found; tdm_server_vblank_info *vblank_info; - if (!keep_private_server) - return; + TDM_RETURN_IF_FAIL(keep_private_server != NULL); LIST_FIND_ITEM(wait_info, &keep_private_server->wait_list, tdm_server_wait_info, link, found); if (!found) { - TDM_DBG("wait_info(%p) is destroyed", wait_info); + TDM_ERR("wait_info(%p) is destroyed", wait_info); return; } diff --git a/src/tdm_vblank.c b/src/tdm_vblank.c index 16c1838..d9738fb 100644 --- a/src/tdm_vblank.c +++ b/src/tdm_vblank.c @@ -126,6 +126,9 @@ typedef struct _tdm_private_vblank { /* for SW */ tdm_event_loop_source *SW_timer; struct list_head SW_wait_list; + + /* for timeout */ + tdm_event_loop_source *timeout_timer; } tdm_private_vblank; struct _tdm_vblank_wait_info { @@ -136,6 +139,7 @@ struct _tdm_vblank_wait_info { double req_time; unsigned int interval; + int hw_interval; tdm_vblank_handler func; void *user_data; @@ -170,6 +174,9 @@ static tdm_error _tdm_vblank_wait_SW(tdm_vblank_wait_info *wait_info); static void _tdm_vblank_cb_vblank_HW(tdm_output *output, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data); +static void _tdm_vblank_timeout_timer_update(tdm_private_vblank *private_vblank, int ms_delay); +static void _tdm_vblank_get_client_information(tdm_private_vblank *private_vblank, + pid_t *pid, const char **name); #if 0 static void @@ -330,6 +337,13 @@ _tdm_vblank_free_HW_wait(tdm_private_vblank *private_vblank, tdm_error error, un { tdm_vblank_wait_info *w = NULL, *ww = NULL; + if (!LIST_IS_EMPTY(&private_vblank->HW_wait_list)) { + pid_t pid; + const char *proc_name; + _tdm_vblank_get_client_information(private_vblank, &pid, &proc_name); + VER("TDM HW vblank destroyed forcely!! (pid: %u, name: %s)", pid, proc_name); + } + LIST_FOR_EACH_ENTRY_SAFE(w, ww, &private_vblank->HW_wait_list, link) { LIST_DEL(&w->link); _tdm_vblank_valid_list_del(&w->valid_link); @@ -401,8 +415,13 @@ _tdm_vblank_cb_output_change(tdm_output *output, tdm_output_change_type type, if (TDM_OUTPUT_DPMS_VSYNC_IS_OFF(value.u32)) { if (private_vblank->enable_fake) _tdm_vblank_change_to_SW(private_vblank); - else + else { + tdm_display_lock(private_vblank->dpy); + _tdm_vblank_timeout_timer_update(private_vblank, 0); + tdm_display_unlock(private_vblank->dpy); + _tdm_vblank_free_HW_wait(private_vblank, TDM_ERROR_DPMS_OFF, 1); + } } break; case TDM_OUTPUT_CHANGE_CONNECTION: @@ -414,8 +433,13 @@ _tdm_vblank_cb_output_change(tdm_output *output, tdm_output_change_type type, if (private_vblank->connection == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) { if (private_vblank->enable_fake) _tdm_vblank_change_to_SW(private_vblank); - else + else { + tdm_display_lock(private_vblank->dpy); + _tdm_vblank_timeout_timer_update(private_vblank, 0); + tdm_display_unlock(private_vblank->dpy); + _tdm_vblank_free_HW_wait(private_vblank, TDM_ERROR_OUTPUT_DISCONNECTED, 1); + } } break; default: @@ -645,7 +669,7 @@ tdm_vblank_create(tdm_display *dpy, tdm_output *output, tdm_error *error) /* LCOV_EXCL_START */ if (error) *error = TDM_ERROR_OUT_OF_MEMORY; - VER("alloc failed"); + TDM_ERR("alloc failed"); return NULL; /* LCOV_EXCL_STOP */ } @@ -706,12 +730,25 @@ tdm_vblank_destroy(tdm_vblank *vblank) _tdm_vblank_free_HW_wait(private_vblank, 0, 0); + if (!LIST_IS_EMPTY(&private_vblank->SW_wait_list)) { + pid_t pid; + const char *proc_name; + _tdm_vblank_get_client_information(private_vblank, &pid, &proc_name); + VER("TDM SW vblank destroyed forcely!! (pid: %u, name: %s)", pid, proc_name); + } + LIST_FOR_EACH_ENTRY_SAFE(w, ww, &private_vblank->SW_wait_list, link) { LIST_DEL(&w->link); _tdm_vblank_valid_list_del(&w->valid_link); free(w); } + if (private_vblank->timeout_timer) { + tdm_display_lock(private_vblank->dpy); + tdm_event_loop_source_remove(private_vblank->timeout_timer); + tdm_display_unlock(private_vblank->dpy); + } + VIN("destroyed"); free(private_vblank); @@ -914,6 +951,65 @@ tdm_vblank_get_enable_fake(tdm_vblank *vblank, unsigned int *enable_fake) } static tdm_error +_tdm_vblank_timeout_timer_cb(void *user_data) +{ + tdm_private_vblank *private_vblank = user_data; + tdm_vblank_wait_info *w = NULL; + pid_t pid; + const char *proc_name; + + TDM_RETURN_VAL_IF_FAIL(private_vblank != NULL, TDM_ERROR_OPERATION_FAILED); + + _tdm_vblank_get_client_information(private_vblank, &pid, &proc_name); + + VER("TDM vblank TIMEOUT!! (pid: %u, name: %s)", pid, proc_name); + VER("quotient(%u) last_seq(%u) last_time(%.6f)", private_vblank->quotient, private_vblank->last_seq, private_vblank->last_time); + + LIST_FOR_EACH_ENTRY(w, &private_vblank->HW_wait_list, link) { + VER("wait_info(%p) req_time(%.6f) target_seq(%u) interval(%u) hw_interval(%d)", + w, w->req_time, w->target_seq, w->interval, w->hw_interval); + tdm_output_vblank_print_wait_information(private_vblank->output, w); + } + + LIST_FOR_EACH_ENTRY(w, &private_vblank->SW_wait_list, link) { + VER("wait_info(%p) req_time(%.6f) target_time(%.6f) target_seq(%u) interval(%u)", + w, w->req_time, w->target_time, w->target_seq, w->interval); + } + + return TDM_ERROR_NONE; +} + +static void +_tdm_vblank_timeout_timer_update(tdm_private_vblank *private_vblank, int ms_delay) +{ + tdm_error ret; + + if (!private_vblank->timeout_timer) { + private_vblank->timeout_timer = + tdm_event_loop_add_timer_handler(private_vblank->dpy, + _tdm_vblank_timeout_timer_cb, + private_vblank, + &ret); + if (!private_vblank->timeout_timer) { + VER("couldn't add timer"); + return; + } + VIN("Create Timeout timer"); + } + + ret = tdm_event_loop_source_timer_update(private_vblank->timeout_timer, ms_delay); + if (ret != TDM_ERROR_NONE) { + VER("couldn't update timer"); + return; + } + + if (ms_delay != 0) + VDB("timeout timer updated"); + else + VDB("timeout timer disabled"); +} + +static tdm_error _tdm_vblank_sw_timer_update(tdm_private_vblank *private_vblank) { tdm_vblank_wait_info *first_wait_info = NULL; @@ -985,7 +1081,7 @@ _tdm_vblank_cb_vblank_HW(tdm_output *output, unsigned int sequence, tdm_private_vblank *private_vblank; if (!_tdm_vblank_check_valid_wait(wait_info)) { - TDM_DBG("can't find wait(%p) from valid_wait_list", wait_info); + TDM_ERR("can't find wait(%p) from valid_wait_list", wait_info); return; } @@ -993,7 +1089,7 @@ _tdm_vblank_cb_vblank_HW(tdm_output *output, unsigned int sequence, TDM_RETURN_IF_FAIL(tdm_vblank_is_valid(private_vblank)); if (!_tdm_vblank_find_wait(wait_info, &private_vblank->HW_wait_list)) { - VDB("can't find wait(%p)", wait_info); + VER("can't find wait(%p)", wait_info); return; } @@ -1014,13 +1110,17 @@ _tdm_vblank_cb_vblank_HW(tdm_output *output, unsigned int sequence, /* wait_info will be freed in _tdm_vblank_cb_vblank_SW() */ if (ret == TDM_ERROR_NONE) { - VDB("wait(%p) SW timer", wait_info); + VIN("wait(%p) SW timer", wait_info); return; } - VWR("couldn't update sw timer"); + VER("couldn't update sw timer"); } + tdm_display_lock(private_vblank->dpy); + _tdm_vblank_timeout_timer_update(private_vblank, 0); + tdm_display_unlock(private_vblank->dpy); + LIST_DEL(&wait_info->link); _tdm_vblank_valid_list_del(&wait_info->valid_link); @@ -1064,9 +1164,9 @@ _tdm_vblank_wait_HW(tdm_vblank_wait_info *wait_info) _tdm_vblank_insert_wait(wait_info, &private_vblank->HW_wait_list); - hw_interval = wait_info->interval * private_vblank->quotient; - if (private_vblank->last_time == 0) { + hw_interval = wait_info->interval * private_vblank->quotient; + /* SW vblank starts from now. SW vblank doesn't need to be aligned with HW vblank. */ private_vblank->last_seq = 0; private_vblank->last_time = tdm_helper_get_time(); @@ -1111,6 +1211,7 @@ _tdm_vblank_wait_HW(tdm_vblank_wait_info *wait_info) } private_vblank->last_interval = hw_interval; + wait_info->hw_interval = hw_interval; if (tdm_ttrace_module & TDM_TTRACE_VBLANK) TDM_TRACE_ASYNC_BEGIN((int)wait_info->req_time, "TDM_Vblank:%u", (unsigned int)private_vblank->stamp); @@ -1155,7 +1256,7 @@ tdm_vblank_cb_vblank_SW(tdm_vblank *vblank, double vblank_stamp) else { private_vblank = _tdm_vblank_find(vblank_stamp); if (!private_vblank) { - TDM_DBG("can't find vblank(%.0f) from valid_list", vblank_stamp); + TDM_ERR("can't find vblank(%.0f) from valid_list", vblank_stamp); return TDM_ERROR_NONE; } } @@ -1180,9 +1281,14 @@ tdm_vblank_cb_vblank_SW(tdm_vblank *vblank, double vblank_stamp) return TDM_ERROR_OPERATION_FAILED; } + if (!LIST_IS_EMPTY(&private_vblank->HW_wait_list)) + TDM_NEVER_GET_HERE(); + first_wait_info = container_of(private_vblank->SW_wait_list.next, first_wait_info, link); TDM_RETURN_VAL_IF_FAIL(first_wait_info != NULL, TDM_ERROR_OPERATION_FAILED); + _tdm_vblank_timeout_timer_update(private_vblank, 0); + if (private_vblank->last_seq >= first_wait_info->target_seq) TDM_ERR("last_seq(%u) target_seq(%u)", private_vblank->last_seq, first_wait_info->target_seq); @@ -1399,6 +1505,10 @@ tdm_vblank_wait(tdm_vblank *vblank, unsigned int req_sec, unsigned int req_usec, /* LCOV_EXCL_STOP */ } + tdm_display_lock(private_vblank->dpy); + _tdm_vblank_timeout_timer_update(private_vblank, 1000); + tdm_display_unlock(private_vblank->dpy); + return TDM_ERROR_NONE; } @@ -1415,7 +1525,7 @@ tdm_vblank_wait_seq(tdm_vblank *vblank, unsigned int req_sec, unsigned int req_u /* if the sequence of vblank reaches the max value, sequence can be 0. */ if (private_vblank->last_seq == 0) { - TDM_WRN("can't calculate interval with sequence(%u)", sequence); + VWR("can't calculate interval with sequence(%u)", sequence); interval = 1; } else if (sequence > private_vblank->last_seq || TDM_VBLANK_SEQ_REACHED_MAX(sequence, private_vblank->last_seq)) { @@ -1443,7 +1553,7 @@ tdm_vblank_wait_seq(tdm_vblank *vblank, unsigned int req_sec, unsigned int req_u interval = (unsigned int)((seq_target - curr) / private_vblank->vblank_gap + TDM_TIME_MARGIN) + 1; } else { /* this seems error. But we handle this like normal to avoid the unexpected error in cliend side */ - TDM_WRN("sequence(%u) should be over the last sequence(%u)", sequence, private_vblank->last_seq); + VER("sequence(%u) should be over the last sequence(%u)", sequence, private_vblank->last_seq); func(vblank, TDM_ERROR_NONE, private_vblank->last_seq, TDM_TIME_SEC(private_vblank->last_time), TDM_TIME_USEC(private_vblank->last_time), user_data); @@ -1512,6 +1622,29 @@ _tdm_vblank_get_waiting_count(tdm_private_vblank *private_vblank) return count; } +static void +_tdm_vblank_get_client_information(tdm_private_vblank *private_vblank, pid_t *pid, const char **name) +{ + struct wl_client *client; + + if (!private_vblank->resource) + goto no_client; + + client = wl_resource_get_client(private_vblank->resource); + if (!client) + goto no_client; + + wl_client_get_credentials(client, pid, NULL, NULL); + *name = tdm_server_get_client_name(*pid); + + return; + +no_client: + *pid = 0; + *name = NULL; + return; +} + /* LCOV_EXCL_START */ INTERN void tdm_vblank_get_vblank_list_information(tdm_display *dpy, char *reply, int *len) @@ -1536,13 +1669,7 @@ tdm_vblank_get_vblank_list_information(tdm_display *dpy, char *reply, int *len) pid_t pid = 0; unsigned int count; - 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_vblank_get_client_information(v, &pid, &proc_name); count = _tdm_vblank_get_waiting_count(v); -- 2.7.4 From e298acd23404bb4fc206cdb8465b026ee6c58f50 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Fri, 2 Feb 2018 14:36:37 +0900 Subject: [PATCH 11/16] remove -f when creating symbolic link file Change-Id: Ie2413243fa9b60b2a913af322f48366b5fb38e6a --- service/tdm-socket-user.service | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/tdm-socket-user.service b/service/tdm-socket-user.service index 367a531..c2e7a18 100644 --- a/service/tdm-socket-user.service +++ b/service/tdm-socket-user.service @@ -4,4 +4,4 @@ DefaultDependencies=no [Service] Type=oneshot -ExecStart=/usr/bin/ln -sf /run/tdm-socket /run/user/%U/ +ExecStart=/usr/bin/ln -s /run/tdm-socket /run/user/%U/ -- 2.7.4 From 5a9bb5a3da7b6d437d35aaa9ea9daeb7acc62476 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Thu, 1 Feb 2018 11:15:42 +0900 Subject: [PATCH 12/16] apply gcov Change-Id: I6a9c95804a76349a62d5b16d6915042cf4920adb --- client/Makefile.am | 1 + packaging/libtdm.spec | 7 +++++++ src/Makefile.am | 2 +- utests/src/ut_main.cpp | 12 ++++++++++++ 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/client/Makefile.am b/client/Makefile.am index af2503f..859e2d3 100644 --- a/client/Makefile.am +++ b/client/Makefile.am @@ -42,6 +42,7 @@ tdm_monitor_LDFLAGS = \ tdm_monitor_LDADD = $(TDM_CLIENT_LIBS) ../common/libtdm-common.la tdm_monitor_CFLAGS = \ -fPIE \ + $(CFLAGS) \ $(TDM_CFLAGS) \ -I$(top_srcdir)/include \ -I$(top_srcdir)/protocol \ diff --git a/packaging/libtdm.spec b/packaging/libtdm.spec index 8abd7e0..3bcc41b 100644 --- a/packaging/libtdm.spec +++ b/packaging/libtdm.spec @@ -1,4 +1,5 @@ %define UTEST_PACKAGE 1 +%define UTEST_GCOV 0 Name: libtdm Version: 1.11.5 @@ -74,6 +75,12 @@ UTEST="no" UTEST="yes" %endif +%if "%{UTEST_GCOV}" == "1" +CFLAGS+=" -fprofile-arcs -ftest-coverage -DTIZEN_TEST_GCOV" +CXXFLAGS+=" -fprofile-arcs -ftest-coverage -DTIZEN_TEST_GCOV" +LDFLAGS+=" -lgcov" +%endif + %reconfigure --disable-static --with-utests=${UTEST} \ CFLAGS="${CFLAGS} -Wall -Werror" \ CXXFLAGS="${CXXFLAGS} -Wall -Werror" \ diff --git a/src/Makefile.am b/src/Makefile.am index 8542130..feabb5d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,6 @@ libtdm_la_LTLIBRARIES = libtdm.la libtdm_ladir = $(libdir) -libtdm_la_LDFLAGS = -version-number 1:0:0 -no-undefined +libtdm_la_LDFLAGS = $(LDFLAGS) -version-number 1:0:0 -no-undefined libtdm_la_LIBADD = $(TDM_LIBS) -ldl -lpthread ../common/libtdm-common.la libtdm_la_CFLAGS = \ $(CFLAGS) \ diff --git a/utests/src/ut_main.cpp b/utests/src/ut_main.cpp index c056a2f..0dbfc72 100644 --- a/utests/src/ut_main.cpp +++ b/utests/src/ut_main.cpp @@ -30,10 +30,18 @@ #include "gtest/gtest.h" +#ifdef TIZEN_TEST_GCOV +extern "C" void __gcov_flush(void); +#endif + int main(int argc, char **argv) { auto AllTestSuccess = false; +#ifdef TIZEN_TEST_GCOV + setenv("GCOV_PREFIX", "/tmp", 1); +#endif + try { ::testing::InitGoogleTest(&argc, argv); ::testing::FLAGS_gtest_death_test_style = "fast"; @@ -50,5 +58,9 @@ int main(int argc, char **argv) std::cout << "\n"; } +#ifdef TIZEN_TEST_GCOV + __gcov_flush(); +#endif + return AllTestSuccess; } \ No newline at end of file -- 2.7.4 From 8bd17e55805dadd575dfc648b329cabd67428cc7 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Fri, 2 Feb 2018 09:47:06 +0900 Subject: [PATCH 13/16] add tdm_vblank_set_client_ignore_global_fps Change-Id: I9b627988ed02dd6e22a2e6d52cd97d205497e857 --- include/tdm.h | 10 ++++++++++ src/tdm_vblank.c | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/include/tdm.h b/include/tdm.h index 18ef948..cb112f7 100644 --- a/include/tdm.h +++ b/include/tdm.h @@ -1268,6 +1268,16 @@ tdm_error tdm_vblank_set_client_vblank_fps(unsigned int pid, const char *name, unsigned int fps); /** + * @brief Set the ignore global fps for the given PID and name. + * @param[in] pid The process ID + * @param[in] name The client vblank name + * @param[in] ignore 1: ignore 0:not ignore(default) + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error +tdm_vblank_set_client_ignore_global_fps(unsigned int pid, const char *name, unsigned int ignore); + +/** * @brief Set the vblank global fps for the entire system. * @param[in] enable 1:enable, 0:disable * @param[in] fps The vblank global fps diff --git a/src/tdm_vblank.c b/src/tdm_vblank.c index d9738fb..21dd98b 100644 --- a/src/tdm_vblank.c +++ b/src/tdm_vblank.c @@ -490,6 +490,46 @@ tdm_vblank_set_client_vblank_fps(unsigned int pid, const char *name, unsigned in } EXTERN tdm_error +tdm_vblank_set_client_ignore_global_fps(unsigned int pid, const char *name, unsigned int ignore) +{ + tdm_private_vblank *v = NULL; + + TDM_RETURN_VAL_IF_FAIL(pid > 0, TDM_ERROR_INVALID_PARAMETER); + + TDM_INFO("pid: %u, name: %s, ignore: %u", pid, name, ignore); + + pthread_mutex_lock(&valid_list_lock); + LIST_FOR_EACH_ENTRY(v, &valid_vblank_list, valid_link) { + struct wl_client *client; + pid_t client_pid = 0; + + if (!v->resource) + continue; + + client = wl_resource_get_client(v->resource); + if (!client) + continue; + + wl_client_get_credentials(client, &client_pid, NULL, NULL); + + if (client_pid != pid) + continue; + + if (name && strncmp(name, TDM_VBLANK_DEFAULT_NAME, TDM_NAME_LEN)) { + if (strncmp(v->name, name, TDM_NAME_LEN)) + continue; + } + + tdm_vblank_ignore_global_fps(v, ignore); + + TDM_INFO("(pid:%u) '%s' ignore changed: %u", pid, v->name, ignore); + } + pthread_mutex_unlock(&valid_list_lock); + + return TDM_ERROR_NONE; +} + +EXTERN tdm_error tdm_vblank_enable_global_fps(unsigned int enable, unsigned int fps) { tdm_private_vblank *v = NULL; -- 2.7.4 From 03a186d6014cced34a6f54f65aa28f26ded5de8d Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Tue, 30 Jan 2018 19:38:18 +0900 Subject: [PATCH 14/16] hwc: remove dump code Change-Id: I3ea9b6011c757497f4afdfd4bbca2bcb715b3b90 --- src/tdm_hwc_window.c | 28 ---------------------------- src/tdm_output.c | 24 ------------------------ 2 files changed, 52 deletions(-) diff --git a/src/tdm_hwc_window.c b/src/tdm_hwc_window.c index 40820ce..23c9775 100644 --- a/src/tdm_hwc_window.c +++ b/src/tdm_hwc_window.c @@ -229,28 +229,6 @@ tdm_hwc_window_set_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info) return ret; } -/* LCOV_EXCL_START */ -static void -_tdm_window_dump_buffer(tdm_hwc_window *hwc_window, tbm_surface_h buffer) -{ - tdm_private_hwc_window *private_window = (tdm_private_hwc_window *)hwc_window; - tdm_private_output *private_output = private_window->private_output; - unsigned int pipe; - uint32_t zpos; - char fname[TDM_PATH_LEN]; - - pipe = private_output->pipe; - zpos = private_window->zpos; - - snprintf(fname, sizeof(fname), "tdm_%d_win_%d", pipe, zpos); - - tbm_surface_internal_dump_buffer(buffer, fname); - TDM_DBG("%s dump excute", fname); - - return; -} -/* LCOV_EXCL_STOP */ - EXTERN tdm_error tdm_hwc_window_set_buffer(tdm_hwc_window *hwc_window, tbm_surface_h buffer) { @@ -280,12 +258,6 @@ tdm_hwc_window_set_buffer(tdm_hwc_window *hwc_window, tbm_surface_h buffer) /* LCOV_EXCL_STOP */ } - /* dump buffer */ - /* LCOV_EXCL_START */ - if (tdm_dump_enable && buffer) - _tdm_window_dump_buffer(hwc_window, buffer); - /* LCOV_EXCL_STOP */ - ret = func_hwc_window->hwc_window_set_buffer(private_hwc_window->hwc_window_backend, buffer); _pthread_mutex_unlock(&private_display->lock); diff --git a/src/tdm_output.c b/src/tdm_output.c index 4105ced..7aad41d 100644 --- a/src/tdm_output.c +++ b/src/tdm_output.c @@ -1755,24 +1755,6 @@ tdm_output_hwc_get_target_buffer_queue(tdm_output *output, tdm_error *error) return queue; } -/* LCOV_EXCL_START */ -static void -_tdm_target_window_dump_buffer(tdm_private_output *private_output, tbm_surface_h buffer) -{ - unsigned int pipe; - char fname[TDM_PATH_LEN]; - - pipe = private_output->pipe; - - snprintf(fname, sizeof(fname), "tdm_%d_target_win", pipe); - - tbm_surface_internal_dump_buffer(buffer, fname); - TDM_DBG("%s dump excute", fname); - - return; -} -/* LCOV_EXCL_STOP */ - EXTERN tdm_error tdm_output_hwc_set_client_target_buffer(tdm_output *output, tbm_surface_h target_buffer, tdm_hwc_region damage, tdm_hwc_window **composited_wnds, @@ -1813,12 +1795,6 @@ tdm_output_hwc_set_client_target_buffer(tdm_output *output, tbm_surface_h target /* LCOV_EXCL_STOP */ } - /* dump buffer */ - if (tdm_dump_enable) - /* LCOV_EXCL_START */ - _tdm_target_window_dump_buffer((tdm_private_output *)output, target_buffer); - /* LCOV_EXCL_STOP */ - if (num_wnds == 0) { ret = func_output->output_hwc_set_client_target_buffer(private_output->output_backend, target_buffer, damage, NULL, 0); -- 2.7.4 From 6b4962965ed73daa5185f2ce28a5f52f60d155b1 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Fri, 2 Feb 2018 14:51:37 +0900 Subject: [PATCH 15/16] package version up to 1.11.6 Change-Id: Ib2e3808acbb0202c81e51e5b732ce35a8c4a5dbd --- packaging/libtdm.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libtdm.spec b/packaging/libtdm.spec index 3bcc41b..970ce1b 100644 --- a/packaging/libtdm.spec +++ b/packaging/libtdm.spec @@ -2,7 +2,7 @@ %define UTEST_GCOV 0 Name: libtdm -Version: 1.11.5 +Version: 1.11.6 Release: 0 Summary: User Library of Tizen Display Manager Group: Development/Libraries -- 2.7.4 From adc84dc2bdaeedfc198dc3328e0614beda9771af Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Fri, 2 Feb 2018 15:20:21 +0900 Subject: [PATCH 16/16] hwc: change the tdm_output_validate api Change-Id: I06d493570e21ae6559a80d7589ab41e3076b68ef --- include/tdm.h | 3 ++- include/tdm_backend.h | 3 ++- src/tdm_output.c | 31 +++++++++++++++++++++++++++++-- utests/src/ut_tdm_hwc_window.cpp | 13 ++++++++++--- 4 files changed, 43 insertions(+), 7 deletions(-) diff --git a/include/tdm.h b/include/tdm.h index cb112f7..43b5e02 100644 --- a/include/tdm.h +++ b/include/tdm.h @@ -653,7 +653,8 @@ tdm_output_hwc_set_client_target_buffer(tdm_output *output, tbm_surface_h target * @since 2.0.0 */ tdm_error -tdm_output_hwc_validate(tdm_output *output, uint32_t *num_types); +tdm_output_hwc_validate(tdm_output *output, tdm_hwc_window **composited_wnds, uint32_t num_wnds, + uint32_t *num_types); /** * @brief Set the 'need to validate' handler for the 'output' diff --git a/include/tdm_backend.h b/include/tdm_backend.h index fa36479..e3940e9 100644 --- a/include/tdm_backend.h +++ b/include/tdm_backend.h @@ -612,7 +612,8 @@ typedef struct _tdm_func_output { * @return #TDM_ERROR_NONE if success. Otherwise, error value. * @since 2.0.0 */ - tdm_error (*output_hwc_validate)(tdm_output *output, uint32_t *num_types); + tdm_error (*output_hwc_validate)(tdm_output *output, tdm_hwc_window **composited_wnds, uint32_t num_wnds, + uint32_t *num_types); /** * @brief Get changed composition types diff --git a/src/tdm_output.c b/src/tdm_output.c index 7aad41d..19dfc4f 100644 --- a/src/tdm_output.c +++ b/src/tdm_output.c @@ -1557,9 +1557,13 @@ tdm_output_hwc_destroy_window(tdm_output *output, tdm_hwc_window *hwc_window) } EXTERN tdm_error -tdm_output_hwc_validate(tdm_output *output, uint32_t *num_types) +tdm_output_hwc_validate(tdm_output *output, tdm_hwc_window **composited_wnds, + uint32_t num_wnds, uint32_t *num_types) { tdm_func_output *func_output = NULL; + tdm_private_hwc_window **composited_wnds_frontend = NULL; + tdm_hwc_window **composited_wnds_backend = NULL; + int i; OUTPUT_FUNC_ENTRY(); @@ -1583,7 +1587,30 @@ tdm_output_hwc_validate(tdm_output *output, uint32_t *num_types) /* LCOV_EXCL_STOP */ } - ret = func_output->output_hwc_validate(private_output->output_backend, num_types); + if (num_wnds == 0) { + ret = func_output->output_hwc_validate(private_output->output_backend, NULL, 0, num_types); + + _pthread_mutex_unlock(&private_display->lock); + + return ret; + } + + composited_wnds_backend = calloc(num_wnds, sizeof(tdm_hwc_window *)); + if (!composited_wnds_backend) { + /* LCOV_EXCL_START */ + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_OUT_OF_MEMORY; + /* LCOV_EXCL_STOP */ + } + + composited_wnds_frontend = (tdm_private_hwc_window **)composited_wnds; + + for (i = 0; i < num_wnds; i++) + composited_wnds_backend[i] = composited_wnds_frontend[i]->hwc_window_backend; + + ret = func_output->output_hwc_validate(private_output->output_backend, composited_wnds_backend, num_wnds, num_types); + + free(composited_wnds_backend); _pthread_mutex_unlock(&private_display->lock); diff --git a/utests/src/ut_tdm_hwc_window.cpp b/utests/src/ut_tdm_hwc_window.cpp index 48472d3..38ceae0 100644 --- a/utests/src/ut_tdm_hwc_window.cpp +++ b/utests/src/ut_tdm_hwc_window.cpp @@ -641,15 +641,17 @@ TEST_F(TDMHwcWindow, VideoGetCapabilitySuccessful) } } -/* tdm_error tdm_output_hwc_validate(tdm_output *output, uint32_t *num_types); */ +/* tdm_error tdm_output_hwc_validate(tdm_output *output, tdm_hwc_window **composited_wnds, uint32_t num_wnds, + uint32_t *num_types); */ +/* TODO: fix the validate test later. TEST_F(TDMOutputHwc, ValidateFailNull) { uint32_t num_types; - error = tdm_output_hwc_validate(NULL, &num_types); + error = tdm_output_hwc_validate(NULL, NULL, 0, &num_types); ASSERT_NE(TDM_ERROR_NONE, error); if (outputs[0]) { - error = tdm_output_hwc_validate(outputs[0], NULL); + error = tdm_output_hwc_validate(outputs[0], NULL, 0, NULL); ASSERT_NE(TDM_ERROR_NONE, error); } } @@ -677,6 +679,7 @@ TEST_F(TDMOutputHwc, ValidateSuccessful) } } } +TODO: */ /* tdm_error tdm_output_hwc_get_changed_composition_types(tdm_output *output, uint32_t *num_elements, tdm_hwc_window **hwc_window, @@ -705,6 +708,7 @@ TEST_F(TDMOutputHwcWithoutHwcCap, GetChangedCompositionTypesFailNoHwc) } } +/* TODO: fix the validate test later. TEST_F(TDMHwcWindow, GetChangedCompositionTypesSuccessful) { uint32_t validate_num; @@ -743,6 +747,7 @@ TEST_F(TDMHwcWindow, GetChangedCompositionTypesSuccessful) } } } +*/ /* tdm_error tdm_output_hwc_accept_changes(tdm_output *output); */ @@ -760,6 +765,7 @@ TEST_F(TDMOutputHwcWithoutHwcCap, AcceptChangesFailNoHwc) } } +/* TODO: fix the validate test later. TEST_F(TDMHwcWindow, AcceptChangesSuccessful) { uint32_t validate_num; @@ -781,6 +787,7 @@ TEST_F(TDMHwcWindow, AcceptChangesSuccessful) } } } +*/ static int need_validate_handler_is_called = 0; static void need_validate_handler(tdm_output *output) -- 2.7.4