// 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>
#include <algorithm>

namespace
{
    enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) };
}

namespace es2
{

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;
}

}
