///////////////////////////////////////////////////////////////////////////////
//
// File		: Asura_PS3_GCM_IndexBuffer.h
// Author	: Andy Tate (22-Jul-2005)
// Modified	: Catalin Arsenescu (27-March-2007)
//
// Copyright (C) 2005 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

#ifdef ASURA_USE_PRAGMA_ONCE
	#pragma once
#endif   // ifdef ASURA_USE_PRAGMA_ONCE

#ifndef __ASURA_PS3_GCM_INDEXBUFFER_H__
#define __ASURA_PS3_GCM_INDEXBUFFER_H__

////////////////////////////////////////////////////////////////////////////////
// Include files...
////////////////////////////////////////////////////////////////////////////////
#include "Rendering/Asura_PS3_Graphics.h"
#include "Rendering/Asura_Render.h"
#include "Rendering/Asura_PS3_RenderingStates.h"
#include "Debugging/Asura_Logfile.h"

////////////////////////////////////////////////////////////////////////////////
// Class declaration...
////////////////////////////////////////////////////////////////////////////////

class Asura_PS3_GCM_VertexBuffer;

class Asura_PS3_GCM_IndexBuffer
{
public:
	// Public functions...

	// Constructor/destructor...
	////////////////////////////////////////////////////////////////////////////////
	// Function     : Asura_PS3_GCM_IndexBuffer::Asura_PS3_GCM_IndexBuffer
	// Author       : 
	// Modified		: Catalin Arsenescu (28-March-2007)
	////////////////////////////////////////////////////////////////////////////////
	Asura_PS3_GCM_IndexBuffer()
	{
		m_uIndexBufferSize		= 0;
		m_bUsingGlobalAllocator	= false;
		m_pxIndex				= NULL;
	}

	////////////////////////////////////////////////////////////////////////////////
	// Function     : Asura_PS3_GCM_IndexBuffer::~Asura_PS3_GCM_IndexBuffer
	// Author       : 
	////////////////////////////////////////////////////////////////////////////////
	~Asura_PS3_GCM_IndexBuffer ()
	{
		Shutdown	();
	}
		
	// Initialisation/shutdown...
	void Initialise				( const u_int uNumberOfVertices, u_char ucIndexArrayType = CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16, u_char ucLocation = CELL_GCM_LOCATION_LOCAL, bool bForceLocation = false );
	void InitialiseFromBuffer	( const u_int uNumberOfVertices );
	void Shutdown		( void );

    const void* GetReadPtr( void ) const
    {
        return m_pxIndex;
    }

	void* LockForWriting (void)
	{ 
		return m_pxIndex;
	}

	void Unlock (void)
	{
		//Probably the cache must be invalidated to maintain the coherency.
	}

	void SetRestartIndex( void ) const
	{
		if( m_ucIndexArrayType == CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16 )
		{
			Asura_PS3_RenderingStates::SetRestartIndex( 0x0000FFFF );
		}
		else
		{
			Asura_PS3_RenderingStates::SetRestartIndex( 0xFFFFFFFF );
		}
	}

	// Rendering functions...
	////////////////////////////////////////////////////////////////////////////////
	// Function     : Asura_PS3_GCM_IndexBuffer::RenderQuadStrip
	// Author       : 
	// Modified		: Catalin Arsenescu (28-March-2007)
	////////////////////////////////////////////////////////////////////////////////
	void RenderQuadStrip (const u_int uNumIndices, const u_int uStartIndex = 0) const
	{
		SetRestartIndex();
		cellGcmSetDrawIndexArrayUnsafeInline( Asura_PS3_Graphics::GetGcmCurrentContext(), CELL_GCM_PRIMITIVE_QUAD_STRIP, uNumIndices, m_ucIndexArrayType, m_ucLocation, m_uIndexOffset + ( uStartIndex * m_ucIndexSize ));
		Asura_Render::AddToTrianglesRendered(uNumIndices - 2);
	}

	////////////////////////////////////////////////////////////////////////////////
	// Function     : Asura_PS3_GCM_IndexBuffer::RenderQuads
	// Author       : 
	// Modified		: Catalin Arsenescu (28-March-2007)
	////////////////////////////////////////////////////////////////////////////////
	void RenderQuads (const u_int uNumIndices, const u_int uStartIndex = 0) const
	{
		SetRestartIndex();
		cellGcmSetDrawIndexArrayUnsafeInline( Asura_PS3_Graphics::GetGcmCurrentContext(), CELL_GCM_PRIMITIVE_QUADS, uNumIndices, m_ucIndexArrayType, m_ucLocation, m_uIndexOffset + ( uStartIndex * m_ucIndexSize ));
		Asura_Render::AddToTrianglesRendered(uNumIndices / 2);
	}

	void RenderQuadsInline( Asura_PS3_GCM_VertexBuffer* pxVertexBuffer, const u_int uNumIndices, const u_int uStartIndex = 0 ) const;

	////////////////////////////////////////////////////////////////////////////////
	// Function     : Asura_PS3_GCM_IndexBuffer::RenderTriangleFan
	// Author       : 
	// Modified		: Catalin Arsenescu (28-March-2007)
	////////////////////////////////////////////////////////////////////////////////
	void RenderTriangleFan (const u_int uNumIndices, const u_int uStartIndex = 0) const
	{
		SetRestartIndex();
		cellGcmSetDrawIndexArrayUnsafeInline( Asura_PS3_Graphics::GetGcmCurrentContext(), CELL_GCM_PRIMITIVE_TRIANGLE_FAN, uNumIndices, m_ucIndexArrayType, m_ucLocation, m_uIndexOffset + ( uStartIndex * m_ucIndexSize ) );
		Asura_Render::AddToTrianglesRendered(uNumIndices - 2);
	}

	////////////////////////////////////////////////////////////////////////////////
	// Function     : Asura_PS3_GCM_IndexBuffer::RenderTriangleStrip
	// Author       : 
	// Modified		: Catalin Arsenescu (28-March-2007)
	////////////////////////////////////////////////////////////////////////////////
	void RenderTriangleStrip (const u_int uNumIndices, const u_int uStartIndex = 0) const
	{
		SetRestartIndex();
		cellGcmSetDrawIndexArrayUnsafeInline( Asura_PS3_Graphics::GetGcmCurrentContext(), CELL_GCM_PRIMITIVE_TRIANGLE_STRIP, uNumIndices, m_ucIndexArrayType, m_ucLocation, m_uIndexOffset + ( uStartIndex * m_ucIndexSize ) );
		Asura_Render::AddToTrianglesRendered(uNumIndices - 2);
	}

	////////////////////////////////////////////////////////////////////////////////
	// Function     : Asura_PS3_GCM_IndexBuffer::RenderTriangles
	// Author       : 
	// Modified		: Catalin Arsenescu (28-March-2007)
	////////////////////////////////////////////////////////////////////////////////
	void RenderTriangles (const u_int uNumIndices, const u_int uStartIndex = 0) const
	{
		SetRestartIndex();
		cellGcmSetDrawIndexArrayUnsafeInline( Asura_PS3_Graphics::GetGcmCurrentContext(), CELL_GCM_PRIMITIVE_TRIANGLES, uNumIndices, m_ucIndexArrayType, m_ucLocation, m_uIndexOffset + ( uStartIndex * m_ucIndexSize ) );
		Asura_Render::AddToTrianglesRendered(uNumIndices / 3);
	}

	////////////////////////////////////////////////////////////////////////////////
	// Function     : Asura_PS3_GCM_IndexBuffer::RenderLineStrip
	// Author       : Ben Weston (10-Oct-2008)
	////////////////////////////////////////////////////////////////////////////////
	void RenderLineStrip (const u_int uNumIndices, const u_int uStartIndex = 0) const
	{
		SetRestartIndex();
		cellGcmSetDrawIndexArrayUnsafeInline( Asura_PS3_Graphics::GetGcmCurrentContext(), CELL_GCM_PRIMITIVE_LINE_STRIP, uNumIndices, m_ucIndexArrayType, m_ucLocation, m_uIndexOffset + ( uStartIndex * m_ucIndexSize ) );
	}

	////////////////////////////////////////////////////////////////////////////////
	// Function     : Asura_PS3_GCM_IndexBuffer::RenderLines
	// Author       : Ben Weston (10-Oct-2008)
	////////////////////////////////////////////////////////////////////////////////
	void RenderLines (const u_int uNumIndices, const u_int uStartIndex = 0) const
	{
		SetRestartIndex();
		cellGcmSetDrawIndexArrayUnsafeInline( Asura_PS3_Graphics::GetGcmCurrentContext(), CELL_GCM_PRIMITIVE_LINES, uNumIndices, m_ucIndexArrayType, m_ucLocation, m_uIndexOffset + ( uStartIndex * m_ucIndexSize ) );
	}

	// Accessor functioms...
	////////////////////////////////////////////////////////////////////////////////
	// Function     : Asura_PS3_GCM_IndexBuffer::GetIndexBufferSize
	// Author       : 
	////////////////////////////////////////////////////////////////////////////////
	u_int GetIndexBufferSize (void) const	{ return ( m_uIndexBufferSize ); }

	bool IsInitialized( void ) const { return m_pxIndex != NULL; }

	bool Is32BitIndex( void ) const { return ( m_ucIndexSize == 4 ); }

private:
	// Private variables...
	void*	m_pxIndex;					// The index data
	u_int	m_uIndexOffset;				// Offset location of the index buffer
	u_int	m_uIndexBufferSize;			// Total size of index-buffer...
	u_char	m_ucLocation;				// CELL_GCM_LOCATION_MAIN or CELL_GCM_LOCATION_LOCAL
	u_char	m_ucIndexArrayType;			// CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16 or CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32
	u_char	m_ucIndexSize;				// 2 or 4 bytes
	bool	m_bUsingGlobalAllocator;

	// Private functions...
	Asura_PS3_GCM_IndexBuffer  (const Asura_PS3_GCM_IndexBuffer& xOther);
	Asura_PS3_GCM_IndexBuffer&	operator=	(const Asura_PS3_GCM_IndexBuffer& xOther);
};   // End of class 'Asura_PS3_GCM_IndexBuffer'.

#endif   // ifndef __ASURA_PS3_GCM_INDEXBUFFER_H__

/// End of file. ///
