// Copyright 2019 The Dawn 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 "dawn_native/AttachmentState.h"

#include "common/BitSetIterator.h"
#include "common/HashUtils.h"
#include "dawn_native/Device.h"
#include "dawn_native/Texture.h"

namespace dawn_native {

    AttachmentStateBlueprint::AttachmentStateBlueprint(const RenderPipelineDescriptor* descriptor)
        : mHasDepthStencilAttachment(descriptor->depthStencilState != nullptr),
          mSampleCount(descriptor->sampleCount) {
        for (uint32_t i = 0; i < descriptor->colorStateCount; ++i) {
            ASSERT(descriptor->colorStates[i] != nullptr);
            mColorAttachmentsSet.set(i);
            mColorFormats[i] = descriptor->colorStates[i]->format;
        }
        if (mHasDepthStencilAttachment) {
            mDepthStencilFormat = descriptor->depthStencilState->format;
        }
    }

    AttachmentStateBlueprint::AttachmentStateBlueprint(const RenderPassDescriptor* descriptor)
        : mHasDepthStencilAttachment(descriptor->depthStencilAttachment != nullptr) {
        for (uint32_t i = 0; i < descriptor->colorAttachmentCount; ++i) {
            TextureViewBase* attachment = descriptor->colorAttachments[i]->attachment;
            mColorAttachmentsSet.set(i);
            mColorFormats[i] = attachment->GetFormat().format;
            if (mSampleCount == 0) {
                mSampleCount = attachment->GetTexture()->GetSampleCount();
            } else {
                ASSERT(mSampleCount == attachment->GetTexture()->GetSampleCount());
            }
        }
        if (mHasDepthStencilAttachment) {
            TextureViewBase* attachment = descriptor->depthStencilAttachment->attachment;
            mDepthStencilFormat = attachment->GetFormat().format;
            if (mSampleCount == 0) {
                mSampleCount = attachment->GetTexture()->GetSampleCount();
            } else {
                ASSERT(mSampleCount == attachment->GetTexture()->GetSampleCount());
            }
        }
        ASSERT(mSampleCount > 0);
    }

    AttachmentStateBlueprint::AttachmentStateBlueprint(const AttachmentStateBlueprint& rhs) =
        default;

    size_t AttachmentStateBlueprint::HashFunc::operator()(
        const AttachmentStateBlueprint* attachmentState) const {
        size_t hash = 0;

        // Hash color formats
        HashCombine(&hash, attachmentState->mColorAttachmentsSet);
        for (uint32_t i : IterateBitSet(attachmentState->mColorAttachmentsSet)) {
            HashCombine(&hash, attachmentState->mColorFormats[i]);
        }

        // Hash depth stencil attachments
        if (attachmentState->mHasDepthStencilAttachment) {
            HashCombine(&hash, attachmentState->mDepthStencilFormat);
        }

        // Hash sample count
        HashCombine(&hash, attachmentState->mSampleCount);

        return hash;
    }

    bool AttachmentStateBlueprint::EqualityFunc::operator()(
        const AttachmentStateBlueprint* a,
        const AttachmentStateBlueprint* b) const {
        // Check set attachments
        if (a->mColorAttachmentsSet != b->mColorAttachmentsSet ||
            a->mHasDepthStencilAttachment != b->mHasDepthStencilAttachment) {
            return false;
        }

        // Check color formats
        for (uint32_t i : IterateBitSet(a->mColorAttachmentsSet)) {
            if (a->mColorFormats[i] != b->mColorFormats[i]) {
                return false;
            }
        }

        // Check depth stencil format
        if (a->mHasDepthStencilAttachment) {
            if (a->mDepthStencilFormat != b->mDepthStencilFormat) {
                return false;
            }
        }

        // Check sample count
        if (a->mSampleCount != b->mSampleCount) {
            return false;
        }

        return true;
    }

    AttachmentState::AttachmentState(DeviceBase* device, const AttachmentStateBlueprint& blueprint)
        : AttachmentStateBlueprint(blueprint), RefCounted(), mDevice(device) {
    }

    AttachmentState::~AttachmentState() {
        mDevice->UncacheAttachmentState(this);
    }

    std::bitset<kMaxColorAttachments> AttachmentState::GetColorAttachmentsMask() const {
        return mColorAttachmentsSet;
    }

    dawn::TextureFormat AttachmentState::GetColorAttachmentFormat(uint32_t index) const {
        ASSERT(mColorAttachmentsSet[index]);
        return mColorFormats[index];
    }

    bool AttachmentState::HasDepthStencilAttachment() const {
        return mHasDepthStencilAttachment;
    }

    dawn::TextureFormat AttachmentState::GetDepthStencilFormat() const {
        ASSERT(mHasDepthStencilAttachment);
        return mDepthStencilFormat;
    }

    uint32_t AttachmentState::GetSampleCount() const {
        return mSampleCount;
    }

}  // namespace dawn_native
