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