virtual: add tdm virtual output test to tdm_test with V option
[platform/core/uifw/libtdm.git] / tools / tdm_test_server.c
index 535462f..b439540 100644 (file)
@@ -108,6 +108,10 @@ static struct optstrings optstrs[] = {
                "<output_idx>[,<layer_idx>]~<w>x<h>[+<x>+<y>][,<h>x<v>][@<format>][*<transform>][^stream]", NULL
        },
        {
+               OPT_TST, "V", "virtual output test.\n\t\t'-l' is used to show the result on screen.",
+               NULL, NULL
+       },
+       {
                OPT_GEN, "w", "set the property of a object",
                "<prop_name>:<value>", NULL
        },
@@ -217,6 +221,7 @@ TDM_BIT_NAME_FB(buf_flag)
 typedef struct _tdm_test_server tdm_test_server;
 typedef struct _tdm_test_server_layer tdm_test_server_layer;
 typedef struct _tdm_test_server_capture tdm_test_server_capture;
+typedef struct _tdm_test_server_voutput tdm_test_server_voutput;
 
 typedef struct _tdm_test_server_prop {
        /* args */
@@ -300,11 +305,21 @@ struct _tdm_test_server_layer {
        int buf_idx;
 };
 
+struct _tdm_test_server_voutput {
+       struct list_head link;
+       tdm_test_server *data;
+       tdm_output *output;
+       tdm_layer *layer;
+       tbm_surface_h bufs[3];
+       int buf_idx;
+};
+
 struct _tdm_test_server {
        /* args */
        int do_query;
        int do_all;
        int do_vblank;
+       int do_voutput;
        int bflags;
        int b_fill;
 
@@ -312,6 +327,7 @@ struct _tdm_test_server {
        struct list_head output_list;
        struct list_head pp_list;
        struct list_head capture_list;
+       struct list_head voutput_list;
        tdm_display *display;
 };
 
@@ -320,6 +336,7 @@ static void run_test(tdm_test_server *data);
 static void output_setup(tdm_test_server_output *o);
 static void layer_show_buffer(tdm_test_server_layer *l, tbm_surface_h b);
 static void capture_attach(tdm_test_server_capture *c, tbm_surface_h b);
+static void _vlayer_show_buffer(tdm_test_server_voutput *voutput);
 
 static char*
 parse_size(tdm_size *size, char *arg)
@@ -596,6 +613,8 @@ parse_args(tdm_test_server *data, int argc, char *argv[])
                        parse_arg_b(data, argv[++i]);
                } else if (!strncmp(argv[i] + 1, "v", 1)) {
                        data->do_vblank = 1;
+               } else if (!strncmp(argv[i] + 1, "V", 1)) {
+                       data->do_voutput = 1;
                } else {
                        usage(argv[0]);
                        destroy(data);
@@ -790,6 +809,238 @@ get_tts_buffer(tbm_surface_h b)
 }
 
 static void
+_vlayer_cb_commit(tdm_layer *layer, unsigned int sequence,
+                               unsigned int tv_sec, unsigned int tv_usec, void *user_data)
+{
+       tdm_test_server_voutput *voutput = (tdm_test_server_voutput *)user_data;
+       TDM_EXIT_IF_FAIL(voutput != NULL);
+       tdm_output_conn_status status;
+       tdm_error ret;
+
+       printf("voutput cb commit:\t %d: l(%p) b(%p)\n", voutput->buf_idx, voutput->layer, voutput->bufs[voutput->buf_idx]);
+
+       ret = tdm_output_get_conn_status(voutput->output, &status);
+       TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
+
+       if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) return;
+
+       voutput->buf_idx++;
+       _vlayer_show_buffer(voutput);
+}
+
+static void
+_vlayer_show_buffer(tdm_test_server_voutput *voutput)
+{
+       tdm_error ret;
+       int index;
+       if (voutput->buf_idx == 3)
+               voutput->buf_idx = 0;
+
+       index = voutput->buf_idx;
+
+       ret = tdm_layer_set_buffer(voutput->layer, voutput->bufs[index]);
+       TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
+
+       ret = tdm_layer_commit(voutput->layer, _vlayer_cb_commit, voutput);
+       TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
+
+       printf("voutput show:\t %d: l(%p) b(%p)\n", index, voutput->layer, voutput->bufs[index]);
+}
+
+static void
+_voutput_buff_init(tdm_test_server_voutput *voutput)
+{
+       tdm_output *output = voutput->output;
+       const tdm_output_mode *mode;
+       tdm_error ret = TDM_ERROR_NONE;
+       int i;
+
+       ret = tdm_output_get_mode(output, &mode);
+       TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
+
+       for (i = 0; i < 3; i++) {
+               tbm_surface_h b = tbm_surface_internal_create_with_flags(mode->hdisplay, mode->vdisplay, DEFAULT_FORMAT, 0);
+               TDM_EXIT_IF_FAIL(b != NULL);
+               tdm_test_buffer_fill(b, i);
+               voutput->bufs[i] = b;
+       }
+}
+
+static void
+_voutput_layer_init(tdm_test_server_voutput *voutput)
+{
+       tdm_output *output = voutput->output;
+       const tdm_output_mode *mode;
+       tdm_info_layer layer_info;
+       tbm_surface_info_s info;
+       tdm_error ret = TDM_ERROR_NONE;
+
+       ret = tdm_output_get_mode(output, &mode);
+       TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
+
+       TDM_ERR("modeinfo : %dx%d %d", mode->hdisplay, mode->vdisplay, mode->vrefresh);
+
+       voutput->layer = tdm_output_get_layer(output, 0, &ret);
+       TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
+
+       _voutput_buff_init(voutput);
+
+       tbm_surface_get_info(voutput->bufs[0], &info);
+       memset(&layer_info, 0x0, sizeof(tdm_info_layer));
+       if (IS_RGB(info.format)) {
+               layer_info.src_config.size.h = info.planes[0].stride >> 2;
+               layer_info.src_config.size.v  = info.height;
+       } else {
+               layer_info.src_config.size.h = info.planes[0].stride;
+               layer_info.src_config.size.v  = info.height;
+       }
+       layer_info.src_config.format = info.format;
+
+       layer_info.src_config.size.h = mode->hdisplay;
+       layer_info.src_config.size.v = mode->vdisplay;
+       layer_info.src_config.pos.x = 0;
+       layer_info.src_config.pos.y = 0;
+       layer_info.src_config.pos.w = mode->hdisplay;
+       layer_info.src_config.pos.h = mode->vdisplay;
+       layer_info.dst_pos.x = 0;
+       layer_info.dst_pos.y = 0;
+       layer_info.dst_pos.w = mode->hdisplay;
+       layer_info.dst_pos.h = mode->vdisplay;
+       layer_info.transform = TDM_TRANSFORM_NORMAL;
+
+       ret = tdm_layer_set_info(voutput->layer, &layer_info);
+       TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
+}
+
+static void
+_voutput_connect(tdm_test_server_voutput *voutput)
+{
+       tdm_output *output;
+       const tdm_output_mode *modes, *found = NULL, *best = NULL, *prefer = NULL;
+       int i, count;
+       tdm_error ret;
+
+       output = voutput->output;
+
+       ret = tdm_output_get_available_modes(output, &modes, &count);
+       TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
+
+       for (i = 0; i < count; i++) {
+               if (!best)
+                       best = &modes[i];
+               if (modes[i].type & TDM_OUTPUT_MODE_TYPE_PREFERRED)
+                       prefer = &modes[i];
+       }
+       if (prefer) {
+               found = prefer;
+               printf("found prefer mode: %dx%d %d\n", found->hdisplay, found->vdisplay, found->vrefresh);
+       }
+       if (!found && best) {
+               found = best;
+               printf("found best mode: %dx%d %d\n", found->hdisplay, found->vdisplay, found->vrefresh);
+       }
+       if (!found) {
+               printf("couldn't find any mode\n");
+               exit(0);
+       }
+
+       ret = tdm_output_set_mode(output, found);
+       TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
+
+       printf("output: %s %d\n", found->name, found->vrefresh);
+
+       ret = tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_ON);
+       TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
+}
+
+static void
+_voutput_disconnect(tdm_test_server_voutput *voutput)
+{
+       tdm_output *output;
+       tdm_error ret;
+
+       output = voutput->output;
+
+       ret = tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_OFF);
+       TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
+}
+
+static void
+_tdm_test_server_cb_output_change(tdm_output *output, tdm_output_change_type type, tdm_value value, void *user_data)
+{
+       tdm_test_server_voutput *voutput = NULL;
+       tdm_output_conn_status status;
+
+       voutput = (tdm_test_server_voutput *)user_data;
+       TDM_EXIT_IF_FAIL(voutput != NULL);
+
+       switch (type) {
+       case TDM_OUTPUT_CHANGE_CONNECTION:
+               status = (tdm_output_conn_status)value.u32;
+               if (status == TDM_OUTPUT_CONN_STATUS_CONNECTED) {
+                       _voutput_connect(voutput);
+                       _voutput_layer_init(voutput);
+                       _vlayer_show_buffer(voutput);
+               } else if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) {
+                       _voutput_disconnect(voutput);
+               }
+               break;
+       default:
+               break;
+       }
+}
+
+static void
+_tdm_output_cb_destroy_handler(tdm_output *output, void *user_data)
+{
+       tdm_test_server_voutput *voutput = NULL;
+       int i;
+
+       voutput = (tdm_test_server_voutput *)user_data;
+       TDM_EXIT_IF_FAIL(voutput != NULL);
+
+       tdm_output_remove_change_handler(output, _tdm_test_server_cb_output_change, voutput);
+       tdm_output_remove_destroy_handler(output, _tdm_output_cb_destroy_handler, voutput);
+
+       LIST_DEL(&voutput->link);
+
+       for (i = 0; i < 3; i++) {
+               tbm_surface_destroy(voutput->bufs[i]);
+       }
+
+       free(voutput);
+}
+
+static void
+_tdm_output_cb_create_handler(tdm_display *dpy, tdm_output *output, void *user_data)
+{
+       tdm_test_server *data;
+       tdm_test_server_voutput *voutput = NULL;
+       tdm_error ret = TDM_ERROR_NONE;
+
+       printf("voutput create call\n");
+
+       data = (tdm_test_server *)user_data;
+       TDM_EXIT_IF_FAIL(data != NULL);
+
+       voutput = calloc(1, sizeof *voutput);
+       TDM_EXIT_IF_FAIL(voutput != NULL);
+
+       ret = tdm_output_add_change_handler(output, _tdm_test_server_cb_output_change, voutput);
+       TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
+
+       ret = tdm_output_add_destroy_handler(output, _tdm_output_cb_destroy_handler, voutput);
+       TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
+
+       voutput->output = output;
+       voutput->data = data;
+
+       printf("voutput create done\n");
+
+       LIST_ADDTAIL(&voutput->link, &data->voutput_list);
+}
+
+static void
 destroy(tdm_test_server *data)
 {
        tdm_test_server_output *o = NULL, *oo = NULL;
@@ -797,6 +1048,7 @@ destroy(tdm_test_server *data)
        tdm_test_server_pp *p = NULL, *pp = NULL;
        tdm_test_server_capture *c = NULL, *cc = NULL;
        tdm_test_server_prop *w = NULL, *ww = NULL;
+       tdm_test_server_voutput *v = NULL, *vv = NULL;
        tdm_error ret;
        int i;
 
@@ -850,6 +1102,17 @@ destroy(tdm_test_server *data)
                free(o);
        }
 
+       LIST_FOR_EACH_ENTRY_SAFE(v, vv, &data->voutput_list, link) {
+               for (int i = 0; i < 3; i++) {
+                       tbm_surface_destroy(v->bufs[i]);
+               }
+               LIST_DEL(&v->link);
+               free(v);
+       }
+
+       if (data->do_voutput)
+               tdm_display_remove_output_create_handler(data->display, _tdm_output_cb_create_handler, data);
+
        if (data->display)
                tdm_display_deinit(data->display);
 
@@ -888,6 +1151,7 @@ main(int argc, char *argv[])
        LIST_INITHEAD(&data->output_list);
        LIST_INITHEAD(&data->pp_list);
        LIST_INITHEAD(&data->capture_list);
+       LIST_INITHEAD(&data->voutput_list);
 
        /* init value */
        data->bflags = TBM_BO_SCANOUT;
@@ -905,6 +1169,12 @@ main(int argc, char *argv[])
                goto done;
        }
 
+       if (data->do_voutput) {
+               printf("support virtual output - server\n");
+               ret = tdm_display_add_output_create_handler(data->display, _tdm_output_cb_create_handler, data);
+               TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
+       }
+
        run_test(data);
 
 done: