From 319dc18780d460662b9ce398def3681f935d5a86 Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Mon, 29 Jul 2019 15:28:39 +0900 Subject: [PATCH 01/16] haltest: check calloc fail Change-Id: I4395553909638d77b870288938f6436deafbd1f9 Signed-off-by: Junkyeong Kim --- haltests/src/tc_tdm_backend_pp.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/haltests/src/tc_tdm_backend_pp.cpp b/haltests/src/tc_tdm_backend_pp.cpp index f739d96..e1087bc 100644 --- a/haltests/src/tc_tdm_backend_pp.cpp +++ b/haltests/src/tc_tdm_backend_pp.cpp @@ -196,6 +196,7 @@ bool TDMBackendPP::FindLayerUnderPrimary(void) if (tc_tdm_output_is_hwc_enable(output)) { pp_formats = (tbm_format *)calloc(1, sizeof(tbm_format) * 2); + TDM_UT_RETURN_FALSE_IF_FAIL(pp_formats != NULL); pp_formats[0] = TBM_FORMAT_NV12; pp_formats[1] = TBM_FORMAT_YUV420; dst_formats = pp_formats; @@ -239,6 +240,7 @@ bool TDMBackendPP::FindLayerOverPrimary(void) if (tc_tdm_output_is_hwc_enable(output)) { pp_formats = (tbm_format *)calloc(1, sizeof(tbm_format) * 2); + TDM_UT_RETURN_FALSE_IF_FAIL(pp_formats != NULL); pp_formats[0] = TBM_FORMAT_ARGB8888; pp_formats[1] = TBM_FORMAT_XRGB8888; dst_formats = formats; @@ -920,4 +922,4 @@ INSTANTIATE_TEST_CASE_P(TDMBackendPPParams, Values(TDM_DEFAULT_MODULE)); #endif -/* LCOV_EXCL_END */ \ No newline at end of file +/* LCOV_EXCL_END */ -- 2.7.4 From fee81d19147a62944f1cdc834d34cd2d10d62a9e Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Mon, 29 Jul 2019 21:31:40 +0900 Subject: [PATCH 02/16] Package version up to 2.9.1 Change-Id: Ia2d03d535a37891931426e763398eca537259370 --- packaging/libtdm.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libtdm.spec b/packaging/libtdm.spec index 4a0282c..377e7e3 100644 --- a/packaging/libtdm.spec +++ b/packaging/libtdm.spec @@ -2,7 +2,7 @@ %define HALTESTS_GCOV 0 Name: libtdm -Version: 2.9.0 +Version: 2.9.1 Release: 0 Summary: User Library of Tizen Display Manager Group: Development/Libraries -- 2.7.4 From f8a9700f675cfd49481d52ae31b57fd74303ba21 Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Wed, 31 Jul 2019 14:02:38 +0900 Subject: [PATCH 03/16] tdm_layer: do not free if wait vblank fail by dpms off if dpms off, the allocated layer_commit_handler memory free in tdm_output_commit_internal. so must not free this memory in _tdm_layer_commit. Change-Id: I0cdb117ccb0c16ec2cb793f873f645f1183d15c8 Signed-off-by: Junkyeong Kim --- src/tdm_layer.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/tdm_layer.c b/src/tdm_layer.c index 0885abb..22cdb47 100644 --- a/src/tdm_layer.c +++ b/src/tdm_layer.c @@ -998,7 +998,14 @@ _tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_da _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); + if (ret != TDM_ERROR_NONE) { + if (TDM_OUTPUT_DPMS_VSYNC_IS_OFF(private_output->current_dpms_value)) { + /* dpms off : the allocated memory was free in tdm_output_commit_internal */ + return ret; + } + goto commit_failed; + + } private_output->layer_waiting_vblank = 1; if (tdm_debug_module & TDM_DEBUG_COMMIT) -- 2.7.4 From 4f708d7fc50b15cc1cb105527c32503acdf13d9c Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Wed, 31 Jul 2019 15:48:40 +0900 Subject: [PATCH 04/16] haltest: init fb_damage Change-Id: I6f27a24b548d33edbd094e11ebdb27154039c9a2 Signed-off-by: Junkyeong Kim --- haltests/src/tc_tdm_output.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/haltests/src/tc_tdm_output.cpp b/haltests/src/tc_tdm_output.cpp index 75aefe4..7707c7d 100644 --- a/haltests/src/tc_tdm_output.cpp +++ b/haltests/src/tc_tdm_output.cpp @@ -280,7 +280,7 @@ tc_tdm_output_unset(tdm_display *dpy, tdm_output *output) tdm_hwc *thwc = NULL; const tdm_output_mode *mode = NULL; tdm_output_dpms dpms = TDM_OUTPUT_DPMS_OFF; - tdm_region fb_damage; + tdm_region fb_damage = {0, }; uint32_t num = 0; if (tc_tdm_output_is_hwc_enable(output)) { -- 2.7.4 From e6152855626b72fe79fc3163f6eb33d44c8b7d1d Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Wed, 31 Jul 2019 16:28:58 +0900 Subject: [PATCH 05/16] Package version up to 2.9.2 Change-Id: I0ca8435bf6da984d1761536b0ac96945df3e9b29 Signed-off-by: Junkyeong Kim --- packaging/libtdm.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libtdm.spec b/packaging/libtdm.spec index 377e7e3..afc3d6d 100644 --- a/packaging/libtdm.spec +++ b/packaging/libtdm.spec @@ -2,7 +2,7 @@ %define HALTESTS_GCOV 0 Name: libtdm -Version: 2.9.1 +Version: 2.9.2 Release: 0 Summary: User Library of Tizen Display Manager Group: Development/Libraries -- 2.7.4 From 398989bae0addb8c17264d1bee02509fafcd101d Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Tue, 6 Aug 2019 09:01:12 +0900 Subject: [PATCH 06/16] change the symbol name related to the voutput 1. The voutput is created at the tdm_display, so it belongs to the tdm_display. The creation of the voutput should be done at the display. 2. The voutput should be distinguished from the output. The functions associated with the voutput has to get the voutput symbol name. Change-Id: Ie21def171a1e8d9c43150e23347542c3a232db23 --- backends/virtual/tdm_virtual.c | 18 ++--- backends/virtual/tdm_virtual.h | 20 +++--- backends/virtual/tdm_virtual_display.c | 18 ++--- include/tdm_backend.h | 4 +- src/tdm_display.c | 115 ++++++++++++++++++++++++++++++++ src/tdm_output.c | 116 --------------------------------- src/tdm_private.h | 2 +- src/tdm_server.c | 2 +- 8 files changed, 146 insertions(+), 149 deletions(-) diff --git a/backends/virtual/tdm_virtual.c b/backends/virtual/tdm_virtual.c index f4ad7fe..580d440 100644 --- a/backends/virtual/tdm_virtual.c +++ b/backends/virtual/tdm_virtual.c @@ -65,7 +65,7 @@ tdm_virtual_init(tdm_display *dpy, tdm_error *error) virtual_func_display.display_get_outputs = virtual_display_get_outputs; virtual_func_display.display_get_fd = virtual_display_get_fd; virtual_func_display.display_handle_events = virtual_display_handle_events; - virtual_func_display.voutput_create = virtual_output_create; + virtual_func_display.display_voutput_create = virtual_display_voutput_create; memset(&virtual_func_output, 0, sizeof(virtual_func_output)); virtual_func_output.output_get_capability = virtual_output_get_capability; @@ -83,14 +83,14 @@ tdm_virtual_init(tdm_display *dpy, tdm_error *error) virtual_func_output.output_set_status_handler = virtual_output_set_status_handler; memset(&virtual_func_voutput, 0, sizeof(virtual_func_voutput)); - virtual_func_voutput.voutput_destroy = virtual_output_destroy; - virtual_func_voutput.voutput_set_available_mode = virtual_output_set_available_mode; - virtual_func_voutput.voutput_set_physical_size = virtual_output_set_physical_size; - virtual_func_voutput.voutput_connect = virtual_output_connect; - virtual_func_voutput.voutput_disconnect = virtual_output_disconnect; - virtual_func_voutput.voutput_get_output = virtual_output_get_output; - virtual_func_voutput.voutput_set_commit_func = virtual_output_set_commit_func; - virtual_func_voutput.voutput_commit_done = virtual_output_commit_done; + virtual_func_voutput.voutput_destroy = virtual_voutput_destroy; + virtual_func_voutput.voutput_set_available_mode = virtual_voutput_set_available_mode; + virtual_func_voutput.voutput_set_physical_size = virtual_voutput_set_physical_size; + virtual_func_voutput.voutput_connect = virtual_voutput_connect; + virtual_func_voutput.voutput_disconnect = virtual_voutput_disconnect; + virtual_func_voutput.voutput_get_output = virtual_voutput_get_output; + virtual_func_voutput.voutput_set_commit_func = virtual_voutput_set_commit_func; + virtual_func_voutput.voutput_commit_done = virtual_voutput_commit_done; memset(&virtual_func_layer, 0, sizeof(virtual_func_layer)); virtual_func_layer.layer_get_capability = virtual_layer_get_capability; diff --git a/backends/virtual/tdm_virtual.h b/backends/virtual/tdm_virtual.h index c85dff6..0a5c377 100644 --- a/backends/virtual/tdm_virtual.h +++ b/backends/virtual/tdm_virtual.h @@ -29,8 +29,7 @@ tdm_error virtual_display_get_capability(tdm_backend_data *bdata, tdm_caps_displ tdm_output **virtual_display_get_outputs(tdm_backend_data *bdata, int *count, tdm_error *error); tdm_error virtual_display_get_fd(tdm_backend_data *bdata, int *fd); tdm_error virtual_display_handle_events(tdm_backend_data *bdata); -tdm_output *virtual_display_output_create(tdm_backend_data *bdata, const char* name, tdm_error *error); -tdm_error virtual_display_output_destroy(tdm_backend_data *bdata, tdm_output *output); +tdm_voutput *virtual_display_voutput_create(tdm_backend_data *bdata, const char *name, tdm_error *error); tdm_error virtual_output_get_capability(tdm_output *output, tdm_caps_output *caps); tdm_layer **virtual_output_get_layers(tdm_output *output, int *count, tdm_error *error); @@ -42,17 +41,16 @@ tdm_error virtual_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value tdm_error virtual_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value); tdm_error virtual_output_set_mode(tdm_output *output, const tdm_output_mode *mode); tdm_error virtual_output_get_mode(tdm_output *output, const tdm_output_mode **mode); -tdm_error virtual_output_set_available_mode(tdm_output *output, const tdm_output_mode *modes, int count); -tdm_error virtual_output_set_physical_size(tdm_output *output, unsigned int mmwidth, unsigned int mmheight); -tdm_error virtual_output_connect(tdm_output *output); -tdm_error virtual_output_disconnect(tdm_output *output); tdm_error virtual_output_set_status_handler(tdm_output *output, tdm_output_status_handler func, void *user_data); -tdm_voutput *virtual_output_create(tdm_backend_data *bdata, const char *name, tdm_error *error); -tdm_error virtual_output_destroy(tdm_voutput *voutput); -tdm_output *virtual_output_get_output(tdm_voutput *voutput, tdm_error *error); -tdm_error virtual_output_set_commit_func(tdm_voutput *voutput, tdm_voutput_commit_handler commit_func); -tdm_error virtual_output_commit_done(tdm_voutput *voutput); +tdm_error virtual_voutput_set_available_mode(tdm_output *output, const tdm_output_mode *modes, int count); +tdm_error virtual_voutput_set_physical_size(tdm_output *output, unsigned int mmwidth, unsigned int mmheight); +tdm_error virtual_voutput_connect(tdm_output *output); +tdm_error virtual_voutput_disconnect(tdm_output *output); +tdm_error virtual_voutput_destroy(tdm_voutput *voutput); +tdm_output *virtual_voutput_get_output(tdm_voutput *voutput, tdm_error *error); +tdm_error virtual_voutput_set_commit_func(tdm_voutput *voutput, tdm_voutput_commit_handler commit_func); +tdm_error virtual_voutput_commit_done(tdm_voutput *voutput); tdm_error virtual_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps); tdm_error virtual_layer_set_info(tdm_layer *layer, tdm_info_layer *info); diff --git a/backends/virtual/tdm_virtual_display.c b/backends/virtual/tdm_virtual_display.c index e9e503f..ea3f5af 100644 --- a/backends/virtual/tdm_virtual_display.c +++ b/backends/virtual/tdm_virtual_display.c @@ -605,7 +605,7 @@ virtual_output_set_status_handler(tdm_output *output, } tdm_error -virtual_output_set_available_mode(tdm_voutput *voutput, const tdm_output_mode *modes, int count) +virtual_voutput_set_available_mode(tdm_voutput *voutput, const tdm_output_mode *modes, int count) { tdm_virtual_voutput_data *voutput_data = voutput; tdm_virtual_output_data *output_data = NULL; @@ -633,7 +633,7 @@ virtual_output_set_available_mode(tdm_voutput *voutput, const tdm_output_mode *m } tdm_error -virtual_output_set_physical_size(tdm_voutput *voutput, unsigned int mmwidth, unsigned int mmheight) +virtual_voutput_set_physical_size(tdm_voutput *voutput, unsigned int mmwidth, unsigned int mmheight) { tdm_virtual_voutput_data *voutput_data = voutput; @@ -648,7 +648,7 @@ virtual_output_set_physical_size(tdm_voutput *voutput, unsigned int mmwidth, uns } tdm_error -virtual_output_connect(tdm_voutput *voutput) +virtual_voutput_connect(tdm_voutput *voutput) { tdm_virtual_voutput_data *voutput_data = voutput; tdm_virtual_output_data *output_data = NULL; @@ -671,7 +671,7 @@ virtual_output_connect(tdm_voutput *voutput) } tdm_error -virtual_output_disconnect(tdm_voutput *voutput) +virtual_voutput_disconnect(tdm_voutput *voutput) { tdm_virtual_voutput_data *voutput_data = voutput; @@ -778,7 +778,7 @@ virtual_layer_unset_buffer(tdm_layer *layer) } tdm_voutput * -virtual_output_create(tdm_backend_data *bdata, const char *name, tdm_error *error) +virtual_display_voutput_create(tdm_backend_data *bdata, const char *name, tdm_error *error) { tdm_virtual_data *virtual_data = bdata; tdm_virtual_voutput_data *voutput_data = NULL; @@ -888,7 +888,7 @@ create_fail: } tdm_error -virtual_output_destroy(tdm_voutput *voutput) +virtual_voutput_destroy(tdm_voutput *voutput) { tdm_virtual_data *virtual_data = NULL; tdm_virtual_voutput_data *vo = NULL, *voutput_data = voutput; @@ -943,7 +943,7 @@ virtual_output_destroy(tdm_voutput *voutput) } tdm_output * -virtual_output_get_output(tdm_voutput *voutput, tdm_error *error) +virtual_voutput_get_output(tdm_voutput *voutput, tdm_error *error) { tdm_virtual_voutput_data *voutput_data = voutput; @@ -958,7 +958,7 @@ virtual_output_get_output(tdm_voutput *voutput, tdm_error *error) } tdm_error -virtual_output_set_commit_func(tdm_voutput *voutput, tdm_voutput_commit_handler commit_func) +virtual_voutput_set_commit_func(tdm_voutput *voutput, tdm_voutput_commit_handler commit_func) { tdm_virtual_voutput_data *voutput_data = voutput; @@ -970,7 +970,7 @@ virtual_output_set_commit_func(tdm_voutput *voutput, tdm_voutput_commit_handler } tdm_error -virtual_output_commit_done(tdm_voutput *voutput) +virtual_voutput_commit_done(tdm_voutput *voutput) { tdm_virtual_voutput_data *voutput_data = voutput; tdm_virtual_output_data *output_data = NULL; diff --git a/include/tdm_backend.h b/include/tdm_backend.h index c5e9e8e..f8ddd85 100644 --- a/include/tdm_backend.h +++ b/include/tdm_backend.h @@ -344,7 +344,7 @@ typedef struct _tdm_func_display { * @remark * A backend module doesn't need to implement this function if doesn't support virtual output. */ - tdm_voutput *(*voutput_create)(tdm_backend_data *bdata, const char *name, tdm_error *error); + tdm_voutput *(*display_voutput_create)(tdm_backend_data *bdata, const char *name, tdm_error *error); void (*reserved2)(void); void (*reserved3)(void); @@ -596,7 +596,7 @@ typedef struct _tdm_func_voutput { * @brief Destroy a virtual output object of a backend module * @param[in] voutput The voutput object * @return #TDM_ERROR_NONE if success. Otherwise, error value. - * @see voutput_create() function + * @see display_voutput_create() function * @remark * A backend module doesn't need to implement this function if doesn't support virtual output. */ diff --git a/src/tdm_display.c b/src/tdm_display.c index 7d2f82b..814e60c 100644 --- a/src/tdm_display.c +++ b/src/tdm_display.c @@ -989,3 +989,118 @@ tdm_module_check_abi(tdm_private_module *private_module, int abimaj, int abimin) return 1; } +INTERN tdm_voutput * +tdm_display_voutput_create(tdm_display *dpy, const char *name, tdm_error *error) +{ + 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_private_display *private_display; + 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); + + _pthread_mutex_lock(&private_display->lock); + + if (error) *error = TDM_ERROR_NONE; + + private_voutput = calloc(1, sizeof(tdm_private_voutput)); + if (!private_voutput) { + if (error) *error = TDM_ERROR_OUT_OF_MEMORY; + _pthread_mutex_unlock(&private_display->lock); + return NULL; + } + + func_display = &private_module->func_display; + func_voutput = &private_module->func_voutput; + current_module = private_display->current_module; + private_display->current_module = private_module; + + voutput_backend = func_display->display_voutput_create(private_module->bdata, name, &ret); + + if (voutput_backend == NULL || ret != TDM_ERROR_NONE) { + TDM_ERR("display_voutput_create fail"); + free(private_voutput); + if (error) *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); + if (error) *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; + } + + 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"); + if (error) *error = ret; + private_display->current_module = current_module; + _pthread_mutex_unlock(&private_display->lock); + return NULL; + } + + LIST_FOR_EACH_ENTRY(private_output, &private_module->output_list, link) { + if (private_output->output_backend == output_backend) { + output_find = 1; + break; + } + } + + 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"); + private_voutput = NULL; + } else { + strncpy(private_voutput->name, name, TDM_NAME_LEN - 1); + private_voutput->name[TDM_NAME_LEN - 1] = '\0'; + strncpy(private_output->name, name, TDM_NAME_LEN - 1); + private_output->name[TDM_NAME_LEN - 1] = '\0'; + + private_voutput->private_output = private_output; + private_output->private_voutput = private_voutput; + + /* do not use vblank */ + tdm_output_choose_commit_per_vblank_mode(private_output, 0); + + LIST_ADDTAIL(&private_voutput->link, &private_module->voutput_list); + } + + private_display->current_module = current_module; + + _pthread_mutex_unlock(&private_display->lock); + + return private_voutput; +} diff --git a/src/tdm_output.c b/src/tdm_output.c index 1a0e980..07cfa4a 100644 --- a/src/tdm_output.c +++ b/src/tdm_output.c @@ -2140,122 +2140,6 @@ 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) -{ - 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_private_display *private_display; - 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); - - _pthread_mutex_lock(&private_display->lock); - - if (error) *error = TDM_ERROR_NONE; - - private_voutput = calloc(1, sizeof(tdm_private_voutput)); - if (!private_voutput) { - if (error) *error = TDM_ERROR_OUT_OF_MEMORY; - _pthread_mutex_unlock(&private_display->lock); - return NULL; - } - - func_display = &private_module->func_display; - func_voutput = &private_module->func_voutput; - current_module = private_display->current_module; - private_display->current_module = private_module; - - voutput_backend = func_display->voutput_create(private_module->bdata, name, &ret); - - if (voutput_backend == NULL || ret != TDM_ERROR_NONE) { - TDM_ERR("voutput_create fail"); - free(private_voutput); - if (error) *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); - if (error) *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; - } - - 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"); - if (error) *error = ret; - private_display->current_module = current_module; - _pthread_mutex_unlock(&private_display->lock); - return NULL; - } - - LIST_FOR_EACH_ENTRY(private_output, &private_module->output_list, link) { - if (private_output->output_backend == output_backend) { - output_find = 1; - break; - } - } - - 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"); - private_voutput = NULL; - } else { - strncpy(private_voutput->name, name, TDM_NAME_LEN - 1); - private_voutput->name[TDM_NAME_LEN - 1] = '\0'; - strncpy(private_output->name, name, TDM_NAME_LEN - 1); - private_output->name[TDM_NAME_LEN - 1] = '\0'; - - private_voutput->private_output = private_output; - private_output->private_voutput = private_voutput; - - /* do not use vblank */ - tdm_output_choose_commit_per_vblank_mode(private_output, 0); - - LIST_ADDTAIL(&private_voutput->link, &private_module->voutput_list); - } - - private_display->current_module = current_module; - - _pthread_mutex_unlock(&private_display->lock); - - return private_voutput; -} - INTERN tdm_error tdm_voutput_destroy(tdm_voutput *voutput) { diff --git a/src/tdm_private.h b/src/tdm_private.h index b65c01e..33904da 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -261,7 +261,7 @@ tdm_monitor_server_command(tdm_display *dpy, const char *options, char *reply, i /* virtual */ tdm_voutput * -tdm_voutput_create(tdm_display *dpy, const char *name, tdm_error *error); +tdm_display_voutput_create(tdm_display *dpy, const char *name, tdm_error *error); tdm_error tdm_voutput_destroy(tdm_voutput *voutput); tdm_error diff --git a/src/tdm_server.c b/src/tdm_server.c index cfaf044..25ad51d 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -1318,7 +1318,7 @@ _tdm_server_cb_create_virtual_output(struct wl_client *client, struct wl_resourc return; } - voutput = tdm_voutput_create(private_server->private_loop->dpy, name, &ret); + voutput = tdm_display_voutput_create(private_server->private_loop->dpy, name, &ret); if (!voutput) { TDM_ERR("voutput creation fail(%s)(%d).", name, ret); wl_resource_post_error(resource, WL_DISPLAY_ERROR_NO_MEMORY, -- 2.7.4 From ceeb07117433a7aaecc0041df8162f43fd8e06de Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Fri, 9 Aug 2019 18:00:36 +0900 Subject: [PATCH 07/16] tdm_virtual: support hwc mode Change-Id: I0b8241af46e33dab41ce2ab2297871895f00519e Signed-off-by: Junkyeong Kim --- backends/virtual/Makefile.am | 2 + backends/virtual/tdm_virtual.c | 51 ++- backends/virtual/tdm_virtual.h | 168 +++++++++- backends/virtual/tdm_virtual_display.c | 181 +++++------ backends/virtual/tdm_virtual_hwc.c | 494 ++++++++++++++++++++++++++++++ backends/virtual/tdm_virtual_hwc.h | 8 + backends/virtual/tdm_virtual_hwc_window.c | 136 ++++++++ backends/virtual/tdm_virtual_hwc_window.h | 6 + src/tdm_backend.c | 20 +- src/tdm_hwc.c | 19 ++ 10 files changed, 981 insertions(+), 104 deletions(-) create mode 100644 backends/virtual/tdm_virtual_hwc.c create mode 100644 backends/virtual/tdm_virtual_hwc.h create mode 100644 backends/virtual/tdm_virtual_hwc_window.c create mode 100644 backends/virtual/tdm_virtual_hwc_window.h diff --git a/backends/virtual/Makefile.am b/backends/virtual/Makefile.am index 099b71e..d872dd9 100644 --- a/backends/virtual/Makefile.am +++ b/backends/virtual/Makefile.am @@ -10,5 +10,7 @@ libtdm_virtual_la_LIBADD = $(TDM_LIBS) $(top_builddir)/src/libtdm.la libtdm_virtual_la_SOURCES = \ tdm_virtual_display.c \ + tdm_virtual_hwc.c \ + tdm_virtual_hwc_window.c \ tdm_virtual.c diff --git a/backends/virtual/tdm_virtual.c b/backends/virtual/tdm_virtual.c index 580d440..dd64ae7 100644 --- a/backends/virtual/tdm_virtual.c +++ b/backends/virtual/tdm_virtual.c @@ -4,6 +4,8 @@ #include "tdm_virtual.h" +#define TDM_HWC 1 + static tdm_virtual_data *virtual_data; void @@ -31,6 +33,8 @@ tdm_virtual_init(tdm_display *dpy, tdm_error *error) tdm_func_display virtual_func_display; tdm_func_output virtual_func_output; tdm_func_voutput virtual_func_voutput; + tdm_func_hwc virtual_func_hwc; + tdm_func_hwc_window virtual_func_hwc_window; tdm_func_layer virtual_func_layer; tdm_error ret; @@ -56,6 +60,10 @@ tdm_virtual_init(tdm_display *dpy, tdm_error *error) return NULL; } +#if TDM_HWC + virtual_data->hwc_mode = 1; +#endif + LIST_INITHEAD(&virtual_data->voutput_list); LIST_INITHEAD(&virtual_data->output_list); LIST_INITHEAD(&virtual_data->buffer_list); @@ -74,13 +82,42 @@ tdm_virtual_init(tdm_display *dpy, tdm_error *error) virtual_func_output.output_set_vblank_handler = virtual_output_set_vblank_handler; virtual_func_output.output_commit = virtual_output_commit; virtual_func_output.output_set_commit_handler = virtual_output_set_commit_handler; - virtual_func_output.output_set_dpms = virtual_output_set_dpms; virtual_func_output.output_get_dpms = virtual_output_get_dpms; - virtual_func_output.output_set_mode = virtual_output_set_mode; virtual_func_output.output_get_mode = virtual_output_get_mode; virtual_func_output.output_set_status_handler = virtual_output_set_status_handler; + if (virtual_data->hwc_mode) { + virtual_func_output.output_get_hwc = virtual_output_get_hwc; + + memset(&virtual_func_hwc, 0, sizeof(virtual_func_hwc)); + virtual_func_hwc.hwc_create_window = virtual_hwc_create_window; + virtual_func_hwc.hwc_get_video_supported_formats = virtual_hwc_get_video_supported_formats; + virtual_func_hwc.hwc_get_video_available_properties = NULL; + virtual_func_hwc.hwc_get_capabilities = virtual_hwc_get_capabilities; + virtual_func_hwc.hwc_get_available_properties = virtual_hwc_get_available_properties; + virtual_func_hwc.hwc_get_client_target_buffer_queue = virtual_hwc_get_client_target_buffer_queue; + virtual_func_hwc.hwc_set_client_target_buffer = virtual_hwc_set_client_target_buffer; + virtual_func_hwc.hwc_validate = virtual_hwc_validate; + virtual_func_hwc.hwc_get_changed_composition_types = virtual_hwc_get_changed_composition_types; + virtual_func_hwc.hwc_accept_validation = virtual_hwc_accept_validation; + virtual_func_hwc.hwc_commit = virtual_hwc_commit; + virtual_func_hwc.hwc_set_commit_handler = virtual_hwc_set_commit_handler; + + memset(&virtual_func_hwc_window, 0, sizeof(virtual_func_hwc_window)); + virtual_func_hwc_window.hwc_window_destroy = virtual_hwc_window_destroy; + virtual_func_hwc_window.hwc_window_acquire_buffer_queue = NULL; // no need + virtual_func_hwc_window.hwc_window_release_buffer_queue = NULL; // no need + virtual_func_hwc_window.hwc_window_set_composition_type = virtual_hwc_window_set_composition_type; + virtual_func_hwc_window.hwc_window_set_buffer_damage = virtual_hwc_window_set_buffer_damage; + virtual_func_hwc_window.hwc_window_set_info = virtual_hwc_window_set_info; + virtual_func_hwc_window.hwc_window_set_buffer = virtual_hwc_window_set_buffer; + virtual_func_hwc_window.hwc_window_set_property = virtual_hwc_window_set_property; + virtual_func_hwc_window.hwc_window_get_property = virtual_hwc_window_get_property; + virtual_func_hwc_window.hwc_window_get_constraints = virtual_hwc_window_get_constraints; + virtual_func_hwc_window.hwc_window_set_name = virtual_hwc_window_set_name; + virtual_func_hwc_window.hwc_window_set_cursor_image = NULL; // no need + } memset(&virtual_func_voutput, 0, sizeof(virtual_func_voutput)); virtual_func_voutput.voutput_destroy = virtual_voutput_destroy; @@ -107,6 +144,16 @@ tdm_virtual_init(tdm_display *dpy, tdm_error *error) if (ret != TDM_ERROR_NONE) goto failed; + if (virtual_data->hwc_mode) { + ret = tdm_backend_register_func_hwc(dpy, &virtual_func_hwc); + if (ret != TDM_ERROR_NONE) + goto failed; + + ret = tdm_backend_register_func_hwc_window(dpy, &virtual_func_hwc_window); + if (ret != TDM_ERROR_NONE) + goto failed; + } + ret = tdm_backend_register_func_voutput(dpy, &virtual_func_voutput); if (ret != TDM_ERROR_NONE) goto failed; diff --git a/backends/virtual/tdm_virtual.h b/backends/virtual/tdm_virtual.h index 0a5c377..cc36d58 100644 --- a/backends/virtual/tdm_virtual.h +++ b/backends/virtual/tdm_virtual.h @@ -52,12 +52,50 @@ tdm_output *virtual_voutput_get_output(tdm_voutput *voutput, tdm_error *error); tdm_error virtual_voutput_set_commit_func(tdm_voutput *voutput, tdm_voutput_commit_handler commit_func); tdm_error virtual_voutput_commit_done(tdm_voutput *voutput); +tdm_hwc *virtual_output_get_hwc(tdm_output *output, tdm_error *error); +tdm_hwc_window *virtual_hwc_create_window(tdm_hwc *hwc, tdm_error *error); +tdm_error virtual_hwc_get_video_supported_formats(tdm_output *output, const tbm_format **formats, int *count); +tdm_error virtual_hwc_get_capabilities(tdm_hwc *hwc, tdm_hwc_capability *capabilities); +tdm_error virtual_hwc_get_available_properties(tdm_hwc *hwc, const tdm_prop **props, int *count); +tbm_surface_queue_h virtual_hwc_get_client_target_buffer_queue(tdm_hwc *hwc, tdm_error *error); +tdm_error virtual_hwc_set_client_target_buffer(tdm_hwc *hwc, tbm_surface_h buffer, tdm_region damage); +tdm_error virtual_hwc_validate(tdm_hwc *hwc, tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types); +tdm_error virtual_hwc_get_changed_composition_types(tdm_hwc *hwc, uint32_t *num_elements, tdm_hwc_window **hwc_wnds, tdm_hwc_window_composition *composition_types); +tdm_error virtual_hwc_accept_validation(tdm_hwc *hwc); +tdm_error virtual_hwc_commit(tdm_hwc *hwc, int sync, void *user_data); +tdm_error virtual_hwc_set_commit_handler(tdm_hwc *hwc, tdm_hwc_commit_handler func); + +void virtual_hwc_window_destroy(tdm_hwc_window *hwc_window); +tdm_error virtual_hwc_window_set_composition_type(tdm_hwc_window *hwc_window, tdm_hwc_window_composition composition_type); +tdm_error virtual_hwc_window_set_buffer_damage(tdm_hwc_window *hwc_window, tdm_region damage); +tdm_error virtual_hwc_window_set_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info); +tdm_error virtual_hwc_window_set_buffer(tdm_hwc_window *hwc_window, tbm_surface_h surface); +tdm_error virtual_hwc_window_set_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value value); +tdm_error virtual_hwc_window_get_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value *value); +tdm_error virtual_hwc_window_get_constraints(tdm_hwc_window *hwc_window, int *constraints); +tdm_error virtual_hwc_window_set_name(tdm_hwc_window *hwc_window, const char *name); + tdm_error virtual_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps); tdm_error virtual_layer_set_info(tdm_layer *layer, tdm_info_layer *info); tdm_error virtual_layer_get_info(tdm_layer *layer, tdm_info_layer *info); tdm_error virtual_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer); tdm_error virtual_layer_unset_buffer(tdm_layer *layer); +#define C(b,m) (((b) >> (m)) & 0xFF) +#define B(c,s) ((((unsigned int)(c)) & 0xff) << (s)) +#define FOURCC(a,b,c,d) (B(d,24) | B(c,16) | B(b,8) | B(a,0)) +#define FOURCC_STR(id) C(id,0), C(id,8), C(id,16), C(id,24) + +#define IS_RGB(format) (format == TBM_FORMAT_XRGB8888 || format == TBM_FORMAT_ARGB8888 || \ + format == TBM_FORMAT_XBGR8888 || format == TBM_FORMAT_ABGR8888) + +#define RETURN_IF_FAIL(cond) { \ + if (!(cond)) { \ + TDM_ERR("'%s' failed", #cond); \ + return; \ + } \ +} + #define RETURN_VAL_IF_FAIL(cond, val) {\ if (!(cond)) {\ TDM_ERR("'%s' failed", #cond);\ @@ -72,16 +110,140 @@ tdm_error virtual_layer_unset_buffer(tdm_layer *layer); }\ } -typedef struct _tdm_virtual_data { +typedef struct _tdm_virtual_data tdm_virtual_data; +typedef struct _tdm_virtual_output_data tdm_virtual_output_data; +typedef struct _tdm_virtual_hwc_data tdm_virtual_hwc_data; +typedef struct _tdm_virtual_hwc_window_data tdm_virtual_hwc_window_data; +typedef struct _tdm_virtual_voutput_data tdm_virtual_voutput_data; +typedef struct _tdm_virtual_layer_data tdm_virtual_layer_data; +typedef struct _tdm_virtual_event_data tdm_virtual_event_data; + +typedef enum { + TDM_VIRTUAL_EVENT_TYPE_WAIT, + TDM_VIRTUAL_EVENT_TYPE_COMMIT, + TDM_VIRTUAL_EVENT_TYPE_VCOMMIT, +} tdm_virtual_event_type; + +struct _tdm_virtual_data { tdm_display *dpy; + int hwc_mode; int pipe[2]; struct list_head voutput_list; struct list_head output_list; struct list_head buffer_list; -} tdm_virtual_data; +}; -void tdm_virtual_display_destroy_output_list(tdm_virtual_data *virtual_data); +struct _tdm_virtual_output_data { + struct list_head link; + + /* data which are fixed at initializing */ + tdm_virtual_data *virtual_data; + tdm_virtual_voutput_data *voutput_data; + + char name[TDM_NAME_LEN]; /* output name */ + uint32_t pipe; + tdm_output_type connector_type; + struct list_head layer_list; + tdm_virtual_layer_data *primary_layer; + + tdm_output_dpms dpms; + + /* not fixed data below */ + tdm_output_vblank_handler vblank_func; + tdm_output_commit_handler commit_func; + void *commit_user_data; + + tdm_output_conn_status status; + tdm_output_status_handler status_func; + void *status_user_data; + + int mode_changed; + const tdm_output_mode *current_mode; + + tdm_event_loop_source *timer; + unsigned int timer_waiting; + struct list_head timer_event_list; + + /* hwc data */ + int hwc_enable; + tdm_virtual_hwc_data *hwc_data; +}; + +struct _tdm_virtual_hwc_data { + tdm_virtual_hwc_window_data *target_hwc_window; + + int need_validate; + int need_target_window; + int need_set_crtc; + + int target_window_zpos; + tdm_virtual_output_data *output_data; + struct list_head hwc_window_list; + + tdm_hwc_commit_handler commit_func; +}; + +struct _tdm_virtual_hwc_window_data { + struct list_head link; + + tdm_virtual_hwc_data *hwc_data; + + tdm_hwc_window_info info; + tbm_surface_h surface; + tdm_hwc_window_composition client_type; + tdm_hwc_window_composition validated_type; + int lzpos; + + char name[TDM_NAME_LEN]; +}; + +struct _tdm_virtual_voutput_data { + struct list_head link; + + /* data which are fixed at initializing */ + tdm_virtual_data *virtual_data; + tdm_virtual_output_data *output_data; + + char name[TDM_NAME_LEN]; /* output name */ + + tdm_voutput_commit_handler vcommit_func; + + tdm_output_mode *output_modes; + int mode_count; + + unsigned int mmwidth; + unsigned int mmheight; +}; + +struct _tdm_virtual_layer_data { + struct list_head link; + + /* data which are fixed at initializing */ + tdm_virtual_data *virtual_data; + tdm_virtual_output_data *output_data; + tdm_layer_capability capabilities; + int zpos; + + /* not fixed data below */ + tdm_info_layer info; + int info_changed; + + tbm_surface_h display_buffer; + int display_buffer_changed; +}; + +struct _tdm_virtual_event_data { + struct list_head link; + + tdm_virtual_event_type type; + tdm_virtual_output_data *output_data; + void *user_data; +}; + +void tdm_virtual_display_destroy_output_list(tdm_virtual_data *virtual_data); +tdm_virtual_layer_data *virtual_output_data_get_layer_data(tdm_virtual_output_data *output_data, int layer_zpos); +tdm_error virtual_hwc_initailize_target_window(tdm_hwc *hwc_data, int width, int height); #endif /* _TDM_VIRTUAL_H_ */ diff --git a/backends/virtual/tdm_virtual_display.c b/backends/virtual/tdm_virtual_display.c index ea3f5af..89f0769 100644 --- a/backends/virtual/tdm_virtual_display.c +++ b/backends/virtual/tdm_virtual_display.c @@ -4,98 +4,12 @@ #include "tdm_virtual.h" -typedef struct _tdm_virtual_output_data tdm_virtual_output_data; -typedef struct _tdm_virtual_voutput_data tdm_virtual_voutput_data; -typedef struct _tdm_virtual_layer_data tdm_virtual_layer_data; -typedef struct _tdm_virtual_event_data tdm_virtual_event_data; - -typedef enum { - TDM_VIRTUAL_EVENT_TYPE_WAIT, - TDM_VIRTUAL_EVENT_TYPE_COMMIT, - TDM_VIRTUAL_EVENT_TYPE_VCOMMIT, -} tdm_virtual_event_type; - -struct _tdm_virtual_event_data { - struct list_head link; - - tdm_virtual_event_type type; - tdm_virtual_output_data *output_data; - void *user_data; -}; - -struct _tdm_virtual_output_data { - struct list_head link; - - /* data which are fixed at initializing */ - tdm_virtual_data *virtual_data; - tdm_virtual_voutput_data *voutput_data; - - char name[TDM_NAME_LEN]; /* output name */ - uint32_t pipe; - tdm_output_type connector_type; - struct list_head layer_list; - tdm_virtual_layer_data *primary_layer; - - tdm_output_dpms dpms; - - /* not fixed data below */ - tdm_output_vblank_handler vblank_func; - tdm_output_commit_handler commit_func; - void *commit_user_data; - - tdm_output_conn_status status; - tdm_output_status_handler status_func; - void *status_user_data; - - int mode_changed; - const tdm_output_mode *current_mode; - - tdm_event_loop_source *timer; - unsigned int timer_waiting; - struct list_head timer_event_list; -}; - -struct _tdm_virtual_voutput_data { - struct list_head link; - - /* data which are fixed at initializing */ - tdm_virtual_data *virtual_data; - tdm_virtual_output_data *output_data; - - char name[TDM_NAME_LEN]; /* output name */ - - tdm_voutput_commit_handler vcommit_func; - - tdm_output_mode *output_modes; - int mode_count; - - unsigned int mmwidth; - unsigned int mmheight; -}; - - -struct _tdm_virtual_layer_data { - struct list_head link; - - /* data which are fixed at initializing */ - tdm_virtual_data *virtual_data; - tdm_virtual_output_data *output_data; - tdm_layer_capability capabilities; - int zpos; - - /* not fixed data below */ - tdm_info_layer info; - int info_changed; - - tbm_surface_h display_buffer; - int display_buffer_changed; -}; - static void _tdm_virtual_display_cb_event(tdm_virtual_output_data *output_data, tdm_virtual_event_data *event_data, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec) { tdm_virtual_voutput_data *voutput_data = NULL; + tdm_virtual_hwc_data *hwc_data; switch (event_data->type) { case TDM_VIRTUAL_EVENT_TYPE_WAIT: @@ -103,8 +17,20 @@ _tdm_virtual_display_cb_event(tdm_virtual_output_data *output_data, tdm_virtual_ output_data->vblank_func(output_data, sequence, tv_sec, tv_usec, event_data->user_data); break; case TDM_VIRTUAL_EVENT_TYPE_COMMIT: - if (output_data->commit_func) - output_data->commit_func(output_data, sequence, tv_sec, tv_usec, event_data->user_data); + if (output_data->hwc_enable) { + hwc_data = output_data->hwc_data; + if (!hwc_data) { + TDM_ERR("no hwc_data"); + break; + } + + if (hwc_data->commit_func) + hwc_data->commit_func(hwc_data, sequence, + tv_sec, tv_usec, + event_data->user_data); + } else + if (output_data->commit_func) + output_data->commit_func(output_data, sequence, tv_sec, tv_usec, event_data->user_data); break; case TDM_VIRTUAL_EVENT_TYPE_VCOMMIT: voutput_data = output_data->voutput_data; @@ -343,6 +269,9 @@ virtual_output_get_capability(tdm_output *output, tdm_caps_output *caps) caps->prop_count = 0; + if (output_data->virtual_data->hwc_mode) + caps->capabilities |= TDM_OUTPUT_CAPABILITY_HWC; + return TDM_ERROR_NONE; failed_get: memset(caps, 0, sizeof(tdm_caps_output)); @@ -361,6 +290,13 @@ virtual_output_get_layers(tdm_output *output, int *count, tdm_error *error) RETURN_VAL_IF_FAIL(output_data, NULL); RETURN_VAL_IF_FAIL(count, NULL); + if (output_data->virtual_data->hwc_mode) { + TDM_INFO("layers aren't supported in HWC mode"); + *count = 0; + ret = TDM_ERROR_NONE; + goto failed_get; + } + *count = 0; LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) (*count)++; @@ -566,10 +502,20 @@ tdm_error virtual_output_set_mode(tdm_output *output, const tdm_output_mode *mode) { tdm_virtual_output_data *output_data = output; + tdm_error ret = TDM_ERROR_NONE; RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER); RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER); + /* create or replace the target_window when the output mode is set */ + if (output_data->virtual_data->hwc_mode) { + ret = virtual_hwc_initailize_target_window(output_data->hwc_data, mode->hdisplay, mode->vdisplay); + if (ret != TDM_ERROR_NONE) { + TDM_ERR("create target hwc window failed (%d)", ret); + return ret; + } + } + output_data->current_mode = mode; output_data->mode_changed = 1; @@ -604,6 +550,45 @@ virtual_output_set_status_handler(tdm_output *output, return TDM_ERROR_NONE; } +tdm_hwc * +virtual_output_get_hwc(tdm_output *output, tdm_error *error) +{ + tdm_virtual_hwc_data *hwc_data = NULL; + tdm_virtual_output_data *output_data = output; + + if (!output_data) { + TDM_ERR("invalid params"); + if (error) + *error = TDM_ERROR_INVALID_PARAMETER; + return NULL; + } + + if (output_data->hwc_data) { + TDM_INFO("hwc_data already exists"); + if (error) + *error = TDM_ERROR_NONE; + return output_data->hwc_data; + } + + hwc_data = calloc(1, sizeof(tdm_virtual_hwc_data)); + if (!hwc_data) { + TDM_ERR("alloc failed"); + if (error) + *error = TDM_ERROR_OUT_OF_MEMORY; + return NULL; + } + hwc_data->output_data = output_data; + + LIST_INITHEAD(&hwc_data->hwc_window_list); + + output_data->hwc_data = hwc_data; + + if (error) + *error = TDM_ERROR_NONE; + + return hwc_data; +} + tdm_error virtual_voutput_set_available_mode(tdm_voutput *voutput, const tdm_output_mode *modes, int count) { @@ -875,6 +860,9 @@ virtual_display_voutput_create(tdm_backend_data *bdata, const char *name, tdm_er TDM_DBG("virtual output create(%s)(%p)(%p)", output_data->name, voutput_data, output_data); + if (output_data->virtual_data->hwc_mode) + output_data->hwc_enable = 1; + return voutput_data; create_fail: @@ -1005,3 +993,18 @@ virtual_voutput_commit_done(tdm_voutput *voutput) return TDM_ERROR_NONE; } +tdm_virtual_layer_data * +virtual_output_data_get_layer_data(tdm_virtual_output_data *output_data, int layer_zpos) +{ + tdm_virtual_layer_data *l = NULL; + + RETURN_VAL_IF_FAIL(output_data, NULL); + + LIST_FOR_EACH_ENTRY(l, &output_data->layer_list, link) { + if (l->zpos == layer_zpos) + return l; + } + + return NULL; +} + diff --git a/backends/virtual/tdm_virtual_hwc.c b/backends/virtual/tdm_virtual_hwc.c new file mode 100644 index 0000000..42031cc --- /dev/null +++ b/backends/virtual/tdm_virtual_hwc.c @@ -0,0 +1,494 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "tdm_virtual.h" + +#define MIN_WIDTH 32 + +#define NUM_LAYERS 1 +#define NUM_BUFFERS 3 + +#define NUM_UI_LAYERS 1 + +#define ZPOS_MAX 1 +#define ZPOS_0 0 +#define ZPOS_NONE -999 + +tbm_format hwc_window_video_formats[] = { + TBM_FORMAT_ARGB8888, + TBM_FORMAT_XRGB8888, +}; + +const char * +_comp_to_str(tdm_hwc_window_composition composition_type) +{ + if (composition_type == TDM_HWC_WIN_COMPOSITION_CLIENT) + return "CLIENT"; + else if (composition_type == TDM_HWC_WIN_COMPOSITION_DEVICE) + return "DEVICE"; + else if (composition_type == TDM_HWC_WIN_COMPOSITION_CURSOR) + return "CURSOR"; + else if (composition_type == TDM_HWC_WIN_COMPOSITION_VIDEO) + return "VIDEO"; + else if (composition_type == TDM_HWC_WIN_COMPOSITION_NONE) + return "SKIP"; + + return "unknown"; +} + +static void +_print_validate_result(tdm_virtual_hwc_data *hwc_data, tdm_hwc_window **composited_wnds, uint32_t num_wnds) +{ + tdm_virtual_hwc_window_data *hwc_window_data = NULL; + int i; + + for (i = 0; i < num_wnds; i++) { + hwc_window_data = composited_wnds[i]; + switch (hwc_window_data->validated_type) { + case TDM_HWC_WIN_COMPOSITION_CLIENT: + TDM_DBG(" window(%p) %s -> %s : lzpos(%d) -- {%s} on TARGET WINDOW", hwc_window_data, + _comp_to_str(hwc_window_data->client_type), + _comp_to_str(hwc_window_data->validated_type), + hwc_data->target_hwc_window->lzpos, + hwc_window_data->name ? hwc_window_data->name : "NONE"); + break; + case TDM_HWC_WIN_COMPOSITION_DEVICE: + case TDM_HWC_WIN_COMPOSITION_VIDEO: + case TDM_HWC_WIN_COMPOSITION_CURSOR: + case TDM_HWC_WIN_COMPOSITION_NONE: + TDM_DBG(" window(%p) %s -> %s : lzpos(%d) -- {%s}", hwc_window_data, + _comp_to_str(hwc_window_data->client_type), + _comp_to_str(hwc_window_data->validated_type), + hwc_window_data->lzpos, + hwc_window_data->name ? hwc_window_data->name : "NONE"); + break; + default: + break; + } + } +} + +static tbm_surface_queue_h +_virtual_hwc_window_get_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error) +{ + tdm_virtual_hwc_window_data *hwc_window_data = NULL; + tbm_surface_queue_h tqueue = NULL; + int width, height; + tbm_format format; + + if (error) + *error = TDM_ERROR_INVALID_PARAMETER; + + RETURN_VAL_IF_FAIL(hwc_window != NULL, NULL); + + hwc_window_data = hwc_window; + + width = hwc_window_data->info.src_config.size.h; + height = hwc_window_data->info.src_config.size.v; + format = hwc_window_data->info.src_config.format; + + tqueue = tbm_surface_queue_create(NUM_BUFFERS, width, height, format, TBM_BO_SCANOUT); + if (error) + *error = TDM_ERROR_OPERATION_FAILED; + RETURN_VAL_IF_FAIL(tqueue != NULL, NULL); + + if (error) + *error = TDM_ERROR_NONE; + + return tqueue; +} + +static tdm_error +_virtual_hwc_layer_attach_window(tdm_virtual_layer_data *layer_data, tdm_virtual_hwc_window_data *hwc_window_data) +{ + tdm_error ret = TDM_ERROR_NONE; + + RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_OPERATION_FAILED); + + if (hwc_window_data == NULL || hwc_window_data->surface == NULL) { + if (layer_data->display_buffer) + ret = virtual_layer_unset_buffer(layer_data); + RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret); + } else { + ret = virtual_layer_set_info((tdm_layer *)layer_data, (tdm_info_layer *)&(hwc_window_data->info)); + RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret); + RETURN_VAL_IF_FAIL(hwc_window_data->surface != NULL, TDM_ERROR_INVALID_PARAMETER); + ret = virtual_layer_set_buffer(layer_data, hwc_window_data->surface); + RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret); + } + + return ret; +} + +static tdm_error +_virtual_hwc_prepare_commit(tdm_virtual_hwc_data *hwc_data) +{ + tdm_virtual_layer_data *layer_data = NULL; + int use_layers_zpos[NUM_LAYERS] = {0,}; + int lzpos = 0; + + /* set target hwc window to the layer */ + if (hwc_data->need_target_window) { + layer_data = virtual_output_data_get_layer_data(hwc_data->output_data, hwc_data->target_hwc_window->lzpos); + _virtual_hwc_layer_attach_window(layer_data, hwc_data->target_hwc_window); + use_layers_zpos[hwc_data->target_hwc_window->lzpos] = 1; + } + + /* unset the unused layers */ + for (lzpos = 0; lzpos < NUM_LAYERS; lzpos++) { + if (use_layers_zpos[lzpos]) + continue; + + layer_data = virtual_output_data_get_layer_data(hwc_data->output_data, lzpos); + if (!layer_data) + continue; + + _virtual_hwc_layer_attach_window(layer_data, NULL); + } + + /* for debug */ + for (lzpos = NUM_LAYERS -1 ; lzpos >= 0; lzpos--) { + if (use_layers_zpos[lzpos]) + TDM_INFO(" lzpos(%d) : %s", lzpos, use_layers_zpos[lzpos] ? "SET" : "UNSET"); + } + + return TDM_ERROR_NONE; +} + +/* assign the validated_type to the composited_wnds + * assign the layer_zpos to the composited_wnds + */ +static void +_virtual_hwc_apply_policy(tdm_virtual_hwc_data *hwc_data , tdm_hwc_window **composited_wnds, uint32_t num_wnds) +{ + tdm_virtual_hwc_window_data *hwc_window_data = NULL; + tdm_virtual_hwc_window_data **composited_list = NULL; + int i = 0; + + composited_list = (tdm_virtual_hwc_window_data **)composited_wnds; + + /* initialize the validated_types */ + LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) { + if (hwc_window_data->validated_type != TDM_HWC_WIN_COMPOSITION_NONE) + hwc_window_data->validated_type = TDM_HWC_WIN_COMPOSITION_NONE; + } + + /* use the target_window to commit when there is no window. */ + if (num_wnds == 0) { + hwc_data->need_target_window = 1; + hwc_data->target_hwc_window->lzpos = ZPOS_0; + return; + } + + /* use onyl target_window */ + for (i = 0; i < num_wnds; i++) { + composited_list[i]->validated_type = TDM_HWC_WIN_COMPOSITION_CLIENT; + composited_list[i]->lzpos = ZPOS_NONE; + } + + hwc_data->need_target_window = 1; + hwc_data->target_hwc_window->lzpos = ZPOS_0; +} + +static int +_virtual_hwc_get_changed_number(tdm_virtual_hwc_data *hwc_data) +{ + int num = 0; + tdm_virtual_hwc_window_data *hwc_window_data = NULL; + + LIST_FOR_EACH_ENTRY(hwc_window_data, &hwc_data->hwc_window_list, link) { + if (hwc_window_data->client_type == TDM_HWC_WIN_COMPOSITION_NONE) + continue; + + if (hwc_window_data->client_type != hwc_window_data->validated_type) + num++; + } + + return num; +} + +tdm_hwc_window * +_virtual_hwc_create_window(tdm_hwc *hwc, tdm_hwc_window_info *info, tdm_error *error) +{ + tdm_virtual_hwc_data *hwc_data = hwc; + tdm_virtual_hwc_window_data *hwc_window_data = NULL; + + if (error) + *error = TDM_ERROR_NONE; + + if (!hwc_data) { + TDM_ERR("invalid params"); + if (error) + *error = TDM_ERROR_INVALID_PARAMETER; + return NULL; + } + + hwc_window_data = calloc(1, sizeof(tdm_virtual_hwc_window_data)); + if (!hwc_window_data) { + TDM_ERR("alloc failed"); + if (error) + *error = TDM_ERROR_OUT_OF_MEMORY; + return NULL; + } + + hwc_window_data->hwc_data = hwc_data; + + if (info) + memcpy(&hwc_window_data->info, info, sizeof(tdm_hwc_window_info)); + + LIST_INITHEAD(&hwc_window_data->link); + + return hwc_window_data; +} + +tdm_hwc_window * +virtual_hwc_create_window(tdm_hwc *hwc, tdm_error *error) +{ + tdm_virtual_hwc_data *hwc_data = hwc; + tdm_virtual_hwc_window_data *hwc_window_data = NULL; + + RETURN_VAL_IF_FAIL(hwc_data, NULL); + + hwc_window_data = _virtual_hwc_create_window(hwc_data, NULL, error); + RETURN_VAL_IF_FAIL(hwc_window_data, NULL); + + LIST_ADDTAIL(&hwc_window_data->link, &hwc_data->hwc_window_list); + + TDM_DBG("hwc_window(%p) create", hwc_window_data); + if (error) + *error = TDM_ERROR_NONE; + + return hwc_window_data; +} + +tdm_error +virtual_hwc_get_video_supported_formats(tdm_hwc *hwc, const tbm_format **formats, int *count) +{ + RETURN_VAL_IF_FAIL(hwc != NULL, TDM_ERROR_INVALID_PARAMETER); + RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER); + RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER); + + // TODO: fix these formats. + *formats = hwc_window_video_formats; + *count = sizeof(hwc_window_video_formats) / sizeof(tbm_format); + + return TDM_ERROR_NONE; +} + +tdm_error +virtual_hwc_get_capabilities(tdm_hwc *hwc, tdm_hwc_capability *capabilities) +{ + RETURN_VAL_IF_FAIL(hwc != NULL, TDM_ERROR_INVALID_PARAMETER); + RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER); + + *capabilities = 0; + + return TDM_ERROR_NONE; +} + +tdm_error +virtual_hwc_get_available_properties(tdm_hwc *hwc, const tdm_prop **props, int *count) +{ + tdm_virtual_hwc_data *hwc_data = hwc; + + RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER); + RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER); + RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER); + + *props = NULL; + *count = 0; + + return TDM_ERROR_NONE; +} + +tbm_surface_queue_h +virtual_hwc_get_client_target_buffer_queue(tdm_hwc *hwc, tdm_error *error) +{ + tdm_virtual_hwc_data *hwc_data = hwc; + tbm_surface_queue_h tqueue = NULL; + + if (error) + *error = TDM_ERROR_INVALID_PARAMETER; + + RETURN_VAL_IF_FAIL(hwc_data != NULL, NULL); + + if (hwc_data->target_hwc_window == NULL) { + if (error) + *error = TDM_ERROR_OPERATION_FAILED; + return NULL; + } + + tqueue = _virtual_hwc_window_get_tbm_buffer_queue(hwc_data->target_hwc_window, error); + RETURN_VAL_IF_FAIL(tqueue, NULL); + + if (error) + *error = TDM_ERROR_NONE; + + return tqueue; +} + +tdm_error +virtual_hwc_set_client_target_buffer(tdm_hwc *hwc, tbm_surface_h buffer, tdm_region damage) +{ + tdm_virtual_hwc_data *hwc_data = hwc; + tdm_error err; + + RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER); + RETURN_VAL_IF_FAIL(hwc_data->target_hwc_window != NULL, TDM_ERROR_OPERATION_FAILED); + + TDM_INFO(" ==============Set Target Buffer Virtual================================="); + + err = virtual_hwc_window_set_buffer(hwc_data->target_hwc_window, buffer); + RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err); + + err = virtual_hwc_window_set_buffer_damage(hwc_data->target_hwc_window, damage); + RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err); + + return TDM_ERROR_NONE; +} + +tdm_error +virtual_hwc_validate(tdm_hwc *hwc, tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types) +{ + tdm_virtual_hwc_data *hwc_data = hwc; + + RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER); + RETURN_VAL_IF_FAIL(num_types != NULL, TDM_ERROR_INVALID_PARAMETER); + + TDM_DBG(" ==============Validate Virtual================================="); + + _virtual_hwc_apply_policy(hwc_data, composited_wnds, num_wnds); + + *num_types = _virtual_hwc_get_changed_number(hwc_data); + + _print_validate_result(hwc_data, composited_wnds, num_wnds); + + return TDM_ERROR_NONE; +} + +tdm_error +virtual_hwc_get_changed_composition_types(tdm_hwc *hwc, uint32_t *num_elements, + tdm_hwc_window **hwc_wnds, tdm_hwc_window_composition *composition_types) +{ + tdm_virtual_hwc_data *hwc_data = hwc; + tdm_virtual_hwc_window_data *hwc_window_data = NULL; + int num = 0; + + RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER); + RETURN_VAL_IF_FAIL(num_elements != NULL, TDM_ERROR_INVALID_PARAMETER); + + if ((hwc_wnds == NULL) || (composition_types == NULL)) { + *num_elements = _virtual_hwc_get_changed_number(hwc_data); + return TDM_ERROR_NONE; + } + + LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) { + if (hwc_window_data->client_type == TDM_HWC_WIN_COMPOSITION_NONE) + continue; + + if (num >= *num_elements) + break; + + if (hwc_window_data->client_type != hwc_window_data->validated_type) { + composition_types[num] = hwc_window_data->validated_type; + hwc_wnds[num] = hwc_window_data; + num++; + } + } + + /* set real num of changed composition types */ + *num_elements = num; + + return TDM_ERROR_NONE; +} + +tdm_error +virtual_hwc_accept_validation(tdm_hwc *hwc) +{ + tdm_virtual_hwc_data *hwc_data = hwc; + tdm_error ret = TDM_ERROR_NONE; + + RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER); + RETURN_VAL_IF_FAIL(hwc_data->output_data != NULL, TDM_ERROR_INVALID_PARAMETER); + + TDM_DBG(" ==============Accept Changes Done Virtual================================="); + + ret = _virtual_hwc_prepare_commit(hwc_data); + RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret); + + return TDM_ERROR_NONE; +} + +tdm_error +virtual_hwc_commit(tdm_hwc *hwc, int sync, void *user_data) +{ + tdm_virtual_hwc_data *hwc_data = hwc; + tdm_virtual_output_data *output_data = NULL; + tdm_error ret; + + RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER); + + output_data = hwc_data->output_data; + RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER); + + TDM_INFO(" ==============COMMIT Virtual================================="); + + ret = virtual_output_commit(output_data, sync, user_data); + RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret); + + return TDM_ERROR_NONE; +} + +tdm_error +virtual_hwc_set_commit_handler(tdm_hwc *hwc, tdm_hwc_commit_handler func) +{ + tdm_virtual_hwc_data *hwc_data = hwc; + + RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER); + RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER); + + hwc_data->commit_func = func; + + return TDM_ERROR_NONE; +} + +tdm_error +virtual_hwc_initailize_target_window(tdm_hwc *hwc, int width, int height) +{ + tdm_hwc_window_info info = {0}; + tdm_error ret = TDM_ERROR_NONE; + tdm_virtual_hwc_window_data *target_hwc_window; + tdm_virtual_hwc_data *hwc_data = hwc; + + RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER); + + info.dst_pos.x = 0; + info.dst_pos.y = 0; + info.dst_pos.h = height; + info.dst_pos.w = width; + + info.src_config.pos.x = 0; + info.src_config.pos.y = 0; + info.src_config.pos.h = height; + info.src_config.pos.w = width; + + info.src_config.size.h = width; + info.src_config.size.v = height; + info.src_config.format = TBM_FORMAT_ARGB8888; + + target_hwc_window = _virtual_hwc_create_window(hwc_data, &info, &ret); + if (ret != TDM_ERROR_NONE) { + TDM_ERR("create target hwc window failed (%d)", ret); + return TDM_ERROR_OPERATION_FAILED; + } + + if (hwc_data->target_hwc_window) + virtual_hwc_window_destroy(hwc_data->target_hwc_window); + + hwc_data->target_hwc_window = target_hwc_window; + hwc_data->need_set_crtc = 1; + + return TDM_ERROR_NONE; +} diff --git a/backends/virtual/tdm_virtual_hwc.h b/backends/virtual/tdm_virtual_hwc.h new file mode 100644 index 0000000..12bb05f --- /dev/null +++ b/backends/virtual/tdm_virtual_hwc.h @@ -0,0 +1,8 @@ +#ifndef _TDM_VIRTUAL_HWC_H_ +#define _TDM_VIRTUAL_HWC_H_ + +#include "tdm_virtual.h" + +tdm_error virtual_hwc_initailize_target_window(tdm_virtual_hwc_data *hwc_data, int width, int height); + +#endif /* _TDM_VIRTUAL_HWC_H_ */ diff --git a/backends/virtual/tdm_virtual_hwc_window.c b/backends/virtual/tdm_virtual_hwc_window.c new file mode 100644 index 0000000..81a9094 --- /dev/null +++ b/backends/virtual/tdm_virtual_hwc_window.c @@ -0,0 +1,136 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "tdm_virtual.h" + +void +virtual_hwc_window_destroy(tdm_hwc_window *hwc_window) +{ + tdm_virtual_hwc_window_data *hwc_window_data = hwc_window; + + RETURN_IF_FAIL(hwc_window_data != NULL); + + LIST_DEL(&hwc_window_data->link); + + free(hwc_window_data); +} + +tdm_error +virtual_hwc_window_set_composition_type(tdm_hwc_window *hwc_window, + tdm_hwc_window_composition comp_type) +{ + tdm_virtual_hwc_window_data *hwc_window_data = hwc_window; + tdm_virtual_hwc_data *hwc_data = hwc_window_data->hwc_data; + + RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER); + RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER); + + /* change the client_type when it is different from one which has before */ + if (hwc_window_data->client_type == comp_type) + return TDM_ERROR_NONE; + + hwc_window_data->client_type = comp_type; + + return TDM_ERROR_NONE; +} + +tdm_error +virtual_hwc_window_set_buffer_damage(tdm_hwc_window *hwc_window, tdm_region damage) +{ + tdm_virtual_hwc_window_data *hwc_window_data = hwc_window; + + RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER); + + //TODO:: + + return TDM_ERROR_NONE; +} + +tdm_error +virtual_hwc_window_set_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info) +{ + tdm_virtual_hwc_window_data *hwc_window_data = hwc_window; + tdm_virtual_hwc_data *hwc_data; + + RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER); + hwc_data = hwc_window_data->hwc_data; + RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER); + RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER); + + if (!memcmp(&hwc_window_data->info, info, sizeof(tdm_hwc_window_info))) + return TDM_ERROR_NONE; + + hwc_window_data->info = *info; + + return TDM_ERROR_NONE; +} + +tdm_error +virtual_hwc_window_set_buffer(tdm_hwc_window *hwc_window, tbm_surface_h surface) +{ + tdm_virtual_hwc_window_data *hwc_window_data = hwc_window; + tdm_error err = TDM_ERROR_OPERATION_FAILED; + + RETURN_VAL_IF_FAIL(hwc_window_data != NULL, err); + + if (hwc_window_data->surface == surface) + return TDM_ERROR_NONE; + + hwc_window_data->surface = surface; + + return TDM_ERROR_NONE; +} + +tdm_error +virtual_hwc_window_set_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value value) +{ + tdm_virtual_hwc_window_data *hwc_window_data = hwc_window; + + RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER); + + //TODO: + + return TDM_ERROR_NONE; +} + +tdm_error +virtual_hwc_window_get_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value *value) +{ + tdm_virtual_hwc_window_data *hwc_window_data = hwc_window; + + RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER); + + //TODO: + + return TDM_ERROR_NONE; +} + +tdm_error +virtual_hwc_window_get_constraints(tdm_hwc_window *hwc_window, int *constraints) +{ + tdm_virtual_hwc_window_data *hwc_window_data = hwc_window; + + RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER); + RETURN_VAL_IF_FAIL(constraints != NULL, TDM_ERROR_INVALID_PARAMETER); + + // no constraints + *constraints = 0; + + return TDM_ERROR_NONE; +} + +tdm_error +virtual_hwc_window_set_name(tdm_hwc_window *hwc_window, const char *name) +{ + tdm_virtual_hwc_window_data *hwc_window_data = hwc_window; + + RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER); + + if (!name) + return TDM_ERROR_NONE; + + snprintf(hwc_window_data->name, TDM_NAME_LEN, "%s", name); + + return TDM_ERROR_NONE; +} diff --git a/backends/virtual/tdm_virtual_hwc_window.h b/backends/virtual/tdm_virtual_hwc_window.h new file mode 100644 index 0000000..e698090 --- /dev/null +++ b/backends/virtual/tdm_virtual_hwc_window.h @@ -0,0 +1,6 @@ +#ifndef _TDM_VIRTUAL_HWC_WINDOW_H_ +#define _TDM_VIRTUAL_HWC_WINDOW_H_ + +#include "tdm_virtual.h" + +#endif /* _TDM_VIRTUAL_HWC_WINDOW_H_ */ diff --git a/src/tdm_backend.c b/src/tdm_backend.c index 12f6a2d..b0d1576 100644 --- a/src/tdm_backend.c +++ b/src/tdm_backend.c @@ -159,7 +159,7 @@ tdm_backend_register_func_layer(tdm_display *dpy, tdm_func_layer *func_layer) EXTERN tdm_error tdm_backend_register_func_hwc(tdm_display *dpy, tdm_func_hwc *func_hwc) { - tdm_backend_module *module; +// tdm_backend_module *module; TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED); @@ -168,10 +168,10 @@ tdm_backend_register_func_hwc(tdm_display *dpy, tdm_func_hwc *func_hwc) TDM_RETURN_VAL_IF_FAIL(func_hwc != NULL, TDM_ERROR_INVALID_PARAMETER); assert(private_display->current_module); - - module = private_display->current_module->module_data; - if (_check_abi_version(module, 2, 0) < 0) - return TDM_ERROR_BAD_MODULE; +// TODO : temp erase module check for virtual +// module = private_display->current_module->module_data; +// if (_check_abi_version(module, 2, 0) < 0) +// return TDM_ERROR_BAD_MODULE; private_display->current_module->func_hwc = *func_hwc; @@ -181,7 +181,7 @@ tdm_backend_register_func_hwc(tdm_display *dpy, tdm_func_hwc *func_hwc) EXTERN tdm_error tdm_backend_register_func_hwc_window(tdm_display *dpy, tdm_func_hwc_window *func_hwc_window) { - tdm_backend_module *module; +// tdm_backend_module *module; TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED); @@ -190,10 +190,10 @@ tdm_backend_register_func_hwc_window(tdm_display *dpy, tdm_func_hwc_window *func TDM_RETURN_VAL_IF_FAIL(func_hwc_window != NULL, TDM_ERROR_INVALID_PARAMETER); assert(private_display->current_module); - - module = private_display->current_module->module_data; - if (_check_abi_version(module, 2, 0) < 0) - return TDM_ERROR_BAD_MODULE; +// TODO : temp erase module check for virtual +// module = private_display->current_module->module_data; +// if (_check_abi_version(module, 2, 0) < 0) +// return TDM_ERROR_BAD_MODULE; private_display->current_module->func_hwc_window = *func_hwc_window; diff --git a/src/tdm_hwc.c b/src/tdm_hwc.c index 65f232c..f3537bc 100644 --- a/src/tdm_hwc.c +++ b/src/tdm_hwc.c @@ -528,6 +528,8 @@ tdm_hwc_commit(tdm_hwc *hwc, int sync, tdm_hwc_commit_handler func, void *user_d tdm_private_module *private_module; tdm_func_hwc *func_hwc = NULL; tdm_private_hwc_commit_handler *hwc_commit_handler = NULL; + tdm_private_voutput *private_voutput = NULL; + tdm_private_voutput_commit_handler *voutput_commit_handler = NULL; HWC_FUNC_ENTRY(); @@ -558,6 +560,14 @@ tdm_hwc_commit(tdm_hwc *hwc, int sync, tdm_hwc_commit_handler func, void *user_d if (tdm_debug_module & TDM_DEBUG_COMMIT) TDM_INFO("hwc(%d) commit", private_hwc->index); + if (private_module == private_display->virtual_module) { + if (!private_output->private_voutput) { + TDM_ERR("virtual module but don't have voutput"); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_BAD_MODULE; + } + } + if (!private_hwc->regist_commit_cb) { private_hwc->regist_commit_cb = 1; ret = func_hwc->hwc_set_commit_handler(private_hwc->hwc_backend, _tdm_hwc_cb_commit); @@ -595,6 +605,15 @@ tdm_hwc_commit(tdm_hwc *hwc, int sync, tdm_hwc_commit_handler func, void *user_d hwc_commit_handler->user_data = user_data; hwc_commit_handler->owner_tid = syscall(SYS_gettid); + if (private_module == private_display->virtual_module) { + private_voutput = private_output->private_voutput; + + 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_hwc->display_target_buffer; + } + } + ret = func_hwc->hwc_commit(private_hwc->hwc_backend, sync, hwc_commit_handler); TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed); -- 2.7.4 From 856fe332170337c9c52583b4757e2a4a47ddc3b5 Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Tue, 13 Aug 2019 14:02:54 +0900 Subject: [PATCH 08/16] Package version up to 2.9.3 Change-Id: I046ee4436411ee9cdc64f54a545952ea7ce1dfcf Signed-off-by: Junkyeong Kim --- packaging/libtdm.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libtdm.spec b/packaging/libtdm.spec index afc3d6d..dacbdee 100644 --- a/packaging/libtdm.spec +++ b/packaging/libtdm.spec @@ -2,7 +2,7 @@ %define HALTESTS_GCOV 0 Name: libtdm -Version: 2.9.2 +Version: 2.9.3 Release: 0 Summary: User Library of Tizen Display Manager Group: Development/Libraries -- 2.7.4 From b564ac8bf2379f3c60c64e179c5697b4391d33d8 Mon Sep 17 00:00:00 2001 From: Yunmi Ha Date: Thu, 22 Aug 2019 02:30:29 +0000 Subject: [PATCH 09/16] Revert "tizen: Add additional unit for "unified" user session" This reverts commit c912cbe6b33ba30309388719316775e5fc44555a. We've optimized systemd-user without unified system/session. So, we revert the patch for unified system/session. Change-Id: I75ea2b0f4e6762d23cc31c0814953ccb69866e69 --- packaging/libtdm.spec | 10 ---------- service/tdm-socket-user@.path | 9 --------- service/tdm-socket-user@.service | 15 --------------- 3 files changed, 34 deletions(-) delete mode 100644 service/tdm-socket-user@.path delete mode 100644 service/tdm-socket-user@.service diff --git a/packaging/libtdm.spec b/packaging/libtdm.spec index dacbdee..8288f58 100644 --- a/packaging/libtdm.spec +++ b/packaging/libtdm.spec @@ -98,10 +98,6 @@ rm -rf %{buildroot} install -m 644 service/tdm-socket-user.service %{buildroot}%{_unitdir_user} install -m 644 service/tdm-socket-user.path %{buildroot}%{_unitdir_user} -%__mkdir_p %{buildroot}%{_unitdir} -install -m 644 service/tdm-socket-user@.service %{buildroot}%{_unitdir} -install -m 644 service/tdm-socket-user@.path %{buildroot}%{_unitdir} - %remove_docs @@ -109,13 +105,9 @@ install -m 644 service/tdm-socket-user@.path %{buildroot}%{_unitdir} %__mkdir_p %{_unitdir_user}/basic.target.wants ln -sf ../tdm-socket-user.path %{_unitdir_user}/basic.target.wants/ -%__mkdir_p %{_unitdir}/user-basic@.target.wants -ln -sf ../tdm-socket-user@.path %{_unitdir}/user-basic@.target.wants/ - %post -p /sbin/ldconfig %postun -p /sbin/ldconfig rm -f %{_unitdir_user}/basic.target.wants/tdm-socket-user.path -rm -f %{_unitdir}/user-basic@.target.wants/tdm-socket-user@.path %files %manifest %{name}.manifest @@ -127,8 +119,6 @@ rm -f %{_unitdir}/user-basic@.target.wants/tdm-socket-user@.path %attr(750,root,root) %{_bindir}/tdm-monitor %{_unitdir_user}/tdm-socket-user.path %{_unitdir_user}/tdm-socket-user.service -%{_unitdir}/tdm-socket-user@.path -%{_unitdir}/tdm-socket-user@.service %files devel %manifest %{name}.manifest diff --git a/service/tdm-socket-user@.path b/service/tdm-socket-user@.path deleted file mode 100644 index e71810c..0000000 --- a/service/tdm-socket-user@.path +++ /dev/null @@ -1,9 +0,0 @@ -[Unit] -PartOf=userlogin@%i.target -DefaultDependencies=no -After=systemd-logind.service -After=systemd-logind.service systemd-logind.service -Description=Wait for tdm-socket - -[Path] -PathExists=/run/tdm-socket diff --git a/service/tdm-socket-user@.service b/service/tdm-socket-user@.service deleted file mode 100644 index 4fca44d..0000000 --- a/service/tdm-socket-user@.service +++ /dev/null @@ -1,15 +0,0 @@ -[Unit] -PartOf=userlogin@%i.target -After=systemd-logind.service -After=display-manager.service systemd-logind.service -Description=Creating a link file for user to access tdm-socket -DefaultDependencies=no -Before=starter@%i.service - -[Service] -User=%i -Environment=DBUS_SESSION_BUS_ADDRESS=kernel:path=/sys/fs/kdbus/%i-user/bus;unix:path=/run/user/%i/bus -Environment=XDG_RUNTIME_DIR=/run/user/%i -SmackProcessLabel=User -Type=oneshot -ExecStart=/usr/bin/sh -c "while [ ! -e /run/tdm-socket ] ; do /usr/bin/sleep .1 ; done ;/usr/bin/ln -s /run/tdm-socket /run/user/%i/" -- 2.7.4 From 7b38a8ccd48715b5147e3c7388ee3815ea1e17ae Mon Sep 17 00:00:00 2001 From: Changyeon Lee Date: Thu, 29 Aug 2019 19:48:16 +0900 Subject: [PATCH 10/16] add stdout log in tdm_display_init Change-Id: I971cabd91d5ff977a18bb5cd8869245cfbe0704b --- include/tdm_log.h | 14 ++++++++++++++ src/tdm.c | 21 ++++++++++++--------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/include/tdm_log.h b/include/tdm_log.h index de56386..0a9bbf3 100644 --- a/include/tdm_log.h +++ b/include/tdm_log.h @@ -116,6 +116,20 @@ extern unsigned int tdm_log_debug_level; } \ } while (0) +#define TDM_INIT_INFO(fmt, args...) \ + do { \ + if (tdm_log_debug_level >= TDM_LOG_LEVEL_INFO) { \ + struct timespec ts; \ + clock_gettime(CLOCK_MONOTONIC, &ts); \ + tdm_log_printf(TDM_LOG_LEVEL_INFO, "[%5d.%06d][%d][%s %d]"fmt, \ + (int)ts.tv_sec, (int)ts.tv_nsec / 1000, \ + (int)syscall(SYS_gettid), __FUNCTION__, __LINE__, ##args); \ + tdm_log_print(TDM_LOG_LEVEL_INFO, "[%5d.%06d][%d][%s %d]"fmt, \ + (int)ts.tv_sec, (int)ts.tv_nsec / 1000, \ + (int)syscall(SYS_gettid), __FUNCTION__, __LINE__, ##args); \ + } \ + } while (0) + #define TDM_NEVER_GET_HERE() TDM_WRN("** NEVER GET HERE **") #define TDM_DEPRECATED(str) \ do { \ diff --git a/src/tdm.c b/src/tdm.c index f20bfa4..c7289e8 100644 --- a/src/tdm.c +++ b/src/tdm.c @@ -805,7 +805,7 @@ _tdm_display_setup(tdm_private_display *private_display) tdm_output **outputs; int i, count = 0; - TDM_INFO("loading a %s backend", TDM_DUMMY_MODULE); + TDM_INIT_INFO("loading a %s backend", TDM_DUMMY_MODULE); ret = _tdm_display_load_module_with_file(private_display, TDM_DUMMY_MODULE); TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, failed_update); TDM_GOTO_IF_FAIL(private_display->dummy_module != NULL, failed_update); @@ -825,7 +825,7 @@ _tdm_display_setup(tdm_private_display *private_display) virtual = tdm_config_get_int(TDM_CONFIG_KEY_GENERAL_VIRTUAL_OUTPUT, 0); if (virtual) { - TDM_INFO("loading a %s backend", TDM_VIRTUAL_MODULE); + TDM_INIT_INFO("loading a %s backend", TDM_VIRTUAL_MODULE); ret = _tdm_display_load_module_with_file(private_display, TDM_VIRTUAL_MODULE); TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, failed_update); TDM_GOTO_IF_FAIL(private_display->virtual_module != NULL, failed_update); @@ -1035,7 +1035,9 @@ _tdm_display_load_module_with_file(tdm_private_display *private_display, /* We don't care if backend_data is NULL or not. It's up to backend. */ TDM_TRACE_BEGIN("TDM_Init_Backend"); stamp = tdm_helper_get_time(); + TDM_INIT_INFO("init backend"); bdata = module_data->init((tdm_display *)private_display, &ret); + TDM_INIT_INFO("init backend done"); TDM_DBG("backend init() time: %.3f ms", (tdm_helper_get_time() - stamp) * 1000.0); TDM_TRACE_END(); @@ -1067,7 +1069,7 @@ _tdm_display_load_module_with_file(tdm_private_display *private_display, LIST_ADDTAIL(&private_module->link, &private_display->module_list); - TDM_INFO("Success to load '%s' module", module_data->name); + TDM_INIT_INFO("Success to load '%s' module", module_data->name); return TDM_ERROR_NONE; failed_load: @@ -1097,12 +1099,12 @@ _tdm_display_load_modules(tdm_private_display *private_display) arg = strtok_r(temp, TDM_CONFIG_DELIM, &end); while (arg) { - TDM_INFO("loading a %s backend", arg); + TDM_INIT_INFO("loading a %s backend", arg); ret = _tdm_display_load_module_with_file(private_display, arg); if (ret == TDM_ERROR_NONE) - TDM_INFO("%s backend loading success", arg); + TDM_INIT_INFO("%s backend loading success", arg); else - TDM_INFO("%s backend loading failed", arg); + TDM_INIT_INFO("%s backend loading failed", arg); arg = strtok_r(NULL, TDM_CONFIG_DELIM, &end); } @@ -1194,7 +1196,7 @@ tdm_display_init(tdm_error *error) goto failed_event; stamp2 = tdm_helper_get_time(); - TDM_INFO("event loop init time: %.3f ms", (stamp2 - stamp1) * 1000.0); + TDM_INIT_INFO("event loop init time: %.3f ms", (stamp2 - stamp1) * 1000.0); stamp1 = stamp2; ret = tdm_vblank_init(private_display); @@ -1222,7 +1224,7 @@ tdm_display_init(tdm_error *error) goto failed_load; stamp2 = tdm_helper_get_time(); - TDM_INFO("loading backend time: %.3f ms", (stamp2 - stamp1) * 1000.0); + TDM_INIT_INFO("loading backend time: %.3f ms", (stamp2 - stamp1) * 1000.0); stamp1 = stamp2; #ifdef INIT_BUFMGR @@ -1245,6 +1247,7 @@ tdm_display_init(tdm_error *error) TDM_TRACE_BEGIN("TDM_Update_Display"); ret = _tdm_display_setup(private_display); + TDM_INIT_INFO("updating display"); TDM_TRACE_END(); if (ret != TDM_ERROR_NONE) goto failed_update; @@ -1284,7 +1287,7 @@ tdm_display_init(tdm_error *error) _pthread_mutex_unlock(&private_display->lock); pthread_mutex_unlock(&gLock); - TDM_INFO("init time: %.3f ms", (tdm_helper_get_time() - start) * 1000.0); + TDM_INIT_INFO("init time: %.3f ms", (tdm_helper_get_time() - start) * 1000.0); return (tdm_display *)private_display; -- 2.7.4 From 4f5b50a0e94c14988f634fd289af4d0d68dd9da5 Mon Sep 17 00:00:00 2001 From: Changyeon Lee Date: Fri, 30 Aug 2019 15:32:54 +0900 Subject: [PATCH 11/16] Package version up to 2.9.4 Change-Id: Id5280b3bbce59ac1200d4afdf5a7ccbf81202215 --- packaging/libtdm.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libtdm.spec b/packaging/libtdm.spec index 8288f58..42569cd 100644 --- a/packaging/libtdm.spec +++ b/packaging/libtdm.spec @@ -2,7 +2,7 @@ %define HALTESTS_GCOV 0 Name: libtdm -Version: 2.9.3 +Version: 2.9.4 Release: 0 Summary: User Library of Tizen Display Manager Group: Development/Libraries -- 2.7.4 From d141eb55873b9e26972c30bb6aa90160553ee16a Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Fri, 6 Sep 2019 16:56:31 +0900 Subject: [PATCH 12/16] tdm_hwc: support tdm-monitor -fps function Change-Id: I4f11ab53483058283717c4b592cb44b989c1daec Signed-off-by: Junkyeong Kim --- src/tdm_hwc.c | 18 ++++++++++++++++++ src/tdm_private_types.h | 3 +++ 2 files changed, 21 insertions(+) diff --git a/src/tdm_hwc.c b/src/tdm_hwc.c index f3537bc..f6d1808 100644 --- a/src/tdm_hwc.c +++ b/src/tdm_hwc.c @@ -109,6 +109,24 @@ _tdm_hwc_thread_cb_commit(tdm_private_display *private_display, void *object, TDM_INFO("handler(%p)", hwc_commit_handler); } + /* LCOV_EXCL_START */ + if (private_display->print_fps) { + double curr = tdm_helper_get_time(); + if (private_hwc->fps_stamp == 0) { + private_hwc->fps_stamp = curr; + } else if ((curr - private_hwc->fps_stamp) > 1.0) { + TDM_INFO("hwc(%p,%d) fps: %d", + private_hwc, private_hwc->index, private_hwc->fps_count); + private_hwc->fps_count = 0; + private_hwc->fps_stamp = curr; + } else + private_hwc->fps_count++; + } else if (private_hwc->fps_stamp != 0) { + private_hwc->fps_stamp = 0; + private_hwc->fps_count = 0; + } + /* LCOV_EXCL_STOP */ + if (hwc_commit_handler->func) { _pthread_mutex_unlock(&private_display->lock); hwc_commit_handler->func(private_hwc, diff --git a/src/tdm_private_types.h b/src/tdm_private_types.h index dfea22a..a778e25 100644 --- a/src/tdm_private_types.h +++ b/src/tdm_private_types.h @@ -329,6 +329,9 @@ struct _tdm_private_hwc { tdm_hwc *hwc_backend; tbm_surface_h display_target_buffer; + + double fps_stamp; + unsigned int fps_count; }; struct _tdm_private_hwc_window { -- 2.7.4 From 67b749a49811a43bfec0cfbb1cdd4a631ae44c00 Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Tue, 10 Sep 2019 14:13:55 +0900 Subject: [PATCH 13/16] Package version up to 2.9.5 Change-Id: Ic7c5cac389615a28df93542df59943ff4bc08298 Signed-off-by: Junkyeong Kim --- packaging/libtdm.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libtdm.spec b/packaging/libtdm.spec index 42569cd..e9d6257 100644 --- a/packaging/libtdm.spec +++ b/packaging/libtdm.spec @@ -2,7 +2,7 @@ %define HALTESTS_GCOV 0 Name: libtdm -Version: 2.9.4 +Version: 2.9.5 Release: 0 Summary: User Library of Tizen Display Manager Group: Development/Libraries -- 2.7.4 From d077eef0042ab7dbc6857ce8e2ec367b3fe90b2e Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Wed, 2 Oct 2019 13:15:04 +0900 Subject: [PATCH 14/16] tdm_output: change log 'dpms' to 'DPMS' Change-Id: I8a2d53631455b9cfef9dd0d799227662408bd567 Signed-off-by: Junkyeong Kim --- src/tdm_output.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/tdm_output.c b/src/tdm_output.c index 07cfa4a..d6e1cc3 100644 --- a/src/tdm_output.c +++ b/src/tdm_output.c @@ -433,7 +433,7 @@ tdm_output_cb_dpms(tdm_output *output_backend, tdm_output_dpms dpms, void *user_ 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); @@ -1778,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 */ } @@ -1796,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); @@ -1849,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; } @@ -1866,12 +1866,12 @@ 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, &sync); @@ -1880,10 +1880,10 @@ tdm_output_set_dpms_async(tdm_output *output, tdm_output_dpms dpms_value) 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)); + 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)); + 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; @@ -1891,7 +1891,7 @@ tdm_output_set_dpms_async(tdm_output *output, tdm_output_dpms dpms_value) /* 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); @@ -1928,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 */ } @@ -1936,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; -- 2.7.4 From 8a3c14ca5ee3453cbf84a9bb8cef5531ffdf6309 Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Wed, 2 Oct 2019 13:16:10 +0900 Subject: [PATCH 15/16] Package version up to 2.9.6 Change-Id: If141ff350ea08c7c8124fba7e2af36f84a395165 Signed-off-by: Junkyeong Kim --- packaging/libtdm.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libtdm.spec b/packaging/libtdm.spec index e9d6257..db7f805 100644 --- a/packaging/libtdm.spec +++ b/packaging/libtdm.spec @@ -2,7 +2,7 @@ %define HALTESTS_GCOV 0 Name: libtdm -Version: 2.9.5 +Version: 2.9.6 Release: 0 Summary: User Library of Tizen Display Manager Group: Development/Libraries -- 2.7.4 From 7a105d2256426d58cb253253cd0ee1acb5054d5e Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Wed, 16 Oct 2019 19:04:28 +0900 Subject: [PATCH 16/16] tdm_hwc: make hwc_vblank set/unset function if set hwc vblank, use vblank instead of hwc commit handler. Change-Id: I9329473bb21dec6cee84fe60cd7e33eca80c2875 Signed-off-by: Junkyeong Kim --- src/tdm_hwc.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++-- src/tdm_private.h | 4 ++ src/tdm_private_types.h | 1 + 3 files changed, 127 insertions(+), 3 deletions(-) diff --git a/src/tdm_hwc.c b/src/tdm_hwc.c index f6d1808..3131ebd 100644 --- a/src/tdm_hwc.c +++ b/src/tdm_hwc.c @@ -70,6 +70,8 @@ TDM_RETURN_IF_FAIL(private_output != NULL); \ private_display = private_output->private_display +static int hwc_use_vblank; +static unsigned int hwc_vblank_fps; static tdm_private_hwc_window * _tdm_hwc_find_private_hwc_window(tdm_private_hwc *private_hwc, tdm_hwc_window *hwc_window_backend) @@ -152,6 +154,9 @@ _tdm_hwc_cb_commit(tdm_hwc *hwc_backend, unsigned int sequence, tdm_thread_cb_hwc_commit hwc_commit; tdm_error ret; + if (hwc_commit_handler && hwc_commit_handler->use_vblank) + return; + if (hwc_commit_handler) private_hwc = hwc_commit_handler->private_hwc; else @@ -171,6 +176,96 @@ _tdm_hwc_cb_commit(tdm_hwc *hwc_backend, unsigned int sequence, TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); } +static void +_tdm_hwc_got_wait_vblank(unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, void *user_data) +{ + tdm_private_hwc_commit_handler *hwc_commit_handler = user_data; + tdm_private_hwc *private_hwc; + tdm_thread_cb_hwc_commit hwc_commit; + + private_hwc = hwc_commit_handler->private_hwc; + private_hwc->private_output->layer_waiting_vblank = 0; + + memset(&hwc_commit, 0, sizeof hwc_commit); + hwc_commit.base.type = TDM_THREAD_CB_HWC_COMMIT; + hwc_commit.base.length = sizeof hwc_commit; + hwc_commit.base.object_stamp = private_hwc->stamp; + hwc_commit.base.data = hwc_commit_handler; + hwc_commit.base.sync = 0; + hwc_commit.sequence = sequence; + hwc_commit.tv_sec = tv_sec; + hwc_commit.tv_usec = tv_usec; + + _tdm_hwc_thread_cb_commit(private_hwc->private_output->private_display, private_hwc, &hwc_commit.base, user_data); +} + +static void +_tdm_hwc_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_hwc_commit_handler *hwc_commit_handler = user_data; + tdm_private_output *private_output = NULL; + tdm_private_display *private_display; + + if (!hwc_commit_handler->use_vblank) + return; + + TDM_RETURN_IF_FAIL(hwc_commit_handler != NULL); + + private_output = hwc_commit_handler->private_hwc->private_output; + TDM_RETURN_IF_FAIL(private_output != NULL); + + private_display = private_output->private_display; + + _pthread_mutex_lock(&private_display->lock); + + _tdm_hwc_got_wait_vblank(sequence, tv_sec, tv_usec, user_data); + + _pthread_mutex_unlock(&private_display->lock); +} + +static tdm_error +_tdm_hwc_vblank(tdm_private_hwc *private_hwc, tdm_private_hwc_commit_handler *hwc_commit_handler) +{ + tdm_private_display *private_display; + tdm_private_output *private_output; + tdm_error ret = TDM_ERROR_NONE; + + private_output = private_hwc->private_output; + TDM_RETURN_VAL_IF_FAIL(private_output != NULL, TDM_ERROR_INVALID_PARAMETER); + private_display = private_output->private_display; + + 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_RETURN_VAL_IF_FAIL(private_output->vblank != NULL, TDM_ERROR_OPERATION_FAILED); + } + + if (!private_output->layer_waiting_vblank) { + ret = tdm_vblank_set_fps(private_output->vblank, hwc_vblank_fps); + if (ret != TDM_ERROR_NONE) + goto done; + + /* 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_hwc_cb_wait_vblank, hwc_commit_handler); + _pthread_mutex_lock(&private_display->lock); + if (ret != TDM_ERROR_NONE) { + if (!TDM_OUTPUT_DPMS_VSYNC_IS_OFF(private_output->current_dpms_value)) + goto done; + } + + hwc_commit_handler->use_vblank = 1; + private_output->layer_waiting_vblank = 1; + } + +done: + return ret; +} + INTERN tdm_error tdm_hwc_init(tdm_private_display *private_display) { @@ -179,6 +274,20 @@ tdm_hwc_init(tdm_private_display *private_display) return TDM_ERROR_NONE; } +INTERN void +tdm_hwc_set_vblank(unsigned int fps) +{ + hwc_use_vblank = 1; + hwc_vblank_fps = fps; +} + +INTERN void +tdm_hwc_unset_vblank(void) +{ + hwc_use_vblank = 0; + hwc_vblank_fps = 0; +} + EXTERN tdm_hwc_window * tdm_hwc_create_window(tdm_hwc *hwc, tdm_error *error) { @@ -635,9 +744,19 @@ tdm_hwc_commit(tdm_hwc *hwc, int sync, tdm_hwc_commit_handler func, void *user_d ret = func_hwc->hwc_commit(private_hwc->hwc_backend, sync, hwc_commit_handler); TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed); - if (tdm_debug_module & TDM_DEBUG_COMMIT) - TDM_INFO("hwc(%d) backend commit: handle(%p) func(%p) user_data(%p)", - private_hwc->index, hwc_commit_handler, func, user_data); + if (hwc_use_vblank) { + ret = _tdm_hwc_vblank(private_hwc, hwc_commit_handler); + if (ret == TDM_ERROR_NONE) { + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("hwc(%d) backend commit: wait vblank handle(%p) func(%p) user_data(%p)", + private_hwc->index, hwc_commit_handler, func, user_data); + } else + goto commit_failed; + } else { + if (tdm_debug_module & TDM_DEBUG_COMMIT) + TDM_INFO("hwc(%d) backend commit: handle(%p) func(%p) user_data(%p)", + private_hwc->index, hwc_commit_handler, func, user_data); + } _pthread_mutex_unlock(&private_display->lock); diff --git a/src/tdm_private.h b/src/tdm_private.h index 33904da..e8e3c08 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -184,6 +184,10 @@ tdm_pp_destroy_internal(tdm_private_pp *private_pp); tdm_error tdm_hwc_init(tdm_private_display *private_display); +void +tdm_hwc_set_vblank(unsigned int fps); +void +tdm_hwc_unset_vblank(void); tdm_hwc_window * tdm_hwc_window_create_internal(tdm_private_hwc *private_hwc, tdm_error *error); void diff --git a/src/tdm_private_types.h b/src/tdm_private_types.h index a778e25..bbc83cd 100644 --- a/src/tdm_private_types.h +++ b/src/tdm_private_types.h @@ -501,6 +501,7 @@ struct _tdm_private_hwc_commit_handler { void *user_data; pid_t owner_tid; + int use_vblank; }; struct _tdm_private_layer_commit_handler { -- 2.7.4