Add error handling, move to create methods for intrinsics.

Change-Id: I81a0d481fef8b9396c648fdf18aee716a2056612
diff --git a/cpp/Element.cpp b/cpp/Element.cpp
index 35f081d..df7b5a0 100644
--- a/cpp/Element.cpp
+++ b/cpp/Element.cpp
@@ -24,40 +24,48 @@
 
 android::RSC::sp<const Element> Element::getSubElement(uint32_t index) {
     if (!mVisibleElementMap.size()) {
-        mRS->throwError("Element contains no sub-elements");
+        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Element contains no sub-elements");
+        return NULL;
     }
     if (index >= mVisibleElementMap.size()) {
-        mRS->throwError("Illegal sub-element index");
+        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Illegal sub-element index");
+        return NULL;
     }
     return mElements[mVisibleElementMap[index]];
 }
 
 const char * Element::getSubElementName(uint32_t index) {
     if (!mVisibleElementMap.size()) {
-        mRS->throwError("Element contains no sub-elements");
+        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Element contains no sub-elements");
+        return NULL;
     }
     if (index >= mVisibleElementMap.size()) {
-        mRS->throwError("Illegal sub-element index");
+        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Illegal sub-element index");
+        return NULL;
     }
     return mElementNames[mVisibleElementMap[index]].c_str();
 }
 
 size_t Element::getSubElementArraySize(uint32_t index) {
     if (!mVisibleElementMap.size()) {
-        mRS->throwError("Element contains no sub-elements");
+        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Element contains no sub-elements");
+        return 0;
     }
     if (index >= mVisibleElementMap.size()) {
-        mRS->throwError("Illegal sub-element index");
+        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Illegal sub-element index");
+        return 0;
     }
     return mArraySizes[mVisibleElementMap[index]];
 }
 
 uint32_t Element::getSubElementOffsetBytes(uint32_t index) {
     if (mVisibleElementMap.size()) {
-        mRS->throwError("Element contains no sub-elements");
+        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Element contains no sub-elements");
+        return 0;
     }
     if (index >= mVisibleElementMap.size()) {
-        mRS->throwError("Illegal sub-element index");
+        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Illegal sub-element index");
+        return 0;
     }
     return mOffsetInBytes[mVisibleElementMap[index]];
 }
@@ -259,7 +267,8 @@
 
 android::RSC::sp<const Element> Element::createVector(android::RSC::sp<RS> rs, RsDataType dt, uint32_t size) {
     if (size < 2 || size > 4) {
-        rs->throwError("Vector size out of range 2-4.");
+        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Vector size out of range 2-4.");
+        return NULL;
     }
     void *id = RS::dispatch->ElementCreate(rs->getContext(), dt, RS_KIND_USER, false, size);
     return new Element(id, rs, dt, RS_KIND_USER, false, size);
@@ -272,26 +281,32 @@
           dk == RS_KIND_PIXEL_RGB ||
           dk == RS_KIND_PIXEL_RGBA ||
           dk == RS_KIND_PIXEL_DEPTH)) {
-        rs->throwError("Unsupported DataKind");
+        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Unsupported DataKind");
+        return NULL;
     }
     if (!(dt == RS_TYPE_UNSIGNED_8 ||
           dt == RS_TYPE_UNSIGNED_16 ||
           dt == RS_TYPE_UNSIGNED_5_6_5 ||
           dt == RS_TYPE_UNSIGNED_4_4_4_4 ||
           dt == RS_TYPE_UNSIGNED_5_5_5_1)) {
-        rs->throwError("Unsupported DataType");
+        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Unsupported DataType");
+        return NULL;
     }
     if (dt == RS_TYPE_UNSIGNED_5_6_5 && dk != RS_KIND_PIXEL_RGB) {
-        rs->throwError("Bad kind and type combo");
+        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Bad kind and type combo");
+        return NULL;
     }
     if (dt == RS_TYPE_UNSIGNED_5_5_5_1 && dk != RS_KIND_PIXEL_RGBA) {
-        rs->throwError("Bad kind and type combo");
+        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Bad kind and type combo");
+        return NULL;
     }
     if (dt == RS_TYPE_UNSIGNED_4_4_4_4 && dk != RS_KIND_PIXEL_RGBA) {
-        rs->throwError("Bad kind and type combo");
+        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Bad kind and type combo");
+        return NULL;
     }
     if (dt == RS_TYPE_UNSIGNED_16 && dk != RS_KIND_PIXEL_DEPTH) {
-        rs->throwError("Bad kind and type combo");
+        rs->throwError(RS_ERROR_INVALID_PARAMETER, "Bad kind and type combo");
+        return NULL;
     }
 
     int size = 1;
diff --git a/cpp/RenderScript.cpp b/cpp/RenderScript.cpp
index 18e7117..561b58f 100644
--- a/cpp/RenderScript.cpp
+++ b/cpp/RenderScript.cpp
@@ -46,6 +46,7 @@
     mMessageFunc = NULL;
     mMessageRun = false;
     mInit = false;
+    mCurrentError = RS_SUCCESS;
 
     memset(&mElements, 0, sizeof(mElements));
     memset(&mSamplers, 0, sizeof(mSamplers));
@@ -496,10 +497,13 @@
     return true;
 }
 
-void RS::throwError(const char *err) const {
-    ALOGE("RS CPP error: %s", err);
-    int * v = NULL;
-    v[0] = 0;
+void RS::throwError(RSError error, const char *errMsg) {
+    if (mCurrentError == RS_SUCCESS) {
+        mCurrentError = error;
+        ALOGE("RS CPP error: %s", errMsg);
+    } else {
+        ALOGE("RS CPP error (masked by previous error): %s", errMsg);
+    }
 }
 
 
@@ -533,7 +537,7 @@
         switch(r) {
         case RS_MESSAGE_TO_CLIENT_ERROR:
             ALOGE("RS Error %s", (const char *)rbuf);
-
+            rs->throwError(RS_ERROR_RUNTIME_ERROR, "Error returned from runtime");
             if(rs->mMessageFunc != NULL) {
                 rs->mErrorFunc(usrID, (const char *)rbuf);
             }
diff --git a/cpp/Script.cpp b/cpp/Script.cpp
index 9bc55ff..29fe12d 100644
--- a/cpp/Script.cpp
+++ b/cpp/Script.cpp
@@ -28,7 +28,7 @@
 void Script::forEach(uint32_t slot, sp<const Allocation> ain, sp<const Allocation> aout,
                        const void *usr, size_t usrLen) const {
     if ((ain == NULL) && (aout == NULL)) {
-        mRS->throwError("At least one of ain or aout is required to be non-null.");
+        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "At least one of ain or aout is required to be non-null.");
     }
     void *in_id = BaseObj::getObjID(ain);
     void *out_id = BaseObj::getObjID(aout);
diff --git a/cpp/ScriptIntrinsics.cpp b/cpp/ScriptIntrinsics.cpp
index 5653078..ab24952 100644
--- a/cpp/ScriptIntrinsics.cpp
+++ b/cpp/ScriptIntrinsics.cpp
@@ -30,6 +30,10 @@
 
 }
 
+sp<ScriptIntrinsic3DLUT> ScriptIntrinsic3DLUT::create(sp<RS> rs, sp<const Element> e) {
+    return new ScriptIntrinsic3DLUT(rs, e);
+}
+
 ScriptIntrinsic3DLUT::ScriptIntrinsic3DLUT(sp<RS> rs, sp<const Element> e)
     : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_3DLUT, e) {
 
@@ -41,6 +45,10 @@
     Script::setVar(0, lut);
 }
 
+sp<ScriptIntrinsicBlend> ScriptIntrinsicBlend::create(sp<RS> rs, sp<const Element> e) {
+    return new ScriptIntrinsicBlend(rs, e);
+}
+
 ScriptIntrinsicBlend::ScriptIntrinsicBlend(sp<RS> rs, sp<const Element> e)
     : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_BLEND, e) {
 }
@@ -110,13 +118,20 @@
 
 
 
+sp<ScriptIntrinsicBlur> ScriptIntrinsicBlur::create(sp<RS> rs, sp<const Element> e) {
+    return new ScriptIntrinsicBlur(rs, e);
+}
+
 ScriptIntrinsicBlur::ScriptIntrinsicBlur(sp<RS> rs, sp<const Element> e)
     : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_BLUR, e) {
 
 }
 
-void ScriptIntrinsicBlur::blur(sp<Allocation> in, sp<Allocation> out) {
+void ScriptIntrinsicBlur::setInput(sp<Allocation> in) {
     Script::setVar(1, in);
+}
+
+void ScriptIntrinsicBlur::forEach(sp<Allocation> out) {
     Script::forEach(0, NULL, out, NULL, 0);
 }
 
@@ -126,6 +141,10 @@
 
 
 
+sp<ScriptIntrinsicColorMatrix> ScriptIntrinsicColorMatrix::create(sp<RS> rs, sp<const Element> e) {
+    return new ScriptIntrinsicColorMatrix(rs, e);
+}
+
 ScriptIntrinsicColorMatrix::ScriptIntrinsicColorMatrix(sp<RS> rs, sp<const Element> e)
     : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_COLOR_MATRIX, e) {
 
@@ -163,6 +182,12 @@
     setColorMatrix3(matrix);
 }
 
+
+
+sp<ScriptIntrinsicConvolve3x3> ScriptIntrinsicConvolve3x3::create(sp<RS> rs, sp<const Element> e) {
+    return new ScriptIntrinsicConvolve3x3(rs, e);
+}
+
 ScriptIntrinsicConvolve3x3::ScriptIntrinsicConvolve3x3(sp<RS> rs, sp<const Element> e)
     : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_CONVOLVE_3x3, e) {
 
@@ -180,6 +205,10 @@
     Script::setVar(0, (void*)v, sizeof(float) * 9);
 }
 
+sp<ScriptIntrinsicConvolve5x5> ScriptIntrinsicConvolve5x5::create(sp<RS> rs, sp<const Element> e) {
+    return new ScriptIntrinsicConvolve5x5(rs, e);
+}
+
 ScriptIntrinsicConvolve5x5::ScriptIntrinsicConvolve5x5(sp<RS> rs, sp<const Element> e)
     : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_CONVOLVE_5x5, e) {
 
@@ -197,6 +226,10 @@
     Script::setVar(0, (void*)v, sizeof(float) * 25);
 }
 
+sp<ScriptIntrinsicHistogram> ScriptIntrinsicHistogram::create(sp<RS> rs, sp<const Element> e) {
+    return new ScriptIntrinsicHistogram(rs, e);
+}
+
 ScriptIntrinsicHistogram::ScriptIntrinsicHistogram(sp<RS> rs, sp<const Element> e)
     : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_HISTOGRAM, e) {
 
@@ -232,6 +265,10 @@
     Script::forEach(1, ain, NULL, NULL, 0);
 }
 
+sp<ScriptIntrinsicLUT> ScriptIntrinsicLUT::create(sp<RS> rs, sp<const Element> e) {
+    return new ScriptIntrinsicLUT(rs, e);
+}
+
 ScriptIntrinsicLUT::ScriptIntrinsicLUT(sp<RS> rs, sp<const Element> e)
     : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_LUT, e), mDirty(true) {
     LUT = Allocation::createSized(rs, e, 1024);
@@ -282,6 +319,10 @@
 
 }
 
+sp<ScriptIntrinsicYuvToRGB> ScriptIntrinsicYuvToRGB::create(sp<RS> rs, sp<const Element> e) {
+    return new ScriptIntrinsicYuvToRGB(rs, e);
+}
+
 ScriptIntrinsicYuvToRGB::ScriptIntrinsicYuvToRGB(sp<RS> rs, sp<const Element> e)
     : ScriptIntrinsic(rs, RS_SCRIPT_INTRINSIC_ID_YUV_TO_RGB, e) {
 
diff --git a/cpp/rsCppStructs.h b/cpp/rsCppStructs.h
index afbff91..f6cb1dd 100644
--- a/cpp/rsCppStructs.h
+++ b/cpp/rsCppStructs.h
@@ -44,6 +44,14 @@
 class ScriptC;
 class Sampler;
 
+ enum RSError {
+     RS_SUCCESS = 0,
+     RS_ERROR_INVALID_PARAMETER = 1,
+     RS_ERROR_RUNTIME_ERROR = 2,
+     RS_ERROR_MAX = 9999
+
+ };
+
  class RS : public android::RSC::LightRefBase<RS> {
 
  public:
@@ -58,7 +66,7 @@
     void setMessageHandler(MessageHandlerFunc_t func);
     MessageHandlerFunc_t getMessageHandler() { return mMessageFunc; }
 
-    void throwError(const char *err) const;
+    void throwError(RSError error, const char *errMsg);
 
     RsContext getContext() { return mContext; }
 
@@ -82,6 +90,7 @@
 
     RsDevice mDev;
     RsContext mContext;
+    RSError mCurrentError;
 
     ErrorHandlerFunc_t mErrorFunc;
     MessageHandlerFunc_t mMessageFunc;
@@ -665,15 +674,19 @@
 };
 
 class ScriptIntrinsic3DLUT : public ScriptIntrinsic {
- public:
+ private:
     ScriptIntrinsic3DLUT(sp<RS> rs, sp<const Element> e);
+ public:
+    static sp<ScriptIntrinsic3DLUT> create(sp<RS> rs, sp<const Element> e);
     void forEach(sp<Allocation> ain, sp<Allocation> aout);
     void setLUT(sp<Allocation> lut);
 };
 
 class ScriptIntrinsicBlend : public ScriptIntrinsic {
- public:
+ private:
     ScriptIntrinsicBlend(sp<RS> rs, sp<const Element> e);
+ public:
+    static sp<ScriptIntrinsicBlend> create(sp<RS> rs, sp<const Element> e);
     void blendClear(sp<Allocation> in, sp<Allocation> out);
     void blendSrc(sp<Allocation> in, sp<Allocation> out);
     void blendDst(sp<Allocation> in, sp<Allocation> out);
@@ -692,15 +705,20 @@
 };
 
 class ScriptIntrinsicBlur : public ScriptIntrinsic {
- public:
+ private:
     ScriptIntrinsicBlur(sp<RS> rs, sp<const Element> e);
-    void blur(sp<Allocation> in, sp<Allocation> out);
+ public:
+    static sp<ScriptIntrinsicBlur> create(sp<RS> rs, sp<const Element> e);
+    void setInput(sp<Allocation> in);
+    void forEach(sp<Allocation> out);
     void setRadius(float radius);
 };
 
 class ScriptIntrinsicColorMatrix : public ScriptIntrinsic {
- public:
+ private:
     ScriptIntrinsicColorMatrix(sp<RS> rs, sp<const Element> e);
+ public:
+    static sp<ScriptIntrinsicColorMatrix> create(sp<RS> rs, sp<const Element> e);
     void forEach(sp<Allocation> in, sp<Allocation> out);
     void setColorMatrix3(float* m);
     void setColorMatrix4(float* m);
@@ -710,24 +728,30 @@
 };
 
 class ScriptIntrinsicConvolve3x3 : public ScriptIntrinsic {
- public:
+ private:
     ScriptIntrinsicConvolve3x3(sp<RS> rs, sp<const Element> e);
+ public:
+    static sp<ScriptIntrinsicConvolve3x3> create(sp<RS> rs, sp<const Element> e);
     void setInput(sp<Allocation> in);
     void forEach(sp<Allocation> out);
     void setCoefficients(float* v);
 };
 
 class ScriptIntrinsicConvolve5x5 : public ScriptIntrinsic {
- public:
+ private:
     ScriptIntrinsicConvolve5x5(sp<RS> rs, sp<const Element> e);
+ public:
+    static sp<ScriptIntrinsicConvolve5x5> create(sp<RS> rs, sp<const Element> e);
     void setInput(sp<Allocation> in);
     void forEach(sp<Allocation> out);
     void setCoefficients(float* v);
 };
 
 class ScriptIntrinsicHistogram : public ScriptIntrinsic {
- public:
+ private:
     ScriptIntrinsicHistogram(sp<RS> rs, sp<const Element> e);
+ public:
+    static sp<ScriptIntrinsicHistogram> create(sp<RS> rs, sp<const Element> e);
     void setOutput(sp<Allocation> aout);
     void setDotCoefficients(float r, float g, float b, float a);
     void forEach(sp<Allocation> ain);
@@ -740,9 +764,10 @@
     bool mDirty;
     unsigned char mCache[1024];
     void setTable(unsigned int offset, unsigned char base, unsigned char length, unsigned char* lutValues);
+    ScriptIntrinsicLUT(sp<RS> rs, sp<const Element> e);
 
  public:
-    ScriptIntrinsicLUT(sp<RS> rs, sp<const Element> e);
+    static sp<ScriptIntrinsicLUT> create(sp<RS> rs, sp<const Element> e);
     void forEach(sp<Allocation> ain, sp<Allocation> aout);
     void setRed(unsigned char base, unsigned char length, unsigned char* lutValues);
     void setGreen(unsigned char base, unsigned char length, unsigned char* lutValues);
@@ -752,8 +777,10 @@
 };
 
 class ScriptIntrinsicYuvToRGB : public ScriptIntrinsic {
- public:
+ private:
     ScriptIntrinsicYuvToRGB(sp<RS> rs, sp<const Element> e);
+ public:
+    static sp<ScriptIntrinsicYuvToRGB> create(sp<RS> rs, sp<const Element> e);
     void setInput(sp<Allocation> in);
     void forEach(sp<Allocation> out);