2772f8417e4eadb94907788ce3cea579834ec2a1
[platform/core/uifw/libds-tizen.git] / src / libds / backend / tdm / backend.c
1 #include <assert.h>
2 #include <stdlib.h>
3
4 #include "libds/log.h"
5 #include "tdm.h"
6
7 static const struct ds_backend_interface tdm_backend_iface;
8 static void tdm_backend_handle_display_destroy(struct wl_listener *listener,
9         void *data);
10 static void tdm_backend_destroy(struct ds_tdm_backend *tdm);
11 static int tdm_backend_handle_tdm_event(int fd, uint32_t mask, void *data);
12
13 WL_EXPORT struct ds_backend *
14 ds_tdm_backend_create(struct wl_display *display)
15 {
16     struct ds_tdm_backend *tdm;
17     struct wl_event_loop *loop;
18     tdm_error err;
19
20     ds_inf("Initializing TDM backend");
21
22     tdm = calloc(1, sizeof *tdm);
23     if (!tdm)
24         return NULL;
25
26     ds_backend_init(&tdm->base, &tdm_backend_iface);
27
28     tdm->wl_display = display;
29     tdm->clock = CLOCK_MONOTONIC;   // FIXME
30
31     wl_list_init(&tdm->outputs);
32     wl_list_init(&tdm->buffers);
33
34     tdm->tdm_display = tdm_display_init(&err);
35     if (err != TDM_ERROR_NONE) {
36         ds_err("Could not initialize tdm_display");
37         goto err_display;
38     }
39
40     err = tdm_display_get_fd(tdm->tdm_display, &tdm->fd);
41     if (err != TDM_ERROR_NONE || tdm->fd < 0) {
42         ds_err("Could not get fd from tdm_display: err(%d)", err);
43         goto err_fd;
44     }
45
46     loop = wl_display_get_event_loop(display);
47     tdm->tdm_event = wl_event_loop_add_fd(loop, tdm->fd, WL_EVENT_READABLE,
48             tdm_backend_handle_tdm_event, tdm);
49     if (!tdm->tdm_event) {
50         ds_err("could not add fd event handler for tdm event");
51         goto err_event;
52     }
53
54     tdm->display_destroy.notify = tdm_backend_handle_display_destroy;
55     wl_display_add_destroy_listener(display, &tdm->display_destroy);
56
57     return &tdm->base;
58
59 err_event:
60     close(tdm->fd);
61 err_fd:
62     tdm_display_deinit(tdm->tdm_display);
63 err_display:
64     free(tdm);
65
66     return NULL;
67 }
68
69 struct ds_tdm_backend *
70 tdm_backend_from_backend(struct ds_backend *backend)
71 {
72     assert(backend->iface == &tdm_backend_iface);
73     return (struct ds_tdm_backend *)backend;
74 }
75
76 static void
77 tdm_backend_destroy(struct ds_tdm_backend *tdm)
78 {
79     struct ds_tdm_output *output, *tmp_output;
80     struct ds_tdm_buffer *buffer, *tmp_buffer;
81
82     wl_list_for_each_safe(output, tmp_output, &tdm->outputs, link) {
83         ds_output_destroy(&output->base);
84     }
85
86     wl_list_for_each_safe(buffer, tmp_buffer, &tdm->buffers, link) {
87         destroy_tdm_buffer(buffer);
88     }
89
90     wl_list_remove(&tdm->display_destroy.link);
91     wl_event_source_remove(tdm->tdm_event);
92     close(tdm->fd);
93     tdm_display_deinit(tdm->tdm_display);
94     free(tdm);
95 }
96
97 static bool
98 tdm_backend_scan_outputs(struct ds_tdm_backend *tdm)
99 {
100     struct ds_tdm_output *output;
101     tdm_output *tdm_output;
102     tdm_error err;
103     int num_outputs, i;
104
105     err = tdm_display_get_output_count(tdm->tdm_display, &num_outputs);
106     if (err != TDM_ERROR_NONE) {
107         ds_err("Could not get number of outputs: err(%d)", err);
108         return false;
109     }
110
111     for (i = 0; i < num_outputs; i++) {
112         tdm_output = tdm_display_get_output(tdm->tdm_display, i, &err);
113         if (err != TDM_ERROR_NONE || !tdm_output) {
114             ds_err("Could not get output from tdm_display: index(%d) err(%d)",
115                     i, err);
116             continue;
117         }
118
119         output = create_tdm_output(tdm, tdm_output);
120         if (!output) {
121             ds_err("Could not create output: index(%d)", i);
122             continue;
123         }
124
125         wl_list_insert(&tdm->outputs, &output->link);
126
127         wl_signal_emit(&tdm->base.events.new_output, &output->base);
128     }
129
130     return true;
131 }
132
133 static bool
134 tdm_backend_iface_start(struct ds_backend *backend)
135 {
136     struct ds_tdm_backend *tdm;
137
138     tdm = tdm_backend_from_backend(backend);
139     return tdm_backend_scan_outputs(tdm);
140 }
141
142 static void
143 tdm_backend_iface_destroy(struct ds_backend *backend)
144 {
145     struct ds_tdm_backend *tdm;
146
147     tdm = tdm_backend_from_backend(backend);
148     tdm_backend_destroy(tdm);
149 }
150
151 static const struct ds_backend_interface tdm_backend_iface = {
152     .start = tdm_backend_iface_start,
153     .destroy = tdm_backend_iface_destroy,
154     .get_drm_fd = NULL,
155 };
156
157 static void
158 tdm_backend_handle_display_destroy(struct wl_listener *listener, void *data)
159 {
160     struct ds_tdm_backend *tdm;
161
162     tdm = wl_container_of(listener, tdm, display_destroy);
163     tdm_backend_destroy(tdm);
164 }
165
166 static int
167 tdm_backend_handle_tdm_event(int fd, uint32_t mask, void *data)
168 {
169     struct ds_tdm_backend *tdm;
170
171     tdm = data;
172     tdm_display_handle_events(tdm->tdm_display);
173
174     return 0;
175 }