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