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.magicsmoke) 18 19#include "rs_graphics.rsh" 20 21#define RSID_NOISESRC1 1 22#define RSID_NOISESRC2 2 23#define RSID_NOISESRC3 3 24#define RSID_NOISESRC4 4 25#define RSID_NOISESRC5 5 26#define RSID_NOISEDST1 6 27#define RSID_NOISEDST2 7 28#define RSID_NOISEDST3 8 29#define RSID_NOISEDST4 9 30#define RSID_NOISEDST5 10 31 32// State set from java 33float gXOffset; 34float gYOffset; 35int gPreset; 36int gTextureMask; 37int gRotate; 38int gTextureSwap; 39int gProcessTextureMode; 40int gBackCol; 41int gLowCol; 42int gHighCol; 43float gAlphaMul; 44int gPreMul; 45 46typedef struct VertexShaderConstants_s { 47 float4 layer0; 48 float4 layer1; 49 float4 layer2; 50 float4 layer3; 51 float4 layer4; 52 float2 panoffset; 53} VertexShaderConstants; 54VertexShaderConstants *gVSConstants; 55 56typedef struct FragmentShaderConstants_s { 57 float4 clearColor; 58} FragmentShaderConstants; 59FragmentShaderConstants *gFSConstants; 60 61typedef struct VertexInputs_s { 62 float4 position; 63 float2 texture0; 64} VertexInputs; 65VertexInputs *gVS; 66 67 68rs_program_fragment gPF5tex; 69rs_program_vertex gPV5tex; 70rs_program_fragment gPF4tex; 71rs_program_vertex gPV4tex; 72 73rs_program_store gPStore; 74 75rs_allocation gTnoise1; 76rs_allocation gTnoise2; 77rs_allocation gTnoise3; 78rs_allocation gTnoise4; 79rs_allocation gTnoise5; 80 81int *gNoisesrc1; 82int *gNoisesrc2; 83int *gNoisesrc3; 84int *gNoisesrc4; 85int *gNoisesrc5; 86 87int *gNoisedst1; 88int *gNoisedst2; 89int *gNoisedst3; 90int *gNoisedst4; 91int *gNoisedst5; 92 93// Local script variables 94static float xshift[5]; 95static float rotation[5]; 96static float scale[5]; 97static float alphafactor; 98static int currentpreset; 99static int lastuptime; 100static float timedelta; 101static float4 clearColor = {0.5f, 0.0f, 0.0f, 1.0f}; 102static int countTextures() 103{ 104 int pos = 0; 105 for (int i = 0; i < 5; i++) 106 { 107 if (gTextureMask & (1<<i)) 108 pos++; 109 } 110 return pos; 111} 112#define rotate(s, a) \ 113do { \ 114 float __agl = (3.1415927f / 180.0f) * a; \ 115 s.x = sin(__agl); \ 116 s.y = cos(__agl); \ 117} while (0) 118 119static void update() 120{ 121 rs_program_vertex pv; 122 pv = gPV5tex; 123 rs_program_fragment pf; 124 pf = gPF5tex; 125 126 if (countTextures() == 4) 127 { 128 pv = gPV4tex; 129 pf = gPF4tex; 130 } 131 rsgBindProgramFragment(pf); 132 rsgBindProgramVertex(pv); 133 rsgBindProgramStore(gPStore); 134 135 rotate(gVSConstants->layer0, rotation[0]); 136 rotate(gVSConstants->layer1, rotation[1]); 137 rotate(gVSConstants->layer2, rotation[2]); 138 rotate(gVSConstants->layer3, rotation[3]); 139 rotate(gVSConstants->layer4, rotation[4]); 140 141 gVSConstants->layer0.w = xshift[0]; 142 gVSConstants->layer1.w = xshift[1]; 143 gVSConstants->layer2.w = xshift[2]; 144 gVSConstants->layer3.w = xshift[3]; 145 gVSConstants->layer4.w = xshift[4]; 146 147 float m = 0.35f; 148 gVSConstants->layer0.z = m * scale[0]; 149 gVSConstants->layer1.z = m * scale[1]; 150 gVSConstants->layer2.z = m * scale[2]; 151 gVSConstants->layer3.z = m * scale[3]; 152 gVSConstants->layer4.z = m * scale[4]; 153 154 gVSConstants->panoffset.x = gXOffset; 155 gVSConstants->panoffset.y = -gYOffset; 156 157 gFSConstants->clearColor = clearColor; 158 159 int pos = 0; 160 for (int i = 0; i < 5; i++) 161 { 162 if (gTextureMask & (1<<i)) 163 { 164 switch (i) 165 { 166 case 0: rsgBindTexture(pf, pos, gTextureSwap != 0 ? gTnoise5 : gTnoise1); break; 167 case 1: rsgBindTexture(pf, pos, gTnoise2); break; 168 case 2: rsgBindTexture(pf, pos, gTnoise3); break; 169 case 3: rsgBindTexture(pf, pos, gTnoise4); break; 170 case 4: rsgBindTexture(pf, pos, gTnoise5); break; 171 default: break; 172 } 173 pos++; 174 } 175 } 176} 177 178static void drawClouds() { 179 if (gRotate != 0) 180 { 181 rotation[0] += 0.100f * timedelta; 182 rotation[1] += 0.102f * timedelta; 183 rotation[2] += 0.106f * timedelta; 184 rotation[3] += 0.114f * timedelta; 185 rotation[4] += 0.123f * timedelta; 186 } 187 188 int mask = gTextureMask; 189 if (mask & 1) { 190 xshift[0] += 0.00100f * timedelta; 191 } 192 if (mask & 2) { 193 xshift[1] += 0.00106f * timedelta; 194 } 195 if (mask & 4) { 196 xshift[2] += 0.00114f * timedelta; 197 } 198 if (mask & 8) { 199 xshift[3] += 0.00118f * timedelta; 200 } 201 if (mask & 16) { 202 xshift[4] += 0.00127f * timedelta; 203 } 204 205 update(); 206 207 float z = 0; 208 rsgDrawQuad( 209 -1.0f, -1.0f, z, 210 1.0f, -1.0f, z, 211 1.0f, 1.0f, z, 212 -1.0f, 1.0f, z 213 ); 214 215 // Make sure the texture coordinates don't continuously increase 216 int i; 217 for(i = 0; i < 5; i++) { 218 if (xshift[i] > 1.f) { 219 xshift[i] -= floor(xshift[i]); 220 } 221 } 222 // Make sure the rotation angles don't continuously increase 223 for(i = 0; i < 5; i++) { 224 if (rotation[i] > 360.f) { 225 float multiplier = floor(rotation[i]/360.f); 226 rotation[i] -= 360.f * multiplier; 227 } 228 } 229} 230 231static int premul(int rgb, int a) { 232 int r = (rgb >> 16) * a + 1; 233 r = (r + (r >> 8)) >> 8; 234 int g = ((rgb >> 8) & 0xff) * a + 1; 235 g = (g + (g >> 8)) >> 8; 236 int b = (rgb & 0xff) * a + 1; 237 b = (b + (b >> 8)) >> 8; 238 return r << 16 | g << 8 | b; 239} 240 241 242static void makeTexture(int *src, int *dst, rs_allocation rsid) { 243 244 int x; 245 int y; 246 int pm = gPreMul; 247 248 if (gProcessTextureMode == 1) { 249 int lowcol = gLowCol; 250 int highcol = gHighCol; 251 252 for (y=0;y<256;y++) { 253 for (x=0;x<256;x++) { 254 int pix = src[y*256+x]; 255 int lum = pix & 0x00ff; 256 int newpix; 257 if (lum < 128) { 258 newpix = lowcol; 259 int newalpha = 255 - (lum * 2); 260 newalpha /= alphafactor; 261 if (pm) newpix = premul(newpix, newalpha); 262 newpix = newpix | (newalpha << 24); 263 } else { 264 newpix = highcol; 265 int newalpha = (lum - 128) * 2; 266 newalpha /= alphafactor; 267 if (pm) newpix = premul(newpix, newalpha); 268 newpix = newpix | (newalpha << 24); 269 } 270 // have ARGB, need ABGR 271 newpix = (newpix & 0xff00ff00) | ((newpix & 0xff) << 16) | ((newpix >> 16) & 0xff); 272 dst[y*256+x] = newpix; 273 } 274 } 275 alphafactor *= gAlphaMul; 276 } else if (gProcessTextureMode == 2) { 277 int lowcol = gLowCol; 278 int highcol = gHighCol; 279 float scale = 255.f / (255.f - lowcol); 280 281 for (y=0;y<256;y++) { 282 for (x=0;x<256;x++) { 283 int pix = src[y*256+x]; 284 int alpha = pix & 0x00ff; 285 if (alpha < lowcol) { 286 alpha = 0; 287 } else { 288 alpha = (alpha - lowcol) * scale; 289 } 290 alpha /= alphafactor; 291 int newpix = highcol; 292 if (pm) newpix = premul(newpix, alpha); 293 newpix = newpix | (alpha << 24); 294 // have ARGB, need ABGR 295 newpix = (newpix & 0xff00ff00) | ((newpix & 0xff) << 16) | ((newpix >> 16) & 0xff); 296 dst[y*256+x] = newpix; 297 } 298 } 299 alphafactor *= gAlphaMul; 300 } else if (gProcessTextureMode == 3) { 301 int lowcol = gLowCol; 302 int highcol = gHighCol; 303 float scale = 255.f / (255.f - lowcol); 304 305 for (y=0;y<256;y++) { 306 for (x=0;x<256;x++) { 307 int pix = src[y*256+x]; 308 int lum = pix & 0x00ff; 309 int newpix; 310 if (lum < 128) lum *= 2; 311 else lum = (255 - (lum - 128) * 2); 312 if (lum < 128) { 313 newpix = lowcol; 314 int newalpha = 255 - (lum * 2); 315 newalpha /= alphafactor; 316 if (pm) newpix = premul(newpix, newalpha); 317 newpix = newpix | (newalpha << 24); 318 } else { 319 newpix = highcol; 320 int newalpha = (lum - 128) * 2; 321 newalpha /= alphafactor; 322 if (pm) newpix = premul(newpix, newalpha); 323 newpix = newpix | (newalpha << 24); 324 } 325 // have ARGB, need ABGR 326 newpix = (newpix & 0xff00ff00) | ((newpix & 0xff) << 16) | ((newpix >> 16) & 0xff); 327 dst[y*256+x] = newpix; 328 } 329 } 330 alphafactor *= gAlphaMul; 331 } else { 332 for (y=0;y<256;y++) { 333 for (x=0;x<256;x++) { 334 int rgb = *src++; 335 int a = (rgb >> 24) & 0xff; 336 rgb &= 0x00ffffff; 337 rgb = premul(rgb, a); 338 int newpix = (a << 24) | rgb; 339 newpix = (newpix & 0xff00ff00) | ((newpix & 0xff) << 16) | ((newpix >> 16) & 0xff); 340 *dst++ = newpix; 341 } 342 } 343 } 344 345 rsgAllocationSyncAll(rsid); 346} 347 348static void makeTextures() { 349 alphafactor = 1.f; 350 makeTexture((int*)gNoisesrc1, (int*)gNoisedst1, gTnoise1); 351 makeTexture((int*)gNoisesrc2, (int*)gNoisedst2, gTnoise2); 352 makeTexture((int*)gNoisesrc3, (int*)gNoisedst3, gTnoise3); 353 makeTexture((int*)gNoisesrc4, (int*)gNoisedst4, gTnoise4); 354 makeTexture((int*)gNoisesrc5, (int*)gNoisedst5, gTnoise5); 355} 356 357void init() { 358 for (int i=0;i<5;i++) { 359 xshift[i] = 0.f; 360 rotation[i] = 360.f * i / 5.f; 361 } 362 363 scale[0] = 4.0f; // changed below based on preset 364 scale[1] = 3.0f; 365 scale[2] = 3.4f; 366 scale[3] = 3.8f; 367 scale[4] = 4.2f; 368 369 currentpreset = -1; 370 lastuptime = (int)rsUptimeMillis(); 371 timedelta = 0; 372} 373 374 375int root(void) { 376 int i; 377 378 int now = (int)rsUptimeMillis(); 379 timedelta = ((float)(now - lastuptime)) / 44.f; 380 lastuptime = now; 381 if (timedelta > 3) { 382 // Limit the step adjustment factor to 3, so we don't get a sudden jump 383 // after coming back from sleep. 384 timedelta = 3; 385 } 386 387 i = gPreset; 388 if (i != currentpreset) { 389 currentpreset = i; 390 clearColor.x = ((float)((gBackCol >> 16) & 0xff)) / 255.0f; 391 clearColor.y = ((float)((gBackCol >> 8) & 0xff)) / 255.0f; 392 clearColor.z = ((float)(gBackCol & 0xff)) / 255.0f; 393 makeTextures(); 394 } 395 396 if (gTextureSwap != 0) { 397 scale[0] = .25f; 398 } else { 399 scale[0] = 4.f; 400 } 401 drawClouds(); 402 403 return 55; 404} 405