/*
 * 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 <GLES/gl.h>
#include <GLES/glext.h>

using namespace android;
using namespace android::renderscript;

pthread_key_t Context::gThreadTLSKey = 0;

void Context::initEGL()
{
    mEGL.mNumConfigs = -1;
    EGLint configAttribs[128];
    EGLint *configAttribsPtr = configAttribs;

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

    configAttribsPtr[0] = EGL_SURFACE_TYPE;
    configAttribsPtr[1] = EGL_WINDOW_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))));

    mEGL.mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    eglInitialize(mEGL.mDisplay, &mEGL.mMajorVersion, &mEGL.mMinorVersion);

    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 (mWndSurface) {
        mEGL.mSurface = eglCreateWindowSurface(mEGL.mDisplay, mEGL.mConfig, mWndSurface, NULL);
    } else {
        mEGL.mSurface = eglCreateWindowSurface(mEGL.mDisplay, mEGL.mConfig,
             android_createDisplaySurface(),
             NULL);
    }

    mEGL.mContext = eglCreateContext(mEGL.mDisplay, mEGL.mConfig, NULL, NULL);
    eglMakeCurrent(mEGL.mDisplay, mEGL.mSurface, mEGL.mSurface, mEGL.mContext);
    eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_WIDTH, &mEGL.mWidth);
    eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_HEIGHT, &mEGL.mHeight);


    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);

    if ((strlen((const char *)mGL.mVersion) < 12) || memcmp(mGL.mVersion, "OpenGL ES-CM", 12)) {
        LOGE("Error, OpenGL ES Lite not supported");
    } else {
        sscanf((const char *)mGL.mVersion + 13, "%i.%i", &mGL.mMajorVersion, &mGL.mMinorVersion);
    }
}

bool Context::runScript(Script *s, uint32_t launchID)
{
    ObjectBaseRef<ProgramFragment> frag(mFragment);
    ObjectBaseRef<ProgramVertex> vtx(mVertex);
    ObjectBaseRef<ProgramFragmentStore> store(mFragmentStore);

    bool ret = s->run(this, launchID);

    mFragment.set(frag);
    mVertex.set(vtx);
    mFragmentStore.set(store);
    return ret;
}


bool Context::runRootScript()
{
#if RS_LOG_TIMES
    timerSet(RS_TIMER_CLEAR_SWAP);
#endif
    rsAssert(mRootScript->mEnviroment.mIsRoot);

    eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_WIDTH, &mEGL.mWidth);
    eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_HEIGHT, &mEGL.mHeight);
    glViewport(0, 0, mEGL.mWidth, mEGL.mHeight);
    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
    //glEnable(GL_POINT_SMOOTH);

    glClearColor(mRootScript->mEnviroment.mClearColor[0],
                 mRootScript->mEnviroment.mClearColor[1],
                 mRootScript->mEnviroment.mClearColor[2],
                 mRootScript->mEnviroment.mClearColor[3]);
    if (mUseDepth) {
        glDepthMask(GL_TRUE);
        glClearDepthf(mRootScript->mEnviroment.mClearDepth);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    } else {
        glClear(GL_COLOR_BUFFER_BIT);
    }

#if RS_LOG_TIMES
    timerSet(RS_TIMER_SCRIPT);
#endif
    bool ret = runScript(mRootScript.get(), 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;

    LOGV("RS: Frame (%lli),   Script %2.1f (%lli),  Clear & Swap %2.1f (%lli),  Idle %2.1f (%lli),  Internal %2.1f (%lli)",
         frame / 1000000,
         100.0 * mTimers[RS_TIMER_SCRIPT] / total, mTimers[RS_TIMER_SCRIPT] / 1000000,
         100.0 * mTimers[RS_TIMER_CLEAR_SWAP] / total, mTimers[RS_TIMER_CLEAR_SWAP] / 1000000,
         100.0 * mTimers[RS_TIMER_IDLE] / total, mTimers[RS_TIMER_IDLE] / 1000000,
         100.0 * mTimers[RS_TIMER_INTERNAL] / total, mTimers[RS_TIMER_INTERNAL] / 1000000);
}

void Context::setupCheck()
{
    mFragmentStore->setupGL(this, &mStateFragmentStore);
    mFragment->setupGL(this, &mStateFragment);
    mRaster->setupGL(this, &mStateRaster);
    mVertex->setupGL(this, &mStateVertex);
}


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

     rsc->initEGL();

     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);
     }

     rsc->mStateRaster.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight);
     rsc->setRaster(NULL);
     rsc->mStateVertex.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight);
     rsc->setVertex(NULL);
     rsc->mStateFragment.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight);
     rsc->setFragment(NULL);
     rsc->mStateFragmentStore.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight);
     rsc->setFragmentStore(NULL);

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

         if (mDraw) {
             mDraw = rsc->runRootScript();
#if RS_LOG_TIMES
             rsc->timerSet(RS_TIMER_CLEAR_SWAP);
#endif
             eglSwapBuffers(rsc->mEGL.mDisplay, rsc->mEGL.mSurface);
#if RS_LOG_TIMES
             rsc->timerFrame();
             rsc->timerSet(RS_TIMER_INTERNAL);
             rsc->timerPrint();
             rsc->timerReset();
#endif
         }
         if (rsc->mObjDestroy.mNeedToEmpty) {
             rsc->objDestroyOOBRun();
         }
     }

     LOGV("RS Thread exiting");
     glClearColor(0,0,0,0);
     glClear(GL_COLOR_BUFFER_BIT);
     eglSwapBuffers(rsc->mEGL.mDisplay, rsc->mEGL.mSurface);
     eglTerminate(rsc->mEGL.mDisplay);
     rsc->objDestroyOOBRun();
     LOGV("RS Thread exited");
     return NULL;
}

Context::Context(Device *dev, Surface *sur, bool useDepth)
{
    dev->addContext(this);
    mDev = dev;
    mRunning = false;
    mExit = false;
    mUseDepth = useDepth;

    int status;
    pthread_attr_t threadAttr;

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

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

    sched_param sparam;
    sparam.sched_priority = ANDROID_PRIORITY_DISPLAY;
    pthread_attr_setschedparam(&threadAttr, &sparam);

    mWndSurface = sur;

    objDestroyOOBInit();
    timerInit();

    LOGV("RS Launching thread");
    status = pthread_create(&mThreadId, &threadAttr, threadProc, this);
    if (status) {
        LOGE("Failed to start rs context thread.");
    }

    while(!mRunning) {
        sleep(1);
    }

    pthread_attr_destroy(&threadAttr);
}

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

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

    if (mDev) {
        mDev->removeContext(this);
        pthread_key_delete(gThreadTLSKey);
    }

    objDestroyOOBDestroy();
}

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

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

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

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

void Context::allocationCheck(const Allocation *a)
{
    mVertex->checkUpdatedAllocation(a);
    mFragment->checkUpdatedAllocation(a);
    mFragmentStore->checkUpdatedAllocation(a);
}

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

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;
        }
    }
}

ObjectBase * Context::lookupName(const char *name) const
{
    for(size_t ct=0; ct < mNames.size(); ct++) {
        if (!strcmp(name, mNames[ct]->getName())) {
            return mNames[ct];
        }
    }
    return NULL;
}

void Context::appendNameDefines(String8 *str) const
{
    char buf[256];
    for (size_t ct=0; ct < mNames.size(); ct++) {
        str->append("#define NAMED_");
        str->append(mNames[ct]->getName());
        str->append(" ");
        sprintf(buf, "%i\n", (int)mNames[ct]);
        str->append(buf);
    }
}

void Context::appendVarDefines(String8 *str) const
{
    char buf[256];
    for (size_t ct=0; ct < mInt32Defines.size(); ct++) {
        str->append("#define ");
        str->append(mInt32Defines.keyAt(ct));
        str->append(" ");
        sprintf(buf, "%i\n", (int)mInt32Defines.valueAt(ct));
        str->append(buf);

    }
    for (size_t ct=0; ct < mFloatDefines.size(); ct++) {
        str->append("#define ");
        str->append(mFloatDefines.keyAt(ct));
        str->append(" ");
        sprintf(buf, "%ff\n", mFloatDefines.valueAt(ct));
        str->append(buf);
    }
}

bool Context::objDestroyOOBInit()
{
    int status = pthread_mutex_init(&mObjDestroy.mMutex, NULL);
    if (status) {
        LOGE("Context::ObjDestroyOOBInit mutex init failure");
        return false;
    }
    return true;
}

void Context::objDestroyOOBRun()
{
    if (mObjDestroy.mNeedToEmpty) {
        int status = pthread_mutex_lock(&mObjDestroy.mMutex);
        if (status) {
            LOGE("Context::ObjDestroyOOBRun: error %i locking for OOBRun.", status);
            return;
        }

        for (size_t ct = 0; ct < mObjDestroy.mDestroyList.size(); ct++) {
            mObjDestroy.mDestroyList[ct]->decUserRef();
        }
        mObjDestroy.mDestroyList.clear();
        mObjDestroy.mNeedToEmpty = false;

        status = pthread_mutex_unlock(&mObjDestroy.mMutex);
        if (status) {
            LOGE("Context::ObjDestroyOOBRun: error %i unlocking for set condition.", status);
        }
    }
}

void Context::objDestroyOOBDestroy()
{
    rsAssert(!mObjDestroy.mNeedToEmpty);
    pthread_mutex_destroy(&mObjDestroy.mMutex);
}

void Context::objDestroyAdd(ObjectBase *obj)
{
    int status = pthread_mutex_lock(&mObjDestroy.mMutex);
    if (status) {
        LOGE("Context::ObjDestroyOOBRun: error %i locking for OOBRun.", status);
        return;
    }

    mObjDestroy.mNeedToEmpty = true;
    mObjDestroy.mDestroyList.add(obj);

    status = pthread_mutex_unlock(&mObjDestroy.mMutex);
    if (status) {
        LOGE("Context::ObjDestroyOOBRun: error %i unlocking for set condition.", status);
    }
}



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

namespace android {
namespace renderscript {


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_ContextBindProgramFragmentStore(Context *rsc, RsProgramFragmentStore vpfs)
{
    ProgramFragmentStore *pfs = static_cast<ProgramFragmentStore *>(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_AssignName(Context *rsc, void * obj, const char *name, uint32_t len)
{
    ObjectBase *ob = static_cast<ObjectBase *>(obj);
    rsc->assignName(ob, name, len);
}

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

void rsi_ContextSetDefineF(Context *rsc, const char* name, float value)
{
    rsc->addInt32Define(name, value);
}

void rsi_ContextSetDefineI32(Context *rsc, const char* name, int32_t value)
{
    rsc->addFloatDefine(name, value);
}

}
}


RsContext rsContextCreate(RsDevice vdev, void *sur, uint32_t version, bool useDepth)
{
    Device * dev = static_cast<Device *>(vdev);
    Context *rsc = new Context(dev, (Surface *)sur, useDepth);
    return rsc;
}

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

void rsObjDestroyOOB(RsContext vrsc, void *obj)
{
    Context * rsc = static_cast<Context *>(vrsc);
    rsc->objDestroyAdd(static_cast<ObjectBase *>(obj));
}

