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

// Indexffer9.cpp: Defines the D3D9 IndexBuffer implementation.

#include "libANGLE/renderer/d3d/d3d9/IndexBuffer9.h"

#include "libANGLE/Context.h"
#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"

namespace rx
{

IndexBuffer9::IndexBuffer9(Renderer9 *const renderer) : mRenderer(renderer)
{
    mIndexBuffer = nullptr;
    mBufferSize  = 0;
    mIndexType   = gl::DrawElementsType::InvalidEnum;
    mDynamic     = false;
}

IndexBuffer9::~IndexBuffer9()
{
    SafeRelease(mIndexBuffer);
}

angle::Result IndexBuffer9::initialize(const gl::Context *context,
                                       unsigned int bufferSize,
                                       gl::DrawElementsType indexType,
                                       bool dynamic)
{
    SafeRelease(mIndexBuffer);

    updateSerial();

    if (bufferSize > 0)
    {
        D3DFORMAT format = D3DFMT_UNKNOWN;
        if (indexType == gl::DrawElementsType::UnsignedShort ||
            indexType == gl::DrawElementsType::UnsignedByte)
        {
            format = D3DFMT_INDEX16;
        }
        else if (indexType == gl::DrawElementsType::UnsignedInt)
        {
            ASSERT(mRenderer->getNativeExtensions().elementIndexUint);
            format = D3DFMT_INDEX32;
        }
        else
            UNREACHABLE();

        DWORD usageFlags = D3DUSAGE_WRITEONLY;
        if (dynamic)
        {
            usageFlags |= D3DUSAGE_DYNAMIC;
        }

        HRESULT result =
            mRenderer->createIndexBuffer(bufferSize, usageFlags, format, &mIndexBuffer);
        ANGLE_TRY_HR(GetImplAs<Context9>(context), result,
                     "Failed to allocate internal index buffer");
    }

    mBufferSize = bufferSize;
    mIndexType  = indexType;
    mDynamic    = dynamic;

    return angle::Result::Continue;
}

angle::Result IndexBuffer9::mapBuffer(const gl::Context *context,
                                      unsigned int offset,
                                      unsigned int size,
                                      void **outMappedMemory)
{
    ASSERT(mIndexBuffer);

    DWORD lockFlags = mDynamic ? D3DLOCK_NOOVERWRITE : 0;

    void *mapPtr   = nullptr;
    HRESULT result = mIndexBuffer->Lock(offset, size, &mapPtr, lockFlags);
    ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to lock internal index buffer");

    *outMappedMemory = mapPtr;
    return angle::Result::Continue;
}

angle::Result IndexBuffer9::unmapBuffer(const gl::Context *context)
{
    ASSERT(mIndexBuffer);
    HRESULT result = mIndexBuffer->Unlock();
    ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to unlock internal index buffer");

    return angle::Result::Continue;
}

gl::DrawElementsType IndexBuffer9::getIndexType() const
{
    return mIndexType;
}

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

angle::Result IndexBuffer9::setSize(const gl::Context *context,
                                    unsigned int bufferSize,
                                    gl::DrawElementsType indexType)
{
    if (bufferSize > mBufferSize || indexType != mIndexType)
    {
        return initialize(context, bufferSize, indexType, mDynamic);
    }

    return angle::Result::Continue;
}

angle::Result IndexBuffer9::discard(const gl::Context *context)
{
    ASSERT(mIndexBuffer);

    void *dummy;
    HRESULT result;

    Context9 *context9 = GetImplAs<Context9>(context);

    result = mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
    ANGLE_TRY_HR(context9, result, "Failed to lock internal index buffer");

    result = mIndexBuffer->Unlock();
    ANGLE_TRY_HR(context9, result, "Failed to unlock internal index buffer");

    return angle::Result::Continue;
}

D3DFORMAT IndexBuffer9::getIndexFormat() const
{
    switch (mIndexType)
    {
        case gl::DrawElementsType::UnsignedByte:
            return D3DFMT_INDEX16;
        case gl::DrawElementsType::UnsignedShort:
            return D3DFMT_INDEX16;
        case gl::DrawElementsType::UnsignedInt:
            return D3DFMT_INDEX32;
        default:
            UNREACHABLE();
            return D3DFMT_UNKNOWN;
    }
}

IDirect3DIndexBuffer9 *IndexBuffer9::getBuffer() const
{
    return mIndexBuffer;
}

}  // namespace rx
