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