summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Sams <rjsams@android.com>2010-11-08 17:06:46 -0800
committerJason Sams <rjsams@android.com>2010-11-08 17:19:31 -0800
commit1c41517124a90fcfdb95dc069fc492c6fcf1ff25 (patch)
tree43a463cfe40b0cf7e96ca9045075e31390d1e60e
parent553a53ef9ff789dff8b5a74dfea4d6f37feeb263 (diff)
downloadframeworks_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.java75
-rw-r--r--graphics/jni/android_renderscript_RenderScript.cpp58
-rw-r--r--libs/rs/RenderScript.h13
-rw-r--r--libs/rs/rsContext.cpp65
-rw-r--r--libs/rs/rsContext.h5
-rw-r--r--libs/rs/rsScriptC_Lib.cpp8
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)