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

#include "backend/Buffer.h"
#include "backend/Device.h"
#include "backend/RenderPass.h"
#include "backend/Texture.h"
#include "common/Assert.h"

namespace backend {

    // Framebuffer

    FramebufferBase::FramebufferBase(FramebufferBuilder* builder)
        : device(builder->device), renderPass(std::move(builder->renderPass)),
        width(builder->width), height(builder->height), textureViews(std::move(builder->textureViews)),
        clearColors(textureViews.size()), clearDepthStencils(textureViews.size()) {
    }

    DeviceBase* FramebufferBase::GetDevice() {
        return device;
    }

    RenderPassBase* FramebufferBase::GetRenderPass() {
        return renderPass.Get();
    }

    TextureViewBase* FramebufferBase::GetTextureView(uint32_t attachmentSlot) {
        ASSERT(attachmentSlot < textureViews.size());
        return textureViews[attachmentSlot].Get();
    }

    FramebufferBase::ClearColor FramebufferBase::GetClearColor(uint32_t attachmentSlot) {
        ASSERT(attachmentSlot < clearColors.size());
        return clearColors[attachmentSlot];
    }

    FramebufferBase::ClearDepthStencil FramebufferBase::GetClearDepthStencil(uint32_t attachmentSlot) {
        ASSERT(attachmentSlot < clearDepthStencils.size());
        return clearDepthStencils[attachmentSlot];
    }

    uint32_t FramebufferBase::GetWidth() const {
        return width;
    }

    uint32_t FramebufferBase::GetHeight() const {
        return height;
    }

    void FramebufferBase::AttachmentSetClearColor(uint32_t attachmentSlot, float clearR, float clearG, float clearB, float clearA) {
        if (attachmentSlot >= renderPass->GetAttachmentCount()) {
            device->HandleError("Framebuffer attachment out of bounds");
            return;
        }
        ASSERT(attachmentSlot < clearColors.size());
        auto& c = clearColors[attachmentSlot];
        c.color[0] = clearR;
        c.color[1] = clearG;
        c.color[2] = clearB;
        c.color[3] = clearA;
    }

    void FramebufferBase::AttachmentSetClearDepthStencil(uint32_t attachmentSlot, float clearDepth, uint32_t clearStencil) {
        if (attachmentSlot >= renderPass->GetAttachmentCount()) {
            device->HandleError("Framebuffer attachment out of bounds");
            return;
        }
        ASSERT(attachmentSlot < clearDepthStencils.size());
        auto& c = clearDepthStencils[attachmentSlot];
        c.depth = clearDepth;
        c.stencil = clearStencil;
    }

    // FramebufferBuilder

    enum FramebufferSetProperties {
        FRAMEBUFFER_PROPERTY_RENDER_PASS = 0x1,
        FRAMEBUFFER_PROPERTY_DIMENSIONS = 0x2,
    };

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

    FramebufferBase* FramebufferBuilder::GetResultImpl() {
        constexpr int requiredProperties = FRAMEBUFFER_PROPERTY_RENDER_PASS | FRAMEBUFFER_PROPERTY_DIMENSIONS;
        if ((propertiesSet & requiredProperties) != requiredProperties) {
            HandleError("Framebuffer missing properties");
            return nullptr;
        }

        // TODO(kainino@chromium.org): Remove this flag when the
        // null=backbuffer hack is removed. Then, using null texture views can
        // be completely disallowed.
        bool usingBackbufferHack = false;
        for (auto& textureView : textureViews) {
            if (!textureView) {
                if (usingBackbufferHack) {
                    // TODO(kainino@chromium.org) update this too
                    HandleError("Framebuffer has more than one null attachment");
                    return nullptr;
                }
                usingBackbufferHack = true;
                continue;
            }

            // TODO(cwallez@chromium.org): Adjust for the mip-level once that is supported.
            if (textureView->GetTexture()->GetWidth() != width ||
                textureView->GetTexture()->GetHeight() != height) {
                HandleError("Framebuffer size doesn't match attachment size");
                return nullptr;
            }
        }

        return device->CreateFramebuffer(this);
    }

    void FramebufferBuilder::SetRenderPass(RenderPassBase* renderPass) {
        if ((propertiesSet & FRAMEBUFFER_PROPERTY_RENDER_PASS) != 0) {
            HandleError("Framebuffer render pass property set multiple times");
            return;
        }
        // TODO(kainino@chromium.org): null checks should not be necessary
        if (renderPass == nullptr) {
            HandleError("Render pass invalid");
            return;
        }

        this->renderPass = renderPass;
        this->textureViews.resize(renderPass->GetAttachmentCount());
        propertiesSet |= FRAMEBUFFER_PROPERTY_RENDER_PASS;
    }

    void FramebufferBuilder::SetDimensions(uint32_t width, uint32_t height) {
        if ((propertiesSet & FRAMEBUFFER_PROPERTY_DIMENSIONS) != 0) {
            HandleError("Framebuffer dimensions property set multiple times");
            return;
        }

        this->width = width;
        this->height = height;
        propertiesSet |= FRAMEBUFFER_PROPERTY_DIMENSIONS;
    }

    void FramebufferBuilder::SetAttachment(uint32_t attachmentSlot, TextureViewBase* textureView) {
        if ((propertiesSet & FRAMEBUFFER_PROPERTY_RENDER_PASS) == 0) {
            HandleError("Render pass must be set before framebuffer attachments");
            return;
        }
        if (attachmentSlot >= textureViews.size()) {
            HandleError("Attachment slot out of bounds");
            return;
        }
        if (textureViews[attachmentSlot]) {
            HandleError("Framebuffer attachment[i] set multiple times");
            return;
        }
        const auto& attachmentInfo = renderPass->GetAttachmentInfo(attachmentSlot);
        const auto* texture = textureView->GetTexture();
        if (attachmentInfo.format != texture->GetFormat()) {
            HandleError("Texture format does not match attachment format");
            return;
        }
        // TODO(kainino@chromium.org): also check attachment samples, etc.

        textureViews[attachmentSlot] = textureView;
    }
}
