• 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)
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::CompressedTexture::DecompressionParams & decompressionParams)129 Texture2D::Texture2D (const RenderContext& context, const ContextInfo& contextInfo, int numLevels, const tcu::CompressedTexture* levels, const tcu::CompressedTexture::DecompressionParams& decompressionParams)
130 	: m_context			(context)
131 	, m_isCompressed	(true)
132 	, m_format			(getGLFormat(levels[0].getFormat()))
133 	, m_refTexture		(levels[0].getUncompressedFormat(), levels[0].getWidth(), levels[0].getHeight())
134 	, m_glTexture		(0)
135 {
136 	const glw::Functions& gl = context.getFunctions();
137 
138 	if (!contextInfo.isCompressedTextureFormatSupported(m_format))
139 		throw tcu::NotSupportedError("Compressed texture format not supported", "", __FILE__, __LINE__);
140 
141 	gl.genTextures(1, &m_glTexture);
142 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
143 
144 	try
145 	{
146 		loadCompressed(numLevels, levels, decompressionParams);
147 	}
148 	catch (const std::exception&)
149 	{
150 		gl.deleteTextures(1, &m_glTexture);
151 		throw;
152 	}
153 }
154 
~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::CompressedTexture::DecompressionParams & decompressionParams)187 void Texture2D::loadCompressed (int numLevels, const tcu::CompressedTexture* levels, const tcu::CompressedTexture::DecompressionParams& decompressionParams)
188 {
189 	const glw::Functions&	gl					= m_context.getFunctions();
190 	deUint32				compressedFormat	= getGLFormat(levels[0].getFormat());
191 
192 	TCU_CHECK(m_glTexture);
193 	gl.bindTexture(GL_TEXTURE_2D, m_glTexture);
194 
195 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
196 	{
197 		const tcu::CompressedTexture& level = levels[levelNdx];
198 
199 		// Decompress to reference texture.
200 		m_refTexture.allocLevel(levelNdx);
201 		tcu::PixelBufferAccess refLevelAccess = m_refTexture.getLevel(levelNdx);
202 		TCU_CHECK(level.getWidth()	== refLevelAccess.getWidth() &&
203 				  level.getHeight()	== refLevelAccess.getHeight());
204 		level.decompress(refLevelAccess, decompressionParams);
205 
206 		// Upload to GL texture in compressed form.
207 		gl.compressedTexImage2D(GL_TEXTURE_2D, levelNdx, compressedFormat,
208 								level.getWidth(), level.getHeight(), 0 /* border */, level.getDataSize(), level.getData());
209 	}
210 
211 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
212 }
213 
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::CompressedTexture::DecompressionParams & decompressionParams)288 TextureCube::TextureCube (const RenderContext& context, const ContextInfo& contextInfo, int numLevels, const tcu::CompressedTexture* levels, const tcu::CompressedTexture::DecompressionParams& decompressionParams)
289 	: m_context			(context)
290 	, m_isCompressed	(true)
291 	, m_format			(getGLFormat(levels[0].getFormat()))
292 	, m_refTexture		(levels[0].getUncompressedFormat(), levels[0].getWidth())
293 	, m_glTexture		(0)
294 {
295 	const glw::Functions& gl = m_context.getFunctions();
296 
297 	TCU_CHECK_INTERNAL(levels[0].getWidth() == levels[0].getHeight());
298 
299 	if (!contextInfo.isCompressedTextureFormatSupported(m_format))
300 		throw tcu::NotSupportedError("Compressed texture format not supported", "", __FILE__, __LINE__);
301 
302 	gl.genTextures(1, &m_glTexture);
303 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
304 
305 	try
306 	{
307 		loadCompressed(numLevels, levels, decompressionParams);
308 	}
309 	catch (const std::exception&)
310 	{
311 		gl.deleteTextures(1, &m_glTexture);
312 		throw;
313 	}
314 }
315 
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 
cubeFaceToGLFace(tcu::CubeFace face)346 static deUint32 cubeFaceToGLFace (tcu::CubeFace face)
347 {
348 	switch (face)
349 	{
350 		case tcu::CUBEFACE_NEGATIVE_X: return GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
351 		case tcu::CUBEFACE_POSITIVE_X: return GL_TEXTURE_CUBE_MAP_POSITIVE_X;
352 		case tcu::CUBEFACE_NEGATIVE_Y: return GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
353 		case tcu::CUBEFACE_POSITIVE_Y: return GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
354 		case tcu::CUBEFACE_NEGATIVE_Z: return GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
355 		case tcu::CUBEFACE_POSITIVE_Z: return GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
356 		default:
357 			DE_ASSERT(DE_FALSE);
358 			return GL_NONE;
359 	}
360 }
361 
upload(void)362 void TextureCube::upload (void)
363 {
364 	const glw::Functions& gl = m_context.getFunctions();
365 
366 	DE_ASSERT(!m_isCompressed);
367 
368 	TCU_CHECK(m_glTexture);
369 	gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_glTexture);
370 	gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
371 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
372 
373 	TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());
374 
375 	for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
376 	{
377 		for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
378 		{
379 			if (m_refTexture.isLevelEmpty((tcu::CubeFace)face, levelNdx))
380 				continue; // Don't upload.
381 
382 			tcu::ConstPixelBufferAccess access = m_refTexture.getLevelFace(levelNdx, (tcu::CubeFace)face);
383 			DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth());
384 			gl.texImage2D(cubeFaceToGLFace((tcu::CubeFace)face), levelNdx, m_format, access.getWidth(), access.getHeight(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
385 		}
386 	}
387 
388 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
389 }
390 
loadCompressed(int numLevels,const tcu::CompressedTexture * levels,const tcu::CompressedTexture::DecompressionParams & decompressionParams)391 void TextureCube::loadCompressed (int numLevels, const tcu::CompressedTexture* levels, const tcu::CompressedTexture::DecompressionParams& decompressionParams)
392 {
393 	const glw::Functions&	gl					= m_context.getFunctions();
394 	deUint32				compressedFormat	= getGLFormat(levels[0].getFormat());
395 
396 	TCU_CHECK(m_glTexture);
397 	gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_glTexture);
398 
399 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
400 	{
401 		for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
402 		{
403 			const tcu::CompressedTexture& level = levels[levelNdx*tcu::CUBEFACE_LAST + face];
404 
405 			// Decompress to reference texture.
406 			m_refTexture.allocLevel((tcu::CubeFace)face, levelNdx);
407 			tcu::PixelBufferAccess refLevelAccess = m_refTexture.getLevelFace(levelNdx, (tcu::CubeFace)face);
408 			TCU_CHECK(level.getWidth()	== refLevelAccess.getWidth() &&
409 					  level.getHeight()	== refLevelAccess.getHeight());
410 			level.decompress(refLevelAccess, decompressionParams);
411 
412 			// Upload to GL texture in compressed form.
413 			gl.compressedTexImage2D(cubeFaceToGLFace((tcu::CubeFace)face), levelNdx, compressedFormat,
414 									level.getWidth(), level.getHeight(), 0 /* border */, level.getDataSize(), level.getData());
415 		}
416 	}
417 
418 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
419 }
420 
create(const RenderContext & context,const ContextInfo & contextInfo,const tcu::Archive & archive,int numLevels,const char * const * filenames)421 TextureCube* TextureCube::create (const RenderContext& context, const ContextInfo& contextInfo, const tcu::Archive& archive, int numLevels, const char* const* filenames)
422 {
423 	DE_ASSERT(numLevels > 0);
424 
425 	std::string ext = de::FilePath(filenames[0]).getFileExtension();
426 
427 	// \todo [2011-11-21 pyry] Support PNG images.
428 	if (ext == "pkm")
429 	{
430 		// Compressed texture.
431 		int								numImages	= numLevels*tcu::CUBEFACE_LAST;
432 		vector<tcu::CompressedTexture>	levels		(numImages);
433 
434 		for (int ndx = 0; ndx < numImages; ndx++)
435 			tcu::ImageIO::loadPKM(levels[ndx], archive, filenames[ndx]);
436 
437 		return new TextureCube(context, contextInfo, numLevels, &levels[0]);
438 	}
439 	else
440 		TCU_FAIL("Unsupported file format");
441 }
442 
create(const RenderContext & context,const ContextInfo & contextInfo,const tcu::Archive & archive,int numLevels,const std::vector<std::string> & filenames)443 TextureCube* TextureCube::create (const RenderContext& context, const ContextInfo& contextInfo, const tcu::Archive& archive, int numLevels, const std::vector<std::string>& filenames)
444 {
445 	DE_STATIC_ASSERT(tcu::CUBEFACE_LAST == 6);
446 	TCU_CHECK(numLevels*tcu::CUBEFACE_LAST == (int)filenames.size());
447 
448 	std::vector<const char*> charPtrs(filenames.size());
449 	for (int ndx = 0; ndx < (int)filenames.size(); ndx++)
450 		charPtrs[ndx] = filenames[ndx].c_str();
451 
452 	return TextureCube::create(context, contextInfo, archive, numLevels, &charPtrs[0]);
453 }
454 
455 // Texture1DArray
456 
Texture1DArray(const RenderContext & context,deUint32 format,deUint32 dataType,int width,int numLevels)457 Texture1DArray::Texture1DArray (const RenderContext& context, deUint32 format, deUint32 dataType, int width, int numLevels)
458 	: m_context			(context)
459 	, m_format			(format)
460 	, m_refTexture		(mapGLTransferFormat(format, dataType), width, numLevels)
461 	, m_glTexture		(0)
462 {
463 	const glw::Functions& gl = m_context.getFunctions();
464 	gl.genTextures(1, &m_glTexture);
465 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
466 }
467 
Texture1DArray(const RenderContext & context,deUint32 sizedFormat,int width,int numLevels)468 Texture1DArray::Texture1DArray (const RenderContext& context, deUint32 sizedFormat, int width, int numLevels)
469 	: m_context			(context)
470 	, m_format			(sizedFormat)
471 	, m_refTexture		(mapGLInternalFormat(sizedFormat), width, numLevels)
472 	, m_glTexture		(0)
473 {
474 	const glw::Functions& gl = m_context.getFunctions();
475 	gl.genTextures(1, &m_glTexture);
476 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
477 }
478 
~Texture1DArray(void)479 Texture1DArray::~Texture1DArray (void)
480 {
481 	if (m_glTexture)
482 		m_context.getFunctions().deleteTextures(1, &m_glTexture);
483 }
484 
upload(void)485 void Texture1DArray::upload (void)
486 {
487 	const glw::Functions& gl = m_context.getFunctions();
488 
489 	TCU_CHECK(m_glTexture);
490 	gl.bindTexture(GL_TEXTURE_1D_ARRAY, m_glTexture);
491 	gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
492 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
493 
494 	TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());
495 
496 	for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
497 	{
498 		if (m_refTexture.isLevelEmpty(levelNdx))
499 			continue; // Don't upload.
500 
501 		tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx);
502 		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth());
503 		gl.texImage2D(GL_TEXTURE_1D_ARRAY, levelNdx, m_format, access.getWidth(), access.getHeight(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
504 	}
505 
506 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
507 }
508 
509 // Texture2DArray
510 
Texture2DArray(const RenderContext & context,deUint32 format,deUint32 dataType,int width,int height,int numLevels)511 Texture2DArray::Texture2DArray (const RenderContext& context, deUint32 format, deUint32 dataType, int width, int height, int numLevels)
512 	: m_context			(context)
513 	, m_format			(format)
514 	, m_refTexture		(mapGLTransferFormat(format, dataType), width, height, numLevels)
515 	, m_glTexture		(0)
516 {
517 	// \todo [2013-04-08 pyry] Check support here.
518 	const glw::Functions& gl = m_context.getFunctions();
519 	gl.genTextures(1, &m_glTexture);
520 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
521 }
522 
Texture2DArray(const RenderContext & context,deUint32 sizedFormat,int width,int height,int numLevels)523 Texture2DArray::Texture2DArray (const RenderContext& context, deUint32 sizedFormat, int width, int height, int numLevels)
524 	: m_context			(context)
525 	, m_format			(sizedFormat)
526 	, m_refTexture		(mapGLInternalFormat(sizedFormat), width, height, numLevels)
527 	, m_glTexture		(0)
528 {
529 	// \todo [2013-04-08 pyry] Check support here.
530 	const glw::Functions& gl = m_context.getFunctions();
531 	gl.genTextures(1, &m_glTexture);
532 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
533 }
534 
~Texture2DArray(void)535 Texture2DArray::~Texture2DArray (void)
536 {
537 	if (m_glTexture)
538 		m_context.getFunctions().deleteTextures(1, &m_glTexture);
539 }
540 
upload(void)541 void Texture2DArray::upload (void)
542 {
543 	const glw::Functions& gl = m_context.getFunctions();
544 
545 	if (!gl.texImage3D)
546 		throw tcu::NotSupportedError("glTexImage3D() is not supported");
547 
548 	TCU_CHECK(m_glTexture);
549 	gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_glTexture);
550 	gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
551 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
552 
553 	TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());
554 
555 	for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
556 	{
557 		if (m_refTexture.isLevelEmpty(levelNdx))
558 			continue; // Don't upload.
559 
560 		tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx);
561 		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth());
562 		DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize()*access.getWidth()*access.getHeight());
563 		gl.texImage3D(GL_TEXTURE_2D_ARRAY, levelNdx, m_format, access.getWidth(), access.getHeight(), access.getDepth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
564 	}
565 
566 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
567 }
568 
569 // Texture3D
570 
Texture3D(const RenderContext & context,deUint32 format,deUint32 dataType,int width,int height,int depth)571 Texture3D::Texture3D (const RenderContext& context, deUint32 format, deUint32 dataType, int width, int height, int depth)
572 	: m_context			(context)
573 	, m_format			(format)
574 	, m_refTexture		(mapGLTransferFormat(format, dataType), width, height, depth)
575 	, m_glTexture		(0)
576 {
577 	// \todo [2013-04-08 pyry] Check support here.
578 	const glw::Functions& gl = m_context.getFunctions();
579 	gl.genTextures(1, &m_glTexture);
580 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
581 }
582 
Texture3D(const RenderContext & context,deUint32 sizedFormat,int width,int height,int depth)583 Texture3D::Texture3D (const RenderContext& context, deUint32 sizedFormat, int width, int height, int depth)
584 	: m_context			(context)
585 	, m_format			(sizedFormat)
586 	, m_refTexture		(mapGLInternalFormat(sizedFormat), width, height, depth)
587 	, m_glTexture		(0)
588 {
589 	// \todo [2013-04-08 pyry] Check support here.
590 	const glw::Functions& gl = m_context.getFunctions();
591 	gl.genTextures(1, &m_glTexture);
592 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
593 }
594 
~Texture3D(void)595 Texture3D::~Texture3D (void)
596 {
597 	if (m_glTexture)
598 		m_context.getFunctions().deleteTextures(1, &m_glTexture);
599 }
600 
upload(void)601 void Texture3D::upload (void)
602 {
603 	const glw::Functions& gl = m_context.getFunctions();
604 
605 	if (!gl.texImage3D)
606 		throw tcu::NotSupportedError("glTexImage3D() is not supported");
607 
608 	TCU_CHECK(m_glTexture);
609 	gl.bindTexture(GL_TEXTURE_3D, m_glTexture);
610 	gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
611 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
612 
613 	TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());
614 
615 	for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
616 	{
617 		if (m_refTexture.isLevelEmpty(levelNdx))
618 			continue; // Don't upload.
619 
620 		tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx);
621 		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth());
622 		DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize()*access.getWidth()*access.getHeight());
623 		gl.texImage3D(GL_TEXTURE_3D, levelNdx, m_format, access.getWidth(), access.getHeight(), access.getDepth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
624 	}
625 
626 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
627 }
628 
629 // TextureCubeArray
630 
TextureCubeArray(const RenderContext & context,deUint32 format,deUint32 dataType,int size,int numLayers)631 TextureCubeArray::TextureCubeArray (const RenderContext& context, deUint32 format, deUint32 dataType, int size, int numLayers)
632 	: m_context			(context)
633 	, m_format			(format)
634 	, m_refTexture		(mapGLTransferFormat(format, dataType), size, numLayers)
635 	, m_glTexture		(0)
636 {
637 	// \todo [2013-04-08 pyry] Check support here.
638 	const glw::Functions& gl = m_context.getFunctions();
639 	gl.genTextures(1, &m_glTexture);
640 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
641 }
642 
TextureCubeArray(const RenderContext & context,deUint32 sizedFormat,int size,int numLayers)643 TextureCubeArray::TextureCubeArray (const RenderContext& context, deUint32 sizedFormat, int size, int numLayers)
644 	: m_context			(context)
645 	, m_format			(sizedFormat)
646 	, m_refTexture		(mapGLInternalFormat(sizedFormat), size, numLayers)
647 	, m_glTexture		(0)
648 {
649 	// \todo [2013-04-08 pyry] Check support here.
650 	const glw::Functions& gl = m_context.getFunctions();
651 	gl.genTextures(1, &m_glTexture);
652 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
653 }
654 
~TextureCubeArray(void)655 TextureCubeArray::~TextureCubeArray (void)
656 {
657 	if (m_glTexture)
658 		m_context.getFunctions().deleteTextures(1, &m_glTexture);
659 }
660 
upload(void)661 void TextureCubeArray::upload (void)
662 {
663 	const glw::Functions& gl = m_context.getFunctions();
664 
665 	if (!gl.texImage3D)
666 		throw tcu::NotSupportedError("glTexImage3D() is not supported");
667 
668 	TCU_CHECK(m_glTexture);
669 	gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, m_glTexture);
670 	gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
671 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
672 
673 	TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());
674 
675 	for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
676 	{
677 		if (m_refTexture.isLevelEmpty(levelNdx))
678 			continue; // Don't upload.
679 
680 		tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx);
681 		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth());
682 		DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize()*access.getWidth()*access.getHeight());
683 		gl.texImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, levelNdx, m_format, access.getWidth(), access.getHeight(), access.getDepth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
684 	}
685 
686 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
687 }
688 
689 // TextureBuffer
690 
TextureBuffer(const RenderContext & context,deUint32 internalFormat,size_t bufferSize)691 TextureBuffer::TextureBuffer (const RenderContext& context, deUint32 internalFormat, size_t bufferSize)
692 	: m_context			(context)
693 	, m_format			(0)
694 	, m_offset			(0)
695 	, m_size			(0)
696 	, m_glTexture		(0)
697 	, m_glBuffer		(0)
698 {
699 	init(internalFormat, bufferSize, 0, 0, DE_NULL);
700 }
701 
TextureBuffer(const RenderContext & context,deUint32 internalFormat,size_t bufferSize,size_t offset,size_t size,const void * data)702 TextureBuffer::TextureBuffer (const RenderContext& context, deUint32 internalFormat, size_t bufferSize, size_t offset, size_t size, const void* data)
703 	: m_context			(context)
704 	, m_format			(0)
705 	, m_offset			(0)
706 	, m_size			(0)
707 	, m_glTexture		(0)
708 	, m_glBuffer		(0)
709 {
710 	init(internalFormat, bufferSize, offset, size, data);
711 }
712 
init(deUint32 internalFormat,size_t bufferSize,size_t offset,size_t size,const void * data)713 void TextureBuffer::init (deUint32 internalFormat, size_t bufferSize, size_t offset, size_t size, const void* data)
714 {
715 	const glw::Functions&		gl		= m_context.getFunctions();
716 	de::UniquePtr<ContextInfo>	info 	(ContextInfo::create(m_context));
717 
718 	if (offset != 0 || size != 0)
719 	{
720 		if (!(contextSupports(m_context.getType(), glu::ApiType(3, 3, glu::PROFILE_CORE)) && info->isExtensionSupported("GL_ARB_texture_buffer_range"))
721 			&& !(contextSupports(m_context.getType(), glu::ApiType(3, 1, glu::PROFILE_ES))
722 				&& info->isExtensionSupported("GL_EXT_texture_buffer")))
723 		{
724 			throw tcu::NotSupportedError("Ranged texture buffers not supported", "", __FILE__, __LINE__);
725 		}
726 	}
727 	else
728 	{
729 		if (!contextSupports(m_context.getType(), glu::ApiType(3, 3, glu::PROFILE_CORE))
730 			&& !(contextSupports(m_context.getType(), glu::ApiType(3, 1, glu::PROFILE_ES))
731 				&& info->isExtensionSupported("GL_EXT_texture_buffer")))
732 		{
733 			throw tcu::NotSupportedError("Texture buffers not supported", "", __FILE__, __LINE__);
734 		}
735 	}
736 
737 	m_refBuffer.resize(bufferSize, 0);
738 
739 	if (data)
740 		deMemcpy(&m_refBuffer[0], data, (int)bufferSize);
741 
742 	m_format	= internalFormat;
743 	m_offset	= offset;
744 	m_size		= size;
745 
746 	DE_ASSERT(size != 0 || offset == 0);
747 
748 	{
749 		const tcu::TextureFormat	format			= mapGLInternalFormat(internalFormat);
750 		deInt32						maxTextureSize	= 0;
751 
752 		gl.getIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTextureSize);
753 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE) failed");
754 
755 		m_refTexture = tcu::PixelBufferAccess(format, de::min<int>((int)maxTextureSize, (int)((m_size != 0 ? m_size : bufferSize) / format.getPixelSize())), 1, 1, &(m_refBuffer[m_offset]));
756 	}
757 
758 	{
759 		gl.genTextures(1, &m_glTexture);
760 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
761 
762 		gl.genBuffers(1, &m_glBuffer);
763 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed");
764 
765 		gl.bindBuffer(GL_TEXTURE_BUFFER, m_glBuffer);
766 		gl.bufferData(GL_TEXTURE_BUFFER, (glw::GLsizei)m_refBuffer.size(), &(m_refBuffer[0]), GL_STATIC_DRAW);
767 		gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
768 		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create buffer");
769 
770 		gl.bindTexture(GL_TEXTURE_BUFFER, m_glTexture);
771 
772 		if (offset != 0 || size != 0)
773 			gl.texBufferRange(GL_TEXTURE_BUFFER, m_format, m_glBuffer, (glw::GLintptr)m_offset, (glw::GLsizeiptr)m_size);
774 		else
775 			gl.texBuffer(GL_TEXTURE_BUFFER, m_format, m_glBuffer);
776 
777 		gl.bindTexture(GL_TEXTURE_BUFFER, 0);
778 		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to bind buffer to texture");
779 	}
780 }
781 
~TextureBuffer(void)782 TextureBuffer::~TextureBuffer (void)
783 {
784 	if (m_glTexture)
785 		m_context.getFunctions().deleteTextures(1, &m_glTexture);
786 
787 	if (m_glBuffer)
788 		m_context.getFunctions().deleteBuffers(1, &m_glBuffer);
789 }
790 
upload(void)791 void TextureBuffer::upload (void)
792 {
793 	const glw::Functions& gl = m_context.getFunctions();
794 
795 	gl.bindBuffer(GL_TEXTURE_BUFFER, m_glBuffer);
796 	gl.bufferData(GL_TEXTURE_BUFFER, (glw::GLsizei)m_refBuffer.size(), &(m_refBuffer[0]), GL_STATIC_DRAW);
797 	gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
798 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to upload buffer");
799 }
800 
bufferData(const deUint8 * data,size_t size)801 void TextureBuffer::bufferData (const deUint8* data, size_t size)
802 {
803 	const glw::Functions& gl = m_context.getFunctions();
804 
805 	m_refBuffer = vector<deUint8>(data, data+size);
806 
807 	{
808 		const tcu::TextureFormat	format			= mapGLInternalFormat(m_format);
809 		deInt32						maxTextureSize	= 0;
810 
811 		gl.getIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTextureSize);
812 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE) failed");
813 
814 		m_refTexture = tcu::PixelBufferAccess(format, de::min<int>((int)maxTextureSize, (int)((m_size != 0 ? m_size : m_refBuffer.size())  / format.getPixelSize())), 1, 1, &(m_refBuffer[m_offset]));
815 	}
816 }
817 
818 } // glu
819