Merge "Add object validity checking."
diff --git a/java/ImageProcessing/src/com/android/rs/image/threshold.rs b/java/ImageProcessing/src/com/android/rs/image/threshold.rs
index 33945a5..f5fecba 100644
--- a/java/ImageProcessing/src/com/android/rs/image/threshold.rs
+++ b/java/ImageProcessing/src/com/android/rs/image/threshold.rs
@@ -65,7 +65,6 @@
 
 
 static void copyInput() {
-    RS_DEBUG_MARKER;
     rs_allocation ain = rsGetAllocation(InPixel);
     uint32_t dimx = rsAllocationGetDimX(ain);
     uint32_t dimy = rsAllocationGetDimY(ain);
@@ -74,7 +73,6 @@
             ScratchPixel1[x + y * dimx] = convert_float4(InPixel[x + y * dimx]);
         }
     }
-    RS_DEBUG_MARKER;
 }
 
 void filter() {
diff --git a/rsContext.cpp b/rsContext.cpp
index cfd6479..4752b35 100644
--- a/rsContext.cpp
+++ b/rsContext.cpp
@@ -282,14 +282,14 @@
      rsc->props.mLogShadersUniforms = getProp("debug.rs.shader.uniforms");
      rsc->props.mLogVisual = getProp("debug.rs.visual");
 
-     ScriptTLSStruct *tlsStruct = new ScriptTLSStruct;
-     if (!tlsStruct) {
+     rsc->mTlsStruct = new ScriptTLSStruct;
+     if (!rsc->mTlsStruct) {
          LOGE("Error allocating tls storage");
          return NULL;
      }
-     tlsStruct->mContext = rsc;
-     tlsStruct->mScript = NULL;
-     int status = pthread_setspecific(rsc->gThreadTLSKey, tlsStruct);
+     rsc->mTlsStruct->mContext = rsc;
+     rsc->mTlsStruct->mScript = NULL;
+     int status = pthread_setspecific(rsc->gThreadTLSKey, rsc->mTlsStruct);
      if (status) {
          LOGE("pthread_setspecific %i", status);
      }
@@ -361,6 +361,7 @@
          rsc->deinitEGL();
          pthread_mutex_unlock(&gInitMutex);
      }
+     delete rsc->mTlsStruct;
 
      LOGV("%p, RS Thread exited", rsc);
      return NULL;
@@ -387,6 +388,11 @@
 #endif
 
      setpriority(PRIO_PROCESS, rsc->mWorkers.mNativeThreadId[idx], rsc->mThreadPriority);
+     int status = pthread_setspecific(rsc->gThreadTLSKey, rsc->mTlsStruct);
+     if (status) {
+         LOGE("pthread_setspecific %i", status);
+     }
+
      while(rsc->mRunning) {
          rsc->mWorkers.mLaunchSignals[idx].wait();
          if (rsc->mWorkers.mLaunchCallback) {
diff --git a/rsContext.h b/rsContext.h
index 2e84930..f90e4af 100644
--- a/rsContext.h
+++ b/rsContext.h
@@ -49,6 +49,24 @@
 
 namespace renderscript {
 
+#if 0
+#define CHECK_OBJ(o) { \
+    GET_TLS(); \
+    if(!ObjectBase::isValid(rsc, (const ObjectBase *)o)) {  \
+        LOGE("Bad object %p at %s, %i", o, __FILE__, __LINE__);  \
+    } \
+}
+#define CHECK_OBJ_OR_NULL(o) { \
+    GET_TLS(); \
+    if(o && !ObjectBase::isValid(rsc, (const ObjectBase *)o)) {  \
+        LOGE("Bad object %p at %s, %i", o, __FILE__, __LINE__);  \
+    } \
+}
+#else
+#define CHECK_OBJ(o)
+#define CHECK_OBJ_OR_NULL(o)
+#endif
+
 class Context
 {
 public:
@@ -64,6 +82,7 @@
         Context * mContext;
         Script * mScript;
     };
+    ScriptTLSStruct *mTlsStruct;
 
     typedef void (*WorkerCallback_t)(void *usr, uint32_t idx);
 
diff --git a/rsObjectBase.cpp b/rsObjectBase.cpp
index 713d61e..f69cb15 100644
--- a/rsObjectBase.cpp
+++ b/rsObjectBase.cpp
@@ -195,3 +195,15 @@
     }
 }
 
+bool ObjectBase::isValid(const Context *rsc, const ObjectBase *obj)
+{
+    const ObjectBase * o = rsc->mObjHead;
+    while (o) {
+        if (o == obj) {
+            return true;
+        }
+        o = o->mNext;
+    }
+    return false;
+}
+
diff --git a/rsObjectBase.h b/rsObjectBase.h
index ad95b81..59fb4a6 100644
--- a/rsObjectBase.h
+++ b/rsObjectBase.h
@@ -56,6 +56,8 @@
     virtual void serialize(OStream *stream) const = 0;
     virtual RsA3DClassID getClassId() const = 0;
 
+    static bool isValid(const Context *rsc, const ObjectBase *obj);
+
 protected:
     const char *mAllocFile;
     uint32_t mAllocLine;
diff --git a/rsScriptC_Lib.cpp b/rsScriptC_Lib.cpp
index 22fd421..e0de867 100644
--- a/rsScriptC_Lib.cpp
+++ b/rsScriptC_Lib.cpp
@@ -203,45 +203,46 @@
 
 static uint32_t SC_allocGetDimX(RsAllocation va)
 {
-    GET_TLS();
     const Allocation *a = static_cast<const Allocation *>(va);
-    //LOGE("SC_allocGetDimX a=%p", a);
-    //LOGE(" type=%p", a->getType());
+    CHECK_OBJ(a);
+    //LOGE("SC_allocGetDimX a=%p  type=%p", a, a->getType());
     return a->getType()->getDimX();
 }
 
 static uint32_t SC_allocGetDimY(RsAllocation va)
 {
-    GET_TLS();
     const Allocation *a = static_cast<const Allocation *>(va);
+    CHECK_OBJ(a);
     return a->getType()->getDimY();
 }
 
 static uint32_t SC_allocGetDimZ(RsAllocation va)
 {
-    GET_TLS();
     const Allocation *a = static_cast<const Allocation *>(va);
+    CHECK_OBJ(a);
     return a->getType()->getDimZ();
 }
 
 static uint32_t SC_allocGetDimLOD(RsAllocation va)
 {
-    GET_TLS();
     const Allocation *a = static_cast<const Allocation *>(va);
+    CHECK_OBJ(a);
     return a->getType()->getDimLOD();
 }
 
 static uint32_t SC_allocGetDimFaces(RsAllocation va)
 {
-    GET_TLS();
     const Allocation *a = static_cast<const Allocation *>(va);
+    CHECK_OBJ(a);
     return a->getType()->getDimFaces();
 }
 
 static const void * SC_getElementAtX(RsAllocation va, uint32_t x)
 {
     const Allocation *a = static_cast<const Allocation *>(va);
+    CHECK_OBJ(a);
     const Type *t = a->getType();
+    CHECK_OBJ(t);
     const uint8_t *p = (const uint8_t *)a->getPtr();
     return &p[t->getElementSizeBytes() * x];
 }
@@ -249,7 +250,9 @@
 static const void * SC_getElementAtXY(RsAllocation va, uint32_t x, uint32_t y)
 {
     const Allocation *a = static_cast<const Allocation *>(va);
+    CHECK_OBJ(a);
     const Type *t = a->getType();
+    CHECK_OBJ(t);
     const uint8_t *p = (const uint8_t *)a->getPtr();
     return &p[t->getElementSizeBytes() * (x + y*t->getDimX())];
 }
@@ -257,7 +260,9 @@
 static const void * SC_getElementAtXYZ(RsAllocation va, uint32_t x, uint32_t y, uint32_t z)
 {
     const Allocation *a = static_cast<const Allocation *>(va);
+    CHECK_OBJ(a);
     const Type *t = a->getType();
+    CHECK_OBJ(t);
     const uint8_t *p = (const uint8_t *)a->getPtr();
     return &p[t->getElementSizeBytes() * (x + y*t->getDimX())];
 }
@@ -265,9 +270,11 @@
 static void SC_setObject(void **vdst, void * vsrc) {
     //LOGE("SC_setObject  %p,%p  %p", vdst, *vdst, vsrc);
     if (vsrc) {
+        CHECK_OBJ(vsrc);
         static_cast<ObjectBase *>(vsrc)->incSysRef();
     }
     if (vdst[0]) {
+        CHECK_OBJ(vdst[0]);
         static_cast<ObjectBase *>(vdst[0])->decSysRef();
     }
     *vdst = vsrc;
@@ -276,6 +283,7 @@
 static void SC_clearObject(void **vdst) {
     //LOGE("SC_clearObject  %p,%p", vdst, *vdst);
     if (vdst[0]) {
+        CHECK_OBJ(vdst[0]);
         static_cast<ObjectBase *>(vdst[0])->decSysRef();
     }
     *vdst = NULL;
diff --git a/rsScriptC_LibGL.cpp b/rsScriptC_LibGL.cpp
index fd4c379..7fd6406 100644
--- a/rsScriptC_LibGL.cpp
+++ b/rsScriptC_LibGL.cpp
@@ -44,6 +44,8 @@
 
 static void SC_bindTexture(RsProgramFragment vpf, uint32_t slot, RsAllocation va)
 {
+    CHECK_OBJ_OR_NULL(va);
+    CHECK_OBJ(vpf);
     GET_TLS();
     rsi_ProgramBindTexture(rsc,
                            static_cast<ProgramFragment *>(vpf),
@@ -54,6 +56,8 @@
 
 static void SC_bindSampler(RsProgramFragment vpf, uint32_t slot, RsSampler vs)
 {
+    CHECK_OBJ_OR_NULL(vs);
+    CHECK_OBJ(vpf);
     GET_TLS();
     rsi_ProgramBindSampler(rsc,
                            static_cast<ProgramFragment *>(vpf),
@@ -64,24 +68,28 @@
 
 static void SC_bindProgramStore(RsProgramStore pfs)
 {
+    CHECK_OBJ_OR_NULL(pfs);
     GET_TLS();
     rsi_ContextBindProgramStore(rsc, pfs);
 }
 
 static void SC_bindProgramFragment(RsProgramFragment pf)
 {
+    CHECK_OBJ_OR_NULL(pf);
     GET_TLS();
     rsi_ContextBindProgramFragment(rsc, pf);
 }
 
 static void SC_bindProgramVertex(RsProgramVertex pv)
 {
+    CHECK_OBJ_OR_NULL(pv);
     GET_TLS();
     rsi_ContextBindProgramVertex(rsc, pv);
 }
 
 static void SC_bindProgramRaster(RsProgramRaster pv)
 {
+    CHECK_OBJ_OR_NULL(pv);
     GET_TLS();
     rsi_ContextBindProgramRaster(rsc, pv);
 }
@@ -112,6 +120,7 @@
 static void SC_pfConstantColor(RsProgramFragment vpf, float r, float g, float b, float a)
 {
     GET_TLS();
+    CHECK_OBJ(vpf);
     ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
     pf->setConstantColor(rsc, r, g, b, a);
 }
@@ -228,6 +237,7 @@
 
 static void SC_drawMesh(RsMesh vsm)
 {
+    CHECK_OBJ(vsm);
     GET_TLS();
     Mesh *sm = static_cast<Mesh *>(vsm);
     if (!rsc->setupCheck()) {
@@ -238,6 +248,7 @@
 
 static void SC_drawMeshPrimitive(RsMesh vsm, uint32_t primIndex)
 {
+    CHECK_OBJ(vsm);
     GET_TLS();
     Mesh *sm = static_cast<Mesh *>(vsm);
     if (!rsc->setupCheck()) {
@@ -248,6 +259,7 @@
 
 static void SC_drawMeshPrimitiveRange(RsMesh vsm, uint32_t primIndex, uint32_t start, uint32_t len)
 {
+    CHECK_OBJ(vsm);
     GET_TLS();
     Mesh *sm = static_cast<Mesh *>(vsm);
     if (!rsc->setupCheck()) {
@@ -259,6 +271,7 @@
 static void SC_meshComputeBoundingBox(RsMesh vsm, float *minX, float *minY, float *minZ,
                                                      float *maxX, float *maxY, float *maxZ)
 {
+    CHECK_OBJ(vsm);
     GET_TLS();
     Mesh *sm = static_cast<Mesh *>(vsm);
     sm->computeBBox();
@@ -285,17 +298,20 @@
 
 static void SC_uploadToTexture2(RsAllocation va, uint32_t baseMipLevel)
 {
+    CHECK_OBJ(va);
     GET_TLS();
     rsi_AllocationUploadToTexture(rsc, va, false, baseMipLevel);
 }
 static void SC_uploadToTexture(RsAllocation va)
 {
+    CHECK_OBJ(va);
     GET_TLS();
     rsi_AllocationUploadToTexture(rsc, va, false, 0);
 }
 
 static void SC_uploadToBufferObject(RsAllocation va)
 {
+    CHECK_OBJ(va);
     GET_TLS();
     rsi_AllocationUploadToBufferObject(rsc, va);
 }
@@ -336,6 +352,7 @@
 
 static void SC_DrawTextAlloc(RsAllocation va, int x, int y)
 {
+    CHECK_OBJ(va);
     GET_TLS();
     Allocation *alloc = static_cast<Allocation *>(va);
     rsc->mStateFont.renderText(alloc, x, y);
@@ -349,6 +366,7 @@
 
 static void SC_BindFont(RsFont font)
 {
+    CHECK_OBJ(font);
     GET_TLS();
     rsi_ContextBindFont(rsc, font);
 }