Streamlining texture creation.
Adding render target textureas.
Adding texture params for shaders.
Making it easier to bind root script.

Change-Id: I96dfc6ffba8bb7391d03a84682c43c82387e0be3
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/FragmentShader.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/FragmentShader.java
index ff6bbba..c8cc3ac 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/FragmentShader.java
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/FragmentShader.java
@@ -93,23 +93,40 @@
         return mProgram;
     }
 
-    public void updateTextures() {
+    ScriptField_ShaderParam_s getTextureParams() {
         RenderScriptGL rs = SceneManager.getRS();
         Resources res = SceneManager.getRes();
         if (rs == null || res == null) {
-            return;
+            return null;
         }
+
+        ArrayList<ScriptField_ShaderParam_s.Item> paramList;
+        paramList = new ArrayList<ScriptField_ShaderParam_s.Item>();
+
         int shaderTextureStart = mTextureTypes.size();
         for (int i = 0; i < mShaderTextureNames.size(); i ++) {
             ShaderParam sp = mSourceParams.get(mShaderTextureNames.get(i));
             if (sp != null && sp instanceof TextureParam) {
                 TextureParam p = (TextureParam)sp;
-                TextureBase tex = p.getTexture();
-                if (tex != null) {
-                    mProgram.bindTexture(tex.getRsData(), shaderTextureStart + i);
-                }
+                ScriptField_ShaderParam_s.Item paramRS = new ScriptField_ShaderParam_s.Item();
+                paramRS.bufferOffset = shaderTextureStart + i;
+                paramRS.transformTimestamp = 0;
+                paramRS.dataTimestamp = 0;
+                paramRS.data = p.getRSData().getAllocation();
+                paramList.add(paramRS);
             }
         }
+
+        ScriptField_ShaderParam_s rsParams = null;
+        int paramCount = paramList.size();
+        if (paramCount != 0) {
+            rsParams = new ScriptField_ShaderParam_s(rs, paramCount);
+            for (int i = 0; i < paramCount; i++) {
+                rsParams.set(paramList.get(i), i, false);
+            }
+            rsParams.copyAll();
+        }
+        return rsParams;
     }
 
     ScriptField_FragmentShader_s getRSData() {
@@ -126,6 +143,11 @@
         ScriptField_FragmentShader_s.Item item = new ScriptField_FragmentShader_s.Item();
         item.program = mProgram;
 
+        ScriptField_ShaderParam_s texParams = getTextureParams();
+        if (texParams != null) {
+            item.shaderTextureParams = texParams.getAllocation();
+        }
+
         linkConstants(rs);
         if (mPerShaderConstants != null) {
             item.shaderConst = mConstantBuffer;
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/RenderPass.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/RenderPass.java
index 3cd70f5..02fd69d 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/RenderPass.java
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/RenderPass.java
@@ -29,11 +29,11 @@
  */
 public class RenderPass extends SceneGraphBase {
 
-    Allocation mColorTarget;
+    TextureRenderTarget mColorTarget;
     Float4 mClearColor;
     boolean mShouldClearColor;
 
-    Allocation mDepthTarget;
+    TextureRenderTarget mDepthTarget;
     float mClearDepth;
     boolean mShouldClearDepth;
 
@@ -59,7 +59,7 @@
         mCamera = c;
     }
 
-    public void setColorTarget(Allocation colorTarget) {
+    public void setColorTarget(TextureRenderTarget colorTarget) {
         mColorTarget = colorTarget;
     }
     public void setClearColor(Float4 clearColor) {
@@ -69,7 +69,7 @@
         mShouldClearColor = shouldClearColor;
     }
 
-    public void setDepthTarget(Allocation depthTarget) {
+    public void setDepthTarget(TextureRenderTarget depthTarget) {
         mDepthTarget = depthTarget;
     }
     public void setClearDepth(float clearDepth) {
@@ -89,8 +89,12 @@
         }
 
         mRsField = new ScriptField_RenderPass_s.Item();
-        mRsField.color_target = mColorTarget;
-        mRsField.depth_target = mDepthTarget;
+        if (mColorTarget != null) {
+            mRsField.color_target = mColorTarget.getRsData(true).get_texture(0);
+        }
+        if (mColorTarget != null) {
+            mRsField.depth_target = mDepthTarget.getRsData(true).get_texture(0);
+        }
         mRsField.camera = mCamera != null ? mCamera.getRSData().getAllocation() : null;
 
         if (mObjectsToDraw.size() != 0) {
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Renderable.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Renderable.java
index 481b2de..9f7ab41 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Renderable.java
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Renderable.java
@@ -128,7 +128,7 @@
         }
     }
 
-    void updateTextures(RenderScriptGL rs, Resources res) {
+    void updateTextures(RenderScriptGL rs) {
         Iterator<ShaderParam> allParamsIter = mSourceParams.values().iterator();
         int paramIndex = 0;
         while (allParamsIter.hasNext()) {
@@ -137,7 +137,7 @@
                 TextureParam p = (TextureParam)sp;
                 TextureBase tex = p.getTexture();
                 if (tex != null) {
-                    mData.pf_textures[paramIndex++] = tex.getRsData();
+                    mData.pf_textures[paramIndex++] = tex.getRsData(false).getAllocation();
                 }
             }
         }
@@ -161,6 +161,7 @@
             return mField;
         }
         updateFieldItem(rs);
+        updateTextures(rs);
 
         mField = new ScriptField_Renderable_s(rs, 1);
         mField.set(mData, 0, true);
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Scene.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Scene.java
index 1c68e30..8c09860 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Scene.java
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Scene.java
@@ -23,6 +23,7 @@
 import java.util.regex.Pattern;
 
 import com.android.scenegraph.SceneManager;
+import com.android.scenegraph.TextureBase;
 
 import android.content.res.Resources;
 import android.os.AsyncTask;
@@ -37,38 +38,6 @@
 public class Scene extends SceneGraphBase {
     private static String TIMER_TAG = "TIMER";
 
-    private class ImageLoaderTask extends AsyncTask<ArrayList<RenderableBase>, Void, Boolean> {
-        protected Boolean doInBackground(ArrayList<RenderableBase>... objects) {
-            long start = System.currentTimeMillis();
-            for (int i = 0; i < objects[0].size(); i ++) {
-                Renderable dI = (Renderable)objects[0].get(i);
-                dI.updateTextures(mRS, mRes);
-            }
-            long end = System.currentTimeMillis();
-            Log.v(TIMER_TAG, "Texture init time: " + (end - start));
-            return new Boolean(true);
-        }
-
-        protected void onPostExecute(Boolean result) {
-        }
-    }
-
-    private class ShaderImageLoader extends AsyncTask<ArrayList<FragmentShader>, Void, Boolean> {
-        protected Boolean doInBackground(ArrayList<FragmentShader>... objects) {
-            long start = System.currentTimeMillis();
-            for (int i = 0; i < objects[0].size(); i ++) {
-                FragmentShader sI = objects[0].get(i);
-                sI.updateTextures();
-            }
-            long end = System.currentTimeMillis();
-            Log.v(TIMER_TAG, "Shader texture init time: " + (end - start));
-            return new Boolean(true);
-        }
-
-        protected void onPostExecute(Boolean result) {
-        }
-    }
-
     CompoundTransform mRootTransforms;
     HashMap<String, Transform> mTransformMap;
     ArrayList<RenderPass> mRenderPasses;
@@ -228,17 +197,13 @@
     }
 
     public void initRenderPassRS(RenderScriptGL rs, SceneManager sceneManager) {
-        new ShaderImageLoader().execute(mFragmentShaders);
         if (mRenderPasses.size() != 0) {
             mRenderPassAlloc = new ScriptField_RenderPass_s(mRS, mRenderPasses.size());
             for (int i = 0; i < mRenderPasses.size(); i ++) {
                 mRenderPassAlloc.set(mRenderPasses.get(i).getRsField(mRS, mRes), i, false);
-                new ImageLoaderTask().execute(mRenderPasses.get(i).getRenderables());
             }
             mRenderPassAlloc.copyAll();
             sceneManager.mRenderLoop.set_gRenderPasses(mRenderPassAlloc.getAllocation());
-        } else {
-            new ImageLoaderTask().execute(mRenderables);
         }
     }
 
@@ -279,9 +244,10 @@
         sceneManager.mRenderLoop.set_gFragmentShaders(shaderData);
     }
 
-    public void initRS(RenderScriptGL rs, Resources res, SceneManager sceneManager) {
-        mRS = rs;
-        mRes = res;
+    public void initRS() {
+        SceneManager sceneManager = SceneManager.getInstance();
+        mRS = SceneManager.getRS();
+        mRes = SceneManager.getRes();
         long start = System.currentTimeMillis();
         mTransformRSData = mRootTransforms.getRSData();
         long end = System.currentTimeMillis();
@@ -294,30 +260,38 @@
         Log.v(TIMER_TAG, "Script init time: " + (end - start));
 
         start = System.currentTimeMillis();
-        addDrawables(rs, res, sceneManager);
+        addDrawables(mRS, mRes, sceneManager);
         end = System.currentTimeMillis();
         Log.v(TIMER_TAG, "Renderable init time: " + (end - start));
 
-        addShaders(rs, res, sceneManager);
+        addShaders(mRS, mRes, sceneManager);
 
-        Allocation opaqueBuffer = Allocation.createSized(rs, Element.U32(rs), mRenderables.size());
-        Allocation transparentBuffer = Allocation.createSized(rs,
-                                                              Element.U32(rs), mRenderables.size());
+        Allocation opaqueBuffer = null;
+        if (mRenderables.size() > 0) {
+            opaqueBuffer = Allocation.createSized(mRS, Element.U32(mRS), mRenderables.size());
+        }
+        Allocation transparentBuffer = null;
+        if (mRenderables.size() > 0) {
+            transparentBuffer = Allocation.createSized(mRS, Element.U32(mRS), mRenderables.size());
+        }
 
         sceneManager.mRenderLoop.bind_gFrontToBack(opaqueBuffer);
         sceneManager.mRenderLoop.bind_gBackToFront(transparentBuffer);
 
-        Allocation cameraData = Allocation.createSized(rs, Element.ALLOCATION(rs), mCameras.size());
-        Allocation[] cameraAllocs = new Allocation[mCameras.size()];
-        for (int i = 0; i < mCameras.size(); i ++) {
-            cameraAllocs[i] = mCameras.get(i).getRSData().getAllocation();
+        if (mCameras.size() > 0) {
+            Allocation cameraData;
+            cameraData = Allocation.createSized(mRS, Element.ALLOCATION(mRS), mCameras.size());
+            Allocation[] cameraAllocs = new Allocation[mCameras.size()];
+            for (int i = 0; i < mCameras.size(); i ++) {
+                cameraAllocs[i] = mCameras.get(i).getRSData().getAllocation();
+            }
+            cameraData.copyFrom(cameraAllocs);
+            sceneManager.mRenderLoop.set_gCameras(cameraData);
         }
-        cameraData.copyFrom(cameraAllocs);
-        sceneManager.mRenderLoop.set_gCameras(cameraData);
 
-        if (mLights.size() != 0) {
-            Allocation lightData = Allocation.createSized(rs,
-                                                          Element.ALLOCATION(rs),
+        if (mLights.size() > 0) {
+            Allocation lightData = Allocation.createSized(mRS,
+                                                          Element.ALLOCATION(mRS),
                                                           mLights.size());
             Allocation[] lightAllocs = new Allocation[mLights.size()];
             for (int i = 0; i < mLights.size(); i ++) {
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneManager.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneManager.java
index 01712b4..0f14486 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneManager.java
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneManager.java
@@ -41,6 +41,7 @@
 import android.renderscript.Allocation.MipmapControl;
 import android.renderscript.Mesh;
 import android.renderscript.RenderScriptGL;
+import android.renderscript.Type.Builder;
 import android.util.Log;
 import android.view.SurfaceHolder;
 
@@ -70,6 +71,52 @@
     Scene mActiveScene;
     private static SceneManager sSceneManager;
 
+    private Allocation sDefault2D;
+    private Allocation sDefaultCube;
+
+    private static Allocation getDefault(boolean isCube) {
+        final int dimension = 4;
+        final int bytesPerPixel = 4;
+        int arraySize = dimension * dimension * bytesPerPixel;
+
+        RenderScriptGL rs = sSceneManager.mRS;
+        Type.Builder b = new Type.Builder(rs, Element.RGBA_8888(rs));
+        b.setX(dimension).setY(dimension);
+        if (isCube) {
+            b.setFaces(true);
+            arraySize *= 6;
+        }
+        Type bitmapType = b.create();
+
+        Allocation.MipmapControl mip = Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE;
+        int usage =  Allocation.USAGE_GRAPHICS_TEXTURE;
+        Allocation defaultImage = Allocation.createTyped(rs, bitmapType, mip, usage);
+
+        byte imageData[] = new byte[arraySize];
+        defaultImage.copyFrom(imageData);
+        return defaultImage;
+    }
+
+    static Allocation getDefaultTex2D() {
+        if (sSceneManager == null) {
+            return null;
+        }
+        if (sSceneManager.sDefault2D == null) {
+            sSceneManager.sDefault2D = getDefault(false);
+        }
+        return sSceneManager.sDefault2D;
+    }
+
+    static Allocation getDefaultTexCube() {
+        if (sSceneManager == null) {
+            return null;
+        }
+        if (sSceneManager.sDefaultCube != null) {
+            sSceneManager.sDefault2D = getDefault(true);
+        }
+        return sSceneManager.sDefaultCube;
+    }
+
     public static boolean isSDCardPath(String path) {
         int sdCardIndex = path.indexOf("sdcard/");
         // We are looking for /sdcard/ or sdcard/
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Texture2D.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Texture2D.java
index 2f04858..0809df8 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Texture2D.java
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Texture2D.java
@@ -32,9 +32,11 @@
     String mFileDir;
 
     public Texture2D() {
+        super(ScriptC_export.const_TextureType_TEXTURE_2D);
     }
 
     public Texture2D(Allocation tex) {
+        super(ScriptC_export.const_TextureType_TEXTURE_2D);
         setTexture(tex);
     }
 
@@ -51,12 +53,22 @@
     }
 
     public void setTexture(Allocation tex) {
-        mRsTexture = tex;
+        mData.texture = tex;
+        if (mField != null) {
+            mField.set_texture(0, mData.texture, true);
+        }
     }
 
-    Allocation getRsData() {
-        if (mRsTexture != null) {
-            return mRsTexture;
+    void load() {
+        RenderScriptGL rs = SceneManager.getRS();
+        Resources res = SceneManager.getRes();
+        String shortName = mFileName.substring(mFileName.lastIndexOf('/') + 1);
+        setTexture(SceneManager.loadTexture2D(mFileDir + shortName, rs, res));
+    }
+
+    ScriptField_Texture_s getRsData(boolean loadNow) {
+        if (mField != null) {
+            return mField;
         }
 
         RenderScriptGL rs = SceneManager.getRS();
@@ -65,10 +77,17 @@
             return null;
         }
 
-        String shortName = mFileName.substring(mFileName.lastIndexOf('/') + 1);
-        mRsTexture = SceneManager.loadTexture2D(mFileDir + shortName, rs, res);
+        mField = new ScriptField_Texture_s(rs, 1);
 
-        return mRsTexture;
+        if (loadNow) {
+            load();
+        } else {
+            mData.texture = SceneManager.getDefaultTex2D();
+            new SingleImageLoaderTask().execute(this);
+        }
+
+        mField.set(mData, 0, true);
+        return mField;
     }
 }
 
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureBase.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureBase.java
index 425c6d6..ba49d4e 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureBase.java
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureBase.java
@@ -19,7 +19,7 @@
 import java.lang.Math;
 
 import com.android.scenegraph.SceneManager;
-
+import android.os.AsyncTask;
 import android.content.res.Resources;
 import android.renderscript.*;
 import android.util.Log;
@@ -28,8 +28,27 @@
  * @hide
  */
 public abstract class TextureBase extends SceneGraphBase {
+
+    class SingleImageLoaderTask extends AsyncTask<TextureBase, Void, Boolean> {
+        protected Boolean doInBackground(TextureBase... objects) {
+            TextureBase tex = objects[0];
+            tex.load();
+            return new Boolean(true);
+        }
+        protected void onPostExecute(Boolean result) {
+        }
+    }
+
+    ScriptField_Texture_s.Item mData;
+    ScriptField_Texture_s mField;
+    TextureBase(int type) {
+        mData = new ScriptField_Texture_s.Item();
+        mData.type = type;
+    }
+
     protected Allocation mRsTexture;
-    abstract Allocation getRsData();
+    abstract ScriptField_Texture_s getRsData(boolean loadNow);
+    abstract void load();
 }
 
 
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureCube.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureCube.java
index ba42494..05870e7 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureCube.java
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureCube.java
@@ -33,13 +33,16 @@
     String mFileDir;
 
     public TextureCube() {
+        super(ScriptC_export.const_TextureType_TEXTURE_CUBE);
     }
 
     public TextureCube(Allocation tex) {
+        super(ScriptC_export.const_TextureType_TEXTURE_CUBE);
         setTexture(tex);
     }
 
     public TextureCube(String dir, String file) {
+        super(ScriptC_export.const_TextureType_TEXTURE_CUBE);
         setFileDir(dir);
         setFileName(file);
     }
@@ -57,12 +60,22 @@
     }
 
     public void setTexture(Allocation tex) {
-        mRsTexture = tex;
+        mData.texture = tex;
+        if (mField != null) {
+            mField.set_texture(0, mData.texture, true);
+        }
     }
 
-    Allocation getRsData() {
-        if (mRsTexture != null) {
-            return mRsTexture;
+    void load() {
+        RenderScriptGL rs = SceneManager.getRS();
+        Resources res = SceneManager.getRes();
+        String shortName = mFileName.substring(mFileName.lastIndexOf('/') + 1);
+        setTexture(SceneManager.loadCubemap(mFileDir + shortName, rs, res));
+    }
+
+    ScriptField_Texture_s getRsData(boolean loadNow) {
+        if (mField != null) {
+            return mField;
         }
 
         RenderScriptGL rs = SceneManager.getRS();
@@ -71,10 +84,17 @@
             return null;
         }
 
-        String shortName = mFileName.substring(mFileName.lastIndexOf('/') + 1);
-        mRsTexture = SceneManager.loadCubemap(mFileDir + shortName, rs, res);
+        mField = new ScriptField_Texture_s(rs, 1);
 
-        return mRsTexture;
+        if (loadNow) {
+            load();
+        } else {
+            mData.texture = SceneManager.getDefaultTexCube();
+            new SingleImageLoaderTask().execute(this);
+        }
+
+        mField.set(mData, 0, true);
+        return mField;
     }
 }
 
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureParam.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureParam.java
index dd6b8f2..e656ed2 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureParam.java
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureParam.java
@@ -54,6 +54,10 @@
     }
 
     void initLocalData() {
+        mData.type = ScriptC_export.const_ShaderParam_TEXTURE;
+        if (mTexture != null) {
+            mData.texture = mTexture.getRsData(false).getAllocation();
+        }
     }
 }
 
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureRenderTarget.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureRenderTarget.java
new file mode 100644
index 0000000..6aa29a5
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureRenderTarget.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2012 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.scenegraph;
+
+import java.lang.Math;
+
+import com.android.scenegraph.SceneManager;
+
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public class TextureRenderTarget extends TextureBase {
+    public TextureRenderTarget() {
+        super(ScriptC_export.const_TextureType_TEXTURE_RENDER_TARGET);
+    }
+
+    public TextureRenderTarget(Allocation tex) {
+        super(ScriptC_export.const_TextureType_TEXTURE_RENDER_TARGET);
+        setTexture(tex);
+    }
+
+    public void setTexture(Allocation tex) {
+        mData.texture = tex;
+        if (mField != null) {
+            mField.set_texture(0, mData.texture, true);
+        }
+    }
+
+    void load() {
+    }
+
+    ScriptField_Texture_s getRsData(boolean loadNow) {
+        if (mField != null) {
+            return mField;
+        }
+
+        RenderScriptGL rs = SceneManager.getRS();
+        if (rs == null) {
+            return null;
+        }
+
+        mField = new ScriptField_Texture_s(rs, 1);
+        mField.set(mData, 0, true);
+        return mField;
+    }
+}
+
+
+
+
+
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/export.rs b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/export.rs
index c34c91e..b438a43 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/export.rs
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/export.rs
@@ -43,6 +43,10 @@
 const int Transform_ROTATE = TRANSFORM_ROTATE;
 const int Transform_SCALE = TRANSFORM_SCALE;
 
+const int TextureType_TEXTURE_2D = TEXTURE_2D;
+const int TextureType_TEXTURE_CUBE = TEXTURE_CUBE;
+const int TextureType_TEXTURE_RENDER_TARGET = TEXTURE_RENDER_TARGET;
+
 SgTransform *exportPtr;
 SgTransformComponent *componentPtr;
 SgRenderState *sExport;
@@ -54,3 +58,4 @@
 SgShaderParamData *spDataExport;
 SgVertexShader *pvExport;
 SgFragmentShader *pfExport;
+SgTexture *texExport;
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/fragment_params.rs b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/fragment_params.rs
index f5816ed..7202285 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/fragment_params.rs
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/fragment_params.rs
@@ -26,4 +26,5 @@
     SgFragmentShader *shader = (SgFragmentShader *)rsGetElementAt(*v_out, 0);
     const SgCamera *camera = (const SgCamera*)usrData;
     processAllParams(shader->shaderConst, shader->shaderConstParams, camera);
+    processTextureParams(shader);
 }
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/params.rsh b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/params.rsh
index d1edb72..575794b 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/params.rsh
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/params.rsh
@@ -19,8 +19,7 @@
 #include "scenegraph_objects.rsh"
 
 //#define DEBUG_PARAMS
-static void debugParam(SgShaderParam *p, SgShaderParamData *pData,
-                       uint8_t *constantBuffer, const SgCamera *currentCam) {
+static void debugParam(SgShaderParam *p, SgShaderParamData *pData) {
     rsDebug("____________ Param ____________", p);
     printName(pData->paramName);
     rsDebug("bufferOffset", p->bufferOffset);
@@ -28,7 +27,6 @@
     rsDebug("data timestamp ", pData->timestamp);
     rsDebug("param timestamp", p->dataTimestamp);
 
-    uint8_t *dataPtr = constantBuffer + p->bufferOffset;
     const SgTransform *pTransform = NULL;
     if (rsIsObject(pData->transform)) {
         pTransform = (const SgTransform *)rsGetElementAt(pData->transform, 0);
@@ -70,7 +68,9 @@
 }
 
 static bool processParam(SgShaderParam *p, SgShaderParamData *pData,
-                         uint8_t *constantBuffer, const SgCamera *currentCam) {
+                         uint8_t *constantBuffer,
+                         const SgCamera *currentCam,
+                         SgFragmentShader *shader) {
     bool isDataOnly = (pData->type > SHADER_PARAM_DATA_ONLY);
     const SgTransform *pTransform = NULL;
     if (rsIsObject(pData->transform)) {
@@ -97,9 +97,18 @@
         pLight = (const SgLight *)rsGetElementAt(pData->light, 0);
     }
 
-    uint8_t *dataPtr = constantBuffer + p->bufferOffset;
+    uint8_t *dataPtr = NULL;
+    const SgTexture *tex = NULL;
+    if (pData->type == SHADER_PARAM_TEXTURE) {
+        tex = rsGetElementAt(pData->texture, 0);
+    } else {
+        dataPtr = constantBuffer + p->bufferOffset;
+    }
 
-    switch(pData->type) {
+    switch (pData->type) {
+    case SHADER_PARAM_TEXTURE:
+        rsgBindTexture(shader->program, p->bufferOffset, tex->texture);
+        break;
     case SHADER_PARAM_FLOAT4_DATA:
         writeFloatData((float*)dataPtr, &pData->float_value, p->float_vecSize);
         break;
@@ -161,9 +170,24 @@
             SgShaderParam *current = (SgShaderParam*)rsGetElementAt(allParams, i);
             SgShaderParamData *currentData = (SgShaderParamData*)rsGetElementAt(current->data, 0);
 #ifdef DEBUG_PARAMS
-            debugParam(current, currentData, constantBuffer, camera);
+            debugParam(current, currentData);
 #endif // DEBUG_PARAMS
-            updated = processParam(current, currentData, constantBuffer, camera) || updated;
+            updated = processParam(current, currentData, constantBuffer, camera, NULL) || updated;
         }
     }
 }
+
+static void processTextureParams(SgFragmentShader *shader) {
+    int numParams = 0;
+    if (rsIsObject(shader->shaderTextureParams)) {
+        numParams = rsAllocationGetDimX(shader->shaderTextureParams);
+    }
+    for (int i = 0; i < numParams; i ++) {
+        SgShaderParam *current = (SgShaderParam*)rsGetElementAt(shader->shaderTextureParams, i);
+        SgShaderParamData *currentData = (SgShaderParamData*)rsGetElementAt(current->data, 0);
+#ifdef DEBUG_PARAMS
+        debugParam(current, currentData);
+#endif // DEBUG_PARAMS
+        processParam(current, currentData, NULL, NULL, shader);
+    }
+}
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/render.rs b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/render.rs
index ecfec08..aea0113 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/render.rs
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/render.rs
@@ -49,7 +49,7 @@
 
 static rs_allocation nullAlloc;
 
-//#define DEBUG_RENDERABLES
+// #define DEBUG_RENDERABLES
 static void draw(SgRenderable *obj) {
 #ifdef DEBUG_RENDERABLES
     const SgTransform *objTransform = (const SgTransform *)rsGetElementAt(obj->transformMatrix, 0);
@@ -87,11 +87,8 @@
     rsgBindProgramFragment(pf->program);
 
     for (uint32_t i = 0; i < obj->pf_num_textures; i ++) {
-        if (rsIsObject(obj->pf_textures[i])) {
-            rsgBindTexture(pf->program, i, obj->pf_textures[i]);
-        } else {
-            rsgBindTexture(pf->program, i, gTGrid);
-        }
+        const SgTexture *tex = rsGetElementAt(obj->pf_textures[i], 0);
+        rsgBindTexture(pf->program, i, tex->texture);
     }
 
     rsgDrawMesh(obj->mesh, obj->meshIndex);
@@ -117,8 +114,10 @@
 
 static void prepareCameras() {
     // now compute all the camera matrices
-    float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
-    rsForEach(gCameraScript, gCameras, nullAlloc, &aspect, sizeof(aspect));
+    if (rsIsObject(gCameras)) {
+        float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
+        rsForEach(gCameraScript, gCameras, nullAlloc, &aspect, sizeof(aspect));
+    }
 }
 
 static void prepareLights() {
@@ -164,20 +163,21 @@
     drawSorted();
 }
 
-void root(const void *v_in, void *v_out) {
+int root(void) {
 #ifdef DEBUG_RENDERABLES
     rsDebug("=============================================================================", 0);
 #endif // DEBUG_RENDERABLES
+
     // first step is to update the transform hierachy
-    rsForEach(gTransformScript, gRootNode->children, nullAlloc, 0, 0);
+    if (gRootNode && rsIsObject(gRootNode->children)) {
+        rsForEach(gTransformScript, gRootNode->children, nullAlloc, 0, 0);
+    }
 
     prepareCameras();
     prepareLights();
 
-    rsgClearDepth(1.0f);
-
-    int numRenderables = rsAllocationGetDimX(gRenderableObjects);
     if (rsIsObject(gRenderPasses)) {
+        rsgClearDepth(1.0f);
         int numPasses = rsAllocationGetDimX(gRenderPasses);
         for (uint i = 0; i < numPasses; i ++) {
             gFrontToBackCount = 0;
@@ -208,10 +208,14 @@
         gBackToFrontCount = 0;
         rsgClearColor(1.0f, 1.0f, 1.0f, 1.0f);
         rsgClearDepth(1.0f);
-        rs_allocation *camAlloc = (rs_allocation*)rsGetElementAt(gCameras, 1);
-        updateActiveCamera(*camAlloc);
+
+        if (rsIsObject(gCameras)) {
+            rs_allocation *camAlloc = (rs_allocation*)rsGetElementAt(gCameras, 0);
+            updateActiveCamera(*camAlloc);
+        }
         drawAllObjects(gRenderableObjects);
     }
+    return 10;
 }
 
 // Search through sorted and culled objects
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/scenegraph_objects.rsh b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/scenegraph_objects.rsh
index 511d78b..bdca3ab 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/scenegraph_objects.rsh
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/scenegraph_objects.rsh
@@ -33,10 +33,10 @@
 #define LIGHT_DIRECTIONAL 1
 
 // Shader params that involve only data
-#define SHADER_PARAM_DATA_ONLY       10000
-#define SHADER_PARAM_FLOAT4_DATA     10001
-#define SHADER_PARAM_TRANSFORM_DATA  10002
-#define SHADER_PARAM_TRANSFORM_MODEL 10003
+#define SHADER_PARAM_DATA_ONLY                 10000
+#define SHADER_PARAM_FLOAT4_DATA               10001
+#define SHADER_PARAM_TRANSFORM_DATA            10002
+#define SHADER_PARAM_TRANSFORM_MODEL           10003
 
 // Shader params that involve camera
 #define SHADER_PARAM_CAMERA                    1000
@@ -54,11 +54,12 @@
 #define SHADER_PARAM_FLOAT4_LIGHT_POS          104
 #define SHADER_PARAM_FLOAT4_LIGHT_DIR          105
 
-#define SHADER_PARAM_TEXTURE 10
+#define SHADER_PARAM_TEXTURE                   10
 
-#define TEXTURE_NONE 0
-#define TEXTURE_2D 1
-#define TEXTURE_CUBE 2
+#define TEXTURE_NONE          0
+#define TEXTURE_2D            1
+#define TEXTURE_CUBE          2
+#define TEXTURE_RENDER_TARGET 3
 
 typedef struct TransformComponent_s {
     float4 value;
@@ -96,6 +97,8 @@
     rs_allocation shaderConst;
     // ShaderParam's that populate data
     rs_allocation shaderConstParams;
+    // ShaderParam's that set textures
+    rs_allocation shaderTextureParams;
     // location of the per object constants on the buffer
     int objectConstIndex;
 } SgFragmentShader;
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/FullscreenBlur.java b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/FullscreenBlur.java
index 3bad3b3..28f916c 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/FullscreenBlur.java
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/FullscreenBlur.java
@@ -35,12 +35,12 @@
 

 class FullscreenBlur {

 

-    static Allocation sRenderTargetBlur0Color;

-    static Allocation sRenderTargetBlur0Depth;

-    static Allocation sRenderTargetBlur1Color;

-    static Allocation sRenderTargetBlur1Depth;

-    static Allocation sRenderTargetBlur2Color;

-    static Allocation sRenderTargetBlur2Depth;

+    static TextureRenderTarget sRenderTargetBlur0Color;

+    static TextureRenderTarget sRenderTargetBlur0Depth;

+    static TextureRenderTarget sRenderTargetBlur1Color;

+    static TextureRenderTarget sRenderTargetBlur1Depth;

+    static TextureRenderTarget sRenderTargetBlur2Color;

+    static TextureRenderTarget sRenderTargetBlur2Depth;

 

     static FragmentShader mPF_BlurH;

     static FragmentShader mPF_BlurV;

@@ -49,23 +49,28 @@
     static VertexShader mPV_Paint;

     static VertexShader mPV_Blur;

 

+    static int targetWidth;

+    static int targetHeight;

+

     // This is only used when full screen blur is enabled

     // Basically, it's the offscreen render targets

     static void createRenderTargets(RenderScriptGL rs, int w, int h) {

+        targetWidth = w/8;

+        targetHeight = h/8;

         Type.Builder b = new Type.Builder(rs, Element.RGBA_8888(rs));

-        Type renderType = b.setX(w/8).setY(h/8).create();

+        Type renderType = b.setX(targetWidth).setY(targetHeight).create();

         int usage = Allocation.USAGE_GRAPHICS_TEXTURE | Allocation.USAGE_GRAPHICS_RENDER_TARGET;

-        sRenderTargetBlur0Color = Allocation.createTyped(rs, renderType, usage);

-        sRenderTargetBlur1Color = Allocation.createTyped(rs, renderType, usage);

-        sRenderTargetBlur2Color = Allocation.createTyped(rs, renderType, usage);

+        sRenderTargetBlur0Color = new TextureRenderTarget(Allocation.createTyped(rs, renderType, usage));

+        sRenderTargetBlur1Color = new TextureRenderTarget(Allocation.createTyped(rs, renderType, usage));

+        sRenderTargetBlur2Color = new TextureRenderTarget(Allocation.createTyped(rs, renderType, usage));

 

         b = new Type.Builder(rs, Element.createPixel(rs, Element.DataType.UNSIGNED_16,

                                                      Element.DataKind.PIXEL_DEPTH));

-        renderType = b.setX(w/8).setY(h/8).create();

+        renderType = b.setX(targetWidth).setY(targetHeight).create();

         usage = Allocation.USAGE_GRAPHICS_RENDER_TARGET;

-        sRenderTargetBlur0Depth = Allocation.createTyped(rs, renderType, usage);

-        sRenderTargetBlur1Depth = Allocation.createTyped(rs, renderType, usage);

-        sRenderTargetBlur2Depth = Allocation.createTyped(rs, renderType, usage);

+        sRenderTargetBlur0Depth = new TextureRenderTarget(Allocation.createTyped(rs, renderType, usage));

+        sRenderTargetBlur1Depth = new TextureRenderTarget(Allocation.createTyped(rs, renderType, usage));

+        sRenderTargetBlur2Depth = new TextureRenderTarget(Allocation.createTyped(rs, renderType, usage));

     }

 

     static void addOffsets(Renderable quad, float advance) {

@@ -75,7 +80,7 @@
         quad.appendSourceParams(new Float4Param("blurOffset3", advance * 3.5f));

     }

 

-    static RenderPass addPass(Scene scene, Camera cam, Allocation color, Allocation depth) {

+    static RenderPass addPass(Scene scene, Camera cam, TextureRenderTarget color, TextureRenderTarget depth) {

         RenderPass pass = new RenderPass();

         pass.setColorTarget(color);

         pass.setDepthTarget(depth);

@@ -117,7 +122,7 @@
                                              sRenderTargetBlur2Color,

                                              sRenderTargetBlur2Depth);

         Renderable quad = sceneManager.getRenderableQuad("ScreenAlignedQuadS", selectCol);

-        quad.appendSourceParams(new TextureParam("color", new Texture2D(sRenderTargetBlur0Color)));

+        quad.appendSourceParams(new TextureParam("color", sRenderTargetBlur0Color));

         selectColorPass.appendRenderable(quad);

 

         // Horizontal blur

@@ -125,8 +130,8 @@
                                                 sRenderTargetBlur1Color,

                                                 sRenderTargetBlur1Depth);

         quad = sceneManager.getRenderableQuad("ScreenAlignedQuadH", hBlur);

-        quad.appendSourceParams(new TextureParam("color", new Texture2D(sRenderTargetBlur2Color)));

-        addOffsets(quad, 1.0f / (float)sRenderTargetBlur0Color.getType().getX());

+        quad.appendSourceParams(new TextureParam("color", sRenderTargetBlur2Color));

+        addOffsets(quad, 1.0f / (float)targetWidth);

         horizontalBlurPass.appendRenderable(quad);

 

         // Vertical Blur

@@ -134,8 +139,8 @@
                                               sRenderTargetBlur2Color,

                                               sRenderTargetBlur2Depth);

         quad = sceneManager.getRenderableQuad("ScreenAlignedQuadV", vBlur);

-        quad.appendSourceParams(new TextureParam("color", new Texture2D(sRenderTargetBlur1Color)));

-        addOffsets(quad, 1.0f / (float)sRenderTargetBlur0Color.getType().getY());

+        quad.appendSourceParams(new TextureParam("color", sRenderTargetBlur1Color));

+        addOffsets(quad, 1.0f / (float)targetHeight);

         verticalBlurPass.appendRenderable(quad);

     }

 

@@ -148,7 +153,7 @@
 

         RenderPass compositePass = addPass(scene, cam, null, null);

         Renderable quad = sceneManager.getRenderableQuad("ScreenAlignedQuadComposite", drawTex);

-        quad.appendSourceParams(new TextureParam("color", new Texture2D(sRenderTargetBlur2Color)));

+        quad.appendSourceParams(new TextureParam("color", sRenderTargetBlur2Color));

         compositePass.appendRenderable(quad);

     }

 

diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/TestAppLoadingScreen.java b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/TestAppLoadingScreen.java
index 60616cc..5bd8f0b 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/TestAppLoadingScreen.java
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/TestAppLoadingScreen.java
@@ -21,6 +21,8 @@
 import java.util.Map;
 import java.util.Vector;
 
+import com.android.scenegraph.SceneManager;
+
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -52,7 +54,11 @@
     }
 
     public void showLoadingScreen(boolean show) {
-        mScript.set_gInitialized(!show);
+        if (show) {
+            mRS.bindRootScript(mScript);
+        } else {
+            mRS.bindRootScript(SceneManager.getInstance().getRenderLoop());
+        }
     }
 
     // The loading screen has some elements that shouldn't be loaded on the UI thread
@@ -104,10 +110,4 @@
         mScript = new ScriptC_test_app(mRS, mRes, R.raw.test_app);
         mRS.bindRootScript(mScript);
     }
-
-    public void setRenderLoop(ScriptC renderLoop) {
-        mScript.set_gRenderLoop(renderLoop);
-        Allocation dummyAlloc = Allocation.createSized(mRS, Element.I32(mRS), 1);
-        mScript.set_gDummyAlloc(dummyAlloc);
-    }
 }
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/TestAppRS.java b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/TestAppRS.java
index 08175f1..7bf7812 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/TestAppRS.java
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/TestAppRS.java
@@ -108,7 +108,6 @@
         // Initi renderscript stuff specific to the app. This will need to be abstracted out later.
         FullscreenBlur.createRenderTargets(mRS, mWidth, mHeight);
         initPaintShaders();
-        mLoadingScreen.setRenderLoop(mSceneManager.getRenderLoop());
 
         // Load a scene to render
         mSceneManager.loadModel(mFilePath + modelName, mLoadedCallback);
@@ -257,7 +256,7 @@
         }
 
         long start = System.currentTimeMillis();
-        mActiveScene.initRS(mRS, mRes, mSceneManager);
+        mActiveScene.initRS();
         long end = System.currentTimeMillis();
         Log.v("TIMER", "Scene init time: " + (end - start));
 
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/test_app.rs b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/test_app.rs
index e4dcc39..997a1a7 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/test_app.rs
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/test_app.rs
@@ -35,11 +35,6 @@
 
 rs_program_store gPFSBackground;
 
-rs_allocation gDummyAlloc;
-rs_script gRenderLoop;
-
-bool gInitialized = false;
-
 float gRotate;
 
 void init() {
@@ -84,15 +79,8 @@
 }
 
 int root(void) {
-    rs_allocation nullAlloc;
-    if (!gInitialized) {
-        rsgClearColor(1.0f, 1.0f, 1.0f, 1.0f);
-        rsgClearDepth(1.0f);
-        displayLoading();
-        return 30;
-    }
-
-    rsForEach(gRenderLoop, gDummyAlloc, nullAlloc);
-
-    return 10;
+    rsgClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+    rsgClearDepth(1.0f);
+    displayLoading();
+    return 30;
 }