Merge "pseudo random number generator in shader with limited precisions" into jb-dev
diff --git a/media/mca/filterpacks/java/android/filterpacks/imageproc/BitmapOverlayFilter.java b/media/mca/filterpacks/java/android/filterpacks/imageproc/BitmapOverlayFilter.java
index d4c901f..e4bb6cf 100644
--- a/media/mca/filterpacks/java/android/filterpacks/imageproc/BitmapOverlayFilter.java
+++ b/media/mca/filterpacks/java/android/filterpacks/imageproc/BitmapOverlayFilter.java
@@ -46,8 +46,6 @@
     private Program mProgram;
     private Frame mFrame;
 
-    private int mWidth = 0;
-    private int mHeight = 0;
     private int mTarget = FrameFormat.TARGET_UNSPECIFIED;
 
     private final String mOverlayShader =
@@ -113,18 +111,17 @@
             initProgram(context, inputFormat.getTarget());
         }
 
-        // Check if the frame size has changed
-        if (inputFormat.getWidth() != mWidth || inputFormat.getHeight() != mHeight) {
-            mWidth = inputFormat.getWidth();
-            mHeight = inputFormat.getHeight();
+        if (mBitmap != null) {
+            Frame frame = createBitmapFrame(context);
+            // Process
+            Frame[] inputs = {input, frame};
+            mProgram.process(inputs, output);
 
-            createBitmapFrame(context);
+            frame.release();
+        } else {
+            output.setDataFromFrame(input);
         }
 
-        // Process
-        Frame[] inputs = {input, mFrame};
-        mProgram.process(inputs, output);
-
         // Push output
         pushOutput("image", output);
 
@@ -132,22 +129,18 @@
         output.release();
     }
 
-    private void createBitmapFrame(FilterContext context) {
-        if (mBitmap != null) {
-            FrameFormat format = ImageFormat.create(mBitmap.getWidth(),
-                                                    mBitmap.getHeight(),
-                                                    ImageFormat.COLORSPACE_RGBA,
-                                                    FrameFormat.TARGET_GPU);
+    private Frame createBitmapFrame(FilterContext context) {
+        FrameFormat format = ImageFormat.create(mBitmap.getWidth(),
+                                                mBitmap.getHeight(),
+                                                ImageFormat.COLORSPACE_RGBA,
+                                                FrameFormat.TARGET_GPU);
 
-            if (mFrame != null) {
-                mFrame.release();
-            }
+        Frame frame = context.getFrameManager().newFrame(format);
+        frame.setBitmap(mBitmap);
 
-            mFrame = context.getFrameManager().newFrame(format);
-            mFrame.setBitmap(mBitmap);
+        mBitmap.recycle();
+        mBitmap = null;
 
-            mBitmap.recycle();
-            mBitmap = null;
-        }
+        return frame;
     }
 }
diff --git a/media/mca/filterpacks/java/android/filterpacks/imageproc/BlackWhiteFilter.java b/media/mca/filterpacks/java/android/filterpacks/imageproc/BlackWhiteFilter.java
index 9e40d37..dd7f5e0 100644
--- a/media/mca/filterpacks/java/android/filterpacks/imageproc/BlackWhiteFilter.java
+++ b/media/mca/filterpacks/java/android/filterpacks/imageproc/BlackWhiteFilter.java
@@ -28,6 +28,7 @@
 import android.filterfw.core.ShaderProgram;
 import android.filterfw.format.ImageFormat;
 
+import java.util.Date;
 import java.util.Random;
 
 public class BlackWhiteFilter extends Filter {
@@ -42,24 +43,30 @@
     private int mTileSize = 640;
 
     private Program mProgram;
+    private Random mRandom;
 
-    private int mWidth = 0;
-    private int mHeight = 0;
     private int mTarget = FrameFormat.TARGET_UNSPECIFIED;
 
     private final String mBlackWhiteShader =
             "precision mediump float;\n" +
             "uniform sampler2D tex_sampler_0;\n" +
+            "uniform vec2 seed;\n" +
             "uniform float black;\n" +
             "uniform float scale;\n" +
             "uniform float stepsize;\n" +
             "varying vec2 v_texcoord;\n" +
             "float rand(vec2 loc) {\n" +
-            "  return fract(sin(dot(loc, vec2(12.9898, 78.233))) * 43758.5453);\n" +
+            "  const float divide = 0.00048828125;\n" +
+            "  const float factor = 2048.0;\n" +
+            "  float value = sin(dot(loc, vec2(12.9898, 78.233)));\n" +
+            "  float residual = mod(dot(mod(loc, divide), vec2(0.9898, 0.233)), divide);\n" +
+            "  float part2 = mod(value, divide);\n" +
+            "  float part1 = value - part2;\n" +
+            "  return fract(0.5453 * part1 + factor * (part2 + residual));\n" +
             "}\n" +
             "void main() {\n" +
             "  vec4 color = texture2D(tex_sampler_0, v_texcoord);\n" +
-            "  float dither = rand(v_texcoord);\n" +
+            "  float dither = rand(v_texcoord + seed);\n" +
             "  vec3 xform = clamp((color.rgb - black) * scale, 0.0, 1.0);\n" +
             "  vec3 temp = clamp((color.rgb + stepsize - black) * scale, 0.0, 1.0);\n" +
             "  vec3 new_color = clamp(xform + (temp - xform) * (dither - 0.5), 0.0, 1.0);\n" +
@@ -68,6 +75,7 @@
 
     public BlackWhiteFilter(String name) {
         super(name);
+        mRandom = new Random(new Date().getTime());
     }
 
     @Override
@@ -100,10 +108,12 @@
     private void updateParameters() {
         float scale = (mBlack != mWhite) ? 1.0f / (mWhite - mBlack) : 2000f;
         float stepsize = 1.0f / 255.0f;
-
         mProgram.setHostValue("black", mBlack);
         mProgram.setHostValue("scale", scale);
         mProgram.setHostValue("stepsize", stepsize);
+
+        float seed[] = { mRandom.nextFloat(), mRandom.nextFloat() };
+        mProgram.setHostValue("seed", seed);
     }
 
     @Override
@@ -124,12 +134,6 @@
             initProgram(context, inputFormat.getTarget());
         }
 
-        // Check if the frame size has changed
-        if (inputFormat.getWidth() != mWidth || inputFormat.getHeight() != mHeight) {
-            mWidth = inputFormat.getWidth();
-            mHeight = inputFormat.getHeight();
-        }
-
         // Create output frame
         Frame output = context.getFrameManager().newFrame(inputFormat);
 
diff --git a/media/mca/filterpacks/java/android/filterpacks/imageproc/DocumentaryFilter.java b/media/mca/filterpacks/java/android/filterpacks/imageproc/DocumentaryFilter.java
index 0144d4e..377e49d5 100644
--- a/media/mca/filterpacks/java/android/filterpacks/imageproc/DocumentaryFilter.java
+++ b/media/mca/filterpacks/java/android/filterpacks/imageproc/DocumentaryFilter.java
@@ -28,6 +28,7 @@
 import android.filterfw.core.ShaderProgram;
 import android.filterfw.format.ImageFormat;
 
+import java.util.Date;
 import java.util.Random;
 
 public class DocumentaryFilter extends Filter {
@@ -36,6 +37,7 @@
     private int mTileSize = 640;
 
     private Program mProgram;
+    private Random mRandom;
 
     private int mWidth = 0;
     private int mHeight = 0;
@@ -44,17 +46,24 @@
     private final String mDocumentaryShader =
             "precision mediump float;\n" +
             "uniform sampler2D tex_sampler_0;\n" +
+            "uniform vec2 seed;\n" +
             "uniform float stepsize;\n" +
             "uniform float inv_max_dist;\n" +
             "uniform vec2 center;\n" +
             "varying vec2 v_texcoord;\n" +
             "float rand(vec2 loc) {\n" +
-            "  return fract(sin(dot(loc, vec2(12.9898, 78.233))) * 43758.5453);\n" +
+            "  const float divide = 0.00048828125;\n" +
+            "  const float factor = 2048.0;\n" +
+            "  float value = sin(dot(loc, vec2(12.9898, 78.233)));\n" +
+            "  float residual = mod(dot(mod(loc, divide), vec2(0.9898, 0.233)), divide);\n" +
+            "  float part2 = mod(value, divide);\n" +
+            "  float part1 = value - part2;\n" +
+            "  return fract(0.5453 * part1 + factor * (part2 + residual));\n" +
             "}\n" +
             "void main() {\n" +
             // black white
             "  vec4 color = texture2D(tex_sampler_0, v_texcoord);\n" +
-            "  float dither = rand(v_texcoord);\n" +
+            "  float dither = rand(v_texcoord + seed);\n" +
             "  vec3 xform = clamp(2.0 * color.rgb, 0.0, 1.0);\n" +
             "  vec3 temp = clamp(2.0 * (color.rgb + stepsize), 0.0, 1.0);\n" +
             "  vec3 new_color = clamp(xform + (temp - xform) * (dither - 0.5), 0.0, 1.0);\n" +
@@ -69,6 +78,8 @@
 
     public DocumentaryFilter(String name) {
         super(name);
+        Date date = new Date();
+        mRandom = new Random(new Date().getTime());
     }
 
     @Override
@@ -138,7 +149,9 @@
             mProgram.setHostValue("center", center);
             mProgram.setHostValue("inv_max_dist", 1.0f / max_dist);
             mProgram.setHostValue("stepsize", 1.0f / 255.0f);
+
+            float seed[] = { mRandom.nextFloat(), mRandom.nextFloat() };
+            mProgram.setHostValue("seed", seed);
         }
     }
-
 }
diff --git a/media/mca/filterpacks/java/android/filterpacks/imageproc/GrainFilter.java b/media/mca/filterpacks/java/android/filterpacks/imageproc/GrainFilter.java
index 31855460..f236856 100644
--- a/media/mca/filterpacks/java/android/filterpacks/imageproc/GrainFilter.java
+++ b/media/mca/filterpacks/java/android/filterpacks/imageproc/GrainFilter.java
@@ -30,6 +30,7 @@
 import android.filterfw.geometry.Quad;
 import android.filterfw.geometry.Point;
 
+import java.util.Date;
 import java.util.Random;
 
 public class GrainFilter extends Filter {
@@ -49,14 +50,20 @@
     private int mHeight = 0;
     private int mTarget = FrameFormat.TARGET_UNSPECIFIED;
 
-    private Random mRandom = new Random();
+    private Random mRandom;
 
     private final String mNoiseShader =
             "precision mediump float;\n" +
             "uniform vec2 seed;\n" +
             "varying vec2 v_texcoord;\n" +
             "float rand(vec2 loc) {\n" +
-            "  return fract(sin(dot(loc, vec2(12.9898, 78.233))) * 43758.5453);\n" +
+            "  const float divide = 0.00048828125;\n" +
+            "  const float factor = 2048.0;\n" +
+            "  float value = sin(dot(loc, vec2(12.9898, 78.233)));\n" +
+            "  float residual = mod(dot(mod(loc, divide), vec2(0.9898, 0.233)), divide);\n" +
+            "  float part2 = mod(value, divide);\n" +
+            "  float part1 = value - part2;\n" +
+            "  return fract(0.5453 * part1 + factor * (part2 + residual));\n" +
             "}\n" +
             "void main() {\n" +
             "  gl_FragColor = vec4(rand(v_texcoord + seed), 0.0, 0.0, 1.0);\n" +
@@ -86,6 +93,7 @@
 
     public GrainFilter(String name) {
         super(name);
+        mRandom = new Random(new Date().getTime());
     }
 
     @Override
diff --git a/media/mca/filterpacks/java/android/filterpacks/imageproc/LomoishFilter.java b/media/mca/filterpacks/java/android/filterpacks/imageproc/LomoishFilter.java
index 0814ba5..22a2ec8 100644
--- a/media/mca/filterpacks/java/android/filterpacks/imageproc/LomoishFilter.java
+++ b/media/mca/filterpacks/java/android/filterpacks/imageproc/LomoishFilter.java
@@ -28,12 +28,16 @@
 import android.filterfw.core.ShaderProgram;
 import android.filterfw.format.ImageFormat;
 
+import java.util.Date;
+import java.util.Random;
+
 public class LomoishFilter extends Filter {
 
     @GenerateFieldPort(name = "tile_size", hasDefault = true)
     private int mTileSize = 640;
 
     private Program mProgram;
+    private Random mRandom;
 
     private int mWidth = 0;
     private int mHeight = 0;
@@ -42,6 +46,7 @@
     private final String mLomoishShader =
             "precision mediump float;\n" +
             "uniform sampler2D tex_sampler_0;\n" +
+            "uniform vec2 seed;\n" +
             "uniform float stepsizeX;\n" +
             "uniform float stepsizeY;\n" +
             "uniform float stepsize;\n" +
@@ -49,7 +54,13 @@
             "uniform float inv_max_dist;\n" +
             "varying vec2 v_texcoord;\n" +
             "float rand(vec2 loc) {\n" +
-            "  return fract(sin(dot(loc, vec2(12.9898, 78.233))) * 43758.5453);\n" +
+            "  const float divide = 0.00048828125;\n" +
+            "  const float factor = 2048.0;\n" +
+            "  float value = sin(dot(loc, vec2(12.9898, 78.233)));\n" +
+            "  float residual = mod(dot(mod(loc, divide), vec2(0.9898, 0.233)), divide);\n" +
+            "  float part2 = mod(value, divide);\n" +
+            "  float part1 = value - part2;\n" +
+            "  return fract(0.5453 * part1 + factor * (part2 + residual));\n" +
             "}\n" +
             "void main() {\n" +
             // sharpen
@@ -96,7 +107,7 @@
             "  }\n" +
             "  c_color.b = s_color.b * 0.5 + 0.25;\n" +
             // blackwhite
-            "  float dither = rand(v_texcoord);\n" +
+            "  float dither = rand(v_texcoord + seed);\n" +
             "  vec3 xform = clamp((c_color.rgb - 0.15) * 1.53846, 0.0, 1.0);\n" +
             "  vec3 temp = clamp((color.rgb + stepsize - 0.15) * 1.53846, 0.0, 1.0);\n" +
             "  vec3 bw_color = clamp(xform + (temp - xform) * (dither - 0.5), 0.0, 1.0);\n" +
@@ -108,6 +119,7 @@
 
     public LomoishFilter(String name) {
         super(name);
+        mRandom = new Random(new Date().getTime());
     }
 
     @Override
@@ -149,6 +161,9 @@
             mProgram.setHostValue("stepsize", 1.0f / 255.0f);
             mProgram.setHostValue("stepsizeX", 1.0f / mWidth);
             mProgram.setHostValue("stepsizeY", 1.0f / mHeight);
+
+            float seed[] = { mRandom.nextFloat(), mRandom.nextFloat() };
+            mProgram.setHostValue("seed", seed);
         }
     }
 
diff --git a/media/mca/filterpacks/java/android/filterpacks/imageproc/RedEyeFilter.java b/media/mca/filterpacks/java/android/filterpacks/imageproc/RedEyeFilter.java
index 5632a5e..3450ef1 100644
--- a/media/mca/filterpacks/java/android/filterpacks/imageproc/RedEyeFilter.java
+++ b/media/mca/filterpacks/java/android/filterpacks/imageproc/RedEyeFilter.java
@@ -115,14 +115,6 @@
     }
 
     @Override
-    public void tearDown(FilterContext context) {
-        if (mRedEyeBitmap != null) {
-            mRedEyeBitmap.recycle();
-            mRedEyeBitmap = null;
-        }
-    }
-
-    @Override
     public void process(FilterContext context) {
         // Get input frame
         Frame input = pullInput("image");
@@ -140,10 +132,7 @@
         if (inputFormat.getWidth() != mWidth || inputFormat.getHeight() != mHeight) {
             mWidth = inputFormat.getWidth();
             mHeight = inputFormat.getHeight();
-
-            createRedEyeBitmap();
         }
-
         createRedEyeFrame(context);
 
         // Process
@@ -168,29 +157,26 @@
         }
     }
 
-    private void createRedEyeBitmap() {
-        if (mRedEyeBitmap != null) {
-            mRedEyeBitmap.recycle();
-        }
-
+    private void createRedEyeFrame(FilterContext context) {
         int bitmapWidth = mWidth / 2;
         int bitmapHeight = mHeight / 2;
 
-        mRedEyeBitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
-        mCanvas.setBitmap(mRedEyeBitmap);
+        Bitmap redEyeBitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
+        mCanvas.setBitmap(redEyeBitmap);
         mPaint.setColor(Color.WHITE);
         mRadius = Math.max(MIN_RADIUS, RADIUS_RATIO * Math.min(bitmapWidth, bitmapHeight));
 
-        updateProgramParams();
-    }
+        for (int i = 0; i < mCenters.length; i += 2) {
+            mCanvas.drawCircle(mCenters[i] * bitmapWidth, mCenters[i + 1] * bitmapHeight,
+                               mRadius, mPaint);
+        }
 
-    private void createRedEyeFrame(FilterContext context) {
-        FrameFormat format = ImageFormat.create(mRedEyeBitmap.getWidth() ,
-                                                mRedEyeBitmap.getHeight(),
+        FrameFormat format = ImageFormat.create(bitmapWidth, bitmapHeight,
                                                 ImageFormat.COLORSPACE_RGBA,
                                                 FrameFormat.TARGET_GPU);
         mRedEyeFrame = context.getFrameManager().newFrame(format);
-        mRedEyeFrame.setBitmap(mRedEyeBitmap);
+        mRedEyeFrame.setBitmap(redEyeBitmap);
+        redEyeBitmap.recycle();
     }
 
     private void updateProgramParams() {
@@ -199,13 +185,5 @@
         if ( mCenters.length % 2 == 1) {
             throw new RuntimeException("The size of center array must be even.");
         }
-
-        if (mRedEyeBitmap != null) {
-            for (int i = 0; i < mCenters.length; i += 2) {
-                mCanvas.drawCircle(mCenters[i] * mRedEyeBitmap.getWidth(),
-                                   mCenters[i + 1] * mRedEyeBitmap.getHeight(),
-                                   mRadius, mPaint);
-            }
-        }
     }
 }