rsContext.cpp revision 4820e8bb83b1f78e6232ebe853221f737da2a1ea
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     if (rsc->mIsGraphicsContext) {
293         rsc->mStateRaster.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight);
294         rsc->setRaster(NULL);
295         rsc->mStateVertex.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight);
296         rsc->setVertex(NULL);
297         rsc->mStateFragment.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight);
298         rsc->setFragment(NULL);
299         rsc->mStateFragmentStore.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight);
300         rsc->setFragmentStore(NULL);
301         rsc->mStateVertexArray.init(rsc);
302     }
303
304     rsc->mRunning = true;
305     bool mDraw = true;
306     while (!rsc->mExit) {
307         mDraw |= rsc->mIO.playCoreCommands(rsc, !mDraw);
308         mDraw &= (rsc->mRootScript.get() != NULL);
309         mDraw &= (rsc->mWndSurface != NULL);
310
311         uint32_t targetTime = 0;
312         if (mDraw && rsc->mIsGraphicsContext) {
313             targetTime = rsc->runRootScript();
314             mDraw = targetTime && !rsc->mPaused;
315             rsc->timerSet(RS_TIMER_CLEAR_SWAP);
316             eglSwapBuffers(rsc->mEGL.mDisplay, rsc->mEGL.mSurface);
317             rsc->timerFrame();
318             rsc->timerSet(RS_TIMER_INTERNAL);
319             rsc->timerPrint();
320             rsc->timerReset();
321         }
322         if (rsc->mObjDestroy.mNeedToEmpty) {
323             rsc->objDestroyOOBRun();
324         }
325         if (rsc->mThreadPriority > 0 && targetTime) {
326             int32_t t = (targetTime - (int32_t)(rsc->mTimeMSLastScript + rsc->mTimeMSLastSwap)) * 1000;
327             if (t > 0) {
328                 usleep(t);
329             }
330         }
331     }
332
333     LOGV("RS Thread exiting");
334     if (rsc->mIsGraphicsContext) {
335         rsc->mRaster.clear();
336         rsc->mFragment.clear();
337         rsc->mVertex.clear();
338         rsc->mFragmentStore.clear();
339         rsc->mRootScript.clear();
340         rsc->mStateRaster.deinit(rsc);
341         rsc->mStateVertex.deinit(rsc);
342         rsc->mStateFragment.deinit(rsc);
343         rsc->mStateFragmentStore.deinit(rsc);
344     }
345     ObjectBase::zeroAllUserRef(rsc);
346
347     rsc->mObjDestroy.mNeedToEmpty = true;
348     rsc->objDestroyOOBRun();
349
350     if (rsc->mIsGraphicsContext) {
351         pthread_mutex_lock(&gInitMutex);
352         rsc->deinitEGL();
353         pthread_mutex_unlock(&gInitMutex);
354     }
355
356     LOGV("RS Thread exited");
357     return NULL;
358}
359
360void Context::setPriority(int32_t p)
361{
362    // Note: If we put this in the proper "background" policy
363    // the wallpapers can become completly unresponsive at times.
364    // This is probably not what we want for something the user is actively
365    // looking at.
366    mThreadPriority = p;
367#if 0
368    SchedPolicy pol = SP_FOREGROUND;
369    if (p > 0) {
370        pol = SP_BACKGROUND;
371    }
372    if (!set_sched_policy(mNativeThreadId, pol)) {
373        // success; reset the priority as well
374    }
375#else
376        setpriority(PRIO_PROCESS, mNativeThreadId, p);
377#endif
378}
379
380Context::Context(Device *dev, bool isGraphics, bool useDepth)
381{
382    pthread_mutex_lock(&gInitMutex);
383
384    dev->addContext(this);
385    mDev = dev;
386    mRunning = false;
387    mExit = false;
388    mUseDepth = useDepth;
389    mPaused = false;
390    mObjHead = NULL;
391    memset(&mEGL, 0, sizeof(mEGL));
392    memset(&mGL, 0, sizeof(mGL));
393    mIsGraphicsContext = isGraphics;
394
395    int status;
396    pthread_attr_t threadAttr;
397
398    if (!gThreadTLSKeyCount) {
399        status = pthread_key_create(&gThreadTLSKey, NULL);
400        if (status) {
401            LOGE("Failed to init thread tls key.");
402            pthread_mutex_unlock(&gInitMutex);
403            return;
404        }
405    }
406    gThreadTLSKeyCount++;
407    pthread_mutex_unlock(&gInitMutex);
408
409    // Global init done at this point.
410
411    status = pthread_attr_init(&threadAttr);
412    if (status) {
413        LOGE("Failed to init thread attribute.");
414        return;
415    }
416
417    mWndSurface = NULL;
418
419    objDestroyOOBInit();
420    timerInit();
421    timerSet(RS_TIMER_INTERNAL);
422
423    LOGV("RS Launching thread");
424    status = pthread_create(&mThreadId, &threadAttr, threadProc, this);
425    if (status) {
426        LOGE("Failed to start rs context thread.");
427    }
428
429    while(!mRunning) {
430        usleep(100);
431    }
432
433    pthread_attr_destroy(&threadAttr);
434}
435
436Context::~Context()
437{
438    LOGV("Context::~Context");
439    mExit = true;
440    mPaused = false;
441    void *res;
442
443    mIO.shutdown();
444    int status = pthread_join(mThreadId, &res);
445    mObjDestroy.mNeedToEmpty = true;
446    objDestroyOOBRun();
447
448    // Global structure cleanup.
449    pthread_mutex_lock(&gInitMutex);
450    if (mDev) {
451        mDev->removeContext(this);
452        --gThreadTLSKeyCount;
453        if (!gThreadTLSKeyCount) {
454            pthread_key_delete(gThreadTLSKey);
455        }
456        mDev = NULL;
457    }
458    pthread_mutex_unlock(&gInitMutex);
459
460    objDestroyOOBDestroy();
461}
462
463void Context::setSurface(uint32_t w, uint32_t h, Surface *sur)
464{
465    rsAssert(mIsGraphicsContext);
466
467    EGLBoolean ret;
468    if (mEGL.mSurface != NULL) {
469        ret = eglMakeCurrent(mEGL.mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
470        checkEglError("eglMakeCurrent", ret);
471
472        ret = eglDestroySurface(mEGL.mDisplay, mEGL.mSurface);
473        checkEglError("eglDestroySurface", ret);
474
475        mEGL.mSurface = NULL;
476        mEGL.mWidth = 0;
477        mEGL.mHeight = 0;
478        mWidth = 0;
479        mHeight = 0;
480    }
481
482    mWndSurface = sur;
483    if (mWndSurface != NULL) {
484        bool first = false;
485        if (!mEGL.mContext) {
486            first = true;
487            pthread_mutex_lock(&gInitMutex);
488            initEGL(true);
489            pthread_mutex_unlock(&gInitMutex);
490        }
491
492        mEGL.mSurface = eglCreateWindowSurface(mEGL.mDisplay, mEGL.mConfig, mWndSurface, NULL);
493        checkEglError("eglCreateWindowSurface");
494        if (mEGL.mSurface == EGL_NO_SURFACE) {
495            LOGE("eglCreateWindowSurface returned EGL_NO_SURFACE");
496        }
497
498        ret = eglMakeCurrent(mEGL.mDisplay, mEGL.mSurface, mEGL.mSurface, mEGL.mContext);
499        checkEglError("eglMakeCurrent", ret);
500
501        eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_WIDTH, &mEGL.mWidth);
502        eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_HEIGHT, &mEGL.mHeight);
503        mWidth = w;
504        mHeight = h;
505        mStateVertex.updateSize(this, w, h);
506
507        if ((int)mWidth != mEGL.mWidth || (int)mHeight != mEGL.mHeight) {
508            LOGE("EGL/Surface mismatch  EGL (%i x %i)  SF (%i x %i)", mEGL.mWidth, mEGL.mHeight, mWidth, mHeight);
509        }
510
511        if (first) {
512            mGL.mVersion = glGetString(GL_VERSION);
513            mGL.mVendor = glGetString(GL_VENDOR);
514            mGL.mRenderer = glGetString(GL_RENDERER);
515            mGL.mExtensions = glGetString(GL_EXTENSIONS);
516
517            //LOGV("EGL Version %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion);
518            LOGV("GL Version %s", mGL.mVersion);
519            //LOGV("GL Vendor %s", mGL.mVendor);
520            LOGV("GL Renderer %s", mGL.mRenderer);
521            //LOGV("GL Extensions %s", mGL.mExtensions);
522
523            const char *verptr = NULL;
524            if (strlen((const char *)mGL.mVersion) > 9) {
525                if (!memcmp(mGL.mVersion, "OpenGL ES-CM", 12)) {
526                    verptr = (const char *)mGL.mVersion + 12;
527                }
528                if (!memcmp(mGL.mVersion, "OpenGL ES ", 10)) {
529                    verptr = (const char *)mGL.mVersion + 9;
530                }
531            }
532
533            if (!verptr) {
534                LOGE("Error, OpenGL ES Lite not supported");
535            } else {
536                sscanf(verptr, " %i.%i", &mGL.mMajorVersion, &mGL.mMinorVersion);
537            }
538
539            glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &mGL.mMaxVertexAttribs);
540            glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &mGL.mMaxVertexUniformVectors);
541            glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mGL.mMaxVertexTextureUnits);
542
543            glGetIntegerv(GL_MAX_VARYING_VECTORS, &mGL.mMaxVaryingVectors);
544            glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mGL.mMaxTextureImageUnits);
545
546            glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &mGL.mMaxFragmentTextureImageUnits);
547            glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &mGL.mMaxFragmentUniformVectors);
548        }
549
550    }
551}
552
553void Context::pause()
554{
555    rsAssert(mIsGraphicsContext);
556    mPaused = true;
557}
558
559void Context::resume()
560{
561    rsAssert(mIsGraphicsContext);
562    mPaused = false;
563}
564
565void Context::setRootScript(Script *s)
566{
567    rsAssert(mIsGraphicsContext);
568    mRootScript.set(s);
569}
570
571void Context::setFragmentStore(ProgramFragmentStore *pfs)
572{
573    rsAssert(mIsGraphicsContext);
574    if (pfs == NULL) {
575        mFragmentStore.set(mStateFragmentStore.mDefault);
576    } else {
577        mFragmentStore.set(pfs);
578    }
579}
580
581void Context::setFragment(ProgramFragment *pf)
582{
583    rsAssert(mIsGraphicsContext);
584    if (pf == NULL) {
585        mFragment.set(mStateFragment.mDefault);
586    } else {
587        mFragment.set(pf);
588    }
589}
590
591void Context::setRaster(ProgramRaster *pr)
592{
593    rsAssert(mIsGraphicsContext);
594    if (pr == NULL) {
595        mRaster.set(mStateRaster.mDefault);
596    } else {
597        mRaster.set(pr);
598    }
599}
600
601void Context::setVertex(ProgramVertex *pv)
602{
603    rsAssert(mIsGraphicsContext);
604    if (pv == NULL) {
605        mVertex.set(mStateVertex.mDefault);
606    } else {
607        mVertex.set(pv);
608    }
609}
610
611void Context::assignName(ObjectBase *obj, const char *name, uint32_t len)
612{
613    rsAssert(!obj->getName());
614    obj->setName(name, len);
615    mNames.add(obj);
616}
617
618void Context::removeName(ObjectBase *obj)
619{
620    for(size_t ct=0; ct < mNames.size(); ct++) {
621        if (obj == mNames[ct]) {
622            mNames.removeAt(ct);
623            return;
624        }
625    }
626}
627
628ObjectBase * Context::lookupName(const char *name) const
629{
630    for(size_t ct=0; ct < mNames.size(); ct++) {
631        if (!strcmp(name, mNames[ct]->getName())) {
632            return mNames[ct];
633        }
634    }
635    return NULL;
636}
637
638void Context::appendNameDefines(String8 *str) const
639{
640    char buf[256];
641    for (size_t ct=0; ct < mNames.size(); ct++) {
642        str->append("#define NAMED_");
643        str->append(mNames[ct]->getName());
644        str->append(" ");
645        sprintf(buf, "%i\n", (int)mNames[ct]);
646        str->append(buf);
647    }
648}
649
650bool Context::objDestroyOOBInit()
651{
652    int status = pthread_mutex_init(&mObjDestroy.mMutex, NULL);
653    if (status) {
654        LOGE("Context::ObjDestroyOOBInit mutex init failure");
655        return false;
656    }
657    return true;
658}
659
660void Context::objDestroyOOBRun()
661{
662    if (mObjDestroy.mNeedToEmpty) {
663        int status = pthread_mutex_lock(&mObjDestroy.mMutex);
664        if (status) {
665            LOGE("Context::ObjDestroyOOBRun: error %i locking for OOBRun.", status);
666            return;
667        }
668
669        for (size_t ct = 0; ct < mObjDestroy.mDestroyList.size(); ct++) {
670            mObjDestroy.mDestroyList[ct]->decUserRef();
671        }
672        mObjDestroy.mDestroyList.clear();
673        mObjDestroy.mNeedToEmpty = false;
674
675        status = pthread_mutex_unlock(&mObjDestroy.mMutex);
676        if (status) {
677            LOGE("Context::ObjDestroyOOBRun: error %i unlocking for set condition.", status);
678        }
679    }
680}
681
682void Context::objDestroyOOBDestroy()
683{
684    rsAssert(!mObjDestroy.mNeedToEmpty);
685    pthread_mutex_destroy(&mObjDestroy.mMutex);
686}
687
688void Context::objDestroyAdd(ObjectBase *obj)
689{
690    int status = pthread_mutex_lock(&mObjDestroy.mMutex);
691    if (status) {
692        LOGE("Context::ObjDestroyOOBRun: error %i locking for OOBRun.", status);
693        return;
694    }
695
696    mObjDestroy.mNeedToEmpty = true;
697    mObjDestroy.mDestroyList.add(obj);
698
699    status = pthread_mutex_unlock(&mObjDestroy.mMutex);
700    if (status) {
701        LOGE("Context::ObjDestroyOOBRun: error %i unlocking for set condition.", status);
702    }
703}
704
705uint32_t Context::getMessageToClient(void *data, size_t *receiveLen, size_t bufferLen, bool wait)
706{
707    //LOGE("getMessageToClient %i %i", bufferLen, wait);
708    if (!wait) {
709        if (mIO.mToClient.isEmpty()) {
710            // No message to get and not going to wait for one.
711            receiveLen = 0;
712            return 0;
713        }
714    }
715
716    //LOGE("getMessageToClient 2 con=%p", this);
717    uint32_t bytesData = 0;
718    uint32_t commandID = 0;
719    const void *d = mIO.mToClient.get(&commandID, &bytesData);
720    //LOGE("getMessageToClient 3    %i  %i", commandID, bytesData);
721
722    *receiveLen = bytesData;
723    if (bufferLen >= bytesData) {
724        memcpy(data, d, bytesData);
725        mIO.mToClient.next();
726        return commandID;
727    }
728    return 0;
729}
730
731bool Context::sendMessageToClient(void *data, uint32_t cmdID, size_t len, bool waitForSpace)
732{
733    //LOGE("sendMessageToClient %i %i %i", cmdID, len, waitForSpace);
734    if (cmdID == 0) {
735        LOGE("Attempting to send invalid command 0 to client.");
736        return false;
737    }
738    if (!waitForSpace) {
739        if (mIO.mToClient.getFreeSpace() < len) {
740            // Not enough room, and not waiting.
741            return false;
742        }
743    }
744    //LOGE("sendMessageToClient 2");
745    void *p = mIO.mToClient.reserve(len);
746    memcpy(p, data, len);
747    mIO.mToClient.commit(cmdID, len);
748    //LOGE("sendMessageToClient 3");
749    return true;
750}
751
752void Context::initToClient()
753{
754    while(!mRunning) {
755        usleep(100);
756    }
757}
758
759void Context::deinitToClient()
760{
761    mIO.mToClient.shutdown();
762}
763
764void Context::dumpDebug() const
765{
766    LOGE("RS Context debug %p", this);
767    LOGE("RS Context debug");
768
769    LOGE(" EGL ver %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion);
770    LOGE(" EGL context %p  surface %p,  w=%i h=%i  Display=%p", mEGL.mContext,
771         mEGL.mSurface, mEGL.mWidth, mEGL.mHeight, mEGL.mDisplay);
772    LOGE(" GL vendor: %s", mGL.mVendor);
773    LOGE(" GL renderer: %s", mGL.mRenderer);
774    LOGE(" GL Version: %s", mGL.mVersion);
775    LOGE(" GL Extensions: %s", mGL.mExtensions);
776    LOGE(" GL int Versions %i %i", mGL.mMajorVersion, mGL.mMinorVersion);
777    LOGE(" RS width %i, height %i", mWidth, mHeight);
778    LOGE(" RS running %i, exit %i, useDepth %i, paused %i", mRunning, mExit, mUseDepth, mPaused);
779    LOGE(" RS pThreadID %li, nativeThreadID %i", mThreadId, mNativeThreadId);
780
781    LOGV("MAX Textures %i, %i  %i", mGL.mMaxVertexTextureUnits, mGL.mMaxFragmentTextureImageUnits, mGL.mMaxTextureImageUnits);
782    LOGV("MAX Attribs %i", mGL.mMaxVertexAttribs);
783    LOGV("MAX Uniforms %i, %i", mGL.mMaxVertexUniformVectors, mGL.mMaxFragmentUniformVectors);
784    LOGV("MAX Varyings %i", mGL.mMaxVaryingVectors);
785}
786
787///////////////////////////////////////////////////////////////////////////////////////////
788//
789
790namespace android {
791namespace renderscript {
792
793
794void rsi_ContextBindRootScript(Context *rsc, RsScript vs)
795{
796    Script *s = static_cast<Script *>(vs);
797    rsc->setRootScript(s);
798}
799
800void rsi_ContextBindSampler(Context *rsc, uint32_t slot, RsSampler vs)
801{
802    Sampler *s = static_cast<Sampler *>(vs);
803
804    if (slot > RS_MAX_SAMPLER_SLOT) {
805        LOGE("Invalid sampler slot");
806        return;
807    }
808
809    s->bindToContext(&rsc->mStateSampler, slot);
810}
811
812void rsi_ContextBindProgramFragmentStore(Context *rsc, RsProgramFragmentStore vpfs)
813{
814    ProgramFragmentStore *pfs = static_cast<ProgramFragmentStore *>(vpfs);
815    rsc->setFragmentStore(pfs);
816}
817
818void rsi_ContextBindProgramFragment(Context *rsc, RsProgramFragment vpf)
819{
820    ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
821    rsc->setFragment(pf);
822}
823
824void rsi_ContextBindProgramRaster(Context *rsc, RsProgramRaster vpr)
825{
826    ProgramRaster *pr = static_cast<ProgramRaster *>(vpr);
827    rsc->setRaster(pr);
828}
829
830void rsi_ContextBindProgramVertex(Context *rsc, RsProgramVertex vpv)
831{
832    ProgramVertex *pv = static_cast<ProgramVertex *>(vpv);
833    rsc->setVertex(pv);
834}
835
836void rsi_AssignName(Context *rsc, void * obj, const char *name, uint32_t len)
837{
838    ObjectBase *ob = static_cast<ObjectBase *>(obj);
839    rsc->assignName(ob, name, len);
840}
841
842void rsi_ObjDestroy(Context *rsc, void *obj)
843{
844    ObjectBase *ob = static_cast<ObjectBase *>(obj);
845    rsc->removeName(ob);
846    ob->decUserRef();
847}
848
849void rsi_ContextPause(Context *rsc)
850{
851    rsc->pause();
852}
853
854void rsi_ContextResume(Context *rsc)
855{
856    rsc->resume();
857}
858
859void rsi_ContextSetSurface(Context *rsc, uint32_t w, uint32_t h, void *sur)
860{
861    rsc->setSurface(w, h, (Surface *)sur);
862}
863
864void rsi_ContextSetPriority(Context *rsc, int32_t p)
865{
866    rsc->setPriority(p);
867}
868
869void rsi_ContextDump(Context *rsc, int32_t bits)
870{
871    ObjectBase::dumpAll(rsc);
872}
873
874}
875}
876
877
878RsContext rsContextCreate(RsDevice vdev, uint32_t version)
879{
880    LOGV("rsContextCreate %p", vdev);
881    Device * dev = static_cast<Device *>(vdev);
882    Context *rsc = new Context(dev, false, false);
883    return rsc;
884}
885
886RsContext rsContextCreateGL(RsDevice vdev, uint32_t version, bool useDepth)
887{
888    LOGV("rsContextCreateGL %p, %i", vdev, useDepth);
889    Device * dev = static_cast<Device *>(vdev);
890    Context *rsc = new Context(dev, true, useDepth);
891    return rsc;
892}
893
894void rsContextDestroy(RsContext vrsc)
895{
896    Context * rsc = static_cast<Context *>(vrsc);
897    delete rsc;
898}
899
900void rsObjDestroyOOB(RsContext vrsc, void *obj)
901{
902    Context * rsc = static_cast<Context *>(vrsc);
903    rsc->objDestroyAdd(static_cast<ObjectBase *>(obj));
904}
905
906uint32_t rsContextGetMessage(RsContext vrsc, void *data, size_t *receiveLen, size_t bufferLen, bool wait)
907{
908    Context * rsc = static_cast<Context *>(vrsc);
909    return rsc->getMessageToClient(data, receiveLen, bufferLen, wait);
910}
911
912void rsContextInitToClient(RsContext vrsc)
913{
914    Context * rsc = static_cast<Context *>(vrsc);
915    rsc->initToClient();
916}
917
918void rsContextDeinitToClient(RsContext vrsc)
919{
920    Context * rsc = static_cast<Context *>(vrsc);
921    rsc->deinitToClient();
922}
923
924