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