/*
* Copyright (C) 2010-2011 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.perftest;
import java.io.Writer;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import android.os.Environment;
import android.content.res.Resources;
import android.renderscript.*;
import android.renderscript.Element.DataKind;
import android.renderscript.Element.DataType;
import android.renderscript.Allocation.MipmapControl;
import android.renderscript.Program.TextureType;
import android.renderscript.RenderScript.RSMessageHandler;
import android.renderscript.Sampler.Value;
import android.renderscript.Mesh.Primitive;
import android.renderscript.Matrix4f;
import android.renderscript.ProgramVertexFixedFunction;
import android.util.Log;
public class RsBenchRS {
private static final String TAG = "RsBenchRS";
int mWidth;
int mHeight;
int mLoops;
int mCurrentLoop;
int mBenchmarkDimX;
int mBenchmarkDimY;
public RsBenchRS() {
}
public void init(RenderScriptGL rs, Resources res, int width, int height, int loops) {
mRS = rs;
mRes = res;
mWidth = width;
mHeight = height;
mMode = 0;
mLoops = loops;
mCurrentLoop = 0;
mBenchmarkDimX = 1280;
mBenchmarkDimY = 720;
initRS();
}
private boolean stopTest = false;
private Resources mRes;
private RenderScriptGL mRS;
private ProgramStore mProgStoreBlendNone;
private ProgramStore mProgStoreBlendAlpha;
private ProgramFragment mProgFragmentTexture;
private ProgramFragment mProgFragmentColor;
private ProgramVertex mProgVertex;
private ProgramVertexFixedFunction.Constants mPVA;
private ProgramVertexFixedFunction.Constants mPvProjectionAlloc;
private ScriptC_rsbench mScript;
ScriptField_TestScripts_s.Item[] mIndividualTests;
int mMode;
String[] mTestNames;
float[] mLocalTestResults;
static Allocation createZeroTerminatedAlloc(RenderScript rs,
String str,
int usage) {
byte[] allocArray = null;
try {
allocArray = str.getBytes("UTF-8");
byte[] allocArrayZero = new byte[allocArray.length + 1];
System.arraycopy(allocArray, 0, allocArrayZero, 0, allocArray.length);
allocArrayZero[allocArrayZero.length - 1] = '\0';
Allocation alloc = Allocation.createSized(rs, Element.U8(rs),
allocArrayZero.length, usage);
alloc.copyFrom(allocArrayZero);
return alloc;
}
catch (Exception e) {
throw new RSRuntimeException("Could not convert string to utf-8.");
}
}
void appendTests(RsBenchBaseTest testSet) {
ScriptField_TestScripts_s.Item[] newTests = testSet.getTests();
if (mIndividualTests != null) {
ScriptField_TestScripts_s.Item[] combined;
combined = new ScriptField_TestScripts_s.Item[newTests.length + mIndividualTests.length];
System.arraycopy(mIndividualTests, 0, combined, 0, mIndividualTests.length);
System.arraycopy(newTests, 0, combined, mIndividualTests.length, newTests.length);
mIndividualTests = combined;
} else {
mIndividualTests = newTests;
}
String[] newNames = testSet.getTestNames();
if (mTestNames != null) {
String[] combinedNames;
combinedNames = new String[newNames.length + mTestNames.length];
System.arraycopy(mTestNames, 0, combinedNames, 0, mTestNames.length);
System.arraycopy(newNames, 0, combinedNames, mTestNames.length, newNames.length);
mTestNames = combinedNames;
} else {
mTestNames = newNames;
}
}
void createTestAllocation() {
int numTests = mIndividualTests.length;
mLocalTestResults = new float[numTests];
ScriptField_TestScripts_s allTests;
allTests = new ScriptField_TestScripts_s(mRS, numTests);
for (int i = 0; i < numTests; i ++) {
allTests.set(mIndividualTests[i], i, false);
}
allTests.copyAll();
mScript.bind_gTestScripts(allTests);
}
private void saveTestResults() {
String state = Environment.getExternalStorageState();
if (!Environment.MEDIA_MOUNTED.equals(state)) {
Log.v(TAG, "sdcard is read only");
return;
}
File sdCard = Environment.getExternalStorageDirectory();
if (!sdCard.canWrite()) {
Log.v(TAG, "ssdcard is read only");
return;
}
File resultFile = new File(sdCard, "rsbench_result" + mCurrentLoop + ".csv");
resultFile.setWritable(true, false);
try {
BufferedWriter results = new BufferedWriter(new FileWriter(resultFile));
for (int i = 0; i < mLocalTestResults.length; i ++) {
results.write(mTestNames[i] + ", " + mLocalTestResults[i] + ",\n");
}
results.close();
Log.v(TAG, "Saved results in: " + resultFile.getAbsolutePath());
} catch (IOException e) {
Log.v(TAG, "Unable to write result file " + e.getMessage());
}
}
/**
* Create a message handler to handle message sent from the script
*/
protected RSMessageHandler mRsMessage = new RSMessageHandler() {
public void run() {
if (mID == mScript.get_RS_MSG_RESULTS_READY()) {
for (int i = 0; i < mLocalTestResults.length; i ++) {
mLocalTestResults[i] = Float.intBitsToFloat(mData[i]);
}
saveTestResults();
if (mLoops > 0) {
mCurrentLoop ++;
mCurrentLoop = mCurrentLoop % mLoops;
}
return;
} else if (mID == mScript.get_RS_MSG_TEST_DONE()) {
synchronized(this) {
stopTest = true;
this.notifyAll();
}
return;
} else {
Log.v(TAG, "Perf test got unexpected message");
return;
}
}
};
/**
* Wait for message from the script
*/
public boolean testIsFinished() {
synchronized(this) {
while (true) {
if (stopTest) {
return true;
} else {
try {
this.wait(60*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
private void initProgramFragment() {
ProgramFragmentFixedFunction.Builder texBuilder = new ProgramFragmentFixedFunction.Builder(mRS);
texBuilder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
mProgFragmentTexture = texBuilder.create();
mProgFragmentTexture.bindSampler(Sampler.CLAMP_LINEAR(mRS), 0);
ProgramFragmentFixedFunction.Builder colBuilder = new ProgramFragmentFixedFunction.Builder(mRS);
colBuilder.setVaryingColor(false);
mProgFragmentColor = colBuilder.create();
mScript.set_gProgFragmentTexture(mProgFragmentTexture);
}
private void initProgramVertex() {
ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
mProgVertex = pvb.create();
mPVA = new ProgramVertexFixedFunction.Constants(mRS);
((ProgramVertexFixedFunction)mProgVertex).bindConstants(mPVA);
Matrix4f proj = new Matrix4f();
proj.loadOrthoWindow(mBenchmarkDimX, mBenchmarkDimY);
mPVA.setProjection(proj);
mScript.set_gProgVertex(mProgVertex);
}
private int strlen(byte[] array) {
int count = 0;
while(count < array.length && array[count] != 0) {
count ++;
}
return count;
}
public void setDebugMode(int num) {
mScript.invoke_setDebugMode(num);
}
public void setBenchmarkMode(int benchNum) {
mScript.invoke_setBenchmarkMode(benchNum);
}
public void pause(boolean pause) {
mScript.set_gPauseRendering(pause);
}
private void initRS() {
mScript = new ScriptC_rsbench(mRS, mRes, R.raw.rsbench);
mRS.bindRootScript(mScript);
mRS.setMessageHandler(mRsMessage);
mScript.set_gMaxLoops(mLoops);
initProgramVertex();
initProgramFragment();
mScript.set_gFontSerif(Font.create(mRS, mRes, "serif", Font.Style.NORMAL, 8));
Type.Builder b = new Type.Builder(mRS, Element.RGBA_8888(mRS));
b.setX(mBenchmarkDimX).setY(mBenchmarkDimY);
Allocation offscreen = Allocation.createTyped(mRS,
b.create(),
Allocation.USAGE_GRAPHICS_TEXTURE |
Allocation.USAGE_GRAPHICS_RENDER_TARGET);
mScript.set_gRenderBufferColor(offscreen);
b = new Type.Builder(mRS,
Element.createPixel(mRS, DataType.UNSIGNED_16,
DataKind.PIXEL_DEPTH));
b.setX(mBenchmarkDimX).setY(mBenchmarkDimY);
offscreen = Allocation.createTyped(mRS,
b.create(),
Allocation.USAGE_GRAPHICS_RENDER_TARGET);
mScript.set_gRenderBufferDepth(offscreen);
mScript.set_gLinearClamp(Sampler.CLAMP_LINEAR(mRS));
RsBenchBaseTest test = new TextTest();
if (test.init(mRS, mRes)) {
appendTests(test);
}
test = new FillTest();
if (test.init(mRS, mRes)) {
appendTests(test);
}
test = new MeshTest();
if (test.init(mRS, mRes)) {
appendTests(test);
}
test = new TorusTest();
if (test.init(mRS, mRes)) {
appendTests(test);
}
test = new UiTest();
if (test.init(mRS, mRes)) {
appendTests(test);
}
createTestAllocation();
mScript.set_gLoadComplete(true);
}
}