commit bbf09f756cb6b817a8b4bef122fc2e9cf68320af
Author: leszek <leszek@koltunski.pl>
Date:   Fri May 5 01:17:27 2017 +0100

    Progress with TransferFeedback app - introduce two modes: USEPOINTS 'true' or 'false'.
    
    On Nexus5X, it works with 'true' and 'false'. On Nexus 4, it works with 'true', but returns GL_INVALID_OPERATION with 'false'.

diff --git a/src/main/java/org/distorted/examples/feedback/FeedbackRenderer.java b/src/main/java/org/distorted/examples/feedback/FeedbackRenderer.java
index 0e2f7e3..f2824d2 100644
--- a/src/main/java/org/distorted/examples/feedback/FeedbackRenderer.java
+++ b/src/main/java/org/distorted/examples/feedback/FeedbackRenderer.java
@@ -22,7 +22,6 @@ package org.distorted.examples.feedback;
 import android.content.res.Resources;
 import android.opengl.GLES30;
 import android.opengl.GLSurfaceView;
-import android.util.Log;
 
 import org.distorted.library.Distorted;
 import org.distorted.library.program.DistortedProgram;
@@ -41,10 +40,13 @@ import javax.microedition.khronos.opengles.GL10;
 class FeedbackRenderer implements GLSurfaceView.Renderer
 {
     private final int BYTESFLOAT = 4;
+    private final int POSITION   = 3;
+
+    private final boolean USEPOINTS=false;
 
     private GLSurfaceView mView;
     private DistortedProgram mFeedbackProgram;
-    private int mBufferLength;
+    private int mVertices;
     private int[] mVBO, mTBO;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -60,24 +62,26 @@ 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], 1, GLES30.GL_FLOAT, false, 0, 0);
+      GLES30.glVertexAttribPointer(mFeedbackProgram.mAttribute[0], USEPOINTS ? 1: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(GLES30.GL_POINTS);
-      GLES30.glDrawArrays(GLES30.GL_POINTS, 0, mBufferLength);
+      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.glEndTransformFeedback();
       GLES30.glDisable(GLES30.GL_RASTERIZER_DISCARD);
       GLES30.glFlush();
 
-      Buffer mappedBuffer =  GLES30.glMapBufferRange(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, mBufferLength*BYTESFLOAT, GLES30.GL_MAP_READ_BIT);
+      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 = "";
 
-      if (mappedBuffer!=null)
-        {
-        FloatBuffer fb = ((ByteBuffer) mappedBuffer).order(ByteOrder.nativeOrder()).asFloatBuffer();
-        Log.d( "Feedback", String.format("values = %.2f %.2f %.2f %.2f %.2f %.2f\n",  fb.get(), fb.get(), fb.get(), fb.get(), fb.get(), fb.get() ));
-        }
+      for(int i=0; i<numVertices*POSITION; i++) msg += (" "+fb.get(i));
+
+      android.util.Log.d( "Feedback", msg);
 
       GLES30.glUnmapBuffer(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER);
       GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0);
@@ -111,30 +115,41 @@ 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 );
         }
       catch(Exception ex)
         {
-        Log.e("TransformFeedback", "exception creating feedback program: "+ex.getMessage());
+        android.util.Log.e("Feedback", "exception creating feedback program: "+ex.getMessage());
         }
 
-      float[] floatData = { 1.0f, 4.0f, 9.0f, 16.0f, 25.0f, 100.0f };
-      mBufferLength = floatData.length;
-      FloatBuffer data = ByteBuffer.allocateDirect(mBufferLength*BYTESFLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();
+      float[] floatData = { 1.0f,4.0f,9.0f, 16.0f,25.0f,36.0f, 49.0f,64.0f,81.0f,  100.0f,121.0f,144.0f};
+      mVertices = floatData.length/POSITION;
+      FloatBuffer data = ByteBuffer.allocateDirect(mVertices*POSITION*BYTESFLOAT).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*BYTESFLOAT, data, GLES30.GL_STATIC_READ);
+      GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, mVertices*POSITION*BYTESFLOAT, data, GLES30.GL_STATIC_READ);
       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, mBufferLength*BYTESFLOAT, null, GLES30.GL_STATIC_READ);
+      GLES30.glBufferData(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, numVertices*POSITION*BYTESFLOAT, null, GLES30.GL_STATIC_READ);
       GLES30.glBindBuffer(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0);
       }
 }
diff --git a/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java b/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java
index 94282a3..aeb0a55 100644
--- a/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java
+++ b/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java
@@ -137,7 +137,7 @@ class MonaLisaRenderer implements GLSurfaceView.Renderer
       if( mTexture==null ) mTexture = new DistortedTexture(bmpWidth,bmpHeight);
 
       // likewise the Mesh
-      if( mMesh==null ) mMesh = new MeshFlat(1,1);//(9,9*bmpHeight/bmpWidth);
+      if( mMesh==null ) mMesh = new MeshFlat(2,2);//(9,9*bmpHeight/bmpWidth);
 
       // even if mTexture wasn't null, we still need to call setTexture() on it
       // because every time activity goes to background, its OpenGL resources
