/*
	Trampoline Sim.
	Copyright (c) 2009, Darragh Coy.
	All rights reserved.
	Original work(s), source code & author(s) details available at: http://www.darraghcoy.com

	Redistribution and use in source and binary forms, with or without modification, are permitted 
	provided that the following conditions are met:

		* 	Redistributions of source code must retain the above copyright notice, this list of 
			conditions and the following disclaimer.
		* 	Redistributions in binary form must reproduce the above copyright notice, this list of 
			conditions and the following disclaimer in the documentation.
		* 	Neither the name of the author nor the names of contributors may be used to endorse or 
			promote products derived from this software without specific prior written permission.
		* 	The use of any third party libraries, modules or data files provided with the source 
			form of the program must follow and respect the individual licensing terms of these 
			components. You do not have permission to modify or circumvent the licensing terms for 
			provided third party components unless the third party licenses specifically allow this. 
			If you do not agree to the terms of provided third party components then you do not have 
			permission to use them in your derived work(s).
		* 	The terms of this license do not apply to separate (but related) distributions if supplied 
			by the author(s), only to the contents of this source distribution, derived works, and the 
			binaries produced by either modified or unmodified versions of the source code. The terms 
			of this license do not also apply to any third party libraries or components provided with 
			the source distribution. Such third party elements are licensed under their own separate 
			agreements.

	THIS SOFTWARE IS PROVIDED BY DARRAGH COY ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
	BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
	ARE DISCLAIMED. IN NO EVENT SHALL DARRAGH COY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
	OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
	OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
	IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef VERTEX_BUFFER_H
#define VERTEX_BUFFER_H

//=====================================================================================================================
//=====================================================================================================================

#include "Graphics\Display.h"
#include "Graphics\DisplayEvictable.h"

//=====================================================================================================================
//=====================================================================================================================

namespace Game
{
	//=================================================================================================================
	//=================================================================================================================

	class Display;
	
	//=================================================================================================================
	/// @brief		Represents a vertex buffer that can be used to store geometric data on the graphics card 
	///				(or wherever the driver places it). Vertex buffers can be either static or dynamic. See the notes
	///				concernng the vertex buffer type.
	/// @pre		Although a best effort will be made to restore the vertex buffer after a device reset, it is not
	///				guaranteed that the buffer will be restored due to whatever resource demands are put on the system.
	///				Therefore once-off validation cannot be used on a VertexBuffer object, it must be checked to see if
	///				it is ok every time before it is used.
	//=================================================================================================================

	class VertexBuffer : public DisplayEvictable
	{
		public:	
		
			//=========================================================================================================
			// Enums
			//=========================================================================================================
			
				/// Represents what type of vertex buffer this is

				enum Type
				{
					//'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
					/// Vertex buffer is designed only to be filled once and is more than likely lumped into VRAM 
					/// directly. There may be a big peformance penalty to writing to static VBs while they are in
					/// use. Vertex buffer contents are automatically cloned in memmory and are automatically restored
					///	upon a device reset.
					//'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

					TYPE_STATIC = 0,
					
					//'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
					/// Vertex buffer is dynamic and designed so that it can be written to arbitrarily. Contents of the 
					/// vertex buffer are discarded upon each write for performance and the contents of the buffer will
					/// not persist across device resets. If the contents of the buffer was lost, this can be determined
					/// by querying AreContentsLost().
					//'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

					TYPE_DYNAMIC = 1
				};

			//=========================================================================================================
			// Functions
			//=========================================================================================================

				/// Creates the vertex buffer
			
				VertexBuffer( Display * display , Type type , unsigned size );

				/// Destroys the vertex buffer

				virtual ~VertexBuffer();

				/// Tells the object to announce it's type name: this is the type name without the Game:: namespace

				virtual const char * GetTypeName() const;
				
				/// Returns a pointer to the directx vertex buffer held by this object
				
				inline IDirect3DVertexBuffer9 * GetDXBuffer(){ return m_vb; }

				/// Writes to the specified area of the vertex buffer

				void Write( void * data , unsigned buffer_offset , unsigned size , bool wait_till_free = true );

				/// Tells the resource to release all it's resources upon the graphics device being lost: only the display should call this! 
				
				virtual void ReleaseEvictableResources();
				
				/// Tells the resource to recreate all it's resources upon the graphics device being recreated: only the display should call this! 
				
				virtual void RecreateEvictableResources();
				
				//'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
				/// @brief		Tells if the contents of the buffer were lost after a device reset, and if they need 
				///				re-updating.
				/// @returns	True if the contents of the vertex buffer were lost
				/// @remarks	This always returns false for TYPE_STATIC vertex buffers since they are automatically
				///				recreated, except in the case where the buffer has been created but not yet filled.
				///				The only way to make this condition false again is to fix the problem and re-fill the 
				///				buffer.
				//'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

				inline bool HasLostContents(){ return m_lost_contents; }
				
				//=====================================================================================================
				/// @brief		Binds this vertex buffer to the pipeline for use by the display
				/// @param		stride - stride or size of each vertex to be drawn
				/// @pre		The vertex buffer must be valid
				/// @pre		This buffer should not already be bound to the pipeline
				//=====================================================================================================
				
				inline void Bind( unsigned stride )
				{
					// Make sure ok:
					
					ENSURE( IsValid()								, "The vertex buffer must be valid"							)
					ENSURE( GetDisplay()->GetVertexBuffer() != this	, "This buffer should not already be bound to the pipeline" )
					
					// Do the bind
				
					GetDisplay()->SetVertexBuffer(this,stride);
				}
				
				//=====================================================================================================
				/// @brief		Unbinds this vertex buffer to the pipeline for use by the display
				/// @pre		The vertex buffer must be valid
				/// @pre		This buffer must be bound to the pipeline
				//=====================================================================================================
				
				inline void Unbind()
				{
					// Make sure ok:
					
					ENSURE( IsValid()								, "The vertex buffer must be valid"				)
					ENSURE( GetDisplay()->GetVertexBuffer() == this	, "This buffer must be bound to the pipeline"	)
					
					// Do the bind
				
					GetDisplay()->SetVertexBuffer(0,0);					
				}

		private:		

			//=========================================================================================================
			// Variables
			//=========================================================================================================
			
				/// The actual directx 9 vertex buffer

				IDirect3DVertexBuffer9 * m_vb;

				/// This is set to true if the contents of the buffer were lost after at device reset

				bool m_lost_contents;

				/// A copy in memory of the vertex buffer. This is only used for static vertex buffers.

				void * m_vb_mem_copy;

				/// What type of vertex buffer this is

				Type m_type;

				/// Size of the vertex buffer

				unsigned m_size;
	};

};

#endif 
