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