/*
 * 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 {
    auto& storePrograms = mRSC->mStateFragmentStore.mStorePrograms;
    for (uint32_t ct = 0; ct < storePrograms.size(); ct++) {
        if (storePrograms[ct] == this) {
            storePrograms.erase(storePrograms.begin() + 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_back(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
