Alex Sakhartchouk | 1fe2ef0 | 2011-11-10 15:27:51 -0800 | [diff] [blame] | 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); |
Alex Sakhartchouk | 1fe2ef0 | 2011-11-10 15:27:51 -0800 | [diff] [blame] | 146 | |
| 147 | if (d < gGalaxyRadius * 0.33f) { |
| 148 | part->color.x = (uchar) (220 + id * 35); |
| 149 | part->color.y = 220; |
| 150 | part->color.z = 220; |
| 151 | } else { |
| 152 | part->color.x = 180; |
| 153 | part->color.y = 180; |
| 154 | part->color.z = (uchar) clamp(140.f + id * 115.f, 140.f, 255.f); |
| 155 | } |
| 156 | // Stash point size * 10 in Alpha |
| 157 | part->color.w = (uchar) (rsRand(1.2f, 2.1f) * 60); |
| 158 | |
| 159 | if (d > gGalaxyRadius * 0.15f) { |
| 160 | z *= 0.6f * (1.0f - id); |
| 161 | } else { |
| 162 | z *= 0.72f; |
| 163 | } |
| 164 | |
| 165 | // Map to the projection coordinates (viewport.x = -1.0 -> 1.0) |
| 166 | d = mapf(-4.0f, gGalaxyRadius + 4.0f, 0.0f, scale, d); |
| 167 | |
| 168 | part->position.x = rsRand(TWO_PI); |
| 169 | part->position.y = d; |
| 170 | gSpeed[idx] = rsRand(0.0015f, 0.0025f) * (0.5f + (scale / d)) * 0.8f; |
| 171 | |
| 172 | part->position.z = z / 5.0f; |
| 173 | } |
| 174 | |
| 175 | /** |
| 176 | * Initialize all the starts, called from Java |
| 177 | */ |
| 178 | void initParticles() { |
| 179 | Particle_t *part = Particles; |
| 180 | float scale = gGalaxyRadius / (gWidth * 0.5f); |
| 181 | int count = rsAllocationGetDimX(gParticlesBuffer); |
| 182 | for (int i = 0; i < count; i ++) { |
| 183 | createParticle(part, i, scale); |
| 184 | part++; |
| 185 | } |
| 186 | } |
| 187 | |
| 188 | static void drawSpace() { |
| 189 | rsgBindProgramFragment(gPFBackground); |
| 190 | rsgBindTexture(gPFBackground, 0, gTSpace); |
| 191 | rsgDrawQuadTexCoords( |
| 192 | 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, |
| 193 | gWidth, 0.0f, 0.0f, 2.0f, 1.0f, |
| 194 | gWidth, gHeight, 0.0f, 2.0f, 0.0f, |
| 195 | 0.0f, gHeight, 0.0f, 0.0f, 0.0f); |
| 196 | } |
| 197 | |
| 198 | static void drawLights() { |
| 199 | rsgBindProgramVertex(gPVBkProj); |
| 200 | rsgBindProgramFragment(gPFBackground); |
| 201 | rsgBindTexture(gPFBackground, 0, gTLight1); |
| 202 | |
| 203 | float scale = 512.0f / gWidth; |
| 204 | float x = -scale - scale * 0.05f; |
| 205 | float y = -scale; |
| 206 | |
| 207 | scale *= 2.0f; |
| 208 | |
| 209 | rsgDrawQuad(x, y, 0.0f, |
| 210 | x + scale * 1.1f, y, 0.0f, |
| 211 | x + scale * 1.1f, y + scale, 0.0f, |
| 212 | x, y + scale, 0.0f); |
| 213 | } |
| 214 | |
| 215 | static void drawParticles(float offset) { |
| 216 | float a = offset * angle; |
| 217 | float absoluteAngle = fabs(a); |
| 218 | |
| 219 | rs_matrix4x4 matrix; |
| 220 | rsMatrixLoadTranslate(&matrix, 0.0f, 0.0f, 10.0f - 6.0f * absoluteAngle / 50.0f); |
| 221 | if (gHeight > gWidth) { |
| 222 | rsMatrixScale(&matrix, 6.6f, 6.0f, 1.0f); |
| 223 | } else { |
| 224 | rsMatrixScale(&matrix, 12.6f, 12.0f, 1.0f); |
| 225 | } |
| 226 | rsMatrixRotate(&matrix, absoluteAngle, 1.0f, 0.0f, 0.0f); |
| 227 | rsMatrixRotate(&matrix, a, 0.0f, 0.4f, 0.1f); |
| 228 | rsMatrixLoad(&vpConstants->MVP, &vpConstants->Proj); |
| 229 | rsMatrixMultiply(&vpConstants->MVP, &matrix); |
| 230 | rsgAllocationSyncAll(rsGetAllocation(vpConstants)); |
| 231 | |
| 232 | rsgBindProgramVertex(gPVStars); |
| 233 | rsgBindProgramFragment(gPFStars); |
| 234 | rsgBindProgramStore(gPSLights); |
| 235 | rsgBindTexture(gPFStars, 0, gTFlares); |
| 236 | |
| 237 | Particle_t *vtx = Particles; |
| 238 | int count = rsAllocationGetDimX(gParticlesBuffer); |
| 239 | for (int i = 0; i < count; i++) { |
| 240 | vtx->position.x = vtx->position.x + gSpeed[i]; |
| 241 | vtx++; |
| 242 | } |
| 243 | |
| 244 | rsgDrawMesh(gParticlesMesh); |
| 245 | } |
| 246 | /* end of methods for drawing galaxy */ |
| 247 | |
| 248 | // Display sample images in a mesh with different texture |
| 249 | static void displayIcons(int meshMode) { |
| 250 | bindProgramVertexOrtho(); |
| 251 | |
| 252 | // Fragment shader with texture |
| 253 | rsgBindProgramStore(gProgStoreBlendAlpha); |
| 254 | rsgBindProgramFragment(gProgFragmentTexture); |
| 255 | rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); |
| 256 | rsgBindTexture(gProgFragmentTexture, 0, gTexTorus); |
| 257 | rsgDrawQuadTexCoords( |
| 258 | 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, |
| 259 | 0.0f, gRenderSurfaceH, 0.0f, 0.0f, 1.0f, |
| 260 | gRenderSurfaceW, gRenderSurfaceH, 0.0f, 1.0f, 1.0f, |
| 261 | gRenderSurfaceW, 0.0f, 0.0f, 1.0f, 0.0f); |
| 262 | |
| 263 | int meshCount = (int)pow(10.0f, (float)(meshMode + 1)); |
| 264 | |
| 265 | float wSize = gRenderSurfaceW/(float)meshCount; |
| 266 | float hSize = gRenderSurfaceH/(float)meshCount; |
| 267 | rs_matrix4x4 matrix; |
| 268 | rsMatrixLoadScale(&matrix, wSize, hSize, 1.0); |
| 269 | |
| 270 | float yPos = 0; |
| 271 | float yPad = hSize / 2; |
| 272 | float xPad = wSize / 2; |
| 273 | for (int y = 0; y < meshCount; y++) { |
| 274 | yPos = y * hSize + yPad; |
| 275 | float xPos = 0; |
| 276 | for (int x = 0; x < meshCount; x++) { |
| 277 | xPos = x * wSize + xPad; |
| 278 | rs_matrix4x4 transMatrix; |
| 279 | rsMatrixLoadTranslate(&transMatrix, xPos, yPos, 0); |
| 280 | rsMatrixMultiply(&transMatrix, &matrix); |
| 281 | rsgProgramVertexLoadModelMatrix(&transMatrix); |
| 282 | int i = (x + y * meshCount) % 100; |
| 283 | rsgBindTexture(gProgFragmentTexture, 0, gTexList100[i].item); |
| 284 | rsgDrawMesh(gSingleMesh); |
| 285 | } |
| 286 | } |
| 287 | } |
| 288 | |
| 289 | // Draw meshes in a single page with top left corner coordinates (xStart, yStart) |
| 290 | static void drawMeshInPage(float xStart, float yStart, int wResolution, int hResolution) { |
| 291 | // Draw wResolution * hResolution meshes in one page |
| 292 | float wMargin = 100.0f; |
| 293 | float hMargin = 100.0f; |
| 294 | float xPad = 50.0f; |
| 295 | float yPad = 20.0f; |
| 296 | float size = 100.0f; // size of images |
| 297 | |
| 298 | // font info |
| 299 | rs_font font = gFontSans; |
| 300 | rsgBindFont(font); |
| 301 | rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); |
| 302 | |
| 303 | // Measure text size |
| 304 | int left = 0, right = 0, top = 0, bottom = 0; |
| 305 | rsgMeasureText(gSampleTextList100[0].item, &left, &right, &top, &bottom); |
| 306 | float textHeight = (float)(top - bottom); |
Alex Sakhartchouk | 1fe2ef0 | 2011-11-10 15:27:51 -0800 | [diff] [blame] | 307 | |
| 308 | rs_matrix4x4 matrix; |
| 309 | rsMatrixLoadScale(&matrix, size, size, 1.0); |
| 310 | |
| 311 | for (int y = 0; y < hResolution; y++) { |
| 312 | float yPos = yStart + hMargin + y * size + y * yPad; |
| 313 | for (int x = 0; x < wResolution; x++) { |
| 314 | float xPos = xStart + wMargin + x * size + x * xPad; |
| 315 | |
| 316 | rs_matrix4x4 transMatrix; |
| 317 | rsMatrixLoadTranslate(&transMatrix, xPos + size/2, yPos + size/2, 0); |
| 318 | rsMatrixMultiply(&transMatrix, &matrix); // scale the mesh |
| 319 | rsgProgramVertexLoadModelMatrix(&transMatrix); |
| 320 | |
| 321 | int i = (y * wResolution + x) % 100; |
| 322 | rsgBindTexture(gProgFragmentTexture, 0, gTexList100[i].item); |
| 323 | rsgDrawMesh(gSingleMesh); |
| 324 | rsgDrawText(gSampleTextList100[i].item, xPos, yPos + size + yPad/2 + textHeight); |
| 325 | } |
| 326 | } |
| 327 | } |
| 328 | |
| 329 | // Display both images and text as shown in launcher and homepage |
| 330 | // meshMode will decide how many pages we draw |
| 331 | // meshMode = 0: draw 3 pages of meshes |
| 332 | // meshMode = 1: draw 5 pages of meshes |
| 333 | static void displayImageWithText(int wResolution, int hResolution, int meshMode) { |
| 334 | bindProgramVertexOrtho(); |
| 335 | |
| 336 | // Fragment shader with texture |
| 337 | rsgBindProgramStore(gProgStoreBlendAlpha); |
| 338 | rsgBindProgramFragment(gProgFragmentTexture); |
| 339 | rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); |
| 340 | |
| 341 | drawMeshInPage(0, 0, wResolution, hResolution); |
| 342 | drawMeshInPage(-1.0f*gRenderSurfaceW, 0, wResolution, hResolution); |
| 343 | drawMeshInPage(1.0f*gRenderSurfaceW, 0, wResolution, hResolution); |
| 344 | if (meshMode == 1) { |
| 345 | // draw another two pages of meshes |
| 346 | drawMeshInPage(-2.0f*gRenderSurfaceW, 0, wResolution, hResolution); |
| 347 | drawMeshInPage(2.0f*gRenderSurfaceW, 0, wResolution, hResolution); |
| 348 | } |
| 349 | } |
| 350 | |
| 351 | // Display a list of text as the list view |
| 352 | static void displayListView() { |
| 353 | // set text color |
| 354 | rsgFontColor(0.9f, 0.9f, 0.9f, 1.0f); |
| 355 | rsgBindFont(gFontSans); |
| 356 | |
| 357 | // get the size of the list |
| 358 | rs_allocation textAlloc; |
| 359 | textAlloc = rsGetAllocation(gListViewText); |
| 360 | int allocSize = rsAllocationGetDimX(textAlloc); |
| 361 | |
| 362 | int listItemHeight = 80; |
| 363 | int yOffset = listItemHeight; |
| 364 | |
| 365 | // set the color for the list divider |
| 366 | rsgBindProgramFragment(gProgFragmentColor); |
| 367 | rsgProgramFragmentConstantColor(gProgFragmentColor, 1.0, 1.0, 1.0, 1); |
| 368 | |
| 369 | // draw the list with divider |
| 370 | for (int i = 0; i < allocSize; i++) { |
| 371 | if (yOffset - listItemHeight > gRenderSurfaceH) { |
| 372 | break; |
| 373 | } |
| 374 | rsgDrawRect(0, yOffset - 1, gRenderSurfaceW, yOffset, 0); |
| 375 | rsgDrawText(gListViewText[i].item, 20, yOffset - 10); |
| 376 | yOffset += listItemHeight; |
| 377 | } |
| 378 | } |
| 379 | |
| 380 | static void drawGalaxy() { |
| 381 | rsgClearColor(0.f, 0.f, 0.f, 1.f); |
| 382 | gParticlesBuffer = rsGetAllocation(Particles); |
| 383 | rsgBindProgramFragment(gPFBackground); |
| 384 | |
| 385 | gWidth = rsgGetWidth(); |
| 386 | gHeight = rsgGetHeight(); |
| 387 | if ((gWidth != gOldWidth) || (gHeight != gOldHeight)) { |
| 388 | initParticles(); |
| 389 | gOldWidth = gWidth; |
| 390 | gOldHeight = gHeight; |
| 391 | } |
| 392 | |
| 393 | float offset = mix(-1.0f, 1.0f, gXOffset); |
| 394 | drawSpace(); |
| 395 | drawParticles(offset); |
| 396 | drawLights(); |
| 397 | } |
| 398 | |
| 399 | // Display images and text with live wallpaper in the background |
| 400 | static void displayLiveWallPaper(int wResolution, int hResolution) { |
| 401 | bindProgramVertexOrtho(); |
| 402 | |
| 403 | drawGalaxy(); |
| 404 | |
| 405 | rsgBindProgramVertex(gProgVertex); |
| 406 | rsgBindProgramStore(gProgStoreBlendAlpha); |
| 407 | rsgBindProgramFragment(gProgFragmentTexture); |
| 408 | rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); |
| 409 | |
| 410 | drawMeshInPage(0, 0, wResolution, hResolution); |
| 411 | drawMeshInPage(-1.0f*gRenderSurfaceW, 0, wResolution, hResolution); |
| 412 | drawMeshInPage(1.0f*gRenderSurfaceW, 0, wResolution, hResolution); |
| 413 | drawMeshInPage(-2.0f*gRenderSurfaceW, 0, wResolution, hResolution); |
| 414 | drawMeshInPage(2.0f*gRenderSurfaceW, 0, wResolution, hResolution); |
| 415 | } |
| 416 | |
| 417 | void root(const void *v_in, void *v_out, const void *usrData, uint32_t x, uint32_t y) { |
| 418 | TestData *testData = (TestData*)usrData; |
| 419 | gRenderSurfaceW = testData->renderSurfaceW; |
| 420 | gRenderSurfaceH = testData->renderSurfaceH; |
| 421 | gDt = testData->dt; |
| 422 | |
| 423 | gData = (UiTestData*)v_in; |
| 424 | |
| 425 | switch(gData->testId) { |
| 426 | case 0: |
| 427 | displayIcons(gData->user1); |
| 428 | break; |
| 429 | case 1: |
| 430 | displayImageWithText(gData->user1, gData->user2, gData->user3); |
| 431 | break; |
| 432 | case 2: |
| 433 | displayListView(); |
| 434 | break; |
| 435 | case 3: |
| 436 | displayLiveWallPaper(gData->user1, gData->user2); |
| 437 | break; |
| 438 | default: |
| 439 | rsDebug("Wrong test number", 0); |
| 440 | break; |
| 441 | } |
| 442 | } |