rsContext.cpp revision 230c94aa69e78ac4df2045a183f9a3f8c9eb9f60
1/*
2 * Copyright (C) 2009 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 "rsDevice.h"
18#include "rsContext.h"
19#include "rsThreadIO.h"
20#include <ui/FramebufferNativeWindow.h>
21#include <ui/EGLUtils.h>
22
23#include <cutils/properties.h>
24
25#include <GLES/gl.h>
26#include <GLES/glext.h>
27
28using namespace android;
29using namespace android::renderscript;
30
31pthread_key_t Context::gThreadTLSKey = 0;
32uint32_t Context::gThreadTLSKeyCount = 0;
33uint32_t Context::gGLContextCount = 0;
34pthread_mutex_t Context::gInitMutex = PTHREAD_MUTEX_INITIALIZER;
35
36static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
37    if (returnVal != EGL_TRUE) {
38        fprintf(stderr, "%s() returned %d\n", op, returnVal);
39    }
40
41    for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
42            = eglGetError()) {
43        fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error),
44                error);
45    }
46}
47
48void Context::initEGL()
49{
50    mEGL.mNumConfigs = -1;
51    EGLint configAttribs[128];
52    EGLint *configAttribsPtr = configAttribs;
53
54    memset(configAttribs, 0, sizeof(configAttribs));
55
56    configAttribsPtr[0] = EGL_SURFACE_TYPE;
57    configAttribsPtr[1] = EGL_WINDOW_BIT;
58    configAttribsPtr += 2;
59
60    if (mUseDepth) {
61        configAttribsPtr[0] = EGL_DEPTH_SIZE;
62        configAttribsPtr[1] = 16;
63        configAttribsPtr += 2;
64    }
65
66    if (mDev->mForceSW) {
67        configAttribsPtr[0] = EGL_CONFIG_CAVEAT;
68        configAttribsPtr[1] = EGL_SLOW_CONFIG;
69        configAttribsPtr += 2;
70    }
71
72    configAttribsPtr[0] = EGL_NONE;
73    rsAssert(configAttribsPtr < (configAttribs + (sizeof(configAttribs) / sizeof(EGLint))));
74
75    LOGV("initEGL start");
76    mEGL.mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
77    checkEglError("eglGetDisplay");
78
79    eglInitialize(mEGL.mDisplay, &mEGL.mMajorVersion, &mEGL.mMinorVersion);
80    checkEglError("eglInitialize");
81
82    status_t err = EGLUtils::selectConfigForNativeWindow(mEGL.mDisplay, configAttribs, mWndSurface, &mEGL.mConfig);
83    if (err) {
84       LOGE("couldn't find an EGLConfig matching the screen format\n");
85    }
86    //eglChooseConfig(mEGL.mDisplay, configAttribs, &mEGL.mConfig, 1, &mEGL.mNumConfigs);
87
88    if (mWndSurface) {
89        mEGL.mSurface = eglCreateWindowSurface(mEGL.mDisplay, mEGL.mConfig, mWndSurface, NULL);
90    } else {
91        mEGL.mSurface = eglCreateWindowSurface(mEGL.mDisplay, mEGL.mConfig,
92             android_createDisplaySurface(),
93             NULL);
94    }
95    checkEglError("eglCreateWindowSurface");
96    if (mEGL.mSurface == EGL_NO_SURFACE) {
97        LOGE("eglCreateWindowSurface returned EGL_NO_SURFACE");
98    }
99
100    mEGL.mContext = eglCreateContext(mEGL.mDisplay, mEGL.mConfig, EGL_NO_CONTEXT, NULL);
101    checkEglError("eglCreateContext");
102    if (mEGL.mContext == EGL_NO_CONTEXT) {
103        LOGE("eglCreateContext returned EGL_NO_CONTEXT");
104    }
105    gGLContextCount++;
106
107    EGLBoolean ret = eglMakeCurrent(mEGL.mDisplay, mEGL.mSurface, mEGL.mSurface, mEGL.mContext);
108    checkEglError("eglCreateContext", ret);
109    if (mEGL.mContext == EGL_NO_CONTEXT) {
110        LOGE("eglCreateContext returned EGL_NO_CONTEXT");
111    }
112
113    eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_WIDTH, &mEGL.mWidth);
114    eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_HEIGHT, &mEGL.mHeight);
115
116
117    mGL.mVersion = glGetString(GL_VERSION);
118    mGL.mVendor = glGetString(GL_VENDOR);
119    mGL.mRenderer = glGetString(GL_RENDERER);
120    mGL.mExtensions = glGetString(GL_EXTENSIONS);
121
122    LOGV("EGL Version %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion);
123    LOGV("GL Version %s", mGL.mVersion);
124    LOGV("GL Vendor %s", mGL.mVendor);
125    LOGV("GL Renderer %s", mGL.mRenderer);
126    LOGV("GL Extensions %s", mGL.mExtensions);
127
128    if ((strlen((const char *)mGL.mVersion) < 12) || memcmp(mGL.mVersion, "OpenGL ES-CM", 12)) {
129        LOGE("Error, OpenGL ES Lite not supported");
130    } else {
131        sscanf((const char *)mGL.mVersion + 13, "%i.%i", &mGL.mMajorVersion, &mGL.mMinorVersion);
132    }
133}
134
135void Context::deinitEGL()
136{
137    EGLBoolean ret = eglMakeCurrent(mEGL.mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
138    checkEglError("eglCreateContext", ret);
139    if (mEGL.mContext == EGL_NO_CONTEXT) {
140        LOGE("eglCreateContext returned EGL_NO_CONTEXT");
141    }
142
143    eglDestroyContext(mEGL.mDisplay, mEGL.mContext);
144    checkEglError("eglDestroyContext");
145
146    gGLContextCount--;
147    if (!gGLContextCount) {
148        eglTerminate(mEGL.mDisplay);
149    }
150}
151
152
153bool Context::runScript(Script *s, uint32_t launchID)
154{
155    ObjectBaseRef<ProgramFragment> frag(mFragment);
156    ObjectBaseRef<ProgramVertex> vtx(mVertex);
157    ObjectBaseRef<ProgramFragmentStore> store(mFragmentStore);
158    ObjectBaseRef<ProgramRaster> raster(mRaster);
159
160    bool ret = s->run(this, launchID);
161
162    mFragment.set(frag);
163    mVertex.set(vtx);
164    mFragmentStore.set(store);
165    mRaster.set(raster);
166    return ret;
167}
168
169
170bool Context::runRootScript()
171{
172    if (props.mLogTimes) {
173        timerSet(RS_TIMER_CLEAR_SWAP);
174    }
175    rsAssert(mRootScript->mEnviroment.mIsRoot);
176
177    eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_WIDTH, &mEGL.mWidth);
178    eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_HEIGHT, &mEGL.mHeight);
179    glViewport(0, 0, mEGL.mWidth, mEGL.mHeight);
180    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
181
182    glClearColor(mRootScript->mEnviroment.mClearColor[0],
183                 mRootScript->mEnviroment.mClearColor[1],
184                 mRootScript->mEnviroment.mClearColor[2],
185                 mRootScript->mEnviroment.mClearColor[3]);
186    if (mUseDepth) {
187        glDepthMask(GL_TRUE);
188        glClearDepthf(mRootScript->mEnviroment.mClearDepth);
189        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
190    } else {
191        glClear(GL_COLOR_BUFFER_BIT);
192    }
193
194    if (this->props.mLogTimes) {
195        timerSet(RS_TIMER_SCRIPT);
196    }
197    mStateFragmentStore.mLast.clear();
198    bool ret = runScript(mRootScript.get(), 0);
199
200    GLenum err = glGetError();
201    if (err != GL_NO_ERROR) {
202        LOGE("Pending GL Error, 0x%x", err);
203    }
204
205    return ret;
206}
207
208uint64_t Context::getTime() const
209{
210    struct timespec t;
211    clock_gettime(CLOCK_MONOTONIC, &t);
212    return t.tv_nsec + ((uint64_t)t.tv_sec * 1000 * 1000 * 1000);
213}
214
215void Context::timerReset()
216{
217    for (int ct=0; ct < _RS_TIMER_TOTAL; ct++) {
218        mTimers[ct] = 0;
219    }
220}
221
222void Context::timerInit()
223{
224    mTimeLast = getTime();
225    mTimeFrame = mTimeLast;
226    mTimeLastFrame = mTimeLast;
227    mTimerActive = RS_TIMER_INTERNAL;
228    timerReset();
229}
230
231void Context::timerFrame()
232{
233    mTimeLastFrame = mTimeFrame;
234    mTimeFrame = getTime();
235}
236
237void Context::timerSet(Timers tm)
238{
239    uint64_t last = mTimeLast;
240    mTimeLast = getTime();
241    mTimers[mTimerActive] += mTimeLast - last;
242    mTimerActive = tm;
243}
244
245void Context::timerPrint()
246{
247    double total = 0;
248    for (int ct = 0; ct < _RS_TIMER_TOTAL; ct++) {
249        total += mTimers[ct];
250    }
251    uint64_t frame = mTimeFrame - mTimeLastFrame;
252
253    LOGV("RS: Frame (%lli),   Script %2.1f (%lli),  Clear & Swap %2.1f (%lli),  Idle %2.1f (%lli),  Internal %2.1f (%lli)",
254         frame / 1000000,
255         100.0 * mTimers[RS_TIMER_SCRIPT] / total, mTimers[RS_TIMER_SCRIPT] / 1000000,
256         100.0 * mTimers[RS_TIMER_CLEAR_SWAP] / total, mTimers[RS_TIMER_CLEAR_SWAP] / 1000000,
257         100.0 * mTimers[RS_TIMER_IDLE] / total, mTimers[RS_TIMER_IDLE] / 1000000,
258         100.0 * mTimers[RS_TIMER_INTERNAL] / total, mTimers[RS_TIMER_INTERNAL] / 1000000);
259}
260
261void Context::setupCheck()
262{
263    mFragmentStore->setupGL(this, &mStateFragmentStore);
264    mFragment->setupGL(this, &mStateFragment);
265    mRaster->setupGL(this, &mStateRaster);
266    mVertex->setupGL(this, &mStateVertex);
267}
268
269static bool getProp(const char *str)
270{
271    char buf[PROPERTY_VALUE_MAX];
272    property_get(str, buf, "0");
273    return 0 != strcmp(buf, "0");
274}
275
276void * Context::threadProc(void *vrsc)
277{
278     Context *rsc = static_cast<Context *>(vrsc);
279
280     rsc->props.mLogTimes = getProp("debug.rs.profile");
281     rsc->props.mLogScripts = getProp("debug.rs.script");
282     rsc->props.mLogObjects = getProp("debug.rs.objects");
283
284     pthread_mutex_lock(&gInitMutex);
285     rsc->initEGL();
286     pthread_mutex_unlock(&gInitMutex);
287
288     ScriptTLSStruct *tlsStruct = new ScriptTLSStruct;
289     if (!tlsStruct) {
290         LOGE("Error allocating tls storage");
291         return NULL;
292     }
293     tlsStruct->mContext = rsc;
294     tlsStruct->mScript = NULL;
295     int status = pthread_setspecific(rsc->gThreadTLSKey, tlsStruct);
296     if (status) {
297         LOGE("pthread_setspecific %i", status);
298     }
299
300     rsc->mStateRaster.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight);
301     rsc->setRaster(NULL);
302     rsc->mStateVertex.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight);
303     rsc->setVertex(NULL);
304     rsc->mStateFragment.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight);
305     rsc->setFragment(NULL);
306     rsc->mStateFragmentStore.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight);
307     rsc->setFragmentStore(NULL);
308
309     rsc->mRunning = true;
310     bool mDraw = true;
311     while (!rsc->mExit) {
312         mDraw |= rsc->mIO.playCoreCommands(rsc, !mDraw);
313         mDraw &= (rsc->mRootScript.get() != NULL);
314
315         if (mDraw) {
316             mDraw = rsc->runRootScript() && !rsc->mPaused;
317             if (rsc->props.mLogTimes) {
318                 rsc->timerSet(RS_TIMER_CLEAR_SWAP);
319             }
320             eglSwapBuffers(rsc->mEGL.mDisplay, rsc->mEGL.mSurface);
321             if (rsc->props.mLogTimes) {
322                 rsc->timerFrame();
323                 rsc->timerSet(RS_TIMER_INTERNAL);
324                 rsc->timerPrint();
325                 rsc->timerReset();
326             }
327         }
328         if (rsc->mObjDestroy.mNeedToEmpty) {
329             rsc->objDestroyOOBRun();
330         }
331     }
332
333     LOGV("RS Thread exiting");
334     rsc->mRaster.clear();
335     rsc->mFragment.clear();
336     rsc->mVertex.clear();
337     rsc->mFragmentStore.clear();
338     rsc->mRootScript.clear();
339     rsc->mStateRaster.deinit(rsc);
340     rsc->mStateVertex.deinit(rsc);
341     rsc->mStateFragment.deinit(rsc);
342     rsc->mStateFragmentStore.deinit(rsc);
343     ObjectBase::zeroAllUserRef(rsc);
344
345     glClearColor(0,0,0,0);
346     glClear(GL_COLOR_BUFFER_BIT);
347     eglSwapBuffers(rsc->mEGL.mDisplay, rsc->mEGL.mSurface);
348
349     pthread_mutex_lock(&gInitMutex);
350     rsc->deinitEGL();
351     pthread_mutex_unlock(&gInitMutex);
352
353     rsc->mObjDestroy.mNeedToEmpty = true;
354     rsc->objDestroyOOBRun();
355     LOGV("RS Thread exited");
356     return NULL;
357}
358
359Context::Context(Device *dev, Surface *sur, bool useDepth)
360{
361    pthread_mutex_lock(&gInitMutex);
362
363    dev->addContext(this);
364    mDev = dev;
365    mRunning = false;
366    mExit = false;
367    mUseDepth = useDepth;
368    mPaused = false;
369    mObjHead = NULL;
370
371    int status;
372    pthread_attr_t threadAttr;
373
374    if (!gThreadTLSKeyCount) {
375        status = pthread_key_create(&gThreadTLSKey, NULL);
376        if (status) {
377            LOGE("Failed to init thread tls key.");
378            pthread_mutex_unlock(&gInitMutex);
379            return;
380        }
381    }
382    gThreadTLSKeyCount++;
383    pthread_mutex_unlock(&gInitMutex);
384
385    // Global init done at this point.
386
387    status = pthread_attr_init(&threadAttr);
388    if (status) {
389        LOGE("Failed to init thread attribute.");
390        return;
391    }
392
393    sched_param sparam;
394    sparam.sched_priority = ANDROID_PRIORITY_DISPLAY;
395    pthread_attr_setschedparam(&threadAttr, &sparam);
396
397    mWndSurface = sur;
398
399    objDestroyOOBInit();
400    timerInit();
401    timerSet(RS_TIMER_INTERNAL);
402
403    LOGV("RS Launching thread");
404    status = pthread_create(&mThreadId, &threadAttr, threadProc, this);
405    if (status) {
406        LOGE("Failed to start rs context thread.");
407    }
408
409    while(!mRunning) {
410        usleep(100);
411    }
412
413    pthread_attr_destroy(&threadAttr);
414}
415
416Context::~Context()
417{
418    LOGV("Context::~Context");
419    mExit = true;
420    mPaused = false;
421    void *res;
422
423    mIO.shutdown();
424    int status = pthread_join(mThreadId, &res);
425    mObjDestroy.mNeedToEmpty = true;
426    objDestroyOOBRun();
427
428    // Global structure cleanup.
429    pthread_mutex_lock(&gInitMutex);
430    if (mDev) {
431        mDev->removeContext(this);
432        --gThreadTLSKeyCount;
433        if (!gThreadTLSKeyCount) {
434            pthread_key_delete(gThreadTLSKey);
435        }
436        mDev = NULL;
437    }
438    pthread_mutex_unlock(&gInitMutex);
439
440    objDestroyOOBDestroy();
441}
442
443void Context::pause()
444{
445    mPaused = true;
446}
447
448void Context::resume()
449{
450    mPaused = false;
451}
452
453void Context::setRootScript(Script *s)
454{
455    mRootScript.set(s);
456}
457
458void Context::setFragmentStore(ProgramFragmentStore *pfs)
459{
460    if (pfs == NULL) {
461        mFragmentStore.set(mStateFragmentStore.mDefault);
462    } else {
463        mFragmentStore.set(pfs);
464    }
465}
466
467void Context::setFragment(ProgramFragment *pf)
468{
469    if (pf == NULL) {
470        mFragment.set(mStateFragment.mDefault);
471    } else {
472        mFragment.set(pf);
473    }
474}
475
476void Context::setRaster(ProgramRaster *pr)
477{
478    if (pr == NULL) {
479        mRaster.set(mStateRaster.mDefault);
480    } else {
481        mRaster.set(pr);
482    }
483}
484
485void Context::setVertex(ProgramVertex *pv)
486{
487    if (pv == NULL) {
488        mVertex.set(mStateVertex.mDefault);
489    } else {
490        mVertex.set(pv);
491    }
492}
493
494void Context::assignName(ObjectBase *obj, const char *name, uint32_t len)
495{
496    rsAssert(!obj->getName());
497    obj->setName(name, len);
498    mNames.add(obj);
499}
500
501void Context::removeName(ObjectBase *obj)
502{
503    for(size_t ct=0; ct < mNames.size(); ct++) {
504        if (obj == mNames[ct]) {
505            mNames.removeAt(ct);
506            return;
507        }
508    }
509}
510
511ObjectBase * Context::lookupName(const char *name) const
512{
513    for(size_t ct=0; ct < mNames.size(); ct++) {
514        if (!strcmp(name, mNames[ct]->getName())) {
515            return mNames[ct];
516        }
517    }
518    return NULL;
519}
520
521void Context::appendNameDefines(String8 *str) const
522{
523    char buf[256];
524    for (size_t ct=0; ct < mNames.size(); ct++) {
525        str->append("#define NAMED_");
526        str->append(mNames[ct]->getName());
527        str->append(" ");
528        sprintf(buf, "%i\n", (int)mNames[ct]);
529        str->append(buf);
530    }
531}
532
533void Context::appendVarDefines(String8 *str) const
534{
535    char buf[256];
536    for (size_t ct=0; ct < mInt32Defines.size(); ct++) {
537        str->append("#define ");
538        str->append(mInt32Defines.keyAt(ct));
539        str->append(" ");
540        sprintf(buf, "%i\n", (int)mInt32Defines.valueAt(ct));
541        str->append(buf);
542
543    }
544    for (size_t ct=0; ct < mFloatDefines.size(); ct++) {
545        str->append("#define ");
546        str->append(mFloatDefines.keyAt(ct));
547        str->append(" ");
548        sprintf(buf, "%ff\n", mFloatDefines.valueAt(ct));
549        str->append(buf);
550    }
551}
552
553bool Context::objDestroyOOBInit()
554{
555    int status = pthread_mutex_init(&mObjDestroy.mMutex, NULL);
556    if (status) {
557        LOGE("Context::ObjDestroyOOBInit mutex init failure");
558        return false;
559    }
560    return true;
561}
562
563void Context::objDestroyOOBRun()
564{
565    if (mObjDestroy.mNeedToEmpty) {
566        int status = pthread_mutex_lock(&mObjDestroy.mMutex);
567        if (status) {
568            LOGE("Context::ObjDestroyOOBRun: error %i locking for OOBRun.", status);
569            return;
570        }
571
572        for (size_t ct = 0; ct < mObjDestroy.mDestroyList.size(); ct++) {
573            mObjDestroy.mDestroyList[ct]->decUserRef();
574        }
575        mObjDestroy.mDestroyList.clear();
576        mObjDestroy.mNeedToEmpty = false;
577
578        status = pthread_mutex_unlock(&mObjDestroy.mMutex);
579        if (status) {
580            LOGE("Context::ObjDestroyOOBRun: error %i unlocking for set condition.", status);
581        }
582    }
583}
584
585void Context::objDestroyOOBDestroy()
586{
587    rsAssert(!mObjDestroy.mNeedToEmpty);
588    pthread_mutex_destroy(&mObjDestroy.mMutex);
589}
590
591void Context::objDestroyAdd(ObjectBase *obj)
592{
593    int status = pthread_mutex_lock(&mObjDestroy.mMutex);
594    if (status) {
595        LOGE("Context::ObjDestroyOOBRun: error %i locking for OOBRun.", status);
596        return;
597    }
598
599    mObjDestroy.mNeedToEmpty = true;
600    mObjDestroy.mDestroyList.add(obj);
601
602    status = pthread_mutex_unlock(&mObjDestroy.mMutex);
603    if (status) {
604        LOGE("Context::ObjDestroyOOBRun: error %i unlocking for set condition.", status);
605    }
606}
607
608uint32_t Context::getMessageToClient(void *data, size_t *receiveLen, size_t bufferLen, bool wait)
609{
610    //LOGE("getMessageToClient %i %i", bufferLen, wait);
611    if (!wait) {
612        if (mIO.mToClient.isEmpty()) {
613            // No message to get and not going to wait for one.
614            receiveLen = 0;
615            return 0;
616        }
617    }
618
619    //LOGE("getMessageToClient 2 con=%p", this);
620    uint32_t bytesData = 0;
621    uint32_t commandID = 0;
622    const void *d = mIO.mToClient.get(&commandID, &bytesData);
623    //LOGE("getMessageToClient 3    %i  %i", commandID, bytesData);
624
625    *receiveLen = bytesData;
626    if (bufferLen >= bytesData) {
627        memcpy(data, d, bytesData);
628        mIO.mToClient.next();
629        return commandID;
630    }
631    return 0;
632}
633
634bool Context::sendMessageToClient(void *data, uint32_t cmdID, size_t len, bool waitForSpace)
635{
636    //LOGE("sendMessageToClient %i %i %i", cmdID, len, waitForSpace);
637    if (cmdID == 0) {
638        LOGE("Attempting to send invalid command 0 to client.");
639        return false;
640    }
641    if (!waitForSpace) {
642        if (mIO.mToClient.getFreeSpace() < len) {
643            // Not enough room, and not waiting.
644            return false;
645        }
646    }
647    //LOGE("sendMessageToClient 2");
648    void *p = mIO.mToClient.reserve(len);
649    memcpy(p, data, len);
650    mIO.mToClient.commit(cmdID, len);
651    //LOGE("sendMessageToClient 3");
652    return true;
653}
654
655void Context::initToClient()
656{
657    while(!mRunning) {
658        usleep(100);
659    }
660}
661
662void Context::deinitToClient()
663{
664    mIO.mToClient.shutdown();
665}
666
667
668///////////////////////////////////////////////////////////////////////////////////////////
669//
670
671namespace android {
672namespace renderscript {
673
674
675void rsi_ContextBindRootScript(Context *rsc, RsScript vs)
676{
677    Script *s = static_cast<Script *>(vs);
678    rsc->setRootScript(s);
679}
680
681void rsi_ContextBindSampler(Context *rsc, uint32_t slot, RsSampler vs)
682{
683    Sampler *s = static_cast<Sampler *>(vs);
684
685    if (slot > RS_MAX_SAMPLER_SLOT) {
686        LOGE("Invalid sampler slot");
687        return;
688    }
689
690    s->bindToContext(&rsc->mStateSampler, slot);
691}
692
693void rsi_ContextBindProgramFragmentStore(Context *rsc, RsProgramFragmentStore vpfs)
694{
695    ProgramFragmentStore *pfs = static_cast<ProgramFragmentStore *>(vpfs);
696    rsc->setFragmentStore(pfs);
697}
698
699void rsi_ContextBindProgramFragment(Context *rsc, RsProgramFragment vpf)
700{
701    ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
702    rsc->setFragment(pf);
703}
704
705void rsi_ContextBindProgramRaster(Context *rsc, RsProgramRaster vpr)
706{
707    ProgramRaster *pr = static_cast<ProgramRaster *>(vpr);
708    rsc->setRaster(pr);
709}
710
711void rsi_ContextBindProgramVertex(Context *rsc, RsProgramVertex vpv)
712{
713    ProgramVertex *pv = static_cast<ProgramVertex *>(vpv);
714    rsc->setVertex(pv);
715}
716
717void rsi_AssignName(Context *rsc, void * obj, const char *name, uint32_t len)
718{
719    ObjectBase *ob = static_cast<ObjectBase *>(obj);
720    rsc->assignName(ob, name, len);
721}
722
723void rsi_ObjDestroy(Context *rsc, void *obj)
724{
725    ObjectBase *ob = static_cast<ObjectBase *>(obj);
726    rsc->removeName(ob);
727    ob->decUserRef();
728}
729
730void rsi_ContextSetDefineF(Context *rsc, const char* name, float value)
731{
732    rsc->addInt32Define(name, value);
733}
734
735void rsi_ContextSetDefineI32(Context *rsc, const char* name, int32_t value)
736{
737    rsc->addFloatDefine(name, value);
738}
739
740void rsi_ContextPause(Context *rsc)
741{
742    rsc->pause();
743}
744
745void rsi_ContextResume(Context *rsc)
746{
747    rsc->resume();
748}
749
750}
751}
752
753
754RsContext rsContextCreate(RsDevice vdev, void *sur, uint32_t version, bool useDepth)
755{
756    Device * dev = static_cast<Device *>(vdev);
757    Context *rsc = new Context(dev, (Surface *)sur, useDepth);
758    return rsc;
759}
760
761void rsContextDestroy(RsContext vrsc)
762{
763    Context * rsc = static_cast<Context *>(vrsc);
764    delete rsc;
765}
766
767void rsObjDestroyOOB(RsContext vrsc, void *obj)
768{
769    Context * rsc = static_cast<Context *>(vrsc);
770    rsc->objDestroyAdd(static_cast<ObjectBase *>(obj));
771}
772
773uint32_t rsContextGetMessage(RsContext vrsc, void *data, size_t *receiveLen, size_t bufferLen, bool wait)
774{
775    Context * rsc = static_cast<Context *>(vrsc);
776    return rsc->getMessageToClient(data, receiveLen, bufferLen, wait);
777}
778
779void rsContextInitToClient(RsContext vrsc)
780{
781    Context * rsc = static_cast<Context *>(vrsc);
782    rsc->initToClient();
783}
784
785void rsContextDeinitToClient(RsContext vrsc)
786{
787    Context * rsc = static_cast<Context *>(vrsc);
788    rsc->deinitToClient();
789}
790
791