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 <sc1.lim@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 **************************************************************************/
45 #include <tbm_surface.h>
46 #include <tbm_surface_internal.h>
51 #include <tdm_helper.h>
52 #include <tdm_backend.h>
54 #include "tdm_macro.h"
55 #include "tdm_private.h"
58 ////////////////////////////////////////////////////////////////////////////////
79 static struct typestrings typestrs[] = {
80 {OPT_QRY, "Query", NULL},
81 {OPT_TST, "Test", NULL},
82 {OPT_GEN, "General", NULL},
85 static struct optstrings optstrs[] = {
87 OPT_QRY, "q", "show tdm output, layer information",
91 OPT_TST, "a", "set all layer objects for all connected outputs",
95 OPT_TST, "o", "set a mode for a output object",
96 "<output_idx>@<mode>[&<refresh>]", "0@1920x1080"
99 OPT_TST, "l", "set a layer object",
100 "<layer_idx>[:<w>x<h>[+<x>+<y>][,<h>x<v>][@<format>]]~<w>x<h>[+<x>+<y>][*<transform>]", NULL
103 OPT_TST, "p", "set a PP object.\n\t\t'-l' is used to show the result on screen.",
104 "<w>x<h>[+<x>+<y>][,<h>x<v>][@<format>]~<w>x<h>[+<x>+<y>][,<h>x<v>][@<format>][*<transform>][&<fps>]", NULL
107 OPT_TST, "c", "catpure a output object or a layer object.\n\t\t'-l' is used to show the result on screen.",
108 "<output_idx>[,<layer_idx>]~<w>x<h>[+<x>+<y>][,<h>x<v>][@<format>][*<transform>]", NULL
111 OPT_GEN, "w", "set the property of a object",
112 "<prop_name>:<value>", NULL
115 OPT_GEN, "b", "set the fill(smtpe,tiles,plane) and framebuffer type(scanout,noncachable,wc)",
116 "<fill>[:<buf_flag>[,<buf_flag2>[,...]]]", NULL
119 OPT_GEN, "v", "update layers every vblank",
125 usage(char *app_name)
127 int type_size = sizeof(typestrs) / sizeof(struct typestrings);
128 int opt_size = sizeof(optstrs) / sizeof(struct optstrings);
131 printf("usage: %s \n\n", app_name);
133 for (t = 0; t < type_size; t++) {
136 for (o = 0; o < opt_size; o++)
137 if (optstrs[o].type == typestrs[t].type) {
139 printf(" %s options: %s\n\n", typestrs[t].string, (typestrs[t].desc) ? : "");
140 printf("\t-%s\t%s\n", optstrs[o].opt, optstrs[o].desc);
142 printf("\t\t %s\n", optstrs[o].arg);
144 printf("\t\t ex) %s\n", optstrs[o].ex);
153 ////////////////////////////////////////////////////////////////////////////////
155 static const char *tdm_buf_flag_names[] = {
160 TDM_BIT_NAME_FB(buf_flag)
162 #define print_size(s) \
163 printf("%dx%d", (s)->h, (s)->v)
164 #define print_pos(p) \
165 printf("%dx%d+%d+%d", (p)->w, (p)->h, (p)->x, (p)->y)
166 #define print_format(f) \
167 if (f) printf("%c%c%c%c", FOURCC_STR(f)); \
169 #define print_config(c) \
171 print_size(&(c)->size); \
173 print_pos(&(c)->pos); \
175 print_format((c)->format); \
177 #define print_prop(w) \
178 printf("%s(%d)", (w)->name, ((w)->value).u32)
180 typedef struct _tdm_test_server tdm_test_server;
181 typedef struct _tdm_test_server_layer tdm_test_server_layer;
182 typedef struct _tdm_test_server_capture tdm_test_server_capture;
184 typedef struct _tdm_test_server_prop {
186 char name[TDM_NAME_LEN];
189 /* variables for test */
190 struct list_head link;
191 } tdm_test_server_prop;
193 typedef struct _tdm_test_server_buffer {
194 /* variables for test */
195 tbm_surface_h buffer;
197 tdm_test_server_layer *l;
199 tdm_test_server_capture *c;
200 tdm_buffer_release_handler done;
201 } tdm_test_server_buffer;
203 typedef struct _tdm_test_server_output {
206 char mode[TDM_NAME_LEN];
209 /* variables for test */
210 struct list_head link;
211 struct list_head prop_list;
212 struct list_head layer_list;
213 tdm_test_server *data;
215 } tdm_test_server_output;
217 typedef struct _tdm_test_server_pp {
222 /* variables for test */
223 struct list_head link;
224 tdm_test_server *data;
225 tdm_test_server_layer *l;
227 tdm_test_server_buffer *bufs[6];
230 tdm_event_loop_source *timer_source;
231 } tdm_test_server_pp;
233 struct _tdm_test_server_capture {
237 tdm_info_capture info;
239 /* variables for test */
240 struct list_head link;
241 tdm_test_server *data;
242 tdm_test_server_layer *l;
243 tdm_capture *capture;
246 struct _tdm_test_server_layer {
251 /* variables for test */
252 struct list_head link;
253 struct list_head prop_list;
254 tdm_test_server *data;
255 tdm_test_server_output *o;
258 tdm_test_server_pp *owner_p;
259 tdm_test_server_capture *owner_c;
260 tdm_test_server_buffer *bufs[3];
264 struct _tdm_test_server {
272 /* variables for test */
273 struct list_head output_list;
274 struct list_head pp_list;
275 struct list_head capture_list;
276 tdm_display *display;
279 static void run_test(tdm_test_server *data);
280 static void output_setup(tdm_test_server_output *o);
281 static void layer_show_buffer(tdm_test_server_layer *l, tdm_test_server_buffer *b);
282 static void capture_attach(tdm_test_server_capture *c, tdm_test_server_buffer *b);
285 parse_size(tdm_size *size, char *arg)
288 size->h = strtol(arg, &end, 10);
289 TDM_EXIT_IF_FAIL(*end == 'x');
291 size->v = strtol(arg, &end, 10);
296 parse_pos(tdm_pos *pos, char *arg)
299 pos->w = strtol(arg, &end, 10);
300 TDM_EXIT_IF_FAIL(*end == 'x');
302 pos->h = strtol(arg, &end, 10);
305 pos->x = strtol(arg, &end, 10);
306 TDM_EXIT_IF_FAIL(*end == '+');
308 pos->y = strtol(arg, &end, 10);
314 parse_config(tdm_info_config *config, char *arg)
317 end = parse_pos(&config->pos, arg);
320 end = parse_size(&config->size, arg);
325 end = strtostr(temp, 32, arg, TDM_DELIM);
326 config->format = FOURCC_ID(temp);
332 parse_arg_o(tdm_test_server_output *o, char *arg)
335 TDM_EXIT_IF_FAIL(arg != NULL);
336 o->idx = strtol(arg, &end, 10);
337 TDM_EXIT_IF_FAIL(*end == '@');
339 end = strtostr(o->mode, TDM_NAME_LEN, arg, TDM_DELIM);
342 o->refresh = strtol(arg, &end, 10);
347 parse_arg_p(tdm_test_server_pp *p, char *arg)
349 tdm_info_pp *pp_info = &p->info;
351 TDM_EXIT_IF_FAIL(arg != NULL);
352 end = parse_config(&pp_info->src_config, arg);
353 TDM_EXIT_IF_FAIL(*end == '~');
355 end = parse_config(&pp_info->dst_config, arg);
358 pp_info->transform = strtol(arg, &end, 10);
362 p->fps = strtol(arg, &end, 10);
367 parse_arg_c(tdm_test_server_capture *c, char *arg)
369 tdm_info_capture *capture_info = &c->info;
371 TDM_EXIT_IF_FAIL(arg != NULL);
372 c->output_idx = strtol(arg, &end, 10);
375 c->layer_idx = strtol(arg, &end, 10);
377 TDM_EXIT_IF_FAIL(*end == '~');
379 end = parse_config(&capture_info->dst_config, arg);
382 capture_info->transform = strtol(arg, &end, 10);
387 parse_arg_l(tdm_test_server_layer *l, char *arg)
389 tdm_info_layer *layer_info = &l->info;
391 TDM_EXIT_IF_FAIL(arg != NULL);
392 l->idx = strtol(arg, &end, 10);
395 end = parse_config(&layer_info->src_config, arg);
397 TDM_EXIT_IF_FAIL(*end == '~');
399 end = parse_pos(&layer_info->dst_pos, arg);
402 layer_info->transform = strtol(arg, &end, 10);
407 parse_arg_w(tdm_test_server_prop *w, char *arg)
410 TDM_EXIT_IF_FAIL(arg != NULL);
411 end = strtostr(w->name, TDM_PATH_LEN, arg, TDM_DELIM);
412 TDM_EXIT_IF_FAIL(*end == ':');
414 w->value.u32 = strtol(arg, &end, 10);
418 parse_arg_b(tdm_test_server *data, char *arg)
421 char temp[TDM_NAME_LEN] = {0,};
422 TDM_EXIT_IF_FAIL(arg != NULL);
424 end = strtostr(temp, 32, arg, TDM_DELIM);
425 if (!strncmp(temp, "smpte", 5))
426 data->b_fill = PATTERN_SMPTE;
427 else if (!strncmp(temp, "tiles", 5))
428 data->b_fill = PATTERN_TILES;
429 else if (!strncmp(temp, "plain", 5))
430 data->b_fill = PATTERN_PLAIN;
432 printf("'%s': unknown flag\n", temp);
439 snprintf(temp, TDM_NAME_LEN, "%s", arg);
440 arg = strtok_r(temp, ",", &end);
442 if (!strncmp(arg, "default", 7))
443 printf("Ignore '%s' flag\n", arg);
444 else if (!strncmp(arg, "scanout", 7))
445 data->bflags |= TBM_BO_SCANOUT;
446 else if (!strncmp(arg, "noncachable", 11))
447 data->bflags |= TBM_BO_NONCACHABLE;
448 else if (!strncmp(arg, "wc", 2))
449 data->bflags |= TBM_BO_WC;
451 printf("'%s': unknown flag\n", arg);
454 arg = strtok_r(NULL, ",", &end);
460 parse_args(tdm_test_server *data, int argc, char *argv[])
462 tdm_test_server_output *o = NULL;
463 tdm_test_server_layer *l = NULL;
464 tdm_test_server_pp *p = NULL;
465 tdm_test_server_capture *c = NULL;
466 tdm_test_server_prop *w = NULL;
467 void *last_option = NULL;
468 void *last_object = NULL;
476 for (i = 1; i < argc; i++) {
477 if (!strncmp(argv[i] + 1, "q", 1)) {
480 } else if (!strncmp(argv[i] + 1, "a", 1)) {
482 } else if (!strncmp(argv[i] + 1, "o", 1)) {
483 TDM_GOTO_IF_FAIL(data->do_all == 0, all);
484 o = calloc(1, sizeof * o);
485 TDM_EXIT_IF_FAIL(o != NULL);
487 LIST_INITHEAD(&o->layer_list);
488 LIST_INITHEAD(&o->prop_list);
489 LIST_ADDTAIL(&o->link, &data->output_list);
490 parse_arg_o(o, argv[++i]);
493 } else if (!strncmp(argv[i] + 1, "p", 1)) {
494 TDM_GOTO_IF_FAIL(data->do_all == 0, all);
495 p = calloc(1, sizeof * p);
496 TDM_EXIT_IF_FAIL(p != NULL);
499 LIST_ADDTAIL(&p->link, &data->pp_list);
500 parse_arg_p(p, argv[++i]);
503 } else if (!strncmp(argv[i] + 1, "c", 1)) {
504 TDM_GOTO_IF_FAIL(data->do_all == 0, all);
505 c = calloc(1, sizeof * c);
506 TDM_EXIT_IF_FAIL(c != NULL);
510 LIST_ADDTAIL(&c->link, &data->capture_list);
511 parse_arg_c(c, argv[++i]);
514 } else if (!strncmp(argv[i] + 1, "l", 1)) {
515 TDM_GOTO_IF_FAIL(data->do_all == 0, all);
518 l = calloc(1, sizeof * l);
519 TDM_EXIT_IF_FAIL(l != NULL);
520 LIST_INITHEAD(&l->prop_list);
521 LIST_ADDTAIL(&l->link, &o->layer_list);
524 parse_arg_l(l, argv[++i]);
525 if (p && last_option == p) {
529 else if (c && last_option == c) {
534 } else if (!strncmp(argv[i] + 1, "w", 1)) {
535 TDM_GOTO_IF_FAIL(data->do_all == 0, all);
538 w = calloc(1, sizeof * w);
539 TDM_EXIT_IF_FAIL(w != NULL);
540 if (o && last_object == o)
541 LIST_ADDTAIL(&w->link, &o->prop_list);
542 else if (l && last_object == l)
543 LIST_ADDTAIL(&w->link, &l->prop_list);
544 parse_arg_w(w, argv[++i]);
545 } else if (!strncmp(argv[i] + 1, "b", 1)) {
546 parse_arg_b(data, argv[++i]);
547 } else if (!strncmp(argv[i] + 1, "v", 1)) {
556 printf("Use '-o' to set a output first.\n");
559 printf("Use '-o' or '-l' or '-p' or '-c' to set a object first.\n");
562 printf("Can't use '-%s' with '-a'.\n", argv[i] + 1);
567 interpret_args(tdm_test_server *data)
569 tdm_test_server_output *o = NULL;
570 tdm_test_server_layer *l = NULL;
576 ret = tdm_display_get_output_count(data->display, &output_count);
577 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
579 for (i = 0; i < output_count; i++) {
583 o = calloc(1, sizeof * o);
584 TDM_EXIT_IF_FAIL(o != NULL);
586 LIST_INITHEAD(&o->layer_list);
587 LIST_INITHEAD(&o->prop_list);
588 LIST_ADDTAIL(&o->link, &data->output_list);
591 output = tdm_display_get_output(data->display, i, &ret);
592 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
593 ret = tdm_output_get_layer_count(output, &layer_count);
594 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
596 for (j = 0; j < layer_count; j++) {
598 tdm_layer_capability capabilities;
600 l = calloc(1, sizeof * l);
601 TDM_EXIT_IF_FAIL(l != NULL);
602 LIST_INITHEAD(&l->prop_list);
603 LIST_ADDTAIL(&l->link, &o->layer_list);
608 layer = tdm_output_get_layer(output, j, &ret);
609 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
610 ret = tdm_layer_get_capabilities(layer, &capabilities);
611 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
613 if (capabilities & TDM_LAYER_CAPABILITY_PRIMARY)
619 /* fill layer information */
620 LIST_FOR_EACH_ENTRY(o, &data->output_list, link) {
622 const tdm_output_mode *mode;
623 int minw, minh, maxw, maxh;
624 int layer_count, i = 1;
628 output = tdm_display_get_output(data->display, o->idx, &ret);
629 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
630 ret = tdm_output_get_mode(output, &mode);
631 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
632 ret = tdm_output_get_layer_count(output, &layer_count);
633 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
634 ret = tdm_output_get_available_size(output, &minw, &minh, &maxw, &maxh, NULL);
635 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
637 if (LIST_IS_EMPTY(&o->layer_list)) {
638 ret = tdm_output_get_layer_count(output, &layer_count);
639 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
641 for (i = 0; i < layer_count; i++) {
643 tdm_layer_capability capabilities;
645 layer = tdm_output_get_layer(output, i, &ret);
646 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
647 ret = tdm_layer_get_capabilities(layer, &capabilities);
648 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
650 if (!(capabilities & TDM_LAYER_CAPABILITY_PRIMARY))
653 l = calloc(1, sizeof * l);
654 TDM_EXIT_IF_FAIL(l != NULL);
655 LIST_INITHEAD(&l->prop_list);
656 LIST_ADDTAIL(&l->link, &o->layer_list);
661 l->info.src_config.pos.w = l->info.src_config.size.h = mode->hdisplay;
662 l->info.src_config.pos.h = l->info.src_config.size.v = mode->vdisplay;
663 l->info.dst_pos = l->info.src_config.pos;
666 LIST_FOR_EACH_ENTRY(l, &o->layer_list, link) {
667 if (l->info.dst_pos.w == 0) {
668 TDM_EXIT_IF_FAIL(!l->owner_p && !l->owner_c);
670 l->info.dst_pos.w = mode->hdisplay;
671 l->info.dst_pos.h = mode->vdisplay;
673 l->info.dst_pos.w = TDM_ALIGN(mode->hdisplay / 3, 2);
674 l->info.dst_pos.h = TDM_ALIGN(mode->vdisplay / 3, 2);
675 l->info.dst_pos.x = TDM_ALIGN(((mode->hdisplay / 3) / layer_count) * i, 2);
676 l->info.dst_pos.y = TDM_ALIGN(((mode->vdisplay / 3) / layer_count) * i, 2);
680 if (minw > 0 && minh > 0) {
681 TDM_EXIT_IF_FAIL(l->info.dst_pos.w >= minw);
682 TDM_EXIT_IF_FAIL(l->info.dst_pos.h >= minh);
684 if (maxw > 0 && maxh > 0) {
685 TDM_EXIT_IF_FAIL(l->info.dst_pos.w <= maxw);
686 TDM_EXIT_IF_FAIL(l->info.dst_pos.h <= maxh);
689 l->info.src_config = l->owner_p->info.dst_config;
690 } else if (l->owner_c) {
691 l->info.src_config = l->owner_c->info.dst_config;
693 if (l->info.src_config.pos.w == 0) {
694 l->info.src_config.pos.w = l->info.dst_pos.w;
695 l->info.src_config.pos.h = l->info.dst_pos.h;
704 print_args(tdm_test_server *data)
706 tdm_test_server_output *o = NULL;
707 tdm_test_server_layer *l = NULL;
708 tdm_test_server_pp *p = NULL;
709 tdm_test_server_capture *c = NULL;
710 tdm_test_server_prop *w = NULL;
712 if (data->do_query) {
716 LIST_FOR_EACH_ENTRY(o, &data->output_list, link) {
717 printf("output %d: %s", o->idx, o->mode);
719 printf(" %d\n", o->refresh);
722 if (!LIST_IS_EMPTY(&o->prop_list)) {
724 LIST_FOR_EACH_ENTRY(w, &o->prop_list, link) {
730 LIST_FOR_EACH_ENTRY(l, &o->layer_list, link) {
732 printf("layer %d: ", l->idx);
733 print_config(&l->info.src_config);
735 print_pos(&l->info.dst_pos);
736 printf(" trans(%d)\n", l->info.transform);
737 if (!LIST_IS_EMPTY(&l->prop_list)) {
738 printf("\t\tprops: ");
739 LIST_FOR_EACH_ENTRY(w, &l->prop_list, link) {
747 LIST_FOR_EACH_ENTRY(p, &data->pp_list, link) {
749 print_config(&p->info.src_config);
751 print_config(&p->info.dst_config);
752 printf(" fps(%d) trans(%d)\n", p->fps, p->info.transform);
754 printf("\toutput_idx(%d) layer_idx(%d)\n", p->l->o->idx, p->l->idx);
756 LIST_FOR_EACH_ENTRY(c, &data->capture_list, link) {
757 printf("capture: o(%d) l(%d) ", c->output_idx, c->layer_idx);
758 print_config(&c->info.dst_config);
759 printf(" trans(%d)\n", c->info.transform);
761 printf("\toutput_idx(%d) layer_idx(%d)\n", c->l->o->idx, c->l->idx);
763 if (data->bflags != 0) {
767 int len = sizeof temp;
768 tdm_buf_flag_str(data->bflags, &p, &len);
769 printf(" (%s)\n", temp);
773 static tdm_test_server tts_data;
778 tdm_test_server *data = &tts_data;
779 tdm_test_server_output *o = NULL, *oo = NULL;
780 tdm_test_server_layer *l = NULL, *ll = NULL;
781 tdm_test_server_pp *p = NULL, *pp = NULL;
782 tdm_test_server_capture *c = NULL, *cc = NULL;
783 tdm_test_server_prop *w = NULL, *ww = NULL;
786 printf("got signal: %d\n", sig);
788 LIST_FOR_EACH_ENTRY_SAFE(o, oo, &data->output_list, link) {
791 LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) {
794 tdm_layer_unset_buffer(l->layer);
796 LIST_FOR_EACH_ENTRY_SAFE(w, ww, &l->prop_list, link) {
800 for (i = 0; i < TDM_ARRAY_SIZE(l->bufs); i++) {
801 tbm_surface_destroy(l->bufs[i]->buffer);
807 tdm_output_commit(o->output, 0, NULL, NULL);
809 LIST_FOR_EACH_ENTRY_SAFE(w, ww, &o->prop_list, link) {
818 LIST_FOR_EACH_ENTRY_SAFE(p, pp, &data->pp_list, link) {
821 tdm_display_lock(data->display);
822 tdm_event_loop_source_remove(p->timer_source);
823 tdm_display_unlock(data->display);
825 tdm_pp_destroy(p->pp);
826 for (i = 0; i < TDM_ARRAY_SIZE(p->bufs); i++) {
827 tbm_surface_destroy(p->bufs[i]->buffer);
833 LIST_FOR_EACH_ENTRY_SAFE(c, cc, &data->capture_list, link) {
835 tdm_capture_destroy(c->capture);
840 tdm_display_deinit(data->display);
846 main(int argc, char *argv[])
848 tdm_test_server *data = &tts_data;
849 char temp[TDM_SERVER_REPLY_MSG_LEN];
850 int len = sizeof temp;
853 signal(SIGINT, exit_test); /* 2 */
854 signal(SIGTERM, exit_test); /* 15 */
856 memset(data, 0, sizeof * data);
857 LIST_INITHEAD(&data->output_list);
858 LIST_INITHEAD(&data->pp_list);
859 LIST_INITHEAD(&data->capture_list);
862 data->bflags = TBM_BO_SCANOUT;
863 data->b_fill = PATTERN_SMPTE;
865 data->display = tdm_display_init(&ret);
866 TDM_EXIT_IF_FAIL(data->display != NULL);
868 parse_args(data, argc, argv);
869 interpret_args(data);
872 if (data->do_query) {
873 tdm_helper_get_display_information(data->display, temp, &len);
881 tdm_display_deinit(data->display);
887 output_setup(tdm_test_server_output *o)
889 tdm_test_server *data = o->data;
890 const tdm_output_mode *modes, *found = NULL, *best = NULL, *prefer = NULL;
891 tdm_test_server_prop *w = NULL;
892 const tdm_prop *props;
896 o->output = tdm_display_get_output(data->display, o->idx, &ret);
897 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
899 ret = tdm_output_get_available_modes(o->output, &modes, &count);
900 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
902 for (i = 0; i < count; i++) {
903 if (!strncmp(o->mode, modes[i].name, TDM_NAME_LEN) && o->refresh == modes[i].vrefresh) {
905 printf("found mode: %dx%d %d\n", found->hdisplay, found->vdisplay, found->vrefresh);
910 if (modes[i].flags & TDM_OUTPUT_MODE_TYPE_PREFERRED)
913 if (!found && prefer) {
915 printf("found prefer mode: %dx%d %d\n", found->hdisplay, found->vdisplay, found->vrefresh);
917 if (!found && best) {
919 printf("found best mode: %dx%d %d\n", found->hdisplay, found->vdisplay, found->vrefresh);
923 printf("couldn't find any mode\n");
927 ret = tdm_output_set_mode(o->output, found);
928 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
930 ret = tdm_output_get_available_properties(o->output, &props, &count);
931 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
933 LIST_FOR_EACH_ENTRY(w, &o->prop_list, link) {
934 for (i = 0; i < count; i++) {
935 if (strncmp(w->name, props[i].name, TDM_NAME_LEN))
937 ret = tdm_output_set_property(o->output, props[i].id, w->value);
938 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
943 /* DPMS on forcely at the first time. */
944 ret = tdm_output_set_dpms(o->output, TDM_OUTPUT_DPMS_ON);
945 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
948 static tdm_test_server_buffer*
949 layer_get_buffer(tdm_test_server_layer *l)
951 int i, size = TDM_ARRAY_SIZE(l->bufs);
953 for (i = 0; i < size; i++) {
954 int width = (l->info.src_config.size.h)?:l->info.src_config.pos.w;
955 int height = (l->info.src_config.size.v)?:l->info.src_config.pos.h;
956 unsigned int format = (l->info.src_config.format)?:TBM_FORMAT_ARGB8888;
957 int flags = l->o->data->bflags;
958 tdm_test_server_buffer *b = calloc(1, sizeof *b);
959 TDM_EXIT_IF_FAIL(b != NULL);
960 b->buffer = tbm_surface_internal_create_with_flags(width, height, format, flags);
961 TDM_EXIT_IF_FAIL(b->buffer != NULL);
965 for (i = 0; i < size; i++) {
966 if (!l->bufs[i]->in_use) {
967 tdm_test_buffer_fill(l->bufs[i]->buffer, l->data->b_fill);
971 printf("no available layer buffer.\n");
976 layer_cb_commit(tdm_output *output, unsigned int sequence,
977 unsigned int tv_sec, unsigned int tv_usec,
980 tdm_test_server_layer *l = user_data;
981 tdm_test_server_buffer *b = layer_get_buffer(l);
983 TDM_EXIT_IF_FAIL(b != NULL);
984 layer_show_buffer(l, b);
988 layer_cb_buffer_release(tbm_surface_h buffer, void *user_data)
990 tdm_test_server_buffer *b = user_data;
992 tdm_buffer_remove_release_handler(b->buffer, layer_cb_buffer_release, b);
994 b->done(buffer, user_data);
998 layer_show_buffer(tdm_test_server_layer *l, tdm_test_server_buffer *b)
1000 tdm_test_server *data = l->o->data;
1003 ret = tdm_layer_set_buffer(l->layer, b->buffer);
1004 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1007 tdm_buffer_add_release_handler(b->buffer, layer_cb_buffer_release, b);
1009 if (data->do_vblank)
1010 ret = tdm_output_commit(l->o->output, 0, layer_cb_commit, l);
1012 ret = tdm_output_commit(l->o->output, 0, NULL, NULL);
1013 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1015 printf("show:\tl(%p) b(%p)\n", l, b);
1019 layer_setup(tdm_test_server_layer *l, tdm_test_server_buffer *b)
1021 tdm_test_server_prop *w = NULL;
1022 const tdm_prop *props;
1025 tbm_surface_info_s info;
1027 l->layer = tdm_output_get_layer(l->o->output, l->idx, &ret);
1028 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1030 /* The size and format information should be same with buffer's */
1031 tbm_surface_get_info(b->buffer, &info);
1032 if (IS_RGB(info.format)) {
1033 l->info.src_config.size.h = info.planes[0].stride >> 2;
1034 l->info.src_config.size.v = info.height;
1036 l->info.src_config.size.h = info.planes[0].stride;
1037 l->info.src_config.size.v = info.height;
1039 l->info.src_config.format = info.format;
1041 ret = tdm_layer_set_info(l->layer, &l->info);
1042 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1044 ret = tdm_layer_get_available_properties(l->layer, &props, &count);
1045 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1047 LIST_FOR_EACH_ENTRY(w, &l->prop_list, link) {
1048 for (i = 0; i < count; i++) {
1049 if (strncmp(w->name, props[i].name, TDM_NAME_LEN))
1051 ret = tdm_layer_set_property(l->layer, props[i].id, w->value);
1052 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1058 static tdm_test_server_buffer*
1059 pp_get_buffer(tdm_test_server_pp *p)
1061 int i, size = TDM_ARRAY_SIZE(p->bufs);
1063 for (i = 0; i < size; i++) {
1064 int width = (p->info.src_config.size.h)?:p->info.src_config.pos.w;
1065 int height = (p->info.src_config.size.v)?:p->info.src_config.pos.h;
1066 unsigned int format = (p->info.src_config.format)?:TBM_FORMAT_ARGB8888;
1067 int flags = p->l->o->data->bflags;
1068 tdm_test_server_buffer *b = calloc(1, sizeof *b);
1069 TDM_EXIT_IF_FAIL(b != NULL);
1070 b->buffer = tbm_surface_internal_create_with_flags(width, height, format, flags);
1071 TDM_EXIT_IF_FAIL(b->buffer != NULL);
1075 for (i = 0; i < size; i++) {
1076 if (!p->bufs[i]->in_use) {
1077 tdm_test_buffer_fill(p->bufs[i]->buffer, p->data->b_fill);
1081 printf("no available pp buffer.\n");
1086 pp_cb_sb_release(tbm_surface_h buffer, void *user_data)
1088 tdm_test_server_buffer *b = user_data;
1090 tdm_buffer_remove_release_handler(b->buffer, pp_cb_sb_release, b);
1094 pp_cb_db_release(tbm_surface_h buffer, void *user_data)
1096 tdm_test_server_buffer *b = user_data;
1098 tdm_buffer_remove_release_handler(b->buffer, pp_cb_db_release, b);
1099 layer_show_buffer(b->l, b);
1103 pp_convert_buffer(tdm_test_server_pp *p, tdm_test_server_buffer *sb, tdm_test_server_buffer *db)
1107 ret = tdm_pp_attach(p->pp, sb->buffer, db->buffer);
1108 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1110 sb->in_use = db->in_use = 1;
1112 tdm_buffer_add_release_handler(sb->buffer, pp_cb_sb_release, sb);
1113 tdm_buffer_add_release_handler(db->buffer, pp_cb_db_release, db);
1115 ret = tdm_pp_commit(p->pp);
1116 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1118 printf("convt:\tp(%p) sb(%p) db(%p)\n", p, sb, db);
1121 /* tdm_event_loop_xxx() function is not for the display server. It's for TDM
1122 * backend module. I use them only for simulating the video play. When we call
1123 * tdm_event_loop_xxx() outside of TDM backend module, we have to lock/unlock
1124 * the TDM display. And when the callback function of tdm_event_loop_xxx() is
1125 * called, the display has been already locked. So in this test application,
1126 * we have to unlock/lock the display for testing.
1129 pp_cb_timeout(void *user_data)
1131 tdm_test_server_pp *p = user_data;
1132 tdm_test_server *data = p->l->o->data;
1133 tdm_test_server_buffer *sb, *db;
1136 tdm_display_unlock(data->display);
1138 sb = pp_get_buffer(p);
1139 TDM_EXIT_IF_FAIL(sb != NULL);
1140 db = layer_get_buffer(p->l);
1141 TDM_EXIT_IF_FAIL(db != NULL);
1143 pp_convert_buffer(p, sb, db);
1145 tdm_display_lock(data->display);
1146 ret = tdm_event_loop_source_timer_update(p->timer_source, 1000 / p->fps);
1147 tdm_display_unlock(data->display);
1148 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1150 tdm_display_lock(data->display);
1152 return TDM_ERROR_NONE;
1156 pp_setup(tdm_test_server_pp *p, tdm_test_server_buffer *sb, tdm_test_server_buffer *db)
1158 tdm_test_server *data = p->l->o->data;
1159 tbm_surface_info_s info;
1162 p->pp = tdm_display_create_pp(data->display, &ret);
1163 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1165 /* The size and format information should be same with buffer's */
1166 tbm_surface_get_info(sb->buffer, &info);
1167 if (IS_RGB(info.format)) {
1168 p->info.src_config.size.h = info.planes[0].stride >> 2;
1169 p->info.src_config.size.v = info.height;
1171 p->info.src_config.size.h = info.planes[0].stride;
1172 p->info.src_config.size.v = info.height;
1174 p->info.src_config.format = info.format;
1176 /* The size and format information should be same with buffer's */
1177 tbm_surface_get_info(db->buffer, &info);
1178 if (IS_RGB(info.format)) {
1179 p->info.dst_config.size.h = info.planes[0].stride >> 2;
1180 p->info.dst_config.size.v = info.height;
1182 p->info.dst_config.size.h = info.planes[0].stride;
1183 p->info.dst_config.size.v = info.height;
1185 p->info.dst_config.format = info.format;
1187 ret = tdm_pp_set_info(p->pp, &p->info);
1188 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1190 layer_setup(p->l, db);
1192 /* tdm_event_loop_xxx() function is not for the display server. It's for TDM
1193 * backend module. I use them only for simulating the video play. When we call
1194 * tdm_event_loop_xxx() outside of TDM backend module, we have to lock/unlock
1195 * the TDM display. And when the callback function of tdm_event_loop_xxx() is
1196 * called, the display has been already locked. So in this test application,
1197 * we have to unlock/lock the display for testing.
1199 tdm_display_lock(data->display);
1200 p->timer_source = tdm_event_loop_add_timer_handler(data->display, pp_cb_timeout, p, &ret);
1201 tdm_display_unlock(data->display);
1202 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1204 tdm_display_lock(data->display);
1205 ret = tdm_event_loop_source_timer_update(p->timer_source, 1000 / p->fps);
1206 tdm_display_unlock(data->display);
1207 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1211 capture_cb_buffer_done(tbm_surface_h buffer, void *user_data)
1213 tdm_test_server_buffer *b = user_data;
1214 capture_attach(b->c, b);
1218 capture_cb_buffer_release(tbm_surface_h buffer, void *user_data)
1220 tdm_test_server_buffer *b = user_data;
1222 tdm_buffer_remove_release_handler(b->buffer, capture_cb_buffer_release, b);
1223 b->done = capture_cb_buffer_done;
1224 layer_show_buffer(b->l, b);
1228 capture_attach(tdm_test_server_capture *c, tdm_test_server_buffer *b)
1232 ret = tdm_capture_attach(c->capture, b->buffer);
1233 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1238 tdm_buffer_add_release_handler(b->buffer, capture_cb_buffer_release, b);
1239 printf("capture:\tc(%p) b(%p)\n", c, b);
1241 ret = tdm_capture_commit(c->capture);
1242 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1246 capture_setup(tdm_test_server_capture *c, tdm_test_server_buffer *b)
1248 tdm_test_server *data = c->l->o->data;
1251 tbm_surface_info_s info;
1254 if (c->output_idx != -1 && c->layer_idx == -1) {
1255 output = tdm_display_get_output(data->display, c->output_idx, &ret);
1256 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1257 c->capture = tdm_output_create_capture(output, &ret);
1258 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1259 } else if (c->output_idx != -1 && c->layer_idx != -1) {
1260 output = tdm_display_get_output(data->display, c->output_idx, &ret);
1261 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1262 layer = tdm_output_get_layer(output, c->layer_idx, &ret);
1263 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1264 c->capture = tdm_layer_create_capture(layer, &ret);
1265 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1268 TDM_EXIT_IF_FAIL(c->capture != NULL);
1270 /* The size and format information should be same with buffer's */
1271 tbm_surface_get_info(b->buffer, &info);
1272 if (IS_RGB(info.format)) {
1273 c->info.dst_config.size.h = info.planes[0].stride >> 2;
1274 c->info.dst_config.size.v = info.height;
1276 c->info.dst_config.size.h = info.planes[0].stride;
1277 c->info.dst_config.size.v = info.height;
1279 c->info.dst_config.format = info.format;
1281 ret = tdm_capture_set_info(c->capture, &c->info);
1282 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1284 layer_setup(c->l, b);
1288 run_test(tdm_test_server *data)
1290 tdm_test_server_output *o = NULL;
1291 tdm_test_server_layer *l = NULL;
1292 tdm_test_server_pp *p = NULL;
1293 tdm_test_server_capture *c = NULL;
1294 tdm_display_capability caps;
1297 ret = tdm_display_get_capabilities(data->display, &caps);
1298 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1300 LIST_FOR_EACH_ENTRY(o, &data->output_list, link) {
1301 LIST_FOR_EACH_ENTRY(l, &o->layer_list, link) {
1302 if (!l->owner_p && !l->owner_c) {
1303 tdm_test_server_buffer *b;
1304 b = layer_get_buffer(l);
1306 layer_show_buffer(l, b);
1311 LIST_FOR_EACH_ENTRY(p, &data->pp_list, link) {
1312 tdm_test_server_buffer *sb, *db;
1313 TDM_GOTO_IF_FAIL(caps & TDM_DISPLAY_CAPABILITY_PP, no_pp);
1314 sb = pp_get_buffer(p);
1315 TDM_EXIT_IF_FAIL(sb != NULL);
1316 db = layer_get_buffer(p->l);
1317 TDM_EXIT_IF_FAIL(db != NULL);
1318 pp_setup(p, sb, db);
1319 pp_convert_buffer(p, sb, db);
1322 LIST_FOR_EACH_ENTRY(c, &data->capture_list, link) {
1323 TDM_GOTO_IF_FAIL(caps & TDM_DISPLAY_CAPABILITY_CAPTURE, no_capture);
1324 tdm_test_server_buffer *b;
1325 b = layer_get_buffer(c->l);
1326 capture_setup(c, b);
1327 capture_attach(c, b);
1328 b = layer_get_buffer(c->l);
1329 capture_attach(c, b);
1330 b = layer_get_buffer(c->l);
1331 capture_attach(c, b);
1334 printf("enter test loop\n");
1337 tdm_display_handle_events(data->display);
1341 printf("no PP capability\n");
1344 printf("no Capture capability\n");