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