More error checks

Change-Id: Id2b9ab7a76bbdf2ed745f5e36e552dc9b101982f
diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h
index 0ed129f..f00f748 100644
--- a/libs/rs/RenderScript.h
+++ b/libs/rs/RenderScript.h
@@ -236,11 +236,16 @@
 };
 
 enum RsError {
-    RS_ERROR_NONE,
-    RS_ERROR_BAD_SHADER,
-    RS_ERROR_BAD_SCRIPT,
-    RS_ERROR_BAD_VALUE,
-    RS_ERROR_OUT_OF_MEMORY
+    RS_ERROR_NONE = 0,
+    RS_ERROR_BAD_SHADER = 1,
+    RS_ERROR_BAD_SCRIPT = 2,
+    RS_ERROR_BAD_VALUE = 3,
+    RS_ERROR_OUT_OF_MEMORY = 4,
+    RS_ERROR_DRIVER = 5,
+
+    RS_ERROR_FATAL_UNKNOWN = 0x1000,
+    RS_ERROR_FATAL_DRIVER = 0x1001,
+    RS_ERROR_FATAL_PROGRAM_LINK = 0x1002
 };
 
 enum RsAnimationInterpolation {
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index 1b584c8..7b35305 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -43,11 +43,6 @@
 	param int32_t bits
 }
 
-ContextGetError {
-	param RsError *err
-	ret const char *
-	}
-
 ContextSetPriority {
 	param int32_t priority
 	}
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 840a10e..35db332 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -287,10 +287,27 @@
     return ret;
 }
 
-void Context::checkError(const char *msg) const {
+void Context::checkError(const char *msg, bool isFatal) const {
+
     GLenum err = glGetError();
     if (err != GL_NO_ERROR) {
-        LOGE("%p, GL Error, 0x%x, from %s", this, err, msg);
+        char buf[1024];
+        snprintf(buf, sizeof(buf), "GL Error = 0x%08x, from: %s", err, msg);
+
+        if (isFatal) {
+            setError(RS_ERROR_FATAL_DRIVER, buf);
+        } else {
+            switch (err) {
+            case GL_OUT_OF_MEMORY:
+                setError(RS_ERROR_OUT_OF_MEMORY, buf);
+                break;
+            default:
+                setError(RS_ERROR_DRIVER, buf);
+                break;
+            }
+        }
+
+        LOGE("%p, %s", this, buf);
     }
 }
 
@@ -597,7 +614,6 @@
     mPaused = false;
     mObjHead = NULL;
     mError = RS_ERROR_NONE;
-    mErrorMsg = NULL;
 }
 
 Context * Context::createContext(Device *dev, const RsSurfaceConfig *sc) {
@@ -861,7 +877,8 @@
     return RS_MESSAGE_TO_CLIENT_RESIZE;
 }
 
-bool Context::sendMessageToClient(const void *data, RsMessageToClientType cmdID, uint32_t subID, size_t len, bool waitForSpace) {
+bool Context::sendMessageToClient(const void *data, RsMessageToClientType cmdID,
+                                  uint32_t subID, size_t len, bool waitForSpace) const {
     //LOGE("sendMessageToClient %i %i %i %i", cmdID, subID, len, waitForSpace);
     if (cmdID == 0) {
         LOGE("Attempting to send invalid command 0 to client.");
@@ -894,18 +911,8 @@
     mIO.mToClient.shutdown();
 }
 
-const char * Context::getError(RsError *err) {
-    *err = mError;
-    mError = RS_ERROR_NONE;
-    if (*err != RS_ERROR_NONE) {
-        return mErrorMsg;
-    }
-    return NULL;
-}
-
-void Context::setError(RsError e, const char *msg) {
+void Context::setError(RsError e, const char *msg) const {
     mError = e;
-    mErrorMsg = msg;
     sendMessageToClient(msg, RS_MESSAGE_TO_CLIENT_ERROR, e, strlen(msg) + 1, true);
 }
 
@@ -1012,14 +1019,6 @@
     ObjectBase::dumpAll(rsc);
 }
 
-const char* rsi_ContextGetError(Context *rsc, RsError *e) {
-    const char *msg = rsc->getError(e);
-    if (*e != RS_ERROR_NONE) {
-        LOGE("RS Error %i %s", *e, msg);
-    }
-    return msg;
-}
-
 }
 }
 
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index c377c73..cafbdff5 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -144,7 +144,7 @@
 
     RsMessageToClientType peekMessageToClient(size_t *receiveLen, uint32_t *subID, bool wait);
     RsMessageToClientType getMessageToClient(void *data, size_t *receiveLen, uint32_t *subID, size_t bufferLen, bool wait);
-    bool sendMessageToClient(const void *data, RsMessageToClientType cmdID, uint32_t subID, size_t len, bool waitForSpace);
+    bool sendMessageToClient(const void *data, RsMessageToClientType cmdID, uint32_t subID, size_t len, bool waitForSpace) const;
     uint32_t runScript(Script *s);
 
     void initToClient();
@@ -169,7 +169,7 @@
     uint32_t getWidth() const {return mWidth;}
     uint32_t getHeight() const {return mHeight;}
 
-    ThreadIO mIO;
+    mutable ThreadIO mIO;
 
     // Timers
     enum Timers {
@@ -197,9 +197,8 @@
     } props;
 
     void dumpDebug() const;
-    void checkError(const char *) const;
-    const char * getError(RsError *);
-    void setError(RsError e, const char *msg = NULL);
+    void checkError(const char *, bool isFatal = false) const;
+    void setError(RsError e, const char *msg = NULL) const;
 
     mutable const ObjectBase * mObjHead;
 
@@ -259,8 +258,7 @@
     bool mRunning;
     bool mExit;
     bool mPaused;
-    RsError mError;
-    const char *mErrorMsg;
+    mutable RsError mError;
 
     pthread_t mThreadId;
     pid_t mNativeThreadId;
diff --git a/libs/rs/rsElement.cpp b/libs/rs/rsElement.cpp
index 40321fe..6ae8bb8 100644
--- a/libs/rs/rsElement.cpp
+++ b/libs/rs/rsElement.cpp
@@ -348,7 +348,6 @@
                             RsDataKind dk,
                             bool norm,
                             uint32_t vecSize) {
-    //LOGE("rsi_ElementCreate %i %i %i %i", dt, dk, norm, vecSize);
     const Element *e = Element::create(rsc, dt, dk, norm, vecSize);
     e->incUserRef();
     return (RsElement)e;
@@ -360,7 +359,6 @@
                              const char ** names,
                              const size_t * nameLengths,
                              const uint32_t * arraySizes) {
-    //LOGE("rsi_ElementCreate2 %i", count);
     const Element *e = Element::create(rsc, count, (const Element **)ein, names, nameLengths, arraySizes);
     e->incUserRef();
     return (RsElement)e;
diff --git a/libs/rs/rsProgramFragment.cpp b/libs/rs/rsProgramFragment.cpp
index ffa7d26..0713fb3 100644
--- a/libs/rs/rsProgramFragment.cpp
+++ b/libs/rs/rsProgramFragment.cpp
@@ -136,9 +136,9 @@
         char buf[256];
         for (uint32_t ct=0; ct < mTextureCount; ct++) {
             if (mTextureTargets[ct] == RS_TEXTURE_2D) {
-                sprintf(buf, "uniform sampler2D UNI_Tex%i;\n", ct);
+                snprintf(buf, sizeof(buf), "uniform sampler2D UNI_Tex%i;\n", ct);
             } else {
-                sprintf(buf, "uniform samplerCube UNI_Tex%i;\n", ct);
+                snprintf(buf, sizeof(buf), "uniform samplerCube UNI_Tex%i;\n", ct);
             }
             mShader.append(buf);
         }
@@ -159,7 +159,7 @@
     mTextureUniformIndexStart = uniformIndex;
     char buf[256];
     for (uint32_t ct=0; ct < mTextureCount; ct++) {
-        sprintf(buf, "UNI_Tex%i", ct);
+        snprintf(buf, sizeof(buf), "UNI_Tex%i", ct);
         mUniformNames[uniformIndex].setTo(buf);
         mUniformArraySizes[uniformIndex] = 1;
         uniformIndex++;
diff --git a/libs/rs/rsProgramVertex.cpp b/libs/rs/rsProgramVertex.cpp
index 3fd2981..a28b9bd 100644
--- a/libs/rs/rsProgramVertex.cpp
+++ b/libs/rs/rsProgramVertex.cpp
@@ -49,7 +49,7 @@
     Program::loadShader(rsc, GL_VERTEX_SHADER);
 }
 
-void ProgramVertex::createShader() {
+void ProgramVertex::createShader(Context *rsc) {
     if (mUserShader.length() > 1) {
 
         appendUserConstants();
@@ -81,13 +81,12 @@
         }
         mShader.append(mUserShader);
     } else {
-        LOGE("ProgramFragment::createShader cannot create program, shader code not defined");
-        rsAssert(0);
+        rsc->setError(RS_ERROR_FATAL_UNKNOWN,
+                      "ProgramFragment::createShader cannot create program, shader code not defined");
     }
 }
 
 void ProgramVertex::setupGL2(Context *rsc, ProgramVertexState *state, ShaderCache *sc) {
-    //LOGE("sgl2 vtx1 %x", glGetError());
     if ((state->mLast.get() == this) && !mDirty) {
         return;
     }
@@ -96,8 +95,8 @@
 
     if (!isUserProgram()) {
         if (mConstants[0].get() == NULL) {
-            LOGE("Unable to set fixed function emulation matrices because allocation is missing");
-            rsc->setError(RS_ERROR_BAD_SHADER, "Fixed function allocation missing");
+            rsc->setError(RS_ERROR_FATAL_UNKNOWN,
+                          "Unable to set fixed function emulation matrices because allocation is missing");
             return;
         }
         float *f = static_cast<float *>(mConstants[0]->getPtr());
@@ -120,12 +119,13 @@
 
 void ProgramVertex::setProjectionMatrix(Context *rsc, const rsc_Matrix *m) const {
     if (isUserProgram()) {
-        LOGE("Attempting to set fixed function emulation matrix projection on user program");
-        rsc->setError(RS_ERROR_BAD_SHADER, "Cannot set emulation matrix on user shader");
+        rsc->setError(RS_ERROR_FATAL_UNKNOWN,
+                      "Attempting to set fixed function emulation matrix projection on user program");
         return;
     }
     if (mConstants[0].get() == NULL) {
-        LOGE("Unable to set fixed function emulation matrix projection because allocation is missing");
+        rsc->setError(RS_ERROR_FATAL_UNKNOWN,
+                      "Unable to set fixed function emulation matrix projection because allocation is missing");
         return;
     }
     float *f = static_cast<float *>(mConstants[0]->getPtr());
@@ -135,13 +135,13 @@
 
 void ProgramVertex::setModelviewMatrix(Context *rsc, const rsc_Matrix *m) const {
     if (isUserProgram()) {
-        LOGE("Attempting to set fixed function emulation matrix modelview on user program");
-        rsc->setError(RS_ERROR_BAD_SHADER, "Cannot set emulation matrix on user shader");
+        rsc->setError(RS_ERROR_FATAL_UNKNOWN,
+                      "Attempting to set fixed function emulation matrix modelview on user program");
         return;
     }
     if (mConstants[0].get() == NULL) {
-        LOGE("Unable to set fixed function emulation matrix modelview because allocation is missing");
-        rsc->setError(RS_ERROR_BAD_SHADER, "Fixed function allocation missing");
+        rsc->setError(RS_ERROR_FATAL_UNKNOWN,
+                      "Unable to set fixed function emulation matrix modelview because allocation is missing");
         return;
     }
     float *f = static_cast<float *>(mConstants[0]->getPtr());
@@ -151,13 +151,13 @@
 
 void ProgramVertex::setTextureMatrix(Context *rsc, const rsc_Matrix *m) const {
     if (isUserProgram()) {
-        LOGE("Attempting to set fixed function emulation matrix texture on user program");
-        rsc->setError(RS_ERROR_BAD_SHADER, "Cannot set emulation matrix on user shader");
+        rsc->setError(RS_ERROR_FATAL_UNKNOWN,
+                      "Attempting to set fixed function emulation matrix texture on user program");
         return;
     }
     if (mConstants[0].get() == NULL) {
-        LOGE("Unable to set fixed function emulation matrix texture because allocation is missing");
-        rsc->setError(RS_ERROR_BAD_SHADER, "Fixed function allocation missing");
+        rsc->setError(RS_ERROR_FATAL_UNKNOWN,
+                      "Unable to set fixed function emulation matrix texture because allocation is missing");
         return;
     }
     float *f = static_cast<float *>(mConstants[0]->getPtr());
@@ -167,13 +167,13 @@
 
 void ProgramVertex::getProjectionMatrix(Context *rsc, rsc_Matrix *m) const {
     if (isUserProgram()) {
-        LOGE("Attempting to get fixed function emulation matrix projection on user program");
-        rsc->setError(RS_ERROR_BAD_SHADER, "Cannot get emulation matrix on user shader");
+        rsc->setError(RS_ERROR_FATAL_UNKNOWN,
+                      "Attempting to get fixed function emulation matrix projection on user program");
         return;
     }
     if (mConstants[0].get() == NULL) {
-        LOGE("Unable to get fixed function emulation matrix projection because allocation is missing");
-        rsc->setError(RS_ERROR_BAD_SHADER, "Fixed function allocation missing");
+        rsc->setError(RS_ERROR_FATAL_UNKNOWN,
+                      "Unable to get fixed function emulation matrix projection because allocation is missing");
         return;
     }
     float *f = static_cast<float *>(mConstants[0]->getPtr());
@@ -202,7 +202,7 @@
             initAddUserElement(mConstantTypes[ct]->getElement(), mUniformNames, mUniformArraySizes, &uniformCount, RS_SHADER_UNI);
         }
     }
-    createShader();
+    createShader(rsc);
 }
 
 void ProgramVertex::serialize(OStream *stream) const {
diff --git a/libs/rs/rsProgramVertex.h b/libs/rs/rsProgramVertex.h
index 824edbb..2a5c863 100644
--- a/libs/rs/rsProgramVertex.h
+++ b/libs/rs/rsProgramVertex.h
@@ -40,7 +40,7 @@
 
     void transformToScreen(Context *, float *v4out, const float *v3in) const;
 
-    virtual void createShader();
+    virtual void createShader(Context *);
     virtual void loadShader(Context *);
     virtual void init(Context *);
 
diff --git a/libs/rs/rsShaderCache.cpp b/libs/rs/rsShaderCache.cpp
index d254018..45384c9 100644
--- a/libs/rs/rsShaderCache.cpp
+++ b/libs/rs/rsShaderCache.cpp
@@ -150,7 +150,7 @@
                 }
             }
             glDeleteProgram(pgm);
-            rsc->setError(RS_ERROR_BAD_SHADER, "Error linking GL Programs");
+            rsc->setError(RS_ERROR_FATAL_PROGRAM_LINK, "Error linking GL Programs");
             return false;
         }
 
diff --git a/libs/rs/rsType.cpp b/libs/rs/rsType.cpp
index 2a51335..c195b9b 100644
--- a/libs/rs/rsType.cpp
+++ b/libs/rs/rsType.cpp
@@ -136,7 +136,7 @@
     char buf[1024];
     ObjectBase::dumpLOGV(prefix);
     LOGV("%s   Type: x=%i y=%i z=%i mip=%i face=%i", prefix, mDimX, mDimY, mDimZ, mDimLOD, mFaces);
-    sprintf(buf, "%s element: ", prefix);
+    snprintf(buf, sizeof(buf), "%s element: ", prefix);
     mElement->dumpLOGV(buf);
 }