/*
 * Copyright 1993-2010 NVIDIA Corporation.  All rights reserved.
 *
 * NVIDIA Corporation and its licensors retain all intellectual property and 
 * proprietary rights in and to this software and related documentation. 
 * Any use, reproduction, disclosure, or distribution of this software 
 * and related documentation without an express license agreement from
 * NVIDIA Corporation is strictly prohibited.
 *
 * Please refer to the applicable NVIDIA end user license agreement (EULA) 
 * associated with this source code for terms and conditions that govern 
 * your use of this NVIDIA software.
 * 
 */

/*	
	Class to encapsulate the data used to stress the CopyEngine - 
	Can be 2d image series (video) or 3d volume time-series
*/


#ifndef _DATA_H_
#define _DATA_H_

#include <vector>
#include <GL/glew.h>
#include "nvThread.h"
using namespace std;

const unsigned int numDownloadBuffers = 4; //must be less than number of time steps
enum TransferMode
{
    TRANSFER_NONE,
    TRANSFER_SYNC,
	TRANSFER_CPUASYNC,
	TRANSFER_GPUASYNC,
    TRANSFER_NUM_MODES
};


class Data {
public:
	Data(const char* filename, int width, int height, int depth, int nTimesteps,  TransferMode downloadMode); //generate data from noise function if filename is NULL
	~Data();
	//step to next frame,delta time can be fraction so that we can interpolate (we dont do that here)
	void step(float deltaTime = 1.0);
	//All the stuff that needs to be done before render goes here
	//eg if using CE wait to get texture handle from download thread otherwise just download
	void startRender(); 
	void render(); //the real rendering
	void endRender(); //signal we are done with the cur texture, inc the texture, 

	//inline accessor/set functions
    unsigned int getWidth() { return m_width; }
    unsigned int getHeight() { return m_height; }
    unsigned int getDepth() { return m_depth; }
	unsigned int getNumTimesteps() { return m_pData.size();}
	//this is the current texture to be rendered maybe different from the one that is actually downloaded in the case of using CE
	GLuint getCurrentTexture() { return m_Tex[m_curRender]; }
	GLenum getTarget() {return m_target;}
	
protected:
	void _init(const char* filename, int timesteps); //setup everything
    void _downloadToTexture(); //download to texture on graphics device

	unsigned int m_width, m_height, m_depth, m_curTimeStep;
	GLuint   m_Tex[numDownloadBuffers]; //3d tex id of the data, we have a pool of textures so that download and render can work on their own set
	unsigned int m_curDownload, m_curRender; //from the texture set above which one are we currently downloading data to and which texture is used for rendering
	GLenum	m_target; //whether 2d or 3d texture
	vector<unsigned char*> m_pData; //time-series array of data (images or volumes)
	GLuint	m_pbo;  // pbo for the texture, one pbo seems to work fine
	TransferMode m_downloadMode; //what method is used for download
	GLsync downloadFence[numDownloadBuffers]; //for each of the textures we have , need a fence to sync between render and download thread, only for CE case
	nvEvent evStartDownload[numDownloadBuffers]; //events to signal that the texture was consumed by render therefore downloader can use it
	nvEvent evDownloadFenceCreated[numDownloadBuffers] ;//event to signal that download has created a gl fence which will be set once the tex was really downloaded
};


#endif


