commit 03cb451ded7bd0cd7c8f248a4b1c7e91875a361f
Author: Leszek Koltunski <leszek@distoretedandroid.org>
Date:   Wed Mar 1 12:06:52 2017 +0000

    Speed up shaders (both compilation and execution) by explicitly enabling only the needed effects.

diff --git a/src/main/java/org/distorted/library/DistortedEffects.java b/src/main/java/org/distorted/library/DistortedEffects.java
index 3fd138f..36c57a7 100644
--- a/src/main/java/org/distorted/library/DistortedEffects.java
+++ b/src/main/java/org/distorted/library/DistortedEffects.java
@@ -55,6 +55,17 @@ public class DistortedEffects
   private static final int TEX_DATA_SIZE     = 2; // Main Program: size of the texture coordinate data in elements.
 
   private static DistortedProgram mProgram;
+  private static boolean[] mEffectEnabled = new boolean[EffectNames.size()];
+
+  static
+    {
+    int len = EffectNames.size();
+
+    for(int i=0; i<len; i++)
+      {
+      mEffectEnabled[i] = false;
+      }
+    }
 
   /// DEBUG ONLY /////
   private static DistortedProgram mDebugProgram;
@@ -91,26 +102,44 @@ public class DistortedEffects
   static void createProgram(Resources resources)
   throws FragmentCompilationException,VertexCompilationException,VertexUniformsException,FragmentUniformsException,LinkingException
     {
-    final InputStream mainVertexStream   = resources.openRawResource(R.raw.main_vertex_shader);
-    final InputStream mainFragmentStream = resources.openRawResource(R.raw.main_fragment_shader);
+    final InputStream mainVertStream = resources.openRawResource(R.raw.main_vertex_shader);
+    final InputStream mainFragStream = resources.openRawResource(R.raw.main_fragment_shader);
+
+    String mainVertHeader= ("#version 100\n");
+    String mainFragHeader= ("#version 100\n");
 
-    String mainVertexHeader= ("#version 100\n#define NUM_VERTEX "  + getMaxVertex()+"\n");
+    EffectNames name;
+    EffectTypes type;
+    boolean foundF = false;
+    boolean foundV = false;
 
-    for(EffectNames name: EffectNames.values() )
+    for(int i=0; i<mEffectEnabled.length; i++)
       {
-      if( name.getType()== EffectTypes.VERTEX)
-        mainVertexHeader += ("#define "+name.name()+" "+name.ordinal()+"\n");
+      if( mEffectEnabled[i] )
+        {
+        name = EffectNames.getName(i);
+        type = EffectNames.getType(i);
+
+        if( type == EffectTypes.VERTEX )
+          {
+          mainVertHeader += ("#define "+name.name()+" "+name.ordinal()+"\n");
+          foundV = true;
+          }
+        else if( type == EffectTypes.FRAGMENT )
+          {
+          mainFragHeader += ("#define "+name.name()+" "+name.ordinal()+"\n");
+          foundF = true;
+          }
+        }
       }
 
-    String mainFragmentHeader= ("#version 100\n#define NUM_FRAGMENT "  + getMaxFragment()+"\n");
+    mainVertHeader += ("#define NUM_VERTEX "   + ( foundV ? getMaxVertex()   : 0 ) + "\n");
+    mainFragHeader += ("#define NUM_FRAGMENT " + ( foundF ? getMaxFragment() : 0 ) + "\n");
 
-    for(EffectNames name: EffectNames.values() )
-      {
-      if( name.getType()== EffectTypes.FRAGMENT)
-        mainFragmentHeader += ("#define "+name.name()+" "+name.ordinal()+"\n");
-      }
+    //android.util.Log.e("Effects", "vertHeader= "+mainVertHeader);
+    //android.util.Log.e("Effects", "fragHeader= "+mainFragHeader);
 
-    mProgram = new DistortedProgram(mainVertexStream,mainFragmentStream, mainVertexHeader, mainFragmentHeader);
+    mProgram = new DistortedProgram(mainVertStream,mainFragStream, mainVertHeader, mainFragHeader);
 
     int mainProgramH = mProgram.getProgramHandle();
     EffectQueueFragment.getUniforms(mainProgramH);
@@ -332,6 +361,13 @@ public class DistortedEffects
   static void onDestroy()
     {
     mNextID = 0;
+
+    int len = EffectNames.size();
+
+    for(int i=0; i<len; i++)
+      {
+      mEffectEnabled[i] = false;
+      }
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -498,6 +534,21 @@ public class DistortedEffects
     return false;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Enables a given Effect.
+ * <p>
+ * By default, all effects are disabled. One has to explicitly enable each effect one intends to use.
+ * This needs to be called BEFORE shaders get compiled, i.e. before the call to Distorted.onCreate().
+ * The point: by enabling only the effects we need, we can optimize the shaders.
+ *
+ * @param name Name of the Effect to enable.
+ */
+  public static void enableEffect(EffectNames name)
+    {
+    mEffectEnabled[name.ordinal()] = true;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
  * Returns the maximum number of Matrix effects.
diff --git a/src/main/java/org/distorted/library/EffectNames.java b/src/main/java/org/distorted/library/EffectNames.java
index f8e7bfb..adea44d 100644
--- a/src/main/java/org/distorted/library/EffectNames.java
+++ b/src/main/java/org/distorted/library/EffectNames.java
@@ -372,6 +372,13 @@ public enum EffectNames
     return false;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  static int size()
+    {
+    return values().length;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // PUBLIC API
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/res/raw/main_fragment_shader.glsl b/src/main/res/raw/main_fragment_shader.glsl
index 378a00c..2e1e140 100644
--- a/src/main/res/raw/main_fragment_shader.glsl
+++ b/src/main/res/raw/main_fragment_shader.glsl
@@ -85,7 +85,7 @@ void saturation(float degree, int effect, inout vec4 color)
   }
 #endif
 
-#endif
+#endif    // NUM_FRAGMENT>0
 
 //////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -96,43 +96,46 @@ void main()
 #if NUM_FRAGMENT>0
   vec2 diff;
   float pointDegree;
-  
+  int j=0;
+
   for(int i=0; i<fNumEffects; i++)
     {
-    diff = (v_Position.xy - fUniforms[2*i+1].xy)/fUniforms[2*i+1].zw;
+    diff = (v_Position.xy - fUniforms[j+1].xy)/fUniforms[j+1].zw;
     pointDegree = max(0.0,1.0-dot(diff,diff));
 
 #ifdef CHROMA
-    if( fType[i]==CHROMA            ) chroma    (sign(pointDegree),2*i,pixel); else
+    if( fType[i]==CHROMA            ) chroma    (sign(pointDegree),j,pixel); else
 #endif
 #ifdef SMOOTH_CHROMA
-    if( fType[i]==SMOOTH_CHROMA     ) chroma    (     pointDegree ,2*i,pixel); else
+    if( fType[i]==SMOOTH_CHROMA     ) chroma    (     pointDegree ,j,pixel); else
 #endif
 #ifdef ALPHA
-    if( fType[i]==ALPHA             ) alpha     (sign(pointDegree),2*i,pixel); else
+    if( fType[i]==ALPHA             ) alpha     (sign(pointDegree),j,pixel); else
 #endif
 #ifdef SMOOTH_ALPHA
-    if( fType[i]==SMOOTH_ALPHA      ) alpha     (     pointDegree ,2*i,pixel); else
+    if( fType[i]==SMOOTH_ALPHA      ) alpha     (     pointDegree ,j,pixel); else
 #endif
 #ifdef BRIGHTNESS
-    if( fType[i]==BRIGHTNESS        ) brightness(sign(pointDegree),2*i,pixel); else
+    if( fType[i]==BRIGHTNESS        ) brightness(sign(pointDegree),j,pixel); else
 #endif
 #ifdef SMOOTH_BRIGHTNESS
-    if( fType[i]==SMOOTH_BRIGHTNESS ) brightness(     pointDegree ,2*i,pixel); else
+    if( fType[i]==SMOOTH_BRIGHTNESS ) brightness(     pointDegree ,j,pixel); else
 #endif
 #ifdef CONTRAST
-    if( fType[i]==CONTRAST          ) contrast  (sign(pointDegree),2*i,pixel); else
+    if( fType[i]==CONTRAST          ) contrast  (sign(pointDegree),j,pixel); else
 #endif
 #ifdef SMOOTH_CONTRAST
-    if( fType[i]==SMOOTH_CONTRAST   ) contrast  (     pointDegree ,2*i,pixel); else
+    if( fType[i]==SMOOTH_CONTRAST   ) contrast  (     pointDegree ,j,pixel); else
 #endif
 #ifdef SATURATION
-    if( fType[i]==SATURATION        ) saturation(sign(pointDegree),2*i,pixel); else
+    if( fType[i]==SATURATION        ) saturation(sign(pointDegree),j,pixel); else
 #endif
 #ifdef SMOOTH_SATURATION
-    if( fType[i]==SMOOTH_SATURATION ) saturation(     pointDegree ,2*i,pixel); else
+    if( fType[i]==SMOOTH_SATURATION ) saturation(     pointDegree ,j,pixel); else
 #endif
     {}
+
+    j+=2;
     }
 #endif
 
