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