//
// Copyright (c) 2002-2010 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.
//

// geometry/IndexDataManager.cpp: Defines the IndexDataManager, a class that
// runs the Buffer translation process for index buffers.

#include "libGLESv2/geometry/IndexDataManager.h"

#include "common/debug.h"

#include "libGLESv2/Buffer.h"
#include "libGLESv2/mathutil.h"
#include "libGLESv2/main.h"

namespace
{
    enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) };
}

namespace gl
{

IndexDataManager::IndexDataManager(Context *context, IDirect3DDevice9 *device) : mDevice(device)
{
    mStreamingBufferShort = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX16);

    if (context->supports32bitIndices())
    {
        mStreamingBufferInt = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX32);
    }
    else
    {
        mStreamingBufferInt = NULL;
    }
}

IndexDataManager::~IndexDataManager()
{
    delete mStreamingBufferShort;
    delete mStreamingBufferInt;
}

void convertIndices(GLenum type, const void *input, GLsizei count, void *output)
{
    if (type == GL_UNSIGNED_BYTE)
    {
        const GLubyte *in = static_cast<const GLubyte*>(input);
        GLushort *out = static_cast<GLushort*>(output);

        for (GLsizei i = 0; i < count; i++)
        {
            out[i] = in[i];
        }
    }
    else if (type == GL_UNSIGNED_INT)
    {
        memcpy(output, input, count * sizeof(GLuint));
    }
    else if (type == GL_UNSIGNED_SHORT)
    {
        memcpy(output, input, count * sizeof(GLushort));
    }
    else UNREACHABLE();
}

template <class IndexType>
void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)
{
    *minIndex = indices[0];
    *maxIndex = indices[0];

    for (GLsizei i = 0; i < count; i++)
    {
        if (*minIndex > indices[i]) *minIndex = indices[i];
        if (*maxIndex < indices[i]) *maxIndex = indices[i];
    }
}

void computeRange(GLenum type, const void *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)
{
    if (type == GL_UNSIGNED_BYTE)
    {
        computeRange(static_cast<const GLubyte*>(indices), count, minIndex, maxIndex);
    }
    else if (type == GL_UNSIGNED_INT)
    {
        computeRange(static_cast<const GLuint*>(indices), count, minIndex, maxIndex);
    }
    else if (type == GL_UNSIGNED_SHORT)
    {
        computeRange(static_cast<const GLushort*>(indices), count, minIndex, maxIndex);
    }
    else UNREACHABLE();
}

GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, Buffer *buffer, const void *indices, TranslatedIndexData *translated)
{
    D3DFORMAT format = (type == GL_UNSIGNED_INT) ? D3DFMT_INDEX32 : D3DFMT_INDEX16;
    intptr_t offset = reinterpret_cast<intptr_t>(indices);
    bool alignedOffset = false;

    if (buffer != NULL)
    {
        switch (type)
        {
          case GL_UNSIGNED_BYTE:  alignedOffset = (offset % sizeof(GLubyte) == 0);  break;
          case GL_UNSIGNED_SHORT: alignedOffset = (offset % sizeof(GLushort) == 0); break;
          case GL_UNSIGNED_INT:   alignedOffset = (offset % sizeof(GLuint) == 0);   break;
          default: UNREACHABLE(); alignedOffset = false;
        }

        if (typeSize(type) * count + offset > static_cast<std::size_t>(buffer->size()))
        {
            return GL_INVALID_OPERATION;
        }

        indices = static_cast<const GLubyte*>(buffer->data()) + offset;
    }

    StreamingIndexBuffer *streamingBuffer = (type == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort;

    StaticIndexBuffer *staticBuffer = buffer ? buffer->getIndexBuffer() : NULL;
    IndexBuffer *indexBuffer = streamingBuffer;
    UINT streamOffset = 0;

    if (staticBuffer && staticBuffer->lookupType(type) && alignedOffset)
    {
        indexBuffer = staticBuffer;
        streamOffset = staticBuffer->lookupRange(offset, count, &translated->minIndex, &translated->maxIndex);

        if (streamOffset == -1)
        {
            streamOffset = (offset / typeSize(type)) * indexSize(format);
            computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
            staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset);
        }
    }
    else
    {
        int convertCount = count;

        if (staticBuffer)
        {
            if (staticBuffer->size() == 0 && alignedOffset)
            {
                indexBuffer = staticBuffer;
                convertCount = buffer->size() / typeSize(type);
            }
            else
            {
                buffer->invalidateStaticData();
                staticBuffer = NULL;
            }
        }

        void *output = NULL;
        
        if (indexBuffer)
        {
            indexBuffer->reserveSpace(convertCount * indexSize(format), type);
            output = indexBuffer->map(indexSize(format) * convertCount, &streamOffset);
        }
        
        if (output == NULL)
        {
            ERR("Failed to map index buffer.");
            return GL_OUT_OF_MEMORY;
        }

        convertIndices(type, staticBuffer ? buffer->data() : indices, convertCount, output);
        indexBuffer->unmap();

        computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);

        if (staticBuffer)
        {
            streamOffset = (offset / typeSize(type)) * indexSize(format);
            staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset);
        }
    }

    translated->indexBuffer = indexBuffer->getBuffer();
    translated->startIndex = streamOffset / indexSize(format);

    return GL_NO_ERROR;
}

std::size_t IndexDataManager::indexSize(D3DFORMAT format) const
{
    return (format == D3DFMT_INDEX32) ? sizeof(unsigned int) : sizeof(unsigned short);
}

std::size_t IndexDataManager::typeSize(GLenum type) const
{
    switch (type)
    {
      case GL_UNSIGNED_INT:   return sizeof(GLuint);
      case GL_UNSIGNED_SHORT: return sizeof(GLushort);
      case GL_UNSIGNED_BYTE:  return sizeof(GLubyte);
      default: UNREACHABLE(); return sizeof(GLushort);
    }
}

IndexBuffer::IndexBuffer(IDirect3DDevice9 *device, UINT size, D3DFORMAT format) : mDevice(device), mBufferSize(size), mIndexBuffer(NULL)
{
    if (size > 0)
    {
        D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY);
        HRESULT result = device->CreateIndexBuffer(size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, format, pool, &mIndexBuffer, NULL);

        if (FAILED(result))
        {
            ERR("Out of memory allocating an index buffer of size %lu.", size);
        }
    }
}

IndexBuffer::~IndexBuffer()
{
    if (mIndexBuffer)
    {
        mIndexBuffer->Release();
    }
}

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

void IndexBuffer::unmap()
{
    if (mIndexBuffer)
    {
        mIndexBuffer->Unlock();
    }
}

StreamingIndexBuffer::StreamingIndexBuffer(IDirect3DDevice9 *device, UINT initialSize, D3DFORMAT format) : IndexBuffer(device, initialSize, format)
{
    mWritePosition = 0;
}

StreamingIndexBuffer::~StreamingIndexBuffer()
{
}

void *StreamingIndexBuffer::map(UINT requiredSpace, UINT *offset)
{
    void *mapPtr = NULL;

    if (mIndexBuffer)
    {
        HRESULT result = mIndexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, D3DLOCK_NOOVERWRITE);
     
        if (FAILED(result))
        {
            ERR(" Lock failed with error 0x%08x", result);
            return NULL;
        }

        *offset = mWritePosition;
        mWritePosition += requiredSpace;
    }

    return mapPtr;
}

void StreamingIndexBuffer::reserveSpace(UINT requiredSpace, GLenum type)
{
    if (requiredSpace > mBufferSize)
    {
        if (mIndexBuffer)
        {
            mIndexBuffer->Release();
            mIndexBuffer = NULL;
        }

        mBufferSize = std::max(requiredSpace, 2 * mBufferSize);

        D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY);
        HRESULT result = mDevice->CreateIndexBuffer(mBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, type == GL_UNSIGNED_INT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, pool, &mIndexBuffer, NULL);
    
        if (FAILED(result))
        {
            ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize);
        }

        mWritePosition = 0;
    }
    else if (mWritePosition + requiredSpace > mBufferSize)   // Recycle
    {
        void *dummy;
        mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
        mIndexBuffer->Unlock();

        mWritePosition = 0;
    }
}

StaticIndexBuffer::StaticIndexBuffer(IDirect3DDevice9 *device) : IndexBuffer(device, 0, D3DFMT_UNKNOWN)
{
    mCacheType = GL_NONE;
}

StaticIndexBuffer::~StaticIndexBuffer()
{
}

void *StaticIndexBuffer::map(UINT requiredSpace, UINT *offset)
{
    void *mapPtr = NULL;

    if (mIndexBuffer)
    {
        HRESULT result = mIndexBuffer->Lock(0, requiredSpace, &mapPtr, 0);
     
        if (FAILED(result))
        {
            ERR(" Lock failed with error 0x%08x", result);
            return NULL;
        }

        *offset = 0;
    }

    return mapPtr;
}

void StaticIndexBuffer::reserveSpace(UINT requiredSpace, GLenum type)
{
    if (!mIndexBuffer && mBufferSize == 0)
    {
        D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_WRITEONLY);
        HRESULT result = mDevice->CreateIndexBuffer(requiredSpace, D3DUSAGE_WRITEONLY, type == GL_UNSIGNED_INT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, pool, &mIndexBuffer, NULL);
    
        if (FAILED(result))
        {
            ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize);
        }

        mBufferSize = requiredSpace;
        mCacheType = type;
    }
    else if (mIndexBuffer && mBufferSize >= requiredSpace && mCacheType == type)
    {
        // Already allocated
    }
    else UNREACHABLE();   // Static index buffers can't be resized
}

bool StaticIndexBuffer::lookupType(GLenum type)
{
    return mCacheType == type;
}

UINT StaticIndexBuffer::lookupRange(intptr_t offset, GLsizei count, UINT *minIndex, UINT *maxIndex)
{
    for (unsigned int range = 0; range < mCache.size(); range++)
    {
        if (mCache[range].offset == offset && mCache[range].count == count)
        {
            *minIndex = mCache[range].minIndex;
            *maxIndex = mCache[range].maxIndex;

            return mCache[range].streamOffset;
        }
    }

    return -1;
}

void StaticIndexBuffer::addRange(intptr_t offset, GLsizei count, UINT minIndex, UINT maxIndex, UINT streamOffset)
{
    IndexRange indexRange = {offset, count, minIndex, maxIndex, streamOffset};
    mCache.push_back(indexRange);
}

}
