/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES Utilities
 * ------------------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Texture classes.
 *//*--------------------------------------------------------------------*/

#include "gluTexture.hpp"
#include "gluTextureUtil.hpp"
#include "deFilePath.hpp"
#include "tcuImageIO.hpp"
#include "tcuSurface.hpp"
#include "tcuTextureUtil.hpp"

#include "glwFunctions.hpp"
#include "glwEnums.hpp"

#include "deUniquePtr.hpp"

using std::vector;

namespace glu
{

static inline int computePixelStore (const tcu::TextureFormat& format)
{
	int pixelSize = format.getPixelSize();
	if (deIsPowerOfTwo32(pixelSize))
		return de::min(pixelSize, 8);
	else
		return 1;
}

// Texture1D

Texture1D::Texture1D (const RenderContext& context, deUint32 format, deUint32 dataType, int width)
	: m_context			(context)
	, m_format			(format)
	, m_refTexture		(mapGLTransferFormat(format, dataType), width)
	, m_glTexture		(0)
{
	const glw::Functions& gl = context.getFunctions();
	gl.genTextures(1, &m_glTexture);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
}

Texture1D::Texture1D (const RenderContext& context, deUint32 sizedFormat, int width)
	: m_context			(context)
	, m_format			(sizedFormat)
	, m_refTexture		(mapGLInternalFormat(sizedFormat), width)
	, m_glTexture		(0)
{
	const glw::Functions& gl = context.getFunctions();
	gl.genTextures(1, &m_glTexture);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
}

Texture1D::~Texture1D (void)
{
	if (m_glTexture)
		m_context.getFunctions().deleteTextures(1, &m_glTexture);
}

void Texture1D::upload (void)
{
	const glw::Functions& gl = m_context.getFunctions();

	TCU_CHECK(m_glTexture);
	gl.bindTexture(GL_TEXTURE_1D, m_glTexture);
	gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");

	TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());

	for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
	{
		if (m_refTexture.isLevelEmpty(levelNdx))
			continue; // Don't upload.

		tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx);
		gl.texImage1D(GL_TEXTURE_1D, levelNdx, m_format, access.getWidth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
	}

	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
}

// Texture2D

Texture2D::Texture2D (const RenderContext& context, deUint32 format, deUint32 dataType, int width, int height)
	: m_context			(context)
	, m_isCompressed	(false)
	, m_format			(format)
	, m_refTexture		(mapGLTransferFormat(format, dataType), width, height)
	, m_glTexture		(0)
{
	const glw::Functions& gl = context.getFunctions();
	gl.genTextures(1, &m_glTexture);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
}

Texture2D::Texture2D (const RenderContext& context, deUint32 sizedFormat, int width, int height)
	: m_context			(context)
	, m_isCompressed	(false)
	, m_format			(sizedFormat)
	, m_refTexture		(mapGLInternalFormat(sizedFormat), width, height)
	, m_glTexture		(0)
{
	const glw::Functions& gl = context.getFunctions();
	gl.genTextures(1, &m_glTexture);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
}

Texture2D::Texture2D (const RenderContext& context, const ContextInfo& contextInfo, int numLevels, const tcu::CompressedTexture* levels, const tcu::TexDecompressionParams& decompressionParams)
	: m_context			(context)
	, m_isCompressed	(true)
	, m_format			(getGLFormat(levels[0].getFormat()))
	, m_refTexture		(getUncompressedFormat(levels[0].getFormat()), levels[0].getWidth(), levels[0].getHeight())
	, m_glTexture		(0)
{
	const glw::Functions& gl = context.getFunctions();

	if (!contextInfo.isCompressedTextureFormatSupported(m_format))
		TCU_THROW(NotSupportedError, "Compressed texture format not supported");

	gl.genTextures(1, &m_glTexture);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");

	try
	{
		loadCompressed(numLevels, levels, decompressionParams);
	}
	catch (const std::exception&)
	{
		gl.deleteTextures(1, &m_glTexture);
		throw;
	}
}

Texture2D::~Texture2D (void)
{
	if (m_glTexture)
		m_context.getFunctions().deleteTextures(1, &m_glTexture);
}

void Texture2D::upload (void)
{
	const glw::Functions& gl = m_context.getFunctions();

	DE_ASSERT(!m_isCompressed);

	TCU_CHECK(m_glTexture);
	gl.bindTexture(GL_TEXTURE_2D, m_glTexture);
	gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");

	TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());

	for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
	{
		if (m_refTexture.isLevelEmpty(levelNdx))
			continue; // Don't upload.

		tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx);
		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth());
		gl.texImage2D(GL_TEXTURE_2D, levelNdx, m_format, access.getWidth(), access.getHeight(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
	}

	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
}

void Texture2D::loadCompressed (int numLevels, const tcu::CompressedTexture* levels, const tcu::TexDecompressionParams& decompressionParams)
{
	const glw::Functions&	gl					= m_context.getFunctions();
	deUint32				compressedFormat	= getGLFormat(levels[0].getFormat());

	TCU_CHECK(m_glTexture);
	gl.bindTexture(GL_TEXTURE_2D, m_glTexture);

	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
	{
		const tcu::CompressedTexture& level = levels[levelNdx];

		// Decompress to reference texture.
		m_refTexture.allocLevel(levelNdx);
		tcu::PixelBufferAccess refLevelAccess = m_refTexture.getLevel(levelNdx);
		TCU_CHECK(level.getWidth()	== refLevelAccess.getWidth() &&
				  level.getHeight()	== refLevelAccess.getHeight());
		level.decompress(refLevelAccess, decompressionParams);

		// Upload to GL texture in compressed form.
		gl.compressedTexImage2D(GL_TEXTURE_2D, levelNdx, compressedFormat,
								level.getWidth(), level.getHeight(), 0 /* border */, level.getDataSize(), level.getData());
	}

	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
}

Texture2D* Texture2D::create (const RenderContext& context, const ContextInfo& contextInfo, const tcu::Archive& archive, int numLevels, const char* const* levelFileNames)
{
	DE_ASSERT(numLevels > 0);

	std::string ext = de::FilePath(levelFileNames[0]).getFileExtension();

	if (ext == "png")
	{
		// Uncompressed texture.

		tcu::TextureLevel level;

		// Load level 0.
		tcu::ImageIO::loadPNG(level, archive, levelFileNames[0]);

		TCU_CHECK_INTERNAL(level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8) ||
						   level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8));

		bool		isRGBA		= level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
		Texture2D*	texture		= new Texture2D(context, isRGBA ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, level.getWidth(), level.getHeight());

		try
		{
			// Fill level 0.
			texture->getRefTexture().allocLevel(0);
			tcu::copy(texture->getRefTexture().getLevel(0), level.getAccess());

			// Fill remaining levels.
			for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
			{
				tcu::ImageIO::loadPNG(level, archive, levelFileNames[levelNdx]);

				texture->getRefTexture().allocLevel(levelNdx);
				tcu::copy(texture->getRefTexture().getLevel(levelNdx), level.getAccess());
			}

			// Upload data.
			texture->upload();
		}
		catch (const std::exception&)
		{
			delete texture;
			throw;
		}

		return texture;
	}
	else if (ext == "pkm")
	{
		// Compressed texture.
		vector<tcu::CompressedTexture> levels(numLevels);

		for (int ndx = 0; ndx < numLevels; ndx++)
			tcu::ImageIO::loadPKM(levels[ndx], archive, levelFileNames[ndx]);

		return new Texture2D(context, contextInfo, numLevels, &levels[0]);
	}
	else
		TCU_FAIL("Unsupported file format");
}

Texture2D* Texture2D::create (const RenderContext& context, const ContextInfo& contextInfo, const tcu::Archive& archive, int numLevels, const std::vector<std::string>& filenames)
{
	TCU_CHECK(numLevels == (int)filenames.size());

	std::vector<const char*> charPtrs(filenames.size());
	for (int ndx = 0; ndx < (int)filenames.size(); ndx++)
		charPtrs[ndx] = filenames[ndx].c_str();

	return Texture2D::create(context, contextInfo, archive, numLevels, &charPtrs[0]);
}

// ImmutableTexture2D

ImmutableTexture2D::ImmutableTexture2D (const RenderContext& context, deUint32 sizedFormat, int width, int height)
	: Texture2D(context, sizedFormat, width, height)
{
}

void ImmutableTexture2D::upload (void)
{
	const glw::Functions& gl = m_context.getFunctions();

	DE_ASSERT(!m_isCompressed);

	TCU_CHECK(m_glTexture);
	gl.bindTexture(GL_TEXTURE_2D, m_glTexture);
	gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");

	TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());

	gl.texStorage2D(GL_TEXTURE_2D, m_refTexture.getNumLevels(), m_format, m_refTexture.getWidth(), m_refTexture.getHeight());
	for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
	{
		if (m_refTexture.isLevelEmpty(levelNdx))
			continue; // Don't upload.

		tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx);
		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth());
		gl.texSubImage2D(GL_TEXTURE_2D, levelNdx, 0, 0, access.getWidth(), access.getHeight(),  transferFormat.format, transferFormat.dataType, access.getDataPtr());
	}

	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
}

// TextureCube

TextureCube::TextureCube (const RenderContext& context, const ContextInfo& contextInfo, int numLevels, const tcu::CompressedTexture* levels, const tcu::TexDecompressionParams& decompressionParams)
	: m_context			(context)
	, m_isCompressed	(true)
	, m_format			(getGLFormat(levels[0].getFormat()))
	, m_refTexture		(getUncompressedFormat(levels[0].getFormat()), levels[0].getWidth())
	, m_glTexture		(0)
{
	const glw::Functions& gl = m_context.getFunctions();

	TCU_CHECK_INTERNAL(levels[0].getWidth() == levels[0].getHeight());

	if (!contextInfo.isCompressedTextureFormatSupported(m_format))
		throw tcu::NotSupportedError("Compressed texture format not supported", "", __FILE__, __LINE__);

	gl.genTextures(1, &m_glTexture);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");

	try
	{
		loadCompressed(numLevels, levels, decompressionParams);
	}
	catch (const std::exception&)
	{
		gl.deleteTextures(1, &m_glTexture);
		throw;
	}
}

TextureCube::TextureCube (const RenderContext& context, deUint32 format, deUint32 dataType, int size)
	: m_context			(context)
	, m_isCompressed	(false)
	, m_format			(format)
	, m_refTexture		(mapGLTransferFormat(format, dataType), size)
	, m_glTexture		(0)
{
	const glw::Functions& gl = m_context.getFunctions();
	gl.genTextures(1, &m_glTexture);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
}

TextureCube::TextureCube (const RenderContext& context, deUint32 internalFormat, int size)
	: m_context			(context)
	, m_isCompressed	(false)
	, m_format			(internalFormat)
	, m_refTexture		(mapGLInternalFormat(internalFormat), size)
	, m_glTexture		(0)
{
	const glw::Functions& gl = m_context.getFunctions();
	gl.genTextures(1, &m_glTexture);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
}

TextureCube::~TextureCube (void)
{
	if (m_glTexture)
		m_context.getFunctions().deleteTextures(1, &m_glTexture);
}

void TextureCube::upload (void)
{
	const glw::Functions& gl = m_context.getFunctions();

	DE_ASSERT(!m_isCompressed);

	TCU_CHECK(m_glTexture);
	gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_glTexture);
	gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");

	TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());

	for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
	{
		for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
		{
			if (m_refTexture.isLevelEmpty((tcu::CubeFace)face, levelNdx))
				continue; // Don't upload.

			tcu::ConstPixelBufferAccess access = m_refTexture.getLevelFace(levelNdx, (tcu::CubeFace)face);
			DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth());
			gl.texImage2D(getGLCubeFace((tcu::CubeFace)face), levelNdx, m_format, access.getWidth(), access.getHeight(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
		}
	}

	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
}

void TextureCube::loadCompressed (int numLevels, const tcu::CompressedTexture* levels, const tcu::TexDecompressionParams& decompressionParams)
{
	const glw::Functions&	gl					= m_context.getFunctions();
	deUint32				compressedFormat	= getGLFormat(levels[0].getFormat());

	TCU_CHECK(m_glTexture);
	gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_glTexture);

	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
	{
		for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
		{
			const tcu::CompressedTexture& level = levels[levelNdx*tcu::CUBEFACE_LAST + face];

			// Decompress to reference texture.
			m_refTexture.allocLevel((tcu::CubeFace)face, levelNdx);
			tcu::PixelBufferAccess refLevelAccess = m_refTexture.getLevelFace(levelNdx, (tcu::CubeFace)face);
			TCU_CHECK(level.getWidth()	== refLevelAccess.getWidth() &&
					  level.getHeight()	== refLevelAccess.getHeight());
			level.decompress(refLevelAccess, decompressionParams);

			// Upload to GL texture in compressed form.
			gl.compressedTexImage2D(getGLCubeFace((tcu::CubeFace)face), levelNdx, compressedFormat,
									level.getWidth(), level.getHeight(), 0 /* border */, level.getDataSize(), level.getData());
		}
	}

	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
}

TextureCube* TextureCube::create (const RenderContext& context, const ContextInfo& contextInfo, const tcu::Archive& archive, int numLevels, const char* const* filenames)
{
	DE_ASSERT(numLevels > 0);

	std::string ext = de::FilePath(filenames[0]).getFileExtension();

	// \todo [2011-11-21 pyry] Support PNG images.
	if (ext == "pkm")
	{
		// Compressed texture.
		int								numImages	= numLevels*tcu::CUBEFACE_LAST;
		vector<tcu::CompressedTexture>	levels		(numImages);

		for (int ndx = 0; ndx < numImages; ndx++)
			tcu::ImageIO::loadPKM(levels[ndx], archive, filenames[ndx]);

		return new TextureCube(context, contextInfo, numLevels, &levels[0]);
	}
	else
		TCU_FAIL("Unsupported file format");
}

TextureCube* TextureCube::create (const RenderContext& context, const ContextInfo& contextInfo, const tcu::Archive& archive, int numLevels, const std::vector<std::string>& filenames)
{
	DE_STATIC_ASSERT(tcu::CUBEFACE_LAST == 6);
	TCU_CHECK(numLevels*tcu::CUBEFACE_LAST == (int)filenames.size());

	std::vector<const char*> charPtrs(filenames.size());
	for (int ndx = 0; ndx < (int)filenames.size(); ndx++)
		charPtrs[ndx] = filenames[ndx].c_str();

	return TextureCube::create(context, contextInfo, archive, numLevels, &charPtrs[0]);
}

// Texture1DArray

Texture1DArray::Texture1DArray (const RenderContext& context, deUint32 format, deUint32 dataType, int width, int numLevels)
	: m_context			(context)
	, m_format			(format)
	, m_refTexture		(mapGLTransferFormat(format, dataType), width, numLevels)
	, m_glTexture		(0)
{
	const glw::Functions& gl = m_context.getFunctions();
	gl.genTextures(1, &m_glTexture);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
}

Texture1DArray::Texture1DArray (const RenderContext& context, deUint32 sizedFormat, int width, int numLevels)
	: m_context			(context)
	, m_format			(sizedFormat)
	, m_refTexture		(mapGLInternalFormat(sizedFormat), width, numLevels)
	, m_glTexture		(0)
{
	const glw::Functions& gl = m_context.getFunctions();
	gl.genTextures(1, &m_glTexture);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
}

Texture1DArray::~Texture1DArray (void)
{
	if (m_glTexture)
		m_context.getFunctions().deleteTextures(1, &m_glTexture);
}

void Texture1DArray::upload (void)
{
	const glw::Functions& gl = m_context.getFunctions();

	TCU_CHECK(m_glTexture);
	gl.bindTexture(GL_TEXTURE_1D_ARRAY, m_glTexture);
	gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");

	TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());

	for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
	{
		if (m_refTexture.isLevelEmpty(levelNdx))
			continue; // Don't upload.

		tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx);
		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth());
		gl.texImage2D(GL_TEXTURE_1D_ARRAY, levelNdx, m_format, access.getWidth(), access.getHeight(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
	}

	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
}

// Texture2DArray

Texture2DArray::Texture2DArray (const RenderContext& context, deUint32 format, deUint32 dataType, int width, int height, int numLevels)
	: m_context			(context)
	, m_isCompressed	(false)
	, m_format			(format)
	, m_refTexture		(mapGLTransferFormat(format, dataType), width, height, numLevels)
	, m_glTexture		(0)
{
	// \todo [2013-04-08 pyry] Check support here.
	const glw::Functions& gl = m_context.getFunctions();
	gl.genTextures(1, &m_glTexture);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
}

Texture2DArray::Texture2DArray (const RenderContext& context, deUint32 sizedFormat, int width, int height, int numLevels)
	: m_context			(context)
	, m_isCompressed	(false)
	, m_format			(sizedFormat)
	, m_refTexture		(mapGLInternalFormat(sizedFormat), width, height, numLevels)
	, m_glTexture		(0)
{
	// \todo [2013-04-08 pyry] Check support here.
	const glw::Functions& gl = m_context.getFunctions();
	gl.genTextures(1, &m_glTexture);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
}

Texture2DArray::Texture2DArray (const RenderContext& context, const ContextInfo& contextInfo, int numLevels, const tcu::CompressedTexture* levels, const tcu::TexDecompressionParams& decompressionParams)
	: m_context			(context)
	, m_isCompressed	(true)
	, m_format			(getGLFormat(levels[0].getFormat()))
	, m_refTexture		(getUncompressedFormat(levels[0].getFormat()), levels[0].getWidth(), levels[0].getHeight(), levels[0].getDepth())
	, m_glTexture		(0)
{
	const glw::Functions& gl = context.getFunctions();

	if (!contextInfo.isCompressedTextureFormatSupported(m_format))
		throw tcu::NotSupportedError("Compressed texture format not supported", "", __FILE__, __LINE__);

	gl.genTextures(1, &m_glTexture);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");

	try
	{
		loadCompressed(numLevels, levels, decompressionParams);
	}
	catch (const std::exception&)
	{
		gl.deleteTextures(1, &m_glTexture);
		throw;
	}
}

Texture2DArray::~Texture2DArray (void)
{
	if (m_glTexture)
		m_context.getFunctions().deleteTextures(1, &m_glTexture);
}

void Texture2DArray::upload (void)
{
	const glw::Functions& gl = m_context.getFunctions();

	if (!gl.texImage3D)
		throw tcu::NotSupportedError("glTexImage3D() is not supported");

	TCU_CHECK(m_glTexture);
	gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_glTexture);
	gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");

	TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());

	for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
	{
		if (m_refTexture.isLevelEmpty(levelNdx))
			continue; // Don't upload.

		tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx);
		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth());
		DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize()*access.getWidth()*access.getHeight());
		gl.texImage3D(GL_TEXTURE_2D_ARRAY, levelNdx, m_format, access.getWidth(), access.getHeight(), access.getDepth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
	}

	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
}

void Texture2DArray::loadCompressed (int numLevels, const tcu::CompressedTexture* levels, const tcu::TexDecompressionParams& decompressionParams)
{
	const glw::Functions&	gl					= m_context.getFunctions();
	deUint32				compressedFormat	= getGLFormat(levels[0].getFormat());

	TCU_CHECK(m_glTexture);
	gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_glTexture);

	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
	{
		const tcu::CompressedTexture& level = levels[levelNdx];

		// Decompress to reference texture.
		m_refTexture.allocLevel(levelNdx);
		tcu::PixelBufferAccess refLevelAccess = m_refTexture.getLevel(levelNdx);
		TCU_CHECK(level.getWidth()	== refLevelAccess.getWidth() &&
				  level.getHeight()	== refLevelAccess.getHeight() &&
				  level.getDepth()	== refLevelAccess.getDepth());
		level.decompress(refLevelAccess, decompressionParams);

		// Upload to GL texture in compressed form.
		gl.compressedTexImage3D(GL_TEXTURE_2D_ARRAY, levelNdx, compressedFormat,
								level.getWidth(), level.getHeight(), m_refTexture.getLevel(levelNdx).getDepth(), 0 /* border */, level.getDataSize(), level.getData());
	}

	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
}

// Texture3D

Texture3D::Texture3D (const RenderContext& context, deUint32 format, deUint32 dataType, int width, int height, int depth)
	: m_context			(context)
	, m_isCompressed	(false)
	, m_format			(format)
	, m_refTexture		(mapGLTransferFormat(format, dataType), width, height, depth)
	, m_glTexture		(0)
{
	// \todo [2013-04-08 pyry] Check support here.
	const glw::Functions& gl = m_context.getFunctions();
	gl.genTextures(1, &m_glTexture);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
}

Texture3D::Texture3D (const RenderContext& context, deUint32 sizedFormat, int width, int height, int depth)
	: m_context			(context)
	, m_isCompressed	(false)
	, m_format			(sizedFormat)
	, m_refTexture		(mapGLInternalFormat(sizedFormat), width, height, depth)
	, m_glTexture		(0)
{
	// \todo [2013-04-08 pyry] Check support here.
	const glw::Functions& gl = m_context.getFunctions();
	gl.genTextures(1, &m_glTexture);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
}

Texture3D::Texture3D (const RenderContext&					context,
					  const ContextInfo&					contextInfo,
					  int									numLevels,
					  const tcu::CompressedTexture*			levels,
					  const tcu::TexDecompressionParams&	decompressionParams)
	: m_context			(context)
	, m_isCompressed	(true)
	, m_format			(getGLFormat(levels[0].getFormat()))
	, m_refTexture		(getUncompressedFormat(levels[0].getFormat()), levels[0].getWidth(), levels[0].getHeight(), levels[0].getDepth())
	, m_glTexture		(0)
{
	const glw::Functions& gl = context.getFunctions();

	if (!contextInfo.isCompressedTextureFormatSupported(m_format))
		throw tcu::NotSupportedError("Compressed texture format not supported", "", __FILE__, __LINE__);

	gl.genTextures(1, &m_glTexture);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");

	try
	{
		loadCompressed(numLevels, levels, decompressionParams);
	}
	catch (const std::exception&)
	{
		gl.deleteTextures(1, &m_glTexture);
		throw;
	}
}

Texture3D::~Texture3D (void)
{
	if (m_glTexture)
		m_context.getFunctions().deleteTextures(1, &m_glTexture);
}

void Texture3D::upload (void)
{
	const glw::Functions& gl = m_context.getFunctions();

	DE_ASSERT(!m_isCompressed);

	if (!gl.texImage3D)
		throw tcu::NotSupportedError("glTexImage3D() is not supported");

	TCU_CHECK(m_glTexture);
	gl.bindTexture(GL_TEXTURE_3D, m_glTexture);
	gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");

	TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());

	for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
	{
		if (m_refTexture.isLevelEmpty(levelNdx))
			continue; // Don't upload.

		tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx);
		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth());
		DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize()*access.getWidth()*access.getHeight());
		gl.texImage3D(GL_TEXTURE_3D, levelNdx, m_format, access.getWidth(), access.getHeight(), access.getDepth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
	}

	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
}

void Texture3D::loadCompressed (int numLevels, const tcu::CompressedTexture* levels, const tcu::TexDecompressionParams& decompressionParams)
{
	const glw::Functions&	gl					= m_context.getFunctions();
	deUint32				compressedFormat	= getGLFormat(levels[0].getFormat());

	if (!gl.compressedTexImage3D)
		throw tcu::NotSupportedError("glCompressedTexImage3D() is not supported");

	TCU_CHECK(m_glTexture);
	gl.bindTexture(GL_TEXTURE_3D, m_glTexture);

	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
	{
		const tcu::CompressedTexture& level = levels[levelNdx];

		// Decompress to reference texture.
		m_refTexture.allocLevel(levelNdx);
		tcu::PixelBufferAccess refLevelAccess = m_refTexture.getLevel(levelNdx);
		TCU_CHECK(level.getWidth()	== refLevelAccess.getWidth() &&
				  level.getHeight()	== refLevelAccess.getHeight() &&
				  level.getDepth()	== refLevelAccess.getDepth());
		level.decompress(refLevelAccess, decompressionParams);

		// Upload to GL texture in compressed form.
		gl.compressedTexImage3D(GL_TEXTURE_3D, levelNdx, compressedFormat,
								level.getWidth(), level.getHeight(), level.getDepth(), 0 /* border */, level.getDataSize(), level.getData());
	}

	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
}

// TextureCubeArray

TextureCubeArray::TextureCubeArray (const RenderContext& context, deUint32 format, deUint32 dataType, int size, int numLayers)
	: m_context			(context)
	, m_format			(format)
	, m_refTexture		(mapGLTransferFormat(format, dataType), size, numLayers)
	, m_glTexture		(0)
{
	// \todo [2013-04-08 pyry] Check support here.
	const glw::Functions& gl = m_context.getFunctions();
	gl.genTextures(1, &m_glTexture);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
}

TextureCubeArray::TextureCubeArray (const RenderContext& context, deUint32 sizedFormat, int size, int numLayers)
	: m_context			(context)
	, m_format			(sizedFormat)
	, m_refTexture		(mapGLInternalFormat(sizedFormat), size, numLayers)
	, m_glTexture		(0)
{
	// \todo [2013-04-08 pyry] Check support here.
	const glw::Functions& gl = m_context.getFunctions();
	gl.genTextures(1, &m_glTexture);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
}

TextureCubeArray::~TextureCubeArray (void)
{
	if (m_glTexture)
		m_context.getFunctions().deleteTextures(1, &m_glTexture);
}

void TextureCubeArray::upload (void)
{
	const glw::Functions& gl = m_context.getFunctions();

	if (!gl.texImage3D)
		throw tcu::NotSupportedError("glTexImage3D() is not supported");

	TCU_CHECK(m_glTexture);
	gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, m_glTexture);
	gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");

	TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());

	for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
	{
		if (m_refTexture.isLevelEmpty(levelNdx))
			continue; // Don't upload.

		tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx);
		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth());
		DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize()*access.getWidth()*access.getHeight());
		gl.texImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, levelNdx, m_format, access.getWidth(), access.getHeight(), access.getDepth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
	}

	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
}

// TextureBuffer

TextureBuffer::TextureBuffer (const RenderContext& context, deUint32 internalFormat, size_t bufferSize)
	: m_context			(context)
	, m_format			(0)
	, m_offset			(0)
	, m_size			(0)
	, m_glTexture		(0)
	, m_glBuffer		(0)
{
	init(internalFormat, bufferSize, 0, 0, DE_NULL);
}

TextureBuffer::TextureBuffer (const RenderContext& context, deUint32 internalFormat, size_t bufferSize, size_t offset, size_t size, const void* data)
	: m_context			(context)
	, m_format			(0)
	, m_offset			(0)
	, m_size			(0)
	, m_glTexture		(0)
	, m_glBuffer		(0)
{
	init(internalFormat, bufferSize, offset, size, data);
}

void TextureBuffer::init (deUint32 internalFormat, size_t bufferSize, size_t offset, size_t size, const void* data)
{
	const glw::Functions&		gl		= m_context.getFunctions();
	de::UniquePtr<ContextInfo>	info	(ContextInfo::create(m_context));

	if (offset != 0 || size != 0)
	{
		if (!(contextSupports(m_context.getType(), glu::ApiType(3, 3, glu::PROFILE_CORE)) && info->isExtensionSupported("GL_ARB_texture_buffer_range"))
			&& !(contextSupports(m_context.getType(), glu::ApiType(3, 1, glu::PROFILE_ES))
				&& info->isExtensionSupported("GL_EXT_texture_buffer")))
		{
			throw tcu::NotSupportedError("Ranged texture buffers not supported", "", __FILE__, __LINE__);
		}
	}
	else
	{
		if (!contextSupports(m_context.getType(), glu::ApiType(3, 3, glu::PROFILE_CORE))
			&& !(contextSupports(m_context.getType(), glu::ApiType(3, 1, glu::PROFILE_ES))
				&& info->isExtensionSupported("GL_EXT_texture_buffer")))
		{
			throw tcu::NotSupportedError("Texture buffers not supported", "", __FILE__, __LINE__);
		}
	}

	m_refBuffer.setStorage(bufferSize);
	if (data)
		deMemcpy(m_refBuffer.getPtr(), data, (int)bufferSize);

	m_format	= internalFormat;
	m_offset	= offset;
	m_size		= size;

	DE_ASSERT(size != 0 || offset == 0);

	{
		gl.genTextures(1, &m_glTexture);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");

		gl.genBuffers(1, &m_glBuffer);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed");

		gl.bindBuffer(GL_TEXTURE_BUFFER, m_glBuffer);
		gl.bufferData(GL_TEXTURE_BUFFER, (glw::GLsizei)m_refBuffer.size(), data, GL_STATIC_DRAW);
		gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create buffer");

		gl.bindTexture(GL_TEXTURE_BUFFER, m_glTexture);

		if (offset != 0 || size != 0)
			gl.texBufferRange(GL_TEXTURE_BUFFER, m_format, m_glBuffer, (glw::GLintptr)m_offset, (glw::GLsizeiptr)m_size);
		else
			gl.texBuffer(GL_TEXTURE_BUFFER, m_format, m_glBuffer);

		gl.bindTexture(GL_TEXTURE_BUFFER, 0);
		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to bind buffer to texture");
	}
}

TextureBuffer::~TextureBuffer (void)
{
	if (m_glTexture)
		m_context.getFunctions().deleteTextures(1, &m_glTexture);

	if (m_glBuffer)
		m_context.getFunctions().deleteBuffers(1, &m_glBuffer);
}


const tcu::PixelBufferAccess TextureBuffer::getFullRefTexture (void)
{
	const tcu::TextureFormat	format				= mapGLInternalFormat(m_format);
	const size_t				bufferLengthBytes	= (m_size != 0) ? (m_size) : (m_refBuffer.size());
	const int					bufferLengthPixels	= (int)bufferLengthBytes / format.getPixelSize();

	return tcu::PixelBufferAccess(format,
								  tcu::IVec3(bufferLengthPixels, 1, 1),
								  (deUint8*)m_refBuffer.getPtr() + m_offset);
}

const tcu::ConstPixelBufferAccess TextureBuffer::getFullRefTexture (void) const
{
	return const_cast<TextureBuffer*>(this)->getFullRefTexture();
}

void TextureBuffer::upload (void)
{
	const glw::Functions& gl = m_context.getFunctions();

	gl.bindBuffer(GL_TEXTURE_BUFFER, m_glBuffer);
	gl.bufferData(GL_TEXTURE_BUFFER, (glw::GLsizei)m_refBuffer.size(), m_refBuffer.getPtr(), GL_STATIC_DRAW);
	gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to upload buffer");
}

} // glu
