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