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