Rice GLES2 (from mupen64plus-ae) plugin. Compile but doesn't works well on the OpenPa...
[mupen64plus-pandora.git] / source / gles2rice / src / OGLFragmentShaders.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 "OGLExtensions.h"
20 #include "OGLDebug.h"
21 #include "OGLFragmentShaders.h"
22 #include "OGLRender.h"
23 #include "OGLGraphicsContext.h"
24
25 COGLFragmentShaderCombiner::COGLFragmentShaderCombiner(CRender *pRender)
26 : COGLColorCombiner(pRender)
27 {
28     m_bShaderIsSupported = false;
29 }
30 COGLFragmentShaderCombiner::~COGLFragmentShaderCombiner()
31 {
32 }
33
34 bool COGLFragmentShaderCombiner::Initialize(void)
35 {
36     if( !COGLColorCombiner::Initialize() )
37         return false;
38
39     COGLGraphicsContext *pcontext = (COGLGraphicsContext *)(CGraphicsContext::g_pGraphicsContext);
40     if( pcontext->IsExtensionSupported("GL_ARB_fragment_shader") )
41     {
42         m_bShaderIsSupported = true;
43     }
44
45     return true;
46 }
47
48 void COGLFragmentShaderCombiner::InitCombinerCycle12(void)
49 {
50 }
51 void COGLFragmentShaderCombiner::DisableCombiner(void)
52 {
53     COGLColorCombiner::DisableCombiner();
54 }
55
56 void COGLFragmentShaderCombiner::InitCombinerCycleCopy(void)
57 {
58     COGLColorCombiner::InitCombinerCycleCopy();
59 }
60
61 void COGLFragmentShaderCombiner::InitCombinerCycleFill(void)
62 {
63     COGLColorCombiner::InitCombinerCycleFill();
64 }
65 void COGLFragmentShaderCombiner::InitCombinerBlenderForSimpleTextureDraw(uint32 tile)
66 {
67     COGLColorCombiner::InitCombinerBlenderForSimpleTextureDraw(tile);
68 }
69
70 #ifdef DEBUGGER
71 void COGLFragmentShaderCombiner::DisplaySimpleMuxString(void)
72 {
73     COGLColorCombiner::DisplaySimpleMuxString();
74 }
75 #endif
76
77
78
79 COGL_FragmentProgramCombiner::COGL_FragmentProgramCombiner(CRender *pRender)
80 : COGLColorCombiner4(pRender)
81 {
82     delete m_pDecodedMux;
83     m_pDecodedMux = new DecodedMuxForPixelShader;
84     m_bFragmentProgramIsSupported = false;
85 }
86 COGL_FragmentProgramCombiner::~COGL_FragmentProgramCombiner()
87 {
88     int size = m_vCompiledShaders.size();
89     for (int i=0; i<size; i++)
90     {
91         GLuint ID = m_vCompiledShaders[i].programID;
92         pglDeleteProgramsARB(1, &ID);
93         OPENGL_CHECK_ERRORS;
94         m_vCompiledShaders[i].programID = 0;
95     }
96
97     m_vCompiledShaders.clear();
98 }
99
100 bool COGL_FragmentProgramCombiner::Initialize(void)
101 {
102     if( !COGLColorCombiner4::Initialize() )
103         return false;
104
105     COGLGraphicsContext *pcontext = (COGLGraphicsContext *)(CGraphicsContext::g_pGraphicsContext);
106     if( pcontext->IsExtensionSupported("GL_ARB_fragment_program") )
107     {
108         m_bFragmentProgramIsSupported = true;
109     }
110
111     return true;
112 }
113
114
115
116 void COGL_FragmentProgramCombiner::DisableCombiner(void)
117 {
118     glDisable(GL_FRAGMENT_PROGRAM_ARB);
119     OPENGL_CHECK_ERRORS;
120     COGLColorCombiner4::DisableCombiner();
121 }
122
123 void COGL_FragmentProgramCombiner::InitCombinerCycleCopy(void)
124 {
125     glDisable(GL_FRAGMENT_PROGRAM_ARB);
126     OPENGL_CHECK_ERRORS;
127     COGLColorCombiner4::InitCombinerCycleCopy();
128 }
129
130 void COGL_FragmentProgramCombiner::InitCombinerCycleFill(void)
131 {
132     glDisable(GL_FRAGMENT_PROGRAM_ARB);
133     OPENGL_CHECK_ERRORS;
134     COGLColorCombiner4::InitCombinerCycleFill();
135 }
136
137 const char *muxToFP_Maps[][2] = {
138 //color -- alpha
139 {"0", "0"},                                //MUX_0 = 0,
140 {"1", "1"},                                //MUX_1,
141 {"comb", "comb.a"},                        //MUX_COMBINED,
142 {"t0", "t0.a"},                            //MUX_TEXEL0,
143 {"t1", "t1.a"},                            //MUX_TEXEL1,
144 {"program.env[2]", "program.env[2].a"},    //MUX_PRIM,
145 {"fragment.color", "fragment.color.a"},    //MUX_SHADE,
146 {"program.env[1]", "program.env[1].a"},    //MUX_ENV,
147 {"comb.a", "comb.a"},                      //MUX_COMBALPHA,
148 {"t0.a", "t0.a"},                          //MUX_T0_ALPHA,
149 {"t1.a", "t1.a"},                          //MUX_T1_ALPHA,
150 {"primcolor.a", "primcolor.a"},            //MUX_PRIM_ALPHA,
151 {"fragment.color.a", "fragment.color.a"},  //MUX_SHADE_ALPHA,
152 {"envcolor.a", "envcolor.a"},              //MUX_ENV_ALPHA,
153 {"program.env[3]", "program.env[3]"},      //MUX_LODFRAC,
154 {"program.env[4]", "program.env[4]"},      //MUX_PRIMLODFRAC,
155 {"1", "1"},                                //MUX_K5,
156 {"1", "1"},                                //MUX_UNK,  // Should not be used
157 };
158
159
160 const char *oglFPTest = 
161 "!!ARBfp1.0\n"
162 "#Declarations\n"
163 "TEMP t0;\n"
164 "TEMP t1;\n"
165 "TEMP comb;\n"
166 "TEMP comb2;\n"
167 "\n"
168 "ATTRIB coord0 = fragment.texcoord[0];\n"
169 "ATTRIB coord1 = fragment.texcoord[1];\n"
170 "ATTRIB shade = fragment.color;\n"
171 "ATTRIB fogfactor = fragment.fogcoord;\n"
172 "\n"
173 "OUTPUT out = result.color;\n"
174 "\n"
175 "#Instructions\n"
176 "TEX t0, coord0, texture[0], 2D;\n"
177 "TEX t1, coord1, texture[1], 2D;\n"
178 "\n"
179 "MAD_SAT out, t0, program.env[1],program.env[0];\n"
180 //"SUB comb.rgb,    t0, 0;\n"
181 //"MAD_SAT out.rgb, comb, program.env[1], 0;\n"
182 //"SUB comb.a,      t0, 0;\n"
183 //"MAD_SAT out.a,   comb, program.env[1], 0;\n"
184 "END\n";
185
186 char oglNewFP[4092];
187
188 char* MuxToOC(uint8 val)
189 {
190 // For color channel
191 if( val&MUX_ALPHAREPLICATE )
192     return (char*)muxToFP_Maps[val&0x1F][1];
193 else
194     return (char*)muxToFP_Maps[val&0x1F][0];
195 }
196
197 char* MuxToOA(uint8 val)
198 {
199 // For alpha channel
200 return (char*)muxToFP_Maps[val&0x1F][0];
201 }
202
203 static void CheckFpVars(uint8 MuxVar, bool &bNeedT0, bool &bNeedT1)
204 {
205     MuxVar &= 0x1f;
206     if (MuxVar == MUX_TEXEL0 || MuxVar == MUX_T0_ALPHA)
207         bNeedT0 = true;
208     if (MuxVar == MUX_TEXEL1 || MuxVar == MUX_T1_ALPHA)
209         bNeedT1 = true;
210 }
211
212 void COGL_FragmentProgramCombiner::GenerateProgramStr()
213 {
214     DecodedMuxForPixelShader &mux = *(DecodedMuxForPixelShader*)m_pDecodedMux;
215
216     mux.splitType[0] = mux.splitType[1] = mux.splitType[2] = mux.splitType[3] = CM_FMT_TYPE_NOT_CHECKED;
217     m_pDecodedMux->Reformat(false);
218
219     char tempstr[500], newFPBody[4092];
220     bool bNeedT0 = false, bNeedT1 = false, bNeedComb2 = false;
221     newFPBody[0] = 0;
222
223     for( int cycle=0; cycle<2; cycle++ )
224     {
225         for( int channel=0; channel<2; channel++)
226         {
227             char* (*func)(uint8) = channel==0?MuxToOC:MuxToOA;
228             char *dst = channel==0?(char*)"rgb":(char*)"a";
229             N64CombinerType &m = mux.m_n64Combiners[cycle*2+channel];
230             switch( mux.splitType[cycle*2+channel] )
231             {
232             case CM_FMT_TYPE_NOT_USED:
233                 tempstr[0] = 0;
234                 break;
235             case CM_FMT_TYPE_D:
236                 sprintf(tempstr, "MOV comb.%s, %s;\n", dst, func(m.d));
237                 CheckFpVars(m.d, bNeedT0, bNeedT1);
238                 break;
239             case CM_FMT_TYPE_A_MOD_C:
240                 sprintf(tempstr, "MUL comb.%s, %s, %s;\n", dst, func(m.a), func(m.c));
241                 CheckFpVars(m.a, bNeedT0, bNeedT1);
242                 CheckFpVars(m.c, bNeedT0, bNeedT1);
243                 break;
244             case CM_FMT_TYPE_A_ADD_D:
245                 sprintf(tempstr, "ADD_SAT comb.%s, %s, %s;\n", dst, func(m.a), func(m.d));
246                 CheckFpVars(m.a, bNeedT0, bNeedT1);
247                 CheckFpVars(m.d, bNeedT0, bNeedT1);
248                 break;
249             case CM_FMT_TYPE_A_SUB_B:
250                 sprintf(tempstr, "SUB comb.%s, %s, %s;\n", dst, func(m.a), func(m.b));
251                 CheckFpVars(m.a, bNeedT0, bNeedT1);
252                 CheckFpVars(m.b, bNeedT0, bNeedT1);
253                 break;
254             case CM_FMT_TYPE_A_MOD_C_ADD_D:
255                 sprintf(tempstr, "MAD_SAT comb.%s, %s, %s, %s;\n", dst, func(m.a), func(m.c), func(m.d));
256                 CheckFpVars(m.a, bNeedT0, bNeedT1);
257                 CheckFpVars(m.c, bNeedT0, bNeedT1);
258                 CheckFpVars(m.d, bNeedT0, bNeedT1);
259                 break;
260             case CM_FMT_TYPE_A_LERP_B_C:
261                 sprintf(tempstr, "LRP_SAT comb.%s, %s, %s, %s;\n", dst, func(m.c), func(m.a), func(m.b));
262                 CheckFpVars(m.a, bNeedT0, bNeedT1);
263                 CheckFpVars(m.b, bNeedT0, bNeedT1);
264                 CheckFpVars(m.c, bNeedT0, bNeedT1);
265                 //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));
266                 break;
267             default:
268                 sprintf(tempstr, "SUB comb2.%s, %s, %s;\nMAD_SAT comb.%s, comb2, %s, %s;\n", dst, func(m.a), func(m.b), dst, func(m.c), func(m.d));
269                 CheckFpVars(m.a, bNeedT0, bNeedT1);
270                 CheckFpVars(m.b, bNeedT0, bNeedT1);
271                 CheckFpVars(m.c, bNeedT0, bNeedT1);
272                 CheckFpVars(m.d, bNeedT0, bNeedT1);
273                 bNeedComb2 = true;
274                 break;
275             }
276             strcat(newFPBody, tempstr);
277         }
278     }
279
280     strcpy(oglNewFP, "!!ARBfp1.0\n");
281     strcat(oglNewFP, "#Declarations\n");
282     if (gRDP.bFogEnableInBlender && gRSP.bFogEnabled)
283         strcat(oglNewFP, "OPTION ARB_fog_linear;\n");
284     if (bNeedT0)
285         strcat(oglNewFP, "TEMP t0;\n");
286     if (bNeedT1)
287         strcat(oglNewFP, "TEMP t1;\n");
288     strcat(oglNewFP, "TEMP comb;\n");
289     if (bNeedComb2)
290         strcat(oglNewFP, "TEMP comb2;\n");
291     strcat(oglNewFP, "#Instructions\n");
292     if (bNeedT0)
293         strcat(oglNewFP, "TEX t0, fragment.texcoord[0], texture[0], 2D;\n");
294     if (bNeedT1)
295         strcat(oglNewFP, "TEX t1, fragment.texcoord[1], texture[1], 2D;\n");
296     strcat(oglNewFP, "# N64 cycle 1, result is in comb\n");
297
298     strcat(oglNewFP, newFPBody);
299
300     strcat(oglNewFP, "MOV result.color, comb;\n");
301     strcat(oglNewFP, "END\n\n");
302 }
303
304 int COGL_FragmentProgramCombiner::ParseDecodedMux()
305 {
306     if( !m_bFragmentProgramIsSupported )
307         return COGLColorCombiner4::ParseDecodedMux();
308
309     OGLShaderCombinerSaveType res;
310
311     pglGenProgramsARB( 1, &res.programID);
312     OPENGL_CHECK_ERRORS;
313     pglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, res.programID);
314     OPENGL_CHECK_ERRORS;
315     GenerateProgramStr();
316
317     pglProgramStringARB( GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(oglNewFP), oglNewFP);
318     OPENGL_CHECK_ERRORS;
319     //pglProgramStringARB(   GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(oglFPTest), oglFPTest);
320
321     if (glGetError() != 0)
322     {
323         GLint position;
324 #ifdef DEBUGGER
325         char *str = (char*)glGetString(GL_PROGRAM_ERROR_STRING_ARB);
326 #endif
327         glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &position);
328         if( position >= 0 )
329         {
330 #ifdef DEBUGGER
331             if( m_lastIndex >= 0 ) COGLColorCombiner4::DisplaySimpleMuxString();
332             DebugMessage(M64MSG_ERROR, "%s - %s", str, oglNewFP+position);
333 #endif
334             glDisable(GL_FRAGMENT_PROGRAM_ARB);
335             return COGLColorCombiner4::ParseDecodedMux();
336         }
337     }
338
339     glEnable(GL_FRAGMENT_PROGRAM_ARB);
340     OPENGL_CHECK_ERRORS;
341     res.dwMux0 = m_pDecodedMux->m_dwMux0;
342     res.dwMux1 = m_pDecodedMux->m_dwMux1;
343     res.fogIsUsed = gRDP.bFogEnableInBlender && gRSP.bFogEnabled;
344
345     m_vCompiledShaders.push_back(res);
346     m_lastIndex = m_vCompiledShaders.size()-1;
347
348     return m_lastIndex;
349 }
350
351 void COGL_FragmentProgramCombiner::GenerateCombinerSetting(int index)
352 {
353     GLuint ID = m_vCompiledShaders[index].programID;
354     pglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, ID );
355     OPENGL_CHECK_ERRORS;
356     glEnable(GL_FRAGMENT_PROGRAM_ARB);
357     OPENGL_CHECK_ERRORS;
358 }
359
360 void COGL_FragmentProgramCombiner::GenerateCombinerSettingConstants(int index)
361 {
362     float *pf;
363     pf = GetEnvColorfv();
364     pglProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 1, pf);
365     OPENGL_CHECK_ERRORS;
366     pf = GetPrimitiveColorfv();
367     pglProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 2, pf);
368     OPENGL_CHECK_ERRORS;
369
370     float frac = gRDP.LODFrac / 255.0f;
371     float tempf[4] = {frac,frac,frac,frac};
372     pglProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 3, tempf);
373     OPENGL_CHECK_ERRORS;
374
375     float frac2 = gRDP.primLODFrac / 255.0f;
376     float tempf2[4] = {frac2,frac2,frac2,frac2};
377     pglProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 4, tempf2);
378     OPENGL_CHECK_ERRORS;
379
380     float tempf3[4] = {0,0,0,0};
381     pglProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0, tempf3);
382     OPENGL_CHECK_ERRORS;
383     pglProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 6, tempf3);
384     OPENGL_CHECK_ERRORS;
385 }
386
387 int COGL_FragmentProgramCombiner::FindCompiledMux()
388 {
389 #ifdef DEBUGGER
390     if( debuggerDropCombiners )
391     {
392         m_vCompiledShaders.clear();
393         //m_dwLastMux0 = m_dwLastMux1 = 0;
394         debuggerDropCombiners = false;
395     }
396 #endif
397     for( uint32 i=0; i<m_vCompiledShaders.size(); i++ )
398     {
399         if( m_vCompiledShaders[i].dwMux0 == m_pDecodedMux->m_dwMux0 
400             && m_vCompiledShaders[i].dwMux1 == m_pDecodedMux->m_dwMux1 
401             && m_vCompiledShaders[i].fogIsUsed == (gRDP.bFogEnableInBlender && gRSP.bFogEnabled) )
402             return (int)i;
403     }
404
405     return -1;
406 }
407
408 //////////////////////////////////////////////////////////////////////////
409 void COGL_FragmentProgramCombiner::InitCombinerCycle12(void)
410 {
411     if( !m_bFragmentProgramIsSupported )    
412     {
413         COGLColorCombiner4::InitCombinerCycle12();
414         return;
415     }
416
417 #ifdef DEBUGGER
418     if( debuggerDropCombiners )
419     {
420         UpdateCombiner(m_pDecodedMux->m_dwMux0,m_pDecodedMux->m_dwMux1);
421         m_vCompiledShaders.clear();
422         m_dwLastMux0 = m_dwLastMux1 = 0;
423         debuggerDropCombiners = false;
424     }
425 #endif
426
427     m_pOGLRender->EnableMultiTexture();
428
429     bool combinerIsChanged = false;
430
431     if( m_pDecodedMux->m_dwMux0 != m_dwLastMux0 || m_pDecodedMux->m_dwMux1 != m_dwLastMux1 || m_lastIndex < 0 )
432     {
433         combinerIsChanged = true;
434         m_lastIndex = FindCompiledMux();
435         if( m_lastIndex < 0 )       // Can not found
436         {
437             m_lastIndex = ParseDecodedMux();
438         }
439
440         m_dwLastMux0 = m_pDecodedMux->m_dwMux0;
441         m_dwLastMux1 = m_pDecodedMux->m_dwMux1;
442     }
443
444
445     GenerateCombinerSettingConstants(m_lastIndex);
446     if( m_bCycleChanged || combinerIsChanged || gRDP.texturesAreReloaded || gRDP.colorsAreReloaded )
447     {
448         if( m_bCycleChanged || combinerIsChanged )
449         {
450             GenerateCombinerSettingConstants(m_lastIndex);
451             GenerateCombinerSetting(m_lastIndex);
452         }
453         else if( gRDP.colorsAreReloaded )
454         {
455             GenerateCombinerSettingConstants(m_lastIndex);
456         }
457
458         m_pOGLRender->SetAllTexelRepeatFlag();
459
460         gRDP.colorsAreReloaded = false;
461         gRDP.texturesAreReloaded = false;
462     }
463     else
464     {
465         m_pOGLRender->SetAllTexelRepeatFlag();
466     }
467 }
468
469 #ifdef DEBUGGER
470 void COGL_FragmentProgramCombiner::DisplaySimpleMuxString(void)
471 {
472     COGLColorCombiner::DisplaySimpleMuxString();
473     DecodedMuxForPixelShader &mux = *(DecodedMuxForPixelShader*)m_pDecodedMux;
474     mux.Reformat(false);
475     GenerateProgramStr();
476     //sprintf(oglNewFP, oglFP, 
477     //  MuxToOC(mux.aRGB0), MuxToOC(mux.bRGB0), MuxToOC(mux.cRGB0), MuxToOC(mux.dRGB0),
478     //  MuxToOA(mux.aA0), MuxToOA(mux.bA0), MuxToOA(mux.cA0), MuxToOA(mux.dA0),
479     //  MuxToOC(mux.aRGB1), MuxToOC(mux.bRGB1), MuxToOC(mux.cRGB1), MuxToOC(mux.dRGB1),
480     //  MuxToOA(mux.aA1), MuxToOA(mux.bA1), MuxToOA(mux.cA1), MuxToOA(mux.dA1)
481     //  );
482
483     TRACE0("OGL Fragment Program:");
484     TRACE0(oglNewFP);
485 }
486 #endif
487