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

#include "Buffer.h"
#include "Device.h"
#include "Texture.h"

namespace backend {

    // RenderPass

    RenderPassBase::RenderPassBase(RenderPassBuilder* builder)
        : attachments(std::move(builder->attachments)), subpasses(std::move(builder->subpasses)) {
    }

    uint32_t RenderPassBase::GetAttachmentCount() const {
        return attachments.size();
    }

    const RenderPassBase::AttachmentInfo& RenderPassBase::GetAttachmentInfo(uint32_t attachment) const {
        ASSERT(attachment < attachments.size());
        return attachments[attachment];
    }

    uint32_t RenderPassBase::GetSubpassCount() const {
        return subpasses.size();
    }

    const RenderPassBase::SubpassInfo& RenderPassBase::GetSubpassInfo(uint32_t subpass) const {
        ASSERT(subpass < subpasses.size());
        return subpasses[subpass];
    }

    bool RenderPassBase::IsCompatibleWith(const RenderPassBase* other) const {
        // TODO(kainino@chromium.org): This check is overly strict; need actual
        // compatibility checking (different load and store ops, etc.)
        return other == this;
    }

    // RenderPassBuilder

    enum RenderPassSetProperties {
        RENDERPASS_PROPERTY_ATTACHMENT_COUNT = 0x1,
        RENDERPASS_PROPERTY_SUBPASS_COUNT = 0x2,
    };

    RenderPassBuilder::RenderPassBuilder(DeviceBase* device)
        : Builder(device), subpasses(1) {
    }

    RenderPassBase* RenderPassBuilder::GetResultImpl() {
        constexpr int requiredProperties = RENDERPASS_PROPERTY_ATTACHMENT_COUNT | RENDERPASS_PROPERTY_SUBPASS_COUNT;
        if ((propertiesSet & requiredProperties) != requiredProperties) {
            HandleError("Render pass missing properties");
            return nullptr;
        }
        for (const auto& prop : attachmentProperties) {
            if (!prop.all()) {
                HandleError("A render pass attachment is missing some property");
                return nullptr;
            }
        }
        return device->CreateRenderPass(this);
    }

    void RenderPassBuilder::SetAttachmentCount(uint32_t attachmentCount) {
        if ((propertiesSet & RENDERPASS_PROPERTY_ATTACHMENT_COUNT) != 0) {
            HandleError("Render pass attachment count property set multiple times");
            return;
        }

        attachmentProperties.resize(attachmentCount);
        attachments.resize(attachmentCount);
        propertiesSet |= RENDERPASS_PROPERTY_ATTACHMENT_COUNT;
    }


    void RenderPassBuilder::AttachmentSetFormat(uint32_t attachmentSlot, nxt::TextureFormat format) {
        if ((propertiesSet & RENDERPASS_PROPERTY_ATTACHMENT_COUNT) == 0) {
            HandleError("Render pass attachment count not set yet");
            return;
        }
        if (attachmentSlot > attachments.size()) {
            HandleError("Render pass attachment index out of bounds");
            return;
        }
        if (attachmentProperties[attachmentSlot][ATTACHMENT_PROPERTY_FORMAT]) {
            HandleError("Render pass attachment format already set");
            return;
        }

        attachments[attachmentSlot].format = format;
        attachmentProperties[attachmentSlot].set(ATTACHMENT_PROPERTY_FORMAT);
    }

    void RenderPassBuilder::SetSubpassCount(uint32_t subpassCount) {
        if ((propertiesSet & RENDERPASS_PROPERTY_SUBPASS_COUNT) != 0) {
            HandleError("Render pass subpass count property set multiple times");
            return;
        }
        if (subpassCount < 1) {
            HandleError("Render pass cannot have fewer than one subpass");
            return;
        }

        subpasses.resize(subpassCount);
        propertiesSet |= RENDERPASS_PROPERTY_SUBPASS_COUNT;
    }

    void RenderPassBuilder::SubpassSetColorAttachment(uint32_t subpass, uint32_t outputAttachmentLocation, uint32_t attachmentSlot) {
        if ((propertiesSet & RENDERPASS_PROPERTY_SUBPASS_COUNT) == 0) {
            HandleError("Render pass subpass count not set yet");
            return;
        }
        if (subpass >= subpasses.size()) {
            HandleError("Subpass index out of bounds");
            return;
        }
        if (outputAttachmentLocation >= kMaxColorAttachments) {
            HandleError("Subpass output attachment location out of bounds");
            return;
        }
        if (attachmentSlot >= attachments.size()) {
            HandleError("Subpass attachment slot out of bounds");
            return;
        }
        if (subpasses[subpass].colorAttachmentsSet[outputAttachmentLocation]) {
            HandleError("Subpass color attachment already set");
            return;
        }

        subpasses[subpass].colorAttachmentsSet.set(outputAttachmentLocation);
        subpasses[subpass].colorAttachments[outputAttachmentLocation] = attachmentSlot;
    }

}
