//	Darkstar Engine  (c) UnderWorld Interactive Studio (all coding by Svarog    2007-2008)
//
//      Данный файл является частью Darkstar Engine. Любое использование кода файла
//      без согласия компании, является нарушением закона об авторском праве (в слу-
//      чае если не оговорено обратное).
//
//      Имя файла: index_buffer_d3d9.cpp
//      Краткое описание: Индексный буфер для платформы Direct3D 9
//

#ifdef GD_D3D9

#include <Darkstar/Resource System/Model/index_buffer_d3d9.hpp>
#include <Darkstar/Kernel/logh.hpp>
#include <Darkstar/Graphic System/Direct3D/graphicDriver.hpp>

using namespace rs;
using gs::GraphicDriver;
using ker::Log;

IndexBuffer::IndexBuffer()
{
	buffer = NULL;
	buf_size = 0;
	ind_count = 0;
};

IndexBuffer::IndexBuffer(const unsigned int ind_count, const IBTYPE& type, const DEUSAGE& usage /* = DEU_DYNAMIC */)
{
	buffer = NULL;
	create(ind_count, type, usage);
};

IndexBuffer::~IndexBuffer()
{
	if(buffer)
	{
		if(FAILED(buffer->Release()))
		{
			lwar << "Cannot release index buffer";
			return;
		};
		buffer = NULL;
	};
};

bool IndexBuffer::create(const unsigned int ind_count, const IBTYPE& type, const DEUSAGE& usage /* = DEU_DYNAMIC */)
{
	if(buffer)
	{
		lwar << "Index buffer have already created";
		return false;
	};
	buf_size = type == DSEIB_16 ? ind_count << 1 : ind_count << 2;
	this->ind_count = ind_count;
	buf_type = type;
	if(FAILED(GraphicDriver::ptr()->getDevice()->CreateIndexBuffer(buf_size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, (D3DFORMAT)buf_type, D3DPOOL_DEFAULT, &buffer, NULL)))
	{
		lwar << "Cannot create index buffer";
		return false;
	};
	is_dynamic = true;
	return true;
};

bool IndexBuffer::createWithData(const unsigned int ind_count, const IBTYPE& type, void* data, const DEUSAGE& usage /* = DEU_DEFAULT */)
{
	if(buffer)
	{
		lwar << "Index buffer have already created";
		return false;
	};
	buf_size = type == DSEIB_16 ? ind_count << 1 : ind_count << 2;
	this->ind_count = ind_count;
	buf_type = type;
	if(FAILED(GraphicDriver::ptr()->getDevice()->CreateIndexBuffer(buf_size, 0, (D3DFORMAT)buf_type, D3DPOOL_MANAGED, &buffer, NULL)))
	{
		lwar << "Cannot create index buffer";
		return false;
	};
	is_dynamic = false;
	upload(0, data, 0);
	return true;
};

bool IndexBuffer::upload(const unsigned int size, void* data, const unsigned int offset)
{
	if(!buffer)
	{
		lwar << "Cannot upload uninitialized buffer";
		return false;
	};
	unsigned int up_size = size;
	if(size == 0)
		up_size = buf_size;
	void* ptr;
	if(!(ptr = map(DEMT_WRITE_DISCARD)))
	{
		lwar << "Cannot map index buffer";
		return false;
	};
	memcpy((char*)ptr + offset, (char*)data, up_size);
	unmap();
	return true;
};

void* IndexBuffer::map(const DEMAPTYPE& map_type)
{
	DWORD flags = is_dynamic ? D3DLOCK_DISCARD : 0;
	void* ptr = NULL;
	if(FAILED(buffer->Lock(0, 0, &ptr, flags)))
	{
		lwar << "Cannot lock entire index buffer";
		return NULL;
	};
	return ptr;
};

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

const unsigned int IndexBuffer::getIndicesNumber() const
{
	return ind_count;
};

void IndexBuffer::set()
{
	GraphicDriver::ptr()->getDevice()->SetIndices(buffer);
};

#endif