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