implement ds_tizen_hwc
[platform/core/uifw/libds-tizen.git] / src / hwc / hwc.c
1 #include <assert.h>
2 #include <stdint.h>
3 #include <stdlib.h>
4 #include <wayland-server.h>
5 #include <tizen-hwc-server-protocol.h>
6 #include <libds/log.h>
7
8 #include "util.h"
9 #include "libds-tizen/hwc.h"
10
11 #define TIZEN_HWC_VERSION 1
12
13 struct ds_tizen_hwc
14 {
15     struct wl_global *global;
16
17     struct wl_list clients;
18
19     struct wl_listener destroy;
20
21     struct {
22         struct wl_signal destroy;
23         struct wl_signal new_commit_feedback;
24     } events;
25 };
26
27 struct ds_tizen_hwc_client
28 {
29     struct ds_tizen_hwc *hwc;
30
31     struct wl_resource *resource;
32     struct wl_client *wl_client;
33
34     struct {
35         struct wl_signal destroy;
36     } events;
37
38     struct wl_list link;
39 };
40
41 struct ds_tizen_hwc_commit_feedback
42 {
43     struct wl_resource *resource;
44
45     struct ds_surface *surface;
46     uint32_t serial;
47
48     struct {
49         struct wl_listener surface_destroy;
50     } listener;
51
52     struct {
53         struct wl_signal destroy;
54     } events;
55 };
56
57 static void
58 hwc_commit_feedback_handle_surface_destroy(struct wl_listener *listener, void *data)
59 {
60     struct ds_tizen_hwc_commit_feedback *commit_feedback;
61
62     commit_feedback = wl_container_of(listener, commit_feedback,
63             listener.surface_destroy);
64
65     if (commit_feedback->listener.surface_destroy.notify) {
66         wl_list_remove(&commit_feedback->listener.surface_destroy.link);
67         commit_feedback->listener.surface_destroy.notify = NULL;
68     }
69
70     commit_feedback->surface = NULL;
71 }
72
73 static void
74 _hwc_commit_feedback_cb_resource_destroy(struct wl_resource *commit_feedback_resource)
75 {
76     struct ds_tizen_hwc_commit_feedback *commit_feedback;
77
78     commit_feedback = wl_resource_get_user_data(commit_feedback_resource);
79
80     ds_inf("hwc_commit_feedback:%p destroy", commit_feedback);
81
82     if (commit_feedback->listener.surface_destroy.notify) {
83         wl_list_remove(&commit_feedback->listener.surface_destroy.link);
84         commit_feedback->listener.surface_destroy.notify = NULL;
85     }
86
87     wl_signal_emit(&commit_feedback->events.destroy, commit_feedback);
88
89     free(commit_feedback);
90 }
91
92 static void
93 hwc_handle_create_commit_feedback(struct wl_client *client,
94     struct wl_resource *hwc_client_resource,
95     struct wl_resource *surface_resource,
96     uint32_t id,
97     uint32_t serial)
98 {
99     struct ds_tizen_hwc_client *hwc_client;
100     struct ds_tizen_hwc_commit_feedback *commit_feedback;
101     struct ds_surface *surface;
102
103     hwc_client = wl_resource_get_user_data(hwc_client_resource);
104
105     surface = ds_surface_from_resource(surface_resource);
106
107     commit_feedback = calloc(1, sizeof *commit_feedback);
108     if (!commit_feedback) {
109         wl_client_post_no_memory(client);
110         return;
111     }
112
113     commit_feedback->resource = wl_resource_create(client, &tizen_hwc_commit_feedback_interface,
114             wl_resource_get_version(hwc_client_resource), id);
115     if (!commit_feedback->resource) {
116         wl_client_post_no_memory(client);
117         free(commit_feedback);
118         return;
119     }
120
121     commit_feedback->listener.surface_destroy.notify = hwc_commit_feedback_handle_surface_destroy;
122     ds_surface_add_destroy_listener(surface, &commit_feedback->listener.surface_destroy);
123     commit_feedback->surface = surface;
124
125     commit_feedback->serial = serial;
126
127     wl_resource_set_implementation(commit_feedback->resource, NULL,
128             commit_feedback, _hwc_commit_feedback_cb_resource_destroy);
129
130     ds_inf("hwc_commit_feedback:%p create", commit_feedback);
131
132     wl_signal_init(&commit_feedback->events.destroy);
133
134     wl_signal_emit(&hwc_client->hwc->events.new_commit_feedback, commit_feedback);
135 }
136
137 static void
138 hwc_handle_destroy(struct wl_client *wl_client,
139     struct wl_resource *resource)
140 {
141     wl_resource_destroy(resource);
142 }
143
144 static const struct tizen_hwc_interface hwc_impl =
145 {
146     .destroy = hwc_handle_destroy,
147     .create_commit_feedback = hwc_handle_create_commit_feedback,
148 };
149
150 static void
151 _tizen_hwc_client_handle_resource_destroy(struct wl_resource *resource)
152 {
153     struct ds_tizen_hwc_client *client;
154
155     client = wl_resource_get_user_data(resource);
156
157     ds_inf("_tizen_hwc_client_handle_destroy (client:%p)", client);
158
159     wl_list_remove(&client->link);
160     free(client);
161 }
162
163 static void
164 hwc_bind(struct wl_client *wl_client, void *data, uint32_t version,
165          uint32_t id)
166 {
167     struct ds_tizen_hwc *hwc = data;
168     struct ds_tizen_hwc_client *hwc_client;
169
170     hwc_client = calloc(1, sizeof *hwc_client);
171     if (hwc_client == NULL) {
172         ds_err("calloc() failed. tizen_hwc");
173         wl_client_post_no_memory(wl_client);
174         return;
175     }
176
177     ds_inf("tizen_hwc_client binds. (hwc_client:%p)", hwc_client);
178
179     hwc_client->hwc = hwc;
180     hwc_client->wl_client = wl_client;
181
182     hwc_client->resource = wl_resource_create(wl_client, &tizen_hwc_interface,
183             MIN(version, TIZEN_HWC_VERSION), id);
184     if (hwc_client->resource == NULL) {
185         ds_err("tizen_hwc : wl_resource_create() failed.");
186         free(hwc_client);
187         wl_client_post_no_memory(wl_client);
188         return;
189     }
190
191     wl_resource_set_implementation(hwc_client->resource, &hwc_impl, hwc_client,
192             _tizen_hwc_client_handle_resource_destroy);
193
194     wl_signal_init(&hwc_client->events.destroy);
195
196     wl_list_insert(&hwc->clients, &hwc_client->link);
197 }
198
199 static void
200 hwc_handle_display_destroy(struct wl_listener *listener, void *data)
201 {
202     struct ds_tizen_hwc *hwc;
203
204     hwc = wl_container_of(listener, hwc, destroy);
205
206     ds_inf("Global destroy: hwc(%p)", hwc);
207
208     wl_signal_emit(&hwc->events.destroy, hwc);
209     wl_list_remove(&hwc->destroy.link);
210     wl_global_destroy(hwc->global);
211     free(hwc);
212 }
213
214 WL_EXPORT struct ds_tizen_hwc *
215 ds_tizen_hwc_create(struct wl_display *display)
216 {
217     struct ds_tizen_hwc *hwc;
218
219     hwc = calloc(1, sizeof *hwc);
220     if (!hwc) {
221         ds_err("calloc() failed.");
222         return NULL;
223     }
224
225     hwc->global = wl_global_create(display, &tizen_hwc_interface,
226             TIZEN_HWC_VERSION, hwc, hwc_bind);
227     if (!hwc->global) {
228         ds_err("wl_global_create() failed. tizen_hwc_interface");
229         free(hwc);
230         return NULL;
231     }
232
233     wl_list_init(&hwc->clients);
234
235     hwc->destroy.notify = hwc_handle_display_destroy;
236     wl_display_add_destroy_listener(display, &hwc->destroy);
237
238     wl_signal_init(&hwc->events.destroy);
239     wl_signal_init(&hwc->events.new_commit_feedback);
240
241     ds_inf("Global created: tizen_hwc(%p)", hwc);
242
243     return hwc;
244 }
245
246 WL_EXPORT void
247 ds_tizen_hwc_add_destroy_listener(
248         struct ds_tizen_hwc *hwc,
249         struct wl_listener *listener)
250 {
251     wl_signal_add(&hwc->events.destroy, listener);
252 }
253
254 WL_EXPORT void
255 ds_tizen_hwc_add_new_commit_feedback_listener(
256         struct ds_tizen_hwc *hwc,
257         struct wl_listener *listener)
258 {
259     wl_signal_add(&hwc->events.new_commit_feedback, listener);
260 }
261
262 WL_EXPORT void
263 ds_tizen_hwc_commit_feedback_add_destroy_listener(
264         struct ds_tizen_hwc_commit_feedback *commit_feedback,
265         struct wl_listener *listener)
266 {
267     wl_signal_add(&commit_feedback->events.destroy, listener);
268 }
269
270 WL_EXPORT struct ds_surface *
271 ds_tizen_hwc_commit_feedback_get_surface(
272         struct ds_tizen_hwc_commit_feedback *commit_feedback)
273 {
274     return commit_feedback->surface;
275 }
276
277 WL_EXPORT void
278 ds_tizen_hwc_commit_feedback_send_committed(
279         struct ds_tizen_hwc_commit_feedback *commit_feedback)
280 {
281     ds_inf("hwc_commit_feedback:%p send committed", commit_feedback);
282
283     tizen_hwc_commit_feedback_send_committed(commit_feedback->resource,
284             commit_feedback->serial);
285     wl_resource_destroy(commit_feedback->resource);
286 }
287
288 WL_EXPORT void
289 ds_tizen_hwc_commit_feedback_send_discarded(
290         struct ds_tizen_hwc_commit_feedback *commit_feedback)
291 {
292     ds_inf("hwc_commit_feedback:%p send discard", commit_feedback);
293
294     tizen_hwc_commit_feedback_send_discarded(commit_feedback->resource,
295             commit_feedback->serial);
296     wl_resource_destroy(commit_feedback->resource);
297 }