commit 2dbed690bdbee80d9bfb22c800073855eb5d0946
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Fri Jun 8 15:03:48 2018 +0100

    In an attempt to contain the flashes on Mali GPU, re-structure the post-processing FBOs from 1 FBO with 2 color attachments + combined depth-stencil to 2 separate FBOs sharing a depth-stencil texture.
    
    Result: this appears to make the flashes slightly worse.

diff --git a/src/main/java/org/distorted/library/effect/PostprocessEffect.java b/src/main/java/org/distorted/library/effect/PostprocessEffect.java
index 28ebd7c..4695e0a 100644
--- a/src/main/java/org/distorted/library/effect/PostprocessEffect.java
+++ b/src/main/java/org/distorted/library/effect/PostprocessEffect.java
@@ -139,7 +139,7 @@ public abstract class PostprocessEffect extends Effect implements DistortedMaste
  *
  * @y.exclude
  */
-  public abstract int apply(float[] uniforms, int index, DistortedOutputSurface[] buffers);
+  public abstract int apply(float[] uniforms, int index, DistortedOutputSurface[][] buffers);
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
diff --git a/src/main/java/org/distorted/library/effect/PostprocessEffectBlur.java b/src/main/java/org/distorted/library/effect/PostprocessEffectBlur.java
index 08cec17..d8d25c7 100644
--- a/src/main/java/org/distorted/library/effect/PostprocessEffectBlur.java
+++ b/src/main/java/org/distorted/library/effect/PostprocessEffectBlur.java
@@ -140,7 +140,7 @@ public class PostprocessEffectBlur extends PostprocessEffect
  *
  * @y.exclude
  */
-  public int apply(float[] uniforms, int index, DistortedOutputSurface[] buffers)
+  public int apply(float[] uniforms, int index, DistortedOutputSurface[][] buffers)
     {
     if( mProgram1 ==null)
       {
@@ -157,16 +157,15 @@ public class PostprocessEffectBlur extends PostprocessEffect
 
     DistortedRenderState.useStencilMark();
 
-    DistortedFramebuffer buffer = (DistortedFramebuffer)buffers[mQualityLevel];
+    DistortedFramebuffer buffer0 = (DistortedFramebuffer)buffers[mQualityLevel][0];
+    DistortedFramebuffer buffer1 = (DistortedFramebuffer)buffers[mQualityLevel][1];
 
-    buffer.setAsOutput();
+    float w= buffer0.getWidth();
+    float h= buffer0.getHeight();
+    float n= 1.0f - buffer0.getNear();
 
-    float w= buffer.getWidth();
-    float h= buffer.getHeight();
-    float n= 1.0f - buffer.getNear();
-
-    float corrW = buffer.getWidthCorrection();
-    float corrH = buffer.getHeightCorrection();
+    float corrW = buffer0.getWidthCorrection();
+    float corrH = buffer0.getHeightCorrection();
     float offsetCorrW = corrW/w;
     float offsetCorrH = corrH/h;
 
@@ -182,8 +181,8 @@ public class PostprocessEffectBlur extends PostprocessEffect
     for(int i=0; i<=radius; i++) mOffsets[i] = offsetsCache[offset+i]*offsetCorrW;
 
     mProgram1.useProgram();
-    buffer.bindForOutput(1);
-    buffer.setAsInput(0);
+    buffer1.setAsOutput();
+    buffer0.setAsInput();
 
     GLES31.glColorMask(true,true,true,true);
     GLES31.glClearColor(1.0f,1.0f,1.0f,0.0f);
@@ -203,8 +202,8 @@ public class PostprocessEffectBlur extends PostprocessEffect
     for(int i=0; i<=radius; i++) mOffsets[i] = offsetsCache[offset+i]*offsetCorrH;
 
     mProgram2.useProgram();
-    buffer.bindForOutput(0);
-    buffer.setAsInput(1);
+    buffer0.setAsOutput();
+    buffer1.setAsInput();
 
     GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT);
 
diff --git a/src/main/java/org/distorted/library/effect/PostprocessEffectGlow.java b/src/main/java/org/distorted/library/effect/PostprocessEffectGlow.java
index e0cd858..bc16afb 100644
--- a/src/main/java/org/distorted/library/effect/PostprocessEffectGlow.java
+++ b/src/main/java/org/distorted/library/effect/PostprocessEffectGlow.java
@@ -144,7 +144,7 @@ public class PostprocessEffectGlow extends PostprocessEffect
  *
  * @y.exclude
  */
-  public int apply(float[] uniforms, int index, DistortedOutputSurface[] buffers)
+  public int apply(float[] uniforms, int index, DistortedOutputSurface[][] buffers)
     {
     if( mProgram1 ==null)
       {
@@ -161,12 +161,13 @@ public class PostprocessEffectGlow extends PostprocessEffect
 
     DistortedRenderState.useStencilMark();
 
-    DistortedFramebuffer  inBuffer = (DistortedFramebuffer)buffers[0];
-    DistortedFramebuffer outBuffer = (DistortedFramebuffer)buffers[mQualityLevel];
+    DistortedFramebuffer  inBuffer  = (DistortedFramebuffer)buffers[0][0];
+    DistortedFramebuffer outBuffer0 = (DistortedFramebuffer)buffers[mQualityLevel][0];
+    DistortedFramebuffer outBuffer1 = (DistortedFramebuffer)buffers[mQualityLevel][1];
 
-    float w= outBuffer.getWidth();
-    float h= outBuffer.getHeight();
-    float n= 1.0f - outBuffer.getNear();
+    float w= outBuffer0.getWidth();
+    float h= outBuffer0.getHeight();
+    float n= 1.0f - outBuffer0.getNear();
 
     float corrW = inBuffer.getWidthCorrection();
     float corrH = inBuffer.getHeightCorrection();
@@ -180,15 +181,14 @@ public class PostprocessEffectGlow extends PostprocessEffect
     int offset = radius + radius*radius/4;
     radius = (radius+1)/2;
 
-    outBuffer.setAsOutput();
     GLES31.glViewport(0, 0, (int)w, (int)h);
 
     // horizontal glow
     for(int i=0; i<=radius; i++) mOffsets[i] = offsetsCache[offset+i]*offsetCorrW;
 
     mProgram1.useProgram();
-    outBuffer.bindForOutput(1);
-    inBuffer.setAsInput(0);
+    outBuffer1.setAsOutput();
+    inBuffer.setAsInput();
 
     GLES31.glColorMask(true,true,true,true);
     GLES31.glClearColor(1.0f,1.0f,1.0f,0.0f);
@@ -209,8 +209,8 @@ public class PostprocessEffectGlow extends PostprocessEffect
     for(int i=0; i<=radius; i++) mOffsets[i] = offsetsCache[offset+i]*offsetCorrH;
 
     mProgram2.useProgram();
-    outBuffer.bindForOutput(0);
-    outBuffer.setAsInput(1);
+    outBuffer0.setAsOutput();
+    outBuffer1.setAsInput();
 
     GLES31.glUniform1f ( mProgram2.mUniform[0] , n );
     GLES31.glUniform2f ( mProgram2.mUniform[1] , corrW, corrH );
@@ -229,7 +229,7 @@ public class PostprocessEffectGlow extends PostprocessEffect
     if( mQualityLevel>0 )
       {
       inBuffer.setAsOutput();
-      outBuffer.setAsInput(0);
+      outBuffer0.setAsInput();
       GLES31.glEnable(GLES31.GL_BLEND);
       DistortedEffects.blitPriv(inBuffer);
       GLES31.glDisable(GLES31.GL_BLEND);
diff --git a/src/main/java/org/distorted/library/main/DistortedFramebuffer.java b/src/main/java/org/distorted/library/main/DistortedFramebuffer.java
index c7614f1..ccea145 100644
--- a/src/main/java/org/distorted/library/main/DistortedFramebuffer.java
+++ b/src/main/java/org/distorted/library/main/DistortedFramebuffer.java
@@ -39,8 +39,6 @@ public class DistortedFramebuffer extends DistortedOutputSurface implements Dist
     if( mColorCreated==NOT_CREATED_YET )
       {
       GLES31.glGenTextures( mNumColors, mColorH, 0);
-      GLES31.glGenFramebuffers(1, mFBOH, 0);
-      GLES31.glBindFramebuffer(GLES31.GL_FRAMEBUFFER, mFBOH[0]);
 
       for(int i=0; i<mNumColors; i++)
         {
@@ -51,8 +49,11 @@ public class DistortedFramebuffer extends DistortedOutputSurface implements Dist
         GLES31.glTexParameterf(GLES31.GL_TEXTURE_2D, GLES31.GL_TEXTURE_MAG_FILTER, GLES31.GL_LINEAR);
         GLES31.glTexImage2D(GLES31.GL_TEXTURE_2D, 0, GLES31.GL_RGBA, mRealWidth, mRealHeight, 0, GLES31.GL_RGBA, GLES31.GL_UNSIGNED_BYTE, null);
         }
-      GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_COLOR_ATTACHMENT0, GLES31.GL_TEXTURE_2D, mColorH[0], 0);
       GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, 0);
+
+      GLES31.glGenFramebuffers(1, mFBOH, 0);
+      GLES31.glBindFramebuffer(GLES31.GL_FRAMEBUFFER, mFBOH[0]);
+      GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_COLOR_ATTACHMENT0, GLES31.GL_TEXTURE_2D, mColorH[0], 0);
       GLES31.glBindFramebuffer(GLES31.GL_FRAMEBUFFER, 0);
 
       mColorCreated = checkStatus("color");
@@ -77,6 +78,7 @@ public class DistortedFramebuffer extends DistortedOutputSurface implements Dist
         }
 
       GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, 0);
+
       GLES31.glBindFramebuffer(GLES31.GL_FRAMEBUFFER, mFBOH[0]);
 
       if( mDepthStencil==DEPTH_NO_STENCIL )
@@ -105,6 +107,11 @@ public class DistortedFramebuffer extends DistortedOutputSurface implements Dist
       GLES31.glDeleteTextures(1, mDepthStencilH, 0);
       mDepthStencilH[0]=0;
       }
+    if( mDepthStencilCreated==COPIED && mDepthStencilH[0]>0 )
+      {
+      mDepthStencilCreated = DONT_CREATE;
+      mDepthStencilH[0]=0;
+      }
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -128,6 +135,19 @@ public class DistortedFramebuffer extends DistortedOutputSurface implements Dist
     return CREATED;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// the Framebuffer was created without DEPTH or STENCIL but now we want to copy it from some other.
+// Framebuffer 'from' MUST be already created!!
+// Must be called from a thread holding OpenGL Context
+//
+// 'Private' , library-only function used only for the postprocessing buffers!
+
+  void copyDepthAndStencil(DistortedFramebuffer from)
+    {
+    mDepthStencilCreated = COPIED;
+    mDepthStencilH[0] = from.mDepthStencilH[0];
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // Must be called from a thread holding OpenGL Context
 
diff --git a/src/main/java/org/distorted/library/main/DistortedObject.java b/src/main/java/org/distorted/library/main/DistortedObject.java
index e147544..b569d4e 100644
--- a/src/main/java/org/distorted/library/main/DistortedObject.java
+++ b/src/main/java/org/distorted/library/main/DistortedObject.java
@@ -39,6 +39,7 @@ abstract class DistortedObject
   static final int NOT_CREATED_YET  = 2;
   static final int DONT_CREATE      = 3;
   static final int CREATED          = 4;
+  static final int COPIED           = 5;
 
   static final int TYPE_USER = 0;
   static final int TYPE_TREE = 1;
diff --git a/src/main/java/org/distorted/library/main/DistortedOutputSurface.java b/src/main/java/org/distorted/library/main/DistortedOutputSurface.java
index 0e8f65f..df03a60 100644
--- a/src/main/java/org/distorted/library/main/DistortedOutputSurface.java
+++ b/src/main/java/org/distorted/library/main/DistortedOutputSurface.java
@@ -69,8 +69,9 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
 
   private ArrayList<Job> mJobs = new ArrayList<>();
 
-  // Global buffers used for postprocessing.
-  private static DistortedOutputSurface[] mBuffer = new DistortedOutputSurface[EffectQuality.LENGTH];
+  // Global buffers used for postprocessing. MipmapLevels x PING_PONG of each for postprocessing ping-pong.
+  private static final int PING_PONG = 2;
+  private static DistortedOutputSurface[][] mBuffer = null;
 
   private long mTime;
   private float mFOV;
@@ -171,20 +172,37 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
 
   private static void createPostprocessingBuffers(int width, int height, float near)
     {
+    mBuffer = new DistortedOutputSurface[EffectQuality.LENGTH][PING_PONG];
     float mipmap=1.0f;
 
-    for (int j=0; j<EffectQuality.LENGTH; j++)
+    for (int i=0; i<EffectQuality.LENGTH; i++)
       {
-      mBuffer[j] = new DistortedFramebuffer(2, BOTH_DEPTH_STENCIL, TYPE_SYST, (int) (width * mipmap), (int) (height * mipmap));
-      mBuffer[j].mMipmap = mipmap;
-      mBuffer[j].mNear = near;  // copy mNear as well (for blitting- see PostprocessEffect.apply() )
-      mBuffer[j].glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
+      mBuffer[i][0] = new DistortedFramebuffer(1, BOTH_DEPTH_STENCIL, TYPE_SYST, (int) (width * mipmap), (int) (height * mipmap));
+      mBuffer[i][0].mMipmap = mipmap;
+      mBuffer[i][0].mNear = near;  // copy mNear as well (for blitting- see PostprocessEffect.apply() )
+      mBuffer[i][0].glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
+
+      for(int j=1; j<PING_PONG; j++)
+        {
+        mBuffer[i][j] = new DistortedFramebuffer(1, NO_DEPTH_NO_STENCIL, TYPE_SYST, (int) (width * mipmap), (int) (height * mipmap));
+        mBuffer[i][j].mMipmap = mipmap;
+        mBuffer[i][j].mNear = near;
+        mBuffer[i][j].glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
+        }
 
       mipmap *= EffectQuality.MULTIPLIER;
       }
 
     DistortedObject.toDo(); // create the FBOs immediately. This is safe as we must be holding the OpenGL context now.
 
+    for (int i=0; i<EffectQuality.LENGTH; i++)
+      {
+      for(int j=1; j<PING_PONG; j++)
+        {
+        ( (DistortedFramebuffer)mBuffer[i][j]).copyDepthAndStencil( (DistortedFramebuffer)mBuffer[i][0] );
+        }
+      }
+
     GLES31.glStencilMask(0xff);
     GLES31.glDepthMask(true);
     GLES31.glColorMask(true, true, true, true);
@@ -192,13 +210,16 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
     GLES31.glClearDepthf(1.0f);
     GLES31.glClearStencil(0);
 
-    for (int j=0; j<EffectQuality.LENGTH; j++)
+    for (int i=0; i<EffectQuality.LENGTH; i++)
       {
-      mBuffer[j].setAsOutput();
-      GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_COLOR_ATTACHMENT0, GLES31.GL_TEXTURE_2D, mBuffer[j].mColorH[1], 0);
+      mBuffer[i][0].setAsOutput();
       GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT | GLES31.GL_DEPTH_BUFFER_BIT | GLES31.GL_STENCIL_BUFFER_BIT);
-      GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_COLOR_ATTACHMENT0, GLES31.GL_TEXTURE_2D, mBuffer[j].mColorH[0], 0);
-      GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT);
+
+      for(int j=1; j<PING_PONG; j++)
+        {
+        mBuffer[i][j].setAsOutput();
+        GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT);
+        }
       }
     }
 
@@ -206,9 +227,17 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
 
   static synchronized void onDestroy()
     {
-    for(int j=0; j<EffectQuality.LENGTH; j++)
+    if( mBuffer!=null )
       {
-      mBuffer[j] = null;
+      for (int i=0; i<EffectQuality.LENGTH; i++)
+        {
+        for (int j=1; j<PING_PONG; j++)
+          {
+          mBuffer[i][j] = null;
+          }
+        }
+
+      mBuffer = null;
       }
     }
 
@@ -220,33 +249,36 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
 
   private static void clonePostprocessingViewport(DistortedOutputSurface from)
     {
-    if( mBuffer[0].mWidth != from.mWidth || mBuffer[0].mHeight != from.mHeight )
+    if( mBuffer[0][0].mWidth != from.mWidth || mBuffer[0][0].mHeight != from.mHeight )
       {
       DistortedOutputSurface surface;
 
       for(int i=0; i<EffectQuality.LENGTH; i++)
         {
-        surface = mBuffer[i];
+        for(int j=0; j<PING_PONG; j++)
+          {
+          surface = mBuffer[i][j];
 
-        surface.mWidth  = (int)(from.mWidth *surface.mMipmap);
-        surface.mHeight = (int)(from.mHeight*surface.mMipmap);
+          surface.mWidth  = (int) (from.mWidth  * surface.mMipmap);
+          surface.mHeight = (int) (from.mHeight * surface.mMipmap);
 
-        surface.mNear   = from.mNear;  // Near plane is independent of the mipmap level
+          surface.mNear = from.mNear;  // Near plane is independent of the mipmap level
 
-        //android.util.Log.e("surface", "viewport "+i+" to ("+from.mWidth+"x"+from.mHeight+")");
+          //android.util.Log.e("surface", "viewport "+i+" to ("+from.mWidth+"x"+from.mHeight+")");
 
-        surface.createProjection();
+          surface.createProjection();
 
-        int maxw = surface.mWidth  > surface.mRealWidth  ? surface.mWidth  : surface.mRealWidth;
-        int maxh = surface.mHeight > surface.mRealHeight ? surface.mHeight : surface.mRealHeight;
+          int maxw = surface.mWidth  > surface.mRealWidth  ? surface.mWidth  : surface.mRealWidth;
+          int maxh = surface.mHeight > surface.mRealHeight ? surface.mHeight : surface.mRealHeight;
 
-        if (maxw > surface.mRealWidth || maxh > surface.mRealHeight)
-          {
-          surface.mRealWidth = maxw;
-          surface.mRealHeight = maxh;
+          if (maxw > surface.mRealWidth || maxh > surface.mRealHeight)
+            {
+            surface.mRealWidth = maxw;
+            surface.mRealHeight = maxh;
 
-          surface.recreate();
-          surface.create();
+            surface.recreate();
+            surface.create();
+            }
           }
         }
       }
@@ -288,7 +320,7 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-// two phases: 1. collapse the SSBO 2. blend the ssbo's color
+// two phases: 1. collapse the SSBO 2. blend the SSBO's color
 
   private int oitRender(long currTime)
     {
@@ -318,7 +350,7 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private static void clearBuffer(DistortedOutputSurface buffer)
+  private static void clearPostprocessingBuffer(int quality)
     {
     GLES31.glStencilMask(0xff);
     GLES31.glDepthMask(true);
@@ -327,13 +359,12 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
     GLES31.glClearDepthf(1.0f);
     GLES31.glClearStencil(0);
 
-    buffer.setAsOutput();
-    GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_COLOR_ATTACHMENT0, GLES31.GL_TEXTURE_2D, buffer.mColorH[buffer.mNumColors-1], 0);
+    mBuffer[quality][0].setAsOutput();
     GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT|GLES31.GL_DEPTH_BUFFER_BIT|GLES31.GL_STENCIL_BUFFER_BIT);
 
-    for(int i=buffer.mNumColors-2; i>=0; i--)
+    for(int j=1; j<PING_PONG; j++)
       {
-      GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_COLOR_ATTACHMENT0, GLES31.GL_TEXTURE_2D, buffer.mColorH[i], 0);
+      mBuffer[quality][j].setAsOutput();
       GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT);
       }
     }
@@ -375,7 +406,7 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
         }
       else
         {
-        if( mBuffer[0]==null ) createPostprocessingBuffers(mWidth,mHeight,mNear);
+        if( mBuffer==null ) createPostprocessingBuffers(mWidth,mHeight,mNear);
 
         if( lastBucket!=currBucket )
           {
@@ -389,13 +420,13 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
             for(int j=bucketChange; j<i; j++)
               {
               child2 = children.get(j);
-              numRenders += child2.markStencilAndDepth(time,mBuffer[internalQuality],lastQueue);
+              numRenders += child2.markStencilAndDepth(time,mBuffer[internalQuality][0],lastQueue);
               }
 
             numRenders += lastQueue.postprocess(mBuffer);
-            numRenders += oitBuild(mBuffer[quality]);
+            numRenders += oitBuild(mBuffer[quality][0]);
             GLES31.glMemoryBarrier(GLES31.GL_SHADER_STORAGE_BARRIER_BIT|GLES31.GL_ATOMIC_COUNTER_BARRIER_BIT);
-            clearBuffer(mBuffer[quality]);
+            clearPostprocessingBuffer(quality);
             }
 
           internalQuality = currQueue.getInternalQuality();
@@ -403,22 +434,22 @@ public abstract class DistortedOutputSurface extends DistortedSurface implements
           bucketChange    = i;
           }
 
-        mBuffer[quality].setAsOutput(time);
-        child1.drawNoBlend(time,mBuffer[quality]);
+        mBuffer[quality][0].setAsOutput(time);
+        child1.drawNoBlend(time,mBuffer[quality][0]);
 
         if( i==numChildren-1 )
           {
           for(int j=bucketChange; j<numChildren; j++)
             {
             child2 = children.get(j);
-            numRenders += child2.markStencilAndDepth(time,mBuffer[internalQuality],currQueue);
+            numRenders += child2.markStencilAndDepth(time,mBuffer[internalQuality][0],currQueue);
             }
 
           numRenders += currQueue.postprocess(mBuffer);
-          numRenders += oitBuild(mBuffer[quality]);
+          numRenders += oitBuild(mBuffer[quality][0]);
           GLES31.glMemoryBarrier(GLES31.GL_SHADER_STORAGE_BARRIER_BIT|GLES31.GL_ATOMIC_COUNTER_BARRIER_BIT);
           numRenders += oitRender(time);  // merge the OIT linked list
-          clearBuffer(mBuffer[quality]);
+          clearPostprocessingBuffer(quality);
           }
         } // end else (postprocessed child)
 
diff --git a/src/main/java/org/distorted/library/main/EffectQueuePostprocess.java b/src/main/java/org/distorted/library/main/EffectQueuePostprocess.java
index d3bb295..0dfb1a8 100644
--- a/src/main/java/org/distorted/library/main/EffectQueuePostprocess.java
+++ b/src/main/java/org/distorted/library/main/EffectQueuePostprocess.java
@@ -100,7 +100,7 @@ class EffectQueuePostprocess extends EffectQueue
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  int postprocess(DistortedOutputSurface[] buffers)
+  int postprocess(DistortedOutputSurface[][] buffers)
     {
     int numRenders = 0;
 
