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