// Copyright 2017 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.

#ifndef DAWNNATIVE_RENDERPIPELINE_H_
#define DAWNNATIVE_RENDERPIPELINE_H_

#include "common/TypedInteger.h"
#include "dawn_native/AttachmentState.h"
#include "dawn_native/IntegerTypes.h"
#include "dawn_native/Pipeline.h"

#include "dawn_native/dawn_platform.h"

#include <array>
#include <bitset>

namespace dawn_native {

    class DeviceBase;

    MaybeError ValidateRenderPipelineDescriptor(DeviceBase* device,
                                                const RenderPipelineDescriptor* descriptor);

    std::vector<StageAndDescriptor> GetStages(const RenderPipelineDescriptor* descriptor);

    size_t IndexFormatSize(wgpu::IndexFormat format);

    bool IsStripPrimitiveTopology(wgpu::PrimitiveTopology primitiveTopology);

    bool StencilTestEnabled(const DepthStencilState* mDepthStencil);

    struct VertexAttributeInfo {
        wgpu::VertexFormat format;
        uint64_t offset;
        VertexAttributeLocation shaderLocation;
        VertexBufferSlot vertexBufferSlot;
    };

    struct VertexBufferInfo {
        uint64_t arrayStride;
        wgpu::InputStepMode stepMode;
    };

    class RenderPipelineBase : public PipelineBase {
      public:
        RenderPipelineBase(DeviceBase* device, const RenderPipelineDescriptor* descriptor);
        ~RenderPipelineBase() override;

        static RenderPipelineBase* MakeError(DeviceBase* device);

        const ityp::bitset<VertexAttributeLocation, kMaxVertexAttributes>&
        GetAttributeLocationsUsed() const;
        const VertexAttributeInfo& GetAttribute(VertexAttributeLocation location) const;
        const ityp::bitset<VertexBufferSlot, kMaxVertexBuffers>& GetVertexBufferSlotsUsed() const;
        const VertexBufferInfo& GetVertexBuffer(VertexBufferSlot slot) const;
        uint32_t GetVertexBufferCount() const;

        const ColorTargetState* GetColorTargetState(ColorAttachmentIndex attachmentSlot) const;
        const DepthStencilState* GetDepthStencilState() const;
        wgpu::PrimitiveTopology GetPrimitiveTopology() const;
        wgpu::IndexFormat GetStripIndexFormat() const;
        wgpu::CullMode GetCullMode() const;
        wgpu::FrontFace GetFrontFace() const;
        bool IsDepthBiasEnabled() const;
        int32_t GetDepthBias() const;
        float GetDepthBiasSlopeScale() const;
        float GetDepthBiasClamp() const;
        bool ShouldClampDepth() const;

        ityp::bitset<ColorAttachmentIndex, kMaxColorAttachments> GetColorAttachmentsMask() const;
        bool HasDepthStencilAttachment() const;
        wgpu::TextureFormat GetColorAttachmentFormat(ColorAttachmentIndex attachment) const;
        wgpu::TextureFormat GetDepthStencilFormat() const;
        uint32_t GetSampleCount() const;
        uint32_t GetSampleMask() const;
        bool IsAlphaToCoverageEnabled() const;

        const AttachmentState* GetAttachmentState() const;

        // Functions necessary for the unordered_set<RenderPipelineBase*>-based cache.
        size_t ComputeContentHash() override;

        struct EqualityFunc {
            bool operator()(const RenderPipelineBase* a, const RenderPipelineBase* b) const;
        };

      private:
        RenderPipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag);

        // Vertex state
        uint32_t mVertexBufferCount;
        ityp::bitset<VertexAttributeLocation, kMaxVertexAttributes> mAttributeLocationsUsed;
        ityp::array<VertexAttributeLocation, VertexAttributeInfo, kMaxVertexAttributes>
            mAttributeInfos;
        ityp::bitset<VertexBufferSlot, kMaxVertexBuffers> mVertexBufferSlotsUsed;
        ityp::array<VertexBufferSlot, VertexBufferInfo, kMaxVertexBuffers> mVertexBufferInfos;

        // Attachments
        Ref<AttachmentState> mAttachmentState;
        ityp::array<ColorAttachmentIndex, ColorTargetState, kMaxColorAttachments> mTargets;
        ityp::array<ColorAttachmentIndex, BlendState, kMaxColorAttachments> mTargetBlend;

        // Other state
        PrimitiveState mPrimitive;
        DepthStencilState mDepthStencil;
        MultisampleState mMultisample;
        bool mClampDepth = false;
    };

}  // namespace dawn_native

#endif  // DAWNNATIVE_RENDERPIPELINE_H_
