5 #include "tdm_virtual.h"
8 _tdm_virtual_display_cb_event(tdm_virtual_output_data *output_data, tdm_virtual_event_data *event_data,
9 unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec)
11 tdm_virtual_voutput_data *voutput_data = NULL;
12 tdm_virtual_hwc_data *hwc_data;
14 switch (event_data->type) {
15 case TDM_VIRTUAL_EVENT_TYPE_WAIT:
16 if (output_data->vblank_func)
17 output_data->vblank_func(output_data, sequence, tv_sec, tv_usec, event_data->user_data);
19 case TDM_VIRTUAL_EVENT_TYPE_COMMIT:
20 if (output_data->hwc_enable) {
21 hwc_data = output_data->hwc_data;
23 TDM_ERR("no hwc_data");
27 if (hwc_data->commit_func)
28 hwc_data->commit_func(hwc_data, sequence,
30 event_data->user_data);
32 if (output_data->commit_func)
33 output_data->commit_func(output_data, sequence, tv_sec, tv_usec, event_data->user_data);
35 case TDM_VIRTUAL_EVENT_TYPE_VCOMMIT:
36 voutput_data = output_data->voutput_data;
37 voutput_data->vcommit_func(voutput_data, sequence, tv_sec, tv_usec, NULL);
43 static void _tdm_virtual_get_current_time(unsigned int *tv_sec, unsigned int *tv_usec)
47 if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) {
49 *tv_usec = tp.tv_nsec / 1000;
51 *tv_sec = *tv_usec = 0;
56 _tdm_virtual_display_cb_timeout(void *user_data)
58 tdm_virtual_output_data *output_data = user_data;
59 tdm_virtual_event_data *e = NULL, *ee = NULL;
60 unsigned int tv_sec, tv_usec;
61 static unsigned int sequence = 0;
65 _tdm_virtual_get_current_time(&tv_sec, &tv_usec);
67 LIST_FOR_EACH_ENTRY_SAFE(e, ee, &output_data->timer_event_list, link) {
69 _tdm_virtual_display_cb_event(output_data, e, sequence, tv_sec, tv_usec);
73 return TDM_ERROR_NONE;
77 _tdm_virtual_display_wait_vblank(tdm_virtual_output_data *output_data, int interval, tdm_virtual_event_data *event_data)
82 RETURN_VAL_IF_FAIL(output_data->timer != NULL, TDM_ERROR_OPERATION_FAILED);
83 RETURN_VAL_IF_FAIL(output_data->current_mode->vrefresh > 0, TDM_ERROR_OPERATION_FAILED);
85 if (output_data->timer_waiting) {
86 LIST_ADDTAIL(&event_data->link, &output_data->timer_event_list);
87 return TDM_ERROR_NONE;
93 ms = ((double)1000.0 / output_data->current_mode->vrefresh) * interval;
95 ret = tdm_event_loop_source_timer_update(output_data->timer, ms);
96 if (ret != TDM_ERROR_NONE)
99 LIST_ADDTAIL(&event_data->link, &output_data->timer_event_list);
101 return TDM_ERROR_NONE;
105 _tdm_virtual_display_destroy_layer_list(tdm_virtual_data *virtual_data)
107 tdm_virtual_output_data *o = NULL;
109 LIST_FOR_EACH_ENTRY(o, &virtual_data->output_list, link) {
110 tdm_virtual_layer_data *l = NULL, *ll = NULL;
111 LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) {
119 tdm_virtual_display_destroy_output_list(tdm_virtual_data *virtual_data)
121 tdm_virtual_output_data *o = NULL, *oo = NULL;
123 if (LIST_IS_EMPTY(&virtual_data->output_list))
126 _tdm_virtual_display_destroy_layer_list(virtual_data);
128 LIST_FOR_EACH_ENTRY_SAFE(o, oo, &virtual_data->output_list, link) {
131 if (!LIST_IS_EMPTY(&o->timer_event_list)) {
132 tdm_virtual_event_data *e = NULL, *ee = NULL;
133 LIST_FOR_EACH_ENTRY_SAFE(e, ee, &o->timer_event_list, link) {
140 tdm_event_loop_source_remove(o->timer);
147 virtual_display_get_capability(tdm_backend_data *bdata, tdm_caps_display *caps)
149 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
151 caps->max_layer_count = -1; /* not defined */
153 return TDM_ERROR_NONE;
157 virtual_display_get_outputs(tdm_backend_data *bdata, int *count, tdm_error *error)
159 tdm_virtual_data *virtual_data = bdata;
160 tdm_virtual_output_data *output_data = NULL;
161 tdm_output **outputs;
165 RETURN_VAL_IF_FAIL(virtual_data, NULL);
166 RETURN_VAL_IF_FAIL(count, NULL);
169 LIST_FOR_EACH_ENTRY(output_data, &virtual_data->output_list, link)
173 ret = TDM_ERROR_NONE;
177 /* will be freed in frontend */
178 outputs = calloc(*count, sizeof(tdm_virtual_output_data *));
180 TDM_ERR("failed: alloc memory");
182 ret = TDM_ERROR_OUT_OF_MEMORY;
187 LIST_FOR_EACH_ENTRY(output_data, &virtual_data->output_list, link)
188 outputs[i++] = output_data;
191 *error = TDM_ERROR_NONE;
201 virtual_display_get_fd(tdm_backend_data *bdata, int *fd)
203 tdm_virtual_data *virtual_data = bdata;
205 RETURN_VAL_IF_FAIL(virtual_data, TDM_ERROR_INVALID_PARAMETER);
206 RETURN_VAL_IF_FAIL(fd, TDM_ERROR_INVALID_PARAMETER);
208 *fd = virtual_data->pipe[0];
210 return TDM_ERROR_NONE;
214 virtual_display_handle_events(tdm_backend_data *bdata)
216 return TDM_ERROR_NONE;
220 virtual_output_get_capability(tdm_output *output, tdm_caps_output *caps)
222 tdm_virtual_output_data *output_data = output;
223 tdm_virtual_voutput_data *voutput_data = NULL;
226 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
227 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
229 voutput_data = output_data->voutput_data;
231 memset(caps, 0, sizeof(tdm_caps_output));
233 snprintf(caps->maker, TDM_NAME_LEN, "virtual");
234 snprintf(caps->model, TDM_NAME_LEN, "virtual");
235 snprintf(caps->name, TDM_NAME_LEN, "%s", output_data->name);
237 caps->status = output_data->status;
238 caps->type = output_data->connector_type;
241 if (output_data->status == TDM_OUTPUT_CONN_STATUS_CONNECTED ||
242 output_data->status == TDM_OUTPUT_CONN_STATUS_MODE_SETTED) {
243 caps->mode_count = voutput_data->mode_count;
244 if (voutput_data->mode_count != 0) {
245 caps->modes = calloc(voutput_data->mode_count, sizeof(tdm_output_mode));
247 ret = TDM_ERROR_OUT_OF_MEMORY;
248 TDM_ERR("alloc failed\n");
251 memcpy(caps->modes, voutput_data->output_modes, voutput_data->mode_count * sizeof(tdm_output_mode));
254 caps->mmWidth = voutput_data->mmwidth;
255 caps->mmHeight = voutput_data->mmheight;
258 caps->mode_count = 0;
268 caps->preferred_align = -1;
270 caps->prop_count = 0;
272 if (output_data->virtual_data->hwc_mode)
273 caps->capabilities |= TDM_OUTPUT_CAPABILITY_HWC;
275 return TDM_ERROR_NONE;
277 memset(caps, 0, sizeof(tdm_caps_output));
282 virtual_output_get_layers(tdm_output *output, int *count, tdm_error *error)
284 tdm_virtual_output_data *output_data = output;
285 tdm_virtual_layer_data *layer_data = NULL;
290 RETURN_VAL_IF_FAIL(output_data, NULL);
291 RETURN_VAL_IF_FAIL(count, NULL);
293 if (output_data->virtual_data->hwc_mode) {
294 TDM_INFO("layers aren't supported in HWC mode");
296 ret = TDM_ERROR_NONE;
301 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
305 ret = TDM_ERROR_NONE;
309 /* will be freed in frontend */
310 layers = calloc(*count, sizeof(tdm_virtual_layer_data *));
312 TDM_ERR("failed: alloc memory");
314 ret = TDM_ERROR_OUT_OF_MEMORY;
319 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
320 layers[i++] = layer_data;
323 *error = TDM_ERROR_NONE;
333 virtual_output_wait_vblank(tdm_output *output, int interval, int sync, void *user_data)
335 tdm_virtual_output_data *output_data = output;
336 tdm_virtual_event_data *event_data;
339 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
341 event_data = calloc(1, sizeof(tdm_virtual_event_data));
343 TDM_ERR("alloc failed");
344 return TDM_ERROR_OUT_OF_MEMORY;
347 event_data->type = TDM_VIRTUAL_EVENT_TYPE_WAIT;
348 event_data->output_data = output_data;
349 event_data->user_data = user_data;
351 ret = _tdm_virtual_display_wait_vblank(output_data, interval, event_data);
352 if (ret != TDM_ERROR_NONE) {
357 return TDM_ERROR_NONE;
361 virtual_output_set_vblank_handler(tdm_output *output, tdm_output_vblank_handler func)
363 tdm_virtual_output_data *output_data = output;
365 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
366 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
368 output_data->vblank_func = func;
370 return TDM_ERROR_NONE;
374 virtual_output_commit(tdm_output *output, int sync, void *user_data)
376 tdm_virtual_output_data *output_data = output;
377 tdm_virtual_voutput_data *voutput_data = NULL;
378 tdm_virtual_layer_data *layer_data = NULL;
379 tdm_virtual_event_data *event_data;
382 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
384 voutput_data = output_data->voutput_data;
385 RETURN_VAL_IF_FAIL(voutput_data, TDM_ERROR_INVALID_PARAMETER);
387 if (output_data->mode_changed) {
388 output_data->mode_changed = 0;
389 output_data->status = TDM_OUTPUT_CONN_STATUS_MODE_SETTED;
391 if (output_data->status_func)
392 output_data->status_func(output_data, TDM_OUTPUT_CONN_STATUS_MODE_SETTED,
393 output_data->status_user_data);
396 layer_data = output_data->primary_layer;
398 if (layer_data->display_buffer == NULL && layer_data->display_buffer_changed == 1) {
399 event_data = calloc(1, sizeof(tdm_virtual_event_data));
401 TDM_ERR("alloc failed");
402 return TDM_ERROR_OUT_OF_MEMORY;
405 event_data->type = TDM_VIRTUAL_EVENT_TYPE_COMMIT;
406 event_data->output_data = output_data;
407 event_data->user_data = user_data;
409 ret = _tdm_virtual_display_wait_vblank(output_data, 3, event_data);
410 if (ret != TDM_ERROR_NONE) {
417 if (voutput_data->vcommit_func) {
418 if (layer_data->display_buffer_changed) {
419 output_data->commit_user_data = user_data;
420 event_data = calloc(1, sizeof(tdm_virtual_event_data));
422 TDM_ERR("alloc failed");
423 return TDM_ERROR_OUT_OF_MEMORY;
426 event_data->type = TDM_VIRTUAL_EVENT_TYPE_VCOMMIT;
427 event_data->output_data = output_data;
428 event_data->user_data = user_data;
430 ret = _tdm_virtual_display_wait_vblank(output_data, 1, event_data);
431 if (ret != TDM_ERROR_NONE) {
437 event_data = calloc(1, sizeof(tdm_virtual_event_data));
439 TDM_ERR("alloc failed");
440 return TDM_ERROR_OUT_OF_MEMORY;
443 event_data->type = TDM_VIRTUAL_EVENT_TYPE_COMMIT;
444 event_data->output_data = output_data;
445 event_data->user_data = user_data;
447 ret = _tdm_virtual_display_wait_vblank(output_data, 1, event_data);
448 if (ret != TDM_ERROR_NONE) {
455 layer_data->display_buffer_changed = 0;
457 return TDM_ERROR_NONE;
461 virtual_output_set_commit_handler(tdm_output *output, tdm_output_commit_handler func)
463 tdm_virtual_output_data *output_data = output;
465 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
466 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
468 output_data->commit_func = func;
470 return TDM_ERROR_NONE;
474 virtual_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
476 tdm_virtual_output_data *output_data = output;
478 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
479 RETURN_VAL_IF_FAIL(dpms_value <= TDM_OUTPUT_DPMS_OFF, TDM_ERROR_INVALID_PARAMETER);
481 TDM_DBG("dpms change [%d] -> [%d]", output_data->dpms, dpms_value);
483 output_data->dpms = dpms_value;
485 return TDM_ERROR_NONE;
489 virtual_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value)
491 tdm_virtual_output_data *output_data = output;
493 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
494 RETURN_VAL_IF_FAIL(dpms_value, TDM_ERROR_INVALID_PARAMETER);
496 *dpms_value = output_data->dpms;
498 return TDM_ERROR_NONE;
502 virtual_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
504 tdm_virtual_output_data *output_data = output;
505 tdm_error ret = TDM_ERROR_NONE;
507 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
508 RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
510 /* create or replace the target_window when the output mode is set */
511 if (output_data->virtual_data->hwc_mode) {
512 ret = virtual_hwc_initailize_target_window(output_data->hwc_data, mode->hdisplay, mode->vdisplay);
513 if (ret != TDM_ERROR_NONE) {
514 TDM_ERR("create target hwc window failed (%d)", ret);
519 output_data->current_mode = mode;
520 output_data->mode_changed = 1;
522 return TDM_ERROR_NONE;
526 virtual_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
528 tdm_virtual_output_data *output_data = output;
530 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
531 RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
533 *mode = output_data->current_mode;
535 return TDM_ERROR_NONE;
539 virtual_output_set_status_handler(tdm_output *output,
540 tdm_output_status_handler func, void *user_data)
542 tdm_virtual_output_data *output_data = output;
544 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
545 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
547 output_data->status_func = func;
548 output_data->status_user_data = user_data;
550 return TDM_ERROR_NONE;
554 virtual_output_get_hwc(tdm_output *output, tdm_error *error)
556 tdm_virtual_hwc_data *hwc_data = NULL;
557 tdm_virtual_output_data *output_data = output;
560 TDM_ERR("invalid params");
562 *error = TDM_ERROR_INVALID_PARAMETER;
566 if (output_data->hwc_data) {
567 TDM_INFO("hwc_data already exists");
569 *error = TDM_ERROR_NONE;
570 return output_data->hwc_data;
573 hwc_data = calloc(1, sizeof(tdm_virtual_hwc_data));
575 TDM_ERR("alloc failed");
577 *error = TDM_ERROR_OUT_OF_MEMORY;
580 hwc_data->output_data = output_data;
582 LIST_INITHEAD(&hwc_data->hwc_window_list);
584 output_data->hwc_data = hwc_data;
587 *error = TDM_ERROR_NONE;
593 virtual_voutput_set_available_mode(tdm_voutput *voutput, const tdm_output_mode *modes, int count)
595 tdm_virtual_voutput_data *voutput_data = voutput;
596 tdm_virtual_output_data *output_data = NULL;
598 RETURN_VAL_IF_FAIL(voutput_data, TDM_ERROR_INVALID_PARAMETER);
599 RETURN_VAL_IF_FAIL(modes, TDM_ERROR_INVALID_PARAMETER);
600 RETURN_VAL_IF_FAIL(count > 0, TDM_ERROR_INVALID_PARAMETER);
602 output_data = voutput_data->output_data;
604 /* set available mode only permittied disconnect status */
605 RETURN_VAL_IF_FAIL(output_data->status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED, TDM_ERROR_BUSY);
607 if (voutput_data->output_modes)
608 free(voutput_data->output_modes);
609 voutput_data->output_modes = NULL;
611 voutput_data->output_modes = calloc(1, count * sizeof(tdm_output_mode));
612 RETURN_VAL_IF_FAIL(voutput_data->output_modes != NULL, TDM_ERROR_OUT_OF_MEMORY);
614 memcpy(voutput_data->output_modes, modes, count * sizeof(tdm_output_mode));
615 voutput_data->mode_count = count;
617 return TDM_ERROR_NONE;
621 virtual_voutput_set_physical_size(tdm_voutput *voutput, unsigned int mmwidth, unsigned int mmheight)
623 tdm_virtual_voutput_data *voutput_data = voutput;
625 RETURN_VAL_IF_FAIL(voutput_data, TDM_ERROR_INVALID_PARAMETER);
626 RETURN_VAL_IF_FAIL(mmwidth != 0, TDM_ERROR_INVALID_PARAMETER);
627 RETURN_VAL_IF_FAIL(mmheight != 0, TDM_ERROR_INVALID_PARAMETER);
629 voutput_data->mmwidth = mmwidth;
630 voutput_data->mmheight = mmheight;
632 return TDM_ERROR_NONE;
636 virtual_voutput_connect(tdm_voutput *voutput)
638 tdm_virtual_voutput_data *voutput_data = voutput;
639 tdm_virtual_output_data *output_data = NULL;
641 RETURN_VAL_IF_FAIL(voutput_data, TDM_ERROR_INVALID_PARAMETER);
643 output_data = voutput_data->output_data;
645 if (output_data->status == TDM_OUTPUT_CONN_STATUS_CONNECTED ||
646 output_data->status == TDM_OUTPUT_CONN_STATUS_MODE_SETTED)
647 return TDM_ERROR_NONE;
649 output_data->status = TDM_OUTPUT_CONN_STATUS_CONNECTED;
651 if (output_data->status_func)
652 output_data->status_func(output_data, output_data->status,
653 output_data->status_user_data);
655 return TDM_ERROR_NONE;
659 virtual_voutput_disconnect(tdm_voutput *voutput)
662 tdm_virtual_voutput_data *voutput_data = voutput;
663 tdm_virtual_output_data *output_data = NULL;
665 RETURN_VAL_IF_FAIL(voutput_data, TDM_ERROR_INVALID_PARAMETER);
667 output_data = voutput_data->output_data;
669 if (output_data->status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED)
670 return TDM_ERROR_NONE;
672 output_data->status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
674 if (output_data->status_func)
675 output_data->status_func(output_data, output_data->status,
676 output_data->status_user_data);
678 return TDM_ERROR_NONE;
682 virtual_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps)
684 tdm_virtual_layer_data *layer_data = layer;
686 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
687 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
689 memset(caps, 0, sizeof(tdm_caps_layer));
691 caps->capabilities = layer_data->capabilities;
692 caps->zpos = layer_data->zpos;
694 caps->format_count = 2;
695 caps->formats = calloc(caps->format_count, sizeof(tbm_format));
696 if (!caps->formats) {
697 TDM_ERR("alloc failed\n");
699 memset(caps, 0, sizeof(tdm_caps_layer));
700 return TDM_ERROR_OUT_OF_MEMORY;
703 caps->formats[0] = TBM_FORMAT_ARGB8888;
704 caps->formats[1] = TBM_FORMAT_XRGB8888;
706 caps->prop_count = 0;
708 return TDM_ERROR_NONE;
712 virtual_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
714 tdm_virtual_layer_data *layer_data = layer;
716 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
717 RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
719 layer_data->info = *info;
720 layer_data->info_changed = 1;
722 return TDM_ERROR_NONE;
726 virtual_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
728 tdm_virtual_layer_data *layer_data = layer;
730 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
731 RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
733 *info = layer_data->info;
735 return TDM_ERROR_NONE;
739 virtual_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
741 tdm_virtual_layer_data *layer_data = layer;
743 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
744 RETURN_VAL_IF_FAIL(buffer, TDM_ERROR_INVALID_PARAMETER);
746 layer_data->display_buffer = buffer;
747 layer_data->display_buffer_changed = 1;
749 return TDM_ERROR_NONE;
753 virtual_layer_unset_buffer(tdm_layer *layer)
755 tdm_virtual_layer_data *layer_data = layer;
757 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
759 layer_data->display_buffer = NULL;
760 layer_data->display_buffer_changed = 1;
762 return TDM_ERROR_NONE;
766 virtual_display_voutput_create(tdm_backend_data *bdata, const char *name, tdm_error *error)
768 tdm_virtual_data *virtual_data = bdata;
769 tdm_virtual_voutput_data *voutput_data = NULL;
770 tdm_virtual_output_data *output_data = NULL;
771 tdm_virtual_layer_data *layer_data = NULL;
773 if (!virtual_data || !name) {
774 TDM_ERR("invalid parameter");
775 if (error) *error = TDM_ERROR_INVALID_PARAMETER;
779 voutput_data = calloc(1, sizeof(tdm_virtual_voutput_data));
781 TDM_ERR("alloc failed");
782 if (error) *error = TDM_ERROR_OUT_OF_MEMORY;
786 voutput_data->output_modes = calloc(1, sizeof(tdm_output_mode));
787 if (!voutput_data->output_modes) {
788 TDM_ERR("alloc failed");
793 snprintf(voutput_data->output_modes->name, TDM_NAME_LEN, "640x480");
794 voutput_data->output_modes->vrefresh = 30;
795 voutput_data->output_modes->clock = 25200;
796 voutput_data->output_modes->hdisplay = 640;
797 voutput_data->output_modes->hsync_start = 656;
798 voutput_data->output_modes->hsync_end = 752;
799 voutput_data->output_modes->htotal = 800;
800 voutput_data->output_modes->hskew = 0;
801 voutput_data->output_modes->vdisplay = 480;
802 voutput_data->output_modes->vsync_start = 490;
803 voutput_data->output_modes->vsync_end = 492;
804 voutput_data->output_modes->vtotal = 525;
805 voutput_data->output_modes->vscan = 0;
806 voutput_data->output_modes->flags = 0;
807 voutput_data->output_modes->type = 0;
808 voutput_data->mode_count = 1;
810 voutput_data->mmwidth = 10;
811 voutput_data->mmheight = 10;
813 voutput_data->virtual_data = virtual_data;
815 output_data = calloc(1, sizeof(tdm_virtual_output_data));
817 TDM_ERR("alloc failed");
820 voutput_data->output_data = output_data;
822 LIST_INITHEAD(&output_data->layer_list);
824 output_data->virtual_data = virtual_data;
825 output_data->voutput_data = voutput_data;
826 output_data->pipe = 0;
827 output_data->connector_type = TDM_OUTPUT_TYPE_Unknown;
828 output_data->status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
830 snprintf(voutput_data->name, TDM_NAME_LEN, "%s", name);
831 snprintf(output_data->name, TDM_NAME_LEN, "%s", name);
833 output_data->timer = tdm_event_loop_add_timer_handler(virtual_data->dpy,
834 _tdm_virtual_display_cb_timeout,
837 if (!output_data->timer) goto create_fail;
839 LIST_INITHEAD(&output_data->timer_event_list);
841 /* The TDM virtual backend output support only one layer. */
842 layer_data = calloc(1, sizeof(tdm_virtual_layer_data));
844 TDM_ERR("alloc failed");
848 layer_data->virtual_data = virtual_data;
849 layer_data->output_data = output_data;
850 layer_data->zpos = 0;
852 layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY | TDM_LAYER_CAPABILITY_GRAPHIC;
853 output_data->primary_layer = layer_data;
855 LIST_ADDTAIL(&voutput_data->link, &virtual_data->voutput_list);
856 LIST_ADDTAIL(&output_data->link, &virtual_data->output_list);
857 LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
859 if (error) *error = TDM_ERROR_NONE;
861 TDM_DBG("virtual output create(%s)(%p)(%p)", output_data->name, voutput_data, output_data);
863 if (output_data->virtual_data->hwc_mode)
864 output_data->hwc_enable = 1;
869 if (output_data) free(output_data);
870 if (voutput_data->output_modes) free(voutput_data->output_modes);
871 if (voutput_data) free(voutput_data);
873 if (error) *error = TDM_ERROR_OUT_OF_MEMORY;
879 virtual_voutput_destroy(tdm_voutput *voutput)
881 tdm_virtual_data *virtual_data = NULL;
882 tdm_virtual_voutput_data *vo = NULL, *voutput_data = voutput;
885 RETURN_VAL_IF_FAIL(voutput_data, TDM_ERROR_INVALID_PARAMETER);
887 virtual_data = voutput_data->virtual_data;
889 LIST_FOR_EACH_ENTRY(vo, &virtual_data->voutput_list, link) {
890 if (vo == voutput_data) {
897 tdm_virtual_layer_data *l = NULL, *ll = NULL;
898 tdm_virtual_output_data *output_data = NULL;
900 TDM_DBG("virtual output destroy(%s)", voutput_data->name);
902 output_data = voutput_data->output_data;
904 if (!LIST_IS_EMPTY(&output_data->timer_event_list)) {
905 tdm_virtual_event_data *e = NULL, *ee = NULL;
906 LIST_FOR_EACH_ENTRY_SAFE(e, ee, &output_data->timer_event_list, link) {
912 if (output_data->timer)
913 tdm_event_loop_source_remove(output_data->timer);
915 LIST_FOR_EACH_ENTRY_SAFE(l, ll, &output_data->layer_list, link) {
920 LIST_DEL(&output_data->link);
923 if (voutput_data->output_modes)
924 free(voutput_data->output_modes);
925 LIST_DEL(&voutput_data->link);
928 return TDM_ERROR_INVALID_PARAMETER;
930 return TDM_ERROR_NONE;
934 virtual_voutput_get_output(tdm_voutput *voutput, tdm_error *error)
936 tdm_virtual_voutput_data *voutput_data = voutput;
939 if (error) *error = TDM_ERROR_INVALID_PARAMETER;
943 if (error) *error = TDM_ERROR_NONE;
945 return voutput_data->output_data;
949 virtual_voutput_set_commit_func(tdm_voutput *voutput, tdm_voutput_commit_handler commit_func)
951 tdm_virtual_voutput_data *voutput_data = voutput;
953 RETURN_VAL_IF_FAIL(voutput_data, TDM_ERROR_INVALID_PARAMETER);
955 voutput_data->vcommit_func = commit_func;
957 return TDM_ERROR_NONE;
961 virtual_voutput_commit_done(tdm_voutput *voutput)
963 tdm_virtual_voutput_data *voutput_data = voutput;
964 tdm_virtual_output_data *output_data = NULL;
965 unsigned int tv_sec, tv_usec;
966 static unsigned int sequence = 0;
967 tdm_virtual_event_data *event_data;
968 tdm_error ret = TDM_ERROR_NONE;
970 RETURN_VAL_IF_FAIL(voutput_data, TDM_ERROR_INVALID_PARAMETER);
971 output_data = voutput_data->output_data;
975 _tdm_virtual_get_current_time(&tv_sec, &tv_usec);
977 event_data = calloc(1, sizeof(tdm_virtual_event_data));
979 TDM_ERR("alloc failed");
980 return TDM_ERROR_OUT_OF_MEMORY;
983 event_data->type = TDM_VIRTUAL_EVENT_TYPE_COMMIT;
984 event_data->output_data = output_data;
985 event_data->user_data = output_data->commit_user_data;
987 ret = _tdm_virtual_display_wait_vblank(output_data, 1, event_data);
988 if (ret != TDM_ERROR_NONE) {
993 return TDM_ERROR_NONE;
996 tdm_virtual_layer_data *
997 virtual_output_data_get_layer_data(tdm_virtual_output_data *output_data, int layer_zpos)
999 tdm_virtual_layer_data *l = NULL;
1001 RETURN_VAL_IF_FAIL(output_data, NULL);
1003 LIST_FOR_EACH_ENTRY(l, &output_data->layer_list, link) {
1004 if (l->zpos == layer_zpos)