OSDN Git Service

DO NOT MERGE. Port Froyo livewallpaper support to eclair for droid..
authorJason Sams <rjsams@android.com>
Fri, 11 Dec 2009 01:32:28 +0000 (17:32 -0800)
committerJason Sams <rjsams@android.com>
Fri, 12 Feb 2010 02:09:56 +0000 (18:09 -0800)
Update grass to use fragment shaders.

Create struct for blade data.

Use indicies to reduce grass cpu usage.  Fix aliasing of tips of grass.

Update to new RS texture API.

Update to new RS element API.

Update to use RS generic attrib support.

Change to user attrib types.

Disable per touch logging.

Simplify the fall water script.  Remove some dead code from the java layer that was left over from the old integer mesh.

Move Fall waveform calculation to vertex shader.

Add uses-feature to the manifest.

Enable red-pulses-only mode in Nexus wallpaper.

Also load textures with CLAMP for Droid compatiblity.

Bug: 2395147
Change-Id: Id310674e1c3160a545d632b286506e55e9cbc8ad

Fix shader problems in Nexus, er, Neural Network LW.

Change-Id: I852bdf4700d61f18a006ebcf619e9d4f3b51e4cd

Fix Galaxy in landscape mode.

 Author:    Romain Guy <romainguy@android.com>
 Committer: Jason Sams <rjsams@android.com>
 On branch droid
 Changes to be committed:
   (use "git reset HEAD <file>..." to unstage)

modified:   src/com/android/wallpaper/galaxy/GalaxyRS.java

AndroidManifest.xml
res/raw/fall.rs
res/raw/galaxy.rs
res/raw/grass.rs
res/raw/nexus.rs
res/values/integers.xml [new file with mode: 0644]
src/com/android/wallpaper/fall/FallRS.java
src/com/android/wallpaper/galaxy/GalaxyRS.java
src/com/android/wallpaper/grass/GrassRS.java
src/com/android/wallpaper/nexus/NexusRS.java

index bcf1dce..22d2533 100644 (file)
@@ -21,6 +21,8 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.wallpaper">
 
+    <uses-feature android:name="android.software.live_wallpaper" />
+
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
     <uses-permission android:name="android.permission.CAMERA" />
 
index e5cd67b..e183178 100644 (file)
@@ -26,21 +26,10 @@ float skyOffsetY;
 float g_DT;
 int g_LastTime;
 
-struct vert_s {
-    float x;
-    float y;
-    float z;
-    float s;
-    float t;
-};
-
 struct drop_s {
     float ampS;
     float ampE;
     float spread;
-    float spread2;
-    float invSpread;
-    float invSpread2;
     float x;
     float y;
 };
@@ -63,9 +52,7 @@ struct Leaves_s {
 };
 
 struct Leaves_s gLeavesStore[LEAVES_COUNT];
-
 struct Leaves_s* gLeaves[LEAVES_COUNT];
-
 struct Leaves_s* gNextLeaves[LEAVES_COUNT];
 
 void init() {
@@ -75,9 +62,6 @@ void init() {
         gDrops[ct].ampS = 0;
         gDrops[ct].ampE = 0;
         gDrops[ct].spread = 1;
-        gDrops[ct].spread2 = gDrops[ct].spread * gDrops[ct].spread;
-        gDrops[ct].invSpread = 1 / gDrops[ct].spread;
-        gDrops[ct].invSpread2 = gDrops[ct].invSpread * gDrops[ct].invSpread;
     }
 }
 
@@ -107,10 +91,7 @@ void initLeaves() {
 
 void updateDrop(int ct) {
     gDrops[ct].spread += 30.f * g_DT;
-    gDrops[ct].spread2 = gDrops[ct].spread * gDrops[ct].spread;
-    gDrops[ct].invSpread = 1 / gDrops[ct].spread;
-    gDrops[ct].invSpread2 = gDrops[ct].invSpread * gDrops[ct].invSpread;
-    gDrops[ct].ampE = gDrops[ct].ampS * gDrops[ct].invSpread;
+    gDrops[ct].ampE = gDrops[ct].ampS / gDrops[ct].spread;
 }
 
 void drop(int x, int y, float s) {
@@ -131,65 +112,20 @@ void drop(int x, int y, float s) {
 }
 
 void generateRipples() {
-    int rippleMapSize = State->rippleMapSize;
-    int width = State->meshWidth;
-    int height = State->meshHeight;
-    int index = State->rippleIndex;
-    float ratio = (float)State->meshWidth / State->glWidth;
-    float xShift = State->xOffset * ratio * 2;
-
-    float *vertices = loadSimpleMeshVerticesF(NAMED_WaterMesh, 0);
-    struct vert_s *vert = (struct vert_s *)vertices;
-
-    float fw = 1.0f / width;
-    float fh = 1.0f / height;
-    int x, y, ct;
-    struct vert_s *v = vert;
-    for (y=0; y < height; y++) {
-        for (x=0; x < width; x++) {
-            struct drop_s * d = &gDrops[0];
-            float z = 0;
-
-            for (ct = 0; ct < gMaxDrops; ct++) {
-                if (d->ampE > 0.01f) {
-                    float dx = (d->x - xShift) - x;
-                    float dy = d->y - y;
-                    float dist2 = dx*dx + dy*dy;
-                    if (dist2 < d->spread2) {
-                        float dist = sqrtf(dist2);
-                        float a = d->ampE * (dist * d->invSpread);
-                        z += sinf(d->spread - dist) * a;
-                    }
-                }
-                d++;
-            }
-            v->z = z;
-            v ++;
-        }
-    }
+    int ct;
     for (ct = 0; ct < gMaxDrops; ct++) {
-        updateDrop(ct);
+        struct drop_s * d = &gDrops[ct];
+        vecF32_4_t *v = &Constants->Drop01;
+        v += ct;
+        v->x = d->x;
+        v->y = d->y;
+        v->z = d->ampE * 0.12f;
+        v->w = d->spread;
     }
+    Constants->Offset.x = State->xOffset;
 
-    v = vert;
-    for (y = 0; y < height; y += 1) {
-        for (x = 0; x < width; x += 1) {
-            struct vec3_s n1, n2, n3;
-            vec3Sub(&n1, (struct vec3_s *)&(v+1)->x, (struct vec3_s *)&v->x);
-            vec3Sub(&n2, (struct vec3_s *)&(v+width)->x, (struct vec3_s *)&v->x);
-            vec3Cross(&n3, &n1, &n2);
-
-            // Average of previous normal and N1 x N2
-            vec3Sub(&n1, (struct vec3_s *)&(v+width+1)->x, (struct vec3_s *)&v->x);
-            vec3Cross(&n2, &n1, &n2);
-            vec3Add(&n3, &n3, &n2);
-            //vec3Norm(&n3);  // Not necessary for our constrained mesh.
-
-            v->s = (float)x * fw + n3.x;// * 0.2;
-            v->t = (float)y * fh + n3.y;// * 0.2;
-            v->z = 0;
-            v += 1;
-        }
+    for (ct = 0; ct < gMaxDrops; ct++) {
+        updateDrop(ct);
     }
 }
 
@@ -357,46 +293,8 @@ void drawLeaves() {
 
 void drawRiverbed() {
     bindTexture(NAMED_PFBackground, 0, NAMED_TRiverbed);
-
-    float matrix[16];
-    matrixLoadScale(matrix, 0.5f * 960.0f / 1024.0f, -1.0f * 800.0f / 1024.0f, 1.0f);
-    matrixTranslate(matrix, State->xOffset, 0.0f, 0.0f);
-    vpLoadTextureMatrix(matrix);
-
-    drawSimpleMesh(NAMED_WaterMesh);
-
-    matrixLoadIdentity(matrix);
-    vpLoadTextureMatrix(matrix);
-}
-
-/*
-void drawSky() {
-    color(1.0f, 1.0f, 1.0f, 0.5f);
-
-    bindProgramFragment(NAMED_PFSky);
-    bindProgramFragmentStore(NAMED_PFSLeaf);
-    bindTexture(NAMED_PFSky, 0, NAMED_TSky);
-
-    float x = skyOffsetX + State->skySpeedX;
-    float y = skyOffsetY + State->skySpeedY;
-
-    if (x > 1.0f) x = 0.0f;
-    if (x < -1.0f) x = 0.0f;
-    if (y > 1.0f) y = 0.0f;
-
-    skyOffsetX = x;
-    skyOffsetY = y;
-
-    float matrix[16];
-    matrixLoadTranslate(matrix, x + State->xOffset, y, 0.0f);
-    vpLoadTextureMatrix(matrix);
-
     drawSimpleMesh(NAMED_WaterMesh);
-
-    matrixLoadIdentity(matrix);
-    vpLoadTextureMatrix(matrix);
 }
-*/
 
 int main(int index) {
     // Compute dt in seconds.
@@ -425,17 +323,17 @@ int main(int index) {
         genLeafDrop(gLeaves[i], randf(0.3f) + 0.1f);
     }
 
-    generateRipples();
-    updateSimpleMesh(NAMED_WaterMesh);
-
     if (State->rotate) {
         float matrix[16];
         matrixLoadRotate(matrix, 90.0f, 0.0f, 0.0f, 1.0f);
         vpLoadModelMatrix(matrix);
     }
 
+    bindProgramVertex(NAMED_PVWater);
+    generateRipples();
     drawRiverbed();
-    // drawSky();
+
+    bindProgramVertex(NAMED_PVSky);
     drawLeaves();
 
     return 30;
index 7c97de0..f37dc6d 100644 (file)
@@ -13,7 +13,7 @@
 // limitations under the License.
 
 #pragma version(1)
-#pragma stateVertex(PVBackground)
+#pragma stateVertex(PVBkOrtho)
 #pragma stateRaster(parent)
 #pragma stateFragment(PFBackground)
 #pragma stateStore(PFSBackground)
@@ -51,25 +51,30 @@ float randomGauss() {
     return x1 * w;
 }
 
+float gSpeed[12000];
+
 /**
  * Generates the properties for a given star.
  */
-void createParticle(struct Stars_s *star, struct Particles_s *part, float scale) {
+void createParticle(struct Particles_s *part, int idx, float scale) {
     float d = fabsf(randomGauss()) * State->galaxyRadius * 0.5f + randf(64.0f);
     float id = d / State->galaxyRadius;
     float z = randomGauss() * 0.4f * (1.0f - id);
     float p = -d * ELLIPSE_TWIST;
 
+    int r,g,b,a;
     if (d < State->galaxyRadius * 0.33f) {
-        part->r = (int) (220 + id * 35);
-        part->g = 220;
-        part->b = 220;
+        r = (int) (220 + id * 35);
+        g = 220;
+        b = 220;
     } else {
-        part->r= 180;
-        part->g = 180;
-        part->b = (int) clampf(140.f + id * 115.f, 140.f, 255.f);
+        = 180;
+        g = 180;
+        b = (int) clampf(140.f + id * 115.f, 140.f, 255.f);
     }
-    part->a = (int) (140 + (1.0f - id) * 115);
+    // Stash point size * 10 in Alpha
+    a = (int) (randf2(1.2f, 2.1f) * 60);
+    part->color = r | g<<8 | b<<16 | a<<24;
 
     if (d > State->galaxyRadius * 0.15f) {
         z *= 0.6f * (1.0f - id);
@@ -80,14 +85,11 @@ void createParticle(struct Stars_s *star, struct Particles_s *part, float scale)
     // Map to the projection coordinates (viewport.x = -1.0 -> 1.0)
     d = mapf(-4.0f, State->galaxyRadius + 4.0f, 0.0f, scale, d);
 
-    star->angle = randf(TWO_PI);
-    star->distance = d;
-    star->speed = randf2(0.0015f, 0.0025f) * (0.5f + (scale / d)) * 0.8f;
-    star->s = cosf(p);
-    star->t = sinf(p);
+    part->position.x = randf(TWO_PI);
+    part->position.y = d;
+    gSpeed[idx] = randf2(0.0015f, 0.0025f) * (0.5f + (scale / d)) * 0.8f;
 
-    part->z = z / 5.0f;
-    part->pointSize = randf2(1.2f, 2.1f) * 6;
+    part->position.z = z / 5.0f;
 }
 
 /**
@@ -98,15 +100,13 @@ void initParticles() {
         angle = 0.0f;
     }
 
-    struct Stars_s *star = Stars;
     struct Particles_s *part = Particles;
     int particlesCount = State->particlesCount;
     float scale = State->galaxyRadius / (State->width * 0.5f);
 
     int i;
     for (i = 0; i < particlesCount; i ++) {
-        createParticle(star, part, scale);
-        star++;
+        createParticle(part, i, scale);
         part++;
     }
 }
@@ -121,7 +121,7 @@ void drawSpace(float xOffset, int width, int height) {
 }
 
 void drawLights(float xOffset, int width, int height) {
-    bindProgramVertex(NAMED_PVStars);
+    bindProgramVertex(NAMED_PVBkProj);
     bindProgramFragment(NAMED_PFBackground);
     bindTexture(NAMED_PFBackground, 0, NAMED_TLight1);
 
@@ -158,26 +158,16 @@ void drawParticles(float xOffset, float offset, int width, int height) {
     vpLoadModelMatrix(matrix);
 
     // quadratic attenuation
-    pointAttenuation(0.1f + 0.3f * fabsf(offset), 0.0f, 0.06f  + 0.1f *  fabsf(offset));
+    //pointAttenuation(0.1f + 0.3f * fabsf(offset), 0.0f, 0.06f  + 0.1f *  fabsf(offset));
 
     int radius = State->galaxyRadius;
     int particlesCount = State->particlesCount;
 
-    struct Stars_s *star = Stars;
     struct Particles_s *vtx = Particles;
 
     int i = 0;
     for ( ; i < particlesCount; i++) {
-        float a = star->angle + star->speed;
-        float x = star->distance * sinf(a);
-        float y = star->distance * cosf(a) * ELLIPSE_RATIO;
-
-        vtx->x = star->t * x + star->s * y + xOffset;
-        vtx->y = star->s * x - star->t * y;
-
-        star->angle = a;
-
-        star++;
+        vtx->position.x = vtx->position.x + gSpeed[i];
         vtx++;
     }
 
index f963791..563af1c 100644 (file)
 #pragma stateFragment(PFBackground)
 #pragma stateStore(PFSBackground)
 
-#define RSID_STATE 0
-#define RSID_BLADES 1
 #define RSID_BLADES_BUFFER 2
 
-#define BLADE_STRUCT_FIELDS_COUNT 13
-#define BLADE_STRUCT_ANGLE 0
-#define BLADE_STRUCT_SIZE 1
-#define BLADE_STRUCT_XPOS 2
-#define BLADE_STRUCT_YPOS 3
-#define BLADE_STRUCT_OFFSET 4
-#define BLADE_STRUCT_SCALE 5
-#define BLADE_STRUCT_LENGTHX 6
-#define BLADE_STRUCT_LENGTHY 7
-#define BLADE_STRUCT_HARDNESS 8
-#define BLADE_STRUCT_H 9
-#define BLADE_STRUCT_S 10
-#define BLADE_STRUCT_B 11
-#define BLADE_STRUCT_TURBULENCEX 12
-
 #define TESSELATION 0.5f
 #define HALF_TESSELATION 0.25f
 
 
 #define REAL_TIME 1
 
+void updateBlades()
+{
+    int bladesCount = State->bladesCount;
+    struct Blades_s *bladeStruct = Blades;
+
+    int i;
+    for (i = 0; i < bladesCount; i ++) {
+        float xpos = randf2(-State->width, State->width);
+        bladeStruct->xPos = xpos;
+        bladeStruct->turbulencex = xpos * 0.006f;
+        bladeStruct->yPos = State->height;
+        bladeStruct++;
+    }
+}
+
 float time(int isPreview) {
     if (REAL_TIME && !isPreview) {
         return (hour() * 3600.0f + minute() * 60.0f + second()) / SECONDS_IN_DAY;
@@ -88,91 +86,62 @@ void drawSunset(int width, int height) {
     drawRect(0.0f, 0.0f, width, height, 0.0f);
 }
 
-int drawBlade(float *bladeStruct, float *bladeBuffer, int *bladeColor,
+int drawBlade(struct Blades_s *bladeStruct, float *bladeBuffer, int *bladeColor,
         float brightness, float xOffset, float now) {
 
-    float offset = bladeStruct[BLADE_STRUCT_OFFSET];
-    float scale = bladeStruct[BLADE_STRUCT_SCALE];
-    float angle = bladeStruct[BLADE_STRUCT_ANGLE];
-    float hardness = bladeStruct[BLADE_STRUCT_HARDNESS];
-    float turbulenceX = bladeStruct[BLADE_STRUCT_TURBULENCEX];
-
-    float xpos = bladeStruct[BLADE_STRUCT_XPOS] + xOffset;
-    float ypos = bladeStruct[BLADE_STRUCT_YPOS];
+    float scale = bladeStruct->scale;
+    float angle = bladeStruct->angle;
+    float xpos = bladeStruct->xPos + xOffset;
+    int size = bladeStruct->size;
 
-    float lengthX = bladeStruct[BLADE_STRUCT_LENGTHX];
-    float lengthY = bladeStruct[BLADE_STRUCT_LENGTHY];
+    int color = hsbToAbgr(bladeStruct->h, bladeStruct->s,
+                          lerpf(0, bladeStruct->b, brightness), 1.0f);
 
-    int size = bladeStruct[BLADE_STRUCT_SIZE];
-
-    float h = bladeStruct[BLADE_STRUCT_H];
-    float s = bladeStruct[BLADE_STRUCT_S];
-    float b = bladeStruct[BLADE_STRUCT_B];
-
-    int color = hsbToAbgr(h, s, lerpf(0, b, brightness), 1.0f);
-
-    float newAngle = (turbulencef2(turbulenceX, now, 4.0f) - 0.5f) * 0.5f;
-    angle = clampf(angle + (newAngle + offset - angle) * 0.15f, -MAX_BEND, MAX_BEND);
+    float newAngle = (turbulencef2(bladeStruct->turbulencex, now, 4.0f) - 0.5f) * 0.5f;
+    angle = clampf(angle + (newAngle + bladeStruct->offset - angle) * 0.15f, -MAX_BEND, MAX_BEND);
 
     float currentAngle = HALF_PI;
 
     float bottomX = xpos;
-    float bottomY = ypos;
+    float bottomY = bladeStruct->yPos;
 
-    float d = angle * hardness;
+    float d = angle * bladeStruct->hardness;
 
-    int triangles = size * 2;
+
+    float si = size * scale;
+    float bottomLeft = bottomX - si;
+    float bottomRight = bottomX + si;
+    float bottom = bottomY + HALF_TESSELATION;
+
+    bladeColor[0] = color;                          // V1.ABGR
+    bladeBuffer[1] = bottomLeft;                    // V1.X
+    bladeBuffer[2] = bottom;                        // V1.Y
+    bladeColor[5] = color;                          // V2.ABGR
+    bladeBuffer[6] = bottomRight;                   // V2.X
+    bladeBuffer[7] = bottom;                        // V2.Y
+    bladeBuffer += 10;
+    bladeColor += 10;
 
     for ( ; size > 0; size -= 1) {
-        float topX = bottomX - cosf_fast(currentAngle) * lengthX;
-        float topY = bottomY - sinf_fast(currentAngle) * lengthY;
+        float topX = bottomX - cosf_fast(currentAngle) * bladeStruct->lengthX;
+        float topY = bottomY - sinf_fast(currentAngle) * bladeStruct->lengthY;
 
-        float si = size * scale;
+        si = (float)size * scale;
         float spi = si - scale;
 
-        float bottomLeft = bottomX - si;
-        float bottomRight = bottomX + si;
         float topLeft = topX - spi;
         float topRight = topX + spi;
-        float bottom = bottomY + HALF_TESSELATION;
 
-        // First triangle
         bladeColor[0] = color;                          // V1.ABGR
+        bladeBuffer[1] = topLeft;                       // V2.X
+        bladeBuffer[2] = topY;                          // V2.Y
 
-        bladeBuffer[1] = bottomLeft;                    // V1.X
-        bladeBuffer[2] = bottom;                        // V1.Y
-
-        bladeColor[5] = color;                          // V1.ABGR
-
-        bladeBuffer[6] = topLeft;                       // V2.X
-        bladeBuffer[7] = topY;                          // V2.Y
-
-        bladeColor[10] = color;                         // V3.ABGR
-
-        bladeBuffer[11] = topRight;                     // V3.X
-        bladeBuffer[12] = topY;                         // V3.Y
-
-        // Second triangle
-        bladeBuffer += 15;
-        bladeColor += 15;
-
-        bladeColor[0] = color;                          // V1.ABGR
-
-        bladeBuffer[1] = bottomLeft;                    // V1.X
-        bladeBuffer[2] = bottom;                        // V1.Y
-
-        bladeColor[5] = color;                          // V2.ABGR
-
-        bladeBuffer[6] = topRight;                      // V2.X
-        bladeBuffer[7] = topY;                          // V2.Y
-
-        bladeColor[10] = color;                         // V3.ABGR
-
-        bladeBuffer[11] = bottomRight;                  // V3.X
-        bladeBuffer[12] = bottom;                       // V3.Y
+        bladeColor[5] = color;                         // V3.ABGR
+        bladeBuffer[6] = topRight;                     // V3.X
+        bladeBuffer[7] = topY;                         // V3.Y
 
-        bladeBuffer += 15;
-        bladeColor += 15;
+        bladeBuffer += 10;
+        bladeColor += 10;
 
         bottomX = topX;
         bottomY = topY;
@@ -180,21 +149,20 @@ int drawBlade(float *bladeStruct, float *bladeBuffer, int *bladeColor,
         currentAngle += d;
     }
 
-    bladeStruct[BLADE_STRUCT_ANGLE] = angle;
+    bladeStruct->angle = angle;
 
-    // 3 vertices per triangle, 5 properties per vertex (RGBA, X, Y, S, T)
-    return triangles * 15;
+    // 2 vertices per triangle, 5 properties per vertex (RGBA, X, Y, S, T)
+    return bladeStruct->size * 10 + 10;
 }
 
 void drawBlades(float brightness, float xOffset) {
     // For anti-aliasing
-    bindTexture(NAMED_PFBackground, 0, NAMED_TAa);
+    bindTexture(NAMED_PFGrass, 0, NAMED_TAa);
 
     int bladesCount = State->bladesCount;
-    int trianglesCount = State->trianglesCount;
 
     int i = 0;
-    float *bladeStruct = loadArrayF(RSID_BLADES, 0);
+    struct Blades_s *bladeStruct = Blades;
     float *bladeBuffer = loadArrayF(RSID_BLADES_BUFFER, 0);
     int *bladeColor = loadArrayI32(RSID_BLADES_BUFFER, 0);
 
@@ -204,11 +172,11 @@ void drawBlades(float brightness, float xOffset) {
         int offset = drawBlade(bladeStruct, bladeBuffer, bladeColor, brightness, xOffset, now);
         bladeBuffer += offset;
         bladeColor += offset;
-        bladeStruct += BLADE_STRUCT_FIELDS_COUNT;
+        bladeStruct ++;
     }
 
     uploadToBufferObject(NAMED_BladesBuffer);
-    drawSimpleMeshRange(NAMED_BladesMesh, 0, trianglesCount * 3);
+    drawSimpleMeshRange(NAMED_BladesMesh, 0, State->indexCount);
 }
 
 int main(int launchID) {
@@ -262,7 +230,8 @@ int main(int launchID) {
         newB = 0.0f;
     }
 
+    bindProgramFragment(NAMED_PFGrass);
     drawBlades(newB, x);
 
-    return 30;
+    return 50;
 }
index 698529c..3b43411 100644 (file)
@@ -14,7 +14,6 @@
 
 #pragma version(1)
 #pragma stateVertex(PVOrtho)
-#pragma stateFragment(PFTexture)
 #pragma stateStore(PSSolid)
 
 #define MAX_PULSES           20
@@ -48,18 +47,21 @@ int gNow;
 
 
 void setColor(int c) {
-    if (c == 0) {
+    if (State->mode == 1) {
+        // sholes red
+        color(0.9f, 0.1f, 0.1f, 0.8f);
+    } else if (c == 0) {
         // red
-        color(1.0f, 0.0f, 0.0f, 1.0f);
+        color(1.0f, 0.0f, 0.0f, 0.8f);
     } else if (c == 1) {
         // green
-        color(0.0f, 0.6f, 0.0f, 1.0f);
+        color(0.0f, 0.8f, 0.0f, 0.8f);
     } else if (c == 2) {
         // blue
-        color(0.0f, 0.4f, 0.8f, 1.0f);
+        color(0.0f, 0.4f, 0.9f, 0.8f);
     } else if (c == 3) {
         // yellow
-        color(1.0f, 0.8f, 0.0f, 1.0f);
+        color(1.0f, 0.8f, 0.0f, 0.8f);
     }
 }
 
@@ -115,7 +117,8 @@ void initPulses() {
 }
 
 void drawBackground(int width, int height) {
-    bindTexture(NAMED_PFTexture, 0, NAMED_TBackground);
+       bindProgramFragment(NAMED_PFTexture565);
+    bindTexture(NAMED_PFTexture565, 0, NAMED_TBackground);
     color(1.0f, 1.0f, 1.0f, 1.0f);
     if (State->rotate) {
         drawRect(0.0f, 0.0f, height*2, width, 0.0f);
@@ -267,8 +270,8 @@ int main(int index) {
     gNow = uptimeMillis();
 
     if (Command->command != 0) {
-        debugF("x", Command->x);
-        debugF("y", Command->y);
+        //debugF("x", Command->x);
+        //debugF("y", Command->y);
         Command->command = 0;
         addTap(Command->x, Command->y);
     }
diff --git a/res/values/integers.xml b/res/values/integers.xml
new file mode 100644 (file)
index 0000000..db671b2
--- /dev/null
@@ -0,0 +1,3 @@
+<resources>
+    <integer name="nexus_mode">0</integer>
+</resources>
index 069bedd..dc86cfb 100644 (file)
@@ -17,6 +17,7 @@
 package com.android.wallpaper.fall;
 
 import android.os.Bundle;
+import android.renderscript.Element;
 import android.renderscript.ScriptC;
 import android.renderscript.ProgramFragment;
 import android.renderscript.ProgramStore;
@@ -28,11 +29,10 @@ import android.renderscript.Type;
 import android.renderscript.SimpleMesh;
 import android.renderscript.Script;
 import static android.renderscript.Sampler.Value.LINEAR;
-import static android.renderscript.Sampler.Value.WRAP;
+import static android.renderscript.Sampler.Value.CLAMP;
 import static android.renderscript.ProgramStore.DepthFunc.*;
 import static android.renderscript.ProgramStore.BlendDstFunc;
 import static android.renderscript.ProgramStore.BlendSrcFunc;
-import static android.renderscript.ProgramFragment.EnvMode.*;
 import static android.renderscript.Element.*;
 
 import android.app.WallpaperManager;
@@ -49,16 +49,20 @@ class FallRS extends RenderScriptScene {
     private static final int MESH_RESOLUTION = 48;
 
     private static final int RSID_STATE = 0;
+    private static final int RSID_CONSTANTS = 1;
+    private static final int RSID_DROP = 2;
 
     private static final int TEXTURES_COUNT = 2;
     private static final int RSID_TEXTURE_RIVERBED = 0;
     private static final int RSID_TEXTURE_LEAVES = 1;
     private static final int RSID_TEXTURE_SKY = 2;
 
-    private static final int RSID_RIPPLE_MAP = 1;
-    private static final int RSID_DROP = 2;
 
 
+    static class Defines {
+
+    };
+
     private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
 
     @SuppressWarnings({"FieldCanBeLocal"})
@@ -71,6 +75,7 @@ class FallRS extends RenderScriptScene {
     private ProgramStore mPfsLeaf;
     @SuppressWarnings({"FieldCanBeLocal"})
     private ProgramVertex mPvSky;
+    private ProgramVertex mPvWater;
     private ProgramVertex.MatrixAllocation mPvOrthoAlloc;
     @SuppressWarnings({"FieldCanBeLocal"})
     private Sampler mSampler;
@@ -81,14 +86,13 @@ class FallRS extends RenderScriptScene {
     private Type mStateType;
     private Type mDropType;
     private int mMeshWidth;
+    private Allocation mUniformAlloc;
 
     private int mMeshHeight;
     @SuppressWarnings({"FieldCanBeLocal"})
     private SimpleMesh mMesh;
     private WorldState mWorldState;
 
-    private Allocation mRippleMap;
-
     private float mGlHeight;
 
     public FallRS(int width, int height) {
@@ -114,7 +118,7 @@ class FallRS extends RenderScriptScene {
         }
         return null;
     }
-    
+
     @Override
     public void start() {
         super.start();
@@ -139,16 +143,19 @@ class FallRS extends RenderScriptScene {
 
     @Override
     protected ScriptC createScript() {
+        createMesh();
+        createState();
         createProgramVertex();
         createProgramFragmentStore();
         createProgramFragment();
-        createMesh();
-        createScriptStructures();
         loadTextures();
 
+
+
         ScriptC.Builder sb = new ScriptC.Builder(mRS);
         sb.setType(mStateType, "State", RSID_STATE);
         sb.setType(mDropType, "Drop", RSID_DROP);
+        sb.setType(mUniformAlloc.getType(), "Constants", RSID_CONSTANTS);
         sb.setScript(mResources, R.raw.fall);
         Script.Invokable invokable = sb.addInvokable("initLeaves");
         sb.setRoot(true);
@@ -158,7 +165,7 @@ class FallRS extends RenderScriptScene {
         script.setTimeZone(TimeZone.getDefault().getID());
 
         script.bindAllocation(mState, RSID_STATE);
-        script.bindAllocation(mRippleMap, RSID_RIPPLE_MAP);
+        script.bindAllocation(mUniformAlloc, RSID_CONSTANTS);
         script.bindAllocation(mDropState, RSID_DROP);
 
         invokable.execute();
@@ -167,8 +174,7 @@ class FallRS extends RenderScriptScene {
     }
 
     private void createMesh() {
-        SimpleMesh.TriangleMeshBuilder tmb = new SimpleMesh.TriangleMeshBuilder(mRS, 3,
-                SimpleMesh.TriangleMeshBuilder.TEXTURE_0);
+        SimpleMesh.TriangleMeshBuilder tmb = new SimpleMesh.TriangleMeshBuilder(mRS, 2, 0);
 
         final int width = mWidth > mHeight ? mHeight : mWidth;
         final int height = mWidth > mHeight ? mWidth : mHeight;
@@ -186,11 +192,9 @@ class FallRS extends RenderScriptScene {
         hResolution += 2;
 
         for (int y = 0; y <= hResolution; y++) {
-            final float yOffset = y * quadHeight - glHeight / 2.0f - quadHeight;
-            final float t = 1.0f - y / (float) hResolution;
+            final float yOffset = (((float)y / hResolution) * 2.f - 1.f) * height / width;
             for (int x = 0; x <= wResolution; x++) {
-                tmb.setTexture(x / (float) wResolution, t);
-                tmb.addVertex(-1.0f + x * quadWidth - quadWidth, yOffset, 0.0f);
+                tmb.addVertex(((float)x / wResolution) * 2.f - 1.f, yOffset);
             }
         }
 
@@ -217,26 +221,12 @@ class FallRS extends RenderScriptScene {
         mMeshHeight = hResolution + 1;
     }
 
-    private void createScriptStructures() {
-        final int rippleMapSize = (mMeshWidth + 2) * (mMeshHeight + 2);
-
-        createState(rippleMapSize);
-        createRippleMap(rippleMapSize);
-    }
-
-    private void createRippleMap(int rippleMapSize) {
-        final int[] rippleMap = new int[rippleMapSize * 2];
-        mRippleMap = Allocation.createSized(mRS, USER_I32(mRS), rippleMap.length);
-        mRippleMap.data(rippleMap);
-    }
-
     static class WorldState {
         public int frameCount;
         public int width;
         public int height;
         public int meshWidth;
         public int meshHeight;
-        public int rippleMapSize;
         public int rippleIndex;
         public int leavesCount;
         public float glWidth;
@@ -253,13 +243,12 @@ class FallRS extends RenderScriptScene {
         public int dropY;
     }
 
-    private void createState(int rippleMapSize) {
+    private void createState() {
         mWorldState = new WorldState();
         mWorldState.width = mWidth;
         mWorldState.height = mHeight;
         mWorldState.meshWidth = mMeshWidth;
         mWorldState.meshHeight = mMeshHeight;
-        mWorldState.rippleMapSize = rippleMapSize;
         mWorldState.rippleIndex = 0;
         mWorldState.glWidth = 2.0f;
         mWorldState.glHeight = mGlHeight;
@@ -280,7 +269,7 @@ class FallRS extends RenderScriptScene {
         mDropState = Allocation.createTyped(mRS, mDropType);
         mDropState.data(mDrop);
     }
-    
+
     private void loadTextures() {
         final Allocation[] textures = new Allocation[TEXTURES_COUNT];
         textures[RSID_TEXTURE_RIVERBED] = loadTexture(R.drawable.pond, "TRiverbed");
@@ -311,20 +300,20 @@ class FallRS extends RenderScriptScene {
         Sampler.Builder sampleBuilder = new Sampler.Builder(mRS);
         sampleBuilder.setMin(LINEAR);
         sampleBuilder.setMag(LINEAR);
-        sampleBuilder.setWrapS(WRAP);
-        sampleBuilder.setWrapT(WRAP);
+        sampleBuilder.setWrapS(CLAMP);
+        sampleBuilder.setWrapT(CLAMP);
         mSampler = sampleBuilder.create();
 
-        ProgramFragment.Builder builder = new ProgramFragment.Builder(mRS, null, null);
-        builder.setTexEnable(true, 0);
-        builder.setTexEnvMode(REPLACE, 0);
+        ProgramFragment.Builder builder = new ProgramFragment.Builder(mRS);
+        builder.setTexture(ProgramFragment.Builder.EnvMode.REPLACE,
+                           ProgramFragment.Builder.Format.RGBA, 0);
         mPfBackground = builder.create();
         mPfBackground.setName("PFBackground");
         mPfBackground.bindSampler(mSampler, 0);
 
-        builder = new ProgramFragment.Builder(mRS, null, null);
-        builder.setTexEnable(true, 0);
-        builder.setTexEnvMode(MODULATE, 0);
+        builder = new ProgramFragment.Builder(mRS);
+        builder.setTexture(ProgramFragment.Builder.EnvMode.MODULATE,
+                           ProgramFragment.Builder.Format.RGBA, 0);
         mPfSky = builder.create();
         mPfSky.setName("PFSky");
         mPfSky.bindSampler(mSampler, 0);
@@ -353,10 +342,157 @@ class FallRS extends RenderScriptScene {
         mPvOrthoAlloc.setupProjectionNormalized(mWidth, mHeight);
 
         ProgramVertex.Builder builder = new ProgramVertex.Builder(mRS, null, null);
-        builder.setTextureMatrixEnable(true);
         mPvSky = builder.create();
         mPvSky.bindAllocation(mPvOrthoAlloc);
         mPvSky.setName("PVSky");
+
+        float dw = 480.f / mMeshWidth;
+        float dh = 800.f / mMeshHeight;
+
+        Element.Builder eb = new Element.Builder(mRS);
+        // Make this an array when we can.
+        eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 4), "Drop01");
+        eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 4), "Drop02");
+        eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 4), "Drop03");
+        eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 4), "Drop04");
+        eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 4), "Drop05");
+        eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 4), "Drop06");
+        eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 4), "Drop07");
+        eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 4), "Drop08");
+        eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 4), "Drop09");
+        eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 4), "Drop10");
+        eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 4), "Offset");
+        Element e = eb.create();
+
+        mUniformAlloc = Allocation.createSized(mRS, e, 1);
+
+
+        ProgramVertex.ShaderBuilder sb = new ProgramVertex.ShaderBuilder(mRS);
+        String t = new String("void main() {\n" +
+                              "  vec4 pos;\n" +
+                              "  pos.x = ATTRIB_position.x;\n" +
+                              "  pos.y = ATTRIB_position.y;\n" +
+                              "  pos.z = 0.0;\n" +
+                              "  pos.w = 1.0;\n" +
+                              "  gl_Position = pos;\n" +
+
+                              // When we resize the texture we will need to tweak this.
+                              "  varTex0.x = (pos.x + 1.0) * 0.25;\n" +
+                              "  varTex0.x += UNI_Offset.x * 0.5 * 0.85;\n" +
+                              "  varTex0.y = (pos.y + 1.6666) * 0.33;\n" +
+                              "  varTex0.w = 0.0;\n" +
+                              "  varColor = vec4(1.0, 1.0, 1.0, 1.0);\n" +
+
+                              "  pos.x += UNI_Offset.x * 2.0;\n" +
+                              "  pos.x += 1.0;\n" +
+                              "  pos.y += 1.0;\n" +
+                              "  pos.x *= 25.0;\n" +
+                              "  pos.y *= 42.0;\n" +
+
+                              "  vec2 delta;\n" +
+                              "  float dist;\n" +
+                              "  float amp;\n" +
+
+                              "  delta = UNI_Drop01.xy - pos.xy;\n" +
+                              "  dist = length(delta);\n" +
+                              "  if (dist < UNI_Drop01.w) { \n" +
+                              "    amp = UNI_Drop01.z * dist;\n" +
+                              "    amp /= UNI_Drop01.w * UNI_Drop01.w;\n" +
+                              "    amp *= sin(UNI_Drop01.w - dist);\n" +
+                              "    varTex0.xy += delta * amp;\n" +
+                              "  }\n" +
+
+                              "  delta = UNI_Drop02.xy - pos.xy;\n" +
+                              "  dist = length(delta);\n" +
+                              "  if (dist < UNI_Drop02.w) { \n" +
+                              "    amp = UNI_Drop02.z * dist;\n" +
+                              "    amp /= UNI_Drop02.w * UNI_Drop02.w;\n" +
+                              "    amp *= sin(UNI_Drop02.w - dist);\n" +
+                              "    varTex0.xy += delta * amp;\n" +
+                              "  }\n" +
+
+                              "  delta = UNI_Drop03.xy - pos.xy;\n" +
+                              "  dist = length(delta);\n" +
+                              "  if (dist < UNI_Drop03.w) { \n" +
+                              "    amp = UNI_Drop03.z * dist;\n" +
+                              "    amp /= UNI_Drop03.w * UNI_Drop03.w;\n" +
+                              "    amp *= sin(UNI_Drop03.w - dist);\n" +
+                              "    varTex0.xy += delta * amp;\n" +
+                              "  }\n" +
+
+                              "  delta = UNI_Drop04.xy - pos.xy;\n" +
+                              "  dist = length(delta);\n" +
+                              "  if (dist < UNI_Drop04.w) { \n" +
+                              "    amp = UNI_Drop04.z * dist;\n" +
+                              "    amp /= UNI_Drop04.w * UNI_Drop04.w;\n" +
+                              "    amp *= sin(UNI_Drop04.w - dist);\n" +
+                              "    varTex0.xy += delta * amp;\n" +
+                              "  }\n" +
+
+                              "  delta = UNI_Drop05.xy - pos.xy;\n" +
+                              "  dist = length(delta);\n" +
+                              "  if (dist < UNI_Drop05.w) { \n" +
+                              "    amp = UNI_Drop05.z * dist;\n" +
+                              "    amp /= UNI_Drop05.w * UNI_Drop05.w;\n" +
+                              "    amp *= sin(UNI_Drop05.w - dist);\n" +
+                              "    varTex0.xy += delta * amp;\n" +
+                              "  }\n" +
+
+                              "  delta = UNI_Drop06.xy - pos.xy;\n" +
+                              "  dist = length(delta);\n" +
+                              "  if (dist < UNI_Drop06.w) { \n" +
+                              "    amp = UNI_Drop06.z * dist;\n" +
+                              "    amp /= UNI_Drop06.w * UNI_Drop06.w;\n" +
+                              "    amp *= sin(UNI_Drop06.w - dist);\n" +
+                              "    varTex0.xy += delta * amp;\n" +
+                              "  }\n" +
+
+                              "  delta = UNI_Drop07.xy - pos.xy;\n" +
+                              "  dist = length(delta);\n" +
+                              "  if (dist < UNI_Drop07.w) { \n" +
+                              "    amp = UNI_Drop07.z * dist;\n" +
+                              "    amp /= UNI_Drop07.w * UNI_Drop07.w;\n" +
+                              "    amp *= sin(UNI_Drop07.w - dist);\n" +
+                              "    varTex0.xy += delta * amp;\n" +
+                              "  }\n" +
+
+                              "  delta = UNI_Drop08.xy - pos.xy;\n" +
+                              "  dist = length(delta);\n" +
+                              "  if (dist < UNI_Drop08.w) { \n" +
+                              "    amp = UNI_Drop08.z * dist;\n" +
+                              "    amp /= UNI_Drop08.w * UNI_Drop08.w;\n" +
+                              "    amp *= sin(UNI_Drop08.w - dist);\n" +
+                              "    varTex0.xy += delta * amp;\n" +
+                              "  }\n" +
+
+                              "  delta = UNI_Drop09.xy - pos.xy;\n" +
+                              "  dist = length(delta);\n" +
+                              "  if (dist < UNI_Drop09.w) { \n" +
+                              "    amp = UNI_Drop09.z * dist;\n" +
+                              "    amp /= UNI_Drop09.w * UNI_Drop09.w;\n" +
+                              "    amp *= sin(UNI_Drop09.w - dist);\n" +
+                              "    varTex0.xy += delta * amp;\n" +
+                              "  }\n" +
+
+                              "  delta = UNI_Drop10.xy - pos.xy;\n" +
+                              "  dist = length(delta);\n" +
+                              "  if (dist < UNI_Drop10.w) { \n" +
+                              "    amp = UNI_Drop10.z * dist;\n" +
+                              "    amp /= UNI_Drop10.w * UNI_Drop10.w;\n" +
+                              "    amp *= sin(UNI_Drop10.w - dist);\n" +
+                              "    varTex0.xy += delta * amp;\n" +
+                              "  }\n" +
+
+
+                              "}\n");
+        sb.setShader(t);
+        sb.addConstant(mUniformAlloc.getType());
+        sb.addInput(mMesh.getVertexType(0).getElement());
+        mPvWater = sb.create();
+        mPvWater.bindAllocation(mPvOrthoAlloc);
+        mPvWater.setName("PVWater");
+        mPvWater.bindConstants(mUniformAlloc, 1);
+
     }
 
     void addDrop(float x, float y) {
index b01dcad..f945c14 100644 (file)
@@ -33,7 +33,6 @@ import static android.renderscript.Sampler.Value.WRAP;
 import static android.renderscript.ProgramStore.DepthFunc.*;
 import static android.renderscript.ProgramStore.BlendDstFunc;
 import static android.renderscript.ProgramStore.BlendSrcFunc;
-import static android.renderscript.ProgramFragment.EnvMode.*;
 import static android.renderscript.Element.*;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -48,8 +47,7 @@ class GalaxyRS extends RenderScriptScene {
     private static final int PARTICLES_COUNT = 12000;
 
     private static final int RSID_STATE = 0;
-    private static final int RSID_PARTICLES = 1;
-    private static final int RSID_PARTICLES_BUFFER = 2;
+    private static final int RSID_PARTICLES_BUFFER = 1;
 
     private static final int TEXTURES_COUNT = 3;
     private static final int RSID_TEXTURE_SPACE = 0;
@@ -67,7 +65,9 @@ class GalaxyRS extends RenderScriptScene {
     @SuppressWarnings({"FieldCanBeLocal"})
     private ProgramStore mPfsLights;
     @SuppressWarnings({"FieldCanBeLocal"})
-    private ProgramVertex mPvBackground;
+    private ProgramVertex mPvBkOrtho;
+    @SuppressWarnings({"FieldCanBeLocal"})
+    private ProgramVertex mPvBkProj;
     @SuppressWarnings({"FieldCanBeLocal"})
     private ProgramVertex mPvStars;
     @SuppressWarnings({"FieldCanBeLocal"})
@@ -84,8 +84,6 @@ class GalaxyRS extends RenderScriptScene {
     private GalaxyState mGalaxyState;
     private Type mStateType;
     private Allocation mState;
-    private Allocation mParticles;
-    private Type mParticlesType;
     private Allocation mParticlesBuffer;
     @SuppressWarnings({"FieldCanBeLocal"})
     private SimpleMesh mParticlesMesh;
@@ -100,17 +98,16 @@ class GalaxyRS extends RenderScriptScene {
 
     @Override
     protected ScriptC createScript() {
+        createScriptStructures();
         createProgramVertex();
         createProgramRaster();
         createProgramFragmentStore();
         createProgramFragment();
-        createScriptStructures();
         loadTextures();
 
         ScriptC.Builder sb = new ScriptC.Builder(mRS);
         sb.setType(mStateType, "State", RSID_STATE);
         sb.setType(mParticlesMesh.getVertexType(0), "Particles", RSID_PARTICLES_BUFFER);
-        sb.setType(mParticlesType, "Stars", RSID_PARTICLES);
         mInitParticles = sb.addInvokable("initParticles");
         sb.setScript(mResources, R.raw.galaxy);
         sb.setRoot(true);
@@ -120,7 +117,6 @@ class GalaxyRS extends RenderScriptScene {
         script.setTimeZone(TimeZone.getDefault().getID());
 
         script.bindAllocation(mState, RSID_STATE);
-        script.bindAllocation(mParticles, RSID_PARTICLES);
         script.bindAllocation(mParticlesBuffer, RSID_PARTICLES_BUFFER);
         mInitParticles.execute();
 
@@ -130,14 +126,14 @@ class GalaxyRS extends RenderScriptScene {
     private void createScriptStructures() {
         createState();
         createParticlesMesh();
-        createParticles();
     }
 
     private void createParticlesMesh() {
         final Builder elementBuilder = new Builder(mRS);
-        elementBuilder.addUNorm8RGBA("");
-        elementBuilder.addFloatXYZ("");
-        elementBuilder.addFloatPointSize("");
+        elementBuilder.add(Element.createAttrib(mRS, Element.DataType.UNSIGNED_8,
+                Element.DataKind.USER, 4), "color");
+        elementBuilder.add(Element.createAttrib(mRS, Element.DataType.FLOAT_32,
+                Element.DataKind.USER, 3), "position");
         final Element vertexElement = elementBuilder.create();
 
         final SimpleMesh.Builder meshBuilder = new SimpleMesh.Builder(mRS);
@@ -167,6 +163,8 @@ class GalaxyRS extends RenderScriptScene {
         mState.data(mGalaxyState);
 
         mPvOrthoAlloc.setupOrthoWindow(mWidth, mHeight);
+        mPvProjectionAlloc.setupProjectionNormalized(mWidth, mHeight);
+
         mInitParticles.execute();
     }
 
@@ -180,14 +178,6 @@ class GalaxyRS extends RenderScriptScene {
         public int scale;
     }
 
-    static class GalaxyParticle {
-        public float angle;
-        public float distance;
-        public float speed;
-        public float s;
-        public float t;
-    }
-
     private void createState() {
         boolean isPreview = isPreview();
 
@@ -207,11 +197,6 @@ class GalaxyRS extends RenderScriptScene {
         mState.data(mGalaxyState);
     }
 
-    private void createParticles() {
-        mParticlesType = Type.createFromClass(mRS, GalaxyParticle.class, PARTICLES_COUNT, "Particle");
-        mParticles = Allocation.createTyped(mRS, mParticlesType);
-    }
-
     private void loadTextures() {
         mTextures = new Allocation[TEXTURES_COUNT];
 
@@ -249,9 +234,9 @@ class GalaxyRS extends RenderScriptScene {
         samplerBuilder.setWrapT(WRAP);
         mSampler = samplerBuilder.create();
 
-        ProgramFragment.Builder builder = new ProgramFragment.Builder(mRS, null, null);
-        builder.setTexEnable(true, 0);
-        builder.setTexEnvMode(REPLACE, 0);
+        ProgramFragment.Builder builder = new ProgramFragment.Builder(mRS);
+        builder.setTexture(ProgramFragment.Builder.EnvMode.REPLACE,
+                           ProgramFragment.Builder.Format.RGB, 0);
         mPfBackground = builder.create();
         mPfBackground.setName("PFBackground");
         mPfBackground.bindSampler(mSampler, 0);
@@ -263,10 +248,10 @@ class GalaxyRS extends RenderScriptScene {
         samplerBuilder.setWrapT(WRAP);
         mStarSampler = samplerBuilder.create();
 
-        builder = new ProgramFragment.Builder(mRS, null, null);
+        builder = new ProgramFragment.Builder(mRS);
         builder.setPointSpriteTexCoordinateReplacement(true);
-        builder.setTexEnable(true, 0);
-        builder.setTexEnvMode(MODULATE, 0);
+        builder.setTexture(ProgramFragment.Builder.EnvMode.MODULATE,
+                           ProgramFragment.Builder.Format.RGBA, 0);
         mPfStars = builder.create();
         mPfStars.setName("PFStars");
         mPfBackground.bindSampler(mStarSampler, 0);
@@ -294,15 +279,40 @@ class GalaxyRS extends RenderScriptScene {
         mPvOrthoAlloc.setupOrthoWindow(mWidth, mHeight);
 
         ProgramVertex.Builder builder = new ProgramVertex.Builder(mRS, null, null);
-        mPvBackground = builder.create();
-        mPvBackground.bindAllocation(mPvOrthoAlloc);
-        mPvBackground.setName("PVBackground");
+        mPvBkOrtho = builder.create();
+        mPvBkOrtho.bindAllocation(mPvOrthoAlloc);
+        mPvBkOrtho.setName("PVBkOrtho");
 
         mPvProjectionAlloc = new ProgramVertex.MatrixAllocation(mRS);
         mPvProjectionAlloc.setupProjectionNormalized(mWidth, mHeight);
 
         builder = new ProgramVertex.Builder(mRS, null, null);
-        mPvStars = builder.create();
+        mPvBkProj = builder.create();
+        mPvBkProj.bindAllocation(mPvProjectionAlloc);
+        mPvBkProj.setName("PVBkProj");
+
+        ProgramVertex.ShaderBuilder sb = new ProgramVertex.ShaderBuilder(mRS);
+        String t = "void main() {\n" +
+                    "  float dist = ATTRIB_position.y;\n" +
+                    "  float angle = ATTRIB_position.x;\n" +
+                    "  float x = dist * sin(angle);\n" +
+                    "  float y = dist * cos(angle) * 0.892;\n" +
+                    "  float p = dist * 5.5;\n" +
+                    "  float s = cos(p);\n" +
+                    "  float t = sin(p);\n" +
+                    "  vec4 pos;\n" +
+                    "  pos.x = t * x + s * y;\n" +
+                    "  pos.y = s * x - t * y;\n" +
+                    "  pos.z = ATTRIB_position.z;\n" +
+                    "  pos.w = 1.0;\n" +
+                    "  gl_Position = UNI_MVP * pos;\n" +
+                    "  gl_PointSize = ATTRIB_color.a * 10.0;\n" +
+                    "  varColor.rgb = ATTRIB_color.rgb;\n" +
+                    "  varColor.a = 1.0;\n" +
+                    "}\n";
+        sb.setShader(t);
+        sb.addInput(mParticlesMesh.getVertexType(0).getElement());
+        mPvStars = sb.create();
         mPvStars.bindAllocation(mPvProjectionAlloc);
         mPvStars.setName("PVStars");
     }
index 1fa8ec5..3b604f5 100644 (file)
@@ -17,7 +17,6 @@
 package com.android.wallpaper.grass;
 
 import android.renderscript.Sampler;
-import static android.renderscript.ProgramFragment.EnvMode.*;
 import static android.renderscript.ProgramStore.DepthFunc.*;
 import static android.renderscript.ProgramStore.BlendSrcFunc;
 import static android.renderscript.ProgramStore.BlendDstFunc;
@@ -53,7 +52,7 @@ class GrassRS extends RenderScriptScene {
     @SuppressWarnings({"UnusedDeclaration"})
     private static final String LOG_TAG = "Grass";
     private static final boolean DEBUG = false;
-    
+
     private static final int LOCATION_UPDATE_MIN_TIME = DEBUG ? 5 * 60 * 1000 : 60 * 60 * 1000; // 1 hour
     private static final int LOCATION_UPDATE_MIN_DISTANCE = DEBUG ? 10 : 150 * 1000; // 150 km
 
@@ -63,32 +62,35 @@ class GrassRS extends RenderScriptScene {
     private static final int RSID_STATE = 0;
     private static final int RSID_BLADES = 1;
     private static final int BLADES_COUNT = 200;
-    private static final int BLADE_STRUCT_FIELDS_COUNT = 13;
-    private static final int BLADE_STRUCT_ANGLE = 0;
-    private static final int BLADE_STRUCT_SIZE = 1;
-    private static final int BLADE_STRUCT_XPOS = 2;
-    private static final int BLADE_STRUCT_YPOS = 3;
-    private static final int BLADE_STRUCT_OFFSET = 4;
-    private static final int BLADE_STRUCT_SCALE = 5;
-    private static final int BLADE_STRUCT_LENGTHX = 6;
-    private static final int BLADE_STRUCT_LENGTHY = 7;
-    private static final int BLADE_STRUCT_HARDNESS = 8;
-    private static final int BLADE_STRUCT_H = 9;
-    private static final int BLADE_STRUCT_S = 10;
-    private static final int BLADE_STRUCT_B = 11;
-    private static final int BLADE_STRUCT_TURBULENCEX = 12;
+
+    class BladesStruct {
+        public float angle;
+        public int size;
+        public float xPos;
+        public float yPos;
+        public float offset;
+        public float scale;
+        public float lengthX;
+        public float lengthY;
+        public float hardness;
+        public float h;
+        public float s;
+        public float b;
+        public float turbulencex;
+    };
 
     private static final int RSID_BLADES_BUFFER = 2;
 
+    private ScriptC.Invokable mUpdateBladesInvokable;
     @SuppressWarnings({ "FieldCanBeLocal" })
     private ProgramFragment mPfBackground;
     @SuppressWarnings({ "FieldCanBeLocal" })
+    private ProgramFragment mPfGrass;
+    @SuppressWarnings({ "FieldCanBeLocal" })
     private ProgramStore mPfsBackground;
     @SuppressWarnings({ "FieldCanBeLocal" })
     private ProgramVertex mPvBackground;
     @SuppressWarnings({"FieldCanBeLocal"})
-    private Sampler mSampler;
-    @SuppressWarnings({"FieldCanBeLocal"})
     private ProgramVertex.MatrixAllocation mPvOrthoAlloc;
 
     @SuppressWarnings({ "FieldCanBeLocal" })
@@ -97,13 +99,17 @@ class GrassRS extends RenderScriptScene {
     private Type mStateType;
     private Allocation mState;
 
+    private Type mBladesType;
     private Allocation mBlades;
     private Allocation mBladesBuffer;
+    private Allocation mBladesIndicies;
     @SuppressWarnings({"FieldCanBeLocal"})
     private SimpleMesh mBladesMesh;
 
-    private int mTriangles;
-    private float[] mBladesData;
+
+    private int mVerticies;
+    private int mIndicies;
+    private int[] mBladeSizes;
     private final float[] mFloatData5 = new float[5];
 
     private WorldState mWorldState;
@@ -132,7 +138,7 @@ class GrassRS extends RenderScriptScene {
             filter.addAction(Intent.ACTION_DATE_CHANGED);
             filter.addAction(Intent.ACTION_TIME_CHANGED);
             filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
-    
+
             mContext.registerReceiver(mTimezoneTracker, filter);
         }
 
@@ -153,7 +159,7 @@ class GrassRS extends RenderScriptScene {
             mContext.unregisterReceiver(mTimezoneTracker);
             mTimezoneTracker = null;
         }
-        
+
         if (mLocationUpdater != null) {
             mLocationManager.removeUpdates(mLocationUpdater);
             mLocationUpdater = null;
@@ -168,27 +174,24 @@ class GrassRS extends RenderScriptScene {
         mWorldState.height = height;
         mState.data(mWorldState);
 
-        final float[] blades = mBladesData;
-        for (int i = 0; i < blades.length; i+= BLADE_STRUCT_FIELDS_COUNT) {
-            updateBlade(blades, i);
-        }
-        mBlades.data(blades);
-
-        mPvOrthoAlloc.setupOrthoWindow(width, height);        
+        mUpdateBladesInvokable.execute();
+        mPvOrthoAlloc.setupOrthoWindow(width, height);
     }
 
     @Override
     protected ScriptC createScript() {
         createProgramVertex();
         createProgramFragmentStore();
+        loadTextures();
         createProgramFragment();
         createScriptStructures();
-        loadTextures();
 
         ScriptC.Builder sb = new ScriptC.Builder(mRS);
         sb.setType(mStateType, "State", RSID_STATE);
+        sb.setType(mBladesType, "Blades", RSID_BLADES);
         sb.setScript(mResources, R.raw.grass);
         sb.setRoot(true);
+        mUpdateBladesInvokable = sb.addInvokable("updateBlades");
 
         ScriptC script = sb.create();
         script.setClearColor(0.0f, 0.0f, 0.0f, 1.0f);
@@ -214,7 +217,7 @@ class GrassRS extends RenderScriptScene {
 
     static class WorldState {
         public int bladesCount;
-        public int trianglesCount;
+        public int indexCount;
         public int width;
         public int height;
         public float xOffset;
@@ -232,7 +235,7 @@ class GrassRS extends RenderScriptScene {
         mWorldState.width = mWidth;
         mWorldState.height = mHeight;
         mWorldState.bladesCount = BLADES_COUNT;
-        mWorldState.trianglesCount = mTriangles;
+        mWorldState.indexCount = mIndicies;
         mWorldState.isPreview = isPreview ? 1 : 0;
         if (isPreview) {
             mWorldState.xOffset = 0.5f;
@@ -244,32 +247,35 @@ class GrassRS extends RenderScriptScene {
     }
 
     private void createBlades() {
-        int triangles = 0;
-
-        mBladesData = new float[BLADES_COUNT * BLADE_STRUCT_FIELDS_COUNT];
-
-        final float[] blades = mBladesData;
-        for (int i = 0; i < blades.length; i+= BLADE_STRUCT_FIELDS_COUNT) {
-            triangles += createBlade(blades, i);
+        mVerticies = 0;
+        mIndicies = 0;
+
+        mBladesType = Type.createFromClass(mRS, BladesStruct.class, BLADES_COUNT, "Blade");
+        mBlades = Allocation.createTyped(mRS, mBladesType);
+        BladesStruct bs = new BladesStruct();
+
+        mBladeSizes = new int[BLADES_COUNT];
+        for (int i = 0; i < BLADES_COUNT; i++) {
+            createBlade(bs);
+            mIndicies += bs.size * 2 * 3;
+            mVerticies += bs.size + 2;
+            mBlades.subData(i, bs);
+            mBladeSizes[i] = bs.size;
         }
 
-        mBlades = Allocation.createSized(mRS, USER_F32(mRS), blades.length);
-        mBlades.data(blades);
-
-        mTriangles = triangles;
-
-        createMesh(triangles);
+        createMesh();
     }
 
-    private void createMesh(int triangles) {
+    private void createMesh() {
         Builder elementBuilder = new Builder(mRS);
-        elementBuilder.addUNorm8RGBA();
-        elementBuilder.addFloatXY();
-        elementBuilder.addFloatST();
+        elementBuilder.add(Element.ATTRIB_COLOR_U8_4(mRS), "color");
+        elementBuilder.add(Element.ATTRIB_POSITION_2(mRS), "position");
+        elementBuilder.add(Element.ATTRIB_TEXTURE_2(mRS), "texture");
         final Element vertexElement = elementBuilder.create();
 
         final SimpleMesh.Builder meshBuilder = new SimpleMesh.Builder(mRS);
-        final int vertexSlot = meshBuilder.addVertexType(vertexElement, triangles * 3);
+        final int vertexSlot = meshBuilder.addVertexType(vertexElement, mVerticies  * 2);
+        meshBuilder.setIndexType(Element.INDEX_16(mRS), mIndicies);
         meshBuilder.setPrimitive(Primitive.TRIANGLE);
         mBladesMesh = meshBuilder.create();
         mBladesMesh.setName("BladesMesh");
@@ -277,74 +283,65 @@ class GrassRS extends RenderScriptScene {
         mBladesBuffer = mBladesMesh.createVertexAllocation(vertexSlot);
         mBladesBuffer.setName("BladesBuffer");
         mBladesMesh.bindVertexAllocation(mBladesBuffer, 0);
+        mBladesIndicies = mBladesMesh.createIndexAllocation();
+        mBladesMesh.bindIndexAllocation(mBladesIndicies);
 
         // Assign the texture coordinates of each triangle
         final float[] floatData = mFloatData5;
         final Allocation buffer = mBladesBuffer;
 
-        int bufferIndex = 0;
-        for (int i = 0; i < triangles; i += 2) {
-            floatData[3] = 0.0f;
-            floatData[4] = 1.0f;
-            buffer.subData1D(bufferIndex, 1, floatData);
-            bufferIndex++;
+        short[] idx = new short[mIndicies];
 
+        int bufferIndex = 0;
+        int i2 = 0;
+        for (int i = 0; i < mVerticies; i +=2) {
             floatData[3] = 0.0f;
             floatData[4] = 0.0f;
-            buffer.subData1D(bufferIndex, 1, floatData);
-            bufferIndex++;
+            buffer.subData1D(bufferIndex++, 1, floatData);
 
             floatData[3] = 1.0f;
             floatData[4] = 0.0f;
-            buffer.subData1D(bufferIndex, 1, floatData);
-            bufferIndex++;
-
-            floatData[3] = 0.0f;
-            floatData[4] = 0.0f;
-            buffer.subData1D(bufferIndex, 1, floatData);
-            bufferIndex++;
-
-            floatData[3] = 1.0f;
-            floatData[4] = 1.0f;
-            buffer.subData1D(bufferIndex, 1, floatData);
-            bufferIndex++;
+            buffer.subData1D(bufferIndex++, 1, floatData);
+        }
 
-            floatData[3] = 1.0f;
-            floatData[4] = 0.0f;
-            buffer.subData1D(bufferIndex, 1, floatData);
-            bufferIndex++;
+        int idxIdx = 0;
+        int vtxIdx = 0;
+        for (int i = 0; i < mBladeSizes.length; i++) {
+            for (int ct = 0; ct < mBladeSizes[i]; ct ++) {
+                idx[idxIdx + 0] = (short)(vtxIdx + 0);
+                idx[idxIdx + 1] = (short)(vtxIdx + 1);
+                idx[idxIdx + 2] = (short)(vtxIdx + 2);
+                idx[idxIdx + 3] = (short)(vtxIdx + 1);
+                idx[idxIdx + 4] = (short)(vtxIdx + 3);
+                idx[idxIdx + 5] = (short)(vtxIdx + 2);
+                idxIdx += 6;
+                vtxIdx += 2;
+            }
+            vtxIdx += 2;
         }
-    }
 
-    private void updateBlade(float[] blades, int index) {
-        final int xpos = random(-mWidth, mWidth);
-        blades[index + BLADE_STRUCT_XPOS] = xpos;
-        blades[index + BLADE_STRUCT_TURBULENCEX] = xpos * 0.006f;
-        blades[index + BLADE_STRUCT_YPOS] = mHeight;
+        mBladesIndicies.data(idx);
+        mBladesIndicies.uploadToBufferObject();
     }
 
-    private int createBlade(float[] blades, int index) {
+    private void createBlade(BladesStruct blades) {
         final float size = random(4.0f) + 4.0f;
         final int xpos = random(-mWidth, mWidth);
 
         //noinspection PointlessArithmeticExpression
-        blades[index + BLADE_STRUCT_ANGLE] = 0.0f;
-        blades[index + BLADE_STRUCT_SIZE] = size / TESSELATION;
-        blades[index + BLADE_STRUCT_XPOS] = xpos;
-        blades[index + BLADE_STRUCT_YPOS] = mHeight;
-        blades[index + BLADE_STRUCT_OFFSET] = random(0.2f) - 0.1f;
-        blades[index + BLADE_STRUCT_SCALE] = 4.0f / (size / TESSELATION) +
-                (random(0.6f) + 0.2f) * TESSELATION;
-        blades[index + BLADE_STRUCT_LENGTHX] = (random(4.5f) + 3.0f) * TESSELATION * size;
-        blades[index + BLADE_STRUCT_LENGTHY] = (random(5.5f) + 2.0f) * TESSELATION * size;
-        blades[index + BLADE_STRUCT_HARDNESS] = (random(1.0f) + 0.2f) * TESSELATION;
-        blades[index + BLADE_STRUCT_H] = random(0.02f) + 0.2f;
-        blades[index + BLADE_STRUCT_S] = random(0.22f) + 0.78f;
-        blades[index + BLADE_STRUCT_B] = random(0.65f) + 0.35f;
-        blades[index + BLADE_STRUCT_TURBULENCEX] = xpos * 0.006f;
-
-        // Each blade is made of "size" quads, so we double to count the triangles
-        return (int) (blades[index + BLADE_STRUCT_SIZE]) * 2;
+        blades.angle = 0.0f;
+        blades.size = (int)(size / TESSELATION);
+        blades.xPos = xpos;
+        blades.yPos = mHeight;
+        blades.offset = random(0.2f) - 0.1f;
+        blades.scale = 4.0f / (size / TESSELATION) + (random(0.6f) + 0.2f) * TESSELATION;
+        blades.lengthX = (random(4.5f) + 3.0f) * TESSELATION * size;
+        blades.lengthY = (random(5.5f) + 2.0f) * TESSELATION * size;
+        blades.hardness = (random(1.0f) + 0.2f) * TESSELATION;
+        blades.h = random(0.02f) + 0.2f;
+        blades.s = random(0.22f) + 0.78f;
+        blades.b = random(0.65f) + 0.35f;
+        blades.turbulencex = xpos * 0.006f;
     }
 
     private void loadTextures() {
@@ -367,10 +364,21 @@ class GrassRS extends RenderScriptScene {
         final Type.Builder builder = new Type.Builder(mRS, A_8(mRS));
         builder.add(Dimension.X, width);
         builder.add(Dimension.Y, height);
+        builder.add(Dimension.LOD, 1);
 
         final Allocation allocation = Allocation.createTyped(mRS, builder.create());
-        allocation.data(data);
         allocation.setName(name);
+
+        int[] grey1 = new int[] {0x3f3f3f3f};
+        int[] grey2 = new int[] {0x00000000};
+        Allocation.Adapter2D a = allocation.createAdapter2D();
+        a.setConstraint(Dimension.LOD, 0);
+        a.subData(0, 0, 4, 1, data);
+        a.setConstraint(Dimension.LOD, 1);
+        a.subData(0, 0, 2, 1, grey1);
+        a.setConstraint(Dimension.LOD, 2);
+        a.subData(0, 0, 1, 1, grey2);
+
         return allocation;
     }
 
@@ -383,18 +391,29 @@ class GrassRS extends RenderScriptScene {
 
     private void createProgramFragment() {
         Sampler.Builder samplerBuilder = new Sampler.Builder(mRS);
-        samplerBuilder.setMin(LINEAR);
+        samplerBuilder.setMin(LINEAR_MIP_LINEAR);
         samplerBuilder.setMag(LINEAR);
         samplerBuilder.setWrapS(WRAP);
         samplerBuilder.setWrapT(WRAP);
-        mSampler = samplerBuilder.create();
-
-        ProgramFragment.Builder builder = new ProgramFragment.Builder(mRS, null, null);
-        builder.setTexEnable(true, 0);
-        builder.setTexEnvMode(REPLACE, 0);
+        Sampler sl = samplerBuilder.create();
+
+        samplerBuilder.setMin(NEAREST);
+        samplerBuilder.setMag(NEAREST);
+        Sampler sn = samplerBuilder.create();
+
+        ProgramFragment.Builder builder = new ProgramFragment.Builder(mRS);
+        builder.setTexture(ProgramFragment.Builder.EnvMode.REPLACE,
+                           ProgramFragment.Builder.Format.ALPHA, 0);
+        mPfGrass = builder.create();
+        mPfGrass.setName("PFGrass");
+        mPfGrass.bindSampler(sl, 0);
+
+        builder = new ProgramFragment.Builder(mRS);
+        builder.setTexture(ProgramFragment.Builder.EnvMode.REPLACE,
+                           ProgramFragment.Builder.Format.RGB, 0);
         mPfBackground = builder.create();
         mPfBackground.setName("PFBackground");
-        mPfBackground.bindSampler(mSampler, 0);
+        mPfBackground.bindSampler(sn, 0);
     }
 
     private void createProgramFragmentStore() {
@@ -412,7 +431,6 @@ class GrassRS extends RenderScriptScene {
         mPvOrthoAlloc.setupOrthoWindow(mWidth, mHeight);
 
         ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS, null, null);
-        pvb.setTextureMatrixEnable(true);
         mPvBackground = pvb.create();
         mPvBackground.bindAllocation(mPvOrthoAlloc);
         mPvBackground.setName("PVBackground");
index 1f5b6d3..6d5cce7 100644 (file)
@@ -18,15 +18,15 @@ package com.android.wallpaper.nexus;
 
 import static android.renderscript.Element.RGBA_8888;
 import static android.renderscript.Element.RGB_565;
-import static android.renderscript.ProgramFragment.EnvMode.MODULATE;
-import static android.renderscript.ProgramFragment.EnvMode.REPLACE;
 import static android.renderscript.ProgramStore.DepthFunc.ALWAYS;
 import static android.renderscript.Sampler.Value.LINEAR;
+import static android.renderscript.Sampler.Value.CLAMP;
 import static android.renderscript.Sampler.Value.WRAP;
 
 import com.android.wallpaper.R;
 import com.android.wallpaper.RenderScriptScene;
 
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Rect;
@@ -56,6 +56,7 @@ class NexusRS extends RenderScriptScene {
     private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
 
     private ProgramFragment mPfTexture;
+    private ProgramFragment mPfTexture565;
 
     private ProgramFragment mPfColor;
 
@@ -67,7 +68,8 @@ class NexusRS extends RenderScriptScene {
 
     private ProgramVertex.MatrixAllocation mPvOrthoAlloc;
 
-    private Sampler mSampler;
+    private Sampler mClampSampler;
+    private Sampler mWrapSampler;
 
     private Allocation mState;
 
@@ -148,6 +150,7 @@ class NexusRS extends RenderScriptScene {
         public int rotate;
         public int isPreview;
         public float xOffset;
+        public int mode;
     }
 
     static class CommandState {
@@ -163,6 +166,12 @@ class NexusRS extends RenderScriptScene {
         mWorldState.rotate = mWidth > mHeight ? 1 : 0;
         mWorldState.isPreview = isPreview() ? 1 : 0;
 
+        try {
+            mWorldState.mode = mResources.getInteger(R.integer.nexus_mode);
+        } catch (Resources.NotFoundException exc) {
+            mWorldState.mode = 0; // standard nexus mode
+        }
+
         mStateType = Type.createFromClass(mRS, WorldState.class, 1, "WorldState");
         mState = Allocation.createTyped(mRS, mStateType);
         mState.data(mWorldState);
@@ -203,26 +212,37 @@ class NexusRS extends RenderScriptScene {
     }
 
     private void createProgramFragment() {
+        // sampler and program fragment for pulses
         Sampler.Builder sampleBuilder = new Sampler.Builder(mRS);
         sampleBuilder.setMin(LINEAR);
         sampleBuilder.setMag(LINEAR);
         sampleBuilder.setWrapS(WRAP);
         sampleBuilder.setWrapT(WRAP);
-        mSampler = sampleBuilder.create();
-
-        ProgramFragment.Builder builder = new ProgramFragment.Builder(mRS, null, null);
-        builder.setTexEnable(true, 0);
-        builder.setTexEnvMode(MODULATE, 0);
+        mWrapSampler = sampleBuilder.create();
+        ProgramFragment.Builder builder = new ProgramFragment.Builder(mRS);
+        builder.setTexture(ProgramFragment.Builder.EnvMode.MODULATE,
+                           ProgramFragment.Builder.Format.RGBA, 0);
         mPfTexture = builder.create();
         mPfTexture.setName("PFTexture");
-        mPfTexture.bindSampler(mSampler, 0);
+        mPfTexture.bindSampler(mWrapSampler, 0);
 
-        builder = new ProgramFragment.Builder(mRS, null, null);
-        builder.setTexEnable(true, 0);
-        builder.setTexEnvMode(REPLACE, 0);
+        builder = new ProgramFragment.Builder(mRS);
+        builder.setTexture(ProgramFragment.Builder.EnvMode.REPLACE,
+                           ProgramFragment.Builder.Format.RGB, 0);
         mPfColor = builder.create();
         mPfColor.setName("PFColor");
-        mPfColor.bindSampler(mSampler, 0);
+        mPfColor.bindSampler(mWrapSampler, 0);
+
+        // sampler and program fragment for background image
+        sampleBuilder.setWrapS(CLAMP);
+        sampleBuilder.setWrapT(CLAMP);
+        mClampSampler = sampleBuilder.create();
+        builder = new ProgramFragment.Builder(mRS);
+        builder.setTexture(ProgramFragment.Builder.EnvMode.MODULATE,
+                           ProgramFragment.Builder.Format.RGB, 0);
+        mPfTexture565 = builder.create();
+        mPfTexture565.setName("PFTexture565");
+        mPfTexture565.bindSampler(mClampSampler, 0);
     }
 
     private void createProgramFragmentStore() {
@@ -278,4 +298,4 @@ class NexusRS extends RenderScriptScene {
         mCommand.command = command;
         mCommandAllocation.data(mCommand);
     }
-}
\ No newline at end of file
+}