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;
19 _dump_context_info(const char *ment, int force_output)
21 MY_MODULE_TSTATE *tstate = NULL;
22 static struct timeval tv_last = { 0, 0 };
24 if (trace_ctx_flag != 1) return;
26 AST(mutex_lock(&ctx_list_access_mutex) == 1);
27 AST(mutex_lock(&general_trace_lists_access_mutex) == 1);
29 if (!force_output && !trace_ctx_force_flag) {
30 struct timeval tv_now = { 0, 0 };
31 AST(gettimeofday(&tv_now, NULL) == 0);
32 if (tv_now.tv_sec - tv_last.tv_sec < _COREGL_TRACE_OUTPUT_INTERVAL_SEC) {
38 GET_MY_TSTATE(tstate, get_current_thread_state());
41 TRACE("\E[40;34m========================================================================================================================\E[0m\n");
42 TRACE("\E[40;32;1m Context info \E[1;37;1m: <PID = %d> %s\E[0m\n", getpid(),
44 TRACE("\E[40;34m========================================================================================================================\E[0m\n");
49 General_Trace_List *current = NULL;
50 current = thread_trace_list;
52 while (current != NULL) {
53 GLThreadState *cur_tstate = (GLThreadState *)current->value;
54 MY_MODULE_TSTATE *cur_tstate_tm = NULL;
56 GET_MY_TSTATE(cur_tstate_tm, cur_tstate);
57 AST(cur_tstate_tm != NULL);
59 TRACE(" %c Thread [0x%12x] : Surf <D=[%12p] R=[%12p]>",
60 (tstate == cur_tstate_tm) ? '*' : ' ',
61 cur_tstate->thread_id,
62 cur_tstate_tm->rsurf_draw,
63 cur_tstate_tm->rsurf_read);
65 if (cur_tstate_tm->cstate != NULL) {
66 TRACE(" GlueCTX=[%12p] RealCTX=[%12p]\E[0m\n",
67 cur_tstate_tm->cstate->data,
68 cur_tstate_tm->cstate);
70 TRACE(" (NOT BINDED TO THREAD)\E[0m\n");
73 // Binded Context State List
75 General_Trace_List *current = NULL;
76 current = context_state_trace_list;
78 while (current != NULL) {
79 GLContextState *cur_cstate = (GLContextState *)current->value;
80 MY_MODULE_TSTATE *cur_tstate_tm = NULL;
82 GET_MY_TSTATE(cur_tstate_tm, cur_tstate);
83 AST(cur_tstate_tm != NULL);
85 if (cur_tstate_tm->cstate == cur_cstate) {
86 TRACE(" -> RealCTX [%12p] : EGLDPY=[%12p] EGLCTX=[%12p] <[%2d] GlueCTXs>\E[0m\n",
90 cur_cstate->ref_count);
92 // Binded Glue Context List
94 General_Trace_List *current = NULL;
95 current = glue_ctx_trace_list;
97 while (current != NULL) {
98 GLGlueContext *cur_gctx = (GLGlueContext *)current->value;
100 if (cur_gctx->cstate == cur_cstate) {
101 TRACE(" -%c GlueCTX [%12p] : EGLDPY=[%12p] TID=[%12d] <MC count [%10d]>",
102 (cur_cstate->data == cur_gctx) ? '>' : '-',
106 cur_gctx->used_count);
108 TRACE(" <Ref [%2d]>\E[0m\n", cur_gctx->ref_count);
111 current = current->next;
116 current = current->next;
122 current = current->next;
126 TRACE("\E[40;33m........................................................................................................................\E[0m\n");
128 // Not-binded Context State List
130 General_Trace_List *current = NULL;
131 current = context_state_trace_list;
133 while (current != NULL) {
134 GLContextState *cur_cstate = (GLContextState *)current->value;
138 if (cur_cstate->data != NULL) {
139 General_Trace_List *current_t = NULL;
140 current_t = thread_trace_list;
142 while (current_t != NULL) {
143 GLThreadState *cur_tstate = (GLThreadState *)current_t->value;
144 MY_MODULE_TSTATE *cur_tstate_tm = NULL;
146 GET_MY_TSTATE(cur_tstate_tm, cur_tstate);
147 AST(cur_tstate_tm != NULL);
149 if (cur_tstate->thread_id == ((GLGlueContext *)cur_cstate->data)->thread_id) {
150 if (cur_tstate_tm->cstate == cur_cstate)
154 current_t = current_t->next;
159 TRACE(" RealCTX [%12p] : EGLDPY=[%12p] EGLCTX=[%12p] <[%2d] GlueCTXs>\E[0m\n",
163 cur_cstate->ref_count);
165 // Binded Glue Context List
167 General_Trace_List *current = NULL;
168 current = glue_ctx_trace_list;
170 while (current != NULL) {
171 GLGlueContext *cur_gctx = (GLGlueContext *)current->value;
173 if (cur_gctx->cstate == cur_cstate) {
174 TRACE(" -%c GlueCTX [%12p] : EGLDPY=[%12p] TID=[%12d] <MC count [%10d]>",
175 (cur_cstate->data == cur_gctx) ? '>' : '-',
179 cur_gctx->used_count);
181 TRACE(" <Ref [%2d]>\E[0m\n", cur_gctx->ref_count);
184 current = current->next;
189 current = current->next;
194 TRACE("\E[40;33m........................................................................................................................\E[0m\n");
196 // Not-binded Glue Context List
198 General_Trace_List *current = NULL;
199 current = glue_ctx_trace_list;
201 while (current != NULL) {
202 GLGlueContext *cur_gctx = (GLGlueContext *)current->value;
204 if (cur_gctx->cstate == NULL) {
205 TRACE(" GlueCTX [%12p] : EGLDPY=[%12p] TID=[%12d] <MC count [%10d]>",
209 cur_gctx->used_count);
211 TRACE(" <Ref [%2d]>\E[0m\n", cur_gctx->ref_count);
214 current = current->next;
218 TRACE("\E[40;34m========================================================================================================================\E[0m\n");
227 AST(mutex_unlock(&general_trace_lists_access_mutex) == 1);
228 AST(mutex_unlock(&ctx_list_access_mutex) == 1);
232 #endif // COREGL_FASTPATH_TRACE_CONTEXT_INFO
236 EGLint context_major_version;
237 EGLint context_minor_version;
238 EGLint context_flags;
239 EGLint context_opengl_profile_mask;
240 EGLint opengl_reset_notification_strategy;
241 } EGL_packed_attrib_list;
246 EGL_packed_attrib_list attrib_list;
251 EGLContext share_context;
252 } EGL_packed_sharable_option;
256 _pack_egl_context_option(EGL_packed_option *pack_data, EGLDisplay dpy,
257 EGLConfig cfg, EGLint force_unique, const EGLint *attrib_list)
259 static int force_unique_free_id = 0;
262 pack_data->dpy = dpy;
263 pack_data->cfg = cfg;
264 if (force_unique != 0)
265 pack_data->force_unique = force_unique_free_id++;
267 // Default context attributes
268 pack_data->attrib_list.context_major_version = EGL_DONT_CARE;
269 pack_data->attrib_list.context_minor_version = EGL_DONT_CARE;
270 pack_data->attrib_list.context_flags = EGL_DONT_CARE;
271 pack_data->attrib_list.context_opengl_profile_mask = EGL_DONT_CARE;
272 pack_data->attrib_list.opengl_reset_notification_strategy = EGL_DONT_CARE;
274 // Apply specified attributes
275 EGLint *attrib = (EGLint *)attrib_list;
276 while (attrib[0] != EGL_NONE) {
278 case EGL_CONTEXT_MAJOR_VERSION_KHR: // EGL_CONTEXT_CLIENT_VERSION
279 pack_data->attrib_list.context_major_version = attrib[1];
281 case EGL_CONTEXT_MINOR_VERSION_KHR:
282 pack_data->attrib_list.context_minor_version = attrib[1];
284 case EGL_CONTEXT_FLAGS_KHR:
285 pack_data->attrib_list.context_flags = attrib[1];
287 case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
288 pack_data->attrib_list.context_opengl_profile_mask = attrib[1];
290 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
291 pack_data->attrib_list.opengl_reset_notification_strategy = attrib[1];
294 COREGL_WRN("\E[40;31;1mInvalid context attribute.\E[0m\n");
300 // Eject condition for context version
301 if (pack_data->attrib_list.context_major_version != 2) {
302 pack_data->force_unique = force_unique_free_id;
313 _unpack_egl_context_option(EGL_packed_option *pack_data, EGLDisplay *dpy,
314 EGLConfig *cfg, EGLint *force_unique, EGLint *attrib_list,
315 const int attrib_list_size)
319 if (dpy != NULL) *dpy = pack_data->dpy;
320 if (cfg != NULL) *cfg = pack_data->cfg;
321 if (force_unique != NULL) *force_unique = pack_data->force_unique;
323 if (attrib_list != NULL && attrib_list_size > 0) {
324 int attrib_list_index = 0;
326 memset(attrib_list, 0x00, sizeof(int) * attrib_list_size);
328 if (pack_data->attrib_list.context_major_version != EGL_DONT_CARE) {
329 AST(attrib_list_index + 2 < attrib_list_size);
330 attrib_list[attrib_list_index] = EGL_CONTEXT_MAJOR_VERSION_KHR;
331 attrib_list[attrib_list_index + 1] =
332 pack_data->attrib_list.context_major_version;
333 attrib_list_index += 2;
335 if (pack_data->attrib_list.context_minor_version != EGL_DONT_CARE) {
336 AST(attrib_list_index + 2 < attrib_list_size);
337 attrib_list[attrib_list_index] = EGL_CONTEXT_MINOR_VERSION_KHR;
338 attrib_list[attrib_list_index + 1] =
339 pack_data->attrib_list.context_minor_version;
340 attrib_list_index += 2;
342 if (pack_data->attrib_list.context_flags != EGL_DONT_CARE) {
343 AST(attrib_list_index + 2 < attrib_list_size);
344 attrib_list[attrib_list_index] = EGL_CONTEXT_FLAGS_KHR;
345 attrib_list[attrib_list_index + 1] = pack_data->attrib_list.context_flags;
346 attrib_list_index += 2;
348 if (pack_data->attrib_list.context_opengl_profile_mask != EGL_DONT_CARE) {
349 AST(attrib_list_index + 2 < attrib_list_size);
350 attrib_list[attrib_list_index] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR;
351 attrib_list[attrib_list_index + 1] =
352 pack_data->attrib_list.context_opengl_profile_mask;
353 attrib_list_index += 2;
355 if (pack_data->attrib_list.opengl_reset_notification_strategy !=
357 AST(attrib_list_index + 2 < attrib_list_size);
358 attrib_list[attrib_list_index] =
359 EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR;
360 attrib_list[attrib_list_index + 1] =
361 pack_data->attrib_list.opengl_reset_notification_strategy;
362 attrib_list_index += 2;
365 attrib_list[attrib_list_index] = EGL_NONE;
375 _pack_egl_context_sharable_option(EGL_packed_sharable_option *pack_data,
376 EGLContext share_context)
380 pack_data->share_context = share_context;
391 _unpack_egl_context_sharable_option(EGL_packed_sharable_option *pack_data,
392 EGLContext *share_context)
396 if (share_context != NULL) *share_context = pack_data->share_context;
407 _link_context_state(GLGlueContext *gctx, GLContextState *cstate)
409 AST(gctx->cstate == NULL);
411 gctx->cstate = cstate;
415 _unlink_context_state(GLGlueContext *gctx, Mutex *ctx_list_mtx)
417 GLContextState *cstate = NULL;
419 cstate = gctx->cstate;
423 AST(cstate->ref_count >= 0);
425 if (cstate->ref_count == 0) {
426 MY_MODULE_TSTATE *tstate = NULL;
428 AST(cstate->data == NULL || cstate->data == initial_ctx);
430 #ifdef COREGL_FASTPATH_TRACE_CONTEXT_INFO
431 if (unlikely(trace_ctx_flag == 1))
432 remove_from_general_trace_list(&context_state_trace_list, cstate);
433 #endif // COREGL_FASTPATH_TRACE_CONTEXT_INFO
435 AST(fastpath_remove_context_states_from_list(cstate, ctx_list_mtx) == 1);
437 GET_MY_TSTATE(tstate, get_current_thread_state());
438 if (tstate != NULL) {
439 if (tstate->cstate == cstate) {
440 _orig_fastpath_eglMakeCurrent(cstate->rdpy, tstate->rsurf_draw,
441 tstate->rsurf_read, EGL_NO_CONTEXT);
442 tstate->cstate = NULL;
445 _orig_fastpath_eglDestroyContext(cstate->rdpy, cstate->rctx);
452 _add_shared_obj_state_ref(GLGlueContext *gctx, GL_Shared_Object_State *sostate)
454 AST(sostate->ref_count >= 0);
455 sostate->ref_count++;
456 add_to_general_trace_list(&sostate->using_gctxs, gctx);
460 _remove_shared_obj_state_ref(GLGlueContext *gctx,
461 GL_Shared_Object_State *sostate)
463 remove_from_general_trace_list(&sostate->using_gctxs, gctx);
465 // Restore attached states
466 fastpath_release_gl_context(gctx);
468 AST(sostate->ref_count > 0);
469 sostate->ref_count--;
470 if (sostate->ref_count == 0) {
471 fastpath_sostate_deinit(sostate);
477 _add_context_ref(GLGlueContext *gctx)
479 if (gctx == initial_ctx) return;
481 AST(gctx->ref_count >= 0);
486 _remove_context_ref(GLGlueContext *gctx, Mutex *ctx_list_mtx)
488 if (gctx == initial_ctx) return;
490 AST(gctx->ref_count > 0);
492 if (gctx->ref_count == 0) {
493 #ifdef COREGL_FASTPATH_TRACE_CONTEXT_INFO
494 if (unlikely(trace_ctx_flag == 1))
495 remove_from_general_trace_list(&glue_ctx_trace_list, gctx);
496 #endif // COREGL_FASTPATH_TRACE_CONTEXT_INFO
498 AST(gctx->cstate != NULL);
499 if (gctx->cstate->data == gctx)
500 gctx->cstate->data = NULL;
502 _unlink_context_state(gctx, ctx_list_mtx);
504 AST(gctx->ostate.shared != NULL);
505 _remove_shared_obj_state_ref(gctx, gctx->ostate.shared);
506 gctx->ostate.shared = NULL;
508 fastpath_ostate_deinit(&gctx->ostate);
510 if (gctx->real_ctx_option != NULL) {
511 free(gctx->real_ctx_option);
512 gctx->real_ctx_option = NULL;
514 if (gctx->real_ctx_sharable_option != NULL) {
515 free(gctx->real_ctx_sharable_option);
516 gctx->real_ctx_sharable_option = NULL;
521 GLGlueContext_List *current = NULL;
523 AST(mutex_lock(&ctx_list_access_mutex) == 1);
527 while (current != NULL) {
528 if (current->gctx == gctx) {
529 if (current->next != NULL)
530 current->next->prev = current->prev;
532 if (current->prev != NULL)
533 current->prev->next = current->next;
535 gctx_list = current->next;
541 current = current->next;
544 AST(mutex_unlock(&ctx_list_access_mutex) == 1);
550 _bind_context_state(GLGlueContext *gctx, GLContextState *cstate,
554 AST(gctx->cstate == cstate);
557 if (cstate->data != gctx) {
558 GLGlueContext *curctx = (GLGlueContext *)cstate->data;
559 GLGlueContext *newctx = gctx;
562 newctx = initial_ctx;
565 curctx = initial_ctx;
570 if (!fastpath_make_context_current(curctx, newctx))
573 cstate->data = (void *)newctx;
574 _remove_context_ref(curctx, ctx_list_mtx);
575 _add_context_ref(newctx);
583 _egl_create_context(EGL_packed_option *real_ctx_option,
584 GLContextState **cstate_new, EGLContext *ctx,
585 EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
587 GLContextState *cstate = NULL;
589 AST(real_ctx_option != NULL);
590 AST(cstate_new != NULL);
593 // Pack context option
594 AST(_pack_egl_context_option(real_ctx_option, dpy, config, 0,
597 if (debug_nofp == 1) {
598 AST(_pack_egl_context_option(real_ctx_option, dpy, config, 1,
602 // Find context state
603 if (real_ctx_option->force_unique == 0) {
604 cstate = fastpath_get_context_state_from_list(real_ctx_option,
605 sizeof(EGL_packed_option), &ctx_list_access_mutex);
608 // Create a real context if it hasn't been created
609 if (cstate == NULL) {
610 EGLContext *real_share_context = EGL_NO_CONTEXT;
612 AST(mutex_lock(&ctx_list_access_mutex) == 1);
614 GLContext_List *current = NULL;
616 current = glctx_list;
617 while (current != NULL) {
618 EGLDisplay cur_dpy = EGL_NO_DISPLAY;
619 AST(_unpack_egl_context_option(current->option, &cur_dpy, NULL, NULL, NULL,
621 if (cur_dpy == dpy) {
622 AST(current->cstate != NULL);
623 real_share_context = current->cstate->rctx;
626 current = current->next;
629 AST(mutex_unlock(&ctx_list_access_mutex) == 1);
631 *ctx = _orig_fastpath_eglCreateContext(dpy, config, real_share_context,
634 if (*ctx == EGL_NO_CONTEXT) {
635 COREGL_WRN("\E[40;31;1mFailed creating a egl real context for Fastpath. (Invalid config?)\E[0m\n");
639 *cstate_new = (GLContextState *)calloc(1, sizeof(GLContextState));
640 if (*cstate_new == NULL) {
641 COREGL_ERR("\E[40;31;1mError creating a new context state. (Memory full)\E[0m\n");
644 (*cstate_new)->rctx = *ctx;
645 (*cstate_new)->rdpy = dpy;
646 (*cstate_new)->data = NULL;
648 AST(fastpath_add_context_state_to_list(real_ctx_option,
649 sizeof(EGL_packed_option), *cstate_new, &ctx_list_access_mutex) == 1);
651 #ifdef COREGL_FASTPATH_TRACE_CONTEXT_INFO
652 if (unlikely(trace_ctx_flag == 1))
653 add_to_general_trace_list(&context_state_trace_list, *cstate_new);
654 #endif // COREGL_FASTPATH_TRACE_CONTEXT_INFO
656 cstate = *cstate_new;
667 extern EGLBoolean (*ovr_eglBindAPI)(EGLenum api);
668 extern EGLenum (*ovr_eglQueryAPI)(void);
671 fastpath_eglBindAPI(EGLenum api)
673 EGLBoolean ret = EGL_FALSE;
674 MY_MODULE_TSTATE *tstate = NULL;
676 _COREGL_FASTPATH_FUNC_BEGIN();
677 if (fp_opt == FP_UNKNOWN_PATH) {
678 COREGL_ERR("\E[40;31;1mInvalid library link! (CoreGL path option is invalid)\E[0m\n");
682 ret = _orig_fastpath_eglBindAPI(api);
684 GET_MY_TSTATE(tstate, get_current_thread_state());
685 if (tstate == NULL) {
686 AST(init_new_thread_state() == 1);
688 GET_MY_TSTATE(tstate, get_current_thread_state());
693 EGLenum newapi = _orig_fastpath_eglQueryAPI();
694 if (tstate->binded_api != EGL_OPENGL_ES_API) {
695 tstate->binded_api = newapi;
702 _COREGL_FASTPATH_FUNC_END();
707 fastpath_eglQueryAPI(void)
710 MY_MODULE_TSTATE *tstate = NULL;
712 _COREGL_FASTPATH_FUNC_BEGIN();
713 if (fp_opt == FP_UNKNOWN_PATH) {
714 COREGL_ERR("\E[40;31;1mInvalid library link! (CoreGL path option is invalid)\E[0m\n");
718 ret = _orig_fastpath_eglQueryAPI();
720 GET_MY_TSTATE(tstate, get_current_thread_state());
721 if (tstate != NULL) {
722 AST(tstate->binded_api == ret);
728 _COREGL_FASTPATH_FUNC_END();
733 fastpath_eglCreateContext(EGLDisplay dpy, EGLConfig config,
734 EGLContext share_context, const EGLint *attrib_list)
736 GLGlueContext *gctx = NULL, *newgctx = NULL;
737 GLGlueContext_List *gctx_list_new = NULL;
738 MY_MODULE_TSTATE *tstate = NULL;
739 GLContextState *cstate = NULL;
740 GLContextState *cstate_new = NULL;
741 GL_Shared_Object_State *sostate_new = NULL;
742 GLContext ctx = NULL;
744 EGL_packed_option *real_ctx_option = NULL;
745 EGL_packed_sharable_option *real_ctx_sharable_option = NULL;
747 // Special eject condition for binding API
748 GET_MY_TSTATE(tstate, get_current_thread_state());
749 if (tstate != NULL && tstate->binded_api != EGL_OPENGL_ES_API) {
750 return _orig_fastpath_eglCreateContext(dpy, config, share_context, attrib_list);
753 _COREGL_FASTPATH_FUNC_BEGIN();
755 real_ctx_option = (EGL_packed_option *)calloc(1, sizeof(EGL_packed_option));
756 if (real_ctx_option == NULL) {
757 COREGL_ERR("\E[40;31;1mError creating a new GLGlueContext(Memory full 1)\E[0m\n");
760 cstate = _egl_create_context(real_ctx_option, &cstate_new, &ctx, dpy, config,
764 // Pack shared context options
765 real_ctx_sharable_option = (EGL_packed_sharable_option *)calloc(1,
766 sizeof(EGL_packed_sharable_option));
767 if (real_ctx_sharable_option == NULL) {
768 COREGL_ERR("\E[40;31;1mError creating a new GLGlueContext(Memory full 2)\E[0m\n");
771 AST(_pack_egl_context_sharable_option(real_ctx_sharable_option,
772 share_context) == 1);
774 // Allocate a new context
775 newgctx = (GLGlueContext *)calloc(1, sizeof(GLGlueContext));
776 if (newgctx == NULL) {
777 COREGL_ERR("\E[40;31;1mError creating a new GLGlueContext(Memory full 3)\E[0m\n");
781 newgctx->magic = MAGIC_GLFAST;
782 newgctx->initialized = 0;
784 newgctx->thread_id = get_current_thread();
786 fastpath_ostate_init(&newgctx->ostate);
788 if (share_context != EGL_NO_CONTEXT) {
789 GLGlueContext *shared_gctx = (GLGlueContext *)share_context;
790 AST(shared_gctx->magic == MAGIC_GLFAST);
791 AST(shared_gctx->ostate.shared != NULL);
792 newgctx->ostate.shared = shared_gctx->ostate.shared;
794 sostate_new = (GL_Shared_Object_State *)calloc(1,
795 sizeof(GL_Shared_Object_State));
796 if (sostate_new == NULL) {
797 COREGL_ERR("\E[40;31;1mError creating a new GLGlueContext(Memory full 4)\E[0m\n");
800 fastpath_sostate_init(sostate_new);
801 newgctx->ostate.shared = sostate_new;
803 _add_shared_obj_state_ref(newgctx, newgctx->ostate.shared);
804 newgctx->real_ctx_option = real_ctx_option;
805 newgctx->real_ctx_option_len = sizeof(EGL_packed_option);
806 newgctx->real_ctx_sharable_option = real_ctx_sharable_option;
807 newgctx->real_ctx_sharable_option_len = sizeof(EGL_packed_sharable_option);
809 _link_context_state(newgctx, cstate);
810 _add_context_ref(newgctx);
812 newgctx->cstate = cstate;
815 // Add glue context to list
816 gctx_list_new = (GLGlueContext_List *)calloc(1, sizeof(GLGlueContext_List));
817 if (gctx_list_new == NULL) {
818 COREGL_ERR("\E[40;31;1mError creating a new GlGlueContext(Memory full 5)\E[0m\n");
822 AST(mutex_lock(&ctx_list_access_mutex) == 1);
824 gctx_list_new->gctx = newgctx;
826 gctx_list_new->prev = NULL;
827 gctx_list_new->next = gctx_list;
828 if (gctx_list != NULL)
829 gctx_list->prev = gctx_list_new;
831 gctx_list = gctx_list_new;
833 AST(mutex_unlock(&ctx_list_access_mutex) == 1);
838 #ifdef COREGL_FASTPATH_TRACE_CONTEXT_INFO
839 if (unlikely(trace_ctx_flag == 1)) {
841 add_to_general_trace_list(&glue_ctx_trace_list, newgctx);
843 sprintf(ment, "eglCreateContext completed (GlueCTX=[%12p])", newgctx);
844 _dump_context_info(ment, 1);
846 #endif // COREGL_FASTPATH_TRACE_CONTEXT_INFO
853 _orig_fastpath_eglDestroyContext(dpy, ctx);
856 if (sostate_new != NULL) {
860 if (real_ctx_option != NULL) {
861 free(real_ctx_option);
862 real_ctx_option = NULL;
864 if (real_ctx_sharable_option != NULL) {
865 free(real_ctx_sharable_option);
866 real_ctx_sharable_option = NULL;
868 if (cstate_new != NULL) {
869 #ifdef COREGL_FASTPATH_TRACE_CONTEXT_INFO
870 if (unlikely(trace_ctx_flag == 1))
871 remove_from_general_trace_list(&context_state_trace_list, cstate_new);
872 #endif // COREGL_FASTPATH_TRACE_CONTEXT_INFO
874 fastpath_remove_context_states_from_list(cstate_new, &ctx_list_access_mutex);
878 if (gctx_list_new != NULL) {
879 AST(mutex_lock(&ctx_list_access_mutex) == 1);
881 if (gctx_list_new->next != NULL)
882 gctx_list_new->next->prev = gctx_list_new->prev;
884 if (gctx_list_new->prev != NULL)
885 gctx_list_new->prev->next = gctx_list_new->next;
887 gctx_list = gctx_list_new->next;
889 AST(mutex_unlock(&ctx_list_access_mutex) == 1);
893 if (newgctx != NULL) {
894 _remove_context_ref(newgctx, &ctx_list_access_mutex);
900 _COREGL_FASTPATH_FUNC_END();
901 return (EGLContext)gctx;
905 fastpath_eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
907 EGLBoolean ret = EGL_FALSE;
908 GLGlueContext *gctx = NULL;
910 _COREGL_FASTPATH_FUNC_BEGIN();
912 gctx = (GLGlueContext *)ctx;
914 if (gctx != NULL && gctx != EGL_NO_CONTEXT) {
915 GLContextState *cstate = NULL;
917 if (gctx->magic != MAGIC_GLFAST) {
918 ret = _orig_fastpath_eglDestroyContext(dpy, ctx);
922 cstate = gctx->cstate;
925 if (gctx->is_destroyed != 1) {
926 gctx->is_destroyed = 1;
927 _remove_context_ref(gctx, &ctx_list_access_mutex);
930 COREGL_WRN("\E[40;31;1mInvalid destroying context. (no exists)\E[0m\n");
939 _COREGL_FASTPATH_FUNC_END();
941 #ifdef COREGL_FASTPATH_TRACE_CONTEXT_INFO
942 if (unlikely(trace_ctx_flag == 1)) {
944 sprintf(ment, "eglDestroyContext completed (GlueCTX=[%12p])", ctx);
945 _dump_context_info(ment, 1);
947 #endif // COREGL_FASTPATH_TRACE_CONTEXT_INFO
953 fastpath_eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute,
956 EGLBoolean ret = EGL_FALSE;
957 EGLContext real_ctx = EGL_NO_CONTEXT;
959 _COREGL_FASTPATH_FUNC_BEGIN();
961 if (ctx != EGL_NO_CONTEXT) {
962 GLGlueContext *gctx = NULL;
963 gctx = (GLGlueContext *)ctx;
965 if (gctx->magic != MAGIC_GLFAST) {
968 AST(gctx->cstate != NULL);
969 real_ctx = gctx->cstate->rctx;
973 ret = _orig_fastpath_eglQueryContext(dpy, real_ctx, attribute, value);
977 _COREGL_FASTPATH_FUNC_END();
984 fastpath_eglReleaseThread(void)
986 EGLBoolean ret = EGL_FALSE;
987 EGLDisplay dpy = EGL_NO_DISPLAY;
988 MY_MODULE_TSTATE *tstate = NULL;
990 GET_MY_TSTATE(tstate, get_current_thread_state());
992 // Special eject condition for binding API
993 if (tstate != NULL && tstate->binded_api != EGL_OPENGL_ES_API) {
994 return _orig_fastpath_eglReleaseThread();
997 _COREGL_FASTPATH_FUNC_BEGIN();
999 dpy = _orig_fastpath_eglGetCurrentDisplay();
1000 AST(dpy != EGL_NO_DISPLAY);
1001 fastpath_eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
1002 ret = _orig_fastpath_eglReleaseThread();
1006 _COREGL_FASTPATH_FUNC_END();
1011 fastpath_eglGetCurrentDisplay(void)
1013 MY_MODULE_TSTATE *tstate = NULL;
1014 EGLDisplay dpy = EGL_NO_DISPLAY;
1016 GET_MY_TSTATE(tstate, get_current_thread_state());
1018 if (tstate != NULL) {
1019 // Special eject condition for binding API
1020 if (tstate->binded_api != EGL_OPENGL_ES_API) {
1021 return _orig_fastpath_eglGetCurrentDisplay();
1024 _COREGL_FASTPATH_FUNC_BEGIN();
1026 if (tstate->cstate != NULL) {
1027 dpy = tstate->cstate->rdpy;
1031 _COREGL_FASTPATH_FUNC_END();
1043 fastpath_eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
1046 EGLBoolean ret = EGL_FALSE;
1047 EGLBoolean need_mc = EGL_FALSE;
1048 GLGlueContext *gctx = NULL;
1050 MY_MODULE_TSTATE *tstate = NULL;
1052 GET_MY_TSTATE(tstate, get_current_thread_state());
1054 // Special eject condition for binding API
1055 if (tstate != NULL && tstate->binded_api != EGL_OPENGL_ES_API) {
1056 return _orig_fastpath_eglMakeCurrent(dpy, draw, read, ctx);
1059 _COREGL_FASTPATH_FUNC_BEGIN();
1061 gctx = (GLGlueContext *)ctx;
1063 if (tstate == NULL) {
1064 AST(init_new_thread_state() == 1);
1066 GET_MY_TSTATE(tstate, get_current_thread_state());
1067 AST(tstate != NULL);
1070 // Special path for context deletion
1071 if (ctx == EGL_NO_CONTEXT) {
1074 if (tstate->cstate != NULL) {
1075 if (_bind_context_state(NULL, tstate->cstate, &ctx_list_access_mutex) != 1) {
1076 COREGL_WRN("\E[40;31;1mError soft-makecurrent for context deletion\E[0m\n");
1078 tstate->cstate = NULL;
1080 if (_orig_fastpath_eglMakeCurrent(dpy, draw, read, ctx) != EGL_TRUE) {
1081 COREGL_WRN("Error making context [%p] current. (invalid EGL display [%p] or EGL surface [D:%p/R:%p])\n",
1082 ctx, dpy, draw, read);
1087 tstate->rsurf_draw = draw;
1088 tstate->rsurf_read = read;
1095 AST(gctx->cstate != NULL);
1097 if (gctx->rdpy != dpy) {
1098 COREGL_WRN("\E[40;31;1mInvalid context (or invalid EGL display)\E[0m\n");
1103 AST(gctx->real_ctx_option != NULL);
1104 AST(gctx->real_ctx_sharable_option != NULL);
1106 // Handle cross threading of context (when used by two or more gctx)
1107 if (gctx->thread_id != get_current_thread() && gctx->cstate->ref_count > 1) {
1108 #define ATTRIB_LIST_BUFFER_SIZE 8
1110 GLContextState *cstate_new = NULL;
1111 EGLContext new_real_ctx = EGL_NO_CONTEXT;
1113 EGLDisplay dpy = EGL_NO_DISPLAY;
1114 EGLConfig config = NULL;
1115 int attrib_list[ATTRIB_LIST_BUFFER_SIZE];
1117 AST(_unpack_egl_context_option(gctx->real_ctx_option, &dpy, &config, NULL,
1118 attrib_list, ATTRIB_LIST_BUFFER_SIZE) == 1);
1119 AST(dpy == gctx->rdpy);
1121 _egl_create_context(gctx->real_ctx_option, &cstate_new, &new_real_ctx, dpy,
1122 config, attrib_list);
1124 AST(cstate_new != NULL);
1126 if (_bind_context_state(gctx, cstate_new, &ctx_list_access_mutex) != 1) {
1127 COREGL_WRN("\E[40;31;1mError soft-makecurrent in Cross-thread usage!\E[0m\n");
1129 _orig_fastpath_eglDestroyContext(dpy, new_real_ctx);
1134 // TODO : Setup context state for new real ctx
1135 COREGL_WRN("\E[40;31;1mCross-thread usage(makecurrent) can cause a state-broken situation!\E[0m\n");
1137 _unlink_context_state(gctx, &ctx_list_access_mutex);
1138 _link_context_state(gctx, cstate_new);
1140 // Apply to new thread
1141 gctx->thread_id = get_current_thread();
1145 // Check if the object is correct
1146 if (gctx->magic != MAGIC_GLFAST) {
1147 COREGL_ERR("\E[40;31;1mGlue-CTX Magic Check Failed!!! (Memory broken?)\E[0m\n");
1153 // If drawable changed, do a make current
1154 if ((tstate->rsurf_draw != draw) ||
1155 (tstate->rsurf_read != read))
1158 AST(gctx->cstate != NULL);
1160 // If binded real context changed, do a make current
1161 if (tstate->cstate == NULL || tstate->cstate != gctx->cstate)
1164 if (need_mc == EGL_TRUE) {
1165 AST(dpy == gctx->cstate->rdpy);
1167 // BB : full makecurrent
1168 if (_orig_fastpath_eglMakeCurrent(dpy, draw, read,
1169 gctx->cstate->rctx) != EGL_TRUE) {
1170 COREGL_WRN("\E[40;31;1mError making context current with the drawable. (Bad match?)\E[0m\n");
1175 // Update references only when the contexts are different
1176 if (tstate->cstate != gctx->cstate) {
1177 if (tstate->cstate != NULL && tstate->cstate->data != NULL)
1178 _remove_context_ref((GLGlueContext *)tstate->cstate->data,
1179 &ctx_list_access_mutex);
1181 tstate->cstate = gctx->cstate;
1183 if (tstate->cstate->data != NULL)
1184 _add_context_ref((GLGlueContext *)tstate->cstate->data);
1187 tstate->rsurf_draw = draw;
1188 tstate->rsurf_read = read;
1191 // Initialize context states
1192 if (gctx->initialized == 0) {
1193 if (fastpath_init_context_states(gctx) != 1) {
1194 COREGL_ERR("\E[40;31;1mError intializing context. (Check driver specification)\E[0m\n");
1199 // Setup initial Viewport & Scissor
1200 if (gctx->surface_attached == 0 && draw != EGL_NO_SURFACE) {
1201 EGLint box_buffer[4];
1205 _orig_fastpath_glGetIntegerv(GL_VIEWPORT, box_buffer);
1206 width = box_buffer[2];
1207 height = box_buffer[3];
1209 gctx->_clear_flag1 |= _CLEAR_FLAG1_BIT_gl_viewport;
1210 gctx->gl_viewport[0] = 0;
1211 gctx->gl_viewport[1] = 0;
1212 gctx->gl_viewport[2] = width;
1213 gctx->gl_viewport[3] = height;
1215 _orig_fastpath_glGetIntegerv(GL_SCISSOR_BOX, box_buffer);
1216 width = box_buffer[2];
1217 height = box_buffer[3];
1219 gctx->_misc_flag2 |= _MISC_FLAG2_BIT_gl_scissor_box;
1220 gctx->gl_scissor_box[0] = 0;
1221 gctx->gl_scissor_box[1] = 0;
1222 gctx->gl_scissor_box[2] = width;
1223 gctx->gl_scissor_box[3] = height;
1225 gctx->surface_attached = 1;
1228 if (_bind_context_state(gctx, tstate->cstate, &ctx_list_access_mutex) != 1) {
1239 _COREGL_FASTPATH_FUNC_END();
1241 #ifdef COREGL_FASTPATH_TRACE_CONTEXT_INFO
1242 if (unlikely(trace_ctx_flag == 1)) {
1244 sprintf(ment, "eglMakeCurrent finished (GlueCTX=[%12p] Surf=[D:%12p R:%12p])",
1246 _dump_context_info(ment, 0);
1248 #endif // COREGL_FASTPATH_TRACE_CONTEXT_INFO
1255 fastpath_eglGetCurrentContext(void)
1257 GLGlueContext *ret = NULL;
1258 MY_MODULE_TSTATE *tstate = NULL;
1260 GET_MY_TSTATE(tstate, get_current_thread_state());
1262 // Special eject condition for binding API
1263 if (tstate != NULL && tstate->binded_api != EGL_OPENGL_ES_API) {
1264 return _orig_fastpath_eglGetCurrentContext();
1267 _COREGL_FASTPATH_FUNC_BEGIN();
1269 if (tstate != NULL) {
1270 if (tstate->cstate != NULL) {
1271 ret = (GLGlueContext *)tstate->cstate->data;
1272 AST(ret->magic == MAGIC_GLFAST);
1278 _COREGL_FASTPATH_FUNC_END();
1279 return (EGLContext)ret;
1284 fastpath_eglGetCurrentSurface(EGLint readdraw)
1286 EGLSurface ret = EGL_NO_SURFACE;
1287 MY_MODULE_TSTATE *tstate = NULL;
1289 GET_MY_TSTATE(tstate, get_current_thread_state());
1291 // Special eject condition for binding API
1292 if (tstate != NULL && tstate->binded_api != EGL_OPENGL_ES_API) {
1293 return _orig_fastpath_eglGetCurrentSurface(readdraw);
1296 _COREGL_FASTPATH_FUNC_BEGIN();
1298 if (tstate != NULL) {
1301 ret = (GLGlueContext *)tstate->rsurf_draw;
1304 ret = (GLGlueContext *)tstate->rsurf_read;
1311 _COREGL_FASTPATH_FUNC_END();
1316 fastpath_eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target,
1317 EGLClientBuffer buffer, const EGLint *attrib_list)
1320 EGLContext real_ctx = EGL_NO_CONTEXT;
1321 GLuint real_obj = 0;
1323 _COREGL_FASTPATH_FUNC_BEGIN();
1325 if (ctx != NULL && ctx != EGL_NO_CONTEXT) {
1326 GLGlueContext *gctx = (GLGlueContext *)ctx;
1328 if (gctx->magic != MAGIC_GLFAST) {
1331 AST(gctx->cstate != NULL);
1332 real_ctx = gctx->cstate->rctx;
1336 case EGL_GL_TEXTURE_2D_KHR:
1337 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
1338 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
1339 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
1340 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
1341 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
1342 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
1343 case EGL_GL_TEXTURE_3D_KHR:
1344 case EGL_GL_RENDERBUFFER_KHR:
1345 if ((GLuint )buffer == 0) {
1346 COREGL_ERR("\E[40;31;1m fastpath_eglCreateImageKHR buffer object NULL \E[0m\n");
1349 real_obj = fastpath_ostate_get_object(&gctx->ostate, GL_OBJECT_TYPE_TEXTURE,
1354 COREGL_ERR("\E[40;31;1mError Not supported target NULL client buffer\E[0m\n");
1359 real_obj = (GLuint )buffer;
1362 ret = _orig_fastpath_eglCreateImageKHR(dpy, real_ctx, target,
1363 (EGLClientBuffer)real_obj, attrib_list);
1369 _COREGL_FASTPATH_FUNC_END();
1374 fastpath_eglGetProcAddress(const char *procname)
1378 _COREGL_FASTPATH_FUNC_BEGIN();
1380 #define _COREGL_SYMBOL(RET_TYPE, FUNC_NAME, PARAM_LIST) \
1381 if (strcmp(procname, #FUNC_NAME) == 0) \
1383 _eng_fn ret_orig = NULL; \
1384 ret_orig = _orig_fastpath_eglGetProcAddress(procname); \
1385 if (ret_orig != NULL) \
1386 ret = (_eng_fn)ovr_##FUNC_NAME; \
1390 #define _COREGL_EXT_SYMBOL_ALIAS(ALIAS_NAME, FUNC_NAME) \
1391 if (strcmp(procname, #ALIAS_NAME) == 0) \
1393 _eng_fn ret_orig = NULL; \
1394 ret_orig = _orig_fastpath_eglGetProcAddress(#ALIAS_NAME); \
1395 if (ret_orig != NULL) \
1396 ret = (_eng_fn)ovr_##FUNC_NAME; \
1400 #include "../../headers/sym_egl.h"
1401 #include "../../headers/sym_gl.h"
1402 #undef _COREGL_SYMBOL
1403 #undef _COREGL_EXT_SYMBOL_ALIAS
1405 ret = _orig_fastpath_eglGetProcAddress(procname);
1408 #define _COREGL_EXT_SYMBOL_FASTPATH_PASS(FUNC_NAME) \
1409 if (strcmp(procname, #FUNC_NAME) == 0) \
1412 #define _COREGL_EXT_SYMBOL_FASTPATH_BLOCK(FUNC_NAME) \
1413 if (strcmp(procname, #FUNC_NAME) == 0) \
1419 #include "../../headers/sym_egl.h"
1420 #include "../../headers/sym_gl.h"
1421 #undef _COREGL_EXT_SYMBOL_FASTPATH_PASS
1422 #undef _COREGL_EXT_SYMBOL_FASTPATH_BLOCK
1424 COREGL_ERR("\E[40;31;1mFASTPATH can't support '%s' (will be terminated with Illegal instruction!)\E[0m\n",
1432 _COREGL_FASTPATH_FUNC_END();
1437 fastpath_eglTerminate(EGLDisplay dpy)
1439 EGLBoolean ret = EGL_FALSE;
1440 GLGlueContext_List *current = NULL;
1441 GLGlueContext_List *remove_list = NULL;
1443 _COREGL_FASTPATH_FUNC_BEGIN();
1445 AST(mutex_lock(&ctx_list_access_mutex) == 1);
1446 current = gctx_list;
1447 while (current != NULL) {
1448 if (current->gctx->cstate->rdpy == dpy) {
1449 GLGlueContext_List *rm_newitm = NULL;
1450 rm_newitm = (GLGlueContext_List *)calloc(1, sizeof(GLGlueContext_List));
1451 rm_newitm->gctx = current->gctx;
1453 rm_newitm->next = remove_list;
1454 remove_list = rm_newitm;
1456 current = current->next;
1458 AST(mutex_unlock(&ctx_list_access_mutex) == 1);
1460 current = remove_list;
1461 while (current != NULL) {
1462 fastpath_eglDestroyContext(dpy, current->gctx);
1463 remove_list = current->next;
1465 current = remove_list;
1468 ret = _orig_fastpath_eglTerminate(dpy);
1472 _COREGL_FASTPATH_FUNC_END();