From 730ee65d4ddb307898053b623120bad1655fadad Mon Sep 17 00:00:00 2001 From: Jason Sams Date: Tue, 18 Aug 2009 17:07:09 -0700 Subject: [PATCH] Implement OOB destroy method that can be called from the java finalizer removing the need to explicitly destroy objects. --- .../java/android/renderscript/BaseObj.java | 7 +- .../android/renderscript/RenderScript.java | 1 + .../jni/android_renderscript_RenderScript.cpp | 10 +++ libs/rs/RenderScript.h | 1 + .../src/com/android/fountain/FountainRS.java | 18 +++-- libs/rs/rsContext.cpp | 69 +++++++++++++++++++ libs/rs/rsContext.h | 12 ++++ 7 files changed, 107 insertions(+), 11 deletions(-) diff --git a/graphics/java/android/renderscript/BaseObj.java b/graphics/java/android/renderscript/BaseObj.java index eaeb40164e898..c25f16a60f2d2 100644 --- a/graphics/java/android/renderscript/BaseObj.java +++ b/graphics/java/android/renderscript/BaseObj.java @@ -60,8 +60,13 @@ class BaseObj { protected void finalize() throws Throwable { if (!mDestroyed) { + if(mID != 0) { + mRS.nObjDestroyOOB(mID); + } + mID = 0; + mDestroyed = true; Log.v(RenderScript.LOG_TAG, - getClass() + " finalized without having released the RS reference."); + getClass() + " auto finalizing object without having released the RS reference."); } super.finalize(); } diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java index 08418c662a8cd..fca1c7ad78d08 100644 --- a/graphics/java/android/renderscript/RenderScript.java +++ b/graphics/java/android/renderscript/RenderScript.java @@ -75,6 +75,7 @@ public class RenderScript { native void nAssignName(int obj, byte[] name); native void nObjDestroy(int id); + native void nObjDestroyOOB(int id); native int nFileOpen(byte[] name); native void nElementBegin(); diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp index 2d4816585034a..001ecd0f03a5a 100644 --- a/graphics/jni/android_renderscript_RenderScript.cpp +++ b/graphics/jni/android_renderscript_RenderScript.cpp @@ -86,6 +86,15 @@ nObjDestroy(JNIEnv *_env, jobject _this, jint obj) rsObjDestroy(con, (void *)obj); } +static void +nObjDestroyOOB(JNIEnv *_env, jobject _this, jint obj) +{ + // This function only differs from nObjDestroy in that it calls the + // special Out Of Band version of ObjDestroy which is thread safe. + RsContext con = (RsContext)(_env->GetIntField(_this, gContextId)); + LOG_API("nObjDestroyOOB, con(%p) obj(%p)", con, (void *)obj); + rsObjDestroyOOB(con, (void *)obj); +} static jint nFileOpen(JNIEnv *_env, jobject _this, jbyteArray str) @@ -1217,6 +1226,7 @@ static JNINativeMethod methods[] = { {"nContextDestroy", "(I)V", (void*)nContextDestroy }, {"nAssignName", "(I[B)V", (void*)nAssignName }, {"nObjDestroy", "(I)V", (void*)nObjDestroy }, +{"nObjDestroyOOB", "(I)V", (void*)nObjDestroyOOB }, {"nFileOpen", "([B)I", (void*)nFileOpen }, diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h index d7d572ea99e71..e4cf00f0d4fc3 100644 --- a/libs/rs/RenderScript.h +++ b/libs/rs/RenderScript.h @@ -51,6 +51,7 @@ void rsDeviceDestroy(RsDevice); RsContext rsContextCreate(RsDevice, void *, uint32_t version); void rsContextDestroy(RsContext); +void rsObjDestroyOOB(RsContext, void *); #define RS_MAX_TEXTURE 2 diff --git a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java b/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java index da9eda8434889..6d400c523ddfa 100644 --- a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java +++ b/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java @@ -67,8 +67,6 @@ public class FountainRS { private RenderScript mRS; private Allocation mIntAlloc; - private Allocation mPartAlloc; - private Script mScript; private SimpleMesh mSM; private SomeData mSD; private Type mSDType; @@ -94,9 +92,9 @@ public class FountainRS { mSM = smb.create(); mSM.setName("PartMesh"); - mPartAlloc = mSM.createVertexAllocation(vtxSlot); - mPartAlloc.setName("PartBuffer"); - mSM.bindVertexAllocation(mPartAlloc, 0); + Allocation partAlloc = mSM.createVertexAllocation(vtxSlot); + partAlloc.setName("PartBuffer"); + mSM.bindVertexAllocation(partAlloc, 0); // All setup of named objects should be done by this point // because we are about to compile the script. @@ -104,12 +102,12 @@ public class FountainRS { sb.setScript(mRes, R.raw.fountain); sb.setRoot(true); sb.setType(mSDType, "Control", 0); - mScript = sb.create(); - mScript.setClearColor(0.0f, 0.0f, 0.0f, 1.0f); + Script script = sb.create(); + script.setClearColor(0.0f, 0.0f, 0.0f, 1.0f); - mScript.bindAllocation(mIntAlloc, 0); - mScript.bindAllocation(mPartAlloc, 1); - mRS.contextBindRootScript(mScript); + script.bindAllocation(mIntAlloc, 0); + script.bindAllocation(partAlloc, 1); + mRS.contextBindRootScript(script); } } diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp index bc0cf12fc147f..7bfa81edaa008 100644 --- a/libs/rs/rsContext.cpp +++ b/libs/rs/rsContext.cpp @@ -170,12 +170,14 @@ void * Context::threadProc(void *vrsc) mDraw = rsc->runRootScript(); eglSwapBuffers(rsc->mDisplay, rsc->mSurface); } + rsc->objDestroyOOBRun(); } glClearColor(0,0,0,0); glClear(GL_COLOR_BUFFER_BIT); eglSwapBuffers(rsc->mDisplay, rsc->mSurface); eglTerminate(rsc->mDisplay); + rsc->objDestroyOOBRun(); return NULL; } @@ -210,6 +212,8 @@ Context::Context(Device *dev, Surface *sur) mWndSurface = sur; + objDestroyOOBInit(); + LOGV("RS Launching thread"); status = pthread_create(&mThreadId, &threadAttr, threadProc, this); if (status) { @@ -229,11 +233,14 @@ Context::~Context() void *res; int status = pthread_join(mThreadId, &res); + objDestroyOOBRun(); if (mDev) { mDev->removeContext(this); pthread_key_delete(gThreadTLSKey); } + + objDestroyOOBDestroy(); } void Context::swapBuffers() @@ -345,6 +352,62 @@ void Context::appendVarDefines(String8 *str) const } } +bool Context::objDestroyOOBInit() +{ + int status = pthread_mutex_init(&mObjDestroy.mMutex, NULL); + if (status) { + LOGE("Context::ObjDestroyOOBInit mutex init failure"); + return false; + } + return true; +} + +void Context::objDestroyOOBRun() +{ + if (mObjDestroy.mNeedToEmpty) { + int status = pthread_mutex_lock(&mObjDestroy.mMutex); + if (status) { + LOGE("Context::ObjDestroyOOBRun: error %i locking for OOBRun.", status); + return; + } + + for (size_t ct = 0; ct < mObjDestroy.mDestroyList.size(); ct++) { + mObjDestroy.mDestroyList[ct]->decRef(); + } + mObjDestroy.mDestroyList.clear(); + mObjDestroy.mNeedToEmpty = false; + + status = pthread_mutex_unlock(&mObjDestroy.mMutex); + if (status) { + LOGE("Context::ObjDestroyOOBRun: error %i unlocking for set condition.", status); + } + } +} + +void Context::objDestroyOOBDestroy() +{ + rsAssert(!mObjDestroy.mNeedToEmpty); + pthread_mutex_destroy(&mObjDestroy.mMutex); +} + +void Context::objDestroyAdd(ObjectBase *obj) +{ + int status = pthread_mutex_lock(&mObjDestroy.mMutex); + if (status) { + LOGE("Context::ObjDestroyOOBRun: error %i locking for OOBRun.", status); + return; + } + + mObjDestroy.mNeedToEmpty = true; + mObjDestroy.mDestroyList.add(obj); + + status = pthread_mutex_unlock(&mObjDestroy.mMutex); + if (status) { + LOGE("Context::ObjDestroyOOBRun: error %i unlocking for set condition.", status); + } +} + + /////////////////////////////////////////////////////////////////////////////////////////// // @@ -429,3 +492,9 @@ void rsContextDestroy(RsContext vrsc) delete rsc; } +void rsObjDestroyOOB(RsContext vrsc, void *obj) +{ + Context * rsc = static_cast(vrsc); + rsc->objDestroyAdd(static_cast(obj)); +} + diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h index 3d17298fbcb97..52901b2d3e680 100644 --- a/libs/rs/rsContext.h +++ b/libs/rs/rsContext.h @@ -118,6 +118,7 @@ public: ThreadIO mIO; + void objDestroyAdd(ObjectBase *); protected: Device *mDev; @@ -142,6 +143,17 @@ protected: ObjectBaseRef mVertex; ObjectBaseRef mFragmentStore; + + struct ObjDestroyOOB { + pthread_mutex_t mMutex; + Vector mDestroyList; + bool mNeedToEmpty; + }; + ObjDestroyOOB mObjDestroy; + bool objDestroyOOBInit(); + void objDestroyOOBRun(); + void objDestroyOOBDestroy(); + private: Context();