Home | History | Annotate | Download | only in rs
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "rs.h"
     18 #include "rsDevice.h"
     19 #include "rsContext.h"
     20 #include "rsThreadIO.h"
     21 #include "rsMesh.h"
     22 #include <ui/FramebufferNativeWindow.h>
     23 #include <gui/DisplayEventReceiver.h>
     24 
     25 #include <sys/types.h>
     26 #include <sys/resource.h>
     27 #include <sched.h>
     28 
     29 #include <cutils/properties.h>
     30 
     31 #include <sys/syscall.h>
     32 #include <string.h>
     33 
     34 using namespace android;
     35 using namespace android::renderscript;
     36 
     37 pthread_mutex_t Context::gInitMutex = PTHREAD_MUTEX_INITIALIZER;
     38 pthread_mutex_t Context::gLibMutex = PTHREAD_MUTEX_INITIALIZER;
     39 
     40 bool Context::initGLThread() {
     41     pthread_mutex_lock(&gInitMutex);
     42 
     43     if (!mHal.funcs.initGraphics(this)) {
     44         pthread_mutex_unlock(&gInitMutex);
     45         ALOGE("%p initGraphics failed", this);
     46         return false;
     47     }
     48 
     49     pthread_mutex_unlock(&gInitMutex);
     50     return true;
     51 }
     52 
     53 void Context::deinitEGL() {
     54     mHal.funcs.shutdownGraphics(this);
     55 }
     56 
     57 Context::PushState::PushState(Context *con) {
     58     mRsc = con;
     59     if (con->mIsGraphicsContext) {
     60         mFragment.set(con->getProgramFragment());
     61         mVertex.set(con->getProgramVertex());
     62         mStore.set(con->getProgramStore());
     63         mRaster.set(con->getProgramRaster());
     64         mFont.set(con->getFont());
     65     }
     66 }
     67 
     68 Context::PushState::~PushState() {
     69     if (mRsc->mIsGraphicsContext) {
     70         mRsc->setProgramFragment(mFragment.get());
     71         mRsc->setProgramVertex(mVertex.get());
     72         mRsc->setProgramStore(mStore.get());
     73         mRsc->setProgramRaster(mRaster.get());
     74         mRsc->setFont(mFont.get());
     75     }
     76 }
     77 
     78 
     79 uint32_t Context::runScript(Script *s) {
     80     PushState(this);
     81 
     82     uint32_t ret = s->run(this);
     83     return ret;
     84 }
     85 
     86 uint32_t Context::runRootScript() {
     87     timerSet(RS_TIMER_SCRIPT);
     88     mStateFragmentStore.mLast.clear();
     89     watchdog.inRoot = true;
     90     uint32_t ret = runScript(mRootScript.get());
     91     watchdog.inRoot = false;
     92 
     93     return ret;
     94 }
     95 
     96 uint64_t Context::getTime() const {
     97 #ifndef ANDROID_RS_SERIALIZE
     98     struct timespec t;
     99     clock_gettime(CLOCK_MONOTONIC, &t);
    100     return t.tv_nsec + ((uint64_t)t.tv_sec * 1000 * 1000 * 1000);
    101 #else
    102     return 0;
    103 #endif //ANDROID_RS_SERIALIZE
    104 }
    105 
    106 void Context::timerReset() {
    107     for (int ct=0; ct < _RS_TIMER_TOTAL; ct++) {
    108         mTimers[ct] = 0;
    109     }
    110 }
    111 
    112 void Context::timerInit() {
    113     mTimeLast = getTime();
    114     mTimeFrame = mTimeLast;
    115     mTimeLastFrame = mTimeLast;
    116     mTimerActive = RS_TIMER_INTERNAL;
    117     mAverageFPSFrameCount = 0;
    118     mAverageFPSStartTime = mTimeLast;
    119     mAverageFPS = 0;
    120     timerReset();
    121 }
    122 
    123 void Context::timerFrame() {
    124     mTimeLastFrame = mTimeFrame;
    125     mTimeFrame = getTime();
    126     // Update average fps
    127     const uint64_t averageFramerateInterval = 1000 * 1000000;
    128     mAverageFPSFrameCount ++;
    129     uint64_t inverval = mTimeFrame - mAverageFPSStartTime;
    130     if (inverval >= averageFramerateInterval) {
    131         inverval = inverval / 1000000;
    132         mAverageFPS = (mAverageFPSFrameCount * 1000) / inverval;
    133         mAverageFPSFrameCount = 0;
    134         mAverageFPSStartTime = mTimeFrame;
    135     }
    136 }
    137 
    138 void Context::timerSet(Timers tm) {
    139     uint64_t last = mTimeLast;
    140     mTimeLast = getTime();
    141     mTimers[mTimerActive] += mTimeLast - last;
    142     mTimerActive = tm;
    143 }
    144 
    145 void Context::timerPrint() {
    146     double total = 0;
    147     for (int ct = 0; ct < _RS_TIMER_TOTAL; ct++) {
    148         total += mTimers[ct];
    149     }
    150     uint64_t frame = mTimeFrame - mTimeLastFrame;
    151     mTimeMSLastFrame = frame / 1000000;
    152     mTimeMSLastScript = mTimers[RS_TIMER_SCRIPT] / 1000000;
    153     mTimeMSLastSwap = mTimers[RS_TIMER_CLEAR_SWAP] / 1000000;
    154 
    155 
    156     if (props.mLogTimes) {
    157         ALOGV("RS: Frame (%i),   Script %2.1f%% (%i),  Swap %2.1f%% (%i),  Idle %2.1f%% (%lli),  Internal %2.1f%% (%lli), Avg fps: %u",
    158              mTimeMSLastFrame,
    159              100.0 * mTimers[RS_TIMER_SCRIPT] / total, mTimeMSLastScript,
    160              100.0 * mTimers[RS_TIMER_CLEAR_SWAP] / total, mTimeMSLastSwap,
    161              100.0 * mTimers[RS_TIMER_IDLE] / total, mTimers[RS_TIMER_IDLE] / 1000000,
    162              100.0 * mTimers[RS_TIMER_INTERNAL] / total, mTimers[RS_TIMER_INTERNAL] / 1000000,
    163              mAverageFPS);
    164     }
    165 }
    166 
    167 bool Context::setupCheck() {
    168 
    169     mFragmentStore->setup(this, &mStateFragmentStore);
    170     mFragment->setup(this, &mStateFragment);
    171     mRaster->setup(this, &mStateRaster);
    172     mVertex->setup(this, &mStateVertex);
    173     mFBOCache.setup(this);
    174     return true;
    175 }
    176 
    177 void Context::setupProgramStore() {
    178     mFragmentStore->setup(this, &mStateFragmentStore);
    179 }
    180 
    181 static uint32_t getProp(const char *str) {
    182     char buf[PROPERTY_VALUE_MAX];
    183     property_get(str, buf, "0");
    184     return atoi(buf);
    185 }
    186 
    187 void Context::displayDebugStats() {
    188     char buffer[128];
    189     sprintf(buffer, "Avg fps %u, Frame %i ms, Script %i ms", mAverageFPS, mTimeMSLastFrame, mTimeMSLastScript);
    190     float oldR, oldG, oldB, oldA;
    191     mStateFont.getFontColor(&oldR, &oldG, &oldB, &oldA);
    192     uint32_t bufferLen = strlen(buffer);
    193 
    194     ObjectBaseRef<Font> lastFont(getFont());
    195     setFont(NULL);
    196     float shadowCol = 0.1f;
    197     mStateFont.setFontColor(shadowCol, shadowCol, shadowCol, 1.0f);
    198     mStateFont.renderText(buffer, bufferLen, 5, getHeight() - 6);
    199 
    200     mStateFont.setFontColor(1.0f, 0.7f, 0.0f, 1.0f);
    201     mStateFont.renderText(buffer, bufferLen, 4, getHeight() - 7);
    202 
    203     setFont(lastFont.get());
    204     mStateFont.setFontColor(oldR, oldG, oldB, oldA);
    205 }
    206 
    207 void * Context::threadProc(void *vrsc) {
    208     Context *rsc = static_cast<Context *>(vrsc);
    209 #ifndef ANDROID_RS_SERIALIZE
    210     rsc->mNativeThreadId = gettid();
    211     setpriority(PRIO_PROCESS, rsc->mNativeThreadId, ANDROID_PRIORITY_DISPLAY);
    212     rsc->mThreadPriority = ANDROID_PRIORITY_DISPLAY;
    213 #endif //ANDROID_RS_SERIALIZE
    214     rsc->props.mLogTimes = getProp("debug.rs.profile") != 0;
    215     rsc->props.mLogScripts = getProp("debug.rs.script") != 0;
    216     rsc->props.mLogObjects = getProp("debug.rs.object") != 0;
    217     rsc->props.mLogShaders = getProp("debug.rs.shader") != 0;
    218     rsc->props.mLogShadersAttr = getProp("debug.rs.shader.attributes") != 0;
    219     rsc->props.mLogShadersUniforms = getProp("debug.rs.shader.uniforms") != 0;
    220     rsc->props.mLogVisual = getProp("debug.rs.visual") != 0;
    221     rsc->props.mDebugMaxThreads = getProp("debug.rs.max-threads");
    222 
    223     if (!rsdHalInit(rsc, 0, 0)) {
    224         rsc->setError(RS_ERROR_FATAL_DRIVER, "Failed initializing GL");
    225         ALOGE("Hal init failed");
    226         return NULL;
    227     }
    228     rsc->mHal.funcs.setPriority(rsc, rsc->mThreadPriority);
    229 
    230     if (rsc->mIsGraphicsContext) {
    231         if (!rsc->initGLThread()) {
    232             rsc->setError(RS_ERROR_OUT_OF_MEMORY, "Failed initializing GL");
    233             return NULL;
    234         }
    235 
    236         rsc->mStateRaster.init(rsc);
    237         rsc->setProgramRaster(NULL);
    238         rsc->mStateVertex.init(rsc);
    239         rsc->setProgramVertex(NULL);
    240         rsc->mStateFragment.init(rsc);
    241         rsc->setProgramFragment(NULL);
    242         rsc->mStateFragmentStore.init(rsc);
    243         rsc->setProgramStore(NULL);
    244         rsc->mStateFont.init(rsc);
    245         rsc->setFont(NULL);
    246         rsc->mStateSampler.init(rsc);
    247         rsc->mFBOCache.init(rsc);
    248     }
    249 
    250     rsc->mRunning = true;
    251     if (!rsc->mIsGraphicsContext) {
    252         while (!rsc->mExit) {
    253             rsc->mIO.playCoreCommands(rsc, -1);
    254         }
    255     } else {
    256 #ifndef ANDROID_RS_SERIALIZE
    257         DisplayEventReceiver displayEvent;
    258         DisplayEventReceiver::Event eventBuffer[1];
    259 #endif
    260         int vsyncRate = 0;
    261         int targetRate = 0;
    262 
    263         bool drawOnce = false;
    264         while (!rsc->mExit) {
    265             rsc->timerSet(RS_TIMER_IDLE);
    266 
    267 #ifndef ANDROID_RS_SERIALIZE
    268             if (!rsc->mRootScript.get() || !rsc->mHasSurface || rsc->mPaused) {
    269                 targetRate = 0;
    270             }
    271 
    272             if (vsyncRate != targetRate) {
    273                 displayEvent.setVsyncRate(targetRate);
    274                 vsyncRate = targetRate;
    275             }
    276             if (targetRate) {
    277                 drawOnce |= rsc->mIO.playCoreCommands(rsc, displayEvent.getFd());
    278                 while (displayEvent.getEvents(eventBuffer, 1) != 0) {
    279                     //ALOGE("vs2 time past %lld", (rsc->getTime() - eventBuffer[0].header.timestamp) / 1000000);
    280                 }
    281             } else
    282 #endif
    283             {
    284                 drawOnce |= rsc->mIO.playCoreCommands(rsc, -1);
    285             }
    286 
    287             if ((rsc->mRootScript.get() != NULL) && rsc->mHasSurface &&
    288                 (targetRate || drawOnce) && !rsc->mPaused) {
    289 
    290                 drawOnce = false;
    291                 targetRate = ((rsc->runRootScript() + 15) / 16);
    292 
    293                 if (rsc->props.mLogVisual) {
    294                     rsc->displayDebugStats();
    295                 }
    296 
    297                 rsc->timerSet(RS_TIMER_CLEAR_SWAP);
    298                 rsc->mHal.funcs.swap(rsc);
    299                 rsc->timerFrame();
    300                 rsc->timerSet(RS_TIMER_INTERNAL);
    301                 rsc->timerPrint();
    302                 rsc->timerReset();
    303             }
    304         }
    305     }
    306 
    307     ALOGV("%p RS Thread exiting", rsc);
    308 
    309     if (rsc->mIsGraphicsContext) {
    310         pthread_mutex_lock(&gInitMutex);
    311         rsc->deinitEGL();
    312         pthread_mutex_unlock(&gInitMutex);
    313     }
    314 
    315     ALOGV("%p RS Thread exited", rsc);
    316     return NULL;
    317 }
    318 
    319 void Context::destroyWorkerThreadResources() {
    320     //ALOGV("destroyWorkerThreadResources 1");
    321     ObjectBase::zeroAllUserRef(this);
    322     if (mIsGraphicsContext) {
    323          mRaster.clear();
    324          mFragment.clear();
    325          mVertex.clear();
    326          mFragmentStore.clear();
    327          mFont.clear();
    328          mRootScript.clear();
    329          mStateRaster.deinit(this);
    330          mStateVertex.deinit(this);
    331          mStateFragment.deinit(this);
    332          mStateFragmentStore.deinit(this);
    333          mStateFont.deinit(this);
    334          mStateSampler.deinit(this);
    335          mFBOCache.deinit(this);
    336     }
    337     ObjectBase::freeAllChildren(this);
    338     mExit = true;
    339     //ALOGV("destroyWorkerThreadResources 2");
    340 }
    341 
    342 void Context::printWatchdogInfo(void *ctx) {
    343     Context *rsc = (Context *)ctx;
    344     if (rsc->watchdog.command && rsc->watchdog.file) {
    345         ALOGE("RS watchdog timeout: %i  %s  line %i %s", rsc->watchdog.inRoot,
    346              rsc->watchdog.command, rsc->watchdog.line, rsc->watchdog.file);
    347     } else {
    348         ALOGE("RS watchdog timeout: %i", rsc->watchdog.inRoot);
    349     }
    350 }
    351 
    352 
    353 void Context::setPriority(int32_t p) {
    354     // Note: If we put this in the proper "background" policy
    355     // the wallpapers can become completly unresponsive at times.
    356     // This is probably not what we want for something the user is actively
    357     // looking at.
    358     mThreadPriority = p;
    359     setpriority(PRIO_PROCESS, mNativeThreadId, p);
    360     mHal.funcs.setPriority(this, mThreadPriority);
    361 }
    362 
    363 Context::Context() {
    364     mDev = NULL;
    365     mRunning = false;
    366     mExit = false;
    367     mPaused = false;
    368     mObjHead = NULL;
    369     mError = RS_ERROR_NONE;
    370     mTargetSdkVersion = 14;
    371     mDPI = 96;
    372     mIsContextLite = false;
    373     memset(&watchdog, 0, sizeof(watchdog));
    374 }
    375 
    376 Context * Context::createContext(Device *dev, const RsSurfaceConfig *sc) {
    377     Context * rsc = new Context();
    378 
    379     if (!rsc->initContext(dev, sc)) {
    380         delete rsc;
    381         return NULL;
    382     }
    383     return rsc;
    384 }
    385 
    386 Context * Context::createContextLite() {
    387     Context * rsc = new Context();
    388     rsc->mIsContextLite = true;
    389     return rsc;
    390 }
    391 
    392 bool Context::initContext(Device *dev, const RsSurfaceConfig *sc) {
    393     pthread_mutex_lock(&gInitMutex);
    394 
    395     mIO.init();
    396     mIO.setTimeoutCallback(printWatchdogInfo, this, 2e9);
    397 
    398     dev->addContext(this);
    399     mDev = dev;
    400     if (sc) {
    401         mUserSurfaceConfig = *sc;
    402     } else {
    403         memset(&mUserSurfaceConfig, 0, sizeof(mUserSurfaceConfig));
    404     }
    405 
    406     mIsGraphicsContext = sc != NULL;
    407 
    408     int status;
    409     pthread_attr_t threadAttr;
    410 
    411     pthread_mutex_unlock(&gInitMutex);
    412 
    413     // Global init done at this point.
    414 
    415     status = pthread_attr_init(&threadAttr);
    416     if (status) {
    417         ALOGE("Failed to init thread attribute.");
    418         return false;
    419     }
    420 
    421     mHasSurface = false;
    422 
    423     timerInit();
    424     timerSet(RS_TIMER_INTERNAL);
    425 
    426     status = pthread_create(&mThreadId, &threadAttr, threadProc, this);
    427     if (status) {
    428         ALOGE("Failed to start rs context thread.");
    429         return false;
    430     }
    431     while (!mRunning && (mError == RS_ERROR_NONE)) {
    432         usleep(100);
    433     }
    434 
    435     if (mError != RS_ERROR_NONE) {
    436         ALOGE("Errors during thread init");
    437         return false;
    438     }
    439 
    440     pthread_attr_destroy(&threadAttr);
    441     return true;
    442 }
    443 
    444 Context::~Context() {
    445     ALOGV("%p Context::~Context", this);
    446 
    447     if (!mIsContextLite) {
    448         mPaused = false;
    449         void *res;
    450 
    451         mIO.shutdown();
    452         int status = pthread_join(mThreadId, &res);
    453         rsAssert(mExit);
    454 
    455         if (mHal.funcs.shutdownDriver) {
    456             mHal.funcs.shutdownDriver(this);
    457         }
    458 
    459         // Global structure cleanup.
    460         pthread_mutex_lock(&gInitMutex);
    461         if (mDev) {
    462             mDev->removeContext(this);
    463             mDev = NULL;
    464         }
    465         pthread_mutex_unlock(&gInitMutex);
    466     }
    467     ALOGV("%p Context::~Context done", this);
    468 }
    469 
    470 void Context::setSurface(uint32_t w, uint32_t h, RsNativeWindow sur) {
    471     rsAssert(mIsGraphicsContext);
    472     mHal.funcs.setSurface(this, w, h, sur);
    473 
    474     mHasSurface = sur != NULL;
    475     mWidth = w;
    476     mHeight = h;
    477 
    478     if (mWidth && mHeight) {
    479         mStateVertex.updateSize(this);
    480         mFBOCache.updateSize();
    481     }
    482 }
    483 
    484 uint32_t Context::getCurrentSurfaceWidth() const {
    485     for (uint32_t i = 0; i < mFBOCache.mHal.state.colorTargetsCount; i ++) {
    486         if (mFBOCache.mHal.state.colorTargets[i] != NULL) {
    487             return mFBOCache.mHal.state.colorTargets[i]->getType()->getDimX();
    488         }
    489     }
    490     if (mFBOCache.mHal.state.depthTarget != NULL) {
    491         return mFBOCache.mHal.state.depthTarget->getType()->getDimX();
    492     }
    493     return mWidth;
    494 }
    495 
    496 uint32_t Context::getCurrentSurfaceHeight() const {
    497     for (uint32_t i = 0; i < mFBOCache.mHal.state.colorTargetsCount; i ++) {
    498         if (mFBOCache.mHal.state.colorTargets[i] != NULL) {
    499             return mFBOCache.mHal.state.colorTargets[i]->getType()->getDimY();
    500         }
    501     }
    502     if (mFBOCache.mHal.state.depthTarget != NULL) {
    503         return mFBOCache.mHal.state.depthTarget->getType()->getDimY();
    504     }
    505     return mHeight;
    506 }
    507 
    508 void Context::pause() {
    509     rsAssert(mIsGraphicsContext);
    510     mPaused = true;
    511 }
    512 
    513 void Context::resume() {
    514     rsAssert(mIsGraphicsContext);
    515     mPaused = false;
    516 }
    517 
    518 void Context::setRootScript(Script *s) {
    519     rsAssert(mIsGraphicsContext);
    520     mRootScript.set(s);
    521 }
    522 
    523 void Context::setProgramStore(ProgramStore *pfs) {
    524     rsAssert(mIsGraphicsContext);
    525     if (pfs == NULL) {
    526         mFragmentStore.set(mStateFragmentStore.mDefault);
    527     } else {
    528         mFragmentStore.set(pfs);
    529     }
    530 }
    531 
    532 void Context::setProgramFragment(ProgramFragment *pf) {
    533     rsAssert(mIsGraphicsContext);
    534     if (pf == NULL) {
    535         mFragment.set(mStateFragment.mDefault);
    536     } else {
    537         mFragment.set(pf);
    538     }
    539 }
    540 
    541 void Context::setProgramRaster(ProgramRaster *pr) {
    542     rsAssert(mIsGraphicsContext);
    543     if (pr == NULL) {
    544         mRaster.set(mStateRaster.mDefault);
    545     } else {
    546         mRaster.set(pr);
    547     }
    548 }
    549 
    550 void Context::setProgramVertex(ProgramVertex *pv) {
    551     rsAssert(mIsGraphicsContext);
    552     if (pv == NULL) {
    553         mVertex.set(mStateVertex.mDefault);
    554     } else {
    555         mVertex.set(pv);
    556     }
    557 }
    558 
    559 void Context::setFont(Font *f) {
    560     rsAssert(mIsGraphicsContext);
    561     if (f == NULL) {
    562         mFont.set(mStateFont.mDefault);
    563     } else {
    564         mFont.set(f);
    565     }
    566 }
    567 
    568 void Context::assignName(ObjectBase *obj, const char *name, uint32_t len) {
    569     rsAssert(!obj->getName());
    570     obj->setName(name, len);
    571     mNames.add(obj);
    572 }
    573 
    574 void Context::removeName(ObjectBase *obj) {
    575     for (size_t ct=0; ct < mNames.size(); ct++) {
    576         if (obj == mNames[ct]) {
    577             mNames.removeAt(ct);
    578             return;
    579         }
    580     }
    581 }
    582 
    583 RsMessageToClientType Context::peekMessageToClient(size_t *receiveLen, uint32_t *subID) {
    584     return (RsMessageToClientType)mIO.getClientHeader(receiveLen, subID);
    585 }
    586 
    587 RsMessageToClientType Context::getMessageToClient(void *data, size_t *receiveLen, uint32_t *subID, size_t bufferLen) {
    588     return (RsMessageToClientType)mIO.getClientPayload(data, receiveLen, subID, bufferLen);
    589 }
    590 
    591 bool Context::sendMessageToClient(const void *data, RsMessageToClientType cmdID,
    592                                   uint32_t subID, size_t len, bool waitForSpace) const {
    593 
    594     return mIO.sendToClient(cmdID, subID, data, len, waitForSpace);
    595 }
    596 
    597 void Context::initToClient() {
    598     while (!mRunning) {
    599         usleep(100);
    600     }
    601 }
    602 
    603 void Context::deinitToClient() {
    604     mIO.clientShutdown();
    605 }
    606 
    607 void Context::setError(RsError e, const char *msg) const {
    608     mError = e;
    609     sendMessageToClient(msg, RS_MESSAGE_TO_CLIENT_ERROR, e, strlen(msg) + 1, true);
    610 }
    611 
    612 
    613 void Context::dumpDebug() const {
    614     ALOGE("RS Context debug %p", this);
    615     ALOGE("RS Context debug");
    616 
    617     ALOGE(" RS width %i, height %i", mWidth, mHeight);
    618     ALOGE(" RS running %i, exit %i, paused %i", mRunning, mExit, mPaused);
    619     ALOGE(" RS pThreadID %li, nativeThreadID %i", (long int)mThreadId, mNativeThreadId);
    620 }
    621 
    622 ///////////////////////////////////////////////////////////////////////////////////////////
    623 //
    624 
    625 namespace android {
    626 namespace renderscript {
    627 
    628 void rsi_ContextFinish(Context *rsc) {
    629 }
    630 
    631 void rsi_ContextBindRootScript(Context *rsc, RsScript vs) {
    632     Script *s = static_cast<Script *>(vs);
    633     rsc->setRootScript(s);
    634 }
    635 
    636 void rsi_ContextBindSampler(Context *rsc, uint32_t slot, RsSampler vs) {
    637     Sampler *s = static_cast<Sampler *>(vs);
    638 
    639     if (slot > RS_MAX_SAMPLER_SLOT) {
    640         ALOGE("Invalid sampler slot");
    641         return;
    642     }
    643 
    644     s->bindToContext(&rsc->mStateSampler, slot);
    645 }
    646 
    647 void rsi_ContextBindProgramStore(Context *rsc, RsProgramStore vpfs) {
    648     ProgramStore *pfs = static_cast<ProgramStore *>(vpfs);
    649     rsc->setProgramStore(pfs);
    650 }
    651 
    652 void rsi_ContextBindProgramFragment(Context *rsc, RsProgramFragment vpf) {
    653     ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
    654     rsc->setProgramFragment(pf);
    655 }
    656 
    657 void rsi_ContextBindProgramRaster(Context *rsc, RsProgramRaster vpr) {
    658     ProgramRaster *pr = static_cast<ProgramRaster *>(vpr);
    659     rsc->setProgramRaster(pr);
    660 }
    661 
    662 void rsi_ContextBindProgramVertex(Context *rsc, RsProgramVertex vpv) {
    663     ProgramVertex *pv = static_cast<ProgramVertex *>(vpv);
    664     rsc->setProgramVertex(pv);
    665 }
    666 
    667 void rsi_ContextBindFont(Context *rsc, RsFont vfont) {
    668     Font *font = static_cast<Font *>(vfont);
    669     rsc->setFont(font);
    670 }
    671 
    672 void rsi_AssignName(Context *rsc, RsObjectBase obj, const char *name, size_t name_length) {
    673     ObjectBase *ob = static_cast<ObjectBase *>(obj);
    674     rsc->assignName(ob, name, name_length);
    675 }
    676 
    677 void rsi_ObjDestroy(Context *rsc, void *optr) {
    678     ObjectBase *ob = static_cast<ObjectBase *>(optr);
    679     rsc->removeName(ob);
    680     ob->decUserRef();
    681 }
    682 
    683 void rsi_ContextPause(Context *rsc) {
    684     rsc->pause();
    685 }
    686 
    687 void rsi_ContextResume(Context *rsc) {
    688     rsc->resume();
    689 }
    690 
    691 void rsi_ContextSetSurface(Context *rsc, uint32_t w, uint32_t h, RsNativeWindow sur) {
    692     rsc->setSurface(w, h, sur);
    693 }
    694 
    695 void rsi_ContextSetPriority(Context *rsc, int32_t p) {
    696     rsc->setPriority(p);
    697 }
    698 
    699 void rsi_ContextDump(Context *rsc, int32_t bits) {
    700     ObjectBase::dumpAll(rsc);
    701 }
    702 
    703 void rsi_ContextDestroyWorker(Context *rsc) {
    704     rsc->destroyWorkerThreadResources();
    705 }
    706 
    707 void rsi_ContextDestroy(Context *rsc) {
    708     ALOGV("%p rsContextDestroy", rsc);
    709     rsContextDestroyWorker(rsc);
    710     delete rsc;
    711     ALOGV("%p rsContextDestroy done", rsc);
    712 }
    713 
    714 
    715 RsMessageToClientType rsi_ContextPeekMessage(Context *rsc,
    716                                            size_t * receiveLen, size_t receiveLen_length,
    717                                            uint32_t * subID, size_t subID_length) {
    718     return rsc->peekMessageToClient(receiveLen, subID);
    719 }
    720 
    721 RsMessageToClientType rsi_ContextGetMessage(Context *rsc, void * data, size_t data_length,
    722                                           size_t * receiveLen, size_t receiveLen_length,
    723                                           uint32_t * subID, size_t subID_length) {
    724     rsAssert(subID_length == sizeof(uint32_t));
    725     rsAssert(receiveLen_length == sizeof(size_t));
    726     return rsc->getMessageToClient(data, receiveLen, subID, data_length);
    727 }
    728 
    729 void rsi_ContextInitToClient(Context *rsc) {
    730     rsc->initToClient();
    731 }
    732 
    733 void rsi_ContextDeinitToClient(Context *rsc) {
    734     rsc->deinitToClient();
    735 }
    736 
    737 }
    738 }
    739 
    740 RsContext rsContextCreate(RsDevice vdev, uint32_t version,
    741                           uint32_t sdkVersion) {
    742     ALOGV("rsContextCreate dev=%p", vdev);
    743     Device * dev = static_cast<Device *>(vdev);
    744     Context *rsc = Context::createContext(dev, NULL);
    745     if (rsc) {
    746         rsc->setTargetSdkVersion(sdkVersion);
    747     }
    748     return rsc;
    749 }
    750 
    751 RsContext rsContextCreateGL(RsDevice vdev, uint32_t version,
    752                             uint32_t sdkVersion, RsSurfaceConfig sc,
    753                             uint32_t dpi) {
    754     ALOGV("rsContextCreateGL dev=%p", vdev);
    755     Device * dev = static_cast<Device *>(vdev);
    756     Context *rsc = Context::createContext(dev, &sc);
    757     if (rsc) {
    758         rsc->setTargetSdkVersion(sdkVersion);
    759         rsc->setDPI(dpi);
    760     }
    761     ALOGV("%p rsContextCreateGL ret", rsc);
    762     return rsc;
    763 }
    764 
    765 // Only to be called at a3d load time, before object is visible to user
    766 // not thread safe
    767 void rsaGetName(RsContext con, void * obj, const char **name) {
    768     ObjectBase *ob = static_cast<ObjectBase *>(obj);
    769     (*name) = ob->getName();
    770 }
    771