/* -----------------------------------------------------------------------------
	GSFramework
	Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */


#ifndef	__GPUDISPLAYLIST__
#define __GPUDISPLAYLIST__


		#include "gpu/gpu_vbo.h"
		#include "core/render_data.h"
		#include "memory/nauto_ptr.h"


namespace GS {

	namespace Core {
		struct Trilist;
		struct Patch;
		class Emitter;
		class Item;
	}
	namespace GPU {
		class Renderer;

//
struct	DisplayList
{
		NPLACEMENT_NEW(Renderer)

		Renderer		&renderer;

		AutoPtr <VBO>	idx, vtx;
		Array <ushort>	idx_map;
		Array <char>	vtx_map;
		size_t			stride;

		MinMax			minmax;

		uint			index_count;

		size_t			vertex_offset,
						normal_offset,
						rgb_offset,
						uv_offset[__UV_PER_GEOMETRY__],
						tangent_offset,
						skinning_offset;

		Array <ushort>	bone;

		Render::sMaterial material;

		/// Create display list from a triangle list.
virtual	bool			Create(Core::Trilist *, Render::Material *);
		/// Draw display list.
virtual	void			Draw() = 0;

		DisplayList(Renderer &r) : renderer(r)
		{
			idx = 0;
			vtx = 0;

			index_count = 0;

			vertex_offset = (size_t)-1;
			normal_offset = (size_t)-1;
			rgb_offset = (size_t)-1;
			for	(uint n = 0; n < __UV_PER_GEOMETRY__; ++n)
				uv_offset[n] = (size_t)-1;
			tangent_offset = (size_t)-1;
			skinning_offset = (size_t)-1;

			stride = 0;
		}
virtual	~DisplayList() {}
};

//
struct	RenderPrimitive
{
		NPLACEMENT_NEW(Renderer)

enum Type
{
		TypeDisplayList		=	0,
		TypeEmitter,
		TypeTerrainPatch
};

		Type		type;
		const Core::Item *item;

		union
		{
			DisplayList		*dlst;
			Core::Emitter	*emitter;
			Core::Patch		*patch;
		};

		bool		operator == (const RenderPrimitive &b)
		{	return (type == b.type) && (item == b.item) && (dlst == b.dlst);	}

		RenderPrimitive(const Core::Item *i, DisplayList *d) : type(TypeDisplayList), item(i), dlst(d) {}
		RenderPrimitive(const Core::Item *i, Core::Emitter *e) : type(TypeEmitter), item(i), emitter(e) {}
		RenderPrimitive(const Core::Item *i, Core::Patch *p) : type(TypeTerrainPatch), item(i), patch(p) {}
};

	} // GPU
} // GS


#endif	// __GPUDISPLAYLIST__
