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