commit 6ce08079bff3f6babd3bff4af6b976d8191897e3
Author: Leszek Koltunski <leszek@distoretedandroid.org>
Date:   Fri May 5 15:26:06 2017 +0100

    This commit (and reading the OpenGL ES 3.0 spec) pretty conclusively proves that, sadly, Nexus 4's Transform Feedback implementation is incomplete (doesn't work with GL_TRIANGLES primitiveMode)

diff --git a/src/main/java/org/distorted/examples/TableOfContents.java b/src/main/java/org/distorted/examples/TableOfContents.java
index 589c6f4..a41d17e 100644
--- a/src/main/java/org/distorted/examples/TableOfContents.java
+++ b/src/main/java/org/distorted/examples/TableOfContents.java
@@ -85,7 +85,16 @@ public class TableOfContents extends ListActivity
    final SparseArray<Class<? extends Activity>> activityMapping = new SparseArray<>();
       
    int i = 0;
-   
+
+   {
+      final Map<String, Object> item = new HashMap<>();
+      item.put(ITEM_IMAGE, R.drawable.icon_example_feedback);
+      item.put(ITEM_TITLE, (i+1)+". "+getText(R.string.example_feedback));
+      item.put(ITEM_SUBTITLE, getText(R.string.example_feedback_subtitle));
+      data.add(item);
+      activityMapping.put(i++, FeedbackActivity.class);
+   }
+
    {
       final Map<String, Object> item = new HashMap<>();
       item.put(ITEM_IMAGE, R.drawable.icon_example_monalisa);
@@ -347,15 +356,6 @@ public class TableOfContents extends ListActivity
       activityMapping.put(i++, MultiblurActivity.class);
    }
 
-   {
-      final Map<String, Object> item = new HashMap<>();
-      item.put(ITEM_IMAGE, R.drawable.icon_example_feedback);
-      item.put(ITEM_TITLE, (i+1)+". "+getText(R.string.example_feedback));
-      item.put(ITEM_SUBTITLE, getText(R.string.example_feedback_subtitle));
-      data.add(item);
-      activityMapping.put(i++, FeedbackActivity.class);
-   }
-
    final SimpleAdapter dataAdapter = new SimpleAdapter(this, data, R.layout.toc_item, new String[] {ITEM_IMAGE, ITEM_TITLE, ITEM_SUBTITLE}, new int[] {R.id.Image, R.id.Title, R.id.SubTitle});
    setListAdapter(dataAdapter);  
       
diff --git a/src/main/java/org/distorted/examples/feedback/FeedbackRenderer.java b/src/main/java/org/distorted/examples/feedback/FeedbackRenderer.java
index f2824d2..0d034c5 100644
--- a/src/main/java/org/distorted/examples/feedback/FeedbackRenderer.java
+++ b/src/main/java/org/distorted/examples/feedback/FeedbackRenderer.java
@@ -42,7 +42,7 @@ class FeedbackRenderer implements GLSurfaceView.Renderer
     private final int BYTESFLOAT = 4;
     private final int POSITION   = 3;
 
-    private final boolean USEPOINTS=false;
+    private final boolean USEPOINTS=true;
 
     private GLSurfaceView mView;
     private DistortedProgram mFeedbackProgram;
@@ -62,19 +62,27 @@ class FeedbackRenderer implements GLSurfaceView.Renderer
       {
       mFeedbackProgram.useProgram();
 
-      int numVertices = (USEPOINTS ? mVertices : 3*(mVertices-2));
-
       GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, mVBO[0]);
-      GLES30.glVertexAttribPointer(mFeedbackProgram.mAttribute[0], USEPOINTS ? 1:POSITION, GLES30.GL_FLOAT, false, 0, 0);
+      GLES30.glVertexAttribPointer(mFeedbackProgram.mAttribute[0], POSITION, GLES30.GL_FLOAT, false, 0, 0);
       GLES30.glBindBufferBase(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTBO[0]);
 
       GLES30.glEnable(GLES30.GL_RASTERIZER_DISCARD);
       GLES30.glBeginTransformFeedback( USEPOINTS ? GLES30.GL_POINTS : GLES30.GL_TRIANGLES);
-      GLES30.glDrawArrays( USEPOINTS ? GLES30.GL_POINTS : GLES30.GL_TRIANGLE_STRIP, 0, USEPOINTS ? mVertices*POSITION : mVertices);
+      GLES30.glDrawArrays( USEPOINTS ? GLES30.GL_POINTS : GLES30.GL_TRIANGLE_STRIP, 0, mVertices);
+
+      int error = GLES30.glGetError();
+
+      if( error != GLES30.GL_NO_ERROR )
+        {
+        throw new RuntimeException("DrawArrays: glError 0x" + Integer.toHexString(error));
+        }
+
       GLES30.glEndTransformFeedback();
       GLES30.glDisable(GLES30.GL_RASTERIZER_DISCARD);
       GLES30.glFlush();
 
+      int numVertices = 3*(mVertices);
+
       Buffer mappedBuffer =  GLES30.glMapBufferRange(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, numVertices*POSITION*BYTESFLOAT, GLES30.GL_MAP_READ_BIT);
       FloatBuffer fb = ((ByteBuffer) mappedBuffer).order(ByteOrder.nativeOrder()).asFloatBuffer();
       String msg = "";
@@ -115,15 +123,6 @@ class FeedbackRenderer implements GLSurfaceView.Renderer
       String header= "#version 300 es\n";
       String[] feedback = { "outValue" };
 
-      if(USEPOINTS)
-        {
-        header += "#define USEPOINTS 1\n";
-        }
-      else
-        {
-        header += "#define USEPOINTS 0\n";
-        }
-
       try
         {
         mFeedbackProgram = new DistortedProgram(vertStream,fragStream, header, header, glsl, feedback );
@@ -141,15 +140,13 @@ class FeedbackRenderer implements GLSurfaceView.Renderer
       mVBO = new int[1];
       GLES30.glGenBuffers(1, mVBO, 0);
       GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, mVBO[0]);
-      GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, mVertices*POSITION*BYTESFLOAT, data, GLES30.GL_STATIC_READ);
+      GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, mVertices*POSITION*BYTESFLOAT, data, GLES30.GL_STATIC_DRAW);
       GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0);
 
-      int numVertices = (USEPOINTS ? mVertices : 3*(mVertices-2));
-
       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, numVertices*POSITION*BYTESFLOAT, null, GLES30.GL_STATIC_READ);
+      GLES30.glBufferData(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 3*(mVertices)*POSITION*BYTESFLOAT, null, GLES30.GL_STATIC_READ);
       GLES30.glBindBuffer(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0);
       }
 }
