From: Junkyeong Kim Date: Wed, 18 Jul 2018 10:31:12 +0000 (+0900) Subject: virtual:add virtual output create/destroy X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7e1f4f71006d85a16303b0b70e5b9d0e45b7e9ec;hp=eca0e8c8a3a8b1a4b27823a87a35f81044f10a77;p=platform%2Fcore%2Fuifw%2Flibtdm.git virtual:add virtual output create/destroy Change-Id: Ib8ef9133c166e8fc67a9b338667941fe35849764 Signed-off-by: Junkyeong Kim --- diff --git a/backends/virtual/tdm_virtual.c b/backends/virtual/tdm_virtual.c index f890829..9c9e4dd 100644 --- a/backends/virtual/tdm_virtual.c +++ b/backends/virtual/tdm_virtual.c @@ -63,6 +63,8 @@ tdm_virtual_init(tdm_display *dpy, tdm_error *error) virtual_func_display.display_get_outputs = virtual_display_get_outputs; virtual_func_display.display_get_fd = virtual_display_get_fd; virtual_func_display.display_handle_events = virtual_display_handle_events; + virtual_func_display.display_output_create = virtual_display_output_create; + virtual_func_display.display_output_destroy = virtual_display_output_destroy; memset(&virtual_func_output, 0, sizeof(virtual_func_output)); virtual_func_output.output_get_capability = virtual_output_get_capability; @@ -100,7 +102,7 @@ tdm_virtual_init(tdm_display *dpy, tdm_error *error) ret = TDM_ERROR_OPERATION_FAILED; goto failed; } - +#if 0 ret = tdm_virtual_display_create_output_list(virtual_data); if (ret != TDM_ERROR_NONE) goto failed; @@ -108,7 +110,7 @@ tdm_virtual_init(tdm_display *dpy, tdm_error *error) ret = tdm_virtual_display_create_layer_list(virtual_data); if (ret != TDM_ERROR_NONE) goto failed; - +#endif if (error) *error = TDM_ERROR_NONE; diff --git a/backends/virtual/tdm_virtual.h b/backends/virtual/tdm_virtual.h index 2a25ab6..f1cdf91 100644 --- a/backends/virtual/tdm_virtual.h +++ b/backends/virtual/tdm_virtual.h @@ -25,52 +25,52 @@ #include /* virtual backend functions (display) */ -tdm_error virtual_display_get_capability(tdm_backend_data *bdata, tdm_caps_display *caps); -tdm_output** virtual_display_get_outputs(tdm_backend_data *bdata, int *count, tdm_error *error); -tdm_error virtual_display_get_fd(tdm_backend_data *bdata, int *fd); -tdm_error virtual_display_handle_events(tdm_backend_data *bdata); +tdm_error virtual_display_get_capability(tdm_backend_data *bdata, tdm_caps_display *caps); +tdm_output **virtual_display_get_outputs(tdm_backend_data *bdata, int *count, tdm_error *error); +tdm_error virtual_display_get_fd(tdm_backend_data *bdata, int *fd); +tdm_error virtual_display_handle_events(tdm_backend_data *bdata); +tdm_output *virtual_display_output_create(tdm_backend_data *bdata, const char* name, tdm_error *error); +tdm_error virtual_display_output_destroy(tdm_backend_data *bdata, tdm_output *output); -tdm_error virtual_output_get_capability(tdm_output *output, tdm_caps_output *caps); -tdm_layer** virtual_output_get_layers(tdm_output *output, int *count, tdm_error *error); -tdm_error virtual_output_wait_vblank(tdm_output *output, int interval, int sync, void *user_data); -tdm_error virtual_output_set_vblank_handler(tdm_output *output, tdm_output_vblank_handler func); -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_get_capability(tdm_output *output, tdm_caps_output *caps); +tdm_layer **virtual_output_get_layers(tdm_output *output, int *count, tdm_error *error); +tdm_error virtual_output_wait_vblank(tdm_output *output, int interval, int sync, void *user_data); +tdm_error virtual_output_set_vblank_handler(tdm_output *output, tdm_output_vblank_handler func); +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_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps); -tdm_error virtual_layer_set_info(tdm_layer *layer, tdm_info_layer *info); -tdm_error virtual_layer_get_info(tdm_layer *layer, tdm_info_layer *info); -tdm_error virtual_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer); -tdm_error virtual_layer_unset_buffer(tdm_layer *layer); +tdm_error virtual_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps); +tdm_error virtual_layer_set_info(tdm_layer *layer, tdm_info_layer *info); +tdm_error virtual_layer_get_info(tdm_layer *layer, tdm_info_layer *info); +tdm_error virtual_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer); +tdm_error virtual_layer_unset_buffer(tdm_layer *layer); #define RETURN_VAL_IF_FAIL(cond, val) {\ - if (!(cond)) {\ - TDM_ERR("'%s' failed", #cond);\ - return val;\ - }\ + if (!(cond)) {\ + TDM_ERR("'%s' failed", #cond);\ + return val;\ + }\ } #define GOTO_IF_FAIL(cond, val) {\ - if (!(cond)) {\ - TDM_ERR("'%s' failed", #cond);\ - goto val;\ - }\ + if (!(cond)) {\ + TDM_ERR("'%s' failed", #cond);\ + goto val;\ + }\ } typedef struct _tdm_virtual_data { - tdm_display *dpy; + tdm_display *dpy; - int pipe[2]; + int pipe[2]; - struct list_head output_list; - struct list_head buffer_list; + struct list_head output_list; + struct list_head buffer_list; } tdm_virtual_data; -tdm_error tdm_virtual_display_create_output_list(tdm_virtual_data *virtual_data); void tdm_virtual_display_destroy_output_list(tdm_virtual_data *virtual_data); -tdm_error tdm_virtual_display_create_layer_list(tdm_virtual_data *virtual_data); #endif /* _TDM_VIRTUAL_H_ */ diff --git a/backends/virtual/tdm_virtual_display.c b/backends/virtual/tdm_virtual_display.c index 185f10d..9bf7363 100644 --- a/backends/virtual/tdm_virtual_display.c +++ b/backends/virtual/tdm_virtual_display.c @@ -29,6 +29,7 @@ struct _tdm_virtual_output_data { uint32_t pipe; tdm_output_mode *output_mode; + int mode_count; tdm_output_type connector_type; struct list_head layer_list; tdm_virtual_layer_data *primary_layer; @@ -45,6 +46,11 @@ struct _tdm_virtual_output_data { tdm_event_loop_source *timer; unsigned int timer_waiting; struct list_head timer_event_list; + + unsigned int mmwidth; + unsigned int mmheight; + + char name[TDM_NAME_LEN]; /**< The output name */ }; struct _tdm_virtual_layer_data { @@ -233,7 +239,7 @@ tdm_virtual_display_create_output_list(tdm_virtual_data *virtual_data) output_data->virtual_data = virtual_data; output_data->pipe = 0; output_data->connector_type = TDM_OUTPUT_TYPE_Unknown; - output_data->status = TDM_OUTPUT_CONN_STATUS_CONNECTED; + output_data->status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED; output_data->output_mode = calloc(1, sizeof(tdm_output_mode)); if (!output_data->output_mode) { @@ -351,6 +357,131 @@ virtual_display_handle_events(tdm_backend_data *bdata) return TDM_ERROR_NONE; } +tdm_output * +virtual_display_output_create(tdm_backend_data *bdata, const char *name, tdm_error *error) +{ + tdm_virtual_data *virtual_data = bdata; + tdm_virtual_output_data *output_data = NULL; + tdm_virtual_layer_data *layer_data = NULL; + tdm_error ret; + + if (!virtual_data || !name) { + TDM_ERR("invalid parameter"); + *error = TDM_ERROR_INVALID_PARAMETER; + return NULL; + } + + output_data = calloc(1, sizeof(tdm_virtual_output_data)); + if (!output_data) { + TDM_ERR("alloc failed"); + *error = TDM_ERROR_OUT_OF_MEMORY; + return NULL; + } + + LIST_INITHEAD(&output_data->layer_list); + + output_data->virtual_data = virtual_data; + output_data->pipe = 0; + output_data->connector_type = TDM_OUTPUT_TYPE_Unknown; + output_data->status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED; + + if (name) + snprintf(output_data->name, TDM_NAME_LEN, "%s", name); + 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) { + 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; + + output_data->mode_count = 1; +#endif + output_data->timer = tdm_event_loop_add_timer_handler(virtual_data->dpy, + _tdm_virtual_display_cb_timeout, + output_data, + &ret); + if (!output_data->timer) goto create_fail; + + LIST_INITHEAD(&output_data->timer_event_list); + + /* The TDM virtual backend output support only one layer. */ + layer_data = calloc(1, sizeof(tdm_virtual_layer_data)); + if (!layer_data) { + TDM_ERR("alloc failed"); + ret = TDM_ERROR_OUT_OF_MEMORY; + goto create_fail; + } + + layer_data->virtual_data = virtual_data; + layer_data->output_data = output_data; + layer_data->zpos = 0; + + layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY | TDM_LAYER_CAPABILITY_GRAPHIC; + output_data->primary_layer = layer_data; + + LIST_ADDTAIL(&layer_data->link, &output_data->layer_list); + + ret = tdm_backend_register_output(virtual_data->dpy, output_data); + GOTO_IF_FAIL(ret == TDM_ERROR_NONE, create_fail); + + *error = TDM_ERROR_NONE; + + return output_data; + +create_fail: + if (layer_data) free(layer_data); + if (output_data->output_mode) free(output_data->output_mode); + free(output_data); + + *error = ret; + + return NULL; +} + +tdm_error +virtual_display_output_destroy(tdm_backend_data *bdata, tdm_output *output) +{ + tdm_virtual_data *virtual_data = bdata; + tdm_virtual_output_data *o, *output_data = output; + int find = 0; + + RETURN_VAL_IF_FAIL(virtual_data, TDM_ERROR_INVALID_PARAMETER); + RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER); + + LIST_FOR_EACH_ENTRY(o, &virtual_data->output_list, link) { + if (o == output_data) { + find = 1; + break; + } + } + + if (find) + tdm_backend_unregister_output(virtual_data->dpy, output); + else + return TDM_ERROR_INVALID_PARAMETER; + + return TDM_ERROR_NONE; +} + tdm_error virtual_output_get_capability(tdm_output *output, tdm_caps_output *caps) { @@ -364,24 +495,26 @@ virtual_output_get_capability(tdm_output *output, tdm_caps_output *caps) snprintf(caps->maker, TDM_NAME_LEN, "virtual"); snprintf(caps->model, TDM_NAME_LEN, "virtual"); - snprintf(caps->name, TDM_NAME_LEN, "virtual"); + snprintf(caps->name, TDM_NAME_LEN, "%s", output_data->name); caps->status = output_data->status; caps->type = output_data->connector_type; caps->type_id = 0; - caps->mode_count = 1; - caps->modes = calloc(1, sizeof(tdm_output_mode)); - if (!caps->modes) { - ret = TDM_ERROR_OUT_OF_MEMORY; - TDM_ERR("alloc failed\n"); - goto failed_get; - } + 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; + } - *caps->modes = *output_data->output_mode; + *caps->modes = *output_data->output_mode; + } - caps->mmWidth = 640; - caps->mmHeight = 480; + caps->mmWidth = output_data->mmwidth; + caps->mmHeight =output_data->mmheight; caps->subpixel = 1; caps->min_w = -1; diff --git a/haltests/src/tc_tdm_client.cpp b/haltests/src/tc_tdm_client.cpp index 20aa27f..f7ff9f8 100644 --- a/haltests/src/tc_tdm_client.cpp +++ b/haltests/src/tc_tdm_client.cpp @@ -50,6 +50,15 @@ enum { TDM_UT_PIPE_MSG_TERMINATE_SERVER, }; +#define TDM_UT_WAIT(fmt, ...) \ + do { \ + char ch; \ + do { \ + printf(fmt" [n]):next ", ##__VA_ARGS__); \ + ch = tc_tdm_getchar(); \ + } while(ch != 'n'); \ + } while (0) + static int _tc_tdm_pipe_read_msg(int fd); static bool _tc_tdm_pipe_write_msg(int fd, int reply_fd, int msg); static pid_t _tc_tdm_client_server_fork(int *pipe_to_parent, int *pipe_to_child); @@ -200,6 +209,23 @@ bool TDMClient::PrepareVblank(void) return true; } +char +tc_tdm_getchar(void) +{ + int c = getchar(); + int ch = c; + + if (ch == '\n' || ch == '\r') + ch = 'y'; + else if (ch < 'a') + ch += ('a' - 'A'); + + while (c != '\n' && c != EOF) + c = getchar(); + + return ch; +} + static int _tc_tdm_pipe_read_msg(int fd) { @@ -1478,9 +1504,13 @@ bool TDMVirtualOutput::PrepareVOutput(void) TDM_UT_RETURN_FALSE_IF_FAIL(ret == TDM_ERROR_NONE); TDM_UT_RETURN_FALSE_IF_FAIL(client != NULL); + voutput = tdm_client_create_voutput(client, name, &ret); TDM_UT_RETURN_FALSE_IF_FAIL(ret == TDM_ERROR_NONE); TDM_UT_RETURN_FALSE_IF_FAIL(voutput != NULL); + +// TDM_UT_WAIT("check & press"); + return true; } diff --git a/include/tdm_backend.h b/include/tdm_backend.h index e9fc70d..9a30004 100644 --- a/include/tdm_backend.h +++ b/include/tdm_backend.h @@ -335,8 +335,10 @@ typedef struct _tdm_func_display { */ tdm_pp *(*display_create_pp)(tdm_backend_data *bdata, tdm_error *error); - void (*reserved1)(void); - void (*reserved2)(void); + /* virtual */ + tdm_output *(*display_output_create)(tdm_backend_data *bdata, const char *name, tdm_error *error); + tdm_error (*display_output_destroy)(tdm_backend_data *bdata, tdm_output *output); + void (*reserved3)(void); void (*reserved4)(void); void (*reserved5)(void); diff --git a/src/tdm_display.c b/src/tdm_display.c index 9f6dd72..a355ab7 100644 --- a/src/tdm_display.c +++ b/src/tdm_display.c @@ -815,6 +815,68 @@ tdm_display_find_output(tdm_display *dpy, const char *name, tdm_error *error) return NULL; } +INTERN tdm_output * +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_func_display *func_display = NULL; + tdm_output *output = NULL; + + DISPLAY_FUNC_ENTRY_ERROR(); + + TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy != NULL, TDM_ERROR_INVALID_PARAMETER, NULL); + private_display = (tdm_private_display*)dpy; + + private_module = private_display->virtual_module; + TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_module != NULL, TDM_ERROR_BAD_MODULE, NULL); + + _pthread_mutex_lock(&private_display->lock); + + if (error) + *error = TDM_ERROR_NONE; + + func_display = &private_module->func_display; + current_module = private_display->current_module; + private_display->current_module = private_module; + output = func_display->display_output_create(private_module->bdata, name, &ret); + private_display->current_module = current_module; + + _pthread_mutex_unlock(&private_display->lock); + + TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(output != NULL, ret, NULL); + + return output; +} + +INTERN tdm_error +tdm_display_destroy_output(tdm_display *dpy, tdm_output *output) +{ + tdm_private_module *private_module = NULL; + tdm_private_module *current_module = NULL; + tdm_func_display *func_display = NULL; + + DISPLAY_FUNC_ENTRY(); + + TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); + private_display = (tdm_private_display*)dpy; + + private_module = private_display->virtual_module; + TDM_RETURN_VAL_IF_FAIL(private_module != NULL, TDM_ERROR_BAD_MODULE); + + _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); + private_display->current_module = current_module; + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} + EXTERN tdm_error tdm_display_get_fd(tdm_display *dpy, int *fd) { diff --git a/src/tdm_private.h b/src/tdm_private.h index 6478221..d747993 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -255,6 +255,11 @@ tdm_config_deinit(void); void tdm_monitor_server_command(tdm_display *dpy, const char *options, char *reply, int *len); +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); + #ifdef __cplusplus } #endif diff --git a/src/tdm_server.c b/src/tdm_server.c index d77151c..d98339c 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -53,6 +53,7 @@ struct _tdm_private_server { tdm_private_loop *private_loop; struct list_head output_list; + struct list_head voutput_list; struct list_head wait_list; }; @@ -65,6 +66,14 @@ typedef struct _tdm_server_output_info { unsigned int watch_output_changes; } tdm_server_output_info; +typedef struct _tdm_server_voutput_info { + struct list_head link; + tdm_private_server *private_server; + struct wl_resource *resource; + tdm_output *output; + struct list_head output_list; +} tdm_server_voutput_info; + typedef struct _tdm_server_vblank_info { struct list_head link; tdm_server_output_info *output_info; @@ -593,7 +602,19 @@ 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) @@ -686,6 +707,26 @@ static void _tdm_server_cb_create_virtual_output(struct wl_client *client, struct wl_resource *resource, const char *name, uint32_t id) { struct wl_resource *voutput_resource = NULL; + tdm_private_server *private_server = wl_resource_get_user_data(resource); + tdm_server_voutput_info *voutput_info; + tdm_output *output; + tdm_error ret; + + output = tdm_display_find_output(private_server->private_loop->dpy, name, NULL); + if (output) { + TDM_ERR("There is '%s' output, cannot create.", name); + wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, + "There is '%s' output", name); + return; + } + + output = tdm_display_create_output(private_server->private_loop->dpy, name, &ret); + if (!output) { + TDM_ERR("output creation fail(%s)(%d).", name, ret); + wl_resource_post_error(resource, WL_DISPLAY_ERROR_NO_MEMORY, + "%s output creation fail", name); + return; + } voutput_resource = wl_resource_create(client, &wl_tdm_voutput_interface, @@ -700,6 +741,27 @@ _tdm_server_cb_create_virtual_output(struct wl_client *client, struct wl_resourc /* LCOV_EXCL_STOP */ } + voutput_info = calloc(1, sizeof * voutput_info); + if (!voutput_info) { + /* LCOV_EXCL_START */ + + wl_resource_post_no_memory(resource); + wl_resource_destroy(voutput_resource); + TDM_ERR("alloc failed"); + return; + + /* LCOV_EXCL_STOP */ + } + + LIST_ADDTAIL(&voutput_info->link, &private_server->voutput_list); + voutput_info->private_server = private_server; + voutput_info->resource = voutput_resource; + voutput_info->output = output; + LIST_INITHEAD(&voutput_info->output_list); +#if 0 + wl_resource_set_implementation(voutput_resource, &tdm_voutput_implementation, + voutput_info, destroy_voutput_callback); +#endif wl_tdm_voutput_send_ack_message(voutput_resource, WL_TDM_VOUTPUT_MESSAGE_ADDED); } @@ -833,6 +895,7 @@ tdm_server_init(tdm_private_loop *private_loop) } LIST_INITHEAD(&private_server->output_list); + LIST_INITHEAD(&private_server->voutput_list); LIST_INITHEAD(&private_server->wait_list); if (!wl_global_create(private_loop->wl_display, &wl_tdm_interface, 1, @@ -859,6 +922,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_wait_info *w = NULL, *ww = NULL; tdm_server_client_info *c = NULL, *cc = NULL; tdm_private_server *private_server; @@ -875,7 +939,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); }