5 #include "tdm_virtual.h"
7 typedef struct _tdm_virtual_output_data tdm_virtual_output_data;
8 typedef struct _tdm_virtual_voutput_data tdm_virtual_voutput_data;
9 typedef struct _tdm_virtual_layer_data tdm_virtual_layer_data;
10 typedef struct _tdm_virtual_event_data tdm_virtual_event_data;
13 TDM_VIRTUAL_EVENT_TYPE_WAIT,
14 TDM_VIRTUAL_EVENT_TYPE_COMMIT,
15 TDM_VIRTUAL_EVENT_TYPE_VCOMMIT,
16 } tdm_virtual_event_type;
18 struct _tdm_virtual_event_data {
19 struct list_head link;
21 tdm_virtual_event_type type;
22 tdm_virtual_output_data *output_data;
26 struct _tdm_virtual_output_data {
27 struct list_head link;
29 /* data which are fixed at initializing */
30 tdm_virtual_data *virtual_data;
31 tdm_virtual_voutput_data *voutput_data;
33 char name[TDM_NAME_LEN]; /* output name */
35 tdm_output_type connector_type;
36 struct list_head layer_list;
37 tdm_virtual_layer_data *primary_layer;
41 /* not fixed data below */
42 tdm_output_vblank_handler vblank_func;
43 tdm_output_commit_handler commit_func;
44 void *commit_user_data;
46 tdm_output_conn_status status;
47 tdm_output_status_handler status_func;
48 void *status_user_data;
51 const tdm_output_mode *current_mode;
53 tdm_event_loop_source *timer;
54 unsigned int timer_waiting;
55 struct list_head timer_event_list;
58 struct _tdm_virtual_voutput_data {
59 struct list_head link;
61 /* data which are fixed at initializing */
62 tdm_virtual_data *virtual_data;
63 tdm_virtual_output_data *output_data;
65 char name[TDM_NAME_LEN]; /* output name */
67 tdm_voutput_commit_handler vcommit_func;
69 tdm_output_mode *output_modes;
73 unsigned int mmheight;
77 struct _tdm_virtual_layer_data {
78 struct list_head link;
80 /* data which are fixed at initializing */
81 tdm_virtual_data *virtual_data;
82 tdm_virtual_output_data *output_data;
83 tdm_layer_capability capabilities;
86 /* not fixed data below */
90 tbm_surface_h display_buffer;
91 int display_buffer_changed;
95 _tdm_virtual_display_cb_event(tdm_virtual_output_data *output_data, tdm_virtual_event_data *event_data,
96 unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec)
98 tdm_virtual_voutput_data *voutput_data = NULL;
100 switch (event_data->type) {
101 case TDM_VIRTUAL_EVENT_TYPE_WAIT:
102 if (output_data->vblank_func)
103 output_data->vblank_func(output_data, sequence, tv_sec, tv_usec, event_data->user_data);
105 case TDM_VIRTUAL_EVENT_TYPE_COMMIT:
106 if (output_data->commit_func)
107 output_data->commit_func(output_data, sequence, tv_sec, tv_usec, event_data->user_data);
109 case TDM_VIRTUAL_EVENT_TYPE_VCOMMIT:
110 voutput_data = output_data->voutput_data;
111 voutput_data->vcommit_func(voutput_data, sequence, tv_sec, tv_usec, NULL);
117 static void _tdm_virtual_get_current_time(unsigned int *tv_sec, unsigned int *tv_usec)
121 if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) {
123 *tv_usec = tp.tv_nsec / 1000;
125 *tv_sec = *tv_usec = 0;
130 _tdm_virtual_display_cb_timeout(void *user_data)
132 tdm_virtual_output_data *output_data = user_data;
133 tdm_virtual_event_data *e = NULL, *ee = NULL;
134 unsigned int tv_sec, tv_usec;
135 static unsigned int sequence = 0;
139 _tdm_virtual_get_current_time(&tv_sec, &tv_usec);
141 LIST_FOR_EACH_ENTRY_SAFE(e, ee, &output_data->timer_event_list, link) {
143 _tdm_virtual_display_cb_event(output_data, e, sequence, tv_sec, tv_usec);
147 return TDM_ERROR_NONE;
151 _tdm_virtual_display_wait_vblank(tdm_virtual_output_data *output_data, int interval, tdm_virtual_event_data *event_data)
156 RETURN_VAL_IF_FAIL(output_data->timer != NULL, TDM_ERROR_OPERATION_FAILED);
157 RETURN_VAL_IF_FAIL(output_data->current_mode->vrefresh > 0, TDM_ERROR_OPERATION_FAILED);
159 if (output_data->timer_waiting) {
160 LIST_ADDTAIL(&event_data->link, &output_data->timer_event_list);
161 return TDM_ERROR_NONE;
167 ms = ((double)1000.0 / output_data->current_mode->vrefresh) * interval;
169 ret = tdm_event_loop_source_timer_update(output_data->timer, ms);
170 if (ret != TDM_ERROR_NONE)
173 LIST_ADDTAIL(&event_data->link, &output_data->timer_event_list);
175 return TDM_ERROR_NONE;
179 _tdm_virtual_display_destroy_layer_list(tdm_virtual_data *virtual_data)
181 tdm_virtual_output_data *o = NULL;
183 LIST_FOR_EACH_ENTRY(o, &virtual_data->output_list, link) {
184 tdm_virtual_layer_data *l = NULL, *ll = NULL;
185 LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) {
193 tdm_virtual_display_destroy_output_list(tdm_virtual_data *virtual_data)
195 tdm_virtual_output_data *o = NULL, *oo = NULL;
197 if (LIST_IS_EMPTY(&virtual_data->output_list))
200 _tdm_virtual_display_destroy_layer_list(virtual_data);
202 LIST_FOR_EACH_ENTRY_SAFE(o, oo, &virtual_data->output_list, link) {
205 if (!LIST_IS_EMPTY(&o->timer_event_list)) {
206 tdm_virtual_event_data *e = NULL, *ee = NULL;
207 LIST_FOR_EACH_ENTRY_SAFE(e, ee, &o->timer_event_list, link) {
214 tdm_event_loop_source_remove(o->timer);
221 virtual_display_get_capability(tdm_backend_data *bdata, tdm_caps_display *caps)
223 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
225 caps->max_layer_count = -1; /* not defined */
227 return TDM_ERROR_NONE;
231 virtual_display_get_outputs(tdm_backend_data *bdata, int *count, tdm_error *error)
233 tdm_virtual_data *virtual_data = bdata;
234 tdm_virtual_output_data *output_data = NULL;
235 tdm_output **outputs;
239 RETURN_VAL_IF_FAIL(virtual_data, NULL);
240 RETURN_VAL_IF_FAIL(count, NULL);
243 LIST_FOR_EACH_ENTRY(output_data, &virtual_data->output_list, link)
247 ret = TDM_ERROR_NONE;
251 /* will be freed in frontend */
252 outputs = calloc(*count, sizeof(tdm_virtual_output_data *));
254 TDM_ERR("failed: alloc memory");
256 ret = TDM_ERROR_OUT_OF_MEMORY;
261 LIST_FOR_EACH_ENTRY(output_data, &virtual_data->output_list, link)
262 outputs[i++] = output_data;
265 *error = TDM_ERROR_NONE;
275 virtual_display_get_fd(tdm_backend_data *bdata, int *fd)
277 tdm_virtual_data *virtual_data = bdata;
279 RETURN_VAL_IF_FAIL(virtual_data, TDM_ERROR_INVALID_PARAMETER);
280 RETURN_VAL_IF_FAIL(fd, TDM_ERROR_INVALID_PARAMETER);
282 *fd = virtual_data->pipe[0];
284 return TDM_ERROR_NONE;
288 virtual_display_handle_events(tdm_backend_data *bdata)
290 return TDM_ERROR_NONE;
294 virtual_output_get_capability(tdm_output *output, tdm_caps_output *caps)
296 tdm_virtual_output_data *output_data = output;
297 tdm_virtual_voutput_data *voutput_data = NULL;
300 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
301 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
303 voutput_data = output_data->voutput_data;
305 memset(caps, 0, sizeof(tdm_caps_output));
307 snprintf(caps->maker, TDM_NAME_LEN, "virtual");
308 snprintf(caps->model, TDM_NAME_LEN, "virtual");
309 snprintf(caps->name, TDM_NAME_LEN, "%s", output_data->name);
311 caps->status = output_data->status;
312 caps->type = output_data->connector_type;
315 if (output_data->status == TDM_OUTPUT_CONN_STATUS_CONNECTED ||
316 output_data->status == TDM_OUTPUT_CONN_STATUS_MODE_SETTED) {
317 caps->mode_count = voutput_data->mode_count;
318 if (voutput_data->mode_count != 0) {
319 caps->modes = calloc(voutput_data->mode_count, sizeof(tdm_output_mode));
321 ret = TDM_ERROR_OUT_OF_MEMORY;
322 TDM_ERR("alloc failed\n");
325 memcpy(caps->modes, voutput_data->output_modes, voutput_data->mode_count * sizeof(tdm_output_mode));
328 caps->mmWidth = voutput_data->mmwidth;
329 caps->mmHeight = voutput_data->mmheight;
332 caps->mode_count = 0;
342 caps->preferred_align = -1;
344 caps->prop_count = 0;
346 return TDM_ERROR_NONE;
348 memset(caps, 0, sizeof(tdm_caps_output));
353 virtual_output_get_layers(tdm_output *output, int *count, tdm_error *error)
355 tdm_virtual_output_data *output_data = output;
356 tdm_virtual_layer_data *layer_data = NULL;
361 RETURN_VAL_IF_FAIL(output_data, NULL);
362 RETURN_VAL_IF_FAIL(count, NULL);
365 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
369 ret = TDM_ERROR_NONE;
373 /* will be freed in frontend */
374 layers = calloc(*count, sizeof(tdm_virtual_layer_data *));
376 TDM_ERR("failed: alloc memory");
378 ret = TDM_ERROR_OUT_OF_MEMORY;
383 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
384 layers[i++] = layer_data;
387 *error = TDM_ERROR_NONE;
397 virtual_output_wait_vblank(tdm_output *output, int interval, int sync, void *user_data)
399 tdm_virtual_output_data *output_data = output;
400 tdm_virtual_event_data *event_data;
403 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
405 event_data = calloc(1, sizeof(tdm_virtual_event_data));
407 TDM_ERR("alloc failed");
408 return TDM_ERROR_OUT_OF_MEMORY;
411 event_data->type = TDM_VIRTUAL_EVENT_TYPE_WAIT;
412 event_data->output_data = output_data;
413 event_data->user_data = user_data;
415 ret = _tdm_virtual_display_wait_vblank(output_data, interval, event_data);
416 if (ret != TDM_ERROR_NONE) {
421 return TDM_ERROR_NONE;
425 virtual_output_set_vblank_handler(tdm_output *output, tdm_output_vblank_handler func)
427 tdm_virtual_output_data *output_data = output;
429 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
430 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
432 output_data->vblank_func = func;
434 return TDM_ERROR_NONE;
438 virtual_output_commit(tdm_output *output, int sync, void *user_data)
440 tdm_virtual_output_data *output_data = output;
441 tdm_virtual_voutput_data *voutput_data = NULL;
442 tdm_virtual_layer_data *layer_data = NULL;
443 tdm_virtual_event_data *event_data;
446 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
448 voutput_data = output_data->voutput_data;
449 RETURN_VAL_IF_FAIL(voutput_data, TDM_ERROR_INVALID_PARAMETER);
451 if (output_data->mode_changed) {
452 output_data->mode_changed = 0;
453 output_data->status = TDM_OUTPUT_CONN_STATUS_MODE_SETTED;
455 if (output_data->status_func)
456 output_data->status_func(output_data, TDM_OUTPUT_CONN_STATUS_MODE_SETTED,
457 output_data->status_user_data);
460 layer_data = output_data->primary_layer;
462 if (layer_data->display_buffer == NULL && layer_data->display_buffer_changed == 1) {
463 event_data = calloc(1, sizeof(tdm_virtual_event_data));
465 TDM_ERR("alloc failed");
466 return TDM_ERROR_OUT_OF_MEMORY;
469 event_data->type = TDM_VIRTUAL_EVENT_TYPE_COMMIT;
470 event_data->output_data = output_data;
471 event_data->user_data = user_data;
473 ret = _tdm_virtual_display_wait_vblank(output_data, 3, event_data);
474 if (ret != TDM_ERROR_NONE) {
481 if (voutput_data->vcommit_func) {
482 if (layer_data->display_buffer_changed) {
483 output_data->commit_user_data = user_data;
484 event_data = calloc(1, sizeof(tdm_virtual_event_data));
486 TDM_ERR("alloc failed");
487 return TDM_ERROR_OUT_OF_MEMORY;
490 event_data->type = TDM_VIRTUAL_EVENT_TYPE_VCOMMIT;
491 event_data->output_data = output_data;
492 event_data->user_data = user_data;
494 ret = _tdm_virtual_display_wait_vblank(output_data, 1, event_data);
495 if (ret != TDM_ERROR_NONE) {
501 event_data = calloc(1, sizeof(tdm_virtual_event_data));
503 TDM_ERR("alloc failed");
504 return TDM_ERROR_OUT_OF_MEMORY;
507 event_data->type = TDM_VIRTUAL_EVENT_TYPE_COMMIT;
508 event_data->output_data = output_data;
509 event_data->user_data = user_data;
511 ret = _tdm_virtual_display_wait_vblank(output_data, 1, event_data);
512 if (ret != TDM_ERROR_NONE) {
519 layer_data->display_buffer_changed = 0;
521 return TDM_ERROR_NONE;
525 virtual_output_set_commit_handler(tdm_output *output, tdm_output_commit_handler func)
527 tdm_virtual_output_data *output_data = output;
529 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
530 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
532 output_data->commit_func = func;
534 return TDM_ERROR_NONE;
538 virtual_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
540 tdm_virtual_output_data *output_data = output;
542 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
543 RETURN_VAL_IF_FAIL(dpms_value <= TDM_OUTPUT_DPMS_OFF, TDM_ERROR_INVALID_PARAMETER);
545 TDM_DBG("dpms change [%d] -> [%d]", output_data->dpms, dpms_value);
547 output_data->dpms = dpms_value;
549 return TDM_ERROR_NONE;
553 virtual_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value)
555 tdm_virtual_output_data *output_data = output;
557 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
558 RETURN_VAL_IF_FAIL(dpms_value, TDM_ERROR_INVALID_PARAMETER);
560 *dpms_value = output_data->dpms;
562 return TDM_ERROR_NONE;
566 virtual_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
568 tdm_virtual_output_data *output_data = output;
570 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
571 RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
573 output_data->current_mode = mode;
574 output_data->mode_changed = 1;
576 return TDM_ERROR_NONE;
580 virtual_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
582 tdm_virtual_output_data *output_data = output;
584 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
585 RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
587 *mode = output_data->current_mode;
589 return TDM_ERROR_NONE;
593 virtual_output_set_status_handler(tdm_output *output,
594 tdm_output_status_handler func, void *user_data)
596 tdm_virtual_output_data *output_data = output;
598 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
599 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
601 output_data->status_func = func;
602 output_data->status_user_data = user_data;
604 return TDM_ERROR_NONE;
608 virtual_voutput_set_available_mode(tdm_voutput *voutput, const tdm_output_mode *modes, int count)
610 tdm_virtual_voutput_data *voutput_data = voutput;
611 tdm_virtual_output_data *output_data = NULL;
613 RETURN_VAL_IF_FAIL(voutput_data, TDM_ERROR_INVALID_PARAMETER);
614 RETURN_VAL_IF_FAIL(modes, TDM_ERROR_INVALID_PARAMETER);
615 RETURN_VAL_IF_FAIL(count > 0, TDM_ERROR_INVALID_PARAMETER);
617 output_data = voutput_data->output_data;
619 /* set available mode only permittied disconnect status */
620 RETURN_VAL_IF_FAIL(output_data->status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED, TDM_ERROR_BUSY);
622 if (voutput_data->output_modes)
623 free(voutput_data->output_modes);
624 voutput_data->output_modes = NULL;
626 voutput_data->output_modes = calloc(1, count * sizeof(tdm_output_mode));
627 RETURN_VAL_IF_FAIL(voutput_data->output_modes != NULL, TDM_ERROR_OUT_OF_MEMORY);
629 memcpy(voutput_data->output_modes, modes, count * sizeof(tdm_output_mode));
630 voutput_data->mode_count = count;
632 return TDM_ERROR_NONE;
636 virtual_voutput_set_physical_size(tdm_voutput *voutput, unsigned int mmwidth, unsigned int mmheight)
638 tdm_virtual_voutput_data *voutput_data = voutput;
640 RETURN_VAL_IF_FAIL(voutput_data, TDM_ERROR_INVALID_PARAMETER);
641 RETURN_VAL_IF_FAIL(mmwidth != 0, TDM_ERROR_INVALID_PARAMETER);
642 RETURN_VAL_IF_FAIL(mmheight != 0, TDM_ERROR_INVALID_PARAMETER);
644 voutput_data->mmwidth = mmwidth;
645 voutput_data->mmheight = mmheight;
647 return TDM_ERROR_NONE;
651 virtual_voutput_connect(tdm_voutput *voutput)
653 tdm_virtual_voutput_data *voutput_data = voutput;
654 tdm_virtual_output_data *output_data = NULL;
656 RETURN_VAL_IF_FAIL(voutput_data, TDM_ERROR_INVALID_PARAMETER);
658 output_data = voutput_data->output_data;
660 if (output_data->status == TDM_OUTPUT_CONN_STATUS_CONNECTED ||
661 output_data->status == TDM_OUTPUT_CONN_STATUS_MODE_SETTED)
662 return TDM_ERROR_NONE;
664 output_data->status = TDM_OUTPUT_CONN_STATUS_CONNECTED;
666 if (output_data->status_func)
667 output_data->status_func(output_data, output_data->status,
668 output_data->status_user_data);
670 return TDM_ERROR_NONE;
674 virtual_voutput_disconnect(tdm_voutput *voutput)
677 tdm_virtual_voutput_data *voutput_data = voutput;
678 tdm_virtual_output_data *output_data = NULL;
680 RETURN_VAL_IF_FAIL(voutput_data, TDM_ERROR_INVALID_PARAMETER);
682 output_data = voutput_data->output_data;
684 if (output_data->status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED)
685 return TDM_ERROR_NONE;
687 output_data->status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
689 if (output_data->status_func)
690 output_data->status_func(output_data, output_data->status,
691 output_data->status_user_data);
693 return TDM_ERROR_NONE;
697 virtual_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps)
699 tdm_virtual_layer_data *layer_data = layer;
701 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
702 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
704 memset(caps, 0, sizeof(tdm_caps_layer));
706 caps->capabilities = layer_data->capabilities;
707 caps->zpos = layer_data->zpos;
709 caps->format_count = 2;
710 caps->formats = calloc(caps->format_count, sizeof(tbm_format));
711 if (!caps->formats) {
712 TDM_ERR("alloc failed\n");
714 memset(caps, 0, sizeof(tdm_caps_layer));
715 return TDM_ERROR_OUT_OF_MEMORY;
718 caps->formats[0] = TBM_FORMAT_ARGB8888;
719 caps->formats[1] = TBM_FORMAT_XRGB8888;
721 caps->prop_count = 0;
723 return TDM_ERROR_NONE;
727 virtual_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
729 tdm_virtual_layer_data *layer_data = layer;
731 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
732 RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
734 layer_data->info = *info;
735 layer_data->info_changed = 1;
737 return TDM_ERROR_NONE;
741 virtual_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
743 tdm_virtual_layer_data *layer_data = layer;
745 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
746 RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
748 *info = layer_data->info;
750 return TDM_ERROR_NONE;
754 virtual_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
756 tdm_virtual_layer_data *layer_data = layer;
758 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
759 RETURN_VAL_IF_FAIL(buffer, TDM_ERROR_INVALID_PARAMETER);
761 layer_data->display_buffer = buffer;
762 layer_data->display_buffer_changed = 1;
764 return TDM_ERROR_NONE;
768 virtual_layer_unset_buffer(tdm_layer *layer)
770 tdm_virtual_layer_data *layer_data = layer;
772 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
774 layer_data->display_buffer = NULL;
775 layer_data->display_buffer_changed = 1;
777 return TDM_ERROR_NONE;
781 virtual_display_voutput_create(tdm_backend_data *bdata, const char *name, tdm_error *error)
783 tdm_virtual_data *virtual_data = bdata;
784 tdm_virtual_voutput_data *voutput_data = NULL;
785 tdm_virtual_output_data *output_data = NULL;
786 tdm_virtual_layer_data *layer_data = NULL;
788 if (!virtual_data || !name) {
789 TDM_ERR("invalid parameter");
790 if (error) *error = TDM_ERROR_INVALID_PARAMETER;
794 voutput_data = calloc(1, sizeof(tdm_virtual_voutput_data));
796 TDM_ERR("alloc failed");
797 if (error) *error = TDM_ERROR_OUT_OF_MEMORY;
801 voutput_data->output_modes = calloc(1, sizeof(tdm_output_mode));
802 if (!voutput_data->output_modes) {
803 TDM_ERR("alloc failed");
808 snprintf(voutput_data->output_modes->name, TDM_NAME_LEN, "640x480");
809 voutput_data->output_modes->vrefresh = 30;
810 voutput_data->output_modes->clock = 25200;
811 voutput_data->output_modes->hdisplay = 640;
812 voutput_data->output_modes->hsync_start = 656;
813 voutput_data->output_modes->hsync_end = 752;
814 voutput_data->output_modes->htotal = 800;
815 voutput_data->output_modes->hskew = 0;
816 voutput_data->output_modes->vdisplay = 480;
817 voutput_data->output_modes->vsync_start = 490;
818 voutput_data->output_modes->vsync_end = 492;
819 voutput_data->output_modes->vtotal = 525;
820 voutput_data->output_modes->vscan = 0;
821 voutput_data->output_modes->flags = 0;
822 voutput_data->output_modes->type = 0;
823 voutput_data->mode_count = 1;
825 voutput_data->mmwidth = 10;
826 voutput_data->mmheight = 10;
828 voutput_data->virtual_data = virtual_data;
830 output_data = calloc(1, sizeof(tdm_virtual_output_data));
832 TDM_ERR("alloc failed");
835 voutput_data->output_data = output_data;
837 LIST_INITHEAD(&output_data->layer_list);
839 output_data->virtual_data = virtual_data;
840 output_data->voutput_data = voutput_data;
841 output_data->pipe = 0;
842 output_data->connector_type = TDM_OUTPUT_TYPE_Unknown;
843 output_data->status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
845 snprintf(voutput_data->name, TDM_NAME_LEN, "%s", name);
846 snprintf(output_data->name, TDM_NAME_LEN, "%s", name);
848 output_data->timer = tdm_event_loop_add_timer_handler(virtual_data->dpy,
849 _tdm_virtual_display_cb_timeout,
852 if (!output_data->timer) goto create_fail;
854 LIST_INITHEAD(&output_data->timer_event_list);
856 /* The TDM virtual backend output support only one layer. */
857 layer_data = calloc(1, sizeof(tdm_virtual_layer_data));
859 TDM_ERR("alloc failed");
863 layer_data->virtual_data = virtual_data;
864 layer_data->output_data = output_data;
865 layer_data->zpos = 0;
867 layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY | TDM_LAYER_CAPABILITY_GRAPHIC;
868 output_data->primary_layer = layer_data;
870 LIST_ADDTAIL(&voutput_data->link, &virtual_data->voutput_list);
871 LIST_ADDTAIL(&output_data->link, &virtual_data->output_list);
872 LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
874 if (error) *error = TDM_ERROR_NONE;
876 TDM_DBG("virtual output create(%s)(%p)(%p)", output_data->name, voutput_data, output_data);
881 if (output_data) free(output_data);
882 if (voutput_data->output_modes) free(voutput_data->output_modes);
883 if (voutput_data) free(voutput_data);
885 if (error) *error = TDM_ERROR_OUT_OF_MEMORY;
891 virtual_voutput_destroy(tdm_voutput *voutput)
893 tdm_virtual_data *virtual_data = NULL;
894 tdm_virtual_voutput_data *vo = NULL, *voutput_data = voutput;
897 RETURN_VAL_IF_FAIL(voutput_data, TDM_ERROR_INVALID_PARAMETER);
899 virtual_data = voutput_data->virtual_data;
901 LIST_FOR_EACH_ENTRY(vo, &virtual_data->voutput_list, link) {
902 if (vo == voutput_data) {
909 tdm_virtual_layer_data *l = NULL, *ll = NULL;
910 tdm_virtual_output_data *output_data = NULL;
912 TDM_DBG("virtual output destroy(%s)", voutput_data->name);
914 output_data = voutput_data->output_data;
916 if (!LIST_IS_EMPTY(&output_data->timer_event_list)) {
917 tdm_virtual_event_data *e = NULL, *ee = NULL;
918 LIST_FOR_EACH_ENTRY_SAFE(e, ee, &output_data->timer_event_list, link) {
924 if (output_data->timer)
925 tdm_event_loop_source_remove(output_data->timer);
927 LIST_FOR_EACH_ENTRY_SAFE(l, ll, &output_data->layer_list, link) {
932 LIST_DEL(&output_data->link);
935 if (voutput_data->output_modes)
936 free(voutput_data->output_modes);
937 LIST_DEL(&voutput_data->link);
940 return TDM_ERROR_INVALID_PARAMETER;
942 return TDM_ERROR_NONE;
946 virtual_voutput_get_output(tdm_voutput *voutput, tdm_error *error)
948 tdm_virtual_voutput_data *voutput_data = voutput;
951 if (error) *error = TDM_ERROR_INVALID_PARAMETER;
955 if (error) *error = TDM_ERROR_NONE;
957 return voutput_data->output_data;
961 virtual_voutput_set_commit_func(tdm_voutput *voutput, tdm_voutput_commit_handler commit_func)
963 tdm_virtual_voutput_data *voutput_data = voutput;
965 RETURN_VAL_IF_FAIL(voutput_data, TDM_ERROR_INVALID_PARAMETER);
967 voutput_data->vcommit_func = commit_func;
969 return TDM_ERROR_NONE;
973 virtual_voutput_commit_done(tdm_voutput *voutput)
975 tdm_virtual_voutput_data *voutput_data = voutput;
976 tdm_virtual_output_data *output_data = NULL;
977 unsigned int tv_sec, tv_usec;
978 static unsigned int sequence = 0;
979 tdm_virtual_event_data *event_data;
980 tdm_error ret = TDM_ERROR_NONE;
982 RETURN_VAL_IF_FAIL(voutput_data, TDM_ERROR_INVALID_PARAMETER);
983 output_data = voutput_data->output_data;
987 _tdm_virtual_get_current_time(&tv_sec, &tv_usec);
989 event_data = calloc(1, sizeof(tdm_virtual_event_data));
991 TDM_ERR("alloc failed");
992 return TDM_ERROR_OUT_OF_MEMORY;
995 event_data->type = TDM_VIRTUAL_EVENT_TYPE_COMMIT;
996 event_data->output_data = output_data;
997 event_data->user_data = output_data->commit_user_data;
999 ret = _tdm_virtual_display_wait_vblank(output_data, 1, event_data);
1000 if (ret != TDM_ERROR_NONE) {
1005 return TDM_ERROR_NONE;