Fix bug in StoreState where state could be overridden by the default unless the script used more than one state. Change only impacts renderscript and renderscript apps.
716 lines
18 KiB
C++
716 lines
18 KiB
C++
/*
|
|
* 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;
|
|
|
|
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))));
|
|
|
|
mEGL.mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
|
eglInitialize(mEGL.mDisplay, &mEGL.mMajorVersion, &mEGL.mMinorVersion);
|
|
|
|
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);
|
|
|
|
if (mWndSurface) {
|
|
mEGL.mSurface = eglCreateWindowSurface(mEGL.mDisplay, mEGL.mConfig, mWndSurface, NULL);
|
|
} else {
|
|
mEGL.mSurface = eglCreateWindowSurface(mEGL.mDisplay, mEGL.mConfig,
|
|
android_createDisplaySurface(),
|
|
NULL);
|
|
}
|
|
|
|
mEGL.mContext = eglCreateContext(mEGL.mDisplay, mEGL.mConfig, NULL, NULL);
|
|
eglMakeCurrent(mEGL.mDisplay, mEGL.mSurface, mEGL.mSurface, mEGL.mContext);
|
|
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);
|
|
}
|
|
}
|
|
|
|
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);
|
|
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");
|
|
|
|
rsc->initEGL();
|
|
|
|
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);
|
|
|
|
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);
|
|
|
|
glClearColor(0,0,0,0);
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
eglSwapBuffers(rsc->mEGL.mDisplay, rsc->mEGL.mSurface);
|
|
eglTerminate(rsc->mEGL.mDisplay);
|
|
rsc->objDestroyOOBRun();
|
|
LOGV("RS Thread exited");
|
|
return NULL;
|
|
}
|
|
|
|
Context::Context(Device *dev, Surface *sur, bool useDepth)
|
|
{
|
|
dev->addContext(this);
|
|
mDev = dev;
|
|
mRunning = false;
|
|
mExit = false;
|
|
mUseDepth = useDepth;
|
|
mPaused = false;
|
|
mObjHead = NULL;
|
|
|
|
int status;
|
|
pthread_attr_t threadAttr;
|
|
|
|
status = pthread_key_create(&gThreadTLSKey, NULL);
|
|
if (status) {
|
|
LOGE("Failed to init thread tls key.");
|
|
return;
|
|
}
|
|
|
|
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);
|
|
objDestroyOOBRun();
|
|
|
|
if (mDev) {
|
|
mDev->removeContext(this);
|
|
pthread_key_delete(gThreadTLSKey);
|
|
}
|
|
|
|
objDestroyOOBDestroy();
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
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();
|
|
}
|
|
|