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