GLE2RICE: Some fixes from muppen64plus-ae
[mupen64plus-pandora.git] / source / gles2rice / src / OGLES2FragmentShaders.cpp
1 /*
2 Copyright (C) 2003 Rice1964
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17 */
18
19 #include "OGLDebug.h"
20 #include "OGLES2FragmentShaders.h"
21 #include "OGLRender.h"
22 #include "OGLGraphicsContext.h"
23 #include "OGLTexture.h"
24
25 #define ALPHA_TEST "    if(gl_FragColor.a < AlphaRef) discard;                        \n"
26 //#define ALPHA_TEST
27 #define ENABLE  true
28 #define DISABLE  false
29
30 GLuint vertexProgram = 9999;
31 const char *vertexShader =
32 "#version " GLSL_VERSION "\n"
33 "attribute mediump vec4 aPosition;                          \n"\
34 "attribute lowp vec4    aColor;                             \n"\
35 "attribute lowp vec2    aTexCoord0;                         \n"\
36 "attribute lowp vec2    aTexCoord1;                         \n"\
37 "attribute lowp vec2    aAtlasTransform;                    \n"\
38 "                                                           \n"\
39 "varying lowp float vFactor;                                \n"\
40 "varying lowp vec4  vShadeColor;                            \n"\
41 "varying mediump vec2 vTexCoord0;                           \n"\
42 "varying lowp vec2    vTexCoord1;                           \n"\
43 "varying lowp float   vFog;                                 \n"\
44 "                                                           \n"\
45 "void main()                                                \n"\
46 "{                                                          \n"\
47 "gl_Position = aPosition; //gl_Position.z = max(0.0,gl_Position.z);                                  \n"\
48 "vShadeColor = aColor;                                      \n"\
49 "vTexCoord0 = aTexCoord0;                                   \n"\
50 "vTexCoord1 = aTexCoord1;                                   \n"\
51 "                                                           \n"\
52 "}                                                          \n"\
53 "                                                           \n";
54
55 const char *fragmentHeader =
56 "#define saturate(x) clamp( x, 0.0, 1.0 )                   \n"\
57 "precision lowp float;                                      \n"\
58 "#ifdef NEED_TEX0                                           \n"\
59 "uniform sampler2D uTex0;                                   \n"\
60 "#endif                                                     \n"\
61 "                                                           \n"\
62 "#ifdef NEED_TEX1                                           \n"\
63 "uniform sampler2D uTex1;                                   \n"\
64 "#endif                                                     \n"\
65 "                                                           \n"\
66 "uniform vec4 EnvColor;                                     \n"\
67 "uniform vec4 PrimColor;                                    \n"\
68 "uniform vec4 EnvFrac;                                      \n"\
69 "uniform vec4 PrimFrac;                                     \n"\
70 "uniform float AlphaRef;                                    \n"\
71 "uniform vec4 FogColor;                                     \n"\
72 "uniform vec2  FogMinMax;                                   \n"\
73 "                                                           \n"\
74 "varying lowp float vFactor;                                \n"\
75 "varying lowp vec4  vShadeColor;                            \n"\
76 "varying mediump vec2  vTexCoord0;                          \n"\
77 "varying lowp vec2  vTexCoord1;                             \n"\
78 "                                                           \n"\
79 "void main()                                                \n"\
80 "{                                                          \n"\
81 "vec4 comb,comb2;                                           \n"\
82 "                                                           \n"\
83 "#ifdef NEED_TEX0                                              \n"\
84 "vec4 t0 = texture2D(uTex0,vTexCoord0);                     \n"\
85 "#endif                                                     \n"\
86 "                                                           \n"\
87 "#ifdef NEED_TEX1                                           \n"\
88 "vec4 t1 = texture2D(uTex1,vTexCoord1);                     \n"\
89 "#endif                                                     \n";
90
91 const char *fragmentFooter =
92 "                                                           \n"\
93 "#ifdef FOG                                                 \n"\
94 "   float z = gl_FragCoord.z * 2.0 - 1.0;                                   \n"\
95 "   float FogFactor = (FogMinMax[1] - z) / (FogMinMax[1] - FogMinMax[0]);   \n"\
96 "   FogFactor = clamp(FogFactor, 0.0, 1.0);                                 \n"\
97 "                                                                           \n"\
98 "   gl_FragColor.rgb = mix(FogColor.rgb, comb.rgb, FogFactor );             \n"\
99 "   gl_FragColor.a = comb.a;                                                \n"\
100 "#else                                                                      \n"\
101 "   gl_FragColor = comb;                                                    \n"\
102 "#endif                                                                     \n"\
103 "                                                                           \n"\
104 "#ifdef ALPHA_TEST                                                          \n"\
105    ALPHA_TEST                                                                  
106 "#endif                                                                     \n"\
107 "}                                                          \n";
108
109 //Fragment shader for InitCycleCopy
110 const char *fragmentCopy =
111 "#version " GLSL_VERSION "\n"\
112 "precision lowp float;                                      \n"\
113 "uniform sampler2D uTex0;                                   \n"\
114 "uniform float AlphaRef;                                    \n"\
115 "varying lowp vec2 vTexCoord0;                              \n"\
116 "void main()                                                \n"\
117 "{                                                          \n"\
118 "   gl_FragColor = texture2D(uTex0,vTexCoord0).bgra;        \n"\
119 ALPHA_TEST
120 "}";
121
122 GLuint copyProgram,copyAlphaLocation;
123
124 //Fragment shader for InitCycleFill
125 const char *fragmentFill =
126 "#version " GLSL_VERSION "\n"\
127 "precision lowp float;                                      \n"
128 "uniform vec4 uColor;                                       \n"
129 "void main()                                                \n"
130 "{                                                          \n"
131 "   gl_FragColor = uColor;                                  \n"
132 "}";
133
134 GLuint fillProgram,fillColorLocation;
135
136 COGLFragmentShaderCombiner::COGLFragmentShaderCombiner(CRender *pRender)
137 : COGLColorCombiner(pRender)
138 {
139     m_bShaderIsSupported = true;
140 }
141 COGLFragmentShaderCombiner::~COGLFragmentShaderCombiner()
142 {
143 }
144
145 bool COGLFragmentShaderCombiner::Initialize(void)
146 {
147     if( !COGLColorCombiner::Initialize() )
148         return false;
149
150     COGLGraphicsContext *pcontext = (COGLGraphicsContext *)(CGraphicsContext::g_pGraphicsContext);
151 //    if( pcontext->IsExtensionSupported("GL_fragment_shader") )
152 //    {
153         m_bShaderIsSupported = true;
154 //    }
155
156     return true;
157 }
158
159 void COGLFragmentShaderCombiner::InitCombinerCycle12(void)
160 {
161 }
162 void COGLFragmentShaderCombiner::DisableCombiner(void)
163 {
164     COGLColorCombiner::DisableCombiner();
165 }
166
167 void COGLFragmentShaderCombiner::InitCombinerCycleCopy(void)
168 {
169     COGLColorCombiner::InitCombinerCycleCopy();
170 }
171
172 void COGLFragmentShaderCombiner::InitCombinerCycleFill(void)
173 {
174     COGLColorCombiner::InitCombinerCycleFill();
175 }
176 void COGLFragmentShaderCombiner::InitCombinerBlenderForSimpleTextureDraw(uint32 tile)
177 {
178     COGLColorCombiner::InitCombinerBlenderForSimpleTextureDraw(tile);
179 }
180
181 #ifdef DEBUGGER
182 void COGLFragmentShaderCombiner::DisplaySimpleMuxString(void)
183 {
184     COGLColorCombiner::DisplaySimpleMuxString();
185 }
186 #endif
187
188
189
190 COGL_FragmentProgramCombiner::COGL_FragmentProgramCombiner(CRender *pRender)
191 : COGLColorCombiner4(pRender)
192 {
193     delete m_pDecodedMux;
194     m_pDecodedMux = new DecodedMuxForPixelShader;
195     m_bFragmentProgramIsSupported = true;
196     m_AlphaRef = 0.0f;
197     bAlphaTestState = DISABLE;
198     bAlphaTestPreviousState = DISABLE;
199     bFogState = DISABLE;
200     bFogPreviousState = DISABLE;
201
202     //Create shaders for fill and copy
203     GLint success;
204     GLuint vs,fs;
205     copyProgram = glCreateProgram();
206     vs = glCreateShader(GL_VERTEX_SHADER);
207     glShaderSource(vs,1,&vertexShader,NULL);
208     glCompileShader(vs);
209
210     glGetShaderiv(vs,GL_COMPILE_STATUS,&success);
211     if(!success)
212     {
213         char log[1024];
214         glGetShaderInfoLog(vs,1024,NULL,log);
215         printf("%s\n",log);
216     }
217
218     fs = glCreateShader(GL_FRAGMENT_SHADER);
219     glShaderSource(fs,1,&fragmentCopy,NULL);
220     glCompileShader(fs);
221
222     glGetShaderiv(fs,GL_COMPILE_STATUS,&success);
223     if(!success)
224     {
225         char log[1024];
226         glGetShaderInfoLog(fs,1024,NULL,log);
227         printf("%s\n",log);
228     }
229
230     glAttachShader(copyProgram,vs);
231     glAttachShader(copyProgram,fs);
232
233     glBindAttribLocation(copyProgram,VS_TEXCOORD0,"aTexCoord0");
234     OPENGL_CHECK_ERRORS;
235     glBindAttribLocation(copyProgram,VS_POSITION,"aPosition");
236     OPENGL_CHECK_ERRORS;
237
238     glLinkProgram(copyProgram);
239     copyAlphaLocation = glGetUniformLocation(copyProgram,"AlphaRef");
240     glGetProgramiv(copyProgram,GL_LINK_STATUS,&success);
241     if(!success)
242     {
243         char log[1024];
244         glGetProgramInfoLog(copyProgram,1024,NULL,log);
245         printf("%s\n",log);
246     }
247
248     glDeleteShader(fs);
249
250     //Fill shader
251     fs = glCreateShader(GL_FRAGMENT_SHADER);
252     glShaderSource(fs,1,&fragmentFill,NULL);
253     glCompileShader(fs);
254
255     glGetShaderiv(fs,GL_COMPILE_STATUS,&success);
256     if(!success)
257     {
258         char log[1024];
259         glGetShaderInfoLog(fs,1024,NULL,log);
260         printf("%s\n",log);
261     }
262
263     fillProgram = glCreateProgram();
264     glAttachShader(fillProgram,vs);
265     glAttachShader(fillProgram,fs);
266
267     glBindAttribLocation(fillProgram,VS_POSITION,"aPosition");
268     OPENGL_CHECK_ERRORS;
269
270     glLinkProgram(fillProgram);
271
272
273     fillColorLocation = glGetUniformLocation(fillProgram,"uColor");
274
275     glDeleteShader(fs);
276     glDeleteShader(vs);
277 }
278 COGL_FragmentProgramCombiner::~COGL_FragmentProgramCombiner()
279 {
280     int size = m_vCompiledShaders.size();
281     for (int i=0; i<size; i++)
282     {
283         GLuint ID = m_vCompiledShaders[i].programID;
284         glDeleteProgram(ID);
285
286         OPENGL_CHECK_ERRORS;
287         m_vCompiledShaders[i].programID = 0;
288     }
289
290     m_vCompiledShaders.clear();
291 }
292
293 bool COGL_FragmentProgramCombiner::Initialize(void)
294 {
295     if( !COGLColorCombiner4::Initialize() )
296         return false;
297
298     COGLGraphicsContext *pcontext = (COGLGraphicsContext *)(CGraphicsContext::g_pGraphicsContext);
299 //    if( pcontext->IsExtensionSupported("GL_fragment_program") )
300 //    {
301         m_bFragmentProgramIsSupported = true;
302 //    }
303
304     return true;
305 }
306
307
308
309 void COGL_FragmentProgramCombiner::DisableCombiner(void)
310 {
311     //glDisable(GL_FRAGMENT_PROGRAM);
312     //OPENGL_CHECK_ERRORS;
313     COGLColorCombiner4::DisableCombiner();
314 }
315
316 void COGL_FragmentProgramCombiner::InitCombinerCycleCopy(void)
317 {
318     m_pOGLRender->DisableMultiTexture();
319     m_pOGLRender->EnableTexUnit(0,TRUE);
320     glUseProgram(copyProgram);
321     glUniform1f(copyAlphaLocation,m_AlphaRef);
322     OPENGL_CHECK_ERRORS;
323     glEnableVertexAttribArray(VS_POSITION);
324     OPENGL_CHECK_ERRORS;
325     glEnableVertexAttribArray(VS_TEXCOORD0);
326     OPENGL_CHECK_ERRORS;
327     glDisableVertexAttribArray(VS_COLOR);
328     OPENGL_CHECK_ERRORS;
329     glDisableVertexAttribArray(VS_TEXCOORD1);
330     OPENGL_CHECK_ERRORS;
331     COGLTexture* pTexture = g_textures[gRSP.curTile].m_pCOGLTexture;
332     if( pTexture )
333     {
334         m_pOGLRender->BindTexture(pTexture->m_dwTextureName, 0);
335         m_pOGLRender->SetTexelRepeatFlags(gRSP.curTile);
336     }
337 }
338
339 void COGL_FragmentProgramCombiner::InitCombinerCycleFill(void)
340 {
341     glUseProgram(fillProgram);
342     glUniform4f(fillColorLocation,((gRDP.fillColor>>16)&0xFF)/255.0f,((gRDP.fillColor>>8)&0xFF)/255.0f,((gRDP.fillColor)&0xFF)/255.0f,((gRDP.fillColor>>24)&0xFF)/255.0f);
343     OPENGL_CHECK_ERRORS;
344 }
345
346 #ifdef BGR_SHADER
347 const char *muxToFP_Maps[][2] = {
348 //color -- alpha
349 {"vec3(0.0)", "0.0"},                      //MUX_0 = 0,
350 {"vec3(1.0)", "1.0"},                      //MUX_1,
351 {"comb.rgb", "comb.a"},                    //MUX_COMBINED,
352 {"t0.rgb", "t0.a"},                        //MUX_TEXEL0,
353 {"t1.rgb", "t1.a"},                        //MUX_TEXEL1,
354 {"PrimColor.rgb", "PrimColor.a"},          //MUX_PRIM,
355 {"vShadeColor.rgb", "vShadeColor.a"},      //MUX_SHADE,
356 {"EnvColor.rgb", "EnvColor.a"},            //MUX_ENV,
357 {"comb.rgb", "comb.a"},                    //MUX_COMBALPHA,
358 {"t0.rgb", "t0.a"},                        //MUX_T0_ALPHA,
359 {"t1.rgb", "t1.a"},                        //MUX_T1_ALPHA,
360 {"PrimColor.rgb", "PrimColor.a"},          //MUX_PRIM_ALPHA,
361 {"vShadeColor.rgb", "vShadeColor.a"},      //MUX_SHADE_ALPHA,
362 {"EnvColor.rgb", "EnvColor.a"},            //MUX_ENV_ALPHA,
363 {"EnvFrac.a", "EnvFrac.a"},                //MUX_LODFRAC,
364 {"PrimFrac.a", "PrimFrac.a"},              //MUX_PRIMLODFRAC,
365 {"vec3(1.0)", "1.0"},                      //MUX_K5,
366 {"vec3(1.0)", "1.0"},                      //MUX_UNK,  // Should not be used
367 };
368 #else
369 const char *muxToFP_Maps[][2] = {
370 //color -- alpha
371 {"vec3(0.0)", "0.0"}, //MUX_0 = 0,
372 {"vec3(1.0)", "1.0"}, //MUX_1,
373 {"comb.rgb", "comb.a"}, //MUX_COMBINED,
374 {"t0.bgr", "t0.a"}, //MUX_TEXEL0,
375 {"t1.bgr", "t1.a"}, //MUX_TEXEL1,
376 {"PrimColor.rgb", "PrimColor.a"}, //MUX_PRIM,
377 {"vShadeColor.rgb", "vShadeColor.a"}, //MUX_SHADE,
378 {"EnvColor.rgb", "EnvColor.a"}, //MUX_ENV,
379 {"comb.rgb", "comb.a"}, //MUX_COMBALPHA,
380 {"t0.bgr", "t0.a"}, //MUX_T0_ALPHA,
381 {"t1.bgr", "t1.a"}, //MUX_T1_ALPHA,
382 {"PrimColor.rgb", "PrimColor.a"}, //MUX_PRIM_ALPHA,
383 {"vShadeColor.rgb", "vShadeColor.a"}, //MUX_SHADE_ALPHA,
384 {"EnvColor.rgb", "EnvColor.a"}, //MUX_ENV_ALPHA,
385 {"EnvFrac.a", "EnvFrac.a"}, //MUX_LODFRAC,
386 {"PrimFrac.a", "PrimFrac.a"}, //MUX_PRIMLODFRAC,
387 {"vec3(1.0)", "1.0"}, //MUX_K5,
388 {"vec3(1.0)", "1.0"}, //MUX_UNK,  // Should not be used
389 };
390 #endif
391
392
393 char oglNewFP[4092];
394
395 char* MuxToOC(uint8 val)
396 {
397 // For color channel
398 if( val&MUX_ALPHAREPLICATE )
399     return (char*)muxToFP_Maps[val&0x1F][1];
400 else
401     return (char*)muxToFP_Maps[val&0x1F][0];
402 }
403
404 char* MuxToOA(uint8 val)
405 {
406 // For alpha channel
407 return (char*)muxToFP_Maps[val&0x1F][1];
408 }
409
410 static void CheckFpVars(uint8 MuxVar, bool &bNeedT0, bool &bNeedT1)
411 {
412     MuxVar &= 0x1f;
413     if (MuxVar == MUX_TEXEL0 || MuxVar == MUX_T0_ALPHA)
414         bNeedT0 = true;
415     if (MuxVar == MUX_TEXEL1 || MuxVar == MUX_T1_ALPHA)
416         bNeedT1 = true;
417 }
418
419 void COGL_FragmentProgramCombiner::GenerateProgramStr()
420 {
421     DecodedMuxForPixelShader &mux = *(DecodedMuxForPixelShader*)m_pDecodedMux;
422
423     mux.splitType[0] = mux.splitType[1] = mux.splitType[2] = mux.splitType[3] = CM_FMT_TYPE_NOT_CHECKED;
424     m_pDecodedMux->Reformat(false);
425
426     char tempstr[500], newFPBody[4092];
427     bool bNeedT0 = false, bNeedT1 = false, bNeedComb2 = false;
428     newFPBody[0] = 0;
429
430     for( int cycle=0; cycle<2; cycle++ )
431     {
432         for( int channel=0; channel<2; channel++)
433         {
434             char* (*func)(uint8) = channel==0?MuxToOC:MuxToOA;
435             char *dst = channel==0?(char*)"rgb":(char*)"a";
436             N64CombinerType &m = mux.m_n64Combiners[cycle*2+channel];
437             switch( mux.splitType[cycle*2+channel] )
438             {
439             case CM_FMT_TYPE_NOT_USED:
440                 tempstr[0] = 0;
441                 break;
442             case CM_FMT_TYPE_D:
443                 sprintf(tempstr, "comb.%s = %s;\n", dst, func(m.d));
444                 CheckFpVars(m.d, bNeedT0, bNeedT1);
445                 break;
446             case CM_FMT_TYPE_A_MOD_C:
447                 sprintf(tempstr, "comb.%s = %s * %s;\n", dst, func(m.a), func(m.c));
448                 CheckFpVars(m.a, bNeedT0, bNeedT1);
449                 CheckFpVars(m.c, bNeedT0, bNeedT1);
450                 break;
451             case CM_FMT_TYPE_A_ADD_D:
452                 sprintf(tempstr, "comb.%s = saturate(%s + %s);\n", dst, func(m.a), func(m.d));
453                 CheckFpVars(m.a, bNeedT0, bNeedT1);
454                 CheckFpVars(m.d, bNeedT0, bNeedT1);
455                 break;
456             case CM_FMT_TYPE_A_SUB_B:
457                 sprintf(tempstr, "comb.%s = %s - %s;\n", dst, func(m.a), func(m.b));
458                 CheckFpVars(m.a, bNeedT0, bNeedT1);
459                 CheckFpVars(m.b, bNeedT0, bNeedT1);
460                 break;
461             case CM_FMT_TYPE_A_MOD_C_ADD_D:
462                 sprintf(tempstr, "comb.%s = saturate(%s * %s + %s);\n", dst, func(m.a), func(m.c),func(m.d));
463                 CheckFpVars(m.a, bNeedT0, bNeedT1);
464                 CheckFpVars(m.c, bNeedT0, bNeedT1);
465                 CheckFpVars(m.d, bNeedT0, bNeedT1);
466                 break;
467             case CM_FMT_TYPE_A_LERP_B_C:
468                 //ARB ASM LERP and mix have different parameter ordering.
469                 //sprintf(tempstr, "comb.%s = saturate(mix(%s, %s, %s));\n", dst,func(m.a),func(m.b), func(m.c));
470                 sprintf(tempstr, "comb.%s = (%s - %s) * %s + %s;\n", dst,func(m.a),func(m.b), func(m.c),func(m.b));
471                 CheckFpVars(m.a, bNeedT0, bNeedT1);
472                 CheckFpVars(m.b, bNeedT0, bNeedT1);
473                 CheckFpVars(m.c, bNeedT0, bNeedT1);
474                 //sprintf(tempstr, "SUB comb.%s, %s, %s;\nMAD_SAT comb.%s, comb, %s, %s;\n", dst, func(m.a), func(m.b), dst, func(m.c), func(m.b));
475                 break;
476             default:
477                 sprintf(tempstr, "comb2.%s = %s - %s;\ncomb.%s = saturate(comb2.%s * %s + %s);\n", dst, func(m.a), func(m.b),  dst,dst, func(m.c),func(m.d));
478                 CheckFpVars(m.a, bNeedT0, bNeedT1);
479                 CheckFpVars(m.b, bNeedT0, bNeedT1);
480                 CheckFpVars(m.c, bNeedT0, bNeedT1);
481                 CheckFpVars(m.d, bNeedT0, bNeedT1);
482                 bNeedComb2 = true;
483                 break;
484             }
485             strcat(newFPBody, tempstr);
486         }
487     }
488
489     oglNewFP[0] = 0;
490     if (bNeedT0)
491         strcat(oglNewFP, "#define NEED_TEX0\n");
492     if (bNeedT1)
493         strcat(oglNewFP, "#define NEED_TEX1\n");
494     strcat(oglNewFP, fragmentHeader);
495     strcat(oglNewFP, newFPBody);
496     strcat(oglNewFP, fragmentFooter);
497
498 }
499
500 int COGL_FragmentProgramCombiner::ParseDecodedMux()
501 {
502     if( !m_bFragmentProgramIsSupported )
503         return COGLColorCombiner4::ParseDecodedMux();
504
505     OGLShaderCombinerSaveType res;
506     GLint success;
507
508     if(vertexProgram == 9999)
509     {
510         vertexProgram = res.vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
511         glShaderSource(res.vertexShaderID, 1, &vertexShader,NULL);
512         OPENGL_CHECK_ERRORS;
513         glCompileShader(res.vertexShaderID);
514         OPENGL_CHECK_ERRORS;
515     }
516     else
517     {
518         res.vertexShaderID = vertexProgram;
519     }
520
521
522     //Create 4 shaders, with and without alphatest + with and without fog
523     GenerateProgramStr();
524
525     for(int alphaTest = 0;alphaTest < 2;alphaTest++)
526     {
527                 for(int fog = 0;fog < 2;fog++) {
528                         res.fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
529
530                         char* tmpShader = (char*)malloc(sizeof(char) * 4096);
531                         strcpy(tmpShader,"#version " GLSL_VERSION "\n");
532
533                         if(alphaTest == 1)
534                         {
535                                 strcat(tmpShader,"#define ALPHA_TEST\n");
536                         }
537                         if(fog == 1)
538                         {
539                                 strcat(tmpShader,"#define FOG\n");
540                         }
541
542                         res.fogIsUsed = fog == 1;
543                         res.alphaTest = alphaTest == 1;
544                         strcat(tmpShader,oglNewFP);
545
546                         glShaderSource(res.fragmentShaderID, 1,(const char**) &tmpShader,NULL);
547                         free(tmpShader);
548
549
550                         OPENGL_CHECK_ERRORS;
551                         glCompileShader(res.fragmentShaderID);
552
553                         glGetShaderiv(res.fragmentShaderID, GL_COMPILE_STATUS, &success);
554                         if (!success)
555                         {
556                                 char Log[1024];
557                                 GLint nLength;
558                                 glGetShaderInfoLog(res.fragmentShaderID, 1024, &nLength, Log);
559                                 printf("Error compiling shader!\n %s",oglNewFP);
560                                 printf("%s", Log);
561                         }
562
563                         res.programID = glCreateProgram();
564                         glAttachShader(res.programID,res.vertexShaderID);
565                         glAttachShader(res.programID,res.fragmentShaderID);
566
567                         //Bind Attributes
568                         glBindAttribLocation(res.programID,VS_COLOR,"aColor");
569                         OPENGL_CHECK_ERRORS;
570                         glBindAttribLocation(res.programID,VS_TEXCOORD0,"aTexCoord0");
571                         OPENGL_CHECK_ERRORS;
572                         glBindAttribLocation(res.programID,VS_TEXCOORD1,"aTexCoord1");
573                         OPENGL_CHECK_ERRORS;
574                         glBindAttribLocation(res.programID,VS_POSITION,"aPosition");
575                         OPENGL_CHECK_ERRORS;
576
577                         glLinkProgram(res.programID);
578                         OPENGL_CHECK_ERRORS;
579
580                         glGetProgramiv(res.programID, GL_LINK_STATUS, &success);
581                         if (!success)
582                         {
583                                 char Log[1024];
584                                 GLint nLength;
585                                 glGetShaderInfoLog(res.fragmentShaderID, 1024, &nLength, Log);
586                                 printf("Error linking program!\n");
587                                 printf("%s\n",Log);
588                         }
589
590                         glUseProgram(res.programID);
591                         OPENGL_CHECK_ERRORS;
592
593                         //Bind texture samplers
594                         GLint tex0 = glGetUniformLocation(res.programID,"uTex0");
595                         GLint tex1 = glGetUniformLocation(res.programID,"uTex1");
596
597                         if(tex0 != -1)
598                                 glUniform1i(tex0,0);
599                         if(tex1 != -1)
600                                 glUniform1i(tex1,1);
601
602                         //Bind Uniforms
603                         res.PrimColorLocation = glGetUniformLocation(res.programID,"PrimColor");
604                         OPENGL_CHECK_ERRORS;
605                         res.EnvColorLocation = glGetUniformLocation(res.programID,"EnvColor");
606                         OPENGL_CHECK_ERRORS;
607                         res.PrimFracLocation = glGetUniformLocation(res.programID,"PrimFrac");
608                         OPENGL_CHECK_ERRORS;
609                         res.EnvFracLocation = glGetUniformLocation(res.programID,"EnvFrac");
610                         OPENGL_CHECK_ERRORS;
611                         res.AlphaRefLocation = glGetUniformLocation(res.programID,"AlphaRef");
612                         OPENGL_CHECK_ERRORS;
613                         res.FogColorLocation = glGetUniformLocation(res.programID,"FogColor");
614                         OPENGL_CHECK_ERRORS;
615                         res.FogMinMaxLocation = glGetUniformLocation(res.programID,"FogMinMax");
616                         OPENGL_CHECK_ERRORS;
617
618                         res.dwMux0 = m_pDecodedMux->m_dwMux0;
619                         res.dwMux1 = m_pDecodedMux->m_dwMux1;
620
621                         m_vCompiledShaders.push_back(res);
622                 }
623     }
624     m_lastIndex = m_vCompiledShaders.size()-4;
625
626     return m_lastIndex;
627 }
628
629 void COGL_FragmentProgramCombiner::GenerateCombinerSetting(int index)
630 {
631     GLuint ID = m_vCompiledShaders[index].programID;
632
633     glUseProgram(ID);
634     glEnableVertexAttribArray(VS_POSITION);
635     OPENGL_CHECK_ERRORS;
636     glVertexAttribPointer(VS_POSITION,4,GL_FLOAT,GL_FALSE,sizeof(float)*5,&(g_vtxProjected5[0][0]));
637     OPENGL_CHECK_ERRORS;
638
639     glEnableVertexAttribArray(VS_TEXCOORD0);
640     OPENGL_CHECK_ERRORS;
641     glVertexAttribPointer(VS_TEXCOORD0,2,GL_FLOAT,GL_FALSE, sizeof( TLITVERTEX ), &(g_vtxBuffer[0].tcord[0].u));
642     OPENGL_CHECK_ERRORS;
643
644     glEnableVertexAttribArray(VS_TEXCOORD1);
645     OPENGL_CHECK_ERRORS;
646     glVertexAttribPointer(VS_TEXCOORD1,2,GL_FLOAT,GL_FALSE, sizeof( TLITVERTEX ), &(g_vtxBuffer[0].tcord[1].u));
647     OPENGL_CHECK_ERRORS;
648
649     glEnableVertexAttribArray(VS_COLOR);
650     OPENGL_CHECK_ERRORS;
651     glVertexAttribPointer(VS_COLOR, 4, GL_UNSIGNED_BYTE,GL_TRUE, sizeof(uint8)*4, &(g_oglVtxColors[0][0]) );
652     OPENGL_CHECK_ERRORS;
653 }
654
655 void COGL_FragmentProgramCombiner::GenerateCombinerSettingConstants(int index)
656 {
657     OGLShaderCombinerSaveType prog = m_vCompiledShaders[index];
658
659     glUseProgram(prog.programID);
660     float *pf;
661     if(prog.EnvColorLocation != -1)
662     {
663         pf = GetEnvColorfv();
664         glUniform4fv(prog.EnvColorLocation,1, pf);
665         OPENGL_CHECK_ERRORS;
666     }
667
668     if(prog.PrimColorLocation != -1)
669     {
670         pf = GetPrimitiveColorfv();
671         glUniform4fv(prog.PrimColorLocation,1, pf);
672         OPENGL_CHECK_ERRORS;
673     }
674
675     if(prog.EnvFracLocation != -1)
676     {
677         float frac = gRDP.LODFrac / 255.0f;
678         float tempf[4] = {frac,frac,frac,frac};
679         glUniform4fv(prog.EnvFracLocation,1, tempf);
680         OPENGL_CHECK_ERRORS;
681     }
682
683     if(prog.PrimFracLocation != -1)
684     {
685         float frac2 = gRDP.primLODFrac / 255.0f;
686         float tempf2[4] = {frac2,frac2,frac2,frac2};
687         glUniform4fv(prog.PrimFracLocation,1, tempf2);
688         OPENGL_CHECK_ERRORS;
689     }
690
691         if(prog.FogColorLocation != -1)
692     {
693         glUniform4f(prog.FogColorLocation, gRDP.fvFogColor[0],gRDP.fvFogColor[1],gRDP.fvFogColor[2], gRDP.fvFogColor[3]);
694         OPENGL_CHECK_ERRORS;
695     }
696         
697         if(prog.FogMinMaxLocation != -1)        
698         {
699         glUniform2f(prog.FogMinMaxLocation,gRSPfFogMin,gRSPfFogMax);
700         OPENGL_CHECK_ERRORS;
701     }
702         
703     if(prog.AlphaRefLocation != -1)
704         {
705         glUniform1f(prog.AlphaRefLocation,m_AlphaRef);
706                 OPENGL_CHECK_ERRORS;
707         }
708 }
709
710 int COGL_FragmentProgramCombiner::FindCompiledMux()
711 {
712 #ifdef DEBUGGER
713     if( debuggerDropCombiners )
714     {
715         m_vCompiledShaders.clear();
716         //m_dwLastMux0 = m_dwLastMux1 = 0;
717         debuggerDropCombiners = false;
718     }
719 #endif
720     for( uint32 i=0; i<m_vCompiledShaders.size(); i++ )
721     {
722         if( m_vCompiledShaders[i].dwMux0 == m_pDecodedMux->m_dwMux0 
723             && m_vCompiledShaders[i].dwMux1 == m_pDecodedMux->m_dwMux1 
724             && m_vCompiledShaders[i].fogIsUsed == bFogState
725             && m_vCompiledShaders[i].alphaTest == bAlphaTestState)
726         {
727             return (int)i;
728         }
729     }
730
731     return -1;
732 }
733
734 //////////////////////////////////////////////////////////////////////////
735 void COGL_FragmentProgramCombiner::InitCombinerCycle12(void)
736 {
737     if( !m_bFragmentProgramIsSupported )    
738     {
739         COGLColorCombiner4::InitCombinerCycle12();
740         return;
741     }
742
743 #ifdef DEBUGGER
744     if( debuggerDropCombiners )
745     {
746         UpdateCombiner(m_pDecodedMux->m_dwMux0,m_pDecodedMux->m_dwMux1);
747         m_vCompiledShaders.clear();
748         m_dwLastMux0 = m_dwLastMux1 = 0;
749         debuggerDropCombiners = false;
750     }
751 #endif
752
753     m_pOGLRender->EnableMultiTexture();
754
755     bool combinerIsChanged = false;
756
757     if( m_pDecodedMux->m_dwMux0 != m_dwLastMux0 || m_pDecodedMux->m_dwMux1 != m_dwLastMux1 
758           || bAlphaTestState != bAlphaTestPreviousState || bFogState != bFogPreviousState || m_lastIndex < 0 )
759     {
760         combinerIsChanged = true;
761         m_lastIndex = FindCompiledMux();
762         if( m_lastIndex < 0 )       // Can not found
763         {
764             m_lastIndex = ParseDecodedMux();
765         }
766
767         m_dwLastMux0 = m_pDecodedMux->m_dwMux0;
768         m_dwLastMux1 = m_pDecodedMux->m_dwMux1;
769         bAlphaTestPreviousState = bAlphaTestState;
770         bFogPreviousState = bFogState;
771         m_AlphaRef = (float)(m_pOGLRender->m_dwAlpha)/255.0f;    
772         }
773
774
775     GenerateCombinerSettingConstants(m_lastIndex);
776     if( m_bCycleChanged || combinerIsChanged || gRDP.texturesAreReloaded || gRDP.colorsAreReloaded )
777     {
778         if( m_bCycleChanged || combinerIsChanged )
779         {
780             GenerateCombinerSettingConstants(m_lastIndex);
781             GenerateCombinerSetting(m_lastIndex);
782         }
783         else if( gRDP.colorsAreReloaded )
784         {
785             GenerateCombinerSettingConstants(m_lastIndex);
786         }
787
788         m_pOGLRender->SetAllTexelRepeatFlag();
789
790         gRDP.colorsAreReloaded = false;
791         gRDP.texturesAreReloaded = false;
792     }
793     else
794     {
795         m_pOGLRender->SetAllTexelRepeatFlag();
796     }
797 }
798
799 #ifdef DEBUGGER
800 void COGL_FragmentProgramCombiner::DisplaySimpleMuxString(void)
801 {
802     COGLColorCombiner::DisplaySimpleMuxString();
803     DecodedMuxForPixelShader &mux = *(DecodedMuxForPixelShader*)m_pDecodedMux;
804     mux.Reformat(false);
805     GenerateProgramStr();
806     //sprintf(oglNewFP, oglFP, 
807     //  MuxToOC(mux.aRGB0), MuxToOC(mux.bRGB0), MuxToOC(mux.cRGB0), MuxToOC(mux.dRGB0),
808     //  MuxToOA(mux.aA0), MuxToOA(mux.bA0), MuxToOA(mux.cA0), MuxToOA(mux.dA0),
809     //  MuxToOC(mux.aRGB1), MuxToOC(mux.bRGB1), MuxToOC(mux.cRGB1), MuxToOC(mux.dRGB1),
810     //  MuxToOA(mux.aA1), MuxToOA(mux.bA1), MuxToOA(mux.cA1), MuxToOA(mux.dA1)
811     //  );
812
813     TRACE0("OGL Fragment Program:");
814     TRACE0(oglNewFP);
815 }
816 #endif
817