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 */
24 const int RS_MSG_TEST_DONE = 100;
25 const int RS_MSG_RESULTS_READY = 101;
26 
27 static const int gMaxModes = 64;
28 int gMaxLoops = 1;
29 int gDisplayMode = 1;
30 
31 // Allocation to write the results into
32 static float gResultBuffer[gMaxModes];
33 
34 rs_font gFontSerif;
35 rs_sampler gLinearClamp;
36 
37 rs_program_vertex gProgVertex;
38 rs_program_fragment gProgFragmentTexture;
39 
40 rs_allocation gRenderBufferColor;
41 rs_allocation gRenderBufferDepth;
42 
43 VertexShaderInputs *gVSInputs;
44 
45 typedef struct TestScripts_s {
46     rs_allocation testData;
47     rs_allocation testName;
48     rs_allocation debugName;
49     rs_script testScript;
50 } TestScripts;
51 TestScripts *gTestScripts;
52 
53 bool gLoadComplete = false;
54 bool gPauseRendering = false;
55 
56 static float gDt = 0;
57 
58 void init() {
59 }
60 
61 static int gRenderSurfaceW;
62 static int gRenderSurfaceH;
63 
64 static void fillSurfaceParams(TestData *testData) {
65     testData->renderSurfaceW = gRenderSurfaceW;
66     testData->renderSurfaceH = gRenderSurfaceH;
67     testData->dt = gDt;
68 }
69 
70 static void setupOffscreenTarget() {
71     rsgBindColorTarget(gRenderBufferColor, 0);
72     rsgBindDepthTarget(gRenderBufferDepth);
73 }
74 
75 static 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 
84 static void runSubTest(int index) {
85     TestData testData;
86     fillSurfaceParams(&testData);
87 
88     rs_allocation null_alloc = {0};
89     rsForEach(gTestScripts[index].testScript,
90               gTestScripts[index].testData,
91               null_alloc,
92               &testData,
93               sizeof(testData));
94 }
95 
96 
97 static 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 
126 static int benchMode = 0;
127 static bool benchmarkSingleTest = false;
128 static int runningLoops = 0;
129 static bool sendMsgFlag = false;
130 
131 static bool gIsDebugMode = false;
132 void setDebugMode(int testNumber) {
133     gIsDebugMode = true;
134     benchMode = testNumber;
135     rsgClearAllRenderTargets();
136 }
137 
138 void setBenchmarkMode(int testNumber) {
139     gIsDebugMode = false;
140     if (testNumber == -1) {
141         benchmarkSingleTest = false;
142         benchMode = 0;
143     } else {
144         benchmarkSingleTest = true;
145         benchMode = testNumber;
146     }
147 
148     runningLoops = 0;
149 }
150 
151 static void drawOffscreenResult(int posX, int posY, int width, int height) {
152     bindProgramVertexOrtho();
153 
154     rs_matrix4x4 matrix;
155     rsMatrixLoadIdentity(&matrix);
156     rsgProgramVertexLoadModelMatrix(&matrix);
157 
158     rsgBindProgramFragment(gProgFragmentTexture);
159 
160     rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
161     rsgBindTexture(gProgFragmentTexture, 0, gRenderBufferColor);
162 
163     float startX = posX, startY = posY;
164     rsgDrawQuadTexCoords(startX, startY, 0, 0, 1,
165                          startX, startY + height, 0, 0, 0,
166                          startX + width, startY + height, 0, 1, 0,
167                          startX + width, startY, 0, 1, 1);
168 }
169 
170 static void benchmark() {
171 
172     gDt = 1.0f / 60.0f;
173 
174     rsgFinish();
175     int64_t start = rsUptimeMillis();
176 
177     int drawPos = 0;
178     int frameCount = 100;
179     for(int i = 0; i < frameCount; i ++) {
180         setupOffscreenTarget();
181         gRenderSurfaceW = rsAllocationGetDimX(gRenderBufferColor);
182         gRenderSurfaceH = rsAllocationGetDimY(gRenderBufferColor);
183         rsgClearColor(0.1f, 0.1f, 0.1f, 1.0f);
184         rsgClearDepth(1.0f);
185 
186         runSubTest(benchMode);
187         rsgClearAllRenderTargets();
188         gRenderSurfaceW = rsgGetWidth();
189         gRenderSurfaceH = rsgGetHeight();
190         int size = 8;
191         // draw each frame at (8, 3/4 gRenderSurfaceH) with size
192         drawOffscreenResult((drawPos+=size)%gRenderSurfaceW, (gRenderSurfaceH * 3) / 4, size, size);
193     }
194 
195     rsgFinish();
196 
197     int64_t end = rsUptimeMillis();
198     float fps = (float)(frameCount) / ((float)(end - start)*0.001f);
199     const char *testName = rsGetElementAt(gTestScripts[benchMode].debugName, 0);
200     rsDebug(testName, fps);
201 
202     gResultBuffer[benchMode] = fps;
203     int bufferW = rsAllocationGetDimX(gRenderBufferColor);
204     int bufferH = rsAllocationGetDimY(gRenderBufferColor);
205 
206     int quadW = gRenderSurfaceW / 2;
207     int quadH = (quadW * bufferH) / bufferW;
208     drawOffscreenResult(0, 0, quadW, quadH);
209 
210     int left = 0, right = 0, top = 0, bottom = 0;
211     uint height = rsgGetHeight();
212     rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f);
213     rsgBindFont(gFontSerif);
214     rsgMeasureText(gTestScripts[benchMode].testName, &left, &right, &top, &bottom);
215     rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
216     rsgDrawText(gTestScripts[benchMode].testName, 2 -left, height - 2 + bottom);
217 
218     if (benchmarkSingleTest) {
219         return;
220     }
221 
222     benchMode ++;
223     int testCount = rsAllocationGetDimX(rsGetAllocation(gTestScripts));
224     if (benchMode == testCount) {
225         rsSendToClientBlocking(RS_MSG_RESULTS_READY, gResultBuffer, testCount*sizeof(float));
226         benchMode = 0;
227         runningLoops++;
228         if ((gMaxLoops > 0) && (runningLoops > gMaxLoops) && !sendMsgFlag) {
229             //Notifiy the test to stop and get results
230             rsDebug("gMaxLoops and runningLoops: ", gMaxLoops, runningLoops);
231             rsSendToClientBlocking(RS_MSG_TEST_DONE);
232             sendMsgFlag = true;
233         }
234     }
235 }
236 
237 static void debug() {
238     gDt = rsGetDt();
239     runSubTest(benchMode);
240 }
241 
242 int root(void) {
243     gRenderSurfaceW = rsgGetWidth();
244     gRenderSurfaceH = rsgGetHeight();
245     rsgClearColor(0.2f, 0.2f, 0.2f, 1.0f);
246     rsgClearDepth(1.0f);
247 
248     if (!gLoadComplete) {
249         rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f);
250         rsgBindFont(gFontSerif);
251         rsgDrawText("Loading", 50, 50);
252         return 0;
253     }
254 
255     if(!checkInit()) {
256         return 1;
257     }
258 
259     if (gPauseRendering) {
260         rsgDrawText("Paused", 50, 50);
261         return 30;
262     }
263     if (gIsDebugMode) {
264         debug();
265     } else {
266         benchmark();
267     }
268 
269     return 1;
270 }
271