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 
computePixelStore(const tcu::TextureFormat & format)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 
Texture1D(const RenderContext & context,deUint32 format,deUint32 dataType,int width)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 
Texture1D(const RenderContext & context,deUint32 sizedFormat,int width)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 
~Texture1D(void)74 Texture1D::~Texture1D (void)
75 {
76 	if (m_glTexture)
77 		m_context.getFunctions().deleteTextures(1, &m_glTexture);
78 }
79 
upload(void)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 
Texture2D(const RenderContext & context,deUint32 format,deUint32 dataType,int width,int height)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 
Texture2D(const RenderContext & context,deUint32 sizedFormat,int width,int height)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 
Texture2D(const RenderContext & context,const ContextInfo & contextInfo,int numLevels,const tcu::CompressedTexture * levels,const tcu::TexDecompressionParams & decompressionParams)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 
~Texture2D(void)155 Texture2D::~Texture2D (void)
156 {
157 	if (m_glTexture)
158 		m_context.getFunctions().deleteTextures(1, &m_glTexture);
159 }
160 
upload(void)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 
loadCompressed(int numLevels,const tcu::CompressedTexture * levels,const tcu::TexDecompressionParams & decompressionParams)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 
create(const RenderContext & context,const ContextInfo & contextInfo,const tcu::Archive & archive,int numLevels,const char * const * levelFileNames)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 
create(const RenderContext & context,const ContextInfo & contextInfo,const tcu::Archive & archive,int numLevels,const std::vector<std::string> & filenames)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 
TextureCube(const RenderContext & context,const ContextInfo & contextInfo,int numLevels,const tcu::CompressedTexture * levels,const tcu::TexDecompressionParams & decompressionParams)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 
TextureCube(const RenderContext & context,deUint32 format,deUint32 dataType,int size)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 
TextureCube(const RenderContext & context,deUint32 internalFormat,int size)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 
~TextureCube(void)340 TextureCube::~TextureCube (void)
341 {
342 	if (m_glTexture)
343 		m_context.getFunctions().deleteTextures(1, &m_glTexture);
344 }
345 
upload(void)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 
loadCompressed(int numLevels,const tcu::CompressedTexture * levels,const tcu::TexDecompressionParams & decompressionParams)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 
create(const RenderContext & context,const ContextInfo & contextInfo,const tcu::Archive & archive,int numLevels,const char * const * filenames)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 
create(const RenderContext & context,const ContextInfo & contextInfo,const tcu::Archive & archive,int numLevels,const std::vector<std::string> & filenames)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 
Texture1DArray(const RenderContext & context,deUint32 format,deUint32 dataType,int width,int numLevels)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 
Texture1DArray(const RenderContext & context,deUint32 sizedFormat,int width,int numLevels)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 
~Texture1DArray(void)463 Texture1DArray::~Texture1DArray (void)
464 {
465 	if (m_glTexture)
466 		m_context.getFunctions().deleteTextures(1, &m_glTexture);
467 }
468 
upload(void)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 
Texture2DArray(const RenderContext & context,deUint32 format,deUint32 dataType,int width,int height,int numLevels)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 
Texture2DArray(const RenderContext & context,deUint32 sizedFormat,int width,int height,int numLevels)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 
Texture2DArray(const RenderContext & context,const ContextInfo & contextInfo,int numLevels,const tcu::CompressedTexture * levels,const tcu::TexDecompressionParams & decompressionParams)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 
~Texture2DArray(void)547 Texture2DArray::~Texture2DArray (void)
548 {
549 	if (m_glTexture)
550 		m_context.getFunctions().deleteTextures(1, &m_glTexture);
551 }
552 
upload(void)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 
loadCompressed(int numLevels,const tcu::CompressedTexture * levels,const tcu::TexDecompressionParams & decompressionParams)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 
Texture3D(const RenderContext & context,deUint32 format,deUint32 dataType,int width,int height,int depth)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 
Texture3D(const RenderContext & context,deUint32 sizedFormat,int width,int height,int depth)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 
Texture3D(const RenderContext & context,const ContextInfo & contextInfo,int numLevels,const tcu::CompressedTexture * levels,const tcu::TexDecompressionParams & decompressionParams)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 
~Texture3D(void)667 Texture3D::~Texture3D (void)
668 {
669 	if (m_glTexture)
670 		m_context.getFunctions().deleteTextures(1, &m_glTexture);
671 }
672 
upload(void)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 
loadCompressed(int numLevels,const tcu::CompressedTexture * levels,const tcu::TexDecompressionParams & decompressionParams)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 
TextureCubeArray(const RenderContext & context,deUint32 format,deUint32 dataType,int size,int numLayers)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 
TextureCubeArray(const RenderContext & context,deUint32 sizedFormat,int size,int numLayers)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 
~TextureCubeArray(void)760 TextureCubeArray::~TextureCubeArray (void)
761 {
762 	if (m_glTexture)
763 		m_context.getFunctions().deleteTextures(1, &m_glTexture);
764 }
765 
upload(void)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 
TextureBuffer(const RenderContext & context,deUint32 internalFormat,size_t bufferSize)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 
TextureBuffer(const RenderContext & context,deUint32 internalFormat,size_t bufferSize,size_t offset,size_t size,const void * data)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 
init(deUint32 internalFormat,size_t bufferSize,size_t offset,size_t size,const void * data)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 
~TextureBuffer(void)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 
getFullRefTexture(void)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 
getFullRefTexture(void) const897 const tcu::ConstPixelBufferAccess TextureBuffer::getFullRefTexture (void) const
898 {
899 	return const_cast<TextureBuffer*>(this)->getFullRefTexture();
900 }
901 
upload(void)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