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