1 // Copyright (C) 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 // Parameters for galaxy live wallpaper 24 rs_allocation gTSpace; 25 rs_allocation gTLight1; 26 rs_allocation gTFlares; 27 rs_mesh gParticlesMesh; 28 29 rs_program_fragment gPFBackground; 30 rs_program_fragment gPFStars; 31 rs_program_vertex gPVStars; 32 rs_program_vertex gPVBkProj; 33 rs_program_store gPSLights; 34 35 float gXOffset = 0.5f; 36 37 #define ELLIPSE_RATIO 0.892f 38 #define PI 3.1415f 39 #define TWO_PI 6.283f 40 #define ELLIPSE_TWIST 0.023333333f 41 42 static float angle = 50.f; 43 static int gOldWidth; 44 static int gOldHeight; 45 static int gWidth; 46 static int gHeight; 47 static float gSpeed[12000]; 48 static int gGalaxyRadius = 300; 49 static rs_allocation gParticlesBuffer; 50 51 typedef struct __attribute__((packed, aligned(4))) Particle { 52 uchar4 color; 53 float3 position; 54 } Particle_t; 55 Particle_t *Particles; 56 57 typedef struct VpConsts { 58 rs_matrix4x4 Proj; 59 rs_matrix4x4 MVP; 60 } VpConsts_t; 61 VpConsts_t *vpConstants; 62 // End of parameters for galaxy live wallpaper 63 64 rs_program_vertex gProgVertex; 65 rs_program_fragment gProgFragmentColor; 66 rs_program_fragment gProgFragmentTexture; 67 68 rs_program_store gProgStoreBlendAlpha; 69 70 rs_allocation gTexOpaque; 71 rs_allocation gTexTorus; 72 rs_allocation gTexGlobe; 73 74 typedef struct ListAllocs_s { 75 rs_allocation item; 76 } ListAllocs; 77 78 ListAllocs *gTexList100; 79 ListAllocs *gSampleTextList100; 80 ListAllocs *gListViewText; 81 82 rs_mesh gSingleMesh; 83 84 rs_font gFontSans; 85 86 rs_sampler gLinearClamp; 87 88 typedef struct UiTestData_s { 89 int testId; 90 int user1; 91 int user2; 92 int user3; 93 } UiTestData; 94 UiTestData *gData; 95 96 static float gDt = 0; 97 98 99 void init() { 100 } 101 102 static int gRenderSurfaceW; 103 static int gRenderSurfaceH; 104 105 static void bindProgramVertexOrtho() { 106 // Default vertex shader 107 rsgBindProgramVertex(gProgVertex); 108 // Setup the projection matrix 109 rs_matrix4x4 proj; 110 rsMatrixLoadOrtho(&proj, 0, gRenderSurfaceW, gRenderSurfaceH, 0, -500, 500); 111 rsgProgramVertexLoadProjectionMatrix(&proj); 112 } 113 114 /** 115 * Methods to draw the galaxy live wall paper 116 */ 117 static float mapf(float minStart, float minStop, float maxStart, float maxStop, float value) { 118 return maxStart + (maxStart - maxStop) * ((value - minStart) / (minStop - minStart)); 119 } 120 121 /** 122 * Helper function to generate the stars. 123 */ 124 static float randomGauss() { 125 float x1; 126 float x2; 127 float w = 2.f; 128 129 while (w >= 1.0f) { 130 x1 = rsRand(2.0f) - 1.0f; 131 x2 = rsRand(2.0f) - 1.0f; 132 w = x1 * x1 + x2 * x2; 133 } 134 135 w = sqrt(-2.0f * log(w) / w); 136 return x1 * w; 137 } 138 139 /** 140 * Generates the properties for a given star. 141 */ 142 static void createParticle(Particle_t *part, int idx, float scale) { 143 float d = fabs(randomGauss()) * gGalaxyRadius * 0.5f + rsRand(64.0f); 144 float id = d / gGalaxyRadius; 145 float z = randomGauss() * 0.4f * (1.0f - id); 146 float p = -d * ELLIPSE_TWIST; 147 148 if (d < gGalaxyRadius * 0.33f) { 149 part->color.x = (uchar) (220 + id * 35); 150 part->color.y = 220; 151 part->color.z = 220; 152 } else { 153 part->color.x = 180; 154 part->color.y = 180; 155 part->color.z = (uchar) clamp(140.f + id * 115.f, 140.f, 255.f); 156 } 157 // Stash point size * 10 in Alpha 158 part->color.w = (uchar) (rsRand(1.2f, 2.1f) * 60); 159 160 if (d > gGalaxyRadius * 0.15f) { 161 z *= 0.6f * (1.0f - id); 162 } else { 163 z *= 0.72f; 164 } 165 166 // Map to the projection coordinates (viewport.x = -1.0 -> 1.0) 167 d = mapf(-4.0f, gGalaxyRadius + 4.0f, 0.0f, scale, d); 168 169 part->position.x = rsRand(TWO_PI); 170 part->position.y = d; 171 gSpeed[idx] = rsRand(0.0015f, 0.0025f) * (0.5f + (scale / d)) * 0.8f; 172 173 part->position.z = z / 5.0f; 174 } 175 176 /** 177 * Initialize all the starts, called from Java 178 */ 179 void initParticles() { 180 Particle_t *part = Particles; 181 float scale = gGalaxyRadius / (gWidth * 0.5f); 182 int count = rsAllocationGetDimX(gParticlesBuffer); 183 for (int i = 0; i < count; i ++) { 184 createParticle(part, i, scale); 185 part++; 186 } 187 } 188 189 static void drawSpace() { 190 rsgBindProgramFragment(gPFBackground); 191 rsgBindTexture(gPFBackground, 0, gTSpace); 192 rsgDrawQuadTexCoords( 193 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 194 gWidth, 0.0f, 0.0f, 2.0f, 1.0f, 195 gWidth, gHeight, 0.0f, 2.0f, 0.0f, 196 0.0f, gHeight, 0.0f, 0.0f, 0.0f); 197 } 198 199 static void drawLights() { 200 rsgBindProgramVertex(gPVBkProj); 201 rsgBindProgramFragment(gPFBackground); 202 rsgBindTexture(gPFBackground, 0, gTLight1); 203 204 float scale = 512.0f / gWidth; 205 float x = -scale - scale * 0.05f; 206 float y = -scale; 207 208 scale *= 2.0f; 209 210 rsgDrawQuad(x, y, 0.0f, 211 x + scale * 1.1f, y, 0.0f, 212 x + scale * 1.1f, y + scale, 0.0f, 213 x, y + scale, 0.0f); 214 } 215 216 static void drawParticles(float offset) { 217 float a = offset * angle; 218 float absoluteAngle = fabs(a); 219 220 rs_matrix4x4 matrix; 221 rsMatrixLoadTranslate(&matrix, 0.0f, 0.0f, 10.0f - 6.0f * absoluteAngle / 50.0f); 222 if (gHeight > gWidth) { 223 rsMatrixScale(&matrix, 6.6f, 6.0f, 1.0f); 224 } else { 225 rsMatrixScale(&matrix, 12.6f, 12.0f, 1.0f); 226 } 227 rsMatrixRotate(&matrix, absoluteAngle, 1.0f, 0.0f, 0.0f); 228 rsMatrixRotate(&matrix, a, 0.0f, 0.4f, 0.1f); 229 rsMatrixLoad(&vpConstants->MVP, &vpConstants->Proj); 230 rsMatrixMultiply(&vpConstants->MVP, &matrix); 231 rsgAllocationSyncAll(rsGetAllocation(vpConstants)); 232 233 rsgBindProgramVertex(gPVStars); 234 rsgBindProgramFragment(gPFStars); 235 rsgBindProgramStore(gPSLights); 236 rsgBindTexture(gPFStars, 0, gTFlares); 237 238 Particle_t *vtx = Particles; 239 int count = rsAllocationGetDimX(gParticlesBuffer); 240 for (int i = 0; i < count; i++) { 241 vtx->position.x = vtx->position.x + gSpeed[i]; 242 vtx++; 243 } 244 245 rsgDrawMesh(gParticlesMesh); 246 } 247 /* end of methods for drawing galaxy */ 248 249 // Display sample images in a mesh with different texture 250 static void displayIcons(int meshMode) { 251 bindProgramVertexOrtho(); 252 253 // Fragment shader with texture 254 rsgBindProgramStore(gProgStoreBlendAlpha); 255 rsgBindProgramFragment(gProgFragmentTexture); 256 rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); 257 rsgBindTexture(gProgFragmentTexture, 0, gTexTorus); 258 rsgDrawQuadTexCoords( 259 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 260 0.0f, gRenderSurfaceH, 0.0f, 0.0f, 1.0f, 261 gRenderSurfaceW, gRenderSurfaceH, 0.0f, 1.0f, 1.0f, 262 gRenderSurfaceW, 0.0f, 0.0f, 1.0f, 0.0f); 263 264 int meshCount = (int)pow(10.0f, (float)(meshMode + 1)); 265 266 float wSize = gRenderSurfaceW/(float)meshCount; 267 float hSize = gRenderSurfaceH/(float)meshCount; 268 rs_matrix4x4 matrix; 269 rsMatrixLoadScale(&matrix, wSize, hSize, 1.0); 270 271 float yPos = 0; 272 float yPad = hSize / 2; 273 float xPad = wSize / 2; 274 for (int y = 0; y < meshCount; y++) { 275 yPos = y * hSize + yPad; 276 float xPos = 0; 277 for (int x = 0; x < meshCount; x++) { 278 xPos = x * wSize + xPad; 279 rs_matrix4x4 transMatrix; 280 rsMatrixLoadTranslate(&transMatrix, xPos, yPos, 0); 281 rsMatrixMultiply(&transMatrix, &matrix); 282 rsgProgramVertexLoadModelMatrix(&transMatrix); 283 int i = (x + y * meshCount) % 100; 284 rsgBindTexture(gProgFragmentTexture, 0, gTexList100[i].item); 285 rsgDrawMesh(gSingleMesh); 286 } 287 } 288 } 289 290 // Draw meshes in a single page with top left corner coordinates (xStart, yStart) 291 static void drawMeshInPage(float xStart, float yStart, int wResolution, int hResolution) { 292 // Draw wResolution * hResolution meshes in one page 293 float wMargin = 100.0f; 294 float hMargin = 100.0f; 295 float xPad = 50.0f; 296 float yPad = 20.0f; 297 float size = 100.0f; // size of images 298 299 // font info 300 rs_font font = gFontSans; 301 rsgBindFont(font); 302 rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); 303 304 // Measure text size 305 int left = 0, right = 0, top = 0, bottom = 0; 306 rsgMeasureText(gSampleTextList100[0].item, &left, &right, &top, &bottom); 307 float textHeight = (float)(top - bottom); 308 float textWidth = (float)(right - left); 309 310 rs_matrix4x4 matrix; 311 rsMatrixLoadScale(&matrix, size, size, 1.0); 312 313 for (int y = 0; y < hResolution; y++) { 314 float yPos = yStart + hMargin + y * size + y * yPad; 315 for (int x = 0; x < wResolution; x++) { 316 float xPos = xStart + wMargin + x * size + x * xPad; 317 318 rs_matrix4x4 transMatrix; 319 rsMatrixLoadTranslate(&transMatrix, xPos + size/2, yPos + size/2, 0); 320 rsMatrixMultiply(&transMatrix, &matrix); // scale the mesh 321 rsgProgramVertexLoadModelMatrix(&transMatrix); 322 323 int i = (y * wResolution + x) % 100; 324 rsgBindTexture(gProgFragmentTexture, 0, gTexList100[i].item); 325 rsgDrawMesh(gSingleMesh); 326 rsgDrawText(gSampleTextList100[i].item, xPos, yPos + size + yPad/2 + textHeight); 327 } 328 } 329 } 330 331 // Display both images and text as shown in launcher and homepage 332 // meshMode will decide how many pages we draw 333 // meshMode = 0: draw 3 pages of meshes 334 // meshMode = 1: draw 5 pages of meshes 335 static void displayImageWithText(int wResolution, int hResolution, int meshMode) { 336 bindProgramVertexOrtho(); 337 338 // Fragment shader with texture 339 rsgBindProgramStore(gProgStoreBlendAlpha); 340 rsgBindProgramFragment(gProgFragmentTexture); 341 rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); 342 343 drawMeshInPage(0, 0, wResolution, hResolution); 344 drawMeshInPage(-1.0f*gRenderSurfaceW, 0, wResolution, hResolution); 345 drawMeshInPage(1.0f*gRenderSurfaceW, 0, wResolution, hResolution); 346 if (meshMode == 1) { 347 // draw another two pages of meshes 348 drawMeshInPage(-2.0f*gRenderSurfaceW, 0, wResolution, hResolution); 349 drawMeshInPage(2.0f*gRenderSurfaceW, 0, wResolution, hResolution); 350 } 351 } 352 353 // Display a list of text as the list view 354 static void displayListView() { 355 // set text color 356 rsgFontColor(0.9f, 0.9f, 0.9f, 1.0f); 357 rsgBindFont(gFontSans); 358 359 // get the size of the list 360 rs_allocation textAlloc; 361 textAlloc = rsGetAllocation(gListViewText); 362 int allocSize = rsAllocationGetDimX(textAlloc); 363 364 int listItemHeight = 80; 365 int yOffset = listItemHeight; 366 367 // set the color for the list divider 368 rsgBindProgramFragment(gProgFragmentColor); 369 rsgProgramFragmentConstantColor(gProgFragmentColor, 1.0, 1.0, 1.0, 1); 370 371 // draw the list with divider 372 for (int i = 0; i < allocSize; i++) { 373 if (yOffset - listItemHeight > gRenderSurfaceH) { 374 break; 375 } 376 rsgDrawRect(0, yOffset - 1, gRenderSurfaceW, yOffset, 0); 377 rsgDrawText(gListViewText[i].item, 20, yOffset - 10); 378 yOffset += listItemHeight; 379 } 380 } 381 382 static void drawGalaxy() { 383 rsgClearColor(0.f, 0.f, 0.f, 1.f); 384 gParticlesBuffer = rsGetAllocation(Particles); 385 rsgBindProgramFragment(gPFBackground); 386 387 gWidth = rsgGetWidth(); 388 gHeight = rsgGetHeight(); 389 if ((gWidth != gOldWidth) || (gHeight != gOldHeight)) { 390 initParticles(); 391 gOldWidth = gWidth; 392 gOldHeight = gHeight; 393 } 394 395 float offset = mix(-1.0f, 1.0f, gXOffset); 396 drawSpace(); 397 drawParticles(offset); 398 drawLights(); 399 } 400 401 // Display images and text with live wallpaper in the background 402 static void displayLiveWallPaper(int wResolution, int hResolution) { 403 bindProgramVertexOrtho(); 404 405 drawGalaxy(); 406 407 rsgBindProgramVertex(gProgVertex); 408 rsgBindProgramStore(gProgStoreBlendAlpha); 409 rsgBindProgramFragment(gProgFragmentTexture); 410 rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); 411 412 drawMeshInPage(0, 0, wResolution, hResolution); 413 drawMeshInPage(-1.0f*gRenderSurfaceW, 0, wResolution, hResolution); 414 drawMeshInPage(1.0f*gRenderSurfaceW, 0, wResolution, hResolution); 415 drawMeshInPage(-2.0f*gRenderSurfaceW, 0, wResolution, hResolution); 416 drawMeshInPage(2.0f*gRenderSurfaceW, 0, wResolution, hResolution); 417 } 418 419 void root(const void *v_in, void *v_out, const void *usrData, uint32_t x, uint32_t y) { 420 TestData *testData = (TestData*)usrData; 421 gRenderSurfaceW = testData->renderSurfaceW; 422 gRenderSurfaceH = testData->renderSurfaceH; 423 gDt = testData->dt; 424 425 gData = (UiTestData*)v_in; 426 427 switch(gData->testId) { 428 case 0: 429 displayIcons(gData->user1); 430 break; 431 case 1: 432 displayImageWithText(gData->user1, gData->user2, gData->user3); 433 break; 434 case 2: 435 displayListView(); 436 break; 437 case 3: 438 displayLiveWallPaper(gData->user1, gData->user2); 439 break; 440 default: 441 rsDebug("Wrong test number", 0); 442 break; 443 } 444 } 445