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