// SwiftShader Software Renderer
//
// Copyright(c) 2005-2012 TransGaming Inc.
//
// All rights reserved. No part of this software may be copied, distributed, transmitted,
// transcribed, stored in a retrieval system, translated into any human or computer
// language by any means, or disclosed to third parties without the explicit written
// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
// or implied, including but not limited to any patent rights, are granted to you.
//

// IndexDataManager.cpp: Defines the IndexDataManager, a class that
// runs the Buffer translation process for index buffers.

#include "IndexDataManager.h"

#include "Buffer.h"
#include "common/debug.h"

#include <string.h>

namespace
{
    enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) };
}

namespace gl
{

IndexDataManager::IndexDataManager()
{
    mStreamingBuffer = new StreamingIndexBuffer(INITIAL_INDEX_BUFFER_SIZE);

    if(!mStreamingBuffer)
    {
        ERR("Failed to allocate the streaming index buffer.");
    }
}

IndexDataManager::~IndexDataManager()
{
    delete mStreamingBuffer;
}

void copyIndices(GLenum type, const void *input, GLsizei count, void *output)
{
    if(type == GL_UNSIGNED_BYTE)
    {
        memcpy(output, input, count * sizeof(GLubyte));
    }
    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)
{
    if(!mStreamingBuffer)
    {
        return GL_OUT_OF_MEMORY;
    }

    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 = mStreamingBuffer;

	sw::Resource *staticBuffer = buffer ? buffer->getResource() : NULL;

    if(staticBuffer)
    {
        computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);

		translated->indexBuffer = staticBuffer;
		translated->indexOffset = offset;
    }
    else
    {
		unsigned int streamOffset = 0;
        int convertCount = count;

        streamingBuffer->reserveSpace(convertCount * typeSize(type), type);
        void *output = streamingBuffer->map(typeSize(type) * convertCount, &streamOffset);
        
        if(output == NULL)
        {
            ERR("Failed to map index buffer.");
            return GL_OUT_OF_MEMORY;
        }

        copyIndices(type, staticBuffer ? buffer->data() : indices, convertCount, output);
        streamingBuffer->unmap();

        computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);

		translated->indexBuffer = streamingBuffer->getResource();
		translated->indexOffset = streamOffset;
    }

    return GL_NO_ERROR;
}

std::size_t IndexDataManager::typeSize(GLenum type)
{
    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);
    }
}

StreamingIndexBuffer::StreamingIndexBuffer(unsigned int initialSize) : mBufferSize(initialSize), mIndexBuffer(NULL)
{
	if(initialSize > 0)
    {
		mIndexBuffer = new sw::Resource(initialSize + 16);

        if(!mIndexBuffer)
        {
            ERR("Out of memory allocating an index buffer of size %lu.", initialSize);
        }
    }

    mWritePosition = 0;
}

StreamingIndexBuffer::~StreamingIndexBuffer()
{
	if(mIndexBuffer)
    {
        mIndexBuffer->destruct();
    }
}

void *StreamingIndexBuffer::map(unsigned int requiredSpace, unsigned int *offset)
{
    void *mapPtr = NULL;

    if(mIndexBuffer)
    {
        mapPtr = (char*)mIndexBuffer->lock(sw::PUBLIC) + mWritePosition;
     
        if(!mapPtr)
        {
            ERR(" Lock failed");
            return NULL;
        }

        *offset = mWritePosition;
        mWritePosition += requiredSpace;
    }

    return mapPtr;
}

void StreamingIndexBuffer::unmap()
{
    if(mIndexBuffer)
    {
        mIndexBuffer->unlock();
    }
}

void StreamingIndexBuffer::reserveSpace(unsigned int requiredSpace, GLenum type)
{
    if(requiredSpace > mBufferSize)
    {
        if(mIndexBuffer)
        {
            mIndexBuffer->destruct();
            mIndexBuffer = 0;
        }

        mBufferSize = std::max(requiredSpace, 2 * mBufferSize);

		mIndexBuffer = new sw::Resource(mBufferSize + 16);
    
        if(!mIndexBuffer)
        {
            ERR("Out of memory allocating an index buffer of size %lu.", mBufferSize);
        }

        mWritePosition = 0;
    }
    else if(mWritePosition + requiredSpace > mBufferSize)   // Recycle
    {
		if(mIndexBuffer)
		{
			mIndexBuffer->destruct();
			mIndexBuffer = new sw::Resource(mBufferSize + 16);
		}

        mWritePosition = 0;
    }
}

sw::Resource *StreamingIndexBuffer::getResource() const
{
    return mIndexBuffer;
}

}
