1 #include "coregl_fastpath.h"
12 #include "../../include_KHR/EGL/eglext.h"
14 #ifdef COREGL_FASTPATH_TRACE_CONTEXT_INFO
16 General_Trace_List *glue_ctx_trace_list = NULL;
17 General_Trace_List *context_state_trace_list = NULL;
18 int current_gl_api_version = 0;
21 _dump_context_info(const char *ment, int force_output)
23 MY_MODULE_TSTATE *tstate = NULL;
24 static struct timeval tv_last = { 0, 0 };
26 if (get_trace_ctx_flag() != 1) return;
28 AST(mutex_lock(&ctx_list_access_mutex) == 1);
29 AST(mutex_lock(&general_trace_lists_access_mutex) == 1);
31 if (!force_output && !get_trace_ctx_force_flag()) {
32 struct timeval tv_now = { 0, 0 };
33 AST(gettimeofday(&tv_now, NULL) == 0);
34 if (tv_now.tv_sec - tv_last.tv_sec < _COREGL_TRACE_OUTPUT_INTERVAL_SEC) {
40 GET_MY_TSTATE(tstate, get_current_thread_state());
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(),
46 TRACE("\E[40;34m========================================================================================================================\E[0m\n");
51 General_Trace_List *current = NULL;
52 current = thread_trace_list;
54 while (current != NULL) {
55 GLThreadState *cur_tstate = (GLThreadState *)current->value;
56 MY_MODULE_TSTATE *cur_tstate_tm = NULL;
58 GET_MY_TSTATE(cur_tstate_tm, cur_tstate);
59 AST(cur_tstate_tm != NULL);
61 if (cur_tstate_tm == NULL)
64 TRACE(" %c Thread [0x%12x] : Surf <D=[%12p] R=[%12p]>",
65 (tstate == cur_tstate_tm) ? '*' : ' ',
66 cur_tstate->thread_id,
67 cur_tstate_tm->rsurf_draw,
68 cur_tstate_tm->rsurf_read);
70 if (cur_tstate_tm->cstate != NULL) {
71 TRACE(" GlueCTX=[%12p] RealCTX=[%12p]\E[0m\n",
72 cur_tstate_tm->cstate->data,
73 cur_tstate_tm->cstate);
75 TRACE(" (NOT BINDED TO THREAD)\E[0m\n");
78 // Binded Context State List
80 General_Trace_List *current = NULL;
81 current = context_state_trace_list;
83 while (current != NULL) {
84 GLContextState *cur_cstate = (GLContextState *)current->value;
85 MY_MODULE_TSTATE *cur_tstate_tm = NULL;
87 GET_MY_TSTATE(cur_tstate_tm, cur_tstate);
88 AST(cur_tstate_tm != NULL);
90 if (cur_tstate_tm != NULL && cur_tstate_tm->cstate == cur_cstate) {
91 TRACE(" -> RealCTX [%12p] : EGLDPY=[%12p] EGLCTX=[%12p] <[%2d] GlueCTXs>\E[0m\n",
95 cur_cstate->ref_count);
97 // Binded Glue Context List
99 General_Trace_List *current = NULL;
100 current = glue_ctx_trace_list;
102 while (current != NULL) {
103 GLGlueContext *cur_gctx = (GLGlueContext *)current->value;
105 if (cur_gctx->cstate == cur_cstate) {
106 TRACE(" -%c GlueCTX [%12p] : EGLDPY=[%12p] TID=[%12d] <MC count [%10d]>",
107 (cur_cstate->data == cur_gctx) ? '>' : '-',
111 cur_gctx->used_count);
113 TRACE(" <Ref [%2d]>\E[0m\n", cur_gctx->ref_count);
116 current = current->next;
121 current = current->next;
127 current = current->next;
131 TRACE("\E[40;33m........................................................................................................................\E[0m\n");
133 // Not-binded Context State List
135 General_Trace_List *current = NULL;
136 current = context_state_trace_list;
138 while (current != NULL) {
139 GLContextState *cur_cstate = (GLContextState *)current->value;
143 if (cur_cstate->data != NULL) {
144 General_Trace_List *current_t = NULL;
145 current_t = thread_trace_list;
147 while (current_t != NULL) {
148 GLThreadState *cur_tstate = (GLThreadState *)current_t->value;
149 MY_MODULE_TSTATE *cur_tstate_tm = NULL;
151 GET_MY_TSTATE(cur_tstate_tm, cur_tstate);
152 AST(cur_tstate_tm != NULL);
154 if (cur_tstate_tm != NULL
155 && cur_tstate->thread_id == ((GLGlueContext *)cur_cstate->data)->thread_id) {
156 if (cur_tstate_tm->cstate == cur_cstate)
160 current_t = current_t->next;
165 TRACE(" RealCTX [%12p] : EGLDPY=[%12p] EGLCTX=[%12p] <[%2d] GlueCTXs>\E[0m\n",
169 cur_cstate->ref_count);
171 // Binded Glue Context List
173 General_Trace_List *current = NULL;
174 current = glue_ctx_trace_list;
176 while (current != NULL) {
177 GLGlueContext *cur_gctx = (GLGlueContext *)current->value;
179 if (cur_gctx->cstate == cur_cstate) {
180 TRACE(" -%c GlueCTX [%12p] : EGLDPY=[%12p] TID=[%12d] <MC count [%10d]>",
181 (cur_cstate->data == cur_gctx) ? '>' : '-',
185 cur_gctx->used_count);
187 TRACE(" <Ref [%2d]>\E[0m\n", cur_gctx->ref_count);
190 current = current->next;
195 current = current->next;
200 TRACE("\E[40;33m........................................................................................................................\E[0m\n");
202 // Not-binded Glue Context List
204 General_Trace_List *current = NULL;
205 current = glue_ctx_trace_list;
207 while (current != NULL) {
208 GLGlueContext *cur_gctx = (GLGlueContext *)current->value;
210 if (cur_gctx->cstate == NULL) {
211 TRACE(" GlueCTX [%12p] : EGLDPY=[%12p] TID=[%12d] <MC count [%10d]>",
215 cur_gctx->used_count);
217 TRACE(" <Ref [%2d]>\E[0m\n", cur_gctx->ref_count);
220 current = current->next;
224 TRACE("\E[40;34m========================================================================================================================\E[0m\n");
233 AST(mutex_unlock(&general_trace_lists_access_mutex) == 1);
234 AST(mutex_unlock(&ctx_list_access_mutex) == 1);
238 #endif // COREGL_FASTPATH_TRACE_CONTEXT_INFO
242 EGLint context_major_version;
243 EGLint context_minor_version;
244 EGLint context_flags;
245 EGLint context_opengl_profile_mask;
246 EGLint opengl_robust_access_ext;
247 EGLint opengl_reset_notification_strategy_khr;
248 EGLint opengl_reset_notification_strategy_ext;
249 } EGL_packed_attrib_list;
254 EGL_packed_attrib_list attrib_list;
259 EGLContext share_context;
260 } EGL_packed_sharable_option;
264 _pack_egl_context_option(EGL_packed_option *pack_data, EGLDisplay dpy,
265 EGLConfig cfg, EGLint force_unique, const EGLint *attrib_list)
267 static int force_unique_free_id = 0;
270 pack_data->dpy = dpy;
271 pack_data->cfg = cfg;
272 if (force_unique != 0)
273 pack_data->force_unique = force_unique_free_id++;
275 // Default context attributes
276 pack_data->attrib_list.context_major_version = 1;
277 pack_data->attrib_list.context_minor_version = 0;
278 pack_data->attrib_list.context_flags = EGL_DONT_CARE;
279 pack_data->attrib_list.context_opengl_profile_mask = EGL_DONT_CARE;
280 pack_data->attrib_list.opengl_robust_access_ext = EGL_DONT_CARE;
281 pack_data->attrib_list.opengl_reset_notification_strategy_khr = EGL_DONT_CARE;
282 pack_data->attrib_list.opengl_reset_notification_strategy_ext = EGL_DONT_CARE;
284 // Apply specified attributes
285 EGLint *attrib = (EGLint *)attrib_list;
286 while ((attrib != NULL) && (attrib[0] != EGL_NONE)) {
288 case EGL_CONTEXT_MAJOR_VERSION_KHR: // EGL_CONTEXT_CLIENT_VERSION
289 pack_data->attrib_list.context_major_version = attrib[1];
291 case EGL_CONTEXT_MINOR_VERSION_KHR:
292 pack_data->attrib_list.context_minor_version = attrib[1];
294 case EGL_CONTEXT_FLAGS_KHR:
295 pack_data->attrib_list.context_flags = attrib[1];
297 case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
298 pack_data->attrib_list.context_opengl_profile_mask = attrib[1];
300 case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
301 pack_data->attrib_list.opengl_robust_access_ext = attrib[1];
303 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
304 pack_data->attrib_list.opengl_reset_notification_strategy_khr = attrib[1];
306 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
307 pack_data->attrib_list.opengl_reset_notification_strategy_ext = attrib[1];
310 COREGL_WARN("Invalid context attribute.");
316 // Eject condition for context version
317 if (pack_data->attrib_list.context_major_version != 2) {
318 pack_data->force_unique = force_unique_free_id;
329 _unpack_egl_context_option(EGL_packed_option *pack_data, EGLDisplay *dpy,
330 EGLConfig *cfg, EGLint *force_unique, EGLint *attrib_list,
331 const int attrib_list_size)
335 if (dpy != NULL) *dpy = pack_data->dpy;
336 if (cfg != NULL) *cfg = pack_data->cfg;
337 if (force_unique != NULL) *force_unique = pack_data->force_unique;
339 if (attrib_list != NULL && attrib_list_size > 0) {
340 int attrib_list_index = 0;
342 memset(attrib_list, 0x00, sizeof(int) * attrib_list_size);
344 if (pack_data->attrib_list.context_major_version != EGL_DONT_CARE) {
345 AST(attrib_list_index + 2 < attrib_list_size);
346 attrib_list[attrib_list_index] = EGL_CONTEXT_MAJOR_VERSION_KHR;
347 attrib_list[attrib_list_index + 1] =
348 pack_data->attrib_list.context_major_version;
349 attrib_list_index += 2;
351 if (pack_data->attrib_list.context_minor_version != EGL_DONT_CARE) {
352 AST(attrib_list_index + 2 < attrib_list_size);
353 attrib_list[attrib_list_index] = EGL_CONTEXT_MINOR_VERSION_KHR;
354 attrib_list[attrib_list_index + 1] =
355 pack_data->attrib_list.context_minor_version;
356 attrib_list_index += 2;
358 if (pack_data->attrib_list.context_flags != EGL_DONT_CARE) {
359 AST(attrib_list_index + 2 < attrib_list_size);
360 attrib_list[attrib_list_index] = EGL_CONTEXT_FLAGS_KHR;
361 attrib_list[attrib_list_index + 1] = pack_data->attrib_list.context_flags;
362 attrib_list_index += 2;
364 if (pack_data->attrib_list.context_opengl_profile_mask != EGL_DONT_CARE) {
365 AST(attrib_list_index + 2 < attrib_list_size);
366 attrib_list[attrib_list_index] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR;
367 attrib_list[attrib_list_index + 1] =
368 pack_data->attrib_list.context_opengl_profile_mask;
369 attrib_list_index += 2;
371 if (pack_data->attrib_list.opengl_robust_access_ext != EGL_DONT_CARE) {
372 AST(attrib_list_index + 2 < attrib_list_size);
373 attrib_list[attrib_list_index] =
374 EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT;
375 attrib_list[attrib_list_index + 1] =
376 pack_data->attrib_list.opengl_robust_access_ext;
377 attrib_list_index += 2;
379 if (pack_data->attrib_list.opengl_reset_notification_strategy_khr !=
381 AST(attrib_list_index + 2 < attrib_list_size);
382 attrib_list[attrib_list_index] =
383 EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR;
384 attrib_list[attrib_list_index + 1] =
385 pack_data->attrib_list.opengl_reset_notification_strategy_khr;
386 attrib_list_index += 2;
388 if (pack_data->attrib_list.opengl_reset_notification_strategy_ext !=
390 AST(attrib_list_index + 2 < attrib_list_size);
391 attrib_list[attrib_list_index] =
392 EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT;
393 attrib_list[attrib_list_index + 1] =
394 pack_data->attrib_list.opengl_reset_notification_strategy_ext;
395 attrib_list_index += 2;
398 attrib_list[attrib_list_index] = EGL_NONE;
408 _pack_egl_context_sharable_option(EGL_packed_sharable_option *pack_data,
409 EGLContext share_context)
413 pack_data->share_context = share_context;
424 _unpack_egl_context_sharable_option(EGL_packed_sharable_option *pack_data,
425 EGLContext *share_context)
429 if (share_context != NULL) *share_context = pack_data->share_context;
440 _link_context_state(GLGlueContext *gctx, GLContextState *cstate)
442 AST(gctx->cstate == NULL);
444 gctx->cstate = cstate;
448 _unlink_context_state(GLGlueContext *gctx, Mutex *ctx_list_mtx)
450 GLContextState *cstate = NULL;
452 cstate = gctx->cstate;
456 AST(cstate->ref_count >= 0);
458 if (cstate->ref_count == 0) {
459 MY_MODULE_TSTATE *tstate = NULL;
461 AST(cstate->data == NULL || cstate->data == initial_ctx);
463 #ifdef COREGL_FASTPATH_TRACE_CONTEXT_INFO
464 if (unlikely(get_trace_ctx_flag() == 1))
465 remove_from_general_trace_list(&context_state_trace_list, cstate);
466 #endif // COREGL_FASTPATH_TRACE_CONTEXT_INFO
468 AST(fastpath_remove_context_states_from_list(cstate, ctx_list_mtx) == 1);
470 GET_MY_TSTATE(tstate, get_current_thread_state());
471 if (tstate != NULL) {
472 if (tstate->cstate == cstate) {
473 _orig_fastpath_eglMakeCurrent(cstate->rdpy, tstate->rsurf_draw,
474 tstate->rsurf_read, EGL_NO_CONTEXT);
475 tstate->cstate = NULL;
478 _orig_fastpath_eglDestroyContext(cstate->rdpy, cstate->rctx);
485 _add_shared_obj_state_ref(GLGlueContext *gctx, GL_Shared_Object_State *sostate)
487 AST(sostate->ref_count >= 0);
488 sostate->ref_count++;
489 add_to_general_trace_list(&sostate->using_gctxs, gctx);
493 _remove_shared_obj_state_ref(GLGlueContext *gctx,
494 GL_Shared_Object_State *sostate)
496 remove_from_general_trace_list(&sostate->using_gctxs, gctx);
498 // Restore attached states
499 fastpath_release_gl_context(gctx);
501 AST(sostate->ref_count > 0);
502 sostate->ref_count--;
503 if (sostate->ref_count == 0) {
504 fastpath_sostate_deinit(sostate);
510 _add_context_ref(GLGlueContext *gctx)
512 if (gctx == initial_ctx) return;
514 AST(gctx->ref_count >= 0);
519 _remove_context_ref(GLGlueContext *gctx, Mutex *ctx_list_mtx)
521 if (gctx == initial_ctx) return;
523 AST(gctx->ref_count > 0);
525 if (gctx->ref_count == 0) {
526 #ifdef COREGL_FASTPATH_TRACE_CONTEXT_INFO
527 if (unlikely(get_trace_ctx_flag() == 1))
528 remove_from_general_trace_list(&glue_ctx_trace_list, gctx);
529 #endif // COREGL_FASTPATH_TRACE_CONTEXT_INFO
531 AST(gctx->cstate != NULL);
532 if (gctx->cstate->data == gctx)
533 gctx->cstate->data = NULL;
535 _unlink_context_state(gctx, ctx_list_mtx);
537 AST(gctx->ostate.shared != NULL);
538 _remove_shared_obj_state_ref(gctx, gctx->ostate.shared);
539 gctx->ostate.shared = NULL;
541 fastpath_ostate_deinit(&gctx->ostate);
543 if (gctx->real_ctx_option != NULL) {
544 free(gctx->real_ctx_option);
545 gctx->real_ctx_option = NULL;
547 if (gctx->real_ctx_sharable_option != NULL) {
548 free(gctx->real_ctx_sharable_option);
549 gctx->real_ctx_sharable_option = NULL;
552 # define GLUE_STATE(TYPE, NAME, SIZE, ARRAY_SIZE, DEFAULT_STMT, GET_STMT) \
553 if (gctx->NAME) {free(gctx->NAME); gctx->NAME = NULL;} \
554 if (gctx->NAME##_updated){free(gctx->NAME##_updated); gctx->NAME##_updated = NULL;}
555 # include "coregl_fastpath_state.h"
560 GLGlueContext_List *current = NULL;
562 AST(mutex_lock(&ctx_list_access_mutex) == 1);
566 while (current != NULL) {
567 if (current->gctx == gctx) {
568 if (current->next != NULL)
569 current->next->prev = current->prev;
571 if (current->prev != NULL)
572 current->prev->next = current->next;
574 gctx_list = current->next;
580 current = current->next;
583 AST(mutex_unlock(&ctx_list_access_mutex) == 1);
589 _bind_context_state(GLGlueContext *gctx, GLContextState *cstate,
593 AST(gctx->cstate == cstate);
596 if (cstate->data != gctx) {
597 GLGlueContext *curctx = (GLGlueContext *)cstate->data;
598 GLGlueContext *newctx = gctx;
601 newctx = initial_ctx;
604 curctx = initial_ctx;
609 if (!fastpath_make_context_current(curctx, newctx))
612 cstate->data = (void *)newctx;
613 _remove_context_ref(curctx, ctx_list_mtx);
614 _add_context_ref(newctx);
622 _egl_create_context(EGL_packed_option *real_ctx_option,
623 GLContextState **cstate_new, EGLContext *ctx,
624 EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
626 GLContextState *cstate = NULL;
628 AST(real_ctx_option != NULL);
629 AST(cstate_new != NULL);
632 // Pack context option
633 AST(_pack_egl_context_option(real_ctx_option, dpy, config, 0,
636 if (debug_nofp == 1) {
637 AST(_pack_egl_context_option(real_ctx_option, dpy, config, 1,
641 // Find context state
642 if (real_ctx_option->force_unique == 0) {
643 cstate = fastpath_get_context_state_from_list(real_ctx_option,
644 sizeof(EGL_packed_option), &ctx_list_access_mutex);
647 // Create a real context if it hasn't been created
648 if (cstate == NULL) {
649 EGLContext *real_share_context = EGL_NO_CONTEXT;
651 AST(mutex_lock(&ctx_list_access_mutex) == 1);
653 GLContext_List *current = NULL;
655 current = glctx_list;
656 while (current != NULL) {
657 EGLDisplay cur_dpy = EGL_NO_DISPLAY;
659 _unpack_egl_context_option(current->option, &cur_dpy, NULL, NULL, attribs, 15);
660 if (cur_dpy == dpy) {
661 if (attribs[0] == EGL_CONTEXT_MAJOR_VERSION_KHR &&
662 attribs[1] != real_ctx_option->attrib_list.context_major_version) {
663 current = current->next;
667 AST(current->cstate != NULL);
668 real_share_context = current->cstate->rctx;
671 current = current->next;
674 AST(mutex_unlock(&ctx_list_access_mutex) == 1);
676 *ctx = _orig_fastpath_eglCreateContext(dpy, config, real_share_context,
679 if (*ctx == EGL_NO_CONTEXT) {
680 COREGL_WARN("Failed creating a egl real context for Fastpath. (Invalid config?)");
684 *cstate_new = (GLContextState *)calloc(1, sizeof(GLContextState));
685 if (*cstate_new == NULL) {
686 COREGL_ERR("Error creating a new context state. (Memory full)");
689 (*cstate_new)->rctx = *ctx;
690 (*cstate_new)->rdpy = dpy;
691 (*cstate_new)->data = NULL;
693 AST(fastpath_add_context_state_to_list(real_ctx_option,
694 sizeof(EGL_packed_option), *cstate_new, &ctx_list_access_mutex) == 1);
696 #ifdef COREGL_FASTPATH_TRACE_CONTEXT_INFO
697 if (unlikely(get_trace_ctx_flag() == 1))
698 add_to_general_trace_list(&context_state_trace_list, *cstate_new);
699 #endif // COREGL_FASTPATH_TRACE_CONTEXT_INFO
701 cstate = *cstate_new;
710 #define ATTRIB_LIST_BUFFER_SIZE 8
713 fastpath_create_context(GLGlueContext *gctx)
715 GLContextState *cstate_new = NULL;
716 EGLContext new_real_ctx = EGL_NO_CONTEXT;
717 EGLDisplay dpy = EGL_NO_DISPLAY;
718 EGLConfig config = NULL;
719 int attrib_list[ATTRIB_LIST_BUFFER_SIZE];
722 AST(_unpack_egl_context_option(gctx->real_ctx_option, &dpy, &config, NULL,
723 attrib_list, ATTRIB_LIST_BUFFER_SIZE) == 1);
724 AST(dpy == gctx->rdpy);
726 _egl_create_context(gctx->real_ctx_option, &cstate_new, &new_real_ctx, dpy,
727 config, attrib_list);
729 AST(cstate_new != NULL);
731 if (_bind_context_state(gctx, cstate_new, &ctx_list_access_mutex) != 1) {
732 COREGL_WARN("Error soft-makecurrent in Cross-thread usage!");
734 _orig_fastpath_eglDestroyContext(dpy, new_real_ctx);
739 /* TODO : Setup context state for new real ctx */
740 COREGL_WARN("Cross-thread usage(makecurrent) can cause a state-broken situation!");
742 _unlink_context_state(gctx, &ctx_list_access_mutex);
743 _link_context_state(gctx, cstate_new);
745 /* Apply to new thread */
746 gctx->thread_id = get_current_thread();
752 fastpath_init_viewport_and_scissor(GLGlueContext *gctx)
754 EGLint box_buffer[4];
758 _orig_fastpath_glGetIntegerv(GL_VIEWPORT, box_buffer);
759 width = box_buffer[2];
760 height = box_buffer[3];
762 gctx->_clear_flag1 |= _CLEAR_FLAG1_BIT_gl_viewport;
763 if (&gctx->gl_viewport[0]) gctx->gl_viewport[0] = 0;
764 if (&gctx->gl_viewport[1]) gctx->gl_viewport[1] = 0;
765 if (&gctx->gl_viewport[2]) gctx->gl_viewport[2] = width;
766 if (&gctx->gl_viewport[3]) gctx->gl_viewport[3] = height;
768 _orig_fastpath_glGetIntegerv(GL_SCISSOR_BOX, box_buffer);
769 width = box_buffer[2];
770 height = box_buffer[3];
772 gctx->_misc_flag2 |= _MISC_FLAG2_BIT_gl_scissor_box;
773 if (&gctx->gl_scissor_box[0]) gctx->gl_scissor_box[0] = 0;
774 if (&gctx->gl_scissor_box[1]) gctx->gl_scissor_box[1] = 0;
775 if (&gctx->gl_scissor_box[2]) gctx->gl_scissor_box[2] = width;
776 if (&gctx->gl_scissor_box[3]) gctx->gl_scissor_box[3] = height;
778 gctx->surface_attached = 1;
782 fastpath_update_context(GLGlueContext *gctx, MY_MODULE_TSTATE *tstate,
783 EGLDisplay dpy, EGLSurface draw, EGLSurface read, int *api_version)
787 AST(dpy == gctx->cstate->rdpy);
789 /* BB : full makecurrent */
790 if (_orig_fastpath_eglMakeCurrent(dpy, draw, read, gctx->cstate->rctx) != EGL_TRUE) {
791 COREGL_WARN("Error making context current with the drawable. (Bad match?)");
796 *api_version = ((EGL_packed_option *)
797 gctx->real_ctx_option)->attrib_list.context_major_version;
799 /* Change overriding for modules according to new API version */
800 if (USE_TRACEPATH || (fp_opt == FP_FAST_PATH)) {
801 if (!current_gl_api_version) {
802 current_gl_api_version = *api_version;
803 if (current_gl_api_version == COREGL_GLAPI_1) {
804 init_export(GL_FALSE, GL_TRUE);
805 COREGL_DBG("Default API path reseted...");
808 if (current_gl_api_version != *api_version) {
809 /* API version becomes 1.x from higher */
810 if (*api_version == COREGL_GLAPI_1) {
811 init_export(GL_FALSE, GL_TRUE);
812 COREGL_DBG("Default API path reseted...");
815 /* API version becomes higher from 1.x */
816 if (current_gl_api_version == COREGL_GLAPI_1) {
820 current_gl_api_version = *api_version;
825 /* Update references only when the contexts are different */
826 if (tstate->cstate != gctx->cstate) {
827 if (tstate->cstate != NULL && tstate->cstate->data != NULL) {
828 _remove_context_ref((GLGlueContext *)tstate->cstate->data,
829 &ctx_list_access_mutex);
832 tstate->cstate = gctx->cstate;
834 if (tstate->cstate->data != NULL) {
835 _add_context_ref((GLGlueContext *)tstate->cstate->data);
839 tstate->rsurf_draw = draw;
840 tstate->rsurf_read = read;
845 extern EGLBoolean (*ovr_eglBindAPI)(EGLenum api);
846 extern EGLenum (*ovr_eglQueryAPI)(void);
849 fastpath_eglBindAPI(EGLenum api)
851 EGLBoolean ret = EGL_FALSE;
852 MY_MODULE_TSTATE *tstate = NULL;
854 _COREGL_FASTPATH_FUNC_BEGIN();
855 if (fp_opt == FP_UNKNOWN_PATH) {
856 COREGL_ERR("Invalid library link! (CoreGL path option is invalid)");
860 ret = _orig_fastpath_eglBindAPI(api);
862 GET_MY_TSTATE(tstate, get_current_thread_state());
863 if (tstate == NULL) {
864 AST(init_new_thread_state() == 1);
866 GET_MY_TSTATE(tstate, get_current_thread_state());
871 EGLenum newapi = _orig_fastpath_eglQueryAPI();
872 if (tstate && (tstate->binded_api != EGL_OPENGL_ES_API)) {
873 tstate->binded_api = newapi;
880 _COREGL_FASTPATH_FUNC_END();
885 fastpath_eglQueryAPI(void)
888 MY_MODULE_TSTATE *tstate = NULL;
890 _COREGL_FASTPATH_FUNC_BEGIN();
891 if (fp_opt == FP_UNKNOWN_PATH) {
892 COREGL_ERR("Invalid library link! (CoreGL path option is invalid)");
896 ret = _orig_fastpath_eglQueryAPI();
898 GET_MY_TSTATE(tstate, get_current_thread_state());
899 if (tstate != NULL) {
900 AST(tstate->binded_api == ret);
906 _COREGL_FASTPATH_FUNC_END();
911 fastpath_eglCreateContext(EGLDisplay dpy, EGLConfig config,
912 EGLContext share_context, const EGLint *attrib_list)
914 GLGlueContext *gctx = NULL, *newgctx = NULL;
915 GLGlueContext_List *gctx_list_new = NULL;
916 MY_MODULE_TSTATE *tstate = NULL;
917 GLContextState *cstate = NULL;
918 GLContextState *cstate_new = NULL;
919 GL_Shared_Object_State *sostate_new = NULL;
920 GLContext ctx = NULL;
922 EGL_packed_option *real_ctx_option = NULL;
923 EGL_packed_sharable_option *real_ctx_sharable_option = NULL;
925 // Special eject condition for binding API
926 GET_MY_TSTATE(tstate, get_current_thread_state());
927 if (tstate != NULL && tstate->binded_api != EGL_OPENGL_ES_API) {
928 return _orig_fastpath_eglCreateContext(dpy, config, share_context, attrib_list);
931 _COREGL_FASTPATH_FUNC_BEGIN();
933 real_ctx_option = (EGL_packed_option *)calloc(1, sizeof(EGL_packed_option));
934 if (real_ctx_option == NULL) {
935 COREGL_ERR("Error creating a new GLGlueContext(Memory full 1)");
938 cstate = _egl_create_context(real_ctx_option, &cstate_new, &ctx, dpy, config,
943 // Pack shared context options
944 real_ctx_sharable_option = (EGL_packed_sharable_option *)calloc(1,
945 sizeof(EGL_packed_sharable_option));
946 if (real_ctx_sharable_option == NULL) {
947 COREGL_ERR("Error creating a new GLGlueContext(Memory full 2)");
950 AST(_pack_egl_context_sharable_option(real_ctx_sharable_option,
951 share_context) == 1);
953 // Allocate a new context
954 newgctx = (GLGlueContext *)calloc(1, sizeof(GLGlueContext));
955 if (newgctx == NULL) {
956 COREGL_ERR("Error creating a new GLGlueContext(Memory full 3)");
960 newgctx->magic = MAGIC_GLFAST;
961 newgctx->initialized = 0;
963 newgctx->thread_id = get_current_thread();
965 fastpath_ostate_init(&newgctx->ostate);
967 if (share_context != EGL_NO_CONTEXT) {
968 GLGlueContext *shared_gctx = (GLGlueContext *)share_context;
969 AST(shared_gctx->magic == MAGIC_GLFAST);
970 AST(shared_gctx->ostate.shared != NULL);
971 newgctx->ostate.shared = shared_gctx->ostate.shared;
973 sostate_new = (GL_Shared_Object_State *)calloc(1,
974 sizeof(GL_Shared_Object_State));
975 if (sostate_new == NULL) {
976 COREGL_ERR("Error creating a new GLGlueContext(Memory full 4)");
979 fastpath_sostate_init(sostate_new);
980 newgctx->ostate.shared = sostate_new;
982 _add_shared_obj_state_ref(newgctx, newgctx->ostate.shared);
983 newgctx->real_ctx_option = real_ctx_option;
984 newgctx->real_ctx_option_len = sizeof(EGL_packed_option);
985 newgctx->real_ctx_sharable_option = real_ctx_sharable_option;
986 newgctx->real_ctx_sharable_option_len = sizeof(EGL_packed_sharable_option);
988 _link_context_state(newgctx, cstate);
989 _add_context_ref(newgctx);
991 newgctx->cstate = cstate;
994 // Add glue context to list
995 gctx_list_new = (GLGlueContext_List *)calloc(1, sizeof(GLGlueContext_List));
996 if (gctx_list_new == NULL) {
997 COREGL_ERR("Error creating a new GlGlueContext(Memory full 5)");
1001 AST(mutex_lock(&ctx_list_access_mutex) == 1);
1003 gctx_list_new->gctx = newgctx;
1005 gctx_list_new->prev = NULL;
1006 gctx_list_new->next = gctx_list;
1007 if (gctx_list != NULL)
1008 gctx_list->prev = gctx_list_new;
1010 gctx_list = gctx_list_new;
1012 AST(mutex_unlock(&ctx_list_access_mutex) == 1);
1017 #ifdef COREGL_FASTPATH_TRACE_CONTEXT_INFO
1018 if (unlikely(get_trace_ctx_flag() == 1)) {
1020 add_to_general_trace_list(&glue_ctx_trace_list, newgctx);
1022 snprintf(ment, sizeof(ment), "eglCreateContext completed (GlueCTX=[%12p])",
1024 _dump_context_info(ment, 1);
1026 #endif // COREGL_FASTPATH_TRACE_CONTEXT_INFO
1033 _orig_fastpath_eglDestroyContext(dpy, ctx);
1036 if (sostate_new != NULL) {
1040 if (real_ctx_option != NULL) {
1041 free(real_ctx_option);
1042 real_ctx_option = NULL;
1044 if (real_ctx_sharable_option != NULL) {
1045 free(real_ctx_sharable_option);
1046 real_ctx_sharable_option = NULL;
1048 if (cstate_new != NULL) {
1049 #ifdef COREGL_FASTPATH_TRACE_CONTEXT_INFO
1050 if (unlikely(get_trace_ctx_flag() == 1))
1051 remove_from_general_trace_list(&context_state_trace_list, cstate_new);
1052 #endif // COREGL_FASTPATH_TRACE_CONTEXT_INFO
1054 fastpath_remove_context_states_from_list(cstate_new, &ctx_list_access_mutex);
1058 if (gctx_list_new != NULL) {
1059 AST(mutex_lock(&ctx_list_access_mutex) == 1);
1061 if (gctx_list_new->next != NULL)
1062 gctx_list_new->next->prev = gctx_list_new->prev;
1064 if (gctx_list_new->prev != NULL)
1065 gctx_list_new->prev->next = gctx_list_new->next;
1067 gctx_list = gctx_list_new->next;
1069 AST(mutex_unlock(&ctx_list_access_mutex) == 1);
1071 free(gctx_list_new);
1073 if (newgctx != NULL) {
1074 _remove_context_ref(newgctx, &ctx_list_access_mutex);
1079 _COREGL_FASTPATH_FUNC_END();
1081 return (EGLContext)gctx;
1085 fastpath_eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1087 EGLBoolean ret = EGL_FALSE;
1088 GLGlueContext *gctx = NULL;
1090 _COREGL_FASTPATH_FUNC_BEGIN();
1092 gctx = (GLGlueContext *)ctx;
1094 if (gctx != NULL && gctx != EGL_NO_CONTEXT) {
1095 GLContextState *cstate = NULL;
1097 if (gctx->magic != MAGIC_GLFAST) {
1098 ret = _orig_fastpath_eglDestroyContext(dpy, ctx);
1102 cstate = gctx->cstate;
1103 AST(cstate != NULL);
1105 if (gctx->is_destroyed != 1) {
1106 gctx->is_destroyed = 1;
1107 _remove_context_ref(gctx, &ctx_list_access_mutex);
1110 COREGL_WARN("Invalid destroying context. (no exists)");
1119 _COREGL_FASTPATH_FUNC_END();
1121 #ifdef COREGL_FASTPATH_TRACE_CONTEXT_INFO
1122 if (unlikely(get_trace_ctx_flag() == 1)) {
1124 snprintf(ment, sizeof(ment), "eglDestroyContext completed (GlueCTX=[%12p])",
1126 _dump_context_info(ment, 1);
1128 #endif // COREGL_FASTPATH_TRACE_CONTEXT_INFO
1134 fastpath_eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute,
1137 EGLBoolean ret = EGL_FALSE;
1138 EGLContext real_ctx = EGL_NO_CONTEXT;
1140 _COREGL_FASTPATH_FUNC_BEGIN();
1142 if (ctx != EGL_NO_CONTEXT) {
1143 GLGlueContext *gctx = NULL;
1144 gctx = (GLGlueContext *)ctx;
1146 if (gctx->magic != MAGIC_GLFAST) {
1149 AST(gctx->cstate != NULL);
1150 real_ctx = gctx->cstate->rctx;
1154 ret = _orig_fastpath_eglQueryContext(dpy, real_ctx, attribute, value);
1158 _COREGL_FASTPATH_FUNC_END();
1165 fastpath_eglReleaseThread(void)
1167 EGLBoolean ret = EGL_FALSE;
1168 EGLDisplay dpy = EGL_NO_DISPLAY;
1169 MY_MODULE_TSTATE *tstate = NULL;
1171 GET_MY_TSTATE(tstate, get_current_thread_state());
1173 // Special eject condition for binding API
1174 if (tstate != NULL && tstate->binded_api != EGL_OPENGL_ES_API) {
1175 return _orig_fastpath_eglReleaseThread();
1178 _COREGL_FASTPATH_FUNC_BEGIN();
1180 dpy = _orig_fastpath_eglGetCurrentDisplay();
1182 /* according to spec,
1183 * Even if EGL is not initialized on any EGLDisplay, eglReleaseThread should succeed
1185 if (dpy != EGL_NO_DISPLAY)
1186 fastpath_eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
1187 ret = _orig_fastpath_eglReleaseThread();
1191 _COREGL_FASTPATH_FUNC_END();
1196 fastpath_eglGetCurrentDisplay(void)
1198 MY_MODULE_TSTATE *tstate = NULL;
1199 EGLDisplay dpy = EGL_NO_DISPLAY;
1201 GET_MY_TSTATE(tstate, get_current_thread_state());
1203 if (tstate != NULL) {
1204 // Special eject condition for binding API
1205 if (tstate->binded_api != EGL_OPENGL_ES_API) {
1206 return _orig_fastpath_eglGetCurrentDisplay();
1209 _COREGL_FASTPATH_FUNC_BEGIN();
1211 if (tstate->cstate != NULL) {
1212 dpy = tstate->cstate->rdpy;
1216 _COREGL_FASTPATH_FUNC_END();
1228 fastpath_eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
1230 EGLBoolean ret = EGL_FALSE;
1231 EGLBoolean need_mc = EGL_FALSE;
1232 GLGlueContext *gctx = (GLGlueContext *)ctx;
1235 MY_MODULE_TSTATE *tstate = NULL;
1237 GET_MY_TSTATE(tstate, get_current_thread_state());
1239 /* Special eject condition for binding API */
1240 if (tstate != NULL && tstate->binded_api != EGL_OPENGL_ES_API) {
1241 return _orig_fastpath_eglMakeCurrent(dpy, draw, read, ctx);
1244 _COREGL_FASTPATH_FUNC_BEGIN();
1246 if (tstate == NULL) {
1247 AST(init_new_thread_state() == 1);
1248 GET_MY_TSTATE(tstate, get_current_thread_state());
1249 AST(tstate != NULL);
1252 /* Special path for context deletion */
1253 if (ctx == EGL_NO_CONTEXT && tstate) {
1254 if (tstate->cstate != NULL) {
1255 if (_bind_context_state(NULL, tstate->cstate, &ctx_list_access_mutex) != 1) {
1256 COREGL_WARN("Error soft-makecurrent for context deletion");
1258 tstate->cstate = NULL;
1261 if (_orig_fastpath_eglMakeCurrent(dpy, draw, read, ctx) != EGL_TRUE) {
1262 COREGL_WARN("Error making context [%p] current. (invalid EGL display [%p] or EGL surface [D:%p/R:%p])",
1263 ctx, dpy, draw, read);
1268 tstate->rsurf_draw = draw;
1269 tstate->rsurf_read = read;
1275 AST(gctx && gctx->cstate && gctx->real_ctx_option && gctx->real_ctx_sharable_option);
1277 if (gctx && (gctx->rdpy != dpy)) {
1278 COREGL_WARN("Invalid context (or invalid EGL display)");
1283 /* Handle cross threading of context (when used by two or more gctx) */
1284 if (gctx && gctx->thread_id != get_current_thread() && gctx->cstate->ref_count > 1) {
1285 if(fastpath_create_context(gctx) == EGL_FALSE)
1289 /* Check if the object is correct */
1290 if (gctx && (gctx->magic != MAGIC_GLFAST)) {
1291 COREGL_ERR("Glue-CTX Magic Check Failed!!! (Memory broken?)");
1296 /* If drawable changed, do a make current */
1297 if (tstate && (tstate->rsurf_draw != draw || tstate->rsurf_read != read)) {
1301 AST(gctx && (gctx->cstate != NULL));
1303 /* If binded real context changed, do a make current */
1304 if (tstate && gctx && (tstate->cstate == NULL || tstate->cstate != gctx->cstate)) {
1308 if (tstate && gctx && gctx->cstate && (need_mc == EGL_TRUE)) {
1309 fastpath_update_context(gctx, tstate, dpy, draw, read, &api_version);
1312 /* Initialize context states */
1313 if (gctx && (gctx->initialized == 0)) {
1314 if (fastpath_init_context_states(gctx) != 1) {
1315 COREGL_ERR("Error intializing context. (Check driver specification)");
1320 /* Setup initial Viewport & Scissor */
1321 if (gctx && gctx->surface_attached == 0 && draw != EGL_NO_SURFACE) {
1322 fastpath_init_viewport_and_scissor(gctx);
1325 if (tstate && tstate->cstate &&
1326 (_bind_context_state(gctx, tstate->cstate, &ctx_list_access_mutex) != 1)) {
1339 _COREGL_FASTPATH_FUNC_END();
1341 #ifdef COREGL_FASTPATH_TRACE_CONTEXT_INFO
1342 if (unlikely(get_trace_ctx_flag() == 1)) {
1344 snprintf(ment, sizeof(ment), "eglMakeCurrent finished (GlueCTX=[%12p] Surf=[D:%12p R:%12p])",
1346 _dump_context_info(ment, 0);
1354 fastpath_eglGetCurrentContext(void)
1356 GLGlueContext *ret = NULL;
1357 MY_MODULE_TSTATE *tstate = NULL;
1359 GET_MY_TSTATE(tstate, get_current_thread_state());
1361 // Special eject condition for binding API
1362 if (tstate != NULL && tstate->binded_api != EGL_OPENGL_ES_API) {
1363 return _orig_fastpath_eglGetCurrentContext();
1366 _COREGL_FASTPATH_FUNC_BEGIN();
1368 if (tstate != NULL) {
1369 if (tstate->cstate != NULL) {
1370 ret = (GLGlueContext *)tstate->cstate->data;
1371 AST(ret->magic == MAGIC_GLFAST);
1377 _COREGL_FASTPATH_FUNC_END();
1378 return (EGLContext)ret;
1383 fastpath_eglGetCurrentSurface(EGLint readdraw)
1385 EGLSurface ret = EGL_NO_SURFACE;
1386 MY_MODULE_TSTATE *tstate = NULL;
1388 GET_MY_TSTATE(tstate, get_current_thread_state());
1390 // Special eject condition for binding API
1391 if (tstate != NULL && tstate->binded_api != EGL_OPENGL_ES_API) {
1392 return _orig_fastpath_eglGetCurrentSurface(readdraw);
1395 _COREGL_FASTPATH_FUNC_BEGIN();
1397 if (tstate != NULL) {
1400 ret = (GLGlueContext *)tstate->rsurf_draw;
1403 ret = (GLGlueContext *)tstate->rsurf_read;
1410 _COREGL_FASTPATH_FUNC_END();
1415 fastpath_eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target,
1416 EGLClientBuffer buffer, const EGLint *attrib_list)
1419 EGLContext real_ctx = EGL_NO_CONTEXT;
1420 EGLClientBuffer real_obj = NULL;
1421 GL_Object_Type type = 0;
1423 if (current_gl_api_version == COREGL_GLAPI_1) {
1424 ret = _orig_fastpath_eglCreateImageKHR(dpy, real_ctx, target, buffer,
1429 if ((EGLint)buffer & GL_OBJECT_TYPE_TEXTURE)
1430 type = GL_OBJECT_TYPE_TEXTURE;
1431 else if ((EGLint)buffer & GL_OBJECT_TYPE_RENDERBUFFER)
1432 type = GL_OBJECT_TYPE_RENDERBUFFER;
1434 ret = _orig_fastpath_eglCreateImageKHR(dpy, real_ctx, target, buffer,
1439 _COREGL_FASTPATH_FUNC_BEGIN();
1441 if (ctx != NULL && ctx != EGL_NO_CONTEXT) {
1442 GLGlueContext *gctx = (GLGlueContext *)ctx;
1444 if (gctx->magic != MAGIC_GLFAST) {
1447 AST(gctx->cstate != NULL);
1448 real_ctx = gctx->cstate->rctx;
1452 case EGL_GL_TEXTURE_2D_KHR:
1453 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
1454 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
1455 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
1456 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
1457 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
1458 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
1459 case EGL_GL_TEXTURE_3D_KHR:
1460 case EGL_GL_RENDERBUFFER_KHR:
1461 real_obj = (EGLClientBuffer)(uintptr_t)fastpath_ostate_get_object(&gctx->ostate,
1462 type, (GLuint)(uintptr_t)buffer);
1465 COREGL_ERR("Error Not supported target NULL client buffer");
1473 ret = _orig_fastpath_eglCreateImageKHR(dpy, real_ctx, target, real_obj,
1480 _COREGL_FASTPATH_FUNC_END();
1485 fastpath_eglGetProcAddress(const char *procname)
1489 _COREGL_FASTPATH_FUNC_BEGIN();
1491 #define _COREGL_SYMBOL(RET_TYPE, FUNC_NAME, PARAM_LIST) \
1492 if (strcmp(procname, #FUNC_NAME) == 0) \
1494 _eng_fn ret_orig = NULL; \
1495 ret_orig = _orig_fastpath_eglGetProcAddress(procname); \
1496 if (ret_orig != NULL) \
1497 ret = (_eng_fn)ovr_##FUNC_NAME; \
1501 #define _COREGL_EXT_SYMBOL_ALIAS(ALIAS_NAME, FUNC_NAME) \
1502 if (strcmp(procname, #ALIAS_NAME) == 0) \
1504 _eng_fn ret_orig = NULL; \
1505 ret_orig = _orig_fastpath_eglGetProcAddress(#ALIAS_NAME); \
1506 if (ret_orig != NULL) \
1507 ret = (_eng_fn)ovr_##FUNC_NAME; \
1511 #include "../headers/sym_egl.h"
1512 #include "../headers/sym_gl1.h"
1513 #include "../headers/sym_gl2.h"
1514 #include "../headers/sym_gl_common.h"
1515 #undef _COREGL_SYMBOL
1516 #undef _COREGL_EXT_SYMBOL_ALIAS
1518 ret = _orig_fastpath_eglGetProcAddress(procname);
1521 #define _COREGL_EXT_SYMBOL_FASTPATH_PASS(FUNC_NAME) \
1522 if (strcmp(procname, #FUNC_NAME) == 0) \
1525 #define _COREGL_EXT_SYMBOL_FASTPATH_BLOCK(FUNC_NAME) \
1526 if (strcmp(procname, #FUNC_NAME) == 0) \
1532 #include "../headers/sym_egl.h"
1533 #include "../headers/sym_gl1.h"
1534 #include "../headers/sym_gl2.h"
1535 #include "../headers/sym_gl_common.h"
1537 #undef _COREGL_EXT_SYMBOL_FASTPATH_PASS
1538 #undef _COREGL_EXT_SYMBOL_FASTPATH_BLOCK
1540 COREGL_ERR("FASTPATH can't support '%s' (will be terminated with Illegal instruction!)",
1548 _COREGL_FASTPATH_FUNC_END();
1553 fastpath_eglTerminate(EGLDisplay dpy)
1555 EGLBoolean ret = EGL_FALSE;
1556 GLGlueContext_List *current = NULL;
1557 GLGlueContext_List *remove_list = NULL;
1559 _COREGL_FASTPATH_FUNC_BEGIN();
1561 AST(mutex_lock(&ctx_list_access_mutex) == 1);
1562 current = gctx_list;
1563 while (current != NULL) {
1564 if (current->gctx->cstate->rdpy == dpy) {
1565 GLGlueContext_List *rm_newitm = NULL;
1566 rm_newitm = (GLGlueContext_List *)calloc(1, sizeof(GLGlueContext_List));
1568 if (rm_newitm == NULL) {
1573 rm_newitm->gctx = current->gctx;
1575 rm_newitm->next = remove_list;
1576 remove_list = rm_newitm;
1578 current = current->next;
1580 AST(mutex_unlock(&ctx_list_access_mutex) == 1);
1582 current = remove_list;
1583 while (current != NULL) {
1584 fastpath_eglDestroyContext(dpy, current->gctx);
1585 remove_list = current->next;
1587 current = remove_list;
1590 ret = _orig_fastpath_eglTerminate(dpy);
1594 _COREGL_FASTPATH_FUNC_END();