fix seg.fault of tdm-test-server
[platform/core/uifw/libtdm.git] / tools / tdm_test_server.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 <sc1.lim@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 <signal.h>
40 #include <poll.h>
41 #include <errno.h>
42 #include <time.h>
43 #include <stdint.h>
44
45 #include <tbm_surface.h>
46 #include <tbm_surface_internal.h>
47
48 #include <tdm.h>
49 #include <tdm_log.h>
50 #include <tdm_list.h>
51 #include <tdm_helper.h>
52 #include <tdm_backend.h>
53
54 #include "tdm_macro.h"
55 #include "tdm_private.h"
56 #include "buffers.h"
57
58 ////////////////////////////////////////////////////////////////////////////////
59 struct typestrings {
60         int type;
61         const char *string;
62         const char *desc;
63 };
64
65 struct optstrings {
66         int  type;
67         const char *opt;
68         const char *desc;
69         const char *arg;
70         const char *ex;
71 };
72
73 enum {
74         OPT_QRY,
75         OPT_TST,
76         OPT_GEN,
77 };
78
79 static struct typestrings typestrs[] = {
80         {OPT_QRY, "Query",          NULL},
81         {OPT_TST, "Test",           NULL},
82         {OPT_GEN, "General",        NULL},
83 };
84
85 static struct optstrings optstrs[] = {
86         {
87                 OPT_QRY, "q", "show tdm output, layer information",
88                 NULL, NULL
89         },
90         {
91                 OPT_TST, "a", "set all layer objects for all connected outputs",
92                 NULL, NULL
93         },
94         {
95                 OPT_TST, "o", "set a mode for a output object",
96                 "<output_idx>@<mode>[&<refresh>]", "0@1920x1080"
97         },
98         {
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
101         },
102         {
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
105         },
106         {
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
109         },
110         {
111                 OPT_GEN, "w", "set the property of a object",
112                 "<prop_name>:<value>", NULL
113         },
114         {
115                 OPT_GEN, "b", "set the fill(smtpe,tiles,plane) and framebuffer type(scanout,noncachable,wc)",
116                 "<fill>[:<buf_flag>[,<buf_flag2>[,...]]]", NULL
117         },
118         {
119                 OPT_GEN, "v", "update layers every vblank",
120                 NULL, NULL
121         },
122 };
123
124 static void
125 usage(char *app_name)
126 {
127         int type_size = sizeof(typestrs) / sizeof(struct typestrings);
128         int opt_size = sizeof(optstrs) / sizeof(struct optstrings);
129         int t;
130
131         printf("usage: %s \n\n", app_name);
132
133         for (t = 0; t < type_size; t++) {
134                 int o, f = 1;
135
136                 for (o = 0; o < opt_size; o++)
137                         if (optstrs[o].type == typestrs[t].type) {
138                                 if (f == 1)
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);
141                                 if (optstrs[o].arg)
142                                         printf("\t\t  %s\n", optstrs[o].arg);
143                                 if (optstrs[o].ex)
144                                         printf("\t\t  ex) %s\n", optstrs[o].ex);
145                                 f = 0;
146                         }
147                 printf("\n");
148         }
149
150         exit(0);
151 }
152
153 ////////////////////////////////////////////////////////////////////////////////
154
155 static const char *tdm_buf_flag_names[] = {
156         "scanout",
157         "noncachable",
158         "wc",
159 };
160 TDM_BIT_NAME_FB(buf_flag)
161
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)); \
168         else printf("NONE")
169 #define print_config(c) \
170         do { \
171                 print_size(&(c)->size); \
172                 printf(" "); \
173                 print_pos(&(c)->pos); \
174                 printf(" "); \
175                 print_format((c)->format); \
176         } while (0)
177 #define print_prop(w) \
178         printf("%s(%d)", (w)->name, ((w)->value).u32)
179
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;
183
184 typedef struct _tdm_test_server_prop {
185         /* args */
186         char name[TDM_NAME_LEN];
187         tdm_value value;
188
189         /* variables for test */
190         struct list_head link;
191 } tdm_test_server_prop;
192
193 typedef struct _tdm_test_server_buffer {
194         /* variables for test */
195         tbm_surface_h buffer;
196         int in_use;
197         tdm_test_server_layer *l;
198
199         tdm_test_server_capture *c;
200         tdm_buffer_release_handler done;
201 } tdm_test_server_buffer;
202
203 typedef struct _tdm_test_server_output {
204         /* args */
205         int idx;
206         char mode[TDM_NAME_LEN];
207         int refresh;
208
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;
214         tdm_output *output;
215 } tdm_test_server_output;
216
217 typedef struct _tdm_test_server_pp {
218         /* args */
219         tdm_info_pp info;
220         int fps;
221
222         /* variables for test */
223         struct list_head link;
224         tdm_test_server *data;
225         tdm_test_server_layer *l;
226         tdm_pp *pp;
227         tdm_test_server_buffer *bufs[6];
228         int buf_idx;
229
230         tdm_event_loop_source *timer_source;
231 } tdm_test_server_pp;
232
233 struct _tdm_test_server_capture {
234         /* args */
235         int output_idx;
236         int layer_idx;
237         tdm_info_capture info;
238
239         /* variables for test */
240         struct list_head link;
241         tdm_test_server *data;
242         tdm_test_server_layer *l;
243         tdm_capture *capture;
244 };
245
246 struct _tdm_test_server_layer {
247         /* args */
248         int idx;
249         tdm_info_layer info;
250
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;
256         tdm_layer *layer;
257         int is_primary;
258         tdm_test_server_pp *owner_p;
259         tdm_test_server_capture *owner_c;
260         tdm_test_server_buffer *bufs[3];
261         int buf_idx;
262 };
263
264 struct _tdm_test_server {
265         /* args */
266         int do_query;
267         int do_all;
268         int do_vblank;
269         int bflags;
270         int b_fill;
271
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;
277 };
278
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);
283
284 static char*
285 parse_size(tdm_size *size, char *arg)
286 {
287         char *end;
288         size->h = strtol(arg, &end, 10);
289         TDM_EXIT_IF_FAIL(*end == 'x');
290         arg = end + 1;
291         size->v = strtol(arg, &end, 10);
292         return end;
293 }
294
295 static char*
296 parse_pos(tdm_pos *pos, char *arg)
297 {
298         char *end;
299         pos->w = strtol(arg, &end, 10);
300         TDM_EXIT_IF_FAIL(*end == 'x');
301         arg = end + 1;
302         pos->h = strtol(arg, &end, 10);
303         if (*end == '+') {
304                 arg = end + 1;
305                 pos->x = strtol(arg, &end, 10);
306                 TDM_EXIT_IF_FAIL(*end == '+');
307                 arg = end + 1;
308                 pos->y = strtol(arg, &end, 10);
309         }
310         return end;
311 }
312
313 static char*
314 parse_config(tdm_info_config *config, char *arg)
315 {
316         char *end;
317         end = parse_pos(&config->pos, arg);
318         if (*end == ',') {
319                 arg = end + 1;
320                 end = parse_size(&config->size, arg);
321         }
322         if (*end == '@') {
323                 char temp[32];
324                 arg = end + 1;
325                 end = strtostr(temp, 32, arg, TDM_DELIM);
326                 config->format = FOURCC_ID(temp);
327         }
328         return end;
329 }
330
331 static void
332 parse_arg_o(tdm_test_server_output *o, char *arg)
333 {
334         char *end;
335         TDM_EXIT_IF_FAIL(arg != NULL);
336         o->idx = strtol(arg, &end, 10);
337         TDM_EXIT_IF_FAIL(*end == '@');
338         arg = end + 1;
339         end = strtostr(o->mode, TDM_NAME_LEN, arg, TDM_DELIM);
340         if (*end == ',') {
341                 arg = end + 1;
342                 o->refresh = strtol(arg, &end, 10);
343         }
344 }
345
346 static void
347 parse_arg_p(tdm_test_server_pp *p, char *arg)
348 {
349         tdm_info_pp *pp_info = &p->info;
350         char *end;
351         TDM_EXIT_IF_FAIL(arg != NULL);
352         end = parse_config(&pp_info->src_config, arg);
353         TDM_EXIT_IF_FAIL(*end == '~');
354         arg = end + 1;
355         end = parse_config(&pp_info->dst_config, arg);
356         if (*end == '*') {
357                 arg = end + 1;
358                 pp_info->transform = strtol(arg, &end, 10);
359         }
360         if (*end == '&') {
361                 arg = end + 1;
362                 p->fps = strtol(arg, &end, 10);
363         }
364 }
365
366 static void
367 parse_arg_c(tdm_test_server_capture *c, char *arg)
368 {
369         tdm_info_capture *capture_info = &c->info;
370         char *end;
371         TDM_EXIT_IF_FAIL(arg != NULL);
372         c->output_idx = strtol(arg, &end, 10);
373         if (*end == ',') {
374                 arg = end + 1;
375                 c->layer_idx = strtol(arg, &end, 10);
376         }
377         TDM_EXIT_IF_FAIL(*end == '~');
378         arg = end + 1;
379         end = parse_config(&capture_info->dst_config, arg);
380         if (*end == '*') {
381                 arg = end + 1;
382                 capture_info->transform = strtol(arg, &end, 10);
383         }
384 }
385
386 static void
387 parse_arg_l(tdm_test_server_layer *l, char *arg)
388 {
389         tdm_info_layer *layer_info = &l->info;
390         char *end;
391         TDM_EXIT_IF_FAIL(arg != NULL);
392         l->idx = strtol(arg, &end, 10);
393         if (*end == ':') {
394                 arg = end + 1;
395                 end = parse_config(&layer_info->src_config, arg);
396         }
397         TDM_EXIT_IF_FAIL(*end == '~');
398         arg = end + 1;
399         end = parse_pos(&layer_info->dst_pos, arg);
400         if (*end == '*') {
401                 arg = end + 1;
402                 layer_info->transform = strtol(arg, &end, 10);
403         }
404 }
405
406 static void
407 parse_arg_w(tdm_test_server_prop *w, char *arg)
408 {
409         char *end;
410         TDM_EXIT_IF_FAIL(arg != NULL);
411         end = strtostr(w->name, TDM_PATH_LEN, arg, TDM_DELIM);
412         TDM_EXIT_IF_FAIL(*end == ':');
413         arg = end + 1;
414         w->value.u32 = strtol(arg, &end, 10);
415 }
416
417 static void
418 parse_arg_b(tdm_test_server *data, char *arg)
419 {
420         char *end = arg;
421         char temp[TDM_NAME_LEN] = {0,};
422         TDM_EXIT_IF_FAIL(arg != NULL);
423
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;
431         else {
432                 printf("'%s': unknown flag\n", temp);
433                 exit(0);
434         }
435
436         if (*arg == ':') {
437                 data->bflags = 0;
438                 arg = end + 1;
439                 snprintf(temp, TDM_NAME_LEN, "%s", arg);
440                 arg = strtok_r(temp, ",", &end);
441                 while (arg) {
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;
450                         else {
451                                 printf("'%s': unknown flag\n", arg);
452                                 exit(0);
453                         }
454                         arg = strtok_r(NULL, ",", &end);
455                 }
456         }
457 }
458
459 static void
460 parse_args(tdm_test_server *data, int argc, char *argv[])
461 {
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;
469         int i;
470
471         if (argc < 2) {
472                 usage(argv[0]);
473                 exit(0);
474         }
475
476         for (i = 1; i < argc; i++) {
477                 if (!strncmp(argv[i] + 1, "q", 1)) {
478                         data->do_query = 1;
479                         return;
480                 } else if (!strncmp(argv[i] + 1, "a", 1)) {
481                         data->do_all = 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);
486                         o->data = data;
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]);
491                         last_option = o;
492                         last_object = o;
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);
497                         p->data = data;
498                         p->fps = 30;
499                         LIST_ADDTAIL(&p->link, &data->pp_list);
500                         parse_arg_p(p, argv[++i]);
501                         last_option = p;
502                         last_object = o;
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);
507                         c->data = data;
508                         c->output_idx = -1;
509                         c->layer_idx = -1;
510                         LIST_ADDTAIL(&c->link, &data->capture_list);
511                         parse_arg_c(c, argv[++i]);
512                         last_option = c;
513                         last_object = o;
514                 } else if (!strncmp(argv[i] + 1, "l", 1)) {
515                         TDM_GOTO_IF_FAIL(data->do_all == 0, all);
516                         if (!o)
517                                 goto no_output;
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);
522                         l->data = data;
523                         l->o = o;
524                         parse_arg_l(l, argv[++i]);
525                         if (p && last_option == p) {
526                                 p->l = l;
527                                 l->owner_p = p;
528                         }
529                         else if (c && last_option == c) {
530                                 c->l = l;
531                                 l->owner_c = c;
532                         }
533                         last_object = o;
534                 } else if (!strncmp(argv[i] + 1, "w", 1)) {
535                         TDM_GOTO_IF_FAIL(data->do_all == 0, all);
536                         if (!last_object)
537                                 goto no_object;
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)) {
548                         data->do_vblank = 1;
549                 } else {
550                         usage(argv[0]);
551                         exit(0);
552                 }
553         }
554         return;
555 no_output:
556         printf("Use '-o' to set a output first.\n");
557         exit(0);
558 no_object:
559         printf("Use '-o' or '-l' or '-p' or '-c' to set a object first.\n");
560         exit(0);
561 all:
562         printf("Can't use '-%s' with '-a'.\n", argv[i] + 1);
563         exit(0);
564 }
565
566 static void
567 interpret_args(tdm_test_server *data)
568 {
569         tdm_test_server_output *o = NULL;
570         tdm_test_server_layer *l = NULL;
571         tdm_error ret;
572
573         if (data->do_all) {
574                 int i, output_count;
575
576                 ret = tdm_display_get_output_count(data->display, &output_count);
577                 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
578
579                 for (i = 0; i < output_count; i++) {
580                         tdm_output *output;
581                         int j, layer_count;
582
583                         o = calloc(1, sizeof * o);
584                         TDM_EXIT_IF_FAIL(o != NULL);
585                         o->data = data;
586                         LIST_INITHEAD(&o->layer_list);
587                         LIST_INITHEAD(&o->prop_list);
588                         LIST_ADDTAIL(&o->link, &data->output_list);
589                         o->idx = i;
590
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);
595
596                         for (j = 0; j < layer_count; j++) {
597                                 tdm_layer *layer;
598                                 tdm_layer_capability capabilities;
599
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);
604                                 l->data = data;
605                                 l->o = o;
606                                 l->idx = j;
607
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);
612
613                                 if (capabilities & TDM_LAYER_CAPABILITY_PRIMARY)
614                                         l->is_primary = 1;
615                         }
616                 }
617         }
618
619         /* fill layer information */
620         LIST_FOR_EACH_ENTRY(o, &data->output_list, link) {
621                 tdm_output *output;
622                 const tdm_output_mode *mode;
623                 int minw, minh, maxw, maxh;
624                 int layer_count, i = 1;
625
626                 output_setup(o);
627
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);
636
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);
640
641                         for (i = 0; i < layer_count; i++) {
642                                 tdm_layer *layer;
643                                 tdm_layer_capability capabilities;
644
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);
649
650                                 if (!(capabilities & TDM_LAYER_CAPABILITY_PRIMARY))
651                                         continue;
652
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);
657                                 l->data = data;
658                                 l->o = o;
659                                 l->idx = i;
660                                 l->is_primary = 1;
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;
664                         }
665                 } else {
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);
669                                         if (l->is_primary) {
670                                                 l->info.dst_pos.w = mode->hdisplay;
671                                                 l->info.dst_pos.h = mode->vdisplay;
672                                         } else {
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);
677                                                 i++;
678                                         }
679                                 }
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);
683                                 }
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);
687                                 }
688                                 if (l->owner_p) {
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;
692                                 } else {
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;
696                                         }
697                                 }
698                         }
699                 }
700         }
701 }
702
703 static void
704 print_args(tdm_test_server *data)
705 {
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;
711
712         if (data->do_query) {
713                 printf("query\n");
714                 return;
715         }
716         LIST_FOR_EACH_ENTRY(o, &data->output_list, link) {
717                 printf("output %d: %s", o->idx, o->mode);
718                 if (o->refresh > 0)
719                         printf(" %d\n", o->refresh);
720                 else
721                         printf("\n");
722                 if (!LIST_IS_EMPTY(&o->prop_list)) {
723                         printf("\tprops: ");
724                         LIST_FOR_EACH_ENTRY(w, &o->prop_list, link) {
725                                 print_prop(w);
726                                 printf(" ");
727                         }
728                         printf("\n");
729                 }
730                 LIST_FOR_EACH_ENTRY(l, &o->layer_list, link) {
731                         printf("\t");
732                         printf("layer %d: ", l->idx);
733                         print_config(&l->info.src_config);
734                         printf(" ! ");
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) {
740                                         print_prop(w);
741                                         printf(" ");
742                                 }
743                                 printf("\n");
744                         }
745                 }
746         }
747         LIST_FOR_EACH_ENTRY(p, &data->pp_list, link) {
748                 printf("pp: ");
749                 print_config(&p->info.src_config);
750                 printf(" ! ");
751                 print_config(&p->info.dst_config);
752                 printf(" fps(%d) trans(%d)\n", p->fps, p->info.transform);
753                 if (p->l)
754                         printf("\toutput_idx(%d) layer_idx(%d)\n", p->l->o->idx, p->l->idx);
755         }
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);
760                 if (c->l)
761                         printf("\toutput_idx(%d) layer_idx(%d)\n", c->l->o->idx, c->l->idx);
762         }
763         if (data->bflags != 0) {
764                 printf("buffer: ");
765                 char temp[256];
766                 char *p = temp;
767                 int len = sizeof temp;
768                 tdm_buf_flag_str(data->bflags, &p, &len);
769                 printf(" (%s)\n", temp);
770         }
771 }
772
773 static tdm_test_server tts_data;
774
775 static void
776 exit_test(int sig)
777 {
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;
784         int i;
785
786         printf("got signal: %d\n", sig);
787
788         LIST_FOR_EACH_ENTRY_SAFE(o, oo, &data->output_list, link) {
789                 LIST_DEL(&o->link);
790
791                 LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) {
792                         LIST_DEL(&l->link);
793
794                         tdm_layer_unset_buffer(l->layer);
795
796                         LIST_FOR_EACH_ENTRY_SAFE(w, ww, &l->prop_list, link) {
797                                 LIST_DEL(&w->link);
798                                 free(w);
799                         }
800                         for (i = 0; i < TDM_ARRAY_SIZE(l->bufs); i++) {
801                                 tbm_surface_destroy(l->bufs[i]->buffer);
802                                 free(l->bufs[i]);
803                         }
804                         free(l);
805                 }
806
807                 tdm_output_commit(o->output, 0, NULL, NULL);
808
809                 LIST_FOR_EACH_ENTRY_SAFE(w, ww, &o->prop_list, link) {
810                         LIST_DEL(&w->link);
811                         free(w);
812                 }
813
814                 free(o);
815         }
816
817
818         LIST_FOR_EACH_ENTRY_SAFE(p, pp, &data->pp_list, link) {
819                 LIST_DEL(&p->link);
820
821                 tdm_display_lock(data->display);
822                 tdm_event_loop_source_remove(p->timer_source);
823                 tdm_display_unlock(data->display);
824
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);
828                         free(p->bufs[i]);
829                 }
830                 free(p);
831         }
832
833         LIST_FOR_EACH_ENTRY_SAFE(c, cc, &data->capture_list, link) {
834                 LIST_DEL(&c->link);
835                 tdm_capture_destroy(c->capture);
836                 free(c);
837         }
838
839         if (data->display)
840                 tdm_display_deinit(data->display);
841
842         exit(0);
843 }
844
845 int
846 main(int argc, char *argv[])
847 {
848         tdm_test_server *data = &tts_data;
849         char temp[TDM_SERVER_REPLY_MSG_LEN];
850         int len = sizeof temp;
851         tdm_error ret;
852
853         signal(SIGINT, exit_test);    /* 2 */
854         signal(SIGTERM, exit_test);   /* 15 */
855
856         memset(data, 0, sizeof * data);
857         LIST_INITHEAD(&data->output_list);
858         LIST_INITHEAD(&data->pp_list);
859         LIST_INITHEAD(&data->capture_list);
860
861         /* init value */
862         data->bflags = TBM_BO_SCANOUT;
863         data->b_fill = PATTERN_SMPTE;
864
865         data->display = tdm_display_init(&ret);
866         TDM_EXIT_IF_FAIL(data->display != NULL);
867
868         parse_args(data, argc, argv);
869         interpret_args(data);
870         print_args(data);
871
872         if (data->do_query) {
873                 tdm_helper_get_display_information(data->display, temp, &len);
874                 printf("%s", temp);
875                 goto done;
876         }
877
878         run_test(data);
879
880 done:
881         tdm_display_deinit(data->display);
882
883         return 0;
884 }
885
886 static void
887 output_setup(tdm_test_server_output *o)
888 {
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;
893         int i, count;
894         tdm_error ret;
895
896         o->output = tdm_display_get_output(data->display, o->idx, &ret);
897         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
898
899         ret = tdm_output_get_available_modes(o->output, &modes, &count);
900         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
901
902         for (i = 0; i < count; i++) {
903                 if (!strncmp(o->mode, modes[i].name, TDM_NAME_LEN) && o->refresh == modes[i].vrefresh) {
904                         found = &modes[i];
905                         printf("found mode: %dx%d %d\n", found->hdisplay, found->vdisplay, found->vrefresh);
906                         break;
907                 }
908                 if (!best)
909                         best = &modes[i];
910                 if (modes[i].flags & TDM_OUTPUT_MODE_TYPE_PREFERRED)
911                         prefer = &modes[i];
912         }
913         if (!found && prefer) {
914                 found = prefer;
915                 printf("found prefer mode: %dx%d %d\n", found->hdisplay, found->vdisplay, found->vrefresh);
916         }
917         if (!found && best) {
918                 found = best;
919                 printf("found best mode: %dx%d %d\n", found->hdisplay, found->vdisplay, found->vrefresh);
920         }
921
922         if (!found) {
923                 printf("couldn't find any mode\n");
924                 exit(0);
925         }
926
927         ret = tdm_output_set_mode(o->output, found);
928         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
929
930         ret = tdm_output_get_available_properties(o->output, &props, &count);
931         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
932
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))
936                                 continue;
937                         ret = tdm_output_set_property(o->output, props[i].id, w->value);
938                         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
939                         break;
940                 }
941         }
942
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);
946 }
947
948 static tdm_test_server_buffer*
949 layer_get_buffer(tdm_test_server_layer *l)
950 {
951         int i, size = TDM_ARRAY_SIZE(l->bufs);
952         if (!l->bufs[0]) {
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);
962                         l->bufs[i] = b;
963                 }
964         }
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);
968                         return l->bufs[i];
969                 }
970         }
971         printf("no available layer buffer.\n");
972         exit(0);
973 }
974
975 static void
976 layer_cb_commit(tdm_output *output, unsigned int sequence,
977                                 unsigned int tv_sec, unsigned int tv_usec,
978                                 void *user_data)
979 {
980         tdm_test_server_layer *l = user_data;
981         tdm_test_server_buffer *b = layer_get_buffer(l);
982
983         TDM_EXIT_IF_FAIL(b != NULL);
984         layer_show_buffer(l, b);
985 }
986
987 static void
988 layer_cb_buffer_release(tbm_surface_h buffer, void *user_data)
989 {
990         tdm_test_server_buffer *b = user_data;
991         b->in_use = 0;
992         tdm_buffer_remove_release_handler(b->buffer, layer_cb_buffer_release, b);
993         if (b->done)
994                 b->done(buffer, user_data);
995 }
996
997 static void
998 layer_show_buffer(tdm_test_server_layer *l, tdm_test_server_buffer *b)
999 {
1000         tdm_test_server *data = l->o->data;
1001         tdm_error ret;
1002
1003         ret = tdm_layer_set_buffer(l->layer, b->buffer);
1004         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1005
1006         b->in_use = 1;
1007         tdm_buffer_add_release_handler(b->buffer, layer_cb_buffer_release, b);
1008
1009         if (data->do_vblank)
1010                 ret = tdm_output_commit(l->o->output, 0, layer_cb_commit, l);
1011         else
1012                 ret = tdm_output_commit(l->o->output, 0, NULL, NULL);
1013         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1014
1015         printf("show:\tl(%p) b(%p)\n", l, b);
1016 }
1017
1018 static void
1019 layer_setup(tdm_test_server_layer *l, tdm_test_server_buffer *b)
1020 {
1021         tdm_test_server_prop *w = NULL;
1022         const tdm_prop *props;
1023         int i, count;
1024         tdm_error ret;
1025         tbm_surface_info_s info;
1026
1027         l->layer = tdm_output_get_layer(l->o->output, l->idx, &ret);
1028         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1029
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;
1035         } else {
1036                 l->info.src_config.size.h = info.planes[0].stride;
1037                 l->info.src_config.size.v = info.height;
1038         }
1039         l->info.src_config.format = info.format;
1040
1041         ret = tdm_layer_set_info(l->layer, &l->info);
1042         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1043
1044         ret = tdm_layer_get_available_properties(l->layer, &props, &count);
1045         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1046
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))
1050                                 continue;
1051                         ret = tdm_layer_set_property(l->layer, props[i].id, w->value);
1052                         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1053                         break;
1054                 }
1055         }
1056 }
1057
1058 static tdm_test_server_buffer*
1059 pp_get_buffer(tdm_test_server_pp *p)
1060 {
1061         int i, size = TDM_ARRAY_SIZE(p->bufs);
1062         if (!p->bufs[0]) {
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);
1072                         p->bufs[i] = b;
1073                 }
1074         }
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);
1078                         return p->bufs[i];
1079                 }
1080         }
1081         printf("no available pp buffer.\n");
1082         exit(0);
1083 }
1084
1085 static void
1086 pp_cb_sb_release(tbm_surface_h buffer, void *user_data)
1087 {
1088         tdm_test_server_buffer *b = user_data;
1089         b->in_use = 0;
1090         tdm_buffer_remove_release_handler(b->buffer, pp_cb_sb_release, b);
1091 }
1092
1093 static void
1094 pp_cb_db_release(tbm_surface_h buffer, void *user_data)
1095 {
1096         tdm_test_server_buffer *b = user_data;
1097         b->in_use = 0;
1098         tdm_buffer_remove_release_handler(b->buffer, pp_cb_db_release, b);
1099         layer_show_buffer(b->l, b);
1100 }
1101
1102 static void
1103 pp_convert_buffer(tdm_test_server_pp *p, tdm_test_server_buffer *sb, tdm_test_server_buffer *db)
1104 {
1105         tdm_error ret;
1106
1107         ret = tdm_pp_attach(p->pp, sb->buffer, db->buffer);
1108         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1109
1110         sb->in_use = db->in_use = 1;
1111         db->l = p->l;
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);
1114
1115         ret = tdm_pp_commit(p->pp);
1116         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1117
1118         printf("convt:\tp(%p) sb(%p) db(%p)\n", p, sb, db);
1119 }
1120
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.
1127  */
1128 static tdm_error
1129 pp_cb_timeout(void *user_data)
1130 {
1131         tdm_test_server_pp *p = user_data;
1132         tdm_test_server *data = p->l->o->data;
1133         tdm_test_server_buffer *sb, *db;
1134         tdm_error ret;
1135
1136         tdm_display_unlock(data->display);
1137
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);
1142
1143         pp_convert_buffer(p, sb, db);
1144
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);
1149
1150         tdm_display_lock(data->display);
1151
1152         return TDM_ERROR_NONE;
1153 }
1154
1155 static void
1156 pp_setup(tdm_test_server_pp *p, tdm_test_server_buffer *sb, tdm_test_server_buffer *db)
1157 {
1158         tdm_test_server *data = p->l->o->data;
1159         tbm_surface_info_s info;
1160         tdm_error ret;
1161
1162         p->pp = tdm_display_create_pp(data->display, &ret);
1163         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1164
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;
1170         } else {
1171                 p->info.src_config.size.h = info.planes[0].stride;
1172                 p->info.src_config.size.v = info.height;
1173         }
1174         p->info.src_config.format = info.format;
1175
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;
1181         } else {
1182                 p->info.dst_config.size.h = info.planes[0].stride;
1183                 p->info.dst_config.size.v = info.height;
1184         }
1185         p->info.dst_config.format = info.format;
1186
1187         ret = tdm_pp_set_info(p->pp, &p->info);
1188         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1189
1190         layer_setup(p->l, db);
1191
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.
1198          */
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);
1203
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);
1208 }
1209
1210 static void
1211 capture_cb_buffer_done(tbm_surface_h buffer, void *user_data)
1212 {
1213         tdm_test_server_buffer *b = user_data;
1214         capture_attach(b->c, b);
1215 }
1216
1217 static void
1218 capture_cb_buffer_release(tbm_surface_h buffer, void *user_data)
1219 {
1220         tdm_test_server_buffer *b = user_data;
1221         b->in_use = 0;
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);
1225 }
1226
1227 static void
1228 capture_attach(tdm_test_server_capture *c, tdm_test_server_buffer *b)
1229 {
1230         tdm_error ret;
1231
1232         ret = tdm_capture_attach(c->capture, b->buffer);
1233         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1234
1235         b->in_use = 1;
1236         b->l = c->l;
1237         b->c = c;
1238         tdm_buffer_add_release_handler(b->buffer, capture_cb_buffer_release, b);
1239         printf("capture:\tc(%p) b(%p)\n", c, b);
1240
1241         ret = tdm_capture_commit(c->capture);
1242         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1243 }
1244
1245 static void
1246 capture_setup(tdm_test_server_capture *c, tdm_test_server_buffer *b)
1247 {
1248         tdm_test_server *data = c->l->o->data;
1249         tdm_output *output;
1250         tdm_layer *layer;
1251         tbm_surface_info_s info;
1252         tdm_error ret;
1253
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);
1266         }
1267
1268         TDM_EXIT_IF_FAIL(c->capture != NULL);
1269
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;
1275         } else {
1276                 c->info.dst_config.size.h = info.planes[0].stride;
1277                 c->info.dst_config.size.v = info.height;
1278         }
1279         c->info.dst_config.format = info.format;
1280
1281         ret = tdm_capture_set_info(c->capture, &c->info);
1282         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1283
1284         layer_setup(c->l, b);
1285 }
1286
1287 static void
1288 run_test(tdm_test_server *data)
1289 {
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;
1295         tdm_error ret;
1296
1297         ret = tdm_display_get_capabilities(data->display, &caps);
1298         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1299
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);
1305                                 layer_setup(l, b);
1306                                 layer_show_buffer(l, b);
1307                         }
1308                 }
1309         }
1310
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);
1320         }
1321
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);
1332         }
1333
1334         printf("enter test loop\n");
1335
1336         while (1)
1337                 tdm_display_handle_events(data->display);
1338
1339         return;
1340 no_pp:
1341         printf("no PP capability\n");
1342         exit(0);
1343 no_capture:
1344         printf("no Capture capability\n");
1345         exit(0);
1346 }