commit 984dc935e7a1088581c9e1840674a838b95c0e2f
Author: Leszek Koltunski <leszek@distoretedandroid.org>
Date:   Wed May 24 11:35:04 2017 +0100

    10% speedup with postprocessing.

diff --git a/src/main/java/org/distorted/library/DistortedEffectsPostprocess.java b/src/main/java/org/distorted/library/DistortedEffectsPostprocess.java
index b25ec53..db09afa 100644
--- a/src/main/java/org/distorted/library/DistortedEffectsPostprocess.java
+++ b/src/main/java/org/distorted/library/DistortedEffectsPostprocess.java
@@ -108,6 +108,13 @@ public class DistortedEffectsPostprocess implements DistortedSlave
     return mP.mQualityLevel;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  int getHalo()
+    {
+    return mP.getHalo();
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   static void onDestroy()
diff --git a/src/main/java/org/distorted/library/DistortedNode.java b/src/main/java/org/distorted/library/DistortedNode.java
index c039d0a..3393a96 100644
--- a/src/main/java/org/distorted/library/DistortedNode.java
+++ b/src/main/java/org/distorted/library/DistortedNode.java
@@ -259,26 +259,29 @@ public class DistortedNode implements DistortedSlave
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  int markStencilAndDraw(long currTime, DistortedOutputSurface surface, int quality)
+  int markStencilAndDraw(long currTime, DistortedOutputSurface surface, DistortedEffectsPostprocess effects)
     {
     DistortedInputSurface input = mNumChildren[0]==0 ? mSurface : mData.mFBO;
 
     if( input.setAsInput() )
       {
+      int quality = effects.getQuality();
       DistortedFramebuffer buffer1 = surface.mBuffer1[quality];
       DistortedFramebuffer buffer2 = surface.mBuffer2[quality];
       float w = mSurface.getWidth() /2.0f;
       float h = mSurface.getHeight()/2.0f;
 
-      // Mark area of our object + marginInPixels pixels around with 1s in Stencil buffer
-      buffer2.setAsOutput(currTime);
-      DistortedRenderState.setUpStencilMark();
-      mEffects.drawPriv(w, h, mMesh, buffer2, currTime, EffectQueuePostprocess.MAX_BLUR*buffer2.mMipmap);
-
       // Actually draw our object.
       buffer1.setAsOutput(currTime);
       mState.apply();
       mEffects.drawPriv(w, h, mMesh, buffer1, currTime, 0);
+
+      // Mark area of our object + marginInPixels pixels around with 1s in Stencil buffer
+      buffer2.setAsOutput(currTime);
+      DistortedRenderState.setUpStencilMark();
+      mEffects.drawPriv(w, h, mMesh, buffer2, currTime, effects.getHalo()*buffer2.mMipmap);
+      DistortedRenderState.unsetUpStencilMark();
+
       return 1;
       }
     return 0;
diff --git a/src/main/java/org/distorted/library/DistortedOutputSurface.java b/src/main/java/org/distorted/library/DistortedOutputSurface.java
index 3003eb4..48d42b5 100644
--- a/src/main/java/org/distorted/library/DistortedOutputSurface.java
+++ b/src/main/java/org/distorted/library/DistortedOutputSurface.java
@@ -200,8 +200,7 @@ abstract class DistortedOutputSurface extends DistortedSurface implements Distor
           DistortedObject.toDo(); // create the FBOs immediately. This is safe as we must be holding the OpenGL context now.
           }
 
-        int quality = currP.getQuality();
-        numRenders += child.markStencilAndDraw(time,this,quality);
+        numRenders += child.markStencilAndDraw(time,this,currP);
 
         if( i==num-1 )
           {
diff --git a/src/main/java/org/distorted/library/DistortedRenderState.java b/src/main/java/org/distorted/library/DistortedRenderState.java
index 57fba06..dc84d88 100644
--- a/src/main/java/org/distorted/library/DistortedRenderState.java
+++ b/src/main/java/org/distorted/library/DistortedRenderState.java
@@ -164,12 +164,16 @@ class DistortedRenderState
     {
     if( cState.stencilTest!=1 )
       {
+      sState.stencilTest = cState.stencilTest;
       cState.stencilTest = 1;
       //android.util.Log.d("State", "stencil test on");
       GLES30.glEnable(GLES30.GL_STENCIL_TEST);
       }
     if( cState.stencilFuncFunc!=GLES30.GL_ALWAYS || cState.stencilFuncRef!=1 || cState.stencilFuncMask!=STENCIL_MASK )
       {
+      sState.stencilFuncFunc = cState.stencilFuncFunc;
+      sState.stencilFuncRef  = cState.stencilFuncRef;
+      sState.stencilFuncMask = cState.stencilFuncMask;
       cState.stencilFuncFunc = GLES30.GL_ALWAYS;
       cState.stencilFuncRef  = 1;
       cState.stencilFuncMask = STENCIL_MASK;
@@ -178,6 +182,9 @@ class DistortedRenderState
       }
     if( cState.stencilOpSfail!=GLES30.GL_KEEP || cState.stencilOpDpfail!=GLES30.GL_KEEP || cState.stencilOpDppass!=GLES30.GL_REPLACE )
       {
+      sState.stencilOpSfail = cState.stencilOpSfail;
+      sState.stencilOpDpfail= cState.stencilOpDpfail;
+      sState.stencilOpDppass= cState.stencilOpDppass;
       cState.stencilOpSfail = GLES30.GL_KEEP;
       cState.stencilOpDpfail= GLES30.GL_KEEP;
       cState.stencilOpDppass= GLES30.GL_REPLACE;
@@ -186,6 +193,10 @@ class DistortedRenderState
       }
     if( cState.colorMaskR!=0 || cState.colorMaskG!=0 || cState.colorMaskB!=0 || cState.colorMaskA!=0 )
       {
+      sState.colorMaskR = cState.colorMaskR;
+      sState.colorMaskG = cState.colorMaskG;
+      sState.colorMaskB = cState.colorMaskB;
+      sState.colorMaskA = cState.colorMaskA;
       cState.colorMaskR = 0;
       cState.colorMaskG = 0;
       cState.colorMaskB = 0;
@@ -195,18 +206,57 @@ class DistortedRenderState
       }
     if( cState.depthMask!=0 )
       {
+      sState.depthMask = cState.depthMask;
       cState.depthMask = 0;
       //android.util.Log.d("State", "switch off depth writing");
       GLES30.glDepthMask(false);
       }
     if( cState.stencilMask!= STENCIL_MASK )
       {
+      sState.stencilMask = cState.stencilMask;
       cState.stencilMask = STENCIL_MASK;
       //android.util.Log.d("State", "stencil mask on");
       GLES30.glStencilMask(cState.stencilMask);
       }
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  static void unsetUpStencilMark()
+    {
+    if( sState.stencilTest!=cState.stencilTest )
+      {
+      cState.stencilTest = sState.stencilTest;
+
+      if (cState.stencilTest == 0)
+        {
+        GLES30.glDisable(GLES30.GL_STENCIL_TEST);
+        }
+      else
+        {
+        GLES30.glEnable(GLES30.GL_STENCIL_TEST);
+        }
+      }
+    if( sState.colorMaskR!=cState.colorMaskR || sState.colorMaskG!=cState.colorMaskG || sState.colorMaskB!=cState.colorMaskB || sState.colorMaskA!=cState.colorMaskA)
+      {
+      cState.colorMaskR = sState.colorMaskR;
+      cState.colorMaskG = sState.colorMaskG;
+      cState.colorMaskB = sState.colorMaskB;
+      cState.colorMaskA = sState.colorMaskA;
+      GLES30.glColorMask(cState.colorMaskR==1,cState.colorMaskG==1,cState.colorMaskB==1,cState.colorMaskA==1);
+      }
+    if( sState.depthMask!=cState.depthMask )
+      {
+      cState.depthMask = sState.depthMask;
+      GLES30.glDepthMask(cState.depthMask==1);
+      }
+    if( sState.stencilMask!=cState.stencilMask )
+      {
+      cState.stencilMask = sState.stencilMask;
+      GLES30.glStencilMask(cState.stencilMask);
+      }
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   static void useStencilMark()
diff --git a/src/main/java/org/distorted/library/EffectQueuePostprocess.java b/src/main/java/org/distorted/library/EffectQueuePostprocess.java
index 417ba34..3f74ec5 100644
--- a/src/main/java/org/distorted/library/EffectQueuePostprocess.java
+++ b/src/main/java/org/distorted/library/EffectQueuePostprocess.java
@@ -257,6 +257,13 @@ class EffectQueuePostprocess extends EffectQueue
       }
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  int getHalo()
+    {
+    return mNumEffects>0 ? (int)mUniforms[0] : 0;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   int postprocess(long time, DistortedOutputSurface surface)
@@ -319,6 +326,8 @@ class EffectQueuePostprocess extends EffectQueue
 
       // after each postprocess, clear the STENCIL
       buffer2.setAsOutput(time);
+      GLES30.glStencilMask(0xff);
+      GLES30.glClearStencil(0);
       GLES30.glClear(GLES30.GL_STENCIL_BUFFER_BIT);
       }
 
