/*======================================================================================

	Program:		Range Imaging Toolkit (RITK)
	Module:			OpenCLRegularMemoryImportImageContainer.h
	Version:		
	Date:			

	Copyright (c) 2010-2011
	Pattern Recognition Lab, 
    University Erlangen-Nuremberg, Germany
    All rights reserved.

	This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
	See RITKCopyright.txt for more information.

	http://www5.informatik.uni-erlangen.de/research/software/ritk

========================================================================================*/

#ifndef OPENCLREGULARMEMORYIMPORTIMAGECONTAINER_H__
#define OPENCLREGULARMEMORYIMPORTIMAGECONTAINER_H__

#include "OpenCLImportImageContainer.h"



namespace ritk
{

/**	@ingroup	OpenCL
 *	@class		OpenCLRegularMemoryImportImageContainer
 *	@author		Martin Stumpf (Origin: Jakob Wasza)
 *	@brief		CUDA regular memory container
 *
 *	@details
 *	This class provides methods for regular CUDA memory management.
 */
template<typename TElementIdentifier, typename TElement>
class OpenCLRegularMemoryImportImageContainer : public OpenCLImportImageContainer<TElementIdentifier,TElement>
{
public:
	/**	@name	Std typedefs */
	//@{
	typedef OpenCLRegularMemoryImportImageContainer						Self;
	typedef OpenCLImportImageContainer<TElementIdentifier,TElement>		Superclass;
	typedef itk::SmartPointer<Self>										Pointer;
	typedef itk::SmartPointer<const Self>								ConstPointer;
	//@}

	/**	@name	Template parameters */
	//@{
	typedef TElementIdentifier  ElementIdentifier;
	typedef TElement            Element;
	//@}

	//@}

	/// Object creation
	itkNewMacro(Self);

	/// RTTI
	itkTypeMacro(OpenCLRegularMemoryImportImageContainer, OpenCLImportImageContainer);

	/**	@name	Host/device synchronization. Is delegated to the superclass */
	//@{
	virtual void SynchronizeDevice();
	virtual void SynchronizeHost();
	//@}

	/**	@brief	Deep copy the buffer
	 *	@param	Container	The GenericImportImageContainer providing the source
	 *
	 *	@details
	 *	Copy the data from a GenericImportImageContainer. This baseclass' implementation
	 *	will perform a host memory copy. Memory will be allocated automatically.
	 */
	virtual void DeepCopy(const GenericImportImageContainer *Container);

	/**	@name	Pointer to the wrapped OpenCL memory. Non-const version will modify the device MTime! */
	//@{
	cl_mem GetOpenCLMemoryPointer();
	const cl_mem GetOpenCLMemoryPointer() const;
	//@}



protected:
	/// Constructor
	OpenCLRegularMemoryImportImageContainer();
	/// Destructor
	virtual ~OpenCLRegularMemoryImportImageContainer();

	/// Print
	virtual void PrintSelf(std::ostream& os, itk::Indent indent) const;

	/// Allocate the buffer. Is delegated to the superclass.
	virtual Element* AllocateElements(ElementIdentifier size) const;

	/// Free the buffer. Is delegated to the superclass
	virtual void DeallocateManagedMemory();

	

protected:
	/// The actual OpenCL memory 
	mutable cl_mem m_OpenCLMemory;
	/// The List to the allocated OpenCLMemories; needed to prevent a bug in itk::ImportImageContainer, where DeallocateManagedMemory and AllocateElements is called in wrong order
	mutable std::list<cl_mem> m_OpenCLMemoryList;
	

private:
	/// purposely not implemented
	OpenCLRegularMemoryImportImageContainer(const Self&); 
	/// purposely not implemented
	void operator=(const Self&);
};

/** @name Template instantiations */
//@{
typedef OpenCLRegularMemoryImportImageContainer<unsigned long,float> OpenCLRegularMemoryImportImageContainerF;
typedef OpenCLRegularMemoryImportImageContainer<unsigned long,unsigned char> OpenCLRegularMemoryImportImageContainerUC;
typedef OpenCLRegularMemoryImportImageContainer<unsigned long,itk::Vector<float,3>> OpenCLRegularMemoryImportImageContainerF3;
//@}

} // ritk


#endif // OPENCLREGULARMEMORYIMPORTIMAGECONTAINER_H__