PUI: fix memory corruption
[platform/core/uifw/libpui.git] / src / PUI.c
1 #include "PUI_internal.h"
2 #include "PUI_backend.h"
3 #include "PUI.h"
4
5 #include <wayland-tbm-client.h>
6 #include <tbm_surface_internal.h>
7 #include <stdio.h>
8 #include <dlfcn.h>
9
10 #ifndef PUI_MODULE_DIR
11 #define PUI_MODULE_DIR "/usr/lib"
12 #endif
13
14 static int _pui_init_count = 0;
15 static pui_module_data *pui_module = NULL;
16
17 int PUI_EVENT_ANI_STARTED = 0;
18 int PUI_EVENT_ANI_STOPPED = 0;
19 int PUI_EVENT_ANI_PAUSED = 0;
20 int PUI_EVENT_ANI_READY_TO_START = 0;
21 int PUI_EVENT_ANI_READY_TO_RESUME = 0;
22 int PUI_EVENT_ANI_FRAME_DONE = 0;
23 int PUI_EVENT_ANI_BUFFER_RELEASED = 0;
24
25 pui_error_string
26 pui_error_to_string(pui_error e)
27 {
28         pui_error_string str = NULL;
29
30         switch (e)
31         {
32                 case PUI_ERROR_NONE:
33                         str = "PUI_No_Error";
34                         break;
35
36                 case PUI_ERROR_INVALID_ANI_HANDLE:
37                         str = "PUI_Invalid_Animation_Handle";
38                         break;
39
40                 case PUI_ERROR_INVALID_ANI_CMD:
41                         str = "PUI_Invalid_Animation_Command";
42                         break;
43
44                 case PUI_ERROR_INTERNAL:
45                         str = "PUI_Internal_Error";
46                         break;
47
48                 default:
49                         str = "PUI_Unknown_Error";
50         }
51
52         return str;
53 }
54
55 pui_h
56 pui_create(Ecore_Wl2_Window *win)
57 {
58         pui_h handle = NULL;
59         Ecore_Wl2_Display *ewd = ecore_wl2_window_display_get(win);
60         struct wayland_tbm_client *wl_tbm_client = NULL;
61
62         if (!win || !ewd)
63         {
64                 pui_err("Invalid window or display !\n");
65                 return NULL;
66         }
67
68         wl_tbm_client = wayland_tbm_client_init(ecore_wl2_display_get(ewd));
69
70         if (!wl_tbm_client)
71         {
72                 pui_err("Failed to init wayland_tbm_client !\n");
73                 return NULL;
74         }
75
76         handle = (pui_h)calloc(1, sizeof(pui));
77
78         if (!handle)
79                 return NULL;
80
81         handle->win = win;
82         handle->ewd = ewd;
83         handle->visibility = 0;
84         handle->wl_tbm_client = wl_tbm_client;
85         handle->ani_handles = NULL;
86         handle->backend_module_data = pui_module->backend_module_data;
87
88         handle->tbm_queue = wayland_tbm_client_create_surface_queue(handle->wl_tbm_client,
89                                                                 ecore_wl2_window_surface_get(handle->win),
90                                                                 2, 100, 100, TBM_FORMAT_ABGR8888);
91
92         if (!handle->tbm_queue)
93         {
94                 pui_err("Failed to create a surface queue !");
95                 goto err;
96         }
97
98         return handle;
99
100 err:
101         pui_destroy(handle);
102
103         return NULL;
104 }
105
106 void
107 pui_destroy(pui_h handle)
108 {
109         pui_ani_h ani_h = NULL;
110
111         if (!handle)
112                 return;
113
114         EINA_LIST_FREE(handle->ani_handles, ani_h)
115         {
116                 pui_ani_destroy(ani_h);
117                 free(ani_h);
118         }
119
120         if (handle->tbm_queue)
121         {
122                 tbm_surface_queue_destroy(handle->tbm_queue);
123         }
124
125         if (handle->wl_tbm_client)
126         {
127                 wayland_tbm_client_deinit(handle->wl_tbm_client);
128                 handle->wl_tbm_client = NULL;
129         }
130
131         free(handle);
132 }
133
134 #define PREFIX_LIB    "libpui-"
135 #define SUFFIX_LIB    ".so"
136 #define DEFAULT_LIB   PREFIX_LIB"default-backend"SUFFIX_LIB
137
138 static void
139 _pui_load_backend_module(void)
140 {
141         //char path[PATH_MAX] = {0, };
142         void *module_info = NULL;
143         pui_backend_module *backend_module_info = NULL;
144         int backend_module_major, backend_module_minor;
145         int pui_backend_major, pui_backend_minor;
146
147         pui_backend_module_data *backend_module_data = NULL;
148
149
150         module_info = dlopen(DEFAULT_LIB, RTLD_LAZY);
151
152         if (!module_info)
153         {
154                 pui_err("Failed to dlopen(error:%s, path:%s) !\n", dlerror(), DEFAULT_LIB);
155                 return;
156         }
157
158         backend_module_info = dlsym(module_info, "pui_backend_module_info");
159
160         if (!backend_module_info) {
161                 pui_err("Backend module(%s) doesn't have pui_backend_module_info !\n", DEFAULT_LIB);
162                 goto err;
163         }
164
165         pui_backend_major = PUI_BACKEND_GET_ABI_MAJOR(PUI_BACKEND_AB_VERSION_LAST);
166         pui_backend_minor = PUI_BACKEND_GET_ABI_MINOR(PUI_BACKEND_AB_VERSION_LAST);
167
168         backend_module_major = PUI_BACKEND_GET_ABI_MAJOR(backend_module_info->abi_version);
169         backend_module_minor = PUI_BACKEND_GET_ABI_MINOR(backend_module_info->abi_version);
170
171         if (backend_module_major > pui_backend_major) {
172                 pui_err("PUI backend module ABI major ver(%d) is newer than the PUI's ver(%d)\n",
173                         backend_module_major, pui_backend_major);
174                 goto err;
175         } else if (backend_module_minor > pui_backend_minor) {
176                 pui_err("PUI backend module ABI minor ver(%d) is newer than the PUI's ver(%d)\n",
177                         backend_module_minor, pui_backend_minor);
178                 goto err;
179         }
180
181         if (!backend_module_info->backend_init || !backend_module_info->backend_deinit)
182         {
183                 pui_err("Backend module doesn't have backend_init/backend_deinit function !\n");
184                 goto err;
185         }
186
187         backend_module_data = backend_module_info->backend_init();
188
189         if (!backend_module_data)
190         {
191                 pui_err("Failed to init module (%s) !\n", DEFAULT_LIB);
192                 goto err;
193         }
194
195         pui_module->module_info = module_info;
196         pui_module->backend_module_info = backend_module_info;
197         pui_module->backend_module_data = backend_module_data;
198
199         return;
200
201 err:
202         if (backend_module_info && backend_module_info->backend_init)
203                 backend_module_info->backend_deinit(backend_module_data);
204
205         if (module_info)
206                 dlclose(module_info);
207
208         return;
209 }
210
211 static void
212 _pui_unload_backend_module(void)
213 {
214         if (!pui_module)
215         {
216                 pui_err("Invalid pui module !\n");
217                 return;
218         }
219
220         if (pui_module->backend_module_info)
221         {
222                 pui_module->backend_module_info->backend_deinit(pui_module->backend_module_data);
223                 pui_module->backend_module_data = NULL;
224                 pui_module->backend_module_info = NULL;
225         }
226
227         if (pui_module->module_info)
228                 dlclose(pui_module->module_info);
229 }
230
231 static void
232 _pui_load_backend_collect_animations(void)
233 {
234         pui_int_error ret;
235
236         if (!pui_module || !pui_module->backend_module_data) {
237                 pui_err("pui module data is not loaded\n");
238                 return;
239         }
240
241         ret = pui_module->backend_module_data->create_ani_collection();
242         if (ret != PUI_INT_ERROR_NONE) {
243                 pui_err("Failed to collect animations data (%s)\n",
244                         pui_error_to_string(ret));
245         }
246 }
247
248 static void
249 _pui_load(void)
250 {
251         _pui_load_backend_module();
252         _pui_load_backend_collect_animations();
253 }
254
255 static void
256 _pui_unload(void)
257 {
258         _pui_unload_backend_module();
259 }
260
261 static void
262 _pui_event_init(void)
263 {
264         PUI_EVENT_ANI_STARTED = ecore_event_type_new();
265         PUI_EVENT_ANI_STOPPED = ecore_event_type_new();
266         PUI_EVENT_ANI_PAUSED = ecore_event_type_new();
267         PUI_EVENT_ANI_READY_TO_START = ecore_event_type_new();
268         PUI_EVENT_ANI_READY_TO_RESUME = ecore_event_type_new();
269         PUI_EVENT_ANI_FRAME_DONE = ecore_event_type_new();
270         PUI_EVENT_ANI_BUFFER_RELEASED = ecore_event_type_new();
271 }
272
273 static void
274 _pui_event_shutdown(void)
275 {
276         ecore_event_type_flush(PUI_EVENT_ANI_STARTED,
277                                         PUI_EVENT_ANI_STOPPED,
278                                         PUI_EVENT_ANI_PAUSED,
279                                         PUI_EVENT_ANI_READY_TO_START,
280                                         PUI_EVENT_ANI_READY_TO_RESUME,
281                                         PUI_EVENT_ANI_FRAME_DONE,
282                                         PUI_EVENT_ANI_BUFFER_RELEASED);
283
284         PUI_EVENT_ANI_STARTED = -1;
285         PUI_EVENT_ANI_STOPPED = -1;
286         PUI_EVENT_ANI_PAUSED = -1;
287         PUI_EVENT_ANI_READY_TO_START = -1;
288         PUI_EVENT_ANI_READY_TO_RESUME = -1;
289         PUI_EVENT_ANI_FRAME_DONE = -1;
290         PUI_EVENT_ANI_BUFFER_RELEASED = -1;
291 }
292
293 int
294 pui_init(void)
295 {
296         if (++_pui_init_count != 1)
297           return _pui_init_count;
298
299         if (pui_module)
300         {
301                 pui_err("Invalid calling of pui_init() !\n");
302                 goto error;
303         }
304
305         pui_module = (pui_module_data *)calloc(1, sizeof(pui_module_data));
306
307         if (!pui_module)
308         {
309                 pui_err("Failed to allocate memory for pui module data !\n");
310                 goto error;
311         }
312
313         //TODO
314         ecore_wl2_init();
315
316         _pui_event_init();
317
318         _pui_load();
319
320         return _pui_init_count;
321
322 error:
323         return --_pui_init_count;
324 }
325
326 int
327 pui_shutdown(void)
328 {
329         if (_pui_init_count <= 0)
330         {
331                 pui_err("Invalid pui init count : %d\n", _pui_init_count);
332                 _pui_init_count = 0;
333                 return 0;
334         }
335
336         if (!pui_module)
337         {
338                 pui_err("Invalid pui module data !\n");
339                 return _pui_init_count;
340         }
341
342         _pui_init_count--;
343
344         //TODO
345         _pui_unload();
346
347         _pui_event_shutdown();
348
349         ecore_wl2_shutdown();
350
351         free(pui_module);
352
353         return _pui_init_count;
354 }
355