Add fpgl-call error handling when makecurrent=null (instead of assertion)
[platform/core/uifw/coregl.git] / src / coregl_fastpath_egl.c
1 #include "coregl_fastpath.h"
2
3 #include <stdlib.h>
4 #include <string.h>
5 #include <sys/time.h>
6
7 #ifdef COREGL_TRACE_CONTEXT_INFO
8
9 General_Trace_List *glue_ctx_trace_list = NULL;
10 General_Trace_List *context_state_trace_list = NULL;
11
12 static void
13 _dump_context_info(const char *ment, int force_output)
14 {
15         GLThreadState *tstate = NULL;
16         static struct timeval tv_last = { 0, 0 };
17
18         if (trace_ctx_flag != 1) return;
19
20         AST(mutex_lock(&ctx_list_access_mutex) == 1);
21         AST(mutex_lock(&general_trace_lists_access_mutex) == 1);
22
23         if (!force_output && !trace_ctx_force_flag)
24         {
25                 struct timeval tv_now = { 0, 0 };
26                 AST(gettimeofday(&tv_now, NULL) == 0);
27                 if (tv_now.tv_sec - tv_last.tv_sec < _COREGL_TRACE_OUTPUT_INTERVAL_SEC)
28                 {
29                         goto finish;
30                 }
31                 tv_last = tv_now;
32         }
33
34         tstate = get_current_thread_state();
35
36         LOG("\n");
37         LOG("\E[40;34m========================================================================================================================\E[0m\n");
38         LOG("\E[40;32;1m  Context info \E[1;37;1m: %s\E[0m\n", ment);
39         LOG("\E[40;34m========================================================================================================================\E[0m\n");
40
41
42         // Thread State List
43         {
44                 General_Trace_List *current = NULL;
45                 current = thread_trace_list;
46
47                 while (current != NULL)
48                 {
49                         GLThreadState *cur_tstate = (GLThreadState *)current->value;
50
51                         LOG(" %c Thread  [%12d] : Surf <D=[%12p] R=[%12p]>",
52                             (tstate == cur_tstate) ? '*' : ' ',
53                             cur_tstate->thread_id,
54                             cur_tstate->rsurf_draw,
55                             cur_tstate->rsurf_read);
56
57                         if (cur_tstate->cstate != NULL)
58                         {
59                                 LOG(" GlueCTX=[%12p] RealCTX=[%12p]\E[0m\n",
60                                     cur_tstate->cstate->data,
61                                     cur_tstate->cstate);
62                         }
63                         else
64                         {
65                                 LOG(" (NOT BINDED TO THREAD)\E[0m\n");
66                         }
67
68                         // Binded Context State List
69                         {
70                                 General_Trace_List *current = NULL;
71                                 current = context_state_trace_list;
72
73                                 while (current != NULL)
74                                 {
75                                         GLContextState *cur_cstate = (GLContextState *)current->value;
76
77                                         if (cur_tstate->cstate == cur_cstate)
78                                         {
79                                                 LOG("   -> RealCTX [%12p] : EGLDPY=[%12p] EGLCTX=[%12p] <[%2d] GlueCTXs>\E[0m\n",
80                                                     cur_cstate,
81                                                     cur_cstate->rdpy,
82                                                     cur_cstate->rctx,
83                                                     cur_cstate->ref_count);
84
85                                                 // Binded Glue Context List
86                                                 {
87                                                         General_Trace_List *current = NULL;
88                                                         current = glue_ctx_trace_list;
89
90                                                         while (current != NULL)
91                                                         {
92                                                                 GLGlueContext *cur_gctx = (GLGlueContext *)current->value;
93
94                                                                 if (cur_gctx->cstate == cur_cstate)
95                                                                 {
96                                                                         LOG("    -%c GlueCTX [%12p] : EGLDPY=[%12p] TID=[%12d] <MC count [%10d]>",
97                                                                             (cur_cstate->data == cur_gctx) ? '>' : '-',
98                                                                             cur_gctx,
99                                                                             cur_gctx->rdpy,
100                                                                             cur_gctx->thread_id,
101                                                                             cur_gctx->used_count);
102
103                                                                         LOG(" <Ref [%2d]>\E[0m\n", cur_gctx->ref_count);
104                                                                 }
105
106                                                                 current = current->next;
107                                                         }
108                                                 }
109                                         }
110
111                                         current = current->next;
112                                 }
113
114                         }
115
116
117                         current = current->next;
118                 }
119         }
120
121         LOG("\E[40;33m........................................................................................................................\E[0m\n");
122
123         // Not-binded Context State List
124         {
125                 General_Trace_List *current = NULL;
126                 current = context_state_trace_list;
127
128                 while (current != NULL)
129                 {
130                         GLContextState *cur_cstate = (GLContextState *)current->value;
131
132                         int isbinded = 0;
133
134                         if (cur_cstate->data != NULL)
135                         {
136                                 General_Trace_List *current_t = NULL;
137                                 current_t = thread_trace_list;
138
139                                 while (current_t != NULL)
140                                 {
141                                         GLThreadState *cur_tstate = (GLThreadState *)current_t->value;
142
143                                         if (cur_tstate->thread_id == ((GLGlueContext *)cur_cstate->data)->thread_id)
144                                         {
145                                                 if (cur_tstate->cstate == cur_cstate)
146                                                         isbinded = 1;
147                                                 break;
148                                         }
149                                         current_t = current_t->next;
150                                 }
151                         }
152
153                         if (isbinded == 0)
154                         {
155                                 LOG("   RealCTX   [%12p] : EGLDPY=[%12p] EGLCTX=[%12p] <[%2d] GlueCTXs>\E[0m\n",
156                                     cur_cstate,
157                                     cur_cstate->rdpy,
158                                     cur_cstate->rctx,
159                                     cur_cstate->ref_count);
160
161                                 // Binded Glue Context List
162                                 {
163                                         General_Trace_List *current = NULL;
164                                         current = glue_ctx_trace_list;
165
166                                         while (current != NULL)
167                                         {
168                                                 GLGlueContext *cur_gctx = (GLGlueContext *)current->value;
169
170                                                 if (cur_gctx->cstate == cur_cstate)
171                                                 {
172                                                         LOG("    -%c GlueCTX [%12p] : EGLDPY=[%12p] TID=[%12d] <MC count [%10d]>",
173                                                             (cur_cstate->data == cur_gctx) ? '>' : '-',
174                                                             cur_gctx,
175                                                             cur_gctx->rdpy,
176                                                             cur_gctx->thread_id,
177                                                             cur_gctx->used_count);
178
179                                                         LOG(" <Ref [%2d]>\E[0m\n", cur_gctx->ref_count);
180                                                 }
181
182                                                 current = current->next;
183                                         }
184                                 }
185                         }
186
187                         current = current->next;
188                 }
189
190         }
191
192         LOG("\E[40;33m........................................................................................................................\E[0m\n");
193
194         // Not-binded Glue Context List
195         {
196                 General_Trace_List *current = NULL;
197                 current = glue_ctx_trace_list;
198
199                 while (current != NULL)
200                 {
201                         GLGlueContext *cur_gctx = (GLGlueContext *)current->value;
202
203                         if (cur_gctx->cstate == NULL)
204                         {
205                                 LOG("   GlueCTX [%12p]   : EGLDPY=[%12p] TID=[%12d] <MC count [%10d]>",
206                                     cur_gctx,
207                                     cur_gctx->rdpy,
208                                     cur_gctx->thread_id,
209                                     cur_gctx->used_count);
210
211                                 LOG(" <Ref [%2d]>\E[0m\n", cur_gctx->ref_count);
212                         }
213
214                         current = current->next;
215                 }
216         }
217
218         LOG("\E[40;34m========================================================================================================================\E[0m\n");
219         LOG("\n");
220
221         goto finish;
222
223 finish:
224
225         AST(mutex_unlock(&general_trace_lists_access_mutex) == 1);
226         AST(mutex_unlock(&ctx_list_access_mutex) == 1);
227
228 }
229
230 #endif // COREGL_TRACE_CONTEXT_INFO
231
232
233 typedef struct
234 {
235         EGLint                        context_client_version;
236 } EGL_packed_attrib_list;
237
238 typedef struct
239 {
240         EGLDisplay                    dpy;
241         EGLConfig                     cfg;
242         EGL_packed_attrib_list        attrib_list;
243         EGLint                                                          debug;
244 } EGL_packed_option;
245
246 typedef struct
247 {
248         EGLContext                    share_context;
249 } EGL_packed_sharable_option;
250
251
252 static int
253 _pack_egl_context_option(EGL_packed_option *pack_data, EGLDisplay dpy, EGLConfig cfg, EGLint debug, const EGLint *attrib_list)
254 {
255         int ret = 0;
256
257         pack_data->dpy = dpy;
258         pack_data->cfg = cfg;
259         pack_data->debug = debug;
260
261         // Default context attributes
262         pack_data->attrib_list.context_client_version = EGL_DONT_CARE;
263
264         // Apply specified attributes
265         EGLint *attrib = (EGLint *)attrib_list;
266         while(attrib[0] != EGL_NONE)
267         {
268                 switch(attrib[0])
269                 {
270                         case EGL_CONTEXT_CLIENT_VERSION:
271                                 pack_data->attrib_list.context_client_version = attrib[1];
272                                 break;
273                         default:
274                                 ERR("Invalid context attribute.\n");
275                                 goto finish;
276                 }
277                 attrib += 2;
278         }
279         ret = 1;
280         goto finish;
281
282 finish:
283         return ret;
284 }
285
286 static int
287 _unpack_egl_context_option(EGL_packed_option *pack_data, EGLDisplay *dpy, EGLConfig *cfg, EGLint *debug, EGLint *attrib_list, const int attrib_list_size)
288 {
289         int ret = 0;
290
291         if (dpy != NULL) *dpy = pack_data->dpy;
292         if (cfg != NULL) *cfg = pack_data->cfg;
293         if (debug != NULL) *debug = pack_data->debug;
294
295         if (attrib_list != NULL && attrib_list_size > 0)
296         {
297                 int attrib_list_index = 0;
298
299                 memset(attrib_list, 0x00, sizeof(int) * attrib_list_size);
300
301                 if (pack_data->attrib_list.context_client_version != EGL_DONT_CARE)
302                 {
303                         AST(attrib_list_index + 2 < attrib_list_size);
304                         attrib_list[attrib_list_index] = EGL_CONTEXT_CLIENT_VERSION;
305                         attrib_list[attrib_list_index + 1] = pack_data->attrib_list.context_client_version;
306                         attrib_list_index += 2;
307                 }
308
309                 attrib_list[attrib_list_index] = EGL_NONE;
310         }
311         ret = 1;
312         goto finish;
313
314 finish:
315         return ret;
316 }
317
318 static int
319 _pack_egl_context_sharable_option(EGL_packed_sharable_option *pack_data, EGLContext share_context)
320 {
321         int ret = 0;
322
323         pack_data->share_context = share_context;
324
325         ret = 1;
326         goto finish;
327
328 finish:
329         return ret;
330 }
331
332 #if 0
333 static int
334 _unpack_egl_context_sharable_option(EGL_packed_sharable_option *pack_data, EGLContext *share_context)
335 {
336         int ret = 0;
337
338         if (share_context != NULL) *share_context = pack_data->share_context;
339
340         ret = 1;
341         goto finish;
342
343 finish:
344         return ret;
345 }
346 #endif
347
348 static void
349 _link_context_state(GLGlueContext *gctx, GLContextState *cstate)
350 {
351         AST(gctx->cstate == NULL);
352         cstate->ref_count++;
353         gctx->cstate = cstate;
354 }
355
356 static void
357 _unlink_context_state(GLGlueContext *gctx, Mutex *ctx_list_mtx)
358 {
359         GLContextState *cstate = NULL;
360
361         cstate = gctx->cstate;
362         AST(cstate != NULL);
363
364         cstate->ref_count--;
365         AST(cstate->ref_count >= 0);
366
367         if (cstate->ref_count == 0)
368         {
369                 GLThreadState *tstate = NULL;
370
371                 AST(cstate->data == NULL || cstate->data == initial_ctx);
372
373 #ifdef COREGL_TRACE_CONTEXT_INFO
374                 remove_from_general_trace_list(&context_state_trace_list, cstate);
375 #endif // COREGL_TRACE_CONTEXT_INFO
376
377                 AST(remove_context_states_from_list(cstate, ctx_list_mtx) == 1);
378
379                 tstate = get_current_thread_state();
380                 if (tstate != NULL)
381                 {
382                         if (tstate->cstate == cstate)
383                         {
384                                 _sym_eglMakeCurrent(cstate->rdpy, tstate->rsurf_draw, tstate->rsurf_read, EGL_NO_CONTEXT);
385                                 tstate->cstate = NULL;
386                         }
387                 }
388                 _sym_eglDestroyContext(cstate->rdpy, cstate->rctx);
389                 free(cstate);
390                 cstate = NULL;
391         }
392 }
393
394 static void
395 _add_shared_obj_state_ref(GL_Shared_Object_State *sostate)
396 {
397         AST(sostate->ref_count >= 0);
398         sostate->ref_count++;
399 }
400
401 static void
402 _remove_shared_obj_state_ref(GL_Shared_Object_State *sostate)
403 {
404         AST(sostate->ref_count > 0);
405         sostate->ref_count--;
406         if (sostate->ref_count == 0)
407         {
408                 free(sostate);
409         }
410 }
411
412 static void
413 _add_context_ref(GLGlueContext *gctx)
414 {
415         if (gctx == initial_ctx) return;
416
417         AST(gctx->ref_count >= 0);
418         gctx->ref_count++;
419 }
420
421 static void
422 _remove_context_ref(GLGlueContext *gctx, Mutex *ctx_list_mtx)
423 {
424         if (gctx == initial_ctx) return;
425
426         AST(gctx->ref_count > 0);
427         gctx->ref_count--;
428         if (gctx->ref_count == 0)
429         {
430 #ifdef COREGL_TRACE_CONTEXT_INFO
431                 remove_from_general_trace_list(&glue_ctx_trace_list, gctx);
432 #endif // COREGL_TRACE_CONTEXT_INFO
433
434                 _unlink_context_state(gctx, ctx_list_mtx);
435
436                 AST(gctx->sostate != NULL);
437                 _remove_shared_obj_state_ref(gctx->sostate);
438                 gctx->sostate = NULL;
439
440                 if (gctx->real_ctx_option != NULL)
441                 {
442                         free(gctx->real_ctx_option);
443                         gctx->real_ctx_option = NULL;
444                 }
445                 if (gctx->real_ctx_sharable_option != NULL)
446                 {
447                         free(gctx->real_ctx_sharable_option);
448                         gctx->real_ctx_sharable_option = NULL;
449                 }
450                 free(gctx);
451         }
452 }
453
454 static void
455 _bind_context_state(GLGlueContext *gctx, GLContextState *cstate, Mutex *ctx_list_mtx)
456 {
457         if (gctx != NULL)
458         {
459                 AST(gctx->cstate == cstate);
460         }
461
462         if (cstate->data != gctx)
463         {
464                 GLGlueContext *curctx = (GLGlueContext *)cstate->data;
465                 GLGlueContext *newctx = gctx;
466
467                 if (newctx == NULL)
468                         newctx = initial_ctx;
469
470                 if (curctx == NULL)
471                         curctx = initial_ctx;
472
473                 AST(newctx != NULL);
474                 AST(curctx != NULL);
475
476                 make_context_current(curctx, newctx);
477                 cstate->data = (void *)newctx;
478                 _remove_context_ref(curctx, ctx_list_mtx);
479                 _add_context_ref(newctx);
480         }
481
482 }
483
484 GLContextState *
485 _egl_create_context(EGL_packed_option *real_ctx_option, GLContextState **cstate_new, EGLContext *ctx,
486                     EGLDisplay dpy, EGLConfig config, const EGLint* attrib_list)
487 {
488         GLContextState *cstate = NULL;
489
490         AST(real_ctx_option != NULL);
491         AST(cstate_new != NULL);
492         AST(ctx != NULL);
493
494         // Pack context option
495         AST(_pack_egl_context_option(real_ctx_option, dpy, config, 0, attrib_list) == 1);
496
497         if (debug_nofp == 1)
498         {
499                 static int debug_force_real = 100001;
500                 AST(_pack_egl_context_option(real_ctx_option, dpy, config, debug_force_real, attrib_list) == 1);
501                 debug_force_real++;
502         }
503
504         // Find context state
505         cstate = get_context_state_from_list(real_ctx_option, sizeof(EGL_packed_option), &ctx_list_access_mutex);
506
507         // Create a real context if it hasn't been created
508         if (cstate == NULL)
509         {
510                 EGLContext *real_share_context = EGL_NO_CONTEXT;
511
512                 AST(mutex_lock(&ctx_list_access_mutex) == 1);
513                 {
514                         GLContext_List *current = NULL;
515
516                         current = glctx_list;
517                         while (current != NULL)
518                         {
519                                 EGLDisplay cur_dpy = EGL_NO_DISPLAY;
520                                 AST(_unpack_egl_context_option(current->option, &cur_dpy, NULL, NULL, NULL, 0) == 1);
521                                 if (cur_dpy == dpy)
522                                 {
523                                         AST(current->cstate != NULL);
524                                         real_share_context = current->cstate->rctx;
525                                         break;
526                                 }
527                                 current = current->next;
528                         }
529                 }
530                 AST(mutex_unlock(&ctx_list_access_mutex) == 1);
531
532                 *ctx = _sym_eglCreateContext(dpy, config, real_share_context, attrib_list);
533
534                 if (*ctx == EGL_NO_CONTEXT)
535                 {
536                         ERR("Failed creating a egl real context for Fastpath.\n");
537                         goto finish;
538                 }
539
540                 *cstate_new = (GLContextState *)calloc(1, sizeof(GLContextState));
541                 if (*cstate_new == NULL)
542                 {
543                         ERR("Error creating a new context state.\n");
544                         goto finish;
545                 }
546                 (*cstate_new)->rctx = *ctx;
547                 (*cstate_new)->rdpy = dpy;
548                 (*cstate_new)->data = NULL;
549
550                 AST(add_context_state_to_list(real_ctx_option, sizeof(EGL_packed_option), *cstate_new, &ctx_list_access_mutex) == 1);
551
552 #ifdef COREGL_TRACE_CONTEXT_INFO
553                 add_to_general_trace_list(&context_state_trace_list, *cstate_new);
554 #endif // COREGL_TRACE_CONTEXT_INFO
555
556                 cstate = *cstate_new;
557         }
558
559         goto finish;
560
561 finish:
562         return cstate;
563
564 }
565
566
567
568
569 //----------------------------------------------------------------//
570 //                   Fastpath EGL Functions                       //
571 //    The functions have prefix 'fpgl_' for (fastpath gl)         //
572 //----------------------------------------------------------------//
573
574 extern EGLBoolean (*_COREGL_NAME_MANGLE(eglBindAPI))(EGLenum api);
575 extern EGLenum (*_COREGL_NAME_MANGLE(eglQueryAPI))(void);
576
577 EGLBoolean
578 fpgl_eglBindAPI(EGLenum api)
579 {
580         EGLBoolean ret = EGL_FALSE;
581         GLThreadState *tstate = NULL;
582
583         _COREGL_FAST_FUNC_BEGIN();
584         if (api_opt == COREGL_UNKNOWN_PATH) goto finish;
585
586         ret = _sym_eglBindAPI(api);
587
588         tstate = get_current_thread_state();
589         if (tstate == NULL)
590         {
591                 AST(init_new_thread_state() == 1);
592
593                 tstate = get_current_thread_state();
594                 AST(tstate != NULL);
595         }
596
597         {
598                 EGLenum newapi = _sym_eglQueryAPI();
599                 if (tstate->binded_api != newapi)
600                 {
601                         if (newapi != EGL_OPENGL_ES_API)
602                         {
603                                 // Fallback when binding other API
604                                 // Fastpath restores when bind OPENGL_ES_API
605                                 override_glue_normal_path();
606                                 _COREGL_NAME_MANGLE(eglBindAPI) = fpgl_eglBindAPI;
607                                 _COREGL_NAME_MANGLE(eglQueryAPI) = fpgl_eglQueryAPI;
608                         }
609                         else
610                         {
611                                 override_glue_fast_path();
612                         }
613                         tstate->binded_api = newapi;
614                 }
615         }
616
617         goto finish;
618
619 finish:
620         _COREGL_FAST_FUNC_END();
621         return ret;
622 }
623
624 EGLenum
625 fpgl_eglQueryAPI(void)
626 {
627         EGLenum ret = 0;
628         GLThreadState *tstate = NULL;
629
630         _COREGL_FAST_FUNC_BEGIN();
631         if (api_opt == COREGL_UNKNOWN_PATH) goto finish;
632
633         ret = _sym_eglQueryAPI();
634
635         tstate = get_current_thread_state();
636         if (tstate != NULL)
637         {
638                 AST(tstate->binded_api == ret);
639         }
640
641         goto finish;
642
643 finish:
644         _COREGL_FAST_FUNC_END();
645         return ret;
646 }
647
648 EGLContext
649 fpgl_eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint* attrib_list)
650 {
651         GLGlueContext *gctx = NULL;
652         GLContextState *cstate = NULL;
653         GLContextState *cstate_new = NULL;
654         GL_Shared_Object_State *sostate_new = NULL;
655         GLContext ctx = NULL;
656
657         EGL_packed_option *real_ctx_option = NULL;
658         EGL_packed_sharable_option *real_ctx_sharable_option = NULL;
659
660         _COREGL_FAST_FUNC_BEGIN();
661
662         real_ctx_option = (EGL_packed_option *)calloc(1, sizeof(EGL_packed_option));
663         if (real_ctx_option == NULL)
664         {
665                 ERR("Error creating a new GLGlueContext(1)\n");
666                 goto finish;
667         }
668         cstate = _egl_create_context(real_ctx_option, &cstate_new, &ctx, dpy, config, attrib_list);
669         AST(cstate != NULL);
670
671         // Pack shared context options
672         real_ctx_sharable_option = (EGL_packed_sharable_option *)calloc(1, sizeof(EGL_packed_sharable_option));
673         if (real_ctx_sharable_option == NULL)
674         {
675                 ERR("Error creating a new GLGlueContext(2)\n");
676                 goto finish;
677         }
678         AST(_pack_egl_context_sharable_option(real_ctx_sharable_option, share_context) == 1);
679
680         // Allocate a new context
681         gctx = (GLGlueContext *)calloc(1, sizeof(GLGlueContext));
682         if (gctx == NULL)
683         {
684                 ERR("Error creating a new GLGlueContext(3)\n");
685                 goto finish;
686         }
687
688         gctx->magic = MAGIC_GLFAST;
689         gctx->initialized = 0;
690         gctx->rdpy = dpy;
691         gctx->thread_id = get_current_thread();
692
693         if (share_context != EGL_NO_CONTEXT)
694         {
695                 GLGlueContext *shared_gctx = (GLGlueContext *)share_context;
696                 AST(shared_gctx->magic == MAGIC_GLFAST);
697                 AST(shared_gctx->sostate != NULL);
698                 gctx->sostate = shared_gctx->sostate;
699         }
700         else
701         {
702                 sostate_new = (GL_Shared_Object_State *)calloc(1, sizeof(GL_Shared_Object_State));
703                 if (sostate_new == NULL)
704                 {
705                         ERR("Error creating a new GLGlueContext(4)\n");
706                         goto finish;
707                 }
708                 gctx->sostate = sostate_new;
709         }
710         _add_shared_obj_state_ref(gctx->sostate);
711         gctx->real_ctx_option = real_ctx_option;
712         gctx->real_ctx_option_len = sizeof(EGL_packed_option);
713         gctx->real_ctx_sharable_option = real_ctx_sharable_option;
714         gctx->real_ctx_sharable_option_len = sizeof(EGL_packed_sharable_option);
715
716         _link_context_state(gctx, cstate);
717         _add_context_ref(gctx);
718
719         gctx->cstate = cstate;
720
721 #ifdef COREGL_TRACE_CONTEXT_INFO
722         add_to_general_trace_list(&glue_ctx_trace_list, gctx);
723
724         {
725                 char ment[256];
726                 sprintf(ment, "eglCreateContext completed (GlueCTX=[%12p])", gctx);
727                 _dump_context_info(ment, 1);
728         }
729 #endif // COREGL_TRACE_CONTEXT_INFO
730
731         goto finish;
732
733 finish:
734         if (gctx == NULL)
735         {
736                 if (ctx != NULL)
737                 {
738                         _sym_eglDestroyContext(dpy, ctx);
739                         ctx = NULL;
740                 }
741                 if (sostate_new != NULL)
742                 {
743                         free(sostate_new);
744                         sostate_new = NULL;
745                 }
746                 if (real_ctx_option != NULL)
747                 {
748                         free(real_ctx_option);
749                         real_ctx_option = NULL;
750                 }
751                 if (real_ctx_sharable_option != NULL)
752                 {
753                         free(real_ctx_sharable_option);
754                         real_ctx_sharable_option = NULL;
755                 }
756                 if (cstate_new != NULL)
757                 {
758 #ifdef COREGL_TRACE_CONTEXT_INFO
759                         remove_from_general_trace_list(&context_state_trace_list, cstate_new);
760 #endif // COREGL_TRACE_CONTEXT_INFO
761
762                         remove_context_states_from_list(cstate_new, &ctx_list_access_mutex);
763                         free(cstate_new);
764                         cstate_new = NULL;
765                 }
766         }
767
768         _COREGL_FAST_FUNC_END();
769         return (EGLContext)gctx;
770 }
771
772 EGLBoolean
773 fpgl_eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
774 {
775         EGLBoolean ret = EGL_FALSE;
776         GLGlueContext *gctx = NULL;
777
778         _COREGL_FAST_FUNC_BEGIN();
779
780         gctx = (GLGlueContext *)ctx;
781
782         if (gctx != NULL)
783         {
784                 GLContextState *cstate = NULL;
785                 if (gctx->magic != MAGIC_GLFAST)
786                 {
787                         ERR("Magic Check Failed!!!\n");
788                         ret = EGL_FALSE;
789                         goto finish;
790                 }
791                 cstate = gctx->cstate;
792                 AST(cstate != NULL);
793
794                 if (gctx->is_destroyed == 1)
795                 {
796                         ERR("\E[40;31;1mWARNING : Context [%p] is already destroyed!!!\E[0m\n", ctx);
797                 }
798                 else
799                 {
800                         gctx->is_destroyed = 1;
801                         _remove_context_ref(gctx, &ctx_list_access_mutex);
802                 }
803         }
804         else
805         {
806                 ERR("Invalid Context.\n");
807                 ret = EGL_FALSE;
808                 goto finish;
809         }
810
811         ret = EGL_TRUE;
812         goto finish;
813
814 finish:
815         _COREGL_FAST_FUNC_END();
816
817 #ifdef COREGL_TRACE_CONTEXT_INFO
818         {
819                 char ment[256];
820                 sprintf(ment, "eglDestroyContext completed (GlueCTX=[%12p])", ctx);
821                 _dump_context_info(ment, 1);
822         }
823 #endif // COREGL_TRACE_CONTEXT_INFO
824
825         return ret;
826 }
827
828 EGLBoolean
829 fpgl_eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
830 {
831         EGLBoolean ret = EGL_FALSE;
832         EGLContext real_ctx = EGL_NO_CONTEXT;
833
834         _COREGL_FAST_FUNC_BEGIN();
835
836         if (ctx != EGL_NO_CONTEXT)
837         {
838                 GLGlueContext *gctx = NULL;
839                 gctx = (GLGlueContext *)ctx;
840
841                 AST(gctx->cstate != NULL);
842                 real_ctx = gctx->cstate->rctx;
843         }
844
845         _COREGL_FAST_FUNC_SYMCALL_BEGIN();
846         ret = _sym_eglQueryContext(dpy, real_ctx, attribute, value);
847         _COREGL_FAST_FUNC_SYMCALL_END();
848         goto finish;
849
850 finish:
851         _COREGL_FAST_FUNC_END();
852         return ret;
853 }
854
855
856
857 EGLBoolean
858 fpgl_eglReleaseThread(void)
859 {
860         EGLBoolean ret = EGL_FALSE;
861         EGLDisplay dpy = EGL_NO_DISPLAY;
862
863         _COREGL_FAST_FUNC_BEGIN();
864
865         dpy = _sym_eglGetCurrentDisplay();
866         AST(dpy != EGL_NO_DISPLAY);
867         fpgl_eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
868         ret = _sym_eglReleaseThread();
869         goto finish;
870
871 finish:
872         _COREGL_FAST_FUNC_END();
873         return ret;
874 }
875
876
877
878 EGLBoolean
879 fpgl_eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
880 {
881         EGLBoolean ret = EGL_FALSE;
882         EGLBoolean need_mc = EGL_FALSE;
883         GLGlueContext *gctx = NULL;
884
885         GLThreadState *tstate = NULL;
886         GLContextState *cstate = NULL;
887
888         _COREGL_FAST_FUNC_BEGIN();
889
890         gctx = (GLGlueContext *)ctx;
891
892         tstate = get_current_thread_state();
893         if (tstate == NULL)
894         {
895                 AST(init_new_thread_state() == 1);
896
897                 tstate = get_current_thread_state();
898                 AST(tstate != NULL);
899         }
900
901         // Special path for context deletion
902         if (ctx == EGL_NO_CONTEXT)
903         {
904                 AST(gctx == NULL);
905
906                 if (tstate->cstate != NULL)
907                 {
908                         _bind_context_state(NULL, tstate->cstate, &ctx_list_access_mutex);
909                         tstate->cstate = NULL;
910                 }
911                 if (_sym_eglMakeCurrent(dpy, draw, read, ctx) != EGL_TRUE)
912                 {
913                         ERR("WARNING : Error making context [%p] current. (invalid EGL display [%p] or EGL surface [D:%p/R:%p])\n", ctx, dpy, draw, read);
914                         ret = EGL_FALSE;
915                         goto finish;
916                 }
917
918                 tstate->rsurf_draw = draw;
919                 tstate->rsurf_read = read;
920
921                 ret = EGL_TRUE;
922                 goto finish;
923         }
924
925         AST(gctx != NULL);
926         AST(gctx->cstate != NULL);
927
928         if (gctx->rdpy != dpy)
929         {
930                 ERR("Invalid context (or invalid EGL display)\n");
931                 ret = EGL_FALSE;
932                 goto finish;
933         }
934
935         AST(gctx->real_ctx_option != NULL);
936         AST(gctx->real_ctx_sharable_option != NULL);
937
938         // Handle cross threading of context (when used by two or more gctx)
939         if (gctx->thread_id != get_current_thread() && gctx->cstate->ref_count > 1)
940         {
941 #define ATTRIB_LIST_BUFFER_SIZE 8
942
943                 GLContextState *cstate_new = NULL;
944                 EGLContext new_real_ctx = EGL_NO_CONTEXT;
945
946                 EGLDisplay dpy = EGL_NO_DISPLAY;
947                 EGLConfig config = NULL;
948                 int attrib_list[ATTRIB_LIST_BUFFER_SIZE];
949
950                 AST(_unpack_egl_context_option(gctx->real_ctx_option, &dpy, &config, NULL, attrib_list, ATTRIB_LIST_BUFFER_SIZE) == 1);
951                 AST(dpy == gctx->rdpy);
952
953                 _egl_create_context(gctx->real_ctx_option, &cstate_new, &new_real_ctx, dpy, config, attrib_list);
954
955                 AST(cstate_new != NULL);
956
957                 _bind_context_state(gctx, cstate_new, &ctx_list_access_mutex);
958
959                 // TODO : Setup context state for new real ctx
960                 ERR("\E[40;31;1mWARNING : Cross-thread usage(makecurrent) can cause a state-broken situation!\E[0m\n");
961
962                 _unlink_context_state(gctx, &ctx_list_access_mutex);
963                 _link_context_state(gctx, cstate_new);
964
965                 // Apply to new thread
966                 gctx->thread_id = get_current_thread();
967
968         }
969
970         // Check if the object is correct
971         if (gctx->magic != MAGIC_GLFAST)
972         {
973                 ERR("Glue-CTX Magic Check Failed!!!\n");
974                 ret = EGL_FALSE;
975                 goto finish;
976
977         }
978
979         cstate = tstate->cstate;
980
981         // If it's a first time or drawable changed, do a make current
982         if (cstate == NULL)
983         {
984                 cstate = get_context_state_from_list(gctx->real_ctx_option, gctx->real_ctx_option_len, &ctx_list_access_mutex);
985
986                 if (cstate == NULL)
987                 {
988                         ERR("Error making context current because context not ready.\n");
989                         ret = EGL_FALSE;
990                         goto finish;
991                 }
992                 need_mc = EGL_TRUE;
993         }
994
995         // If drawable changed, do a make current
996         if ((tstate->rsurf_draw != draw) ||
997             (tstate->rsurf_read != read))
998                 need_mc = EGL_TRUE;
999
1000         AST(gctx->cstate != NULL);
1001
1002         // If binded real context changed, do a make current
1003         if (gctx->cstate->rctx != cstate->rctx)
1004                 need_mc = EGL_TRUE;
1005
1006         if (need_mc == EGL_TRUE)
1007         {
1008                 // BB : full makecurrent
1009                 if (_sym_eglMakeCurrent(dpy, draw, read, gctx->cstate->rctx) != EGL_TRUE)
1010                 {
1011                         ERR("Error making context current with the drawable.\n");
1012                         ret = EGL_FALSE;
1013                         goto finish;
1014                 }
1015
1016                 tstate->cstate = gctx->cstate;
1017
1018                 tstate->rsurf_draw = draw;
1019                 tstate->rsurf_read = read;
1020         }
1021
1022         // Initialize context states
1023         if (gctx->initialized == 0)
1024         {
1025                 if (init_context_states(gctx) != 1)
1026                 {
1027                         ERR("Error intializing context\n");
1028                         goto finish;
1029                 }
1030         }
1031
1032         // Setup initial Viewport & Scissor
1033         if (gctx->surface_attached == 0 && draw != EGL_NO_SURFACE)
1034         {
1035                 EGLint width;
1036                 EGLint height;
1037                 _sym_eglQuerySurface(dpy, draw, EGL_WIDTH, &width);
1038                 _sym_eglQuerySurface(dpy, draw, EGL_HEIGHT, &height);
1039
1040                 gctx->_clear_flag1 |= FLAG_BIT_0;
1041                 gctx->gl_viewport[0] = 0;
1042                 gctx->gl_viewport[1] = 0;
1043                 gctx->gl_viewport[2] = width;
1044                 gctx->gl_viewport[3] = height;
1045
1046                 gctx->_misc_flag2 |= FLAG_BIT_0;
1047                 gctx->gl_scissor_box[0] = 0;
1048                 gctx->gl_scissor_box[1] = 0;
1049                 gctx->gl_scissor_box[2] = width;
1050                 gctx->gl_scissor_box[3] = height;
1051
1052                 gctx->surface_attached = 1;
1053         }
1054
1055         _bind_context_state(gctx, tstate->cstate, &ctx_list_access_mutex);
1056         gctx->used_count++;
1057
1058         ret = EGL_TRUE;
1059         goto finish;
1060
1061 finish:
1062
1063         _COREGL_FAST_FUNC_END();
1064
1065 #ifdef COREGL_TRACE_CONTEXT_INFO
1066         {
1067                 char ment[256];
1068                 sprintf(ment, "eglMakeCurrent finished (GlueCTX=[%12p] Surf=[D:%12p R:%12p])", ctx, draw, read);
1069                 _dump_context_info(ment, 0);
1070         }
1071 #endif // COREGL_TRACE_CONTEXT_INFO
1072
1073         return ret;
1074 }
1075
1076
1077 EGLContext
1078 fpgl_eglGetCurrentContext(void)
1079 {
1080         GLGlueContext *ret = NULL;
1081         GLThreadState *tstate = NULL;
1082
1083         _COREGL_FAST_FUNC_BEGIN();
1084
1085         tstate = get_current_thread_state();
1086
1087         if (tstate != NULL)
1088         {
1089                 if (tstate->cstate != NULL)
1090                 {
1091                         ret = (GLGlueContext *)tstate->cstate->data;
1092                 }
1093         }
1094         goto finish;
1095
1096 finish:
1097         _COREGL_FAST_FUNC_END();
1098         return (EGLContext)ret;
1099 }
1100
1101
1102 EGLSurface
1103 fpgl_eglGetCurrentSurface(EGLint readdraw)
1104 {
1105         EGLSurface ret = EGL_NO_SURFACE;
1106         GLThreadState *tstate = NULL;
1107
1108         _COREGL_FAST_FUNC_BEGIN();
1109
1110         tstate = get_current_thread_state();
1111
1112         if (tstate != NULL)
1113         {
1114                 switch (readdraw)
1115                 {
1116                         case EGL_DRAW :
1117                                 ret = (GLGlueContext *)tstate->rsurf_draw;
1118                                 break;
1119                         case EGL_READ :
1120                                 ret = (GLGlueContext *)tstate->rsurf_read;
1121                                 break;
1122                 }
1123         }
1124         goto finish;
1125
1126 finish:
1127         _COREGL_FAST_FUNC_END();
1128         return ret;
1129 }
1130
1131 EGLImageKHR
1132 fpgl_eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
1133 {
1134         void *ret = NULL;
1135         EGLContext real_ctx = EGL_NO_CONTEXT;
1136
1137         _COREGL_FAST_FUNC_BEGIN();
1138
1139         if (ctx != NULL && ctx != EGL_NO_CONTEXT)
1140         {
1141                 GLGlueContext *gctx = (GLGlueContext *)ctx;
1142
1143                 if (gctx->magic != MAGIC_GLFAST)
1144                 {
1145                         real_ctx = ctx;
1146                 }
1147                 else
1148                 {
1149                         AST(gctx->cstate != NULL);
1150                         real_ctx = gctx->cstate->rctx;
1151                 }
1152         }
1153         ret = _sym_eglCreateImageKHR(dpy, real_ctx, target, buffer, attrib_list);
1154
1155         goto finish;
1156
1157 finish:
1158         _COREGL_FAST_FUNC_END();
1159         return ret;
1160 }
1161
1162 _eng_fn
1163 fpgl_eglGetProcAddress(const char* procname)
1164 {
1165         _eng_fn ret = NULL;
1166
1167         _COREGL_FAST_FUNC_BEGIN();
1168
1169 #define _COREGL_SYMBOL(IS_EXTENSION, RET_TYPE, FUNC_NAME, PARAM_LIST) \
1170         if (strcmp(procname, #FUNC_NAME) == 0) \
1171         { \
1172                 ret = (_eng_fn)FUNC_NAME; \
1173                 goto finish; \
1174         }
1175 #include "headers/sym_egl.h"
1176 #include "headers/sym_gl.h"
1177 #undef _COREGL_SYMBOL
1178
1179         ret = _sym_eglGetProcAddress(procname);
1180         if (ret != NULL)
1181         {
1182                 LOG("\E[40;31;1mWARNING : COREGL can't support '%s' (unmanaged situation may occur)\E[0m\n", procname);
1183         }
1184
1185         goto finish;
1186
1187 finish:
1188         _COREGL_FAST_FUNC_END();
1189         return ret;
1190 }
1191