/*
 * 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.
 */

#ifndef ANDROID_RS_BUILD_FOR_HOST
#include "rsContext.h"
#include <GLES/gl.h>
#include <GLES/glext.h>
#else
#include "rsContextHostStub.h"
#include <OpenGL/gl.h>
#include <OpenGl/glext.h>
#endif //ANDROID_RS_BUILD_FOR_HOST

#include "rsProgramStore.h"

using namespace android;
using namespace android::renderscript;


ProgramStore::ProgramStore(Context *rsc) :
    Program(rsc)
{
    mDitherEnable = true;
    mBlendEnable = false;
    mColorRWriteEnable = true;
    mColorGWriteEnable = true;
    mColorBWriteEnable = true;
    mColorAWriteEnable = true;
    mBlendSrc = GL_ONE;
    mBlendDst = GL_ZERO;


    mDepthTestEnable = false;
    mDepthWriteEnable = true;
    mDepthFunc = GL_LESS;


}

ProgramStore::~ProgramStore()
{
}

void ProgramStore::setupGL2(const Context *rsc, ProgramStoreState *state)
{
    if (state->mLast.get() == this) {
        return;
    }
    state->mLast.set(this);

    glColorMask(mColorRWriteEnable,
                mColorGWriteEnable,
                mColorBWriteEnable,
                mColorAWriteEnable);
    if (mBlendEnable) {
        glEnable(GL_BLEND);
        glBlendFunc(mBlendSrc, mBlendDst);
    } else {
        glDisable(GL_BLEND);
    }

    //LOGE("pfs  %i, %i, %x", mDepthWriteEnable, mDepthTestEnable, mDepthFunc);

    if (rsc->mUserSurfaceConfig.depthMin > 0) {
        glDepthMask(mDepthWriteEnable);
        if(mDepthTestEnable || mDepthWriteEnable) {
            glEnable(GL_DEPTH_TEST);
            glDepthFunc(mDepthFunc);
        } else {
            glDisable(GL_DEPTH_TEST);
        }
    } else {
        glDepthMask(false);
        glDisable(GL_DEPTH_TEST);
    }

    if (rsc->mUserSurfaceConfig.stencilMin > 0) {
    } else {
        glStencilMask(0);
        glDisable(GL_STENCIL_TEST);
    }

    if (mDitherEnable) {
        glEnable(GL_DITHER);
    } else {
        glDisable(GL_DITHER);
    }
}


void ProgramStore::setDitherEnable(bool enable)
{
    mDitherEnable = enable;
}

void ProgramStore::serialize(OStream *stream) const
{

}

ProgramStore *ProgramStore::createFromStream(Context *rsc, IStream *stream)
{
    return NULL;
}


void ProgramStore::setDepthFunc(RsDepthFunc func)
{
    mDepthTestEnable = true;

    switch(func) {
    case RS_DEPTH_FUNC_ALWAYS:
        mDepthTestEnable = false;
        mDepthFunc = GL_ALWAYS;
        break;
    case RS_DEPTH_FUNC_LESS:
        mDepthFunc = GL_LESS;
        break;
    case RS_DEPTH_FUNC_LEQUAL:
        mDepthFunc = GL_LEQUAL;
        break;
    case RS_DEPTH_FUNC_GREATER:
        mDepthFunc = GL_GREATER;
        break;
    case RS_DEPTH_FUNC_GEQUAL:
        mDepthFunc = GL_GEQUAL;
        break;
    case RS_DEPTH_FUNC_EQUAL:
        mDepthFunc = GL_EQUAL;
        break;
    case RS_DEPTH_FUNC_NOTEQUAL:
        mDepthFunc = GL_NOTEQUAL;
        break;
    }
}

void ProgramStore::setDepthMask(bool mask)
{
    mDepthWriteEnable = mask;
}

void ProgramStore::setBlendFunc(RsBlendSrcFunc src, RsBlendDstFunc dst)
{
    mBlendEnable = true;
    if ((src == RS_BLEND_SRC_ONE) &&
        (dst == RS_BLEND_DST_ZERO)) {
        mBlendEnable = false;
    }

    switch(src) {
    case RS_BLEND_SRC_ZERO:
        mBlendSrc = GL_ZERO;
        break;
    case RS_BLEND_SRC_ONE:
        mBlendSrc = GL_ONE;
        break;
    case RS_BLEND_SRC_DST_COLOR:
        mBlendSrc = GL_DST_COLOR;
        break;
    case RS_BLEND_SRC_ONE_MINUS_DST_COLOR:
        mBlendSrc = GL_ONE_MINUS_DST_COLOR;
        break;
    case RS_BLEND_SRC_SRC_ALPHA:
        mBlendSrc = GL_SRC_ALPHA;
        break;
    case RS_BLEND_SRC_ONE_MINUS_SRC_ALPHA:
        mBlendSrc = GL_ONE_MINUS_SRC_ALPHA;
        break;
    case RS_BLEND_SRC_DST_ALPHA:
        mBlendSrc = GL_DST_ALPHA;
        break;
    case RS_BLEND_SRC_ONE_MINUS_DST_ALPHA:
        mBlendSrc = GL_ONE_MINUS_DST_ALPHA;
        break;
    case RS_BLEND_SRC_SRC_ALPHA_SATURATE:
        mBlendSrc = GL_SRC_ALPHA_SATURATE;
        break;
    }

    switch(dst) {
    case RS_BLEND_DST_ZERO:
        mBlendDst = GL_ZERO;
        break;
    case RS_BLEND_DST_ONE:
        mBlendDst = GL_ONE;
        break;
    case RS_BLEND_DST_SRC_COLOR:
        mBlendDst = GL_SRC_COLOR;
        break;
    case RS_BLEND_DST_ONE_MINUS_SRC_COLOR:
        mBlendDst = GL_ONE_MINUS_SRC_COLOR;
        break;
    case RS_BLEND_DST_SRC_ALPHA:
        mBlendDst = GL_SRC_ALPHA;
        break;
    case RS_BLEND_DST_ONE_MINUS_SRC_ALPHA:
        mBlendDst = GL_ONE_MINUS_SRC_ALPHA;
        break;
    case RS_BLEND_DST_DST_ALPHA:
        mBlendDst = GL_DST_ALPHA;
        break;
    case RS_BLEND_DST_ONE_MINUS_DST_ALPHA:
        mBlendDst = GL_ONE_MINUS_DST_ALPHA;
        break;
    }
}

void ProgramStore::setColorMask(bool r, bool g, bool b, bool a)
{
    mColorRWriteEnable = r;
    mColorGWriteEnable = g;
    mColorBWriteEnable = b;
    mColorAWriteEnable = a;
}


ProgramStoreState::ProgramStoreState()
{
    mPFS = NULL;
}

ProgramStoreState::~ProgramStoreState()
{
    ObjectBase::checkDelete(mPFS);
    mPFS = NULL;
}

void ProgramStoreState::init(Context *rsc)
{
    ProgramStore *pfs = new ProgramStore(rsc);
    mDefault.set(pfs);
}

void ProgramStoreState::deinit(Context *rsc)
{
    mDefault.clear();
    mLast.clear();
}


namespace android {
namespace renderscript {

void rsi_ProgramStoreBegin(Context * rsc, RsElement in, RsElement out)
{
    ObjectBase::checkDelete(rsc->mStateFragmentStore.mPFS);
    rsc->mStateFragmentStore.mPFS = new ProgramStore(rsc);
}

void rsi_ProgramStoreDepthFunc(Context *rsc, RsDepthFunc func)
{
    rsc->mStateFragmentStore.mPFS->setDepthFunc(func);
}

void rsi_ProgramStoreDepthMask(Context *rsc, bool mask)
{
    rsc->mStateFragmentStore.mPFS->setDepthMask(mask);
}

void rsi_ProgramStoreColorMask(Context *rsc, bool r, bool g, bool b, bool a)
{
    rsc->mStateFragmentStore.mPFS->setColorMask(r, g, b, a);
}

void rsi_ProgramStoreBlendFunc(Context *rsc, RsBlendSrcFunc src, RsBlendDstFunc dst)
{
    rsc->mStateFragmentStore.mPFS->setBlendFunc(src, dst);
}

RsProgramStore rsi_ProgramStoreCreate(Context *rsc)
{
    ProgramStore *pfs = rsc->mStateFragmentStore.mPFS;
    pfs->incUserRef();
    rsc->mStateFragmentStore.mPFS = 0;
    return pfs;
}

void rsi_ProgramStoreDither(Context *rsc, bool enable)
{
    rsc->mStateFragmentStore.mPFS->setDitherEnable(enable);
}


}
}
