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