1 #include "coregl_fastpath.h"
13 #ifdef COREGL_FASTPATH_TRACE_CONTEXT_INFO
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;
20 _dump_context_info(const char *ment, int force_output)
22 MY_MODULE_TSTATE *tstate = NULL;
23 static struct timeval tv_last = { 0, 0 };
25 if (trace_ctx_flag != 1) return;
27 AST(mutex_lock(&ctx_list_access_mutex) == 1);
28 AST(mutex_lock(&general_trace_lists_access_mutex) == 1);
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) {
39 GET_MY_TSTATE(tstate, get_current_thread_state());
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(),
45 TRACE("\E[40;34m========================================================================================================================\E[0m\n");
50 General_Trace_List *current = NULL;
51 current = thread_trace_list;
53 while (current != NULL) {
54 GLThreadState *cur_tstate = (GLThreadState *)current->value;
55 MY_MODULE_TSTATE *cur_tstate_tm = NULL;
57 GET_MY_TSTATE(cur_tstate_tm, cur_tstate);
58 AST(cur_tstate_tm != NULL);
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);
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);
71 TRACE(" (NOT BINDED TO THREAD)\E[0m\n");
74 // Binded Context State List
76 General_Trace_List *current = NULL;
77 current = context_state_trace_list;
79 while (current != NULL) {
80 GLContextState *cur_cstate = (GLContextState *)current->value;
81 MY_MODULE_TSTATE *cur_tstate_tm = NULL;
83 GET_MY_TSTATE(cur_tstate_tm, cur_tstate);
84 AST(cur_tstate_tm != NULL);
86 if (cur_tstate_tm->cstate == cur_cstate) {
87 TRACE(" -> RealCTX [%12p] : EGLDPY=[%12p] EGLCTX=[%12p] <[%2d] GlueCTXs>\E[0m\n",
91 cur_cstate->ref_count);
93 // Binded Glue Context List
95 General_Trace_List *current = NULL;
96 current = glue_ctx_trace_list;
98 while (current != NULL) {
99 GLGlueContext *cur_gctx = (GLGlueContext *)current->value;
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) ? '>' : '-',
107 cur_gctx->used_count);
109 TRACE(" <Ref [%2d]>\E[0m\n", cur_gctx->ref_count);
112 current = current->next;
117 current = current->next;
123 current = current->next;
127 TRACE("\E[40;33m........................................................................................................................\E[0m\n");
129 // Not-binded Context State List
131 General_Trace_List *current = NULL;
132 current = context_state_trace_list;
134 while (current != NULL) {
135 GLContextState *cur_cstate = (GLContextState *)current->value;
139 if (cur_cstate->data != NULL) {
140 General_Trace_List *current_t = NULL;
141 current_t = thread_trace_list;
143 while (current_t != NULL) {
144 GLThreadState *cur_tstate = (GLThreadState *)current_t->value;
145 MY_MODULE_TSTATE *cur_tstate_tm = NULL;
147 GET_MY_TSTATE(cur_tstate_tm, cur_tstate);
148 AST(cur_tstate_tm != NULL);
150 if (cur_tstate->thread_id == ((GLGlueContext *)cur_cstate->data)->thread_id) {
151 if (cur_tstate_tm->cstate == cur_cstate)
155 current_t = current_t->next;
160 TRACE(" RealCTX [%12p] : EGLDPY=[%12p] EGLCTX=[%12p] <[%2d] GlueCTXs>\E[0m\n",
164 cur_cstate->ref_count);
166 // Binded Glue Context List
168 General_Trace_List *current = NULL;
169 current = glue_ctx_trace_list;
171 while (current != NULL) {
172 GLGlueContext *cur_gctx = (GLGlueContext *)current->value;
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) ? '>' : '-',
180 cur_gctx->used_count);
182 TRACE(" <Ref [%2d]>\E[0m\n", cur_gctx->ref_count);
185 current = current->next;
190 current = current->next;
195 TRACE("\E[40;33m........................................................................................................................\E[0m\n");
197 // Not-binded Glue Context List
199 General_Trace_List *current = NULL;
200 current = glue_ctx_trace_list;
202 while (current != NULL) {
203 GLGlueContext *cur_gctx = (GLGlueContext *)current->value;
205 if (cur_gctx->cstate == NULL) {
206 TRACE(" GlueCTX [%12p] : EGLDPY=[%12p] TID=[%12d] <MC count [%10d]>",
210 cur_gctx->used_count);
212 TRACE(" <Ref [%2d]>\E[0m\n", cur_gctx->ref_count);
215 current = current->next;
219 TRACE("\E[40;34m========================================================================================================================\E[0m\n");
228 AST(mutex_unlock(&general_trace_lists_access_mutex) == 1);
229 AST(mutex_unlock(&ctx_list_access_mutex) == 1);
233 #endif // COREGL_FASTPATH_TRACE_CONTEXT_INFO
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;
247 EGL_packed_attrib_list attrib_list;
252 EGLContext share_context;
253 } EGL_packed_sharable_option;
257 _pack_egl_context_option(EGL_packed_option *pack_data, EGLDisplay dpy,
258 EGLConfig cfg, EGLint force_unique, const EGLint *attrib_list)
260 static int force_unique_free_id = 0;
263 pack_data->dpy = dpy;
264 pack_data->cfg = cfg;
265 if (force_unique != 0)
266 pack_data->force_unique = force_unique_free_id++;
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;
275 // Apply specified attributes
276 EGLint *attrib = (EGLint *)attrib_list;
277 while ((attrib != NULL) && (attrib[0] != EGL_NONE)) {
279 case EGL_CONTEXT_MAJOR_VERSION_KHR: // EGL_CONTEXT_CLIENT_VERSION
280 pack_data->attrib_list.context_major_version = attrib[1];
282 case EGL_CONTEXT_MINOR_VERSION_KHR:
283 pack_data->attrib_list.context_minor_version = attrib[1];
285 case EGL_CONTEXT_FLAGS_KHR:
286 pack_data->attrib_list.context_flags = attrib[1];
288 case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
289 pack_data->attrib_list.context_opengl_profile_mask = attrib[1];
291 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
292 pack_data->attrib_list.opengl_reset_notification_strategy = attrib[1];
295 COREGL_WRN("\E[40;31;1mInvalid context attribute.\E[0m\n");
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;
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)
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;
324 if (attrib_list != NULL && attrib_list_size > 0) {
325 int attrib_list_index = 0;
327 memset(attrib_list, 0x00, sizeof(int) * attrib_list_size);
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;
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;
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;
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;
356 if (pack_data->attrib_list.opengl_reset_notification_strategy !=
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;
366 attrib_list[attrib_list_index] = EGL_NONE;
376 _pack_egl_context_sharable_option(EGL_packed_sharable_option *pack_data,
377 EGLContext share_context)
381 pack_data->share_context = share_context;
392 _unpack_egl_context_sharable_option(EGL_packed_sharable_option *pack_data,
393 EGLContext *share_context)
397 if (share_context != NULL) *share_context = pack_data->share_context;
408 _link_context_state(GLGlueContext *gctx, GLContextState *cstate)
410 AST(gctx->cstate == NULL);
412 gctx->cstate = cstate;
416 _unlink_context_state(GLGlueContext *gctx, Mutex *ctx_list_mtx)
418 GLContextState *cstate = NULL;
420 cstate = gctx->cstate;
424 AST(cstate->ref_count >= 0);
426 if (cstate->ref_count == 0) {
427 MY_MODULE_TSTATE *tstate = NULL;
429 AST(cstate->data == NULL || cstate->data == initial_ctx);
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
436 AST(fastpath_remove_context_states_from_list(cstate, ctx_list_mtx) == 1);
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;
446 _orig_fastpath_eglDestroyContext(cstate->rdpy, cstate->rctx);
453 _add_shared_obj_state_ref(GLGlueContext *gctx, GL_Shared_Object_State *sostate)
455 AST(sostate->ref_count >= 0);
456 sostate->ref_count++;
457 add_to_general_trace_list(&sostate->using_gctxs, gctx);
461 _remove_shared_obj_state_ref(GLGlueContext *gctx,
462 GL_Shared_Object_State *sostate)
464 remove_from_general_trace_list(&sostate->using_gctxs, gctx);
466 // Restore attached states
467 fastpath_release_gl_context(gctx);
469 AST(sostate->ref_count > 0);
470 sostate->ref_count--;
471 if (sostate->ref_count == 0) {
472 fastpath_sostate_deinit(sostate);
478 _add_context_ref(GLGlueContext *gctx)
480 if (gctx == initial_ctx) return;
482 AST(gctx->ref_count >= 0);
487 _remove_context_ref(GLGlueContext *gctx, Mutex *ctx_list_mtx)
489 if (gctx == initial_ctx) return;
491 AST(gctx->ref_count > 0);
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
499 AST(gctx->cstate != NULL);
500 if (gctx->cstate->data == gctx)
501 gctx->cstate->data = NULL;
503 _unlink_context_state(gctx, ctx_list_mtx);
505 AST(gctx->ostate.shared != NULL);
506 _remove_shared_obj_state_ref(gctx, gctx->ostate.shared);
507 gctx->ostate.shared = NULL;
509 fastpath_ostate_deinit(&gctx->ostate);
511 if (gctx->real_ctx_option != NULL) {
512 free(gctx->real_ctx_option);
513 gctx->real_ctx_option = NULL;
515 if (gctx->real_ctx_sharable_option != NULL) {
516 free(gctx->real_ctx_sharable_option);
517 gctx->real_ctx_sharable_option = NULL;
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"
528 GLGlueContext_List *current = NULL;
530 AST(mutex_lock(&ctx_list_access_mutex) == 1);
534 while (current != NULL) {
535 if (current->gctx == gctx) {
536 if (current->next != NULL)
537 current->next->prev = current->prev;
539 if (current->prev != NULL)
540 current->prev->next = current->next;
542 gctx_list = current->next;
548 current = current->next;
551 AST(mutex_unlock(&ctx_list_access_mutex) == 1);
557 _bind_context_state(GLGlueContext *gctx, GLContextState *cstate,
561 AST(gctx->cstate == cstate);
564 if (cstate->data != gctx) {
565 GLGlueContext *curctx = (GLGlueContext *)cstate->data;
566 GLGlueContext *newctx = gctx;
569 newctx = initial_ctx;
572 curctx = initial_ctx;
577 if (!fastpath_make_context_current(curctx, newctx))
580 cstate->data = (void *)newctx;
581 _remove_context_ref(curctx, ctx_list_mtx);
582 _add_context_ref(newctx);
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)
594 GLContextState *cstate = NULL;
596 AST(real_ctx_option != NULL);
597 AST(cstate_new != NULL);
600 // Pack context option
601 AST(_pack_egl_context_option(real_ctx_option, dpy, config, 0,
604 if (debug_nofp == 1) {
605 AST(_pack_egl_context_option(real_ctx_option, dpy, config, 1,
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);
615 // Create a real context if it hasn't been created
616 if (cstate == NULL) {
617 EGLContext *real_share_context = EGL_NO_CONTEXT;
619 AST(mutex_lock(&ctx_list_access_mutex) == 1);
621 GLContext_List *current = NULL;
623 current = glctx_list;
624 while (current != NULL) {
625 EGLDisplay cur_dpy = EGL_NO_DISPLAY;
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;
635 AST(current->cstate != NULL);
636 real_share_context = current->cstate->rctx;
639 current = current->next;
642 AST(mutex_unlock(&ctx_list_access_mutex) == 1);
644 *ctx = _orig_fastpath_eglCreateContext(dpy, config, real_share_context,
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");
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");
657 (*cstate_new)->rctx = *ctx;
658 (*cstate_new)->rdpy = dpy;
659 (*cstate_new)->data = NULL;
661 AST(fastpath_add_context_state_to_list(real_ctx_option,
662 sizeof(EGL_packed_option), *cstate_new, &ctx_list_access_mutex) == 1);
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
669 cstate = *cstate_new;
679 extern EGLBoolean (*ovr_eglBindAPI)(EGLenum api);
680 extern EGLenum (*ovr_eglQueryAPI)(void);
683 fastpath_eglBindAPI(EGLenum api)
685 EGLBoolean ret = EGL_FALSE;
686 MY_MODULE_TSTATE *tstate = NULL;
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");
694 ret = _orig_fastpath_eglBindAPI(api);
696 GET_MY_TSTATE(tstate, get_current_thread_state());
697 if (tstate == NULL) {
698 AST(init_new_thread_state() == 1);
700 GET_MY_TSTATE(tstate, get_current_thread_state());
705 EGLenum newapi = _orig_fastpath_eglQueryAPI();
706 if (tstate && (tstate->binded_api != EGL_OPENGL_ES_API)) {
707 tstate->binded_api = newapi;
714 _COREGL_FASTPATH_FUNC_END();
719 fastpath_eglQueryAPI(void)
722 MY_MODULE_TSTATE *tstate = NULL;
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");
730 ret = _orig_fastpath_eglQueryAPI();
732 GET_MY_TSTATE(tstate, get_current_thread_state());
733 if (tstate != NULL) {
734 AST(tstate->binded_api == ret);
740 _COREGL_FASTPATH_FUNC_END();
745 fastpath_eglCreateContext(EGLDisplay dpy, EGLConfig config,
746 EGLContext share_context, const EGLint *attrib_list)
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;
756 EGL_packed_option *real_ctx_option = NULL;
757 EGL_packed_sharable_option *real_ctx_sharable_option = NULL;
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);
765 _COREGL_FASTPATH_FUNC_BEGIN();
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");
772 cstate = _egl_create_context(real_ctx_option, &cstate_new, &ctx, dpy, config,
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");
784 AST(_pack_egl_context_sharable_option(real_ctx_sharable_option,
785 share_context) == 1);
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");
794 newgctx->magic = MAGIC_GLFAST;
795 newgctx->initialized = 0;
797 newgctx->thread_id = get_current_thread();
799 fastpath_ostate_init(&newgctx->ostate);
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;
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");
813 fastpath_sostate_init(sostate_new);
814 newgctx->ostate.shared = sostate_new;
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);
822 _link_context_state(newgctx, cstate);
823 _add_context_ref(newgctx);
825 newgctx->cstate = cstate;
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");
835 AST(mutex_lock(&ctx_list_access_mutex) == 1);
837 gctx_list_new->gctx = newgctx;
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;
844 gctx_list = gctx_list_new;
846 AST(mutex_unlock(&ctx_list_access_mutex) == 1);
851 #ifdef COREGL_FASTPATH_TRACE_CONTEXT_INFO
852 if (unlikely(trace_ctx_flag == 1)) {
854 add_to_general_trace_list(&glue_ctx_trace_list, newgctx);
856 snprintf(ment, sizeof(ment), "eglCreateContext completed (GlueCTX=[%12p])",
858 _dump_context_info(ment, 1);
860 #endif // COREGL_FASTPATH_TRACE_CONTEXT_INFO
867 _orig_fastpath_eglDestroyContext(dpy, ctx);
870 if (sostate_new != NULL) {
874 if (real_ctx_option != NULL) {
875 free(real_ctx_option);
876 real_ctx_option = NULL;
878 if (real_ctx_sharable_option != NULL) {
879 free(real_ctx_sharable_option);
880 real_ctx_sharable_option = NULL;
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
888 fastpath_remove_context_states_from_list(cstate_new, &ctx_list_access_mutex);
892 if (gctx_list_new != NULL) {
893 AST(mutex_lock(&ctx_list_access_mutex) == 1);
895 if (gctx_list_new->next != NULL)
896 gctx_list_new->next->prev = gctx_list_new->prev;
898 if (gctx_list_new->prev != NULL)
899 gctx_list_new->prev->next = gctx_list_new->next;
901 gctx_list = gctx_list_new->next;
903 AST(mutex_unlock(&ctx_list_access_mutex) == 1);
907 if (newgctx != NULL) {
908 _remove_context_ref(newgctx, &ctx_list_access_mutex);
914 _COREGL_FASTPATH_FUNC_END();
916 return (EGLContext)gctx;
920 fastpath_eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
922 EGLBoolean ret = EGL_FALSE;
923 GLGlueContext *gctx = NULL;
925 _COREGL_FASTPATH_FUNC_BEGIN();
927 gctx = (GLGlueContext *)ctx;
929 if (gctx != NULL && gctx != EGL_NO_CONTEXT) {
930 GLContextState *cstate = NULL;
932 if (gctx->magic != MAGIC_GLFAST) {
933 ret = _orig_fastpath_eglDestroyContext(dpy, ctx);
937 cstate = gctx->cstate;
940 if (gctx->is_destroyed != 1) {
941 gctx->is_destroyed = 1;
942 _remove_context_ref(gctx, &ctx_list_access_mutex);
945 COREGL_WRN("\E[40;31;1mInvalid destroying context. (no exists)\E[0m\n");
954 _COREGL_FASTPATH_FUNC_END();
956 #ifdef COREGL_FASTPATH_TRACE_CONTEXT_INFO
957 if (unlikely(trace_ctx_flag == 1)) {
959 snprintf(ment, sizeof(ment), "eglDestroyContext completed (GlueCTX=[%12p])",
961 _dump_context_info(ment, 1);
963 #endif // COREGL_FASTPATH_TRACE_CONTEXT_INFO
969 fastpath_eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute,
972 EGLBoolean ret = EGL_FALSE;
973 EGLContext real_ctx = EGL_NO_CONTEXT;
975 _COREGL_FASTPATH_FUNC_BEGIN();
977 if (ctx != EGL_NO_CONTEXT) {
978 GLGlueContext *gctx = NULL;
979 gctx = (GLGlueContext *)ctx;
981 if (gctx->magic != MAGIC_GLFAST) {
984 AST(gctx->cstate != NULL);
985 real_ctx = gctx->cstate->rctx;
989 ret = _orig_fastpath_eglQueryContext(dpy, real_ctx, attribute, value);
993 _COREGL_FASTPATH_FUNC_END();
1000 fastpath_eglReleaseThread(void)
1002 EGLBoolean ret = EGL_FALSE;
1003 EGLDisplay dpy = EGL_NO_DISPLAY;
1004 MY_MODULE_TSTATE *tstate = NULL;
1006 GET_MY_TSTATE(tstate, get_current_thread_state());
1008 // Special eject condition for binding API
1009 if (tstate != NULL && tstate->binded_api != EGL_OPENGL_ES_API) {
1010 return _orig_fastpath_eglReleaseThread();
1013 _COREGL_FASTPATH_FUNC_BEGIN();
1015 dpy = _orig_fastpath_eglGetCurrentDisplay();
1017 /* according to spec,
1018 * Even if EGL is not initialized on any EGLDisplay, eglReleaseThread should succeed
1020 if (dpy != EGL_NO_DISPLAY)
1021 fastpath_eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
1022 ret = _orig_fastpath_eglReleaseThread();
1026 _COREGL_FASTPATH_FUNC_END();
1031 fastpath_eglGetCurrentDisplay(void)
1033 MY_MODULE_TSTATE *tstate = NULL;
1034 EGLDisplay dpy = EGL_NO_DISPLAY;
1036 GET_MY_TSTATE(tstate, get_current_thread_state());
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();
1044 _COREGL_FASTPATH_FUNC_BEGIN();
1046 if (tstate->cstate != NULL) {
1047 dpy = tstate->cstate->rdpy;
1051 _COREGL_FASTPATH_FUNC_END();
1063 fastpath_eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
1066 EGLBoolean ret = EGL_FALSE;
1067 EGLBoolean need_mc = EGL_FALSE;
1068 GLGlueContext *gctx = NULL;
1071 MY_MODULE_TSTATE *tstate = NULL;
1073 GET_MY_TSTATE(tstate, get_current_thread_state());
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);
1080 _COREGL_FASTPATH_FUNC_BEGIN();
1082 gctx = (GLGlueContext *)ctx;
1084 if (tstate == NULL) {
1085 AST(init_new_thread_state() == 1);
1087 GET_MY_TSTATE(tstate, get_current_thread_state());
1088 AST(tstate != NULL);
1091 // Special path for context deletion
1092 if (ctx == EGL_NO_CONTEXT) {
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");
1101 tstate->cstate = NULL;
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);
1110 tstate->rsurf_draw = draw;
1111 tstate->rsurf_read = read;
1119 AST(gctx && (gctx->cstate != NULL));
1121 if (gctx && (gctx->rdpy != dpy)) {
1122 COREGL_WRN("\E[40;31;1mInvalid context (or invalid EGL display)\E[0m\n");
1127 AST(gctx && (gctx->real_ctx_option != NULL));
1128 AST(gctx && (gctx->real_ctx_sharable_option != NULL));
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
1135 GLContextState *cstate_new = NULL;
1136 EGLContext new_real_ctx = EGL_NO_CONTEXT;
1138 EGLDisplay dpy = EGL_NO_DISPLAY;
1139 EGLConfig config = NULL;
1140 int attrib_list[ATTRIB_LIST_BUFFER_SIZE];
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);
1146 _egl_create_context(gctx->real_ctx_option, &cstate_new, &new_real_ctx, dpy,
1147 config, attrib_list);
1149 AST(cstate_new != NULL);
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");
1154 _orig_fastpath_eglDestroyContext(dpy, new_real_ctx);
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");
1162 _unlink_context_state(gctx, &ctx_list_access_mutex);
1163 _link_context_state(gctx, cstate_new);
1165 // Apply to new thread
1166 gctx->thread_id = get_current_thread();
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");
1178 // If drawable changed, do a make current
1180 ((tstate->rsurf_draw != draw) || (tstate->rsurf_read != read)))
1183 AST(gctx && (gctx->cstate != NULL));
1185 // If binded real context changed, do a make current
1186 if (tstate && gctx && ((tstate->cstate == NULL) ||
1187 (tstate->cstate != gctx->cstate)))
1190 if (tstate && gctx && gctx->cstate && (need_mc == EGL_TRUE)) {
1191 AST(dpy == gctx->cstate->rdpy);
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");
1201 api_version = ((EGL_packed_option *)
1202 gctx->real_ctx_option)->attrib_list.context_major_version;
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");
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");
1219 // API version becomes higher from 1.x
1220 if (current_gl_api_version == COREGL_GLAPI_1)
1222 current_gl_api_version = api_version;
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);
1233 tstate->cstate = gctx->cstate;
1235 if (tstate->cstate->data != NULL)
1236 _add_context_ref((GLGlueContext *)tstate->cstate->data);
1239 tstate->rsurf_draw = draw;
1240 tstate->rsurf_read = read;
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");
1251 // Setup initial Viewport & Scissor
1252 if (gctx && gctx->surface_attached == 0 && draw != EGL_NO_SURFACE) {
1253 EGLint box_buffer[4];
1257 _orig_fastpath_glGetIntegerv(GL_VIEWPORT, box_buffer);
1258 width = box_buffer[2];
1259 height = box_buffer[3];
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;
1267 _orig_fastpath_glGetIntegerv(GL_SCISSOR_BOX, box_buffer);
1268 width = box_buffer[2];
1269 height = box_buffer[3];
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;
1277 gctx->surface_attached = 1;
1281 (_bind_context_state(gctx, tstate->cstate, &ctx_list_access_mutex) != 1)) {
1285 if (gctx) gctx->used_count++;
1292 _COREGL_FASTPATH_FUNC_END();
1294 #ifdef COREGL_FASTPATH_TRACE_CONTEXT_INFO
1295 if (unlikely(trace_ctx_flag == 1)) {
1297 snprintf(ment, sizeof(ment),
1298 "eglMakeCurrent finished (GlueCTX=[%12p] Surf=[D:%12p R:%12p])",
1300 _dump_context_info(ment, 0);
1302 #endif // COREGL_FASTPATH_TRACE_CONTEXT_INFO
1309 fastpath_eglGetCurrentContext(void)
1311 GLGlueContext *ret = NULL;
1312 MY_MODULE_TSTATE *tstate = NULL;
1314 GET_MY_TSTATE(tstate, get_current_thread_state());
1316 // Special eject condition for binding API
1317 if (tstate != NULL && tstate->binded_api != EGL_OPENGL_ES_API) {
1318 return _orig_fastpath_eglGetCurrentContext();
1321 _COREGL_FASTPATH_FUNC_BEGIN();
1323 if (tstate != NULL) {
1324 if (tstate->cstate != NULL) {
1325 ret = (GLGlueContext *)tstate->cstate->data;
1326 AST(ret->magic == MAGIC_GLFAST);
1332 _COREGL_FASTPATH_FUNC_END();
1333 return (EGLContext)ret;
1338 fastpath_eglGetCurrentSurface(EGLint readdraw)
1340 EGLSurface ret = EGL_NO_SURFACE;
1341 MY_MODULE_TSTATE *tstate = NULL;
1343 GET_MY_TSTATE(tstate, get_current_thread_state());
1345 // Special eject condition for binding API
1346 if (tstate != NULL && tstate->binded_api != EGL_OPENGL_ES_API) {
1347 return _orig_fastpath_eglGetCurrentSurface(readdraw);
1350 _COREGL_FASTPATH_FUNC_BEGIN();
1352 if (tstate != NULL) {
1355 ret = (GLGlueContext *)tstate->rsurf_draw;
1358 ret = (GLGlueContext *)tstate->rsurf_read;
1365 _COREGL_FASTPATH_FUNC_END();
1370 fastpath_eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target,
1371 EGLClientBuffer buffer, const EGLint *attrib_list)
1374 EGLContext real_ctx = EGL_NO_CONTEXT;
1375 EGLClientBuffer real_obj = NULL;
1376 GL_Object_Type type = 0;
1378 if (current_gl_api_version == COREGL_GLAPI_1) {
1379 ret = _orig_fastpath_eglCreateImageKHR(dpy, real_ctx, target, real_obj,
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;
1389 ret = _orig_fastpath_eglCreateImageKHR(dpy, real_ctx, target, buffer,
1394 _COREGL_FASTPATH_FUNC_BEGIN();
1396 if (ctx != NULL && ctx != EGL_NO_CONTEXT) {
1397 GLGlueContext *gctx = (GLGlueContext *)ctx;
1399 if (gctx->magic != MAGIC_GLFAST) {
1402 AST(gctx->cstate != NULL);
1403 real_ctx = gctx->cstate->rctx;
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");
1420 real_obj = (EGLClientBuffer)(uintptr_t)fastpath_ostate_get_object(&gctx->ostate,
1421 type, (GLuint)(uintptr_t)buffer);
1425 COREGL_ERR("\E[40;31;1mError Not supported target NULL client buffer\E[0m\n");
1433 ret = _orig_fastpath_eglCreateImageKHR(dpy, real_ctx, target, real_obj,
1440 _COREGL_FASTPATH_FUNC_END();
1445 fastpath_eglGetProcAddress(const char *procname)
1449 _COREGL_FASTPATH_FUNC_BEGIN();
1451 #define _COREGL_SYMBOL(RET_TYPE, FUNC_NAME, PARAM_LIST) \
1452 if (strcmp(procname, #FUNC_NAME) == 0) \
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; \
1461 #define _COREGL_EXT_SYMBOL_ALIAS(ALIAS_NAME, FUNC_NAME) \
1462 if (strcmp(procname, #ALIAS_NAME) == 0) \
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; \
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
1478 ret = _orig_fastpath_eglGetProcAddress(procname);
1481 #define _COREGL_EXT_SYMBOL_FASTPATH_PASS(FUNC_NAME) \
1482 if (strcmp(procname, #FUNC_NAME) == 0) \
1485 #define _COREGL_EXT_SYMBOL_FASTPATH_BLOCK(FUNC_NAME) \
1486 if (strcmp(procname, #FUNC_NAME) == 0) \
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"
1497 #undef _COREGL_EXT_SYMBOL_FASTPATH_PASS
1498 #undef _COREGL_EXT_SYMBOL_FASTPATH_BLOCK
1500 COREGL_ERR("\E[40;31;1mFASTPATH can't support '%s' (will be terminated with Illegal instruction!)\E[0m\n",
1508 _COREGL_FASTPATH_FUNC_END();
1513 fastpath_eglTerminate(EGLDisplay dpy)
1515 EGLBoolean ret = EGL_FALSE;
1516 GLGlueContext_List *current = NULL;
1517 GLGlueContext_List *remove_list = NULL;
1519 _COREGL_FASTPATH_FUNC_BEGIN();
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;
1529 rm_newitm->next = remove_list;
1530 remove_list = rm_newitm;
1532 current = current->next;
1534 AST(mutex_unlock(&ctx_list_access_mutex) == 1);
1536 current = remove_list;
1537 while (current != NULL) {
1538 fastpath_eglDestroyContext(dpy, current->gctx);
1539 remove_list = current->next;
1541 current = remove_list;
1544 ret = _orig_fastpath_eglTerminate(dpy);
1548 _COREGL_FASTPATH_FUNC_END();