commit ed13a5de62017d302cedc71a71186b39b98ac7ae
Author: Leszek Koltunski <leszek@distoretedandroid.org>
Date:   Mon Dec 5 17:10:28 2016 +0000

    Cleanup

diff --git a/src/main/java/org/distorted/library/Distorted.java b/src/main/java/org/distorted/library/Distorted.java
index c3245d4..819f891 100644
--- a/src/main/java/org/distorted/library/Distorted.java
+++ b/src/main/java/org/distorted/library/Distorted.java
@@ -91,7 +91,7 @@ public class Distorted
   static int mTextureCoordH;    // pass in model texture coordinate information.
   static int mProgramH;         // This is a handle to our shading program.
 
-  static DistortedRenderTarget mRenderTarget = new DistortedRenderTarget(0);
+  static DistortedFramebuffer mFramebuffer = new DistortedFramebuffer(0);
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -292,7 +292,7 @@ public class Distorted
  */
   public static void setFov(float fov)
     {
-    mRenderTarget.setProjection(fov,0.0f,0.0f);
+    mFramebuffer.setProjection(fov,0.0f,0.0f);
     }
   
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -362,7 +362,7 @@ public class Distorted
  */
   public static void onSurfaceChanged(int surfaceWidth, int surfaceHeight)
     {
-    mRenderTarget.resize(surfaceWidth,surfaceHeight);
+    mFramebuffer.resize(surfaceWidth,surfaceHeight);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/library/DistortedFramebuffer.java b/src/main/java/org/distorted/library/DistortedFramebuffer.java
new file mode 100644
index 0000000..07bfb11
--- /dev/null
+++ b/src/main/java/org/distorted/library/DistortedFramebuffer.java
@@ -0,0 +1,242 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Copyright 2016 Leszek Koltunski                                                               //
+//                                                                                               //
+// This file is part of Distorted.                                                               //
+//                                                                                               //
+// Distorted is free software: you can redistribute it and/or modify                             //
+// it under the terms of the GNU General Public License as published by                          //
+// the Free Software Foundation, either version 2 of the License, or                             //
+// (at your option) any later version.                                                           //
+//                                                                                               //
+// Distorted is distributed in the hope that it will be useful,                                  //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
+// GNU General Public License for more details.                                                  //
+//                                                                                               //
+// You should have received a copy of the GNU General Public License                             //
+// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+package org.distorted.library;
+
+import android.opengl.GLES20;
+import android.opengl.Matrix;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class DistortedFramebuffer
+  {
+  private static final int TEXTURE_FAILED_TO_CREATE = -1;
+  private static final int TEXTURE_NOT_CREATED_YET  = -2;
+  private static final int TEXTURE_DONT_CREATE      = -3;
+
+  private int mFramebufferID, mTextureID;
+  private float mX, mY;
+  private float mFOV;
+
+  int mWidth,mHeight,mDepth,mDistance;
+  float[] mProjectionMatrix;
+  boolean mMarked;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void createProjection()
+    {
+    float ratio  = (float) mWidth / mHeight;
+    float left   =-ratio;          //
+    float right  = ratio;          // Create a new perspective projection matrix.
+    float bottom = -1.0f;          //
+    float top    =  1.0f;          // any change to those values will have serious consequences!
+    float near, far;
+
+    if( mFOV>0.0f )  // perspective projection
+      {
+      near= (float)(top / Math.tan(mFOV*Math.PI/360));
+      mDistance = (int)(mHeight*near/(top-bottom));
+      far = 2*mDistance-near;
+
+      Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
+      }
+    else                      // parallel projection
+      {
+      near= (float)(top / Math.tan(Math.PI/360));
+      mDistance = (int)(mHeight*near/(top-bottom));
+      far = 2*mDistance-near;
+
+      Matrix.orthoM(mProjectionMatrix, 0, -mWidth/2, mWidth/2,-mHeight/2, mHeight/2, near, far);
+      }
+
+    mDepth = (int)((far-near)/2);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// must be called form a thread holding OpenGL Context
+
+  private boolean createFBO()
+    {
+    int[] textureIds = new int[1];
+    GLES20.glGenTextures(1, textureIds, 0);
+    mTextureID = textureIds[0];
+    int[] mFBORenderToTexture = new int[1];
+
+    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);
+    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
+    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
+    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
+    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
+    GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, mWidth, mHeight, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
+
+    GLES20.glGenFramebuffers(1, mFBORenderToTexture, 0);
+    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFBORenderToTexture[0]);
+    GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, mTextureID, 0);
+    int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
+
+    if(status != GLES20.GL_FRAMEBUFFER_COMPLETE)
+      {
+      android.util.Log.e("RenderTarget", "failed to create framebuffer, error="+status);
+
+      GLES20.glDeleteTextures(1, textureIds, 0);
+      GLES20.glDeleteFramebuffers(1, mFBORenderToTexture, 0);
+      mFramebufferID = 0;
+      mTextureID = TEXTURE_FAILED_TO_CREATE;
+      return false;
+      }
+
+    mFramebufferID = mFBORenderToTexture[0];
+
+    return true;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// must be called form a thread holding OpenGL Context
+
+  private void deleteFBO()
+    {
+    int[] textureIds = new int[1];
+    int[] mFBORenderToTexture = new int[1];
+
+    textureIds[0] = mTextureID;
+    mFBORenderToTexture[0] = mFramebufferID;
+
+    GLES20.glDeleteTextures(1, textureIds, 0);
+    GLES20.glDeleteFramebuffers(1, mFBORenderToTexture, 0);
+
+    mFramebufferID = 0;
+    mTextureID = TEXTURE_NOT_CREATED_YET;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// must be called form a thread holding OpenGL Context
+
+  void release()
+    {
+    if( mTextureID>=0 ) deleteFBO();
+
+    mProjectionMatrix = null;
+    mMarked = false;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  void reset()
+    {
+    mTextureID = TEXTURE_NOT_CREATED_YET;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// PUBLIC API
+
+  public DistortedFramebuffer(int width, int height)
+    {
+    mProjectionMatrix = new float[16];
+
+    mHeight        = height;
+    mWidth         = width;
+    mFramebufferID = 0;
+    mTextureID     = TEXTURE_NOT_CREATED_YET;
+    mFOV           = 60.0f;
+    mX             = 0.0f;
+    mY             = 0.0f;
+
+    mMarked = false;
+
+    createProjection();
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public DistortedFramebuffer(int fbo)
+    {
+    mProjectionMatrix = new float[16];
+
+    mFramebufferID = fbo;
+    mTextureID     = TEXTURE_DONT_CREATE;
+    mFOV           = 60.0f;
+    mX             = 0.0f;
+    mY             = 0.0f;
+
+    mMarked = false;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void markForDeletion()
+    {
+    DistortedFramebufferList.markForDeletion();
+    mMarked = true;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void setProjection(float FOV, float x, float y)
+    {
+    mFOV = FOV;
+    mX   = x;
+    mY   = y;
+
+    createProjection();
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void resize(int width, int height)
+    {
+    if( mWidth!=width || mHeight!=height )
+      {
+      mWidth = width;
+      mHeight= height;
+
+      createProjection();
+
+      if( mTextureID>0 ) markForDeletion();
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int getFBO()
+    {
+    return mFramebufferID;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// set this as Render Target to draw to. Must be called from a thread holding OpenGL context.
+
+  public void setOutput()
+    {
+    if( mTextureID==TEXTURE_NOT_CREATED_YET ) createFBO();
+
+    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFramebufferID);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// set this as Render Target to draw from. Must be called from a thread holding OpenGL context.
+
+  public void setInput()
+    {
+    if( mTextureID==TEXTURE_NOT_CREATED_YET ) createFBO();
+
+    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);
+    }
+
+  }
diff --git a/src/main/java/org/distorted/library/DistortedFramebufferList.java b/src/main/java/org/distorted/library/DistortedFramebufferList.java
new file mode 100644
index 0000000..469bcd6
--- /dev/null
+++ b/src/main/java/org/distorted/library/DistortedFramebufferList.java
@@ -0,0 +1,77 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Copyright 2016 Leszek Koltunski                                                               //
+//                                                                                               //
+// This file is part of Distorted.                                                               //
+//                                                                                               //
+// Distorted is free software: you can redistribute it and/or modify                             //
+// it under the terms of the GNU General Public License as published by                          //
+// the Free Software Foundation, either version 2 of the License, or                             //
+// (at your option) any later version.                                                           //
+//                                                                                               //
+// Distorted is distributed in the hope that it will be useful,                                  //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
+// GNU General Public License for more details.                                                  //
+//                                                                                               //
+// You should have received a copy of the GNU General Public License                             //
+// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+package org.distorted.library;
+
+import java.util.LinkedList;
+import java.util.Iterator;
+
+/**
+ * List of all DistortedRenderTarget objects currently created by the application.
+ *
+ * The point: we need to be able ot mark RenderTargets for deletion, and delete all marked
+ * objects later at a convenient time. Thus we keep all of them in a LinkedList here.
+ */
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+final class DistortedFramebufferList
+  {
+  private static boolean mMarked = false;
+  private static LinkedList<DistortedFramebuffer> mList = new LinkedList<>();
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  static synchronized void add(DistortedFramebuffer drt)
+    {
+    mList.add(drt);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  static synchronized void markForDeletion()
+    {
+    mMarked = true;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// must be called form a thread holding OpenGL Context
+
+  static synchronized void deleteAllMarked()
+    {
+    if( mMarked )
+      {
+      DistortedFramebuffer tmp;
+      Iterator<DistortedFramebuffer> iterator = mList.iterator();
+
+      while(iterator.hasNext())
+        {
+        tmp = iterator.next();
+
+        if( tmp.mMarked )
+          {
+          tmp.release();
+          iterator.remove();
+          }
+        }
+
+      mMarked = false;
+      }
+    }
+  }
diff --git a/src/main/java/org/distorted/library/DistortedNode.java b/src/main/java/org/distorted/library/DistortedNode.java
index fa8ffbe..687f4e4 100644
--- a/src/main/java/org/distorted/library/DistortedNode.java
+++ b/src/main/java/org/distorted/library/DistortedNode.java
@@ -48,14 +48,14 @@ public class DistortedNode
     {
     long ID;
     int numPointingNodes;
-    DistortedRenderTarget mDRT;
+    DistortedFramebuffer mDF;
     boolean mRendered;
 
     NodeData(long id)
       {
       ID              = id;
       numPointingNodes= 1;
-      mDRT            = null;
+      mDF             = null;
       mRendered       = false;
       }
     }
@@ -82,7 +82,7 @@ public class DistortedNode
   
 ///////////////////////////////////////////////////////////////////////////////////////////////////
   
-  private void drawRecursive(long currTime, DistortedRenderTarget drt)
+  private void drawRecursive(long currTime, DistortedFramebuffer df)
     {
     if( mNumChildren[0]<=0 )
       {
@@ -93,7 +93,7 @@ public class DistortedNode
       if( mData.mRendered==false )
         {
         mData.mRendered = true;
-        mData.mDRT.setOutput();
+        mData.mDF.setOutput();
 
         GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
         GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
@@ -101,23 +101,23 @@ public class DistortedNode
         if( mObject.mBitmapSet[0] )
           {
           GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mObject.mTextureDataH[0]);
-          mObject.drawNoEffectsPriv(mData.mDRT);
+          mObject.drawNoEffectsPriv(mData.mDF);
           }
       
         synchronized(this)
           {
           for(int i=0; i<mNumChildren[0]; i++)
             {
-            mChildren.get(i).drawRecursive(currTime, mData.mDRT);
+            mChildren.get(i).drawRecursive(currTime, mData.mDF);
             }
           }
         }
 
-      drt.setOutput();
-      mData.mDRT.setInput();   // this is safe because we must have called createFBO() above before.
+      df.setOutput();
+      mData.mDF.setInput();   // this is safe because we must have called createFBO() above before.
       }
     
-    mObject.drawPriv(currTime, drt);
+    mObject.drawPriv(currTime, df);
     }
   
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -173,8 +173,8 @@ public class DistortedNode
       if( otherNodesPoint )  mData = new NodeData(++mNextNodeID);
       else                   mData.ID = ++mNextNodeID;  // numPointingNodes must be 1 already
 
-      if( newList.size()>1 && mData.mDRT==null )
-        mData.mDRT = new DistortedRenderTarget(mObject.getWidth(), mObject.getHeight());
+      if( newList.size()>1 && mData.mDF==null )
+        mData.mDF = new DistortedFramebuffer(mObject.getWidth(), mObject.getHeight());
 
       mMapNodeID.put(newList, mData);
       }
@@ -197,9 +197,9 @@ public class DistortedNode
       {
       tmp = mMapNodeID.get(key);
           
-      if( tmp.mDRT != null )
+      if( tmp.mDF != null )
         {
-    	  tmp.mDRT.reset();
+    	  tmp.mDF.reset();
         tmp.mRendered  = false;
         }
       }
@@ -445,10 +445,8 @@ public class DistortedNode
     GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
     GLES20.glUniform1i(Distorted.mTextureUniformH, 0);  
 
-    DistortedRenderTargetList.deleteAllMarked();
-
     markRecursive();
-    drawRecursive(currTime,Distorted.mRenderTarget);
+    drawRecursive(currTime,Distorted.mFramebuffer);
     }
  
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/library/DistortedObject.java b/src/main/java/org/distorted/library/DistortedObject.java
index efc214e..71a12fc 100644
--- a/src/main/java/org/distorted/library/DistortedObject.java
+++ b/src/main/java/org/distorted/library/DistortedObject.java
@@ -159,12 +159,12 @@ public abstract class DistortedObject
   
 ///////////////////////////////////////////////////////////////////////////////////////////////////
    
-  void drawPriv(long currTime, DistortedRenderTarget drt)
+  void drawPriv(long currTime, DistortedFramebuffer df)
     {
-    GLES20.glViewport(0, 0, drt.mWidth, drt.mHeight);
+    GLES20.glViewport(0, 0, df.mWidth, df.mHeight);
       
     mM.compute(currTime);
-    mM.send(drt);
+    mM.send(df);
       
     mV.compute(currTime);
     mV.send();
@@ -177,10 +177,10 @@ public abstract class DistortedObject
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
    
-  void drawNoEffectsPriv(DistortedRenderTarget drt)
+  void drawNoEffectsPriv(DistortedFramebuffer df)
     {
-    GLES20.glViewport(0, 0, drt.mWidth, drt.mHeight);
-    mM.sendZero(drt);
+    GLES20.glViewport(0, 0, df.mWidth, df.mHeight);
+    mM.sendZero(df);
     mV.sendZero();
     mF.sendZero();
     mGrid.draw();
@@ -274,8 +274,10 @@ public abstract class DistortedObject
     GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
     GLES20.glUniform1i(Distorted.mTextureUniformH, 0);
     GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataH[0]);
-      
-    drawPriv(currTime, Distorted.mRenderTarget);
+
+    DistortedFramebufferList.deleteAllMarked();
+
+    drawPriv(currTime, Distorted.mFramebuffer);
     }
  
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/library/DistortedRenderTarget.java b/src/main/java/org/distorted/library/DistortedRenderTarget.java
deleted file mode 100644
index 440d0c3..0000000
--- a/src/main/java/org/distorted/library/DistortedRenderTarget.java
+++ /dev/null
@@ -1,243 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Copyright 2016 Leszek Koltunski                                                               //
-//                                                                                               //
-// This file is part of Distorted.                                                               //
-//                                                                                               //
-// Distorted is free software: you can redistribute it and/or modify                             //
-// it under the terms of the GNU General Public License as published by                          //
-// the Free Software Foundation, either version 2 of the License, or                             //
-// (at your option) any later version.                                                           //
-//                                                                                               //
-// Distorted is distributed in the hope that it will be useful,                                  //
-// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
-// GNU General Public License for more details.                                                  //
-//                                                                                               //
-// You should have received a copy of the GNU General Public License                             //
-// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-package org.distorted.library;
-
-import android.opengl.GLES20;
-import android.opengl.Matrix;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-public class DistortedRenderTarget
-  {
-  private static final int TEXTURE_FAILED_TO_CREATE = -1;
-  private static final int TEXTURE_NOT_CREATED_YET  = -2;
-  private static final int TEXTURE_DONT_CREATE      = -3;
-
-  private int mFramebufferID, mTextureID;
-  private float mX, mY;
-  private float mFOV;
-
-  int mWidth,mHeight,mDepth,mDistance;
-  float[] mProjectionMatrix;
-
-  boolean mMarked;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void createProjection()
-    {
-    float ratio  = (float) mWidth / mHeight;
-    float left   =-ratio;          //
-    float right  = ratio;          // Create a new perspective projection matrix.
-    float bottom = -1.0f;          //
-    float top    =  1.0f;          // any change to those values will have serious consequences!
-    float near, far;
-
-    if( mFOV>0.0f )  // perspective projection
-      {
-      near= (float)(top / Math.tan(mFOV*Math.PI/360));
-      mDistance = (int)(mHeight*near/(top-bottom));
-      far = 2*mDistance-near;
-
-      Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
-      }
-    else                      // parallel projection
-      {
-      near= (float)(top / Math.tan(Math.PI/360));
-      mDistance = (int)(mHeight*near/(top-bottom));
-      far = 2*mDistance-near;
-
-      Matrix.orthoM(mProjectionMatrix, 0, -mWidth/2, mWidth/2,-mHeight/2, mHeight/2, near, far);
-      }
-
-    mDepth = (int)((far-near)/2);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// must be called form a thread holding OpenGL Context
-
-  private boolean createFBO()
-    {
-    int[] textureIds = new int[1];
-    GLES20.glGenTextures(1, textureIds, 0);
-    mTextureID = textureIds[0];
-    int[] mFBORenderToTexture = new int[1];
-
-    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);
-    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
-    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
-    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
-    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
-    GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, mWidth, mHeight, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
-
-    GLES20.glGenFramebuffers(1, mFBORenderToTexture, 0);
-    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFBORenderToTexture[0]);
-    GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, mTextureID, 0);
-    int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
-
-    if(status != GLES20.GL_FRAMEBUFFER_COMPLETE)
-      {
-      android.util.Log.e("RenderTarget", "failed to create framebuffer, error="+status);
-
-      GLES20.glDeleteTextures(1, textureIds, 0);
-      GLES20.glDeleteFramebuffers(1, mFBORenderToTexture, 0);
-      mFramebufferID = 0;
-      mTextureID = TEXTURE_FAILED_TO_CREATE;
-      return false;
-      }
-
-    mFramebufferID = mFBORenderToTexture[0];
-
-    return true;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// must be called form a thread holding OpenGL Context
-
-  private void deleteFBO()
-    {
-    int[] textureIds = new int[1];
-    int[] mFBORenderToTexture = new int[1];
-
-    textureIds[0] = mTextureID;
-    mFBORenderToTexture[0] = mFramebufferID;
-
-    GLES20.glDeleteTextures(1, textureIds, 0);
-    GLES20.glDeleteFramebuffers(1, mFBORenderToTexture, 0);
-
-    mFramebufferID = 0;
-    mTextureID = TEXTURE_NOT_CREATED_YET;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// must be called form a thread holding OpenGL Context
-
-  void release()
-    {
-    if( mTextureID>=0 ) deleteFBO();
-
-    mProjectionMatrix = null;
-    mMarked = false;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  void reset()
-    {
-    mTextureID = TEXTURE_NOT_CREATED_YET;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// PUBLIC API
-
-  public DistortedRenderTarget(int width, int height)
-    {
-    mProjectionMatrix = new float[16];
-
-    mHeight        = height;
-    mWidth         = width;
-    mFramebufferID = 0;
-    mTextureID     = TEXTURE_NOT_CREATED_YET;
-    mFOV           = 60.0f;
-    mX             = 0.0f;
-    mY             = 0.0f;
-
-    mMarked = false;
-
-    createProjection();
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public DistortedRenderTarget(int fbo)
-    {
-    mProjectionMatrix = new float[16];
-
-    mFramebufferID = fbo;
-    mTextureID     = TEXTURE_DONT_CREATE;
-    mFOV           = 60.0f;
-    mX             = 0.0f;
-    mY             = 0.0f;
-
-    mMarked = false;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void markForDeletion()
-    {
-    DistortedRenderTargetList.markForDeletion();
-    mMarked = true;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void setProjection(float FOV, float x, float y)
-    {
-    mFOV = FOV;
-    mX   = x;
-    mY   = y;
-
-    createProjection();
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void resize(int width, int height)
-    {
-    if( mWidth!=width || mHeight!=height )
-      {
-      mWidth = width;
-      mHeight= height;
-
-      createProjection();
-
-      if( mTextureID>0 ) markForDeletion();
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public int getFBO()
-    {
-    return mFramebufferID;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// set this as Render Target to draw to. Must be called from a thread holding OpenGL context.
-
-  public void setOutput()
-    {
-    if( mTextureID==TEXTURE_NOT_CREATED_YET ) createFBO();
-
-    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFramebufferID);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// set this as Render Target to draw from. Must be called from a thread holding OpenGL context.
-
-  public void setInput()
-    {
-    if( mTextureID==TEXTURE_NOT_CREATED_YET ) createFBO();
-
-    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);
-    }
-
-  }
diff --git a/src/main/java/org/distorted/library/DistortedRenderTargetList.java b/src/main/java/org/distorted/library/DistortedRenderTargetList.java
deleted file mode 100644
index 813c250..0000000
--- a/src/main/java/org/distorted/library/DistortedRenderTargetList.java
+++ /dev/null
@@ -1,77 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Copyright 2016 Leszek Koltunski                                                               //
-//                                                                                               //
-// This file is part of Distorted.                                                               //
-//                                                                                               //
-// Distorted is free software: you can redistribute it and/or modify                             //
-// it under the terms of the GNU General Public License as published by                          //
-// the Free Software Foundation, either version 2 of the License, or                             //
-// (at your option) any later version.                                                           //
-//                                                                                               //
-// Distorted is distributed in the hope that it will be useful,                                  //
-// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
-// GNU General Public License for more details.                                                  //
-//                                                                                               //
-// You should have received a copy of the GNU General Public License                             //
-// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-package org.distorted.library;
-
-import java.util.LinkedList;
-import java.util.Iterator;
-
-/**
- * List of all DistortedRenderTarget objects currently created by the application.
- *
- * The point: we need to be able ot mark RenderTargets for deletion, and delete all marked
- * objects later at a convenient time. Thus we keep all of them in a LinkedList here.
- */
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-final class DistortedRenderTargetList
-  {
-  private static boolean mMarked = false;
-  private static LinkedList<DistortedRenderTarget> mList = new LinkedList<>();
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  static synchronized void add(DistortedRenderTarget drt)
-    {
-    mList.add(drt);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  static synchronized void markForDeletion()
-    {
-    mMarked = true;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// must be called form a thread holding OpenGL Context
-
-  static synchronized void deleteAllMarked()
-    {
-    if( mMarked )
-      {
-      DistortedRenderTarget tmp;
-      Iterator<DistortedRenderTarget> iterator = mList.iterator();
-
-      while(iterator.hasNext())
-        {
-        tmp = iterator.next();
-
-        if( tmp.mMarked )
-          {
-          tmp.release();
-          iterator.remove();
-          }
-        }
-
-      mMarked = false;
-      }
-    }
-  }
diff --git a/src/main/java/org/distorted/library/EffectQueueMatrix.java b/src/main/java/org/distorted/library/EffectQueueMatrix.java
index 8db7619..e0afd41 100644
--- a/src/main/java/org/distorted/library/EffectQueueMatrix.java
+++ b/src/main/java/org/distorted/library/EffectQueueMatrix.java
@@ -153,10 +153,10 @@ class EffectQueueMatrix extends EffectQueue
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // here construct the ModelView Matrix
 
-  synchronized void send(DistortedRenderTarget drt)
+  synchronized void send(DistortedFramebuffer df)
     {
     Matrix.setIdentityM(mViewMatrix, 0);
-    Matrix.translateM(mViewMatrix, 0, -drt.mWidth/2, drt.mHeight/2, -drt.mDistance);
+    Matrix.translateM(mViewMatrix, 0, -df.mWidth/2, df.mHeight/2, -df.mDistance);
     
     float x,y,z, sx,sy,sz;
    
@@ -230,10 +230,10 @@ class EffectQueueMatrix extends EffectQueue
       }
    
     Matrix.translateM(mViewMatrix, 0, mObjHalfX,-mObjHalfY, 0);
-    Matrix.multiplyMM(mMVPMatrix, 0, drt.mProjectionMatrix, 0, mViewMatrix, 0);
+    Matrix.multiplyMM(mMVPMatrix, 0, df.mProjectionMatrix, 0, mViewMatrix, 0);
     
     GLES20.glUniform3f( mObjDH , mObjHalfX, mObjHalfY, mObjHalfZ);
-    GLES20.glUniform1f( mDepthH, drt.mDepth);
+    GLES20.glUniform1f( mDepthH, df.mDepth);
     GLES20.glUniformMatrix4fv(mMVMatrixH , 1, false, mViewMatrix, 0);
     GLES20.glUniformMatrix4fv(mMVPMatrixH, 1, false, mMVPMatrix , 0);
     }
@@ -241,14 +241,14 @@ class EffectQueueMatrix extends EffectQueue
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // here construct the ModelView Matrix, but without any effects
 
-  synchronized void sendZero(DistortedRenderTarget drt)
+  synchronized void sendZero(DistortedFramebuffer df)
     {
     Matrix.setIdentityM(mTmpMatrix, 0);
-    Matrix.translateM(mTmpMatrix, 0, mObjHalfX-drt.mWidth/2, drt.mHeight/2-mObjHalfY, -drt.mDistance);
-    Matrix.multiplyMM(mMVPMatrix, 0, drt.mProjectionMatrix, 0, mTmpMatrix, 0);
+    Matrix.translateM(mTmpMatrix, 0, mObjHalfX-df.mWidth/2, df.mHeight/2-mObjHalfY, -df.mDistance);
+    Matrix.multiplyMM(mMVPMatrix, 0, df.mProjectionMatrix, 0, mTmpMatrix, 0);
     
     GLES20.glUniform3f( mObjDH , mObjHalfX, mObjHalfY, mObjHalfZ);
-    GLES20.glUniform1f( mDepthH, drt.mDepth);
+    GLES20.glUniform1f( mDepthH, df.mDepth);
     GLES20.glUniformMatrix4fv(mMVMatrixH , 1, false, mTmpMatrix, 0);
     GLES20.glUniformMatrix4fv(mMVPMatrixH, 1, false, mMVPMatrix, 0);
     }
