commit 604b28992918024cd73288df27b72b374d99bb9d
Author: Leszek Koltunski <leszek@distoretedandroid.org>
Date:   Wed May 10 13:56:08 2017 +0100

    Dynamic display of bounding rectangles (with coords computed by Vertex Shader and gotten with Transform Feedback) works now.
    
    Major problem: the glMapBufferRange() slows doewn rendering in a major way. Multiblur's FPS:
    
    Nexus5X : 35.4 before -> 12.6 after
    Nexus4     26.5 before -> ~12 after

diff --git a/src/main/java/org/distorted/library/DistortedEffects.java b/src/main/java/org/distorted/library/DistortedEffects.java
index c63367b..8c1e6c7 100644
--- a/src/main/java/org/distorted/library/DistortedEffects.java
+++ b/src/main/java/org/distorted/library/DistortedEffects.java
@@ -142,7 +142,7 @@ public class DistortedEffects
     //android.util.Log.e("Effects", "vertHeader= "+mainVertHeader);
     //android.util.Log.e("Effects", "fragHeader= "+mainFragHeader);
 
-    String[] feedback = { "v_Position","v_Normal","v_TexCoordinate" };
+    String[] feedback = { "v_Position", "v_Normal", "v_ndcPosition" };
 
     mMainProgram = new DistortedProgram(mainVertStream,mainFragStream, mainVertHeader, mainFragHeader, Distorted.GLSL, feedback);
 
@@ -231,92 +231,76 @@ public class DistortedEffects
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-// DEBUG ONLY
 
   @SuppressWarnings("unused")
-  private void displayBoundingRect(float halfX, float halfY, float halfZ, DistortedOutputSurface surface, float[] mvp, float[] vertices, long currTime)
+  private void displayBoundingRect(float halfW, float halfH, DistortedOutputSurface surface, MeshObject mesh)
     {
-    int len  = vertices.length/3;
-    int minx = Integer.MAX_VALUE;
-    int maxx = Integer.MIN_VALUE;
-    int miny = Integer.MAX_VALUE;
-    int maxy = Integer.MIN_VALUE;
-    int wx,wy;
+    GLES30.glBindBufferBase(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, mesh.mAttTFO[0]);
+    GLES30.glBeginTransformFeedback( GLES30.GL_POINTS);
+
+    DistortedRenderState.switchOffDrawing();
+    GLES30.glDrawArrays( GLES30.GL_POINTS, 0, mesh.numVertices);
+    DistortedRenderState.restoreDrawing();
 
-    float x,y,z, X,Y,W, ndcX,ndcY;
+    int error = GLES30.glGetError();
 
-    for(int i=0; i<len; i++)
+    if( error != GLES30.GL_NO_ERROR )
       {
-      x = 2*halfX*vertices[3*i  ];
-      y = 2*halfY*vertices[3*i+1];
-      z = 2*halfZ*vertices[3*i+2];
+      throw new RuntimeException("DrawArrays: glError 0x" + Integer.toHexString(error));
+      }
 
-      X = mvp[ 0]*x + mvp[ 4]*y + mvp[ 8]*z + mvp[12];
-      Y = mvp[ 1]*x + mvp[ 5]*y + mvp[ 9]*z + mvp[13];
-      W = mvp[ 3]*x + mvp[ 7]*y + mvp[11]*z + mvp[15];
+    // mapping the buffer range slows down rendering /////////////////////////
+    int size = (MeshObject.POS_DATA_SIZE+MeshObject.NOR_DATA_SIZE+MeshObject.NDC_DATA_SIZE)*mesh.numVertices;
 
-      ndcX = X/W;
-      ndcY = Y/W;
+    Buffer mappedBuffer =  GLES30.glMapBufferRange(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, 4*size, GLES30.GL_MAP_READ_BIT);
+    FloatBuffer fb = ((ByteBuffer) mappedBuffer).order(ByteOrder.nativeOrder()).asFloatBuffer();
+    GLES30.glUnmapBuffer(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER);
+    // end of slowdown //////////////////////////////////////////////////////
 
-      wx = (int)(surface.mWidth *(ndcX+1)/2);
-      wy = (int)(surface.mHeight*(ndcY+1)/2);
+    GLES30.glEndTransformFeedback();
+    GLES30.glBindBufferBase(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
+/*
+    String msg = "";
+    for(int i=0; i<size; i++) msg += (" "+fb.get(i));
+    android.util.Log.d( "Feedback", msg);
+*/
+    float minx = Integer.MAX_VALUE;
+    float maxx = Integer.MIN_VALUE;
+    float miny = Integer.MAX_VALUE;
+    float maxy = Integer.MIN_VALUE;
+    float ndcX,ndcY;
+
+    for(int i=0; i<mesh.numVertices; i++)
+      {
+      ndcX = fb.get(8*i+6);
+      ndcY = fb.get(8*i+7);
 
-      if( wx<minx ) minx = wx;
-      if( wx>maxx ) maxx = wx;
-      if( wy<miny ) miny = wy;
-      if( wy>maxy ) maxy = wy;
+      if( ndcX<minx ) minx = ndcX;
+      if( ndcX>maxx ) maxx = ndcX;
+      if( ndcY<miny ) miny = ndcY;
+      if( ndcY>maxy ) maxy = ndcY;
       }
 
+    minx = surface.mWidth *(minx+1)/2;   //
+    miny = surface.mHeight*(miny+1)/2;   // transform from NDC to
+    maxx = surface.mWidth *(maxx+1)/2;   // window coordinates
+    maxy = surface.mHeight*(maxy+1)/2;   //
+
     mDebugProgram.useProgram();
-    surface.setAsOutput(currTime);
 
     Matrix.setIdentityM( mTmpMatrix, 0);
     Matrix.translateM  ( mTmpMatrix, 0, minx-surface.mWidth/2, maxy-surface.mHeight/2, -surface.mDistance);
-    Matrix.scaleM      ( mTmpMatrix, 0, (float)(maxx-minx)/(2*halfX), (float)(maxy-miny)/(2*halfY), 1.0f);
-    Matrix.translateM  ( mTmpMatrix, 0, halfX,-halfY, 0);
+    Matrix.scaleM      ( mTmpMatrix, 0, (maxx-minx)/(2*halfW), (maxy-miny)/(2*halfH), 1.0f);
+    Matrix.translateM  ( mTmpMatrix, 0, halfW,-halfH, 0);
     Matrix.multiplyMM  ( mMVPMatrix, 0, surface.mProjectionMatrix, 0, mTmpMatrix, 0);
 
-    GLES30.glUniform2f(mDebugObjDH, 2*halfX, 2*halfY);
+    GLES30.glUniform2f(mDebugObjDH, 2*halfW, 2*halfH);
     GLES30.glUniformMatrix4fv(mDebugMVPMatrixH, 1, false, mMVPMatrix , 0);
 
     GLES30.glVertexAttribPointer(mDebugProgram.mAttribute[0], 2, GLES30.GL_FLOAT, false, 0, mQuadPositions);
     GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, 0, 4);
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void displayTransformFeedback(MeshObject mesh)
-    {
-    GLES30.glBindBufferBase(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, mesh.mAttTFO[0]);
-    GLES30.glBeginTransformFeedback( GLES30.GL_POINTS);
-
-    DistortedRenderState.switchOffDrawing();
-    GLES30.glDrawArrays( GLES30.GL_POINTS, 0, mesh.numVertices);
-    DistortedRenderState.restoreDrawing();
-
-    int error = GLES30.glGetError();
-
-      if( error != GLES30.GL_NO_ERROR )
-        {
-        throw new RuntimeException("DrawArrays: glError 0x" + Integer.toHexString(error));
-        }
-/*
-    int size = (MeshObject.POS_DATA_SIZE+MeshObject.NOR_DATA_SIZE+MeshObject.TEX_DATA_SIZE)*mesh.numVertices;
-
-    Buffer mappedBuffer =  GLES30.glMapBufferRange(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, 4*size, GLES30.GL_MAP_READ_BIT);
-    FloatBuffer fb = ((ByteBuffer) mappedBuffer).order(ByteOrder.nativeOrder()).asFloatBuffer();
-    String msg = "";
-
-    for(int i=0; i<size; i++) msg += (" "+fb.get(i));
-
-    android.util.Log.d( "Feedback", msg);
-
-    GLES30.glUnmapBuffer(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER);
-*/
-    GLES30.glEndTransformFeedback();
-    GLES30.glBindBufferBase(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
-    }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   void drawPriv(float halfW, float halfH, MeshObject mesh, DistortedOutputSurface surface, long currTime)
@@ -341,25 +325,11 @@ public class DistortedEffects
 
     mM.send(surface,halfW,halfH,halfZ);
     mV.send(halfW,halfH,halfZ);
-
-    displayTransformFeedback(mesh);
-
-    EffectQueueMatrix.sendZero();
-    EffectQueueVertex.sendZero();
-
     mF.send(halfW,halfH);
 
-    GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, mesh.mAttTFO[0]);
-    GLES30.glVertexAttribPointer(mMainProgram.mAttribute[0], MeshObject.POS_DATA_SIZE, GLES30.GL_FLOAT, false, MeshObject.VERTSIZE, MeshObject.OFFSET0);
-    GLES30.glVertexAttribPointer(mMainProgram.mAttribute[1], MeshObject.NOR_DATA_SIZE, GLES30.GL_FLOAT, false, MeshObject.VERTSIZE, MeshObject.OFFSET1);
-    GLES30.glVertexAttribPointer(mMainProgram.mAttribute[2], MeshObject.TEX_DATA_SIZE, GLES30.GL_FLOAT, false, MeshObject.VERTSIZE, MeshObject.OFFSET2);
-    GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0 );
-
     GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, 0, mesh.numVertices);
 
-    /// DEBUG ONLY //////
-    // displayBoundingRect(halfW, halfH, halfZ, surface, mM.getMVP(), mesh.getBoundingVertices() );
-    /// END DEBUG ///////
+    displayBoundingRect(halfW,halfH,surface,mesh);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/library/EffectQueueMatrix.java b/src/main/java/org/distorted/library/EffectQueueMatrix.java
index 917c9cd..647ccd3 100644
--- a/src/main/java/org/distorted/library/EffectQueueMatrix.java
+++ b/src/main/java/org/distorted/library/EffectQueueMatrix.java
@@ -261,17 +261,6 @@ class EffectQueueMatrix extends EffectQueue
     GLES30.glUniformMatrix4fv(mMVPMatrixH, 1, false, mMVPMatrix , 0);
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  static synchronized void sendZero()
-    {
-    Matrix.setIdentityM(mTmpMatrix, 0);
-
-    GLES30.glUniform3f( mObjDH , 0.5f, 0.5f, 0.5f);
-    GLES30.glUniformMatrix4fv(mMVMatrixH , 1, false, mTmpMatrix , 0);
-    GLES30.glUniformMatrix4fv(mMVPMatrixH, 1, false, mMVPMatrix , 0);
-    }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // move, scale
 
diff --git a/src/main/java/org/distorted/library/EffectQueueVertex.java b/src/main/java/org/distorted/library/EffectQueueVertex.java
index 6e86832..e25acfd 100644
--- a/src/main/java/org/distorted/library/EffectQueueVertex.java
+++ b/src/main/java/org/distorted/library/EffectQueueVertex.java
@@ -151,13 +151,6 @@ class EffectQueueVertex extends EffectQueue
       }
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  static synchronized void sendZero()
-    {
-    GLES30.glUniform1i( mNumEffectsH, 0);
-    }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // Do various post-processing on already computed effects.
 // 1) here unlike in the fragment queue, we don't have to multiply the points by ModelView matrix because that gets done in the shader.
diff --git a/src/main/java/org/distorted/library/MeshObject.java b/src/main/java/org/distorted/library/MeshObject.java
index 4655be6..e5b049a 100644
--- a/src/main/java/org/distorted/library/MeshObject.java
+++ b/src/main/java/org/distorted/library/MeshObject.java
@@ -38,10 +38,13 @@ public abstract class MeshObject extends DistortedObject
    static final int POS_DATA_SIZE= 3;
    static final int NOR_DATA_SIZE= 3;
    static final int TEX_DATA_SIZE= 2;
+   static final int NDC_DATA_SIZE= 2;
 
    static final int OFFSET0 =                                                           0;
    static final int OFFSET1 = (POS_DATA_SIZE                            )*BYTES_PER_FLOAT;
    static final int OFFSET2 = (POS_DATA_SIZE+NOR_DATA_SIZE              )*BYTES_PER_FLOAT;
+
+   static final int TFSIZE  = (POS_DATA_SIZE+NOR_DATA_SIZE+NDC_DATA_SIZE)*BYTES_PER_FLOAT;
    static final int VERTSIZE= (POS_DATA_SIZE+NOR_DATA_SIZE+TEX_DATA_SIZE)*BYTES_PER_FLOAT;
 
    int numVertices;
@@ -81,7 +84,7 @@ public abstract class MeshObject extends DistortedObject
        {
        GLES30.glGenBuffers(1, mAttTFO, 0);
        GLES30.glBindBuffer(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, mAttTFO[0]);
-       GLES30.glBufferData(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, numVertices*VERTSIZE, null, GLES30.GL_STATIC_READ);
+       GLES30.glBufferData(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, numVertices*TFSIZE, null, GLES30.GL_STATIC_READ);
        GLES30.glBindBuffer(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0);
        }
      }
diff --git a/src/main/res/raw/main_vertex_shader.glsl b/src/main/res/raw/main_vertex_shader.glsl
index 1b53e0b..dac81d5 100644
--- a/src/main/res/raw/main_vertex_shader.glsl
+++ b/src/main/res/raw/main_vertex_shader.glsl
@@ -24,6 +24,7 @@ in vec3 a_Position;                  // Per-vertex position.
 in vec3 a_Normal;                    // Per-vertex normal vector.
 in vec2 a_TexCoordinate;             // Per-vertex texture coordinate.
 out vec3 v_Position;                 //
+out vec2 v_ndcPosition;              // for Transform Feedback only
 out vec3 v_Normal;                   //
 out vec2 v_TexCoordinate;            //
 #else
@@ -31,6 +32,7 @@ attribute vec3 a_Position;           // Per-vertex position.
 attribute vec3 a_Normal;             // Per-vertex normal vector.
 attribute vec2 a_TexCoordinate;      // Per-vertex texture coordinate.
 varying vec3 v_Position;             //
+varying vec2 v_ndcPosition;          // for Transform Feedback only
 varying vec3 v_Normal;               //
 varying vec2 v_TexCoordinate;        //
 #endif
@@ -525,6 +527,7 @@ void main()
   {
   vec3 v = 2.0*u_objD*a_Position;
   vec3 n = a_Normal;
+  vec4 mvpPos;
 
 #if NUM_VERTEX>0
   int j=0;
@@ -558,5 +561,7 @@ void main()
   v_Position      = v;
   v_TexCoordinate = a_TexCoordinate;
   v_Normal        = normalize(vec3(u_MVMatrix*vec4(n,0.0)));
-  gl_Position     = u_MVPMatrix*vec4(v,1.0);
+  mvpPos          = u_MVPMatrix*vec4(v,1.0);
+  v_ndcPosition   = vec2(mvpPos.x/mvpPos.w,mvpPos.y/mvpPos.w);
+  gl_Position     = mvpPos;
   }                               
