/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "rsDevice.h"
#include "rsContext.h"
#include "rsThreadIO.h"
#include <ui/FramebufferNativeWindow.h>
#include <ui/EGLUtils.h>
#include <ui/egl/android_natives.h>

#include <sys/types.h>
#include <sys/resource.h>
#include <sched.h>

#include <cutils/properties.h>

#include <GLES/gl.h>
#include <GLES/glext.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>

#include <cutils/sched_policy.h>

using namespace android;
using namespace android::renderscript;

pthread_key_t Context::gThreadTLSKey = 0;
uint32_t Context::gThreadTLSKeyCount = 0;
uint32_t Context::gGLContextCount = 0;
pthread_mutex_t Context::gInitMutex = PTHREAD_MUTEX_INITIALIZER;

static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
    if (returnVal != EGL_TRUE) {
        fprintf(stderr, "%s() returned %d\n", op, returnVal);
    }

    for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
            = eglGetError()) {
        fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error),
                error);
    }
}

void Context::initEGL(bool useGL2)
{
    mEGL.mNumConfigs = -1;
    EGLint configAttribs[128];
    EGLint *configAttribsPtr = configAttribs;
    EGLint context_attribs2[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };

    memset(configAttribs, 0, sizeof(configAttribs));

    configAttribsPtr[0] = EGL_SURFACE_TYPE;
    configAttribsPtr[1] = EGL_WINDOW_BIT;
    configAttribsPtr += 2;

    if (useGL2) {
        configAttribsPtr[0] = EGL_RENDERABLE_TYPE;
        configAttribsPtr[1] = EGL_OPENGL_ES2_BIT;
        configAttribsPtr += 2;
    }

    if (mUseDepth) {
        configAttribsPtr[0] = EGL_DEPTH_SIZE;
        configAttribsPtr[1] = 16;
        configAttribsPtr += 2;
    }

    if (mDev->mForceSW) {
        configAttribsPtr[0] = EGL_CONFIG_CAVEAT;
        configAttribsPtr[1] = EGL_SLOW_CONFIG;
        configAttribsPtr += 2;
    }

    configAttribsPtr[0] = EGL_NONE;
    rsAssert(configAttribsPtr < (configAttribs + (sizeof(configAttribs) / sizeof(EGLint))));

    LOGV("initEGL start");
    mEGL.mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    checkEglError("eglGetDisplay");

    eglInitialize(mEGL.mDisplay, &mEGL.mMajorVersion, &mEGL.mMinorVersion);
    checkEglError("eglInitialize");

    status_t err = EGLUtils::selectConfigForNativeWindow(mEGL.mDisplay, configAttribs, mWndSurface, &mEGL.mConfig);
    if (err) {
       LOGE("couldn't find an EGLConfig matching the screen format\n");
    }
    //eglChooseConfig(mEGL.mDisplay, configAttribs, &mEGL.mConfig, 1, &mEGL.mNumConfigs);


    if (useGL2) {
        mEGL.mContext = eglCreateContext(mEGL.mDisplay, mEGL.mConfig, EGL_NO_CONTEXT, context_attribs2);
    } else {
        mEGL.mContext = eglCreateContext(mEGL.mDisplay, mEGL.mConfig, EGL_NO_CONTEXT, NULL);
    }
    checkEglError("eglCreateContext");
    if (mEGL.mContext == EGL_NO_CONTEXT) {
        LOGE("eglCreateContext returned EGL_NO_CONTEXT");
    }
    gGLContextCount++;
}

void Context::deinitEGL()
{
    LOGV("deinitEGL");
    setSurface(0, 0, NULL);
    eglDestroyContext(mEGL.mDisplay, mEGL.mContext);
    checkEglError("eglDestroyContext");

    gGLContextCount--;
    if (!gGLContextCount) {
        eglTerminate(mEGL.mDisplay);
    }
}


uint32_t Context::runScript(Script *s)
{
    ObjectBaseRef<ProgramFragment> frag(mFragment);
    ObjectBaseRef<ProgramVertex> vtx(mVertex);
    ObjectBaseRef<ProgramStore> store(mFragmentStore);
    ObjectBaseRef<ProgramRaster> raster(mRaster);
    ObjectBaseRef<Font> font(mFont);

    uint32_t ret = s->run(this);

    mFragment.set(frag);
    mVertex.set(vtx);
    mFragmentStore.set(store);
    mRaster.set(raster);
    mFont.set(font);
    return ret;
}

void Context::checkError(const char *msg) const
{
    GLenum err = glGetError();
    if (err != GL_NO_ERROR) {
        LOGE("GL Error, 0x%x, from %s", err, msg);
    }
}

uint32_t Context::runRootScript()
{
    glViewport(0, 0, mWidth, mHeight);

    timerSet(RS_TIMER_SCRIPT);
    mStateFragmentStore.mLast.clear();
    uint32_t ret = runScript(mRootScript.get());

    checkError("runRootScript");
    if (mError != RS_ERROR_NONE) {
        // If we have an error condition we stop rendering until
        // somthing changes that might fix it.
        ret = 0;
    }
    return ret;
}

uint64_t Context::getTime() const
{
    struct timespec t;
    clock_gettime(CLOCK_MONOTONIC, &t);
    return t.tv_nsec + ((uint64_t)t.tv_sec * 1000 * 1000 * 1000);
}

void Context::timerReset()
{
    for (int ct=0; ct < _RS_TIMER_TOTAL; ct++) {
        mTimers[ct] = 0;
    }
}

void Context::timerInit()
{
    mTimeLast = getTime();
    mTimeFrame = mTimeLast;
    mTimeLastFrame = mTimeLast;
    mTimerActive = RS_TIMER_INTERNAL;
    timerReset();
}

void Context::timerFrame()
{
    mTimeLastFrame = mTimeFrame;
    mTimeFrame = getTime();
}

void Context::timerSet(Timers tm)
{
    uint64_t last = mTimeLast;
    mTimeLast = getTime();
    mTimers[mTimerActive] += mTimeLast - last;
    mTimerActive = tm;
}

void Context::timerPrint()
{
    double total = 0;
    for (int ct = 0; ct < _RS_TIMER_TOTAL; ct++) {
        total += mTimers[ct];
    }
    uint64_t frame = mTimeFrame - mTimeLastFrame;
    mTimeMSLastFrame = frame / 1000000;
    mTimeMSLastScript = mTimers[RS_TIMER_SCRIPT] / 1000000;
    mTimeMSLastSwap = mTimers[RS_TIMER_CLEAR_SWAP] / 1000000;


    if (props.mLogTimes) {
        LOGV("RS: Frame (%i),   Script %2.1f (%i),  Clear & Swap %2.1f (%i),  Idle %2.1f (%lli),  Internal %2.1f (%lli)",
             mTimeMSLastFrame,
             100.0 * mTimers[RS_TIMER_SCRIPT] / total, mTimeMSLastScript,
             100.0 * mTimers[RS_TIMER_CLEAR_SWAP] / total, mTimeMSLastSwap,
             100.0 * mTimers[RS_TIMER_IDLE] / total, mTimers[RS_TIMER_IDLE] / 1000000,
             100.0 * mTimers[RS_TIMER_INTERNAL] / total, mTimers[RS_TIMER_INTERNAL] / 1000000);
    }
}

bool Context::setupCheck()
{
    if (checkVersion2_0()) {
        if (!mShaderCache.lookup(this, mVertex.get(), mFragment.get())) {
            LOGE("Context::setupCheck() 1 fail");
            return false;
        }

        mFragmentStore->setupGL2(this, &mStateFragmentStore);
        mFragment->setupGL2(this, &mStateFragment, &mShaderCache);
        mRaster->setupGL2(this, &mStateRaster);
        mVertex->setupGL2(this, &mStateVertex, &mShaderCache);

    } else {
        mFragmentStore->setupGL(this, &mStateFragmentStore);
        mFragment->setupGL(this, &mStateFragment);
        mRaster->setupGL(this, &mStateRaster);
        mVertex->setupGL(this, &mStateVertex);
    }
    return true;
}

static bool getProp(const char *str)
{
    char buf[PROPERTY_VALUE_MAX];
    property_get(str, buf, "0");
    return 0 != strcmp(buf, "0");
}

void Context::displayDebugStats()
{
    char buffer[128];
    sprintf(buffer, "Frame %i ms, Script %i ms", mTimeMSLastFrame, mTimeMSLastScript);
    float oldR, oldG, oldB, oldA;
    mStateFont.getFontColor(&oldR, &oldG, &oldB, &oldA);

    float shadowCol = 0.2f;
    mStateFont.setFontColor(shadowCol, shadowCol, shadowCol, 1.0f);
    mStateFont.renderText(buffer, 5, getHeight() - 5);

    float textCol = 0.9f;
    mStateFont.setFontColor(textCol, textCol, textCol, 1.0f);
    mStateFont.renderText(buffer, 4, getHeight() - 6);

    mStateFont.setFontColor(oldR, oldG, oldB, oldA);
}

void * Context::threadProc(void *vrsc)
{
     Context *rsc = static_cast<Context *>(vrsc);
     rsc->mNativeThreadId = gettid();

     setpriority(PRIO_PROCESS, rsc->mNativeThreadId, ANDROID_PRIORITY_DISPLAY);
     rsc->mThreadPriority = ANDROID_PRIORITY_DISPLAY;

     rsc->props.mLogTimes = getProp("debug.rs.profile");
     rsc->props.mLogScripts = getProp("debug.rs.script");
     rsc->props.mLogObjects = getProp("debug.rs.object");
     rsc->props.mLogShaders = getProp("debug.rs.shader");
     rsc->props.mLogVisual = getProp("debug.rs.visual");

     ScriptTLSStruct *tlsStruct = new ScriptTLSStruct;
     if (!tlsStruct) {
         LOGE("Error allocating tls storage");
         return NULL;
     }
     tlsStruct->mContext = rsc;
     tlsStruct->mScript = NULL;
     int status = pthread_setspecific(rsc->gThreadTLSKey, tlsStruct);
     if (status) {
         LOGE("pthread_setspecific %i", status);
     }

     if (rsc->mIsGraphicsContext) {
         rsc->mStateRaster.init(rsc);
         rsc->setRaster(NULL);
         rsc->mStateVertex.init(rsc);
         rsc->setVertex(NULL);
         rsc->mStateFragment.init(rsc);
         rsc->setFragment(NULL);
         rsc->mStateFragmentStore.init(rsc);
         rsc->setFragmentStore(NULL);
         rsc->mStateFont.init(rsc);
         rsc->setFont(NULL);
         rsc->mStateVertexArray.init(rsc);
     }

     rsc->mRunning = true;
     bool mDraw = true;
     while (!rsc->mExit) {
         mDraw |= rsc->mIO.playCoreCommands(rsc, !mDraw);
         mDraw &= (rsc->mRootScript.get() != NULL);
         mDraw &= (rsc->mWndSurface != NULL);

         uint32_t targetTime = 0;
         if (mDraw && rsc->mIsGraphicsContext) {
             targetTime = rsc->runRootScript();

             if(rsc->props.mLogVisual) {
                 rsc->displayDebugStats();
             }

             mDraw = targetTime && !rsc->mPaused;
             rsc->timerSet(RS_TIMER_CLEAR_SWAP);
             eglSwapBuffers(rsc->mEGL.mDisplay, rsc->mEGL.mSurface);
             rsc->timerFrame();
             rsc->timerSet(RS_TIMER_INTERNAL);
             rsc->timerPrint();
             rsc->timerReset();
         }
         if (rsc->mThreadPriority > 0 && targetTime) {
             int32_t t = (targetTime - (int32_t)(rsc->mTimeMSLastScript + rsc->mTimeMSLastSwap)) * 1000;
             if (t > 0) {
                 usleep(t);
             }
         }
     }

     LOGV("RS Thread exiting");
     if (rsc->mIsGraphicsContext) {
         rsc->mRaster.clear();
         rsc->mFragment.clear();
         rsc->mVertex.clear();
         rsc->mFragmentStore.clear();
         rsc->mFont.clear();
         rsc->mRootScript.clear();
         rsc->mStateRaster.deinit(rsc);
         rsc->mStateVertex.deinit(rsc);
         rsc->mStateFragment.deinit(rsc);
         rsc->mStateFragmentStore.deinit(rsc);
         rsc->mStateFont.deinit(rsc);
     }
     ObjectBase::zeroAllUserRef(rsc);

     if (rsc->mIsGraphicsContext) {
         pthread_mutex_lock(&gInitMutex);
         rsc->deinitEGL();
         pthread_mutex_unlock(&gInitMutex);
     }

     LOGV("RS Thread exited");
     return NULL;
}

void * Context::helperThreadProc(void *vrsc)
{
     Context *rsc = static_cast<Context *>(vrsc);
     uint32_t idx = (uint32_t)android_atomic_inc(&rsc->mWorkers.mLaunchCount);

     LOGV("RS helperThread starting %p idx=%i", rsc, idx);

     rsc->mWorkers.mLaunchSignals[idx].init();
     rsc->mWorkers.mNativeThreadId[idx] = gettid();

     //cpu_set_t cpset[16];
     //int ret = sched_getaffinity(rsc->mWorkers.mNativeThreadId[idx], sizeof(cpset), &cpset);
     //LOGE("ret = %i", ret);

//sched_setaffinity

     setpriority(PRIO_PROCESS, rsc->mWorkers.mNativeThreadId[idx], rsc->mThreadPriority);
     while(rsc->mRunning) {
         rsc->mWorkers.mLaunchSignals[idx].wait();
         if (rsc->mWorkers.mLaunchCallback) {
            rsc->mWorkers.mLaunchCallback(rsc->mWorkers.mLaunchData, idx);
         }
         android_atomic_dec(&rsc->mWorkers.mRunningCount);
         rsc->mWorkers.mCompleteSignal.set();
     }

     LOGV("RS helperThread exiting %p idx=%i", rsc, idx);
     return NULL;
}

void Context::launchThreads(WorkerCallback_t cbk, void *data)
{
    mWorkers.mLaunchData = data;
    mWorkers.mLaunchCallback = cbk;
    mWorkers.mRunningCount = (int)mWorkers.mCount;
    for (uint32_t ct = 0; ct < mWorkers.mCount; ct++) {
        mWorkers.mLaunchSignals[ct].set();
    }
    while(mWorkers.mRunningCount) {
        mWorkers.mCompleteSignal.wait();
    }
}

void Context::setPriority(int32_t p)
{
    // Note: If we put this in the proper "background" policy
    // the wallpapers can become completly unresponsive at times.
    // This is probably not what we want for something the user is actively
    // looking at.
    mThreadPriority = p;
#if 0
    SchedPolicy pol = SP_FOREGROUND;
    if (p > 0) {
        pol = SP_BACKGROUND;
    }
    if (!set_sched_policy(mNativeThreadId, pol)) {
        // success; reset the priority as well
    }
#else
    setpriority(PRIO_PROCESS, mNativeThreadId, p);
    for (uint32_t ct=0; ct < mWorkers.mCount; ct++) {
        setpriority(PRIO_PROCESS, mWorkers.mNativeThreadId[ct], p);
    }
#endif
}

Context::Context(Device *dev, bool isGraphics, bool useDepth)
{
    pthread_mutex_lock(&gInitMutex);

    dev->addContext(this);
    mDev = dev;
    mRunning = false;
    mExit = false;
    mUseDepth = useDepth;
    mPaused = false;
    mObjHead = NULL;
    mError = RS_ERROR_NONE;
    mErrorMsg = NULL;

    memset(&mEGL, 0, sizeof(mEGL));
    memset(&mGL, 0, sizeof(mGL));
    mIsGraphicsContext = isGraphics;

    int status;
    pthread_attr_t threadAttr;

    if (!gThreadTLSKeyCount) {
        status = pthread_key_create(&gThreadTLSKey, NULL);
        if (status) {
            LOGE("Failed to init thread tls key.");
            pthread_mutex_unlock(&gInitMutex);
            return;
        }
    }
    gThreadTLSKeyCount++;
    pthread_mutex_unlock(&gInitMutex);

    // Global init done at this point.

    status = pthread_attr_init(&threadAttr);
    if (status) {
        LOGE("Failed to init thread attribute.");
        return;
    }

    mWndSurface = NULL;

    timerInit();
    timerSet(RS_TIMER_INTERNAL);

    int cpu = sysconf(_SC_NPROCESSORS_ONLN);
    LOGV("RS Launching thread(s), reported CPU count %i", cpu);
    if (cpu < 2) cpu = 0;

    mWorkers.mCount = (uint32_t)cpu;
    mWorkers.mThreadId = (pthread_t *) calloc(mWorkers.mCount, sizeof(pthread_t));
    mWorkers.mNativeThreadId = (pid_t *) calloc(mWorkers.mCount, sizeof(pid_t));
    mWorkers.mLaunchSignals = new Signal[mWorkers.mCount];
    mWorkers.mLaunchCallback = NULL;
    status = pthread_create(&mThreadId, &threadAttr, threadProc, this);
    if (status) {
        LOGE("Failed to start rs context thread.");
        return;
    }
    while(!mRunning) {
        usleep(100);
    }

    mWorkers.mRunningCount = 0;
    mWorkers.mLaunchCount = 0;
    for (uint32_t ct=0; ct < mWorkers.mCount; ct++) {
        status = pthread_create(&mWorkers.mThreadId[ct], &threadAttr, helperThreadProc, this);
        if (status) {
            mWorkers.mCount = ct;
            LOGE("Created fewer than expected number of RS threads.");
            break;
        }
    }


    pthread_attr_destroy(&threadAttr);
}

Context::~Context()
{
    LOGV("Context::~Context");
    mExit = true;
    mPaused = false;
    void *res;

    mIO.shutdown();
    int status = pthread_join(mThreadId, &res);

    // Global structure cleanup.
    pthread_mutex_lock(&gInitMutex);
    if (mDev) {
        mDev->removeContext(this);
        --gThreadTLSKeyCount;
        if (!gThreadTLSKeyCount) {
            pthread_key_delete(gThreadTLSKey);
        }
        mDev = NULL;
    }
    pthread_mutex_unlock(&gInitMutex);
}

void Context::setSurface(uint32_t w, uint32_t h, ANativeWindow *sur)
{
    rsAssert(mIsGraphicsContext);

    EGLBoolean ret;
    if (mEGL.mSurface != NULL) {
        ret = eglMakeCurrent(mEGL.mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
        checkEglError("eglMakeCurrent", ret);

        ret = eglDestroySurface(mEGL.mDisplay, mEGL.mSurface);
        checkEglError("eglDestroySurface", ret);

        mEGL.mSurface = NULL;
        mWidth = 0;
        mHeight = 0;
    }

    mWndSurface = sur;
    if (mWndSurface != NULL) {
        mWidth = w;
        mHeight = h;
        bool first = false;
        if (!mEGL.mContext) {
            first = true;
            pthread_mutex_lock(&gInitMutex);
            initEGL(true);
            pthread_mutex_unlock(&gInitMutex);
        }

        mEGL.mSurface = eglCreateWindowSurface(mEGL.mDisplay, mEGL.mConfig, mWndSurface, NULL);
        checkEglError("eglCreateWindowSurface");
        if (mEGL.mSurface == EGL_NO_SURFACE) {
            LOGE("eglCreateWindowSurface returned EGL_NO_SURFACE");
        }

        ret = eglMakeCurrent(mEGL.mDisplay, mEGL.mSurface, mEGL.mSurface, mEGL.mContext);
        checkEglError("eglMakeCurrent", ret);

        mStateVertex.updateSize(this);

        if (first) {
            mGL.mVersion = glGetString(GL_VERSION);
            mGL.mVendor = glGetString(GL_VENDOR);
            mGL.mRenderer = glGetString(GL_RENDERER);
            mGL.mExtensions = glGetString(GL_EXTENSIONS);

            //LOGV("EGL Version %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion);
            LOGV("GL Version %s", mGL.mVersion);
            //LOGV("GL Vendor %s", mGL.mVendor);
            LOGV("GL Renderer %s", mGL.mRenderer);
            //LOGV("GL Extensions %s", mGL.mExtensions);

            const char *verptr = NULL;
            if (strlen((const char *)mGL.mVersion) > 9) {
                if (!memcmp(mGL.mVersion, "OpenGL ES-CM", 12)) {
                    verptr = (const char *)mGL.mVersion + 12;
                }
                if (!memcmp(mGL.mVersion, "OpenGL ES ", 10)) {
                    verptr = (const char *)mGL.mVersion + 9;
                }
            }

            if (!verptr) {
                LOGE("Error, OpenGL ES Lite not supported");
            } else {
                sscanf(verptr, " %i.%i", &mGL.mMajorVersion, &mGL.mMinorVersion);
            }

            glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &mGL.mMaxVertexAttribs);
            glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &mGL.mMaxVertexUniformVectors);
            glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mGL.mMaxVertexTextureUnits);

            glGetIntegerv(GL_MAX_VARYING_VECTORS, &mGL.mMaxVaryingVectors);
            glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mGL.mMaxTextureImageUnits);

            glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &mGL.mMaxFragmentTextureImageUnits);
            glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &mGL.mMaxFragmentUniformVectors);

            mGL.OES_texture_npot = NULL != strstr((const char *)mGL.mExtensions, "GL_OES_texture_npot");
        }

    }
}

void Context::pause()
{
    rsAssert(mIsGraphicsContext);
    mPaused = true;
}

void Context::resume()
{
    rsAssert(mIsGraphicsContext);
    mPaused = false;
}

void Context::setRootScript(Script *s)
{
    rsAssert(mIsGraphicsContext);
    mRootScript.set(s);
}

void Context::setFragmentStore(ProgramStore *pfs)
{
    rsAssert(mIsGraphicsContext);
    if (pfs == NULL) {
        mFragmentStore.set(mStateFragmentStore.mDefault);
    } else {
        mFragmentStore.set(pfs);
    }
}

void Context::setFragment(ProgramFragment *pf)
{
    rsAssert(mIsGraphicsContext);
    if (pf == NULL) {
        mFragment.set(mStateFragment.mDefault);
    } else {
        mFragment.set(pf);
    }
}

void Context::setRaster(ProgramRaster *pr)
{
    rsAssert(mIsGraphicsContext);
    if (pr == NULL) {
        mRaster.set(mStateRaster.mDefault);
    } else {
        mRaster.set(pr);
    }
}

void Context::setVertex(ProgramVertex *pv)
{
    rsAssert(mIsGraphicsContext);
    if (pv == NULL) {
        mVertex.set(mStateVertex.mDefault);
    } else {
        mVertex.set(pv);
    }
}

void Context::setFont(Font *f)
{
    rsAssert(mIsGraphicsContext);
    if (f == NULL) {
        mFont.set(mStateFont.mDefault);
    } else {
        mFont.set(f);
    }
}

void Context::assignName(ObjectBase *obj, const char *name, uint32_t len)
{
    rsAssert(!obj->getName());
    obj->setName(name, len);
    mNames.add(obj);
}

void Context::removeName(ObjectBase *obj)
{
    for(size_t ct=0; ct < mNames.size(); ct++) {
        if (obj == mNames[ct]) {
            mNames.removeAt(ct);
            return;
        }
    }
}

uint32_t Context::getMessageToClient(void *data, size_t *receiveLen, size_t bufferLen, bool wait)
{
    //LOGE("getMessageToClient %i %i", bufferLen, wait);
    if (!wait) {
        if (mIO.mToClient.isEmpty()) {
            // No message to get and not going to wait for one.
            receiveLen = 0;
            return 0;
        }
    }

    //LOGE("getMessageToClient 2 con=%p", this);
    uint32_t bytesData = 0;
    uint32_t commandID = 0;
    const void *d = mIO.mToClient.get(&commandID, &bytesData);
    //LOGE("getMessageToClient 3    %i  %i", commandID, bytesData);

    *receiveLen = bytesData;
    if (bufferLen >= bytesData) {
        memcpy(data, d, bytesData);
        mIO.mToClient.next();
        return commandID;
    }
    return 0;
}

bool Context::sendMessageToClient(void *data, uint32_t cmdID, size_t len, bool waitForSpace)
{
    //LOGE("sendMessageToClient %i %i %i", cmdID, len, waitForSpace);
    if (cmdID == 0) {
        LOGE("Attempting to send invalid command 0 to client.");
        return false;
    }
    if (!waitForSpace) {
        if (!mIO.mToClient.makeSpaceNonBlocking(len + 8)) {
            // Not enough room, and not waiting.
            return false;
        }
    }
    //LOGE("sendMessageToClient 2");
    if (len > 0) {
        void *p = mIO.mToClient.reserve(len);
        memcpy(p, data, len);
        mIO.mToClient.commit(cmdID, len);
    } else {
        mIO.mToClient.commit(cmdID, 0);
    }
    //LOGE("sendMessageToClient 3");
    return true;
}

void Context::initToClient()
{
    while(!mRunning) {
        usleep(100);
    }
}

void Context::deinitToClient()
{
    mIO.mToClient.shutdown();
}

const char * Context::getError(RsError *err)
{
    *err = mError;
    mError = RS_ERROR_NONE;
    if (*err != RS_ERROR_NONE) {
        return mErrorMsg;
    }
    return NULL;
}

void Context::setError(RsError e, const char *msg)
{
    mError = e;
    mErrorMsg = msg;
}


void Context::dumpDebug() const
{
    LOGE("RS Context debug %p", this);
    LOGE("RS Context debug");

    LOGE(" EGL ver %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion);
    LOGE(" EGL context %p  surface %p,  Display=%p", mEGL.mContext, mEGL.mSurface, mEGL.mDisplay);
    LOGE(" GL vendor: %s", mGL.mVendor);
    LOGE(" GL renderer: %s", mGL.mRenderer);
    LOGE(" GL Version: %s", mGL.mVersion);
    LOGE(" GL Extensions: %s", mGL.mExtensions);
    LOGE(" GL int Versions %i %i", mGL.mMajorVersion, mGL.mMinorVersion);
    LOGE(" RS width %i, height %i", mWidth, mHeight);
    LOGE(" RS running %i, exit %i, useDepth %i, paused %i", mRunning, mExit, mUseDepth, mPaused);
    LOGE(" RS pThreadID %li, nativeThreadID %i", mThreadId, mNativeThreadId);

    LOGV("MAX Textures %i, %i  %i", mGL.mMaxVertexTextureUnits, mGL.mMaxFragmentTextureImageUnits, mGL.mMaxTextureImageUnits);
    LOGV("MAX Attribs %i", mGL.mMaxVertexAttribs);
    LOGV("MAX Uniforms %i, %i", mGL.mMaxVertexUniformVectors, mGL.mMaxFragmentUniformVectors);
    LOGV("MAX Varyings %i", mGL.mMaxVaryingVectors);
}

///////////////////////////////////////////////////////////////////////////////////////////
//

namespace android {
namespace renderscript {

void rsi_ContextFinish(Context *rsc)
{
}

void rsi_ContextBindRootScript(Context *rsc, RsScript vs)
{
    Script *s = static_cast<Script *>(vs);
    rsc->setRootScript(s);
}

void rsi_ContextBindSampler(Context *rsc, uint32_t slot, RsSampler vs)
{
    Sampler *s = static_cast<Sampler *>(vs);

    if (slot > RS_MAX_SAMPLER_SLOT) {
        LOGE("Invalid sampler slot");
        return;
    }

    s->bindToContext(&rsc->mStateSampler, slot);
}

void rsi_ContextBindProgramStore(Context *rsc, RsProgramStore vpfs)
{
    ProgramStore *pfs = static_cast<ProgramStore *>(vpfs);
    rsc->setFragmentStore(pfs);
}

void rsi_ContextBindProgramFragment(Context *rsc, RsProgramFragment vpf)
{
    ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
    rsc->setFragment(pf);
}

void rsi_ContextBindProgramRaster(Context *rsc, RsProgramRaster vpr)
{
    ProgramRaster *pr = static_cast<ProgramRaster *>(vpr);
    rsc->setRaster(pr);
}

void rsi_ContextBindProgramVertex(Context *rsc, RsProgramVertex vpv)
{
    ProgramVertex *pv = static_cast<ProgramVertex *>(vpv);
    rsc->setVertex(pv);
}

void rsi_ContextBindFont(Context *rsc, RsFont vfont)
{
    Font *font = static_cast<Font *>(vfont);
    rsc->setFont(font);
}

void rsi_AssignName(Context *rsc, void * obj, const char *name, uint32_t len)
{
    ObjectBase *ob = static_cast<ObjectBase *>(obj);
    rsc->assignName(ob, name, len);
}

void rsi_GetName(Context *rsc, void * obj, const char **name)
{
    ObjectBase *ob = static_cast<ObjectBase *>(obj);
    (*name) = ob->getName();
}

void rsi_ObjDestroy(Context *rsc, void *obj)
{
    ObjectBase *ob = static_cast<ObjectBase *>(obj);
    rsc->removeName(ob);
    ob->decUserRef();
}

void rsi_ContextPause(Context *rsc)
{
    rsc->pause();
}

void rsi_ContextResume(Context *rsc)
{
    rsc->resume();
}

void rsi_ContextSetSurface(Context *rsc, uint32_t w, uint32_t h, ANativeWindow *sur)
{
    rsc->setSurface(w, h, sur);
}

void rsi_ContextSetPriority(Context *rsc, int32_t p)
{
    rsc->setPriority(p);
}

void rsi_ContextDump(Context *rsc, int32_t bits)
{
    ObjectBase::dumpAll(rsc);
}

const char * rsi_ContextGetError(Context *rsc, RsError *e)
{
    const char *msg = rsc->getError(e);
    if (*e != RS_ERROR_NONE) {
        LOGE("RS Error %i %s", *e, msg);
    }
    return msg;
}

}
}


RsContext rsContextCreate(RsDevice vdev, uint32_t version)
{
    LOGV("rsContextCreate %p", vdev);
    Device * dev = static_cast<Device *>(vdev);
    Context *rsc = new Context(dev, false, false);
    return rsc;
}

RsContext rsContextCreateGL(RsDevice vdev, uint32_t version, bool useDepth)
{
    LOGV("rsContextCreateGL %p, %i", vdev, useDepth);
    Device * dev = static_cast<Device *>(vdev);
    Context *rsc = new Context(dev, true, useDepth);
    return rsc;
}

void rsContextDestroy(RsContext vrsc)
{
    Context * rsc = static_cast<Context *>(vrsc);
    delete rsc;
}

uint32_t rsContextGetMessage(RsContext vrsc, void *data, size_t *receiveLen, size_t bufferLen, bool wait)
{
    Context * rsc = static_cast<Context *>(vrsc);
    return rsc->getMessageToClient(data, receiveLen, bufferLen, wait);
}

void rsContextInitToClient(RsContext vrsc)
{
    Context * rsc = static_cast<Context *>(vrsc);
    rsc->initToClient();
}

void rsContextDeinitToClient(RsContext vrsc)
{
    Context * rsc = static_cast<Context *>(vrsc);
    rsc->deinitToClient();
}

