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