Creating the jni and java layer to integrate a3d

Change-Id: I438359633bae59bf9188cd2c4664a92ca16c5f37
diff --git a/RenderScript.h b/RenderScript.h
index 5e246ce..e7c0274 100644
--- a/RenderScript.h
+++ b/RenderScript.h
@@ -40,6 +40,7 @@
 typedef void * RsSimpleMesh;
 typedef void * RsType;
 typedef void * RsLight;
+typedef void * RsObjectBase;
 
 typedef void * RsProgram;
 typedef void * RsProgramVertex;
@@ -229,6 +230,30 @@
     RS_ANIMATION_EDGE_CYLE_RELATIVE
 };
 
+enum RsA3DClassID {
+    RS_A3D_CLASS_ID_UNKNOWN,
+    RS_A3D_CLASS_ID_MESH,
+    RS_A3D_CLASS_ID_SIMPLE_MESH,
+    RS_A3D_CLASS_ID_TYPE,
+    RS_A3D_CLASS_ID_ELEMENT,
+    RS_A3D_CLASS_ID_ALLOCATION,
+    RS_A3D_CLASS_ID_PROGRAM_VERTEX,
+    RS_A3D_CLASS_ID_PROGRAM_RASTER,
+    RS_A3D_CLASS_ID_PROGRAM_FRAGMENT,
+    RS_A3D_CLASS_ID_PROGRAM_STORE,
+    RS_A3D_CLASS_ID_SAMPLER,
+    RS_A3D_CLASS_ID_ANIMATION,
+    RS_A3D_CLASS_ID_LIGHT,
+    RS_A3D_CLASS_ID_ADAPTER_1D,
+    RS_A3D_CLASS_ID_ADAPTER_2D,
+    RS_A3D_CLASS_ID_SCRIPT_C
+};
+
+typedef struct {
+    RsA3DClassID classID;
+    const char* objectName;
+} RsFileIndexEntry;
+
 #ifndef NO_RS_FUNCS
 #include "rsgApiFuncDecl.h"
 #endif
diff --git a/java/ModelViewer/Android.mk b/java/ModelViewer/Android.mk
new file mode 100644
index 0000000..8bec6d6
--- /dev/null
+++ b/java/ModelViewer/Android.mk
@@ -0,0 +1,27 @@
+#
+# 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_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+#LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript
+
+LOCAL_PACKAGE_NAME := ModelViewer
+
+include $(BUILD_PACKAGE)
diff --git a/java/ModelViewer/AndroidManifest.xml b/java/ModelViewer/AndroidManifest.xml
new file mode 100644
index 0000000..ebbe743
--- /dev/null
+++ b/java/ModelViewer/AndroidManifest.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.modelviewer">
+    <application android:label="ModelViewer">
+        <activity android:name="ModelViewer"
+                  android:screenOrientation="portrait"
+                  android:theme="@android:style/Theme.Black.NoTitleBar">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/java/ModelViewer/res/drawable/robot.png b/java/ModelViewer/res/drawable/robot.png
new file mode 100644
index 0000000..7c85e56
--- /dev/null
+++ b/java/ModelViewer/res/drawable/robot.png
Binary files differ
diff --git a/java/ModelViewer/res/raw/modelviewer.rs b/java/ModelViewer/res/raw/modelviewer.rs
new file mode 100644
index 0000000..6a98f90
--- /dev/null
+++ b/java/ModelViewer/res/raw/modelviewer.rs
@@ -0,0 +1,59 @@
+// Copyright (C) 2009 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+
+#include "../../../../scriptc/rs_types.rsh"
+#include "../../../../scriptc/rs_math.rsh"
+#include "../../../../scriptc/rs_graphics.rsh"
+
+rs_program_vertex gPVBackground;
+rs_program_fragment gPFBackground;
+
+rs_allocation gTGrid;
+rs_mesh gTestMesh;
+
+rs_program_store gPFSBackground;
+
+float gRotate;
+
+#pragma rs export_var(gPVBackground, gPFBackground, gTGrid, gTestMesh, gPFSBackground, gRotate)
+
+void init() {
+    gRotate = 0.0f;
+}
+
+int root(int launchID) {
+
+    rsgClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+    rsgClearDepth(1.0f);
+
+    rsgBindProgramVertex(gPVBackground);
+
+    rsgBindProgramFragment(gPFBackground);
+    rsgBindProgramStore(gPFSBackground);
+    rsgBindTexture(gPFBackground, 0, gTGrid);
+
+    rs_matrix4x4 matrix;
+    rsMatrixLoadIdentity(&matrix);
+    // Position our model on the screen
+    rsMatrixTranslate(&matrix, 0.0f, -0.3f, 1.2f);
+    rsMatrixScale(&matrix, 0.2f, 0.2f, 0.2f);
+    rsMatrixRotate(&matrix, gRotate, 0.0f, 1.0f, 0.0f);
+    rsgProgramVertexLoadModelMatrix(&matrix);
+
+    rsgDrawSimpleMesh(gTestMesh);
+
+    return 10;
+}
diff --git a/java/ModelViewer/res/raw/modelviewer_bc.bc b/java/ModelViewer/res/raw/modelviewer_bc.bc
new file mode 100644
index 0000000..b02250b
--- /dev/null
+++ b/java/ModelViewer/res/raw/modelviewer_bc.bc
Binary files differ
diff --git a/java/ModelViewer/res/raw/robot.a3d b/java/ModelViewer/res/raw/robot.a3d
new file mode 100644
index 0000000..c0c66ae
--- /dev/null
+++ b/java/ModelViewer/res/raw/robot.a3d
Binary files differ
diff --git a/java/ModelViewer/src/com/android/modelviewer/ModelViewer.java b/java/ModelViewer/src/com/android/modelviewer/ModelViewer.java
new file mode 100644
index 0000000..7491744
--- /dev/null
+++ b/java/ModelViewer/src/com/android/modelviewer/ModelViewer.java
@@ -0,0 +1,71 @@
+/*
+ * 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.modelviewer;
+
+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 ModelViewer extends Activity {
+
+    private ModelViewerView mView;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        // Create our Preview view and set it as the content of our
+        // Activity
+        mView = new ModelViewerView(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();
+    }
+
+}
+
diff --git a/java/ModelViewer/src/com/android/modelviewer/ModelViewerRS.java b/java/ModelViewer/src/com/android/modelviewer/ModelViewerRS.java
new file mode 100644
index 0000000..dd52955
--- /dev/null
+++ b/java/ModelViewer/src/com/android/modelviewer/ModelViewerRS.java
@@ -0,0 +1,156 @@
+/*
+ * 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.modelviewer;
+
+import java.io.Writer;
+
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.renderscript.ProgramStore.DepthFunc;
+import android.util.Log;
+
+
+public class ModelViewerRS {
+
+    private final int STATE_LAST_FOCUS = 1;
+
+    int mWidth;
+    int mHeight;
+    int mRotation;
+
+    public ModelViewerRS() {
+    }
+
+    public void init(RenderScriptGL rs, Resources res, int width, int height) {
+        mRS = rs;
+        mRes = res;
+        mWidth = width;
+        mHeight = height;
+        mRotation = 0;
+        initRS();
+    }
+
+    private Resources mRes;
+    private RenderScriptGL mRS;
+    private Sampler mSampler;
+    private ProgramStore mPSBackground;
+    private ProgramFragment mPFBackground;
+    private ProgramVertex mPVBackground;
+    private ProgramVertex.MatrixAllocation mPVA;
+
+    private Allocation mGridImage;
+    private Allocation mAllocPV;
+
+    private SimpleMesh mMesh;
+
+    private ScriptC_ModelViewer mScript;
+
+    int mLastX;
+    int mLastY;
+
+    public void touchEvent(int x, int y) {
+        int dx = mLastX - x;
+        if(Math.abs(dx) > 50 || Math.abs(dx) < 3) {
+            dx = 0;
+        }
+
+        mRotation -= dx;
+        if(mRotation > 360) {
+            mRotation -= 360;
+        }
+        if(mRotation < 0) {
+            mRotation += 360;
+        }
+
+        mScript.set_gRotate(-(float)mRotation);
+
+        mLastX = x;
+        mLastY = y;
+    }
+
+    private void initPFS() {
+        ProgramStore.Builder b = new ProgramStore.Builder(mRS, null, null);
+
+        b.setDepthFunc(ProgramStore.DepthFunc.LESS);
+        b.setDitherEnable(false);
+        b.setDepthMask(true);
+        mPSBackground = b.create();
+
+        mScript.set_gPFSBackground(mPSBackground);
+    }
+
+    private void initPF() {
+        Sampler.Builder bs = new Sampler.Builder(mRS);
+        bs.setMin(Sampler.Value.LINEAR);
+        bs.setMag(Sampler.Value.LINEAR);
+        bs.setWrapS(Sampler.Value.CLAMP);
+        bs.setWrapT(Sampler.Value.WRAP);
+        mSampler = bs.create();
+
+        ProgramFragment.Builder b = new ProgramFragment.Builder(mRS);
+        b.setTexture(ProgramFragment.Builder.EnvMode.REPLACE,
+                     ProgramFragment.Builder.Format.RGBA, 0);
+        mPFBackground = b.create();
+        mPFBackground.bindSampler(mSampler, 0);
+
+        mScript.set_gPFBackground(mPFBackground);
+    }
+
+    private void initPV() {
+        ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS, null, null);
+        mPVBackground = pvb.create();
+
+        mPVA = new ProgramVertex.MatrixAllocation(mRS);
+        mPVBackground.bindAllocation(mPVA);
+        mPVA.setupProjectionNormalized(mWidth, mHeight);
+
+        mScript.set_gPVBackground(mPVBackground);
+    }
+
+    private void loadImage() {
+        mGridImage = Allocation.createFromBitmapResourceBoxed(mRS, mRes, R.drawable.robot, Element.RGB_565(mRS), true);
+        mGridImage.uploadToTexture(1);
+
+        mScript.set_gTGrid(mGridImage);
+    }
+
+    private void initRS() {
+
+        mScript = new ScriptC_ModelViewer(mRS, mRes, true);
+
+        initPFS();
+        initPF();
+        initPV();
+
+        loadImage();
+
+        FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.robot);
+        FileA3D.IndexEntry entry = model.getIndexEntry(0);
+        if(entry == null || entry.getClassID() != FileA3D.ClassID.SIMPLE_MESH) {
+            Log.e("rs", "could not load model");
+        }
+        else {
+            mMesh = (SimpleMesh)entry.getObject();
+            mScript.set_gTestMesh(mMesh);
+        }
+
+        mRS.contextBindRootScript(mScript);
+    }
+}
+
+
+
diff --git a/java/ModelViewer/src/com/android/modelviewer/ModelViewerView.java b/java/ModelViewer/src/com/android/modelviewer/ModelViewerView.java
new file mode 100644
index 0000000..ce76e1a
--- /dev/null
+++ b/java/ModelViewer/src/com/android/modelviewer/ModelViewerView.java
@@ -0,0 +1,95 @@
+/*
+ * 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.modelviewer;
+
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.concurrent.Semaphore;
+
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScript;
+import android.renderscript.RenderScriptGL;
+
+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;
+
+public class ModelViewerView extends RSSurfaceView {
+
+    public ModelViewerView(Context context) {
+        super(context);
+        //setFocusable(true);
+    }
+
+    private RenderScriptGL mRS;
+    private ModelViewerRS 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 ModelViewerRS();
+            mRender.init(mRS, getResources(), w, h);
+        }
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        if(mRS != null) {
+            mRS = null;
+            destroyRenderScript();
+        }
+    }
+
+    @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);
+    }
+
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev)
+    {
+        boolean ret = true;
+        int act = ev.getAction();
+        if (act == ev.ACTION_UP) {
+            ret = false;
+        }
+
+        Log.v("rs", "Values " + (int)ev.getX() + " " + (int)ev.getY());
+        mRender.touchEvent((int)ev.getX(), (int)ev.getY());
+        return ret;
+    }
+}
+
+
diff --git a/java/ModelViewer/src/com/android/modelviewer/ScriptC_ModelViewer.java b/java/ModelViewer/src/com/android/modelviewer/ScriptC_ModelViewer.java
new file mode 100644
index 0000000..f617c77
--- /dev/null
+++ b/java/ModelViewer/src/com/android/modelviewer/ScriptC_ModelViewer.java
@@ -0,0 +1,42 @@
+
+package com.android.modelviewer;
+
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.util.Log;
+
+
+
+public class ScriptC_ModelViewer
+    extends android.renderscript.ScriptC
+{
+    public ScriptC_ModelViewer(RenderScript rs, Resources resources, boolean isRoot) {
+        super(rs, resources, R.raw.modelviewer_bc, isRoot);
+    }
+
+    public void set_gPVBackground(ProgramVertex v) {
+        setVar(0, v.getID());
+    }
+
+    public void set_gPFBackground(ProgramFragment v) {
+        setVar(1, v.getID());
+    }
+
+    public void set_gTGrid(Allocation v) {
+        setVar(2, v.getID());
+    }
+
+    public void set_gTestMesh(SimpleMesh v) {
+        setVar(3, v.getID());
+    }
+
+    public void set_gPFSBackground(ProgramStore v) {
+        setVar(4, v.getID());
+    }
+
+    public void set_gRotate(float v) {
+        setVar(5, v);
+    }
+
+}
+
diff --git a/rs.spec b/rs.spec
index 2a872cd..4867cad 100644
--- a/rs.spec
+++ b/rs.spec
@@ -441,12 +441,34 @@
 	param float b
 	}
 
+FileA3DCreateFromAssetStream {
+	param const void * data
+	param size_t len
+	ret RsFile
+	}
+
 FileOpen {
 	ret RsFile
 	param const char *name
 	param size_t len
 	}
 
+FileA3DGetNumIndexEntries {
+	param int32_t * numEntries
+	param RsFile file
+	}
+
+FileA3DGetIndexEntries {
+	param RsFileIndexEntry * fileEntries
+	param uint32_t numEntries
+	param RsFile fileA3D
+	}
+
+FileA3DGetEntryByIndex {
+	param uint32_t index
+	param RsFile file
+	ret RsObjectBase
+	}
 
 SimpleMeshCreate {
 	ret RsSimpleMesh
diff --git a/rsAdapter.h b/rsAdapter.h
index 937ef50..449e7ad 100644
--- a/rsAdapter.h
+++ b/rsAdapter.h
@@ -49,9 +49,9 @@
 
     void subData(uint32_t xoff, uint32_t count, const void *data);
     void data(const void *data);
-    
+
     virtual void serialize(OStream *stream) const;
-    virtual A3DClassID getClassId() const { return A3D_CLASS_ID_ADAPTER_1D; }
+    virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_ADAPTER_1D; }
     static Adapter1D *createFromStream(Context *rsc, IStream *stream);
 
 protected:
@@ -85,9 +85,9 @@
 
     void data(const void *data);
     void subData(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void *data);
-    
+
     virtual void serialize(OStream *stream) const;
-    virtual A3DClassID getClassId() const { return A3D_CLASS_ID_ADAPTER_2D; }
+    virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_ADAPTER_2D; }
     static Adapter2D *createFromStream(Context *rsc, IStream *stream);
 
 protected:
diff --git a/rsAllocation.cpp b/rsAllocation.cpp
index 4db6a04..289cb30 100644
--- a/rsAllocation.cpp
+++ b/rsAllocation.cpp
@@ -348,8 +348,8 @@
 Allocation *Allocation::createFromStream(Context *rsc, IStream *stream)
 {
     // First make sure we are reading the correct object
-    A3DClassID classID = (A3DClassID)stream->loadU32();
-    if(classID != A3D_CLASS_ID_ALLOCATION) {
+    RsA3DClassID classID = (RsA3DClassID)stream->loadU32();
+    if(classID != RS_A3D_CLASS_ID_ALLOCATION) {
         LOGE("allocation loading skipped due to invalid class id\n");
         return NULL;
     }
diff --git a/rsAllocation.h b/rsAllocation.h
index 84a7c85..a408a57 100644
--- a/rsAllocation.h
+++ b/rsAllocation.h
@@ -73,7 +73,7 @@
 
     virtual void dumpLOGV(const char *prefix) const;
     virtual void serialize(OStream *stream) const;
-    virtual A3DClassID getClassId() const { return A3D_CLASS_ID_ALLOCATION; }
+    virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_ALLOCATION; }
     static Allocation *createFromStream(Context *rsc, IStream *stream);
 
     virtual void uploadCheck(const Context *rsc);
diff --git a/rsAnimation.h b/rsAnimation.h
index ed92c1a..340314e 100644
--- a/rsAnimation.h
+++ b/rsAnimation.h
@@ -36,9 +36,9 @@
                               RsAnimationEdge pre, RsAnimationEdge post);
 
     float eval(float) const;
-    
+
     virtual void serialize(OStream *stream) const;
-    virtual A3DClassID getClassId() const { return A3D_CLASS_ID_ANIMATION; }
+    virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_ANIMATION; }
     static Animation *createFromStream(Context *rsc, IStream *stream);
 
 protected:
diff --git a/rsElement.cpp b/rsElement.cpp
index 3b18c98..8fbf004 100644
--- a/rsElement.cpp
+++ b/rsElement.cpp
@@ -109,8 +109,8 @@
 Element *Element::createFromStream(Context *rsc, IStream *stream)
 {
     // First make sure we are reading the correct object
-    A3DClassID classID = (A3DClassID)stream->loadU32();
-    if(classID != A3D_CLASS_ID_ELEMENT) {
+    RsA3DClassID classID = (RsA3DClassID)stream->loadU32();
+    if(classID != RS_A3D_CLASS_ID_ELEMENT) {
         LOGE("element loading skipped due to invalid class id\n");
         return NULL;
     }
diff --git a/rsElement.h b/rsElement.h
index a302553..5c4f5c4 100644
--- a/rsElement.h
+++ b/rsElement.h
@@ -60,7 +60,7 @@
 
     void dumpLOGV(const char *prefix) const;
     virtual void serialize(OStream *stream) const;
-    virtual A3DClassID getClassId() const { return A3D_CLASS_ID_ELEMENT; }
+    virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_ELEMENT; }
     static Element *createFromStream(Context *rsc, IStream *stream);
 
     static const Element * create(Context *rsc, RsDataType dt, RsDataKind dk,
diff --git a/rsFileA3D.cpp b/rsFileA3D.cpp
index b88f7b0..23c0cf5 100644
--- a/rsFileA3D.cpp
+++ b/rsFileA3D.cpp
@@ -29,11 +29,8 @@
 using namespace android;
 using namespace android::renderscript;
 
-
-
-FileA3D::FileA3D()
+FileA3D::FileA3D(Context *rsc) : ObjectBase(rsc)
 {
-    mRsc = NULL;
     mAlloc = NULL;
     mData = NULL;
     mWriteStream = NULL;
@@ -63,7 +60,110 @@
     }
 }
 
-bool FileA3D::load(Context *rsc, FILE *f)
+void FileA3D::parseHeader(IStream *headerStream)
+{
+    mMajorVersion = headerStream->loadU32();
+    mMinorVersion = headerStream->loadU32();
+    uint32_t flags = headerStream->loadU32();
+    mUse64BitOffsets = (flags & 1) != 0;
+
+    LOGE("file open 64bit = %i", mUse64BitOffsets);
+
+    uint32_t numIndexEntries = headerStream->loadU32();
+    for(uint32_t i = 0; i < numIndexEntries; i ++) {
+        A3DIndexEntry *entry = new A3DIndexEntry();
+        headerStream->loadString(&entry->mObjectName);
+        LOGE("Header data, entry name = %s", entry->mObjectName.string());
+        entry->mType = (RsA3DClassID)headerStream->loadU32();
+        if(mUse64BitOffsets){
+            entry->mOffset = headerStream->loadOffset();
+            entry->mLength = headerStream->loadOffset();
+        }
+        else {
+            entry->mOffset = headerStream->loadU32();
+            entry->mLength = headerStream->loadU32();
+        }
+        entry->mRsObj = NULL;
+        mIndex.push(entry);
+    }
+}
+
+bool FileA3D::load(const void *data, size_t length)
+{
+    LOGE("Loading data. Size: %u", length);
+    const uint8_t *localData = (const uint8_t *)data;
+
+    size_t lengthRemaining = length;
+    size_t magicStrLen = 12;
+    if ((length < magicStrLen) ||
+        memcmp(data, "Android3D_ff", magicStrLen)) {
+        return false;
+    }
+
+    localData += magicStrLen;
+    lengthRemaining -= magicStrLen;
+
+    // Next we get our header size
+    uint64_t headerSize = 0;
+    if(lengthRemaining < sizeof(headerSize)) {
+        return false;
+    }
+
+    memcpy(&headerSize, localData, sizeof(headerSize));
+    localData += sizeof(headerSize);
+    lengthRemaining -= sizeof(headerSize);
+
+    LOGE("Loading data, headerSize = %lli", headerSize);
+
+    if(lengthRemaining < headerSize) {
+        return false;
+    }
+
+    uint8_t *headerData = (uint8_t *)malloc(headerSize);
+    if(!headerData) {
+        return false;
+    }
+
+    memcpy(headerData, localData, headerSize);
+
+    // Now open the stream to parse the header
+    IStream headerStream(headerData, false);
+    parseHeader(&headerStream);
+
+    free(headerData);
+
+    localData += headerSize;
+    lengthRemaining -= headerSize;
+
+    if(lengthRemaining < sizeof(mDataSize)) {
+        return false;
+    }
+
+    // Read the size of the data
+    memcpy(&mDataSize, localData, sizeof(mDataSize));
+    localData += sizeof(mDataSize);
+    lengthRemaining -= sizeof(mDataSize);
+
+    LOGE("Loading data, mDataSize = %lli", mDataSize);
+
+    if(lengthRemaining < mDataSize) {
+        return false;
+    }
+
+    // We should know enough to read the file in at this point.
+    mAlloc = malloc(mDataSize);
+    if (!mAlloc) {
+        return false;
+    }
+    mData = (uint8_t *)mAlloc;
+    memcpy(mAlloc, localData, mDataSize);
+
+    mReadStream = new IStream(mData, mUse64BitOffsets);
+
+    return true;
+}
+
+bool FileA3D::load(FILE *f)
 {
     char magicString[12];
     size_t len;
@@ -94,28 +194,9 @@
 
     // Now open the stream to parse the header
     IStream headerStream(headerData, false);
+    parseHeader(&headerStream);
 
-    mMajorVersion = headerStream.loadU32();
-    mMinorVersion = headerStream.loadU32();
-    uint32_t flags = headerStream.loadU32();
-    mUse64BitOffsets = (flags & 1) != 0;
-
-    LOGE("file open 64bit = %i", mUse64BitOffsets);
-
-    uint32_t numIndexEntries = headerStream.loadU32();
-    for(uint32_t i = 0; i < numIndexEntries; i ++) {
-        A3DIndexEntry *entry = new A3DIndexEntry();
-        headerStream.loadString(&entry->mID);
-        entry->mType = (A3DClassID)headerStream.loadU32();
-        if(mUse64BitOffsets){
-            entry->mOffset = headerStream.loadOffset();
-        }
-        else {
-            entry->mOffset = headerStream.loadU32();
-        }
-        entry->mRsObj = NULL;
-        mIndex.push(entry);
-    }
+    free(headerData);
 
     // Next thing is the size of the header
     len = fread(&mDataSize, 1, sizeof(mDataSize), f);
@@ -138,65 +219,90 @@
 
     mReadStream = new IStream(mData, mUse64BitOffsets);
 
-    mRsc = rsc;
-
     LOGE("Header is read an stream initialized");
     return true;
 }
 
-size_t FileA3D::getNumLoadedEntries() const {
+size_t FileA3D::getNumIndexEntries() const {
     return mIndex.size();
 }
 
-const FileA3D::A3DIndexEntry *FileA3D::getLoadedEntry(size_t index) const {
+const FileA3D::A3DIndexEntry *FileA3D::getIndexEntry(size_t index) const {
     if(index < mIndex.size()) {
         return mIndex[index];
     }
     return NULL;
 }
 
-ObjectBase *FileA3D::initializeFromEntry(const FileA3D::A3DIndexEntry *entry) {
+ObjectBase *FileA3D::initializeFromEntry(size_t index) {
+    if(index >= mIndex.size()) {
+        return NULL;
+    }
+
+    FileA3D::A3DIndexEntry *entry = mIndex[index];
     if(!entry) {
         return NULL;
     }
 
+    if(entry->mRsObj) {
+        entry->mRsObj->incUserRef();
+        return entry->mRsObj;
+    }
+
     // Seek to the beginning of object
     mReadStream->reset(entry->mOffset);
     switch (entry->mType) {
-        case A3D_CLASS_ID_UNKNOWN:
+        case RS_A3D_CLASS_ID_UNKNOWN:
             return NULL;
-        case A3D_CLASS_ID_MESH:
-            return Mesh::createFromStream(mRsc, mReadStream);
-        case A3D_CLASS_ID_SIMPLE_MESH:
-            return SimpleMesh::createFromStream(mRsc, mReadStream);
-        case A3D_CLASS_ID_TYPE:
-            return Type::createFromStream(mRsc, mReadStream);
-        case A3D_CLASS_ID_ELEMENT:
-            return Element::createFromStream(mRsc, mReadStream);
-        case A3D_CLASS_ID_ALLOCATION:
-            return Allocation::createFromStream(mRsc, mReadStream);
-        case A3D_CLASS_ID_PROGRAM_VERTEX:
-            return ProgramVertex::createFromStream(mRsc, mReadStream);
-        case A3D_CLASS_ID_PROGRAM_RASTER:
-            return ProgramRaster::createFromStream(mRsc, mReadStream);
-        case A3D_CLASS_ID_PROGRAM_FRAGMENT:
-            return ProgramFragment::createFromStream(mRsc, mReadStream);
-        case A3D_CLASS_ID_PROGRAM_STORE:
-            return ProgramStore::createFromStream(mRsc, mReadStream);
-        case A3D_CLASS_ID_SAMPLER:
-            return Sampler::createFromStream(mRsc, mReadStream);
-        case A3D_CLASS_ID_ANIMATION:
-            return Animation::createFromStream(mRsc, mReadStream);
-        case A3D_CLASS_ID_LIGHT:
-            return Light::createFromStream(mRsc, mReadStream);
-        case A3D_CLASS_ID_ADAPTER_1D:
-            return Adapter1D::createFromStream(mRsc, mReadStream);
-        case A3D_CLASS_ID_ADAPTER_2D:
-            return Adapter2D::createFromStream(mRsc, mReadStream);
-        case A3D_CLASS_ID_SCRIPT_C:
+        case RS_A3D_CLASS_ID_MESH:
+            entry->mRsObj = Mesh::createFromStream(mRSC, mReadStream);
+            break;
+        case RS_A3D_CLASS_ID_SIMPLE_MESH:
+            entry->mRsObj = SimpleMesh::createFromStream(mRSC, mReadStream);
+            break;
+        case RS_A3D_CLASS_ID_TYPE:
+            entry->mRsObj = Type::createFromStream(mRSC, mReadStream);
+            break;
+        case RS_A3D_CLASS_ID_ELEMENT:
+            entry->mRsObj = Element::createFromStream(mRSC, mReadStream);
+            break;
+        case RS_A3D_CLASS_ID_ALLOCATION:
+            entry->mRsObj = Allocation::createFromStream(mRSC, mReadStream);
+            break;
+        case RS_A3D_CLASS_ID_PROGRAM_VERTEX:
+            entry->mRsObj = ProgramVertex::createFromStream(mRSC, mReadStream);
+            break;
+        case RS_A3D_CLASS_ID_PROGRAM_RASTER:
+            entry->mRsObj = ProgramRaster::createFromStream(mRSC, mReadStream);
+            break;
+        case RS_A3D_CLASS_ID_PROGRAM_FRAGMENT:
+            entry->mRsObj = ProgramFragment::createFromStream(mRSC, mReadStream);
+            break;
+        case RS_A3D_CLASS_ID_PROGRAM_STORE:
+            entry->mRsObj = ProgramStore::createFromStream(mRSC, mReadStream);
+            break;
+        case RS_A3D_CLASS_ID_SAMPLER:
+            entry->mRsObj = Sampler::createFromStream(mRSC, mReadStream);
+            break;
+        case RS_A3D_CLASS_ID_ANIMATION:
+            entry->mRsObj = Animation::createFromStream(mRSC, mReadStream);
+            break;
+        case RS_A3D_CLASS_ID_LIGHT:
+            entry->mRsObj = Light::createFromStream(mRSC, mReadStream);
+            break;
+        case RS_A3D_CLASS_ID_ADAPTER_1D:
+            entry->mRsObj = Adapter1D::createFromStream(mRSC, mReadStream);
+            break;
+        case RS_A3D_CLASS_ID_ADAPTER_2D:
+            entry->mRsObj = Adapter2D::createFromStream(mRSC, mReadStream);
+            break;
+        case RS_A3D_CLASS_ID_SCRIPT_C:
             return NULL;
     }
-    return NULL;
+    if(entry->mRsObj) {
+        entry->mRsObj->incUserRef();
+    }
+    return entry->mRsObj;
 }
 
 bool FileA3D::writeFile(const char *filename)
@@ -226,14 +332,17 @@
     uint32_t writeIndexSize = mWriteIndex.size();
     headerStream.addU32(writeIndexSize);
     for(uint32_t i = 0; i < writeIndexSize; i ++) {
-        headerStream.addString(&mWriteIndex[i]->mID);
+        headerStream.addString(&mWriteIndex[i]->mObjectName);
         headerStream.addU32((uint32_t)mWriteIndex[i]->mType);
         if(mUse64BitOffsets){
             headerStream.addOffset(mWriteIndex[i]->mOffset);
+            headerStream.addOffset(mWriteIndex[i]->mLength);
         }
         else {
             uint32_t offset = (uint32_t)mWriteIndex[i]->mOffset;
             headerStream.addU32(offset);
+            offset = (uint32_t)mWriteIndex[i]->mLength;
+            headerStream.addU32(offset);
         }
     }
 
@@ -273,26 +382,93 @@
         mWriteStream = new OStream(initialStreamSize, false);
     }
     A3DIndexEntry *indexEntry = new A3DIndexEntry();
-    indexEntry->mID.setTo(obj->getName());
+    indexEntry->mObjectName.setTo(obj->getName());
     indexEntry->mType = obj->getClassId();
     indexEntry->mOffset = mWriteStream->getPos();
-    indexEntry->mRsObj = (void*)obj;
+    indexEntry->mRsObj = obj;
     mWriteIndex.push(indexEntry);
     obj->serialize(mWriteStream);
+    indexEntry->mLength = mWriteStream->getPos() - indexEntry->mOffset;
+    mWriteStream->align(4);
 }
 
 namespace android {
 namespace renderscript {
 
+void rsi_FileA3DGetNumIndexEntries(Context *rsc, int32_t *numEntries, RsFile file)
+{
+    FileA3D *fa3d = static_cast<FileA3D *>(file);
+
+    if(fa3d) {
+        *numEntries = fa3d->getNumIndexEntries();
+    }
+    else {
+        *numEntries = 0;
+    }
+}
+
+void rsi_FileA3DGetIndexEntries(Context *rsc, RsFileIndexEntry *fileEntries, uint32_t numEntries, RsFile file)
+{
+    FileA3D *fa3d = static_cast<FileA3D *>(file);
+
+    if(!fa3d) {
+        LOGE("Can't load index entries. No valid file");
+        return;
+    }
+
+    uint32_t numFileEntries = fa3d->getNumIndexEntries();
+    if(numFileEntries != numEntries || numEntries == 0 || fileEntries == NULL) {
+        LOGE("Can't load index entries. Invalid number requested");
+        return;
+    }
+
+    for(uint32_t i = 0; i < numFileEntries; i ++) {
+        const FileA3D::A3DIndexEntry *entry = fa3d->getIndexEntry(i);
+        fileEntries[i].classID = entry->getType();
+        fileEntries[i].objectName = entry->getObjectName().string();
+    }
+
+}
+
+RsObjectBase rsi_FileA3DGetEntryByIndex(Context *rsc, uint32_t index, RsFile file)
+{
+    FileA3D *fa3d = static_cast<FileA3D *>(file);
+    if(!fa3d) {
+        LOGE("Can't load entry. No valid file");
+        return NULL;
+    }
+
+    ObjectBase *obj = fa3d->initializeFromEntry(index);
+    LOGE("Returning object with name %s", obj->getName());
+
+    return obj;
+}
+
+RsFile rsi_FileA3DCreateFromAssetStream(Context *rsc, const void *data, uint32_t len)
+{
+    if (data == NULL) {
+        LOGE("File load failed. Asset stream is NULL");
+        return NULL;
+    }
+
+    FileA3D *fa3d = new FileA3D(rsc);
+
+    fa3d->load(data, len);
+    fa3d->incUserRef();
+
+    return fa3d;
+}
+
 
 RsFile rsi_FileOpen(Context *rsc, char const *path, unsigned int len)
 {
-    FileA3D *fa3d = new FileA3D;
+    FileA3D *fa3d = new FileA3D(rsc);
 
     FILE *f = fopen("/sdcard/test.a3d", "rb");
     if (f) {
-        fa3d->load(rsc, f);
+        fa3d->load(f);
         fclose(f);
+        fa3d->incUserRef();
         return fa3d;
     }
     delete fa3d;
diff --git a/rsFileA3D.h b/rsFileA3D.h
index e744291..b985907 100644
--- a/rsFileA3D.h
+++ b/rsFileA3D.h
@@ -18,21 +18,23 @@
 #define ANDROID_RS_FILE_A3D_H
 
 #include "RenderScript.h"
-#include "rsFileA3DDecls.h"
 #include "rsMesh.h"
 
 #include <utils/String8.h>
 #include "rsStream.h"
 #include <stdio.h>
 
+#define A3D_MAGIC_KEY "Android3D_ff"
+
 // ---------------------------------------------------------------------------
 namespace android {
+
 namespace renderscript {
 
-class FileA3D
+class FileA3D : public ObjectBase
 {
 public:
-    FileA3D();
+    FileA3D(Context *rsc);
     ~FileA3D();
 
     uint32_t mMajorVersion;
@@ -41,27 +43,47 @@
     uint64_t mStringTableOffset;
     bool mUse64BitOffsets;
 
-    struct A3DIndexEntry {
-        String8 mID;
-        A3DClassID mType;
+    class A3DIndexEntry {
+        String8 mObjectName;
+        RsA3DClassID mType;
         uint64_t mOffset;
-        void * mRsObj;
+        uint64_t mLength;
+        ObjectBase *mRsObj;
+    public:
+        friend class FileA3D;
+        const String8 &getObjectName() const {
+            return mObjectName;
+        }
+        RsA3DClassID getType() const {
+            return mType;
+        }
     };
 
-    bool load(Context *rsc, FILE *f);
-    size_t getNumLoadedEntries() const;
-    const A3DIndexEntry* getLoadedEntry(size_t index) const;
-    ObjectBase *initializeFromEntry(const A3DIndexEntry *entry);
+    bool load(FILE *f);
+    bool load(const void *data, size_t length);
+
+    size_t getNumIndexEntries() const;
+    const A3DIndexEntry* getIndexEntry(size_t index) const;
+    ObjectBase *initializeFromEntry(size_t index);
 
     void appendToFile(ObjectBase *obj);
     bool writeFile(const char *filename);
 
+    // Currently files do not get serialized,
+    // but we need to inherit from ObjectBase for ref tracking
+    virtual void serialize(OStream *stream) const {
+    }
+    virtual RsA3DClassID getClassId() const {
+        return RS_A3D_CLASS_ID_UNKNOWN;
+    }
+
 protected:
 
+    void parseHeader(IStream *headerStream);
+
     const uint8_t * mData;
     void * mAlloc;
     uint64_t mDataSize;
-    Context * mRsc;
 
     OStream *mWriteStream;
     Vector<A3DIndexEntry*> mWriteIndex;
diff --git a/rsFileA3DDecls.h b/rsFileA3DDecls.h
deleted file mode 100644
index b752442..0000000
--- a/rsFileA3DDecls.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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_RS_FILE_A3D_DECLS_H
-#define ANDROID_RS_FILE_A3D_DECLS_H
-
-
-#define A3D_MAGIC_KEY "Android3D_ff"
-
-namespace android {
-namespace renderscript {
-
-    enum A3DClassID {
-        A3D_CLASS_ID_UNKNOWN,
-        A3D_CLASS_ID_MESH,
-        A3D_CLASS_ID_SIMPLE_MESH,
-        A3D_CLASS_ID_TYPE,
-        A3D_CLASS_ID_ELEMENT,
-        A3D_CLASS_ID_ALLOCATION,
-        A3D_CLASS_ID_PROGRAM_VERTEX,
-        A3D_CLASS_ID_PROGRAM_RASTER,
-        A3D_CLASS_ID_PROGRAM_FRAGMENT,
-        A3D_CLASS_ID_PROGRAM_STORE,
-        A3D_CLASS_ID_SAMPLER,
-        A3D_CLASS_ID_ANIMATION,
-        A3D_CLASS_ID_LIGHT,
-        A3D_CLASS_ID_ADAPTER_1D,
-        A3D_CLASS_ID_ADAPTER_2D,
-        A3D_CLASS_ID_SCRIPT_C
-    };
-
-
-}
-}
-#endif //ANDROID_RS_FILE_A3D_H
-
-
-
diff --git a/rsLight.h b/rsLight.h
index 4216052..bd58979 100644
--- a/rsLight.h
+++ b/rsLight.h
@@ -38,7 +38,7 @@
 
     void setupGL(uint32_t num) const;
     virtual void serialize(OStream *stream) const;
-    virtual A3DClassID getClassId() const { return A3D_CLASS_ID_LIGHT; }
+    virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_LIGHT; }
     static Light *createFromStream(Context *rsc, IStream *stream);
 
 protected:
diff --git a/rsMesh.cpp b/rsMesh.cpp
index b51e28a..bd9cd27 100644
--- a/rsMesh.cpp
+++ b/rsMesh.cpp
@@ -107,8 +107,8 @@
 Mesh *Mesh::createFromStream(Context *rsc, IStream *stream)
 {
     // First make sure we are reading the correct object
-    A3DClassID classID = (A3DClassID)stream->loadU32();
-    if(classID != A3D_CLASS_ID_MESH) {
+    RsA3DClassID classID = (RsA3DClassID)stream->loadU32();
+    if(classID != RS_A3D_CLASS_ID_MESH) {
         LOGE("mesh loading skipped due to invalid class id");
         return NULL;
     }
diff --git a/rsMesh.h b/rsMesh.h
index e3edf52..8c7e8a4 100644
--- a/rsMesh.h
+++ b/rsMesh.h
@@ -70,9 +70,9 @@
 
     void analyzeElement();
     virtual void serialize(OStream *stream) const;
-    virtual A3DClassID getClassId() const { return A3D_CLASS_ID_MESH; }
+    virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_MESH; }
     static Mesh *createFromStream(Context *rsc, IStream *stream);
-    
+
 protected:
 };
 
diff --git a/rsObjectBase.h b/rsObjectBase.h
index f423232..ad95b81 100644
--- a/rsObjectBase.h
+++ b/rsObjectBase.h
@@ -54,7 +54,7 @@
 
     virtual void dumpLOGV(const char *prefix) const;
     virtual void serialize(OStream *stream) const = 0;
-    virtual A3DClassID getClassId() const = 0;
+    virtual RsA3DClassID getClassId() const = 0;
 
 protected:
     const char *mAllocFile;
diff --git a/rsProgramFragment.h b/rsProgramFragment.h
index 68593b5..e5bbe1b 100644
--- a/rsProgramFragment.h
+++ b/rsProgramFragment.h
@@ -41,7 +41,7 @@
     virtual void loadShader(Context *rsc);
     virtual void init(Context *rsc);
     virtual void serialize(OStream *stream) const;
-    virtual A3DClassID getClassId() const { return A3D_CLASS_ID_PROGRAM_FRAGMENT; }
+    virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_PROGRAM_FRAGMENT; }
     static ProgramFragment *createFromStream(Context *rsc, IStream *stream);
 
 protected:
diff --git a/rsProgramRaster.h b/rsProgramRaster.h
index 477208c..79b1475 100644
--- a/rsProgramRaster.h
+++ b/rsProgramRaster.h
@@ -37,7 +37,7 @@
     virtual void setupGL(const Context *, ProgramRasterState *);
     virtual void setupGL2(const Context *, ProgramRasterState *);
     virtual void serialize(OStream *stream) const;
-    virtual A3DClassID getClassId() const { return A3D_CLASS_ID_PROGRAM_RASTER; }
+    virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_PROGRAM_RASTER; }
     static ProgramRaster *createFromStream(Context *rsc, IStream *stream);
 
     void setLineWidth(float w);
diff --git a/rsProgramStore.h b/rsProgramStore.h
index c6c312f..fe8d78e 100644
--- a/rsProgramStore.h
+++ b/rsProgramStore.h
@@ -44,7 +44,7 @@
     void setDitherEnable(bool);
 
     virtual void serialize(OStream *stream) const;
-    virtual A3DClassID getClassId() const { return A3D_CLASS_ID_PROGRAM_STORE; }
+    virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_PROGRAM_STORE; }
     static ProgramStore *createFromStream(Context *rsc, IStream *stream);
 
 protected:
diff --git a/rsProgramVertex.h b/rsProgramVertex.h
index 734fabd..cb93eaf 100644
--- a/rsProgramVertex.h
+++ b/rsProgramVertex.h
@@ -53,7 +53,7 @@
     virtual void init(Context *);
 
     virtual void serialize(OStream *stream) const;
-    virtual A3DClassID getClassId() const { return A3D_CLASS_ID_PROGRAM_VERTEX; }
+    virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_PROGRAM_VERTEX; }
     static ProgramVertex *createFromStream(Context *rsc, IStream *stream);
 
 protected:
diff --git a/rsSampler.h b/rsSampler.h
index 1742111..3786439 100644
--- a/rsSampler.h
+++ b/rsSampler.h
@@ -45,9 +45,9 @@
 
     void bindToContext(SamplerState *, uint32_t slot);
     void unbindFromContext(SamplerState *);
-    
+
     virtual void serialize(OStream *stream) const;
-    virtual A3DClassID getClassId() const { return A3D_CLASS_ID_SAMPLER; }
+    virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_SAMPLER; }
     static Sampler *createFromStream(Context *rsc, IStream *stream);
 
 protected:
diff --git a/rsScriptC.h b/rsScriptC.h
index a144234..50e8a4c 100644
--- a/rsScriptC.h
+++ b/rsScriptC.h
@@ -61,9 +61,8 @@
     virtual void runForEach(Context *rsc, const Allocation *ain, Allocation *aout, uint32_t xStart, uint32_t xEnd);
     virtual void runForEach(Context *rsc, const Allocation *ain, Allocation *aout, uint32_t xStart, uint32_t yStart, uint32_t xEnd, uint32_t yEnd);
 
-
     virtual void serialize(OStream *stream) const {    }
-    virtual A3DClassID getClassId() const { return A3D_CLASS_ID_SCRIPT_C; }
+    virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_SCRIPT_C; }
     static Type *createFromStream(Context *rsc, IStream *stream) { return NULL; }
 
 protected:
diff --git a/rsSimpleMesh.cpp b/rsSimpleMesh.cpp
index 2dd082d..5eb4b80 100644
--- a/rsSimpleMesh.cpp
+++ b/rsSimpleMesh.cpp
@@ -48,15 +48,18 @@
 void SimpleMesh::render(Context *rsc) const
 {
     if (mPrimitiveType.get()) {
+        LOGE("Rendering primitive");
         renderRange(rsc, 0, mPrimitiveType->getDimX());
         return;
     }
 
     if (mIndexType.get()) {
+        LOGE("Rendering index");
         renderRange(rsc, 0, mIndexType->getDimX());
         return;
     }
 
+    LOGE("Rendering non-indexed");
     renderRange(rsc, 0, mVertexTypes[0]->getDimX());
 }
 
@@ -150,8 +153,8 @@
 SimpleMesh *SimpleMesh::createFromStream(Context *rsc, IStream *stream)
 {
     // First make sure we are reading the correct object
-    A3DClassID classID = (A3DClassID)stream->loadU32();
-    if(classID != A3D_CLASS_ID_SIMPLE_MESH) {
+    RsA3DClassID classID = (RsA3DClassID)stream->loadU32();
+    if(classID != RS_A3D_CLASS_ID_SIMPLE_MESH) {
         LOGE("simple mesh loading skipped due to invalid class id");
         return NULL;
     }
@@ -189,6 +192,25 @@
         }
     }
 
+    LOGE("Triangles: %u", indexType->getDimX()/3);
+    uint16_t *indices = (uint16_t*)indexAlloc->getPtr();
+    for(uint32_t i = 0; i < indexType->getDimX(); i += 3) {
+        LOGE("T: %.2u %.2u %2.u", indices[i], indices[i+1], indices[i+2]);
+    }
+
+    uint32_t numVerts = mesh->mVertexTypes[0]->getDimX();
+    LOGE("Vertices: %u", numVerts);
+    float *verts = (float*)mesh->mVertexBuffers[0]->getPtr();
+
+    for(uint32_t i = 0; i < numVerts; i ++) {
+
+        LOGE("Vpnt: %+4.2f %+4.2f %+4.2f %+4.2f %+4.2f %+4.2f %+4.2f %+4.2f", verts[8*i], verts[8*i+1], verts[8*i+2],
+                                                                                    verts[8*i+3], verts[8*i+4], verts[8*i+5],
+                                                                                    verts[8*i+6], verts[8*i+7] );
+    }
+
+    mesh->uploadAll(rsc);
+
     return mesh;
 }
 
diff --git a/rsSimpleMesh.h b/rsSimpleMesh.h
index 94e6a26..362c7fb 100644
--- a/rsSimpleMesh.h
+++ b/rsSimpleMesh.h
@@ -49,9 +49,9 @@
     void renderRange(Context *, uint32_t start, uint32_t len) const;
     void uploadAll(Context *);
     void updateGLPrimitive();
-    
+
     virtual void serialize(OStream *stream) const;
-    virtual A3DClassID getClassId() const { return A3D_CLASS_ID_SIMPLE_MESH; }
+    virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_SIMPLE_MESH; }
     static SimpleMesh *createFromStream(Context *rsc, IStream *stream);
 
 protected:
diff --git a/rsStream.cpp b/rsStream.cpp
index 03827dc..39874a9 100644
--- a/rsStream.cpp
+++ b/rsStream.cpp
@@ -53,10 +53,9 @@
 
 void IStream::loadString(String8 *s)
 {
-    LOGE("loadString");
     uint32_t len = loadU32();
-    LOGE("loadString len %i", len);
     s->setTo((const char *)&mData[mPos], len);
+    LOGE("loadString %s", s->string());
     mPos += len;
 }
 
diff --git a/rsStream.h b/rsStream.h
index 5ccd6ca..d401cd1 100644
--- a/rsStream.h
+++ b/rsStream.h
@@ -86,6 +86,13 @@
     OStream(uint64_t length, bool use64);
     ~OStream();
     
+    void align(uint32_t bytes) {
+        mPos = (mPos + (bytes - 1)) & (~(bytes - 1));
+        if(mPos >= mLength) {
+            growSize();
+        }
+    }
+    
     void addF(float v) {
         uint32_t uintV = *reinterpret_cast<uint32_t*> (&v);
         addU32(uintV);
diff --git a/rsType.cpp b/rsType.cpp
index 89e73b0..75abc76 100644
--- a/rsType.cpp
+++ b/rsType.cpp
@@ -200,8 +200,8 @@
 Type *Type::createFromStream(Context *rsc, IStream *stream)
 {
     // First make sure we are reading the correct object
-    A3DClassID classID = (A3DClassID)stream->loadU32();
-    if(classID != A3D_CLASS_ID_TYPE) {
+    RsA3DClassID classID = (RsA3DClassID)stream->loadU32();
+    if(classID != RS_A3D_CLASS_ID_TYPE) {
         LOGE("type loading skipped due to invalid class id\n");
         return NULL;
     }
diff --git a/rsType.h b/rsType.h
index f598f64..5b51e20 100644
--- a/rsType.h
+++ b/rsType.h
@@ -74,7 +74,7 @@
 
     void dumpLOGV(const char *prefix) const;
     virtual void serialize(OStream *stream) const;
-    virtual A3DClassID getClassId() const { return A3D_CLASS_ID_TYPE; }
+    virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_TYPE; }
     static Type *createFromStream(Context *rsc, IStream *stream);
 
 protected:
diff --git a/rsUtils.h b/rsUtils.h
index 7ea3b61..b0eb520 100644
--- a/rsUtils.h
+++ b/rsUtils.h
@@ -23,7 +23,6 @@
 #include <utils/Log.h>
 
 #include "rsStream.h"
-#include "rsFileA3DDecls.h"
 
 #include <utils/String8.h>
 #include <utils/Vector.h>