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