Home | History | Annotate | Download | only in opengl
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES Utilities
      3  * ------------------------------------------------
      4  *
      5  * Copyright 2014 The Android Open Source Project
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  *//*!
     20  * \file
     21  * \brief Texture classes.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "gluTexture.hpp"
     25 #include "gluTextureUtil.hpp"
     26 #include "deFilePath.hpp"
     27 #include "tcuImageIO.hpp"
     28 #include "tcuSurface.hpp"
     29 #include "tcuTextureUtil.hpp"
     30 
     31 #include "glwFunctions.hpp"
     32 #include "glwEnums.hpp"
     33 
     34 #include "deUniquePtr.hpp"
     35 
     36 using std::vector;
     37 
     38 namespace glu
     39 {
     40 
     41 static inline int computePixelStore (const tcu::TextureFormat& format)
     42 {
     43 	int pixelSize = format.getPixelSize();
     44 	if (deIsPowerOfTwo32(pixelSize))
     45 		return de::min(pixelSize, 8);
     46 	else
     47 		return 1;
     48 }
     49 
     50 // Texture1D
     51 
     52 Texture1D::Texture1D (const RenderContext& context, deUint32 format, deUint32 dataType, int width)
     53 	: m_context			(context)
     54 	, m_format			(format)
     55 	, m_refTexture		(mapGLTransferFormat(format, dataType), width)
     56 	, m_glTexture		(0)
     57 {
     58 	const glw::Functions& gl = context.getFunctions();
     59 	gl.genTextures(1, &m_glTexture);
     60 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
     61 }
     62 
     63 Texture1D::Texture1D (const RenderContext& context, deUint32 sizedFormat, int width)
     64 	: m_context			(context)
     65 	, m_format			(sizedFormat)
     66 	, m_refTexture		(mapGLInternalFormat(sizedFormat), width)
     67 	, m_glTexture		(0)
     68 {
     69 	const glw::Functions& gl = context.getFunctions();
     70 	gl.genTextures(1, &m_glTexture);
     71 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
     72 }
     73 
     74 Texture1D::~Texture1D (void)
     75 {
     76 	if (m_glTexture)
     77 		m_context.getFunctions().deleteTextures(1, &m_glTexture);
     78 }
     79 
     80 void Texture1D::upload (void)
     81 {
     82 	const glw::Functions& gl = m_context.getFunctions();
     83 
     84 	TCU_CHECK(m_glTexture);
     85 	gl.bindTexture(GL_TEXTURE_1D, m_glTexture);
     86 	gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
     87 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
     88 
     89 	TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());
     90 
     91 	for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
     92 	{
     93 		if (m_refTexture.isLevelEmpty(levelNdx))
     94 			continue; // Don't upload.
     95 
     96 		tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx);
     97 		gl.texImage1D(GL_TEXTURE_1D, levelNdx, m_format, access.getWidth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
     98 	}
     99 
    100 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    101 }
    102 
    103 // Texture2D
    104 
    105 Texture2D::Texture2D (const RenderContext& context, deUint32 format, deUint32 dataType, int width, int height)
    106 	: m_context			(context)
    107 	, m_isCompressed	(false)
    108 	, m_format			(format)
    109 	, m_refTexture		(mapGLTransferFormat(format, dataType), width, height)
    110 	, m_glTexture		(0)
    111 {
    112 	const glw::Functions& gl = context.getFunctions();
    113 	gl.genTextures(1, &m_glTexture);
    114 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
    115 }
    116 
    117 Texture2D::Texture2D (const RenderContext& context, deUint32 sizedFormat, int width, int height)
    118 	: m_context			(context)
    119 	, m_isCompressed	(false)
    120 	, m_format			(sizedFormat)
    121 	, m_refTexture		(mapGLInternalFormat(sizedFormat), width, height)
    122 	, m_glTexture		(0)
    123 {
    124 	const glw::Functions& gl = context.getFunctions();
    125 	gl.genTextures(1, &m_glTexture);
    126 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
    127 }
    128 
    129 Texture2D::Texture2D (const RenderContext& context, const ContextInfo& contextInfo, int numLevels, const tcu::CompressedTexture* levels, const tcu::CompressedTexture::DecompressionParams& decompressionParams)
    130 	: m_context			(context)
    131 	, m_isCompressed	(true)
    132 	, m_format			(getGLFormat(levels[0].getFormat()))
    133 	, m_refTexture		(levels[0].getUncompressedFormat(), levels[0].getWidth(), levels[0].getHeight())
    134 	, m_glTexture		(0)
    135 {
    136 	const glw::Functions& gl = context.getFunctions();
    137 
    138 	if (!contextInfo.isCompressedTextureFormatSupported(m_format))
    139 		throw tcu::NotSupportedError("Compressed texture format not supported", "", __FILE__, __LINE__);
    140 
    141 	gl.genTextures(1, &m_glTexture);
    142 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
    143 
    144 	try
    145 	{
    146 		loadCompressed(numLevels, levels, decompressionParams);
    147 	}
    148 	catch (const std::exception&)
    149 	{
    150 		gl.deleteTextures(1, &m_glTexture);
    151 		throw;
    152 	}
    153 }
    154 
    155 Texture2D::~Texture2D (void)
    156 {
    157 	if (m_glTexture)
    158 		m_context.getFunctions().deleteTextures(1, &m_glTexture);
    159 }
    160 
    161 void Texture2D::upload (void)
    162 {
    163 	const glw::Functions& gl = m_context.getFunctions();
    164 
    165 	DE_ASSERT(!m_isCompressed);
    166 
    167 	TCU_CHECK(m_glTexture);
    168 	gl.bindTexture(GL_TEXTURE_2D, m_glTexture);
    169 	gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
    170 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    171 
    172 	TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());
    173 
    174 	for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
    175 	{
    176 		if (m_refTexture.isLevelEmpty(levelNdx))
    177 			continue; // Don't upload.
    178 
    179 		tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx);
    180 		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth());
    181 		gl.texImage2D(GL_TEXTURE_2D, levelNdx, m_format, access.getWidth(), access.getHeight(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
    182 	}
    183 
    184 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    185 }
    186 
    187 void Texture2D::loadCompressed (int numLevels, const tcu::CompressedTexture* levels, const tcu::CompressedTexture::DecompressionParams& decompressionParams)
    188 {
    189 	const glw::Functions&	gl					= m_context.getFunctions();
    190 	deUint32				compressedFormat	= getGLFormat(levels[0].getFormat());
    191 
    192 	TCU_CHECK(m_glTexture);
    193 	gl.bindTexture(GL_TEXTURE_2D, m_glTexture);
    194 
    195 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
    196 	{
    197 		const tcu::CompressedTexture& level = levels[levelNdx];
    198 
    199 		// Decompress to reference texture.
    200 		m_refTexture.allocLevel(levelNdx);
    201 		tcu::PixelBufferAccess refLevelAccess = m_refTexture.getLevel(levelNdx);
    202 		TCU_CHECK(level.getWidth()	== refLevelAccess.getWidth() &&
    203 				  level.getHeight()	== refLevelAccess.getHeight());
    204 		level.decompress(refLevelAccess, decompressionParams);
    205 
    206 		// Upload to GL texture in compressed form.
    207 		gl.compressedTexImage2D(GL_TEXTURE_2D, levelNdx, compressedFormat,
    208 								level.getWidth(), level.getHeight(), 0 /* border */, level.getDataSize(), level.getData());
    209 	}
    210 
    211 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    212 }
    213 
    214 Texture2D* Texture2D::create (const RenderContext& context, const ContextInfo& contextInfo, const tcu::Archive& archive, int numLevels, const char* const* levelFileNames)
    215 {
    216 	DE_ASSERT(numLevels > 0);
    217 
    218 	std::string ext = de::FilePath(levelFileNames[0]).getFileExtension();
    219 
    220 	if (ext == "png")
    221 	{
    222 		// Uncompressed texture.
    223 
    224 		tcu::TextureLevel level;
    225 
    226 		// Load level 0.
    227 		tcu::ImageIO::loadPNG(level, archive, levelFileNames[0]);
    228 
    229 		TCU_CHECK_INTERNAL(level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8) ||
    230 						   level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8));
    231 
    232 		bool		isRGBA		= level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
    233 		Texture2D*	texture		= new Texture2D(context, isRGBA ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, level.getWidth(), level.getHeight());
    234 
    235 		try
    236 		{
    237 			// Fill level 0.
    238 			texture->getRefTexture().allocLevel(0);
    239 			tcu::copy(texture->getRefTexture().getLevel(0), level.getAccess());
    240 
    241 			// Fill remaining levels.
    242 			for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
    243 			{
    244 				tcu::ImageIO::loadPNG(level, archive, levelFileNames[levelNdx]);
    245 
    246 				texture->getRefTexture().allocLevel(levelNdx);
    247 				tcu::copy(texture->getRefTexture().getLevel(levelNdx), level.getAccess());
    248 			}
    249 
    250 			// Upload data.
    251 			texture->upload();
    252 		}
    253 		catch (const std::exception&)
    254 		{
    255 			delete texture;
    256 			throw;
    257 		}
    258 
    259 		return texture;
    260 	}
    261 	else if (ext == "pkm")
    262 	{
    263 		// Compressed texture.
    264 		vector<tcu::CompressedTexture> levels(numLevels);
    265 
    266 		for (int ndx = 0; ndx < numLevels; ndx++)
    267 			tcu::ImageIO::loadPKM(levels[ndx], archive, levelFileNames[ndx]);
    268 
    269 		return new Texture2D(context, contextInfo, numLevels, &levels[0]);
    270 	}
    271 	else
    272 		TCU_FAIL("Unsupported file format");
    273 }
    274 
    275 Texture2D* Texture2D::create (const RenderContext& context, const ContextInfo& contextInfo, const tcu::Archive& archive, int numLevels, const std::vector<std::string>& filenames)
    276 {
    277 	TCU_CHECK(numLevels == (int)filenames.size());
    278 
    279 	std::vector<const char*> charPtrs(filenames.size());
    280 	for (int ndx = 0; ndx < (int)filenames.size(); ndx++)
    281 		charPtrs[ndx] = filenames[ndx].c_str();
    282 
    283 	return Texture2D::create(context, contextInfo, archive, numLevels, &charPtrs[0]);
    284 }
    285 
    286 // TextureCube
    287 
    288 TextureCube::TextureCube (const RenderContext& context, const ContextInfo& contextInfo, int numLevels, const tcu::CompressedTexture* levels, const tcu::CompressedTexture::DecompressionParams& decompressionParams)
    289 	: m_context			(context)
    290 	, m_isCompressed	(true)
    291 	, m_format			(getGLFormat(levels[0].getFormat()))
    292 	, m_refTexture		(levels[0].getUncompressedFormat(), levels[0].getWidth())
    293 	, m_glTexture		(0)
    294 {
    295 	const glw::Functions& gl = m_context.getFunctions();
    296 
    297 	TCU_CHECK_INTERNAL(levels[0].getWidth() == levels[0].getHeight());
    298 
    299 	if (!contextInfo.isCompressedTextureFormatSupported(m_format))
    300 		throw tcu::NotSupportedError("Compressed texture format not supported", "", __FILE__, __LINE__);
    301 
    302 	gl.genTextures(1, &m_glTexture);
    303 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
    304 
    305 	try
    306 	{
    307 		loadCompressed(numLevels, levels, decompressionParams);
    308 	}
    309 	catch (const std::exception&)
    310 	{
    311 		gl.deleteTextures(1, &m_glTexture);
    312 		throw;
    313 	}
    314 }
    315 
    316 TextureCube::TextureCube (const RenderContext& context, deUint32 format, deUint32 dataType, int size)
    317 	: m_context			(context)
    318 	, m_isCompressed	(false)
    319 	, m_format			(format)
    320 	, m_refTexture		(mapGLTransferFormat(format, dataType), size)
    321 	, m_glTexture		(0)
    322 {
    323 	const glw::Functions& gl = m_context.getFunctions();
    324 	gl.genTextures(1, &m_glTexture);
    325 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
    326 }
    327 
    328 TextureCube::TextureCube (const RenderContext& context, deUint32 internalFormat, int size)
    329 	: m_context			(context)
    330 	, m_isCompressed	(false)
    331 	, m_format			(internalFormat)
    332 	, m_refTexture		(mapGLInternalFormat(internalFormat), size)
    333 	, m_glTexture		(0)
    334 {
    335 	const glw::Functions& gl = m_context.getFunctions();
    336 	gl.genTextures(1, &m_glTexture);
    337 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
    338 }
    339 
    340 TextureCube::~TextureCube (void)
    341 {
    342 	if (m_glTexture)
    343 		m_context.getFunctions().deleteTextures(1, &m_glTexture);
    344 }
    345 
    346 static deUint32 cubeFaceToGLFace (tcu::CubeFace face)
    347 {
    348 	switch (face)
    349 	{
    350 		case tcu::CUBEFACE_NEGATIVE_X: return GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
    351 		case tcu::CUBEFACE_POSITIVE_X: return GL_TEXTURE_CUBE_MAP_POSITIVE_X;
    352 		case tcu::CUBEFACE_NEGATIVE_Y: return GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
    353 		case tcu::CUBEFACE_POSITIVE_Y: return GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
    354 		case tcu::CUBEFACE_NEGATIVE_Z: return GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
    355 		case tcu::CUBEFACE_POSITIVE_Z: return GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
    356 		default:
    357 			DE_ASSERT(DE_FALSE);
    358 			return GL_NONE;
    359 	}
    360 }
    361 
    362 void TextureCube::upload (void)
    363 {
    364 	const glw::Functions& gl = m_context.getFunctions();
    365 
    366 	DE_ASSERT(!m_isCompressed);
    367 
    368 	TCU_CHECK(m_glTexture);
    369 	gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_glTexture);
    370 	gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
    371 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    372 
    373 	TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());
    374 
    375 	for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
    376 	{
    377 		for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
    378 		{
    379 			if (m_refTexture.isLevelEmpty((tcu::CubeFace)face, levelNdx))
    380 				continue; // Don't upload.
    381 
    382 			tcu::ConstPixelBufferAccess access = m_refTexture.getLevelFace(levelNdx, (tcu::CubeFace)face);
    383 			DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth());
    384 			gl.texImage2D(cubeFaceToGLFace((tcu::CubeFace)face), levelNdx, m_format, access.getWidth(), access.getHeight(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
    385 		}
    386 	}
    387 
    388 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    389 }
    390 
    391 void TextureCube::loadCompressed (int numLevels, const tcu::CompressedTexture* levels, const tcu::CompressedTexture::DecompressionParams& decompressionParams)
    392 {
    393 	const glw::Functions&	gl					= m_context.getFunctions();
    394 	deUint32				compressedFormat	= getGLFormat(levels[0].getFormat());
    395 
    396 	TCU_CHECK(m_glTexture);
    397 	gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_glTexture);
    398 
    399 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
    400 	{
    401 		for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
    402 		{
    403 			const tcu::CompressedTexture& level = levels[levelNdx*tcu::CUBEFACE_LAST + face];
    404 
    405 			// Decompress to reference texture.
    406 			m_refTexture.allocLevel((tcu::CubeFace)face, levelNdx);
    407 			tcu::PixelBufferAccess refLevelAccess = m_refTexture.getLevelFace(levelNdx, (tcu::CubeFace)face);
    408 			TCU_CHECK(level.getWidth()	== refLevelAccess.getWidth() &&
    409 					  level.getHeight()	== refLevelAccess.getHeight());
    410 			level.decompress(refLevelAccess, decompressionParams);
    411 
    412 			// Upload to GL texture in compressed form.
    413 			gl.compressedTexImage2D(cubeFaceToGLFace((tcu::CubeFace)face), levelNdx, compressedFormat,
    414 									level.getWidth(), level.getHeight(), 0 /* border */, level.getDataSize(), level.getData());
    415 		}
    416 	}
    417 
    418 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    419 }
    420 
    421 TextureCube* TextureCube::create (const RenderContext& context, const ContextInfo& contextInfo, const tcu::Archive& archive, int numLevels, const char* const* filenames)
    422 {
    423 	DE_ASSERT(numLevels > 0);
    424 
    425 	std::string ext = de::FilePath(filenames[0]).getFileExtension();
    426 
    427 	// \todo [2011-11-21 pyry] Support PNG images.
    428 	if (ext == "pkm")
    429 	{
    430 		// Compressed texture.
    431 		int								numImages	= numLevels*tcu::CUBEFACE_LAST;
    432 		vector<tcu::CompressedTexture>	levels		(numImages);
    433 
    434 		for (int ndx = 0; ndx < numImages; ndx++)
    435 			tcu::ImageIO::loadPKM(levels[ndx], archive, filenames[ndx]);
    436 
    437 		return new TextureCube(context, contextInfo, numLevels, &levels[0]);
    438 	}
    439 	else
    440 		TCU_FAIL("Unsupported file format");
    441 }
    442 
    443 TextureCube* TextureCube::create (const RenderContext& context, const ContextInfo& contextInfo, const tcu::Archive& archive, int numLevels, const std::vector<std::string>& filenames)
    444 {
    445 	DE_STATIC_ASSERT(tcu::CUBEFACE_LAST == 6);
    446 	TCU_CHECK(numLevels*tcu::CUBEFACE_LAST == (int)filenames.size());
    447 
    448 	std::vector<const char*> charPtrs(filenames.size());
    449 	for (int ndx = 0; ndx < (int)filenames.size(); ndx++)
    450 		charPtrs[ndx] = filenames[ndx].c_str();
    451 
    452 	return TextureCube::create(context, contextInfo, archive, numLevels, &charPtrs[0]);
    453 }
    454 
    455 // Texture1DArray
    456 
    457 Texture1DArray::Texture1DArray (const RenderContext& context, deUint32 format, deUint32 dataType, int width, int numLevels)
    458 	: m_context			(context)
    459 	, m_format			(format)
    460 	, m_refTexture		(mapGLTransferFormat(format, dataType), width, numLevels)
    461 	, m_glTexture		(0)
    462 {
    463 	const glw::Functions& gl = m_context.getFunctions();
    464 	gl.genTextures(1, &m_glTexture);
    465 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
    466 }
    467 
    468 Texture1DArray::Texture1DArray (const RenderContext& context, deUint32 sizedFormat, int width, int numLevels)
    469 	: m_context			(context)
    470 	, m_format			(sizedFormat)
    471 	, m_refTexture		(mapGLInternalFormat(sizedFormat), width, numLevels)
    472 	, m_glTexture		(0)
    473 {
    474 	const glw::Functions& gl = m_context.getFunctions();
    475 	gl.genTextures(1, &m_glTexture);
    476 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
    477 }
    478 
    479 Texture1DArray::~Texture1DArray (void)
    480 {
    481 	if (m_glTexture)
    482 		m_context.getFunctions().deleteTextures(1, &m_glTexture);
    483 }
    484 
    485 void Texture1DArray::upload (void)
    486 {
    487 	const glw::Functions& gl = m_context.getFunctions();
    488 
    489 	TCU_CHECK(m_glTexture);
    490 	gl.bindTexture(GL_TEXTURE_1D_ARRAY, m_glTexture);
    491 	gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
    492 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    493 
    494 	TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());
    495 
    496 	for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
    497 	{
    498 		if (m_refTexture.isLevelEmpty(levelNdx))
    499 			continue; // Don't upload.
    500 
    501 		tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx);
    502 		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth());
    503 		gl.texImage2D(GL_TEXTURE_1D_ARRAY, levelNdx, m_format, access.getWidth(), access.getHeight(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
    504 	}
    505 
    506 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    507 }
    508 
    509 // Texture2DArray
    510 
    511 Texture2DArray::Texture2DArray (const RenderContext& context, deUint32 format, deUint32 dataType, int width, int height, int numLevels)
    512 	: m_context			(context)
    513 	, m_format			(format)
    514 	, m_refTexture		(mapGLTransferFormat(format, dataType), width, height, numLevels)
    515 	, m_glTexture		(0)
    516 {
    517 	// \todo [2013-04-08 pyry] Check support here.
    518 	const glw::Functions& gl = m_context.getFunctions();
    519 	gl.genTextures(1, &m_glTexture);
    520 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
    521 }
    522 
    523 Texture2DArray::Texture2DArray (const RenderContext& context, deUint32 sizedFormat, int width, int height, int numLevels)
    524 	: m_context			(context)
    525 	, m_format			(sizedFormat)
    526 	, m_refTexture		(mapGLInternalFormat(sizedFormat), width, height, numLevels)
    527 	, m_glTexture		(0)
    528 {
    529 	// \todo [2013-04-08 pyry] Check support here.
    530 	const glw::Functions& gl = m_context.getFunctions();
    531 	gl.genTextures(1, &m_glTexture);
    532 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
    533 }
    534 
    535 Texture2DArray::~Texture2DArray (void)
    536 {
    537 	if (m_glTexture)
    538 		m_context.getFunctions().deleteTextures(1, &m_glTexture);
    539 }
    540 
    541 void Texture2DArray::upload (void)
    542 {
    543 	const glw::Functions& gl = m_context.getFunctions();
    544 
    545 	if (!gl.texImage3D)
    546 		throw tcu::NotSupportedError("glTexImage3D() is not supported");
    547 
    548 	TCU_CHECK(m_glTexture);
    549 	gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_glTexture);
    550 	gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
    551 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    552 
    553 	TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());
    554 
    555 	for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
    556 	{
    557 		if (m_refTexture.isLevelEmpty(levelNdx))
    558 			continue; // Don't upload.
    559 
    560 		tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx);
    561 		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth());
    562 		DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize()*access.getWidth()*access.getHeight());
    563 		gl.texImage3D(GL_TEXTURE_2D_ARRAY, levelNdx, m_format, access.getWidth(), access.getHeight(), access.getDepth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
    564 	}
    565 
    566 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    567 }
    568 
    569 // Texture3D
    570 
    571 Texture3D::Texture3D (const RenderContext& context, deUint32 format, deUint32 dataType, int width, int height, int depth)
    572 	: m_context			(context)
    573 	, m_format			(format)
    574 	, m_refTexture		(mapGLTransferFormat(format, dataType), width, height, depth)
    575 	, m_glTexture		(0)
    576 {
    577 	// \todo [2013-04-08 pyry] Check support here.
    578 	const glw::Functions& gl = m_context.getFunctions();
    579 	gl.genTextures(1, &m_glTexture);
    580 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
    581 }
    582 
    583 Texture3D::Texture3D (const RenderContext& context, deUint32 sizedFormat, int width, int height, int depth)
    584 	: m_context			(context)
    585 	, m_format			(sizedFormat)
    586 	, m_refTexture		(mapGLInternalFormat(sizedFormat), width, height, depth)
    587 	, m_glTexture		(0)
    588 {
    589 	// \todo [2013-04-08 pyry] Check support here.
    590 	const glw::Functions& gl = m_context.getFunctions();
    591 	gl.genTextures(1, &m_glTexture);
    592 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
    593 }
    594 
    595 Texture3D::~Texture3D (void)
    596 {
    597 	if (m_glTexture)
    598 		m_context.getFunctions().deleteTextures(1, &m_glTexture);
    599 }
    600 
    601 void Texture3D::upload (void)
    602 {
    603 	const glw::Functions& gl = m_context.getFunctions();
    604 
    605 	if (!gl.texImage3D)
    606 		throw tcu::NotSupportedError("glTexImage3D() is not supported");
    607 
    608 	TCU_CHECK(m_glTexture);
    609 	gl.bindTexture(GL_TEXTURE_3D, m_glTexture);
    610 	gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
    611 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    612 
    613 	TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());
    614 
    615 	for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
    616 	{
    617 		if (m_refTexture.isLevelEmpty(levelNdx))
    618 			continue; // Don't upload.
    619 
    620 		tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx);
    621 		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth());
    622 		DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize()*access.getWidth()*access.getHeight());
    623 		gl.texImage3D(GL_TEXTURE_3D, levelNdx, m_format, access.getWidth(), access.getHeight(), access.getDepth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
    624 	}
    625 
    626 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    627 }
    628 
    629 // TextureCubeArray
    630 
    631 TextureCubeArray::TextureCubeArray (const RenderContext& context, deUint32 format, deUint32 dataType, int size, int numLayers)
    632 	: m_context			(context)
    633 	, m_format			(format)
    634 	, m_refTexture		(mapGLTransferFormat(format, dataType), size, numLayers)
    635 	, m_glTexture		(0)
    636 {
    637 	// \todo [2013-04-08 pyry] Check support here.
    638 	const glw::Functions& gl = m_context.getFunctions();
    639 	gl.genTextures(1, &m_glTexture);
    640 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
    641 }
    642 
    643 TextureCubeArray::TextureCubeArray (const RenderContext& context, deUint32 sizedFormat, int size, int numLayers)
    644 	: m_context			(context)
    645 	, m_format			(sizedFormat)
    646 	, m_refTexture		(mapGLInternalFormat(sizedFormat), size, numLayers)
    647 	, m_glTexture		(0)
    648 {
    649 	// \todo [2013-04-08 pyry] Check support here.
    650 	const glw::Functions& gl = m_context.getFunctions();
    651 	gl.genTextures(1, &m_glTexture);
    652 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
    653 }
    654 
    655 TextureCubeArray::~TextureCubeArray (void)
    656 {
    657 	if (m_glTexture)
    658 		m_context.getFunctions().deleteTextures(1, &m_glTexture);
    659 }
    660 
    661 void TextureCubeArray::upload (void)
    662 {
    663 	const glw::Functions& gl = m_context.getFunctions();
    664 
    665 	if (!gl.texImage3D)
    666 		throw tcu::NotSupportedError("glTexImage3D() is not supported");
    667 
    668 	TCU_CHECK(m_glTexture);
    669 	gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, m_glTexture);
    670 	gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
    671 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    672 
    673 	TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());
    674 
    675 	for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
    676 	{
    677 		if (m_refTexture.isLevelEmpty(levelNdx))
    678 			continue; // Don't upload.
    679 
    680 		tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx);
    681 		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth());
    682 		DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize()*access.getWidth()*access.getHeight());
    683 		gl.texImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, levelNdx, m_format, access.getWidth(), access.getHeight(), access.getDepth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
    684 	}
    685 
    686 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    687 }
    688 
    689 // TextureBuffer
    690 
    691 TextureBuffer::TextureBuffer (const RenderContext& context, deUint32 internalFormat, size_t bufferSize)
    692 	: m_context			(context)
    693 	, m_format			(0)
    694 	, m_offset			(0)
    695 	, m_size			(0)
    696 	, m_glTexture		(0)
    697 	, m_glBuffer		(0)
    698 {
    699 	init(internalFormat, bufferSize, 0, 0, DE_NULL);
    700 }
    701 
    702 TextureBuffer::TextureBuffer (const RenderContext& context, deUint32 internalFormat, size_t bufferSize, size_t offset, size_t size, const void* data)
    703 	: m_context			(context)
    704 	, m_format			(0)
    705 	, m_offset			(0)
    706 	, m_size			(0)
    707 	, m_glTexture		(0)
    708 	, m_glBuffer		(0)
    709 {
    710 	init(internalFormat, bufferSize, offset, size, data);
    711 }
    712 
    713 void TextureBuffer::init (deUint32 internalFormat, size_t bufferSize, size_t offset, size_t size, const void* data)
    714 {
    715 	const glw::Functions&		gl		= m_context.getFunctions();
    716 	de::UniquePtr<ContextInfo>	info 	(ContextInfo::create(m_context));
    717 
    718 	if (offset != 0 || size != 0)
    719 	{
    720 		if (!(contextSupports(m_context.getType(), glu::ApiType(3, 3, glu::PROFILE_CORE)) && info->isExtensionSupported("GL_ARB_texture_buffer_range"))
    721 			&& !(contextSupports(m_context.getType(), glu::ApiType(3, 1, glu::PROFILE_ES))
    722 				&& info->isExtensionSupported("GL_EXT_texture_buffer")))
    723 		{
    724 			throw tcu::NotSupportedError("Ranged texture buffers not supported", "", __FILE__, __LINE__);
    725 		}
    726 	}
    727 	else
    728 	{
    729 		if (!contextSupports(m_context.getType(), glu::ApiType(3, 3, glu::PROFILE_CORE))
    730 			&& !(contextSupports(m_context.getType(), glu::ApiType(3, 1, glu::PROFILE_ES))
    731 				&& info->isExtensionSupported("GL_EXT_texture_buffer")))
    732 		{
    733 			throw tcu::NotSupportedError("Texture buffers not supported", "", __FILE__, __LINE__);
    734 		}
    735 	}
    736 
    737 	m_refBuffer.resize(bufferSize, 0);
    738 
    739 	if (data)
    740 		deMemcpy(&m_refBuffer[0], data, (int)bufferSize);
    741 
    742 	m_format	= internalFormat;
    743 	m_offset	= offset;
    744 	m_size		= size;
    745 
    746 	DE_ASSERT(size != 0 || offset == 0);
    747 
    748 	{
    749 		const tcu::TextureFormat	format			= mapGLInternalFormat(internalFormat);
    750 		deInt32						maxTextureSize	= 0;
    751 
    752 		gl.getIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTextureSize);
    753 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE) failed");
    754 
    755 		m_refTexture = tcu::PixelBufferAccess(format, de::min<int>((int)maxTextureSize, (int)((m_size != 0 ? m_size : bufferSize) / format.getPixelSize())), 1, 1, &(m_refBuffer[m_offset]));
    756 	}
    757 
    758 	{
    759 		gl.genTextures(1, &m_glTexture);
    760 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
    761 
    762 		gl.genBuffers(1, &m_glBuffer);
    763 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed");
    764 
    765 		gl.bindBuffer(GL_TEXTURE_BUFFER, m_glBuffer);
    766 		gl.bufferData(GL_TEXTURE_BUFFER, (glw::GLsizei)m_refBuffer.size(), &(m_refBuffer[0]), GL_STATIC_DRAW);
    767 		gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
    768 		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create buffer");
    769 
    770 		gl.bindTexture(GL_TEXTURE_BUFFER, m_glTexture);
    771 
    772 		if (offset != 0 || size != 0)
    773 			gl.texBufferRange(GL_TEXTURE_BUFFER, m_format, m_glBuffer, (glw::GLintptr)m_offset, (glw::GLsizeiptr)m_size);
    774 		else
    775 			gl.texBuffer(GL_TEXTURE_BUFFER, m_format, m_glBuffer);
    776 
    777 		gl.bindTexture(GL_TEXTURE_BUFFER, 0);
    778 		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to bind buffer to texture");
    779 	}
    780 }
    781 
    782 TextureBuffer::~TextureBuffer (void)
    783 {
    784 	if (m_glTexture)
    785 		m_context.getFunctions().deleteTextures(1, &m_glTexture);
    786 
    787 	if (m_glBuffer)
    788 		m_context.getFunctions().deleteBuffers(1, &m_glBuffer);
    789 }
    790 
    791 void TextureBuffer::upload (void)
    792 {
    793 	const glw::Functions& gl = m_context.getFunctions();
    794 
    795 	gl.bindBuffer(GL_TEXTURE_BUFFER, m_glBuffer);
    796 	gl.bufferData(GL_TEXTURE_BUFFER, (glw::GLsizei)m_refBuffer.size(), &(m_refBuffer[0]), GL_STATIC_DRAW);
    797 	gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
    798 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to upload buffer");
    799 }
    800 
    801 void TextureBuffer::bufferData (const deUint8* data, size_t size)
    802 {
    803 	const glw::Functions& gl = m_context.getFunctions();
    804 
    805 	m_refBuffer = vector<deUint8>(data, data+size);
    806 
    807 	{
    808 		const tcu::TextureFormat	format			= mapGLInternalFormat(m_format);
    809 		deInt32						maxTextureSize	= 0;
    810 
    811 		gl.getIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTextureSize);
    812 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE) failed");
    813 
    814 		m_refTexture = tcu::PixelBufferAccess(format, de::min<int>((int)maxTextureSize, (int)((m_size != 0 ? m_size : m_refBuffer.size())  / format.getPixelSize())), 1, 1, &(m_refBuffer[m_offset]));
    815 	}
    816 }
    817 
    818 } // glu
    819