More flexible structure for rs benchmark.
Major refactoring to allow adding more benchmarks easily.
Change-Id: I00e7c900b7383498da28cb9ffdc6fff855c5a581
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/ui_test.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/ui_test.rs
new file mode 100644
index 0000000..5089092
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/ui_test.rs
@@ -0,0 +1,444 @@
+// Copyright (C) 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.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.perftest)
+
+#include "rs_graphics.rsh"
+#include "shader_def.rsh"
+#include "subtest_def.rsh"
+
+// Parameters for galaxy live wallpaper
+rs_allocation gTSpace;
+rs_allocation gTLight1;
+rs_allocation gTFlares;
+rs_mesh gParticlesMesh;
+
+rs_program_fragment gPFBackground;
+rs_program_fragment gPFStars;
+rs_program_vertex gPVStars;
+rs_program_vertex gPVBkProj;
+rs_program_store gPSLights;
+
+float gXOffset = 0.5f;
+
+#define ELLIPSE_RATIO 0.892f
+#define PI 3.1415f
+#define TWO_PI 6.283f
+#define ELLIPSE_TWIST 0.023333333f
+
+static float angle = 50.f;
+static int gOldWidth;
+static int gOldHeight;
+static int gWidth;
+static int gHeight;
+static float gSpeed[12000];
+static int gGalaxyRadius = 300;
+static rs_allocation gParticlesBuffer;
+
+typedef struct __attribute__((packed, aligned(4))) Particle {
+ uchar4 color;
+ float3 position;
+} Particle_t;
+Particle_t *Particles;
+
+typedef struct VpConsts {
+ rs_matrix4x4 Proj;
+ rs_matrix4x4 MVP;
+} VpConsts_t;
+VpConsts_t *vpConstants;
+// End of parameters for galaxy live wallpaper
+
+rs_program_vertex gProgVertex;
+rs_program_fragment gProgFragmentColor;
+rs_program_fragment gProgFragmentTexture;
+
+rs_program_store gProgStoreBlendAlpha;
+
+rs_allocation gTexOpaque;
+rs_allocation gTexTorus;
+rs_allocation gTexGlobe;
+
+typedef struct ListAllocs_s {
+ rs_allocation item;
+} ListAllocs;
+
+ListAllocs *gTexList100;
+ListAllocs *gSampleTextList100;
+ListAllocs *gListViewText;
+
+rs_mesh gSingleMesh;
+
+rs_font gFontSans;
+
+rs_sampler gLinearClamp;
+
+typedef struct UiTestData_s {
+ int testId;
+ int user1;
+ int user2;
+ int user3;
+} UiTestData;
+UiTestData *gData;
+
+static float gDt = 0;
+
+
+void init() {
+}
+
+static int gRenderSurfaceW;
+static int gRenderSurfaceH;
+
+static void bindProgramVertexOrtho() {
+ // Default vertex shader
+ rsgBindProgramVertex(gProgVertex);
+ // Setup the projection matrix
+ rs_matrix4x4 proj;
+ rsMatrixLoadOrtho(&proj, 0, gRenderSurfaceW, gRenderSurfaceH, 0, -500, 500);
+ rsgProgramVertexLoadProjectionMatrix(&proj);
+}
+
+/**
+ * Methods to draw the galaxy live wall paper
+ */
+static float mapf(float minStart, float minStop, float maxStart, float maxStop, float value) {
+ return maxStart + (maxStart - maxStop) * ((value - minStart) / (minStop - minStart));
+}
+
+/**
+ * Helper function to generate the stars.
+ */
+static float randomGauss() {
+ float x1;
+ float x2;
+ float w = 2.f;
+
+ while (w >= 1.0f) {
+ x1 = rsRand(2.0f) - 1.0f;
+ x2 = rsRand(2.0f) - 1.0f;
+ w = x1 * x1 + x2 * x2;
+ }
+
+ w = sqrt(-2.0f * log(w) / w);
+ return x1 * w;
+}
+
+/**
+ * Generates the properties for a given star.
+ */
+static void createParticle(Particle_t *part, int idx, float scale) {
+ float d = fabs(randomGauss()) * gGalaxyRadius * 0.5f + rsRand(64.0f);
+ float id = d / gGalaxyRadius;
+ float z = randomGauss() * 0.4f * (1.0f - id);
+ float p = -d * ELLIPSE_TWIST;
+
+ if (d < gGalaxyRadius * 0.33f) {
+ part->color.x = (uchar) (220 + id * 35);
+ part->color.y = 220;
+ part->color.z = 220;
+ } else {
+ part->color.x = 180;
+ part->color.y = 180;
+ part->color.z = (uchar) clamp(140.f + id * 115.f, 140.f, 255.f);
+ }
+ // Stash point size * 10 in Alpha
+ part->color.w = (uchar) (rsRand(1.2f, 2.1f) * 60);
+
+ if (d > gGalaxyRadius * 0.15f) {
+ z *= 0.6f * (1.0f - id);
+ } else {
+ z *= 0.72f;
+ }
+
+ // Map to the projection coordinates (viewport.x = -1.0 -> 1.0)
+ d = mapf(-4.0f, gGalaxyRadius + 4.0f, 0.0f, scale, d);
+
+ part->position.x = rsRand(TWO_PI);
+ part->position.y = d;
+ gSpeed[idx] = rsRand(0.0015f, 0.0025f) * (0.5f + (scale / d)) * 0.8f;
+
+ part->position.z = z / 5.0f;
+}
+
+/**
+ * Initialize all the starts, called from Java
+ */
+void initParticles() {
+ Particle_t *part = Particles;
+ float scale = gGalaxyRadius / (gWidth * 0.5f);
+ int count = rsAllocationGetDimX(gParticlesBuffer);
+ for (int i = 0; i < count; i ++) {
+ createParticle(part, i, scale);
+ part++;
+ }
+}
+
+static void drawSpace() {
+ rsgBindProgramFragment(gPFBackground);
+ rsgBindTexture(gPFBackground, 0, gTSpace);
+ rsgDrawQuadTexCoords(
+ 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
+ gWidth, 0.0f, 0.0f, 2.0f, 1.0f,
+ gWidth, gHeight, 0.0f, 2.0f, 0.0f,
+ 0.0f, gHeight, 0.0f, 0.0f, 0.0f);
+}
+
+static void drawLights() {
+ rsgBindProgramVertex(gPVBkProj);
+ rsgBindProgramFragment(gPFBackground);
+ rsgBindTexture(gPFBackground, 0, gTLight1);
+
+ float scale = 512.0f / gWidth;
+ float x = -scale - scale * 0.05f;
+ float y = -scale;
+
+ scale *= 2.0f;
+
+ rsgDrawQuad(x, y, 0.0f,
+ x + scale * 1.1f, y, 0.0f,
+ x + scale * 1.1f, y + scale, 0.0f,
+ x, y + scale, 0.0f);
+}
+
+static void drawParticles(float offset) {
+ float a = offset * angle;
+ float absoluteAngle = fabs(a);
+
+ rs_matrix4x4 matrix;
+ rsMatrixLoadTranslate(&matrix, 0.0f, 0.0f, 10.0f - 6.0f * absoluteAngle / 50.0f);
+ if (gHeight > gWidth) {
+ rsMatrixScale(&matrix, 6.6f, 6.0f, 1.0f);
+ } else {
+ rsMatrixScale(&matrix, 12.6f, 12.0f, 1.0f);
+ }
+ rsMatrixRotate(&matrix, absoluteAngle, 1.0f, 0.0f, 0.0f);
+ rsMatrixRotate(&matrix, a, 0.0f, 0.4f, 0.1f);
+ rsMatrixLoad(&vpConstants->MVP, &vpConstants->Proj);
+ rsMatrixMultiply(&vpConstants->MVP, &matrix);
+ rsgAllocationSyncAll(rsGetAllocation(vpConstants));
+
+ rsgBindProgramVertex(gPVStars);
+ rsgBindProgramFragment(gPFStars);
+ rsgBindProgramStore(gPSLights);
+ rsgBindTexture(gPFStars, 0, gTFlares);
+
+ Particle_t *vtx = Particles;
+ int count = rsAllocationGetDimX(gParticlesBuffer);
+ for (int i = 0; i < count; i++) {
+ vtx->position.x = vtx->position.x + gSpeed[i];
+ vtx++;
+ }
+
+ rsgDrawMesh(gParticlesMesh);
+}
+/* end of methods for drawing galaxy */
+
+// Display sample images in a mesh with different texture
+static void displayIcons(int meshMode) {
+ bindProgramVertexOrtho();
+
+ // Fragment shader with texture
+ rsgBindProgramStore(gProgStoreBlendAlpha);
+ rsgBindProgramFragment(gProgFragmentTexture);
+ rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
+ rsgBindTexture(gProgFragmentTexture, 0, gTexTorus);
+ rsgDrawQuadTexCoords(
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, gRenderSurfaceH, 0.0f, 0.0f, 1.0f,
+ gRenderSurfaceW, gRenderSurfaceH, 0.0f, 1.0f, 1.0f,
+ gRenderSurfaceW, 0.0f, 0.0f, 1.0f, 0.0f);
+
+ int meshCount = (int)pow(10.0f, (float)(meshMode + 1));
+
+ float wSize = gRenderSurfaceW/(float)meshCount;
+ float hSize = gRenderSurfaceH/(float)meshCount;
+ rs_matrix4x4 matrix;
+ rsMatrixLoadScale(&matrix, wSize, hSize, 1.0);
+
+ float yPos = 0;
+ float yPad = hSize / 2;
+ float xPad = wSize / 2;
+ for (int y = 0; y < meshCount; y++) {
+ yPos = y * hSize + yPad;
+ float xPos = 0;
+ for (int x = 0; x < meshCount; x++) {
+ xPos = x * wSize + xPad;
+ rs_matrix4x4 transMatrix;
+ rsMatrixLoadTranslate(&transMatrix, xPos, yPos, 0);
+ rsMatrixMultiply(&transMatrix, &matrix);
+ rsgProgramVertexLoadModelMatrix(&transMatrix);
+ int i = (x + y * meshCount) % 100;
+ rsgBindTexture(gProgFragmentTexture, 0, gTexList100[i].item);
+ rsgDrawMesh(gSingleMesh);
+ }
+ }
+}
+
+// Draw meshes in a single page with top left corner coordinates (xStart, yStart)
+static void drawMeshInPage(float xStart, float yStart, int wResolution, int hResolution) {
+ // Draw wResolution * hResolution meshes in one page
+ float wMargin = 100.0f;
+ float hMargin = 100.0f;
+ float xPad = 50.0f;
+ float yPad = 20.0f;
+ float size = 100.0f; // size of images
+
+ // font info
+ rs_font font = gFontSans;
+ rsgBindFont(font);
+ rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
+
+ // Measure text size
+ int left = 0, right = 0, top = 0, bottom = 0;
+ rsgMeasureText(gSampleTextList100[0].item, &left, &right, &top, &bottom);
+ float textHeight = (float)(top - bottom);
+ float textWidth = (float)(right - left);
+
+ rs_matrix4x4 matrix;
+ rsMatrixLoadScale(&matrix, size, size, 1.0);
+
+ for (int y = 0; y < hResolution; y++) {
+ float yPos = yStart + hMargin + y * size + y * yPad;
+ for (int x = 0; x < wResolution; x++) {
+ float xPos = xStart + wMargin + x * size + x * xPad;
+
+ rs_matrix4x4 transMatrix;
+ rsMatrixLoadTranslate(&transMatrix, xPos + size/2, yPos + size/2, 0);
+ rsMatrixMultiply(&transMatrix, &matrix); // scale the mesh
+ rsgProgramVertexLoadModelMatrix(&transMatrix);
+
+ int i = (y * wResolution + x) % 100;
+ rsgBindTexture(gProgFragmentTexture, 0, gTexList100[i].item);
+ rsgDrawMesh(gSingleMesh);
+ rsgDrawText(gSampleTextList100[i].item, xPos, yPos + size + yPad/2 + textHeight);
+ }
+ }
+}
+
+// Display both images and text as shown in launcher and homepage
+// meshMode will decide how many pages we draw
+// meshMode = 0: draw 3 pages of meshes
+// meshMode = 1: draw 5 pages of meshes
+static void displayImageWithText(int wResolution, int hResolution, int meshMode) {
+ bindProgramVertexOrtho();
+
+ // Fragment shader with texture
+ rsgBindProgramStore(gProgStoreBlendAlpha);
+ rsgBindProgramFragment(gProgFragmentTexture);
+ rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
+
+ drawMeshInPage(0, 0, wResolution, hResolution);
+ drawMeshInPage(-1.0f*gRenderSurfaceW, 0, wResolution, hResolution);
+ drawMeshInPage(1.0f*gRenderSurfaceW, 0, wResolution, hResolution);
+ if (meshMode == 1) {
+ // draw another two pages of meshes
+ drawMeshInPage(-2.0f*gRenderSurfaceW, 0, wResolution, hResolution);
+ drawMeshInPage(2.0f*gRenderSurfaceW, 0, wResolution, hResolution);
+ }
+}
+
+// Display a list of text as the list view
+static void displayListView() {
+ // set text color
+ rsgFontColor(0.9f, 0.9f, 0.9f, 1.0f);
+ rsgBindFont(gFontSans);
+
+ // get the size of the list
+ rs_allocation textAlloc;
+ textAlloc = rsGetAllocation(gListViewText);
+ int allocSize = rsAllocationGetDimX(textAlloc);
+
+ int listItemHeight = 80;
+ int yOffset = listItemHeight;
+
+ // set the color for the list divider
+ rsgBindProgramFragment(gProgFragmentColor);
+ rsgProgramFragmentConstantColor(gProgFragmentColor, 1.0, 1.0, 1.0, 1);
+
+ // draw the list with divider
+ for (int i = 0; i < allocSize; i++) {
+ if (yOffset - listItemHeight > gRenderSurfaceH) {
+ break;
+ }
+ rsgDrawRect(0, yOffset - 1, gRenderSurfaceW, yOffset, 0);
+ rsgDrawText(gListViewText[i].item, 20, yOffset - 10);
+ yOffset += listItemHeight;
+ }
+}
+
+static void drawGalaxy() {
+ rsgClearColor(0.f, 0.f, 0.f, 1.f);
+ gParticlesBuffer = rsGetAllocation(Particles);
+ rsgBindProgramFragment(gPFBackground);
+
+ gWidth = rsgGetWidth();
+ gHeight = rsgGetHeight();
+ if ((gWidth != gOldWidth) || (gHeight != gOldHeight)) {
+ initParticles();
+ gOldWidth = gWidth;
+ gOldHeight = gHeight;
+ }
+
+ float offset = mix(-1.0f, 1.0f, gXOffset);
+ drawSpace();
+ drawParticles(offset);
+ drawLights();
+}
+
+// Display images and text with live wallpaper in the background
+static void displayLiveWallPaper(int wResolution, int hResolution) {
+ bindProgramVertexOrtho();
+
+ drawGalaxy();
+
+ rsgBindProgramVertex(gProgVertex);
+ rsgBindProgramStore(gProgStoreBlendAlpha);
+ rsgBindProgramFragment(gProgFragmentTexture);
+ rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
+
+ drawMeshInPage(0, 0, wResolution, hResolution);
+ drawMeshInPage(-1.0f*gRenderSurfaceW, 0, wResolution, hResolution);
+ drawMeshInPage(1.0f*gRenderSurfaceW, 0, wResolution, hResolution);
+ drawMeshInPage(-2.0f*gRenderSurfaceW, 0, wResolution, hResolution);
+ drawMeshInPage(2.0f*gRenderSurfaceW, 0, wResolution, hResolution);
+}
+
+void root(const void *v_in, void *v_out, const void *usrData, uint32_t x, uint32_t y) {
+ TestData *testData = (TestData*)usrData;
+ gRenderSurfaceW = testData->renderSurfaceW;
+ gRenderSurfaceH = testData->renderSurfaceH;
+ gDt = testData->dt;
+
+ gData = (UiTestData*)v_in;
+
+ switch(gData->testId) {
+ case 0:
+ displayIcons(gData->user1);
+ break;
+ case 1:
+ displayImageWithText(gData->user1, gData->user2, gData->user3);
+ break;
+ case 2:
+ displayListView();
+ break;
+ case 3:
+ displayLiveWallPaper(gData->user1, gData->user2);
+ break;
+ default:
+ rsDebug("Wrong test number", 0);
+ break;
+ }
+}