From: Boram Park Date: Tue, 17 Jan 2017 11:51:31 +0000 (+0900) Subject: use vblank instead of the output commit handler in case of tdm_layer_commit X-Git-Tag: submit/tizen_3.0/20170118.120050~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=41fb6132b55a38e0418d08e8cdaa93d13fcd8649;p=platform%2Fcore%2Fuifw%2Flibtdm.git use vblank instead of the output commit handler in case of tdm_layer_commit Change-Id: Ib2a29cc331b8243922d43325265891119c809510 --- diff --git a/src/tdm_display.c b/src/tdm_display.c index f3a4e057..4a317b95 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,74 +1970,21 @@ _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); } 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) @@ -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 badde954..0d4cfdaf 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 114e7436..8e3f7dbb 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; +} +