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

#include "dawn_native/opengl/RenderPipelineGL.h"

#include "dawn_native/opengl/DeviceGL.h"
#include "dawn_native/opengl/Forward.h"
#include "dawn_native/opengl/PersistentPipelineStateGL.h"
#include "dawn_native/opengl/UtilsGL.h"

namespace dawn_native { namespace opengl {

    namespace {

        GLenum GLPrimitiveTopology(wgpu::PrimitiveTopology primitiveTopology) {
            switch (primitiveTopology) {
                case wgpu::PrimitiveTopology::PointList:
                    return GL_POINTS;
                case wgpu::PrimitiveTopology::LineList:
                    return GL_LINES;
                case wgpu::PrimitiveTopology::LineStrip:
                    return GL_LINE_STRIP;
                case wgpu::PrimitiveTopology::TriangleList:
                    return GL_TRIANGLES;
                case wgpu::PrimitiveTopology::TriangleStrip:
                    return GL_TRIANGLE_STRIP;
            }
            UNREACHABLE();
        }

        void ApplyFrontFaceAndCulling(const OpenGLFunctions& gl,
                                      wgpu::FrontFace face,
                                      wgpu::CullMode mode) {
            // Note that we invert winding direction in OpenGL. Because Y axis is up in OpenGL,
            // which is different from WebGPU and other backends (Y axis is down).
            GLenum direction = (face == wgpu::FrontFace::CCW) ? GL_CW : GL_CCW;
            gl.FrontFace(direction);

            if (mode == wgpu::CullMode::None) {
                gl.Disable(GL_CULL_FACE);
            } else {
                gl.Enable(GL_CULL_FACE);

                GLenum cullMode = (mode == wgpu::CullMode::Front) ? GL_FRONT : GL_BACK;
                gl.CullFace(cullMode);
            }
        }

        GLenum GLBlendFactor(wgpu::BlendFactor factor, bool alpha) {
            switch (factor) {
                case wgpu::BlendFactor::Zero:
                    return GL_ZERO;
                case wgpu::BlendFactor::One:
                    return GL_ONE;
                case wgpu::BlendFactor::Src:
                    return GL_SRC_COLOR;
                case wgpu::BlendFactor::OneMinusSrc:
                    return GL_ONE_MINUS_SRC_COLOR;
                case wgpu::BlendFactor::SrcAlpha:
                    return GL_SRC_ALPHA;
                case wgpu::BlendFactor::OneMinusSrcAlpha:
                    return GL_ONE_MINUS_SRC_ALPHA;
                case wgpu::BlendFactor::Dst:
                    return GL_DST_COLOR;
                case wgpu::BlendFactor::OneMinusDst:
                    return GL_ONE_MINUS_DST_COLOR;
                case wgpu::BlendFactor::DstAlpha:
                    return GL_DST_ALPHA;
                case wgpu::BlendFactor::OneMinusDstAlpha:
                    return GL_ONE_MINUS_DST_ALPHA;
                case wgpu::BlendFactor::SrcAlphaSaturated:
                    return GL_SRC_ALPHA_SATURATE;
                case wgpu::BlendFactor::Constant:
                    return alpha ? GL_CONSTANT_ALPHA : GL_CONSTANT_COLOR;
                case wgpu::BlendFactor::OneMinusConstant:
                    return alpha ? GL_ONE_MINUS_CONSTANT_ALPHA : GL_ONE_MINUS_CONSTANT_COLOR;
            }
            UNREACHABLE();
        }

        GLenum GLBlendMode(wgpu::BlendOperation operation) {
            switch (operation) {
                case wgpu::BlendOperation::Add:
                    return GL_FUNC_ADD;
                case wgpu::BlendOperation::Subtract:
                    return GL_FUNC_SUBTRACT;
                case wgpu::BlendOperation::ReverseSubtract:
                    return GL_FUNC_REVERSE_SUBTRACT;
                case wgpu::BlendOperation::Min:
                    return GL_MIN;
                case wgpu::BlendOperation::Max:
                    return GL_MAX;
            }
            UNREACHABLE();
        }

        void ApplyColorState(const OpenGLFunctions& gl,
                             ColorAttachmentIndex attachment,
                             const ColorTargetState* state) {
            GLuint colorBuffer = static_cast<GLuint>(static_cast<uint8_t>(attachment));
            if (state->blend != nullptr) {
                gl.Enablei(GL_BLEND, colorBuffer);
                gl.BlendEquationSeparatei(colorBuffer, GLBlendMode(state->blend->color.operation),
                                          GLBlendMode(state->blend->alpha.operation));
                gl.BlendFuncSeparatei(colorBuffer,
                                      GLBlendFactor(state->blend->color.srcFactor, false),
                                      GLBlendFactor(state->blend->color.dstFactor, false),
                                      GLBlendFactor(state->blend->alpha.srcFactor, true),
                                      GLBlendFactor(state->blend->alpha.dstFactor, true));
            } else {
                gl.Disablei(GL_BLEND, colorBuffer);
            }
            gl.ColorMaski(colorBuffer, state->writeMask & wgpu::ColorWriteMask::Red,
                          state->writeMask & wgpu::ColorWriteMask::Green,
                          state->writeMask & wgpu::ColorWriteMask::Blue,
                          state->writeMask & wgpu::ColorWriteMask::Alpha);
        }

        void ApplyColorState(const OpenGLFunctions& gl, const ColorTargetState* state) {
            if (state->blend != nullptr) {
                gl.Enable(GL_BLEND);
                gl.BlendEquationSeparate(GLBlendMode(state->blend->color.operation),
                                         GLBlendMode(state->blend->alpha.operation));
                gl.BlendFuncSeparate(GLBlendFactor(state->blend->color.srcFactor, false),
                                     GLBlendFactor(state->blend->color.dstFactor, false),
                                     GLBlendFactor(state->blend->alpha.srcFactor, true),
                                     GLBlendFactor(state->blend->alpha.dstFactor, true));
            } else {
                gl.Disable(GL_BLEND);
            }
            gl.ColorMask(state->writeMask & wgpu::ColorWriteMask::Red,
                         state->writeMask & wgpu::ColorWriteMask::Green,
                         state->writeMask & wgpu::ColorWriteMask::Blue,
                         state->writeMask & wgpu::ColorWriteMask::Alpha);
        }

        bool Equal(const BlendComponent& lhs, const BlendComponent& rhs) {
            return lhs.operation == rhs.operation && lhs.srcFactor == rhs.srcFactor &&
                   lhs.dstFactor == rhs.dstFactor;
        }

        GLuint OpenGLStencilOperation(wgpu::StencilOperation stencilOperation) {
            switch (stencilOperation) {
                case wgpu::StencilOperation::Keep:
                    return GL_KEEP;
                case wgpu::StencilOperation::Zero:
                    return GL_ZERO;
                case wgpu::StencilOperation::Replace:
                    return GL_REPLACE;
                case wgpu::StencilOperation::Invert:
                    return GL_INVERT;
                case wgpu::StencilOperation::IncrementClamp:
                    return GL_INCR;
                case wgpu::StencilOperation::DecrementClamp:
                    return GL_DECR;
                case wgpu::StencilOperation::IncrementWrap:
                    return GL_INCR_WRAP;
                case wgpu::StencilOperation::DecrementWrap:
                    return GL_DECR_WRAP;
            }
            UNREACHABLE();
        }

        void ApplyDepthStencilState(const OpenGLFunctions& gl,
                                    const DepthStencilState* descriptor,
                                    PersistentPipelineState* persistentPipelineState) {
            // Depth writes only occur if depth is enabled
            if (descriptor->depthCompare == wgpu::CompareFunction::Always &&
                !descriptor->depthWriteEnabled) {
                gl.Disable(GL_DEPTH_TEST);
            } else {
                gl.Enable(GL_DEPTH_TEST);
            }

            if (descriptor->depthWriteEnabled) {
                gl.DepthMask(GL_TRUE);
            } else {
                gl.DepthMask(GL_FALSE);
            }

            gl.DepthFunc(ToOpenGLCompareFunction(descriptor->depthCompare));

            if (StencilTestEnabled(descriptor)) {
                gl.Enable(GL_STENCIL_TEST);
            } else {
                gl.Disable(GL_STENCIL_TEST);
            }

            GLenum backCompareFunction = ToOpenGLCompareFunction(descriptor->stencilBack.compare);
            GLenum frontCompareFunction = ToOpenGLCompareFunction(descriptor->stencilFront.compare);
            persistentPipelineState->SetStencilFuncsAndMask(
                gl, backCompareFunction, frontCompareFunction, descriptor->stencilReadMask);

            gl.StencilOpSeparate(GL_BACK, OpenGLStencilOperation(descriptor->stencilBack.failOp),
                                 OpenGLStencilOperation(descriptor->stencilBack.depthFailOp),
                                 OpenGLStencilOperation(descriptor->stencilBack.passOp));
            gl.StencilOpSeparate(GL_FRONT, OpenGLStencilOperation(descriptor->stencilFront.failOp),
                                 OpenGLStencilOperation(descriptor->stencilFront.depthFailOp),
                                 OpenGLStencilOperation(descriptor->stencilFront.passOp));

            gl.StencilMask(descriptor->stencilWriteMask);
        }

    }  // anonymous namespace

    // static
    Ref<RenderPipeline> RenderPipeline::CreateUninitialized(
        Device* device,
        const RenderPipelineDescriptor* descriptor) {
        return AcquireRef(new RenderPipeline(device, descriptor));
    }

    RenderPipeline::RenderPipeline(Device* device, const RenderPipelineDescriptor* descriptor)
        : RenderPipelineBase(device, descriptor),
          mVertexArrayObject(0),
          mGlPrimitiveTopology(GLPrimitiveTopology(GetPrimitiveTopology())) {
    }

    MaybeError RenderPipeline::Initialize() {
        DAWN_TRY(
            InitializeBase(ToBackend(GetDevice())->gl, ToBackend(GetLayout()), GetAllStages()));
        CreateVAOForVertexState();
        return {};
    }

    RenderPipeline::~RenderPipeline() = default;

    void RenderPipeline::DestroyImpl() {
        RenderPipelineBase::DestroyImpl();
        const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
        gl.DeleteVertexArrays(1, &mVertexArrayObject);
        gl.BindVertexArray(0);
        DeleteProgram(gl);
    }

    GLenum RenderPipeline::GetGLPrimitiveTopology() const {
        return mGlPrimitiveTopology;
    }

    ityp::bitset<VertexAttributeLocation, kMaxVertexAttributes>
    RenderPipeline::GetAttributesUsingVertexBuffer(VertexBufferSlot slot) const {
        ASSERT(!IsError());
        return mAttributesUsingVertexBuffer[slot];
    }

    void RenderPipeline::CreateVAOForVertexState() {
        const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;

        gl.GenVertexArrays(1, &mVertexArrayObject);
        gl.BindVertexArray(mVertexArrayObject);

        for (VertexAttributeLocation location : IterateBitSet(GetAttributeLocationsUsed())) {
            const auto& attribute = GetAttribute(location);
            GLuint glAttrib = static_cast<GLuint>(static_cast<uint8_t>(location));
            gl.EnableVertexAttribArray(glAttrib);

            mAttributesUsingVertexBuffer[attribute.vertexBufferSlot][location] = true;
            const VertexBufferInfo& vertexBuffer = GetVertexBuffer(attribute.vertexBufferSlot);

            if (vertexBuffer.arrayStride == 0) {
                // Emulate a stride of zero (constant vertex attribute) by
                // setting the attribute instance divisor to a huge number.
                gl.VertexAttribDivisor(glAttrib, 0xffffffff);
            } else {
                switch (vertexBuffer.stepMode) {
                    case wgpu::VertexStepMode::Vertex:
                        break;
                    case wgpu::VertexStepMode::Instance:
                        gl.VertexAttribDivisor(glAttrib, 1);
                        break;
                }
            }
        }
    }

    void RenderPipeline::ApplyNow(PersistentPipelineState& persistentPipelineState) {
        const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
        PipelineGL::ApplyNow(gl);

        ASSERT(mVertexArrayObject);
        gl.BindVertexArray(mVertexArrayObject);

        ApplyFrontFaceAndCulling(gl, GetFrontFace(), GetCullMode());

        ApplyDepthStencilState(gl, GetDepthStencilState(), &persistentPipelineState);

        gl.SampleMaski(0, GetSampleMask());
        if (IsAlphaToCoverageEnabled()) {
            gl.Enable(GL_SAMPLE_ALPHA_TO_COVERAGE);
        } else {
            gl.Disable(GL_SAMPLE_ALPHA_TO_COVERAGE);
        }

        if (IsDepthBiasEnabled()) {
            gl.Enable(GL_POLYGON_OFFSET_FILL);
            float depthBias = GetDepthBias();
            float slopeScale = GetDepthBiasSlopeScale();
            if (gl.PolygonOffsetClamp != nullptr) {
                gl.PolygonOffsetClamp(slopeScale, depthBias, GetDepthBiasClamp());
            } else {
                gl.PolygonOffset(slopeScale, depthBias);
            }
        } else {
            gl.Disable(GL_POLYGON_OFFSET_FILL);
        }

        if (!GetDevice()->IsToggleEnabled(Toggle::DisableIndexedDrawBuffers)) {
            for (ColorAttachmentIndex attachmentSlot : IterateBitSet(GetColorAttachmentsMask())) {
                ApplyColorState(gl, attachmentSlot, GetColorTargetState(attachmentSlot));
            }
        } else {
            const ColorTargetState* prevDescriptor = nullptr;
            for (ColorAttachmentIndex attachmentSlot : IterateBitSet(GetColorAttachmentsMask())) {
                const ColorTargetState* descriptor = GetColorTargetState(attachmentSlot);
                if (!prevDescriptor) {
                    ApplyColorState(gl, descriptor);
                    prevDescriptor = descriptor;
                } else if ((descriptor->blend == nullptr) != (prevDescriptor->blend == nullptr)) {
                    // TODO(crbug.com/dawn/582): GLES < 3.2 does not support different blend states
                    // per color target. Add validation to prevent this as it is not.
                    ASSERT(false);
                } else if (descriptor->blend != nullptr) {
                    if (!Equal(descriptor->blend->alpha, prevDescriptor->blend->alpha) ||
                        !Equal(descriptor->blend->color, prevDescriptor->blend->color) ||
                        descriptor->writeMask != prevDescriptor->writeMask) {
                        // TODO(crbug.com/dawn/582)
                        ASSERT(false);
                    }
                }
            }
        }
    }

}}  // namespace dawn_native::opengl
