Home | History | Annotate | Download | only in magicsmoke
      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
     33 float gXOffset;
     34 float gYOffset;
     35 int   gPreset;
     36 int   gTextureMask;
     37 int   gRotate;
     38 int   gTextureSwap;
     39 int   gProcessTextureMode;
     40 int   gBackCol;
     41 int   gLowCol;
     42 int   gHighCol;
     43 float gAlphaMul;
     44 int   gPreMul;
     45 
     46 typedef struct VertexShaderConstants_s {
     47     float4 layer0;
     48     float4 layer1;
     49     float4 layer2;
     50     float4 layer3;
     51     float4 layer4;
     52     float2 panoffset;
     53 } VertexShaderConstants;
     54 VertexShaderConstants *gVSConstants;
     55 
     56 typedef struct FragmentShaderConstants_s {
     57     float4 clearColor;
     58 } FragmentShaderConstants;
     59 FragmentShaderConstants *gFSConstants;
     60 
     61 typedef struct VertexInputs_s {
     62     float4 position;
     63     float2 texture0;
     64 } VertexInputs;
     65 VertexInputs *gVS;
     66 
     67 
     68 rs_program_fragment gPF5tex;
     69 rs_program_vertex gPV5tex;
     70 rs_program_fragment gPF4tex;
     71 rs_program_vertex gPV4tex;
     72 
     73 rs_program_store gPStore;
     74 
     75 rs_allocation gTnoise1;
     76 rs_allocation gTnoise2;
     77 rs_allocation gTnoise3;
     78 rs_allocation gTnoise4;
     79 rs_allocation gTnoise5;
     80 
     81 int *gNoisesrc1;
     82 int *gNoisesrc2;
     83 int *gNoisesrc3;
     84 int *gNoisesrc4;
     85 int *gNoisesrc5;
     86 
     87 int *gNoisedst1;
     88 int *gNoisedst2;
     89 int *gNoisedst3;
     90 int *gNoisedst4;
     91 int *gNoisedst5;
     92 
     93 // Local script variables
     94 static float xshift[5];
     95 static float rotation[5];
     96 static float scale[5];
     97 static float alphafactor;
     98 static int currentpreset;
     99 static int lastuptime;
    100 static float timedelta;
    101 static float4 clearColor = {0.5f, 0.0f, 0.0f, 1.0f};
    102 static 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) \
    113 do { \
    114     float __agl = (3.1415927f / 180.0f) * a; \
    115     s.x = sin(__agl); \
    116     s.y = cos(__agl); \
    117 } while (0)
    118 
    119 static 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 
    178 static 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 
    231 static 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 
    242 static 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 
    348 static 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 
    357 void 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 
    375 int 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