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