• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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