Merge "Add --auto-add-overlay option to aapt. DO NOT MERGE" into eclair
diff --git a/Android.mk b/Android.mk
index 4c90ece..5574886 100644
--- a/Android.mk
+++ b/Android.mk
@@ -355,6 +355,8 @@
 
 sample_dir := development/samples
 
+# the list here should match the list of samples included in the sdk samples package
+# (see development/build/sdk.atree)
 web_docs_sample_code_flags := \
 		-hdf android.hasSamples 1 \
 		-samplecode $(sample_dir)/ApiDemos \
@@ -365,6 +367,8 @@
 		            resources/samples/BusinessCard "Business Card" \
 		-samplecode $(sample_dir)/ContactManager \
 		            resources/samples/ContactManager "Contact Manager" \
+                -samplecode $(sample_dir)/CubeLiveWallpaper \
+                            resources/samples/CubeLiveWallpaper "Live Wallpaper" \
 		-samplecode $(sample_dir)/Home \
 		            resources/samples/Home "Home" \
 		-samplecode $(sample_dir)/JetBoy \
@@ -375,6 +379,8 @@
 		            resources/samples/MultiResolution "Multiple Resolutions" \
 		-samplecode $(sample_dir)/NotePad \
 		            resources/samples/NotePad "Note Pad" \
+                -samplecode $(sample_dir)/SampleSyncAdapter \
+                            resources/samples/SampleSyncAdapter "Sample Sync Adapter" \
 		-samplecode $(sample_dir)/SearchableDictionary \
 		            resources/samples/SearchableDictionary "Searchable Dictionary" \
 		-samplecode $(sample_dir)/Snake \
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index ecee0d0..c5c14d3 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -434,7 +434,7 @@
     private boolean mWrapContent;
 
     // whether support multi-touch
-    private static boolean mSupportMultiTouch;
+    private boolean mSupportMultiTouch;
     // use the framework's ScaleGestureDetector to handle multi-touch
     private ScaleGestureDetector mScaleDetector;
     // minimum scale change during multi-touch zoom
diff --git a/core/java/android/webkit/WebViewDatabase.java b/core/java/android/webkit/WebViewDatabase.java
index 6e10811..110e4f8 100644
--- a/core/java/android/webkit/WebViewDatabase.java
+++ b/core/java/android/webkit/WebViewDatabase.java
@@ -27,6 +27,7 @@
 import android.database.Cursor;
 import android.database.DatabaseUtils;
 import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteException;
 import android.database.sqlite.SQLiteStatement;
 import android.util.Log;
 import android.webkit.CookieManager.Cookie;
@@ -174,7 +175,16 @@
     public static synchronized WebViewDatabase getInstance(Context context) {
         if (mInstance == null) {
             mInstance = new WebViewDatabase();
-            mDatabase = context.openOrCreateDatabase(DATABASE_FILE, 0, null);
+            try {
+                mDatabase = context
+                        .openOrCreateDatabase(DATABASE_FILE, 0, null);
+            } catch (SQLiteException e) {
+                // try again by deleting the old db and create a new one
+                if (context.deleteDatabase(DATABASE_FILE)) {
+                    mDatabase = context.openOrCreateDatabase(DATABASE_FILE, 0,
+                            null);
+                }
+            }
 
             // mDatabase should not be null, 
             // the only case is RequestAPI test has problem to create db 
@@ -194,8 +204,16 @@
                 mDatabase.setLockingEnabled(false);
             }
 
-            mCacheDatabase = context.openOrCreateDatabase(CACHE_DATABASE_FILE,
-                    0, null);
+            try {
+                mCacheDatabase = context.openOrCreateDatabase(
+                        CACHE_DATABASE_FILE, 0, null);
+            } catch (SQLiteException e) {
+                // try again by deleting the old db and create a new one
+                if (context.deleteDatabase(CACHE_DATABASE_FILE)) {
+                    mCacheDatabase = context.openOrCreateDatabase(
+                            CACHE_DATABASE_FILE, 0, null);
+                }
+            }
 
             // mCacheDatabase should not be null, 
             // the only case is RequestAPI test has problem to create db 
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 6cd6ff9..0b6f97e 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -218,8 +218,4 @@
     <!-- Component name of the default wallpaper. This will be ImageWallpaper if not 
          specified -->
     <string name="default_wallpaper_component">@null</string>
-
-    <!-- Flag indicating whether headset events are used by kernel to indicate
-    TTY mode changes. -->
-    <bool name="tty_mode_uses_headset_events">false</bool>
 </resources>
diff --git a/docs/html/resources/articles/images/live_wallpapers_small.png b/docs/html/resources/articles/images/live_wallpapers_small.png
new file mode 100644
index 0000000..3b49b24
--- /dev/null
+++ b/docs/html/resources/articles/images/live_wallpapers_small.png
Binary files differ
diff --git a/docs/html/resources/articles/index.jd b/docs/html/resources/articles/index.jd
index 4fda6d7..d2f0996 100644
--- a/docs/html/resources/articles/index.jd
+++ b/docs/html/resources/articles/index.jd
@@ -77,6 +77,11 @@
 </dl>
 
 <dl>
+  <dt><a href="{@docRoot}resources/articles/live-wallpapers.html">Live Wallpapers</a></dt>
+  <dd>Live wallpapers are richer, animated, interactive backgrounds that users can display in their home screens. Learn how to create a live wallpaper and bundle it in an application that users can install on their devices.</dd>
+</dl>
+
+<dl>
   <dt><a href="{@docRoot}resources/articles/on-screen-inputs.html">Onscreen Input Methods</a></dt>
   <dd>The Input Method Framework (IMF) allows users to take advantage of on-screen input methods, such as software keyboards. This article provides an overview of Input Method Editors (IMEs) and how applications interact with them.</dd>
 </dl>
diff --git a/docs/html/resources/articles/live-wallpapers.jd b/docs/html/resources/articles/live-wallpapers.jd
new file mode 100644
index 0000000..8dda879
--- /dev/null
+++ b/docs/html/resources/articles/live-wallpapers.jd
@@ -0,0 +1,84 @@
+page.title=Live Wallpapers
+@jd:body
+
+<p>Starting with Android 2.1 (API Level 7), users can now enjoy <em>live
+wallpapers</em> &mdash; richer, animated, interactive backgrounds &mdash; on
+their home screens. A live wallpaper is very similar to a normal Android
+application and has access to all the facilities of the platform: SGL (2D
+drawing), OpenGL (3D drawing), GPS, accelerometers, network access, etc. The
+live wallpapers included on Nexus One demonstrate the use of some of these APIs
+to create fun and interesting user experiences. For instance, the Grass
+wallpaper uses the phone's location to compute sunrise and sunset times in order
+to display the appropriate sky.</p>
+
+<img src="images/live_wallpapers_small.png" style="align:center" />
+
+<p>Creating your own live wallpaper is easy, especially if you have had
+previous experience with <a
+href="../../../reference/android/view/SurfaceView.html"><code>SurfaceView</code></a> or <a
+href="../../../reference/android/graphics/Canvas.html"><code>Canvas</code></a>. 
+To learn how to create a live wallpaper, you should check out the <a 
+href="../samples/CubeLiveWallpaper/index.html">CubeLiveWallpaper sample code</a>.</p>
+
+<p>In terms of implementation, a live wallpaper is very similar to a regular
+Android <a href="../../../reference/android/app/Service.html">service</a>. The
+only difference is the addition of a new method, <a
+href="../../../reference/android/service/wallpaper/WallpaperService.
+html#onCreateEngine()"><code>onCreateEngine()</code></a>, whose goal is to create a <a
+href="../../../reference/android/service/wallpaper/WallpaperService.Engine.html">
+<code>WallpaperService.Engine</code></a>. The engine is responsible for
+handling the lifecycle and drawing of a wallpaper. The system provides a surface
+on which you can draw, just like you would with a <code>SurfaceView</code></a>.
+Drawing a wallpaper can be very expensive so you should optimize your code
+as much as possible to avoid using too much CPU, not only for battery life
+but also to avoid slowing down the rest of the system. That is also why the
+most important part of the lifecycle of a wallpaper is <a href="../../../reference/android/service/wallpaper/WallpaperService.Engine.html#onVisibilityChanged%28boolean%29">when it becomes invisible</a>. 
+When invisible, such as when the user launches an application that covers
+the home screen, a wallpaper must stop all activity.</p>
+
+<p>The engine can also implement several methods to interact with the user
+or the home application. For instance, if you want your wallpaper to scroll
+along when the user swipes from one home screen to another, you can use <a href="../../../reference/android/service/wallpaper/WallpaperService.Engine.html#onOffsetsChanged%28float,%20float,%20float,%20float,%20int,%20int%29"><code>onOffsetsChanged()</code></a>.
+To react to touch events, simply implement <a href="../../../reference/android/service/wallpaper/WallpaperService.Engine.html#onTouchEvent%28android.view.MotionEvent%29"><code>onTouchEvent(MotionEvent)</code></a>.
+Finally, applications can send arbitrary commands to the live wallpaper.
+Currently, only the standard home application sends commands to the <a
+href="../../../reference/android/service/wallpaper/WallpaperService.Engine.html#onCommand%28java.lang.String,%20int,%20int,%20int,%20android.os.Bundle,%20boolean%29"><code>onCommand()</code></a>
+method of the live wallpaper:</p>
+
+<ul>
+<li><code>android.wallpaper.tap</code>: When the user taps an empty space
+on the workspace. This command is interpreted by the Nexus and Water live
+wallpapers to make the wallpaper react to user interaction. For instance,
+if you tap an empty space on the Water live wallpaper, new ripples appear
+under your finger.</li>
+<li><code>android.home.drop</code>: When the user drops an icon or a widget
+on the workspace. This command is also interpreted by the Nexus and Water
+live wallpapers.</li>
+</ul>
+
+<p>If you are developing a live wallpaper, remember that the feature is
+supported only on Android 2.1 (API level 7) and higher versions of the platform.
+To ensure that your application can only be installed on devices that support
+live wallpapers, remember to add the following to the application's manifest
+before publishing to Android Market:</p>
+
+<ul>
+<li><code>&lt;uses-sdk android:minSdkVersion="7" /&gt;</code>, which indicates
+to Android Market and the platform that your application requires Android 2.1 or
+higher. For more information, see the <a href="../../../guide/appendix/api-levels.html">API
+Levels</a> and the documentation for the
+<a href="../../../guide/topics/manifest/uses-sdk-element.html"><code>&lt;uses-sdk&gt;</code></a>
+element.</li>
+<li><code>&lt;uses-feature android:name="android.software.live_wallpaper" /&gt;</code>,
+which tells Android Market that your application includes a live wallpaper
+Android Market uses this feature as a filter, when presenting users lists of
+available applications. When you declaring this feature, Android Market
+displays your application only to users whose devices support live wallpapers,
+while hiding it from other devices on which it would not be able to run. For
+more information, see the documentation for the
+<a href="../../../guide/topics/manifest/uses-feature-element.html"><code>&lt;uses-feature&gt;</code></a>
+element.</li>
+</ul>
+
+<p>Many great live wallpapers are already available on Android Market and
+we can't wait to see more!</p>
diff --git a/docs/html/resources/resources_toc.cs b/docs/html/resources/resources_toc.cs
index e337e38..0972029 100644
--- a/docs/html/resources/resources_toc.cs
+++ b/docs/html/resources/resources_toc.cs
@@ -83,6 +83,9 @@
         <li><a href="<?cs var:toroot ?>resources/articles/live-folders.html">
                 <span class="en">Live Folders</span>
                 </a></li>
+        <li><a href="<?cs var:toroot ?>resources/articles/live-wallpapers.html">
+                <span class="en">Live Wallpapers</span>
+                </a> <span class="new">new!</span></li>
         <li><a href="<?cs var:toroot ?>resources/articles/on-screen-inputs.html">
                 <span class="en">Onscreen Input Methods</span>
                 </a></li>
@@ -178,28 +181,34 @@
               </a></li>
           <li><a href="<?cs var:toroot ?>resources/samples/BluetoothChat/index.html">
                 <span class="en">Bluetooth Chat</span>
-              </a> <span class="new">new!</span></li>
+              </a></li>
           <li><a href="<?cs var:toroot ?>resources/samples/BusinessCard/index.html">
                 <span class="en">Business Card</span>
-              </a> <span class="new">new!</span></li>
+              </a></li>
           <li><a href="<?cs var:toroot ?>resources/samples/ContactManager/index.html">
                 <span class="en">Contact Manager</span>
-              </a> <span class="new">new!</span></li>
+              </a></li>
           <li><a href="<?cs var:toroot ?>resources/samples/Home/index.html">
                 <span class="en">Home</span>
               </a></li>
           <li><a href="<?cs var:toroot ?>resources/samples/JetBoy/index.html">
                 <span class="en">JetBoy</span>
               </a></li>
+          <li><a href="<?cs var:toroot ?>resources/samples/CubeLiveWallpaper/index.html">
+                <span class="en">Live Wallpaper</span>
+                </a> <span class="new">new!</span></li>
           <li><a href="<?cs var:toroot ?>resources/samples/LunarLander/index.html">
                 <span class="en">Lunar Lander</span>
               </a></li>
           <li><a href="<?cs var:toroot ?>resources/samples/MultiResolution/index.html">
                 <span class="en">Multiple Resolutions</span>
-              </a> <span class="new">new!</span></li>
+              </a></li>
           <li><a href="<?cs var:toroot ?>resources/samples/NotePad/index.html">
                 <span class="en">Note Pad</span>
               </a></li>
+          <li><a href="<?cs var:toroot ?>resources/samples/SampleSyncAdapter/index.html">
+                <span class="en">Sample Sync Adapter</span>
+              </a> <span class="new">new!</span></li>
           <li><a href="<?cs var:toroot ?>resources/samples/SearchableDictionary/index.html">
                 <span class="en">Searchable Dictionary</span>
               </a></li>
@@ -211,10 +220,10 @@
               </a></li>
           <li><a href="<?cs var:toroot ?>resources/samples/Wiktionary/index.html">
                 <span class="en">Wiktionary</span>
-              </a> <span class="new">new!</span></li>
+              </a></li>
           <li><a href="<?cs var:toroot ?>resources/samples/WiktionarySimple/index.html">
                 <span class="en">Wiktionary (Simplified)</span>
-              </a> <span class="new">new!</span></li>
+              </a></li>
         </ul>
       </li>
     </ul>
diff --git a/docs/html/resources/samples/images/CubeLiveWallpaper1.png b/docs/html/resources/samples/images/CubeLiveWallpaper1.png
new file mode 100644
index 0000000..55bc1e9
--- /dev/null
+++ b/docs/html/resources/samples/images/CubeLiveWallpaper1.png
Binary files differ
diff --git a/docs/html/resources/samples/images/CubeLiveWallpaper3.png b/docs/html/resources/samples/images/CubeLiveWallpaper3.png
new file mode 100644
index 0000000..2747a88
--- /dev/null
+++ b/docs/html/resources/samples/images/CubeLiveWallpaper3.png
Binary files differ
diff --git a/docs/html/resources/samples/index.jd b/docs/html/resources/samples/index.jd
index 0beb781..5ebf41c 100644
--- a/docs/html/resources/samples/index.jd
+++ b/docs/html/resources/samples/index.jd
@@ -27,10 +27,10 @@
 platforms) and allow you to view the source files in your browser. </p>
 
 <div class="special">
-  <p>Some of the samples in this listing are not yet available in the
-  SDK. While we work to update the SDK, you can
-  <a href="{@docRoot}shareables/latest_samples.zip">download the latest samples</a> as a ZIP
-  archive.</p>
+  <p>Some of the samples in this listing may not yet be available in the
+  SDK. To ensure that you have the latest versions of the samples, you can
+  <a href="{@docRoot}shareables/latest_samples.zip">download the samples pack</a>
+  as a .zip archive.</p>
 </div>
 
 <dl>
@@ -55,11 +55,15 @@
 
  <dt><a href="Home/index.html">Home</a></dt>
   <dd>A home screen replacement application.</dd>
-  
+
  <dt><a href="JetBoy/index.html">JetBoy</a></dt>
   <dd>A game that demonstrates the SONiVOX JET interactive music technology,
   with {@link android.media.JetPlayer}.</dd>
-    
+
+ <dt><a href="CubeLiveWallpaper/index.html">Live Wallpaper</a></dt>
+  <dd>An application that demonstrates how to create a live wallpaper and 
+  bundle it in an application that users can install on their devices.</dd>
+
  <dt><a href="LunarLander/index.html">Lunar Lander</a></dt>
   <dd>A classic Lunar Lander game.</dd>
 
@@ -70,14 +74,21 @@
  <dt><a href="NotePad/index.html">Note Pad</a></dt>
   <dd>An application for saving notes. Similar (but not identical) to the 
     <a href="{@docRoot}resources/tutorials/notepad/index.html">Notepad tutorial</a>.</dd>
-  
+
+ <dt><a href="SampleSyncAdapter/index.html">SampleSyncAdapter</a></dt>
+  <dd>Demonstrates how an application can communicate with a
+cloud-based service and synchronize its data with data stored locally in a
+content provider. The sample uses two related parts of the Android framework
+&mdash; the account manager and the synchronization manager (through a sync
+adapter).</dd>
+
  <dt><a href="SearchableDictionary/index.html">Searchable Dictionary</a></dt>
   <dd>A sample application that demonstrates Android's search framework, 
   including how to provide search suggestions for Quick Search Box.</dd>
-  
+
  <dt><a href="Snake/index.html">Snake</a></dt>
   <dd>An implementation of the classic game "Snake."</dd>
-  
+
  <dt><a href="SoftKeyboard/index.html">Soft Keyboard</a></dt>
   <dd>An example of writing an input method for a software keyboard.</dd>
 
diff --git a/docs/html/shareables/latest_samples.zip b/docs/html/shareables/latest_samples.zip
index 42fad99..34102c5 100644
--- a/docs/html/shareables/latest_samples.zip
+++ b/docs/html/shareables/latest_samples.zip
Binary files differ
diff --git a/docs/html/sitemap.txt b/docs/html/sitemap.txt
index f82b2fe..5039dfc 100644
--- a/docs/html/sitemap.txt
+++ b/docs/html/sitemap.txt
@@ -2864,11 +2864,6 @@
 http://developer.android.com/reference/org/apache/http/cookie/params/package-descr.html
 http://developer.android.com/reference/java/util/concurrent/locks/package-descr.html
 http://developer.android.com/reference/org/apache/http/conn/routing/package-descr.html
-http://developer.android.com/guide/samples/index.html
-http://developer.android.com/guide/tutorials/notepad/notepad-ex1.html
-http://developer.android.com/guide/tutorials/notepad/notepad-ex2.html
-http://developer.android.com/guide/tutorials/notepad/notepad-ex3.html
-http://developer.android.com/guide/tutorials/notepad/notepad-extra-credit.html
 http://developer.android.com/guide/appendix/faq/commontasks.html
 http://developer.android.com/reference/javax/security/cert/package-descr.html
 http://developer.android.com/reference/org/xml/sax/ext/package-descr.html
@@ -3029,7 +3024,6 @@
 http://developer.android.com/sdk/api_diff/6/changes/android.view.WindowManager.LayoutParams.html
 http://developer.android.com/reference/android/net/package-descr.html
 http://developer.android.com/reference/org/apache/http/client/package-descr.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html
 http://developer.android.com/sdk/download.html?v=archives/android-sdk-windows-1.6_r1.zip
 http://developer.android.com/sdk/download.html?v=archives/android-sdk-mac_x86-1.6_r1.zip
 http://developer.android.com/sdk/download.html?v=archives/android-sdk-linux_x86-1.6_r1.tgz
@@ -3299,7 +3293,6 @@
 http://developer.android.com/resources/samples/BluetoothChat/res/layout/message.html
 http://developer.android.com/resources/samples/NotePad/res/drawable-ldpi-v6/app_notes.html
 http://developer.android.com/resources/samples/NotePad/res/drawable-ldpi-v6/live_folder_notes.html
-http://developer.android.com/guide/tutorials/views/index.html
 http://developer.android.com/sdk/api_diff/4/changes/pkg_android.html
 http://developer.android.com/sdk/api_diff/4/changes/pkg_android.app.html
 http://developer.android.com/sdk/api_diff/4/changes/pkg_android.content.res.html
@@ -3523,21 +3516,6 @@
 http://developer.android.com/resources/samples/ApiDemos/tests/src/com/example/android/apis/index.html
 http://developer.android.com/reference/org/apache/http/conn/ssl/package-descr.html
 http://developer.android.com/resources/samples/ContactManager/res/drawable-hdpi/icon.html
-http://developer.android.com/guide/tutorials/views/hello-linearlayout.html
-http://developer.android.com/guide/tutorials/views/hello-relativelayout.html
-http://developer.android.com/guide/tutorials/views/hello-tablelayout.html
-http://developer.android.com/guide/tutorials/views/hello-datepicker.html
-http://developer.android.com/guide/tutorials/views/hello-timepicker.html
-http://developer.android.com/guide/tutorials/views/hello-formstuff.html
-http://developer.android.com/guide/tutorials/views/hello-spinner.html
-http://developer.android.com/guide/tutorials/views/hello-autocomplete.html
-http://developer.android.com/guide/tutorials/views/hello-listview.html
-http://developer.android.com/guide/tutorials/views/hello-gridview.html
-http://developer.android.com/guide/tutorials/views/hello-gallery.html
-http://developer.android.com/guide/tutorials/views/hello-tabwidget.html
-http://developer.android.com/guide/tutorials/views/hello-mapview.html
-http://developer.android.com/guide/tutorials/views/hello-webview.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/index.html
 http://developer.android.com/sdk/api_diff/5/changes/packages_index_all.html
 http://developer.android.com/sdk/api_diff/5/changes/classes_index_all.html
 http://developer.android.com/sdk/api_diff/5/changes/constructors_index_all.html
@@ -3858,112 +3836,6 @@
 http://developer.android.com/reference/org/w3c/dom/package-descr.html
 http://developer.android.com/reference/org/apache/http/package-descr.html
 http://developer.android.com/resources/samples/MultiResolution/src/com/example/index.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/RelativeLayout1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/RelativeLayout2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout3.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout4.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout5.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout6.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout7.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout8.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout9.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ScrollView1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ScrollView2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/TableLayout1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/TableLayout2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/TableLayout3.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/TableLayout4.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/TableLayout5.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/TableLayout6.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/TableLayout7.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/TableLayout8.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/TableLayout9.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/TableLayout10.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/TableLayout11.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/TableLayout12.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Baseline1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Baseline2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Baseline3.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Baseline4.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Baseline6.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Baseline7.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/BaselineNested1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/BaselineNested2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/BaselineNested3.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/RadioGroup1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ScrollBar1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ScrollBar2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Visibility1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List3.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List4.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List5.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List6.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List7.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List8.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/CustomView1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ImageButton1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/DateWidgets1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/DateWidgets2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Gallery1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Gallery2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Spinner1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Grid1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Grid2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ImageSwitcher1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/TextSwitcher1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Animation1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Animation2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Controls1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Controls2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete3.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete4.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete5.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ProgressBar1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ProgressBar2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ProgressBar3.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ProgressBar4.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Focus1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Focus2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Focus3.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Animation3.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete6.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Buttons1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ChronometerDemo.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ExpandableList1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ExpandableList2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ExpandableList3.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ImageView1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/InternalSelectionFocus.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/InternalSelectionScroll.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/InternalSelectionView.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LabelView.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation3.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation4.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation5.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation6.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation7.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout10.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List10.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List11.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List12.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List13.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List14.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List9.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/RatingBar1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ScrollBar3.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/SeekBar1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Tabs1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Tabs2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Tabs3.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/WebView1.html
 http://developer.android.com/resources/samples/Home/res/drawable/all_applications.html
 http://developer.android.com/resources/samples/Home/res/drawable/all_applications_background.html
 http://developer.android.com/resources/samples/Home/res/drawable/all_applications_button_background.html
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index b6ac14a..e5cf38e 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -39,15 +39,17 @@
         mType = t;
     }
 
+    public Type getType() {
+        return mType;
+    }
+
     public void uploadToTexture(int baseMipLevel) {
         mRS.validate();
-        mRS.validateSurface();
         mRS.nAllocationUploadToTexture(mID, baseMipLevel);
     }
 
     public void uploadToBufferObject() {
         mRS.validate();
-        mRS.validateSurface();
         mRS.nAllocationUploadToBufferObject(mID);
     }
 
@@ -171,9 +173,10 @@
     public Adapter1D createAdapter1D() {
         mRS.validate();
         int id = mRS.nAdapter1DCreate();
-        if (id != 0) {
-            mRS.nAdapter1DBindAllocation(id, mID);
+        if(id == 0) {
+            throw new IllegalStateException("allocation failed.");
         }
+        mRS.nAdapter1DBindAllocation(id, mID);
         return new Adapter1D(id, mRS);
     }
 
@@ -213,9 +216,10 @@
     public Adapter2D createAdapter2D() {
         mRS.validate();
         int id = mRS.nAdapter2DCreate();
-        if (id != 0) {
-            mRS.nAdapter2DBindAllocation(id, mID);
+        if(id == 0) {
+            throw new IllegalStateException("allocation failed.");
         }
+        mRS.nAdapter2DBindAllocation(id, mID);
         return new Adapter2D(id, mRS);
     }
 
@@ -258,14 +262,20 @@
 
         rs.validate();
         int id = rs.nAllocationCreateFromBitmap(dstFmt.mID, genMips, b);
+        if(id == 0) {
+            throw new IllegalStateException("Load failed.");
+        }
         return new Allocation(id, rs, null);
     }
 
-    static public Allocation createFromBitmapBoxed(RenderScript rs, Bitmap b, Element dstFmt, boolean genMips)
+    static Allocation createFromBitmapBoxed(RenderScript rs, Bitmap b, Element dstFmt, boolean genMips)
         throws IllegalArgumentException {
 
         rs.validate();
         int id = rs.nAllocationCreateFromBitmapBoxed(dstFmt.mID, genMips, b);
+        if(id == 0) {
+            throw new IllegalStateException("Load failed.");
+        }
         return new Allocation(id, rs, null);
     }
 
@@ -282,6 +292,9 @@
             int allocationId = rs.nAllocationCreateFromAssetStream(dstFmt.mID, genMips,
                     asset);
 
+            if(allocationId == 0) {
+                throw new IllegalStateException("Load failed.");
+            }
             return new Allocation(allocationId, rs, null);
         } catch (Exception e) {
             // Ignore
diff --git a/graphics/java/android/renderscript/BaseObj.java b/graphics/java/android/renderscript/BaseObj.java
index e802ec5..002fc78 100644
--- a/graphics/java/android/renderscript/BaseObj.java
+++ b/graphics/java/android/renderscript/BaseObj.java
@@ -25,6 +25,7 @@
 class BaseObj {
 
     BaseObj(RenderScript rs) {
+        rs.validate();
         mRS = rs;
         mID = 0;
         mDestroyed = false;
diff --git a/graphics/java/android/renderscript/Element.java b/graphics/java/android/renderscript/Element.java
index ee9b098..10ef05a 100644
--- a/graphics/java/android/renderscript/Element.java
+++ b/graphics/java/android/renderscript/Element.java
@@ -24,248 +24,66 @@
  **/
 public class Element extends BaseObj {
     int mSize;
-    Entry[] mEntries;
+    Element[] mElements;
+    String[] mElementNames;
 
-    int getSizeBytes() {
-        return mSize;
-    }
-    int getComponentCount() {
-        return mEntries.length;
-    }
-    Element.DataType getComponentDataType(int num) {
-        return mEntries[num].mType;
-    }
-    Element.DataKind getComponentDataKind(int num) {
-        return mEntries[num].mKind;
-    }
-    boolean getComponentIsNormalized(int num) {
-        return mEntries[num].mIsNormalized;
-    }
-    int getComponentBits(int num) {
-        return mEntries[num].mBits;
-    }
-    String getComponentName(int num) {
-        return mEntries[num].mName;
-    }
+    DataType mType;
+    DataKind mKind;
+    boolean mNormalized;
+    int mVectorSize;
 
-    static class Entry {
-        //Element mElement;
-        Element.DataType mType;
-        Element.DataKind mKind;
-        boolean mIsNormalized;
-        int mBits;
-        String mName;
-
-        //Entry(Element e, int bits) {
-            //mElement = e;
-            //int mBits = bits;
-        //}
-
-        Entry(DataType dt, DataKind dk, boolean isNorm, int bits, String name) {
-            mType = dt;
-            mKind = dk;
-            mIsNormalized = isNorm;
-            mBits = bits;
-            mName = name;
-        }
-    }
-
-    public static Element USER_U8(RenderScript rs) {
-        if(rs.mElement_USER_U8 == null) {
-            rs.mElement_USER_U8 = new Element(rs, 1);
-            rs.mElement_USER_U8.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.USER, false, 8, null);
-            rs.mElement_USER_U8.init();
-        }
-        return rs.mElement_USER_U8;
-    }
-
-    public static Element USER_I8(RenderScript rs) {
-        if(rs.mElement_USER_I8 == null) {
-            rs.mElement_USER_I8 = new Element(rs, 1);
-            rs.mElement_USER_I8.mEntries[0] = new Entry(DataType.SIGNED, DataKind.USER, false, 8, null);
-            rs.mElement_USER_I8.init();
-        }
-        return rs.mElement_USER_I8;
-    }
-
-    public static Element USER_U16(RenderScript rs) {
-        if(rs.mElement_USER_U16 == null) {
-            rs.mElement_USER_U16 = new Element(rs, 1);
-            rs.mElement_USER_U16.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.USER, false, 16, null);
-            rs.mElement_USER_U16.init();
-        }
-        return rs.mElement_USER_U16;
-    }
-
-    public static Element USER_I16(RenderScript rs) {
-        if(rs.mElement_USER_I16 == null) {
-            rs.mElement_USER_I16 = new Element(rs, 1);
-            rs.mElement_USER_I16.mEntries[0] = new Entry(DataType.SIGNED, DataKind.USER, false, 16, null);
-            rs.mElement_USER_I16.init();
-        }
-        return rs.mElement_USER_I16;
-    }
-
-    public static Element USER_U32(RenderScript rs) {
-        if(rs.mElement_USER_U32 == null) {
-            rs.mElement_USER_U32 = new Element(rs, 1);
-            rs.mElement_USER_U32.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.USER, false, 32, null);
-            rs.mElement_USER_U32.init();
-        }
-        return rs.mElement_USER_U32;
-    }
-
-    public static Element USER_I32(RenderScript rs) {
-        if(rs.mElement_USER_I32 == null) {
-            rs.mElement_USER_I32 = new Element(rs, 1);
-            rs.mElement_USER_I32.mEntries[0] = new Entry(DataType.SIGNED, DataKind.USER, false, 32, null);
-            rs.mElement_USER_I32.init();
-        }
-        return rs.mElement_USER_I32;
-    }
-
-    public static Element USER_F32(RenderScript rs) {
-        if(rs.mElement_USER_FLOAT == null) {
-            rs.mElement_USER_FLOAT = new Element(rs, 1);
-            rs.mElement_USER_FLOAT.mEntries[0] = new Entry(DataType.FLOAT, DataKind.USER, false, 32, null);
-            rs.mElement_USER_FLOAT.init();
-        }
-        return rs.mElement_USER_FLOAT;
-    }
-
-    public static Element A_8(RenderScript rs) {
-        if(rs.mElement_A_8 == null) {
-            rs.mElement_A_8 = new Element(rs, 1);
-            rs.mElement_A_8.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.ALPHA, true, 8, "a");
-            rs.mElement_A_8.init();
-        }
-        return rs.mElement_A_8;
-    }
-
-    public static Element RGB_565(RenderScript rs) {
-        if(rs.mElement_RGB_565 == null) {
-            rs.mElement_RGB_565 = new Element(rs, 3);
-            rs.mElement_RGB_565.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.RED, true, 5, "r");
-            rs.mElement_RGB_565.mEntries[1] = new Entry(DataType.UNSIGNED, DataKind.GREEN, true, 6, "g");
-            rs.mElement_RGB_565.mEntries[2] = new Entry(DataType.UNSIGNED, DataKind.BLUE, true, 5, "b");
-            rs.mElement_RGB_565.init();
-        }
-        return rs.mElement_RGB_565;
-    }
-
-    public static Element RGB_888(RenderScript rs) {
-        if(rs.mElement_RGB_888 == null) {
-            rs.mElement_RGB_888 = new Element(rs, 3);
-            rs.mElement_RGB_888.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.RED, true, 8, "r");
-            rs.mElement_RGB_888.mEntries[1] = new Entry(DataType.UNSIGNED, DataKind.GREEN, true, 8, "g");
-            rs.mElement_RGB_888.mEntries[2] = new Entry(DataType.UNSIGNED, DataKind.BLUE, true, 8, "b");
-            rs.mElement_RGB_888.init();
-        }
-        return rs.mElement_RGB_888;
-    }
-
-    public static Element RGBA_5551(RenderScript rs) {
-        if(rs.mElement_RGBA_5551 == null) {
-            rs.mElement_RGBA_5551 = new Element(rs, 4);
-            rs.mElement_RGBA_5551.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.RED, true, 5, "r");
-            rs.mElement_RGBA_5551.mEntries[1] = new Entry(DataType.UNSIGNED, DataKind.GREEN, true, 5, "g");
-            rs.mElement_RGBA_5551.mEntries[2] = new Entry(DataType.UNSIGNED, DataKind.BLUE, true, 5, "b");
-            rs.mElement_RGBA_5551.mEntries[3] = new Entry(DataType.UNSIGNED, DataKind.ALPHA, true, 1, "a");
-            rs.mElement_RGBA_5551.init();
-        }
-        return rs.mElement_RGBA_5551;
-    }
-
-    public static Element RGBA_4444(RenderScript rs) {
-        if(rs.mElement_RGBA_4444 == null) {
-            rs.mElement_RGBA_4444 = new Element(rs, 4);
-            rs.mElement_RGBA_4444.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.RED, true, 4, "r");
-            rs.mElement_RGBA_4444.mEntries[1] = new Entry(DataType.UNSIGNED, DataKind.GREEN, true, 4, "g");
-            rs.mElement_RGBA_4444.mEntries[2] = new Entry(DataType.UNSIGNED, DataKind.BLUE, true, 4, "b");
-            rs.mElement_RGBA_4444.mEntries[3] = new Entry(DataType.UNSIGNED, DataKind.ALPHA, true, 4, "a");
-            rs.mElement_RGBA_4444.init();
-        }
-        return rs.mElement_RGBA_4444;
-    }
-
-    public static Element RGBA_8888(RenderScript rs) {
-        if(rs.mElement_RGBA_8888 == null) {
-            rs.mElement_RGBA_8888 = new Element(rs, 4);
-            rs.mElement_RGBA_8888.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.RED, true, 8, "r");
-            rs.mElement_RGBA_8888.mEntries[1] = new Entry(DataType.UNSIGNED, DataKind.GREEN, true, 8, "g");
-            rs.mElement_RGBA_8888.mEntries[2] = new Entry(DataType.UNSIGNED, DataKind.BLUE, true, 8, "b");
-            rs.mElement_RGBA_8888.mEntries[3] = new Entry(DataType.UNSIGNED, DataKind.ALPHA, true, 8, "a");
-            rs.mElement_RGBA_8888.init();
-        }
-        return rs.mElement_RGBA_8888;
-    }
-
-    public static Element INDEX_16(RenderScript rs) {
-        if(rs.mElement_INDEX_16 == null) {
-            rs.mElement_INDEX_16 = new Element(rs, 1);
-            rs.mElement_INDEX_16.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.INDEX, false, 16, "index");
-            rs.mElement_INDEX_16.init();
-        }
-        return rs.mElement_INDEX_16;
-    }
-
-    public static Element XY_F32(RenderScript rs) {
-        if(rs.mElement_XY_F32 == null) {
-            rs.mElement_XY_F32 = new Element(rs, 2);
-            rs.mElement_XY_F32.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.X, false, 32, "x");
-            rs.mElement_XY_F32.mEntries[1] = new Entry(DataType.UNSIGNED, DataKind.Y, false, 32, "y");
-            rs.mElement_XY_F32.init();
-        }
-        return rs.mElement_XY_F32;
-    }
-
-    public static Element XYZ_F32(RenderScript rs) {
-        if(rs.mElement_XYZ_F32 == null) {
-            rs.mElement_XYZ_F32 = new Element(rs, 3);
-            rs.mElement_XYZ_F32.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.X, false, 32, "x");
-            rs.mElement_XYZ_F32.mEntries[1] = new Entry(DataType.UNSIGNED, DataKind.Y, false, 32, "y");
-            rs.mElement_XYZ_F32.mEntries[2] = new Entry(DataType.UNSIGNED, DataKind.Z, false, 32, "z");
-            rs.mElement_XYZ_F32.init();
-        }
-        return rs.mElement_XYZ_F32;
-    }
-
-    static void initPredefined(RenderScript rs) {
-        rs.nInitElements(A_8(rs).mID, RGBA_4444(rs).mID, RGBA_8888(rs).mID, RGB_565(rs).mID);
-    }
+    int getSizeBytes() {return mSize;}
 
     public enum DataType {
-        FLOAT (0),
-        UNSIGNED (1),
-        SIGNED (2);
+        //FLOAT_16 (1, 2),
+        FLOAT_32 (2, 4),
+        //FLOAT_64 (3, 8),
+        SIGNED_8 (4, 1),
+        SIGNED_16 (5, 2),
+        SIGNED_32 (6, 4),
+        //SIGNED_64 (7, 8),
+        UNSIGNED_8 (8, 1),
+        UNSIGNED_16 (9, 2),
+        UNSIGNED_32 (10, 4),
+        //UNSIGNED_64 (11, 8),
+
+        UNSIGNED_5_6_5 (12, 2),
+        UNSIGNED_5_5_5_1 (13, 2),
+        UNSIGNED_4_4_4_4 (14, 2),
+
+        RS_ELEMENT (15, 4),
+        RS_TYPE (16, 4),
+        RS_ALLOCATION (17, 4),
+        RS_SAMPLER (18, 4),
+        RS_SCRIPT (19, 4),
+        RS_MESH (20, 4),
+        RS_PROGRAM_FRAGMENT (21, 4),
+        RS_PROGRAM_VERTEX (22, 4),
+        RS_PROGRAM_RASTER (23, 4),
+        RS_PROGRAM_STORE (24, 4);
 
         int mID;
-        DataType(int id) {
+        int mSize;
+        DataType(int id, int size) {
             mID = id;
+            mSize = size;
         }
     }
 
     public enum DataKind {
         USER (0),
-        RED (1),
-        GREEN (2),
-        BLUE (3),
-        ALPHA (4),
-        LUMINANCE (5),
-        INTENSITY (6),
-        X (7),
-        Y (8),
-        Z (9),
-        W (10),
-        S (11),
-        T (12),
-        Q (13),
-        R (14),
-        NX (15),
-        NY (16),
-        NZ (17),
-        INDEX (18),
-        POINT_SIZE(19);
+        COLOR (1),
+        POSITION (2),
+        TEXTURE (3),
+        NORMAL (4),
+        INDEX (5),
+        POINT_SIZE(6),
+
+        PIXEL_L (7),
+        PIXEL_A (8),
+        PIXEL_LA (9),
+        PIXEL_RGB (10),
+        PIXEL_RGBA (11);
 
         int mID;
         DataKind(int id) {
@@ -273,10 +91,153 @@
         }
     }
 
-    Element(RenderScript rs, int count) {
+    public static Element USER_U8(RenderScript rs) {
+        if(rs.mElement_USER_U8 == null) {
+            rs.mElement_USER_U8 = createUser(rs, DataType.UNSIGNED_8);
+        }
+        return rs.mElement_USER_U8;
+    }
+
+    public static Element USER_I8(RenderScript rs) {
+        if(rs.mElement_USER_I8 == null) {
+            rs.mElement_USER_I8 = createUser(rs, DataType.SIGNED_8);
+        }
+        return rs.mElement_USER_I8;
+    }
+
+    public static Element USER_U32(RenderScript rs) {
+        if(rs.mElement_USER_U32 == null) {
+            rs.mElement_USER_U32 = createUser(rs, DataType.UNSIGNED_32);
+        }
+        return rs.mElement_USER_U32;
+    }
+
+    public static Element USER_I32(RenderScript rs) {
+        if(rs.mElement_USER_I32 == null) {
+            rs.mElement_USER_I32 = createUser(rs, DataType.SIGNED_32);
+        }
+        return rs.mElement_USER_I32;
+    }
+
+    public static Element USER_F32(RenderScript rs) {
+        if(rs.mElement_USER_F32 == null) {
+            rs.mElement_USER_F32 = createUser(rs, DataType.FLOAT_32);
+        }
+        return rs.mElement_USER_F32;
+    }
+
+    public static Element A_8(RenderScript rs) {
+        if(rs.mElement_A_8 == null) {
+            rs.mElement_A_8 = createPixel(rs, DataType.UNSIGNED_8, DataKind.PIXEL_A);
+        }
+        return rs.mElement_A_8;
+    }
+
+    public static Element RGB_565(RenderScript rs) {
+        if(rs.mElement_RGB_565 == null) {
+            rs.mElement_RGB_565 = createPixel(rs, DataType.UNSIGNED_5_6_5, DataKind.PIXEL_RGB);
+        }
+        return rs.mElement_RGB_565;
+    }
+
+    public static Element RGB_888(RenderScript rs) {
+        if(rs.mElement_RGB_888 == null) {
+            rs.mElement_RGB_888 = createPixel(rs, DataType.UNSIGNED_8, DataKind.PIXEL_RGB);
+        }
+        return rs.mElement_RGB_888;
+    }
+
+    public static Element RGBA_5551(RenderScript rs) {
+        if(rs.mElement_RGBA_5551 == null) {
+            rs.mElement_RGBA_5551 = createPixel(rs, DataType.UNSIGNED_5_5_5_1, DataKind.PIXEL_RGBA);
+        }
+        return rs.mElement_RGBA_5551;
+    }
+
+    public static Element RGBA_4444(RenderScript rs) {
+        if(rs.mElement_RGBA_4444 == null) {
+            rs.mElement_RGBA_4444 = createPixel(rs, DataType.UNSIGNED_4_4_4_4, DataKind.PIXEL_RGBA);
+        }
+        return rs.mElement_RGBA_4444;
+    }
+
+    public static Element RGBA_8888(RenderScript rs) {
+        if(rs.mElement_RGBA_8888 == null) {
+            rs.mElement_RGBA_8888 = createPixel(rs, DataType.UNSIGNED_8, DataKind.PIXEL_RGBA);
+        }
+        return rs.mElement_RGBA_8888;
+    }
+
+    public static Element INDEX_16(RenderScript rs) {
+        if(rs.mElement_INDEX_16 == null) {
+            rs.mElement_INDEX_16 = createIndex(rs);
+        }
+        return rs.mElement_INDEX_16;
+    }
+
+    public static Element ATTRIB_POSITION_2(RenderScript rs) {
+        if(rs.mElement_POSITION_2 == null) {
+            rs.mElement_POSITION_2 = createAttrib(rs, DataType.FLOAT_32, DataKind.POSITION, 2);
+        }
+        return rs.mElement_POSITION_2;
+    }
+
+    public static Element ATTRIB_POSITION_3(RenderScript rs) {
+        if(rs.mElement_POSITION_3 == null) {
+            rs.mElement_POSITION_3 = createAttrib(rs, DataType.FLOAT_32, DataKind.POSITION, 3);
+        }
+        return rs.mElement_POSITION_3;
+    }
+
+    public static Element ATTRIB_TEXTURE_2(RenderScript rs) {
+        if(rs.mElement_TEXTURE_2 == null) {
+            rs.mElement_TEXTURE_2 = createAttrib(rs, DataType.FLOAT_32, DataKind.TEXTURE, 2);
+        }
+        return rs.mElement_TEXTURE_2;
+    }
+
+    public static Element ATTRIB_NORMAL_3(RenderScript rs) {
+        if(rs.mElement_NORMAL_3 == null) {
+            rs.mElement_NORMAL_3 = createAttrib(rs, DataType.FLOAT_32, DataKind.NORMAL, 3);
+        }
+        return rs.mElement_NORMAL_3;
+    }
+
+    public static Element ATTRIB_COLOR_U8_4(RenderScript rs) {
+        if(rs.mElement_COLOR_U8_4 == null) {
+            rs.mElement_COLOR_U8_4 = createAttrib(rs, DataType.UNSIGNED_8, DataKind.COLOR, 4);
+        }
+        return rs.mElement_COLOR_U8_4;
+    }
+
+    public static Element ATTRIB_COLOR_F32_4(RenderScript rs) {
+        if(rs.mElement_COLOR_F32_4 == null) {
+            rs.mElement_COLOR_F32_4 = createAttrib(rs, DataType.FLOAT_32, DataKind.COLOR, 4);
+        }
+        return rs.mElement_COLOR_F32_4;
+    }
+
+    Element(RenderScript rs, Element[] e, String[] n) {
         super(rs);
         mSize = 0;
-        mEntries = new Entry[count];
+        mElements = e;
+        mElementNames = n;
+        int[] ids = new int[mElements.length];
+        for (int ct = 0; ct < mElements.length; ct++ ) {
+            mSize += mElements[ct].mSize;
+            ids[ct] = mElements[ct].mID;
+        }
+        mID = rs.nElementCreate2(ids, mElementNames);
+    }
+
+    Element(RenderScript rs, DataType dt, DataKind dk, boolean norm, int size) {
+        super(rs);
+        mSize = dt.mSize * size;
+        mType = dt;
+        mKind = dk;
+        mNormalized = norm;
+        mVectorSize = size;
+        mID = rs.nElementCreate(dt.mID, dk.mID, norm, size);
     }
 
     public void destroy() throws IllegalStateException {
@@ -291,13 +252,13 @@
         for(Field f: fields) {
             Class fc = f.getType();
             if(fc == int.class) {
-                b.add(Element.DataType.SIGNED, Element.DataKind.USER, false, 32, f.getName());
+                b.add(createUser(rs, DataType.SIGNED_32), f.getName());
             } else if(fc == short.class) {
-                b.add(Element.DataType.SIGNED, Element.DataKind.USER, false, 16, f.getName());
+                b.add(createUser(rs, DataType.SIGNED_16), f.getName());
             } else if(fc == byte.class) {
-                b.add(Element.DataType.SIGNED, Element.DataKind.USER, false, 8, f.getName());
+                b.add(createUser(rs, DataType.SIGNED_8), f.getName());
             } else if(fc == float.class) {
-                b.add(Element.DataType.FLOAT, Element.DataKind.USER, false, 32, f.getName());
+                b.add(createUser(rs, DataType.FLOAT_32), f.getName());
             } else {
                 throw new IllegalArgumentException("Unkown field type");
             }
@@ -305,193 +266,157 @@
         return b.create();
     }
 
-    static synchronized void internalCreate(RenderScript rs, Element e) {
-        rs.nElementBegin();
-        int bits = 0;
-        for (int ct=0; ct < e.mEntries.length; ct++) {
-            Entry en = e.mEntries[ct];
-            //if(en.mElement !=  null) {
-                //rs.nElementAdd(en.mElement.mID);
-            //} else
-            {
-                rs.nElementAdd(en.mKind.mID, en.mType.mID, en.mIsNormalized, en.mBits, en.mName);
-                bits += en.mBits;
-            }
+
+    /////////////////////////////////////////
+    public static Element createUser(RenderScript rs, DataType dt) {
+        return new Element(rs, dt, DataKind.USER, false, 1);
+    }
+
+    public static Element createVector(RenderScript rs, DataType dt, int size) {
+        if (size < 2 || size > 4) {
+            throw new IllegalArgumentException("Bad size");
         }
-        e.mID = rs.nElementCreate();
-        e.mSize = (bits + 7) >> 3;
+        return new Element(rs, dt, DataKind.USER, false, size);
     }
 
-    void init() {
-        mRS.validate();
-        internalCreate(mRS, this);
+    public static Element createIndex(RenderScript rs) {
+        return new Element(rs, DataType.UNSIGNED_16, DataKind.INDEX, false, 1);
     }
 
+    public static Element createAttrib(RenderScript rs, DataType dt, DataKind dk, int size) {
+        if (!(dt == DataType.FLOAT_32 ||
+              dt == DataType.UNSIGNED_8 ||
+              dt == DataType.UNSIGNED_16 ||
+              dt == DataType.UNSIGNED_32 ||
+              dt == DataType.SIGNED_8 ||
+              dt == DataType.SIGNED_16 ||
+              dt == DataType.SIGNED_32)) {
+            throw new IllegalArgumentException("Unsupported DataType");
+        }
+
+        if (!(dk == DataKind.COLOR ||
+              dk == DataKind.POSITION ||
+              dk == DataKind.TEXTURE ||
+              dk == DataKind.NORMAL ||
+              dk == DataKind.POINT_SIZE ||
+              dk == DataKind.USER)) {
+            throw new IllegalArgumentException("Unsupported DataKind");
+        }
+
+        if (dk == DataKind.COLOR &&
+            ((dt != DataType.FLOAT_32 && dt != DataType.UNSIGNED_8) ||
+             size < 3 || size > 4)) {
+            throw new IllegalArgumentException("Bad combo");
+        }
+        if (dk == DataKind.POSITION && (size < 1 || size > 4)) {
+            throw new IllegalArgumentException("Bad combo");
+        }
+        if (dk == DataKind.TEXTURE &&
+            (dt != DataType.FLOAT_32 || size < 1 || size > 4)) {
+            throw new IllegalArgumentException("Bad combo");
+        }
+        if (dk == DataKind.NORMAL &&
+            (dt != DataType.FLOAT_32 || size != 3)) {
+            throw new IllegalArgumentException("Bad combo");
+        }
+        if (dk == DataKind.POINT_SIZE &&
+            (dt != DataType.FLOAT_32 || size != 1)) {
+            throw new IllegalArgumentException("Bad combo");
+        }
+
+        boolean norm = false;
+        if (dk == DataKind.COLOR && dt == DataType.UNSIGNED_8) {
+            norm = true;
+        }
+
+        return new Element(rs, dt, dk, norm, size);
+    }
+
+    public static Element createPixel(RenderScript rs, DataType dt, DataKind dk) {
+        if (!(dk == DataKind.PIXEL_L ||
+              dk == DataKind.PIXEL_A ||
+              dk == DataKind.PIXEL_LA ||
+              dk == DataKind.PIXEL_RGB ||
+              dk == DataKind.PIXEL_RGBA)) {
+            throw new IllegalArgumentException("Unsupported DataKind");
+        }
+        if (!(dt == DataType.UNSIGNED_8 ||
+              dt == DataType.UNSIGNED_5_6_5 ||
+              dt == DataType.UNSIGNED_4_4_4_4 ||
+              dt == DataType.UNSIGNED_5_5_5_1)) {
+            throw new IllegalArgumentException("Unsupported DataType");
+        }
+        if (dt == DataType.UNSIGNED_5_6_5 && dk != DataKind.PIXEL_RGB) {
+            throw new IllegalArgumentException("Bad kind and type combo");
+        }
+        if (dt == DataType.UNSIGNED_5_5_5_1 && dk != DataKind.PIXEL_RGBA) {
+            throw new IllegalArgumentException("Bad kind and type combo");
+        }
+        if (dt == DataType.UNSIGNED_4_4_4_4 && dk != DataKind.PIXEL_RGBA) {
+            throw new IllegalArgumentException("Bad kind and type combo");
+        }
+
+        int size = 1;
+        if (dk == DataKind.PIXEL_LA) {
+            size = 2;
+        }
+        if (dk == DataKind.PIXEL_RGB) {
+            size = 3;
+        }
+        if (dk == DataKind.PIXEL_RGBA) {
+            size = 4;
+        }
+
+        return new Element(rs, dt, dk, true, size);
+    }
 
     public static class Builder {
         RenderScript mRS;
-        Entry[] mEntries;
-        int mEntryCount;
+        Element[] mElements;
+        String[] mElementNames;
+        int mCount;
 
         public Builder(RenderScript rs) {
             mRS = rs;
-            mEntryCount = 0;
-            mEntries = new Entry[8];
+            mCount = 0;
+            mElements = new Element[8];
+            mElementNames = new String[8];
         }
 
-        void addEntry(Entry e) {
-            if(mEntries.length >= mEntryCount) {
-                Entry[] en = new Entry[mEntryCount + 8];
-                System.arraycopy(mEntries, 0, en, 0, mEntries.length);
-                mEntries = en;
+        public void add(Element element, String name) {
+            if(mCount == mElements.length) {
+                Element[] e = new Element[mCount + 8];
+                String[] s = new String[mCount + 8];
+                System.arraycopy(mElements, 0, e, 0, mCount);
+                System.arraycopy(mElementNames, 0, s, 0, mCount);
+                mElements = e;
+                mElementNames = s;
             }
-            mEntries[mEntryCount] = e;
-            mEntryCount++;
-        }
-
-        //public Builder add(Element e) throws IllegalArgumentException {
-            //Entry en = new Entry(e, e.mSize * 8);
-            //addEntry(en);
-            //return this;
-        //}
-
-        public Builder add(Element.DataType dt, Element.DataKind dk, boolean isNormalized, int bits, String name) {
-            Entry en = new Entry(dt, dk, isNormalized, bits, name);
-            addEntry(en);
-            return this;
-        }
-
-        public Builder add(Element.DataType dt, Element.DataKind dk, boolean isNormalized, int bits) {
-            add(dt, dk, isNormalized, bits, null);
-            return this;
-        }
-
-        public Builder addFloat(Element.DataKind dk) {
-            add(DataType.FLOAT, dk, false, 32, null);
-            return this;
-        }
-
-        public Builder addFloat(Element.DataKind dk, String name) {
-            add(DataType.FLOAT, dk, false, 32, name);
-            return this;
-        }
-
-        public Builder addFloatXY() {
-            add(DataType.FLOAT, DataKind.X, false, 32, null);
-            add(DataType.FLOAT, DataKind.Y, false, 32, null);
-            return this;
-        }
-
-        public Builder addFloatXY(String prefix) {
-            add(DataType.FLOAT, DataKind.X, false, 32, prefix + "x");
-            add(DataType.FLOAT, DataKind.Y, false, 32, prefix + "y");
-            return this;
-        }
-
-        public Builder addFloatXYZ() {
-            add(DataType.FLOAT, DataKind.X, false, 32, null);
-            add(DataType.FLOAT, DataKind.Y, false, 32, null);
-            add(DataType.FLOAT, DataKind.Z, false, 32, null);
-            return this;
-        }
-
-        public Builder addFloatXYZ(String prefix) {
-            add(DataType.FLOAT, DataKind.X, false, 32, prefix + "x");
-            add(DataType.FLOAT, DataKind.Y, false, 32, prefix + "y");
-            add(DataType.FLOAT, DataKind.Z, false, 32, prefix + "z");
-            return this;
-        }
-
-        public Builder addFloatST() {
-            add(DataType.FLOAT, DataKind.S, false, 32, null);
-            add(DataType.FLOAT, DataKind.T, false, 32, null);
-            return this;
-        }
-
-        public Builder addFloatST(String prefix) {
-            add(DataType.FLOAT, DataKind.S, false, 32, prefix + "s");
-            add(DataType.FLOAT, DataKind.T, false, 32, prefix + "t");
-            return this;
-        }
-
-        public Builder addFloatNorm() {
-            add(DataType.FLOAT, DataKind.NX, false, 32, null);
-            add(DataType.FLOAT, DataKind.NY, false, 32, null);
-            add(DataType.FLOAT, DataKind.NZ, false, 32, null);
-            return this;
-        }
-
-        public Builder addFloatNorm(String prefix) {
-            add(DataType.FLOAT, DataKind.NX, false, 32, prefix + "nx");
-            add(DataType.FLOAT, DataKind.NY, false, 32, prefix + "ny");
-            add(DataType.FLOAT, DataKind.NZ, false, 32, prefix + "nz");
-            return this;
-        }
-
-        public Builder addFloatPointSize() {
-            add(DataType.FLOAT, DataKind.POINT_SIZE, false, 32, null);
-            return this;
-        }
-
-        public Builder addFloatPointSize(String prefix) {
-            add(DataType.FLOAT, DataKind.POINT_SIZE, false, 32, prefix + "pointSize");
-            return this;
-        }
-
-        public Builder addFloatRGB() {
-            add(DataType.FLOAT, DataKind.RED, false, 32, null);
-            add(DataType.FLOAT, DataKind.GREEN, false, 32, null);
-            add(DataType.FLOAT, DataKind.BLUE, false, 32, null);
-            return this;
-        }
-
-        public Builder addFloatRGB(String prefix) {
-            add(DataType.FLOAT, DataKind.RED, false, 32, prefix + "r");
-            add(DataType.FLOAT, DataKind.GREEN, false, 32, prefix + "g");
-            add(DataType.FLOAT, DataKind.BLUE, false, 32, prefix + "b");
-            return this;
-        }
-
-        public Builder addFloatRGBA() {
-            add(DataType.FLOAT, DataKind.RED, false, 32, null);
-            add(DataType.FLOAT, DataKind.GREEN, false, 32, null);
-            add(DataType.FLOAT, DataKind.BLUE, false, 32, null);
-            add(DataType.FLOAT, DataKind.ALPHA, false, 32, null);
-            return this;
-        }
-
-        public Builder addFloatRGBA(String prefix) {
-            add(DataType.FLOAT, DataKind.RED, false, 32, prefix + "r");
-            add(DataType.FLOAT, DataKind.GREEN, false, 32, prefix + "g");
-            add(DataType.FLOAT, DataKind.BLUE, false, 32, prefix + "b");
-            add(DataType.FLOAT, DataKind.ALPHA, false, 32, prefix + "a");
-            return this;
-        }
-
-        public Builder addUNorm8RGBA() {
-            add(DataType.UNSIGNED, DataKind.RED, true, 8, null);
-            add(DataType.UNSIGNED, DataKind.GREEN, true, 8, null);
-            add(DataType.UNSIGNED, DataKind.BLUE, true, 8, null);
-            add(DataType.UNSIGNED, DataKind.ALPHA, true, 8, null);
-            return this;
-        }
-
-        public Builder addUNorm8RGBA(String prefix) {
-            add(DataType.UNSIGNED, DataKind.RED, true, 8, prefix + "r");
-            add(DataType.UNSIGNED, DataKind.GREEN, true, 8, prefix + "g");
-            add(DataType.UNSIGNED, DataKind.BLUE, true, 8, prefix + "b");
-            add(DataType.UNSIGNED, DataKind.ALPHA, true, 8, prefix + "a");
-            return this;
+            mElements[mCount] = element;
+            mElementNames[mCount] = name;
+            mCount++;
         }
 
         public Element create() {
             mRS.validate();
-            Element e = new Element(mRS, mEntryCount);
-            java.lang.System.arraycopy(mEntries, 0, e.mEntries, 0, mEntryCount);
-            e.init();
-            return e;
+            Element[] ein = new Element[mCount];
+            String[] sin = new String[mCount];
+            java.lang.System.arraycopy(mElements, 0, ein, 0, mCount);
+            java.lang.System.arraycopy(mElementNames, 0, sin, 0, mCount);
+            return new Element(mRS, ein, sin);
         }
     }
 
+    static void initPredefined(RenderScript rs) {
+        int a8 = rs.nElementCreate(DataType.UNSIGNED_8.mID,
+                                   DataKind.PIXEL_A.mID, true, 1);
+        int rgba4444 = rs.nElementCreate(DataType.UNSIGNED_4_4_4_4.mID,
+                                         DataKind.PIXEL_RGBA.mID, true, 4);
+        int rgba8888 = rs.nElementCreate(DataType.UNSIGNED_8.mID,
+                                         DataKind.PIXEL_RGBA.mID, true, 4);
+        int rgb565 = rs.nElementCreate(DataType.UNSIGNED_5_6_5.mID,
+                                       DataKind.PIXEL_RGB.mID, true, 3);
+        rs.nInitElements(a8, rgba4444, rgba8888, rgb565);
+    }
 }
 
diff --git a/graphics/java/android/renderscript/Program.java b/graphics/java/android/renderscript/Program.java
new file mode 100644
index 0000000..1614ec5
--- /dev/null
+++ b/graphics/java/android/renderscript/Program.java
@@ -0,0 +1,144 @@
+/*
+ * 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 android.renderscript;
+
+
+import android.util.Config;
+import android.util.Log;
+
+
+/**
+ * @hide
+ *
+ **/
+public class Program extends BaseObj {
+    public static final int MAX_INPUT = 8;
+    public static final int MAX_OUTPUT = 8;
+    public static final int MAX_CONSTANT = 8;
+    public static final int MAX_TEXTURE = 8;
+
+    Element mInputs[];
+    Element mOutputs[];
+    Type mConstants[];
+    int mTextureCount;
+    String mShader;
+
+    Program(int id, RenderScript rs) {
+        super(rs);
+        mID = id;
+    }
+
+    public void bindConstants(Allocation a, int slot) {
+        mRS.nProgramBindConstants(mID, slot, a.mID);
+    }
+
+    public void bindTexture(Allocation va, int slot)
+        throws IllegalArgumentException {
+        mRS.validate();
+        if((slot < 0) || (slot >= mTextureCount)) {
+            throw new IllegalArgumentException("Slot ID out of range.");
+        }
+
+        mRS.nProgramBindTexture(mID, slot, va.mID);
+    }
+
+    public void bindSampler(Sampler vs, int slot)
+        throws IllegalArgumentException {
+        mRS.validate();
+        if((slot < 0) || (slot >= mTextureCount)) {
+            throw new IllegalArgumentException("Slot ID out of range.");
+        }
+
+        mRS.nProgramBindSampler(mID, slot, vs.mID);
+    }
+
+
+    public static class BaseProgramBuilder {
+        RenderScript mRS;
+        Element mInputs[];
+        Element mOutputs[];
+        Type mConstants[];
+        Type mTextures[];
+        int mInputCount;
+        int mOutputCount;
+        int mConstantCount;
+        int mTextureCount;
+        String mShader;
+
+
+        protected BaseProgramBuilder(RenderScript rs) {
+            mRS = rs;
+            mInputs = new Element[MAX_INPUT];
+            mOutputs = new Element[MAX_OUTPUT];
+            mConstants = new Type[MAX_CONSTANT];
+            mInputCount = 0;
+            mOutputCount = 0;
+            mConstantCount = 0;
+            mTextureCount = 0;
+        }
+
+        public void setShader(String s) {
+            mShader = s;
+        }
+
+        public void addInput(Element e) throws IllegalStateException {
+            // Should check for consistant and non-conflicting names...
+            if(mInputCount >= MAX_INPUT) {
+                throw new IllegalArgumentException("Max input count exceeded.");
+            }
+            mInputs[mInputCount++] = e;
+        }
+
+        public void addOutput(Element e) throws IllegalStateException {
+            // Should check for consistant and non-conflicting names...
+            if(mOutputCount >= MAX_OUTPUT) {
+                throw new IllegalArgumentException("Max output count exceeded.");
+            }
+            mOutputs[mOutputCount++] = e;
+        }
+
+        public int addConstant(Type t) throws IllegalStateException {
+            // Should check for consistant and non-conflicting names...
+            if(mConstantCount >= MAX_CONSTANT) {
+                throw new IllegalArgumentException("Max input count exceeded.");
+            }
+            mConstants[mConstantCount] = t;
+            return mConstantCount++;
+        }
+
+        public void setTextureCount(int count) throws IllegalArgumentException {
+            // Should check for consistant and non-conflicting names...
+            if(count >= MAX_CONSTANT) {
+                throw new IllegalArgumentException("Max texture count exceeded.");
+            }
+            mTextureCount = count;
+        }
+
+        protected void initProgram(Program p) {
+            p.mInputs = new Element[mInputCount];
+            System.arraycopy(mInputs, 0, p.mInputs, 0, mInputCount);
+            p.mOutputs = new Element[mOutputCount];
+            System.arraycopy(mOutputs, 0, p.mOutputs, 0, mOutputCount);
+            p.mConstants = new Type[mConstantCount];
+            System.arraycopy(mConstants, 0, p.mConstants, 0, mConstantCount);
+            p.mTextureCount = mTextureCount;
+        }
+    }
+
+}
+
+
diff --git a/graphics/java/android/renderscript/ProgramFragment.java b/graphics/java/android/renderscript/ProgramFragment.java
index 1a72578..5e04f0c 100644
--- a/graphics/java/android/renderscript/ProgramFragment.java
+++ b/graphics/java/android/renderscript/ProgramFragment.java
@@ -25,134 +25,115 @@
  * @hide
  *
  **/
-public class ProgramFragment extends BaseObj {
-    public static final int MAX_SLOT = 2;
-
-    public enum EnvMode {
-        REPLACE (0),
-        MODULATE (1),
-        DECAL (2);
-
-        int mID;
-        EnvMode(int id) {
-            mID = id;
-        }
-    }
-
-
+public class ProgramFragment extends Program {
     ProgramFragment(int id, RenderScript rs) {
-        super(rs);
-        mID = id;
+        super(id, rs);
     }
 
-    public void bindTexture(Allocation va, int slot)
-        throws IllegalArgumentException {
-        mRS.validate();
-        if((slot < 0) || (slot >= MAX_SLOT)) {
-            throw new IllegalArgumentException("Slot ID out of range.");
+    public static class ShaderBuilder extends BaseProgramBuilder {
+        public ShaderBuilder(RenderScript rs) {
+            super(rs);
         }
 
-        mRS.nProgramFragmentBindTexture(mID, slot, va.mID);
-    }
+        public ProgramFragment create() {
+            mRS.validate();
+            int[] tmp = new int[(mInputCount + mOutputCount + mConstantCount + 1) * 2];
+            int idx = 0;
 
-    public void bindSampler(Sampler vs, int slot)
-        throws IllegalArgumentException {
-        mRS.validate();
-        if((slot < 0) || (slot >= MAX_SLOT)) {
-            throw new IllegalArgumentException("Slot ID out of range.");
+            for (int i=0; i < mInputCount; i++) {
+                tmp[idx++] = 0;
+                tmp[idx++] = mInputs[i].mID;
+            }
+            for (int i=0; i < mOutputCount; i++) {
+                tmp[idx++] = 1;
+                tmp[idx++] = mOutputs[i].mID;
+            }
+            for (int i=0; i < mConstantCount; i++) {
+                tmp[idx++] = 2;
+                tmp[idx++] = mConstants[i].mID;
+            }
+            tmp[idx++] = 3;
+            tmp[idx++] = mTextureCount;
+
+            int id = mRS.nProgramFragmentCreate2(mShader, tmp);
+            ProgramFragment pf = new ProgramFragment(id, mRS);
+            initProgram(pf);
+            return pf;
         }
-
-        mRS.nProgramFragmentBindSampler(mID, slot, vs.mID);
     }
 
-
     public static class Builder {
+        public static final int MAX_TEXTURE = 2;
         RenderScript mRS;
-        Element mIn;
-        Element mOut;
         boolean mPointSpriteEnable;
 
-        private class Slot {
-            Type mType;
-            EnvMode mEnv;
-            boolean mTexEnable;
+        public enum EnvMode {
+            REPLACE (1),
+            MODULATE (2),
+            DECAL (3);
 
-            Slot() {
-                mTexEnable = false;
+            int mID;
+            EnvMode(int id) {
+                mID = id;
+            }
+        }
+
+        public enum Format {
+            ALPHA (1),
+            LUMINANCE_ALPHA (2),
+            RGB (3),
+            RGBA (4);
+
+            int mID;
+            Format(int id) {
+                mID = id;
+            }
+        }
+
+        private class Slot {
+            EnvMode env;
+            Format format;
+            Slot(EnvMode _env, Format _fmt) {
+                env = _env;
+                format = _fmt;
             }
         }
         Slot[] mSlots;
 
-        public Builder(RenderScript rs, Element in, Element out) {
+        public Builder(RenderScript rs) {
             mRS = rs;
-            mIn = in;
-            mOut = out;
-            mSlots = new Slot[MAX_SLOT];
+            mSlots = new Slot[MAX_TEXTURE];
             mPointSpriteEnable = false;
-            for(int ct=0; ct < MAX_SLOT; ct++) {
-                mSlots[ct] = new Slot();
-            }
         }
 
-        public void setType(int slot, Type t)
+        public void setTexture(EnvMode env, Format fmt, int slot)
             throws IllegalArgumentException {
-            if((slot < 0) || (slot >= MAX_SLOT)) {
-                throw new IllegalArgumentException("Slot ID out of range.");
+            if((slot < 0) || (slot >= MAX_TEXTURE)) {
+                throw new IllegalArgumentException("MAX_TEXTURE exceeded.");
             }
-
-            mSlots[slot].mType = t;
-        }
-
-        public void setTexEnable(boolean enable, int slot)
-            throws IllegalArgumentException {
-            if((slot < 0) || (slot >= MAX_SLOT)) {
-                throw new IllegalArgumentException("Slot ID out of range.");
-            }
-
-            mSlots[slot].mTexEnable = enable;
-        }
-
-        public void setTexEnvMode(EnvMode env, int slot)
-            throws IllegalArgumentException {
-            if((slot < 0) || (slot >= MAX_SLOT)) {
-                throw new IllegalArgumentException("Slot ID out of range.");
-            }
-
-            mSlots[slot].mEnv = env;
+            mSlots[slot] = new Slot(env, fmt);
         }
 
         public void setPointSpriteTexCoordinateReplacement(boolean enable) {
             mPointSpriteEnable = enable;
         }
 
-        static synchronized ProgramFragment internalCreate(RenderScript rs, Builder b) {
-            int inID = 0;
-            int outID = 0;
-            if (b.mIn != null) {
-                inID = b.mIn.mID;
-            }
-            if (b.mOut != null) {
-                outID = b.mOut.mID;
-            }
-            rs.nProgramFragmentBegin(inID, outID, b.mPointSpriteEnable);
-            for(int ct=0; ct < MAX_SLOT; ct++) {
-                if(b.mSlots[ct].mTexEnable) {
-                    Slot s = b.mSlots[ct];
-                    int typeID = 0;
-                    if(s.mType != null) {
-                        typeID = s.mType.mID;
-                    }
-                    rs.nProgramFragmentSetSlot(ct, true, s.mEnv.mID, typeID);
-                }
-            }
-
-            int id = rs.nProgramFragmentCreate();
-            return new ProgramFragment(id, rs);
-        }
-
         public ProgramFragment create() {
             mRS.validate();
-            return internalCreate(mRS, this);
+            int[] tmp = new int[MAX_TEXTURE * 2 + 1];
+            if (mSlots[0] != null) {
+                tmp[0] = mSlots[0].env.mID;
+                tmp[1] = mSlots[0].format.mID;
+            }
+            if (mSlots[1] != null) {
+                tmp[2] = mSlots[1].env.mID;
+                tmp[3] = mSlots[1].format.mID;
+            }
+            tmp[4] = mPointSpriteEnable ? 1 : 0;
+            int id = mRS.nProgramFragmentCreate(tmp);
+            ProgramFragment pf = new ProgramFragment(id, mRS);
+            pf.mTextureCount = MAX_TEXTURE;
+            return pf;
         }
     }
 }
diff --git a/graphics/java/android/renderscript/ProgramVertex.java b/graphics/java/android/renderscript/ProgramVertex.java
index ba97d5b..84f6f2d 100644
--- a/graphics/java/android/renderscript/ProgramVertex.java
+++ b/graphics/java/android/renderscript/ProgramVertex.java
@@ -25,72 +25,67 @@
  * @hide
  *
  **/
-public class ProgramVertex extends BaseObj {
+public class ProgramVertex extends Program {
     public static final int MAX_LIGHT = 8;
 
+
     ProgramVertex(int id, RenderScript rs) {
-        super(rs);
-        mID = id;
+        super(id, rs);
     }
 
     public void bindAllocation(MatrixAllocation va) {
         mRS.validate();
-        mRS.nProgramVertexBindAllocation(mID, va.mAlloc.mID);
+        bindConstants(va.mAlloc, 0);
     }
 
 
     public static class Builder {
         RenderScript mRS;
-        Element mIn;
-        Element mOut;
-        Light[] mLights;
-        int mLightCount;
         boolean mTextureMatrixEnable;
 
-
         public Builder(RenderScript rs, Element in, Element out) {
             mRS = rs;
-            mIn = in;
-            mOut = out;
-            mLights = new Light[MAX_LIGHT];
-            mLightCount = 0;
         }
 
         public void setTextureMatrixEnable(boolean enable) {
             mTextureMatrixEnable = enable;
         }
 
-        public void addLight(Light l) throws IllegalStateException {
-            if(mLightCount >= MAX_LIGHT) {
-                throw new IllegalArgumentException("Max light count exceeded.");
-            }
-            mLights[mLightCount] = l;
-            mLightCount++;
+        public ProgramVertex create() {
+            int id = mRS.nProgramVertexCreate(mTextureMatrixEnable);
+            return new ProgramVertex(id, mRS);
         }
+    }
 
-
-
-        static synchronized ProgramVertex internalCreate(RenderScript rs, Builder b) {
-            int inID = 0;
-            int outID = 0;
-            if (b.mIn != null) {
-                inID = b.mIn.mID;
-            }
-            if (b.mOut != null) {
-                outID = b.mOut.mID;
-            }
-            rs.nProgramVertexBegin(inID, outID);
-            for(int ct=0; ct < b.mLightCount; ct++) {
-                rs.nProgramVertexAddLight(b.mLights[ct].mID);
-            }
-            rs.nProgramVertexSetTextureMatrixEnable(b.mTextureMatrixEnable);
-            int id = rs.nProgramVertexCreate();
-            return new ProgramVertex(id, rs);
+    public static class ShaderBuilder extends BaseProgramBuilder {
+        public ShaderBuilder(RenderScript rs) {
+            super(rs);
         }
 
         public ProgramVertex create() {
             mRS.validate();
-            return internalCreate(mRS, this);
+            int[] tmp = new int[(mInputCount + mOutputCount + mConstantCount +1) * 2];
+            int idx = 0;
+
+            for (int i=0; i < mInputCount; i++) {
+                tmp[idx++] = 0;
+                tmp[idx++] = mInputs[i].mID;
+            }
+            for (int i=0; i < mOutputCount; i++) {
+                tmp[idx++] = 1;
+                tmp[idx++] = mOutputs[i].mID;
+            }
+            for (int i=0; i < mConstantCount; i++) {
+                tmp[idx++] = 2;
+                tmp[idx++] = mConstants[i].mID;
+            }
+            tmp[idx++] = 3;
+            tmp[idx++] = mTextureCount;
+
+            int id = mRS.nProgramVertexCreate2(mShader, tmp);
+            ProgramVertex pv = new ProgramVertex(id, mRS);
+            initProgram(pv);
+            return pv;
         }
     }
 
@@ -112,7 +107,7 @@
             mProjection = new Matrix();
             mTexture = new Matrix();
 
-            mAlloc = Allocation.createSized(rs, Element.USER_F32(rs), 48);
+            mAlloc = Allocation.createSized(rs, Element.createUser(rs, Element.DataType.FLOAT_32), 48);
             mAlloc.subData1D(MODELVIEW_OFFSET, 16, mModel.mMat);
             mAlloc.subData1D(PROJECTION_OFFSET, 16, mProjection.mMat);
             mAlloc.subData1D(TEXTURE_OFFSET, 16, mTexture.mMat);
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 0d8b675..29361af 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -76,8 +76,6 @@
     native void nContextBindProgramFragment(int pf);
     native void nContextBindProgramVertex(int pf);
     native void nContextBindProgramRaster(int pr);
-    native void nContextAddDefineI32(String name, int value);
-    native void nContextAddDefineF(String name, float value);
     native void nContextPause();
     native void nContextResume();
     native int nContextGetMessage(int[] data, boolean wait);
@@ -89,9 +87,9 @@
     native void nObjDestroyOOB(int id);
     native int  nFileOpen(byte[] name);
 
-    native void nElementBegin();
-    native void nElementAdd(int kind, int type, boolean norm, int bits, String s);
-    native int  nElementCreate();
+
+    native int  nElementCreate(int type, int kind, boolean norm, int vecSize);
+    native int  nElementCreate2(int[] elements, String[] names);
 
     native void nTypeBegin(int elementID);
     native void nTypeAdd(int dim, int val);
@@ -167,17 +165,15 @@
     native void nProgramRasterSetLineWidth(int pr, float v);
     native void nProgramRasterSetPointSize(int pr, float v);
 
-    native void nProgramFragmentBegin(int in, int out, boolean pointSpriteEnable);
-    native void nProgramFragmentBindTexture(int vpf, int slot, int a);
-    native void nProgramFragmentBindSampler(int vpf, int slot, int s);
-    native void nProgramFragmentSetSlot(int slot, boolean enable, int env, int vt);
-    native int  nProgramFragmentCreate();
+    native void nProgramBindConstants(int pv, int slot, int mID);
+    native void nProgramBindTexture(int vpf, int slot, int a);
+    native void nProgramBindSampler(int vpf, int slot, int s);
 
-    native void nProgramVertexBindAllocation(int pv, int mID);
-    native void nProgramVertexBegin(int inID, int outID);
-    native void nProgramVertexSetTextureMatrixEnable(boolean enable);
-    native void nProgramVertexAddLight(int id);
-    native int  nProgramVertexCreate();
+    native int  nProgramFragmentCreate(int[] params);
+    native int  nProgramFragmentCreate2(String shader, int[] params);
+
+    native int  nProgramVertexCreate(boolean texMat);
+    native int  nProgramVertexCreate2(String shader, int[] params);
 
     native void nLightBegin();
     native void nLightSetIsMono(boolean isMono);
@@ -200,14 +196,13 @@
     private Surface mSurface;
     private MessageThread mMessageThread;
 
-
     Element mElement_USER_U8;
     Element mElement_USER_I8;
     Element mElement_USER_U16;
     Element mElement_USER_I16;
     Element mElement_USER_U32;
     Element mElement_USER_I32;
-    Element mElement_USER_FLOAT;
+    Element mElement_USER_F32;
 
     Element mElement_A_8;
     Element mElement_RGB_565;
@@ -217,9 +212,12 @@
     Element mElement_RGBA_8888;
 
     Element mElement_INDEX_16;
-    Element mElement_XY_F32;
-    Element mElement_XYZ_F32;
-
+    Element mElement_POSITION_2;
+    Element mElement_POSITION_3;
+    Element mElement_TEXTURE_2;
+    Element mElement_NORMAL_3;
+    Element mElement_COLOR_U8_4;
+    Element mElement_COLOR_F32_4;
 
     ///////////////////////////////////////////////////////////////////////////////////
     //
@@ -248,13 +246,8 @@
         }
     }
 
-    void validateSurface() {
-        if (mSurface == null) {
-            throw new IllegalStateException("Uploading data to GL with no surface.");
-        }
-    }
-
     public void contextSetPriority(Priority p) {
+        validate();
         nContextSetPriority(p.mID);
     }
 
@@ -305,23 +298,26 @@
             nDeviceSetConfig(mDev, 0, 1);
         }
         mContext = nContextCreate(mDev, 0, useDepth);
-        Element.initPredefined(this);
         mMessageThread = new MessageThread(this);
         mMessageThread.start();
+        Element.initPredefined(this);
     }
 
     public void contextSetSurface(int w, int h, Surface sur) {
         mSurface = sur;
         mWidth = w;
         mHeight = h;
+        validate();
         nContextSetSurface(w, h, mSurface);
     }
 
     public void contextDump(int bits) {
+        validate();
         nContextDump(bits);
     }
 
     public void destroy() {
+        validate();
         nContextDeinitToClient();
         mMessageThread.mRun = false;
 
@@ -337,10 +333,12 @@
     }
 
     void pause() {
+        validate();
         nContextPause();
     }
 
     void resume() {
+        validate();
         nContextResume();
     }
 
@@ -381,22 +379,27 @@
     }
 
     public void contextBindRootScript(Script s) {
+        validate();
         nContextBindRootScript(safeID(s));
     }
 
     public void contextBindProgramFragmentStore(ProgramStore p) {
+        validate();
         nContextBindProgramFragmentStore(safeID(p));
     }
 
     public void contextBindProgramFragment(ProgramFragment p) {
+        validate();
         nContextBindProgramFragment(safeID(p));
     }
 
     public void contextBindProgramRaster(ProgramRaster p) {
+        validate();
         nContextBindProgramRaster(safeID(p));
     }
 
     public void contextBindProgramVertex(ProgramVertex p) {
+        validate();
         nContextBindProgramVertex(safeID(p));
     }
 
diff --git a/graphics/java/android/renderscript/Sampler.java b/graphics/java/android/renderscript/Sampler.java
index 625a576..40ba722 100644
--- a/graphics/java/android/renderscript/Sampler.java
+++ b/graphics/java/android/renderscript/Sampler.java
@@ -69,23 +69,45 @@
         }
 
         public void setMin(Value v) {
-            mMin = v;
+            if (v == Value.NEAREST ||
+                v == Value.LINEAR ||
+                v == Value.LINEAR_MIP_LINEAR) {
+                mMin = v;
+            } else {
+                throw new IllegalArgumentException("Invalid value");
+            }
         }
 
         public void setMag(Value v) {
-            mMag = v;
+            if (v == Value.NEAREST || v == Value.LINEAR) {
+                mMag = v;
+            } else {
+                throw new IllegalArgumentException("Invalid value");
+            }
         }
 
         public void setWrapS(Value v) {
-            mWrapS = v;
+            if (v == Value.WRAP || v == Value.CLAMP) {
+                mWrapS = v;
+            } else {
+                throw new IllegalArgumentException("Invalid value");
+            }
         }
 
         public void setWrapT(Value v) {
-            mWrapT = v;
+            if (v == Value.WRAP || v == Value.CLAMP) {
+                mWrapT = v;
+            } else {
+                throw new IllegalArgumentException("Invalid value");
+            }
         }
 
         public void setWrapR(Value v) {
-            mWrapR = v;
+            if (v == Value.WRAP || v == Value.CLAMP) {
+                mWrapR = v;
+            } else {
+                throw new IllegalArgumentException("Invalid value");
+            }
         }
 
         static synchronized Sampler internalCreate(RenderScript rs, Builder b) {
diff --git a/graphics/java/android/renderscript/SimpleMesh.java b/graphics/java/android/renderscript/SimpleMesh.java
index f45074e..4a217a9 100644
--- a/graphics/java/android/renderscript/SimpleMesh.java
+++ b/graphics/java/android/renderscript/SimpleMesh.java
@@ -313,28 +313,36 @@
         public SimpleMesh create() {
             Element.Builder b = new Element.Builder(mRS);
             int floatCount = mVtxSize;
-            if (mVtxSize == 2) {
-                b.addFloatXY();
-            } else {
-                b.addFloatXYZ();
-            }
+            b.add(Element.createAttrib(mRS,
+                                       Element.DataType.FLOAT_32,
+                                       Element.DataKind.POSITION,
+                                       mVtxSize), "position");
             if ((mFlags & COLOR) != 0) {
                 floatCount += 4;
-                b.addFloatRGBA();
+                b.add(Element.createAttrib(mRS,
+                                           Element.DataType.FLOAT_32,
+                                           Element.DataKind.COLOR,
+                                           4), "color");
             }
             if ((mFlags & TEXTURE_0) != 0) {
                 floatCount += 2;
-                b.addFloatST();
+                b.add(Element.createAttrib(mRS,
+                                           Element.DataType.FLOAT_32,
+                                           Element.DataKind.TEXTURE,
+                                           2), "texture");
             }
             if ((mFlags & NORMAL) != 0) {
                 floatCount += 3;
-                b.addFloatNorm();
+                b.add(Element.createAttrib(mRS,
+                                           Element.DataType.FLOAT_32,
+                                           Element.DataKind.NORMAL,
+                                           3), "normal");
             }
             mElement = b.create();
 
             Builder smb = new Builder(mRS);
             smb.addVertexType(mElement, mVtxCount / floatCount);
-            smb.setIndexType(Element.INDEX_16(mRS), mIndexCount);
+            smb.setIndexType(Element.createIndex(mRS), mIndexCount);
             smb.setPrimitive(Primitive.TRIANGLE);
             SimpleMesh sm = smb.create();
 
diff --git a/graphics/java/android/renderscript/Type.java b/graphics/java/android/renderscript/Type.java
index ad4cf6b..62d3867 100644
--- a/graphics/java/android/renderscript/Type.java
+++ b/graphics/java/android/renderscript/Type.java
@@ -34,6 +34,9 @@
     private int mNativeCache;
     Class mJavaClass;
 
+    public Element getElement() {
+        return mElement;
+    }
 
     public int getX() {
         return mDimX;
@@ -122,16 +125,16 @@
                 Field f = fields[ct];
                 Class fc = f.getType();
                 if(fc == int.class) {
-                    arTypes[ct] = Element.DataType.SIGNED.mID;
+                    arTypes[ct] = Element.DataType.SIGNED_32.mID;
                     arBits[ct] = 32;
                 } else if(fc == short.class) {
-                    arTypes[ct] = Element.DataType.SIGNED.mID;
+                    arTypes[ct] = Element.DataType.SIGNED_16.mID;
                     arBits[ct] = 16;
                 } else if(fc == byte.class) {
-                    arTypes[ct] = Element.DataType.SIGNED.mID;
+                    arTypes[ct] = Element.DataType.SIGNED_8.mID;
                     arBits[ct] = 8;
                 } else if(fc == float.class) {
-                    arTypes[ct] = Element.DataType.FLOAT.mID;
+                    arTypes[ct] = Element.DataType.FLOAT_32.mID;
                     arBits[ct] = 32;
                 } else {
                     throw new IllegalArgumentException("Unkown field type");
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index af3bc74..7ded133 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -247,36 +247,39 @@
 }
 
 
-static void
-nElementBegin(JNIEnv *_env, jobject _this)
+static jint
+nElementCreate(JNIEnv *_env, jobject _this, jint type, jint kind, jboolean norm, jint size)
 {
     RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
-    LOG_API("nElementBegin, con(%p)", con);
-    rsElementBegin(con);
-}
-
-
-static void
-nElementAdd(JNIEnv *_env, jobject _this, jint kind, jint type, jboolean norm, jint bits, jstring name)
-{
-    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
-    const char* n = NULL;
-    if (name) {
-        n = _env->GetStringUTFChars(name, NULL);
-    }
-    LOG_API("nElementAdd, con(%p), kind(%i), type(%i), norm(%i), bits(%i)", con, kind, type, norm, bits);
-    rsElementAdd(con, (RsDataKind)kind, (RsDataType)type, norm != 0, (size_t)bits, n);
-    if (n) {
-        _env->ReleaseStringUTFChars(name, n);
-    }
+    LOG_API("nElementCreate, con(%p), type(%i), kind(%i), norm(%i), size(%i)", con, type, kind, norm, size);
+    return (jint)rsElementCreate(con, (RsDataType)type, (RsDataKind)kind, norm, size);
 }
 
 static jint
-nElementCreate(JNIEnv *_env, jobject _this)
+nElementCreate2(JNIEnv *_env, jobject _this, jintArray _ids, jobjectArray _names)
 {
+    int fieldCount = _env->GetArrayLength(_ids);
     RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
-    LOG_API("nElementCreate, con(%p)", con);
-    return (jint)rsElementCreate(con);
+    LOG_API("nElementCreate, con(%p), type(%i), kind(%i), norm(%i), size(%i)", con, type, kind, norm, size);
+
+    jint *ids = _env->GetIntArrayElements(_ids, NULL);
+    const char ** nameArray = (const char **)calloc(fieldCount, sizeof(char *));
+    size_t* sizeArray = (size_t*)calloc(fieldCount, sizeof(size_t));
+
+    for (int ct=0; ct < fieldCount; ct++) {
+        jstring s = (jstring)_env->GetObjectArrayElement(_names, ct);
+        nameArray[ct] = _env->GetStringUTFChars(s, NULL);
+        sizeArray[ct] = _env->GetStringUTFLength(s);
+    }
+    jint id = (jint)rsElementCreate2(con, fieldCount, (RsElement *)ids, nameArray, sizeArray);
+    for (int ct=0; ct < fieldCount; ct++) {
+        jstring s = (jstring)_env->GetObjectArrayElement(_names, ct);
+        _env->ReleaseStringUTFChars(s, nameArray[ct]);
+    }
+    _env->ReleaseIntArrayElements(_ids, ids, JNI_ABORT);
+    free(nameArray);
+    free(sizeArray);
+    return (jint)id;
 }
 
 // -----------------------------------
@@ -395,26 +398,24 @@
         tfc[ct].bits = fBits[ct];
 
         switch(fType[ct]) {
-        case RS_TYPE_FLOAT:
+        case RS_TYPE_FLOAT_32:
             tfc[ct].ptr = SF_LoadFloat;
             tfc[ct].readPtr = SF_SaveFloat;
             break;
-        case RS_TYPE_UNSIGNED:
-        case RS_TYPE_SIGNED:
-            switch(tfc[ct].bits) {
-            case 32:
-                tfc[ct].ptr = SF_LoadInt;
-                tfc[ct].readPtr = SF_SaveInt;
-                break;
-            case 16:
-                tfc[ct].ptr = SF_LoadShort;
-                tfc[ct].readPtr = SF_SaveShort;
-                break;
-            case 8:
-                tfc[ct].ptr = SF_LoadByte;
-                tfc[ct].readPtr = SF_SaveByte;
-                break;
-            }
+        case RS_TYPE_UNSIGNED_32:
+        case RS_TYPE_SIGNED_32:
+            tfc[ct].ptr = SF_LoadInt;
+            tfc[ct].readPtr = SF_SaveInt;
+            break;
+        case RS_TYPE_UNSIGNED_16:
+        case RS_TYPE_SIGNED_16:
+            tfc[ct].ptr = SF_LoadShort;
+            tfc[ct].readPtr = SF_SaveShort;
+            break;
+        case RS_TYPE_UNSIGNED_8:
+        case RS_TYPE_SIGNED_8:
+            tfc[ct].ptr = SF_LoadByte;
+            tfc[ct].readPtr = SF_SaveByte;
             break;
         }
         tc->size += 4;
@@ -1056,91 +1057,93 @@
 // ---------------------------------------------------------------------------
 
 static void
-nProgramFragmentBegin(JNIEnv *_env, jobject _this, jint in, jint out, jboolean pointSpriteEnable)
+nProgramBindConstants(JNIEnv *_env, jobject _this, jint vpv, jint slot, jint a)
 {
     RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
-    LOG_API("nProgramFragmentBegin, con(%p), in(%p), out(%p) PointSprite(%i)", con, (RsElement)in, (RsElement)out, pointSpriteEnable);
-    rsProgramFragmentBegin(con, (RsElement)in, (RsElement)out, pointSpriteEnable);
+    LOG_API("nProgramBindConstants, con(%p), vpf(%p), sloat(%i), a(%p)", con, (RsProgramVertex)vpv, slot, (RsAllocation)a);
+    rsProgramBindConstants(con, (RsProgram)vpv, slot, (RsAllocation)a);
 }
 
 static void
-nProgramFragmentBindTexture(JNIEnv *_env, jobject _this, jint vpf, jint slot, jint a)
+nProgramBindTexture(JNIEnv *_env, jobject _this, jint vpf, jint slot, jint a)
 {
     RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
-    LOG_API("nProgramFragmentBindTexture, con(%p), vpf(%p), slot(%i), a(%p)", con, (RsProgramFragment)vpf, slot, (RsAllocation)a);
-    rsProgramFragmentBindTexture(con, (RsProgramFragment)vpf, slot, (RsAllocation)a);
+    LOG_API("nProgramBindTexture, con(%p), vpf(%p), slot(%i), a(%p)", con, (RsProgramFragment)vpf, slot, (RsAllocation)a);
+    rsProgramBindTexture(con, (RsProgramFragment)vpf, slot, (RsAllocation)a);
 }
 
 static void
-nProgramFragmentBindSampler(JNIEnv *_env, jobject _this, jint vpf, jint slot, jint a)
+nProgramBindSampler(JNIEnv *_env, jobject _this, jint vpf, jint slot, jint a)
 {
     RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
-    LOG_API("nProgramFragmentBindSampler, con(%p), vpf(%p), slot(%i), a(%p)", con, (RsProgramFragment)vpf, slot, (RsSampler)a);
-    rsProgramFragmentBindSampler(con, (RsProgramFragment)vpf, slot, (RsSampler)a);
-}
-
-static void
-nProgramFragmentSetSlot(JNIEnv *_env, jobject _this, jint slot, jboolean enable, jint env, jint vt)
-{
-    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
-    LOG_API("nProgramFragmentSetType, con(%p), slot(%i), enable(%i), env(%i), vt(%p)", con, slot, enable, env, (RsType)vt);
-    rsProgramFragmentSetSlot(con, slot, enable, (RsTexEnvMode)env, (RsType)vt);
-}
-
-static jint
-nProgramFragmentCreate(JNIEnv *_env, jobject _this, jint slot, jboolean enable)
-{
-    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
-    LOG_API("nProgramFragmentCreate, con(%p)", con);
-    return (jint)rsProgramFragmentCreate(con);
+    LOG_API("nProgramBindSampler, con(%p), vpf(%p), slot(%i), a(%p)", con, (RsProgramFragment)vpf, slot, (RsSampler)a);
+    rsProgramBindSampler(con, (RsProgramFragment)vpf, slot, (RsSampler)a);
 }
 
 // ---------------------------------------------------------------------------
 
-static void
-nProgramVertexBegin(JNIEnv *_env, jobject _this, jint in, jint out)
+static jint
+nProgramFragmentCreate(JNIEnv *_env, jobject _this, jintArray params)
 {
     RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
-    LOG_API("nProgramVertexBegin, con(%p), in(%p), out(%p)", con, (RsElement)in, (RsElement)out);
-    rsProgramVertexBegin(con, (RsElement)in, (RsElement)out);
-}
+    jint *paramPtr = _env->GetIntArrayElements(params, NULL);
+    jint paramLen = _env->GetArrayLength(params);
 
-static void
-nProgramVertexBindAllocation(JNIEnv *_env, jobject _this, jint vpv, jint a)
-{
-    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
-    LOG_API("nProgramVertexBindAllocation, con(%p), vpf(%p), a(%p)", con, (RsProgramVertex)vpv, (RsAllocation)a);
-    rsProgramVertexBindAllocation(con, (RsProgramFragment)vpv, (RsAllocation)a);
-}
+    LOG_API("nProgramFragmentCreate, con(%p), paramLen(%i)", con, shaderLen, paramLen);
 
-static void
-nProgramVertexSetTextureMatrixEnable(JNIEnv *_env, jobject _this, jboolean enable)
-{
-    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
-    LOG_API("nProgramVertexSetTextureMatrixEnable, con(%p), enable(%i)", con, enable);
-    rsProgramVertexSetTextureMatrixEnable(con, enable);
-}
-
-static void
-nProgramVertexAddLight(JNIEnv *_env, jobject _this, jint light)
-{
-    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
-    LOG_API("nProgramVertexAddLight, con(%p), light(%p)", con, (RsLight)light);
-    rsProgramVertexAddLight(con, (RsLight)light);
+    jint ret = (jint)rsProgramFragmentCreate(con, (uint32_t *)paramPtr, paramLen);
+    _env->ReleaseIntArrayElements(params, paramPtr, JNI_ABORT);
+    return ret;
 }
 
 static jint
-nProgramVertexCreate(JNIEnv *_env, jobject _this)
+nProgramFragmentCreate2(JNIEnv *_env, jobject _this, jstring shader, jintArray params)
 {
     RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
-    LOG_API("nProgramVertexCreate, con(%p)", con);
-    return (jint)rsProgramVertexCreate(con);
+    const char* shaderUTF = _env->GetStringUTFChars(shader, NULL);
+    jint shaderLen = _env->GetStringUTFLength(shader);
+    jint *paramPtr = _env->GetIntArrayElements(params, NULL);
+    jint paramLen = _env->GetArrayLength(params);
+
+    LOG_API("nProgramFragmentCreate2, con(%p), shaderLen(%i), paramLen(%i)", con, shaderLen, paramLen);
+
+    jint ret = (jint)rsProgramFragmentCreate2(con, shaderUTF, shaderLen, (uint32_t *)paramPtr, paramLen);
+    _env->ReleaseStringUTFChars(shader, shaderUTF);
+    _env->ReleaseIntArrayElements(params, paramPtr, JNI_ABORT);
+    return ret;
 }
 
 
 // ---------------------------------------------------------------------------
 
 static jint
+nProgramVertexCreate(JNIEnv *_env, jobject _this, jboolean texMat)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nProgramVertexCreate, con(%p), texMat(%i)", con, texMat);
+    return (jint)rsProgramVertexCreate(con, texMat);
+}
+
+static jint
+nProgramVertexCreate2(JNIEnv *_env, jobject _this, jstring shader, jintArray params)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    const char* shaderUTF = _env->GetStringUTFChars(shader, NULL);
+    jint shaderLen = _env->GetStringUTFLength(shader);
+    jint *paramPtr = _env->GetIntArrayElements(params, NULL);
+    jint paramLen = _env->GetArrayLength(params);
+
+    LOG_API("nProgramVertexCreate2, con(%p), shaderLen(%i), paramLen(%i)", con, shaderLen, paramLen);
+
+    jint ret = (jint)rsProgramVertexCreate2(con, shaderUTF, shaderLen, (uint32_t *)paramPtr, paramLen);
+    _env->ReleaseStringUTFChars(shader, shaderUTF);
+    _env->ReleaseIntArrayElements(params, paramPtr, JNI_ABORT);
+    return ret;
+}
+
+// ---------------------------------------------------------------------------
+
+static jint
 nProgramRasterCreate(JNIEnv *_env, jobject _this, jint in, jint out,
                      jboolean pointSmooth, jboolean lineSmooth, jboolean pointSprite)
 {
@@ -1209,26 +1212,6 @@
     rsContextBindProgramRaster(con, (RsProgramRaster)pf);
 }
 
-static void
-nContextAddDefineI32(JNIEnv *_env, jobject _this, jstring name, jint value)
-{
-    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
-    const char* n = _env->GetStringUTFChars(name, NULL);
-    LOG_API("nScriptCAddDefineI32, con(%p) name(%s) value(%d)", con, n, value);
-    rsContextSetDefineI32(con, n, value);
-    _env->ReleaseStringUTFChars(name, n);
-}
-
-static void
-nContextAddDefineF(JNIEnv *_env, jobject _this, jstring name, jfloat value)
-{
-    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
-    const char* n = _env->GetStringUTFChars(name, NULL);
-    LOG_API("nScriptCAddDefineF, con(%p) name(%s) value(%f)", con, n, value);
-    rsContextSetDefineF(con, n, value);
-    _env->ReleaseStringUTFChars(name, n);
-}
-
 
 // ---------------------------------------------------------------------------
 
@@ -1365,9 +1348,8 @@
 
 {"nFileOpen",                      "([B)I",                                (void*)nFileOpen },
 
-{"nElementBegin",                  "()V",                                  (void*)nElementBegin },
-{"nElementAdd",                    "(IIZILjava/lang/String;)V",            (void*)nElementAdd },
-{"nElementCreate",                 "()I",                                  (void*)nElementCreate },
+{"nElementCreate",                 "(IIZI)I",                              (void*)nElementCreate },
+{"nElementCreate2",                "([I[Ljava/lang/String;)I",             (void*)nElementCreate2 },
 
 {"nTypeBegin",                     "(I)V",                                 (void*)nTypeBegin },
 {"nTypeAdd",                       "(II)V",                                (void*)nTypeAdd },
@@ -1432,21 +1414,19 @@
 {"nProgramFragmentStoreDither",    "(Z)V",                                 (void*)nProgramFragmentStoreDither },
 {"nProgramFragmentStoreCreate",    "()I",                                  (void*)nProgramFragmentStoreCreate },
 
-{"nProgramFragmentBegin",          "(IIZ)V",                               (void*)nProgramFragmentBegin },
-{"nProgramFragmentBindTexture",    "(III)V",                               (void*)nProgramFragmentBindTexture },
-{"nProgramFragmentBindSampler",    "(III)V",                               (void*)nProgramFragmentBindSampler },
-{"nProgramFragmentSetSlot",        "(IZII)V",                              (void*)nProgramFragmentSetSlot },
-{"nProgramFragmentCreate",         "()I",                                  (void*)nProgramFragmentCreate },
+{"nProgramBindConstants",          "(III)V",                               (void*)nProgramBindConstants },
+{"nProgramBindTexture",            "(III)V",                               (void*)nProgramBindTexture },
+{"nProgramBindSampler",            "(III)V",                               (void*)nProgramBindSampler },
+
+{"nProgramFragmentCreate",         "([I)I",                                (void*)nProgramFragmentCreate },
+{"nProgramFragmentCreate2",        "(Ljava/lang/String;[I)I",              (void*)nProgramFragmentCreate2 },
 
 {"nProgramRasterCreate",           "(IIZZZ)I",                             (void*)nProgramRasterCreate },
 {"nProgramRasterSetPointSize",     "(IF)V",                                (void*)nProgramRasterSetPointSize },
 {"nProgramRasterSetLineWidth",     "(IF)V",                                (void*)nProgramRasterSetLineWidth },
 
-{"nProgramVertexBindAllocation",   "(II)V",                                (void*)nProgramVertexBindAllocation },
-{"nProgramVertexBegin",            "(II)V",                                (void*)nProgramVertexBegin },
-{"nProgramVertexSetTextureMatrixEnable",   "(Z)V",                         (void*)nProgramVertexSetTextureMatrixEnable },
-{"nProgramVertexAddLight",         "(I)V",                                 (void*)nProgramVertexAddLight },
-{"nProgramVertexCreate",           "()I",                                  (void*)nProgramVertexCreate },
+{"nProgramVertexCreate",           "(Z)I",                                 (void*)nProgramVertexCreate },
+{"nProgramVertexCreate2",          "(Ljava/lang/String;[I)I",              (void*)nProgramVertexCreate2 },
 
 {"nLightBegin",                    "()V",                                  (void*)nLightBegin },
 {"nLightSetIsMono",                "(Z)V",                                 (void*)nLightSetIsMono },
diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk
index d364277..88521f6 100644
--- a/libs/rs/Android.mk
+++ b/libs/rs/Android.mk
@@ -96,11 +96,14 @@
 	rsScript.cpp \
 	rsScriptC.cpp \
 	rsScriptC_Lib.cpp \
+        rsShaderCache.cpp \
 	rsSimpleMesh.cpp \
 	rsThreadIO.cpp \
-	rsType.cpp
+	rsType.cpp \
+	rsVertexArray.cpp
 
-LOCAL_SHARED_LIBRARIES += libcutils libutils libEGL libGLESv1_CM libui libacc
+
+LOCAL_SHARED_LIBRARIES += libcutils libutils libEGL libGLESv1_CM libGLESv2 libui libacc
 LOCAL_LDLIBS := -lpthread -ldl
 LOCAL_MODULE:= libRS
 LOCAL_MODULE_TAGS := optional
diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h
index 3ca8b15..6662333 100644
--- a/libs/rs/RenderScript.h
+++ b/libs/rs/RenderScript.h
@@ -36,11 +36,11 @@
 typedef void * RsFile;
 typedef void * RsSampler;
 typedef void * RsScript;
-typedef void * RsScriptBasicTemp;
 typedef void * RsSimpleMesh;
 typedef void * RsType;
 typedef void * RsLight;
 
+typedef void * RsProgram;
 typedef void * RsProgramVertex;
 typedef void * RsProgramFragment;
 typedef void * RsProgramFragmentStore;
@@ -64,34 +64,53 @@
 void rsContextDeinitToClient(RsContext);
 
 #define RS_MAX_TEXTURE 2
+#define RS_MAX_ATTRIBS 16
 
 enum RsDataType {
-    RS_TYPE_FLOAT,
-    RS_TYPE_UNSIGNED,
-    RS_TYPE_SIGNED
+    RS_TYPE_NONE,
+    RS_TYPE_FLOAT_16,
+    RS_TYPE_FLOAT_32,
+    RS_TYPE_FLOAT_64,
+    RS_TYPE_SIGNED_8,
+    RS_TYPE_SIGNED_16,
+    RS_TYPE_SIGNED_32,
+    RS_TYPE_SIGNED_64,
+    RS_TYPE_UNSIGNED_8,
+    RS_TYPE_UNSIGNED_16,
+    RS_TYPE_UNSIGNED_32,
+    RS_TYPE_UNSIGNED_64,
+
+    RS_TYPE_UNSIGNED_5_6_5,
+    RS_TYPE_UNSIGNED_5_5_5_1,
+    RS_TYPE_UNSIGNED_4_4_4_4,
+
+    RS_TYPE_ELEMENT,
+    RS_TYPE_TYPE,
+    RS_TYPE_ALLOCATION,
+    RS_TYPE_SAMPLER,
+    RS_TYPE_SCRIPT,
+    RS_TYPE_MESH,
+    RS_TYPE_PROGRAM_FRAGMENT,
+    RS_TYPE_PROGRAM_VERTEX,
+    RS_TYPE_PROGRAM_RASTER,
+    RS_TYPE_PROGRAM_STORE
 };
 
 enum RsDataKind {
     RS_KIND_USER,
-    RS_KIND_RED,
-    RS_KIND_GREEN,
-    RS_KIND_BLUE,
-    RS_KIND_ALPHA,
-    RS_KIND_LUMINANCE,
-    RS_KIND_INTENSITY,
-    RS_KIND_X,
-    RS_KIND_Y,
-    RS_KIND_Z,
-    RS_KIND_W,
-    RS_KIND_S,
-    RS_KIND_T,
-    RS_KIND_Q,
-    RS_KIND_R,
-    RS_KIND_NX,
-    RS_KIND_NY,
-    RS_KIND_NZ,
+    RS_KIND_COLOR,
+    RS_KIND_POSITION,
+    RS_KIND_TEXTURE,
+    RS_KIND_NORMAL,
     RS_KIND_INDEX,
-    RS_KIND_POINT_SIZE
+    RS_KIND_POINT_SIZE,
+
+    RS_KIND_PIXEL_L,
+    RS_KIND_PIXEL_A,
+    RS_KIND_PIXEL_LA,
+    RS_KIND_PIXEL_RGB,
+    RS_KIND_PIXEL_RGBA,
+
 };
 
 enum RsSamplerParam {
@@ -158,11 +177,19 @@
 };
 
 enum RsTexEnvMode {
+    RS_TEX_ENV_MODE_NONE,
     RS_TEX_ENV_MODE_REPLACE,
     RS_TEX_ENV_MODE_MODULATE,
     RS_TEX_ENV_MODE_DECAL
 };
 
+enum RsProgramParam {
+    RS_PROGRAM_PARAM_INPUT,
+    RS_PROGRAM_PARAM_OUTPUT,
+    RS_PROGRAM_PARAM_CONSTANT,
+    RS_PROGRAM_PARAM_TEXTURE_COUNT,
+};
+
 enum RsPrimitive {
     RS_PRIMITIVE_POINT,
     RS_PRIMITIVE_LINE,
diff --git a/libs/rs/RenderScriptEnv.h b/libs/rs/RenderScriptEnv.h
index ff0a7b1..99b8c04 100644
--- a/libs/rs/RenderScriptEnv.h
+++ b/libs/rs/RenderScriptEnv.h
@@ -9,7 +9,6 @@
 typedef void * RsElement;
 typedef void * RsSampler;
 typedef void * RsScript;
-typedef void * RsScriptBasicTemp;
 typedef void * RsSimpleMesh;
 typedef void * RsType;
 typedef void * RsProgramFragment;
diff --git a/libs/rs/java/Film/src/com/android/film/FilmRS.java b/libs/rs/java/Film/src/com/android/film/FilmRS.java
index b5b6723..b80e619 100644
--- a/libs/rs/java/Film/src/com/android/film/FilmRS.java
+++ b/libs/rs/java/Film/src/com/android/film/FilmRS.java
@@ -121,13 +121,13 @@
         bs.setWrapT(Sampler.Value.WRAP);
         mSampler = bs.create();
 
-        ProgramFragment.Builder b = new ProgramFragment.Builder(mRS, null, null);
-
+        ProgramFragment.Builder b = new ProgramFragment.Builder(mRS);
         mPFBackground = b.create();
         mPFBackground.setName("PFBackground");
 
-        b.setTexEnable(true, 0);
-        b.setTexEnvMode(ProgramFragment.EnvMode.REPLACE, 0);
+        b = new ProgramFragment.Builder(mRS);
+        b.setTexture(ProgramFragment.Builder.EnvMode.REPLACE,
+                     ProgramFragment.Builder.Format.RGBA, 0);
         mPFImages = b.create();
         mPFImages.bindSampler(mSampler, 0);
         mPFImages.setName("PFImages");
@@ -138,7 +138,7 @@
         mLight.setPosition(0, -0.5f, -1.0f);
 
         ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS, null, null);
-        pvb.addLight(mLight);
+        //pvb.addLight(mLight);
         mPVBackground = pvb.create();
         mPVBackground.setName("PVBackground");
 
@@ -152,9 +152,10 @@
         mBufferIDs = new int[13];
         mImages = new Allocation[13];
         mAllocIDs = Allocation.createSized(mRS,
-            Element.USER_F32(mRS), mBufferIDs.length);
+            Element.createUser(mRS, Element.DataType.FLOAT_32),
+            mBufferIDs.length);
 
-        Element ie = Element.RGB_565(mRS);
+        Element ie = Element.createPixel(mRS, Element.DataType.UNSIGNED_5_6_5, Element.DataKind.PIXEL_RGB);
         mImages[0] = Allocation.createFromBitmapResourceBoxed(mRS, mRes, R.drawable.p01, ie, true);
         mImages[1] = Allocation.createFromBitmapResourceBoxed(mRS, mRes, R.drawable.p02, ie, true);
         mImages[2] = Allocation.createFromBitmapResourceBoxed(mRS, mRes, R.drawable.p03, ie, true);
@@ -195,7 +196,8 @@
     {
         mBufferState = new int[10];
         mAllocState = Allocation.createSized(mRS,
-            Element.USER_F32(mRS), mBufferState.length);
+            Element.createUser(mRS, Element.DataType.FLOAT_32),
+            mBufferState.length);
         mBufferState[STATE_LAST_FOCUS] = -1;
         mAllocState.data(mBufferState);
     }
@@ -238,12 +240,12 @@
 
 
         mAllocOffsets = Allocation.createSized(mRS,
-            Element.USER_I32(mRS), mFSM.mTriangleOffsets.length);
+            Element.createUser(mRS, Element.DataType.SIGNED_32), mFSM.mTriangleOffsets.length);
         mAllocOffsets.data(mFSM.mTriangleOffsets);
         mScriptStrip.bindAllocation(mAllocOffsets, 4);
 
         mAllocOffsetsTex = Allocation.createSized(mRS,
-            Element.USER_F32(mRS), mFSM.mTriangleOffsetsTex.length);
+            Element.createUser(mRS, Element.DataType.FLOAT_32), mFSM.mTriangleOffsetsTex.length);
         mAllocOffsetsTex.data(mFSM.mTriangleOffsetsTex);
         mScriptStrip.bindAllocation(mAllocOffsetsTex, 5);
 
diff --git a/libs/rs/java/Film/src/com/android/film/FilmView.java b/libs/rs/java/Film/src/com/android/film/FilmView.java
index 1c5b2bc..4a201fd 100644
--- a/libs/rs/java/Film/src/com/android/film/FilmView.java
+++ b/libs/rs/java/Film/src/com/android/film/FilmView.java
@@ -42,19 +42,29 @@
 
     public FilmView(Context context) {
         super(context);
-
         //setFocusable(true);
     }
 
     private RenderScript mRS;
     private FilmRS mRender;
 
+
     public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
         super.surfaceChanged(holder, format, w, h);
+        if (mRS == null) {
+            mRS = createRenderScript(true);
+            mRS.contextSetSurface(w, h, holder.getSurface());
+            mRender = new FilmRS();
+            mRender.init(mRS, getResources(), w, h);
+        }
+    }
 
-        mRS = createRenderScript(true);
-        mRender = new FilmRS();
-        mRender.init(mRS, getResources(), w, h);
+    @Override
+    protected void onDetachedFromWindow() {
+        if(mRS != null) {
+            mRS = null;
+            destroyRenderScript();
+        }
     }
 
     @Override
diff --git a/libs/rs/java/Fountain/res/raw/fountain.c b/libs/rs/java/Fountain/res/raw/fountain.c
index f218f9b..73b819b 100644
--- a/libs/rs/java/Fountain/res/raw/fountain.c
+++ b/libs/rs/java/Fountain/res/raw/fountain.c
@@ -14,19 +14,17 @@
         float rMax = ((float)rate) * 0.005f;
         int x = Control->x;
         int y = Control->y;
-        char r = Control->r * 255.f;
-        char g = Control->g * 255.f;
-        char b = Control->b * 255.f;
+        int color = ((int)(Control->r * 255.f)) |
+                    ((int)(Control->g * 255.f)) << 8 |
+                    ((int)(Control->b * 255.f)) << 16 |
+                    (0xf0 << 24);
         struct point_s * np = &p[newPart];
 
         while (rate--) {
-            vec2Rand((float *)np, rMax);
-            np->x = x;
-            np->y = y;
-            np->r = r;
-            np->g = g;
-            np->b = b;
-            np->a = 0xf0;
+            vec2Rand((float *)&np->delta.x, rMax);
+            np->position.x = x;
+            np->position.y = y;
+            np->color = color;
             newPart++;
             np++;
             if (newPart >= count) {
@@ -37,14 +35,14 @@
     }
 
     for (ct=0; ct < count; ct++) {
-        float dy = p->dy + 0.15f;
-        float posy = p->y + dy;
+        float dy = p->delta.y + 0.15f;
+        float posy = p->position.y + dy;
         if ((posy > height) && (dy > 0)) {
             dy *= -0.3f;
         }
-        p->dy = dy;
-        p->x += p->dx;
-        p->y = posy;
+        p->delta.y = dy;
+        p->position.x += p->delta.x;
+        p->position.y = posy;
         p++;
     }
 
diff --git a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java b/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
index f4f9b0c..71f95a7 100644
--- a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
+++ b/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
@@ -79,10 +79,9 @@
         mIntAlloc.data(mSD);
 
         Element.Builder eb = new Element.Builder(mRS);
-        eb.addFloat(Element.DataKind.USER, "dx");
-        eb.addFloat(Element.DataKind.USER, "dy");
-        eb.addFloatXY("");
-        eb.addUNorm8RGBA("");
+        eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 2), "delta");
+        eb.add(Element.createAttrib(mRS, Element.DataType.FLOAT_32, Element.DataKind.POSITION, 2), "position");
+        eb.add(Element.createAttrib(mRS, Element.DataType.UNSIGNED_8, Element.DataKind.COLOR, 4), "color");
         Element primElement = eb.create();
 
 
diff --git a/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java b/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java
index 1e7c5a2..fcb93f4 100644
--- a/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java
+++ b/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java
@@ -51,7 +51,7 @@
     public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
         super.surfaceChanged(holder, format, w, h);
         if (mRS == null) {
-            mRS = createRenderScript(false, true);
+            mRS = createRenderScript(false);
             mRS.contextSetSurface(w, h, holder.getSurface());
             mRender = new FountainRS();
             mRender.init(mRS, getResources(), w, h);
diff --git a/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java b/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
index 334fd9c..0ca00b3 100644
--- a/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
+++ b/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
@@ -62,7 +62,7 @@
 
         public float threshold;
     }
-    
+
     static class Pixel {
         public byte a;
         public byte r;
@@ -78,7 +78,7 @@
                         mParams.outWidth, mParams.outHeight);
                 mDisplayView.invalidate();
             }
-        };        
+        };
 
         @Override
         public void run() {
@@ -131,7 +131,7 @@
 
     public void surfaceDestroyed(SurfaceHolder holder) {
     }
-        
+
     private Script.Invokable createScript() {
         mRS = new RenderScript(false, false);
         mRS.mMessageCallback = new FilterCallback();
@@ -143,9 +143,11 @@
         final int pixelCount = mParams.inWidth * mParams.inHeight;
 
         mPixelType = Type.createFromClass(mRS, Pixel.class, 1, "Pixel");
-        mInPixelsAllocation = Allocation.createSized(mRS, Element.USER_I32(mRS),
+        mInPixelsAllocation = Allocation.createSized(mRS,
+                Element.createUser(mRS, Element.DataType.SIGNED_32),
                 pixelCount);
-        mOutPixelsAllocation = Allocation.createSized(mRS, Element.USER_I32(mRS),
+        mOutPixelsAllocation = Allocation.createSized(mRS,
+                Element.createUser(mRS, Element.DataType.SIGNED_32),
                 pixelCount);
 
         final int[] data = new int[pixelCount];
@@ -154,7 +156,7 @@
 
         mOutData = new int[pixelCount];
         mOutPixelsAllocation.data(mOutData);
-        
+
         ScriptC.Builder sb = new ScriptC.Builder(mRS);
         sb.setType(mParamsType, "Params", 0);
         sb.setType(mPixelType, "InPixel", 1);
diff --git a/libs/rs/java/Rollo/Android.mk b/libs/rs/java/Rollo/Android.mk
deleted file mode 100644
index 5a4957c..0000000
--- a/libs/rs/java/Rollo/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-#LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript
-
-LOCAL_PACKAGE_NAME := Rollo
-
-include $(BUILD_PACKAGE)
diff --git a/libs/rs/java/Rollo/AndroidManifest.xml b/libs/rs/java/Rollo/AndroidManifest.xml
deleted file mode 100644
index 12cb28f..0000000
--- a/libs/rs/java/Rollo/AndroidManifest.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.rollo">
-    <application
-        android:label="Rollo"
-        android:icon="@drawable/test_pattern">
-        <activity android:name="Rollo"
-                  android:theme="@android:style/Theme.Translucent"
-                  android:icon="@drawable/test_pattern">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
-    </application>
-</manifest>
diff --git a/libs/rs/java/Rollo/res/drawable/test_pattern.png b/libs/rs/java/Rollo/res/drawable/test_pattern.png
deleted file mode 100644
index e7d1455..0000000
--- a/libs/rs/java/Rollo/res/drawable/test_pattern.png
+++ /dev/null
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/browser.png b/libs/rs/java/Rollo/res/raw/browser.png
deleted file mode 100644
index 513f0be..0000000
--- a/libs/rs/java/Rollo/res/raw/browser.png
+++ /dev/null
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/calendar.png b/libs/rs/java/Rollo/res/raw/calendar.png
deleted file mode 100644
index 030ae73..0000000
--- a/libs/rs/java/Rollo/res/raw/calendar.png
+++ /dev/null
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/g1155.png b/libs/rs/java/Rollo/res/raw/g1155.png
deleted file mode 100644
index 68e1843..0000000
--- a/libs/rs/java/Rollo/res/raw/g1155.png
+++ /dev/null
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/g2140.png b/libs/rs/java/Rollo/res/raw/g2140.png
deleted file mode 100644
index 8c4e853..0000000
--- a/libs/rs/java/Rollo/res/raw/g2140.png
+++ /dev/null
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/maps.png b/libs/rs/java/Rollo/res/raw/maps.png
deleted file mode 100644
index fd5fc39..0000000
--- a/libs/rs/java/Rollo/res/raw/maps.png
+++ /dev/null
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/market.png b/libs/rs/java/Rollo/res/raw/market.png
deleted file mode 100644
index 83b6910..0000000
--- a/libs/rs/java/Rollo/res/raw/market.png
+++ /dev/null
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/path1920.png b/libs/rs/java/Rollo/res/raw/path1920.png
deleted file mode 100644
index 3510665..0000000
--- a/libs/rs/java/Rollo/res/raw/path1920.png
+++ /dev/null
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/path1927.png b/libs/rs/java/Rollo/res/raw/path1927.png
deleted file mode 100644
index fccc846..0000000
--- a/libs/rs/java/Rollo/res/raw/path1927.png
+++ /dev/null
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/path3099.png b/libs/rs/java/Rollo/res/raw/path3099.png
deleted file mode 100644
index 527ebf6..0000000
--- a/libs/rs/java/Rollo/res/raw/path3099.png
+++ /dev/null
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/path3950.png b/libs/rs/java/Rollo/res/raw/path3950.png
deleted file mode 100644
index 59a646a..0000000
--- a/libs/rs/java/Rollo/res/raw/path3950.png
+++ /dev/null
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/path431.png b/libs/rs/java/Rollo/res/raw/path431.png
deleted file mode 100644
index 5d2ed75..0000000
--- a/libs/rs/java/Rollo/res/raw/path431.png
+++ /dev/null
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/path4481.png b/libs/rs/java/Rollo/res/raw/path4481.png
deleted file mode 100644
index 78be0fc..0000000
--- a/libs/rs/java/Rollo/res/raw/path4481.png
+++ /dev/null
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/path5168.png b/libs/rs/java/Rollo/res/raw/path5168.png
deleted file mode 100644
index a7c3a19..0000000
--- a/libs/rs/java/Rollo/res/raw/path5168.png
+++ /dev/null
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/path676.png b/libs/rs/java/Rollo/res/raw/path676.png
deleted file mode 100644
index 2099690..0000000
--- a/libs/rs/java/Rollo/res/raw/path676.png
+++ /dev/null
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/path754.png b/libs/rs/java/Rollo/res/raw/path754.png
deleted file mode 100644
index 88aed5b..0000000
--- a/libs/rs/java/Rollo/res/raw/path754.png
+++ /dev/null
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/path815.png b/libs/rs/java/Rollo/res/raw/path815.png
deleted file mode 100644
index 407570f..0000000
--- a/libs/rs/java/Rollo/res/raw/path815.png
+++ /dev/null
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/photos.png b/libs/rs/java/Rollo/res/raw/photos.png
deleted file mode 100644
index 1ed8f1e..0000000
--- a/libs/rs/java/Rollo/res/raw/photos.png
+++ /dev/null
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/polygon2408.png b/libs/rs/java/Rollo/res/raw/polygon2408.png
deleted file mode 100644
index 4413954..0000000
--- a/libs/rs/java/Rollo/res/raw/polygon2408.png
+++ /dev/null
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/rollo.c b/libs/rs/java/Rollo/res/raw/rollo.c
deleted file mode 100644
index b31be81..0000000
--- a/libs/rs/java/Rollo/res/raw/rollo.c
+++ /dev/null
@@ -1,184 +0,0 @@
-#pragma version(1)
-#pragma stateVertex(PV)
-#pragma stateFragment(PF)
-#pragma stateStore(PFS)
-
-// Scratch buffer layout
-#define SCRATCH_FADE 0
-#define SCRATCH_ZOOM 1
-#define SCRATCH_ROT 2
-
-//#define STATE_POS_X             0
-#define STATE_DONE              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
-#define STATE_TOUCH             9
-
-
-float filter(float val, float target, float str)
-{
-    float delta = (target - val);
-    return val + delta * str;
-}
-
-int main(void* con, int ft, int launchID)
-{
-    int rowCount;
-    int row;
-    int col;
-    int imageID;
-    int done = loadI32(0, STATE_DONE);
-    int selectedID = loadI32(0, STATE_SELECTION);
-
-    float f = loadF(2, 0);
-
-    pfClearColor(0.0f, 0.0f, 0.0f, f);
-    if (done) {
-        if (f > 0.02f) {
-            //f = f - 0.02f;
-            //storeF(2, 0, f);
-        }
-    } else {
-        if (f < 0.8f) {
-            f = f + 0.02f;
-            storeF(2, 0, f);
-        }
-    }
-
-    float touchCut = 1.f;
-    if (loadI32(0, STATE_TOUCH)) {
-        touchCut = 4.f;
-    }
-
-
-    float targetZoom = ((float)loadI32(0, STATE_ZOOM)) / 1000.f;
-    float zoom = filter(loadF(2, SCRATCH_ZOOM), targetZoom, 0.15 * touchCut);
-    storeF(2, SCRATCH_ZOOM, zoom);
-
-    float targetRot = loadI32(0, STATE_FIRST_VISIBLE) / 180.0f * 3.14f;
-    targetRot = targetRot * 0.80f - .12f;
-    float drawRot = filter(loadF(2, SCRATCH_ROT), targetRot, 0.1f * touchCut);
-    storeF(2, SCRATCH_ROT, drawRot);
-
-    float diam = 8.f;
-    float scale = 1.0f / zoom;
-
-    // Bug makes 1.0f alpha fail.
-    color(1.0f, 1.0f, 1.0f, 0.99f);
-
-    float rot = drawRot * scale;
-    float rotStep = 16.0f / 180.0f * 3.14f * scale;
-    rowCount = 4;
-    int index = 0;
-    int iconCount = loadI32(0, STATE_COUNT);
-    while (iconCount) {
-        float tmpSin = sinf(rot);
-        float tmpCos = cosf(rot);
-            //debugF("rot", rot);
-
-        float tx1 = tmpSin * diam - (tmpCos * scale * 0.9f);
-        float tx2 = tx1 + (tmpCos * scale * 1.8f);
-        float tz1 = tmpCos * diam + (tmpSin * scale * 0.9f);
-        float tz2 = tz1 - (tmpSin * scale * 1.8f);
-
-        int y;
-        for (y = rowCount -1; (y >= 0) && iconCount; y--) {
-            float ty1 = ((y * 3.1f) - 5.f) * scale;
-            float ty2 = ty1 + scale * 1.8f;
-            bindTexture(NAMED_PF, 0, loadI32(1, index));
-            drawQuad(tx1, ty1, tz1,
-                     tx2, ty1, tz2,
-                     tx2, ty2, tz2,
-                     tx1, ty2, tz1);
-
-            iconCount--;
-            index++;
-        }
-        rot = rot + rotStep;
-    }
-
-    if ((zoom < 1.1f) && (zoom > 0.9f)) {
-        bindProgramVertex(NAMED_PVOrtho);
-        bindProgramFragment(NAMED_PFText);
-        bindProgramStore(NAMED_PFSText);
-
-        rot = drawRot * scale;
-        index = 0;
-        iconCount = loadI32(0, STATE_COUNT);
-        while (iconCount) {
-            int y;
-
-            float tx = 240.f + floorf(sinf(rot) * 430.f) - 64.f + 16.f;
-
-            float alpha = 2.4f - (fabsf(tx - 240.f + 48.f) / 76.f);
-            if (alpha > 0.99f) {
-                alpha = 0.99f;
-            }
-            alpha = alpha * (1.f - (fabsf(zoom - 1.f) * 10.f));
-
-            tx = tx + 0.25f;
-
-            for (y = rowCount -1; (y >= 0) && iconCount; y--) {
-
-                if (alpha > 0) {
-                    color(1.0f, 1.0f, 1.0f, alpha);
-
-                    float ty = 605.f - y * 150.f;
-
-                    ty = ty + 0.25f;
-
-                    bindTexture(NAMED_PFText, 0, loadI32(3, index));
-                    drawRect(tx, ty, tx + 128.f, ty + 32.f, 0.5f);
-                }
-                iconCount--;
-                index++;
-            }
-            rot = rot + rotStep;
-        }
-
-
-        bindProgramVertex(NAMED_PV);
-        bindProgramFragment(NAMED_PF);
-        bindProgramStore(NAMED_PFS);
-    }
-
-    // Draw the selected icon
-    color(1.0f, 1.0f, 1.0f, 0.9f);
-    rot = drawRot * scale;
-    index = 0;
-    iconCount = loadI32(0, STATE_COUNT);
-    while (iconCount) {
-        int y;
-        for (y = rowCount -1; (y >= 0) && iconCount; y--) {
-            if (index == selectedID) {
-
-                float tmpSin = sinf(rot) * scale;
-                float tmpCos = cosf(rot) * scale;
-                float tx1 = tmpSin * diam * 0.9f - tmpCos * 2.f;
-                float tx2 = tx1 + (tmpCos * 4.f);
-                float tz1 = tmpCos * diam * 0.9f + tmpSin * 2.f;
-                float tz2 = tz1 - (tmpSin * 4.f);
-
-                float ty1 = ((y * 3.1f) - 4.5f) * scale;
-                float ty2 = ty1 + scale * 4.f;
-                bindTexture(NAMED_PF, 0, loadI32(1, index));
-                drawQuad(tx1, ty1, tz1,
-                         tx2, ty1, tz2,
-                         tx2, ty2, tz2,
-                         tx1, ty2, tz1);
-            }
-            iconCount--;
-            index++;
-        }
-        rot = rot + rotStep;
-    }
-
-    return 1;
-}
-
-
diff --git a/libs/rs/java/Rollo/res/raw/rollo2.c b/libs/rs/java/Rollo/res/raw/rollo2.c
deleted file mode 100644
index 5b5cb2d..0000000
--- a/libs/rs/java/Rollo/res/raw/rollo2.c
+++ /dev/null
@@ -1,155 +0,0 @@
-#pragma version(1)
-#pragma stateVertex(PV)
-#pragma stateFragment(PF)
-#pragma stateStore(PFS)
-
-// Scratch buffer layout
-#define SCRATCH_FADE 0
-#define SCRATCH_ZOOM 1
-#define SCRATCH_ROT 2
-
-//#define STATE_POS_X             0
-#define STATE_DONE              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
-#define STATE_TOUCH             9
-
-float filter(float val, float target, float str)
-{
-    float delta = (target - val);
-    return val + delta * str;
-}
-
-
-int main(void* con, int ft, int launchID)
-{
-    int rowCount;
-    int imageID;
-    int done = loadI32(0, STATE_DONE);
-    int selectedID = loadI32(0, STATE_SELECTION);
-    int iconCount = loadI32(0, STATE_COUNT);
-
-    float f = loadF(2, 0);
-
-    float iconSize = 1.f;
-    float iconSpacing = 0.2f;
-    float z = 4.f;
-
-    pfClearColor(0.0f, 0.0f, 0.0f, f);
-    if (done) {
-    } else {
-        if (f < 0.8f) {
-            f = f + 0.02f;
-            storeF(2, 0, f);
-        }
-    }
-
-    float touchCut = 1.f;
-    if (loadI32(0, STATE_TOUCH)) {
-        touchCut = 5.f;
-    }
-
-
-    float targetZoom = ((float)loadI32(0, STATE_ZOOM)) / 1000.f;
-    float zoom = filter(loadF(2, SCRATCH_ZOOM), targetZoom, 0.15 * touchCut);
-    storeF(2, SCRATCH_ZOOM, zoom);
-
-    float targetPos = loadI32(0, STATE_FIRST_VISIBLE) / (-20.0f);
-    float pos = filter(loadF(2, SCRATCH_ROT), targetPos, 0.1f * touchCut);
-    storeF(2, SCRATCH_ROT, pos);
-    pos = pos - 1.f;
-
-    color(1.0f, 1.0f, 1.0f, 1.0f);
-
-
-    // Draw flat icons first
-    int index = ((int)pos) * 4;
-    int row;
-    int col;
-    float xoffset = -0.3f;
-    float gridSize = iconSize * 4.f + iconSpacing * 3.f;
-    float yoffset = (pos - ((int)pos));
-    for (row = 0; row < 4; row ++) {
-        float ty1 = (gridSize / 2.f) - ((float)row - yoffset) * (iconSize + iconSpacing) - iconSize;
-        float ty2 = ty1 + iconSize;
-
-        for (col = 0; (col < 4) && (index < iconCount); col ++) {
-            if (index >= 0) {
-                bindTexture(NAMED_PF, 0, loadI32(1, index));
-                float fcol = col;
-                float tx1 = xoffset + (-gridSize / 2.f) + (fcol * (iconSize + iconSpacing));
-                float tx2 = tx1 + iconSize;
-
-                drawQuad(tx1, ty1, z,
-                         tx2, ty1, z,
-                         tx2, ty2, z,
-                         tx1, ty2, z);
-            }
-            index++;
-        }
-    }
-
-    // bottom roller
-    {
-        float roll = (1.f - yoffset) * 0.5f * 3.14f;
-        float tmpSin = sinf(roll);
-        float tmpCos = cosf(roll);
-
-        for (col = 0; (col < 4) && (index < iconCount) && (index >= 0); col ++) {
-            float ty2 = (gridSize / 2.f) - ((float)row - yoffset) * (iconSize + iconSpacing);
-            float ty1 = ty2 - tmpCos * iconSize;
-
-            float tz1 = z + tmpSin * iconSize;
-            float tz2 = z;
-
-            float tx1 = xoffset + (-gridSize / 2.f) + ((float)col * (iconSize + iconSpacing));
-            float tx2 = tx1 + iconSize;
-
-            bindTexture(NAMED_PF, 0, loadI32(1, index));
-            drawQuad(tx1, ty1, tz1,
-                     tx2, ty1, tz1,
-                     tx2, ty2, tz2,
-                     tx1, ty2, tz2);
-            index++;
-        }
-    }
-
-    // Top roller
-    {
-        index = (((int)pos) * 4) - 4;
-        float roll = yoffset * 0.5f * 3.14f;
-        float tmpSin = sinf(roll);
-        float tmpCos = cosf(roll);
-
-        for (col = 0; (col < 4) && (index < iconCount) && (index >= 0); col ++) {
-            float ty1 = (gridSize / 2.f) - ((float)-1.f - yoffset) * (iconSize + iconSpacing) - iconSize;
-            float ty2 = ty1 + tmpCos * iconSize;
-
-            float tz1 = z;
-            float tz2 = z + tmpSin * iconSize;
-
-            float tx1 = xoffset + (-gridSize / 2.f) + ((float)col * (iconSize + iconSpacing));
-            float tx2 = tx1 + iconSize;
-
-            bindTexture(NAMED_PF, 0, loadI32(1, index));
-            drawQuad(tx1, ty1, tz1,
-                     tx2, ty1, tz1,
-                     tx2, ty2, tz2,
-                     tx1, ty2, tz2);
-            index++;
-        }
-    }
-
-
-
-
-    return 1;
-}
-
-
-
diff --git a/libs/rs/java/Rollo/res/raw/settings.png b/libs/rs/java/Rollo/res/raw/settings.png
deleted file mode 100644
index dd2cd95..0000000
--- a/libs/rs/java/Rollo/res/raw/settings.png
+++ /dev/null
Binary files differ
diff --git a/libs/rs/java/Rollo/src/com/android/rollo/Rollo.java b/libs/rs/java/Rollo/src/com/android/rollo/Rollo.java
deleted file mode 100644
index 400d801..0000000
--- a/libs/rs/java/Rollo/src/com/android/rollo/Rollo.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * 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.rollo;
-
-import android.renderscript.RSSurfaceView;
-import android.renderscript.RenderScript;
-
-import android.app.Activity;
-import android.content.res.Configuration;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.provider.Settings.System;
-import android.util.Config;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.Window;
-import android.widget.Button;
-import android.widget.ListView;
-
-import java.lang.Runtime;
-
-public class Rollo extends Activity {
-    //EventListener mListener = new EventListener();
-
-    private static final String LOG_TAG = "libRS_jni";
-    private static final boolean DEBUG  = false;
-    private static final boolean LOG_ENABLED = DEBUG ? Config.LOGD : Config.LOGV;
-
-    private RolloView mView;
-
-    // get the current looper (from your Activity UI thread for instance
-
-
-
-    @Override
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-
-        // Create our Preview view and set it as the content of our
-        // Activity
-        mView = new RolloView(this);
-        setContentView(mView);
-    }
-
-    @Override
-    protected void onResume() {
-        // Ideally a game should implement onResume() and onPause()
-        // to take appropriate action when the activity looses focus
-        super.onResume();
-        mView.onResume();
-    }
-
-    @Override
-    protected void onPause() {
-        // Ideally a game should implement onResume() and onPause()
-        // to take appropriate action when the activity looses focus
-        super.onPause();
-        mView.onPause();
-
-        Runtime.getRuntime().exit(0);
-    }
-
-
-    static void log(String message) {
-        if (LOG_ENABLED) {
-            Log.v(LOG_TAG, message);
-        }
-    }
-
-
-}
-
diff --git a/libs/rs/java/Rollo/src/com/android/rollo/RolloRS.java b/libs/rs/java/Rollo/src/com/android/rollo/RolloRS.java
deleted file mode 100644
index ff89bc3..0000000
--- a/libs/rs/java/Rollo/src/com/android/rollo/RolloRS.java
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * 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.rollo;
-
-import java.io.Writer;
-
-import android.renderscript.RenderScript;
-import android.renderscript.ProgramVertex;
-import android.renderscript.Element;
-import android.renderscript.Allocation;
-import android.renderscript.Script;
-import android.renderscript.ScriptC;
-import android.renderscript.ProgramFragment;
-import android.renderscript.ProgramStore;
-import android.renderscript.Sampler;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.graphics.Typeface;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.util.Log;
-
-public class RolloRS {
-    //public static final int STATE_SELECTED_ID = 0;
-    public static final int STATE_DONE = 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 static final int STATE_TOUCH = 9;
-
-
-    public RolloRS() {
-    }
-
-    public void init(RenderScript rs, Resources res, int width, int height) {
-        mRS = rs;
-        mRes = res;
-        mWidth = width;
-        mHeight = height;
-        initNamed();
-        initRS();
-    }
-
-    public void setPosition(float column) {
-        mAllocStateBuf[STATE_FIRST_VISIBLE] = (int)(column * (-20));
-        mAllocState.data(mAllocStateBuf);
-    }
-
-    public void setTouch(boolean touch) {
-        mAllocStateBuf[STATE_TOUCH] = touch ? 1 : 0;
-        mAllocState.data(mAllocStateBuf);
-    }
-
-    public void setZoom(float z) {
-        //Log.e("rs", "zoom " + Float.toString(z));
-
-        mAllocStateBuf[STATE_ZOOM] = (int)(z * 1000.f);
-        mAllocState.data(mAllocStateBuf);
-    }
-
-    public void setSelected(int index) {
-        //Log.e("rs",  "setSelected " + Integer.toString(index));
-
-        mAllocStateBuf[STATE_SELECTION] = index;
-        mAllocStateBuf[STATE_DONE] = 1;
-        mAllocState.data(mAllocStateBuf);
-    }
-
-    private int mWidth;
-    private int mHeight;
-
-    private Resources mRes;
-    private RenderScript mRS;
-    private Script mScript;
-    private Sampler mSampler;
-    private Sampler mSamplerText;
-    private ProgramStore mPSBackground;
-    private ProgramStore mPSText;
-    private ProgramFragment mPFImages;
-    private ProgramFragment mPFText;
-    private ProgramVertex mPV;
-    private ProgramVertex.MatrixAllocation mPVAlloc;
-    private ProgramVertex mPVOrtho;
-    private ProgramVertex.MatrixAllocation mPVOrthoAlloc;
-    private Allocation[] mIcons;
-    private Allocation[] mLabels;
-
-    private int[] mAllocStateBuf;
-    private Allocation mAllocState;
-
-    private int[] mAllocIconIDBuf;
-    private Allocation mAllocIconID;
-
-    private int[] mAllocLabelIDBuf;
-    private Allocation mAllocLabelID;
-
-    private int[] mAllocScratchBuf;
-    private Allocation mAllocScratch;
-
-    private void initNamed() {
-        Sampler.Builder sb = new Sampler.Builder(mRS);
-        sb.setMin(Sampler.Value.LINEAR);//_MIP_LINEAR);
-        sb.setMag(Sampler.Value.LINEAR);
-        sb.setWrapS(Sampler.Value.CLAMP);
-        sb.setWrapT(Sampler.Value.CLAMP);
-        mSampler = sb.create();
-
-        sb.setMin(Sampler.Value.NEAREST);
-        sb.setMag(Sampler.Value.NEAREST);
-        mSamplerText = sb.create();
-
-
-        ProgramFragment.Builder bf = new ProgramFragment.Builder(mRS, null, null);
-        bf.setTexEnable(true, 0);
-        bf.setTexEnvMode(ProgramFragment.EnvMode.MODULATE, 0);
-        mPFImages = bf.create();
-        mPFImages.setName("PF");
-        mPFImages.bindSampler(mSampler, 0);
-
-        bf.setTexEnvMode(ProgramFragment.EnvMode.MODULATE, 0);
-        mPFText = bf.create();
-        mPFText.setName("PFText");
-        mPFText.bindSampler(mSamplerText, 0);
-
-        ProgramStore.Builder bs = new ProgramStore.Builder(mRS, null, null);
-        bs.setDepthFunc(ProgramStore.DepthFunc.LESS);
-        bs.setDitherEnable(false);
-        bs.setDepthMask(true);
-        bs.setBlendFunc(ProgramStore.BlendSrcFunc.SRC_ALPHA,
-                        ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA);
-        mPSBackground = bs.create();
-        mPSBackground.setName("PFS");
-
-        bs.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
-        bs.setDepthMask(false);
-        bs.setBlendFunc(ProgramStore.BlendSrcFunc.SRC_ALPHA,
-                        ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA);
-        mPSText = bs.create();
-        mPSText.setName("PFSText");
-
-        mPVAlloc = new ProgramVertex.MatrixAllocation(mRS);
-        mPVAlloc.setupProjectionNormalized(mWidth, mHeight);
-
-        ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS, null, null);
-        mPV = pvb.create();
-        mPV.setName("PV");
-        mPV.bindAllocation(mPVAlloc);
-
-        mPVOrthoAlloc = new ProgramVertex.MatrixAllocation(mRS);
-        mPVOrthoAlloc.setupOrthoWindow(mWidth, mHeight);
-
-        pvb.setTextureMatrixEnable(true);
-        mPVOrtho = pvb.create();
-        mPVOrtho.setName("PVOrtho");
-        mPVOrtho.bindAllocation(mPVOrthoAlloc);
-
-        mRS.contextBindProgramVertex(mPV);
-
-        mAllocScratchBuf = new int[32];
-        mAllocScratch = Allocation.createSized(mRS,
-            Element.USER_I32(mRS), mAllocScratchBuf.length);
-        mAllocScratch.data(mAllocScratchBuf);
-
-        Log.e("rs", "Done loading named");
-
-
-
-        {
-            mIcons = new Allocation[29];
-            mAllocIconIDBuf = new int[mIcons.length];
-            mAllocIconID = Allocation.createSized(mRS,
-                Element.USER_I32(mRS), mAllocIconIDBuf.length);
-
-            mLabels = new Allocation[29];
-            mAllocLabelIDBuf = new int[mLabels.length];
-            mAllocLabelID = Allocation.createSized(mRS,
-                Element.USER_I32(mRS), mLabels.length);
-
-            Element ie8888 = Element.RGBA_8888(mRS);
-
-            mIcons[0] = Allocation.createFromBitmapResource(mRS, mRes, R.raw.browser, ie8888, true);
-            mIcons[1] = Allocation.createFromBitmapResource(mRS, mRes, R.raw.market, ie8888, true);
-            mIcons[2] = Allocation.createFromBitmapResource(mRS, mRes, R.raw.photos, ie8888, true);
-            mIcons[3] = Allocation.createFromBitmapResource(mRS, mRes, R.raw.settings, ie8888, true);
-            mIcons[4] = Allocation.createFromBitmapResource(mRS, mRes, R.raw.calendar, ie8888, true);
-            mIcons[5] = Allocation.createFromBitmapResource(mRS, mRes, R.raw.g1155, ie8888, true);
-            mIcons[6] = Allocation.createFromBitmapResource(mRS, mRes, R.raw.g2140, ie8888, true);
-            mIcons[7] = Allocation.createFromBitmapResource(mRS, mRes, R.raw.maps, ie8888, true);
-            mIcons[8] = Allocation.createFromBitmapResource(mRS, mRes, R.raw.path431, ie8888, true);
-            mIcons[9] = Allocation.createFromBitmapResource(mRS, mRes, R.raw.path676, ie8888, true);
-            mIcons[10] = Allocation.createFromBitmapResource(mRS, mRes, R.raw.path754, ie8888, true);
-            mIcons[11] = Allocation.createFromBitmapResource(mRS, mRes, R.raw.path815, ie8888, true);
-            mIcons[12] = Allocation.createFromBitmapResource(mRS, mRes, R.raw.path1920, ie8888, true);
-            mIcons[13] = Allocation.createFromBitmapResource(mRS, mRes, R.raw.path1927, ie8888, true);
-            mIcons[14] = Allocation.createFromBitmapResource(mRS, mRes, R.raw.path3099, ie8888, true);
-            mIcons[15] = Allocation.createFromBitmapResource(mRS, mRes, R.raw.path3950, ie8888, true);
-            mIcons[16] = Allocation.createFromBitmapResource(mRS, mRes, R.raw.path4481, ie8888, true);
-            mIcons[17] = Allocation.createFromBitmapResource(mRS, mRes, R.raw.path5168, ie8888, true);
-            mIcons[18] = Allocation.createFromBitmapResource(mRS, mRes, R.raw.polygon2408, ie8888, true);
-
-            mLabels[0] = makeTextBitmap("browser");
-            mLabels[1] = makeTextBitmap("market");
-            mLabels[2] = makeTextBitmap("photos");
-            mLabels[3] = makeTextBitmap("settings");
-            mLabels[4] = makeTextBitmap("calendar");
-            mLabels[5] = makeTextBitmap("g1155");
-            mLabels[6] = makeTextBitmap("g2140");
-            mLabels[7] = makeTextBitmap("maps");
-            mLabels[8] = makeTextBitmap("path431");
-            mLabels[9] = makeTextBitmap("path676");
-            mLabels[10] = makeTextBitmap("path754");
-            mLabels[11] = makeTextBitmap("path815");
-            mLabels[12] = makeTextBitmap("path1920");
-            mLabels[13] = makeTextBitmap("path1927");
-            mLabels[14] = makeTextBitmap("path3099");
-            mLabels[15] = makeTextBitmap("path3950");
-            mLabels[16] = makeTextBitmap("path4481");
-            mLabels[17] = makeTextBitmap("path5168");
-            mLabels[18] = makeTextBitmap("polygon2408");
-
-            mIcons[19] = mIcons[0];
-            mIcons[20] = mIcons[1];
-            mIcons[21] = mIcons[2];
-            mIcons[22] = mIcons[3];
-            mIcons[23] = mIcons[4];
-            mIcons[24] = mIcons[5];
-            mIcons[25] = mIcons[6];
-            mIcons[26] = mIcons[7];
-            mIcons[27] = mIcons[8];
-            mIcons[28] = mIcons[9];
-
-            mLabels[19] = mLabels[0];
-            mLabels[20] = mLabels[1];
-            mLabels[21] = mLabels[2];
-            mLabels[22] = mLabels[3];
-            mLabels[23] = mLabels[4];
-            mLabels[24] = mLabels[5];
-            mLabels[25] = mLabels[6];
-            mLabels[26] = mLabels[7];
-            mLabels[27] = mLabels[8];
-            mLabels[28] = mLabels[9];
-
-            for(int ct=0; ct < mIcons.length; ct++) {
-                mIcons[ct].uploadToTexture(0);
-                mLabels[ct].uploadToTexture(0);
-                mAllocIconIDBuf[ct] = mIcons[ct].getID();
-                mAllocLabelIDBuf[ct] = mLabels[ct].getID();
-            }
-            mAllocIconID.data(mAllocIconIDBuf);
-            mAllocLabelID.data(mAllocLabelIDBuf);
-        }
-
-    }
-
-    Allocation makeTextBitmap(String t) {
-        Bitmap b = Bitmap.createBitmap(128, 32, Bitmap.Config.ARGB_8888);
-        Canvas c = new Canvas(b);
-        Paint p = new Paint();
-        p.setTypeface(Typeface.DEFAULT_BOLD);
-        p.setTextSize(20);
-        p.setColor(0xffffffff);
-        c.drawText(t, 2, 26, p);
-        return Allocation.createFromBitmap(mRS, b, Element.RGBA_8888(mRS), true);
-    }
-
-
-    private void initRS() {
-        ScriptC.Builder sb = new ScriptC.Builder(mRS);
-        sb.setScript(mRes, R.raw.rollo);
-        //sb.setScript(mRes, R.raw.rollo2);
-        sb.setRoot(true);
-        mScript = sb.create();
-        mScript.setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-
-        mAllocStateBuf = new int[] {0, 0, 0, 8, 0, 0, -1, 0, mAllocIconIDBuf.length, 0, 0};
-        mAllocState = Allocation.createSized(mRS,
-            Element.USER_I32(mRS), mAllocStateBuf.length);
-        mScript.bindAllocation(mAllocState, 0);
-        mScript.bindAllocation(mAllocIconID, 1);
-        mScript.bindAllocation(mAllocScratch, 2);
-        mScript.bindAllocation(mAllocLabelID, 3);
-        setPosition(0);
-        setZoom(1);
-
-        //RenderScript.File f = mRS.fileOpen("/sdcard/test.a3d");
-
-        mRS.contextBindRootScript(mScript);
-    }
-}
-
-
diff --git a/libs/rs/java/Rollo/src/com/android/rollo/RolloView.java b/libs/rs/java/Rollo/src/com/android/rollo/RolloView.java
deleted file mode 100644
index 7524a0e..0000000
--- a/libs/rs/java/Rollo/src/com/android/rollo/RolloView.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * 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.rollo;
-
-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;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.os.Message;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.Surface;
-import android.view.SurfaceHolder;
-import android.view.SurfaceView;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.graphics.PixelFormat;
-
-
-public class RolloView extends RSSurfaceView {
-    public RolloView(Context context) {
-        super(context);
-        setFocusable(true);
-        getHolder().setFormat(PixelFormat.TRANSLUCENT);
-    }
-
-    private RenderScript mRS;
-    private RolloRS mRender;
-
-    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
-        super.surfaceChanged(holder, format, w, h);
-
-        mRS = createRenderScript(false);
-        mRender = new RolloRS();
-        mRender.init(mRS, getResources(), w, h);
-    }
-
-    @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event)
-    {
-        // break point at here
-        // this method doesn't work when 'extends View' include 'extends ScrollView'.
-        return super.onKeyDown(keyCode, event);
-    }
-
-    boolean mControlMode = false;
-    boolean mZoomMode = false;
-    boolean mFlingMode = false;
-    float mFlingX = 0;
-    float mFlingY = 0;
-    float mColumn = -1;
-    float mOldColumn;
-    float mZoom = 1;
-
-    int mIconCount = 29;
-    int mRows = 4;
-    int mColumns = (mIconCount + mRows - 1) / mRows;
-
-    float mMaxZoom = ((float)mColumns) / 3.f;
-
-
-    void setColumn(boolean clamp)
-    {
-        //Log.e("rs", " col = " + Float.toString(mColumn));
-        float c = mColumn;
-        if(c > (mColumns -2)) {
-            c = (mColumns -2);
-        }
-        if(c < 0) {
-            c = 0;
-        }
-        mRender.setPosition(c);
-        if(clamp) {
-            mColumn = c;
-        }
-    }
-
-    void computeSelection(float x, float y)
-    {
-        float col = mColumn + (x - 0.5f) * 4 + 1.25f;
-        int iCol = (int)(col + 0.25f);
-
-        float row = (y / 0.8f) * mRows;
-        int iRow = (int)(row - 0.5f);
-
-        mRender.setSelected(iCol * mRows + iRow);
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent ev)
-    {
-        boolean ret = true;
-        int act = ev.getAction();
-        if (act == ev.ACTION_UP) {
-            ret = false;
-        }
-
-        float nx = ev.getX() / getWidth();
-        float ny = ev.getY() / getHeight();
-
-        //Log.e("rs", "width=" + Float.toString(getWidth()));
-        //Log.e("rs", "height=" + Float.toString(getHeight()));
-
-        mRender.setTouch(ret);
-
-        if((ny > 0.85f) || mControlMode) {
-            mFlingMode = false;
-
-            // Projector control
-            if((nx > 0.2f) && (nx < 0.8f) || mControlMode) {
-                if(act != ev.ACTION_UP) {
-                    float zoom = mMaxZoom;
-                    if(mControlMode) {
-                        if(!mZoomMode) {
-                            zoom = 1.f;
-                        }
-                        float dx = nx - mFlingX;
-
-                        if((ny < 0.9) && mZoomMode) {
-                            zoom = mMaxZoom - ((0.9f - ny) * 10.f);
-                            if(zoom < 1) {
-                                zoom = 1;
-                                mZoomMode = false;
-                            }
-                            mOldColumn = mColumn;
-                        }
-                        mColumn += dx * 4;// * zoom;
-                        if(zoom > 1.01f) {
-                            mColumn += (mZoom - zoom) * (nx - 0.5f) * 4 * zoom;
-                        }
-                    } else {
-                        mOldColumn = mColumn;
-                        mColumn = ((float)mColumns) / 2;
-                        mControlMode = true;
-                        mZoomMode = true;
-                    }
-                    mZoom = zoom;
-                    mFlingX = nx;
-                    mRender.setZoom(zoom);
-                    if(mZoom < 1.01f) {
-                        computeSelection(nx, ny);
-                    }
-                } else {
-                    mControlMode = false;
-                    mColumn = mOldColumn;
-                    mRender.setZoom(1.f);
-                    mRender.setSelected(-1);
-                }
-            } else {
-                // Do something with corners here....
-            }
-            setColumn(true);
-
-        } else {
-            // icon control
-            if(act != ev.ACTION_UP) {
-                if(mFlingMode) {
-                    mColumn += (mFlingX - nx) * 4;
-                    setColumn(true);
-                }
-                mFlingMode = true;
-                mFlingX = nx;
-                mFlingY = ny;
-            } else {
-                mFlingMode = false;
-                mColumn = (float)(java.lang.Math.floor(mColumn * 0.25f + 0.3f) * 4.f) + 1.f;
-                setColumn(true);
-            }
-        }
-
-
-        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/rs.spec b/libs/rs/rs.spec
index a4e72d9..ac115d3 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -20,16 +20,6 @@
 	param RsProgramRaster pgm
 	}
 
-ContextSetDefineF {
-    param const char* name
-    param float value
-    }
-
-ContextSetDefineI32 {
-    param const char* name
-    param int32_t value
-    }
-
 ContextPause {
 	}
 
@@ -60,18 +50,19 @@
 	param void *obj
 	}
 
-ElementBegin {
-}
-
-ElementAdd {
-	param RsDataKind dataKind
-	param RsDataType dataType
-	param bool isNormalized
-	param size_t bits
-	param const char * name
+ElementCreate {
+	param RsDataType mType
+	param RsDataKind mKind
+	param bool mNormalized
+	param uint32_t mVectorSize
+	ret RsElement
 	}
 
-ElementCreate {
+ElementCreate2 {
+	param size_t count
+	param const RsElement * elements
+	param const char ** names
+	param const size_t * nameLengths
 	ret RsElement
 	}
 
@@ -366,56 +357,50 @@
 }
 
 
-ProgramFragmentBegin {
-	param RsElement in
-	param RsElement out
-	param bool pointSpriteEnable
+ProgramBindConstants {
+	param RsProgram vp
+	param uint32_t slot
+	param RsAllocation constants
 	}
 
-ProgramFragmentBindTexture {
+
+ProgramBindTexture {
 	param RsProgramFragment pf
 	param uint32_t slot
 	param RsAllocation a
 	}
 
-ProgramFragmentBindSampler {
+ProgramBindSampler {
 	param RsProgramFragment pf
 	param uint32_t slot
 	param RsSampler s
 	}
 
-ProgramFragmentSetSlot {
-	param uint32_t slot
-	param bool enable
-	param RsTexEnvMode env
-	param RsType t
-	}
-
 ProgramFragmentCreate {
+	param const uint32_t * params
+	param uint32_t paramLength
 	ret RsProgramFragment
 	}
 
-
-ProgramVertexBegin {
-	param RsElement in
-	param RsElement out
+ProgramFragmentCreate2 {
+	param const char * shaderText
+	param uint32_t shaderLength
+	param const uint32_t * params
+	param uint32_t paramLength
+	ret RsProgramFragment
 	}
 
 ProgramVertexCreate {
+	param bool texMat
 	ret RsProgramVertex
 	}
 
-ProgramVertexBindAllocation {
-	param RsProgramVertex vpgm
-	param RsAllocation constants
-	}
-
-ProgramVertexSetTextureMatrixEnable {
-	param bool enable
-	}
-
-ProgramVertexAddLight {
-	param RsLight light
+ProgramVertexCreate2 {
+	param const char * shaderText
+	param uint32_t shaderLength
+	param const uint32_t * params
+	param uint32_t paramLength
+	ret RsProgramVertex
 	}
 
 LightBegin {
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index ff8d29f..eb6c503 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -38,9 +38,9 @@
 
     mIsTexture = false;
     mTextureID = 0;
-
     mIsVertexBuffer = false;
     mBufferID = 0;
+    mUploadDefered = false;
 
     mType.set(type);
     rsAssert(type);
@@ -88,13 +88,26 @@
     return false;
 }
 
-void Allocation::uploadToTexture(Context *rsc, uint32_t lodOffset)
+void Allocation::deferedUploadToTexture(const Context *rsc, uint32_t lodOffset)
+{
+    rsAssert(lodOffset < mType->getLODCount());
+    mIsTexture = true;
+    mTextureLOD = lodOffset;
+    mUploadDefered = true;
+}
+
+void Allocation::uploadToTexture(const Context *rsc)
 {
     //rsAssert(!mTextureId);
-    rsAssert(lodOffset < mType->getLODCount());
 
-    GLenum type = mType->getElement()->getGLType();
-    GLenum format = mType->getElement()->getGLFormat();
+    mIsTexture = true;
+    if (!rsc->checkDriver()) {
+        mUploadDefered = true;
+        return;
+    }
+
+    GLenum type = mType->getElement()->getComponent().getGLType();
+    GLenum format = mType->getElement()->getComponent().getGLFormat();
 
     if (!type || !format) {
         return;
@@ -109,15 +122,16 @@
             // Force a crash to 1: restart the app, 2: make sure we get a bugreport.
             LOGE("Upload to texture failed to gen mTextureID");
             rsc->dumpDebug();
-            ((char *)0)[0] = 0;
+            mUploadDefered = true;
+            return;
         }
     }
     glBindTexture(GL_TEXTURE_2D, mTextureID);
     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 
     Adapter2D adapt(getContext(), this);
-    for(uint32_t lod = 0; (lod + lodOffset) < mType->getLODCount(); lod++) {
-        adapt.setLOD(lod+lodOffset);
+    for(uint32_t lod = 0; (lod + mTextureLOD) < mType->getLODCount(); lod++) {
+        adapt.setLOD(lod+mTextureLOD);
 
         uint16_t * ptr = static_cast<uint16_t *>(adapt.getElement(0,0));
         glTexImage2D(GL_TEXTURE_2D, lod, format,
@@ -126,19 +140,50 @@
     }
 }
 
-void Allocation::uploadToBufferObject()
+void Allocation::deferedUploadToBufferObject(const Context *rsc)
+{
+    mIsVertexBuffer = true;
+    mUploadDefered = true;
+}
+
+void Allocation::uploadToBufferObject(const Context *rsc)
 {
     rsAssert(!mType->getDimY());
     rsAssert(!mType->getDimZ());
 
+    mIsVertexBuffer = true;
+    if (!rsc->checkDriver()) {
+        mUploadDefered = true;
+        return;
+    }
+
     if (!mBufferID) {
         glGenBuffers(1, &mBufferID);
     }
+    if (!mBufferID) {
+        LOGE("Upload to buffer object failed");
+        mUploadDefered = true;
+        return;
+    }
+
     glBindBuffer(GL_ARRAY_BUFFER, mBufferID);
     glBufferData(GL_ARRAY_BUFFER, mType->getSizeBytes(), getPtr(), GL_DYNAMIC_DRAW);
     glBindBuffer(GL_ARRAY_BUFFER, 0);
 }
 
+void Allocation::uploadCheck(const Context *rsc)
+{
+    if (mUploadDefered) {
+        mUploadDefered = false;
+        if (mIsVertexBuffer) {
+            uploadToBufferObject(rsc);
+        }
+        if (mIsTexture) {
+            uploadToTexture(rsc);
+        }
+    }
+}
+
 
 void Allocation::data(const void *data, uint32_t sizeBytes)
 {
@@ -148,6 +193,8 @@
         return;
     }
     memcpy(mPtr, data, size);
+    sendDirty();
+    mUploadDefered = true;
 }
 
 void Allocation::read(void *data)
@@ -168,6 +215,8 @@
         return;
     }
     memcpy(ptr, data, size);
+    sendDirty();
+    mUploadDefered = true;
 }
 
 void Allocation::subData(uint32_t xoff, uint32_t yoff,
@@ -192,6 +241,8 @@
         src += lineSize;
         dst += destW * eSize;
     }
+    sendDirty();
+    mUploadDefered = true;
 }
 
 void Allocation::subData(uint32_t xoff, uint32_t yoff, uint32_t zoff,
@@ -214,10 +265,30 @@
 
     LOGV("%s allocation mIsTexture=%i mTextureID=%i, mIsVertexBuffer=%i, mBufferID=%i",
           prefix, mIsTexture, mTextureID, mIsVertexBuffer, mBufferID);
-
-
 }
 
+void Allocation::addProgramToDirty(const Program *p)
+{
+    mToDirtyList.add(p);
+}
+
+void Allocation::removeProgramToDirty(const Program *p)
+{
+    for (size_t ct=0; ct < mToDirtyList.size(); ct++) {
+        if (mToDirtyList[ct] == p) {
+            mToDirtyList.removeAt(ct);
+            return;
+        }
+    }
+    rsAssert(0);
+}
+
+void Allocation::sendDirty() const
+{
+    for (size_t ct=0; ct < mToDirtyList.size(); ct++) {
+        mToDirtyList[ct]->forceDirty();
+    }
+}
 
 /////////////////
 //
@@ -247,13 +318,13 @@
 void rsi_AllocationUploadToTexture(Context *rsc, RsAllocation va, uint32_t baseMipLevel)
 {
     Allocation *alloc = static_cast<Allocation *>(va);
-    alloc->uploadToTexture(rsc, baseMipLevel);
+    alloc->deferedUploadToTexture(rsc, baseMipLevel);
 }
 
 void rsi_AllocationUploadToBufferObject(Context *rsc, RsAllocation va)
 {
     Allocation *alloc = static_cast<Allocation *>(va);
-    alloc->uploadToBufferObject();
+    alloc->deferedUploadToBufferObject(rsc);
 }
 
 static void mip565(const Adapter2D &out, const Adapter2D &in)
@@ -294,6 +365,25 @@
     }
 }
 
+static void mip8(const Adapter2D &out, const Adapter2D &in)
+{
+    uint32_t w = out.getDimX();
+    uint32_t h = out.getDimY();
+
+    for (uint32_t y=0; y < h; y++) {
+        uint8_t *oPtr = static_cast<uint8_t *>(out.getElement(0, y));
+        const uint8_t *i1 = static_cast<uint8_t *>(in.getElement(0, y*2));
+        const uint8_t *i2 = static_cast<uint8_t *>(in.getElement(0, y*2+1));
+
+        for (uint32_t x=0; x < w; x++) {
+            *oPtr = (uint8_t)(((uint32_t)i1[0] + i1[1] + i2[0] + i2[1]) * 0.25f);
+            oPtr ++;
+            i1 += 2;
+            i2 += 2;
+        }
+    }
+}
+
 static void mip(const Adapter2D &out, const Adapter2D &in)
 {
     switch(out.getBaseType()->getElement()->getSizeBits()) {
@@ -303,6 +393,9 @@
     case 16:
         mip565(out, in);
         break;
+    case 8:
+        mip8(out, in);
+        break;
 
     }
 
@@ -350,10 +443,10 @@
 
 static ElementConverter_t pickConverter(const Element *dst, const Element *src)
 {
-    GLenum srcGLType = src->getGLType();
-    GLenum srcGLFmt = src->getGLFormat();
-    GLenum dstGLType = dst->getGLType();
-    GLenum dstGLFmt = dst->getGLFormat();
+    GLenum srcGLType = src->getComponent().getGLType();
+    GLenum srcGLFmt = src->getComponent().getGLFormat();
+    GLenum dstGLType = dst->getComponent().getGLType();
+    GLenum dstGLFmt = dst->getComponent().getGLFormat();
 
     if (srcGLFmt == dstGLFmt && srcGLType == dstGLType) {
         switch(dst->getSizeBytes()) {
@@ -391,8 +484,9 @@
 {
     const Element *src = static_cast<const Element *>(_src);
     const Element *dst = static_cast<const Element *>(_dst);
-    rsAssert(!(w & (w-1)));
-    rsAssert(!(h & (h-1)));
+
+    // Check for pow2 on pre es 2.0 versions.
+    rsAssert(rsc->checkVersion2_0() || (!(w & (w-1)) && !(h & (h-1))));
 
     //LOGE("rsi_AllocationCreateFromBitmap %i %i %i %i %i", w, h, dstFmt, srcFmt, genMips);
     rsi_TypeBegin(rsc, _dst);
@@ -452,31 +546,24 @@
     RsAllocation ret = rsi_AllocationCreateFromBitmap(rsc, w2, h2, _dst, _src, genMips, tmp);
     free(tmp);
     return ret;
-
-
-
-
 }
 
 void rsi_AllocationData(Context *rsc, RsAllocation va, const void *data, uint32_t sizeBytes)
 {
     Allocation *a = static_cast<Allocation *>(va);
     a->data(data, sizeBytes);
-    rsc->allocationCheck(a);
 }
 
 void rsi_Allocation1DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t count, const void *data, uint32_t sizeBytes)
 {
     Allocation *a = static_cast<Allocation *>(va);
     a->subData(xoff, count, data, sizeBytes);
-    rsc->allocationCheck(a);
 }
 
 void rsi_Allocation2DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes)
 {
     Allocation *a = static_cast<Allocation *>(va);
     a->subData(xoff, yoff, w, h, data, sizeBytes);
-    rsc->allocationCheck(a);
 }
 
 void rsi_AllocationRead(Context *rsc, RsAllocation va, void *data)
diff --git a/libs/rs/rsAllocation.h b/libs/rs/rsAllocation.h
index f54284a..f0b2122 100644
--- a/libs/rs/rsAllocation.h
+++ b/libs/rs/rsAllocation.h
@@ -23,7 +23,7 @@
 namespace android {
 namespace renderscript {
 
-
+class Program;
 
 class Allocation : public ObjectBase
 {
@@ -46,10 +46,12 @@
     void * getPtr() const {return mPtr;}
     const Type * getType() const {return mType.get();}
 
-    void uploadToTexture(Context *rsc, uint32_t lodOffset = 0);
+    void deferedUploadToTexture(const Context *rsc, uint32_t lodOffset);
+    void uploadToTexture(const Context *rsc);
     uint32_t getTextureID() const {return mTextureID;}
 
-    void uploadToBufferObject();
+    void deferedUploadToBufferObject(const Context *rsc);
+    void uploadToBufferObject(const Context *rsc);
     uint32_t getBufferObjectID() const {return mBufferID;}
 
 
@@ -65,13 +67,21 @@
     void enableGLVertexBuffers() const;
     void setupGLIndexBuffers() const;
 
+    void addProgramToDirty(const Program *);
+    void removeProgramToDirty(const Program *);
+
     virtual void dumpLOGV(const char *prefix) const;
 
+    virtual void uploadCheck(const Context *rsc);
 
 protected:
+    void sendDirty() const;
+
     ObjectBaseRef<const Type> mType;
     void * mPtr;
 
+    Vector<const Program *> mToDirtyList;
+
     // Usage restrictions
     bool mCpuWrite;
     bool mCpuRead;
@@ -88,6 +98,7 @@
     // Is this a legal structure to be used as a texture source.
     // Initially this will require 1D or 2D and color data
     bool mIsTexture;
+    uint32_t mTextureLOD;
     uint32_t mTextureID;
 
     // Is this a legal structure to be used as a vertex source.
@@ -95,6 +106,8 @@
     // is allowed.
     bool mIsVertexBuffer;
     uint32_t mBufferID;
+
+    bool mUploadDefered;
 };
 
 }
diff --git a/libs/rs/rsComponent.cpp b/libs/rs/rsComponent.cpp
index de074c8..15a56f7 100644
--- a/libs/rs/rsComponent.cpp
+++ b/libs/rs/rsComponent.cpp
@@ -15,96 +15,323 @@
  */
 
 #include "rsComponent.h"
+
 #include <GLES/gl.h>
 
 using namespace android;
 using namespace android::renderscript;
 
-
-Component::Component(Context *rsc) : ObjectBase(rsc)
+Component::Component()
 {
-    mAllocFile = __FILE__;
-    mAllocLine = __LINE__;
-    mType = FLOAT;
-    mKind = USER;
-    mIsNormalized = false;
-    mBits = 0;
-}
-
-Component::Component(Context *rsc,
-    DataKind dk, DataType dt,
-    bool isNormalized, uint32_t bits, const char * name) : ObjectBase(rsc)
-{
-    mAllocFile = __FILE__;
-    mAllocLine = __LINE__;
-    mType = dt;
-    mKind = dk;
-    mIsNormalized = isNormalized;
-    mBits = bits;
-    if (name) {
-        mName = name;
-    }
-}
-
-const char * Component::getCType() const
-{
-    switch(mType) {
-    case FLOAT:
-        return "float";
-    case SIGNED:
-    case UNSIGNED:
-        switch(mBits) {
-        case 32:
-            return "int";
-        case 16:
-            return "short";
-        case 8:
-            return "char";
-        }
-        break;
-    }
-    return NULL;
+    set(RS_TYPE_NONE, RS_KIND_USER, false, 1);
 }
 
 Component::~Component()
 {
 }
 
-uint32_t Component::getGLType() const
+void Component::set(RsDataType dt, RsDataKind dk, bool norm, uint32_t vecSize)
 {
-    switch(mType) {
-    case RS_TYPE_FLOAT:
-        rsAssert(mBits == 32);
-        return GL_FLOAT;
-    case RS_TYPE_SIGNED:
-        switch(mBits) {
-        case 32:
-            return 0;//GL_INT;
-        case 16:
-            return GL_SHORT;
-        case 8:
-            return GL_BYTE;
-        }
+    mType = dt;
+    mKind = dk;
+    mNormalized = norm;
+    mVectorSize = vecSize;
+    rsAssert(vecSize <= 4);
+
+    mBits = 0;
+    mTypeBits = 0;
+    mIsFloat = false;
+    mIsSigned = false;
+    mIsPixel = false;
+
+    switch(mKind) {
+    case RS_KIND_PIXEL_L:
+    case RS_KIND_PIXEL_A:
+        mIsPixel = true;
+        rsAssert(mVectorSize == 1);
+        rsAssert(mNormalized == true);
         break;
-    case RS_TYPE_UNSIGNED:
-        switch(mBits) {
-        case 32:
-            return 0;//GL_UNSIGNED_INT;
-        case 16:
-            return GL_UNSIGNED_SHORT;
-        case 8:
-            return GL_UNSIGNED_BYTE;
-        }
+    case RS_KIND_PIXEL_LA:
+        mIsPixel = true;
+        rsAssert(mVectorSize == 2);
+        rsAssert(mNormalized == true);
+        break;
+    case RS_KIND_PIXEL_RGB:
+        mIsPixel = true;
+        rsAssert(mVectorSize == 3);
+        rsAssert(mNormalized == true);
+        break;
+    case RS_KIND_PIXEL_RGBA:
+        mIsPixel = true;
+        rsAssert(mVectorSize == 4);
+        rsAssert(mNormalized == true);
+        break;
+    default:
         break;
     }
-    //rsAssert(!"Bad type");
-    //LOGE("mType %i, mKind %i, mBits %i, mIsNormalized %i", mType, mKind, mBits, mIsNormalized);
+
+    switch(mType) {
+    case RS_TYPE_NONE:
+        return;
+    case RS_TYPE_UNSIGNED_5_6_5:
+        mVectorSize = 3;
+        mBits = 16;
+        mNormalized = true;
+        rsAssert(mKind == RS_KIND_PIXEL_RGB);
+        return;
+    case RS_TYPE_UNSIGNED_5_5_5_1:
+        mVectorSize = 4;
+        mBits = 16;
+        mNormalized = true;
+        rsAssert(mKind == RS_KIND_PIXEL_RGBA);
+        return;
+    case RS_TYPE_UNSIGNED_4_4_4_4:
+        mVectorSize = 4;
+        mBits = 16;
+        mNormalized = true;
+        rsAssert(mKind == RS_KIND_PIXEL_RGBA);
+        return;
+    case RS_TYPE_ELEMENT:
+    case RS_TYPE_TYPE:
+    case RS_TYPE_ALLOCATION:
+    case RS_TYPE_SAMPLER:
+    case RS_TYPE_SCRIPT:
+    case RS_TYPE_MESH:
+    case RS_TYPE_PROGRAM_FRAGMENT:
+    case RS_TYPE_PROGRAM_VERTEX:
+    case RS_TYPE_PROGRAM_RASTER:
+    case RS_TYPE_PROGRAM_STORE:
+        rsAssert(mVectorSize == 1);
+        rsAssert(mNormalized == false);
+        rsAssert(mKind == RS_KIND_USER);
+        mBits = 32;
+        mTypeBits = 32;
+        return;
+
+    case RS_TYPE_FLOAT_16:
+        mTypeBits = 16;
+        mIsFloat = true;
+        break;
+    case RS_TYPE_FLOAT_32:
+        mTypeBits = 32;
+        mIsFloat = true;
+        break;
+    case RS_TYPE_FLOAT_64:
+        mTypeBits = 64;
+        mIsFloat = true;
+        break;
+    case RS_TYPE_SIGNED_8:
+        mTypeBits = 8;
+        mIsSigned = true;
+        break;
+    case RS_TYPE_SIGNED_16:
+        mTypeBits = 16;
+        mIsSigned = true;
+        break;
+    case RS_TYPE_SIGNED_32:
+        mTypeBits = 32;
+        mIsSigned = true;
+        break;
+    case RS_TYPE_SIGNED_64:
+        mTypeBits = 64;
+        mIsSigned = true;
+        break;
+    case RS_TYPE_UNSIGNED_8:
+        mTypeBits = 8;
+        break;
+    case RS_TYPE_UNSIGNED_16:
+        mTypeBits = 16;
+        break;
+    case RS_TYPE_UNSIGNED_32:
+        mTypeBits = 32;
+        break;
+    case RS_TYPE_UNSIGNED_64:
+        mTypeBits = 64;
+        break;
+    }
+
+    mBits = mTypeBits * mVectorSize;
+}
+
+
+
+
+uint32_t Component::getGLType() const
+{
+    switch (mType) {
+    case RS_TYPE_UNSIGNED_5_6_5:    return GL_UNSIGNED_SHORT_5_6_5;
+    case RS_TYPE_UNSIGNED_5_5_5_1:  return GL_UNSIGNED_SHORT_5_5_5_1;
+    case RS_TYPE_UNSIGNED_4_4_4_4:  return GL_UNSIGNED_SHORT_4_4_4_4;
+
+    //case RS_TYPE_FLOAT_16:      return GL_HALF_FLOAT;
+    case RS_TYPE_FLOAT_32:      return GL_FLOAT;
+    case RS_TYPE_UNSIGNED_8:    return GL_UNSIGNED_BYTE;
+    case RS_TYPE_UNSIGNED_16:   return GL_UNSIGNED_SHORT;
+    case RS_TYPE_SIGNED_8:      return GL_BYTE;
+    case RS_TYPE_SIGNED_16:     return GL_SHORT;
+    default:    break;
+    }
+
     return 0;
 }
 
+uint32_t Component::getGLFormat() const
+{
+    switch (mKind) {
+    case RS_KIND_PIXEL_L: return GL_LUMINANCE;
+    case RS_KIND_PIXEL_A: return GL_ALPHA;
+    case RS_KIND_PIXEL_LA: return GL_LUMINANCE_ALPHA;
+    case RS_KIND_PIXEL_RGB: return GL_RGB;
+    case RS_KIND_PIXEL_RGBA: return GL_RGBA;
+    default: break;
+    }
+    return 0;
+}
+
+static const char * gCTypeStrings[] = {
+    0,
+    0,//"F16",
+    "float",
+    "double",
+    "char",
+    "short",
+    "int",
+    0,//"S64",
+    "char",//U8",
+    "short",//U16",
+    "int",//U32",
+    0,//"U64",
+    0,//"UP_565",
+    0,//"UP_5551",
+    0,//"UP_4444",
+    0,//"ELEMENT",
+    0,//"TYPE",
+    0,//"ALLOCATION",
+    0,//"SAMPLER",
+    0,//"SCRIPT",
+    0,//"MESH",
+    0,//"PROGRAM_FRAGMENT",
+    0,//"PROGRAM_VERTEX",
+    0,//"PROGRAM_RASTER",
+    0,//"PROGRAM_STORE",
+};
+
+static const char * gCVecTypeStrings[] = {
+    0,
+    0,//"F16",
+    "vecF32",
+    "vecF64",
+    "vecI8",
+    "vecI16",
+    "vecI32",
+    0,//"S64",
+    "vecU8",//U8",
+    "vecU16",//U16",
+    "vecU32",//U32",
+    0,//"U64",
+    0,//"UP_565",
+    0,//"UP_5551",
+    0,//"UP_4444",
+    0,//"ELEMENT",
+    0,//"TYPE",
+    0,//"ALLOCATION",
+    0,//"SAMPLER",
+    0,//"SCRIPT",
+    0,//"MESH",
+    0,//"PROGRAM_FRAGMENT",
+    0,//"PROGRAM_VERTEX",
+    0,//"PROGRAM_RASTER",
+    0,//"PROGRAM_STORE",
+};
+
+String8 Component::getCType() const
+{
+    char buf[64];
+    if (mVectorSize == 1) {
+        return String8(gCTypeStrings[mType]);
+    }
+
+    // Yuck, acc WAR
+    // Appears to have problems packing chars
+    if (mVectorSize == 4 && mType == RS_TYPE_UNSIGNED_8) {
+        return String8("int");
+    }
+
+
+    String8 s(gCVecTypeStrings[mType]);
+    sprintf(buf, "_%i_t", mVectorSize);
+    s.append(buf);
+    return s;
+}
+
+String8 Component::getGLSLType() const
+{
+    if (mType == RS_TYPE_SIGNED_32) {
+        switch(mVectorSize) {
+        case 1: return String8("int");
+        case 2: return String8("ivec2");
+        case 3: return String8("ivec3");
+        case 4: return String8("ivec4");
+        }
+    }
+    if (mType == RS_TYPE_FLOAT_32) {
+        switch(mVectorSize) {
+        case 1: return String8("float");
+        case 2: return String8("vec2");
+        case 3: return String8("vec3");
+        case 4: return String8("vec4");
+        }
+    }
+    return String8();
+}
+
+static const char * gTypeStrings[] = {
+    "NONE",
+    "F16",
+    "F32",
+    "F64",
+    "S8",
+    "S16",
+    "S32",
+    "S64",
+    "U8",
+    "U16",
+    "U32",
+    "U64",
+    "UP_565",
+    "UP_5551",
+    "UP_4444",
+    "ELEMENT",
+    "TYPE",
+    "ALLOCATION",
+    "SAMPLER",
+    "SCRIPT",
+    "MESH",
+    "PROGRAM_FRAGMENT",
+    "PROGRAM_VERTEX",
+    "PROGRAM_RASTER",
+    "PROGRAM_STORE",
+};
+
+static const char * gKindStrings[] = {
+    "USER",
+    "COLOR",
+    "POSITION",
+    "TEXTURE",
+    "NORMAL",
+    "INDEX",
+    "POINT_SIZE",
+    "PIXEL_L",
+    "PIXEL_A",
+    "PIXEL_LA",
+    "PIXEL_RGB",
+    "PIXEL_RGBA",
+};
+
 void Component::dumpLOGV(const char *prefix) const
 {
-    ObjectBase::dumpLOGV(prefix);
-    LOGV("%s   component: %i %i %i %i", prefix, mType, mKind, mIsNormalized, mBits);
+    LOGV("%s   Component: %s, %s, vectorSize=%i, bits=%i",
+         prefix, gTypeStrings[mType], gKindStrings[mKind], mVectorSize, mBits);
 }
 
+
diff --git a/libs/rs/rsComponent.h b/libs/rs/rsComponent.h
index 5366cc4..71de324 100644
--- a/libs/rs/rsComponent.h
+++ b/libs/rs/rsComponent.h
@@ -14,65 +14,56 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_RS_STRUCTURED_COMPONENT_H
-#define ANDROID_RS_STRUCTURED_COMPONENT_H
+#ifndef ANDROID_COMPONENT_H
+#define ANDROID_COMPONENT_H
 
 #include "rsUtils.h"
-#include "rsObjectBase.h"
 
 // ---------------------------------------------------------------------------
 namespace android {
 namespace renderscript {
 
-class Component : public ObjectBase
+
+// An element is a group of Components that occupies one cell in a structure.
+class Component
 {
 public:
-    enum DataType {
-        FLOAT,
-        UNSIGNED,
-        SIGNED
-    };
+    Component();
+    ~Component();
 
-    enum DataKind {
-        USER,
-        RED, GREEN, BLUE, ALPHA, LUMINANCE, INTENSITY,
-        X, Y, Z, W,
-        S, T, Q, R,
-        NX, NY, NZ,
-        INDEX,
-        POINT_SIZE
-    };
-
-
-    Component(Context *rsc, DataKind dk, DataType dt, bool isNorm, uint32_t bits, const char *);
-    virtual ~Component();
-
-    DataType getType() const {return mType;}
-    bool getIsNormalized() const {return mIsNormalized;}
-    DataKind getKind() const {return mKind;}
-    uint32_t getBits() const {return mBits;}
+    void set(RsDataType dt, RsDataKind dk, bool norm, uint32_t vecSize=1);
 
     uint32_t getGLType() const;
-    const char * getCType() const;
+    uint32_t getGLFormat() const;
+    String8 getCType() const;
+    String8 getGLSLType() const;
+    void dumpLOGV(const char *prefix) const;
 
-    const char * getComponentName() const {return mName.string();}
-    virtual void dumpLOGV(const char *prefix) const;
+
+    RsDataType getType() const {return mType;}
+    RsDataKind getKind() const {return mKind;}
+    bool getIsNormalized() const {return mNormalized;}
+    uint32_t getVectorSize() const {return mVectorSize;}
+    bool getIsFloat() const {return mIsFloat;}
+    bool getIsSigned() const {return mIsSigned;}
+    uint32_t getBits() const {return mBits;}
 
 protected:
+    RsDataType mType;
+    RsDataKind mKind;
+    bool mNormalized;
+    uint32_t mVectorSize;
 
-    DataType mType;
-    bool mIsNormalized;
-    DataKind mKind;
+    // derived
     uint32_t mBits;
-    String8 mName;
-
-private:
-    Component(Context *rsc);
+    uint32_t mTypeBits;
+    bool mIsFloat;
+    bool mIsSigned;
+    bool mIsPixel;
 };
 
-
 }
 }
 
-#endif //ANDROID_RS_STRUCTURED_COMPONENT_H
+#endif
 
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 3652f0a..261b827 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -27,6 +27,8 @@
 
 #include <GLES/gl.h>
 #include <GLES/glext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
 
 #include <cutils/sched_policy.h>
 
@@ -50,11 +52,12 @@
     }
 }
 
-void Context::initEGL()
+void Context::initEGL(bool useGL2)
 {
     mEGL.mNumConfigs = -1;
     EGLint configAttribs[128];
     EGLint *configAttribsPtr = configAttribs;
+    EGLint context_attribs2[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
 
     memset(configAttribs, 0, sizeof(configAttribs));
 
@@ -62,6 +65,12 @@
     configAttribsPtr[1] = EGL_WINDOW_BIT;
     configAttribsPtr += 2;
 
+    if (useGL2) {
+        configAttribsPtr[0] = EGL_RENDERABLE_TYPE;
+        configAttribsPtr[1] = EGL_OPENGL_ES2_BIT;
+        configAttribsPtr += 2;
+    }
+
     if (mUseDepth) {
         configAttribsPtr[0] = EGL_DEPTH_SIZE;
         configAttribsPtr[1] = 16;
@@ -91,7 +100,11 @@
     //eglChooseConfig(mEGL.mDisplay, configAttribs, &mEGL.mConfig, 1, &mEGL.mNumConfigs);
 
 
-    mEGL.mContext = eglCreateContext(mEGL.mDisplay, mEGL.mConfig, EGL_NO_CONTEXT, NULL);
+    if (useGL2) {
+        mEGL.mContext = eglCreateContext(mEGL.mDisplay, mEGL.mConfig, EGL_NO_CONTEXT, context_attribs2);
+    } else {
+        mEGL.mContext = eglCreateContext(mEGL.mDisplay, mEGL.mConfig, EGL_NO_CONTEXT, NULL);
+    }
     checkEglError("eglCreateContext");
     if (mEGL.mContext == EGL_NO_CONTEXT) {
         LOGE("eglCreateContext returned EGL_NO_CONTEXT");
@@ -129,6 +142,13 @@
     return ret;
 }
 
+void Context::checkError(const char *msg) const
+{
+    GLenum err = glGetError();
+    if (err != GL_NO_ERROR) {
+        LOGE("GL Error, 0x%x, from %s", err, msg);
+    }
+}
 
 uint32_t Context::runRootScript()
 {
@@ -156,11 +176,7 @@
     mStateFragmentStore.mLast.clear();
     uint32_t ret = runScript(mRootScript.get(), 0);
 
-    GLenum err = glGetError();
-    if (err != GL_NO_ERROR) {
-        LOGE("Pending GL Error, 0x%x", err);
-    }
-
+    checkError("runRootScript");
     return ret;
 }
 
@@ -225,10 +241,20 @@
 
 void Context::setupCheck()
 {
-    mFragmentStore->setupGL(this, &mStateFragmentStore);
-    mFragment->setupGL(this, &mStateFragment);
-    mRaster->setupGL(this, &mStateRaster);
-    mVertex->setupGL(this, &mStateVertex);
+    if (checkVersion2_0()) {
+        mShaderCache.lookup(this, mVertex.get(), mFragment.get());
+
+        mFragmentStore->setupGL2(this, &mStateFragmentStore);
+        mFragment->setupGL2(this, &mStateFragment, &mShaderCache);
+        mRaster->setupGL2(this, &mStateRaster);
+        mVertex->setupGL2(this, &mStateVertex, &mShaderCache);
+
+    } else {
+        mFragmentStore->setupGL(this, &mStateFragmentStore);
+        mFragment->setupGL(this, &mStateFragment);
+        mRaster->setupGL(this, &mStateRaster);
+        mVertex->setupGL(this, &mStateVertex);
+    }
 }
 
 static bool getProp(const char *str)
@@ -248,11 +274,8 @@
 
      rsc->props.mLogTimes = getProp("debug.rs.profile");
      rsc->props.mLogScripts = getProp("debug.rs.script");
-     rsc->props.mLogObjects = getProp("debug.rs.objects");
-
-     //pthread_mutex_lock(&gInitMutex);
-     //rsc->initEGL();
-     //pthread_mutex_unlock(&gInitMutex);
+     rsc->props.mLogObjects = getProp("debug.rs.object");
+     rsc->props.mLogShaders = getProp("debug.rs.shader");
 
      ScriptTLSStruct *tlsStruct = new ScriptTLSStruct;
      if (!tlsStruct) {
@@ -274,6 +297,7 @@
      rsc->setFragment(NULL);
      rsc->mStateFragmentStore.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight);
      rsc->setFragmentStore(NULL);
+     rsc->mStateVertexArray.init(rsc);
 
      rsc->mRunning = true;
      bool mDraw = true;
@@ -319,10 +343,6 @@
      rsc->mObjDestroy.mNeedToEmpty = true;
      rsc->objDestroyOOBRun();
 
-     glClearColor(0,0,0,0);
-     glClear(GL_COLOR_BUFFER_BIT);
-     eglSwapBuffers(rsc->mEGL.mDisplay, rsc->mEGL.mSurface);
-
      pthread_mutex_lock(&gInitMutex);
      rsc->deinitEGL();
      pthread_mutex_unlock(&gInitMutex);
@@ -457,7 +477,7 @@
         if (!mEGL.mContext) {
             first = true;
             pthread_mutex_lock(&gInitMutex);
-            initEGL();
+            initEGL(true);
             pthread_mutex_unlock(&gInitMutex);
         }
 
@@ -488,15 +508,35 @@
 
             //LOGV("EGL Version %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion);
             LOGV("GL Version %s", mGL.mVersion);
-            LOGV("GL Vendor %s", mGL.mVendor);
+            //LOGV("GL Vendor %s", mGL.mVendor);
             LOGV("GL Renderer %s", mGL.mRenderer);
             //LOGV("GL Extensions %s", mGL.mExtensions);
 
-            if ((strlen((const char *)mGL.mVersion) < 12) || memcmp(mGL.mVersion, "OpenGL ES-CM", 12)) {
+            const char *verptr = NULL;
+            if (strlen((const char *)mGL.mVersion) > 9) {
+                if (!memcmp(mGL.mVersion, "OpenGL ES-CM", 12)) {
+                    verptr = (const char *)mGL.mVersion + 12;
+                }
+                if (!memcmp(mGL.mVersion, "OpenGL ES ", 10)) {
+                    verptr = (const char *)mGL.mVersion + 9;
+                }
+            }
+
+            if (!verptr) {
                 LOGE("Error, OpenGL ES Lite not supported");
             } else {
-                sscanf((const char *)mGL.mVersion + 13, "%i.%i", &mGL.mMajorVersion, &mGL.mMinorVersion);
+                sscanf(verptr, " %i.%i", &mGL.mMajorVersion, &mGL.mMinorVersion);
             }
+
+            glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &mGL.mMaxVertexAttribs);
+            glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &mGL.mMaxVertexUniformVectors);
+            glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mGL.mMaxVertexTextureUnits);
+
+            glGetIntegerv(GL_MAX_VARYING_VECTORS, &mGL.mMaxVaryingVectors);
+            glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mGL.mMaxTextureImageUnits);
+
+            glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &mGL.mMaxFragmentTextureImageUnits);
+            glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &mGL.mMaxFragmentUniformVectors);
         }
 
     }
@@ -544,13 +584,6 @@
     }
 }
 
-void Context::allocationCheck(const Allocation *a)
-{
-    mVertex->checkUpdatedAllocation(a);
-    mFragment->checkUpdatedAllocation(a);
-    mFragmentStore->checkUpdatedAllocation(a);
-}
-
 void Context::setVertex(ProgramVertex *pv)
 {
     if (pv == NULL) {
@@ -558,7 +591,6 @@
     } else {
         mVertex.set(pv);
     }
-    mVertex->forceDirty();
 }
 
 void Context::assignName(ObjectBase *obj, const char *name, uint32_t len)
@@ -600,26 +632,6 @@
     }
 }
 
-void Context::appendVarDefines(String8 *str) const
-{
-    char buf[256];
-    for (size_t ct=0; ct < mInt32Defines.size(); ct++) {
-        str->append("#define ");
-        str->append(mInt32Defines.keyAt(ct));
-        str->append(" ");
-        sprintf(buf, "%i\n", (int)mInt32Defines.valueAt(ct));
-        str->append(buf);
-
-    }
-    for (size_t ct=0; ct < mFloatDefines.size(); ct++) {
-        str->append("#define ");
-        str->append(mFloatDefines.keyAt(ct));
-        str->append(" ");
-        sprintf(buf, "%ff\n", mFloatDefines.valueAt(ct));
-        str->append(buf);
-    }
-}
-
 bool Context::objDestroyOOBInit()
 {
     int status = pthread_mutex_init(&mObjDestroy.mMutex, NULL);
@@ -751,6 +763,10 @@
     LOGE(" RS running %i, exit %i, useDepth %i, paused %i", mRunning, mExit, mUseDepth, mPaused);
     LOGE(" RS pThreadID %li, nativeThreadID %i", mThreadId, mNativeThreadId);
 
+    LOGV("MAX Textures %i, %i  %i", mGL.mMaxVertexTextureUnits, mGL.mMaxFragmentTextureImageUnits, mGL.mMaxTextureImageUnits);
+    LOGV("MAX Attribs %i", mGL.mMaxVertexAttribs);
+    LOGV("MAX Uniforms %i, %i", mGL.mMaxVertexUniformVectors, mGL.mMaxFragmentUniformVectors);
+    LOGV("MAX Varyings %i", mGL.mMaxVaryingVectors);
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////
@@ -815,16 +831,6 @@
     ob->decUserRef();
 }
 
-void rsi_ContextSetDefineF(Context *rsc, const char* name, float value)
-{
-    rsc->addInt32Define(name, value);
-}
-
-void rsi_ContextSetDefineI32(Context *rsc, const char* name, int32_t value)
-{
-    rsc->addFloatDefine(name, value);
-}
-
 void rsi_ContextPause(Context *rsc)
 {
     rsc->pause();
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index 1770ee6..2edd16d 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -37,6 +37,8 @@
 #include "rsProgramFragmentStore.h"
 #include "rsProgramRaster.h"
 #include "rsProgramVertex.h"
+#include "rsShaderCache.h"
+#include "rsVertexArray.h"
 
 #include "rsgApiStructs.h"
 #include "rsLocklessFifo.h"
@@ -72,8 +74,10 @@
     ProgramRasterState mStateRaster;
     ProgramVertexState mStateVertex;
     LightState mStateLight;
+    VertexArrayState mStateVertexArray;
 
     ScriptCState mScriptC;
+    ShaderCache mShaderCache;
 
     void swapBuffers();
     void setRootScript(Script *);
@@ -90,7 +94,7 @@
     const ProgramVertex * getVertex() {return mVertex.get();}
 
     void setupCheck();
-    void allocationCheck(const Allocation *);
+    bool checkDriver() const {return mEGL.mSurface != 0;}
 
     void pause();
     void resume();
@@ -101,7 +105,6 @@
     void removeName(ObjectBase *obj);
     ObjectBase * lookupName(const char *name) const;
     void appendNameDefines(String8 *str) const;
-    void appendVarDefines(String8 *str) const;
 
     uint32_t getMessageToClient(void *data, size_t *receiveLen, size_t bufferLen, bool wait);
     bool sendMessageToClient(void *data, uint32_t cmdID, size_t len, bool waitForSpace);
@@ -123,14 +126,6 @@
         return mStateRaster.mDefault.get();
     }
 
-    void addInt32Define(const char* name, int32_t value) {
-        mInt32Defines.add(String8(name), value);
-    }
-
-    void addFloatDefine(const char* name, float value) {
-        mFloatDefines.add(String8(name), value);
-    }
-
     uint32_t getWidth() const {return mEGL.mWidth;}
     uint32_t getHeight() const {return mEGL.mHeight;}
 
@@ -160,9 +155,11 @@
         bool mLogTimes;
         bool mLogScripts;
         bool mLogObjects;
+        bool mLogShaders;
     } props;
 
     void dumpDebug() const;
+    void checkError(const char *) const;
 
     mutable const ObjectBase * mObjHead;
 
@@ -190,6 +187,15 @@
         uint32_t mMajorVersion;
         uint32_t mMinorVersion;
 
+        int32_t mMaxVaryingVectors;
+        int32_t mMaxTextureImageUnits;
+
+        int32_t mMaxFragmentTextureImageUnits;
+        int32_t mMaxFragmentUniformVectors;
+
+        int32_t mMaxVertexAttribs;
+        int32_t mMaxVertexUniformVectors;
+        int32_t mMaxVertexTextureUnits;
     } mGL;
 
     uint32_t mWidth;
@@ -224,7 +230,7 @@
 private:
     Context();
 
-    void initEGL();
+    void initEGL(bool useGL2);
     void deinitEGL();
 
     uint32_t runRootScript();
@@ -234,8 +240,6 @@
     Surface *mWndSurface;
 
     Vector<ObjectBase *> mNames;
-    KeyedVector<String8,int> mInt32Defines;
-    KeyedVector<String8,float> mFloatDefines;
 
     uint64_t mTimers[_RS_TIMER_TOTAL];
     Timers mTimerActive;
diff --git a/libs/rs/rsElement.cpp b/libs/rs/rsElement.cpp
index 67e4f14..207ad15 100644
--- a/libs/rs/rsElement.cpp
+++ b/libs/rs/rsElement.cpp
@@ -24,19 +24,13 @@
 
 Element::Element(Context *rsc) : ObjectBase(rsc)
 {
+    mBits = 0;
     mAllocFile = __FILE__;
     mAllocLine = __LINE__;
-    mComponents = NULL;
-    mComponentCount = 0;
+    mFields = NULL;
+    mFieldCount = 0;
 }
 
-Element::Element(Context *rsc, uint32_t count) : ObjectBase(rsc)
-{
-    mAllocFile = __FILE__;
-    mAllocLine = __LINE__;
-    mComponents = new ObjectBaseRef<Component> [count];
-    mComponentCount = count;
-}
 
 Element::~Element()
 {
@@ -45,153 +39,129 @@
 
 void Element::clear()
 {
-    delete [] mComponents;
-    mComponents = NULL;
-    mComponentCount = 0;
+    delete [] mFields;
+    mFields = NULL;
+    mFieldCount = 0;
 }
 
-void Element::setComponent(uint32_t idx, Component *c)
-{
-    rsAssert(!mComponents[idx].get());
-    rsAssert(idx < mComponentCount);
-    mComponents[idx].set(c);
-
-// Fixme: This should probably not be here
-    c->incUserRef();
-}
-
-
 size_t Element::getSizeBits() const
 {
+    if (!mFieldCount) {
+        return mBits;
+    }
+
     size_t total = 0;
-    for (size_t ct=0; ct < mComponentCount; ct++) {
-        total += mComponents[ct]->getBits();
+    for (size_t ct=0; ct < mFieldCount; ct++) {
+        total += mFields[ct].e->mBits;
     }
     return total;
 }
 
-size_t Element::getComponentOffsetBits(uint32_t componentNumber) const
+size_t Element::getFieldOffsetBits(uint32_t componentNumber) const
 {
     size_t offset = 0;
     for (uint32_t ct = 0; ct < componentNumber; ct++) {
-        offset += mComponents[ct]->getBits();
+        offset += mFields[ct].e->mBits;
     }
     return offset;
 }
 
-uint32_t Element::getGLType() const
-{
-    int bits[4];
-
-    if (mComponentCount > 4) {
-        return 0;
-    }
-
-    for (uint32_t ct=0; ct < mComponentCount; ct++) {
-        bits[ct] = mComponents[ct]->getBits();
-        if (mComponents[ct]->getType() != Component::UNSIGNED) {
-            return 0;
-        }
-        if (!mComponents[ct]->getIsNormalized()) {
-            return 0;
-        }
-    }
-
-    switch(mComponentCount) {
-    case 1:
-        if (bits[0] == 8) {
-            return GL_UNSIGNED_BYTE;
-        }
-        return 0;
-    case 2:
-        if ((bits[0] == 8) &&
-            (bits[1] == 8)) {
-            return GL_UNSIGNED_BYTE;
-        }
-        return 0;
-    case 3:
-        if ((bits[0] == 8) &&
-            (bits[1] == 8) &&
-            (bits[2] == 8)) {
-            return GL_UNSIGNED_BYTE;
-        }
-        if ((bits[0] == 5) &&
-            (bits[1] == 6) &&
-            (bits[2] == 5)) {
-            return GL_UNSIGNED_SHORT_5_6_5;
-        }
-        return 0;
-    case 4:
-        if ((bits[0] == 8) &&
-            (bits[1] == 8) &&
-            (bits[2] == 8) &&
-            (bits[3] == 8)) {
-            return GL_UNSIGNED_BYTE;
-        }
-        if ((bits[0] == 4) &&
-            (bits[1] == 4) &&
-            (bits[2] == 4) &&
-            (bits[3] == 4)) {
-            return GL_UNSIGNED_SHORT_4_4_4_4;
-        }
-        if ((bits[0] == 5) &&
-            (bits[1] == 5) &&
-            (bits[2] == 5) &&
-            (bits[3] == 1)) {
-            return GL_UNSIGNED_SHORT_5_5_5_1;
-        }
-    }
-    return 0;
-}
-
-uint32_t Element::getGLFormat() const
-{
-    switch(mComponentCount) {
-    case 1:
-        if (mComponents[0]->getKind() == Component::ALPHA) {
-            return GL_ALPHA;
-        }
-        if (mComponents[0]->getKind() == Component::LUMINANCE) {
-            return GL_LUMINANCE;
-        }
-        break;
-    case 2:
-        if ((mComponents[0]->getKind() == Component::LUMINANCE) &&
-            (mComponents[1]->getKind() == Component::ALPHA)) {
-            return GL_LUMINANCE_ALPHA;
-        }
-        break;
-    case 3:
-        if ((mComponents[0]->getKind() == Component::RED) &&
-            (mComponents[1]->getKind() == Component::GREEN) &&
-            (mComponents[2]->getKind() == Component::BLUE)) {
-            return GL_RGB;
-        }
-        break;
-    case 4:
-        if ((mComponents[0]->getKind() == Component::RED) &&
-            (mComponents[1]->getKind() == Component::GREEN) &&
-            (mComponents[2]->getKind() == Component::BLUE) &&
-            (mComponents[3]->getKind() == Component::ALPHA)) {
-            return GL_RGBA;
-        }
-        break;
-    }
-    return 0;
-}
-
-
 void Element::dumpLOGV(const char *prefix) const
 {
     ObjectBase::dumpLOGV(prefix);
-    LOGV("%s   Element: components %i,  size %i", prefix, mComponentCount, getSizeBytes());
-    for (uint32_t ct = 0; ct < mComponentCount; ct++) {
+    LOGV("%s   Element: components %i,  size %i", prefix, mFieldCount, mBits);
+    for (uint32_t ct = 0; ct < mFieldCount; ct++) {
         char buf[1024];
         sprintf(buf, "%s component %i: ", prefix, ct);
-        mComponents[ct]->dumpLOGV(buf);
+        //mComponents[ct]->dumpLOGV(buf);
     }
 }
 
+
+Element * Element::create(Context *rsc, RsDataType dt, RsDataKind dk,
+                            bool isNorm, uint32_t vecSize)
+{
+    Element *e = new Element(rsc);
+    e->mComponent.set(dt, dk, isNorm, vecSize);
+    e->mBits = e->mComponent.getBits();
+    return e;
+}
+
+Element * Element::create(Context *rsc, size_t count, const Element **ein,
+                            const char **nin, const size_t * lengths)
+{
+    Element *e = new Element(rsc);
+    e->mFields = new ElementField_t [count];
+    e->mFieldCount = count;
+
+    for (size_t ct=0; ct < count; ct++) {
+        e->mFields[ct].e.set(ein[ct]);
+        e->mFields[ct].name.setTo(nin[ct], lengths[ct]);
+    }
+
+    return e;
+}
+
+String8 Element::getCStructBody(uint32_t indent) const
+{
+    String8 si;
+    for (uint32_t ct=0; ct < indent; ct++) {
+        si.append(" ");
+    }
+
+    String8 s(si);
+    s.append("{\n");
+    for (uint32_t ct = 0; ct < mFieldCount; ct++) {
+        s.append(si);
+        s.append(mFields[ct].e->getCType(indent+4));
+        s.append(" ");
+        s.append(mFields[ct].name);
+        s.append(";\n");
+    }
+    s.append(si);
+    s.append("}");
+    return s;
+}
+
+String8 Element::getCType(uint32_t indent) const
+{
+    String8 s;
+    for (uint32_t ct=0; ct < indent; ct++) {
+        s.append(" ");
+    }
+
+    if (!mFieldCount) {
+        // Basic component.
+        s.append(mComponent.getCType());
+    } else {
+        s.append("struct ");
+        s.append(getCStructBody(indent));
+    }
+
+    return s;
+}
+
+String8 Element::getGLSLType(uint32_t indent) const
+{
+    String8 s;
+    for (uint32_t ct=0; ct < indent; ct++) {
+        s.append(" ");
+    }
+
+    if (!mFieldCount) {
+        // Basic component.
+        s.append(mComponent.getGLSLType());
+    } else {
+        rsAssert(0);
+        //s.append("struct ");
+        //s.append(getCStructBody(indent));
+    }
+
+    return s;
+}
+
+
+
 ElementState::ElementState()
 {
 }
@@ -200,46 +170,35 @@
 {
 }
 
+
 /////////////////////////////////////////
 //
 
 namespace android {
 namespace renderscript {
 
-void rsi_ElementBegin(Context *rsc)
+RsElement rsi_ElementCreate(Context *rsc,
+                            RsDataType dt,
+                            RsDataKind dk,
+                            bool norm,
+                            uint32_t vecSize)
 {
-    rsc->mStateElement.mComponentBuildList.clear();
+    //LOGE("rsi_ElementCreate %i %i %i %i", dt, dk, norm, vecSize);
+    Element *e = Element::create(rsc, dt, dk, norm, vecSize);
+    e->incUserRef();
+    return e;
 }
 
-void rsi_ElementAdd(Context *rsc, RsDataKind dk, RsDataType dt, bool isNormalized, size_t bits, const char *name)
+RsElement rsi_ElementCreate2(Context *rsc,
+                             size_t count,
+                             const RsElement * ein,
+                             const char ** names,
+                             const size_t * nameLengths)
 {
-    ElementState * sec = &rsc->mStateElement;
-
-    rsAssert(bits > 0);
-
-    Component *c = new Component(rsc,
-                                 static_cast<Component::DataKind>(dk),
-                                 static_cast<Component::DataType>(dt),
-                                 isNormalized,
-                                 bits,
-                                 name);
-    sec->mComponentBuildList.add(c);
-}
-
-RsElement rsi_ElementCreate(Context *rsc)
-{
-    ElementState * sec = &rsc->mStateElement;
-    Element *se = new Element(rsc, sec->mComponentBuildList.size());
-
-    rsAssert(se->getComponentCount() > 0);
-
-    for (size_t ct = 0; ct < se->getComponentCount(); ct++) {
-        se->setComponent(ct, sec->mComponentBuildList[ct]);
-    }
-
-    rsc->mStateElement.mComponentBuildList.clear();
-    se->incUserRef();
-    return se;
+    //LOGE("rsi_ElementCreate2 %i", count);
+    Element *e = Element::create(rsc, count, (const Element **)ein, names, nameLengths);
+    e->incUserRef();
+    return e;
 }
 
 
diff --git a/libs/rs/rsElement.h b/libs/rs/rsElement.h
index b41c552..777e8ee 100644
--- a/libs/rs/rsElement.h
+++ b/libs/rs/rsElement.h
@@ -18,6 +18,8 @@
 #define ANDROID_STRUCTURED_ELEMENT_H
 
 #include "rsComponent.h"
+#include "rsUtils.h"
+#include "rsObjectBase.h"
 
 // ---------------------------------------------------------------------------
 namespace android {
@@ -28,41 +30,57 @@
 class Element : public ObjectBase
 {
 public:
-    Element(Context *, uint32_t count);
     ~Element();
 
-
-    void setComponent(uint32_t idx, Component *c);
-
     uint32_t getGLType() const;
     uint32_t getGLFormat() const;
 
-
     size_t getSizeBits() const;
     size_t getSizeBytes() const {
         return (getSizeBits() + 7) >> 3;
     }
 
-    size_t getComponentOffsetBits(uint32_t componentNumber) const;
-    size_t getComponentOffsetBytes(uint32_t componentNumber) const {
-        return (getComponentOffsetBits(componentNumber) + 7) >> 3;
+    size_t getFieldOffsetBits(uint32_t componentNumber) const;
+    size_t getFieldOffsetBytes(uint32_t componentNumber) const {
+        return (getFieldOffsetBits(componentNumber) + 7) >> 3;
     }
 
-    uint32_t getComponentCount() const {return mComponentCount;}
-    Component * getComponent(uint32_t idx) const {return mComponents[idx].get();}
+    uint32_t getFieldCount() const {return mFieldCount;}
+    const Element * getField(uint32_t idx) const {return mFields[idx].e.get();}
+    const char * getFieldName(uint32_t idx) const {return mFields[idx].name.string();}
 
+    const Component & getComponent() const {return mComponent;}
+    RsDataType getType() const {return mComponent.getType();}
+    RsDataKind getKind() const {return mComponent.getKind();}
+    uint32_t getBits() const {return mBits;}
+
+    String8 getCType(uint32_t indent=0) const;
+    String8 getCStructBody(uint32_t indent=0) const;
+    String8 getGLSLType(uint32_t indent=0) const;
 
     void dumpLOGV(const char *prefix) const;
 
+    static Element * create(Context *rsc, RsDataType dt, RsDataKind dk,
+                            bool isNorm, uint32_t vecSize);
+    static Element * create(Context *rsc, size_t count, const Element **,
+                            const char **, const size_t * lengths);
+
 protected:
     // deallocate any components that are part of this element.
     void clear();
 
-    size_t mComponentCount;
-    ObjectBaseRef<Component> * mComponents;
-    //uint32_t *mOffsetTable;
+    typedef struct {
+        String8 name;
+        ObjectBaseRef<const Element> e;
+    } ElementField_t;
+    ElementField_t *mFields;
+    size_t mFieldCount;
+
 
     Element(Context *);
+
+    Component mComponent;
+    uint32_t mBits;
 };
 
 
@@ -71,7 +89,6 @@
     ElementState();
     ~ElementState();
 
-    Vector<Component *> mComponentBuildList;
 };
 
 
diff --git a/libs/rs/rsFileA3D.cpp b/libs/rs/rsFileA3D.cpp
index c566665..e3272c5 100644
--- a/libs/rs/rsFileA3D.cpp
+++ b/libs/rs/rsFileA3D.cpp
@@ -324,6 +324,7 @@
 
 void FileA3D::processChunk_Element(Context *rsc, IO *io, A3DIndexEntry *ie)
 {
+    /*
     rsi_ElementBegin(rsc);
 
     uint32_t count = io->loadU32();
@@ -338,6 +339,7 @@
     }
     LOGE("processChunk_Element create");
     ie->mRsObj = rsi_ElementCreate(rsc);
+    */
 }
 
 void FileA3D::processChunk_ElementSource(Context *rsc, IO *io, A3DIndexEntry *ie)
diff --git a/libs/rs/rsProgram.cpp b/libs/rs/rsProgram.cpp
index 5f2a609..656a3c3 100644
--- a/libs/rs/rsProgram.cpp
+++ b/libs/rs/rsProgram.cpp
@@ -17,34 +17,245 @@
 #include "rsContext.h"
 #include "rsProgram.h"
 
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
 using namespace android;
 using namespace android::renderscript;
 
 
-Program::Program(Context *rsc, Element *in, Element *out) : ObjectBase(rsc)
+Program::Program(Context *rsc) : ObjectBase(rsc)
 {
     mAllocFile = __FILE__;
     mAllocLine = __LINE__;
+    mDirty = true;
+    mShaderID = 0;
+    mAttribCount = 0;
+    mUniformCount = 0;
 
-    mElementIn.set(in);
-    mElementOut.set(out);
+    mInputElements = NULL;
+    mOutputElements = NULL;
+    mConstantTypes = NULL;
+    mInputCount = 0;
+    mOutputCount = 0;
+    mConstantCount = 0;
+}
+
+Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength,
+                 const uint32_t * params, uint32_t paramLength) :
+    ObjectBase(rsc)
+{
+    mAllocFile = __FILE__;
+    mAllocLine = __LINE__;
+    mDirty = true;
+    mShaderID = 0;
+    mAttribCount = 0;
+    mUniformCount = 0;
+    mTextureCount = 0;
+
+    mInputCount = 0;
+    mOutputCount = 0;
+    mConstantCount = 0;
+
+    for (uint32_t ct=0; ct < paramLength; ct+=2) {
+        if (params[ct] == RS_PROGRAM_PARAM_INPUT) {
+            mInputCount++;
+        }
+        if (params[ct] == RS_PROGRAM_PARAM_OUTPUT) {
+            mOutputCount++;
+        }
+        if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) {
+            mConstantCount++;
+        }
+        if (params[ct] == RS_PROGRAM_PARAM_TEXTURE_COUNT) {
+            mTextureCount = params[ct+1];
+        }
+    }
+
+    mInputElements = new ObjectBaseRef<Element>[mInputCount];
+    mOutputElements = new ObjectBaseRef<Element>[mOutputCount];
+    mConstantTypes = new ObjectBaseRef<Type>[mConstantCount];
+
+    uint32_t input = 0;
+    uint32_t output = 0;
+    uint32_t constant = 0;
+    for (uint32_t ct=0; ct < paramLength; ct+=2) {
+        if (params[ct] == RS_PROGRAM_PARAM_INPUT) {
+            mInputElements[input++].set(reinterpret_cast<Element *>(params[ct+1]));
+        }
+        if (params[ct] == RS_PROGRAM_PARAM_OUTPUT) {
+            mOutputElements[output++].set(reinterpret_cast<Element *>(params[ct+1]));
+        }
+        if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) {
+            mConstantTypes[constant++].set(reinterpret_cast<Type *>(params[ct+1]));
+        }
+    }
+    mUserShader.setTo(shaderText, shaderLength);
 }
 
 Program::~Program()
 {
+    for (uint32_t ct=0; ct < MAX_UNIFORMS; ct++) {
+        bindAllocation(NULL, ct);
+    }
+
+    delete[] mInputElements;
+    delete[] mOutputElements;
+    delete[] mConstantTypes;
+    mInputCount = 0;
+    mOutputCount = 0;
+    mConstantCount = 0;
 }
 
 
-void Program::bindAllocation(Allocation *alloc)
+void Program::bindAllocation(Allocation *alloc, uint32_t slot)
 {
-    mConstants.set(alloc);
+    if (mConstants[slot].get() == alloc) {
+        return;
+    }
+    if (mConstants[slot].get()) {
+        mConstants[slot].get()->removeProgramToDirty(this);
+    }
+    mConstants[slot].set(alloc);
+    if (alloc) {
+        alloc->addProgramToDirty(this);
+    }
     mDirty = true;
 }
 
-void Program::checkUpdatedAllocation(const Allocation *alloc)
+void Program::bindTexture(uint32_t slot, Allocation *a)
 {
-    if (mConstants.get() == alloc) {
-        mDirty = true;
+    if (slot >= MAX_TEXTURE) {
+        LOGE("Attempt to bind a texture to a slot > MAX_TEXTURE");
+        return;
     }
+
+    //LOGE("bindtex %i %p", slot, a);
+    mTextures[slot].set(a);
+    mDirty = true;
+}
+
+void Program::bindSampler(uint32_t slot, Sampler *s)
+{
+    if (slot >= MAX_TEXTURE) {
+        LOGE("Attempt to bind a Sampler to a slot > MAX_TEXTURE");
+        return;
+    }
+
+    mSamplers[slot].set(s);
+    mDirty = true;
+}
+
+String8 Program::getGLSLInputString() const
+{
+    String8 s;
+    for (uint32_t ct=0; ct < mInputCount; ct++) {
+        const Element *e = mInputElements[ct].get();
+        for (uint32_t field=0; field < e->getFieldCount(); field++) {
+            const Element *f = e->getField(field);
+
+            // Cannot be complex
+            rsAssert(!f->getFieldCount());
+            switch(f->getComponent().getVectorSize()) {
+            case 1: s.append("attribute float ATTRIB_"); break;
+            case 2: s.append("attribute vec2 ATTRIB_"); break;
+            case 3: s.append("attribute vec3 ATTRIB_"); break;
+            case 4: s.append("attribute vec4 ATTRIB_"); break;
+            default:
+                rsAssert(0);
+            }
+
+            s.append(e->getFieldName(field));
+            s.append(";\n");
+        }
+    }
+    return s;
+}
+
+String8 Program::getGLSLOutputString() const
+{
+    return String8();
+}
+
+String8 Program::getGLSLConstantString() const
+{
+    return String8();
+}
+
+
+void Program::createShader()
+{
+}
+
+bool Program::loadShader(Context *rsc, uint32_t type)
+{
+    mShaderID = glCreateShader(type);
+    rsAssert(mShaderID);
+
+    if (rsc->props.mLogShaders) {
+        LOGV("Loading shader type %x, ID %i", type, mShaderID);
+        LOGV(mShader.string());
+    }
+
+    if (mShaderID) {
+        const char * ss = mShader.string();
+        glShaderSource(mShaderID, 1, &ss, NULL);
+        glCompileShader(mShaderID);
+
+        GLint compiled = 0;
+        glGetShaderiv(mShaderID, GL_COMPILE_STATUS, &compiled);
+        if (!compiled) {
+            GLint infoLen = 0;
+            glGetShaderiv(mShaderID, GL_INFO_LOG_LENGTH, &infoLen);
+            if (infoLen) {
+                char* buf = (char*) malloc(infoLen);
+                if (buf) {
+                    glGetShaderInfoLog(mShaderID, infoLen, NULL, buf);
+                    LOGE("Could not compile shader \n%s\n", buf);
+                    free(buf);
+                }
+                glDeleteShader(mShaderID);
+                mShaderID = 0;
+                return false;
+            }
+        }
+    }
+
+    if (rsc->props.mLogShaders) {
+        LOGV("--Shader load result %x ", glGetError());
+    }
+    return true;
+}
+
+void Program::setShader(const char *txt, uint32_t len)
+{
+    mUserShader.setTo(txt, len);
+}
+
+
+
+namespace android {
+namespace renderscript {
+
+
+void rsi_ProgramBindConstants(Context *rsc, RsProgram vp, uint32_t slot, RsAllocation constants)
+{
+    Program *p = static_cast<Program *>(vp);
+    p->bindAllocation(static_cast<Allocation *>(constants), slot);
+}
+
+void rsi_ProgramBindTexture(Context *rsc, RsProgram vpf, uint32_t slot, RsAllocation a)
+{
+    Program *p = static_cast<Program *>(vpf);
+    p->bindTexture(slot, static_cast<Allocation *>(a));
+}
+
+void rsi_ProgramBindSampler(Context *rsc, RsProgram vpf, uint32_t slot, RsSampler s)
+{
+    Program *p = static_cast<Program *>(vpf);
+    p->bindSampler(slot, static_cast<Sampler *>(s));
+}
+
+}
 }
 
diff --git a/libs/rs/rsProgram.h b/libs/rs/rsProgram.h
index 57c654f..238ee7f 100644
--- a/libs/rs/rsProgram.h
+++ b/libs/rs/rsProgram.h
@@ -25,29 +25,78 @@
 namespace renderscript {
 
 
+class ShaderCache;
 
 class Program : public ObjectBase
 {
 public:
-    Program(Context *, Element *in, Element *out);
+    const static uint32_t MAX_ATTRIBS = 8;
+    const static uint32_t MAX_UNIFORMS = 16;
+    const static uint32_t MAX_TEXTURE = 2;
+
+    Program(Context *);
+    Program(Context *, const char * shaderText, uint32_t shaderLength,
+                       const uint32_t * params, uint32_t paramLength);
     virtual ~Program();
 
-    void bindAllocation(Allocation *);
-    void checkUpdatedAllocation(const Allocation *);
+    void bindAllocation(Allocation *, uint32_t slot);
+    virtual void createShader();
+
+    bool isUserProgram() const {return mUserShader.size() > 0;}
+
+    void bindTexture(uint32_t slot, Allocation *);
+    void bindSampler(uint32_t slot, Sampler *);
+
+    uint32_t getShaderID() const {return mShaderID;}
+    void setShader(const char *, uint32_t len);
+
+    uint32_t getAttribCount() const {return mAttribCount;}
+    uint32_t getUniformCount() const {return mUniformCount;}
+    const String8 & getAttribName(uint32_t i) const {return mAttribNames[i];}
+    const String8 & getUniformName(uint32_t i) const {return mUniformNames[i];}
+
+    String8 getGLSLInputString() const;
+    String8 getGLSLOutputString() const;
+    String8 getGLSLConstantString() const;
+
+    const Allocation * getTexture(uint32_t i) const {return mTextures[i].get();}
 
 protected:
     // Components not listed in "in" will be passed though
     // unless overwritten by components in out.
-    ObjectBaseRef<Element> mElementIn;
-    ObjectBaseRef<Element> mElementOut;
+    ObjectBaseRef<Element> *mInputElements;
+    ObjectBaseRef<Element> *mOutputElements;
+    ObjectBaseRef<Type> *mConstantTypes;
+    uint32_t mInputCount;
+    uint32_t mOutputCount;
+    uint32_t mConstantCount;
 
-    ObjectBaseRef<Allocation> mConstants;
+    ObjectBaseRef<Allocation> mConstants[MAX_UNIFORMS];
 
     mutable bool mDirty;
+    String8 mShader;
+    String8 mUserShader;
+    uint32_t mShaderID;
 
+    uint32_t mTextureCount;
+    uint32_t mAttribCount;
+    uint32_t mUniformCount;
+    String8 mAttribNames[MAX_ATTRIBS];
+    String8 mUniformNames[MAX_UNIFORMS];
+
+    // The difference between Textures and Constants is how they are accessed
+    // Texture lookups go though a sampler which in effect converts normalized
+    // coordinates into type specific.  Multiple samples may also be taken
+    // and filtered.
+    //
+    // Constants are strictly accessed by programetic loads.
+    ObjectBaseRef<Allocation> mTextures[MAX_TEXTURE];
+    ObjectBaseRef<Sampler> mSamplers[MAX_TEXTURE];
+
+    bool loadShader(Context *, uint32_t type);
 
 public:
-    void forceDirty() {mDirty = true;}
+    void forceDirty() const {mDirty = true;}
 };
 
 
diff --git a/libs/rs/rsProgramFragment.cpp b/libs/rs/rsProgramFragment.cpp
index 5f2dfae..15f3269 100644
--- a/libs/rs/rsProgramFragment.cpp
+++ b/libs/rs/rsProgramFragment.cpp
@@ -19,25 +19,50 @@
 
 #include <GLES/gl.h>
 #include <GLES/glext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
 
 using namespace android;
 using namespace android::renderscript;
 
 
-ProgramFragment::ProgramFragment(Context *rsc, Element *in, Element *out, bool pointSpriteEnable) :
-    Program(rsc, in, out)
+ProgramFragment::ProgramFragment(Context *rsc, const uint32_t * params,
+                                 uint32_t paramLength) :
+    Program(rsc)
 {
     mAllocFile = __FILE__;
     mAllocLine = __LINE__;
-    for (uint32_t ct=0; ct < MAX_TEXTURE; ct++) {
-        mEnvModes[ct] = RS_TEX_ENV_MODE_REPLACE;
-        mTextureDimensions[ct] = 2;
-    }
+    rsAssert(paramLength = 5);
+
+    mEnvModes[0] = (RsTexEnvMode)params[0];
+    mTextureFormats[0] = params[1];
+    mEnvModes[1] = (RsTexEnvMode)params[2];
+    mTextureFormats[1] = params[3];
+    mPointSpriteEnable = params[4] != 0;
+
     mTextureEnableMask = 0;
-    mPointSpriteEnable = pointSpriteEnable;
-    mEnvModes[1] = RS_TEX_ENV_MODE_DECAL;
+    if (mEnvModes[0]) {
+        mTextureEnableMask |= 1;
+    }
+    if (mEnvModes[1]) {
+        mTextureEnableMask |= 2;
+    }
+    init(rsc);
 }
 
+ProgramFragment::ProgramFragment(Context *rsc, const char * shaderText,
+                                 uint32_t shaderLength, const uint32_t * params,
+                                 uint32_t paramLength) :
+    Program(rsc, shaderText, shaderLength, params, paramLength)
+{
+    mAllocFile = __FILE__;
+    mAllocLine = __LINE__;
+
+    init(rsc);
+    mTextureEnableMask = (1 << mTextureCount) -1;
+}
+
+
 ProgramFragment::~ProgramFragment()
 {
 }
@@ -65,23 +90,13 @@
             }
             glTexEnvi(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, mPointSpriteEnable);
         }
-
-        rsAssert(mTextures[ct]->getTextureID() != 0);
-        if (mTextures[ct]->getTextureID() == 0) {
-            // This is a hack for eclair to try to fix the white squares bug.
-            Allocation *a = (Allocation *)mTextures[ct].get();
-            a->uploadToTexture((Context *)rsc, 0);
-            if (mTextures[ct]->getTextureID() == 0) {
-                // At this point we are screwed.  Crash to restart the app.
-                rsc->dumpDebug();
-                LOGE("Multiple failures during texture upload.  Driver appears wedged.");
-                ((char *)0)[0] = 0;
-            }
-
-        }
+        mTextures[ct]->uploadCheck(rsc);
         glBindTexture(GL_TEXTURE_2D, mTextures[ct]->getTextureID());
 
         switch(mEnvModes[ct]) {
+        case RS_TEX_ENV_MODE_NONE:
+            rsAssert(0);
+            break;
         case RS_TEX_ENV_MODE_REPLACE:
             glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
             break;
@@ -94,7 +109,7 @@
         }
 
         if (mSamplers[ct].get()) {
-            mSamplers[ct]->setupGL();
+            mSamplers[ct]->setupGL(rsc);
         } else {
             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -121,74 +136,159 @@
     }
     glActiveTexture(GL_TEXTURE0);
     mDirty = false;
+    rsc->checkError("ProgramFragment::setupGL");
 }
 
-
-void ProgramFragment::bindTexture(uint32_t slot, Allocation *a)
+void ProgramFragment::setupGL2(const Context *rsc, ProgramFragmentState *state, ShaderCache *sc)
 {
-    if (slot >= MAX_TEXTURE) {
-        LOGE("Attempt to bind a texture to a slot > MAX_TEXTURE");
-        return;
+
+    //LOGE("sgl2 frag1 %x", glGetError());
+    if ((state->mLast.get() == this) && !mDirty) {
+        //return;
+    }
+    state->mLast.set(this);
+
+    rsc->checkError("ProgramFragment::setupGL2 start");
+    for (uint32_t ct=0; ct < MAX_TEXTURE; ct++) {
+        glActiveTexture(GL_TEXTURE0 + ct);
+        if (!(mTextureEnableMask & (1 << ct)) || !mTextures[ct].get()) {
+            continue;
+        }
+
+        mTextures[ct]->uploadCheck(rsc);
+        glBindTexture(GL_TEXTURE_2D, mTextures[ct]->getTextureID());
+        rsc->checkError("ProgramFragment::setupGL2 tex bind");
+        if (mSamplers[ct].get()) {
+            mSamplers[ct]->setupGL(rsc);
+        } else {
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+            rsc->checkError("ProgramFragment::setupGL2 tex env");
+        }
+
+        glUniform1i(sc->fragUniformSlot(ct), ct);
+        rsc->checkError("ProgramFragment::setupGL2 uniforms");
     }
 
-    //LOGE("bindtex %i %p", slot, a);
-    mTextures[slot].set(a);
-    mDirty = true;
+    glActiveTexture(GL_TEXTURE0);
+    mDirty = false;
+    rsc->checkError("ProgramFragment::setupGL2");
 }
 
-void ProgramFragment::bindSampler(uint32_t slot, Sampler *s)
+void ProgramFragment::loadShader(Context *rsc) {
+    Program::loadShader(rsc, GL_FRAGMENT_SHADER);
+}
+
+void ProgramFragment::createShader()
 {
-    if (slot >= MAX_TEXTURE) {
-        LOGE("Attempt to bind a Sampler to a slot > MAX_TEXTURE");
-        return;
-    }
+    mShader.setTo("precision mediump float;\n");
+    mShader.append("varying vec4 varColor;\n");
+    mShader.append("varying vec4 varTex0;\n");
 
-    mSamplers[slot].set(s);
-    mDirty = true;
+    if (mUserShader.length() > 1) {
+        for (uint32_t ct=0; ct < mTextureCount; ct++) {
+            char buf[256];
+            sprintf(buf, "uniform sampler2D uni_Tex%i;\n", ct);
+            mShader.append(buf);
+        }
+
+        mShader.append(mUserShader);
+    } else {
+        uint32_t mask = mTextureEnableMask;
+        uint32_t texNum = 0;
+        while (mask) {
+            if (mask & 1) {
+                char buf[64];
+                mShader.append("uniform sampler2D uni_Tex");
+                sprintf(buf, "%i", texNum);
+                mShader.append(buf);
+                mShader.append(";\n");
+            }
+            mask >>= 1;
+            texNum++;
+        }
+
+
+        mShader.append("void main() {\n");
+        mShader.append("  vec4 col = varColor;\n");
+
+        if (mTextureEnableMask) {
+            if (mPointSpriteEnable) {
+                mShader.append("  vec2 t0 = gl_PointCoord;\n");
+            } else {
+                mShader.append("  vec2 t0 = varTex0.xy;\n");
+            }
+        }
+
+        mask = mTextureEnableMask;
+        texNum = 0;
+        while (mask) {
+            if (mask & 1) {
+                switch(mEnvModes[texNum]) {
+                case RS_TEX_ENV_MODE_NONE:
+                    rsAssert(0);
+                    break;
+                case RS_TEX_ENV_MODE_REPLACE:
+                    switch(mTextureFormats[texNum]) {
+                    case 1:
+                        mShader.append("  col.a = texture2D(uni_Tex0, t0).a;\n");
+                        break;
+                    case 2:
+                        mShader.append("  col.rgba = texture2D(uni_Tex0, t0).rgba;\n");
+                        break;
+                    case 3:
+                        mShader.append("  col.rgb = texture2D(uni_Tex0, t0).rgb;\n");
+                        break;
+                    case 4:
+                        mShader.append("  col.rgba = texture2D(uni_Tex0, t0).rgba;\n");
+                        break;
+                    }
+                    break;
+                case RS_TEX_ENV_MODE_MODULATE:
+                    switch(mTextureFormats[texNum]) {
+                    case 1:
+                        mShader.append("  col.a *= texture2D(uni_Tex0, t0).a;\n");
+                        break;
+                    case 2:
+                        mShader.append("  col.rgba *= texture2D(uni_Tex0, t0).rgba;\n");
+                        break;
+                    case 3:
+                        mShader.append("  col.rgb *= texture2D(uni_Tex0, t0).rgb;\n");
+                        break;
+                    case 4:
+                        mShader.append("  col.rgba *= texture2D(uni_Tex0, t0).rgba;\n");
+                        break;
+                    }
+                    break;
+                case RS_TEX_ENV_MODE_DECAL:
+                    mShader.append("  col = texture2D(uni_Tex0, t0);\n");
+                    break;
+                }
+
+            }
+            mask >>= 1;
+            texNum++;
+        }
+
+        //mShader.append("  col.a = 1.0;\n");
+        //mShader.append("  col.r = 0.5;\n");
+
+        mShader.append("  gl_FragColor = col;\n");
+        mShader.append("}\n");
+    }
 }
 
-void ProgramFragment::setType(uint32_t slot, const Element *e, uint32_t dim)
+void ProgramFragment::init(Context *rsc)
 {
-    if (slot >= MAX_TEXTURE) {
-        LOGE("Attempt to setType to a slot > MAX_TEXTURE");
-        return;
-    }
+    mUniformCount = 2;
+    mUniformNames[0].setTo("uni_Tex0");
+    mUniformNames[1].setTo("uni_Tex1");
 
-    if (dim >= 4) {
-        LOGE("Attempt to setType to a dimension > 3");
-        return;
-    }
-
-    mTextureFormats[slot].set(e);
-    mTextureDimensions[slot] = dim;
+    createShader();
 }
 
-void ProgramFragment::setEnvMode(uint32_t slot, RsTexEnvMode env)
-{
-    if (slot >= MAX_TEXTURE) {
-        LOGE("Attempt to setEnvMode to a slot > MAX_TEXTURE");
-        return;
-    }
-
-    mEnvModes[slot] = env;
-}
-
-void ProgramFragment::setTexEnable(uint32_t slot, bool enable)
-{
-    if (slot >= MAX_TEXTURE) {
-        LOGE("Attempt to setEnvMode to a slot > MAX_TEXTURE");
-        return;
-    }
-
-    uint32_t bit = 1 << slot;
-    mTextureEnableMask &= ~bit;
-    if (enable) {
-        mTextureEnableMask |= bit;
-    }
-}
-
-
-
 ProgramFragmentState::ProgramFragmentState()
 {
     mPF = NULL;
@@ -202,8 +302,14 @@
 
 void ProgramFragmentState::init(Context *rsc, int32_t w, int32_t h)
 {
-    ProgramFragment *pf = new ProgramFragment(rsc, NULL, NULL, false);
+    uint32_t tmp[5] = {
+        RS_TEX_ENV_MODE_NONE, 0,
+        RS_TEX_ENV_MODE_NONE, 0,
+        0
+    };
+    ProgramFragment *pf = new ProgramFragment(rsc, tmp, 5);
     mDefault.set(pf);
+    pf->init(rsc);
 }
 
 void ProgramFragmentState::deinit(Context *rsc)
@@ -216,49 +322,23 @@
 namespace android {
 namespace renderscript {
 
-void rsi_ProgramFragmentBegin(Context * rsc, RsElement in, RsElement out, bool pointSpriteEnable)
+RsProgramFragment rsi_ProgramFragmentCreate(Context *rsc,
+                                            const uint32_t * params,
+                                            uint32_t paramLength)
 {
-    delete rsc->mStateFragment.mPF;
-    rsc->mStateFragment.mPF = new ProgramFragment(rsc, (Element *)in, (Element *)out, pointSpriteEnable);
-}
-
-void rsi_ProgramFragmentBindTexture(Context *rsc, RsProgramFragment vpf, uint32_t slot, RsAllocation a)
-{
-    ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
-    pf->bindTexture(slot, static_cast<Allocation *>(a));
-}
-
-void rsi_ProgramFragmentBindSampler(Context *rsc, RsProgramFragment vpf, uint32_t slot, RsSampler s)
-{
-    ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
-    pf->bindSampler(slot, static_cast<Sampler *>(s));
-}
-
-void rsi_ProgramFragmentSetSlot(Context *rsc, uint32_t slot, bool enable, RsTexEnvMode env, RsType vt)
-{
-    const Type *t = static_cast<const Type *>(vt);
-    if (t) {
-        uint32_t dim = 1;
-        if (t->getDimY()) {
-            dim ++;
-            if (t->getDimZ()) {
-                dim ++;
-            }
-        }
-        rsc->mStateFragment.mPF->setType(slot, t->getElement(), dim);
-    }
-    rsc->mStateFragment.mPF->setEnvMode(slot, env);
-    rsc->mStateFragment.mPF->setTexEnable(slot, enable);
-}
-
-RsProgramFragment rsi_ProgramFragmentCreate(Context *rsc)
-{
-    ProgramFragment *pf = rsc->mStateFragment.mPF;
+    ProgramFragment *pf = new ProgramFragment(rsc, params, paramLength);
     pf->incUserRef();
-    rsc->mStateFragment.mPF = 0;
     return pf;
 }
 
+RsProgramFragment rsi_ProgramFragmentCreate2(Context *rsc, const char * shaderText,
+                             uint32_t shaderLength, const uint32_t * params,
+                             uint32_t paramLength)
+{
+    ProgramFragment *pf = new ProgramFragment(rsc, shaderText, shaderLength, params, paramLength);
+    pf->incUserRef();
+    return pf;
+}
 
 }
 }
diff --git a/libs/rs/rsProgramFragment.h b/libs/rs/rsProgramFragment.h
index e26c6e8..9fa565d 100644
--- a/libs/rs/rsProgramFragment.h
+++ b/libs/rs/rsProgramFragment.h
@@ -28,40 +28,23 @@
 class ProgramFragment : public Program
 {
 public:
-    const static uint32_t MAX_TEXTURE = 2;
-
-
-
-    ProgramFragment(Context *, Element *in, Element *out, bool pointSpriteEnable);
+    ProgramFragment(Context *, const uint32_t * params, uint32_t paramLength);
+    ProgramFragment(Context *rsc, const char * shaderText,
+                             uint32_t shaderLength, const uint32_t * params,
+                             uint32_t paramLength);
     virtual ~ProgramFragment();
 
     virtual void setupGL(const Context *, ProgramFragmentState *);
+    virtual void setupGL2(const Context *, ProgramFragmentState *, ShaderCache *sc);
 
-
-
-    void bindTexture(uint32_t slot, Allocation *);
-    void bindSampler(uint32_t slot, Sampler *);
-    void setType(uint32_t slot, const Element *, uint32_t dim);
-
-    void setEnvMode(uint32_t slot, RsTexEnvMode);
-    void setTexEnable(uint32_t slot, bool);
-
-
+    virtual void createShader();
+    virtual void loadShader(Context *rsc);
+    virtual void init(Context *rsc);
 
 protected:
-    // The difference between Textures and Constants is how they are accessed
-    // Texture lookups go though a sampler which in effect converts normalized
-    // coordinates into type specific.  Multiple samples may also be taken
-    // and filtered.
-    //
-    // Constants are strictly accessed by programetic loads.
-    ObjectBaseRef<Allocation> mTextures[MAX_TEXTURE];
-    ObjectBaseRef<Sampler> mSamplers[MAX_TEXTURE];
-    ObjectBaseRef<const Element> mTextureFormats[MAX_TEXTURE];
-    uint32_t mTextureDimensions[MAX_TEXTURE];
-
-
     // Hacks to create a program for now
+    uint32_t mTextureFormats[MAX_TEXTURE];
+    uint32_t mTextureDimensions[MAX_TEXTURE];
     RsTexEnvMode mEnvModes[MAX_TEXTURE];
     uint32_t mTextureEnableMask;
     bool mPointSpriteEnable;
diff --git a/libs/rs/rsProgramFragmentStore.cpp b/libs/rs/rsProgramFragmentStore.cpp
index de33d9c..8a2157f 100644
--- a/libs/rs/rsProgramFragmentStore.cpp
+++ b/libs/rs/rsProgramFragmentStore.cpp
@@ -24,8 +24,8 @@
 using namespace android::renderscript;
 
 
-ProgramFragmentStore::ProgramFragmentStore(Context *rsc, Element *in, Element *out) :
-    Program(rsc, in, out)
+ProgramFragmentStore::ProgramFragmentStore(Context *rsc) :
+    Program(rsc)
 {
     mAllocFile = __FILE__;
     mAllocLine = __LINE__;
@@ -83,10 +83,44 @@
     } else {
         glDisable(GL_DITHER);
     }
-
-
 }
 
+void ProgramFragmentStore::setupGL2(const Context *rsc, ProgramFragmentStoreState *state)
+{
+    if (state->mLast.get() == this) {
+        return;
+    }
+    state->mLast.set(this);
+
+    glColorMask(mColorRWriteEnable,
+                mColorGWriteEnable,
+                mColorBWriteEnable,
+                mColorAWriteEnable);
+    if (mBlendEnable) {
+        glEnable(GL_BLEND);
+        glBlendFunc(mBlendSrc, mBlendDst);
+    } else {
+        glDisable(GL_BLEND);
+    }
+
+    //LOGE("pfs  %i, %i, %x", mDepthWriteEnable, mDepthTestEnable, mDepthFunc);
+
+    glDepthMask(mDepthWriteEnable);
+    if(mDepthTestEnable || mDepthWriteEnable) {
+        glEnable(GL_DEPTH_TEST);
+        glDepthFunc(mDepthFunc);
+    } else {
+        glDisable(GL_DEPTH_TEST);
+    }
+
+    if (mDitherEnable) {
+        glEnable(GL_DITHER);
+    } else {
+        glDisable(GL_DITHER);
+    }
+}
+
+
 void ProgramFragmentStore::setDitherEnable(bool enable)
 {
     mDitherEnable = enable;
@@ -215,7 +249,7 @@
 
 void ProgramFragmentStoreState::init(Context *rsc, int32_t w, int32_t h)
 {
-    ProgramFragmentStore *pfs = new ProgramFragmentStore(rsc, NULL, NULL);
+    ProgramFragmentStore *pfs = new ProgramFragmentStore(rsc);
     mDefault.set(pfs);
 }
 
@@ -232,7 +266,7 @@
 void rsi_ProgramFragmentStoreBegin(Context * rsc, RsElement in, RsElement out)
 {
     delete rsc->mStateFragmentStore.mPFS;
-    rsc->mStateFragmentStore.mPFS = new ProgramFragmentStore(rsc, (Element *)in, (Element *)out);
+    rsc->mStateFragmentStore.mPFS = new ProgramFragmentStore(rsc);
 
 }
 
diff --git a/libs/rs/rsProgramFragmentStore.h b/libs/rs/rsProgramFragmentStore.h
index a344387..3412c99 100644
--- a/libs/rs/rsProgramFragmentStore.h
+++ b/libs/rs/rsProgramFragmentStore.h
@@ -28,10 +28,11 @@
 class ProgramFragmentStore : public Program
 {
 public:
-    ProgramFragmentStore(Context *, Element *in, Element *out);
+    ProgramFragmentStore(Context *);
     virtual ~ProgramFragmentStore();
 
     virtual void setupGL(const Context *, ProgramFragmentStoreState *);
+    virtual void setupGL2(const Context *, ProgramFragmentStoreState *);
 
     void setDepthFunc(RsDepthFunc);
     void setDepthMask(bool);
diff --git a/libs/rs/rsProgramRaster.cpp b/libs/rs/rsProgramRaster.cpp
index 51ae7cf..13887d1 100644
--- a/libs/rs/rsProgramRaster.cpp
+++ b/libs/rs/rsProgramRaster.cpp
@@ -25,12 +25,10 @@
 
 
 ProgramRaster::ProgramRaster(Context *rsc,
-                             Element *in,
-                             Element *out,
                              bool pointSmooth,
                              bool lineSmooth,
                              bool pointSprite) :
-    Program(rsc, in, out)
+    Program(rsc)
 {
     mAllocFile = __FILE__;
     mAllocLine = __LINE__;
@@ -86,6 +84,14 @@
     }
 }
 
+void ProgramRaster::setupGL2(const Context *rsc, ProgramRasterState *state)
+{
+    if (state->mLast.get() == this) {
+        return;
+    }
+    state->mLast.set(this);
+}
+
 
 
 ProgramRasterState::ProgramRasterState()
@@ -98,7 +104,7 @@
 
 void ProgramRasterState::init(Context *rsc, int32_t w, int32_t h)
 {
-    ProgramRaster *pr = new ProgramRaster(rsc, NULL, NULL, false, false, false);
+    ProgramRaster *pr = new ProgramRaster(rsc, false, false, false);
     mDefault.set(pr);
 }
 
@@ -118,8 +124,6 @@
                                       bool pointSprite)
 {
     ProgramRaster *pr = new ProgramRaster(rsc,
-                                          static_cast<Element *>(in),
-                                          static_cast<Element *>(out),
                                           pointSmooth,
                                           lineSmooth,
                                           pointSprite);
diff --git a/libs/rs/rsProgramRaster.h b/libs/rs/rsProgramRaster.h
index a6d5ba8..c3a9c90 100644
--- a/libs/rs/rsProgramRaster.h
+++ b/libs/rs/rsProgramRaster.h
@@ -29,14 +29,13 @@
 {
 public:
     ProgramRaster(Context *rsc,
-                  Element *in,
-                  Element *out,
                   bool pointSmooth,
                   bool lineSmooth,
                   bool pointSprite);
     virtual ~ProgramRaster();
 
     virtual void setupGL(const Context *, ProgramRasterState *);
+    virtual void setupGL2(const Context *, ProgramRasterState *);
 
     void setLineWidth(float w);
     void setPointSize(float s);
diff --git a/libs/rs/rsProgramVertex.cpp b/libs/rs/rsProgramVertex.cpp
index 68f589f..28f13d4 100644
--- a/libs/rs/rsProgramVertex.cpp
+++ b/libs/rs/rsProgramVertex.cpp
@@ -19,18 +19,34 @@
 
 #include <GLES/gl.h>
 #include <GLES/glext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
 
 using namespace android;
 using namespace android::renderscript;
 
 
-ProgramVertex::ProgramVertex(Context *rsc, Element *in, Element *out) :
-    Program(rsc, in, out)
+ProgramVertex::ProgramVertex(Context *rsc, bool texMat) :
+    Program(rsc)
+{
+    mAllocFile = __FILE__;
+    mAllocLine = __LINE__;
+    mTextureMatrixEnable = texMat;
+    mLightCount = 0;
+    init(rsc);
+}
+
+ProgramVertex::ProgramVertex(Context *rsc, const char * shaderText,
+                             uint32_t shaderLength, const uint32_t * params,
+                             uint32_t paramLength) :
+    Program(rsc, shaderText, shaderLength, params, paramLength)
 {
     mAllocFile = __FILE__;
     mAllocLine = __LINE__;
     mTextureMatrixEnable = false;
     mLightCount = 0;
+
+    init(rsc);
 }
 
 ProgramVertex::~ProgramVertex()
@@ -40,10 +56,10 @@
 static void logMatrix(const char *txt, const float *f)
 {
     LOGV("Matrix %s, %p", txt, f);
-    LOGV("%6.2f, %6.2f, %6.2f, %6.2f", f[0], f[4], f[8], f[12]);
-    LOGV("%6.2f, %6.2f, %6.2f, %6.2f", f[1], f[5], f[9], f[13]);
-    LOGV("%6.2f, %6.2f, %6.2f, %6.2f", f[2], f[6], f[10], f[14]);
-    LOGV("%6.2f, %6.2f, %6.2f, %6.2f", f[3], f[7], f[11], f[15]);
+    LOGV("%6.4f, %6.4f, %6.4f, %6.4f", f[0], f[4], f[8], f[12]);
+    LOGV("%6.4f, %6.4f, %6.4f, %6.4f", f[1], f[5], f[9], f[13]);
+    LOGV("%6.4f, %6.4f, %6.4f, %6.4f", f[2], f[6], f[10], f[14]);
+    LOGV("%6.4f, %6.4f, %6.4f, %6.4f", f[3], f[7], f[11], f[15]);
 }
 
 void ProgramVertex::setupGL(const Context *rsc, ProgramVertexState *state)
@@ -53,7 +69,7 @@
     }
     state->mLast.set(this);
 
-    const float *f = static_cast<const float *>(mConstants->getPtr());
+    const float *f = static_cast<const float *>(mConstants[0]->getPtr());
 
     glMatrixMode(GL_TEXTURE);
     if (mTextureMatrixEnable) {
@@ -92,6 +108,172 @@
     mDirty = false;
 }
 
+void ProgramVertex::loadShader(Context *rsc) {
+    Program::loadShader(rsc, GL_VERTEX_SHADER);
+}
+
+void ProgramVertex::createShader()
+{
+    mShader.setTo("");
+
+    mShader.append("varying vec4 varColor;\n");
+    mShader.append("varying vec4 varTex0;\n");
+
+    if (mUserShader.length() > 1) {
+        mShader.append("uniform mat4 ");
+        mShader.append(mUniformNames[0]);
+        mShader.append(";\n");
+
+        for (uint32_t ct=0; ct < mConstantCount; ct++) {
+            const Element *e = mConstantTypes[ct]->getElement();
+            for (uint32_t field=0; field < e->getFieldCount(); field++) {
+                const Element *f = e->getField(field);
+
+                // Cannot be complex
+                rsAssert(!f->getFieldCount());
+                switch(f->getComponent().getVectorSize()) {
+                case 1: mShader.append("uniform float UNI_"); break;
+                case 2: mShader.append("uniform vec2 UNI_"); break;
+                case 3: mShader.append("uniform vec3 UNI_"); break;
+                case 4: mShader.append("uniform vec4 UNI_"); break;
+                default:
+                    rsAssert(0);
+                }
+
+                mShader.append(e->getFieldName(field));
+                mShader.append(";\n");
+            }
+        }
+
+
+        for (uint32_t ct=0; ct < mInputCount; ct++) {
+            const Element *e = mInputElements[ct].get();
+            for (uint32_t field=0; field < e->getFieldCount(); field++) {
+                const Element *f = e->getField(field);
+
+                // Cannot be complex
+                rsAssert(!f->getFieldCount());
+                switch(f->getComponent().getVectorSize()) {
+                case 1: mShader.append("attribute float ATTRIB_"); break;
+                case 2: mShader.append("attribute vec2 ATTRIB_"); break;
+                case 3: mShader.append("attribute vec3 ATTRIB_"); break;
+                case 4: mShader.append("attribute vec4 ATTRIB_"); break;
+                default:
+                    rsAssert(0);
+                }
+
+                mShader.append(e->getFieldName(field));
+                mShader.append(";\n");
+            }
+        }
+        mShader.append(mUserShader);
+    } else {
+        mShader.append("attribute vec4 ATTRIB_LegacyPosition;\n");
+        mShader.append("attribute vec4 ATTRIB_LegacyColor;\n");
+        mShader.append("attribute vec3 ATTRIB_LegacyNormal;\n");
+        mShader.append("attribute float ATTRIB_LegacyPointSize;\n");
+        mShader.append("attribute vec4 ATTRIB_LegacyTexture;\n");
+
+        for (uint32_t ct=0; ct < mUniformCount; ct++) {
+            mShader.append("uniform mat4 ");
+            mShader.append(mUniformNames[ct]);
+            mShader.append(";\n");
+        }
+
+        mShader.append("void main() {\n");
+        mShader.append("  gl_Position = UNI_MVP * ATTRIB_LegacyPosition;\n");
+        mShader.append("  gl_PointSize = ATTRIB_LegacyPointSize;\n");
+
+        mShader.append("  varColor = ATTRIB_LegacyColor;\n");
+        if (mTextureMatrixEnable) {
+            mShader.append("  varTex0 = UNI_TexMatrix * ATTRIB_LegacyTexture;\n");
+        } else {
+            mShader.append("  varTex0 = ATTRIB_LegacyTexture;\n");
+        }
+        //mShader.append("  pos.x = pos.x / 480.0;\n");
+        //mShader.append("  pos.y = pos.y / 800.0;\n");
+        //mShader.append("  gl_Position = pos;\n");
+        mShader.append("}\n");
+    }
+}
+
+void ProgramVertex::setupGL2(const Context *rsc, ProgramVertexState *state, ShaderCache *sc)
+{
+    //LOGE("sgl2 vtx1 %x", glGetError());
+    if ((state->mLast.get() == this) && !mDirty) {
+        //return;
+    }
+
+    rsc->checkError("ProgramVertex::setupGL2 start");
+    glVertexAttrib4f(1, state->color[0], state->color[1], state->color[2], state->color[3]);
+
+    const float *f = static_cast<const float *>(mConstants[0]->getPtr());
+
+    Matrix mvp;
+    mvp.load(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET]);
+    Matrix t;
+    t.load(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET]);
+    mvp.multiply(&t);
+
+    glUniformMatrix4fv(sc->vtxUniformSlot(0), 1, GL_FALSE, mvp.m);
+    if (mTextureMatrixEnable) {
+        glUniformMatrix4fv(sc->vtxUniformSlot(1), 1, GL_FALSE,
+                           &f[RS_PROGRAM_VERTEX_TEXTURE_OFFSET]);
+    }
+
+    rsc->checkError("ProgramVertex::setupGL2 begin uniforms");
+    uint32_t uidx = 1;
+    for (uint32_t ct=0; ct < mConstantCount; ct++) {
+        Allocation *alloc = mConstants[ct+1].get();
+        if (!alloc) {
+            continue;
+        }
+
+        const uint8_t *data = static_cast<const uint8_t *>(alloc->getPtr());
+        const Element *e = mConstantTypes[ct]->getElement();
+        for (uint32_t field=0; field < e->getFieldCount(); field++) {
+            const Element *f = e->getField(field);
+            uint32_t offset = e->getFieldOffsetBytes(field);
+            int32_t slot = sc->vtxUniformSlot(uidx);
+
+            const float *fd = reinterpret_cast<const float *>(&data[offset]);
+
+            //LOGE("Uniform  slot=%i, offset=%i, constant=%i, field=%i, uidx=%i", slot, offset, ct, field, uidx);
+            if (slot >= 0) {
+                switch(f->getComponent().getVectorSize()) {
+                case 1:
+                    //LOGE("Uniform 1 = %f", fd[0]);
+                    glUniform1fv(slot, 1, fd);
+                    break;
+                case 2:
+                    //LOGE("Uniform 2 = %f %f", fd[0], fd[1]);
+                    glUniform2fv(slot, 1, fd);
+                    break;
+                case 3:
+                    //LOGE("Uniform 3 = %f %f %f", fd[0], fd[1], fd[2]);
+                    glUniform3fv(slot, 1, fd);
+                    break;
+                case 4:
+                    //LOGE("Uniform 4 = %f %f %f %f", fd[0], fd[1], fd[2], fd[3]);
+                    glUniform4fv(slot, 1, fd);
+                    break;
+                default:
+                    rsAssert(0);
+                }
+            }
+            uidx ++;
+        }
+    }
+
+    for (uint32_t ct=0; ct < mConstantCount; ct++) {
+        uint32_t glSlot = sc->vtxUniformSlot(ct + 1);
+
+    }
+
+    state->mLast.set(this);
+    rsc->checkError("ProgramVertex::setupGL2");
+}
+
 void ProgramVertex::addLight(const Light *l)
 {
     if (mLightCount < MAX_LIGHTS) {
@@ -102,60 +284,103 @@
 
 void ProgramVertex::setProjectionMatrix(const rsc_Matrix *m) const
 {
-    float *f = static_cast<float *>(mConstants->getPtr());
+    float *f = static_cast<float *>(mConstants[0]->getPtr());
     memcpy(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET], m, sizeof(rsc_Matrix));
     mDirty = true;
 }
 
 void ProgramVertex::setModelviewMatrix(const rsc_Matrix *m) const
 {
-    float *f = static_cast<float *>(mConstants->getPtr());
+    float *f = static_cast<float *>(mConstants[0]->getPtr());
     memcpy(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET], m, sizeof(rsc_Matrix));
     mDirty = true;
 }
 
 void ProgramVertex::setTextureMatrix(const rsc_Matrix *m) const
 {
-    float *f = static_cast<float *>(mConstants->getPtr());
+    float *f = static_cast<float *>(mConstants[0]->getPtr());
     memcpy(&f[RS_PROGRAM_VERTEX_TEXTURE_OFFSET], m, sizeof(rsc_Matrix));
     mDirty = true;
 }
 
 void ProgramVertex::transformToScreen(const Context *rsc, float *v4out, const float *v3in) const
 {
-    float *f = static_cast<float *>(mConstants->getPtr());
+    float *f = static_cast<float *>(mConstants[0]->getPtr());
     Matrix mvp;
     mvp.loadMultiply((Matrix *)&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET],
                      (Matrix *)&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET]);
     mvp.vectorMultiply(v4out, v3in);
 }
 
+void ProgramVertex::initAddUserElement(const Element *e, String8 *names, uint32_t *count, const char *prefix)
+{
+    rsAssert(e->getFieldCount());
+    for (uint32_t ct=0; ct < e->getFieldCount(); ct++) {
+        const Element *ce = e->getField(ct);
+        if (ce->getFieldCount()) {
+            initAddUserElement(ce, names, count, prefix);
+        } else {
+            String8 tmp(prefix);
+            tmp.append(e->getFieldName(ct));
+            names[*count].setTo(tmp.string());
+            (*count)++;
+        }
+    }
+}
+
+
+void ProgramVertex::init(Context *rsc)
+{
+    mAttribCount = 0;
+    if (mUserShader.size() > 0) {
+        for (uint32_t ct=0; ct < mInputCount; ct++) {
+            initAddUserElement(mInputElements[ct].get(), mAttribNames, &mAttribCount, "ATTRIB_");
+        }
+
+        mUniformCount = 1;
+        mUniformNames[0].setTo("UNI_MVP");
+        for (uint32_t ct=0; ct < mConstantCount; ct++) {
+            initAddUserElement(mConstantTypes[ct]->getElement(), mUniformNames, &mUniformCount, "UNI_");
+        }
+    } else {
+        mUniformCount = 2;
+        mUniformNames[0].setTo("UNI_MVP");
+        mUniformNames[1].setTo("UNI_TexMatrix");
+    }
+
+    createShader();
+}
+
+
+///////////////////////////////////////////////////////////////////////
+
 ProgramVertexState::ProgramVertexState()
 {
-    mPV = NULL;
 }
 
 ProgramVertexState::~ProgramVertexState()
 {
-    delete mPV;
 }
 
 void ProgramVertexState::init(Context *rsc, int32_t w, int32_t h)
 {
-    rsi_ElementBegin(rsc);
-    rsi_ElementAdd(rsc, RS_KIND_USER, RS_TYPE_FLOAT, false, 32, NULL);
-    RsElement e = rsi_ElementCreate(rsc);
+    RsElement e = Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1);
 
     rsi_TypeBegin(rsc, e);
     rsi_TypeAdd(rsc, RS_DIMENSION_X, 48);
     mAllocType.set((Type *)rsi_TypeCreate(rsc));
 
-    ProgramVertex *pv = new ProgramVertex(rsc, NULL, NULL);
+    ProgramVertex *pv = new ProgramVertex(rsc, false);
     Allocation *alloc = (Allocation *)rsi_AllocationCreateTyped(rsc, mAllocType.get());
     mDefaultAlloc.set(alloc);
     mDefault.set(pv);
+    pv->init(rsc);
+    pv->bindAllocation(alloc, 0);
 
-    pv->bindAllocation(alloc);
+    color[0] = 1.f;
+    color[1] = 1.f;
+    color[2] = 1.f;
+    color[3] = 1.f;
 
     updateSize(rsc, w, h);
 }
@@ -176,42 +401,27 @@
     mDefault.clear();
     mAllocType.clear();
     mLast.clear();
-    delete mPV;
-    mPV = NULL;
 }
 
 
 namespace android {
 namespace renderscript {
 
-void rsi_ProgramVertexBegin(Context *rsc, RsElement in, RsElement out)
-{
-    delete rsc->mStateVertex.mPV;
-    rsc->mStateVertex.mPV = new ProgramVertex(rsc, (Element *)in, (Element *)out);
-}
 
-RsProgramVertex rsi_ProgramVertexCreate(Context *rsc)
+RsProgramVertex rsi_ProgramVertexCreate(Context *rsc, bool texMat)
 {
-    ProgramVertex *pv = rsc->mStateVertex.mPV;
+    ProgramVertex *pv = new ProgramVertex(rsc, texMat);
     pv->incUserRef();
-    rsc->mStateVertex.mPV = 0;
     return pv;
 }
 
-void rsi_ProgramVertexBindAllocation(Context *rsc, RsProgramVertex vpgm, RsAllocation constants)
+RsProgramVertex rsi_ProgramVertexCreate2(Context *rsc, const char * shaderText,
+                             uint32_t shaderLength, const uint32_t * params,
+                             uint32_t paramLength)
 {
-    ProgramVertex *pv = static_cast<ProgramVertex *>(vpgm);
-    pv->bindAllocation(static_cast<Allocation *>(constants));
-}
-
-void rsi_ProgramVertexSetTextureMatrixEnable(Context *rsc, bool enable)
-{
-    rsc->mStateVertex.mPV->setTextureMatrixEnable(enable);
-}
-
-void rsi_ProgramVertexAddLight(Context *rsc, RsLight light)
-{
-    rsc->mStateVertex.mPV->addLight(static_cast<const Light *>(light));
+    ProgramVertex *pv = new ProgramVertex(rsc, shaderText, shaderLength, params, paramLength);
+    pv->incUserRef();
+    return pv;
 }
 
 
diff --git a/libs/rs/rsProgramVertex.h b/libs/rs/rsProgramVertex.h
index a97ba38..28554cc 100644
--- a/libs/rs/rsProgramVertex.h
+++ b/libs/rs/rsProgramVertex.h
@@ -30,10 +30,13 @@
 public:
     const static uint32_t MAX_LIGHTS = 8;
 
-    ProgramVertex(Context *, Element *in, Element *out);
+    ProgramVertex(Context *,const char * shaderText, uint32_t shaderLength,
+                  const uint32_t * params, uint32_t paramLength);
+    ProgramVertex(Context *, bool texMat);
     virtual ~ProgramVertex();
 
     virtual void setupGL(const Context *rsc, ProgramVertexState *state);
+    virtual void setupGL2(const Context *rsc, ProgramVertexState *state, ShaderCache *sc);
 
 
     void setTextureMatrixEnable(bool e) {mTextureMatrixEnable = e;}
@@ -45,6 +48,10 @@
 
     void transformToScreen(const Context *, float *v4out, const float *v3in) const;
 
+    virtual void createShader();
+    virtual void loadShader(Context *);
+    virtual void init(Context *);
+
 
 protected:
     uint32_t mLightCount;
@@ -52,6 +59,9 @@
 
     // Hacks to create a program for now
     bool mTextureMatrixEnable;
+
+private:
+    void initAddUserElement(const Element *e, String8 *names, uint32_t *count, const char *prefix);
 };
 
 
@@ -71,11 +81,8 @@
 
     ObjectBaseRef<Type> mAllocType;
 
-    ProgramVertex *mPV;
 
-    //ObjectBaseRef<Type> mTextureTypes[ProgramFragment::MAX_TEXTURE];
-
-
+    float color[4];
 };
 
 
diff --git a/libs/rs/rsSampler.cpp b/libs/rs/rsSampler.cpp
index b793750..7552d54 100644
--- a/libs/rs/rsSampler.cpp
+++ b/libs/rs/rsSampler.cpp
@@ -53,7 +53,7 @@
 {
 }
 
-void Sampler::setupGL()
+void Sampler::setupGL(const Context *rsc)
 {
     GLenum trans[] = {
         GL_NEAREST, //RS_SAMPLER_NEAREST,
@@ -64,12 +64,12 @@
 
     };
 
-
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, trans[mMinFilter]);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, trans[mMagFilter]);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, trans[mWrapS]);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, trans[mWrapT]);
 
+    rsc->checkError("ProgramFragment::setupGL2 tex env");
 }
 
 void Sampler::bindToContext(SamplerState *ss, uint32_t slot)
@@ -84,18 +84,18 @@
     mBoundSlot = -1;
     ss->mSamplers[slot].clear();
 }
-
+/*
 void SamplerState::setupGL()
 {
     for (uint32_t ct=0; ct < RS_MAX_SAMPLER_SLOT; ct++) {
         Sampler *s = mSamplers[ct].get();
         if (s) {
-            s->setupGL();
+            s->setupGL(rsc);
         } else {
             glBindTexture(GL_TEXTURE_2D, 0);
         }
     }
-}
+}*/
 
 ////////////////////////////////
 
diff --git a/libs/rs/rsSampler.h b/libs/rs/rsSampler.h
index ccf9b4d..9e20a2f 100644
--- a/libs/rs/rsSampler.h
+++ b/libs/rs/rsSampler.h
@@ -41,7 +41,7 @@
     virtual ~Sampler();
 
     void bind(Allocation *);
-    void setupGL();
+    void setupGL(const Context *);
 
     void bindToContext(SamplerState *, uint32_t slot);
     void unbindFromContext(SamplerState *);
@@ -74,7 +74,7 @@
 
     ObjectBaseRef<Sampler> mSamplers[RS_MAX_SAMPLER_SLOT];
 
-    void setupGL();
+    //void setupGL();
 
 };
 
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index f11b862..b7e0b86 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -137,7 +137,6 @@
 
     rsc->appendNameDefines(&tmp);
     appendDecls(&tmp);
-    rsc->appendVarDefines(&tmp);
     appendVarDefines(rsc, &tmp);
     appendTypes(rsc, &tmp);
     tmp.append("#line 1\n");
@@ -270,12 +269,12 @@
 static void appendElementBody(String8 *s, const Element *e)
 {
     s->append(" {\n");
-    for (size_t ct2=0; ct2 < e->getComponentCount(); ct2++) {
-        const Component *c = e->getComponent(ct2);
+    for (size_t ct2=0; ct2 < e->getFieldCount(); ct2++) {
+        const Element *c = e->getField(ct2);
         s->append("    ");
         s->append(c->getCType());
         s->append(" ");
-        s->append(c->getComponentName());
+        s->append(e->getFieldName(ct2));
         s->append(";\n");
     }
     s->append("}");
@@ -311,9 +310,15 @@
     char buf[256];
     String8 tmp;
 
-    str->append("struct vec2_s {float x; float y;};");
-    str->append("struct vec3_s {float x; float y; float z;};");
-    str->append("struct vec4_s {float x; float y; float z; float w;};");
+    str->append("struct vecF32_2_s {float x; float y;};\n");
+    str->append("struct vecF32_3_s {float x; float y; float z;};\n");
+    str->append("struct vecF32_4_s {float x; float y; float z; float w;};\n");
+    str->append("struct vecU8_4_s {char r; char g; char b; char a;};\n");
+    str->append("#define vecF32_2_t struct vecF32_2_s\n");
+    str->append("#define vecF32_3_t struct vecF32_3_s\n");
+    str->append("#define vecF32_4_t struct vecF32_4_s\n");
+    str->append("#define vecU8_4_t struct vecU8_4_s\n");
+    str->append("#define vecI8_4_t struct vecU8_4_s\n");
 
     for (size_t ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
         const Type *t = mConstantBufferTypes[ct].get();
@@ -321,11 +326,12 @@
             continue;
         }
         const Element *e = t->getElement();
-        if (e->getName() && (e->getComponentCount() > 1)) {
+        if (e->getName() && (e->getFieldCount() > 1)) {
             String8 s("struct struct_");
             s.append(e->getName());
-            appendElementBody(&s, e);
+            s.append(e->getCStructBody());
             s.append(";\n");
+
             s.append("#define ");
             s.append(e->getName());
             s.append("_t struct struct_");
@@ -337,45 +343,25 @@
             str->append(s);
         }
 
-        if (t->getName()) {
-            for (size_t ct2=0; ct2 < e->getComponentCount(); ct2++) {
-                const Component *c = e->getComponent(ct2);
-                tmp.setTo("#define OFFSETOF_");
-                tmp.append(t->getName());
-                tmp.append("_");
-                tmp.append(c->getComponentName());
-                sprintf(buf, " %i\n", ct2);
-                tmp.append(buf);
-                if (rsc->props.mLogScripts) {
-                    LOGV(tmp);
-                }
-                str->append(tmp);
-            }
-        }
-
         if (mSlotNames[ct].length() > 0) {
             String8 s;
-            if (e->getComponentCount() > 1) {
-                if (e->getName()) {
-                    // Use the named struct
-                    s.setTo(e->getName());
-                    s.append("_t *");
-                } else {
-                    // create an struct named from the slot.
-                    s.setTo("struct ");
-                    s.append(mSlotNames[ct]);
-                    s.append("_s");
-                    appendElementBody(&s, e);
-                    s.append(";\n");
-                    s.append("struct ");
-                    s.append(mSlotNames[ct]);
-                    s.append("_s * ");
-                }
+            if (e->getName()) {
+                // Use the named struct
+                s.setTo(e->getName());
             } else {
-                // Just make an array
-                s.setTo(e->getComponent(0)->getCType());
-                s.append("_t *");
+                // create an struct named from the slot.
+                s.setTo("struct ");
+                s.append(mSlotNames[ct]);
+                s.append("_s");
+                s.append(e->getCStructBody());
+                //appendElementBody(&s, e);
+                s.append(";\n");
+                s.append("struct ");
+                s.append(mSlotNames[ct]);
+                s.append("_s");
             }
+
+            s.append(" * ");
             s.append(mSlotNames[ct]);
             s.append(";\n");
             if (rsc->props.mLogScripts) {
diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp
index de8df39..61bb16f 100644
--- a/libs/rs/rsScriptC_Lib.cpp
+++ b/libs/rs/rsScriptC_Lib.cpp
@@ -26,6 +26,8 @@
 
 #include <GLES/gl.h>
 #include <GLES/glext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
 
 #include <time.h>
 
@@ -102,8 +104,9 @@
 
 static void SC_updateSimpleMesh(RsSimpleMesh mesh)
 {
+    GET_TLS();
     SimpleMesh *sm = static_cast<SimpleMesh *>(mesh);
-    sm->uploadAll();
+    sm->uploadAll(rsc);
 }
 
 static uint32_t SC_loadU32(uint32_t bank, uint32_t offset)
@@ -616,20 +619,20 @@
 static void SC_bindTexture(RsProgramFragment vpf, uint32_t slot, RsAllocation va)
 {
     GET_TLS();
-    rsi_ProgramFragmentBindTexture(rsc,
-                                   static_cast<ProgramFragment *>(vpf),
-                                   slot,
-                                   static_cast<Allocation *>(va));
+    rsi_ProgramBindTexture(rsc,
+                           static_cast<ProgramFragment *>(vpf),
+                           slot,
+                           static_cast<Allocation *>(va));
 
 }
 
 static void SC_bindSampler(RsProgramFragment vpf, uint32_t slot, RsSampler vs)
 {
     GET_TLS();
-    rsi_ProgramFragmentBindSampler(rsc,
-                                   static_cast<ProgramFragment *>(vpf),
-                                   slot,
-                                   static_cast<Sampler *>(vs));
+    rsi_ProgramBindSampler(rsc,
+                           static_cast<ProgramFragment *>(vpf),
+                           slot,
+                           static_cast<Sampler *>(vs));
 
 }
 
@@ -683,13 +686,13 @@
     rsc->setupCheck();
 
     float vtx[] = { x1, y1, z1, x2, y2, z2 };
-
-    glBindBuffer(GL_ARRAY_BUFFER, 0);
-    glEnableClientState(GL_VERTEX_ARRAY);
-    glVertexPointer(3, GL_FLOAT, 0, vtx);
-
-    glDisableClientState(GL_NORMAL_ARRAY);
-    glDisableClientState(GL_COLOR_ARRAY);
+    VertexArray va;
+    va.addLegacy(GL_FLOAT, 3, 12, RS_KIND_POSITION, false, (uint32_t)vtx);
+    if (rsc->checkVersion2_0()) {
+        va.setupGL2(rsc, &rsc->mStateVertexArray, &rsc->mShaderCache);
+    } else {
+        va.setupGL(rsc, &rsc->mStateVertexArray);
+    }
 
     glDrawArrays(GL_LINES, 0, 2);
 }
@@ -701,12 +704,13 @@
 
     float vtx[] = { x, y, z };
 
-    glBindBuffer(GL_ARRAY_BUFFER, 0);
-    glEnableClientState(GL_VERTEX_ARRAY);
-    glVertexPointer(3, GL_FLOAT, 0, vtx);
-
-    glDisableClientState(GL_NORMAL_ARRAY);
-    glDisableClientState(GL_COLOR_ARRAY);
+    VertexArray va;
+    va.addLegacy(GL_FLOAT, 3, 12, RS_KIND_POSITION, false, (uint32_t)vtx);
+    if (rsc->checkVersion2_0()) {
+        va.setupGL2(rsc, &rsc->mStateVertexArray, &rsc->mShaderCache);
+    } else {
+        va.setupGL(rsc, &rsc->mStateVertexArray);
+    }
 
     glDrawArrays(GL_POINTS, 0, 1);
 }
@@ -721,6 +725,7 @@
                                  float u4, float v4)
 {
     GET_TLS();
+    rsc->setupCheck();
 
     //LOGE("Quad");
     //LOGE("%4.2f, %4.2f, %4.2f", x1, y1, z1);
@@ -731,26 +736,15 @@
     float vtx[] = {x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4};
     const float tex[] = {u1,v1, u2,v2, u3,v3, u4,v4};
 
-    rsc->setupCheck();
+    VertexArray va;
+    va.addLegacy(GL_FLOAT, 3, 12, RS_KIND_POSITION, false, (uint32_t)vtx);
+    va.addLegacy(GL_FLOAT, 2, 8, RS_KIND_TEXTURE, false, (uint32_t)tex);
+    if (rsc->checkVersion2_0()) {
+        va.setupGL2(rsc, &rsc->mStateVertexArray, &rsc->mShaderCache);
+    } else {
+        va.setupGL(rsc, &rsc->mStateVertexArray);
+    }
 
-    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);
 }
@@ -769,29 +763,46 @@
 static void SC_drawSpriteScreenspace(float x, float y, float z, float w, float h)
 {
     GET_TLS();
-    rsc->setupCheck();
+    ObjectBaseRef<const ProgramVertex> tmp(rsc->getVertex());
+    rsc->setVertex(rsc->getDefaultProgramVertex());
+    //rsc->setupCheck();
 
-    GLint crop[4] = {0, h, w, -h};
-    glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
-    glDrawTexfOES(x, y, z, w, h);
+    //GLint crop[4] = {0, h, w, -h};
+
+    float sh = rsc->getHeight();
+
+    SC_drawQuad(x,   sh - y,     z,
+                x+w, sh - y,     z,
+                x+w, sh - (y+h), z,
+                x,   sh - (y+h), z);
+    rsc->setVertex((ProgramVertex *)tmp.get());
 }
 
 static void SC_drawSpriteScreenspaceCropped(float x, float y, float z, float w, float h,
         float cx0, float cy0, float cx1, float cy1)
 {
     GET_TLS();
-    rsc->setupCheck();
+    ObjectBaseRef<const ProgramVertex> tmp(rsc->getVertex());
+    rsc->setVertex(rsc->getDefaultProgramVertex());
 
-    GLint crop[4] = {cx0, cy0, cx1, cy1};
-    glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
-    glDrawTexfOES(x, y, z, w, h);
+    float tw = rsc->getFragment()->getTexture(0)->getType()->getDimY();
+    float th = rsc->getFragment()->getTexture(0)->getType()->getDimX();
+    float sh = rsc->getHeight();
+    float u0 = cx0 / tw;
+    float u1 = (cx1 + cx0) / tw;
+    float v0 = cy0 / th;
+    float v1 = (cy1 + cy0) / th;
+
+    SC_drawQuadTexCoords(x,   sh - y,     z, u0, v0,
+                         x+w, sh - y,     z, u1, v0,
+                         x+w, sh - (y+h), z, u1, v1,
+                         x,   sh - (y+h), z, u0, v1);
+    rsc->setVertex((ProgramVertex *)tmp.get());
 }
 
 static void SC_drawSprite(float x, float y, float z, float w, float h)
 {
     GET_TLS();
-    rsc->setupCheck();
-
     float vin[3] = {x, y, z};
     float vout[4];
 
@@ -813,9 +824,8 @@
     //LOGE("ds  out2 %f %f %f", vout[0], vout[1], vout[2]);
 
     // U, V, W, H
-    GLint crop[4] = {0, h, w, -h};
-    glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
-    glDrawTexiOES(vout[0], vout[1], 0/*vout[2]*/, w, h);
+    SC_drawSpriteScreenspace(vout[0], vout[1], z, h, w);
+    //rsc->setupCheck();
 }
 
 
@@ -833,7 +843,7 @@
     GET_TLS();
     SimpleMesh *sm = static_cast<SimpleMesh *>(vsm);
     rsc->setupCheck();
-    sm->render();
+    sm->render(rsc);
 }
 
 static void SC_drawSimpleMeshRange(RsSimpleMesh vsm, uint32_t start, uint32_t len)
@@ -841,7 +851,7 @@
     GET_TLS();
     SimpleMesh *sm = static_cast<SimpleMesh *>(vsm);
     rsc->setupCheck();
-    sm->renderRange(start, len);
+    sm->renderRange(rsc, start, len);
 }
 
 
@@ -851,7 +861,14 @@
 
 static void SC_color(float r, float g, float b, float a)
 {
-    glColor4f(r, g, b, a);
+    GET_TLS();
+    rsc->mStateVertex.color[0] = r;
+    rsc->mStateVertex.color[1] = g;
+    rsc->mStateVertex.color[2] = b;
+    rsc->mStateVertex.color[3] = a;
+    if (!rsc->checkVersion2_0()) {
+        glColor4f(r, g, b, a);
+    }
 }
 
 static void SC_ambient(float r, float g, float b, float a)
@@ -956,9 +973,14 @@
 
 static void SC_hsb(float h, float s, float b, float a)
 {
+    GET_TLS();
     float rgb[3];
     SC_hsbToRgb(h, s, b, rgb);
-    glColor4f(rgb[0], rgb[1], rgb[2], a);
+    if (rsc->checkVersion2_0()) {
+        glVertexAttrib4f(1, rgb[0], rgb[1], rgb[2], a);
+    } else {
+        glColor4f(rgb[0], rgb[1], rgb[2], a);
+    }
 }
 
 static void SC_uploadToTexture(RsAllocation va, uint32_t baseMipLevel)
@@ -973,6 +995,13 @@
     rsi_AllocationUploadToBufferObject(rsc, va);
 }
 
+static void SC_syncToGL(RsAllocation va)
+{
+    GET_TLS();
+    Allocation *a = static_cast<Allocation *>(va);
+
+}
+
 static void SC_ClearColor(float r, float g, float b, float a)
 {
     //LOGE("c %f %f %f %f", r, g, b, a);
@@ -1221,33 +1250,33 @@
 
     // vec3
     { "vec3Norm", (void *)&SC_vec3Norm,
-        "void", "(struct vec3_s *)" },
+        "void", "(struct vecF32_3_s *)" },
     { "vec3Length", (void *)&SC_vec3Length,
-        "float", "(struct vec3_s *)" },
+        "float", "(struct vecF32_3_s *)" },
     { "vec3Add", (void *)&SC_vec3Add,
-        "void", "(struct vec3_s *dest, struct vec3_s *lhs, struct vec3_s *rhs)" },
+        "void", "(struct vecF32_3_s *dest, struct vecF32_3_s *lhs, struct vecF32_3_s *rhs)" },
     { "vec3Sub", (void *)&SC_vec3Sub,
-        "void", "(struct vec3_s *dest, struct vec3_s *lhs, struct vec3_s *rhs)" },
+        "void", "(struct vecF32_3_s *dest, struct vecF32_3_s *lhs, struct vecF32_3_s *rhs)" },
     { "vec3Cross", (void *)&SC_vec3Cross,
-        "void", "(struct vec3_s *dest, struct vec3_s *lhs, struct vec3_s *rhs)" },
+        "void", "(struct vecF32_3_s *dest, struct vecF32_3_s *lhs, struct vecF32_3_s *rhs)" },
     { "vec3Dot", (void *)&SC_vec3Dot,
-        "float", "(struct vec3_s *lhs, struct vec3_s *rhs)" },
+        "float", "(struct vecF32_3_s *lhs, struct vecF32_3_s *rhs)" },
     { "vec3Scale", (void *)&SC_vec3Scale,
-        "void", "(struct vec3_s *lhs, float scale)" },
+        "void", "(struct vecF32_3_s *lhs, float scale)" },
 
     // vec4
     { "vec4Norm", (void *)&SC_vec4Norm,
-        "void", "(struct vec4_s *)" },
+        "void", "(struct vecF32_4_s *)" },
     { "vec4Length", (void *)&SC_vec4Length,
-        "float", "(struct vec4_s *)" },
+        "float", "(struct vecF32_4_s *)" },
     { "vec4Add", (void *)&SC_vec4Add,
-        "void", "(struct vec4_s *dest, struct vec4_s *lhs, struct vec4_s *rhs)" },
+        "void", "(struct vecF32_4_s *dest, struct vecF32_4_s *lhs, struct vecF32_4_s *rhs)" },
     { "vec4Sub", (void *)&SC_vec4Sub,
-        "void", "(struct vec4_s *dest, struct vec4_s *lhs, struct vec4_s *rhs)" },
+        "void", "(struct vecF32_4_s *dest, struct vecF32_4_s *lhs, struct vecF32_4_s *rhs)" },
     { "vec4Dot", (void *)&SC_vec4Dot,
-        "float", "(struct vec4_s *lhs, struct vec4_s *rhs)" },
+        "float", "(struct vecF32_4_s *lhs, struct vecF32_4_s *rhs)" },
     { "vec4Scale", (void *)&SC_vec4Scale,
-        "void", "(struct vec4_s *lhs, float scale)" },
+        "void", "(struct vecF32_4_s *lhs, float scale)" },
 
     // context
     { "bindProgramFragment", (void *)&SC_bindProgramFragment,
@@ -1323,6 +1352,9 @@
     { "uploadToBufferObject", (void *)&SC_uploadToBufferObject,
         "void", "(int)" },
 
+    { "syncToGL", (void *)&SC_syncToGL,
+        "void", "(int)" },
+
     { "colorFloatRGBAtoUNorm8", (void *)&SC_colorFloatRGBAtoUNorm8,
         "int", "(float, float, float, float)" },
     { "colorFloatRGBto565", (void *)&SC_colorFloatRGBAto565,
diff --git a/libs/rs/rsShaderCache.cpp b/libs/rs/rsShaderCache.cpp
new file mode 100644
index 0000000..3a1f370
--- /dev/null
+++ b/libs/rs/rsShaderCache.cpp
@@ -0,0 +1,167 @@
+/*
+ * 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.
+ */
+
+#include "rsContext.h"
+
+#include <GLES/gl.h>
+#include <GLES2/gl2.h>
+
+using namespace android;
+using namespace android::renderscript;
+
+
+ShaderCache::ShaderCache()
+{
+    mEntryCount = 0;
+    mEntryAllocationCount = 16;
+    mEntries = (entry_t *)calloc(mEntryAllocationCount, sizeof(entry_t));
+}
+
+ShaderCache::~ShaderCache()
+{
+    for (uint32_t ct=0; ct < mEntryCount; ct++) {
+        glDeleteProgram(mEntries[ct].program);
+    }
+
+    mEntryCount = 0;
+    mEntryAllocationCount = 0;
+    free(mEntries);
+}
+
+bool ShaderCache::lookup(Context *rsc, ProgramVertex *vtx, ProgramFragment *frag)
+{
+    if (!vtx->getShaderID()) {
+        vtx->loadShader(rsc);
+    }
+    if (!frag->getShaderID()) {
+        frag->loadShader(rsc);
+    }
+    //LOGV("ShaderCache lookup  vtx %i, frag %i", vtx->getShaderID(), frag->getShaderID());
+
+    for (uint32_t ct=0; ct < mEntryCount; ct++) {
+        if ((mEntries[ct].vtx == vtx->getShaderID()) &&
+            (mEntries[ct].frag == frag->getShaderID())) {
+
+            //LOGV("SC using program %i", mEntries[ct].program);
+            glUseProgram(mEntries[ct].program);
+            mCurrent = &mEntries[ct];
+            //LOGV("ShaderCache hit, using %i", ct);
+            rsc->checkError("ShaderCache::lookup (hit)");
+            return true;
+        }
+    }
+    // Not in cache, add it.
+
+    if (mEntryAllocationCount == mEntryCount) {
+        // Out of space, make some.
+        mEntryAllocationCount *= 2;
+        entry_t *e = (entry_t *)calloc(mEntryAllocationCount, sizeof(entry_t));
+        if (!e) {
+            LOGE("Out of memory for ShaderCache::lookup");
+            return false;
+        }
+        memcpy(e, mEntries, sizeof(entry_t) * mEntryCount);
+        free(mEntries);
+        mEntries = e;
+    }
+
+    //LOGV("ShaderCache miss, using %i", mEntryCount);
+    //LOGE("e0 %x", glGetError());
+
+    entry_t *e = &mEntries[mEntryCount];
+    mCurrent = e;
+    e->vtx = vtx->getShaderID();
+    e->frag = frag->getShaderID();
+    e->program = glCreateProgram();
+    e->mUserVertexProgram = vtx->isUserProgram();
+    if (mEntries[mEntryCount].program) {
+        GLuint pgm = e->program;
+        glAttachShader(pgm, vtx->getShaderID());
+        //LOGE("e1 %x", glGetError());
+        glAttachShader(pgm, frag->getShaderID());
+
+        if (!vtx->isUserProgram()) {
+            glBindAttribLocation(pgm, 0, "ATTRIB_LegacyPosition");
+            glBindAttribLocation(pgm, 1, "ATTRIB_LegacyColor");
+            glBindAttribLocation(pgm, 2, "ATTRIB_LegacyNormal");
+            glBindAttribLocation(pgm, 3, "ATTRIB_LegacyPointSize");
+            glBindAttribLocation(pgm, 4, "ATTRIB_LegacyTexture");
+            e->mVtxAttribSlots[RS_KIND_POSITION] = 0;
+            e->mVtxAttribSlots[RS_KIND_COLOR] = 1;
+            e->mVtxAttribSlots[RS_KIND_NORMAL] = 2;
+            e->mVtxAttribSlots[RS_KIND_POINT_SIZE] = 3;
+            e->mVtxAttribSlots[RS_KIND_TEXTURE] = 4;
+        }
+
+        //LOGE("e2 %x", glGetError());
+        glLinkProgram(pgm);
+        //LOGE("e3 %x", glGetError());
+        GLint linkStatus = GL_FALSE;
+        glGetProgramiv(pgm, GL_LINK_STATUS, &linkStatus);
+        if (linkStatus != GL_TRUE) {
+            GLint bufLength = 0;
+            glGetProgramiv(pgm, GL_INFO_LOG_LENGTH, &bufLength);
+            if (bufLength) {
+                char* buf = (char*) malloc(bufLength);
+                if (buf) {
+                    glGetProgramInfoLog(pgm, bufLength, NULL, buf);
+                    LOGE("Could not link program:\n%s\n", buf);
+                    free(buf);
+                }
+            }
+            glDeleteProgram(pgm);
+        }
+        if (vtx->isUserProgram()) {
+            for (uint32_t ct=0; ct < vtx->getAttribCount(); ct++) {
+                e->mVtxAttribSlots[ct] = glGetAttribLocation(pgm, vtx->getAttribName(ct));
+                if (rsc->props.mLogShaders) {
+                    LOGV("vtx A %i, %s = %d\n", ct, vtx->getAttribName(ct).string(), e->mVtxAttribSlots[ct]);
+                }
+            }
+        }
+        for (uint32_t ct=0; ct < vtx->getUniformCount(); ct++) {
+            e->mVtxUniformSlots[ct] = glGetUniformLocation(pgm, vtx->getUniformName(ct));
+            if (rsc->props.mLogShaders) {
+                LOGV("vtx U, %s = %d\n", vtx->getUniformName(ct).string(), e->mVtxUniformSlots[ct]);
+            }
+        }
+        for (uint32_t ct=0; ct < frag->getUniformCount(); ct++) {
+            e->mFragUniformSlots[ct] = glGetUniformLocation(pgm, frag->getUniformName(ct));
+            if (rsc->props.mLogShaders) {
+                LOGV("frag U, %s = %d\n", frag->getUniformName(ct).string(), e->mFragUniformSlots[ct]);
+            }
+        }
+    }
+
+    //LOGV("SC made program %i", e->program);
+    glUseProgram(e->program);
+    mEntryCount++;
+    rsc->checkError("ShaderCache::lookup (miss)");
+    return true;
+}
+
+void ShaderCache::cleanupVertex(uint32_t id)
+{
+}
+
+void ShaderCache::cleanupFragment(uint32_t id)
+{
+}
+
+void ShaderCache::cleanupAll()
+{
+}
+
diff --git a/libs/rs/rsShaderCache.h b/libs/rs/rsShaderCache.h
new file mode 100644
index 0000000..7aa8183
--- /dev/null
+++ b/libs/rs/rsShaderCache.h
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_SHADER_CACHE_H
+#define ANDROID_SHADER_CACHE_H
+
+
+#include "rsObjectBase.h"
+#include "rsVertexArray.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+
+// An element is a group of Components that occupies one cell in a structure.
+class ShaderCache
+{
+public:
+    ShaderCache();
+    virtual ~ShaderCache();
+
+    bool lookup(Context *rsc, ProgramVertex *, ProgramFragment *);
+
+    void cleanupVertex(uint32_t id);
+    void cleanupFragment(uint32_t id);
+
+    void cleanupAll();
+
+    int32_t vtxAttribSlot(uint32_t a) const {return mCurrent->mVtxAttribSlots[a];}
+    int32_t vtxUniformSlot(uint32_t a) const {return mCurrent->mVtxUniformSlots[a];}
+    int32_t fragAttribSlot(uint32_t a) const {return mCurrent->mFragAttribSlots[a];}
+    int32_t fragUniformSlot(uint32_t a) const {return mCurrent->mFragUniformSlots[a];}
+    bool isUserVertexProgram() const {return mCurrent->mUserVertexProgram;}
+
+protected:
+    typedef struct {
+        uint32_t vtx;
+        uint32_t frag;
+        uint32_t program;
+        int32_t mVtxAttribSlots[Program::MAX_ATTRIBS];
+        int32_t mVtxUniformSlots[Program::MAX_UNIFORMS];
+        int32_t mFragAttribSlots[Program::MAX_ATTRIBS];
+        int32_t mFragUniformSlots[Program::MAX_UNIFORMS];
+        bool mUserVertexProgram;
+    } entry_t;
+    entry_t *mEntries;
+    entry_t *mCurrent;
+
+    uint32_t mEntryCount;
+    uint32_t mEntryAllocationCount;
+
+};
+
+
+
+}
+}
+#endif //ANDROID_SHADER_CACHE_H
+
+
+
+
diff --git a/libs/rs/rsSimpleMesh.cpp b/libs/rs/rsSimpleMesh.cpp
index b082fd7..53ce5cd 100644
--- a/libs/rs/rsSimpleMesh.cpp
+++ b/libs/rs/rsSimpleMesh.cpp
@@ -34,62 +34,71 @@
     delete[] mVertexBuffers;
 }
 
-void SimpleMesh::render() const
+void SimpleMesh::render(Context *rsc) const
 {
     if (mPrimitiveType.get()) {
-        renderRange(0, mPrimitiveType->getDimX());
+        renderRange(rsc, 0, mPrimitiveType->getDimX());
         return;
     }
 
     if (mIndexType.get()) {
-        renderRange(0, mIndexType->getDimX());
+        renderRange(rsc, 0, mIndexType->getDimX());
         return;
     }
 
-    renderRange(0, mVertexTypes[0]->getDimX());
+    renderRange(rsc, 0, mVertexTypes[0]->getDimX());
 }
 
-void SimpleMesh::renderRange(uint32_t start, uint32_t len) const
+void SimpleMesh::renderRange(Context *rsc, uint32_t start, uint32_t len) const
 {
     if (len < 1) {
         return;
     }
 
-    glDisableClientState(GL_VERTEX_ARRAY);
-    glDisableClientState(GL_NORMAL_ARRAY);
-    glDisableClientState(GL_COLOR_ARRAY);
-    for (uint32_t ct=0; ct < RS_MAX_TEXTURE; ct++) {
-        glClientActiveTexture(GL_TEXTURE0 + ct);
-        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-    }
-    glClientActiveTexture(GL_TEXTURE0);
-
-    for (uint32_t ct=0; ct < mVertexTypeCount; ct++) {
-        glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffers[ct]->getBufferObjectID());
-        mVertexTypes[ct]->enableGLVertexBuffer();
+    rsc->checkError("SimpleMesh::renderRange 1");
+    VertexArray va;
+    if (rsc->checkVersion2_0()) {
+        for (uint32_t ct=0; ct < mVertexTypeCount; ct++) {
+            mVertexBuffers[ct]->uploadCheck(rsc);
+            va.setActiveBuffer(mVertexBuffers[ct]->getBufferObjectID());
+            mVertexTypes[ct]->enableGLVertexBuffer2(&va);
+        }
+        va.setupGL2(rsc, &rsc->mStateVertexArray, &rsc->mShaderCache);
+    } else {
+        for (uint32_t ct=0; ct < mVertexTypeCount; ct++) {
+            mVertexBuffers[ct]->uploadCheck(rsc);
+            va.setActiveBuffer(mVertexBuffers[ct]->getBufferObjectID());
+            mVertexTypes[ct]->enableGLVertexBuffer(&va);
+        }
+        va.setupGL(rsc, 0);
     }
 
+    rsc->checkError("SimpleMesh::renderRange 2");
     if (mIndexType.get()) {
+        mIndexBuffer->uploadCheck(rsc);
         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->getBufferObjectID());
         glDrawElements(mGLPrimitive, len, GL_UNSIGNED_SHORT, (uint16_t *)(start * 2));
     } else {
         glDrawArrays(mGLPrimitive, start, len);
     }
+
+    rsc->checkError("SimpleMesh::renderRange");
 }
 
-void SimpleMesh::uploadAll()
+void SimpleMesh::uploadAll(Context *rsc)
 {
     for (uint32_t ct=0; ct < mVertexTypeCount; ct++) {
         if (mVertexBuffers[ct].get()) {
-            mVertexBuffers[ct]->uploadToBufferObject();
+            mVertexBuffers[ct]->deferedUploadToBufferObject(rsc);
         }
     }
     if (mIndexBuffer.get()) {
-        mIndexBuffer->uploadToBufferObject();
+        mIndexBuffer->deferedUploadToBufferObject(rsc);
     }
     if (mPrimitiveBuffer.get()) {
-        mPrimitiveBuffer->uploadToBufferObject();
+        mPrimitiveBuffer->deferedUploadToBufferObject(rsc);
     }
+    rsc->checkError("SimpleMesh::uploadAll");
 }
 
 
diff --git a/libs/rs/rsSimpleMesh.h b/libs/rs/rsSimpleMesh.h
index 1e5c908..6defbda 100644
--- a/libs/rs/rsSimpleMesh.h
+++ b/libs/rs/rsSimpleMesh.h
@@ -45,9 +45,9 @@
     uint32_t mGLPrimitive;
 
 
-    void render() const;
-    void renderRange(uint32_t start, uint32_t len) const;
-    void uploadAll();
+    void render(Context *) const;
+    void renderRange(Context *, uint32_t start, uint32_t len) const;
+    void uploadAll(Context *);
 
 
 protected:
diff --git a/libs/rs/rsType.cpp b/libs/rs/rsType.cpp
index ddaa2f0..22a267a 100644
--- a/libs/rs/rsType.cpp
+++ b/libs/rs/rsType.cpp
@@ -26,7 +26,6 @@
     mAllocLine = __LINE__;
     mLODs = 0;
     mLODCount = 0;
-    memset(&mGL, 0, sizeof(mGL));
     clear();
 }
 
@@ -93,9 +92,9 @@
         mLODs[lod].mZ = tz;
         mLODs[lod].mOffset = offset;
         offset += tx * rsMax(ty, 1u) * rsMax(tz, 1u) * mElement->getSizeBytes();
-        tx = (tx + 1) >> 1;
-        ty = (ty + 1) >> 1;
-        tz = (tz + 1) >> 1;
+        if (tx > 1) tx >>= 1;
+        if (ty > 1) ty >>= 1;
+        if (tz > 1) tz >>= 1;
     }
 
     // At this point the offset is the size of a mipmap chain;
@@ -133,110 +132,64 @@
 
 void Type::makeGLComponents()
 {
-    uint32_t texNum = 0;
-    memset(&mGL, 0, sizeof(mGL));
+    uint32_t userNum = 0;
 
-    for (uint32_t ct=0; ct < getElement()->getComponentCount(); ct++) {
-        const Component *c = getElement()->getComponent(ct);
+    for (uint32_t ct=0; ct < getElement()->getFieldCount(); ct++) {
+        const Component &c = getElement()->getField(ct)->getComponent();
 
-        switch(c->getKind()) {
-        case Component::X:
+        switch(c.getKind()) {
+        case RS_KIND_USER:
+            mGL.mUser[userNum].size = c.getVectorSize();
+            mGL.mUser[userNum].offset = mElement->getFieldOffsetBytes(ct);
+            mGL.mUser[userNum].type = c.getGLType();
+            mGL.mUser[userNum].normalized = c.getType() != RS_TYPE_FLOAT_32;//c.getIsNormalized();
+            mGL.mUser[userNum].name.setTo(getElement()->getFieldName(ct));
+            userNum ++;
+            break;
+
+        case RS_KIND_POSITION:
             rsAssert(mGL.mVtx.size == 0);
-            mGL.mVtx.size = 1;
-            mGL.mVtx.offset = mElement->getComponentOffsetBytes(ct);
-            mGL.mVtx.type = c->getGLType();
+            mGL.mVtx.size = c.getVectorSize();
+            mGL.mVtx.offset = mElement->getFieldOffsetBytes(ct);
+            mGL.mVtx.type = c.getGLType();
+            mGL.mVtx.normalized = false;
+            mGL.mVtx.name.setTo("Position");
             break;
-        case Component::Y:
-            rsAssert(mGL.mVtx.size == 1);
-            rsAssert(mGL.mVtx.type == c->getGLType());
-            mGL.mVtx.size = 2;
-            break;
-        case Component::Z:
-            rsAssert(mGL.mVtx.size == 2);
-            rsAssert(mGL.mVtx.type == c->getGLType());
-            mGL.mVtx.size = 3;
-            break;
-        case Component::W:
-            rsAssert(mGL.mVtx.size == 4);
-            rsAssert(mGL.mVtx.type == c->getGLType());
-            mGL.mVtx.size = 4;
-        break;
 
-        case Component::RED:
+        case RS_KIND_COLOR:
             rsAssert(mGL.mColor.size == 0);
-            mGL.mColor.size = 1;
-            mGL.mColor.offset = mElement->getComponentOffsetBytes(ct);
-            mGL.mColor.type = c->getGLType();
+            mGL.mColor.size = c.getVectorSize();
+            mGL.mColor.offset = mElement->getFieldOffsetBytes(ct);
+            mGL.mColor.type = c.getGLType();
+            mGL.mColor.normalized = c.getType() != RS_TYPE_FLOAT_32;
+            mGL.mColor.name.setTo("Color");
             break;
-        case Component::GREEN:
-            rsAssert(mGL.mColor.size == 1);
-            rsAssert(mGL.mColor.type == c->getGLType());
-            mGL.mColor.size = 2;
-            break;
-        case Component::BLUE:
-            rsAssert(mGL.mColor.size == 2);
-            rsAssert(mGL.mColor.type == c->getGLType());
-            mGL.mColor.size = 3;
-            break;
-        case Component::ALPHA:
-            // Can be RGBA or A at this point
-            if (mGL.mColor.size > 0) {
-                rsAssert(mGL.mColor.size == 3);
-                rsAssert(mGL.mColor.type == c->getGLType());
-                mGL.mColor.size = 4;
-            } else {
-                mGL.mColor.size = 1;
-                mGL.mColor.offset = mElement->getComponentOffsetBytes(ct);
-                mGL.mColor.type = c->getGLType();
-            }
-        break;
 
-        case Component::NX:
+        case RS_KIND_NORMAL:
             rsAssert(mGL.mNorm.size == 0);
-            mGL.mNorm.size = 1;
-            mGL.mNorm.offset = mElement->getComponentOffsetBytes(ct);
-            mGL.mNorm.type = c->getGLType();
-        break;
-        case Component::NY:
-            rsAssert(mGL.mNorm.size == 1);
-            rsAssert(mGL.mNorm.type == c->getGLType());
-            mGL.mNorm.size = 2;
-        break;
-        case Component::NZ:
-            rsAssert(mGL.mNorm.size == 2);
-            rsAssert(mGL.mNorm.type == c->getGLType());
-            mGL.mNorm.size = 3;
-        break;
+            mGL.mNorm.size = c.getVectorSize();
+            mGL.mNorm.offset = mElement->getFieldOffsetBytes(ct);
+            mGL.mNorm.type = c.getGLType();
+            mGL.mNorm.normalized = false;
+            mGL.mNorm.name.setTo("Normal");
+            break;
 
-        case Component::S:
-            if (mGL.mTex[texNum].size) {
-                texNum++;
-            }
-            mGL.mTex[texNum].size = 1;
-            mGL.mTex[texNum].offset = mElement->getComponentOffsetBytes(ct);
-            mGL.mTex[texNum].type = c->getGLType();
-        break;
-        case Component::T:
-            rsAssert(mGL.mTex[texNum].size == 1);
-            rsAssert(mGL.mTex[texNum].type == c->getGLType());
-            mGL.mTex[texNum].size = 2;
-        break;
-        case Component::R:
-            rsAssert(mGL.mTex[texNum].size == 2);
-            rsAssert(mGL.mTex[texNum].type == c->getGLType());
-            mGL.mTex[texNum].size = 3;
-        break;
-        case Component::Q:
-            rsAssert(mGL.mTex[texNum].size == 3);
-            rsAssert(mGL.mTex[texNum].type == c->getGLType());
-            mGL.mTex[texNum].size = 4;
-        break;
+        case RS_KIND_TEXTURE:
+            rsAssert(mGL.mTex.size == 0);
+            mGL.mTex.size = c.getVectorSize();
+            mGL.mTex.offset = mElement->getFieldOffsetBytes(ct);
+            mGL.mTex.type = c.getGLType();
+            mGL.mTex.normalized = false;
+            mGL.mTex.name.setTo("Texture");
+            break;
 
-        case Component::POINT_SIZE:
+        case RS_KIND_POINT_SIZE:
             rsAssert(!mGL.mPointSize.size);
-            mGL.mPointSize.size = 1;
-            mGL.mPointSize.offset = mElement->getComponentOffsetBytes(ct);
-            mGL.mPointSize.type = c->getGLType();
+            mGL.mPointSize.size = c.getVectorSize();
+            mGL.mPointSize.offset = mElement->getFieldOffsetBytes(ct);
+            mGL.mPointSize.type = c.getGLType();
+            mGL.mPointSize.normalized = false;
+            mGL.mPointSize.name.setTo("PointSize");
         break;
 
         default:
@@ -245,62 +198,75 @@
     }
 }
 
-void Type::enableGLVertexBuffer() const
+void Type::enableGLVertexBuffer(VertexArray *va) const
 {
     // Note: We are only going to enable buffers and never disable them
-    // here.  The reasonis more than one Allocation may be used as a vertex
+    // here.  The reason is more than one Allocation may be used as a vertex
     // source.  So we cannot disable arrays that may have been in use by
     // another allocation.
 
     uint32_t stride = mElement->getSizeBytes();
     if (mGL.mVtx.size) {
-        //LOGE("va vtx %i %x, %i, %p", mGL.mVtx.size, mGL.mVtx.type, stride, (void *)mGL.mVtx.offset);
-        glEnableClientState(GL_VERTEX_ARRAY);
-        glVertexPointer(mGL.mVtx.size,
-                        mGL.mVtx.type,
-                        stride,
-                        (void *)mGL.mVtx.offset);
+        va->addLegacy(mGL.mVtx.type,
+                      mGL.mVtx.size,
+                      stride,
+                      RS_KIND_POSITION,
+                      false,
+                      mGL.mVtx.offset);
     }
 
     if (mGL.mNorm.size) {
-        //LOGE("va norm %i %x, %i, %p", mGL.mNorm.size, mGL.mNorm.type, stride, (void *)mGL.mNorm.offset);
-        glEnableClientState(GL_NORMAL_ARRAY);
-        rsAssert(mGL.mNorm.size == 3);
-        glNormalPointer(mGL.mNorm.type,
-                        stride,
-                        (void *)mGL.mNorm.offset);
+        va->addLegacy(mGL.mNorm.type,
+                     3,
+                     stride,
+                     RS_KIND_NORMAL,
+                     false,
+                     mGL.mNorm.offset);
     }
 
     if (mGL.mColor.size) {
-        glEnableClientState(GL_COLOR_ARRAY);
-        glColorPointer(mGL.mColor.size,
-                       mGL.mColor.type,
-                       stride,
-                       (void *)mGL.mColor.offset);
+        va->addLegacy(mGL.mColor.type,
+                     mGL.mColor.size,
+                     stride,
+                     RS_KIND_COLOR,
+                     true,
+                     mGL.mColor.offset);
     }
 
-    for (uint32_t ct=0; ct < RS_MAX_TEXTURE; ct++) {
-        if (mGL.mTex[ct].size) {
-            //LOGE("va tex%i %i %x, %i, %p", ct, mGL.mTex[ct].size, mGL.mTex[ct].type, stride, (void *)mGL.mTex[ct].offset);
-            glClientActiveTexture(GL_TEXTURE0 + ct);
-            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-            glTexCoordPointer(mGL.mTex[ct].size,
-                              mGL.mTex[ct].type,
-                              stride,
-                              (void *)mGL.mTex[ct].offset);
-        }
+    if (mGL.mTex.size) {
+        va->addLegacy(mGL.mTex.type,
+                     mGL.mTex.size,
+                     stride,
+                     RS_KIND_TEXTURE,
+                     false,
+                     mGL.mTex.offset);
     }
-    glClientActiveTexture(GL_TEXTURE0);
 
     if (mGL.mPointSize.size) {
-        glEnableClientState(GL_POINT_SIZE_ARRAY_OES);
-        glPointSizePointerOES(mGL.mPointSize.type,
-                              stride,
-                              (void *)mGL.mPointSize.offset);
+        va->addLegacy(mGL.mPointSize.type,
+                     1,
+                     stride,
+                     RS_KIND_POINT_SIZE,
+                     false,
+                     mGL.mPointSize.offset);
     }
 
 }
 
+void Type::enableGLVertexBuffer2(VertexArray *va) const
+{
+    // Do legacy buffers
+    enableGLVertexBuffer(va);
+
+    uint32_t stride = mElement->getSizeBytes();
+    for (uint32_t ct=0; ct < RS_MAX_ATTRIBS; ct++) {
+        if (mGL.mUser[ct].size) {
+            va->addUser(mGL.mUser[ct], stride);
+        }
+    }
+}
+
+
 
 void Type::dumpLOGV(const char *prefix) const
 {
diff --git a/libs/rs/rsType.h b/libs/rs/rsType.h
index 2c43405..4fa4933 100644
--- a/libs/rs/rsType.h
+++ b/libs/rs/rsType.h
@@ -18,6 +18,7 @@
 #define ANDROID_STRUCTURED_TYPE_H
 
 #include "rsElement.h"
+#include "rsVertexArray.h"
 
 // ---------------------------------------------------------------------------
 namespace android {
@@ -67,7 +68,8 @@
     void clear();
     void compute();
 
-    void enableGLVertexBuffer() const;
+    void enableGLVertexBuffer(class VertexArray *) const;
+    void enableGLVertexBuffer2(class VertexArray *) const;
 
     void dumpLOGV(const char *prefix) const;
 
@@ -108,18 +110,13 @@
     LOD *mLODs;
     uint32_t mLODCount;
 
-    struct VertexComponent_t {
-        uint32_t offset;
-        uint32_t type;
-        uint32_t size;
-        uint32_t stride;
-    };
     struct GLState_t {
-        VertexComponent_t mVtx;
-        VertexComponent_t mNorm;
-        VertexComponent_t mColor;
-        VertexComponent_t mTex[RS_MAX_TEXTURE];
-        VertexComponent_t mPointSize;
+        VertexArray::Attrib mUser[RS_MAX_ATTRIBS];
+        VertexArray::Attrib mVtx;
+        VertexArray::Attrib mNorm;
+        VertexArray::Attrib mColor;
+        VertexArray::Attrib mTex;
+        VertexArray::Attrib mPointSize;
     };
     GLState_t mGL;
     void makeGLComponents();
diff --git a/libs/rs/rsVertexArray.cpp b/libs/rs/rsVertexArray.cpp
new file mode 100644
index 0000000..d0c0414
--- /dev/null
+++ b/libs/rs/rsVertexArray.cpp
@@ -0,0 +1,216 @@
+/*
+ * 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.
+ */
+
+#include "rsContext.h"
+
+#include <GLES/gl.h>
+#include <GLES2/gl2.h>
+
+using namespace android;
+using namespace android::renderscript;
+
+
+VertexArray::VertexArray()
+{
+    clearAll();
+}
+
+VertexArray::~VertexArray()
+{
+}
+
+
+void VertexArray::clearAll()
+{
+    for (uint32_t ct=0; ct < RS_MAX_ATTRIBS; ct++) {
+        mAttribs[ct].clear();
+    }
+    mActiveBuffer = 0;
+    mCount = 0;
+}
+
+VertexArray::Attrib::Attrib()
+{
+    clear();
+}
+
+void VertexArray::Attrib::set(const Attrib &a)
+{
+    buffer = a.buffer;
+    offset = a.offset;
+    type = a.type;
+    size = a.size;
+    stride = a.stride;
+    normalized = a.normalized;
+    kind = RS_KIND_USER;
+    name.setTo(a.name);
+}
+
+void VertexArray::Attrib::clear()
+{
+    buffer = 0;
+    offset = 0;
+    type = 0;
+    size = 0;
+    stride = 0;
+    normalized = false;
+    name.setTo("");
+}
+
+void VertexArray::clear(uint32_t n)
+{
+    mAttribs[n].clear();
+}
+
+void VertexArray::addUser(const Attrib &a, uint32_t stride)
+{
+    assert(mCount < RS_MAX_ATTRIBS);
+    mAttribs[mCount].set(a);
+    mAttribs[mCount].buffer = mActiveBuffer;
+    mAttribs[mCount].stride = stride;
+    mAttribs[mCount].kind = RS_KIND_USER;
+    mCount ++;
+}
+
+void VertexArray::addLegacy(uint32_t type, uint32_t size, uint32_t stride, RsDataKind kind, bool normalized, uint32_t offset)
+{
+    assert(mCount < RS_MAX_ATTRIBS);
+    mAttribs[mCount].clear();
+    mAttribs[mCount].type = type;
+    mAttribs[mCount].size = size;
+    mAttribs[mCount].offset = offset;
+    mAttribs[mCount].normalized = normalized;
+    mAttribs[mCount].buffer = mActiveBuffer;
+    mAttribs[mCount].stride = stride;
+    mAttribs[mCount].kind = kind;
+    mCount ++;
+}
+
+void VertexArray::logAttrib(uint32_t idx, uint32_t slot) const {
+    LOGE("va %i: slot=%i name=%s buf=%i  size=%i  type=0x%x  kind=%i  stride=0x%x  norm=%i  offset=0x%x", idx, slot,
+         mAttribs[idx].name.string(),
+         mAttribs[idx].buffer,
+         mAttribs[idx].size,
+         mAttribs[idx].type,
+         mAttribs[idx].kind,
+         mAttribs[idx].stride,
+         mAttribs[idx].normalized,
+         mAttribs[idx].offset);
+}
+
+void VertexArray::setupGL(const Context *rsc, class VertexArrayState *state) const
+{
+    glClientActiveTexture(GL_TEXTURE0);
+    glDisableClientState(GL_NORMAL_ARRAY);
+    glDisableClientState(GL_COLOR_ARRAY);
+    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+    glDisableClientState(GL_POINT_SIZE_ARRAY_OES);
+
+    for (uint32_t ct=0; ct < mCount; ct++) {
+        switch(mAttribs[ct].kind) {
+        case RS_KIND_POSITION:
+            //logAttrib(POSITION);
+            glEnableClientState(GL_VERTEX_ARRAY);
+            glBindBuffer(GL_ARRAY_BUFFER, mAttribs[ct].buffer);
+            glVertexPointer(mAttribs[ct].size,
+                            mAttribs[ct].type,
+                            mAttribs[ct].stride,
+                            (void *)mAttribs[ct].offset);
+            break;
+
+        case RS_KIND_NORMAL:
+            //logAttrib(NORMAL);
+            glEnableClientState(GL_NORMAL_ARRAY);
+            rsAssert(mAttribs[ct].size == 3);
+            glBindBuffer(GL_ARRAY_BUFFER, mAttribs[ct].buffer);
+            glNormalPointer(mAttribs[ct].type,
+                            mAttribs[ct].stride,
+                            (void *)mAttribs[ct].offset);
+            break;
+
+        case RS_KIND_COLOR:
+            //logAttrib(COLOR);
+            glEnableClientState(GL_COLOR_ARRAY);
+            glBindBuffer(GL_ARRAY_BUFFER, mAttribs[ct].buffer);
+            glColorPointer(mAttribs[ct].size,
+                           mAttribs[ct].type,
+                           mAttribs[ct].stride,
+                           (void *)mAttribs[ct].offset);
+            break;
+
+        case RS_KIND_TEXTURE:
+            //logAttrib(TEXTURE);
+            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+            glBindBuffer(GL_ARRAY_BUFFER, mAttribs[ct].buffer);
+            glTexCoordPointer(mAttribs[ct].size,
+                              mAttribs[ct].type,
+                              mAttribs[ct].stride,
+                              (void *)mAttribs[ct].offset);
+            break;
+
+        case RS_KIND_POINT_SIZE:
+            //logAttrib(POINT_SIZE);
+            glEnableClientState(GL_POINT_SIZE_ARRAY_OES);
+            glBindBuffer(GL_ARRAY_BUFFER, mAttribs[ct].buffer);
+            glPointSizePointerOES(mAttribs[ct].type,
+                                  mAttribs[ct].stride,
+                                  (void *)mAttribs[ct].offset);
+            break;
+
+        default:
+            rsAssert(0);
+        }
+    }
+
+    rsc->checkError("VertexArray::setupGL");
+}
+
+void VertexArray::setupGL2(const Context *rsc, class VertexArrayState *state, ShaderCache *sc) const
+{
+    rsc->checkError("VertexArray::setupGL2 start");
+    for (uint32_t ct=1; ct <= state->mLastEnableCount; ct++) {
+        glDisableVertexAttribArray(ct);
+    }
+
+    rsc->checkError("VertexArray::setupGL2 disabled");
+    for (uint32_t ct=0; ct < mCount; ct++) {
+        uint32_t slot = 0;
+        if (sc->isUserVertexProgram()) {
+            slot = sc->vtxAttribSlot(ct);
+        } else {
+            slot = sc->vtxAttribSlot(mAttribs[ct].kind);
+        }
+
+        //logAttrib(ct, slot);
+        glEnableVertexAttribArray(slot);
+        glBindBuffer(GL_ARRAY_BUFFER, mAttribs[ct].buffer);
+
+        glVertexAttribPointer(slot,
+                              mAttribs[ct].size,
+                              mAttribs[ct].type,
+                              mAttribs[ct].normalized,
+                              mAttribs[ct].stride,
+                              (void *)mAttribs[ct].offset);
+    }
+    state->mLastEnableCount = mCount;
+    rsc->checkError("VertexArray::setupGL2 done");
+}
+////////////////////////////////////////////
+
+void VertexArrayState::init(Context *) {
+    mLastEnableCount = 0;
+}
+
diff --git a/libs/rs/rsVertexArray.h b/libs/rs/rsVertexArray.h
new file mode 100644
index 0000000..3904cb6
--- /dev/null
+++ b/libs/rs/rsVertexArray.h
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_VERTEX_ARRAY_H
+#define ANDROID_VERTEX_ARRAY_H
+
+
+#include "rsObjectBase.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+class ShaderCache;
+
+// An element is a group of Components that occupies one cell in a structure.
+class VertexArray
+{
+public:
+    VertexArray();
+    virtual ~VertexArray();
+
+
+    class Attrib {
+    public:
+        uint32_t buffer;
+        uint32_t offset;
+        uint32_t type;
+        uint32_t size;
+        uint32_t stride;
+        bool normalized;
+        String8 name;
+        RsDataKind kind;
+
+        Attrib();
+        void set(const Attrib &);
+        void clear();
+    };
+
+
+    void clearAll();
+    void setActiveBuffer(uint32_t id) {mActiveBuffer = id;}
+    void addUser(const Attrib &, uint32_t stride);
+    void addLegacy(uint32_t type, uint32_t size, uint32_t stride, RsDataKind kind, bool normalized, uint32_t offset);
+
+    void setupGL(const Context *rsc, class VertexArrayState *) const;
+    void setupGL2(const Context *rsc, class VertexArrayState *, ShaderCache *) const;
+    void logAttrib(uint32_t idx, uint32_t slot) const;
+
+protected:
+    void clear(uint32_t index);
+    uint32_t mActiveBuffer;
+    uint32_t mCount;
+
+    Attrib mAttribs[RS_MAX_ATTRIBS];
+};
+
+
+class VertexArrayState {
+public:
+    void init(Context *);
+
+    uint32_t mLastEnableCount;
+    //VertexArray::Attrib mAttribs[VertexArray::_LAST];
+};
+
+
+}
+}
+#endif //ANDROID_LIGHT_H
+
+
+
diff --git a/services/java/com/android/server/HeadsetObserver.java b/services/java/com/android/server/HeadsetObserver.java
index c94450b..9d69564 100644
--- a/services/java/com/android/server/HeadsetObserver.java
+++ b/services/java/com/android/server/HeadsetObserver.java
@@ -53,19 +53,6 @@
     private final Context mContext;
     private final WakeLock mWakeLock;  // held while there is a pending route change
 
-    private boolean mHandleTTY;
-    private int mTTYState;
-    private AudioManager mAudioManager = null;
-
-    // special use of bits in headset state received from kernel made by some
-    // platforms to indicate changes in TTY mode.
-    private static final int BIT_TTY_OFF = 0;
-    private static final int BIT_TTY_FULL = (1 << 2);
-    private static final int BIT_TTY_VCO = (1 << 5);
-    private static final int BIT_TTY_HCO = (1 << 6);
-    private static final int TTY_BITS_MASK = (BIT_TTY_FULL | BIT_TTY_VCO | BIT_TTY_HCO);
-
-
     public HeadsetObserver(Context context) {
         mContext = context;
         PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
@@ -74,11 +61,6 @@
 
         startObserving(HEADSET_UEVENT_MATCH);
 
-        // read settings for TTY mode indication method
-        mHandleTTY = context.getResources().getBoolean(
-                com.android.internal.R.bool.tty_mode_uses_headset_events);
-        mTTYState = BIT_TTY_OFF;
-
         init();  // set initial status
     }
 
@@ -118,39 +100,6 @@
     }
 
     private synchronized final void update(String newName, int newState) {
-        // handle TTY state change first
-        if (mHandleTTY) {
-            int ttyState = newState  & TTY_BITS_MASK;
-            if (ttyState != mTTYState) {
-                String ttyMode;
-
-                switch (ttyState) {
-                case BIT_TTY_FULL:
-                    ttyMode = "tty_full";
-                    break;
-                case BIT_TTY_VCO:
-                    ttyMode = "tty_vco";
-                    break;
-                case BIT_TTY_HCO:
-                    ttyMode = "tty_hco";
-                    break;
-                case BIT_TTY_OFF:
-                    ttyMode = "tty_off";
-                    break;
-                default:
-                    ttyMode = "tty_invalid";
-                    break;
-
-                }
-                if (ttyMode != "tty_invalid") {
-                    mTTYState = ttyState;
-                    if (mAudioManager == null) {
-                        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
-                    }
-                    mAudioManager.setParameters("tty_mode="+ttyMode);
-                }
-            }
-        }
         // Retain only relevant bits
         int headsetState = newState & SUPPORTED_HEADSETS;
         int newOrOld = headsetState | mHeadsetState;
diff --git a/telephony/java/com/android/internal/telephony/cdma/TtyIntent.java b/telephony/java/com/android/internal/telephony/cdma/TtyIntent.java
index f27f79c..3813b1d 100644
--- a/telephony/java/com/android/internal/telephony/cdma/TtyIntent.java
+++ b/telephony/java/com/android/internal/telephony/cdma/TtyIntent.java
@@ -43,4 +43,25 @@
      */
     public static final String TTY_ENABLED = "ttyEnabled";
 
+    /**
+     * Broadcast intent action indicating that the TTY preferred operating mode
+     * has changed. An intent extra provides the new mode as an int.
+     * @see #TTY_PREFFERED_MODE
+     *
+     * {@hide}
+     */
+    public static final String TTY_PREFERRED_MODE_CHANGE_ACTION =
+        "com.android.internal.telephony.cdma.intent.action.TTY_PREFERRED_MODE_CHANGE";
+
+    /**
+     * The lookup key for an int that indicates preferred TTY mode.
+     * Valid modes are:
+     * - {@link Phone.TTY_MODE_OFF}
+     * - {@link Phone.TTY_MODE_FULL}
+     * - {@link Phone.TTY_MODE_HCO}
+     * - {@link Phone.TTY_MODE_VCO}
+     *
+     * {@hide}
+     */
+    public static final String TTY_PREFFERED_MODE = "ttyPreferredMode";
 }