diff options
author | Jason Sams <rjsams@android.com> | 2010-11-08 17:06:46 -0800 |
---|---|---|
committer | Jason Sams <rjsams@android.com> | 2010-11-08 17:19:31 -0800 |
commit | 1c41517124a90fcfdb95dc069fc492c6fcf1ff25 (patch) | |
tree | 43a463cfe40b0cf7e96ca9045075e31390d1e60e | |
parent | 553a53ef9ff789dff8b5a74dfea4d6f37feeb263 (diff) | |
download | frameworks_base-1c41517124a90fcfdb95dc069fc492c6fcf1ff25.zip frameworks_base-1c41517124a90fcfdb95dc069fc492c6fcf1ff25.tar.gz frameworks_base-1c41517124a90fcfdb95dc069fc492c6fcf1ff25.tar.bz2 |
Handle user message ID 0
Pass RS runtime errors back to java.
throw exceptions for runtime errors.
Change-Id: Ifcf16cbbf9b98137971dced5076f8a5563eb016c
-rw-r--r-- | graphics/java/android/renderscript/RenderScript.java | 75 | ||||
-rw-r--r-- | graphics/jni/android_renderscript_RenderScript.cpp | 58 | ||||
-rw-r--r-- | libs/rs/RenderScript.h | 13 | ||||
-rw-r--r-- | libs/rs/rsContext.cpp | 65 | ||||
-rw-r--r-- | libs/rs/rsContext.h | 5 | ||||
-rw-r--r-- | libs/rs/rsScriptC_Lib.cpp | 8 |
6 files changed, 164 insertions, 60 deletions
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java index 0c9a4ed..b3774d4 100644 --- a/graphics/java/android/renderscript/RenderScript.java +++ b/graphics/java/android/renderscript/RenderScript.java @@ -62,7 +62,9 @@ public class RenderScript { native int nDeviceCreate(); native void nDeviceDestroy(int dev); native void nDeviceSetConfig(int dev, int param, int value); - native int nContextGetMessage(int con, int[] data, boolean wait); + native void nContextGetUserMessage(int con, int[] data); + native String nContextGetErrorMessage(int con); + native int nContextPeekMessage(int con, int[] subID, boolean wait); native void nContextInitToClient(int con); native void nContextDeinitToClient(int con); @@ -582,11 +584,20 @@ public class RenderScript { public static class RSMessage implements Runnable { protected int[] mData; protected int mID; + protected int mLength; public void run() { } } public RSMessage mMessageCallback = null; + public static class RSAsyncError implements Runnable { + protected String mErrorMessage; + protected int mErrorNum; + public void run() { + } + } + public RSAsyncError mErrorCallback = null; + public enum Priority { LOW (5), //ANDROID_PRIORITY_BACKGROUND + 5 NORMAL (-4); //ANDROID_PRIORITY_DISPLAY @@ -611,6 +622,13 @@ public class RenderScript { protected static class MessageThread extends Thread { RenderScript mRS; boolean mRun = true; + int[] auxData = new int[2]; + + public static final int RS_MESSAGE_TO_CLIENT_NONE = 0; + public static final int RS_MESSAGE_TO_CLIENT_EXCEPTION = 1; + public static final int RS_MESSAGE_TO_CLIENT_RESIZE = 2; + public static final int RS_MESSAGE_TO_CLIENT_ERROR = 3; + public static final int RS_MESSAGE_TO_CLIENT_USER = 4; MessageThread(RenderScript rs) { super("RSMessageThread"); @@ -625,28 +643,47 @@ public class RenderScript { mRS.nContextInitToClient(mRS.mContext); while(mRun) { rbuf[0] = 0; - int msg = mRS.nContextGetMessage(mRS.mContext, rbuf, true); - if ((msg == 0)) { - // Can happen for two reasons - if (rbuf[0] > 0 && mRun) { - // 1: Buffer needs to be enlarged. - rbuf = new int[rbuf[0] + 2]; + int msg = mRS.nContextPeekMessage(mRS.mContext, auxData, true); + int size = auxData[1]; + int subID = auxData[0]; + + if (msg == RS_MESSAGE_TO_CLIENT_USER) { + if ((size>>2) >= rbuf.length) { + rbuf = new int[(size + 3) >> 2]; + } + mRS.nContextGetUserMessage(mRS.mContext, rbuf); + + if(mRS.mMessageCallback != null) { + mRS.mMessageCallback.mData = rbuf; + mRS.mMessageCallback.mID = subID; + mRS.mMessageCallback.mLength = size; + mRS.mMessageCallback.run(); } 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) { - } + throw new RSInvalidStateException("Received a message from the script with no message handler installed."); } continue; } - if(mRS.mMessageCallback != null) { - mRS.mMessageCallback.mData = rbuf; - mRS.mMessageCallback.mID = msg; - mRS.mMessageCallback.run(); + + if (msg == RS_MESSAGE_TO_CLIENT_ERROR) { + String e = mRS.nContextGetErrorMessage(mRS.mContext); + + if(mRS.mErrorCallback != null) { + mRS.mErrorCallback.mErrorMessage = e; + mRS.mErrorCallback.mErrorNum = subID; + mRS.mErrorCallback.run(); + } else { + //throw new RSRuntimeException("Received error num " + subID + ", details: " + e); + } + continue; + } + + // 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) { } } Log.d(LOG_TAG, "MessageThread exiting."); diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp index 77cbc10..dd84848 100644 --- a/graphics/jni/android_renderscript_RenderScript.cpp +++ b/graphics/jni/android_renderscript_RenderScript.cpp @@ -223,19 +223,48 @@ nContextResume(JNIEnv *_env, jobject _this, RsContext con) rsContextResume(con); } -static jint -nContextGetMessage(JNIEnv *_env, jobject _this, RsContext con, jintArray data, jboolean wait) + +static jstring +nContextGetErrorMessage(JNIEnv *_env, jobject _this, RsContext con) +{ + LOG_API("nContextGetErrorMessage, con(%p)", con); + char buf[1024]; + + size_t receiveLen; + uint32_t subID; + int id = rsContextGetMessage(con, buf, &receiveLen, &subID, sizeof(buf), true); + if (!id && receiveLen) { + LOGV("message receive buffer too small. %i", receiveLen); + } + return _env->NewStringUTF(buf); +} + +static void +nContextGetUserMessage(JNIEnv *_env, jobject _this, RsContext con, jintArray data) { jint len = _env->GetArrayLength(data); LOG_API("nContextGetMessage, con(%p), len(%i)", con, len); jint *ptr = _env->GetIntArrayElements(data, NULL); size_t receiveLen; - int id = rsContextGetMessage(con, ptr, &receiveLen, len * 4, wait); + uint32_t subID; + int id = rsContextGetMessage(con, ptr, &receiveLen, &subID, len * 4, true); if (!id && receiveLen) { LOGV("message receive buffer too small. %i", receiveLen); - *ptr = (jint)receiveLen; } _env->ReleaseIntArrayElements(data, ptr, 0); +} + +static jint +nContextPeekMessage(JNIEnv *_env, jobject _this, RsContext con, jintArray auxData, jboolean wait) +{ + LOG_API("nContextPeekMessage, con(%p)", con); + jint *auxDataPtr = _env->GetIntArrayElements(auxData, NULL); + size_t receiveLen; + uint32_t subID; + int id = rsContextPeekMessage(con, &receiveLen, &subID, wait); + auxDataPtr[0] = (jint)subID; + auxDataPtr[1] = (jint)receiveLen; + _env->ReleaseIntArrayElements(auxData, auxDataPtr, 0); return id; } @@ -1218,15 +1247,18 @@ nMeshGetIndices(JNIEnv *_env, jobject _this, RsContext con, jint mesh, jintArray static const char *classPathName = "android/renderscript/RenderScript"; static JNINativeMethod methods[] = { -{"_nInit", "()V", (void*)_nInit }, -{"nInitElements", "(IIII)V", (void*)nInitElements }, - -{"nDeviceCreate", "()I", (void*)nDeviceCreate }, -{"nDeviceDestroy", "(I)V", (void*)nDeviceDestroy }, -{"nDeviceSetConfig", "(III)V", (void*)nDeviceSetConfig }, -{"nContextGetMessage", "(I[IZ)I", (void*)nContextGetMessage }, -{"nContextInitToClient", "(I)V", (void*)nContextInitToClient }, -{"nContextDeinitToClient", "(I)V", (void*)nContextDeinitToClient }, +{"_nInit", "()V", (void*)_nInit }, +{"nInitElements", "(IIII)V", (void*)nInitElements }, + +{"nDeviceCreate", "()I", (void*)nDeviceCreate }, +{"nDeviceDestroy", "(I)V", (void*)nDeviceDestroy }, +{"nDeviceSetConfig", "(III)V", (void*)nDeviceSetConfig }, +{"nContextGetUserMessage", "(I[I)V", (void*)nContextGetUserMessage }, +{"nContextGetErrorMessage", "(I)Ljava/lang/String;", (void*)nContextGetErrorMessage }, +{"nContextPeekMessage", "(I[IZ)I", (void*)nContextPeekMessage }, + +{"nContextInitToClient", "(I)V", (void*)nContextInitToClient }, +{"nContextDeinitToClient", "(I)V", (void*)nContextDeinitToClient }, // All methods below are thread protected in java. diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h index 8c2081d..20e289d 100644 --- a/libs/rs/RenderScript.h +++ b/libs/rs/RenderScript.h @@ -79,13 +79,24 @@ RsContext rsContextCreate(RsDevice, uint32_t version); RsContext rsContextCreateGL(RsDevice, uint32_t version, RsSurfaceConfig sc); void rsContextDestroy(RsContext); -uint32_t rsContextGetMessage(RsContext, void *data, size_t *receiveLen, size_t bufferLen, bool wait); +enum RsMessageToClientType { + RS_MESSAGE_TO_CLIENT_NONE = 0, + RS_MESSAGE_TO_CLIENT_EXCEPTION = 1, + RS_MESSAGE_TO_CLIENT_RESIZE = 2, + RS_MESSAGE_TO_CLIENT_ERROR = 3, + RS_MESSAGE_TO_CLIENT_USER = 4 +}; + +RsMessageToClientType rsContextGetMessage(RsContext vrsc, void *data, size_t *receiveLen, uint32_t *subID, size_t bufferLen, bool wait); +RsMessageToClientType rsContextPeekMessage(RsContext vrsc, size_t *receiveLen, uint32_t *subID, bool wait); void rsContextInitToClient(RsContext); void rsContextDeinitToClient(RsContext); #define RS_MAX_TEXTURE 2 #define RS_MAX_ATTRIBS 16 + + enum RsDataType { RS_TYPE_NONE, RS_TYPE_FLOAT_16, diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp index 678d327..9d766b7 100644 --- a/libs/rs/rsContext.cpp +++ b/libs/rs/rsContext.cpp @@ -846,53 +846,69 @@ void Context::removeName(ObjectBase *obj) } } -uint32_t Context::getMessageToClient(void *data, size_t *receiveLen, size_t bufferLen, bool wait) +RsMessageToClientType Context::peekMessageToClient(size_t *receiveLen, uint32_t *subID, bool wait) +{ + *receiveLen = 0; + if (!wait && mIO.mToClient.isEmpty()) { + return RS_MESSAGE_TO_CLIENT_NONE; + } + + uint32_t bytesData = 0; + uint32_t commandID = 0; + const uint32_t *d = (const uint32_t *)mIO.mToClient.get(&commandID, &bytesData); + *receiveLen = bytesData - sizeof(uint32_t); + if (bytesData) { + *subID = d[0]; + } + return (RsMessageToClientType)commandID; +} + +RsMessageToClientType Context::getMessageToClient(void *data, size_t *receiveLen, uint32_t *subID, 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. - return 0; - } + if (!wait && mIO.mToClient.isEmpty()) { + return RS_MESSAGE_TO_CLIENT_NONE; } //LOGE("getMessageToClient 2 con=%p", this); uint32_t bytesData = 0; uint32_t commandID = 0; - const void *d = mIO.mToClient.get(&commandID, &bytesData); + const uint32_t *d = (const uint32_t *)mIO.mToClient.get(&commandID, &bytesData); //LOGE("getMessageToClient 3 %i %i", commandID, bytesData); - *receiveLen = bytesData; + *receiveLen = bytesData - sizeof(uint32_t); + *subID = d[0]; + + //LOGE("getMessageToClient %i %i", commandID, *subID); if (bufferLen >= bytesData) { - memcpy(data, d, bytesData); + memcpy(data, d+1, *receiveLen); mIO.mToClient.next(); - return commandID; + return (RsMessageToClientType)commandID; } - return 0; + return RS_MESSAGE_TO_CLIENT_RESIZE; } -bool Context::sendMessageToClient(void *data, uint32_t cmdID, size_t len, bool waitForSpace) +bool Context::sendMessageToClient(const void *data, RsMessageToClientType cmdID, uint32_t subID, size_t len, bool waitForSpace) { - //LOGE("sendMessageToClient %i %i %i", cmdID, len, waitForSpace); + //LOGE("sendMessageToClient %i %i %i %i", cmdID, subID, len, waitForSpace); if (cmdID == 0) { LOGE("Attempting to send invalid command 0 to client."); return false; } if (!waitForSpace) { - if (!mIO.mToClient.makeSpaceNonBlocking(len + 8)) { + if (!mIO.mToClient.makeSpaceNonBlocking(len + 12)) { // Not enough room, and not waiting. return false; } } //LOGE("sendMessageToClient 2"); + uint32_t *p = (uint32_t *)mIO.mToClient.reserve(len + sizeof(subID)); + p[0] = subID; if (len > 0) { - void *p = mIO.mToClient.reserve(len); - memcpy(p, data, len); - mIO.mToClient.commit(cmdID, len); - } else { - mIO.mToClient.commit(cmdID, 0); + memcpy(p+1, data, len); } + mIO.mToClient.commit(cmdID, len + sizeof(subID)); //LOGE("sendMessageToClient 3"); return true; } @@ -923,6 +939,7 @@ void Context::setError(RsError e, const char *msg) { mError = e; mErrorMsg = msg; + sendMessageToClient(msg, RS_MESSAGE_TO_CLIENT_ERROR, e, strlen(msg) + 1, true); } @@ -1080,10 +1097,16 @@ void rsContextDestroy(RsContext vrsc) delete rsc; } -uint32_t rsContextGetMessage(RsContext vrsc, void *data, size_t *receiveLen, size_t bufferLen, bool wait) +RsMessageToClientType rsContextPeekMessage(RsContext vrsc, size_t *receiveLen, uint32_t *subID, bool wait) +{ + Context * rsc = static_cast<Context *>(vrsc); + return rsc->peekMessageToClient(receiveLen, subID, wait); +} + +RsMessageToClientType rsContextGetMessage(RsContext vrsc, void *data, size_t *receiveLen, uint32_t *subID, size_t bufferLen, bool wait) { Context * rsc = static_cast<Context *>(vrsc); - return rsc->getMessageToClient(data, receiveLen, bufferLen, wait); + return rsc->getMessageToClient(data, receiveLen, subID, bufferLen, wait); } void rsContextInitToClient(RsContext vrsc) diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h index 2017ceb..2b9e57a 100644 --- a/libs/rs/rsContext.h +++ b/libs/rs/rsContext.h @@ -128,8 +128,9 @@ public: void assignName(ObjectBase *obj, const char *name, uint32_t len); void removeName(ObjectBase *obj); - uint32_t getMessageToClient(void *data, size_t *receiveLen, size_t bufferLen, bool wait); - bool sendMessageToClient(void *data, uint32_t cmdID, size_t len, bool waitForSpace); + 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); uint32_t runScript(Script *s); void initToClient(); diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp index ecae306..bb8e6a7 100644 --- a/libs/rs/rsScriptC_Lib.cpp +++ b/libs/rs/rsScriptC_Lib.cpp @@ -347,28 +347,28 @@ static uint32_t SC_toClient2(int cmdID, void *data, int len) { GET_TLS(); //LOGE("SC_toClient %i %i %i", cmdID, len); - return rsc->sendMessageToClient(data, cmdID, len, false); + return rsc->sendMessageToClient(data, RS_MESSAGE_TO_CLIENT_USER, cmdID, len, false); } static uint32_t SC_toClient(int cmdID) { GET_TLS(); //LOGE("SC_toClient %i", cmdID); - return rsc->sendMessageToClient(NULL, cmdID, 0, false); + return rsc->sendMessageToClient(NULL, RS_MESSAGE_TO_CLIENT_USER, cmdID, 0, false); } static uint32_t SC_toClientBlocking2(int cmdID, void *data, int len) { GET_TLS(); //LOGE("SC_toClientBlocking %i %i", cmdID, len); - return rsc->sendMessageToClient(data, cmdID, len, true); + return rsc->sendMessageToClient(data, RS_MESSAGE_TO_CLIENT_USER, cmdID, len, true); } static uint32_t SC_toClientBlocking(int cmdID) { GET_TLS(); //LOGE("SC_toClientBlocking %i", cmdID); - return rsc->sendMessageToClient(NULL, cmdID, 0, true); + return rsc->sendMessageToClient(NULL, RS_MESSAGE_TO_CLIENT_USER, cmdID, 0, true); } int SC_divsi3(int a, int b) |