rice: avoid redundant gl calls
[mupen64plus-pandora.git] / source / gles2rice / src / OGLES2FragmentShaders.cpp
index 29b8e97..0fa4150 100755 (executable)
@@ -35,6 +35,9 @@ const char *vertexShader =
 "attribute lowp vec2    aTexCoord0;                         \n"\
 "attribute lowp vec2    aTexCoord1;                         \n"\
 "attribute lowp vec2    aAtlasTransform;                    \n"\
+"attribute mediump float aFogCoord;                         \n"\
+"                                                           \n"\
+"uniform vec2 FogMinMax;                                    \n"\
 "                                                           \n"\
 "varying lowp float vFactor;                                \n"\
 "varying lowp vec4  vShadeColor;                            \n"\
@@ -48,7 +51,9 @@ const char *vertexShader =
 "vShadeColor = aColor;                                      \n"\
 "vTexCoord0 = aTexCoord0;                                   \n"\
 "vTexCoord1 = aTexCoord1;                                   \n"\
+"vFog = (FogMinMax[1] - aFogCoord) / (FogMinMax[1] - FogMinMax[0]);  \n"\
 "                                                           \n"\
+"vFog = clamp(vFog, 0.0, 1.0);                              \n"\
 "}                                                          \n"\
 "                                                           \n";
 
@@ -69,18 +74,17 @@ const char *fragmentHeader =
 "uniform vec4 PrimFrac;                                     \n"\
 "uniform float AlphaRef;                                    \n"\
 "uniform vec4 FogColor;                                     \n"\
-"uniform vec2  FogMinMax;                                   \n"\
 "                                                           \n"\
-"varying lowp float vFactor;                                \n"\
 "varying lowp vec4  vShadeColor;                            \n"\
 "varying mediump vec2  vTexCoord0;                          \n"\
 "varying lowp vec2  vTexCoord1;                             \n"\
+"varying lowp float vFog;                                   \n"\
 "                                                           \n"\
 "void main()                                                \n"\
 "{                                                          \n"\
 "vec4 comb,comb2;                                           \n"\
 "                                                           \n"\
-"#ifdef NEED_TEX0                                              \n"\
+"#ifdef NEED_TEX0                                           \n"\
 "vec4 t0 = texture2D(uTex0,vTexCoord0);                     \n"\
 "#endif                                                     \n"\
 "                                                           \n"\
@@ -91,19 +95,15 @@ const char *fragmentHeader =
 const char *fragmentFooter =
 "                                                           \n"\
 "#ifdef FOG                                                 \n"\
-"   float z = gl_FragCoord.z * 2.0 - 1.0;                                   \n"\
-"   float FogFactor = (FogMinMax[1] - z) / (FogMinMax[1] - FogMinMax[0]);   \n"\
-"   FogFactor = clamp(FogFactor, 0.0, 1.0);                                 \n"\
-"                                                                           \n"\
-"   gl_FragColor.rgb = mix(FogColor.rgb, comb.rgb, FogFactor );             \n"\
-"   gl_FragColor.a = comb.a;                                                \n"\
-"#else                                                                      \n"\
-"   gl_FragColor = comb;                                                    \n"\
-"#endif                                                                     \n"\
-"                                                                           \n"\
-"#ifdef ALPHA_TEST                                                          \n"\
+"gl_FragColor.rgb = mix(FogColor.rgb,comb.rgb,vFog);        \n"\
+"gl_FragColor.a = comb.a;                                   \n"\
+"#else                                                      \n"\
+"gl_FragColor = comb;                                       \n"\
+"#endif                                                     \n"\
+"                                                           \n"\
+"#ifdef ALPHA_TEST                                          \n"\
    ALPHA_TEST                                                                  
-"#endif                                                                     \n"\
+"#endif                                                     \n"\
 "}                                                          \n";
 
 //Fragment shader for InitCycleCopy
@@ -147,7 +147,7 @@ bool COGLFragmentShaderCombiner::Initialize(void)
     if( !COGLColorCombiner::Initialize() )
         return false;
 
-    COGLGraphicsContext *pcontext = (COGLGraphicsContext *)(CGraphicsContext::g_pGraphicsContext);
+//    COGLGraphicsContext *pcontext = (COGLGraphicsContext *)(CGraphicsContext::g_pGraphicsContext);
 //    if( pcontext->IsExtensionSupported("GL_fragment_shader") )
 //    {
         m_bShaderIsSupported = true;
@@ -194,10 +194,10 @@ COGL_FragmentProgramCombiner::COGL_FragmentProgramCombiner(CRender *pRender)
     m_pDecodedMux = new DecodedMuxForPixelShader;
     m_bFragmentProgramIsSupported = true;
     m_AlphaRef = 0.0f;
-    bAlphaTestState = DISABLE;
-    bAlphaTestPreviousState = DISABLE;
-    bFogState = DISABLE;
-    bFogPreviousState = DISABLE;
+    bAlphaTestState = false;
+    bAlphaTestPreviousState = false;
+    bFogState = false;
+    bFogPreviousState = false;
 
     //Create shaders for fill and copy
     GLint success;
@@ -295,7 +295,7 @@ bool COGL_FragmentProgramCombiner::Initialize(void)
     if( !COGLColorCombiner4::Initialize() )
         return false;
 
-    COGLGraphicsContext *pcontext = (COGLGraphicsContext *)(CGraphicsContext::g_pGraphicsContext);
+//    COGLGraphicsContext *pcontext = (COGLGraphicsContext *)(CGraphicsContext::g_pGraphicsContext);
 //    if( pcontext->IsExtensionSupported("GL_fragment_program") )
 //    {
         m_bFragmentProgramIsSupported = true;
@@ -306,6 +306,14 @@ bool COGL_FragmentProgramCombiner::Initialize(void)
 
 
 
+void COGL_FragmentProgramCombiner::UseProgram(GLuint program)
+{
+    if (program != currentProgram) {
+        glUseProgram(program);
+        currentProgram = program;
+    }
+}
+
 void COGL_FragmentProgramCombiner::DisableCombiner(void)
 {
     //glDisable(GL_FRAGMENT_PROGRAM);
@@ -317,7 +325,7 @@ void COGL_FragmentProgramCombiner::InitCombinerCycleCopy(void)
 {
     m_pOGLRender->DisableMultiTexture();
     m_pOGLRender->EnableTexUnit(0,TRUE);
-    glUseProgram(copyProgram);
+    UseProgram(copyProgram);
     glUniform1f(copyAlphaLocation,m_AlphaRef);
     OPENGL_CHECK_ERRORS;
     glEnableVertexAttribArray(VS_POSITION);
@@ -328,6 +336,8 @@ void COGL_FragmentProgramCombiner::InitCombinerCycleCopy(void)
     OPENGL_CHECK_ERRORS;
     glDisableVertexAttribArray(VS_TEXCOORD1);
     OPENGL_CHECK_ERRORS;
+       glDisableVertexAttribArray(VS_FOG);
+       OPENGL_CHECK_ERRORS;
     COGLTexture* pTexture = g_textures[gRSP.curTile].m_pCOGLTexture;
     if( pTexture )
     {
@@ -338,7 +348,7 @@ void COGL_FragmentProgramCombiner::InitCombinerCycleCopy(void)
 
 void COGL_FragmentProgramCombiner::InitCombinerCycleFill(void)
 {
-    glUseProgram(fillProgram);
+    UseProgram(fillProgram);
     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);
     OPENGL_CHECK_ERRORS;
 }
@@ -573,6 +583,8 @@ int COGL_FragmentProgramCombiner::ParseDecodedMux()
                        OPENGL_CHECK_ERRORS;
                        glBindAttribLocation(res.programID,VS_POSITION,"aPosition");
                        OPENGL_CHECK_ERRORS;
+                       glBindAttribLocation(res.programID,VS_FOG,"aFogCoord");
+                       OPENGL_CHECK_ERRORS;
 
                        glLinkProgram(res.programID);
                        OPENGL_CHECK_ERRORS;
@@ -587,7 +599,7 @@ int COGL_FragmentProgramCombiner::ParseDecodedMux()
                                printf("%s\n",Log);
                        }
 
-                       glUseProgram(res.programID);
+                       UseProgram(res.programID);
                        OPENGL_CHECK_ERRORS;
 
                        //Bind texture samplers
@@ -630,7 +642,7 @@ void COGL_FragmentProgramCombiner::GenerateCombinerSetting(int index)
 {
     GLuint ID = m_vCompiledShaders[index].programID;
 
-    glUseProgram(ID);
+    UseProgram(ID);
     glEnableVertexAttribArray(VS_POSITION);
     OPENGL_CHECK_ERRORS;
     glVertexAttribPointer(VS_POSITION,4,GL_FLOAT,GL_FALSE,sizeof(float)*5,&(g_vtxProjected5[0][0]));
@@ -650,61 +662,90 @@ void COGL_FragmentProgramCombiner::GenerateCombinerSetting(int index)
     OPENGL_CHECK_ERRORS;
     glVertexAttribPointer(VS_COLOR, 4, GL_UNSIGNED_BYTE,GL_TRUE, sizeof(uint8)*4, &(g_oglVtxColors[0][0]) );
     OPENGL_CHECK_ERRORS;
+       
+       glEnableVertexAttribArray(VS_FOG);
+       OPENGL_CHECK_ERRORS;
+       glVertexAttribPointer(VS_FOG,1,GL_FLOAT,GL_FALSE,sizeof(float)*5,&(g_vtxProjected5[0][4]));
+       OPENGL_CHECK_ERRORS;
 }
 
 void COGL_FragmentProgramCombiner::GenerateCombinerSettingConstants(int index)
 {
-    OGLShaderCombinerSaveType prog = m_vCompiledShaders[index];
+    OGLShaderCombinerSaveType &prog = m_vCompiledShaders[index];
 
-    glUseProgram(prog.programID);
+    UseProgram(prog.programID);
     float *pf;
     if(prog.EnvColorLocation != -1)
     {
         pf = GetEnvColorfv();
-        glUniform4fv(prog.EnvColorLocation,1, pf);
-        OPENGL_CHECK_ERRORS;
+        if (memcmp(pf, prog.EnvColors, sizeof(prog.EnvColors))) {
+            memcpy(prog.EnvColors, pf, sizeof(prog.EnvColors));
+            glUniform4fv(prog.EnvColorLocation, 1, pf);
+            OPENGL_CHECK_ERRORS;
+        }
     }
 
     if(prog.PrimColorLocation != -1)
     {
         pf = GetPrimitiveColorfv();
-        glUniform4fv(prog.PrimColorLocation,1, pf);
-        OPENGL_CHECK_ERRORS;
+        if (memcmp(pf, prog.PrimColors, sizeof(prog.PrimColors))) {
+            memcpy(prog.PrimColors, pf, sizeof(prog.PrimColors));
+            glUniform4fv(prog.PrimColorLocation, 1, pf);
+            OPENGL_CHECK_ERRORS;
+        }
     }
 
     if(prog.EnvFracLocation != -1)
     {
-        float frac = gRDP.LODFrac / 255.0f;
-        float tempf[4] = {frac,frac,frac,frac};
-        glUniform4fv(prog.EnvFracLocation,1, tempf);
-        OPENGL_CHECK_ERRORS;
+        // avoid slow float compare..
+        if( *(int *)&gRDP.LODFrac != *(int *)&prog.EnvLODFrac ) {
+            prog.EnvLODFrac = gRDP.LODFrac;
+            float frac = gRDP.LODFrac / 255.0f;
+            float tempf[4] = {frac,frac,frac,frac};
+            glUniform4fv(prog.EnvFracLocation, 1, tempf);
+            OPENGL_CHECK_ERRORS;
+        }
     }
 
     if(prog.PrimFracLocation != -1)
     {
-        float frac2 = gRDP.primLODFrac / 255.0f;
-        float tempf2[4] = {frac2,frac2,frac2,frac2};
-        glUniform4fv(prog.PrimFracLocation,1, tempf2);
-        OPENGL_CHECK_ERRORS;
+        if( *(int *)&gRDP.primLODFrac != *(int *)&prog.PrimLODFrac ) {
+            prog.PrimLODFrac = gRDP.primLODFrac;
+            float frac2 = gRDP.primLODFrac / 255.0f;
+            float tempf2[4] = {frac2,frac2,frac2,frac2};
+            glUniform4fv(prog.PrimFracLocation, 1, tempf2);
+            OPENGL_CHECK_ERRORS;
+        }
     }
 
-       if(prog.FogColorLocation != -1)
+    if(prog.FogColorLocation != -1)
     {
-        glUniform4f(prog.FogColorLocation, gRDP.fvFogColor[0],gRDP.fvFogColor[1],gRDP.fvFogColor[2], gRDP.fvFogColor[3]);
-        OPENGL_CHECK_ERRORS;
+        pf = &gRDP.fvFogColor[0];
+        if (memcmp(pf, prog.FogColors, sizeof(prog.FogColors))) {
+            memcpy(prog.FogColors, pf, sizeof(prog.FogColors));
+            glUniform4fv(prog.FogColorLocation, 1, pf);
+            OPENGL_CHECK_ERRORS;
+        }
     }
        
-       if(prog.FogMinMaxLocation != -1)        
-       {
-        glUniform2f(prog.FogMinMaxLocation,gRSPfFogMin,gRSPfFogMax);
-        OPENGL_CHECK_ERRORS;
+    if(prog.FogMinMaxLocation != -1)   
+    {
+        if( gRSPfFogMin != prog.FogMin || gRSPfFogMax != prog.FogMax ) {
+            prog.FogMin = gRSPfFogMin;
+            prog.FogMax = gRSPfFogMax;
+            glUniform2f(prog.FogMinMaxLocation,gRSPfFogMin,gRSPfFogMax);
+            OPENGL_CHECK_ERRORS;
+        }
     }
        
     if(prog.AlphaRefLocation != -1)
-       {
-        glUniform1f(prog.AlphaRefLocation,m_AlphaRef);
-               OPENGL_CHECK_ERRORS;
-       }
+    {
+        if( m_AlphaRef != prog.AlphaRef ) {
+            prog.AlphaRef = m_AlphaRef;
+            glUniform1f(prog.AlphaRefLocation, m_AlphaRef);
+            OPENGL_CHECK_ERRORS;
+        }
+    }
 }
 
 int COGL_FragmentProgramCombiner::FindCompiledMux()