commit c834348d6c8da774935ee03122192aacdfc87837
Author: leszek <leszek@koltunski.pl>
Date:   Thu Feb 23 23:41:09 2017 +0000

    Make it possible to render each DistortedNode with adjustable OpeGL state (writeing to Color, Depth,Stencil buffers, DEPTH, STENCIL, BLENDING on.off, etc)

diff --git a/src/main/java/org/distorted/library/DistortedNode.java b/src/main/java/org/distorted/library/DistortedNode.java
index 76a528c..a49ebaf 100644
--- a/src/main/java/org/distorted/library/DistortedNode.java
+++ b/src/main/java/org/distorted/library/DistortedNode.java
@@ -44,6 +44,7 @@ public class DistortedNode implements DistortedAttacheable
   private MeshObject mMesh;
   private DistortedEffects mEffects;
   private DistortedInputSurface mSurface;
+  private DistortedRenderState mState;
   private NodeData mData;
 
   private ArrayList<DistortedNode> mChildren;
@@ -227,6 +228,7 @@ public class DistortedNode implements DistortedAttacheable
     if( input.setAsInput() )
       {
       ret++;
+      mState.apply();
       mEffects.drawPriv(halfX, halfY, mMesh, surface, currTime);
       }
 
@@ -248,6 +250,7 @@ public class DistortedNode implements DistortedAttacheable
     mSurface       = surface;
     mEffects       = effects;
     mMesh          = mesh;
+    mState         = new DistortedRenderState();
     mChildren      = null;
     mNumChildren   = new int[1];
     mNumChildren[0]= 0;
@@ -284,6 +287,7 @@ public class DistortedNode implements DistortedAttacheable
     {
     mEffects= new DistortedEffects(node.mEffects,flags);
     mMesh   = node.mMesh;
+    mState  = new DistortedRenderState();
     mParent = null;
 
     if( (flags & Distorted.CLONE_SURFACE) != 0 )
@@ -521,4 +525,117 @@ public class DistortedNode implements DistortedAttacheable
     return mData.mFBO;
     }
 
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * When rendering this Node, use ColorMask (r,g,b,a).
+ *
+ * @param r Write to the RED color channel when rendering this Node?
+ * @param g Write to the GREEN color channel when rendering this Node?
+ * @param b Write to the BLUE color channel when rendering this Node?
+ * @param a Write to the ALPHA channel when rendering this Node?
+ */
+  public void glColorMask(boolean r, boolean g, boolean b, boolean a)
+    {
+    mState.glColorMask(r,g,b,a);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * When rendering this Node, switch on writing to Depth buffer?
+ *
+ * @param mask Write to the Depth buffer when rendering this Node?
+ */
+  public void glDepthMask(boolean mask)
+    {
+    mState.glDepthMask(mask);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * When rendering this Node, which bits of the Stencil buffer to write to?
+ *
+ * @param mask Marks the bits of the Stencil buffer we will write to when rendering this Node.
+ */
+  public void glStencilMask(int mask)
+    {
+    mState.glStencilMask(mask);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * When rendering this Node, which Tests to enable?
+ *
+ * @param test Valid values: GL_DEPTH_TEST, GL_STENCIL_TEST, GL_BLEND
+ */
+  public void glEnable(int test)
+    {
+    mState.glEnable(test);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * When rendering this Node, which Tests to enable?
+ *
+ * @param test Valid values: GL_DEPTH_TEST, GL_STENCIL_TEST, GL_BLEND
+ */
+  public void glDisable(int test)
+    {
+    mState.glDisable(test);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * When rendering this Node, use the following StencilFunc.
+ *
+ * @param func Valid values: GL_NEVER, GL_ALWAYS, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL
+ * @param ref  Reference valut to compare our stencil with.
+ * @param mask Mask used when comparing.
+ */
+  public void glStencilFunc(int func, int ref, int mask)
+    {
+    mState.glStencilFunc(func,ref,mask);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * When rendering this Node, use the following StencilOp.
+ * <p>
+ * Valid values of all 3 parameters: GL_KEEP, GL_ZERO, GL_REPLACE, GL_INCR, GL_DECR, GL_INVERT, GL_INCR_WRAP, GL_DECR_WRAP
+ *
+ * @param sfail  What to do when Stencil Test fails.
+ * @param dpfail What to do when Depth Test fails.
+ * @param dppass What to do when Depth Test passes.
+ */
+  public void glStencilOp(int sfail, int dpfail, int dppass)
+    {
+    mState.glStencilOp(sfail,dpfail,dppass);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * When rendering this Node, use the following DepthFunc.
+ *
+ * @param func Valid values: GL_NEVER, GL_ALWAYS, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL
+ */
+  public void glDepthFunc(int func)
+    {
+    mState.glDepthFunc(func);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * When rendering this Node, use the following Blending mode.
+ * <p>
+ * Valid values: GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
+ *               GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR,
+ *               GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA, GL_SRC_ALPHA_SATURATE
+ *
+ * @param src Source Blend function
+ * @param dst Destination Blend function
+ */
+  public void glBlendFunc(int src, int dst)
+    {
+    mState.glBlendFunc(src,dst);
+    }
   }
diff --git a/src/main/java/org/distorted/library/DistortedOutputSurface.java b/src/main/java/org/distorted/library/DistortedOutputSurface.java
index c543bbd..5150b44 100644
--- a/src/main/java/org/distorted/library/DistortedOutputSurface.java
+++ b/src/main/java/org/distorted/library/DistortedOutputSurface.java
@@ -143,8 +143,8 @@ abstract class DistortedOutputSurface extends DistortedSurface implements Distor
       DistortedSurface.debugLists();
       }
 */
-    GLES30.glEnable(GLES30.GL_BLEND);
-    GLES30.glBlendFunc(GLES30.GL_SRC_ALPHA, GLES30.GL_ONE_MINUS_SRC_ALPHA);
+    // mark OpenGL state as unknown
+    DistortedRenderState.reset();
 
     int numRenders = 0;
 
@@ -163,17 +163,6 @@ abstract class DistortedOutputSurface extends DistortedSurface implements Distor
   public void setAsOutput()
     {
     GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, mFBOH[0]);
-
-    if( mDepthCreated==CREATED )
-      {
-      GLES30.glEnable(GLES30.GL_DEPTH_TEST);
-      GLES30.glDepthMask(true);
-      }
-    else
-      {
-      GLES30.glDisable(GLES30.GL_DEPTH_TEST);
-      GLES30.glDepthMask(false);
-      }
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/library/DistortedRenderState.java b/src/main/java/org/distorted/library/DistortedRenderState.java
index e6544b3..b73b0c3 100644
--- a/src/main/java/org/distorted/library/DistortedRenderState.java
+++ b/src/main/java/org/distorted/library/DistortedRenderState.java
@@ -35,6 +35,8 @@ class DistortedRenderState
   private static int sStencilFuncFunc, sStencilFuncRef, sStencilFuncMask;
   private static int sStencilOpSfail, sStencilOpDpfail, sStencilOpDppass;
   private static int sDepthFunc;
+  private static int sBlend;
+  private static int sBlendSrc, sBlendDst;
 
   private int mColorMaskR, mColorMaskG, mColorMaskB, mColorMaskA;
   private int mDepthMask;
@@ -44,8 +46,11 @@ class DistortedRenderState
   private int mStencilFuncFunc, mStencilFuncRef, mStencilFuncMask;
   private int mStencilOpSfail, mStencilOpDpfail, mStencilOpDppass;
   private int mDepthFunc;
+  private int mBlend;
+  private int mBlendSrc, mBlendDst;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
+// default: color writes on, depth test and writes on, blending on, stencil off.
 
   DistortedRenderState()
     {
@@ -53,21 +58,27 @@ class DistortedRenderState
     mColorMaskG = 1;
     mColorMaskB = 1;
     mColorMaskA = 1;
-    mDepthMask  = 1;
-    mStencilMask= 0x11111111;
+
     mDepthTest  = 1;
-    mStencilTest= 0;
+    mDepthMask  = 1;
+    mDepthFunc  = GLES30.GL_LEQUAL;
 
+    mBlend      = 1;
+    mBlendSrc   = GLES30.GL_SRC_ALPHA;
+    mBlendDst   = GLES30.GL_ONE_MINUS_SRC_ALPHA;
+
+    mStencilTest     = 0;
+    mStencilMask     = 0x11111111;
     mStencilFuncFunc = GLES30.GL_NEVER;
     mStencilFuncRef  = 0;
     mStencilFuncMask = 0x11111111;
     mStencilOpSfail  = GLES30.GL_KEEP;
     mStencilOpDpfail = GLES30.GL_KEEP;
     mStencilOpDppass = GLES30.GL_KEEP;
-    mDepthFunc       = GLES30.GL_LEQUAL;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
+// reset state of everything to 'unknown'
 
   static void reset()
     {
@@ -75,18 +86,23 @@ class DistortedRenderState
     sColorMaskG = -1;
     sColorMaskB = -1;
     sColorMaskA = -1;
-    sDepthMask  = -1;
-    sStencilMask= -1;
+
     sDepthTest  = -1;
-    sStencilTest= -1;
+    sDepthMask  = -1;
+    sDepthFunc  = -1;
+
+    sBlend      = -1;
+    sBlendSrc   = -1;
+    sBlendDst   = -1;
 
+    sStencilTest     = -1;
+    sStencilMask     = -1;
     sStencilFuncFunc = -1;
     sStencilFuncRef  = -1;
     sStencilFuncMask = -1;
     sStencilOpSfail  = -1;
     sStencilOpDpfail = -1;
     sStencilOpDppass = -1;
-    sDepthFunc       = -1;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -124,6 +140,23 @@ class DistortedRenderState
         }
       }
 
+    if( mBlend!=sBlend )
+      {
+      sBlend = mBlend;
+      if( sBlend==0 ) GLES30.glDisable(GLES30.GL_BLEND);
+      else
+        {
+        GLES30.glEnable(GLES30.GL_BLEND);
+
+        if( mBlendSrc!=sBlendSrc || mBlendDst!=sBlendDst )
+          {
+          sBlendSrc = mBlendSrc;
+          sBlendDst = mBlendDst;
+          GLES30.glBlendFunc(sBlendSrc,sBlendDst);
+          }
+        }
+      }
+
     if( mStencilTest!=sStencilTest )
       {
       sStencilTest = mStencilTest;
@@ -187,6 +220,7 @@ class DistortedRenderState
     {
          if( test==GLES30.GL_DEPTH_TEST   ) mDepthTest   = 1;
     else if( test==GLES30.GL_STENCIL_TEST ) mStencilTest = 1;
+    else if( test==GLES30.GL_BLEND        ) mBlend       = 1;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -195,6 +229,7 @@ class DistortedRenderState
     {
          if( test==GLES30.GL_DEPTH_TEST   ) mDepthTest   = 0;
     else if( test==GLES30.GL_STENCIL_TEST ) mStencilTest = 0;
+    else if( test==GLES30.GL_BLEND        ) mBlend       = 0;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -221,4 +256,13 @@ class DistortedRenderState
     {
     mDepthFunc = func;
     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  void glBlendFunc(int src, int dst)
+    {
+    mBlendSrc = src;
+    mBlendDst = dst;
+    }
+
 }
