/*
	ZOpenGLDimensionTexture.hpp
	Author: James Russell <jcrussell@762studios.com>
	Created: 7/1/2012

	Purpose: 

	OpenGL implementation of a 'dimensional' (1D, 2D, 3D) texture.

	License:

	TODO

*/

#pragma once

#ifndef _ZOPENGLDIMENSIONTEXTURE_HPP
#define _ZOPENGLDIMENSIONTEXTURE_HPP

#include <SST/SST_GLAPI.h>

#include <ZRenderer/ZDimensionTextureBase.hpp>

//Forward Declarations
class ZOpenGLRenderer;

//OpenGL implementation of the two dimensional texture interface
class ZOpenGLDimensionTexture : public ZDimensionTextureBase
{
private:
	DISABLE_COPY_AND_ASSIGN(ZOpenGLDimensionTexture);

protected:
	//Gets the texture data from the graphics device as part of a thread request
	static void GetDeviceData_( ZThread *_renderThread, void *_dataBuffer );

	//Subclass Implementation
	virtual void GetDeviceData(void* _buffer);

public:
	//Renderer associated with this texture
	ZOpenGLRenderer *Renderer;

	//The OpenGL handle to the loaded texture
	GLuint GLHandle;

	//Gets the OpenGL 'target' parameter for this texture type
	GLenum GetGLTarget()
	{
		switch(Type)
		{
		case ZTT_TEXTURE1D:			return GL_TEXTURE_1D;
		case ZTT_TEXTURE2D:			return GL_TEXTURE_2D;
		case ZTT_TEXTURE3D:			return GL_TEXTURE_3D;
		case ZTT_TEXTURE_CUBE:		/* Invalid Here */
		default:					return GL_INVALID_ENUM;
		}
	}

	//Gets the OpenGL 'internalFormat' parameter for this texture format (used for glTexImage*D)
	GLenum GetGLInternalFormat()
	{
		switch (Format)
		{
		case ZTF_R8:				return GL_R8;
		case ZTF_R8_SNORM:			return GL_R8_SNORM;
		case ZTF_R8I:				return GL_R8I;
		case ZTF_R8UI:				return GL_R8UI;
		case ZTF_R16:				return GL_R16;
		case ZTF_R16_SNORM:			return GL_R16_SNORM;
		case ZTF_R16I:				return GL_R16I;
		case ZTF_R16UI:				return GL_R16UI;
		case ZTF_R16F:				return GL_R16F;
		case ZTF_R32I:				return GL_R32I;
		case ZTF_R32UI:				return GL_R32UI;
		case ZTF_R32F:				return GL_R32F;

		case ZTF_RG8:				return GL_RG8;
		case ZTF_RG8_SNORM:			return GL_RG8_SNORM;
		case ZTF_RG8I:				return GL_RG8I;
		case ZTF_RG8UI:				return GL_RG8UI;
		case ZTF_RG16:				return GL_RG16;
		case ZTF_RG16_SNORM:		return GL_RG16_SNORM;
		case ZTF_RG16I:				return GL_RG16I;
		case ZTF_RG16UI:			return GL_RG16UI;
		case ZTF_RG16F:				return GL_RG16F;
		case ZTF_RG32I:				return GL_RG32I;
		case ZTF_RG32UI:			return GL_RG32UI;
		case ZTF_RG32F:				return GL_RG32F;

		case ZTF_RGB8:				return GL_RGB8;
		case ZTF_RGB8_SNORM:		return GL_RGB8_SNORM;
		case ZTF_RGB8I:				return GL_RGB8I;
		case ZTF_RGB8UI:			return GL_RGB8UI;
		case ZTF_RGB16:				return GL_RGB16; 
		case ZTF_RGB16_SNORM:		return GL_RGB16_SNORM;
		case ZTF_RGB16I:			return GL_RGB16I;
		case ZTF_RGB16UI:			return GL_RGB16UI;
		case ZTF_RGB16F:			return GL_RGB16F;
		case ZTF_RGB32I:			return GL_RGB32I;
		case ZTF_RGB32UI:			return GL_RGB32UI;
		case ZTF_RGB32F:			return GL_RGB32F;

		case ZTF_RGBA8:				return GL_RGBA8;
		case ZTF_RGBA8_SNORM:		return GL_RGBA8_SNORM;
		case ZTF_RGBA8I:			return GL_RGBA8I;
		case ZTF_RGBA8UI:			return GL_RGBA8UI;
		case ZTF_RGBA16:			return GL_RGBA16;
		case ZTF_RGBA16_SNORM:		return GL_RGBA16_SNORM;
		case ZTF_RGBA16I:			return GL_RGBA16I;
		case ZTF_RGBA16UI:			return GL_RGBA16UI;
		case ZTF_RGBA16F:			return GL_RGBA16F;
		case ZTF_RGBA32I:			return GL_RGBA32I;
		case ZTF_RGBA32UI:			return GL_RGBA32UI;
		case ZTF_RGBA32F:			return GL_RGBA32F;

		case ZTF_DEPTH16:			return GL_DEPTH_COMPONENT16;
		case ZTF_DEPTH24:			return GL_DEPTH_COMPONENT24;
		case ZTF_DEPTH32:			return GL_DEPTH_COMPONENT32;
		case ZTF_DEPTH24_STENCIL8:	return GL_DEPTH24_STENCIL8;

		default:					return GL_INVALID_ENUM;
		}
	}

	//Gets the OpenGL 'format' parameter for this texture's bitmap format (used for glTexImage*D)
	GLenum GetGLFormat()
	{
		switch (Bitmap.GetFormat())
		{
		case ZBF_R8:
		case ZBF_R8I:
		case ZBF_R16:
		case ZBF_R16I:
		case ZBF_R32:
		case ZBF_R32I:
		case ZBF_R32F:		return GL_RED;

		case ZBF_RG8:		
		case ZBF_RG8I:		
		case ZBF_RG16:
		case ZBF_RG16I:
		case ZBF_RG32:		
		case ZBF_RG32I:
		case ZBF_RG32F:		return GL_RG;

		case ZBF_RGB8:		
		case ZBF_RGB8I:		
		case ZBF_RGB16:	
		case ZBF_RGB16I:	
		case ZBF_RGB32:		
		case ZBF_RGB32I:
		case ZBF_RGB32F:	return GL_RGB;

		case ZBF_RGBA8:	
		case ZBF_RGBA8I:
		case ZBF_RGBA16:
		case ZBF_RGBA16I:
		case ZBF_RGBA32:
		case ZBF_RGBA32I:
		case ZBF_RGBA32F:	return GL_RGBA;

		case ZBF_BGR8:		
		case ZBF_BGR8I:		
		case ZBF_BGR16:	
		case ZBF_BGR16I:	
		case ZBF_BGR32:		
		case ZBF_BGR32I:	
		case ZBF_BGR32F:	return GL_BGR;

		case ZBF_BGRA8:	
		case ZBF_BGRA8I:	
		case ZBF_BGRA16:	
		case ZBF_BGRA16I:	
		case ZBF_BGRA32:	
		case ZBF_BGRA32I:	
		case ZBF_BGRA32F:	return GL_BGRA;

		case ZBF_DEPTH32:	return GL_DEPTH_COMPONENT;

		default:			return GL_INVALID_ENUM;	
		}
	}

	//Gets the OpenGL 'type' parameter for this texture's bitmap format (used for glTexImage*D calls)
	GLenum GetGLType()
	{
		switch (Bitmap.GetFormat())
		{
		case ZBF_R8:
		case ZBF_RG8:			
		case ZBF_RGB8:		
		case ZBF_RGBA8:	
		case ZBF_BGR8:				
		case ZBF_BGRA8:		return GL_UNSIGNED_BYTE;

		case ZBF_R8I:
		case ZBF_RG8I:
		case ZBF_RGB8I:	
		case ZBF_RGBA8I:
		case ZBF_BGR8I:	
		case ZBF_BGRA8I:	return GL_BYTE;

		case ZBF_R16:
		case ZBF_RG16:
		case ZBF_RGB16:	
		case ZBF_RGBA16:
		case ZBF_BGR16:	
		case ZBF_BGRA16:	return GL_UNSIGNED_SHORT;

		case ZBF_R16I:
		case ZBF_RG16I:
		case ZBF_RGB16I:	
		case ZBF_RGBA16I:
		case ZBF_BGR16I:	
		case ZBF_BGRA16I:	return GL_SHORT;

		case ZBF_R32:
		case ZBF_RG32:		
		case ZBF_RGB32:		
		case ZBF_RGBA32:
		case ZBF_BGR32:	
		case ZBF_BGRA32:	return GL_UNSIGNED_INT;

		case ZBF_R32I:
		case ZBF_RG32I:
		case ZBF_RGB32I:
		case ZBF_RGBA32I:
		case ZBF_BGR32I:	
		case ZBF_BGRA32I:	return GL_INT;

		case ZBF_R32F:		
		case ZBF_RG32F:		
		case ZBF_RGB32F:	
		case ZBF_RGBA32F:	
		case ZBF_BGR32F:	
		case ZBF_BGRA32F:	return GL_FLOAT;

		case ZBF_DEPTH32:	return GL_UNSIGNED_INT;

		default:			return GL_INVALID_ENUM;	
		}
	}

	/*
	Constructor.

	@param _renderer - the current renderer instance
	@param _type - the type of texture
	@param _format - the format of the texture
	@param _usage - the usage type of texture
	@param _bitmap - the bitmap for this texture (or side, in case of cube map)
	@param _generateMipmaps - flag indicating we should generate mipmaps
	*/
	ZOpenGLDimensionTexture(ZOpenGLRenderer* _renderer, ZTextureType _type, ZTextureFormat _format, ZTextureUsage _usage, const ZBitmap& _bitmap, bool _generateMipmaps);

	//Virtual destructor
	virtual ~ZOpenGLDimensionTexture();
};

#endif 
