commit af27df8771e4c69fbaf80f1224a99090c650275d
Author: leszek <leszek@koltunski.pl>
Date:   Tue Feb 14 15:28:05 2017 +0000

    A lot of different fixes.
    
    A lot of issues still there:
    
    1) if we only render part of the tree, tree isomorphism will sometimes not work correctly
    2) when we change Effects that are inside Trees mid-render, even if we detach() the affected parts of the Tree first, for the last frame the new Effects will be used
    3) Something is wrong wil the System FBOs after app restart (Blur & MultiBlur apps work erratically)

diff --git a/src/main/java/org/distorted/library/DistortedEffects.java b/src/main/java/org/distorted/library/DistortedEffects.java
index df8f1af..1aeb4af 100644
--- a/src/main/java/org/distorted/library/DistortedEffects.java
+++ b/src/main/java/org/distorted/library/DistortedEffects.java
@@ -77,7 +77,7 @@ public class DistortedEffects
   private static long mNextID =0;
   private long mID;
 
-  private static DistortedFramebuffer mBufferFBO = new DistortedFramebuffer(1,1,true);
+  private static DistortedFramebuffer mBufferFBO = new DistortedFramebuffer(true,1,1);
 
   private EffectQueueMatrix      mM;
   private EffectQueueFragment    mF;
diff --git a/src/main/java/org/distorted/library/DistortedFramebuffer.java b/src/main/java/org/distorted/library/DistortedFramebuffer.java
index 2f5d816..a992491 100644
--- a/src/main/java/org/distorted/library/DistortedFramebuffer.java
+++ b/src/main/java/org/distorted/library/DistortedFramebuffer.java
@@ -156,6 +156,18 @@ public class DistortedFramebuffer extends DistortedOutputSurface implements Dist
     create();
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// create 'system' Framebuffers, i.e. those that are used internally by the library.
+// Those do not get removed in onDestroy();
+
+  public DistortedFramebuffer(boolean depthEnabled, int width, int height)
+    {
+    super(width,height,NOT_CREATED_YET,true);
+    mDepthEnabled= depthEnabled;
+    mFBOH[0]     = NOT_CREATED_YET;
+    mDepthH[0]   = NOT_CREATED_YET;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // PUBLIC API
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -169,7 +181,7 @@ public class DistortedFramebuffer extends DistortedOutputSurface implements Dist
   @SuppressWarnings("unused")
   public DistortedFramebuffer(int width, int height, boolean depthEnabled)
     {
-    super(width,height,NOT_CREATED_YET);
+    super(width,height,NOT_CREATED_YET,false);
     mDepthEnabled= depthEnabled;
     mFBOH[0]     = NOT_CREATED_YET;
     mDepthH[0]   = NOT_CREATED_YET;
@@ -186,7 +198,7 @@ public class DistortedFramebuffer extends DistortedOutputSurface implements Dist
   @SuppressWarnings("unused")
   public DistortedFramebuffer(int width, int height)
     {
-    super(width,height,NOT_CREATED_YET);
+    super(width,height,NOT_CREATED_YET,false);
     mDepthEnabled= false;
     mFBOH[0]     = NOT_CREATED_YET;
     mDepthH[0]   = NOT_CREATED_YET;
diff --git a/src/main/java/org/distorted/library/DistortedNode.java b/src/main/java/org/distorted/library/DistortedNode.java
index 638dcc0..9b88072 100644
--- a/src/main/java/org/distorted/library/DistortedNode.java
+++ b/src/main/java/org/distorted/library/DistortedNode.java
@@ -53,11 +53,13 @@ public class DistortedNode implements DistortedAttacheable
     long ID;
     int numPointingNodes;
     int numRendered;
+    ArrayList<Long> key;
     DistortedFramebuffer mFBO;
 
-    NodeData(long id)
+    NodeData(long id, ArrayList<Long> k)
       {
       ID              = id;
+      key             = k;
       numPointingNodes= 1;
       numRendered     = 0;
       mFBO            = null;
@@ -108,6 +110,7 @@ public class DistortedNode implements DistortedAttacheable
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // Debug - print all the Node IDs
 
+  @SuppressWarnings("unused")
   void debug(int depth)
     {
     String tmp="";
@@ -125,6 +128,7 @@ public class DistortedNode implements DistortedAttacheable
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // Debug - print contents of the HashMap
 
+  @SuppressWarnings("unused")
   static void debugMap()
     {
     NodeData tmp;
@@ -140,13 +144,6 @@ public class DistortedNode implements DistortedAttacheable
 
   void treeIsomorphism()
     {
-    android.util.Log.e("NODE", "begin treeIso for Node Surface ID="+mSurface.getID());
-    debug(0);
-    debugMap();
-    android.util.Log.e("NODE", "begin treeIso for Node Surface ID="+mSurface.getID());
-
-    ArrayList<Long> oldList = generateIDList();
-
     for(int i=0; i<mNumChildren[0]; i++)
       {
       mChildren.get(i).treeIsomorphism();
@@ -157,12 +154,8 @@ public class DistortedNode implements DistortedAttacheable
 
     if( newData==null )
       {
-      android.util.Log.d("NODE", "  inserted newData to map, newList="+newList);
-
-
-      newData = new NodeData(++mNextNodeID);
+      newData = new NodeData(++mNextNodeID,newList);
       mMapNodeID.put(newList,newData);
-      debugMap();
       }
     else if( newData.ID != mData.ID )
       {
@@ -177,30 +170,34 @@ public class DistortedNode implements DistortedAttacheable
         {
         if( mData.mFBO!=null )
           {
+          android.util.Log.d("NODE", "copying over FBO of node surfaceID="+mSurface.getID());
+
           newData.mFBO = mData.mFBO;
           fboUsed = true;
           }
         else
           {
+          android.util.Log.d("NODE", "creating new FBO of node surfaceID="+mSurface.getID());
           newData.mFBO = new DistortedFramebuffer(mSurface.getWidth(),mSurface.getHeight());
           }
         }
       if( mNumChildren[0]==0 && newData.mFBO!=null )
         {
+        android.util.Log.d("NODE", "deleting FBO of newData node!!");
+
+
         newData.mFBO.markForDeletion();
         newData.mFBO = null;
         }
 
       if( --mData.numPointingNodes==0 )
         {
-        android.util.Log.d("NODE", "  removed oldData to map, oldList="+oldList);
-
-
-        mMapNodeID.remove(oldList);
-        debugMap();
+        mMapNodeID.remove(mData.key);
 
         if( !fboUsed && mData.mFBO!=null )
           {
+          android.util.Log.d("NODE", "deleting FBO of node surfaceID="+mSurface.getID());
+
           mData.mFBO.markForDeletion();
           mData.mFBO = null;
           }
@@ -208,11 +205,6 @@ public class DistortedNode implements DistortedAttacheable
 
       mData = newData;
       }
-
-    android.util.Log.e("NODE", "end treeIso for Node SurfaceID="+mSurface.getID()+" newList="+newList);
-    debug(0);
-    debugMap();
-    android.util.Log.e("NODE", "end treeIso for Node SurfaceID="+mSurface.getID()+" newList="+newList);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -282,7 +274,7 @@ public class DistortedNode implements DistortedAttacheable
       }
     else
       {
-      mData = new NodeData(++mNextNodeID);   
+      mData = new NodeData(++mNextNodeID,list);
       mMapNodeID.put(list, mData);
       }
     }
@@ -348,7 +340,7 @@ public class DistortedNode implements DistortedAttacheable
       }
     else
       {
-      mData = new NodeData(++mNextNodeID);   
+      mData = new NodeData(++mNextNodeID,list);
       mMapNodeID.put(list, mData);
       }
     }
@@ -458,6 +450,12 @@ public class DistortedNode implements DistortedAttacheable
     if( mNumChildren[0]>0 && mChildren.remove(node) )
       {
       mNumChildren[0]--;
+
+      if( mNumChildren[0]==0 && mData.mFBO!=null )
+        {
+        mData.mFBO.markForDeletion();
+        mData.mFBO = null;
+        }
       }
     }
 
@@ -485,6 +483,12 @@ public class DistortedNode implements DistortedAttacheable
       {
       mNumChildren[0] = 0;
       mChildren.clear();
+
+      if( mData.mFBO!=null )
+        {
+        mData.mFBO.markForDeletion();
+        mData.mFBO = null;
+        }
       }
     }
 
diff --git a/src/main/java/org/distorted/library/DistortedOutputSurface.java b/src/main/java/org/distorted/library/DistortedOutputSurface.java
index 75703a0..0d7d433 100644
--- a/src/main/java/org/distorted/library/DistortedOutputSurface.java
+++ b/src/main/java/org/distorted/library/DistortedOutputSurface.java
@@ -36,9 +36,9 @@ abstract class DistortedOutputSurface extends DistortedSurface implements Distor
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  DistortedOutputSurface(int width, int height, int color)
+  DistortedOutputSurface(int width, int height, int color, boolean system)
     {
-    super(width,height,color);
+    super(width,height,color,system);
 
     mProjectionMatrix = new float[16];
 
@@ -106,16 +106,26 @@ abstract class DistortedOutputSurface extends DistortedSurface implements Distor
     // can result in additional Framebuffers that would need
     // to be created immediately, before the calls to drawRecursive()
 
-    if( DistortedAttachDaemon.toDo() )
+    boolean changed = DistortedAttachDaemon.toDo();
+
+    if( changed )
       {
       for(int i=0; i<mNumChildren; i++)
         {
         mChildren.get(i).treeIsomorphism();
+        mChildren.get(i).debug(0);
         }
+
+      //DistortedNode.debugMap();
       }
 
     toDo();
 
+    if( changed )
+      {
+      DistortedSurface.debugLists();
+      }
+
     for(int i=0; i<mNumChildren; i++)
       {
       mChildren.get(i).drawRecursive(time,this);
@@ -219,6 +229,35 @@ abstract class DistortedOutputSurface extends DistortedSurface implements Distor
     mNumChildren++;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Removes the first occurrence of a specified child from the list of children of our Surface.
+ * <p>
+ * A bit questionable method as there can be many different Nodes attached as children, some
+ * of them having the same Effects but - for instance - different Mesh. Use with care.
+ * <p>
+ * We cannot do this mid-render - actual detachment will be done just before the next render, by the
+ * DistortedAttachDeamon (by calling detachNow())
+ *
+ * @param effects DistortedEffects to remove.
+ */
+  public void detach(DistortedEffects effects)
+    {
+    long id = effects.getID();
+    DistortedNode node;
+
+    for(int i=0; i<mNumChildren; i++)
+      {
+      node = mChildren.get(i);
+
+      if( node.getEffects().getID()==id )
+        {
+        DistortedAttachDaemon.detach(this,node);
+        break;
+        }
+      }
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
  * Removes the first occurrence of a specified child from the list of children of our Surface.
diff --git a/src/main/java/org/distorted/library/DistortedScreen.java b/src/main/java/org/distorted/library/DistortedScreen.java
index da1b469..9101c0b 100644
--- a/src/main/java/org/distorted/library/DistortedScreen.java
+++ b/src/main/java/org/distorted/library/DistortedScreen.java
@@ -46,7 +46,7 @@ public class DistortedScreen extends DistortedOutputSurface
  */
   public DistortedScreen()
     {
-    super(0,0,DONT_CREATE);
+    super(0,0,DONT_CREATE,false);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/library/DistortedSurface.java b/src/main/java/org/distorted/library/DistortedSurface.java
index d76e3e9..944011c 100644
--- a/src/main/java/org/distorted/library/DistortedSurface.java
+++ b/src/main/java/org/distorted/library/DistortedSurface.java
@@ -38,10 +38,12 @@ abstract class DistortedSurface
   private static boolean mToDo = false;
   private static LinkedList<DistortedSurface> mDoneList = new LinkedList<>();
   private static LinkedList<DistortedSurface> mToDoList = new LinkedList<>();
-  private static long mNextID = 0;
+  private static long mNextClientID = 0;
+  private static long mNextSystemID = 0;
 
   private long mID;
   private boolean mMarked;
+  private boolean mSystem;
   int[] mColorH = new int[1];
   int mSizeX, mSizeY;  // in screen space
 
@@ -93,16 +95,25 @@ abstract class DistortedSurface
     for(int i=0; i<num; i++)
       {
       surface = mDoneList.removeFirst();
+      if( surface.mSystem ) mToDoList.add(surface);
+      }
+
+    num = mToDoList.size();
+
+    for(int i=0; i<num; i++)
+      {
+      surface = mToDoList.get(i);
 
-      if( !surface.mMarked )
+      if( !surface.mSystem )
         {
-        surface.recreate();
-        mToDoList.add(surface);
+        mDoneList.remove(i);
+        i--;
+        num--;
         }
       }
 
-    mToDo = true;
-    mNextID = 0;
+    mToDo = (num>0);
+    mNextClientID = 0;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -118,13 +129,49 @@ abstract class DistortedSurface
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  DistortedSurface(int width, int height, int color)
+  @SuppressWarnings("unused")
+  static void debugLists()
+    {
+    android.util.Log.e("Surface", "Done list:");
+    debugList(mDoneList);
+    android.util.Log.e("Surface", "ToDo list:");
+    debugList(mToDoList);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private static void debugList(LinkedList<DistortedSurface> list)
+    {
+    DistortedSurface surface;
+    String str;
+
+    int num = list.size();
+
+    for(int i=0; i<num; i++)
+      {
+      surface = list.get(i);
+
+      if( surface instanceof DistortedFramebuffer ) str = (i+": Framebuffer ");
+      else if( surface instanceof DistortedTexture) str = (i+": Texture     ");
+      else if( surface instanceof DistortedScreen ) str = (i+": Screen      ");
+      else                                          str = (i+": UNKNOWN     ");
+
+      str += ("("+surface.getWidth()+","+surface.getHeight()+") surfaceID:"+surface.getID());
+
+      android.util.Log.e("Surface", str);
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  DistortedSurface(int width, int height, int color, boolean system)
     {
     mSizeX    = width ;
     mSizeY    = height;
     mColorH[0]= color;
     mMarked   = false;
-    mID       = mNextID++;
+    mID       = system ? --mNextSystemID : ++mNextClientID;
+    mSystem   = system;
 
     if( color!=DONT_CREATE )
       {
diff --git a/src/main/java/org/distorted/library/DistortedTexture.java b/src/main/java/org/distorted/library/DistortedTexture.java
index c7248e6..7a26118 100644
--- a/src/main/java/org/distorted/library/DistortedTexture.java
+++ b/src/main/java/org/distorted/library/DistortedTexture.java
@@ -117,7 +117,7 @@ public class DistortedTexture extends DistortedSurface implements DistortedInput
  */
   public DistortedTexture(int width, int height)
     {
-    super(width,height,NOT_CREATED_YET);
+    super(width,height,NOT_CREATED_YET,false);
     mBmp= null;
     }
 
diff --git a/src/main/java/org/distorted/library/EffectQueuePostprocess.java b/src/main/java/org/distorted/library/EffectQueuePostprocess.java
index d32ded9..5086af8 100644
--- a/src/main/java/org/distorted/library/EffectQueuePostprocess.java
+++ b/src/main/java/org/distorted/library/EffectQueuePostprocess.java
@@ -69,7 +69,7 @@ class EffectQueuePostprocess extends EffectQueue
     mQuadTextureInv.put(textureInv).position(0);
     }
 
-  private static DistortedFramebuffer mBufferFBO = new DistortedFramebuffer(1,1,true);
+  private static DistortedFramebuffer mBufferFBO = new DistortedFramebuffer(true,1,1);
 
   private static float[] mMVPMatrix = new float[16];
   private static float[] mTmpMatrix = new float[16];
