Make log related global variables as local
[platform/core/uifw/coregl.git] / src / modules / coregl_fastpath_egl.c
1 #include "coregl_fastpath.h"
2
3 #include <stdlib.h>
4 #include <string.h>
5 #include <sys/time.h>
6 #include <execinfo.h>
7
8 #include <sys/types.h>
9 #include <unistd.h>
10 #include <signal.h>
11 #include <assert.h>
12 #include "../../include_KHR/EGL/eglext.h"
13
14 #ifdef COREGL_FASTPATH_TRACE_CONTEXT_INFO
15
16 General_Trace_List *glue_ctx_trace_list = NULL;
17 General_Trace_List *context_state_trace_list = NULL;
18 int current_gl_api_version = 0;
19
20 static void
21 _dump_context_info(const char *ment, int force_output)
22 {
23         MY_MODULE_TSTATE *tstate = NULL;
24         static struct timeval tv_last = { 0, 0 };
25
26         if (get_trace_ctx_flag() != 1) return;
27
28         AST(mutex_lock(&ctx_list_access_mutex) == 1);
29         AST(mutex_lock(&general_trace_lists_access_mutex) == 1);
30
31         if (!force_output && !get_trace_ctx_force_flag()) {
32                 struct timeval tv_now = { 0, 0 };
33                 AST(gettimeofday(&tv_now, NULL) == 0);
34                 if (tv_now.tv_sec - tv_last.tv_sec < _COREGL_TRACE_OUTPUT_INTERVAL_SEC) {
35                         goto finish;
36                 }
37                 tv_last = tv_now;
38         }
39
40         GET_MY_TSTATE(tstate, get_current_thread_state());
41
42         TRACE("\n");
43         TRACE("\E[40;34m========================================================================================================================\E[0m\n");
44         TRACE("\E[40;32;1m  Context info \E[1;37;1m: <PID = %d> %s\E[0m\n", getpid(),
45                   ment);
46         TRACE("\E[40;34m========================================================================================================================\E[0m\n");
47
48
49         // Thread State List
50         {
51                 General_Trace_List *current = NULL;
52                 current = thread_trace_list;
53
54                 while (current != NULL) {
55                         GLThreadState *cur_tstate = (GLThreadState *)current->value;
56                         MY_MODULE_TSTATE *cur_tstate_tm = NULL;
57
58                         GET_MY_TSTATE(cur_tstate_tm, cur_tstate);
59                         AST(cur_tstate_tm != NULL);
60
61                         if (cur_tstate_tm == NULL)
62                                 continue;
63
64                         TRACE(" %c Thread  [0x%12x] : Surf <D=[%12p] R=[%12p]>",
65                                   (tstate == cur_tstate_tm) ? '*' : ' ',
66                                   cur_tstate->thread_id,
67                                   cur_tstate_tm->rsurf_draw,
68                                   cur_tstate_tm->rsurf_read);
69
70                         if (cur_tstate_tm->cstate != NULL) {
71                                 TRACE(" GlueCTX=[%12p] RealCTX=[%12p]\E[0m\n",
72                                           cur_tstate_tm->cstate->data,
73                                           cur_tstate_tm->cstate);
74                         } else {
75                                 TRACE(" (NOT BINDED TO THREAD)\E[0m\n");
76                         }
77
78                         // Binded Context State List
79                         {
80                                 General_Trace_List *current = NULL;
81                                 current = context_state_trace_list;
82
83                                 while (current != NULL) {
84                                         GLContextState *cur_cstate = (GLContextState *)current->value;
85                                         MY_MODULE_TSTATE *cur_tstate_tm = NULL;
86
87                                         GET_MY_TSTATE(cur_tstate_tm, cur_tstate);
88                                         AST(cur_tstate_tm != NULL);
89
90                                         if (cur_tstate_tm != NULL && cur_tstate_tm->cstate == cur_cstate) {
91                                                 TRACE("   -> RealCTX [%12p] : EGLDPY=[%12p] EGLCTX=[%12p] <[%2d] GlueCTXs>\E[0m\n",
92                                                           cur_cstate,
93                                                           cur_cstate->rdpy,
94                                                           cur_cstate->rctx,
95                                                           cur_cstate->ref_count);
96
97                                                 // Binded Glue Context List
98                                                 {
99                                                         General_Trace_List *current = NULL;
100                                                         current = glue_ctx_trace_list;
101
102                                                         while (current != NULL) {
103                                                                 GLGlueContext *cur_gctx = (GLGlueContext *)current->value;
104
105                                                                 if (cur_gctx->cstate == cur_cstate) {
106                                                                         TRACE("    -%c GlueCTX [%12p] : EGLDPY=[%12p] TID=[%12d] <MC count [%10d]>",
107                                                                                   (cur_cstate->data == cur_gctx) ? '>' : '-',
108                                                                                   cur_gctx,
109                                                                                   cur_gctx->rdpy,
110                                                                                   cur_gctx->thread_id,
111                                                                                   cur_gctx->used_count);
112
113                                                                         TRACE(" <Ref [%2d]>\E[0m\n", cur_gctx->ref_count);
114                                                                 }
115
116                                                                 current = current->next;
117                                                         }
118                                                 }
119                                         }
120
121                                         current = current->next;
122                                 }
123
124                         }
125
126
127                         current = current->next;
128                 }
129         }
130
131         TRACE("\E[40;33m........................................................................................................................\E[0m\n");
132
133         // Not-binded Context State List
134         {
135                 General_Trace_List *current = NULL;
136                 current = context_state_trace_list;
137
138                 while (current != NULL) {
139                         GLContextState *cur_cstate = (GLContextState *)current->value;
140
141                         int isbinded = 0;
142
143                         if (cur_cstate->data != NULL) {
144                                 General_Trace_List *current_t = NULL;
145                                 current_t = thread_trace_list;
146
147                                 while (current_t != NULL) {
148                                         GLThreadState *cur_tstate = (GLThreadState *)current_t->value;
149                                         MY_MODULE_TSTATE *cur_tstate_tm = NULL;
150
151                                         GET_MY_TSTATE(cur_tstate_tm, cur_tstate);
152                                         AST(cur_tstate_tm != NULL);
153
154                                         if (cur_tstate_tm != NULL
155                                                         && cur_tstate->thread_id == ((GLGlueContext *)cur_cstate->data)->thread_id) {
156                                                 if (cur_tstate_tm->cstate == cur_cstate)
157                                                         isbinded = 1;
158                                                 break;
159                                         }
160                                         current_t = current_t->next;
161                                 }
162                         }
163
164                         if (isbinded == 0) {
165                                 TRACE("   RealCTX   [%12p] : EGLDPY=[%12p] EGLCTX=[%12p] <[%2d] GlueCTXs>\E[0m\n",
166                                           cur_cstate,
167                                           cur_cstate->rdpy,
168                                           cur_cstate->rctx,
169                                           cur_cstate->ref_count);
170
171                                 // Binded Glue Context List
172                                 {
173                                         General_Trace_List *current = NULL;
174                                         current = glue_ctx_trace_list;
175
176                                         while (current != NULL) {
177                                                 GLGlueContext *cur_gctx = (GLGlueContext *)current->value;
178
179                                                 if (cur_gctx->cstate == cur_cstate) {
180                                                         TRACE("    -%c GlueCTX [%12p] : EGLDPY=[%12p] TID=[%12d] <MC count [%10d]>",
181                                                                   (cur_cstate->data == cur_gctx) ? '>' : '-',
182                                                                   cur_gctx,
183                                                                   cur_gctx->rdpy,
184                                                                   cur_gctx->thread_id,
185                                                                   cur_gctx->used_count);
186
187                                                         TRACE(" <Ref [%2d]>\E[0m\n", cur_gctx->ref_count);
188                                                 }
189
190                                                 current = current->next;
191                                         }
192                                 }
193                         }
194
195                         current = current->next;
196                 }
197
198         }
199
200         TRACE("\E[40;33m........................................................................................................................\E[0m\n");
201
202         // Not-binded Glue Context List
203         {
204                 General_Trace_List *current = NULL;
205                 current = glue_ctx_trace_list;
206
207                 while (current != NULL) {
208                         GLGlueContext *cur_gctx = (GLGlueContext *)current->value;
209
210                         if (cur_gctx->cstate == NULL) {
211                                 TRACE("   GlueCTX [%12p]   : EGLDPY=[%12p] TID=[%12d] <MC count [%10d]>",
212                                           cur_gctx,
213                                           cur_gctx->rdpy,
214                                           cur_gctx->thread_id,
215                                           cur_gctx->used_count);
216
217                                 TRACE(" <Ref [%2d]>\E[0m\n", cur_gctx->ref_count);
218                         }
219
220                         current = current->next;
221                 }
222         }
223
224         TRACE("\E[40;34m========================================================================================================================\E[0m\n");
225         TRACE("\n");
226
227         TRACE_END();
228
229         goto finish;
230
231 finish:
232
233         AST(mutex_unlock(&general_trace_lists_access_mutex) == 1);
234         AST(mutex_unlock(&ctx_list_access_mutex) == 1);
235
236 }
237
238 #endif // COREGL_FASTPATH_TRACE_CONTEXT_INFO
239
240
241 typedef struct {
242         EGLint                        context_major_version;
243         EGLint                        context_minor_version;
244         EGLint                        context_flags;
245         EGLint                        context_opengl_profile_mask;
246         EGLint                        opengl_robust_access_ext;
247         EGLint                        opengl_reset_notification_strategy_khr;
248         EGLint                        opengl_reset_notification_strategy_ext;
249 } EGL_packed_attrib_list;
250
251 typedef struct {
252         EGLDisplay                    dpy;
253         EGLConfig                     cfg;
254         EGL_packed_attrib_list        attrib_list;
255         EGLint                                                          force_unique;
256 } EGL_packed_option;
257
258 typedef struct {
259         EGLContext                    share_context;
260 } EGL_packed_sharable_option;
261
262
263 static int
264 _pack_egl_context_option(EGL_packed_option *pack_data, EGLDisplay dpy,
265                                                  EGLConfig cfg, EGLint force_unique, const EGLint *attrib_list)
266 {
267         static int force_unique_free_id = 0;
268         int ret = 0;
269
270         pack_data->dpy = dpy;
271         pack_data->cfg = cfg;
272         if (force_unique != 0)
273                 pack_data->force_unique = force_unique_free_id++;
274
275         // Default context attributes
276         pack_data->attrib_list.context_major_version = 1;
277         pack_data->attrib_list.context_minor_version = 0;
278         pack_data->attrib_list.context_flags = EGL_DONT_CARE;
279         pack_data->attrib_list.context_opengl_profile_mask = EGL_DONT_CARE;
280         pack_data->attrib_list.opengl_robust_access_ext = EGL_DONT_CARE;
281         pack_data->attrib_list.opengl_reset_notification_strategy_khr = EGL_DONT_CARE;
282         pack_data->attrib_list.opengl_reset_notification_strategy_ext = EGL_DONT_CARE;
283
284         // Apply specified attributes
285         EGLint *attrib = (EGLint *)attrib_list;
286         while ((attrib != NULL) && (attrib[0] != EGL_NONE)) {
287                 switch (attrib[0]) {
288                 case EGL_CONTEXT_MAJOR_VERSION_KHR: // EGL_CONTEXT_CLIENT_VERSION
289                         pack_data->attrib_list.context_major_version = attrib[1];
290                         break;
291                 case EGL_CONTEXT_MINOR_VERSION_KHR:
292                         pack_data->attrib_list.context_minor_version = attrib[1];
293                         break;
294                 case EGL_CONTEXT_FLAGS_KHR:
295                         pack_data->attrib_list.context_flags = attrib[1];
296                         break;
297                 case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
298                         pack_data->attrib_list.context_opengl_profile_mask = attrib[1];
299                         break;
300                 case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
301                         pack_data->attrib_list.opengl_robust_access_ext = attrib[1];
302                         break;
303                 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
304                         pack_data->attrib_list.opengl_reset_notification_strategy_khr = attrib[1];
305                         break;
306                 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
307                         pack_data->attrib_list.opengl_reset_notification_strategy_ext = attrib[1];
308                         break;
309                 default:
310                         COREGL_WARN("Invalid context attribute.");
311                         goto finish;
312                 }
313                 attrib += 2;
314         }
315
316         // Eject condition for context version
317         if (pack_data->attrib_list.context_major_version != 2) {
318                 pack_data->force_unique = force_unique_free_id;
319         }
320
321         ret = 1;
322         goto finish;
323
324 finish:
325         return ret;
326 }
327
328 static int
329 _unpack_egl_context_option(EGL_packed_option *pack_data, EGLDisplay *dpy,
330                                                    EGLConfig *cfg, EGLint *force_unique, EGLint *attrib_list,
331                                                    const int attrib_list_size)
332 {
333         int ret = 0;
334
335         if (dpy != NULL) *dpy = pack_data->dpy;
336         if (cfg != NULL) *cfg = pack_data->cfg;
337         if (force_unique != NULL) *force_unique = pack_data->force_unique;
338
339         if (attrib_list != NULL && attrib_list_size > 0) {
340                 int attrib_list_index = 0;
341
342                 memset(attrib_list, 0x00, sizeof(int) * attrib_list_size);
343
344                 if (pack_data->attrib_list.context_major_version != EGL_DONT_CARE) {
345                         AST(attrib_list_index + 2 < attrib_list_size);
346                         attrib_list[attrib_list_index] = EGL_CONTEXT_MAJOR_VERSION_KHR;
347                         attrib_list[attrib_list_index + 1] =
348                                 pack_data->attrib_list.context_major_version;
349                         attrib_list_index += 2;
350                 }
351                 if (pack_data->attrib_list.context_minor_version != EGL_DONT_CARE) {
352                         AST(attrib_list_index + 2 < attrib_list_size);
353                         attrib_list[attrib_list_index] = EGL_CONTEXT_MINOR_VERSION_KHR;
354                         attrib_list[attrib_list_index + 1] =
355                                 pack_data->attrib_list.context_minor_version;
356                         attrib_list_index += 2;
357                 }
358                 if (pack_data->attrib_list.context_flags != EGL_DONT_CARE) {
359                         AST(attrib_list_index + 2 < attrib_list_size);
360                         attrib_list[attrib_list_index] = EGL_CONTEXT_FLAGS_KHR;
361                         attrib_list[attrib_list_index + 1] = pack_data->attrib_list.context_flags;
362                         attrib_list_index += 2;
363                 }
364                 if (pack_data->attrib_list.context_opengl_profile_mask != EGL_DONT_CARE) {
365                         AST(attrib_list_index + 2 < attrib_list_size);
366                         attrib_list[attrib_list_index] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR;
367                         attrib_list[attrib_list_index + 1] =
368                                 pack_data->attrib_list.context_opengl_profile_mask;
369                         attrib_list_index += 2;
370                 }
371                 if (pack_data->attrib_list.opengl_robust_access_ext != EGL_DONT_CARE) {
372                         AST(attrib_list_index + 2 < attrib_list_size);
373                         attrib_list[attrib_list_index] =
374                                 EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT;
375                         attrib_list[attrib_list_index + 1] =
376                                 pack_data->attrib_list.opengl_robust_access_ext;
377                         attrib_list_index += 2;
378                 }
379                 if (pack_data->attrib_list.opengl_reset_notification_strategy_khr !=
380                                 EGL_DONT_CARE) {
381                         AST(attrib_list_index + 2 < attrib_list_size);
382                         attrib_list[attrib_list_index] =
383                                 EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR;
384                         attrib_list[attrib_list_index + 1] =
385                                 pack_data->attrib_list.opengl_reset_notification_strategy_khr;
386                         attrib_list_index += 2;
387                 }
388                 if (pack_data->attrib_list.opengl_reset_notification_strategy_ext !=
389                                 EGL_DONT_CARE) {
390                         AST(attrib_list_index + 2 < attrib_list_size);
391                         attrib_list[attrib_list_index] =
392                                 EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT;
393                         attrib_list[attrib_list_index + 1] =
394                                 pack_data->attrib_list.opengl_reset_notification_strategy_ext;
395                         attrib_list_index += 2;
396                 }
397
398                 attrib_list[attrib_list_index] = EGL_NONE;
399         }
400         ret = 1;
401         goto finish;
402
403 finish:
404         return ret;
405 }
406
407 static int
408 _pack_egl_context_sharable_option(EGL_packed_sharable_option *pack_data,
409                                                                   EGLContext share_context)
410 {
411         int ret = 0;
412
413         pack_data->share_context = share_context;
414
415         ret = 1;
416         goto finish;
417
418 finish:
419         return ret;
420 }
421
422 #if 0
423 static int
424 _unpack_egl_context_sharable_option(EGL_packed_sharable_option *pack_data,
425                                                                         EGLContext *share_context)
426 {
427         int ret = 0;
428
429         if (share_context != NULL) *share_context = pack_data->share_context;
430
431         ret = 1;
432         goto finish;
433
434 finish:
435         return ret;
436 }
437 #endif
438
439 static void
440 _link_context_state(GLGlueContext *gctx, GLContextState *cstate)
441 {
442         AST(gctx->cstate == NULL);
443         cstate->ref_count++;
444         gctx->cstate = cstate;
445 }
446
447 static void
448 _unlink_context_state(GLGlueContext *gctx, Mutex *ctx_list_mtx)
449 {
450         GLContextState *cstate = NULL;
451
452         cstate = gctx->cstate;
453         AST(cstate != NULL);
454
455         cstate->ref_count--;
456         AST(cstate->ref_count >= 0);
457
458         if (cstate->ref_count == 0) {
459                 MY_MODULE_TSTATE *tstate = NULL;
460
461                 AST(cstate->data == NULL || cstate->data == initial_ctx);
462
463 #ifdef COREGL_FASTPATH_TRACE_CONTEXT_INFO
464                 if (unlikely(get_trace_ctx_flag() == 1))
465                         remove_from_general_trace_list(&context_state_trace_list, cstate);
466 #endif // COREGL_FASTPATH_TRACE_CONTEXT_INFO
467
468                 AST(fastpath_remove_context_states_from_list(cstate, ctx_list_mtx) == 1);
469
470                 GET_MY_TSTATE(tstate, get_current_thread_state());
471                 if (tstate != NULL) {
472                         if (tstate->cstate == cstate) {
473                                 _orig_fastpath_eglMakeCurrent(cstate->rdpy, tstate->rsurf_draw,
474                                                                                           tstate->rsurf_read, EGL_NO_CONTEXT);
475                                 tstate->cstate = NULL;
476                         }
477                 }
478                 _orig_fastpath_eglDestroyContext(cstate->rdpy, cstate->rctx);
479                 free(cstate);
480                 cstate = NULL;
481         }
482 }
483
484 static void
485 _add_shared_obj_state_ref(GLGlueContext *gctx, GL_Shared_Object_State *sostate)
486 {
487         AST(sostate->ref_count >= 0);
488         sostate->ref_count++;
489         add_to_general_trace_list(&sostate->using_gctxs, gctx);
490 }
491
492 static void
493 _remove_shared_obj_state_ref(GLGlueContext *gctx,
494                                                          GL_Shared_Object_State *sostate)
495 {
496         remove_from_general_trace_list(&sostate->using_gctxs, gctx);
497
498         // Restore attached states
499         fastpath_release_gl_context(gctx);
500
501         AST(sostate->ref_count > 0);
502         sostate->ref_count--;
503         if (sostate->ref_count == 0) {
504                 fastpath_sostate_deinit(sostate);
505                 free(sostate);
506         }
507 }
508
509 static void
510 _add_context_ref(GLGlueContext *gctx)
511 {
512         if (gctx == initial_ctx) return;
513
514         AST(gctx->ref_count >= 0);
515         gctx->ref_count++;
516 }
517
518 static void
519 _remove_context_ref(GLGlueContext *gctx, Mutex *ctx_list_mtx)
520 {
521         if (gctx == initial_ctx) return;
522
523         AST(gctx->ref_count > 0);
524         gctx->ref_count--;
525         if (gctx->ref_count == 0) {
526 #ifdef COREGL_FASTPATH_TRACE_CONTEXT_INFO
527                 if (unlikely(get_trace_ctx_flag() == 1))
528                         remove_from_general_trace_list(&glue_ctx_trace_list, gctx);
529 #endif // COREGL_FASTPATH_TRACE_CONTEXT_INFO
530
531                 AST(gctx->cstate != NULL);
532                 if (gctx->cstate->data == gctx)
533                         gctx->cstate->data = NULL;
534
535                 _unlink_context_state(gctx, ctx_list_mtx);
536
537                 AST(gctx->ostate.shared != NULL);
538                 _remove_shared_obj_state_ref(gctx, gctx->ostate.shared);
539                 gctx->ostate.shared = NULL;
540
541                 fastpath_ostate_deinit(&gctx->ostate);
542
543                 if (gctx->real_ctx_option != NULL) {
544                         free(gctx->real_ctx_option);
545                         gctx->real_ctx_option = NULL;
546                 }
547                 if (gctx->real_ctx_sharable_option != NULL) {
548                         free(gctx->real_ctx_sharable_option);
549                         gctx->real_ctx_sharable_option = NULL;
550                 }
551
552 # define GLUE_STATE(TYPE, NAME, SIZE, ARRAY_SIZE, DEFAULT_STMT, GET_STMT)  \
553         if (gctx->NAME) {free(gctx->NAME); gctx->NAME = NULL;}  \
554         if (gctx->NAME##_updated){free(gctx->NAME##_updated); gctx->NAME##_updated = NULL;}
555 #  include "coregl_fastpath_state.h"
556 #undef GLUE_STATE
557                 free(gctx);
558
559                 {
560                         GLGlueContext_List *current = NULL;
561
562                         AST(mutex_lock(&ctx_list_access_mutex) == 1);
563
564                         current = gctx_list;
565
566                         while (current != NULL) {
567                                 if (current->gctx == gctx) {
568                                         if (current->next != NULL)
569                                                 current->next->prev = current->prev;
570
571                                         if (current->prev != NULL)
572                                                 current->prev->next = current->next;
573                                         else
574                                                 gctx_list = current->next;
575
576                                         free(current);
577
578                                         break;
579                                 }
580                                 current = current->next;
581                         }
582
583                         AST(mutex_unlock(&ctx_list_access_mutex) == 1);
584                 }
585         }
586 }
587
588 static int
589 _bind_context_state(GLGlueContext *gctx, GLContextState *cstate,
590                                         Mutex *ctx_list_mtx)
591 {
592         if (gctx != NULL) {
593                 AST(gctx->cstate == cstate);
594         }
595
596         if (cstate->data != gctx) {
597                 GLGlueContext *curctx = (GLGlueContext *)cstate->data;
598                 GLGlueContext *newctx = gctx;
599
600                 if (newctx == NULL)
601                         newctx = initial_ctx;
602
603                 if (curctx == NULL)
604                         curctx = initial_ctx;
605
606                 AST(newctx != NULL);
607                 AST(curctx != NULL);
608
609                 if (!fastpath_make_context_current(curctx, newctx))
610                         return 0;
611
612                 cstate->data = (void *)newctx;
613                 _remove_context_ref(curctx, ctx_list_mtx);
614                 _add_context_ref(newctx);
615         }
616
617         return 1;
618
619 }
620
621 GLContextState *
622 _egl_create_context(EGL_packed_option *real_ctx_option,
623                                         GLContextState **cstate_new, EGLContext *ctx,
624                                         EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
625 {
626         GLContextState *cstate = NULL;
627
628         AST(real_ctx_option != NULL);
629         AST(cstate_new != NULL);
630         AST(ctx != NULL);
631
632         // Pack context option
633         AST(_pack_egl_context_option(real_ctx_option, dpy, config, 0,
634                                                                  attrib_list) == 1);
635
636         if (debug_nofp == 1) {
637                 AST(_pack_egl_context_option(real_ctx_option, dpy, config, 1,
638                                                                          attrib_list) == 1);
639         }
640
641         // Find context state
642         if (real_ctx_option->force_unique == 0) {
643                 cstate = fastpath_get_context_state_from_list(real_ctx_option,
644                                  sizeof(EGL_packed_option), &ctx_list_access_mutex);
645         }
646
647         // Create a real context if it hasn't been created
648         if (cstate == NULL) {
649                 EGLContext *real_share_context = EGL_NO_CONTEXT;
650
651                 AST(mutex_lock(&ctx_list_access_mutex) == 1);
652                 {
653                         GLContext_List *current = NULL;
654
655                         current = glctx_list;
656                         while (current != NULL) {
657                                 EGLDisplay cur_dpy = EGL_NO_DISPLAY;
658                                 EGLint attribs[15];
659                                 _unpack_egl_context_option(current->option, &cur_dpy, NULL, NULL, attribs, 15);
660                                 if (cur_dpy == dpy) {
661                                         if (attribs[0] == EGL_CONTEXT_MAJOR_VERSION_KHR &&
662                                                         attribs[1] != real_ctx_option->attrib_list.context_major_version) {
663                                                 current = current->next;
664                                                 continue;
665                                         }
666
667                                         AST(current->cstate != NULL);
668                                         real_share_context = current->cstate->rctx;
669                                         break;
670                                 }
671                                 current = current->next;
672                         }
673                 }
674                 AST(mutex_unlock(&ctx_list_access_mutex) == 1);
675
676                 *ctx = _orig_fastpath_eglCreateContext(dpy, config, real_share_context,
677                                                                                            attrib_list);
678
679                 if (*ctx == EGL_NO_CONTEXT) {
680                         COREGL_WARN("Failed creating a egl real context for Fastpath. (Invalid config?)");
681                         goto finish;
682                 }
683
684                 *cstate_new = (GLContextState *)calloc(1, sizeof(GLContextState));
685                 if (*cstate_new == NULL) {
686                         COREGL_ERR("Error creating a new context state. (Memory full)");
687                         goto finish;
688                 }
689                 (*cstate_new)->rctx = *ctx;
690                 (*cstate_new)->rdpy = dpy;
691                 (*cstate_new)->data = NULL;
692
693                 AST(fastpath_add_context_state_to_list(real_ctx_option,
694                                                                                            sizeof(EGL_packed_option), *cstate_new, &ctx_list_access_mutex) == 1);
695
696 #ifdef COREGL_FASTPATH_TRACE_CONTEXT_INFO
697                 if (unlikely(get_trace_ctx_flag() == 1))
698                         add_to_general_trace_list(&context_state_trace_list, *cstate_new);
699 #endif // COREGL_FASTPATH_TRACE_CONTEXT_INFO
700
701                 cstate = *cstate_new;
702         }
703
704         goto finish;
705
706 finish:
707         return cstate;
708 }
709
710 #define ATTRIB_LIST_BUFFER_SIZE 8
711
712 static int
713 fastpath_create_context(GLGlueContext *gctx)
714 {
715         GLContextState *cstate_new = NULL;
716         EGLContext new_real_ctx = EGL_NO_CONTEXT;
717         EGLDisplay dpy = EGL_NO_DISPLAY;
718         EGLConfig config = NULL;
719         int attrib_list[ATTRIB_LIST_BUFFER_SIZE];
720         int ret = EGL_TRUE;
721
722         AST(_unpack_egl_context_option(gctx->real_ctx_option, &dpy, &config, NULL,
723                                                                    attrib_list, ATTRIB_LIST_BUFFER_SIZE) == 1);
724         AST(dpy == gctx->rdpy);
725
726         _egl_create_context(gctx->real_ctx_option, &cstate_new, &new_real_ctx, dpy,
727                                                 config, attrib_list);
728
729         AST(cstate_new != NULL);
730
731         if (_bind_context_state(gctx, cstate_new, &ctx_list_access_mutex) != 1) {
732                 COREGL_WARN("Error soft-makecurrent in Cross-thread usage!");
733                 free(cstate_new);
734                 _orig_fastpath_eglDestroyContext(dpy, new_real_ctx);
735                 ret = EGL_FALSE;
736                 return ret;
737         }
738
739         /* TODO : Setup context state for new real ctx */
740         COREGL_WARN("Cross-thread usage(makecurrent) can cause a state-broken situation!");
741
742         _unlink_context_state(gctx, &ctx_list_access_mutex);
743         _link_context_state(gctx, cstate_new);
744
745         /* Apply to new thread */
746         gctx->thread_id = get_current_thread();
747
748         return ret;
749 }
750
751 static void
752 fastpath_init_viewport_and_scissor(GLGlueContext *gctx)
753 {
754         EGLint box_buffer[4];
755         EGLint width = 0;
756         EGLint height = 0;
757
758         _orig_fastpath_glGetIntegerv(GL_VIEWPORT, box_buffer);
759         width = box_buffer[2];
760         height = box_buffer[3];
761
762         gctx->_clear_flag1 |= _CLEAR_FLAG1_BIT_gl_viewport;
763         if (&gctx->gl_viewport[0]) gctx->gl_viewport[0] = 0;
764         if (&gctx->gl_viewport[1]) gctx->gl_viewport[1] = 0;
765         if (&gctx->gl_viewport[2]) gctx->gl_viewport[2] = width;
766         if (&gctx->gl_viewport[3]) gctx->gl_viewport[3] = height;
767
768         _orig_fastpath_glGetIntegerv(GL_SCISSOR_BOX, box_buffer);
769         width = box_buffer[2];
770         height = box_buffer[3];
771
772         gctx->_misc_flag2 |= _MISC_FLAG2_BIT_gl_scissor_box;
773         if (&gctx->gl_scissor_box[0]) gctx->gl_scissor_box[0] = 0;
774         if (&gctx->gl_scissor_box[1]) gctx->gl_scissor_box[1] = 0;
775         if (&gctx->gl_scissor_box[2]) gctx->gl_scissor_box[2] = width;
776         if (&gctx->gl_scissor_box[3]) gctx->gl_scissor_box[3] = height;
777
778         gctx->surface_attached = 1;
779 }
780
781 static int
782 fastpath_update_context(GLGlueContext *gctx, MY_MODULE_TSTATE *tstate,
783                                                            EGLDisplay dpy, EGLSurface draw, EGLSurface read, int *api_version)
784 {
785         int ret = EGL_TRUE;
786
787         AST(dpy == gctx->cstate->rdpy);
788
789         /* BB : full makecurrent */
790         if (_orig_fastpath_eglMakeCurrent(dpy, draw, read, gctx->cstate->rctx) != EGL_TRUE) {
791                 COREGL_WARN("Error making context current with the drawable. (Bad match?)");
792                 ret = EGL_FALSE;
793                 return ret;
794         }
795
796         *api_version = ((EGL_packed_option *)
797                                    gctx->real_ctx_option)->attrib_list.context_major_version;
798
799         /* Change overriding for modules according to new API version */
800         if (USE_TRACEPATH || (fp_opt == FP_FAST_PATH)) {
801                 if (!current_gl_api_version) {
802                         current_gl_api_version = *api_version;
803                         if (current_gl_api_version == COREGL_GLAPI_1) {
804                                 init_export(GL_FALSE, GL_TRUE);
805                                 COREGL_DBG("Default API path reseted...");
806                         }
807                 } else {
808                         if (current_gl_api_version != *api_version) {
809                                 /* API version becomes 1.x from higher */
810                                 if (*api_version == COREGL_GLAPI_1) {
811                                         init_export(GL_FALSE, GL_TRUE);
812                                         COREGL_DBG("Default API path reseted...");
813                                 }
814
815                                 /* API version becomes higher from 1.x */
816                                 if (current_gl_api_version == COREGL_GLAPI_1) {
817                                         init_modules();
818                                 }
819
820                                 current_gl_api_version = *api_version;
821                         }
822                 }
823         }
824
825         /* Update references only when the contexts are different */
826         if (tstate->cstate != gctx->cstate) {
827                 if (tstate->cstate != NULL && tstate->cstate->data != NULL) {
828                         _remove_context_ref((GLGlueContext *)tstate->cstate->data,
829                                                                 &ctx_list_access_mutex);
830                 }
831
832                 tstate->cstate = gctx->cstate;
833
834                 if (tstate->cstate->data != NULL) {
835                         _add_context_ref((GLGlueContext *)tstate->cstate->data);
836                 }
837         }
838
839         tstate->rsurf_draw = draw;
840         tstate->rsurf_read = read;
841
842         return ret;
843 }
844
845 extern EGLBoolean (*ovr_eglBindAPI)(EGLenum api);
846 extern EGLenum (*ovr_eglQueryAPI)(void);
847
848 EGLBoolean
849 fastpath_eglBindAPI(EGLenum api)
850 {
851         EGLBoolean ret = EGL_FALSE;
852         MY_MODULE_TSTATE *tstate = NULL;
853
854         _COREGL_FASTPATH_FUNC_BEGIN();
855         if (fp_opt == FP_UNKNOWN_PATH) {
856                 COREGL_ERR("Invalid library link! (CoreGL path option is invalid)");
857                 goto finish;
858         }
859
860         ret = _orig_fastpath_eglBindAPI(api);
861
862         GET_MY_TSTATE(tstate, get_current_thread_state());
863         if (tstate == NULL) {
864                 AST(init_new_thread_state() == 1);
865
866                 GET_MY_TSTATE(tstate, get_current_thread_state());
867                 AST(tstate != NULL);
868         }
869
870         {
871                 EGLenum newapi = _orig_fastpath_eglQueryAPI();
872                 if (tstate && (tstate->binded_api != EGL_OPENGL_ES_API)) {
873                         tstate->binded_api = newapi;
874                 }
875         }
876
877         goto finish;
878
879 finish:
880         _COREGL_FASTPATH_FUNC_END();
881         return ret;
882 }
883
884 EGLenum
885 fastpath_eglQueryAPI(void)
886 {
887         EGLenum ret = 0;
888         MY_MODULE_TSTATE *tstate = NULL;
889
890         _COREGL_FASTPATH_FUNC_BEGIN();
891         if (fp_opt == FP_UNKNOWN_PATH) {
892                 COREGL_ERR("Invalid library link! (CoreGL path option is invalid)");
893                 goto finish;
894         }
895
896         ret = _orig_fastpath_eglQueryAPI();
897
898         GET_MY_TSTATE(tstate, get_current_thread_state());
899         if (tstate != NULL) {
900                 AST(tstate->binded_api == ret);
901         }
902
903         goto finish;
904
905 finish:
906         _COREGL_FASTPATH_FUNC_END();
907         return ret;
908 }
909
910 EGLContext
911 fastpath_eglCreateContext(EGLDisplay dpy, EGLConfig config,
912                                                   EGLContext share_context, const EGLint *attrib_list)
913 {
914         GLGlueContext *gctx = NULL, *newgctx = NULL;
915         GLGlueContext_List *gctx_list_new = NULL;
916         MY_MODULE_TSTATE *tstate = NULL;
917         GLContextState *cstate = NULL;
918         GLContextState *cstate_new = NULL;
919         GL_Shared_Object_State *sostate_new = NULL;
920         GLContext ctx = NULL;
921
922         EGL_packed_option *real_ctx_option = NULL;
923         EGL_packed_sharable_option *real_ctx_sharable_option = NULL;
924
925         // Special eject condition for binding API
926         GET_MY_TSTATE(tstate, get_current_thread_state());
927         if (tstate != NULL && tstate->binded_api != EGL_OPENGL_ES_API) {
928                 return _orig_fastpath_eglCreateContext(dpy, config, share_context, attrib_list);
929         }
930
931         _COREGL_FASTPATH_FUNC_BEGIN();
932
933         real_ctx_option = (EGL_packed_option *)calloc(1, sizeof(EGL_packed_option));
934         if (real_ctx_option == NULL) {
935                 COREGL_ERR("Error creating a new GLGlueContext(Memory full 1)");
936                 goto finish;
937         }
938         cstate = _egl_create_context(real_ctx_option, &cstate_new, &ctx, dpy, config,
939                                                                  attrib_list);
940         if (cstate == NULL)
941                 goto finish;
942
943         // Pack shared context options
944         real_ctx_sharable_option = (EGL_packed_sharable_option *)calloc(1,
945                                                            sizeof(EGL_packed_sharable_option));
946         if (real_ctx_sharable_option == NULL) {
947                 COREGL_ERR("Error creating a new GLGlueContext(Memory full 2)");
948                 goto finish;
949         }
950         AST(_pack_egl_context_sharable_option(real_ctx_sharable_option,
951                                                                                   share_context) == 1);
952
953         // Allocate a new context
954         newgctx = (GLGlueContext *)calloc(1, sizeof(GLGlueContext));
955         if (newgctx == NULL) {
956                 COREGL_ERR("Error creating a new GLGlueContext(Memory full 3)");
957                 goto finish;
958         }
959
960         newgctx->magic = MAGIC_GLFAST;
961         newgctx->initialized = 0;
962         newgctx->rdpy = dpy;
963         newgctx->thread_id = get_current_thread();
964
965         fastpath_ostate_init(&newgctx->ostate);
966
967         if (share_context != EGL_NO_CONTEXT) {
968                 GLGlueContext *shared_gctx = (GLGlueContext *)share_context;
969                 AST(shared_gctx->magic == MAGIC_GLFAST);
970                 AST(shared_gctx->ostate.shared != NULL);
971                 newgctx->ostate.shared = shared_gctx->ostate.shared;
972         } else {
973                 sostate_new = (GL_Shared_Object_State *)calloc(1,
974                                           sizeof(GL_Shared_Object_State));
975                 if (sostate_new == NULL) {
976                         COREGL_ERR("Error creating a new GLGlueContext(Memory full 4)");
977                         goto finish;
978                 }
979                 fastpath_sostate_init(sostate_new);
980                 newgctx->ostate.shared = sostate_new;
981         }
982         _add_shared_obj_state_ref(newgctx, newgctx->ostate.shared);
983         newgctx->real_ctx_option = real_ctx_option;
984         newgctx->real_ctx_option_len = sizeof(EGL_packed_option);
985         newgctx->real_ctx_sharable_option = real_ctx_sharable_option;
986         newgctx->real_ctx_sharable_option_len = sizeof(EGL_packed_sharable_option);
987
988         _link_context_state(newgctx, cstate);
989         _add_context_ref(newgctx);
990
991         newgctx->cstate = cstate;
992
993         {
994                 // Add glue context to list
995                 gctx_list_new = (GLGlueContext_List *)calloc(1, sizeof(GLGlueContext_List));
996                 if (gctx_list_new == NULL) {
997                         COREGL_ERR("Error creating a new GlGlueContext(Memory full 5)");
998                         goto finish;
999                 }
1000
1001                 AST(mutex_lock(&ctx_list_access_mutex) == 1);
1002
1003                 gctx_list_new->gctx = newgctx;
1004
1005                 gctx_list_new->prev = NULL;
1006                 gctx_list_new->next = gctx_list;
1007                 if (gctx_list != NULL)
1008                         gctx_list->prev = gctx_list_new;
1009
1010                 gctx_list = gctx_list_new;
1011
1012                 AST(mutex_unlock(&ctx_list_access_mutex) == 1);
1013         }
1014
1015         gctx = newgctx;
1016
1017 #ifdef COREGL_FASTPATH_TRACE_CONTEXT_INFO
1018         if (unlikely(get_trace_ctx_flag() == 1)) {
1019                 char ment[256];
1020                 add_to_general_trace_list(&glue_ctx_trace_list, newgctx);
1021
1022                 snprintf(ment, sizeof(ment), "eglCreateContext completed (GlueCTX=[%12p])",
1023                                  newgctx);
1024                 _dump_context_info(ment, 1);
1025         }
1026 #endif // COREGL_FASTPATH_TRACE_CONTEXT_INFO
1027
1028         goto finish;
1029
1030 finish:
1031         if (gctx == NULL) {
1032                 if (ctx != NULL) {
1033                         _orig_fastpath_eglDestroyContext(dpy, ctx);
1034                         ctx = NULL;
1035                 }
1036                 if (sostate_new != NULL) {
1037                         free(sostate_new);
1038                         sostate_new = NULL;
1039                 }
1040                 if (real_ctx_option != NULL) {
1041                         free(real_ctx_option);
1042                         real_ctx_option = NULL;
1043                 }
1044                 if (real_ctx_sharable_option != NULL) {
1045                         free(real_ctx_sharable_option);
1046                         real_ctx_sharable_option = NULL;
1047                 }
1048                 if (cstate_new != NULL) {
1049 #ifdef COREGL_FASTPATH_TRACE_CONTEXT_INFO
1050                         if (unlikely(get_trace_ctx_flag() == 1))
1051                                 remove_from_general_trace_list(&context_state_trace_list, cstate_new);
1052 #endif // COREGL_FASTPATH_TRACE_CONTEXT_INFO
1053
1054                         fastpath_remove_context_states_from_list(cstate_new, &ctx_list_access_mutex);
1055                         free(cstate_new);
1056                         cstate_new = NULL;
1057                 }
1058                 if (gctx_list_new != NULL) {
1059                         AST(mutex_lock(&ctx_list_access_mutex) == 1);
1060
1061                         if (gctx_list_new->next != NULL)
1062                                 gctx_list_new->next->prev = gctx_list_new->prev;
1063
1064                         if (gctx_list_new->prev != NULL)
1065                                 gctx_list_new->prev->next = gctx_list_new->next;
1066                         else
1067                                 gctx_list = gctx_list_new->next;
1068
1069                         AST(mutex_unlock(&ctx_list_access_mutex) == 1);
1070
1071                         free(gctx_list_new);
1072                 }
1073                 if (newgctx != NULL) {
1074                         _remove_context_ref(newgctx, &ctx_list_access_mutex);
1075                         newgctx = NULL;
1076                 }
1077         }
1078
1079         _COREGL_FASTPATH_FUNC_END();
1080
1081         return (EGLContext)gctx;
1082 }
1083
1084 EGLBoolean
1085 fastpath_eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1086 {
1087         EGLBoolean ret = EGL_FALSE;
1088         GLGlueContext *gctx = NULL;
1089
1090         _COREGL_FASTPATH_FUNC_BEGIN();
1091
1092         gctx = (GLGlueContext *)ctx;
1093
1094         if (gctx != NULL && gctx != EGL_NO_CONTEXT) {
1095                 GLContextState *cstate = NULL;
1096
1097                 if (gctx->magic != MAGIC_GLFAST) {
1098                         ret = _orig_fastpath_eglDestroyContext(dpy, ctx);
1099                         goto finish;
1100                 }
1101
1102                 cstate = gctx->cstate;
1103                 AST(cstate != NULL);
1104
1105                 if (gctx->is_destroyed != 1) {
1106                         gctx->is_destroyed = 1;
1107                         _remove_context_ref(gctx, &ctx_list_access_mutex);
1108                 }
1109         } else {
1110                 COREGL_WARN("Invalid destroying context. (no exists)");
1111                 ret = EGL_FALSE;
1112                 goto finish;
1113         }
1114
1115         ret = EGL_TRUE;
1116         goto finish;
1117
1118 finish:
1119         _COREGL_FASTPATH_FUNC_END();
1120
1121 #ifdef COREGL_FASTPATH_TRACE_CONTEXT_INFO
1122         if (unlikely(get_trace_ctx_flag() == 1)) {
1123                 char ment[256];
1124                 snprintf(ment, sizeof(ment), "eglDestroyContext completed (GlueCTX=[%12p])",
1125                                  ctx);
1126                 _dump_context_info(ment, 1);
1127         }
1128 #endif // COREGL_FASTPATH_TRACE_CONTEXT_INFO
1129
1130         return ret;
1131 }
1132
1133 EGLBoolean
1134 fastpath_eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute,
1135                                                  EGLint *value)
1136 {
1137         EGLBoolean ret = EGL_FALSE;
1138         EGLContext real_ctx = EGL_NO_CONTEXT;
1139
1140         _COREGL_FASTPATH_FUNC_BEGIN();
1141
1142         if (ctx != EGL_NO_CONTEXT) {
1143                 GLGlueContext *gctx = NULL;
1144                 gctx = (GLGlueContext *)ctx;
1145
1146                 if (gctx->magic != MAGIC_GLFAST) {
1147                         real_ctx = ctx;
1148                 } else {
1149                         AST(gctx->cstate != NULL);
1150                         real_ctx = gctx->cstate->rctx;
1151                 }
1152         }
1153
1154         ret = _orig_fastpath_eglQueryContext(dpy, real_ctx, attribute, value);
1155         goto finish;
1156
1157 finish:
1158         _COREGL_FASTPATH_FUNC_END();
1159         return ret;
1160 }
1161
1162
1163
1164 EGLBoolean
1165 fastpath_eglReleaseThread(void)
1166 {
1167         EGLBoolean ret = EGL_FALSE;
1168         EGLDisplay dpy = EGL_NO_DISPLAY;
1169         MY_MODULE_TSTATE *tstate = NULL;
1170
1171         GET_MY_TSTATE(tstate, get_current_thread_state());
1172
1173         // Special eject condition for binding API
1174         if (tstate != NULL && tstate->binded_api != EGL_OPENGL_ES_API) {
1175                 return _orig_fastpath_eglReleaseThread();
1176         }
1177
1178         _COREGL_FASTPATH_FUNC_BEGIN();
1179
1180         dpy = _orig_fastpath_eglGetCurrentDisplay();
1181
1182         /* according to spec,
1183          * Even if EGL is not initialized on any EGLDisplay, eglReleaseThread should succeed
1184          */
1185         if (dpy != EGL_NO_DISPLAY)
1186                 fastpath_eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
1187         ret = _orig_fastpath_eglReleaseThread();
1188         goto finish;
1189
1190 finish:
1191         _COREGL_FASTPATH_FUNC_END();
1192         return ret;
1193 }
1194
1195 EGLDisplay
1196 fastpath_eglGetCurrentDisplay(void)
1197 {
1198         MY_MODULE_TSTATE *tstate = NULL;
1199         EGLDisplay dpy = EGL_NO_DISPLAY;
1200
1201         GET_MY_TSTATE(tstate, get_current_thread_state());
1202
1203         if (tstate != NULL) {
1204                 // Special eject condition for binding API
1205                 if (tstate->binded_api != EGL_OPENGL_ES_API) {
1206                         return _orig_fastpath_eglGetCurrentDisplay();
1207                 }
1208
1209                 _COREGL_FASTPATH_FUNC_BEGIN();
1210
1211                 if (tstate->cstate != NULL) {
1212                         dpy = tstate->cstate->rdpy;
1213
1214                 }
1215
1216                 _COREGL_FASTPATH_FUNC_END();
1217
1218         }
1219
1220         goto finish;
1221
1222 finish:
1223
1224         return dpy;
1225 }
1226
1227 EGLBoolean
1228 fastpath_eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
1229 {
1230         EGLBoolean ret = EGL_FALSE;
1231         EGLBoolean need_mc = EGL_FALSE;
1232         GLGlueContext *gctx = (GLGlueContext *)ctx;
1233         int api_version;
1234
1235         MY_MODULE_TSTATE *tstate = NULL;
1236
1237         GET_MY_TSTATE(tstate, get_current_thread_state());
1238
1239         /* Special eject condition for binding API */
1240         if (tstate != NULL && tstate->binded_api != EGL_OPENGL_ES_API) {
1241                 return _orig_fastpath_eglMakeCurrent(dpy, draw, read, ctx);
1242         }
1243
1244         _COREGL_FASTPATH_FUNC_BEGIN();
1245
1246         if (tstate == NULL) {
1247                 AST(init_new_thread_state() == 1);
1248                 GET_MY_TSTATE(tstate, get_current_thread_state());
1249                 AST(tstate != NULL);
1250         }
1251
1252         /* Special path for context deletion */
1253         if (ctx == EGL_NO_CONTEXT && tstate) {
1254                 if (tstate->cstate != NULL) {
1255                         if (_bind_context_state(NULL, tstate->cstate, &ctx_list_access_mutex) != 1) {
1256                                 COREGL_WARN("Error soft-makecurrent for context deletion");
1257                         }
1258                         tstate->cstate = NULL;
1259                 }
1260
1261                 if (_orig_fastpath_eglMakeCurrent(dpy, draw, read, ctx) != EGL_TRUE) {
1262                         COREGL_WARN("Error making context [%p] current. (invalid EGL display [%p] or EGL surface [D:%p/R:%p])",
1263                                                 ctx, dpy, draw, read);
1264                         ret = EGL_FALSE;
1265                         goto finish;
1266                 }
1267
1268                 tstate->rsurf_draw = draw;
1269                 tstate->rsurf_read = read;
1270
1271                 ret = EGL_TRUE;
1272                 goto finish;
1273         }
1274
1275         AST(gctx && gctx->cstate && gctx->real_ctx_option && gctx->real_ctx_sharable_option);
1276
1277         if (gctx && (gctx->rdpy != dpy)) {
1278                 COREGL_WARN("Invalid context (or invalid EGL display)");
1279                 ret = EGL_FALSE;
1280                 goto finish;
1281         }
1282
1283         /* Handle cross threading of context (when used by two or more gctx) */
1284         if (gctx && gctx->thread_id != get_current_thread() && gctx->cstate->ref_count > 1) {
1285                 if(fastpath_create_context(gctx) == EGL_FALSE)
1286                         goto finish;
1287         }
1288
1289         /* Check if the object is correct */
1290         if (gctx && (gctx->magic != MAGIC_GLFAST)) {
1291                 COREGL_ERR("Glue-CTX Magic Check Failed!!! (Memory broken?)");
1292                 ret = EGL_FALSE;
1293                 goto finish;
1294         }
1295
1296         /* If drawable changed, do a make current */
1297         if (tstate && (tstate->rsurf_draw != draw || tstate->rsurf_read != read)) {
1298                 need_mc = EGL_TRUE;
1299         }
1300
1301         AST(gctx && (gctx->cstate != NULL));
1302
1303         /* If binded real context changed, do a make current */
1304         if (tstate && gctx && (tstate->cstate == NULL || tstate->cstate != gctx->cstate)) {
1305                 need_mc = EGL_TRUE;
1306         }
1307
1308         if (tstate && gctx && gctx->cstate && (need_mc == EGL_TRUE)) {
1309                 fastpath_update_context(gctx, tstate, dpy, draw, read, &api_version);
1310         }
1311
1312         /* Initialize context states */
1313         if (gctx && (gctx->initialized == 0)) {
1314                 if (fastpath_init_context_states(gctx) != 1) {
1315                         COREGL_ERR("Error intializing context. (Check driver specification)");
1316                         goto finish;
1317                 }
1318         }
1319
1320         /* Setup initial Viewport & Scissor */
1321         if (gctx && gctx->surface_attached == 0 && draw != EGL_NO_SURFACE) {
1322                 fastpath_init_viewport_and_scissor(gctx);
1323         }
1324
1325         if (tstate && tstate->cstate &&
1326                         (_bind_context_state(gctx, tstate->cstate, &ctx_list_access_mutex) != 1)) {
1327                 ret = EGL_FALSE;
1328                 goto finish;
1329         }
1330
1331         if (gctx) {
1332                 gctx->used_count++;
1333         }
1334
1335         ret = EGL_TRUE;
1336         goto finish;
1337
1338 finish:
1339         _COREGL_FASTPATH_FUNC_END();
1340
1341 #ifdef COREGL_FASTPATH_TRACE_CONTEXT_INFO
1342         if (unlikely(get_trace_ctx_flag() == 1)) {
1343                 char ment[256];
1344                 snprintf(ment, sizeof(ment), "eglMakeCurrent finished (GlueCTX=[%12p] Surf=[D:%12p R:%12p])",
1345                                  ctx, draw, read);
1346                 _dump_context_info(ment, 0);
1347         }
1348 #endif
1349
1350         return ret;
1351 }
1352
1353 EGLContext
1354 fastpath_eglGetCurrentContext(void)
1355 {
1356         GLGlueContext *ret = NULL;
1357         MY_MODULE_TSTATE *tstate = NULL;
1358
1359         GET_MY_TSTATE(tstate, get_current_thread_state());
1360
1361         // Special eject condition for binding API
1362         if (tstate != NULL && tstate->binded_api != EGL_OPENGL_ES_API) {
1363                 return _orig_fastpath_eglGetCurrentContext();
1364         }
1365
1366         _COREGL_FASTPATH_FUNC_BEGIN();
1367
1368         if (tstate != NULL) {
1369                 if (tstate->cstate != NULL) {
1370                         ret = (GLGlueContext *)tstate->cstate->data;
1371                         AST(ret->magic == MAGIC_GLFAST);
1372                 }
1373         }
1374         goto finish;
1375
1376 finish:
1377         _COREGL_FASTPATH_FUNC_END();
1378         return (EGLContext)ret;
1379 }
1380
1381
1382 EGLSurface
1383 fastpath_eglGetCurrentSurface(EGLint readdraw)
1384 {
1385         EGLSurface ret = EGL_NO_SURFACE;
1386         MY_MODULE_TSTATE *tstate = NULL;
1387
1388         GET_MY_TSTATE(tstate, get_current_thread_state());
1389
1390         // Special eject condition for binding API
1391         if (tstate != NULL && tstate->binded_api != EGL_OPENGL_ES_API) {
1392                 return _orig_fastpath_eglGetCurrentSurface(readdraw);
1393         }
1394
1395         _COREGL_FASTPATH_FUNC_BEGIN();
1396
1397         if (tstate != NULL) {
1398                 switch (readdraw) {
1399                 case EGL_DRAW :
1400                         ret = (GLGlueContext *)tstate->rsurf_draw;
1401                         break;
1402                 case EGL_READ :
1403                         ret = (GLGlueContext *)tstate->rsurf_read;
1404                         break;
1405                 }
1406         }
1407         goto finish;
1408
1409 finish:
1410         _COREGL_FASTPATH_FUNC_END();
1411         return ret;
1412 }
1413
1414 EGLImageKHR
1415 fastpath_eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target,
1416                                                         EGLClientBuffer buffer, const EGLint *attrib_list)
1417 {
1418         void *ret = NULL;
1419         EGLContext real_ctx = EGL_NO_CONTEXT;
1420         EGLClientBuffer real_obj = NULL;
1421         GL_Object_Type type = 0;
1422
1423         if (current_gl_api_version == COREGL_GLAPI_1) {
1424                 ret = _orig_fastpath_eglCreateImageKHR(dpy, real_ctx, target, buffer,
1425                                                                                            attrib_list);
1426                 goto finish;
1427         }
1428
1429         if ((EGLint)buffer & GL_OBJECT_TYPE_TEXTURE)
1430                 type = GL_OBJECT_TYPE_TEXTURE;
1431         else if ((EGLint)buffer & GL_OBJECT_TYPE_RENDERBUFFER)
1432                 type = GL_OBJECT_TYPE_RENDERBUFFER;
1433         else {
1434                 ret = _orig_fastpath_eglCreateImageKHR(dpy, real_ctx, target, buffer,
1435                                                                                            attrib_list);
1436                 goto finish;
1437         }
1438
1439         _COREGL_FASTPATH_FUNC_BEGIN();
1440
1441         if (ctx != NULL && ctx != EGL_NO_CONTEXT) {
1442                 GLGlueContext *gctx = (GLGlueContext *)ctx;
1443
1444                 if (gctx->magic != MAGIC_GLFAST) {
1445                         real_ctx = ctx;
1446                 } else {
1447                         AST(gctx->cstate != NULL);
1448                         real_ctx = gctx->cstate->rctx;
1449                 }
1450
1451                 switch (target) {
1452                 case EGL_GL_TEXTURE_2D_KHR:
1453                 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
1454                 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
1455                 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
1456                 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
1457                 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
1458                 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
1459                 case EGL_GL_TEXTURE_3D_KHR:
1460                 case EGL_GL_RENDERBUFFER_KHR:
1461                         real_obj = (EGLClientBuffer)(uintptr_t)fastpath_ostate_get_object(&gctx->ostate,
1462                                                 type, (GLuint)(uintptr_t)buffer);
1463                         break;
1464                 default:
1465                         COREGL_ERR("Error Not supported target NULL client buffer");
1466                         goto finish;
1467                 }
1468
1469         } else  {
1470                 real_obj = buffer;
1471         }
1472
1473         ret = _orig_fastpath_eglCreateImageKHR(dpy, real_ctx, target, real_obj,
1474                                                                                    attrib_list);
1475
1476
1477         goto finish;
1478
1479 finish:
1480         _COREGL_FASTPATH_FUNC_END();
1481         return ret;
1482 }
1483
1484 _eng_fn
1485 fastpath_eglGetProcAddress(const char *procname)
1486 {
1487         _eng_fn ret = NULL;
1488
1489         _COREGL_FASTPATH_FUNC_BEGIN();
1490
1491 #define _COREGL_SYMBOL(RET_TYPE, FUNC_NAME, PARAM_LIST) \
1492         if (strcmp(procname, #FUNC_NAME) == 0) \
1493         { \
1494                 _eng_fn ret_orig = NULL; \
1495                 ret_orig = _orig_fastpath_eglGetProcAddress(procname); \
1496                 if (ret_orig != NULL) \
1497                         ret = (_eng_fn)ovr_##FUNC_NAME; \
1498                 goto finish; \
1499         }
1500
1501 #define _COREGL_EXT_SYMBOL_ALIAS(ALIAS_NAME, FUNC_NAME) \
1502         if (strcmp(procname, #ALIAS_NAME) == 0) \
1503         { \
1504                 _eng_fn ret_orig = NULL; \
1505                 ret_orig = _orig_fastpath_eglGetProcAddress(#ALIAS_NAME); \
1506                 if (ret_orig != NULL) \
1507                         ret = (_eng_fn)ovr_##FUNC_NAME; \
1508                 goto finish; \
1509         }
1510
1511 #include "../headers/sym_egl.h"
1512 #include "../headers/sym_gl1.h"
1513 #include "../headers/sym_gl2.h"
1514 #include "../headers/sym_gl_common.h"
1515 #undef _COREGL_SYMBOL
1516 #undef _COREGL_EXT_SYMBOL_ALIAS
1517
1518         ret = _orig_fastpath_eglGetProcAddress(procname);
1519         if (ret != NULL) {
1520
1521 #define _COREGL_EXT_SYMBOL_FASTPATH_PASS(FUNC_NAME) \
1522         if (strcmp(procname, #FUNC_NAME) == 0) \
1523                 goto finish;
1524
1525 #define _COREGL_EXT_SYMBOL_FASTPATH_BLOCK(FUNC_NAME) \
1526         if (strcmp(procname, #FUNC_NAME) == 0) \
1527         { \
1528                 ret = NULL; \
1529                 goto finish; \
1530         }
1531
1532 #include "../headers/sym_egl.h"
1533 #include "../headers/sym_gl1.h"
1534 #include "../headers/sym_gl2.h"
1535 #include "../headers/sym_gl_common.h"
1536
1537 #undef _COREGL_EXT_SYMBOL_FASTPATH_PASS
1538 #undef _COREGL_EXT_SYMBOL_FASTPATH_BLOCK
1539
1540                 COREGL_ERR("FASTPATH can't support '%s' (will be terminated with Illegal instruction!)",
1541                                    procname);
1542                 assert(0);
1543         }
1544
1545         goto finish;
1546
1547 finish:
1548         _COREGL_FASTPATH_FUNC_END();
1549         return ret;
1550 }
1551
1552 EGLBoolean
1553 fastpath_eglTerminate(EGLDisplay dpy)
1554 {
1555         EGLBoolean ret = EGL_FALSE;
1556         GLGlueContext_List *current = NULL;
1557         GLGlueContext_List *remove_list = NULL;
1558
1559         _COREGL_FASTPATH_FUNC_BEGIN();
1560
1561         AST(mutex_lock(&ctx_list_access_mutex) == 1);
1562         current = gctx_list;
1563         while (current != NULL) {
1564                 if (current->gctx->cstate->rdpy == dpy) {
1565                         GLGlueContext_List *rm_newitm = NULL;
1566                         rm_newitm = (GLGlueContext_List *)calloc(1, sizeof(GLGlueContext_List));
1567
1568                         if (rm_newitm == NULL) {
1569                                 ret = EGL_FALSE;
1570                                 goto finish;
1571                         }
1572
1573                         rm_newitm->gctx = current->gctx;
1574
1575                         rm_newitm->next = remove_list;
1576                         remove_list = rm_newitm;
1577                 }
1578                 current = current->next;
1579         }
1580         AST(mutex_unlock(&ctx_list_access_mutex) == 1);
1581
1582         current = remove_list;
1583         while (current != NULL) {
1584                 fastpath_eglDestroyContext(dpy, current->gctx);
1585                 remove_list = current->next;
1586                 free(current);
1587                 current = remove_list;
1588         }
1589
1590         ret = _orig_fastpath_eglTerminate(dpy);
1591         goto finish;
1592
1593 finish:
1594         _COREGL_FASTPATH_FUNC_END();
1595         return ret;
1596 }
1597