virtual: add set_available_mode & set_phsycal_size function
[platform/core/uifw/libtdm.git] / backends / virtual / tdm_virtual_display.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include "tdm_virtual.h"
6
7 typedef struct _tdm_virtual_output_data tdm_virtual_output_data;
8 typedef struct _tdm_virtual_layer_data tdm_virtual_layer_data;
9 typedef struct _tdm_virtual_event_data tdm_virtual_event_data;
10
11 typedef enum {
12         TDM_VIRTUAL_EVENT_TYPE_WAIT,
13         TDM_VIRTUAL_EVENT_TYPE_COMMIT,
14 } tdm_virtual_event_type;
15
16 struct _tdm_virtual_event_data {
17         struct list_head link;
18
19         tdm_virtual_event_type type;
20         tdm_virtual_output_data *output_data;
21         void *user_data;
22 };
23
24 struct _tdm_virtual_output_data {
25         struct list_head link;
26
27         /* data which are fixed at initializing */
28         tdm_virtual_data *virtual_data;
29
30         uint32_t pipe;
31         tdm_output_mode *output_modes;
32         int mode_count;
33         tdm_output_type connector_type;
34         struct list_head layer_list;
35         tdm_virtual_layer_data *primary_layer;
36
37         /* not fixed data below */
38         tdm_output_vblank_handler vblank_func;
39         tdm_output_commit_handler commit_func;
40
41         tdm_output_conn_status status;
42
43         int mode_changed;
44         const tdm_output_mode *current_mode;
45
46         tdm_event_loop_source *timer;
47         unsigned int timer_waiting;
48         struct list_head timer_event_list;
49
50         unsigned int mmwidth;
51         unsigned int mmheight;
52
53         char name[TDM_NAME_LEN];        /**< The output name */
54 };
55
56 struct _tdm_virtual_layer_data {
57         struct list_head link;
58
59         /* data which are fixed at initializing */
60         tdm_virtual_data *virtual_data;
61         tdm_virtual_output_data *output_data;
62         tdm_layer_capability capabilities;
63         int zpos;
64
65         /* not fixed data below */
66         tdm_info_layer info;
67         int info_changed;
68
69         tbm_surface_h display_buffer;
70         int display_buffer_changed;
71 };
72
73 static void
74 _tdm_virtual_display_cb_event(tdm_virtual_output_data *output_data, tdm_virtual_event_data *event_data,
75                                                         unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec)
76 {
77         switch (event_data->type) {
78         case TDM_VIRTUAL_EVENT_TYPE_WAIT:
79                 if (output_data->vblank_func)
80                         output_data->vblank_func(output_data, sequence, tv_sec, tv_usec, event_data->user_data);
81                 break;
82         case TDM_VIRTUAL_EVENT_TYPE_COMMIT:
83                 if (output_data->commit_func)
84                         output_data->commit_func(output_data, sequence, tv_sec, tv_usec, event_data->user_data);
85                 break;
86         default:
87                 break;
88         }
89 }
90
91 static tdm_error
92 _tdm_virtual_display_cb_timeout(void *user_data)
93 {
94         tdm_virtual_output_data *output_data = user_data;
95         tdm_virtual_event_data *e = NULL, *ee = NULL;
96         unsigned int tv_sec, tv_usec;
97         static unsigned int sequence = 0;
98         struct timespec tp;
99
100         sequence++;
101
102         if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) {
103                 tv_sec = tp.tv_sec;
104                 tv_usec = tp.tv_nsec / 1000;
105         } else {
106                 tv_sec = tv_usec = 0;
107         }
108
109         LIST_FOR_EACH_ENTRY_SAFE(e, ee, &output_data->timer_event_list, link) {
110                 LIST_DEL(&e->link);
111                 _tdm_virtual_display_cb_event(output_data, e, sequence, tv_sec, tv_usec);
112                 free(e);
113         }
114
115         return TDM_ERROR_NONE;
116 }
117
118 static tdm_error
119 _tdm_virtual_display_wait_vblank(tdm_virtual_output_data *output_data, int interval, tdm_virtual_event_data *event_data)
120 {
121         tdm_error ret;
122         unsigned int ms;
123
124         RETURN_VAL_IF_FAIL(output_data->timer != NULL, TDM_ERROR_OPERATION_FAILED);
125         RETURN_VAL_IF_FAIL(output_data->current_mode->vrefresh > 0, TDM_ERROR_OPERATION_FAILED);
126
127         if (output_data->timer_waiting) {
128                 LIST_ADDTAIL(&event_data->link, &output_data->timer_event_list);
129                 return TDM_ERROR_NONE;
130         }
131
132         ms = ((double)1000.0 / output_data->current_mode->vrefresh) * interval;
133
134         ret = tdm_event_loop_source_timer_update(output_data->timer, ms);
135         if (ret != TDM_ERROR_NONE)
136                 return ret;
137
138         LIST_ADDTAIL(&event_data->link, &output_data->timer_event_list);
139
140         return TDM_ERROR_NONE;
141 }
142
143 static void
144 _tdm_virtual_display_destroy_layer_list(tdm_virtual_data *virtual_data)
145 {
146         tdm_virtual_output_data *o = NULL;
147
148         LIST_FOR_EACH_ENTRY(o, &virtual_data->output_list, link) {
149                 tdm_virtual_layer_data *l = NULL, *ll = NULL;
150                 LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) {
151                         LIST_DEL(&l->link);
152                         free(l);
153                 }
154         }
155 }
156
157 tdm_error
158 tdm_virtual_display_create_layer_list(tdm_virtual_data *virtual_data)
159 {
160         tdm_virtual_output_data *output_data = NULL;
161         tdm_error ret = TDM_ERROR_NONE;
162
163         if (LIST_IS_EMPTY(&virtual_data->output_list)) {
164                 TDM_ERR("no output");
165                 return TDM_ERROR_OPERATION_FAILED;
166         }
167
168         /* The TDM virtual backend only support one output. */
169         LIST_FOR_EACH_ENTRY(output_data, &virtual_data->output_list, link) {
170                 tdm_virtual_layer_data *layer_data = calloc(1, sizeof(tdm_virtual_layer_data));
171                 if (!layer_data) {
172                         TDM_ERR("alloc failed");
173                         ret = TDM_ERROR_OUT_OF_MEMORY;
174                         goto failed;
175                 }
176
177                 layer_data->virtual_data = virtual_data;
178                 layer_data->output_data = output_data;
179                 layer_data->zpos = 0;
180
181                 layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY | TDM_LAYER_CAPABILITY_GRAPHIC;
182                 output_data->primary_layer = layer_data;
183
184                 LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
185         }
186
187         return TDM_ERROR_NONE;
188 failed:
189         _tdm_virtual_display_destroy_layer_list(virtual_data);
190         return ret;
191 }
192
193 void
194 tdm_virtual_display_destroy_output_list(tdm_virtual_data *virtual_data)
195 {
196         tdm_virtual_output_data *o = NULL, *oo = NULL;
197
198         if (LIST_IS_EMPTY(&virtual_data->output_list))
199                 return;
200
201         _tdm_virtual_display_destroy_layer_list(virtual_data);
202
203         LIST_FOR_EACH_ENTRY_SAFE(o, oo, &virtual_data->output_list, link) {
204                 LIST_DEL(&o->link);
205
206                 if (!LIST_IS_EMPTY(&o->timer_event_list)) {
207                         tdm_virtual_event_data *e = NULL, *ee = NULL;
208                         LIST_FOR_EACH_ENTRY_SAFE(e, ee, &o->timer_event_list, link) {
209                                 LIST_DEL(&e->link);
210                                 free(e);
211                         }
212                 }
213
214                 if (o->timer)
215                         tdm_event_loop_source_remove(o->timer);
216
217                 free(o->output_modes);
218                 free(o);
219         }
220 }
221
222 tdm_error
223 tdm_virtual_display_create_output_list(tdm_virtual_data *virtual_data)
224 {
225         tdm_virtual_output_data *output_data;
226         tdm_error ret;
227
228         RETURN_VAL_IF_FAIL(LIST_IS_EMPTY(&virtual_data->output_list), TDM_ERROR_OPERATION_FAILED);
229
230         output_data = calloc(1, sizeof(tdm_virtual_output_data));
231         if (!output_data) {
232                 TDM_ERR("alloc failed");
233                 ret = TDM_ERROR_OUT_OF_MEMORY;
234                 goto failed_create;
235         }
236
237         LIST_INITHEAD(&output_data->layer_list);
238
239         output_data->virtual_data = virtual_data;
240         output_data->pipe = 0;
241         output_data->connector_type = TDM_OUTPUT_TYPE_Unknown;
242         output_data->status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
243
244         output_data->output_modes = calloc(1, sizeof(tdm_output_mode));
245         if (!output_data->output_modes) {
246                 TDM_ERR("alloc failed");
247                 free(output_data);
248                 ret = TDM_ERROR_OUT_OF_MEMORY;
249                 goto failed_create;
250         }
251
252         snprintf(output_data->output_modes->name, TDM_NAME_LEN, "640x480");
253         output_data->output_modes->vrefresh = 30;
254         output_data->output_modes->clock = 25200;
255         output_data->output_modes->hdisplay = 640;
256         output_data->output_modes->hsync_start = 656;
257         output_data->output_modes->hsync_end = 752;
258         output_data->output_modes->htotal = 800;
259         output_data->output_modes->hskew = 0;
260         output_data->output_modes->vdisplay = 480;
261         output_data->output_modes->vsync_start = 490;
262         output_data->output_modes->vsync_end = 492;
263         output_data->output_modes->vtotal = 525;
264         output_data->output_modes->vscan = 0;
265         output_data->output_modes->flags = 0;
266         output_data->output_modes->type = 0;
267
268         output_data->timer = tdm_event_loop_add_timer_handler(virtual_data->dpy,
269                                                                                                                   _tdm_virtual_display_cb_timeout,
270                                                                                                                   output_data,
271                                                                                                                   &ret);
272         if (!output_data->timer) {
273                 free(output_data);
274                 return ret;
275         }
276
277         LIST_INITHEAD(&output_data->timer_event_list);
278
279         LIST_ADDTAIL(&output_data->link, &virtual_data->output_list);
280
281         return TDM_ERROR_NONE;
282 failed_create:
283         tdm_virtual_display_destroy_output_list(virtual_data);
284         return ret;
285 }
286
287 tdm_error
288 virtual_display_get_capability(tdm_backend_data *bdata, tdm_caps_display *caps)
289 {
290         RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
291
292         caps->max_layer_count = -1; /* not defined */
293
294         return TDM_ERROR_NONE;
295 }
296
297 tdm_output **
298 virtual_display_get_outputs(tdm_backend_data *bdata, int *count, tdm_error *error)
299 {
300         tdm_virtual_data *virtual_data = bdata;
301         tdm_virtual_output_data *output_data = NULL;
302         tdm_output **outputs;
303         tdm_error ret;
304         int i;
305
306         RETURN_VAL_IF_FAIL(virtual_data, NULL);
307         RETURN_VAL_IF_FAIL(count, NULL);
308
309         *count = 0;
310         LIST_FOR_EACH_ENTRY(output_data, &virtual_data->output_list, link)
311         (*count)++;
312
313         if (*count == 0) {
314                 ret = TDM_ERROR_NONE;
315                 goto failed_get;
316         }
317
318         /* will be freed in frontend */
319         outputs = calloc(*count, sizeof(tdm_virtual_output_data *));
320         if (!outputs) {
321                 TDM_ERR("failed: alloc memory");
322                 *count = 0;
323                 ret = TDM_ERROR_OUT_OF_MEMORY;
324                 goto failed_get;
325         }
326
327         i = 0;
328         LIST_FOR_EACH_ENTRY(output_data, &virtual_data->output_list, link)
329         outputs[i++] = output_data;
330
331         if (error)
332                 *error = TDM_ERROR_NONE;
333
334         return outputs;
335 failed_get:
336         if (error)
337                 *error = ret;
338         return NULL;
339 }
340
341 tdm_error
342 virtual_display_get_fd(tdm_backend_data *bdata, int *fd)
343 {
344         tdm_virtual_data *virtual_data = bdata;
345
346         RETURN_VAL_IF_FAIL(virtual_data, TDM_ERROR_INVALID_PARAMETER);
347         RETURN_VAL_IF_FAIL(fd, TDM_ERROR_INVALID_PARAMETER);
348
349         *fd = virtual_data->pipe[0];
350
351         return TDM_ERROR_NONE;
352 }
353
354 tdm_error
355 virtual_display_handle_events(tdm_backend_data *bdata)
356 {
357         return TDM_ERROR_NONE;
358 }
359
360 tdm_output *
361 virtual_display_output_create(tdm_backend_data *bdata, const char *name, tdm_error *error)
362 {
363         tdm_virtual_data *virtual_data = bdata;
364         tdm_virtual_output_data *output_data = NULL;
365         tdm_virtual_layer_data *layer_data = NULL;
366         tdm_error ret;
367
368         if (!virtual_data || !name) {
369                 TDM_ERR("invalid parameter");
370                 *error = TDM_ERROR_INVALID_PARAMETER;
371                 return NULL;
372         }
373
374         output_data = calloc(1, sizeof(tdm_virtual_output_data));
375         if (!output_data) {
376                 TDM_ERR("alloc failed");
377                 *error = TDM_ERROR_OUT_OF_MEMORY;
378                 return NULL;
379         }
380
381         LIST_INITHEAD(&output_data->layer_list);
382
383         output_data->virtual_data = virtual_data;
384         output_data->pipe = 0;
385         output_data->connector_type = TDM_OUTPUT_TYPE_Unknown;
386         output_data->status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
387
388         if (name)
389                 snprintf(output_data->name, TDM_NAME_LEN, "%s", name);
390         else
391                 snprintf(output_data->name, TDM_NAME_LEN, "unknown");
392 #if 0
393         output_data->output_modes = calloc(1, sizeof(tdm_output_mode));
394         if (!output_data->output_modes) {
395                 TDM_ERR("alloc failed");
396                 ret = TDM_ERROR_OUT_OF_MEMORY;
397                 goto create_fail;
398         }
399
400         snprintf(output_data->output_modes->name, TDM_NAME_LEN, "640x480");
401         output_data->output_modes->vrefresh = 30;
402         output_data->output_modes->clock = 25200;
403         output_data->output_modes->hdisplay = 640;
404         output_data->output_modes->hsync_start = 656;
405         output_data->output_modes->hsync_end = 752;
406         output_data->output_modes->htotal = 800;
407         output_data->output_modes->hskew = 0;
408         output_data->output_modes->vdisplay = 480;
409         output_data->output_modes->vsync_start = 490;
410         output_data->output_modes->vsync_end = 492;
411         output_data->output_modes->vtotal = 525;
412         output_data->output_modes->vscan = 0;
413         output_data->output_modes->flags = 0;
414         output_data->output_modes->type = 0;
415
416         output_data->mode_count = 1;
417 #endif
418         output_data->timer = tdm_event_loop_add_timer_handler(virtual_data->dpy,
419                                                                                                                   _tdm_virtual_display_cb_timeout,
420                                                                                                                   output_data,
421                                                                                                                   &ret);
422         if (!output_data->timer) goto create_fail;
423
424         LIST_INITHEAD(&output_data->timer_event_list);
425
426         /* The TDM virtual backend output support only one layer. */
427         layer_data = calloc(1, sizeof(tdm_virtual_layer_data));
428         if (!layer_data) {
429                 TDM_ERR("alloc failed");
430                 ret = TDM_ERROR_OUT_OF_MEMORY;
431                 goto create_fail;
432         }
433
434         layer_data->virtual_data = virtual_data;
435         layer_data->output_data = output_data;
436         layer_data->zpos = 0;
437
438         layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY | TDM_LAYER_CAPABILITY_GRAPHIC;
439         output_data->primary_layer = layer_data;
440
441         LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
442
443         ret = tdm_backend_register_output(virtual_data->dpy, output_data);
444         GOTO_IF_FAIL(ret == TDM_ERROR_NONE, create_fail);
445
446         *error = TDM_ERROR_NONE;
447
448         return output_data;
449
450 create_fail:
451         if (layer_data) free(layer_data);
452         if (output_data->output_modes) free(output_data->output_modes);
453         free(output_data);
454
455         *error = ret;
456
457         return NULL;
458 }
459
460 tdm_error
461 virtual_display_output_destroy(tdm_backend_data *bdata, tdm_output *output)
462 {
463         tdm_virtual_data *virtual_data = bdata;
464         tdm_virtual_output_data *o, *output_data = output;
465         int find = 0;
466
467         RETURN_VAL_IF_FAIL(virtual_data, TDM_ERROR_INVALID_PARAMETER);
468         RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
469
470         LIST_FOR_EACH_ENTRY(o, &virtual_data->output_list, link) {
471                 if (o == output_data) {
472                         find = 1;
473                         break;
474                 }
475         }
476
477         if (find) {
478                 if (output_data->output_modes)
479                         free(output_data->output_modes);
480                 tdm_backend_unregister_output(virtual_data->dpy, output);
481         }
482         else
483                 return TDM_ERROR_INVALID_PARAMETER;
484
485         return TDM_ERROR_NONE;
486 }
487
488 tdm_error
489 virtual_output_get_capability(tdm_output *output, tdm_caps_output *caps)
490 {
491         tdm_virtual_output_data *output_data = output;
492         tdm_error ret;
493
494         RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
495         RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
496
497         memset(caps, 0, sizeof(tdm_caps_output));
498
499         snprintf(caps->maker, TDM_NAME_LEN, "virtual");
500         snprintf(caps->model, TDM_NAME_LEN, "virtual");
501         snprintf(caps->name, TDM_NAME_LEN, "%s", output_data->name);
502
503         caps->status = output_data->status;
504         caps->type = output_data->connector_type;
505         caps->type_id = 0;
506
507         caps->mode_count = output_data->mode_count;
508         if (output_data->mode_count != 0) {
509                 caps->modes = calloc(output_data->mode_count, sizeof(tdm_output_mode));
510                 if (!caps->modes) {
511                         ret = TDM_ERROR_OUT_OF_MEMORY;
512                         TDM_ERR("alloc failed\n");
513                         goto failed_get;
514                 }
515
516                 *caps->modes = *output_data->output_modes;
517         }
518
519         caps->mmWidth = output_data->mmwidth;
520         caps->mmHeight =output_data->mmheight;
521         caps->subpixel = 1;
522
523         caps->min_w = -1;
524         caps->min_h = -1;
525         caps->max_w = -1;
526         caps->max_h = -1;
527         caps->preferred_align = -1;
528
529         caps->prop_count = 0;
530
531         return TDM_ERROR_NONE;
532 failed_get:
533         memset(caps, 0, sizeof(tdm_caps_output));
534         return ret;
535 }
536
537 tdm_layer **
538 virtual_output_get_layers(tdm_output *output,  int *count, tdm_error *error)
539 {
540         tdm_virtual_output_data *output_data = output;
541         tdm_virtual_layer_data *layer_data = NULL;
542         tdm_layer **layers;
543         tdm_error ret;
544         int i;
545
546         RETURN_VAL_IF_FAIL(output_data, NULL);
547         RETURN_VAL_IF_FAIL(count, NULL);
548
549         *count = 0;
550         LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
551         (*count)++;
552
553         if (*count == 0) {
554                 ret = TDM_ERROR_NONE;
555                 goto failed_get;
556         }
557
558         /* will be freed in frontend */
559         layers = calloc(*count, sizeof(tdm_virtual_layer_data *));
560         if (!layers) {
561                 TDM_ERR("failed: alloc memory");
562                 *count = 0;
563                 ret = TDM_ERROR_OUT_OF_MEMORY;
564                 goto failed_get;
565         }
566
567         i = 0;
568         LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
569         layers[i++] = layer_data;
570
571         if (error)
572                 *error = TDM_ERROR_NONE;
573
574         return layers;
575 failed_get:
576         if (error)
577                 *error = ret;
578         return NULL;
579 }
580
581 tdm_error
582 virtual_output_wait_vblank(tdm_output *output, int interval, int sync, void *user_data)
583 {
584         tdm_virtual_output_data *output_data = output;
585         tdm_virtual_event_data *event_data;
586         tdm_error ret;
587
588         RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
589
590         event_data = calloc(1, sizeof(tdm_virtual_event_data));
591         if (!event_data) {
592                 TDM_ERR("alloc failed");
593                 return TDM_ERROR_OUT_OF_MEMORY;
594         }
595
596         event_data->type = TDM_VIRTUAL_EVENT_TYPE_WAIT;
597         event_data->output_data = output_data;
598         event_data->user_data = user_data;
599
600         ret = _tdm_virtual_display_wait_vblank(output_data, interval, event_data);
601         if (ret != TDM_ERROR_NONE) {
602                 free(event_data);
603                 return ret;
604         }
605
606         return TDM_ERROR_NONE;
607 }
608
609 tdm_error
610 virtual_output_set_vblank_handler(tdm_output *output, tdm_output_vblank_handler func)
611 {
612         tdm_virtual_output_data *output_data = output;
613
614         RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
615         RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
616
617         output_data->vblank_func = func;
618
619         return TDM_ERROR_NONE;
620 }
621
622 tdm_error
623 virtual_output_commit(tdm_output *output, int sync, void *user_data)
624 {
625         tdm_virtual_output_data *output_data = output;
626         tdm_virtual_event_data *event_data;
627         tdm_error ret;
628
629         RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
630
631         event_data = calloc(1, sizeof(tdm_virtual_event_data));
632         if (!event_data) {
633                 TDM_ERR("alloc failed");
634                 return TDM_ERROR_OUT_OF_MEMORY;
635         }
636
637         event_data->type = TDM_VIRTUAL_EVENT_TYPE_COMMIT;
638         event_data->output_data = output_data;
639         event_data->user_data = user_data;
640
641         ret = _tdm_virtual_display_wait_vblank(output_data, 1, event_data);
642         if (ret != TDM_ERROR_NONE) {
643                 free(event_data);
644                 return ret;
645         }
646
647         return TDM_ERROR_NONE;
648 }
649
650 tdm_error
651 virtual_output_set_commit_handler(tdm_output *output, tdm_output_commit_handler func)
652 {
653         tdm_virtual_output_data *output_data = output;
654
655         RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
656         RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
657
658         output_data->commit_func = func;
659
660         return TDM_ERROR_NONE;
661 }
662
663 tdm_error
664 virtual_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
665 {
666         tdm_virtual_output_data *output_data = output;
667
668         RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
669         RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
670
671         output_data->current_mode = mode;
672         output_data->mode_changed = 1;
673
674         return TDM_ERROR_NONE;
675 }
676
677 tdm_error
678 virtual_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
679 {
680         tdm_virtual_output_data *output_data = output;
681
682         RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
683         RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
684
685         *mode = output_data->current_mode;
686
687         return TDM_ERROR_NONE;
688 }
689
690 tdm_error
691 virtual_output_set_available_mode(tdm_output *output, const tdm_output_mode *modes, int count)
692 {
693         tdm_virtual_output_data *output_data = output;
694
695         RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
696         RETURN_VAL_IF_FAIL(modes, TDM_ERROR_INVALID_PARAMETER);
697         RETURN_VAL_IF_FAIL(count > 0, TDM_ERROR_INVALID_PARAMETER);
698
699         /* set available mode only permittied disconnect status */
700         RETURN_VAL_IF_FAIL(output_data->status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED, TDM_ERROR_BUSY);
701
702         if (output_data->output_modes)
703                 free(output_data->output_modes);
704         output_data->output_modes = NULL;
705
706         output_data->output_modes = calloc(1, count * sizeof(tdm_output_mode));
707         RETURN_VAL_IF_FAIL(output_data->output_modes != NULL, TDM_ERROR_OUT_OF_MEMORY);
708
709         memcpy(output_data->output_modes, modes, count * sizeof(tdm_output_mode));
710         output_data->mode_count = count;
711
712         return TDM_ERROR_NONE;
713 }
714
715 tdm_error
716 virtual_output_set_physical_size(tdm_output *output, unsigned int mmwidth, unsigned int mmheight)
717 {
718         tdm_virtual_output_data *output_data = output;
719
720         RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
721         RETURN_VAL_IF_FAIL(mmwidth != 0, TDM_ERROR_INVALID_PARAMETER);
722         RETURN_VAL_IF_FAIL(mmheight != 0, TDM_ERROR_INVALID_PARAMETER);
723
724         output_data->mmwidth = mmwidth;
725         output_data->mmheight = mmheight;
726
727         return TDM_ERROR_NONE;
728 }
729
730 tdm_error
731 virtual_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps)
732 {
733         tdm_virtual_layer_data *layer_data = layer;
734
735         RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
736         RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
737
738         memset(caps, 0, sizeof(tdm_caps_layer));
739
740         caps->capabilities = layer_data->capabilities;
741         caps->zpos = layer_data->zpos;
742
743         caps->format_count = 2;
744         caps->formats = calloc(caps->format_count, sizeof(tbm_format));
745         if (!caps->formats) {
746                 TDM_ERR("alloc failed\n");
747                 free(caps->formats);
748                 memset(caps, 0, sizeof(tdm_caps_layer));
749                 return TDM_ERROR_OUT_OF_MEMORY;
750         }
751
752         caps->formats[0] = TBM_FORMAT_ARGB8888;
753         caps->formats[1] = TBM_FORMAT_XRGB8888;
754
755         caps->prop_count = 0;
756
757         return TDM_ERROR_NONE;
758 }
759
760 tdm_error
761 virtual_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
762 {
763         tdm_virtual_layer_data *layer_data = layer;
764
765         RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
766         RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
767
768         layer_data->info = *info;
769         layer_data->info_changed = 1;
770
771         return TDM_ERROR_NONE;
772 }
773
774 tdm_error
775 virtual_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
776 {
777         tdm_virtual_layer_data *layer_data = layer;
778
779         RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
780         RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
781
782         *info = layer_data->info;
783
784         return TDM_ERROR_NONE;
785 }
786
787 tdm_error
788 virtual_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
789 {
790         tdm_virtual_layer_data *layer_data = layer;
791
792         RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
793         RETURN_VAL_IF_FAIL(buffer, TDM_ERROR_INVALID_PARAMETER);
794
795         layer_data->display_buffer = buffer;
796         layer_data->display_buffer_changed = 1;
797
798         return TDM_ERROR_NONE;
799 }
800
801 tdm_error
802 virtual_layer_unset_buffer(tdm_layer *layer)
803 {
804         tdm_virtual_layer_data *layer_data = layer;
805
806         RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
807
808         layer_data->display_buffer = NULL;
809         layer_data->display_buffer_changed = 1;
810
811         return TDM_ERROR_NONE;
812 }