[Title] Added defensive codes against unusual usages in memory tracing
[platform/core/uifw/coregl.git] / src / modules / fastpath / coregl_fastpath.c
1 #include "coregl_fastpath.h"
2
3 #include <stdlib.h>
4 #include <string.h>
5 #include <sys/time.h>
6
7 #include <sys/types.h>
8 #include <unistd.h>
9
10 #define _COREGL_SYMBOL(IS_EXTENSION, RET_TYPE, FUNC_NAME, PARAM_LIST)     RET_TYPE (*_orig_fastpath_##FUNC_NAME) PARAM_LIST = NULL;
11 #include "../../headers/sym.h"
12 #undef _COREGL_SYMBOL
13
14 Fastpath_Opt_Flag   fp_opt = FP_UNKNOWN_PATH;
15
16 int                 debug_nofp = 0;
17 FILE               *trace_fp = NULL;
18
19 GLenum              FPGL_Error = GL_NO_ERROR;
20
21 GLGlueContext_List *gctx_list = NULL;
22
23 Mutex               init_context_mutex = MUTEX_INITIALIZER;
24 GLGlueContext      *initial_ctx = NULL;
25
26 Mutex               ctx_list_access_mutex = MUTEX_INITIALIZER;
27
28 GLContext_List     *glctx_list = NULL;
29
30 static void
31 _get_texture_states(GLenum pname, GLint *params)
32 {
33         GLuint cur_active_tex = 0;
34
35         AST(initial_ctx != NULL);
36
37         _sym_glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint *)&cur_active_tex);
38         int i;
39         for (i = 0; i < initial_ctx->gl_num_tex_units[0]; i++)
40         {
41                 _sym_glActiveTexture(GL_TEXTURE0 + i);
42                 _sym_glGetIntegerv(pname, &(((GLint *)params)[i]));
43         }
44         _sym_glActiveTexture(cur_active_tex);
45 }
46
47 static GLuint
48 _get_stencil_max_mask()
49 {
50         GLuint stencil_bit = 0;
51
52         _sym_glGetIntegerv(GL_STENCIL_BITS, (GLint *)&stencil_bit);
53         return (1 << stencil_bit) - 1;
54 }
55
56 void
57 init_modules_fastpath()
58 {
59         int fastpath_opt = 0;
60         int fastpath_force_off_opt = 0;
61
62         LOG("[CoreGL] <Fastpath> : ");
63
64         fastpath_opt = atoi(get_env_setting("COREGL_FASTPATH"));
65         fastpath_force_off_opt = atoi(get_env_setting("COREGL_FASTPATH_FORCE_OFF"));
66
67         if (fastpath_force_off_opt == 1)
68         {
69                 LOG("\E[0;31;1m(DISABLED by force option)\E[0m ");
70                 fastpath_opt = 0;
71         }
72
73         switch (fastpath_opt)
74         {
75                 case 1:
76                         LOG("(%d) Fastpath enabled...\n", fastpath_opt);
77                         fp_opt = FP_FAST_PATH;
78                         break;
79                 default:
80                         LOG("(%d) Default API path enabled...\n", fastpath_opt);
81                         fp_opt = FP_NORMAL_PATH;
82                         break;
83         }
84
85         debug_nofp = atoi(get_env_setting("COREGL_DEBUG_NOFP"));
86
87         fastpath_apply_overrides();
88
89 }
90
91 void
92 deinit_modules_fastpath()
93 {
94         GLContext_List *current = NULL;
95
96         AST(mutex_lock(&ctx_list_access_mutex) == 1);
97
98         // Destroy remained context & Detect leaks
99         int retry_destroy = 0;
100
101         while (1)
102         {
103                 retry_destroy = 0;
104                 current = glctx_list;
105                 while (current)
106                 {
107                         if (current->cstate != NULL)
108                         {
109                                 ERR("\E[0;31;1mWARNING : Context attached to [dpy=%p|rctx=%p] has not been completely destroyed.(leak)\E[0m\n", current->cstate->rdpy, current->cstate->rctx);
110
111                                 _sym_eglMakeCurrent(current->cstate->rdpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
112                                 _sym_eglDestroyContext(current->cstate->rdpy, current->cstate->rctx);
113
114                                 fastpath_remove_context_states_from_list(current->cstate, NULL);
115                                 retry_destroy = 1;
116                                 break;
117                         }
118
119                         glctx_list = current->next;
120                         free(current);
121                         current = glctx_list;
122                 }
123                 if (retry_destroy == 0) break;
124         }
125         goto finish;
126
127 finish:
128         AST(mutex_unlock(&ctx_list_access_mutex) == 1);
129 }
130
131 void
132 init_modules_tstate_fastpath(GLThreadState *tstate)
133 {
134         MY_MODULE_TSTATE *tstate_mt = NULL;
135
136         tstate_mt = (MY_MODULE_TSTATE *)calloc(1, sizeof(MY_MODULE_TSTATE));
137
138         tstate_mt->binded_api = EGL_OPENGL_ES_API;
139
140         tstate->module_data[MY_MODULE_ID] = tstate_mt;
141 }
142
143 void
144 deinit_modules_tstate_fastpath(GLThreadState *tstate)
145 {
146         if (tstate->module_data[MY_MODULE_ID] != NULL)
147         {
148                 free(tstate->module_data[MY_MODULE_ID]);
149                 tstate->module_data[MY_MODULE_ID] = NULL;
150         }
151 }
152
153 void
154 fastpath_apply_overrides()
155 {
156         switch(fp_opt)
157         {
158                 case FP_FAST_PATH:
159                         fastpath_apply_overrides_egl(1);
160                         fastpath_apply_overrides_gl(1);
161                         break;
162                 case FP_NORMAL_PATH:
163                         break;
164                 default:
165                         ERR("Invalide GL Override Option!!!\n");
166                         break;
167         }
168 }
169
170 #define OVERRIDE(f) \
171         if (enable == 1) \
172         { \
173                 COREGL_OVERRIDE_API(_orig_fastpath_, f, ovr_); \
174                 COREGL_OVERRIDE_API(ovr_, f, fastpath_); \
175         } \
176         else \
177         { \
178                 AST(ovr_##f != NULL); \
179                 COREGL_OVERRIDE_API(ovr_, f, _orig_fastpath_); \
180                 _orig_fastpath_##f = NULL; \
181         }
182
183 void
184 fastpath_apply_overrides_egl(int enable)
185 {
186         // Fast-Path Core Functions
187         OVERRIDE(eglGetProcAddress);
188
189         OVERRIDE(eglBindAPI);
190         OVERRIDE(eglQueryAPI);
191
192         OVERRIDE(eglCreateContext);
193         OVERRIDE(eglCreateImageKHR);
194         OVERRIDE(eglMakeCurrent);
195         OVERRIDE(eglDestroyContext);
196         OVERRIDE(eglQueryContext);
197         OVERRIDE(eglGetCurrentContext);
198         OVERRIDE(eglReleaseThread);
199         OVERRIDE(eglGetCurrentSurface);
200         OVERRIDE(eglTerminate);
201
202 }
203
204 void
205 fastpath_apply_overrides_gl(int enable)
206 {
207         // Fast-Path Functions
208         if (debug_nofp != 1)
209         {
210                 OVERRIDE(glGetError);
211
212                 OVERRIDE(glGetIntegerv);
213                 OVERRIDE(glGetFloatv);
214                 OVERRIDE(glGetBooleanv);
215
216                 OVERRIDE(glActiveTexture);
217                 OVERRIDE(glGenTextures);
218                 OVERRIDE(glBindTexture);
219                 OVERRIDE(glIsTexture);
220                 OVERRIDE(glDeleteTextures);
221                 OVERRIDE(glFramebufferTexture2D);
222                 OVERRIDE(glFramebufferTexture2DMultisampleEXT);
223
224                 OVERRIDE(glGenBuffers);
225                 OVERRIDE(glBindBuffer);
226                 OVERRIDE(glIsBuffer);
227                 OVERRIDE(glDeleteBuffers);
228
229                 OVERRIDE(glGenFramebuffers);
230                 OVERRIDE(glBindFramebuffer);
231                 OVERRIDE(glIsFramebuffer);
232                 OVERRIDE(glDeleteFramebuffers);
233
234                 OVERRIDE(glGenRenderbuffers);
235                 OVERRIDE(glBindRenderbuffer);
236                 OVERRIDE(glFramebufferRenderbuffer);
237                 OVERRIDE(glIsRenderbuffer);
238                 OVERRIDE(glDeleteRenderbuffers);
239
240                 OVERRIDE(glCreateShader);
241                 OVERRIDE(glCreateProgram);
242                 OVERRIDE(glAttachShader);
243                 OVERRIDE(glCompileShader);
244                 OVERRIDE(glShaderBinary);
245                 OVERRIDE(glDeleteShader);
246                 OVERRIDE(glDetachShader);
247                 OVERRIDE(glGetShaderiv);
248                 OVERRIDE(glGetShaderInfoLog);
249                 OVERRIDE(glGetShaderSource);
250                 OVERRIDE(glIsShader);
251                 OVERRIDE(glShaderSource);
252                 OVERRIDE(glBindAttribLocation);
253                 OVERRIDE(glDeleteProgram);
254                 OVERRIDE(glDetachShader);
255                 OVERRIDE(glGetActiveAttrib);
256                 OVERRIDE(glGetActiveUniform);
257                 OVERRIDE(glGetAttachedShaders);
258                 OVERRIDE(glGetAttribLocation);
259                 OVERRIDE(glGetProgramiv);
260                 OVERRIDE(glGetProgramInfoLog);
261                 OVERRIDE(glGetUniformfv);
262                 OVERRIDE(glGetUniformiv);
263                 OVERRIDE(glGetUniformLocation);
264                 OVERRIDE(glIsProgram);
265                 OVERRIDE(glLinkProgram);
266                 OVERRIDE(glUseProgram);
267                 OVERRIDE(glValidateProgram);
268                 OVERRIDE(glGetProgramBinary);
269                 OVERRIDE(glProgramBinary);
270
271                 OVERRIDE(glBlendColor);
272                 OVERRIDE(glBlendEquation);
273                 OVERRIDE(glBlendEquationSeparate);
274                 OVERRIDE(glBlendFunc);
275                 OVERRIDE(glBlendFuncSeparate);
276                 OVERRIDE(glClearColor);
277                 OVERRIDE(glClearDepthf);
278                 OVERRIDE(glClearStencil);
279                 OVERRIDE(glColorMask);
280                 OVERRIDE(glCullFace);
281                 OVERRIDE(glDepthFunc);
282                 OVERRIDE(glDepthMask);
283                 OVERRIDE(glDepthRangef);
284                 OVERRIDE(glDisable);
285                 OVERRIDE(glDisableVertexAttribArray);
286                 OVERRIDE(glDrawArrays);
287                 OVERRIDE(glDrawElements);
288                 OVERRIDE(glEnable);
289                 OVERRIDE(glEnableVertexAttribArray);
290                 OVERRIDE(glFrontFace);
291                 OVERRIDE(glGetVertexAttribfv);
292                 OVERRIDE(glGetVertexAttribiv);
293                 OVERRIDE(glGetVertexAttribPointerv);
294                 OVERRIDE(glHint);
295                 OVERRIDE(glLineWidth);
296                 OVERRIDE(glPixelStorei);
297                 OVERRIDE(glPolygonOffset);
298                 OVERRIDE(glSampleCoverage);
299                 OVERRIDE(glScissor);
300                 OVERRIDE(glStencilFunc);
301                 OVERRIDE(glStencilFuncSeparate);
302                 OVERRIDE(glStencilMask);
303                 OVERRIDE(glStencilMaskSeparate);
304                 OVERRIDE(glStencilOp);
305                 OVERRIDE(glStencilOpSeparate);
306                 OVERRIDE(glVertexAttrib1f);
307                 OVERRIDE(glVertexAttrib1fv);
308                 OVERRIDE(glVertexAttrib2f);
309                 OVERRIDE(glVertexAttrib2fv);
310                 OVERRIDE(glVertexAttrib3f);
311                 OVERRIDE(glVertexAttrib3fv);
312                 OVERRIDE(glVertexAttrib4f);
313                 OVERRIDE(glVertexAttrib4fv);
314                 OVERRIDE(glVertexAttribPointer);
315                 OVERRIDE(glViewport);
316
317                 OVERRIDE(glEGLImageTargetTexture2DOES);
318
319         }
320         else
321         {
322                 LOG("\E[0;35;1m[CoreGL] SKIP GL FASTPATH...\E[0m\n");
323         }
324 }
325
326 #undef OVERRIDE
327
328 static GL_Object **
329 _get_shared_object(GL_Shared_Object_State *sostate, GL_Object_Type type)
330 {
331         switch (type)
332         {
333                 case GL_OBJECT_TYPE_TEXTURE:
334                         return sostate->texture;
335                 case GL_OBJECT_TYPE_BUFFER:
336                         return sostate->buffer;
337                 case GL_OBJECT_TYPE_FRAMEBUFFER:
338                         return sostate->framebuffer;
339                 case GL_OBJECT_TYPE_RENDERBUFFER:
340                         return sostate->renderbuffer;
341                 case GL_OBJECT_TYPE_PROGRAM:
342                         return sostate->program;
343                 default:
344                         return NULL;
345         }
346 }
347
348 int
349 fastpath_add_context_state_to_list(const void *option, const int option_len, GLContextState *cstate, Mutex *mtx)
350 {
351         int ret = 0;
352         int tid = 0;
353         GLContext_List *current = NULL;
354         GLContext_List *newitm = NULL;
355
356         if (mtx != NULL) AST(mutex_lock(mtx) == 1);
357
358         AST(cstate != NULL);
359
360         tid = get_current_thread();
361
362         current = glctx_list;
363         while (current != NULL)
364         {
365                 if (current->option_len == option_len &&
366                     memcmp(current->option, option, option_len) == 0 &&
367                     current->thread_id == tid)
368                 {
369                         AST(current->cstate == cstate);
370                         goto finish;
371                 }
372                 current = current->next;
373         }
374
375         newitm = (GLContext_List *)calloc(1, sizeof(GLContext_List));
376         if (newitm == NULL)
377         {
378                 ERR("Failed to create context list.\n");
379                 goto finish;
380         }
381
382         newitm->cstate = cstate;
383         newitm->thread_id = tid;
384         newitm->option_len = option_len;
385         newitm->option = (void *)malloc(option_len);
386         memcpy(newitm->option, option, option_len);
387
388         if (glctx_list != NULL)
389                 newitm->next = glctx_list;
390
391         glctx_list = newitm;
392
393         ret = 1;
394         goto finish;
395
396 finish:
397         if (ret != 1)
398         {
399                 if (newitm != NULL)
400                 {
401                         free(newitm);
402                         newitm = NULL;
403                 }
404                 if (cstate != NULL)
405                 {
406                         free(cstate);
407                         cstate = NULL;
408                 }
409         }
410         if (mtx != NULL) AST(mutex_unlock(mtx) == 1);
411
412         return ret;
413 }
414
415 GLContextState *
416 fastpath_get_context_state_from_list(const void *option, const int option_len, Mutex *mtx)
417 {
418         GLContextState *ret = NULL;
419         GLContext_List *current = NULL;
420         int tid = 0;
421
422         if (mtx != NULL) AST(mutex_lock(mtx) == 1);
423
424         tid = get_current_thread();
425
426         current = glctx_list;
427         while (current != NULL)
428         {
429                 if (current->option_len == option_len &&
430                     memcmp(current->option, option, option_len) == 0 &&
431                     current->thread_id == tid)
432                 {
433                         ret = current->cstate;
434                         goto finish;
435                 }
436                 current = current->next;
437         }
438         goto finish;
439
440 finish:
441         if (mtx != NULL) AST(mutex_unlock(mtx) == 1);
442         return ret;
443 }
444
445 int
446 fastpath_remove_context_states_from_list(GLContextState *cstate, Mutex *mtx)
447 {
448         int ret = 0;
449         int tid = 0;
450         GLContext_List *olditm = NULL;
451         GLContext_List *current = NULL;
452
453         if (mtx != NULL) AST(mutex_lock(mtx) == 1);
454
455         AST(cstate != NULL);
456
457         tid = get_current_thread();
458         current = glctx_list;
459
460         while (current != NULL)
461         {
462                 if (current->cstate == cstate)
463                 {
464                         GLContext_List *nextitm = NULL;
465                         if (olditm != NULL)
466                         {
467                                 olditm->next = current->next;
468                                 nextitm = olditm->next;
469                         }
470                         else
471                         {
472                                 glctx_list = current->next;
473                                 nextitm = glctx_list;
474                         }
475                         free(current);
476                         ret = 1;
477                         current = nextitm;
478                         continue;
479                 }
480                 olditm = current;
481                 current = current->next;
482         }
483         goto finish;
484
485 finish:
486         if (mtx != NULL) AST(mutex_unlock(mtx) == 1);
487         return ret;
488 }
489
490 GLuint
491 fastpath_sostate_create_object(GL_Shared_Object_State *sostate, GL_Object_Type type, GLuint real_name)
492 {
493         GL_Object **object = NULL;
494         GLuint ret = _COREGL_INT_INIT_VALUE;
495         int i;
496
497         object = _get_shared_object(sostate, type);
498
499         for (i = 1; i < MAX_GL_OBJECT_SIZE; i++)
500         {
501                 if (object[i] == NULL)
502                 {
503                         GL_Object *newobj = (GL_Object *)calloc(1, sizeof(GL_Object));
504                         newobj->id = (int)type + i;
505                         newobj->real_id = real_name;
506                         object[i] = newobj;
507                         ret = newobj->id;
508                         goto finish;
509                 }
510         }
511         goto finish;
512
513 finish:
514         return ret;
515 }
516
517 GLuint
518 fastpath_sostate_remove_object(GL_Shared_Object_State *sostate, GL_Object_Type type, GLuint glue_name)
519 {
520         GL_Object **object = NULL;
521         GLuint ret = _COREGL_INT_INIT_VALUE;
522         int hash = _COREGL_INT_INIT_VALUE;
523
524         object = _get_shared_object(sostate, type);
525
526         hash = glue_name - (int)type;
527         if (hash < 0 ||
528             hash > MAX_GL_OBJECT_SIZE ||
529             object[hash] == NULL ||
530             object[hash]->id != glue_name)
531         {
532                 ret = 0;
533                 goto finish;
534         }
535
536         free(object[hash]);
537         object[hash] = NULL;
538         ret = 1;
539         goto finish;
540
541 finish:
542         return ret;
543 }
544
545 GLuint
546 fastpath_sostate_get_object(GL_Shared_Object_State *sostate, GL_Object_Type type, GLuint glue_name)
547 {
548         GL_Object **object = NULL;
549         GLuint ret = _COREGL_INT_INIT_VALUE;
550         int hash = _COREGL_INT_INIT_VALUE;
551
552         object = _get_shared_object(sostate, type);
553
554         hash = glue_name - (int)type;
555         if (hash < 0 ||
556             hash > MAX_GL_OBJECT_SIZE ||
557             object[hash] == NULL ||
558             object[hash]->id != glue_name)
559         {
560                 ret = 0;
561                 goto finish;
562         }
563         ret = object[hash]->real_id;
564         goto finish;
565
566 finish:
567         return ret;
568 }
569
570 GLuint
571 fastpath_sostate_find_object(GL_Shared_Object_State *sostate, GL_Object_Type type, GLuint real_name)
572 {
573         GL_Object **object = NULL;
574         GLuint ret = _COREGL_INT_INIT_VALUE;
575         int i;
576
577         object = _get_shared_object(sostate, type);
578
579         for (i = 1; i < MAX_GL_OBJECT_SIZE; i++)
580         {
581                 if (object[i] != NULL && object[i]->real_id == real_name)
582                 {
583                         ret = object[i]->id;
584                         goto finish;
585                 }
586         }
587         ret = 0;
588         goto finish;
589
590 finish:
591         return ret;
592 }
593
594 void
595 fastpath_dump_context_states(GLGlueContext *ctx, int force_output)
596 {
597         static struct timeval tv_last = { 0, 0 };
598
599         if (unlikely(trace_state_flag != 1)) return;
600
601         if (!force_output)
602         {
603                 struct timeval tv_now = { 0, 0 };
604                 AST(gettimeofday(&tv_now, NULL) == 0);
605                 if (tv_now.tv_sec - tv_last.tv_sec < _COREGL_TRACE_OUTPUT_INTERVAL_SEC)
606                 {
607                         goto finish;
608                 }
609                 tv_last = tv_now;
610         }
611
612         TRACE("\n");
613         TRACE("\E[0;40;34m========================================================================================================================\E[0m\n");
614         TRACE("\E[0;32;1m  State info \E[1;37;1m: <PID = %d> GlueCTX = %p\E[0m\n", getpid(), ctx);
615         TRACE("\E[0;40;34m========================================================================================================================\E[0m\n");
616
617 #define PRINTF_CHAR_GLenum "%10d"
618 #define PRINTF_CHAR_GLboolean "%10d"
619 #define PRINTF_CHAR_GLint "%10d"
620 #define PRINTF_CHAR_GLsizei "%10u"
621 #define PRINTF_CHAR_GLuint "%10u"
622 #define PRINTF_CHAR_GLuintmask "0x%8X"
623
624 #define PRINTF_CHAR_GLclampf "%10.6f"
625 #define PRINTF_CHAR_GLfloat "%10.6f"
626
627 #define PRINTF_CHAR_GLvoidptr "%10p"
628
629 #define PRINTF_CHAR(type) PRINTF_CHAR_##type
630
631 #define INITIAL_CTX initial_ctx
632 #define GLUE_STATE(TYPE, NAME, SIZE, ARRAY_SIZE, DEFAULT_STMT, GET_STMT)  \
633    { \
634       TYPE valuedata[SIZE]; \
635       TYPE *value = NULL; \
636       value = valuedata; GET_STMT; value = valuedata; \
637       TRACE("\E[0;37;1m %-30.30s : (\E[0m ", #NAME); \
638       for (int i = 0; i < SIZE; i++) \
639       { \
640          if (i > 0) { \
641             if (i % 4 == 0) \
642                TRACE("\n %-30.30s     ", "");\
643             else \
644                TRACE(", "); \
645          } \
646          TRACE(PRINTF_CHAR(TYPE), ctx->NAME[i]); \
647          TRACE("["PRINTF_CHAR(TYPE)"]", value[i]); \
648       } \
649       TRACE(" \E[0;37;1m)\E[0m\n"); \
650    }
651 # include "coregl_fastpath_state.h"
652 #undef GLUE_STATE
653 #undef INITIAL_CTX
654
655         TRACE("\E[0;40;34m========================================================================================================================\E[0m\n");
656         TRACE("\n");
657
658         TRACE_END();
659
660 finish:
661         return;
662 }
663
664 int
665 fastpath_init_context_states(GLGlueContext *ctx)
666 {
667         int ret = 0;
668
669         AST(mutex_lock(&init_context_mutex) == 1);
670
671         if (ctx == NULL)
672         {
673                 ERR("Context NULL\n");
674                 ret = 0;
675                 goto finish;
676         }
677
678         AST(ctx->initialized == 0);
679         AST(ctx->sostate != NULL);
680
681         if (initial_ctx == NULL)
682         {
683                 initial_ctx = (GLGlueContext *)calloc(1, sizeof(GLGlueContext));
684                 AST(initial_ctx != NULL);
685
686 //#define FORCE_DEFAULT_VALUE
687 #ifdef FORCE_DEFAULT_VALUE
688 # define INITIAL_CTX initial_ctx
689 # define GLUE_STATE(TYPE, NAME, SIZE, ARRAY_SIZE, DEFAULT_STMT, GET_STMT)  \
690       { \
691          int i; \
692          TYPE valuedata[SIZE]; \
693          TYPE *value = NULL; \
694          memset(valuedata, 0xcc, sizeof(TYPE) * SIZE); \
695          value = valuedata; DEFAULT_STMT; value = valuedata; \
696          for (i = 0; i < SIZE; i++) \
697          { \
698             if (*((char *)(&value[i])) == 0xcc) \
699             { \
700                memset(&value[i], 0xaa, sizeof(TYPE)); \
701                value = valuedata; DEFAULT_STMT; value = valuedata; \
702                if (*((char *)(&value[i])) == 0xaa) \
703                { \
704                   ERR("\E[0;31;1mWARNING : GL-state '"#NAME"' cannot be retrieved\E[0m\n"); \
705                   break; \
706                } \
707             } \
708             initial_ctx->NAME[i] = value[i]; \
709          } \
710       }
711 #  include "coregl_fastpath_state.h"
712 # undef GLUE_STATE
713 # undef INITIAL_CTX
714 #else
715 # define INITIAL_CTX initial_ctx
716 # define SET_GLUE_VALUE(DEFAULT_STMT, FALLBACK_STMT) \
717       if (try_step == 1) \
718       { \
719          value = valuedata; DEFAULT_STMT; value = valuedata; \
720       } \
721       else \
722       { \
723          value = valuedata; FALLBACK_STMT; value = valuedata; \
724       }
725
726 # define GLUE_STATE(TYPE, NAME, SIZE, ARRAY_SIZE, DEFAULT_STMT, GET_STMT)  \
727       { \
728          int i; \
729          int try_step = 0;\
730          TYPE valuedata[SIZE]; \
731          TYPE *value = NULL; \
732          memset(valuedata, 0xcc, sizeof(TYPE) * SIZE); \
733          do { \
734             try_step++; \
735             SET_GLUE_VALUE(GET_STMT, DEFAULT_STMT); \
736             for (i = 0; i < SIZE; i++) \
737             { \
738                if (*((char *)(&value[i])) == 0xcc) \
739                { \
740                   memset(&value[i], 0xaa, sizeof(TYPE)); \
741                   SET_GLUE_VALUE(GET_STMT, DEFAULT_STMT); \
742                   if (*((char *)(&value[i])) == 0xaa) \
743                   { \
744                      try_step++; \
745                      if (try_step == 2) \
746                      { \
747                         ERR("\E[0;31;1mWARNING : GL-state '"#NAME"' cannot be retrieved\E[0m\n"); \
748                      } \
749                      break; \
750                   } \
751                } \
752                initial_ctx->NAME[i] = value[i]; \
753             } \
754             if (try_step != 2) \
755             { \
756                value = valuedata; DEFAULT_STMT; value = valuedata; \
757                for (i = 0; i < SIZE; i++) \
758                { \
759                   if (initial_ctx->NAME[i] != value[i]) \
760                   { \
761                      ERR("WARNING : GL-state '"#NAME"'[%d] value ["PRINTF_CHAR(TYPE)"] is different from SPEC-DEFAULT ["PRINTF_CHAR(TYPE)"]\n", i, ctx->NAME[i], value[i]); \
762                   } \
763                } \
764             } \
765          } \
766          while (try_step == 2); \
767       }
768 #  include "coregl_fastpath_state.h"
769 # undef SET_GLUE_VALUE
770 # undef GLUE_STATE
771 # undef INITIAL_CTX
772 #endif
773
774                 if (initial_ctx->gl_num_vertex_attribs[0] > MAX_VERTEX_ATTRIBS)
775                 {
776                         ERR("\E[0;31;1mWARNING : Number of vertex attrib is too big! (%d-%d)\E[0m\n", MAX_VERTEX_ATTRIBS, initial_ctx->gl_num_vertex_attribs[0]);
777                 }
778                 if (initial_ctx->gl_num_tex_units[0] > MAX_TEXTURE_UNITS)
779                 {
780                         ERR("\E[0;31;1mWARNING : Number of texture unit is too big! (%d-%d)\E[0m\n", MAX_TEXTURE_UNITS, initial_ctx->gl_num_tex_units[0]);
781                 }
782         }
783
784         {
785                 int i;
786 #define INITIAL_CTX initial_ctx
787 #define GLUE_STATE(TYPE, NAME, SIZE, ARRAY_SIZE, DEFAULT_STMT, GET_STMT)  \
788          for (i = 0; i < SIZE; i++) \
789          { \
790             ctx->NAME[i] = initial_ctx->NAME[i]; \
791          }
792 # include "coregl_fastpath_state.h"
793 #undef GLUE_STATE
794 #undef INITIAL_CTX
795         }
796
797         ctx->initialized = 1;
798         ret = 1;
799         goto finish;
800
801 finish:
802         AST(mutex_unlock(&init_context_mutex) == 1);
803
804         return ret;
805 }
806
807 #ifdef COREGL_USE_MODULE_TRACEPATH
808 extern void *tracepath_api_trace_begin(const char *name, void *hint, int trace_total_time);
809 extern void *tracepath_api_trace_end(const char *name, void *hint, int trace_total_time);
810 #endif
811
812 void
813 fastpath_make_context_current(GLGlueContext *oldctx, GLGlueContext *newctx)
814 {
815         unsigned char flag = 0;
816         int i = 0;
817
818         if (debug_nofp == 1) goto finish;
819
820         // Return if they're the same
821         if (oldctx == newctx) goto finish;
822
823 #define STATE_COMPARE(state) \
824    if ((oldctx->state) != (newctx->state))
825
826 #define STATES_COMPARE(state_ptr, bytes) \
827    if ((memcmp((oldctx->state_ptr), (newctx->state_ptr), (bytes))) != 0)
828
829
830 #ifdef COREGL_USE_MODULE_TRACEPATH
831         static void *trace_hint_glfinish = NULL;
832         trace_hint_glfinish = tracepath_api_trace_begin("eglMakeCurrent(FP glFinish)", trace_hint_glfinish, 0);
833 #endif // COREGL_USE_MODULE_TRACEPATH
834
835         _sym_glFlush();
836
837 #ifdef COREGL_USE_MODULE_TRACEPATH
838         tracepath_api_trace_end("eglMakeCurrent(FP glFinish)", trace_hint_glfinish, 0);
839 #endif // COREGL_USE_MODULE_TRACEPATH
840
841 #ifdef COREGL_USE_MODULE_TRACEPATH
842         static void *trace_hint_bindbuffers = NULL;
843         trace_hint_bindbuffers = tracepath_api_trace_begin("eglMakeCurrent(FP bind buffers)", trace_hint_bindbuffers, 0);
844 #endif // COREGL_USE_MODULE_TRACEPATH
845
846         //------------------//
847         // _bind_flag
848         flag = oldctx->_bind_flag | newctx->_bind_flag;
849         if (flag)
850         {
851                 STATE_COMPARE(gl_array_buffer_binding[0])
852                 {
853                         _sym_glBindBuffer(GL_ARRAY_BUFFER, newctx->gl_array_buffer_binding[0]);
854                 }
855                 STATE_COMPARE(gl_element_array_buffer_binding[0])
856                 {
857                         _sym_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, newctx->gl_element_array_buffer_binding[0]);
858                 }
859                 STATE_COMPARE(gl_framebuffer_binding[0])
860                 {
861                         _sym_glBindFramebuffer(GL_FRAMEBUFFER, newctx->gl_framebuffer_binding[0]);
862                 }
863                 STATE_COMPARE(gl_renderbuffer_binding[0])
864                 {
865                         _sym_glBindRenderbuffer(GL_RENDERBUFFER, newctx->gl_renderbuffer_binding[0]);
866                 }
867         }
868
869 #ifdef COREGL_USE_MODULE_TRACEPATH
870         tracepath_api_trace_end("eglMakeCurrent(FP bind buffers)", trace_hint_bindbuffers, 0);
871 #endif // COREGL_USE_MODULE_TRACEPATH
872
873
874         //------------------//
875         // Enable States
876         // _enable_flag1
877 #ifdef COREGL_USE_MODULE_TRACEPATH
878         static void *trace_hint_enable_states = NULL;
879         trace_hint_enable_states = tracepath_api_trace_begin("eglMakeCurrent(FP enable states)", trace_hint_enable_states, 0);
880 #endif // COREGL_USE_MODULE_TRACEPATH
881
882         flag = oldctx->_enable_flag1 | newctx->_enable_flag1;
883         if (flag)
884         {
885                 STATE_COMPARE(gl_blend[0])
886                 {
887                         if (newctx->gl_blend[0])
888                                 _sym_glEnable(GL_BLEND);
889                         else
890                                 _sym_glDisable(GL_BLEND);
891                 }
892                 STATE_COMPARE(gl_cull_face[0])
893                 {
894                         if (newctx->gl_cull_face[0])
895                                 _sym_glEnable(GL_CULL_FACE);
896                         else
897                                 _sym_glDisable(GL_CULL_FACE);
898                 }
899                 STATE_COMPARE(gl_depth_test[0])
900                 {
901                         if (newctx->gl_depth_test[0])
902                                 _sym_glEnable(GL_DEPTH_TEST);
903                         else
904                                 _sym_glDisable(GL_DEPTH_TEST);
905                 }
906                 STATE_COMPARE(gl_dither[0])
907                 {
908                         if (newctx->gl_dither[0])
909                                 _sym_glEnable(GL_DITHER);
910                         else
911                                 _sym_glDisable(GL_DITHER);
912                 }
913         }
914
915         // _enable_flag2
916         flag = oldctx->_enable_flag2 | newctx->_enable_flag2;
917         if (flag)
918         {
919                 STATE_COMPARE(gl_polygon_offset_fill[0])
920                 {
921                         if (newctx->gl_polygon_offset_fill[0])
922                                 _sym_glEnable(GL_POLYGON_OFFSET_FILL);
923                         else
924                                 _sym_glDisable(GL_POLYGON_OFFSET_FILL);
925                 }
926                 STATE_COMPARE(gl_sample_alpha_to_coverage[0])
927                 {
928                         if (newctx->gl_sample_alpha_to_coverage[0])
929                                 _sym_glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
930                         else
931                                 _sym_glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
932                 }
933                 STATE_COMPARE(gl_sample_coverage[0])
934                 {
935                         if (newctx->gl_sample_coverage[0])
936                                 _sym_glEnable(GL_SAMPLE_COVERAGE);
937                         else
938                                 _sym_glDisable(GL_SAMPLE_COVERAGE);
939                 }
940                 STATE_COMPARE(gl_scissor_test[0])
941                 {
942                         if (newctx->gl_scissor_test[0])
943                                 _sym_glEnable(GL_SCISSOR_TEST);
944                         else
945                                 _sym_glDisable(GL_SCISSOR_TEST);
946                 }
947                 STATE_COMPARE(gl_stencil_test[0])
948                 {
949                         if (newctx->gl_stencil_test[0])
950                                 _sym_glEnable(GL_STENCIL_TEST);
951                         else
952                                 _sym_glDisable(GL_STENCIL_TEST);
953                 }
954         }
955
956 #ifdef COREGL_USE_MODULE_TRACEPATH
957         tracepath_api_trace_end("eglMakeCurrent(FP enable states)", trace_hint_enable_states, 0);
958 #endif // COREGL_USE_MODULE_TRACEPATH
959
960         //------------------//
961         // _clear_flag1
962 #ifdef COREGL_USE_MODULE_TRACEPATH
963         static void *trace_hint_clear_viewport = NULL;
964         trace_hint_clear_viewport = tracepath_api_trace_begin("eglMakeCurrent(FP clear/viewport)", trace_hint_clear_viewport, 0);
965 #endif // COREGL_USE_MODULE_TRACEPATH
966
967         flag = oldctx->_clear_flag1 | newctx->_clear_flag1;
968         if (flag)
969         {
970                 // Viewport.
971                 STATES_COMPARE(gl_viewport, 4 * sizeof(GLint))
972                 {
973                         _sym_glViewport(newctx->gl_viewport[0],
974                                         newctx->gl_viewport[1],
975                                         newctx->gl_viewport[2],
976                                         newctx->gl_viewport[3]);
977                 }
978
979                 STATE_COMPARE(gl_current_program[0])
980                 {
981                         _sym_glUseProgram(newctx->gl_current_program[0]);
982                 }
983                 STATES_COMPARE(gl_color_clear_value, 4 * sizeof(GLclampf))
984                 {
985                         _sym_glClearColor(newctx->gl_color_clear_value[0],
986                                           newctx->gl_color_clear_value[1],
987                                           newctx->gl_color_clear_value[2],
988                                           newctx->gl_color_clear_value[3]);
989                 }
990         }
991
992
993         // _clear_flag2
994         flag = oldctx->_clear_flag2 | newctx->_clear_flag2;
995         if (flag)
996         {
997                 STATES_COMPARE(gl_color_writemask, 4 * sizeof(GLboolean))
998                 {
999                         _sym_glColorMask(newctx->gl_color_writemask[0],
1000                                          newctx->gl_color_writemask[1],
1001                                          newctx->gl_color_writemask[2],
1002                                          newctx->gl_color_writemask[3]);
1003                 }
1004                 STATES_COMPARE(gl_depth_range, 2 * sizeof(GLclampf))
1005                 {
1006                         _sym_glDepthRangef(newctx->gl_depth_range[0],
1007                                            newctx->gl_depth_range[1]);
1008                 }
1009                 STATE_COMPARE(gl_depth_clear_value[0])
1010                 {
1011                         _sym_glClearDepthf(newctx->gl_depth_clear_value[0]);
1012                 }
1013                 STATE_COMPARE(gl_depth_func[0])
1014                 {
1015                         _sym_glDepthFunc(newctx->gl_depth_func[0]);
1016                 }
1017                 STATE_COMPARE(gl_depth_writemask[0])
1018                 {
1019                         _sym_glDepthMask(newctx->gl_depth_writemask[0]);
1020                 }
1021                 STATE_COMPARE(gl_cull_face_mode[0])
1022                 {
1023                         _sym_glCullFace(newctx->gl_cull_face_mode[0]);
1024                 }
1025
1026         }
1027
1028 #ifdef COREGL_USE_MODULE_TRACEPATH
1029         tracepath_api_trace_end("eglMakeCurrent(FP clear/viewport)", trace_hint_clear_viewport, 0);
1030 #endif // COREGL_USE_MODULE_TRACEPATH
1031
1032         //------------------//
1033         // Texture here...
1034 #ifdef COREGL_USE_MODULE_TRACEPATH
1035         static void *trace_hint_bind_textures = NULL;
1036         trace_hint_bind_textures = tracepath_api_trace_begin("eglMakeCurrent(FP bind textures)", trace_hint_bind_textures, 0);
1037 #endif // COREGL_USE_MODULE_TRACEPATH
1038
1039         flag = oldctx->_tex_flag1 | newctx->_tex_flag1;
1040         if (flag)
1041         {
1042
1043                 for (i = 0; i < oldctx->gl_num_tex_units[0]; i++)
1044                 {
1045                         STATE_COMPARE(gl_tex_2d_state[i])
1046                         {
1047                                 _sym_glActiveTexture(GL_TEXTURE0 + i);
1048                                 _sym_glBindTexture(GL_TEXTURE_2D, newctx->gl_tex_2d_state[i]);
1049                         }
1050
1051                         STATE_COMPARE(gl_tex_cube_state[i])
1052                         {
1053                                 _sym_glActiveTexture(GL_TEXTURE0 + i);
1054                                 _sym_glBindTexture(GL_TEXTURE_CUBE_MAP, newctx->gl_tex_cube_state[i]);
1055                         }
1056                 }
1057
1058                 // Restore active texture
1059                 _sym_glActiveTexture(newctx->gl_active_texture[0]);
1060
1061                 STATE_COMPARE(gl_generate_mipmap_hint[0])
1062                 {
1063                         _sym_glHint(GL_GENERATE_MIPMAP_HINT, newctx->gl_generate_mipmap_hint[0]);
1064                 }
1065         }
1066 #ifdef COREGL_USE_MODULE_TRACEPATH
1067         tracepath_api_trace_end("eglMakeCurrent(FP bind textures)", trace_hint_bind_textures, 0);
1068 #endif // COREGL_USE_MODULE_TRACEPATH
1069
1070         //------------------//
1071 #ifdef COREGL_USE_MODULE_TRACEPATH
1072         static void *trace_hint_etc = NULL;
1073         trace_hint_etc = tracepath_api_trace_begin("eglMakeCurrent(FP etc.)", trace_hint_etc, 0);
1074 #endif // COREGL_USE_MODULE_TRACEPATH
1075
1076         flag = oldctx->_blend_flag | newctx->_blend_flag;
1077         if (flag)
1078         {
1079                 STATES_COMPARE(gl_blend_color, 4 * sizeof(GLclampf))
1080                 {
1081                         _sym_glBlendColor(newctx->gl_blend_color[0],
1082                                           newctx->gl_blend_color[1],
1083                                           newctx->gl_blend_color[2],
1084                                           newctx->gl_blend_color[3]);
1085                 }
1086                 if ((oldctx->gl_blend_src_rgb[0] != newctx->gl_blend_src_rgb[0]) ||
1087                     (oldctx->gl_blend_dst_rgb[0] != newctx->gl_blend_dst_rgb[0]) ||
1088                     (oldctx->gl_blend_src_alpha[0] != newctx->gl_blend_src_alpha[0]) ||
1089                     (oldctx->gl_blend_dst_alpha[0] != newctx->gl_blend_dst_alpha[0]))
1090                 {
1091                         _sym_glBlendFuncSeparate(newctx->gl_blend_src_rgb[0],
1092                                                  newctx->gl_blend_dst_rgb[0],
1093                                                  newctx->gl_blend_src_alpha[0],
1094                                                  newctx->gl_blend_dst_alpha[0]);
1095                 }
1096                 if ((oldctx->gl_blend_equation_rgb[0] != newctx->gl_blend_equation_rgb[0]) ||
1097                     (oldctx->gl_blend_equation_alpha[0] != newctx->gl_blend_equation_alpha[0]))
1098                 {
1099                         _sym_glBlendEquationSeparate(newctx->gl_blend_equation_rgb[0], newctx->gl_blend_equation_alpha[0]);
1100                 }
1101
1102         }
1103
1104         //------------------//
1105         // _stencil_flag1
1106         flag = oldctx->_stencil_flag1 | newctx->_stencil_flag1;
1107         if (flag)
1108         {
1109                 if ((oldctx->gl_stencil_func[0] != newctx->gl_stencil_func[0]) ||
1110                     (oldctx->gl_stencil_ref[0]  != newctx->gl_stencil_ref[0])  ||
1111                     (oldctx->gl_stencil_value_mask[0] != newctx->gl_stencil_value_mask[0]))
1112                 {
1113                         _sym_glStencilFuncSeparate(GL_FRONT,
1114                                                    newctx->gl_stencil_func[0],
1115                                                    newctx->gl_stencil_ref[0],
1116                                                    newctx->gl_stencil_value_mask[0]);
1117                 }
1118                 if ((oldctx->gl_stencil_fail[0] != newctx->gl_stencil_fail[0]) ||
1119                     (oldctx->gl_stencil_pass_depth_fail[0] != newctx->gl_stencil_pass_depth_fail[0]) ||
1120                     (oldctx->gl_stencil_pass_depth_pass[0] != newctx->gl_stencil_pass_depth_pass[0]))
1121                 {
1122                         _sym_glStencilOpSeparate(GL_FRONT,
1123                                                  newctx->gl_stencil_fail[0],
1124                                                  newctx->gl_stencil_pass_depth_fail[0],
1125                                                  newctx->gl_stencil_pass_depth_pass[0]);
1126                 }
1127
1128                 STATE_COMPARE(gl_stencil_writemask[0])
1129                 {
1130                         _sym_glStencilMaskSeparate(GL_FRONT, newctx->gl_stencil_writemask[0]);
1131                 }
1132         }
1133
1134
1135         // _stencil_flag1
1136         flag = oldctx->_stencil_flag2 | newctx->_stencil_flag2;
1137         if (flag)
1138         {
1139                 if ((oldctx->gl_stencil_back_func[0] != newctx->gl_stencil_back_func[0]) ||
1140                     (oldctx->gl_stencil_back_ref[0]  != newctx->gl_stencil_back_ref[0])  ||
1141                     (oldctx->gl_stencil_back_value_mask[0] != newctx->gl_stencil_back_value_mask[0]))
1142                 {
1143                         _sym_glStencilFuncSeparate(GL_BACK,
1144                                                    newctx->gl_stencil_back_func[0],
1145                                                    newctx->gl_stencil_back_ref[0],
1146                                                    newctx->gl_stencil_back_value_mask[0]);
1147                 }
1148                 if ((oldctx->gl_stencil_back_fail[0] != newctx->gl_stencil_back_fail[0]) ||
1149                     (oldctx->gl_stencil_back_pass_depth_fail[0] != newctx->gl_stencil_back_pass_depth_fail[0]) ||
1150                     (oldctx->gl_stencil_back_pass_depth_pass[0] != newctx->gl_stencil_back_pass_depth_pass[0]))
1151                 {
1152                         _sym_glStencilOpSeparate(GL_BACK,
1153                                                  newctx->gl_stencil_back_fail[0],
1154                                                  newctx->gl_stencil_back_pass_depth_fail[0],
1155                                                  newctx->gl_stencil_back_pass_depth_pass[0]);
1156                 }
1157
1158                 STATE_COMPARE(gl_stencil_back_writemask[0])
1159                 {
1160                         _sym_glStencilMaskSeparate(GL_BACK, newctx->gl_stencil_back_writemask[0]);
1161                 }
1162                 STATE_COMPARE(gl_stencil_clear_value[0])
1163                 {
1164                         _sym_glClearStencil(newctx->gl_stencil_clear_value[0]);
1165                 }
1166         }
1167
1168         //------------------//
1169         // _misc_flag1
1170         flag = oldctx->_misc_flag1 | newctx->_misc_flag1;
1171         if (flag)
1172         {
1173                 STATE_COMPARE(gl_front_face[0])
1174                 {
1175                         _sym_glFrontFace(newctx->gl_front_face[0]);
1176                 }
1177                 STATE_COMPARE(gl_line_width[0])
1178                 {
1179                         _sym_glLineWidth(newctx->gl_line_width[0]);
1180                 }
1181                 if ((oldctx->gl_polygon_offset_factor[0] != newctx->gl_polygon_offset_factor[0]) ||
1182                     (oldctx->gl_polygon_offset_units[0]  != newctx->gl_polygon_offset_units[0]))
1183                 {
1184                         _sym_glPolygonOffset(newctx->gl_polygon_offset_factor[0],
1185                                              newctx->gl_polygon_offset_units[0]);
1186                 }
1187                 if ((oldctx->gl_sample_coverage_value[0]  != newctx->gl_sample_coverage_value[0]) ||
1188                     (oldctx->gl_sample_coverage_invert[0] != newctx->gl_sample_coverage_invert[0]))
1189                 {
1190                         _sym_glSampleCoverage(newctx->gl_sample_coverage_value[0],
1191                                               newctx->gl_sample_coverage_invert[0]);
1192                 }
1193         }
1194
1195         // _misc_flag2
1196         flag = oldctx->_misc_flag2 | newctx->_misc_flag2;
1197         if (flag)
1198         {
1199                 STATES_COMPARE(gl_scissor_box, 4 * sizeof(GLint))
1200                 {
1201                         _sym_glScissor(newctx->gl_scissor_box[0],
1202                                        newctx->gl_scissor_box[1],
1203                                        newctx->gl_scissor_box[2],
1204                                        newctx->gl_scissor_box[3]);
1205                 }
1206                 STATE_COMPARE(gl_pack_alignment[0])
1207                 {
1208                         _sym_glPixelStorei(GL_PACK_ALIGNMENT, newctx->gl_pack_alignment[0]);
1209                 }
1210                 STATE_COMPARE(gl_unpack_alignment[0])
1211                 {
1212                         _sym_glPixelStorei(GL_UNPACK_ALIGNMENT, newctx->gl_unpack_alignment[0]);
1213                 }
1214         }
1215 #ifdef COREGL_USE_MODULE_TRACEPATH
1216         tracepath_api_trace_end("eglMakeCurrent(FP etc.)", trace_hint_etc, 0);
1217 #endif // COREGL_USE_MODULE_TRACEPATH
1218
1219         // _varray_flag
1220 #ifdef COREGL_USE_MODULE_TRACEPATH
1221         static void *trace_hint_vertex_attrib = NULL;
1222         trace_hint_vertex_attrib = tracepath_api_trace_begin("eglMakeCurrent(FP vertex attrib)", trace_hint_vertex_attrib, 0);
1223 #endif // COREGL_USE_MODULE_TRACEPATH
1224
1225         flag = oldctx->_vattrib_flag | newctx->_vattrib_flag;
1226         if (flag)
1227         {
1228                 for (i = 0; i < oldctx->gl_num_vertex_attribs[0]; i++)
1229                 {
1230                         if (newctx->gl_vertex_array_buf_id[i] != oldctx->gl_vertex_array_buf_id[i])
1231                         {
1232                                 _sym_glBindBuffer(GL_ARRAY_BUFFER, newctx->gl_vertex_array_buf_id[i]);
1233                         }
1234                         else _sym_glBindBuffer(GL_ARRAY_BUFFER, 0);
1235
1236                         _sym_glVertexAttribPointer(i,
1237                                                    newctx->gl_vertex_array_size[i],
1238                                                    newctx->gl_vertex_array_type[i],
1239                                                    newctx->gl_vertex_array_normalized[i],
1240                                                    newctx->gl_vertex_array_stride[i],
1241                                                    newctx->gl_vertex_array_pointer[i]);
1242
1243                         STATES_COMPARE(gl_vertex_attrib_value + 4 * i, 4 * sizeof(GLfloat))
1244                         {
1245                                 _sym_glVertexAttrib4fv(i, &newctx->gl_vertex_attrib_value[4 * i]);
1246                         }
1247
1248                         if (newctx->gl_vertex_array_enabled[i] == GL_TRUE)
1249                         {
1250                                 _sym_glEnableVertexAttribArray(i);
1251                         }
1252                         else
1253                         {
1254                                 _sym_glDisableVertexAttribArray(i);
1255                         }
1256                 }
1257
1258                 STATE_COMPARE(gl_array_buffer_binding[0])
1259                 {
1260                         _sym_glBindBuffer(GL_ARRAY_BUFFER, newctx->gl_array_buffer_binding[0]);
1261                 }
1262                 STATE_COMPARE(gl_element_array_buffer_binding[0])
1263                 {
1264                         _sym_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, newctx->gl_element_array_buffer_binding[0]);
1265                 }
1266
1267         }
1268
1269 #ifdef COREGL_USE_MODULE_TRACEPATH
1270         tracepath_api_trace_end("eglMakeCurrent(FP vertex attrib)", trace_hint_vertex_attrib, 0);
1271 #endif // COREGL_USE_MODULE_TRACEPATH
1272
1273         goto finish;
1274
1275 finish:
1276
1277 #ifdef COREGL_FASTPATH_TRACE_STATE_INFO
1278         if (unlikely(trace_state_flag == 1))
1279                 fastpath_dump_context_states(newctx, 0);
1280 #endif // COREGL_FASTPATH_TRACE_STATE_INFO
1281         return;
1282 #undef STATE_COMPARE
1283 #undef STATES_COMPARE
1284 }
1285