/****************************/
/*	VERTEX ARRAY RANGE.C	*/
/* (c)2004 Pangea Software  */
/* By Brian Greenstone      */
/****************************/

#include <string.h>

/****************************/
/*    PROTOTYPES            */
/****************************/



/**************************/
/*    EXTERNS             */
/**************************/



/**************************/
/*    CONSTANTS           */
/**************************/

#define	NUM_VERTEX_ARRAY_RANGES	10



typedef struct
{
	long	rangeSize;				// # of bytes in this VAR block
	void	*dataBlockPtr;			// ptr to the memory that we're making VAR
	Boolean	forceUpdate;			// true if data in VAR block needs updating
	Boolean	activated;				// set to true the first time we use it
}VertexArrayRangeType;


/****************************/
/*    VARIABLES             */
/****************************/

GLuint							gVertexArrayRangeObjects[NUM_VERTEX_ARRAY_RANGES];	// OpenGL's VAR object references
static	VertexArrayRangeType	gVertexArrayRangeData[NUM_VERTEX_ARRAY_RANGES];		// our info about each VAR block


/************* INIT VERTEX ARRAY RANGES ******************/
//
// Initilizes data that we'll need later to assign RAM for VAR use.
//

void OGL_InitVertexArrayRanges(void)
{
short		i;
static char	*s;

			/* DETERMINE IF HARDWARE SUPPORTS VAR */

	s = (char *)glGetString(GL_EXTENSIONS);					// get extensions list
				
	if (strstr(s, "GL_APPLE_vertex_array_range") == nil)
		DoFatalAlert("\pVertex Array Range not supported.");

	
		/* GENERATE VERTEX ARRAY OBJECTS */
		//
		// Each object represents a chunk of RAM that
		// weĠre marking for VAR use.
		//
		
	glGenVertexArraysAPPLE(NUM_VERTEX_ARRAY_RANGES, &gVertexArrayRangeObjects[0]);


			/* INIT OUR DATA */
			//
			// None of the VAR objects has been assigned to any data yet, 
			// so here we just initialize our info.  We'll assign the VAR objects
			// to data later.
			//
			
	for (i = 0; i < NUM_VERTEX_ARRAY_RANGES; i++)							
	{
		gVertexArrayRangeData[i].rangeSize		= 0;
		gVertexArrayRangeData[i].dataBlockPtr	= nil;
		gVertexArrayRangeData[i].forceUpdate	= true;
		gVertexArrayRangeData[i].activated		= false;
	}
}


/*************** ASSIGN VERTEX ARRAY RANGE MEMORY *********************/
//
// Adds a block of memory to our VAR list.
//
// INPUT:	size = # of bytes in block of memory
//			data = pointer to memory
//			whichVAR = which VAR # in our list to store this into
//

void OGL_AssignVertexArrayRangeMemory(long size, void *data, Byte whichVAR)
{
	if (whichVAR >= NUM_VERTEX_ARRAY_RANGES)
		DoFatalAlert("\pVAR is out of range!");

	gVertexArrayRangeData[whichVAR].rangeSize 		= size;
	gVertexArrayRangeData[whichVAR].dataBlockPtr 	= data;
	gVertexArrayRangeData[whichVAR].forceUpdate 	= true;
}


/***************** UPDATE VERTEX ARRAY RANGES *******************/
//
// Called from OGL_DrawScene() before any geometry is submitted.  
// This makes sure that all of our VAR memory is updated and active so that
// things will be kosher when we start drawing.
//

void OGL_UpdateVertexArrayRange(void)
{
long	size;
Byte	i;

	for (i = 0; i < NUM_VERTEX_ARRAY_RANGES; i++)
	{
				/* SEE IF THIS VAR IS USED */

		size = gVertexArrayRangeData[i].rangeSize;
		if (size == 0)		
			continue;
			

				/* SEE IF VAR NEEDS UPDATING */
					
		if (!gVertexArrayRangeData[i].forceUpdate)
			continue;


			/* BIND THIS VAR OBJECT SO WE CAN DO STUFF TO IT */

		glBindVertexArrayAPPLE(gVertexArrayRangeObjects[i]);				

				/* SEE IF THIS IS THE FIRST TIME IN */
								
		if (!gVertexArrayRangeData[i].activated)
		{
			glVertexArrayRangeAPPLE(size, gVertexArrayRangeData[i].dataBlockPtr);
			glVertexArrayParameteriAPPLE(GL_VERTEX_ARRAY_STORAGE_HINT_APPLE,GL_STORAGE_SHARED_APPLE);

					// you MUST call this flush to get the data primed!

			glFlushVertexArrayRangeAPPLE(size, gVertexArrayRangeData[i].dataBlockPtr);		
			glEnableClientState(GL_VERTEX_ARRAY_RANGE_APPLE);
			gVertexArrayRangeData[i].activated = true;
		}
		
				/* ALREADY ACTIVE, SO JUST UPDATING */
				
		else
		{
			glFlushVertexArrayRangeAPPLE(size, gVertexArrayRangeData[i].dataBlockPtr);
		}

		gVertexArrayRangeData[i].forceUpdate = false;		
	}		
}







