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(__ANDROID__)
     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(__ANDROID__)
    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.mLogReduce = getProp("debug.rs.reduce");
    263     rsc->props.mDebugReduceSplitAccum = getProp("debug.rs.reduce-split-accum") != 0;
    264     rsc->props.mDebugMaxThreads = getProp("debug.rs.max-threads");
    265 
    266     if (getProp("debug.rs.debug") != 0) {
    267         ALOGD("Forcing debug context due to debug.rs.debug.");
    268         rsc->mContextType = RS_CONTEXT_TYPE_DEBUG;
    269         rsc->mForceCpu = true;
    270     }
    271 
    272     bool forceCpu = getProp("debug.rs.default-CPU-driver") != 0;
    273     if (forceCpu) {
    274         ALOGD("Skipping hardware driver and loading default CPU driver");
    275         rsc->mForceCpu = true;
    276     }
    277 
    278     rsc->mForceCpu |= rsc->mIsGraphicsContext;
    279     rsc->loadDriver(rsc->mForceCpu);
    280 
    281     if (!rsc->isSynchronous()) {
    282         // Due to legacy we default to normal_graphics
    283         // setPriority will make the adjustments as needed.
    284         rsc->setPriority(RS_THREAD_PRIORITY_NORMAL_GRAPHICS);
    285     }
    286 
    287 #ifndef RS_COMPATIBILITY_LIB
    288     if (rsc->mIsGraphicsContext) {
    289         if (!rsc->initGLThread()) {
    290             rsc->setError(RS_ERROR_OUT_OF_MEMORY, "Failed initializing GL");
    291             return nullptr;
    292         }
    293 
    294         rsc->mStateRaster.init(rsc);
    295         rsc->setProgramRaster(nullptr);
    296         rsc->mStateVertex.init(rsc);
    297         rsc->setProgramVertex(nullptr);
    298         rsc->mStateFragment.init(rsc);
    299         rsc->setProgramFragment(nullptr);
    300         rsc->mStateFragmentStore.init(rsc);
    301         rsc->setProgramStore(nullptr);
    302         rsc->mStateFont.init(rsc);
    303         rsc->setFont(nullptr);
    304         rsc->mStateSampler.init(rsc);
    305         rsc->mFBOCache.init(rsc);
    306     }
    307 #endif
    308 
    309     rsc->mRunning = true;
    310 
    311     if (rsc->isSynchronous()) {
    312         return nullptr;
    313     }
    314 
    315     if (!rsc->mIsGraphicsContext) {
    316         while (!rsc->mExit) {
    317             rsc->mIO.playCoreCommands(rsc, -1);
    318         }
    319 #ifndef RS_COMPATIBILITY_LIB
    320     } else {
    321 #ifndef ANDROID_RS_SERIALIZE
    322         DisplayEventReceiver displayEvent;
    323         DisplayEventReceiver::Event eventBuffer[1];
    324 #endif
    325         int vsyncRate = 0;
    326         int targetRate = 0;
    327 
    328         bool drawOnce = false;
    329         while (!rsc->mExit) {
    330             rsc->timerSet(RS_TIMER_IDLE);
    331 
    332 #ifndef ANDROID_RS_SERIALIZE
    333             if (!rsc->mRootScript.get() || !rsc->mHasSurface || rsc->mPaused) {
    334                 targetRate = 0;
    335             }
    336 
    337             if (vsyncRate != targetRate) {
    338                 displayEvent.setVsyncRate(targetRate);
    339                 vsyncRate = targetRate;
    340             }
    341             if (targetRate) {
    342                 drawOnce |= rsc->mIO.playCoreCommands(rsc, displayEvent.getFd());
    343                 while (displayEvent.getEvents(eventBuffer, 1) != 0) {
    344                     //ALOGE("vs2 time past %lld", (rsc->getTime() - eventBuffer[0].header.timestamp) / 1000000);
    345                 }
    346             } else
    347 #endif
    348             {
    349                 drawOnce |= rsc->mIO.playCoreCommands(rsc, -1);
    350             }
    351 
    352             if ((rsc->mRootScript.get() != nullptr) && rsc->mHasSurface &&
    353                 (targetRate || drawOnce) && !rsc->mPaused) {
    354 
    355                 drawOnce = false;
    356                 targetRate = ((rsc->runRootScript() + 15) / 16);
    357 
    358                 if (rsc->props.mLogVisual) {
    359                     rsc->displayDebugStats();
    360                 }
    361 
    362                 rsc->timerSet(RS_TIMER_CLEAR_SWAP);
    363                 rsc->mHal.funcs.swap(rsc);
    364                 rsc->timerFrame();
    365                 rsc->timerSet(RS_TIMER_INTERNAL);
    366                 rsc->timerPrint();
    367                 rsc->timerReset();
    368             }
    369         }
    370 #endif
    371     }
    372 
    373     //ALOGV("%p RS Thread exiting", rsc);
    374 
    375 #ifndef RS_COMPATIBILITY_LIB
    376     if (rsc->mIsGraphicsContext) {
    377         pthread_mutex_lock(&gInitMutex);
    378         rsc->deinitEGL();
    379         pthread_mutex_unlock(&gInitMutex);
    380     }
    381 #endif
    382 
    383     //ALOGV("%p RS Thread exited", rsc);
    384     return nullptr;
    385 }
    386 
    387 void Context::destroyWorkerThreadResources() {
    388     //ALOGV("destroyWorkerThreadResources 1");
    389     ObjectBase::zeroAllUserRef(this);
    390 #ifndef RS_COMPATIBILITY_LIB
    391     if (mIsGraphicsContext) {
    392          mRaster.clear();
    393          mFragment.clear();
    394          mVertex.clear();
    395          mFragmentStore.clear();
    396          mFont.clear();
    397          mRootScript.clear();
    398          mStateRaster.deinit(this);
    399          mStateVertex.deinit(this);
    400          mStateFragment.deinit(this);
    401          mStateFragmentStore.deinit(this);
    402          mStateFont.deinit(this);
    403          mStateSampler.deinit(this);
    404          mFBOCache.deinit(this);
    405     }
    406 #endif
    407     ObjectBase::freeAllChildren(this);
    408     mExit = true;
    409     //ALOGV("destroyWorkerThreadResources 2");
    410 }
    411 
    412 void Context::printWatchdogInfo(void *ctx) {
    413     Context *rsc = (Context *)ctx;
    414     if (rsc->watchdog.command && rsc->watchdog.file) {
    415         ALOGE("RS watchdog timeout: %i  %s  line %i %s", rsc->watchdog.inRoot,
    416              rsc->watchdog.command, rsc->watchdog.line, rsc->watchdog.file);
    417     } else {
    418         ALOGE("RS watchdog timeout: %i", rsc->watchdog.inRoot);
    419     }
    420 }
    421 
    422 
    423 void Context::setPriority(int32_t p) {
    424     switch (p) {
    425     // The public API will always send NORMAL_GRAPHICS
    426     // for normal, we adjust here
    427     case RS_THREAD_PRIORITY_NORMAL_GRAPHICS:
    428         if (mIsGraphicsContext) {
    429             break;
    430         } else {
    431             if (mHal.flags & RS_CONTEXT_LOW_LATENCY) {
    432                 p = RS_THREAD_PRIORITY_LOW_LATENCY;
    433             } else {
    434                 p = RS_THREAD_PRIORITY_NORMAL;
    435             }
    436         }
    437     case RS_THREAD_PRIORITY_LOW:
    438         break;
    439     }
    440 
    441     // Note: If we put this in the proper "background" policy
    442     // the wallpapers can become completly unresponsive at times.
    443     // This is probably not what we want for something the user is actively
    444     // looking at.
    445     mThreadPriority = p;
    446     setpriority(PRIO_PROCESS, mNativeThreadId, p);
    447     mHal.funcs.setPriority(this, mThreadPriority);
    448 }
    449 
    450 Context::Context() {
    451     mDev = nullptr;
    452     mRunning = false;
    453     mExit = false;
    454     mPaused = false;
    455     mObjHead = nullptr;
    456     mError = RS_ERROR_NONE;
    457     mTargetSdkVersion = 14;
    458     mDPI = 96;
    459     mIsContextLite = false;
    460     memset(&watchdog, 0, sizeof(watchdog));
    461     memset(&mHal, 0, sizeof(mHal));
    462     mForceCpu = false;
    463     mContextType = RS_CONTEXT_TYPE_NORMAL;
    464     mOptLevel = 3;
    465     mSynchronous = false;
    466     mFatalErrorOccured = false;
    467 
    468     memset(mCacheDir, 0, sizeof(mCacheDir));
    469 #ifdef RS_COMPATIBILITY_LIB
    470     memset(nativeLibDir, 0, sizeof(nativeLibDir));
    471 #endif
    472 }
    473 
    474 void Context::setCacheDir(const char * cacheDir_arg, uint32_t length) {
    475     if (!hasSetCacheDir) {
    476         if (length <= PATH_MAX) {
    477             memcpy(mCacheDir, cacheDir_arg, length);
    478             mCacheDir[length] = 0;
    479             hasSetCacheDir = true;
    480         } else {
    481             setError(RS_ERROR_BAD_VALUE, "Invalid path");
    482         }
    483     }
    484 }
    485 
    486 void Context::waitForDebugger() {
    487     while (!gDebuggerPresent) {
    488         sleep(0);
    489     }
    490 }
    491 
    492 Context * Context::createContext(Device *dev, const RsSurfaceConfig *sc,
    493                                  RsContextType ct, uint32_t flags) {
    494     Context * rsc = new Context();
    495 
    496     if (flags & RS_CONTEXT_LOW_LATENCY) {
    497         rsc->mForceCpu = true;
    498     }
    499     if (flags & RS_CONTEXT_SYNCHRONOUS) {
    500         rsc->mSynchronous = true;
    501     }
    502     rsc->mContextType = ct;
    503     rsc->mHal.flags = flags;
    504 
    505     if (!rsc->initContext(dev, sc)) {
    506         delete rsc;
    507         return nullptr;
    508     }
    509 
    510     if (flags & RS_CONTEXT_WAIT_FOR_ATTACH) {
    511         rsc->waitForDebugger();
    512     }
    513 
    514     return rsc;
    515 }
    516 
    517 Context * Context::createContextLite() {
    518     Context * rsc = new Context();
    519     rsc->mIsContextLite = true;
    520     return rsc;
    521 }
    522 
    523 bool Context::initContext(Device *dev, const RsSurfaceConfig *sc) {
    524     pthread_mutex_lock(&gInitMutex);
    525 
    526     mIO.init();
    527     mIO.setTimeoutCallback(printWatchdogInfo, this, 2e9);
    528 
    529     dev->addContext(this);
    530     mDev = dev;
    531     if (sc) {
    532         mUserSurfaceConfig = *sc;
    533     } else {
    534         memset(&mUserSurfaceConfig, 0, sizeof(mUserSurfaceConfig));
    535     }
    536 
    537     mIsGraphicsContext = sc != nullptr;
    538 
    539     int status;
    540     pthread_attr_t threadAttr;
    541 
    542     pthread_mutex_unlock(&gInitMutex);
    543 
    544     // Global init done at this point.
    545 
    546     status = pthread_attr_init(&threadAttr);
    547     if (status) {
    548         ALOGE("Failed to init thread attribute.");
    549         return false;
    550     }
    551 
    552     mHasSurface = false;
    553     mDriverName = NULL;
    554 
    555     timerInit();
    556     timerSet(RS_TIMER_INTERNAL);
    557     if (mSynchronous) {
    558         threadProc(this);
    559 
    560         if (mError != RS_ERROR_NONE) {
    561             ALOGE("Errors during thread init (sync mode)");
    562             return false;
    563         }
    564     } else {
    565         status = pthread_create(&mThreadId, &threadAttr, threadProc, this);
    566         if (status) {
    567             ALOGE("Failed to start rs context thread.");
    568             return false;
    569         }
    570         while (!mRunning && (mError == RS_ERROR_NONE)) {
    571             usleep(100);
    572         }
    573 
    574         if (mError != RS_ERROR_NONE) {
    575             ALOGE("Errors during thread init");
    576             return false;
    577         }
    578 
    579         pthread_attr_destroy(&threadAttr);
    580     }
    581     return true;
    582 }
    583 
    584 Context::~Context() {
    585     if (!mIsContextLite) {
    586         mPaused = false;
    587         void *res;
    588 
    589         mIO.shutdown();
    590         if (!mSynchronous) {
    591             pthread_join(mThreadId, &res);
    592         }
    593         rsAssert(mExit);
    594 
    595         if (mHal.funcs.shutdownDriver && mHal.drv) {
    596             mHal.funcs.shutdownDriver(this);
    597         }
    598 
    599         // Global structure cleanup.
    600         pthread_mutex_lock(&gInitMutex);
    601         if (mDev) {
    602             mDev->removeContext(this);
    603         }
    604         pthread_mutex_unlock(&gInitMutex);
    605     }
    606 
    607     delete mDev;
    608 }
    609 
    610 #ifndef RS_COMPATIBILITY_LIB
    611 void Context::setSurface(uint32_t w, uint32_t h, RsNativeWindow sur) {
    612     rsAssert(mIsGraphicsContext);
    613     mHal.funcs.setSurface(this, w, h, sur);
    614 
    615     mHasSurface = sur != nullptr;
    616     mWidth = w;
    617     mHeight = h;
    618 
    619     if (mWidth && mHeight) {
    620         mStateVertex.updateSize(this);
    621         mFBOCache.updateSize();
    622     }
    623 }
    624 
    625 uint32_t Context::getCurrentSurfaceWidth() const {
    626     for (uint32_t i = 0; i < mFBOCache.mHal.state.colorTargetsCount; i ++) {
    627         if (mFBOCache.mHal.state.colorTargets[i] != nullptr) {
    628             return mFBOCache.mHal.state.colorTargets[i]->getType()->getDimX();
    629         }
    630     }
    631     if (mFBOCache.mHal.state.depthTarget != nullptr) {
    632         return mFBOCache.mHal.state.depthTarget->getType()->getDimX();
    633     }
    634     return mWidth;
    635 }
    636 
    637 uint32_t Context::getCurrentSurfaceHeight() const {
    638     for (uint32_t i = 0; i < mFBOCache.mHal.state.colorTargetsCount; i ++) {
    639         if (mFBOCache.mHal.state.colorTargets[i] != nullptr) {
    640             return mFBOCache.mHal.state.colorTargets[i]->getType()->getDimY();
    641         }
    642     }
    643     if (mFBOCache.mHal.state.depthTarget != nullptr) {
    644         return mFBOCache.mHal.state.depthTarget->getType()->getDimY();
    645     }
    646     return mHeight;
    647 }
    648 
    649 void Context::pause() {
    650     rsAssert(mIsGraphicsContext);
    651     mPaused = true;
    652 }
    653 
    654 void Context::resume() {
    655     rsAssert(mIsGraphicsContext);
    656     mPaused = false;
    657 }
    658 
    659 void Context::setRootScript(Script *s) {
    660     rsAssert(mIsGraphicsContext);
    661     mRootScript.set(s);
    662 }
    663 
    664 void Context::setProgramStore(ProgramStore *pfs) {
    665     rsAssert(mIsGraphicsContext);
    666     if (pfs == nullptr) {
    667         mFragmentStore.set(mStateFragmentStore.mDefault);
    668     } else {
    669         mFragmentStore.set(pfs);
    670     }
    671 }
    672 
    673 void Context::setProgramFragment(ProgramFragment *pf) {
    674     rsAssert(mIsGraphicsContext);
    675     if (pf == nullptr) {
    676         mFragment.set(mStateFragment.mDefault);
    677     } else {
    678         mFragment.set(pf);
    679     }
    680 }
    681 
    682 void Context::setProgramRaster(ProgramRaster *pr) {
    683     rsAssert(mIsGraphicsContext);
    684     if (pr == nullptr) {
    685         mRaster.set(mStateRaster.mDefault);
    686     } else {
    687         mRaster.set(pr);
    688     }
    689 }
    690 
    691 void Context::setProgramVertex(ProgramVertex *pv) {
    692     rsAssert(mIsGraphicsContext);
    693     if (pv == nullptr) {
    694         mVertex.set(mStateVertex.mDefault);
    695     } else {
    696         mVertex.set(pv);
    697     }
    698 }
    699 
    700 void Context::setFont(Font *f) {
    701     rsAssert(mIsGraphicsContext);
    702     if (f == nullptr) {
    703         mFont.set(mStateFont.mDefault);
    704     } else {
    705         mFont.set(f);
    706     }
    707 }
    708 #endif
    709 
    710 void Context::finish() {
    711     if (mHal.funcs.finish) {
    712         mHal.funcs.finish(this);
    713     }
    714 }
    715 
    716 void Context::assignName(ObjectBase *obj, const char *name, uint32_t len) {
    717     rsAssert(!obj->getName());
    718     obj->setName(name, len);
    719     mNames.add(obj);
    720 }
    721 
    722 void Context::removeName(ObjectBase *obj) {
    723     for (size_t ct=0; ct < mNames.size(); ct++) {
    724         if (obj == mNames[ct]) {
    725             mNames.removeAt(ct);
    726             return;
    727         }
    728     }
    729 }
    730 
    731 RsMessageToClientType Context::peekMessageToClient(size_t *receiveLen, uint32_t *subID) {
    732     return (RsMessageToClientType)mIO.getClientHeader(receiveLen, subID);
    733 }
    734 
    735 RsMessageToClientType Context::getMessageToClient(void *data, size_t *receiveLen, uint32_t *subID, size_t bufferLen) {
    736     return (RsMessageToClientType)mIO.getClientPayload(data, receiveLen, subID, bufferLen);
    737 }
    738 
    739 bool Context::sendMessageToClient(const void *data, RsMessageToClientType cmdID,
    740                                   uint32_t subID, size_t len, bool waitForSpace) const {
    741 
    742     pthread_mutex_lock(&gMessageMutex);
    743     bool ret = mIO.sendToClient(cmdID, subID, data, len, waitForSpace);
    744     pthread_mutex_unlock(&gMessageMutex);
    745     return ret;
    746 }
    747 
    748 void Context::initToClient() {
    749     while (!mRunning) {
    750         usleep(100);
    751     }
    752 }
    753 
    754 void Context::deinitToClient() {
    755     mIO.clientShutdown();
    756 }
    757 
    758 void Context::setError(RsError e, const char *msg) const {
    759     mError = e;
    760 
    761     if (mError >= RS_ERROR_FATAL_DEBUG) {
    762         // If a FATAL error occurred, set the flag to indicate the process
    763         // will be goign down
    764         mFatalErrorOccured = true;
    765     }
    766 
    767     sendMessageToClient(msg, RS_MESSAGE_TO_CLIENT_ERROR, e, strlen(msg) + 1, true);
    768 }
    769 
    770 
    771 void Context::dumpDebug() const {
    772     ALOGE("RS Context debug %p", this);
    773     ALOGE("RS Context debug");
    774 
    775     ALOGE(" RS width %i, height %i", mWidth, mHeight);
    776     ALOGE(" RS running %i, exit %i, paused %i", mRunning, mExit, mPaused);
    777     ALOGE(" RS pThreadID %li, nativeThreadID %i", (long int)mThreadId, mNativeThreadId);
    778 }
    779 
    780 ///////////////////////////////////////////////////////////////////////////////////////////
    781 //
    782 
    783 namespace android {
    784 namespace renderscript {
    785 
    786 void rsi_ContextFinish(Context *rsc) {
    787     rsc->finish();
    788 }
    789 
    790 void rsi_ContextBindRootScript(Context *rsc, RsScript vs) {
    791 #ifndef RS_COMPATIBILITY_LIB
    792     Script *s = static_cast<Script *>(vs);
    793     rsc->setRootScript(s);
    794 #endif
    795 }
    796 
    797 void rsi_ContextSetCacheDir(Context *rsc, const char *cacheDir, size_t cacheDir_length) {
    798     rsc->setCacheDir(cacheDir, cacheDir_length);
    799 }
    800 
    801 void rsi_ContextBindSampler(Context *rsc, uint32_t slot, RsSampler vs) {
    802     Sampler *s = static_cast<Sampler *>(vs);
    803 
    804     if (slot > RS_MAX_SAMPLER_SLOT) {
    805         ALOGE("Invalid sampler slot");
    806         return;
    807     }
    808 
    809     s->bindToContext(&rsc->mStateSampler, slot);
    810 }
    811 
    812 #ifndef RS_COMPATIBILITY_LIB
    813 void rsi_ContextBindProgramStore(Context *rsc, RsProgramStore vpfs) {
    814     ProgramStore *pfs = static_cast<ProgramStore *>(vpfs);
    815     rsc->setProgramStore(pfs);
    816 }
    817 
    818 void rsi_ContextBindProgramFragment(Context *rsc, RsProgramFragment vpf) {
    819     ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
    820     rsc->setProgramFragment(pf);
    821 }
    822 
    823 void rsi_ContextBindProgramRaster(Context *rsc, RsProgramRaster vpr) {
    824     ProgramRaster *pr = static_cast<ProgramRaster *>(vpr);
    825     rsc->setProgramRaster(pr);
    826 }
    827 
    828 void rsi_ContextBindProgramVertex(Context *rsc, RsProgramVertex vpv) {
    829     ProgramVertex *pv = static_cast<ProgramVertex *>(vpv);
    830     rsc->setProgramVertex(pv);
    831 }
    832 
    833 void rsi_ContextBindFont(Context *rsc, RsFont vfont) {
    834     Font *font = static_cast<Font *>(vfont);
    835     rsc->setFont(font);
    836 }
    837 #endif
    838 
    839 void rsi_AssignName(Context *rsc, RsObjectBase obj, const char *name, size_t name_length) {
    840     ObjectBase *ob = static_cast<ObjectBase *>(obj);
    841     rsc->assignName(ob, name, name_length);
    842 }
    843 
    844 void rsi_ObjDestroy(Context *rsc, void *optr) {
    845     ObjectBase *ob = static_cast<ObjectBase *>(optr);
    846     rsc->removeName(ob);
    847     ob->decUserRef();
    848 }
    849 
    850 #ifndef RS_COMPATIBILITY_LIB
    851 void rsi_ContextPause(Context *rsc) {
    852     rsc->pause();
    853 }
    854 
    855 void rsi_ContextResume(Context *rsc) {
    856     rsc->resume();
    857 }
    858 
    859 void rsi_ContextSetSurface(Context *rsc, uint32_t w, uint32_t h, RsNativeWindow sur) {
    860     rsc->setSurface(w, h, sur);
    861 }
    862 #endif
    863 
    864 void rsi_ContextSetPriority(Context *rsc, int32_t p) {
    865     rsc->setPriority(p);
    866 }
    867 
    868 void rsi_ContextDump(Context *rsc, int32_t bits) {
    869     ObjectBase::dumpAll(rsc);
    870 }
    871 
    872 void rsi_ContextDestroyWorker(Context *rsc) {
    873     rsc->destroyWorkerThreadResources();
    874 }
    875 
    876 void rsi_ContextDestroy(Context *rsc) {
    877     //ALOGE("%p rsContextDestroy", rsc);
    878     rsc->destroyWorkerThreadResources();
    879     delete rsc;
    880     //ALOGV("%p rsContextDestroy done", rsc);
    881 }
    882 
    883 RsMessageToClientType rsi_ContextPeekMessage(Context *rsc,
    884                                            size_t * receiveLen, size_t receiveLen_length,
    885                                            uint32_t * subID, size_t subID_length) {
    886     return rsc->peekMessageToClient(receiveLen, subID);
    887 }
    888 
    889 RsMessageToClientType rsi_ContextGetMessage(Context *rsc, void * data, size_t data_length,
    890                                           size_t * receiveLen, size_t receiveLen_length,
    891                                           uint32_t * subID, size_t subID_length) {
    892     rsAssert(subID_length == sizeof(uint32_t));
    893     rsAssert(receiveLen_length == sizeof(size_t));
    894     return rsc->getMessageToClient(data, receiveLen, subID, data_length);
    895 }
    896 
    897 void rsi_ContextInitToClient(Context *rsc) {
    898     rsc->initToClient();
    899 }
    900 
    901 void rsi_ContextDeinitToClient(Context *rsc) {
    902     rsc->deinitToClient();
    903 }
    904 
    905 void rsi_ContextSendMessage(Context *rsc, uint32_t id, const uint8_t *data, size_t len) {
    906     rsc->sendMessageToClient(data, RS_MESSAGE_TO_CLIENT_USER, id, len, true);
    907 }
    908 
    909 // implementation of handcode LF_ObjDestroy
    910 // required so nObjDestroy can be run from finalizer without blocking
    911 void LF_ObjDestroy_handcode(const Context *rsc, RsAsyncVoidPtr objPtr) {
    912     if (((Context *)rsc)->isSynchronous()) {
    913         rsi_ObjDestroy((Context *)rsc, objPtr);
    914         return;
    915     }
    916 
    917     // struct has two parts:
    918     // RsPlaybackRemoteHeader (cmdID and bytes)
    919     // RS_CMD_ObjDestroy (ptr)
    920     struct destroyCmd {
    921         uint32_t cmdID;
    922         uint32_t bytes;
    923         RsAsyncVoidPtr ptr;
    924      };
    925 
    926     destroyCmd cmd;
    927     cmd.cmdID = RS_CMD_ID_ObjDestroy;
    928     cmd.bytes = sizeof(RsAsyncVoidPtr);
    929     cmd.ptr = objPtr;
    930     ThreadIO *io = &((Context *)rsc)->mIO;
    931     io->coreWrite((void*)&cmd, sizeof(destroyCmd));
    932 
    933 }
    934 
    935 }
    936 }
    937