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::TexDecompressionParams& decompressionParams)
    130 	: m_context			(context)
    131 	, m_isCompressed	(true)
    132 	, m_format			(getGLFormat(levels[0].getFormat()))
    133 	, m_refTexture		(getUncompressedFormat(levels[0].getFormat()), 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 		TCU_THROW(NotSupportedError, "Compressed texture format not supported");
    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::TexDecompressionParams& 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::TexDecompressionParams& decompressionParams)
    289 	: m_context			(context)
    290 	, m_isCompressed	(true)
    291 	, m_format			(getGLFormat(levels[0].getFormat()))
    292 	, m_refTexture		(getUncompressedFormat(levels[0].getFormat()), 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 void TextureCube::upload (void)
    347 {
    348 	const glw::Functions& gl = m_context.getFunctions();
    349 
    350 	DE_ASSERT(!m_isCompressed);
    351 
    352 	TCU_CHECK(m_glTexture);
    353 	gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_glTexture);
    354 	gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
    355 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    356 
    357 	TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());
    358 
    359 	for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
    360 	{
    361 		for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
    362 		{
    363 			if (m_refTexture.isLevelEmpty((tcu::CubeFace)face, levelNdx))
    364 				continue; // Don't upload.
    365 
    366 			tcu::ConstPixelBufferAccess access = m_refTexture.getLevelFace(levelNdx, (tcu::CubeFace)face);
    367 			DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth());
    368 			gl.texImage2D(getGLCubeFace((tcu::CubeFace)face), levelNdx, m_format, access.getWidth(), access.getHeight(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
    369 		}
    370 	}
    371 
    372 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    373 }
    374 
    375 void TextureCube::loadCompressed (int numLevels, const tcu::CompressedTexture* levels, const tcu::TexDecompressionParams& decompressionParams)
    376 {
    377 	const glw::Functions&	gl					= m_context.getFunctions();
    378 	deUint32				compressedFormat	= getGLFormat(levels[0].getFormat());
    379 
    380 	TCU_CHECK(m_glTexture);
    381 	gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_glTexture);
    382 
    383 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
    384 	{
    385 		for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
    386 		{
    387 			const tcu::CompressedTexture& level = levels[levelNdx*tcu::CUBEFACE_LAST + face];
    388 
    389 			// Decompress to reference texture.
    390 			m_refTexture.allocLevel((tcu::CubeFace)face, levelNdx);
    391 			tcu::PixelBufferAccess refLevelAccess = m_refTexture.getLevelFace(levelNdx, (tcu::CubeFace)face);
    392 			TCU_CHECK(level.getWidth()	== refLevelAccess.getWidth() &&
    393 					  level.getHeight()	== refLevelAccess.getHeight());
    394 			level.decompress(refLevelAccess, decompressionParams);
    395 
    396 			// Upload to GL texture in compressed form.
    397 			gl.compressedTexImage2D(getGLCubeFace((tcu::CubeFace)face), levelNdx, compressedFormat,
    398 									level.getWidth(), level.getHeight(), 0 /* border */, level.getDataSize(), level.getData());
    399 		}
    400 	}
    401 
    402 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    403 }
    404 
    405 TextureCube* TextureCube::create (const RenderContext& context, const ContextInfo& contextInfo, const tcu::Archive& archive, int numLevels, const char* const* filenames)
    406 {
    407 	DE_ASSERT(numLevels > 0);
    408 
    409 	std::string ext = de::FilePath(filenames[0]).getFileExtension();
    410 
    411 	// \todo [2011-11-21 pyry] Support PNG images.
    412 	if (ext == "pkm")
    413 	{
    414 		// Compressed texture.
    415 		int								numImages	= numLevels*tcu::CUBEFACE_LAST;
    416 		vector<tcu::CompressedTexture>	levels		(numImages);
    417 
    418 		for (int ndx = 0; ndx < numImages; ndx++)
    419 			tcu::ImageIO::loadPKM(levels[ndx], archive, filenames[ndx]);
    420 
    421 		return new TextureCube(context, contextInfo, numLevels, &levels[0]);
    422 	}
    423 	else
    424 		TCU_FAIL("Unsupported file format");
    425 }
    426 
    427 TextureCube* TextureCube::create (const RenderContext& context, const ContextInfo& contextInfo, const tcu::Archive& archive, int numLevels, const std::vector<std::string>& filenames)
    428 {
    429 	DE_STATIC_ASSERT(tcu::CUBEFACE_LAST == 6);
    430 	TCU_CHECK(numLevels*tcu::CUBEFACE_LAST == (int)filenames.size());
    431 
    432 	std::vector<const char*> charPtrs(filenames.size());
    433 	for (int ndx = 0; ndx < (int)filenames.size(); ndx++)
    434 		charPtrs[ndx] = filenames[ndx].c_str();
    435 
    436 	return TextureCube::create(context, contextInfo, archive, numLevels, &charPtrs[0]);
    437 }
    438 
    439 // Texture1DArray
    440 
    441 Texture1DArray::Texture1DArray (const RenderContext& context, deUint32 format, deUint32 dataType, int width, int numLevels)
    442 	: m_context			(context)
    443 	, m_format			(format)
    444 	, m_refTexture		(mapGLTransferFormat(format, dataType), width, numLevels)
    445 	, m_glTexture		(0)
    446 {
    447 	const glw::Functions& gl = m_context.getFunctions();
    448 	gl.genTextures(1, &m_glTexture);
    449 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
    450 }
    451 
    452 Texture1DArray::Texture1DArray (const RenderContext& context, deUint32 sizedFormat, int width, int numLevels)
    453 	: m_context			(context)
    454 	, m_format			(sizedFormat)
    455 	, m_refTexture		(mapGLInternalFormat(sizedFormat), width, numLevels)
    456 	, m_glTexture		(0)
    457 {
    458 	const glw::Functions& gl = m_context.getFunctions();
    459 	gl.genTextures(1, &m_glTexture);
    460 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
    461 }
    462 
    463 Texture1DArray::~Texture1DArray (void)
    464 {
    465 	if (m_glTexture)
    466 		m_context.getFunctions().deleteTextures(1, &m_glTexture);
    467 }
    468 
    469 void Texture1DArray::upload (void)
    470 {
    471 	const glw::Functions& gl = m_context.getFunctions();
    472 
    473 	TCU_CHECK(m_glTexture);
    474 	gl.bindTexture(GL_TEXTURE_1D_ARRAY, m_glTexture);
    475 	gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
    476 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    477 
    478 	TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());
    479 
    480 	for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
    481 	{
    482 		if (m_refTexture.isLevelEmpty(levelNdx))
    483 			continue; // Don't upload.
    484 
    485 		tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx);
    486 		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth());
    487 		gl.texImage2D(GL_TEXTURE_1D_ARRAY, levelNdx, m_format, access.getWidth(), access.getHeight(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
    488 	}
    489 
    490 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    491 }
    492 
    493 // Texture2DArray
    494 
    495 Texture2DArray::Texture2DArray (const RenderContext& context, deUint32 format, deUint32 dataType, int width, int height, int numLevels)
    496 	: m_context			(context)
    497 	, m_isCompressed	(false)
    498 	, m_format			(format)
    499 	, m_refTexture		(mapGLTransferFormat(format, dataType), width, height, numLevels)
    500 	, m_glTexture		(0)
    501 {
    502 	// \todo [2013-04-08 pyry] Check support here.
    503 	const glw::Functions& gl = m_context.getFunctions();
    504 	gl.genTextures(1, &m_glTexture);
    505 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
    506 }
    507 
    508 Texture2DArray::Texture2DArray (const RenderContext& context, deUint32 sizedFormat, int width, int height, int numLevels)
    509 	: m_context			(context)
    510 	, m_isCompressed	(false)
    511 	, m_format			(sizedFormat)
    512 	, m_refTexture		(mapGLInternalFormat(sizedFormat), width, height, numLevels)
    513 	, m_glTexture		(0)
    514 {
    515 	// \todo [2013-04-08 pyry] Check support here.
    516 	const glw::Functions& gl = m_context.getFunctions();
    517 	gl.genTextures(1, &m_glTexture);
    518 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
    519 }
    520 
    521 Texture2DArray::Texture2DArray (const RenderContext& context, const ContextInfo& contextInfo, int numLevels, const tcu::CompressedTexture* levels, const tcu::TexDecompressionParams& decompressionParams)
    522 	: m_context			(context)
    523 	, m_isCompressed	(true)
    524 	, m_format			(getGLFormat(levels[0].getFormat()))
    525 	, m_refTexture		(getUncompressedFormat(levels[0].getFormat()), levels[0].getWidth(), levels[0].getHeight(), levels[0].getDepth())
    526 	, m_glTexture		(0)
    527 {
    528 	const glw::Functions& gl = context.getFunctions();
    529 
    530 	if (!contextInfo.isCompressedTextureFormatSupported(m_format))
    531 		throw tcu::NotSupportedError("Compressed texture format not supported", "", __FILE__, __LINE__);
    532 
    533 	gl.genTextures(1, &m_glTexture);
    534 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
    535 
    536 	try
    537 	{
    538 		loadCompressed(numLevels, levels, decompressionParams);
    539 	}
    540 	catch (const std::exception&)
    541 	{
    542 		gl.deleteTextures(1, &m_glTexture);
    543 		throw;
    544 	}
    545 }
    546 
    547 Texture2DArray::~Texture2DArray (void)
    548 {
    549 	if (m_glTexture)
    550 		m_context.getFunctions().deleteTextures(1, &m_glTexture);
    551 }
    552 
    553 void Texture2DArray::upload (void)
    554 {
    555 	const glw::Functions& gl = m_context.getFunctions();
    556 
    557 	if (!gl.texImage3D)
    558 		throw tcu::NotSupportedError("glTexImage3D() is not supported");
    559 
    560 	TCU_CHECK(m_glTexture);
    561 	gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_glTexture);
    562 	gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
    563 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    564 
    565 	TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());
    566 
    567 	for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
    568 	{
    569 		if (m_refTexture.isLevelEmpty(levelNdx))
    570 			continue; // Don't upload.
    571 
    572 		tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx);
    573 		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth());
    574 		DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize()*access.getWidth()*access.getHeight());
    575 		gl.texImage3D(GL_TEXTURE_2D_ARRAY, levelNdx, m_format, access.getWidth(), access.getHeight(), access.getDepth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
    576 	}
    577 
    578 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    579 }
    580 
    581 void Texture2DArray::loadCompressed (int numLevels, const tcu::CompressedTexture* levels, const tcu::TexDecompressionParams& decompressionParams)
    582 {
    583 	const glw::Functions&	gl					= m_context.getFunctions();
    584 	deUint32				compressedFormat	= getGLFormat(levels[0].getFormat());
    585 
    586 	TCU_CHECK(m_glTexture);
    587 	gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_glTexture);
    588 
    589 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
    590 	{
    591 		const tcu::CompressedTexture& level = levels[levelNdx];
    592 
    593 		// Decompress to reference texture.
    594 		m_refTexture.allocLevel(levelNdx);
    595 		tcu::PixelBufferAccess refLevelAccess = m_refTexture.getLevel(levelNdx);
    596 		TCU_CHECK(level.getWidth()	== refLevelAccess.getWidth() &&
    597 				  level.getHeight()	== refLevelAccess.getHeight() &&
    598 				  level.getDepth()	== refLevelAccess.getDepth());
    599 		level.decompress(refLevelAccess, decompressionParams);
    600 
    601 		// Upload to GL texture in compressed form.
    602 		gl.compressedTexImage3D(GL_TEXTURE_2D_ARRAY, levelNdx, compressedFormat,
    603 								level.getWidth(), level.getHeight(), m_refTexture.getLevel(levelNdx).getDepth(), 0 /* border */, level.getDataSize(), level.getData());
    604 	}
    605 
    606 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    607 }
    608 
    609 // Texture3D
    610 
    611 Texture3D::Texture3D (const RenderContext& context, deUint32 format, deUint32 dataType, int width, int height, int depth)
    612 	: m_context			(context)
    613 	, m_isCompressed	(false)
    614 	, m_format			(format)
    615 	, m_refTexture		(mapGLTransferFormat(format, dataType), width, height, depth)
    616 	, m_glTexture		(0)
    617 {
    618 	// \todo [2013-04-08 pyry] Check support here.
    619 	const glw::Functions& gl = m_context.getFunctions();
    620 	gl.genTextures(1, &m_glTexture);
    621 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
    622 }
    623 
    624 Texture3D::Texture3D (const RenderContext& context, deUint32 sizedFormat, int width, int height, int depth)
    625 	: m_context			(context)
    626 	, m_isCompressed	(false)
    627 	, m_format			(sizedFormat)
    628 	, m_refTexture		(mapGLInternalFormat(sizedFormat), width, height, depth)
    629 	, m_glTexture		(0)
    630 {
    631 	// \todo [2013-04-08 pyry] Check support here.
    632 	const glw::Functions& gl = m_context.getFunctions();
    633 	gl.genTextures(1, &m_glTexture);
    634 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
    635 }
    636 
    637 Texture3D::Texture3D (const RenderContext&					context,
    638 					  const ContextInfo&					contextInfo,
    639 					  int									numLevels,
    640 					  const tcu::CompressedTexture*			levels,
    641 					  const tcu::TexDecompressionParams&	decompressionParams)
    642 	: m_context			(context)
    643 	, m_isCompressed	(true)
    644 	, m_format			(getGLFormat(levels[0].getFormat()))
    645 	, m_refTexture		(getUncompressedFormat(levels[0].getFormat()), levels[0].getWidth(), levels[0].getHeight(), levels[0].getDepth())
    646 	, m_glTexture		(0)
    647 {
    648 	const glw::Functions& gl = context.getFunctions();
    649 
    650 	if (!contextInfo.isCompressedTextureFormatSupported(m_format))
    651 		throw tcu::NotSupportedError("Compressed texture format not supported", "", __FILE__, __LINE__);
    652 
    653 	gl.genTextures(1, &m_glTexture);
    654 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
    655 
    656 	try
    657 	{
    658 		loadCompressed(numLevels, levels, decompressionParams);
    659 	}
    660 	catch (const std::exception&)
    661 	{
    662 		gl.deleteTextures(1, &m_glTexture);
    663 		throw;
    664 	}
    665 }
    666 
    667 Texture3D::~Texture3D (void)
    668 {
    669 	if (m_glTexture)
    670 		m_context.getFunctions().deleteTextures(1, &m_glTexture);
    671 }
    672 
    673 void Texture3D::upload (void)
    674 {
    675 	const glw::Functions& gl = m_context.getFunctions();
    676 
    677 	DE_ASSERT(!m_isCompressed);
    678 
    679 	if (!gl.texImage3D)
    680 		throw tcu::NotSupportedError("glTexImage3D() is not supported");
    681 
    682 	TCU_CHECK(m_glTexture);
    683 	gl.bindTexture(GL_TEXTURE_3D, m_glTexture);
    684 	gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
    685 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    686 
    687 	TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());
    688 
    689 	for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
    690 	{
    691 		if (m_refTexture.isLevelEmpty(levelNdx))
    692 			continue; // Don't upload.
    693 
    694 		tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx);
    695 		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth());
    696 		DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize()*access.getWidth()*access.getHeight());
    697 		gl.texImage3D(GL_TEXTURE_3D, levelNdx, m_format, access.getWidth(), access.getHeight(), access.getDepth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
    698 	}
    699 
    700 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    701 }
    702 
    703 void Texture3D::loadCompressed (int numLevels, const tcu::CompressedTexture* levels, const tcu::TexDecompressionParams& decompressionParams)
    704 {
    705 	const glw::Functions&	gl					= m_context.getFunctions();
    706 	deUint32				compressedFormat	= getGLFormat(levels[0].getFormat());
    707 
    708 	if (!gl.compressedTexImage3D)
    709 		throw tcu::NotSupportedError("glCompressedTexImage3D() is not supported");
    710 
    711 	TCU_CHECK(m_glTexture);
    712 	gl.bindTexture(GL_TEXTURE_3D, m_glTexture);
    713 
    714 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
    715 	{
    716 		const tcu::CompressedTexture& level = levels[levelNdx];
    717 
    718 		// Decompress to reference texture.
    719 		m_refTexture.allocLevel(levelNdx);
    720 		tcu::PixelBufferAccess refLevelAccess = m_refTexture.getLevel(levelNdx);
    721 		TCU_CHECK(level.getWidth()	== refLevelAccess.getWidth() &&
    722 				  level.getHeight()	== refLevelAccess.getHeight() &&
    723 				  level.getDepth()	== refLevelAccess.getDepth());
    724 		level.decompress(refLevelAccess, decompressionParams);
    725 
    726 		// Upload to GL texture in compressed form.
    727 		gl.compressedTexImage3D(GL_TEXTURE_3D, levelNdx, compressedFormat,
    728 								level.getWidth(), level.getHeight(), level.getDepth(), 0 /* border */, level.getDataSize(), level.getData());
    729 	}
    730 
    731 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    732 }
    733 
    734 // TextureCubeArray
    735 
    736 TextureCubeArray::TextureCubeArray (const RenderContext& context, deUint32 format, deUint32 dataType, int size, int numLayers)
    737 	: m_context			(context)
    738 	, m_format			(format)
    739 	, m_refTexture		(mapGLTransferFormat(format, dataType), size, numLayers)
    740 	, m_glTexture		(0)
    741 {
    742 	// \todo [2013-04-08 pyry] Check support here.
    743 	const glw::Functions& gl = m_context.getFunctions();
    744 	gl.genTextures(1, &m_glTexture);
    745 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
    746 }
    747 
    748 TextureCubeArray::TextureCubeArray (const RenderContext& context, deUint32 sizedFormat, int size, int numLayers)
    749 	: m_context			(context)
    750 	, m_format			(sizedFormat)
    751 	, m_refTexture		(mapGLInternalFormat(sizedFormat), size, numLayers)
    752 	, m_glTexture		(0)
    753 {
    754 	// \todo [2013-04-08 pyry] Check support here.
    755 	const glw::Functions& gl = m_context.getFunctions();
    756 	gl.genTextures(1, &m_glTexture);
    757 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
    758 }
    759 
    760 TextureCubeArray::~TextureCubeArray (void)
    761 {
    762 	if (m_glTexture)
    763 		m_context.getFunctions().deleteTextures(1, &m_glTexture);
    764 }
    765 
    766 void TextureCubeArray::upload (void)
    767 {
    768 	const glw::Functions& gl = m_context.getFunctions();
    769 
    770 	if (!gl.texImage3D)
    771 		throw tcu::NotSupportedError("glTexImage3D() is not supported");
    772 
    773 	TCU_CHECK(m_glTexture);
    774 	gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, m_glTexture);
    775 	gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
    776 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    777 
    778 	TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());
    779 
    780 	for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
    781 	{
    782 		if (m_refTexture.isLevelEmpty(levelNdx))
    783 			continue; // Don't upload.
    784 
    785 		tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx);
    786 		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth());
    787 		DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize()*access.getWidth()*access.getHeight());
    788 		gl.texImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, levelNdx, m_format, access.getWidth(), access.getHeight(), access.getDepth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
    789 	}
    790 
    791 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
    792 }
    793 
    794 // TextureBuffer
    795 
    796 TextureBuffer::TextureBuffer (const RenderContext& context, deUint32 internalFormat, size_t bufferSize)
    797 	: m_context			(context)
    798 	, m_format			(0)
    799 	, m_offset			(0)
    800 	, m_size			(0)
    801 	, m_glTexture		(0)
    802 	, m_glBuffer		(0)
    803 {
    804 	init(internalFormat, bufferSize, 0, 0, DE_NULL);
    805 }
    806 
    807 TextureBuffer::TextureBuffer (const RenderContext& context, deUint32 internalFormat, size_t bufferSize, size_t offset, size_t size, const void* data)
    808 	: m_context			(context)
    809 	, m_format			(0)
    810 	, m_offset			(0)
    811 	, m_size			(0)
    812 	, m_glTexture		(0)
    813 	, m_glBuffer		(0)
    814 {
    815 	init(internalFormat, bufferSize, offset, size, data);
    816 }
    817 
    818 void TextureBuffer::init (deUint32 internalFormat, size_t bufferSize, size_t offset, size_t size, const void* data)
    819 {
    820 	const glw::Functions&		gl		= m_context.getFunctions();
    821 	de::UniquePtr<ContextInfo>	info 	(ContextInfo::create(m_context));
    822 
    823 	if (offset != 0 || size != 0)
    824 	{
    825 		if (!(contextSupports(m_context.getType(), glu::ApiType(3, 3, glu::PROFILE_CORE)) && info->isExtensionSupported("GL_ARB_texture_buffer_range"))
    826 			&& !(contextSupports(m_context.getType(), glu::ApiType(3, 1, glu::PROFILE_ES))
    827 				&& info->isExtensionSupported("GL_EXT_texture_buffer")))
    828 		{
    829 			throw tcu::NotSupportedError("Ranged texture buffers not supported", "", __FILE__, __LINE__);
    830 		}
    831 	}
    832 	else
    833 	{
    834 		if (!contextSupports(m_context.getType(), glu::ApiType(3, 3, glu::PROFILE_CORE))
    835 			&& !(contextSupports(m_context.getType(), glu::ApiType(3, 1, glu::PROFILE_ES))
    836 				&& info->isExtensionSupported("GL_EXT_texture_buffer")))
    837 		{
    838 			throw tcu::NotSupportedError("Texture buffers not supported", "", __FILE__, __LINE__);
    839 		}
    840 	}
    841 
    842 	m_refBuffer.setStorage(bufferSize);
    843 	if (data)
    844 		deMemcpy(m_refBuffer.getPtr(), data, (int)bufferSize);
    845 
    846 	m_format	= internalFormat;
    847 	m_offset	= offset;
    848 	m_size		= size;
    849 
    850 	DE_ASSERT(size != 0 || offset == 0);
    851 
    852 	{
    853 		gl.genTextures(1, &m_glTexture);
    854 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
    855 
    856 		gl.genBuffers(1, &m_glBuffer);
    857 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed");
    858 
    859 		gl.bindBuffer(GL_TEXTURE_BUFFER, m_glBuffer);
    860 		gl.bufferData(GL_TEXTURE_BUFFER, (glw::GLsizei)m_refBuffer.size(), data, GL_STATIC_DRAW);
    861 		gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
    862 		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create buffer");
    863 
    864 		gl.bindTexture(GL_TEXTURE_BUFFER, m_glTexture);
    865 
    866 		if (offset != 0 || size != 0)
    867 			gl.texBufferRange(GL_TEXTURE_BUFFER, m_format, m_glBuffer, (glw::GLintptr)m_offset, (glw::GLsizeiptr)m_size);
    868 		else
    869 			gl.texBuffer(GL_TEXTURE_BUFFER, m_format, m_glBuffer);
    870 
    871 		gl.bindTexture(GL_TEXTURE_BUFFER, 0);
    872 		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to bind buffer to texture");
    873 	}
    874 }
    875 
    876 TextureBuffer::~TextureBuffer (void)
    877 {
    878 	if (m_glTexture)
    879 		m_context.getFunctions().deleteTextures(1, &m_glTexture);
    880 
    881 	if (m_glBuffer)
    882 		m_context.getFunctions().deleteBuffers(1, &m_glBuffer);
    883 }
    884 
    885 
    886 const tcu::PixelBufferAccess TextureBuffer::getFullRefTexture (void)
    887 {
    888 	const tcu::TextureFormat	format				= mapGLInternalFormat(m_format);
    889 	const size_t				bufferLengthBytes	= (m_size != 0) ? (m_size) : (m_refBuffer.size());
    890 	const int					bufferLengthPixels	= (int)bufferLengthBytes / format.getPixelSize();
    891 
    892 	return tcu::PixelBufferAccess(format,
    893 								  tcu::IVec3(bufferLengthPixels, 1, 1),
    894 								  (deUint8*)m_refBuffer.getPtr() + m_offset);
    895 }
    896 
    897 const tcu::ConstPixelBufferAccess TextureBuffer::getFullRefTexture (void) const
    898 {
    899 	return const_cast<TextureBuffer*>(this)->getFullRefTexture();
    900 }
    901 
    902 void TextureBuffer::upload (void)
    903 {
    904 	const glw::Functions& gl = m_context.getFunctions();
    905 
    906 	gl.bindBuffer(GL_TEXTURE_BUFFER, m_glBuffer);
    907 	gl.bufferData(GL_TEXTURE_BUFFER, (glw::GLsizei)m_refBuffer.size(), m_refBuffer.getPtr(), GL_STATIC_DRAW);
    908 	gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
    909 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to upload buffer");
    910 }
    911 
    912 } // glu
    913