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