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_mode;
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->output_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->output_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_mode);
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_mode = calloc(1, sizeof(tdm_output_mode));
245 if (!output_data->output_mode) {
246 TDM_ERR("alloc failed");
248 ret = TDM_ERROR_OUT_OF_MEMORY;
252 snprintf(output_data->output_mode->name, TDM_NAME_LEN, "640x480");
253 output_data->output_mode->vrefresh = 30;
254 output_data->output_mode->clock = 25200;
255 output_data->output_mode->hdisplay = 640;
256 output_data->output_mode->hsync_start = 656;
257 output_data->output_mode->hsync_end = 752;
258 output_data->output_mode->htotal = 800;
259 output_data->output_mode->hskew = 0;
260 output_data->output_mode->vdisplay = 480;
261 output_data->output_mode->vsync_start = 490;
262 output_data->output_mode->vsync_end = 492;
263 output_data->output_mode->vtotal = 525;
264 output_data->output_mode->vscan = 0;
265 output_data->output_mode->flags = 0;
266 output_data->output_mode->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_mode = calloc(1, sizeof(tdm_output_mode));
394 if (!output_data->output_mode) {
395 TDM_ERR("alloc failed");
396 ret = TDM_ERROR_OUT_OF_MEMORY;
400 snprintf(output_data->output_mode->name, TDM_NAME_LEN, "640x480");
401 output_data->output_mode->vrefresh = 30;
402 output_data->output_mode->clock = 25200;
403 output_data->output_mode->hdisplay = 640;
404 output_data->output_mode->hsync_start = 656;
405 output_data->output_mode->hsync_end = 752;
406 output_data->output_mode->htotal = 800;
407 output_data->output_mode->hskew = 0;
408 output_data->output_mode->vdisplay = 480;
409 output_data->output_mode->vsync_start = 490;
410 output_data->output_mode->vsync_end = 492;
411 output_data->output_mode->vtotal = 525;
412 output_data->output_mode->vscan = 0;
413 output_data->output_mode->flags = 0;
414 output_data->output_mode->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_mode) free(output_data->output_mode);
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 tdm_backend_unregister_output(virtual_data->dpy, output);
480 return TDM_ERROR_INVALID_PARAMETER;
482 return TDM_ERROR_NONE;
486 virtual_output_get_capability(tdm_output *output, tdm_caps_output *caps)
488 tdm_virtual_output_data *output_data = output;
491 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
492 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
494 memset(caps, 0, sizeof(tdm_caps_output));
496 snprintf(caps->maker, TDM_NAME_LEN, "virtual");
497 snprintf(caps->model, TDM_NAME_LEN, "virtual");
498 snprintf(caps->name, TDM_NAME_LEN, "%s", output_data->name);
500 caps->status = output_data->status;
501 caps->type = output_data->connector_type;
504 caps->mode_count = output_data->mode_count;
505 if (output_data->mode_count != 0) {
506 caps->modes = calloc(output_data->mode_count, sizeof(tdm_output_mode));
508 ret = TDM_ERROR_OUT_OF_MEMORY;
509 TDM_ERR("alloc failed\n");
513 *caps->modes = *output_data->output_mode;
516 caps->mmWidth = output_data->mmwidth;
517 caps->mmHeight =output_data->mmheight;
524 caps->preferred_align = -1;
526 caps->prop_count = 0;
528 return TDM_ERROR_NONE;
530 memset(caps, 0, sizeof(tdm_caps_output));
535 virtual_output_get_layers(tdm_output *output, int *count, tdm_error *error)
537 tdm_virtual_output_data *output_data = output;
538 tdm_virtual_layer_data *layer_data = NULL;
543 RETURN_VAL_IF_FAIL(output_data, NULL);
544 RETURN_VAL_IF_FAIL(count, NULL);
547 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
551 ret = TDM_ERROR_NONE;
555 /* will be freed in frontend */
556 layers = calloc(*count, sizeof(tdm_virtual_layer_data *));
558 TDM_ERR("failed: alloc memory");
560 ret = TDM_ERROR_OUT_OF_MEMORY;
565 LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
566 layers[i++] = layer_data;
569 *error = TDM_ERROR_NONE;
579 virtual_output_wait_vblank(tdm_output *output, int interval, int sync, void *user_data)
581 tdm_virtual_output_data *output_data = output;
582 tdm_virtual_event_data *event_data;
585 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
587 event_data = calloc(1, sizeof(tdm_virtual_event_data));
589 TDM_ERR("alloc failed");
590 return TDM_ERROR_OUT_OF_MEMORY;
593 event_data->type = TDM_VIRTUAL_EVENT_TYPE_WAIT;
594 event_data->output_data = output_data;
595 event_data->user_data = user_data;
597 ret = _tdm_virtual_display_wait_vblank(output_data, interval, event_data);
598 if (ret != TDM_ERROR_NONE) {
603 return TDM_ERROR_NONE;
607 virtual_output_set_vblank_handler(tdm_output *output, tdm_output_vblank_handler func)
609 tdm_virtual_output_data *output_data = output;
611 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
612 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
614 output_data->vblank_func = func;
616 return TDM_ERROR_NONE;
620 virtual_output_commit(tdm_output *output, int sync, void *user_data)
622 tdm_virtual_output_data *output_data = output;
623 tdm_virtual_event_data *event_data;
626 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
628 event_data = calloc(1, sizeof(tdm_virtual_event_data));
630 TDM_ERR("alloc failed");
631 return TDM_ERROR_OUT_OF_MEMORY;
634 event_data->type = TDM_VIRTUAL_EVENT_TYPE_COMMIT;
635 event_data->output_data = output_data;
636 event_data->user_data = user_data;
638 ret = _tdm_virtual_display_wait_vblank(output_data, 1, event_data);
639 if (ret != TDM_ERROR_NONE) {
644 return TDM_ERROR_NONE;
648 virtual_output_set_commit_handler(tdm_output *output, tdm_output_commit_handler func)
650 tdm_virtual_output_data *output_data = output;
652 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
653 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
655 output_data->commit_func = func;
657 return TDM_ERROR_NONE;
661 virtual_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
663 tdm_virtual_output_data *output_data = output;
665 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
666 RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
668 output_data->current_mode = mode;
669 output_data->mode_changed = 1;
671 return TDM_ERROR_NONE;
675 virtual_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
677 tdm_virtual_output_data *output_data = output;
679 RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
680 RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
682 *mode = output_data->current_mode;
684 return TDM_ERROR_NONE;
688 virtual_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps)
690 tdm_virtual_layer_data *layer_data = layer;
692 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
693 RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER);
695 memset(caps, 0, sizeof(tdm_caps_layer));
697 caps->capabilities = layer_data->capabilities;
698 caps->zpos = layer_data->zpos;
700 caps->format_count = 2;
701 caps->formats = calloc(caps->format_count, sizeof(tbm_format));
702 if (!caps->formats) {
703 TDM_ERR("alloc failed\n");
705 memset(caps, 0, sizeof(tdm_caps_layer));
706 return TDM_ERROR_OUT_OF_MEMORY;
709 caps->formats[0] = TBM_FORMAT_ARGB8888;
710 caps->formats[1] = TBM_FORMAT_XRGB8888;
712 caps->prop_count = 0;
714 return TDM_ERROR_NONE;
718 virtual_layer_set_info(tdm_layer *layer, tdm_info_layer *info)
720 tdm_virtual_layer_data *layer_data = layer;
722 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
723 RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
725 layer_data->info = *info;
726 layer_data->info_changed = 1;
728 return TDM_ERROR_NONE;
732 virtual_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
734 tdm_virtual_layer_data *layer_data = layer;
736 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
737 RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
739 *info = layer_data->info;
741 return TDM_ERROR_NONE;
745 virtual_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
747 tdm_virtual_layer_data *layer_data = layer;
749 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
750 RETURN_VAL_IF_FAIL(buffer, TDM_ERROR_INVALID_PARAMETER);
752 layer_data->display_buffer = buffer;
753 layer_data->display_buffer_changed = 1;
755 return TDM_ERROR_NONE;
759 virtual_layer_unset_buffer(tdm_layer *layer)
761 tdm_virtual_layer_data *layer_data = layer;
763 RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
765 layer_data->display_buffer = NULL;
766 layer_data->display_buffer_changed = 1;
768 return TDM_ERROR_NONE;