commit a5973e7d7a79df9f3f87a0365213ed5a9e996c36
Author: leszek <leszek@koltunski.pl>
Date:   Tue May 2 22:13:06 2017 +0100

    Progress with moving Transform Feedback into library.

diff --git a/src/main/java/org/distorted/examples/feedback/FeedbackRenderer.java b/src/main/java/org/distorted/examples/feedback/FeedbackRenderer.java
index 96f243d..fabc648 100644
--- a/src/main/java/org/distorted/examples/feedback/FeedbackRenderer.java
+++ b/src/main/java/org/distorted/examples/feedback/FeedbackRenderer.java
@@ -64,7 +64,7 @@ class FeedbackRenderer implements GLSurfaceView.Renderer
         }
       catch(Exception ex)
         {
-        android.util.Log.e("MonaLisa", ex.getMessage() );
+        android.util.Log.e("Feedback", ex.getMessage() );
         }
 
       mTF = new TransformFeedback(mView.getContext());
diff --git a/src/main/java/org/distorted/examples/feedback/TransformFeedback.java b/src/main/java/org/distorted/examples/feedback/TransformFeedback.java
index d17df96..7eb60cd 100644
--- a/src/main/java/org/distorted/examples/feedback/TransformFeedback.java
+++ b/src/main/java/org/distorted/examples/feedback/TransformFeedback.java
@@ -35,14 +35,15 @@ import java.nio.FloatBuffer;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-public class TransformFeedback
+class TransformFeedback
     {
-    private static DistortedProgram mFeedbackProgram;
-    private static int mProgramHandle;
+    private DistortedProgram mFeedbackProgram;
+    private int mBufferLength;
+    private int[] mVBO, mTBO;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    public TransformFeedback(final Context context)
+    TransformFeedback(final Context context)
         {
         final Resources resources = context.getResources();
         final InputStream vertStream = resources.openRawResource(org.distorted.library.R.raw.feedback_vertex_shader);
@@ -55,95 +56,58 @@ public class TransformFeedback
         try
           {
           mFeedbackProgram = new DistortedProgram(vertStream,fragStream, vertHeader, fragHeader, Distorted.GLSL, feedback );
-          mProgramHandle = mFeedbackProgram.getProgramHandle();
           }
         catch(Exception ex)
           {
           Log.e("TransformFeedback", "exception creating feedback program: "+ex.getMessage());
           }
+
+        float[] floatData = { 2.0f, 4.0f, 9.0f, 16.0f, 25.0f, 100.0f };
+        mBufferLength = floatData.length * 4;
+        FloatBuffer data = ByteBuffer.allocateDirect(mBufferLength).order(ByteOrder.nativeOrder()).asFloatBuffer();
+        data.put(floatData).position(0);
+
+        mVBO = new int[1];
+        GLES30.glGenBuffers(1, mVBO, 0);
+        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, mVBO[0]);
+        GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, mBufferLength, data, GLES30.GL_STATIC_READ);
+
+        mTBO = new int[1];
+        GLES30.glGenBuffers(1, mTBO, 0);
+        GLES30.glBindBuffer(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, mTBO[0]);
+        GLES30.glBufferData(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, mBufferLength, null, GLES30.GL_STATIC_READ);
         }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
     void render()
         {
-        GLES30.glUseProgram(mProgramHandle);
-        checkGlError("glUseProgram");
+        mFeedbackProgram.useProgram();
 
-        // Create data to fill VBO
-        float[] floatData = { 1.0f, 4.0f, 9.0f, 16.0f, 25.0f, 100.0f };
-        int bufferLength = floatData.length * 4;
-        FloatBuffer data = ByteBuffer.allocateDirect(bufferLength).order(ByteOrder.nativeOrder()).asFloatBuffer();
-        data.put(floatData).position(0);
+        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, mVBO[0]);
+        GLES30.glVertexAttribPointer(mFeedbackProgram.mAttribute[0], 1, GLES30.GL_FLOAT, false, 4, 0);
+        GLES30.glBindBufferBase(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTBO[0]);
 
-        // Create VBO and fill with data
-        int[] vbo = new int[1];
-        GLES30.glGenBuffers(1, vbo, 0);
-        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbo[0]);
-        GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, bufferLength, data, GLES30.GL_STATIC_READ);
-        checkGlError("glBufferData GL_ARRAY_BUFFER");
-
-        // Link created VBO to shader attribute "inValue"
-        int inputAttrib = GLES30.glGetAttribLocation(mProgramHandle, "inValue");
-        GLES30.glEnableVertexAttribArray(inputAttrib);
-        GLES30.glVertexAttribPointer(inputAttrib, 1, GLES30.GL_FLOAT, false, 4, 0);
-        checkGlError("glVertexAttribPointer");
-
-        // Create transform feedback buffer object and bind to transform feedback
-        //  this creates space in a buffer object for the TransformFeedback.
-        int[] tbo = new int[1];
-        GLES30.glGenBuffers(1, tbo, 0);
-        GLES30.glBindBuffer(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, tbo[0]);
-        GLES30.glBufferData(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, bufferLength, null, GLES30.GL_STATIC_READ);
-        GLES30.glBindBufferBase(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, tbo[0]); //very important
-
-        checkGlError("glBindBufferBase");
-
-        // Disable Rasterizer if you just need the data
         GLES30.glEnable(GLES30.GL_RASTERIZER_DISCARD);
-
-        // Start the TransformFeedback, Draw the Arrays, then End the Transform Feedback
         GLES30.glBeginTransformFeedback(GLES30.GL_POINTS);
-        GLES30.glDrawArrays(GLES30.GL_POINTS, 0, bufferLength);
-        checkGlError("glDrawArrays");
+        GLES30.glDrawArrays(GLES30.GL_POINTS, 0, mBufferLength);
         GLES30.glEndTransformFeedback();
-
-        // Reenable Rasterizer if you need it, which you do if you are drawing anything.
         GLES30.glDisable(GLES30.GL_RASTERIZER_DISCARD);
-
-        // Flush out anything in GL before mapping the buffer.
         GLES30.glFlush();
-        checkGlError("pre-glMapBufferRange ");
 
-        // Map the transform feedback buffer to local address space.
-        Buffer mappedBuffer =  GLES30.glMapBufferRange(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER,
-                0, bufferLength, GLES30.GL_MAP_READ_BIT);
-        checkGlError("glMapBufferRange");
+        Buffer mappedBuffer =  GLES30.glMapBufferRange(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, mBufferLength, GLES30.GL_MAP_READ_BIT);
 
-        // Read out the data, here we write to logcat.
-        if (mappedBuffer!=null){
+        if (mappedBuffer!=null)
+            {
             ByteBuffer bb = ((ByteBuffer) mappedBuffer);
             bb.order(ByteOrder.nativeOrder());
             FloatBuffer transformedData = bb.asFloatBuffer();
 
-            Log.d( "TransofrmFeedback", String.format("output values = %f %f %f %f %f %f\n",
+            Log.d( "TransformFeedback", String.format("output values = %f %f %f %f %f %f\n",
                     transformedData.get(), transformedData.get(), transformedData.get(),
                     transformedData.get(), transformedData.get(), transformedData.get() ));
-        }
-        // Don't forget to Unmap the Transform Feeback Buffer.
-        GLES30.glUnmapBuffer(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER);
-        }
+            }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    private static void checkGlError(String op)
-        {
-        int error = GLES30.glGetError();
-
-        if (error != GLES30.GL_NO_ERROR)
-          {
-          String msg = op + ": glError 0x" + Integer.toHexString(error);
-          throw new RuntimeException(msg);
-          }
+        GLES30.glUnmapBuffer(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER);
         }
 }
