X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Ftdm_output.c;h=d6e1cc35e22be34bcc69e82b44c736c1e5249b62;hb=1b7ce67e473517578e9c78b4afe05fb0bf2a8361;hp=ee760c16b75847d01423fca9a358524ca67e72d1;hpb=08707fc90dc3c6adccea7a958ed6a58604990aee;p=platform%2Fcore%2Fuifw%2Flibtdm.git diff --git a/src/tdm_output.c b/src/tdm_output.c index ee760c1..d6e1cc3 100644 --- a/src/tdm_output.c +++ b/src/tdm_output.c @@ -130,15 +130,131 @@ _tdm_output_vblank_timeout_update(tdm_private_output *private_output, int ms_del INTERN tdm_error tdm_output_init(tdm_private_display *private_display) { + tdm_thread_cb_set_find_func(TDM_THREAD_CB_OUTPUT_DESTROY, tdm_display_find_output_stamp); tdm_thread_cb_set_find_func(TDM_THREAD_CB_OUTPUT_COMMIT, tdm_display_find_output_stamp); tdm_thread_cb_set_find_func(TDM_THREAD_CB_OUTPUT_VBLANK, tdm_display_find_output_stamp); tdm_thread_cb_set_find_func(TDM_THREAD_CB_OUTPUT_STATUS, tdm_display_find_output_stamp); tdm_thread_cb_set_find_func(TDM_THREAD_CB_OUTPUT_DPMS, tdm_display_find_output_stamp); + tdm_thread_cb_set_find_func(TDM_THREAD_CB_VOUTPUT_COMMIT, tdm_display_find_private_voutput); + return TDM_ERROR_NONE; +} + +INTERN tdm_error +tdm_output_call_thread_cb_destroy(tdm_private_output *private_output) +{ + tdm_thread_cb_output_destroy output_destroy; + tdm_error ret; + + memset(&output_destroy, 0, sizeof output_destroy); + output_destroy.base.type = TDM_THREAD_CB_OUTPUT_DESTROY; + output_destroy.base.length = sizeof output_destroy; + output_destroy.base.object_stamp = private_output->stamp; + output_destroy.base.data = NULL; + output_destroy.base.sync = 1; + + ret = tdm_thread_cb_call(private_output, &output_destroy.base, 1); + TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); return TDM_ERROR_NONE; } +INTERN void +tdm_output_thread_cb_destroy(tdm_private_display *private_display, void *object, tdm_thread_cb_base *cb_base, void *user_data) +{ + tdm_private_output *private_output = object; + tdm_private_output_destroy_handler *destroy_handler = user_data; + + TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); + + assert(destroy_handler->owner_tid == syscall(SYS_gettid)); + + _pthread_mutex_unlock(&private_display->lock); + destroy_handler->func(private_output, destroy_handler->user_data); + _pthread_mutex_lock(&private_display->lock); +} + +EXTERN tdm_error +tdm_output_add_destroy_handler(tdm_output *output, + tdm_output_destroy_handler func, + void *user_data) +{ + tdm_private_output_destroy_handler *destroy_handler = NULL; + OUTPUT_FUNC_ENTRY(); + + TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER); + + _pthread_mutex_lock(&private_display->lock); + + LIST_FOR_EACH_ENTRY(destroy_handler, &private_output->destroy_handler_list, link) { + if (destroy_handler->func == func && destroy_handler->user_data == user_data) { + TDM_ERR("can't add twice"); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_BAD_REQUEST; + } + } + + destroy_handler = calloc(1, sizeof(tdm_private_output_destroy_handler)); + if (!destroy_handler) { + TDM_ERR("failed: alloc memory"); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_OUT_OF_MEMORY; + } + + ret = tdm_thread_cb_add(private_output, TDM_THREAD_CB_OUTPUT_DESTROY, NULL, tdm_output_thread_cb_destroy, destroy_handler); + if (ret != TDM_ERROR_NONE) { + TDM_ERR("tdm_thread_cb_add failed"); + free(destroy_handler); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_OPERATION_FAILED; + } + + destroy_handler->private_output = private_output; + destroy_handler->func = func; + destroy_handler->user_data = user_data; + destroy_handler->owner_tid = syscall(SYS_gettid); + + LIST_ADDTAIL(&destroy_handler->link, &private_output->destroy_handler_list); + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} + +EXTERN void +tdm_output_remove_destroy_handler(tdm_output *output, + tdm_output_destroy_handler func, + void *user_data) +{ + tdm_private_display *private_display; + tdm_private_output *private_output; + tdm_private_output_destroy_handler *destroy_handler = NULL, *hh = NULL; + + TDM_RETURN_IF_FAIL(output != NULL); + TDM_RETURN_IF_FAIL(func != NULL); + + private_output = (tdm_private_output*)output; + private_display = private_output->private_display; + + _pthread_mutex_lock(&private_display->lock); + + LIST_FOR_EACH_ENTRY_SAFE(destroy_handler, hh, &private_output->destroy_handler_list, link) { + if (destroy_handler->func != func || destroy_handler->user_data != user_data) + continue; + + tdm_thread_cb_remove(private_output, TDM_THREAD_CB_OUTPUT_DESTROY, NULL, tdm_output_thread_cb_destroy, destroy_handler); + + LIST_DEL(&destroy_handler->link); + free(destroy_handler); + + _pthread_mutex_unlock(&private_display->lock); + + return; + } + + _pthread_mutex_unlock(&private_display->lock); +} + EXTERN tdm_module * tdm_output_get_backend_module(tdm_output *output, tdm_error *error) { @@ -297,7 +413,7 @@ tdm_output_cb_status(tdm_output *output_backend, tdm_output_conn_status status, if ((private_output->caps.status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED && status != TDM_OUTPUT_CONN_STATUS_DISCONNECTED) || (private_output->caps.status != TDM_OUTPUT_CONN_STATUS_DISCONNECTED && status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED)) { - ret = tdm_display_update_output(private_output->private_module, output_backend, private_output->pipe, 1); + ret = tdm_display_update_output(private_output->private_module, output_backend); TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE); } else { private_output->caps.status = status; @@ -313,11 +429,11 @@ tdm_output_cb_dpms(tdm_output *output_backend, tdm_output_dpms dpms, void *user_ tdm_private_output *private_output = user_data; tdm_error ret; - TDM_INFO("output(%d) %s", private_output->pipe, tdm_status_str(dpms)); + TDM_INFO("output(%d) %s", private_output->pipe, tdm_dpms_str(dpms)); private_output->current_dpms_value = dpms; private_output->waiting_dpms_change = 0; - TDM_INFO("output(%d) dpms async '%s' done", private_output->pipe, tdm_dpms_str(dpms)); + TDM_INFO("output(%d) DPMS async '%s' done", private_output->pipe, tdm_dpms_str(dpms)); ret = _tdm_output_call_thread_cb_dpms(private_output, dpms); TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); @@ -385,6 +501,85 @@ tdm_output_add_change_handler(tdm_output *output, return ret; } +EXTERN tdm_error +tdm_output_add_mode_change_request_handler(tdm_output *output, + tdm_output_mode_change_request_handler func, + void *user_data) +{ + tdm_private_display *private_display; + tdm_private_output *private_output; + tdm_private_output_mode_change_handler *mode_change_handler = NULL; + + TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER); + + private_output = (tdm_private_output*)output; + private_display = private_output->private_display; + + _pthread_mutex_lock(&private_display->lock); + + LIST_FOR_EACH_ENTRY(mode_change_handler, &private_output->mode_change_request_handler_list, link) { + if (mode_change_handler->func == func && mode_change_handler->user_data == user_data) { + TDM_ERR("can't add twice"); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_BAD_REQUEST; + } + } + + mode_change_handler = calloc(1, sizeof(tdm_private_output_mode_change_handler)); + if (!mode_change_handler) { + /* LCOV_EXCL_START */ + TDM_ERR("failed: alloc memory"); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_OUT_OF_MEMORY; + /* LCOV_EXCL_STOP */ + } + + mode_change_handler->private_output = private_output; + mode_change_handler->func = func; + mode_change_handler->user_data = user_data; + + LIST_ADDTAIL(&mode_change_handler->link, &private_output->mode_change_request_handler_list); + + _pthread_mutex_unlock(&private_display->lock); + + return TDM_ERROR_NONE; +} + +EXTERN tdm_error +tdm_output_remove_mode_change_request_handler(tdm_output *output, + tdm_output_mode_change_request_handler func, + void *user_data) +{ + tdm_private_display *private_display; + tdm_private_output *private_output; + tdm_private_output_mode_change_handler *mode_change_handler = NULL, *hh = NULL; + + TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER); + + private_output = (tdm_private_output*)output; + private_display = private_output->private_display; + + _pthread_mutex_lock(&private_display->lock); + + LIST_FOR_EACH_ENTRY_SAFE(mode_change_handler, hh, &private_output->mode_change_request_handler_list, link) { + if (mode_change_handler->func != func || mode_change_handler->user_data != user_data) + continue; + + LIST_DEL(&mode_change_handler->link); + free(mode_change_handler); + + _pthread_mutex_unlock(&private_display->lock); + + return TDM_ERROR_NONE; + } + + _pthread_mutex_unlock(&private_display->lock); + + return TDM_ERROR_INVALID_PARAMETER; +} + EXTERN void tdm_output_remove_change_handler(tdm_output *output, tdm_output_change_handler func, @@ -456,7 +651,7 @@ tdm_output_get_layer_count(tdm_output *output, int *count) *count = 0; LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) - (*count)++; + (*count)++; if (*count == 0) { _pthread_mutex_unlock(&private_display->lock); return TDM_ERROR_NONE; @@ -881,6 +1076,87 @@ _tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence, TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); } +static void +_tdm_voutput_thread_cb_commit(tdm_private_display *private_display, void *object, tdm_thread_cb_base *cb_base, void *user_data) +{ + tdm_thread_cb_voutput_commit *voutput_commit = (tdm_thread_cb_voutput_commit *)cb_base; + tdm_private_voutput_commit_handler *voutput_commit_handler = voutput_commit->base.data; + tdm_private_voutput *private_voutput = object; + tdm_private_output *private_output = NULL; + + TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); + + if (!voutput_commit_handler) + return; + + assert(voutput_commit_handler->owner_tid == syscall(SYS_gettid)); + + tdm_thread_cb_remove(private_voutput, TDM_THREAD_CB_VOUTPUT_COMMIT, voutput_commit_handler, _tdm_voutput_thread_cb_commit, NULL); + + LIST_DEL(&voutput_commit_handler->link); + + private_output = private_voutput->private_output; + if (tdm_debug_module & TDM_DEBUG_COMMIT) { + TDM_INFO("----------------------------------------- voutput(%d) committed", private_output->pipe); + TDM_INFO("handler(%p)", voutput_commit_handler); + } + + if (voutput_commit_handler->func && private_voutput->set_voutput_commit != 0) { + _pthread_mutex_unlock(&private_display->lock); + voutput_commit_handler->func(private_voutput, voutput_commit_handler->user_data); + _pthread_mutex_lock(&private_display->lock); + } + + free(voutput_commit_handler); + + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("-----------------------------------------..."); +} + +static void +_tdm_voutput_cb_commit(tdm_voutput *voutput_backend, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, void *user_data) +{ + tdm_private_voutput_commit_handler *voutput_commit_handler = NULL; + tdm_private_module *private_module; + tdm_private_voutput *private_voutput = NULL, *v = NULL; + tdm_private_output *private_output; + tdm_thread_cb_voutput_commit voutput_commit; + tdm_error ret; + + private_module = tdm_display_get()->virtual_module; + + LIST_FOR_EACH_ENTRY(v, &private_module->voutput_list, link) { + if (v->voutput_backend == voutput_backend) { + private_voutput = v; + break; + } + } + if (!private_voutput) { + TDM_ERR("cannot find voutput"); + return; + } + + if (LIST_LENGTH(&private_voutput->voutput_commit_handler_list) == 0) return; + + voutput_commit_handler = LIST_FIRST_ENTRY(&private_voutput->voutput_commit_handler_list, tdm_private_voutput_commit_handler, link); + + private_output = private_voutput->private_output; + + memset(&voutput_commit, 0, sizeof voutput_commit); + voutput_commit.base.type = TDM_THREAD_CB_VOUTPUT_COMMIT; + voutput_commit.base.length = sizeof voutput_commit; + voutput_commit.base.object_stamp = private_output->stamp; + voutput_commit.base.data = voutput_commit_handler; + voutput_commit.base.sync = 0; + voutput_commit.sequence = sequence; + voutput_commit.tv_sec = tv_sec; + voutput_commit.tv_usec = tv_usec; + + ret = tdm_thread_cb_call(private_voutput, &voutput_commit.base, 1); + TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); +} + /* 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. @@ -1091,13 +1367,164 @@ tdm_output_remove_commit_handler(tdm_output *output, tdm_output_commit_handler f return ret; } +INTERN void +tdm_output_request_mode_set(tdm_output *output, unsigned int index) +{ + tdm_private_output *private_output = (tdm_private_output*)output; + tdm_private_output_mode_change_handler *mode_change_handler = NULL; + + TDM_RETURN_IF_FAIL(private_output != NULL); + + if (LIST_IS_EMPTY(&private_output->mode_change_request_handler_list)) + return; + + LIST_FOR_EACH_ENTRY(mode_change_handler, &private_output->mode_change_request_handler_list, link) { + mode_change_handler->func(mode_change_handler->private_output, index, mode_change_handler->user_data); + } +} + +static void +_voutput_commit_func(tdm_voutput *voutput, tbm_surface_h buffer) +{ + tdm_private_voutput *private_voutput = (tdm_private_voutput *)voutput; + tdm_error ret; + + TDM_RETURN_IF_FAIL(voutput != NULL); + TDM_RETURN_IF_FAIL(buffer != NULL); + + ret = tdm_voutput_attach_buffer(private_voutput, buffer); + TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE); + ret = tdm_voutput_commit_buffer(private_voutput); + TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE); + + return; +} + +INTERN tdm_error +tdm_output_set_voutput_commit(tdm_voutput *voutput) +{ + tdm_private_display *private_display; + tdm_private_output *private_output; + tdm_private_voutput *private_voutput; + tdm_private_voutput_commit_handler *voutput_commit_handler = NULL; + tdm_error ret = TDM_ERROR_NONE; + + TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER); + + private_voutput = (tdm_private_voutput *)voutput; + private_display = private_voutput->private_display; + private_output = (tdm_private_output *)private_voutput->private_output; + + _pthread_mutex_lock(&private_display->lock); + + if (LIST_LENGTH(&private_voutput->voutput_commit_handler_list) != 0) { + _pthread_mutex_unlock(&private_display->lock); + return ret; + } + + if (!private_voutput->regist_commit_cb) { + private_voutput->regist_commit_cb = 1; + ret = tdm_voutput_set_commit_func(private_voutput, _tdm_voutput_cb_commit); + if (ret != TDM_ERROR_NONE) { + TDM_ERR("failed: tdm_voutput_set_commit_func"); + _pthread_mutex_unlock(&private_display->lock); + return ret; + } + } + + voutput_commit_handler = calloc(1, sizeof(tdm_private_voutput_commit_handler)); + if (!voutput_commit_handler) { + /* LCOV_EXCL_START */ + TDM_ERR("failed: alloc memory"); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_OUT_OF_MEMORY; + /* LCOV_EXCL_STOP */ + } + + ret = tdm_thread_cb_add(private_output->private_voutput, TDM_THREAD_CB_VOUTPUT_COMMIT, voutput_commit_handler, _tdm_voutput_thread_cb_commit, NULL); + if (ret != TDM_ERROR_NONE) { + TDM_ERR("tdm_thread_cb_add failed"); + free(voutput_commit_handler); + _pthread_mutex_unlock(&private_display->lock); + return ret; + } + + LIST_ADDTAIL(&voutput_commit_handler->link, &private_voutput->voutput_commit_handler_list); + voutput_commit_handler->private_voutput = private_voutput; + voutput_commit_handler->func = _voutput_commit_func; + voutput_commit_handler->owner_tid = syscall(SYS_gettid); + + private_voutput->set_voutput_commit = 1; + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} + +INTERN tdm_error +tdm_output_unset_voutput_commit(tdm_voutput *voutput) +{ + tdm_private_display *private_display; + tdm_private_output *private_output; + tdm_private_voutput *private_voutput; + tdm_private_voutput_commit_handler *voutput_commit_handler = NULL; + tdm_error ret = TDM_ERROR_NONE; + + TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER); + + private_voutput = (tdm_private_voutput *)voutput; + private_display = private_voutput->private_display; + private_output = (tdm_private_output *)private_voutput->private_output; + + _pthread_mutex_lock(&private_display->lock); + + private_voutput->set_voutput_commit = 0; + + if (private_voutput->regist_commit_cb) { + private_voutput->regist_commit_cb = 0; + ret = tdm_voutput_set_commit_func(private_voutput, NULL); + if (ret != TDM_ERROR_NONE) { + TDM_ERR("failed: tdm_voutput_set_commit_func"); + _pthread_mutex_unlock(&private_display->lock); + return ret; + } + } + + if (LIST_LENGTH(&private_voutput->voutput_commit_handler_list) == 0) { + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_NONE; + } + + if (LIST_LENGTH(&private_output->output_commit_handler_list) != 0) { + //commiting. don't remove voutput commit thread here + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_NONE; + } + + if (LIST_LENGTH(&private_voutput->voutput_commit_handler_list) != 0) { + voutput_commit_handler = LIST_FIRST_ENTRY(&private_voutput->voutput_commit_handler_list, tdm_private_voutput_commit_handler, link); + } else { + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_NONE; + } + + tdm_thread_cb_remove(private_output->private_voutput, TDM_THREAD_CB_VOUTPUT_COMMIT, voutput_commit_handler, _tdm_voutput_thread_cb_commit, NULL); + + _pthread_mutex_unlock(&private_display->lock); + + return TDM_ERROR_NONE; +} + INTERN tdm_error tdm_output_commit_internal(tdm_output *output, int sync, tdm_output_commit_handler func, void *user_data) { + tdm_private_display *private_display; tdm_private_output *private_output; + tdm_private_voutput *private_voutput; tdm_private_module *private_module; tdm_func_output *func_output; tdm_private_output_commit_handler *output_commit_handler = NULL; + tdm_private_voutput_commit_handler *voutput_commit_handler = NULL; tdm_private_layer *private_layer = NULL; tdm_output_dpms dpms_value = TDM_OUTPUT_DPMS_ON; tdm_error ret = TDM_ERROR_NONE; @@ -1106,6 +1533,7 @@ tdm_output_commit_internal(tdm_output *output, int sync, tdm_output_commit_handl private_output = (tdm_private_output*)output; private_module = private_output->private_module; + private_display = private_module->private_display; func_output = &private_module->func_output; if (!func_output->output_commit) { @@ -1133,6 +1561,14 @@ tdm_output_commit_internal(tdm_output *output, int sync, tdm_output_commit_handl /* LCOV_EXCL_STOP */ } + if (private_module == private_display->virtual_module) { + if (!private_output->private_voutput) { + TDM_ERR("virtual module but don't have voutput"); + free(output_commit_handler); + return TDM_ERROR_BAD_MODULE; + } + } + ret = tdm_thread_cb_add(private_output, TDM_THREAD_CB_OUTPUT_COMMIT, output_commit_handler, _tdm_output_thread_cb_commit, NULL); if (ret != TDM_ERROR_NONE) { TDM_ERR("tdm_thread_cb_add failed"); @@ -1146,6 +1582,18 @@ tdm_output_commit_internal(tdm_output *output, int sync, tdm_output_commit_handl output_commit_handler->user_data = user_data; output_commit_handler->owner_tid = syscall(SYS_gettid); + if (private_module == private_display->virtual_module) { + private_voutput = private_output->private_voutput; + + /* voutput use only 1 layer */ + private_layer = LIST_FIRST_ENTRY(&private_output->layer_list, tdm_private_layer, link); + + if (LIST_LENGTH(&private_voutput->voutput_commit_handler_list) != 0) { + voutput_commit_handler = LIST_FIRST_ENTRY(&private_voutput->voutput_commit_handler_list, tdm_private_voutput_commit_handler, link); + voutput_commit_handler->user_data = private_layer->commiting_buffer; + } + } + ret = func_output->output_commit(private_output->output_backend, sync, output_commit_handler); TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed); @@ -1173,6 +1621,7 @@ tdm_output_commit_internal(tdm_output *output, int sync, tdm_output_commit_handl private_layer->committed_buffer = private_layer->waiting_buffer; private_layer->waiting_buffer = NULL; + private_layer->commiting_buffer = NULL; if (tdm_debug_module & TDM_DEBUG_BUFFER) TDM_INFO("layer(%p) waiting_buffer(%p) committed_buffer(%p)", private_layer, private_layer->waiting_buffer, @@ -1181,8 +1630,11 @@ tdm_output_commit_internal(tdm_output *output, int sync, tdm_output_commit_handl if (TDM_OUTPUT_DPMS_VSYNC_IS_OFF(dpms_value)) { TDM_WRN("dpms %s. Directly call commit handler instead of commit.", tdm_dpms_str(dpms_value)); - if (func) + if (func) { + _pthread_mutex_unlock(&private_display->lock); func(output, 0, 0, 0, user_data); + _pthread_mutex_lock(&private_display->lock); + } } return ret; @@ -1194,6 +1646,7 @@ commit_failed: LIST_DEL(&output_commit_handler->link); free(output_commit_handler); } + return ret; /* LCOV_EXCL_STOP */ } @@ -1325,14 +1778,14 @@ tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value) private_module = private_output->private_module; func_output = &private_module->func_output; - TDM_INFO("output(%d) dpms '%s'", private_output->pipe, tdm_dpms_str(dpms_value)); + TDM_INFO("output(%d) DPMS '%s'", private_output->pipe, tdm_dpms_str(dpms_value)); if (func_output->output_set_dpms) ret = func_output->output_set_dpms(private_output->output_backend, dpms_value); else { /* LCOV_EXCL_START */ ret = TDM_ERROR_NONE; - TDM_WRN("not implemented!!"); + TDM_WRN("DPMS not implemented!!"); goto done; /* LCOV_EXCL_STOP */ } @@ -1343,14 +1796,14 @@ done: private_output->current_dpms_value = dpms_value; _tdm_output_call_thread_cb_dpms(private_output, dpms_value); } - TDM_INFO("output(%d) dpms '%s' done", private_output->pipe, tdm_dpms_str(dpms_value)); + TDM_INFO("output(%d) DPMS '%s' done", private_output->pipe, tdm_dpms_str(dpms_value)); } else { tdm_output_dpms temp = TDM_OUTPUT_DPMS_OFF; /* update current_dpms_value forcely */ tdm_output_get_dpms_internal(output, &temp); - TDM_ERR("output(%d) set_dpms failed: dpms '%s'", private_output->pipe, tdm_dpms_str(temp)); + TDM_ERR("output(%d) set DPMS failed: dpms '%s'", private_output->pipe, tdm_dpms_str(temp)); } _pthread_mutex_unlock(&private_display->lock); @@ -1364,6 +1817,7 @@ tdm_output_set_dpms_async(tdm_output *output, tdm_output_dpms dpms_value) { tdm_private_module *private_module; tdm_func_output *func_output; + int sync = 0; OUTPUT_FUNC_ENTRY(); if (!(private_output->caps.capabilities & TDM_OUTPUT_CAPABILITY_ASYNC_DPMS)) { @@ -1395,13 +1849,13 @@ tdm_output_set_dpms_async(tdm_output *output, tdm_output_dpms dpms_value) private_module = private_output->private_module; func_output = &private_module->func_output; if (!func_output->output_set_dpms_handler) { - TDM_WRN("not implemented: output_set_dpms_handler"); + TDM_WRN("not implemented DPMS: output_set_dpms_handler"); _pthread_mutex_unlock(&private_display->lock); return TDM_ERROR_NOT_IMPLEMENTED; } if (!func_output->output_set_dpms_async) { - TDM_WRN("not implemented: output_set_dpms_async"); + TDM_WRN("not implemented DPMS: output_set_dpms_async"); _pthread_mutex_unlock(&private_display->lock); return TDM_ERROR_NOT_IMPLEMENTED; } @@ -1412,25 +1866,32 @@ tdm_output_set_dpms_async(tdm_output *output, tdm_output_dpms dpms_value) tdm_output_cb_dpms, private_output); if (ret != TDM_ERROR_NONE) { _pthread_mutex_unlock(&private_display->lock); - TDM_ERR("Can't set the dpms handler!!"); + TDM_ERR("Can't set the DPMS handler!!"); return ret; } } - TDM_INFO("output(%d) dpms async '%s'", private_output->pipe, tdm_dpms_str(dpms_value)); + TDM_INFO("output(%d) DPMS async '%s'", private_output->pipe, tdm_dpms_str(dpms_value)); - ret = func_output->output_set_dpms_async(private_output->output_backend, dpms_value); + ret = func_output->output_set_dpms_async(private_output->output_backend, dpms_value, &sync); if (ret == TDM_ERROR_NONE) { - private_output->waiting_dpms_change = 1; - TDM_INFO("output(%d) dpms async '%s' waiting", private_output->pipe, tdm_dpms_str(dpms_value)); + if (sync) { + tdm_output_dpms temp = TDM_OUTPUT_DPMS_OFF; + + tdm_output_get_dpms_internal(output, &temp); + TDM_INFO("output(%d) DPMS async '%s'(%s) done", private_output->pipe, tdm_dpms_str(dpms_value), tdm_dpms_str(temp)); + } else { + private_output->waiting_dpms_change = 1; + TDM_INFO("output(%d) DPMS async '%s' waiting", private_output->pipe, tdm_dpms_str(dpms_value)); + } } else { tdm_output_dpms temp = TDM_OUTPUT_DPMS_OFF; /* update current_dpms_value forcely */ tdm_output_get_dpms_internal(output, &temp); - TDM_ERR("output(%d) set_dpms_async failed: dpms '%s'", private_output->pipe, tdm_dpms_str(temp)); + TDM_ERR("output(%d) set DPMS async failed: dpms '%s'", private_output->pipe, tdm_dpms_str(temp)); } _pthread_mutex_unlock(&private_display->lock); @@ -1467,7 +1928,7 @@ tdm_output_get_dpms_internal(tdm_output *output, tdm_output_dpms *dpms_value) if (!func_output->output_get_dpms) { /* LCOV_EXCL_START */ *dpms_value = private_output->current_dpms_value; - TDM_WRN("not implemented!!"); + TDM_WRN("DPMS get not implemented!!"); return TDM_ERROR_NONE; /* LCOV_EXCL_STOP */ } @@ -1475,14 +1936,14 @@ tdm_output_get_dpms_internal(tdm_output *output, tdm_output_dpms *dpms_value) ret = func_output->output_get_dpms(private_output->output_backend, dpms_value); if (ret != TDM_ERROR_NONE) { /* LCOV_EXCL_START */ - TDM_ERR("output_get_dpms failed"); + TDM_ERR("output get DPMS failed"); *dpms_value = TDM_OUTPUT_DPMS_OFF; /* LCOV_EXCL_STOP */ } /* checking with backend's value */ if (*dpms_value != private_output->current_dpms_value) { - TDM_ERR("output(%d) dpms changed suddenly: %s -> %s", + TDM_ERR("output(%d) DPMS changed suddenly: %s -> %s", private_output->pipe, tdm_dpms_str(private_output->current_dpms_value), tdm_dpms_str(*dpms_value)); private_output->current_dpms_value = *dpms_value; @@ -1574,6 +2035,90 @@ tdm_output_get_hwc(tdm_output *output, tdm_error *error) return private_hwc; } +EXTERN tdm_error +tdm_output_set_mirror(tdm_output *output, tdm_output *src_output, tdm_transform transform) +{ + /* LCOV_EXCL_START */ + tdm_private_module *private_module; + tdm_func_output *func_output; + tdm_private_output *private_src_output; + + OUTPUT_FUNC_ENTRY(); + + TDM_RETURN_VAL_IF_FAIL(src_output != NULL, TDM_ERROR_INVALID_PARAMETER); + + _pthread_mutex_lock(&private_display->lock); + + private_module = private_output->private_module; + func_output = &private_module->func_output; + private_src_output = (tdm_private_output*)src_output; + + if (!(private_output->caps.capabilities & TDM_OUTPUT_CAPABILITY_MIRROR)) { + TDM_INFO("output(%d) doesn't support the mirror.", private_output->pipe); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_BAD_REQUEST; + } + + if (!func_output->output_set_mirror) { + TDM_WRN("not implemented!!"); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_NOT_IMPLEMENTED; + } + + ret = func_output->output_set_mirror(private_output->output_backend, + private_src_output->output_backend, + transform); + if (ret != TDM_ERROR_NONE) { + TDM_ERR("output(%p) fails to set MIRROR.", private_output); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_BAD_REQUEST; + } + + _pthread_mutex_unlock(&private_display->lock); + + return ret; + /* LCOV_EXCL_STOP */ +} + +tdm_error +tdm_output_unset_mirror(tdm_output *output) +{ + /* LCOV_EXCL_START */ + tdm_private_module *private_module; + tdm_func_output *func_output; + + OUTPUT_FUNC_ENTRY(); + + _pthread_mutex_lock(&private_display->lock); + + private_module = private_output->private_module; + func_output = &private_module->func_output; + + if (!(private_output->caps.capabilities & TDM_OUTPUT_CAPABILITY_MIRROR)) { + TDM_INFO("output(%d) doesn't support the mirror.", private_output->pipe); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_BAD_REQUEST; + } + + if (!func_output->output_unset_mirror) { + TDM_WRN("not implemented!!"); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_NOT_IMPLEMENTED; + } + + ret = func_output->output_unset_mirror(private_output->output_backend); + if (ret != TDM_ERROR_NONE) { + TDM_ERR("output(%p) fails to unset MIRROR.", private_output); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_BAD_REQUEST; + } + + _pthread_mutex_unlock(&private_display->lock); + + return ret; + /* LCOV_EXCL_STOP */ +} + INTERN tdm_error tdm_output_choose_commit_per_vblank_mode(tdm_private_output *private_output, int mode) { @@ -1594,4 +2139,212 @@ tdm_output_choose_commit_per_vblank_mode(tdm_private_output *private_output, int return TDM_ERROR_NONE; } + +INTERN tdm_error +tdm_voutput_destroy(tdm_voutput *voutput) +{ + tdm_private_module *private_module = NULL; + tdm_voutput *voutput_backend = NULL; + tdm_func_voutput *func_voutput = NULL; + + tdm_private_display *private_display; + tdm_private_voutput *private_voutput; + tdm_private_output *private_output; + tdm_error ret = TDM_ERROR_NONE; + TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER); + private_voutput = (tdm_private_voutput*)voutput; + private_display = private_voutput->private_display; + private_module = private_voutput->private_module; + TDM_RETURN_VAL_IF_FAIL(private_module == private_display->virtual_module, TDM_ERROR_BAD_MODULE); + + _pthread_mutex_lock(&private_display->lock); + + func_voutput = &private_module->func_voutput; + voutput_backend = private_voutput->voutput_backend; + private_output = private_voutput->private_output; + tdm_display_destroy_private_output(private_output); + LIST_DEL(&private_voutput->link); + free(private_voutput); + if (func_voutput->voutput_destroy) + ret = func_voutput->voutput_destroy(voutput_backend); + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} + +INTERN tdm_error +tdm_voutput_set_available_mode(tdm_voutput *voutput, const tdm_output_mode *modes, int count) +{ + tdm_private_display *private_display; + tdm_private_module *private_module = NULL; + tdm_private_voutput *private_voutput; + tdm_func_voutput *func_voutput = NULL; + tdm_error ret = TDM_ERROR_NONE; + + TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(modes != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(count != 0, TDM_ERROR_INVALID_PARAMETER); + + private_voutput = (tdm_private_voutput*)voutput; + private_display = private_voutput->private_display; + private_module = private_voutput->private_module; + TDM_RETURN_VAL_IF_FAIL(private_module == private_display->virtual_module, TDM_ERROR_BAD_MODULE); + + _pthread_mutex_lock(&private_display->lock); + + func_voutput = &private_module->func_voutput; + if (func_voutput->voutput_set_available_mode) + ret = func_voutput->voutput_set_available_mode(private_voutput->voutput_backend, modes, count); + else + ret = TDM_ERROR_NOT_IMPLEMENTED; + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} + +INTERN tdm_error +tdm_voutput_set_physical_size(tdm_voutput *voutput, unsigned int mmwidth, unsigned int mmheight) +{ + tdm_private_display *private_display; + tdm_private_module *private_module = NULL; + tdm_private_voutput *private_voutput; + tdm_func_voutput *func_voutput = NULL; + tdm_error ret = TDM_ERROR_NONE; + + TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(mmwidth != 0, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(mmheight != 0, TDM_ERROR_INVALID_PARAMETER); + + private_voutput = (tdm_private_voutput*)voutput; + private_display = private_voutput->private_display; + private_module = private_voutput->private_module; + TDM_RETURN_VAL_IF_FAIL(private_module == private_display->virtual_module, TDM_ERROR_BAD_MODULE); + + _pthread_mutex_lock(&private_display->lock); + + func_voutput = &private_module->func_voutput; + if (func_voutput->voutput_set_physical_size) + ret = func_voutput->voutput_set_physical_size(private_voutput->voutput_backend, mmwidth, mmheight); + else + ret = TDM_ERROR_NOT_IMPLEMENTED; + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} + +INTERN tdm_error +tdm_voutput_connect(tdm_voutput *voutput) +{ + tdm_private_display *private_display; + tdm_private_module *private_module = NULL; + tdm_private_voutput *private_voutput; + tdm_func_voutput *func_voutput = NULL; + tdm_error ret = TDM_ERROR_NONE; + + TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER); + + private_voutput = (tdm_private_voutput*)voutput; + private_display = private_voutput->private_display; + private_module = private_voutput->private_module; + TDM_RETURN_VAL_IF_FAIL(private_module == private_display->virtual_module, TDM_ERROR_BAD_MODULE); + + _pthread_mutex_lock(&private_display->lock); + + func_voutput = &private_module->func_voutput; + if (func_voutput->voutput_connect) + ret = func_voutput->voutput_connect(private_voutput->voutput_backend); + else + ret = TDM_ERROR_NOT_IMPLEMENTED; + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} + +INTERN tdm_error +tdm_voutput_disconnect(tdm_voutput *voutput) +{ + tdm_private_display *private_display; + tdm_private_module *private_module = NULL; + tdm_private_voutput *private_voutput; + tdm_func_voutput *func_voutput = NULL; + tdm_error ret = TDM_ERROR_NONE; + + TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER); + + private_voutput = (tdm_private_voutput*)voutput; + private_display = private_voutput->private_display; + private_module = private_voutput->private_module; + TDM_RETURN_VAL_IF_FAIL(private_module == private_display->virtual_module, TDM_ERROR_BAD_MODULE); + + _pthread_mutex_lock(&private_display->lock); + + func_voutput = &private_module->func_voutput; + if (func_voutput->voutput_disconnect) + ret = func_voutput->voutput_disconnect(private_voutput->voutput_backend); + else + ret = TDM_ERROR_NOT_IMPLEMENTED; + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} + +/* LCOV_EXCL_START */ +INTERN tdm_error +tdm_voutput_set_commit_func(tdm_voutput *voutput, tdm_voutput_commit_handler func) +{ + tdm_private_display *private_display; + tdm_private_module *private_module = NULL; + tdm_private_voutput *private_voutput; + tdm_func_voutput *func_voutput = NULL; + tdm_error ret = TDM_ERROR_NONE; + + TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER); + + private_voutput = (tdm_private_voutput*)voutput; + private_display = private_voutput->private_display; + private_module = private_voutput->private_module; + TDM_RETURN_VAL_IF_FAIL(private_module == private_display->virtual_module, TDM_ERROR_BAD_MODULE); + + func_voutput = &private_module->func_voutput; + if (func_voutput->voutput_set_commit_func) + ret = func_voutput->voutput_set_commit_func(private_voutput->voutput_backend, func); + else + ret = TDM_ERROR_NOT_IMPLEMENTED; + + return ret; +} + +INTERN tdm_error +tdm_voutput_commit_done(tdm_voutput *voutput) +{ + tdm_private_display *private_display; + tdm_private_module *private_module = NULL; + tdm_private_voutput *private_voutput; + tdm_func_voutput *func_voutput = NULL; + tdm_error ret = TDM_ERROR_NONE; + + TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER); + + private_voutput = (tdm_private_voutput*)voutput; + private_display = private_voutput->private_display; + private_module = private_voutput->private_module; + TDM_RETURN_VAL_IF_FAIL(private_module == private_display->virtual_module, TDM_ERROR_BAD_MODULE); + + _pthread_mutex_lock(&private_display->lock); + + func_voutput = &private_module->func_voutput; + if (func_voutput->voutput_commit_done) + ret = func_voutput->voutput_commit_done(private_voutput->voutput_backend); + else + ret = TDM_ERROR_NOT_IMPLEMENTED; + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} /* LCOV_EXCL_STOP */