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

#ifdef GD_D3D10

#include <Darkstar/Resource System/Model/input_layout_d3d10.hpp>
#include <Darkstar/Graphic System/direct3D.hpp>
#include <Darkstar/Kernel/logh.hpp>

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

InputLayout::InputLayout()
{
	decl = NULL;
}

InputLayout::~InputLayout()
{
	if(decl)
	{
		if(FAILED(decl->Release()))
		{
			lwar << "Cannot release vertex declaration";
			return;
		};
		decl = NULL;
	}
}

std::vector<D3D10_INPUT_ELEMENT_DESC> InputLayout::_getD3DElements()
{
	std::vector<D3D10_INPUT_ELEMENT_DESC> elems;
	for(unsigned int i = 0; i < (unsigned int)elements.size(); ++i)
	{
		D3D10_INPUT_ELEMENT_DESC new_elem;
		new_elem.AlignedByteOffset = elements[i].offset;
		new_elem.Format = (DXGI_FORMAT)elements[i].format;
		new_elem.InputSlot = elements[i].stream;
		new_elem.InputSlotClass = D3D10_INPUT_PER_VERTEX_DATA;
		new_elem.InstanceDataStepRate = 0;
		new_elem.SemanticIndex = elements[i].usage_index;
		new_elem.SemanticName = elements[i].usage.c_str();
		elems.push_back(new_elem);
	};
	return elems;
};

bool InputLayout::create(const void* compiled_shader_code, const unsigned int code_size)
{
	if(!compiled_shader_code)
	{
		lwar << "Compiled shader code is not define";
		return false;
	};
	if(decl)
	{
		lwar << "Vertex declaration have already created";
		return false;
	};
	if(elements.empty())
	{
		lwar << "Cannot create vertex declaration. Vector of elements is empty";
		return false;
	};
	std::vector<D3D10_INPUT_ELEMENT_DESC> d3d_elements = _getD3DElements();
	unsigned int num_elements = static_cast<unsigned int>(d3d_elements.size());
	if(FAILED(GraphicDriver::ptr()->getDevice()->CreateInputLayout(&d3d_elements[0], num_elements,
		compiled_shader_code, code_size, &decl)))
	{
		lwar << "Cannot create input layout";
		return false;
	};
	elements.clear();
	return true;
};

void InputLayout::set()
{
	GraphicDriver::ptr()->getDevice()->IASetInputLayout(decl);
};

#endif