X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Ftdm_output.c;h=d6e1cc35e22be34bcc69e82b44c736c1e5249b62;hb=bba097bfa37e259cd0d59e00b1f7d24db54fe5e9;hp=4a96e1632e00fae91086890a52e7d8190f1b83ad;hpb=f9c6b2e12aaad5b265609d4ab3a901b37ceb2f11;p=platform%2Fcore%2Fuifw%2Flibtdm.git diff --git a/src/tdm_output.c b/src/tdm_output.c index 4a96e16..d6e1cc3 100644 --- a/src/tdm_output.c +++ b/src/tdm_output.c @@ -135,6 +135,7 @@ tdm_output_init(tdm_private_display *private_display) 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; } @@ -428,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); @@ -500,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, @@ -996,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. @@ -1206,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; @@ -1221,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) { @@ -1248,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"); @@ -1261,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); @@ -1288,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, @@ -1296,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; @@ -1309,6 +1646,7 @@ commit_failed: LIST_DEL(&output_commit_handler->link); free(output_commit_handler); } + return ret; /* LCOV_EXCL_STOP */ } @@ -1440,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 */ } @@ -1458,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); @@ -1479,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)) { @@ -1510,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; } @@ -1527,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); @@ -1582,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 */ } @@ -1590,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; @@ -1689,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) { @@ -1710,132 +2140,196 @@ tdm_output_choose_commit_per_vblank_mode(tdm_private_output *private_output, int return TDM_ERROR_NONE; } -INTERN tdm_voutput * -tdm_voutput_create(tdm_display *dpy, const char *name, tdm_error *error) +INTERN tdm_error +tdm_voutput_destroy(tdm_voutput *voutput) { tdm_private_module *private_module = NULL; - tdm_private_module *current_module = NULL; - tdm_private_voutput *private_voutput = NULL; - tdm_private_output *private_output = NULL; - tdm_func_display *func_display = NULL; - tdm_func_voutput *func_voutput = NULL; tdm_voutput *voutput_backend = NULL; - tdm_output *output_backend = NULL; - int output_find = 0; + 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_WITH_ERROR(dpy != NULL, TDM_ERROR_INVALID_PARAMETER, NULL); - private_display = (tdm_private_display*)dpy; - private_module = private_display->virtual_module; - TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_module != NULL, TDM_ERROR_BAD_MODULE, NULL); + 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); - if (error) - *error = TDM_ERROR_NONE; + 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; - private_voutput = calloc(1, sizeof(tdm_private_voutput)); - if (!private_voutput) { - *error = TDM_ERROR_OUT_OF_MEMORY; - _pthread_mutex_unlock(&private_display->lock); - return NULL; - } + _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_display = &private_module->func_display; func_voutput = &private_module->func_voutput; - current_module = private_display->current_module; - private_display->current_module = private_module; + 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; - voutput_backend = func_display->voutput_create(private_module->bdata, name, &ret); + _pthread_mutex_unlock(&private_display->lock); - if (voutput_backend == NULL || ret != TDM_ERROR_NONE) { - TDM_ERR("voutput_create fail"); - free(private_voutput); - *error = ret; - private_display->current_module = current_module; - _pthread_mutex_unlock(&private_display->lock); - return NULL; - } - private_voutput->voutput_backend = voutput_backend; - private_voutput->private_display = private_display; - private_voutput->private_module = private_module; - LIST_INITHEAD(&private_voutput->voutput_commit_handler_list); - - output_backend = func_voutput->voutput_get_output(voutput_backend, &ret); - if (output_backend == NULL || ret != TDM_ERROR_NONE) { - TDM_ERR("voutput_get_output fail"); - free(private_voutput); - *error = ret; - if (func_voutput->voutput_destroy) - func_voutput->voutput_destroy(voutput_backend); - else - TDM_ERR("no destroy function"); - private_display->current_module = current_module; - _pthread_mutex_unlock(&private_display->lock); - return NULL; - } + return ret; +} - ret = tdm_display_update_output(private_display->current_module, output_backend); - if (ret != TDM_ERROR_NONE) { - TDM_ERR("tdm_display_update_output fail"); - free(private_voutput); - if (func_voutput->voutput_destroy) - func_voutput->voutput_destroy(voutput_backend); - else - TDM_ERR("no destroy function"); - *error = ret; - private_display->current_module = current_module; - _pthread_mutex_unlock(&private_display->lock); - return NULL; - } +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; - LIST_FOR_EACH_ENTRY(private_output, &private_module->output_list, link) { - if (private_output->output_backend == output_backend) { - output_find = 1; - break; - } - } + TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER); - if (output_find != 1) { - private_output = NULL; - free(private_voutput); - if (func_voutput->voutput_destroy) - func_voutput->voutput_destroy(voutput_backend); - else - TDM_ERR("no destroy function"); - } else { - strncpy(private_voutput->name, name, TDM_NAME_LEN); - strncpy(private_output->name, name, TDM_NAME_LEN); + 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); - private_voutput->private_output = private_output; - private_output->private_voutput = private_voutput; + _pthread_mutex_lock(&private_display->lock); - /* do not use vblank */ - tdm_output_choose_commit_per_vblank_mode(private_output, 0); + 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; - LIST_ADDTAIL(&private_voutput->link, &private_module->voutput_list); - } + _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); - private_display->current_module = current_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 private_voutput; + return ret; } +/* LCOV_EXCL_START */ INTERN tdm_error -tdm_voutput_destroy(tdm_voutput *voutput) +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_voutput *voutput_backend = 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_private_output *private_output; + 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; @@ -1844,15 +2338,13 @@ tdm_voutput_destroy(tdm_voutput *voutput) _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); + 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 */