commit 344ac0e45291499131b0a70c4dc4a05cb48b48ea
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Wed May 30 15:22:36 2018 +0100

    OIT: fix for 'out of memory' crash on Mali GPUs.
    
    ~The thing still does not fully work there - there are still strange flashes in apps that innvolve OIT, for example in 'Triblur'.

diff --git a/src/main/java/org/distorted/library/main/DistortedEffects.java b/src/main/java/org/distorted/library/main/DistortedEffects.java
index 1466563..8f7b951 100644
--- a/src/main/java/org/distorted/library/main/DistortedEffects.java
+++ b/src/main/java/org/distorted/library/main/DistortedEffects.java
@@ -78,6 +78,9 @@ public class DistortedEffects
     mAtomicCounter[0] = -1;
     }
 
+  ///////////////////////////////////////////////////////////////
+  // this has to be at least as big as the number of pixels in
+  // the screen, lest the oitClear() pass overwrite memory.
   private static int mBufferSize=(0x1<<23);  // 8 million entries
 
   /// OIT CLEAR PROGRAM ///
@@ -126,7 +129,6 @@ public class DistortedEffects
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   static void createProgram(Resources resources)
-  throws FragmentCompilationException,VertexCompilationException,VertexUniformsException,FragmentUniformsException,LinkingException
     {
     // MAIN PROGRAM ////////////////////////////////////
     final InputStream mainVertStream = resources.openRawResource(R.raw.main_vertex_shader);
@@ -226,9 +228,9 @@ public class DistortedEffects
     if( mLinkedListSSBO[0]<0 )
       {
       GLES31.glGenBuffers(1,mLinkedListSSBO,0);
-      GLES31.glBindBufferBase(GLES31.GL_SHADER_STORAGE_BUFFER, 1, mLinkedListSSBO[0]);
       GLES31.glBindBuffer(GLES31.GL_SHADER_STORAGE_BUFFER, mLinkedListSSBO[0]);
       GLES31.glBufferData(GLES31.GL_SHADER_STORAGE_BUFFER, mBufferSize*4 , null, GLES31.GL_DYNAMIC_READ|GLES31.GL_DYNAMIC_DRAW);
+      GLES31.glBindBufferBase(GLES31.GL_SHADER_STORAGE_BUFFER, 1, mLinkedListSSBO[0]);
       GLES31.glBindBuffer(GLES31.GL_SHADER_STORAGE_BUFFER, 0);
       }
 
@@ -470,7 +472,7 @@ public class DistortedEffects
     GLES31.glViewport(0, 0, surface.mWidth, surface.mHeight );
     GLES31.glUniform2f(mOITClearTexCorrH, 1.0f, 1.0f );   // corrections do not really matter here - only present because of common vertex shader.
     GLES31.glUniform1f( mOITClearDepthH , 1.0f);          // likewise depth
-    GLES31.glUniform2f(mOITClearSizeH, surface.mWidth, surface.mHeight);
+    GLES31.glUniform2ui(mOITClearSizeH, surface.mWidth, surface.mHeight);
     GLES31.glVertexAttribPointer(mOITClearProgram.mAttribute[0], 2, GLES31.GL_FLOAT, false, 0, mQuadPositions);
     GLES31.glDrawArrays(GLES31.GL_TRIANGLE_STRIP, 0, 4);
     }
@@ -486,7 +488,7 @@ public class DistortedEffects
     GLES31.glUniform1i(mOITBuildTextureH, 0);
     GLES31.glUniform1i(mOITBuildDepthTextureH, 1);
     GLES31.glUniform2f(mOITBuildTexCorrH, corrW, corrH );
-    GLES31.glUniform2f(mOITBuildSizeH, surface.mWidth, surface.mHeight);
+    GLES31.glUniform2ui(mOITBuildSizeH, surface.mWidth, surface.mHeight);
     GLES31.glUniform1ui(mOITBuildNumRecordsH, (mBufferSize-surface.mWidth*surface.mHeight)/3 );  // see the fragment shader
     GLES31.glUniform1f(mOITBuildDepthH , 1.0f-surface.mNear);
     GLES31.glVertexAttribPointer(mOITBuildProgram.mAttribute[0], 2, GLES31.GL_FLOAT, false, 0, mQuadPositions);
@@ -503,7 +505,7 @@ public class DistortedEffects
     GLES31.glViewport(0, 0, surface.mWidth, surface.mHeight );
     GLES31.glUniform1i(mOITCollapseDepthTextureH, 1);
     GLES31.glUniform2f(mOITCollapseTexCorrH, corrW, corrH );
-    GLES31.glUniform2f(mOITCollapseSizeH, surface.mWidth, surface.mHeight);
+    GLES31.glUniform2ui(mOITCollapseSizeH, surface.mWidth, surface.mHeight);
     GLES31.glUniform1f( mOITCollapseDepthH , 1.0f-surface.mNear);
     GLES31.glVertexAttribPointer(mOITCollapseProgram.mAttribute[0], 2, GLES31.GL_FLOAT, false, 0, mQuadPositions);
     GLES31.glDrawArrays(GLES31.GL_TRIANGLE_STRIP, 0, 4);
@@ -518,61 +520,20 @@ public class DistortedEffects
 
     GLES31.glViewport(0, 0, surface.mWidth, surface.mHeight );
     GLES31.glUniform2f(mOITRenderTexCorrH, corrW, corrH );
-    GLES31.glUniform2f(mOITRenderSizeH, surface.mWidth, surface.mHeight);
+    GLES31.glUniform2ui(mOITRenderSizeH, surface.mWidth, surface.mHeight);
     GLES31.glUniform1f( mOITRenderDepthH , 1.0f-surface.mNear);
     GLES31.glVertexAttribPointer(mOITRenderProgram.mAttribute[0], 2, GLES31.GL_FLOAT, false, 0, mQuadPositions);
     GLES31.glDrawArrays(GLES31.GL_TRIANGLE_STRIP, 0, 4);
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private static void analyzeBuffer(int w, int h)
-    {
-    int ptr, index;
-    int errors = 0;
-
-    GLES31.glBindBuffer(GLES31.GL_SHADER_STORAGE_BUFFER, mLinkedListSSBO[0]);
-    ByteBuffer buf = (ByteBuffer)GLES31.glMapBufferRange(GLES31.GL_SHADER_STORAGE_BUFFER, 0, mBufferSize*4, GLES31.GL_MAP_READ_BIT);
-    IntBuffer intBuf = buf.order(ByteOrder.nativeOrder()).asIntBuffer();
-
-    for(int col=0; col<w; col++)
-      for(int row=0; row<h; row++)
-        {
-        index = col+row*w;
-        ptr = intBuf.get(index);
-
-        if( ptr!=0 )
-          {
-          if( ptr>0 && ptr<mBufferSize )
-            {
-            ptr = intBuf.get(ptr);
-            if( ptr != index )
-              {
-              android.util.Log.d("surface", "col="+col+" row="+row+" val="+ptr+" expected: "+index);
-              errors++;
-              }
-            }
-          else
-            {
-            android.util.Log.d("surface", "overflow!");
-            }
-          }
-        }
-
-    GLES31.glUnmapBuffer(GLES31.GL_SHADER_STORAGE_BUFFER);
-    GLES31.glBindBuffer(GLES31.GL_SHADER_STORAGE_BUFFER, 0);
-
-    if( errors>0 ) android.util.Log.e("surface", "errors: "+errors);
-    }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private void releasePriv()
     {
-    if( !matrixCloned   )   mM.abortAll(false);
-    if( !vertexCloned   )   mV.abortAll(false);
-    if( !fragmentCloned )   mF.abortAll(false);
-    if( !postprocessCloned) mP.abortAll(false);
+    if( !matrixCloned      ) mM.abortAll(false);
+    if( !vertexCloned      ) mV.abortAll(false);
+    if( !fragmentCloned    ) mF.abortAll(false);
+    if( !postprocessCloned ) mP.abortAll(false);
 
     mM = null;
     mV = null;
diff --git a/src/main/java/org/distorted/library/main/DistortedOutputSurface.java b/src/main/java/org/distorted/library/main/DistortedOutputSurface.java
index 96bb1b8..6a47301 100644
--- a/src/main/java/org/distorted/library/main/DistortedOutputSurface.java
+++ b/src/main/java/org/distorted/library/main/DistortedOutputSurface.java
@@ -379,9 +379,6 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
         {
         GLES31.glBindFramebuffer(GLES31.GL_FRAMEBUFFER, mFBOH[0]);
         numRenders += child1.draw(time, this);
-
-        //setAsOutput(time);
-        //numRenders += child1.draw(time,this);
         }
       else
         {
diff --git a/src/main/res/raw/oit_build_fragment_shader.glsl b/src/main/res/raw/oit_build_fragment_shader.glsl
index 3fd1ddd..d1faf2c 100644
--- a/src/main/res/raw/oit_build_fragment_shader.glsl
+++ b/src/main/res/raw/oit_build_fragment_shader.glsl
@@ -30,7 +30,7 @@ uniform sampler2D u_DepthTexture;
 //////////////////////////////////////////////////////////////////////////////////////////////
 // per-pixel linked list. Order Independent Transparency.
 
-uniform vec2 u_Size;
+uniform uvec2 u_Size;
 uniform uint u_numRecords;
 
 layout (binding=0, offset=0) uniform atomic_uint u_Counter;
@@ -53,14 +53,14 @@ void insert( vec2 ij, uint depth, uint rgba )
 
   if( ptr<u_numRecords )
     {
-    ptr = 3u*ptr + uint(u_Size.x*u_Size.y);
+    ptr = 3u*ptr + u_Size.x*u_Size.y;
 
     u_Records[ptr+1u] = depth;
     u_Records[ptr+2u] = rgba;
 
     memoryBarrier();
 
-    uint prev = uint(ij.x + ij.y * u_Size.x);
+    uint prev = uint(ij.x) + uint(ij.y) * u_Size.x;
     uint curr = u_Records[prev];
 
     while (true)
diff --git a/src/main/res/raw/oit_clear_fragment_shader.glsl b/src/main/res/raw/oit_clear_fragment_shader.glsl
index 701fa42..18eceb1 100644
--- a/src/main/res/raw/oit_clear_fragment_shader.glsl
+++ b/src/main/res/raw/oit_clear_fragment_shader.glsl
@@ -26,7 +26,7 @@ in vec2 v_Pixel;              // location of the current fragment, in pixels
 //////////////////////////////////////////////////////////////////////////////////////////////
 // per-pixel linked list. Order Independent Transparency.
 
-uniform vec2 u_Size;
+uniform uvec2 u_Size;
 
 layout (std430,binding=1) buffer linkedlist  // first (u_Size.x*u_Size.y) uints - head pointers,
   {                                          // one for each pixel in the Output rectangle.
@@ -41,7 +41,7 @@ layout (std430,binding=1) buffer linkedlist  // first (u_Size.x*u_Size.y) uints
 
 void main()                    		
   {
-  uint index= uint(v_Pixel.x + v_Pixel.y * u_Size.x);
+  uint index= uint(v_Pixel.x) + uint(v_Pixel.y) * u_Size.x;
   u_Records[index] = 0u;
   discard;
   }
\ No newline at end of file
diff --git a/src/main/res/raw/oit_collapse_fragment_shader.glsl b/src/main/res/raw/oit_collapse_fragment_shader.glsl
index abbda53..1077e92 100644
--- a/src/main/res/raw/oit_collapse_fragment_shader.glsl
+++ b/src/main/res/raw/oit_collapse_fragment_shader.glsl
@@ -29,7 +29,7 @@ uniform sampler2D u_DepthTexture;
 //////////////////////////////////////////////////////////////////////////////////////////////
 // per-pixel linked list. Order Independent Transparency.
 
-uniform vec2 u_Size;
+uniform uvec2 u_Size;
 
 layout (std430,binding=1) buffer linkedlist  // first (u_Size.x*u_Size.y) uints - head pointers,
   {                                          // one for each pixel in the Output rectangle.
@@ -42,7 +42,7 @@ layout (std430,binding=1) buffer linkedlist  // first (u_Size.x*u_Size.y) uints
 
 void main()                    		
   {
-  uint prev = uint(v_Pixel.x + v_Pixel.y * u_Size.x);
+  uint prev = uint(v_Pixel.x) + uint(v_Pixel.y) * u_Size.x;
   uint curr = u_Records[prev];
 
   if (curr != 0u)
diff --git a/src/main/res/raw/oit_render_fragment_shader.glsl b/src/main/res/raw/oit_render_fragment_shader.glsl
index e412c80..3415c7f 100644
--- a/src/main/res/raw/oit_render_fragment_shader.glsl
+++ b/src/main/res/raw/oit_render_fragment_shader.glsl
@@ -27,7 +27,7 @@ in vec2 v_Pixel;              // location of the current fragment, in pixels
 //////////////////////////////////////////////////////////////////////////////////////////////
 // per-pixel linked list. Order Independent Transparency.
 
-uniform vec2 u_Size;
+uniform uvec2 u_Size;
 
 layout (std430,binding=1) buffer linkedlist  // first (u_Size.x*u_Size.y) uints - head pointers,
   {                                          // one for each pixel in the Output rectangle.
@@ -59,7 +59,7 @@ vec4 blend(vec4 A,vec4 B)
 
 void main()                    		
   {
-  uint prev = uint(v_Pixel.x + v_Pixel.y * u_Size.x);
+  uint prev = uint(v_Pixel.x) + uint(v_Pixel.y) * u_Size.x;
   uint curr = u_Records[prev];
 
   if (curr != 0u)
diff --git a/src/main/res/raw/oit_vertex_shader.glsl b/src/main/res/raw/oit_vertex_shader.glsl
index 17228a5..86dcf4c 100644
--- a/src/main/res/raw/oit_vertex_shader.glsl
+++ b/src/main/res/raw/oit_vertex_shader.glsl
@@ -30,13 +30,13 @@ uniform vec2  u_TexCorr;      // when we blit from postprocessing buffers, the b
                               // reused!) so we need to compensate here by adjusting the texture
                               // coords.
 
-uniform vec2 u_Size;          // size of the output surface, in pixels.
+uniform uvec2 u_Size;         // size of the output surface, in pixels.
 
 //////////////////////////////////////////////////////////////////////////////////////////////
 
 void main()
   {
   v_TexCoordinate = (a_Position + 0.5) * u_TexCorr;
-  v_Pixel         = (a_Position + 0.5) * u_Size;
+  v_Pixel         = (a_Position + 0.5) * vec2(u_Size);
   gl_Position     = vec4(2.0*a_Position,u_Depth,1.0);
   }
