/*
 * Copyright (C) 2011 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 "rsdCore.h"
#include "rsdProgramStore.h"

#include "rsContext.h"
#include "rsProgramStore.h"

#include <GLES/gl.h>
#include <GLES/glext.h>

using android::renderscript::Context;
using android::renderscript::ProgramStore;

struct DrvProgramStore {
    GLenum blendSrc;
    GLenum blendDst;
    bool blendEnable;

    GLenum depthFunc;
    bool depthTestEnable;
};

bool rsdProgramStoreInit(const Context *rsc, const ProgramStore *ps) {
    DrvProgramStore *drv = (DrvProgramStore *)calloc(1, sizeof(DrvProgramStore));
    if (drv == nullptr) {
        return false;
    }

    ps->mHal.drv = drv;
    drv->depthTestEnable = true;

    switch (ps->mHal.state.depthFunc) {
    case RS_DEPTH_FUNC_ALWAYS:
        drv->depthTestEnable = false;
        drv->depthFunc = GL_ALWAYS;
        break;
    case RS_DEPTH_FUNC_LESS:
        drv->depthFunc = GL_LESS;
        break;
    case RS_DEPTH_FUNC_LEQUAL:
        drv->depthFunc = GL_LEQUAL;
        break;
    case RS_DEPTH_FUNC_GREATER:
        drv->depthFunc = GL_GREATER;
        break;
    case RS_DEPTH_FUNC_GEQUAL:
        drv->depthFunc = GL_GEQUAL;
        break;
    case RS_DEPTH_FUNC_EQUAL:
        drv->depthFunc = GL_EQUAL;
        break;
    case RS_DEPTH_FUNC_NOTEQUAL:
        drv->depthFunc = GL_NOTEQUAL;
        break;
    default:
        ALOGE("Unknown depth function.");
        goto error;
    }



    drv->blendEnable = true;
    if ((ps->mHal.state.blendSrc == RS_BLEND_SRC_ONE) &&
        (ps->mHal.state.blendDst == RS_BLEND_DST_ZERO)) {
        drv->blendEnable = false;
    }

    switch (ps->mHal.state.blendSrc) {
    case RS_BLEND_SRC_ZERO:
        drv->blendSrc = GL_ZERO;
        break;
    case RS_BLEND_SRC_ONE:
        drv->blendSrc = GL_ONE;
        break;
    case RS_BLEND_SRC_DST_COLOR:
        drv->blendSrc = GL_DST_COLOR;
        break;
    case RS_BLEND_SRC_ONE_MINUS_DST_COLOR:
        drv->blendSrc = GL_ONE_MINUS_DST_COLOR;
        break;
    case RS_BLEND_SRC_SRC_ALPHA:
        drv->blendSrc = GL_SRC_ALPHA;
        break;
    case RS_BLEND_SRC_ONE_MINUS_SRC_ALPHA:
        drv->blendSrc = GL_ONE_MINUS_SRC_ALPHA;
        break;
    case RS_BLEND_SRC_DST_ALPHA:
        drv->blendSrc = GL_DST_ALPHA;
        break;
    case RS_BLEND_SRC_ONE_MINUS_DST_ALPHA:
        drv->blendSrc = GL_ONE_MINUS_DST_ALPHA;
        break;
    case RS_BLEND_SRC_SRC_ALPHA_SATURATE:
        drv->blendSrc = GL_SRC_ALPHA_SATURATE;
        break;
    default:
        rsc->setError(RS_ERROR_FATAL_DRIVER, "Unknown blend src mode.");
        goto error;
    }

    switch (ps->mHal.state.blendDst) {
    case RS_BLEND_DST_ZERO:
        drv->blendDst = GL_ZERO;
        break;
    case RS_BLEND_DST_ONE:
        drv->blendDst = GL_ONE;
        break;
    case RS_BLEND_DST_SRC_COLOR:
        drv->blendDst = GL_SRC_COLOR;
        break;
    case RS_BLEND_DST_ONE_MINUS_SRC_COLOR:
        drv->blendDst = GL_ONE_MINUS_SRC_COLOR;
        break;
    case RS_BLEND_DST_SRC_ALPHA:
        drv->blendDst = GL_SRC_ALPHA;
        break;
    case RS_BLEND_DST_ONE_MINUS_SRC_ALPHA:
        drv->blendDst = GL_ONE_MINUS_SRC_ALPHA;
        break;
    case RS_BLEND_DST_DST_ALPHA:
        drv->blendDst = GL_DST_ALPHA;
        break;
    case RS_BLEND_DST_ONE_MINUS_DST_ALPHA:
        drv->blendDst = GL_ONE_MINUS_DST_ALPHA;
        break;
    default:
        rsc->setError(RS_ERROR_FATAL_DRIVER, "Unknown blend dst mode.");
        goto error;
    }

    return true;

error:
    free(drv);
    ps->mHal.drv = nullptr;
    return false;
}

void rsdProgramStoreSetActive(const Context *rsc, const ProgramStore *ps) {
    DrvProgramStore *drv = (DrvProgramStore *)ps->mHal.drv;

    RSD_CALL_GL(glColorMask, ps->mHal.state.colorRWriteEnable,
                ps->mHal.state.colorGWriteEnable,
                ps->mHal.state.colorBWriteEnable,
                ps->mHal.state.colorAWriteEnable);

    if (drv->blendEnable) {
        RSD_CALL_GL(glEnable, GL_BLEND);
        RSD_CALL_GL(glBlendFunc, drv->blendSrc, drv->blendDst);
    } else {
        RSD_CALL_GL(glDisable, GL_BLEND);
    }

    if (rsc->mUserSurfaceConfig.depthMin > 0) {
        RSD_CALL_GL(glDepthMask, ps->mHal.state.depthWriteEnable);
        if (drv->depthTestEnable || ps->mHal.state.depthWriteEnable) {
            RSD_CALL_GL(glEnable, GL_DEPTH_TEST);
            RSD_CALL_GL(glDepthFunc, drv->depthFunc);
        } else {
            RSD_CALL_GL(glDisable, GL_DEPTH_TEST);
        }
    } else {
        RSD_CALL_GL(glDepthMask, false);
        RSD_CALL_GL(glDisable, GL_DEPTH_TEST);
    }

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

    if (ps->mHal.state.ditherEnable) {
        RSD_CALL_GL(glEnable, GL_DITHER);
    } else {
        RSD_CALL_GL(glDisable, GL_DITHER);
    }
}

void rsdProgramStoreDestroy(const Context *rsc, const ProgramStore *ps) {
    free(ps->mHal.drv);
    ps->mHal.drv = nullptr;
}


