Add matrix component types.
Fix potental overflow in script -> java messages.

Change-Id: Ie6fd9dc376be4043fc938a1517106936937689c8
diff --git a/graphics/java/android/renderscript/Element.java b/graphics/java/android/renderscript/Element.java
index b811479..ed09f89 100644
--- a/graphics/java/android/renderscript/Element.java
+++ b/graphics/java/android/renderscript/Element.java
@@ -54,16 +54,20 @@
         UNSIGNED_5_5_5_1 (14, 2),
         UNSIGNED_4_4_4_4 (15, 2),
 
-        RS_ELEMENT (16, 4),
-        RS_TYPE (17, 4),
-        RS_ALLOCATION (18, 4),
-        RS_SAMPLER (19, 4),
-        RS_SCRIPT (20, 4),
-        RS_MESH (21, 4),
-        RS_PROGRAM_FRAGMENT (22, 4),
-        RS_PROGRAM_VERTEX (23, 4),
-        RS_PROGRAM_RASTER (24, 4),
-        RS_PROGRAM_STORE (25, 4);
+        MATRIX_4X4 (16, 64),
+        MATRIX_3X3 (17, 36),
+        MATRIX_2X2 (18, 16),
+
+        RS_ELEMENT (1000, 4),
+        RS_TYPE (1001, 4),
+        RS_ALLOCATION (1002, 4),
+        RS_SAMPLER (1003, 4),
+        RS_SCRIPT (1004, 4),
+        RS_MESH (1005, 4),
+        RS_PROGRAM_FRAGMENT (1006, 4),
+        RS_PROGRAM_VERTEX (1007, 4),
+        RS_PROGRAM_RASTER (1008, 4),
+        RS_PROGRAM_STORE (1009, 4);
 
         int mID;
         int mSize;
@@ -285,6 +289,29 @@
         return rs.mElement_UCHAR_4;
     }
 
+    public static Element MATRIX_4X4(RenderScript rs) {
+        if(rs.mElement_MATRIX_4X4 == null) {
+            rs.mElement_MATRIX_4X4 = createUser(rs, DataType.MATRIX_4X4);
+        }
+        return rs.mElement_MATRIX_4X4;
+    }
+    public static Element MATRIX4X4(RenderScript rs) {
+        return MATRIX_4X4(rs);
+    }
+
+    public static Element MATRIX_3X3(RenderScript rs) {
+        if(rs.mElement_MATRIX_3X3 == null) {
+            rs.mElement_MATRIX_3X3 = createUser(rs, DataType.MATRIX_3X3);
+        }
+        return rs.mElement_MATRIX_4X4;
+    }
+
+    public static Element MATRIX_2X2(RenderScript rs) {
+        if(rs.mElement_MATRIX_2X2 == null) {
+            rs.mElement_MATRIX_2X2 = createUser(rs, DataType.MATRIX_2X2);
+        }
+        return rs.mElement_MATRIX_2X2;
+    }
 
     Element(int id, RenderScript rs, Element[] e, String[] n) {
         super(id, rs);
diff --git a/graphics/java/android/renderscript/FieldPacker.java b/graphics/java/android/renderscript/FieldPacker.java
index 24f0409..b6f88be 100644
--- a/graphics/java/android/renderscript/FieldPacker.java
+++ b/graphics/java/android/renderscript/FieldPacker.java
@@ -248,6 +248,24 @@
         addU32(v.w);
     }
 
+    public void addObj(Matrix4f v) {
+        for (int i=0; i < v.mMat.length; i++) {
+            addF32(v.mMat[i]);
+        }
+    }
+
+    public void addObj(Matrix3f v) {
+        for (int i=0; i < v.mMat.length; i++) {
+            addF32(v.mMat[i]);
+        }
+    }
+
+    public void addObj(Matrix2f v) {
+        for (int i=0; i < v.mMat.length; i++) {
+            addF32(v.mMat[i]);
+        }
+    }
+
     public void addBoolean(boolean v) {
         addI8((byte)(v ? 1 : 0));
     }
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index ab1d765..08ba7e2 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -542,6 +542,10 @@
     Element mElement_FLOAT_4;
     Element mElement_UCHAR_4;
 
+    Element mElement_MATRIX_4X4;
+    Element mElement_MATRIX_3X3;
+    Element mElement_MATRIX_2X2;
+
     Sampler mSampler_CLAMP_NEAREST;
     Sampler mSampler_CLAMP_LINEAR;
     Sampler mSampler_CLAMP_LINEAR_MIP_LINEAR;
@@ -614,15 +618,22 @@
             int[] rbuf = new int[16];
             mRS.nContextInitToClient(mRS.mContext);
             while(mRun) {
+                rbuf[0] = 0;
                 int msg = mRS.nContextGetMessage(mRS.mContext, rbuf, true);
                 if (msg == 0) {
-                    // Should only happen during teardown.
-                    // But we want to avoid starving other threads during
-                    // teardown by yielding until the next line in the destructor
-                    // can execute to set mRun = false
-                    try {
-                        sleep(1, 0);
-                    } catch(InterruptedException e) {
+                    // Can happen for two reasons
+                    if (rbuf[0] > 0) {
+                        // 1: Buffer needs to be enlarged.
+                        rbuf = new int[rbuf[0] + 2];
+                    } else {
+                        // 2: teardown.
+                        // But we want to avoid starving other threads during
+                        // teardown by yielding until the next line in the destructor
+                        // can execute to set mRun = false
+                        try {
+                            sleep(1, 0);
+                        } catch(InterruptedException e) {
+                        }
                     }
                 }
                 if(mRS.mMessageCallback != null) {
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index b2e8dd9..81f08e9 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -228,7 +228,8 @@
     size_t receiveLen;
     int id = rsContextGetMessage(con, ptr, &receiveLen, len * 4, wait);
     if (!id && receiveLen) {
-        LOGE("message receive buffer too small.  %i", receiveLen);
+        LOGV("message receive buffer too small.  %i", receiveLen);
+        *ptr = (jint)receiveLen;
     }
     _env->ReleaseIntArrayElements(data, ptr, 0);
     return id;
diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h
index 3406287..7902b9a 100644
--- a/libs/rs/RenderScript.h
+++ b/libs/rs/RenderScript.h
@@ -91,7 +91,11 @@
     RS_TYPE_UNSIGNED_5_5_5_1,
     RS_TYPE_UNSIGNED_4_4_4_4,
 
-    RS_TYPE_ELEMENT,
+    RS_TYPE_MATRIX_4X4,
+    RS_TYPE_MATRIX_3X3,
+    RS_TYPE_MATRIX_2X2,
+
+    RS_TYPE_ELEMENT = 1000,
     RS_TYPE_TYPE,
     RS_TYPE_ALLOCATION,
     RS_TYPE_SAMPLER,
@@ -100,7 +104,7 @@
     RS_TYPE_PROGRAM_FRAGMENT,
     RS_TYPE_PROGRAM_VERTEX,
     RS_TYPE_PROGRAM_RASTER,
-    RS_TYPE_PROGRAM_STORE
+    RS_TYPE_PROGRAM_STORE,
 };
 
 enum RsDataKind {
diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/SgTransform.java b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SgTransform.java
index bfc9bb7..e70e811 100644
--- a/libs/rs/java/ModelViewer/src/com/android/modelviewer/SgTransform.java
+++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SgTransform.java
@@ -82,15 +82,8 @@
 
     void setData() {
 
-        mTransformData.globalMat_Row0 = new Float4(1, 0, 0, 0);
-        mTransformData.globalMat_Row1 = new Float4(0, 1, 0, 0);
-        mTransformData.globalMat_Row2 = new Float4(0, 0, 1, 0);
-        mTransformData.globalMat_Row3 = new Float4(0, 0, 0, 1);
-
-        mTransformData.localMat_Row0 = new Float4(1, 0, 0, 0);
-        mTransformData.localMat_Row1 = new Float4(0, 1, 0, 0);
-        mTransformData.localMat_Row2 = new Float4(0, 0, 1, 0);
-        mTransformData.localMat_Row3 = new Float4(0, 0, 0, 1);
+        mTransformData.globalMat = new Matrix4f();
+        mTransformData.localMat = new Matrix4f();
 
         mTransformData.transforms0 = mTransforms[0];
         mTransformData.transforms1 = mTransforms[1];
diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/scenegraph.rs b/libs/rs/java/ModelViewer/src/com/android/modelviewer/scenegraph.rs
index 8053306..c794438 100644
--- a/libs/rs/java/ModelViewer/src/com/android/modelviewer/scenegraph.rs
+++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/scenegraph.rs
@@ -76,10 +76,10 @@
     rsgBindProgramStore(gPFSBackground);
     rsgBindTexture(gPFBackground, 0, gTGrid);
 
-    rsgProgramVertexLoadModelMatrix((rs_matrix4x4 *)&robot1Ptr->globalMat_Row0);
+    rsgProgramVertexLoadModelMatrix(&robot1Ptr->globalMat);
     rsgDrawMesh(gTestMesh);
 
-    rsgProgramVertexLoadModelMatrix((rs_matrix4x4 *)&robot2Ptr->globalMat_Row0);
+    rsgProgramVertexLoadModelMatrix(&robot2Ptr->globalMat);
     rsgDrawMesh(gTestMesh);
 
     color(0.3f, 0.3f, 0.3f, 1.0f);
diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/transform.rs b/libs/rs/java/ModelViewer/src/com/android/modelviewer/transform.rs
index 7b9cd1c..2ef29cf 100644
--- a/libs/rs/java/ModelViewer/src/com/android/modelviewer/transform.rs
+++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/transform.rs
@@ -52,8 +52,8 @@
     //rsDebug("Transform data", (int)data);
     //rsDebug("Entering parent", (int)parent);
 
-    rs_matrix4x4 *localMat = (rs_matrix4x4*)&data->localMat_Row0;
-    rs_matrix4x4 *globalMat = (rs_matrix4x4*)&data->globalMat_Row0;
+    rs_matrix4x4 *localMat = &data->localMat;
+    rs_matrix4x4 *globalMat = &data->globalMat;
 
     ParentData toChild;
     toChild.changed = 0;
diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/transform_def.rsh b/libs/rs/java/ModelViewer/src/com/android/modelviewer/transform_def.rsh
index a66e6c5..5c872a7 100644
--- a/libs/rs/java/ModelViewer/src/com/android/modelviewer/transform_def.rsh
+++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/transform_def.rsh
@@ -22,15 +22,8 @@
 #define TRANSFORM_SCALE 3
 
 typedef struct {
-    float4 globalMat_Row0;
-    float4 globalMat_Row1;
-    float4 globalMat_Row2;
-    float4 globalMat_Row3;
-
-    float4 localMat_Row0;
-    float4 localMat_Row1;
-    float4 localMat_Row2;
-    float4 localMat_Row3;
+    rs_matrix4x4 globalMat;
+    rs_matrix4x4 localMat;
 
     float4 transforms0;
     float4 transforms1;
diff --git a/libs/rs/rsComponent.cpp b/libs/rs/rsComponent.cpp
index fbaa75f..f51b23e 100644
--- a/libs/rs/rsComponent.cpp
+++ b/libs/rs/rsComponent.cpp
@@ -95,6 +95,26 @@
         mNormalized = true;
         rsAssert(mKind == RS_KIND_PIXEL_RGBA);
         return;
+
+    case RS_TYPE_MATRIX_4X4:
+        mTypeBits = 16 * 32;
+        rsAssert(mVectorSize == 1);
+        rsAssert(mNormalized == false);
+        rsAssert(mKind == RS_KIND_USER);
+        break;
+    case RS_TYPE_MATRIX_3X3:
+        mTypeBits = 9 * 32;
+        rsAssert(mVectorSize == 1);
+        rsAssert(mNormalized == false);
+        rsAssert(mKind == RS_KIND_USER);
+        break;
+    case RS_TYPE_MATRIX_2X2:
+        mTypeBits = 4 * 32;
+        rsAssert(mVectorSize == 1);
+        rsAssert(mNormalized == false);
+        rsAssert(mKind == RS_KIND_USER);
+        break;
+
     case RS_TYPE_ELEMENT:
     case RS_TYPE_TYPE:
     case RS_TYPE_ALLOCATION:
@@ -218,10 +238,19 @@
         case 4: return String8("vec4");
         }
     }
+    if ((mType == RS_TYPE_MATRIX_4X4) && (mVectorSize == 1)) {
+        return String8("mat4");
+    }
+    if ((mType == RS_TYPE_MATRIX_3X3) && (mVectorSize == 1)) {
+        return String8("mat3");
+    }
+    if ((mType == RS_TYPE_MATRIX_2X2) && (mVectorSize == 1)) {
+        return String8("mat2");
+    }
     return String8();
 }
 
-static const char * gTypeStrings[] = {
+static const char * gTypeBasicStrings[] = {
     "NONE",
     "F16",
     "F32",
@@ -238,6 +267,12 @@
     "UP_565",
     "UP_5551",
     "UP_4444",
+    "MATRIX_4X4",
+    "MATRIX_3X3",
+    "MATRIX_2X2",
+};
+
+static const char * gTypeObjStrings[] = {
     "ELEMENT",
     "TYPE",
     "ALLOCATION",
@@ -267,8 +302,13 @@
 
 void Component::dumpLOGV(const char *prefix) const
 {
-    LOGV("%s   Component: %s, %s, vectorSize=%i, bits=%i",
-         prefix, gTypeStrings[mType], gKindStrings[mKind], mVectorSize, mBits);
+    if (mType >= RS_TYPE_ELEMENT) {
+        LOGV("%s   Component: %s, %s, vectorSize=%i, bits=%i",
+             prefix, gTypeObjStrings[mType - RS_TYPE_ELEMENT], gKindStrings[mKind], mVectorSize, mBits);
+    } else {
+        LOGV("%s   Component: %s, %s, vectorSize=%i, bits=%i",
+             prefix, gTypeBasicStrings[mType], gKindStrings[mKind], mVectorSize, mBits);
+    }
 }
 
 void Component::serialize(OStream *stream) const
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 08dd57b..f67a9d5 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -713,10 +713,10 @@
 uint32_t Context::getMessageToClient(void *data, size_t *receiveLen, size_t bufferLen, bool wait)
 {
     //LOGE("getMessageToClient %i %i", bufferLen, wait);
+    *receiveLen = 0;
     if (!wait) {
         if (mIO.mToClient.isEmpty()) {
             // No message to get and not going to wait for one.
-            receiveLen = 0;
             return 0;
         }
     }