/*
 * 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 "rsProgramRaster.h"

namespace android {
namespace renderscript {

ProgramRaster::ProgramRaster(Context *rsc, bool pointSprite, RsCullMode cull)
    : ProgramBase(rsc) {

    memset(&mHal, 0, sizeof(mHal));
    mHal.state.pointSprite = pointSprite;
    mHal.state.cull = cull;
    rsc->mHal.funcs.raster.init(rsc, this);
}

void ProgramRaster::preDestroy() const {
    auto& rasterPrograms = mRSC->mStateRaster.mRasterPrograms;
    for (uint32_t ct = 0; ct < rasterPrograms.size(); ct++) {
        if (rasterPrograms[ct] == this) {
            rasterPrograms.erase(rasterPrograms.begin() + ct);
            break;
        }
    }
}

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

void ProgramRaster::setup(const Context *rsc, ProgramRasterState *state) {
    if (state->mLast.get() == this && !mDirty) {
        return;
    }
    state->mLast.set(this);
    mDirty = false;

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

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

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

ProgramRasterState::ProgramRasterState() {
}

ProgramRasterState::~ProgramRasterState() {
}

void ProgramRasterState::init(Context *rsc) {
    mDefault.set(ProgramRaster::getProgramRaster(rsc, false, RS_CULL_BACK).get());
}

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

ObjectBaseRef<ProgramRaster> ProgramRaster::getProgramRaster(Context *rsc,
                                                             bool pointSprite,
                                                             RsCullMode cull) {
    ObjectBaseRef<ProgramRaster> returnRef;
    ObjectBase::asyncLock();
    for (uint32_t ct = 0; ct < rsc->mStateRaster.mRasterPrograms.size(); ct++) {
        ProgramRaster *existing = rsc->mStateRaster.mRasterPrograms[ct];
        if (existing->mHal.state.pointSprite != pointSprite) continue;
        if (existing->mHal.state.cull != cull) continue;
        returnRef.set(existing);
        ObjectBase::asyncUnlock();
        return returnRef;
    }
    ObjectBase::asyncUnlock();

    ProgramRaster *pr = new ProgramRaster(rsc, pointSprite, cull);
    returnRef.set(pr);

    ObjectBase::asyncLock();
    rsc->mStateRaster.mRasterPrograms.push_back(pr);
    ObjectBase::asyncUnlock();

    return returnRef;
}

RsProgramRaster rsi_ProgramRasterCreate(Context * rsc, bool pointSprite, RsCullMode cull) {
    ObjectBaseRef<ProgramRaster> pr = ProgramRaster::getProgramRaster(rsc, pointSprite, cull);
    pr->incUserRef();
    return pr.get();
}

} // namespace renderscript
} // namespace android
