Home | History | Annotate | Download | only in nexus
      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.wallpaper.nexus)
     18 
     19 #include "rs_graphics.rsh"
     20 #pragma stateVertex(parent)
     21 
     22 #define MAX_PULSES           20
     23 #define MAX_EXTRAS           40
     24 #define PULSE_SIZE           14 // Size in pixels of a cell
     25 #define HALF_PULSE_SIZE      7
     26 #define GLOW_SIZE            64 // Size of the leading glow in pixels
     27 #define HALF_GLOW_SIZE       32
     28 #define SPEED                0.2f // (200 / 1000) Pixels per ms
     29 #define SPEED_DELTA_MIN      0.7f
     30 #define SPEED_DELTA_MAX      1.7f
     31 #define PULSE_NORMAL         0
     32 #define PULSE_EXTRA          1
     33 #define TRAIL_SIZE           40 // Number of cells in a trail
     34 #define MAX_DELAY          2000 // Delay between a pulse going offscreen and restarting
     35 
     36 typedef struct pulse_s {
     37     int pulseType;
     38     float originX;
     39     float originY;
     40     int color;
     41     int startTime;
     42     float dx;
     43     float dy;
     44     float scale;
     45     int active;
     46 } pulse_t;
     47 
     48 static pulse_t gPulses[MAX_PULSES];
     49 static pulse_t gExtras[MAX_EXTRAS];
     50 static int gNow;
     51 static int gWidth;
     52 static int gHeight;
     53 static int gRotate;
     54 
     55 float gWorldScaleX;
     56 float gWorldScaleY;
     57 float gXOffset;
     58 int gIsPreview;
     59 int gMode;
     60 
     61 rs_program_fragment gPFTexture;
     62 rs_program_store gPSBlend;
     63 rs_program_fragment gPFTexture565;
     64 
     65 rs_allocation gTBackground;
     66 rs_allocation gTPulse;
     67 rs_allocation gTGlow;
     68 
     69 static void setColor(int c) {
     70     if (gMode == 1) {
     71         // sholes red
     72         rsgProgramFragmentConstantColor(gPFTexture, 0.9f, 0.1f, 0.1f, 0.8f);
     73     } else if (c == 0) {
     74         // red
     75         rsgProgramFragmentConstantColor(gPFTexture, 1.0f, 0.0f, 0.0f, 0.8f);
     76     } else if (c == 1) {
     77         // green
     78         rsgProgramFragmentConstantColor(gPFTexture, 0.0f, 0.8f, 0.0f, 0.8f);
     79     } else if (c == 2) {
     80         // blue
     81         rsgProgramFragmentConstantColor(gPFTexture, 0.0f, 0.4f, 0.9f, 0.8f);
     82     } else if (c == 3) {
     83         // yellow
     84         rsgProgramFragmentConstantColor(gPFTexture, 1.0f, 0.8f, 0.0f, 0.8f);
     85     }
     86 }
     87 
     88 static void initPulse(struct pulse_s * pulse, int pulseType) {
     89     float scale = rsRand(SPEED_DELTA_MIN, SPEED_DELTA_MAX);
     90     pulse->scale = scale;
     91     gWidth = rsgGetWidth();
     92     gHeight = rsgGetHeight();
     93     if (rsRand(1.f) > 0.5f) {
     94         pulse->originX = rsRand(gWidth * 2 / PULSE_SIZE) * PULSE_SIZE;
     95         pulse->dx = 0;
     96         if (rsRand(1.f) > 0.5f) {
     97             // Top
     98             pulse->originY = 0;
     99             pulse->dy = scale;
    100         } else {
    101             // Bottom
    102             pulse->originY = gHeight / scale;
    103             pulse->dy = -scale;
    104         }
    105     } else {
    106         pulse->originY = rsRand(gHeight / PULSE_SIZE) * PULSE_SIZE;
    107         pulse->dy = 0;
    108         if (rsRand(1.f) > 0.5f) {
    109             // Left
    110             pulse->originX = 0;
    111             pulse->dx = scale;
    112         } else {
    113             // Right
    114             pulse->originX = gWidth * 2 / scale;
    115             pulse->dx = -scale;
    116         }
    117     }
    118     pulse->startTime = gNow + rsRand(MAX_DELAY);
    119 
    120     pulse->color = rsRand(4);
    121 
    122     pulse->pulseType = pulseType;
    123     if (pulseType == PULSE_EXTRA) {
    124         pulse->active = 0;
    125     } else {
    126         pulse->active = 1;
    127     }
    128 }
    129 
    130 void initPulses() {
    131     gNow = (int)rsUptimeMillis();
    132     int i;
    133     for (i=0; i<MAX_PULSES; i++) {
    134         initPulse(&gPulses[i], PULSE_NORMAL);
    135     }
    136     for (i=0; i<MAX_EXTRAS; i++) {
    137         struct pulse_s * p = &gExtras[i];
    138         p->pulseType = PULSE_EXTRA;
    139         p->active = 0;
    140     }
    141 }
    142 
    143 static void drawBackground() {
    144     rsgBindProgramFragment(gPFTexture565);
    145     rsgBindTexture(gPFTexture565, 0, gTBackground);
    146     if (gRotate) {
    147         rsgDrawRect(0.0f, 0.0f, gHeight*2, gWidth, 0.0f);
    148     } else {
    149         rsgDrawRect(0.0f, 0.0f, gWidth*2, gHeight, 0.0f);
    150     }
    151 }
    152 
    153 static void drawPulses(pulse_t * pulseSet, int setSize) {
    154     rsgBindProgramFragment(gPFTexture);
    155     rsgBindProgramStore(gPSBlend);
    156 
    157     rs_matrix4x4 matrix;
    158     rs_matrix4x4 modelMatrix;
    159     for (int i=0; i<setSize; i++) {
    160         struct pulse_s * p = &pulseSet[i];
    161         int delta = gNow - p->startTime;
    162 
    163         if (p->active != 0 && delta >= 0) {
    164         
    165             rsMatrixLoadIdentity(&modelMatrix);
    166             if (gRotate) {
    167                 //matrixLoadRotate(modelMatrix, 90.0f, 0.0f, 0.0f, 1.0f);
    168                 //matrixTranslate(modelMatrix, 0.0f, -height, 1.0f);
    169                 // XXX: HAX: do not slide display in landscape
    170             } else {
    171                  rsMatrixTranslate(&modelMatrix, -(gXOffset * gWidth), 0, 0);
    172             }
    173             rsMatrixScale(&modelMatrix, p->scale * gWorldScaleX, p->scale * gWorldScaleY, 1.0f);
    174             rsgProgramVertexLoadModelMatrix(&modelMatrix);
    175 
    176            float x = p->originX + (p->dx * SPEED * delta);
    177            float y = p->originY + (p->dy * SPEED * delta);
    178 
    179            rsMatrixLoadIdentity(&matrix);
    180            if (p->dx < 0) {
    181                rsgProgramVertexLoadTextureMatrix(&matrix);
    182                float xx = x + (TRAIL_SIZE * PULSE_SIZE);
    183                if (xx <= 0) {
    184                    initPulse(p, p->pulseType);
    185                } else {
    186                    setColor(p->color);
    187                    rsgBindTexture(gPFTexture, 0, gTPulse);
    188                    rsgDrawRect(x, y, xx, y + PULSE_SIZE, 0.0f);
    189                    rsgBindTexture(gPFTexture, 0, gTGlow);
    190                    rsgDrawRect(x + HALF_PULSE_SIZE - HALF_GLOW_SIZE,
    191                        y + HALF_PULSE_SIZE - HALF_GLOW_SIZE,
    192                        x + HALF_PULSE_SIZE + HALF_GLOW_SIZE,
    193                        y + HALF_PULSE_SIZE + HALF_GLOW_SIZE,
    194                        0.0f);
    195                }
    196            } else if (p->dx > 0) {
    197                x += PULSE_SIZE; // need to start on the other side of this cell
    198                rsMatrixRotate(&matrix, 180.0f, 0.0f, 0.0f, 1.0f);
    199                rsgProgramVertexLoadTextureMatrix(&matrix);
    200                float xx = x - (TRAIL_SIZE * PULSE_SIZE);
    201               if (xx >= gWidth * 2) {
    202                   initPulse(p, p->pulseType);
    203                } else {
    204                    setColor(p->color);
    205                    rsgBindTexture(gPFTexture, 0, gTPulse);
    206                    rsgDrawRect(xx, y, x, y + PULSE_SIZE, 0.0f);
    207                    rsgBindTexture(gPFTexture, 0, gTGlow);
    208                    rsgDrawRect(x - HALF_PULSE_SIZE - HALF_GLOW_SIZE,
    209                        y + HALF_PULSE_SIZE - HALF_GLOW_SIZE,
    210                        x - HALF_PULSE_SIZE + HALF_GLOW_SIZE,
    211                        y + HALF_PULSE_SIZE + HALF_GLOW_SIZE,
    212                        0.0f);
    213                }
    214            } else if (p->dy < 0) {
    215                rsMatrixRotate(&matrix, -90.0f, 0.0f, 0.0f, 1.0f);
    216                rsgProgramVertexLoadTextureMatrix(&matrix);
    217                float yy = y + (TRAIL_SIZE * PULSE_SIZE);
    218                if (yy <= 0) {
    219                   initPulse(p, p->pulseType);
    220                } else {
    221                    setColor(p->color);
    222                    rsgBindTexture(gPFTexture, 0, gTPulse);
    223                    rsgDrawRect(x, y, x + PULSE_SIZE, yy, 0.0f);
    224                    rsgBindTexture(gPFTexture, 0, gTGlow);
    225                    rsgDrawRect(x + HALF_PULSE_SIZE - HALF_GLOW_SIZE,
    226                        y + HALF_PULSE_SIZE - HALF_GLOW_SIZE,
    227                        x + HALF_PULSE_SIZE + HALF_GLOW_SIZE,
    228                        y + HALF_PULSE_SIZE + HALF_GLOW_SIZE,
    229                        0.0f);
    230                }
    231            } else if (p->dy > 0) {
    232             y += PULSE_SIZE; // need to start on the other side of this cell
    233                rsMatrixRotate(&matrix, 90.0f, 0.0f, 0.0f, 1.0f);
    234                rsgProgramVertexLoadTextureMatrix(&matrix);
    235                float yy = y - (TRAIL_SIZE * PULSE_SIZE);
    236                if (yy >= gHeight) {
    237                   initPulse(p, p->pulseType);
    238                } else {
    239                    setColor(p->color);
    240                    rsgBindTexture(gPFTexture, 0, gTPulse);
    241                    rsgDrawRect(x, yy, x + PULSE_SIZE, y, 0.0f);
    242                    rsgBindTexture(gPFTexture, 0, gTGlow);
    243                    rsgDrawRect(x + HALF_PULSE_SIZE - HALF_GLOW_SIZE,
    244                        y - HALF_PULSE_SIZE - HALF_GLOW_SIZE,
    245                        x + HALF_PULSE_SIZE + HALF_GLOW_SIZE,
    246                        y - HALF_PULSE_SIZE + HALF_GLOW_SIZE,
    247                        0.0f);
    248                }
    249            }
    250        }
    251     }
    252 
    253     rsMatrixLoadIdentity(&matrix);
    254     rsgProgramVertexLoadTextureMatrix(&matrix);
    255 }
    256 
    257 void addTap(int x, int y) {
    258     int count = 0;
    259     int color = rsRand(4);
    260     float scale = rsRand(0.9f, 1.9f);
    261     x = (x / PULSE_SIZE) * PULSE_SIZE;
    262     y = (y / PULSE_SIZE) * PULSE_SIZE;
    263     for (int i=0; i<MAX_EXTRAS; i++) {
    264         struct pulse_s * p = &gExtras[i];
    265         if (p->active == 0) {
    266             p->originX = x/scale;
    267             p->originY = y/scale;
    268             p->scale = scale;
    269 
    270             if (count == 0) {
    271                 p->dx = scale;
    272                 p->dy = 0.0f;
    273             } else if (count == 1) {
    274                 p->dx = -scale;
    275                 p->dy = 0.0f;
    276             } else if (count == 2) {
    277                 p->dx = 0.0f;
    278                 p->dy = scale;
    279             } else if (count == 3) {
    280                 p->dx = 0.0f;
    281                 p->dy = -scale;
    282             }
    283 
    284             p->active = 1;
    285             p->color = color;
    286             color++;
    287             if (color >= 4) {
    288                 color = 0;
    289             }
    290             p->startTime = gNow;
    291             count++;
    292             if (count == 4) {
    293                 break;
    294             }
    295         }
    296     }
    297 }
    298 
    299 int root() {
    300     rsgClearColor(0.f, 0.f, 0.f, 1.f);
    301 
    302     gWidth = rsgGetWidth();
    303     gHeight = rsgGetHeight();
    304     gRotate = gWidth > gHeight ? 1 : 0;
    305 
    306     gNow = (int)rsUptimeMillis();
    307 
    308     rs_matrix4x4 matrix;
    309     rsMatrixLoadIdentity(&matrix);
    310     rsMatrixScale(&matrix, gWorldScaleX, gWorldScaleY, 1.0f);
    311 
    312     if (gRotate) {
    313         //matrixLoadRotate(matrix, 90.0f, 0.0f, 0.0f, 1.0f);
    314         //matrixTranslate(matrix, 0.0f, -height, 1.0f);
    315         // XXX: HAX: do not slide display in landscape
    316     } else {
    317          rsMatrixTranslate(&matrix, -(gXOffset * gWidth), 0, 0);
    318     }
    319 
    320     rsgProgramVertexLoadModelMatrix(&matrix);
    321 
    322     drawBackground();
    323     drawPulses(gPulses, MAX_PULSES);
    324     drawPulses(gExtras, MAX_EXTRAS);
    325 
    326     return 45;
    327 }
    328