cac60a80a36f23a6ca08ebc3528d32c81373aa7a
[platform/core/uifw/libtdm.git] / tools / tdm_test_client.c
1 /**************************************************************************
2  *
3  * libtdm
4  *
5  * Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
6  *
7  * Contact: Eunchul Kim <chulspro.kim@samsung.com>,
8  *          JinYoung Jeon <jy0.jeon@samsung.com>,
9  *          Taeheon Kim <th908.kim@samsung.com>,
10  *          YoungJun Cho <yj44.cho@samsung.com>,
11  *          SooChan Lim <sc1.lim@samsung.com>,
12  *          Boram Park <boram1288.park@samsung.com>
13  *
14  * Permission is hereby granted, free of charge, to any person obtaining a
15  * copy of this software and associated documentation files (the
16  * "Software"), to deal in the Software without restriction, including
17  * without limitation the rights to use, copy, modify, merge, publish,
18  * distribute, sub license, and/or sell copies of the Software, and to
19  * permit persons to whom the Software is furnished to do so, subject to
20  * the following conditions:
21  *
22  * The above copyright notice and this permission notice (including the
23  * next paragraph) shall be included in all copies or substantial portions
24  * of the Software.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
27  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
29  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
30  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
31  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
32  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33  *
34 **************************************************************************/
35
36 #include <stdio.h>
37 #include <string.h>
38 #include <stdlib.h>
39 #include <poll.h>
40 #include <errno.h>
41 #include <time.h>
42 #include <stdint.h>
43 #include <png.h>
44
45 #include "tdm_client.h"
46 #include "tdm_macro.h"
47 #include "buffers.h"
48
49 typedef struct _tdm_test_client_arg {
50         char *output_name;
51         int fps;
52         int sync;
53         int interval;
54         int offset;
55         int enable_fake;
56         int pid;
57         char *vblank_name;
58 } tdm_test_client_arg;
59
60 typedef struct _tdm_test_client {
61         tdm_test_client_arg args;
62
63         int do_query;
64         int do_vblank;
65         int do_voutput;
66         int waiting;
67
68         tdm_client *client;
69         tdm_client_voutput *voutput;
70         tdm_client_output *output;
71 } tdm_test_client;
72
73 struct typestrings {
74         int type;
75         const char *string;
76 };
77
78 struct optstrings {
79         int  type;
80         const char *opt;
81         const char *desc;
82         const char *arg;
83         const char *ex;
84 };
85
86 enum {
87         OPT_QRY,
88         OPT_TST,
89         OPT_GNR,
90 };
91
92 static struct typestrings typestrs[] = {
93         {OPT_QRY, "Query"},
94         {OPT_TST, "Test"},
95         {OPT_GNR, "General"},
96 };
97
98 static struct optstrings optstrs[] = {
99         {OPT_QRY, "qo", "output objects info", "<output_name>", "primary"},
100         {OPT_TST, "v", "vblank test", "<output_name>[,<sync>][@<fps>][~<interval>][+<offset>][*fake][^vblank_name]", "primary,0@60~1+0*1^test"},
101         {OPT_TST, "V", "virtual output test", NULL, NULL},
102 };
103
104 static void
105 usage(char *app_name)
106 {
107         int type_size = sizeof(typestrs) / sizeof(struct typestrings);
108         int opt_size = sizeof(optstrs) / sizeof(struct optstrings);
109         int t;
110
111         printf("usage: %s \n\n", app_name);
112
113         for (t = 0; t < type_size; t++) {
114                 int o, f = 1;
115
116                 for (o = 0; o < opt_size; o++)
117                         if (optstrs[o].type == typestrs[t].type) {
118                                 if (f == 1)
119                                         printf(" %s options:\n\n", typestrs[t].string);
120                                 printf("\t-%s\t%s\n", optstrs[o].opt, optstrs[o].desc);
121                                 if (optstrs[o].arg)
122                                         printf("\t\t  %s\n", optstrs[o].arg);
123                                 if (optstrs[o].ex)
124                                         printf("\t\t  ex) %s\n", optstrs[o].ex);
125                                 f = 0;
126                         }
127                 printf("\n");
128         }
129
130         exit(0);
131 }
132
133 //"<output_name>"
134 static void
135 parse_arg_qo(tdm_test_client *data, char *arg)
136 {
137         char name[TDM_NAME_LEN];
138         strtostr(name, TDM_NAME_LEN, arg, TDM_DELIM);
139         data->args.output_name = strndup(name, TDM_NAME_LEN);
140 }
141
142 //"<output_name>[,<sync>][@<fps>][~<interval>][+<offset>][*fake]"
143 static void
144 parse_arg_v(tdm_test_client *data, char *arg)
145 {
146         char *end = arg;
147         char name[TDM_NAME_LEN];
148
149         end = strtostr(name, TDM_NAME_LEN, arg, TDM_DELIM);
150         data->args.output_name = strndup(name, TDM_NAME_LEN);
151
152         if (*end == ',') {
153                 arg = end + 1;
154                 data->args.sync = strtol(arg, &end, 10);
155         }
156
157         if (*end == '@') {
158                 arg = end + 1;
159                 data->args.fps = strtol(arg, &end, 10);
160         }
161
162         if (*end == '~') {
163                 arg = end + 1;
164                 data->args.interval = strtol(arg, &end, 10);
165         }
166
167         if (*end == '+' || *end == '-') {
168                 arg = end;
169                 data->args.offset = strtol(arg, &end, 10);
170         }
171
172         if (*end == '*') {
173                 arg = end + 1;
174                 data->args.enable_fake = strtol(arg, &end, 10);
175         }
176
177         if (*end == '^') {
178                 char name[TDM_NAME_LEN];
179                 arg = end + 1;
180                 end = strtostr(name, TDM_NAME_LEN, arg, TDM_DELIM);
181                 data->args.vblank_name = strndup(name, TDM_NAME_LEN);
182         }
183 }
184
185 static void
186 parse_args(tdm_test_client *data, int argc, char *argv[])
187 {
188         int i;
189
190         if (argc < 2) {
191                 usage(argv[0]);
192                 exit(0);
193         }
194
195         memset(data, 0, sizeof *data);
196         data->args.interval = 1;
197
198         for (i = 1; i < argc; i++) {
199                 if (!strncmp(argv[i] + 1, "qo", 2)) {
200                         data->do_query = 1;
201                         parse_arg_qo(data, argv[++i]);
202                 } else if (!strncmp(argv[i] + 1, "v", 1)) {
203                         data->do_vblank = 1;
204                         parse_arg_v(data, argv[++i]);
205                 } else if (!strncmp(argv[i] + 1, "V", 1)) {
206                         data->do_voutput = 1;
207                 } else {
208                         usage(argv[0]);
209                         exit(0);
210                 }
211         }
212 }
213
214 static double
215 get_time(void)
216 {
217         struct timespec tp;
218
219         if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
220                 return (double)tp.tv_sec + ((double)tp.tv_nsec) / 1000000000.0;
221
222         return 0;
223 }
224
225 static void
226 _client_vblank_handler(tdm_client_vblank *vblank, tdm_error error, unsigned int sequence,
227                                            unsigned int tv_sec, unsigned int tv_usec, void *user_data)
228 {
229         tdm_test_client *data = user_data;
230         double cur, vbl;
231         static double p_vbl = 0;
232
233         data->waiting = 0;
234
235         if (error == TDM_ERROR_DPMS_OFF) {
236                 printf("exit: dpms off\n");
237                 exit(0);
238         }
239
240         if (error != TDM_ERROR_NONE) {
241                 printf("exit: error(%d)\n", error);
242                 exit(0);
243         }
244
245         cur = get_time();
246         vbl = (double)tv_sec + ((double)tv_usec) / 1000000.0;
247
248         printf("vblank              : %.6f us vbl(%.6f)\n", vbl - p_vbl, vbl);
249
250         if (cur - vbl > 0.002) /* 2ms */
251                 printf("kernel -> tdm-client: %.0f us\n", (cur - vbl) * 1000000.0);
252
253         p_vbl = vbl;
254 }
255
256 static char *conn_str[3] = {"disconnected", "connected", "mode_setted"};
257 static char *dpms_str[4] = {"on", "standy", "suspend", "off"};
258
259 static void
260 _client_output_handler(tdm_client_output *output, tdm_output_change_type type,
261                                            tdm_value value, void *user_data)
262 {
263         if (type == TDM_OUTPUT_CHANGE_CONNECTION)
264                 printf("output %s.\n", conn_str[value.u32]);
265         else if (type == TDM_OUTPUT_CHANGE_DPMS)
266                 printf("dpms %s.\n", dpms_str[value.u32]);
267 }
268
269 static void
270 do_query(tdm_test_client *data)
271 {
272         tdm_client_output *output;
273         tdm_output_conn_status status;
274         tdm_output_dpms dpms;
275         unsigned int refresh;
276         tdm_error error;
277
278         output = tdm_client_get_output(data->client, NULL, &error);
279         if (error != TDM_ERROR_NONE) {
280                 printf("tdm_client_get_output failed\n");
281                 return;
282         }
283
284         error = tdm_client_output_get_conn_status(output, &status);
285         TDM_WARNING_IF_FAIL(error == TDM_ERROR_NONE);
286         error = tdm_client_output_get_dpms(output, &dpms);
287         TDM_WARNING_IF_FAIL(error == TDM_ERROR_NONE);
288         error = tdm_client_output_get_refresh_rate(output, &refresh);
289         TDM_WARNING_IF_FAIL(error == TDM_ERROR_NONE);
290
291         printf("tdm_output \"%s\"\n", data->args.output_name);
292         printf("\tstatus : %s\n", conn_str[status]);
293         printf("\tdpms : %s\n", dpms_str[dpms]);
294         printf("\trefresh : %d\n", refresh);
295 }
296
297 static void
298 do_vblank(tdm_test_client *data)
299 {
300         tdm_client_output *output;
301         tdm_client_vblank *vblank = NULL;
302         tdm_error error;
303         int fd = -1;
304         struct pollfd fds;
305
306         output = tdm_client_get_output(data->client, data->args.output_name, &error);
307         if (error != TDM_ERROR_NONE) {
308                 printf("tdm_client_get_output failed\n");
309                 return;
310         }
311
312         error = tdm_client_output_add_change_handler(output, _client_output_handler, NULL);
313         TDM_WARNING_IF_FAIL(error == TDM_ERROR_NONE);
314
315         vblank = tdm_client_output_create_vblank(output, &error);
316         if (error != TDM_ERROR_NONE) {
317                 printf("tdm_client_output_create_vblank failed\n");
318                 return;
319         }
320
321         error = tdm_client_vblank_set_name(vblank, data->args.vblank_name);
322         TDM_WARNING_IF_FAIL(error == TDM_ERROR_NONE);
323         error = tdm_client_vblank_set_enable_fake(vblank, data->args.enable_fake);
324         TDM_WARNING_IF_FAIL(error == TDM_ERROR_NONE);
325         error = tdm_client_vblank_set_sync(vblank, data->args.sync);
326         TDM_WARNING_IF_FAIL(error == TDM_ERROR_NONE);
327         if (data->args.fps > 0) {
328                 error = tdm_client_vblank_set_fps(vblank, data->args.fps);
329                 TDM_WARNING_IF_FAIL(error == TDM_ERROR_NONE);
330         }
331         error = tdm_client_vblank_set_offset(vblank, data->args.offset);
332         TDM_WARNING_IF_FAIL(error == TDM_ERROR_NONE);
333
334         error = tdm_client_get_fd(data->client, &fd);
335         if (error != TDM_ERROR_NONE || fd < 0) {
336                 printf("tdm_client_get_fd failed\n");
337                 goto done;
338         }
339
340         fds.events = POLLIN;
341         fds.fd = fd;
342         fds.revents = 0;
343
344         while (1) {
345                 int ret;
346
347                 if (!data->waiting) {
348                         error = tdm_client_vblank_wait(vblank, data->args.interval,
349                                                                                    _client_vblank_handler, data);
350                         if (error == TDM_ERROR_DPMS_OFF) {
351                                 printf("tdm_client_vblank_wait failed (dpms off)\n");
352                                 goto done;
353                         }
354                         if (error != TDM_ERROR_NONE) {
355                                 printf("tdm_client_vblank_wait failed (error: %d)\n", error);
356                                 goto done;
357                         }
358                         data->waiting = 1;
359                 }
360
361                 if (!data->args.sync) {
362                         ret = poll(&fds, 1, -1);
363                         if (ret < 0) {
364                                 if (errno == EINTR || errno == EAGAIN)  /* normal case */
365                                         continue;
366                                 else {
367                                         printf("poll failed: %m\n");
368                                         goto done;
369                                 }
370                         }
371
372                         error = tdm_client_handle_events(data->client);
373                         if (error != TDM_ERROR_NONE) {
374                                 printf("tdm_client_handle_events failed\n");
375                                 goto done;
376                         }
377                 }
378         }
379
380 done:
381         if (vblank)
382                 tdm_client_vblank_destroy(vblank);
383 }
384
385 #define PNG_DEPTH 8
386
387 void
388 _tdm_client_get_buffer_full_size(tbm_surface_h buffer, int *buffer_w, int *buffer_h)
389 {
390         tbm_surface_info_s info;
391         int ret;
392
393         TDM_RETURN_IF_FAIL(buffer != NULL);
394
395         ret = tbm_surface_get_info(buffer, &info);
396         TDM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
397
398         if (buffer_w) {
399                 if (IS_RGB(info.format))
400                         *buffer_w = info.planes[0].stride >> 2;
401                 else
402                         *buffer_w = info.planes[0].stride;
403         }
404
405         if (buffer_h)
406                 *buffer_h = info.planes[0].size / info.planes[0].stride;
407 }
408
409 static void
410 _tdm_client_dump_png(const char *file, const void *data, int width,
411                                          int height)
412 {
413         FILE *fp;
414
415         fp = fopen(file, "wb");
416         TDM_RETURN_IF_FAIL(fp != NULL);
417
418         png_structp pPngStruct =
419                 png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
420         if (!pPngStruct) {
421                 fclose(fp);
422                 return;
423         }
424
425         png_infop pPngInfo = png_create_info_struct(pPngStruct);
426         if (!pPngInfo) {
427                 png_destroy_write_struct(&pPngStruct, NULL);
428                 fclose(fp);
429                 return;
430         }
431
432         png_init_io(pPngStruct, fp);
433         png_set_IHDR(pPngStruct,
434                                  pPngInfo,
435                                  width,
436                                  height,
437                                  PNG_DEPTH,
438                                  PNG_COLOR_TYPE_RGBA,
439                                  PNG_INTERLACE_NONE,
440                                  PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
441
442         png_set_bgr(pPngStruct);
443         png_write_info(pPngStruct, pPngInfo);
444
445         const int pixel_size = 4;       // RGBA
446         png_bytep *row_pointers =
447                 png_malloc(pPngStruct, height * sizeof(png_byte *));
448         if (!row_pointers) {
449                 png_destroy_write_struct(&pPngStruct, &pPngInfo);
450                 fclose(fp);
451                 return;
452         }
453
454         unsigned int *blocks = (unsigned int *)data;
455         int y = 0;
456         int x = 0;
457
458         for (; y < height; ++y) {
459                 png_bytep row =
460                         png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
461                 if (!row) {
462                         for (x = 0; x < y; x++)
463                                 png_free(pPngStruct, row_pointers[x]);
464                         png_free(pPngStruct, row_pointers);
465                         png_destroy_write_struct(&pPngStruct, &pPngInfo);
466                         fclose(fp);
467                         return;
468                 }
469
470                 row_pointers[y] = (png_bytep)row;
471                 for (x = 0; x < width; ++x) {
472                         unsigned int curBlock = blocks[y * width + x];
473                         row[x * pixel_size] = (curBlock & 0xFF);
474                         row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
475                         row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
476                         row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
477                 }
478         }
479
480         png_write_image(pPngStruct, row_pointers);
481         png_write_end(pPngStruct, pPngInfo);
482
483         for (y = 0; y < height; y++)
484                 png_free(pPngStruct, row_pointers[y]);
485         png_free(pPngStruct, row_pointers);
486
487         png_destroy_write_struct(&pPngStruct, &pPngInfo);
488
489         fclose(fp);
490 }
491
492 void
493 _tdm_client_dump_buffer(tbm_surface_h buffer, const char *file)
494 {
495         char temp[TDM_PATH_LEN] = {0,};
496         tbm_surface_info_s info;
497         int len, ret;
498         const char *ext;
499         int bo_cnt;
500         int bw, bh;
501         char *dot, *p = temp;
502         const char *file_exts[2] = {"png", "raw"};
503
504         TDM_RETURN_IF_FAIL(buffer != NULL);
505         TDM_RETURN_IF_FAIL(file != NULL);
506
507         ret = tbm_surface_map(buffer, TBM_OPTION_READ, &info);
508         TDM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
509
510         if (IS_RGB(info.format))
511                 ext = file_exts[0];
512         else
513                 ext = file_exts[1];
514
515         dot = strrchr(file, '.');
516         if (!dot || strlen(dot + 1) != 3 || strncmp(dot + 1, ext, 3)) {
517                 len = strnlen(file, TDM_PATH_LEN - 5);
518                 strncat(p, file, len);
519                 p += len;
520                 *(p++) = '.';
521                 strncat(p, ext, 3);
522                 p += 3;
523                 *p = '\0';
524         } else {
525                 len = strnlen(file, TDM_PATH_LEN - 1);
526                 strncat(p, file, len);
527                 p += len;
528                 *p = '\0';
529         }
530
531         _tdm_client_get_buffer_full_size(buffer, &bw, &bh);
532
533         bo_cnt = tbm_surface_internal_get_num_bos(buffer);
534         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)",
535                         bo_cnt, bw, bh, info.width, info.height, FOURCC_STR(info.format),
536                         info.planes[0].ptr, info.planes[0].offset, info.planes[0].stride, info.planes[0].size,
537                         info.planes[1].ptr, info.planes[1].offset, info.planes[1].stride, info.planes[1].size,
538                         info.planes[2].ptr, info.planes[2].offset, info.planes[2].stride, info.planes[2].size);
539
540         _tdm_client_dump_png(temp, info.planes[0].ptr, bw, bh);
541
542         tbm_surface_unmap(buffer);
543
544         printf("dump %s", temp);
545 }
546
547 static void
548 _dump_buffer(tbm_surface_h buffer, int count)
549 {
550         char temp[TDM_PATH_LEN] = {0,};
551
552         snprintf(temp, TDM_PATH_LEN, "/tmp/%c%c%c%c_%dx%d_%d",
553                 FOURCC_STR(tbm_surface_get_format(buffer)),
554                 tbm_surface_get_width(buffer),
555                 tbm_surface_get_height(buffer),
556                 count);
557         _tdm_client_dump_buffer(buffer, temp);
558 }
559
560 static void
561 _voutput_commit(tdm_client_voutput *voutput, tbm_surface_h buffer, void *user_data)
562 {
563         tdm_test_client *data = (tdm_test_client *)user_data;
564         static int count = 0;
565
566         TDM_EXIT_IF_FAIL(data != NULL);
567         TDM_EXIT_IF_FAIL(buffer != NULL);
568
569         if (count < 10)
570                 _dump_buffer(buffer, count);
571         count++;
572
573         if (count == 70) {
574                 printf("client: %d commited(%p), disconnect\n", count, buffer);
575                 tdm_client_output_disconnect(data->output);
576         } else {
577                 printf("client: %d commited(%p)\n", count, buffer);
578         }
579
580         tdm_client_voutput_commit_done(voutput);
581 }
582
583 static void
584 _voutput_output_handler(tdm_client_output *output, tdm_output_change_type type,
585                                            tdm_value value, void *user_data)
586 {
587         tdm_client_voutput *voutput = NULL;
588         tdm_output_conn_status status;
589         tdm_test_client *data;
590
591         data = (tdm_test_client *) user_data;
592         TDM_RETURN_IF_FAIL(data != NULL);
593         voutput = data->voutput;
594         TDM_RETURN_IF_FAIL(voutput != NULL);
595
596         if (type == TDM_OUTPUT_CHANGE_CONNECTION) {
597                 status = (tdm_output_conn_status)value.u32;
598                 printf("output %s.\n", conn_str[value.u32]);
599
600                 if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) {
601                         printf("client: disconnected, destroy voutput\n");
602                         tdm_client_output_remove_change_handler(output, _voutput_output_handler, data);
603                         tdm_client_voutput_destroy(voutput);
604                 } else if (status == TDM_OUTPUT_CONN_STATUS_CONNECTED) {
605                         printf("client: connected\n");
606                 }
607         } else if (type == TDM_OUTPUT_CHANGE_DPMS) {
608                 printf("output %s.\n", dpms_str[value.u32]);
609         }
610 }
611
612  static void
613 _voutput_make_available_mode(tdm_client_output_mode *modes, int count)
614 {
615         int i;
616         for (i = 0; i < count; i++) {
617                 modes[i].clock = 25200;
618                 modes[i].hdisplay = 640;
619                 modes[i].hsync_start = 656;
620                 modes[i].hsync_end = 752;
621                 modes[i].htotal = 800;
622                 modes[i].hskew = 0;
623                 modes[i].vdisplay = 480;
624                 modes[i].vsync_start = 490;
625                 modes[i].vsync_end = 492;
626                 modes[i].vtotal = 525;
627                 modes[i].vscan = 0;
628                 modes[i].vrefresh = 30;
629                 modes[i].flags = 0;
630                 modes[i].type = 0;
631                 snprintf(modes[i].name, TDM_NAME_LEN, "%dx%d_%d", modes[i].hdisplay, modes[i].vdisplay, i);
632         }
633 }
634
635 static void
636 do_voutput(tdm_test_client *data)
637 {
638         tdm_client_voutput *voutput = NULL;
639         tdm_client_output *output = NULL;
640         tdm_client_output_mode modes[2];
641         tdm_error ret = TDM_ERROR_NONE;
642
643         printf("virtual output test - client\n");
644
645         voutput = tdm_client_create_voutput(data->client, "virtual-test", &ret);
646         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
647
648         ret = tdm_client_voutput_add_commit_handler(voutput, _voutput_commit, data);
649         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done);
650
651         output = tdm_client_voutput_get_client_output(voutput, &ret);
652         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done);
653
654         ret = tdm_client_output_add_change_handler(output, _voutput_output_handler, data);
655         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done);
656
657         ret = tdm_client_voutput_set_physical_size(voutput, 300, 200);
658         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done);
659
660         _voutput_make_available_mode(modes, 2);
661         ret = tdm_client_voutput_set_available_modes(voutput, modes, 2);
662         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done);
663
664         ret = tdm_client_output_connect(output);
665         TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done);
666
667         data->voutput = voutput;
668         data->output = output;
669
670         while (1) {
671                 tdm_client_handle_events_timeout(data->client, 1000);
672         }
673
674 done:
675         if (voutput)
676                 tdm_client_voutput_destroy(voutput);
677 }
678
679 static tdm_test_client ttc_data;
680
681 int
682 main(int argc, char *argv[])
683 {
684         tdm_test_client *data = &ttc_data;
685         tdm_error error;
686
687 #if 1 /* for testing */
688         const char *xdg = (const char*)getenv("XDG_RUNTIME_DIR");
689         if (!xdg) {
690                 char buf[32];
691                 snprintf(buf, sizeof(buf), "/run");
692                 int ret = setenv("XDG_RUNTIME_DIR", (const char*)buf, 1);
693                 if (ret != 0)
694                         exit(0);
695         }
696
697         /* for tbm_bufmgr_init */
698         const char *s  = (const char*)getenv("TBM_DISPLAY_SERVER");
699         if (!s) {
700                 char buf[32];
701                 snprintf(buf, sizeof(buf), "1");
702                 int ret = setenv("TBM_DISPLAY_SERVER", (const char*)buf, 1);
703                 if (ret != 0)
704                         exit(0);
705         }
706 #endif
707
708         parse_args(data, argc, argv);
709
710         printf("sync(%d) fps(%d) interval(%d) offset(%d) enable_fake(%d) pid(%d)\n",
711                    data->args.sync, data->args.fps, data->args.interval,
712                    data->args.offset, data->args.enable_fake, data->args.pid);
713
714         data->client = tdm_client_create(&error);
715         if (error != TDM_ERROR_NONE) {
716                 printf("tdm_client_create failed\n");
717                 goto done;
718         }
719
720         if (data->do_query)
721                 do_query(data);
722         if (data->do_vblank)
723                 do_vblank(data);
724         if (data->do_voutput)
725                 do_voutput(data);
726
727 done:
728         if (data->args.output_name)
729                 free(data->args.output_name);
730         if (data->args.vblank_name)
731                 free(data->args.vblank_name);
732         if (data->client)
733                 tdm_client_destroy(data->client);
734
735         return 0;
736 }