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;
42 tdm_output_status_handler status_func;
43 void *status_user_data;
46 const tdm_output_mode *current_mode;
48 tdm_event_loop_source *timer;
49 unsigned int timer_waiting;
50 struct list_head timer_event_list;
53 unsigned int mmheight;
55 char name[TDM_NAME_LEN]; /**< The output name */
58 struct _tdm_virtual_layer_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;
64 tdm_layer_capability capabilities;
67 /* not fixed data below */
71 tbm_surface_h display_buffer;
72 int display_buffer_changed;
76 _tdm_virtual_display_cb_event(tdm_virtual_output_data *output_data, tdm_virtual_event_data *event_data,
77 unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec)
79 switch (event_data->type) {
80 case TDM_VIRTUAL_EVENT_TYPE_WAIT:
81 if (output_data->vblank_func)
82 output_data->vblank_func(output_data, sequence, tv_sec, tv_usec, event_data->user_data);
84 case TDM_VIRTUAL_EVENT_TYPE_COMMIT:
85 if (output_data->commit_func)
86 output_data->commit_func(output_data, sequence, tv_sec, tv_usec, event_data->user_data);
94 _tdm_virtual_display_cb_timeout(void *user_data)
96 tdm_virtual_output_data *output_data = user_data;
97 tdm_virtual_event_data *e = NULL, *ee = NULL;
98 unsigned int tv_sec, tv_usec;
99 static unsigned int sequence = 0;
104 if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) {
106 tv_usec = tp.tv_nsec / 1000;
108 tv_sec = tv_usec = 0;
111 LIST_FOR_EACH_ENTRY_SAFE(e, ee, &output_data->timer_event_list, link) {
113 _tdm_virtual_display_cb_event(output_data, e, sequence, tv_sec, tv_usec);
117 return TDM_ERROR_NONE;
121 _tdm_virtual_display_wait_vblank(tdm_virtual_output_data *output_data, int interval, tdm_virtual_event_data *event_data)
126 RETURN_VAL_IF_FAIL(output_data->timer != NULL, TDM_ERROR_OPERATION_FAILED);
127 RETURN_VAL_IF_FAIL(output_data->current_mode->vrefresh > 0, TDM_ERROR_OPERATION_FAILED);
129 if (output_data->timer_waiting) {
130 LIST_ADDTAIL(&event_data->link, &output_data->timer_event_list);
131 return TDM_ERROR_NONE;
134 ms = ((double)1000.0 / output_data->current_mode->vrefresh) * interval;
136 ret = tdm_event_loop_source_timer_update(output_data->timer, ms);
137 if (ret != TDM_ERROR_NONE)
140 LIST_ADDTAIL(&event_data->link, &output_data->timer_event_list);
142 return TDM_ERROR_NONE;
146 _tdm_virtual_display_destroy_layer_list(tdm_virtual_data *virtual_data)
148 tdm_virtual_output_data *o = NULL;
150 LIST_FOR_EACH_ENTRY(o, &virtual_data->output_list, link) {
151 tdm_virtual_layer_data *l = NULL, *ll = NULL;
152 LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) {
160 tdm_virtual_display_destroy_output_list(tdm_virtual_data *virtual_data)
162 tdm_virtual_output_data *o = NULL, *oo = NULL;
164 if (LIST_IS_EMPTY(&virtual_data->output_list))
167 _tdm_virtual_display_destroy_layer_list(virtual_data);
169 LIST_FOR_EACH_ENTRY_SAFE(o, oo, &virtual_data->output_list, link) {
172 if (!LIST_IS_EMPTY(&o->timer_event_list)) {
173 tdm_virtual_event_data *e = NULL, *ee = NULL;
174 LIST_FOR_EACH_ENTRY_SAFE(e, ee, &o->timer_event_list, link) {
181 tdm_event_loop_source_remove(o->timer);
184 free(o->output_modes);
190 virtual_display_get_capability(tdm_backend_data *bdata, tdm_caps_display *caps)
192 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
194 caps->max_layer_count = -1; /* not defined */
196 return TDM_ERROR_NONE;
200 virtual_display_get_outputs(tdm_backend_data *bdata, int *count, tdm_error *error)
202 tdm_virtual_data *virtual_data = bdata;
203 tdm_virtual_output_data *output_data = NULL;
204 tdm_output **outputs;
208 RETURN_VAL_IF_FAIL(virtual_data, NULL);
209 RETURN_VAL_IF_FAIL(count, NULL);
212 LIST_FOR_EACH_ENTRY(output_data, &virtual_data->output_list, link)
216 ret = TDM_ERROR_NONE;
220 /* will be freed in frontend */
221 outputs = calloc(*count, sizeof(tdm_virtual_output_data *));
223 TDM_ERR("failed: alloc memory");
225 ret = TDM_ERROR_OUT_OF_MEMORY;
230 LIST_FOR_EACH_ENTRY(output_data, &virtual_data->output_list, link)
231 outputs[i++] = output_data;
234 *error = TDM_ERROR_NONE;
244 virtual_display_get_fd(tdm_backend_data *bdata, int *fd)
246 tdm_virtual_data *virtual_data = bdata;
248 RETURN_VAL_IF_FAIL(virtual_data, TDM_ERROR_INVALID_PARAMETER);
249 RETURN_VAL_IF_FAIL(fd, TDM_ERROR_INVALID_PARAMETER);
251 *fd = virtual_data->pipe[0];
253 return TDM_ERROR_NONE;
257 virtual_display_handle_events(tdm_backend_data *bdata)
259 return TDM_ERROR_NONE;
263 virtual_display_output_create(tdm_backend_data *bdata, const char *name, tdm_error *error)
265 tdm_virtual_data *virtual_data = bdata;
266 tdm_virtual_output_data *output_data = NULL;
267 tdm_virtual_layer_data *layer_data = NULL;
270 if (!virtual_data || !name) {
271 TDM_ERR("invalid parameter");
272 *error = TDM_ERROR_INVALID_PARAMETER;
276 output_data = calloc(1, sizeof(tdm_virtual_output_data));
278 TDM_ERR("alloc failed");
279 *error = TDM_ERROR_OUT_OF_MEMORY;
283 LIST_INITHEAD(&output_data->layer_list);
285 output_data->virtual_data = virtual_data;
286 output_data->pipe = 0;
287 output_data->connector_type = TDM_OUTPUT_TYPE_Unknown;
288 output_data->status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
291 snprintf(output_data->name, TDM_NAME_LEN, "%s", name);
293 snprintf(output_data->name, TDM_NAME_LEN, "unknown");
295 output_data->output_modes = calloc(1, sizeof(tdm_output_mode));
296 if (!output_data->output_modes) {
297 TDM_ERR("alloc failed");
298 ret = TDM_ERROR_OUT_OF_MEMORY;
303 snprintf(output_data->output_modes->name, TDM_NAME_LEN, "640x480");
304 output_data->output_modes->vrefresh = 30;
305 output_data->output_modes->clock = 25200;
306 output_data->output_modes->hdisplay = 640;
307 output_data->output_modes->hsync_start = 656;
308 output_data->output_modes->hsync_end = 752;
309 output_data->output_modes->htotal = 800;
310 output_data->output_modes->hskew = 0;
311 output_data->output_modes->vdisplay = 480;
312 output_data->output_modes->vsync_start = 490;
313 output_data->output_modes->vsync_end = 492;
314 output_data->output_modes->vtotal = 525;
315 output_data->output_modes->vscan = 0;
316 output_data->output_modes->flags = 0;
317 output_data->output_modes->type = 0;
318 output_data->mode_count = 1;
320 output_data->timer = tdm_event_loop_add_timer_handler(virtual_data->dpy,
321 _tdm_virtual_display_cb_timeout,
324 if (!output_data->timer) goto create_fail;
326 LIST_INITHEAD(&output_data->timer_event_list);
328 /* The TDM virtual backend output support only one layer. */
329 layer_data = calloc(1, sizeof(tdm_virtual_layer_data));
331 TDM_ERR("alloc failed");
332 ret = TDM_ERROR_OUT_OF_MEMORY;
336 layer_data->virtual_data = virtual_data;
337 layer_data->output_data = output_data;
338 layer_data->zpos = 0;
340 layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY | TDM_LAYER_CAPABILITY_GRAPHIC;
341 output_data->primary_layer = layer_data;
343 LIST_ADDTAIL(&output_data->link, &virtual_data->output_list);
344 LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
346 ret = tdm_backend_register_output(virtual_data->dpy, output_data);
347 if (ret != TDM_ERROR_NONE) {
348 LIST_DEL(&output_data->link);
352 *error = TDM_ERROR_NONE;
357 if (layer_data) free(layer_data);
358 if (output_data->output_modes) free(output_data->output_modes);
367 virtual_display_output_destroy(tdm_backend_data *bdata, tdm_output *output)
369 tdm_virtual_data *virtual_data = bdata;
370 tdm_virtual_output_data *o, *output_data = output;
373 RETURN_VAL_IF_FAIL(virtual_data, TDM_ERROR_INVALID_PARAMETER);
374 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
376 LIST_FOR_EACH_ENTRY(o, &virtual_data->output_list, link) {
377 if (o == output_data) {
384 tdm_virtual_layer_data *l = NULL, *ll = NULL;
386 tdm_backend_unregister_output(virtual_data->dpy, output);
388 if (!LIST_IS_EMPTY(&o->timer_event_list)) {
389 tdm_virtual_event_data *e = NULL, *ee = NULL;
390 LIST_FOR_EACH_ENTRY_SAFE(e, ee, &o->timer_event_list, link) {
397 tdm_event_loop_source_remove(o->timer);
399 LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) {
404 if (output_data->output_modes)
405 free(output_data->output_modes);
410 return TDM_ERROR_INVALID_PARAMETER;
412 return TDM_ERROR_NONE;
416 virtual_output_get_capability(tdm_output *output, tdm_caps_output *caps)
418 tdm_virtual_output_data *output_data = output;
421 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
422 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
424 memset(caps, 0, sizeof(tdm_caps_output));
426 snprintf(caps->maker, TDM_NAME_LEN, "virtual");
427 snprintf(caps->model, TDM_NAME_LEN, "virtual");
428 snprintf(caps->name, TDM_NAME_LEN, "%s", output_data->name);
430 caps->status = output_data->status;
431 caps->type = output_data->connector_type;
434 if (output_data->status == TDM_OUTPUT_CONN_STATUS_CONNECTED ||
435 output_data->status == TDM_OUTPUT_CONN_STATUS_MODE_SETTED) {
436 caps->mode_count = output_data->mode_count;
437 if (output_data->mode_count != 0) {
438 caps->modes = calloc(output_data->mode_count, sizeof(tdm_output_mode));
440 ret = TDM_ERROR_OUT_OF_MEMORY;
441 TDM_ERR("alloc failed\n");
444 memcpy(caps->modes, output_data->output_modes, output_data->mode_count * sizeof(tdm_output_mode));
447 caps->mmWidth = output_data->mmwidth;
448 caps->mmHeight = output_data->mmheight;
451 caps->mode_count = 0;
461 caps->preferred_align = -1;
463 caps->prop_count = 0;
465 return TDM_ERROR_NONE;
467 memset(caps, 0, sizeof(tdm_caps_output));
472 virtual_output_get_layers(tdm_output *output, int *count, tdm_error *error)
474 tdm_virtual_output_data *output_data = output;
475 tdm_virtual_layer_data *layer_data = NULL;
480 RETURN_VAL_IF_FAIL(output_data, NULL);
481 RETURN_VAL_IF_FAIL(count, NULL);
484 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
488 ret = TDM_ERROR_NONE;
492 /* will be freed in frontend */
493 layers = calloc(*count, sizeof(tdm_virtual_layer_data *));
495 TDM_ERR("failed: alloc memory");
497 ret = TDM_ERROR_OUT_OF_MEMORY;
502 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
503 layers[i++] = layer_data;
506 *error = TDM_ERROR_NONE;
516 virtual_output_wait_vblank(tdm_output *output, int interval, int sync, void *user_data)
518 tdm_virtual_output_data *output_data = output;
519 tdm_virtual_event_data *event_data;
522 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
524 event_data = calloc(1, sizeof(tdm_virtual_event_data));
526 TDM_ERR("alloc failed");
527 return TDM_ERROR_OUT_OF_MEMORY;
530 event_data->type = TDM_VIRTUAL_EVENT_TYPE_WAIT;
531 event_data->output_data = output_data;
532 event_data->user_data = user_data;
534 ret = _tdm_virtual_display_wait_vblank(output_data, interval, event_data);
535 if (ret != TDM_ERROR_NONE) {
540 return TDM_ERROR_NONE;
544 virtual_output_set_vblank_handler(tdm_output *output, tdm_output_vblank_handler func)
546 tdm_virtual_output_data *output_data = output;
548 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
549 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
551 output_data->vblank_func = func;
553 return TDM_ERROR_NONE;
557 virtual_output_commit(tdm_output *output, int sync, void *user_data)
559 tdm_virtual_output_data *output_data = output;
560 tdm_virtual_event_data *event_data;
563 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
565 event_data = calloc(1, sizeof(tdm_virtual_event_data));
567 TDM_ERR("alloc failed");
568 return TDM_ERROR_OUT_OF_MEMORY;
571 event_data->type = TDM_VIRTUAL_EVENT_TYPE_COMMIT;
572 event_data->output_data = output_data;
573 event_data->user_data = user_data;
575 ret = _tdm_virtual_display_wait_vblank(output_data, 1, event_data);
576 if (ret != TDM_ERROR_NONE) {
581 return TDM_ERROR_NONE;
585 virtual_output_set_commit_handler(tdm_output *output, tdm_output_commit_handler func)
587 tdm_virtual_output_data *output_data = output;
589 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
590 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
592 output_data->commit_func = func;
594 return TDM_ERROR_NONE;
598 virtual_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
600 tdm_virtual_output_data *output_data = output;
602 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
603 RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
605 output_data->current_mode = mode;
606 output_data->mode_changed = 1;
608 return TDM_ERROR_NONE;
612 virtual_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
614 tdm_virtual_output_data *output_data = output;
616 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
617 RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
619 *mode = output_data->current_mode;
621 return TDM_ERROR_NONE;
625 virtual_output_set_available_mode(tdm_output *output, const tdm_output_mode *modes, int count)
627 tdm_virtual_output_data *output_data = output;
629 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
630 RETURN_VAL_IF_FAIL(modes, TDM_ERROR_INVALID_PARAMETER);
631 RETURN_VAL_IF_FAIL(count > 0, TDM_ERROR_INVALID_PARAMETER);
633 /* set available mode only permittied disconnect status */
634 RETURN_VAL_IF_FAIL(output_data->status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED, TDM_ERROR_BUSY);
636 if (output_data->output_modes)
637 free(output_data->output_modes);
638 output_data->output_modes = NULL;
640 output_data->output_modes = calloc(1, count * sizeof(tdm_output_mode));
641 RETURN_VAL_IF_FAIL(output_data->output_modes != NULL, TDM_ERROR_OUT_OF_MEMORY);
643 memcpy(output_data->output_modes, modes, count * sizeof(tdm_output_mode));
644 output_data->mode_count = count;
646 return TDM_ERROR_NONE;
650 virtual_output_set_physical_size(tdm_output *output, unsigned int mmwidth, unsigned int mmheight)
652 tdm_virtual_output_data *output_data = output;
654 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
655 RETURN_VAL_IF_FAIL(mmwidth != 0, TDM_ERROR_INVALID_PARAMETER);
656 RETURN_VAL_IF_FAIL(mmheight != 0, TDM_ERROR_INVALID_PARAMETER);
658 output_data->mmwidth = mmwidth;
659 output_data->mmheight = mmheight;
661 return TDM_ERROR_NONE;
665 virtual_output_set_connect(tdm_output *output)
667 tdm_virtual_output_data *output_data = output;
669 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
671 if (output_data->status == TDM_OUTPUT_CONN_STATUS_CONNECTED ||
672 output_data->status == TDM_OUTPUT_CONN_STATUS_MODE_SETTED)
673 return TDM_ERROR_NONE;
675 output_data->status = TDM_OUTPUT_CONN_STATUS_CONNECTED;
677 if (output_data->status_func)
678 output_data->status_func(output_data, output_data->status,
679 output_data->status_user_data);
681 return TDM_ERROR_NONE;
685 virtual_output_set_disconnect(tdm_output *output)
687 tdm_virtual_output_data *output_data = output;
689 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
691 if (output_data->status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED)
692 return TDM_ERROR_NONE;
694 output_data->status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
696 if (output_data->status_func)
697 output_data->status_func(output_data, output_data->status,
698 output_data->status_user_data);
700 return TDM_ERROR_NONE;
704 virtual_output_set_status_handler(tdm_output *output,
705 tdm_output_status_handler func, void *user_data)
707 tdm_virtual_output_data *output_data = output;
709 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
710 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
712 output_data->status_func = func;
713 output_data->status_user_data = user_data;
715 return TDM_ERROR_NONE;
719 virtual_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps)
721 tdm_virtual_layer_data *layer_data = layer;
723 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
724 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
726 memset(caps, 0, sizeof(tdm_caps_layer));
728 caps->capabilities = layer_data->capabilities;
729 caps->zpos = layer_data->zpos;
731 caps->format_count = 2;
732 caps->formats = calloc(caps->format_count, sizeof(tbm_format));
733 if (!caps->formats) {
734 TDM_ERR("alloc failed\n");
736 memset(caps, 0, sizeof(tdm_caps_layer));
737 return TDM_ERROR_OUT_OF_MEMORY;
740 caps->formats[0] = TBM_FORMAT_ARGB8888;
741 caps->formats[1] = TBM_FORMAT_XRGB8888;
743 caps->prop_count = 0;
745 return TDM_ERROR_NONE;
749 virtual_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
751 tdm_virtual_layer_data *layer_data = layer;
753 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
754 RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
756 layer_data->info = *info;
757 layer_data->info_changed = 1;
759 return TDM_ERROR_NONE;
763 virtual_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
765 tdm_virtual_layer_data *layer_data = layer;
767 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
768 RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
770 *info = layer_data->info;
772 return TDM_ERROR_NONE;
776 virtual_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
778 tdm_virtual_layer_data *layer_data = layer;
780 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
781 RETURN_VAL_IF_FAIL(buffer, TDM_ERROR_INVALID_PARAMETER);
783 layer_data->display_buffer = buffer;
784 layer_data->display_buffer_changed = 1;
786 return TDM_ERROR_NONE;
790 virtual_layer_unset_buffer(tdm_layer *layer)
792 tdm_virtual_layer_data *layer_data = layer;
794 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
796 layer_data->display_buffer = NULL;
797 layer_data->display_buffer_changed = 1;
799 return TDM_ERROR_NONE;