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