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

#include "backend/Device.h"
#include "backend/Texture.h"
#include "common/Assert.h"
#include "common/BitSetIterator.h"

namespace backend {

    // RenderPassDescriptor

    RenderPassDescriptorBase::RenderPassDescriptorBase(RenderPassDescriptorBuilder* builder)
        : mColorAttachmentsSet(builder->mColorAttachmentsSet),
          mColorAttachments(builder->mColorAttachments),
          mDepthStencilAttachmentSet(builder->mDepthStencilAttachmentSet),
          mDepthStencilAttachment(builder->mDepthStencilAttachment),
          mWidth(builder->mWidth),
          mHeight(builder->mHeight) {
    }

    std::bitset<kMaxColorAttachments> RenderPassDescriptorBase::GetColorAttachmentMask() const {
        return mColorAttachmentsSet;
    }

    bool RenderPassDescriptorBase::HasDepthStencilAttachment() const {
        return mDepthStencilAttachmentSet;
    }

    const RenderPassColorAttachmentInfo& RenderPassDescriptorBase::GetColorAttachment(
        uint32_t attachment) const {
        ASSERT(attachment < kMaxColorAttachments);
        ASSERT(mColorAttachmentsSet[attachment]);

        return mColorAttachments[attachment];
    }

    RenderPassColorAttachmentInfo& RenderPassDescriptorBase::GetColorAttachment(
        uint32_t attachment) {
        ASSERT(attachment < kMaxColorAttachments);
        ASSERT(mColorAttachmentsSet[attachment]);

        return mColorAttachments[attachment];
    }

    const RenderPassDepthStencilAttachmentInfo&
    RenderPassDescriptorBase::GetDepthStencilAttachment() const {
        ASSERT(mDepthStencilAttachmentSet);

        return mDepthStencilAttachment;
    }

    RenderPassDepthStencilAttachmentInfo& RenderPassDescriptorBase::GetDepthStencilAttachment() {
        ASSERT(mDepthStencilAttachmentSet);

        return mDepthStencilAttachment;
    }

    uint32_t RenderPassDescriptorBase::GetWidth() const {
        return mWidth;
    }

    uint32_t RenderPassDescriptorBase::GetHeight() const {
        return mHeight;
    }

    // RenderPassDescriptorBuilder

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

    RenderPassDescriptorBase* RenderPassDescriptorBuilder::GetResultImpl() {
        auto CheckOrSetSize = [this](const TextureViewBase* attachment) -> bool {
            if (this->mWidth == 0) {
                ASSERT(this->mHeight == 0);

                this->mWidth = attachment->GetTexture()->GetWidth();
                this->mHeight = attachment->GetTexture()->GetHeight();
                ASSERT(this->mWidth != 0 && this->mHeight != 0);

                return true;
            }

            ASSERT(this->mWidth != 0 && this->mHeight != 0);
            return this->mWidth == attachment->GetTexture()->GetWidth() &&
                   this->mHeight == attachment->GetTexture()->GetHeight();
        };

        uint32_t attachmentCount = 0;
        for (uint32_t i : IterateBitSet(mColorAttachmentsSet)) {
            attachmentCount++;
            if (!CheckOrSetSize(mColorAttachments[i].view.Get())) {
                HandleError("Attachment size mismatch");
                return nullptr;
            }
        }

        if (mDepthStencilAttachmentSet) {
            attachmentCount++;
            if (!CheckOrSetSize(mDepthStencilAttachment.view.Get())) {
                HandleError("Attachment size mismatch");
                return nullptr;
            }
        }

        if (attachmentCount == 0) {
            HandleError("Should have at least one attachment");
            return nullptr;
        }

        return mDevice->CreateRenderPassDescriptor(this);
    }

    void RenderPassDescriptorBuilder::SetColorAttachment(uint32_t attachment,
                                                         TextureViewBase* textureView,
                                                         nxt::LoadOp loadOp) {
        if (attachment >= kMaxColorAttachments) {
            HandleError("Setting color attachment out of bounds");
            return;
        }

        if (TextureFormatHasDepthOrStencil(textureView->GetTexture()->GetFormat())) {
            HandleError("Using depth stencil texture as color attachment");
            return;
        }

        mColorAttachmentsSet.set(attachment);
        mColorAttachments[attachment].loadOp = loadOp;
        mColorAttachments[attachment].view = textureView;
    }

    void RenderPassDescriptorBuilder::SetColorAttachmentClearColor(uint32_t attachment,
                                                                   float clearR,
                                                                   float clearG,
                                                                   float clearB,
                                                                   float clearA) {
        if (attachment >= kMaxColorAttachments) {
            HandleError("Setting color attachment out of bounds");
            return;
        }

        mColorAttachments[attachment].clearColor[0] = clearR;
        mColorAttachments[attachment].clearColor[1] = clearG;
        mColorAttachments[attachment].clearColor[2] = clearB;
        mColorAttachments[attachment].clearColor[3] = clearA;
    }

    void RenderPassDescriptorBuilder::SetDepthStencilAttachment(TextureViewBase* textureView,
                                                                nxt::LoadOp depthLoadOp,
                                                                nxt::LoadOp stencilLoadOp) {
        if (!TextureFormatHasDepthOrStencil(textureView->GetTexture()->GetFormat())) {
            HandleError("Using color texture as depth stencil attachment");
            return;
        }

        mDepthStencilAttachmentSet = true;
        mDepthStencilAttachment.depthLoadOp = depthLoadOp;
        mDepthStencilAttachment.stencilLoadOp = stencilLoadOp;
        mDepthStencilAttachment.view = textureView;
    }

    void RenderPassDescriptorBuilder::SetDepthStencilAttachmentClearValue(float clearDepth,
                                                                          uint32_t clearStencil) {
        mDepthStencilAttachment.clearDepth = clearDepth;
        mDepthStencilAttachment.clearStencil = clearStencil;
    }

}  // namespace backend
