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

#include "common/Commands.h"
#include "OpenGLBackend.h"
#include "PersistentPipelineStateGL.h"
#include "PipelineGL.h"
#include "PipelineLayoutGL.h"
#include "SamplerGL.h"
#include "TextureGL.h"

#include <cstring>

namespace backend {
namespace opengl {

    PersistentPipelineState persistentPipelineState;

    CommandBuffer::CommandBuffer(Device* device, CommandBufferBuilder* builder)
        : CommandBufferBase(builder), device(device), commands(builder->AcquireCommands()) {
    }

    CommandBuffer::~CommandBuffer() {
        FreeCommands(&commands);
    }

    static GLenum IndexFormatType(nxt::IndexFormat format) {
        switch (format) {
            case nxt::IndexFormat::Uint16:
                return GL_UNSIGNED_SHORT;
            case nxt::IndexFormat::Uint32:
                return GL_UNSIGNED_INT;
        }
    }

    static GLenum VertexFormatType(nxt::VertexFormat format) {
        switch (format) {
            case nxt::VertexFormat::FloatR32G32B32A32:
            case nxt::VertexFormat::FloatR32G32B32:
            case nxt::VertexFormat::FloatR32G32:
                return GL_FLOAT;
        }
    }

    void CommandBuffer::Execute() {
        Command type;
        Pipeline* lastPipeline = nullptr;
        uint32_t indexBufferOffset = 0;
        nxt::IndexFormat indexBufferFormat = nxt::IndexFormat::Uint16;

        while(commands.NextCommandId(&type)) {
            switch (type) {
                case Command::AdvanceSubpass:
                    {
                        // TODO(kainino@chromium.org): implement
                    }
                    break;

                case Command::BeginRenderPass:
                    {
                        // TODO(kainino@chromium.org): implement
                    }
                    break;

                case Command::CopyBufferToTexture:
                    {
                        CopyBufferToTextureCmd* copy = commands.NextCommand<CopyBufferToTextureCmd>();
                        Buffer* buffer = ToBackend(copy->buffer.Get());
                        Texture* texture = ToBackend(copy->texture.Get());
                        GLenum target = texture->GetGLTarget();
                        auto format = texture->GetGLFormat();

                        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer->GetHandle());
                        glActiveTexture(GL_TEXTURE0);
                        glBindTexture(target, texture->GetHandle());

                        glTexSubImage2D(target, copy->level, copy->x, copy->y, copy->width, copy->height,
                                        format.format, format.type,
                                        reinterpret_cast<void*>(static_cast<uintptr_t>(copy->bufferOffset)));
                        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
                    }
                    break;

                case Command::Dispatch:
                    {
                        DispatchCmd* dispatch = commands.NextCommand<DispatchCmd>();
                        glDispatchCompute(dispatch->x, dispatch->y, dispatch->z);
                        // TODO(cwallez@chromium.org): add barriers to the API
                        glMemoryBarrier(GL_ALL_BARRIER_BITS);
                    }
                    break;

                case Command::DrawArrays:
                    {
                        DrawArraysCmd* draw = commands.NextCommand<DrawArraysCmd>();
                        if (draw->firstInstance > 0) {
                            glDrawArraysInstancedBaseInstance(GL_TRIANGLES,
                                draw->firstVertex, draw->vertexCount, draw->instanceCount, draw->firstInstance);
                        } else {
                            // This branch is only needed on OpenGL < 4.2
                            glDrawArraysInstanced(GL_TRIANGLES,
                                draw->firstVertex, draw->vertexCount, draw->instanceCount);
                        }
                    }
                    break;

                case Command::DrawElements:
                    {
                        DrawElementsCmd* draw = commands.NextCommand<DrawElementsCmd>();
                        size_t formatSize = IndexFormatSize(indexBufferFormat);
                        GLenum formatType = IndexFormatType(indexBufferFormat);

                        if (draw->firstInstance > 0) {
                            glDrawElementsInstancedBaseInstance(GL_TRIANGLES,
                                draw->indexCount, formatType,
                                reinterpret_cast<void*>(draw->firstIndex * formatSize + indexBufferOffset),
                                draw->instanceCount, draw->firstInstance);
                        } else {
                            // This branch is only needed on OpenGL < 4.2
                            glDrawElementsInstanced(GL_TRIANGLES,
                                draw->indexCount, formatType,
                                reinterpret_cast<void*>(draw->firstIndex * formatSize + indexBufferOffset),
                                draw->instanceCount);
                        }
                    }
                    break;

                case Command::EndRenderPass:
                    {
                        // TODO(kainino@chromium.org): implement
                    }
                    break;

                case Command::SetPipeline:
                    {
                        SetPipelineCmd* cmd = commands.NextCommand<SetPipelineCmd>();
                        ToBackend(cmd->pipeline)->ApplyNow(persistentPipelineState);
                        lastPipeline = ToBackend(cmd->pipeline).Get();
                    }
                    break;

                case Command::SetPushConstants:
                    {
                        SetPushConstantsCmd* cmd = commands.NextCommand<SetPushConstantsCmd>();
                        uint32_t* valuesUInt = commands.NextData<uint32_t>(cmd->count);
                        int32_t* valuesInt = reinterpret_cast<int32_t*>(valuesUInt);
                        float* valuesFloat = reinterpret_cast<float*>(valuesUInt);

                        for (auto stage : IterateStages(cmd->stage)) {
                            const auto& pushConstants = lastPipeline->GetPushConstants(stage);
                            const auto& glPushConstants = lastPipeline->GetGLPushConstants(stage);
                            for (size_t i = 0; i < cmd->count; i++) {
                                GLint location = glPushConstants[cmd->offset + i];

                                switch (pushConstants.types[cmd->offset + i]) {
                                    case PushConstantType::Int:
                                        glUniform1i(location, valuesInt[i]);
                                        break;
                                    case PushConstantType::UInt:
                                        glUniform1ui(location, valuesUInt[i]);
                                        break;
                                    case PushConstantType::Float:
                                        glUniform1f(location, valuesFloat[i]);
                                        break;
                                }
                            }
                        }
                    }
                    break;

                case Command::SetStencilReference:
                    {
                        SetStencilReferenceCmd* cmd = commands.NextCommand<SetStencilReferenceCmd>();
                        DepthStencilState* depthStencilState = ToBackend(lastPipeline->GetDepthStencilState());
                        persistentPipelineState.UpdateStencilReference(cmd->reference);
                        persistentPipelineState.ApplyStencilNow();
                    }
                    break;

                case Command::SetBindGroup:
                    {
                        SetBindGroupCmd* cmd = commands.NextCommand<SetBindGroupCmd>();
                        size_t index = cmd->index;
                        BindGroup* group = ToBackend(cmd->group.Get());

                        const auto& indices = ToBackend(lastPipeline->GetLayout())->GetBindingIndexInfo()[index];
                        const auto& layout = group->GetLayout()->GetBindingInfo();

                        // TODO(cwallez@chromium.org): iterate over the layout bitmask instead
                        for (size_t binding = 0; binding < kMaxBindingsPerGroup; ++binding) {
                            if (!layout.mask[binding]) {
                                continue;
                            }

                            switch (layout.types[binding]) {
                                case nxt::BindingType::UniformBuffer:
                                    {
                                        BufferView* view = ToBackend(group->GetBindingAsBufferView(binding));
                                        GLuint buffer = ToBackend(view->GetBuffer())->GetHandle();
                                        GLuint index = indices[binding];

                                        glBindBufferRange(GL_UNIFORM_BUFFER, index, buffer, view->GetOffset(), view->GetSize());
                                    }
                                    break;

                                case nxt::BindingType::Sampler:
                                    {
                                        GLuint sampler = ToBackend(group->GetBindingAsSampler(binding))->GetHandle();
                                        GLuint index = indices[binding];

                                        for (auto unit : lastPipeline->GetTextureUnitsForSampler(index)) {
                                            glBindSampler(unit, sampler);
                                        }
                                    }
                                    break;

                                case nxt::BindingType::SampledTexture:
                                    {
                                        TextureView* view = ToBackend(group->GetBindingAsTextureView(binding));
                                        Texture* texture = ToBackend(view->GetTexture());
                                        GLuint handle = texture->GetHandle();
                                        GLenum target = texture->GetGLTarget();
                                        GLuint index = indices[binding];

                                        for (auto unit : lastPipeline->GetTextureUnitsForTexture(index)) {
                                            glActiveTexture(GL_TEXTURE0 + unit);
                                            glBindTexture(target, handle);
                                        }
                                    }
                                    break;

                                case nxt::BindingType::StorageBuffer:
                                    {
                                        BufferView* view = ToBackend(group->GetBindingAsBufferView(binding));
                                        GLuint buffer = ToBackend(view->GetBuffer())->GetHandle();
                                        GLuint index = indices[binding];

                                        glBindBufferRange(GL_SHADER_STORAGE_BUFFER, index, buffer, view->GetOffset(), view->GetSize());
                                    }
                                    break;
                            }
                        }
                    }
                    break;

                case Command::SetIndexBuffer:
                    {
                        SetIndexBufferCmd* cmd = commands.NextCommand<SetIndexBufferCmd>();

                        GLuint buffer = ToBackend(cmd->buffer.Get())->GetHandle();
                        indexBufferOffset = cmd->offset;
                        indexBufferFormat = cmd->format;
                        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
                    }
                    break;

                case Command::SetVertexBuffers:
                    {
                        SetVertexBuffersCmd* cmd = commands.NextCommand<SetVertexBuffersCmd>();
                        auto buffers = commands.NextData<Ref<BufferBase>>(cmd->count);
                        auto offsets = commands.NextData<uint32_t>(cmd->count);

                        auto inputState = lastPipeline->GetInputState();

                        auto& attributesSetMask = inputState->GetAttributesSetMask();
                        for (uint32_t location = 0; location < attributesSetMask.size(); ++location) {
                            if (!attributesSetMask[location]) {
                                // This slot is not used in the input state
                                continue;
                            }
                            auto attribute = inputState->GetAttribute(location);
                            auto slot = attribute.bindingSlot;
                            ASSERT(slot < kMaxVertexInputs);
                            if (slot < cmd->startSlot || slot >= cmd->startSlot + cmd->count) {
                                // This slot is not affected by this call
                                continue;
                            }
                            size_t bufferIndex = slot - cmd->startSlot;
                            GLuint buffer = ToBackend(buffers[bufferIndex])->GetHandle();
                            uint32_t bufferOffset = offsets[bufferIndex];

                            auto input = inputState->GetInput(slot);

                            auto components = VertexFormatNumComponents(attribute.format);
                            auto formatType = VertexFormatType(attribute.format);

                            glBindBuffer(GL_ARRAY_BUFFER, buffer);
                            glVertexAttribPointer(
                                    location, components, formatType, GL_FALSE,
                                    input.stride,
                                    reinterpret_cast<void*>(static_cast<intptr_t>(bufferOffset + attribute.offset)));
                        }
                    }
                    break;

                case Command::TransitionBufferUsage:
                    {
                        TransitionBufferUsageCmd* cmd = commands.NextCommand<TransitionBufferUsageCmd>();

                        cmd->buffer->TransitionUsageImpl(cmd->usage);
                    }
                    break;

                case Command::TransitionTextureUsage:
                    {
                        TransitionTextureUsageCmd* cmd = commands.NextCommand<TransitionTextureUsageCmd>();

                        cmd->texture->TransitionUsageImpl(cmd->usage);
                    }
                    break;
            }
        }

        // HACK: cleanup a tiny bit of state to make this work with
        // virtualized contexts enabled in Chromium
        glBindSampler(0, 0);
    }

}
}
