X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=tools%2Ftdm_test_client.c;h=14feed9c40fb08942ea487fff8d982aaf559cc36;hb=1cb788d07421cbebd057aa18d2c5533a7be80352;hp=817ca3e0b3605bcc58bc33edf9fa93af784eb396;hpb=1859505491bd4f1b58b8a865cddbbb73297276f5;p=platform%2Fcore%2Fuifw%2Flibtdm.git diff --git a/tools/tdm_test_client.c b/tools/tdm_test_client.c index 817ca3e..14feed9 100644 --- a/tools/tdm_test_client.c +++ b/tools/tdm_test_client.c @@ -1,82 +1,340 @@ -/* -Copyright (C) 2015 Samsung Electronics co., Ltd. All Rights Reserved. - -Contact: - Changyeon Lee , - JunKyeong Kim , - Boram Park , - SooChan Lim - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice (including the next -paragraph) shall be included in all copies or substantial portions of the -Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ +/************************************************************************** + * + * libtdm + * + * Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved. + * + * Contact: Eunchul Kim , + * JinYoung Jeon , + * Taeheon Kim , + * YoungJun Cho , + * SooChan Lim , + * Boram Park + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * +**************************************************************************/ #include +#include #include #include #include #include #include +#include -#include -#include +#include "tdm_client.h" +#include "tdm_macro.h" +#include "buffers.h" -static int -get_time_in_millis(void) +#define CHECK_V_STEP 0 + +typedef struct _tdm_test_client_arg { + char *output_name; + int fps; + int sync; + int interval; + int offset; + int enable_fake; + int pid; + char *vblank_name; +} tdm_test_client_arg; + +typedef struct _tdm_test_client { + tdm_test_client_arg args; + + int do_query; + int do_vblank; + int do_voutput; + int waiting; + + tdm_client *client; + tdm_client_voutput *voutput; + tdm_client_output *output; +} tdm_test_client; + +struct typestrings { + int type; + const char *string; +}; + +struct optstrings { + int type; + const char *opt; + const char *desc; + const char *arg; + const char *ex; +}; + +enum { + OPT_QRY, + OPT_TST, + OPT_GNR, +}; + +static struct typestrings typestrs[] = { + {OPT_QRY, "Query"}, + {OPT_TST, "Test"}, + {OPT_GNR, "General"}, +}; + +static struct optstrings optstrs[] = { + {OPT_QRY, "qo", "output objects info", "", "primary"}, + {OPT_TST, "v", "vblank test", "[,][@][~][+][*fake][^vblank_name]", "primary,0@60~1+0*1^test"}, + {OPT_TST, "V", "virtual output test", NULL, NULL}, +}; + +static void +usage(char *app_name) +{ + int type_size = sizeof(typestrs) / sizeof(struct typestrings); + int opt_size = sizeof(optstrs) / sizeof(struct optstrings); + int t; + + printf("usage: %s \n\n", app_name); + + for (t = 0; t < type_size; t++) { + int o, f = 1; + + for (o = 0; o < opt_size; o++) + if (optstrs[o].type == typestrs[t].type) { + if (f == 1) + printf(" %s options:\n\n", typestrs[t].string); + printf("\t-%s\t%s\n", optstrs[o].opt, optstrs[o].desc); + if (optstrs[o].arg) + printf("\t\t %s\n", optstrs[o].arg); + if (optstrs[o].ex) + printf("\t\t ex) %s\n", optstrs[o].ex); + f = 0; + } + printf("\n"); + } + + exit(0); +} + +//"" +static void +parse_arg_qo(tdm_test_client *data, char *arg) +{ + char name[TDM_NAME_LEN]; + strtostr(name, TDM_NAME_LEN, arg, TDM_DELIM); + data->args.output_name = strndup(name, TDM_NAME_LEN); +} + +//"[,][@][~][+][*fake]" +static void +parse_arg_v(tdm_test_client *data, char *arg) +{ + char *end = arg; + char name[TDM_NAME_LEN]; + + end = strtostr(name, TDM_NAME_LEN, arg, TDM_DELIM); + data->args.output_name = strndup(name, TDM_NAME_LEN); + + if (*end == ',') { + arg = end + 1; + data->args.sync = strtol(arg, &end, 10); + } + + if (*end == '@') { + arg = end + 1; + data->args.fps = strtol(arg, &end, 10); + } + + if (*end == '~') { + arg = end + 1; + data->args.interval = strtol(arg, &end, 10); + } + + if (*end == '+' || *end == '-') { + arg = end; + data->args.offset = strtol(arg, &end, 10); + } + + if (*end == '*') { + arg = end + 1; + data->args.enable_fake = strtol(arg, &end, 10); + } + + if (*end == '^') { + char name[TDM_NAME_LEN]; + arg = end + 1; + end = strtostr(name, TDM_NAME_LEN, arg, TDM_DELIM); + data->args.vblank_name = strndup(name, TDM_NAME_LEN); + } +} + +static void +parse_args(tdm_test_client *data, int argc, char *argv[]) +{ + int i; + + if (argc < 2) { + usage(argv[0]); + exit(0); + } + + memset(data, 0, sizeof *data); + data->args.interval = 1; + + for (i = 1; i < argc; i++) { + if (!strncmp(argv[i] + 1, "qo", 2)) { + data->do_query = 1; + parse_arg_qo(data, argv[++i]); + } else if (!strncmp(argv[i] + 1, "v", 1)) { + data->do_vblank = 1; + parse_arg_v(data, argv[++i]); + } else if (!strncmp(argv[i] + 1, "V", 1)) { + data->do_voutput = 1; + } else { + usage(argv[0]); + exit(0); + } + } +} + +static double +get_time(void) { struct timespec tp; if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) - return (int)(tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L); + return (double)tp.tv_sec + ((double)tp.tv_nsec) / 1000000000.0; return 0; } static void -_client_vblank_handler(unsigned int sequence, unsigned int tv_sec, - unsigned int tv_usec, void *user_data) +_client_vblank_handler(tdm_client_vblank *vblank, tdm_error error, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, void *user_data) { - int temp1, temp2; + tdm_test_client *data = user_data; + double cur, vbl; + static double p_vbl = 0; + + data->waiting = 0; - temp1 = (intptr_t)user_data; - temp2 = get_time_in_millis(); + if (error == TDM_ERROR_DPMS_OFF) { + printf("exit: dpms off\n"); + exit(0); + } + + if (error != TDM_ERROR_NONE) { + printf("exit: error(%d)\n", error); + exit(0); + } - printf("%d ms\n", temp2 - temp1); + cur = get_time(); + vbl = (double)tv_sec + ((double)tv_usec) / 1000000.0; + + printf("vblank : %.6f us vbl(%.6f)\n", vbl - p_vbl, vbl); + + if (cur - vbl > 0.002) /* 2ms */ + printf("kernel -> tdm-client: %.0f us\n", (cur - vbl) * 1000000.0); + + p_vbl = vbl; } +static char *conn_str[3] = {"disconnected", "connected", "mode_setted"}; +static char *dpms_str[4] = {"on", "standy", "suspend", "off"}; -int -main(int argc, char *argv[]) +static void +_client_output_handler(tdm_client_output *output, tdm_output_change_type type, + tdm_value value, void *user_data) { - tdm_client *client; - tdm_client_error error; + if (type == TDM_OUTPUT_CHANGE_CONNECTION) + printf("output %s.\n", conn_str[value.u32]); + else if (type == TDM_OUTPUT_CHANGE_DPMS) + printf("dpms %s.\n", dpms_str[value.u32]); +} + +static void +do_query(tdm_test_client *data) +{ + tdm_client_output *output; + tdm_output_conn_status status; + tdm_output_dpms dpms; + unsigned int refresh; + tdm_error error; + + output = tdm_client_get_output(data->client, NULL, &error); + if (error != TDM_ERROR_NONE) { + printf("tdm_client_get_output failed\n"); + return; + } + + error = tdm_client_output_get_conn_status(output, &status); + TDM_WARNING_IF_FAIL(error == TDM_ERROR_NONE); + error = tdm_client_output_get_dpms(output, &dpms); + TDM_WARNING_IF_FAIL(error == TDM_ERROR_NONE); + error = tdm_client_output_get_refresh_rate(output, &refresh); + TDM_WARNING_IF_FAIL(error == TDM_ERROR_NONE); + + printf("tdm_output \"%s\"\n", data->args.output_name); + printf("\tstatus : %s\n", conn_str[status]); + printf("\tdpms : %s\n", dpms_str[dpms]); + printf("\trefresh : %d\n", refresh); +} + +static void +do_vblank(tdm_test_client *data) +{ + tdm_client_output *output; + tdm_client_vblank *vblank = NULL; + tdm_error error; int fd = -1; struct pollfd fds; - client = tdm_client_create(&error); - if (error != TDM_CLIENT_ERROR_NONE) { - printf("tdm_client_create failed\n"); - exit(1); + output = tdm_client_get_output(data->client, data->args.output_name, &error); + if (error != TDM_ERROR_NONE) { + printf("tdm_client_get_output failed\n"); + return; + } + + error = tdm_client_output_add_change_handler(output, _client_output_handler, NULL); + TDM_WARNING_IF_FAIL(error == TDM_ERROR_NONE); + + vblank = tdm_client_output_create_vblank(output, &error); + if (error != TDM_ERROR_NONE) { + printf("tdm_client_output_create_vblank failed\n"); + return; + } + + error = tdm_client_vblank_set_name(vblank, data->args.vblank_name); + TDM_WARNING_IF_FAIL(error == TDM_ERROR_NONE); + error = tdm_client_vblank_set_enable_fake(vblank, data->args.enable_fake); + TDM_WARNING_IF_FAIL(error == TDM_ERROR_NONE); + error = tdm_client_vblank_set_sync(vblank, data->args.sync); + TDM_WARNING_IF_FAIL(error == TDM_ERROR_NONE); + if (data->args.fps > 0) { + error = tdm_client_vblank_set_fps(vblank, data->args.fps); + TDM_WARNING_IF_FAIL(error == TDM_ERROR_NONE); } + error = tdm_client_vblank_set_offset(vblank, data->args.offset); + TDM_WARNING_IF_FAIL(error == TDM_ERROR_NONE); - error = tdm_client_get_fd(client, &fd); - if (error != TDM_CLIENT_ERROR_NONE || fd < 0) { + error = tdm_client_get_fd(data->client, &fd); + if (error != TDM_ERROR_NONE || fd < 0) { printf("tdm_client_get_fd failed\n"); goto done; } @@ -88,30 +346,410 @@ main(int argc, char *argv[]) while (1) { int ret; - error = tdm_client_wait_vblank(client, "unknown-0", 1, 0, - _client_vblank_handler, - (void*)(intptr_t)get_time_in_millis()); - if (error != TDM_CLIENT_ERROR_NONE) { - printf("tdm_client_wait_vblank failed\n"); - goto done; + if (!data->waiting) { + error = tdm_client_vblank_wait(vblank, data->args.interval, + _client_vblank_handler, data); + if (error == TDM_ERROR_DPMS_OFF) { + printf("tdm_client_vblank_wait failed (dpms off)\n"); + goto done; + } + if (error != TDM_ERROR_NONE) { + printf("tdm_client_vblank_wait failed (error: %d)\n", error); + goto done; + } + data->waiting = 1; } - ret = poll(&fds, 1, -1); - if (ret < 0) { - if (errno == EBUSY) /* normal case */ - continue; - else { - printf("poll failed: %m\n"); + if (!data->args.sync) { + ret = poll(&fds, 1, -1); + if (ret < 0) { + if (errno == EINTR || errno == EAGAIN) /* normal case */ + continue; + else { + printf("poll failed: %m\n"); + goto done; + } + } + + error = tdm_client_handle_events(data->client); + if (error != TDM_ERROR_NONE) { + printf("tdm_client_handle_events failed\n"); goto done; } } + } + +done: + if (vblank) + tdm_client_vblank_destroy(vblank); +} + +#define PNG_DEPTH 8 + +void +_tdm_client_get_buffer_full_size(tbm_surface_h buffer, int *buffer_w, int *buffer_h) +{ + tbm_surface_info_s info; + int ret; + + TDM_RETURN_IF_FAIL(buffer != NULL); + + ret = tbm_surface_get_info(buffer, &info); + TDM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE); + + if (buffer_w) { + if (IS_RGB(info.format)) + *buffer_w = info.planes[0].stride >> 2; + else + *buffer_w = info.planes[0].stride; + } + + if (buffer_h) + *buffer_h = info.planes[0].size / info.planes[0].stride; +} + +static void +_tdm_client_dump_png(const char *file, const void *data, int width, + int height) +{ + FILE *fp; + + fp = fopen(file, "wb"); + TDM_RETURN_IF_FAIL(fp != NULL); + + png_structp pPngStruct = + png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!pPngStruct) { + fclose(fp); + return; + } + + png_infop pPngInfo = png_create_info_struct(pPngStruct); + if (!pPngInfo) { + png_destroy_write_struct(&pPngStruct, NULL); + fclose(fp); + return; + } + + png_init_io(pPngStruct, fp); + png_set_IHDR(pPngStruct, + pPngInfo, + width, + height, + PNG_DEPTH, + PNG_COLOR_TYPE_RGBA, + PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + png_set_bgr(pPngStruct); + png_write_info(pPngStruct, pPngInfo); + + const int pixel_size = 4; // RGBA + png_bytep *row_pointers = + png_malloc(pPngStruct, height * sizeof(png_byte *)); + if (!row_pointers) { + png_destroy_write_struct(&pPngStruct, &pPngInfo); + fclose(fp); + return; + } + + unsigned int *blocks = (unsigned int *)data; + int y = 0; + int x = 0; + + for (; y < height; ++y) { + png_bytep row = + png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size); + if (!row) { + for (x = 0; x < y; x++) + png_free(pPngStruct, row_pointers[x]); + png_free(pPngStruct, row_pointers); + png_destroy_write_struct(&pPngStruct, &pPngInfo); + fclose(fp); + return; + } + + row_pointers[y] = (png_bytep)row; + for (x = 0; x < width; ++x) { + unsigned int curBlock = blocks[y * width + x]; + row[x * pixel_size] = (curBlock & 0xFF); + row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF; + row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF; + row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF; + } + } + + png_write_image(pPngStruct, row_pointers); + png_write_end(pPngStruct, pPngInfo); + + for (y = 0; y < height; y++) + png_free(pPngStruct, row_pointers[y]); + png_free(pPngStruct, row_pointers); + + png_destroy_write_struct(&pPngStruct, &pPngInfo); + + fclose(fp); +} + +void +_tdm_client_dump_buffer(tbm_surface_h buffer, const char *file) +{ + char temp[TDM_PATH_LEN] = {0,}; + tbm_surface_info_s info; + int len, ret; + const char *ext; + int bo_cnt; + int bw, bh; + char *dot, *p = temp; + const char *file_exts[2] = {"png", "raw"}; + + TDM_RETURN_IF_FAIL(buffer != NULL); + TDM_RETURN_IF_FAIL(file != NULL); + + ret = tbm_surface_map(buffer, TBM_OPTION_READ, &info); + TDM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE); + + if (IS_RGB(info.format)) + ext = file_exts[0]; + else + ext = file_exts[1]; + + dot = strrchr(file, '.'); + if (!dot || strlen(dot + 1) != 3 || strncmp(dot + 1, ext, 3)) { + len = strnlen(file, TDM_PATH_LEN - 5); + strncat(p, file, len); + p += len; + *(p++) = '.'; + strncat(p, ext, 4); + p += 3; + *p = '\0'; + } else { + len = strnlen(file, TDM_PATH_LEN - 1); + strncat(p, file, len); + p += len; + *p = '\0'; + } + + _tdm_client_get_buffer_full_size(buffer, &bw, &bh); + + bo_cnt = tbm_surface_internal_get_num_bos(buffer); + TDM_DBG("buffer: bo_cnt(%d) %dx%d(%dx%d) %c%c%c%c, plane: (%p+%d, %d,%d) (%p+%d, %d,%d) (%p+%d, %d,%d)", + bo_cnt, bw, bh, info.width, info.height, FOURCC_STR(info.format), + info.planes[0].ptr, info.planes[0].offset, info.planes[0].stride, info.planes[0].size, + info.planes[1].ptr, info.planes[1].offset, info.planes[1].stride, info.planes[1].size, + info.planes[2].ptr, info.planes[2].offset, info.planes[2].stride, info.planes[2].size); + + _tdm_client_dump_png(temp, info.planes[0].ptr, bw, bh); + + tbm_surface_unmap(buffer); + + printf("dump %s\n", temp); +} + +static void +_dump_buffer(tbm_surface_h buffer, int count) +{ + char temp[TDM_PATH_LEN] = {0,}; + + snprintf(temp, TDM_PATH_LEN, "/tmp/%c%c%c%c_%dx%d_%d", + FOURCC_STR(tbm_surface_get_format(buffer)), + tbm_surface_get_width(buffer), + tbm_surface_get_height(buffer), + count); + _tdm_client_dump_buffer(buffer, temp); +} + +static void +_voutput_commit(tdm_client_voutput *voutput, tbm_surface_h buffer, void *user_data) +{ + tdm_test_client *data = (tdm_test_client *)user_data; + static int count = 0; + + TDM_EXIT_IF_FAIL(data != NULL); + TDM_EXIT_IF_FAIL(buffer != NULL); + + if ((count < 10) || (count >= 31 && count <= 40)) + _dump_buffer(buffer, count); + count++; + + if (count == 30) { + printf("client: %d commited(%p), mode change request to index 1\n", count, buffer); + tdm_client_voutput_set_mode(data->voutput, 1); + } else if (count == 50) { + printf("client: %d commited(%p), disconnect\n", count, buffer); + tdm_client_voutput_disconnect(data->voutput); + } else { + printf("client: %d commited(%p)\n", count, buffer); + } + + tdm_client_voutput_commit_done(voutput); +} + +static void +_voutput_output_handler(tdm_client_output *output, tdm_output_change_type type, + tdm_value value, void *user_data) +{ + tdm_client_voutput *voutput = NULL; + tdm_output_conn_status status; + tdm_test_client *data; + unsigned int width, height; + + data = (tdm_test_client *) user_data; + TDM_RETURN_IF_FAIL(data != NULL); + voutput = data->voutput; + TDM_RETURN_IF_FAIL(voutput != NULL); + + if (type == TDM_OUTPUT_CHANGE_CONNECTION) { + status = (tdm_output_conn_status)value.u32; + printf("output %s.\n", conn_str[value.u32]); + + if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) { + printf("client: disconnected, destroy voutput\n"); + tdm_client_output_remove_change_handler(output, _voutput_output_handler, data); +#if CHECK_V_STEP + printf("press enter to continuet\n"); + getchar(); +#endif + tdm_client_voutput_destroy(voutput); + } else if (status == TDM_OUTPUT_CONN_STATUS_CONNECTED) { + printf("client: connected\n"); + } else if (status == TDM_OUTPUT_CONN_STATUS_MODE_SETTED) { + tdm_client_output_get_mode(output, &width, &height); + printf("client: mode setted(%dx%d)\n", width, height); +#if CHECK_V_STEP + printf("press enter to continuet\n"); + getchar(); +#endif + } + } else if (type == TDM_OUTPUT_CHANGE_DPMS) { + printf("output %s.\n", dpms_str[value.u32]); + } +} - error = tdm_client_handle_events(client); - if (error != TDM_CLIENT_ERROR_NONE) - printf("tdm_client_handle_events failed\n"); +static void +_voutput_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 * (count - i); + modes[i].hsync_start = 656; + modes[i].hsync_end = 752; + modes[i].htotal = 800; + modes[i].hskew = 0; + modes[i].vdisplay = 480 * (count - i); + 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); } +} + +static void +do_voutput(tdm_test_client *data) +{ + tdm_client_voutput *voutput = NULL; + tdm_client_output *output = NULL; + tdm_client_output_mode modes[2]; + tdm_error ret = TDM_ERROR_NONE; + + printf("virtual output test - client\n"); + + voutput = tdm_client_create_voutput(data->client, "virtual-test", &ret); + TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE); + + ret = tdm_client_voutput_add_commit_handler(voutput, _voutput_commit, data); + TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done); + + output = tdm_client_voutput_get_client_output(voutput, &ret); + TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done); + + ret = tdm_client_output_add_change_handler(output, _voutput_output_handler, data); + TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done); + + ret = tdm_client_voutput_set_physical_size(voutput, 300, 200); + TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done); + + _voutput_make_available_mode(modes, 2); + ret = tdm_client_voutput_set_available_modes(voutput, modes, 2); + TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done); +#if CHECK_V_STEP + printf("virtual output test - press enter to connect\n"); + getchar(); +#endif + ret = tdm_client_voutput_connect(voutput); + TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done); + + data->voutput = voutput; + data->output = output; + + while (1) { + tdm_client_handle_events_timeout(data->client, 1000); + } + +done: + if (voutput) + tdm_client_voutput_destroy(voutput); +} + +static tdm_test_client ttc_data; + +int +main(int argc, char *argv[]) +{ + tdm_test_client *data = &ttc_data; + tdm_error error; + + /* for testing */ + const char *xdg = (const char*)getenv("XDG_RUNTIME_DIR"); + if (!xdg) { + char buf[32]; + snprintf(buf, sizeof(buf), "/run"); + int ret = setenv("XDG_RUNTIME_DIR", (const char*)buf, 1); + if (ret != 0) + exit(0); + } + + /* for tbm_bufmgr_init */ + const char *s = (const char*)getenv("TBM_DISPLAY_SERVER"); + if (!s) { + char buf[32]; + snprintf(buf, sizeof(buf), "1"); + int ret = setenv("TBM_DISPLAY_SERVER", (const char*)buf, 1); + if (ret != 0) + exit(0); + } + + parse_args(data, argc, argv); + + printf("sync(%d) fps(%d) interval(%d) offset(%d) enable_fake(%d) pid(%d)\n", + data->args.sync, data->args.fps, data->args.interval, + data->args.offset, data->args.enable_fake, data->args.pid); + + data->client = tdm_client_create(&error); + if (error != TDM_ERROR_NONE) { + printf("tdm_client_create failed\n"); + goto done; + } + + if (data->do_query) + do_query(data); + if (data->do_vblank) + do_vblank(data); + if (data->do_voutput) + do_voutput(data); done: - tdm_client_destroy(client); + if (data->args.output_name) + free(data->args.output_name); + if (data->args.vblank_name) + free(data->args.vblank_name); + if (data->client) + tdm_client_destroy(data->client); + return 0; }