// 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 "dawn_native/AttachmentState.h"
#include "dawn_native/Pipeline.h"

#include "dawn_native/dawn_platform.h"

#include <array>
#include <bitset>

namespace dawn_native {

    struct BeginRenderPassCmd;

    class DeviceBase;

    MaybeError ValidateRenderPipelineDescriptor(const DeviceBase* device,
                                                const RenderPipelineDescriptor* descriptor);
    size_t IndexFormatSize(dawn::IndexFormat format);
    uint32_t VertexFormatNumComponents(dawn::VertexFormat format);
    size_t VertexFormatComponentSize(dawn::VertexFormat format);
    size_t VertexFormatSize(dawn::VertexFormat format);

    bool StencilTestEnabled(const DepthStencilStateDescriptor* mDepthStencilState);
    bool BlendEnabled(const ColorStateDescriptor* mColorState);

    struct VertexAttributeInfo {
        uint32_t shaderLocation;
        uint32_t inputSlot;
        uint64_t offset;
        dawn::VertexFormat format;
    };

    struct VertexBufferInfo {
        uint64_t stride;
        dawn::InputStepMode stepMode;
    };

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

        static RenderPipelineBase* MakeError(DeviceBase* device);

        const VertexInputDescriptor* GetVertexInputDescriptor() const;
        const std::bitset<kMaxVertexAttributes>& GetAttributesSetMask() const;
        const VertexAttributeInfo& GetAttribute(uint32_t location) const;
        const std::bitset<kMaxVertexBuffers>& GetInputsSetMask() const;
        const VertexBufferInfo& GetInput(uint32_t slot) const;

        const ColorStateDescriptor* GetColorStateDescriptor(uint32_t attachmentSlot) const;
        const DepthStencilStateDescriptor* GetDepthStencilStateDescriptor() const;
        dawn::PrimitiveTopology GetPrimitiveTopology() const;
        dawn::CullMode GetCullMode() const;
        dawn::FrontFace GetFrontFace() const;

        std::bitset<kMaxColorAttachments> GetColorAttachmentsMask() const;
        bool HasDepthStencilAttachment() const;
        dawn::TextureFormat GetColorAttachmentFormat(uint32_t attachment) const;
        dawn::TextureFormat GetDepthStencilFormat() const;
        uint32_t GetSampleCount() const;

        const AttachmentState* GetAttachmentState() const;

        std::bitset<kMaxVertexAttributes> GetAttributesUsingInput(uint32_t slot) const;
        std::array<std::bitset<kMaxVertexAttributes>, kMaxVertexBuffers> attributesUsingInput;

        // Functors necessary for the unordered_set<RenderPipelineBase*>-based cache.
        struct HashFunc {
            size_t operator()(const RenderPipelineBase* pipeline) const;
        };
        struct EqualityFunc {
            bool operator()(const RenderPipelineBase* a, const RenderPipelineBase* b) const;
        };

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

        // Vertex input
        VertexInputDescriptor mVertexInput;
        std::bitset<kMaxVertexAttributes> mAttributesSetMask;
        std::array<VertexAttributeInfo, kMaxVertexAttributes> mAttributeInfos;
        std::bitset<kMaxVertexBuffers> mInputsSetMask;
        std::array<VertexBufferInfo, kMaxVertexBuffers> mInputInfos;

        // Attachments
        Ref<AttachmentState> mAttachmentState;
        DepthStencilStateDescriptor mDepthStencilState;
        std::array<ColorStateDescriptor, kMaxColorAttachments> mColorStates;

        // Other state
        dawn::PrimitiveTopology mPrimitiveTopology;
        RasterizationStateDescriptor mRasterizationState;
        uint32_t mSampleMask;
        bool mAlphaToCoverageEnabled;

        // Stage information
        // TODO(cwallez@chromium.org): Store a crypto hash of the modules instead.
        Ref<ShaderModuleBase> mVertexModule;
        std::string mVertexEntryPoint;
        Ref<ShaderModuleBase> mFragmentModule;
        std::string mFragmentEntryPoint;

        bool mIsBlueprint = false;
    };

}  // namespace dawn_native

#endif  // DAWNNATIVE_RENDERPIPELINE_H_
