Handle user message ID 0
Pass RS runtime errors back to java. throw exceptions for runtime errors. Change-Id: Ifcf16cbbf9b98137971dced5076f8a5563eb016c
This commit is contained in:
@@ -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.");
|
||||
|
||||
@@ -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 },
|
||||
{"_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 },
|
||||
{"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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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->getMessageToClient(data, receiveLen, bufferLen, wait);
|
||||
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, subID, bufferLen, wait);
|
||||
}
|
||||
|
||||
void rsContextInitToClient(RsContext vrsc)
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user