From 132c57993f4a6d8c1c89ac8308a46669266934ca Mon Sep 17 00:00:00 2001 From: Boram Park Date: Fri, 6 Jan 2017 22:15:11 +0900 Subject: [PATCH 01/16] package version up to 1.5.3 Change-Id: I9647ce823de2d4e110425a09a28a9829415f16c6 --- packaging/libtdm.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libtdm.spec b/packaging/libtdm.spec index 31bd12b..2409923 100644 --- a/packaging/libtdm.spec +++ b/packaging/libtdm.spec @@ -1,7 +1,7 @@ %bcond_with utest Name: libtdm -Version: 1.5.2 +Version: 1.5.3 Release: 0 Summary: User Library of Tizen Display Manager Group: Development/Libraries -- 2.7.4 From 9ebea63128d7636ad9a35ae0e823a89eb6aaf7b2 Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Mon, 9 Jan 2017 11:38:33 +0900 Subject: [PATCH 02/16] change capture destroy eina_list element structure Change-Id: Ifc52fd72ae0b484d01e0f4533d8439c961b92eb7 Signed-off-by: Junkyeong Kim --- src/tdm_capture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tdm_capture.c b/src/tdm_capture.c index 45ea3e1..a422914 100644 --- a/src/tdm_capture.c +++ b/src/tdm_capture.c @@ -326,7 +326,7 @@ tdm_capture_destroy_internal(tdm_private_capture *private_capture) { tdm_private_display *private_display; tdm_func_capture *func_capture; - tdm_pp_private_buffer *b = NULL, *bb = NULL; + tdm_capture_private_buffer *b = NULL, *bb = NULL; struct list_head clone_list; TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); -- 2.7.4 From 1c44c129755a129a45d4d59e54ac482a58d64f62 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Wed, 11 Jan 2017 19:38:22 +0900 Subject: [PATCH 03/16] apply tizen coding rule Change-Id: I22de70e36d516c2c4dce32642945e46c64477573 --- client/tdm_client.c | 2 +- src/tdm.c | 10 +++++----- src/tdm_buffer.c | 2 +- src/tdm_capture.c | 2 +- src/tdm_display.c | 4 ++-- src/tdm_helper.c | 28 +++++++++++++--------------- src/tdm_monitor_server.c | 5 ++--- src/tdm_pp.c | 2 +- src/tdm_server.c | 6 +++--- src/tdm_vblank.c | 10 +++++----- tools/tdm_test_client.c | 4 ++-- tools/tdm_test_server.c | 12 ++++++------ 12 files changed, 42 insertions(+), 45 deletions(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index 7e17d1e..c9b312c 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -852,4 +852,4 @@ tdm_client_vblank_wait_seq(tdm_client_vblank *vblank, unsigned int sequence, free(w); return TDM_ERROR_NONE; -} \ No newline at end of file +} diff --git a/src/tdm.c b/src/tdm.c index 5d2714c..c6023a2 100644 --- a/src/tdm.c +++ b/src/tdm.c @@ -1110,7 +1110,7 @@ tdm_display_enable_dump(tdm_private_display *private_display, const char *dump_s if (!strncmp(arg, "none", 4)) { tdm_debug_dump = 0; - TDM_SNPRINTF(reply, len, "path: %s\n", (tdm_debug_dump_dir)?:"unknown"); + TDM_SNPRINTF(reply, len, "path: %s\n", (tdm_debug_dump_dir) ? : "unknown"); if (tdm_debug_dump_dir) { free(tdm_debug_dump_dir); tdm_debug_dump_dir = NULL; @@ -1257,9 +1257,9 @@ tdm_display_enable_ttrace_vblank(tdm_display *dpy, tdm_output *output, int enabl return TDM_ERROR_NONE; enable_fail: - if (vblank) - tdm_vblank_destroy(vblank); - vblank = NULL; - return ret; + if (vblank) + tdm_vblank_destroy(vblank); + vblank = NULL; + return ret; } diff --git a/src/tdm_buffer.c b/src/tdm_buffer.c index e691507..e3f4107 100644 --- a/src/tdm_buffer.c +++ b/src/tdm_buffer.c @@ -223,7 +223,7 @@ tdm_buffer_unref_backend(tbm_surface_h buffer) tbm_surface_internal_ref(buffer); LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link) - func_info->release_func(buffer, func_info->user_data); + func_info->release_func(buffer, func_info->user_data); tbm_surface_internal_unref(buffer); tbm_surface_internal_unref(buffer); diff --git a/src/tdm_capture.c b/src/tdm_capture.c index a422914..4772332 100644 --- a/src/tdm_capture.c +++ b/src/tdm_capture.c @@ -494,7 +494,7 @@ tdm_capture_attach(tdm_capture *capture, tbm_surface_h buffer) } } - capture_buffer = calloc(1, sizeof *capture_buffer); + capture_buffer = calloc(1, sizeof * capture_buffer); if (!capture_buffer) { _pthread_mutex_unlock(&private_display->lock); TDM_ERR("alloc failed"); diff --git a/src/tdm_display.c b/src/tdm_display.c index 935824e..9cfd290 100644 --- a/src/tdm_display.c +++ b/src/tdm_display.c @@ -1280,7 +1280,7 @@ tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value) if (!private_output->dpms_changed_timer) { private_output->dpms_changed_timer = tdm_event_loop_add_timer_handler(private_output->private_display, - _tdm_output_dpms_changed_timeout, private_output, NULL); + _tdm_output_dpms_changed_timeout, private_output, NULL); if (!private_output->dpms_changed_timer) { TDM_ERR("can't create dpms timer!!"); _pthread_mutex_unlock(&private_display->lock); @@ -1301,7 +1301,7 @@ tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value) if (!private_output->regist_dpms_cb) { private_output->regist_dpms_cb = 1; ret = func_output->output_set_dpms_handler(private_output->output_backend, - tdm_output_cb_dpms, private_output); + tdm_output_cb_dpms, private_output); } } diff --git a/src/tdm_helper.c b/src/tdm_helper.c index 9b31d68..a72f3eb 100644 --- a/src/tdm_helper.c +++ b/src/tdm_helper.c @@ -191,7 +191,7 @@ tdm_helper_dump_make_directory(const char *path, char *reply, int *len) TDM_GOTO_IF_FAIL(t != NULL, failed_make); snprintf(fullpath, TDM_PATH_LEN, "%s/dump_%04d%02d%02d.%02d%02d%02d", path, - t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); + t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); if ((mkdir(fullpath, 0755)) < 0) { TDM_ERR("mkdir '%s' fail\n", fullpath); @@ -457,15 +457,15 @@ tdm_helper_convert_buffer(tbm_surface_h srcbuf, tbm_surface_h dstbuf, if (rotate_step > 0) { int c, s, tx = 0, ty = 0; switch (rotate_step) { - case 1: - c = 0, s = -1, tx = -dstpos->w; - break; - case 2: - c = -1, s = 0, tx = -dstpos->w, ty = -dstpos->h; - break; - case 3: - c = 0, s = 1, ty = -dstpos->h; - break; + case 1: + c = 0, s = -1, tx = -dstpos->w; + break; + case 2: + c = -1, s = 0, tx = -dstpos->w, ty = -dstpos->h; + break; + case 3: + c = 0, s = 1, ty = -dstpos->h; + break; } pixman_f_transform_translate(&ft, NULL, tx, ty); pixman_f_transform_rotate(&ft, NULL, c, s); @@ -595,14 +595,12 @@ _tdm_helper_buffer_convert(tbm_surface_h srcbuf, tbm_surface_h dstbuf, TDM_RETURN_VAL_IF_FAIL(srcbuf != NULL, TDM_ERROR_INVALID_PARAMETER); TDM_RETURN_VAL_IF_FAIL(dstbuf != NULL, TDM_ERROR_INVALID_PARAMETER); - if (tbm_surface_map(srcbuf, TBM_SURF_OPTION_READ, &src_info) - != TBM_SURFACE_ERROR_NONE) { + if (tbm_surface_map(srcbuf, TBM_SURF_OPTION_READ, &src_info) != TBM_SURFACE_ERROR_NONE) { TDM_ERR("cannot mmap srcbuf\n"); return TDM_ERROR_OPERATION_FAILED; } - if (tbm_surface_map(dstbuf, TBM_SURF_OPTION_WRITE, &dst_info) - != TBM_SURFACE_ERROR_NONE) { + if (tbm_surface_map(dstbuf, TBM_SURF_OPTION_WRITE, &dst_info) != TBM_SURFACE_ERROR_NONE) { TDM_ERR("cannot mmap dstbuf\n"); tbm_surface_unmap(srcbuf); return TDM_ERROR_OPERATION_FAILED; @@ -845,7 +843,7 @@ tdm_helper_get_display_information(tdm_display *dpy, char *reply, int *len) size.v = tbm_surface_get_height(private_layer->showing_buffer); if (info.src_config.format) - format = (info.src_config.format)?:format; + format = (info.src_config.format) ? : format; TDM_SNPRINTF(reply, len, "%d %d %d %p %c%c%c%c %ux%u %ux%u+%u+%u %ux%u+%u+%u %s\n", private_layer->index, diff --git a/src/tdm_monitor_server.c b/src/tdm_monitor_server.c index 2a1b318..55ef89b 100644 --- a/src/tdm_monitor_server.c +++ b/src/tdm_monitor_server.c @@ -124,7 +124,7 @@ _tdm_monitor_server_ttrace_vblank(unsigned int pid, char *cwd, int argc, char *a tdm_display_enable_ttrace_vblank(dpy, output, enable); TDM_SNPRINTF(reply, len, "%s ttrace vblank for '%s'\n", - (enable)?"enable":"disable", tdm_conn_str(type)); + (enable) ? "enable" : "disable", tdm_conn_str(type)); } static void @@ -357,8 +357,7 @@ _tdm_monitor_server_punch(unsigned int pid, char *cwd, int argc, char *argv[], c } tdm_helper_clear_buffer_pos(buffer, &pos); - } - else + } else tdm_helper_clear_buffer(buffer); } diff --git a/src/tdm_pp.c b/src/tdm_pp.c index 3be10d3..02de669 100644 --- a/src/tdm_pp.c +++ b/src/tdm_pp.c @@ -418,7 +418,7 @@ tdm_pp_attach(tdm_pp *pp, tbm_surface_h src, tbm_surface_h dst) tdm_helper_dump_buffer_str(src, tdm_debug_dump_dir, str); } - pp_buffer = calloc(1, sizeof *pp_buffer); + pp_buffer = calloc(1, sizeof * pp_buffer); if (!pp_buffer) { _pthread_mutex_unlock(&private_display->lock); TDM_ERR("alloc failed"); diff --git a/src/tdm_server.c b/src/tdm_server.c index ca1ef40..914b1da 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -247,7 +247,7 @@ _tdm_server_vblank_cb_wait_vblank(struct wl_client *client, struct wl_resource * TDM_TRACE_COUNT(ServerWaitVBlank, req_id); - wait_info = calloc(1, sizeof *wait_info); + wait_info = calloc(1, sizeof * wait_info); if (!wait_info) { TDM_ERR("alloc failed"); ret = TDM_ERROR_OUT_OF_MEMORY; @@ -287,7 +287,7 @@ _tdm_server_vblank_cb_wait_vblank_seq(struct wl_client *client, struct wl_resour TDM_TRACE_COUNT(ServerWaitVBlank, req_id); - wait_info = calloc(1, sizeof *wait_info); + wait_info = calloc(1, sizeof * wait_info); if (!wait_info) { TDM_ERR("alloc failed"); ret = TDM_ERROR_OUT_OF_MEMORY; @@ -357,7 +357,7 @@ _tdm_server_output_cb_create_vblank(struct wl_client *client, struct wl_resource return; } - vblank_info = calloc(1, sizeof *vblank_info); + vblank_info = calloc(1, sizeof * vblank_info); if (!vblank_info) { wl_resource_post_no_memory(resource); wl_resource_destroy(vblank_resource); diff --git a/src/tdm_vblank.c b/src/tdm_vblank.c index 8dc85e5..947fcf6 100644 --- a/src/tdm_vblank.c +++ b/src/tdm_vblank.c @@ -296,7 +296,7 @@ _tdm_vblank_cb_output_change(tdm_output *output, tdm_output_change_type type, } } -EXTERN tdm_vblank* +EXTERN tdm_vblank * tdm_vblank_create(tdm_display *dpy, tdm_output *output, tdm_error *error) { tdm_private_vblank *private_vblank; @@ -332,7 +332,7 @@ tdm_vblank_create(tdm_display *dpy, tdm_output *output, tdm_error *error) tdm_output_get_dpms(output, &dpms); - private_vblank = calloc(1, sizeof *private_vblank); + private_vblank = calloc(1, sizeof * private_vblank); if (!private_vblank) { if (error) *error = TDM_ERROR_OUT_OF_MEMORY; @@ -364,7 +364,7 @@ tdm_vblank_create(tdm_display *dpy, tdm_output *output, tdm_error *error) VIN("created. vrefresh(%d) dpms(%d)", private_vblank->vrefresh, private_vblank->dpms); - return (tdm_vblank*)private_vblank; + return (tdm_vblank *)private_vblank; } EXTERN void @@ -498,7 +498,7 @@ _tdm_vblank_sw_timer_update(tdm_private_vblank *private_vblank) if (ms_delay > 5000) VER("wait(%p) curr(%.6f) target(%.6f) ms_delay(%d)", first_wait_info, curr, target, ms_delay); - else if (tdm_debug_module & TDM_DEBUG_VBLANK) + else if (tdm_debug_module & TDM_DEBUG_VBLANK) VIN("wait(%p) curr(%.6f) target(%.6f) ms_delay(%d)", first_wait_info, curr, target, ms_delay); tdm_display_lock(private_vblank->dpy); @@ -828,7 +828,7 @@ tdm_vblank_wait(tdm_vblank *vblank, unsigned int req_sec, unsigned int req_usec, return TDM_ERROR_DPMS_OFF; } - wait_info = calloc(1, sizeof *wait_info); + wait_info = calloc(1, sizeof * wait_info); if (!wait_info) { VER("alloc failed"); return TDM_ERROR_OUT_OF_MEMORY; diff --git a/tools/tdm_test_client.c b/tools/tdm_test_client.c index bb80cc7..fb371f5 100644 --- a/tools/tdm_test_client.c +++ b/tools/tdm_test_client.c @@ -177,10 +177,10 @@ parse_args(tdm_test_client *data, int argc, char *argv[]) data->args.interval = 1; for (i = 1; i < argc; i++) { - if (!strncmp(argv[i]+1, "qo", 2)) { + if (!strncmp(argv[i] + 1, "qo", 2)) { data->do_query = 1; parse_arg_qo(data, argv[++i]); - } else if (!strncmp(argv[i]+1, "v", 1)) { + } else if (!strncmp(argv[i] + 1, "v", 1)) { data->do_vblank = 1; parse_arg_v(data, argv[++i]); } else { diff --git a/tools/tdm_test_server.c b/tools/tdm_test_server.c index d6942a8..1b3854e 100644 --- a/tools/tdm_test_server.c +++ b/tools/tdm_test_server.c @@ -974,9 +974,9 @@ layer_get_buffer(tdm_test_server_layer *l) int i, size = TDM_ARRAY_SIZE(l->bufs); if (!l->bufs[0]) { for (i = 0; i < size; i++) { - int width = (l->info.src_config.size.h)?:l->info.src_config.pos.w; - int height = (l->info.src_config.size.v)?:l->info.src_config.pos.h; - unsigned int format = (l->info.src_config.format)?:DEFAULT_FORMAT; + int width = (l->info.src_config.size.h) ? : l->info.src_config.pos.w; + int height = (l->info.src_config.size.v) ? : l->info.src_config.pos.h; + unsigned int format = (l->info.src_config.format) ? : DEFAULT_FORMAT; int flags = l->o->data->bflags; tbm_surface_h b = buffer_allocate(width, height, format, flags); TDM_EXIT_IF_FAIL(b != NULL); @@ -1109,9 +1109,9 @@ pp_get_buffer(tdm_test_server_pp *p) int i, size = TDM_ARRAY_SIZE(p->bufs); if (!p->bufs[0]) { for (i = 0; i < size; i++) { - int width = (p->info.src_config.size.h)?:p->info.src_config.pos.w; - int height = (p->info.src_config.size.v)?:p->info.src_config.pos.h; - unsigned int format = (p->info.src_config.format)?:DEFAULT_FORMAT; + int width = (p->info.src_config.size.h) ? : p->info.src_config.pos.w; + int height = (p->info.src_config.size.v) ? : p->info.src_config.pos.h; + unsigned int format = (p->info.src_config.format) ? : DEFAULT_FORMAT; tbm_surface_h b = buffer_allocate(width, height, format, 0); TDM_EXIT_IF_FAIL(b != NULL); p->bufs[i] = b; -- 2.7.4 From 323fcbba2cb5dc0ccdad67008c768b240809df19 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Tue, 29 Nov 2016 12:23:07 +0900 Subject: [PATCH 04/16] support the commit-per-vblank If TDM_COMMIT_PER_VBLANK enviroment is set to 1, tdm frontend will call the backend's output_commit function once per a vblank. Change-Id: I9df27288fd9318a64305491e4dc96d686a223baf --- doc/tdm_doc.h | 2 +- include/tdm.h | 22 +- include/tdm_types.h | 10 +- src/tdm.c | 84 +++++-- src/tdm_display.c | 606 ++++++++++++++++++++++++++++++++++++++++------- src/tdm_macro.h | 2 +- src/tdm_monitor_server.c | 52 ++++ src/tdm_private.h | 44 +++- src/tdm_vblank.c | 5 +- tools/tdm_test_server.c | 8 +- 10 files changed, 717 insertions(+), 118 deletions(-) diff --git a/doc/tdm_doc.h b/doc/tdm_doc.h index 2bcfce7..02e3024 100644 --- a/doc/tdm_doc.h +++ b/doc/tdm_doc.h @@ -56,7 +56,7 @@ * and #tdm_layer_create_capture if available.\n * \n * All changes of output/layer/pp/capture objects are applied when committed. - * See #tdm_output_commit, #tdm_pp_commit and #tdm_capture_commit. + * See #tdm_output_commit, #tdm_layer_commit, #tdm_pp_commit and #tdm_capture_commit. * \n * @par Buffer management * TDM has its own buffer release mechanism to let an user know when a TDM buffer diff --git a/include/tdm.h b/include/tdm.h index 15b1f56..3a066c1 100644 --- a/include/tdm.h +++ b/include/tdm.h @@ -479,6 +479,7 @@ tdm_output_wait_vblank(tdm_output *output, int interval, int sync, * @param[in] func A user commit handler * @param[in] user_data The user data * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see #tdm_layer_commit */ tdm_error tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, @@ -613,7 +614,7 @@ tdm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value); * @param[in] layer A layer object * @param[in] info The geometry information * @return #TDM_ERROR_NONE if success. Otherwise, error value. - * @see tdm_output_commit + * @see tdm_layer_commit */ tdm_error tdm_layer_set_info(tdm_layer *layer, tdm_info_layer *info); @@ -634,7 +635,7 @@ tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info); * @param[in] layer A layer object * @param[in] buffer A TDM buffer * @return #TDM_ERROR_NONE if success. Otherwise, error value. - * @see tdm_output_commit + * @see tdm_layer_commit */ tdm_error tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer); @@ -650,6 +651,21 @@ tdm_error tdm_layer_unset_buffer(tdm_layer *layer); /** + * @brief Commit changes for a layer object + * @details After all change of a layer object are applied, a user commit handler + * will be called. + * @param[in] layer A layer object + * @param[in] func A user commit handler + * @param[in] user_data The user data + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error +tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data); + +tdm_error +tdm_layer_is_committing(tdm_layer *layer, unsigned int *committing); + +/** * @brief Get a displaying TDM buffer from a layer object * @details A displaying TDM buffer is a current showing buffer on screen * that is set to layer object and applied output object of a layer object. @@ -666,7 +682,7 @@ tdm_layer_get_displaying_buffer(tdm_layer *layer, tdm_error *error); * @param[in] layer A layer object * @param[in] buffer_queue A TBM surface_queue * @return #TDM_ERROR_NONE if success. Otherwise, error value. - * @see tdm_output_commit + * @see tdm_layer_commit */ tdm_error tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue); diff --git a/include/tdm_types.h b/include/tdm_types.h index 3cd8560..3b62ff5 100644 --- a/include/tdm_types.h +++ b/include/tdm_types.h @@ -166,12 +166,20 @@ typedef void (*tdm_output_vblank_handler)(tdm_output *output, unsigned int seque void *user_data); /** - * @brief The commit handler + * @brief The output commit handler * @see output_set_commit_handler() function of #tdm_func_display */ typedef void (*tdm_output_commit_handler)(tdm_output *output, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data); + +/** + * @brief The layer commit handler + */ +typedef void (*tdm_layer_commit_handler)(tdm_layer *layer, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, + void *user_data); + /** * @brief The done handler of a pp object */ diff --git a/src/tdm.c b/src/tdm.c index c6023a2..ef6e1af 100644 --- a/src/tdm.c +++ b/src/tdm.c @@ -146,10 +146,12 @@ _tdm_display_destroy_private_layer(tdm_private_layer *private_layer) static void _tdm_display_destroy_private_output(tdm_private_output *private_output) { + tdm_private_display *private_display = private_output->private_display; tdm_private_layer *l = NULL, *ll = NULL; tdm_private_capture *c = NULL, *cc = NULL; tdm_private_vblank_handler *v = NULL, *vv = NULL; - tdm_private_commit_handler *m = NULL, *mm = NULL; + tdm_private_output_commit_handler *om = NULL, *omm = NULL; + tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL; tdm_private_change_handler *h = NULL, *hh = NULL; LIST_DEL(&private_output->link); @@ -161,9 +163,19 @@ _tdm_display_destroy_private_output(tdm_private_output *private_output) free(v); } - LIST_FOR_EACH_ENTRY_SAFE(m, mm, &private_output->commit_handler_list, link) { - LIST_DEL(&m->link); - free(m); + LIST_FOR_EACH_ENTRY_SAFE(om, omm, &private_output->output_commit_handler_list, link) { + LIST_DEL(&om->link); + free(om); + } + + LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) { + LIST_DEL(&lm->link); + free(lm); + } + + LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) { + LIST_DEL(&lm->link); + free(lm); } LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list_main, link) { @@ -176,6 +188,13 @@ _tdm_display_destroy_private_output(tdm_private_output *private_output) free(h); } + if (private_output->vblank) { + /* tdm_vblank APIs is for server. it should be called in unlock status*/ + _pthread_mutex_unlock(&private_display->lock); + tdm_vblank_destroy(private_output->vblank); + _pthread_mutex_lock(&private_display->lock); + } + LIST_FOR_EACH_ENTRY_SAFE(c, cc, &private_output->capture_list, link) tdm_capture_destroy_internal(c); @@ -381,7 +400,9 @@ tdm_display_update_output(tdm_private_display *private_display, LIST_INITHEAD(&private_output->layer_list); LIST_INITHEAD(&private_output->capture_list); LIST_INITHEAD(&private_output->vblank_handler_list); - LIST_INITHEAD(&private_output->commit_handler_list); + LIST_INITHEAD(&private_output->output_commit_handler_list); + LIST_INITHEAD(&private_output->layer_commit_handler_list); + LIST_INITHEAD(&private_output->pending_commit_handler_list); LIST_INITHEAD(&private_output->change_handler_list_main); LIST_INITHEAD(&private_output->change_handler_list_sub); @@ -862,7 +883,7 @@ EXTERN tdm_display * tdm_display_init(tdm_error *error) { tdm_private_display *private_display = NULL; - const char *debug; + const char *str; tdm_error ret; double stamp1, stamp2, start; @@ -885,17 +906,21 @@ tdm_display_init(tdm_error *error) goto failed_alloc; } - debug = getenv("TDM_DEBUG_MODULE"); - if (debug) - tdm_display_enable_debug_module(debug); + str = getenv("TDM_DEBUG_MODULE"); + if (str) + tdm_display_enable_debug_module(str); + + str = getenv("TDM_DEBUG_DUMP"); + if (str) + tdm_display_enable_dump(private_display, str, NULL, NULL); - debug = getenv("TDM_DEBUG_DUMP"); - if (debug) - tdm_display_enable_dump(private_display, debug, NULL, NULL); + str = getenv("TDM_DEBUG_PATH"); + if (str) + tdm_display_enable_path(str); - debug = getenv("TDM_DEBUG_PATH"); - if (debug) - tdm_display_enable_path(debug); + str = getenv("TDM_COMMIT_PER_VBLANK"); + if (str && (strstr(str, "1"))) + tdm_display_enable_commit_per_vblank(private_display, 1); if (pthread_mutex_init(&private_display->lock, NULL)) { ret = TDM_ERROR_OPERATION_FAILED; @@ -956,6 +981,7 @@ tdm_display_init(tdm_error *error) tdm_event_loop_create_backend_source(private_display); private_display->init_count = 1; + private_display->commit_type = TDM_COMMIT_TYPE_NONE; g_private_display = private_display; @@ -1076,6 +1102,8 @@ tdm_display_enable_debug_module(const char*modules) tdm_debug_module |= TDM_DEBUG_MUTEX; else if (!strncmp(arg, "vblank", 6)) tdm_debug_module |= TDM_DEBUG_VBLANK; + else if (!strncmp(arg, "commit", 6)) + tdm_debug_module |= TDM_DEBUG_COMMIT; else return TDM_ERROR_BAD_REQUEST; @@ -1263,3 +1291,29 @@ enable_fail: return ret; } +INTERN tdm_error +tdm_display_enable_commit_per_vblank(tdm_private_display *private_display, int enable) +{ + private_display->commit_per_vblank = enable; + + if (private_display->commit_per_vblank == 1) + TDM_INFO("commit per vblank: enable (1 layer)"); + else if (private_display->commit_per_vblank == 2) + TDM_INFO("commit per vblank: enable (previous commit)"); + else if (private_display->commit_per_vblank > 0) + TDM_INFO("commit per vblank: enable (unknown)"); + else + TDM_INFO("commit per vblank: disable"); + + return TDM_ERROR_NONE; +} + +INTERN tdm_error +tdm_display_enable_fps(tdm_private_display *private_display, int enable) +{ + private_display->print_fps = enable; + + TDM_INFO("print fps: %s", (enable) ? "enable" : "disable"); + + return TDM_ERROR_NONE; +} diff --git a/src/tdm_display.c b/src/tdm_display.c index 9cfd290..9cd7c4a 100644 --- a/src/tdm_display.c +++ b/src/tdm_display.c @@ -102,6 +102,12 @@ private_output = private_layer->private_output; \ private_display = private_output->private_display +static void _tdm_layer_committed(tdm_private_layer *private_layer); +static void _tdm_layer_cb_output_commit(tdm_output *output, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, void *user_data); +static void _tdm_layer_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, void *user_data); + EXTERN tdm_error tdm_display_get_capabilities(tdm_display *dpy, tdm_display_capability *capabilities) @@ -492,6 +498,20 @@ tdm_output_get_conn_status(tdm_output *output, tdm_output_conn_status *status) return ret; } +static unsigned int +_tdm_output_used_layer_count(tdm_private_output *private_output) +{ + tdm_private_layer *private_layer = NULL; + unsigned int count = 0; + + LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) { + if (!private_layer->usable) + count++; + } + + return count; +} + static void _tdm_output_update(tdm_output *output_backend, void *user_data) { @@ -926,14 +946,20 @@ tdm_output_cb_vblank(tdm_output *output_backend, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data) { tdm_private_vblank_handler *vblank_handler = user_data; + tdm_private_vblank_handler *v = NULL, *vv = NULL; + tdm_private_output *private_output; tdm_private_display *private_display; + struct list_head clone_list; + int interval, sync; + pid_t tid = syscall(SYS_gettid); TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); TDM_RETURN_IF_FAIL(vblank_handler); - private_display = vblank_handler->private_output->private_display; + private_output = vblank_handler->private_output; + private_display = private_output->private_display; - if (vblank_handler->owner_tid != syscall(SYS_gettid)) { + if (vblank_handler->owner_tid != tid) { tdm_thread_cb_output_vblank output_vblank; tdm_error ret; @@ -951,36 +977,48 @@ tdm_output_cb_vblank(tdm_output *output_backend, unsigned int sequence, return; } - if (vblank_handler->owner_tid != syscall(SYS_gettid)) + if (vblank_handler->owner_tid != tid) TDM_NEVER_GET_HERE(); - if (vblank_handler->func) { - _pthread_mutex_unlock(&private_display->lock); - vblank_handler->func(vblank_handler->private_output, sequence, - tv_sec, tv_usec, vblank_handler->user_data); - _pthread_mutex_lock(&private_display->lock); + interval = vblank_handler->interval; + sync = vblank_handler->sync; + + LIST_INITHEAD(&clone_list); + + LIST_FOR_EACH_ENTRY_SAFE(v, vv, &private_output->vblank_handler_list, link) { + if (v->interval != interval || v->sync != sync || v->owner_tid != tid) + continue; + + LIST_DEL(&v->link); + LIST_ADD(&v->link, &clone_list); } - LIST_DEL(&vblank_handler->link); - free(vblank_handler); + _pthread_mutex_unlock(&private_display->lock); + LIST_FOR_EACH_ENTRY_SAFE(v, vv, &clone_list, link) { + if (v->func) + v->func(v->private_output, sequence, tv_sec, tv_usec, v->user_data); + LIST_DEL(&v->link); + free(v); + } + _pthread_mutex_lock(&private_display->lock); } INTERN void tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data) { - tdm_private_commit_handler *commit_handler = user_data; + tdm_private_output_commit_handler *output_commit_handler = user_data; tdm_private_display *private_display; tdm_private_output *private_output; tdm_private_layer *private_layer = NULL; TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); - TDM_RETURN_IF_FAIL(commit_handler); + TDM_RETURN_IF_FAIL(output_commit_handler); - private_output = commit_handler->private_output; + private_output = output_commit_handler->private_output; private_display = private_output->private_display; - if (commit_handler->owner_tid != syscall(SYS_gettid)) { + if (output_commit_handler->owner_tid != syscall(SYS_gettid)) { tdm_thread_cb_output_commit output_commit; tdm_error ret; @@ -998,94 +1036,103 @@ tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence, return; } - LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) { - if (!private_layer->waiting_buffer) - continue; - - if (private_layer->showing_buffer) { - _pthread_mutex_unlock(&private_display->lock); - tdm_buffer_unref_backend(private_layer->showing_buffer); - _pthread_mutex_lock(&private_display->lock); - - if (private_layer->buffer_queue) { - _pthread_mutex_unlock(&private_display->lock); - tbm_surface_queue_release(private_layer->buffer_queue, - private_layer->showing_buffer); - _pthread_mutex_lock(&private_display->lock); - } + if (private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT) { + /* In case of layer commit, the below will be handled in the layer commit callback */ + LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) { + _tdm_layer_committed(private_layer); } - - private_layer->showing_buffer = private_layer->waiting_buffer; - private_layer->waiting_buffer = NULL; - - if (tdm_debug_module & TDM_DEBUG_BUFFER) - TDM_INFO("layer(%p) waiting_buffer(%p) showing_buffer(%p)", - private_layer, private_layer->waiting_buffer, - private_layer->showing_buffer); } - if (commit_handler->func) { + if (output_commit_handler->func) { _pthread_mutex_unlock(&private_display->lock); - commit_handler->func(private_output, sequence, - tv_sec, tv_usec, commit_handler->user_data); + output_commit_handler->func(private_output, sequence, + tv_sec, tv_usec, output_commit_handler->user_data); _pthread_mutex_lock(&private_display->lock); } - LIST_DEL(&commit_handler->link); - free(commit_handler); + LIST_DEL(&output_commit_handler->link); + free(output_commit_handler); } -EXTERN tdm_error -tdm_output_wait_vblank(tdm_output *output, int interval, int sync, - tdm_output_vblank_handler func, void *user_data) +static tdm_error +_tdm_output_wait_vblank(tdm_output *output, int interval, int sync, + tdm_output_vblank_handler func, void *user_data) { tdm_func_output *func_output; - tdm_private_vblank_handler *vblank_handler; - OUTPUT_FUNC_ENTRY(); - - _pthread_mutex_lock(&private_display->lock); + tdm_private_vblank_handler *vblank_handler = NULL, *v = NULL; + unsigned int skip_request = 0; + pid_t tid = syscall(SYS_gettid); - if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) { - TDM_WRN("output(%d) dpms: %s", private_output->pipe, - tdm_dpms_str(private_output->current_dpms_value)); - _pthread_mutex_unlock(&private_display->lock); - return TDM_ERROR_DPMS_OFF; - } + OUTPUT_FUNC_ENTRY(); func_output = &private_display->func_output; if (!func_output->output_wait_vblank) { - _pthread_mutex_unlock(&private_display->lock); TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; } + if (!private_output->regist_vblank_cb) { + private_output->regist_vblank_cb = 1; + ret = func_output->output_set_vblank_handler(private_output->output_backend, + tdm_output_cb_vblank); + } + vblank_handler = calloc(1, sizeof(tdm_private_vblank_handler)); if (!vblank_handler) { TDM_ERR("failed: alloc memory"); - _pthread_mutex_unlock(&private_display->lock); return TDM_ERROR_OUT_OF_MEMORY; } + LIST_FOR_EACH_ENTRY(v, &private_output->vblank_handler_list, link) { + if (v->interval == interval && v->sync == sync && v->owner_tid == tid) { + skip_request = 1; + break; + } + } + LIST_ADD(&vblank_handler->link, &private_output->vblank_handler_list); vblank_handler->private_output = private_output; + vblank_handler->interval = interval; + vblank_handler->sync = sync; vblank_handler->func = func; vblank_handler->user_data = user_data; - vblank_handler->owner_tid = syscall(SYS_gettid); + vblank_handler->owner_tid = tid; - ret = func_output->output_wait_vblank(private_output->output_backend, interval, - sync, vblank_handler); - if (ret != TDM_ERROR_NONE) { - _pthread_mutex_unlock(&private_display->lock); - return ret; + /* If there is the previous request, we can skip to call output_wait_vblank() */ + if (!skip_request) { + ret = func_output->output_wait_vblank(private_output->output_backend, interval, + sync, vblank_handler); + TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed); } - if (!private_output->regist_vblank_cb) { - private_output->regist_vblank_cb = 1; - ret = func_output->output_set_vblank_handler(private_output->output_backend, - tdm_output_cb_vblank); + return ret; + +wait_failed: + if (vblank_handler) { + LIST_DEL(&vblank_handler->link); + free(vblank_handler); + } + return ret; +} + +EXTERN tdm_error +tdm_output_wait_vblank(tdm_output *output, int interval, int sync, + tdm_output_vblank_handler func, void *user_data) +{ + OUTPUT_FUNC_ENTRY(); + + _pthread_mutex_lock(&private_display->lock); + + if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) { + TDM_WRN("output(%d) dpms: %s", private_output->pipe, + tdm_dpms_str(private_output->current_dpms_value)); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_DPMS_OFF; } + ret = _tdm_output_wait_vblank(output, interval, sync, func, user_data); + _pthread_mutex_unlock(&private_display->lock); return ret; @@ -1096,7 +1143,7 @@ _tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, void *user_data) { tdm_func_output *func_output; - tdm_private_commit_handler *commit_handler; + tdm_private_output_commit_handler *output_commit_handler = NULL; OUTPUT_FUNC_ENTRY(); func_output = &private_display->func_output; @@ -1106,29 +1153,39 @@ _tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, return TDM_ERROR_NOT_IMPLEMENTED; } - commit_handler = calloc(1, sizeof(tdm_private_commit_handler)); - if (!commit_handler) { - TDM_ERR("failed: alloc memory"); - return TDM_ERROR_OUT_OF_MEMORY; - } - - LIST_ADD(&commit_handler->link, &private_output->commit_handler_list); - commit_handler->private_output = private_output; - commit_handler->func = func; - commit_handler->user_data = user_data; - commit_handler->owner_tid = syscall(SYS_gettid); - if (!private_output->regist_commit_cb) { private_output->regist_commit_cb = 1; ret = func_output->output_set_commit_handler(private_output->output_backend, tdm_output_cb_commit); } + output_commit_handler = calloc(1, sizeof(tdm_private_output_commit_handler)); + if (!output_commit_handler) { + TDM_ERR("failed: alloc memory"); + return TDM_ERROR_OUT_OF_MEMORY; + } + + LIST_ADD(&output_commit_handler->link, &private_output->output_commit_handler_list); + output_commit_handler->private_output = private_output; + output_commit_handler->func = func; + output_commit_handler->user_data = user_data; + output_commit_handler->owner_tid = syscall(SYS_gettid); + ret = func_output->output_commit(private_output->output_backend, sync, - commit_handler); - TDM_RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret); + output_commit_handler); + TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed); + + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("output(%d) backend commit", private_output->pipe); return ret; + +commit_failed: + if (output_commit_handler) { + LIST_DEL(&output_commit_handler->link); + free(output_commit_handler); + } + return ret; } EXTERN tdm_error @@ -1139,6 +1196,20 @@ tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, _pthread_mutex_lock(&private_display->lock); + if (private_display->commit_type == TDM_COMMIT_TYPE_NONE) + private_display->commit_type = TDM_COMMIT_TYPE_OUTPUT; + else if (private_display->commit_type == TDM_COMMIT_TYPE_LAYER) { + TDM_ERR("Can't supported. Use tdm_layer_commit"); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_BAD_REQUEST; + } + + if (private_display->commit_per_vblank) { + TDM_ERR("Use tdm_layer_commit"); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_BAD_REQUEST; + } + if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) { TDM_ERR("output(%d) dpms: %s", private_output->pipe, tdm_dpms_str(private_output->current_dpms_value)); @@ -1146,6 +1217,9 @@ tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, return TDM_ERROR_DPMS_OFF; } + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("output(%d) commit", private_output->pipe); + ret = _tdm_output_commit(output, sync, func, user_data); _pthread_mutex_unlock(&private_display->lock); @@ -1488,7 +1562,7 @@ tdm_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value) func_layer = &private_display->func_layer; if (private_layer->usable) - TDM_INFO("layer(%p) not usable", private_layer); + TDM_INFO("layer(%d) not usable", private_layer->index); private_layer->usable = 0; @@ -1686,6 +1760,7 @@ tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer) EXTERN tdm_error tdm_layer_unset_buffer(tdm_layer *layer) { + tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL; tdm_func_layer *func_layer; LAYER_FUNC_ENTRY(); @@ -1715,6 +1790,20 @@ tdm_layer_unset_buffer(tdm_layer *layer) private_layer, private_layer->showing_buffer); } + LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) { + if (lm->private_layer != private_layer) + continue; + LIST_DEL(&lm->link); + free(lm); + } + + LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) { + if (lm->private_layer != private_layer) + continue; + LIST_DEL(&lm->link); + free(lm); + } + private_layer->usable = 1; if (private_layer->usable) @@ -1734,6 +1823,343 @@ tdm_layer_unset_buffer(tdm_layer *layer) return ret; } +static void +_tdm_layer_committed(tdm_private_layer *private_layer) +{ + tdm_private_output *private_output = private_layer->private_output; + tdm_private_display *private_display = private_output->private_display; + + private_layer->committing = 0; + + if (private_display->print_fps) { + double curr = tdm_helper_get_time(); + private_layer->fps_count++; + if (private_layer->fps_stamp == 0) { + private_layer->fps_stamp = curr; + } else if ((curr - private_layer->fps_stamp) > 1.0) { + TDM_INFO("output(%d) layer(%d) fps: %d", private_output->index, private_layer->index, private_layer->fps_count - 1); + private_layer->fps_count = 1; + private_layer->fps_stamp = curr; + } + } else if (private_layer->fps_stamp != 0) { + private_layer->fps_stamp = 0; + private_layer->fps_count = 0; + } + + if (!private_layer->waiting_buffer) + return; + + if (private_layer->showing_buffer) { + _pthread_mutex_unlock(&private_display->lock); + tdm_buffer_unref_backend(private_layer->showing_buffer); + _pthread_mutex_lock(&private_display->lock); + + if (private_layer->buffer_queue) { + _pthread_mutex_unlock(&private_display->lock); + tbm_surface_queue_release(private_layer->buffer_queue, + private_layer->showing_buffer); + _pthread_mutex_lock(&private_display->lock); + } + } + + private_layer->showing_buffer = private_layer->waiting_buffer; + private_layer->waiting_buffer = NULL; + + if (tdm_debug_module & TDM_DEBUG_BUFFER) + TDM_INFO("layer(%p) waiting_buffer(%p) showing_buffer(%p)", + private_layer, private_layer->waiting_buffer, + private_layer->showing_buffer); +} + +static void +_tdm_layer_got_output_vblank(tdm_private_output *private_output, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec) +{ + tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL; + tdm_private_display *private_display; + tdm_error ret; + + private_display = private_output->private_display; + + private_output->waiting_vblank = 0; + + LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) { + _tdm_layer_committed(lm->private_layer); + + if (lm->func) { + _pthread_mutex_unlock(&private_display->lock); + lm->func(lm->private_layer, sequence, tv_sec, tv_usec, lm->user_data); + _pthread_mutex_lock(&private_display->lock); + } + + LIST_DEL(&lm->link); + free(lm); + } + + if (LIST_IS_EMPTY(&private_output->pending_commit_handler_list)) + return; + +#if 1 + ret = _tdm_output_commit(private_output, 0, _tdm_layer_cb_output_commit, NULL); + TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed); + + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("layer commit: output(%d) commit", private_output->pipe); + + private_output->waiting_vblank = 1; +#else + ret = _tdm_output_commit(private_output, 0, NULL, NULL); + TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed); + + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("layer commit: output(%d) commit", private_output->pipe); + + TDM_RETURN_IF_FAIL(private_output->vblank != NULL); + + /* tdm_vblank APIs is for server. it should be called in unlock status*/ + _pthread_mutex_unlock(&private_display->lock); + ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output); + _pthread_mutex_lock(&private_display->lock); + TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed); + private_output->waiting_vblank = 1; + + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("layer commit: output(%d) wait vblank", private_output->pipe); +#endif + + LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) { + LIST_DEL(&lm->link); + LIST_ADD(&lm->link, &private_output->layer_commit_handler_list); + } + + return; +wait_failed: + LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) { + LIST_DEL(&lm->link); + free(lm); + } + return; +} + +static void +_tdm_layer_cb_output_commit(tdm_output *output, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, void *user_data) +{ + tdm_private_layer_commit_handler *layer_commit_handler = user_data; + tdm_private_display *private_display; + tdm_private_output *private_output = output; + tdm_private_layer *private_layer; + + private_display = private_output->private_display; + + _pthread_mutex_lock(&private_display->lock); + + if (layer_commit_handler) { + tdm_private_layer_commit_handler *lm = NULL; + int found = 0; + + LIST_FOR_EACH_ENTRY(lm, &private_output->layer_commit_handler_list, link) { + if (layer_commit_handler == lm) { + found = 1; + break; + } + } + + if (found) { + private_layer = layer_commit_handler->private_layer; + + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("layer(%p) commit: output(%d) committed", private_layer, private_output->pipe); + + _tdm_layer_committed(private_layer); + + if (layer_commit_handler->func) { + _pthread_mutex_unlock(&private_display->lock); + layer_commit_handler->func(private_output, sequence, + tv_sec, tv_usec, layer_commit_handler->user_data); + _pthread_mutex_lock(&private_display->lock); + } + + LIST_DEL(&layer_commit_handler->link); + free(layer_commit_handler); + } + } else { + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("layer commit: output(%d) committed", private_output->pipe); + + _tdm_layer_got_output_vblank(private_output, sequence, tv_sec, tv_usec); + } + + _pthread_mutex_unlock(&private_display->lock); +} + +static void +_tdm_layer_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, void *user_data) +{ + tdm_private_output *private_output = user_data; + tdm_private_display *private_display; + + TDM_RETURN_IF_FAIL(private_output != NULL); + + private_display = private_output->private_display; + + _pthread_mutex_lock(&private_display->lock); + + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("layer commit: output(%d) got vblank", private_output->pipe); + + _tdm_layer_got_output_vblank(private_output, sequence, tv_sec, tv_usec); + + _pthread_mutex_unlock(&private_display->lock); +} + +static int +_tdm_layer_commit_possible(tdm_private_layer *private_layer) +{ + tdm_private_output *private_output = private_layer->private_output; + tdm_private_display *private_display = private_output->private_display; + + if (!private_display->commit_per_vblank) { + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("layer(%p) commit: commit_per_vblank false", private_layer); + return 1; + } + + if (private_display->commit_per_vblank == 1 && _tdm_output_used_layer_count(private_output) == 1) { + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("layer(%p) commit: 1 layer", private_layer); + return 1; + } + + if (private_display->commit_per_vblank == 2 && LIST_IS_EMPTY(&private_output->layer_commit_handler_list)) { + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("layer(%p) commit: non previous commit", private_layer); + return 1; + } + + return 0; +} + +static tdm_error +_tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data) +{ + tdm_private_layer_commit_handler *layer_commit_handler; + LAYER_FUNC_ENTRY(); + + layer_commit_handler = calloc(1, sizeof(tdm_private_layer_commit_handler)); + if (!layer_commit_handler) { + TDM_ERR("failed: alloc memory"); + return TDM_ERROR_OUT_OF_MEMORY; + } + + LIST_INITHEAD(&layer_commit_handler->link); + layer_commit_handler->private_layer = private_layer; + layer_commit_handler->func = func; + layer_commit_handler->user_data = user_data; + + if (_tdm_layer_commit_possible(private_layer)) { + if (private_layer->committing) + TDM_WRN("layer(%d) too many commit", private_layer->index); + else + private_layer->committing = 1; + + LIST_ADD(&layer_commit_handler->link, &private_output->layer_commit_handler_list); + ret = _tdm_output_commit(private_layer->private_output, 0, _tdm_layer_cb_output_commit, layer_commit_handler); + TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed); + + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("layer(%p) commit: output", private_layer); + } else { + if (private_layer->committing) + TDM_WRN("layer(%d) too many commit", private_layer->index); + else + private_layer->committing = 1; + + LIST_ADD(&layer_commit_handler->link, &private_output->pending_commit_handler_list); + + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("layer(%p) commit: pending", private_layer); + + if (!private_output->vblank) { + /* tdm_vblank APIs is for server. it should be called in unlock status*/ + _pthread_mutex_unlock(&private_display->lock); + private_output->vblank = tdm_vblank_create(private_display, private_output, NULL); + _pthread_mutex_lock(&private_display->lock); + TDM_GOTO_IF_FAIL(private_output->vblank != NULL, commit_failed); + } + + if (!private_output->waiting_vblank) { + /* tdm_vblank APIs is for server. it should be called in unlock status*/ + _pthread_mutex_unlock(&private_display->lock); + ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output); + _pthread_mutex_lock(&private_display->lock); + TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed); + private_output->waiting_vblank = 1; + + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("layer(%p) commit: wait vblank", private_layer); + } + } + + return ret; + +commit_failed: + if (layer_commit_handler) { + LIST_DEL(&layer_commit_handler->link); + free(layer_commit_handler); + } + return ret; +} + +EXTERN tdm_error +tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data) +{ + LAYER_FUNC_ENTRY(); + + _pthread_mutex_lock(&private_display->lock); + + if (private_display->commit_type == TDM_COMMIT_TYPE_NONE) + private_display->commit_type = TDM_COMMIT_TYPE_LAYER; + else if (private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT) { + TDM_ERR("Can't supported. Use tdm_output_commit"); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_BAD_REQUEST; + } + + if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) { + TDM_ERR("layer(%p)'s output(%d) dpms: %s", layer, private_output->pipe, + tdm_dpms_str(private_output->current_dpms_value)); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_DPMS_OFF; + } + + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("layer(%p) commit", private_layer); + + ret = _tdm_layer_commit(private_layer, func, user_data); + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} + +EXTERN tdm_error +tdm_layer_is_committing(tdm_layer *layer, unsigned int *committing) +{ + LAYER_FUNC_ENTRY(); + + TDM_RETURN_VAL_IF_FAIL(committing != NULL, TDM_ERROR_INVALID_PARAMETER); + + _pthread_mutex_lock(&private_display->lock); + + *committing = private_layer->committing; + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} + EXTERN tbm_surface_h tdm_layer_get_displaying_buffer(tdm_layer *layer, tdm_error *error) { @@ -1803,9 +2229,17 @@ _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data) TDM_INFO("layer(%p) waiting_buffer(%p)", private_layer, private_layer->waiting_buffer); - ret = _tdm_output_commit(private_layer->private_output, 0, NULL, NULL); - if (ret != TDM_ERROR_NONE) - TDM_ERR("layer(%p) _tdm_output_commit() is fail", private_layer); + if (private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT) { + ret = _tdm_output_commit(private_layer->private_output, 0, NULL, NULL); + if (ret != TDM_ERROR_NONE) + TDM_ERR("_tdm_output_commit() is fail"); + } else if (private_display->commit_type == TDM_COMMIT_TYPE_LAYER) { + ret = _tdm_layer_commit(private_layer, NULL, NULL); + if (ret != TDM_ERROR_NONE) + TDM_ERR("layer(%p) _tdm_layer_commit() is fail", private_layer); + } else { + TDM_NEVER_GET_HERE(); + } } _pthread_mutex_unlock(&private_display->lock); diff --git a/src/tdm_macro.h b/src/tdm_macro.h index 61d8658..f377fae 100644 --- a/src/tdm_macro.h +++ b/src/tdm_macro.h @@ -96,7 +96,7 @@ extern "C" { #define TDM_WARNING_IF_FAIL(cond) { \ if (!(cond)) \ - TDM_ERR("'%s' failed", #cond); \ + TDM_WRN("'%s' failed", #cond); \ } #define TDM_GOTO_IF_FAIL(cond, dst) { \ if (!(cond)) { \ diff --git a/src/tdm_monitor_server.c b/src/tdm_monitor_server.c index 55ef89b..0d18743 100644 --- a/src/tdm_monitor_server.c +++ b/src/tdm_monitor_server.c @@ -201,6 +201,46 @@ done: } static void +_tdm_monitor_server_commit_per_vblank(unsigned int pid, char *cwd, int argc, char *argv[], char *reply, int *len, tdm_display *dpy) +{ + int enable; + char *arg; + char *end; + + if (argc < 3) { + _tdm_monitor_server_usage(argv[0], reply, len); + return; + } + + arg = argv[2]; + enable = strtol(arg, &end, 10); + + tdm_display_enable_commit_per_vblank(dpy, enable); + + TDM_SNPRINTF(reply, len, "%s the commit-per-vblank\n", (enable) ? "enable" : "disable"); +} + +static void +_tdm_monitor_server_fps(unsigned int pid, char *cwd, int argc, char *argv[], char *reply, int *len, tdm_display *dpy) +{ + int enable; + char *arg; + char *end; + + if (argc < 3) { + _tdm_monitor_server_usage(argv[0], reply, len); + return; + } + + arg = argv[2]; + enable = strtol(arg, &end, 10); + + tdm_display_enable_fps(dpy, enable); + + TDM_SNPRINTF(reply, len, "%s to print fps\n", (enable) ? "enable" : "disable"); +} + +static void _tdm_monitor_server_prop(unsigned int pid, char *cwd, int argc, char *argv[], char *reply, int *len, tdm_display *dpy) { tdm_output *output; @@ -394,6 +434,18 @@ static struct { "console" }, { + "commit_per_vblank", _tdm_monitor_server_commit_per_vblank, + "enable/disable the commit per vblank", + "", + "0 or 1" + }, + { + "fps", _tdm_monitor_server_fps, + "enable/disable to print fps", + "", + "0 or 1" + }, + { "prop", _tdm_monitor_server_prop, "set the property of a output or a layer", "[,]:,", diff --git a/src/tdm_private.h b/src/tdm_private.h index 5749782..0e52605 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -80,6 +80,7 @@ enum { TDM_DEBUG_THREAD = (1 << 2), TDM_DEBUG_SERVER = (1 << 3), TDM_DEBUG_VBLANK = (1 << 4), + TDM_DEBUG_COMMIT = (1 << 5), }; extern int tdm_debug_module; @@ -111,6 +112,12 @@ enum { #define TDM_DUMP_DIR "/tmp" +typedef enum { + TDM_COMMIT_TYPE_NONE, + TDM_COMMIT_TYPE_OUTPUT, + TDM_COMMIT_TYPE_LAYER, +} tdm_commit_type; + typedef struct _tdm_private_display tdm_private_display; typedef struct _tdm_private_output tdm_private_output; typedef struct _tdm_private_layer tdm_private_layer; @@ -120,7 +127,8 @@ typedef struct _tdm_private_loop tdm_private_loop; typedef struct _tdm_private_server tdm_private_server; typedef struct _tdm_private_thread tdm_private_thread; typedef struct _tdm_private_vblank_handler tdm_private_vblank_handler; -typedef struct _tdm_private_commit_handler tdm_private_commit_handler; +typedef struct _tdm_private_output_commit_handler tdm_private_output_commit_handler; +typedef struct _tdm_private_layer_commit_handler tdm_private_layer_commit_handler; typedef struct _tdm_private_change_handler tdm_private_change_handler; struct _tdm_private_display { @@ -161,6 +169,12 @@ struct _tdm_private_display { /* output order */ tdm_output **outputs; + + /* calling a output commit per a vblank */ + int commit_per_vblank; + tdm_commit_type commit_type; + + int print_fps; }; struct _tdm_private_output { @@ -186,7 +200,13 @@ struct _tdm_private_output { struct list_head layer_list; struct list_head capture_list; struct list_head vblank_handler_list; - struct list_head commit_handler_list; + struct list_head output_commit_handler_list; + + /* for layer commit */ + struct list_head layer_commit_handler_list; + struct list_head pending_commit_handler_list; + tdm_vblank *vblank; + int waiting_vblank; /* seperate list for multi-thread*/ struct list_head change_handler_list_main; @@ -217,6 +237,10 @@ struct _tdm_private_layer { struct list_head capture_list; unsigned int usable; + unsigned int committing; + + double fps_stamp; + unsigned int fps_count; }; struct _tdm_private_pp { @@ -298,13 +322,15 @@ struct _tdm_private_vblank_handler { struct list_head link; tdm_private_output *private_output; + int interval; + int sync; tdm_output_vblank_handler func; void *user_data; pid_t owner_tid; }; -struct _tdm_private_commit_handler { +struct _tdm_private_output_commit_handler { struct list_head link; tdm_private_output *private_output; @@ -314,6 +340,14 @@ struct _tdm_private_commit_handler { pid_t owner_tid; }; +struct _tdm_private_layer_commit_handler { + struct list_head link; + + tdm_private_layer *private_layer; + tdm_layer_commit_handler func; + void *user_data; +}; + struct _tdm_private_change_handler { struct list_head link; @@ -593,6 +627,10 @@ tdm_error tdm_display_enable_path(const char *path); tdm_error tdm_display_enable_ttrace_vblank(tdm_display *dpy, tdm_output *output, int enable); +tdm_error +tdm_display_enable_commit_per_vblank(tdm_private_display *private_display, int enable); +tdm_error +tdm_display_enable_fps(tdm_private_display *private_display, int enable); void tdm_monitor_server_command(tdm_display *dpy, const char *options, char *reply, int *len); diff --git a/src/tdm_vblank.c b/src/tdm_vblank.c index 947fcf6..114e743 100644 --- a/src/tdm_vblank.c +++ b/src/tdm_vblank.c @@ -575,9 +575,6 @@ _tdm_vblank_cb_vblank_HW(tdm_output *output, unsigned int sequence, VWR("couldn't update sw timer"); } - if (private_vblank->last_seq >= wait_info->target_seq) - TDM_ERR("last_seq(%u) target_seq(%u)", private_vblank->last_seq, wait_info->target_seq); - /* tv_sec & tv_usec shouldn't be zero. But sometimes they are zero in some hardware. * We need to prohibit that last_time becomes zero because "last_time == 0" means * that a tdm_vblank object is just created and doesn't have the first vblank event. @@ -819,7 +816,7 @@ tdm_vblank_wait(tdm_vblank *vblank, unsigned int req_sec, unsigned int req_usec, TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER); if (private_vblank->owner_tid != syscall(SYS_gettid)) { - TDM_ERR("SHOULD be called in the owner thread"); + TDM_ERR("SHOULD be called in the owner thread(%d)", (int)private_vblank->owner_tid); return TDM_ERROR_BAD_REQUEST; } diff --git a/tools/tdm_test_server.c b/tools/tdm_test_server.c index 1b3854e..cfd6a02 100644 --- a/tools/tdm_test_server.c +++ b/tools/tdm_test_server.c @@ -819,7 +819,7 @@ exit_test(int sig) LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) { tdm_layer_unset_buffer(l->layer); } - tdm_output_commit(o->output, 0, NULL, NULL); + tdm_layer_commit(l->layer, NULL, NULL); } LIST_FOR_EACH_ENTRY_SAFE(p, pp, &data->pp_list, link) { @@ -994,7 +994,7 @@ layer_get_buffer(tdm_test_server_layer *l) } static void -layer_cb_commit(tdm_output *output, unsigned int sequence, +layer_cb_commit(tdm_layer *layer, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data) { @@ -1038,9 +1038,9 @@ layer_show_buffer(tdm_test_server_layer *l, tbm_surface_h b) tdm_buffer_add_release_handler(b, layer_cb_buffer_release, NULL); if (data->do_vblank) - ret = tdm_output_commit(l->o->output, 0, layer_cb_commit, l); + ret = tdm_layer_commit(l->layer, layer_cb_commit, l); else - ret = tdm_output_commit(l->o->output, 0, NULL, NULL); + ret = tdm_layer_commit(l->layer, NULL, NULL); TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE); printf("show:\tl(%p) b(%p)\n", l, b); -- 2.7.4 From b7496cae4a1ccb6e86fe3586c26784a547f385d5 Mon Sep 17 00:00:00 2001 From: Anamika Singh Date: Tue, 10 Jan 2017 18:28:12 +0530 Subject: [PATCH 05/16] Add return value check. Change-Id: If2bebc87b5ba75c286bae6c7215055938d506c7b Signed-off-by: Anamika Singh Signed-off-by: Boram Park --- src/tdm_display.c | 2 ++ src/tdm_helper.c | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/tdm_display.c b/src/tdm_display.c index 9cd7c4a..a8fa694 100644 --- a/src/tdm_display.c +++ b/src/tdm_display.c @@ -1157,6 +1157,7 @@ _tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, private_output->regist_commit_cb = 1; ret = func_output->output_set_commit_handler(private_output->output_backend, tdm_output_cb_commit); + TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed); } output_commit_handler = calloc(1, sizeof(tdm_private_output_commit_handler)); @@ -1376,6 +1377,7 @@ tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value) private_output->regist_dpms_cb = 1; ret = func_output->output_set_dpms_handler(private_output->output_backend, tdm_output_cb_dpms, private_output); + TDM_RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret); } } diff --git a/src/tdm_helper.c b/src/tdm_helper.c index a72f3eb..87df714 100644 --- a/src/tdm_helper.c +++ b/src/tdm_helper.c @@ -534,7 +534,12 @@ tdm_helper_get_fd(const char *env) TDM_INFO("%s: fd(%d) newfd(%d)", env, fd, newfd); - fcntl(newfd, F_SETFD, flags | FD_CLOEXEC); + ret = fcntl(newfd, F_SETFD, flags | FD_CLOEXEC); + if (ret == -1) { + TDM_ERR("fcntl failed: %m"); + close(newfd); + return -1; + } return newfd; } -- 2.7.4 From 8a27a8b8c3a3c11caab2b0588e8abcd64229a632 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Thu, 12 Jan 2017 14:03:05 +0900 Subject: [PATCH 06/16] packaging version up to 1.6.0 Change-Id: I1662dbb355ac039eacd612efad423c3f2ef58698 --- configure.ac | 2 +- doc/tdm_doc.h | 2 +- packaging/libtdm.spec | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 1ed0aac..ddd144a 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ AC_PREREQ([2.60]) m4_define([tdm_major_version], [1]) -m4_define([tdm_minor_version], [5]) +m4_define([tdm_minor_version], [6]) m4_define([tdm_micro_version], [0]) m4_define([tdm_version], [tdm_major_version.tdm_minor_version.tdm_micro_version]) diff --git a/doc/tdm_doc.h b/doc/tdm_doc.h index 02e3024..35d9ee9 100644 --- a/doc/tdm_doc.h +++ b/doc/tdm_doc.h @@ -39,7 +39,7 @@ /** * @mainpage TDM * @author Boram Park, boram1288.park@samsung.com - * @version 1.5.0 + * @version 1.6.0 * @par Introduction * TDM stands for Tizen Display Manager. It's the display HAL layer for tizen * display server. It offers the frontend APIs(@ref tdm.h) for a frontend user diff --git a/packaging/libtdm.spec b/packaging/libtdm.spec index 2409923..c757a49 100644 --- a/packaging/libtdm.spec +++ b/packaging/libtdm.spec @@ -1,7 +1,7 @@ %bcond_with utest Name: libtdm -Version: 1.5.3 +Version: 1.6.0 Release: 0 Summary: User Library of Tizen Display Manager Group: Development/Libraries -- 2.7.4 From 825a194a3b39cb5094ab7242814c12718bfd140f Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 16 Jan 2017 15:33:28 +0900 Subject: [PATCH 07/16] unlock mutex before return Change-Id: I7f31a7a6f2eded7ba07af8b6cb33e5ca68e6c592 --- src/tdm_display.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/tdm_display.c b/src/tdm_display.c index a8fa694..f3a4e05 100644 --- a/src/tdm_display.c +++ b/src/tdm_display.c @@ -1377,7 +1377,11 @@ tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value) private_output->regist_dpms_cb = 1; ret = func_output->output_set_dpms_handler(private_output->output_backend, tdm_output_cb_dpms, private_output); - TDM_RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret); + if (ret != TDM_ERROR_NONE) { + _pthread_mutex_unlock(&private_display->lock); + TDM_ERR("Can't set the dpms handler!!"); + return ret; + } } } -- 2.7.4 From 3e229010502a87238f7da196e7847095366f928c Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 16 Jan 2017 15:43:11 +0900 Subject: [PATCH 08/16] enhance the debugging information Change-Id: I637f7ff180eceefa821ef66e45513ea46f62df09 --- src/tdm.c | 2 ++ src/tdm_private.h | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/src/tdm.c b/src/tdm.c index ef6e1af..69a81c2 100644 --- a/src/tdm.c +++ b/src/tdm.c @@ -44,6 +44,8 @@ pthread_mutex_t tdm_mutex_check_lock = PTHREAD_MUTEX_INITIALIZER; int tdm_mutex_locked; +const char *tdm_mutex_lock_func; +int tdm_mutex_lock_line; static tdm_private_layer * _tdm_display_find_private_layer(tdm_private_output *private_output, diff --git a/src/tdm_private.h b/src/tdm_private.h index 0e52605..badde95 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -558,6 +558,8 @@ tdm_helper_get_time(void); extern pthread_mutex_t tdm_mutex_check_lock; extern int tdm_mutex_locked; +extern const char *tdm_mutex_lock_func; +extern int tdm_mutex_lock_line; extern int tdm_dump_enable; extern char *tdm_debug_dump_dir; @@ -567,6 +569,8 @@ extern char *tdm_debug_dump_dir; TDM_INFO("mutex unlock"); \ pthread_mutex_lock(&tdm_mutex_check_lock); \ tdm_mutex_locked = 0; \ + tdm_mutex_lock_func = NULL; \ + tdm_mutex_lock_line = 0; \ pthread_mutex_unlock(&tdm_mutex_check_lock); \ pthread_mutex_unlock(l); \ } while (0) @@ -586,6 +590,8 @@ extern char *tdm_debug_dump_dir; else { \ pthread_mutex_lock(&tdm_mutex_check_lock); \ tdm_mutex_locked = 1; \ + tdm_mutex_lock_func = __FUNCTION__; \ + tdm_mutex_lock_line = __LINE__; \ pthread_mutex_unlock(&tdm_mutex_check_lock); \ } \ } while (0) @@ -597,6 +603,8 @@ extern char *tdm_debug_dump_dir; pthread_mutex_lock(l); \ pthread_mutex_lock(&tdm_mutex_check_lock); \ tdm_mutex_locked = 1; \ + tdm_mutex_lock_func = __FUNCTION__; \ + tdm_mutex_lock_line = __LINE__; \ pthread_mutex_unlock(&tdm_mutex_check_lock); \ } while (0) #endif //TDM_CONFIG_MUTEX_TIMEOUT -- 2.7.4 From ed64f90f6be233537de2fcd3b957668373a61a49 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 16 Jan 2017 21:35:44 +0900 Subject: [PATCH 09/16] package version up to 1.6.1 Change-Id: I20a1eb1fc3fe4bfc07b7c58fed36be848b39b33e --- packaging/libtdm.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libtdm.spec b/packaging/libtdm.spec index c757a49..cd5dd5a 100644 --- a/packaging/libtdm.spec +++ b/packaging/libtdm.spec @@ -1,7 +1,7 @@ %bcond_with utest Name: libtdm -Version: 1.6.0 +Version: 1.6.1 Release: 0 Summary: User Library of Tizen Display Manager Group: Development/Libraries -- 2.7.4 From 41fb6132b55a38e0418d08e8cdaa93d13fcd8649 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Tue, 17 Jan 2017 20:51:31 +0900 Subject: [PATCH 10/16] use vblank instead of the output commit handler in case of tdm_layer_commit Change-Id: Ib2a29cc331b8243922d43325265891119c809510 --- src/tdm_display.c | 236 +++++++++++++++++++++++++----------------------------- src/tdm_private.h | 6 ++ src/tdm_vblank.c | 28 ++++++- 3 files changed, 143 insertions(+), 127 deletions(-) diff --git a/src/tdm_display.c b/src/tdm_display.c index f3a4e05..4a317b9 100644 --- a/src/tdm_display.c +++ b/src/tdm_display.c @@ -103,8 +103,6 @@ private_display = private_output->private_display static void _tdm_layer_committed(tdm_private_layer *private_layer); -static void _tdm_layer_cb_output_commit(tdm_output *output, unsigned int sequence, - unsigned int tv_sec, unsigned int tv_usec, void *user_data); static void _tdm_layer_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data); @@ -990,7 +988,7 @@ tdm_output_cb_vblank(tdm_output *output_backend, unsigned int sequence, continue; LIST_DEL(&v->link); - LIST_ADD(&v->link, &clone_list); + LIST_ADDTAIL(&v->link, &clone_list); } _pthread_mutex_unlock(&private_display->lock); @@ -1013,7 +1011,9 @@ tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence, tdm_private_layer *private_layer = NULL; TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); - TDM_RETURN_IF_FAIL(output_commit_handler); + + if (!output_commit_handler) + return; private_output = output_commit_handler->private_output; private_display = private_output->private_display; @@ -1054,9 +1054,14 @@ tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence, free(output_commit_handler); } +/* add_front: To distinguish between the user vblank handlers and the layer + * commit vblank handlers. The layer commit handlers will be called + * before calling the user vblank handlers. + */ static tdm_error _tdm_output_wait_vblank(tdm_output *output, int interval, int sync, - tdm_output_vblank_handler func, void *user_data) + tdm_output_vblank_handler func, void *user_data, + unsigned int add_front) { tdm_func_output *func_output; tdm_private_vblank_handler *vblank_handler = NULL, *v = NULL; @@ -1067,6 +1072,10 @@ _tdm_output_wait_vblank(tdm_output *output, int interval, int sync, func_output = &private_display->func_output; + /* interval SHOULD be at least 1 */ + if (interval <= 0) + interval = 1; + if (!func_output->output_wait_vblank) { TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; @@ -1091,7 +1100,11 @@ _tdm_output_wait_vblank(tdm_output *output, int interval, int sync, } } - LIST_ADD(&vblank_handler->link, &private_output->vblank_handler_list); + if (add_front) + LIST_ADD(&vblank_handler->link, &private_output->vblank_handler_list); + else + LIST_ADDTAIL(&vblank_handler->link, &private_output->vblank_handler_list); + vblank_handler->private_output = private_output; vblank_handler->interval = interval; vblank_handler->sync = sync; @@ -1131,7 +1144,29 @@ tdm_output_wait_vblank(tdm_output *output, int interval, int sync, return TDM_ERROR_DPMS_OFF; } - ret = _tdm_output_wait_vblank(output, interval, sync, func, user_data); + ret = _tdm_output_wait_vblank(output, interval, sync, func, user_data, 0); + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} + +EXTERN tdm_error +tdm_output_wait_vblank_add_front(tdm_output *output, int interval, int sync, + tdm_output_vblank_handler func, void *user_data) +{ + OUTPUT_FUNC_ENTRY(); + + _pthread_mutex_lock(&private_display->lock); + + if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) { + TDM_WRN("output(%d) dpms: %s", private_output->pipe, + tdm_dpms_str(private_output->current_dpms_value)); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_DPMS_OFF; + } + + ret = _tdm_output_wait_vblank(output, interval, sync, func, user_data, 1); _pthread_mutex_unlock(&private_display->lock); @@ -1153,24 +1188,26 @@ _tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, return TDM_ERROR_NOT_IMPLEMENTED; } - if (!private_output->regist_commit_cb) { - private_output->regist_commit_cb = 1; - ret = func_output->output_set_commit_handler(private_output->output_backend, - tdm_output_cb_commit); - TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed); - } + if (func) { + if (!private_output->regist_commit_cb) { + private_output->regist_commit_cb = 1; + ret = func_output->output_set_commit_handler(private_output->output_backend, + tdm_output_cb_commit); + TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed); + } - output_commit_handler = calloc(1, sizeof(tdm_private_output_commit_handler)); - if (!output_commit_handler) { - TDM_ERR("failed: alloc memory"); - return TDM_ERROR_OUT_OF_MEMORY; - } + output_commit_handler = calloc(1, sizeof(tdm_private_output_commit_handler)); + if (!output_commit_handler) { + TDM_ERR("failed: alloc memory"); + return TDM_ERROR_OUT_OF_MEMORY; + } - LIST_ADD(&output_commit_handler->link, &private_output->output_commit_handler_list); - output_commit_handler->private_output = private_output; - output_commit_handler->func = func; - output_commit_handler->user_data = user_data; - output_commit_handler->owner_tid = syscall(SYS_gettid); + LIST_ADD(&output_commit_handler->link, &private_output->output_commit_handler_list); + output_commit_handler->private_output = private_output; + output_commit_handler->func = func; + output_commit_handler->user_data = user_data; + output_commit_handler->owner_tid = syscall(SYS_gettid); + } ret = func_output->output_commit(private_output->output_backend, sync, output_commit_handler); @@ -1883,45 +1920,47 @@ _tdm_layer_got_output_vblank(tdm_private_output *private_output, unsigned int se { tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL; tdm_private_display *private_display; + struct list_head clone_list, pending_clone_list; tdm_error ret; private_display = private_output->private_display; private_output->waiting_vblank = 0; + LIST_INITHEAD(&clone_list); + LIST_INITHEAD(&pending_clone_list); + LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) { - _tdm_layer_committed(lm->private_layer); + LIST_DEL(&lm->link); + LIST_ADDTAIL(&lm->link, &clone_list); + } - if (lm->func) { - _pthread_mutex_unlock(&private_display->lock); - lm->func(lm->private_layer, sequence, tv_sec, tv_usec, lm->user_data); - _pthread_mutex_lock(&private_display->lock); - } + LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) { + LIST_DEL(&lm->link); + LIST_ADDTAIL(&lm->link, &pending_clone_list); + } + LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &clone_list, link) { + _tdm_layer_committed(lm->private_layer); + _pthread_mutex_unlock(&private_display->lock); + if (lm->func) + lm->func(lm->private_layer, sequence, tv_sec, tv_usec, lm->user_data); + _pthread_mutex_lock(&private_display->lock); LIST_DEL(&lm->link); free(lm); } - if (LIST_IS_EMPTY(&private_output->pending_commit_handler_list)) + if (LIST_IS_EMPTY(&pending_clone_list)) return; -#if 1 - ret = _tdm_output_commit(private_output, 0, _tdm_layer_cb_output_commit, NULL); - TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed); - - if (tdm_debug_module & TDM_DEBUG_COMMIT) - TDM_INFO("layer commit: output(%d) commit", private_output->pipe); + TDM_GOTO_IF_FAIL(private_output->vblank != NULL, wait_failed); - private_output->waiting_vblank = 1; -#else ret = _tdm_output_commit(private_output, 0, NULL, NULL); TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed); if (tdm_debug_module & TDM_DEBUG_COMMIT) TDM_INFO("layer commit: output(%d) commit", private_output->pipe); - TDM_RETURN_IF_FAIL(private_output->vblank != NULL); - /* tdm_vblank APIs is for server. it should be called in unlock status*/ _pthread_mutex_unlock(&private_display->lock); ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output); @@ -1931,16 +1970,15 @@ _tdm_layer_got_output_vblank(tdm_private_output *private_output, unsigned int se if (tdm_debug_module & TDM_DEBUG_COMMIT) TDM_INFO("layer commit: output(%d) wait vblank", private_output->pipe); -#endif - LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) { + LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &pending_clone_list, link) { LIST_DEL(&lm->link); - LIST_ADD(&lm->link, &private_output->layer_commit_handler_list); + LIST_ADDTAIL(&lm->link, &private_output->layer_commit_handler_list); } return; wait_failed: - LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) { + LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &pending_clone_list, link) { LIST_DEL(&lm->link); free(lm); } @@ -1948,58 +1986,6 @@ wait_failed: } static void -_tdm_layer_cb_output_commit(tdm_output *output, unsigned int sequence, - unsigned int tv_sec, unsigned int tv_usec, void *user_data) -{ - tdm_private_layer_commit_handler *layer_commit_handler = user_data; - tdm_private_display *private_display; - tdm_private_output *private_output = output; - tdm_private_layer *private_layer; - - private_display = private_output->private_display; - - _pthread_mutex_lock(&private_display->lock); - - if (layer_commit_handler) { - tdm_private_layer_commit_handler *lm = NULL; - int found = 0; - - LIST_FOR_EACH_ENTRY(lm, &private_output->layer_commit_handler_list, link) { - if (layer_commit_handler == lm) { - found = 1; - break; - } - } - - if (found) { - private_layer = layer_commit_handler->private_layer; - - if (tdm_debug_module & TDM_DEBUG_COMMIT) - TDM_INFO("layer(%p) commit: output(%d) committed", private_layer, private_output->pipe); - - _tdm_layer_committed(private_layer); - - if (layer_commit_handler->func) { - _pthread_mutex_unlock(&private_display->lock); - layer_commit_handler->func(private_output, sequence, - tv_sec, tv_usec, layer_commit_handler->user_data); - _pthread_mutex_lock(&private_display->lock); - } - - LIST_DEL(&layer_commit_handler->link); - free(layer_commit_handler); - } - } else { - if (tdm_debug_module & TDM_DEBUG_COMMIT) - TDM_INFO("layer commit: output(%d) committed", private_output->pipe); - - _tdm_layer_got_output_vblank(private_output, sequence, tv_sec, tv_usec); - } - - _pthread_mutex_unlock(&private_display->lock); -} - -static void _tdm_layer_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data) { @@ -2050,9 +2036,14 @@ _tdm_layer_commit_possible(tdm_private_layer *private_layer) static tdm_error _tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data) { - tdm_private_layer_commit_handler *layer_commit_handler; + tdm_private_layer_commit_handler *layer_commit_handler = NULL; LAYER_FUNC_ENTRY(); + if (private_layer->committing) + TDM_WRN("layer(%d) too many commit", private_layer->index); + else + private_layer->committing = 1; + layer_commit_handler = calloc(1, sizeof(tdm_private_layer_commit_handler)); if (!layer_commit_handler) { TDM_ERR("failed: alloc memory"); @@ -2065,47 +2056,42 @@ _tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_da layer_commit_handler->user_data = user_data; if (_tdm_layer_commit_possible(private_layer)) { - if (private_layer->committing) - TDM_WRN("layer(%d) too many commit", private_layer->index); - else - private_layer->committing = 1; - + /* add to layer_commit_handler_list */ LIST_ADD(&layer_commit_handler->link, &private_output->layer_commit_handler_list); - ret = _tdm_output_commit(private_layer->private_output, 0, _tdm_layer_cb_output_commit, layer_commit_handler); + + ret = _tdm_output_commit(private_layer->private_output, 0, NULL, NULL); TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed); if (tdm_debug_module & TDM_DEBUG_COMMIT) TDM_INFO("layer(%p) commit: output", private_layer); } else { - if (private_layer->committing) - TDM_WRN("layer(%d) too many commit", private_layer->index); - else - private_layer->committing = 1; - + /* add to pending_commit_handler_list. It will be commited when a vblank occurs */ LIST_ADD(&layer_commit_handler->link, &private_output->pending_commit_handler_list); if (tdm_debug_module & TDM_DEBUG_COMMIT) TDM_INFO("layer(%p) commit: pending", private_layer); + } - if (!private_output->vblank) { - /* tdm_vblank APIs is for server. it should be called in unlock status*/ - _pthread_mutex_unlock(&private_display->lock); - private_output->vblank = tdm_vblank_create(private_display, private_output, NULL); - _pthread_mutex_lock(&private_display->lock); - TDM_GOTO_IF_FAIL(private_output->vblank != NULL, commit_failed); - } + if (!private_output->vblank) { + /* tdm_vblank APIs is for server. it should be called in unlock status*/ + _pthread_mutex_unlock(&private_display->lock); + private_output->vblank = tdm_vblank_create(private_display, private_output, NULL); + _pthread_mutex_lock(&private_display->lock); + TDM_GOTO_IF_FAIL(private_output->vblank != NULL, commit_failed); - if (!private_output->waiting_vblank) { - /* tdm_vblank APIs is for server. it should be called in unlock status*/ - _pthread_mutex_unlock(&private_display->lock); - ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output); - _pthread_mutex_lock(&private_display->lock); - TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed); - private_output->waiting_vblank = 1; + tdm_vblank_set_add_front(private_output->vblank, 1); + } - if (tdm_debug_module & TDM_DEBUG_COMMIT) - TDM_INFO("layer(%p) commit: wait vblank", private_layer); - } + if (!private_output->waiting_vblank) { + /* tdm_vblank APIs is for server. it should be called in unlock status*/ + _pthread_mutex_unlock(&private_display->lock); + ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output); + _pthread_mutex_lock(&private_display->lock); + TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed); + private_output->waiting_vblank = 1; + + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("layer(%p) commit: wait vblank", private_layer); } return ret; diff --git a/src/tdm_private.h b/src/tdm_private.h index badde95..0d4cfda 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -406,6 +406,10 @@ tdm_output_cb_status(tdm_output *output_backend, tdm_output_conn_status status, void tdm_output_cb_dpms(tdm_output *output_backend, tdm_output_dpms dpms, 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); + void tdm_pp_cb_done(tdm_pp *pp_backend, tbm_surface_h src, tbm_surface_h dst, void *user_data); @@ -414,6 +418,8 @@ tdm_capture_cb_done(tdm_capture *capture_backend, tbm_surface_h buffer, void *user_data); tdm_error tdm_vblank_cb_vblank_SW(tdm_vblank *vblank, double vblank_stamp); +tdm_error +tdm_vblank_set_add_front(tdm_vblank *vblank, unsigned int add_front); void tdm_output_call_change_handler_internal(tdm_private_output *private_output, diff --git a/src/tdm_vblank.c b/src/tdm_vblank.c index 114e743..8e3f7db 100644 --- a/src/tdm_vblank.c +++ b/src/tdm_vblank.c @@ -101,6 +101,8 @@ typedef struct _tdm_private_vblank { unsigned int last_seq; double last_time; + unsigned int add_front; + /* for HW */ double HW_vblank_gap; struct list_head HW_wait_list; @@ -652,8 +654,12 @@ _tdm_vblank_wait_HW(tdm_vblank_wait_info *wait_info) skip, hw_interval, wait_info->target_seq); } - ret = tdm_output_wait_vblank(private_vblank->output, hw_interval, 0, - _tdm_vblank_cb_vblank_HW, wait_info); + 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); + else + ret = tdm_output_wait_vblank(private_vblank->output, hw_interval, 0, + _tdm_vblank_cb_vblank_HW, wait_info); if (ret != TDM_ERROR_NONE) { LIST_DEL(&wait_info->link); @@ -936,3 +942,21 @@ tdm_vblank_wait_seq(tdm_vblank *vblank, unsigned int req_sec, unsigned int req_u return tdm_vblank_wait(vblank, req_sec, req_usec, interval, func, user_data); } + +INTERN tdm_error +tdm_vblank_set_add_front(tdm_vblank *vblank, unsigned int add_front) +{ + tdm_private_vblank *private_vblank = vblank; + + TDM_RETURN_VAL_IF_FAIL(private_vblank != NULL, TDM_ERROR_INVALID_PARAMETER); + + TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED); + + if (private_vblank->add_front == add_front) + return TDM_ERROR_NONE; + + private_vblank->add_front = add_front; + + return TDM_ERROR_NONE; +} + -- 2.7.4 From 7517fcf25f737eae2c0e0afb7e7dab42e7e6e92e Mon Sep 17 00:00:00 2001 From: Boram Park Date: Wed, 18 Jan 2017 21:25:12 +0900 Subject: [PATCH 11/16] package version up to 1.6.2 Change-Id: Ib975943b530c3e159a049aa8db68f8c8f3ae2c96 --- packaging/libtdm.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libtdm.spec b/packaging/libtdm.spec index cd5dd5a..2a9f0ea 100644 --- a/packaging/libtdm.spec +++ b/packaging/libtdm.spec @@ -1,7 +1,7 @@ %bcond_with utest Name: libtdm -Version: 1.6.1 +Version: 1.6.2 Release: 0 Summary: User Library of Tizen Display Manager Group: Development/Libraries -- 2.7.4 From 5007f0fc0b17adbed88c04fb054e5d8379ed4428 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Wed, 1 Feb 2017 21:07:02 +0900 Subject: [PATCH 12/16] vblank: use mutex to protect the vblank lists for multi-thread Change-Id: I332407aeb258b7b51165db87bfa47405d3c82efa --- src/tdm_vblank.c | 65 +++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 22 deletions(-) diff --git a/src/tdm_vblank.c b/src/tdm_vblank.c index 8e3f7db..0e3c1aa 100644 --- a/src/tdm_vblank.c +++ b/src/tdm_vblank.c @@ -80,7 +80,7 @@ typedef enum { typedef struct _tdm_vblank_wait_info tdm_vblank_wait_info; typedef struct _tdm_private_vblank { - struct list_head link; + struct list_head valid_link; double stamp; pid_t owner_tid; @@ -131,8 +131,11 @@ struct _tdm_vblank_wait_info { unsigned int target_seq; }; -static pthread_mutex_t vblank_list_lock; -static struct list_head vblank_list; +/* valid_vblank_list and valid_wait_list should be protected by valid_list_lock because + * tdm_vblank can be used in multi-thread. + */ +static pthread_mutex_t valid_list_lock; +static struct list_head valid_vblank_list; static struct list_head valid_wait_list; static unsigned int vblank_list_inited; static double stamp = 0; @@ -153,6 +156,22 @@ _print_list(struct list_head *list) } #endif +static void +_tdm_vblank_valid_list_add(struct list_head *valid_link, struct list_head *valid_list) +{ + pthread_mutex_lock(&valid_list_lock); + LIST_ADDTAIL(valid_link, valid_list); + pthread_mutex_unlock(&valid_list_lock); +} + +static void +_tdm_vblank_valid_list_del(struct list_head *valid_link) +{ + pthread_mutex_lock(&valid_list_lock); + LIST_DEL(valid_link); + pthread_mutex_unlock(&valid_list_lock); +} + static inline tdm_private_vblank* _tdm_vblank_find(double vblank_stamp) { @@ -161,14 +180,14 @@ _tdm_vblank_find(double vblank_stamp) if (!vblank_stamp) return 0; - pthread_mutex_lock(&vblank_list_lock); - LIST_FOR_EACH_ENTRY(v, &vblank_list, link) { + pthread_mutex_lock(&valid_list_lock); + LIST_FOR_EACH_ENTRY(v, &valid_vblank_list, valid_link) { if (v->stamp == vblank_stamp) { - pthread_mutex_unlock(&vblank_list_lock); + pthread_mutex_unlock(&valid_list_lock); return v; } } - pthread_mutex_unlock(&vblank_list_lock); + pthread_mutex_unlock(&valid_list_lock); return 0; } @@ -181,10 +200,14 @@ _tdm_vblank_check_valid_wait(tdm_vblank_wait_info *wait_info) if (!wait_info) return 0; + pthread_mutex_lock(&valid_list_lock); LIST_FOR_EACH_ENTRY(w, &valid_wait_list, valid_link) { - if (w->stamp == wait_info->stamp) + if (w->stamp == wait_info->stamp) { + pthread_mutex_unlock(&valid_list_lock); return 1; + } } + pthread_mutex_unlock(&valid_list_lock); return 0; } @@ -257,7 +280,7 @@ _tdm_vblank_free_HW_wait(tdm_private_vblank *private_vblank, tdm_error error, un LIST_FOR_EACH_ENTRY_SAFE(w, ww, &private_vblank->HW_wait_list, link) { LIST_DEL(&w->link); - LIST_DEL(&w->valid_link); + _tdm_vblank_valid_list_del(&w->valid_link); if (call_cb && w->func) w->func(private_vblank, error, 0, 0, 0, w->user_data); @@ -313,13 +336,13 @@ tdm_vblank_create(tdm_display *dpy, tdm_output *output, tdm_error *error) *error = TDM_ERROR_NONE; if (!vblank_list_inited) { - if (pthread_mutex_init(&vblank_list_lock, NULL)) { + if (pthread_mutex_init(&valid_list_lock, NULL)) { TDM_ERR("mutex init failed: %m"); if (error) *error = TDM_ERROR_OPERATION_FAILED; return NULL; } - LIST_INITHEAD(&vblank_list); + LIST_INITHEAD(&valid_vblank_list); LIST_INITHEAD(&valid_wait_list); vblank_list_inited = 1; } @@ -358,9 +381,7 @@ tdm_vblank_create(tdm_display *dpy, tdm_output *output, tdm_error *error) LIST_INITHEAD(&private_vblank->HW_wait_list); LIST_INITHEAD(&private_vblank->SW_wait_list); - pthread_mutex_lock(&vblank_list_lock); - LIST_ADD(&private_vblank->link, &vblank_list); - pthread_mutex_unlock(&vblank_list_lock); + _tdm_vblank_valid_list_add(&private_vblank->valid_link, &valid_vblank_list); if (tdm_debug_module & TDM_DEBUG_VBLANK) VIN("created. vrefresh(%d) dpms(%d)", @@ -378,9 +399,7 @@ tdm_vblank_destroy(tdm_vblank *vblank) if (!private_vblank) return; - pthread_mutex_lock(&vblank_list_lock); - LIST_DEL(&private_vblank->link); - pthread_mutex_unlock(&vblank_list_lock); + _tdm_vblank_valid_list_del(&private_vblank->valid_link); if (private_vblank->SW_timer) { tdm_display_lock(private_vblank->dpy); @@ -395,7 +414,7 @@ tdm_vblank_destroy(tdm_vblank *vblank) LIST_FOR_EACH_ENTRY_SAFE(w, ww, &private_vblank->SW_wait_list, link) { LIST_DEL(&w->link); - LIST_DEL(&w->valid_link); + _tdm_vblank_valid_list_del(&w->valid_link); free(w); } @@ -599,7 +618,7 @@ _tdm_vblank_cb_vblank_HW(tdm_output *output, unsigned int sequence, tv_sec, tv_usec, wait_info->user_data); LIST_DEL(&wait_info->link); - LIST_DEL(&wait_info->valid_link); + _tdm_vblank_valid_list_del(&wait_info->valid_link); free(wait_info); } @@ -737,7 +756,7 @@ tdm_vblank_cb_vblank_SW(tdm_vblank *vblank, double vblank_stamp) break; LIST_DEL(&w->link); - LIST_DEL(&w->valid_link); + _tdm_vblank_valid_list_del(&w->valid_link); if (w->func) { tdm_display_unlock(private_vblank->dpy); @@ -845,7 +864,9 @@ tdm_vblank_wait(tdm_vblank *vblank, unsigned int req_sec, unsigned int req_usec, } LIST_INITHEAD(&wait_info->link); - LIST_ADDTAIL(&wait_info->valid_link, &valid_wait_list); + + _tdm_vblank_valid_list_add(&wait_info->valid_link, &valid_wait_list); + wait_info->stamp = ++stamp; wait_info->req_time = TDM_TIME(req_sec, req_usec); wait_info->interval = interval; @@ -884,7 +905,7 @@ tdm_vblank_wait(tdm_vblank *vblank, unsigned int req_sec, unsigned int req_usec, if (ret != TDM_ERROR_NONE) { LIST_DEL(&wait_info->link); - LIST_DEL(&wait_info->valid_link); + _tdm_vblank_valid_list_del(&wait_info->valid_link); free(wait_info); return ret; } -- 2.7.4 From 951cfca2138b9bf33561685ef518cb210f6b8b6c Mon Sep 17 00:00:00 2001 From: Boram Park Date: Thu, 2 Feb 2017 10:31:54 +0900 Subject: [PATCH 13/16] commit: add function to check whether commit-per-vblank is enabled Change-Id: Ib5b58f06c4fe11d81c0cfc61343e0b9ea676c6cb --- include/tdm_helper.h | 8 ++++++++ src/tdm.c | 20 +++++++++++++------- src/tdm_helper.c | 13 +++++++++++++ 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/include/tdm_helper.h b/include/tdm_helper.h index ba94a66..c80057d 100644 --- a/include/tdm_helper.h +++ b/include/tdm_helper.h @@ -209,6 +209,14 @@ tdm_helper_capture_output(tdm_output *output, tbm_surface_h dst_buffer, void tdm_helper_get_display_information(tdm_display *dpy, char *reply, int *len); +/** + * @brief Get whether the commit-per-vblank functionality is enabled or not. + * @param[in] dpy A display object + * @return 1 if enabled. Otherwise, 0. + */ +int +tdm_helper_commit_per_vblank_enabled(tdm_display *dpy); + #ifdef __cplusplus } #endif diff --git a/src/tdm.c b/src/tdm.c index 69a81c2..041d4c2 100644 --- a/src/tdm.c +++ b/src/tdm.c @@ -921,8 +921,12 @@ tdm_display_init(tdm_error *error) tdm_display_enable_path(str); str = getenv("TDM_COMMIT_PER_VBLANK"); - if (str && (strstr(str, "1"))) - tdm_display_enable_commit_per_vblank(private_display, 1); + if (str) { + char *end; + int enable = strtol(str, &end, 10); + + tdm_display_enable_commit_per_vblank(private_display, enable); + } if (pthread_mutex_init(&private_display->lock, NULL)) { ret = TDM_ERROR_OPERATION_FAILED; @@ -1298,14 +1302,16 @@ tdm_display_enable_commit_per_vblank(tdm_private_display *private_display, int e { private_display->commit_per_vblank = enable; - if (private_display->commit_per_vblank == 1) + if (private_display->commit_per_vblank == 0) + TDM_INFO("commit per vblank: disable"); + else if (private_display->commit_per_vblank == 1) TDM_INFO("commit per vblank: enable (1 layer)"); else if (private_display->commit_per_vblank == 2) TDM_INFO("commit per vblank: enable (previous commit)"); - else if (private_display->commit_per_vblank > 0) - TDM_INFO("commit per vblank: enable (unknown)"); - else - TDM_INFO("commit per vblank: disable"); + else { + private_display->commit_per_vblank = 1; + TDM_INFO("commit per vblank: enable (changed to 1 layer)"); + } return TDM_ERROR_NONE; } diff --git a/src/tdm_helper.c b/src/tdm_helper.c index 87df714..06ecba4 100644 --- a/src/tdm_helper.c +++ b/src/tdm_helper.c @@ -987,3 +987,16 @@ tdm_helper_get_display_information(tdm_display *dpy, char *reply, int *len) unlock: _pthread_mutex_unlock(&private_display->lock); } + +EXTERN int +tdm_helper_commit_per_vblank_enabled(tdm_display *dpy) +{ + tdm_private_display *private_display; + + TDM_RETURN_VAL_IF_FAIL(dpy != NULL, 0); + + private_display = dpy; + + return private_display->commit_per_vblank; +} + -- 2.7.4 From 37020c1af24de60847594b139006c03734018a14 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Thu, 2 Feb 2017 13:00:18 +0900 Subject: [PATCH 14/16] commit: use _tdm_output_commit in case of non commit-per-vblank Change-Id: If83c02ab7a6801dbae64f14337bf0baf364a7df8 --- src/tdm_display.c | 134 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 94 insertions(+), 40 deletions(-) diff --git a/src/tdm_display.c b/src/tdm_display.c index 4a317b9..79734ce 100644 --- a/src/tdm_display.c +++ b/src/tdm_display.c @@ -1986,6 +1986,53 @@ wait_failed: } static void +_tdm_layer_cb_output_commit(tdm_output *output, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, void *user_data) +{ + tdm_private_layer_commit_handler *layer_commit_handler = user_data; + tdm_private_layer_commit_handler *lm = NULL; + tdm_private_display *private_display; + tdm_private_output *private_output = output; + tdm_private_layer *private_layer; + int found = 0; + + TDM_RETURN_IF_FAIL(layer_commit_handler != NULL); + + private_display = private_output->private_display; + + LIST_FOR_EACH_ENTRY(lm, &private_output->layer_commit_handler_list, link) { + if (layer_commit_handler == lm) { + found = 1; + break; + } + } + + if (!found) + return; + + private_layer = layer_commit_handler->private_layer; + + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("layer(%p) commit: output(%d) committed", private_layer, private_output->pipe); + + _pthread_mutex_lock(&private_display->lock); + + _tdm_layer_committed(private_layer); + + if (layer_commit_handler->func) { + _pthread_mutex_unlock(&private_display->lock); + layer_commit_handler->func(private_output, sequence, + tv_sec, tv_usec, layer_commit_handler->user_data); + _pthread_mutex_lock(&private_display->lock); + } + + LIST_DEL(&layer_commit_handler->link); + free(layer_commit_handler); + + _pthread_mutex_unlock(&private_display->lock); +} + +static void _tdm_layer_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data) { @@ -2012,12 +2059,6 @@ _tdm_layer_commit_possible(tdm_private_layer *private_layer) tdm_private_output *private_output = private_layer->private_output; tdm_private_display *private_display = private_output->private_display; - if (!private_display->commit_per_vblank) { - if (tdm_debug_module & TDM_DEBUG_COMMIT) - TDM_INFO("layer(%p) commit: commit_per_vblank false", private_layer); - return 1; - } - if (private_display->commit_per_vblank == 1 && _tdm_output_used_layer_count(private_output) == 1) { if (tdm_debug_module & TDM_DEBUG_COMMIT) TDM_INFO("layer(%p) commit: 1 layer", private_layer); @@ -2036,7 +2077,7 @@ _tdm_layer_commit_possible(tdm_private_layer *private_layer) static tdm_error _tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data) { - tdm_private_layer_commit_handler *layer_commit_handler = NULL; + tdm_private_layer_commit_handler *layer_commit_handler; LAYER_FUNC_ENTRY(); if (private_layer->committing) @@ -2055,43 +2096,57 @@ _tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_da layer_commit_handler->func = func; layer_commit_handler->user_data = user_data; - if (_tdm_layer_commit_possible(private_layer)) { - /* add to layer_commit_handler_list */ - LIST_ADD(&layer_commit_handler->link, &private_output->layer_commit_handler_list); + if (!private_display->commit_per_vblank) { + TDM_GOTO_IF_FAIL(private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT, commit_failed); - ret = _tdm_output_commit(private_layer->private_output, 0, NULL, NULL); + LIST_ADD(&layer_commit_handler->link, &private_output->layer_commit_handler_list); + ret = _tdm_output_commit(private_layer->private_output, 0, _tdm_layer_cb_output_commit, layer_commit_handler); TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed); if (tdm_debug_module & TDM_DEBUG_COMMIT) - TDM_INFO("layer(%p) commit: output", private_layer); + TDM_INFO("layer(%p) commit: no commit-per-vblank", private_layer); } else { - /* add to pending_commit_handler_list. It will be commited when a vblank occurs */ - LIST_ADD(&layer_commit_handler->link, &private_output->pending_commit_handler_list); + TDM_GOTO_IF_FAIL(private_display->commit_type == TDM_COMMIT_TYPE_LAYER, commit_failed); - if (tdm_debug_module & TDM_DEBUG_COMMIT) - TDM_INFO("layer(%p) commit: pending", private_layer); - } + if (_tdm_layer_commit_possible(private_layer)) { + /* add to layer_commit_handler_list */ + LIST_ADD(&layer_commit_handler->link, &private_output->layer_commit_handler_list); - if (!private_output->vblank) { - /* tdm_vblank APIs is for server. it should be called in unlock status*/ - _pthread_mutex_unlock(&private_display->lock); - private_output->vblank = tdm_vblank_create(private_display, private_output, NULL); - _pthread_mutex_lock(&private_display->lock); - TDM_GOTO_IF_FAIL(private_output->vblank != NULL, commit_failed); + ret = _tdm_output_commit(private_layer->private_output, 0, NULL, NULL); + TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed); - tdm_vblank_set_add_front(private_output->vblank, 1); - } + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("layer(%p) commit: output", private_layer); + } else { + /* add to pending_commit_handler_list. It will be commited when a vblank occurs */ + LIST_ADD(&layer_commit_handler->link, &private_output->pending_commit_handler_list); - if (!private_output->waiting_vblank) { - /* tdm_vblank APIs is for server. it should be called in unlock status*/ - _pthread_mutex_unlock(&private_display->lock); - ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output); - _pthread_mutex_lock(&private_display->lock); - TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed); - private_output->waiting_vblank = 1; + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("layer(%p) commit: pending", private_layer); + } - if (tdm_debug_module & TDM_DEBUG_COMMIT) - TDM_INFO("layer(%p) commit: wait vblank", private_layer); + if (!private_output->vblank) { + /* tdm_vblank APIs is for server. it should be called in unlock status*/ + _pthread_mutex_unlock(&private_display->lock); + private_output->vblank = tdm_vblank_create(private_display, private_output, NULL); + _pthread_mutex_lock(&private_display->lock); + TDM_GOTO_IF_FAIL(private_output->vblank != NULL, commit_failed); + + /* to call the frontend's internal vblank handlers before the extern vblank handlers */ + tdm_vblank_set_add_front(private_output->vblank, 1); + } + + if (!private_output->waiting_vblank) { + /* tdm_vblank APIs is for server. it should be called in unlock status*/ + _pthread_mutex_unlock(&private_display->lock); + ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output); + _pthread_mutex_lock(&private_display->lock); + TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed); + private_output->waiting_vblank = 1; + + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("layer(%p) commit: wait vblank", private_layer); + } } return ret; @@ -2111,12 +2166,11 @@ tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_dat _pthread_mutex_lock(&private_display->lock); - if (private_display->commit_type == TDM_COMMIT_TYPE_NONE) - private_display->commit_type = TDM_COMMIT_TYPE_LAYER; - else if (private_display->commit_type == TDM_COMMIT_TYPE_OUTPUT) { - TDM_ERR("Can't supported. Use tdm_output_commit"); - _pthread_mutex_unlock(&private_display->lock); - return TDM_ERROR_BAD_REQUEST; + if (private_display->commit_type == TDM_COMMIT_TYPE_NONE) { + if (!private_display->commit_per_vblank) + private_display->commit_type = TDM_COMMIT_TYPE_OUTPUT; + else + private_display->commit_type = TDM_COMMIT_TYPE_LAYER; } if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) { -- 2.7.4 From a2e97e82ced93e820a4e76e08980b4ff9d62ef3b Mon Sep 17 00:00:00 2001 From: Boram Park Date: Thu, 2 Feb 2017 14:39:53 +0900 Subject: [PATCH 15/16] package version up to 1.6.3 Change-Id: I8bf469b2dd657964faa8bf1406f47512d97080e8 --- packaging/libtdm.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libtdm.spec b/packaging/libtdm.spec index 2a9f0ea..8d130e8 100644 --- a/packaging/libtdm.spec +++ b/packaging/libtdm.spec @@ -1,7 +1,7 @@ %bcond_with utest Name: libtdm -Version: 1.6.2 +Version: 1.6.3 Release: 0 Summary: User Library of Tizen Display Manager Group: Development/Libraries -- 2.7.4 From 00bb90bf1d12d0b0ea02d93dac48686398f2bbe7 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Fri, 3 Feb 2017 15:41:16 +0900 Subject: [PATCH 16/16] commit: enhance debug log Change-Id: Ifd020ef0723b4d7d2121e77aa6be5682aaeeaa2d --- src/tdm_display.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/tdm_display.c b/src/tdm_display.c index 79734ce..53b1c7c 100644 --- a/src/tdm_display.c +++ b/src/tdm_display.c @@ -993,6 +993,9 @@ tdm_output_cb_vblank(tdm_output *output_backend, unsigned int sequence, _pthread_mutex_unlock(&private_display->lock); LIST_FOR_EACH_ENTRY_SAFE(v, vv, &clone_list, link) { + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("output(%d) got vblank: handler(%p)", private_output->pipe, v); + if (v->func) v->func(v->private_output, sequence, tv_sec, tv_usec, v->user_data); LIST_DEL(&v->link); @@ -1093,6 +1096,9 @@ _tdm_output_wait_vblank(tdm_output *output, int interval, int sync, return TDM_ERROR_OUT_OF_MEMORY; } + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("output(%d) wait_vblank: handler(%p)", private_output->pipe, vblank_handler); + LIST_FOR_EACH_ENTRY(v, &private_output->vblank_handler_list, link) { if (v->interval == interval && v->sync == sync && v->owner_tid == tid) { skip_request = 1; @@ -1117,6 +1123,9 @@ _tdm_output_wait_vblank(tdm_output *output, int interval, int sync, ret = func_output->output_wait_vblank(private_output->output_backend, interval, sync, vblank_handler); TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed); + + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("output(%d) backend wait_vblank", private_output->pipe); } return ret; @@ -1941,6 +1950,9 @@ _tdm_layer_got_output_vblank(tdm_private_output *private_output, unsigned int se } LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &clone_list, link) { + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("layer(%p) committed. handle(%p)", lm->private_layer, (lm)?:NULL); + _tdm_layer_committed(lm->private_layer); _pthread_mutex_unlock(&private_display->lock); if (lm->func) @@ -2013,7 +2025,8 @@ _tdm_layer_cb_output_commit(tdm_output *output, unsigned int sequence, private_layer = layer_commit_handler->private_layer; if (tdm_debug_module & TDM_DEBUG_COMMIT) - TDM_INFO("layer(%p) commit: output(%d) committed", private_layer, private_output->pipe); + TDM_INFO("layer(%p) commit: output(%d) committed. handle(%p)", + private_layer, private_output->pipe, (layer_commit_handler)?:NULL); _pthread_mutex_lock(&private_display->lock); @@ -2080,17 +2093,15 @@ _tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_da tdm_private_layer_commit_handler *layer_commit_handler; LAYER_FUNC_ENTRY(); - if (private_layer->committing) - TDM_WRN("layer(%d) too many commit", private_layer->index); - else - private_layer->committing = 1; - layer_commit_handler = calloc(1, sizeof(tdm_private_layer_commit_handler)); if (!layer_commit_handler) { TDM_ERR("failed: alloc memory"); return TDM_ERROR_OUT_OF_MEMORY; } + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("layer(%p) commit: handle(%p)", private_layer, layer_commit_handler); + LIST_INITHEAD(&layer_commit_handler->link); layer_commit_handler->private_layer = private_layer; layer_commit_handler->func = func; @@ -2108,6 +2119,11 @@ _tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_da } else { TDM_GOTO_IF_FAIL(private_display->commit_type == TDM_COMMIT_TYPE_LAYER, commit_failed); + if (private_layer->committing) + TDM_WRN("layer(%d) too many commit", private_layer->index); + else + private_layer->committing = 1; + if (_tdm_layer_commit_possible(private_layer)) { /* add to layer_commit_handler_list */ LIST_ADD(&layer_commit_handler->link, &private_output->layer_commit_handler_list); @@ -2180,9 +2196,6 @@ tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_dat return TDM_ERROR_DPMS_OFF; } - if (tdm_debug_module & TDM_DEBUG_COMMIT) - TDM_INFO("layer(%p) commit", private_layer); - ret = _tdm_layer_commit(private_layer, func, user_data); _pthread_mutex_unlock(&private_display->lock); -- 2.7.4