c643291c17b5685554be173c2e5b2f3e0542f0d9
[platform/core/appfw/aul-1.git] / src / aul_rsm.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17
18 #include <glib.h>
19 #include <bundle.h>
20 #include <Ecore.h>
21 #include <Ecore_Wayland.h>
22 #include <tizen-remote-surface-client-protocol.h>
23 #include <tbm_surface.h>
24 #include "aul_util.h"
25 #include "aul_app_com.h"
26 #include "aul_api.h"
27 #include "aul_rsm_provider.h"
28 #include "aul_rsm_viewer.h"
29
30 struct __remote_surface_s {
31         struct wl_surface *surface;
32         struct tizen_remote_surface_provider *rsp;
33         char *id;
34         Ecore_Wl_Window *win;
35 };
36
37 struct __surface_s {
38         char *id;
39         void (*update_cb)(struct tizen_remote_surface *trs, struct wl_buffer *buffer, uint32_t time, void *data);
40         void (*missing_cb)(struct tizen_remote_surface *trs, void *data);
41         void *data;
42         struct tizen_remote_surface *surface;
43         int resource_id;
44 };
45
46 static struct tizen_remote_surface_manager *__rsm;
47 static struct wayland_tbm_client *__tbm_client;
48 static struct wl_tbm *__tbm;
49 static int __init_count;
50 static GHashTable *__viewer_tbl;
51 static aul_app_com_connection_h __conn;
52
53 int aul_rsm_init()
54 {
55         struct wl_registry *registry;
56         Ecore_Wl_Global *global;
57         Eina_Inlist *globals;
58
59         if (__init_count > 0) {
60                 return 0;
61         }
62
63         ecore_wl_init(NULL);
64
65         registry = ecore_wl_registry_get();
66         globals = ecore_wl_globals_get();
67
68         if (!registry || !globals) {
69                 _E("could not get registry(%p) or global list(%p)", registry,
70                         globals);
71                 return -1;
72         }
73
74         EINA_INLIST_FOREACH(globals, global) {
75                 if (!strcmp(global->interface, "tizen_remote_surface_manager")) {
76                         __rsm = wl_registry_bind(registry, global->id,
77                                 &tizen_remote_surface_manager_interface, 1);
78                 }
79         }
80
81         if (!__rsm) {
82                 _E("could not get remote surface manager");
83                 return -1;
84         }
85
86         __init_count++;
87         return 0;
88 }
89
90
91 int aul_rsm_fini()
92 {
93         if (__init_count > 1)
94                 return 0;
95
96         if (__tbm_client)
97                 wayland_tbm_client_deinit(__tbm_client);
98
99         if (__rsm)
100                 tizen_remote_surface_manager_destroy(__rsm);
101
102         ecore_wl_shutdown();
103
104         __init_count--;
105
106         return 0;
107 }
108
109 API int aul_rsm_provider_init()
110 {
111         aul_rsm_init();
112
113         return 0;
114 }
115
116 API int aul_rsm_provider_fini()
117 {
118         aul_rsm_fini();
119
120         return 0;
121 }
122
123 static void __rsp_resource_id_cb(void *data, struct tizen_remote_surface_provider *provider, uint32_t res_id)
124 {
125         struct __remote_surface_s *remote = (struct __remote_surface_s *)data;
126         bundle *envelope = bundle_create();
127
128         if (envelope == NULL) {
129                 _E("failed to create envelope");
130                 return;
131         }
132
133         bundle_add_str(envelope, "__AUL_RSP_RESOURCE_ID__", remote->id);
134         bundle_add_byte(envelope, "__AUL_RSP_SURFACE_ID__", &res_id, sizeof(uint32_t));
135
136         if (aul_app_com_send("tbm_surface_notify", envelope) < 0) {
137                 _E("failed to send surface notify");
138         }
139
140         bundle_free(envelope);
141 }
142
143 static void __rsp_visibility_cb(void *data, struct tizen_remote_surface_provider *provider, uint32_t visibility)
144 {
145         struct __remote_surface_s *remote = (struct __remote_surface_s *)data;
146         Ecore_Wl_Event_Window_Visibility_Change *ev;
147
148         ev = calloc(1, sizeof(Ecore_Wl_Event_Window_Visibility_Change));
149         if (!ev) {
150                 _E("out of memory");
151                 return;
152         }
153
154         ev->win = ecore_wl_window_id_get(remote->win);
155
156         if (visibility == TIZEN_REMOTE_SURFACE_VISIBILITY_TYPE_VISIBLE)
157                 ev->fully_obscured = 0;
158         else
159                 ev->fully_obscured = 1;
160
161         _D("visibility changed:%d", visibility);
162
163         ecore_event_add(ECORE_WL_EVENT_WINDOW_VISIBILITY_CHANGE, ev, NULL, NULL);
164 }
165
166 static const struct tizen_remote_surface_provider_listener __rsp_listener = {
167         __rsp_resource_id_cb,
168         __rsp_visibility_cb,
169 };
170
171 API int aul_rsm_provider_remote_enable(const char *id, struct wl_surface *surface)
172 {
173         struct __remote_surface_s *remote;
174
175         if (!__rsm) {
176                 _E("__rsm is not ready");
177                 return -1;
178         }
179
180         if (!surface || !id) {
181                 _E("invalid parameter");
182                 return -1;
183         }
184
185         remote = (struct __remote_surface_s *)malloc(sizeof(struct __remote_surface_s));
186         if (!remote) {
187                 _E("out of memory");
188                 return -1;
189         }
190
191         remote->surface = surface;
192         remote->win = ecore_wl_window_surface_find(surface);
193         if (!remote->win) {
194                 _E("failed to find win");
195                 return -1;
196         }
197
198         remote->rsp = tizen_remote_surface_manager_create_provider(__rsm, surface);
199         if (!remote->rsp) {
200                 _E("failed to create provider");
201                 return -1;
202         }
203
204         remote->id = strdup(id);
205         if (!remote->id) {
206                 _E("out of memory");
207                 return -1;
208         }
209
210         tizen_remote_surface_provider_add_listener(remote->rsp, &__rsp_listener, remote);
211
212         wl_display_roundtrip(ecore_wl_display_get());
213         _D("%d surface remote enable");
214
215         return 0;
216 }
217
218 static void __rs_buffer_update_cb(void *data, struct tizen_remote_surface *trs,
219         struct wl_buffer *buffer, uint32_t time)
220 {
221         struct __surface_s *surface = data;
222         if (surface)
223                 surface->update_cb(trs, buffer, time, surface->data);
224 }
225
226 static void __rs_missing_cb(void *data, struct tizen_remote_surface *trs)
227 {
228         struct __surface_s *surface = data;
229         if (surface)
230                 surface->missing_cb(trs, surface->data);
231 }
232
233 static const struct tizen_remote_surface_listener __rs_listener = {
234         __rs_buffer_update_cb,
235         __rs_missing_cb,
236 };
237
238 static void __redirect_surface(char *id, int res_id)
239 {
240         struct __surface_s *surface = NULL;
241
242         if (id) {
243                 surface = g_hash_table_lookup(__viewer_tbl, id);
244                 if (!surface) {
245                         _E("unknown surface");
246                         return;
247                 }
248         }
249
250         surface->resource_id = res_id;
251         surface->surface = tizen_remote_surface_manager_create_surface(__rsm,
252                                         (uint32_t)res_id, __tbm);
253         tizen_remote_surface_add_listener(surface->surface, &__rs_listener,
254                                                         surface);
255         tizen_remote_surface_redirect(surface->surface);
256 }
257
258 static int __tbm_handler(const char *endpoint, aul_app_com_result_e e,
259         bundle *envelope, void *user_data)
260 {
261         char *id = NULL;
262         uint32_t *res_id = NULL;
263         size_t sz;
264
265         bundle_get_str(envelope, "__AUL_RSP_RESOURCE_ID__", &id);
266         bundle_get_byte(envelope, "__AUL_RSP_SURFACE_ID__", (void **)&res_id,
267                                                                         &sz);
268
269         if (id && res_id)
270                 __redirect_surface(id, (int)*res_id);
271         else
272                 _E("bad tbm message received. missing arguments");
273
274         return 0;
275 }
276
277 API int aul_rsm_viewer_init()
278 {
279         aul_rsm_init();
280
281         __tbm_client = (struct wayland_tbm_client *)wayland_tbm_client_init(ecore_wl_display_get());
282         if (!__tbm_client) {
283                 _E("could not get tbm client");
284                 return -1;
285         }
286
287         __tbm = (struct wl_tbm *)wayland_tbm_client_get_wl_tbm(__tbm_client);
288         if (!__tbm) {
289                 _E("could not get tbm");
290                 return -1;
291         }
292
293         aul_app_com_create("tbm_surface_notify", NULL, __tbm_handler, NULL, &__conn);
294         if (!__conn) {
295                 _E("failed to create app com");
296                 return -1;
297         }
298
299         return 0;
300 }
301
302 API int aul_rsm_viewer_fini()
303 {
304         aul_rsm_fini();
305
306         return 0;
307 }
308
309 API int aul_rsm_viewer_set_surface_handler(const char *id, aul_rsm_handler *cbs, void *data)
310 {
311         struct __surface_s *surface;
312
313         if (!id || !cbs) {
314                 _E("invalid parameter");
315                 return -1;
316         }
317
318         if (!__viewer_tbl) {
319                 __viewer_tbl = g_hash_table_new(g_str_hash, g_str_equal);
320                 if (!__viewer_tbl) {
321                         _E("unable to create hashtable");
322                         return -1;
323                 }
324         }
325
326         surface = (struct __surface_s *)malloc(sizeof(struct __surface_s));
327         if (!surface) {
328                 _E("out of memory");
329                 return -1;
330         }
331
332         surface->id = strdup(id);
333         if (!surface->id) {
334                 _E("out of memory");
335                 free(surface);
336                 return -1;
337         }
338
339         surface->resource_id = -1;
340         surface->data = data;
341         surface->update_cb = cbs->aul_rsm_surface_update_cb;
342         surface->missing_cb = cbs->aul_rsm_surface_missing_cb;
343
344         g_hash_table_insert(__viewer_tbl, surface->id, surface);
345
346         return 0;
347 }
348
349 API int aul_rsm_viewer_set_surface_handler_by_rid(int resource_id, aul_rsm_handler *cbs, void *data)
350 {
351         char buf[32];
352
353         snprintf(buf, sizeof(buf), "%d", resource_id);
354         aul_rsm_viewer_set_surface_handler(buf, cbs, data);
355         __redirect_surface(buf, resource_id);
356
357         return 0;
358 }
359
360 API int aul_rsm_viewer_get_surface_rid(const char *id, int *resource_id)
361 {
362         struct __surface_s *surface;
363
364         if (!id || !resource_id) {
365                 _E("illegal arguments");
366                 return -1;
367         }
368
369         surface = g_hash_table_lookup(__viewer_tbl, id);
370         if (!surface) {
371                 _E("unknown surface");
372                 return -1;
373         }
374
375         if (surface->resource_id < 0) {
376                 _E("resource id not yet initialized");
377                 return -1;
378         }
379
380         *resource_id = surface->resource_id;
381         return 0;
382 }