1 /**************************************************************************
5 * Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
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>
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:
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
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.
34 **************************************************************************/
44 #include "tdm_client.h"
45 #include "tdm_macro.h"
48 #define CHECK_V_STEP 0
50 typedef struct _tdm_test_client_arg {
59 } tdm_test_client_arg;
61 typedef struct _tdm_test_client {
62 tdm_test_client_arg args;
70 tdm_client_voutput *voutput;
71 tdm_client_output *output;
93 static struct typestrings typestrs[] = {
99 static struct optstrings optstrs[] = {
100 {OPT_QRY, "qo", "output objects info", "<output_name>", "primary"},
101 {OPT_TST, "v", "vblank test", "<output_name>[,<sync>][@<fps>][~<interval>][+<offset>][*fake][^vblank_name]", "primary,0@60~1+0*1^test"},
102 {OPT_TST, "V", "virtual output test", NULL, NULL},
106 usage(char *app_name)
108 int type_size = sizeof(typestrs) / sizeof(struct typestrings);
109 int opt_size = sizeof(optstrs) / sizeof(struct optstrings);
112 printf("usage: %s \n\n", app_name);
114 for (t = 0; t < type_size; t++) {
117 for (o = 0; o < opt_size; o++)
118 if (optstrs[o].type == typestrs[t].type) {
120 printf(" %s options:\n\n", typestrs[t].string);
121 printf("\t-%s\t%s\n", optstrs[o].opt, optstrs[o].desc);
123 printf("\t\t %s\n", optstrs[o].arg);
125 printf("\t\t ex) %s\n", optstrs[o].ex);
136 parse_arg_qo(tdm_test_client *data, char *arg)
138 char name[TDM_NAME_LEN];
139 strtostr(name, TDM_NAME_LEN, arg, TDM_DELIM);
140 data->args.output_name = strndup(name, TDM_NAME_LEN);
143 //"<output_name>[,<sync>][@<fps>][~<interval>][+<offset>][*fake]"
145 parse_arg_v(tdm_test_client *data, char *arg)
148 char name[TDM_NAME_LEN];
150 end = strtostr(name, TDM_NAME_LEN, arg, TDM_DELIM);
151 data->args.output_name = strndup(name, TDM_NAME_LEN);
155 data->args.sync = strtol(arg, &end, 10);
160 data->args.fps = strtol(arg, &end, 10);
165 data->args.interval = strtol(arg, &end, 10);
168 if (*end == '+' || *end == '-') {
170 data->args.offset = strtol(arg, &end, 10);
175 data->args.enable_fake = strtol(arg, &end, 10);
179 char name[TDM_NAME_LEN];
181 end = strtostr(name, TDM_NAME_LEN, arg, TDM_DELIM);
182 data->args.vblank_name = strndup(name, TDM_NAME_LEN);
187 parse_args(tdm_test_client *data, int argc, char *argv[])
196 memset(data, 0, sizeof *data);
197 data->args.interval = 1;
199 for (i = 1; i < argc; i++) {
200 if (!strncmp(argv[i] + 1, "qo", 2)) {
202 parse_arg_qo(data, argv[++i]);
203 } else if (!strncmp(argv[i] + 1, "v", 1)) {
205 parse_arg_v(data, argv[++i]);
206 } else if (!strncmp(argv[i] + 1, "V", 1)) {
207 data->do_voutput = 1;
220 if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
221 return (double)tp.tv_sec + ((double)tp.tv_nsec) / 1000000000.0;
227 _client_vblank_handler(tdm_client_vblank *vblank, tdm_error error, unsigned int sequence,
228 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
230 tdm_test_client *data = user_data;
232 static double p_vbl = 0;
236 if (error == TDM_ERROR_DPMS_OFF) {
237 printf("exit: dpms off\n");
241 if (error != TDM_ERROR_NONE) {
242 printf("exit: error(%d)\n", error);
247 vbl = (double)tv_sec + ((double)tv_usec) / 1000000.0;
249 printf("vblank : %.6f us vbl(%.6f)\n", vbl - p_vbl, vbl);
251 if (cur - vbl > 0.002) /* 2ms */
252 printf("kernel -> tdm-client: %.0f us\n", (cur - vbl) * 1000000.0);
257 static char *conn_str[3] = {"disconnected", "connected", "mode_setted"};
258 static char *dpms_str[4] = {"on", "standy", "suspend", "off"};
261 _client_output_handler(tdm_client_output *output, tdm_output_change_type type,
262 tdm_value value, void *user_data)
264 if (type == TDM_OUTPUT_CHANGE_CONNECTION)
265 printf("output %s.\n", conn_str[value.u32]);
266 else if (type == TDM_OUTPUT_CHANGE_DPMS)
267 printf("dpms %s.\n", dpms_str[value.u32]);
271 do_query(tdm_test_client *data)
273 tdm_client_output *output;
274 tdm_output_conn_status status;
275 tdm_output_dpms dpms;
276 unsigned int refresh;
279 output = tdm_client_get_output(data->client, NULL, &error);
280 if (error != TDM_ERROR_NONE) {
281 printf("tdm_client_get_output failed\n");
285 error = tdm_client_output_get_conn_status(output, &status);
286 TDM_WARNING_IF_FAIL(error == TDM_ERROR_NONE);
287 error = tdm_client_output_get_dpms(output, &dpms);
288 TDM_WARNING_IF_FAIL(error == TDM_ERROR_NONE);
289 error = tdm_client_output_get_refresh_rate(output, &refresh);
290 TDM_WARNING_IF_FAIL(error == TDM_ERROR_NONE);
292 printf("tdm_output \"%s\"\n", data->args.output_name);
293 printf("\tstatus : %s\n", conn_str[status]);
294 printf("\tdpms : %s\n", dpms_str[dpms]);
295 printf("\trefresh : %d\n", refresh);
299 do_vblank(tdm_test_client *data)
301 tdm_client_output *output;
302 tdm_client_vblank *vblank = NULL;
307 output = tdm_client_get_output(data->client, data->args.output_name, &error);
308 if (error != TDM_ERROR_NONE) {
309 printf("tdm_client_get_output failed\n");
313 error = tdm_client_output_add_change_handler(output, _client_output_handler, NULL);
314 TDM_WARNING_IF_FAIL(error == TDM_ERROR_NONE);
316 vblank = tdm_client_output_create_vblank(output, &error);
317 if (error != TDM_ERROR_NONE) {
318 printf("tdm_client_output_create_vblank failed\n");
322 error = tdm_client_vblank_set_name(vblank, data->args.vblank_name);
323 TDM_WARNING_IF_FAIL(error == TDM_ERROR_NONE);
324 error = tdm_client_vblank_set_enable_fake(vblank, data->args.enable_fake);
325 TDM_WARNING_IF_FAIL(error == TDM_ERROR_NONE);
326 error = tdm_client_vblank_set_sync(vblank, data->args.sync);
327 TDM_WARNING_IF_FAIL(error == TDM_ERROR_NONE);
328 if (data->args.fps > 0) {
329 error = tdm_client_vblank_set_fps(vblank, data->args.fps);
330 TDM_WARNING_IF_FAIL(error == TDM_ERROR_NONE);
332 error = tdm_client_vblank_set_offset(vblank, data->args.offset);
333 TDM_WARNING_IF_FAIL(error == TDM_ERROR_NONE);
335 error = tdm_client_get_fd(data->client, &fd);
336 if (error != TDM_ERROR_NONE || fd < 0) {
337 printf("tdm_client_get_fd failed\n");
348 if (!data->waiting) {
349 error = tdm_client_vblank_wait(vblank, data->args.interval,
350 _client_vblank_handler, data);
351 if (error == TDM_ERROR_DPMS_OFF) {
352 printf("tdm_client_vblank_wait failed (dpms off)\n");
355 if (error != TDM_ERROR_NONE) {
356 printf("tdm_client_vblank_wait failed (error: %d)\n", error);
362 if (!data->args.sync) {
363 ret = poll(&fds, 1, -1);
365 if (errno == EINTR || errno == EAGAIN) /* normal case */
368 printf("poll failed: %m\n");
373 error = tdm_client_handle_events(data->client);
374 if (error != TDM_ERROR_NONE) {
375 printf("tdm_client_handle_events failed\n");
383 tdm_client_vblank_destroy(vblank);
387 _dump_buffer(tbm_surface_h buffer, int count)
389 char temp[TDM_PATH_LEN] = {0,};
391 const char *ext, *file_exts[2] = {"png", "yuv"};
393 tformat = tbm_surface_get_format(buffer);
400 snprintf(temp, TDM_PATH_LEN, "%c%c%c%c_%dx%d_%d",
401 FOURCC_STR(tbm_surface_get_format(buffer)),
402 tbm_surface_get_width(buffer),
403 tbm_surface_get_height(buffer),
405 tbm_surface_internal_capture_buffer(buffer, "/tmp", temp, ext);
409 _voutput_commit(tdm_client_voutput *voutput, tbm_surface_h buffer, void *user_data)
411 tdm_test_client *data = (tdm_test_client *)user_data;
412 static int count = 0;
414 TDM_EXIT_IF_FAIL(data != NULL);
415 TDM_EXIT_IF_FAIL(buffer != NULL);
417 if ((count < 10) || (count >= 31 && count <= 40))
418 _dump_buffer(buffer, count);
422 printf("client: %d commited(%p), mode change request to index 1\n", count, buffer);
423 tdm_client_voutput_set_mode(data->voutput, 1);
424 } else if (count == 50) {
425 printf("client: %d commited(%p), disconnect\n", count, buffer);
426 tdm_client_voutput_disconnect(data->voutput);
428 printf("client: %d commited(%p)\n", count, buffer);
431 tdm_client_voutput_commit_done(voutput);
435 _voutput_output_handler(tdm_client_output *output, tdm_output_change_type type,
436 tdm_value value, void *user_data)
438 tdm_client_voutput *voutput = NULL;
439 tdm_output_conn_status status;
440 tdm_test_client *data;
441 unsigned int width, height;
443 data = (tdm_test_client *) user_data;
444 TDM_RETURN_IF_FAIL(data != NULL);
445 voutput = data->voutput;
446 TDM_RETURN_IF_FAIL(voutput != NULL);
448 if (type == TDM_OUTPUT_CHANGE_CONNECTION) {
449 status = (tdm_output_conn_status)value.u32;
451 printf("output %s.\n", conn_str[value.u32]);
453 printf("output unkown.\n");
455 if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) {
456 printf("client: disconnected, destroy voutput\n");
457 tdm_client_output_remove_change_handler(output, _voutput_output_handler, data);
459 printf("press enter to continuet\n");
462 tdm_client_voutput_destroy(voutput);
463 } else if (status == TDM_OUTPUT_CONN_STATUS_CONNECTED) {
464 printf("client: connected\n");
465 } else if (status == TDM_OUTPUT_CONN_STATUS_MODE_SETTED) {
466 tdm_client_output_get_mode(output, &width, &height);
467 printf("client: mode setted(%dx%d)\n", width, height);
469 printf("press enter to continuet\n");
473 } else if (type == TDM_OUTPUT_CHANGE_DPMS) {
474 printf("output %s.\n", dpms_str[value.u32]);
479 _voutput_make_available_mode(tdm_client_output_mode *modes, int count)
482 for (i = 0 ; i < count; i++) {
483 modes[i].clock = 25200;
484 modes[i].hdisplay = 640 * (count - i);
485 modes[i].hsync_start = 656;
486 modes[i].hsync_end = 752;
487 modes[i].htotal = 800;
489 modes[i].vdisplay = 480 * (count - i);
490 modes[i].vsync_start = 490;
491 modes[i].vsync_end = 492;
492 modes[i].vtotal = 525;
494 modes[i].vrefresh = 30;
497 snprintf(modes[i].name, TDM_NAME_LEN, "%dx%d_%d", modes[i].hdisplay, modes[i].vdisplay, i);
502 do_voutput(tdm_test_client *data)
504 tdm_client_voutput *voutput = NULL;
505 tdm_client_output *output = NULL;
506 tdm_client_output_mode modes[2];
507 tdm_error ret = TDM_ERROR_NONE;
509 printf("virtual output test - client\n");
511 voutput = tdm_client_create_voutput(data->client, "virtual-test", &ret);
512 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
514 ret = tdm_client_voutput_add_commit_handler(voutput, _voutput_commit, data);
515 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done);
517 output = tdm_client_voutput_get_client_output(voutput, &ret);
518 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done);
520 ret = tdm_client_output_add_change_handler(output, _voutput_output_handler, data);
521 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done);
523 ret = tdm_client_voutput_set_physical_size(voutput, 300, 200);
524 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done);
526 _voutput_make_available_mode(modes, 2);
527 ret = tdm_client_voutput_set_available_modes(voutput, modes, 2);
528 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done);
530 printf("virtual output test - press enter to connect\n");
533 ret = tdm_client_voutput_connect(voutput);
534 TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done);
536 data->voutput = voutput;
537 data->output = output;
540 tdm_client_handle_events_timeout(data->client, 1000);
545 tdm_client_voutput_destroy(voutput);
548 static tdm_test_client ttc_data;
551 main(int argc, char *argv[])
553 tdm_test_client *data = &ttc_data;
557 const char *xdg = (const char*)getenv("XDG_RUNTIME_DIR");
560 snprintf(buf, sizeof(buf), "/run");
561 int ret = setenv("XDG_RUNTIME_DIR", (const char*)buf, 1);
566 /* for tbm_bufmgr_init */
567 const char *s = (const char*)getenv("TBM_DISPLAY_SERVER");
570 snprintf(buf, sizeof(buf), "1");
571 int ret = setenv("TBM_DISPLAY_SERVER", (const char*)buf, 1);
576 parse_args(data, argc, argv);
578 printf("sync(%d) fps(%d) interval(%d) offset(%d) enable_fake(%d) pid(%d)\n",
579 data->args.sync, data->args.fps, data->args.interval,
580 data->args.offset, data->args.enable_fake, data->args.pid);
582 data->client = tdm_client_create(&error);
583 if (error != TDM_ERROR_NONE) {
584 printf("tdm_client_create failed\n");
592 if (data->do_voutput)
596 if (data->args.output_name)
597 free(data->args.output_name);
598 if (data->args.vblank_name)
599 free(data->args.vblank_name);
601 tdm_client_destroy(data->client);