• 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 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