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 *gInternalDebuggerPresent = nullptr;
     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     // Wait until this symbol has been properly set up, and the flag itself is
    488     // set to a non-zero value.
    489     while (!gInternalDebuggerPresent || !*gInternalDebuggerPresent) {
    490         sleep(0);
    491     }
    492 }
    493 
    494 Context * Context::createContext(Device *dev, const RsSurfaceConfig *sc,
    495                                  RsContextType ct, uint32_t flags) {
    496     Context * rsc = new Context();
    497 
    498     if (flags & RS_CONTEXT_LOW_LATENCY) {
    499         rsc->mForceCpu = true;
    500     }
    501     if (flags & RS_CONTEXT_SYNCHRONOUS) {
    502         rsc->mSynchronous = true;
    503     }
    504     rsc->mContextType = ct;
    505     rsc->mHal.flags = flags;
    506 
    507     if (!rsc->initContext(dev, sc)) {
    508         delete rsc;
    509         return nullptr;
    510     }
    511 
    512     if (flags & RS_CONTEXT_WAIT_FOR_ATTACH) {
    513         rsc->waitForDebugger();
    514     }
    515 
    516     return rsc;
    517 }
    518 
    519 Context * Context::createContextLite() {
    520     Context * rsc = new Context();
    521     rsc->mIsContextLite = true;
    522     return rsc;
    523 }
    524 
    525 bool Context::initContext(Device *dev, const RsSurfaceConfig *sc) {
    526     pthread_mutex_lock(&gInitMutex);
    527 
    528     mIO.init();
    529     mIO.setTimeoutCallback(printWatchdogInfo, this, 2e9);
    530 
    531     dev->addContext(this);
    532     mDev = dev;
    533     if (sc) {
    534         mUserSurfaceConfig = *sc;
    535     } else {
    536         memset(&mUserSurfaceConfig, 0, sizeof(mUserSurfaceConfig));
    537     }
    538 
    539     mIsGraphicsContext = sc != nullptr;
    540 
    541     int status;
    542     pthread_attr_t threadAttr;
    543 
    544     pthread_mutex_unlock(&gInitMutex);
    545 
    546     // Global init done at this point.
    547 
    548     status = pthread_attr_init(&threadAttr);
    549     if (status) {
    550         ALOGE("Failed to init thread attribute.");
    551         return false;
    552     }
    553 
    554     mHasSurface = false;
    555     mDriverName = NULL;
    556 
    557     timerInit();
    558     timerSet(RS_TIMER_INTERNAL);
    559     if (mSynchronous) {
    560         threadProc(this);
    561 
    562         if (mError != RS_ERROR_NONE) {
    563             ALOGE("Errors during thread init (sync mode)");
    564             return false;
    565         }
    566     } else {
    567         status = pthread_create(&mThreadId, &threadAttr, threadProc, this);
    568         if (status) {
    569             ALOGE("Failed to start rs context thread.");
    570             return false;
    571         }
    572         while (!mRunning && (mError == RS_ERROR_NONE)) {
    573             usleep(100);
    574         }
    575 
    576         if (mError != RS_ERROR_NONE) {
    577             ALOGE("Errors during thread init");
    578             return false;
    579         }
    580 
    581         pthread_attr_destroy(&threadAttr);
    582     }
    583     return true;
    584 }
    585 
    586 Context::~Context() {
    587     if (!mIsContextLite) {
    588         mPaused = false;
    589         void *res;
    590 
    591         mIO.shutdown();
    592         if (!mSynchronous) {
    593             pthread_join(mThreadId, &res);
    594         }
    595         rsAssert(mExit);
    596 
    597         if (mHal.funcs.shutdownDriver && mHal.drv) {
    598             mHal.funcs.shutdownDriver(this);
    599         }
    600 
    601         // Global structure cleanup.
    602         pthread_mutex_lock(&gInitMutex);
    603         if (mDev) {
    604             mDev->removeContext(this);
    605         }
    606         pthread_mutex_unlock(&gInitMutex);
    607     }
    608 
    609     delete mDev;
    610 }
    611 
    612 #ifndef RS_COMPATIBILITY_LIB
    613 void Context::setSurface(uint32_t w, uint32_t h, RsNativeWindow sur) {
    614     rsAssert(mIsGraphicsContext);
    615     mHal.funcs.setSurface(this, w, h, sur);
    616 
    617     mHasSurface = sur != nullptr;
    618     mWidth = w;
    619     mHeight = h;
    620 
    621     if (mWidth && mHeight) {
    622         mStateVertex.updateSize(this);
    623         mFBOCache.updateSize();
    624     }
    625 }
    626 
    627 uint32_t Context::getCurrentSurfaceWidth() const {
    628     for (uint32_t i = 0; i < mFBOCache.mHal.state.colorTargetsCount; i ++) {
    629         if (mFBOCache.mHal.state.colorTargets[i] != nullptr) {
    630             return mFBOCache.mHal.state.colorTargets[i]->getType()->getDimX();
    631         }
    632     }
    633     if (mFBOCache.mHal.state.depthTarget != nullptr) {
    634         return mFBOCache.mHal.state.depthTarget->getType()->getDimX();
    635     }
    636     return mWidth;
    637 }
    638 
    639 uint32_t Context::getCurrentSurfaceHeight() const {
    640     for (uint32_t i = 0; i < mFBOCache.mHal.state.colorTargetsCount; i ++) {
    641         if (mFBOCache.mHal.state.colorTargets[i] != nullptr) {
    642             return mFBOCache.mHal.state.colorTargets[i]->getType()->getDimY();
    643         }
    644     }
    645     if (mFBOCache.mHal.state.depthTarget != nullptr) {
    646         return mFBOCache.mHal.state.depthTarget->getType()->getDimY();
    647     }
    648     return mHeight;
    649 }
    650 
    651 void Context::pause() {
    652     rsAssert(mIsGraphicsContext);
    653     mPaused = true;
    654 }
    655 
    656 void Context::resume() {
    657     rsAssert(mIsGraphicsContext);
    658     mPaused = false;
    659 }
    660 
    661 void Context::setRootScript(Script *s) {
    662     rsAssert(mIsGraphicsContext);
    663     mRootScript.set(s);
    664 }
    665 
    666 void Context::setProgramStore(ProgramStore *pfs) {
    667     rsAssert(mIsGraphicsContext);
    668     if (pfs == nullptr) {
    669         mFragmentStore.set(mStateFragmentStore.mDefault);
    670     } else {
    671         mFragmentStore.set(pfs);
    672     }
    673 }
    674 
    675 void Context::setProgramFragment(ProgramFragment *pf) {
    676     rsAssert(mIsGraphicsContext);
    677     if (pf == nullptr) {
    678         mFragment.set(mStateFragment.mDefault);
    679     } else {
    680         mFragment.set(pf);
    681     }
    682 }
    683 
    684 void Context::setProgramRaster(ProgramRaster *pr) {
    685     rsAssert(mIsGraphicsContext);
    686     if (pr == nullptr) {
    687         mRaster.set(mStateRaster.mDefault);
    688     } else {
    689         mRaster.set(pr);
    690     }
    691 }
    692 
    693 void Context::setProgramVertex(ProgramVertex *pv) {
    694     rsAssert(mIsGraphicsContext);
    695     if (pv == nullptr) {
    696         mVertex.set(mStateVertex.mDefault);
    697     } else {
    698         mVertex.set(pv);
    699     }
    700 }
    701 
    702 void Context::setFont(Font *f) {
    703     rsAssert(mIsGraphicsContext);
    704     if (f == nullptr) {
    705         mFont.set(mStateFont.mDefault);
    706     } else {
    707         mFont.set(f);
    708     }
    709 }
    710 #endif
    711 
    712 void Context::finish() {
    713     if (mHal.funcs.finish) {
    714         mHal.funcs.finish(this);
    715     }
    716 }
    717 
    718 void Context::assignName(ObjectBase *obj, const char *name, uint32_t len) {
    719     rsAssert(!obj->getName());
    720     obj->setName(name, len);
    721     mNames.add(obj);
    722 }
    723 
    724 void Context::removeName(ObjectBase *obj) {
    725     for (size_t ct=0; ct < mNames.size(); ct++) {
    726         if (obj == mNames[ct]) {
    727             mNames.removeAt(ct);
    728             return;
    729         }
    730     }
    731 }
    732 
    733 RsMessageToClientType Context::peekMessageToClient(size_t *receiveLen, uint32_t *subID) {
    734     return (RsMessageToClientType)mIO.getClientHeader(receiveLen, subID);
    735 }
    736 
    737 RsMessageToClientType Context::getMessageToClient(void *data, size_t *receiveLen, uint32_t *subID, size_t bufferLen) {
    738     return (RsMessageToClientType)mIO.getClientPayload(data, receiveLen, subID, bufferLen);
    739 }
    740 
    741 bool Context::sendMessageToClient(const void *data, RsMessageToClientType cmdID,
    742                                   uint32_t subID, size_t len, bool waitForSpace) const {
    743 
    744     pthread_mutex_lock(&gMessageMutex);
    745     bool ret = mIO.sendToClient(cmdID, subID, data, len, waitForSpace);
    746     pthread_mutex_unlock(&gMessageMutex);
    747     return ret;
    748 }
    749 
    750 void Context::initToClient() {
    751     while (!mRunning) {
    752         usleep(100);
    753     }
    754 }
    755 
    756 void Context::deinitToClient() {
    757     mIO.clientShutdown();
    758 }
    759 
    760 void Context::setError(RsError e, const char *msg) const {
    761     mError = e;
    762 
    763     if (mError >= RS_ERROR_FATAL_DEBUG) {
    764         // If a FATAL error occurred, set the flag to indicate the process
    765         // will be goign down
    766         mFatalErrorOccured = true;
    767     }
    768 
    769     sendMessageToClient(msg, RS_MESSAGE_TO_CLIENT_ERROR, e, strlen(msg) + 1, true);
    770 }
    771 
    772 
    773 void Context::dumpDebug() const {
    774     ALOGE("RS Context debug %p", this);
    775     ALOGE("RS Context debug");
    776 
    777     ALOGE(" RS width %i, height %i", mWidth, mHeight);
    778     ALOGE(" RS running %i, exit %i, paused %i", mRunning, mExit, mPaused);
    779     ALOGE(" RS pThreadID %li, nativeThreadID %i", (long int)mThreadId, mNativeThreadId);
    780 }
    781 
    782 ///////////////////////////////////////////////////////////////////////////////////////////
    783 //
    784 
    785 namespace android {
    786 namespace renderscript {
    787 
    788 void rsi_ContextFinish(Context *rsc) {
    789     rsc->finish();
    790 }
    791 
    792 void rsi_ContextBindRootScript(Context *rsc, RsScript vs) {
    793 #ifndef RS_COMPATIBILITY_LIB
    794     Script *s = static_cast<Script *>(vs);
    795     rsc->setRootScript(s);
    796 #endif
    797 }
    798 
    799 void rsi_ContextSetCacheDir(Context *rsc, const char *cacheDir, size_t cacheDir_length) {
    800     rsc->setCacheDir(cacheDir, cacheDir_length);
    801 }
    802 
    803 void rsi_ContextBindSampler(Context *rsc, uint32_t slot, RsSampler vs) {
    804     Sampler *s = static_cast<Sampler *>(vs);
    805 
    806     if (slot > RS_MAX_SAMPLER_SLOT) {
    807         ALOGE("Invalid sampler slot");
    808         return;
    809     }
    810 
    811     s->bindToContext(&rsc->mStateSampler, slot);
    812 }
    813 
    814 #ifndef RS_COMPATIBILITY_LIB
    815 void rsi_ContextBindProgramStore(Context *rsc, RsProgramStore vpfs) {
    816     ProgramStore *pfs = static_cast<ProgramStore *>(vpfs);
    817     rsc->setProgramStore(pfs);
    818 }
    819 
    820 void rsi_ContextBindProgramFragment(Context *rsc, RsProgramFragment vpf) {
    821     ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
    822     rsc->setProgramFragment(pf);
    823 }
    824 
    825 void rsi_ContextBindProgramRaster(Context *rsc, RsProgramRaster vpr) {
    826     ProgramRaster *pr = static_cast<ProgramRaster *>(vpr);
    827     rsc->setProgramRaster(pr);
    828 }
    829 
    830 void rsi_ContextBindProgramVertex(Context *rsc, RsProgramVertex vpv) {
    831     ProgramVertex *pv = static_cast<ProgramVertex *>(vpv);
    832     rsc->setProgramVertex(pv);
    833 }
    834 
    835 void rsi_ContextBindFont(Context *rsc, RsFont vfont) {
    836     Font *font = static_cast<Font *>(vfont);
    837     rsc->setFont(font);
    838 }
    839 #endif
    840 
    841 void rsi_AssignName(Context *rsc, RsObjectBase obj, const char *name, size_t name_length) {
    842     ObjectBase *ob = static_cast<ObjectBase *>(obj);
    843     rsc->assignName(ob, name, name_length);
    844 }
    845 
    846 void rsi_ObjDestroy(Context *rsc, void *optr) {
    847     ObjectBase *ob = static_cast<ObjectBase *>(optr);
    848     rsc->removeName(ob);
    849     ob->decUserRef();
    850 }
    851 
    852 #ifndef RS_COMPATIBILITY_LIB
    853 void rsi_ContextPause(Context *rsc) {
    854     rsc->pause();
    855 }
    856 
    857 void rsi_ContextResume(Context *rsc) {
    858     rsc->resume();
    859 }
    860 
    861 void rsi_ContextSetSurface(Context *rsc, uint32_t w, uint32_t h, RsNativeWindow sur) {
    862     rsc->setSurface(w, h, sur);
    863 }
    864 #endif
    865 
    866 void rsi_ContextSetPriority(Context *rsc, int32_t p) {
    867     rsc->setPriority(p);
    868 }
    869 
    870 void rsi_ContextDump(Context *rsc, int32_t bits) {
    871     ObjectBase::dumpAll(rsc);
    872 }
    873 
    874 void rsi_ContextDestroyWorker(Context *rsc) {
    875     rsc->destroyWorkerThreadResources();
    876 }
    877 
    878 void rsi_ContextDestroy(Context *rsc) {
    879     //ALOGE("%p rsContextDestroy", rsc);
    880     rsc->destroyWorkerThreadResources();
    881     delete rsc;
    882     //ALOGV("%p rsContextDestroy done", rsc);
    883 }
    884 
    885 RsMessageToClientType rsi_ContextPeekMessage(Context *rsc,
    886                                            size_t * receiveLen, size_t receiveLen_length,
    887                                            uint32_t * subID, size_t subID_length) {
    888     return rsc->peekMessageToClient(receiveLen, subID);
    889 }
    890 
    891 RsMessageToClientType rsi_ContextGetMessage(Context *rsc, void * data, size_t data_length,
    892                                           size_t * receiveLen, size_t receiveLen_length,
    893                                           uint32_t * subID, size_t subID_length) {
    894     rsAssert(subID_length == sizeof(uint32_t));
    895     rsAssert(receiveLen_length == sizeof(size_t));
    896     return rsc->getMessageToClient(data, receiveLen, subID, data_length);
    897 }
    898 
    899 void rsi_ContextInitToClient(Context *rsc) {
    900     rsc->initToClient();
    901 }
    902 
    903 void rsi_ContextDeinitToClient(Context *rsc) {
    904     rsc->deinitToClient();
    905 }
    906 
    907 void rsi_ContextSendMessage(Context *rsc, uint32_t id, const uint8_t *data, size_t len) {
    908     rsc->sendMessageToClient(data, RS_MESSAGE_TO_CLIENT_USER, id, len, true);
    909 }
    910 
    911 // implementation of handcode LF_ObjDestroy
    912 // required so nObjDestroy can be run from finalizer without blocking
    913 void LF_ObjDestroy_handcode(const Context *rsc, RsAsyncVoidPtr objPtr) {
    914     if (((Context *)rsc)->isSynchronous()) {
    915         rsi_ObjDestroy((Context *)rsc, objPtr);
    916         return;
    917     }
    918 
    919     // struct has two parts:
    920     // RsPlaybackRemoteHeader (cmdID and bytes)
    921     // RS_CMD_ObjDestroy (ptr)
    922     struct destroyCmd {
    923         uint32_t cmdID;
    924         uint32_t bytes;
    925         RsAsyncVoidPtr ptr;
    926      };
    927 
    928     destroyCmd cmd;
    929     cmd.cmdID = RS_CMD_ID_ObjDestroy;
    930     cmd.bytes = sizeof(RsAsyncVoidPtr);
    931     cmd.ptr = objPtr;
    932     ThreadIO *io = &((Context *)rsc)->mIO;
    933     io->coreWrite((void*)&cmd, sizeof(destroyCmd));
    934 
    935 }
    936 
    937 }
    938 }
    939