Update AUTHORS and boiler plates
[platform/core/uifw/libpui.git] / src / PUI.c
1 /*
2  * Copyright © 2019 Samsung Electronics co., Ltd. All Rights Reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sublicense, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial
14  * portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  */
25
26 #include "PUI_internal.h"
27 #include "PUI_backend.h"
28 #include "PUI.h"
29
30 #include <wayland-tbm-client.h>
31 #include <tbm_surface_internal.h>
32 #include <stdio.h>
33 #include <dlfcn.h>
34
35 #ifndef PUI_MODULE_DIR
36 #define PUI_MODULE_DIR "/usr/lib"
37 #endif
38
39 static int _pui_init_count = 0;
40 static pui_module_data *pui_module = NULL;
41
42 int PUI_EVENT_ANI_STARTED = 0;
43 int PUI_EVENT_ANI_STOPPED = 0;
44 int PUI_EVENT_ANI_PAUSED = 0;
45 int PUI_EVENT_ANI_READY_TO_START = 0;
46 int PUI_EVENT_ANI_READY_TO_RESUME = 0;
47 int PUI_EVENT_ANI_FRAME_DONE = 0;
48 int PUI_EVENT_ANI_BUFFER_RELEASED = 0;
49
50 pui_error_string
51 pui_error_to_string(pui_error e)
52 {
53         pui_error_string str = NULL;
54
55         switch (e)
56         {
57                 case PUI_ERROR_NONE:
58                         str = "PUI_No_Error";
59                         break;
60
61                 case PUI_ERROR_INVALID_ANI_HANDLE:
62                         str = "PUI_Invalid_Animation_Handle";
63                         break;
64
65                 case PUI_ERROR_INVALID_ANI_CMD:
66                         str = "PUI_Invalid_Animation_Command";
67                         break;
68
69                 case PUI_ERROR_INTERNAL:
70                         str = "PUI_Internal_Error";
71                         break;
72
73                 default:
74                         str = "PUI_Unknown_Error";
75         }
76
77         return str;
78 }
79
80 pui_h
81 pui_create(Ecore_Wl2_Window *win)
82 {
83         pui_h handle = NULL;
84         Ecore_Wl2_Display *ewd = ecore_wl2_window_display_get(win);
85         struct wayland_tbm_client *wl_tbm_client = NULL;
86
87         if (!win || !ewd)
88         {
89                 pui_err("Invalid window or display !\n");
90                 return NULL;
91         }
92
93         wl_tbm_client = wayland_tbm_client_init(ecore_wl2_display_get(ewd));
94
95         if (!wl_tbm_client)
96         {
97                 pui_err("Failed to init wayland_tbm_client !\n");
98                 return NULL;
99         }
100
101         handle = (pui_h)calloc(1, sizeof(pui));
102
103         if (!handle)
104                 return NULL;
105
106         handle->win = win;
107         handle->ewd = ewd;
108         handle->visibility = 0;
109         handle->wl_tbm_client = wl_tbm_client;
110         handle->ani_handles = NULL;
111         handle->backend_module_data = pui_module->backend_module_data;
112
113         handle->tbm_queue = wayland_tbm_client_create_surface_queue(handle->wl_tbm_client,
114                                                                 ecore_wl2_window_surface_get(handle->win),
115                                                                 2, 100, 100, TBM_FORMAT_ABGR8888);
116
117         if (!handle->tbm_queue)
118         {
119                 pui_err("Failed to create a surface queue !");
120                 goto err;
121         }
122
123         return handle;
124
125 err:
126         pui_destroy(handle);
127
128         return NULL;
129 }
130
131 void
132 pui_destroy(pui_h handle)
133 {
134         pui_ani_h ani_h = NULL;
135
136         if (!handle)
137                 return;
138
139         EINA_LIST_FREE(handle->ani_handles, ani_h)
140         {
141                 pui_ani_destroy(ani_h);
142                 free(ani_h);
143         }
144
145         if (handle->tbm_queue)
146         {
147                 tbm_surface_queue_destroy(handle->tbm_queue);
148         }
149
150         if (handle->wl_tbm_client)
151         {
152                 wayland_tbm_client_deinit(handle->wl_tbm_client);
153                 handle->wl_tbm_client = NULL;
154         }
155
156         free(handle);
157 }
158
159 #define PREFIX_LIB    "libpui-"
160 #define SUFFIX_LIB    ".so"
161 #define DEFAULT_LIB   PREFIX_LIB"default-backend"SUFFIX_LIB
162
163 static void
164 _pui_load_backend_module(void)
165 {
166         //char path[PATH_MAX] = {0, };
167         void *module_info = NULL;
168         pui_backend_module *backend_module_info = NULL;
169         int backend_module_major, backend_module_minor;
170         int pui_backend_major, pui_backend_minor;
171
172         pui_backend_module_data *backend_module_data = NULL;
173
174
175         module_info = dlopen(DEFAULT_LIB, RTLD_LAZY);
176
177         if (!module_info)
178         {
179                 pui_err("Failed to dlopen(error:%s, path:%s) !\n", dlerror(), DEFAULT_LIB);
180                 return;
181         }
182
183         backend_module_info = dlsym(module_info, "pui_backend_module_info");
184
185         if (!backend_module_info) {
186                 pui_err("Backend module(%s) doesn't have pui_backend_module_info !\n", DEFAULT_LIB);
187                 goto err;
188         }
189
190         pui_backend_major = PUI_BACKEND_GET_ABI_MAJOR(PUI_BACKEND_AB_VERSION_LAST);
191         pui_backend_minor = PUI_BACKEND_GET_ABI_MINOR(PUI_BACKEND_AB_VERSION_LAST);
192
193         backend_module_major = PUI_BACKEND_GET_ABI_MAJOR(backend_module_info->abi_version);
194         backend_module_minor = PUI_BACKEND_GET_ABI_MINOR(backend_module_info->abi_version);
195
196         if (backend_module_major > pui_backend_major) {
197                 pui_err("PUI backend module ABI major ver(%d) is newer than the PUI's ver(%d)\n",
198                         backend_module_major, pui_backend_major);
199                 goto err;
200         } else if (backend_module_minor > pui_backend_minor) {
201                 pui_err("PUI backend module ABI minor ver(%d) is newer than the PUI's ver(%d)\n",
202                         backend_module_minor, pui_backend_minor);
203                 goto err;
204         }
205
206         if (!backend_module_info->backend_init || !backend_module_info->backend_deinit)
207         {
208                 pui_err("Backend module doesn't have backend_init/backend_deinit function !\n");
209                 goto err;
210         }
211
212         backend_module_data = backend_module_info->backend_init();
213
214         if (!backend_module_data)
215         {
216                 pui_err("Failed to init module (%s) !\n", DEFAULT_LIB);
217                 goto err;
218         }
219
220         pui_module->module_info = module_info;
221         pui_module->backend_module_info = backend_module_info;
222         pui_module->backend_module_data = backend_module_data;
223
224         return;
225
226 err:
227         if (backend_module_info && backend_module_info->backend_init)
228                 backend_module_info->backend_deinit(backend_module_data);
229
230         if (module_info)
231                 dlclose(module_info);
232
233         return;
234 }
235
236 static void
237 _pui_unload_backend_module(void)
238 {
239         if (!pui_module)
240         {
241                 pui_err("Invalid pui module !\n");
242                 return;
243         }
244
245         if (pui_module->backend_module_info)
246         {
247                 pui_module->backend_module_info->backend_deinit(pui_module->backend_module_data);
248                 pui_module->backend_module_data = NULL;
249                 pui_module->backend_module_info = NULL;
250         }
251
252         if (pui_module->module_info)
253                 dlclose(pui_module->module_info);
254 }
255
256 static void
257 _pui_load_backend_collect_animations(void)
258 {
259         pui_int_error ret;
260
261         if (!pui_module || !pui_module->backend_module_data) {
262                 pui_err("pui module data is not loaded\n");
263                 return;
264         }
265
266         ret = pui_module->backend_module_data->create_ani_collection();
267         if (ret != PUI_INT_ERROR_NONE) {
268                 pui_err("Failed to collect animations data (%s)\n",
269                         pui_error_to_string(ret));
270         }
271 }
272
273 static void
274 _pui_load(void)
275 {
276         _pui_load_backend_module();
277         _pui_load_backend_collect_animations();
278 }
279
280 static void
281 _pui_unload(void)
282 {
283         _pui_unload_backend_module();
284 }
285
286 static void
287 _pui_event_init(void)
288 {
289         PUI_EVENT_ANI_STARTED = ecore_event_type_new();
290         PUI_EVENT_ANI_STOPPED = ecore_event_type_new();
291         PUI_EVENT_ANI_PAUSED = ecore_event_type_new();
292         PUI_EVENT_ANI_READY_TO_START = ecore_event_type_new();
293         PUI_EVENT_ANI_READY_TO_RESUME = ecore_event_type_new();
294         PUI_EVENT_ANI_FRAME_DONE = ecore_event_type_new();
295         PUI_EVENT_ANI_BUFFER_RELEASED = ecore_event_type_new();
296 }
297
298 static void
299 _pui_event_shutdown(void)
300 {
301         ecore_event_type_flush(PUI_EVENT_ANI_STARTED,
302                                         PUI_EVENT_ANI_STOPPED,
303                                         PUI_EVENT_ANI_PAUSED,
304                                         PUI_EVENT_ANI_READY_TO_START,
305                                         PUI_EVENT_ANI_READY_TO_RESUME,
306                                         PUI_EVENT_ANI_FRAME_DONE,
307                                         PUI_EVENT_ANI_BUFFER_RELEASED);
308
309         PUI_EVENT_ANI_STARTED = -1;
310         PUI_EVENT_ANI_STOPPED = -1;
311         PUI_EVENT_ANI_PAUSED = -1;
312         PUI_EVENT_ANI_READY_TO_START = -1;
313         PUI_EVENT_ANI_READY_TO_RESUME = -1;
314         PUI_EVENT_ANI_FRAME_DONE = -1;
315         PUI_EVENT_ANI_BUFFER_RELEASED = -1;
316 }
317
318 int
319 pui_init(void)
320 {
321         if (++_pui_init_count != 1)
322           return _pui_init_count;
323
324         if (pui_module)
325         {
326                 pui_err("Invalid calling of pui_init() !\n");
327                 goto error;
328         }
329
330         pui_module = (pui_module_data *)calloc(1, sizeof(pui_module_data));
331
332         if (!pui_module)
333         {
334                 pui_err("Failed to allocate memory for pui module data !\n");
335                 goto error;
336         }
337
338         //TODO
339         ecore_wl2_init();
340
341         _pui_event_init();
342
343         _pui_load();
344
345         return _pui_init_count;
346
347 error:
348         return --_pui_init_count;
349 }
350
351 int
352 pui_shutdown(void)
353 {
354         if (_pui_init_count <= 0)
355         {
356                 pui_err("Invalid pui init count : %d\n", _pui_init_count);
357                 _pui_init_count = 0;
358                 return 0;
359         }
360
361         if (!pui_module)
362         {
363                 pui_err("Invalid pui module data !\n");
364                 return _pui_init_count;
365         }
366
367         _pui_init_count--;
368
369         //TODO
370         _pui_unload();
371
372         _pui_event_shutdown();
373
374         ecore_wl2_shutdown();
375
376         free(pui_module);
377
378         return _pui_init_count;
379 }
380