Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1c415171 authored by Jason Sams's avatar Jason Sams
Browse files

Handle user message ID 0

Pass RS runtime errors back to java.
throw exceptions for runtime errors.

Change-Id: Ifcf16cbbf9b98137971dced5076f8a5563eb016c
parent 553a53ef
Loading
Loading
Loading
Loading
+56 −19
Original line number Diff line number Diff line
@@ -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,13 +643,40 @@ 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 {
                        throw new RSInvalidStateException("Received a message from the script with no message handler installed.");
                    }
                    continue;
                }

                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
@@ -641,14 +686,6 @@ public class RenderScript {
                } catch(InterruptedException e) {
                }
            }
                    continue;
                }
                if(mRS.mMessageCallback != null) {
                    mRS.mMessageCallback.mData = rbuf;
                    mRS.mMessageCallback.mID = msg;
                    mRS.mMessageCallback.run();
                }
            }
            Log.d(LOG_TAG, "MessageThread exiting.");
        }
    }
+45 −13
Original line number Diff line number Diff line
@@ -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;
}

@@ -1224,7 +1253,10 @@ static JNINativeMethod methods[] = {
{"nDeviceCreate",                  "()I",                                     (void*)nDeviceCreate },
{"nDeviceDestroy",                 "(I)V",                                    (void*)nDeviceDestroy },
{"nDeviceSetConfig",               "(III)V",                                  (void*)nDeviceSetConfig },
{"nContextGetMessage",             "(I[IZ)I",                               (void*)nContextGetMessage },
{"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 },

+12 −1
Original line number Diff line number Diff line
@@ -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,
+44 −21
Original line number Diff line number Diff line
@@ -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)
{
    //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;
    }

    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 && 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)
+3 −2
Original line number Diff line number Diff line
@@ -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();
Loading