1// Copyright (C) 2010-2011 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#pragma version(1)
16
17#pragma rs java_package_name(com.android.perftest)
18
19#include "rs_graphics.rsh"
20#include "shader_def.rsh"
21#include "subtest_def.rsh"
22
23/* Message sent from script to renderscript */
24const int RS_MSG_TEST_DONE = 100;
25const int RS_MSG_RESULTS_READY = 101;
26
27static const int gMaxModes = 64;
28int gMaxLoops = 1;
29int gDisplayMode = 1;
30
31// Allocation to write the results into
32static float gResultBuffer[gMaxModes];
33
34rs_font gFontSerif;
35rs_sampler gLinearClamp;
36
37rs_program_vertex gProgVertex;
38rs_program_fragment gProgFragmentTexture;
39
40rs_allocation gRenderBufferColor;
41rs_allocation gRenderBufferDepth;
42
43VertexShaderInputs *gVSInputs;
44
45typedef struct TestScripts_s {
46    rs_allocation testData;
47    rs_allocation testName;
48    rs_allocation debugName;
49    rs_script testScript;
50} TestScripts;
51TestScripts *gTestScripts;
52
53bool gLoadComplete = false;
54bool gPauseRendering = false;
55
56static float gDt = 0;
57
58void init() {
59}
60
61static int gRenderSurfaceW;
62static int gRenderSurfaceH;
63
64static void fillSurfaceParams(TestData *testData) {
65    testData->renderSurfaceW = gRenderSurfaceW;
66    testData->renderSurfaceH = gRenderSurfaceH;
67    testData->dt = gDt;
68}
69
70static void setupOffscreenTarget() {
71    rsgBindColorTarget(gRenderBufferColor, 0);
72    rsgBindDepthTarget(gRenderBufferDepth);
73}
74
75static void bindProgramVertexOrtho() {
76    // Default vertex shader
77    rsgBindProgramVertex(gProgVertex);
78    // Setup the projection matrix
79    rs_matrix4x4 proj;
80    rsMatrixLoadOrtho(&proj, 0, gRenderSurfaceW, gRenderSurfaceH, 0, -500, 500);
81    rsgProgramVertexLoadProjectionMatrix(&proj);
82}
83
84static void runSubTest(int index) {
85    TestData testData;
86    fillSurfaceParams(&testData);
87
88    rs_allocation null_alloc;
89    rsForEach(gTestScripts[index].testScript,
90              gTestScripts[index].testData,
91              null_alloc,
92              &testData,
93              sizeof(testData));
94}
95
96
97static bool checkInit() {
98
99    static int countdown = 3;
100
101    // Perform all the uploads so we only measure rendered time
102    if(countdown > 1) {
103        int testCount = rsAllocationGetDimX(rsGetAllocation(gTestScripts));
104        for(int i = 0; i < testCount; i ++) {
105            rsgClearColor(0.2f, 0.2f, 0.2f, 0.0f);
106            runSubTest(i);
107            rsgFinish();
108        }
109        countdown --;
110        rsgClearColor(0.2f, 0.2f, 0.2f, 0.0f);
111
112        rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f);
113        rsgBindFont(gFontSerif);
114        if (countdown == 1) {
115            rsgDrawText("Rendering", 50, 50);
116        } else {
117            rsgDrawText("Initializing", 50, 50);
118        }
119
120        return false;
121    }
122
123    return true;
124}
125
126static int benchMode = 0;
127static bool benchmarkSingleTest = false;
128static int benchSubMode = 0;
129static int runningLoops = 0;
130static bool sendMsgFlag = false;
131
132static bool gIsDebugMode = false;
133void setDebugMode(int testNumber) {
134    gIsDebugMode = true;
135    benchMode = testNumber;
136    rsgClearAllRenderTargets();
137}
138
139void setBenchmarkMode(int testNumber) {
140    gIsDebugMode = false;
141    if (testNumber == -1) {
142        benchmarkSingleTest = false;
143        benchMode = 0;
144    } else {
145        benchmarkSingleTest = true;
146        benchMode = testNumber;
147    }
148
149    runningLoops = 0;
150}
151
152static void drawOffscreenResult(int posX, int posY, int width, int height) {
153    bindProgramVertexOrtho();
154
155    rs_matrix4x4 matrix;
156    rsMatrixLoadIdentity(&matrix);
157    rsgProgramVertexLoadModelMatrix(&matrix);
158
159    rsgBindProgramFragment(gProgFragmentTexture);
160
161    rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
162    rsgBindTexture(gProgFragmentTexture, 0, gRenderBufferColor);
163
164    float startX = posX, startY = posY;
165    rsgDrawQuadTexCoords(startX, startY, 0, 0, 1,
166                         startX, startY + height, 0, 0, 0,
167                         startX + width, startY + height, 0, 1, 0,
168                         startX + width, startY, 0, 1, 1);
169}
170
171static void benchmark() {
172
173    gDt = 1.0f / 60.0f;
174
175    rsgFinish();
176    int64_t start = rsUptimeMillis();
177
178    int drawPos = 0;
179    int frameCount = 100;
180    for(int i = 0; i < frameCount; i ++) {
181        setupOffscreenTarget();
182        gRenderSurfaceW = rsAllocationGetDimX(gRenderBufferColor);
183        gRenderSurfaceH = rsAllocationGetDimY(gRenderBufferColor);
184        rsgClearColor(0.1f, 0.1f, 0.1f, 1.0f);
185        rsgClearDepth(1.0f);
186
187        runSubTest(benchMode);
188        rsgClearAllRenderTargets();
189        gRenderSurfaceW = rsgGetWidth();
190        gRenderSurfaceH = rsgGetHeight();
191        int size = 8;
192        // draw each frame at (8, 3/4 gRenderSurfaceH) with size
193        drawOffscreenResult((drawPos+=size)%gRenderSurfaceW, (gRenderSurfaceH * 3) / 4, size, size);
194    }
195
196    rsgFinish();
197
198    int64_t end = rsUptimeMillis();
199    float fps = (float)(frameCount) / ((float)(end - start)*0.001f);
200    const char *testName = rsGetElementAt(gTestScripts[benchMode].debugName, 0);
201    rsDebug(testName, fps);
202
203    gResultBuffer[benchMode] = fps;
204    int bufferW = rsAllocationGetDimX(gRenderBufferColor);
205    int bufferH = rsAllocationGetDimY(gRenderBufferColor);
206
207    int quadW = gRenderSurfaceW / 2;
208    int quadH = (quadW * bufferH) / bufferW;
209    drawOffscreenResult(0, 0, quadW, quadH);
210
211    int left = 0, right = 0, top = 0, bottom = 0;
212    uint width = rsgGetWidth();
213    uint height = rsgGetHeight();
214    rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f);
215    rsgBindFont(gFontSerif);
216    rsgMeasureText(gTestScripts[benchMode].testName, &left, &right, &top, &bottom);
217    rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
218    rsgDrawText(gTestScripts[benchMode].testName, 2 -left, height - 2 + bottom);
219
220    if (benchmarkSingleTest) {
221        return;
222    }
223
224    benchMode ++;
225    int testCount = rsAllocationGetDimX(rsGetAllocation(gTestScripts));
226    if (benchMode == testCount) {
227        rsSendToClientBlocking(RS_MSG_RESULTS_READY, gResultBuffer, testCount*sizeof(float));
228        benchMode = 0;
229        runningLoops++;
230        if ((gMaxLoops > 0) && (runningLoops > gMaxLoops) && !sendMsgFlag) {
231            //Notifiy the test to stop and get results
232            rsDebug("gMaxLoops and runningLoops: ", gMaxLoops, runningLoops);
233            rsSendToClientBlocking(RS_MSG_TEST_DONE);
234            sendMsgFlag = true;
235        }
236    }
237}
238
239static void debug() {
240    gDt = rsGetDt();
241    runSubTest(benchMode);
242}
243
244int root(void) {
245    gRenderSurfaceW = rsgGetWidth();
246    gRenderSurfaceH = rsgGetHeight();
247    rsgClearColor(0.2f, 0.2f, 0.2f, 1.0f);
248    rsgClearDepth(1.0f);
249
250    if (!gLoadComplete) {
251        rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f);
252        rsgBindFont(gFontSerif);
253        rsgDrawText("Loading", 50, 50);
254        return 0;
255    }
256
257    if(!checkInit()) {
258        return 1;
259    }
260
261    if (gPauseRendering) {
262        rsgDrawText("Paused", 50, 50);
263        return 30;
264    }
265    if (gIsDebugMode) {
266        debug();
267    } else {
268        benchmark();
269    }
270
271    return 1;
272}
273