[Title] Renamed/Added some EXT/OES extensions
[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
215                 COREGL_OVERRIDE(fastpath_, glGenBuffers);
216                 COREGL_OVERRIDE(fastpath_, glBindBuffer);
217                 COREGL_OVERRIDE(fastpath_, glIsBuffer);
218                 COREGL_OVERRIDE(fastpath_, glDeleteBuffers);
219
220                 COREGL_OVERRIDE(fastpath_, glGenFramebuffers);
221                 COREGL_OVERRIDE(fastpath_, glBindFramebuffer);
222                 COREGL_OVERRIDE(fastpath_, glIsFramebuffer);
223                 COREGL_OVERRIDE(fastpath_, glDeleteFramebuffers);
224
225                 COREGL_OVERRIDE(fastpath_, glGenRenderbuffers);
226                 COREGL_OVERRIDE(fastpath_, glBindRenderbuffer);
227                 COREGL_OVERRIDE(fastpath_, glFramebufferRenderbuffer);
228                 COREGL_OVERRIDE(fastpath_, glIsRenderbuffer);
229                 COREGL_OVERRIDE(fastpath_, glDeleteRenderbuffers);
230
231                 COREGL_OVERRIDE(fastpath_, glCreateShader);
232                 COREGL_OVERRIDE(fastpath_, glCreateProgram);
233                 COREGL_OVERRIDE(fastpath_, glAttachShader);
234                 COREGL_OVERRIDE(fastpath_, glCompileShader);
235                 COREGL_OVERRIDE(fastpath_, glShaderBinary);
236                 COREGL_OVERRIDE(fastpath_, glDeleteShader);
237                 COREGL_OVERRIDE(fastpath_, glDetachShader);
238                 COREGL_OVERRIDE(fastpath_, glGetShaderiv);
239                 COREGL_OVERRIDE(fastpath_, glGetShaderInfoLog);
240                 COREGL_OVERRIDE(fastpath_, glGetShaderSource);
241                 COREGL_OVERRIDE(fastpath_, glIsShader);
242                 COREGL_OVERRIDE(fastpath_, glShaderSource);
243                 COREGL_OVERRIDE(fastpath_, glBindAttribLocation);
244                 COREGL_OVERRIDE(fastpath_, glDeleteProgram);
245                 COREGL_OVERRIDE(fastpath_, glGetActiveAttrib);
246                 COREGL_OVERRIDE(fastpath_, glGetActiveUniform);
247                 COREGL_OVERRIDE(fastpath_, glGetAttachedShaders);
248                 COREGL_OVERRIDE(fastpath_, glGetAttribLocation);
249                 COREGL_OVERRIDE(fastpath_, glGetProgramiv);
250                 COREGL_OVERRIDE(fastpath_, glGetProgramInfoLog);
251                 COREGL_OVERRIDE(fastpath_, glGetUniformfv);
252                 COREGL_OVERRIDE(fastpath_, glGetUniformiv);
253                 COREGL_OVERRIDE(fastpath_, glGetUniformLocation);
254                 COREGL_OVERRIDE(fastpath_, glIsProgram);
255                 COREGL_OVERRIDE(fastpath_, glLinkProgram);
256                 COREGL_OVERRIDE(fastpath_, glUseProgram);
257                 COREGL_OVERRIDE(fastpath_, glValidateProgram);
258
259                 COREGL_OVERRIDE(fastpath_, glBlendColor);
260                 COREGL_OVERRIDE(fastpath_, glBlendEquation);
261                 COREGL_OVERRIDE(fastpath_, glBlendEquationSeparate);
262                 COREGL_OVERRIDE(fastpath_, glBlendFunc);
263                 COREGL_OVERRIDE(fastpath_, glBlendFuncSeparate);
264                 COREGL_OVERRIDE(fastpath_, glClearColor);
265                 COREGL_OVERRIDE(fastpath_, glClearDepthf);
266                 COREGL_OVERRIDE(fastpath_, glClearStencil);
267                 COREGL_OVERRIDE(fastpath_, glColorMask);
268                 COREGL_OVERRIDE(fastpath_, glCullFace);
269                 COREGL_OVERRIDE(fastpath_, glDepthFunc);
270                 COREGL_OVERRIDE(fastpath_, glDepthMask);
271                 COREGL_OVERRIDE(fastpath_, glDepthRangef);
272                 COREGL_OVERRIDE(fastpath_, glDisable);
273                 COREGL_OVERRIDE(fastpath_, glDisableVertexAttribArray);
274                 COREGL_OVERRIDE(fastpath_, glEnable);
275                 COREGL_OVERRIDE(fastpath_, glEnableVertexAttribArray);
276                 COREGL_OVERRIDE(fastpath_, glFrontFace);
277                 COREGL_OVERRIDE(fastpath_, glHint);
278                 COREGL_OVERRIDE(fastpath_, glLineWidth);
279                 COREGL_OVERRIDE(fastpath_, glPixelStorei);
280                 COREGL_OVERRIDE(fastpath_, glPolygonOffset);
281                 COREGL_OVERRIDE(fastpath_, glSampleCoverage);
282                 COREGL_OVERRIDE(fastpath_, glScissor);
283                 COREGL_OVERRIDE(fastpath_, glStencilFunc);
284                 COREGL_OVERRIDE(fastpath_, glStencilFuncSeparate);
285                 COREGL_OVERRIDE(fastpath_, glStencilMask);
286                 COREGL_OVERRIDE(fastpath_, glStencilMaskSeparate);
287                 COREGL_OVERRIDE(fastpath_, glStencilOp);
288                 COREGL_OVERRIDE(fastpath_, glStencilOpSeparate);
289                 COREGL_OVERRIDE(fastpath_, glVertexAttrib1f);
290                 COREGL_OVERRIDE(fastpath_, glVertexAttrib1fv);
291                 COREGL_OVERRIDE(fastpath_, glVertexAttrib2f);
292                 COREGL_OVERRIDE(fastpath_, glVertexAttrib2fv);
293                 COREGL_OVERRIDE(fastpath_, glVertexAttrib3f);
294                 COREGL_OVERRIDE(fastpath_, glVertexAttrib3fv);
295                 COREGL_OVERRIDE(fastpath_, glVertexAttrib4f);
296                 COREGL_OVERRIDE(fastpath_, glVertexAttrib4fv);
297                 COREGL_OVERRIDE(fastpath_, glVertexAttribPointer);
298                 COREGL_OVERRIDE(fastpath_, glViewport);
299
300                 COREGL_OVERRIDE(fastpath_, glFramebufferTexture2DMultisampleEXT);
301                 COREGL_OVERRIDE(fastpath_, glGetProgramBinaryOES);
302                 COREGL_OVERRIDE(fastpath_, glProgramBinaryOES);
303                 COREGL_OVERRIDE(fastpath_, glProgramParameteriEXT);
304                 COREGL_OVERRIDE(fastpath_, glEGLImageTargetTexture2DOES);
305
306         }
307         else
308         {
309                 LOG("\E[0;35;1m[CoreGL] SKIP GL FASTPATH...\E[0m\n");
310         }
311 }
312
313 #undef OVERRIDE
314
315 static inline GL_Object_Hash_Base *
316 _get_shared_object_hash(GL_Shared_Object_State *sostate, GL_Object_Type type)
317 {
318         switch (type)
319         {
320                 case GL_OBJECT_TYPE_TEXTURE:
321                         return &sostate->texture;
322                 case GL_OBJECT_TYPE_BUFFER:
323                         return &sostate->buffer;
324                 case GL_OBJECT_TYPE_FRAMEBUFFER:
325                         return &sostate->framebuffer;
326                 case GL_OBJECT_TYPE_RENDERBUFFER:
327                         return &sostate->renderbuffer;
328                 case GL_OBJECT_TYPE_PROGRAM:
329                         return &sostate->program;
330                 default:
331                         return NULL;
332         }
333 }
334
335 static inline GL_Object_Hash_Base *
336 _get_shared_object_hash_real(GL_Shared_Object_State *sostate, GL_Object_Type type)
337 {
338         switch (type)
339         {
340                 case GL_OBJECT_TYPE_TEXTURE:
341                         return &sostate->texture_real;
342                 case GL_OBJECT_TYPE_BUFFER:
343                         return &sostate->buffer_real;
344                 case GL_OBJECT_TYPE_FRAMEBUFFER:
345                         return &sostate->framebuffer_real;
346                 case GL_OBJECT_TYPE_RENDERBUFFER:
347                         return &sostate->renderbuffer_real;
348                 case GL_OBJECT_TYPE_PROGRAM:
349                         return &sostate->program_real;
350                 default:
351                         return NULL;
352         }
353 }
354
355 int
356 fastpath_add_context_state_to_list(const void *option, const int option_len, GLContextState *cstate, Mutex *mtx)
357 {
358         int ret = 0;
359         int tid = 0;
360         GLContext_List *current = NULL;
361         GLContext_List *newitm = NULL;
362
363         if (mtx != NULL) AST(mutex_lock(mtx) == 1);
364
365         AST(cstate != NULL);
366
367         tid = get_current_thread();
368
369         current = glctx_list;
370         while (current != NULL)
371         {
372                 if (current->option_len == option_len &&
373                     memcmp(current->option, option, option_len) == 0 &&
374                     current->thread_id == tid)
375                 {
376                         AST(current->cstate == cstate);
377                         goto finish;
378                 }
379                 current = current->next;
380         }
381
382         newitm = (GLContext_List *)calloc(1, sizeof(GLContext_List));
383         if (newitm == NULL)
384         {
385                 ERR("Failed to create context list.\n");
386                 goto finish;
387         }
388
389         newitm->cstate = cstate;
390         newitm->thread_id = tid;
391         newitm->option_len = option_len;
392         newitm->option = (void *)malloc(option_len);
393         memcpy(newitm->option, option, option_len);
394
395         if (glctx_list != NULL)
396                 newitm->next = glctx_list;
397
398         glctx_list = newitm;
399
400         ret = 1;
401         goto finish;
402
403 finish:
404         if (ret != 1)
405         {
406                 if (newitm != NULL)
407                 {
408                         free(newitm);
409                         newitm = NULL;
410                 }
411                 if (cstate != NULL)
412                 {
413                         free(cstate);
414                         cstate = NULL;
415                 }
416         }
417         if (mtx != NULL) AST(mutex_unlock(mtx) == 1);
418
419         return ret;
420 }
421
422 GLContextState *
423 fastpath_get_context_state_from_list(const void *option, const int option_len, Mutex *mtx)
424 {
425         GLContextState *ret = NULL;
426         GLContext_List *current = NULL;
427         int tid = 0;
428
429         if (mtx != NULL) AST(mutex_lock(mtx) == 1);
430
431         tid = get_current_thread();
432
433         current = glctx_list;
434         while (current != NULL)
435         {
436                 if (current->option_len == option_len &&
437                     memcmp(current->option, option, option_len) == 0 &&
438                     current->thread_id == tid)
439                 {
440                         ret = current->cstate;
441                         goto finish;
442                 }
443                 current = current->next;
444         }
445         goto finish;
446
447 finish:
448         if (mtx != NULL) AST(mutex_unlock(mtx) == 1);
449         return ret;
450 }
451
452 int
453 fastpath_remove_context_states_from_list(GLContextState *cstate, Mutex *mtx)
454 {
455         int ret = 0;
456         int tid = 0;
457         GLContext_List *olditm = NULL;
458         GLContext_List *current = NULL;
459
460         if (mtx != NULL) AST(mutex_lock(mtx) == 1);
461
462         AST(cstate != NULL);
463
464         tid = get_current_thread();
465         current = glctx_list;
466
467         while (current != NULL)
468         {
469                 if (current->cstate == cstate)
470                 {
471                         GLContext_List *nextitm = NULL;
472                         if (olditm != NULL)
473                         {
474                                 olditm->next = current->next;
475                                 nextitm = olditm->next;
476                         }
477                         else
478                         {
479                                 glctx_list = current->next;
480                                 nextitm = glctx_list;
481                         }
482                         free(current);
483                         ret = 1;
484                         current = nextitm;
485                         continue;
486                 }
487                 olditm = current;
488                 current = current->next;
489         }
490         goto finish;
491
492 finish:
493         if (mtx != NULL) AST(mutex_unlock(mtx) == 1);
494         return ret;
495 }
496
497 void
498 fastpath_sostate_init(GL_Shared_Object_State *sostate)
499 {
500 #define HASH_INIT(hash_base) \
501         hash_base.hash_field = (GL_Object_Hash **)calloc(1, sizeof(GL_Object_Hash *) * GL_OBJECT_HASH_BASE); \
502         hash_base.hash_size = GL_OBJECT_HASH_BASE;
503
504         HASH_INIT(sostate->texture);
505         HASH_INIT(sostate->buffer);
506         HASH_INIT(sostate->framebuffer);
507         HASH_INIT(sostate->renderbuffer);
508         HASH_INIT(sostate->program);
509
510         HASH_INIT(sostate->texture_real);
511         HASH_INIT(sostate->buffer_real);
512         HASH_INIT(sostate->framebuffer_real);
513         HASH_INIT(sostate->renderbuffer_real);
514         HASH_INIT(sostate->program_real);
515
516 #undef HASH_INIT
517 }
518
519 static void
520 _add_hash(GL_Object_Hash_Base *hash_base, GL_Object_Hash *data)
521 {
522         int array_idx = data->hash_key & (hash_base->hash_size - 1);
523         if (hash_base->hash_field[array_idx] == NULL)
524         {
525                 hash_base->hash_field[array_idx] = data;
526         }
527         else
528         {
529                 GL_Object_Hash *current = hash_base->hash_field[array_idx];
530                 while(current->next)
531                 {
532                         AST(current->hash_key != data->hash_key);
533                         current = current->next;
534                 }
535                 current->next = data;
536         }
537         data->next = NULL;
538         hash_base->item_size++;
539 }
540
541 static int
542 _remove_hash(GL_Object_Hash_Base *hash_base, GLuint hash)
543 {
544         int ret = 0;
545         int array_idx = hash & (hash_base->hash_size - 1);
546
547         GL_Object_Hash *current = hash_base->hash_field[array_idx];
548         GL_Object_Hash *prev = NULL;
549
550         while(current)
551         {
552                 if (current->hash_key == hash)
553                 {
554                         if (prev != NULL)
555                                 prev->next = current->next;
556                         else
557                                 hash_base->hash_field[array_idx] = current->next;
558                         hash_base->item_size--;
559                         ret = 1;
560                         break;
561                 }
562                 current = current->next;
563         }
564
565         return ret;
566 }
567
568 static void
569 _free_hash_list(GL_Object_Hash_Base *hash_base, int free_data)
570 {
571         if (hash_base->item_size == 0) return;
572
573         for (int i = 0; i < hash_base->hash_size; i++)
574         {
575                 if (hash_base->hash_field[i] != NULL)
576                 {
577                         GL_Object_Hash *current = hash_base->hash_field[i];
578
579                         while (current != NULL)
580                         {
581                                 GL_Object_Hash *current_next = current->next;
582
583                                 if (free_data == 1 && current->item != NULL)
584                                 {
585                                         free(current->item);
586                                 }
587
588                                 free(current);
589                                 hash_base->item_size--;
590                                 current = current_next;
591                         }
592                 }
593         }
594 }
595
596 void
597 fastpath_sostate_deinit(GL_Shared_Object_State *sostate)
598 {
599 #define HASH_DEINIT(hash_base, free_data) \
600         _free_hash_list(&hash_base, free_data); \
601         free(hash_base.hash_field); \
602         hash_base.hash_size = 0;
603
604         HASH_DEINIT(sostate->texture, 1);
605         HASH_DEINIT(sostate->buffer, 1);
606         HASH_DEINIT(sostate->framebuffer, 1);
607         HASH_DEINIT(sostate->renderbuffer, 1);
608         HASH_DEINIT(sostate->program, 1);
609
610         HASH_DEINIT(sostate->texture_real, 0);
611         HASH_DEINIT(sostate->buffer_real, 0);
612         HASH_DEINIT(sostate->framebuffer_real, 0);
613         HASH_DEINIT(sostate->renderbuffer_real, 0);
614         HASH_DEINIT(sostate->program_real, 0);
615
616 #undef HASH_DEINIT
617 }
618
619 #define FIND_HASH(hash_base, key, ret) \
620 { \
621         GL_Object_Hash *fh_current = hash_base->hash_field[(key) & (hash_base->hash_size - 1)]; \
622         while(fh_current) \
623         { \
624                 if (fh_current->hash_key == (key)) \
625                 { \
626                         ret = fh_current; \
627                         break; \
628                 } \
629                 fh_current = fh_current->next; \
630         } \
631 }
632
633 void
634 _sostate_hash_check(GL_Object_Hash_Base *hash_base)
635 {
636         if (hash_base->item_size < hash_base->hash_size)
637                 return;
638
639         int oldsize = hash_base->hash_size;
640         GL_Object_Hash **oldfield = hash_base->hash_field;
641
642         hash_base->hash_size = oldsize << 1;
643         hash_base->hash_field = (GL_Object_Hash **)calloc(1, sizeof(GL_Object_Hash *) * hash_base->hash_size);
644         AST(hash_base->hash_field != NULL);
645
646         for (int i = 0; i < oldsize; i++)
647         {
648                 if (oldfield[i] != NULL)
649                 {
650                         GL_Object_Hash *current = oldfield[i];
651
652                         while (current != NULL)
653                         {
654                                 GL_Object_Hash *current_next = current->next;
655                                 _add_hash(hash_base, current);
656                                 hash_base->item_size--;
657                                 current = current_next;
658                         }
659                 }
660         }
661         free(oldfield);
662
663 }
664
665 GLuint
666 fastpath_sostate_create_object(GL_Shared_Object_State *sostate, GL_Object_Type type, GLuint real_name)
667 {
668         GLuint ret = _COREGL_INT_INIT_VALUE;
669
670         GL_Object_Hash_Base *hash_base = NULL;
671         GL_Object_Hash_Base *hash_base_real = NULL;
672         int newid = _COREGL_INT_INIT_VALUE;
673
674         hash_base = _get_shared_object_hash(sostate, type);
675         hash_base_real = _get_shared_object_hash_real(sostate, type);
676
677         newid = hash_base->last_id + 1;
678         if (newid >= GL_OBJECT_ID_LIMIT)
679         {
680                 hash_base->is_looped = 1;
681                 newid = 1;
682                 hash_base->last_id = 1;
683         }
684
685         if (hash_base->is_looped != 0)
686         {
687                 int i;
688                 int findingid = newid;
689                 newid = -1;
690                 for (i = 0; i < GL_OBJECT_ID_LIMIT; i++)
691                 {
692                         GL_Object_Hash *exist_hash = NULL;
693                         FIND_HASH(hash_base, findingid, exist_hash);
694                         if (exist_hash == NULL)
695                         {
696                                 newid = findingid;
697                                 break;
698                         }
699                         findingid++;
700                         if (findingid >= GL_OBJECT_ID_LIMIT) findingid = 1;
701                 }
702                 AST(newid != -1);
703         }
704         hash_base->last_id = newid;
705
706         {
707                 GL_Object *newobj = (GL_Object *)calloc(1, sizeof(GL_Object));
708                 AST(newobj != NULL);
709                 newobj->id = (int)type + newid;
710                 newobj->real_id = real_name;
711                 newobj->ref_count = 1;
712                 ret = newobj->id;
713
714                 GL_Object_Hash *newobj_hash = (GL_Object_Hash *)calloc(1, sizeof(GL_Object_Hash));
715                 AST(newobj_hash != NULL);
716                 newobj_hash->item = newobj;
717                 newobj_hash->hash_key = newid;
718                 _add_hash(hash_base, newobj_hash);
719
720                 GL_Object_Hash *newobj_hash_real = (GL_Object_Hash *)calloc(1, sizeof(GL_Object_Hash));
721                 AST(newobj_hash_real != NULL);
722                 newobj_hash_real->item = newobj;
723                 newobj_hash_real->hash_key = real_name;
724                 _add_hash(hash_base_real, newobj_hash_real);
725         }
726
727         _sostate_hash_check(hash_base);
728         _sostate_hash_check(hash_base_real);
729
730         goto finish;
731
732 finish:
733         return ret;
734 }
735
736 #define FIND_OBJ_FROM_HASH_WITH_VERIFY(hash_base, hash, object) \
737         if ((hash) < 0 || (hash) > GL_OBJECT_ID_LIMIT) { ret = 0; goto finish; } \
738         { \
739                 GL_Object_Hash *object_hash = NULL; \
740                 FIND_HASH((hash_base), (hash), object_hash); \
741                 if (object_hash == NULL) { ret = 0; goto finish; } \
742                 (object) = object_hash->item; \
743                 if ((object) == NULL) { ret = 0; goto finish; } \
744         }
745
746 GLuint
747 fastpath_sostate_remove_object(GL_Shared_Object_State *sostate, GL_Object_Type type, GLuint glue_name)
748 {
749         GLuint ret = _COREGL_INT_INIT_VALUE;
750
751         GL_Object_Hash_Base *hash_base = NULL;
752         GL_Object_Hash_Base *hash_base_real = NULL;
753         GL_Object *object = NULL;
754
755         hash_base = _get_shared_object_hash(sostate, type);
756         hash_base_real = _get_shared_object_hash_real(sostate, type);
757
758         FIND_OBJ_FROM_HASH_WITH_VERIFY(hash_base, glue_name - (int)type, object);
759
760         object->ref_count--;
761
762         if (object->ref_count <= 0)
763         {
764                 GL_Object_Hash *object_hash = NULL;
765
766                 FIND_HASH(hash_base, object->id - (int)type, object_hash);
767                 AST(object_hash != NULL);
768                 _remove_hash(hash_base, object->id - (int)type);
769                 free(object_hash);
770                 object_hash = NULL;
771
772                 FIND_HASH(hash_base_real, object->real_id, object_hash);
773                 AST(object_hash != NULL);
774                 _remove_hash(hash_base_real, object->real_id);
775                 free(object_hash);
776                 object_hash = NULL;
777
778                 free(object);
779                 object = NULL;
780         }
781
782         ret = 1;
783         goto finish;
784
785 finish:
786         return ret;
787 }
788
789 GLuint
790 fastpath_sostate_get_object(GL_Shared_Object_State *sostate, GL_Object_Type type, GLuint glue_name)
791 {
792         GLuint ret = _COREGL_INT_INIT_VALUE;
793
794         GL_Object_Hash_Base *hash_base = NULL;
795         GL_Object *object = NULL;
796
797         hash_base = _get_shared_object_hash(sostate, type);
798
799         FIND_OBJ_FROM_HASH_WITH_VERIFY(hash_base, glue_name - (int)type, object);
800
801         ret = object->real_id;
802         goto finish;
803
804 finish:
805         return ret;
806 }
807
808 GLint
809 fastpath_sostate_set_object_tag(GL_Shared_Object_State *sostate, GL_Object_Type type, GLuint glue_name, GLvoid *tag)
810 {
811         GLint ret = _COREGL_INT_INIT_VALUE;
812
813         GL_Object_Hash_Base *hash_base = NULL;
814         GL_Object *object = NULL;
815         int hash = _COREGL_INT_INIT_VALUE;
816
817         hash_base = _get_shared_object_hash(sostate, type);
818
819         hash = glue_name - (int)type;
820
821         FIND_OBJ_FROM_HASH_WITH_VERIFY(hash_base, hash, object);
822
823         object->tag = tag;
824         ret = 1;
825         goto finish;
826
827 finish:
828         return ret;
829 }
830
831 GLvoid *
832 fastpath_sostate_get_object_tag(GL_Shared_Object_State *sostate, GL_Object_Type type, GLuint glue_name)
833 {
834         GLvoid *ret = NULL;
835
836         GL_Object_Hash_Base *hash_base = NULL;
837         GL_Object *object = NULL;
838
839         hash_base = _get_shared_object_hash(sostate, type);
840
841         FIND_OBJ_FROM_HASH_WITH_VERIFY(hash_base, glue_name - (int)type, object);
842
843         ret = object->tag;
844         goto finish;
845
846 finish:
847         return ret;
848 }
849
850 GLuint
851 fastpath_sostate_find_object(GL_Shared_Object_State *sostate, GL_Object_Type type, GLuint real_name)
852 {
853         GLuint ret = _COREGL_INT_INIT_VALUE;
854
855         GL_Object_Hash_Base *hash_base_real = NULL;
856         GL_Object *object = NULL;
857
858         hash_base_real = _get_shared_object_hash_real(sostate, type);
859
860         FIND_OBJ_FROM_HASH_WITH_VERIFY(hash_base_real, real_name, object);
861
862         ret = object->id;
863         goto finish;
864
865 finish:
866         return ret;
867 }
868
869 GLint
870 fastpath_sostate_use_object(GL_Shared_Object_State *sostate, GL_Object_Type type, GLuint glue_name)
871 {
872         GLint ret = _COREGL_INT_INIT_VALUE;
873
874         GL_Object_Hash_Base *hash_base = NULL;
875         GL_Object *object = NULL;
876
877         hash_base = _get_shared_object_hash(sostate, type);
878
879         FIND_OBJ_FROM_HASH_WITH_VERIFY(hash_base, glue_name - (int)type, object);
880
881         object->ref_count++;
882         ret = 1;
883         goto finish;
884
885 finish:
886         return ret;
887 }
888
889 void
890 fastpath_dump_context_states(GLGlueContext *ctx, int force_output)
891 {
892         static struct timeval tv_last = { 0, 0 };
893
894         if (unlikely(trace_state_flag != 1)) return;
895
896         if (!force_output)
897         {
898                 struct timeval tv_now = { 0, 0 };
899                 AST(gettimeofday(&tv_now, NULL) == 0);
900                 if (tv_now.tv_sec - tv_last.tv_sec < _COREGL_TRACE_OUTPUT_INTERVAL_SEC)
901                 {
902                         goto finish;
903                 }
904                 tv_last = tv_now;
905         }
906
907         TRACE("\n");
908         TRACE("\E[0;40;34m========================================================================================================================\E[0m\n");
909         TRACE("\E[0;32;1m  State info \E[1;37;1m: <PID = %d> GlueCTX = %p\E[0m\n", getpid(), ctx);
910         TRACE("\E[0;40;34m========================================================================================================================\E[0m\n");
911
912 #define PRINTF_CHAR_GLenum "%10d"
913 #define PRINTF_CHAR_GLboolean "%10d"
914 #define PRINTF_CHAR_GLint "%10d"
915 #define PRINTF_CHAR_GLsizei "%10u"
916 #define PRINTF_CHAR_GLuint "%10u"
917 #define PRINTF_CHAR_GLuintmask "0x%8X"
918
919 #define PRINTF_CHAR_GLclampf "%10.6f"
920 #define PRINTF_CHAR_GLfloat "%10.6f"
921
922 #define PRINTF_CHAR_GLvoidptr "%10p"
923
924 #define PRINTF_CHAR(type) PRINTF_CHAR_##type
925
926 #define INITIAL_CTX initial_ctx
927 #define GLUE_STATE(TYPE, NAME, SIZE, ARRAY_SIZE, DEFAULT_STMT, GET_STMT)  \
928    { \
929       TYPE valuedata[SIZE]; \
930       TYPE *value = NULL; \
931       value = valuedata; GET_STMT; value = valuedata; \
932       TRACE("\E[0;37;1m %-30.30s : (\E[0m ", #NAME); \
933       for (int i = 0; i < SIZE; i++) \
934       { \
935          if (i > 0) { \
936             if (i % 4 == 0) \
937                TRACE("\n %-30.30s     ", "");\
938             else \
939                TRACE(", "); \
940          } \
941          TRACE(PRINTF_CHAR(TYPE), ctx->NAME[i]); \
942          TRACE("["PRINTF_CHAR(TYPE)"]", value[i]); \
943       } \
944       TRACE(" \E[0;37;1m)\E[0m\n"); \
945    }
946 # include "coregl_fastpath_state.h"
947 #undef GLUE_STATE
948 #undef INITIAL_CTX
949
950         TRACE("\E[0;40;34m========================================================================================================================\E[0m\n");
951         TRACE("\n");
952
953         TRACE_END();
954
955 finish:
956         return;
957 }
958
959 int
960 fastpath_init_context_states(GLGlueContext *ctx)
961 {
962         int ret = 0;
963
964         AST(mutex_lock(&init_context_mutex) == 1);
965
966         if (ctx == NULL)
967         {
968                 ERR("Context NULL\n");
969                 ret = 0;
970                 goto finish;
971         }
972
973         AST(ctx->initialized == 0);
974         AST(ctx->sostate != NULL);
975
976         if (initial_ctx == NULL)
977         {
978                 initial_ctx = (GLGlueContext *)calloc(1, sizeof(GLGlueContext));
979                 AST(initial_ctx != NULL);
980
981 //#define FORCE_DEFAULT_VALUE
982 #ifdef FORCE_DEFAULT_VALUE
983 # define INITIAL_CTX initial_ctx
984 # define GLUE_STATE(TYPE, NAME, SIZE, ARRAY_SIZE, DEFAULT_STMT, GET_STMT)  \
985       { \
986          int i; \
987          TYPE valuedata[SIZE]; \
988          TYPE *value = NULL; \
989          memset(valuedata, 0xcc, sizeof(TYPE) * SIZE); \
990          value = valuedata; DEFAULT_STMT; value = valuedata; \
991          for (i = 0; i < SIZE; i++) \
992          { \
993             if (*((char *)(&value[i])) == 0xcc) \
994             { \
995                memset(&value[i], 0xaa, sizeof(TYPE)); \
996                value = valuedata; DEFAULT_STMT; value = valuedata; \
997                if (*((char *)(&value[i])) == 0xaa) \
998                { \
999                   ERR("\E[0;31;1mWARNING : GL-state '"#NAME"' cannot be retrieved\E[0m\n"); \
1000                   break; \
1001                } \
1002             } \
1003             initial_ctx->NAME[i] = value[i]; \
1004          } \
1005       }
1006 #  include "coregl_fastpath_state.h"
1007 # undef GLUE_STATE
1008 # undef INITIAL_CTX
1009 #else
1010 # define INITIAL_CTX initial_ctx
1011 # define SET_GLUE_VALUE(DEFAULT_STMT, FALLBACK_STMT) \
1012       if (try_step == 1) \
1013       { \
1014          value = valuedata; DEFAULT_STMT; value = valuedata; \
1015       } \
1016       else \
1017       { \
1018          value = valuedata; FALLBACK_STMT; value = valuedata; \
1019       }
1020
1021 # define GLUE_STATE(TYPE, NAME, SIZE, ARRAY_SIZE, DEFAULT_STMT, GET_STMT)  \
1022       { \
1023          int i; \
1024          int try_step = 0;\
1025          TYPE valuedata[SIZE]; \
1026          TYPE *value = NULL; \
1027          memset(valuedata, 0xcc, sizeof(TYPE) * SIZE); \
1028          do { \
1029             try_step++; \
1030             SET_GLUE_VALUE(GET_STMT, DEFAULT_STMT); \
1031             for (i = 0; i < SIZE; i++) \
1032             { \
1033                if (*((char *)(&value[i])) == 0xcc) \
1034                { \
1035                   memset(&value[i], 0xaa, sizeof(TYPE)); \
1036                   SET_GLUE_VALUE(GET_STMT, DEFAULT_STMT); \
1037                   if (*((char *)(&value[i])) == 0xaa) \
1038                   { \
1039                      try_step++; \
1040                      if (try_step == 2) \
1041                      { \
1042                         ERR("\E[0;31;1mWARNING : GL-state '"#NAME"' cannot be retrieved\E[0m\n"); \
1043                      } \
1044                      break; \
1045                   } \
1046                } \
1047                initial_ctx->NAME[i] = value[i]; \
1048             } \
1049             if (try_step != 2) \
1050             { \
1051                value = valuedata; DEFAULT_STMT; value = valuedata; \
1052                for (i = 0; i < SIZE; i++) \
1053                { \
1054                   if (initial_ctx->NAME[i] != value[i]) \
1055                   { \
1056                      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]); \
1057                   } \
1058                } \
1059             } \
1060          } \
1061          while (try_step == 2); \
1062       }
1063 #  include "coregl_fastpath_state.h"
1064 # undef SET_GLUE_VALUE
1065 # undef GLUE_STATE
1066 # undef INITIAL_CTX
1067 #endif
1068
1069                 if (initial_ctx->gl_num_vertex_attribs[0] > MAX_VERTEX_ATTRIBS)
1070                 {
1071                         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]);
1072                 }
1073                 if (initial_ctx->gl_num_tex_units[0] > MAX_TEXTURE_UNITS)
1074                 {
1075                         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]);
1076                 }
1077         }
1078
1079         {
1080                 int i;
1081 #define INITIAL_CTX initial_ctx
1082 #define GLUE_STATE(TYPE, NAME, SIZE, ARRAY_SIZE, DEFAULT_STMT, GET_STMT)  \
1083          for (i = 0; i < SIZE; i++) \
1084          { \
1085             ctx->NAME[i] = initial_ctx->NAME[i]; \
1086          }
1087 # include "coregl_fastpath_state.h"
1088 #undef GLUE_STATE
1089 #undef INITIAL_CTX
1090         }
1091
1092         ctx->initialized = 1;
1093         ret = 1;
1094         goto finish;
1095
1096 finish:
1097         AST(mutex_unlock(&init_context_mutex) == 1);
1098
1099         return ret;
1100 }
1101
1102 #ifdef COREGL_USE_MODULE_TRACEPATH
1103 extern void *tracepath_api_trace_begin(const char *name, void *hint, int trace_total_time);
1104 extern void *tracepath_api_trace_end(const char *name, void *hint, int trace_total_time);
1105 #endif
1106
1107 #define CHECK_GL_ERROR(func) \
1108         { \
1109                 func; \
1110                 int err = _orig_fastpath_glGetError(); \
1111                 if (err != GL_NO_ERROR) \
1112                 { \
1113                         ERR("\E[0;31;1mERROR(GL %p) : %s returns GL error 0x%X\E[0m\n", oldctx->cstate, #func, err); \
1114                         goto finish; \
1115                 } \
1116         }
1117
1118 int
1119 fastpath_make_context_current(GLGlueContext *oldctx, GLGlueContext *newctx)
1120 {
1121         int ret = 0;
1122         unsigned char flag = 0;
1123         int i = 0;
1124
1125         if (debug_nofp == 1)
1126         {
1127                 ret = 1;
1128                 goto finish;
1129         }
1130
1131         // Return if they're the same
1132         if (oldctx == newctx)
1133         {
1134                 ret = 1;
1135                 goto finish;
1136         }
1137
1138 #define STATE_COMPARE(state) \
1139    if ((oldctx->state) != (newctx->state))
1140
1141 #define STATES_COMPARE(state_ptr, bytes) \
1142    if ((memcmp((oldctx->state_ptr), (newctx->state_ptr), (bytes))) != 0)
1143
1144
1145 #ifdef COREGL_USE_MODULE_TRACEPATH
1146         static void *trace_hint_glfinish = NULL;
1147         trace_hint_glfinish = tracepath_api_trace_begin("eglMakeCurrent(FP glFinish)", trace_hint_glfinish, 0);
1148 #endif // COREGL_USE_MODULE_TRACEPATH
1149
1150         {
1151                 int err = _orig_fastpath_glGetError();
1152                 if (err != GL_NO_ERROR && oldctx->gl_error == GL_NO_ERROR)
1153                         oldctx->gl_error = err;
1154         }
1155
1156         CHECK_GL_ERROR(_orig_fastpath_glFlush())
1157
1158 #ifdef COREGL_USE_MODULE_TRACEPATH
1159         tracepath_api_trace_end("eglMakeCurrent(FP glFinish)", trace_hint_glfinish, 0);
1160 #endif // COREGL_USE_MODULE_TRACEPATH
1161
1162 #ifdef COREGL_USE_MODULE_TRACEPATH
1163         static void *trace_hint_bindbuffers = NULL;
1164         trace_hint_bindbuffers = tracepath_api_trace_begin("eglMakeCurrent(FP bind buffers)", trace_hint_bindbuffers, 0);
1165 #endif // COREGL_USE_MODULE_TRACEPATH
1166
1167
1168         //------------------//
1169         // _bind_flag
1170         flag = oldctx->_bind_flag | newctx->_bind_flag;
1171         if (flag)
1172         {
1173                 STATE_COMPARE(gl_array_buffer_binding[0])
1174                 {
1175                         CHECK_GL_ERROR(_orig_fastpath_glBindBuffer(GL_ARRAY_BUFFER, newctx->gl_array_buffer_binding[0]))
1176                 }
1177                 STATE_COMPARE(gl_element_array_buffer_binding[0])
1178                 {
1179                         CHECK_GL_ERROR(_orig_fastpath_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, newctx->gl_element_array_buffer_binding[0]))
1180                 }
1181                 STATE_COMPARE(gl_framebuffer_binding[0])
1182                 {
1183                         CHECK_GL_ERROR(_orig_fastpath_glBindFramebuffer(GL_FRAMEBUFFER, newctx->gl_framebuffer_binding[0]))
1184                 }
1185                 STATE_COMPARE(gl_renderbuffer_binding[0])
1186                 {
1187                         CHECK_GL_ERROR(_orig_fastpath_glBindRenderbuffer(GL_RENDERBUFFER, newctx->gl_renderbuffer_binding[0]))
1188                 }
1189         }
1190
1191 #ifdef COREGL_USE_MODULE_TRACEPATH
1192         tracepath_api_trace_end("eglMakeCurrent(FP bind buffers)", trace_hint_bindbuffers, 0);
1193 #endif // COREGL_USE_MODULE_TRACEPATH
1194
1195
1196         //------------------//
1197         // Enable States
1198         // _enable_flag1
1199 #ifdef COREGL_USE_MODULE_TRACEPATH
1200         static void *trace_hint_enable_states = NULL;
1201         trace_hint_enable_states = tracepath_api_trace_begin("eglMakeCurrent(FP enable states)", trace_hint_enable_states, 0);
1202 #endif // COREGL_USE_MODULE_TRACEPATH
1203
1204         flag = oldctx->_enable_flag1 | newctx->_enable_flag1;
1205         if (flag)
1206         {
1207                 STATE_COMPARE(gl_blend[0])
1208                 {
1209                         if (newctx->gl_blend[0])
1210                         {
1211                                 CHECK_GL_ERROR(_orig_fastpath_glEnable(GL_BLEND))
1212                         }
1213                         else
1214                                 CHECK_GL_ERROR(_orig_fastpath_glDisable(GL_BLEND))
1215                         }
1216                 STATE_COMPARE(gl_cull_face[0])
1217                 {
1218                         if (newctx->gl_cull_face[0])
1219                         {
1220                                 CHECK_GL_ERROR(_orig_fastpath_glEnable(GL_CULL_FACE))
1221                         }
1222                         else
1223                                 CHECK_GL_ERROR(_orig_fastpath_glDisable(GL_CULL_FACE))
1224                         }
1225                 STATE_COMPARE(gl_depth_test[0])
1226                 {
1227                         if (newctx->gl_depth_test[0])
1228                         {
1229                                 CHECK_GL_ERROR(_orig_fastpath_glEnable(GL_DEPTH_TEST))
1230                         }
1231                         else
1232                                 CHECK_GL_ERROR(_orig_fastpath_glDisable(GL_DEPTH_TEST))
1233                         }
1234                 STATE_COMPARE(gl_dither[0])
1235                 {
1236                         if (newctx->gl_dither[0])
1237                         {
1238                                 CHECK_GL_ERROR(_orig_fastpath_glEnable(GL_DITHER))
1239                         }
1240                         else
1241                                 CHECK_GL_ERROR(_orig_fastpath_glDisable(GL_DITHER))
1242                         }
1243         }
1244
1245         // _enable_flag2
1246         flag = oldctx->_enable_flag2 | newctx->_enable_flag2;
1247         if (flag)
1248         {
1249                 STATE_COMPARE(gl_polygon_offset_fill[0])
1250                 {
1251                         if (newctx->gl_polygon_offset_fill[0])
1252                         {
1253                                 CHECK_GL_ERROR(_orig_fastpath_glEnable(GL_POLYGON_OFFSET_FILL))
1254                         }
1255                         else
1256                                 CHECK_GL_ERROR(_orig_fastpath_glDisable(GL_POLYGON_OFFSET_FILL))
1257                         }
1258                 STATE_COMPARE(gl_sample_alpha_to_coverage[0])
1259                 {
1260                         if (newctx->gl_sample_alpha_to_coverage[0])
1261                         {
1262                                 CHECK_GL_ERROR(_orig_fastpath_glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE))
1263                         }
1264                         else
1265                                 CHECK_GL_ERROR(_orig_fastpath_glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE))
1266                         }
1267                 STATE_COMPARE(gl_sample_coverage[0])
1268                 {
1269                         if (newctx->gl_sample_coverage[0])
1270                         {
1271                                 CHECK_GL_ERROR(_orig_fastpath_glEnable(GL_SAMPLE_COVERAGE))
1272                         }
1273                         else
1274                                 CHECK_GL_ERROR(_orig_fastpath_glDisable(GL_SAMPLE_COVERAGE))
1275                         }
1276                 STATE_COMPARE(gl_scissor_test[0])
1277                 {
1278                         if (newctx->gl_scissor_test[0])
1279                         {
1280                                 CHECK_GL_ERROR(_orig_fastpath_glEnable(GL_SCISSOR_TEST))
1281                         }
1282                         else
1283                                 CHECK_GL_ERROR(_orig_fastpath_glDisable(GL_SCISSOR_TEST))
1284                         }
1285                 STATE_COMPARE(gl_stencil_test[0])
1286                 {
1287                         if (newctx->gl_stencil_test[0])
1288                         {
1289                                 CHECK_GL_ERROR(_orig_fastpath_glEnable(GL_STENCIL_TEST))
1290                         }
1291                         else
1292                                 CHECK_GL_ERROR(_orig_fastpath_glDisable(GL_STENCIL_TEST))
1293                         }
1294         }
1295
1296 #ifdef COREGL_USE_MODULE_TRACEPATH
1297         tracepath_api_trace_end("eglMakeCurrent(FP enable states)", trace_hint_enable_states, 0);
1298 #endif // COREGL_USE_MODULE_TRACEPATH
1299
1300         //------------------//
1301         // _clear_flag1
1302 #ifdef COREGL_USE_MODULE_TRACEPATH
1303         static void *trace_hint_clear_viewport = NULL;
1304         trace_hint_clear_viewport = tracepath_api_trace_begin("eglMakeCurrent(FP clear/viewport)", trace_hint_clear_viewport, 0);
1305 #endif // COREGL_USE_MODULE_TRACEPATH
1306
1307         flag = oldctx->_clear_flag1 | newctx->_clear_flag1;
1308         if (flag)
1309         {
1310                 // Viewport.
1311                 STATES_COMPARE(gl_viewport, 4 * sizeof(GLint))
1312                 {
1313                         CHECK_GL_ERROR(_orig_fastpath_glViewport(newctx->gl_viewport[0],
1314                                        newctx->gl_viewport[1],
1315                                        newctx->gl_viewport[2],
1316                                        newctx->gl_viewport[3]))
1317                 }
1318
1319                 STATE_COMPARE(gl_current_program[0])
1320                 {
1321                         CHECK_GL_ERROR(_orig_fastpath_glUseProgram(newctx->gl_current_program[0]))
1322                 }
1323                 STATES_COMPARE(gl_color_clear_value, 4 * sizeof(GLclampf))
1324                 {
1325                         CHECK_GL_ERROR(_orig_fastpath_glClearColor(newctx->gl_color_clear_value[0],
1326                                        newctx->gl_color_clear_value[1],
1327                                        newctx->gl_color_clear_value[2],
1328                                        newctx->gl_color_clear_value[3]))
1329                 }
1330         }
1331
1332
1333         // _clear_flag2
1334         flag = oldctx->_clear_flag2 | newctx->_clear_flag2;
1335         if (flag)
1336         {
1337                 STATES_COMPARE(gl_color_writemask, 4 * sizeof(GLboolean))
1338                 {
1339                         CHECK_GL_ERROR(_orig_fastpath_glColorMask(newctx->gl_color_writemask[0],
1340                                        newctx->gl_color_writemask[1],
1341                                        newctx->gl_color_writemask[2],
1342                                        newctx->gl_color_writemask[3]))
1343                 }
1344                 STATES_COMPARE(gl_depth_range, 2 * sizeof(GLclampf))
1345                 {
1346                         CHECK_GL_ERROR(_orig_fastpath_glDepthRangef(newctx->gl_depth_range[0],
1347                                        newctx->gl_depth_range[1]))
1348                 }
1349                 STATE_COMPARE(gl_depth_clear_value[0])
1350                 {
1351                         CHECK_GL_ERROR(_orig_fastpath_glClearDepthf(newctx->gl_depth_clear_value[0]))
1352                 }
1353                 STATE_COMPARE(gl_depth_func[0])
1354                 {
1355                         CHECK_GL_ERROR(_orig_fastpath_glDepthFunc(newctx->gl_depth_func[0]))
1356                 }
1357                 STATE_COMPARE(gl_depth_writemask[0])
1358                 {
1359                         CHECK_GL_ERROR(_orig_fastpath_glDepthMask(newctx->gl_depth_writemask[0]))
1360                 }
1361                 STATE_COMPARE(gl_cull_face_mode[0])
1362                 {
1363                         CHECK_GL_ERROR(_orig_fastpath_glCullFace(newctx->gl_cull_face_mode[0]))
1364                 }
1365
1366         }
1367
1368 #ifdef COREGL_USE_MODULE_TRACEPATH
1369         tracepath_api_trace_end("eglMakeCurrent(FP clear/viewport)", trace_hint_clear_viewport, 0);
1370 #endif // COREGL_USE_MODULE_TRACEPATH
1371
1372         //------------------//
1373         // Texture here...
1374 #ifdef COREGL_USE_MODULE_TRACEPATH
1375         static void *trace_hint_bind_textures = NULL;
1376         trace_hint_bind_textures = tracepath_api_trace_begin("eglMakeCurrent(FP bind textures)", trace_hint_bind_textures, 0);
1377 #endif // COREGL_USE_MODULE_TRACEPATH
1378
1379         flag = oldctx->_tex_flag1 | newctx->_tex_flag1;
1380         if (flag)
1381         {
1382
1383                 for (i = 0; i < oldctx->gl_num_tex_units[0]; i++)
1384                 {
1385                         STATE_COMPARE(gl_tex_2d_state[i])
1386                         {
1387                                 CHECK_GL_ERROR(_orig_fastpath_glActiveTexture(GL_TEXTURE0 + i))
1388                                 CHECK_GL_ERROR(_orig_fastpath_glBindTexture(GL_TEXTURE_2D, newctx->gl_tex_2d_state[i]))
1389                         }
1390
1391                         STATE_COMPARE(gl_tex_cube_state[i])
1392                         {
1393                                 CHECK_GL_ERROR(_orig_fastpath_glActiveTexture(GL_TEXTURE0 + i))
1394                                 CHECK_GL_ERROR(_orig_fastpath_glBindTexture(GL_TEXTURE_CUBE_MAP, newctx->gl_tex_cube_state[i]))
1395                         }
1396                 }
1397
1398                 // Restore active texture
1399                 CHECK_GL_ERROR(_orig_fastpath_glActiveTexture(newctx->gl_active_texture[0]))
1400
1401                 STATE_COMPARE(gl_generate_mipmap_hint[0])
1402                 {
1403                         CHECK_GL_ERROR(_orig_fastpath_glHint(GL_GENERATE_MIPMAP_HINT, newctx->gl_generate_mipmap_hint[0]))
1404                 }
1405         }
1406 #ifdef COREGL_USE_MODULE_TRACEPATH
1407         tracepath_api_trace_end("eglMakeCurrent(FP bind textures)", trace_hint_bind_textures, 0);
1408 #endif // COREGL_USE_MODULE_TRACEPATH
1409
1410         //------------------//
1411 #ifdef COREGL_USE_MODULE_TRACEPATH
1412         static void *trace_hint_etc = NULL;
1413         trace_hint_etc = tracepath_api_trace_begin("eglMakeCurrent(FP etc.)", trace_hint_etc, 0);
1414 #endif // COREGL_USE_MODULE_TRACEPATH
1415
1416         flag = oldctx->_blend_flag | newctx->_blend_flag;
1417         if (flag)
1418         {
1419                 STATES_COMPARE(gl_blend_color, 4 * sizeof(GLclampf))
1420                 {
1421                         CHECK_GL_ERROR(_orig_fastpath_glBlendColor(newctx->gl_blend_color[0],
1422                                        newctx->gl_blend_color[1],
1423                                        newctx->gl_blend_color[2],
1424                                        newctx->gl_blend_color[3]))
1425                 }
1426                 if ((oldctx->gl_blend_src_rgb[0] != newctx->gl_blend_src_rgb[0]) ||
1427                     (oldctx->gl_blend_dst_rgb[0] != newctx->gl_blend_dst_rgb[0]) ||
1428                     (oldctx->gl_blend_src_alpha[0] != newctx->gl_blend_src_alpha[0]) ||
1429                     (oldctx->gl_blend_dst_alpha[0] != newctx->gl_blend_dst_alpha[0]))
1430                 {
1431                         CHECK_GL_ERROR(_orig_fastpath_glBlendFuncSeparate(newctx->gl_blend_src_rgb[0],
1432                                        newctx->gl_blend_dst_rgb[0],
1433                                        newctx->gl_blend_src_alpha[0],
1434                                        newctx->gl_blend_dst_alpha[0]))
1435                 }
1436                 if ((oldctx->gl_blend_equation_rgb[0] != newctx->gl_blend_equation_rgb[0]) ||
1437                     (oldctx->gl_blend_equation_alpha[0] != newctx->gl_blend_equation_alpha[0]))
1438                 {
1439                         CHECK_GL_ERROR(_orig_fastpath_glBlendEquationSeparate(newctx->gl_blend_equation_rgb[0], newctx->gl_blend_equation_alpha[0]))
1440                 }
1441
1442         }
1443
1444         //------------------//
1445         // _stencil_flag1
1446         flag = oldctx->_stencil_flag1 | newctx->_stencil_flag1;
1447         if (flag)
1448         {
1449                 if ((oldctx->gl_stencil_func[0] != newctx->gl_stencil_func[0]) ||
1450                     (oldctx->gl_stencil_ref[0]  != newctx->gl_stencil_ref[0])  ||
1451                     (oldctx->gl_stencil_value_mask[0] != newctx->gl_stencil_value_mask[0]))
1452                 {
1453                         CHECK_GL_ERROR(_orig_fastpath_glStencilFuncSeparate(GL_FRONT,
1454                                        newctx->gl_stencil_func[0],
1455                                        newctx->gl_stencil_ref[0],
1456                                        newctx->gl_stencil_value_mask[0]))
1457                 }
1458                 if ((oldctx->gl_stencil_fail[0] != newctx->gl_stencil_fail[0]) ||
1459                     (oldctx->gl_stencil_pass_depth_fail[0] != newctx->gl_stencil_pass_depth_fail[0]) ||
1460                     (oldctx->gl_stencil_pass_depth_pass[0] != newctx->gl_stencil_pass_depth_pass[0]))
1461                 {
1462                         CHECK_GL_ERROR(_orig_fastpath_glStencilOpSeparate(GL_FRONT,
1463                                        newctx->gl_stencil_fail[0],
1464                                        newctx->gl_stencil_pass_depth_fail[0],
1465                                        newctx->gl_stencil_pass_depth_pass[0]))
1466                 }
1467
1468                 STATE_COMPARE(gl_stencil_writemask[0])
1469                 {
1470                         CHECK_GL_ERROR(_orig_fastpath_glStencilMaskSeparate(GL_FRONT, newctx->gl_stencil_writemask[0]))
1471                 }
1472         }
1473
1474
1475         // _stencil_flag1
1476         flag = oldctx->_stencil_flag2 | newctx->_stencil_flag2;
1477         if (flag)
1478         {
1479                 if ((oldctx->gl_stencil_back_func[0] != newctx->gl_stencil_back_func[0]) ||
1480                     (oldctx->gl_stencil_back_ref[0]  != newctx->gl_stencil_back_ref[0])  ||
1481                     (oldctx->gl_stencil_back_value_mask[0] != newctx->gl_stencil_back_value_mask[0]))
1482                 {
1483                         CHECK_GL_ERROR(_orig_fastpath_glStencilFuncSeparate(GL_BACK,
1484                                        newctx->gl_stencil_back_func[0],
1485                                        newctx->gl_stencil_back_ref[0],
1486                                        newctx->gl_stencil_back_value_mask[0]))
1487                 }
1488                 if ((oldctx->gl_stencil_back_fail[0] != newctx->gl_stencil_back_fail[0]) ||
1489                     (oldctx->gl_stencil_back_pass_depth_fail[0] != newctx->gl_stencil_back_pass_depth_fail[0]) ||
1490                     (oldctx->gl_stencil_back_pass_depth_pass[0] != newctx->gl_stencil_back_pass_depth_pass[0]))
1491                 {
1492                         CHECK_GL_ERROR(_orig_fastpath_glStencilOpSeparate(GL_BACK,
1493                                        newctx->gl_stencil_back_fail[0],
1494                                        newctx->gl_stencil_back_pass_depth_fail[0],
1495                                        newctx->gl_stencil_back_pass_depth_pass[0]))
1496                 }
1497
1498                 STATE_COMPARE(gl_stencil_back_writemask[0])
1499                 {
1500                         CHECK_GL_ERROR(_orig_fastpath_glStencilMaskSeparate(GL_BACK, newctx->gl_stencil_back_writemask[0]))
1501                 }
1502                 STATE_COMPARE(gl_stencil_clear_value[0])
1503                 {
1504                         CHECK_GL_ERROR(_orig_fastpath_glClearStencil(newctx->gl_stencil_clear_value[0]))
1505                 }
1506         }
1507
1508         //------------------//
1509         // _misc_flag1
1510         flag = oldctx->_misc_flag1 | newctx->_misc_flag1;
1511         if (flag)
1512         {
1513                 STATE_COMPARE(gl_front_face[0])
1514                 {
1515                         CHECK_GL_ERROR(_orig_fastpath_glFrontFace(newctx->gl_front_face[0]))
1516                 }
1517                 STATE_COMPARE(gl_line_width[0])
1518                 {
1519                         CHECK_GL_ERROR(_orig_fastpath_glLineWidth(newctx->gl_line_width[0]))
1520                 }
1521                 if ((oldctx->gl_polygon_offset_factor[0] != newctx->gl_polygon_offset_factor[0]) ||
1522                     (oldctx->gl_polygon_offset_units[0]  != newctx->gl_polygon_offset_units[0]))
1523                 {
1524                         CHECK_GL_ERROR(_orig_fastpath_glPolygonOffset(newctx->gl_polygon_offset_factor[0],
1525                                        newctx->gl_polygon_offset_units[0]))
1526                 }
1527                 if ((oldctx->gl_sample_coverage_value[0]  != newctx->gl_sample_coverage_value[0]) ||
1528                     (oldctx->gl_sample_coverage_invert[0] != newctx->gl_sample_coverage_invert[0]))
1529                 {
1530                         CHECK_GL_ERROR(_orig_fastpath_glSampleCoverage(newctx->gl_sample_coverage_value[0],
1531                                        newctx->gl_sample_coverage_invert[0]))
1532                 }
1533         }
1534
1535         // _misc_flag2
1536         flag = oldctx->_misc_flag2 | newctx->_misc_flag2;
1537         if (flag)
1538         {
1539                 STATES_COMPARE(gl_scissor_box, 4 * sizeof(GLint))
1540                 {
1541                         CHECK_GL_ERROR(_orig_fastpath_glScissor(newctx->gl_scissor_box[0],
1542                                                                 newctx->gl_scissor_box[1],
1543                                                                 newctx->gl_scissor_box[2],
1544                                                                 newctx->gl_scissor_box[3]))
1545                 }
1546                 STATE_COMPARE(gl_pack_alignment[0])
1547                 {
1548                         CHECK_GL_ERROR(_orig_fastpath_glPixelStorei(GL_PACK_ALIGNMENT, newctx->gl_pack_alignment[0]))
1549                 }
1550                 STATE_COMPARE(gl_unpack_alignment[0])
1551                 {
1552                         CHECK_GL_ERROR(_orig_fastpath_glPixelStorei(GL_UNPACK_ALIGNMENT, newctx->gl_unpack_alignment[0]))
1553                 }
1554         }
1555 #ifdef COREGL_USE_MODULE_TRACEPATH
1556         tracepath_api_trace_end("eglMakeCurrent(FP etc.)", trace_hint_etc, 0);
1557 #endif // COREGL_USE_MODULE_TRACEPATH
1558
1559         // _varray_flag
1560 #ifdef COREGL_USE_MODULE_TRACEPATH
1561         static void *trace_hint_vertex_attrib = NULL;
1562         trace_hint_vertex_attrib = tracepath_api_trace_begin("eglMakeCurrent(FP vertex attrib)", trace_hint_vertex_attrib, 0);
1563 #endif // COREGL_USE_MODULE_TRACEPATH
1564
1565         flag = oldctx->_vattrib_flag | newctx->_vattrib_flag;
1566         if (flag)
1567         {
1568                 for (i = 0; i < oldctx->gl_num_vertex_attribs[0]; i++)
1569                 {
1570                         if (newctx->gl_vertex_array_buf_id[i] != oldctx->gl_vertex_array_buf_id[i])
1571                         {
1572                                 CHECK_GL_ERROR(_orig_fastpath_glBindBuffer(GL_ARRAY_BUFFER, newctx->gl_vertex_array_buf_id[i]))
1573                         }
1574                         else
1575                         {
1576                                 CHECK_GL_ERROR(_orig_fastpath_glBindBuffer(GL_ARRAY_BUFFER, 0))
1577                         }
1578
1579                         CHECK_GL_ERROR(_orig_fastpath_glVertexAttribPointer(i,
1580                                        newctx->gl_vertex_array_size[i],
1581                                        newctx->gl_vertex_array_type[i],
1582                                        newctx->gl_vertex_array_normalized[i],
1583                                        newctx->gl_vertex_array_stride[i],
1584                                        newctx->gl_vertex_array_pointer[i]))
1585
1586                         STATES_COMPARE(gl_vertex_attrib_value + 4 * i, 4 * sizeof(GLfloat))
1587                         {
1588                                 CHECK_GL_ERROR(_orig_fastpath_glVertexAttrib4fv(i, &newctx->gl_vertex_attrib_value[4 * i]))
1589                         }
1590
1591                         if (newctx->gl_vertex_array_enabled[i] == GL_TRUE)
1592                         {
1593                                 CHECK_GL_ERROR(_orig_fastpath_glEnableVertexAttribArray(i))
1594                         }
1595                         else
1596                         {
1597                                 CHECK_GL_ERROR(_orig_fastpath_glDisableVertexAttribArray(i))
1598                         }
1599                 }
1600
1601                 STATE_COMPARE(gl_array_buffer_binding[0])
1602                 {
1603                         CHECK_GL_ERROR(_orig_fastpath_glBindBuffer(GL_ARRAY_BUFFER, newctx->gl_array_buffer_binding[0]))
1604                 }
1605                 STATE_COMPARE(gl_element_array_buffer_binding[0])
1606                 {
1607                         CHECK_GL_ERROR(_orig_fastpath_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, newctx->gl_element_array_buffer_binding[0]))
1608                 }
1609
1610         }
1611
1612 #ifdef COREGL_USE_MODULE_TRACEPATH
1613         tracepath_api_trace_end("eglMakeCurrent(FP vertex attrib)", trace_hint_vertex_attrib, 0);
1614 #endif // COREGL_USE_MODULE_TRACEPATH
1615
1616         ret = 1;
1617         goto finish;
1618
1619 finish:
1620
1621 #ifdef COREGL_FASTPATH_TRACE_STATE_INFO
1622         if (unlikely(trace_state_flag == 1))
1623                 fastpath_dump_context_states(newctx, 0);
1624 #endif // COREGL_FASTPATH_TRACE_STATE_INFO
1625         return ret;
1626 #undef STATE_COMPARE
1627 #undef STATES_COMPARE
1628 }
1629