Update rollo with new interactivity model.
diff --git a/libs/rs/java/Rollo/res/raw/rollo.c b/libs/rs/java/Rollo/res/raw/rollo.c
index f181e49..54cb21f 100644
--- a/libs/rs/java/Rollo/res/raw/rollo.c
+++ b/libs/rs/java/Rollo/res/raw/rollo.c
@@ -3,50 +3,114 @@
 #pragma stateFragment(PF)
 #pragma stateFragmentStore(PFS)
 
+// Scratch buffer layout
+// 0: fadeIn
+// 1: zoomFade
+
+#define SCRATCH_FADE 0
+#define SCRATCH_ZOOM 1
+#define SCRATCH_ROT 2
+
+
+#define STATE_POS_X             0
+#define STATE_POS_Y             1
+#define STATE_PRESSURE          2
+#define STATE_ZOOM              3
+#define STATE_WARP              4
+#define STATE_ORIENTATION       5
+#define STATE_SELECTION         6
+#define STATE_FIRST_VISIBLE     7
+#define STATE_COUNT             8
+
+void pfClearColor(float, float, float, float);
+float loadF(int, int);
+void storeF(int, int, float);
+void drawQuadF(float x1, float y1, float z1,
+                         float x2, float y2, float z2,
+                          float x3, float y3, float z3,
+                          float x4, float y4, float z4);
+float sinf(float);
+float cosf(float);
+
 int main(void* con, int ft, int launchID)
 {
     int rowCount;
-    int x;
-    int y;
     int row;
     int col;
     int imageID;
-    int tx1;
-    int ty1;
-    int tz1;
-    int tx2;
-    int ty2;
-    int tz2;
-    int rot;
-    int rotStep;
-    int tmpSin;
-    int tmpCos;
     int iconCount;
     int pressure;
 
+    float f = loadF(2, 0);
+    pfClearColor(0.0f, 0.0f, 0.0f, f);
+    if (f < 0.8f) {
+        f = f + 0.02f;
+        storeF(2, 0, f);
+    }
 
-    rotStep = 20 * 0x10000;
-    pressure = loadI32(0, 2);
+    float zoom = loadF(2, SCRATCH_ZOOM);
+    float targetZoom = ((float)loadI32(0, STATE_ZOOM)) / 10.f;
+    zoom = zoom + (targetZoom - zoom) * 0.15f;
+    storeF(2, SCRATCH_ZOOM, zoom);
 
+    float rot = loadF(2, SCRATCH_ROT);
+    float targetRot = loadI32(0, STATE_FIRST_VISIBLE) / 180.0f * 3.14f;
+    rot = rot + (targetRot - rot) * 0.15f;
+    storeF(2, SCRATCH_ROT, rot);
+
+    float diam = 8.f;// + curve * 2.f;
+    float scale = 1.0f / zoom;
+
+    pressure = loadI32(0, STATE_PRESSURE);
+    if (pressure) {
+        contextBindProgramFragmentStore(NAMED_PFSShadow);
+
+        // compute the projected shadow
+        float x = loadI32(0, STATE_POS_X) / 1000.f;
+        float y = loadI32(0, STATE_POS_Y) / 1000.f;
+        float s = loadI32(0, STATE_PRESSURE) / 1000.f;
+
+        s = s * 3.f;
+
+        float dxdy1 = (x - 0.5f - s) / (1.001f - y);
+        float dxdy2 = (x - 0.5f + s) / (1.001f - y);
+
+        float xlt = y * dxdy1 + x;
+        float xrt = y * dxdy2 + x;
+
+        float yb = (0.5f - y) * 5.f + 0.2f;
+
+        drawQuadF(xlt, 5.f, 1,
+                  xrt, 5.f, 1,
+                  x + s, yb, 1,
+                  x - s, yb, 1);
+
+        contextBindProgramFragmentStore(NAMED_PFS);
+    }
+
+
+    rot = rot * scale;
+    float rotStep = 20.0f / 180.0f * 3.14f * scale;
+    //pressure = loadI32(0, 2);
     rowCount = 4;
-
-    iconCount = loadI32(0, 1);
-    rot = (-20 + loadI32(0, 0)) * 0x10000;
+    iconCount = 32;//loadI32(0, 1);
     while (iconCount) {
-        tmpSin = sinx(rot);
-        tmpCos = cosx(rot);
+        float tmpSin = sinf(rot);
+        float tmpCos = cosf(rot);
 
-        tx1 = tmpSin * 8 - tmpCos;
-        tx2 = tx1 + tmpCos * 2;
+        //tmpCos = tmpCos * curve;
 
-        tz1 = tmpCos * 8 + tmpSin + pressure;
-        tz2 = tz1 - tmpSin * 2;
+        float tx1 = tmpSin * diam - (tmpCos * scale);
+        float tx2 = tx1 + (tmpCos * scale * 2.f);
+
+        float tz1 = tmpCos * diam + (tmpSin * scale);
+        float tz2 = tz1 - (tmpSin * scale * 2.f);
 
         for (y = 0; (y < rowCount) && iconCount; y++) {
-            ty1 = (y * 0x30000) - 0x48000;
-            ty2 = ty1 + 0x20000;
+            float ty1 = ((y * 3.0f) - 4.5f) * scale;
+            float ty2 = ty1 + scale * 2.f;
             pfBindTexture(NAMED_PF, 0, loadI32(1, y));
-            drawQuad(tx1, ty1, tz1,
+            drawQuadF(tx1, ty1, tz1,
                      tx2, ty1, tz2,
                      tx2, ty2, tz2,
                      tx1, ty2, tz1);
@@ -58,3 +122,4 @@
     return 0;
 }
 
+
diff --git a/libs/rs/java/Rollo/src/com/android/rollo/RolloRS.java b/libs/rs/java/Rollo/src/com/android/rollo/RolloRS.java
index d086702..fc928d6 100644
--- a/libs/rs/java/Rollo/src/com/android/rollo/RolloRS.java
+++ b/libs/rs/java/Rollo/src/com/android/rollo/RolloRS.java
@@ -37,6 +37,16 @@
 import android.view.MotionEvent;
 
 public class RolloRS {
+    public static final int STATE_POS_X = 0;
+    public static final int STATE_POS_Y = 1;
+    public static final int STATE_PRESSURE = 2;
+    public static final int STATE_ZOOM = 3;
+    public static final int STATE_WARP = 4;
+    public static final int STATE_ORIENTATION = 5;
+    public static final int STATE_SELECTION = 6;
+    public static final int STATE_FIRST_VISIBLE = 7;
+    public static final int STATE_COUNT = 8;
+
 
     public RolloRS() {
     }
@@ -48,9 +58,33 @@
         initRS();
     }
 
-    public void setPosition(float dx, float pressure) {
-        mAllocStateBuf[0] += (int)(dx);
-        mAllocStateBuf[2] = (int)(pressure * 0x40000);
+    public void setPosition(float column) {
+        mAllocStateBuf[STATE_FIRST_VISIBLE] = (int)(column * 20);
+        mAllocState.data(mAllocStateBuf);
+    }
+
+    public void setShadow(float x, float y, float size) {
+        // x and y are normalized at this point.
+        mAllocStateBuf[STATE_POS_X] = (int)(x * 1000);
+        mAllocStateBuf[STATE_POS_Y] = (int)(y * 1000);
+        mAllocStateBuf[STATE_PRESSURE] = (int)(size * 1000);
+
+        Log.e("rs","shadow x=" + Integer.toString(mAllocStateBuf[STATE_POS_X]) +
+              "  y=" + Integer.toString(mAllocStateBuf[STATE_POS_X]) +
+              "  s=" + Integer.toString(mAllocStateBuf[STATE_PRESSURE]));
+        mAllocState.data(mAllocStateBuf);
+    }
+
+    public void setZoom(float z) {
+        Log.e("rs", "zoom " + Float.toString(z));
+
+        mAllocStateBuf[STATE_ZOOM] = (int)(z * 10.f);
+        mAllocState.data(mAllocStateBuf);
+    }
+
+    public void setCurve(float c) {
+        mAllocStateBuf[STATE_WARP] = (int)(c * 100);
+        Log.e("rs", "curve " + Integer.toString(mAllocStateBuf[STATE_WARP]));
         mAllocState.data(mAllocStateBuf);
     }
 
@@ -63,7 +97,7 @@
 
     private RenderScript.Sampler mSampler;
     private RenderScript.ProgramFragmentStore mPFSBackground;
-    private RenderScript.ProgramFragmentStore mPFSImages;
+    private RenderScript.ProgramFragmentStore mPFSShadow;
     private RenderScript.ProgramFragment mPFBackground;
     private RenderScript.ProgramFragment mPFImages;
     private RenderScript.ProgramVertex mPV;
@@ -77,6 +111,9 @@
     private int[] mAllocIconIDBuf;
     private RenderScript.Allocation mAllocIconID;
 
+    private int[] mAllocScratchBuf;
+    private RenderScript.Allocation mAllocScratch;
+
     private void initNamed() {
         mRS.samplerBegin();
         mRS.samplerSet(RenderScript.SamplerParam.FILTER_MIN,
@@ -101,7 +138,7 @@
         mPFImages.bindSampler(mSampler, 1);
 
         mRS.programFragmentStoreBegin(null, null);
-        mRS.programFragmentStoreDepthFunc(RenderScript.DepthFunc.ALWAYS);
+        mRS.programFragmentStoreDepthFunc(RenderScript.DepthFunc.LESS);
         mRS.programFragmentStoreDitherEnable(false);
         mRS.programFragmentStoreDepthMask(false);
         mRS.programFragmentStoreBlendFunc(RenderScript.BlendSrcFunc.ONE, 
@@ -109,6 +146,15 @@
         mPFSBackground = mRS.programFragmentStoreCreate();
         mPFSBackground.setName("PFS");
 
+        mRS.programFragmentStoreBegin(null, null);
+        mRS.programFragmentStoreDepthFunc(RenderScript.DepthFunc.ALWAYS);
+        mRS.programFragmentStoreDitherEnable(false);
+        mRS.programFragmentStoreDepthMask(true);
+        mRS.programFragmentStoreColorMask(false, false, false, false);
+        mPFSShadow = mRS.programFragmentStoreCreate();
+        mPFSShadow.setName("PFSShadow");
+
+
 
         mPVAlloc = new ProgramVertexAlloc(mRS);
         mRS.programVertexBegin(null, null);
@@ -123,10 +169,18 @@
         //mPVAlloc.setupOrthoNormalized(320, 480);
         mRS.contextBindProgramVertex(mPV);
 
+        mAllocScratchBuf = new int[32];
+        for(int ct=0; ct < mAllocScratchBuf.length; ct++) {
+            mAllocScratchBuf[ct] = 0;
+        }
+        mAllocScratch = mRS.allocationCreatePredefSized(
+            RenderScript.ElementPredefined.USER_I32, mAllocScratchBuf.length);
+        mAllocScratch.data(mAllocScratchBuf);
 
         Log.e("rs", "Done loading named");
 
 
+
         {
             mIcons = new RenderScript.Allocation[4];
             mAllocIconIDBuf = new int[mIcons.length];
@@ -190,18 +244,21 @@
 
     private void initRS() {
         mRS.scriptCBegin();
-        mRS.scriptCSetClearColor(0.0f, 0.0f, 0.1f, 0.5f);
-        //mRS.scriptCSetScript(mRes, R.raw.rollo);
-        mRS.scriptCSetScript(mRes, R.raw.rollo2);
+        mRS.scriptCSetClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+        mRS.scriptCSetScript(mRes, R.raw.rollo);
+        //mRS.scriptCSetScript(mRes, R.raw.rollo2);
         mRS.scriptCSetRoot(true);
+        //mRS.scriptCSetClearDepth(0);
         mScript = mRS.scriptCCreate();
 
-        mAllocStateBuf = new int[] {0, 38, 0};
+        mAllocStateBuf = new int[] {0, 0, 0, 8, 0, 0, 0, 0, 38, 0};
         mAllocState = mRS.allocationCreatePredefSized(
             RenderScript.ElementPredefined.USER_I32, mAllocStateBuf.length);
         mScript.bindAllocation(mAllocState, 0);
         mScript.bindAllocation(mAllocIconID, 1);
-        setPosition(0, 0);
+        mScript.bindAllocation(mAllocScratch, 2);
+        setPosition(0);
+        setZoom(1);
 
         //RenderScript.File f = mRS.fileOpen("/sdcard/test.a3d");
 
diff --git a/libs/rs/java/Rollo/src/com/android/rollo/RolloView.java b/libs/rs/java/Rollo/src/com/android/rollo/RolloView.java
index 4b0520b..6e2768c 100644
--- a/libs/rs/java/Rollo/src/com/android/rollo/RolloView.java
+++ b/libs/rs/java/Rollo/src/com/android/rollo/RolloView.java
@@ -19,6 +19,7 @@
 import java.io.Writer;
 import java.util.ArrayList;
 import java.util.concurrent.Semaphore;
+import java.lang.Float;
 
 import android.renderscript.RSSurfaceView;
 import android.renderscript.RenderScript;
@@ -43,8 +44,7 @@
 
     public RolloView(Context context) {
         super(context);
-
-        //setFocusable(true);
+        setFocusable(true);
         getHolder().setFormat(PixelFormat.TRANSLUCENT);
     }
 
@@ -57,8 +57,6 @@
         mRS = createRenderScript();
         mRender = new RolloRS();
         mRender.init(mRS, getResources(), w, h);
-
-
     }
 
     @Override
@@ -69,6 +67,13 @@
         return super.onKeyDown(keyCode, event);
     }
 
+    boolean mControlMode = false;
+    boolean mFlingMode = false;
+    float mFlingX = 0;
+    float mFlingY = 0;
+    float mColumn = -1;
+    float mCurve = 1;
+    float mZoom = 1;
 
     @Override
     public boolean onTouchEvent(MotionEvent ev)
@@ -78,14 +83,100 @@
         if (act == ev.ACTION_UP) {
             ret = false;
         }
-        float x = ev.getX();
-        x = (x - 180) / 40;
-        //Log.e("rs", Float(x).toString());
 
-        mRender.setPosition(x, ev.getPressure());
-        //mRender.newTouchPosition((int)ev.getX(), (int)ev.getY());
+        float nx = ev.getX() / getWidth();
+        float ny = ev.getY() / getHeight();
+
+        if((ny > 0.85f) || mControlMode) {
+            mRender.setShadow(0, 0, 0);
+            mFlingMode = false;
+
+            // Projector control
+            if((nx > 0.2f) && (nx < 0.8f) || mControlMode) {
+                if(act != ev.ACTION_UP) {
+                    float zoom = 5.f;//1.f + 10.f * ev.getSize();
+                    if(mControlMode) {
+                        float dx = nx - mFlingX;
+
+                        if(ny < 0.9) {
+                            zoom = 5.f - ((0.9f - ny) * 10.f);
+                            if(zoom < 1) {
+                                zoom = 1;
+                                mControlMode = false;
+                            }
+                        }
+                        mColumn += dx * 3;// * zoom;
+                        mColumn += -(mZoom - zoom) * (nx - 0.5f) * 2 * zoom;
+                        mZoom = zoom;
+
+                        if(mColumn > 1) {
+                            mColumn = 1;
+                        }
+                        mRender.setPosition(mColumn);
+                    } else {
+                        mControlMode = true;
+                        mZoom = 5;
+                    }
+                    mFlingX = nx;
+                    mRender.setZoom(zoom);
+                } else {
+                    mControlMode = false;
+                    mRender.setZoom(1.f);
+                }
+            } else {
+                if(nx > 0.2f) {
+                    mCurve += 0.1f;
+                    if(mCurve > 2) {
+                        mCurve = 2;
+                    }
+                }
+                if(nx < 0.8f) {
+                    mCurve -= 0.1f;
+                    if(mCurve < (-2)) {
+                        mCurve = -2;
+                    }
+                }
+                mRender.setCurve(mCurve);
+            }
+
+        } else {
+            // icon control
+            if(act != ev.ACTION_UP) {
+                if(mFlingMode) {
+                    float dx = nx - mFlingX;
+                    mColumn += dx * 5;
+                    if(mColumn > 1) {
+                        mColumn = 1;
+                    }
+                    mRender.setPosition(mColumn);
+                }
+                mFlingMode = true;
+                mFlingX = nx;
+                mFlingY = ny;
+                //mRender.setShadow(nx, ny, ev.getSize());
+            } else {
+                mFlingMode = false;
+                mRender.setShadow(nx, ny, 0);
+            }
+        }
+
+
         return ret;
     }
+
+    @Override
+    public boolean onTrackballEvent(MotionEvent ev)
+    {
+        float x = ev.getX();
+        float y = ev.getY();
+        //Float tx = new Float(x);
+        //Float ty = new Float(y);
+        //Log.e("rs", "tbe " + tx.toString() + ", " + ty.toString());
+
+
+        return true;
+    }
+       
 }
 
 
diff --git a/libs/rs/rsProgramFragmentStore.cpp b/libs/rs/rsProgramFragmentStore.cpp
index 0b65680..9ee270f 100644
--- a/libs/rs/rsProgramFragmentStore.cpp
+++ b/libs/rs/rsProgramFragmentStore.cpp
@@ -61,8 +61,10 @@
         glDisable(GL_BLEND);
     }
 
+    //LOGE("pfs  %i, %i, %x", mDepthWriteEnable, mDepthTestEnable, mDepthFunc);
+
     glDepthMask(mDepthWriteEnable);
-    if(mDepthTestEnable) {
+    if(mDepthTestEnable || mDepthWriteEnable) {
         glEnable(GL_DEPTH_TEST);
         glDepthFunc(mDepthFunc);
     } else {
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index 0ec6baf..c19f0bb 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -133,13 +133,17 @@
 extern "C" float loadF(uint32_t bank, uint32_t offset)
 {
     GET_TLS();
-    return static_cast<const float *>(sc->mSlots[bank]->getPtr())[offset];
+    float f = static_cast<const float *>(sc->mSlots[bank]->getPtr())[offset];
+    //LOGE("loadF %i %i = %f %x", bank, offset, f, ((int *)&f)[0]);
+    return f;
 }
 
 extern "C" int32_t loadI32(uint32_t bank, uint32_t offset)
 {
     GET_TLS();
-    return static_cast<const int32_t *>(sc->mSlots[bank]->getPtr())[offset];
+    int32_t t = static_cast<const int32_t *>(sc->mSlots[bank]->getPtr())[offset];
+    //LOGE("loadI32 %i %i = %i", bank, offset, t);
+    return t;
 }
 
 extern "C" uint32_t loadU32(uint32_t bank, uint32_t offset)
@@ -163,6 +167,7 @@
 
 extern "C" void storeF(uint32_t bank, uint32_t offset, float v)
 {
+    //LOGE("storeF %i %i %f", bank, offset, v);
     GET_TLS();
     static_cast<float *>(sc->mSlots[bank]->getPtr())[offset] = v;
 }
@@ -307,6 +312,47 @@
     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
 }
 
+extern "C" void drawQuadF(float x1, float y1, float z1,
+                          float x2, float y2, float z2,
+                          float x3, float y3, float z3,
+                          float x4, float y4, float z4)
+{
+    GET_TLS();
+
+    //LOGE("Quad");
+    //LOGE("%4.2f, %4.2f, %4.2f", x1, y1, z1);
+    //LOGE("%4.2f, %4.2f, %4.2f", x2, y2, z2);
+    //LOGE("%4.2f, %4.2f, %4.2f", x3, y3, z3);
+    //LOGE("%4.2f, %4.2f, %4.2f", x4, y4, z4);
+
+    float vtx[] = {x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4};
+    static const float tex[] = {0,0, 0,1, 1,1, 1,0};
+
+
+    rsc->setupCheck();
+
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tm->mBufferObjects[1]);
+
+    glEnableClientState(GL_VERTEX_ARRAY);
+    glVertexPointer(3, GL_FLOAT, 0, vtx);
+
+    glClientActiveTexture(GL_TEXTURE0);
+    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+    glTexCoordPointer(2, GL_FLOAT, 0, tex);
+    glClientActiveTexture(GL_TEXTURE1);
+    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+    glTexCoordPointer(2, GL_FLOAT, 0, tex);
+    glClientActiveTexture(GL_TEXTURE0);
+
+    glDisableClientState(GL_NORMAL_ARRAY);
+    glDisableClientState(GL_COLOR_ARRAY);
+
+    //glColorPointer(4, GL_UNSIGNED_BYTE, 12, ptr);
+
+    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+}
+
 extern "C" void drawQuad(int32_t x1, int32_t y1, int32_t z1,
                          int32_t x2, int32_t y2, int32_t z2,
                          int32_t x3, int32_t y3, int32_t z3,
@@ -368,6 +414,28 @@
     return int32_t(s * 0x10000);
 }
 
+extern "C" float sinf(float angle)
+{
+    float s = (float)sin(angle);
+    return s;
+}
+
+extern "C" float cosf(float angle)
+{
+    float s = (float)cos(angle);
+    return s;
+}
+
+extern "C" void pfClearColor(float r, float g, float b, float a)
+{
+    //LOGE("c %f %f %f %f", r, g, b, a);
+    GET_TLS();
+    sc->mEnviroment.mClearColor[0] = r;
+    sc->mEnviroment.mClearColor[1] = g;
+    sc->mEnviroment.mClearColor[2] = b;
+    sc->mEnviroment.mClearColor[3] = a;
+}
+
 extern "C" void pfBindTexture(RsProgramFragment vpf, uint32_t slot, RsAllocation va)
 {
     GET_TLS();