95d78c0c128bc7d69512546d0b9c147ef6d7503e
[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                 return;
714
715         LIST_FOR_EACH_ENTRY(o, &data->output_list, link) {
716                 printf("output %d: %s", o->idx, o->mode);
717                 if (o->refresh > 0)
718                         printf(" %d\n", o->refresh);
719                 else
720                         printf("\n");
721                 if (!LIST_IS_EMPTY(&o->prop_list)) {
722                         printf("\tprops: ");
723                         LIST_FOR_EACH_ENTRY(w, &o->prop_list, link) {
724                                 print_prop(w);
725                                 printf(" ");
726                         }
727                         printf("\n");
728                 }
729                 LIST_FOR_EACH_ENTRY(l, &o->layer_list, link) {
730                         printf("\t");
731                         printf("layer %d: ", l->idx);
732                         print_config(&l->info.src_config);
733                         printf(" ! ");
734                         print_pos(&l->info.dst_pos);
735                         printf(" trans(%d)\n", l->info.transform);
736                         if (!LIST_IS_EMPTY(&l->prop_list)) {
737                                 printf("\t\tprops: ");
738                                 LIST_FOR_EACH_ENTRY(w, &l->prop_list, link) {
739                                         print_prop(w);
740                                         printf(" ");
741                                 }
742                                 printf("\n");
743                         }
744                 }
745         }
746         LIST_FOR_EACH_ENTRY(p, &data->pp_list, link) {
747                 printf("pp: ");
748                 print_config(&p->info.src_config);
749                 printf(" ! ");
750                 print_config(&p->info.dst_config);
751                 printf(" fps(%d) trans(%d)\n", p->fps, p->info.transform);
752                 if (p->l)
753                         printf("\toutput_idx(%d) layer_idx(%d)\n", p->l->o->idx, p->l->idx);
754         }
755         LIST_FOR_EACH_ENTRY(c, &data->capture_list, link) {
756                 printf("capture: o(%d) l(%d) ", c->output_idx, c->layer_idx);
757                 print_config(&c->info.dst_config);
758                 printf(" trans(%d)\n", c->info.transform);
759                 if (c->l)
760                         printf("\toutput_idx(%d) layer_idx(%d)\n", c->l->o->idx, c->l->idx);
761         }
762         if (data->bflags != 0) {
763                 printf("buffer: ");
764                 char temp[256];
765                 char *p = temp;
766                 int len = sizeof temp;
767                 tdm_buf_flag_str(data->bflags, &p, &len);
768                 printf(" (%s)\n", temp);
769         }
770 }
771
772 static tdm_test_server tts_data;
773
774 static void
775 exit_test(int sig)
776 {
777         tdm_test_server *data = &tts_data;
778         tdm_test_server_output *o = NULL, *oo = NULL;
779         tdm_test_server_layer *l = NULL, *ll = NULL;
780         tdm_test_server_pp *p = NULL, *pp = NULL;
781         tdm_test_server_capture *c = NULL, *cc = NULL;
782         tdm_test_server_prop *w = NULL, *ww = NULL;
783         int i;
784
785         printf("got signal: %d\n", sig);
786
787         LIST_FOR_EACH_ENTRY_SAFE(o, oo, &data->output_list, link) {
788                 LIST_DEL(&o->link);
789
790                 LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) {
791                         LIST_DEL(&l->link);
792
793                         tdm_layer_unset_buffer(l->layer);
794
795                         LIST_FOR_EACH_ENTRY_SAFE(w, ww, &l->prop_list, link) {
796                                 LIST_DEL(&w->link);
797                                 free(w);
798                         }
799                         for (i = 0; i < TDM_ARRAY_SIZE(l->bufs); i++) {
800                                 tbm_surface_destroy(l->bufs[i]->buffer);
801                                 free(l->bufs[i]);
802                         }
803                         free(l);
804                 }
805
806                 tdm_output_commit(o->output, 0, NULL, NULL);
807
808                 LIST_FOR_EACH_ENTRY_SAFE(w, ww, &o->prop_list, link) {
809                         LIST_DEL(&w->link);
810                         free(w);
811                 }
812
813                 free(o);
814         }
815
816
817         LIST_FOR_EACH_ENTRY_SAFE(p, pp, &data->pp_list, link) {
818                 LIST_DEL(&p->link);
819
820                 tdm_display_lock(data->display);
821                 tdm_event_loop_source_remove(p->timer_source);
822                 tdm_display_unlock(data->display);
823
824                 tdm_pp_destroy(p->pp);
825                 for (i = 0; i < TDM_ARRAY_SIZE(p->bufs); i++) {
826                         tbm_surface_destroy(p->bufs[i]->buffer);
827                         free(p->bufs[i]);
828                 }
829                 free(p);
830         }
831
832         LIST_FOR_EACH_ENTRY_SAFE(c, cc, &data->capture_list, link) {
833                 LIST_DEL(&c->link);
834                 tdm_capture_destroy(c->capture);
835                 free(c);
836         }
837
838         if (data->display)
839                 tdm_display_deinit(data->display);
840
841         exit(0);
842 }
843
844 int
845 main(int argc, char *argv[])
846 {
847         tdm_test_server *data = &tts_data;
848         char temp[TDM_SERVER_REPLY_MSG_LEN];
849         int len = sizeof temp;
850         tdm_error ret;
851
852         signal(SIGINT, exit_test);    /* 2 */
853         signal(SIGTERM, exit_test);   /* 15 */
854
855         memset(data, 0, sizeof * data);
856         LIST_INITHEAD(&data->output_list);
857         LIST_INITHEAD(&data->pp_list);
858         LIST_INITHEAD(&data->capture_list);
859
860         /* init value */
861         data->bflags = TBM_BO_SCANOUT;
862         data->b_fill = PATTERN_SMPTE;
863
864         data->display = tdm_display_init(&ret);
865         TDM_EXIT_IF_FAIL(data->display != NULL);
866
867         parse_args(data, argc, argv);
868         interpret_args(data);
869         print_args(data);
870
871         if (data->do_query) {
872                 tdm_helper_get_display_information(data->display, temp, &len);
873                 printf("%s", temp);
874                 goto done;
875         }
876
877         run_test(data);
878
879 done:
880         tdm_display_deinit(data->display);
881
882         return 0;
883 }
884
885 static void
886 output_setup(tdm_test_server_output *o)
887 {
888         tdm_test_server *data = o->data;
889         const tdm_output_mode *modes, *found = NULL, *best = NULL, *prefer = NULL;
890         tdm_test_server_prop *w = NULL;
891         const tdm_prop *props;
892         int i, count;
893         tdm_error ret;
894
895         o->output = tdm_display_get_output(data->display, o->idx, &ret);
896         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
897
898         ret = tdm_output_get_available_modes(o->output, &modes, &count);
899         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
900
901         for (i = 0; i < count; i++) {
902                 if (!strncmp(o->mode, modes[i].name, TDM_NAME_LEN) && o->refresh == modes[i].vrefresh) {
903                         found = &modes[i];
904                         printf("found mode: %dx%d %d\n", found->hdisplay, found->vdisplay, found->vrefresh);
905                         break;
906                 }
907                 if (!best)
908                         best = &modes[i];
909                 if (modes[i].flags & TDM_OUTPUT_MODE_TYPE_PREFERRED)
910                         prefer = &modes[i];
911         }
912         if (!found && prefer) {
913                 found = prefer;
914                 printf("found prefer mode: %dx%d %d\n", found->hdisplay, found->vdisplay, found->vrefresh);
915         }
916         if (!found && best) {
917                 found = best;
918                 printf("found best mode: %dx%d %d\n", found->hdisplay, found->vdisplay, found->vrefresh);
919         }
920
921         if (!found) {
922                 printf("couldn't find any mode\n");
923                 exit(0);
924         }
925
926         ret = tdm_output_set_mode(o->output, found);
927         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
928
929         ret = tdm_output_get_available_properties(o->output, &props, &count);
930         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
931
932         LIST_FOR_EACH_ENTRY(w, &o->prop_list, link) {
933                 for (i = 0; i < count; i++) {
934                         if (strncmp(w->name, props[i].name, TDM_NAME_LEN))
935                                 continue;
936                         ret = tdm_output_set_property(o->output, props[i].id, w->value);
937                         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
938                         break;
939                 }
940         }
941
942         /* DPMS on forcely at the first time. */
943         ret = tdm_output_set_dpms(o->output, TDM_OUTPUT_DPMS_ON);
944         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
945 }
946
947 static tdm_test_server_buffer*
948 layer_get_buffer(tdm_test_server_layer *l)
949 {
950         int i, size = TDM_ARRAY_SIZE(l->bufs);
951         if (!l->bufs[0]) {
952                 for (i = 0; i < size; i++) {
953                         int width = (l->info.src_config.size.h)?:l->info.src_config.pos.w;
954                         int height = (l->info.src_config.size.v)?:l->info.src_config.pos.h;
955                         unsigned int format = (l->info.src_config.format)?:TBM_FORMAT_ARGB8888;
956                         int flags = l->o->data->bflags;
957                         tdm_test_server_buffer *b = calloc(1, sizeof *b);
958                         TDM_EXIT_IF_FAIL(b != NULL);
959                         b->buffer = tbm_surface_internal_create_with_flags(width, height, format, flags);
960                         TDM_EXIT_IF_FAIL(b->buffer != NULL);
961                         l->bufs[i] = b;
962                 }
963         }
964         for (i = 0; i < size; i++) {
965                 if (!l->bufs[i]->in_use) {
966                         tdm_test_buffer_fill(l->bufs[i]->buffer, l->data->b_fill);
967                         return l->bufs[i];
968                 }
969         }
970         printf("no available layer buffer.\n");
971         exit(0);
972 }
973
974 static void
975 layer_cb_commit(tdm_output *output, unsigned int sequence,
976                                 unsigned int tv_sec, unsigned int tv_usec,
977                                 void *user_data)
978 {
979         tdm_test_server_layer *l = user_data;
980         tdm_test_server_buffer *b = layer_get_buffer(l);
981
982         TDM_EXIT_IF_FAIL(b != NULL);
983         layer_show_buffer(l, b);
984 }
985
986 static void
987 layer_cb_buffer_release(tbm_surface_h buffer, void *user_data)
988 {
989         tdm_test_server_buffer *b = user_data;
990         b->in_use = 0;
991         tdm_buffer_remove_release_handler(b->buffer, layer_cb_buffer_release, b);
992         if (b->done)
993                 b->done(buffer, user_data);
994 }
995
996 static void
997 layer_show_buffer(tdm_test_server_layer *l, tdm_test_server_buffer *b)
998 {
999         tdm_test_server *data = l->o->data;
1000         tdm_error ret;
1001
1002         ret = tdm_layer_set_buffer(l->layer, b->buffer);
1003         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1004
1005         b->in_use = 1;
1006         tdm_buffer_add_release_handler(b->buffer, layer_cb_buffer_release, b);
1007
1008         if (data->do_vblank)
1009                 ret = tdm_output_commit(l->o->output, 0, layer_cb_commit, l);
1010         else
1011                 ret = tdm_output_commit(l->o->output, 0, NULL, NULL);
1012         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1013
1014         printf("show:\tl(%p) b(%p)\n", l, b);
1015 }
1016
1017 static void
1018 layer_setup(tdm_test_server_layer *l, tdm_test_server_buffer *b)
1019 {
1020         tdm_test_server_prop *w = NULL;
1021         const tdm_prop *props;
1022         int i, count;
1023         tdm_error ret;
1024         tbm_surface_info_s info;
1025
1026         l->layer = tdm_output_get_layer(l->o->output, l->idx, &ret);
1027         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1028
1029         /* The size and format information should be same with buffer's */
1030         tbm_surface_get_info(b->buffer, &info);
1031         if (IS_RGB(info.format)) {
1032                 l->info.src_config.size.h = info.planes[0].stride >> 2;
1033                 l->info.src_config.size.v = info.height;
1034         } else {
1035                 l->info.src_config.size.h = info.planes[0].stride;
1036                 l->info.src_config.size.v = info.height;
1037         }
1038         l->info.src_config.format = info.format;
1039
1040         ret = tdm_layer_set_info(l->layer, &l->info);
1041         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1042
1043         ret = tdm_layer_get_available_properties(l->layer, &props, &count);
1044         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1045
1046         LIST_FOR_EACH_ENTRY(w, &l->prop_list, link) {
1047                 for (i = 0; i < count; i++) {
1048                         if (strncmp(w->name, props[i].name, TDM_NAME_LEN))
1049                                 continue;
1050                         ret = tdm_layer_set_property(l->layer, props[i].id, w->value);
1051                         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1052                         break;
1053                 }
1054         }
1055 }
1056
1057 static tdm_test_server_buffer*
1058 pp_get_buffer(tdm_test_server_pp *p)
1059 {
1060         int i, size = TDM_ARRAY_SIZE(p->bufs);
1061         if (!p->bufs[0]) {
1062                 for (i = 0; i < size; i++) {
1063                         int width = (p->info.src_config.size.h)?:p->info.src_config.pos.w;
1064                         int height = (p->info.src_config.size.v)?:p->info.src_config.pos.h;
1065                         unsigned int format = (p->info.src_config.format)?:TBM_FORMAT_ARGB8888;
1066                         int flags = p->l->o->data->bflags;
1067                         tdm_test_server_buffer *b = calloc(1, sizeof *b);
1068                         TDM_EXIT_IF_FAIL(b != NULL);
1069                         b->buffer = tbm_surface_internal_create_with_flags(width, height, format, flags);
1070                         TDM_EXIT_IF_FAIL(b->buffer != NULL);
1071                         p->bufs[i] = b;
1072                 }
1073         }
1074         for (i = 0; i < size; i++) {
1075                 if (!p->bufs[i]->in_use) {
1076                         tdm_test_buffer_fill(p->bufs[i]->buffer, p->data->b_fill);
1077                         return p->bufs[i];
1078                 }
1079         }
1080         printf("no available pp buffer.\n");
1081         exit(0);
1082 }
1083
1084 static void
1085 pp_cb_sb_release(tbm_surface_h buffer, void *user_data)
1086 {
1087         tdm_test_server_buffer *b = user_data;
1088         b->in_use = 0;
1089         tdm_buffer_remove_release_handler(b->buffer, pp_cb_sb_release, b);
1090 }
1091
1092 static void
1093 pp_cb_db_release(tbm_surface_h buffer, void *user_data)
1094 {
1095         tdm_test_server_buffer *b = user_data;
1096         b->in_use = 0;
1097         tdm_buffer_remove_release_handler(b->buffer, pp_cb_db_release, b);
1098         layer_show_buffer(b->l, b);
1099 }
1100
1101 static void
1102 pp_convert_buffer(tdm_test_server_pp *p, tdm_test_server_buffer *sb, tdm_test_server_buffer *db)
1103 {
1104         tdm_error ret;
1105
1106         ret = tdm_pp_attach(p->pp, sb->buffer, db->buffer);
1107         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1108
1109         sb->in_use = db->in_use = 1;
1110         db->l = p->l;
1111         tdm_buffer_add_release_handler(sb->buffer, pp_cb_sb_release, sb);
1112         tdm_buffer_add_release_handler(db->buffer, pp_cb_db_release, db);
1113
1114         ret = tdm_pp_commit(p->pp);
1115         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1116
1117         printf("convt:\tp(%p) sb(%p) db(%p)\n", p, sb, db);
1118 }
1119
1120 /* tdm_event_loop_xxx() function is not for the display server. It's for TDM
1121  * backend module. I use them only for simulating the video play. When we call
1122  * tdm_event_loop_xxx() outside of TDM backend module, we have to lock/unlock
1123  * the TDM display. And when the callback function of tdm_event_loop_xxx() is
1124  * called, the display has been already locked. So in this test application,
1125  * we have to unlock/lock the display for testing.
1126  */
1127 static tdm_error
1128 pp_cb_timeout(void *user_data)
1129 {
1130         tdm_test_server_pp *p = user_data;
1131         tdm_test_server *data = p->l->o->data;
1132         tdm_test_server_buffer *sb, *db;
1133         tdm_error ret;
1134
1135         tdm_display_unlock(data->display);
1136
1137         sb = pp_get_buffer(p);
1138         TDM_EXIT_IF_FAIL(sb != NULL);
1139         db = layer_get_buffer(p->l);
1140         TDM_EXIT_IF_FAIL(db != NULL);
1141
1142         pp_convert_buffer(p, sb, db);
1143
1144         tdm_display_lock(data->display);
1145         ret = tdm_event_loop_source_timer_update(p->timer_source, 1000 / p->fps);
1146         tdm_display_unlock(data->display);
1147         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1148
1149         tdm_display_lock(data->display);
1150
1151         return TDM_ERROR_NONE;
1152 }
1153
1154 static void
1155 pp_setup(tdm_test_server_pp *p, tdm_test_server_buffer *sb, tdm_test_server_buffer *db)
1156 {
1157         tdm_test_server *data = p->l->o->data;
1158         tbm_surface_info_s info;
1159         tdm_error ret;
1160
1161         p->pp = tdm_display_create_pp(data->display, &ret);
1162         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1163
1164         /* The size and format information should be same with buffer's */
1165         tbm_surface_get_info(sb->buffer, &info);
1166         if (IS_RGB(info.format)) {
1167                 p->info.src_config.size.h = info.planes[0].stride >> 2;
1168                 p->info.src_config.size.v = info.height;
1169         } else {
1170                 p->info.src_config.size.h = info.planes[0].stride;
1171                 p->info.src_config.size.v = info.height;
1172         }
1173         p->info.src_config.format = info.format;
1174
1175         /* The size and format information should be same with buffer's */
1176         tbm_surface_get_info(db->buffer, &info);
1177         if (IS_RGB(info.format)) {
1178                 p->info.dst_config.size.h = info.planes[0].stride >> 2;
1179                 p->info.dst_config.size.v = info.height;
1180         } else {
1181                 p->info.dst_config.size.h = info.planes[0].stride;
1182                 p->info.dst_config.size.v = info.height;
1183         }
1184         p->info.dst_config.format = info.format;
1185
1186         ret = tdm_pp_set_info(p->pp, &p->info);
1187         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1188
1189         layer_setup(p->l, db);
1190
1191         /* tdm_event_loop_xxx() function is not for the display server. It's for TDM
1192          * backend module. I use them only for simulating the video play. When we call
1193          * tdm_event_loop_xxx() outside of TDM backend module, we have to lock/unlock
1194          * the TDM display. And when the callback function of tdm_event_loop_xxx() is
1195          * called, the display has been already locked. So in this test application,
1196          * we have to unlock/lock the display for testing.
1197          */
1198         tdm_display_lock(data->display);
1199         p->timer_source = tdm_event_loop_add_timer_handler(data->display, pp_cb_timeout, p, &ret);
1200         tdm_display_unlock(data->display);
1201         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1202
1203         tdm_display_lock(data->display);
1204         ret = tdm_event_loop_source_timer_update(p->timer_source, 1000 / p->fps);
1205         tdm_display_unlock(data->display);
1206         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1207 }
1208
1209 static void
1210 capture_cb_buffer_done(tbm_surface_h buffer, void *user_data)
1211 {
1212         tdm_test_server_buffer *b = user_data;
1213         capture_attach(b->c, b);
1214 }
1215
1216 static void
1217 capture_cb_buffer_release(tbm_surface_h buffer, void *user_data)
1218 {
1219         tdm_test_server_buffer *b = user_data;
1220         b->in_use = 0;
1221         tdm_buffer_remove_release_handler(b->buffer, capture_cb_buffer_release, b);
1222         b->done = capture_cb_buffer_done;
1223         layer_show_buffer(b->l, b);
1224 }
1225
1226 static void
1227 capture_attach(tdm_test_server_capture *c, tdm_test_server_buffer *b)
1228 {
1229         tdm_error ret;
1230
1231         ret = tdm_capture_attach(c->capture, b->buffer);
1232         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1233
1234         b->in_use = 1;
1235         b->l = c->l;
1236         b->c = c;
1237         tdm_buffer_add_release_handler(b->buffer, capture_cb_buffer_release, b);
1238         printf("capture:\tc(%p) b(%p)\n", c, b);
1239
1240         ret = tdm_capture_commit(c->capture);
1241         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1242 }
1243
1244 static void
1245 capture_setup(tdm_test_server_capture *c, tdm_test_server_buffer *b)
1246 {
1247         tdm_test_server *data = c->l->o->data;
1248         tdm_output *output;
1249         tdm_layer *layer;
1250         tbm_surface_info_s info;
1251         tdm_error ret;
1252
1253         if (c->output_idx != -1 && c->layer_idx == -1) {
1254                 output = tdm_display_get_output(data->display, c->output_idx, &ret);
1255                 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1256                 c->capture = tdm_output_create_capture(output, &ret);
1257                 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1258         } else if (c->output_idx != -1 && c->layer_idx != -1) {
1259                 output = tdm_display_get_output(data->display, c->output_idx, &ret);
1260                 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1261                 layer = tdm_output_get_layer(output, c->layer_idx, &ret);
1262                 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1263                 c->capture = tdm_layer_create_capture(layer, &ret);
1264                 TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1265         }
1266
1267         TDM_EXIT_IF_FAIL(c->capture != NULL);
1268
1269         /* The size and format information should be same with buffer's */
1270         tbm_surface_get_info(b->buffer, &info);
1271         if (IS_RGB(info.format)) {
1272                 c->info.dst_config.size.h = info.planes[0].stride >> 2;
1273                 c->info.dst_config.size.v = info.height;
1274         } else {
1275                 c->info.dst_config.size.h = info.planes[0].stride;
1276                 c->info.dst_config.size.v = info.height;
1277         }
1278         c->info.dst_config.format = info.format;
1279
1280         ret = tdm_capture_set_info(c->capture, &c->info);
1281         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1282
1283         layer_setup(c->l, b);
1284 }
1285
1286 static void
1287 run_test(tdm_test_server *data)
1288 {
1289         tdm_test_server_output *o = NULL;
1290         tdm_test_server_layer *l = NULL;
1291         tdm_test_server_pp *p = NULL;
1292         tdm_test_server_capture *c = NULL;
1293         tdm_display_capability caps;
1294         tdm_error ret;
1295
1296         ret = tdm_display_get_capabilities(data->display, &caps);
1297         TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE);
1298
1299         LIST_FOR_EACH_ENTRY(o, &data->output_list, link) {
1300                 LIST_FOR_EACH_ENTRY(l, &o->layer_list, link) {
1301                         if (!l->owner_p && !l->owner_c) {
1302                                 tdm_test_server_buffer *b;
1303                                 b = layer_get_buffer(l);
1304                                 layer_setup(l, b);
1305                                 layer_show_buffer(l, b);
1306                         }
1307                 }
1308         }
1309
1310         LIST_FOR_EACH_ENTRY(p, &data->pp_list, link) {
1311                 tdm_test_server_buffer *sb, *db;
1312                 TDM_GOTO_IF_FAIL(caps & TDM_DISPLAY_CAPABILITY_PP, no_pp);
1313                 sb = pp_get_buffer(p);
1314                 TDM_EXIT_IF_FAIL(sb != NULL);
1315                 db = layer_get_buffer(p->l);
1316                 TDM_EXIT_IF_FAIL(db != NULL);
1317                 pp_setup(p, sb, db);
1318                 pp_convert_buffer(p, sb, db);
1319         }
1320
1321         LIST_FOR_EACH_ENTRY(c, &data->capture_list, link) {
1322                 TDM_GOTO_IF_FAIL(caps & TDM_DISPLAY_CAPABILITY_CAPTURE, no_capture);
1323                 tdm_test_server_buffer *b;
1324                 b = layer_get_buffer(c->l);
1325                 capture_setup(c, b);
1326                 capture_attach(c, b);
1327                 b = layer_get_buffer(c->l);
1328                 capture_attach(c, b);
1329                 b = layer_get_buffer(c->l);
1330                 capture_attach(c, b);
1331         }
1332
1333         printf("enter test loop\n");
1334
1335         while (1)
1336                 tdm_display_handle_events(data->display);
1337
1338         return;
1339 no_pp:
1340         printf("no PP capability\n");
1341         exit(0);
1342 no_capture:
1343         printf("no Capture capability\n");
1344         exit(0);
1345 }