From 9c947c16a27e74229f34c29093dce9822ae63e5b Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Thu, 19 Jul 2018 16:42:23 +0900 Subject: [PATCH 01/16] virtual output: Remove definition, 'tdm_client_output_set_buffer_queue'. Change-Id: Ia3dec1f59ed6afe316b8ff37b551f9bf8ea548f6 --- client/tdm_client.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index 4c05811..acd832e 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -1803,16 +1803,6 @@ tdm_client_voutput_get_client_output(tdm_client_voutput *voutput, tdm_error *err } tdm_error -tdm_client_output_set_buffer_queue(tdm_client_output *output, void *queue, void *func) -{ - TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); - TDM_RETURN_VAL_IF_FAIL(queue != NULL, TDM_ERROR_INVALID_PARAMETER); - TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER); - - return TDM_ERROR_NONE; -} - -tdm_error tdm_client_output_get_available_modes(tdm_client_output *output, tdm_client_output_mode **modes, int *count) { TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); -- 2.7.4 From 3f08108dd38965411ce789e7751210f5a95162cb Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Thu, 19 Jul 2018 17:59:03 +0900 Subject: [PATCH 02/16] virtual output: fix build break. Remove redefinition, 'tdm_server_voutput_info'. Change-Id: I277e3a14cd31e3db712c9005420e811f88528318 --- src/tdm_server.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/tdm_server.c b/src/tdm_server.c index ed4ddff..3ce52cb 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -72,6 +72,13 @@ typedef struct _tdm_server_voutput_info { struct wl_resource *resource; tdm_output *output; struct list_head output_list; + + tdm_output_conn_status status; + struct + { + int count; + tdm_output_mode *modes; + } available_modes; } tdm_server_voutput_info; typedef struct _tdm_server_vblank_info { @@ -703,16 +710,6 @@ _tdm_server_cb_create_output(struct wl_client *client, struct wl_resource *resou } } -typedef struct _tdm_server_voutput_info { - tdm_private_server *private_server; - tdm_output_conn_status status; - struct - { - int count; - tdm_output_mode *modes; - } available_modes; -} tdm_server_voutput_info; - static void _tdm_voutput_cb_destroy(struct wl_client *client, struct wl_resource *resource) { wl_resource_destroy(resource); -- 2.7.4 From ffd3cecfa5117811d4016bff1b39307139765703 Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Fri, 20 Jul 2018 18:48:41 +0900 Subject: [PATCH 03/16] virtual: add set_available_mode & set_phsycal_size function Change-Id: I9f0e0115ab64786207db49f934d72a0d7c7e8ffc Signed-off-by: Junkyeong Kim --- backends/virtual/tdm_virtual.c | 2 + backends/virtual/tdm_virtual.h | 2 + backends/virtual/tdm_virtual_display.c | 125 ++++++++++++++++++++++----------- include/tdm_backend.h | 4 ++ src/tdm_display.c | 17 ++++- src/tdm_output.c | 48 +++++++++++++ src/tdm_private.h | 5 ++ 7 files changed, 160 insertions(+), 43 deletions(-) diff --git a/backends/virtual/tdm_virtual.c b/backends/virtual/tdm_virtual.c index 9c9e4dd..426feaf 100644 --- a/backends/virtual/tdm_virtual.c +++ b/backends/virtual/tdm_virtual.c @@ -75,6 +75,8 @@ tdm_virtual_init(tdm_display *dpy, tdm_error *error) virtual_func_output.output_set_commit_handler = virtual_output_set_commit_handler; 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_available_mode = virtual_output_set_available_mode; + virtual_func_output.output_set_physical_size = virtual_output_set_physical_size; 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 f1cdf91..1ad4550 100644 --- a/backends/virtual/tdm_virtual.h +++ b/backends/virtual/tdm_virtual.h @@ -40,6 +40,8 @@ tdm_error virtual_output_commit(tdm_output *output, int sync, void *user_data); tdm_error virtual_output_set_commit_handler(tdm_output *output, tdm_output_commit_handler func); 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_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 9bf7363..2288a72 100644 --- a/backends/virtual/tdm_virtual_display.c +++ b/backends/virtual/tdm_virtual_display.c @@ -28,7 +28,7 @@ struct _tdm_virtual_output_data { tdm_virtual_data *virtual_data; uint32_t pipe; - tdm_output_mode *output_mode; + tdm_output_mode *output_modes; int mode_count; tdm_output_type connector_type; struct list_head layer_list; @@ -122,14 +122,14 @@ _tdm_virtual_display_wait_vblank(tdm_virtual_output_data *output_data, int inter unsigned int ms; RETURN_VAL_IF_FAIL(output_data->timer != NULL, TDM_ERROR_OPERATION_FAILED); - RETURN_VAL_IF_FAIL(output_data->output_mode->vrefresh > 0, TDM_ERROR_OPERATION_FAILED); + RETURN_VAL_IF_FAIL(output_data->current_mode->vrefresh > 0, TDM_ERROR_OPERATION_FAILED); if (output_data->timer_waiting) { LIST_ADDTAIL(&event_data->link, &output_data->timer_event_list); return TDM_ERROR_NONE; } - ms = ((double)1000.0 / output_data->output_mode->vrefresh) * interval; + ms = ((double)1000.0 / output_data->current_mode->vrefresh) * interval; ret = tdm_event_loop_source_timer_update(output_data->timer, ms); if (ret != TDM_ERROR_NONE) @@ -214,7 +214,7 @@ tdm_virtual_display_destroy_output_list(tdm_virtual_data *virtual_data) if (o->timer) tdm_event_loop_source_remove(o->timer); - free(o->output_mode); + free(o->output_modes); free(o); } } @@ -241,29 +241,29 @@ tdm_virtual_display_create_output_list(tdm_virtual_data *virtual_data) output_data->connector_type = TDM_OUTPUT_TYPE_Unknown; output_data->status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED; - output_data->output_mode = calloc(1, sizeof(tdm_output_mode)); - if (!output_data->output_mode) { + output_data->output_modes = calloc(1, sizeof(tdm_output_mode)); + if (!output_data->output_modes) { TDM_ERR("alloc failed"); free(output_data); ret = TDM_ERROR_OUT_OF_MEMORY; goto failed_create; } - snprintf(output_data->output_mode->name, TDM_NAME_LEN, "640x480"); - output_data->output_mode->vrefresh = 30; - output_data->output_mode->clock = 25200; - output_data->output_mode->hdisplay = 640; - output_data->output_mode->hsync_start = 656; - output_data->output_mode->hsync_end = 752; - output_data->output_mode->htotal = 800; - output_data->output_mode->hskew = 0; - output_data->output_mode->vdisplay = 480; - output_data->output_mode->vsync_start = 490; - output_data->output_mode->vsync_end = 492; - output_data->output_mode->vtotal = 525; - output_data->output_mode->vscan = 0; - output_data->output_mode->flags = 0; - output_data->output_mode->type = 0; + snprintf(output_data->output_modes->name, TDM_NAME_LEN, "640x480"); + output_data->output_modes->vrefresh = 30; + output_data->output_modes->clock = 25200; + output_data->output_modes->hdisplay = 640; + output_data->output_modes->hsync_start = 656; + output_data->output_modes->hsync_end = 752; + output_data->output_modes->htotal = 800; + output_data->output_modes->hskew = 0; + output_data->output_modes->vdisplay = 480; + output_data->output_modes->vsync_start = 490; + output_data->output_modes->vsync_end = 492; + output_data->output_modes->vtotal = 525; + output_data->output_modes->vscan = 0; + output_data->output_modes->flags = 0; + output_data->output_modes->type = 0; output_data->timer = tdm_event_loop_add_timer_handler(virtual_data->dpy, _tdm_virtual_display_cb_timeout, @@ -390,28 +390,28 @@ virtual_display_output_create(tdm_backend_data *bdata, const char *name, tdm_err else snprintf(output_data->name, TDM_NAME_LEN, "unknown"); #if 0 - output_data->output_mode = calloc(1, sizeof(tdm_output_mode)); - if (!output_data->output_mode) { + output_data->output_modes = calloc(1, sizeof(tdm_output_mode)); + if (!output_data->output_modes) { TDM_ERR("alloc failed"); ret = TDM_ERROR_OUT_OF_MEMORY; goto create_fail; } - snprintf(output_data->output_mode->name, TDM_NAME_LEN, "640x480"); - output_data->output_mode->vrefresh = 30; - output_data->output_mode->clock = 25200; - output_data->output_mode->hdisplay = 640; - output_data->output_mode->hsync_start = 656; - output_data->output_mode->hsync_end = 752; - output_data->output_mode->htotal = 800; - output_data->output_mode->hskew = 0; - output_data->output_mode->vdisplay = 480; - output_data->output_mode->vsync_start = 490; - output_data->output_mode->vsync_end = 492; - output_data->output_mode->vtotal = 525; - output_data->output_mode->vscan = 0; - output_data->output_mode->flags = 0; - output_data->output_mode->type = 0; + snprintf(output_data->output_modes->name, TDM_NAME_LEN, "640x480"); + output_data->output_modes->vrefresh = 30; + output_data->output_modes->clock = 25200; + output_data->output_modes->hdisplay = 640; + output_data->output_modes->hsync_start = 656; + output_data->output_modes->hsync_end = 752; + output_data->output_modes->htotal = 800; + output_data->output_modes->hskew = 0; + output_data->output_modes->vdisplay = 480; + output_data->output_modes->vsync_start = 490; + output_data->output_modes->vsync_end = 492; + output_data->output_modes->vtotal = 525; + output_data->output_modes->vscan = 0; + output_data->output_modes->flags = 0; + output_data->output_modes->type = 0; output_data->mode_count = 1; #endif @@ -449,7 +449,7 @@ virtual_display_output_create(tdm_backend_data *bdata, const char *name, tdm_err create_fail: if (layer_data) free(layer_data); - if (output_data->output_mode) free(output_data->output_mode); + if (output_data->output_modes) free(output_data->output_modes); free(output_data); *error = ret; @@ -474,8 +474,11 @@ virtual_display_output_destroy(tdm_backend_data *bdata, tdm_output *output) } } - if (find) + if (find) { + if (output_data->output_modes) + free(output_data->output_modes); tdm_backend_unregister_output(virtual_data->dpy, output); + } else return TDM_ERROR_INVALID_PARAMETER; @@ -510,7 +513,7 @@ virtual_output_get_capability(tdm_output *output, tdm_caps_output *caps) goto failed_get; } - *caps->modes = *output_data->output_mode; + *caps->modes = *output_data->output_modes; } caps->mmWidth = output_data->mmwidth; @@ -685,6 +688,46 @@ 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_virtual_output_data *output_data = output; + + RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER); + RETURN_VAL_IF_FAIL(modes, TDM_ERROR_INVALID_PARAMETER); + RETURN_VAL_IF_FAIL(count > 0, TDM_ERROR_INVALID_PARAMETER); + + /* set available mode only permittied disconnect status */ + RETURN_VAL_IF_FAIL(output_data->status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED, TDM_ERROR_BUSY); + + if (output_data->output_modes) + free(output_data->output_modes); + output_data->output_modes = NULL; + + output_data->output_modes = calloc(1, count * sizeof(tdm_output_mode)); + RETURN_VAL_IF_FAIL(output_data->output_modes != NULL, TDM_ERROR_OUT_OF_MEMORY); + + memcpy(output_data->output_modes, modes, count * sizeof(tdm_output_mode)); + output_data->mode_count = count; + + return TDM_ERROR_NONE; +} + +tdm_error +virtual_output_set_physical_size(tdm_output *output, unsigned int mmwidth, unsigned int mmheight) +{ + tdm_virtual_output_data *output_data = output; + + RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER); + RETURN_VAL_IF_FAIL(mmwidth != 0, TDM_ERROR_INVALID_PARAMETER); + RETURN_VAL_IF_FAIL(mmheight != 0, TDM_ERROR_INVALID_PARAMETER); + + output_data->mmwidth = mmwidth; + output_data->mmheight = mmheight; + + return TDM_ERROR_NONE; +} + +tdm_error virtual_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps) { tdm_virtual_layer_data *layer_data = layer; diff --git a/include/tdm_backend.h b/include/tdm_backend.h index 2e80d99..7f43ee2 100644 --- a/include/tdm_backend.h +++ b/include/tdm_backend.h @@ -550,6 +550,10 @@ typedef struct _tdm_func_output { */ tdm_hwc *(*output_get_hwc)(tdm_output *output, tdm_error *error); + /* virtual */ + tdm_error (*output_set_available_mode)(tdm_output *output, const tdm_output_mode *modes, int count); + tdm_error (*output_set_physical_size)(tdm_output *output, unsigned int mmwidth, unsigned int mmheight); + void (*reserved5)(void); void (*reserved6)(void); void (*reserved7)(void); diff --git a/src/tdm_display.c b/src/tdm_display.c index a355ab7..3373f88 100644 --- a/src/tdm_display.c +++ b/src/tdm_display.c @@ -820,8 +820,10 @@ tdm_display_create_output(tdm_display *dpy, const char *name, tdm_error *error) { tdm_private_module *private_module = NULL; tdm_private_module *current_module = NULL; + tdm_private_output *private_output = NULL; tdm_func_display *func_display = NULL; tdm_output *output = NULL; + int output_find = 0; DISPLAY_FUNC_ENTRY_ERROR(); @@ -840,13 +842,21 @@ tdm_display_create_output(tdm_display *dpy, const char *name, tdm_error *error) current_module = private_display->current_module; private_display->current_module = private_module; output = func_display->display_output_create(private_module->bdata, name, &ret); + LIST_FOR_EACH_ENTRY(private_output, &private_module->output_list, link) { + if (private_output->output_backend == output) { + output_find = 1; + break; + } + } private_display->current_module = current_module; _pthread_mutex_unlock(&private_display->lock); TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(output != NULL, ret, NULL); + if (output_find != 1) + private_output = NULL; - return output; + return private_output; } INTERN tdm_error @@ -854,6 +864,7 @@ tdm_display_destroy_output(tdm_display *dpy, tdm_output *output) { tdm_private_module *private_module = NULL; tdm_private_module *current_module = NULL; + tdm_private_output *private_output = NULL; tdm_func_display *func_display = NULL; DISPLAY_FUNC_ENTRY(); @@ -864,12 +875,14 @@ tdm_display_destroy_output(tdm_display *dpy, tdm_output *output) private_module = private_display->virtual_module; TDM_RETURN_VAL_IF_FAIL(private_module != NULL, TDM_ERROR_BAD_MODULE); + private_output = (tdm_private_output*)output; + _pthread_mutex_lock(&private_display->lock); func_display = &private_module->func_display; current_module = private_display->current_module; private_display->current_module = private_module; - ret = func_display->display_output_destroy(private_module->bdata, output); + ret = func_display->display_output_destroy(private_module->bdata, private_output->output_backend); private_display->current_module = current_module; _pthread_mutex_unlock(&private_display->lock); diff --git a/src/tdm_output.c b/src/tdm_output.c index 550a750..a7813da 100644 --- a/src/tdm_output.c +++ b/src/tdm_output.c @@ -1717,4 +1717,52 @@ tdm_output_choose_commit_per_vblank_mode(tdm_private_output *private_output, int return TDM_ERROR_NONE; } + +INTERN tdm_error +tdm_output_set_available_mode(tdm_output *output, const tdm_output_mode *modes, int count) +{ + tdm_private_module *private_module = NULL; + tdm_func_output *func_output = NULL; + + OUTPUT_FUNC_ENTRY(); + + TDM_RETURN_VAL_IF_FAIL(modes != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(count != 0, TDM_ERROR_INVALID_PARAMETER); + + private_module = private_output->private_module; + TDM_RETURN_VAL_IF_FAIL(private_module == private_display->virtual_module, TDM_ERROR_BAD_MODULE); + + _pthread_mutex_lock(&private_display->lock); + + func_output = &private_module->func_output; + ret = func_output->output_set_available_mode(private_output->output_backend, modes, count); + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} + +INTERN tdm_error +tdm_output_set_physical_size(tdm_output *output, unsigned int mmwidth, unsigned int mmheight) +{ + tdm_private_module *private_module = NULL; + tdm_func_output *func_output = NULL; + + OUTPUT_FUNC_ENTRY(); + + TDM_RETURN_VAL_IF_FAIL(mmwidth != 0, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(mmheight != 0, TDM_ERROR_INVALID_PARAMETER); + + private_module = private_output->private_module; + TDM_RETURN_VAL_IF_FAIL(private_module == private_display->virtual_module, TDM_ERROR_BAD_MODULE); + + _pthread_mutex_lock(&private_display->lock); + + func_output = &private_module->func_output; + ret = func_output->output_set_physical_size(private_output->output_backend, mmwidth, mmheight); + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} /* LCOV_EXCL_STOP */ diff --git a/src/tdm_private.h b/src/tdm_private.h index d747993..2e7ffa3 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -255,10 +255,15 @@ tdm_config_deinit(void); void tdm_monitor_server_command(tdm_display *dpy, const char *options, char *reply, int *len); +/* virtual */ tdm_output * tdm_display_create_output(tdm_display *dpy, const char *name, tdm_error *error); tdm_error tdm_display_destroy_output(tdm_display *dpy, tdm_output *output); +tdm_error +tdm_output_set_available_mode(tdm_output *output, const tdm_output_mode *modes, int count); +tdm_error +tdm_output_set_physical_size(tdm_output *output, unsigned int mmwidth, unsigned int mmheight); #ifdef __cplusplus } -- 2.7.4 From 77aaf72a8ef5ff9d32b1be594659201d59ccf2e1 Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Mon, 23 Jul 2018 15:03:45 +0900 Subject: [PATCH 04/16] virtual: add set_physical_size protocol Change-Id: I19f67d59f816bd1486f6c1f408416856c03469ac Signed-off-by: Junkyeong Kim --- client/tdm_client.c | 20 +++++++++++++++++--- client/tdm_client.h | 2 +- haltests/src/tc_tdm_client.cpp | 8 ++++---- protocol/tdm.xml | 5 +++++ src/tdm_server.c | 16 ++++++++++++++++ 5 files changed, 43 insertions(+), 8 deletions(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index acd832e..e86f2d2 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -99,6 +99,9 @@ typedef struct _tdm_private_client_voutput { tdm_client_output_mode *modes; } available_modes; + unsigned int mmwidth; + unsigned int mmheight; + uint32_t msg; } tdm_private_client_voutput; @@ -1772,11 +1775,22 @@ tdm_client_voutput_set_available_modes(tdm_client_voutput *voutput, const tdm_cl } tdm_error -tdm_client_voutput_set_physical_size(tdm_client_voutput *voutput, int mmWidth, int mmHeight) +tdm_client_voutput_set_physical_size(tdm_client_voutput *voutput, unsigned int mmWidth, unsigned int mmHeight) { + tdm_private_client_voutput *private_voutput; + 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); + 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_client_voutput *)voutput; + + if (private_voutput->base.connection == TDM_OUTPUT_CONN_STATUS_CONNECTED) + return TDM_ERROR_BAD_REQUEST; + + private_voutput->mmwidth = mmWidth; + private_voutput->mmheight = mmHeight; + wl_tdm_voutput_set_physical_size(private_voutput->wl_voutput, private_voutput->mmwidth, private_voutput->mmheight); return TDM_ERROR_NONE; } diff --git a/client/tdm_client.h b/client/tdm_client.h index 4ffe435..d0512cc 100644 --- a/client/tdm_client.h +++ b/client/tdm_client.h @@ -442,7 +442,7 @@ tdm_error tdm_client_voutput_set_available_modes(tdm_client_voutput *voutput, const tdm_client_output_mode *modes, int count); tdm_error -tdm_client_voutput_set_physical_size(tdm_client_voutput *voutput, int mmWidth, int mmHeight); +tdm_client_voutput_set_physical_size(tdm_client_voutput *voutput, unsigned int mmWidth, unsigned int mmHeight); tdm_error tdm_client_voutput_add_commit_handler(tdm_client_voutput *voutput, tdm_client_voutput_commit_handler *func); diff --git a/haltests/src/tc_tdm_client.cpp b/haltests/src/tc_tdm_client.cpp index 1909ff0..c637d88 100644 --- a/haltests/src/tc_tdm_client.cpp +++ b/haltests/src/tc_tdm_client.cpp @@ -1559,8 +1559,8 @@ TEST_F(TDMVirtualOutput, FailTestSetAvailableModes) TEST_F(TDMVirtualOutput, SetPhysicalSize) { tdm_error ret; - int mmWidth = 1234, mmHeight = 1234; - + unsigned int mmWidth = 1234, mmHeight = 1234; + ret = tdm_client_voutput_set_physical_size(this->voutput, mmWidth, mmHeight); ASSERT_EQ(ret, TDM_ERROR_NONE); } @@ -1568,8 +1568,8 @@ TEST_F(TDMVirtualOutput, SetPhysicalSize) TEST_F(TDMVirtualOutput, FailTestSetPhysicalSize) { tdm_error ret; - int invalid_mmWidth = -1, invalid_mmHeight = -1; - + unsigned int invalid_mmWidth = 0, invalid_mmHeight = 0; + ret = tdm_client_voutput_set_physical_size(this->voutput, invalid_mmWidth, invalid_mmHeight); ASSERT_EQ(ret, TDM_ERROR_INVALID_PARAMETER); } diff --git a/protocol/tdm.xml b/protocol/tdm.xml index 1248920..3db00b1 100644 --- a/protocol/tdm.xml +++ b/protocol/tdm.xml @@ -96,6 +96,11 @@ + + + + + diff --git a/src/tdm_server.c b/src/tdm_server.c index 3ce52cb..cf743fa 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -79,6 +79,9 @@ typedef struct _tdm_server_voutput_info { int count; tdm_output_mode *modes; } available_modes; + + unsigned int mmwidth; + unsigned int mmheight; } tdm_server_voutput_info; typedef struct _tdm_server_vblank_info { @@ -786,6 +789,18 @@ _tdm_voutput_cb_set_available_modes(struct wl_client *client, } static void +_tdm_voutput_cb_set_physical_size(struct wl_client *client, struct wl_resource *resource, + unsigned int mmwidth, unsigned int mmheight) +{ + tdm_server_voutput_info *voutput_info; + + voutput_info = wl_resource_get_user_data(resource); + + voutput_info->mmwidth = mmwidth; + voutput_info->mmheight = mmheight; +} + +static void _tdm_voutput_cb_connect(struct wl_client *client, struct wl_resource *resource) { tdm_server_voutput_info *voutput_info; @@ -811,6 +826,7 @@ _tdm_voutput_cb_disconnect(struct wl_client *client, struct wl_resource *resourc static const struct wl_tdm_voutput_interface tdm_voutput_implementation = { _tdm_voutput_cb_destroy, _tdm_voutput_cb_set_available_modes, + _tdm_voutput_cb_set_physical_size, _tdm_voutput_cb_connect, _tdm_voutput_cb_disconnect }; -- 2.7.4 From 5838dcaade3b2ed12a2beafb0b42e1d38160f1a5 Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Mon, 23 Jul 2018 15:25:35 +0900 Subject: [PATCH 05/16] virtual: execute tdm_display_destroy_output when voutput destroy execute set_available_modes and set_physical_size when connect Change-Id: Ifd37190120ee6b4139d0c75a2f53001f6475ba09 Signed-off-by: Junkyeong Kim --- src/tdm_server.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/tdm_server.c b/src/tdm_server.c index cf743fa..e540133 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -715,6 +715,22 @@ _tdm_server_cb_create_output(struct wl_client *client, struct wl_resource *resou static void _tdm_voutput_cb_destroy(struct wl_client *client, struct wl_resource *resource) { + tdm_server_voutput_info *voutput_info; + tdm_private_server *private_server; + tdm_output *output; + tdm_error ret = TDM_ERROR_NONE; + + voutput_info = wl_resource_get_user_data(resource); + + private_server = voutput_info->private_server; + output = voutput_info->output; + + if (output) + ret = tdm_display_destroy_output(private_server->private_loop->dpy, output); + + if (ret != TDM_ERROR_NONE) + TDM_ERR("_tdm_voutput_cb_destroy fail"); + wl_resource_destroy(resource); } @@ -807,6 +823,10 @@ _tdm_voutput_cb_connect(struct wl_client *client, struct wl_resource *resource) voutput_info = wl_resource_get_user_data(resource); voutput_info->status = TDM_OUTPUT_CONN_STATUS_CONNECTED; + + tdm_output_set_physical_size(voutput_info->output, voutput_info->mmwidth, voutput_info->mmheight); + tdm_output_set_available_mode(voutput_info->output, voutput_info->available_modes.modes, voutput_info->available_modes.count); + //tdm_output_set_connect(); } static void -- 2.7.4 From 36484ad90323ab7d4555b40702579e2eac77ff77 Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Mon, 23 Jul 2018 20:35:02 +0900 Subject: [PATCH 06/16] virtual: add tdm_voutput_connect & disconnect Change-Id: Ia80b476627ff79ff3eac2e3187aa8e8577a7cf6b Signed-off-by: Junkyeong Kim --- backends/virtual/tdm_virtual.c | 3 ++ backends/virtual/tdm_virtual.h | 3 ++ backends/virtual/tdm_virtual_display.c | 83 +++++++++++++++++++++++++++++----- include/tdm_backend.h | 2 + src/tdm_output.c | 50 +++++++++++++++++++- src/tdm_private.h | 4 ++ src/tdm_server.c | 33 +++++--------- 7 files changed, 144 insertions(+), 34 deletions(-) diff --git a/backends/virtual/tdm_virtual.c b/backends/virtual/tdm_virtual.c index 426feaf..1b96a4c 100644 --- a/backends/virtual/tdm_virtual.c +++ b/backends/virtual/tdm_virtual.c @@ -77,6 +77,9 @@ tdm_virtual_init(tdm_display *dpy, tdm_error *error) virtual_func_output.output_get_mode = virtual_output_get_mode; virtual_func_output.output_set_available_mode = virtual_output_set_available_mode; virtual_func_output.output_set_physical_size = virtual_output_set_physical_size; + virtual_func_output.output_set_connect = virtual_output_set_connect; + virtual_func_output.output_set_disconnect = virtual_output_set_disconnect; + virtual_func_output.output_set_status_handler = virtual_output_set_status_handler; 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 1ad4550..766a155 100644 --- a/backends/virtual/tdm_virtual.h +++ b/backends/virtual/tdm_virtual.h @@ -42,6 +42,9 @@ tdm_error virtual_output_set_mode(tdm_output *output, const tdm_output_mode *mod 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_set_connect(tdm_output *output); +tdm_error virtual_output_set_disconnect(tdm_output *output); +tdm_error virtual_output_set_status_handler(tdm_output *output, tdm_output_status_handler func, void *user_data); 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 2288a72..1e8f20c 100644 --- a/backends/virtual/tdm_virtual_display.c +++ b/backends/virtual/tdm_virtual_display.c @@ -39,6 +39,8 @@ struct _tdm_virtual_output_data { tdm_output_commit_handler commit_func; tdm_output_conn_status status; + tdm_output_status_handler status_func; + void *status_user_data; int mode_changed; const tdm_output_mode *current_mode; @@ -504,20 +506,27 @@ virtual_output_get_capability(tdm_output *output, tdm_caps_output *caps) caps->type = output_data->connector_type; caps->type_id = 0; - caps->mode_count = output_data->mode_count; - if (output_data->mode_count != 0) { - caps->modes = calloc(output_data->mode_count, sizeof(tdm_output_mode)); - if (!caps->modes) { - ret = TDM_ERROR_OUT_OF_MEMORY; - TDM_ERR("alloc failed\n"); - goto failed_get; + if (output_data->status == TDM_OUTPUT_CONN_STATUS_CONNECTED || + output_data->status == TDM_OUTPUT_CONN_STATUS_MODE_SETTED) { + caps->mode_count = output_data->mode_count; + if (output_data->mode_count != 0) { + caps->modes = calloc(output_data->mode_count, sizeof(tdm_output_mode)); + if (!caps->modes) { + ret = TDM_ERROR_OUT_OF_MEMORY; + TDM_ERR("alloc failed\n"); + goto failed_get; + } + memcpy(caps->modes, output_data->output_modes, output_data->mode_count * sizeof(tdm_output_mode)); } - *caps->modes = *output_data->output_modes; + caps->mmWidth = output_data->mmwidth; + caps->mmHeight = output_data->mmheight; + } else { + caps->modes = NULL; + caps->mode_count = 0; + caps->mmWidth = 0; + caps->mmHeight = 0; } - - caps->mmWidth = output_data->mmwidth; - caps->mmHeight =output_data->mmheight; caps->subpixel = 1; caps->min_w = -1; @@ -727,6 +736,58 @@ virtual_output_set_physical_size(tdm_output *output, unsigned int mmwidth, unsig return TDM_ERROR_NONE; } +tdm_error virtual_output_set_connect(tdm_output *output) +{ + tdm_virtual_output_data *output_data = output; + + RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER); + + if (output_data->status == TDM_OUTPUT_CONN_STATUS_CONNECTED || + output_data->status == TDM_OUTPUT_CONN_STATUS_MODE_SETTED) + return TDM_ERROR_NONE; + + output_data->status = TDM_OUTPUT_CONN_STATUS_CONNECTED; + + if (output_data->status_func) + output_data->status_func(output_data, output_data->status, + output_data->status_user_data); + + return TDM_ERROR_NONE; +} + +tdm_error virtual_output_set_disconnect(tdm_output *output) +{ + tdm_virtual_output_data *output_data = output; + + RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER); + + if (output_data->status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) + return TDM_ERROR_NONE; + + output_data->status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED; + + if (output_data->status_func) + output_data->status_func(output_data, output_data->status, + output_data->status_user_data); + + return TDM_ERROR_NONE; +} + +tdm_error +virtual_output_set_status_handler(tdm_output *output, + tdm_output_status_handler func, void *user_data) +{ + tdm_virtual_output_data *output_data = output; + + RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER); + RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER); + + output_data->status_func = func; + output_data->status_user_data = user_data; + + return TDM_ERROR_NONE; +} + tdm_error virtual_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps) { diff --git a/include/tdm_backend.h b/include/tdm_backend.h index 7f43ee2..72136b1 100644 --- a/include/tdm_backend.h +++ b/include/tdm_backend.h @@ -553,6 +553,8 @@ typedef struct _tdm_func_output { /* virtual */ tdm_error (*output_set_available_mode)(tdm_output *output, const tdm_output_mode *modes, int count); tdm_error (*output_set_physical_size)(tdm_output *output, unsigned int mmwidth, unsigned int mmheight); + tdm_error (*output_set_connect)(tdm_output *output); + tdm_error (*output_set_disconnect)(tdm_output *output); void (*reserved5)(void); void (*reserved6)(void); diff --git a/src/tdm_output.c b/src/tdm_output.c index a7813da..778dc6d 100644 --- a/src/tdm_output.c +++ b/src/tdm_output.c @@ -1735,7 +1735,8 @@ tdm_output_set_available_mode(tdm_output *output, const tdm_output_mode *modes, _pthread_mutex_lock(&private_display->lock); func_output = &private_module->func_output; - ret = func_output->output_set_available_mode(private_output->output_backend, modes, count); + if (func_output->output_set_available_mode) + ret = func_output->output_set_available_mode(private_output->output_backend, modes, count); _pthread_mutex_unlock(&private_display->lock); @@ -1759,7 +1760,52 @@ tdm_output_set_physical_size(tdm_output *output, unsigned int mmwidth, unsigned _pthread_mutex_lock(&private_display->lock); func_output = &private_module->func_output; - ret = func_output->output_set_physical_size(private_output->output_backend, mmwidth, mmheight); + if (func_output->output_set_physical_size) + ret = func_output->output_set_physical_size(private_output->output_backend, mmwidth, mmheight); + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} + +INTERN tdm_error +tdm_output_set_connect(tdm_output *output) +{ + tdm_private_module *private_module = NULL; + tdm_func_output *func_output = NULL; + + OUTPUT_FUNC_ENTRY(); + + private_module = private_output->private_module; + TDM_RETURN_VAL_IF_FAIL(private_module == private_display->virtual_module, TDM_ERROR_BAD_MODULE); + + _pthread_mutex_lock(&private_display->lock); + + func_output = &private_module->func_output; + if (func_output->output_set_connect) + ret = func_output->output_set_connect(private_output->output_backend); + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} + +INTERN tdm_error +tdm_output_set_disconnect(tdm_output *output) +{ + tdm_private_module *private_module = NULL; + tdm_func_output *func_output = NULL; + + OUTPUT_FUNC_ENTRY(); + + private_module = private_output->private_module; + TDM_RETURN_VAL_IF_FAIL(private_module == private_display->virtual_module, TDM_ERROR_BAD_MODULE); + + _pthread_mutex_lock(&private_display->lock); + + func_output = &private_module->func_output; + if (func_output->output_set_disconnect) + ret = func_output->output_set_disconnect(private_output->output_backend); _pthread_mutex_unlock(&private_display->lock); diff --git a/src/tdm_private.h b/src/tdm_private.h index 2e7ffa3..02464d8 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -264,6 +264,10 @@ tdm_error tdm_output_set_available_mode(tdm_output *output, const tdm_output_mode *modes, int count); tdm_error tdm_output_set_physical_size(tdm_output *output, unsigned int mmwidth, unsigned int mmheight); +tdm_error +tdm_output_set_connect(tdm_output *output); +tdm_error +tdm_output_set_disconnect(tdm_output *output); #ifdef __cplusplus } diff --git a/src/tdm_server.c b/src/tdm_server.c index e540133..0b15154 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -612,19 +612,7 @@ destroy_output_callback(struct wl_resource *resource) free(output_info); } -#if 0 -static void -destroy_voutput_callback(struct wl_resource *resource) -{ - tdm_server_voutput_info *voutput_info = wl_resource_get_user_data(resource); - - TDM_RETURN_IF_FAIL(voutput_info != NULL); - - LIST_DEL(&voutput_info->link); - free(voutput_info); -} -#endif static void _tdm_server_cb_create_output(struct wl_client *client, struct wl_resource *resource, const char *name, uint32_t id) @@ -763,10 +751,8 @@ _tdm_voutput_cb_set_available_modes(struct wl_client *client, count = voutput_info->available_modes.count; old_modes = voutput_info->available_modes.modes; - if (index >= count) - { - if (count > 0) - { + if (index >= count) { + if (count > 0) { tmp_modes = malloc(count * sizeof(*tmp_modes)); memcpy(tmp_modes, old_modes, count * sizeof(tdm_output_mode)); } @@ -776,8 +762,7 @@ _tdm_voutput_cb_set_available_modes(struct wl_client *client, realloc(voutput_info->available_modes.modes, sizeof(tdm_output_mode) * (index + 1)); - if (count > 0) - { + if (count > 0) { memcpy(voutput_info->available_modes.modes, tmp_modes, count * sizeof(tdm_output_mode)); free(tmp_modes); } @@ -826,7 +811,7 @@ _tdm_voutput_cb_connect(struct wl_client *client, struct wl_resource *resource) tdm_output_set_physical_size(voutput_info->output, voutput_info->mmwidth, voutput_info->mmheight); tdm_output_set_available_mode(voutput_info->output, voutput_info->available_modes.modes, voutput_info->available_modes.count); - //tdm_output_set_connect(); + tdm_output_set_connect(voutput_info->output); } static void @@ -841,6 +826,10 @@ _tdm_voutput_cb_disconnect(struct wl_client *client, struct wl_resource *resourc free(voutput_info->available_modes.modes); voutput_info->available_modes.modes = NULL; voutput_info->available_modes.count = 0; + voutput_info->mmwidth = 0; + voutput_info->mmheight = 0; + + tdm_output_set_disconnect(voutput_info->output); } static const struct wl_tdm_voutput_interface tdm_voutput_implementation = { @@ -854,9 +843,11 @@ static const struct wl_tdm_voutput_interface tdm_voutput_implementation = { void tdm_voutput_cb_resource_destroy(struct wl_resource *resource) { - tdm_server_voutput_info *voutput_info; + tdm_server_voutput_info *voutput_info = wl_resource_get_user_data(resource); - voutput_info = wl_resource_get_user_data(resource); + TDM_RETURN_IF_FAIL(voutput_info != NULL); + + LIST_DEL(&voutput_info->link); /* Do free your own resource */ free(voutput_info); -- 2.7.4 From bcf7c12f8345fe7a4699df63ebb31d60cf1ab120 Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Mon, 23 Jul 2018 20:50:12 +0900 Subject: [PATCH 07/16] virtual: send set_physical_size when voutput connect change tdm_client tc mode values for virtual output test Change-Id: Ib3b904388cc44c2042bcb3d8b2aa7ce51fa9df78 Signed-off-by: Junkyeong Kim --- client/tdm_client.c | 5 ++-- haltests/src/tc_tdm_client.cpp | 61 ++++++++++++++++++++++++++++-------------- 2 files changed, 43 insertions(+), 23 deletions(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index e86f2d2..9fa0ab5 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -1790,7 +1790,6 @@ tdm_client_voutput_set_physical_size(tdm_client_voutput *voutput, unsigned int m private_voutput->mmwidth = mmWidth; private_voutput->mmheight = mmHeight; - wl_tdm_voutput_set_physical_size(private_voutput->wl_voutput, private_voutput->mmwidth, private_voutput->mmheight); return TDM_ERROR_NONE; } @@ -1854,8 +1853,7 @@ tdm_client_output_connect(tdm_client_output *output) private_output->connection = TDM_OUTPUT_CONN_STATUS_CONNECTED; modes = private_voutput->available_modes.modes; - for (i = 0; i < private_voutput->available_modes.count; i++) - { + for (i = 0; i < private_voutput->available_modes.count; i++) { wl_tdm_voutput_set_available_modes(private_voutput->wl_voutput, i, modes[i].clock, modes[i].hdisplay, modes[i].hsync_start, modes[i].hsync_end, @@ -1866,6 +1864,7 @@ tdm_client_output_connect(tdm_client_output *output) modes[i].flags, modes[i].type, modes[i].name); } + wl_tdm_voutput_set_physical_size(private_voutput->wl_voutput, private_voutput->mmwidth, private_voutput->mmheight); wl_tdm_voutput_connect(private_voutput->wl_voutput); diff --git a/haltests/src/tc_tdm_client.cpp b/haltests/src/tc_tdm_client.cpp index c637d88..6be6821 100644 --- a/haltests/src/tc_tdm_client.cpp +++ b/haltests/src/tc_tdm_client.cpp @@ -1483,6 +1483,8 @@ void TDMVirtualOutput::SetUpTestCase(void) void TDMVirtualOutput::TearDownTestCase(void) { +// TDM_UT_WAIT("check & press"); + if (voutput) tdm_client_voutput_destroy(voutput); @@ -1514,30 +1516,37 @@ bool TDMVirtualOutput::PrepareVOutput(void) return true; } +static void +_tc_tdm_client_virutual_make_available_mode(tdm_client_output_mode *modes, int count) +{ + int i; + + for (i = 0; i < count; i++) { + modes[i].clock = 25200; + modes[i].hdisplay = 640; + modes[i].hsync_start = 656; + modes[i].hsync_end = 752; + modes[i].htotal = 800; + modes[i].hskew = 0; + modes[i].vdisplay = 480; + modes[i].vsync_start = 490; + modes[i].vsync_end = 492; + modes[i].vtotal = 525; + modes[i].vscan = 0; + modes[i].vrefresh = 30; + modes[i].flags = 0; + modes[i].type = 0; + snprintf(modes[i].name, TDM_NAME_LEN, "%dx%d_%d", modes[i].hdisplay, modes[i].vdisplay, i); + } +} + TEST_F(TDMVirtualOutput, SetAvailableModes) { tdm_error ret; tdm_client_output_mode modes[this->MODE_COUNT]; - int i, count = this->MODE_COUNT; - - for (i = 0; i < count; i++) - { - modes[i].clock = 1; - modes[i].hdisplay = 2; - modes[i].hsync_start = 3; - modes[i].hsync_end = 4; - modes[i].htotal = 5; - modes[i].hskew = 6; - modes[i].vdisplay = 7; - modes[i].vsync_start = 8; - modes[i].vsync_end = 9; - modes[i].vtotal = 10; - modes[i].vscan = 11; - modes[i].vrefresh = 12; - modes[i].flags = 13; - modes[i].type = 14; - snprintf(modes[i].name, TDM_NAME_LEN, "TestModeSetting %d", i); - } + int count = this->MODE_COUNT; + + _tc_tdm_client_virutual_make_available_mode(modes, count); ret = tdm_client_voutput_set_available_modes(this->voutput, modes, count); ASSERT_EQ(ret, TDM_ERROR_NONE); @@ -1588,11 +1597,21 @@ TEST_F(TDMVirtualOutput, Connect) { tdm_error ret; tdm_client_output *output; + unsigned int mmWidth = 300, mmHeight = 150; + tdm_client_output_mode modes[this->MODE_COUNT]; + int count = this->MODE_COUNT; output = tdm_client_voutput_get_client_output(this->voutput, &ret); ASSERT_EQ(ret, TDM_ERROR_NONE); ASSERT_NE(output, NULL); + ret = tdm_client_voutput_set_physical_size(this->voutput, mmWidth, mmHeight); + ASSERT_EQ(ret, TDM_ERROR_NONE); + + _tc_tdm_client_virutual_make_available_mode(modes, count); + ret = tdm_client_voutput_set_available_modes(this->voutput, modes, count); + ASSERT_EQ(ret, TDM_ERROR_NONE); + ret = tdm_client_output_connect(output); ASSERT_EQ(ret, TDM_ERROR_NONE); @@ -1604,6 +1623,8 @@ TEST_F(TDMVirtualOutput, Disconnect) tdm_error ret; tdm_client_output *output; +// TDM_UT_WAIT("check & press"); + output = tdm_client_voutput_get_client_output(this->voutput, &ret); ASSERT_EQ(ret, TDM_ERROR_NONE); ASSERT_NE(output, NULL); -- 2.7.4 From 83f2396f960f101e9d1ae8c1f787125afc30c655 Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Tue, 24 Jul 2018 13:54:57 +0900 Subject: [PATCH 08/16] virtual: free output data when virtual output destroy Change-Id: Ib193d05639a7762711fce2080ae5cc03ce1cf3df Signed-off-by: Junkyeong Kim --- backends/virtual/tdm_virtual_display.c | 36 ++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/backends/virtual/tdm_virtual_display.c b/backends/virtual/tdm_virtual_display.c index 1e8f20c..14c1e62 100644 --- a/backends/virtual/tdm_virtual_display.c +++ b/backends/virtual/tdm_virtual_display.c @@ -216,7 +216,8 @@ tdm_virtual_display_destroy_output_list(tdm_virtual_data *virtual_data) if (o->timer) tdm_event_loop_source_remove(o->timer); - free(o->output_modes); + if (o->output_modes) + free(o->output_modes); free(o); } } @@ -477,11 +478,32 @@ virtual_display_output_destroy(tdm_backend_data *bdata, tdm_output *output) } if (find) { + tdm_virtual_layer_data *l = NULL, *ll = NULL; + + tdm_backend_unregister_output(virtual_data->dpy, output); + + if (!LIST_IS_EMPTY(&o->timer_event_list)) { + tdm_virtual_event_data *e = NULL, *ee = NULL; + LIST_FOR_EACH_ENTRY_SAFE(e, ee, &o->timer_event_list, link) { + LIST_DEL(&e->link); + free(e); + } + } + + if (o->timer) + tdm_event_loop_source_remove(o->timer); + + LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) { + LIST_DEL(&l->link); + free(l); + } + if (output_data->output_modes) free(output_data->output_modes); - tdm_backend_unregister_output(virtual_data->dpy, output); - } - else + + LIST_DEL(&o->link); + free(o); + } else return TDM_ERROR_INVALID_PARAMETER; return TDM_ERROR_NONE; @@ -736,7 +758,8 @@ virtual_output_set_physical_size(tdm_output *output, unsigned int mmwidth, unsig return TDM_ERROR_NONE; } -tdm_error virtual_output_set_connect(tdm_output *output) +tdm_error +virtual_output_set_connect(tdm_output *output) { tdm_virtual_output_data *output_data = output; @@ -755,7 +778,8 @@ tdm_error virtual_output_set_connect(tdm_output *output) return TDM_ERROR_NONE; } -tdm_error virtual_output_set_disconnect(tdm_output *output) +tdm_error +virtual_output_set_disconnect(tdm_output *output) { tdm_virtual_output_data *output_data = output; -- 2.7.4 From 0613d5ca5f9a733c596b7b61d02ebd08c19a87ed Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Thu, 19 Jul 2018 19:17:02 +0900 Subject: [PATCH 09/16] virtual output: free memory for available modes when voutput is destroyed. Change-Id: I56c732d55d1bdeef8b471cc10c5682adcdfa35c5 --- client/tdm_client.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/tdm_client.c b/client/tdm_client.c index 9fa0ab5..b1af3f1 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -1740,6 +1740,9 @@ tdm_client_voutput_destroy(tdm_client_voutput *voutput) if (!private_voutput) return; + if (private_voutput->available_modes.modes) + free(private_voutput->available_modes.modes); + wl_tdm_voutput_destroy(private_voutput->wl_voutput); free(private_voutput); -- 2.7.4 From 7e7fcd357fbec8140bb607ba4f9417baef49f747 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Thu, 26 Jul 2018 13:37:34 +0900 Subject: [PATCH 10/16] virtual (client): Added implementation for setting available format. Change-Id: I59a1716409d2b4d18b4ff66b65bf94cfcf76292a --- client/tdm_client.c | 58 ++++++++++++++++++++++++++++++++++++++++++ client/tdm_client.h | 3 +++ haltests/src/tc_tdm_client.cpp | 22 ++++++++++++++++ protocol/tdm.xml | 4 +++ src/tdm_server.c | 31 ++++++++++++++++++++++ 5 files changed, 118 insertions(+) diff --git a/client/tdm_client.c b/client/tdm_client.c index b1af3f1..d3e8b47 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -96,6 +96,12 @@ typedef struct _tdm_private_client_voutput { struct { int count; + tbm_format *formats; + } available_formats; + + struct + { + int count; tdm_client_output_mode *modes; } available_modes; @@ -1743,6 +1749,9 @@ tdm_client_voutput_destroy(tdm_client_voutput *voutput) if (private_voutput->available_modes.modes) free(private_voutput->available_modes.modes); + if (private_voutput->available_formats.formats) + free(private_voutput->available_formats.formats); + wl_tdm_voutput_destroy(private_voutput->wl_voutput); free(private_voutput); @@ -1778,6 +1787,35 @@ tdm_client_voutput_set_available_modes(tdm_client_voutput *voutput, const tdm_cl } tdm_error +tdm_client_voutput_set_available_formats(tdm_client_voutput *voutput, const tbm_format *formats, const int count) +{ + tdm_private_client_voutput *private_voutput; + + TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER); + + if ((count > 0) && (formats == NULL)) + return TDM_ERROR_INVALID_PARAMETER; + + private_voutput = (tdm_private_client_voutput *)voutput; + + if (private_voutput->base.connection == TDM_OUTPUT_CONN_STATUS_CONNECTED) + return TDM_ERROR_BAD_REQUEST; + + if (private_voutput->available_formats.formats) + free(private_voutput->available_formats.formats); + + private_voutput->available_formats.count = count; + + if (count != 0) + { + private_voutput->available_formats.formats = calloc(count, sizeof(tbm_format)); + memcpy(private_voutput->available_formats.formats, formats, sizeof(tbm_format) * count); + } + + return TDM_ERROR_NONE; +} + +tdm_error tdm_client_voutput_set_physical_size(tdm_client_voutput *voutput, unsigned int mmWidth, unsigned int mmHeight) { tdm_private_client_voutput *private_voutput; @@ -1837,6 +1875,23 @@ tdm_client_output_set_mode(tdm_client_output *output, const tdm_client_output_mo return TDM_ERROR_NONE; } +void +_tdm_client_voutput_send_available_formats(tdm_private_client_voutput *private_voutput) +{ + tbm_format *format; + struct wl_array array; + int i, size; + + size = sizeof(tbm_format); + wl_array_init(&array); + for (i = 0; i < private_voutput->available_formats.count; i++) { + format = wl_array_add(&array, size); + *format = private_voutput->available_formats.formats[i]; + } + wl_tdm_voutput_set_available_formats(private_voutput->wl_voutput, &array); + wl_array_release(&array); +} + tdm_error tdm_client_output_connect(tdm_client_output *output) { @@ -1867,6 +1922,9 @@ tdm_client_output_connect(tdm_client_output *output) modes[i].flags, modes[i].type, modes[i].name); } + + _tdm_client_voutput_send_available_formats(private_voutput); + wl_tdm_voutput_set_physical_size(private_voutput->wl_voutput, private_voutput->mmwidth, private_voutput->mmheight); wl_tdm_voutput_connect(private_voutput->wl_voutput); diff --git a/client/tdm_client.h b/client/tdm_client.h index d0512cc..c0ffeb7 100644 --- a/client/tdm_client.h +++ b/client/tdm_client.h @@ -442,6 +442,9 @@ tdm_error tdm_client_voutput_set_available_modes(tdm_client_voutput *voutput, const tdm_client_output_mode *modes, int count); tdm_error +tdm_client_voutput_set_available_formats(tdm_client_voutput *voutput, const tbm_format *formats, const int count); + +tdm_error tdm_client_voutput_set_physical_size(tdm_client_voutput *voutput, unsigned int mmWidth, unsigned int mmHeight); tdm_error diff --git a/haltests/src/tc_tdm_client.cpp b/haltests/src/tc_tdm_client.cpp index 6be6821..1ee78c5 100644 --- a/haltests/src/tc_tdm_client.cpp +++ b/haltests/src/tc_tdm_client.cpp @@ -1413,6 +1413,7 @@ protected: static tdm_client *client; static tdm_client_voutput *voutput; const int MODE_COUNT = 2; + const int FORMAT_COUNT = 2; private: static pid_t server_pid; @@ -1540,6 +1541,7 @@ _tc_tdm_client_virutual_make_available_mode(tdm_client_output_mode *modes, int c } } + TEST_F(TDMVirtualOutput, SetAvailableModes) { tdm_error ret; @@ -1565,6 +1567,19 @@ TEST_F(TDMVirtualOutput, FailTestSetAvailableModes) ASSERT_EQ(ret, TDM_ERROR_INVALID_PARAMETER); } +TEST_F(TDMVirtualOutput, SetAvailableFormats) +{ + const int nformats = 2; + tdm_error ret; + tbm_format formats[nformats]; + + formats[0] = TBM_FORMAT_ARGB8888; + formats[1] = TBM_FORMAT_XRGB8888; + + ret = tdm_client_voutput_set_available_formats(this->voutput, formats, nformats); + ASSERT_EQ(ret, TDM_ERROR_NONE); +} + TEST_F(TDMVirtualOutput, SetPhysicalSize) { tdm_error ret; @@ -1595,10 +1610,12 @@ TEST_F(TDMVirtualOutput, GetClientOutput) TEST_F(TDMVirtualOutput, Connect) { + const int nformats = 2; tdm_error ret; tdm_client_output *output; unsigned int mmWidth = 300, mmHeight = 150; tdm_client_output_mode modes[this->MODE_COUNT]; + tbm_format formats[nformats]; int count = this->MODE_COUNT; output = tdm_client_voutput_get_client_output(this->voutput, &ret); @@ -1612,6 +1629,11 @@ TEST_F(TDMVirtualOutput, Connect) ret = tdm_client_voutput_set_available_modes(this->voutput, modes, count); ASSERT_EQ(ret, TDM_ERROR_NONE); + formats[0] = TBM_FORMAT_ARGB8888; + formats[1] = TBM_FORMAT_XRGB8888; + ret = tdm_client_voutput_set_available_formats(this->voutput, formats, nformats); + ASSERT_EQ(ret, TDM_ERROR_NONE); + ret = tdm_client_output_connect(output); ASSERT_EQ(ret, TDM_ERROR_NONE); diff --git a/protocol/tdm.xml b/protocol/tdm.xml index 3db00b1..4cc3aae 100644 --- a/protocol/tdm.xml +++ b/protocol/tdm.xml @@ -96,6 +96,10 @@ + + + + diff --git a/src/tdm_server.c b/src/tdm_server.c index 0b15154..b394618 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -79,6 +79,11 @@ typedef struct _tdm_server_voutput_info { int count; tdm_output_mode *modes; } available_modes; + struct + { + int count; + tbm_format *formats; + } available_formats; unsigned int mmwidth; unsigned int mmheight; @@ -790,6 +795,31 @@ _tdm_voutput_cb_set_available_modes(struct wl_client *client, } static void +_tdm_voutput_cb_set_available_formats(struct wl_client *client, + struct wl_resource *resource, + struct wl_array *formats) +{ + tdm_server_voutput_info *voutput_info; + tbm_format *f; + int count = 0, i = 0; + + voutput_info = wl_resource_get_user_data(resource); + + voutput_info->available_formats.count = 0; + if (voutput_info->available_formats.formats) + free(voutput_info->available_formats.formats); + + wl_array_for_each(f, formats) + count++; + + voutput_info->available_formats.formats = malloc(count * sizeof(tbm_format)); + voutput_info->available_formats.count = count; + + wl_array_for_each(f, formats) + voutput_info->available_formats.formats[i++] = *f; +} + +static void _tdm_voutput_cb_set_physical_size(struct wl_client *client, struct wl_resource *resource, unsigned int mmwidth, unsigned int mmheight) { @@ -835,6 +865,7 @@ _tdm_voutput_cb_disconnect(struct wl_client *client, struct wl_resource *resourc static const struct wl_tdm_voutput_interface tdm_voutput_implementation = { _tdm_voutput_cb_destroy, _tdm_voutput_cb_set_available_modes, + _tdm_voutput_cb_set_available_formats, _tdm_voutput_cb_set_physical_size, _tdm_voutput_cb_connect, _tdm_voutput_cb_disconnect -- 2.7.4 From e1e0134f1c58c97b0b28eb2e26086666c0ec93ea Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Thu, 26 Jul 2018 14:17:09 +0900 Subject: [PATCH 11/16] virtual (client): Use 'wl_array' when client sends available modes to server. Change-Id: I022945ad04eeb7b684305cc6604033c9760b005a --- client/tdm_client.c | 35 ++++++++++++++++------------ protocol/tdm.xml | 17 +------------- src/tdm_server.c | 67 +++++++++++------------------------------------------ 3 files changed, 34 insertions(+), 85 deletions(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index d3e8b47..65c37da 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -1889,6 +1889,25 @@ _tdm_client_voutput_send_available_formats(tdm_private_client_voutput *private_v *format = private_voutput->available_formats.formats[i]; } wl_tdm_voutput_set_available_formats(private_voutput->wl_voutput, &array); + wl_array_release(&array); +} + +void +_tdm_client_voutput_send_available_modes(tdm_private_client_voutput *private_voutput) +{ + tdm_client_output_mode *modes, *mode; + struct wl_array array; + int i, size; + + modes = private_voutput->available_modes.modes; + size = sizeof(tdm_client_output_mode); + + wl_array_init(&array); + for (i = 0; i < private_voutput->available_modes.count; i++) { + mode = wl_array_add(&array, size); + memcpy(mode, &modes[i], size); + } + wl_tdm_voutput_set_available_modes(private_voutput->wl_voutput, &array); wl_array_release(&array); } @@ -1897,8 +1916,6 @@ tdm_client_output_connect(tdm_client_output *output) { tdm_private_client_output *private_output; tdm_private_client_voutput *private_voutput; - tdm_client_output_mode *modes; - int i; TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); @@ -1910,19 +1927,7 @@ tdm_client_output_connect(tdm_client_output *output) private_output->connection = TDM_OUTPUT_CONN_STATUS_CONNECTED; - modes = private_voutput->available_modes.modes; - for (i = 0; i < private_voutput->available_modes.count; i++) { - wl_tdm_voutput_set_available_modes(private_voutput->wl_voutput, i, - modes[i].clock, modes[i].hdisplay, - modes[i].hsync_start, modes[i].hsync_end, - modes[i].htotal, modes[i].hskew, - modes[i].vdisplay, modes[i].vsync_start, - modes[i].vsync_end, modes[i].vtotal, - modes[i].vscan, modes[i].vrefresh, - modes[i].flags, modes[i].type, - modes[i].name); - } - + _tdm_client_voutput_send_available_modes(private_voutput); _tdm_client_voutput_send_available_formats(private_voutput); wl_tdm_voutput_set_physical_size(private_voutput->wl_voutput, private_voutput->mmwidth, private_voutput->mmheight); diff --git a/protocol/tdm.xml b/protocol/tdm.xml index 4cc3aae..f36636e 100644 --- a/protocol/tdm.xml +++ b/protocol/tdm.xml @@ -78,22 +78,7 @@ - - - - - - - - - - - - - - - - + diff --git a/src/tdm_server.c b/src/tdm_server.c index b394618..08fb539 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -730,68 +730,27 @@ static void _tdm_voutput_cb_destroy(struct wl_client *client, struct wl_resource static void _tdm_voutput_cb_set_available_modes(struct wl_client *client, struct wl_resource *resource, - uint32_t index, - uint32_t clock, - uint32_t hdisplay, - uint32_t hsync_start, - uint32_t hsync_end, - uint32_t htotal, - uint32_t hskew, - uint32_t vdisplay, - uint32_t vsync_start, - uint32_t vsync_end, - uint32_t vtotal, - uint32_t vscan, - uint32_t vrefresh, - uint32_t flags, - uint32_t type, - const char *name) + struct wl_array *modes) { tdm_server_voutput_info *voutput_info; - tdm_output_mode *tmp_modes, *old_modes; - tdm_output_mode *new_mode; - int count, len; + tdm_output_mode *mode; + int size, count = 0, i = 0; voutput_info = wl_resource_get_user_data(resource); - count = voutput_info->available_modes.count; - old_modes = voutput_info->available_modes.modes; - if (index >= count) { - if (count > 0) { - tmp_modes = malloc(count * sizeof(*tmp_modes)); - memcpy(tmp_modes, old_modes, count * sizeof(tdm_output_mode)); - } + voutput_info->available_modes.count = 0; + if (voutput_info->available_modes.modes) + free(voutput_info->available_modes.modes); - voutput_info->available_modes.count = index + 1; - voutput_info->available_modes.modes = - realloc(voutput_info->available_modes.modes, - sizeof(tdm_output_mode) * (index + 1)); + wl_array_for_each(mode, modes) + count++; + size = sizeof(tdm_output_mode); - if (count > 0) { - memcpy(voutput_info->available_modes.modes, tmp_modes, count * sizeof(tdm_output_mode)); - free(tmp_modes); - } - } + voutput_info->available_modes.modes = malloc(count * size); + voutput_info->available_modes.count = count; - new_mode = &voutput_info->available_modes.modes[index]; - new_mode->clock = clock; - new_mode->hdisplay = hdisplay; - new_mode->hsync_start = hsync_start; - new_mode->hsync_end = hsync_end; - new_mode->htotal = htotal; - new_mode->hskew= hskew; - new_mode->vdisplay= vdisplay; - new_mode->vsync_start= vsync_start; - new_mode->vsync_end = vsync_end; - new_mode->vtotal = vtotal; - new_mode->vscan = vscan; - new_mode->vrefresh = vrefresh; - new_mode->flags = flags; - new_mode->type = type; - - len = strlen(name); - strncpy(new_mode->name, name, len); - new_mode->name[len] = '\0'; + wl_array_for_each(mode, modes) + memcpy(&voutput_info->available_modes.modes[i++], mode, size); } static void -- 2.7.4 From 20059d63049f7c781c25383cf422f836b478cee1 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Thu, 26 Jul 2018 17:59:59 +0900 Subject: [PATCH 12/16] virtual (client): Add APIs and implementation for related commit. tdm_client_voutput_add_commit_handler() tdm_client_voutput_remove_commit_handler() tdm_client_voutput_commit_done() Change-Id: I895ae3e3478a140086801ab8599233b4d7faabde --- client/tdm_client.c | 135 +++++++++++++++++++++++++++++++++++++++++ client/tdm_client.h | 8 ++- haltests/src/tc_tdm_client.cpp | 32 ++++++++++ protocol/tdm.xml | 3 + src/tdm_server.c | 16 ++++- 5 files changed, 192 insertions(+), 2 deletions(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index 65c37da..9aac858 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -92,6 +92,7 @@ typedef struct _tdm_private_client_output { typedef struct _tdm_private_client_voutput { tdm_private_client_output base; struct wl_tdm_voutput *wl_voutput; + struct list_head commit_handler_list; struct { @@ -157,6 +158,17 @@ typedef struct _tdm_client_wait_info { struct list_head call_link; } tdm_client_wait_info; +typedef struct _tdm_client_voutput_commit_handler_info +{ + tdm_private_client_voutput *private_voutput; + + tdm_client_voutput_commit_handler func; + void *user_data; + + struct list_head link; + struct list_head call_link; +} tdm_client_voutput_commit_handler_info; + static unsigned int _tdm_client_check_wl_error(tdm_private_client *private_client, const char *func, int line) { @@ -1615,6 +1627,33 @@ tdm_client_vblank_is_waiting(tdm_client_vblank *vblank) } void +tdm_client_voutput_cb_commit(void *data, struct wl_tdm_voutput *wl_voutput) +{ + tdm_private_client_voutput *private_voutput; + tdm_private_client *private_client; + tdm_client_voutput_commit_handler_info *h = NULL, *hh = NULL; + struct list_head call_list; + + private_voutput = (tdm_private_client_voutput *)data; + TDM_RETURN_IF_FAIL(private_voutput != NULL); + + private_client = private_voutput->base.private_client; + + LIST_INITHEAD(&call_list); + + LIST_FOR_EACH_ENTRY(h, &private_voutput->commit_handler_list, link) { + LIST_ADDTAIL(&h->call_link, &call_list); + } + + pthread_mutex_unlock(&private_client->lock); + LIST_FOR_EACH_ENTRY_SAFE(h, hh, &call_list, call_link) { + if (h->func) + h->func(private_voutput, h->user_data); + } + pthread_mutex_lock(&private_client->lock); +} + +void tdm_client_voutput_cb_ack_message(void *data, struct wl_tdm_voutput *wl_voutput, uint32_t msg) { tdm_private_client_voutput *private_voutput = data; @@ -1623,6 +1662,7 @@ tdm_client_voutput_cb_ack_message(void *data, struct wl_tdm_voutput *wl_voutput, } static const struct wl_tdm_voutput_listener tdm_client_voutput_lisntener = { + tdm_client_voutput_cb_commit, tdm_client_voutput_cb_ack_message }; @@ -1693,6 +1733,8 @@ tdm_client_create_voutput(tdm_client *client, const char *name, tdm_error *error /* LOCV_EXCL_STOP */ } + LIST_INITHEAD(&private_voutput->commit_handler_list); + private_voutput->base.private_client = private_client; private_voutput->wl_voutput = wl_tdm_create_voutput((struct wl_tdm *)wrapper, private_voutput->base.name); @@ -1742,6 +1784,7 @@ void tdm_client_voutput_destroy(tdm_client_voutput *voutput) { tdm_private_client_voutput *private_voutput = (tdm_private_client_voutput *)voutput; + tdm_client_voutput_commit_handler_info *h = NULL, *hh = NULL; if (!private_voutput) return; @@ -1752,6 +1795,11 @@ tdm_client_voutput_destroy(tdm_client_voutput *voutput) if (private_voutput->available_formats.formats) free(private_voutput->available_formats.formats); + LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_voutput->commit_handler_list, link) { + LIST_DEL(&h->link); + free(h); + } + wl_tdm_voutput_destroy(private_voutput->wl_voutput); free(private_voutput); @@ -1835,6 +1883,93 @@ tdm_client_voutput_set_physical_size(tdm_client_voutput *voutput, unsigned int m return TDM_ERROR_NONE; } +tdm_error +tdm_client_voutput_add_commit_handler(tdm_client_voutput *voutput, + tdm_client_voutput_commit_handler func, + void *user_data) +{ + tdm_private_client_voutput *private_voutput; + tdm_private_client *private_client; + tdm_client_voutput_commit_handler_info *h = NULL; + + TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER); + + private_voutput = (tdm_private_client_voutput *)voutput; + private_client = private_voutput->base.private_client; + + LIST_FOR_EACH_ENTRY(h, &private_voutput->commit_handler_list, link) { + if (h->func == func && h->user_data == user_data) { + TDM_ERR("can't add twice"); + return TDM_ERROR_BAD_REQUEST; + } + } + + h = calloc(1, sizeof *h); + TDM_RETURN_VAL_IF_FAIL(h != NULL, TDM_ERROR_OUT_OF_MEMORY); + + pthread_mutex_lock(&private_client->lock); + + if (CHECK_WL_PROTOCOL_ERROR(private_client)) { + free(h); + pthread_mutex_unlock(&private_client->lock); + return TDM_ERROR_PROTOCOL_ERROR; + } + + h->private_voutput = private_voutput; + h->func = func; + h->user_data = user_data; + LIST_ADDTAIL(&h->link, &private_voutput->commit_handler_list); + LIST_INITHEAD(&h->call_link); + + pthread_mutex_unlock(&private_client->lock); + + return TDM_ERROR_NONE; +} + +void +tdm_client_voutput_remove_commit_handler(tdm_client_voutput *voutput, + tdm_client_voutput_commit_handler func, + void *user_data) +{ + tdm_private_client_voutput *private_voutput; + tdm_private_client *private_client; + tdm_client_voutput_commit_handler_info *h = NULL; + + TDM_RETURN_IF_FAIL(voutput != NULL); + TDM_RETURN_IF_FAIL(func != NULL); + + private_voutput = (tdm_private_client_voutput *)voutput; + private_client = private_voutput->base.private_client; + + pthread_mutex_lock(&private_client->lock); + + LIST_FOR_EACH_ENTRY(h, &private_voutput->commit_handler_list, link) { + if (h->func != func || h->user_data != user_data) + continue; + + LIST_DEL(&h->link); + free(h); + + pthread_mutex_unlock(&private_client->lock); + } + + pthread_mutex_unlock(&private_client->lock); +} + +tdm_error +tdm_client_voutput_commit_done(tdm_client_voutput *voutput) +{ + tdm_private_client_voutput *private_voutput; + + TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER); + + private_voutput = (tdm_private_client_voutput *)voutput; + wl_tdm_voutput_commit_done(private_voutput->wl_voutput); + + return TDM_ERROR_NONE; +} + tdm_client_output * tdm_client_voutput_get_client_output(tdm_client_voutput *voutput, tdm_error *error) { diff --git a/client/tdm_client.h b/client/tdm_client.h index c0ffeb7..d6dc32a 100644 --- a/client/tdm_client.h +++ b/client/tdm_client.h @@ -448,11 +448,17 @@ tdm_error tdm_client_voutput_set_physical_size(tdm_client_voutput *voutput, unsigned int mmWidth, unsigned int mmHeight); tdm_error -tdm_client_voutput_add_commit_handler(tdm_client_voutput *voutput, tdm_client_voutput_commit_handler *func); +tdm_client_voutput_add_commit_handler(tdm_client_voutput *voutput, tdm_client_voutput_commit_handler func, void *user_data); + +void +tdm_client_voutput_remove_commit_handler(tdm_client_voutput *voutput, tdm_client_voutput_commit_handler func, void *user_data); tdm_error tdm_client_voutput_get_committed_tbm_surface(tdm_client_voutput *voutput, tbm_surface_h surface); +tdm_error +tdm_client_voutput_commit_done(tdm_client_voutput *voutput); + tdm_client_output * tdm_client_voutput_get_client_output(tdm_client_voutput *voutput, tdm_error *error); diff --git a/haltests/src/tc_tdm_client.cpp b/haltests/src/tc_tdm_client.cpp index 1ee78c5..fc43491 100644 --- a/haltests/src/tc_tdm_client.cpp +++ b/haltests/src/tc_tdm_client.cpp @@ -1598,6 +1598,38 @@ TEST_F(TDMVirtualOutput, FailTestSetPhysicalSize) ASSERT_EQ(ret, TDM_ERROR_INVALID_PARAMETER); } +static void +_tc_tdm_client_voutput_commit_handler(tdm_client_voutput *voutput, void *user_data) +{ + int *flag; + flag = (int *)user_data; + *flag = 1; +} + +TEST_F(TDMVirtualOutput, AddCommitHandler) +{ + tdm_error ret; + int flag_callback_called = 0; + + ret = tdm_client_voutput_add_commit_handler(this->voutput, + _tc_tdm_client_voutput_commit_handler, + &flag_callback_called); + ASSERT_EQ(ret, TDM_ERROR_NONE); +// ASSERT_EQ(flag_callback_called, 1); + + tdm_client_voutput_remove_commit_handler(this->voutput, + _tc_tdm_client_voutput_commit_handler, + &flag_callback_called); +} + +TEST_F(TDMVirtualOutput, CommitDone) +{ + tdm_error ret; + + ret = tdm_client_voutput_commit_done(this->voutput); + ASSERT_EQ(ret, TDM_ERROR_NONE); +} + TEST_F(TDMVirtualOutput, GetClientOutput) { tdm_error ret; diff --git a/protocol/tdm.xml b/protocol/tdm.xml index f36636e..3de2c0f 100644 --- a/protocol/tdm.xml +++ b/protocol/tdm.xml @@ -94,6 +94,9 @@ + + + diff --git a/src/tdm_server.c b/src/tdm_server.c index 08fb539..b99980b 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -821,13 +821,27 @@ _tdm_voutput_cb_disconnect(struct wl_client *client, struct wl_resource *resourc tdm_output_set_disconnect(voutput_info->output); } +static void +_tdm_voutput_cb_commit_done(struct wl_client *client, struct wl_resource *resource) +{ + tdm_server_voutput_info *voutput_info; + + voutput_info = wl_resource_get_user_data(resource); + if (voutput_info->status != TDM_OUTPUT_CONN_STATUS_CONNECTED) + { + // handle error + return; + } +} + static const struct wl_tdm_voutput_interface tdm_voutput_implementation = { _tdm_voutput_cb_destroy, _tdm_voutput_cb_set_available_modes, _tdm_voutput_cb_set_available_formats, _tdm_voutput_cb_set_physical_size, _tdm_voutput_cb_connect, - _tdm_voutput_cb_disconnect + _tdm_voutput_cb_disconnect, + _tdm_voutput_cb_commit_done }; void -- 2.7.4 From df5d9204977983ae215d9e23325338016c893f09 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Fri, 3 Aug 2018 11:21:10 +0900 Subject: [PATCH 13/16] Revert "virtual (client): Added implementation for setting available format." This reverts commit 7e7fcd357fbec8140bb607ba4f9417baef49f747. Change-Id: Ieac70ebde6f66460664bbae1f10687368b0e64aa --- client/tdm_client.c | 56 ------------------------------------------ client/tdm_client.h | 3 --- haltests/src/tc_tdm_client.cpp | 22 ----------------- protocol/tdm.xml | 4 --- src/tdm_server.c | 31 ----------------------- 5 files changed, 116 deletions(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index 9aac858..92b1626 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -97,12 +97,6 @@ typedef struct _tdm_private_client_voutput { struct { int count; - tbm_format *formats; - } available_formats; - - struct - { - int count; tdm_client_output_mode *modes; } available_modes; @@ -1792,9 +1786,6 @@ tdm_client_voutput_destroy(tdm_client_voutput *voutput) if (private_voutput->available_modes.modes) free(private_voutput->available_modes.modes); - if (private_voutput->available_formats.formats) - free(private_voutput->available_formats.formats); - LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_voutput->commit_handler_list, link) { LIST_DEL(&h->link); free(h); @@ -1835,35 +1826,6 @@ tdm_client_voutput_set_available_modes(tdm_client_voutput *voutput, const tdm_cl } tdm_error -tdm_client_voutput_set_available_formats(tdm_client_voutput *voutput, const tbm_format *formats, const int count) -{ - tdm_private_client_voutput *private_voutput; - - TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER); - - if ((count > 0) && (formats == NULL)) - return TDM_ERROR_INVALID_PARAMETER; - - private_voutput = (tdm_private_client_voutput *)voutput; - - if (private_voutput->base.connection == TDM_OUTPUT_CONN_STATUS_CONNECTED) - return TDM_ERROR_BAD_REQUEST; - - if (private_voutput->available_formats.formats) - free(private_voutput->available_formats.formats); - - private_voutput->available_formats.count = count; - - if (count != 0) - { - private_voutput->available_formats.formats = calloc(count, sizeof(tbm_format)); - memcpy(private_voutput->available_formats.formats, formats, sizeof(tbm_format) * count); - } - - return TDM_ERROR_NONE; -} - -tdm_error tdm_client_voutput_set_physical_size(tdm_client_voutput *voutput, unsigned int mmWidth, unsigned int mmHeight) { tdm_private_client_voutput *private_voutput; @@ -2011,23 +1973,6 @@ tdm_client_output_set_mode(tdm_client_output *output, const tdm_client_output_mo } void -_tdm_client_voutput_send_available_formats(tdm_private_client_voutput *private_voutput) -{ - tbm_format *format; - struct wl_array array; - int i, size; - - size = sizeof(tbm_format); - wl_array_init(&array); - for (i = 0; i < private_voutput->available_formats.count; i++) { - format = wl_array_add(&array, size); - *format = private_voutput->available_formats.formats[i]; - } - wl_tdm_voutput_set_available_formats(private_voutput->wl_voutput, &array); - wl_array_release(&array); -} - -void _tdm_client_voutput_send_available_modes(tdm_private_client_voutput *private_voutput) { tdm_client_output_mode *modes, *mode; @@ -2063,7 +2008,6 @@ tdm_client_output_connect(tdm_client_output *output) private_output->connection = TDM_OUTPUT_CONN_STATUS_CONNECTED; _tdm_client_voutput_send_available_modes(private_voutput); - _tdm_client_voutput_send_available_formats(private_voutput); wl_tdm_voutput_set_physical_size(private_voutput->wl_voutput, private_voutput->mmwidth, private_voutput->mmheight); diff --git a/client/tdm_client.h b/client/tdm_client.h index d6dc32a..f431f1c 100644 --- a/client/tdm_client.h +++ b/client/tdm_client.h @@ -442,9 +442,6 @@ tdm_error tdm_client_voutput_set_available_modes(tdm_client_voutput *voutput, const tdm_client_output_mode *modes, int count); tdm_error -tdm_client_voutput_set_available_formats(tdm_client_voutput *voutput, const tbm_format *formats, const int count); - -tdm_error tdm_client_voutput_set_physical_size(tdm_client_voutput *voutput, unsigned int mmWidth, unsigned int mmHeight); tdm_error diff --git a/haltests/src/tc_tdm_client.cpp b/haltests/src/tc_tdm_client.cpp index fc43491..3d4aa47 100644 --- a/haltests/src/tc_tdm_client.cpp +++ b/haltests/src/tc_tdm_client.cpp @@ -1413,7 +1413,6 @@ protected: static tdm_client *client; static tdm_client_voutput *voutput; const int MODE_COUNT = 2; - const int FORMAT_COUNT = 2; private: static pid_t server_pid; @@ -1541,7 +1540,6 @@ _tc_tdm_client_virutual_make_available_mode(tdm_client_output_mode *modes, int c } } - TEST_F(TDMVirtualOutput, SetAvailableModes) { tdm_error ret; @@ -1567,19 +1565,6 @@ TEST_F(TDMVirtualOutput, FailTestSetAvailableModes) ASSERT_EQ(ret, TDM_ERROR_INVALID_PARAMETER); } -TEST_F(TDMVirtualOutput, SetAvailableFormats) -{ - const int nformats = 2; - tdm_error ret; - tbm_format formats[nformats]; - - formats[0] = TBM_FORMAT_ARGB8888; - formats[1] = TBM_FORMAT_XRGB8888; - - ret = tdm_client_voutput_set_available_formats(this->voutput, formats, nformats); - ASSERT_EQ(ret, TDM_ERROR_NONE); -} - TEST_F(TDMVirtualOutput, SetPhysicalSize) { tdm_error ret; @@ -1642,12 +1627,10 @@ TEST_F(TDMVirtualOutput, GetClientOutput) TEST_F(TDMVirtualOutput, Connect) { - const int nformats = 2; tdm_error ret; tdm_client_output *output; unsigned int mmWidth = 300, mmHeight = 150; tdm_client_output_mode modes[this->MODE_COUNT]; - tbm_format formats[nformats]; int count = this->MODE_COUNT; output = tdm_client_voutput_get_client_output(this->voutput, &ret); @@ -1661,11 +1644,6 @@ TEST_F(TDMVirtualOutput, Connect) ret = tdm_client_voutput_set_available_modes(this->voutput, modes, count); ASSERT_EQ(ret, TDM_ERROR_NONE); - formats[0] = TBM_FORMAT_ARGB8888; - formats[1] = TBM_FORMAT_XRGB8888; - ret = tdm_client_voutput_set_available_formats(this->voutput, formats, nformats); - ASSERT_EQ(ret, TDM_ERROR_NONE); - ret = tdm_client_output_connect(output); ASSERT_EQ(ret, TDM_ERROR_NONE); diff --git a/protocol/tdm.xml b/protocol/tdm.xml index 3de2c0f..b1d6699 100644 --- a/protocol/tdm.xml +++ b/protocol/tdm.xml @@ -81,10 +81,6 @@ - - - - diff --git a/src/tdm_server.c b/src/tdm_server.c index b99980b..c86de65 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -79,11 +79,6 @@ typedef struct _tdm_server_voutput_info { int count; tdm_output_mode *modes; } available_modes; - struct - { - int count; - tbm_format *formats; - } available_formats; unsigned int mmwidth; unsigned int mmheight; @@ -754,31 +749,6 @@ _tdm_voutput_cb_set_available_modes(struct wl_client *client, } static void -_tdm_voutput_cb_set_available_formats(struct wl_client *client, - struct wl_resource *resource, - struct wl_array *formats) -{ - tdm_server_voutput_info *voutput_info; - tbm_format *f; - int count = 0, i = 0; - - voutput_info = wl_resource_get_user_data(resource); - - voutput_info->available_formats.count = 0; - if (voutput_info->available_formats.formats) - free(voutput_info->available_formats.formats); - - wl_array_for_each(f, formats) - count++; - - voutput_info->available_formats.formats = malloc(count * sizeof(tbm_format)); - voutput_info->available_formats.count = count; - - wl_array_for_each(f, formats) - voutput_info->available_formats.formats[i++] = *f; -} - -static void _tdm_voutput_cb_set_physical_size(struct wl_client *client, struct wl_resource *resource, unsigned int mmwidth, unsigned int mmheight) { @@ -837,7 +807,6 @@ _tdm_voutput_cb_commit_done(struct wl_client *client, struct wl_resource *resour static const struct wl_tdm_voutput_interface tdm_voutput_implementation = { _tdm_voutput_cb_destroy, _tdm_voutput_cb_set_available_modes, - _tdm_voutput_cb_set_available_formats, _tdm_voutput_cb_set_physical_size, _tdm_voutput_cb_connect, _tdm_voutput_cb_disconnect, -- 2.7.4 From 52eca1efc87b46a754e8d0de7445d1e84061ced6 Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Wed, 1 Aug 2018 21:34:57 +0900 Subject: [PATCH 14/16] virtual: add protocol to share wl_buffer(tbm_surface) with tdm_client Change-Id: I5066e0a66230b309dc55101276885445ed7968a1 Signed-off-by: Junkyeong Kim --- client/tdm_client.c | 271 ++++++++++++++++++++++++++++++++++++++++++++++++ client/tdm_client.h | 1 + configure.ac | 2 +- packaging/libtdm.spec | 1 + protocol/tdm.xml | 42 ++++++++ src/tdm_private.h | 2 + src/tdm_server.c | 282 +++++++++++++++++++++++++++++++++++++++++++++++++- 7 files changed, 596 insertions(+), 5 deletions(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index 92b1626..53434f1 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -33,6 +33,8 @@ * **************************************************************************/ +#define WL_HIDE_DEPRECATED + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -53,6 +55,8 @@ #include "tdm.h" #include "tdm_private.h" +#define TDM_ARRAY_NTH_DATA(array, type, n) (((type*)((array)->data)) + n) + typedef struct _tdm_private_client_vblank tdm_private_client_vblank; typedef struct _tdm_private_client { @@ -89,6 +93,11 @@ typedef struct _tdm_private_client_output { struct list_head link; } tdm_private_client_output; +typedef struct _tdm_private_client_buffer { + struct list_head link; + struct wl_buffer *wl_buffer; +} tdm_private_client_buffer; + typedef struct _tdm_private_client_voutput { tdm_private_client_output base; struct wl_tdm_voutput *wl_voutput; @@ -104,6 +113,10 @@ typedef struct _tdm_private_client_voutput { unsigned int mmheight; uint32_t msg; + + struct list_head buffer_list; + tbm_bufmgr bufmgr; + tdm_private_client_buffer *commit_buffer; } tdm_private_client_voutput; struct _tdm_private_client_vblank { @@ -1620,6 +1633,223 @@ tdm_client_vblank_is_waiting(tdm_client_vblank *vblank) return (LIST_LENGTH(&private_vblank->wait_list) > 0) ? 1 : 0; } +static tbm_surface_h +_tdm_client_voutput_create_surface_from_param(tbm_bufmgr bufmgr, + int is_fd, + int32_t width, + int32_t height, + uint32_t format, + int32_t bpp, + int32_t size, + int32_t num_plane, + struct wl_array *plane_buf_idx, + struct wl_array *plane_offset, + struct wl_array *plane_stride, + struct wl_array *plane_size, + uint32_t flags, + int32_t num_buf, + uint32_t buf0, + uint32_t buf1, + uint32_t buf2) +{ + int32_t names[TBM_SURF_PLANE_MAX] = { -1, -1, -1, -1}; + tbm_surface_info_s info = { 0, }; + tbm_bo bos[TBM_SURF_PLANE_MAX]; + int i, numPlane, numName; + tbm_surface_h tbm_surface; + + numPlane = tbm_surface_internal_get_num_planes(format); + TDM_RETURN_VAL_IF_FAIL(numPlane == num_plane, NULL); + + info.width = width; + info.height = height; + info.format = format; + info.bpp = bpp; + info.size = size; + info.num_planes = numPlane; + + /*Fill plane info*/ + for (i = 0; i < numPlane; i++) { + info.planes[i].offset = *TDM_ARRAY_NTH_DATA(plane_offset, int32_t, i); + info.planes[i].stride = *TDM_ARRAY_NTH_DATA(plane_stride, int32_t, i); + info.planes[i].size = *TDM_ARRAY_NTH_DATA(plane_size, int32_t, i); + } + + /*Fill buffer*/ + numName = num_buf; + names[0] = buf0; + names[1] = buf1; + names[2] = buf2; + + for (i = 0; i < numName; i++) { + if (is_fd) + bos[i] = tbm_bo_import_fd(bufmgr, names[i]); + else + bos[i] = tbm_bo_import(bufmgr, names[i]); + } + + tbm_surface = tbm_surface_internal_create_with_bos(&info, bos, numName); + if (tbm_surface == NULL) { + if (is_fd) { + close(buf0); + close(buf1); + close(buf2); + } + return NULL; + } + + if (is_fd) { + close(buf0); + close(buf1); + close(buf2); + } + + for (i = 0; i < numName; i++) + tbm_bo_unref(bos[i]); + + return tbm_surface; +} +static void +tdm_client_voutput_cb_buffer_import_with_id(void *data, + struct wl_tdm_voutput *wl_voutput, + struct wl_buffer *wl_buffer, + int32_t width, + int32_t height, + uint32_t format, + int32_t bpp, + int32_t size, + int32_t num_plane, + struct wl_array *plane_buf_idx, + struct wl_array *plane_offset, + struct wl_array *plane_stride, + struct wl_array *plane_size, + uint32_t flags, + int32_t num_buf, + uint32_t buf0, + uint32_t buf1, + uint32_t buf2) +{ + tdm_private_client_voutput *private_voutput = (tdm_private_client_voutput *)data; + tdm_private_client_buffer *buffer = NULL; + tbm_surface_h tbm_surface; + + TDM_RETURN_IF_FAIL(private_voutput != NULL); + + buffer = calloc(1, sizeof *buffer); + TDM_RETURN_IF_FAIL(buffer != NULL); + + tbm_surface = _tdm_client_voutput_create_surface_from_param(private_voutput->bufmgr, 0, + width, height, format, bpp, size, + num_plane, + plane_buf_idx, plane_offset, plane_stride, plane_size, + 0, + num_buf, + buf0, buf1, buf2); + TDM_GOTO_IF_FAIL(tbm_surface != NULL, fail); + + tbm_surface_internal_ref(tbm_surface); + wl_buffer_set_user_data(wl_buffer, tbm_surface); + + buffer->wl_buffer = wl_buffer; + + LIST_ADDTAIL(&buffer->link, &private_voutput->buffer_list); + + return; + +fail: + if (buffer) + free(buffer); + + if (wl_buffer) + wl_buffer_destroy(wl_buffer); +} + +static void +tdm_client_voutput_cb_buffer_import_with_fd(void *data, + struct wl_tdm_voutput *wl_voutput, + struct wl_buffer *wl_buffer, + int32_t width, + int32_t height, + uint32_t format, + int32_t bpp, + int32_t size, + int32_t num_plane, + struct wl_array *plane_buf_idx, + struct wl_array *plane_offset, + struct wl_array *plane_stride, + struct wl_array *plane_size, + uint32_t flags, + int32_t num_buf, + int32_t buf0, + int32_t buf1, + int32_t buf2) +{ + tdm_private_client_voutput *private_voutput = (tdm_private_client_voutput *)data; + tdm_private_client_buffer *buffer = NULL; + tbm_surface_h tbm_surface; + + TDM_RETURN_IF_FAIL(private_voutput != NULL); + + buffer = calloc(1, sizeof *buffer); + TDM_RETURN_IF_FAIL(buffer != NULL); + + tbm_surface = _tdm_client_voutput_create_surface_from_param(private_voutput->bufmgr, 1, + width, height, format, bpp, size, + num_plane, + plane_buf_idx, plane_offset, plane_stride, plane_size, + 0, + num_buf, + buf0, buf1, buf2); + TDM_GOTO_IF_FAIL(tbm_surface != NULL, fail); + + tbm_surface_internal_ref(tbm_surface); + wl_buffer_set_user_data(wl_buffer, tbm_surface); + + buffer->wl_buffer = wl_buffer; + + LIST_ADDTAIL(&buffer->link, &private_voutput->buffer_list); + + return; + +fail: + if (buffer) + free(buffer); + + if (wl_buffer) + wl_buffer_destroy(wl_buffer); +} + +static void +tdm_client_voutput_cb_buffer_destroy(void *data, + struct wl_tdm_voutput *wl_voutput, + struct wl_buffer *wl_buffer) +{ + tdm_private_client_voutput *private_voutput = (tdm_private_client_voutput *)data; + tdm_private_client_buffer *cb = NULL, *cbb = NULL; + tbm_surface_h tbm_surface = NULL; + + TDM_RETURN_IF_FAIL(private_voutput != NULL); + + LIST_FOR_EACH_ENTRY_SAFE(cb, cbb, &private_voutput->buffer_list, link) { + if (wl_buffer == cb->wl_buffer) { + LIST_DEL(&cb->link); + + tbm_surface = (tbm_surface_h)wl_buffer_get_user_data(wl_buffer); + if (tbm_surface) + tbm_surface_internal_unref(tbm_surface); + + wl_buffer_set_user_data(wl_buffer, NULL); + wl_buffer_destroy(wl_buffer); + + free(cb); + + break; + } + } + + return; +} + void tdm_client_voutput_cb_commit(void *data, struct wl_tdm_voutput *wl_voutput) { @@ -1656,6 +1886,9 @@ tdm_client_voutput_cb_ack_message(void *data, struct wl_tdm_voutput *wl_voutput, } static const struct wl_tdm_voutput_listener tdm_client_voutput_lisntener = { + tdm_client_voutput_cb_buffer_import_with_id, + tdm_client_voutput_cb_buffer_import_with_fd, + tdm_client_voutput_cb_buffer_destroy, tdm_client_voutput_cb_commit, tdm_client_voutput_cb_ack_message }; @@ -1723,11 +1956,25 @@ tdm_client_create_voutput(tdm_client *client, const char *name, tdm_error *error TDM_ERR("alloc failed"); if (error) *error = TDM_ERROR_OUT_OF_MEMORY; + pthread_mutex_unlock(&private_client->lock); return NULL; /* LOCV_EXCL_STOP */ } + private_voutput->bufmgr = tbm_bufmgr_init(-1); + if (private_voutput->bufmgr == NULL) { + /* LCOV_EXCL_START */ + TDM_ERR("fail tbm_bufmgr_init"); + free(private_voutput); + if (error) + *error = TDM_ERROR_OUT_OF_MEMORY; + pthread_mutex_unlock(&private_client->lock); + return NULL; + /* LCOV_EXCL_STOP */ + } + LIST_INITHEAD(&private_voutput->commit_handler_list); + LIST_INITHEAD(&private_voutput->buffer_list); private_voutput->base.private_client = private_client; @@ -1783,6 +2030,30 @@ tdm_client_voutput_destroy(tdm_client_voutput *voutput) if (!private_voutput) return; + if (!(LIST_IS_EMPTY(&private_voutput->buffer_list))) { + tdm_private_client_buffer *cb = NULL, *cbb = NULL; + + LIST_FOR_EACH_ENTRY_SAFE(cb, cbb, &private_voutput->buffer_list, link) { + tbm_surface_h tbm_surface = NULL; + + if (!cb) continue; + + LIST_DEL(&cb->link); + + tbm_surface = (tbm_surface_h)wl_buffer_get_user_data(cb->wl_buffer); + if (tbm_surface) + tbm_surface_internal_unref(tbm_surface); + + wl_buffer_set_user_data(cb->wl_buffer, NULL); + wl_buffer_destroy(cb->wl_buffer); + + free(cb); + } + } + + if (private_voutput->bufmgr) + tbm_bufmgr_deinit(private_voutput->bufmgr); + if (private_voutput->available_modes.modes) free(private_voutput->available_modes.modes); diff --git a/client/tdm_client.h b/client/tdm_client.h index f431f1c..420c5e2 100644 --- a/client/tdm_client.h +++ b/client/tdm_client.h @@ -431,6 +431,7 @@ tdm_client_vblank_is_waiting(tdm_client_vblank *vblank); /* Virtual Output */ #include +#include tdm_client_voutput * tdm_client_create_voutput(tdm_client *client, const char *name, tdm_error *error); diff --git a/configure.ac b/configure.ac index 81d3828..51ceb3c 100644 --- a/configure.ac +++ b/configure.ac @@ -45,7 +45,7 @@ fi PKG_CHECK_MODULES(WAYLAND_SCANNER, wayland-scanner >= 1.7.0) PKG_CHECK_MODULES(TDM, dlog libtbm libpng pixman-1 wayland-server iniparser) -PKG_CHECK_MODULES(TDM_CLIENT, dlog wayland-client) +PKG_CHECK_MODULES(TDM_CLIENT, dlog libtbm wayland-client) PKG_CHECK_MODULES(TTRACE, [ttrace], diff --git a/packaging/libtdm.spec b/packaging/libtdm.spec index c915e01..ada8f04 100644 --- a/packaging/libtdm.spec +++ b/packaging/libtdm.spec @@ -13,6 +13,7 @@ BuildRequires: pkgconfig(libtbm) BuildRequires: pkgconfig(libpng) BuildRequires: pkgconfig(ttrace) BuildRequires: pkgconfig(wayland-server) +BuildRequires: pkgconfig(wayland-client) BuildRequires: pkgconfig(iniparser) BuildRequires: pkgconfig(pixman-1) BuildRequires: gtest-devel diff --git a/protocol/tdm.xml b/protocol/tdm.xml index b1d6699..20ba4cd 100644 --- a/protocol/tdm.xml +++ b/protocol/tdm.xml @@ -92,6 +92,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tdm_private.h b/src/tdm_private.h index 02464d8..fea8715 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -268,6 +268,8 @@ tdm_error tdm_output_set_connect(tdm_output *output); tdm_error tdm_output_set_disconnect(tdm_output *output); +tdm_error +tdm_output_send_buffer(tdm_output *output, tbm_surface_h tbm_surface); #ifdef __cplusplus } diff --git a/src/tdm_server.c b/src/tdm_server.c index c86de65..bf38211 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -37,6 +37,8 @@ #include "config.h" #endif +#define WL_HIDE_DEPRECATED + #include #include "tdm_private.h" @@ -66,6 +68,12 @@ typedef struct _tdm_server_output_info { unsigned int watch_output_changes; } tdm_server_output_info; +typedef struct _tdm_server_voutput_buffer { + struct list_head link; + struct wl_resource *wl_buffer; + tbm_surface_h surface; +} tdm_server_voutput_buffer; + typedef struct _tdm_server_voutput_info { struct list_head link; tdm_private_server *private_server; @@ -82,6 +90,9 @@ typedef struct _tdm_server_voutput_info { unsigned int mmwidth; unsigned int mmheight; + + struct list_head buffer_list; + tdm_server_voutput_buffer *attach_buffer; } tdm_server_voutput_info; typedef struct _tdm_server_vblank_info { @@ -813,13 +824,275 @@ static const struct wl_tdm_voutput_interface tdm_voutput_implementation = { _tdm_voutput_cb_commit_done }; +static void +_tdm_voutput_wl_buffer_destroy(struct wl_client *client, struct wl_resource *wl_buffer) +{ + wl_resource_destroy(wl_buffer); +} + +static const struct wl_buffer_interface _tdm_voutput_buffer_impementation = { + _tdm_voutput_wl_buffer_destroy +}; + +static void +_tdm_voutput_buffer_destory(struct wl_resource *wl_buffer) +{ + tdm_server_voutput_info *voutput_info = NULL; + tdm_server_voutput_buffer *vb = NULL; + + voutput_info = (tdm_server_voutput_info *)wl_resource_get_user_data(wl_buffer); + TDM_RETURN_IF_FAIL(voutput_info != NULL); + + LIST_FOR_EACH_ENTRY(vb, &voutput_info->buffer_list, link) { + if (vb->wl_buffer == wl_buffer) { + tbm_surface_internal_unref(vb->surface); + wl_resource_set_user_data(wl_buffer, NULL); + free(vb); + } + } +} + +struct wl_resource * +_tdm_voutput_create_wl_buffer(tdm_server_voutput_info *voutput_info) +{ + struct wl_client *wl_client; + struct wl_resource *wl_buffer = NULL; + + wl_client = wl_resource_get_client(voutput_info->resource); + + /* create a wl_buffer resource */ + wl_buffer = wl_resource_create(wl_client, &wl_buffer_interface, 1, 0); + TDM_RETURN_VAL_IF_FAIL(wl_buffer != NULL, NULL); + + wl_resource_set_implementation(wl_buffer, + (void (**)(void)) &_tdm_voutput_buffer_impementation, + voutput_info, _tdm_voutput_buffer_destory); + + return wl_buffer; +} + +struct wl_resource * +_tdm_voutput_export_buffer(tdm_server_voutput_info *voutput_info, + tbm_surface_h surface) +{ + int bufs[TBM_SURF_PLANE_MAX] = { -1, -1, -1, -1}; + struct wl_resource *wl_buffer = NULL; + int num_buf, is_fd = -1, i; + tbm_surface_info_s info; + uint32_t flags = 0; + struct wl_array plane_buf_idx, plane_offset, plane_stride, plane_size; + int *p; + + TDM_RETURN_VAL_IF_FAIL(voutput_info != NULL, NULL); + TDM_RETURN_VAL_IF_FAIL(surface != NULL, NULL); + + if (tbm_surface_get_info(surface, &info) != TBM_SURFACE_ERROR_NONE) { + TDM_ERR("Failed to create buffer from surface"); + return NULL; + } + + if (info.num_planes > 3) { + TDM_ERR("invalid num_planes(%d)", info.num_planes); + return NULL; + } + + num_buf = tbm_surface_internal_get_num_bos(surface); + if (num_buf == 0) { + TDM_ERR("surface doesn't have any bo."); + return NULL; + } + + for (i = 0; i < num_buf; i++) { + tbm_bo bo = tbm_surface_internal_get_bo(surface, i); + if (bo == NULL) { + TDM_ERR("Failed to get bo from surface"); + goto err; + } + + /* try to get fd first */ + if (is_fd == -1 || is_fd == 1) { + bufs[i] = tbm_bo_export_fd(bo); + if (is_fd == -1 && bufs[i] >= 0) + is_fd = 1; + } + + /* if fail to get fd, try to get name second */ + if (is_fd == -1 || is_fd == 0) { + bufs[i] = tbm_bo_export(bo); + if (is_fd == -1 && bufs[i] > 0) + is_fd = 0; + } + + if (is_fd == -1 || + (is_fd == 1 && bufs[i] < 0) || + (is_fd == 0 && bufs[i] <= 0)) { + TDM_ERR("Failed to export(is_fd:%d, bufs:%d)", is_fd, bufs[i]); + goto err; + } + } + + wl_buffer = _tdm_voutput_create_wl_buffer(voutput_info); + if (!wl_buffer) { + TDM_ERR("Failed to create wl_buffer"); + goto err; + } + + wl_array_init(&plane_buf_idx); + wl_array_init(&plane_offset); + wl_array_init(&plane_stride); + wl_array_init(&plane_size); + + for (i = 0; i < 3; i++) { + p = wl_array_add(&plane_buf_idx, sizeof(int)); + *p = tbm_surface_internal_get_plane_bo_idx(surface, i); + p = wl_array_add(&plane_offset, sizeof(int)); + *p = info.planes[i].offset; + p = wl_array_add(&plane_stride, sizeof(int)); + *p = info.planes[i].stride; + p = wl_array_add(&plane_size, sizeof(int)); + *p = info.planes[i].size; + } + + if (is_fd == 1) + wl_tdm_voutput_send_buffer_set_with_fd(voutput_info->resource, + wl_buffer, + info.width, info.height, info.format, info.bpp, info.size, info.num_planes, + &plane_buf_idx, &plane_offset, &plane_stride, &plane_size, + flags, num_buf, bufs[0], + (bufs[1] == -1) ? bufs[0] : bufs[1], + (bufs[2] == -1) ? bufs[0] : bufs[2]); + else + wl_tdm_voutput_send_buffer_set_with_id(voutput_info->resource, + wl_buffer, + info.width, info.height, info.format, info.bpp, info.size, info.num_planes, + &plane_buf_idx, &plane_offset, &plane_stride, &plane_size, + flags, + num_buf, bufs[0], bufs[1], bufs[2]); + + wl_array_release(&plane_buf_idx); + wl_array_release(&plane_offset); + wl_array_release(&plane_stride); + wl_array_release(&plane_size); + + for (i = 0; i < TBM_SURF_PLANE_MAX; i++) { + if (is_fd == 1 && (bufs[i] >= 0)) + close(bufs[i]); + } + + return wl_buffer; + +err: + for (i = 0; i < TBM_SURF_PLANE_MAX; i++) { + if (is_fd == 1 && (bufs[i] >= 0)) + close(bufs[i]); + } + + return NULL; +} + +tdm_server_voutput_buffer * +_tdm_output_get_voutput_buffer(tdm_server_voutput_info *voutput_info, tbm_surface_h surface) +{ + tdm_server_voutput_buffer *voutput_buffer = NULL, *vb = NULL; + + LIST_FOR_EACH_ENTRY(vb, &voutput_info->buffer_list, link) { + if (vb && vb->surface == surface) + return vb; + } + + tbm_surface_internal_ref(surface); + voutput_buffer = calloc(1, sizeof *voutput_buffer); + if (!voutput_buffer) { + /* LCOV_EXCL_START */ + + TDM_ERR("fail calloc"); + tbm_surface_internal_unref(surface); + return NULL; + + /* LCOV_EXCL_STOP */ + } + + voutput_buffer->wl_buffer = _tdm_voutput_export_buffer(voutput_info, surface); + if (!voutput_buffer->wl_buffer) { + /* LCOV_EXCL_START */ + + TDM_ERR("fail export buffer"); + free(voutput_buffer); + tbm_surface_internal_unref(surface); + return NULL; + + /* LCOV_EXCL_STOP */ + } + + voutput_buffer->surface = surface; + LIST_ADDTAIL(&voutput_info->link, &voutput_info->buffer_list); + + return voutput_buffer; +} + +tdm_error +tdm_output_send_buffer(tdm_output *output, tbm_surface_h surface) +{ + tdm_private_server *private_server = keep_private_server; + tdm_server_voutput_info *voutput_info = NULL, *vo = NULL; + tdm_server_voutput_buffer *voutput_buffer = NULL; + + TDM_RETURN_VAL_IF_FAIL(keep_private_server != NULL, TDM_ERROR_OPERATION_FAILED); + + LIST_FOR_EACH_ENTRY(vo, &private_server->voutput_list, link) { + if (vo && vo->output == output) { + voutput_info = vo; + break; + } + } + TDM_RETURN_VAL_IF_FAIL(voutput_info != NULL, TDM_ERROR_INVALID_PARAMETER); + + voutput_buffer = _tdm_output_get_voutput_buffer(voutput_info, surface); + TDM_RETURN_VAL_IF_FAIL(voutput_buffer != NULL, TDM_ERROR_OUT_OF_MEMORY); + + voutput_info->attach_buffer = voutput_buffer; + + return TDM_ERROR_NONE; +} + +tdm_error +tdm_output_commit_buffer(tdm_output *output) +{ + tdm_private_server *private_server = keep_private_server; + tdm_server_voutput_info *voutput_info = NULL, *vo = NULL; + + TDM_RETURN_VAL_IF_FAIL(keep_private_server != NULL, TDM_ERROR_OPERATION_FAILED); + + LIST_FOR_EACH_ENTRY(vo, &private_server->voutput_list, link) { + if (vo && vo->output == output) { + voutput_info = vo; + break; + } + } + TDM_RETURN_VAL_IF_FAIL(voutput_info != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(voutput_info->attach_buffer != NULL, TDM_ERROR_INVALID_PARAMETER); + + wl_tdm_voutput_send_commit(voutput_info->resource); + + return TDM_ERROR_NONE; +} + void tdm_voutput_cb_resource_destroy(struct wl_resource *resource) { tdm_server_voutput_info *voutput_info = wl_resource_get_user_data(resource); - + tdm_server_voutput_buffer *vb, *vbb; TDM_RETURN_IF_FAIL(voutput_info != NULL); + LIST_FOR_EACH_ENTRY_SAFE(vb, vbb, &voutput_info->buffer_list, link) { + if (!vb) continue; + + LIST_DEL(&vb->link); + + if (vb->wl_buffer) + wl_resource_destroy(vb->wl_buffer); + } + LIST_DEL(&voutput_info->link); /* Do free your own resource */ @@ -881,6 +1154,7 @@ _tdm_server_cb_create_virtual_output(struct wl_client *client, struct wl_resourc voutput_info->resource = voutput_resource; voutput_info->output = output; LIST_INITHEAD(&voutput_info->output_list); + LIST_INITHEAD(&voutput_info->buffer_list); wl_resource_set_implementation(voutput_resource, &tdm_voutput_implementation, @@ -1047,7 +1321,7 @@ INTERN void tdm_server_deinit(tdm_private_loop *private_loop) { tdm_server_output_info *o = NULL, *oo = NULL; -// tdm_server_voutput_info *vo = NULL, *voo = NULL; + tdm_server_voutput_info *vo = NULL, *voo = NULL; tdm_server_wait_info *w = NULL, *ww = NULL; tdm_server_client_info *c = NULL, *cc = NULL; tdm_private_server *private_server; @@ -1064,11 +1338,11 @@ tdm_server_deinit(tdm_private_loop *private_loop) LIST_FOR_EACH_ENTRY_SAFE(o, oo, &private_server->output_list, link) { wl_resource_destroy(o->resource); } -#if 0 + LIST_FOR_EACH_ENTRY_SAFE(vo, voo, &private_server->voutput_list, link) { wl_resource_destroy(vo->resource); } -#endif + LIST_FOR_EACH_ENTRY_SAFE(c, cc, &client_list, link) { wl_resource_destroy(c->resource); } -- 2.7.4 From 17a49e755585adc9926ebaa00b34ac39ed79bdd5 Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Mon, 6 Aug 2018 13:39:36 +0900 Subject: [PATCH 15/16] move tbm_surface_internal.h file to c file. Change-Id: I71ad0dfdb2919f6dc9cba2f1eccc08009913b746 --- client/tdm_client.c | 1 + client/tdm_client.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index 53434f1..32bdb52 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -54,6 +54,7 @@ #include "tdm_list.h" #include "tdm.h" #include "tdm_private.h" +#include #define TDM_ARRAY_NTH_DATA(array, type, n) (((type*)((array)->data)) + n) diff --git a/client/tdm_client.h b/client/tdm_client.h index 420c5e2..f431f1c 100644 --- a/client/tdm_client.h +++ b/client/tdm_client.h @@ -431,7 +431,6 @@ tdm_client_vblank_is_waiting(tdm_client_vblank *vblank); /* Virtual Output */ #include -#include tdm_client_voutput * tdm_client_create_voutput(tdm_client *client, const char *name, tdm_error *error); -- 2.7.4 From 69e26b823f4c84b3f7a74d43176340d58f03f10f Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 26 Mar 2018 17:04:33 +0900 Subject: [PATCH 16/16] virtual: add output create/destroy interface Change-Id: I1ee25761ef62df057c4bbfa63408f47501cda380 --- include/tdm.h | 23 +++++++++++++++++++++++ include/tdm_backend.h | 9 +++++++++ include/tdm_common.h | 1 + 3 files changed, 33 insertions(+) diff --git a/include/tdm.h b/include/tdm.h index 7beccd0..979c35e 100644 --- a/include/tdm.h +++ b/include/tdm.h @@ -206,6 +206,16 @@ tdm_display_get_output_count(tdm_display *dpy, int *count); tdm_output * tdm_display_get_output(tdm_display *dpy, int index, tdm_error *error); +tdm_error +tdm_display_add_output_create_handler(tdm_display *dpy, + tdm_output_create_handler func, + void *user_data); + +void +tdm_display_remove_output_create_handler(tdm_display *dpy, + tdm_output_create_handler func, + void *user_data); + /** * @brief Find a output object which has the given name. * @param[in] dpy A display object @@ -238,6 +248,16 @@ tdm_error tdm_module_get_info(tdm_module *module, const char **name, const char **vendor, int *major, int *minor); +tdm_error +tdm_output_add_destroy_handler(tdm_output *output, + tdm_output_destroy_handler func, + void *user_data); + +void +tdm_output_remove_destroy_handler(tdm_output *output, + tdm_output_destroy_handler func, + void *user_data); + /** * @brief Get a backend module object of the given output. * @param[in] output A output object @@ -761,6 +781,9 @@ tdm_layer_get_displaying_buffer(tdm_layer *layer, tdm_error *error); tdm_error tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue); +tdm_error +tdm_layer_get_own_buffer_queue(tdm_layer *layer, tbm_surface_queue_h *buffer_queue); + /** * @brief Unset a TBM surface_queue from a layer object * @details When this function is called, a current surface_queue will be diff --git a/include/tdm_backend.h b/include/tdm_backend.h index 72136b1..a28654a 100644 --- a/include/tdm_backend.h +++ b/include/tdm_backend.h @@ -682,6 +682,15 @@ typedef struct _tdm_func_layer { */ tdm_error (*layer_get_buffer_flags)(tdm_layer *layer, unsigned int *flags); + /** + * @brief Get buffer queue which the layer offers. + * @param[in] layer A layer object + * @param[out] buffer_queue The buffer queue + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @since 2.0.0 + */ + tdm_error (*layer_get_buffer_queue)(tdm_layer *layer, tbm_surface_queue_h *buffer_queue); + void (*reserved1)(void); void (*reserved2)(void); void (*reserved3)(void); diff --git a/include/tdm_common.h b/include/tdm_common.h index 328f837..cc79e90 100644 --- a/include/tdm_common.h +++ b/include/tdm_common.h @@ -134,6 +134,7 @@ typedef enum { TDM_LAYER_CAPABILITY_SCANOUT = (1 << 10), /**< if a layer allows a scanout buffer only */ TDM_LAYER_CAPABILITY_RESEVED_MEMORY = (1 << 11), /**< if a layer allows a reserved buffer only */ TDM_LAYER_CAPABILITY_NO_CROP = (1 << 12), /**< if a layer has no cropping capability */ + TDM_LAYER_CAPABILITY_BUFFER_QUEUE = (1 << 13), /**< if a layer has an own buffer queue */ } tdm_layer_capability; /** -- 2.7.4