am 2fa85974: Java side of OpenGL performance benchmark
# Via Android (Google) Code Review
* commit '2fa859749e605251775dc358ff4045a46fb5db2b':
Java side of OpenGL performance benchmark
diff --git a/suite/pts/PtsBenchmarkingList.mk b/suite/pts/PtsBenchmarkingList.mk
index c106e1f..7c0ad47 100644
--- a/suite/pts/PtsBenchmarkingList.mk
+++ b/suite/pts/PtsBenchmarkingList.mk
@@ -23,7 +23,8 @@
PtsDeviceDram \
PtsDeviceSimpleCpu \
PtsDeviceBrowserBench \
- PtsDeviceVideoPerf
+ PtsDeviceVideoPerf \
+ PtsDeviceOpenGl
PTS_SUPPORT_PACKAGES := \
PtsDeviceTaskswitchingAppA \
diff --git a/suite/pts/deviceTests/opengl/Android.mk b/suite/pts/deviceTests/opengl/Android.mk
new file mode 100644
index 0000000..377562c
--- /dev/null
+++ b/suite/pts/deviceTests/opengl/Android.mk
@@ -0,0 +1,35 @@
+# Copyright (C) 2012 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_STATIC_JAVA_LIBRARIES := ptsutil ctsutil ctstestrunner
+
+LOCAL_JNI_SHARED_LIBRARIES := libptsopengl_jni
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := PtsDeviceOpenGl
+
+LOCAL_SDK_VERSION := 16
+
+include $(BUILD_CTS_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/suite/pts/deviceTests/opengl/AndroidManifest.xml b/suite/pts/deviceTests/opengl/AndroidManifest.xml
new file mode 100644
index 0000000..a91766f
--- /dev/null
+++ b/suite/pts/deviceTests/opengl/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.pts.opengl"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk
+ android:minSdkVersion="16" />
+
+ <uses-feature
+ android:glEsVersion="0x00020000"
+ android:required="true" />
+
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />\
+ <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+
+ <application android:allowBackup="false" >
+ <uses-library android:name="android.test.runner" />
+
+ <activity
+ android:name="com.android.pts.opengl.primitive.GLActivity"
+ android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+ <instrumentation
+ android:name="android.test.InstrumentationCtsTestRunner"
+ android:label="OpenGL ES 2.0 Benchmark"
+ android:targetPackage="com.android.pts.opengl" />
+
+</manifest>
\ No newline at end of file
diff --git a/suite/pts/deviceTests/opengl/jni/Android.mk b/suite/pts/deviceTests/opengl/jni/Android.mk
new file mode 100644
index 0000000..b872b02
--- /dev/null
+++ b/suite/pts/deviceTests/opengl/jni/Android.mk
@@ -0,0 +1,31 @@
+# Copyright (C) 2012 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.
+#
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libptsopengl_jni
+
+LOCAL_MODULE_TAGS := optional
+
+# Get all cpp files but not hidden files
+LOCAL_SRC_FILES := $(patsubst ./%,%, $(shell cd $(LOCAL_PATH); \
+ find . -name "*.cpp" -and -not -name ".*"))
+
+LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
+
+LOCAL_SHARED_LIBRARIES := libEGL libGLESv2 libandroid libutils
+
+include $(BUILD_SHARED_LIBRARY)
\ No newline at end of file
diff --git a/suite/pts/deviceTests/opengl/jni/GLNative.cpp b/suite/pts/deviceTests/opengl/jni/GLNative.cpp
new file mode 100644
index 0000000..48b87a5
--- /dev/null
+++ b/suite/pts/deviceTests/opengl/jni/GLNative.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+#include <jni.h>
+
+extern "C" JNIEXPORT jboolean JNICALL
+Java_com_android_pts_opengl_primitive_GLActivity_startBenchmark(
+ JNIEnv* env, jclass clazz, jint numFrames, jdoubleArray frameTimes) {
+ return true;
+}
+
+extern "C" JNIEXPORT void JNICALL
+Java_com_android_pts_opengl_primitive_GLActivity_setupFullPipelineBenchmark(
+ JNIEnv* env, jclass clazz, jobject surface, jint workload) {
+}
+
+extern "C" JNIEXPORT void JNICALL
+Java_com_android_pts_opengl_primitive_GLActivity_setupPixelOutputBenchmark(
+ JNIEnv* env, jclass clazz, jobject surface, jint workload) {
+}
+
+extern "C" JNIEXPORT void JNICALL
+Java_com_android_pts_opengl_primitive_GLActivity_setupShaderPerfBenchmark(
+ JNIEnv* env, jclass clazz, jobject surface, jint workload) {
+}
+
+extern "C" JNIEXPORT void JNICALL
+Java_com_android_pts_opengl_primitive_GLActivity_setupContextSwitchBenchmark(
+ JNIEnv* env, jclass clazz, jobject surface, jint workload) {
+}
diff --git a/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/Benchmark.java b/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/Benchmark.java
new file mode 100644
index 0000000..d61f45d
--- /dev/null
+++ b/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/Benchmark.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2013 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 com.android.pts.opengl.primitive;
+
+/**
+ * Represents the different primitive benchmarks.
+ */
+public enum Benchmark {
+ FullPipeline,
+ PixelOutput,
+ ShaderPerf,
+ ContextSwitch;
+}
diff --git a/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLActivity.java b/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLActivity.java
new file mode 100644
index 0000000..0caa576
--- /dev/null
+++ b/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLActivity.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2013 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 com.android.pts.opengl.primitive;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.cts.util.WatchDog;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.Surface;
+
+import com.android.pts.util.ResultType;
+import com.android.pts.util.ResultUnit;
+
+public class GLActivity extends Activity {
+
+ public final static String TAG = "GLActivity";
+ /**
+ * Holds the name of the benchmark to run.
+ */
+ public final static String INTENT_EXTRA_BENCHMARK_NAME = "benchmark_name";
+ /**
+ * Holds the number of milliseconds to wait before timing out.
+ */
+ public final static String INTENT_EXTRA_TIMEOUT = "timeout";
+ /**
+ * The minimum number of frames per second the device must achieve to pass.
+ */
+ public final static String INTENT_EXTRA_MIN_FPS = "min_fps";
+ /**
+ * The number of frames to render for each workload.
+ */
+ public final static String INTENT_EXTRA_NUM_FRAMES = "num_frames";
+
+ private Worker runner;
+ private volatile Exception mException;
+ private volatile Surface mSurface;
+
+ private Benchmark mBenchmark;
+ private int mTimeout;
+ private double mMinFps;
+ private int mNumFrames;
+ private volatile int mWorkload = 0;
+
+ @Override
+ public void onCreate(Bundle data) {
+ super.onCreate(data);
+ System.loadLibrary("ptsopengl_jni");
+ Intent intent = getIntent();
+ mBenchmark = Benchmark.valueOf(intent.getStringExtra(INTENT_EXTRA_BENCHMARK_NAME));
+ mTimeout = intent.getIntExtra(INTENT_EXTRA_TIMEOUT, 0);
+ mMinFps = intent.getDoubleExtra(INTENT_EXTRA_MIN_FPS, 0);
+ mNumFrames = intent.getIntExtra(INTENT_EXTRA_NUM_FRAMES, 0);
+
+ Log.i(TAG, "Benchmark: " + mBenchmark);
+ Log.i(TAG, "Time Out: " + mTimeout);
+ Log.i(TAG, "Min FPS: " + mMinFps);
+ Log.i(TAG, "Num Frames: " + mNumFrames);
+
+ SurfaceView surfaceView = new SurfaceView(this);
+ surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+ mSurface = holder.getSurface();
+ }
+
+ @Override
+ public void surfaceCreated(SurfaceHolder holder) {}
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {}
+ });
+ setContentView(surfaceView);
+ }
+
+ public int waitForCompletion() throws Exception {
+ // Creates, starts and waits for a worker to run the benchmark.
+ runner = new Worker();
+ runner.start();
+ runner.join();
+ if (mException != null) {
+ throw mException;
+ }
+ return mWorkload;
+ }
+
+ private static native void setupFullPipelineBenchmark(Surface surface, int workload);
+
+ private static native void setupPixelOutputBenchmark(Surface surface, int workload);
+
+ private static native void setupShaderPerfBenchmark(Surface surface, int workload);
+
+ private static native void setupContextSwitchBenchmark(Surface surface, int workload);
+
+ private static native boolean startBenchmark(int numFrames, double[] frameTimes);
+
+ /**
+ * This thread runs the benchmarks, freeing the UI thread.
+ */
+ private class Worker extends Thread {
+
+ private volatile boolean repeat = true;
+ private WatchDog watchDog;
+
+ @Override
+ public void run() {
+ // Creates a watchdog to ensure a iteration doesn't exceed the timeout.
+ watchDog = new WatchDog(mTimeout);
+ watchDog.start();
+ // Used to record the start and end time of the iteration.
+ double[] times = new double[2];
+ while (repeat) {
+ // The workload to use for this iteration.
+ int wl = mWorkload + 1;
+ // Setup the benchmark.
+ switch (mBenchmark) {
+ case FullPipeline:
+ setupFullPipelineBenchmark(mSurface, wl);
+ break;
+ case PixelOutput:
+ setupPixelOutputBenchmark(mSurface, wl);
+ break;
+ case ShaderPerf:
+ setupShaderPerfBenchmark(mSurface, wl);
+ break;
+ case ContextSwitch:
+ setupContextSwitchBenchmark(mSurface, wl);
+ break;
+ }
+ // Start benchmark.
+ if (!startBenchmark(mNumFrames, times)) {
+ mException = new Exception("Could not run benchmark");
+ repeat = false;
+ } else {
+ // Calculate FPS.
+ double totalTimeTaken = times[1] - times[0];
+ double meanFps = mNumFrames * 1000.0f / totalTimeTaken;
+ Log.i(TAG, "Workload: " + wl);
+ Log.i(TAG, "MeanFPS: " + meanFps);
+ if (meanFps >= mMinFps) {
+ // Iteration passed, proceed to next one.
+ mWorkload++;
+ } else {
+ // Iteration failed.
+ repeat = false;
+ }
+ }
+ // Resets the watchdog for the next iteration.
+ watchDog.reset();
+ }
+ watchDog.stop();
+ }
+
+ }
+}
diff --git a/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLBenchmark.java b/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLBenchmark.java
new file mode 100644
index 0000000..ad3159f
--- /dev/null
+++ b/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLBenchmark.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2013 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 com.android.pts.opengl.primitive;
+
+import android.content.Intent;
+
+import com.android.pts.util.PtsActivityInstrumentationTestCase2;
+import com.android.pts.util.ResultType;
+import com.android.pts.util.ResultUnit;
+
+/**
+ * Runs the Primitive OpenGL ES 2.0 Benchmarks.
+ */
+public class GLBenchmark extends PtsActivityInstrumentationTestCase2<GLActivity> {
+
+ private static final double MIN_FPS = 50;
+
+ public GLBenchmark() {
+ super(GLActivity.class);
+ }
+
+ /**
+ * Runs the full OpenGL ES 2.0 pipeline test.
+ *
+ * @throws Exception If the benchmark could not be run.
+ */
+ public void testFullPipeline() throws Exception {
+ runBenchmark(Benchmark.FullPipeline, 500, 10000);
+ }
+
+ /**
+ * Runs the pixel output test.
+ *
+ * @throws Exception If the benchmark could not be run.
+ */
+ public void testPixelOutput() throws Exception {
+ runBenchmark(Benchmark.PixelOutput, 500, 10000);
+ }
+
+ /**
+ * Runs the shader performance test.
+ *
+ * @throws Exception If the benchmark could not be run.
+ */
+ public void testShaderPerf() throws Exception {
+ // TODO(stuartscott): Not yet implemented
+ // runBenchmark(Benchmark.ShaderPerf, 500, 10000);
+ }
+
+ /**
+ * Runs the OpenGL context switch overhead test.
+ *
+ * @throws Exception If the benchmark could not be run.
+ */
+ public void testContextSwitch() throws Exception {
+ runBenchmark(Benchmark.ContextSwitch, 500, 10000);
+ }
+
+ /**
+ * Runs the specified test.
+ *
+ * @param benchmark An enum representing the benchmark to run.
+ * @param numFrames The number of frames to render.
+ * @param timeout The milliseconds to wait for an iteration of the benchmark before timing out.
+ * @throws Exception If the benchmark could not be run.
+ */
+ private void runBenchmark(Benchmark benchmark, int numFrames, int timeout) throws Exception {
+ String benchmarkName = benchmark.toString();
+ Intent intent = new Intent();
+ intent.putExtra(GLActivity.INTENT_EXTRA_BENCHMARK_NAME, benchmarkName);
+ intent.putExtra(GLActivity.INTENT_EXTRA_TIMEOUT, timeout);
+ intent.putExtra(GLActivity.INTENT_EXTRA_MIN_FPS, MIN_FPS);
+ intent.putExtra(GLActivity.INTENT_EXTRA_NUM_FRAMES, numFrames);
+
+ GLActivity activity = null;
+ setActivityIntent(intent);
+ try {
+ activity = getActivity();
+ int workload = activity.waitForCompletion();
+ // represents the maximum workload it can do whilst maintaining MIN_FPS.
+ getReportLog()
+ .printSummary("Workload", workload, ResultType.HIGHER_BETTER, ResultUnit.SCORE);
+ } finally {
+ if (activity != null) {
+ activity.finish();
+ }
+ }
+ }
+}