summaryrefslogtreecommitdiff
path: root/libs/rs/rsContext.cpp
diff options
context:
space:
mode:
author Jean-Baptiste Queru <jbq@google.com> 2009-11-15 12:06:20 -0800
committer Jean-Baptiste Queru <jbq@google.com> 2009-11-15 12:06:23 -0800
commit478de466ce0504b9af639c3338b883893670a8e8 (patch)
tree61aba455baf06a4821a65b82d1115929619b49bd /libs/rs/rsContext.cpp
parent2b63ff51d5202eb2b458e937d4b65b326238733e (diff)
parent9db3d07b9620b4269ab33f78604a36327e536ce1 (diff)
merge from eclair
Diffstat (limited to 'libs/rs/rsContext.cpp')
-rw-r--r--libs/rs/rsContext.cpp815
1 files changed, 815 insertions, 0 deletions
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
new file mode 100644
index 000000000000..3e4cc36bc36a
--- /dev/null
+++ b/libs/rs/rsContext.cpp
@@ -0,0 +1,815 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsDevice.h"
+#include "rsContext.h"
+#include "rsThreadIO.h"
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/EGLUtils.h>
+
+#include <cutils/properties.h>
+
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+using namespace android;
+using namespace android::renderscript;
+
+pthread_key_t Context::gThreadTLSKey = 0;
+uint32_t Context::gThreadTLSKeyCount = 0;
+uint32_t Context::gGLContextCount = 0;
+pthread_mutex_t Context::gInitMutex = PTHREAD_MUTEX_INITIALIZER;
+
+static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
+ if (returnVal != EGL_TRUE) {
+ fprintf(stderr, "%s() returned %d\n", op, returnVal);
+ }
+
+ for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
+ = eglGetError()) {
+ fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error),
+ error);
+ }
+}
+
+void Context::initEGL()
+{
+ mEGL.mNumConfigs = -1;
+ EGLint configAttribs[128];
+ EGLint *configAttribsPtr = configAttribs;
+
+ memset(configAttribs, 0, sizeof(configAttribs));
+
+ configAttribsPtr[0] = EGL_SURFACE_TYPE;
+ configAttribsPtr[1] = EGL_WINDOW_BIT;
+ configAttribsPtr += 2;
+
+ if (mUseDepth) {
+ configAttribsPtr[0] = EGL_DEPTH_SIZE;
+ configAttribsPtr[1] = 16;
+ configAttribsPtr += 2;
+ }
+
+ if (mDev->mForceSW) {
+ configAttribsPtr[0] = EGL_CONFIG_CAVEAT;
+ configAttribsPtr[1] = EGL_SLOW_CONFIG;
+ configAttribsPtr += 2;
+ }
+
+ configAttribsPtr[0] = EGL_NONE;
+ rsAssert(configAttribsPtr < (configAttribs + (sizeof(configAttribs) / sizeof(EGLint))));
+
+ LOGV("initEGL start");
+ mEGL.mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ checkEglError("eglGetDisplay");
+
+ eglInitialize(mEGL.mDisplay, &mEGL.mMajorVersion, &mEGL.mMinorVersion);
+ checkEglError("eglInitialize");
+
+ status_t err = EGLUtils::selectConfigForNativeWindow(mEGL.mDisplay, configAttribs, mWndSurface, &mEGL.mConfig);
+ if (err) {
+ LOGE("couldn't find an EGLConfig matching the screen format\n");
+ }
+ //eglChooseConfig(mEGL.mDisplay, configAttribs, &mEGL.mConfig, 1, &mEGL.mNumConfigs);
+
+
+ mEGL.mContext = eglCreateContext(mEGL.mDisplay, mEGL.mConfig, EGL_NO_CONTEXT, NULL);
+ checkEglError("eglCreateContext");
+ if (mEGL.mContext == EGL_NO_CONTEXT) {
+ LOGE("eglCreateContext returned EGL_NO_CONTEXT");
+ }
+ gGLContextCount++;
+
+ if (mWndSurface) {
+ setSurface(mWndSurface);
+ } else {
+ setSurface((Surface *)android_createDisplaySurface());
+ }
+
+ eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_WIDTH, &mEGL.mWidth);
+ eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_HEIGHT, &mEGL.mHeight);
+
+
+ mGL.mVersion = glGetString(GL_VERSION);
+ mGL.mVendor = glGetString(GL_VENDOR);
+ mGL.mRenderer = glGetString(GL_RENDERER);
+ mGL.mExtensions = glGetString(GL_EXTENSIONS);
+
+ LOGV("EGL Version %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion);
+ LOGV("GL Version %s", mGL.mVersion);
+ LOGV("GL Vendor %s", mGL.mVendor);
+ LOGV("GL Renderer %s", mGL.mRenderer);
+ LOGV("GL Extensions %s", mGL.mExtensions);
+
+ if ((strlen((const char *)mGL.mVersion) < 12) || memcmp(mGL.mVersion, "OpenGL ES-CM", 12)) {
+ LOGE("Error, OpenGL ES Lite not supported");
+ } else {
+ sscanf((const char *)mGL.mVersion + 13, "%i.%i", &mGL.mMajorVersion, &mGL.mMinorVersion);
+ }
+}
+
+void Context::deinitEGL()
+{
+ setSurface(NULL);
+ eglDestroyContext(mEGL.mDisplay, mEGL.mContext);
+ checkEglError("eglDestroyContext");
+
+ gGLContextCount--;
+ if (!gGLContextCount) {
+ eglTerminate(mEGL.mDisplay);
+ }
+}
+
+
+bool Context::runScript(Script *s, uint32_t launchID)
+{
+ ObjectBaseRef<ProgramFragment> frag(mFragment);
+ ObjectBaseRef<ProgramVertex> vtx(mVertex);
+ ObjectBaseRef<ProgramFragmentStore> store(mFragmentStore);
+ ObjectBaseRef<ProgramRaster> raster(mRaster);
+
+ bool ret = s->run(this, launchID);
+
+ mFragment.set(frag);
+ mVertex.set(vtx);
+ mFragmentStore.set(store);
+ mRaster.set(raster);
+ return ret;
+}
+
+
+bool Context::runRootScript()
+{
+ if (props.mLogTimes) {
+ timerSet(RS_TIMER_CLEAR_SWAP);
+ }
+ rsAssert(mRootScript->mEnviroment.mIsRoot);
+
+ eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_WIDTH, &mEGL.mWidth);
+ eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_HEIGHT, &mEGL.mHeight);
+ glViewport(0, 0, mEGL.mWidth, mEGL.mHeight);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+
+ glClearColor(mRootScript->mEnviroment.mClearColor[0],
+ mRootScript->mEnviroment.mClearColor[1],
+ mRootScript->mEnviroment.mClearColor[2],
+ mRootScript->mEnviroment.mClearColor[3]);
+ if (mUseDepth) {
+ glDepthMask(GL_TRUE);
+ glClearDepthf(mRootScript->mEnviroment.mClearDepth);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ } else {
+ glClear(GL_COLOR_BUFFER_BIT);
+ }
+
+ if (this->props.mLogTimes) {
+ timerSet(RS_TIMER_SCRIPT);
+ }
+ mStateFragmentStore.mLast.clear();
+ bool ret = runScript(mRootScript.get(), 0);
+
+ GLenum err = glGetError();
+ if (err != GL_NO_ERROR) {
+ LOGE("Pending GL Error, 0x%x", err);
+ }
+
+ return ret;
+}
+
+uint64_t Context::getTime() const
+{
+ struct timespec t;
+ clock_gettime(CLOCK_MONOTONIC, &t);
+ return t.tv_nsec + ((uint64_t)t.tv_sec * 1000 * 1000 * 1000);
+}
+
+void Context::timerReset()
+{
+ for (int ct=0; ct < _RS_TIMER_TOTAL; ct++) {
+ mTimers[ct] = 0;
+ }
+}
+
+void Context::timerInit()
+{
+ mTimeLast = getTime();
+ mTimeFrame = mTimeLast;
+ mTimeLastFrame = mTimeLast;
+ mTimerActive = RS_TIMER_INTERNAL;
+ timerReset();
+}
+
+void Context::timerFrame()
+{
+ mTimeLastFrame = mTimeFrame;
+ mTimeFrame = getTime();
+}
+
+void Context::timerSet(Timers tm)
+{
+ uint64_t last = mTimeLast;
+ mTimeLast = getTime();
+ mTimers[mTimerActive] += mTimeLast - last;
+ mTimerActive = tm;
+}
+
+void Context::timerPrint()
+{
+ double total = 0;
+ for (int ct = 0; ct < _RS_TIMER_TOTAL; ct++) {
+ total += mTimers[ct];
+ }
+ uint64_t frame = mTimeFrame - mTimeLastFrame;
+
+ LOGV("RS: Frame (%lli), Script %2.1f (%lli), Clear & Swap %2.1f (%lli), Idle %2.1f (%lli), Internal %2.1f (%lli)",
+ frame / 1000000,
+ 100.0 * mTimers[RS_TIMER_SCRIPT] / total, mTimers[RS_TIMER_SCRIPT] / 1000000,
+ 100.0 * mTimers[RS_TIMER_CLEAR_SWAP] / total, mTimers[RS_TIMER_CLEAR_SWAP] / 1000000,
+ 100.0 * mTimers[RS_TIMER_IDLE] / total, mTimers[RS_TIMER_IDLE] / 1000000,
+ 100.0 * mTimers[RS_TIMER_INTERNAL] / total, mTimers[RS_TIMER_INTERNAL] / 1000000);
+}
+
+void Context::setupCheck()
+{
+ mFragmentStore->setupGL(this, &mStateFragmentStore);
+ mFragment->setupGL(this, &mStateFragment);
+ mRaster->setupGL(this, &mStateRaster);
+ mVertex->setupGL(this, &mStateVertex);
+}
+
+static bool getProp(const char *str)
+{
+ char buf[PROPERTY_VALUE_MAX];
+ property_get(str, buf, "0");
+ return 0 != strcmp(buf, "0");
+}
+
+void * Context::threadProc(void *vrsc)
+{
+ Context *rsc = static_cast<Context *>(vrsc);
+
+ rsc->props.mLogTimes = getProp("debug.rs.profile");
+ rsc->props.mLogScripts = getProp("debug.rs.script");
+ rsc->props.mLogObjects = getProp("debug.rs.objects");
+
+ pthread_mutex_lock(&gInitMutex);
+ rsc->initEGL();
+ pthread_mutex_unlock(&gInitMutex);
+
+ ScriptTLSStruct *tlsStruct = new ScriptTLSStruct;
+ if (!tlsStruct) {
+ LOGE("Error allocating tls storage");
+ return NULL;
+ }
+ tlsStruct->mContext = rsc;
+ tlsStruct->mScript = NULL;
+ int status = pthread_setspecific(rsc->gThreadTLSKey, tlsStruct);
+ if (status) {
+ LOGE("pthread_setspecific %i", status);
+ }
+
+ rsc->mStateRaster.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight);
+ rsc->setRaster(NULL);
+ rsc->mStateVertex.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight);
+ rsc->setVertex(NULL);
+ rsc->mStateFragment.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight);
+ rsc->setFragment(NULL);
+ rsc->mStateFragmentStore.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight);
+ rsc->setFragmentStore(NULL);
+
+ rsc->mRunning = true;
+ bool mDraw = true;
+ while (!rsc->mExit) {
+ mDraw |= rsc->mIO.playCoreCommands(rsc, !mDraw);
+ mDraw &= (rsc->mRootScript.get() != NULL);
+ mDraw &= (rsc->mWndSurface != NULL);
+
+ if (mDraw) {
+ mDraw = rsc->runRootScript() && !rsc->mPaused;
+ if (rsc->props.mLogTimes) {
+ rsc->timerSet(RS_TIMER_CLEAR_SWAP);
+ }
+ eglSwapBuffers(rsc->mEGL.mDisplay, rsc->mEGL.mSurface);
+ if (rsc->props.mLogTimes) {
+ rsc->timerFrame();
+ rsc->timerSet(RS_TIMER_INTERNAL);
+ rsc->timerPrint();
+ rsc->timerReset();
+ }
+ }
+ if (rsc->mObjDestroy.mNeedToEmpty) {
+ rsc->objDestroyOOBRun();
+ }
+ }
+
+ LOGV("RS Thread exiting");
+ rsc->mRaster.clear();
+ rsc->mFragment.clear();
+ rsc->mVertex.clear();
+ rsc->mFragmentStore.clear();
+ rsc->mRootScript.clear();
+ rsc->mStateRaster.deinit(rsc);
+ rsc->mStateVertex.deinit(rsc);
+ rsc->mStateFragment.deinit(rsc);
+ rsc->mStateFragmentStore.deinit(rsc);
+ ObjectBase::zeroAllUserRef(rsc);
+
+ rsc->mObjDestroy.mNeedToEmpty = true;
+ rsc->objDestroyOOBRun();
+
+ glClearColor(0,0,0,0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ eglSwapBuffers(rsc->mEGL.mDisplay, rsc->mEGL.mSurface);
+
+ pthread_mutex_lock(&gInitMutex);
+ rsc->deinitEGL();
+ pthread_mutex_unlock(&gInitMutex);
+
+ LOGV("RS Thread exited");
+ return NULL;
+}
+
+Context::Context(Device *dev, Surface *sur, bool useDepth)
+{
+ pthread_mutex_lock(&gInitMutex);
+
+ dev->addContext(this);
+ mDev = dev;
+ mRunning = false;
+ mExit = false;
+ mUseDepth = useDepth;
+ mPaused = false;
+ mObjHead = NULL;
+
+ int status;
+ pthread_attr_t threadAttr;
+
+ if (!gThreadTLSKeyCount) {
+ status = pthread_key_create(&gThreadTLSKey, NULL);
+ if (status) {
+ LOGE("Failed to init thread tls key.");
+ pthread_mutex_unlock(&gInitMutex);
+ return;
+ }
+ }
+ gThreadTLSKeyCount++;
+ pthread_mutex_unlock(&gInitMutex);
+
+ // Global init done at this point.
+
+ status = pthread_attr_init(&threadAttr);
+ if (status) {
+ LOGE("Failed to init thread attribute.");
+ return;
+ }
+
+ sched_param sparam;
+ sparam.sched_priority = ANDROID_PRIORITY_DISPLAY;
+ pthread_attr_setschedparam(&threadAttr, &sparam);
+
+ mWndSurface = sur;
+
+ objDestroyOOBInit();
+ timerInit();
+ timerSet(RS_TIMER_INTERNAL);
+
+ LOGV("RS Launching thread");
+ status = pthread_create(&mThreadId, &threadAttr, threadProc, this);
+ if (status) {
+ LOGE("Failed to start rs context thread.");
+ }
+
+ while(!mRunning) {
+ usleep(100);
+ }
+
+ pthread_attr_destroy(&threadAttr);
+}
+
+Context::~Context()
+{
+ LOGV("Context::~Context");
+ mExit = true;
+ mPaused = false;
+ void *res;
+
+ mIO.shutdown();
+ int status = pthread_join(mThreadId, &res);
+ mObjDestroy.mNeedToEmpty = true;
+ objDestroyOOBRun();
+
+ // Global structure cleanup.
+ pthread_mutex_lock(&gInitMutex);
+ if (mDev) {
+ mDev->removeContext(this);
+ --gThreadTLSKeyCount;
+ if (!gThreadTLSKeyCount) {
+ pthread_key_delete(gThreadTLSKey);
+ }
+ mDev = NULL;
+ }
+ pthread_mutex_unlock(&gInitMutex);
+
+ objDestroyOOBDestroy();
+}
+
+void Context::setSurface(Surface *sur)
+{
+ EGLBoolean ret;
+ if (mEGL.mSurface != NULL) {
+ ret = eglMakeCurrent(mEGL.mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ checkEglError("eglMakeCurrent", ret);
+
+ ret = eglDestroySurface(mEGL.mDisplay, mEGL.mSurface);
+ checkEglError("eglDestroySurface", ret);
+
+ mEGL.mSurface = NULL;
+ }
+
+ mWndSurface = sur;
+ if (mWndSurface != NULL) {
+ mEGL.mSurface = eglCreateWindowSurface(mEGL.mDisplay, mEGL.mConfig, mWndSurface, NULL);
+ checkEglError("eglCreateWindowSurface");
+ if (mEGL.mSurface == EGL_NO_SURFACE) {
+ LOGE("eglCreateWindowSurface returned EGL_NO_SURFACE");
+ }
+
+ ret = eglMakeCurrent(mEGL.mDisplay, mEGL.mSurface, mEGL.mSurface, mEGL.mContext);
+ checkEglError("eglMakeCurrent", ret);
+ }
+}
+
+void Context::pause()
+{
+ mPaused = true;
+}
+
+void Context::resume()
+{
+ mPaused = false;
+}
+
+void Context::setRootScript(Script *s)
+{
+ mRootScript.set(s);
+}
+
+void Context::setFragmentStore(ProgramFragmentStore *pfs)
+{
+ if (pfs == NULL) {
+ mFragmentStore.set(mStateFragmentStore.mDefault);
+ } else {
+ mFragmentStore.set(pfs);
+ }
+}
+
+void Context::setFragment(ProgramFragment *pf)
+{
+ if (pf == NULL) {
+ mFragment.set(mStateFragment.mDefault);
+ } else {
+ mFragment.set(pf);
+ }
+}
+
+void Context::setRaster(ProgramRaster *pr)
+{
+ if (pr == NULL) {
+ mRaster.set(mStateRaster.mDefault);
+ } else {
+ mRaster.set(pr);
+ }
+}
+
+void Context::allocationCheck(const Allocation *a)
+{
+ mVertex->checkUpdatedAllocation(a);
+ mFragment->checkUpdatedAllocation(a);
+ mFragmentStore->checkUpdatedAllocation(a);
+}
+
+void Context::setVertex(ProgramVertex *pv)
+{
+ if (pv == NULL) {
+ mVertex.set(mStateVertex.mDefault);
+ } else {
+ mVertex.set(pv);
+ }
+ mVertex->forceDirty();
+}
+
+void Context::assignName(ObjectBase *obj, const char *name, uint32_t len)
+{
+ rsAssert(!obj->getName());
+ obj->setName(name, len);
+ mNames.add(obj);
+}
+
+void Context::removeName(ObjectBase *obj)
+{
+ for(size_t ct=0; ct < mNames.size(); ct++) {
+ if (obj == mNames[ct]) {
+ mNames.removeAt(ct);
+ return;
+ }
+ }
+}
+
+ObjectBase * Context::lookupName(const char *name) const
+{
+ for(size_t ct=0; ct < mNames.size(); ct++) {
+ if (!strcmp(name, mNames[ct]->getName())) {
+ return mNames[ct];
+ }
+ }
+ return NULL;
+}
+
+void Context::appendNameDefines(String8 *str) const
+{
+ char buf[256];
+ for (size_t ct=0; ct < mNames.size(); ct++) {
+ str->append("#define NAMED_");
+ str->append(mNames[ct]->getName());
+ str->append(" ");
+ sprintf(buf, "%i\n", (int)mNames[ct]);
+ str->append(buf);
+ }
+}
+
+void Context::appendVarDefines(String8 *str) const
+{
+ char buf[256];
+ for (size_t ct=0; ct < mInt32Defines.size(); ct++) {
+ str->append("#define ");
+ str->append(mInt32Defines.keyAt(ct));
+ str->append(" ");
+ sprintf(buf, "%i\n", (int)mInt32Defines.valueAt(ct));
+ str->append(buf);
+
+ }
+ for (size_t ct=0; ct < mFloatDefines.size(); ct++) {
+ str->append("#define ");
+ str->append(mFloatDefines.keyAt(ct));
+ str->append(" ");
+ sprintf(buf, "%ff\n", mFloatDefines.valueAt(ct));
+ str->append(buf);
+ }
+}
+
+bool Context::objDestroyOOBInit()
+{
+ int status = pthread_mutex_init(&mObjDestroy.mMutex, NULL);
+ if (status) {
+ LOGE("Context::ObjDestroyOOBInit mutex init failure");
+ return false;
+ }
+ return true;
+}
+
+void Context::objDestroyOOBRun()
+{
+ if (mObjDestroy.mNeedToEmpty) {
+ int status = pthread_mutex_lock(&mObjDestroy.mMutex);
+ if (status) {
+ LOGE("Context::ObjDestroyOOBRun: error %i locking for OOBRun.", status);
+ return;
+ }
+
+ for (size_t ct = 0; ct < mObjDestroy.mDestroyList.size(); ct++) {
+ mObjDestroy.mDestroyList[ct]->decUserRef();
+ }
+ mObjDestroy.mDestroyList.clear();
+ mObjDestroy.mNeedToEmpty = false;
+
+ status = pthread_mutex_unlock(&mObjDestroy.mMutex);
+ if (status) {
+ LOGE("Context::ObjDestroyOOBRun: error %i unlocking for set condition.", status);
+ }
+ }
+}
+
+void Context::objDestroyOOBDestroy()
+{
+ rsAssert(!mObjDestroy.mNeedToEmpty);
+ pthread_mutex_destroy(&mObjDestroy.mMutex);
+}
+
+void Context::objDestroyAdd(ObjectBase *obj)
+{
+ int status = pthread_mutex_lock(&mObjDestroy.mMutex);
+ if (status) {
+ LOGE("Context::ObjDestroyOOBRun: error %i locking for OOBRun.", status);
+ return;
+ }
+
+ mObjDestroy.mNeedToEmpty = true;
+ mObjDestroy.mDestroyList.add(obj);
+
+ status = pthread_mutex_unlock(&mObjDestroy.mMutex);
+ if (status) {
+ LOGE("Context::ObjDestroyOOBRun: error %i unlocking for set condition.", status);
+ }
+}
+
+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();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+//
+
+namespace android {
+namespace renderscript {
+
+
+void rsi_ContextBindRootScript(Context *rsc, RsScript vs)
+{
+ Script *s = static_cast<Script *>(vs);
+ rsc->setRootScript(s);
+}
+
+void rsi_ContextBindSampler(Context *rsc, uint32_t slot, RsSampler vs)
+{
+ Sampler *s = static_cast<Sampler *>(vs);
+
+ if (slot > RS_MAX_SAMPLER_SLOT) {
+ LOGE("Invalid sampler slot");
+ return;
+ }
+
+ s->bindToContext(&rsc->mStateSampler, slot);
+}
+
+void rsi_ContextBindProgramFragmentStore(Context *rsc, RsProgramFragmentStore vpfs)
+{
+ ProgramFragmentStore *pfs = static_cast<ProgramFragmentStore *>(vpfs);
+ rsc->setFragmentStore(pfs);
+}
+
+void rsi_ContextBindProgramFragment(Context *rsc, RsProgramFragment vpf)
+{
+ ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
+ rsc->setFragment(pf);
+}
+
+void rsi_ContextBindProgramRaster(Context *rsc, RsProgramRaster vpr)
+{
+ ProgramRaster *pr = static_cast<ProgramRaster *>(vpr);
+ rsc->setRaster(pr);
+}
+
+void rsi_ContextBindProgramVertex(Context *rsc, RsProgramVertex vpv)
+{
+ ProgramVertex *pv = static_cast<ProgramVertex *>(vpv);
+ rsc->setVertex(pv);
+}
+
+void rsi_AssignName(Context *rsc, void * obj, const char *name, uint32_t len)
+{
+ ObjectBase *ob = static_cast<ObjectBase *>(obj);
+ rsc->assignName(ob, name, len);
+}
+
+void rsi_ObjDestroy(Context *rsc, void *obj)
+{
+ ObjectBase *ob = static_cast<ObjectBase *>(obj);
+ rsc->removeName(ob);
+ ob->decUserRef();
+}
+
+void rsi_ContextSetDefineF(Context *rsc, const char* name, float value)
+{
+ rsc->addInt32Define(name, value);
+}
+
+void rsi_ContextSetDefineI32(Context *rsc, const char* name, int32_t value)
+{
+ rsc->addFloatDefine(name, value);
+}
+
+void rsi_ContextPause(Context *rsc)
+{
+ rsc->pause();
+}
+
+void rsi_ContextResume(Context *rsc)
+{
+ rsc->resume();
+}
+
+void rsi_ContextSetSurface(Context *rsc, void *sur)
+{
+ rsc->setSurface((Surface *)sur);
+}
+
+}
+}
+
+
+RsContext rsContextCreate(RsDevice vdev, void *sur, uint32_t version, bool useDepth)
+{
+ Device * dev = static_cast<Device *>(vdev);
+ Context *rsc = new Context(dev, (Surface *)sur, useDepth);
+ return rsc;
+}
+
+void rsContextDestroy(RsContext vrsc)
+{
+ Context * rsc = static_cast<Context *>(vrsc);
+ delete rsc;
+}
+
+void rsObjDestroyOOB(RsContext vrsc, void *obj)
+{
+ Context * rsc = static_cast<Context *>(vrsc);
+ 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();
+}
+