Added initial sweeping tests to uirendering tests.

Change-Id: Ia1f1c3b39d78165e80ac448fcabd76ab7faee1a0
diff --git a/tests/tests/uirendering/res/drawable/sunset1.jpg b/tests/tests/uirendering/res/drawable/sunset1.jpg
new file mode 100644
index 0000000..92851f3d
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable/sunset1.jpg
Binary files differ
diff --git a/tests/tests/uirendering/res/values/themes.xml b/tests/tests/uirendering/res/values/themes.xml
index 66941ff..2f13f47 100644
--- a/tests/tests/uirendering/res/values/themes.xml
+++ b/tests/tests/uirendering/res/values/themes.xml
@@ -18,5 +18,6 @@
         <item name="android:textColor">#FFF</item>
         <item name="android:windowNoTitle">true</item>
         <item name="android:windowFullscreen">true</item>
+        <item name="android:fadingEdge">none</item>
     </style>
 </resources>
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/BasicExactTests.java b/tests/tests/uirendering/src/android/uirendering/cts/BasicExactTests.java
index cadb109..f154476 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/BasicExactTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/BasicExactTests.java
@@ -158,7 +158,6 @@
                 canvas.drawText(testString, 30, 50, p);
             }
         };
-
         executeCanvasTest(canvasClient, mBitmapComparer);
     }
 
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/CanvasClientView.java b/tests/tests/uirendering/src/android/uirendering/cts/CanvasClientView.java
index 3c12ffd..aaa403a 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/CanvasClientView.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/CanvasClientView.java
@@ -17,6 +17,8 @@
 
 import android.content.Context;
 import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
 import android.view.View;
 
 /**
@@ -36,6 +38,13 @@
 
     @Override
     public void onDraw(Canvas canvas) {
+        if (CanvasCompareActivityTest.DEBUG) {
+            String s = canvas.isHardwareAccelerated() ? "HARDWARE" : "SOFTWARE";
+            Paint paint = new Paint();
+            paint.setColor(Color.BLACK);
+            paint.setTextSize(20);
+            canvas.drawText(s, 200, 200, paint);
+        }
         if (mCanvasClient != null) {
             canvas.save();
             canvas.clipRect(0, 0, mWidth, mHeight);
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/CanvasCompareActivityTest.java b/tests/tests/uirendering/src/android/uirendering/cts/CanvasCompareActivityTest.java
index b4ac593..90940c3 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/CanvasCompareActivityTest.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/CanvasCompareActivityTest.java
@@ -16,14 +16,13 @@
 package android.uirendering.cts;
 
 import android.graphics.Bitmap;
+import android.renderscript.Allocation;
+import android.renderscript.RenderScript;
+import android.test.ActivityInstrumentationTestCase2;
 import android.uirendering.cts.differencecalculators.DifferenceCalculator;
 import android.uirendering.cts.differencevisualizers.DifferenceVisualizer;
 import android.uirendering.cts.differencevisualizers.PassFailVisualizer;
 import android.uirendering.cts.util.BitmapDumper;
-import android.renderscript.Allocation;
-import android.renderscript.RenderScript;
-import android.test.ActivityInstrumentationTestCase2;
-import android.util.Log;
 
 /**
  * This class contains the basis for the graphics hardware test classes. Contained within this class
@@ -63,9 +62,6 @@
     public void setUp() {
         mDifferenceVisualizer = new PassFailVisualizer();
         mRenderScript = RenderScript.create(getActivity().getApplicationContext());
-        if (DEBUG) {
-            Log.d(TAG_NAME, "TEST NAME : " + getName());
-        }
     }
 
     /**
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/DisplayModifier.java b/tests/tests/uirendering/src/android/uirendering/cts/DisplayModifier.java
new file mode 100644
index 0000000..a884c5f
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/DisplayModifier.java
@@ -0,0 +1,592 @@
+/*
+     * Copyright (C) 2014 The Android Open Source Project
+     *
+     * Licensed under the Apache License, Version 2.0 (the "License");
+     * you may not use this file except in compliance with the License.
+     * You may obtain a copy of the License at
+     *
+     *      http://www.apache.org/licenses/LICENSE2.0
+     *
+     * Unless required by applicable law or agreed to in riting, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+package android.uirendering.cts;
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.RectF;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Modifies the canvas and paint objects when called.
+ */
+public abstract class DisplayModifier {
+    private static final RectF gRect = new RectF(0, 0, 100, 100);
+    private static final float[] gPts = new float[]{
+            0, 100, 100, 0, 100, 200, 200, 100
+    };
+    private static final float[] gTriPts = new float[]{
+            75, 0, 130, 130, 130, 130, 0, 130, 0, 130, 75, 0
+    };
+    private static final int NUM_PARALLEL_LINES = 24;
+    private static final float[] gLinePts = new float[NUM_PARALLEL_LINES * 8 + gTriPts.length];
+
+    static {
+        int index;
+        for (index = 0; index < gTriPts.length; index++) {
+            gLinePts[index] = gTriPts[index];
+        }
+        float val = 0;
+        for (int i = 0; i < NUM_PARALLEL_LINES; i++) {
+            gLinePts[index + 0] = 150;
+            gLinePts[index + 1] = val;
+            gLinePts[index + 2] = 300;
+            gLinePts[index + 3] = val;
+            index += 4;
+            val += 8 + (2.0f / NUM_PARALLEL_LINES);
+        }
+        val = 0;
+        for (int i = 0; i < NUM_PARALLEL_LINES; i++) {
+            gLinePts[index + 0] = val;
+            gLinePts[index + 1] = 150;
+            gLinePts[index + 2] = val;
+            gLinePts[index + 3] = 300;
+            index += 4;
+            val += 8 + (2.0f / NUM_PARALLEL_LINES);
+        }
+    }
+
+    // This linked hash map contains each of the different things that can be done to a canvas and
+    // paint object, like anti-aliasing or drawing. Within those LinkedHashMaps are the various
+    // options for that specific topic, which contains a displaymodifier which will affect the
+    // given canvas and paint objects.
+    public static final LinkedHashMap<String, LinkedHashMap<String, DisplayModifier>> sMaps =
+            new LinkedHashMap<String, LinkedHashMap<String,DisplayModifier>>() {
+                {
+                    put("aa", new LinkedHashMap<String, DisplayModifier>() {
+                        {
+                            put("true", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setAntiAlias(true);
+                                }
+                            });
+                            put("false", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setAntiAlias(false);
+                                }
+                            });
+                        }
+                    });
+                    put("style", new LinkedHashMap<String, DisplayModifier>() {
+                        {
+                            put("fill", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStyle(Paint.Style.FILL);
+                                }
+                            });
+                            put("stroke", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStyle(Paint.Style.STROKE);
+                                }
+                            });
+                            put("fillAndStroke", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStyle(Paint.Style.FILL_AND_STROKE);
+                                }
+                            });
+                        }
+                    });
+                    put("strokeWidth", new LinkedHashMap<String, DisplayModifier>() {
+                        {
+                            put("hair", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStrokeWidth(0);
+                                }
+                            });
+                            put("0.3", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStrokeWidth(0.3f);
+                                }
+                            });
+                            put("1", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStrokeWidth(1);
+                                }
+                            });
+                            put("5", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStrokeWidth(5);
+                                }
+                            });
+                            put("30", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStrokeWidth(30);
+                                }
+                            });
+                        }
+                    });
+                    put("strokeCap", new LinkedHashMap<String, DisplayModifier>() {
+                        {
+                            put("butt", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStrokeCap(Paint.Cap.BUTT);
+                                }
+                            });
+                            put("round", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStrokeCap(Paint.Cap.ROUND);
+                                }
+                            });
+                            put("square", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStrokeCap(Paint.Cap.SQUARE);
+                                }
+                            });
+                        }
+                    });
+                    put("strokeJoin", new LinkedHashMap<String, DisplayModifier>() {
+                        {
+                            put("bevel", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStrokeJoin(Paint.Join.BEVEL);
+                                }
+                            });
+                            put("round", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStrokeJoin(Paint.Join.ROUND);
+                                }
+                            });
+                            put("miter", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStrokeJoin(Paint.Join.MITER);
+                                }
+                            });
+                            // TODO: add miter0, miter1 etc to test miter distances
+                        }
+                    });
+
+                    put("transform", new LinkedHashMap<String, DisplayModifier>() {
+                        {
+                            put("noTransform", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                }
+                            });
+                            put("rotate5", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.rotate(5);
+                                }
+                            });
+                            put("rotate45", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.rotate(45);
+                                }
+                            });
+                            put("rotate90", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.rotate(90);
+                                    canvas.translate(0, -200);
+                                }
+                            });
+                            put("scale2x2", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.scale(2, 2);
+                                }
+                            });
+                            put("rot20scl1x4", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.rotate(20);
+                                    canvas.scale(1, 4);
+                                }
+                            });
+                        }
+                    });
+
+                    put("shader", new LinkedHashMap<String, DisplayModifier>() {
+                        {
+                            put("noShader", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                }
+                            });
+                            put("repeatShader", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setShader(ResourceModifier.instance().repeatShader);
+                                }
+                            });
+                            put("translatedShader", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setShader(ResourceModifier.instance().translatedShader);
+                                }
+                            });
+                            put("scaledShader", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setShader(ResourceModifier.instance().scaledShader);
+                                }
+                            });
+                            put("horGradient", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setShader(ResourceModifier.instance().horGradient);
+                                }
+                            });
+                            put("diagGradient", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setShader(ResourceModifier.instance().diagGradient);
+                                }
+                            });
+                            put("vertGradient", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setShader(ResourceModifier.instance().vertGradient);
+                                }
+                            });
+                            put("radGradient", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setShader(ResourceModifier.instance().radGradient);
+                                }
+                            });
+                            put("sweepGradient", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setShader(ResourceModifier.instance().sweepGradient);
+                                }
+                            });
+                            put("composeShader", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setShader(ResourceModifier.instance().composeShader);
+                                }
+                            });
+                            put("bad composeShader", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setShader(ResourceModifier.instance().nestedComposeShader);
+                                }
+                            });
+                            put("bad composeShader 2", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setShader(
+                                            ResourceModifier.instance().doubleGradientComposeShader);
+                                }
+                            });
+                        }
+                    });
+
+                    put("xfermodes", new LinkedHashMap<String, DisplayModifier>() {
+                        {
+                            put("SRC", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
+                                }
+                            });
+                            put("DST", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST));
+                                }
+                            });
+                            put("SRC_OVER", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
+                                }
+                            });
+                            put("DST_OVER", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OVER));
+                                }
+                            });
+                            put("SRC_IN", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
+                                }
+                            });
+                            put("DST_IN", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
+                                }
+                            });
+                            put("SRC_OUT", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
+                                }
+                            });
+                            put("DST_OUT", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
+                                }
+                            });
+                            put("SRC_ATOP", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
+                                }
+                            });
+                            put("DST_ATOP", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP));
+                                }
+                            });
+                            put("XOR", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR));
+                                }
+                            });
+                            put("MULTIPLY", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
+                                }
+                            });
+                            put("SCREEN", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SCREEN));
+                                }
+                            });
+                        }
+                    });
+
+                    // FINAL MAP: DOES ACTUAL DRAWING
+                    put("drawing", new LinkedHashMap<String, DisplayModifier>() {
+                        {
+                            put("roundRect", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.drawRoundRect(gRect, 20, 20, paint);
+                                }
+                            });
+                            put("rect", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.drawRect(gRect, paint);
+                                }
+                            });
+                            put("circle", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.drawCircle(100, 100, 75, paint);
+                                }
+                            });
+                            put("oval", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.drawOval(gRect, paint);
+                                }
+                            });
+                            put("lines", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.drawLines(gLinePts, paint);
+                                }
+                            });
+                            put("plusPoints", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.drawPoints(gPts, paint);
+                                }
+                            });
+                            put("text", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setTextSize(36);
+                                    canvas.drawText("TEXTTEST", 0, 50, paint);
+                                }
+                            });
+                            put("shadowtext", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setTextSize(36);
+                                    paint.setShadowLayer(3.0f, 0.0f, 3.0f, 0xffff00ff);
+                                    canvas.drawText("TEXTTEST", 0, 50, paint);
+                                }
+                            });
+                            put("bitmapMesh", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.drawBitmapMesh(ResourceModifier.instance().bitmap, 3, 3,
+                                            ResourceModifier.instance().bitmapVertices, 0, null, 0,
+                                            null);
+                                }
+                            });
+                            put("arc", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.drawArc(gRect, 260, 285, false, paint);
+                                }
+                            });
+                            put("arcFromCenter", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.drawArc(gRect, 260, 285, true, paint);
+                                }
+                            });
+                        }
+                    });
+                    // WARNING: DON'T PUT MORE MAPS BELOW THIS
+                }
+            };
+
+    abstract public void modifyDrawing(Paint paint, Canvas canvas);
+
+    public static class Accessor {
+        public final static int AA_MASK =           0x1 << 0;
+        public final static int STYLE_MASK =        0x1 << 1;
+        public final static int STROKE_WIDTH_MASK = 0x1 << 2;
+        public final static int STROKE_CAP_MASK =   0x1 << 3;
+        public final static int STROKE_JOIN_MASK =  0x1 << 4;
+        public final static int TRANSFORM_MASK =    0x1 << 5;
+        public final static int SHADER_MASK =       0x1 << 6;
+        public final static int XFERMODE_MASK =     0x1 << 7;
+        public final static int SHAPES_MASK =       0x1 << 8;
+        public final static int ALL_OPTIONS_MASK = 0x1FF;
+        public final static int SHAPES_INDEX = 8;
+        public final static int XFERMODE_INDEX = 7;
+        private final int mMask;
+
+        private int[] mIndices;
+        private LinkedHashMap<String, LinkedHashMap<String, DisplayModifier>> mDisplayMap;
+
+        public Accessor(int mask) {
+            int totalModifiers = Integer.bitCount(mask);
+            mIndices = new int[totalModifiers];
+            mMask = mask;
+            // Create a Display Map of the valid indices
+            mDisplayMap = new LinkedHashMap<String, LinkedHashMap<String, DisplayModifier>>();
+            int index = 0;
+            for (String key : DisplayModifier.sMaps.keySet()) {
+                if (validIndex(index)) {
+                    mDisplayMap.put(key, DisplayModifier.sMaps.get(key));
+                }
+                index++;
+            }
+        }
+
+        private LinkedHashMap<String, DisplayModifier> getMapAtIndex(int index) {
+            int i = 0;
+            for (LinkedHashMap<String, DisplayModifier> map : mDisplayMap.values()) {
+                if (i == index) {
+                    return map;
+                }
+                i++;
+            }
+            return null;
+        }
+
+        /**
+         * This will create the next combination of drawing commands. If we have done every combination,
+         * then we will return false.
+         * @return true if there is more combinations to do
+         */
+        public boolean step() {
+            int modifierMapIndex = mIndices.length - 1;
+            // Start from the last map, and loop until it is at the front
+            while (modifierMapIndex >= 0) {
+                LinkedHashMap<String, DisplayModifier> map = getMapAtIndex(modifierMapIndex);
+                mIndices[modifierMapIndex]++;
+
+                // If we are still at a valid index, then we don't need to update any others
+                if (mIndices[modifierMapIndex] < map.size()) {
+                    break;
+                }
+
+                // If we updated and it was outside the boundary, and it was the last index then
+                // we are done
+                if (modifierMapIndex == 0) {
+                    return false;
+                }
+                // If we ran off the end of the map, we need to update one more down the list
+                mIndices[modifierMapIndex] = 0;
+
+                modifierMapIndex--;
+            }
+            return true;
+        }
+
+        /**
+         * Modifies the canvas and paint given for the particular combination currently
+         */
+        public void modifyDrawing(Canvas canvas, Paint paint) {
+            final ArrayList<DisplayModifier> modifierArrayList = getModifierList();
+            for (DisplayModifier modifier : modifierArrayList) {
+                modifier.modifyDrawing(paint, canvas);
+            }
+        }
+
+        /**
+         * Gets a list of all the current modifications to be used.
+         */
+        private ArrayList<DisplayModifier> getModifierList() {
+            ArrayList<DisplayModifier> modifierArrayList = new ArrayList<DisplayModifier>();
+            int mapIndex = 0;
+
+            // Through each possible category of modification
+            for (LinkedHashMap<String, DisplayModifier> map : mDisplayMap.values()) {
+                int displayModifierIndex = mIndices[mapIndex];
+                // Loop until we find the modification we are going to use
+                for (Map.Entry<String, DisplayModifier> modifierEntry : map.entrySet()) {
+                    // Once we find the modification we want, then we will add it to the list,
+                    // and the last applied modifications
+                    if (displayModifierIndex == 0) {
+                        modifierArrayList.add(modifierEntry.getValue());
+                        break;
+                    }
+                    displayModifierIndex--;
+                }
+                mapIndex++;
+            }
+            return modifierArrayList;
+        }
+
+        /**
+         * Using the given masks, it tells if the map at the given index should be used, or not.
+         */
+        private boolean validIndex(int index) {
+            return (mMask & (0x1 << index)) != 0;
+        }
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/DrawActivity.java b/tests/tests/uirendering/src/android/uirendering/cts/DrawActivity.java
index e4c9a85..a2de434 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/DrawActivity.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/DrawActivity.java
@@ -30,6 +30,7 @@
 public class DrawActivity extends Activity {
     private final static long TIME_OUT = 10000;
     private final Object mLock = new Object();
+    public static final int MIN_NUMBER_OF_DRAWS = 5;
 
     private Handler mHandler;
     private View mView;
@@ -92,7 +93,6 @@
     }
 
     private class DrawCounterListener implements ViewTreeObserver.OnPreDrawListener {
-        private static final int MIN_NUMBER_OF_DRAWS = 5;
         private int mCurrentDraws = 0;
 
         @Override
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/LayoutTest.java b/tests/tests/uirendering/src/android/uirendering/cts/LayoutTest.java
index 114e00f..3644d8b 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/LayoutTest.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/LayoutTest.java
@@ -39,7 +39,6 @@
 
     @SmallTest
     public void testSimpleRectLayout() {
-        executeLayoutTest(R.layout.simple_rect_layout,
-                mBitmapComparer);
+        executeLayoutTest(R.layout.simple_rect_layout, mBitmapComparer);
     }
 }
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/ResourceModifier.java b/tests/tests/uirendering/src/android/uirendering/cts/ResourceModifier.java
new file mode 100644
index 0000000..a9e7dec
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/ResourceModifier.java
@@ -0,0 +1,133 @@
+/*
+  * Copyright (C) 2014 The Android Open Source Project
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *      http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+package android.uirendering.cts;
+
+import com.android.cts.uirendering.R;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.BitmapShader;
+import android.graphics.Color;
+import android.graphics.ComposeShader;
+import android.graphics.LinearGradient;
+import android.graphics.Matrix;
+import android.graphics.PorterDuff;
+import android.graphics.RadialGradient;
+import android.graphics.Shader;
+import android.graphics.SweepGradient;
+
+/**
+ * This will contain the resource-based content for the DisplayModifiers
+ */
+public class ResourceModifier {
+    private static ResourceModifier sInstance = null;
+
+    public final BitmapShader repeatShader;
+    public final BitmapShader translatedShader;
+    public final BitmapShader scaledShader;
+    public final LinearGradient horGradient;
+    public final LinearGradient diagGradient;
+    public final LinearGradient vertGradient;
+    public final RadialGradient radGradient;
+    public final SweepGradient sweepGradient;
+    public final ComposeShader composeShader;
+    public final ComposeShader nestedComposeShader;
+    public final ComposeShader doubleGradientComposeShader;
+    public final Bitmap bitmap;
+    public final float[] bitmapVertices;
+    public final int[] bitmapColors;
+
+    public ResourceModifier(Resources resources) {
+        bitmap = BitmapFactory.decodeResource(resources, R.drawable.sunset1);
+        int texWidth = bitmap.getWidth();
+        int texHeight = bitmap.getHeight();
+
+        int drawWidth = CanvasCompareActivityTest.TEST_WIDTH;
+        int drawHeight = CanvasCompareActivityTest.TEST_HEIGHT;
+
+        repeatShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT,
+                Shader.TileMode.REPEAT);
+
+        translatedShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT,
+                Shader.TileMode.REPEAT);
+        Matrix matrix = new Matrix();
+        matrix.setTranslate(texWidth / 2.0f, texHeight / 2.0f);
+        matrix.postRotate(45, 0, 0);
+        translatedShader.setLocalMatrix(matrix);
+
+        scaledShader = new BitmapShader(bitmap, Shader.TileMode.MIRROR,
+                Shader.TileMode.MIRROR);
+        matrix = new Matrix();
+        matrix.setScale(0.5f, 0.5f);
+        scaledShader.setLocalMatrix(matrix);
+
+        horGradient = new LinearGradient(0.0f, 0.0f, 1.0f, 0.0f,
+                Color.RED, Color.GREEN, Shader.TileMode.CLAMP);
+        matrix = new Matrix();
+        matrix.setScale(drawHeight, 1.0f);
+        matrix.postRotate(-90.0f);
+        matrix.postTranslate(0.0f, drawHeight);
+        horGradient.setLocalMatrix(matrix);
+
+        diagGradient = new LinearGradient(0.0f, 0.0f, drawWidth / 2.0f, drawHeight / 2.0f,
+                Color.BLUE, Color.RED, Shader.TileMode.CLAMP);
+
+        vertGradient = new LinearGradient(0.0f, 0.0f, 0.0f, drawHeight / 2.0f,
+                Color.YELLOW, Color.MAGENTA, Shader.TileMode.MIRROR);
+
+        sweepGradient = new SweepGradient(drawWidth / 2.0f, drawHeight / 2.0f,
+                Color.YELLOW, Color.MAGENTA);
+
+        composeShader = new ComposeShader(repeatShader, horGradient,
+                PorterDuff.Mode.MULTIPLY);
+
+        final float width = bitmap.getWidth() / 8.0f;
+        final float height = bitmap.getHeight() / 8.0f;
+
+        bitmapVertices = new float[]{
+                0.0f, 0.0f, width, 0.0f, width * 2, 0.0f, width * 3, 0.0f,
+                0.0f, height, width, height, width * 2, height, width * 4, height,
+                0.0f, height * 2, width, height * 2, width * 2, height * 2, width * 3, height * 2,
+                0.0f, height * 4, width, height * 4, width * 2, height * 4, width * 4, height * 4,
+        };
+
+        bitmapColors = new int[]{
+                0xffff0000, 0xff00ff00, 0xff0000ff, 0xffff0000,
+                0xff0000ff, 0xffff0000, 0xff00ff00, 0xff00ff00,
+                0xff00ff00, 0xff0000ff, 0xffff0000, 0xff00ff00,
+                0x00ff0000, 0x0000ff00, 0x000000ff, 0x00ff0000,
+        };
+
+        // Use a repeating gradient with many colors to test the non simple case.
+        radGradient = new RadialGradient(drawWidth / 4.0f, drawHeight / 4.0f, 4.0f,
+                bitmapColors, null, Shader.TileMode.REPEAT);
+
+        nestedComposeShader = new ComposeShader(radGradient, composeShader,
+                PorterDuff.Mode.MULTIPLY);
+
+        doubleGradientComposeShader = new ComposeShader(radGradient, vertGradient,
+                PorterDuff.Mode.MULTIPLY);
+    }
+
+    public static ResourceModifier instance() {
+        return sInstance;
+    }
+
+    public static void init(Resources resources) {
+        sInstance = new ResourceModifier(resources);
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/SweepTests.java b/tests/tests/uirendering/src/android/uirendering/cts/SweepTests.java
new file mode 100644
index 0000000..270afe0
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/SweepTests.java
@@ -0,0 +1,174 @@
+/*
+* Copyright (C) 2014 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE2.0
+*
+* Unless required by applicable law or agreed to in riting, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package android.uirendering.cts;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.RectF;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.uirendering.cts.differencecalculators.DifferenceCalculatorContainer;
+import android.uirendering.cts.differencecalculators.MSSIMCalculator;
+import android.uirendering.cts.differencecalculators.SamplePointsCalculator;
+
+/**
+ * Test cases of all combination of resource modifications.
+ */
+public class SweepTests extends CanvasCompareActivityTest {
+    public static final int BG_COLOR = 0xFFFFFFFF;
+    public static final int DST_COLOR = 0xFFFFCC44;
+    public static final int SRC_COLOR = 0xFF66AAFF;
+    public static final int MULTIPLY_COLOR = 0xFF668844;
+    public static final int SCREEN_COLOR = 0xFFFFEEFF;
+
+    /**
+     * There are 4 locations we care about in XFermode testing.
+     *
+     * 1) Both empty
+     * 2) Only src, dst empty
+     * 3) Both src + dst
+     * 4) Only dst, src empty
+     */
+    private final int[][] XFERMODE_COLOR_ARRAYS = new int[][] {
+            {BG_COLOR, BG_COLOR, SRC_COLOR, SRC_COLOR},
+            {BG_COLOR, DST_COLOR, DST_COLOR, BG_COLOR},
+            {BG_COLOR, DST_COLOR, SRC_COLOR, SRC_COLOR},
+            {BG_COLOR, DST_COLOR, DST_COLOR, SRC_COLOR},
+            {BG_COLOR, BG_COLOR, SRC_COLOR, BG_COLOR},
+            {BG_COLOR, BG_COLOR, DST_COLOR, BG_COLOR},
+            {BG_COLOR, BG_COLOR, BG_COLOR, SRC_COLOR},
+            {BG_COLOR, DST_COLOR, BG_COLOR, BG_COLOR},
+            {BG_COLOR, DST_COLOR, SRC_COLOR, BG_COLOR},
+            {BG_COLOR, BG_COLOR, DST_COLOR, SRC_COLOR},
+            {BG_COLOR, DST_COLOR, BG_COLOR, SRC_COLOR},
+            {BG_COLOR, BG_COLOR, MULTIPLY_COLOR, BG_COLOR},
+            {BG_COLOR, DST_COLOR, SCREEN_COLOR, SRC_COLOR}
+    };
+
+    // These points are in pairs, the first being the lower left corner, the second is only in the
+    // Destination bitmap, the third is the intersection of the two bitmaps, and the fourth is in
+    // the Source bitmap.
+    private final static Point[] XFERMODE_TEST_POINTS = new Point[] {
+            new Point(1, 160), new Point(50, 50), new Point(70, 70), new Point(140, 140)
+    };
+
+    private final static DisplayModifier XFERMODE_MODIFIER = new DisplayModifier() {
+        private final static int mWidth = 180;
+        private final static int mHeight = 180;
+        private final RectF mSrcRect = new RectF(60, 60, 160, 160);
+        private final RectF mDstRect = new RectF(20, 20, 120, 120);
+        private final Bitmap mSrcBitmap = createSrc();
+        private final Bitmap mDstBitmap = createDst();
+
+        @Override
+        public void modifyDrawing(Paint paint, Canvas canvas) {
+            // Draw the background
+            canvas.drawColor(Color.WHITE);
+
+            int sc = canvas.saveLayer(0, 0, mWidth, mHeight, null);
+            canvas.drawBitmap(mDstBitmap, 0, 0, null);
+            canvas.drawBitmap(mSrcBitmap, 0, 0, paint);
+            canvas.restoreToCount(sc);
+        }
+
+        private Bitmap createSrc() {
+            Bitmap srcB = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
+            Canvas srcCanvas = new Canvas(srcB);
+            Paint srcPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+            srcPaint.setColor(SRC_COLOR);
+            srcCanvas.drawRect(mSrcRect, srcPaint);
+            return srcB;
+        }
+
+        private Bitmap createDst() {
+            Bitmap dstB = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
+            Canvas dstCanvas = new Canvas(dstB);
+            Paint dstPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+            dstPaint.setColor(DST_COLOR);
+            dstCanvas.drawOval(mDstRect, dstPaint);
+            return dstB;
+        }
+    };
+
+    /**
+     * In this case, a lower number would mean it is easier to pass the test. In terms of MSSIM,
+     * a 1 would indicate that the images are exactly the same, where as 0.1 is vastly different.
+     */
+    private final float HIGH_THRESHOLD = 0.1f;
+
+    public static final DisplayModifier mCircleDrawModifier = new DisplayModifier() {
+        @Override
+        public void modifyDrawing(Paint paint, Canvas canvas) {
+            canvas.drawCircle(CanvasCompareActivityTest.TEST_WIDTH / 2,
+                    CanvasCompareActivityTest.TEST_HEIGHT / 2,
+                    CanvasCompareActivityTest.TEST_HEIGHT / 2, paint);
+        }
+    };
+
+    @SmallTest
+    public void testBasicDraws() {
+        DifferenceCalculatorContainer container = new DifferenceCalculatorContainer();
+        container.addCalculator(new MSSIMCalculator(HIGH_THRESHOLD));
+        sweepModifiersForMask(DisplayModifier.Accessor.SHAPES_MASK, null, container);
+    }
+
+    @SmallTest
+    public void testShaderDraws() {
+        DifferenceCalculatorContainer container = new DifferenceCalculatorContainer();
+        container.addCalculator(new MSSIMCalculator(HIGH_THRESHOLD));
+        sweepModifiersForMask(DisplayModifier.Accessor.SHADER_MASK, mCircleDrawModifier, container);
+    }
+
+    @SmallTest
+    public void testXfermodes() {
+        DifferenceCalculatorContainer container = new DifferenceCalculatorContainer();
+        for (int i = 0 ; i < XFERMODE_COLOR_ARRAYS.length ; i++) {
+            container.addCalculator(new SamplePointsCalculator(XFERMODE_TEST_POINTS,
+                    XFERMODE_COLOR_ARRAYS[i]));
+        }
+        sweepModifiersForMask(DisplayModifier.Accessor.XFERMODE_MASK, XFERMODE_MODIFIER, container);
+    }
+
+    protected void sweepModifiersForMask(int mask, final DisplayModifier drawOp,
+            DifferenceCalculatorContainer container) {
+        if ((mask & DisplayModifier.Accessor.ALL_OPTIONS_MASK) == 0) {
+            throw new IllegalArgumentException("Attempt to test with a mask that is invalid");
+        }
+        // Get the accessor of all the different modifications possible
+        final DisplayModifier.Accessor modifierAccessor = new DisplayModifier.Accessor(mask);
+        // Initialize the resources that we will need to access
+        ResourceModifier.init(getActivity().getResources());
+        // For each modification combination, we will get the CanvasClient associated with it and
+        // from there execute a normal canvas test with that.
+        CanvasClient canvasClient = new CanvasClient() {
+            @Override
+            public void draw(Canvas canvas, int width, int height) {
+                Paint paint = new Paint();
+                modifierAccessor.modifyDrawing(canvas, paint);
+                if (drawOp != null) {
+                    drawOp.modifyDrawing(paint, canvas);
+                }
+            }
+        };
+        int index = 0;
+        do {
+            executeCanvasTest(canvasClient, container.getCalculator(index));
+            index++;
+        } while (modifierAccessor.step());
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/DifferenceCalculator.java b/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/DifferenceCalculator.java
index f483597..ce42954 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/DifferenceCalculator.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/DifferenceCalculator.java
@@ -22,7 +22,7 @@
 /**
  * This abstract class can be used by the tester to implement their own comparison methods
  */
-public interface DifferenceCalculator{
+public abstract class DifferenceCalculator{
     /**
      * Compares the two bitmaps given using Java.
      * @param offset where in the bitmaps to start
@@ -31,14 +31,21 @@
      * @param height the height of the subsection being tested
      * @return
      */
-    public boolean verifySame(int[] ideal, int[] given, int offset, int stride, int width,
+    public abstract boolean verifySame(int[] ideal, int[] given, int offset, int stride, int width,
             int height);
 
     /**
      * Compare the two bitmaps using RenderScript code.
      * @return if the method deems the two images are similar enough then the result is true
      */
-    public boolean verifySameRS(Resources resources, Allocation ideal,
+    public abstract boolean verifySameRS(Resources resources, Allocation ideal,
             Allocation given, int offset, int stride, int width, int height,
             RenderScript renderScript);
+
+    /**
+     * This calculates the position in an array that would represent a bitmap given the parameters.
+     */
+    protected static int indexFromXAndY(int x, int y, int stride, int offset) {
+        return x + (y * stride) + offset;
+    }
 }
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/ExactComparer.java b/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/ExactComparer.java
index bb1e539..1eab5a5 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/ExactComparer.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/ExactComparer.java
@@ -28,8 +28,7 @@
 /**
  * This class does an exact comparison of the pixels in a bitmap.
  */
-public class ExactComparer implements DifferenceCalculator {
-    private final int REGION_SIZE = 8;
+public class ExactComparer extends DifferenceCalculator {
     private ScriptC_ExactComparer mScript;
 
     /**
@@ -39,9 +38,9 @@
             int height) {
         int count = 0;
 
-        for (int i = 0 ; i < height ; i++) {
-            for (int j = 0 ; j < width ; j++) {
-                int index = offset + (i * stride) + j;
+        for (int y = 0 ; y < height ; y++) {
+            for (int x = 0 ; x < width ; x++) {
+                int index = indexFromXAndY(x, y, stride, offset);
                 if (ideal[index] != given[index]) {
                     if (!CanvasCompareActivityTest.DEBUG) {
                         return false;
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/MSSIMCalculator.java b/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/MSSIMCalculator.java
index b7663dc..303011c 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/MSSIMCalculator.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/MSSIMCalculator.java
@@ -17,10 +17,8 @@
 
 import android.content.res.Resources;
 import android.graphics.Color;
-import android.uirendering.cts.CanvasCompareActivityTest;
 import android.renderscript.Allocation;
 import android.renderscript.RenderScript;
-import android.util.Log;
 
 /**
  * Image comparison using Structural Similarity Index, developed by Wang, Bovik, Sheikh, and
@@ -28,51 +26,53 @@
  *
  * https://ece.uwaterloo.ca/~z70wang/publications/ssim.pdf
  */
-public class MSSIMCalculator implements DifferenceCalculator {
+public class MSSIMCalculator extends DifferenceCalculator {
     // These values were taken from the publication
     public static final double CONSTANT_L = 254;
     public static final double CONSTANT_K1 = 0.01;
     public static final double CONSTANT_K2 = 0.03;
     public static final double CONSTANT_C1 = Math.pow(CONSTANT_L * CONSTANT_K1, 2);
     public static final double CONSTANT_C2 = Math.pow(CONSTANT_L * CONSTANT_K2, 2);
-    public static final float MIN_SSIM = 0.7f;
     public static final int WINDOW_SIZE = 10;
 
+    private float mThreshold;
+
+    public MSSIMCalculator(float threshold) {
+        mThreshold = threshold;
+    }
+
     @Override
     public boolean verifySame(int[] ideal, int[] given, int offset, int stride, int width,
             int height) {
-        float SSIMTotal = 0;
-        int interestingRegions = 0;
+        double SSIMTotal = 0;
+        int windows = 0;
 
-        for (int i = 0 ; i < height ; i += WINDOW_SIZE) {
-            for (int j = 0 ; j < width ; j += WINDOW_SIZE) {
-                int start = j + (i * stride) + offset;
-                if (inspectRegions(ideal, start, stride) ||
-                        inspectRegions(given, start, stride)) {
-                    interestingRegions++;
-                    float meanX = meanIntensityOfWindow(ideal, start, stride);
-                    float meanY = meanIntensityOfWindow(given, start, stride);
-                    float stdX = standardDeviationIntensityOfWindow(ideal, meanX, start, offset);
-                    float stdY = standardDeviationIntensityOfWindow(given, meanY, start, offset);
-                    float stdBoth = standardDeviationBothWindows(ideal, given, meanX, meanY, start,
-                            stride);
-                    SSIMTotal += SSIM(meanX, meanY, stdX, stdY, stdBoth);
+        for (int currentWindowY = 0 ; currentWindowY < height ; currentWindowY += WINDOW_SIZE) {
+            for (int currentWindowX = 0 ; currentWindowX < width ; currentWindowX += WINDOW_SIZE) {
+                int start = indexFromXAndY(currentWindowX, currentWindowY, stride, offset);
+                if (isWindowWhite(ideal, start, stride) && isWindowWhite(given, start, stride)) {
+                    continue;
                 }
+                windows++;
+                double meanX = meanIntensityOfWindow(ideal, start, stride);
+                double meanY = meanIntensityOfWindow(given, start, stride);
+                double stdX = standardDeviationIntensityOfWindow(ideal, meanX, start, offset);
+                double stdY = standardDeviationIntensityOfWindow(given, meanY, start, offset);
+                double stdBoth = standardDeviationBothWindows(ideal, given, meanX, meanY, start,
+                        stride);
+                SSIMTotal += SSIM(meanX, meanY, stdX, stdY, stdBoth);
             }
         }
-        if (interestingRegions == 0) {
+
+        if (windows == 0) { //if they were both white screens then we are good
             return true;
         }
 
-        SSIMTotal /= interestingRegions;
-        if (CanvasCompareActivityTest.DEBUG) {
-            Log.d(CanvasCompareActivityTest.TAG_NAME, "SSIM : " + SSIMTotal);
-        }
+        SSIMTotal /= windows;
 
-        return (SSIMTotal > MIN_SSIM);
+        return (SSIMTotal > mThreshold);
     }
 
-
     @Override
     public boolean verifySameRS(Resources resources, Allocation ideal,
             Allocation given, int offset, int stride, int width, int height,
@@ -80,77 +80,67 @@
         return false;
     }
 
-    /**
-     * Checks to see if the entire region is white, and if so it returns true
-     */
-    private boolean inspectRegions(int[] colors, int x, int stride) {
-        for (int i = 0 ; i < WINDOW_SIZE ; i++) {
-            for (int j = 0 ; j < WINDOW_SIZE ; j++) {
-                if (colors[x + j + (i * stride)] != Color.WHITE) {
-                    return true;
+    private boolean isWindowWhite(int[] colors, int start, int stride) {
+        for (int y = 0 ; y < WINDOW_SIZE ; y++) {
+            for (int x = 0 ; x < WINDOW_SIZE ; x++) {
+                if (colors[indexFromXAndY(x, y, stride, start)] != Color.WHITE) {
+                    return false;
                 }
             }
         }
-        return false;
+        return true;
     }
 
-    /**
-     * Finds the SSIM for the given parameters
-     */
-    private float SSIM(float muX, float muY, float sigX, float sigY, float sigXY) {
-        float SSIM = (float) ((2 * muX * muY + CONSTANT_C1) * (2 * sigXY + CONSTANT_C2));
-        SSIM /= (muX * muX + muY * muY + CONSTANT_C1);
-        SSIM /= (sigX * sigX + sigY * sigY + CONSTANT_C2);
+    private double SSIM(double muX, double muY, double sigX, double sigY, double sigXY) {
+        double SSIM = ((2 * muX * muY + CONSTANT_C1) * (2 * sigXY + CONSTANT_C2));
+        double denom = (muX * muX + muY * muY + CONSTANT_C1)
+                * (sigX * sigX + sigY * sigY + CONSTANT_C2);
+        SSIM /= denom;
+        //TODO I need to find a better way to deal with this
+        if (Double.isNaN(SSIM)) {
+            return 0;
+        }
         return SSIM;
     }
 
-    /**
-     * Finds the standard deviation amongst the two windows
-     */
-    private float standardDeviationBothWindows(int[] pixel1, int[] pixel2, float mean1, float mean2,
+    private double standardDeviationBothWindows(int[] pixel1, int[] pixel2, double mean1, double mean2,
             int start, int stride) {
-        float val = 0;
+        double val = 0;
 
-        for (int i = 0 ; i < WINDOW_SIZE ; i++) {
-            for (int j = 0 ; j < WINDOW_SIZE ; j++) {
-                int index = start + (i * stride) + j;
+        for (int y = 0 ; y < WINDOW_SIZE ; y++) {
+            for (int x = 0 ; x < WINDOW_SIZE ; x++) {
+                int index = indexFromXAndY(x, y, stride, start);
                 val += ((getIntensity(pixel1[index]) - mean1) * (getIntensity(pixel2[index]) - mean2));
             }
         }
 
         val /= (WINDOW_SIZE * WINDOW_SIZE) - 1;
-        val = (float) Math.pow(val, .5);
+        val = Math.pow(val, .5);
         return val;
     }
 
-    /**
-     * Finds the standard deviation of the given window
-     */
-    private float standardDeviationIntensityOfWindow(int[] pixels, float meanIntensity, int start,
+    private double standardDeviationIntensityOfWindow(int[] pixels, double meanIntensity, int start,
             int stride) {
-        float stdDev = 0f;
+        double stdDev = 0;
 
-        for (int i = 0 ; i < WINDOW_SIZE ; i++) {
-            for (int j = 0 ; j < WINDOW_SIZE ; j++) {
-                int index = start + (i * stride) + j;
+        for (int y = 0 ; y < WINDOW_SIZE ; y++) {
+            for (int x = 0 ; x < WINDOW_SIZE ; x++) {
+                int index = indexFromXAndY(x, y, stride, start);
                 stdDev += Math.pow(getIntensity(pixels[index]) - meanIntensity, 2);
             }
         }
 
         stdDev /= (WINDOW_SIZE * WINDOW_SIZE) - 1;
-        stdDev = (float) Math.pow(stdDev, .5);
+        stdDev = Math.pow(stdDev, .5);
         return stdDev;
     }
 
-    /**
-     * Finds the mean of the given window
-     */
-    private float meanIntensityOfWindow(int[] pixels, int start, int stride) {
-        float avgL = 0f;
+    private double meanIntensityOfWindow(int[] pixels, int start, int stride) {
+        double avgL = 0f;
 
-        for (int i = 0 ; i < WINDOW_SIZE ; i++) {
-            for (int j = 0 ; j < WINDOW_SIZE ; j++) {
-                int index = start + (i * stride) + j;
+        for (int y = 0 ; y < WINDOW_SIZE ; y++) {
+            for (int x = 0 ; x < WINDOW_SIZE ; x++) {
+                int index = indexFromXAndY(x, y, stride, start);
                 avgL += getIntensity(pixels[index]);
             }
         }
@@ -160,13 +150,16 @@
     /**
      * Gets the intensity of a given pixel in RGB using luminosity formula
      *
-     * l = 0.21R + 0.72G + 0.07B
+     * l = 0.21R' + 0.72G' + 0.07B'
+     *
+     * The prime symbols dictate a gamma correction of 2.2.
      */
-    private float getIntensity(int pixel) {
-        float l = 0;
-        l += (0.21f * Color.red(pixel));
-        l += (0.72f * Color.green(pixel));
-        l += (0.07f * Color.blue(pixel));
+    private double getIntensity(int pixel) {
+        final double gamma = 2.2;
+        double l = 0;
+        l += (0.21f * Math.pow(Color.red(pixel), gamma));
+        l += (0.72f * Math.pow(Color.green(pixel), gamma));
+        l += (0.07f * Math.pow(Color.blue(pixel), gamma));
         return l;
     }
 }
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/MeanSquaredCalculator.java b/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/MeanSquaredCalculator.java
index 64e3c98..243dc66 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/MeanSquaredCalculator.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/MeanSquaredCalculator.java
@@ -29,17 +29,23 @@
 /**
  * Finds the MSE using two images.
  */
-public class MeanSquaredCalculator implements DifferenceCalculator{
-    private final double MAX_ERROR_PER_PIXEL = .5;
+public class MeanSquaredCalculator extends DifferenceCalculator {
     private ScriptC_MeanSquaredCalculator mScript;
+    private float mErrorPerPixel;
+
+    /**
+     * @param errorPerPixel threshold for which the test will pass/fail. This is the mean-squared
+     *                      error averaged across all of those before comparing.
+     */
+    public MeanSquaredCalculator(float errorPerPixel) {
+        mErrorPerPixel = errorPerPixel;
+    }
 
     @Override
     public boolean verifySame(int[] ideal, int[] given, int offset, int stride, int width,
             int height) {
         float totalError = getMSE(ideal, given, offset, stride, width, height);
-
-        Log.d("Testing", "TOTAL MSE : " + totalError);
-        return (totalError < (MAX_ERROR_PER_PIXEL * ideal.length));
+        return (totalError < (mErrorPerPixel * ideal.length));
     }
 
     @Override
@@ -88,7 +94,7 @@
 
         error /= width * height;
 
-        return (error < MAX_ERROR_PER_PIXEL * width * height);
+        return (error < mErrorPerPixel * width * height);
     }
 
     /**
@@ -98,9 +104,9 @@
             int height) {
         float totalError = 0;
 
-        for (int i = 0 ; i < height ; i++) {
-            for (int j = 0 ; j < width ; j++) {
-                int index = offset + (i * stride) + j;
+        for (int y = 0 ; y < height ; y++) {
+            for (int x = 0 ; x < width ; x++) {
+                int index = indexFromXAndY(x, y, stride, offset);
                 float intensity1 = getIntensity(ideal[index]);
                 float intensity2 = getIntensity(given[index]);
                 totalError += (intensity1 - intensity2) * (intensity1 - intensity2);
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/PSNRCalculator.java b/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/PSNRCalculator.java
index d6b1a9f..b194078 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/PSNRCalculator.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/PSNRCalculator.java
@@ -17,27 +17,34 @@
 
 import android.content.res.Resources;
 import android.graphics.Color;
-import android.uirendering.cts.CanvasCompareActivityTest;
 import android.renderscript.Allocation;
 import android.renderscript.RenderScript;
-import android.util.Log;
 
 /**
  * Uses the Peak Signal-to-Noise Ratio approach to determine if two images are considered the same.
  */
-public class PSNRCalculator implements DifferenceCalculator{
+public class PSNRCalculator extends DifferenceCalculator {
     private final float MAX = 255;
-    private final float MIN_PSNR = 20;
     private final int REGION_SIZE = 10;
 
+    private float mThreshold;
+
+    /**
+     * @param threshold the PSNR necessary to pass the test, if the calculated PSNR is below this
+     *                  value, then the test will fail.
+     */
+    public PSNRCalculator(float threshold) {
+        mThreshold = threshold;
+    }
+
     @Override
     public boolean verifySame(int[] ideal, int[] given, int offset, int stride, int width,
             int height) {
         float MSE = 0f;
         int interestingRegions = 0;
-        for (int i = 0 ; i < height ; i += REGION_SIZE) {
-            for (int j = 0 ; j < width ; j += REGION_SIZE) {
-                int index = offset + (i * stride) + j;
+        for (int y = 0 ; y < height ; y += REGION_SIZE) {
+            for (int x = 0 ; x < width ; x += REGION_SIZE) {
+                int index = indexFromXAndY(x, y, stride, offset);
                 if (inspectRegion(ideal, index)) {
                     interestingRegions++;
                 }
@@ -48,9 +55,9 @@
             return true;
         }
 
-        for (int i = 0 ; i < height ; i += REGION_SIZE) {
-            for (int j = 0 ; j < width ; j += REGION_SIZE) {
-                int index = offset + (i * stride) + j;
+        for (int y = 0 ; y < height ; y += REGION_SIZE) {
+            for (int x = 0 ; x < width ; x += REGION_SIZE) {
+                int index = indexFromXAndY(x, y, stride, offset);
                 if (ideal[index] == given[index]) {
                     continue;
                 }
@@ -68,9 +75,7 @@
         fraction = (float) Math.log(fraction);
         fraction *= 10;
 
-        Log.d(CanvasCompareActivityTest.TAG_NAME, "PSNR : " + fraction);
-
-        return (fraction > MIN_PSNR);
+        return (fraction > mThreshold);
     }
 
     private boolean inspectRegion(int[] ideal, int index) {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/DifferentPixelCalculator.java b/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/PassCalculator.java
similarity index 62%
rename from tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/DifferentPixelCalculator.java
rename to tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/PassCalculator.java
index 08d5301..5870152 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/DifferentPixelCalculator.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/PassCalculator.java
@@ -20,33 +20,18 @@
 import android.renderscript.RenderScript;
 
 /**
- * This calculator counts the number of pixels that are different amongs the two images. If the
- * number of pixels is under a certain percentile then it will pass.
+ * This class is purely for debug purposes. It will automatically pass any tests.
  */
-public class DifferentPixelCalculator implements DifferenceCalculator{
-    private final float MAX_PERCENT = .1f;
-
+public class PassCalculator extends DifferenceCalculator {
     @Override
     public boolean verifySame(int[] ideal, int[] given, int offset, int stride, int width,
             int height) {
-        int count = 0;
-
-        for (int i = 0 ; i < height ; i++) {
-            for (int j = 0 ; j < width ; j++) {
-                int index = offset + (i * stride) + j;
-                if (ideal[index] != given[index]) {
-                    count++;
-                }
-            }
-        }
-
-        float percent = ((count) * 1.0f / (width * height));
-        return (percent < MAX_PERCENT);
+        return true;
     }
 
     @Override
     public boolean verifySameRS(Resources resources, Allocation ideal, Allocation given, int offset,
             int stride, int width, int height, RenderScript renderScript) {
-        return false;
+        return true;
     }
 }
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/SamplePointsCalculator.java b/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/SamplePointsCalculator.java
new file mode 100644
index 0000000..38f0633
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/SamplePointsCalculator.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.uirendering.cts.differencecalculators;
+
+import android.content.res.Resources;
+import android.graphics.Point;
+import android.renderscript.Allocation;
+import android.renderscript.RenderScript;
+import android.util.Log;
+
+/**
+ * This class will test specific points, and ensure that they match up perfectly with the input colors
+ */
+public class SamplePointsCalculator extends DifferenceCalculator {
+    private Point[] mTestPoints;
+    private int[] mExpectedColors;
+
+    public SamplePointsCalculator(Point[] testPoints, int[] expectedColors) {
+        mTestPoints = testPoints;
+        mExpectedColors = expectedColors;
+    }
+
+    @Override
+    public boolean verifySame(int[] ideal, int[] given, int offset, int stride, int width,
+            int height) {
+        for (int i = 0 ; i < mTestPoints.length; i++) {
+            int xPos = mTestPoints[i].x;
+            int yPos = mTestPoints[i].y;
+            int index = indexFromXAndY(xPos, yPos, stride, offset);
+            if (ideal[index] != mExpectedColors[i] || given[index] != mExpectedColors[i]) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public boolean verifySameRS(Resources resources, Allocation ideal, Allocation given, int offset,
+            int stride, int width, int height, RenderScript renderScript) {
+        return false;
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/ThresholdDifferenceCalculator.java b/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/ThresholdDifferenceCalculator.java
index e18a61b..170e626 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/ThresholdDifferenceCalculator.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/ThresholdDifferenceCalculator.java
@@ -31,19 +31,29 @@
 /**
  * Compares two images to see if each pixel is the same, within a certain threshold value
  */
-public class ThresholdDifferenceCalculator implements DifferenceCalculator{
-    public static final int THRESHOLD = 45;
+public class ThresholdDifferenceCalculator extends DifferenceCalculator {
     private ScriptC_ThresholdDifferenceCalculator mScript;
+    private int mThreshold;
+
+    /**
+     * @param threshold Each pixel is compared against each other, in each of the individual
+     *                  channels. If the sum of the errors amongst the channels is greater than some
+     *                  threshold, then this test will fail.
+     */
+    public ThresholdDifferenceCalculator(int threshold) {
+        mThreshold = threshold;
+    }
 
     @Override
-    public boolean verifySame(int[] ideal, int[] given, int offset, int stride, int width, int height) {
-        for (int i = 0 ; i < height ; i++) {
-            for (int j = 0 ; j < width ; j++) {
-                int index = offset + (i * stride) + j;
+    public boolean verifySame(int[] ideal, int[] given, int offset, int stride, int width,
+            int height) {
+        for (int y = 0 ; y < height ; y++) {
+            for (int x = 0 ; x < width ; x++) {
+                int index = indexFromXAndY(x, y, stride, offset);
                 int error = Math.abs(Color.red(ideal[index]) - Color.red(given[index]));
                 error += Math.abs(Color.blue(ideal[index]) - Color.blue(given[index]));
                 error += Math.abs(Color.green(ideal[index]) - Color.green(given[index]));
-                if (error > THRESHOLD) {
+                if (error > mThreshold) {
                     return false;
                 }
             }
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/WeightedPixelDifference.java b/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/WeightedPixelDifference.java
index 9ad3f66..932481c 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/WeightedPixelDifference.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/WeightedPixelDifference.java
@@ -19,6 +19,7 @@
 import android.graphics.Color;
 import android.renderscript.Allocation;
 import android.renderscript.RenderScript;
+import android.uirendering.cts.CanvasCompareActivityTest;
 import android.util.Log;
 
 /**
@@ -26,20 +27,25 @@
  * account the number of pixels that are non-white. Note only use this if the content background is
  * white.
  */
-public class WeightedPixelDifference implements DifferenceCalculator {
-    private static final float THRESHOLD = 0.006f;
+public class WeightedPixelDifference extends DifferenceCalculator {
     private static final int NUM_OF_COLUMNS = 10;
     private static final float TOTAL_ERROR_DIVISOR = 1024.0f;
 
+    private float mThreshold;
+
+    public WeightedPixelDifference(float threshold) {
+        mThreshold = threshold;
+    }
+
     /**
      * Calculates if pixels in a specific line are the same color
      * @return true if the pixels are the same color
      */
-    private static boolean inspectRegions(int[] ideal, int x, int stride, int regionSize) {
-        int regionColor = ideal[x];
-        for (int i = 0 ; i < regionSize ; i++) {
-            for (int j = 0 ; j < regionSize ; j++) {
-                int index = x + (i * stride) + j;
+    private static boolean inspectRegions(int[] ideal, int start, int stride, int regionSize) {
+        int regionColor = ideal[start];
+        for (int y = 0 ; y < regionSize ; y++) {
+            for (int x = 0 ; x < regionSize ; x++) {
+                int index = indexFromXAndY(x, y, stride, start);
                 if (ideal[index] != regionColor) {
                     return true;
                 }
@@ -70,9 +76,9 @@
         int interestingRegions = 0;
         int regionSize = width / NUM_OF_COLUMNS;
 
-        for (int i = 0 ; i < height ; i += regionSize) {
-            for (int j = 0 ; j < width ; j += regionSize) {
-                int index = offset + (i * stride) + j;
+        for (int y = 0 ; y < height ; y += regionSize) {
+            for (int x = 0 ; x < width ; x += regionSize) {
+                int index = indexFromXAndY(x, y,stride, offset);
                 if (inspectRegions(ideal, index, stride, regionSize)) {
                     interestingRegions++;
                 }
@@ -83,9 +89,9 @@
 
         float totalError = 0;
 
-        for (int i = 0 ; i < height ; i++) {
-            for (int j = 0 ; j < width ; j++) {
-                int index = offset + (i * stride) + j;
+        for (int y = 0 ; y < height ; y++) {
+            for (int x = 0 ; x < width ; x++) {
+                int index = indexFromXAndY(x, y, stride, offset);
                 int idealColor = ideal[index];
                 int givenColor = given[index];
                 if (idealColor == givenColor) {
@@ -98,9 +104,11 @@
         totalError /= TOTAL_ERROR_DIVISOR;
         totalError /= interestingPixels;
 
-        Log.d("CtsGraphicsHardware", "TOTAL ERROR : " + totalError);
+        if (CanvasCompareActivityTest.DEBUG) {
+            Log.d("CtsGraphicsHardware", "TOTAL ERROR : " + totalError);
+        }
 
-        return totalError < THRESHOLD;
+        return totalError < mThreshold;
     }
 
     @Override