// Texture.cpp: implementation of the CTexture class.
//
//////////////////////////////////////////////////////////////////////

#include "Texture.h"

#include "OpenGL.h"

#include "..\Common\Image.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CTexture::CTexture()
{
	m_pszClassName = "CTexture";

	///////////////////////////////////////////////////////////////////////////
	m_nName = 0;
}

CTexture::~CTexture()
{
	Destroy();
}

void CTexture::Destroy()
{
	if (m_nName)
	{
		glDeleteTextures(1, &m_nName);
		m_nName = 0;
	}

	CUnknown::Destroy();
}

bool CTexture::Create(LPSTR lpszName)
{
	if (!CUnknown::Create(lpszName))
		return false;

	// Create the texture
	glGenTextures(1, &m_nName);
	glBindTexture(GL_TEXTURE_2D, m_nName);

	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

	// Set Texture Wrap Parameter (Repeat)
	//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

	// Set Filtering Parameter (Linear)
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

	return true;
}

void CTexture::Apply()
{
	glBindTexture(GL_TEXTURE_2D, m_nName);

	//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
	//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
	//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}

void CTexture::Upload(CImage* lpImage)
{
    GLenum formats[] =
    {
		GL_RGB,
        GL_RGBA,
		GL_COLOR_INDEX,
		GL_LUMINANCE,

		GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
		GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
		GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
    };

	int nComponents[] = 
	{
		3,
		4,
		1,
		1,

		0,
		0,
		0,
	};

	CImage::FORMAT format = lpImage->GetFormat();
	GLenum internalFormat = formats[format];

	int components = nComponents[format];

	// Upload Texture
	glBindTexture(GL_TEXTURE_2D, m_nName);

	switch (internalFormat)
	{
	case GL_COLOR_INDEX:
		glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT,
						GL_RGB,
						256,
						GL_RGB,
						GL_UNSIGNED_BYTE,
						lpImage->GetPalBuffer());

	case GL_RGB:
    case GL_RGBA:
	case GL_LUMINANCE:
		glTexImage2D(GL_TEXTURE_2D,
					 0,
					 components,
					 lpImage->GetWidth(), lpImage->GetHeight(),
					 0,
					 internalFormat,
					 GL_UNSIGNED_BYTE, 
					 lpImage->GetBuffer());
		break;

	case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
	case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
	case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
		glCompressedTexImage2DARB(GL_TEXTURE_2D,
								  0,
								  internalFormat,
								  lpImage->GetWidth(), lpImage->GetHeight(),
								  0,
								  lpImage->GetBufferLength(),
								  lpImage->GetBuffer());
		break;
	}
}