Merge commit '9816a5d1ee1dfa733c740defbe71bf7bf5b9fc52' into eclair-mr2-plus-aosp * commit '9816a5d1ee1dfa733c740defbe71bf7bf5b9fc52': Implement data push from scripts. Fixes the problem where apps would have to poll to monitor a scripts state.
This commit is contained in:
@@ -75,6 +75,9 @@ public class RenderScript {
|
|||||||
native void nContextAddDefineF(String name, float value);
|
native void nContextAddDefineF(String name, float value);
|
||||||
native void nContextPause();
|
native void nContextPause();
|
||||||
native void nContextResume();
|
native void nContextResume();
|
||||||
|
native int nContextGetMessage(int[] data, boolean wait);
|
||||||
|
native void nContextInitToClient();
|
||||||
|
native void nContextDeinitToClient();
|
||||||
|
|
||||||
native void nAssignName(int obj, byte[] name);
|
native void nAssignName(int obj, byte[] name);
|
||||||
native void nObjDestroy(int id);
|
native void nObjDestroy(int id);
|
||||||
@@ -190,6 +193,7 @@ public class RenderScript {
|
|||||||
private int mContext;
|
private int mContext;
|
||||||
@SuppressWarnings({"FieldCanBeLocal"})
|
@SuppressWarnings({"FieldCanBeLocal"})
|
||||||
private Surface mSurface;
|
private Surface mSurface;
|
||||||
|
private MessageThread mMessageThread;
|
||||||
|
|
||||||
|
|
||||||
Element mElement_USER_U8;
|
Element mElement_USER_U8;
|
||||||
@@ -214,6 +218,52 @@ public class RenderScript {
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
|
||||||
|
public static class RSMessage implements Runnable {
|
||||||
|
protected int[] mData;
|
||||||
|
protected int mID;
|
||||||
|
public void run() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public RSMessage mMessageCallback = null;
|
||||||
|
|
||||||
|
private static class MessageThread extends Thread {
|
||||||
|
RenderScript mRS;
|
||||||
|
boolean mRun = true;
|
||||||
|
|
||||||
|
MessageThread(RenderScript rs) {
|
||||||
|
super("RSMessageThread");
|
||||||
|
mRS = rs;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
// This function is a temporary solution. The final solution will
|
||||||
|
// used typed allocations where the message id is the type indicator.
|
||||||
|
int[] rbuf = new int[16];
|
||||||
|
mRS.nContextInitToClient();
|
||||||
|
while(mRun) {
|
||||||
|
int msg = mRS.nContextGetMessage(rbuf, true);
|
||||||
|
if (msg == 0) {
|
||||||
|
// Should only happen during 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) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(mRS.mMessageCallback != null) {
|
||||||
|
mRS.mMessageCallback.mData = rbuf;
|
||||||
|
mRS.mMessageCallback.mID = msg;
|
||||||
|
mRS.mMessageCallback.run();
|
||||||
|
}
|
||||||
|
//Log.d("rs", "MessageThread msg " + msg + " v1 " + rbuf[0] + " v2 " + rbuf[1] + " v3 " +rbuf[2]);
|
||||||
|
}
|
||||||
|
Log.d("rs", "MessageThread exiting.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public RenderScript(Surface sur, boolean useDepth, boolean forceSW) {
|
public RenderScript(Surface sur, boolean useDepth, boolean forceSW) {
|
||||||
mSurface = sur;
|
mSurface = sur;
|
||||||
mDev = nDeviceCreate();
|
mDev = nDeviceCreate();
|
||||||
@@ -222,9 +272,14 @@ public class RenderScript {
|
|||||||
}
|
}
|
||||||
mContext = nContextCreate(mDev, mSurface, 0, useDepth);
|
mContext = nContextCreate(mDev, mSurface, 0, useDepth);
|
||||||
Element.initPredefined(this);
|
Element.initPredefined(this);
|
||||||
|
mMessageThread = new MessageThread(this);
|
||||||
|
mMessageThread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
|
nContextDeinitToClient();
|
||||||
|
mMessageThread.mRun = false;
|
||||||
|
|
||||||
nContextDestroy(mContext);
|
nContextDestroy(mContext);
|
||||||
mContext = 0;
|
mContext = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -194,6 +194,37 @@ nContextResume(JNIEnv *_env, jobject _this)
|
|||||||
rsContextResume(con);
|
rsContextResume(con);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static jint
|
||||||
|
nContextGetMessage(JNIEnv *_env, jobject _this, jintArray data, jboolean wait)
|
||||||
|
{
|
||||||
|
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
|
||||||
|
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);
|
||||||
|
if (!id && receiveLen) {
|
||||||
|
LOGE("message receive buffer too small. %i", receiveLen);
|
||||||
|
}
|
||||||
|
_env->ReleaseIntArrayElements(data, ptr, 0);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nContextInitToClient(JNIEnv *_env, jobject _this)
|
||||||
|
{
|
||||||
|
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
|
||||||
|
LOG_API("nContextInitToClient, con(%p)", con);
|
||||||
|
rsContextInitToClient(con);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nContextDeinitToClient(JNIEnv *_env, jobject _this)
|
||||||
|
{
|
||||||
|
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
|
||||||
|
LOG_API("nContextDeinitToClient, con(%p)", con);
|
||||||
|
rsContextDeinitToClient(con);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
nElementBegin(JNIEnv *_env, jobject _this)
|
nElementBegin(JNIEnv *_env, jobject _this)
|
||||||
{
|
{
|
||||||
@@ -1303,6 +1334,9 @@ static JNINativeMethod methods[] = {
|
|||||||
{"nAssignName", "(I[B)V", (void*)nAssignName },
|
{"nAssignName", "(I[B)V", (void*)nAssignName },
|
||||||
{"nObjDestroy", "(I)V", (void*)nObjDestroy },
|
{"nObjDestroy", "(I)V", (void*)nObjDestroy },
|
||||||
{"nObjDestroyOOB", "(I)V", (void*)nObjDestroyOOB },
|
{"nObjDestroyOOB", "(I)V", (void*)nObjDestroyOOB },
|
||||||
|
{"nContextGetMessage", "([IZ)I", (void*)nContextGetMessage },
|
||||||
|
{"nContextInitToClient", "()V", (void*)nContextInitToClient },
|
||||||
|
{"nContextDeinitToClient", "()V", (void*)nContextDeinitToClient },
|
||||||
|
|
||||||
{"nFileOpen", "([B)I", (void*)nFileOpen },
|
{"nFileOpen", "([B)I", (void*)nFileOpen },
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,10 @@ RsContext rsContextCreate(RsDevice, void *, uint32_t version, bool useDepth);
|
|||||||
void rsContextDestroy(RsContext);
|
void rsContextDestroy(RsContext);
|
||||||
void rsObjDestroyOOB(RsContext, void *);
|
void rsObjDestroyOOB(RsContext, void *);
|
||||||
|
|
||||||
|
uint32_t rsContextGetMessage(RsContext, void *data, size_t *receiveLen, size_t bufferLen, bool wait);
|
||||||
|
void rsContextInitToClient(RsContext);
|
||||||
|
void rsContextDeinitToClient(RsContext);
|
||||||
|
|
||||||
#define RS_MAX_TEXTURE 2
|
#define RS_MAX_TEXTURE 2
|
||||||
|
|
||||||
enum RsDataType {
|
enum RsDataType {
|
||||||
|
|||||||
@@ -142,6 +142,7 @@ bool Context::runRootScript()
|
|||||||
if (this->props.mLogTimes) {
|
if (this->props.mLogTimes) {
|
||||||
timerSet(RS_TIMER_SCRIPT);
|
timerSet(RS_TIMER_SCRIPT);
|
||||||
}
|
}
|
||||||
|
mStateFragmentStore.mLast.clear();
|
||||||
bool ret = runScript(mRootScript.get(), 0);
|
bool ret = runScript(mRootScript.get(), 0);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -529,6 +530,64 @@ void Context::objDestroyAdd(ObjectBase *obj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t Context::getMessageToClient(void *data, size_t *receiveLen, size_t bufferLen, bool wait)
|
||||||
|
{
|
||||||
|
//LOGE("getMessageToClient %i %i", bufferLen, wait);
|
||||||
|
if (!wait) {
|
||||||
|
if (mIO.mToClient.isEmpty()) {
|
||||||
|
// No message to get and not going to wait for one.
|
||||||
|
receiveLen = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//LOGE("getMessageToClient 2 con=%p", this);
|
||||||
|
uint32_t bytesData = 0;
|
||||||
|
uint32_t commandID = 0;
|
||||||
|
const void *d = mIO.mToClient.get(&commandID, &bytesData);
|
||||||
|
//LOGE("getMessageToClient 3 %i %i", commandID, bytesData);
|
||||||
|
|
||||||
|
*receiveLen = bytesData;
|
||||||
|
if (bufferLen >= bytesData) {
|
||||||
|
memcpy(data, d, bytesData);
|
||||||
|
mIO.mToClient.next();
|
||||||
|
return commandID;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Context::sendMessageToClient(void *data, uint32_t cmdID, size_t len, bool waitForSpace)
|
||||||
|
{
|
||||||
|
//LOGE("sendMessageToClient %i %i %i", cmdID, len, waitForSpace);
|
||||||
|
if (cmdID == 0) {
|
||||||
|
LOGE("Attempting to send invalid command 0 to client.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!waitForSpace) {
|
||||||
|
if (mIO.mToClient.getFreeSpace() < len) {
|
||||||
|
// Not enough room, and not waiting.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//LOGE("sendMessageToClient 2");
|
||||||
|
void *p = mIO.mToClient.reserve(len);
|
||||||
|
memcpy(p, data, len);
|
||||||
|
mIO.mToClient.commit(cmdID, len);
|
||||||
|
//LOGE("sendMessageToClient 3");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Context::initToClient()
|
||||||
|
{
|
||||||
|
while(!mRunning) {
|
||||||
|
usleep(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Context::deinitToClient()
|
||||||
|
{
|
||||||
|
mIO.mToClient.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -636,3 +695,21 @@ void rsObjDestroyOOB(RsContext vrsc, void *obj)
|
|||||||
rsc->objDestroyAdd(static_cast<ObjectBase *>(obj));
|
rsc->objDestroyAdd(static_cast<ObjectBase *>(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t rsContextGetMessage(RsContext vrsc, void *data, size_t *receiveLen, size_t bufferLen, bool wait)
|
||||||
|
{
|
||||||
|
Context * rsc = static_cast<Context *>(vrsc);
|
||||||
|
return rsc->getMessageToClient(data, receiveLen, bufferLen, wait);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rsContextInitToClient(RsContext vrsc)
|
||||||
|
{
|
||||||
|
Context * rsc = static_cast<Context *>(vrsc);
|
||||||
|
rsc->initToClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
void rsContextDeinitToClient(RsContext vrsc)
|
||||||
|
{
|
||||||
|
Context * rsc = static_cast<Context *>(vrsc);
|
||||||
|
rsc->deinitToClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -97,6 +97,12 @@ public:
|
|||||||
void appendNameDefines(String8 *str) const;
|
void appendNameDefines(String8 *str) const;
|
||||||
void appendVarDefines(String8 *str) const;
|
void appendVarDefines(String8 *str) const;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
void initToClient();
|
||||||
|
void deinitToClient();
|
||||||
|
|
||||||
ProgramFragment * getDefaultProgramFragment() const {
|
ProgramFragment * getDefaultProgramFragment() const {
|
||||||
return mStateFragment.mDefault.get();
|
return mStateFragment.mDefault.get();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,6 +99,9 @@ void * LocklessCommandFifo::reserve(uint32_t sizeInBytes)
|
|||||||
|
|
||||||
void LocklessCommandFifo::commit(uint32_t command, uint32_t sizeInBytes)
|
void LocklessCommandFifo::commit(uint32_t command, uint32_t sizeInBytes)
|
||||||
{
|
{
|
||||||
|
if (mInShutdown) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
//dumpState("commit 1");
|
//dumpState("commit 1");
|
||||||
reinterpret_cast<uint16_t *>(mPut)[0] = command;
|
reinterpret_cast<uint16_t *>(mPut)[0] = command;
|
||||||
reinterpret_cast<uint16_t *>(mPut)[1] = sizeInBytes;
|
reinterpret_cast<uint16_t *>(mPut)[1] = sizeInBytes;
|
||||||
@@ -109,6 +112,9 @@ void LocklessCommandFifo::commit(uint32_t command, uint32_t sizeInBytes)
|
|||||||
|
|
||||||
void LocklessCommandFifo::commitSync(uint32_t command, uint32_t sizeInBytes)
|
void LocklessCommandFifo::commitSync(uint32_t command, uint32_t sizeInBytes)
|
||||||
{
|
{
|
||||||
|
if (mInShutdown) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
commit(command, sizeInBytes);
|
commit(command, sizeInBytes);
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1002,6 +1002,12 @@ static uint32_t SC_colorFloatRGBAto565(float r, float g, float b)
|
|||||||
return rs888to565(ir, ig, ib);
|
return rs888to565(ir, ig, ib);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t SC_toClient(void *data, int cmdID, int len, int waitForSpace)
|
||||||
|
{
|
||||||
|
GET_TLS();
|
||||||
|
return rsc->sendMessageToClient(data, cmdID, len, waitForSpace != 0);
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
// Class implementation
|
// Class implementation
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -1270,6 +1276,8 @@ ScriptCState::SymbolTable_t ScriptCState::gSyms[] = {
|
|||||||
{ "getHeight", (void *)&SC_getHeight,
|
{ "getHeight", (void *)&SC_getHeight,
|
||||||
"int", "()" },
|
"int", "()" },
|
||||||
|
|
||||||
|
{ "sendToClient", (void *)&SC_toClient,
|
||||||
|
"int", "(void *data, int cmdID, int len, int waitForSpace)" },
|
||||||
|
|
||||||
|
|
||||||
{ "debugF", (void *)&SC_debugF,
|
{ "debugF", (void *)&SC_debugF,
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ using namespace android::renderscript;
|
|||||||
ThreadIO::ThreadIO()
|
ThreadIO::ThreadIO()
|
||||||
{
|
{
|
||||||
mToCore.init(16 * 1024);
|
mToCore.init(16 * 1024);
|
||||||
|
mToClient.init(1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadIO::~ThreadIO()
|
ThreadIO::~ThreadIO()
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
LocklessCommandFifo mToCore;
|
LocklessCommandFifo mToCore;
|
||||||
//LocklessCommandFifo mToClient;
|
LocklessCommandFifo mToClient;
|
||||||
|
|
||||||
intptr_t mToCoreRet;
|
intptr_t mToCoreRet;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user