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 
     22 #include "rsgApiStructs.h"
     23 
     24 #ifndef RS_COMPATIBILITY_LIB
     25 #include "rsMesh.h"
     26 #include <gui/DisplayEventReceiver.h>
     27 #endif
     28 
     29 #include <sys/types.h>
     30 #include <sys/resource.h>
     31 #include <sched.h>
     32 
     33 #include <sys/syscall.h>
     34 #include <string.h>
     35 #include <dlfcn.h>
     36 #include <inttypes.h>
     37 #include <unistd.h>
     38 
     39 #if !defined(RS_SERVER) && !defined(RS_COMPATIBILITY_LIB) && \
     40         defined(HAVE_ANDROID_OS)
     41 #include <cutils/properties.h>
     42 #endif
     43 
     44 #ifdef RS_COMPATIBILITY_LIB
     45 #include "rsCompatibilityLib.h"
     46 #endif
     47 
     48 int gDebuggerPresent = 0;
     49 
     50 #ifdef RS_SERVER
     51 // Android exposes gettid(), standard Linux does not
     52 static pid_t gettid() {
     53     return syscall(SYS_gettid);
     54 }
     55 #endif
     56 
     57 using namespace android;
     58 using namespace android::renderscript;
     59 
     60 pthread_mutex_t Context::gInitMutex = PTHREAD_MUTEX_INITIALIZER;
     61 pthread_mutex_t Context::gMessageMutex = PTHREAD_MUTEX_INITIALIZER;
     62 pthread_mutex_t Context::gLibMutex = PTHREAD_MUTEX_INITIALIZER;
     63 
     64 bool Context::initGLThread() {
     65     pthread_mutex_lock(&gInitMutex);
     66 
     67     if (!mHal.funcs.initGraphics(this)) {
     68         pthread_mutex_unlock(&gInitMutex);
     69         ALOGE("%p initGraphics failed", this);
     70         return false;
     71     }
     72 
     73     pthread_mutex_unlock(&gInitMutex);
     74     return true;
     75 }
     76 
     77 void Context::deinitEGL() {
     78 #ifndef RS_COMPATIBILITY_LIB
     79     mHal.funcs.shutdownGraphics(this);
     80 #endif
     81 }
     82 
     83 Context::PushState::PushState(Context *con) {
     84     mRsc = con;
     85 #ifndef RS_COMPATIBILITY_LIB
     86     if (con->mIsGraphicsContext) {
     87         mFragment.set(con->getProgramFragment());
     88         mVertex.set(con->getProgramVertex());
     89         mStore.set(con->getProgramStore());
     90         mRaster.set(con->getProgramRaster());
     91         mFont.set(con->getFont());
     92     }
     93 #endif
     94 }
     95 
     96 Context::PushState::~PushState() {
     97 #ifndef RS_COMPATIBILITY_LIB
     98     if (mRsc->mIsGraphicsContext) {
     99         mRsc->setProgramFragment(mFragment.get());
    100         mRsc->setProgramVertex(mVertex.get());
    101         mRsc->setProgramStore(mStore.get());
    102         mRsc->setProgramRaster(mRaster.get());
    103         mRsc->setFont(mFont.get());
    104     }
    105 #endif
    106 }
    107 
    108 
    109 uint32_t Context::runScript(Script *s) {
    110     PushState ps(this);
    111 
    112     uint32_t ret = s->run(this);
    113     return ret;
    114 }
    115 
    116 uint32_t Context::runRootScript() {
    117     timerSet(RS_TIMER_SCRIPT);
    118 #ifndef RS_COMPATIBILITY_LIB
    119     mStateFragmentStore.mLast.clear();
    120 #endif
    121     watchdog.inRoot = true;
    122     uint32_t ret = runScript(mRootScript.get());
    123     watchdog.inRoot = false;
    124 
    125     return ret;
    126 }
    127 
    128 uint64_t Context::getTime() const {
    129 #ifndef ANDROID_RS_SERIALIZE
    130     struct timespec t;
    131     clock_gettime(CLOCK_MONOTONIC, &t);
    132     return t.tv_nsec + ((uint64_t)t.tv_sec * 1000 * 1000 * 1000);
    133 #else
    134     return 0;
    135 #endif //ANDROID_RS_SERIALIZE
    136 }
    137 
    138 void Context::timerReset() {
    139     for (int ct=0; ct < _RS_TIMER_TOTAL; ct++) {
    140         mTimers[ct] = 0;
    141     }
    142 }
    143 
    144 void Context::timerInit() {
    145     mTimeLast = getTime();
    146     mTimeFrame = mTimeLast;
    147     mTimeLastFrame = mTimeLast;
    148     mTimerActive = RS_TIMER_INTERNAL;
    149     mAverageFPSFrameCount = 0;
    150     mAverageFPSStartTime = mTimeLast;
    151     mAverageFPS = 0;
    152     timerReset();
    153 }
    154 
    155 void Context::timerFrame() {
    156     mTimeLastFrame = mTimeFrame;
    157     mTimeFrame = getTime();
    158     // Update average fps
    159     const uint64_t averageFramerateInterval = 1000 * 1000000;
    160     mAverageFPSFrameCount ++;
    161     uint64_t inverval = mTimeFrame - mAverageFPSStartTime;
    162     if (inverval >= averageFramerateInterval) {
    163         inverval = inverval / 1000000;
    164         mAverageFPS = (mAverageFPSFrameCount * 1000) / inverval;
    165         mAverageFPSFrameCount = 0;
    166         mAverageFPSStartTime = mTimeFrame;
    167     }
    168 }
    169 
    170 void Context::timerSet(Timers tm) {
    171     uint64_t last = mTimeLast;
    172     mTimeLast = getTime();
    173     mTimers[mTimerActive] += mTimeLast - last;
    174     mTimerActive = tm;
    175 }
    176 
    177 void Context::timerPrint() {
    178     double total = 0;
    179     for (int ct = 0; ct < _RS_TIMER_TOTAL; ct++) {
    180         total += mTimers[ct];
    181     }
    182     uint64_t frame = mTimeFrame - mTimeLastFrame;
    183     mTimeMSLastFrame = frame / 1000000;
    184     mTimeMSLastScript = mTimers[RS_TIMER_SCRIPT] / 1000000;
    185     mTimeMSLastSwap = mTimers[RS_TIMER_CLEAR_SWAP] / 1000000;
    186 
    187 
    188     if (props.mLogTimes) {
    189         ALOGV("RS: Frame (%i),   Script %2.1f%% (%i),  Swap %2.1f%% (%i),  Idle %2.1f%% (%" PRIi64 "),  "
    190               "Internal %2.1f%% (%" PRIi64 "), Avg fps: %u",
    191              mTimeMSLastFrame,
    192              100.0 * mTimers[RS_TIMER_SCRIPT] / total, mTimeMSLastScript,
    193              100.0 * mTimers[RS_TIMER_CLEAR_SWAP] / total, mTimeMSLastSwap,
    194              100.0 * mTimers[RS_TIMER_IDLE] / total, mTimers[RS_TIMER_IDLE] / 1000000,
    195              100.0 * mTimers[RS_TIMER_INTERNAL] / total, mTimers[RS_TIMER_INTERNAL] / 1000000,
    196              mAverageFPS);
    197     }
    198 }
    199 
    200 bool Context::setupCheck() {
    201 #ifndef RS_COMPATIBILITY_LIB
    202     mFragmentStore->setup(this, &mStateFragmentStore);
    203     mFragment->setup(this, &mStateFragment);
    204     mRaster->setup(this, &mStateRaster);
    205     mVertex->setup(this, &mStateVertex);
    206     mFBOCache.setup(this);
    207 #endif
    208     return true;
    209 }
    210 
    211 #ifndef RS_COMPATIBILITY_LIB
    212 void Context::setupProgramStore() {
    213     mFragmentStore->setup(this, &mStateFragmentStore);
    214 }
    215 #endif
    216 
    217 static uint32_t getProp(const char *str) {
    218 #if !defined(RS_SERVER) && defined(HAVE_ANDROID_OS)
    219     char buf[PROPERTY_VALUE_MAX];
    220     property_get(str, buf, "0");
    221     return atoi(buf);
    222 #else
    223     return 0;
    224 #endif
    225 }
    226 
    227 void Context::displayDebugStats() {
    228 #ifndef RS_COMPATIBILITY_LIB
    229     char buffer[128];
    230     sprintf(buffer, "Avg fps %u, Frame %i ms, Script %i ms", mAverageFPS, mTimeMSLastFrame, mTimeMSLastScript);
    231     float oldR, oldG, oldB, oldA;
    232     mStateFont.getFontColor(&oldR, &oldG, &oldB, &oldA);
    233     uint32_t bufferLen = strlen(buffer);
    234 
    235     ObjectBaseRef<Font> lastFont(getFont());
    236     setFont(nullptr);
    237     float shadowCol = 0.1f;
    238     mStateFont.setFontColor(shadowCol, shadowCol, shadowCol, 1.0f);
    239     mStateFont.renderText(buffer, bufferLen, 5, getHeight() - 6);
    240 
    241     mStateFont.setFontColor(1.0f, 0.7f, 0.0f, 1.0f);
    242     mStateFont.renderText(buffer, bufferLen, 4, getHeight() - 7);
    243 
    244     setFont(lastFont.get());
    245     mStateFont.setFontColor(oldR, oldG, oldB, oldA);
    246 #endif
    247 }
    248 
    249 void * Context::threadProc(void *vrsc) {
    250     Context *rsc = static_cast<Context *>(vrsc);
    251 
    252 #ifndef ANDROID_RS_SERIALIZE
    253     rsc->mNativeThreadId = gettid();
    254 #endif //ANDROID_RS_SERIALIZE
    255 
    256     rsc->props.mLogTimes = getProp("debug.rs.profile") != 0;
    257     rsc->props.mLogScripts = getProp("debug.rs.script") != 0;
    258     rsc->props.mLogShaders = getProp("debug.rs.shader") != 0;
    259     rsc->props.mLogShadersAttr = getProp("debug.rs.shader.attributes") != 0;
    260     rsc->props.mLogShadersUniforms = getProp("debug.rs.shader.uniforms") != 0;
    261     rsc->props.mLogVisual = getProp("debug.rs.visual") != 0;
    262     rsc->props.mDebugMaxThreads = getProp("debug.rs.max-threads");
    263 
    264     if (getProp("debug.rs.debug") != 0) {
    265         ALOGD("Forcing debug context due to debug.rs.debug.");
    266         rsc->mContextType = RS_CONTEXT_TYPE_DEBUG;
    267         rsc->mForceCpu = true;
    268     }
    269 
    270     bool forceCpu = getProp("debug.rs.default-CPU-driver") != 0;
    271     if (forceCpu) {
    272         ALOGD("Skipping hardware driver and loading default CPU driver");
    273         rsc->mForceCpu = true;
    274     }
    275 
    276     rsc->mForceCpu |= rsc->mIsGraphicsContext;
    277     rsc->loadDriver(rsc->mForceCpu);
    278 
    279     if (!rsc->isSynchronous()) {
    280         // Due to legacy we default to normal_graphics
    281         // setPriority will make the adjustments as needed.
    282         rsc->setPriority(RS_THREAD_PRIORITY_NORMAL_GRAPHICS);
    283     }
    284 
    285 #ifndef RS_COMPATIBILITY_LIB
    286     if (rsc->mIsGraphicsContext) {
    287         if (!rsc->initGLThread()) {
    288             rsc->setError(RS_ERROR_OUT_OF_MEMORY, "Failed initializing GL");
    289             return nullptr;
    290         }
    291 
    292         rsc->mStateRaster.init(rsc);
    293         rsc->setProgramRaster(nullptr);
    294         rsc->mStateVertex.init(rsc);
    295         rsc->setProgramVertex(nullptr);
    296         rsc->mStateFragment.init(rsc);
    297         rsc->setProgramFragment(nullptr);
    298         rsc->mStateFragmentStore.init(rsc);
    299         rsc->setProgramStore(nullptr);
    300         rsc->mStateFont.init(rsc);
    301         rsc->setFont(nullptr);
    302         rsc->mStateSampler.init(rsc);
    303         rsc->mFBOCache.init(rsc);
    304     }
    305 #endif
    306 
    307     rsc->mRunning = true;
    308 
    309     if (rsc->isSynchronous()) {
    310         return nullptr;
    311     }
    312 
    313     if (!rsc->mIsGraphicsContext) {
    314         while (!rsc->mExit) {
    315             rsc->mIO.playCoreCommands(rsc, -1);
    316         }
    317 #ifndef RS_COMPATIBILITY_LIB
    318     } else {
    319 #ifndef ANDROID_RS_SERIALIZE
    320         DisplayEventReceiver displayEvent;
    321         DisplayEventReceiver::Event eventBuffer[1];
    322 #endif
    323         int vsyncRate = 0;
    324         int targetRate = 0;
    325 
    326         bool drawOnce = false;
    327         while (!rsc->mExit) {
    328             rsc->timerSet(RS_TIMER_IDLE);
    329 
    330 #ifndef ANDROID_RS_SERIALIZE
    331             if (!rsc->mRootScript.get() || !rsc->mHasSurface || rsc->mPaused) {
    332                 targetRate = 0;
    333             }
    334 
    335             if (vsyncRate != targetRate) {
    336                 displayEvent.setVsyncRate(targetRate);
    337                 vsyncRate = targetRate;
    338             }
    339             if (targetRate) {
    340                 drawOnce |= rsc->mIO.playCoreCommands(rsc, displayEvent.getFd());
    341                 while (displayEvent.getEvents(eventBuffer, 1) != 0) {
    342                     //ALOGE("vs2 time past %lld", (rsc->getTime() - eventBuffer[0].header.timestamp) / 1000000);
    343                 }
    344             } else
    345 #endif
    346             {
    347                 drawOnce |= rsc->mIO.playCoreCommands(rsc, -1);
    348             }
    349 
    350             if ((rsc->mRootScript.get() != nullptr) && rsc->mHasSurface &&
    351                 (targetRate || drawOnce) && !rsc->mPaused) {
    352 
    353                 drawOnce = false;
    354                 targetRate = ((rsc->runRootScript() + 15) / 16);
    355 
    356                 if (rsc->props.mLogVisual) {
    357                     rsc->displayDebugStats();
    358                 }
    359 
    360                 rsc->timerSet(RS_TIMER_CLEAR_SWAP);
    361                 rsc->mHal.funcs.swap(rsc);
    362                 rsc->timerFrame();
    363                 rsc->timerSet(RS_TIMER_INTERNAL);
    364                 rsc->timerPrint();
    365                 rsc->timerReset();
    366             }
    367         }
    368 #endif
    369     }
    370 
    371     //ALOGV("%p RS Thread exiting", rsc);
    372 
    373 #ifndef RS_COMPATIBILITY_LIB
    374     if (rsc->mIsGraphicsContext) {
    375         pthread_mutex_lock(&gInitMutex);
    376         rsc->deinitEGL();
    377         pthread_mutex_unlock(&gInitMutex);
    378     }
    379 #endif
    380 
    381     //ALOGV("%p RS Thread exited", rsc);
    382     return nullptr;
    383 }
    384 
    385 void Context::destroyWorkerThreadResources() {
    386     //ALOGV("destroyWorkerThreadResources 1");
    387     ObjectBase::zeroAllUserRef(this);
    388 #ifndef RS_COMPATIBILITY_LIB
    389     if (mIsGraphicsContext) {
    390          mRaster.clear();
    391          mFragment.clear();
    392          mVertex.clear();
    393          mFragmentStore.clear();
    394          mFont.clear();
    395          mRootScript.clear();
    396          mStateRaster.deinit(this);
    397          mStateVertex.deinit(this);
    398          mStateFragment.deinit(this);
    399          mStateFragmentStore.deinit(this);
    400          mStateFont.deinit(this);
    401          mStateSampler.deinit(this);
    402          mFBOCache.deinit(this);
    403     }
    404 #endif
    405     ObjectBase::freeAllChildren(this);
    406     mExit = true;
    407     //ALOGV("destroyWorkerThreadResources 2");
    408 }
    409 
    410 void Context::printWatchdogInfo(void *ctx) {
    411     Context *rsc = (Context *)ctx;
    412     if (rsc->watchdog.command && rsc->watchdog.file) {
    413         ALOGE("RS watchdog timeout: %i  %s  line %i %s", rsc->watchdog.inRoot,
    414              rsc->watchdog.command, rsc->watchdog.line, rsc->watchdog.file);
    415     } else {
    416         ALOGE("RS watchdog timeout: %i", rsc->watchdog.inRoot);
    417     }
    418 }
    419 
    420 
    421 void Context::setPriority(int32_t p) {
    422     switch (p) {
    423     // The public API will always send NORMAL_GRAPHICS
    424     // for normal, we adjust here
    425     case RS_THREAD_PRIORITY_NORMAL_GRAPHICS:
    426         if (mIsGraphicsContext) {
    427             break;
    428         } else {
    429             if (mHal.flags & RS_CONTEXT_LOW_LATENCY) {
    430                 p = RS_THREAD_PRIORITY_LOW_LATENCY;
    431             } else {
    432                 p = RS_THREAD_PRIORITY_NORMAL;
    433             }
    434         }
    435     case RS_THREAD_PRIORITY_LOW:
    436         break;
    437     }
    438 
    439     // Note: If we put this in the proper "background" policy
    440     // the wallpapers can become completly unresponsive at times.
    441     // This is probably not what we want for something the user is actively
    442     // looking at.
    443     mThreadPriority = p;
    444     setpriority(PRIO_PROCESS, mNativeThreadId, p);
    445     mHal.funcs.setPriority(this, mThreadPriority);
    446 }
    447 
    448 Context::Context() {
    449     mDev = nullptr;
    450     mRunning = false;
    451     mExit = false;
    452     mPaused = false;
    453     mObjHead = nullptr;
    454     mError = RS_ERROR_NONE;
    455     mTargetSdkVersion = 14;
    456     mDPI = 96;
    457     mIsContextLite = false;
    458     memset(&watchdog, 0, sizeof(watchdog));
    459     memset(&mHal, 0, sizeof(mHal));
    460     mForceCpu = false;
    461     mContextType = RS_CONTEXT_TYPE_NORMAL;
    462     mSynchronous = false;
    463     mFatalErrorOccured = false;
    464 
    465     memset(mCacheDir, 0, sizeof(mCacheDir));
    466 #ifdef RS_COMPATIBILITY_LIB
    467     memset(nativeLibDir, 0, sizeof(nativeLibDir));
    468 #endif
    469 }
    470 
    471 void Context::setCacheDir(const char * cacheDir_arg, uint32_t length) {
    472     if (!hasSetCacheDir) {
    473         if (length <= PATH_MAX) {
    474             memcpy(mCacheDir, cacheDir_arg, length);
    475             mCacheDir[length] = 0;
    476             hasSetCacheDir = true;
    477         } else {
    478             setError(RS_ERROR_BAD_VALUE, "Invalid path");
    479         }
    480     }
    481 }
    482 
    483 void Context::waitForDebugger() {
    484     while (!gDebuggerPresent) {
    485         sleep(0);
    486     }
    487 }
    488 
    489 Context * Context::createContext(Device *dev, const RsSurfaceConfig *sc,
    490                                  RsContextType ct, uint32_t flags) {
    491     Context * rsc = new Context();
    492 
    493     if (flags & RS_CONTEXT_LOW_LATENCY) {
    494         rsc->mForceCpu = true;
    495     }
    496     if (flags & RS_CONTEXT_SYNCHRONOUS) {
    497         rsc->mSynchronous = true;
    498     }
    499     rsc->mContextType = ct;
    500     rsc->mHal.flags = flags;
    501 
    502     if (!rsc->initContext(dev, sc)) {
    503         delete rsc;
    504         return nullptr;
    505     }
    506 
    507     if (flags & RS_CONTEXT_WAIT_FOR_ATTACH) {
    508         rsc->waitForDebugger();
    509     }
    510 
    511     return rsc;
    512 }
    513 
    514 Context * Context::createContextLite() {
    515     Context * rsc = new Context();
    516     rsc->mIsContextLite = true;
    517     return rsc;
    518 }
    519 
    520 bool Context::initContext(Device *dev, const RsSurfaceConfig *sc) {
    521     pthread_mutex_lock(&gInitMutex);
    522 
    523     mIO.init();
    524     mIO.setTimeoutCallback(printWatchdogInfo, this, 2e9);
    525 
    526     dev->addContext(this);
    527     mDev = dev;
    528     if (sc) {
    529         mUserSurfaceConfig = *sc;
    530     } else {
    531         memset(&mUserSurfaceConfig, 0, sizeof(mUserSurfaceConfig));
    532     }
    533 
    534     mIsGraphicsContext = sc != nullptr;
    535 
    536     int status;
    537     pthread_attr_t threadAttr;
    538 
    539     pthread_mutex_unlock(&gInitMutex);
    540 
    541     // Global init done at this point.
    542 
    543     status = pthread_attr_init(&threadAttr);
    544     if (status) {
    545         ALOGE("Failed to init thread attribute.");
    546         return false;
    547     }
    548 
    549     mHasSurface = false;
    550     mDriverName = NULL;
    551 
    552     timerInit();
    553     timerSet(RS_TIMER_INTERNAL);
    554     if (mSynchronous) {
    555         threadProc(this);
    556 
    557         if (mError != RS_ERROR_NONE) {
    558             ALOGE("Errors during thread init (sync mode)");
    559             return false;
    560         }
    561     } else {
    562         status = pthread_create(&mThreadId, &threadAttr, threadProc, this);
    563         if (status) {
    564             ALOGE("Failed to start rs context thread.");
    565             return false;
    566         }
    567         while (!mRunning && (mError == RS_ERROR_NONE)) {
    568             usleep(100);
    569         }
    570 
    571         if (mError != RS_ERROR_NONE) {
    572             ALOGE("Errors during thread init");
    573             return false;
    574         }
    575 
    576         pthread_attr_destroy(&threadAttr);
    577     }
    578     return true;
    579 }
    580 
    581 Context::~Context() {
    582     //ALOGV("%p Context::~Context", this);
    583 
    584     if (!mIsContextLite) {
    585         mPaused = false;
    586         void *res;
    587 
    588         mIO.shutdown();
    589         if (!mSynchronous) {
    590             pthread_join(mThreadId, &res);
    591         }
    592         rsAssert(mExit);
    593 
    594         if (mHal.funcs.shutdownDriver && mHal.drv) {
    595             mHal.funcs.shutdownDriver(this);
    596         }
    597 
    598         // Global structure cleanup.
    599         pthread_mutex_lock(&gInitMutex);
    600         if (mDev) {
    601             mDev->removeContext(this);
    602             mDev = nullptr;
    603         }
    604         pthread_mutex_unlock(&gInitMutex);
    605     }
    606     //ALOGV("%p Context::~Context done", this);
    607 }
    608 
    609 #ifndef RS_COMPATIBILITY_LIB
    610 void Context::setSurface(uint32_t w, uint32_t h, RsNativeWindow sur) {
    611     rsAssert(mIsGraphicsContext);
    612     mHal.funcs.setSurface(this, w, h, sur);
    613 
    614     mHasSurface = sur != nullptr;
    615     mWidth = w;
    616     mHeight = h;
    617 
    618     if (mWidth && mHeight) {
    619         mStateVertex.updateSize(this);
    620         mFBOCache.updateSize();
    621     }
    622 }
    623 
    624 uint32_t Context::getCurrentSurfaceWidth() const {
    625     for (uint32_t i = 0; i < mFBOCache.mHal.state.colorTargetsCount; i ++) {
    626         if (mFBOCache.mHal.state.colorTargets[i] != nullptr) {
    627             return mFBOCache.mHal.state.colorTargets[i]->getType()->getDimX();
    628         }
    629     }
    630     if (mFBOCache.mHal.state.depthTarget != nullptr) {
    631         return mFBOCache.mHal.state.depthTarget->getType()->getDimX();
    632     }
    633     return mWidth;
    634 }
    635 
    636 uint32_t Context::getCurrentSurfaceHeight() const {
    637     for (uint32_t i = 0; i < mFBOCache.mHal.state.colorTargetsCount; i ++) {
    638         if (mFBOCache.mHal.state.colorTargets[i] != nullptr) {
    639             return mFBOCache.mHal.state.colorTargets[i]->getType()->getDimY();
    640         }
    641     }
    642     if (mFBOCache.mHal.state.depthTarget != nullptr) {
    643         return mFBOCache.mHal.state.depthTarget->getType()->getDimY();
    644     }
    645     return mHeight;
    646 }
    647 
    648 void Context::pause() {
    649     rsAssert(mIsGraphicsContext);
    650     mPaused = true;
    651 }
    652 
    653 void Context::resume() {
    654     rsAssert(mIsGraphicsContext);
    655     mPaused = false;
    656 }
    657 
    658 void Context::setRootScript(Script *s) {
    659     rsAssert(mIsGraphicsContext);
    660     mRootScript.set(s);
    661 }
    662 
    663 void Context::setProgramStore(ProgramStore *pfs) {
    664     rsAssert(mIsGraphicsContext);
    665     if (pfs == nullptr) {
    666         mFragmentStore.set(mStateFragmentStore.mDefault);
    667     } else {
    668         mFragmentStore.set(pfs);
    669     }
    670 }
    671 
    672 void Context::setProgramFragment(ProgramFragment *pf) {
    673     rsAssert(mIsGraphicsContext);
    674     if (pf == nullptr) {
    675         mFragment.set(mStateFragment.mDefault);
    676     } else {
    677         mFragment.set(pf);
    678     }
    679 }
    680 
    681 void Context::setProgramRaster(ProgramRaster *pr) {
    682     rsAssert(mIsGraphicsContext);
    683     if (pr == nullptr) {
    684         mRaster.set(mStateRaster.mDefault);
    685     } else {
    686         mRaster.set(pr);
    687     }
    688 }
    689 
    690 void Context::setProgramVertex(ProgramVertex *pv) {
    691     rsAssert(mIsGraphicsContext);
    692     if (pv == nullptr) {
    693         mVertex.set(mStateVertex.mDefault);
    694     } else {
    695         mVertex.set(pv);
    696     }
    697 }
    698 
    699 void Context::setFont(Font *f) {
    700     rsAssert(mIsGraphicsContext);
    701     if (f == nullptr) {
    702         mFont.set(mStateFont.mDefault);
    703     } else {
    704         mFont.set(f);
    705     }
    706 }
    707 #endif
    708 
    709 void Context::finish() {
    710     if (mHal.funcs.finish) {
    711         mHal.funcs.finish(this);
    712     }
    713 }
    714 
    715 void Context::assignName(ObjectBase *obj, const char *name, uint32_t len) {
    716     rsAssert(!obj->getName());
    717     obj->setName(name, len);
    718     mNames.add(obj);
    719 }
    720 
    721 void Context::removeName(ObjectBase *obj) {
    722     for (size_t ct=0; ct < mNames.size(); ct++) {
    723         if (obj == mNames[ct]) {
    724             mNames.removeAt(ct);
    725             return;
    726         }
    727     }
    728 }
    729 
    730 RsMessageToClientType Context::peekMessageToClient(size_t *receiveLen, uint32_t *subID) {
    731     return (RsMessageToClientType)mIO.getClientHeader(receiveLen, subID);
    732 }
    733 
    734 RsMessageToClientType Context::getMessageToClient(void *data, size_t *receiveLen, uint32_t *subID, size_t bufferLen) {
    735     return (RsMessageToClientType)mIO.getClientPayload(data, receiveLen, subID, bufferLen);
    736 }
    737 
    738 bool Context::sendMessageToClient(const void *data, RsMessageToClientType cmdID,
    739                                   uint32_t subID, size_t len, bool waitForSpace) const {
    740 
    741     pthread_mutex_lock(&gMessageMutex);
    742     bool ret = mIO.sendToClient(cmdID, subID, data, len, waitForSpace);
    743     pthread_mutex_unlock(&gMessageMutex);
    744     return ret;
    745 }
    746 
    747 void Context::initToClient() {
    748     while (!mRunning) {
    749         usleep(100);
    750     }
    751 }
    752 
    753 void Context::deinitToClient() {
    754     mIO.clientShutdown();
    755 }
    756 
    757 void Context::setError(RsError e, const char *msg) const {
    758     mError = e;
    759 
    760     if (mError >= RS_ERROR_FATAL_DEBUG) {
    761         // If a FATAL error occurred, set the flag to indicate the process
    762         // will be goign down
    763         mFatalErrorOccured = true;
    764     }
    765 
    766     sendMessageToClient(msg, RS_MESSAGE_TO_CLIENT_ERROR, e, strlen(msg) + 1, true);
    767 }
    768 
    769 
    770 void Context::dumpDebug() const {
    771     ALOGE("RS Context debug %p", this);
    772     ALOGE("RS Context debug");
    773 
    774     ALOGE(" RS width %i, height %i", mWidth, mHeight);
    775     ALOGE(" RS running %i, exit %i, paused %i", mRunning, mExit, mPaused);
    776     ALOGE(" RS pThreadID %li, nativeThreadID %i", (long int)mThreadId, mNativeThreadId);
    777 }
    778 
    779 ///////////////////////////////////////////////////////////////////////////////////////////
    780 //
    781 
    782 namespace android {
    783 namespace renderscript {
    784 
    785 void rsi_ContextFinish(Context *rsc) {
    786     rsc->finish();
    787 }
    788 
    789 void rsi_ContextBindRootScript(Context *rsc, RsScript vs) {
    790 #ifndef RS_COMPATIBILITY_LIB
    791     Script *s = static_cast<Script *>(vs);
    792     rsc->setRootScript(s);
    793 #endif
    794 }
    795 
    796 void rsi_ContextSetCacheDir(Context *rsc, const char *cacheDir, size_t cacheDir_length) {
    797     rsc->setCacheDir(cacheDir, cacheDir_length);
    798 }
    799 
    800 void rsi_ContextBindSampler(Context *rsc, uint32_t slot, RsSampler vs) {
    801     Sampler *s = static_cast<Sampler *>(vs);
    802 
    803     if (slot > RS_MAX_SAMPLER_SLOT) {
    804         ALOGE("Invalid sampler slot");
    805         return;
    806     }
    807 
    808     s->bindToContext(&rsc->mStateSampler, slot);
    809 }
    810 
    811 #ifndef RS_COMPATIBILITY_LIB
    812 void rsi_ContextBindProgramStore(Context *rsc, RsProgramStore vpfs) {
    813     ProgramStore *pfs = static_cast<ProgramStore *>(vpfs);
    814     rsc->setProgramStore(pfs);
    815 }
    816 
    817 void rsi_ContextBindProgramFragment(Context *rsc, RsProgramFragment vpf) {
    818     ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
    819     rsc->setProgramFragment(pf);
    820 }
    821 
    822 void rsi_ContextBindProgramRaster(Context *rsc, RsProgramRaster vpr) {
    823     ProgramRaster *pr = static_cast<ProgramRaster *>(vpr);
    824     rsc->setProgramRaster(pr);
    825 }
    826 
    827 void rsi_ContextBindProgramVertex(Context *rsc, RsProgramVertex vpv) {
    828     ProgramVertex *pv = static_cast<ProgramVertex *>(vpv);
    829     rsc->setProgramVertex(pv);
    830 }
    831 
    832 void rsi_ContextBindFont(Context *rsc, RsFont vfont) {
    833     Font *font = static_cast<Font *>(vfont);
    834     rsc->setFont(font);
    835 }
    836 #endif
    837 
    838 void rsi_AssignName(Context *rsc, RsObjectBase obj, const char *name, size_t name_length) {
    839     ObjectBase *ob = static_cast<ObjectBase *>(obj);
    840     rsc->assignName(ob, name, name_length);
    841 }
    842 
    843 void rsi_ObjDestroy(Context *rsc, void *optr) {
    844     ObjectBase *ob = static_cast<ObjectBase *>(optr);
    845     rsc->removeName(ob);
    846     ob->decUserRef();
    847 }
    848 
    849 #ifndef RS_COMPATIBILITY_LIB
    850 void rsi_ContextPause(Context *rsc) {
    851     rsc->pause();
    852 }
    853 
    854 void rsi_ContextResume(Context *rsc) {
    855     rsc->resume();
    856 }
    857 
    858 void rsi_ContextSetSurface(Context *rsc, uint32_t w, uint32_t h, RsNativeWindow sur) {
    859     rsc->setSurface(w, h, sur);
    860 }
    861 #endif
    862 
    863 void rsi_ContextSetPriority(Context *rsc, int32_t p) {
    864     rsc->setPriority(p);
    865 }
    866 
    867 void rsi_ContextDump(Context *rsc, int32_t bits) {
    868     ObjectBase::dumpAll(rsc);
    869 }
    870 
    871 void rsi_ContextDestroyWorker(Context *rsc) {
    872     rsc->destroyWorkerThreadResources();
    873 }
    874 
    875 void rsi_ContextDestroy(Context *rsc) {
    876     //ALOGE("%p rsContextDestroy", rsc);
    877     rsContextDestroyWorker(rsc);
    878     delete rsc;
    879     //ALOGV("%p rsContextDestroy done", rsc);
    880 }
    881 
    882 RsMessageToClientType rsi_ContextPeekMessage(Context *rsc,
    883                                            size_t * receiveLen, size_t receiveLen_length,
    884                                            uint32_t * subID, size_t subID_length) {
    885     return rsc->peekMessageToClient(receiveLen, subID);
    886 }
    887 
    888 RsMessageToClientType rsi_ContextGetMessage(Context *rsc, void * data, size_t data_length,
    889                                           size_t * receiveLen, size_t receiveLen_length,
    890                                           uint32_t * subID, size_t subID_length) {
    891     rsAssert(subID_length == sizeof(uint32_t));
    892     rsAssert(receiveLen_length == sizeof(size_t));
    893     return rsc->getMessageToClient(data, receiveLen, subID, data_length);
    894 }
    895 
    896 void rsi_ContextInitToClient(Context *rsc) {
    897     rsc->initToClient();
    898 }
    899 
    900 void rsi_ContextDeinitToClient(Context *rsc) {
    901     rsc->deinitToClient();
    902 }
    903 
    904 void rsi_ContextSendMessage(Context *rsc, uint32_t id, const uint8_t *data, size_t len) {
    905     rsc->sendMessageToClient(data, RS_MESSAGE_TO_CLIENT_USER, id, len, true);
    906 }
    907 
    908 // implementation of handcode LF_ObjDestroy
    909 // required so nObjDestroy can be run from finalizer without blocking
    910 void LF_ObjDestroy_handcode(const Context *rsc, RsAsyncVoidPtr objPtr) {
    911     if (((Context *)rsc)->isSynchronous()) {
    912         rsi_ObjDestroy((Context *)rsc, objPtr);
    913         return;
    914     }
    915 
    916     // struct has two parts:
    917     // RsPlaybackRemoteHeader (cmdID and bytes)
    918     // RS_CMD_ObjDestroy (ptr)
    919     struct destroyCmd {
    920         uint32_t cmdID;
    921         uint32_t bytes;
    922         RsAsyncVoidPtr ptr;
    923      };
    924 
    925     destroyCmd cmd;
    926     cmd.cmdID = RS_CMD_ID_ObjDestroy;
    927     cmd.bytes = sizeof(RsAsyncVoidPtr);
    928     cmd.ptr = objPtr;
    929     ThreadIO *io = &((Context *)rsc)->mIO;
    930     io->coreWrite((void*)&cmd, sizeof(destroyCmd));
    931 
    932 }
    933 
    934 }
    935 }
    936 
    937 extern "C" RsContext rsContextCreate(RsDevice vdev, uint32_t version, uint32_t sdkVersion,
    938                                      RsContextType ct, uint32_t flags) {
    939     //ALOGV("rsContextCreate dev=%p", vdev);
    940     Device * dev = static_cast<Device *>(vdev);
    941     Context *rsc = Context::createContext(dev, nullptr, ct, flags);
    942     if (rsc) {
    943         rsc->setTargetSdkVersion(sdkVersion);
    944     }
    945     return rsc;
    946 }
    947 
    948 extern "C" void rsaContextSetNativeLibDir(RsContext con, char *libDir, size_t length) {
    949 #ifdef RS_COMPATIBILITY_LIB
    950     Context *rsc = static_cast<Context *>(con);
    951     rsc->setNativeLibDir(libDir, length);
    952 #endif
    953 }
    954 
    955 #ifndef RS_COMPATIBILITY_LIB
    956 RsContext rsContextCreateGL(RsDevice vdev, uint32_t version,
    957                             uint32_t sdkVersion, RsSurfaceConfig sc,
    958                             uint32_t dpi) {
    959     //ALOGV("rsContextCreateGL dev=%p", vdev);
    960     Device * dev = static_cast<Device *>(vdev);
    961     Context *rsc = Context::createContext(dev, &sc);
    962     if (rsc) {
    963         rsc->setTargetSdkVersion(sdkVersion);
    964         rsc->setDPI(dpi);
    965     }
    966     //ALOGV("%p rsContextCreateGL ret", rsc);
    967     return rsc;
    968 }
    969 #endif
    970 
    971 // Only to be called at a3d load time, before object is visible to user
    972 // not thread safe
    973 void rsaGetName(RsContext con, void * obj, const char **name) {
    974     ObjectBase *ob = static_cast<ObjectBase *>(obj);
    975     (*name) = ob->getName();
    976 }
    977