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

// ResourceManager.cpp: Implements the ResourceManager class, which tracks and
// retrieves objects which may be shared by multiple Contexts.

#include "ResourceManager.h"

#include "Buffer.h"
#include "Fence.h"
#include "Program.h"
#include "Renderbuffer.h"
#include "Sampler.h"
#include "Shader.h"
#include "Texture.h"

namespace es2
{
ResourceManager::ResourceManager()
{
    mRefCount = 1;
}

ResourceManager::~ResourceManager()
{
    while(!mBufferNameSpace.empty())
    {
        deleteBuffer(mBufferNameSpace.firstName());
    }

	while(!mProgramNameSpace.empty())
    {
		deleteProgram(mProgramNameSpace.firstName());
    }

	while(!mShaderNameSpace.empty())
    {
		deleteShader(mShaderNameSpace.firstName());
    }

    while(!mRenderbufferNameSpace.empty())
    {
        deleteRenderbuffer(mRenderbufferNameSpace.firstName());
    }

    while(!mTextureNameSpace.empty())
    {
        deleteTexture(mTextureNameSpace.firstName());
    }

	while(!mSamplerNameSpace.empty())
	{
		deleteSampler(mSamplerNameSpace.firstName());
	}

	while(!mFenceSyncNameSpace.empty())
	{
		deleteFenceSync(mFenceSyncNameSpace.firstName());
	}
}

void ResourceManager::addRef()
{
    mRefCount++;
}

void ResourceManager::release()
{
    if(--mRefCount == 0)
    {
        delete this;
    }
}

// Returns an unused buffer name
GLuint ResourceManager::createBuffer()
{
    return mBufferNameSpace.allocate();
}

// Returns an unused shader name
GLuint ResourceManager::createShader(GLenum type)
{
	GLuint name = mProgramShaderNameSpace.allocate();

    if(type == GL_VERTEX_SHADER)
    {
		mShaderNameSpace.insert(name, new VertexShader(this, name));
    }
    else if(type == GL_FRAGMENT_SHADER)
    {
		mShaderNameSpace.insert(name, new FragmentShader(this, name));
    }
    else UNREACHABLE(type);

	return name;
}

// Returns an unused program name
GLuint ResourceManager::createProgram()
{
	GLuint name = mProgramShaderNameSpace.allocate();

	mProgramNameSpace.insert(name, new Program(this, name));

	return name;
}

// Returns an unused texture name
GLuint ResourceManager::createTexture()
{
	return mTextureNameSpace.allocate();
}

// Returns an unused renderbuffer name
GLuint ResourceManager::createRenderbuffer()
{
	return mRenderbufferNameSpace.allocate();
}

// Returns an unused sampler name
GLuint ResourceManager::createSampler()
{
	return mSamplerNameSpace.allocate();
}

// Returns the next unused fence name, and allocates the fence
GLuint ResourceManager::createFenceSync(GLenum condition, GLbitfield flags)
{
	GLuint name = mFenceSyncNameSpace.allocate();

	FenceSync *fenceSync = new FenceSync(name, condition, flags);
	fenceSync->addRef();

	mFenceSyncNameSpace.insert(name, fenceSync);

	return name;
}

void ResourceManager::deleteBuffer(GLuint buffer)
{
	Buffer *bufferObject = mBufferNameSpace.remove(buffer);

    if(bufferObject)
    {
		bufferObject->release();
    }
}

void ResourceManager::deleteShader(GLuint shader)
{
    Shader *shaderObject = mShaderNameSpace.find(shader);

    if(shaderObject)
    {
        if(shaderObject->getRefCount() == 0)
        {
			delete shaderObject;
			mShaderNameSpace.remove(shader);
			mProgramShaderNameSpace.remove(shader);
        }
        else
        {
            shaderObject->flagForDeletion();
        }
    }
}

void ResourceManager::deleteProgram(GLuint program)
{
    Program *programObject = mProgramNameSpace.find(program);

    if(programObject)
    {
        if(programObject->getRefCount() == 0)
        {
			delete programObject;
			mProgramNameSpace.remove(program);
			mProgramShaderNameSpace.remove(program);
        }
        else
        {
            programObject->flagForDeletion();
        }
    }
}

void ResourceManager::deleteTexture(GLuint texture)
{
    Texture *textureObject = mTextureNameSpace.remove(texture);

    if(textureObject)
    {
		textureObject->release();
    }
}

void ResourceManager::deleteRenderbuffer(GLuint renderbuffer)
{
    Renderbuffer *renderbufferObject = mRenderbufferNameSpace.remove(renderbuffer);

    if(renderbufferObject)
    {
		renderbufferObject->release();
    }
}

void ResourceManager::deleteSampler(GLuint sampler)
{
	Sampler *samplerObject = mSamplerNameSpace.remove(sampler);

	if(samplerObject)
	{
		samplerObject->release();
	}
}

void ResourceManager::deleteFenceSync(GLuint fenceSync)
{
	FenceSync *fenceObject = mFenceSyncNameSpace.remove(fenceSync);

	if(fenceObject)
	{
		fenceObject->release();
	}
}

Buffer *ResourceManager::getBuffer(unsigned int handle)
{
    return mBufferNameSpace.find(handle);
}

Shader *ResourceManager::getShader(unsigned int handle)
{
    return mShaderNameSpace.find(handle);
}

Texture *ResourceManager::getTexture(unsigned int handle)
{
    return mTextureNameSpace.find(handle);
}

Program *ResourceManager::getProgram(unsigned int handle)
{
    return mProgramNameSpace.find(handle);
}

Renderbuffer *ResourceManager::getRenderbuffer(unsigned int handle)
{
    return mRenderbufferNameSpace.find(handle);
}

Sampler *ResourceManager::getSampler(unsigned int handle)
{
	return mSamplerNameSpace.find(handle);
}

FenceSync *ResourceManager::getFenceSync(unsigned int handle)
{
	return mFenceSyncNameSpace.find(handle);
}

void ResourceManager::checkBufferAllocation(unsigned int buffer)
{
    if(buffer != 0 && !getBuffer(buffer))
    {
        Buffer *bufferObject = new Buffer(buffer);
		bufferObject->addRef();

		mBufferNameSpace.insert(buffer, bufferObject);
    }
}

void ResourceManager::checkTextureAllocation(GLuint texture, TextureType type)
{
    if(!getTexture(texture) && texture != 0)
    {
        Texture *textureObject;

        if(type == TEXTURE_2D)
        {
            textureObject = new Texture2D(texture);
        }
        else if(type == TEXTURE_CUBE)
        {
            textureObject = new TextureCubeMap(texture);
        }
		else if(type == TEXTURE_EXTERNAL)
		{
			textureObject = new TextureExternal(texture);
		}
		else if(type == TEXTURE_3D)
		{
			textureObject = new Texture3D(texture);
		}
		else if(type == TEXTURE_2D_ARRAY)
		{
			textureObject = new Texture2DArray(texture);
		}
		else
        {
            UNREACHABLE(type);
            return;
        }

		textureObject->addRef();

		mTextureNameSpace.insert(texture, textureObject);
    }
}

void ResourceManager::checkRenderbufferAllocation(GLuint handle)
{
	if(handle != 0 && !getRenderbuffer(handle))
	{
		Renderbuffer *renderbufferObject = new Renderbuffer(handle, new Colorbuffer(0, 0, GL_RGBA4_OES, 0));
		renderbufferObject->addRef();

		mRenderbufferNameSpace.insert(handle, renderbufferObject);
	}
}

void ResourceManager::checkSamplerAllocation(GLuint sampler)
{
	if(sampler != 0 && !getSampler(sampler))
	{
		Sampler *samplerObject = new Sampler(sampler);
		samplerObject->addRef();

		mSamplerNameSpace.insert(sampler, samplerObject);
	}
}

bool ResourceManager::isSampler(GLuint sampler)
{
	return mSamplerNameSpace.isReserved(sampler);
}

}
