// Copyright 2017 The NXT Authors
//
// 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 "backend/DepthStencilState.h"

#include "backend/Device.h"

namespace backend {

    // DepthStencilStateBase

    DepthStencilStateBase::DepthStencilStateBase(DepthStencilStateBuilder* builder)
        : mDepthInfo(builder->mDepthInfo), mStencilInfo(builder->mStencilInfo) {
    }

    bool DepthStencilStateBase::StencilTestEnabled() const {
        return mStencilInfo.back.compareFunction != nxt::CompareFunction::Always ||
               mStencilInfo.back.stencilFail != nxt::StencilOperation::Keep ||
               mStencilInfo.back.depthFail != nxt::StencilOperation::Keep ||
               mStencilInfo.back.depthStencilPass != nxt::StencilOperation::Keep ||
               mStencilInfo.front.compareFunction != nxt::CompareFunction::Always ||
               mStencilInfo.front.stencilFail != nxt::StencilOperation::Keep ||
               mStencilInfo.front.depthFail != nxt::StencilOperation::Keep ||
               mStencilInfo.front.depthStencilPass != nxt::StencilOperation::Keep;
    }

    const DepthStencilStateBase::DepthInfo& DepthStencilStateBase::GetDepth() const {
        return mDepthInfo;
    }

    const DepthStencilStateBase::StencilInfo& DepthStencilStateBase::GetStencil() const {
        return mStencilInfo;
    }

    // DepthStencilStateBuilder

    enum DepthStencilStateSetProperties {
        DEPTH_STENCIL_STATE_PROPERTY_DEPTH_COMPARE_FUNCTION = 0x1,
        DEPTH_STENCIL_STATE_PROPERTY_DEPTH_WRITE_ENABLED = 0x2,
        DEPTH_STENCIL_STATE_PROPERTY_STENCIL_BACK_FUNCTION = 0x4,
        DEPTH_STENCIL_STATE_PROPERTY_STENCIL_FRONT_FUNCTION = 0x08,
        DEPTH_STENCIL_STATE_PROPERTY_STENCIL_MASK = 0x10,
    };

    DepthStencilStateBuilder::DepthStencilStateBuilder(DeviceBase* device) : Builder(device) {
    }

    DepthStencilStateBase* DepthStencilStateBuilder::GetResultImpl() {
        return mDevice->CreateDepthStencilState(this);
    }

    void DepthStencilStateBuilder::SetDepthCompareFunction(
        nxt::CompareFunction depthCompareFunction) {
        if ((mPropertiesSet & DEPTH_STENCIL_STATE_PROPERTY_DEPTH_COMPARE_FUNCTION) != 0) {
            HandleError("Depth compare property set multiple times");
            return;
        }

        mPropertiesSet |= DEPTH_STENCIL_STATE_PROPERTY_DEPTH_COMPARE_FUNCTION;

        mDepthInfo.compareFunction = depthCompareFunction;
    }

    void DepthStencilStateBuilder::SetDepthWriteEnabled(bool enabled) {
        if ((mPropertiesSet & DEPTH_STENCIL_STATE_PROPERTY_DEPTH_WRITE_ENABLED) != 0) {
            HandleError("Depth write enabled property set multiple times");
            return;
        }

        mPropertiesSet |= DEPTH_STENCIL_STATE_PROPERTY_DEPTH_WRITE_ENABLED;

        mDepthInfo.depthWriteEnabled = enabled;
    }

    void DepthStencilStateBuilder::SetStencilFunction(nxt::Face face,
                                                      nxt::CompareFunction stencilCompareFunction,
                                                      nxt::StencilOperation stencilFail,
                                                      nxt::StencilOperation depthFail,
                                                      nxt::StencilOperation depthStencilPass) {
        if (face == nxt::Face::None) {
            HandleError("Can't set stencil function of None face");
            return;
        }

        if (face & nxt::Face::Back) {
            if ((mPropertiesSet & DEPTH_STENCIL_STATE_PROPERTY_STENCIL_BACK_FUNCTION) != 0) {
                HandleError("Stencil back function property set multiple times");
                return;
            }

            mPropertiesSet |= DEPTH_STENCIL_STATE_PROPERTY_STENCIL_BACK_FUNCTION;

            mStencilInfo.back.compareFunction = stencilCompareFunction;
            mStencilInfo.back.stencilFail = stencilFail;
            mStencilInfo.back.depthFail = depthFail;
            mStencilInfo.back.depthStencilPass = depthStencilPass;
        }
        if (face & nxt::Face::Front) {
            if ((mPropertiesSet & DEPTH_STENCIL_STATE_PROPERTY_STENCIL_FRONT_FUNCTION) != 0) {
                HandleError("Stencil front function property set multiple times");
                return;
            }

            mPropertiesSet |= DEPTH_STENCIL_STATE_PROPERTY_STENCIL_FRONT_FUNCTION;

            mStencilInfo.front.compareFunction = stencilCompareFunction;
            mStencilInfo.front.stencilFail = stencilFail;
            mStencilInfo.front.depthFail = depthFail;
            mStencilInfo.front.depthStencilPass = depthStencilPass;
        }
    }

    void DepthStencilStateBuilder::SetStencilMask(uint32_t readMask, uint32_t writeMask) {
        if ((mPropertiesSet & DEPTH_STENCIL_STATE_PROPERTY_STENCIL_MASK) != 0) {
            HandleError("Stencilmask property set multiple times");
            return;
        }

        mPropertiesSet |= DEPTH_STENCIL_STATE_PROPERTY_STENCIL_MASK;
        mStencilInfo.readMask = readMask;
        mStencilInfo.writeMask = writeMask;
    }

}  // namespace backend
