1 // Copyright (C) 2009 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 const int gMaxModes = 31; 28 int gMaxLoops; 29 30 // Parameters for galaxy live wallpaper 31 rs_allocation gTSpace; 32 rs_allocation gTLight1; 33 rs_allocation gTFlares; 34 rs_mesh gParticlesMesh; 35 36 rs_program_fragment gPFBackground; 37 rs_program_fragment gPFStars; 38 rs_program_vertex gPVStars; 39 rs_program_vertex gPVBkProj; 40 rs_program_store gPSLights; 41 42 float gXOffset = 0.5f; 43 44 #define ELLIPSE_RATIO 0.892f 45 #define PI 3.1415f 46 #define TWO_PI 6.283f 47 #define ELLIPSE_TWIST 0.023333333f 48 49 static float angle = 50.f; 50 static int gOldWidth; 51 static int gOldHeight; 52 static int gWidth; 53 static int gHeight; 54 static float gSpeed[12000]; 55 static int gGalaxyRadius = 300; 56 static rs_allocation gParticlesBuffer; 57 58 typedef struct __attribute__((packed, aligned(4))) Particle { 59 uchar4 color; 60 float3 position; 61 } Particle_t; 62 Particle_t *Particles; 63 64 typedef struct VpConsts { 65 rs_matrix4x4 Proj; 66 rs_matrix4x4 MVP; 67 } VpConsts_t; 68 VpConsts_t *vpConstants; 69 // End of parameters for galaxy live wallpaper 70 71 // Allocation to send test names back to java 72 char *gStringBuffer = 0; 73 // Allocation to write the results into 74 static float gResultBuffer[gMaxModes]; 75 76 rs_program_vertex gProgVertex; 77 rs_program_fragment gProgFragmentColor; 78 rs_program_fragment gProgFragmentTexture; 79 80 rs_program_store gProgStoreBlendNoneDepth; 81 rs_program_store gProgStoreBlendNone; 82 rs_program_store gProgStoreBlendAlpha; 83 rs_program_store gProgStoreBlendAdd; 84 85 rs_allocation gTexOpaque; 86 rs_allocation gTexTorus; 87 rs_allocation gTexTransparent; 88 rs_allocation gTexChecker; 89 rs_allocation gTexGlobe; 90 91 typedef struct ListAllocs_s { 92 rs_allocation item; 93 } ListAllocs; 94 95 ListAllocs *gTexList100; 96 ListAllocs *gSampleTextList100; 97 ListAllocs *gListViewText; 98 99 rs_mesh g10by10Mesh; 100 rs_mesh g100by100Mesh; 101 rs_mesh gWbyHMesh; 102 rs_mesh gSingleMesh; 103 104 rs_font gFontSans; 105 rs_font gFontSerif; 106 107 int gDisplayMode; 108 109 rs_sampler gLinearClamp; 110 rs_sampler gLinearWrap; 111 rs_sampler gMipLinearWrap; 112 rs_sampler gNearestClamp; 113 114 rs_program_raster gCullBack; 115 rs_program_raster gCullFront; 116 rs_program_raster gCullNone; 117 118 // Export these out to easily set the inputs to shader 119 VertexShaderInputs *gVSInputs; 120 121 rs_program_fragment gProgFragmentMultitex; 122 123 rs_allocation gRenderBufferColor; 124 rs_allocation gRenderBufferDepth; 125 126 static float gDt = 0; 127 128 void init() { 129 } 130 131 static int gRenderSurfaceW; 132 static int gRenderSurfaceH; 133 134 /** 135 * Methods to draw the galaxy live wall paper 136 */ 137 static float mapf(float minStart, float minStop, float maxStart, float maxStop, float value) { 138 return maxStart + (maxStart - maxStop) * ((value - minStart) / (minStop - minStart)); 139 } 140 141 /** 142 * Helper function to generate the stars. 143 */ 144 static float randomGauss() { 145 float x1; 146 float x2; 147 float w = 2.f; 148 149 while (w >= 1.0f) { 150 x1 = rsRand(2.0f) - 1.0f; 151 x2 = rsRand(2.0f) - 1.0f; 152 w = x1 * x1 + x2 * x2; 153 } 154 155 w = sqrt(-2.0f * log(w) / w); 156 return x1 * w; 157 } 158 159 /** 160 * Generates the properties for a given star. 161 */ 162 static void createParticle(Particle_t *part, int idx, float scale) { 163 float d = fabs(randomGauss()) * gGalaxyRadius * 0.5f + rsRand(64.0f); 164 float id = d / gGalaxyRadius; 165 float z = randomGauss() * 0.4f * (1.0f - id); 166 float p = -d * ELLIPSE_TWIST; 167 168 if (d < gGalaxyRadius * 0.33f) { 169 part->color.x = (uchar) (220 + id * 35); 170 part->color.y = 220; 171 part->color.z = 220; 172 } else { 173 part->color.x = 180; 174 part->color.y = 180; 175 part->color.z = (uchar) clamp(140.f + id * 115.f, 140.f, 255.f); 176 } 177 // Stash point size * 10 in Alpha 178 part->color.w = (uchar) (rsRand(1.2f, 2.1f) * 60); 179 180 if (d > gGalaxyRadius * 0.15f) { 181 z *= 0.6f * (1.0f - id); 182 } else { 183 z *= 0.72f; 184 } 185 186 // Map to the projection coordinates (viewport.x = -1.0 -> 1.0) 187 d = mapf(-4.0f, gGalaxyRadius + 4.0f, 0.0f, scale, d); 188 189 part->position.x = rsRand(TWO_PI); 190 part->position.y = d; 191 gSpeed[idx] = rsRand(0.0015f, 0.0025f) * (0.5f + (scale / d)) * 0.8f; 192 193 part->position.z = z / 5.0f; 194 } 195 196 /** 197 * Initialize all the starts, called from Java 198 */ 199 void initParticles() { 200 Particle_t *part = Particles; 201 float scale = gGalaxyRadius / (gWidth * 0.5f); 202 int count = rsAllocationGetDimX(gParticlesBuffer); 203 for (int i = 0; i < count; i ++) { 204 createParticle(part, i, scale); 205 part++; 206 } 207 } 208 209 static void drawSpace() { 210 rsgBindProgramFragment(gPFBackground); 211 rsgBindTexture(gPFBackground, 0, gTSpace); 212 rsgDrawQuadTexCoords( 213 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 214 gWidth, 0.0f, 0.0f, 2.0f, 1.0f, 215 gWidth, gHeight, 0.0f, 2.0f, 0.0f, 216 0.0f, gHeight, 0.0f, 0.0f, 0.0f); 217 } 218 219 static void drawLights() { 220 rsgBindProgramVertex(gPVBkProj); 221 rsgBindProgramFragment(gPFBackground); 222 rsgBindTexture(gPFBackground, 0, gTLight1); 223 224 float scale = 512.0f / gWidth; 225 float x = -scale - scale * 0.05f; 226 float y = -scale; 227 228 scale *= 2.0f; 229 230 rsgDrawQuad(x, y, 0.0f, 231 x + scale * 1.1f, y, 0.0f, 232 x + scale * 1.1f, y + scale, 0.0f, 233 x, y + scale, 0.0f); 234 } 235 236 static void drawParticles(float offset) { 237 float a = offset * angle; 238 float absoluteAngle = fabs(a); 239 240 rs_matrix4x4 matrix; 241 rsMatrixLoadTranslate(&matrix, 0.0f, 0.0f, 10.0f - 6.0f * absoluteAngle / 50.0f); 242 if (gHeight > gWidth) { 243 rsMatrixScale(&matrix, 6.6f, 6.0f, 1.0f); 244 } else { 245 rsMatrixScale(&matrix, 12.6f, 12.0f, 1.0f); 246 } 247 rsMatrixRotate(&matrix, absoluteAngle, 1.0f, 0.0f, 0.0f); 248 rsMatrixRotate(&matrix, a, 0.0f, 0.4f, 0.1f); 249 rsMatrixLoad(&vpConstants->MVP, &vpConstants->Proj); 250 rsMatrixMultiply(&vpConstants->MVP, &matrix); 251 rsgAllocationSyncAll(rsGetAllocation(vpConstants)); 252 253 rsgBindProgramVertex(gPVStars); 254 rsgBindProgramFragment(gPFStars); 255 rsgBindProgramStore(gPSLights); 256 rsgBindTexture(gPFStars, 0, gTFlares); 257 258 Particle_t *vtx = Particles; 259 int count = rsAllocationGetDimX(gParticlesBuffer); 260 for (int i = 0; i < count; i++) { 261 vtx->position.x = vtx->position.x + gSpeed[i]; 262 vtx++; 263 } 264 265 rsgDrawMesh(gParticlesMesh); 266 } 267 /* end of methods for drawing galaxy */ 268 269 static void setupOffscreenTarget() { 270 rsgBindColorTarget(gRenderBufferColor, 0); 271 rsgBindDepthTarget(gRenderBufferDepth); 272 } 273 274 rs_script gFontScript; 275 rs_script gTorusScript; 276 rs_allocation gDummyAlloc; 277 278 static void displayFontSamples(int fillNum) { 279 TestData testData; 280 testData.renderSurfaceW = gRenderSurfaceW; 281 testData.renderSurfaceH = gRenderSurfaceH; 282 testData.user = fillNum; 283 rsForEach(gFontScript, gDummyAlloc, gDummyAlloc, &testData, sizeof(testData)); 284 } 285 286 static void bindProgramVertexOrtho() { 287 // Default vertex shader 288 rsgBindProgramVertex(gProgVertex); 289 // Setup the projection matrix 290 rs_matrix4x4 proj; 291 rsMatrixLoadOrtho(&proj, 0, gRenderSurfaceW, gRenderSurfaceH, 0, -500, 500); 292 rsgProgramVertexLoadProjectionMatrix(&proj); 293 } 294 295 static void displaySingletexFill(bool blend, int quadCount) { 296 bindProgramVertexOrtho(); 297 rs_matrix4x4 matrix; 298 rsMatrixLoadIdentity(&matrix); 299 rsgProgramVertexLoadModelMatrix(&matrix); 300 301 // Fragment shader with texture 302 if (!blend) { 303 rsgBindProgramStore(gProgStoreBlendNone); 304 } else { 305 rsgBindProgramStore(gProgStoreBlendAlpha); 306 } 307 rsgBindProgramFragment(gProgFragmentTexture); 308 rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); 309 rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque); 310 311 for (int i = 0; i < quadCount; i ++) { 312 float startX = 5 * i, startY = 5 * i; 313 float width = gRenderSurfaceW - startX, height = gRenderSurfaceH - startY; 314 rsgDrawQuadTexCoords(startX, startY, 0, 0, 0, 315 startX, startY + height, 0, 0, 1, 316 startX + width, startY + height, 0, 1, 1, 317 startX + width, startY, 0, 1, 0); 318 } 319 } 320 321 static void displayMeshSamples(int meshNum) { 322 323 bindProgramVertexOrtho(); 324 rs_matrix4x4 matrix; 325 rsMatrixLoadTranslate(&matrix, gRenderSurfaceW/2, gRenderSurfaceH/2, 0); 326 rsgProgramVertexLoadModelMatrix(&matrix); 327 328 // Fragment shader with texture 329 rsgBindProgramStore(gProgStoreBlendNone); 330 rsgBindProgramFragment(gProgFragmentTexture); 331 rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); 332 333 rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque); 334 335 if (meshNum == 0) { 336 rsgDrawMesh(g10by10Mesh); 337 } else if (meshNum == 1) { 338 rsgDrawMesh(g100by100Mesh); 339 } else if (meshNum == 2) { 340 rsgDrawMesh(gWbyHMesh); 341 } 342 } 343 344 // Display sample images in a mesh with different texture 345 static void displayIcons(int meshMode) { 346 bindProgramVertexOrtho(); 347 348 // Fragment shader with texture 349 rsgBindProgramStore(gProgStoreBlendAlpha); 350 rsgBindProgramFragment(gProgFragmentTexture); 351 rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); 352 rsgBindTexture(gProgFragmentTexture, 0, gTexTorus); 353 rsgDrawQuadTexCoords( 354 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 355 0.0f, gRenderSurfaceH, 0.0f, 0.0f, 1.0f, 356 gRenderSurfaceW, gRenderSurfaceH, 0.0f, 1.0f, 1.0f, 357 gRenderSurfaceW, 0.0f, 0.0f, 1.0f, 0.0f); 358 359 int meshCount = (int)pow(10.0f, (float)(meshMode + 1)); 360 361 float wSize = gRenderSurfaceW/(float)meshCount; 362 float hSize = gRenderSurfaceH/(float)meshCount; 363 rs_matrix4x4 matrix; 364 rsMatrixLoadScale(&matrix, wSize, hSize, 1.0); 365 366 float yPos = 0; 367 float yPad = hSize / 2; 368 float xPad = wSize / 2; 369 for (int y = 0; y < meshCount; y++) { 370 yPos = y * hSize + yPad; 371 float xPos = 0; 372 for (int x = 0; x < meshCount; x++) { 373 xPos = x * wSize + xPad; 374 rs_matrix4x4 transMatrix; 375 rsMatrixLoadTranslate(&transMatrix, xPos, yPos, 0); 376 rsMatrixMultiply(&transMatrix, &matrix); 377 rsgProgramVertexLoadModelMatrix(&transMatrix); 378 int i = (x + y * meshCount) % 100; 379 rsgBindTexture(gProgFragmentTexture, 0, gTexList100[i].item); 380 rsgDrawMesh(gSingleMesh); 381 } 382 } 383 } 384 385 // Draw meshes in a single page with top left corner coordinates (xStart, yStart) 386 static void drawMeshInPage(float xStart, float yStart, int wResolution, int hResolution) { 387 // Draw wResolution * hResolution meshes in one page 388 float wMargin = 100.0f; 389 float hMargin = 100.0f; 390 float xPad = 50.0f; 391 float yPad = 20.0f; 392 float size = 100.0f; // size of images 393 394 // font info 395 rs_font font = gFontSans; 396 rsgBindFont(font); 397 rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); 398 399 // Measure text size 400 int left = 0, right = 0, top = 0, bottom = 0; 401 rsgMeasureText(gSampleTextList100[0].item, &left, &right, &top, &bottom); 402 float textHeight = (float)(top - bottom); 403 float textWidth = (float)(right - left); 404 405 rs_matrix4x4 matrix; 406 rsMatrixLoadScale(&matrix, size, size, 1.0); 407 408 for (int y = 0; y < hResolution; y++) { 409 float yPos = yStart + hMargin + y * size + y * yPad; 410 for (int x = 0; x < wResolution; x++) { 411 float xPos = xStart + wMargin + x * size + x * xPad; 412 413 rs_matrix4x4 transMatrix; 414 rsMatrixLoadTranslate(&transMatrix, xPos + size/2, yPos + size/2, 0); 415 rsMatrixMultiply(&transMatrix, &matrix); // scale the mesh 416 rsgProgramVertexLoadModelMatrix(&transMatrix); 417 418 int i = (y * wResolution + x) % 100; 419 rsgBindTexture(gProgFragmentTexture, 0, gTexList100[i].item); 420 rsgDrawMesh(gSingleMesh); 421 rsgDrawText(gSampleTextList100[i].item, xPos, yPos + size + yPad/2 + textHeight); 422 } 423 } 424 } 425 426 // Display both images and text as shown in launcher and homepage 427 // meshMode will decide how many pages we draw 428 // meshMode = 0: draw 3 pages of meshes 429 // meshMode = 1: draw 5 pages of meshes 430 static void displayImageWithText(int wResolution, int hResolution, int meshMode) { 431 bindProgramVertexOrtho(); 432 433 // Fragment shader with texture 434 rsgBindProgramStore(gProgStoreBlendAlpha); 435 rsgBindProgramFragment(gProgFragmentTexture); 436 rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); 437 438 drawMeshInPage(0, 0, wResolution, hResolution); 439 drawMeshInPage(-1.0f*gRenderSurfaceW, 0, wResolution, hResolution); 440 drawMeshInPage(1.0f*gRenderSurfaceW, 0, wResolution, hResolution); 441 if (meshMode == 1) { 442 // draw another two pages of meshes 443 drawMeshInPage(-2.0f*gRenderSurfaceW, 0, wResolution, hResolution); 444 drawMeshInPage(2.0f*gRenderSurfaceW, 0, wResolution, hResolution); 445 } 446 } 447 448 // Display a list of text as the list view 449 static void displayListView() { 450 // set text color 451 rsgFontColor(0.9f, 0.9f, 0.9f, 1.0f); 452 rsgBindFont(gFontSans); 453 454 // get the size of the list 455 rs_allocation textAlloc; 456 textAlloc = rsGetAllocation(gListViewText); 457 int allocSize = rsAllocationGetDimX(textAlloc); 458 459 int listItemHeight = 80; 460 int yOffset = listItemHeight; 461 462 // set the color for the list divider 463 rsgBindProgramFragment(gProgFragmentColor); 464 rsgProgramFragmentConstantColor(gProgFragmentColor, 1.0, 1.0, 1.0, 1); 465 466 // draw the list with divider 467 for (int i = 0; i < allocSize; i++) { 468 if (yOffset - listItemHeight > gRenderSurfaceH) { 469 break; 470 } 471 rsgDrawRect(0, yOffset - 1, gRenderSurfaceW, yOffset, 0); 472 rsgDrawText(gListViewText[i].item, 20, yOffset - 10); 473 yOffset += listItemHeight; 474 } 475 } 476 477 static void drawGalaxy() { 478 rsgClearColor(0.f, 0.f, 0.f, 1.f); 479 gParticlesBuffer = rsGetAllocation(Particles); 480 rsgBindProgramFragment(gPFBackground); 481 482 gWidth = rsgGetWidth(); 483 gHeight = rsgGetHeight(); 484 if ((gWidth != gOldWidth) || (gHeight != gOldHeight)) { 485 initParticles(); 486 gOldWidth = gWidth; 487 gOldHeight = gHeight; 488 } 489 490 float offset = mix(-1.0f, 1.0f, gXOffset); 491 drawSpace(); 492 drawParticles(offset); 493 drawLights(); 494 } 495 496 // Display images and text with live wallpaper in the background 497 static void displayLiveWallPaper(int wResolution, int hResolution) { 498 bindProgramVertexOrtho(); 499 500 drawGalaxy(); 501 502 rsgBindProgramVertex(gProgVertex); 503 rsgBindProgramStore(gProgStoreBlendAlpha); 504 rsgBindProgramFragment(gProgFragmentTexture); 505 rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); 506 507 drawMeshInPage(0, 0, wResolution, hResolution); 508 drawMeshInPage(-1.0f*gRenderSurfaceW, 0, wResolution, hResolution); 509 drawMeshInPage(1.0f*gRenderSurfaceW, 0, wResolution, hResolution); 510 drawMeshInPage(-2.0f*gRenderSurfaceW, 0, wResolution, hResolution); 511 drawMeshInPage(2.0f*gRenderSurfaceW, 0, wResolution, hResolution); 512 } 513 514 // Quick hack to get some geometry numbers 515 static void displaySimpleGeoSamples(bool useTexture, int numMeshes) { 516 TestData testData; 517 testData.renderSurfaceW = gRenderSurfaceW; 518 testData.renderSurfaceH = gRenderSurfaceH; 519 testData.dt = gDt; 520 testData.user = 0; 521 testData.user1 = useTexture ? 1 : 0; 522 testData.user2 = numMeshes; 523 rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData, sizeof(testData)); 524 } 525 526 static void displayCustomShaderSamples(int numMeshes) { 527 TestData testData; 528 testData.renderSurfaceW = gRenderSurfaceW; 529 testData.renderSurfaceH = gRenderSurfaceH; 530 testData.dt = gDt; 531 testData.user = 1; 532 testData.user1 = numMeshes; 533 rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData, sizeof(testData)); 534 } 535 536 static void displayPixelLightSamples(int numMeshes, bool heavyVertex) { 537 TestData testData; 538 testData.renderSurfaceW = gRenderSurfaceW; 539 testData.renderSurfaceH = gRenderSurfaceH; 540 testData.dt = gDt; 541 testData.user = 2; 542 testData.user1 = numMeshes; 543 testData.user2 = heavyVertex ? 1 : 0; 544 rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData, sizeof(testData)); 545 } 546 547 static void displayMultitextureSample(bool blend, int quadCount) { 548 bindProgramVertexOrtho(); 549 rs_matrix4x4 matrix; 550 rsMatrixLoadIdentity(&matrix); 551 rsgProgramVertexLoadModelMatrix(&matrix); 552 553 // Fragment shader with texture 554 if (!blend) { 555 rsgBindProgramStore(gProgStoreBlendNone); 556 } else { 557 rsgBindProgramStore(gProgStoreBlendAlpha); 558 } 559 rsgBindProgramFragment(gProgFragmentMultitex); 560 rsgBindSampler(gProgFragmentMultitex, 0, gLinearClamp); 561 rsgBindSampler(gProgFragmentMultitex, 1, gLinearWrap); 562 rsgBindSampler(gProgFragmentMultitex, 2, gLinearClamp); 563 rsgBindTexture(gProgFragmentMultitex, 0, gTexChecker); 564 rsgBindTexture(gProgFragmentMultitex, 1, gTexTorus); 565 rsgBindTexture(gProgFragmentMultitex, 2, gTexTransparent); 566 567 for (int i = 0; i < quadCount; i ++) { 568 float startX = 10 * i, startY = 10 * i; 569 float width = gRenderSurfaceW - startX, height = gRenderSurfaceH - startY; 570 rsgDrawQuadTexCoords(startX, startY, 0, 0, 0, 571 startX, startY + height, 0, 0, 1, 572 startX + width, startY + height, 0, 1, 1, 573 startX + width, startY, 0, 1, 0); 574 } 575 } 576 577 static bool checkInit() { 578 579 static int countdown = 5; 580 581 // Perform all the uploads so we only measure rendered time 582 if(countdown > 1) { 583 displayFontSamples(5); 584 displaySingletexFill(true, 3); 585 displayMeshSamples(0); 586 displayMeshSamples(1); 587 displayMeshSamples(2); 588 displayMultitextureSample(true, 5); 589 displayPixelLightSamples(1, false); 590 displayPixelLightSamples(1, true); 591 countdown --; 592 rsgClearColor(0.2f, 0.2f, 0.2f, 0.0f); 593 594 rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f); 595 rsgBindFont(gFontSerif); 596 if (countdown == 1) { 597 rsgDrawText("Rendering", 50, 50); 598 } else { 599 rsgDrawText("Initializing", 50, 50); 600 } 601 602 return false; 603 } 604 605 return true; 606 } 607 608 static int benchMode = 0; 609 static int runningLoops = 0; 610 static bool sendMsgFlag = false; 611 612 static const char *testNames[] = { 613 "Fill screen with text 1 time", 614 "Fill screen with text 3 times", 615 "Fill screen with text 5 times", 616 "Geo test 25.6k flat color", 617 "Geo test 51.2k flat color", 618 "Geo test 204.8k small tries flat color", 619 "Geo test 25.6k single texture", 620 "Geo test 51.2k single texture", 621 "Geo test 204.8k small tries single texture", 622 "Full screen mesh 10 by 10", 623 "Full screen mesh 100 by 100", 624 "Full screen mesh W / 4 by H / 4", 625 "Geo test 25.6k geo heavy vertex", 626 "Geo test 51.2k geo heavy vertex", 627 "Geo test 204.8k geo raster load heavy vertex", 628 "Fill screen 10x singletexture", 629 "Fill screen 10x 3tex multitexture", 630 "Fill screen 10x blended singletexture", 631 "Fill screen 10x blended 3tex multitexture", 632 "Geo test 25.6k heavy fragment", 633 "Geo test 51.2k heavy fragment", 634 "Geo test 204.8k small tries heavy fragment", 635 "Geo test 25.6k heavy fragment heavy vertex", 636 "Geo test 51.2k heavy fragment heavy vertex", 637 "Geo test 204.8k small tries heavy fragment heavy vertex", 638 "UI test with icon display 10 by 10", 639 "UI test with icon display 100 by 100", 640 "UI test with image and text display 3 pages", 641 "UI test with image and text display 5 pages", 642 "UI test with list view", 643 "UI test with live wallpaper", 644 }; 645 646 static bool gIsDebugMode = false; 647 void setDebugMode(int testNumber) { 648 gIsDebugMode = true; 649 benchMode = testNumber; 650 rsgClearAllRenderTargets(); 651 } 652 653 void setBenchmarkMode() { 654 gIsDebugMode = false; 655 benchMode = 0; 656 runningLoops = 0; 657 } 658 659 660 void getTestName(int testIndex) { 661 int bufferLen = rsAllocationGetDimX(rsGetAllocation(gStringBuffer)); 662 if (testIndex >= gMaxModes) { 663 return; 664 } 665 uint charIndex = 0; 666 while (testNames[testIndex][charIndex] != '\0' && charIndex < bufferLen) { 667 gStringBuffer[charIndex] = testNames[testIndex][charIndex]; 668 charIndex ++; 669 } 670 gStringBuffer[charIndex] = '\0'; 671 } 672 673 static void runTest(int index) { 674 switch (index) { 675 case 0: 676 displayFontSamples(1); 677 break; 678 case 1: 679 displayFontSamples(3); 680 break; 681 case 2: 682 displayFontSamples(5); 683 break; 684 case 3: 685 displaySimpleGeoSamples(false, 1); 686 break; 687 case 4: 688 displaySimpleGeoSamples(false, 2); 689 break; 690 case 5: 691 displaySimpleGeoSamples(false, 8); 692 break; 693 case 6: 694 displaySimpleGeoSamples(true, 1); 695 break; 696 case 7: 697 displaySimpleGeoSamples(true, 2); 698 break; 699 case 8: 700 displaySimpleGeoSamples(true, 8); 701 break; 702 case 9: 703 displayMeshSamples(0); 704 break; 705 case 10: 706 displayMeshSamples(1); 707 break; 708 case 11: 709 displayMeshSamples(2); 710 break; 711 case 12: 712 displayCustomShaderSamples(1); 713 break; 714 case 13: 715 displayCustomShaderSamples(2); 716 break; 717 case 14: 718 displayCustomShaderSamples(10); 719 break; 720 case 15: 721 displaySingletexFill(false, 10); 722 break; 723 case 16: 724 displayMultitextureSample(false, 10); 725 break; 726 case 17: 727 displaySingletexFill(true, 10); 728 break; 729 case 18: 730 displayMultitextureSample(true, 10); 731 break; 732 case 19: 733 displayPixelLightSamples(1, false); 734 break; 735 case 20: 736 displayPixelLightSamples(2, false); 737 break; 738 case 21: 739 displayPixelLightSamples(8, false); 740 break; 741 case 22: 742 displayPixelLightSamples(1, true); 743 break; 744 case 23: 745 displayPixelLightSamples(2, true); 746 break; 747 case 24: 748 displayPixelLightSamples(8, true); 749 break; 750 case 25: 751 displayIcons(0); 752 break; 753 case 26: 754 displayIcons(1); 755 break; 756 case 27: 757 displayImageWithText(7, 5, 0); 758 break; 759 case 28: 760 displayImageWithText(7, 5, 1); 761 break; 762 case 29: 763 displayListView(); 764 break; 765 case 30: 766 displayLiveWallPaper(7, 5); 767 break; 768 } 769 } 770 771 static void drawOffscreenResult(int posX, int posY, int width, int height) { 772 bindProgramVertexOrtho(); 773 774 rs_matrix4x4 matrix; 775 rsMatrixLoadIdentity(&matrix); 776 rsgProgramVertexLoadModelMatrix(&matrix); 777 778 rsgBindProgramFragment(gProgFragmentTexture); 779 780 rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); 781 rsgBindTexture(gProgFragmentTexture, 0, gRenderBufferColor); 782 783 float startX = posX, startY = posY; 784 rsgDrawQuadTexCoords(startX, startY, 0, 0, 1, 785 startX, startY + height, 0, 0, 0, 786 startX + width, startY + height, 0, 1, 0, 787 startX + width, startY, 0, 1, 1); 788 } 789 790 static void benchmark() { 791 792 gDt = 1.0f / 60.0f; 793 794 rsgFinish(); 795 int64_t start = rsUptimeMillis(); 796 797 int drawPos = 0; 798 int frameCount = 100; 799 for(int i = 0; i < frameCount; i ++) { 800 setupOffscreenTarget(); 801 gRenderSurfaceW = rsAllocationGetDimX(gRenderBufferColor); 802 gRenderSurfaceH = rsAllocationGetDimY(gRenderBufferColor); 803 rsgClearColor(0.1f, 0.1f, 0.1f, 1.0f); 804 rsgClearDepth(1.0f); 805 806 runTest(benchMode); 807 rsgClearAllRenderTargets(); 808 gRenderSurfaceW = rsgGetWidth(); 809 gRenderSurfaceH = rsgGetHeight(); 810 int size = 8; 811 // draw each frame at (8, 3/4 gRenderSurfaceH) with size 812 drawOffscreenResult((drawPos+=size)%gRenderSurfaceW, (gRenderSurfaceH * 3) / 4, size, size); 813 } 814 815 rsgFinish(); 816 817 int64_t end = rsUptimeMillis(); 818 float fps = (float)(frameCount) / ((float)(end - start)*0.001f); 819 rsDebug(testNames[benchMode], fps); 820 gResultBuffer[benchMode] = fps; 821 drawOffscreenResult(0, 0, 822 gRenderSurfaceW / 2, 823 gRenderSurfaceH / 2); 824 const char* text = testNames[benchMode]; 825 int left = 0, right = 0, top = 0, bottom = 0; 826 uint width = rsgGetWidth(); 827 uint height = rsgGetHeight(); 828 rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f); 829 rsgBindFont(gFontSerif); 830 rsgMeasureText(text, &left, &right, &top, &bottom); 831 rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); 832 rsgDrawText(text, 2 -left, height - 2 + bottom); 833 834 benchMode ++; 835 836 if (benchMode == gMaxModes) { 837 rsSendToClientBlocking(RS_MSG_RESULTS_READY, gResultBuffer, gMaxModes*sizeof(float)); 838 benchMode = 0; 839 runningLoops++; 840 if ((gMaxLoops > 0) && (runningLoops > gMaxLoops) && !sendMsgFlag) { 841 //Notifiy the test to stop and get results 842 rsDebug("gMaxLoops and runningLoops: ", gMaxLoops, runningLoops); 843 rsSendToClientBlocking(RS_MSG_TEST_DONE); 844 sendMsgFlag = true; 845 } 846 } 847 848 } 849 850 static void debug() { 851 gDt = rsGetDt(); 852 853 rsgFinish(); 854 runTest(benchMode); 855 } 856 857 int root(void) { 858 gRenderSurfaceW = rsgGetWidth(); 859 gRenderSurfaceH = rsgGetHeight(); 860 rsgClearColor(0.2f, 0.2f, 0.2f, 1.0f); 861 rsgClearDepth(1.0f); 862 if(!checkInit()) { 863 return 1; 864 } 865 866 if (gIsDebugMode) { 867 debug(); 868 } else { 869 benchmark(); 870 } 871 872 return 1; 873 } 874