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