//
// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

// VertexBuffer11.cpp: Defines the D3D11 VertexBuffer implementation.

#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"

#include "libANGLE/Buffer.h"
#include "libANGLE/VertexAttribute.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"

namespace rx
{

VertexBuffer11::VertexBuffer11(Renderer11 *const renderer) : mRenderer(renderer)
{
    mBuffer             = nullptr;
    mBufferSize         = 0;
    mDynamicUsage       = false;
    mMappedResourceData = nullptr;
}

VertexBuffer11::~VertexBuffer11()
{
    ASSERT(mMappedResourceData == nullptr);
    SafeRelease(mBuffer);
}

gl::Error VertexBuffer11::initialize(unsigned int size, bool dynamicUsage)
{
    SafeRelease(mBuffer);

    updateSerial();

    if (size > 0)
    {
        ID3D11Device *dxDevice = mRenderer->getDevice();

        D3D11_BUFFER_DESC bufferDesc;
        bufferDesc.ByteWidth           = size;
        bufferDesc.Usage               = D3D11_USAGE_DYNAMIC;
        bufferDesc.BindFlags           = D3D11_BIND_VERTEX_BUFFER;
        bufferDesc.CPUAccessFlags      = D3D11_CPU_ACCESS_WRITE;
        bufferDesc.MiscFlags           = 0;
        bufferDesc.StructureByteStride = 0;

        HRESULT result = dxDevice->CreateBuffer(&bufferDesc, nullptr, &mBuffer);
        if (FAILED(result))
        {
            return gl::Error(GL_OUT_OF_MEMORY,
                             "Failed to allocate internal vertex buffer of size, %lu.", size);
        }

        if (dynamicUsage)
        {
            d3d11::SetDebugName(mBuffer, "VertexBuffer11 (dynamic)");
        }
        else
        {
            d3d11::SetDebugName(mBuffer, "VertexBuffer11 (static)");
        }
    }

    mBufferSize   = size;
    mDynamicUsage = dynamicUsage;

    return gl::NoError();
}

gl::Error VertexBuffer11::mapResource()
{
    if (mMappedResourceData == nullptr)
    {
        ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();

        D3D11_MAPPED_SUBRESOURCE mappedResource;

        HRESULT result =
            dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
        if (FAILED(result))
        {
            return gl::Error(GL_OUT_OF_MEMORY,
                             "Failed to map internal vertex buffer, HRESULT: 0x%08x.", result);
        }

        mMappedResourceData = reinterpret_cast<uint8_t *>(mappedResource.pData);
    }

    return gl::NoError();
}

void VertexBuffer11::hintUnmapResource()
{
    if (mMappedResourceData != nullptr)
    {
        ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
        dxContext->Unmap(mBuffer, 0);

        mMappedResourceData = nullptr;
    }
}

gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib,
                                                const gl::VertexBinding &binding,
                                                GLenum currentValueType,
                                                GLint start,
                                                GLsizei count,
                                                GLsizei instances,
                                                unsigned int offset,
                                                const uint8_t *sourceData)
{
    if (!mBuffer)
    {
        return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
    }

    int inputStride = static_cast<int>(ComputeVertexAttributeStride(attrib, binding));

    // This will map the resource if it isn't already mapped.
    ANGLE_TRY(mapResource());

    uint8_t *output = mMappedResourceData + offset;

    const uint8_t *input = sourceData;

    if (instances == 0 || binding.divisor == 0)
    {
        input += inputStride * start;
    }

    gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, currentValueType);
    const D3D_FEATURE_LEVEL featureLevel  = mRenderer->getRenderer11DeviceCaps().featureLevel;
    const d3d11::VertexFormat &vertexFormatInfo =
        d3d11::GetVertexFormatInfo(vertexFormatType, featureLevel);
    ASSERT(vertexFormatInfo.copyFunction != nullptr);
    vertexFormatInfo.copyFunction(input, inputStride, count, output);

    return gl::NoError();
}

unsigned int VertexBuffer11::getBufferSize() const
{
    return mBufferSize;
}

gl::Error VertexBuffer11::setBufferSize(unsigned int size)
{
    if (size > mBufferSize)
    {
        return initialize(size, mDynamicUsage);
    }
    else
    {
        return gl::NoError();
    }
}

gl::Error VertexBuffer11::discard()
{
    if (!mBuffer)
    {
        return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
    }

    ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();

    D3D11_MAPPED_SUBRESOURCE mappedResource;
    HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
    if (FAILED(result))
    {
        return gl::Error(GL_OUT_OF_MEMORY,
                         "Failed to map internal buffer for discarding, HRESULT: 0x%08x", result);
    }

    dxContext->Unmap(mBuffer, 0);

    return gl::NoError();
}

ID3D11Buffer *VertexBuffer11::getBuffer() const
{
    return mBuffer;
}

}  // namespace rx
