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