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