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