/*
 * 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 "rsContext.h"
#include "rsProgramStore.h"

namespace android {
namespace renderscript {

ProgramStore::ProgramStore(Context *rsc,
                           bool colorMaskR, bool colorMaskG, bool colorMaskB, bool colorMaskA,
                           bool depthMask, bool ditherEnable,
                           RsBlendSrcFunc srcFunc, RsBlendDstFunc destFunc,
                           RsDepthFunc depthFunc) : ProgramBase(rsc) {
    memset(&mHal, 0, sizeof(mHal));

    mHal.state.ditherEnable = ditherEnable;

    mHal.state.colorRWriteEnable = colorMaskR;
    mHal.state.colorGWriteEnable = colorMaskG;
    mHal.state.colorBWriteEnable = colorMaskB;
    mHal.state.colorAWriteEnable = colorMaskA;
    mHal.state.blendSrc = srcFunc;
    mHal.state.blendDst = destFunc;

    mHal.state.depthWriteEnable = depthMask;
    mHal.state.depthFunc = depthFunc;
}

void ProgramStore::preDestroy() const {
    for (uint32_t ct = 0; ct < mRSC->mStateFragmentStore.mStorePrograms.size(); ct++) {
        if (mRSC->mStateFragmentStore.mStorePrograms[ct] == this) {
            mRSC->mStateFragmentStore.mStorePrograms.removeAt(ct);
            break;
        }
    }
}

ProgramStore::~ProgramStore() {
    mRSC->mHal.funcs.store.destroy(mRSC, this);
}

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

    rsc->mHal.funcs.store.setActive(rsc, this);
}

void ProgramStore::serialize(Context *rsc, OStream *stream) const {
}

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

void ProgramStore::init() {
    mRSC->mHal.funcs.store.init(mRSC, this);
}

ProgramStoreState::ProgramStoreState() {
}

ProgramStoreState::~ProgramStoreState() {
}

ObjectBaseRef<ProgramStore> ProgramStore::getProgramStore(Context *rsc,
                                                          bool colorMaskR,
                                                          bool colorMaskG,
                                                          bool colorMaskB,
                                                          bool colorMaskA,
                                                          bool depthMask, bool ditherEnable,
                                                          RsBlendSrcFunc srcFunc,
                                                          RsBlendDstFunc destFunc,
                                                          RsDepthFunc depthFunc) {
    ObjectBaseRef<ProgramStore> returnRef;
    ObjectBase::asyncLock();
    for (uint32_t ct = 0; ct < rsc->mStateFragmentStore.mStorePrograms.size(); ct++) {
        ProgramStore *existing = rsc->mStateFragmentStore.mStorePrograms[ct];
        if (existing->mHal.state.ditherEnable != ditherEnable) continue;
        if (existing->mHal.state.colorRWriteEnable != colorMaskR) continue;
        if (existing->mHal.state.colorGWriteEnable != colorMaskG) continue;
        if (existing->mHal.state.colorBWriteEnable != colorMaskB) continue;
        if (existing->mHal.state.colorAWriteEnable != colorMaskA) continue;
        if (existing->mHal.state.blendSrc != srcFunc) continue;
        if (existing->mHal.state.blendDst != destFunc) continue;
        if (existing->mHal.state.depthWriteEnable != depthMask) continue;
        if (existing->mHal.state.depthFunc != depthFunc) continue;

        returnRef.set(existing);
        ObjectBase::asyncUnlock();
        return returnRef;
    }
    ObjectBase::asyncUnlock();

    ProgramStore *pfs = new ProgramStore(rsc,
                                         colorMaskR, colorMaskG, colorMaskB, colorMaskA,
                                         depthMask, ditherEnable,
                                         srcFunc, destFunc, depthFunc);
    returnRef.set(pfs);

    pfs->init();

    ObjectBase::asyncLock();
    rsc->mStateFragmentStore.mStorePrograms.push(pfs);
    ObjectBase::asyncUnlock();

    return returnRef;
}



void ProgramStoreState::init(Context *rsc) {
    mDefault.set(ProgramStore::getProgramStore(rsc,
                                               true, true, true, true,
                                               true, true,
                                               RS_BLEND_SRC_ONE, RS_BLEND_DST_ZERO,
                                               RS_DEPTH_FUNC_LESS).get());
}

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


RsProgramStore rsi_ProgramStoreCreate(Context *rsc,
                                      bool colorMaskR, bool colorMaskG, bool colorMaskB, bool colorMaskA,
                                      bool depthMask, bool ditherEnable,
                                      RsBlendSrcFunc srcFunc, RsBlendDstFunc destFunc,
                                      RsDepthFunc depthFunc) {


    ObjectBaseRef<ProgramStore> ps = ProgramStore::getProgramStore(rsc,
                                                                   colorMaskR, colorMaskG,
                                                                   colorMaskB, colorMaskA,
                                                                   depthMask, ditherEnable,
                                                                   srcFunc, destFunc, depthFunc);
    ps->incUserRef();
    return ps.get();
}

} // namespace renderscript
} // namespace android
