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