5 #include "tdm_virtual.h"
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;
12 TDM_VIRTUAL_EVENT_TYPE_WAIT,
13 TDM_VIRTUAL_EVENT_TYPE_COMMIT,
14 } tdm_virtual_event_type;
16 struct _tdm_virtual_event_data {
17 struct list_head link;
19 tdm_virtual_event_type type;
20 tdm_virtual_output_data *output_data;
24 struct _tdm_virtual_output_data {
25 struct list_head link;
27 /* data which are fixed at initializing */
28 tdm_virtual_data *virtual_data;
31 tdm_output_mode *output_modes;
33 tdm_output_type connector_type;
34 struct list_head layer_list;
35 tdm_virtual_layer_data *primary_layer;
37 /* not fixed data below */
38 tdm_output_vblank_handler vblank_func;
39 tdm_output_commit_handler commit_func;
41 tdm_output_conn_status status;
44 const tdm_output_mode *current_mode;
46 tdm_event_loop_source *timer;
47 unsigned int timer_waiting;
48 struct list_head timer_event_list;
51 unsigned int mmheight;
53 char name[TDM_NAME_LEN]; /**< The output name */
56 struct _tdm_virtual_layer_data {
57 struct list_head link;
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;
65 /* not fixed data below */
69 tbm_surface_h display_buffer;
70 int display_buffer_changed;
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)
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);
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);
92 _tdm_virtual_display_cb_timeout(void *user_data)
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;
102 if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) {
104 tv_usec = tp.tv_nsec / 1000;
106 tv_sec = tv_usec = 0;
109 LIST_FOR_EACH_ENTRY_SAFE(e, ee, &output_data->timer_event_list, link) {
111 _tdm_virtual_display_cb_event(output_data, e, sequence, tv_sec, tv_usec);
115 return TDM_ERROR_NONE;
119 _tdm_virtual_display_wait_vblank(tdm_virtual_output_data *output_data, int interval, tdm_virtual_event_data *event_data)
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);
127 if (output_data->timer_waiting) {
128 LIST_ADDTAIL(&event_data->link, &output_data->timer_event_list);
129 return TDM_ERROR_NONE;
132 ms = ((double)1000.0 / output_data->current_mode->vrefresh) * interval;
134 ret = tdm_event_loop_source_timer_update(output_data->timer, ms);
135 if (ret != TDM_ERROR_NONE)
138 LIST_ADDTAIL(&event_data->link, &output_data->timer_event_list);
140 return TDM_ERROR_NONE;
144 _tdm_virtual_display_destroy_layer_list(tdm_virtual_data *virtual_data)
146 tdm_virtual_output_data *o = NULL;
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) {
158 tdm_virtual_display_create_layer_list(tdm_virtual_data *virtual_data)
160 tdm_virtual_output_data *output_data = NULL;
161 tdm_error ret = TDM_ERROR_NONE;
163 if (LIST_IS_EMPTY(&virtual_data->output_list)) {
164 TDM_ERR("no output");
165 return TDM_ERROR_OPERATION_FAILED;
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));
172 TDM_ERR("alloc failed");
173 ret = TDM_ERROR_OUT_OF_MEMORY;
177 layer_data->virtual_data = virtual_data;
178 layer_data->output_data = output_data;
179 layer_data->zpos = 0;
181 layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY | TDM_LAYER_CAPABILITY_GRAPHIC;
182 output_data->primary_layer = layer_data;
184 LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
187 return TDM_ERROR_NONE;
189 _tdm_virtual_display_destroy_layer_list(virtual_data);
194 tdm_virtual_display_destroy_output_list(tdm_virtual_data *virtual_data)
196 tdm_virtual_output_data *o = NULL, *oo = NULL;
198 if (LIST_IS_EMPTY(&virtual_data->output_list))
201 _tdm_virtual_display_destroy_layer_list(virtual_data);
203 LIST_FOR_EACH_ENTRY_SAFE(o, oo, &virtual_data->output_list, link) {
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) {
215 tdm_event_loop_source_remove(o->timer);
217 free(o->output_modes);
223 tdm_virtual_display_create_output_list(tdm_virtual_data *virtual_data)
225 tdm_virtual_output_data *output_data;
228 RETURN_VAL_IF_FAIL(LIST_IS_EMPTY(&virtual_data->output_list), TDM_ERROR_OPERATION_FAILED);
230 output_data = calloc(1, sizeof(tdm_virtual_output_data));
232 TDM_ERR("alloc failed");
233 ret = TDM_ERROR_OUT_OF_MEMORY;
237 LIST_INITHEAD(&output_data->layer_list);
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;
244 output_data->output_modes = calloc(1, sizeof(tdm_output_mode));
245 if (!output_data->output_modes) {
246 TDM_ERR("alloc failed");
248 ret = TDM_ERROR_OUT_OF_MEMORY;
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;
268 output_data->timer = tdm_event_loop_add_timer_handler(virtual_data->dpy,
269 _tdm_virtual_display_cb_timeout,
272 if (!output_data->timer) {
277 LIST_INITHEAD(&output_data->timer_event_list);
279 LIST_ADDTAIL(&output_data->link, &virtual_data->output_list);
281 return TDM_ERROR_NONE;
283 tdm_virtual_display_destroy_output_list(virtual_data);
288 virtual_display_get_capability(tdm_backend_data *bdata, tdm_caps_display *caps)
290 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
292 caps->max_layer_count = -1; /* not defined */
294 return TDM_ERROR_NONE;
298 virtual_display_get_outputs(tdm_backend_data *bdata, int *count, tdm_error *error)
300 tdm_virtual_data *virtual_data = bdata;
301 tdm_virtual_output_data *output_data = NULL;
302 tdm_output **outputs;
306 RETURN_VAL_IF_FAIL(virtual_data, NULL);
307 RETURN_VAL_IF_FAIL(count, NULL);
310 LIST_FOR_EACH_ENTRY(output_data, &virtual_data->output_list, link)
314 ret = TDM_ERROR_NONE;
318 /* will be freed in frontend */
319 outputs = calloc(*count, sizeof(tdm_virtual_output_data *));
321 TDM_ERR("failed: alloc memory");
323 ret = TDM_ERROR_OUT_OF_MEMORY;
328 LIST_FOR_EACH_ENTRY(output_data, &virtual_data->output_list, link)
329 outputs[i++] = output_data;
332 *error = TDM_ERROR_NONE;
342 virtual_display_get_fd(tdm_backend_data *bdata, int *fd)
344 tdm_virtual_data *virtual_data = bdata;
346 RETURN_VAL_IF_FAIL(virtual_data, TDM_ERROR_INVALID_PARAMETER);
347 RETURN_VAL_IF_FAIL(fd, TDM_ERROR_INVALID_PARAMETER);
349 *fd = virtual_data->pipe[0];
351 return TDM_ERROR_NONE;
355 virtual_display_handle_events(tdm_backend_data *bdata)
357 return TDM_ERROR_NONE;
361 virtual_display_output_create(tdm_backend_data *bdata, const char *name, tdm_error *error)
363 tdm_virtual_data *virtual_data = bdata;
364 tdm_virtual_output_data *output_data = NULL;
365 tdm_virtual_layer_data *layer_data = NULL;
368 if (!virtual_data || !name) {
369 TDM_ERR("invalid parameter");
370 *error = TDM_ERROR_INVALID_PARAMETER;
374 output_data = calloc(1, sizeof(tdm_virtual_output_data));
376 TDM_ERR("alloc failed");
377 *error = TDM_ERROR_OUT_OF_MEMORY;
381 LIST_INITHEAD(&output_data->layer_list);
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;
389 snprintf(output_data->name, TDM_NAME_LEN, "%s", name);
391 snprintf(output_data->name, TDM_NAME_LEN, "unknown");
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;
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;
416 output_data->mode_count = 1;
418 output_data->timer = tdm_event_loop_add_timer_handler(virtual_data->dpy,
419 _tdm_virtual_display_cb_timeout,
422 if (!output_data->timer) goto create_fail;
424 LIST_INITHEAD(&output_data->timer_event_list);
426 /* The TDM virtual backend output support only one layer. */
427 layer_data = calloc(1, sizeof(tdm_virtual_layer_data));
429 TDM_ERR("alloc failed");
430 ret = TDM_ERROR_OUT_OF_MEMORY;
434 layer_data->virtual_data = virtual_data;
435 layer_data->output_data = output_data;
436 layer_data->zpos = 0;
438 layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY | TDM_LAYER_CAPABILITY_GRAPHIC;
439 output_data->primary_layer = layer_data;
441 LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
443 ret = tdm_backend_register_output(virtual_data->dpy, output_data);
444 GOTO_IF_FAIL(ret == TDM_ERROR_NONE, create_fail);
446 *error = TDM_ERROR_NONE;
451 if (layer_data) free(layer_data);
452 if (output_data->output_modes) free(output_data->output_modes);
461 virtual_display_output_destroy(tdm_backend_data *bdata, tdm_output *output)
463 tdm_virtual_data *virtual_data = bdata;
464 tdm_virtual_output_data *o, *output_data = output;
467 RETURN_VAL_IF_FAIL(virtual_data, TDM_ERROR_INVALID_PARAMETER);
468 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
470 LIST_FOR_EACH_ENTRY(o, &virtual_data->output_list, link) {
471 if (o == output_data) {
478 if (output_data->output_modes)
479 free(output_data->output_modes);
480 tdm_backend_unregister_output(virtual_data->dpy, output);
483 return TDM_ERROR_INVALID_PARAMETER;
485 return TDM_ERROR_NONE;
489 virtual_output_get_capability(tdm_output *output, tdm_caps_output *caps)
491 tdm_virtual_output_data *output_data = output;
494 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
495 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
497 memset(caps, 0, sizeof(tdm_caps_output));
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);
503 caps->status = output_data->status;
504 caps->type = output_data->connector_type;
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));
511 ret = TDM_ERROR_OUT_OF_MEMORY;
512 TDM_ERR("alloc failed\n");
516 *caps->modes = *output_data->output_modes;
519 caps->mmWidth = output_data->mmwidth;
520 caps->mmHeight =output_data->mmheight;
527 caps->preferred_align = -1;
529 caps->prop_count = 0;
531 return TDM_ERROR_NONE;
533 memset(caps, 0, sizeof(tdm_caps_output));
538 virtual_output_get_layers(tdm_output *output, int *count, tdm_error *error)
540 tdm_virtual_output_data *output_data = output;
541 tdm_virtual_layer_data *layer_data = NULL;
546 RETURN_VAL_IF_FAIL(output_data, NULL);
547 RETURN_VAL_IF_FAIL(count, NULL);
550 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
554 ret = TDM_ERROR_NONE;
558 /* will be freed in frontend */
559 layers = calloc(*count, sizeof(tdm_virtual_layer_data *));
561 TDM_ERR("failed: alloc memory");
563 ret = TDM_ERROR_OUT_OF_MEMORY;
568 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
569 layers[i++] = layer_data;
572 *error = TDM_ERROR_NONE;
582 virtual_output_wait_vblank(tdm_output *output, int interval, int sync, void *user_data)
584 tdm_virtual_output_data *output_data = output;
585 tdm_virtual_event_data *event_data;
588 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
590 event_data = calloc(1, sizeof(tdm_virtual_event_data));
592 TDM_ERR("alloc failed");
593 return TDM_ERROR_OUT_OF_MEMORY;
596 event_data->type = TDM_VIRTUAL_EVENT_TYPE_WAIT;
597 event_data->output_data = output_data;
598 event_data->user_data = user_data;
600 ret = _tdm_virtual_display_wait_vblank(output_data, interval, event_data);
601 if (ret != TDM_ERROR_NONE) {
606 return TDM_ERROR_NONE;
610 virtual_output_set_vblank_handler(tdm_output *output, tdm_output_vblank_handler func)
612 tdm_virtual_output_data *output_data = output;
614 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
615 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
617 output_data->vblank_func = func;
619 return TDM_ERROR_NONE;
623 virtual_output_commit(tdm_output *output, int sync, void *user_data)
625 tdm_virtual_output_data *output_data = output;
626 tdm_virtual_event_data *event_data;
629 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
631 event_data = calloc(1, sizeof(tdm_virtual_event_data));
633 TDM_ERR("alloc failed");
634 return TDM_ERROR_OUT_OF_MEMORY;
637 event_data->type = TDM_VIRTUAL_EVENT_TYPE_COMMIT;
638 event_data->output_data = output_data;
639 event_data->user_data = user_data;
641 ret = _tdm_virtual_display_wait_vblank(output_data, 1, event_data);
642 if (ret != TDM_ERROR_NONE) {
647 return TDM_ERROR_NONE;
651 virtual_output_set_commit_handler(tdm_output *output, tdm_output_commit_handler func)
653 tdm_virtual_output_data *output_data = output;
655 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
656 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
658 output_data->commit_func = func;
660 return TDM_ERROR_NONE;
664 virtual_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
666 tdm_virtual_output_data *output_data = output;
668 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
669 RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
671 output_data->current_mode = mode;
672 output_data->mode_changed = 1;
674 return TDM_ERROR_NONE;
678 virtual_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
680 tdm_virtual_output_data *output_data = output;
682 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
683 RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
685 *mode = output_data->current_mode;
687 return TDM_ERROR_NONE;
691 virtual_output_set_available_mode(tdm_output *output, const tdm_output_mode *modes, int count)
693 tdm_virtual_output_data *output_data = output;
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);
699 /* set available mode only permittied disconnect status */
700 RETURN_VAL_IF_FAIL(output_data->status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED, TDM_ERROR_BUSY);
702 if (output_data->output_modes)
703 free(output_data->output_modes);
704 output_data->output_modes = NULL;
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);
709 memcpy(output_data->output_modes, modes, count * sizeof(tdm_output_mode));
710 output_data->mode_count = count;
712 return TDM_ERROR_NONE;
716 virtual_output_set_physical_size(tdm_output *output, unsigned int mmwidth, unsigned int mmheight)
718 tdm_virtual_output_data *output_data = output;
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);
724 output_data->mmwidth = mmwidth;
725 output_data->mmheight = mmheight;
727 return TDM_ERROR_NONE;
731 virtual_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps)
733 tdm_virtual_layer_data *layer_data = layer;
735 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
736 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
738 memset(caps, 0, sizeof(tdm_caps_layer));
740 caps->capabilities = layer_data->capabilities;
741 caps->zpos = layer_data->zpos;
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");
748 memset(caps, 0, sizeof(tdm_caps_layer));
749 return TDM_ERROR_OUT_OF_MEMORY;
752 caps->formats[0] = TBM_FORMAT_ARGB8888;
753 caps->formats[1] = TBM_FORMAT_XRGB8888;
755 caps->prop_count = 0;
757 return TDM_ERROR_NONE;
761 virtual_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
763 tdm_virtual_layer_data *layer_data = layer;
765 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
766 RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
768 layer_data->info = *info;
769 layer_data->info_changed = 1;
771 return TDM_ERROR_NONE;
775 virtual_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
777 tdm_virtual_layer_data *layer_data = layer;
779 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
780 RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
782 *info = layer_data->info;
784 return TDM_ERROR_NONE;
788 virtual_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
790 tdm_virtual_layer_data *layer_data = layer;
792 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
793 RETURN_VAL_IF_FAIL(buffer, TDM_ERROR_INVALID_PARAMETER);
795 layer_data->display_buffer = buffer;
796 layer_data->display_buffer_changed = 1;
798 return TDM_ERROR_NONE;
802 virtual_layer_unset_buffer(tdm_layer *layer)
804 tdm_virtual_layer_data *layer_data = layer;
806 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
808 layer_data->display_buffer = NULL;
809 layer_data->display_buffer_changed = 1;
811 return TDM_ERROR_NONE;