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
36using std::vector;
37
38namespace glu
39{
40
41static 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
52Texture1D::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
63Texture1D::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
74Texture1D::~Texture1D (void)
75{
76	if (m_glTexture)
77		m_context.getFunctions().deleteTextures(1, &m_glTexture);
78}
79
80void 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
105Texture2D::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
117Texture2D::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
129Texture2D::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
155Texture2D::~Texture2D (void)
156{
157	if (m_glTexture)
158		m_context.getFunctions().deleteTextures(1, &m_glTexture);
159}
160
161void 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
187void 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
214Texture2D* 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
275Texture2D* 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
288ImmutableTexture2D::ImmutableTexture2D (const RenderContext& context, deUint32 sizedFormat, int width, int height)
289	: Texture2D(context, sizedFormat, width, height)
290{
291}
292
293void 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
322TextureCube::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
350TextureCube::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
362TextureCube::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
374TextureCube::~TextureCube (void)
375{
376	if (m_glTexture)
377		m_context.getFunctions().deleteTextures(1, &m_glTexture);
378}
379
380void 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
409void 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
439TextureCube* 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
461TextureCube* 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
475Texture1DArray::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
486Texture1DArray::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
497Texture1DArray::~Texture1DArray (void)
498{
499	if (m_glTexture)
500		m_context.getFunctions().deleteTextures(1, &m_glTexture);
501}
502
503void 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
529Texture2DArray::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
542Texture2DArray::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
555Texture2DArray::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
581Texture2DArray::~Texture2DArray (void)
582{
583	if (m_glTexture)
584		m_context.getFunctions().deleteTextures(1, &m_glTexture);
585}
586
587void 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
615void 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
645Texture3D::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
658Texture3D::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
671Texture3D::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
701Texture3D::~Texture3D (void)
702{
703	if (m_glTexture)
704		m_context.getFunctions().deleteTextures(1, &m_glTexture);
705}
706
707void 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
737void 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
770TextureCubeArray::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
782TextureCubeArray::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
794TextureCubeArray::~TextureCubeArray (void)
795{
796	if (m_glTexture)
797		m_context.getFunctions().deleteTextures(1, &m_glTexture);
798}
799
800void 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
830TextureBuffer::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
841TextureBuffer::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
852void 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
910TextureBuffer::~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
920const 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
931const tcu::ConstPixelBufferAccess TextureBuffer::getFullRefTexture (void) const
932{
933	return const_cast<TextureBuffer*>(this)->getFullRefTexture();
934}
935
936void 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