Renderscript samples.
Resolving name conflict in model viewer.
Adding fov projection matrix function.
Adding helper methods for blending.

Change-Id: Ibd3f1510436811398787c285845d050158bd6de8
diff --git a/java/ModelViewer/AndroidManifest.xml b/java/ModelViewer/AndroidManifest.xml
index 39976d2..959fe53 100644
--- a/java/ModelViewer/AndroidManifest.xml
+++ b/java/ModelViewer/AndroidManifest.xml
@@ -2,7 +2,8 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.modelviewer">
     <application android:label="ModelViewer">
-        <activity android:name="ModelViewer"
+        <activity android:name="SimpleModel"
+                  android:label="SimpleModel"
                   android:screenOrientation="portrait"
                   android:theme="@android:style/Theme.Black.NoTitleBar">
             <intent-filter>
diff --git a/java/ModelViewer/src/com/android/modelviewer/SceneGraphRS.java b/java/ModelViewer/src/com/android/modelviewer/SceneGraphRS.java
index 3f4d930..9672a6a 100644
--- a/java/ModelViewer/src/com/android/modelviewer/SceneGraphRS.java
+++ b/java/ModelViewer/src/com/android/modelviewer/SceneGraphRS.java
@@ -90,7 +90,7 @@
     }
 
     private void initPFS() {
-        ProgramStore.Builder b = new ProgramStore.Builder(mRS, null, null);
+        ProgramStore.Builder b = new ProgramStore.Builder(mRS);
 
         b.setDepthFunc(ProgramStore.DepthFunc.LESS);
         b.setDitherEnable(false);
@@ -118,7 +118,7 @@
     }
 
     private void initPV() {
-        ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS, null, null);
+        ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS);
         mPVBackground = pvb.create();
 
         mPVA = new ProgramVertex.MatrixAllocation(mRS);
diff --git a/java/ModelViewer/src/com/android/modelviewer/ModelViewer.java b/java/ModelViewer/src/com/android/modelviewer/SimpleModel.java
similarity index 93%
rename from java/ModelViewer/src/com/android/modelviewer/ModelViewer.java
rename to java/ModelViewer/src/com/android/modelviewer/SimpleModel.java
index 7491744..cb7c39c 100644
--- a/java/ModelViewer/src/com/android/modelviewer/ModelViewer.java
+++ b/java/ModelViewer/src/com/android/modelviewer/SimpleModel.java
@@ -37,9 +37,9 @@
 
 import java.lang.Runtime;
 
-public class ModelViewer extends Activity {
+public class SimpleModel extends Activity {
 
-    private ModelViewerView mView;
+    private SimpleModelView mView;
 
     @Override
     public void onCreate(Bundle icicle) {
@@ -47,7 +47,7 @@
 
         // Create our Preview view and set it as the content of our
         // Activity
-        mView = new ModelViewerView(this);
+        mView = new SimpleModelView(this);
         setContentView(mView);
     }
 
diff --git a/java/ModelViewer/src/com/android/modelviewer/ModelViewerRS.java b/java/ModelViewer/src/com/android/modelviewer/SimpleModelRS.java
similarity index 93%
rename from java/ModelViewer/src/com/android/modelviewer/ModelViewerRS.java
rename to java/ModelViewer/src/com/android/modelviewer/SimpleModelRS.java
index 479aaf3..b8b0119 100644
--- a/java/ModelViewer/src/com/android/modelviewer/ModelViewerRS.java
+++ b/java/ModelViewer/src/com/android/modelviewer/SimpleModelRS.java
@@ -24,7 +24,7 @@
 import android.util.Log;
 
 
-public class ModelViewerRS {
+public class SimpleModelRS {
 
     private final int STATE_LAST_FOCUS = 1;
 
@@ -32,7 +32,7 @@
     int mHeight;
     int mRotation;
 
-    public ModelViewerRS() {
+    public SimpleModelRS() {
     }
 
     public void init(RenderScriptGL rs, Resources res, int width, int height) {
@@ -60,7 +60,7 @@
     private Font mItalic;
     private Allocation mTextAlloc;
 
-    private ScriptC_Modelviewer mScript;
+    private ScriptC_Simplemodel mScript;
 
     int mLastX;
     int mLastY;
@@ -86,7 +86,7 @@
     }
 
     private void initPFS() {
-        ProgramStore.Builder b = new ProgramStore.Builder(mRS, null, null);
+        ProgramStore.Builder b = new ProgramStore.Builder(mRS);
 
         b.setDepthFunc(ProgramStore.DepthFunc.LESS);
         b.setDitherEnable(false);
@@ -114,7 +114,7 @@
     }
 
     private void initPV() {
-        ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS, null, null);
+        ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS);
         mPVBackground = pvb.create();
 
         mPVA = new ProgramVertex.MatrixAllocation(mRS);
@@ -139,7 +139,7 @@
 
     private void initRS() {
 
-        mScript = new ScriptC_Modelviewer(mRS, mRes, R.raw.modelviewer, true);
+        mScript = new ScriptC_Simplemodel(mRS, mRes, R.raw.simplemodel, true);
 
         initPFS();
         initPF();
diff --git a/java/ModelViewer/src/com/android/modelviewer/ModelViewerView.java b/java/ModelViewer/src/com/android/modelviewer/SimpleModelView.java
similarity index 93%
rename from java/ModelViewer/src/com/android/modelviewer/ModelViewerView.java
rename to java/ModelViewer/src/com/android/modelviewer/SimpleModelView.java
index 061cf8e..2574fdd 100644
--- a/java/ModelViewer/src/com/android/modelviewer/ModelViewerView.java
+++ b/java/ModelViewer/src/com/android/modelviewer/SimpleModelView.java
@@ -39,15 +39,15 @@
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 
-public class ModelViewerView extends RSSurfaceView {
+public class SimpleModelView extends RSSurfaceView {
 
-    public ModelViewerView(Context context) {
+    public SimpleModelView(Context context) {
         super(context);
         //setFocusable(true);
     }
 
     private RenderScriptGL mRS;
-    private ModelViewerRS mRender;
+    private SimpleModelRS mRender;
 
 
     public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
@@ -55,7 +55,7 @@
         if (mRS == null) {
             mRS = createRenderScript(true);
             mRS.contextSetSurface(w, h, holder.getSurface());
-            mRender = new ModelViewerRS();
+            mRender = new SimpleModelRS();
             mRender.init(mRS, getResources(), w, h);
         }
     }
diff --git a/java/ModelViewer/src/com/android/modelviewer/modelviewer.rs b/java/ModelViewer/src/com/android/modelviewer/simplemodel.rs
similarity index 100%
rename from java/ModelViewer/src/com/android/modelviewer/modelviewer.rs
rename to java/ModelViewer/src/com/android/modelviewer/simplemodel.rs
diff --git a/java/Samples/AndroidManifest.xml b/java/Samples/AndroidManifest.xml
index 17c6b16..be191f2 100644
--- a/java/Samples/AndroidManifest.xml
+++ b/java/Samples/AndroidManifest.xml
@@ -11,5 +11,14 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+        
+        <activity android:name="RsRenderStates"
+                  android:label="RsStates"                  
+                  android:theme="@android:style/Theme.Black.NoTitleBar">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
     </application>
 </manifest>
diff --git a/java/Samples/res/drawable/data.png b/java/Samples/res/drawable/data.png
new file mode 100644
index 0000000..8e34714
--- /dev/null
+++ b/java/Samples/res/drawable/data.png
Binary files differ
diff --git a/java/Samples/res/drawable/leaf.png b/java/Samples/res/drawable/leaf.png
new file mode 100644
index 0000000..3cd3775
--- /dev/null
+++ b/java/Samples/res/drawable/leaf.png
Binary files differ
diff --git a/java/ModelViewer/src/com/android/modelviewer/ModelViewer.java b/java/Samples/src/com/android/samples/RsRenderStates.java
similarity index 91%
copy from java/ModelViewer/src/com/android/modelviewer/ModelViewer.java
copy to java/Samples/src/com/android/samples/RsRenderStates.java
index 7491744..391007e 100644
--- a/java/ModelViewer/src/com/android/modelviewer/ModelViewer.java
+++ b/java/Samples/src/com/android/samples/RsRenderStates.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.modelviewer;
+package com.android.samples;
 
 import android.renderscript.RSSurfaceView;
 import android.renderscript.RenderScript;
@@ -37,9 +37,9 @@
 
 import java.lang.Runtime;
 
-public class ModelViewer extends Activity {
+public class RsRenderStates extends Activity {
 
-    private ModelViewerView mView;
+    private RsRenderStatesView mView;
 
     @Override
     public void onCreate(Bundle icicle) {
@@ -47,7 +47,7 @@
 
         // Create our Preview view and set it as the content of our
         // Activity
-        mView = new ModelViewerView(this);
+        mView = new RsRenderStatesView(this);
         setContentView(mView);
     }
 
diff --git a/java/Samples/src/com/android/samples/RsRenderStatesRS.java b/java/Samples/src/com/android/samples/RsRenderStatesRS.java
new file mode 100644
index 0000000..5a6ff23
--- /dev/null
+++ b/java/Samples/src/com/android/samples/RsRenderStatesRS.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.samples;
+
+import java.io.Writer;
+
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.renderscript.ProgramStore.DepthFunc;
+import android.util.Log;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap;
+
+
+public class RsRenderStatesRS {
+
+    int mWidth;
+    int mHeight;
+
+    public RsRenderStatesRS() {
+    }
+
+    public void init(RenderScriptGL rs, Resources res, int width, int height) {
+        mRS = rs;
+        mRes = res;
+        mWidth = width;
+        mHeight = height;
+        mOptionsARGB.inScaled = false;
+        mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888;
+        mMode = 0;
+        mMaxModes = 4;
+        initRS();
+    }
+
+    private Resources mRes;
+    private RenderScriptGL mRS;
+
+    private Sampler mSampler;
+
+    private ProgramStore mProgStoreBlendNone;
+    private ProgramStore mProgStoreBlendAlpha;
+    private ProgramStore mProgStoreBlendAdd;
+
+    private ProgramFragment mProgFragmentTexture;
+    private ProgramFragment mProgFragmentColor;
+    private ProgramVertex mProgVertex;
+    private ProgramVertex.MatrixAllocation mPVA;
+
+    private Allocation mTexOpaque;
+    private Allocation mTexTransparent;
+
+    private Allocation mAllocPV;
+
+    private Mesh mMbyNMesh;
+
+    Font mFontSans;
+    Font mFontSerif;
+    Font mFontSerifBold;
+    Font mFontSerifItalic;
+    Font mFontSerifBoldItalic;
+    Font mFontMono;
+
+    private Allocation mTextAlloc;
+
+    private ScriptC_Rsrenderstates mScript;
+
+    private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
+
+    int mMode;
+    int mMaxModes;
+
+    public void onActionDown(int x, int y) {
+        mMode ++;
+        mMode = mMode % mMaxModes;
+        mScript.set_gDisplayMode(mMode);
+    }
+
+
+    private void initProgramStore() {
+        // Use stock the stock program store object
+        mProgStoreBlendNone = ProgramStore.BlendNone_DepthNoDepth(mRS);
+
+        // Create a custom program store
+        ProgramStore.Builder builder = new ProgramStore.Builder(mRS);
+        builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
+        builder.setBlendFunc(ProgramStore.BlendSrcFunc.SRC_ALPHA,
+                             ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA);
+        builder.setDitherEnable(false);
+        builder.setDepthMask(false);
+        mProgStoreBlendAlpha = builder.create();
+
+        mProgStoreBlendAdd = ProgramStore.BlendAdd_DepthNoDepth(mRS);
+
+        mScript.set_gProgStoreBlendNone(mProgStoreBlendNone);
+        mScript.set_gProgStoreBlendAlpha(mProgStoreBlendAlpha);
+        mScript.set_gProgStoreBlendAdd(mProgStoreBlendAdd);
+    }
+
+    private void initProgramFragment() {
+
+        Sampler.Builder bs = new Sampler.Builder(mRS);
+        bs.setMin(Sampler.Value.LINEAR);
+        bs.setMag(Sampler.Value.LINEAR);
+        bs.setWrapS(Sampler.Value.CLAMP);
+        bs.setWrapT(Sampler.Value.CLAMP);
+        mSampler = bs.create();
+
+        ProgramFragment.Builder texBuilder = new ProgramFragment.Builder(mRS);
+        texBuilder.setTexture(ProgramFragment.Builder.EnvMode.REPLACE,
+                              ProgramFragment.Builder.Format.RGBA, 0);
+        mProgFragmentTexture = texBuilder.create();
+        mProgFragmentTexture.bindSampler(mSampler, 0);
+
+        ProgramFragment.Builder colBuilder = new ProgramFragment.Builder(mRS);
+        colBuilder.setVaryingColor(false);
+        mProgFragmentColor = colBuilder.create();
+
+        mScript.set_gProgFragmentColor(mProgFragmentColor);
+        mScript.set_gProgFragmentTexture(mProgFragmentTexture);
+    }
+
+    private void initProgramVertex() {
+        ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS);
+        mProgVertex = pvb.create();
+
+        mPVA = new ProgramVertex.MatrixAllocation(mRS);
+        mProgVertex.bindAllocation(mPVA);
+        mPVA.setupOrthoWindow(mWidth, mHeight);
+
+        mScript.set_gProgVertex(mProgVertex);
+    }
+
+    private Allocation loadTextureRGB(int id) {
+        final Allocation allocation = Allocation.createFromBitmapResource(mRS, mRes,
+                id, Element.RGB_565(mRS), false);
+        allocation.uploadToTexture(0);
+        return allocation;
+    }
+
+    private Allocation loadTextureARGB(int id) {
+        Bitmap b = BitmapFactory.decodeResource(mRes, id, mOptionsARGB);
+        final Allocation allocation = Allocation.createFromBitmap(mRS, b, Element.RGBA_8888(mRS), false);
+        allocation.uploadToTexture(0);
+        return allocation;
+    }
+
+    private void loadImages() {
+        mTexOpaque = loadTextureRGB(R.drawable.data);
+        mTexTransparent = loadTextureARGB(R.drawable.leaf);
+
+        mScript.set_gTexOpaque(mTexOpaque);
+        mScript.set_gTexTransparent(mTexTransparent);
+    }
+
+    private void initFonts() {
+        // Sans font by family name
+        mFontSans = Font.createFromFamily(mRS, mRes, "sans-serif", Font.Style.NORMAL, 8);
+        // Create font by file name
+        mFontSerif = Font.create(mRS, mRes, "DroidSerif-Regular.ttf", 8);
+        // Create fonts by family and style
+        mFontSerifBold = Font.createFromFamily(mRS, mRes, "serif", Font.Style.BOLD, 8);
+        mFontSerifItalic = Font.createFromFamily(mRS, mRes, "serif", Font.Style.ITALIC, 8);
+        mFontSerifBoldItalic = Font.createFromFamily(mRS, mRes, "serif", Font.Style.BOLD_ITALIC, 8);
+        mFontMono = Font.createFromFamily(mRS, mRes, "mono", Font.Style.NORMAL, 8);
+
+        mScript.set_gFontSans(mFontSans);
+        mScript.set_gFontSerif(mFontSerif);
+        mScript.set_gFontSerifBold(mFontSerifBold);
+        mScript.set_gFontSerifItalic(mFontSerifItalic);
+        mScript.set_gFontSerifBoldItalic(mFontSerifBoldItalic);
+        mScript.set_gFontMono(mFontMono);
+    }
+
+    private void initRS() {
+
+        mScript = new ScriptC_Rsrenderstates(mRS, mRes, R.raw.rsrenderstates, true);
+
+        initProgramStore();
+        initProgramFragment();
+        initProgramVertex();
+
+        initFonts();
+
+        loadImages();
+
+
+
+        mRS.contextBindRootScript(mScript);
+    }
+}
+
+
+
diff --git a/java/ModelViewer/src/com/android/modelviewer/ModelViewerView.java b/java/Samples/src/com/android/samples/RsRenderStatesView.java
similarity index 85%
copy from java/ModelViewer/src/com/android/modelviewer/ModelViewerView.java
copy to java/Samples/src/com/android/samples/RsRenderStatesView.java
index 061cf8e..5548de3 100644
--- a/java/ModelViewer/src/com/android/modelviewer/ModelViewerView.java
+++ b/java/Samples/src/com/android/samples/RsRenderStatesView.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.modelviewer;
+package com.android.samples;
 
 import java.io.Writer;
 import java.util.ArrayList;
@@ -39,15 +39,15 @@
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 
-public class ModelViewerView extends RSSurfaceView {
+public class RsRenderStatesView extends RSSurfaceView {
 
-    public ModelViewerView(Context context) {
+    public RsRenderStatesView(Context context) {
         super(context);
         //setFocusable(true);
     }
 
     private RenderScriptGL mRS;
-    private ModelViewerRS mRender;
+    private RsRenderStatesRS mRender;
 
 
     public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
@@ -55,7 +55,7 @@
         if (mRS == null) {
             mRS = createRenderScript(true);
             mRS.contextSetSurface(w, h, holder.getSurface());
-            mRender = new ModelViewerRS();
+            mRender = new RsRenderStatesRS();
             mRender.init(mRS, getResources(), w, h);
         }
     }
@@ -80,13 +80,13 @@
     @Override
     public boolean onTouchEvent(MotionEvent ev)
     {
-        boolean ret = true;
+        boolean ret = false;
         int act = ev.getAction();
-        if (act == ev.ACTION_UP) {
-            ret = false;
+        if (act == ev.ACTION_DOWN) {
+            mRender.onActionDown((int)ev.getX(), (int)ev.getY());
+            ret = true;
         }
 
-        mRender.touchEvent((int)ev.getX(), (int)ev.getY());
         return ret;
     }
 }
diff --git a/java/Samples/src/com/android/samples/rsrenderstates.rs b/java/Samples/src/com/android/samples/rsrenderstates.rs
new file mode 100644
index 0000000..1526a50
--- /dev/null
+++ b/java/Samples/src/com/android/samples/rsrenderstates.rs
@@ -0,0 +1,194 @@
+// Copyright (C) 2009 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.samples)
+
+#include "rs_graphics.rsh"
+
+rs_program_vertex gProgVertex;
+rs_program_fragment gProgFragmentColor;
+rs_program_fragment gProgFragmentTexture;
+
+rs_program_store gProgStoreBlendNone;
+rs_program_store gProgStoreBlendAlpha;
+rs_program_store gProgStoreBlendAdd;
+
+rs_allocation gTexOpaque;
+rs_allocation gTexTransparent;
+
+rs_mesh gMbyNMesh;
+
+rs_font gFontSans;
+rs_font gFontSerif;
+rs_font gFontSerifBold;
+rs_font gFontSerifItalic;
+rs_font gFontSerifBoldItalic;
+rs_font gFontMono;
+
+int gDisplayMode;
+
+#pragma rs export_var(gProgVertex, gProgFragmentColor, gProgFragmentTexture)
+#pragma rs export_var(gProgStoreBlendNone, gProgStoreBlendAlpha, gProgStoreBlendAdd)
+#pragma rs export_var(gTexOpaque, gTexTransparent)
+#pragma rs export_var(gMbyNMesh)
+#pragma rs export_var(gFontSans, gFontSerif, gFontSerifBold, gFontSerifItalic, gFontSerifBoldItalic, gFontMono)
+
+//What we are showing
+#pragma rs export_var(gDisplayMode)
+
+void init() {
+}
+
+void displayFontSamples() {
+    rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
+    int yPos = 30;
+    rsgBindFont(gFontSans);
+    rsgDrawText("Sans font sample", 30, yPos);
+    yPos += 30;
+    rsgFontColor(0.5f, 0.9f, 0.5f, 1.0f);
+    rsgBindFont(gFontSerif);
+    rsgDrawText("Serif font sample", 30, yPos);
+    yPos += 30;
+    rsgFontColor(0.7f, 0.7f, 0.7f, 1.0f);
+    rsgBindFont(gFontSerifBold);
+    rsgDrawText("Serif Bold font sample", 30, yPos);
+    yPos += 30;
+    rsgFontColor(0.5f, 0.5f, 0.9f, 1.0f);
+    rsgBindFont(gFontSerifItalic);
+    rsgDrawText("Serif Italic font sample", 30, yPos);
+    yPos += 30;
+    rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
+    rsgBindFont(gFontSerifBoldItalic);
+    rsgDrawText("Serif Bold Italic font sample", 30, yPos);
+    yPos += 30;
+    rsgBindFont(gFontMono);
+    rsgDrawText("Monospace font sample", 30, yPos);
+}
+
+void displayShaderSamples() {
+    // Default vertex sahder
+    rsgBindProgramVertex(gProgVertex);
+    rs_matrix4x4 matrix;
+    rsMatrixLoadIdentity(&matrix);
+    rsgProgramVertexLoadModelMatrix(&matrix);
+
+    // Fragment shader with texture
+    rsgBindProgramStore(gProgStoreBlendNone);
+    rsgBindProgramFragment(gProgFragmentTexture);
+    rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque);
+
+    rsgDrawQuadTexCoords(0, 0,     0, 0, 0,
+                         0, 256,   0, 0, 1,
+                         256, 256, 0, 1, 1,
+                         256, 0,   0, 1, 0);
+
+    rsgDrawQuadTexCoords(200, 0,     0, 0, 0,
+                         200, 128,   0, 0, 1,
+                         328, 128,   0, 1, 1,
+                         328, 0,     0, 1, 0);
+
+    rsgBindProgramStore(gProgStoreBlendAlpha);
+    rsgBindTexture(gProgFragmentTexture, 0, gTexTransparent);
+    rsgDrawQuadTexCoords(0, 200,   0, 0, 0,
+                         0, 328,   0, 0, 1,
+                         128, 328, 0, 1, 1,
+                         128, 200, 0, 1, 0);
+
+    // Fragment program with simple color
+    rsgBindProgramFragment(gProgFragmentColor);
+    rsgProgramFragmentConstantColor(gProgFragmentColor, 0.9, 0.3, 0.3, 1);
+    rsgDrawRect(200, 300, 350, 450, 0);
+    rsgProgramFragmentConstantColor(gProgFragmentColor, 0.3, 0.9, 0.3, 1);
+    rsgDrawRect(50, 400, 400, 600, 0);
+
+    rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
+    rsgBindFont(gFontMono);
+    rsgDrawText("Texture shader", 10, 50);
+    rsgDrawText("Alpha-blended texture shader", 10, 280);
+    rsgDrawText("Flat color shader", 100, 450);
+}
+
+void displayBlendingSamples() {
+    int i;
+
+    rsgBindProgramVertex(gProgVertex);
+    rs_matrix4x4 matrix;
+    rsMatrixLoadIdentity(&matrix);
+    rsgProgramVertexLoadModelMatrix(&matrix);
+
+    rsgBindProgramFragment(gProgFragmentColor);
+
+    rsgBindProgramStore(gProgStoreBlendNone);
+    for(i = 0; i < 3; i ++) {
+        float iPlusOne = (float)(i + 1);
+        rsgProgramFragmentConstantColor(gProgFragmentColor,
+                                        0.1f*iPlusOne, 0.2f*iPlusOne, 0.3f*iPlusOne, 1);
+        float yPos = 150 * (float)i;
+        rsgDrawRect(0, yPos, 200, yPos + 200, 0);
+    }
+
+    rsgBindProgramStore(gProgStoreBlendAlpha);
+    for(i = 0; i < 3; i ++) {
+        float iPlusOne = (float)(i + 1);
+        rsgProgramFragmentConstantColor(gProgFragmentColor,
+                                        0.2f*iPlusOne, 0.3f*iPlusOne, 0.1f*iPlusOne, 0.5);
+        float yPos = 150 * (float)i;
+        rsgDrawRect(150, yPos, 350, yPos + 200, 0);
+    }
+
+    rsgBindProgramStore(gProgStoreBlendAdd);
+    for(i = 0; i < 3; i ++) {
+        float iPlusOne = (float)(i + 1);
+        rsgProgramFragmentConstantColor(gProgFragmentColor,
+                                        0.3f*iPlusOne, 0.1f*iPlusOne, 0.2f*iPlusOne, 0.5);
+        float yPos = 150 * (float)i;
+        rsgDrawRect(300, yPos, 500, yPos + 200, 0);
+    }
+
+
+    rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
+    rsgBindFont(gFontMono);
+    rsgDrawText("No Blending", 10, 50);
+    rsgDrawText("Alpha Blending", 160, 150);
+    rsgDrawText("Additive Blending", 320, 250);
+
+}
+
+void displayMeshSamples() {
+}
+
+int root(int launchID) {
+
+    rsgClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+    rsgClearDepth(1.0f);
+
+    switch(gDisplayMode) {
+    case 0:
+        displayFontSamples();
+        break;
+    case 1:
+        displayShaderSamples();
+        break;
+    case 2:
+        displayBlendingSamples();
+        break;
+    case 3:
+        displayMeshSamples();
+        break;
+    }
+
+    return 10;
+}
diff --git a/scriptc/rs_core.rsh b/scriptc/rs_core.rsh
index 0bfb3b9..99fc166 100644
--- a/scriptc/rs_core.rsh
+++ b/scriptc/rs_core.rsh
@@ -429,6 +429,15 @@
     m->m[15]= 0.f;
 }
 
+static void __attribute__((overloadable))
+rsMatrixLoadPerspective(rs_matrix4x4* m, float fovy, float aspect, float near, float far) {
+    float top = near * tan((float) (fovy * M_PI / 360.0f));
+    float bottom = -top;
+    float left = bottom * aspect;
+    float right = top * aspect;
+    rsMatrixLoadFrustum(m, left, right, bottom, top, near, far);
+}
+
 static float4 __attribute__((overloadable))
 rsMatrixMultiply(rs_matrix4x4 *m, float4 in) {
     float4 ret;