Sync with released version for TIZEN 1.0 demo
[platform/core/uifw/coregl.git] / src / coregl.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <dlfcn.h>
4 #include <string.h>
5 #include "coregl_internal.h"
6
7 CoreGL_Opt_Flag         api_opt = COREGL_UNKNOWN_PATH;
8
9 Mutex                   ctx_list_access_mutex = MUTEX_INITIALIZER;
10
11 void                   *egl_lib_handle;
12 void                   *gl_lib_handle;
13
14 GLContext_List         *glctx_list = NULL;
15
16 int                 trace_api_flag = 0;
17 int                 trace_ctx_flag = 0;
18 int                 trace_state_flag = 0;
19 int                 debug_nofp = 0;
20
21 // Symbol definition for real
22 #define _COREGL_SYMBOL(IS_EXTENSION, RET_TYPE, FUNC_NAME, PARAM_LIST)     RET_TYPE (*_sym_##FUNC_NAME) PARAM_LIST;
23 #include "headers/sym.h"
24 #undef _COREGL_SYMBOL
25
26 const char *
27 get_env_setting(const char *name)
28 {
29         char *fp_env = NULL;
30         static char *fp_default = "\0";
31         fp_env = getenv(name);
32         if (fp_env == NULL) fp_env = fp_default;
33         return fp_env;
34 }
35
36 int
37 add_context_state_to_list(const void *option, const int option_len, GLContextState *cstate, Mutex *mtx)
38 {
39         int ret = 0;
40         int tid = 0;
41         GLContext_List *current = NULL;
42         GLContext_List *newitm = NULL;
43
44         if (mtx != NULL) AST(mutex_lock(mtx) == 1);
45
46         AST(cstate != NULL);
47
48         tid = get_current_thread();
49
50         current = glctx_list;
51         while (current != NULL)
52         {
53                 if (current->option_len == option_len &&
54                     memcmp(current->option, option, option_len) == 0 &&
55                     current->thread_id == tid)
56                 {
57                         AST(current->cstate == cstate);
58                         goto finish;
59                 }
60                 current = current->next;
61         }
62
63         newitm = (GLContext_List *)calloc(1, sizeof(GLContext_List));
64         if (newitm == NULL)
65         {
66                 ERR("Failed to create context list.\n");
67                 goto finish;
68         }
69
70         newitm->cstate = cstate;
71         newitm->thread_id = tid;
72         newitm->option_len = option_len;
73         newitm->option = (void *)malloc(option_len);
74         memcpy(newitm->option, option, option_len);
75
76         if (glctx_list != NULL)
77                 newitm->next = glctx_list;
78
79         glctx_list = newitm;
80
81         ret = 1;
82         goto finish;
83
84 finish:
85         if (ret != 1)
86         {
87                 if (newitm != NULL)
88                 {
89                         free(newitm);
90                         newitm = NULL;
91                 }
92                 if (cstate != NULL)
93                 {
94                         free(cstate);
95                         cstate = NULL;
96                 }
97         }
98         if (mtx != NULL) AST(mutex_unlock(mtx) == 1);
99
100         return ret;
101 }
102
103 GLContextState *
104 get_context_state_from_list(const void *option, const int option_len, Mutex *mtx)
105 {
106         GLContextState *ret = NULL;
107         GLContext_List *current = NULL;
108         int tid = 0;
109
110         if (mtx != NULL) AST(mutex_lock(mtx) == 1);
111
112         tid = get_current_thread();
113
114         current = glctx_list;
115         while (current != NULL)
116         {
117                 if (current->option_len == option_len &&
118                     memcmp(current->option, option, option_len) == 0 &&
119                     current->thread_id == tid)
120                 {
121                         ret = current->cstate;
122                         goto finish;
123                 }
124                 current = current->next;
125         }
126         goto finish;
127
128 finish:
129         if (mtx != NULL) AST(mutex_unlock(mtx) == 1);
130         return ret;
131 }
132
133 int
134 remove_context_states_from_list(GLContextState *cstate, Mutex *mtx)
135 {
136         int ret = 0;
137         int tid = 0;
138         GLContext_List *olditm = NULL;
139         GLContext_List *current = NULL;
140
141         if (mtx != NULL) AST(mutex_lock(mtx) == 1);
142
143         AST(cstate != NULL);
144
145         tid = get_current_thread();
146         current = glctx_list;
147
148         while (current != NULL)
149         {
150                 if (current->cstate == cstate)
151                 {
152                         GLContext_List *nextitm = NULL;
153                         if (olditm != NULL)
154                         {
155                                 olditm->next = current->next;
156                                 nextitm = olditm->next;
157                         }
158                         else
159                         {
160                                 glctx_list = current->next;
161                                 nextitm = glctx_list;
162                         }
163                         free(current);
164                         ret = 1;
165                         current = nextitm;
166                         continue;
167                 }
168                 olditm = current;
169                 current = current->next;
170         }
171         goto finish;
172
173 finish:
174         if (mtx != NULL) AST(mutex_unlock(mtx) == 1);
175         return ret;
176 }
177
178 int
179 init_new_thread_state()
180 {
181         int ret = 0;
182         GLThreadState *tstate = NULL;
183
184         tstate = get_current_thread_state();
185         AST(tstate == NULL);
186
187         tstate = (GLThreadState *)calloc(1, sizeof(GLThreadState));
188         tstate->thread_id = get_current_thread();
189         tstate->binded_api = EGL_NONE;
190
191         set_current_thread_state(&ctx_list_access_mutex, tstate);
192
193 #ifdef COREGL_TRACE_CONTEXT_INFO
194         add_to_general_trace_list(&thread_trace_list, tstate);
195 #endif // COREGL_TRACE_CONTEXT_INFO
196         ret = 1;
197         goto finish;
198
199 finish:
200         return ret;
201 }
202
203 static void
204 _sym_missing()
205 {
206         ERR("GL symbol missing!\n");
207 }
208
209 static int
210 _glue_sym_init(void)
211 {
212
213 #define FINDSYM(libhandle, getproc, dst, sym) \
214    if ((!dst) && (getproc)) dst = (__typeof__(dst))getproc(sym); \
215    if (!dst) dst = (__typeof__(dst))dlsym(libhandle, sym);
216
217 #define FALLBAK(dst) \
218    if (!dst) { dst = (__typeof__(dst))_sym_missing; ERR("WARNING : symbol '"#dst"' missing!\n"); }
219
220
221 #ifndef _COREGL_DESKTOP_GL
222 # define _COREGL_SYMBOL(IS_EXTENSION, RET_TYPE, FUNC_NAME, PARAM_LIST) \
223      FINDSYM(egl_lib_handle, _sym_eglGetProcAddress, _sym_##FUNC_NAME, #FUNC_NAME); \
224      if (IS_EXTENSION == GL_TRUE) { \
225         FINDSYM(egl_lib_handle, _sym_eglGetProcAddress, _sym_##FUNC_NAME, #FUNC_NAME"EXT"); \
226         FINDSYM(egl_lib_handle, _sym_eglGetProcAddress, _sym_##FUNC_NAME, #FUNC_NAME"ARB"); \
227         FINDSYM(egl_lib_handle, _sym_eglGetProcAddress, _sym_##FUNC_NAME, #FUNC_NAME"OES"); \
228         FINDSYM(egl_lib_handle, _sym_eglGetProcAddress, _sym_##FUNC_NAME, #FUNC_NAME"KHR"); \
229      } else { FALLBAK(_sym_##FUNC_NAME); }
230 # include "headers/sym_egl.h"
231 # undef _COREGL_SYMBOL
232 #else
233 # define _COREGL_SYMBOL(IS_EXTENSION, RET_TYPE, FUNC_NAME, PARAM_LIST) \
234      FINDSYM(glue_lib_handle, _sym_glXGetProcAddress, _sym_##FUNC_NAME, #FUNC_NAME); \
235      if (IS_EXTENSION == GL_TRUE) { \
236         FINDSYM(gl_lib_handle, _sym_glXGetProcAddress, _sym_##FUNC_NAME, #FUNC_NAME"EXT"); \
237         FINDSYM(gl_lib_handle, _sym_glXGetProcAddress, _sym_##FUNC_NAME, #FUNC_NAME"ARB"); \
238         FINDSYM(gl_lib_handle, _sym_glXGetProcAddress, _sym_##FUNC_NAME, #FUNC_NAME"OES"); \
239         FINDSYM(gl_lib_handle, _sym_glXGetProcAddress, _sym_##FUNC_NAME, #FUNC_NAME"MESA"); \
240         FINDSYM(gl_lib_handle, _sym_glXGetProcAddress, _sym_##FUNC_NAME, #FUNC_NAME"SGI"); \
241      } else { FALLBAK(_sym_##FUNC_NAME); }
242 # include "headers/sym_glx.h"
243 # undef _COREGL_SYMBOL
244 #endif
245
246 #undef FINDSYM
247 #undef FALLBAK
248
249         return 1;
250 }
251
252 static int
253 _gl_sym_init(void)
254 {
255
256 #define FINDSYM(libhandle, getproc, dst, sym) \
257    if ((!dst) && (getproc)) dst = (__typeof__(dst))getproc(sym); \
258    if (!dst) dst = (__typeof__(dst))dlsym(gl_lib_handle, sym);
259 #define FALLBAK(dst) \
260    if (!dst) { dst = (__typeof__(dst))_sym_missing; ERR("WARNING : symbol '"#dst"' missing!\n"); }
261
262 #ifndef _COREGL_DESKTOP_GL
263 # define _COREGL_SYMBOL(IS_EXTENSION, RET_TYPE, FUNC_NAME, PARAM_LIST) \
264      FINDSYM(gl_lib_handle, _sym_eglGetProcAddress, _sym_##FUNC_NAME, #FUNC_NAME); \
265      if (IS_EXTENSION == GL_TRUE) { \
266         FINDSYM(gl_lib_handle, _sym_eglGetProcAddress, _sym_##FUNC_NAME, #FUNC_NAME"EXT"); \
267         FINDSYM(gl_lib_handle, _sym_eglGetProcAddress, _sym_##FUNC_NAME, #FUNC_NAME"ARB"); \
268         FINDSYM(gl_lib_handle, _sym_eglGetProcAddress, _sym_##FUNC_NAME, #FUNC_NAME"OES"); \
269         FINDSYM(gl_lib_handle, _sym_eglGetProcAddress, _sym_##FUNC_NAME, #FUNC_NAME"KHR"); \
270       } else { FALLBAK(_sym_##FUNC_NAME); }
271 # include "headers/sym_gl.h"
272 # undef _COREGL_SYMBOL
273 #else
274 # define _COREGL_SYMBOL(IS_EXTENSION, RET_TYPE, FUNC_NAME, PARAM_LIST) \
275      if (IS_EXTENSION == GL_TRUE) { \
276         FINDSYM(gl_lib_handle, _sym_glXGetProcAddress, _sym_##FUNC_NAME, #FUNC_NAME); \
277         FINDSYM(gl_lib_handle, _sym_glXGetProcAddress, _sym_##FUNC_NAME, #FUNC_NAME"EXT"); \
278         FINDSYM(gl_lib_handle, _sym_glXGetProcAddress, _sym_##FUNC_NAME, #FUNC_NAME"ARB"); \
279         FINDSYM(gl_lib_handle, _sym_glXGetProcAddress, _sym_##FUNC_NAME, #FUNC_NAME"OES"); \
280      } else { FALLBAK(_sym_##FUNC_NAME); }
281 # include "headers/sym_gl.h"
282 # undef _COREGL_SYMBOL
283 #endif
284
285 #undef FINDSYM
286 #undef FALLBAK
287
288         return 1;
289 }
290
291 COREGL_API void coregl_symbol_exported()
292 {
293         LOG("\E[0;31;1mERROR : Invalid library link! (Check linkage of libCOREGL)\E[0m\n");
294 }
295
296 static int
297 _gl_lib_init(void)
298 {
299
300 #ifndef _COREGL_DESKTOP_GL
301         //------------------------------------------------//
302         // Open EGL Library as EGL is separate
303 #ifndef _COREGL_EMBED_EVAS
304         egl_lib_handle = dlopen("libEGL_drv.so", RTLD_NOW);
305 #else
306         egl_lib_handle = dlopen("libEGL.so.1", RTLD_NOW);
307         if (!egl_lib_handle)
308                 egl_lib_handle = dlopen("libEGL.so", RTLD_NOW);
309 #endif
310         if (!egl_lib_handle)
311         {
312                 ERR("\E[0;31;1mERROR : %s\E[0m\n\n", dlerror());
313                 ERR("\E[0;31;1mERROR : Invalid library link! (Check linkage of libCOREGL -> libEGL_drv)\E[0m\n");
314                 return 0;
315         }
316
317         // test for invalid linking egl
318         if (dlsym(egl_lib_handle, "coregl_symbol_exported"))
319         {
320                 ERR("\E[0;31;1mERROR : Invalid library link! (Check linkage of libCOREGL -> libEGL_drv)\E[0m\n");
321                 return 0;
322         }
323
324         // use gl_lib handle for GL symbols
325 #ifndef _COREGL_EMBED_EVAS
326         gl_lib_handle = dlopen("libGLESv2_drv.so", RTLD_NOW);
327 #else
328         gl_lib_handle = dlopen("libGLESv2.so.1", RTLD_NOW);
329         if (!gl_lib_handle)
330                 gl_lib_handle = dlopen("libGLESv2.so", RTLD_NOW);
331 #endif
332         if (!gl_lib_handle)
333         {
334                 ERR("\E[0;31;1mERROR : %s\E[0m\n\n", dlerror());
335                 ERR("\E[0;31;1mERROR : Invalid library link! (Check linkage of libCOREGL -> libGLESv2_drv)\E[0m\n");
336                 return 0;
337         }
338
339         // test for invalid linking gl
340         if (dlsym(gl_lib_handle, "coregl_symbol_exported"))
341         {
342                 ERR("\E[0;31;1mERROR : Invalid library link! (Check linkage of libCOREGL -> libGLESv2_drv)\E[0m\n");
343                 return 0;
344         }
345         //------------------------------------------------//
346
347 #else // GLX
348
349
350 #ifndef _COREGL_EMBED_EVAS
351         gl_lib_handle = dlopen("libGL_drv.so", RTLD_NOW);
352 #else
353         gl_lib_handle = dlopen("libGL.so.1", RTLD_NOW);
354         if (!gl_lib_handle)
355                 gl_lib_handle = dlopen("libGL.so", RTLD_NOW);
356 #endif
357         if (!gl_lib_handle)
358         {
359                 ERR("%s\n", dlerror());
360                 return 0;
361         }
362
363         //------------------------------------------------//
364
365 #endif // _COREGL_DESKTOP_GL
366
367         if (!_glue_sym_init()) return 0;
368         if (!_gl_sym_init()) return 0;
369
370         return 1;
371 }
372
373 extern void init_fast_gl();
374 extern void init_wrap_gl();
375
376 #ifndef _COREGL_EMBED_EVAS
377 __attribute__((constructor))
378 #endif
379 int
380 init_gl()
381 {
382         int fastpath_opt = 0;
383
384         LOG("[CoreGL] ");
385
386         if (!_gl_lib_init()) return 0;
387
388         fastpath_opt = atoi(get_env_setting("COREGL_FASTPATH"));
389
390         switch (fastpath_opt)
391         {
392                 case 1:
393                         api_opt = COREGL_FAST_PATH;
394                         LOG(": (%d) Fastpath enabled...\n", fastpath_opt);
395                         init_fast_gl();
396                         break;
397                 default:
398                         LOG(": (%d) Default API path enabled...\n", fastpath_opt);
399                         api_opt = COREGL_NORMAL_PATH;
400                         init_wrap_gl();
401                         break;
402         }
403
404 #ifdef COREGL_TRACE_APICALL_INFO
405         trace_api_flag = atoi(get_env_setting("COREGL_TRACE_API"));
406 #endif
407 #ifdef COREGL_TRACE_CONTEXT_INFO
408         trace_ctx_flag = atoi(get_env_setting("COREGL_TRACE_CTX"));
409 #endif
410 #ifdef COREGL_TRACE_STATE_INFO
411         trace_state_flag = atoi(get_env_setting("COREGL_TRACE_STATE"));
412 #endif
413
414         debug_nofp = atoi(get_env_setting("COREGL_DEBUG_NOFP"));
415
416
417         override_glue_apis(api_opt);
418         override_gl_apis(api_opt);
419
420         return 1;
421 }
422
423 extern void free_fast_gl();
424 extern void free_wrap_gl();
425
426 #ifndef _COREGL_EMBED_EVAS
427 __attribute__((destructor))
428 #endif
429 void
430 free_gl()
431 {
432         GLContext_List *current = NULL;
433
434         switch (api_opt)
435         {
436                 case COREGL_FAST_PATH:
437                         free_fast_gl();
438                         break;
439                 default:
440                         free_wrap_gl();
441                         break;
442         }
443
444         AST(mutex_lock(&ctx_list_access_mutex) == 1);
445
446         {
447                 // Destroy remained context & Detect leaks
448                 int retry_destroy = 0;
449
450                 while (1)
451                 {
452                         retry_destroy = 0;
453                         current = glctx_list;
454                         while (current)
455                         {
456                                 if (current->cstate != NULL)
457                                 {
458                                         ERR("\E[0;31;1mWARNING : Context attached to [dpy=%p|rctx=%p] has not been completely destroyed.(leak)\E[0m\n", current->cstate->rdpy, current->cstate->rctx);
459
460 #ifndef _COREGL_DESKTOP_GL
461                                         _sym_eglMakeCurrent(current->cstate->rdpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
462                                         _sym_eglDestroyContext(current->cstate->rdpy, current->cstate->rctx);
463 #else
464                                         _sym_glXDestroyContext(current->cstate->rdpy, current->cstate->rctx);
465 #endif
466
467                                         remove_context_states_from_list(current->cstate, NULL);
468                                         retry_destroy = 1;
469                                         break;
470                                 }
471
472                                 glctx_list = current->next;
473                                 free(current);
474                                 current = glctx_list;
475                         }
476                         if (retry_destroy == 0) break;
477                 }
478         }
479
480 #ifndef _COREGL_DESKTOP_GL
481         if (egl_lib_handle) dlclose(egl_lib_handle);
482 #endif
483         if (gl_lib_handle) dlclose(gl_lib_handle);
484         goto finish;
485
486 finish:
487         AST(mutex_unlock(&ctx_list_access_mutex) == 1);
488 }
489