Adding better default behaviour for programmatically created objects.

Change-Id: I24078b27f9ddf7f36855eaf223cd4211f459bc78
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/FragmentShader.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/FragmentShader.java
index c8cc3ac..c8e25feb 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/FragmentShader.java
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/FragmentShader.java
@@ -48,6 +48,11 @@
             return this;
         }
 
+        public Builder setShader(String code) {
+            mBuilder.setShader(code);
+            return this;
+        }
+
         public Builder setObjectConst(Type type) {
             mShader.mPerObjConstants = type;
             return this;
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Renderable.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Renderable.java
index 9f7ab41..3476e35 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Renderable.java
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Renderable.java
@@ -196,6 +196,9 @@
     }
 
     void updateFieldItem(RenderScriptGL rs) {
+        if (mRenderState == null) {
+            mRenderState = SceneManager.getDefaultState();
+        }
         updateVertexConstants(rs);
         updateFragmentConstants(rs);
 
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Scene.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Scene.java
index 8c09860..e840346 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Scene.java
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Scene.java
@@ -75,6 +75,9 @@
     }
 
     public void appendTransform(Transform t) {
+        if (t == null) {
+            throw new RuntimeException("Adding null object");
+        }
         mRootTransforms.appendChild(t);
     }
 
@@ -88,6 +91,9 @@
     }
 
     public void appendRenderPass(RenderPass p) {
+        if (p == null) {
+            throw new RuntimeException("Adding null object");
+        }
         mRenderPasses.add(p);
     }
 
@@ -96,18 +102,30 @@
     }
 
     public void appendLight(LightBase l) {
+        if (l == null) {
+            throw new RuntimeException("Adding null object");
+        }
         mLights.add(l);
     }
 
     public void appendCamera(Camera c) {
+        if (c == null) {
+            throw new RuntimeException("Adding null object");
+        }
         mCameras.add(c);
     }
 
     public void appendShader(FragmentShader f) {
+        if (f == null) {
+            throw new RuntimeException("Adding null object");
+        }
         mFragmentShaders.add(f);
     }
 
     public void appendShader(VertexShader v) {
+        if (v == null) {
+            throw new RuntimeException("Adding null object");
+        }
         mVertexShaders.add(v);
     }
 
@@ -120,6 +138,9 @@
     }
 
     public void appendRenderable(RenderableBase d) {
+        if (d == null) {
+            throw new RuntimeException("Adding null object");
+        }
         mRenderables.add(d);
         mRenderableMap.put(d.getName(), d);
     }
@@ -133,6 +154,9 @@
     }
 
     public void appendTextures(Texture2D tex) {
+        if (tex == null) {
+            throw new RuntimeException("Adding null object");
+        }
         mTextures.add(tex);
     }
 
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneManager.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneManager.java
index 535905a..2e9a5eb 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneManager.java
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneManager.java
@@ -29,8 +29,10 @@
 import java.util.regex.Pattern;
 
 import com.android.scenegraph.Camera;
+import com.android.scenegraph.FragmentShader;
 import com.android.scenegraph.MatrixTransform;
 import com.android.scenegraph.Scene;
+import com.android.scenegraph.VertexShader;
 import com.android.testapp.R;
 
 import android.content.res.Resources;
@@ -41,7 +43,6 @@
 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;
 
@@ -74,6 +75,12 @@
     private Allocation mDefault2D;
     private Allocation mDefaultCube;
 
+    private FragmentShader mColor;
+    private FragmentShader mTexture;
+    private VertexShader mDefaultVertex;
+
+    private RenderState mDefaultState;
+
     private static Allocation getDefault(boolean isCube) {
         final int dimension = 4;
         final int bytesPerPixel = 4;
@@ -101,6 +108,9 @@
         if (sSceneManager == null) {
             return null;
         }
+        if (sSceneManager.mDefault2D == null) {
+            sSceneManager.mDefault2D = getDefault(false);
+        }
         return sSceneManager.mDefault2D;
     }
 
@@ -108,6 +118,9 @@
         if (sSceneManager == null) {
             return null;
         }
+        if (sSceneManager.mDefaultCube == null) {
+            sSceneManager.mDefaultCube = getDefault(true);
+        }
         return sSceneManager.mDefaultCube;
     }
 
@@ -229,6 +242,10 @@
     public void setActiveScene(Scene s) {
         mActiveScene = s;
 
+        if (mActiveScene == null) {
+            return;
+        }
+
         // Do some sanity checking
         if (mActiveScene.getCameras().size() == 0) {
             Matrix4f camPos = new Matrix4f();
@@ -242,6 +259,8 @@
             cam.setTransform(cameraTransform);
             mActiveScene.appendCamera(cam);
         }
+
+        mActiveScene.appendShader(getDefaultVS());
     }
 
     static RenderScriptGL getRS() {
@@ -258,6 +277,114 @@
         return sSceneManager.mRes;
     }
 
+    // Provides the folowing inputs to fragment shader
+    // Assigned by default if nothing is present
+    // vec3 varWorldPos;
+    // vec3 varWorldNormal;
+    // vec2 varTex0;
+    public static VertexShader getDefaultVS() {
+        if (sSceneManager == null) {
+            return null;
+        }
+
+        if (sSceneManager.mDefaultVertex == null) {
+            RenderScriptGL rs = getRS();
+            Element.Builder b = new Element.Builder(rs);
+            b.add(Element.MATRIX_4X4(rs), "model");
+            Type.Builder objConstBuilder = new Type.Builder(rs, b.create());
+
+            b = new Element.Builder(rs);
+            b.add(Element.MATRIX_4X4(rs), "viewProj");
+            Type.Builder shaderConstBuilder = new Type.Builder(rs, b.create());
+
+            b = new Element.Builder(rs);
+            b.add(Element.F32_4(rs), "position");
+            b.add(Element.F32_2(rs), "texture0");
+            b.add(Element.F32_3(rs), "normal");
+            Element defaultIn = b.create();
+
+            final String code = "\n" +
+                "varying vec3 varWorldPos;\n" +
+                "varying vec3 varWorldNormal;\n" +
+                "varying vec2 varTex0;\n" +
+                "void main() {" +
+                "   vec4 objPos = ATTRIB_position;\n" +
+                "   vec4 worldPos = UNI_model * objPos;\n" +
+                "   gl_Position = UNI_viewProj * worldPos;\n" +
+                "   mat3 model3 = mat3(UNI_model[0].xyz, UNI_model[1].xyz, UNI_model[2].xyz);\n" +
+                "   vec3 worldNorm = model3 * ATTRIB_normal;\n" +
+                "   varWorldPos = worldPos.xyz;\n" +
+                "   varWorldNormal = worldNorm;\n" +
+                "   varTex0 = ATTRIB_texture0;\n" +
+                "}\n";
+
+            VertexShader.Builder sb = new VertexShader.Builder(rs);
+            sb.addInput(defaultIn);
+            sb.setObjectConst(objConstBuilder.setX(1).create());
+            sb.setShaderConst(shaderConstBuilder.setX(1).create());
+            sb.setShader(code);
+            sSceneManager.mDefaultVertex = sb.create();
+        }
+
+        return sSceneManager.mDefaultVertex;
+    }
+
+    public static FragmentShader getColorFS() {
+        if (sSceneManager == null) {
+            return null;
+        }
+        if (sSceneManager.mColor == null) {
+            RenderScriptGL rs = getRS();
+            Element.Builder b = new Element.Builder(rs);
+            b.add(Element.F32_4(rs), "color");
+            Type.Builder objConstBuilder = new Type.Builder(rs, b.create());
+
+            final String code = "\n" +
+                "varying vec2 varTex0;\n" +
+                "void main() {\n" +
+                "   lowp vec4 col = texture2D(UNI_Tex0, varTex0).rgba;\n" +
+                "   gl_FragColor = col;\n" +
+                "}\n";
+            FragmentShader.Builder fb = new FragmentShader.Builder(rs);
+            fb.setShader(code);
+            fb.setObjectConst(objConstBuilder.create());
+            sSceneManager.mColor = fb.create();
+        }
+
+        return sSceneManager.mColor;
+    }
+
+    public static FragmentShader getTextureFS() {
+        if (sSceneManager == null) {
+            return null;
+        }
+        if (sSceneManager.mTexture == null) {
+            RenderScriptGL rs = getRS();
+            final String code = "\n" +
+                "varying vec2 varTex0;\n" +
+                "void main() {\n" +
+                "   lowp vec4 col = UNI_color;\n" +
+                "   gl_FragColor = col;\n" +
+                "}\n";
+            FragmentShader.Builder fb = new FragmentShader.Builder(rs);
+            fb.setShader(code);
+            fb.addTexture(Program.TextureType.TEXTURE_2D, "Tex0");
+            sSceneManager.mTexture = fb.create();
+        }
+
+        return sSceneManager.mTexture;
+    }
+
+    static RenderState getDefaultState() {
+        if (sSceneManager == null) {
+            return null;
+        }
+        if (sSceneManager.mDefaultState == null) {
+            sSceneManager.mDefaultState = new RenderState(getDefaultVS(), getColorFS(), null, null);
+        }
+        return sSceneManager.mDefaultState;
+    }
+
     public static SceneManager getInstance() {
         if (sSceneManager == null) {
             sSceneManager = new SceneManager();
@@ -316,8 +443,12 @@
         mAllocationMap = new HashMap<String, Allocation>();
 
         mQuad = null;
-        mDefault2D = getDefault(false);
-        mDefaultCube = getDefault(true);
+        mDefault2D = null;
+        mDefaultCube = null;
+        mDefaultVertex = null;
+        mColor = null;
+        mTexture = null;
+        mDefaultState = null;
 
         mExportScript = new ScriptC_export(rs, res, R.raw.export);
 
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/ShaderParam.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/ShaderParam.java
index 8dea535..3dd41ca 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/ShaderParam.java
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/ShaderParam.java
@@ -75,7 +75,7 @@
             // Make one if it's not there
             if (matchingParam == null) {
                 if (subElem.getDataType() == Element.DataType.FLOAT_32) {
-                    matchingParam = new Float4Param(inputName);
+                    matchingParam = new Float4Param(inputName, 0.5f, 0.5f, 0.5f, 0.5f);
                 } else if (subElem.getDataType() == Element.DataType.MATRIX_4X4) {
                     TransformParam trParam = new TransformParam(inputName);
                     trParam.setTransform(transform);
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/VertexShader.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/VertexShader.java
index f7d0e6d..4efaff7 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/VertexShader.java
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/VertexShader.java
@@ -44,6 +44,11 @@
             return this;
         }
 
+        public Builder setShader(String code) {
+            mBuilder.setShader(code);
+            return this;
+        }
+
         public Builder setObjectConst(Type type) {
             mShader.mPerObjConstants = type;
             return this;
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/TestAppRS.java b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/TestAppRS.java
index 7bf7812..f159e85 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/TestAppRS.java
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/TestAppRS.java
@@ -149,34 +149,27 @@
     }
 
     private void initPaintShaders() {
-        ScriptField_ModelParams objConst = new ScriptField_ModelParams(mRS, 1);
-        ScriptField_ViewProjParams shaderConst = new ScriptField_ViewProjParams(mRS, 1);
+        mGenericV = SceneManager.getDefaultVS();
 
-        VertexShader.Builder vb = new VertexShader.Builder(mRS);
-        vb.addInput(ScriptField_VertexShaderInputs.createElement(mRS));
-        vb.setShader(mRes, R.raw.shader2v);
-        vb.setObjectConst(objConst.getAllocation().getType());
-        vb.setShaderConst(shaderConst.getAllocation().getType());
-        mGenericV = vb.create();
+        ScriptField_CameraParams camParams = new ScriptField_CameraParams(mRS, 1);
+        Type camParamType = camParams.getAllocation().getType();
+        ScriptField_LightParams lightParams = new ScriptField_LightParams(mRS, 1);
 
-        ScriptField_CameraParams fsConst = new ScriptField_CameraParams(mRS, 1);
-        ScriptField_LightParams fsConst2 = new ScriptField_LightParams(mRS, 1);
-
-        mPaintF = createFromResource(R.raw.paintf, true, fsConst.getAllocation().getType());
+        mPaintF = createFromResource(R.raw.paintf, true, camParamType);
         // Assign a reflection map
         TextureCube envCube = new TextureCube("sdcard/scenegraph/", "cube_env.png");
         mPaintF.appendSourceParams(new TextureParam("reflection", envCube));
 
-        mAluminumF = createFromResource(R.raw.metal, true, fsConst.getAllocation().getType());
+        mAluminumF = createFromResource(R.raw.metal, true, camParamType);
         TextureCube diffCube = new TextureCube("sdcard/scenegraph/", "cube_spec.png");
         mAluminumF.appendSourceParams(new TextureParam("reflection", diffCube));
 
-        mPlasticF = createFromResource(R.raw.plastic, false, fsConst.getAllocation().getType());
-        mDiffuseF = createFromResource(R.raw.diffuse, false, fsConst.getAllocation().getType());
-        mTextureF = createFromResource(R.raw.texture, false, fsConst.getAllocation().getType());
+        mPlasticF = createFromResource(R.raw.plastic, false, camParamType);
+        mDiffuseF = createFromResource(R.raw.diffuse, false, camParamType);
+        mTextureF = SceneManager.getTextureFS();
 
         FragmentShader.Builder fb = new FragmentShader.Builder(mRS);
-        fb.setObjectConst(fsConst2.getAllocation().getType());
+        fb.setObjectConst(lightParams.getAllocation().getType());
         fb.setShader(mRes, R.raw.plastic_lights);
         mLightsF = fb.create();
 
@@ -214,7 +207,6 @@
         mActiveScene.appendShader(mPlasticF);
         mActiveScene.appendShader(mDiffuseF);
         mActiveScene.appendShader(mTextureF);
-        mActiveScene.appendShader(mGenericV);
     }
 
     public void prepareToRender(Scene s) {