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