commit 86d322b5bb07f6a4744c49a01af6bf7d425af959
Author: Leszek Koltunski <leszek@distoretedandroid.org>
Date:   Tue Jun 27 14:03:20 2017 +0100

    Make Postprocessing quality per-effect (rather than applied to the whole queue)

diff --git a/src/main/java/org/distorted/library/effect/PostprocessEffect.java b/src/main/java/org/distorted/library/effect/PostprocessEffect.java
index 4e413f9..11e7370 100644
--- a/src/main/java/org/distorted/library/effect/PostprocessEffect.java
+++ b/src/main/java/org/distorted/library/effect/PostprocessEffect.java
@@ -20,6 +20,7 @@
 package org.distorted.library.effect;
 
 import org.distorted.library.main.DistortedFramebuffer;
+import org.distorted.library.main.DistortedMaster;
 import org.distorted.library.program.DistortedProgram;
 
 import java.nio.ByteBuffer;
@@ -31,8 +32,9 @@ import java.util.ArrayList;
 /**
  * Postprocessing Effect - an Effect that works by running a certain Shader Program(s) on a Framebuffer.
  */
-public abstract class PostprocessEffect extends Effect
+public abstract class PostprocessEffect extends Effect implements DistortedMaster.Slave
   {
+  private static final int MIPMAP = 0;
 /**
  * 5: 5 per-effect interpolated values.
  */
@@ -64,7 +66,7 @@ public abstract class PostprocessEffect extends Effect
     {
     private String mName, mVertexShader, mFragmentShader;
 
-    public Source(String name, String vertex, String fragment)
+    Source(String name, String vertex, String fragment)
       {
       mName           = name;
       mVertexShader   = vertex;
@@ -76,6 +78,23 @@ public abstract class PostprocessEffect extends Effect
   private static ArrayList<Source> mSources = new ArrayList<>();
   private static int mNumSources = 0;
 
+  private class Job
+    {
+    int type;
+    int level;
+
+    Job(int t, int l)
+      {
+      type = t;
+      level= l;
+      }
+    }
+
+  private ArrayList<Job> mJobs = new ArrayList<>();
+
+  int mQualityLevel;
+  float mQualityScale;
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   static int register(final String name, final String vertexShader, final String fragmentShader)
@@ -120,12 +139,69 @@ public abstract class PostprocessEffect extends Effect
  *
  * @y.exclude
  */
-  public abstract int apply(float[] uniforms, int index, float qualityScale, DistortedFramebuffer buffer);
+  public abstract int apply(float[] uniforms, int index, DistortedFramebuffer[] buffers);
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Only for use by the library itself.
+ *
+ * @y.exclude
+ */
+  public abstract int getQuality();
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * This is not really part of the public API. Has to be public only because it is a part of the
+ * DistortedSlave interface, which should really be a class that we extend here instead but
+ * Java has no multiple inheritance.
+ *
+ * @y.exclude
+ */
+  public void doWork()
+    {
+    int num = mJobs.size();
+    Job job;
+
+    for(int i=0; i<num; i++)
+      {
+      job = mJobs.remove(0);
+
+      switch(job.type)
+        {
+        case MIPMAP: int level = job.level;
+                     mQualityLevel = level;
+                     mQualityScale = 1.0f;
+                     for(int j=0; j<level; j++) mQualityScale*= EffectQuality.MULTIPLIER;
+                     break;
+        }
+      }
+    }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   PostprocessEffect(EffectName name)
     {
     super(name);
+
+    mQualityLevel = 0;
+    mQualityScale = 1.0f;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// PUBLIC API
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * The higher the quality, the better the effect will look like and the slower it will be.
+ * <p>
+ * This works by rendering into smaller and smaller intermediate buffers. Each step renders into a
+ * buffer that's half the size of the previous one.
+ * <p>
+ * We cannot this during mid-render - thus, give it to the Master to assign us back this job on the
+ * next render.
+ */
+  public void setQuality(EffectQuality quality)
+    {
+    mJobs.add(new Job(MIPMAP,quality.getLevel()));
+    DistortedMaster.newSlave(this);
     }
   }
\ No newline at end of file
diff --git a/src/main/java/org/distorted/library/effect/PostprocessEffectBlur.java b/src/main/java/org/distorted/library/effect/PostprocessEffectBlur.java
index b474b85..97533dc 100644
--- a/src/main/java/org/distorted/library/effect/PostprocessEffectBlur.java
+++ b/src/main/java/org/distorted/library/effect/PostprocessEffectBlur.java
@@ -127,7 +127,18 @@ public class PostprocessEffectBlur extends PostprocessEffect
  *
  * @y.exclude
  */
-  public int apply(float[] uniforms, int index, float qualityScale, DistortedFramebuffer buffer)
+ public int getQuality()
+   {
+   return mQualityLevel;
+   }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Only for use by the library itself.
+ *
+ * @y.exclude
+ */
+  public int apply(float[] uniforms, int index, DistortedFramebuffer[] buffers)
     {
     if( mProgram1 ==null)
       {
@@ -135,13 +146,15 @@ public class PostprocessEffectBlur extends PostprocessEffect
       mProgram2 = mPrograms.get(mIndex2);
       }
 
+    DistortedFramebuffer buffer = buffers[mQualityLevel];
+
     buffer.setAsOutput();
 
     float w1  = buffer.getWidth();
     float h1  = buffer.getHeight();
     float near= 1.0f - buffer.getNear();
 
-    int radius = (int)(uniforms[index]*qualityScale);
+    int radius = (int)(uniforms[index]*mQualityScale);
     if( radius>=MAX_HALO ) radius = MAX_HALO-1;
     computeGaussianKernel(radius);
 
diff --git a/src/main/java/org/distorted/library/effect/PostprocessEffectGlow.java b/src/main/java/org/distorted/library/effect/PostprocessEffectGlow.java
index 959ab0a..782fd30 100644
--- a/src/main/java/org/distorted/library/effect/PostprocessEffectGlow.java
+++ b/src/main/java/org/distorted/library/effect/PostprocessEffectGlow.java
@@ -130,7 +130,18 @@ public class PostprocessEffectGlow extends PostprocessEffect
  *
  * @y.exclude
  */
-  public int apply(float[] uniforms, int index, float qualityScale, DistortedFramebuffer buffer)
+ public int getQuality()
+   {
+   return 0;
+   }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Only for use by the library itself.
+ *
+ * @y.exclude
+ */
+  public int apply(float[] uniforms, int index, DistortedFramebuffer[] buffers)
     {
     if( mProgram1 ==null)
       {
@@ -138,13 +149,15 @@ public class PostprocessEffectGlow extends PostprocessEffect
       mProgram2 = mPrograms.get(mIndex2);
       }
 
+    DistortedFramebuffer buffer = buffers[mQualityLevel];
+
     buffer.setAsOutput();
 
     float w1  = buffer.getWidth();
     float h1  = buffer.getHeight();
     float near= 1.0f - buffer.getNear();
 
-    int radius = (int)(uniforms[index]*qualityScale);
+    int radius = (int)(uniforms[index]*mQualityScale);
     if( radius>=MAX_HALO ) radius = MAX_HALO-1;
     computeGaussianKernel(radius);
 
diff --git a/src/main/java/org/distorted/library/main/DistortedEffects.java b/src/main/java/org/distorted/library/main/DistortedEffects.java
index b633cbf..0a60dc6 100644
--- a/src/main/java/org/distorted/library/main/DistortedEffects.java
+++ b/src/main/java/org/distorted/library/main/DistortedEffects.java
@@ -49,10 +49,8 @@ import java.util.ArrayList;
  * <p>
  * The queues hold actual effects to be applied to a given (InputSurface,MeshObject) combo.
  */
-public class DistortedEffects implements DistortedSlave
+public class DistortedEffects
   {
-  private static final int MIPMAP = 0;
-
   /// MAIN PROGRAM ///
   private static DistortedProgram mMainProgram;
   private static int mMainTextureH;
@@ -91,20 +89,6 @@ public class DistortedEffects implements DistortedSlave
 
   private boolean matrixCloned, vertexCloned, fragmentCloned, postprocessCloned;
 
-  private class Job
-    {
-    int type;
-    int level;
-
-    Job(int t, int l)
-      {
-      type = t;
-      level= l;
-      }
-    }
-
-  private ArrayList<Job> mJobs = new ArrayList<>();
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   static void createProgram(Resources resources)
@@ -263,7 +247,7 @@ public class DistortedEffects implements DistortedSlave
 
   int getQuality()
     {
-    return mP.mQualityLevel;
+    return mP.getQuality();
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -283,34 +267,6 @@ public class DistortedEffects implements DistortedSlave
     mP.newNode(node);
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * This is not really part of the public API. Has to be public only because it is a part of the
- * DistortedSlave interface, which should really be a class that we extend here instead but
- * Java has no multiple inheritance.
- *
- * @y.exclude
- */
-  public void doWork()
-    {
-    int num = mJobs.size();
-    Job job;
-
-    for(int i=0; i<num; i++)
-      {
-      job = mJobs.remove(0);
-
-      switch(job.type)
-        {
-        case MIPMAP: int level = job.level;
-                     mP.mQualityLevel = level;
-                     mP.mQualityScale = 1.0f;
-                     for(int j=0; j<level; j++) mP.mQualityScale*= EffectQuality.MULTIPLIER;
-                     break;
-        }
-      }
-    }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private void displayNormals(MeshObject mesh)
@@ -627,22 +583,6 @@ public class DistortedEffects implements DistortedSlave
     return EffectQueue.setMax(type.ordinal(),max);
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * The higher the quality, the better the effect will look like and the slower it will be.
- * <p>
- * This works by rendering into smaller and smaller intermediate buffers. Each step renders into a
- * buffer that's half the size of the previous one.
- * <p>
- * We cannot this during mid-render - thus, give it to the Master to assign us back this job on the
- * next render.
- */
-  public void setPostprocessingQuality(EffectQuality quality)
-    {
-    mJobs.add(new Job(MIPMAP,quality.getLevel()));
-    DistortedMaster.newSlave(this);
-    }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
  * Add a new Effect to our queue.
diff --git a/src/main/java/org/distorted/library/main/DistortedMaster.java b/src/main/java/org/distorted/library/main/DistortedMaster.java
index d39fcc0..65c561e 100644
--- a/src/main/java/org/distorted/library/main/DistortedMaster.java
+++ b/src/main/java/org/distorted/library/main/DistortedMaster.java
@@ -25,10 +25,27 @@ import java.util.ArrayList;
 /**
  * This static class handles assigning jobs to other classes. It does it once, at the beginning of
  * each frame.
+ * <p>
+ * Not part of public API, do not document (public only because has to be used in PostprocessEffects)
+ *
+ * @y.exclude
  */
-class DistortedMaster
+public class DistortedMaster
   {
-  private static ArrayList<DistortedSlave> mSlaves = new ArrayList<>();
+  private static ArrayList<Slave> mSlaves = new ArrayList<>();
+/**
+ * Not part of public API, do not document (public only because has to be used in PostprocessEffects)
+ *
+ * @y.exclude
+ */
+  public interface Slave
+    {
+    /**
+     * Not part of public API, do not document
+     * @y.exclude
+     */
+    void doWork();
+    }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -41,7 +58,7 @@ class DistortedMaster
 
   static boolean toDo()
     {
-    DistortedSlave slave;
+    Slave slave;
     int num = mSlaves.size();
 
     for(int i=0; i<num; i++)
@@ -54,12 +71,15 @@ class DistortedMaster
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  static void newSlave(DistortedSlave s)
+/**
+ * Not part of public API, do not document
+ * @y.exclude
+ */
+  public static void newSlave(Slave s)
     {
     int num = mSlaves.size();
     boolean found = false;
-    DistortedSlave tmp;
+    Slave tmp;
 
     for(int i=0; i<num; i++)
       {
diff --git a/src/main/java/org/distorted/library/main/DistortedNode.java b/src/main/java/org/distorted/library/main/DistortedNode.java
index 53ed1af..5436670 100644
--- a/src/main/java/org/distorted/library/main/DistortedNode.java
+++ b/src/main/java/org/distorted/library/main/DistortedNode.java
@@ -34,7 +34,7 @@ import java.util.HashMap;
  * to sub-class 'NodeData'. Two identical sub-trees attached at different points of the main tree
  * will point to the same NodeData; only the first of this is rendered (mData.numRender!).
  */
-public class DistortedNode implements DistortedSlave
+public class DistortedNode implements DistortedMaster.Slave
   {
   private static final int ATTACH = 0;
   private static final int DETACH = 1;
diff --git a/src/main/java/org/distorted/library/main/DistortedOutputSurface.java b/src/main/java/org/distorted/library/main/DistortedOutputSurface.java
index a21ac17..bb2817d 100644
--- a/src/main/java/org/distorted/library/main/DistortedOutputSurface.java
+++ b/src/main/java/org/distorted/library/main/DistortedOutputSurface.java
@@ -28,7 +28,7 @@ import java.util.ArrayList;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-abstract class DistortedOutputSurface extends DistortedSurface implements DistortedSlave
+abstract class DistortedOutputSurface extends DistortedSurface implements DistortedMaster.Slave
 {
 //////////// DEBUG FLAGS /////////////////////////////////////////////
 /**
diff --git a/src/main/java/org/distorted/library/main/DistortedSlave.java b/src/main/java/org/distorted/library/main/DistortedSlave.java
deleted file mode 100644
index b9d3c6c..0000000
--- a/src/main/java/org/distorted/library/main/DistortedSlave.java
+++ /dev/null
@@ -1,37 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Copyright 2016 Leszek Koltunski                                                               //
-//                                                                                               //
-// This file is part of Distorted.                                                               //
-//                                                                                               //
-// Distorted is free software: you can redistribute it and/or modify                             //
-// it under the terms of the GNU General Public License as published by                          //
-// the Free Software Foundation, either version 2 of the License, or                             //
-// (at your option) any later version.                                                           //
-//                                                                                               //
-// Distorted is distributed in the hope that it will be useful,                                  //
-// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
-// GNU General Public License for more details.                                                  //
-//                                                                                               //
-// You should have received a copy of the GNU General Public License                             //
-// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-package org.distorted.library.main;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * Package-private interface implemented by all objects which can be assigned work by the DistortedMaster.
- * <p>
- * All the methods below are really meant to be package-local; and this interface should really be a
- * package-local class which other classes would extend (but that's impossible because OutputSurface
- * already extends other class).
- */
-interface DistortedSlave
-  {
-  /**
-   * Not part of public API, do not document
-   * @y.exclude
-   */
-  void doWork();
-  }
diff --git a/src/main/java/org/distorted/library/main/EffectQueue.java b/src/main/java/org/distorted/library/main/EffectQueue.java
index 5178c6e..ef9fe4f 100644
--- a/src/main/java/org/distorted/library/main/EffectQueue.java
+++ b/src/main/java/org/distorted/library/main/EffectQueue.java
@@ -30,7 +30,7 @@ import java.util.HashMap;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-abstract class EffectQueue implements DistortedSlave
+abstract class EffectQueue implements DistortedMaster.Slave
   {
   private static final int ATTACH = 0;
   private static final int DETACH = 1;
diff --git a/src/main/java/org/distorted/library/main/EffectQueuePostprocess.java b/src/main/java/org/distorted/library/main/EffectQueuePostprocess.java
index 07462fa..e2f336f 100644
--- a/src/main/java/org/distorted/library/main/EffectQueuePostprocess.java
+++ b/src/main/java/org/distorted/library/main/EffectQueuePostprocess.java
@@ -30,8 +30,7 @@ class EffectQueuePostprocess extends EffectQueue
   private static final int NUM_UNIFORMS = PostprocessEffect.NUM_UNIFORMS;
   private static final int INDEX = EffectType.POSTPROCESS.ordinal();
 
-  int mQualityLevel;
-  float mQualityScale;
+
   private int mHalo;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -39,9 +38,6 @@ class EffectQueuePostprocess extends EffectQueue
   EffectQueuePostprocess(long id)
     { 
     super(id,NUM_UNIFORMS,INDEX );
-
-    mQualityLevel = 0;
-    mQualityScale = 1.0f;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -87,6 +83,13 @@ class EffectQueuePostprocess extends EffectQueue
     return mNumEffects>0 ? mHalo : 0;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  int getQuality()
+    {
+    return mNumEffects>0 ? ((PostprocessEffect)mEffects[0]).getQuality() : 0;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   int postprocess(DistortedOutputSurface surface)
@@ -97,7 +100,7 @@ class EffectQueuePostprocess extends EffectQueue
 
     for(int i=0; i<mNumEffects; i++)
       {
-      numRenders += ((PostprocessEffect)mEffects[i]).apply(mUniforms,NUM_UNIFORMS*i,mQualityScale,surface.mBuffer[mQualityLevel]);
+      numRenders += ((PostprocessEffect)mEffects[i]).apply(mUniforms,NUM_UNIFORMS*i, surface.mBuffer);
       }
     DistortedRenderState.unuseStencilMark();
 
